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 |