Home | History | Annotate | Download | only in X86
      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, %ecx
    449 ; CHECK-NEXT: %esi, %r8d
    450 ; CHECK-NEXT: %esi, %r9d
    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: jae [[LOR_LHS_FALSE:LBB[0-9_]+]]
    536 ;
    537 ; CHECK: [[CLEANUP]]: ## %cleanup
    538 ; DISABLE: popq
    539 ; CHECK-NEXT: retq
    540 ;
    541 ; CHECK: [[LOR_LHS_FALSE]]: ## %lor.lhs.false
    542 ; CHECK: cmpl $134, %e[[BF_LOAD2]]
    543 ; CHECK-NEXT: je [[CLEANUP]]
    544 ;
    545 ; CHECK: cmpl $140, %e[[BF_LOAD2]]
    546 ; CHECK-NEXT: je [[CLEANUP]]
    547 ;
    548 ; ENABLE: pushq
    549 ; CHECK: callq _find_temp_slot_from_address
    550 ; CHECK-NEXT: testq   %rax, %rax
    551 ;
    552 ; The adjustment must use LEA here (or be moved above the test).
    553 ; ENABLE-NEXT: leaq 8(%rsp), %rsp
    554 ;
    555 ; CHECK-NEXT: je [[CLEANUP]]
    556 ;
    557 ; CHECK: movb $1, 57(%rax)
    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 }
    601 
    602 ; Make sure we do not insert unreachable code after noreturn function.
    603 ; Although this is not incorrect to insert such code, it is useless
    604 ; and it hurts the binary size.
    605 ;
    606 ; CHECK-LABEL: noreturn:
    607 ; DISABLE: pushq
    608 ;
    609 ; CHECK: testb   %dil, %dil
    610 ; CHECK-NEXT: jne      [[ABORT:LBB[0-9_]+]]
    611 ;
    612 ; CHECK: movl $42, %eax
    613 ;
    614 ; DISABLE-NEXT: popq
    615 ;
    616 ; CHECK-NEXT: retq
    617 ;
    618 ; CHECK: [[ABORT]]: ## %if.abort
    619 ;
    620 ; ENABLE: pushq
    621 ;
    622 ; CHECK: callq _abort
    623 ; ENABLE-NOT: popq
    624 define i32 @noreturn(i8 signext %bad_thing) {
    625 entry:
    626   %tobool = icmp eq i8 %bad_thing, 0
    627   br i1 %tobool, label %if.end, label %if.abort
    628 
    629 if.abort:
    630   tail call void @abort() #0
    631   unreachable
    632 
    633 if.end:
    634   ret i32 42
    635 }
    636 
    637 declare void @abort() #0
    638 
    639 attributes #0 = { noreturn nounwind }
    640 
    641 
    642 ; Make sure that we handle infinite loops properly When checking that the Save
    643 ; and Restore blocks are control flow equivalent, the loop searches for the
    644 ; immediate (post) dominator for the (restore) save blocks. When either the Save
    645 ; or Restore block is located in an infinite loop the only immediate (post)
    646 ; dominator is itself. In this case, we cannot perform shrink wrapping, but we
    647 ; should return gracefully and continue compilation.
    648 ; The only condition for this test is the compilation finishes correctly.
    649 ;
    650 ; CHECK-LABEL: infiniteloop
    651 ; CHECK: retq
    652 define void @infiniteloop() {
    653 entry:
    654   br i1 undef, label %if.then, label %if.end
    655 
    656 if.then:
    657   %ptr = alloca i32, i32 4
    658   br label %for.body
    659 
    660 for.body:                                         ; preds = %for.body, %entry
    661   %sum.03 = phi i32 [ 0, %if.then ], [ %add, %for.body ]
    662   %call = tail call i32 asm "movl $$1, $0", "=r,~{ebx}"()
    663   %add = add nsw i32 %call, %sum.03
    664   store i32 %add, i32* %ptr
    665   br label %for.body
    666 
    667 if.end:
    668   ret void
    669 }
    670 
    671 ; Another infinite loop test this time with a body bigger than just one block.
    672 ; CHECK-LABEL: infiniteloop2
    673 ; CHECK: retq
    674 define void @infiniteloop2() {
    675 entry:
    676   br i1 undef, label %if.then, label %if.end
    677 
    678 if.then:
    679   %ptr = alloca i32, i32 4
    680   br label %for.body
    681 
    682 for.body:                                         ; preds = %for.body, %entry
    683   %sum.03 = phi i32 [ 0, %if.then ], [ %add, %body1 ], [ 1, %body2]
    684   %call = tail call i32 asm "movl $$1, $0", "=r,~{ebx}"()
    685   %add = add nsw i32 %call, %sum.03
    686   store i32 %add, i32* %ptr
    687   br i1 undef, label %body1, label %body2
    688 
    689 body1:
    690   tail call void asm sideeffect "nop", "~{ebx}"()
    691   br label %for.body
    692 
    693 body2:
    694   tail call void asm sideeffect "nop", "~{ebx}"()
    695   br label %for.body
    696 
    697 if.end:
    698   ret void
    699 }
    700 
    701 ; Another infinite loop test this time with two nested infinite loop.
    702 ; CHECK-LABEL: infiniteloop3
    703 ; CHECK: retq
    704 define void @infiniteloop3() {
    705 entry:
    706   br i1 undef, label %loop2a, label %body
    707 
    708 body:                                             ; preds = %entry
    709   br i1 undef, label %loop2a, label %end
    710 
    711 loop1:                                            ; preds = %loop2a, %loop2b
    712   %var.phi = phi i32* [ %next.phi, %loop2b ], [ %var, %loop2a ]
    713   %next.phi = phi i32* [ %next.load, %loop2b ], [ %next.var, %loop2a ]
    714   %0 = icmp eq i32* %var, null
    715   %next.load = load i32*, i32** undef
    716   br i1 %0, label %loop2a, label %loop2b
    717 
    718 loop2a:                                           ; preds = %loop1, %body, %entry
    719   %var = phi i32* [ null, %body ], [ null, %entry ], [ %next.phi, %loop1 ]
    720   %next.var = phi i32* [ undef, %body ], [ null, %entry ], [ %next.load, %loop1 ]
    721   br label %loop1
    722 
    723 loop2b:                                           ; preds = %loop1
    724   %gep1 = bitcast i32* %var.phi to i32*
    725   %next.ptr = bitcast i32* %gep1 to i32**
    726   store i32* %next.phi, i32** %next.ptr
    727   br label %loop1
    728 
    729 end:
    730   ret void
    731 }
    732 
    733 ; Check that we just don't bail out on RegMask.
    734 ; In this case, the RegMask does not touch a CSR so we are good to go!
    735 ; CHECK-LABEL: regmask:
    736 ;
    737 ; Compare the arguments and jump to exit.
    738 ; No prologue needed.
    739 ; ENABLE: cmpl %esi, %edi
    740 ; ENABLE-NEXT: jge [[EXIT_LABEL:LBB[0-9_]+]]
    741 ;
    742 ; Prologue code.
    743 ; (What we push does not matter. It should be some random sratch register.)
    744 ; CHECK: pushq
    745 ;
    746 ; Compare the arguments and jump to exit.
    747 ; After the prologue is set.
    748 ; DISABLE: cmpl %esi, %edi
    749 ; DISABLE-NEXT: jge [[EXIT_LABEL:LBB[0-9_]+]]
    750 ;
    751 ; CHECK: nop
    752 ; Set the first argument to zero.
    753 ; CHECK: xorl %edi, %edi
    754 ; Set the second argument to addr.
    755 ; CHECK-NEXT: movq %rdx, %rsi
    756 ; CHECK-NEXT: callq _doSomething
    757 ; CHECK-NEXT: popq
    758 ; CHECK-NEXT: retq
    759 ;
    760 ; CHECK: [[EXIT_LABEL]]:
    761 ; Set the first argument to 6.
    762 ; CHECK-NEXT: movl $6, %edi
    763 ; Set the second argument to addr.
    764 ; CHECK-NEXT: movq %rdx, %rsi
    765 ;
    766 ; Without shrink-wrapping, we need to restore the stack before
    767 ; making the tail call.
    768 ; Epilogue code.
    769 ; DISABLE-NEXT: popq
    770 ;
    771 ; CHECK-NEXT: jmp _doSomething
    772 define i32 @regmask(i32 %a, i32 %b, i32* %addr) {
    773   %tmp2 = icmp slt i32 %a, %b
    774   br i1 %tmp2, label %true, label %false
    775 
    776 true:
    777   ; Clobber a CSR so that we check something on the regmask
    778   ; of the tail call.
    779   tail call void asm sideeffect "nop", "~{ebx}"()
    780   %tmp4 = call i32 @doSomething(i32 0, i32* %addr)
    781   br label %end
    782 
    783 false:
    784   %tmp5 = tail call i32 @doSomething(i32 6, i32* %addr)
    785   br label %end
    786 
    787 end:
    788   %tmp.0 = phi i32 [ %tmp4, %true ], [ %tmp5, %false ]
    789   ret i32 %tmp.0
    790 }
    791 
    792 @b = internal unnamed_addr global i1 false
    793 @c = internal unnamed_addr global i8 0, align 1
    794 @a = common global i32 0, align 4
    795 
    796 ; Make sure the prologue does not clobber the EFLAGS when
    797 ; it is live accross.
    798 ; PR25629.
    799 ; Note: The registers may change in the following patterns, but
    800 ; because they imply register hierarchy (e.g., eax, al) this is
    801 ; tricky to write robust patterns.
    802 ;
    803 ; CHECK-LABEL: useLEAForPrologue:
    804 ;
    805 ; Prologue is at the beginning of the function when shrink-wrapping
    806 ; is disabled.
    807 ; DISABLE: pushq
    808 ; The stack adjustment can use SUB instr because we do not need to
    809 ; preserve the EFLAGS at this point.
    810 ; DISABLE-NEXT: subq $16, %rsp
    811 ;
    812 ; Load the value of b.
    813 ; CHECK: movb _b(%rip), [[BOOL:%cl]]
    814 ; Extract i1 from the loaded value.
    815 ; CHECK-NEXT: andb $1, [[BOOL]]
    816 ; Create the zero value for the select assignment.
    817 ; CHECK-NEXT: xorl [[CMOVE_VAL:%eax]], [[CMOVE_VAL]]
    818 ; CHECK-NEXT: testb [[BOOL]], [[BOOL]]
    819 ; CHECK-NEXT: jne [[STOREC_LABEL:LBB[0-9_]+]]
    820 ;
    821 ; CHECK: movb $48, [[CMOVE_VAL:%al]]
    822 ;
    823 ; CHECK: [[STOREC_LABEL]]:
    824 ;
    825 ; ENABLE-NEXT: pushq
    826 ; For the stack adjustment, we need to preserve the EFLAGS.
    827 ; ENABLE-NEXT: leaq -16(%rsp), %rsp
    828 ;
    829 ; Technically, we should use CMOVE_VAL here or its subregister.
    830 ; CHECK-NEXT: movb %al, _c(%rip)
    831 ; testb set the EFLAGS read here.
    832 ; CHECK-NEXT: je [[VARFUNC_CALL:LBB[0-9_]+]]
    833 ;
    834 ; The code of the loop is not interesting.
    835 ; [...]
    836 ;
    837 ; CHECK: [[VARFUNC_CALL]]:
    838 ; Set the null parameter.
    839 ; CHECK-NEXT: xorl %edi, %edi
    840 ; CHECK-NEXT: callq _varfunc
    841 ;
    842 ; Set the return value.
    843 ; CHECK-NEXT: xorl %eax, %eax
    844 ;
    845 ; Epilogue code.
    846 ; CHECK-NEXT: addq $16, %rsp
    847 ; CHECK-NEXT: popq
    848 ; CHECK-NEXT: retq
    849 define i32 @useLEAForPrologue(i32 %d, i32 %a, i8 %c) #3 {
    850 entry:
    851   %tmp = alloca i3
    852   %.b = load i1, i1* @b, align 1
    853   %bool = select i1 %.b, i8 0, i8 48
    854   store i8 %bool, i8* @c, align 1
    855   br i1 %.b, label %for.body.lr.ph, label %for.end
    856 
    857 for.body.lr.ph:                                   ; preds = %entry
    858   tail call void asm sideeffect "nop", "~{ebx}"()
    859   br label %for.body
    860 
    861 for.body:                                         ; preds = %for.body.lr.ph, %for.body
    862   %inc6 = phi i8 [ %c, %for.body.lr.ph ], [ %inc, %for.body ]
    863   %cond5 = phi i32 [ %a, %for.body.lr.ph ], [ %conv3, %for.body ]
    864   %cmp2 = icmp slt i32 %d, %cond5
    865   %conv3 = zext i1 %cmp2 to i32
    866   %inc = add i8 %inc6, 1
    867   %cmp = icmp slt i8 %inc, 45
    868   br i1 %cmp, label %for.body, label %for.cond.for.end_crit_edge
    869 
    870 for.cond.for.end_crit_edge:                       ; preds = %for.body
    871   store i32 %conv3, i32* @a, align 4
    872   br label %for.end
    873 
    874 for.end:                                          ; preds = %for.cond.for.end_crit_edge, %entry
    875   %call = tail call i32 (i8*) @varfunc(i8* null)
    876   ret i32 0
    877 }
    878 
    879 declare i32 @varfunc(i8* nocapture readonly)
    880 
    881 attributes #3 = { nounwind }
    882