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: include/llvm/Analysis/InstructionSimplify.h =================================================================== --- include/llvm/Analysis/InstructionSimplify.h +++ include/llvm/Analysis/InstructionSimplify.h @@ -229,7 +229,8 @@ /// SimplifyGEPInst - Given operands for an GetElementPtrInst, see if we can /// fold the result. If not, this returns null. - Value *SimplifyGEPInst(ArrayRef Ops, const DataLayout &DL, + Value *SimplifyGEPInst(Type *SrcTy, ArrayRef Ops, + const DataLayout &DL, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, AssumptionCache *AC = nullptr, Index: include/llvm/Analysis/TargetTransformInfoImpl.h =================================================================== --- include/llvm/Analysis/TargetTransformInfoImpl.h +++ include/llvm/Analysis/TargetTransformInfoImpl.h @@ -421,7 +421,7 @@ // Assumes the address space is 0 when Ptr is nullptr. unsigned AS = (Ptr == nullptr ? 0 : Ptr->getType()->getPointerAddressSpace()); - auto GTI = gep_type_begin(PointerType::get(PointeeType, AS), Operands); + auto GTI = gep_type_begin(PointeeType, AS, Operands); for (auto I = Operands.begin(); I != Operands.end(); ++I, ++GTI) { // We assume that the cost of Scalar GEP with constant index and the // cost of Vector GEP with splat constant index are the same. Index: include/llvm/IR/DataLayout.h =================================================================== --- include/llvm/IR/DataLayout.h +++ include/llvm/IR/DataLayout.h @@ -441,8 +441,9 @@ /// \brief Returns the offset from the beginning of the type for the specified /// indices. /// + /// Note that this takes the element type, not the pointer type. /// This is used to implement getelementptr. - uint64_t getIndexedOffset(Type *Ty, ArrayRef Indices) const; + uint64_t getIndexedOffset(Type *ElemTy, ArrayRef Indices) const; /// \brief Returns a StructLayout object, indicating the alignment of the /// struct, its size, and the offsets of its fields. Index: include/llvm/IR/GetElementPtrTypeIterator.h =================================================================== --- include/llvm/IR/GetElementPtrTypeIterator.h +++ include/llvm/IR/GetElementPtrTypeIterator.h @@ -33,12 +33,6 @@ generic_gep_type_iterator() {} public: - static generic_gep_type_iterator begin(Type *Ty, ItTy It) { - generic_gep_type_iterator I; - I.CurTy.setPointer(Ty); - I.OpIt = It; - return I; - } static generic_gep_type_iterator begin(Type *Ty, unsigned AddrSpace, ItTy It) { generic_gep_type_iterator I; @@ -125,13 +119,13 @@ template inline generic_gep_type_iterator - gep_type_begin(Type *Op0, ArrayRef A) { - return generic_gep_type_iterator::begin(Op0, A.begin()); + gep_type_begin(Type *Op0, unsigned AS, ArrayRef A) { + return generic_gep_type_iterator::begin(Op0, AS, A.begin()); } template inline generic_gep_type_iterator - gep_type_end(Type * /*Op0*/, ArrayRef A) { + gep_type_end(Type * /*Op0*/, unsigned /*AS*/, ArrayRef A) { return generic_gep_type_iterator::end(A.end()); } } // end namespace llvm Index: include/llvm/IR/Operator.h =================================================================== --- include/llvm/IR/Operator.h +++ include/llvm/IR/Operator.h @@ -401,6 +401,7 @@ } Type *getSourceElementType() const; + Type *getResultElementType() const; /// Method to return the address space of the pointer operand. unsigned getPointerAddressSpace() const { Index: lib/Analysis/BasicAliasAnalysis.cpp =================================================================== --- lib/Analysis/BasicAliasAnalysis.cpp +++ lib/Analysis/BasicAliasAnalysis.cpp @@ -381,7 +381,7 @@ } // Don't attempt to analyze GEPs over unsized objects. - if (!GEPOp->getOperand(0)->getType()->getPointerElementType()->isSized()) + if (!GEPOp->getSourceElementType()->isSized()) return V; unsigned AS = GEPOp->getPointerAddressSpace(); 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' @@ -766,9 +764,9 @@ APInt Offset = APInt(BitWidth, DL.getIndexedOffset( - Ptr->getType(), + SrcTy, 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)) { @@ -785,8 +783,9 @@ break; Ptr = cast(GEP->getOperand(0)); - Offset += APInt(BitWidth, DL.getIndexedOffset(Ptr->getType(), NestedOps)); - Ptr = StripPtrCastKeepAS(Ptr); + SrcTy = GEP->getSourceElementType(); + Offset += APInt(BitWidth, DL.getIndexedOffset(SrcTy, NestedOps)); + Ptr = StripPtrCastKeepAS(Ptr, SrcTy); } // If the base value for this address is a literal integer value, fold the @@ -813,19 +812,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 +861,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 +961,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 +984,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 +1011,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 +1099,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); } } @@ -3527,13 +3527,13 @@ Ops.slice(1)); } -Value *llvm::SimplifyGEPInst(ArrayRef Ops, const DataLayout &DL, +Value *llvm::SimplifyGEPInst(Type *SrcTy, ArrayRef Ops, + const DataLayout &DL, const TargetLibraryInfo *TLI, const DominatorTree *DT, AssumptionCache *AC, const Instruction *CxtI) { - return ::SimplifyGEPInst( - cast(Ops[0]->getType()->getScalarType())->getElementType(), - Ops, Query(DL, TLI, DT, AC, CxtI), RecursionLimit); + return ::SimplifyGEPInst(SrcTy, Ops, + Query(DL, TLI, DT, AC, CxtI), RecursionLimit); } /// Given operands for an InsertValueInst, see if we can fold the result. @@ -4038,7 +4038,8 @@ break; case Instruction::GetElementPtr: { SmallVector Ops(I->op_begin(), I->op_end()); - Result = SimplifyGEPInst(Ops, DL, TLI, DT, AC, I); + Result = SimplifyGEPInst(cast(I)->getSourceElementType(), + Ops, DL, TLI, DT, AC, I); break; } case Instruction::InsertValue: { Index: lib/Analysis/PHITransAddr.cpp =================================================================== --- lib/Analysis/PHITransAddr.cpp +++ lib/Analysis/PHITransAddr.cpp @@ -229,7 +229,8 @@ return GEP; // Simplify the GEP to handle 'gep x, 0' -> x etc. - if (Value *V = SimplifyGEPInst(GEPOps, DL, TLI, DT, AC)) { + if (Value *V = SimplifyGEPInst(GEP->getSourceElementType(), + GEPOps, DL, TLI, DT, AC)) { for (unsigned i = 0, e = GEPOps.size(); i != e; ++i) RemoveInstInputs(GEPOps[i], InstInputs); Index: lib/Analysis/ScalarEvolution.cpp =================================================================== --- lib/Analysis/ScalarEvolution.cpp +++ lib/Analysis/ScalarEvolution.cpp @@ -4089,7 +4089,7 @@ const SCEV *ScalarEvolution::createNodeForGEP(GEPOperator *GEP) { Value *Base = GEP->getOperand(0); // Don't attempt to analyze GEPs over unsized objects. - if (!Base->getType()->getPointerElementType()->isSized()) + if (!GEP->getSourceElementType()->isSized()) return getUnknown(GEP); SmallVector IndexExprs; @@ -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/Analysis/ValueTracking.cpp =================================================================== --- lib/Analysis/ValueTracking.cpp +++ lib/Analysis/ValueTracking.cpp @@ -2886,8 +2886,7 @@ return false; // Make sure the index-ee is a pointer to array of i8. - PointerType *PT = cast(GEP->getOperand(0)->getType()); - ArrayType *AT = dyn_cast(PT->getElementType()); + ArrayType *AT = dyn_cast(GEP->getSourceElementType()); if (!AT || !AT->getElementType()->isIntegerTy(8)) return false; @@ -3254,7 +3253,7 @@ // For GEPs, determine if the indexing lands within the allocated object. if (const GEPOperator *GEP = dyn_cast(V)) { Type *VTy = GEP->getType(); - Type *Ty = VTy->getPointerElementType(); + Type *Ty = GEP->getResultElementType(); const Value *Base = GEP->getPointerOperand(); // Conservatively require that the base pointer be fully dereferenceable @@ -3272,7 +3271,7 @@ // Check if the load is within the bounds of the underlying object // and offset is aligned. uint64_t LoadSize = DL.getTypeStoreSize(Ty); - Type *BaseType = Base->getType()->getPointerElementType(); + Type *BaseType = GEP->getSourceElementType(); assert(isPowerOf2_32(Align) && "must be a power of 2!"); return (Offset + LoadSize).ule(DL.getTypeAllocSize(BaseType)) && !(Offset & APInt(Offset.getBitWidth(), Align-1)); Index: lib/Analysis/VectorUtils.cpp =================================================================== --- lib/Analysis/VectorUtils.cpp +++ lib/Analysis/VectorUtils.cpp @@ -231,8 +231,7 @@ unsigned llvm::getGEPInductionOperand(const GetElementPtrInst *Gep) { const DataLayout &DL = Gep->getModule()->getDataLayout(); unsigned LastOperand = Gep->getNumOperands() - 1; - unsigned GEPAllocSize = DL.getTypeAllocSize( - cast(Gep->getType()->getScalarType())->getElementType()); + unsigned GEPAllocSize = DL.getTypeAllocSize(Gep->getResultElementType()); // Walk backwards and try to peel off zeros. while (LastOperand > 1 && match(Gep->getOperand(LastOperand), m_Zero())) { Index: lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp =================================================================== --- lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp +++ lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp @@ -192,14 +192,14 @@ addToAccelTable = true; // GV is a merged global. DIELoc *Loc = new (DIEValueAllocator) DIELoc; - Value *Ptr = CE->getOperand(0); - MCSymbol *Sym = Asm->getSymbol(cast(Ptr)); + auto *Ptr = cast(CE->getOperand(0)); + MCSymbol *Sym = Asm->getSymbol(Ptr); DD->addArangeLabel(SymbolCU(this, Sym)); addOpAddress(*Loc, Sym); addUInt(*Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_constu); SmallVector Idx(CE->op_begin() + 1, CE->op_end()); addUInt(*Loc, dwarf::DW_FORM_udata, - Asm->getDataLayout().getIndexedOffset(Ptr->getType(), Idx)); + Asm->getDataLayout().getIndexedOffset(Ptr->getValueType(), Idx)); addUInt(*Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_plus); addBlock(*VariableDIE, dwarf::DW_AT_location, Loc); } Index: lib/CodeGen/SelectionDAG/FastISel.cpp =================================================================== --- lib/CodeGen/SelectionDAG/FastISel.cpp +++ lib/CodeGen/SelectionDAG/FastISel.cpp @@ -513,7 +513,11 @@ } Ty = StTy->getElementType(Field); } else { - Ty = cast(Ty)->getElementType(); + if (Ty->isPointerTy()) { + Ty = cast(I)->getSourceElementType(); + } else { + Ty = cast(Ty)->getElementType(); + } // If this is a constant subscript, handle it quickly. if (const auto *CI = dyn_cast(Idx)) { Index: lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp =================================================================== --- lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -3018,7 +3018,12 @@ Ty = StTy->getElementType(Field); } else { - Ty = cast(Ty)->getElementType(); + if (Ty->isPointerTy()) { + Ty = cast(&I)->getSourceElementType(); + } else { + Ty = cast(Ty)->getElementType(); + } + MVT PtrTy = DAG.getTargetLoweringInfo().getPointerTy(DAG.getDataLayout(), AS); unsigned PtrSize = PtrTy.getSizeInBits(); Index: lib/IR/ConstantFold.h =================================================================== --- lib/IR/ConstantFold.h +++ lib/IR/ConstantFold.h @@ -47,10 +47,6 @@ Constant *V2); Constant *ConstantFoldCompareInstruction(unsigned short predicate, Constant *C1, Constant *C2); - Constant *ConstantFoldGetElementPtr(Constant *C, bool inBounds, - ArrayRef Idxs); - Constant *ConstantFoldGetElementPtr(Constant *C, bool inBounds, - ArrayRef Idxs); Constant *ConstantFoldGetElementPtr(Type *Ty, Constant *C, bool inBounds, ArrayRef Idxs); Constant *ConstantFoldGetElementPtr(Type *Ty, Constant *C, bool inBounds, Index: lib/IR/ConstantFold.cpp =================================================================== --- lib/IR/ConstantFold.cpp +++ lib/IR/ConstantFold.cpp @@ -2040,9 +2040,8 @@ return C; if (isa(C)) { - PointerType *Ptr = cast(C->getType()); - Type *Ty = GetElementPtrInst::getIndexedType( - cast(Ptr->getScalarType())->getElementType(), Idxs); + PointerType *Ptr = cast(C->getType()->getScalarType()); + Type *Ty = GetElementPtrInst::getIndexedType(PointeeTy, Idxs); assert(Ty && "Invalid indices for GEP!"); return UndefValue::get(PointerType::get(Ty, Ptr->getAddressSpace())); } @@ -2055,9 +2054,8 @@ break; } if (isNull) { - PointerType *Ptr = cast(C->getType()); - Type *Ty = GetElementPtrInst::getIndexedType( - cast(Ptr->getScalarType())->getElementType(), Idxs); + PointerType *Ptr = cast(C->getType()->getScalarType()); + Type *Ty = GetElementPtrInst::getIndexedType(PointeeTy, Idxs); assert(Ty && "Invalid indices for GEP!"); return ConstantPointerNull::get(PointerType::get(Ty, Ptr->getAddressSpace())); @@ -2237,22 +2235,6 @@ return nullptr; } -Constant *llvm::ConstantFoldGetElementPtr(Constant *C, - bool inBounds, - ArrayRef Idxs) { - return ConstantFoldGetElementPtrImpl( - cast(C->getType()->getScalarType())->getElementType(), C, - inBounds, Idxs); -} - -Constant *llvm::ConstantFoldGetElementPtr(Constant *C, - bool inBounds, - ArrayRef Idxs) { - return ConstantFoldGetElementPtrImpl( - cast(C->getType()->getScalarType())->getElementType(), C, - inBounds, Idxs); -} - Constant *llvm::ConstantFoldGetElementPtr(Type *Ty, Constant *C, bool inBounds, ArrayRef Idxs) { Index: lib/IR/Constants.cpp =================================================================== --- lib/IR/Constants.cpp +++ lib/IR/Constants.cpp @@ -2330,12 +2330,13 @@ } GetElementPtrConstantExpr::GetElementPtrConstantExpr( - Type *SrcElementTy, Constant *C, ArrayRef IdxList, Type *DestTy) + Type *SrcElementTy, Type *ResElementTy, + Constant *C, ArrayRef IdxList, Type *DestTy) : ConstantExpr(DestTy, Instruction::GetElementPtr, OperandTraits::op_end(this) - (IdxList.size() + 1), IdxList.size() + 1), - SrcElementTy(SrcElementTy) { + SrcElementTy(SrcElementTy), ResElementTy(ResElementTy) { Op<0>() = C; Use *OperandList = getOperandList(); for (unsigned i = 0, E = IdxList.size(); i != E; ++i) @@ -2346,6 +2347,10 @@ return SrcElementTy; } +Type *GetElementPtrConstantExpr::getResultElementType() const { + return ResElementTy; +} + //===----------------------------------------------------------------------===// // ConstantData* implementations Index: lib/IR/ConstantsContext.h =================================================================== --- lib/IR/ConstantsContext.h +++ lib/IR/ConstantsContext.h @@ -225,28 +225,25 @@ /// used behind the scenes to implement getelementpr constant exprs. class GetElementPtrConstantExpr : public ConstantExpr { Type *SrcElementTy; + Type *ResElementTy; void anchor() override; - GetElementPtrConstantExpr(Type *SrcElementTy, Constant *C, - ArrayRef IdxList, Type *DestTy); + GetElementPtrConstantExpr(Type *SrcElementTy, Type *ResElementTy, + Constant *C, ArrayRef IdxList, + Type *DestTy); public: - static GetElementPtrConstantExpr *Create(Constant *C, - ArrayRef IdxList, - Type *DestTy, - unsigned Flags) { - return Create( - cast(C->getType()->getScalarType())->getElementType(), C, - IdxList, DestTy, Flags); - } - static GetElementPtrConstantExpr *Create(Type *SrcElementTy, Constant *C, + static GetElementPtrConstantExpr *Create(Type *SrcElementTy, + Type *ResElementTy, Constant *C, ArrayRef IdxList, Type *DestTy, unsigned Flags) { GetElementPtrConstantExpr *Result = new (IdxList.size() + 1) - GetElementPtrConstantExpr(SrcElementTy, C, IdxList, DestTy); + GetElementPtrConstantExpr(SrcElementTy, ResElementTy, + C, IdxList, DestTy); Result->SubclassOptionalData = Flags; return Result; } Type *getSourceElementType() const; + Type *getResultElementType() const; /// Transparently provide more efficient getOperand methods. DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); @@ -535,6 +532,7 @@ ExplicitTy ? ExplicitTy : cast(Ops[0]->getType()->getScalarType()) ->getElementType(), + cast(Ty->getScalarType())->getPointerElementType(), Ops[0], Ops.slice(1), Ty, SubclassOptionalData); case Instruction::ICmp: return new CompareConstantExpr(Ty, Instruction::ICmp, SubclassData, Index: lib/IR/DataLayout.cpp =================================================================== --- lib/IR/DataLayout.cpp +++ lib/IR/DataLayout.cpp @@ -723,36 +723,33 @@ return Max != LegalIntWidths.end() ? *Max : 0; } -uint64_t DataLayout::getIndexedOffset(Type *ptrTy, +uint64_t DataLayout::getIndexedOffset(Type *ElemTy, ArrayRef Indices) const { - Type *Ty = ptrTy; - assert(Ty->isPointerTy() && "Illegal argument for getIndexedOffset()"); uint64_t Result = 0; + // We can use 0 as the address space as we don't need + // to get pointer types back from gep_type_iterator. + unsigned AS = 0; generic_gep_type_iterator - TI = gep_type_begin(ptrTy, Indices); - for (unsigned CurIDX = 0, EndIDX = Indices.size(); CurIDX != EndIDX; - ++CurIDX, ++TI) { - if (StructType *STy = dyn_cast(*TI)) { - assert(Indices[CurIDX]->getType() == - Type::getInt32Ty(ptrTy->getContext()) && + GTI = gep_type_begin(ElemTy, AS, Indices), + GTE = gep_type_end(ElemTy, AS, Indices); + for (; GTI != GTE; ++GTI) { + Value *Idx = GTI.getOperand(); + if (StructType *STy = dyn_cast(*GTI)) { + assert(Idx->getType() == + Type::getInt32Ty(ElemTy->getContext()) && "Illegal struct idx"); - unsigned FieldNo = cast(Indices[CurIDX])->getZExtValue(); + unsigned FieldNo = cast(Idx)->getZExtValue(); // Get structure layout information... const StructLayout *Layout = getStructLayout(STy); // Add in the offset, as calculated by the structure layout info... Result += Layout->getElementOffset(FieldNo); - - // Update Ty to refer to current element - Ty = STy->getElementType(FieldNo); } else { - // Update Ty to refer to current element - Ty = cast(Ty)->getElementType(); - + Type *Ty = GTI.getIndexedType(); // Get the array index and the size of each array element. - if (int64_t arrayIdx = cast(Indices[CurIDX])->getSExtValue()) + if (int64_t arrayIdx = cast(Idx)->getSExtValue()) Result += (uint64_t)arrayIdx * getTypeAllocSize(Ty); } } Index: lib/IR/Operator.cpp =================================================================== --- lib/IR/Operator.cpp +++ lib/IR/Operator.cpp @@ -12,6 +12,12 @@ return cast(this)->getSourceElementType(); } +Type *GEPOperator::getResultElementType() const { + if (auto *I = dyn_cast(this)) + return I->getResultElementType(); + return cast(this)->getResultElementType(); +} + bool GEPOperator::accumulateConstantOffset(const DataLayout &DL, APInt &Offset) const { assert(Offset.getBitWidth() == Index: lib/Target/AArch64/AArch64FastISel.cpp =================================================================== --- lib/Target/AArch64/AArch64FastISel.cpp +++ lib/Target/AArch64/AArch64FastISel.cpp @@ -4825,7 +4825,11 @@ TotalOffs += DL.getStructLayout(StTy)->getElementOffset(Field); Ty = StTy->getElementType(Field); } else { - Ty = cast(Ty)->getElementType(); + if (Ty->isPointerTy()) { + Ty = cast(I)->getSourceElementType(); + } else { + Ty = cast(Ty)->getElementType(); + } // If this is a constant subscript, handle it quickly. if (const auto *CI = dyn_cast(Idx)) { if (CI->isZero()) Index: lib/Transforms/IPO/GlobalOpt.cpp =================================================================== --- lib/Transforms/IPO/GlobalOpt.cpp +++ lib/Transforms/IPO/GlobalOpt.cpp @@ -329,7 +329,7 @@ // we already know what the result of any load from that GEP is. // TODO: Handle splats. if (Init && isa(Init) && GEP->isInBounds()) - SubInit = Constant::getNullValue(GEP->getType()->getElementType()); + SubInit = Constant::getNullValue(GEP->getResultElementType()); } Changed |= CleanupConstantGlobalUsers(GEP, SubInit, DL, TLI); Index: lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp =================================================================== --- lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp +++ lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp @@ -694,10 +694,8 @@ return false; SmallVector Ops(GEPI->idx_begin(), GEPI->idx_begin() + Idx); - Type *AllocTy = GetElementPtrInst::getIndexedType( - cast(GEPI->getOperand(0)->getType()->getScalarType()) - ->getElementType(), - Ops); + Type *AllocTy = + GetElementPtrInst::getIndexedType(GEPI->getSourceElementType(), Ops); if (!AllocTy || !AllocTy->isSized()) return false; const DataLayout &DL = IC.getDataLayout(); Index: lib/Transforms/InstCombine/InstructionCombining.cpp =================================================================== --- lib/Transforms/InstCombine/InstructionCombining.cpp +++ lib/Transforms/InstCombine/InstructionCombining.cpp @@ -1334,7 +1334,7 @@ Instruction *InstCombiner::visitGetElementPtrInst(GetElementPtrInst &GEP) { SmallVector Ops(GEP.op_begin(), GEP.op_end()); - if (Value *V = SimplifyGEPInst(Ops, DL, TLI, DT, AC)) + if (Value *V = SimplifyGEPInst(GEP.getSourceElementType(), Ops, DL, TLI, DT, AC)) return ReplaceInstUsesWith(GEP, V); Value *PtrOp = GEP.getOperand(0); @@ -1349,19 +1349,18 @@ for (User::op_iterator I = GEP.op_begin() + 1, E = GEP.op_end(); I != E; ++I, ++GTI) { // Skip indices into struct types. - SequentialType *SeqTy = dyn_cast(*GTI); - if (!SeqTy) + if (isa(*GTI)) continue; // Index type should have the same width as IntPtr Type *IndexTy = (*I)->getType(); Type *NewIndexType = IndexTy->isVectorTy() ? VectorType::get(IntPtrTy, IndexTy->getVectorNumElements()) : IntPtrTy; - + // If the element type has zero size then any index over it is equivalent // to an index of zero, so replace it with zero if it is not zero already. - if (SeqTy->getElementType()->isSized() && - DL.getTypeAllocSize(SeqTy->getElementType()) == 0) + Type *EltTy = GTI.getIndexedType(); + if (EltTy->isSized() && DL.getTypeAllocSize(EltTy) == 0) if (!isa(*I) || !cast(*I)->isNullValue()) { *I = Constant::getNullValue(NewIndexType); MadeChange = true; @@ -1405,7 +1404,7 @@ return nullptr; // Keep track of the type as we walk the GEP. - Type *CurTy = Op1->getOperand(0)->getType()->getScalarType(); + Type *CurTy = nullptr; for (unsigned J = 0, F = Op1->getNumOperands(); J != F; ++J) { if (Op1->getOperand(J)->getType() != Op2->getOperand(J)->getType()) @@ -1419,7 +1418,7 @@ // The first two arguments can vary for any GEP, the rest have to be // static for struct slots - if (J > 1 && CurTy->isStructTy()) + if (J > 1 && CurTy && CurTy->isStructTy()) return nullptr; DI = J; @@ -1436,7 +1435,9 @@ // Sink down a layer of the type for the next iteration. if (J > 0) { - if (CompositeType *CT = dyn_cast(CurTy)) { + if (J == 1) { + CurTy = Op1->getSourceElementType(); + } else if (CompositeType *CT = dyn_cast(CurTy)) { CurTy = CT->getTypeAtIndex(Op1->getOperand(J)); } else { CurTy = nullptr; @@ -1565,8 +1566,7 @@ unsigned AS = GEP.getPointerAddressSpace(); if (GEP.getOperand(1)->getType()->getScalarSizeInBits() == DL.getPointerSizeInBits(AS)) { - Type *PtrTy = GEP.getPointerOperandType(); - Type *Ty = PtrTy->getPointerElementType(); + Type *Ty = GEP.getSourceElementType(); uint64_t TyAllocSize = DL.getTypeAllocSize(Ty); bool Matched = false; @@ -1629,9 +1629,8 @@ // // This occurs when the program declares an array extern like "int X[];" if (HasZeroPointerIndex) { - PointerType *CPTy = cast(PtrOp->getType()); if (ArrayType *CATy = - dyn_cast(CPTy->getElementType())) { + dyn_cast(GEP.getSourceElementType())) { // GEP (bitcast i8* X to [0 x i8]*), i32 0, ... ? if (CATy->getElementType() == StrippedPtrTy->getElementType()) { // -> GEP i8* X, ... @@ -1688,7 +1687,7 @@ // %t = getelementptr i32* bitcast ([2 x i32]* %str to i32*), i32 %V // into: %t1 = getelementptr [2 x i32]* %str, i32 0, i32 %V; bitcast Type *SrcElTy = StrippedPtrTy->getElementType(); - Type *ResElTy = PtrOp->getType()->getPointerElementType(); + Type *ResElTy = GEP.getSourceElementType(); if (SrcElTy->isArrayTy() && DL.getTypeAllocSize(SrcElTy->getArrayElementType()) == DL.getTypeAllocSize(ResElTy)) { Index: lib/Transforms/Scalar/NaryReassociate.cpp =================================================================== --- lib/Transforms/Scalar/NaryReassociate.cpp +++ lib/Transforms/Scalar/NaryReassociate.cpp @@ -335,7 +335,7 @@ } unsigned AddrSpace = GEP->getPointerAddressSpace(); - return TTI->isLegalAddressingMode(GEP->getType()->getElementType(), BaseGV, + return TTI->isLegalAddressingMode(GEP->getResultElementType(), BaseGV, BaseOffset, HasBaseReg, Scale, AddrSpace); } @@ -434,7 +434,7 @@ // NewGEP = (char *)Candidate + RHS * sizeof(IndexedType) uint64_t IndexedSize = DL->getTypeAllocSize(IndexedType); - Type *ElementType = GEP->getType()->getElementType(); + Type *ElementType = GEP->getResultElementType(); uint64_t ElementSize = DL->getTypeAllocSize(ElementType); // Another less rare case: because I is not necessarily the last index of the // GEP, the size of the type at the I-th index (IndexedSize) is not Index: lib/Transforms/Scalar/RewriteStatepointsForGC.cpp =================================================================== --- lib/Transforms/Scalar/RewriteStatepointsForGC.cpp +++ lib/Transforms/Scalar/RewriteStatepointsForGC.cpp @@ -2109,7 +2109,7 @@ } else if (GetElementPtrInst *GEP = dyn_cast(Instr)) { // Cost of the address calculation - Type *ValTy = GEP->getPointerOperandType()->getPointerElementType(); + Type *ValTy = GEP->getSourceElementType(); Cost += TTI.getAddressComputationCost(ValTy); // And cost of the GEP itself Index: lib/Transforms/Scalar/ScalarReplAggregates.cpp =================================================================== --- lib/Transforms/Scalar/ScalarReplAggregates.cpp +++ lib/Transforms/Scalar/ScalarReplAggregates.cpp @@ -510,15 +510,11 @@ if (GetElementPtrInst *GEP = dyn_cast(UI)) { // If this is a GEP with a variable indices, we can't handle it. - PointerType* PtrTy = dyn_cast(GEP->getPointerOperandType()); - if (!PtrTy) - return false; - // Compute the offset that this GEP adds to the pointer. SmallVector Indices(GEP->op_begin()+1, GEP->op_end()); Value *GEPNonConstantIdx = nullptr; if (!GEP->hasAllConstantIndices()) { - if (!isa(PtrTy->getElementType())) + if (!isa(GEP->getSourceElementType())) return false; if (NonConstantIdx) return false; @@ -528,7 +524,7 @@ HadDynamicAccess = true; } else GEPNonConstantIdx = NonConstantIdx; - uint64_t GEPOffset = DL.getIndexedOffset(PtrTy, + uint64_t GEPOffset = DL.getIndexedOffset(GEP->getSourceElementType(), Indices); // See if all uses can be converted. if (!CanConvertToScalar(GEP, Offset+GEPOffset, GEPNonConstantIdx)) @@ -623,7 +619,7 @@ GEPNonConstantIdx = Indices.pop_back_val(); } else GEPNonConstantIdx = NonConstantIdx; - uint64_t GEPOffset = DL.getIndexedOffset(GEP->getPointerOperandType(), + uint64_t GEPOffset = DL.getIndexedOffset(GEP->getSourceElementType(), Indices); ConvertUsesToScalar(GEP, NewAI, Offset+GEPOffset*8, GEPNonConstantIdx); GEP->eraseFromParent(); @@ -1749,7 +1745,7 @@ Indices.pop_back(); const DataLayout &DL = GEPI->getModule()->getDataLayout(); - Offset += DL.getIndexedOffset(GEPI->getPointerOperandType(), Indices); + Offset += DL.getIndexedOffset(GEPI->getSourceElementType(), Indices); if (!TypeHasComponent(Info.AI->getAllocatedType(), Offset, NonConstantIdxSize, DL)) MarkUnsafe(Info, GEPI); @@ -2065,7 +2061,7 @@ Value* NonConstantIdx = nullptr; if (!GEPI->hasAllConstantIndices()) NonConstantIdx = Indices.pop_back_val(); - Offset += DL.getIndexedOffset(GEPI->getPointerOperandType(), Indices); + Offset += DL.getIndexedOffset(GEPI->getSourceElementType(), Indices); RewriteForScalarRepl(GEPI, AI, Offset, NewElts); Index: lib/Transforms/Scalar/SeparateConstOffsetFromGEP.cpp =================================================================== --- lib/Transforms/Scalar/SeparateConstOffsetFromGEP.cpp +++ lib/Transforms/Scalar/SeparateConstOffsetFromGEP.cpp @@ -911,7 +911,7 @@ getAnalysis().getTTI( *GEP->getParent()->getParent()); unsigned AddrSpace = GEP->getPointerAddressSpace(); - if (!TTI.isLegalAddressingMode(GEP->getType()->getElementType(), + if (!TTI.isLegalAddressingMode(GEP->getResultElementType(), /*BaseGV=*/nullptr, AccumulativeByteOffset, /*HasBaseReg=*/true, /*Scale=*/0, AddrSpace)) { @@ -1018,7 +1018,7 @@ // unsigned.. Therefore, we cast ElementTypeSizeOfGEP to signed because it is // used with unsigned integers later. int64_t ElementTypeSizeOfGEP = static_cast( - DL->getTypeAllocSize(GEP->getType()->getElementType())); + DL->getTypeAllocSize(GEP->getResultElementType())); Type *IntPtrTy = DL->getIntPtrType(GEP->getType()); if (AccumulativeByteOffset % ElementTypeSizeOfGEP == 0) { // Very likely. As long as %gep is natually aligned, the byte offset we Index: lib/Transforms/Scalar/StraightLineStrengthReduce.cpp =================================================================== --- lib/Transforms/Scalar/StraightLineStrengthReduce.cpp +++ lib/Transforms/Scalar/StraightLineStrengthReduce.cpp @@ -270,7 +270,7 @@ } unsigned AddrSpace = GEP->getPointerAddressSpace(); - return TTI->isLegalAddressingMode(GEP->getType()->getElementType(), BaseGV, + return TTI->isLegalAddressingMode(GEP->getResultElementType(), BaseGV, BaseOffset, HasBaseReg, Scale, AddrSpace); } @@ -566,8 +566,7 @@ if (Basis.CandidateKind == Candidate::GEP) { APInt ElementSize( IndexOffset.getBitWidth(), - DL->getTypeAllocSize( - cast(Basis.Ins)->getType()->getElementType())); + DL->getTypeAllocSize(cast(Basis.Ins)->getResultElementType())); APInt Q, R; APInt::sdivrem(IndexOffset, ElementSize, Q, R); if (R.getSExtValue() == 0) 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