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