Index: include/llvm/IR/Instruction.h =================================================================== --- include/llvm/IR/Instruction.h +++ include/llvm/IR/Instruction.h @@ -484,6 +484,9 @@ /// operands in the corresponding predecessor block. bool isUsedOutsideOfBlock(const BasicBlock *BB) const; + /// Return true if operand number \c OpIdx must be a Constant. If this returns + /// false then it is safe to replace the operand with a variable. + bool mustOperandBeConstant(unsigned OpIdx) const; /// Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const Value *V) { Index: lib/IR/Instruction.cpp =================================================================== --- lib/IR/Instruction.cpp +++ lib/IR/Instruction.cpp @@ -14,7 +14,9 @@ #include "llvm/IR/Instruction.h" #include "llvm/IR/CallSite.h" #include "llvm/IR/Constants.h" +#include "llvm/IR/GetElementPtrTypeIterator.h" #include "llvm/IR/Instructions.h" +#include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/Module.h" #include "llvm/IR/Operator.h" #include "llvm/IR/Type.h" @@ -489,6 +491,33 @@ return false; } +bool Instruction::mustOperandBeConstant(unsigned OpIdx) const { + switch (getOpcode()) { + default: + return false; + case Instruction::Call: + case Instruction::Invoke: + // FIXME: many arithmetic intrinsics have no issue taking a + // variable, however it's hard to distingish these from + // specials such as @llvm.frameaddress that require a constant. + return isa(this); + case Instruction::ShuffleVector: + // Shufflevector masks are constant. + return OpIdx == 2; + case Instruction::ExtractValue: + case Instruction::InsertValue: + // All operands apart from the first are constant. + return OpIdx != 0; + case Instruction::Alloca: + return true; + case Instruction::GetElementPtr: + if (OpIdx == 0) + return false; + gep_type_iterator It = std::next(gep_type_begin(this), OpIdx - 1); + return It->isStructTy(); + } +} + /// mayReadFromMemory - Return true if this instruction may read memory. /// bool Instruction::mayReadFromMemory() const { Index: lib/Transforms/Utils/SimplifyCFG.cpp =================================================================== --- lib/Transforms/Utils/SimplifyCFG.cpp +++ lib/Transforms/Utils/SimplifyCFG.cpp @@ -1376,40 +1376,6 @@ return true; } -// Is it legal to place a variable in operand \c OpIdx of \c I? -// FIXME: This should be promoted to Instruction. -static bool canReplaceOperandWithVariable(const Instruction *I, - unsigned OpIdx) { - // Early exit. - if (!isa(I->getOperand(OpIdx))) - return true; - - switch (I->getOpcode()) { - default: - return true; - case Instruction::Call: - case Instruction::Invoke: - // FIXME: many arithmetic intrinsics have no issue taking a - // variable, however it's hard to distingish these from - // specials such as @llvm.frameaddress that require a constant. - return !isa(I); - case Instruction::ShuffleVector: - // Shufflevector masks are constant. - return OpIdx != 2; - case Instruction::ExtractValue: - case Instruction::InsertValue: - // All operands apart from the first are constant. - return OpIdx == 0; - case Instruction::Alloca: - return false; - case Instruction::GetElementPtr: - if (OpIdx == 0) - return true; - gep_type_iterator It = std::next(gep_type_begin(I), OpIdx - 1); - return !It->isStructTy(); - } -} - // All blocks in Blocks unconditionally jump to a common successor. Analyze // the last non-terminator instruction in each block and return true if it would // be possible to sink them into their successor, creating one common @@ -1469,7 +1435,7 @@ I0->getOperand(OI), I0->getIterator()); }; if (!all_of(Insts, SameAsI0)) { - if (!canReplaceOperandWithVariable(I0, OI)) + if (I0->mustOperandBeConstant(OI)) // We can't create a PHI from this GEP. return false; if ((isa(I0) || isa(I0)) && OI != 0)