Imported Upstream version 6.4.0.137

Former-commit-id: 943baa9f16a098c33e129777827f3a9d20da00d6
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2019-07-26 19:53:28 +00:00
parent e9207cf623
commit ef583813eb
2712 changed files with 74169 additions and 40587 deletions

View File

@@ -10,16 +10,10 @@ define i64 @test_add_i64(i64 %arg1, i64 %arg2) {
;
; X32-LABEL: test_add_i64:
; X32: # %bb.0:
; X32-NEXT: pushl %ebp
; X32-NEXT: .cfi_def_cfa_offset 8
; X32-NEXT: .cfi_offset %ebp, -8
; X32-NEXT: movl %esp, %ebp
; X32-NEXT: .cfi_def_cfa_register %ebp
; X32-NEXT: movl 16(%ebp), %eax
; X32-NEXT: movl 20(%ebp), %edx
; X32-NEXT: addl 8(%ebp), %eax
; X32-NEXT: adcl 12(%ebp), %edx
; X32-NEXT: popl %ebp
; X32-NEXT: movl {{[0-9]+}}(%esp), %eax
; X32-NEXT: movl {{[0-9]+}}(%esp), %edx
; X32-NEXT: addl {{[0-9]+}}(%esp), %eax
; X32-NEXT: adcl {{[0-9]+}}(%esp), %edx
; X32-NEXT: retl
%ret = add i64 %arg1, %arg2
ret i64 %ret

View File

@@ -37,6 +37,8 @@
; CHECK-NEXT: X86 PIC Global Base Reg Initialization
; CHECK-NEXT: Expand ISel Pseudo-instructions
; CHECK-NEXT: Local Stack Slot Allocation
; CHECK-NEXT: MachineDominator Tree Construction
; CHECK-NEXT: X86 EFLAGS copy lowering
; CHECK-NEXT: X86 WinAlloca Expander
; CHECK-NEXT: Eliminate PHI nodes for register allocation
; CHECK-NEXT: Two-Address instruction pass

View File

@@ -1,37 +0,0 @@
; RUN: llc < %s -verify-machineinstrs -mcpu=generic -mtriple=x86_64-linux | FileCheck %s
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
target triple = "x86_64-apple-macosx10.7.0"
; In the code below we need to copy the EFLAGS because of scheduling constraints.
; When copying the EFLAGS we need to write to the stack with push/pop. This forces
; us to emit the prolog.
; CHECK: main
; CHECK: subq{{.*}}rsp
; CHECK: ret
define i32 @main(i32 %arg, i8** %arg1) nounwind {
bb:
%tmp = alloca i32, align 4 ; [#uses=3 type=i32*]
%tmp2 = alloca i32, align 4 ; [#uses=3 type=i32*]
%tmp3 = alloca i32 ; [#uses=1 type=i32*]
store volatile i32 1, i32* %tmp, align 4
store volatile i32 1, i32* %tmp2, align 4
br label %bb4
bb4: ; preds = %bb4, %bb
%tmp6 = load volatile i32, i32* %tmp2, align 4 ; [#uses=1 type=i32]
%tmp7 = add i32 %tmp6, -1 ; [#uses=2 type=i32]
store volatile i32 %tmp7, i32* %tmp2, align 4
%tmp8 = icmp eq i32 %tmp7, 0 ; [#uses=1 type=i1]
%tmp9 = load volatile i32, i32* %tmp ; [#uses=1 type=i32]
%tmp10 = add i32 %tmp9, -1 ; [#uses=1 type=i32]
store volatile i32 %tmp10, i32* %tmp3
br i1 %tmp8, label %bb11, label %bb4
bb11: ; preds = %bb4
%tmp12 = load volatile i32, i32* %tmp, align 4 ; [#uses=1 type=i32]
ret i32 %tmp12
}

View File

@@ -1,100 +1,110 @@
; RUN: llc -mtriple=i386-linux-gnu %s -o - | FileCheck %s -check-prefix=i386
; RUN: llc -mtriple=i386-linux-gnu -pre-RA-sched=fast %s -o - | FileCheck %s -check-prefix=i386f
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc -mtriple=i386-linux-gnu -verify-machineinstrs %s -o - | FileCheck %s --check-prefixes=32-ALL,32-GOOD-RA
; RUN: llc -mtriple=i386-linux-gnu -verify-machineinstrs -pre-RA-sched=fast %s -o - | FileCheck %s --check-prefixes=32-ALL,32-FAST-RA
; RUN: llc -mtriple=x86_64-linux-gnu %s -o - | FileCheck %s -check-prefix=x8664
; RUN: llc -mtriple=x86_64-linux-gnu -pre-RA-sched=fast %s -o - | FileCheck %s -check-prefix=x8664
; RUN: llc -mtriple=x86_64-linux-gnu -mattr=+sahf %s -o - | FileCheck %s -check-prefix=x8664-sahf
; RUN: llc -mtriple=x86_64-linux-gnu -mattr=+sahf -pre-RA-sched=fast %s -o - | FileCheck %s -check-prefix=x8664-sahf
; RUN: llc -mtriple=x86_64-linux-gnu -mcpu=corei7 %s -o - | FileCheck %s -check-prefix=x8664-sahf
; TODO: Reenable verify-machineinstr once the if (!AXDead) // FIXME
; in X86InstrInfo::copyPhysReg() is resolved.
; RUN: llc -mtriple=x86_64-linux-gnu -verify-machineinstrs %s -o - | FileCheck %s --check-prefixes=64-ALL,64-GOOD-RA
; RUN: llc -mtriple=x86_64-linux-gnu -verify-machineinstrs -pre-RA-sched=fast %s -o - | FileCheck %s --check-prefixes=64-ALL,64-FAST-RA
; RUN: llc -mtriple=x86_64-linux-gnu -verify-machineinstrs -mattr=+sahf %s -o - | FileCheck %s --check-prefixes=64-ALL,64-GOOD-RA-SAHF
; RUN: llc -mtriple=x86_64-linux-gnu -verify-machineinstrs -mattr=+sahf -pre-RA-sched=fast %s -o - | FileCheck %s --check-prefixes=64-ALL,64-FAST-RA-SAHF
; RUN: llc -mtriple=x86_64-linux-gnu -verify-machineinstrs -mcpu=corei7 %s -o - | FileCheck %s --check-prefixes=64-ALL,64-GOOD-RA-SAHF
declare i32 @foo()
declare i32 @bar(i64)
define i64 @test_intervening_call(i64* %foo, i64 %bar, i64 %baz) {
; i386-LABEL: test_intervening_call:
; i386: cmpxchg8b
; i386-NEXT: pushl %eax
; i386-NEXT: seto %al
; i386-NEXT: lahf
; i386-NEXT: movl %eax, [[FLAGS:%.*]]
; i386-NEXT: popl %eax
; i386-NEXT: subl $8, %esp
; i386-NEXT: pushl %edx
; i386-NEXT: pushl %eax
; i386-NEXT: calll bar
; i386-NEXT: addl $16, %esp
; i386-NEXT: movl [[FLAGS]], %eax
; i386-NEXT: addb $127, %al
; i386-NEXT: sahf
; i386-NEXT: jne
; In the following case we get a long chain of EFLAGS save/restore due to
; a sequence of:
; In the following case when using fast scheduling we get a long chain of
; EFLAGS save/restore due to a sequence of:
; cmpxchg8b (implicit-def eflags)
; eax = copy eflags
; adjcallstackdown32
; ...
; use of eax
; During PEI the adjcallstackdown32 is replaced with the subl which
; clobbers eflags, effectively interfering in the liveness interval.
; Is this a case we care about? Maybe no, considering this issue
; happens with the fast pre-regalloc scheduler enforced. A more
; performant scheduler would move the adjcallstackdown32 out of the
; eflags liveness interval.
; i386f-LABEL: test_intervening_call:
; i386f: cmpxchg8b
; i386f-NEXT: pushl %eax
; i386f-NEXT: seto %al
; i386f-NEXT: lahf
; i386f-NEXT: movl %eax, [[FLAGS:%.*]]
; i386f-NEXT: popl %eax
; i386f-NEXT: subl $8, %esp
; i386f-NEXT: pushl %eax
; i386f-NEXT: movl %ecx, %eax
; i386f-NEXT: addb $127, %al
; i386f-NEXT: sahf
; i386f-NEXT: popl %eax
; i386f-NEXT: pushl %eax
; i386f-NEXT: seto %al
; i386f-NEXT: lahf
; i386f-NEXT: movl %eax, %esi
; i386f-NEXT: popl %eax
; i386f-NEXT: pushl %edx
; i386f-NEXT: pushl %eax
; i386f-NEXT: calll bar
; i386f-NEXT: addl $16, %esp
; i386f-NEXT: movl %esi, %eax
; i386f-NEXT: addb $127, %al
; x8664-LABEL: test_intervening_call:
; x8664: cmpxchgq
; x8664: pushfq
; x8664-NEXT: popq [[FLAGS:%.*]]
; x8664-NEXT: movq %rax, %rdi
; x8664-NEXT: callq bar
; x8664-NEXT: pushq [[FLAGS]]
; x8664-NEXT: popfq
; x8664-NEXT: jne
; x8664-sahf-LABEL: test_intervening_call:
; x8664-sahf: cmpxchgq
; x8664-sahf: pushq %rax
; x8664-sahf-NEXT: seto %al
; x8664-sahf-NEXT: lahf
; x8664-sahf-NEXT: movq %rax, [[FLAGS:%.*]]
; x8664-sahf-NEXT: popq %rax
; x8664-sahf-NEXT: movq %rax, %rdi
; x8664-sahf-NEXT: callq bar
; RAX is dead, no need to push and pop it.
; x8664-sahf-NEXT: movq [[FLAGS]], %rax
; x8664-sahf-NEXT: addb $127, %al
; x8664-sahf-NEXT: sahf
; x8664-sahf-NEXT: jne
; clobbers eflags, effectively interfering in the liveness interval. However,
; we then promote these copies into independent conditions in GPRs that avoids
; repeated saving and restoring logic and can be trivially managed by the
; register allocator.
define i64 @test_intervening_call(i64* %foo, i64 %bar, i64 %baz) nounwind {
; 32-GOOD-RA-LABEL: test_intervening_call:
; 32-GOOD-RA: # %bb.0: # %entry
; 32-GOOD-RA-NEXT: pushl %ebx
; 32-GOOD-RA-NEXT: pushl %esi
; 32-GOOD-RA-NEXT: pushl %eax
; 32-GOOD-RA-NEXT: movl {{[0-9]+}}(%esp), %eax
; 32-GOOD-RA-NEXT: movl {{[0-9]+}}(%esp), %edx
; 32-GOOD-RA-NEXT: movl {{[0-9]+}}(%esp), %ebx
; 32-GOOD-RA-NEXT: movl {{[0-9]+}}(%esp), %ecx
; 32-GOOD-RA-NEXT: movl {{[0-9]+}}(%esp), %esi
; 32-GOOD-RA-NEXT: lock cmpxchg8b (%esi)
; 32-GOOD-RA-NEXT: setne %bl
; 32-GOOD-RA-NEXT: subl $8, %esp
; 32-GOOD-RA-NEXT: pushl %edx
; 32-GOOD-RA-NEXT: pushl %eax
; 32-GOOD-RA-NEXT: calll bar
; 32-GOOD-RA-NEXT: addl $16, %esp
; 32-GOOD-RA-NEXT: testb %bl, %bl
; 32-GOOD-RA-NEXT: jne .LBB0_3
; 32-GOOD-RA-NEXT: # %bb.1: # %t
; 32-GOOD-RA-NEXT: movl $42, %eax
; 32-GOOD-RA-NEXT: jmp .LBB0_2
; 32-GOOD-RA-NEXT: .LBB0_3: # %f
; 32-GOOD-RA-NEXT: xorl %eax, %eax
; 32-GOOD-RA-NEXT: .LBB0_2: # %t
; 32-GOOD-RA-NEXT: xorl %edx, %edx
; 32-GOOD-RA-NEXT: addl $4, %esp
; 32-GOOD-RA-NEXT: popl %esi
; 32-GOOD-RA-NEXT: popl %ebx
; 32-GOOD-RA-NEXT: retl
;
; 32-FAST-RA-LABEL: test_intervening_call:
; 32-FAST-RA: # %bb.0: # %entry
; 32-FAST-RA-NEXT: pushl %ebx
; 32-FAST-RA-NEXT: pushl %esi
; 32-FAST-RA-NEXT: pushl %eax
; 32-FAST-RA-NEXT: movl {{[0-9]+}}(%esp), %esi
; 32-FAST-RA-NEXT: movl {{[0-9]+}}(%esp), %ebx
; 32-FAST-RA-NEXT: movl {{[0-9]+}}(%esp), %ecx
; 32-FAST-RA-NEXT: movl {{[0-9]+}}(%esp), %eax
; 32-FAST-RA-NEXT: movl {{[0-9]+}}(%esp), %edx
; 32-FAST-RA-NEXT: lock cmpxchg8b (%esi)
; 32-FAST-RA-NEXT: setne %bl
; 32-FAST-RA-NEXT: subl $8, %esp
; 32-FAST-RA-NEXT: pushl %edx
; 32-FAST-RA-NEXT: pushl %eax
; 32-FAST-RA-NEXT: calll bar
; 32-FAST-RA-NEXT: addl $16, %esp
; 32-FAST-RA-NEXT: testb %bl, %bl
; 32-FAST-RA-NEXT: jne .LBB0_3
; 32-FAST-RA-NEXT: # %bb.1: # %t
; 32-FAST-RA-NEXT: movl $42, %eax
; 32-FAST-RA-NEXT: jmp .LBB0_2
; 32-FAST-RA-NEXT: .LBB0_3: # %f
; 32-FAST-RA-NEXT: xorl %eax, %eax
; 32-FAST-RA-NEXT: .LBB0_2: # %t
; 32-FAST-RA-NEXT: xorl %edx, %edx
; 32-FAST-RA-NEXT: addl $4, %esp
; 32-FAST-RA-NEXT: popl %esi
; 32-FAST-RA-NEXT: popl %ebx
; 32-FAST-RA-NEXT: retl
;
; 64-ALL-LABEL: test_intervening_call:
; 64-ALL: # %bb.0: # %entry
; 64-ALL-NEXT: pushq %rbx
; 64-ALL-NEXT: movq %rsi, %rax
; 64-ALL-NEXT: lock cmpxchgq %rdx, (%rdi)
; 64-ALL-NEXT: setne %bl
; 64-ALL-NEXT: movq %rax, %rdi
; 64-ALL-NEXT: callq bar
; 64-ALL-NEXT: testb %bl, %bl
; 64-ALL-NEXT: jne .LBB0_2
; 64-ALL-NEXT: # %bb.1: # %t
; 64-ALL-NEXT: movl $42, %eax
; 64-ALL-NEXT: popq %rbx
; 64-ALL-NEXT: retq
; 64-ALL-NEXT: .LBB0_2: # %f
; 64-ALL-NEXT: xorl %eax, %eax
; 64-ALL-NEXT: popq %rbx
; 64-ALL-NEXT: retq
entry:
%cx = cmpxchg i64* %foo, i64 %bar, i64 %baz seq_cst seq_cst
%v = extractvalue { i64, i1 } %cx, 0
%p = extractvalue { i64, i1 } %cx, 1
@@ -109,23 +119,62 @@ f:
}
; Interesting in producing a clobber without any function calls.
define i32 @test_control_flow(i32* %p, i32 %i, i32 %j) {
; i386-LABEL: test_control_flow:
; i386: cmpxchg
; i386-NEXT: jne
; i386f-LABEL: test_control_flow:
; i386f: cmpxchg
; i386f-NEXT: jne
; x8664-LABEL: test_control_flow:
; x8664: cmpxchg
; x8664-NEXT: jne
; x8664-sahf-LABEL: test_control_flow:
; x8664-sahf: cmpxchg
; x8664-sahf-NEXT: jne
define i32 @test_control_flow(i32* %p, i32 %i, i32 %j) nounwind {
; 32-ALL-LABEL: test_control_flow:
; 32-ALL: # %bb.0: # %entry
; 32-ALL-NEXT: movl {{[0-9]+}}(%esp), %eax
; 32-ALL-NEXT: cmpl {{[0-9]+}}(%esp), %eax
; 32-ALL-NEXT: jle .LBB1_6
; 32-ALL-NEXT: # %bb.1: # %loop_start
; 32-ALL-NEXT: movl {{[0-9]+}}(%esp), %ecx
; 32-ALL-NEXT: .p2align 4, 0x90
; 32-ALL-NEXT: .LBB1_2: # %while.condthread-pre-split.i
; 32-ALL-NEXT: # =>This Loop Header: Depth=1
; 32-ALL-NEXT: # Child Loop BB1_3 Depth 2
; 32-ALL-NEXT: movl (%ecx), %edx
; 32-ALL-NEXT: .p2align 4, 0x90
; 32-ALL-NEXT: .LBB1_3: # %while.cond.i
; 32-ALL-NEXT: # Parent Loop BB1_2 Depth=1
; 32-ALL-NEXT: # => This Inner Loop Header: Depth=2
; 32-ALL-NEXT: movl %edx, %eax
; 32-ALL-NEXT: xorl %edx, %edx
; 32-ALL-NEXT: testl %eax, %eax
; 32-ALL-NEXT: je .LBB1_3
; 32-ALL-NEXT: # %bb.4: # %while.body.i
; 32-ALL-NEXT: # in Loop: Header=BB1_2 Depth=1
; 32-ALL-NEXT: lock cmpxchgl %eax, (%ecx)
; 32-ALL-NEXT: jne .LBB1_2
; 32-ALL-NEXT: # %bb.5:
; 32-ALL-NEXT: xorl %eax, %eax
; 32-ALL-NEXT: .LBB1_6: # %cond.end
; 32-ALL-NEXT: retl
;
; 64-ALL-LABEL: test_control_flow:
; 64-ALL: # %bb.0: # %entry
; 64-ALL-NEXT: cmpl %edx, %esi
; 64-ALL-NEXT: jle .LBB1_5
; 64-ALL-NEXT: .p2align 4, 0x90
; 64-ALL-NEXT: .LBB1_1: # %while.condthread-pre-split.i
; 64-ALL-NEXT: # =>This Loop Header: Depth=1
; 64-ALL-NEXT: # Child Loop BB1_2 Depth 2
; 64-ALL-NEXT: movl (%rdi), %ecx
; 64-ALL-NEXT: .p2align 4, 0x90
; 64-ALL-NEXT: .LBB1_2: # %while.cond.i
; 64-ALL-NEXT: # Parent Loop BB1_1 Depth=1
; 64-ALL-NEXT: # => This Inner Loop Header: Depth=2
; 64-ALL-NEXT: movl %ecx, %eax
; 64-ALL-NEXT: xorl %ecx, %ecx
; 64-ALL-NEXT: testl %eax, %eax
; 64-ALL-NEXT: je .LBB1_2
; 64-ALL-NEXT: # %bb.3: # %while.body.i
; 64-ALL-NEXT: # in Loop: Header=BB1_1 Depth=1
; 64-ALL-NEXT: lock cmpxchgl %eax, (%rdi)
; 64-ALL-NEXT: jne .LBB1_1
; 64-ALL-NEXT: # %bb.4:
; 64-ALL-NEXT: xorl %esi, %esi
; 64-ALL-NEXT: .LBB1_5: # %cond.end
; 64-ALL-NEXT: movl %esi, %eax
; 64-ALL-NEXT: retq
entry:
%cmp = icmp sgt i32 %i, %j
br i1 %cmp, label %loop_start, label %cond.end
@@ -158,52 +207,68 @@ cond.end:
; This one is an interesting case because CMOV doesn't have a chain
; operand. Naive attempts to limit cmpxchg EFLAGS use are likely to fail here.
define i32 @test_feed_cmov(i32* %addr, i32 %desired, i32 %new) {
; i386-LABEL: test_feed_cmov:
; i386: cmpxchgl
; i386-NEXT: seto %al
; i386-NEXT: lahf
; i386-NEXT: movl %eax, [[FLAGS:%.*]]
; i386-NEXT: calll foo
; i386-NEXT: pushl %eax
; i386-NEXT: movl [[FLAGS]], %eax
; i386-NEXT: addb $127, %al
; i386-NEXT: sahf
; i386-NEXT: popl %eax
; i386f-LABEL: test_feed_cmov:
; i386f: cmpxchgl
; i386f-NEXT: seto %al
; i386f-NEXT: lahf
; i386f-NEXT: movl %eax, [[FLAGS:%.*]]
; i386f-NEXT: calll foo
; i386f-NEXT: pushl %eax
; i386f-NEXT: movl [[FLAGS]], %eax
; i386f-NEXT: addb $127, %al
; i386f-NEXT: sahf
; i386f-NEXT: popl %eax
; x8664-LABEL: test_feed_cmov:
; x8664: cmpxchg
; x8664: pushfq
; x8664-NEXT: popq [[FLAGS:%.*]]
; x8664-NEXT: callq foo
; x8664-NEXT: pushq [[FLAGS]]
; x8664-NEXT: popfq
; x8664-sahf-LABEL: test_feed_cmov:
; x8664-sahf: cmpxchgl
; RAX is dead, do not push or pop it.
; x8664-sahf-NEXT: seto %al
; x8664-sahf-NEXT: lahf
; x8664-sahf-NEXT: movq %rax, [[FLAGS:%.*]]
; x8664-sahf-NEXT: callq foo
; x8664-sahf-NEXT: pushq %rax
; x8664-sahf-NEXT: movq [[FLAGS]], %rax
; x8664-sahf-NEXT: addb $127, %al
; x8664-sahf-NEXT: sahf
; x8664-sahf-NEXT: popq %rax
define i32 @test_feed_cmov(i32* %addr, i32 %desired, i32 %new) nounwind {
; 32-GOOD-RA-LABEL: test_feed_cmov:
; 32-GOOD-RA: # %bb.0: # %entry
; 32-GOOD-RA-NEXT: pushl %ebx
; 32-GOOD-RA-NEXT: pushl %esi
; 32-GOOD-RA-NEXT: pushl %eax
; 32-GOOD-RA-NEXT: movl {{[0-9]+}}(%esp), %eax
; 32-GOOD-RA-NEXT: movl {{[0-9]+}}(%esp), %esi
; 32-GOOD-RA-NEXT: movl {{[0-9]+}}(%esp), %ecx
; 32-GOOD-RA-NEXT: lock cmpxchgl %esi, (%ecx)
; 32-GOOD-RA-NEXT: sete %bl
; 32-GOOD-RA-NEXT: calll foo
; 32-GOOD-RA-NEXT: testb %bl, %bl
; 32-GOOD-RA-NEXT: jne .LBB2_2
; 32-GOOD-RA-NEXT: # %bb.1: # %entry
; 32-GOOD-RA-NEXT: movl %eax, %esi
; 32-GOOD-RA-NEXT: .LBB2_2: # %entry
; 32-GOOD-RA-NEXT: movl %esi, %eax
; 32-GOOD-RA-NEXT: addl $4, %esp
; 32-GOOD-RA-NEXT: popl %esi
; 32-GOOD-RA-NEXT: popl %ebx
; 32-GOOD-RA-NEXT: retl
;
; 32-FAST-RA-LABEL: test_feed_cmov:
; 32-FAST-RA: # %bb.0: # %entry
; 32-FAST-RA-NEXT: pushl %ebx
; 32-FAST-RA-NEXT: pushl %esi
; 32-FAST-RA-NEXT: pushl %eax
; 32-FAST-RA-NEXT: movl {{[0-9]+}}(%esp), %ecx
; 32-FAST-RA-NEXT: movl {{[0-9]+}}(%esp), %esi
; 32-FAST-RA-NEXT: movl {{[0-9]+}}(%esp), %eax
; 32-FAST-RA-NEXT: lock cmpxchgl %esi, (%ecx)
; 32-FAST-RA-NEXT: sete %bl
; 32-FAST-RA-NEXT: calll foo
; 32-FAST-RA-NEXT: testb %bl, %bl
; 32-FAST-RA-NEXT: jne .LBB2_2
; 32-FAST-RA-NEXT: # %bb.1: # %entry
; 32-FAST-RA-NEXT: movl %eax, %esi
; 32-FAST-RA-NEXT: .LBB2_2: # %entry
; 32-FAST-RA-NEXT: movl %esi, %eax
; 32-FAST-RA-NEXT: addl $4, %esp
; 32-FAST-RA-NEXT: popl %esi
; 32-FAST-RA-NEXT: popl %ebx
; 32-FAST-RA-NEXT: retl
;
; 64-ALL-LABEL: test_feed_cmov:
; 64-ALL: # %bb.0: # %entry
; 64-ALL-NEXT: pushq %rbp
; 64-ALL-NEXT: pushq %rbx
; 64-ALL-NEXT: pushq %rax
; 64-ALL-NEXT: movl %edx, %ebx
; 64-ALL-NEXT: movl %esi, %eax
; 64-ALL-NEXT: lock cmpxchgl %ebx, (%rdi)
; 64-ALL-NEXT: sete %bpl
; 64-ALL-NEXT: callq foo
; 64-ALL-NEXT: testb %bpl, %bpl
; 64-ALL-NEXT: cmovnel %ebx, %eax
; 64-ALL-NEXT: addq $8, %rsp
; 64-ALL-NEXT: popq %rbx
; 64-ALL-NEXT: popq %rbp
; 64-ALL-NEXT: retq
entry:
%res = cmpxchg i32* %addr, i32 %desired, i32 %new seq_cst seq_cst
%success = extractvalue { i32, i1 } %res, 1

View File

@@ -1,6 +1,8 @@
; RUN: llc -o - %s | FileCheck %s
; This tests for the problem originally reported in http://llvm.org/PR25951
target triple = "i686-unknown-linux-gnu"
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc -o - -mtriple=i686-unknown-unknown %s | FileCheck %s --check-prefixes=ALL,X32
; RUN: llc -o - -mtriple=x86_64-unknown-unknown %s | FileCheck %s --check-prefixes=ALL,X64
;
; Test patterns that require preserving and restoring flags.
@b = common global i8 0, align 1
@c = common global i32 0, align 4
@@ -8,13 +10,61 @@ target triple = "i686-unknown-linux-gnu"
@d = common global i8 0, align 1
@.str = private unnamed_addr constant [4 x i8] c"%d\0A\00", align 1
; CHECK-LABEL: func:
; This tests whether eax is properly saved/restored around the
; lahf/sahf instruction sequences. We make mem op volatile to prevent
; their reordering to avoid spills.
declare void @external(i32)
define i32 @func() {
; A test that re-uses flags in interesting ways due to volatile accesses.
; Specifically, the first increment's flags are reused for the branch despite
; being clobbered by the second increment.
define i32 @test1() nounwind {
; X32-LABEL: test1:
; X32: # %bb.0: # %entry
; X32-NEXT: movb b, %cl
; X32-NEXT: movl %ecx, %eax
; X32-NEXT: incb %al
; X32-NEXT: movb %al, b
; X32-NEXT: incl c
; X32-NEXT: sete %dl
; X32-NEXT: movb a, %ah
; X32-NEXT: movb %ah, %ch
; X32-NEXT: incb %ch
; X32-NEXT: cmpb %cl, %ah
; X32-NEXT: sete d
; X32-NEXT: movb %ch, a
; X32-NEXT: testb %dl, %dl
; X32-NEXT: jne .LBB0_2
; X32-NEXT: # %bb.1: # %if.then
; X32-NEXT: movsbl %al, %eax
; X32-NEXT: pushl %eax
; X32-NEXT: calll external
; X32-NEXT: addl $4, %esp
; X32-NEXT: .LBB0_2: # %if.end
; X32-NEXT: xorl %eax, %eax
; X32-NEXT: retl
;
; X64-LABEL: test1:
; X64: # %bb.0: # %entry
; X64-NEXT: movb {{.*}}(%rip), %dil
; X64-NEXT: movl %edi, %eax
; X64-NEXT: incb %al
; X64-NEXT: movb %al, {{.*}}(%rip)
; X64-NEXT: incl {{.*}}(%rip)
; X64-NEXT: sete %sil
; X64-NEXT: movb {{.*}}(%rip), %cl
; X64-NEXT: movl %ecx, %edx
; X64-NEXT: incb %dl
; X64-NEXT: cmpb %dil, %cl
; X64-NEXT: sete {{.*}}(%rip)
; X64-NEXT: movb %dl, {{.*}}(%rip)
; X64-NEXT: testb %sil, %sil
; X64-NEXT: jne .LBB0_2
; X64-NEXT: # %bb.1: # %if.then
; X64-NEXT: pushq %rax
; X64-NEXT: movsbl %al, %edi
; X64-NEXT: callq external
; X64-NEXT: addq $8, %rsp
; X64-NEXT: .LBB0_2: # %if.end
; X64-NEXT: xorl %eax, %eax
; X64-NEXT: retq
entry:
%bval = load i8, i8* @b
%inc = add i8 %bval, 1
@@ -25,33 +75,290 @@ entry:
%aval = load volatile i8, i8* @a
%inc2 = add i8 %aval, 1
store volatile i8 %inc2, i8* @a
; Copy flags produced by the incb of %inc1 to a register, need to save+restore
; eax around it. The flags will be reused by %tobool.
; CHECK: pushl %eax
; CHECK: seto %al
; CHECK: lahf
; CHECK: movl %eax, [[REG:%[a-z]+]]
; CHECK: popl %eax
%cmp = icmp eq i8 %aval, %bval
%conv5 = zext i1 %cmp to i8
store i8 %conv5, i8* @d
%tobool = icmp eq i32 %inc1, 0
; We restore flags with an 'addb, sahf' sequence, need to save+restore eax
; around it.
; CHECK: pushl %eax
; CHECK: movl [[REG]], %eax
; CHECK: addb $127, %al
; CHECK: sahf
; CHECK: popl %eax
br i1 %tobool, label %if.end, label %if.then
if.then:
%conv6 = sext i8 %inc to i32
%call = tail call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0), i32 %conv6)
call void @external(i32 %conv6)
br label %if.end
if.end:
ret i32 0
}
declare i32 @printf(i8* nocapture readonly, ...)
; Preserve increment flags across a call.
define i32 @test2(i32* %ptr) nounwind {
; X32-LABEL: test2:
; X32: # %bb.0: # %entry
; X32-NEXT: pushl %ebx
; X32-NEXT: movl {{[0-9]+}}(%esp), %eax
; X32-NEXT: incl (%eax)
; X32-NEXT: setne %bl
; X32-NEXT: pushl $42
; X32-NEXT: calll external
; X32-NEXT: addl $4, %esp
; X32-NEXT: testb %bl, %bl
; X32-NEXT: je .LBB1_1
; X32-NEXT: # %bb.2: # %else
; X32-NEXT: xorl %eax, %eax
; X32-NEXT: popl %ebx
; X32-NEXT: retl
; X32-NEXT: .LBB1_1: # %then
; X32-NEXT: movl $64, %eax
; X32-NEXT: popl %ebx
; X32-NEXT: retl
;
; X64-LABEL: test2:
; X64: # %bb.0: # %entry
; X64-NEXT: pushq %rbx
; X64-NEXT: incl (%rdi)
; X64-NEXT: setne %bl
; X64-NEXT: movl $42, %edi
; X64-NEXT: callq external
; X64-NEXT: testb %bl, %bl
; X64-NEXT: je .LBB1_1
; X64-NEXT: # %bb.2: # %else
; X64-NEXT: xorl %eax, %eax
; X64-NEXT: popq %rbx
; X64-NEXT: retq
; X64-NEXT: .LBB1_1: # %then
; X64-NEXT: movl $64, %eax
; X64-NEXT: popq %rbx
; X64-NEXT: retq
entry:
%val = load i32, i32* %ptr
%inc = add i32 %val, 1
store i32 %inc, i32* %ptr
%cmp = icmp eq i32 %inc, 0
call void @external(i32 42)
br i1 %cmp, label %then, label %else
then:
ret i32 64
else:
ret i32 0
}
declare void @external_a()
declare void @external_b()
; This lowers to a conditional tail call instead of a conditional branch. This
; is tricky because we can only do this from a leaf function, and so we have to
; use volatile stores similar to test1 to force the save and restore of
; a condition without calling another function. We then set up subsequent calls
; in tail position.
define void @test_tail_call(i32* %ptr) nounwind optsize {
; X32-LABEL: test_tail_call:
; X32: # %bb.0: # %entry
; X32-NEXT: movl {{[0-9]+}}(%esp), %eax
; X32-NEXT: incl (%eax)
; X32-NEXT: setne %al
; X32-NEXT: incb a
; X32-NEXT: sete d
; X32-NEXT: testb %al, %al
; X32-NEXT: jne external_b # TAILCALL
; X32-NEXT: # %bb.1: # %then
; X32-NEXT: jmp external_a # TAILCALL
;
; X64-LABEL: test_tail_call:
; X64: # %bb.0: # %entry
; X64-NEXT: incl (%rdi)
; X64-NEXT: setne %al
; X64-NEXT: incb {{.*}}(%rip)
; X64-NEXT: sete {{.*}}(%rip)
; X64-NEXT: testb %al, %al
; X64-NEXT: jne external_b # TAILCALL
; X64-NEXT: # %bb.1: # %then
; X64-NEXT: jmp external_a # TAILCALL
entry:
%val = load i32, i32* %ptr
%inc = add i32 %val, 1
store i32 %inc, i32* %ptr
%cmp = icmp eq i32 %inc, 0
%aval = load volatile i8, i8* @a
%inc2 = add i8 %aval, 1
store volatile i8 %inc2, i8* @a
%cmp2 = icmp eq i8 %inc2, 0
%conv5 = zext i1 %cmp2 to i8
store i8 %conv5, i8* @d
br i1 %cmp, label %then, label %else
then:
tail call void @external_a()
ret void
else:
tail call void @external_b()
ret void
}
; Test a function that gets special select lowering into CFG with copied EFLAGS
; threaded across the CFG. This requires our EFLAGS copy rewriting to handle
; cross-block rewrites in at least some narrow cases.
define void @PR37100(i8 %arg1, i16 %arg2, i64 %arg3, i8 %arg4, i8* %ptr1, i32* %ptr2) {
; X32-LABEL: PR37100:
; X32: # %bb.0: # %bb
; X32-NEXT: pushl %ebp
; X32-NEXT: .cfi_def_cfa_offset 8
; X32-NEXT: pushl %ebx
; X32-NEXT: .cfi_def_cfa_offset 12
; X32-NEXT: pushl %edi
; X32-NEXT: .cfi_def_cfa_offset 16
; X32-NEXT: pushl %esi
; X32-NEXT: .cfi_def_cfa_offset 20
; X32-NEXT: .cfi_offset %esi, -20
; X32-NEXT: .cfi_offset %edi, -16
; X32-NEXT: .cfi_offset %ebx, -12
; X32-NEXT: .cfi_offset %ebp, -8
; X32-NEXT: movl {{[0-9]+}}(%esp), %esi
; X32-NEXT: movl {{[0-9]+}}(%esp), %edi
; X32-NEXT: movl {{[0-9]+}}(%esp), %ebx
; X32-NEXT: movb {{[0-9]+}}(%esp), %ch
; X32-NEXT: movb {{[0-9]+}}(%esp), %cl
; X32-NEXT: jmp .LBB3_1
; X32-NEXT: .p2align 4, 0x90
; X32-NEXT: .LBB3_5: # %bb1
; X32-NEXT: # in Loop: Header=BB3_1 Depth=1
; X32-NEXT: xorl %eax, %eax
; X32-NEXT: xorl %edx, %edx
; X32-NEXT: idivl %ebp
; X32-NEXT: .LBB3_1: # %bb1
; X32-NEXT: # =>This Inner Loop Header: Depth=1
; X32-NEXT: movsbl %cl, %eax
; X32-NEXT: movl %eax, %edx
; X32-NEXT: sarl $31, %edx
; X32-NEXT: cmpl %eax, %esi
; X32-NEXT: movl {{[0-9]+}}(%esp), %eax
; X32-NEXT: sbbl %edx, %eax
; X32-NEXT: setl %al
; X32-NEXT: setl %dl
; X32-NEXT: movzbl %dl, %ebp
; X32-NEXT: negl %ebp
; X32-NEXT: testb %al, %al
; X32-NEXT: jne .LBB3_3
; X32-NEXT: # %bb.2: # %bb1
; X32-NEXT: # in Loop: Header=BB3_1 Depth=1
; X32-NEXT: movb %ch, %cl
; X32-NEXT: .LBB3_3: # %bb1
; X32-NEXT: # in Loop: Header=BB3_1 Depth=1
; X32-NEXT: movb %cl, (%ebx)
; X32-NEXT: movl (%edi), %edx
; X32-NEXT: testb %al, %al
; X32-NEXT: jne .LBB3_5
; X32-NEXT: # %bb.4: # %bb1
; X32-NEXT: # in Loop: Header=BB3_1 Depth=1
; X32-NEXT: movl %edx, %ebp
; X32-NEXT: jmp .LBB3_5
;
; X64-LABEL: PR37100:
; X64: # %bb.0: # %bb
; X64-NEXT: movq %rdx, %r10
; X64-NEXT: jmp .LBB3_1
; X64-NEXT: .p2align 4, 0x90
; X64-NEXT: .LBB3_5: # %bb1
; X64-NEXT: # in Loop: Header=BB3_1 Depth=1
; X64-NEXT: xorl %eax, %eax
; X64-NEXT: xorl %edx, %edx
; X64-NEXT: idivl %esi
; X64-NEXT: .LBB3_1: # %bb1
; X64-NEXT: # =>This Inner Loop Header: Depth=1
; X64-NEXT: movsbq %dil, %rax
; X64-NEXT: xorl %esi, %esi
; X64-NEXT: cmpq %rax, %r10
; X64-NEXT: setl %sil
; X64-NEXT: negl %esi
; X64-NEXT: cmpq %rax, %r10
; X64-NEXT: jl .LBB3_3
; X64-NEXT: # %bb.2: # %bb1
; X64-NEXT: # in Loop: Header=BB3_1 Depth=1
; X64-NEXT: movl %ecx, %edi
; X64-NEXT: .LBB3_3: # %bb1
; X64-NEXT: # in Loop: Header=BB3_1 Depth=1
; X64-NEXT: movb %dil, (%r8)
; X64-NEXT: jl .LBB3_5
; X64-NEXT: # %bb.4: # %bb1
; X64-NEXT: # in Loop: Header=BB3_1 Depth=1
; X64-NEXT: movl (%r9), %esi
; X64-NEXT: jmp .LBB3_5
bb:
br label %bb1
bb1:
%tmp = phi i8 [ %tmp8, %bb1 ], [ %arg1, %bb ]
%tmp2 = phi i16 [ %tmp12, %bb1 ], [ %arg2, %bb ]
%tmp3 = icmp sgt i16 %tmp2, 7
%tmp4 = select i1 %tmp3, i16 %tmp2, i16 7
%tmp5 = sext i8 %tmp to i64
%tmp6 = icmp slt i64 %arg3, %tmp5
%tmp7 = sext i1 %tmp6 to i32
%tmp8 = select i1 %tmp6, i8 %tmp, i8 %arg4
store volatile i8 %tmp8, i8* %ptr1
%tmp9 = load volatile i32, i32* %ptr2
%tmp10 = select i1 %tmp6, i32 %tmp7, i32 %tmp9
%tmp11 = srem i32 0, %tmp10
%tmp12 = trunc i32 %tmp11 to i16
br label %bb1
}
; Use a particular instruction pattern in order to lower to the post-RA pseudo
; used to lower SETB into an SBB pattern in order to make sure that kind of
; usage of a copied EFLAGS continues to work.
define void @PR37431(i32* %arg1, i8* %arg2, i8* %arg3) {
; X32-LABEL: PR37431:
; X32: # %bb.0: # %entry
; X32-NEXT: pushl %esi
; X32-NEXT: .cfi_def_cfa_offset 8
; X32-NEXT: .cfi_offset %esi, -8
; X32-NEXT: movl {{[0-9]+}}(%esp), %eax
; X32-NEXT: movl (%eax), %eax
; X32-NEXT: movl %eax, %ecx
; X32-NEXT: sarl $31, %ecx
; X32-NEXT: cmpl %eax, %eax
; X32-NEXT: sbbl %ecx, %eax
; X32-NEXT: setb %al
; X32-NEXT: sbbb %cl, %cl
; X32-NEXT: movl {{[0-9]+}}(%esp), %esi
; X32-NEXT: movl {{[0-9]+}}(%esp), %edx
; X32-NEXT: movb %cl, (%edx)
; X32-NEXT: movzbl %al, %eax
; X32-NEXT: xorl %ecx, %ecx
; X32-NEXT: subl %eax, %ecx
; X32-NEXT: xorl %eax, %eax
; X32-NEXT: xorl %edx, %edx
; X32-NEXT: idivl %ecx
; X32-NEXT: movb %dl, (%esi)
; X32-NEXT: popl %esi
; X32-NEXT: retl
;
; X64-LABEL: PR37431:
; X64: # %bb.0: # %entry
; X64-NEXT: movq %rdx, %rcx
; X64-NEXT: movslq (%rdi), %rax
; X64-NEXT: cmpq %rax, %rax
; X64-NEXT: sbbb %dl, %dl
; X64-NEXT: cmpq %rax, %rax
; X64-NEXT: movb %dl, (%rsi)
; X64-NEXT: sbbl %esi, %esi
; X64-NEXT: xorl %eax, %eax
; X64-NEXT: xorl %edx, %edx
; X64-NEXT: idivl %esi
; X64-NEXT: movb %dl, (%rcx)
; X64-NEXT: retq
entry:
%tmp = load i32, i32* %arg1
%tmp1 = sext i32 %tmp to i64
%tmp2 = icmp ugt i64 %tmp1, undef
%tmp3 = zext i1 %tmp2 to i8
%tmp4 = sub i8 0, %tmp3
store i8 %tmp4, i8* %arg2
%tmp5 = sext i8 %tmp4 to i32
%tmp6 = srem i32 0, %tmp5
%tmp7 = trunc i32 %tmp6 to i8
store i8 %tmp7, i8* %arg3
ret void
}

View File

@@ -0,0 +1,24 @@
; RUN: llc -mcpu=skylake-avx512 -mtriple=x86_64-unknown-linux-gnu %s -o - | FileCheck %s
; Check that the X86 Domain Reassignment pass doesn't drop IMPLICIT_DEF nodes,
; which would later cause crashes (e.g. in LiveVariables) - see PR37430
define void @domain_reassignment_implicit_def(i1 %cond, i8 *%mem, float %arg) {
; CHECK: vxorps %xmm1, %xmm1, %xmm1
; CHECK: vcmpneqss %xmm1, %xmm0, %k0
; CHECK: kmovb %k0, (%rsi)
top:
br i1 %cond, label %L19, label %L15
L15: ; preds = %top
%tmp47 = fcmp une float 0.000000e+00, %arg
%tmp48 = zext i1 %tmp47 to i8
br label %L21
L19: ; preds = %top
br label %L21
L21: ; preds = %L19, %L15
%.sroa.0.0 = phi i8 [ undef, %L19 ], [ %tmp48, %L15 ]
store i8 %.sroa.0.0, i8* %mem, align 1
ret void
}

View File

@@ -0,0 +1,37 @@
; RUN: llc -mcpu=skylake-avx512 -mtriple=x86_64-unknown-linux-gnu %s -o - | FileCheck %s
; RUN: llc -mcpu=skylake-avx512 -mtriple=x86_64-unknown-linux-gnu %s -o - | llvm-mc -triple=x86_64-unknown-linux-gnu -mcpu=skylake-avx512
; Check that the X86 domain reassignment pass doesn't introduce an illegal
; test instruction. See PR37396
define void @japi1_foo2_34617() {
pass2:
br label %if5
L174:
%tmp = icmp sgt <2 x i64> undef, zeroinitializer
%tmp1 = icmp sle <2 x i64> undef, undef
%tmp2 = and <2 x i1> %tmp, %tmp1
%tmp3 = extractelement <2 x i1> %tmp2, i32 0
%tmp4 = extractelement <2 x i1> %tmp2, i32 1
%tmp106 = and i1 %tmp4, %tmp3
%tmp107 = zext i1 %tmp106 to i8
%tmp108 = and i8 %tmp122, %tmp107
%tmp109 = icmp eq i8 %tmp108, 0
; CHECK-NOT: testb {{%k[0-7]}}
br i1 %tmp109, label %L188, label %L190
if5:
%b.055 = phi i8 [ 1, %pass2 ], [ %tmp122, %if5 ]
%tmp118 = icmp sgt i64 undef, 0
%tmp119 = icmp sle i64 undef, undef
%tmp120 = and i1 %tmp118, %tmp119
%tmp121 = zext i1 %tmp120 to i8
%tmp122 = and i8 %b.055, %tmp121
br i1 undef, label %L174, label %if5
L188:
unreachable
L190:
ret void
}

View File

@@ -1,64 +0,0 @@
# RUN: llc -run-pass postrapseudos -mtriple=i386-apple-macosx -o - %s | FileCheck %s
# Verify that we correctly save and restore eax when copying eflags,
# even when only a smaller alias of eax is used. We used to check only
# eax and not its aliases.
# PR27624.
--- |
target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
define void @foo() {
entry:
br label %false
false:
ret void
}
...
---
name: foo
tracksRegLiveness: true
liveins:
- { reg: '%edi' }
body: |
bb.0.entry:
liveins: %edi
NOOP implicit-def %al
; The bug was triggered only when LivePhysReg is used, which
; happens only when the heuristic for the liveness computation
; failed. The liveness computation heuristic looks at 10 instructions
; before and after the copy. Make sure we do not reach the definition of
; AL in 10 instructions, otherwise the heuristic will see that it is live.
NOOP
NOOP
NOOP
NOOP
NOOP
NOOP
NOOP
NOOP
NOOP
NOOP
NOOP
NOOP
NOOP
; Save AL.
; CHECK: PUSH32r killed %eax
; Copy edi into EFLAGS
; CHECK-NEXT: %eax = MOV32rr %edi
; CHECK-NEXT: %al = ADD8ri %al, 127, implicit-def %eflags
; CHECK-NEXT: SAHF implicit-def %eflags, implicit %ah
%eflags = COPY %edi
; Restore AL.
; CHECK-NEXT: %eax = POP32r
bb.1.false:
liveins: %al
NOOP implicit %al
RETQ
...

View File

@@ -381,3 +381,15 @@ define i64 @ashr_imm4_i64(i64 %a) {
%c = ashr i64 %a, 4
ret i64 %c
}
; Make sure we don't crash on out of bounds i8 shifts.
define i8 @PR36731(i8 %a) {
; CHECK-LABEL: PR36731:
; CHECK: ## %bb.0:
; CHECK-NEXT: movb $255, %cl
; CHECK-NEXT: shlb %cl, %dil
; CHECK-NEXT: movl %edi, %eax
; CHECK-NEXT: retq
%b = shl i8 %a, -1
ret i8 %b
}

File diff suppressed because it is too large Load Diff

View File

@@ -3,7 +3,7 @@
target triple = "x86_64-unknown-unknown"
declare void @bar1()
define preserve_allcc void @foo()#0 {
; CHECK: foo Clobbered Registers: %cs %ds %eflags %eip %eiz %es %fpsw %fs %gs %ip %rip %riz %ss %ssp %bnd0 %bnd1 %bnd2 %bnd3 %cr0 %cr1 %cr2 %cr3 %cr4 %cr5 %cr6 %cr7 %cr8 %cr9 %cr10 %cr11 %cr12 %cr13 %cr14 %cr15 %dr0 %dr1 %dr2 %dr3 %dr4 %dr5 %dr6 %dr7 %dr8 %dr9 %dr10 %dr11 %dr12 %dr13 %dr14 %dr15 %fp0 %fp1 %fp2 %fp3 %fp4 %fp5 %fp6 %fp7 %k0 %k1 %k2 %k3 %k4 %k5 %k6 %k7 %mm0 %mm1 %mm2 %mm3 %mm4 %mm5 %mm6 %mm7 %r11 %st0 %st1 %st2 %st3 %st4 %st5 %st6 %st7 %xmm16 %xmm17 %xmm18 %xmm19 %xmm20 %xmm21 %xmm22 %xmm23 %xmm24 %xmm25 %xmm26 %xmm27 %xmm28 %xmm29 %xmm30 %xmm31 %ymm0 %ymm1 %ymm2 %ymm3 %ymm4 %ymm5 %ymm6 %ymm7 %ymm8 %ymm9 %ymm10 %ymm11 %ymm12 %ymm13 %ymm14 %ymm15 %ymm16 %ymm17 %ymm18 %ymm19 %ymm20 %ymm21 %ymm22 %ymm23 %ymm24 %ymm25 %ymm26 %ymm27 %ymm28 %ymm29 %ymm30 %ymm31 %zmm0 %zmm1 %zmm2 %zmm3 %zmm4 %zmm5 %zmm6 %zmm7 %zmm8 %zmm9 %zmm10 %zmm11 %zmm12 %zmm13 %zmm14 %zmm15 %zmm16 %zmm17 %zmm18 %zmm19 %zmm20 %zmm21 %zmm22 %zmm23 %zmm24 %zmm25 %zmm26 %zmm27 %zmm28 %zmm29 %zmm30 %zmm31 %r11b %r11d %r11w
; CHECK: foo Clobbered Registers: %cs %df %ds %eflags %eip %eiz %es %fpsw %fs %gs %ip %rip %riz %ss %ssp %bnd0 %bnd1 %bnd2 %bnd3 %cr0 %cr1 %cr2 %cr3 %cr4 %cr5 %cr6 %cr7 %cr8 %cr9 %cr10 %cr11 %cr12 %cr13 %cr14 %cr15 %dr0 %dr1 %dr2 %dr3 %dr4 %dr5 %dr6 %dr7 %dr8 %dr9 %dr10 %dr11 %dr12 %dr13 %dr14 %dr15 %fp0 %fp1 %fp2 %fp3 %fp4 %fp5 %fp6 %fp7 %k0 %k1 %k2 %k3 %k4 %k5 %k6 %k7 %mm0 %mm1 %mm2 %mm3 %mm4 %mm5 %mm6 %mm7 %r11 %st0 %st1 %st2 %st3 %st4 %st5 %st6 %st7 %xmm16 %xmm17 %xmm18 %xmm19 %xmm20 %xmm21 %xmm22 %xmm23 %xmm24 %xmm25 %xmm26 %xmm27 %xmm28 %xmm29 %xmm30 %xmm31 %ymm0 %ymm1 %ymm2 %ymm3 %ymm4 %ymm5 %ymm6 %ymm7 %ymm8 %ymm9 %ymm10 %ymm11 %ymm12 %ymm13 %ymm14 %ymm15 %ymm16 %ymm17 %ymm18 %ymm19 %ymm20 %ymm21 %ymm22 %ymm23 %ymm24 %ymm25 %ymm26 %ymm27 %ymm28 %ymm29 %ymm30 %ymm31 %zmm0 %zmm1 %zmm2 %zmm3 %zmm4 %zmm5 %zmm6 %zmm7 %zmm8 %zmm9 %zmm10 %zmm11 %zmm12 %zmm13 %zmm14 %zmm15 %zmm16 %zmm17 %zmm18 %zmm19 %zmm20 %zmm21 %zmm22 %zmm23 %zmm24 %zmm25 %zmm26 %zmm27 %zmm28 %zmm29 %zmm30 %zmm31 %r11b %r11d %r11w
call void @bar1()
call void @bar2()
ret void

View File

@@ -1 +1 @@
9980042a4ccc8fbd2d076d697f931340813ec909
16fb112efadb2d79b4ca251491aefd844d079edf

View File

@@ -1,13 +1,10 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc -mtriple=i386-linux-gnu %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK32
; RUN: llc -mtriple=x86_64-linux-gnu -mattr=+sahf %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK64
; TODO: Reenable verify-machineinstrs once the if (!AXDead) // FIXME in
; X86InstrInfo::copyPhysReg() is resolved.
; RUN: llc -mtriple=i386-linux-gnu -verify-machineinstrs %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK32
; RUN: llc -mtriple=x86_64-linux-gnu -verify-machineinstrs %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK64
; The peephole optimizer can elide some physical register copies such as
; EFLAGS. Make sure the flags are used directly, instead of needlessly using
; lahf, when possible.
; saving and restoring specific conditions.
@L = external global i32
@M = external global i8
@@ -209,29 +206,22 @@ exit2:
define i64 @test_intervening_call(i64* %foo, i64 %bar, i64 %baz) nounwind {
; CHECK32-LABEL: test_intervening_call:
; CHECK32: # %bb.0: # %entry
; CHECK32-NEXT: pushl %ebp
; CHECK32-NEXT: movl %esp, %ebp
; CHECK32-NEXT: pushl %ebx
; CHECK32-NEXT: pushl %esi
; CHECK32-NEXT: movl 12(%ebp), %eax
; CHECK32-NEXT: movl 16(%ebp), %edx
; CHECK32-NEXT: movl 20(%ebp), %ebx
; CHECK32-NEXT: movl 24(%ebp), %ecx
; CHECK32-NEXT: movl 8(%ebp), %esi
; CHECK32-NEXT: lock cmpxchg8b (%esi)
; CHECK32-NEXT: pushl %eax
; CHECK32-NEXT: seto %al
; CHECK32-NEXT: lahf
; CHECK32-NEXT: movl %eax, %esi
; CHECK32-NEXT: popl %eax
; CHECK32-NEXT: movl {{[0-9]+}}(%esp), %eax
; CHECK32-NEXT: movl {{[0-9]+}}(%esp), %edx
; CHECK32-NEXT: movl {{[0-9]+}}(%esp), %ebx
; CHECK32-NEXT: movl {{[0-9]+}}(%esp), %ecx
; CHECK32-NEXT: movl {{[0-9]+}}(%esp), %esi
; CHECK32-NEXT: lock cmpxchg8b (%esi)
; CHECK32-NEXT: setne %bl
; CHECK32-NEXT: subl $8, %esp
; CHECK32-NEXT: pushl %edx
; CHECK32-NEXT: pushl %eax
; CHECK32-NEXT: calll bar
; CHECK32-NEXT: addl $16, %esp
; CHECK32-NEXT: movl %esi, %eax
; CHECK32-NEXT: addb $127, %al
; CHECK32-NEXT: sahf
; CHECK32-NEXT: testb %bl, %bl
; CHECK32-NEXT: jne .LBB4_3
; CHECK32-NEXT: # %bb.1: # %t
; CHECK32-NEXT: movl $42, %eax
@@ -240,39 +230,28 @@ define i64 @test_intervening_call(i64* %foo, i64 %bar, i64 %baz) nounwind {
; CHECK32-NEXT: xorl %eax, %eax
; CHECK32-NEXT: .LBB4_2: # %t
; CHECK32-NEXT: xorl %edx, %edx
; CHECK32-NEXT: addl $4, %esp
; CHECK32-NEXT: popl %esi
; CHECK32-NEXT: popl %ebx
; CHECK32-NEXT: popl %ebp
; CHECK32-NEXT: retl
;
; CHECK64-LABEL: test_intervening_call:
; CHECK64: # %bb.0: # %entry
; CHECK64-NEXT: pushq %rbp
; CHECK64-NEXT: movq %rsp, %rbp
; CHECK64-NEXT: pushq %rbx
; CHECK64-NEXT: pushq %rax
; CHECK64-NEXT: movq %rsi, %rax
; CHECK64-NEXT: lock cmpxchgq %rdx, (%rdi)
; CHECK64-NEXT: pushq %rax
; CHECK64-NEXT: seto %al
; CHECK64-NEXT: lahf
; CHECK64-NEXT: movq %rax, %rbx
; CHECK64-NEXT: popq %rax
; CHECK64-NEXT: setne %bl
; CHECK64-NEXT: movq %rax, %rdi
; CHECK64-NEXT: callq bar
; CHECK64-NEXT: movq %rbx, %rax
; CHECK64-NEXT: addb $127, %al
; CHECK64-NEXT: sahf
; CHECK64-NEXT: jne .LBB4_3
; CHECK64-NEXT: testb %bl, %bl
; CHECK64-NEXT: jne .LBB4_2
; CHECK64-NEXT: # %bb.1: # %t
; CHECK64-NEXT: movl $42, %eax
; CHECK64-NEXT: jmp .LBB4_2
; CHECK64-NEXT: .LBB4_3: # %f
; CHECK64-NEXT: xorl %eax, %eax
; CHECK64-NEXT: .LBB4_2: # %t
; CHECK64-NEXT: addq $8, %rsp
; CHECK64-NEXT: popq %rbx
; CHECK64-NEXT: popq %rbp
; CHECK64-NEXT: retq
; CHECK64-NEXT: .LBB4_2: # %f
; CHECK64-NEXT: xorl %eax, %eax
; CHECK64-NEXT: popq %rbx
; CHECK64-NEXT: retq
entry:
; cmpxchg sets EFLAGS, call clobbers it, then br uses EFLAGS.
@@ -293,32 +272,27 @@ define i64 @test_two_live_flags(i64* %foo0, i64 %bar0, i64 %baz0, i64* %foo1, i6
; CHECK32-LABEL: test_two_live_flags:
; CHECK32: # %bb.0: # %entry
; CHECK32-NEXT: pushl %ebp
; CHECK32-NEXT: movl %esp, %ebp
; CHECK32-NEXT: pushl %ebx
; CHECK32-NEXT: pushl %edi
; CHECK32-NEXT: pushl %esi
; CHECK32-NEXT: movl 44(%ebp), %edi
; CHECK32-NEXT: movl 12(%ebp), %eax
; CHECK32-NEXT: movl 16(%ebp), %edx
; CHECK32-NEXT: movl 20(%ebp), %ebx
; CHECK32-NEXT: movl 24(%ebp), %ecx
; CHECK32-NEXT: movl 8(%ebp), %esi
; CHECK32-NEXT: lock cmpxchg8b (%esi)
; CHECK32-NEXT: seto %al
; CHECK32-NEXT: lahf
; CHECK32-NEXT: movl %eax, %esi
; CHECK32-NEXT: movl 32(%ebp), %eax
; CHECK32-NEXT: movl 36(%ebp), %edx
; CHECK32-NEXT: movl %edi, %ecx
; CHECK32-NEXT: movl 40(%ebp), %ebx
; CHECK32-NEXT: movl 28(%ebp), %edi
; CHECK32-NEXT: lock cmpxchg8b (%edi)
; CHECK32-NEXT: sete %al
; CHECK32-NEXT: pushl %eax
; CHECK32-NEXT: movl %esi, %eax
; CHECK32-NEXT: addb $127, %al
; CHECK32-NEXT: sahf
; CHECK32-NEXT: popl %eax
; CHECK32-NEXT: movl {{[0-9]+}}(%esp), %edi
; CHECK32-NEXT: movl {{[0-9]+}}(%esp), %ebp
; CHECK32-NEXT: movl {{[0-9]+}}(%esp), %eax
; CHECK32-NEXT: movl {{[0-9]+}}(%esp), %edx
; CHECK32-NEXT: movl {{[0-9]+}}(%esp), %ebx
; CHECK32-NEXT: movl {{[0-9]+}}(%esp), %ecx
; CHECK32-NEXT: movl {{[0-9]+}}(%esp), %esi
; CHECK32-NEXT: lock cmpxchg8b (%esi)
; CHECK32-NEXT: setne {{[-0-9]+}}(%e{{[sb]}}p) # 1-byte Folded Spill
; CHECK32-NEXT: movl {{[0-9]+}}(%esp), %eax
; CHECK32-NEXT: movl %edi, %edx
; CHECK32-NEXT: movl %ebp, %ecx
; CHECK32-NEXT: movl {{[0-9]+}}(%esp), %ebx
; CHECK32-NEXT: movl {{[0-9]+}}(%esp), %esi
; CHECK32-NEXT: lock cmpxchg8b (%esi)
; CHECK32-NEXT: sete %al
; CHECK32-NEXT: cmpb $0, {{[-0-9]+}}(%e{{[sb]}}p) # 1-byte Folded Reload
; CHECK32-NEXT: jne .LBB5_4
; CHECK32-NEXT: # %bb.1: # %entry
; CHECK32-NEXT: testb %al, %al
@@ -330,6 +304,7 @@ define i64 @test_two_live_flags(i64* %foo0, i64 %bar0, i64 %baz0, i64* %foo1, i6
; CHECK32-NEXT: xorl %eax, %eax
; CHECK32-NEXT: .LBB5_3: # %t
; CHECK32-NEXT: xorl %edx, %edx
; CHECK32-NEXT: addl $4, %esp
; CHECK32-NEXT: popl %esi
; CHECK32-NEXT: popl %edi
; CHECK32-NEXT: popl %ebx
@@ -338,32 +313,22 @@ define i64 @test_two_live_flags(i64* %foo0, i64 %bar0, i64 %baz0, i64* %foo1, i6
;
; CHECK64-LABEL: test_two_live_flags:
; CHECK64: # %bb.0: # %entry
; CHECK64-NEXT: pushq %rbp
; CHECK64-NEXT: movq %rsp, %rbp
; CHECK64-NEXT: movq %rsi, %rax
; CHECK64-NEXT: lock cmpxchgq %rdx, (%rdi)
; CHECK64-NEXT: seto %al
; CHECK64-NEXT: lahf
; CHECK64-NEXT: movq %rax, %rdx
; CHECK64-NEXT: setne %dl
; CHECK64-NEXT: movq %r8, %rax
; CHECK64-NEXT: lock cmpxchgq %r9, (%rcx)
; CHECK64-NEXT: sete %al
; CHECK64-NEXT: pushq %rax
; CHECK64-NEXT: movq %rdx, %rax
; CHECK64-NEXT: addb $127, %al
; CHECK64-NEXT: sahf
; CHECK64-NEXT: popq %rax
; CHECK64-NEXT: testb %dl, %dl
; CHECK64-NEXT: jne .LBB5_3
; CHECK64-NEXT: # %bb.1: # %entry
; CHECK64-NEXT: testb %al, %al
; CHECK64-NEXT: je .LBB5_3
; CHECK64-NEXT: # %bb.2: # %t
; CHECK64-NEXT: movl $42, %eax
; CHECK64-NEXT: popq %rbp
; CHECK64-NEXT: retq
; CHECK64-NEXT: .LBB5_3: # %f
; CHECK64-NEXT: xorl %eax, %eax
; CHECK64-NEXT: popq %rbp
; CHECK64-NEXT: retq
entry:
%cx0 = cmpxchg i64* %foo0, i64 %bar0, i64 %baz0 seq_cst seq_cst

View File

@@ -0,0 +1,12 @@
; RUN: llc < %s -mtriple=x86_64--
define void @a() local_unnamed_addr #0 {
ret void
}
define void @b() local_unnamed_addr #1 {
ret void
}
attributes #0 = { "target-features"="+avx,+avx2,+avx512bw,+avx512f,+f16c,+fma,+mmx,+popcnt,+sse,+sse2,+sse3,+sse4.1,+sse4.2,+ssse3,+x87,+xsave" }
attributes #1 = { "target-features"="+avx,+avx2,+avx512f,+avx512vl,+f16c,+fma,+mmx,+popcnt,+sse,+sse2,+sse3,+sse4.1,+sse4.2,+ssse3,+x87,+xsave" }

View File

@@ -1,43 +1,85 @@
; RUN: llc < %s -mtriple=x86_64-pc-win32 | FileCheck %s --check-prefix=CHECK --check-prefix=PUSHF
; RUN: llc < %s -mtriple=x86_64-pc-win32 -mattr=+sahf | FileCheck %s --check-prefix=SAHF
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc < %s -mtriple=x86_64-pc-win32 | FileCheck %s --check-prefix=ALL --check-prefix=PUSHF
; RUN: llc < %s -mtriple=x86_64-pc-win32 -mattr=+sahf | FileCheck %s --check-prefix=ALL --check-prefix=SAHF
define i32 @f1(i32 %p1, i32 %p2, i32 %p3, i32 %p4, i32 %p5) "no-frame-pointer-elim"="true" {
; CHECK-LABEL: f1:
; CHECK: movl 48(%rbp), %eax
; ALL-LABEL: f1:
; ALL: # %bb.0:
; ALL-NEXT: pushq %rbp
; ALL-NEXT: .seh_pushreg 5
; ALL-NEXT: movq %rsp, %rbp
; ALL-NEXT: .seh_setframe 5, 0
; ALL-NEXT: .seh_endprologue
; ALL-NEXT: movl 48(%rbp), %eax
; ALL-NEXT: popq %rbp
; ALL-NEXT: retq
; ALL-NEXT: .seh_handlerdata
; ALL-NEXT: .text
; ALL-NEXT: .seh_endproc
ret i32 %p5
}
define void @f2(i32 %p, ...) "no-frame-pointer-elim"="true" {
; CHECK-LABEL: f2:
; CHECK: .seh_stackalloc 8
; CHECK: movq %rsp, %rbp
; CHECK: .seh_setframe 5, 0
; CHECK: movq %rdx, 32(%rbp)
; CHECK: leaq 32(%rbp), %rax
; ALL-LABEL: f2:
; ALL: # %bb.0:
; ALL-NEXT: pushq %rbp
; ALL-NEXT: .seh_pushreg 5
; ALL-NEXT: pushq %rax
; ALL-NEXT: .seh_stackalloc 8
; ALL-NEXT: movq %rsp, %rbp
; ALL-NEXT: .seh_setframe 5, 0
; ALL-NEXT: .seh_endprologue
; ALL-NEXT: movq %r9, 48(%rbp)
; ALL-NEXT: movq %r8, 40(%rbp)
; ALL-NEXT: movq %rdx, 32(%rbp)
; ALL-NEXT: leaq 32(%rbp), %rax
; ALL-NEXT: movq %rax, (%rbp)
; ALL-NEXT: addq $8, %rsp
; ALL-NEXT: popq %rbp
; ALL-NEXT: retq
; ALL-NEXT: .seh_handlerdata
; ALL-NEXT: .text
; ALL-NEXT: .seh_endproc
%ap = alloca i8, align 8
call void @llvm.va_start(i8* %ap)
ret void
}
define i8* @f3() "no-frame-pointer-elim"="true" {
; CHECK-LABEL: f3:
; CHECK: movq %rsp, %rbp
; CHECK: .seh_setframe 5, 0
; CHECK: movq 8(%rbp), %rax
; ALL-LABEL: f3:
; ALL: # %bb.0:
; ALL-NEXT: pushq %rbp
; ALL-NEXT: .seh_pushreg 5
; ALL-NEXT: movq %rsp, %rbp
; ALL-NEXT: .seh_setframe 5, 0
; ALL-NEXT: .seh_endprologue
; ALL-NEXT: movq 8(%rbp), %rax
; ALL-NEXT: popq %rbp
; ALL-NEXT: retq
; ALL-NEXT: .seh_handlerdata
; ALL-NEXT: .text
; ALL-NEXT: .seh_endproc
%ra = call i8* @llvm.returnaddress(i32 0)
ret i8* %ra
}
define i8* @f4() "no-frame-pointer-elim"="true" {
; CHECK-LABEL: f4:
; CHECK: pushq %rbp
; CHECK: .seh_pushreg 5
; CHECK: subq $304, %rsp
; CHECK: .seh_stackalloc 304
; CHECK: leaq 128(%rsp), %rbp
; CHECK: .seh_setframe 5, 128
; CHECK: .seh_endprologue
; CHECK: movq 184(%rbp), %rax
; ALL-LABEL: f4:
; ALL: # %bb.0:
; ALL-NEXT: pushq %rbp
; ALL-NEXT: .seh_pushreg 5
; ALL-NEXT: subq $304, %rsp # imm = 0x130
; ALL-NEXT: .seh_stackalloc 304
; ALL-NEXT: leaq {{[0-9]+}}(%rsp), %rbp
; ALL-NEXT: .seh_setframe 5, 128
; ALL-NEXT: .seh_endprologue
; ALL-NEXT: movq 184(%rbp), %rax
; ALL-NEXT: addq $304, %rsp # imm = 0x130
; ALL-NEXT: popq %rbp
; ALL-NEXT: retq
; ALL-NEXT: .seh_handlerdata
; ALL-NEXT: .text
; ALL-NEXT: .seh_endproc
alloca [300 x i8]
%ra = call i8* @llvm.returnaddress(i32 0)
ret i8* %ra
@@ -46,13 +88,24 @@ define i8* @f4() "no-frame-pointer-elim"="true" {
declare void @external(i8*)
define void @f5() "no-frame-pointer-elim"="true" {
; CHECK-LABEL: f5:
; CHECK: subq $336, %rsp
; CHECK: .seh_stackalloc 336
; CHECK: leaq 128(%rsp), %rbp
; CHECK: .seh_setframe 5, 128
; CHECK: leaq -92(%rbp), %rcx
; CHECK: callq external
; ALL-LABEL: f5:
; ALL: # %bb.0:
; ALL-NEXT: pushq %rbp
; ALL-NEXT: .seh_pushreg 5
; ALL-NEXT: subq $336, %rsp # imm = 0x150
; ALL-NEXT: .seh_stackalloc 336
; ALL-NEXT: leaq {{[0-9]+}}(%rsp), %rbp
; ALL-NEXT: .seh_setframe 5, 128
; ALL-NEXT: .seh_endprologue
; ALL-NEXT: leaq -92(%rbp), %rcx
; ALL-NEXT: callq external
; ALL-NEXT: nop
; ALL-NEXT: addq $336, %rsp # imm = 0x150
; ALL-NEXT: popq %rbp
; ALL-NEXT: retq
; ALL-NEXT: .seh_handlerdata
; ALL-NEXT: .text
; ALL-NEXT: .seh_endproc
%a = alloca [300 x i8]
%gep = getelementptr [300 x i8], [300 x i8]* %a, i32 0, i32 0
call void @external(i8* %gep)
@@ -60,13 +113,24 @@ define void @f5() "no-frame-pointer-elim"="true" {
}
define void @f6(i32 %p, ...) "no-frame-pointer-elim"="true" {
; CHECK-LABEL: f6:
; CHECK: subq $336, %rsp
; CHECK: .seh_stackalloc 336
; CHECK: leaq 128(%rsp), %rbp
; CHECK: .seh_setframe 5, 128
; CHECK: leaq -92(%rbp), %rcx
; CHECK: callq external
; ALL-LABEL: f6:
; ALL: # %bb.0:
; ALL-NEXT: pushq %rbp
; ALL-NEXT: .seh_pushreg 5
; ALL-NEXT: subq $336, %rsp # imm = 0x150
; ALL-NEXT: .seh_stackalloc 336
; ALL-NEXT: leaq {{[0-9]+}}(%rsp), %rbp
; ALL-NEXT: .seh_setframe 5, 128
; ALL-NEXT: .seh_endprologue
; ALL-NEXT: leaq -92(%rbp), %rcx
; ALL-NEXT: callq external
; ALL-NEXT: nop
; ALL-NEXT: addq $336, %rsp # imm = 0x150
; ALL-NEXT: popq %rbp
; ALL-NEXT: retq
; ALL-NEXT: .seh_handlerdata
; ALL-NEXT: .text
; ALL-NEXT: .seh_endproc
%a = alloca [300 x i8]
%gep = getelementptr [300 x i8], [300 x i8]* %a, i32 0, i32 0
call void @external(i8* %gep)
@@ -74,130 +138,147 @@ define void @f6(i32 %p, ...) "no-frame-pointer-elim"="true" {
}
define i32 @f7(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e) "no-frame-pointer-elim"="true" {
; CHECK-LABEL: f7:
; CHECK: pushq %rbp
; CHECK: .seh_pushreg 5
; CHECK: subq $304, %rsp
; CHECK: .seh_stackalloc 304
; CHECK: leaq 128(%rsp), %rbp
; CHECK: .seh_setframe 5, 128
; CHECK: andq $-64, %rsp
; CHECK: movl 224(%rbp), %eax
; CHECK: leaq 176(%rbp), %rsp
; ALL-LABEL: f7:
; ALL: # %bb.0:
; ALL-NEXT: pushq %rbp
; ALL-NEXT: .seh_pushreg 5
; ALL-NEXT: subq $304, %rsp # imm = 0x130
; ALL-NEXT: .seh_stackalloc 304
; ALL-NEXT: leaq {{[0-9]+}}(%rsp), %rbp
; ALL-NEXT: .seh_setframe 5, 128
; ALL-NEXT: .seh_endprologue
; ALL-NEXT: andq $-64, %rsp
; ALL-NEXT: movl 224(%rbp), %eax
; ALL-NEXT: leaq 176(%rbp), %rsp
; ALL-NEXT: popq %rbp
; ALL-NEXT: retq
; ALL-NEXT: .seh_handlerdata
; ALL-NEXT: .text
; ALL-NEXT: .seh_endproc
alloca [300 x i8], align 64
ret i32 %e
}
define i32 @f8(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e) "no-frame-pointer-elim"="true" {
; CHECK-LABEL: f8:
; CHECK: subq $352, %rsp
; CHECK: .seh_stackalloc 352
; CHECK: leaq 128(%rsp), %rbp
; CHECK: .seh_setframe 5, 128
; ALL-LABEL: f8:
; ALL: # %bb.0:
; ALL-NEXT: pushq %rbp
; ALL-NEXT: .seh_pushreg 5
; ALL-NEXT: pushq %rsi
; ALL-NEXT: .seh_pushreg 6
; ALL-NEXT: pushq %rbx
; ALL-NEXT: .seh_pushreg 3
; ALL-NEXT: subq $352, %rsp # imm = 0x160
; ALL-NEXT: .seh_stackalloc 352
; ALL-NEXT: leaq {{[0-9]+}}(%rsp), %rbp
; ALL-NEXT: .seh_setframe 5, 128
; ALL-NEXT: .seh_endprologue
; ALL-NEXT: andq $-64, %rsp
; ALL-NEXT: movq %rsp, %rbx
; ALL-NEXT: movl 288(%rbp), %esi
; ALL-NEXT: movl %ecx, %eax
; ALL-NEXT: leaq 15(,%rax,4), %rcx
; ALL-NEXT: movabsq $34359738352, %rax # imm = 0x7FFFFFFF0
; ALL-NEXT: andq %rcx, %rax
; ALL-NEXT: callq __chkstk
; ALL-NEXT: subq %rax, %rsp
; ALL-NEXT: subq $32, %rsp
; ALL-NEXT: movq %rbx, %rcx
; ALL-NEXT: callq external
; ALL-NEXT: addq $32, %rsp
; ALL-NEXT: movl %esi, %eax
; ALL-NEXT: leaq 224(%rbp), %rsp
; ALL-NEXT: popq %rbx
; ALL-NEXT: popq %rsi
; ALL-NEXT: popq %rbp
; ALL-NEXT: retq
; ALL-NEXT: .seh_handlerdata
; ALL-NEXT: .text
; ALL-NEXT: .seh_endproc
%alloca = alloca [300 x i8], align 64
; CHECK: andq $-64, %rsp
; CHECK: movq %rsp, %rbx
alloca i32, i32 %a
; CHECK: movl %ecx, %eax
; CHECK: leaq 15(,%rax,4), %rcx
; CHECK: movabsq $34359738352, %rax
; CHECK: andq %rcx, %rax
; CHECK: callq __chkstk
; CHECK: subq %rax, %rsp
%gep = getelementptr [300 x i8], [300 x i8]* %alloca, i32 0, i32 0
call void @external(i8* %gep)
; CHECK: subq $32, %rsp
; CHECK: movq %rbx, %rcx
; CHECK: callq external
; CHECK: addq $32, %rsp
ret i32 %e
; CHECK: movl %esi, %eax
; CHECK: leaq 224(%rbp), %rsp
}
define i64 @f9() {
; ALL-LABEL: f9:
; ALL: # %bb.0: # %entry
; ALL-NEXT: pushq %rbp
; ALL-NEXT: .seh_pushreg 5
; ALL-NEXT: movq %rsp, %rbp
; ALL-NEXT: .seh_setframe 5, 0
; ALL-NEXT: .seh_endprologue
; ALL-NEXT: pushfq
; ALL-NEXT: popq %rax
; ALL-NEXT: popq %rbp
; ALL-NEXT: retq
; ALL-NEXT: .seh_handlerdata
; ALL-NEXT: .text
; ALL-NEXT: .seh_endproc
entry:
; CHECK-LABEL: f9:
; CHECK: pushq %rbp
; CHECK: .seh_pushreg 5
; CHECK-NEXT: movq %rsp, %rbp
; CHECK: .seh_setframe 5, 0
; CHECK: .seh_endprologue
%call = call i64 @llvm.x86.flags.read.u64()
; CHECK-NEXT: pushfq
; CHECK-NEXT: popq %rax
ret i64 %call
; CHECK-NEXT: popq %rbp
; CHECK-NEXT: retq
}
declare i64 @dummy()
define i64 @f10(i64* %foo, i64 %bar, i64 %baz) {
; CHECK-LABEL: f10:
; CHECK: pushq %rbp
; CHECK: .seh_pushreg 5
; CHECK: pushq %rsi
; CHECK: .seh_pushreg 6
; CHECK: pushq %rdi
; CHECK: .seh_pushreg 7
; CHECK: subq $32, %rsp
; CHECK: .seh_stackalloc 32
; CHECK: leaq 32(%rsp), %rbp
; CHECK: .seh_setframe 5, 32
; CHECK: .seh_endprologue
; ALL-LABEL: f10:
; ALL: # %bb.0:
; ALL-NEXT: pushq %rsi
; ALL-NEXT: .seh_pushreg 6
; ALL-NEXT: pushq %rbx
; ALL-NEXT: .seh_pushreg 3
; ALL-NEXT: subq $40, %rsp
; ALL-NEXT: .seh_stackalloc 40
; ALL-NEXT: .seh_endprologue
; ALL-NEXT: movq %rdx, %rsi
; ALL-NEXT: movq %rsi, %rax
; ALL-NEXT: lock cmpxchgq %r8, (%rcx)
; ALL-NEXT: sete %bl
; ALL-NEXT: callq dummy
; ALL-NEXT: testb %bl, %bl
; ALL-NEXT: cmoveq %rsi, %rax
; ALL-NEXT: addq $40, %rsp
; ALL-NEXT: popq %rbx
; ALL-NEXT: popq %rsi
; ALL-NEXT: retq
; ALL-NEXT: .seh_handlerdata
; ALL-NEXT: .text
; ALL-NEXT: .seh_endproc
%cx = cmpxchg i64* %foo, i64 %bar, i64 %baz seq_cst seq_cst
; PUSHF: lock cmpxchgq
; PUSHF-NEXT: pushfq
; PUSHF-NEXT: popq %[[REG:.*]]
; SAHF: lock cmpxchgq
; SAHF-NEXT: seto %al
; SAHF-NEXT: lahf
%v = extractvalue { i64, i1 } %cx, 0
%p = extractvalue { i64, i1 } %cx, 1
%call = call i64 @dummy()
; PUSHF: callq dummy
; PUSHF-NEXT: pushq %[[REG]]
; PUSHF-NEXT: popfq
; SAHF: callq dummy
; SAHF-NEXT: pushq
; SAHF: addb $127, %al
; SAHF-NEXT: sahf
; SAHF-NEXT: popq
%sel = select i1 %p, i64 %call, i64 %bar
; CHECK-NEXT: cmovneq
ret i64 %sel
; CHECK-NEXT: addq $32, %rsp
; CHECK-NEXT: popq %rdi
; CHECK-NEXT: popq %rsi
; CHECK-NEXT: popq %rbp
}
define i8* @f11() "no-frame-pointer-elim"="true" {
; CHECK-LABEL: f11:
; CHECK: pushq %rbp
; CHECK: movq %rsp, %rbp
; CHECK: .seh_setframe 5, 0
; CHECK: leaq 8(%rbp), %rax
; ALL-LABEL: f11:
; ALL: # %bb.0:
; ALL-NEXT: pushq %rbp
; ALL-NEXT: .seh_pushreg 5
; ALL-NEXT: movq %rsp, %rbp
; ALL-NEXT: .seh_setframe 5, 0
; ALL-NEXT: .seh_endprologue
; ALL-NEXT: leaq 8(%rbp), %rax
; ALL-NEXT: popq %rbp
; ALL-NEXT: retq
; ALL-NEXT: .seh_handlerdata
; ALL-NEXT: .text
; ALL-NEXT: .seh_endproc
%aora = call i8* @llvm.addressofreturnaddress()
ret i8* %aora
}
define i8* @f12() {
; CHECK-LABEL: f12:
; CHECK-NOT: push
; CHECK: movq %rsp, %rax
; ALL-LABEL: f12:
; ALL: # %bb.0:
; ALL-NEXT: movq %rsp, %rax
; ALL-NEXT: retq
%aora = call i8* @llvm.addressofreturnaddress()
ret i8* %aora
}
@@ -205,5 +286,4 @@ define i8* @f12() {
declare i8* @llvm.returnaddress(i32) nounwind readnone
declare i8* @llvm.addressofreturnaddress() nounwind readnone
declare i64 @llvm.x86.flags.read.u64()
declare void @llvm.va_start(i8*) nounwind

View File

@@ -1,4 +1,4 @@
; RUN: llc < %s | FileCheck %s
; RUN: llc -verify-machineinstrs < %s | FileCheck %s
target datalayout = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32"
target triple = "i686-pc-windows-msvc18.0.0"
@@ -39,15 +39,12 @@ declare void @g(%struct.T*)
; CHECK: leal 8(%esp), %esi
; CHECK: decl (%esp)
; CHECK: seto %al
; CHECK: lahf
; CHECK: movl %eax, %edi
; CHECK: setne %[[NE_REG:.*]]
; CHECK: pushl %esi
; CHECK: calll _g
; CHECK: addl $4, %esp
; CHECK: movl %edi, %eax
; CHECK: addb $127, %al
; CHECK: sahf
; CHECK: testb %[[NE_REG]], %[[NE_REG]]
; CHECK: jne
attributes #0 = { nounwind optsize }
attributes #1 = { argmemonly nounwind }