Skip to content

Commit 1105b3c

Browse files
committed
[ValueTracking] Support GEPs in matchSimpleRecurrence.
1 parent de6a832 commit 1105b3c

File tree

3 files changed

+54
-24
lines changed

3 files changed

+54
-24
lines changed

llvm/include/llvm/Analysis/ValueTracking.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -961,7 +961,11 @@ LLVM_ABI bool matchSimpleRecurrence(const PHINode *P, BinaryOperator *&BO,
961961
Value *&Start, Value *&Step);
962962

963963
/// Analogous to the above, but starting from the binary operator
964-
LLVM_ABI bool matchSimpleRecurrence(const BinaryOperator *I, PHINode *&P,
964+
LLVM_ABI bool matchSimpleRecurrence(const Instruction *I, PHINode *&P,
965+
Value *&Start, Value *&Step);
966+
967+
/// Analogous to the above, but also supporting non-binary operators.
968+
LLVM_ABI bool matchSimpleRecurrence(const PHINode *P, Instruction *&BO,
965969
Value *&Start, Value *&Step);
966970

967971
/// Attempt to match a simple value-accumulating recurrence of the form:

llvm/lib/Analysis/ValueTracking.cpp

Lines changed: 36 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1577,7 +1577,7 @@ static void computeKnownBitsFromOperator(const Operator *I,
15771577
}
15781578
case Instruction::PHI: {
15791579
const PHINode *P = cast<PHINode>(I);
1580-
BinaryOperator *BO = nullptr;
1580+
Instruction *BO = nullptr;
15811581
Value *R = nullptr, *L = nullptr;
15821582
if (matchSimpleRecurrence(P, BO, R, L)) {
15831583
// Handle the case of a simple two-predecessor recurrence PHI.
@@ -1641,6 +1641,7 @@ static void computeKnownBitsFromOperator(const Operator *I,
16411641
case Instruction::Sub:
16421642
case Instruction::And:
16431643
case Instruction::Or:
1644+
case Instruction::GetElementPtr:
16441645
case Instruction::Mul: {
16451646
// Change the context instruction to the "edge" that flows into the
16461647
// phi. This is important because that is where the value is actually
@@ -1659,6 +1660,11 @@ static void computeKnownBitsFromOperator(const Operator *I,
16591660

16601661
// We need to take the minimum number of known bits
16611662
KnownBits Known3(BitWidth);
1663+
if (BitWidth != getBitWidth(L->getType(), Q.DL)) {
1664+
assert(isa<GetElementPtrInst>(BO) &&
1665+
"Bitwidth should only be different for GEPs.");
1666+
break;
1667+
}
16621668
RecQ.CxtI = LInst;
16631669
computeKnownBits(L, DemandedElts, Known3, RecQ, Depth + 1);
16641670

@@ -1821,6 +1827,7 @@ static void computeKnownBitsFromOperator(const Operator *I,
18211827
Known.resetAll();
18221828
}
18231829
}
1830+
18241831
if (const IntrinsicInst *II = dyn_cast<IntrinsicInst>(I)) {
18251832
switch (II->getIntrinsicID()) {
18261833
default:
@@ -2351,7 +2358,7 @@ void computeKnownBits(const Value *V, const APInt &DemandedElts,
23512358
/// always a power of two (or zero).
23522359
static bool isPowerOfTwoRecurrence(const PHINode *PN, bool OrZero,
23532360
SimplifyQuery &Q, unsigned Depth) {
2354-
BinaryOperator *BO = nullptr;
2361+
Instruction *BO = nullptr;
23552362
Value *Start = nullptr, *Step = nullptr;
23562363
if (!matchSimpleRecurrence(PN, BO, Start, Step))
23572364
return false;
@@ -2389,7 +2396,7 @@ static bool isPowerOfTwoRecurrence(const PHINode *PN, bool OrZero,
23892396
// Divisor must be a power of two.
23902397
// If OrZero is false, cannot guarantee induction variable is non-zero after
23912398
// division, same for Shr, unless it is exact division.
2392-
return (OrZero || Q.IIQ.isExact(BO)) &&
2399+
return (OrZero || Q.IIQ.isExact(cast<BinaryOperator>(BO))) &&
23932400
isKnownToBeAPowerOfTwo(Step, false, Q, Depth);
23942401
case Instruction::Shl:
23952402
return OrZero || Q.IIQ.hasNoUnsignedWrap(BO) || Q.IIQ.hasNoSignedWrap(BO);
@@ -2398,7 +2405,7 @@ static bool isPowerOfTwoRecurrence(const PHINode *PN, bool OrZero,
23982405
return false;
23992406
[[fallthrough]];
24002407
case Instruction::LShr:
2401-
return OrZero || Q.IIQ.isExact(BO);
2408+
return OrZero || Q.IIQ.isExact(cast<BinaryOperator>(BO));
24022409
default:
24032410
return false;
24042411
}
@@ -2810,7 +2817,7 @@ static bool rangeMetadataExcludesValue(const MDNode* Ranges, const APInt& Value)
28102817
/// Try to detect a recurrence that monotonically increases/decreases from a
28112818
/// non-zero starting value. These are common as induction variables.
28122819
static bool isNonZeroRecurrence(const PHINode *PN) {
2813-
BinaryOperator *BO = nullptr;
2820+
Instruction *BO = nullptr;
28142821
Value *Start = nullptr, *Step = nullptr;
28152822
const APInt *StartC, *StepC;
28162823
if (!matchSimpleRecurrence(PN, BO, Start, Step) ||
@@ -3648,9 +3655,9 @@ getInvertibleOperands(const Operator *Op1,
36483655
// If PN1 and PN2 are both recurrences, can we prove the entire recurrences
36493656
// are a single invertible function of the start values? Note that repeated
36503657
// application of an invertible function is also invertible
3651-
BinaryOperator *BO1 = nullptr;
3658+
Instruction *BO1 = nullptr;
36523659
Value *Start1 = nullptr, *Step1 = nullptr;
3653-
BinaryOperator *BO2 = nullptr;
3660+
Instruction *BO2 = nullptr;
36543661
Value *Start2 = nullptr, *Step2 = nullptr;
36553662
if (PN1->getParent() != PN2->getParent() ||
36563663
!matchSimpleRecurrence(PN1, BO1, Start1, Step1) ||
@@ -9130,6 +9137,13 @@ static bool matchTwoInputRecurrence(const PHINode *PN, InstTy *&Inst,
91309137
if (LHS != PN && RHS != PN)
91319138
continue;
91329139

9140+
Value *LR;
9141+
if (match(Operation, m_PtrAdd(m_Specific(PN), m_Value(LR)))) {
9142+
Inst = Operation;
9143+
Init = PN->getIncomingValue(!I);
9144+
OtherOp = LR;
9145+
return true;
9146+
}
91339147
Inst = Operation;
91349148
Init = PN->getIncomingValue(!I);
91359149
OtherOp = (LHS == PN) ? RHS : LHS;
@@ -9147,12 +9161,24 @@ bool llvm::matchSimpleRecurrence(const PHINode *P, BinaryOperator *&BO,
91479161
// Or:
91489162
// %iv = [Start, %entry], [%iv.next, %backedge]
91499163
// %iv.next = binop Step, %iv
9150-
return matchTwoInputRecurrence(P, BO, Start, Step);
9164+
return matchTwoInputRecurrence(P, BO, Start, Step) && isa<BinaryOperator>(BO);
9165+
}
9166+
9167+
bool llvm::matchSimpleRecurrence(const PHINode *P, Instruction *&BO,
9168+
Value *&Start, Value *&Step) {
9169+
// We try to match a recurrence of the form:
9170+
// %iv = [Start, %entry], [%iv.next, %backedge]
9171+
// %iv.next = binop %iv, Step
9172+
// Or:
9173+
// %iv = [Start, %entry], [%iv.next, %backedge]
9174+
// %iv.next = binop Step, %iv
9175+
return matchTwoInputRecurrence(P, BO, Start, Step) &&
9176+
isa<BinaryOperator, GetElementPtrInst>(BO);
91519177
}
91529178

9153-
bool llvm::matchSimpleRecurrence(const BinaryOperator *I, PHINode *&P,
9179+
bool llvm::matchSimpleRecurrence(const Instruction *I, PHINode *&P,
91549180
Value *&Start, Value *&Step) {
9155-
BinaryOperator *BO = nullptr;
9181+
Instruction *BO = nullptr;
91569182
P = dyn_cast<PHINode>(I->getOperand(0));
91579183
if (!P)
91589184
P = dyn_cast<PHINode>(I->getOperand(1));

llvm/test/Transforms/InferAlignment/gep-recurrence.ll

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ define void @recur_i8_128(ptr align 128 %dst) {
1212
; CHECK-NEXT: br label %[[LOOP:.*]]
1313
; CHECK: [[LOOP]]:
1414
; CHECK-NEXT: [[IV:%.*]] = phi ptr [ [[DST]], %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
15-
; CHECK-NEXT: store i64 0, ptr [[IV]], align 1
15+
; CHECK-NEXT: store i64 0, ptr [[IV]], align 128
1616
; CHECK-NEXT: [[IV_NEXT]] = getelementptr nusw i8, ptr [[IV]], i64 128
1717
; CHECK-NEXT: [[C:%.*]] = call i1 @cond()
1818
; CHECK-NEXT: br i1 [[C]], label %[[LOOP]], label %[[EXIT:.*]]
@@ -40,7 +40,7 @@ define void @recur_i8_128_no_nusw(ptr align 128 %dst) {
4040
; CHECK-NEXT: br label %[[LOOP:.*]]
4141
; CHECK: [[LOOP]]:
4242
; CHECK-NEXT: [[IV:%.*]] = phi ptr [ [[DST]], %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
43-
; CHECK-NEXT: store i64 0, ptr [[IV]], align 1
43+
; CHECK-NEXT: store i64 0, ptr [[IV]], align 128
4444
; CHECK-NEXT: [[IV_NEXT]] = getelementptr i8, ptr [[IV]], i64 128
4545
; CHECK-NEXT: [[C:%.*]] = call i1 @cond()
4646
; CHECK-NEXT: br i1 [[C]], label %[[LOOP]], label %[[EXIT:.*]]
@@ -68,7 +68,7 @@ define void @recur_i8_64(ptr align 128 %dst) {
6868
; CHECK-NEXT: br label %[[LOOP:.*]]
6969
; CHECK: [[LOOP]]:
7070
; CHECK-NEXT: [[IV:%.*]] = phi ptr [ [[DST]], %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
71-
; CHECK-NEXT: store i64 0, ptr [[IV]], align 1
71+
; CHECK-NEXT: store i64 0, ptr [[IV]], align 64
7272
; CHECK-NEXT: [[IV_NEXT]] = getelementptr nusw i8, ptr [[IV]], i64 64
7373
; CHECK-NEXT: [[C:%.*]] = call i1 @cond()
7474
; CHECK-NEXT: br i1 [[C]], label %[[LOOP]], label %[[EXIT:.*]]
@@ -124,7 +124,7 @@ define void @recur_i8_32(ptr align 128 %dst) {
124124
; CHECK-NEXT: br label %[[LOOP:.*]]
125125
; CHECK: [[LOOP]]:
126126
; CHECK-NEXT: [[IV:%.*]] = phi ptr [ [[DST]], %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
127-
; CHECK-NEXT: store i64 0, ptr [[IV]], align 1
127+
; CHECK-NEXT: store i64 0, ptr [[IV]], align 32
128128
; CHECK-NEXT: [[IV_NEXT]] = getelementptr nusw i8, ptr [[IV]], i64 32
129129
; CHECK-NEXT: [[C:%.*]] = call i1 @cond()
130130
; CHECK-NEXT: br i1 [[C]], label %[[LOOP]], label %[[EXIT:.*]]
@@ -152,7 +152,7 @@ define void @recur_i8_16(ptr align 128 %dst) {
152152
; CHECK-NEXT: br label %[[LOOP:.*]]
153153
; CHECK: [[LOOP]]:
154154
; CHECK-NEXT: [[IV:%.*]] = phi ptr [ [[DST]], %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
155-
; CHECK-NEXT: store i64 0, ptr [[IV]], align 1
155+
; CHECK-NEXT: store i64 0, ptr [[IV]], align 16
156156
; CHECK-NEXT: [[IV_NEXT]] = getelementptr nusw i8, ptr [[IV]], i64 16
157157
; CHECK-NEXT: [[C:%.*]] = call i1 @cond()
158158
; CHECK-NEXT: br i1 [[C]], label %[[LOOP]], label %[[EXIT:.*]]
@@ -180,7 +180,7 @@ define void @recur_i8_8(ptr align 128 %dst) {
180180
; CHECK-NEXT: br label %[[LOOP:.*]]
181181
; CHECK: [[LOOP]]:
182182
; CHECK-NEXT: [[IV:%.*]] = phi ptr [ [[DST]], %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
183-
; CHECK-NEXT: store i64 0, ptr [[IV]], align 1
183+
; CHECK-NEXT: store i64 0, ptr [[IV]], align 8
184184
; CHECK-NEXT: [[IV_NEXT]] = getelementptr nusw i8, ptr [[IV]], i64 8
185185
; CHECK-NEXT: [[C:%.*]] = call i1 @cond()
186186
; CHECK-NEXT: br i1 [[C]], label %[[LOOP]], label %[[EXIT:.*]]
@@ -208,7 +208,7 @@ define void @recur_i8_4(ptr align 128 %dst) {
208208
; CHECK-NEXT: br label %[[LOOP:.*]]
209209
; CHECK: [[LOOP]]:
210210
; CHECK-NEXT: [[IV:%.*]] = phi ptr [ [[DST]], %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
211-
; CHECK-NEXT: store i64 0, ptr [[IV]], align 1
211+
; CHECK-NEXT: store i64 0, ptr [[IV]], align 4
212212
; CHECK-NEXT: [[IV_NEXT]] = getelementptr nusw i8, ptr [[IV]], i64 4
213213
; CHECK-NEXT: [[C:%.*]] = call i1 @cond()
214214
; CHECK-NEXT: br i1 [[C]], label %[[LOOP]], label %[[EXIT:.*]]
@@ -236,7 +236,7 @@ define void @recur_i8_2(ptr align 128 %dst) {
236236
; CHECK-NEXT: br label %[[LOOP:.*]]
237237
; CHECK: [[LOOP]]:
238238
; CHECK-NEXT: [[IV:%.*]] = phi ptr [ [[DST]], %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
239-
; CHECK-NEXT: store i64 0, ptr [[IV]], align 1
239+
; CHECK-NEXT: store i64 0, ptr [[IV]], align 2
240240
; CHECK-NEXT: [[IV_NEXT]] = getelementptr nusw i8, ptr [[IV]], i64 2
241241
; CHECK-NEXT: [[C:%.*]] = call i1 @cond()
242242
; CHECK-NEXT: br i1 [[C]], label %[[LOOP]], label %[[EXIT:.*]]
@@ -412,7 +412,7 @@ define void @recur_i32_4(ptr align 128 %dst) {
412412
; CHECK-NEXT: br label %[[LOOP:.*]]
413413
; CHECK: [[LOOP]]:
414414
; CHECK-NEXT: [[IV:%.*]] = phi ptr [ [[DST]], %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
415-
; CHECK-NEXT: store i64 0, ptr [[IV]], align 1
415+
; CHECK-NEXT: store i64 0, ptr [[IV]], align 4
416416
; CHECK-NEXT: [[IV_NEXT]] = getelementptr nusw i32, ptr [[IV]], i64 4
417417
; CHECK-NEXT: [[C:%.*]] = call i1 @cond()
418418
; CHECK-NEXT: br i1 [[C]], label %[[LOOP]], label %[[EXIT:.*]]
@@ -440,7 +440,7 @@ define void @recur_i32_3(ptr align 128 %dst) {
440440
; CHECK-NEXT: br label %[[LOOP:.*]]
441441
; CHECK: [[LOOP]]:
442442
; CHECK-NEXT: [[IV:%.*]] = phi ptr [ [[DST]], %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
443-
; CHECK-NEXT: store i64 0, ptr [[IV]], align 1
443+
; CHECK-NEXT: store i64 0, ptr [[IV]], align 4
444444
; CHECK-NEXT: [[IV_NEXT]] = getelementptr nusw i32, ptr [[IV]], i64 4
445445
; CHECK-NEXT: [[C:%.*]] = call i1 @cond()
446446
; CHECK-NEXT: br i1 [[C]], label %[[LOOP]], label %[[EXIT:.*]]
@@ -468,7 +468,7 @@ define void @recur_i8_neg_128(ptr align 128 %dst) {
468468
; CHECK-NEXT: br label %[[LOOP:.*]]
469469
; CHECK: [[LOOP]]:
470470
; CHECK-NEXT: [[IV:%.*]] = phi ptr [ [[DST]], %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
471-
; CHECK-NEXT: store i64 0, ptr [[IV]], align 1
471+
; CHECK-NEXT: store i64 0, ptr [[IV]], align 128
472472
; CHECK-NEXT: [[IV_NEXT]] = getelementptr nusw i8, ptr [[IV]], i64 -128
473473
; CHECK-NEXT: [[C:%.*]] = call i1 @cond()
474474
; CHECK-NEXT: br i1 [[C]], label %[[LOOP]], label %[[EXIT:.*]]
@@ -496,7 +496,7 @@ define void @recur_i8_neg64(ptr align 128 %dst) {
496496
; CHECK-NEXT: br label %[[LOOP:.*]]
497497
; CHECK: [[LOOP]]:
498498
; CHECK-NEXT: [[IV:%.*]] = phi ptr [ [[DST]], %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
499-
; CHECK-NEXT: store i64 0, ptr [[IV]], align 1
499+
; CHECK-NEXT: store i64 0, ptr [[IV]], align 64
500500
; CHECK-NEXT: [[IV_NEXT]] = getelementptr nusw i8, ptr [[IV]], i64 -64
501501
; CHECK-NEXT: [[C:%.*]] = call i1 @cond()
502502
; CHECK-NEXT: br i1 [[C]], label %[[LOOP]], label %[[EXIT:.*]]
@@ -552,7 +552,7 @@ define void @recur_i8_neg_32(ptr align 128 %dst) {
552552
; CHECK-NEXT: br label %[[LOOP:.*]]
553553
; CHECK: [[LOOP]]:
554554
; CHECK-NEXT: [[IV:%.*]] = phi ptr [ [[DST]], %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
555-
; CHECK-NEXT: store i64 0, ptr [[IV]], align 1
555+
; CHECK-NEXT: store i64 0, ptr [[IV]], align 32
556556
; CHECK-NEXT: [[IV_NEXT]] = getelementptr nusw i8, ptr [[IV]], i64 -32
557557
; CHECK-NEXT: [[C:%.*]] = call i1 @cond()
558558
; CHECK-NEXT: br i1 [[C]], label %[[LOOP]], label %[[EXIT:.*]]

0 commit comments

Comments
 (0)