diff --git a/include/llvm/Analysis/ConstantFolding.h b/include/llvm/Analysis/ConstantFolding.h index b1504004d83..9f93d6efd62 100644 --- a/include/llvm/Analysis/ConstantFolding.h +++ b/include/llvm/Analysis/ConstantFolding.h @@ -25,6 +25,7 @@ class APInt; template class ArrayRef; class Constant; class ConstantExpr; +class ConstantVector; class DataLayout; class Function; class GlobalValue; @@ -45,11 +46,11 @@ bool IsConstantOffsetFromGlobal(Constant *C, GlobalValue *&GV, APInt &Offset, Constant *ConstantFoldInstruction(Instruction *I, const DataLayout &DL, const TargetLibraryInfo *TLI = nullptr); -/// ConstantFoldConstantExpression - Attempt to fold the constant expression -/// using the specified DataLayout. If successful, the constant result is -/// result is returned, if not, null is returned. -Constant * -ConstantFoldConstantExpression(const ConstantExpr *CE, const DataLayout &DL, +/// ConstantFoldConstant - Attempt to fold the constant using the +/// specified DataLayout. +/// If successful, the constant result is result is returned, if not, +/// null is returned. +Constant *ConstantFoldConstant(const Constant *C, const DataLayout &DL, const TargetLibraryInfo *TLI = nullptr); /// ConstantFoldInstOperands - Attempt to constant fold an instruction with the diff --git a/include/llvm/Analysis/TargetFolder.h b/include/llvm/Analysis/TargetFolder.h index 12bf9fe78a4..ae75d377336 100644 --- a/include/llvm/Analysis/TargetFolder.h +++ b/include/llvm/Analysis/TargetFolder.h @@ -34,9 +34,8 @@ class TargetFolder { /// Fold - Fold the constant using target specific information. Constant *Fold(Constant *C) const { - if (ConstantExpr *CE = dyn_cast(C)) - if (Constant *CF = ConstantFoldConstantExpression(CE, DL)) - return CF; + if (Constant *CF = ConstantFoldConstant(C, DL)) + return CF; return C; } diff --git a/lib/Analysis/ConstantFolding.cpp b/lib/Analysis/ConstantFolding.cpp index 1a6a54b9a76..7ee3e8cb4d4 100644 --- a/lib/Analysis/ConstantFolding.cpp +++ b/lib/Analysis/ConstantFolding.cpp @@ -714,10 +714,8 @@ Constant *CastGEPIndices(Type *SrcElemTy, ArrayRef Ops, return nullptr; Constant *C = ConstantExpr::getGetElementPtr(SrcElemTy, Ops[0], NewIdxs); - if (auto *CE = dyn_cast(C)) { - if (Constant *Folded = ConstantFoldConstantExpression(CE, DL, TLI)) - C = Folded; - } + if (Constant *Folded = ConstantFoldConstant(C, DL, TLI)) + C = Folded; return C; } @@ -775,10 +773,8 @@ Constant *SymbolicallyEvaluateGEP(const GEPOperator *GEP, Constant *Res = ConstantExpr::getPtrToInt(Ptr, CE->getType()); Res = ConstantExpr::getSub(Res, CE->getOperand(1)); Res = ConstantExpr::getIntToPtr(Res, ResTy); - if (auto *ResCE = dyn_cast(Res)) - if (auto *FoldedRes = - ConstantFoldConstantExpression(ResCE, DL, TLI)) - Res = FoldedRes; + if (auto *FoldedRes = ConstantFoldConstant(Res, DL, TLI)) + Res = FoldedRes; return Res; } } @@ -968,12 +964,59 @@ Constant *ConstantFoldInstOperandsImpl(const Value *InstOrCE, Type *DestTy, // Constant Folding public APIs //===----------------------------------------------------------------------===// +namespace { + +Constant * +ConstantFoldConstantImpl(const Constant *C, const DataLayout &DL, + const TargetLibraryInfo *TLI, + SmallDenseMap &FoldedOps) { + if (!isa(C) && !isa(C)) + return nullptr; + + SmallVector Ops; + for (const Use &NewU : C->operands()) { + auto *NewC = cast(&NewU); + // Recursively fold the ConstantExpr's operands. If we have already folded + // a ConstantExpr, we don't have to process it again. + if (isa(NewC) || isa(NewC)) { + auto It = FoldedOps.find(NewC); + if (It == FoldedOps.end()) { + if (auto *FoldedC = + ConstantFoldConstantImpl(NewC, DL, TLI, FoldedOps)) { + NewC = FoldedC; + FoldedOps.insert({NewC, FoldedC}); + } else { + FoldedOps.insert({NewC, NewC}); + } + } else { + NewC = It->second; + } + } + Ops.push_back(NewC); + } + + if (auto *CE = dyn_cast(C)) { + if (CE->isCompare()) + return ConstantFoldCompareInstOperands(CE->getPredicate(), Ops[0], Ops[1], + DL, TLI); + + return ConstantFoldInstOperandsImpl(CE, CE->getType(), CE->getOpcode(), Ops, + DL, TLI); + } + + assert(isa(C)); + return ConstantVector::get(Ops); +} + +} // end anonymous namespace + Constant *llvm::ConstantFoldInstruction(Instruction *I, const DataLayout &DL, const TargetLibraryInfo *TLI) { // Handle PHI nodes quickly here... if (auto *PN = dyn_cast(I)) { Constant *CommonValue = nullptr; + SmallDenseMap FoldedOps; for (Value *Incoming : PN->incoming_values()) { // If the incoming value is undef then skip it. Note that while we could // skip the value if it is equal to the phi node itself we choose not to @@ -986,9 +1029,8 @@ Constant *llvm::ConstantFoldInstruction(Instruction *I, const DataLayout &DL, if (!C) return nullptr; // Fold the PHI's operands. - if (auto *NewC = dyn_cast(C)) - if (auto *FoldedC = ConstantFoldConstantExpression(NewC, DL, TLI)) - C = FoldedC; + if (auto *FoldedC = ConstantFoldConstantImpl(C, DL, TLI, FoldedOps)) + C = FoldedC; // If the incoming value is a different constant to // the one we saw previously, then give up. if (CommonValue && C != CommonValue) @@ -996,7 +1038,6 @@ Constant *llvm::ConstantFoldInstruction(Instruction *I, const DataLayout &DL, CommonValue = C; } - // If we reach here, all incoming values are the same constant or undef. return CommonValue ? CommonValue : UndefValue::get(PN->getType()); } @@ -1006,13 +1047,13 @@ Constant *llvm::ConstantFoldInstruction(Instruction *I, const DataLayout &DL, if (!all_of(I->operands(), [](Use &U) { return isa(U); })) return nullptr; + SmallDenseMap FoldedOps; SmallVector Ops; for (const Use &OpU : I->operands()) { auto *Op = cast(&OpU); // Fold the Instruction's operands. - if (auto *NewCE = dyn_cast(Op)) - if (auto *FoldedOp = ConstantFoldConstantExpression(NewCE, DL, TLI)) - Op = FoldedOp; + if (auto *FoldedOp = ConstantFoldConstantImpl(Op, DL, TLI, FoldedOps)) + Op = FoldedOp; Ops.push_back(Op); } @@ -1040,48 +1081,10 @@ Constant *llvm::ConstantFoldInstruction(Instruction *I, const DataLayout &DL, return ConstantFoldInstOperands(I, Ops, DL, TLI); } -namespace { - -Constant *ConstantFoldConstantExpressionImpl( - const ConstantExpr *CE, const DataLayout &DL, const TargetLibraryInfo *TLI, - SmallDenseMap &FoldedOps) { - SmallVector Ops; - for (const Use &NewU : CE->operands()) { - auto *NewC = cast(&NewU); - // Recursively fold the ConstantExpr's operands. If we have already folded - // a ConstantExpr, we don't have to process it again. - if (auto *NewCE = dyn_cast(NewC)) { - auto It = FoldedOps.find(NewCE); - if (It == FoldedOps.end()) { - if (auto *FoldedC = - ConstantFoldConstantExpressionImpl(NewCE, DL, TLI, FoldedOps)) { - NewC = FoldedC; - FoldedOps.insert({NewCE, FoldedC}); - } else { - FoldedOps.insert({NewCE, NewCE}); - } - } else { - NewC = It->second; - } - } - Ops.push_back(NewC); - } - - if (CE->isCompare()) - return ConstantFoldCompareInstOperands(CE->getPredicate(), Ops[0], Ops[1], - DL, TLI); - - return ConstantFoldInstOperandsImpl(CE, CE->getType(), CE->getOpcode(), Ops, - DL, TLI); -} - -} // end anonymous namespace - -Constant *llvm::ConstantFoldConstantExpression(const ConstantExpr *CE, - const DataLayout &DL, - const TargetLibraryInfo *TLI) { - SmallDenseMap FoldedOps; - return ConstantFoldConstantExpressionImpl(CE, DL, TLI, FoldedOps); +Constant *llvm::ConstantFoldConstant(const Constant *C, const DataLayout &DL, + const TargetLibraryInfo *TLI) { + SmallDenseMap FoldedOps; + return ConstantFoldConstantImpl(C, DL, TLI, FoldedOps); } Constant *llvm::ConstantFoldInstOperands(Instruction *I, diff --git a/lib/Analysis/Lint.cpp b/lib/Analysis/Lint.cpp index fdf5f55dab9..0b374bad129 100644 --- a/lib/Analysis/Lint.cpp +++ b/lib/Analysis/Lint.cpp @@ -680,9 +680,9 @@ Value *Lint::findValueImpl(Value *V, bool OffsetOk, if (Instruction *Inst = dyn_cast(V)) { if (Value *W = SimplifyInstruction(Inst, *DL, TLI, DT, AC)) return findValueImpl(W, OffsetOk, Visited); - } else if (ConstantExpr *CE = dyn_cast(V)) { - if (Value *W = ConstantFoldConstantExpression(CE, *DL, TLI)) - if (W != V) + } else if (auto *C = dyn_cast(V)) { + if (Value *W = ConstantFoldConstant(C, *DL, TLI)) + if (W && W != V) return findValueImpl(W, OffsetOk, Visited); } diff --git a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index 90ed275ed97..c5f415cb529 100644 --- a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -1764,7 +1764,7 @@ const MCExpr *AsmPrinter::lowerConstant(const Constant *CV) { // If the code isn't optimized, there may be outstanding folding // opportunities. Attempt to fold the expression using DataLayout as a // last resort before giving up. - if (Constant *C = ConstantFoldConstantExpression(CE, getDataLayout())) + if (Constant *C = ConstantFoldConstant(CE, getDataLayout())) if (C != CE) return lowerConstant(C); @@ -2299,7 +2299,7 @@ static void emitGlobalConstantImpl(const DataLayout &DL, const Constant *CV, // If the constant expression's size is greater than 64-bits, then we have // to emit the value in chunks. Try to constant fold the value and emit it // that way. - Constant *New = ConstantFoldConstantExpression(CE, DL); + Constant *New = ConstantFoldConstant(CE, DL); if (New && New != CE) return emitGlobalConstantImpl(DL, New, AP); } diff --git a/lib/Target/NVPTX/NVPTXAsmPrinter.cpp b/lib/Target/NVPTX/NVPTXAsmPrinter.cpp index f2bd585a8f3..e627be0b23d 100644 --- a/lib/Target/NVPTX/NVPTXAsmPrinter.cpp +++ b/lib/Target/NVPTX/NVPTXAsmPrinter.cpp @@ -1848,9 +1848,9 @@ void NVPTXAsmPrinter::bufferLEByte(const Constant *CPV, int Bytes, ConvertIntToBytes<>(ptr, int32); aggBuffer->addBytes(ptr, 4, Bytes); break; - } else if (const ConstantExpr *Cexpr = dyn_cast(CPV)) { - if (const ConstantInt *constInt = dyn_cast( - ConstantFoldConstantExpression(Cexpr, DL))) { + } else if (const auto *Cexpr = dyn_cast(CPV)) { + if (const auto *constInt = dyn_cast_or_null( + ConstantFoldConstant(Cexpr, DL))) { int int32 = (int)(constInt->getZExtValue()); ConvertIntToBytes<>(ptr, int32); aggBuffer->addBytes(ptr, 4, Bytes); @@ -1871,8 +1871,8 @@ void NVPTXAsmPrinter::bufferLEByte(const Constant *CPV, int Bytes, aggBuffer->addBytes(ptr, 8, Bytes); break; } else if (const ConstantExpr *Cexpr = dyn_cast(CPV)) { - if (const ConstantInt *constInt = dyn_cast( - ConstantFoldConstantExpression(Cexpr, DL))) { + if (const auto *constInt = dyn_cast_or_null( + ConstantFoldConstant(Cexpr, DL))) { long long int64 = (long long)(constInt->getZExtValue()); ConvertIntToBytes<>(ptr, int64); aggBuffer->addBytes(ptr, 8, Bytes); @@ -2074,8 +2074,8 @@ NVPTXAsmPrinter::lowerConstantForGV(const Constant *CV, bool ProcessingGeneric) // If the code isn't optimized, there may be outstanding folding // opportunities. Attempt to fold the expression using DataLayout as a // last resort before giving up. - if (Constant *C = ConstantFoldConstantExpression(CE, getDataLayout())) - if (C != CE) + if (Constant *C = ConstantFoldConstant(CE, getDataLayout())) + if (C && C != CE) return lowerConstantForGV(C, ProcessingGeneric); // Otherwise report the problem to the user. diff --git a/lib/Transforms/IPO/GlobalOpt.cpp b/lib/Transforms/IPO/GlobalOpt.cpp index 99b12d4db0d..967aeb32d86 100644 --- a/lib/Transforms/IPO/GlobalOpt.cpp +++ b/lib/Transforms/IPO/GlobalOpt.cpp @@ -2079,10 +2079,10 @@ OptimizeGlobalVars(Module &M, TargetLibraryInfo *TLI, GV->setLinkage(GlobalValue::InternalLinkage); // Simplify the initializer. if (GV->hasInitializer()) - if (ConstantExpr *CE = dyn_cast(GV->getInitializer())) { + if (auto *C = dyn_cast(GV->getInitializer())) { auto &DL = M.getDataLayout(); - Constant *New = ConstantFoldConstantExpression(CE, DL, TLI); - if (New && New != CE) + Constant *New = ConstantFoldConstant(C, DL, TLI); + if (New && New != C) GV->setInitializer(New); } diff --git a/lib/Transforms/InstCombine/InstCombineCasts.cpp b/lib/Transforms/InstCombine/InstCombineCasts.cpp index d41c449c7d2..840feca3338 100644 --- a/lib/Transforms/InstCombine/InstCombineCasts.cpp +++ b/lib/Transforms/InstCombine/InstCombineCasts.cpp @@ -161,9 +161,8 @@ Value *InstCombiner::EvaluateInDifferentType(Value *V, Type *Ty, if (Constant *C = dyn_cast(V)) { C = ConstantExpr::getIntegerCast(C, Ty, isSigned /*Sext or ZExt*/); // If we got a constantexpr back, try to simplify it with DL info. - if (ConstantExpr *CE = dyn_cast(C)) - if (Constant *FoldedC = ConstantFoldConstantExpression(CE, DL, TLI)) - C = FoldedC; + if (Constant *FoldedC = ConstantFoldConstant(C, DL, TLI)) + C = FoldedC; return C; } diff --git a/lib/Transforms/InstCombine/InstCombineShifts.cpp b/lib/Transforms/InstCombine/InstCombineShifts.cpp index 08e16a7ee1a..279eaad0174 100644 --- a/lib/Transforms/InstCombine/InstCombineShifts.cpp +++ b/lib/Transforms/InstCombine/InstCombineShifts.cpp @@ -194,8 +194,10 @@ static Value *GetShiftedValue(Value *V, unsigned NumBits, bool isLeftShift, else V = IC.Builder->CreateLShr(C, NumBits); // If we got a constantexpr back, try to simplify it with TD info. - if (ConstantExpr *CE = dyn_cast(V)) - V = ConstantFoldConstantExpression(CE, DL, IC.getTargetLibraryInfo()); + if (auto *C = dyn_cast(V)) + if (auto *FoldedC = + ConstantFoldConstant(C, DL, IC.getTargetLibraryInfo())) + V = FoldedC; return V; } diff --git a/lib/Transforms/InstCombine/InstructionCombining.cpp b/lib/Transforms/InstCombine/InstructionCombining.cpp index 377ccb9c37f..6e4c823901a 100644 --- a/lib/Transforms/InstCombine/InstructionCombining.cpp +++ b/lib/Transforms/InstCombine/InstructionCombining.cpp @@ -2981,7 +2981,7 @@ static bool AddReachableCodeToWorklist(BasicBlock *BB, const DataLayout &DL, Worklist.push_back(BB); SmallVector InstrsForInstCombineWorklist; - DenseMap FoldedConstants; + DenseMap FoldedConstants; do { BB = Worklist.pop_back_val(); @@ -3017,17 +3017,17 @@ static bool AddReachableCodeToWorklist(BasicBlock *BB, const DataLayout &DL, // See if we can constant fold its operands. for (User::op_iterator i = Inst->op_begin(), e = Inst->op_end(); i != e; ++i) { - ConstantExpr *CE = dyn_cast(i); - if (CE == nullptr) + if (!isa(i) && !isa(i)) continue; - Constant *&FoldRes = FoldedConstants[CE]; + auto *C = cast(i); + Constant *&FoldRes = FoldedConstants[C]; if (!FoldRes) - FoldRes = ConstantFoldConstantExpression(CE, DL, TLI); + FoldRes = ConstantFoldConstant(C, DL, TLI); if (!FoldRes) - FoldRes = CE; + FoldRes = C; - if (FoldRes != CE) { + if (FoldRes != C) { *i = FoldRes; MadeIRChange = true; } diff --git a/lib/Transforms/Scalar/GVN.cpp b/lib/Transforms/Scalar/GVN.cpp index a35a1062cbc..6f2ce243f5f 100644 --- a/lib/Transforms/Scalar/GVN.cpp +++ b/lib/Transforms/Scalar/GVN.cpp @@ -725,8 +725,9 @@ static Value *CoerceAvailableValueToLoadType(Value *StoredVal, Type *LoadedTy, assert(CanCoerceMustAliasedValueToLoad(StoredVal, LoadedTy, DL) && "precondition violation - materialization can't fail"); - if (auto *CExpr = dyn_cast(StoredVal)) - StoredVal = ConstantFoldConstantExpression(CExpr, DL); + if (auto *C = dyn_cast(StoredVal)) + if (auto *FoldedStoredVal = ConstantFoldConstant(C, DL)) + StoredVal = FoldedStoredVal; // If this is already the right type, just return it. Type *StoredValTy = StoredVal->getType(); @@ -759,8 +760,9 @@ static Value *CoerceAvailableValueToLoadType(Value *StoredVal, Type *LoadedTy, StoredVal = IRB.CreateIntToPtr(StoredVal, LoadedTy); } - if (auto *CExpr = dyn_cast(StoredVal)) - StoredVal = ConstantFoldConstantExpression(CExpr, DL); + if (auto *C = dyn_cast(StoredVal)) + if (auto *FoldedStoredVal = ConstantFoldConstant(C, DL)) + StoredVal = FoldedStoredVal; return StoredVal; } @@ -804,8 +806,9 @@ static Value *CoerceAvailableValueToLoadType(Value *StoredVal, Type *LoadedTy, StoredVal = IRB.CreateBitCast(StoredVal, LoadedTy, "bitcast"); } - if (auto *CExpr = dyn_cast(StoredVal)) - StoredVal = ConstantFoldConstantExpression(CExpr, DL); + if (auto *C = dyn_cast(StoredVal)) + if (auto *FoldedStoredVal = ConstantFoldConstant(C, DL)) + StoredVal = FoldedStoredVal; return StoredVal; } diff --git a/lib/Transforms/Utils/Evaluator.cpp b/lib/Transforms/Utils/Evaluator.cpp index cd130abf451..008ee505b39 100644 --- a/lib/Transforms/Utils/Evaluator.cpp +++ b/lib/Transforms/Utils/Evaluator.cpp @@ -203,9 +203,9 @@ bool Evaluator::EvaluateBlock(BasicBlock::iterator CurInst, return false; // no volatile/atomic accesses. } Constant *Ptr = getVal(SI->getOperand(1)); - if (ConstantExpr *CE = dyn_cast(Ptr)) { + if (auto *FoldedPtr = ConstantFoldConstant(Ptr, DL, TLI)) { DEBUG(dbgs() << "Folding constant ptr expression: " << *Ptr); - Ptr = ConstantFoldConstantExpression(CE, DL, TLI); + Ptr = FoldedPtr; DEBUG(dbgs() << "; To: " << *Ptr << "\n"); } if (!isSimpleEnoughPointerToCommit(Ptr)) { @@ -249,8 +249,8 @@ bool Evaluator::EvaluateBlock(BasicBlock::iterator CurInst, Constant * const IdxList[] = {IdxZero, IdxZero}; Ptr = ConstantExpr::getGetElementPtr(nullptr, Ptr, IdxList); - if (ConstantExpr *CE = dyn_cast(Ptr)) - Ptr = ConstantFoldConstantExpression(CE, DL, TLI); + if (auto *FoldedPtr = ConstantFoldConstant(Ptr, DL, TLI)) + Ptr = FoldedPtr; // If we can't improve the situation by introspecting NewTy, // we have to give up. @@ -324,8 +324,8 @@ bool Evaluator::EvaluateBlock(BasicBlock::iterator CurInst, } Constant *Ptr = getVal(LI->getOperand(0)); - if (ConstantExpr *CE = dyn_cast(Ptr)) { - Ptr = ConstantFoldConstantExpression(CE, DL, TLI); + if (auto *FoldedPtr = ConstantFoldConstant(Ptr, DL, TLI)) { + Ptr = FoldedPtr; DEBUG(dbgs() << "Found a constant pointer expression, constant " "folding: " << *Ptr << "\n"); } @@ -512,8 +512,8 @@ bool Evaluator::EvaluateBlock(BasicBlock::iterator CurInst, } if (!CurInst->use_empty()) { - if (ConstantExpr *CE = dyn_cast(InstResult)) - InstResult = ConstantFoldConstantExpression(CE, DL, TLI); + if (auto *FoldedInstResult = ConstantFoldConstant(InstResult, DL, TLI)) + InstResult = FoldedInstResult; setVal(&*CurInst, InstResult); } diff --git a/test/Transforms/InstCombine/icmp-vec.ll b/test/Transforms/InstCombine/icmp-vec.ll index 6fe3f631701..f831e2bae29 100644 --- a/test/Transforms/InstCombine/icmp-vec.ll +++ b/test/Transforms/InstCombine/icmp-vec.ll @@ -159,11 +159,9 @@ define <2 x i1> @ule_max(<2 x i3> %x) { ret <2 x i1> %cmp } -; If we can't determine if a constant element is min/max (eg, it's a ConstantExpr), do nothing. - define <2 x i1> @PR27756_1(<2 x i8> %a) { ; CHECK-LABEL: @PR27756_1( -; CHECK-NEXT: [[CMP:%.*]] = icmp sle <2 x i8> %a, to i8), i8 0> +; CHECK-NEXT: [[CMP:%.*]] = icmp slt <2 x i8> %a, ; CHECK-NEXT: ret <2 x i1> [[CMP]] ; %cmp = icmp sle <2 x i8> %a, to i8), i8 0>