diff options
Diffstat (limited to 'contrib/llvm-project/llvm/lib/Analysis/InstructionSimplify.cpp')
-rw-r--r-- | contrib/llvm-project/llvm/lib/Analysis/InstructionSimplify.cpp | 283 |
1 files changed, 155 insertions, 128 deletions
diff --git a/contrib/llvm-project/llvm/lib/Analysis/InstructionSimplify.cpp b/contrib/llvm-project/llvm/lib/Analysis/InstructionSimplify.cpp index 69ab0052b0a7..864eeea4f8bf 100644 --- a/contrib/llvm-project/llvm/lib/Analysis/InstructionSimplify.cpp +++ b/contrib/llvm-project/llvm/lib/Analysis/InstructionSimplify.cpp @@ -70,8 +70,8 @@ static Value *SimplifyOrInst(Value *, Value *, const SimplifyQuery &, unsigned); static Value *SimplifyXorInst(Value *, Value *, const SimplifyQuery &, unsigned); static Value *SimplifyCastInst(unsigned, Value *, Type *, const SimplifyQuery &, unsigned); -static Value *SimplifyGEPInst(Type *, ArrayRef<Value *>, const SimplifyQuery &, - unsigned); +static Value *SimplifyGEPInst(Type *, ArrayRef<Value *>, bool, + const SimplifyQuery &, unsigned); static Value *SimplifySelectInst(Value *, Value *, Value *, const SimplifyQuery &, unsigned); @@ -698,13 +698,12 @@ static Constant *stripAndComputeConstantOffsets(const DataLayout &DL, Value *&V, bool AllowNonInbounds = false) { assert(V->getType()->isPtrOrPtrVectorTy()); - Type *IntIdxTy = DL.getIndexType(V->getType())->getScalarType(); - APInt Offset = APInt::getNullValue(IntIdxTy->getIntegerBitWidth()); + APInt Offset = APInt::getZero(DL.getIndexTypeSizeInBits(V->getType())); V = V->stripAndAccumulateConstantOffsets(DL, Offset, AllowNonInbounds); // As that strip may trace through `addrspacecast`, need to sext or trunc // the offset calculated. - IntIdxTy = DL.getIndexType(V->getType())->getScalarType(); + Type *IntIdxTy = DL.getIndexType(V->getType())->getScalarType(); Offset = Offset.sextOrTrunc(IntIdxTy->getIntegerBitWidth()); Constant *OffsetIntPtr = ConstantInt::get(IntIdxTy, Offset); @@ -1407,8 +1406,7 @@ static Value *SimplifyLShrInst(Value *Op0, Value *Op1, bool isExact, match(Op0, m_c_Or(m_NUWShl(m_Value(X), m_APInt(ShLAmt)), m_Value(Y))) && *ShRAmt == *ShLAmt) { const KnownBits YKnown = computeKnownBits(Y, Q.DL, 0, Q.AC, Q.CxtI, Q.DT); - const unsigned Width = Op0->getType()->getScalarSizeInBits(); - const unsigned EffWidthY = Width - YKnown.countMinLeadingZeros(); + const unsigned EffWidthY = YKnown.countMaxActiveBits(); if (ShRAmt->uge(EffWidthY)) return X; } @@ -1429,9 +1427,11 @@ static Value *SimplifyAShrInst(Value *Op0, Value *Op1, bool isExact, MaxRecurse)) return V; - // all ones >>a X -> -1 + // -1 >>a X --> -1 + // (-1 << X) a>> X --> -1 // Do not return Op0 because it may contain undef elements if it's a vector. - if (match(Op0, m_AllOnes())) + if (match(Op0, m_AllOnes()) || + match(Op0, m_Shl(m_AllOnes(), m_Specific(Op1)))) return Constant::getAllOnesValue(Op0->getType()); // (X << A) >> A -> X @@ -1765,7 +1765,7 @@ static Value *simplifyAndOrOfICmpsWithLimitConst(ICmpInst *Cmp0, ICmpInst *Cmp1, if (match(Cmp0->getOperand(1), m_APInt(C))) MinMaxC = HasNotOp ? ~*C : *C; else if (isa<ConstantPointerNull>(Cmp0->getOperand(1))) - MinMaxC = APInt::getNullValue(8); + MinMaxC = APInt::getZero(8); else return nullptr; @@ -2040,24 +2040,32 @@ static Value *SimplifyAndInst(Value *Op0, Value *Op1, const SimplifyQuery &Q, if (match(Op1, m_c_Or(m_Specific(Op0), m_Value()))) return Op0; + // (X | Y) & (X | ~Y) --> X (commuted 8 ways) + Value *X, *Y; + if (match(Op0, m_c_Or(m_Value(X), m_Not(m_Value(Y)))) && + match(Op1, m_c_Or(m_Deferred(X), m_Deferred(Y)))) + return X; + if (match(Op1, m_c_Or(m_Value(X), m_Not(m_Value(Y)))) && + match(Op0, m_c_Or(m_Deferred(X), m_Deferred(Y)))) + return X; + if (Value *V = simplifyLogicOfAddSub(Op0, Op1, Instruction::And)) return V; // A mask that only clears known zeros of a shifted value is a no-op. - Value *X; const APInt *Mask; const APInt *ShAmt; if (match(Op1, m_APInt(Mask))) { // If all bits in the inverted and shifted mask are clear: // and (shl X, ShAmt), Mask --> shl X, ShAmt if (match(Op0, m_Shl(m_Value(X), m_APInt(ShAmt))) && - (~(*Mask)).lshr(*ShAmt).isNullValue()) + (~(*Mask)).lshr(*ShAmt).isZero()) return Op0; // If all bits in the inverted and shifted mask are clear: // and (lshr X, ShAmt), Mask --> lshr X, ShAmt if (match(Op0, m_LShr(m_Value(X), m_APInt(ShAmt))) && - (~(*Mask)).shl(*ShAmt).isNullValue()) + (~(*Mask)).shl(*ShAmt).isZero()) return Op0; } @@ -2141,7 +2149,7 @@ static Value *SimplifyAndInst(Value *Op0, Value *Op1, const SimplifyQuery &Q, // if Mask = ((1 << effective_width_of(X)) - 1) << A // SimplifyDemandedBits in InstCombine can optimize the general case. // This pattern aims to help other passes for a common case. - Value *Y, *XShifted; + Value *XShifted; if (match(Op1, m_APInt(Mask)) && match(Op0, m_c_Or(m_CombineAnd(m_NUWShl(m_Value(X), m_APInt(ShAmt)), m_Value(XShifted)), @@ -2149,11 +2157,11 @@ static Value *SimplifyAndInst(Value *Op0, Value *Op1, const SimplifyQuery &Q, const unsigned Width = Op0->getType()->getScalarSizeInBits(); const unsigned ShftCnt = ShAmt->getLimitedValue(Width); const KnownBits YKnown = computeKnownBits(Y, Q.DL, 0, Q.AC, Q.CxtI, Q.DT); - const unsigned EffWidthY = Width - YKnown.countMinLeadingZeros(); + const unsigned EffWidthY = YKnown.countMaxActiveBits(); if (EffWidthY <= ShftCnt) { const KnownBits XKnown = computeKnownBits(X, Q.DL, 0, Q.AC, Q.CxtI, Q.DT); - const unsigned EffWidthX = Width - XKnown.countMinLeadingZeros(); + const unsigned EffWidthX = XKnown.countMaxActiveBits(); const APInt EffBitsY = APInt::getLowBitsSet(Width, EffWidthY); const APInt EffBitsX = APInt::getLowBitsSet(Width, EffWidthX) << ShftCnt; // If the mask is extracting all bits from X or Y as is, we can skip @@ -2257,6 +2265,19 @@ static Value *SimplifyOrInst(Value *Op0, Value *Op1, const SimplifyQuery &Q, match(Op0, m_c_Xor(m_Not(m_Specific(A)), m_Specific(B))))) return Op0; + // (A | B) | (A ^ B) --> A | B + // (B | A) | (A ^ B) --> B | A + if (match(Op1, m_Xor(m_Value(A), m_Value(B))) && + match(Op0, m_c_Or(m_Specific(A), m_Specific(B)))) + return Op0; + + // Commute the outer 'or' operands. + // (A ^ B) | (A | B) --> A | B + // (A ^ B) | (B | A) --> B | A + if (match(Op0, m_Xor(m_Value(A), m_Value(B))) && + match(Op1, m_c_Or(m_Specific(A), m_Specific(B)))) + return Op1; + // (~A & B) | ~(A | B) --> ~A // (~A & B) | ~(B | A) --> ~A // (B & ~A) | ~(A | B) --> ~A @@ -2276,6 +2297,23 @@ static Value *SimplifyOrInst(Value *Op0, Value *Op1, const SimplifyQuery &Q, match(Op0, m_Not(m_c_Or(m_Specific(A), m_Specific(B))))) return NotA; + // Rotated -1 is still -1: + // (-1 << X) | (-1 >> (C - X)) --> -1 + // (-1 >> X) | (-1 << (C - X)) --> -1 + // ...with C <= bitwidth (and commuted variants). + Value *X, *Y; + if ((match(Op0, m_Shl(m_AllOnes(), m_Value(X))) && + match(Op1, m_LShr(m_AllOnes(), m_Value(Y)))) || + (match(Op1, m_Shl(m_AllOnes(), m_Value(X))) && + match(Op0, m_LShr(m_AllOnes(), m_Value(Y))))) { + const APInt *C; + if ((match(X, m_Sub(m_APInt(C), m_Specific(Y))) || + match(Y, m_Sub(m_APInt(C), m_Specific(X)))) && + C->ule(X->getType()->getScalarSizeInBits())) { + return ConstantInt::getAllOnesValue(X->getType()); + } + } + if (Value *V = simplifyAndOrOfCmps(Q, Op0, Op1, false)) return V; @@ -3090,7 +3128,7 @@ static Value *simplifyICmpWithBinOp(CmpInst::Predicate Pred, Value *LHS, // - C isn't zero. if (Q.IIQ.hasNoSignedWrap(cast<OverflowingBinaryOperator>(LBO)) || Q.IIQ.hasNoUnsignedWrap(cast<OverflowingBinaryOperator>(LBO)) || - match(LHS, m_Shl(m_One(), m_Value())) || !C->isNullValue()) { + match(LHS, m_Shl(m_One(), m_Value())) || !C->isZero()) { if (Pred == ICmpInst::ICMP_EQ) return ConstantInt::getFalse(GetCompareTy(RHS)); if (Pred == ICmpInst::ICMP_NE) @@ -3640,30 +3678,6 @@ static Value *SimplifyICmpInst(unsigned Predicate, Value *LHS, Value *RHS, CRHS->getPointerOperand(), Q)) return C; - if (GetElementPtrInst *GLHS = dyn_cast<GetElementPtrInst>(LHS)) { - if (GEPOperator *GRHS = dyn_cast<GEPOperator>(RHS)) { - if (GLHS->getPointerOperand() == GRHS->getPointerOperand() && - GLHS->hasAllConstantIndices() && GRHS->hasAllConstantIndices() && - (ICmpInst::isEquality(Pred) || - (GLHS->isInBounds() && GRHS->isInBounds() && - Pred == ICmpInst::getSignedPredicate(Pred)))) { - // The bases are equal and the indices are constant. Build a constant - // expression GEP with the same indices and a null base pointer to see - // what constant folding can make out of it. - Constant *Null = Constant::getNullValue(GLHS->getPointerOperandType()); - SmallVector<Value *, 4> IndicesLHS(GLHS->indices()); - Constant *NewLHS = ConstantExpr::getGetElementPtr( - GLHS->getSourceElementType(), Null, IndicesLHS); - - SmallVector<Value *, 4> IndicesRHS(GRHS->idx_begin(), GRHS->idx_end()); - Constant *NewRHS = ConstantExpr::getGetElementPtr( - GLHS->getSourceElementType(), Null, IndicesRHS); - Constant *NewICmp = ConstantExpr::getICmp(Pred, NewLHS, NewRHS); - return ConstantFoldConstant(NewICmp, Q.DL); - } - } - } - // If the comparison is with the result of a select instruction, check whether // comparing with either branch of the select always yields the same value. if (isa<SelectInst>(LHS) || isa<SelectInst>(RHS)) @@ -3966,7 +3980,8 @@ static Value *simplifyWithOpReplaced(Value *V, Value *Op, Value *RepOp, if (auto *GEP = dyn_cast<GetElementPtrInst>(I)) return PreventSelfSimplify(SimplifyGEPInst(GEP->getSourceElementType(), - NewOps, Q, MaxRecurse - 1)); + NewOps, GEP->isInBounds(), Q, + MaxRecurse - 1)); if (isa<SelectInst>(I)) return PreventSelfSimplify( @@ -4226,14 +4241,27 @@ static Value *SimplifySelectInst(Value *Cond, Value *TrueVal, Value *FalseVal, return FalseVal; } - // select i1 Cond, i1 true, i1 false --> i1 Cond assert(Cond->getType()->isIntOrIntVectorTy(1) && "Select must have bool or bool vector condition"); assert(TrueVal->getType() == FalseVal->getType() && "Select must have same types for true/false ops"); - if (Cond->getType() == TrueVal->getType() && - match(TrueVal, m_One()) && match(FalseVal, m_ZeroInt())) - return Cond; + + if (Cond->getType() == TrueVal->getType()) { + // select i1 Cond, i1 true, i1 false --> i1 Cond + if (match(TrueVal, m_One()) && match(FalseVal, m_ZeroInt())) + return Cond; + + // (X || Y) && (X || !Y) --> X (commuted 8 ways) + Value *X, *Y; + if (match(FalseVal, m_ZeroInt())) { + if (match(Cond, m_c_LogicalOr(m_Value(X), m_Not(m_Value(Y)))) && + match(TrueVal, m_c_LogicalOr(m_Specific(X), m_Specific(Y)))) + return X; + if (match(TrueVal, m_c_LogicalOr(m_Value(X), m_Not(m_Value(Y)))) && + match(Cond, m_c_LogicalOr(m_Specific(X), m_Specific(Y)))) + return X; + } + } // select ?, X, X -> X if (TrueVal == FalseVal) @@ -4311,7 +4339,7 @@ Value *llvm::SimplifySelectInst(Value *Cond, Value *TrueVal, Value *FalseVal, /// Given operands for an GetElementPtrInst, see if we can fold the result. /// If not, this returns null. -static Value *SimplifyGEPInst(Type *SrcTy, ArrayRef<Value *> Ops, +static Value *SimplifyGEPInst(Type *SrcTy, ArrayRef<Value *> Ops, bool InBounds, const SimplifyQuery &Q, unsigned) { // The type of the GEP pointer operand. unsigned AS = @@ -4412,14 +4440,14 @@ static Value *SimplifyGEPInst(Type *SrcTy, ArrayRef<Value *> Ops, // gep (gep V, C), (sub 0, V) -> C if (match(Ops.back(), m_Sub(m_Zero(), m_PtrToInt(m_Specific(StrippedBasePtr)))) && - !BasePtrOffset.isNullValue()) { + !BasePtrOffset.isZero()) { auto *CI = ConstantInt::get(GEPTy->getContext(), BasePtrOffset); return ConstantExpr::getIntToPtr(CI, GEPTy); } // gep (gep V, C), (xor V, -1) -> C-1 if (match(Ops.back(), m_Xor(m_PtrToInt(m_Specific(StrippedBasePtr)), m_AllOnes())) && - !BasePtrOffset.isOneValue()) { + !BasePtrOffset.isOne()) { auto *CI = ConstantInt::get(GEPTy->getContext(), BasePtrOffset - 1); return ConstantExpr::getIntToPtr(CI, GEPTy); } @@ -4431,13 +4459,13 @@ static Value *SimplifyGEPInst(Type *SrcTy, ArrayRef<Value *> Ops, return nullptr; auto *CE = ConstantExpr::getGetElementPtr(SrcTy, cast<Constant>(Ops[0]), - Ops.slice(1)); + Ops.slice(1), InBounds); return ConstantFoldConstant(CE, Q.DL); } -Value *llvm::SimplifyGEPInst(Type *SrcTy, ArrayRef<Value *> Ops, +Value *llvm::SimplifyGEPInst(Type *SrcTy, ArrayRef<Value *> Ops, bool InBounds, const SimplifyQuery &Q) { - return ::SimplifyGEPInst(SrcTy, Ops, Q, RecursionLimit); + return ::SimplifyGEPInst(SrcTy, Ops, InBounds, Q, RecursionLimit); } /// Given operands for an InsertValueInst, see if we can fold the result. @@ -4907,6 +4935,11 @@ static Constant *simplifyFPOp(ArrayRef<Value *> Ops, FastMathFlags FMF, return nullptr; } +// TODO: Move this out to a header file: +static inline bool canIgnoreSNaN(fp::ExceptionBehavior EB, FastMathFlags FMF) { + return (EB == fp::ebIgnore || FMF.noNaNs()); +} + /// Given operands for an FAdd, see if we can fold the result. If not, this /// returns null. static Value * @@ -4921,17 +4954,25 @@ SimplifyFAddInst(Value *Op0, Value *Op1, FastMathFlags FMF, if (Constant *C = simplifyFPOp({Op0, Op1}, FMF, Q, ExBehavior, Rounding)) return C; - if (!isDefaultFPEnvironment(ExBehavior, Rounding)) - return nullptr; - // fadd X, -0 ==> X - if (match(Op1, m_NegZeroFP())) - return Op0; + // With strict/constrained FP, we have these possible edge cases that do + // not simplify to Op0: + // fadd SNaN, -0.0 --> QNaN + // fadd +0.0, -0.0 --> -0.0 (but only with round toward negative) + if (canIgnoreSNaN(ExBehavior, FMF) && + (!canRoundingModeBe(Rounding, RoundingMode::TowardNegative) || + FMF.noSignedZeros())) + if (match(Op1, m_NegZeroFP())) + return Op0; // fadd X, 0 ==> X, when we know X is not -0 - if (match(Op1, m_PosZeroFP()) && - (FMF.noSignedZeros() || CannotBeNegativeZero(Op0, Q.TLI))) - return Op0; + if (canIgnoreSNaN(ExBehavior, FMF)) + if (match(Op1, m_PosZeroFP()) && + (FMF.noSignedZeros() || CannotBeNegativeZero(Op0, Q.TLI))) + return Op0; + + if (!isDefaultFPEnvironment(ExBehavior, Rounding)) + return nullptr; // With nnan: -X + X --> 0.0 (and commuted variant) // We don't have to explicitly exclude infinities (ninf): INF + -INF == NaN. @@ -5473,6 +5514,9 @@ static Value *simplifyUnaryIntrinsic(Function *F, Value *Op0, if (match(Op0, m_Intrinsic<Intrinsic::experimental_vector_reverse>(m_Value(X)))) return X; + // experimental.vector.reverse(splat(X)) -> splat(X) + if (isSplatValue(Op0)) + return Op0; break; default: break; @@ -5788,13 +5832,32 @@ static Value *simplifyBinaryIntrinsic(Function *F, Value *Op0, Value *Op1, static Value *simplifyIntrinsic(CallBase *Call, const SimplifyQuery &Q) { - // Intrinsics with no operands have some kind of side effect. Don't simplify. - unsigned NumOperands = Call->getNumArgOperands(); - if (!NumOperands) - return nullptr; - + unsigned NumOperands = Call->arg_size(); Function *F = cast<Function>(Call->getCalledFunction()); Intrinsic::ID IID = F->getIntrinsicID(); + + // Most of the intrinsics with no operands have some kind of side effect. + // Don't simplify. + if (!NumOperands) { + switch (IID) { + case Intrinsic::vscale: { + // Call may not be inserted into the IR yet at point of calling simplify. + if (!Call->getParent() || !Call->getParent()->getParent()) + return nullptr; + auto Attr = Call->getFunction()->getFnAttribute(Attribute::VScaleRange); + if (!Attr.isValid()) + return nullptr; + unsigned VScaleMin, VScaleMax; + std::tie(VScaleMin, VScaleMax) = Attr.getVScaleRangeArgs(); + if (VScaleMin == VScaleMax && VScaleMax != 0) + return ConstantInt::get(F->getReturnType(), VScaleMin); + return nullptr; + } + default: + return nullptr; + } + } + if (NumOperands == 1) return simplifyUnaryIntrinsic(F, Call->getArgOperand(0), Q); @@ -5830,9 +5893,18 @@ static Value *simplifyIntrinsic(CallBase *Call, const SimplifyQuery &Q) { if (match(ShAmtArg, m_APInt(ShAmtC))) { // If there's effectively no shift, return the 1st arg or 2nd arg. APInt BitWidth = APInt(ShAmtC->getBitWidth(), ShAmtC->getBitWidth()); - if (ShAmtC->urem(BitWidth).isNullValue()) + if (ShAmtC->urem(BitWidth).isZero()) return Call->getArgOperand(IID == Intrinsic::fshl ? 0 : 1); } + + // Rotating zero by anything is zero. + if (match(Op0, m_Zero()) && match(Op1, m_Zero())) + return ConstantInt::getNullValue(F->getReturnType()); + + // Rotating -1 by anything is -1. + if (match(Op0, m_AllOnes()) && match(Op1, m_AllOnes())) + return ConstantInt::getAllOnesValue(F->getReturnType()); + return nullptr; } case Intrinsic::experimental_constrained_fma: { @@ -5955,7 +6027,7 @@ static Value *tryConstantFoldCall(CallBase *Call, const SimplifyQuery &Q) { return nullptr; SmallVector<Constant *, 4> ConstantArgs; - unsigned NumArgs = Call->getNumArgOperands(); + unsigned NumArgs = Call->arg_size(); ConstantArgs.reserve(NumArgs); for (auto &Arg : Call->args()) { Constant *C = dyn_cast<Constant>(&Arg); @@ -6006,73 +6078,27 @@ Value *llvm::SimplifyFreezeInst(Value *Op0, const SimplifyQuery &Q) { return ::SimplifyFreezeInst(Op0, Q); } -static Constant *ConstructLoadOperandConstant(Value *Op) { - SmallVector<Value *, 4> Worklist; - // Invalid IR in unreachable code may contain self-referential values. Don't infinitely loop. - SmallPtrSet<Value *, 4> Visited; - Worklist.push_back(Op); - while (true) { - Value *CurOp = Worklist.back(); - if (!Visited.insert(CurOp).second) - return nullptr; - if (isa<Constant>(CurOp)) - break; - if (auto *BC = dyn_cast<BitCastOperator>(CurOp)) { - Worklist.push_back(BC->getOperand(0)); - } else if (auto *GEP = dyn_cast<GEPOperator>(CurOp)) { - for (unsigned I = 1; I != GEP->getNumOperands(); ++I) { - if (!isa<Constant>(GEP->getOperand(I))) - return nullptr; - } - Worklist.push_back(GEP->getOperand(0)); - } else if (auto *II = dyn_cast<IntrinsicInst>(CurOp)) { - if (II->isLaunderOrStripInvariantGroup()) - Worklist.push_back(II->getOperand(0)); - else - return nullptr; - } else { - return nullptr; - } - } - - Constant *NewOp = cast<Constant>(Worklist.pop_back_val()); - while (!Worklist.empty()) { - Value *CurOp = Worklist.pop_back_val(); - if (isa<BitCastOperator>(CurOp)) { - NewOp = ConstantExpr::getBitCast(NewOp, CurOp->getType()); - } else if (auto *GEP = dyn_cast<GEPOperator>(CurOp)) { - SmallVector<Constant *> Idxs; - Idxs.reserve(GEP->getNumOperands() - 1); - for (unsigned I = 1, E = GEP->getNumOperands(); I != E; ++I) { - Idxs.push_back(cast<Constant>(GEP->getOperand(I))); - } - NewOp = ConstantExpr::getGetElementPtr(GEP->getSourceElementType(), NewOp, - Idxs, GEP->isInBounds(), - GEP->getInRangeIndex()); - } else { - assert(isa<IntrinsicInst>(CurOp) && - cast<IntrinsicInst>(CurOp)->isLaunderOrStripInvariantGroup() && - "expected invariant group intrinsic"); - NewOp = ConstantExpr::getBitCast(NewOp, CurOp->getType()); - } - } - return NewOp; -} - static Value *SimplifyLoadInst(LoadInst *LI, Value *PtrOp, const SimplifyQuery &Q) { if (LI->isVolatile()) return nullptr; - // Try to make the load operand a constant, specifically handle - // invariant.group intrinsics. + APInt Offset(Q.DL.getIndexTypeSizeInBits(PtrOp->getType()), 0); auto *PtrOpC = dyn_cast<Constant>(PtrOp); - if (!PtrOpC) - PtrOpC = ConstructLoadOperandConstant(PtrOp); + // Try to convert operand into a constant by stripping offsets while looking + // through invariant.group intrinsics. Don't bother if the underlying object + // is not constant, as calculating GEP offsets is expensive. + if (!PtrOpC && isa<Constant>(getUnderlyingObject(PtrOp))) { + PtrOp = PtrOp->stripAndAccumulateConstantOffsets( + Q.DL, Offset, /* AllowNonInbounts */ true, + /* AllowInvariantGroup */ true); + // Index size may have changed due to address space casts. + Offset = Offset.sextOrTrunc(Q.DL.getIndexTypeSizeInBits(PtrOp->getType())); + PtrOpC = dyn_cast<Constant>(PtrOp); + } if (PtrOpC) - return ConstantFoldLoadFromConstPtr(PtrOpC, LI->getType(), Q.DL); - + return ConstantFoldLoadFromConstPtr(PtrOpC, LI->getType(), Offset, Q.DL); return nullptr; } @@ -6172,8 +6198,9 @@ static Value *simplifyInstructionWithOperands(Instruction *I, Result = SimplifySelectInst(NewOps[0], NewOps[1], NewOps[2], Q); break; case Instruction::GetElementPtr: { - Result = SimplifyGEPInst(cast<GetElementPtrInst>(I)->getSourceElementType(), - NewOps, Q); + auto *GEPI = cast<GetElementPtrInst>(I); + Result = SimplifyGEPInst(GEPI->getSourceElementType(), NewOps, + GEPI->isInBounds(), Q); break; } case Instruction::InsertValue: { |