5848eddf4375f20985648068fe17d0d94a9799d4
[oota-llvm.git] / test / CodeGen / X86 / x86-shrink-wrapping.ll
1 ; RUN: llc %s -o - -enable-shrink-wrap=true | FileCheck %s --check-prefix=CHECK --check-prefix=ENABLE
2 ; RUN: llc %s -o - -enable-shrink-wrap=false | FileCheck %s --check-prefix=CHECK --check-prefix=DISABLE
3 ;
4 ; Note: Lots of tests use inline asm instead of regular calls.
5 ; This allows to have a better control on what the allocation will do.
6 ; Otherwise, we may have spill right in the entry block, defeating
7 ; shrink-wrapping. Moreover, some of the inline asm statement (nop)
8 ; are here to ensure that the related paths do not end up as critical
9 ; edges.
10 target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128"
11 target triple = "x86_64-apple-macosx"
12
13
14 ; Initial motivating example: Simple diamond with a call just on one side.
15 ; CHECK-LABEL: foo:
16 ;
17 ; Compare the arguments and jump to exit.
18 ; No prologue needed.
19 ; ENABLE: movl %edi, [[ARG0CPY:%e[a-z]+]]
20 ; ENABLE-NEXT: cmpl %esi, [[ARG0CPY]]
21 ; ENABLE-NEXT: jge [[EXIT_LABEL:LBB[0-9_]+]]
22 ;
23 ; Prologue code.
24 ; (What we push does not matter. It should be some random sratch register.)
25 ; CHECK: pushq
26 ;
27 ; Compare the arguments and jump to exit.
28 ; After the prologue is set.
29 ; DISABLE: movl %edi, [[ARG0CPY:%e[a-z]+]]
30 ; DISABLE-NEXT: cmpl %esi, [[ARG0CPY]]
31 ; DISABLE-NEXT: jge [[EXIT_LABEL:LBB[0-9_]+]]
32 ;
33 ; Store %a in the alloca.
34 ; CHECK: movl [[ARG0CPY]], 4(%rsp)
35 ; Set the alloca address in the second argument.
36 ; CHECK-NEXT: leaq 4(%rsp), %rsi
37 ; Set the first argument to zero.
38 ; CHECK-NEXT: xorl %edi, %edi
39 ; CHECK-NEXT: callq _doSomething
40 ;
41 ; With shrink-wrapping, epilogue is just after the call.
42 ; ENABLE-NEXT: addq $8, %rsp
43 ;
44 ; CHECK: [[EXIT_LABEL]]:
45 ;
46 ; Without shrink-wrapping, epilogue is in the exit block.
47 ; Epilogue code. (What we pop does not matter.)
48 ; DISABLE-NEXT: popq
49 ;
50 ; CHECK-NEXT: retq
51 define i32 @foo(i32 %a, i32 %b) {
52   %tmp = alloca i32, align 4
53   %tmp2 = icmp slt i32 %a, %b
54   br i1 %tmp2, label %true, label %false
55
56 true:
57   store i32 %a, i32* %tmp, align 4
58   %tmp4 = call i32 @doSomething(i32 0, i32* %tmp)
59   br label %false
60
61 false:
62   %tmp.0 = phi i32 [ %tmp4, %true ], [ %a, %0 ]
63   ret i32 %tmp.0
64 }
65
66 ; Function Attrs: optsize
67 declare i32 @doSomething(i32, i32*)
68
69
70 ; Check that we do not perform the restore inside the loop whereas the save
71 ; is outside.
72 ; CHECK-LABEL: freqSaveAndRestoreOutsideLoop:
73 ;
74 ; Shrink-wrapping allows to skip the prologue in the else case.
75 ; ENABLE: testl %edi, %edi  
76 ; ENABLE: je [[ELSE_LABEL:LBB[0-9_]+]]
77 ;
78 ; Prologue code.
79 ; Make sure we save the CSR used in the inline asm: rbx.
80 ; CHECK: pushq %rbx
81 ;
82 ; DISABLE: testl %edi, %edi
83 ; DISABLE: je [[ELSE_LABEL:LBB[0-9_]+]]
84 ;
85 ; SUM is in %esi because it is coalesced with the second
86 ; argument on the else path.
87 ; CHECK: xorl [[SUM:%esi]], [[SUM]]
88 ; CHECK-NEXT: movl $10, [[IV:%e[a-z]+]]
89 ;
90 ; Next BB.
91 ; CHECK: [[LOOP:LBB[0-9_]+]]: ## %for.body
92 ; CHECK: movl $1, [[TMP:%e[a-z]+]]
93 ; CHECK: addl [[TMP]], [[SUM]]
94 ; CHECK-NEXT: decl [[IV]]
95 ; CHECK-NEXT: jne [[LOOP]]
96 ;
97 ; Next BB.
98 ; SUM << 3.
99 ; CHECK: shll $3, [[SUM]]
100 ;
101 ; Jump to epilogue.
102 ; DISABLE: jmp [[EPILOG_BB:LBB[0-9_]+]]
103 ;
104 ; DISABLE: [[ELSE_LABEL]]: ## %if.else
105 ; Shift second argument by one and store into returned register.
106 ; DISABLE: addl %esi, %esi
107 ; DISABLE: [[EPILOG_BB]]: ## %if.end
108 ;
109 ; Epilogue code.
110 ; CHECK-DAG: popq %rbx
111 ; CHECK-DAG: movl %esi, %eax
112 ; CHECK: retq
113 ;
114 ; ENABLE: [[ELSE_LABEL]]: ## %if.else
115 ; Shift second argument by one and store into returned register.
116 ; ENABLE: addl %esi, %esi
117 ; ENABLE-NEXT: movl %esi, %eax
118 ; ENABLE-NEXT: retq
119 define i32 @freqSaveAndRestoreOutsideLoop(i32 %cond, i32 %N) {
120 entry:
121   %tobool = icmp eq i32 %cond, 0
122   br i1 %tobool, label %if.else, label %for.preheader
123
124 for.preheader:
125   tail call void asm "nop", ""()
126   br label %for.body
127
128 for.body:                                         ; preds = %entry, %for.body
129   %i.05 = phi i32 [ %inc, %for.body ], [ 0, %for.preheader ]
130   %sum.04 = phi i32 [ %add, %for.body ], [ 0, %for.preheader ]
131   %call = tail call i32 asm "movl $$1, $0", "=r,~{ebx}"()
132   %add = add nsw i32 %call, %sum.04
133   %inc = add nuw nsw i32 %i.05, 1
134   %exitcond = icmp eq i32 %inc, 10
135   br i1 %exitcond, label %for.end, label %for.body
136
137 for.end:                                          ; preds = %for.body
138   %shl = shl i32 %add, 3
139   br label %if.end
140
141 if.else:                                          ; preds = %entry
142   %mul = shl nsw i32 %N, 1
143   br label %if.end
144
145 if.end:                                           ; preds = %if.else, %for.end
146   %sum.1 = phi i32 [ %shl, %for.end ], [ %mul, %if.else ]
147   ret i32 %sum.1
148 }
149
150 declare i32 @something(...)
151
152 ; Check that we do not perform the shrink-wrapping inside the loop even
153 ; though that would be legal. The cost model must prevent that.
154 ; CHECK-LABEL: freqSaveAndRestoreOutsideLoop2:
155 ; Prologue code.
156 ; Make sure we save the CSR used in the inline asm: rbx.
157 ; CHECK: pushq %rbx
158 ; CHECK: nop
159 ; CHECK: xorl [[SUM:%e[a-z]+]], [[SUM]]
160 ; CHECK-NEXT: movl $10, [[IV:%e[a-z]+]]
161 ; Next BB.
162 ; CHECK: [[LOOP_LABEL:LBB[0-9_]+]]: ## %for.body
163 ; CHECK: movl $1, [[TMP:%e[a-z]+]]
164 ; CHECK: addl [[TMP]], [[SUM]]
165 ; CHECK-NEXT: decl [[IV]]
166 ; CHECK-NEXT: jne [[LOOP_LABEL]]
167 ; Next BB.
168 ; CHECK: ## %for.exit
169 ; CHECK: nop
170 ; CHECK: popq %rbx
171 ; CHECK-NEXT: retq
172 define i32 @freqSaveAndRestoreOutsideLoop2(i32 %cond) {
173 entry:
174   br label %for.preheader
175
176 for.preheader:
177   tail call void asm "nop", ""()
178   br label %for.body
179
180 for.body:                                         ; preds = %for.body, %entry
181   %i.04 = phi i32 [ 0, %for.preheader ], [ %inc, %for.body ]
182   %sum.03 = phi i32 [ 0, %for.preheader ], [ %add, %for.body ]
183   %call = tail call i32 asm "movl $$1, $0", "=r,~{ebx}"()
184   %add = add nsw i32 %call, %sum.03
185   %inc = add nuw nsw i32 %i.04, 1
186   %exitcond = icmp eq i32 %inc, 10
187   br i1 %exitcond, label %for.exit, label %for.body
188
189 for.exit:
190   tail call void asm "nop", ""()
191   br label %for.end
192
193 for.end:                                          ; preds = %for.body
194   ret i32 %add
195 }
196
197 ; Check with a more complex case that we do not have save within the loop and
198 ; restore outside.
199 ; CHECK-LABEL: loopInfoSaveOutsideLoop:
200 ;
201 ; ENABLE: testl %edi, %edi
202 ; ENABLE-NEXT: je [[ELSE_LABEL:LBB[0-9_]+]]
203 ;
204 ; Prologue code.
205 ; Make sure we save the CSR used in the inline asm: rbx.
206 ; CHECK: pushq %rbx
207 ;
208 ; DISABLE: testl %edi, %edi
209 ; DISABLE-NEXT: je [[ELSE_LABEL:LBB[0-9_]+]]
210 ;
211 ; CHECK: nop
212 ; CHECK: xorl [[SUM:%esi]], [[SUM]]
213 ; CHECK-NEXT: movl $10, [[IV:%e[a-z]+]]
214 ;
215 ; CHECK: [[LOOP_LABEL:LBB[0-9_]+]]: ## %for.body
216 ; CHECK: movl $1, [[TMP:%e[a-z]+]]
217 ; CHECK: addl [[TMP]], [[SUM]]
218 ; CHECK-NEXT: decl [[IV]]
219 ; CHECK-NEXT: jne [[LOOP_LABEL]]
220 ; Next BB.
221 ; CHECK: nop
222 ; CHECK: shll $3, [[SUM]]
223 ;
224 ; DISABLE: jmp [[EPILOG_BB:LBB[0-9_]+]]
225 ;
226 ; DISABLE: [[ELSE_LABEL]]: ## %if.else
227 ; Shift second argument by one and store into returned register.
228 ; DISABLE: addl %esi, %esi
229 ; DISABLE: [[EPILOG_BB]]: ## %if.end
230 ;
231 ; Epilogue code.
232 ; CHECK-DAG: popq %rbx
233 ; CHECK-DAG: movl %esi, %eax
234 ; CHECK: retq
235 ;
236 ; ENABLE: [[ELSE_LABEL]]: ## %if.else
237 ; Shift second argument by one and store into returned register.
238 ; ENABLE: addl %esi, %esi
239 ; ENABLE-NEXT: movl %esi, %eax
240 ; ENABLE-NEXT: retq
241 define i32 @loopInfoSaveOutsideLoop(i32 %cond, i32 %N) {
242 entry:
243   %tobool = icmp eq i32 %cond, 0
244   br i1 %tobool, label %if.else, label %for.preheader
245
246 for.preheader:
247   tail call void asm "nop", ""()
248   br label %for.body
249
250 for.body:                                         ; preds = %entry, %for.body
251   %i.05 = phi i32 [ %inc, %for.body ], [ 0, %for.preheader ]
252   %sum.04 = phi i32 [ %add, %for.body ], [ 0, %for.preheader ]
253   %call = tail call i32 asm "movl $$1, $0", "=r,~{ebx}"()
254   %add = add nsw i32 %call, %sum.04
255   %inc = add nuw nsw i32 %i.05, 1
256   %exitcond = icmp eq i32 %inc, 10
257   br i1 %exitcond, label %for.end, label %for.body
258
259 for.end:                                          ; preds = %for.body
260   tail call void asm "nop", "~{ebx}"()
261   %shl = shl i32 %add, 3
262   br label %if.end
263
264 if.else:                                          ; preds = %entry
265   %mul = shl nsw i32 %N, 1
266   br label %if.end
267
268 if.end:                                           ; preds = %if.else, %for.end
269   %sum.1 = phi i32 [ %shl, %for.end ], [ %mul, %if.else ]
270   ret i32 %sum.1
271 }
272
273 declare void @somethingElse(...)
274
275 ; Check with a more complex case that we do not have restore within the loop and
276 ; save outside.
277 ; CHECK-LABEL: loopInfoRestoreOutsideLoop:
278 ;
279 ; ENABLE: testl %edi, %edi
280 ; ENABLE-NEXT: je [[ELSE_LABEL:LBB[0-9_]+]]
281 ;
282 ; Prologue code.
283 ; Make sure we save the CSR used in the inline asm: rbx.
284 ; CHECK: pushq %rbx
285 ;
286 ; DISABLE: testl %edi, %edi
287 ; DISABLE-NEXT: je [[ELSE_LABEL:LBB[0-9_]+]]
288 ;
289 ; CHECK: nop
290 ; CHECK: xorl [[SUM:%esi]], [[SUM]]
291 ; CHECK-NEXT: movl $10, [[IV:%e[a-z]+]]
292 ;
293 ; CHECK: [[LOOP_LABEL:LBB[0-9_]+]]: ## %for.body
294 ; CHECK: movl $1, [[TMP:%e[a-z]+]]
295 ; CHECK: addl [[TMP]], [[SUM]]
296 ; CHECK-NEXT: decl [[IV]]
297 ; CHECK-NEXT: jne [[LOOP_LABEL]]
298 ; Next BB.
299 ; CHECK: shll $3, [[SUM]]
300 ;
301 ; DISABLE: jmp [[EPILOG_BB:LBB[0-9_]+]]
302 ;
303 ; DISABLE: [[ELSE_LABEL]]: ## %if.else
304
305 ; Shift second argument by one and store into returned register.
306 ; DISABLE: addl %esi, %esi
307 ; DISABLE: [[EPILOG_BB]]: ## %if.end
308 ;
309 ; Epilogue code.
310 ; CHECK-DAG: popq %rbx
311 ; CHECK-DAG: movl %esi, %eax
312 ; CHECK: retq
313 ;
314 ; ENABLE: [[ELSE_LABEL]]: ## %if.else
315 ; Shift second argument by one and store into returned register.
316 ; ENABLE: addl %esi, %esi
317 ; ENABLE-NEXT: movl %esi, %eax
318 ; ENABLE-NEXT: retq
319 define i32 @loopInfoRestoreOutsideLoop(i32 %cond, i32 %N) #0 {
320 entry:
321   %tobool = icmp eq i32 %cond, 0
322   br i1 %tobool, label %if.else, label %if.then
323
324 if.then:                                          ; preds = %entry
325   tail call void asm "nop", "~{ebx}"()
326   br label %for.body
327
328 for.body:                                         ; preds = %for.body, %if.then
329   %i.05 = phi i32 [ 0, %if.then ], [ %inc, %for.body ]
330   %sum.04 = phi i32 [ 0, %if.then ], [ %add, %for.body ]
331   %call = tail call i32 asm "movl $$1, $0", "=r,~{ebx}"()
332   %add = add nsw i32 %call, %sum.04
333   %inc = add nuw nsw i32 %i.05, 1
334   %exitcond = icmp eq i32 %inc, 10
335   br i1 %exitcond, label %for.end, label %for.body
336
337 for.end:                                          ; preds = %for.body
338   %shl = shl i32 %add, 3
339   br label %if.end
340
341 if.else:                                          ; preds = %entry
342   %mul = shl nsw i32 %N, 1
343   br label %if.end
344
345 if.end:                                           ; preds = %if.else, %for.end
346   %sum.1 = phi i32 [ %shl, %for.end ], [ %mul, %if.else ]
347   ret i32 %sum.1
348 }
349
350 ; Check that we handle function with no frame information correctly.
351 ; CHECK-LABEL: emptyFrame:
352 ; CHECK: ## %entry
353 ; CHECK-NEXT: xorl %eax, %eax
354 ; CHECK-NEXT: retq
355 define i32 @emptyFrame() {
356 entry:
357   ret i32 0
358 }
359
360 ; Check that we handle inline asm correctly.
361 ; CHECK-LABEL: inlineAsm:
362 ;
363 ; ENABLE: testl %edi, %edi
364 ; ENABLE-NEXT: je [[ELSE_LABEL:LBB[0-9_]+]]
365 ;
366 ; Prologue code.
367 ; Make sure we save the CSR used in the inline asm: rbx.
368 ; CHECK: pushq %rbx
369 ;
370 ; DISABLE: testl %edi, %edi
371 ; DISABLE-NEXT: je [[ELSE_LABEL:LBB[0-9_]+]]
372 ;
373 ; CHECK: nop
374 ; CHECK: movl $10, [[IV:%e[a-z]+]]
375 ;
376 ; CHECK: [[LOOP_LABEL:LBB[0-9_]+]]: ## %for.body
377 ; Inline asm statement.
378 ; CHECK: addl $1, %ebx
379 ; CHECK: decl [[IV]]
380 ; CHECK-NEXT: jne [[LOOP_LABEL]]
381 ; Next BB.
382 ; CHECK: nop
383 ; CHECK: xorl %esi, %esi
384 ;
385 ; DISABLE: jmp [[EPILOG_BB:LBB[0-9_]+]]
386 ;
387 ; DISABLE: [[ELSE_LABEL]]: ## %if.else
388 ; Shift second argument by one and store into returned register.
389 ; DISABLE: addl %esi, %esi
390 ; DISABLE: [[EPILOG_BB]]: ## %if.end
391 ;
392 ; Epilogue code.
393 ; CHECK-DAG: popq %rbx
394 ; CHECK-DAG: movl %esi, %eax
395 ; CHECK: retq
396 ;
397 ; ENABLE: [[ELSE_LABEL]]: ## %if.else
398 ; Shift second argument by one and store into returned register.
399 ; ENABLE: addl %esi, %esi
400 ; ENABLE-NEXT: movl %esi, %eax
401 ; ENABLE-NEXT: retq
402 define i32 @inlineAsm(i32 %cond, i32 %N) {
403 entry:
404   %tobool = icmp eq i32 %cond, 0
405   br i1 %tobool, label %if.else, label %for.preheader
406
407 for.preheader:
408   tail call void asm "nop", ""()
409   br label %for.body
410
411 for.body:                                         ; preds = %entry, %for.body
412   %i.03 = phi i32 [ %inc, %for.body ], [ 0, %for.preheader ]
413   tail call void asm "addl $$1, %ebx", "~{ebx}"()
414   %inc = add nuw nsw i32 %i.03, 1
415   %exitcond = icmp eq i32 %inc, 10
416   br i1 %exitcond, label %for.exit, label %for.body
417
418 for.exit:
419   tail call void asm "nop", ""()
420   br label %if.end
421
422 if.else:                                          ; preds = %entry
423   %mul = shl nsw i32 %N, 1
424   br label %if.end
425
426 if.end:                                           ; preds = %for.body, %if.else
427   %sum.0 = phi i32 [ %mul, %if.else ], [ 0, %for.exit ]
428   ret i32 %sum.0
429 }
430
431 ; Check that we handle calls to variadic functions correctly.
432 ; CHECK-LABEL: callVariadicFunc:
433 ;
434 ; ENABLE: testl %edi, %edi
435 ; ENABLE-NEXT: je [[ELSE_LABEL:LBB[0-9_]+]]
436 ;
437 ; Prologue code.
438 ; CHECK: pushq
439 ;
440 ; DISABLE: testl %edi, %edi
441 ; DISABLE-NEXT: je [[ELSE_LABEL:LBB[0-9_]+]]
442 ;
443 ; Setup of the varags.
444 ; CHECK: movl %esi, (%rsp)
445 ; CHECK-NEXT: xorl %eax, %eax
446 ; CHECK-NEXT: %esi, %edi
447 ; CHECK-NEXT: %esi, %edx
448 ; CHECK-NEXT: %esi, %r8d
449 ; CHECK-NEXT: %esi, %r9d
450 ; CHECK-NEXT: %esi, %ecx
451 ; CHECK-NEXT: callq _someVariadicFunc
452 ; CHECK-NEXT: movl %eax, %esi
453 ; CHECK-NEXT: shll $3, %esi
454 ;
455 ; ENABLE-NEXT: addq $8, %rsp
456 ; ENABLE-NEXT: movl %esi, %eax
457 ; ENABLE-NEXT: retq
458 ;
459 ; DISABLE: jmp [[IFEND_LABEL:LBB[0-9_]+]]
460 ;
461 ; CHECK: [[ELSE_LABEL]]: ## %if.else
462 ; Shift second argument by one and store into returned register.
463 ; CHECK: addl %esi, %esi
464 ;
465 ; DISABLE: [[IFEND_LABEL]]: ## %if.end
466 ;
467 ; Epilogue code.
468 ; CHECK-NEXT: movl %esi, %eax
469 ; DISABLE-NEXT: popq
470 ; CHECK-NEXT: retq
471 define i32 @callVariadicFunc(i32 %cond, i32 %N) {
472 entry:
473   %tobool = icmp eq i32 %cond, 0
474   br i1 %tobool, label %if.else, label %if.then
475
476 if.then:                                          ; preds = %entry
477   %call = tail call i32 (i32, ...) @someVariadicFunc(i32 %N, i32 %N, i32 %N, i32 %N, i32 %N, i32 %N, i32 %N)
478   %shl = shl i32 %call, 3
479   br label %if.end
480
481 if.else:                                          ; preds = %entry
482   %mul = shl nsw i32 %N, 1
483   br label %if.end
484
485 if.end:                                           ; preds = %if.else, %if.then
486   %sum.0 = phi i32 [ %shl, %if.then ], [ %mul, %if.else ]
487   ret i32 %sum.0
488 }
489
490 declare i32 @someVariadicFunc(i32, ...)
491
492 ; Check that we use LEA not to clobber EFLAGS.
493 %struct.temp_slot = type { %struct.temp_slot*, %struct.rtx_def*, %struct.rtx_def*, i32, i64, %union.tree_node*, %union.tree_node*, i8, i8, i32, i32, i64, i64 }
494 %union.tree_node = type { %struct.tree_decl }
495 %struct.tree_decl = type { %struct.tree_common, i8*, i32, i32, %union.tree_node*, i48, %union.anon, %union.tree_node*, %union.tree_node*, %union.tree_node*, %union.tree_node*, %union.tree_node*, %union.tree_node*, %union.tree_node*, %union.tree_node*, %union.tree_node*, %union.tree_node*, %struct.rtx_def*, %struct.rtx_def*, %union.anon.1, %union.tree_node*, %union.tree_node*, %union.tree_node*, i64, %struct.lang_decl* }
496 %struct.tree_common = type { %union.tree_node*, %union.tree_node*, i32 }
497 %union.anon = type { i64 }
498 %union.anon.1 = type { %struct.function* }
499 %struct.function = type { %struct.eh_status*, %struct.stmt_status*, %struct.expr_status*, %struct.emit_status*, %struct.varasm_status*, i8*, %union.tree_node*, %struct.function*, i32, i32, i32, i32, %struct.rtx_def*, %struct.ix86_args, %struct.rtx_def*, %struct.rtx_def*, i8*, %struct.initial_value_struct*, i32, %union.tree_node*, %struct.rtx_def*, %struct.rtx_def*, %struct.rtx_def*, %struct.rtx_def*, %struct.rtx_def*, %struct.rtx_def*, %struct.rtx_def*, %union.tree_node*, %struct.rtx_def*, %struct.rtx_def*, %struct.rtx_def*, %struct.rtx_def*, i64, %union.tree_node*, %union.tree_node*, %struct.rtx_def*, %struct.rtx_def*, i32, %struct.rtx_def**, %struct.temp_slot*, i32, i32, i32, %struct.var_refs_queue*, i32, i32, i8*, %union.tree_node*, %struct.rtx_def*, i32, i32, %struct.machine_function*, i32, i32, %struct.language_function*, %struct.rtx_def*, i24 }
500 %struct.eh_status = type opaque
501 %struct.stmt_status = type opaque
502 %struct.expr_status = type { i32, i32, i32, %struct.rtx_def*, %struct.rtx_def*, %struct.rtx_def*, %struct.rtx_def* }
503 %struct.emit_status = type { i32, i32, %struct.rtx_def*, %struct.rtx_def*, %union.tree_node*, %struct.sequence_stack*, i32, i32, i8*, i32, i8*, %union.tree_node**, %struct.rtx_def** }
504 %struct.sequence_stack = type { %struct.rtx_def*, %struct.rtx_def*, %union.tree_node*, %struct.sequence_stack* }
505 %struct.varasm_status = type opaque
506 %struct.ix86_args = type { i32, i32, i32, i32, i32, i32, i32 }
507 %struct.initial_value_struct = type opaque
508 %struct.var_refs_queue = type { %struct.rtx_def*, i32, i32, %struct.var_refs_queue* }
509 %struct.machine_function = type opaque
510 %struct.language_function = type opaque
511 %struct.lang_decl = type opaque
512 %struct.rtx_def = type { i32, [1 x %union.rtunion_def] }
513 %union.rtunion_def = type { i64 }
514
515 declare hidden fastcc %struct.temp_slot* @find_temp_slot_from_address(%struct.rtx_def* readonly)
516
517 ; CHECK-LABEL: useLEA:
518 ; DISABLE: pushq 
519 ;
520 ; CHECK: testq   %rdi, %rdi
521 ; CHECK-NEXT: je      [[CLEANUP:LBB[0-9_]+]]
522 ;
523 ; CHECK: movzwl  (%rdi), [[BF_LOAD:%e[a-z]+]]
524 ; CHECK-NEXT: cmpl $66, [[BF_LOAD]]
525 ; CHECK-NEXT: jne [[CLEANUP]]
526 ;
527 ; CHECK: movq 8(%rdi), %rdi
528 ; CHECK-NEXT: movzwl (%rdi), %e[[BF_LOAD2:[a-z]+]]
529 ; CHECK-NEXT: leal -54(%r[[BF_LOAD2]]), [[TMP:%e[a-z]+]]
530 ; CHECK-NEXT: cmpl $14, [[TMP]]
531 ; CHECK-NEXT: ja [[LOR_LHS_FALSE:LBB[0-9_]+]]
532 ;
533 ; CHECK: movl $24599, [[TMP2:%e[a-z]+]]
534 ; CHECK-NEXT: btl [[TMP]], [[TMP2]]
535 ; CHECK-NEXT: jb [[CLEANUP]]
536 ;
537 ; CHECK: [[LOR_LHS_FALSE]]: ## %lor.lhs.false
538 ; CHECK: cmpl $134, %e[[BF_LOAD2]]
539 ; CHECK-NEXT: je [[CLEANUP]]
540 ;
541 ; CHECK: cmpl $140, %e[[BF_LOAD2]]
542 ; CHECK-NEXT: je [[CLEANUP]]
543 ;
544 ; ENABLE: pushq
545 ; CHECK: callq _find_temp_slot_from_address
546 ; CHECK-NEXT: testq   %rax, %rax
547 ;
548 ; The adjustment must use LEA here (or be moved above the test).
549 ; ENABLE-NEXT: leaq 8(%rsp), %rsp
550 ;
551 ; CHECK-NEXT: je [[CLEANUP]]
552 ;
553 ; CHECK: movb $1, 57(%rax)
554 ;
555 ; CHECK: [[CLEANUP]]: ## %cleanup
556 ; DISABLE: popq
557 ; CHECK-NEXT: retq
558 define void @useLEA(%struct.rtx_def* readonly %x) {
559 entry:
560   %cmp = icmp eq %struct.rtx_def* %x, null
561   br i1 %cmp, label %cleanup, label %if.end
562
563 if.end:                                           ; preds = %entry
564   %tmp = getelementptr inbounds %struct.rtx_def, %struct.rtx_def* %x, i64 0, i32 0
565   %bf.load = load i32, i32* %tmp, align 8
566   %bf.clear = and i32 %bf.load, 65535
567   %cmp1 = icmp eq i32 %bf.clear, 66
568   br i1 %cmp1, label %lor.lhs.false, label %cleanup
569
570 lor.lhs.false:                                    ; preds = %if.end
571   %arrayidx = getelementptr inbounds %struct.rtx_def, %struct.rtx_def* %x, i64 0, i32 1, i64 0
572   %rtx = bitcast %union.rtunion_def* %arrayidx to %struct.rtx_def**
573   %tmp1 = load %struct.rtx_def*, %struct.rtx_def** %rtx, align 8
574   %tmp2 = getelementptr inbounds %struct.rtx_def, %struct.rtx_def* %tmp1, i64 0, i32 0
575   %bf.load2 = load i32, i32* %tmp2, align 8
576   %bf.clear3 = and i32 %bf.load2, 65535
577   switch i32 %bf.clear3, label %if.end.55 [
578     i32 67, label %cleanup
579     i32 68, label %cleanup
580     i32 54, label %cleanup
581     i32 55, label %cleanup
582     i32 58, label %cleanup
583     i32 134, label %cleanup
584     i32 56, label %cleanup
585     i32 140, label %cleanup
586   ]
587
588 if.end.55:                                        ; preds = %lor.lhs.false
589   %call = tail call fastcc %struct.temp_slot* @find_temp_slot_from_address(%struct.rtx_def* %tmp1) #2
590   %cmp59 = icmp eq %struct.temp_slot* %call, null
591   br i1 %cmp59, label %cleanup, label %if.then.60
592
593 if.then.60:                                       ; preds = %if.end.55
594   %addr_taken = getelementptr inbounds %struct.temp_slot, %struct.temp_slot* %call, i64 0, i32 8
595   store i8 1, i8* %addr_taken, align 1
596   br label %cleanup
597
598 cleanup:                                          ; preds = %if.then.60, %if.end.55, %lor.lhs.false, %lor.lhs.false, %lor.lhs.false, %lor.lhs.false, %lor.lhs.false, %lor.lhs.false, %lor.lhs.false, %lor.lhs.false, %if.end, %entry
599   ret void
600 }