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 53 define i64 @one64_minsize() minsize { 54 entry: 55 ret i64 1 56 ; On 64-bit we don't do xor-inc yet, so push-pop it is. 57 ; CHECK64-LABEL: one64_minsize: 58 ; CHECK64: pushq $1 59 ; CHECK64: .cfi_adjust_cfa_offset 8 60 ; CHECK64: popq %rax 61 ; CHECK64: .cfi_adjust_cfa_offset -8 62 ; CHECK64-NEXT: retq 63 64 ; On Win64 we can't adjust the stack unless there's a frame pointer. 65 ; CHECKWIN64-LABEL: one64_minsize: 66 ; CHECKWIN64: movl $1, %eax 67 ; CHECKWIN64-NEXT: retq 68 } 69 70 define i32 @minus_one32() optsize { 71 entry: 72 ret i32 -1 73 74 ; CHECK32-LABEL: minus_one32: 75 ; CHECK32: xorl %eax, %eax 76 ; CHECK32-NEXT: decl %eax 77 ; CHECK32-NEXT: retl 78 } 79 80 define i32 @minus_one32_minsize() minsize { 81 entry: 82 ret i32 -1 83 84 ; xor-dec is preferred over push-pop. 85 ; CHECK32-LABEL: minus_one32_minsize: 86 ; CHECK32: xorl %eax, %eax 87 ; CHECK32-NEXT: decl %eax 88 ; CHECK32-NEXT: retl 89 } 90 91 define i16 @one16() optsize { 92 entry: 93 ret i16 1 94 95 ; CHECK32-LABEL: one16: 96 ; CHECK32: xorl %eax, %eax 97 ; CHECK32-NEXT: incl %eax 98 ; CHECK32-NEXT: retl 99 } 100 101 define i16 @minus_one16() optsize { 102 entry: 103 ret i16 -1 104 105 ; CHECK32-LABEL: minus_one16: 106 ; CHECK32: xorl %eax, %eax 107 ; CHECK32-NEXT: decl %eax 108 ; CHECK32-NEXT: retl 109 } 110 111 define i32 @minus_five32() minsize { 112 entry: 113 ret i32 -5 114 115 ; CHECK32-LABEL: minus_five32: 116 ; CHECK32: pushl $-5 117 ; CHECK32: popl %eax 118 ; CHECK32: retl 119 } 120 121 define i64 @minus_five64() minsize { 122 entry: 123 ret i64 -5 124 125 ; CHECK64-LABEL: minus_five64: 126 ; CHECK64: pushq $-5 127 ; CHECK64: .cfi_adjust_cfa_offset 8 128 ; CHECK64: popq %rax 129 ; CHECK64: .cfi_adjust_cfa_offset -8 130 ; CHECK64: retq 131 } 132 133 define i32 @rematerialize_minus_one() optsize { 134 entry: 135 ; Materialize -1 (thiscall forces it into %ecx). 136 tail call x86_thiscallcc void @f(i32 -1) 137 138 ; Clobber all registers except %esp, leaving nowhere to store the -1 besides 139 ; spilling it to the stack. 140 tail call void asm sideeffect "", "~{eax},~{ebx},~{ecx},~{edx},~{edi},~{esi},~{ebp},~{dirflag},~{fpsr},~{flags}"() 141 142 ; -1 should be re-materialized here instead of getting spilled above. 143 ret i32 -1 144 145 ; CHECK32-LABEL: rematerialize_minus_one 146 ; CHECK32: xorl %ecx, %ecx 147 ; CHECK32-NEXT: decl %ecx 148 ; CHECK32: calll 149 ; CHECK32: xorl %eax, %eax 150 ; CHECK32-NEXT: decl %eax 151 ; CHECK32-NOT: %eax 152 ; CHECK32: retl 153 } 154 155 define i32 @rematerialize_minus_one_eflags(i32 %x) optsize { 156 entry: 157 ; Materialize -1 (thiscall forces it into %ecx). 158 tail call x86_thiscallcc void @f(i32 -1) 159 160 ; Clobber all registers except %esp, leaving nowhere to store the -1 besides 161 ; spilling it to the stack. 162 tail call void asm sideeffect "", "~{eax},~{ebx},~{ecx},~{edx},~{edi},~{esi},~{ebp},~{dirflag},~{fpsr},~{flags}"() 163 164 ; Define eflags. 165 %a = icmp ne i32 %x, 123 166 %b = zext i1 %a to i32 167 ; Cause -1 to be rematerialized right in front of the cmov, which needs eflags. 168 ; It must therefore not use the xor-dec lowering. 169 %c = select i1 %a, i32 %b, i32 -1 170 ret i32 %c 171 172 ; CHECK32-LABEL: rematerialize_minus_one_eflags 173 ; CHECK32: xorl %ecx, %ecx 174 ; CHECK32-NEXT: decl %ecx 175 ; CHECK32: calll 176 ; CHECK32: cmpl 177 ; CHECK32: setne 178 ; CHECK32-NOT: xorl 179 ; CHECK32: movl $-1 180 ; CHECK32: cmov 181 ; CHECK32: retl 182 } 183 184 declare x86_thiscallcc void @f(i32) 185