| OLD | NEW |
| 1 ; Tests various aspects of x86 immediate encoding. Some encodings are shorter. | 1 ; Tests various aspects of x86 immediate encoding. Some encodings are shorter. |
| 2 ; For example, the encoding is shorter for 8-bit immediates or when using EAX. | 2 ; For example, the encoding is shorter for 8-bit immediates or when using EAX. |
| 3 ; This assumes that EAX is chosen as the first free register in O2 mode. | 3 ; This assumes that EAX is chosen as the first free register in O2 mode. |
| 4 | 4 |
| 5 ; RUN: %p2i -i %s --args -O2 --verbose none \ | 5 ; RUN: %p2i --assemble --disassemble -i %s --args -O2 --verbose none \ |
| 6 ; RUN: | llvm-mc -triple=i686-none-nacl -filetype=obj \ | 6 ; RUN: | FileCheck %s |
| 7 ; RUN: | llvm-objdump -d --symbolize -x86-asm-syntax=intel - | FileCheck %s | |
| 8 | 7 |
| 9 define internal i32 @testXor8Imm8(i32 %arg) { | 8 define internal i32 @testXor8Imm8(i32 %arg) { |
| 10 entry: | 9 entry: |
| 11 %arg_i8 = trunc i32 %arg to i8 | 10 %arg_i8 = trunc i32 %arg to i8 |
| 12 %result_i8 = xor i8 %arg_i8, 127 | 11 %result_i8 = xor i8 %arg_i8, 127 |
| 13 %result = zext i8 %result_i8 to i32 | 12 %result = zext i8 %result_i8 to i32 |
| 14 ret i32 %result | 13 ret i32 %result |
| 15 } | 14 } |
| 16 ; CHECK-LABEL: testXor8Imm8 | 15 ; CHECK-LABEL: testXor8Imm8 |
| 17 ; CHECK: 34 7f xor al, 127 | 16 ; CHECK: 34 7f xor al |
| 18 | 17 |
| 19 define internal i32 @testXor8Imm8Neg(i32 %arg) { | 18 define internal i32 @testXor8Imm8Neg(i32 %arg) { |
| 20 entry: | 19 entry: |
| 21 %arg_i8 = trunc i32 %arg to i8 | 20 %arg_i8 = trunc i32 %arg to i8 |
| 22 %result_i8 = xor i8 %arg_i8, -128 | 21 %result_i8 = xor i8 %arg_i8, -128 |
| 23 %result = zext i8 %result_i8 to i32 | 22 %result = zext i8 %result_i8 to i32 |
| 24 ret i32 %result | 23 ret i32 %result |
| 25 } | 24 } |
| 26 ; CHECK-LABEL: testXor8Imm8Neg | 25 ; CHECK-LABEL: testXor8Imm8Neg |
| 27 ; CHECK: 34 80 xor al, -128 | 26 ; CHECK: 34 80 xor al |
| 28 | 27 |
| 29 define internal i32 @testXor8Imm8NotEAX(i32 %arg, i32 %arg2, i32 %arg3) { | 28 define internal i32 @testXor8Imm8NotEAX(i32 %arg, i32 %arg2, i32 %arg3) { |
| 30 entry: | 29 entry: |
| 31 %arg_i8 = trunc i32 %arg to i8 | 30 %arg_i8 = trunc i32 %arg to i8 |
| 32 %arg2_i8 = trunc i32 %arg2 to i8 | 31 %arg2_i8 = trunc i32 %arg2 to i8 |
| 33 %arg3_i8 = trunc i32 %arg3 to i8 | 32 %arg3_i8 = trunc i32 %arg3 to i8 |
| 34 %x1 = xor i8 %arg_i8, 127 | 33 %x1 = xor i8 %arg_i8, 127 |
| 35 %x2 = xor i8 %arg2_i8, 127 | 34 %x2 = xor i8 %arg2_i8, 127 |
| 36 %x3 = xor i8 %arg3_i8, 127 | 35 %x3 = xor i8 %arg3_i8, 127 |
| 37 %x4 = add i8 %x1, %x2 | 36 %x4 = add i8 %x1, %x2 |
| 38 %x5 = add i8 %x4, %x3 | 37 %x5 = add i8 %x4, %x3 |
| 39 %result = zext i8 %x5 to i32 | 38 %result = zext i8 %x5 to i32 |
| 40 ret i32 %result | 39 ret i32 %result |
| 41 } | 40 } |
| 42 ; CHECK-LABEL: testXor8Imm8NotEAX | 41 ; CHECK-LABEL: testXor8Imm8NotEAX |
| 43 ; CHECK: 80 f{{[1-3]}} 7f xor {{[^a]}}l, 127 | 42 ; CHECK: 80 f{{[1-3]}} 7f xor {{[^a]}}l |
| 44 | 43 |
| 45 define internal i32 @testXor16Imm8(i32 %arg) { | 44 define internal i32 @testXor16Imm8(i32 %arg) { |
| 46 entry: | 45 entry: |
| 47 %arg_i16 = trunc i32 %arg to i16 | 46 %arg_i16 = trunc i32 %arg to i16 |
| 48 %result_i16 = xor i16 %arg_i16, 127 | 47 %result_i16 = xor i16 %arg_i16, 127 |
| 49 %result = zext i16 %result_i16 to i32 | 48 %result = zext i16 %result_i16 to i32 |
| 50 ret i32 %result | 49 ret i32 %result |
| 51 } | 50 } |
| 52 ; CHECK-LABEL: testXor16Imm8 | 51 ; CHECK-LABEL: testXor16Imm8 |
| 53 ; CHECK: 66 83 f0 7f xor ax, 127 | 52 ; CHECK: 66 83 f0 7f xor ax |
| 54 | 53 |
| 55 define internal i32 @testXor16Imm8Neg(i32 %arg) { | 54 define internal i32 @testXor16Imm8Neg(i32 %arg) { |
| 56 entry: | 55 entry: |
| 57 %arg_i16 = trunc i32 %arg to i16 | 56 %arg_i16 = trunc i32 %arg to i16 |
| 58 %result_i16 = xor i16 %arg_i16, -128 | 57 %result_i16 = xor i16 %arg_i16, -128 |
| 59 %result = zext i16 %result_i16 to i32 | 58 %result = zext i16 %result_i16 to i32 |
| 60 ret i32 %result | 59 ret i32 %result |
| 61 } | 60 } |
| 62 ; CHECK-LABEL: testXor16Imm8Neg | 61 ; CHECK-LABEL: testXor16Imm8Neg |
| 63 ; CHECK: 66 83 f0 80 xor ax, -128 | 62 ; CHECK: 66 83 f0 80 xor ax |
| 64 | 63 |
| 65 define internal i32 @testXor16Imm16Eax(i32 %arg) { | 64 define internal i32 @testXor16Imm16Eax(i32 %arg) { |
| 66 entry: | 65 entry: |
| 67 %arg_i16 = trunc i32 %arg to i16 | 66 %arg_i16 = trunc i32 %arg to i16 |
| 68 %tmp = xor i16 %arg_i16, 1024 | 67 %tmp = xor i16 %arg_i16, 1024 |
| 69 %result_i16 = add i16 %tmp, 1 | 68 %result_i16 = add i16 %tmp, 1 |
| 70 %result = zext i16 %result_i16 to i32 | 69 %result = zext i16 %result_i16 to i32 |
| 71 ret i32 %result | 70 ret i32 %result |
| 72 } | 71 } |
| 73 ; CHECK-LABEL: testXor16Imm16Eax | 72 ; CHECK-LABEL: testXor16Imm16Eax |
| 74 ; CHECK: 66 35 00 04 xor ax, 1024 | 73 ; CHECK: 66 35 00 04 xor ax |
| 75 ; CHECK-NEXT: add ax, 1 | 74 ; CHECK-NEXT: add ax,0x1 |
| 76 | 75 |
| 77 define internal i32 @testXor16Imm16NegEax(i32 %arg) { | 76 define internal i32 @testXor16Imm16NegEax(i32 %arg) { |
| 78 entry: | 77 entry: |
| 79 %arg_i16 = trunc i32 %arg to i16 | 78 %arg_i16 = trunc i32 %arg to i16 |
| 80 %tmp = xor i16 %arg_i16, -256 | 79 %tmp = xor i16 %arg_i16, -256 |
| 81 %result_i16 = add i16 %tmp, 1 | 80 %result_i16 = add i16 %tmp, 1 |
| 82 %result = zext i16 %result_i16 to i32 | 81 %result = zext i16 %result_i16 to i32 |
| 83 ret i32 %result | 82 ret i32 %result |
| 84 } | 83 } |
| 85 ; CHECK-LABEL: testXor16Imm16NegEax | 84 ; CHECK-LABEL: testXor16Imm16NegEax |
| 86 ; CHECK: 66 35 00 ff xor ax, 65280 | 85 ; CHECK: 66 35 00 ff xor ax |
| 87 ; CHECK-NEXT: add ax, 1 | 86 ; CHECK-NEXT: add ax,0x1 |
| 88 | 87 |
| 89 define internal i32 @testXor16Imm16NotEAX(i32 %arg_i32, i32 %arg2_i32, i32 %arg3
_i32) { | 88 define internal i32 @testXor16Imm16NotEAX(i32 %arg_i32, i32 %arg2_i32, i32 %arg3
_i32) { |
| 90 entry: | 89 entry: |
| 91 %arg = trunc i32 %arg_i32 to i16 | 90 %arg = trunc i32 %arg_i32 to i16 |
| 92 %arg2 = trunc i32 %arg2_i32 to i16 | 91 %arg2 = trunc i32 %arg2_i32 to i16 |
| 93 %arg3 = trunc i32 %arg3_i32 to i16 | 92 %arg3 = trunc i32 %arg3_i32 to i16 |
| 94 %x = xor i16 %arg, 32767 | 93 %x = xor i16 %arg, 32767 |
| 95 %x2 = xor i16 %arg2, 32767 | 94 %x2 = xor i16 %arg2, 32767 |
| 96 %x3 = xor i16 %arg3, 32767 | 95 %x3 = xor i16 %arg3, 32767 |
| 97 %add1 = add i16 %x, %x2 | 96 %add1 = add i16 %x, %x2 |
| 98 %add2 = add i16 %add1, %x3 | 97 %add2 = add i16 %add1, %x3 |
| 99 %result = zext i16 %add2 to i32 | 98 %result = zext i16 %add2 to i32 |
| 100 ret i32 %result | 99 ret i32 %result |
| 101 } | 100 } |
| 102 ; CHECK-LABEL: testXor16Imm16NotEAX | 101 ; CHECK-LABEL: testXor16Imm16NotEAX |
| 103 ; CHECK: 66 81 f{{[1-3]}} ff 7f xor {{[^a]}}x, 32767 | 102 ; CHECK: 66 81 f{{[1-3]}} ff 7f xor {{[^a]}}x |
| 104 ; CHECK-NEXT: 66 81 f{{[1-3]}} ff 7f xor {{[^a]}}x, 32767 | 103 ; CHECK-NEXT: 66 81 f{{[1-3]}} ff 7f xor {{[^a]}}x |
| 105 | 104 |
| 106 define internal i32 @testXor32Imm8(i32 %arg) { | 105 define internal i32 @testXor32Imm8(i32 %arg) { |
| 107 entry: | 106 entry: |
| 108 %result = xor i32 %arg, 127 | 107 %result = xor i32 %arg, 127 |
| 109 ret i32 %result | 108 ret i32 %result |
| 110 } | 109 } |
| 111 ; CHECK-LABEL: testXor32Imm8 | 110 ; CHECK-LABEL: testXor32Imm8 |
| 112 ; CHECK: 83 f0 7f xor eax, 127 | 111 ; CHECK: 83 f0 7f xor eax |
| 113 | 112 |
| 114 define internal i32 @testXor32Imm8Neg(i32 %arg) { | 113 define internal i32 @testXor32Imm8Neg(i32 %arg) { |
| 115 entry: | 114 entry: |
| 116 %result = xor i32 %arg, -128 | 115 %result = xor i32 %arg, -128 |
| 117 ret i32 %result | 116 ret i32 %result |
| 118 } | 117 } |
| 119 ; CHECK-LABEL: testXor32Imm8Neg | 118 ; CHECK-LABEL: testXor32Imm8Neg |
| 120 ; CHECK: 83 f0 80 xor eax, -128 | 119 ; CHECK: 83 f0 80 xor eax |
| 121 | 120 |
| 122 define internal i32 @testXor32Imm32Eax(i32 %arg) { | 121 define internal i32 @testXor32Imm32Eax(i32 %arg) { |
| 123 entry: | 122 entry: |
| 124 %result = xor i32 %arg, 16777216 | 123 %result = xor i32 %arg, 16777216 |
| 125 ret i32 %result | 124 ret i32 %result |
| 126 } | 125 } |
| 127 ; CHECK-LABEL: testXor32Imm32Eax | 126 ; CHECK-LABEL: testXor32Imm32Eax |
| 128 ; CHECK: 35 00 00 00 01 xor eax, 16777216 | 127 ; CHECK: 35 00 00 00 01 xor eax |
| 129 | 128 |
| 130 define internal i32 @testXor32Imm32NegEax(i32 %arg) { | 129 define internal i32 @testXor32Imm32NegEax(i32 %arg) { |
| 131 entry: | 130 entry: |
| 132 %result = xor i32 %arg, -256 | 131 %result = xor i32 %arg, -256 |
| 133 ret i32 %result | 132 ret i32 %result |
| 134 } | 133 } |
| 135 ; CHECK-LABEL: testXor32Imm32NegEax | 134 ; CHECK-LABEL: testXor32Imm32NegEax |
| 136 ; CHECK: 35 00 ff ff ff xor eax, 4294967040 | 135 ; CHECK: 35 00 ff ff ff xor eax |
| 137 | 136 |
| 138 define internal i32 @testXor32Imm32NotEAX(i32 %arg, i32 %arg2, i32 %arg3) { | 137 define internal i32 @testXor32Imm32NotEAX(i32 %arg, i32 %arg2, i32 %arg3) { |
| 139 entry: | 138 entry: |
| 140 %x = xor i32 %arg, 32767 | 139 %x = xor i32 %arg, 32767 |
| 141 %x2 = xor i32 %arg2, 32767 | 140 %x2 = xor i32 %arg2, 32767 |
| 142 %x3 = xor i32 %arg3, 32767 | 141 %x3 = xor i32 %arg3, 32767 |
| 143 %add1 = add i32 %x, %x2 | 142 %add1 = add i32 %x, %x2 |
| 144 %add2 = add i32 %add1, %x3 | 143 %add2 = add i32 %add1, %x3 |
| 145 ret i32 %add2 | 144 ret i32 %add2 |
| 146 } | 145 } |
| 147 ; CHECK-LABEL: testXor32Imm32NotEAX | 146 ; CHECK-LABEL: testXor32Imm32NotEAX |
| 148 ; CHECK: 81 f{{[1-3]}} ff 7f 00 00 xor e{{[^a]}}x, 32767 | 147 ; CHECK: 81 f{{[1-3]}} ff 7f 00 00 xor e{{[^a]}}x, |
| 149 | 148 |
| 150 ; Should be similar for add, sub, etc., so sample a few. | 149 ; Should be similar for add, sub, etc., so sample a few. |
| 151 | 150 |
| 152 define internal i32 @testAdd8Imm8(i32 %arg) { | 151 define internal i32 @testAdd8Imm8(i32 %arg) { |
| 153 entry: | 152 entry: |
| 154 %arg_i8 = trunc i32 %arg to i8 | 153 %arg_i8 = trunc i32 %arg to i8 |
| 155 %result_i8 = add i8 %arg_i8, 126 | 154 %result_i8 = add i8 %arg_i8, 126 |
| 156 %result = zext i8 %result_i8 to i32 | 155 %result = zext i8 %result_i8 to i32 |
| 157 ret i32 %result | 156 ret i32 %result |
| 158 } | 157 } |
| 159 ; CHECK-LABEL: testAdd8Imm8 | 158 ; CHECK-LABEL: testAdd8Imm8 |
| 160 ; CHECK: 04 7e add al, 126 | 159 ; CHECK: 04 7e add al |
| 161 | 160 |
| 162 define internal i32 @testSub8Imm8(i32 %arg) { | 161 define internal i32 @testSub8Imm8(i32 %arg) { |
| 163 entry: | 162 entry: |
| 164 %arg_i8 = trunc i32 %arg to i8 | 163 %arg_i8 = trunc i32 %arg to i8 |
| 165 %result_i8 = sub i8 %arg_i8, 125 | 164 %result_i8 = sub i8 %arg_i8, 125 |
| 166 %result = zext i8 %result_i8 to i32 | 165 %result = zext i8 %result_i8 to i32 |
| 167 ret i32 %result | 166 ret i32 %result |
| 168 } | 167 } |
| 169 ; CHECK-LABEL: testSub8Imm8 | 168 ; CHECK-LABEL: testSub8Imm8 |
| 170 ; CHECK: 2c 7d sub al, 125 | 169 ; CHECK: 2c 7d sub al |
| 171 | 170 |
| 172 ; imul has some shorter 8-bit immediate encodings. | 171 ; imul has some shorter 8-bit immediate encodings. |
| 173 ; It also has a shorter encoding for eax, but we don't do that yet. | 172 ; It also has a shorter encoding for eax, but we don't do that yet. |
| 174 | 173 |
| 175 define internal i32 @testMul16Imm8(i32 %arg) { | 174 define internal i32 @testMul16Imm8(i32 %arg) { |
| 176 entry: | 175 entry: |
| 177 %arg_i16 = trunc i32 %arg to i16 | 176 %arg_i16 = trunc i32 %arg to i16 |
| 178 %tmp = mul i16 %arg_i16, 99 | 177 %tmp = mul i16 %arg_i16, 99 |
| 179 %result_i16 = add i16 %tmp, 1 | 178 %result_i16 = add i16 %tmp, 1 |
| 180 %result = zext i16 %result_i16 to i32 | 179 %result = zext i16 %result_i16 to i32 |
| 181 ret i32 %result | 180 ret i32 %result |
| 182 } | 181 } |
| 183 ; CHECK-LABEL: testMul16Imm8 | 182 ; CHECK-LABEL: testMul16Imm8 |
| 184 ; CHECK: 66 6b c0 63 imul ax, ax, 99 | 183 ; CHECK: 66 6b c0 63 imul ax,ax |
| 185 ; CHECK-NEXT: add ax, 1 | 184 ; CHECK-NEXT: add ax,0x1 |
| 186 | 185 |
| 187 define internal i32 @testMul16Imm8Neg(i32 %arg) { | 186 define internal i32 @testMul16Imm8Neg(i32 %arg) { |
| 188 entry: | 187 entry: |
| 189 %arg_i16 = trunc i32 %arg to i16 | 188 %arg_i16 = trunc i32 %arg to i16 |
| 190 %tmp = mul i16 %arg_i16, -111 | 189 %tmp = mul i16 %arg_i16, -111 |
| 191 %result_i16 = add i16 %tmp, 1 | 190 %result_i16 = add i16 %tmp, 1 |
| 192 %result = zext i16 %result_i16 to i32 | 191 %result = zext i16 %result_i16 to i32 |
| 193 ret i32 %result | 192 ret i32 %result |
| 194 } | 193 } |
| 195 ; CHECK-LABEL: testMul16Imm8Neg | 194 ; CHECK-LABEL: testMul16Imm8Neg |
| 196 ; CHECK: 66 6b c0 91 imul ax, ax, -111 | 195 ; CHECK: 66 6b c0 91 imul ax,ax |
| 197 ; CHECK-NEXT: add ax, 1 | 196 ; CHECK-NEXT: add ax,0x1 |
| 198 | 197 |
| 199 define internal i32 @testMul16Imm16(i32 %arg) { | 198 define internal i32 @testMul16Imm16(i32 %arg) { |
| 200 entry: | 199 entry: |
| 201 %arg_i16 = trunc i32 %arg to i16 | 200 %arg_i16 = trunc i32 %arg to i16 |
| 202 %tmp = mul i16 %arg_i16, 1024 | 201 %tmp = mul i16 %arg_i16, 1024 |
| 203 %result_i16 = add i16 %tmp, 1 | 202 %result_i16 = add i16 %tmp, 1 |
| 204 %result = zext i16 %result_i16 to i32 | 203 %result = zext i16 %result_i16 to i32 |
| 205 ret i32 %result | 204 ret i32 %result |
| 206 } | 205 } |
| 207 ; CHECK-LABEL: testMul16Imm16 | 206 ; CHECK-LABEL: testMul16Imm16 |
| 208 ; CHECK: 66 69 c0 00 04 imul ax, ax, 1024 | 207 ; CHECK: 66 69 c0 00 04 imul ax,ax |
| 209 ; CHECK-NEXT: add ax, 1 | 208 ; CHECK-NEXT: add ax,0x1 |
| 210 | 209 |
| 211 define internal i32 @testMul16Imm16Neg(i32 %arg) { | 210 define internal i32 @testMul16Imm16Neg(i32 %arg) { |
| 212 entry: | 211 entry: |
| 213 %arg_i16 = trunc i32 %arg to i16 | 212 %arg_i16 = trunc i32 %arg to i16 |
| 214 %tmp = mul i16 %arg_i16, -256 | 213 %tmp = mul i16 %arg_i16, -256 |
| 215 %result_i16 = add i16 %tmp, 1 | 214 %result_i16 = add i16 %tmp, 1 |
| 216 %result = zext i16 %result_i16 to i32 | 215 %result = zext i16 %result_i16 to i32 |
| 217 ret i32 %result | 216 ret i32 %result |
| 218 } | 217 } |
| 219 ; CHECK-LABEL: testMul16Imm16Neg | 218 ; CHECK-LABEL: testMul16Imm16Neg |
| 220 ; CHECK: 66 69 c0 00 ff imul ax, ax, 65280 | 219 ; CHECK: 66 69 c0 00 ff imul ax,ax |
| 221 ; CHECK-NEXT: add ax, 1 | 220 ; CHECK-NEXT: add ax,0x1 |
| 222 | 221 |
| 223 define internal i32 @testMul32Imm8(i32 %arg) { | 222 define internal i32 @testMul32Imm8(i32 %arg) { |
| 224 entry: | 223 entry: |
| 225 %result = mul i32 %arg, 99 | 224 %result = mul i32 %arg, 99 |
| 226 ret i32 %result | 225 ret i32 %result |
| 227 } | 226 } |
| 228 ; CHECK-LABEL: testMul32Imm8 | 227 ; CHECK-LABEL: testMul32Imm8 |
| 229 ; CHECK: 6b c0 63 imul eax, eax, 99 | 228 ; CHECK: 6b c0 63 imul eax,eax |
| 230 | 229 |
| 231 define internal i32 @testMul32Imm8Neg(i32 %arg) { | 230 define internal i32 @testMul32Imm8Neg(i32 %arg) { |
| 232 entry: | 231 entry: |
| 233 %result = mul i32 %arg, -111 | 232 %result = mul i32 %arg, -111 |
| 234 ret i32 %result | 233 ret i32 %result |
| 235 } | 234 } |
| 236 ; CHECK-LABEL: testMul32Imm8Neg | 235 ; CHECK-LABEL: testMul32Imm8Neg |
| 237 ; CHECK: 6b c0 91 imul eax, eax, -111 | 236 ; CHECK: 6b c0 91 imul eax,eax |
| 238 | 237 |
| 239 define internal i32 @testMul32Imm16(i32 %arg) { | 238 define internal i32 @testMul32Imm16(i32 %arg) { |
| 240 entry: | 239 entry: |
| 241 %result = mul i32 %arg, 1024 | 240 %result = mul i32 %arg, 1024 |
| 242 ret i32 %result | 241 ret i32 %result |
| 243 } | 242 } |
| 244 ; CHECK-LABEL: testMul32Imm16 | 243 ; CHECK-LABEL: testMul32Imm16 |
| 245 ; CHECK: 69 c0 00 04 00 00 imul eax, eax, 1024 | 244 ; CHECK: 69 c0 00 04 00 00 imul eax,eax |
| 246 | 245 |
| 247 define internal i32 @testMul32Imm16Neg(i32 %arg) { | 246 define internal i32 @testMul32Imm16Neg(i32 %arg) { |
| 248 entry: | 247 entry: |
| 249 %result = mul i32 %arg, -256 | 248 %result = mul i32 %arg, -256 |
| 250 ret i32 %result | 249 ret i32 %result |
| 251 } | 250 } |
| 252 ; CHECK-LABEL: testMul32Imm16Neg | 251 ; CHECK-LABEL: testMul32Imm16Neg |
| 253 ; CHECK: 69 c0 00 ff ff ff imul eax, eax, 4294967040 | 252 ; CHECK: 69 c0 00 ff ff ff imul eax,eax |
| 254 | 253 |
| 255 ; The GPR shift instructions either allow an 8-bit immediate or | 254 ; The GPR shift instructions either allow an 8-bit immediate or |
| 256 ; have a special encoding for "1". | 255 ; have a special encoding for "1". |
| 257 define internal i32 @testShl16Imm8(i32 %arg) { | 256 define internal i32 @testShl16Imm8(i32 %arg) { |
| 258 entry: | 257 entry: |
| 259 %arg_i16 = trunc i32 %arg to i16 | 258 %arg_i16 = trunc i32 %arg to i16 |
| 260 %tmp = shl i16 %arg_i16, 13 | 259 %tmp = shl i16 %arg_i16, 13 |
| 261 %result = zext i16 %tmp to i32 | 260 %result = zext i16 %tmp to i32 |
| 262 ret i32 %result | 261 ret i32 %result |
| 263 } | 262 } |
| 264 ; CHECK-LABEL: testShl16Imm8 | 263 ; CHECK-LABEL: testShl16Imm8 |
| 265 ; CHECK: 66 c1 e0 0d shl ax, 13 | 264 ; CHECK: 66 c1 e0 0d shl ax,0xd |
| 266 | 265 |
| 267 define internal i32 @testShl16Imm1(i32 %arg) { | 266 define internal i32 @testShl16Imm1(i32 %arg) { |
| 268 entry: | 267 entry: |
| 269 %arg_i16 = trunc i32 %arg to i16 | 268 %arg_i16 = trunc i32 %arg to i16 |
| 270 %tmp = shl i16 %arg_i16, 1 | 269 %tmp = shl i16 %arg_i16, 1 |
| 271 %result = zext i16 %tmp to i32 | 270 %result = zext i16 %tmp to i32 |
| 272 ret i32 %result | 271 ret i32 %result |
| 273 } | 272 } |
| 274 ; CHECK-LABEL: testShl16Imm1 | 273 ; CHECK-LABEL: testShl16Imm1 |
| 275 ; CHECK: 66 d1 e0 shl ax | 274 ; CHECK: 66 d1 e0 shl ax |
| 276 | 275 |
| 277 ; Currently the "test" instruction is used for 64-bit shifts, and | 276 ; Currently the "test" instruction is used for 64-bit shifts, and |
| 278 ; for ctlz 64-bit, so we use those to test the "test" instruction. | 277 ; for ctlz 64-bit, so we use those to test the "test" instruction. |
| 279 ; One optimization for "test": the "test" instruction is essentially a | 278 ; One optimization for "test": the "test" instruction is essentially a |
| 280 ; bitwise AND that doesn't modify the two source operands, so for immediates | 279 ; bitwise AND that doesn't modify the two source operands, so for immediates |
| 281 ; under 8-bits and registers with 8-bit variants we can use the shorter form. | 280 ; under 8-bits and registers with 8-bit variants we can use the shorter form. |
| 282 | 281 |
| 283 define internal i64 @test_via_shl64Bit(i64 %a, i64 %b) { | 282 define internal i64 @test_via_shl64Bit(i64 %a, i64 %b) { |
| 284 entry: | 283 entry: |
| 285 %shl = shl i64 %a, %b | 284 %shl = shl i64 %a, %b |
| 286 ret i64 %shl | 285 ret i64 %shl |
| 287 } | 286 } |
| 288 ; CHECK-LABEL: test_via_shl64Bit | 287 ; CHECK-LABEL: test_via_shl64Bit |
| 289 ; CHECK: 0f a5 c2 shld edx, eax, cl | 288 ; CHECK: 0f a5 c2 shld edx,eax,cl |
| 290 ; CHECK: d3 e0 shl eax, cl | 289 ; CHECK: d3 e0 shl eax,cl |
| 291 ; CHECK: f6 c1 20 test cl, 32 | 290 ; CHECK: f6 c1 20 test cl,0x20 |
| 292 | 291 |
| 293 ; Test a few register encodings of "test". | 292 ; Test a few register encodings of "test". |
| 294 declare i64 @llvm.ctlz.i64(i64, i1) | 293 declare i64 @llvm.ctlz.i64(i64, i1) |
| 295 | 294 |
| 296 define i64 @test_via_ctlz_64(i64 %x, i64 %y, i64 %z, i64 %w) { | 295 define i64 @test_via_ctlz_64(i64 %x, i64 %y, i64 %z, i64 %w) { |
| 297 entry: | 296 entry: |
| 298 %r = call i64 @llvm.ctlz.i64(i64 %x, i1 false) | 297 %r = call i64 @llvm.ctlz.i64(i64 %x, i1 false) |
| 299 %r2 = call i64 @llvm.ctlz.i64(i64 %y, i1 false) | 298 %r2 = call i64 @llvm.ctlz.i64(i64 %y, i1 false) |
| 300 %r3 = call i64 @llvm.ctlz.i64(i64 %z, i1 false) | 299 %r3 = call i64 @llvm.ctlz.i64(i64 %z, i1 false) |
| 301 %r4 = call i64 @llvm.ctlz.i64(i64 %w, i1 false) | 300 %r4 = call i64 @llvm.ctlz.i64(i64 %w, i1 false) |
| 302 %res1 = add i64 %r, %r2 | 301 %res1 = add i64 %r, %r2 |
| 303 %res2 = add i64 %r3, %r4 | 302 %res2 = add i64 %r3, %r4 |
| 304 %res = add i64 %res1, %res2 | 303 %res = add i64 %res1, %res2 |
| 305 ret i64 %res | 304 ret i64 %res |
| 306 } | 305 } |
| 307 ; CHECK-LABEL: test_via_ctlz_64 | 306 ; CHECK-LABEL: test_via_ctlz_64 |
| 308 ; CHECK-DAG: 85 c0 test eax, eax | 307 ; CHECK-DAG: 85 c0 test eax,eax |
| 309 ; CHECK-DAG: 85 db test ebx, ebx | 308 ; CHECK-DAG: 85 db test ebx,ebx |
| 310 ; CHECK-DAG: 85 f6 test esi, esi | 309 ; CHECK-DAG: 85 f6 test esi,esi |
| OLD | NEW |