OLD | NEW |
1 ; Tests various aspects of i1 related lowering. | 1 ; Tests various aspects of i1 related lowering. |
2 | 2 |
3 ; RUN: %if --need=target_X8632 --command %p2i --filetype=obj --disassemble \ | 3 ; RUN: %if --need=target_X8632 --command %p2i --filetype=obj --disassemble \ |
4 ; RUN: --target x8632 -i %s --args -O2 \ | 4 ; RUN: --target x8632 -i %s --args -O2 \ |
5 ; RUN: | %if --need=target_X8632 --command FileCheck %s | 5 ; RUN: | %if --need=target_X8632 --command FileCheck %s |
6 | 6 |
7 ; RUN: %if --need=target_X8632 --command %p2i --filetype=obj --disassemble \ | 7 ; RUN: %if --need=target_X8632 --command %p2i --filetype=obj --disassemble \ |
8 ; RUN: --target x8632 -i %s --args -Om1 \ | 8 ; RUN: --target x8632 -i %s --args -Om1 \ |
9 ; RUN: | %if --need=target_X8632 --command FileCheck %s | 9 ; RUN: | %if --need=target_X8632 --command FileCheck %s |
10 | 10 |
11 ; TODO(jvoung): Stop skipping unimplemented parts (via --skip-unimplemented) | 11 ; TODO(jpp): Switch to --filetype=obj when possible. |
12 ; once enough infrastructure is in. Also, switch to --filetype=obj | |
13 ; when possible. | |
14 ; RUN: %if --need=target_ARM32 --need=allow_dump \ | 12 ; RUN: %if --need=target_ARM32 --need=allow_dump \ |
15 ; RUN: --command %p2i --filetype=asm --assemble \ | 13 ; RUN: --command %p2i --filetype=asm --assemble \ |
16 ; RUN: --disassemble --target arm32 -i %s --args -O2 --skip-unimplemented \ | 14 ; RUN: --disassemble --target arm32 -i %s --args -O2 \ |
17 ; RUN: | %if --need=target_ARM32 --need=allow_dump \ | |
18 ; RUN: --command FileCheck --check-prefix ARM32 %s | |
19 ; RUN: %if --need=target_ARM32 --need=allow_dump \ | |
20 ; RUN: --command %p2i --filetype=asm --assemble \ | |
21 ; RUN: --disassemble --target arm32 -i %s --args -Om1 --skip-unimplemented \ | |
22 ; RUN: | %if --need=target_ARM32 --need=allow_dump \ | 15 ; RUN: | %if --need=target_ARM32 --need=allow_dump \ |
23 ; RUN: --command FileCheck --check-prefix ARM32 %s | 16 ; RUN: --command FileCheck --check-prefix ARM32 %s |
24 | 17 |
25 ; TODO(jvoung): test this. | 18 ; TODO(jvoung): test this. |
26 | 19 |
27 ; Test that and with true uses immediate 1, not -1. | 20 ; Test that and with true uses immediate 1, not -1. |
28 define internal i32 @testAndTrue(i32 %arg) { | 21 define internal i32 @testAndTrue(i32 %arg) { |
29 entry: | 22 entry: |
30 %arg_i1 = trunc i32 %arg to i1 | 23 %arg_i1 = trunc i32 %arg to i1 |
31 %result_i1 = and i1 %arg_i1, true | 24 %result_i1 = and i1 %arg_i1, true |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
66 ; Test that trunc to i1 masks correctly. | 59 ; Test that trunc to i1 masks correctly. |
67 define internal i32 @testTrunc(i32 %arg) { | 60 define internal i32 @testTrunc(i32 %arg) { |
68 entry: | 61 entry: |
69 %arg_i1 = trunc i32 %arg to i1 | 62 %arg_i1 = trunc i32 %arg to i1 |
70 %result = zext i1 %arg_i1 to i32 | 63 %result = zext i1 %arg_i1 to i32 |
71 ret i32 %result | 64 ret i32 %result |
72 } | 65 } |
73 ; CHECK-LABEL: testTrunc | 66 ; CHECK-LABEL: testTrunc |
74 ; CHECK: and {{.*}},0x1 | 67 ; CHECK: and {{.*}},0x1 |
75 ; ARM32-LABEL: testTrunc | 68 ; ARM32-LABEL: testTrunc |
76 ; ARM32: and {{.*}}, #1 | 69 ; ARM32: tst r0, #1 |
| 70 ; ARM32: moveq [[REG:r[0-9]*]], #0 |
| 71 ; ARM32: movne [[REG]], #1 |
77 | 72 |
78 ; Test zext to i8. | 73 ; Test zext to i8. |
79 define internal i32 @testZextI8(i32 %arg) { | 74 define internal i32 @testZextI8(i32 %arg) { |
80 entry: | 75 entry: |
81 %arg_i1 = trunc i32 %arg to i1 | 76 %arg_i1 = trunc i32 %arg to i1 |
82 %result_i8 = zext i1 %arg_i1 to i8 | 77 %result_i8 = zext i1 %arg_i1 to i8 |
83 %result = zext i8 %result_i8 to i32 | 78 %result = zext i8 %result_i8 to i32 |
84 ret i32 %result | 79 ret i32 %result |
85 } | 80 } |
86 ; CHECK-LABEL: testZextI8 | 81 ; CHECK-LABEL: testZextI8 |
87 ; match the trunc instruction | 82 ; match the trunc instruction |
88 ; CHECK: and {{.*}},0x1 | 83 ; CHECK: and {{.*}},0x1 |
89 ; match the zext i1 instruction (NOTE: no mov need between i1 and i8). | 84 ; match the zext i1 instruction (NOTE: no mov need between i1 and i8). |
90 ; CHECK-NOT: and {{.*}},0x1 | 85 ; CHECK-NOT: and {{.*}},0x1 |
91 ; ARM32-LABEL: testZextI8 | 86 ; ARM32-LABEL: testZextI8 |
92 ; ARM32: and {{.*}}, #1 | 87 ; ARM32: tst r0, #1 |
93 ; ARM32: and {{.*}}, #1 | 88 ; ARM32: moveq [[REG:r[0-9]*]], #0 |
| 89 ; ARM32: movne [[REG]], #1 |
| 90 ; ARM32: uxtb [[REG]] |
94 | 91 |
95 ; Test zext to i16. | 92 ; Test zext to i16. |
96 define internal i32 @testZextI16(i32 %arg) { | 93 define internal i32 @testZextI16(i32 %arg) { |
97 entry: | 94 entry: |
98 %arg_i1 = trunc i32 %arg to i1 | 95 %arg_i1 = trunc i32 %arg to i1 |
99 %result_i16 = zext i1 %arg_i1 to i16 | 96 %result_i16 = zext i1 %arg_i1 to i16 |
100 %result = zext i16 %result_i16 to i32 | 97 %result = zext i16 %result_i16 to i32 |
101 ret i32 %result | 98 ret i32 %result |
102 } | 99 } |
103 ; CHECK-LABEL: testZextI16 | 100 ; CHECK-LABEL: testZextI16 |
104 ; match the trunc instruction | 101 ; match the trunc instruction |
105 ; CHECK: and {{.*}},0x1 | 102 ; CHECK: and {{.*}},0x1 |
106 ; match the zext i1 instruction (note 32-bit reg is used because it's shorter). | 103 ; match the zext i1 instruction (note 32-bit reg is used because it's shorter). |
107 ; CHECK: movzx [[REG:e.*]],{{[a-d]l|BYTE PTR}} | 104 ; CHECK: movzx [[REG:e.*]],{{[a-d]l|BYTE PTR}} |
108 ; CHECK-NOT: and [[REG]],0x1 | 105 ; CHECK-NOT: and [[REG]],0x1 |
109 | 106 |
110 ; ARM32-LABEL: testZextI16 | 107 ; ARM32-LABEL: testZextI16 |
111 ; match the trunc instruction | 108 ; ARM32: tst r0, #1 |
112 ; ARM32: and {{.*}}, #1 | 109 ; ARM32: moveq [[REG:r[0-9]*]], #0 |
113 ; match the zext (no need to uxt into a reg if src is already in a reg) | 110 ; ARM32: movne [[REG]], #1 |
114 ; ARM32: and {{.*}}, #1 | 111 ; ARM32: uxth [[REG]] |
115 | 112 |
116 ; Test zext to i32. | 113 ; Test zext to i32. |
117 define internal i32 @testZextI32(i32 %arg) { | 114 define internal i32 @testZextI32(i32 %arg) { |
118 entry: | 115 entry: |
119 %arg_i1 = trunc i32 %arg to i1 | 116 %arg_i1 = trunc i32 %arg to i1 |
120 %result_i32 = zext i1 %arg_i1 to i32 | 117 %result_i32 = zext i1 %arg_i1 to i32 |
121 ret i32 %result_i32 | 118 ret i32 %result_i32 |
122 } | 119 } |
123 ; CHECK-LABEL: testZextI32 | 120 ; CHECK-LABEL: testZextI32 |
124 ; match the trunc instruction | 121 ; match the trunc instruction |
125 ; CHECK: and {{.*}},0x1 | 122 ; CHECK: and {{.*}},0x1 |
126 ; match the zext i1 instruction | 123 ; match the zext i1 instruction |
127 ; CHECK: movzx | 124 ; CHECK: movzx |
128 ; CHECK-NOT: and {{.*}},0x1 | 125 ; CHECK-NOT: and {{.*}},0x1 |
129 ; ARM32-LABEL: testZextI32 | 126 ; ARM32-LABEL: testZextI32 |
130 ; ARM32: and {{.*}}, #1 | 127 ; ARM32: tst r0, #1 |
131 ; ARM32: and {{.*}}, #1 | 128 ; ARM32: moveq [[REG:r[0-9]*]], #0 |
| 129 ; ARM32: movne [[REG]], #1 |
132 | 130 |
133 ; Test zext to i64. | 131 ; Test zext to i64. |
134 define internal i64 @testZextI64(i32 %arg) { | 132 define internal i64 @testZextI64(i32 %arg) { |
135 entry: | 133 entry: |
136 %arg_i1 = trunc i32 %arg to i1 | 134 %arg_i1 = trunc i32 %arg to i1 |
137 %result_i64 = zext i1 %arg_i1 to i64 | 135 %result_i64 = zext i1 %arg_i1 to i64 |
138 ret i64 %result_i64 | 136 ret i64 %result_i64 |
139 } | 137 } |
140 ; CHECK-LABEL: testZextI64 | 138 ; CHECK-LABEL: testZextI64 |
141 ; match the trunc instruction | 139 ; match the trunc instruction |
142 ; CHECK: and {{.*}},0x1 | 140 ; CHECK: and {{.*}},0x1 |
143 ; match the zext i1 instruction | 141 ; match the zext i1 instruction |
144 ; CHECK: movzx | 142 ; CHECK: movzx |
145 ; CHECK: mov {{.*}},0x0 | 143 ; CHECK: mov {{.*}},0x0 |
146 ; ARM32-LABEL: testZextI64 | 144 ; ARM32-LABEL: testZextI64 |
147 ; ARM32: and {{.*}}, #1 | 145 ; ARM32: tst r0, #1 |
148 ; ARM32: and {{.*}}, #1 | 146 ; ARM32: mov r{{[0-9]*}}, #0 |
149 ; ARM32: mov {{.*}}, #0 | 147 ; ARM32: moveq [[REG:r[0-9]*]], #0 |
| 148 ; ARM32: movne [[REG]], #1 |
150 | 149 |
151 ; Test sext to i8. | 150 ; Test sext to i8. |
152 define internal i32 @testSextI8(i32 %arg) { | 151 define internal i32 @testSextI8(i32 %arg) { |
153 entry: | 152 entry: |
154 %arg_i1 = trunc i32 %arg to i1 | 153 %arg_i1 = trunc i32 %arg to i1 |
155 %result_i8 = sext i1 %arg_i1 to i8 | 154 %result_i8 = sext i1 %arg_i1 to i8 |
156 %result = sext i8 %result_i8 to i32 | 155 %result = sext i8 %result_i8 to i32 |
157 ret i32 %result | 156 ret i32 %result |
158 } | 157 } |
159 ; CHECK-LABEL: testSextI8 | 158 ; CHECK-LABEL: testSextI8 |
160 ; match the trunc instruction | 159 ; match the trunc instruction |
161 ; CHECK: and {{.*}},0x1 | 160 ; CHECK: and {{.*}},0x1 |
162 ; match the sext i1 instruction | 161 ; match the sext i1 instruction |
163 ; CHECK: shl [[REG:.*]],0x7 | 162 ; CHECK: shl [[REG:.*]],0x7 |
164 ; CHECK-NEXT: sar [[REG]],0x7 | 163 ; CHECK-NEXT: sar [[REG]],0x7 |
165 ; | 164 ; |
166 ; ARM shifts by 32, since there aren't any byte regs. | |
167 ; ARM32-LABEL: testSextI8 | 165 ; ARM32-LABEL: testSextI8 |
168 ; match the trunc instruction | 166 ; ARM32: tst r0, #1 |
169 ; ARM32: and {{.*}}, #1 | 167 ; ARM32: mvn [[REG_M1:r[0-9]*]], #0 |
170 ; match the sext i1 instruction | 168 ; ARM32: moveq [[REG:r[0-9]*]], #0 |
171 ; ARM32: lsl {{.*}}, #31 | 169 ; ARM32: movne [[REG]], [[REG_M1]] |
172 ; ARM32-NEXT: asr {{.*}}, #31 | 170 ; ARM32: sxtb [[REG]] |
173 | 171 |
174 ; Test sext to i16. | 172 ; Test sext to i16. |
175 define internal i32 @testSextI16(i32 %arg) { | 173 define internal i32 @testSextI16(i32 %arg) { |
176 entry: | 174 entry: |
177 %arg_i1 = trunc i32 %arg to i1 | 175 %arg_i1 = trunc i32 %arg to i1 |
178 %result_i16 = sext i1 %arg_i1 to i16 | 176 %result_i16 = sext i1 %arg_i1 to i16 |
179 %result = sext i16 %result_i16 to i32 | 177 %result = sext i16 %result_i16 to i32 |
180 ret i32 %result | 178 ret i32 %result |
181 } | 179 } |
182 ; CHECK-LABEL: testSextI16 | 180 ; CHECK-LABEL: testSextI16 |
183 ; match the trunc instruction | 181 ; match the trunc instruction |
184 ; CHECK: and {{.*}},0x1 | 182 ; CHECK: and {{.*}},0x1 |
185 ; match the sext i1 instruction | 183 ; match the sext i1 instruction |
186 ; CHECK: movzx e[[REG:.*]],{{[a-d]l|BYTE PTR}} | 184 ; CHECK: movzx e[[REG:.*]],{{[a-d]l|BYTE PTR}} |
187 ; CHECK-NEXT: shl [[REG]],0xf | 185 ; CHECK-NEXT: shl [[REG]],0xf |
188 ; CHECK-NEXT: sar [[REG]],0xf | 186 ; CHECK-NEXT: sar [[REG]],0xf |
189 | 187 |
190 ; ARM32-LABEL: testSextI16 | 188 ; ARM32-LABEL: testSextI16 |
191 ; ARM32: and {{.*}}, #1 | 189 ; ARM32: tst r0, #1 |
192 ; ARM32: lsl {{.*}}, #31 | 190 ; ARM32: mvn [[REG_M1:r[0-9]*]], #0 |
193 ; ARM32-NEXT: asr {{.*}}, #31 | 191 ; ARM32: moveq [[REG:r[0-9]*]], #0 |
| 192 ; ARM32: movne [[REG]], [[REG_M1]] |
| 193 ; ARM32: sxth [[REG]] |
194 | 194 |
195 ; Test sext to i32. | 195 ; Test sext to i32. |
196 define internal i32 @testSextI32(i32 %arg) { | 196 define internal i32 @testSextI32(i32 %arg) { |
197 entry: | 197 entry: |
198 %arg_i1 = trunc i32 %arg to i1 | 198 %arg_i1 = trunc i32 %arg to i1 |
199 %result_i32 = sext i1 %arg_i1 to i32 | 199 %result_i32 = sext i1 %arg_i1 to i32 |
200 ret i32 %result_i32 | 200 ret i32 %result_i32 |
201 } | 201 } |
202 ; CHECK-LABEL: testSextI32 | 202 ; CHECK-LABEL: testSextI32 |
203 ; match the trunc instruction | 203 ; match the trunc instruction |
204 ; CHECK: and {{.*}},0x1 | 204 ; CHECK: and {{.*}},0x1 |
205 ; match the sext i1 instruction | 205 ; match the sext i1 instruction |
206 ; CHECK: movzx [[REG:.*]], | 206 ; CHECK: movzx [[REG:.*]], |
207 ; CHECK-NEXT: shl [[REG]],0x1f | 207 ; CHECK-NEXT: shl [[REG]],0x1f |
208 ; CHECK-NEXT: sar [[REG]],0x1f | 208 ; CHECK-NEXT: sar [[REG]],0x1f |
209 | 209 |
210 ; ARM32-LABEL: testSextI32 | 210 ; ARM32-LABEL: testSextI32 |
211 ; ARM32: and {{.*}}, #1 | 211 ; ARM32: tst r0, #1 |
212 ; ARM32: lsl {{.*}}, #31 | 212 ; ARM32: mvn [[REG_M1:r[0-9]*]], #0 |
213 ; ARM32-NEXT: asr {{.*}}, #31 | 213 ; ARM32: moveq [[REG:r[0-9]*]], #0 |
| 214 ; ARM32: movne [[REG]], [[REG_M1]] |
214 | 215 |
215 ; Test sext to i64. | 216 ; Test sext to i64. |
216 define internal i64 @testSextI64(i32 %arg) { | 217 define internal i64 @testSextI64(i32 %arg) { |
217 entry: | 218 entry: |
218 %arg_i1 = trunc i32 %arg to i1 | 219 %arg_i1 = trunc i32 %arg to i1 |
219 %result_i64 = sext i1 %arg_i1 to i64 | 220 %result_i64 = sext i1 %arg_i1 to i64 |
220 ret i64 %result_i64 | 221 ret i64 %result_i64 |
221 } | 222 } |
222 ; CHECK-LABEL: testSextI64 | 223 ; CHECK-LABEL: testSextI64 |
223 ; match the trunc instruction | 224 ; match the trunc instruction |
224 ; CHECK: and {{.*}},0x1 | 225 ; CHECK: and {{.*}},0x1 |
225 ; match the sext i1 instruction | 226 ; match the sext i1 instruction |
226 ; CHECK: movzx [[REG:.*]], | 227 ; CHECK: movzx [[REG:.*]], |
227 ; CHECK-NEXT: shl [[REG]],0x1f | 228 ; CHECK-NEXT: shl [[REG]],0x1f |
228 ; CHECK-NEXT: sar [[REG]],0x1f | 229 ; CHECK-NEXT: sar [[REG]],0x1f |
229 | 230 |
230 ; ARM32-LABEL: testSextI64 | 231 ; ARM32-LABEL: testSextI64 |
231 ; ARM32: and {{.*}}, #1 | 232 ; ARM32: tst r0, #1 |
232 ; ARM32: lsl {{.*}}, #31 | 233 ; ARM32: mvn [[REG_M1:r[0-9]*]], #0 |
233 ; ARM32-NEXT: asr [[REG:r.*]], {{.*}}, #31 | 234 ; ARM32: moveq [[REG:r[0-9]*]], #0 |
234 ; ARM32-NEXT: {{(mov|str).*}} [[REG]] | 235 ; ARM32: movne [[REG]], [[REG_M1]] |
| 236 ; ARM32: mov r{{[0-9]+}}, [[REG]] |
235 | 237 |
236 ; Kind of like sext i1 to i32, but with an immediate source. On ARM, | 238 ; Kind of like sext i1 to i32, but with an immediate source. On ARM, |
237 ; sxtb cannot take an immediate operand, so make sure it's using a reg. | 239 ; sxtb cannot take an immediate operand, so make sure it's using a reg. |
238 ; If we had optimized constants, this could just be mov dst, 0xffffffff | 240 ; If we had optimized constants, this could just be mov dst, 0xffffffff |
239 ; or mvn dst, #0. | 241 ; or mvn dst, #0. |
240 define internal i32 @testSextTrue() { | 242 define internal i32 @testSextTrue() { |
241 %result = sext i1 true to i32 | 243 %result = sext i1 true to i32 |
242 ret i32 %result | 244 ret i32 %result |
243 } | 245 } |
244 ; CHECK-LABEL: testSextTrue | 246 ; CHECK-LABEL: testSextTrue |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
281 %arg_i1 = fptosi double %arg to i1 | 283 %arg_i1 = fptosi double %arg to i1 |
282 %result = sext i1 %arg_i1 to i32 | 284 %result = sext i1 %arg_i1 to i32 |
283 ret i32 %result | 285 ret i32 %result |
284 } | 286 } |
285 ; CHECK-LABEL: testFptosiDouble | 287 ; CHECK-LABEL: testFptosiDouble |
286 ; CHECK: cvttsd2si | 288 ; CHECK: cvttsd2si |
287 ; CHECK: and {{.*}},0x1 | 289 ; CHECK: and {{.*}},0x1 |
288 ; CHECK: movzx [[REG:.*]], | 290 ; CHECK: movzx [[REG:.*]], |
289 ; CHECK-NEXT: shl [[REG]],0x1f | 291 ; CHECK-NEXT: shl [[REG]],0x1f |
290 ; CHECK-NEXT: sar [[REG]],0x1f | 292 ; CHECK-NEXT: sar [[REG]],0x1f |
OLD | NEW |