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 5define i32 @one32_nooptsize() { 6entry: 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 18define i32 @one32() optsize { 19entry: 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 33define i32 @one32_minsize() minsize { 34entry: 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 58define i32 @pr26023() minsize { 59entry: 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 83define i64 @one64_minsize() minsize { 84entry: 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 100define i32 @minus_one32() optsize { 101entry: 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 110define i32 @minus_one32_minsize() minsize { 111entry: 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 121define i16 @one16() optsize { 122entry: 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 132define i16 @minus_one16() optsize { 133entry: 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 143define i32 @minus_five32() minsize { 144entry: 145 ret i32 -5 146 147; CHECK32-LABEL: minus_five32: 148; CHECK32: pushl $-5 149; CHECK32: popl %eax 150; CHECK32: retl 151} 152 153define i64 @minus_five64() minsize { 154entry: 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 165define i32 @rematerialize_minus_one() optsize { 166entry: 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 187define i32 @rematerialize_minus_one_eflags(i32 %x) optsize { 188entry: 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 216declare x86_thiscallcc void @f(i32) 217