Skip to content

Commit 4a4d517

Browse files
committed
ValueTracking: complete matchSimpleRecurrence
matchSimpleRecurrence only misses recurrence cases for UDiv, SDiv, URem, and SRem, as no meaningful simplification can be performed on an Xor recurrence using the KnownBits infrastructure; Xor with zero is already simplified. Further, the FMul in the switch statement is uncreachable code, as KnownBits doesn't support fp values. Hence, write simplifications for UDiv, SDiv, URem and SRem recurrences using KnownBits, and strip the FMul from the switch statement, completing the function.
1 parent 5b8fbcc commit 4a4d517

File tree

2 files changed

+57
-67
lines changed

2 files changed

+57
-67
lines changed

llvm/lib/Analysis/ValueTracking.cpp

Lines changed: 47 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1451,34 +1451,34 @@ static void computeKnownBitsFromOperator(const Operator *I,
14511451
};
14521452
}
14531453

1454-
// Check for operations that have the property that if
1455-
// both their operands have low zero bits, the result
1456-
// will have low zero bits.
1457-
if (Opcode == Instruction::Add ||
1458-
Opcode == Instruction::Sub ||
1459-
Opcode == Instruction::And ||
1460-
Opcode == Instruction::Or ||
1461-
Opcode == Instruction::Mul) {
1462-
// Change the context instruction to the "edge" that flows into the
1463-
// phi. This is important because that is where the value is actually
1464-
// "evaluated" even though it is used later somewhere else. (see also
1465-
// D69571).
1466-
SimplifyQuery RecQ = Q.getWithoutCondContext();
1454+
// Change the context instruction to the "edge" that flows into the
1455+
// phi. This is important because that is where the value is actually
1456+
// "evaluated" even though it is used later somewhere else. (see also
1457+
// D69571).
1458+
SimplifyQuery RecQ = Q.getWithoutCondContext();
14671459

1468-
unsigned OpNum = P->getOperand(0) == R ? 0 : 1;
1469-
Instruction *RInst = P->getIncomingBlock(OpNum)->getTerminator();
1470-
Instruction *LInst = P->getIncomingBlock(1 - OpNum)->getTerminator();
1460+
unsigned OpNum = P->getOperand(0) == R ? 0 : 1;
1461+
Instruction *RInst = P->getIncomingBlock(OpNum)->getTerminator();
1462+
Instruction *LInst = P->getIncomingBlock(1 - OpNum)->getTerminator();
14711463

1472-
// Ok, we have a PHI of the form L op= R. Check for low
1473-
// zero bits.
1474-
RecQ.CxtI = RInst;
1475-
computeKnownBits(R, DemandedElts, Known2, Depth + 1, RecQ);
1464+
// Ok, we have a PHI of the form L op= R. R and Known2 correspond to the
1465+
// start value.
1466+
RecQ.CxtI = RInst;
1467+
computeKnownBits(R, DemandedElts, Known2, Depth + 1, RecQ);
14761468

1477-
// We need to take the minimum number of known bits
1478-
KnownBits Known3(BitWidth);
1479-
RecQ.CxtI = LInst;
1480-
computeKnownBits(L, DemandedElts, Known3, Depth + 1, RecQ);
1469+
KnownBits Known3(BitWidth);
1470+
RecQ.CxtI = LInst;
1471+
computeKnownBits(L, DemandedElts, Known3, Depth + 1, RecQ);
14811472

1473+
switch (Opcode) {
1474+
// Check for operations that have the property that if both their operands
1475+
// have low zero bits, the result will have low zero bits.
1476+
case Instruction::Add:
1477+
case Instruction::Sub:
1478+
case Instruction::And:
1479+
case Instruction::Or:
1480+
case Instruction::Mul: {
1481+
// We need to take the minimum number of known bits
14821482
Known.Zero.setLowBits(std::min(Known2.countMinTrailingZeros(),
14831483
Known3.countMinTrailingZeros()));
14841484

@@ -1514,9 +1514,26 @@ static void computeKnownBitsFromOperator(const Operator *I,
15141514
Known3.isNonNegative())
15151515
Known.makeNonNegative();
15161516
}
1517-
15181517
break;
15191518
}
1519+
case Instruction::UDiv:
1520+
case Instruction::URem:
1521+
// Result cannot be larger than start value.
1522+
Known.Zero.setHighBits(Known2.countMinLeadingZeros());
1523+
break;
1524+
case Instruction::SDiv:
1525+
case Instruction::SRem: {
1526+
// Magnitude of result cannot be larger than that of start value.
1527+
if (Known2.isNonNegative())
1528+
Known.Zero.setHighBits(Known2.countMinLeadingZeros());
1529+
else if (Known2.isNegative())
1530+
Known.One.setHighBits(Known2.countMinLeadingOnes());
1531+
break;
1532+
}
1533+
default:
1534+
break;
1535+
}
1536+
break;
15201537
}
15211538

