mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 20:51:52 +01:00
18451cc4a4
The motivation is that the update script has at least two deviations (`<...>@GOT`/`<...>@PLT`/ and not hiding pointer arithmetics) from what pretty much all the checklines were generated with, and most of the tests are still not updated, so each time one of the non-up-to-date tests is updated to see the effect of the code change, there is a lot of noise. Instead of having to deal with that each time, let's just deal with everything at once. This has been done via: ``` cd llvm-project/llvm/test/CodeGen/X86 grep -rl "; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py" | xargs -L1 <...>/llvm-project/llvm/utils/update_llc_test_checks.py --llc-binary <...>/llvm-project/build/bin/llc ``` Not all tests were regenerated, however.
1584 lines
54 KiB
LLVM
1584 lines
54 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
|
|
; RUN: llc %s -o - -enable-shrink-wrap=true -pass-remarks-output=%t | FileCheck %s --check-prefix=ENABLE
|
|
; RUN: cat %t | FileCheck %s --check-prefix=REMARKS
|
|
; RUN: llc %s -o - -enable-shrink-wrap=false | FileCheck %s --check-prefix=DISABLE
|
|
;
|
|
; Note: Lots of tests use inline asm instead of regular calls.
|
|
; This allows to have a better control on what the allocation will do.
|
|
; Otherwise, we may have spill right in the entry block, defeating
|
|
; shrink-wrapping. Moreover, some of the inline asm statement (nop)
|
|
; are here to ensure that the related paths do not end up as critical
|
|
; edges.
|
|
target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128"
|
|
target triple = "x86_64-apple-macosx"
|
|
|
|
|
|
; Initial motivating example: Simple diamond with a call just on one side.
|
|
define i32 @foo(i32 %a, i32 %b) {
|
|
; ENABLE-LABEL: foo:
|
|
; ENABLE: ## %bb.0:
|
|
; ENABLE-NEXT: movl %edi, %eax
|
|
; ENABLE-NEXT: cmpl %esi, %edi
|
|
; ENABLE-NEXT: jge LBB0_2
|
|
; ENABLE-NEXT: ## %bb.1: ## %true
|
|
; ENABLE-NEXT: pushq %rax
|
|
; ENABLE-NEXT: .cfi_def_cfa_offset 16
|
|
; ENABLE-NEXT: movl %eax, {{[0-9]+}}(%rsp)
|
|
; ENABLE-NEXT: leaq {{[0-9]+}}(%rsp), %rsi
|
|
; ENABLE-NEXT: xorl %edi, %edi
|
|
; ENABLE-NEXT: callq _doSomething
|
|
; ENABLE-NEXT: addq $8, %rsp
|
|
; ENABLE-NEXT: LBB0_2: ## %false
|
|
; ENABLE-NEXT: retq
|
|
;
|
|
; DISABLE-LABEL: foo:
|
|
; DISABLE: ## %bb.0:
|
|
; DISABLE-NEXT: pushq %rax
|
|
; DISABLE-NEXT: .cfi_def_cfa_offset 16
|
|
; DISABLE-NEXT: movl %edi, %eax
|
|
; DISABLE-NEXT: cmpl %esi, %edi
|
|
; DISABLE-NEXT: jge LBB0_2
|
|
; DISABLE-NEXT: ## %bb.1: ## %true
|
|
; DISABLE-NEXT: movl %eax, {{[0-9]+}}(%rsp)
|
|
; DISABLE-NEXT: leaq {{[0-9]+}}(%rsp), %rsi
|
|
; DISABLE-NEXT: xorl %edi, %edi
|
|
; DISABLE-NEXT: callq _doSomething
|
|
; DISABLE-NEXT: LBB0_2: ## %false
|
|
; DISABLE-NEXT: popq %rcx
|
|
; DISABLE-NEXT: retq
|
|
%tmp = alloca i32, align 4
|
|
%tmp2 = icmp slt i32 %a, %b
|
|
br i1 %tmp2, label %true, label %false
|
|
|
|
true:
|
|
store i32 %a, i32* %tmp, align 4
|
|
%tmp4 = call i32 @doSomething(i32 0, i32* %tmp)
|
|
br label %false
|
|
|
|
false:
|
|
%tmp.0 = phi i32 [ %tmp4, %true ], [ %a, %0 ]
|
|
ret i32 %tmp.0
|
|
}
|
|
|
|
; Function Attrs: optsize
|
|
declare i32 @doSomething(i32, i32*)
|
|
|
|
|
|
; Check that we do not perform the restore inside the loop whereas the save
|
|
; is outside.
|
|
define i32 @freqSaveAndRestoreOutsideLoop(i32 %cond, i32 %N) {
|
|
; ENABLE-LABEL: freqSaveAndRestoreOutsideLoop:
|
|
; ENABLE: ## %bb.0: ## %entry
|
|
; ENABLE-NEXT: testl %edi, %edi
|
|
; ENABLE-NEXT: je LBB1_4
|
|
; ENABLE-NEXT: ## %bb.1: ## %for.preheader
|
|
; ENABLE-NEXT: pushq %rbx
|
|
; ENABLE-NEXT: .cfi_def_cfa_offset 16
|
|
; ENABLE-NEXT: .cfi_offset %rbx, -16
|
|
; ENABLE-NEXT: ## InlineAsm Start
|
|
; ENABLE-NEXT: nop
|
|
; ENABLE-NEXT: ## InlineAsm End
|
|
; ENABLE-NEXT: xorl %eax, %eax
|
|
; ENABLE-NEXT: movl $10, %ecx
|
|
; ENABLE-NEXT: .p2align 4, 0x90
|
|
; ENABLE-NEXT: LBB1_2: ## %for.body
|
|
; ENABLE-NEXT: ## =>This Inner Loop Header: Depth=1
|
|
; ENABLE-NEXT: ## InlineAsm Start
|
|
; ENABLE-NEXT: movl $1, %edx
|
|
; ENABLE-NEXT: ## InlineAsm End
|
|
; ENABLE-NEXT: addl %edx, %eax
|
|
; ENABLE-NEXT: decl %ecx
|
|
; ENABLE-NEXT: jne LBB1_2
|
|
; ENABLE-NEXT: ## %bb.3: ## %for.end
|
|
; ENABLE-NEXT: shll $3, %eax
|
|
; ENABLE-NEXT: popq %rbx
|
|
; ENABLE-NEXT: retq
|
|
; ENABLE-NEXT: LBB1_4: ## %if.else
|
|
; ENABLE-NEXT: movl %esi, %eax
|
|
; ENABLE-NEXT: addl %esi, %eax
|
|
; ENABLE-NEXT: retq
|
|
;
|
|
; DISABLE-LABEL: freqSaveAndRestoreOutsideLoop:
|
|
; DISABLE: ## %bb.0: ## %entry
|
|
; DISABLE-NEXT: pushq %rbx
|
|
; DISABLE-NEXT: .cfi_def_cfa_offset 16
|
|
; DISABLE-NEXT: .cfi_offset %rbx, -16
|
|
; DISABLE-NEXT: testl %edi, %edi
|
|
; DISABLE-NEXT: je LBB1_4
|
|
; DISABLE-NEXT: ## %bb.1: ## %for.preheader
|
|
; DISABLE-NEXT: ## InlineAsm Start
|
|
; DISABLE-NEXT: nop
|
|
; DISABLE-NEXT: ## InlineAsm End
|
|
; DISABLE-NEXT: xorl %eax, %eax
|
|
; DISABLE-NEXT: movl $10, %ecx
|
|
; DISABLE-NEXT: .p2align 4, 0x90
|
|
; DISABLE-NEXT: LBB1_2: ## %for.body
|
|
; DISABLE-NEXT: ## =>This Inner Loop Header: Depth=1
|
|
; DISABLE-NEXT: ## InlineAsm Start
|
|
; DISABLE-NEXT: movl $1, %edx
|
|
; DISABLE-NEXT: ## InlineAsm End
|
|
; DISABLE-NEXT: addl %edx, %eax
|
|
; DISABLE-NEXT: decl %ecx
|
|
; DISABLE-NEXT: jne LBB1_2
|
|
; DISABLE-NEXT: ## %bb.3: ## %for.end
|
|
; DISABLE-NEXT: shll $3, %eax
|
|
; DISABLE-NEXT: popq %rbx
|
|
; DISABLE-NEXT: retq
|
|
; DISABLE-NEXT: LBB1_4: ## %if.else
|
|
; DISABLE-NEXT: movl %esi, %eax
|
|
; DISABLE-NEXT: addl %esi, %eax
|
|
; DISABLE-NEXT: popq %rbx
|
|
; DISABLE-NEXT: retq
|
|
entry:
|
|
%tobool = icmp eq i32 %cond, 0
|
|
br i1 %tobool, label %if.else, label %for.preheader
|
|
|
|
for.preheader:
|
|
tail call void asm "nop", ""()
|
|
br label %for.body
|
|
|
|
for.body: ; preds = %entry, %for.body
|
|
%i.05 = phi i32 [ %inc, %for.body ], [ 0, %for.preheader ]
|
|
%sum.04 = phi i32 [ %add, %for.body ], [ 0, %for.preheader ]
|
|
%call = tail call i32 asm sideeffect "movl $$1, $0", "=r,~{ebx}"()
|
|
%add = add nsw i32 %call, %sum.04
|
|
%inc = add nuw nsw i32 %i.05, 1
|
|
%exitcond = icmp eq i32 %inc, 10
|
|
br i1 %exitcond, label %for.end, label %for.body
|
|
|
|
for.end: ; preds = %for.body
|
|
%shl = shl i32 %add, 3
|
|
br label %if.end
|
|
|
|
if.else: ; preds = %entry
|
|
%mul = shl nsw i32 %N, 1
|
|
br label %if.end
|
|
|
|
if.end: ; preds = %if.else, %for.end
|
|
%sum.1 = phi i32 [ %shl, %for.end ], [ %mul, %if.else ]
|
|
ret i32 %sum.1
|
|
}
|
|
|
|
declare i32 @something(...)
|
|
|
|
; Check that we do not perform the shrink-wrapping inside the loop even
|
|
; though that would be legal. The cost model must prevent that.
|
|
define i32 @freqSaveAndRestoreOutsideLoop2(i32 %cond) {
|
|
; ENABLE-LABEL: freqSaveAndRestoreOutsideLoop2:
|
|
; ENABLE: ## %bb.0: ## %entry
|
|
; ENABLE-NEXT: pushq %rbx
|
|
; ENABLE-NEXT: .cfi_def_cfa_offset 16
|
|
; ENABLE-NEXT: .cfi_offset %rbx, -16
|
|
; ENABLE-NEXT: ## InlineAsm Start
|
|
; ENABLE-NEXT: nop
|
|
; ENABLE-NEXT: ## InlineAsm End
|
|
; ENABLE-NEXT: xorl %eax, %eax
|
|
; ENABLE-NEXT: movl $10, %ecx
|
|
; ENABLE-NEXT: .p2align 4, 0x90
|
|
; ENABLE-NEXT: LBB2_1: ## %for.body
|
|
; ENABLE-NEXT: ## =>This Inner Loop Header: Depth=1
|
|
; ENABLE-NEXT: ## InlineAsm Start
|
|
; ENABLE-NEXT: movl $1, %edx
|
|
; ENABLE-NEXT: ## InlineAsm End
|
|
; ENABLE-NEXT: addl %edx, %eax
|
|
; ENABLE-NEXT: decl %ecx
|
|
; ENABLE-NEXT: jne LBB2_1
|
|
; ENABLE-NEXT: ## %bb.2: ## %for.exit
|
|
; ENABLE-NEXT: ## InlineAsm Start
|
|
; ENABLE-NEXT: nop
|
|
; ENABLE-NEXT: ## InlineAsm End
|
|
; ENABLE-NEXT: popq %rbx
|
|
; ENABLE-NEXT: retq
|
|
;
|
|
; DISABLE-LABEL: freqSaveAndRestoreOutsideLoop2:
|
|
; DISABLE: ## %bb.0: ## %entry
|
|
; DISABLE-NEXT: pushq %rbx
|
|
; DISABLE-NEXT: .cfi_def_cfa_offset 16
|
|
; DISABLE-NEXT: .cfi_offset %rbx, -16
|
|
; DISABLE-NEXT: ## InlineAsm Start
|
|
; DISABLE-NEXT: nop
|
|
; DISABLE-NEXT: ## InlineAsm End
|
|
; DISABLE-NEXT: xorl %eax, %eax
|
|
; DISABLE-NEXT: movl $10, %ecx
|
|
; DISABLE-NEXT: .p2align 4, 0x90
|
|
; DISABLE-NEXT: LBB2_1: ## %for.body
|
|
; DISABLE-NEXT: ## =>This Inner Loop Header: Depth=1
|
|
; DISABLE-NEXT: ## InlineAsm Start
|
|
; DISABLE-NEXT: movl $1, %edx
|
|
; DISABLE-NEXT: ## InlineAsm End
|
|
; DISABLE-NEXT: addl %edx, %eax
|
|
; DISABLE-NEXT: decl %ecx
|
|
; DISABLE-NEXT: jne LBB2_1
|
|
; DISABLE-NEXT: ## %bb.2: ## %for.exit
|
|
; DISABLE-NEXT: ## InlineAsm Start
|
|
; DISABLE-NEXT: nop
|
|
; DISABLE-NEXT: ## InlineAsm End
|
|
; DISABLE-NEXT: popq %rbx
|
|
; DISABLE-NEXT: retq
|
|
entry:
|
|
br label %for.preheader
|
|
|
|
for.preheader:
|
|
tail call void asm "nop", ""()
|
|
br label %for.body
|
|
|
|
for.body: ; preds = %for.body, %entry
|
|
%i.04 = phi i32 [ 0, %for.preheader ], [ %inc, %for.body ]
|
|
%sum.03 = phi i32 [ 0, %for.preheader ], [ %add, %for.body ]
|
|
%call = tail call i32 asm sideeffect "movl $$1, $0", "=r,~{ebx}"()
|
|
%add = add nsw i32 %call, %sum.03
|
|
%inc = add nuw nsw i32 %i.04, 1
|
|
%exitcond = icmp eq i32 %inc, 10
|
|
br i1 %exitcond, label %for.exit, label %for.body
|
|
|
|
for.exit:
|
|
tail call void asm "nop", ""()
|
|
br label %for.end
|
|
|
|
for.end: ; preds = %for.body
|
|
ret i32 %add
|
|
}
|
|
|
|
; Check with a more complex case that we do not have save within the loop and
|
|
; restore outside.
|
|
define i32 @loopInfoSaveOutsideLoop(i32 %cond, i32 %N) {
|
|
; ENABLE-LABEL: loopInfoSaveOutsideLoop:
|
|
; ENABLE: ## %bb.0: ## %entry
|
|
; ENABLE-NEXT: testl %edi, %edi
|
|
; ENABLE-NEXT: je LBB3_4
|
|
; ENABLE-NEXT: ## %bb.1: ## %for.preheader
|
|
; ENABLE-NEXT: pushq %rbx
|
|
; ENABLE-NEXT: .cfi_def_cfa_offset 16
|
|
; ENABLE-NEXT: .cfi_offset %rbx, -16
|
|
; ENABLE-NEXT: ## InlineAsm Start
|
|
; ENABLE-NEXT: nop
|
|
; ENABLE-NEXT: ## InlineAsm End
|
|
; ENABLE-NEXT: xorl %eax, %eax
|
|
; ENABLE-NEXT: movl $10, %ecx
|
|
; ENABLE-NEXT: .p2align 4, 0x90
|
|
; ENABLE-NEXT: LBB3_2: ## %for.body
|
|
; ENABLE-NEXT: ## =>This Inner Loop Header: Depth=1
|
|
; ENABLE-NEXT: ## InlineAsm Start
|
|
; ENABLE-NEXT: movl $1, %edx
|
|
; ENABLE-NEXT: ## InlineAsm End
|
|
; ENABLE-NEXT: addl %edx, %eax
|
|
; ENABLE-NEXT: decl %ecx
|
|
; ENABLE-NEXT: jne LBB3_2
|
|
; ENABLE-NEXT: ## %bb.3: ## %for.end
|
|
; ENABLE-NEXT: ## InlineAsm Start
|
|
; ENABLE-NEXT: nop
|
|
; ENABLE-NEXT: ## InlineAsm End
|
|
; ENABLE-NEXT: shll $3, %eax
|
|
; ENABLE-NEXT: popq %rbx
|
|
; ENABLE-NEXT: retq
|
|
; ENABLE-NEXT: LBB3_4: ## %if.else
|
|
; ENABLE-NEXT: movl %esi, %eax
|
|
; ENABLE-NEXT: addl %esi, %eax
|
|
; ENABLE-NEXT: retq
|
|
;
|
|
; DISABLE-LABEL: loopInfoSaveOutsideLoop:
|
|
; DISABLE: ## %bb.0: ## %entry
|
|
; DISABLE-NEXT: pushq %rbx
|
|
; DISABLE-NEXT: .cfi_def_cfa_offset 16
|
|
; DISABLE-NEXT: .cfi_offset %rbx, -16
|
|
; DISABLE-NEXT: testl %edi, %edi
|
|
; DISABLE-NEXT: je LBB3_4
|
|
; DISABLE-NEXT: ## %bb.1: ## %for.preheader
|
|
; DISABLE-NEXT: ## InlineAsm Start
|
|
; DISABLE-NEXT: nop
|
|
; DISABLE-NEXT: ## InlineAsm End
|
|
; DISABLE-NEXT: xorl %eax, %eax
|
|
; DISABLE-NEXT: movl $10, %ecx
|
|
; DISABLE-NEXT: .p2align 4, 0x90
|
|
; DISABLE-NEXT: LBB3_2: ## %for.body
|
|
; DISABLE-NEXT: ## =>This Inner Loop Header: Depth=1
|
|
; DISABLE-NEXT: ## InlineAsm Start
|
|
; DISABLE-NEXT: movl $1, %edx
|
|
; DISABLE-NEXT: ## InlineAsm End
|
|
; DISABLE-NEXT: addl %edx, %eax
|
|
; DISABLE-NEXT: decl %ecx
|
|
; DISABLE-NEXT: jne LBB3_2
|
|
; DISABLE-NEXT: ## %bb.3: ## %for.end
|
|
; DISABLE-NEXT: ## InlineAsm Start
|
|
; DISABLE-NEXT: nop
|
|
; DISABLE-NEXT: ## InlineAsm End
|
|
; DISABLE-NEXT: shll $3, %eax
|
|
; DISABLE-NEXT: popq %rbx
|
|
; DISABLE-NEXT: retq
|
|
; DISABLE-NEXT: LBB3_4: ## %if.else
|
|
; DISABLE-NEXT: movl %esi, %eax
|
|
; DISABLE-NEXT: addl %esi, %eax
|
|
; DISABLE-NEXT: popq %rbx
|
|
; DISABLE-NEXT: retq
|
|
entry:
|
|
%tobool = icmp eq i32 %cond, 0
|
|
br i1 %tobool, label %if.else, label %for.preheader
|
|
|
|
for.preheader:
|
|
tail call void asm "nop", ""()
|
|
br label %for.body
|
|
|
|
for.body: ; preds = %entry, %for.body
|
|
%i.05 = phi i32 [ %inc, %for.body ], [ 0, %for.preheader ]
|
|
%sum.04 = phi i32 [ %add, %for.body ], [ 0, %for.preheader ]
|
|
%call = tail call i32 asm sideeffect "movl $$1, $0", "=r,~{ebx}"()
|
|
%add = add nsw i32 %call, %sum.04
|
|
%inc = add nuw nsw i32 %i.05, 1
|
|
%exitcond = icmp eq i32 %inc, 10
|
|
br i1 %exitcond, label %for.end, label %for.body
|
|
|
|
for.end: ; preds = %for.body
|
|
tail call void asm "nop", "~{ebx}"()
|
|
%shl = shl i32 %add, 3
|
|
br label %if.end
|
|
|
|
if.else: ; preds = %entry
|
|
%mul = shl nsw i32 %N, 1
|
|
br label %if.end
|
|
|
|
if.end: ; preds = %if.else, %for.end
|
|
%sum.1 = phi i32 [ %shl, %for.end ], [ %mul, %if.else ]
|
|
ret i32 %sum.1
|
|
}
|
|
|
|
; Check with a more complex case that we do not have restore within the loop and
|
|
; save outside.
|
|
define i32 @loopInfoRestoreOutsideLoop(i32 %cond, i32 %N) nounwind {
|
|
; ENABLE-LABEL: loopInfoRestoreOutsideLoop:
|
|
; ENABLE: ## %bb.0: ## %entry
|
|
; ENABLE-NEXT: testl %edi, %edi
|
|
; ENABLE-NEXT: je LBB4_4
|
|
; ENABLE-NEXT: ## %bb.1: ## %if.then
|
|
; ENABLE-NEXT: pushq %rbx
|
|
; ENABLE-NEXT: ## InlineAsm Start
|
|
; ENABLE-NEXT: nop
|
|
; ENABLE-NEXT: ## InlineAsm End
|
|
; ENABLE-NEXT: xorl %eax, %eax
|
|
; ENABLE-NEXT: movl $10, %ecx
|
|
; ENABLE-NEXT: .p2align 4, 0x90
|
|
; ENABLE-NEXT: LBB4_2: ## %for.body
|
|
; ENABLE-NEXT: ## =>This Inner Loop Header: Depth=1
|
|
; ENABLE-NEXT: ## InlineAsm Start
|
|
; ENABLE-NEXT: movl $1, %edx
|
|
; ENABLE-NEXT: ## InlineAsm End
|
|
; ENABLE-NEXT: addl %edx, %eax
|
|
; ENABLE-NEXT: decl %ecx
|
|
; ENABLE-NEXT: jne LBB4_2
|
|
; ENABLE-NEXT: ## %bb.3: ## %for.end
|
|
; ENABLE-NEXT: shll $3, %eax
|
|
; ENABLE-NEXT: popq %rbx
|
|
; ENABLE-NEXT: retq
|
|
; ENABLE-NEXT: LBB4_4: ## %if.else
|
|
; ENABLE-NEXT: movl %esi, %eax
|
|
; ENABLE-NEXT: addl %esi, %eax
|
|
; ENABLE-NEXT: retq
|
|
;
|
|
; DISABLE-LABEL: loopInfoRestoreOutsideLoop:
|
|
; DISABLE: ## %bb.0: ## %entry
|
|
; DISABLE-NEXT: pushq %rbx
|
|
; DISABLE-NEXT: testl %edi, %edi
|
|
; DISABLE-NEXT: je LBB4_4
|
|
; DISABLE-NEXT: ## %bb.1: ## %if.then
|
|
; DISABLE-NEXT: ## InlineAsm Start
|
|
; DISABLE-NEXT: nop
|
|
; DISABLE-NEXT: ## InlineAsm End
|
|
; DISABLE-NEXT: xorl %eax, %eax
|
|
; DISABLE-NEXT: movl $10, %ecx
|
|
; DISABLE-NEXT: .p2align 4, 0x90
|
|
; DISABLE-NEXT: LBB4_2: ## %for.body
|
|
; DISABLE-NEXT: ## =>This Inner Loop Header: Depth=1
|
|
; DISABLE-NEXT: ## InlineAsm Start
|
|
; DISABLE-NEXT: movl $1, %edx
|
|
; DISABLE-NEXT: ## InlineAsm End
|
|
; DISABLE-NEXT: addl %edx, %eax
|
|
; DISABLE-NEXT: decl %ecx
|
|
; DISABLE-NEXT: jne LBB4_2
|
|
; DISABLE-NEXT: ## %bb.3: ## %for.end
|
|
; DISABLE-NEXT: shll $3, %eax
|
|
; DISABLE-NEXT: popq %rbx
|
|
; DISABLE-NEXT: retq
|
|
; DISABLE-NEXT: LBB4_4: ## %if.else
|
|
; DISABLE-NEXT: movl %esi, %eax
|
|
; DISABLE-NEXT: addl %esi, %eax
|
|
; DISABLE-NEXT: popq %rbx
|
|
; DISABLE-NEXT: retq
|
|
entry:
|
|
%tobool = icmp eq i32 %cond, 0
|
|
br i1 %tobool, label %if.else, label %if.then
|
|
|
|
if.then: ; preds = %entry
|
|
tail call void asm "nop", "~{ebx}"()
|
|
br label %for.body
|
|
|
|
for.body: ; preds = %for.body, %if.then
|
|
%i.05 = phi i32 [ 0, %if.then ], [ %inc, %for.body ]
|
|
%sum.04 = phi i32 [ 0, %if.then ], [ %add, %for.body ]
|
|
%call = tail call i32 asm sideeffect "movl $$1, $0", "=r,~{ebx}"()
|
|
%add = add nsw i32 %call, %sum.04
|
|
%inc = add nuw nsw i32 %i.05, 1
|
|
%exitcond = icmp eq i32 %inc, 10
|
|
br i1 %exitcond, label %for.end, label %for.body
|
|
|
|
for.end: ; preds = %for.body
|
|
%shl = shl i32 %add, 3
|
|
br label %if.end
|
|
|
|
if.else: ; preds = %entry
|
|
%mul = shl nsw i32 %N, 1
|
|
br label %if.end
|
|
|
|
if.end: ; preds = %if.else, %for.end
|
|
%sum.1 = phi i32 [ %shl, %for.end ], [ %mul, %if.else ]
|
|
ret i32 %sum.1
|
|
}
|
|
|
|
; Check that we handle function with no frame information correctly.
|
|
define i32 @emptyFrame() {
|
|
; ENABLE-LABEL: emptyFrame:
|
|
; ENABLE: ## %bb.0: ## %entry
|
|
; ENABLE-NEXT: xorl %eax, %eax
|
|
; ENABLE-NEXT: retq
|
|
;
|
|
; DISABLE-LABEL: emptyFrame:
|
|
; DISABLE: ## %bb.0: ## %entry
|
|
; DISABLE-NEXT: xorl %eax, %eax
|
|
; DISABLE-NEXT: retq
|
|
entry:
|
|
ret i32 0
|
|
}
|
|
|
|
; Check that we handle inline asm correctly.
|
|
define i32 @inlineAsm(i32 %cond, i32 %N) {
|
|
; ENABLE-LABEL: inlineAsm:
|
|
; ENABLE: ## %bb.0: ## %entry
|
|
; ENABLE-NEXT: testl %edi, %edi
|
|
; ENABLE-NEXT: je LBB6_4
|
|
; ENABLE-NEXT: ## %bb.1: ## %for.preheader
|
|
; ENABLE-NEXT: pushq %rbx
|
|
; ENABLE-NEXT: .cfi_def_cfa_offset 16
|
|
; ENABLE-NEXT: .cfi_offset %rbx, -16
|
|
; ENABLE-NEXT: ## InlineAsm Start
|
|
; ENABLE-NEXT: nop
|
|
; ENABLE-NEXT: ## InlineAsm End
|
|
; ENABLE-NEXT: movl $10, %eax
|
|
; ENABLE-NEXT: .p2align 4, 0x90
|
|
; ENABLE-NEXT: LBB6_2: ## %for.body
|
|
; ENABLE-NEXT: ## =>This Inner Loop Header: Depth=1
|
|
; ENABLE-NEXT: ## InlineAsm Start
|
|
; ENABLE-NEXT: addl $1, %ebx
|
|
; ENABLE-NEXT: ## InlineAsm End
|
|
; ENABLE-NEXT: decl %eax
|
|
; ENABLE-NEXT: jne LBB6_2
|
|
; ENABLE-NEXT: ## %bb.3: ## %for.exit
|
|
; ENABLE-NEXT: ## InlineAsm Start
|
|
; ENABLE-NEXT: nop
|
|
; ENABLE-NEXT: ## InlineAsm End
|
|
; ENABLE-NEXT: xorl %eax, %eax
|
|
; ENABLE-NEXT: popq %rbx
|
|
; ENABLE-NEXT: retq
|
|
; ENABLE-NEXT: LBB6_4: ## %if.else
|
|
; ENABLE-NEXT: movl %esi, %eax
|
|
; ENABLE-NEXT: addl %esi, %eax
|
|
; ENABLE-NEXT: retq
|
|
;
|
|
; DISABLE-LABEL: inlineAsm:
|
|
; DISABLE: ## %bb.0: ## %entry
|
|
; DISABLE-NEXT: pushq %rbx
|
|
; DISABLE-NEXT: .cfi_def_cfa_offset 16
|
|
; DISABLE-NEXT: .cfi_offset %rbx, -16
|
|
; DISABLE-NEXT: testl %edi, %edi
|
|
; DISABLE-NEXT: je LBB6_4
|
|
; DISABLE-NEXT: ## %bb.1: ## %for.preheader
|
|
; DISABLE-NEXT: ## InlineAsm Start
|
|
; DISABLE-NEXT: nop
|
|
; DISABLE-NEXT: ## InlineAsm End
|
|
; DISABLE-NEXT: movl $10, %eax
|
|
; DISABLE-NEXT: .p2align 4, 0x90
|
|
; DISABLE-NEXT: LBB6_2: ## %for.body
|
|
; DISABLE-NEXT: ## =>This Inner Loop Header: Depth=1
|
|
; DISABLE-NEXT: ## InlineAsm Start
|
|
; DISABLE-NEXT: addl $1, %ebx
|
|
; DISABLE-NEXT: ## InlineAsm End
|
|
; DISABLE-NEXT: decl %eax
|
|
; DISABLE-NEXT: jne LBB6_2
|
|
; DISABLE-NEXT: ## %bb.3: ## %for.exit
|
|
; DISABLE-NEXT: ## InlineAsm Start
|
|
; DISABLE-NEXT: nop
|
|
; DISABLE-NEXT: ## InlineAsm End
|
|
; DISABLE-NEXT: xorl %eax, %eax
|
|
; DISABLE-NEXT: popq %rbx
|
|
; DISABLE-NEXT: retq
|
|
; DISABLE-NEXT: LBB6_4: ## %if.else
|
|
; DISABLE-NEXT: movl %esi, %eax
|
|
; DISABLE-NEXT: addl %esi, %eax
|
|
; DISABLE-NEXT: popq %rbx
|
|
; DISABLE-NEXT: retq
|
|
entry:
|
|
%tobool = icmp eq i32 %cond, 0
|
|
br i1 %tobool, label %if.else, label %for.preheader
|
|
|
|
for.preheader:
|
|
tail call void asm "nop", ""()
|
|
br label %for.body
|
|
|
|
for.body: ; preds = %entry, %for.body
|
|
%i.03 = phi i32 [ %inc, %for.body ], [ 0, %for.preheader ]
|
|
tail call void asm "addl $$1, %ebx", "~{ebx}"()
|
|
%inc = add nuw nsw i32 %i.03, 1
|
|
%exitcond = icmp eq i32 %inc, 10
|
|
br i1 %exitcond, label %for.exit, label %for.body
|
|
|
|
for.exit:
|
|
tail call void asm "nop", ""()
|
|
br label %if.end
|
|
|
|
if.else: ; preds = %entry
|
|
%mul = shl nsw i32 %N, 1
|
|
br label %if.end
|
|
|
|
if.end: ; preds = %for.body, %if.else
|
|
%sum.0 = phi i32 [ %mul, %if.else ], [ 0, %for.exit ]
|
|
ret i32 %sum.0
|
|
}
|
|
|
|
; Check that we handle calls to variadic functions correctly.
|
|
define i32 @callVariadicFunc(i32 %cond, i32 %N) {
|
|
; ENABLE-LABEL: callVariadicFunc:
|
|
; ENABLE: ## %bb.0: ## %entry
|
|
; ENABLE-NEXT: movl %esi, %eax
|
|
; ENABLE-NEXT: testl %edi, %edi
|
|
; ENABLE-NEXT: je LBB7_2
|
|
; ENABLE-NEXT: ## %bb.1: ## %if.then
|
|
; ENABLE-NEXT: pushq %rax
|
|
; ENABLE-NEXT: .cfi_def_cfa_offset 16
|
|
; ENABLE-NEXT: movl %eax, (%rsp)
|
|
; ENABLE-NEXT: movl %eax, %edi
|
|
; ENABLE-NEXT: movl %eax, %esi
|
|
; ENABLE-NEXT: movl %eax, %edx
|
|
; ENABLE-NEXT: movl %eax, %ecx
|
|
; ENABLE-NEXT: movl %eax, %r8d
|
|
; ENABLE-NEXT: movl %eax, %r9d
|
|
; ENABLE-NEXT: xorl %eax, %eax
|
|
; ENABLE-NEXT: callq _someVariadicFunc
|
|
; ENABLE-NEXT: shll $3, %eax
|
|
; ENABLE-NEXT: addq $8, %rsp
|
|
; ENABLE-NEXT: retq
|
|
; ENABLE-NEXT: LBB7_2: ## %if.else
|
|
; ENABLE-NEXT: addl %eax, %eax
|
|
; ENABLE-NEXT: retq
|
|
;
|
|
; DISABLE-LABEL: callVariadicFunc:
|
|
; DISABLE: ## %bb.0: ## %entry
|
|
; DISABLE-NEXT: pushq %rax
|
|
; DISABLE-NEXT: .cfi_def_cfa_offset 16
|
|
; DISABLE-NEXT: movl %esi, %eax
|
|
; DISABLE-NEXT: testl %edi, %edi
|
|
; DISABLE-NEXT: je LBB7_2
|
|
; DISABLE-NEXT: ## %bb.1: ## %if.then
|
|
; DISABLE-NEXT: movl %eax, (%rsp)
|
|
; DISABLE-NEXT: movl %eax, %edi
|
|
; DISABLE-NEXT: movl %eax, %esi
|
|
; DISABLE-NEXT: movl %eax, %edx
|
|
; DISABLE-NEXT: movl %eax, %ecx
|
|
; DISABLE-NEXT: movl %eax, %r8d
|
|
; DISABLE-NEXT: movl %eax, %r9d
|
|
; DISABLE-NEXT: xorl %eax, %eax
|
|
; DISABLE-NEXT: callq _someVariadicFunc
|
|
; DISABLE-NEXT: shll $3, %eax
|
|
; DISABLE-NEXT: popq %rcx
|
|
; DISABLE-NEXT: retq
|
|
; DISABLE-NEXT: LBB7_2: ## %if.else
|
|
; DISABLE-NEXT: addl %eax, %eax
|
|
; DISABLE-NEXT: popq %rcx
|
|
; DISABLE-NEXT: retq
|
|
entry:
|
|
%tobool = icmp eq i32 %cond, 0
|
|
br i1 %tobool, label %if.else, label %if.then
|
|
|
|
if.then: ; preds = %entry
|
|
%call = tail call i32 (i32, ...) @someVariadicFunc(i32 %N, i32 %N, i32 %N, i32 %N, i32 %N, i32 %N, i32 %N)
|
|
%shl = shl i32 %call, 3
|
|
br label %if.end
|
|
|
|
if.else: ; preds = %entry
|
|
%mul = shl nsw i32 %N, 1
|
|
br label %if.end
|
|
|
|
if.end: ; preds = %if.else, %if.then
|
|
%sum.0 = phi i32 [ %shl, %if.then ], [ %mul, %if.else ]
|
|
ret i32 %sum.0
|
|
}
|
|
|
|
declare i32 @someVariadicFunc(i32, ...)
|
|
|
|
; Check that we use LEA not to clobber EFLAGS.
|
|
%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 }
|
|
%union.tree_node = type { %struct.tree_decl }
|
|
%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* }
|
|
%struct.tree_common = type { %union.tree_node*, %union.tree_node*, i32 }
|
|
%union.anon = type { i64 }
|
|
%union.anon.1 = type { %struct.function* }
|
|
%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 }
|
|
%struct.eh_status = type opaque
|
|
%struct.stmt_status = type opaque
|
|
%struct.expr_status = type { i32, i32, i32, %struct.rtx_def*, %struct.rtx_def*, %struct.rtx_def*, %struct.rtx_def* }
|
|
%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** }
|
|
%struct.sequence_stack = type { %struct.rtx_def*, %struct.rtx_def*, %union.tree_node*, %struct.sequence_stack* }
|
|
%struct.varasm_status = type opaque
|
|
%struct.ix86_args = type { i32, i32, i32, i32, i32, i32, i32 }
|
|
%struct.initial_value_struct = type opaque
|
|
%struct.var_refs_queue = type { %struct.rtx_def*, i32, i32, %struct.var_refs_queue* }
|
|
%struct.machine_function = type opaque
|
|
%struct.language_function = type opaque
|
|
%struct.lang_decl = type opaque
|
|
%struct.rtx_def = type { i32, [1 x %union.rtunion_def] }
|
|
%union.rtunion_def = type { i64 }
|
|
|
|
declare hidden fastcc %struct.temp_slot* @find_temp_slot_from_address(%struct.rtx_def* readonly)
|
|
|
|
define void @useLEA(%struct.rtx_def* readonly %x) {
|
|
; ENABLE-LABEL: useLEA:
|
|
; ENABLE: ## %bb.0: ## %entry
|
|
; ENABLE-NEXT: pushq %rax
|
|
; ENABLE-NEXT: .cfi_def_cfa_offset 16
|
|
; ENABLE-NEXT: testq %rdi, %rdi
|
|
; ENABLE-NEXT: je LBB8_7
|
|
; ENABLE-NEXT: ## %bb.1: ## %if.end
|
|
; ENABLE-NEXT: cmpw $66, (%rdi)
|
|
; ENABLE-NEXT: jne LBB8_7
|
|
; ENABLE-NEXT: ## %bb.2: ## %lor.lhs.false
|
|
; ENABLE-NEXT: movq 8(%rdi), %rdi
|
|
; ENABLE-NEXT: movzwl (%rdi), %eax
|
|
; ENABLE-NEXT: leal -54(%rax), %ecx
|
|
; ENABLE-NEXT: cmpl $14, %ecx
|
|
; ENABLE-NEXT: ja LBB8_3
|
|
; ENABLE-NEXT: ## %bb.8: ## %lor.lhs.false
|
|
; ENABLE-NEXT: movl $24599, %edx ## imm = 0x6017
|
|
; ENABLE-NEXT: btl %ecx, %edx
|
|
; ENABLE-NEXT: jae LBB8_3
|
|
; ENABLE-NEXT: LBB8_7: ## %cleanup
|
|
; ENABLE-NEXT: popq %rax
|
|
; ENABLE-NEXT: retq
|
|
; ENABLE-NEXT: LBB8_3: ## %lor.lhs.false
|
|
; ENABLE-NEXT: cmpl $134, %eax
|
|
; ENABLE-NEXT: je LBB8_7
|
|
; ENABLE-NEXT: ## %bb.4: ## %lor.lhs.false
|
|
; ENABLE-NEXT: cmpl $140, %eax
|
|
; ENABLE-NEXT: je LBB8_7
|
|
; ENABLE-NEXT: ## %bb.5: ## %if.end.55
|
|
; ENABLE-NEXT: callq _find_temp_slot_from_address
|
|
; ENABLE-NEXT: testq %rax, %rax
|
|
; ENABLE-NEXT: je LBB8_7
|
|
; ENABLE-NEXT: ## %bb.6: ## %if.then.60
|
|
; ENABLE-NEXT: movb $1, 57(%rax)
|
|
; ENABLE-NEXT: popq %rax
|
|
; ENABLE-NEXT: retq
|
|
;
|
|
; DISABLE-LABEL: useLEA:
|
|
; DISABLE: ## %bb.0: ## %entry
|
|
; DISABLE-NEXT: pushq %rax
|
|
; DISABLE-NEXT: .cfi_def_cfa_offset 16
|
|
; DISABLE-NEXT: testq %rdi, %rdi
|
|
; DISABLE-NEXT: je LBB8_7
|
|
; DISABLE-NEXT: ## %bb.1: ## %if.end
|
|
; DISABLE-NEXT: cmpw $66, (%rdi)
|
|
; DISABLE-NEXT: jne LBB8_7
|
|
; DISABLE-NEXT: ## %bb.2: ## %lor.lhs.false
|
|
; DISABLE-NEXT: movq 8(%rdi), %rdi
|
|
; DISABLE-NEXT: movzwl (%rdi), %eax
|
|
; DISABLE-NEXT: leal -54(%rax), %ecx
|
|
; DISABLE-NEXT: cmpl $14, %ecx
|
|
; DISABLE-NEXT: ja LBB8_3
|
|
; DISABLE-NEXT: ## %bb.8: ## %lor.lhs.false
|
|
; DISABLE-NEXT: movl $24599, %edx ## imm = 0x6017
|
|
; DISABLE-NEXT: btl %ecx, %edx
|
|
; DISABLE-NEXT: jae LBB8_3
|
|
; DISABLE-NEXT: LBB8_7: ## %cleanup
|
|
; DISABLE-NEXT: popq %rax
|
|
; DISABLE-NEXT: retq
|
|
; DISABLE-NEXT: LBB8_3: ## %lor.lhs.false
|
|
; DISABLE-NEXT: cmpl $134, %eax
|
|
; DISABLE-NEXT: je LBB8_7
|
|
; DISABLE-NEXT: ## %bb.4: ## %lor.lhs.false
|
|
; DISABLE-NEXT: cmpl $140, %eax
|
|
; DISABLE-NEXT: je LBB8_7
|
|
; DISABLE-NEXT: ## %bb.5: ## %if.end.55
|
|
; DISABLE-NEXT: callq _find_temp_slot_from_address
|
|
; DISABLE-NEXT: testq %rax, %rax
|
|
; DISABLE-NEXT: je LBB8_7
|
|
; DISABLE-NEXT: ## %bb.6: ## %if.then.60
|
|
; DISABLE-NEXT: movb $1, 57(%rax)
|
|
; DISABLE-NEXT: popq %rax
|
|
; DISABLE-NEXT: retq
|
|
entry:
|
|
%cmp = icmp eq %struct.rtx_def* %x, null
|
|
br i1 %cmp, label %cleanup, label %if.end
|
|
|
|
if.end: ; preds = %entry
|
|
%tmp = getelementptr inbounds %struct.rtx_def, %struct.rtx_def* %x, i64 0, i32 0
|
|
%bf.load = load i32, i32* %tmp, align 8
|
|
%bf.clear = and i32 %bf.load, 65535
|
|
%cmp1 = icmp eq i32 %bf.clear, 66
|
|
br i1 %cmp1, label %lor.lhs.false, label %cleanup
|
|
|
|
lor.lhs.false: ; preds = %if.end
|
|
%arrayidx = getelementptr inbounds %struct.rtx_def, %struct.rtx_def* %x, i64 0, i32 1, i64 0
|
|
%rtx = bitcast %union.rtunion_def* %arrayidx to %struct.rtx_def**
|
|
%tmp1 = load %struct.rtx_def*, %struct.rtx_def** %rtx, align 8
|
|
%tmp2 = getelementptr inbounds %struct.rtx_def, %struct.rtx_def* %tmp1, i64 0, i32 0
|
|
%bf.load2 = load i32, i32* %tmp2, align 8
|
|
%bf.clear3 = and i32 %bf.load2, 65535
|
|
switch i32 %bf.clear3, label %if.end.55 [
|
|
i32 67, label %cleanup
|
|
i32 68, label %cleanup
|
|
i32 54, label %cleanup
|
|
i32 55, label %cleanup
|
|
i32 58, label %cleanup
|
|
i32 134, label %cleanup
|
|
i32 56, label %cleanup
|
|
i32 140, label %cleanup
|
|
]
|
|
|
|
if.end.55: ; preds = %lor.lhs.false
|
|
%call = tail call fastcc %struct.temp_slot* @find_temp_slot_from_address(%struct.rtx_def* %tmp1) #2
|
|
%cmp59 = icmp eq %struct.temp_slot* %call, null
|
|
br i1 %cmp59, label %cleanup, label %if.then.60
|
|
|
|
if.then.60: ; preds = %if.end.55
|
|
%addr_taken = getelementptr inbounds %struct.temp_slot, %struct.temp_slot* %call, i64 0, i32 8
|
|
store i8 1, i8* %addr_taken, align 1
|
|
br label %cleanup
|
|
|
|
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
|
|
ret void
|
|
}
|
|
|
|
; Make sure we do not insert unreachable code after noreturn function.
|
|
; Although this is not incorrect to insert such code, it is useless
|
|
; and it hurts the binary size.
|
|
define i32 @noreturn(i8 signext %bad_thing) {
|
|
; ENABLE-LABEL: noreturn:
|
|
; ENABLE: ## %bb.0: ## %entry
|
|
; ENABLE-NEXT: testb %dil, %dil
|
|
; ENABLE-NEXT: jne LBB9_2
|
|
; ENABLE-NEXT: ## %bb.1: ## %if.end
|
|
; ENABLE-NEXT: movl $42, %eax
|
|
; ENABLE-NEXT: retq
|
|
; ENABLE-NEXT: LBB9_2: ## %if.abort
|
|
; ENABLE-NEXT: pushq %rax
|
|
; ENABLE-NEXT: .cfi_def_cfa_offset 16
|
|
; ENABLE-NEXT: callq _abort
|
|
;
|
|
; DISABLE-LABEL: noreturn:
|
|
; DISABLE: ## %bb.0: ## %entry
|
|
; DISABLE-NEXT: pushq %rax
|
|
; DISABLE-NEXT: .cfi_def_cfa_offset 16
|
|
; DISABLE-NEXT: testb %dil, %dil
|
|
; DISABLE-NEXT: jne LBB9_2
|
|
; DISABLE-NEXT: ## %bb.1: ## %if.end
|
|
; DISABLE-NEXT: movl $42, %eax
|
|
; DISABLE-NEXT: popq %rcx
|
|
; DISABLE-NEXT: retq
|
|
; DISABLE-NEXT: LBB9_2: ## %if.abort
|
|
; DISABLE-NEXT: callq _abort
|
|
entry:
|
|
%tobool = icmp eq i8 %bad_thing, 0
|
|
br i1 %tobool, label %if.end, label %if.abort
|
|
|
|
if.abort:
|
|
tail call void @abort() #0
|
|
unreachable
|
|
|
|
if.end:
|
|
ret i32 42
|
|
}
|
|
|
|
declare void @abort() #0
|
|
|
|
attributes #0 = { noreturn nounwind }
|
|
|
|
|
|
; Make sure that we handle infinite loops properly When checking that the Save
|
|
; and Restore blocks are control flow equivalent, the loop searches for the
|
|
; immediate (post) dominator for the (restore) save blocks. When either the Save
|
|
; or Restore block is located in an infinite loop the only immediate (post)
|
|
; dominator is itself. In this case, we cannot perform shrink wrapping, but we
|
|
; should return gracefully and continue compilation.
|
|
; The only condition for this test is the compilation finishes correctly.
|
|
;
|
|
define void @infiniteloop() {
|
|
; ENABLE-LABEL: infiniteloop:
|
|
; ENABLE: ## %bb.0: ## %entry
|
|
; ENABLE-NEXT: pushq %rbp
|
|
; ENABLE-NEXT: .cfi_def_cfa_offset 16
|
|
; ENABLE-NEXT: .cfi_offset %rbp, -16
|
|
; ENABLE-NEXT: movq %rsp, %rbp
|
|
; ENABLE-NEXT: .cfi_def_cfa_register %rbp
|
|
; ENABLE-NEXT: pushq %rbx
|
|
; ENABLE-NEXT: pushq %rax
|
|
; ENABLE-NEXT: .cfi_offset %rbx, -24
|
|
; ENABLE-NEXT: xorl %eax, %eax
|
|
; ENABLE-NEXT: testb %al, %al
|
|
; ENABLE-NEXT: jne LBB10_3
|
|
; ENABLE-NEXT: ## %bb.1: ## %if.then
|
|
; ENABLE-NEXT: movq %rsp, %rcx
|
|
; ENABLE-NEXT: addq $-16, %rcx
|
|
; ENABLE-NEXT: movq %rcx, %rsp
|
|
; ENABLE-NEXT: ## InlineAsm Start
|
|
; ENABLE-NEXT: movl $1, %edx
|
|
; ENABLE-NEXT: ## InlineAsm End
|
|
; ENABLE-NEXT: .p2align 4, 0x90
|
|
; ENABLE-NEXT: LBB10_2: ## %for.body
|
|
; ENABLE-NEXT: ## =>This Inner Loop Header: Depth=1
|
|
; ENABLE-NEXT: addl %edx, %eax
|
|
; ENABLE-NEXT: movl %eax, (%rcx)
|
|
; ENABLE-NEXT: jmp LBB10_2
|
|
; ENABLE-NEXT: LBB10_3: ## %if.end
|
|
; ENABLE-NEXT: leaq -8(%rbp), %rsp
|
|
; ENABLE-NEXT: popq %rbx
|
|
; ENABLE-NEXT: popq %rbp
|
|
; ENABLE-NEXT: retq
|
|
;
|
|
; DISABLE-LABEL: infiniteloop:
|
|
; DISABLE: ## %bb.0: ## %entry
|
|
; DISABLE-NEXT: pushq %rbp
|
|
; DISABLE-NEXT: .cfi_def_cfa_offset 16
|
|
; DISABLE-NEXT: .cfi_offset %rbp, -16
|
|
; DISABLE-NEXT: movq %rsp, %rbp
|
|
; DISABLE-NEXT: .cfi_def_cfa_register %rbp
|
|
; DISABLE-NEXT: pushq %rbx
|
|
; DISABLE-NEXT: pushq %rax
|
|
; DISABLE-NEXT: .cfi_offset %rbx, -24
|
|
; DISABLE-NEXT: xorl %eax, %eax
|
|
; DISABLE-NEXT: testb %al, %al
|
|
; DISABLE-NEXT: jne LBB10_3
|
|
; DISABLE-NEXT: ## %bb.1: ## %if.then
|
|
; DISABLE-NEXT: movq %rsp, %rcx
|
|
; DISABLE-NEXT: addq $-16, %rcx
|
|
; DISABLE-NEXT: movq %rcx, %rsp
|
|
; DISABLE-NEXT: ## InlineAsm Start
|
|
; DISABLE-NEXT: movl $1, %edx
|
|
; DISABLE-NEXT: ## InlineAsm End
|
|
; DISABLE-NEXT: .p2align 4, 0x90
|
|
; DISABLE-NEXT: LBB10_2: ## %for.body
|
|
; DISABLE-NEXT: ## =>This Inner Loop Header: Depth=1
|
|
; DISABLE-NEXT: addl %edx, %eax
|
|
; DISABLE-NEXT: movl %eax, (%rcx)
|
|
; DISABLE-NEXT: jmp LBB10_2
|
|
; DISABLE-NEXT: LBB10_3: ## %if.end
|
|
; DISABLE-NEXT: leaq -8(%rbp), %rsp
|
|
; DISABLE-NEXT: popq %rbx
|
|
; DISABLE-NEXT: popq %rbp
|
|
; DISABLE-NEXT: retq
|
|
entry:
|
|
br i1 undef, label %if.then, label %if.end
|
|
|
|
if.then:
|
|
%ptr = alloca i32, i32 4
|
|
br label %for.body
|
|
|
|
for.body: ; preds = %for.body, %entry
|
|
%sum.03 = phi i32 [ 0, %if.then ], [ %add, %for.body ]
|
|
%call = tail call i32 asm "movl $$1, $0", "=r,~{ebx}"()
|
|
%add = add nsw i32 %call, %sum.03
|
|
store i32 %add, i32* %ptr
|
|
br label %for.body
|
|
|
|
if.end:
|
|
ret void
|
|
}
|
|
|
|
; Another infinite loop test this time with a body bigger than just one block.
|
|
define void @infiniteloop2() {
|
|
; ENABLE-LABEL: infiniteloop2:
|
|
; ENABLE: ## %bb.0: ## %entry
|
|
; ENABLE-NEXT: pushq %rbp
|
|
; ENABLE-NEXT: .cfi_def_cfa_offset 16
|
|
; ENABLE-NEXT: .cfi_offset %rbp, -16
|
|
; ENABLE-NEXT: movq %rsp, %rbp
|
|
; ENABLE-NEXT: .cfi_def_cfa_register %rbp
|
|
; ENABLE-NEXT: pushq %rbx
|
|
; ENABLE-NEXT: pushq %rax
|
|
; ENABLE-NEXT: .cfi_offset %rbx, -24
|
|
; ENABLE-NEXT: xorl %eax, %eax
|
|
; ENABLE-NEXT: testb %al, %al
|
|
; ENABLE-NEXT: jne LBB11_5
|
|
; ENABLE-NEXT: ## %bb.1: ## %if.then
|
|
; ENABLE-NEXT: movq %rsp, %rcx
|
|
; ENABLE-NEXT: addq $-16, %rcx
|
|
; ENABLE-NEXT: movq %rcx, %rsp
|
|
; ENABLE-NEXT: xorl %edx, %edx
|
|
; ENABLE-NEXT: jmp LBB11_2
|
|
; ENABLE-NEXT: .p2align 4, 0x90
|
|
; ENABLE-NEXT: LBB11_4: ## %body2
|
|
; ENABLE-NEXT: ## in Loop: Header=BB11_2 Depth=1
|
|
; ENABLE-NEXT: ## InlineAsm Start
|
|
; ENABLE-NEXT: nop
|
|
; ENABLE-NEXT: ## InlineAsm End
|
|
; ENABLE-NEXT: movl $1, %edx
|
|
; ENABLE-NEXT: LBB11_2: ## %for.body
|
|
; ENABLE-NEXT: ## =>This Inner Loop Header: Depth=1
|
|
; ENABLE-NEXT: movl %edx, %esi
|
|
; ENABLE-NEXT: ## InlineAsm Start
|
|
; ENABLE-NEXT: movl $1, %edx
|
|
; ENABLE-NEXT: ## InlineAsm End
|
|
; ENABLE-NEXT: addl %esi, %edx
|
|
; ENABLE-NEXT: movl %edx, (%rcx)
|
|
; ENABLE-NEXT: testb %al, %al
|
|
; ENABLE-NEXT: jne LBB11_4
|
|
; ENABLE-NEXT: ## %bb.3: ## %body1
|
|
; ENABLE-NEXT: ## in Loop: Header=BB11_2 Depth=1
|
|
; ENABLE-NEXT: ## InlineAsm Start
|
|
; ENABLE-NEXT: nop
|
|
; ENABLE-NEXT: ## InlineAsm End
|
|
; ENABLE-NEXT: jmp LBB11_2
|
|
; ENABLE-NEXT: LBB11_5: ## %if.end
|
|
; ENABLE-NEXT: leaq -8(%rbp), %rsp
|
|
; ENABLE-NEXT: popq %rbx
|
|
; ENABLE-NEXT: popq %rbp
|
|
; ENABLE-NEXT: retq
|
|
;
|
|
; DISABLE-LABEL: infiniteloop2:
|
|
; DISABLE: ## %bb.0: ## %entry
|
|
; DISABLE-NEXT: pushq %rbp
|
|
; DISABLE-NEXT: .cfi_def_cfa_offset 16
|
|
; DISABLE-NEXT: .cfi_offset %rbp, -16
|
|
; DISABLE-NEXT: movq %rsp, %rbp
|
|
; DISABLE-NEXT: .cfi_def_cfa_register %rbp
|
|
; DISABLE-NEXT: pushq %rbx
|
|
; DISABLE-NEXT: pushq %rax
|
|
; DISABLE-NEXT: .cfi_offset %rbx, -24
|
|
; DISABLE-NEXT: xorl %eax, %eax
|
|
; DISABLE-NEXT: testb %al, %al
|
|
; DISABLE-NEXT: jne LBB11_5
|
|
; DISABLE-NEXT: ## %bb.1: ## %if.then
|
|
; DISABLE-NEXT: movq %rsp, %rcx
|
|
; DISABLE-NEXT: addq $-16, %rcx
|
|
; DISABLE-NEXT: movq %rcx, %rsp
|
|
; DISABLE-NEXT: xorl %edx, %edx
|
|
; DISABLE-NEXT: jmp LBB11_2
|
|
; DISABLE-NEXT: .p2align 4, 0x90
|
|
; DISABLE-NEXT: LBB11_4: ## %body2
|
|
; DISABLE-NEXT: ## in Loop: Header=BB11_2 Depth=1
|
|
; DISABLE-NEXT: ## InlineAsm Start
|
|
; DISABLE-NEXT: nop
|
|
; DISABLE-NEXT: ## InlineAsm End
|
|
; DISABLE-NEXT: movl $1, %edx
|
|
; DISABLE-NEXT: LBB11_2: ## %for.body
|
|
; DISABLE-NEXT: ## =>This Inner Loop Header: Depth=1
|
|
; DISABLE-NEXT: movl %edx, %esi
|
|
; DISABLE-NEXT: ## InlineAsm Start
|
|
; DISABLE-NEXT: movl $1, %edx
|
|
; DISABLE-NEXT: ## InlineAsm End
|
|
; DISABLE-NEXT: addl %esi, %edx
|
|
; DISABLE-NEXT: movl %edx, (%rcx)
|
|
; DISABLE-NEXT: testb %al, %al
|
|
; DISABLE-NEXT: jne LBB11_4
|
|
; DISABLE-NEXT: ## %bb.3: ## %body1
|
|
; DISABLE-NEXT: ## in Loop: Header=BB11_2 Depth=1
|
|
; DISABLE-NEXT: ## InlineAsm Start
|
|
; DISABLE-NEXT: nop
|
|
; DISABLE-NEXT: ## InlineAsm End
|
|
; DISABLE-NEXT: jmp LBB11_2
|
|
; DISABLE-NEXT: LBB11_5: ## %if.end
|
|
; DISABLE-NEXT: leaq -8(%rbp), %rsp
|
|
; DISABLE-NEXT: popq %rbx
|
|
; DISABLE-NEXT: popq %rbp
|
|
; DISABLE-NEXT: retq
|
|
entry:
|
|
br i1 undef, label %if.then, label %if.end
|
|
|
|
if.then:
|
|
%ptr = alloca i32, i32 4
|
|
br label %for.body
|
|
|
|
for.body: ; preds = %for.body, %entry
|
|
%sum.03 = phi i32 [ 0, %if.then ], [ %add, %body1 ], [ 1, %body2]
|
|
%call = tail call i32 asm "movl $$1, $0", "=r,~{ebx}"()
|
|
%add = add nsw i32 %call, %sum.03
|
|
store i32 %add, i32* %ptr
|
|
br i1 undef, label %body1, label %body2
|
|
|
|
body1:
|
|
tail call void asm sideeffect "nop", "~{ebx}"()
|
|
br label %for.body
|
|
|
|
body2:
|
|
tail call void asm sideeffect "nop", "~{ebx}"()
|
|
br label %for.body
|
|
|
|
if.end:
|
|
ret void
|
|
}
|
|
|
|
; Another infinite loop test this time with two nested infinite loop.
|
|
define void @infiniteloop3() {
|
|
; ENABLE-LABEL: infiniteloop3:
|
|
; ENABLE: ## %bb.0: ## %entry
|
|
; ENABLE-NEXT: xorl %eax, %eax
|
|
; ENABLE-NEXT: testb %al, %al
|
|
; ENABLE-NEXT: jne LBB12_2
|
|
; ENABLE-NEXT: ## %bb.1: ## %body
|
|
; ENABLE-NEXT: xorl %eax, %eax
|
|
; ENABLE-NEXT: testb %al, %al
|
|
; ENABLE-NEXT: jne LBB12_7
|
|
; ENABLE-NEXT: LBB12_2: ## %loop2a.preheader
|
|
; ENABLE-NEXT: xorl %eax, %eax
|
|
; ENABLE-NEXT: xorl %ecx, %ecx
|
|
; ENABLE-NEXT: movq %rax, %rsi
|
|
; ENABLE-NEXT: jmp LBB12_4
|
|
; ENABLE-NEXT: .p2align 4, 0x90
|
|
; ENABLE-NEXT: LBB12_3: ## %loop2b
|
|
; ENABLE-NEXT: ## in Loop: Header=BB12_4 Depth=1
|
|
; ENABLE-NEXT: movq %rdx, (%rsi)
|
|
; ENABLE-NEXT: movq %rdx, %rsi
|
|
; ENABLE-NEXT: LBB12_4: ## %loop1
|
|
; ENABLE-NEXT: ## =>This Inner Loop Header: Depth=1
|
|
; ENABLE-NEXT: movq %rcx, %rdx
|
|
; ENABLE-NEXT: testq %rax, %rax
|
|
; ENABLE-NEXT: movq (%rax), %rcx
|
|
; ENABLE-NEXT: jne LBB12_3
|
|
; ENABLE-NEXT: ## %bb.5: ## in Loop: Header=BB12_4 Depth=1
|
|
; ENABLE-NEXT: movq %rdx, %rax
|
|
; ENABLE-NEXT: movq %rdx, %rsi
|
|
; ENABLE-NEXT: jmp LBB12_4
|
|
; ENABLE-NEXT: LBB12_7: ## %end
|
|
; ENABLE-NEXT: retq
|
|
;
|
|
; DISABLE-LABEL: infiniteloop3:
|
|
; DISABLE: ## %bb.0: ## %entry
|
|
; DISABLE-NEXT: xorl %eax, %eax
|
|
; DISABLE-NEXT: testb %al, %al
|
|
; DISABLE-NEXT: jne LBB12_2
|
|
; DISABLE-NEXT: ## %bb.1: ## %body
|
|
; DISABLE-NEXT: xorl %eax, %eax
|
|
; DISABLE-NEXT: testb %al, %al
|
|
; DISABLE-NEXT: jne LBB12_7
|
|
; DISABLE-NEXT: LBB12_2: ## %loop2a.preheader
|
|
; DISABLE-NEXT: xorl %eax, %eax
|
|
; DISABLE-NEXT: xorl %ecx, %ecx
|
|
; DISABLE-NEXT: movq %rax, %rsi
|
|
; DISABLE-NEXT: jmp LBB12_4
|
|
; DISABLE-NEXT: .p2align 4, 0x90
|
|
; DISABLE-NEXT: LBB12_3: ## %loop2b
|
|
; DISABLE-NEXT: ## in Loop: Header=BB12_4 Depth=1
|
|
; DISABLE-NEXT: movq %rdx, (%rsi)
|
|
; DISABLE-NEXT: movq %rdx, %rsi
|
|
; DISABLE-NEXT: LBB12_4: ## %loop1
|
|
; DISABLE-NEXT: ## =>This Inner Loop Header: Depth=1
|
|
; DISABLE-NEXT: movq %rcx, %rdx
|
|
; DISABLE-NEXT: testq %rax, %rax
|
|
; DISABLE-NEXT: movq (%rax), %rcx
|
|
; DISABLE-NEXT: jne LBB12_3
|
|
; DISABLE-NEXT: ## %bb.5: ## in Loop: Header=BB12_4 Depth=1
|
|
; DISABLE-NEXT: movq %rdx, %rax
|
|
; DISABLE-NEXT: movq %rdx, %rsi
|
|
; DISABLE-NEXT: jmp LBB12_4
|
|
; DISABLE-NEXT: LBB12_7: ## %end
|
|
; DISABLE-NEXT: retq
|
|
entry:
|
|
br i1 undef, label %loop2a, label %body
|
|
|
|
body: ; preds = %entry
|
|
br i1 undef, label %loop2a, label %end
|
|
|
|
loop1: ; preds = %loop2a, %loop2b
|
|
%var.phi = phi i32* [ %next.phi, %loop2b ], [ %var, %loop2a ]
|
|
%next.phi = phi i32* [ %next.load, %loop2b ], [ %next.var, %loop2a ]
|
|
%0 = icmp eq i32* %var, null
|
|
%next.load = load i32*, i32** undef
|
|
br i1 %0, label %loop2a, label %loop2b
|
|
|
|
loop2a: ; preds = %loop1, %body, %entry
|
|
%var = phi i32* [ null, %body ], [ null, %entry ], [ %next.phi, %loop1 ]
|
|
%next.var = phi i32* [ undef, %body ], [ null, %entry ], [ %next.load, %loop1 ]
|
|
br label %loop1
|
|
|
|
loop2b: ; preds = %loop1
|
|
%gep1 = bitcast i32* %var.phi to i32*
|
|
%next.ptr = bitcast i32* %gep1 to i32**
|
|
store i32* %next.phi, i32** %next.ptr
|
|
br label %loop1
|
|
|
|
end:
|
|
ret void
|
|
}
|
|
|
|
; Check that we just don't bail out on RegMask.
|
|
; In this case, the RegMask does not touch a CSR so we are good to go!
|
|
define i32 @regmask(i32 %a, i32 %b, i32* %addr) {
|
|
; ENABLE-LABEL: regmask:
|
|
; ENABLE: ## %bb.0:
|
|
; ENABLE-NEXT: cmpl %esi, %edi
|
|
; ENABLE-NEXT: jge LBB13_2
|
|
; ENABLE-NEXT: ## %bb.1: ## %true
|
|
; ENABLE-NEXT: pushq %rbx
|
|
; ENABLE-NEXT: .cfi_def_cfa_offset 16
|
|
; ENABLE-NEXT: .cfi_offset %rbx, -16
|
|
; ENABLE-NEXT: ## InlineAsm Start
|
|
; ENABLE-NEXT: nop
|
|
; ENABLE-NEXT: ## InlineAsm End
|
|
; ENABLE-NEXT: xorl %edi, %edi
|
|
; ENABLE-NEXT: movq %rdx, %rsi
|
|
; ENABLE-NEXT: callq _doSomething
|
|
; ENABLE-NEXT: popq %rbx
|
|
; ENABLE-NEXT: retq
|
|
; ENABLE-NEXT: LBB13_2: ## %false
|
|
; ENABLE-NEXT: movl $6, %edi
|
|
; ENABLE-NEXT: movq %rdx, %rsi
|
|
; ENABLE-NEXT: jmp _doSomething ## TAILCALL
|
|
;
|
|
; DISABLE-LABEL: regmask:
|
|
; DISABLE: ## %bb.0:
|
|
; DISABLE-NEXT: pushq %rbx
|
|
; DISABLE-NEXT: .cfi_def_cfa_offset 16
|
|
; DISABLE-NEXT: .cfi_offset %rbx, -16
|
|
; DISABLE-NEXT: cmpl %esi, %edi
|
|
; DISABLE-NEXT: jge LBB13_2
|
|
; DISABLE-NEXT: ## %bb.1: ## %true
|
|
; DISABLE-NEXT: ## InlineAsm Start
|
|
; DISABLE-NEXT: nop
|
|
; DISABLE-NEXT: ## InlineAsm End
|
|
; DISABLE-NEXT: xorl %edi, %edi
|
|
; DISABLE-NEXT: movq %rdx, %rsi
|
|
; DISABLE-NEXT: callq _doSomething
|
|
; DISABLE-NEXT: popq %rbx
|
|
; DISABLE-NEXT: retq
|
|
; DISABLE-NEXT: LBB13_2: ## %false
|
|
; DISABLE-NEXT: movl $6, %edi
|
|
; DISABLE-NEXT: movq %rdx, %rsi
|
|
; DISABLE-NEXT: popq %rbx
|
|
; DISABLE-NEXT: jmp _doSomething ## TAILCALL
|
|
%tmp2 = icmp slt i32 %a, %b
|
|
br i1 %tmp2, label %true, label %false
|
|
|
|
true:
|
|
; Clobber a CSR so that we check something on the regmask
|
|
; of the tail call.
|
|
tail call void asm sideeffect "nop", "~{ebx}"()
|
|
%tmp4 = call i32 @doSomething(i32 0, i32* %addr)
|
|
br label %end
|
|
|
|
false:
|
|
%tmp5 = tail call i32 @doSomething(i32 6, i32* %addr)
|
|
br label %end
|
|
|
|
end:
|
|
%tmp.0 = phi i32 [ %tmp4, %true ], [ %tmp5, %false ]
|
|
ret i32 %tmp.0
|
|
}
|
|
|
|
@b = internal unnamed_addr global i1 false
|
|
@c = internal unnamed_addr global i8 0, align 1
|
|
@a = common global i32 0, align 4
|
|
|
|
; Make sure the prologue does not clobber the EFLAGS when
|
|
; it is live accross.
|
|
; PR25629.
|
|
; Note: The registers may change in the following patterns, but
|
|
; because they imply register hierarchy (e.g., eax, al) this is
|
|
; tricky to write robust patterns.
|
|
define i32 @useLEAForPrologue(i32 %d, i32 %a, i8 %c) #3 {
|
|
; ENABLE-LABEL: useLEAForPrologue:
|
|
; ENABLE: ## %bb.0: ## %entry
|
|
; ENABLE-NEXT: pushq %rbx
|
|
; ENABLE-NEXT: subq $16, %rsp
|
|
; ENABLE-NEXT: xorl %eax, %eax
|
|
; ENABLE-NEXT: cmpb $0, _b(%rip)
|
|
; ENABLE-NEXT: movl $48, %ecx
|
|
; ENABLE-NEXT: cmovnel %eax, %ecx
|
|
; ENABLE-NEXT: movb %cl, _c(%rip)
|
|
; ENABLE-NEXT: je LBB14_4
|
|
; ENABLE-NEXT: ## %bb.1: ## %for.body.lr.ph
|
|
; ENABLE-NEXT: ## InlineAsm Start
|
|
; ENABLE-NEXT: nop
|
|
; ENABLE-NEXT: ## InlineAsm End
|
|
; ENABLE-NEXT: .p2align 4, 0x90
|
|
; ENABLE-NEXT: LBB14_2: ## %for.body
|
|
; ENABLE-NEXT: ## =>This Inner Loop Header: Depth=1
|
|
; ENABLE-NEXT: cmpl %esi, %edi
|
|
; ENABLE-NEXT: setl %al
|
|
; ENABLE-NEXT: xorl %esi, %esi
|
|
; ENABLE-NEXT: movb %al, %sil
|
|
; ENABLE-NEXT: incb %dl
|
|
; ENABLE-NEXT: cmpb $45, %dl
|
|
; ENABLE-NEXT: jl LBB14_2
|
|
; ENABLE-NEXT: ## %bb.3: ## %for.cond.for.end_crit_edge
|
|
; ENABLE-NEXT: movq _a@GOTPCREL(%rip), %rax
|
|
; ENABLE-NEXT: movl %esi, (%rax)
|
|
; ENABLE-NEXT: LBB14_4: ## %for.end
|
|
; ENABLE-NEXT: xorl %edi, %edi
|
|
; ENABLE-NEXT: callq _varfunc
|
|
; ENABLE-NEXT: xorl %eax, %eax
|
|
; ENABLE-NEXT: addq $16, %rsp
|
|
; ENABLE-NEXT: popq %rbx
|
|
; ENABLE-NEXT: retq
|
|
;
|
|
; DISABLE-LABEL: useLEAForPrologue:
|
|
; DISABLE: ## %bb.0: ## %entry
|
|
; DISABLE-NEXT: pushq %rbx
|
|
; DISABLE-NEXT: subq $16, %rsp
|
|
; DISABLE-NEXT: xorl %eax, %eax
|
|
; DISABLE-NEXT: cmpb $0, _b(%rip)
|
|
; DISABLE-NEXT: movl $48, %ecx
|
|
; DISABLE-NEXT: cmovnel %eax, %ecx
|
|
; DISABLE-NEXT: movb %cl, _c(%rip)
|
|
; DISABLE-NEXT: je LBB14_4
|
|
; DISABLE-NEXT: ## %bb.1: ## %for.body.lr.ph
|
|
; DISABLE-NEXT: ## InlineAsm Start
|
|
; DISABLE-NEXT: nop
|
|
; DISABLE-NEXT: ## InlineAsm End
|
|
; DISABLE-NEXT: .p2align 4, 0x90
|
|
; DISABLE-NEXT: LBB14_2: ## %for.body
|
|
; DISABLE-NEXT: ## =>This Inner Loop Header: Depth=1
|
|
; DISABLE-NEXT: cmpl %esi, %edi
|
|
; DISABLE-NEXT: setl %al
|
|
; DISABLE-NEXT: xorl %esi, %esi
|
|
; DISABLE-NEXT: movb %al, %sil
|
|
; DISABLE-NEXT: incb %dl
|
|
; DISABLE-NEXT: cmpb $45, %dl
|
|
; DISABLE-NEXT: jl LBB14_2
|
|
; DISABLE-NEXT: ## %bb.3: ## %for.cond.for.end_crit_edge
|
|
; DISABLE-NEXT: movq _a@GOTPCREL(%rip), %rax
|
|
; DISABLE-NEXT: movl %esi, (%rax)
|
|
; DISABLE-NEXT: LBB14_4: ## %for.end
|
|
; DISABLE-NEXT: xorl %edi, %edi
|
|
; DISABLE-NEXT: callq _varfunc
|
|
; DISABLE-NEXT: xorl %eax, %eax
|
|
; DISABLE-NEXT: addq $16, %rsp
|
|
; DISABLE-NEXT: popq %rbx
|
|
; DISABLE-NEXT: retq
|
|
entry:
|
|
%tmp = alloca i3
|
|
%.b = load i1, i1* @b, align 1
|
|
%bool = select i1 %.b, i8 0, i8 48
|
|
store i8 %bool, i8* @c, align 1
|
|
br i1 %.b, label %for.body.lr.ph, label %for.end
|
|
|
|
for.body.lr.ph: ; preds = %entry
|
|
tail call void asm sideeffect "nop", "~{ebx}"()
|
|
br label %for.body
|
|
|
|
for.body: ; preds = %for.body.lr.ph, %for.body
|
|
%inc6 = phi i8 [ %c, %for.body.lr.ph ], [ %inc, %for.body ]
|
|
%cond5 = phi i32 [ %a, %for.body.lr.ph ], [ %conv3, %for.body ]
|
|
%cmp2 = icmp slt i32 %d, %cond5
|
|
%conv3 = zext i1 %cmp2 to i32
|
|
%inc = add i8 %inc6, 1
|
|
%cmp = icmp slt i8 %inc, 45
|
|
br i1 %cmp, label %for.body, label %for.cond.for.end_crit_edge
|
|
|
|
for.cond.for.end_crit_edge: ; preds = %for.body
|
|
store i32 %conv3, i32* @a, align 4
|
|
br label %for.end
|
|
|
|
for.end: ; preds = %for.cond.for.end_crit_edge, %entry
|
|
%call = tail call i32 (i8*) @varfunc(i8* null)
|
|
ret i32 0
|
|
}
|
|
|
|
declare i32 @varfunc(i8* nocapture readonly)
|
|
|
|
@sum1 = external hidden thread_local global i32, align 4
|
|
|
|
|
|
; Function Attrs: nounwind
|
|
; Make sure the TLS call used to access @sum1 happens after the prologue
|
|
; and before the epilogue.
|
|
; TLS calls used to be wrongly model and shrink-wrapping would have inserted
|
|
; the prologue and epilogue just around the call to doSomething.
|
|
; PR25820.
|
|
define i32 @tlsCall(i1 %bool1, i32 %arg, i32* readonly dereferenceable(4) %sum1) #3 {
|
|
; ENABLE-LABEL: tlsCall:
|
|
; ENABLE: ## %bb.0: ## %entry
|
|
; ENABLE-NEXT: pushq %rax
|
|
; ENABLE-NEXT: testb $1, %dil
|
|
; ENABLE-NEXT: je LBB15_2
|
|
; ENABLE-NEXT: ## %bb.1: ## %master
|
|
; ENABLE-NEXT: movl (%rdx), %ecx
|
|
; ENABLE-NEXT: movq _sum1@TLVP(%rip), %rdi
|
|
; ENABLE-NEXT: callq *(%rdi)
|
|
; ENABLE-NEXT: movl %ecx, (%rax)
|
|
; ENABLE-NEXT: jmp LBB15_3
|
|
; ENABLE-NEXT: LBB15_2: ## %else
|
|
; ENABLE-NEXT: xorl %edi, %edi
|
|
; ENABLE-NEXT: xorl %esi, %esi
|
|
; ENABLE-NEXT: callq _doSomething
|
|
; ENABLE-NEXT: movl %eax, %esi
|
|
; ENABLE-NEXT: LBB15_3: ## %exit
|
|
; ENABLE-NEXT: movl %esi, %eax
|
|
; ENABLE-NEXT: popq %rcx
|
|
; ENABLE-NEXT: retq
|
|
;
|
|
; DISABLE-LABEL: tlsCall:
|
|
; DISABLE: ## %bb.0: ## %entry
|
|
; DISABLE-NEXT: pushq %rax
|
|
; DISABLE-NEXT: testb $1, %dil
|
|
; DISABLE-NEXT: je LBB15_2
|
|
; DISABLE-NEXT: ## %bb.1: ## %master
|
|
; DISABLE-NEXT: movl (%rdx), %ecx
|
|
; DISABLE-NEXT: movq _sum1@TLVP(%rip), %rdi
|
|
; DISABLE-NEXT: callq *(%rdi)
|
|
; DISABLE-NEXT: movl %ecx, (%rax)
|
|
; DISABLE-NEXT: jmp LBB15_3
|
|
; DISABLE-NEXT: LBB15_2: ## %else
|
|
; DISABLE-NEXT: xorl %edi, %edi
|
|
; DISABLE-NEXT: xorl %esi, %esi
|
|
; DISABLE-NEXT: callq _doSomething
|
|
; DISABLE-NEXT: movl %eax, %esi
|
|
; DISABLE-NEXT: LBB15_3: ## %exit
|
|
; DISABLE-NEXT: movl %esi, %eax
|
|
; DISABLE-NEXT: popq %rcx
|
|
; DISABLE-NEXT: retq
|
|
entry:
|
|
br i1 %bool1, label %master, label %else
|
|
|
|
master:
|
|
%tmp1 = load i32, i32* %sum1, align 4
|
|
store i32 %tmp1, i32* @sum1, align 4
|
|
br label %exit
|
|
|
|
else:
|
|
%call = call i32 @doSomething(i32 0, i32* null)
|
|
br label %exit
|
|
|
|
exit:
|
|
%res = phi i32 [ %arg, %master], [ %call, %else ]
|
|
ret i32 %res
|
|
}
|
|
|
|
attributes #3 = { nounwind }
|
|
|
|
@irreducibleCFGa = common global i32 0, align 4
|
|
@irreducibleCFGf = common global i8 0, align 1
|
|
@irreducibleCFGb = common global i32 0, align 4
|
|
|
|
; Check that we do not run shrink-wrapping on irreducible CFGs until
|
|
; it is actually supported.
|
|
; At the moment, on those CFGs the loop information may be incorrect
|
|
; and since we use that information to do the placement, we may end up
|
|
; inserting the prologue/epilogue at incorrect places.
|
|
; PR25988.
|
|
; Make sure we emit missed optimization remarks for this.
|
|
; REMARKS: Pass: shrink-wrap
|
|
; REMARKS-NEXT: Name: UnsupportedIrreducibleCFG
|
|
; REMARKS-NEXT: Function: irreducibleCFG
|
|
; REMARKS-NEXT: Args:
|
|
; REMARKS-NEXT: - String: Irreducible CFGs are not supported yet
|
|
|
|
define i32 @irreducibleCFG() #4 {
|
|
; ENABLE-LABEL: irreducibleCFG:
|
|
; ENABLE: ## %bb.0: ## %entry
|
|
; ENABLE-NEXT: pushq %rbp
|
|
; ENABLE-NEXT: .cfi_def_cfa_offset 16
|
|
; ENABLE-NEXT: .cfi_offset %rbp, -16
|
|
; ENABLE-NEXT: movq %rsp, %rbp
|
|
; ENABLE-NEXT: .cfi_def_cfa_register %rbp
|
|
; ENABLE-NEXT: pushq %rbx
|
|
; ENABLE-NEXT: pushq %rax
|
|
; ENABLE-NEXT: .cfi_offset %rbx, -24
|
|
; ENABLE-NEXT: movq _irreducibleCFGf@GOTPCREL(%rip), %rax
|
|
; ENABLE-NEXT: cmpb $0, (%rax)
|
|
; ENABLE-NEXT: je LBB16_2
|
|
; ENABLE-NEXT: .p2align 4, 0x90
|
|
; ENABLE-NEXT: LBB16_1: ## %preheader
|
|
; ENABLE-NEXT: ## =>This Inner Loop Header: Depth=1
|
|
; ENABLE-NEXT: jmp LBB16_1
|
|
; ENABLE-NEXT: LBB16_2: ## %split
|
|
; ENABLE-NEXT: movq _irreducibleCFGb@GOTPCREL(%rip), %rax
|
|
; ENABLE-NEXT: cmpl $0, (%rax)
|
|
; ENABLE-NEXT: je LBB16_3
|
|
; ENABLE-NEXT: ## %bb.4: ## %for.body4.i
|
|
; ENABLE-NEXT: movq _irreducibleCFGa@GOTPCREL(%rip), %rax
|
|
; ENABLE-NEXT: movl (%rax), %edi
|
|
; ENABLE-NEXT: xorl %ebx, %ebx
|
|
; ENABLE-NEXT: xorl %eax, %eax
|
|
; ENABLE-NEXT: callq _something
|
|
; ENABLE-NEXT: jmp LBB16_5
|
|
; ENABLE-NEXT: LBB16_3:
|
|
; ENABLE-NEXT: xorl %ebx, %ebx
|
|
; ENABLE-NEXT: .p2align 4, 0x90
|
|
; ENABLE-NEXT: LBB16_5: ## %for.inc
|
|
; ENABLE-NEXT: ## =>This Inner Loop Header: Depth=1
|
|
; ENABLE-NEXT: incl %ebx
|
|
; ENABLE-NEXT: cmpl $7, %ebx
|
|
; ENABLE-NEXT: jl LBB16_5
|
|
; ENABLE-NEXT: ## %bb.6: ## %fn1.exit
|
|
; ENABLE-NEXT: xorl %eax, %eax
|
|
; ENABLE-NEXT: addq $8, %rsp
|
|
; ENABLE-NEXT: popq %rbx
|
|
; ENABLE-NEXT: popq %rbp
|
|
; ENABLE-NEXT: retq
|
|
;
|
|
; DISABLE-LABEL: irreducibleCFG:
|
|
; DISABLE: ## %bb.0: ## %entry
|
|
; DISABLE-NEXT: pushq %rbp
|
|
; DISABLE-NEXT: .cfi_def_cfa_offset 16
|
|
; DISABLE-NEXT: .cfi_offset %rbp, -16
|
|
; DISABLE-NEXT: movq %rsp, %rbp
|
|
; DISABLE-NEXT: .cfi_def_cfa_register %rbp
|
|
; DISABLE-NEXT: pushq %rbx
|
|
; DISABLE-NEXT: pushq %rax
|
|
; DISABLE-NEXT: .cfi_offset %rbx, -24
|
|
; DISABLE-NEXT: movq _irreducibleCFGf@GOTPCREL(%rip), %rax
|
|
; DISABLE-NEXT: cmpb $0, (%rax)
|
|
; DISABLE-NEXT: je LBB16_2
|
|
; DISABLE-NEXT: .p2align 4, 0x90
|
|
; DISABLE-NEXT: LBB16_1: ## %preheader
|
|
; DISABLE-NEXT: ## =>This Inner Loop Header: Depth=1
|
|
; DISABLE-NEXT: jmp LBB16_1
|
|
; DISABLE-NEXT: LBB16_2: ## %split
|
|
; DISABLE-NEXT: movq _irreducibleCFGb@GOTPCREL(%rip), %rax
|
|
; DISABLE-NEXT: cmpl $0, (%rax)
|
|
; DISABLE-NEXT: je LBB16_3
|
|
; DISABLE-NEXT: ## %bb.4: ## %for.body4.i
|
|
; DISABLE-NEXT: movq _irreducibleCFGa@GOTPCREL(%rip), %rax
|
|
; DISABLE-NEXT: movl (%rax), %edi
|
|
; DISABLE-NEXT: xorl %ebx, %ebx
|
|
; DISABLE-NEXT: xorl %eax, %eax
|
|
; DISABLE-NEXT: callq _something
|
|
; DISABLE-NEXT: jmp LBB16_5
|
|
; DISABLE-NEXT: LBB16_3:
|
|
; DISABLE-NEXT: xorl %ebx, %ebx
|
|
; DISABLE-NEXT: .p2align 4, 0x90
|
|
; DISABLE-NEXT: LBB16_5: ## %for.inc
|
|
; DISABLE-NEXT: ## =>This Inner Loop Header: Depth=1
|
|
; DISABLE-NEXT: incl %ebx
|
|
; DISABLE-NEXT: cmpl $7, %ebx
|
|
; DISABLE-NEXT: jl LBB16_5
|
|
; DISABLE-NEXT: ## %bb.6: ## %fn1.exit
|
|
; DISABLE-NEXT: xorl %eax, %eax
|
|
; DISABLE-NEXT: addq $8, %rsp
|
|
; DISABLE-NEXT: popq %rbx
|
|
; DISABLE-NEXT: popq %rbp
|
|
; DISABLE-NEXT: retq
|
|
entry:
|
|
%i0 = load i32, i32* @irreducibleCFGa, align 4
|
|
%.pr = load i8, i8* @irreducibleCFGf, align 1
|
|
%bool = icmp eq i8 %.pr, 0
|
|
br i1 %bool, label %split, label %preheader
|
|
|
|
preheader:
|
|
br label %preheader
|
|
|
|
split:
|
|
%i1 = load i32, i32* @irreducibleCFGb, align 4
|
|
%tobool1.i = icmp ne i32 %i1, 0
|
|
br i1 %tobool1.i, label %for.body4.i, label %for.cond8.i.preheader
|
|
|
|
for.body4.i:
|
|
%call.i = tail call i32 (...) @something(i32 %i0)
|
|
br label %for.cond8
|
|
|
|
for.cond8:
|
|
%p1 = phi i32 [ %inc18.i, %for.inc ], [ 0, %for.body4.i ]
|
|
%.pr1.pr = load i32, i32* @irreducibleCFGb, align 4
|
|
br label %for.cond8.i.preheader
|
|
|
|
for.cond8.i.preheader:
|
|
%.pr1 = phi i32 [ %.pr1.pr, %for.cond8 ], [ %i1, %split ]
|
|
%p13 = phi i32 [ %p1, %for.cond8 ], [ 0, %split ]
|
|
br label %for.inc
|
|
|
|
fn1.exit:
|
|
ret i32 0
|
|
|
|
for.inc:
|
|
%inc18.i = add nuw nsw i32 %p13, 1
|
|
%cmp = icmp slt i32 %inc18.i, 7
|
|
br i1 %cmp, label %for.cond8, label %fn1.exit
|
|
}
|
|
|
|
attributes #4 = { "frame-pointer"="all" }
|
|
|
|
@x = external global i32, align 4
|
|
@y = external global i32, align 4
|
|
|
|
; The post-dominator tree does not include the branch containing the infinite
|
|
; loop, which can occur into a misplacement of the restore block, if we're
|
|
; looking for the nearest common post-dominator of an "unreachable" block.
|
|
|
|
define void @infiniteLoopNoSuccessor() #5 {
|
|
; ENABLE-LABEL: infiniteLoopNoSuccessor:
|
|
; ENABLE: ## %bb.0:
|
|
; ENABLE-NEXT: pushq %rbp
|
|
; ENABLE-NEXT: movq %rsp, %rbp
|
|
; ENABLE-NEXT: movq _x@GOTPCREL(%rip), %rax
|
|
; ENABLE-NEXT: cmpl $0, (%rax)
|
|
; ENABLE-NEXT: je LBB17_2
|
|
; ENABLE-NEXT: ## %bb.1:
|
|
; ENABLE-NEXT: movl $0, (%rax)
|
|
; ENABLE-NEXT: LBB17_2:
|
|
; ENABLE-NEXT: xorl %eax, %eax
|
|
; ENABLE-NEXT: callq _somethingElse
|
|
; ENABLE-NEXT: movq _y@GOTPCREL(%rip), %rax
|
|
; ENABLE-NEXT: cmpl $0, (%rax)
|
|
; ENABLE-NEXT: je LBB17_3
|
|
; ENABLE-NEXT: ## %bb.5:
|
|
; ENABLE-NEXT: popq %rbp
|
|
; ENABLE-NEXT: retq
|
|
; ENABLE-NEXT: LBB17_3:
|
|
; ENABLE-NEXT: xorl %eax, %eax
|
|
; ENABLE-NEXT: callq _something
|
|
; ENABLE-NEXT: .p2align 4, 0x90
|
|
; ENABLE-NEXT: LBB17_4: ## =>This Inner Loop Header: Depth=1
|
|
; ENABLE-NEXT: xorl %eax, %eax
|
|
; ENABLE-NEXT: callq _somethingElse
|
|
; ENABLE-NEXT: jmp LBB17_4
|
|
;
|
|
; DISABLE-LABEL: infiniteLoopNoSuccessor:
|
|
; DISABLE: ## %bb.0:
|
|
; DISABLE-NEXT: pushq %rbp
|
|
; DISABLE-NEXT: movq %rsp, %rbp
|
|
; DISABLE-NEXT: movq _x@GOTPCREL(%rip), %rax
|
|
; DISABLE-NEXT: cmpl $0, (%rax)
|
|
; DISABLE-NEXT: je LBB17_2
|
|
; DISABLE-NEXT: ## %bb.1:
|
|
; DISABLE-NEXT: movl $0, (%rax)
|
|
; DISABLE-NEXT: LBB17_2:
|
|
; DISABLE-NEXT: xorl %eax, %eax
|
|
; DISABLE-NEXT: callq _somethingElse
|
|
; DISABLE-NEXT: movq _y@GOTPCREL(%rip), %rax
|
|
; DISABLE-NEXT: cmpl $0, (%rax)
|
|
; DISABLE-NEXT: je LBB17_3
|
|
; DISABLE-NEXT: ## %bb.5:
|
|
; DISABLE-NEXT: popq %rbp
|
|
; DISABLE-NEXT: retq
|
|
; DISABLE-NEXT: LBB17_3:
|
|
; DISABLE-NEXT: xorl %eax, %eax
|
|
; DISABLE-NEXT: callq _something
|
|
; DISABLE-NEXT: .p2align 4, 0x90
|
|
; DISABLE-NEXT: LBB17_4: ## =>This Inner Loop Header: Depth=1
|
|
; DISABLE-NEXT: xorl %eax, %eax
|
|
; DISABLE-NEXT: callq _somethingElse
|
|
; DISABLE-NEXT: jmp LBB17_4
|
|
%1 = load i32, i32* @x, align 4
|
|
%2 = icmp ne i32 %1, 0
|
|
br i1 %2, label %3, label %4
|
|
|
|
; <label>:3:
|
|
store i32 0, i32* @x, align 4
|
|
br label %4
|
|
|
|
; <label>:4:
|
|
call void (...) @somethingElse()
|
|
%5 = load i32, i32* @y, align 4
|
|
%6 = icmp ne i32 %5, 0
|
|
br i1 %6, label %10, label %7
|
|
|
|
; <label>:7:
|
|
%8 = call i32 (...) @something()
|
|
br label %9
|
|
|
|
; <label>:9:
|
|
call void (...) @somethingElse()
|
|
br label %9
|
|
|
|
; <label>:10:
|
|
ret void
|
|
}
|
|
|
|
declare void @somethingElse(...)
|
|
|
|
attributes #5 = { nounwind "frame-pointer"="non-leaf" }
|