diff --git a/llvm/include/llvm/IR/Instruction.h b/llvm/include/llvm/IR/Instruction.h --- a/llvm/include/llvm/IR/Instruction.h +++ b/llvm/include/llvm/IR/Instruction.h @@ -634,6 +634,15 @@ } } + /// Returns true if I modifies the stack state of the function. + /// These are: + /// 1. static and dynamic allocas + /// 2. llvm.stacksave and llvm.stackrestore intrinsics used with dynamic + /// allocas. + /// Use this API to identify instructions that are illegal to move (even if + /// they are marked side-effect free: allocas for example). + bool isFunctionStackStateModifying() const; + /// Return true if the instruction may have side effects. /// /// Side effects are: 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 @@ -680,6 +680,20 @@ return isa(this); } +bool Instruction::isFunctionStackStateModifying() const { + // This includes both static allocas (in entry blocks) and dynamic allocas + // (recorded between a stacksave/stackrestore pair). + // Correctly sinking dynamic allocas require proper checks for + // stacksave/stackrestore intrinsics. + if (isa(this)) + return true; + auto *II = dyn_cast(this); + if (!II) + return false; + Intrinsic::ID ID = II->getIntrinsicID(); + return ID == Intrinsic::stacksave || ID == Intrinsic::stackrestore; +} + bool Instruction::mayHaveSideEffects() const { return mayWriteToMemory() || mayThrow() || !willReturn(); } diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp --- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp +++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp @@ -3671,7 +3671,7 @@ // remain in the entry block, and dynamic allocas must not be sunk in between // a stacksave / stackrestore pair, which would incorrectly shorten its // lifetime. - if (isa(I)) + if (I->isFunctionStackStateModifying()) return false; // Do not sink into catchswitch blocks. diff --git a/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp b/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp --- a/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp +++ b/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp @@ -1241,8 +1241,7 @@ // Don't sink alloca: we never want to sink static alloca's out of the // entry block, and correctly sinking dynamic alloca's requires // checks for stacksave/stackrestore intrinsics. - // FIXME: Refactor this check somehow? - if (isa(I)) + if (I->isFunctionStackStateModifying()) continue; // Determine if there is a use in or before the loop (direct or