diff --git a/llvm/include/llvm/Analysis/ConstantFolding.h b/llvm/include/llvm/Analysis/ConstantFolding.h index 0137dad368a9b..af7b87c56c315 100644 --- a/llvm/include/llvm/Analysis/ConstantFolding.h +++ b/llvm/include/llvm/Analysis/ConstantFolding.h @@ -51,8 +51,7 @@ ConstantFoldConstantExpression(const ConstantExpr *CE, const DataLayout &DL, /// fold instructions like loads and stores, which have no constant expression /// form. /// -Constant *ConstantFoldInstOperands(unsigned Opcode, Type *DestTy, - ArrayRef Ops, +Constant *ConstantFoldInstOperands(Instruction *I, ArrayRef Ops, const DataLayout &DL, const TargetLibraryInfo *TLI = nullptr); diff --git a/llvm/lib/Analysis/ConstantFolding.cpp b/llvm/lib/Analysis/ConstantFolding.cpp index 95c56b96deaa1..a69521abc77f0 100644 --- a/llvm/lib/Analysis/ConstantFolding.cpp +++ b/llvm/lib/Analysis/ConstantFolding.cpp @@ -881,6 +881,56 @@ static Constant *SymbolicallyEvaluateGEP(Type *SrcTy, ArrayRef Ops, return C; } +/// Attempt to constant fold an instruction with the +/// specified opcode and operands. If successful, the constant result is +/// returned, if not, null is returned. Note that this function can fail when +/// attempting to fold instructions like loads and stores, which have no +/// constant expression form. +/// +/// TODO: This function neither utilizes nor preserves nsw/nuw/inbounds/etc +/// information, due to only being passed an opcode and operands. Constant +/// folding using this function strips this information. +/// +static Constant *ConstantFoldInstOperandsImpl(unsigned Opcode, Type *DestTy, + ArrayRef Ops, + const DataLayout &DL, + const TargetLibraryInfo *TLI) { + // Handle easy binops first. + if (Instruction::isBinaryOp(Opcode)) + return ConstantFoldBinaryOpOperands(Opcode, Ops[0], Ops[1], DL); + + if (Instruction::isCast(Opcode)) + return ConstantFoldCastOperand(Opcode, Ops[0], DestTy, DL); + + switch (Opcode) { + default: return nullptr; + case Instruction::ICmp: + case Instruction::FCmp: llvm_unreachable("Invalid for compares"); + case Instruction::Call: + if (Function *F = dyn_cast(Ops.back())) + if (canConstantFoldCallTo(F)) + return ConstantFoldCall(F, Ops.slice(0, Ops.size() - 1), TLI); + return nullptr; + case Instruction::Select: + return ConstantExpr::getSelect(Ops[0], Ops[1], Ops[2]); + case Instruction::ExtractElement: + return ConstantExpr::getExtractElement(Ops[0], Ops[1]); + case Instruction::InsertElement: + return ConstantExpr::getInsertElement(Ops[0], Ops[1], Ops[2]); + case Instruction::ShuffleVector: + return ConstantExpr::getShuffleVector(Ops[0], Ops[1], Ops[2]); + case Instruction::GetElementPtr: { + Type *SrcTy = nullptr; + if (Constant *C = CastGEPIndices(SrcTy, Ops, DestTy, DL, TLI)) + return C; + if (Constant *C = SymbolicallyEvaluateGEP(SrcTy, Ops, DestTy, DL, TLI)) + return C; + + return ConstantExpr::getGetElementPtr(SrcTy, Ops[0], Ops.slice(1)); + } + } +} + //===----------------------------------------------------------------------===// @@ -925,7 +975,7 @@ Constant *llvm::ConstantFoldInstruction(Instruction *I, const DataLayout &DL, } // Scan the operand list, checking to see if they are all constants, if so, - // hand off to ConstantFoldInstOperands. + // hand off to ConstantFoldInstOperandsImpl. SmallVector Ops; for (User::op_iterator i = I->op_begin(), e = I->op_end(); i != e; ++i) { Constant *Op = dyn_cast(*i); @@ -959,7 +1009,7 @@ Constant *llvm::ConstantFoldInstruction(Instruction *I, const DataLayout &DL, EVI->getIndices()); } - return ConstantFoldInstOperands(I->getOpcode(), I->getType(), Ops, DL, TLI); + return ConstantFoldInstOperandsImpl(I->getOpcode(), I->getType(), Ops, DL, TLI); } static Constant * @@ -982,7 +1032,7 @@ ConstantFoldConstantExpressionImpl(const ConstantExpr *CE, const DataLayout &DL, if (CE->isCompare()) return ConstantFoldCompareInstOperands(CE->getPredicate(), Ops[0], Ops[1], DL, TLI); - return ConstantFoldInstOperands(CE->getOpcode(), CE->getType(), Ops, DL, TLI); + return ConstantFoldInstOperandsImpl(CE->getOpcode(), CE->getType(), Ops, DL, TLI); } /// Attempt to fold the constant expression @@ -995,54 +1045,12 @@ Constant *llvm::ConstantFoldConstantExpression(const ConstantExpr *CE, return ConstantFoldConstantExpressionImpl(CE, DL, TLI, FoldedOps); } -/// Attempt to constant fold an instruction with the -/// specified opcode and operands. If successful, the constant result is -/// returned, if not, null is returned. Note that this function can fail when -/// attempting to fold instructions like loads and stores, which have no -/// constant expression form. -/// -/// TODO: This function neither utilizes nor preserves nsw/nuw/inbounds/etc -/// information, due to only being passed an opcode and operands. Constant -/// folding using this function strips this information. -/// -Constant *llvm::ConstantFoldInstOperands(unsigned Opcode, Type *DestTy, +Constant *llvm::ConstantFoldInstOperands(Instruction *I, ArrayRef Ops, const DataLayout &DL, const TargetLibraryInfo *TLI) { - // Handle easy binops first. - if (Instruction::isBinaryOp(Opcode)) - return ConstantFoldBinaryOpOperands(Opcode, Ops[0], Ops[1], DL); - - if (Instruction::isCast(Opcode)) - return ConstantFoldCastOperand(Opcode, Ops[0], DestTy, DL); - - switch (Opcode) { - default: return nullptr; - case Instruction::ICmp: - case Instruction::FCmp: llvm_unreachable("Invalid for compares"); - case Instruction::Call: - if (Function *F = dyn_cast(Ops.back())) - if (canConstantFoldCallTo(F)) - return ConstantFoldCall(F, Ops.slice(0, Ops.size() - 1), TLI); - return nullptr; - case Instruction::Select: - return ConstantExpr::getSelect(Ops[0], Ops[1], Ops[2]); - case Instruction::ExtractElement: - return ConstantExpr::getExtractElement(Ops[0], Ops[1]); - case Instruction::InsertElement: - return ConstantExpr::getInsertElement(Ops[0], Ops[1], Ops[2]); - case Instruction::ShuffleVector: - return ConstantExpr::getShuffleVector(Ops[0], Ops[1], Ops[2]); - case Instruction::GetElementPtr: { - Type *SrcTy = nullptr; - if (Constant *C = CastGEPIndices(SrcTy, Ops, DestTy, DL, TLI)) - return C; - if (Constant *C = SymbolicallyEvaluateGEP(SrcTy, Ops, DestTy, DL, TLI)) - return C; - - return ConstantExpr::getGetElementPtr(SrcTy, Ops[0], Ops.slice(1)); - } - } + return ConstantFoldInstOperandsImpl(I->getOpcode(), I->getType(), Ops, DL, + TLI); } /// Attempt to constant fold a compare diff --git a/llvm/lib/Analysis/InlineCost.cpp b/llvm/lib/Analysis/InlineCost.cpp index 2b9e06e421073..32e8e2760d241 100644 --- a/llvm/lib/Analysis/InlineCost.cpp +++ b/llvm/lib/Analysis/InlineCost.cpp @@ -533,8 +533,7 @@ bool CallAnalyzer::visitUnaryInstruction(UnaryInstruction &I) { COp = SimplifiedValues.lookup(Operand); if (COp) { const DataLayout &DL = F.getParent()->getDataLayout(); - if (Constant *C = ConstantFoldInstOperands(I.getOpcode(), I.getType(), - COp, DL)) { + if (Constant *C = ConstantFoldInstOperands(&I, COp, DL)) { SimplifiedValues[&I] = C; return true; } diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp index fc21a14cb106a..2b577f0342bb5 100644 --- a/llvm/lib/Analysis/InstructionSimplify.cpp +++ b/llvm/lib/Analysis/InstructionSimplify.cpp @@ -3261,8 +3261,7 @@ static const Value *SimplifyWithOpReplaced(Value *V, Value *Op, Value *RepOp, if (!LI->isVolatile()) return ConstantFoldLoadFromConstPtr(ConstOps[0], Q.DL); - return ConstantFoldInstOperands(I->getOpcode(), I->getType(), ConstOps, - Q.DL, Q.TLI); + return ConstantFoldInstOperands(I, ConstOps, Q.DL, Q.TLI); } } diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp index ed640acfda5ce..dc580dfdf2638 100644 --- a/llvm/lib/Analysis/ScalarEvolution.cpp +++ b/llvm/lib/Analysis/ScalarEvolution.cpp @@ -5917,8 +5917,7 @@ static Constant *EvaluateExpression(Value *V, const Loop *L, if (!LI->isVolatile()) return ConstantFoldLoadFromConstPtr(Operands[0], DL); } - return ConstantFoldInstOperands(I->getOpcode(), I->getType(), Operands, DL, - TLI); + return ConstantFoldInstOperands(I, Operands, DL, TLI); } @@ -6306,8 +6305,7 @@ const SCEV *ScalarEvolution::computeSCEVAtScope(const SCEV *V, const Loop *L) { if (!LI->isVolatile()) C = ConstantFoldLoadFromConstPtr(Operands[0], DL); } else - C = ConstantFoldInstOperands(I->getOpcode(), I->getType(), Operands, - DL, &TLI); + C = ConstantFoldInstOperands(I, Operands, DL, &TLI); if (!C) return V; return getSCEV(C); } diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp index 3125a2c359b68..8cb1573fb9c59 100644 --- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp +++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp @@ -3989,7 +3989,7 @@ ConstantFold(Instruction *I, const DataLayout &DL, COps[1], DL); } - return ConstantFoldInstOperands(I->getOpcode(), I->getType(), COps, DL); + return ConstantFoldInstOperands(I, COps, DL); } /// Try to determine the resulting constant values in phi nodes