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