llvm.org GIT mirror llvm / 79a680d
[Profile] Enhance expect lowering to handle correlated branches builtin_expect applied on && or || expressions were not handled properly before. With this patch, the problem is fixed. Differential Revision: http://reviews.llvm.org/D33164 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@304517 91177308-0d34-0410-b5e6-96231b3b80d8 Xinliang David Li 2 years ago
4 changed file(s) with 663 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
1313 #include "llvm/Transforms/Scalar/LowerExpectIntrinsic.h"
1414 #include "llvm/ADT/SmallVector.h"
1515 #include "llvm/ADT/Statistic.h"
16 #include "llvm/ADT/iterator_range.h"
1617 #include "llvm/IR/BasicBlock.h"
1718 #include "llvm/IR/Constants.h"
1819 #include "llvm/IR/Function.h"
8081
8182 SI.setCondition(ArgValue);
8283 return true;
84 }
85
86 /// Handler for PHINodes that define the value argument to an
87 /// @llvm.expect call.
88 ///
89 /// If the operand of the phi has a constant value and it 'contradicts'
90 /// with the expected value of phi def, then the corresponding incoming
91 /// edge of the phi is unlikely to be taken. Using that information,
92 /// the branch probability info for the originating branch can be inferred.
93 static void handlePhiDef(CallInst *Expect) {
94 Value &Arg = *Expect->getArgOperand(0);
95 ConstantInt *ExpectedValue = cast(Expect->getArgOperand(1));
96 const APInt &ExpectedPhiValue = ExpectedValue->getValue();
97
98 // Walk up in backward a list of instructions that
99 // have 'copy' semantics by 'stripping' the copies
100 // until a PHI node or an instruction of unknown kind
101 // is reached. Negation via xor is also handled.
102 //
103 // C = PHI(...);
104 // B = C;
105 // A = B;
106 // D = __builtin_expect(A, 0);
107 //
108 Value *V = &Arg;
109 SmallVector Operations;
110 while (!isa(V)) {
111 if (ZExtInst *ZExt = dyn_cast(V)) {
112 V = ZExt->getOperand(0);
113 Operations.push_back(ZExt);
114 continue;
115 }
116
117 if (SExtInst *SExt = dyn_cast(V)) {
118 V = SExt->getOperand(0);
119 Operations.push_back(SExt);
120 continue;
121 }
122
123 BinaryOperator *BinOp = dyn_cast(V);
124 if (!BinOp || BinOp->getOpcode() != Instruction::Xor)
125 return;
126
127 ConstantInt *CInt = dyn_cast(BinOp->getOperand(1));
128 if (!CInt)
129 return;
130
131 V = BinOp->getOperand(0);
132 Operations.push_back(BinOp);
133 }
134
135 // Executes the recorded operations on input 'Value'.
136 auto ApplyOperations = [&](const APInt &Value) {
137 APInt Result = Value;
138 for (auto Op : llvm::reverse(Operations)) {
139 switch (Op->getOpcode()) {
140 case Instruction::Xor:
141 Result ^= cast(Op->getOperand(1))->getValue();
142 break;
143 case Instruction::ZExt:
144 Result = Result.zext(Op->getType()->getIntegerBitWidth());
145 break;
146 case Instruction::SExt:
147 Result = Result.sext(Op->getType()->getIntegerBitWidth());
148 break;
149 default:
150 llvm_unreachable("Unexpected operation");
151 }
152 }
153 return Result;
154 };
155
156 auto *PhiDef = dyn_cast(V);
157
158 // Get the first dominating conditional branch of the operand
159 // i's incoming block.
160 auto GetDomConditional = [&](unsigned i) -> BranchInst * {
161 BasicBlock *BB = PhiDef->getIncomingBlock(i);
162 BranchInst *BI = dyn_cast(BB->getTerminator());
163 if (BI && BI->isConditional())
164 return BI;
165 BB = BB->getSinglePredecessor();
166 if (!BB)
167 return nullptr;
168 BI = dyn_cast(BB->getTerminator());
169 if (!BI || BI->isUnconditional())
170 return nullptr;
171 return BI;
172 };
173
174 // Now walk through all Phi operands to find phi oprerands with values
175 // conflicting with the expected phi output value. Any such operand
176 // indicates the incoming edge to that operand is unlikely.
177 for (unsigned i = 0, e = PhiDef->getNumIncomingValues(); i != e; ++i) {
178
179 Value *PhiOpnd = PhiDef->getIncomingValue(i);
180 ConstantInt *CI = dyn_cast(PhiOpnd);
181 if (!CI)
182 continue;
183
184 // Not an interesting case when IsUnlikely is false -- we can not infer
185 // anything useful when the operand value matches the expected phi
186 // output.
187 if (ExpectedPhiValue == ApplyOperations(CI->getValue()))
188 continue;
189
190 BranchInst *BI = GetDomConditional(i);
191 if (!BI)
192 continue;
193
194 MDBuilder MDB(PhiDef->getContext());
195
196 // There are two situations in which an operand of the PhiDef comes
197 // from a given successor of a branch instruction BI.
198 // 1) When the incoming block of the operand is the successor block;
199 // 2) When the incoming block is BI's enclosing block and the
200 // successor is the PhiDef's enclosing block.
201 //
202 // Returns true if the operand which comes from OpndIncomingBB
203 // comes from outgoing edge of BI that leads to Succ block.
204 auto *OpndIncomingBB = PhiDef->getIncomingBlock(i);
205 auto IsOpndComingFromSuccessor = [&](BasicBlock *Succ) {
206 if (OpndIncomingBB == Succ)
207 // If this successor is the incoming block for this
208 // Phi operand, then this successor does lead to the Phi.
209 return true;
210 if (OpndIncomingBB == BI->getParent() && Succ == PhiDef->getParent())
211 // Otherwise, if the edge is directly from the branch
212 // to the Phi, this successor is the one feeding this
213 // Phi operand.
214 return true;
215 return false;
216 };
217
218 if (IsOpndComingFromSuccessor(BI->getSuccessor(1)))
219 BI->setMetadata(
220 LLVMContext::MD_prof,
221 MDB.createBranchWeights(LikelyBranchWeight, UnlikelyBranchWeight));
222 else if (IsOpndComingFromSuccessor(BI->getSuccessor(0)))
223 BI->setMetadata(
224 LLVMContext::MD_prof,
225 MDB.createBranchWeights(UnlikelyBranchWeight, LikelyBranchWeight));
226 }
83227 }
84228
85229 // Handle both BranchInst and SelectInst.
186330
187331 Function *Fn = CI->getCalledFunction();
188332 if (Fn && Fn->getIntrinsicID() == Intrinsic::expect) {
333 // Before erasing the llvm.expect, walk backward to find
334 // phi that define llvm.expect's first arg, and
335 // infer branch probability:
336 handlePhiDef(CI);
189337 Value *Exp = CI->getArgOperand(0);
190338 CI->replaceAllUsesWith(Exp);
191339 CI->eraseFromParent();
0 ; RUN: opt -lower-expect -S -o - < %s | FileCheck %s
1 ; RUN: opt -S -passes='function(lower-expect)' < %s | FileCheck %s
2
3 ; The C case
4 ; if (__builtin_expect((x > goo() && y > hoo() && z > too()), 1))
5 ; For the above case, all 3 branches should be annotated.
6 ;
7 ; if (__builtin_expect((x > goo() && y > hoo() && z > too()), 0))
8 ; For the above case, we don't have enough information, so
9 ; only the last branch is annotated.
10
11 define void @foo(i32 %arg, i32 %arg1, i32 %arg2, i32 %arg3) {
12 ; CHECK-LABEL: void @foo
13 bb:
14 %tmp8 = call i32 @goo()
15 %tmp9 = icmp sgt i32 %tmp8, %arg
16 br i1 %tmp9, label %bb10, label %bb18
17 ; CHECK: !prof [[WEIGHT:![0-9]+]]
18
19 bb10: ; preds = %bb
20 %tmp12 = call i32 @hoo()
21 %tmp13 = icmp sgt i32 %arg1, %tmp12
22 br i1 %tmp13, label %bb14, label %bb18
23 ; CHECK: br i1 %tmp13, {{.*}}!prof [[WEIGHT]]
24
25 bb14: ; preds = %bb10
26 %tmp16 = call i32 @too()
27 %tmp17 = icmp sgt i32 %arg2, %tmp16
28 br label %bb18
29
30 bb18: ; preds = %bb14, %bb10, %bb
31 %tmp19 = phi i1 [ false, %bb10 ], [ false, %bb ], [ %tmp17, %bb14 ]
32 %tmp20 = xor i1 %tmp19, true
33 %tmp21 = xor i1 %tmp20, true
34 %tmp22 = zext i1 %tmp21 to i32
35 %tmp23 = sext i32 %tmp22 to i64
36 %tmp24 = call i64 @llvm.expect.i64(i64 %tmp23, i64 1)
37 %tmp25 = icmp ne i64 %tmp24, 0
38 br i1 %tmp25, label %bb26, label %bb28
39 ; CHECK: br i1 %tmp25,{{.*}}!prof [[WEIGHT]]
40
41 bb26: ; preds = %bb18
42 %tmp27 = call i32 @goo()
43 br label %bb30
44
45 bb28: ; preds = %bb18
46 %tmp29 = call i32 @hoo()
47 br label %bb30
48
49 bb30: ; preds = %bb28, %bb26
50 ret void
51 }
52
53 define void @foo2(i32 %arg, i32 %arg1, i32 %arg2, i32 %arg3) {
54 ; CHECK-LABEL: void @foo2
55 bb:
56 %tmp8 = call i32 @goo()
57 %tmp9 = icmp sgt i32 %tmp8, %arg
58 br i1 %tmp9, label %bb10, label %bb18
59 ; CHECK: br i1 %tmp9
60 ; CHECK-NOT: !prof
61
62 bb10: ; preds = %bb
63 %tmp12 = call i32 @hoo()
64 %tmp13 = icmp sgt i32 %arg1, %tmp12
65 br i1 %tmp13, label %bb14, label %bb18
66 ; CHECK: br i1 %tmp13
67 ; CHECK-NOT: !prof
68
69 bb14: ; preds = %bb10
70 %tmp16 = call i32 @too()
71 %tmp17 = icmp sgt i32 %arg2, %tmp16
72 br label %bb18
73
74 bb18: ; preds = %bb14, %bb10, %bb
75 %tmp19 = phi i1 [ false, %bb10 ], [ false, %bb ], [ %tmp17, %bb14 ]
76 %tmp20 = xor i1 %tmp19, true
77 %tmp21 = xor i1 %tmp20, true
78 %tmp22 = zext i1 %tmp21 to i32
79 %tmp23 = sext i32 %tmp22 to i64
80 %tmp24 = call i64 @llvm.expect.i64(i64 %tmp23, i64 0)
81 %tmp25 = icmp ne i64 %tmp24, 0
82 br i1 %tmp25, label %bb26, label %bb28
83 ; CHECK: br i1 %tmp25,{{.*}}!prof [[WEIGHT2:![0-9]+]]
84
85 bb26: ; preds = %bb18
86 %tmp27 = call i32 @goo()
87 br label %bb30
88
89 bb28: ; preds = %bb18
90 %tmp29 = call i32 @hoo()
91 br label %bb30
92
93 bb30: ; preds = %bb28, %bb26
94 ret void
95 }
96
97 define void @foo_i32(i32 %arg, i32 %arg1, i32 %arg2, i32 %arg3) {
98 ; CHECK-LABEL: void @foo_i32
99 bb:
100 %tmp8 = call i32 @goo()
101 %tmp9 = icmp sgt i32 %tmp8, %arg
102 br i1 %tmp9, label %bb10, label %bb18
103 ; CHECK: !prof [[WEIGHT]]
104
105 bb10: ; preds = %bb
106 %tmp12 = call i32 @hoo()
107 %tmp13 = icmp sgt i32 %arg1, %tmp12
108 br i1 %tmp13, label %bb14, label %bb18
109 ; CHECK: br i1 %tmp13, {{.*}}!prof [[WEIGHT]]
110
111 bb14: ; preds = %bb10
112 %tmp16 = call i32 @too()
113 %tmp17 = icmp sgt i32 %arg2, %tmp16
114 br label %bb18
115
116 bb18: ; preds = %bb14, %bb10, %bb
117 %tmp19 = phi i32 [ 5, %bb10 ], [ 5, %bb ], [ %tmp16, %bb14 ]
118 %tmp23 = sext i32 %tmp19 to i64
119 %tmp24 = call i64 @llvm.expect.i64(i64 %tmp23, i64 4)
120 %tmp25 = icmp ne i64 %tmp24, 0
121 br i1 %tmp25, label %bb26, label %bb28
122 ; CHECK: br i1 %tmp25,{{.*}}!prof [[WEIGHT]]
123
124 bb26: ; preds = %bb18
125 %tmp27 = call i32 @goo()
126 br label %bb30
127
128 bb28: ; preds = %bb18
129 %tmp29 = call i32 @hoo()
130 br label %bb30
131
132 bb30: ; preds = %bb28, %bb26
133 ret void
134 }
135
136
137 define void @foo_i32_not_unlikely(i32 %arg, i32 %arg1, i32 %arg2, i32 %arg3) {
138 ; CHECK-LABEL: void @foo_i32_not_unlikely
139 bb:
140 %tmp8 = call i32 @goo()
141 %tmp9 = icmp sgt i32 %tmp8, %arg
142 br i1 %tmp9, label %bb10, label %bb18
143 ; CHECK: br i1 %tmp9
144 ; CHECK-NOT: !prof
145
146 bb10: ; preds = %bb
147 %tmp12 = call i32 @hoo()
148 %tmp13 = icmp sgt i32 %arg1, %tmp12
149 br i1 %tmp13, label %bb14, label %bb18
150 ; CHECK: br i1 %tmp13
151 ; CHECK-NOT: !prof
152
153 bb14: ; preds = %bb10
154 %tmp16 = call i32 @too()
155 %tmp17 = icmp sgt i32 %arg2, %tmp16
156 br label %bb18
157
158 bb18: ; preds = %bb14, %bb10, %bb
159 %tmp19 = phi i32 [ 4, %bb10 ], [ 4, %bb ], [ %tmp16, %bb14 ]
160 %tmp23 = sext i32 %tmp19 to i64
161 %tmp24 = call i64 @llvm.expect.i64(i64 %tmp23, i64 4)
162 %tmp25 = icmp ne i64 %tmp24, 0
163 br i1 %tmp25, label %bb26, label %bb28
164 ; CHECK: br i1 %tmp25,{{.*}}!prof [[WEIGHT]]
165
166 bb26: ; preds = %bb18
167 %tmp27 = call i32 @goo()
168 br label %bb30
169
170 bb28: ; preds = %bb18
171 %tmp29 = call i32 @hoo()
172 br label %bb30
173
174 bb30: ; preds = %bb28, %bb26
175 ret void
176 }
177
178 define void @foo_i32_xor(i32 %arg, i32 %arg1, i32 %arg2, i32 %arg3) {
179 ; CHECK-LABEL: void @foo_i32_xor
180 bb:
181 %tmp8 = call i32 @goo()
182 %tmp9 = icmp sgt i32 %tmp8, %arg
183 br i1 %tmp9, label %bb10, label %bb18
184 ; CHECK: br i1 %tmp9,{{.*}}!prof [[WEIGHT]]
185
186 bb10: ; preds = %bb
187 %tmp12 = call i32 @hoo()
188 %tmp13 = icmp sgt i32 %arg1, %tmp12
189 br i1 %tmp13, label %bb14, label %bb18
190 ; CHECK: br i1 %tmp13,{{.*}}!prof [[WEIGHT]]
191
192 bb14: ; preds = %bb10
193 %tmp16 = call i32 @too()
194 %tmp17 = icmp sgt i32 %arg2, %tmp16
195 br label %bb18
196
197 bb18: ; preds = %bb14, %bb10, %bb
198 %tmp19 = phi i32 [ 6, %bb10 ], [ 6, %bb ], [ %tmp16, %bb14 ]
199 %tmp20 = xor i32 %tmp19, 3
200 %tmp23 = sext i32 %tmp20 to i64
201 %tmp24 = call i64 @llvm.expect.i64(i64 %tmp23, i64 4)
202 %tmp25 = icmp ne i64 %tmp24, 0
203 br i1 %tmp25, label %bb26, label %bb28
204 ; CHECK: br i1 %tmp25,{{.*}}!prof [[WEIGHT]]
205
206 bb26: ; preds = %bb18
207 %tmp27 = call i32 @goo()
208 br label %bb30
209
210 bb28: ; preds = %bb18
211 %tmp29 = call i32 @hoo()
212 br label %bb30
213 bb30: ; preds = %bb28, %bb26
214 ret void
215 }
216
217 define void @foo_i8_sext(i32 %arg, i32 %arg1, i8 %arg2, i32 %arg3) {
218 ; CHECK-LABEL: void @foo_i8_sext
219 bb:
220 %tmp8 = call i32 @goo()
221 %tmp9 = icmp sgt i32 %tmp8, %arg
222 br i1 %tmp9, label %bb10, label %bb18
223 ; CHECK: br i1 %tmp9,{{.*}}!prof [[WEIGHT]]
224
225 bb10: ; preds = %bb
226 %tmp12 = call i32 @hoo()
227 %tmp13 = icmp sgt i32 %arg1, %tmp12
228 br i1 %tmp13, label %bb14, label %bb18
229 ; CHECK: br i1 %tmp13,{{.*}}!prof [[WEIGHT]]
230
231 bb14: ; preds = %bb10
232 %tmp16 = call i8 @too8()
233 %tmp17 = icmp sgt i8 %arg2, %tmp16
234 br label %bb18
235
236 bb18: ; preds = %bb14, %bb10, %bb
237 %tmp19 = phi i8 [ 255, %bb10 ], [ 255, %bb ], [ %tmp16, %bb14 ]
238 %tmp23 = sext i8 %tmp19 to i64
239 ; after sign extension, the operand value becomes -1 which does not match 255
240 %tmp24 = call i64 @llvm.expect.i64(i64 %tmp23, i64 255)
241 %tmp25 = icmp ne i64 %tmp24, 0
242 br i1 %tmp25, label %bb26, label %bb28
243 ; CHECK: br i1 %tmp25,{{.*}}!prof [[WEIGHT]]
244
245 bb26: ; preds = %bb18
246 %tmp27 = call i32 @goo()
247 br label %bb30
248
249 bb28: ; preds = %bb18
250 %tmp29 = call i32 @hoo()
251 br label %bb30
252 bb30: ; preds = %bb28, %bb26
253 ret void
254 }
255
256 define void @foo_i8_sext_not_unlikely(i32 %arg, i32 %arg1, i8 %arg2, i32 %arg3) {
257 ; CHECK-LABEL: void @foo_i8_sext_not_unlikely
258 bb:
259 %tmp8 = call i32 @goo()
260 %tmp9 = icmp sgt i32 %tmp8, %arg
261 br i1 %tmp9, label %bb10, label %bb18
262 ; CHECK: br i1 %tmp9
263 ; CHECK-NOT: !prof
264
265 bb10: ; preds = %bb
266 %tmp12 = call i32 @hoo()
267 %tmp13 = icmp sgt i32 %arg1, %tmp12
268 br i1 %tmp13, label %bb14, label %bb18
269 ; CHECK: br i1 %tmp13
270 ; CHECK-NOT: !prof
271
272 bb14: ; preds = %bb10
273 %tmp16 = call i8 @too8()
274 %tmp17 = icmp sgt i8 %arg2, %tmp16
275 br label %bb18
276
277 bb18: ; preds = %bb14, %bb10, %bb
278 %tmp19 = phi i8 [ 255, %bb10 ], [ 255, %bb ], [ %tmp16, %bb14 ]
279 %tmp23 = sext i8 %tmp19 to i64
280 ; after sign extension, the operand value becomes -1 which matches -1
281 %tmp24 = call i64 @llvm.expect.i64(i64 %tmp23, i64 -1)
282 %tmp25 = icmp ne i64 %tmp24, 0
283 br i1 %tmp25, label %bb26, label %bb28
284 ; CHECK: br i1 %tmp25,{{.*}}!prof [[WEIGHT]]
285
286 bb26: ; preds = %bb18
287 %tmp27 = call i32 @goo()
288 br label %bb30
289
290 bb28: ; preds = %bb18
291 %tmp29 = call i32 @hoo()
292 br label %bb30
293 bb30: ; preds = %bb28, %bb26
294 ret void
295 }
296
297
298 define void @foo_i32_xor_not_unlikely(i32 %arg, i32 %arg1, i32 %arg2, i32 %arg3) {
299 ; CHECK-LABEL: void @foo_i32_xor_not_unlikely
300 bb:
301 %tmp8 = call i32 @goo()
302 %tmp9 = icmp sgt i32 %tmp8, %arg
303 br i1 %tmp9, label %bb10, label %bb18
304 ; CHECK: br i1 %tmp9
305 ; CHECK-NOT: !prof
306
307 bb10: ; preds = %bb
308 %tmp12 = call i32 @hoo()
309 %tmp13 = icmp sgt i32 %arg1, %tmp12
310 br i1 %tmp13, label %bb14, label %bb18
311 ; CHECK: br i1 %tmp13
312 ; CHECK-NOT: !prof
313
314 bb14: ; preds = %bb10
315 %tmp16 = call i32 @too()
316 %tmp17 = icmp sgt i32 %arg2, %tmp16
317 br label %bb18
318
319 bb18: ; preds = %bb14, %bb10, %bb
320 %tmp19 = phi i32 [ 6, %bb10 ], [ 6, %bb ], [ %tmp16, %bb14 ]
321 %tmp20 = xor i32 %tmp19, 2
322 %tmp23 = sext i32 %tmp20 to i64
323 %tmp24 = call i64 @llvm.expect.i64(i64 %tmp23, i64 4)
324 %tmp25 = icmp ne i64 %tmp24, 0
325 br i1 %tmp25, label %bb26, label %bb28
326 ; CHECK: br i1 %tmp25,{{.*}}!prof [[WEIGHT]]
327
328 bb26: ; preds = %bb18
329 %tmp27 = call i32 @goo()
330 br label %bb30
331
332 bb28: ; preds = %bb18
333 %tmp29 = call i32 @hoo()
334 br label %bb30
335
336 bb30: ; preds = %bb28, %bb26
337 ret void
338 }
339
340 declare i32 @goo()
341
342 declare i32 @hoo()
343
344 declare i32 @too()
345
346 declare i8 @too8()
347
348 ; Function Attrs: nounwind readnone
349 declare i64 @llvm.expect.i64(i64, i64)
350
351 !llvm.ident = !{!0}
352
353 !0 = !{!"clang version 5.0.0 (trunk 302965)"}
354 ; CHECK: [[WEIGHT]] = !{!"branch_weights", i32 2000, i32 1}
355 ; CHECK: [[WEIGHT2]] = !{!"branch_weights", i32 1, i32 2000}
0 ; RUN: opt -lower-expect -S -o - < %s | FileCheck %s
1 ; RUN: opt -S -passes='function(lower-expect)' < %s | FileCheck %s
2 ;
3 ; if (__builtin_expect((x > goo() || y > hoo()), 1)) {
4 ; ..
5 ; }
6 ; For the above case, only the second branch should be
7 ; annotated.
8 ; if (__builtin_expect((x > goo() || y > hoo()), 0)) {
9 ; ..
10 ; }
11 ; For the above case, two branches should be annotated.
12 ; Function Attrs: noinline nounwind uwtable
13 define void @foo(i32 %arg, i32 %arg1, i32 %arg2, i32 %arg3) {
14 ; CHECK-LABEL: void @foo
15 bb:
16 %tmp8 = call i32 @goo()
17 %tmp9 = icmp slt i32 %arg, %tmp8
18 br i1 %tmp9, label %bb14, label %bb10
19 ; CHECK: br i1 %tmp9
20 ; CHECK-NOT: br i1 %tmp9{{.*}}!prof
21
22 bb10: ; preds = %bb
23 %tmp12 = call i32 @hoo()
24 %tmp13 = icmp sgt i32 %arg1, %tmp12
25 br label %bb14
26
27 bb14: ; preds = %bb10, %bb
28 %tmp15 = phi i1 [ true, %bb ], [ %tmp13, %bb10 ]
29 %tmp16 = zext i1 %tmp15 to i32
30 %tmp17 = sext i32 %tmp16 to i64
31 %expect = call i64 @llvm.expect.i64(i64 %tmp17, i64 1)
32 %tmp18 = icmp ne i64 %expect, 0
33 br i1 %tmp18, label %bb19, label %bb21
34 ; CHECK: br i1 %tmp18{{.*}}!prof [[WEIGHT:![0-9]+]]
35
36 bb19: ; preds = %bb14
37 %tmp20 = call i32 @goo()
38 br label %bb23
39
40 bb21: ; preds = %bb14
41 %tmp22 = call i32 @hoo()
42 br label %bb23
43
44 bb23: ; preds = %bb21, %bb19
45 ret void
46 }
47
48 define void @foo2(i32 %arg, i32 %arg1, i32 %arg2, i32 %arg3) {
49 ; CHECK-LABEL: void @foo2
50 bb:
51 %tmp = alloca i32, align 4
52 %tmp4 = alloca i32, align 4
53 %tmp5 = alloca i32, align 4
54 %tmp6 = alloca i32, align 4
55 store i32 %arg, i32* %tmp, align 4
56 store i32 %arg1, i32* %tmp4, align 4
57 store i32 %arg2, i32* %tmp5, align 4
58 store i32 %arg3, i32* %tmp6, align 4
59 %tmp7 = load i32, i32* %tmp, align 4
60 %tmp8 = call i32 @goo()
61 %tmp9 = icmp slt i32 %tmp7, %tmp8
62 br i1 %tmp9, label %bb14, label %bb10
63 ; CHECK: br i1 %tmp9{{.*}}!prof [[WEIGHT2:![0-9]+]]
64
65 bb10: ; preds = %bb
66 %tmp11 = load i32, i32* %tmp5, align 4
67 %tmp12 = call i32 @hoo()
68 %tmp13 = icmp sgt i32 %tmp11, %tmp12
69 br label %bb14
70
71 bb14: ; preds = %bb10, %bb
72 %tmp15 = phi i1 [ true, %bb ], [ %tmp13, %bb10 ]
73 %tmp16 = zext i1 %tmp15 to i32
74 %tmp17 = sext i32 %tmp16 to i64
75 %expect = call i64 @llvm.expect.i64(i64 %tmp17, i64 0)
76 %tmp18 = icmp ne i64 %expect, 0
77 br i1 %tmp18, label %bb19, label %bb21
78 ; CHECK: br i1 %tmp18{{.*}}!prof [[WEIGHT2]]
79
80 bb19: ; preds = %bb14
81 %tmp20 = call i32 @goo()
82 br label %bb23
83
84 bb21: ; preds = %bb14
85 %tmp22 = call i32 @hoo()
86 br label %bb23
87
88 bb23: ; preds = %bb21, %bb19
89 ret void
90 }
91
92 declare i32 @goo()
93 declare i32 @hoo()
94 declare i64 @llvm.expect.i64(i64, i64)
95
96
97 !llvm.ident = !{!0}
98
99
100 !0 = !{!"clang version 5.0.0 (trunk 302965)"}
101 ; CHECK: [[WEIGHT]] = !{!"branch_weights", i32 2000, i32 1}
102 ; CHECK: [[WEIGHT2]] = !{!"branch_weights", i32 1, i32 2000}
0 ; RUN: opt -lower-expect -S -o - < %s | FileCheck %s
1 ; RUN: opt -S -passes='function(lower-expect)' < %s | FileCheck %s
2
3 ; return __builtin_expect((a > b ? 1, goo(), 0);
4 ;
5 ; Function Attrs: noinline nounwind uwtable
6 define i32 @foo(i32 %arg, i32 %arg1) {
7 ; CHECK-LABEL: i32 @foo
8 bb:
9 %tmp5 = icmp sgt i32 %arg, %arg1
10 br i1 %tmp5, label %bb9, label %bb7
11 ; CHECK: br i1 %tmp5{{.*}}!prof [[WEIGHT:![0-9]+]]
12
13 bb7: ; preds = %bb
14 %tmp8 = call i32 @goo()
15 br label %bb9
16
17 bb9: ; preds = %bb7, %bb9
18 %tmp10 = phi i32 [ 1, %bb ], [ %tmp8, %bb7 ]
19 %tmp11 = sext i32 %tmp10 to i64
20 %expect = call i64 @llvm.expect.i64(i64 %tmp11, i64 0)
21 %tmp12 = trunc i64 %expect to i32
22 ret i32 %tmp12
23 }
24
25 define i32 @foo2(i32 %arg, i32 %arg1) {
26 bb:
27 %tmp5 = icmp sgt i32 %arg, %arg1
28 br i1 %tmp5, label %bb6, label %bb7
29 ; CHECK: br i1 %tmp5{{.*}}!prof [[WEIGHT:![0-9]+]]
30
31 bb6: ; preds = %bb
32 br label %bb9
33
34 bb7: ; preds = %bb
35 %tmp8 = call i32 @goo()
36 br label %bb9
37
38 bb9: ; preds = %bb7, %bb6
39 %tmp10 = phi i32 [ 1, %bb6 ], [ %tmp8, %bb7 ]
40 %tmp11 = sext i32 %tmp10 to i64
41 %expect = call i64 @llvm.expect.i64(i64 %tmp11, i64 0)
42 %tmp12 = trunc i64 %expect to i32
43 ret i32 %tmp12
44 }
45
46 declare i32 @goo()
47 declare i64 @llvm.expect.i64(i64, i64)
48
49
50
51 !llvm.ident = !{!0}
52
53 !0 = !{!"clang version 5.0.0 (trunk 302965)"}
54
55 ; CHECK: [[WEIGHT]] = !{!"branch_weights", i32 1, i32 2000}