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: include/llvm/IR/IntrinsicInst.h =================================================================== --- include/llvm/IR/IntrinsicInst.h +++ include/llvm/IR/IntrinsicInst.h @@ -24,6 +24,7 @@ #ifndef LLVM_IR_INTRINSICINST_H #define LLVM_IR_INTRINSICINST_H +#include "llvm/ADT/Optional.h" #include "llvm/IR/Constants.h" #include "llvm/IR/Function.h" #include "llvm/IR/Instructions.h" @@ -44,6 +45,10 @@ return getCalledFunction()->getIntrinsicID(); } + /// If the given argument to this intrinsic must be a subclass of Constant, + /// return a string giving the reason. Otherwise return None. + Optional mustOperandBeConstant(unsigned OpIdx) const; + // Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const CallInst *I) { if (const Function *CF = I->getCalledFunction()) 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,32 @@ return false; } +bool Instruction::mustOperandBeConstant(unsigned OpIdx) const { + switch (getOpcode()) { + default: + return false; + case Instruction::Call: + case Instruction::Invoke: + if (auto *I = dyn_cast(this)) + return I->mustOperandBeConstant(OpIdx) != None; + return false; + 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/IR/IntrinsicInst.cpp =================================================================== --- lib/IR/IntrinsicInst.cpp +++ lib/IR/IntrinsicInst.cpp @@ -83,3 +83,52 @@ return LastLow - NameTable.begin(); return -1; } + +Optional +IntrinsicInst::mustOperandBeConstant(unsigned OpIdx) const { + switch (getIntrinsicID()) { + default: + return None; + case Intrinsic::ctlz: + case Intrinsic::cttz: + if (OpIdx == 1) + return "is_zero_undef argument of bit counting intrinsics must be a " + "constant int"; + break; + case Intrinsic::memcpy: + case Intrinsic::memmove: + case Intrinsic::memset: + if (OpIdx == 3) + return "alignment argument of memory intrinsics must be a constant int"; + if (OpIdx == 4) + return "isvolatile argument of memory intrinsics must be a constant int"; + break; + case Intrinsic::gcroot: + case Intrinsic::gcwrite: + case Intrinsic::gcread: + if (OpIdx == 1) + return "llvm.gcroot parameter #2 must be a constant."; + break; + case Intrinsic::lifetime_start: + case Intrinsic::lifetime_end: + case Intrinsic::invariant_start: + if (OpIdx == 0) + return "size argument of memory use markers must be a constant integer"; + break; + case Intrinsic::invariant_end: + if (OpIdx == 1) + return "llvm.invariant.end parameter #2 must be a constant integer"; + break; + case Intrinsic::localrecover: + if (OpIdx == 2) + return "idx argument of llvm.localrecover must be a constant int"; + break; + case Intrinsic::experimental_gc_relocate: + if (OpIdx == 1) + return "gc.relocate operand #2 must be an integer offset"; + if (OpIdx == 2) + return "gc.relocate operand #3 must be an integer offset"; + break; + } + return None; +} Index: lib/IR/Verifier.cpp =================================================================== --- lib/IR/Verifier.cpp +++ lib/IR/Verifier.cpp @@ -3869,6 +3869,13 @@ if (auto *MD = dyn_cast(V)) visitMetadataAsValue(*MD, CS.getCaller()); + if (auto *II = dyn_cast(IF)) + for (unsigned OpIdx = 0; OpIdx < CS.getNumArgOperands(); ++OpIdx) { + auto MaybeReason = II->mustOperandBeConstant(OpIdx); + if (MaybeReason != None) + Assert(isa(CS.getArgOperand(OpIdx)), MaybeReason.getValue()); + } + switch (ID) { default: break; 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)