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