Commit 74d8a849 authored by Chandler Carruth's avatar Chandler Carruth
Browse files

Merge a series of test updates r329055-329057.

These required skipping the updates to the update test scripts. Note that to
regenerate these tests you'll need to use the test update script close to trunk
rather than on the branch. =/

llvm-svn: 332902
parent 8879eba9
Loading
Loading
Loading
Loading
+212 −25
Original line number Diff line number Diff line
; 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,75 @@ 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:    movb %cl, %al
; X32-NEXT:    incb %al
; X32-NEXT:    movb %al, b
; X32-NEXT:    incl c
; X32-NEXT:    pushl %eax
; X32-NEXT:    seto %al
; X32-NEXT:    lahf
; X32-NEXT:    movl %eax, %edx
; X32-NEXT:    popl %eax
; 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:    pushl %eax
; X32-NEXT:    movl %edx, %eax
; X32-NEXT:    addb $127, %al
; X32-NEXT:    sahf
; X32-NEXT:    popl %eax
; X32-NEXT:    je .LBB0_2
; X32-NEXT:  # %bb.1: # %if.then
; X32-NEXT:    pushl %ebp
; X32-NEXT:    movl %esp, %ebp
; X32-NEXT:    movsbl %al, %eax
; X32-NEXT:    pushl %eax
; X32-NEXT:    calll external
; X32-NEXT:    addl $4, %esp
; X32-NEXT:    popl %ebp
; 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:    pushfq
; X64-NEXT:    popq %rsi
; 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:    pushq %rsi
; X64-NEXT:    popfq
; X64-NEXT:    je .LBB0_2
; X64-NEXT:  # %bb.1: # %if.then
; X64-NEXT:    pushq %rbp
; X64-NEXT:    movq %rsp, %rbp
; X64-NEXT:    movsbl %al, %edi
; X64-NEXT:    callq external
; X64-NEXT:    popq %rbp
; 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 +89,156 @@ 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 %ebp
; X32-NEXT:    movl %esp, %ebp
; X32-NEXT:    pushl %esi
; X32-NEXT:    movl 8(%ebp), %eax
; X32-NEXT:    incl (%eax)
; X32-NEXT:    seto %al
; X32-NEXT:    lahf
; X32-NEXT:    movl %eax, %esi
; X32-NEXT:    pushl $42
; X32-NEXT:    calll external
; X32-NEXT:    addl $4, %esp
; X32-NEXT:    movl %esi, %eax
; X32-NEXT:    addb $127, %al
; X32-NEXT:    sahf
; X32-NEXT:    je .LBB1_1
; X32-NEXT:  # %bb.3: # %else
; X32-NEXT:    xorl %eax, %eax
; X32-NEXT:    jmp .LBB1_2
; X32-NEXT:  .LBB1_1: # %then
; X32-NEXT:    movl $64, %eax
; X32-NEXT:  .LBB1_2: # %then
; X32-NEXT:    popl %esi
; X32-NEXT:    popl %ebp
; X32-NEXT:    retl
;
; X64-LABEL: test2:
; X64:       # %bb.0: # %entry
; X64-NEXT:    pushq %rbp
; X64-NEXT:    movq %rsp, %rbp
; X64-NEXT:    pushq %rbx
; X64-NEXT:    pushq %rax
; X64-NEXT:    incl (%rdi)
; X64-NEXT:    pushfq
; X64-NEXT:    popq %rbx
; X64-NEXT:    movl $42, %edi
; X64-NEXT:    callq external
; X64-NEXT:    pushq %rbx
; X64-NEXT:    popfq
; X64-NEXT:    je .LBB1_1
; X64-NEXT:  # %bb.3: # %else
; X64-NEXT:    xorl %eax, %eax
; X64-NEXT:    jmp .LBB1_2
; X64-NEXT:  .LBB1_1: # %then
; X64-NEXT:    movl $64, %eax
; X64-NEXT:  .LBB1_2: # %then
; X64-NEXT:    addq $8, %rsp
; X64-NEXT:    popq %rbx
; X64-NEXT:    popq %rbp
; 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:    pushl %ebp
; X32-NEXT:    movl %esp, %ebp
; X32-NEXT:    movl 8(%ebp), %eax
; X32-NEXT:    incl (%eax)
; X32-NEXT:    seto %al
; X32-NEXT:    lahf
; X32-NEXT:    movl %eax, %eax
; X32-NEXT:    incb a
; X32-NEXT:    sete d
; X32-NEXT:    movl %eax, %eax
; X32-NEXT:    addb $127, %al
; X32-NEXT:    sahf
; X32-NEXT:    je .LBB2_1
; X32-NEXT:  # %bb.2: # %else
; X32-NEXT:    popl %ebp
; X32-NEXT:    jmp external_b # TAILCALL
; X32-NEXT:  .LBB2_1: # %then
; X32-NEXT:    popl %ebp
; X32-NEXT:    jmp external_a # TAILCALL
;
; X64-LABEL: test_tail_call:
; X64:       # %bb.0: # %entry
; X64-NEXT:    pushq %rbp
; X64-NEXT:    movq %rsp, %rbp
; X64-NEXT:    incl (%rdi)
; X64-NEXT:    pushfq
; X64-NEXT:    popq %rax
; X64-NEXT:    incb {{.*}}(%rip)
; X64-NEXT:    sete {{.*}}(%rip)
; X64-NEXT:    pushq %rax
; X64-NEXT:    popfq
; X64-NEXT:    je .LBB2_1
; X64-NEXT:  # %bb.2: # %else
; X64-NEXT:    popq %rbp
; X64-NEXT:    jmp external_b # TAILCALL
; X64-NEXT:  .LBB2_1: # %then
; X64-NEXT:    popq %rbp
; 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
}
+3904 −3904

File changed.

Preview size limit exceeded, changes collapsed.