Author: Nikita Popov Date: 2021-02-19T16:32:06-08:00 New Revision: d1d7dc779a296001568d855bba7843a9eb94a585
URL: https://github.com/llvm/llvm-project/commit/d1d7dc779a296001568d855bba7843a9eb94a585 DIFF: https://github.com/llvm/llvm-project/commit/d1d7dc779a296001568d855bba7843a9eb94a585.diff LOG: [IR] Move willReturn() to Instruction This moves the willReturn() helper from CallBase to Instruction, so that it can be used in a more generic manner. This will make it easier to fix additional passes (ADCE and BDCE), and will give us one place to change if additional instructions should become non-willreturn (e.g. there has been talk about handling volatile operations this way). I have also included the IntrinsicInst workaround directly in here, so that it gets applied consistently. (As such this change is not entirely NFC -- FuncAttrs will now use this as well.) Differential Revision: https://reviews.llvm.org/D96992 (cherry picked from commit 370addb996138a9e3634899cf264c7621307617a) Added: Modified: llvm/include/llvm/IR/InstrTypes.h llvm/include/llvm/IR/Instruction.h llvm/lib/Analysis/ValueTracking.cpp llvm/lib/IR/Instruction.cpp llvm/lib/Transforms/IPO/FunctionAttrs.cpp llvm/lib/Transforms/Utils/Local.cpp Removed: ################################################################################ diff --git a/llvm/include/llvm/IR/InstrTypes.h b/llvm/include/llvm/IR/InstrTypes.h index f42ef48de6b3..955ac8e537fe 100644 --- a/llvm/include/llvm/IR/InstrTypes.h +++ b/llvm/include/llvm/IR/InstrTypes.h @@ -1757,9 +1757,6 @@ class CallBase : public Instruction { return doesNotAccessMemory() || hasFnAttr(Attribute::ReadOnly); } - /// Returns true if this function is guaranteed to return. - bool willReturn() const { return hasFnAttr(Attribute::WillReturn); } - void setOnlyReadsMemory() { addAttribute(AttributeList::FunctionIndex, Attribute::ReadOnly); } diff --git a/llvm/include/llvm/IR/Instruction.h b/llvm/include/llvm/IR/Instruction.h index d2a55f89fac9..85afaed5225e 100644 --- a/llvm/include/llvm/IR/Instruction.h +++ b/llvm/include/llvm/IR/Instruction.h @@ -633,6 +633,10 @@ class Instruction : public User, /// generated program. bool isSafeToRemove() const; + /// Return true if the instruction will return (unwinding is considered as + /// a form of returning control flow here). + bool willReturn() const; + /// Return true if the instruction is a variety of EH-block. bool isEHPad() const { switch (getOpcode()) { diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp index 5600a3b33750..e174c5efe424 100644 --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -5018,36 +5018,14 @@ bool llvm::isGuaranteedToTransferExecutionToSuccessor(const Instruction *I) { // arbitrary length of time, but programs aren't allowed to rely on that. // If there is no successor, then execution can't transfer to it. - if (const auto *CRI = dyn_cast<CleanupReturnInst>(I)) - return !CRI->unwindsToCaller(); - if (const auto *CatchSwitch = dyn_cast<CatchSwitchInst>(I)) - return !CatchSwitch->unwindsToCaller(); - if (isa<ResumeInst>(I)) - return false; if (isa<ReturnInst>(I)) return false; if (isa<UnreachableInst>(I)) return false; - // Calls can throw, or contain an infinite loop, or kill the process. - if (const auto *CB = dyn_cast<CallBase>(I)) { - // Call sites that throw have implicit non-local control flow. - if (!CB->doesNotThrow()) - return false; - - // A function which doens't throw and has "willreturn" attribute will - // always return. - if (CB->hasFnAttr(Attribute::WillReturn)) - return true; - - // FIXME: Temporarily assume that all side-effect free intrinsics will - // return. Remove this workaround once all intrinsics are appropriately - // annotated. - return isa<IntrinsicInst>(CB) && CB->onlyReadsMemory(); - } - - // Other instructions return normally. - return true; + // An instruction that returns without throwing must transfer control flow + // to a successor. + return !I->mayThrow() && I->willReturn(); } bool llvm::isGuaranteedToTransferExecutionToSuccessor(const BasicBlock *BB) { diff --git a/llvm/lib/IR/Instruction.cpp b/llvm/lib/IR/Instruction.cpp index 1e3fcd672a43..246180e72172 100644 --- a/llvm/lib/IR/Instruction.cpp +++ b/llvm/lib/IR/Instruction.cpp @@ -633,6 +633,16 @@ bool Instruction::isSafeToRemove() const { !this->isTerminator(); } +bool Instruction::willReturn() const { + if (const auto *CB = dyn_cast<CallBase>(this)) + // FIXME: Temporarily assume that all side-effect free intrinsics will + // return. Remove this workaround once all intrinsics are appropriately + // annotated. + return CB->hasFnAttr(Attribute::WillReturn) || + (isa<IntrinsicInst>(CB) && CB->onlyReadsMemory()); + return true; +} + bool Instruction::isLifetimeStartOrEnd() const { auto II = dyn_cast<IntrinsicInst>(this); if (!II) diff --git a/llvm/lib/Transforms/IPO/FunctionAttrs.cpp b/llvm/lib/Transforms/IPO/FunctionAttrs.cpp index 30a1f81ad0e1..256acd7e1d17 100644 --- a/llvm/lib/Transforms/IPO/FunctionAttrs.cpp +++ b/llvm/lib/Transforms/IPO/FunctionAttrs.cpp @@ -1445,8 +1445,7 @@ static bool functionWillReturn(const Function &F) { // If there are no loops, then the function is willreturn if all calls in // it are willreturn. return all_of(instructions(F), [](const Instruction &I) { - const auto *CB = dyn_cast<CallBase>(&I); - return !CB || CB->hasFnAttr(Attribute::WillReturn); + return I.willReturn(); }); } diff --git a/llvm/lib/Transforms/Utils/Local.cpp b/llvm/lib/Transforms/Utils/Local.cpp index 477ea458c763..d055f3dd3084 100644 --- a/llvm/lib/Transforms/Utils/Local.cpp +++ b/llvm/lib/Transforms/Utils/Local.cpp @@ -420,13 +420,8 @@ bool llvm::wouldInstructionBeTriviallyDead(Instruction *I, return true; } - if (auto *CB = dyn_cast<CallBase>(I)) { - // Treat calls that may not return as alive. - // TODO: Remove the intrinsic escape hatch once all intrinsics set - // willreturn properly. - if (!CB->willReturn() && !isa<IntrinsicInst>(I)) - return false; - } + if (!I->willReturn()) + return false; if (!I->mayHaveSideEffects()) return true; _______________________________________________ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits