llvm.org GIT mirror llvm / 91054cc
[ValueTracking] Support icmps fed by 'and' and 'or'. This patch adds support for handling some forms of ands and ors in ValueTracking's isImpliedCondition API. PR33611 https://reviews.llvm.org/D34901 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@307304 91177308-0d34-0410-b5e6-96231b3b80d8 Chad Rosier 3 years ago
4 changed file(s) with 259 addition(s) and 11 deletion(s). Raw diff Collapse all Expand all
522522 /// (A)
523523 Optional isImpliedCondition(const Value *LHS, const Value *RHS,
524524 const DataLayout &DL,
525 bool InvertAPred = false,
526 unsigned Depth = 0,
525 bool LHSIsFalse = false, unsigned Depth = 0,
527526 AssumptionCache *AC = nullptr,
528527 const Instruction *CxtI = nullptr,
529528 const DominatorTree *DT = nullptr);
43924392 }
43934393
43944394 Optional llvm::isImpliedCondition(const Value *LHS, const Value *RHS,
4395 const DataLayout &DL, bool InvertAPred,
4395 const DataLayout &DL, bool LHSIsFalse,
43964396 unsigned Depth, AssumptionCache *AC,
43974397 const Instruction *CxtI,
43984398 const DominatorTree *DT) {
44044404 assert(OpTy->getScalarType()->isIntegerTy(1));
44054405
44064406 // LHS ==> RHS by definition
4407 if (!InvertAPred && LHS == RHS)
4407 if (!LHSIsFalse && LHS == RHS)
44084408 return true;
44094409
44104410 if (OpTy->isVectorTy())
44124412 return None;
44134413 assert(OpTy->isIntegerTy(1) && "implied by above");
44144414
4415 ICmpInst::Predicate APred, BPred;
4415 Value *BLHS, *BRHS;
4416 ICmpInst::Predicate BPred;
4417 // We expect the RHS to be an icmp.
4418 if (!match(RHS, m_ICmp(BPred, m_Value(BLHS), m_Value(BRHS))))
4419 return None;
4420
44164421 Value *ALHS, *ARHS;
4417 Value *BLHS, *BRHS;
4418
4419 if (!match(LHS, m_ICmp(APred, m_Value(ALHS), m_Value(ARHS))) ||
4420 !match(RHS, m_ICmp(BPred, m_Value(BLHS), m_Value(BRHS))))
4422 ICmpInst::Predicate APred;
4423 // The LHS can be an 'or', 'and', or 'icmp'.
4424 if (!match(LHS, m_ICmp(APred, m_Value(ALHS), m_Value(ARHS)))) {
4425 // The remaining tests are all recursive, so bail out if we hit the limit.
4426 if (Depth == MaxDepth)
4427 return None;
4428 // If the result of an 'or' is false, then we know both legs of the 'or' are
4429 // false. Similarly, if the result of an 'and' is true, then we know both
4430 // legs of the 'and' are true.
4431 if ((LHSIsFalse && match(LHS, m_Or(m_Value(ALHS), m_Value(ARHS)))) ||
4432 (!LHSIsFalse && match(LHS, m_And(m_Value(ALHS), m_Value(ARHS))))) {
4433 if (Optional Implication = isImpliedCondition(
4434 ALHS, RHS, DL, LHSIsFalse, Depth + 1, AC, CxtI, DT))
4435 return Implication;
4436 if (Optional Implication = isImpliedCondition(
4437 ARHS, RHS, DL, LHSIsFalse, Depth + 1, AC, CxtI, DT))
4438 return Implication;
4439 return None;
4440 }
44214441 return None;
4422
4423 if (InvertAPred)
4442 }
4443 // All of the below logic assumes both LHS and RHS are icmps.
4444 assert(isa(LHS) && isa(RHS) && "Expected icmps.");
4445
4446 // The rest of the logic assumes the LHS condition is true. If that's not the
4447 // case, invert the predicate to make it so.
4448 if (LHSIsFalse)
44244449 APred = CmpInst::getInversePredicate(APred);
44254450
44264451 // Can we infer anything when the two compares have matching operands?
120120
121121 declare void @foo(i32)
122122 declare i32 @bar(i32)
123
124 ; CHECK-LABEL: @test_and
125 ; CHECK: tpath:
126 ; CHECK-NOT: select
127 ; CHECK: ret i32 313
128 define i32 @test_and(i32 %a, i32 %b) {
129 entry:
130 %cmp1 = icmp ne i32 %a, 0
131 %cmp2 = icmp ne i32 %b, 0
132 %and = and i1 %cmp1, %cmp2
133 br i1 %and, label %tpath, label %end
134
135 tpath:
136 %cmp3 = icmp eq i32 %a, 0 ;; <-- implied false
137 %c = select i1 %cmp3, i32 0, i32 313
138 ret i32 %c
139
140 end:
141 ret i32 0
142 }
143
144 ; cmp1 and cmp2 are false on the 'fpath' path and thus cmp3 is true.
145 ; CHECK-LABEL: @test_or1
146 ; CHECK: fpath:
147 ; CHECK-NOT: select
148 ; CHECK: ret i32 37
149 define i32 @test_or1(i32 %a, i32 %b) {
150 entry:
151 %cmp1 = icmp eq i32 %a, 0
152 %cmp2 = icmp eq i32 %b, 0
153 %or = or i1 %cmp1, %cmp2
154 br i1 %or, label %end, label %fpath
155
156 fpath:
157 %cmp3 = icmp ne i32 %a, 0 ;; <-- implied true
158 %c = select i1 %cmp3, i32 37, i32 0
159 ret i32 %c
160
161 end:
162 ret i32 0
163 }
0 ; RUN: opt %s -S -simplifycfg | FileCheck %s
1
2 declare void @foo()
3 declare void @bar()
4
5
6 ; CHECK-LABEL: @test_and1
7 ; CHECK: taken:
8 ; CHECK-NOT: cmp3
9 ; CHECK: call void @bar()
10 ; CHECK-NEXT: call void @foo()
11 ; CHECK: ret
12 define void @test_and1(i32 %a, i32 %b) {
13 entry:
14 %cmp1 = icmp eq i32 %a, 0
15 %cmp2 = icmp eq i32 %b, 0
16 %and = and i1 %cmp1, %cmp2
17 br i1 %and, label %taken, label %end
18
19 taken:
20 call void @bar()
21 %cmp3 = icmp eq i32 %a, 0 ;; <-- implied true
22 br i1 %cmp3, label %if.then, label %end
23
24 if.then:
25 call void @foo()
26 br label %end
27
28 end:
29 ret void
30 }
31
32 ; We can't infer anything if the result of the 'and' is false
33 ; CHECK-LABEL: @test_and2
34 ; CHECK: taken:
35 ; CHECK: call void @bar()
36 ; CHECK: %cmp3
37 ; CHECK: br i1 %cmp3
38 ; CHECK: if.then:
39 ; CHECK: call void @foo()
40 ; CHECK: ret
41 define void @test_and2(i32 %a, i32 %b) {
42 entry:
43 %cmp1 = icmp eq i32 %a, 0
44 %cmp2 = icmp eq i32 %b, 0
45 %and = and i1 %cmp1, %cmp2
46 br i1 %and, label %end, label %taken
47
48 taken:
49 call void @bar()
50 %cmp3 = icmp eq i32 %a, 0
51 br i1 %cmp3, label %if.then, label %end
52
53 if.then:
54 call void @foo()
55 br label %end
56
57 end:
58 ret void
59 }
60
61 ; CHECK-LABEL: @test_or1
62 ; CHECK: taken:
63 ; CHECK-NOT: cmp3
64 ; CHECK: call void @bar()
65 ; CHECK-NEXT: call void @foo()
66 ; CHECK: ret
67 define void @test_or1(i32 %a, i32 %b) {
68 entry:
69 %cmp1 = icmp eq i32 %a, 0
70 %cmp2 = icmp eq i32 %b, 0
71 %or = or i1 %cmp1, %cmp2
72 br i1 %or, label %end, label %taken
73
74 taken:
75 call void @bar()
76 %cmp3 = icmp ne i32 %a, 0 ;; <-- implied true
77 br i1 %cmp3, label %if.then, label %end
78
79 if.then:
80 call void @foo()
81 br label %end
82
83 end:
84 ret void
85 }
86
87 ; We can't infer anything if the result of the 'or' is true
88 ; CHECK-LABEL: @test_or2
89 ; CHECK: call void @bar()
90 ; CHECK: %cmp3
91 ; CHECK: br i1 %cmp3
92 ; CHECK: if.then:
93 ; CHECK: call void @foo()
94 ; CHECK: ret
95 define void @test_or2(i32 %a, i32 %b) {
96 entry:
97 %cmp1 = icmp eq i32 %a, 0
98 %cmp2 = icmp eq i32 %b, 0
99 %or = or i1 %cmp1, %cmp2
100 br i1 %or, label %taken, label %end
101
102 taken:
103 call void @bar()
104 %cmp3 = icmp eq i32 %a, 0
105 br i1 %cmp3, label %if.then, label %end
106
107 if.then:
108 call void @foo()
109 br label %end
110
111 end:
112 ret void
113 }
114
115 ; We can recurse a tree of 'and' or 'or's.
116 ; CHECK-LABEL: @test_and_recurse1
117 ; CHECK: taken:
118 ; CHECK-NEXT: call void @bar()
119 ; CHECK-NEXT: call void @foo()
120 ; CHECK-NEXT: br label %end
121 ; CHECK: ret
122 define void @test_and_recurse1(i32 %a, i32 %b, i32 %c) {
123 entry:
124 %cmpa = icmp eq i32 %a, 0
125 %cmpb = icmp eq i32 %b, 0
126 %cmpc = icmp eq i32 %c, 0
127 %and1 = and i1 %cmpa, %cmpb
128 %and2 = and i1 %and1, %cmpc
129 br i1 %and2, label %taken, label %end
130
131 taken:
132 call void @bar()
133 %cmp3 = icmp eq i32 %a, 0
134 br i1 %cmp3, label %if.then, label %end
135
136 if.then:
137 call void @foo()
138 br label %end
139
140 end:
141 ret void
142 }
143
144 ; Check to make sure we don't recurse too deep.
145 ; CHECK-LABEL: @test_and_recurse2
146 ; CHECK: taken:
147 ; CHECK-NEXT: call void @bar()
148 ; CHECK-NEXT: %cmp3 = icmp eq i32 %a, 0
149 ; CHECK-NEXT: br i1 %cmp3, label %if.then, label %end
150 ; CHECK: ret
151 define void @test_and_recurse2(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f,
152 i32 %g, i32 %h) {
153 entry:
154 %cmpa = icmp eq i32 %a, 0
155 %cmpb = icmp eq i32 %b, 0
156 %cmpc = icmp eq i32 %c, 0
157 %cmpd = icmp eq i32 %d, 0
158 %cmpe = icmp eq i32 %e, 0
159 %cmpf = icmp eq i32 %f, 0
160 %cmpg = icmp eq i32 %g, 0
161 %cmph = icmp eq i32 %h, 0
162 %and1 = and i1 %cmpa, %cmpb
163 %and2 = and i1 %and1, %cmpc
164 %and3 = and i1 %and2, %cmpd
165 %and4 = and i1 %and3, %cmpe
166 %and5 = and i1 %and4, %cmpf
167 %and6 = and i1 %and5, %cmpg
168 %and7 = and i1 %and6, %cmph
169 br i1 %and7, label %taken, label %end
170
171 taken:
172 call void @bar()
173 %cmp3 = icmp eq i32 %a, 0 ; <-- can be implied true
174 br i1 %cmp3, label %if.then, label %end
175
176 if.then:
177 call void @foo()
178 br label %end
179
180 end:
181 ret void
182 }