15221539
// Unreachable blocks may have zero-operand PHI nodes.
@@ -8968,7 +8985,6 @@ bool llvm::matchSimpleRecurrence(const PHINode *P, BinaryOperator *&BO,
89688985
switch (Opcode) {
89698986
default:
89708987
continue;
8971-
// TODO: Expand list -- xor, div, gep, uaddo, etc..
89728988
case Instruction::LShr:
89738989
case Instruction::AShr:
89748990
case Instruction::Shl:
@@ -8977,7 +8993,11 @@ bool llvm::matchSimpleRecurrence(const PHINode *P, BinaryOperator *&BO,
89778993
case Instruction::And:
89788994
case Instruction::Or:
89798995
case Instruction::Mul:
8980-
case Instruction::FMul: {
8996+
case Instruction::FMul:
8997+
case Instruction::UDiv:
8998+
case Instruction::SDiv:
8999+
case Instruction::URem:
9000+
case Instruction::SRem: {
89819001
Value *LL = LU->getOperand(0);
89829002
Value *LR = LU->getOperand(1);
89839003
// Find a recurrence.

llvm/test/Analysis/ValueTracking/recurrence-knownbits.ll

Lines changed: 10 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -86,12 +86,9 @@ define i64 @test_udiv(i1 %c) {
8686
; CHECK-NEXT: entry:
8787
; CHECK-NEXT: br label [[LOOP:%.*]]
8888
; CHECK: loop:
89-
; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 9, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
90-
; CHECK-NEXT: [[IV_NEXT]] = udiv i64 [[IV]], 3
9189
; CHECK-NEXT: br i1 [[C:%.*]], label [[EXIT:%.*]], label [[LOOP]]
9290
; CHECK: exit:
93-
; CHECK-NEXT: [[RES:%.*]] = and i64 [[IV]], 16
94-
; CHECK-NEXT: ret i64 [[RES]]
91+
; CHECK-NEXT: ret i64 0
9592
;
9693
entry:
9794
br label %loop
@@ -109,12 +106,9 @@ define i64 @test_sdiv(i1 %c) {
109106
; CHECK-NEXT: entry:
110107
; CHECK-NEXT: br label [[LOOP:%.*]]
111108
; CHECK: loop:
112-
; CHECK-NEXT: [[IV:%.*]] = phi i64 [ -9, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
113-
; CHECK-NEXT: [[IV_NEXT]] = sdiv i64 [[IV]], -3
114109
; CHECK-NEXT: br i1 [[C:%.*]], label [[EXIT:%.*]], label [[LOOP]]
115110
; CHECK: exit:
116-
; CHECK-NEXT: [[RES:%.*]] = and i64 [[IV]], 16
117-
; CHECK-NEXT: ret i64 [[RES]]
111+
; CHECK-NEXT: ret i64 16
118112
;
119113
entry:
120114
br label %loop
@@ -132,12 +126,9 @@ define i64 @test_sdiv2(i1 %c) {
132126
; CHECK-NEXT: entry:
133127
; CHECK-NEXT: br label [[LOOP:%.*]]
134128
; CHECK: loop:
135-
; CHECK-NEXT: [[IV:%.*]] = phi i64 [ -9, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
136-
; CHECK-NEXT: [[IV_NEXT]] = sdiv i64 [[IV]], 3
137129
; CHECK-NEXT: br i1 [[C:%.*]], label [[EXIT:%.*]], label [[LOOP]]
138130
; CHECK: exit:
139-
; CHECK-NEXT: [[RES:%.*]] = and i64 [[IV]], 16
140-
; CHECK-NEXT: ret i64 [[RES]]
131+
; CHECK-NEXT: ret i64 16
141132
;
142133
entry:
143134
br label %loop
@@ -155,12 +146,9 @@ define i64 @test_sdiv3(i1 %c) {
155146
; CHECK-NEXT: entry:
156147
; CHECK-NEXT: br label [[LOOP:%.*]]
157148
; CHECK: loop:
158-
; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 9, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
159-
; CHECK-NEXT: [[IV_NEXT]] = sdiv i64 [[IV]], -3
160149
; CHECK-NEXT: br i1 [[C:%.*]], label [[EXIT:%.*]], label [[LOOP]]
161150
; CHECK: exit:
162-
; CHECK-NEXT: [[RES:%.*]] = and i64 [[IV]], -16
163-
; CHECK-NEXT: ret i64 [[RES]]
151+
; CHECK-NEXT: ret i64 0
164152
;
165153
entry:
166154
br label %loop
@@ -178,12 +166,9 @@ define i64 @test_urem(i1 %c) {
178166
; CHECK-NEXT: entry:
179167
; CHECK-NEXT: br label [[LOOP:%.*]]
180168
; CHECK: loop:
181-
; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 3, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
182-
; CHECK-NEXT: [[IV_NEXT]] = urem i64 9, [[IV]]
183169
; CHECK-NEXT: br i1 [[C:%.*]], label [[EXIT:%.*]], label [[LOOP]]
184170
; CHECK: exit:
185-
; CHECK-NEXT: [[RES:%.*]] = and i64 [[IV]], 4
186-
; CHECK-NEXT: ret i64 [[RES]]
171+
; CHECK-NEXT: ret i64 0
187172
;
188173
entry:
189174
br label %loop
@@ -201,12 +186,9 @@ define i64 @test_srem(i1 %c) {
201186
; CHECK-NEXT: entry:
202187
; CHECK-NEXT: br label [[LOOP:%.*]]
203188
; CHECK: loop:
204-
; CHECK-NEXT: [[IV:%.*]] = phi i64 [ -9, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
205-
; CHECK-NEXT: [[IV_NEXT]] = srem i64 [[IV]], 3
206189
; CHECK-NEXT: br i1 [[C:%.*]], label [[EXIT:%.*]], label [[LOOP]]
207190
; CHECK: exit:
208-
; CHECK-NEXT: [[RES:%.*]] = and i64 [[IV]], 16
209-
; CHECK-NEXT: ret i64 [[RES]]
191+
; CHECK-NEXT: ret i64 16
210192
;
211193
entry:
212194
br label %loop
@@ -224,12 +206,9 @@ define i64 @test_srem2(i1 %c) {
224206
; CHECK-NEXT: entry:
225207
; CHECK-NEXT: br label [[LOOP:%.*]]
226208
; CHECK: loop:
227-
; CHECK-NEXT: [[IV:%.*]] = phi i64 [ -9, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
228-
; CHECK-NEXT: [[IV_NEXT]] = srem i64 [[IV]], 3
229209
; CHECK-NEXT: br i1 [[C:%.*]], label [[EXIT:%.*]], label [[LOOP]]
230210
; CHECK: exit:
231-
; CHECK-NEXT: [[RES:%.*]] = and i64 [[IV]], 16
232-
; CHECK-NEXT: ret i64 [[RES]]
211+
; CHECK-NEXT: ret i64 16
233212
;
234213
entry:
235214
br label %loop
@@ -247,12 +226,9 @@ define i64 @test_srem2_flipped(i1 %c) {
247226
; CHECK-NEXT: entry:
248227
; CHECK-NEXT: br label [[LOOP:%.*]]
249228
; CHECK: loop:
250-
; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 3, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
251-
; CHECK-NEXT: [[IV_NEXT]] = srem i64 -9, [[IV]]
252229
; CHECK-NEXT: br i1 [[C:%.*]], label [[EXIT:%.*]], label [[LOOP]]
253230
; CHECK: exit:
254-
; CHECK-NEXT: [[RES:%.*]] = and i64 [[IV]], 4
255-
; CHECK-NEXT: ret i64 [[RES]]
231+
; CHECK-NEXT: ret i64 0
256232
;
257233
entry:
258234
br label %loop
@@ -270,12 +246,9 @@ define i64 @test_srem3(i1 %c) {
270246
; CHECK-NEXT: entry:
271247
; CHECK-NEXT: br label [[LOOP:%.*]]
272248
; CHECK: loop:
273-
; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 9, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
274-
; CHECK-NEXT: [[IV_NEXT]] = srem i64 [[IV]], 3
275249
; CHECK-NEXT: br i1 [[C:%.*]], label [[EXIT:%.*]], label [[LOOP]]
276250
; CHECK: exit:
277-
; CHECK-NEXT: [[RES:%.*]] = and i64 [[IV]], -16
278-
; CHECK-NEXT: ret i64 [[RES]]
251+
; CHECK-NEXT: ret i64 0
279252
;
280253
entry:
281254
br label %loop
@@ -293,12 +266,9 @@ define i64 @test_srem3_flipped(i1 %c) {
293266
; CHECK-NEXT: entry:
294267
; CHECK-NEXT: br label [[LOOP:%.*]]
295268
; CHECK: loop:
296-
; CHECK-NEXT: [[IV:%.*]] = phi i64 [ -3, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
297-
; CHECK-NEXT: [[IV_NEXT]] = srem i64 9, [[IV]]
298269
; CHECK-NEXT: br i1 [[C:%.*]], label [[EXIT:%.*]], label [[LOOP]]
299270
; CHECK: exit:
300-
; CHECK-NEXT: [[RES:%.*]] = and i64 [[IV]], -4
301-
; CHECK-NEXT: ret i64 [[RES]]
271+
; CHECK-NEXT: ret i64 -4
302272
;
303273
entry:
304274
br label %loop

0 commit comments

Comments
 (0)