Skip to content

Commit 7294978

Browse files
committed
[ValueTracking] Handle recursive PHI's in computeKnownBits
Finish porting llvm#114008 to `KnownBits` (Follow up to llvm#113707).
1 parent 15e0b46 commit 7294978

File tree

5 files changed

+63
-66
lines changed

5 files changed

+63
-66
lines changed

llvm/lib/Analysis/ValueTracking.cpp

Lines changed: 48 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -580,6 +580,43 @@ static bool cmpExcludesZero(CmpInst::Predicate Pred, const Value *RHS) {
580580
return true;
581581
}
582582

583+
static void breakSelfRecursivePHI(const Use *U, const PHINode *PHI,
584+
Value *&ValOut, Instruction *&CtxIOut,
585+
unsigned *DepthInOut = nullptr) {
586+
ValOut = U->get();
587+
if (ValOut == PHI)
588+
return;
589+
CtxIOut = PHI->getIncomingBlock(*U)->getTerminator();
590+
Value *V;
591+
// If the Use is a select of this phi, compute analysis on other arm to be
592+
// recusion.
593+
// TODO: FMin/FMax
594+
if (match(ValOut, m_Select(m_Value(), m_Specific(PHI), m_Value(V))) ||
595+
match(ValOut, m_Select(m_Value(), m_Value(V), m_Specific(PHI))) ||
596+
match(ValOut, m_c_MaxOrMin(m_Value(V), m_Specific(PHI)))) {
597+
ValOut = V;
598+
return;
599+
}
600+
601+
if (DepthInOut)
602+
*DepthInOut = MaxAnalysisRecursionDepth - 1;
603+
604+
// Same for select, if this phi is 2-operand phi, compute analysis on other
605+
// incoming value to break recursion.
606+
// TODO: We could handle any number of incoming edges as long as we only have
607+
// two unique values.
608+
if (auto *IncPhi = dyn_cast<PHINode>(ValOut);
609+
IncPhi && IncPhi->getNumIncomingValues() == 2) {
610+
for (int Idx = 0; Idx < 2; ++Idx) {
611+
if (IncPhi->getIncomingValue(Idx) == PHI) {
612+
ValOut = IncPhi->getIncomingValue(1 - Idx);
613+
CtxIOut = IncPhi->getIncomingBlock(1 - Idx)->getTerminator();
614+
return;
615+
}
616+
}
617+
}
618+
}
619+
583620
static bool isKnownNonZeroFromAssume(const Value *V, const SimplifyQuery &Q) {
584621
// Use of assumptions is context-sensitive. If we don't have a context, we
585622
// cannot use them!
@@ -1561,33 +1598,20 @@ static void computeKnownBitsFromOperator(const Operator *I,
15611598

15621599
Known.Zero.setAllBits();
15631600
Known.One.setAllBits();
1564-
for (unsigned u = 0, e = P->getNumIncomingValues(); u < e; ++u) {
1565-
Value *IncValue = P->getIncomingValue(u);
1601+
for (const Use &U : P->operands()) {
1602+
Value *IncValue;
1603+
Instruction *CxtI;
1604+
unsigned IncDepth = Depth + 1;
1605+
breakSelfRecursivePHI(&U, P, IncValue, CxtI, &IncDepth);
15661606
// Skip direct self references.
1567-
if (IncValue == P) continue;
1568-
1569-
// Recurse, but cap the recursion to one level, because we don't
1570-
// want to waste time spinning around in loops.
1571-
// TODO: See if we can base recursion limiter on number of incoming phi
1572-
// edges so we don't overly clamp analysis.
1573-
unsigned IncDepth = MaxAnalysisRecursionDepth - 1;
1574-
1575-
// If the Use is a select of this phi, use the knownbit of the other
1576-
// operand to break the recursion.
1577-
if (auto *SI = dyn_cast<SelectInst>(IncValue)) {
1578-
if (SI->getTrueValue() == P || SI->getFalseValue() == P) {
1579-
IncValue = SI->getTrueValue() == P ? SI->getFalseValue()
1580-
: SI->getTrueValue();
1581-
IncDepth = Depth + 1;
1582-
}
1583-
}
1607+
if (IncValue == P)
1608+
continue;
15841609

15851610
// Change the context instruction to the "edge" that flows into the
15861611
// phi. This is important because that is where the value is actually
15871612
// "evaluated" even though it is used later somewhere else. (see also
15881613
// D69571).
1589-
SimplifyQuery RecQ = Q.getWithoutCondContext();
1590-
RecQ.CxtI = P->getIncomingBlock(u)->getTerminator();
1614+
SimplifyQuery RecQ = Q.getWithoutCondContext().getWithInstruction(CxtI);
15911615

15921616
Known2 = KnownBits(BitWidth);
15931617
computeKnownBits(IncValue, DemandedElts, Known2, IncDepth, RecQ);
@@ -6008,30 +6032,13 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
60086032
bool First = true;
60096033

60106034
for (const Use &U : P->operands()) {
6011-
Value *IncValue = U.get();
6035+
Value *IncValue;
6036+
Instruction *CxtI;
6037+
breakSelfRecursivePHI(&U, P, IncValue, CxtI);
60126038
// Skip direct self references.
60136039
if (IncValue == P)
60146040
continue;
60156041

6016-
Instruction *CxtI = P->getIncomingBlock(U)->getTerminator();
6017-
6018-
// If the Use is a select of this phi, use the fp class of the other
6019-
// operand to break the recursion. Same around 2-operand phi nodes
6020-
Value *V;
6021-
if (match(IncValue, m_Select(m_Value(), m_Specific(P), m_Value(V))) ||
6022-
match(IncValue, m_Select(m_Value(), m_Value(V), m_Specific(P)))) {
6023-
IncValue = V;
6024-
} else if (auto *IncPhi = dyn_cast<PHINode>(IncValue);
6025-
IncPhi && IncPhi->getNumIncomingValues() == 2) {
6026-
for (int Idx = 0; Idx < 2; ++Idx) {
6027-
if (IncPhi->getIncomingValue(Idx) == P) {
6028-
IncValue = IncPhi->getIncomingValue(1 - Idx);
6029-
CxtI = IncPhi->getIncomingBlock(1 - Idx)->getTerminator();
6030-
break;
6031-
}
6032-
}
6033-
}
6034-
60356042
KnownFPClass KnownSrc;
60366043
// Recurse, but cap the recursion to two levels, because we don't want
60376044
// to waste time spinning around in loops. We need at least depth 2 to

llvm/test/Analysis/ScalarEvolution/cycled_phis.ll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@ define void @test_01() {
88
; CHECK-LABEL: 'test_01'
99
; CHECK-NEXT: Classifying expressions for: @test_01
1010
; CHECK-NEXT: %phi_1 = phi i32 [ 10, %entry ], [ %phi_2, %loop ]
11-
; CHECK-NEXT: --> %phi_1 U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
11+
; CHECK-NEXT: --> %phi_1 U: [0,31) S: [0,31) Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
1212
; CHECK-NEXT: %phi_2 = phi i32 [ 20, %entry ], [ %phi_1, %loop ]
13-
; CHECK-NEXT: --> %phi_2 U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
13+
; CHECK-NEXT: --> %phi_2 U: [0,31) S: [0,31) Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
1414
; CHECK-NEXT: %cond = call i1 @cond()
1515
; CHECK-NEXT: --> %cond U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
1616
; CHECK-NEXT: Determining loop execution counts for: @test_01

llvm/test/Analysis/ScalarEvolution/unknown_phis.ll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,9 @@ define void @merge_values_with_ranges_looped(ptr %a_len_ptr, ptr %b_len_ptr) {
3939
; CHECK-NEXT: %len_b = load i32, ptr %b_len_ptr, align 4, !range !0
4040
; CHECK-NEXT: --> %len_b U: [0,2147483647) S: [0,2147483647)
4141
; CHECK-NEXT: %p1 = phi i32 [ %len_a, %entry ], [ %p2, %loop ]
42-
; CHECK-NEXT: --> %p1 U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
42+
; CHECK-NEXT: --> %p1 U: [0,-2147483648) S: [0,-2147483648) Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
4343
; CHECK-NEXT: %p2 = phi i32 [ %len_b, %entry ], [ %p1, %loop ]
44-
; CHECK-NEXT: --> %p2 U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
44+
; CHECK-NEXT: --> %p2 U: [0,-2147483648) S: [0,-2147483648) Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
4545
; CHECK-NEXT: %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ]
4646
; CHECK-NEXT: --> {0,+,1}<nuw><nsw><%loop> U: [0,100) S: [0,100) Exits: 99 LoopDispositions: { %loop: Computable }
4747
; CHECK-NEXT: %iv.next = add i32 %iv, 1

llvm/test/Transforms/InstCombine/known-phi-recurse.ll

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -261,14 +261,11 @@ define i8 @knownbits_umax_select_test() {
261261
; CHECK-NEXT: entry:
262262
; CHECK-NEXT: br label [[LOOP:%.*]]
263263
; CHECK: loop:
264-
; CHECK-NEXT: [[INDVAR:%.*]] = phi i8 [ 0, [[ENTRY:%.*]] ], [ [[CONTAIN:%.*]], [[LOOP]] ]
265264
; CHECK-NEXT: [[COND0:%.*]] = call i1 @cond()
266-
; CHECK-NEXT: [[CONTAIN]] = call i8 @llvm.umax.i8(i8 [[INDVAR]], i8 1)
267265
; CHECK-NEXT: [[COND1:%.*]] = call i1 @cond()
268266
; CHECK-NEXT: br i1 [[COND1]], label [[EXIT:%.*]], label [[LOOP]]
269267
; CHECK: exit:
270-
; CHECK-NEXT: [[BOOL:%.*]] = and i8 [[CONTAIN]], 1
271-
; CHECK-NEXT: ret i8 [[BOOL]]
268+
; CHECK-NEXT: ret i8 1
272269
;
273270
entry:
274271
br label %loop
@@ -301,8 +298,7 @@ define i8 @knownbits_phi_phi_test() {
301298
; CHECK-NEXT: [[COND1:%.*]] = call i1 @cond()
302299
; CHECK-NEXT: br i1 [[COND1]], label [[EXIT:%.*]], label [[LOOP]]
303300
; CHECK: exit:
304-
; CHECK-NEXT: [[BOOL:%.*]] = and i8 [[CONTAIN]], 1
305-
; CHECK-NEXT: ret i8 [[BOOL]]
301+
; CHECK-NEXT: ret i8 [[CONTAIN]]
306302
;
307303
entry:
308304
br label %loop

llvm/test/Transforms/SimplifyCFG/switch-branch-fold-indirectbr-102351.ll

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,29 +8,23 @@ define dso_local noundef i32 @main() {
88
; CHECK-LABEL: define dso_local noundef i32 @main() {
99
; CHECK-NEXT: [[BB:.*]]:
1010
; CHECK-NEXT: [[ALLOCA:%.*]] = alloca [2 x ptr], align 16
11-
; CHECK-NEXT: store ptr blockaddress(@main, %[[BB4:.*]]), ptr [[ALLOCA]], align 16, !tbaa [[TBAA0:![0-9]+]]
11+
; CHECK-NEXT: store ptr blockaddress(@main, %[[BB1:.*]]), ptr [[ALLOCA]], align 16, !tbaa [[TBAA0:![0-9]+]]
1212
; CHECK-NEXT: [[GETELEMENTPTR:%.*]] = getelementptr inbounds [2 x ptr], ptr [[ALLOCA]], i64 0, i64 1
1313
; CHECK-NEXT: store ptr blockaddress(@main, %[[BB10:.*]]), ptr [[GETELEMENTPTR]], align 8, !tbaa [[TBAA0]]
14-
; CHECK-NEXT: br label %[[BB1:.*]]
14+
; CHECK-NEXT: br label %[[BB1]]
1515
; CHECK: [[BB1]]:
16-
; CHECK-NEXT: [[PHI:%.*]] = phi i32 [ 0, %[[BB]] ], [ [[PHI8:%.*]], %[[BB7:.*]] ]
17-
; CHECK-NEXT: [[PHI2:%.*]] = phi i32 [ 0, %[[BB]] ], [ [[PHI9:%.*]], %[[BB7]] ]
18-
; CHECK-NEXT: switch i32 [[PHI]], label %[[BB7]] [
19-
; CHECK-NEXT: i32 0, label %[[BB12:.*]]
20-
; CHECK-NEXT: i32 1, label %[[BB4]]
16+
; CHECK-NEXT: [[PHI:%.*]] = phi i32 [ 0, %[[BB]] ], [ 2, %[[BB12:.*]] ]
17+
; CHECK-NEXT: [[PHI2:%.*]] = phi i32 [ 0, %[[BB]] ], [ [[PHI13:%.*]], %[[BB12]] ]
18+
; CHECK-NEXT: switch i32 [[PHI]], label %[[BB1_UNREACHABLEDEFAULT:.*]] [
19+
; CHECK-NEXT: i32 0, label %[[BB12]]
2120
; CHECK-NEXT: i32 2, label %[[BB6:.*]]
2221
; CHECK-NEXT: ]
23-
; CHECK: [[BB4]]:
24-
; CHECK-NEXT: [[PHI5:%.*]] = phi i32 [ [[PHI13:%.*]], %[[BB12]] ], [ [[PHI2]], %[[BB1]] ]
25-
; CHECK-NEXT: br label %[[BB7]]
2622
; CHECK: [[BB6]]:
2723
; CHECK-NEXT: [[CALL:%.*]] = call i32 @foo(i32 noundef [[PHI2]])
2824
; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[PHI2]], 1
2925
; CHECK-NEXT: br label %[[BB12]]
30-
; CHECK: [[BB7]]:
31-
; CHECK-NEXT: [[PHI8]] = phi i32 [ [[PHI]], %[[BB1]] ], [ 2, %[[BB4]] ]
32-
; CHECK-NEXT: [[PHI9]] = phi i32 [ [[PHI2]], %[[BB1]] ], [ [[PHI5]], %[[BB4]] ]
33-
; CHECK-NEXT: br label %[[BB1]], !llvm.loop [[LOOP4:![0-9]+]]
26+
; CHECK: [[BB1_UNREACHABLEDEFAULT]]:
27+
; CHECK-NEXT: unreachable
3428
; CHECK: [[BB10]]:
3529
; CHECK-NEXT: [[CALL11:%.*]] = call i32 @foo(i32 noundef [[PHI13]])
3630
; CHECK-NEXT: ret i32 0
@@ -39,7 +33,7 @@ define dso_local noundef i32 @main() {
3933
; CHECK-NEXT: [[SEXT:%.*]] = sext i32 [[PHI13]] to i64
4034
; CHECK-NEXT: [[GETELEMENTPTR14:%.*]] = getelementptr inbounds [2 x ptr], ptr [[ALLOCA]], i64 0, i64 [[SEXT]]
4135
; CHECK-NEXT: [[LOAD:%.*]] = load ptr, ptr [[GETELEMENTPTR14]], align 8, !tbaa [[TBAA0]]
42-
; CHECK-NEXT: indirectbr ptr [[LOAD]], [label %[[BB4]], label %bb10]
36+
; CHECK-NEXT: indirectbr ptr [[LOAD]], [label %[[BB1]], label %bb10], !llvm.loop [[LOOP4:![0-9]+]]
4337
;
4438
bb:
4539
%alloca = alloca [2 x ptr], align 16

0 commit comments

Comments
 (0)