diff --git a/llvm/lib/IR/Instruction.cpp b/llvm/lib/IR/Instruction.cpp --- a/llvm/lib/IR/Instruction.cpp +++ b/llvm/lib/IR/Instruction.cpp @@ -455,11 +455,24 @@ SI->getSyncScopeID() == cast(I2)->getSyncScopeID(); if (const CmpInst *CI = dyn_cast(I1)) return CI->getPredicate() == cast(I2)->getPredicate(); - if (const CallInst *CI = dyn_cast(I1)) + if (const CallInst *CI = dyn_cast(I1)) { + // Must have the same "Final Suspend" flag. + if (const IntrinsicInst *II = dyn_cast(I1)) { + if (II->getIntrinsicID() == Intrinsic::coro_save && I1->getNumUses() && + I2->getNumUses()) { + auto *CS1 = cast(I1->user_back()); + auto *CS2 = cast(I2->user_back()); + assert(CS1->getIntrinsicID() == Intrinsic::coro_suspend && + CS2->getIntrinsicID() == Intrinsic::coro_suspend); + return cast(CS1->getArgOperand(1))->isOneValue() == + cast(CS2->getArgOperand(1))->isOneValue(); + } + } return CI->isTailCall() == cast(I2)->isTailCall() && CI->getCallingConv() == cast(I2)->getCallingConv() && CI->getAttributes() == cast(I2)->getAttributes() && CI->hasIdenticalOperandBundleSchema(*cast(I2)); + } if (const InvokeInst *CI = dyn_cast(I1)) return CI->getCallingConv() == cast(I2)->getCallingConv() && CI->getAttributes() == cast(I2)->getAttributes() && diff --git a/llvm/lib/Transforms/Utils/FunctionComparator.cpp b/llvm/lib/Transforms/Utils/FunctionComparator.cpp --- a/llvm/lib/Transforms/Utils/FunctionComparator.cpp +++ b/llvm/lib/Transforms/Utils/FunctionComparator.cpp @@ -28,6 +28,7 @@ #include "llvm/IR/GlobalValue.h" #include "llvm/IR/InlineAsm.h" #include "llvm/IR/InstrTypes.h" +#include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/Instruction.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/LLVMContext.h" @@ -596,6 +597,21 @@ if (const CmpInst *CI = dyn_cast(L)) return cmpNumbers(CI->getPredicate(), cast(R)->getPredicate()); if (auto *CBL = dyn_cast(L)) { + // Must have the same "Final Suspend" flag. + if (const IntrinsicInst *II = dyn_cast(L)) { + if (II->getIntrinsicID() == Intrinsic::coro_save && L->getNumUses() && + R->getNumUses()) { + auto *CS1 = cast(L->user_back()); + auto *CS2 = cast(R->user_back()); + assert(CS1->getIntrinsicID() == Intrinsic::coro_suspend && + CS2->getIntrinsicID() == Intrinsic::coro_suspend); + bool IsFinal1 = cast(CS1->getArgOperand(1))->isOneValue(); + bool IsFinal2 = cast(CS2->getArgOperand(1))->isOneValue(); + if (int Res = cmpNumbers(IsFinal1, IsFinal2)) + return Res; + } + } + auto *CBR = cast(R); if (int Res = cmpNumbers(CBL->getCallingConv(), CBR->getCallingConv())) return Res; diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp --- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp +++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp @@ -1505,10 +1505,6 @@ if (I1->isTerminator()) goto HoistTerminator; - // Hoisting token-returning instructions would obscure the origin. - if (I1->getType()->isTokenTy()) - return Changed; - // If we're going to hoist a call, make sure that the two instructions we're // commoning/hoisting are both marked with musttail, or neither of them is // marked as such. Otherwise, we might end up in a situation where we hoist