Index: include/llvm/Analysis/ConstantFolding.h =================================================================== --- include/llvm/Analysis/ConstantFolding.h +++ include/llvm/Analysis/ConstantFolding.h @@ -28,6 +28,7 @@ class TargetLibraryInfo; class Function; class Type; + class Value; template class ArrayRef; @@ -46,6 +47,12 @@ ConstantFoldConstantExpression(const ConstantExpr *CE, const DataLayout &DL, const TargetLibraryInfo *TLI = nullptr); + Constant *ConstantFoldInstOperands(const Value *InstOrCE, + unsigned Opcode, Type *DestTy, + ArrayRef Ops, + const DataLayout &DL, + const TargetLibraryInfo *TLI = nullptr); + /// ConstantFoldInstOperands - Attempt to constant fold an instruction with the /// specified operands. If successful, the constant result is returned, if not, /// null is returned. Note that this function can fail when attempting to Index: lib/Analysis/ConstantFolding.cpp =================================================================== --- lib/Analysis/ConstantFolding.cpp +++ lib/Analysis/ConstantFolding.cpp @@ -683,9 +683,7 @@ SmallVector NewIdxs; for (unsigned i = 1, e = Ops.size(); i != e; ++i) { if ((i == 1 || - !isa(GetElementPtrInst::getIndexedType( - cast(Ops[0]->getType()->getScalarType()) - ->getElementType(), + !isa(GetElementPtrInst::getIndexedType(SrcTy, Ops.slice(1, i - 1)))) && Ops[i]->getType() != IntPtrTy) { Any = true; @@ -711,16 +709,17 @@ } /// Strip the pointer casts, but preserve the address space information. -static Constant* StripPtrCastKeepAS(Constant* Ptr) { +static Constant* StripPtrCastKeepAS(Constant* Ptr, Type *&SrcTy) { assert(Ptr->getType()->isPointerTy() && "Not a pointer type"); PointerType *OldPtrTy = cast(Ptr->getType()); Ptr = Ptr->stripPointerCasts(); PointerType *NewPtrTy = cast(Ptr->getType()); + SrcTy = NewPtrTy->getPointerElementType(); + // Preserve the address space number of the pointer. if (NewPtrTy->getAddressSpace() != OldPtrTy->getAddressSpace()) { - NewPtrTy = NewPtrTy->getElementType()->getPointerTo( - OldPtrTy->getAddressSpace()); + NewPtrTy = SrcTy->getPointerTo(OldPtrTy->getAddressSpace()); Ptr = ConstantExpr::getPointerCast(Ptr, NewPtrTy); } return Ptr; @@ -728,15 +727,14 @@ /// If we can symbolically evaluate the GEP constant expression, do so. static Constant *SymbolicallyEvaluateGEP(Type *SrcTy, ArrayRef Ops, - Type *ResultTy, const DataLayout &DL, + Type *ResultTy, Type *ResultElementTy, + const DataLayout &DL, const TargetLibraryInfo *TLI) { Constant *Ptr = Ops[0]; - if (!Ptr->getType()->getPointerElementType()->isSized() || - !Ptr->getType()->isPointerTy()) + if (!SrcTy->isSized() || !Ptr->getType()->isPointerTy()) return nullptr; Type *IntPtrTy = DL.getIntPtrType(Ptr->getType()); - Type *ResultElementTy = ResultTy->getPointerElementType(); // If this is a constant expr gep that is effectively computing an // "offsetof", fold it into 'cast int Size to T*' instead of 'gep 0, 0, 12' @@ -768,7 +766,7 @@ DL.getIndexedOffset( Ptr->getType(), makeArrayRef((Value * const *)Ops.data() + 1, Ops.size() - 1))); - Ptr = StripPtrCastKeepAS(Ptr); + Ptr = StripPtrCastKeepAS(Ptr, SrcTy); // If this is a GEP of a GEP, fold it all into a single GEP. while (GEPOperator *GEP = dyn_cast(Ptr)) { @@ -786,7 +784,7 @@ Ptr = cast(GEP->getOperand(0)); Offset += APInt(BitWidth, DL.getIndexedOffset(Ptr->getType(), NestedOps)); - Ptr = StripPtrCastKeepAS(Ptr); + Ptr = StripPtrCastKeepAS(Ptr, SrcTy); } // If the base value for this address is a literal integer value, fold the @@ -813,19 +811,43 @@ SmallVector NewIdxs; do { - if (SequentialType *ATy = dyn_cast(Ty)) { - if (ATy->isPointerTy()) { + if (StructType *STy = dyn_cast(Ty)) { + // If we end up with an offset that isn't valid for this struct type, we + // can't re-form this GEP in a regular form, so bail out. The pointer + // operand likely went through casts that are necessary to make the GEP + // sensible. + const StructLayout &SL = *DL.getStructLayout(STy); + if (Offset.uge(SL.getSizeInBytes())) + break; + + // Determine which field of the struct the offset points into. The + // getZExtValue is fine as we've already ensured that the offset is + // within the range representable by the StructLayout API. + unsigned ElIdx = SL.getElementContainingOffset(Offset.getZExtValue()); + NewIdxs.push_back(ConstantInt::get(Type::getInt32Ty(Ty->getContext()), + ElIdx)); + Offset -= APInt(BitWidth, SL.getElementOffset(ElIdx)); + Ty = STy->getTypeAtIndex(ElIdx); + } else { + if (Ty->isPointerTy()) { // The only pointer indexing we'll do is on the first index of the GEP. if (!NewIdxs.empty()) break; + Ty = SrcTy; + // Only handle pointers to sized types, not pointers to functions. - if (!ATy->getElementType()->isSized()) + if (!Ty->isSized()) return nullptr; + } else if (auto *ATy = dyn_cast(Ty)) { + Ty = ATy->getElementType(); + } else { + // We've reached some non-indexable type. + break; } // Determine which element of the array the offset points into. - APInt ElemSize(BitWidth, DL.getTypeAllocSize(ATy->getElementType())); + APInt ElemSize(BitWidth, DL.getTypeAllocSize(Ty)); if (ElemSize == 0) // The element size is 0. This may be [0 x Ty]*, so just use a zero // index for this level and proceed to the next level to see if it can @@ -838,27 +860,6 @@ Offset -= NewIdx * ElemSize; NewIdxs.push_back(ConstantInt::get(IntPtrTy, NewIdx)); } - Ty = ATy->getElementType(); - } else if (StructType *STy = dyn_cast(Ty)) { - // If we end up with an offset that isn't valid for this struct type, we - // can't re-form this GEP in a regular form, so bail out. The pointer - // operand likely went through casts that are necessary to make the GEP - // sensible. - const StructLayout &SL = *DL.getStructLayout(STy); - if (Offset.uge(SL.getSizeInBytes())) - break; - - // Determine which field of the struct the offset points into. The - // getZExtValue is fine as we've already ensured that the offset is - // within the range representable by the StructLayout API. - unsigned ElIdx = SL.getElementContainingOffset(Offset.getZExtValue()); - NewIdxs.push_back(ConstantInt::get(Type::getInt32Ty(Ty->getContext()), - ElIdx)); - Offset -= APInt(BitWidth, SL.getElementOffset(ElIdx)); - Ty = STy->getTypeAtIndex(ElIdx); - } else { - // We've reached some non-indexable type. - break; } } while (Ty != ResultElementTy); @@ -959,7 +960,7 @@ EVI->getIndices()); } - return ConstantFoldInstOperands(I->getOpcode(), I->getType(), Ops, DL, TLI); + return ConstantFoldInstOperands(I, I->getOpcode(), I->getType(), Ops, DL, TLI); } static Constant * @@ -982,7 +983,7 @@ if (CE->isCompare()) return ConstantFoldCompareInstOperands(CE->getPredicate(), Ops[0], Ops[1], DL, TLI); - return ConstantFoldInstOperands(CE->getOpcode(), CE->getType(), Ops, DL, TLI); + return ConstantFoldInstOperands(CE, CE->getOpcode(), CE->getType(), Ops, DL, TLI); } /// Attempt to fold the constant expression @@ -1009,6 +1010,14 @@ ArrayRef Ops, const DataLayout &DL, const TargetLibraryInfo *TLI) { + return ConstantFoldInstOperands(nullptr, Opcode, DestTy, Ops, DL, TLI); +} + +Constant *llvm::ConstantFoldInstOperands(const Value *InstOrCE, + unsigned Opcode, Type *DestTy, + ArrayRef Ops, + const DataLayout &DL, + const TargetLibraryInfo *TLI) { // Handle easy binops first. if (Instruction::isBinaryOp(Opcode)) { if (isa(Ops[0]) || isa(Ops[1])) { @@ -1089,10 +1098,14 @@ case Instruction::ShuffleVector: return ConstantExpr::getShuffleVector(Ops[0], Ops[1], Ops[2]); case Instruction::GetElementPtr: { - Type *SrcTy = nullptr; + assert(InstOrCE && "Missing instruction/constant expression"); + auto *GEP = cast(InstOrCE); + Type *SrcTy = GEP->getSourceElementType(); + Type *DestElemTy = GEP->getResultElementType(); + if (Constant *C = CastGEPIndices(SrcTy, Ops, DestTy, DL, TLI)) return C; - if (Constant *C = SymbolicallyEvaluateGEP(SrcTy, Ops, DestTy, DL, TLI)) + if (Constant *C = SymbolicallyEvaluateGEP(SrcTy, Ops, DestTy, DestElemTy, DL, TLI)) return C; return ConstantExpr::getGetElementPtr(SrcTy, Ops[0], Ops.slice(1)); Index: lib/Analysis/InlineCost.cpp =================================================================== --- lib/Analysis/InlineCost.cpp +++ lib/Analysis/InlineCost.cpp @@ -533,7 +533,7 @@ COp = SimplifiedValues.lookup(Operand); if (COp) { const DataLayout &DL = F.getParent()->getDataLayout(); - if (Constant *C = ConstantFoldInstOperands(I.getOpcode(), I.getType(), + if (Constant *C = ConstantFoldInstOperands(&I, I.getOpcode(), I.getType(), COp, DL)) { SimplifiedValues[&I] = C; return true; Index: lib/Analysis/InstructionSimplify.cpp =================================================================== --- lib/Analysis/InstructionSimplify.cpp +++ lib/Analysis/InstructionSimplify.cpp @@ -3297,7 +3297,7 @@ if (!LI->isVolatile()) return ConstantFoldLoadFromConstPtr(ConstOps[0], Q.DL); - return ConstantFoldInstOperands(I->getOpcode(), I->getType(), ConstOps, + return ConstantFoldInstOperands(I, I->getOpcode(), I->getType(), ConstOps, Q.DL, Q.TLI); } } Index: lib/Analysis/ScalarEvolution.cpp =================================================================== --- lib/Analysis/ScalarEvolution.cpp +++ lib/Analysis/ScalarEvolution.cpp @@ -5910,7 +5910,7 @@ if (!LI->isVolatile()) return ConstantFoldLoadFromConstPtr(Operands[0], DL); } - return ConstantFoldInstOperands(I->getOpcode(), I->getType(), Operands, DL, + return ConstantFoldInstOperands(I, I->getOpcode(), I->getType(), Operands, DL, TLI); } @@ -6299,7 +6299,7 @@ if (!LI->isVolatile()) C = ConstantFoldLoadFromConstPtr(Operands[0], DL); } else - C = ConstantFoldInstOperands(I->getOpcode(), I->getType(), Operands, + C = ConstantFoldInstOperands(I, I->getOpcode(), I->getType(), Operands, DL, &TLI); if (!C) return V; return getSCEV(C); Index: lib/Transforms/Utils/SimplifyCFG.cpp =================================================================== --- lib/Transforms/Utils/SimplifyCFG.cpp +++ lib/Transforms/Utils/SimplifyCFG.cpp @@ -3989,7 +3989,7 @@ COps[1], DL); } - return ConstantFoldInstOperands(I->getOpcode(), I->getType(), COps, DL); + return ConstantFoldInstOperands(I, I->getOpcode(), I->getType(), COps, DL); } /// Try to determine the resulting constant values in phi nodes