Home | History | Annotate | Download | only in X86
      1 ; RUN: llc -mtriple=i686-unknown-linux-gnu -mattr=+cmov %s -o - | FileCheck %s --check-prefix=CHECK32
      2 ; RUN: llc -mtriple=x86_64-unknown-linux-gnu -mattr=+cmov %s -o - | FileCheck %s --check-prefix=CHECK64
      3 ; RUN: llc -mtriple=x86_64-pc-win32 -mattr=+cmov %s -o - | FileCheck %s --check-prefix=CHECKWIN64
      4 
      5 define i32 @one32_nooptsize() {
      6 entry:
      7   ret i32 1
      8 
      9 ; When not optimizing for size, use mov.
     10 ; CHECK32-LABEL: one32_nooptsize:
     11 ; CHECK32:       movl $1, %eax
     12 ; CHECK32-NEXT:  retl
     13 ; CHECK64-LABEL: one32_nooptsize:
     14 ; CHECK64:       movl $1, %eax
     15 ; CHECK64-NEXT:  retq
     16 }
     17 
     18 define i32 @one32() optsize {
     19 entry:
     20   ret i32 1
     21 
     22 ; CHECK32-LABEL: one32:
     23 ; CHECK32:       xorl %eax, %eax
     24 ; CHECK32-NEXT:  incl %eax
     25 ; CHECK32-NEXT:  retl
     26 
     27 ; FIXME: Figure out the best approach in 64-bit mode.
     28 ; CHECK64-LABEL: one32:
     29 ; CHECK64:       movl $1, %eax
     30 ; CHECK64-NEXT:  retq
     31 }
     32 
     33 define i32 @one32_minsize() minsize {
     34 entry:
     35   ret i32 1
     36 
     37 ; On 32-bit, xor-inc is preferred over push-pop.
     38 ; CHECK32-LABEL: one32_minsize:
     39 ; CHECK32:       xorl %eax, %eax
     40 ; CHECK32-NEXT:  incl %eax
     41 ; CHECK32-NEXT:  retl
     42 
     43 ; On 64-bit we don't do xor-inc yet, so push-pop it is. Note that we have to
     44 ; pop into a 64-bit register even when we just need 32 bits.
     45 ; CHECK64-LABEL: one32_minsize:
     46 ; CHECK64:       pushq $1
     47 ; CHECK64:       .cfi_adjust_cfa_offset 8
     48 ; CHECK64:       popq %rax
     49 ; CHECK64:       .cfi_adjust_cfa_offset -8
     50 ; CHECK64-NEXT:  retq
     51 
     52 ; On Win64 we can't adjust the stack unless there's a frame pointer.
     53 ; CHECKWIN64-LABEL: one32_minsize:
     54 ; CHECKWIN64:       movl $1, %eax
     55 ; CHECKWIN64-NEXT:  retq
     56 }
     57 
     58 define i32 @pr26023() minsize {
     59 entry:
     60   %x = alloca [120 x i8]
     61   %0 = getelementptr inbounds [120 x i8], [120 x i8]* %x, i64 0, i64 0
     62   call void asm sideeffect "", "imr,~{memory},~{dirflag},~{fpsr},~{flags}"(i8* %0)
     63   %arrayidx = getelementptr inbounds [120 x i8], [120 x i8]* %x, i64 0, i64 119
     64   store volatile i8 -2, i8* %arrayidx
     65   call void asm sideeffect "", "r,~{dirflag},~{fpsr},~{flags}"(i32 5)
     66   %1 = load volatile i8, i8* %arrayidx
     67   %conv = sext i8 %1 to i32
     68   ret i32 %conv
     69 
     70 ; The function writes to the redzone, so push/pop cannot be used.
     71 ; CHECK64-LABEL: pr26023:
     72 ; CHECK64:       movl $5, %ecx
     73 ; CHECK64:       retq
     74 
     75 ; 32-bit X86 doesn't have a redzone.
     76 ; CHECK32-LABEL: pr26023:
     77 ; CHECK32:       pushl $5
     78 ; CHECK32:       popl %ecx
     79 ; CHECK32:       retl
     80 }
     81 
     82 
     83 define i64 @one64_minsize() minsize {
     84 entry:
     85   ret i64 1
     86 ; On 64-bit we don't do xor-inc yet, so push-pop it is.
     87 ; CHECK64-LABEL: one64_minsize:
     88 ; CHECK64:       pushq $1
     89 ; CHECK64:       .cfi_adjust_cfa_offset 8
     90 ; CHECK64:       popq %rax
     91 ; CHECK64:       .cfi_adjust_cfa_offset -8
     92 ; CHECK64-NEXT:  retq
     93 
     94 ; On Win64 we can't adjust the stack unless there's a frame pointer.
     95 ; CHECKWIN64-LABEL: one64_minsize:
     96 ; CHECKWIN64:       movl $1, %eax
     97 ; CHECKWIN64-NEXT:  retq
     98 }
     99 
    100 define i32 @minus_one32() optsize {
    101 entry:
    102   ret i32 -1
    103 
    104 ; CHECK32-LABEL: minus_one32:
    105 ; CHECK32:       xorl %eax, %eax
    106 ; CHECK32-NEXT:  decl %eax
    107 ; CHECK32-NEXT:  retl
    108 }
    109 
    110 define i32 @minus_one32_minsize() minsize {
    111 entry:
    112   ret i32 -1
    113 
    114 ; xor-dec is preferred over push-pop.
    115 ; CHECK32-LABEL: minus_one32_minsize:
    116 ; CHECK32:       xorl %eax, %eax
    117 ; CHECK32-NEXT:  decl %eax
    118 ; CHECK32-NEXT:  retl
    119 }
    120 
    121 define i16 @one16() optsize {
    122 entry:
    123   ret i16 1
    124 
    125 ; CHECK32-LABEL: one16:
    126 ; CHECK32:       xorl %eax, %eax
    127 ; CHECK32-NEXT:  incl %eax
    128 ; CHECK32-NEXT:  # kill
    129 ; CHECK32-NEXT:  retl
    130 }
    131 
    132 define i16 @minus_one16() optsize {
    133 entry:
    134   ret i16 -1
    135 
    136 ; CHECK32-LABEL: minus_one16:
    137 ; CHECK32:       xorl %eax, %eax
    138 ; CHECK32-NEXT:  decl %eax
    139 ; CHECK32-NEXT:  # kill
    140 ; CHECK32-NEXT:  retl
    141 }
    142 
    143 define i32 @minus_five32() minsize {
    144 entry:
    145   ret i32 -5
    146 
    147 ; CHECK32-LABEL: minus_five32:
    148 ; CHECK32: pushl $-5
    149 ; CHECK32: popl %eax
    150 ; CHECK32: retl
    151 }
    152 
    153 define i64 @minus_five64() minsize {
    154 entry:
    155   ret i64 -5
    156 
    157 ; CHECK64-LABEL: minus_five64:
    158 ; CHECK64: pushq $-5
    159 ; CHECK64:       .cfi_adjust_cfa_offset 8
    160 ; CHECK64: popq %rax
    161 ; CHECK64:       .cfi_adjust_cfa_offset -8
    162 ; CHECK64: retq
    163 }
    164 
    165 define i32 @rematerialize_minus_one() optsize {
    166 entry:
    167   ; Materialize -1 (thiscall forces it into %ecx).
    168   tail call x86_thiscallcc void @f(i32 -1)
    169 
    170   ; Clobber all registers except %esp, leaving nowhere to store the -1 besides
    171   ; spilling it to the stack.
    172   tail call void asm sideeffect "", "~{eax},~{ebx},~{ecx},~{edx},~{edi},~{esi},~{ebp},~{dirflag},~{fpsr},~{flags}"()
    173 
    174   ; -1 should be re-materialized here instead of getting spilled above.
    175   ret i32 -1
    176 
    177 ; CHECK32-LABEL: rematerialize_minus_one
    178 ; CHECK32:       xorl %ecx, %ecx
    179 ; CHECK32-NEXT:  decl %ecx
    180 ; CHECK32:       calll
    181 ; CHECK32:       xorl %eax, %eax
    182 ; CHECK32-NEXT:  decl %eax
    183 ; CHECK32-NOT:   %eax
    184 ; CHECK32:       retl
    185 }
    186 
    187 define i32 @rematerialize_minus_one_eflags(i32 %x) optsize {
    188 entry:
    189   ; Materialize -1 (thiscall forces it into %ecx).
    190   tail call x86_thiscallcc void @f(i32 -1)
    191 
    192   ; Clobber all registers except %esp, leaving nowhere to store the -1 besides
    193   ; spilling it to the stack.
    194   tail call void asm sideeffect "", "~{eax},~{ebx},~{ecx},~{edx},~{edi},~{esi},~{ebp},~{dirflag},~{fpsr},~{flags}"()
    195 
    196   ; Define eflags.
    197   %a = icmp ne i32 %x, 123
    198   %b = zext i1 %a to i32
    199   ; Cause -1 to be rematerialized right in front of the cmov, which needs eflags.
    200   ; It must therefore not use the xor-dec lowering.
    201   %c = select i1 %a, i32 %b, i32 -1
    202   ret i32 %c
    203 
    204 ; CHECK32-LABEL: rematerialize_minus_one_eflags
    205 ; CHECK32:       xorl %ecx, %ecx
    206 ; CHECK32-NEXT:  decl %ecx
    207 ; CHECK32:       calll
    208 ; CHECK32:       cmpl
    209 ; CHECK32:       setne
    210 ; CHECK32-NOT:   xorl
    211 ; CHECK32:       movl $-1
    212 ; CHECK32:       cmov
    213 ; CHECK32:       retl
    214 }
    215 
    216 declare x86_thiscallcc void @f(i32)
    217