diff --git a/llvm/include/llvm/Transforms/Utils/CodeMoverUtils.h b/llvm/include/llvm/Transforms/Utils/CodeMoverUtils.h --- a/llvm/include/llvm/Transforms/Utils/CodeMoverUtils.h +++ b/llvm/include/llvm/Transforms/Utils/CodeMoverUtils.h @@ -41,6 +41,9 @@ DominatorTree &DT, const PostDominatorTree &PDT, DependenceInfo &DI); +/// Return true if \p I is a safe candidate for code motion +bool isSafeToMove(Instruction &I); + /// Return true if all instructions (except the terminator) in \p BB can be /// safely moved before \p InsertPoint. bool isSafeToMoveBefore(BasicBlock &BB, Instruction &InsertPoint, diff --git a/llvm/lib/Transforms/Utils/CodeMoverUtils.cpp b/llvm/lib/Transforms/Utils/CodeMoverUtils.cpp --- a/llvm/lib/Transforms/Utils/CodeMoverUtils.cpp +++ b/llvm/lib/Transforms/Utils/CodeMoverUtils.cpp @@ -19,6 +19,7 @@ #include "llvm/Analysis/PostDominators.h" #include "llvm/Analysis/ValueTracking.h" #include "llvm/IR/Dominators.h" +#include "llvm/IR/IntrinsicInst.h" using namespace llvm; @@ -30,7 +31,14 @@ STATISTIC(NotControlFlowEquivalent, "Instructions are not control flow equivalent"); STATISTIC(NotMovedPHINode, "Movement of PHINodes are not supported"); -STATISTIC(NotMovedTerminator, "Movement of Terminator are not supported"); +STATISTIC(NotMovedDebugInfo, "Movement of DebugInfo are not supported"); +STATISTIC(NotMovedThrowCall, "Movement of Calls that throw are not supported"); +STATISTIC(NotMovedVolatileOrderedLoad, + "Movement of Volatile or Ordered Loads are not supported"); +STATISTIC(NotMovedVolatileOrderedStore, + "Movement of Volatile or Ordered Stores are not supported"); +STATISTIC(NotMovedInstruction, + "Movement of this Instruction type is not supported"); namespace { /// Represent a control condition. A control condition is a condition of a @@ -296,9 +304,38 @@ } } +bool llvm::isSafeToMove(Instruction &I) { + if (!(isa(I) || isa(I) || isa(I) || + isa(I) || isa(I) || isa(I) || + isa(I) || isa(I) || + isa(I) || isa(I) || + isa(I) || isa(I) || + isa(I) || isa(I) || + isa(I) || isa(I))) { + return reportInvalidCandidate(I, NotMovedInstruction); + } + if (LoadInst *LI = dyn_cast(&I)) { + if (!LI->isUnordered()) + return reportInvalidCandidate(I, NotMovedVolatileOrderedLoad); + } else if (CallInst *CI = dyn_cast(&I)) { + if (isa(I)) + return reportInvalidCandidate(I, NotMovedDebugInfo); + if (CI->mayThrow()) + return reportInvalidCandidate(I, NotMovedThrowCall); + } else if (auto *SI = dyn_cast(&I)) { + if (!SI->isUnordered()) + return reportInvalidCandidate(I, NotMovedVolatileOrderedStore); + } + return true; +} + bool llvm::isSafeToMoveBefore(Instruction &I, Instruction &InsertPoint, DominatorTree &DT, const PostDominatorTree &PDT, DependenceInfo &DI) { + // check can we move Instruction + if (!isSafeToMove(I)) + return false; + // Cannot move itself before itself. if (&I == &InsertPoint) return false; @@ -307,12 +344,9 @@ if (I.getNextNode() == &InsertPoint) return true; - if (isa(I) || isa(InsertPoint)) + if (isa(InsertPoint)) return reportInvalidCandidate(I, NotMovedPHINode); - if (I.isTerminator()) - return reportInvalidCandidate(I, NotMovedTerminator); - // TODO remove this limitation. if (!isControlFlowEquivalent(I, InsertPoint, DT, PDT)) return reportInvalidCandidate(I, NotControlFlowEquivalent); @@ -338,8 +372,8 @@ if (!MoveForward) InstsToCheck.insert(&InsertPoint); - // Check if there exists instructions which may throw, may synchonize, or may - // never return, from I to InsertPoint. + // Check if there exists instructions which may throw, may synchonize, or + // may never return, from I to InsertPoint. if (!isSafeToSpeculativelyExecute(&I)) if (std::any_of(InstsToCheck.begin(), InstsToCheck.end(), [](Instruction *I) {