aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/llvm/lib/Analysis/InstructionSimplify.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/llvm/lib/Analysis/InstructionSimplify.cpp')
-rw-r--r--contrib/llvm-project/llvm/lib/Analysis/InstructionSimplify.cpp283
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: {