| 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 ; RUN: %if --need=target_MIPS32 --need=allow_dump \ |
| 19 ; RUN: --command %p2i --filetype=asm --assemble --disassemble --target \ |
| 20 ; RUN: mips32 -i %s --args -O2 -allow-externally-defined-symbols \ |
| 21 ; RUN: | %if --need=target_MIPS32 --need=allow_dump \ |
| 22 ; RUN: --command FileCheck --check-prefix MIPS32 %s |
| 23 |
| 18 ; Test that and with true uses immediate 1, not -1. | 24 ; Test that and with true uses immediate 1, not -1. |
| 19 define internal i32 @testAndTrue(i32 %arg) { | 25 define internal i32 @testAndTrue(i32 %arg) { |
| 20 entry: | 26 entry: |
| 21 %arg_i1 = trunc i32 %arg to i1 | 27 %arg_i1 = trunc i32 %arg to i1 |
| 22 %result_i1 = and i1 %arg_i1, true | 28 %result_i1 = and i1 %arg_i1, true |
| 23 %result = zext i1 %result_i1 to i32 | 29 %result = zext i1 %result_i1 to i32 |
| 24 ret i32 %result | 30 ret i32 %result |
| 25 } | 31 } |
| 26 ; CHECK-LABEL: testAndTrue | 32 ; CHECK-LABEL: testAndTrue |
| 27 ; CHECK: and {{.*}},0x1 | 33 ; CHECK: and {{.*}},0x1 |
| 28 ; ARM32-LABEL: testAndTrue | 34 ; ARM32-LABEL: testAndTrue |
| 29 ; ARM32: and {{.*}}, #1 | 35 ; ARM32: and {{.*}}, #1 |
| 36 ; MIPS32-LABEL: testAndTrue |
| 37 ; MIPS32: li [[REG:.*]],1 |
| 38 ; MIPS32: and {{.*}},[[REG]] |
| 30 | 39 |
| 31 ; Test that or with true uses immediate 1, not -1. | 40 ; Test that or with true uses immediate 1, not -1. |
| 32 define internal i32 @testOrTrue(i32 %arg) { | 41 define internal i32 @testOrTrue(i32 %arg) { |
| 33 entry: | 42 entry: |
| 34 %arg_i1 = trunc i32 %arg to i1 | 43 %arg_i1 = trunc i32 %arg to i1 |
| 35 %result_i1 = or i1 %arg_i1, true | 44 %result_i1 = or i1 %arg_i1, true |
| 36 %result = zext i1 %result_i1 to i32 | 45 %result = zext i1 %result_i1 to i32 |
| 37 ret i32 %result | 46 ret i32 %result |
| 38 } | 47 } |
| 39 ; CHECK-LABEL: testOrTrue | 48 ; CHECK-LABEL: testOrTrue |
| 40 ; CHECK: or {{.*}},0x1 | 49 ; CHECK: or {{.*}},0x1 |
| 41 ; ARM32-LABEL: testOrTrue | 50 ; ARM32-LABEL: testOrTrue |
| 42 ; ARM32: orr {{.*}}, #1 | 51 ; ARM32: orr {{.*}}, #1 |
| 52 ; MIPS32-LABEL: testOrTrue |
| 53 ; MIPS32: li [[REG:.*]],1 |
| 54 ; MIPS32: or {{.*}},[[REG]] |
| 43 | 55 |
| 44 ; Test that xor with true uses immediate 1, not -1. | 56 ; Test that xor with true uses immediate 1, not -1. |
| 45 define internal i32 @testXorTrue(i32 %arg) { | 57 define internal i32 @testXorTrue(i32 %arg) { |
| 46 entry: | 58 entry: |
| 47 %arg_i1 = trunc i32 %arg to i1 | 59 %arg_i1 = trunc i32 %arg to i1 |
| 48 %result_i1 = xor i1 %arg_i1, true | 60 %result_i1 = xor i1 %arg_i1, true |
| 49 %result = zext i1 %result_i1 to i32 | 61 %result = zext i1 %result_i1 to i32 |
| 50 ret i32 %result | 62 ret i32 %result |
| 51 } | 63 } |
| 52 ; CHECK-LABEL: testXorTrue | 64 ; CHECK-LABEL: testXorTrue |
| 53 ; CHECK: xor {{.*}},0x1 | 65 ; CHECK: xor {{.*}},0x1 |
| 54 ; ARM32-LABEL: testXorTrue | 66 ; ARM32-LABEL: testXorTrue |
| 55 ; ARM32: eor {{.*}}, #1 | 67 ; ARM32: eor {{.*}}, #1 |
| 68 ; MIPS32-LABEL: testXorTrue |
| 69 ; MIPS32: li [[REG:.*]],1 |
| 70 ; MIPS32: xor {{.*}},[[REG]] |
| 56 | 71 |
| 57 ; Test that trunc to i1 masks correctly. | 72 ; Test that trunc to i1 masks correctly. |
| 58 define internal i32 @testTrunc(i32 %arg) { | 73 define internal i32 @testTrunc(i32 %arg) { |
| 59 entry: | 74 entry: |
| 60 %arg_i1 = trunc i32 %arg to i1 | 75 %arg_i1 = trunc i32 %arg to i1 |
| 61 %result = zext i1 %arg_i1 to i32 | 76 %result = zext i1 %arg_i1 to i32 |
| 62 ret i32 %result | 77 ret i32 %result |
| 63 } | 78 } |
| 64 ; CHECK-LABEL: testTrunc | 79 ; CHECK-LABEL: testTrunc |
| 65 ; CHECK: and {{.*}},0x1 | 80 ; CHECK: and {{.*}},0x1 |
| 66 ; ARM32-LABEL: testTrunc | 81 ; ARM32-LABEL: testTrunc |
| 67 ; ARM32: and {{.*}}, #1 | 82 ; ARM32: and {{.*}}, #1 |
| 83 ; MIPS32-LABEL: testTrunc |
| 84 ; MIPS32: andi {{.*}},0x1 |
| 68 | 85 |
| 69 ; Test zext to i8. | 86 ; Test zext to i8. |
| 70 define internal i32 @testZextI8(i32 %arg) { | 87 define internal i32 @testZextI8(i32 %arg) { |
| 71 entry: | 88 entry: |
| 72 %arg_i1 = trunc i32 %arg to i1 | 89 %arg_i1 = trunc i32 %arg to i1 |
| 73 %result_i8 = zext i1 %arg_i1 to i8 | 90 %result_i8 = zext i1 %arg_i1 to i8 |
| 74 %result = zext i8 %result_i8 to i32 | 91 %result = zext i8 %result_i8 to i32 |
| 75 ret i32 %result | 92 ret i32 %result |
| 76 } | 93 } |
| 77 ; CHECK-LABEL: testZextI8 | 94 ; CHECK-LABEL: testZextI8 |
| 78 ; match the trunc instruction | 95 ; match the trunc instruction |
| 79 ; CHECK: and {{.*}},0x1 | 96 ; CHECK: and {{.*}},0x1 |
| 80 ; match the zext i1 instruction (NOTE: no mov need between i1 and i8). | 97 ; match the zext i1 instruction (NOTE: no mov need between i1 and i8). |
| 81 ; CHECK-NOT: and {{.*}},0x1 | 98 ; CHECK-NOT: and {{.*}},0x1 |
| 82 ; ARM32-LABEL: testZextI8 | 99 ; ARM32-LABEL: testZextI8 |
| 83 ; ARM32: {{.*}}, #1 | 100 ; ARM32: {{.*}}, #1 |
| 84 ; ARM32: uxtb | 101 ; ARM32: uxtb |
| 102 ; MIPS32-LABEL: testZextI8 |
| 103 ; MIPS32: andi {{.*}},0x1 |
| 104 ; MIPS32: andi {{.*}},0xff |
| 85 | 105 |
| 86 ; Test zext to i16. | 106 ; Test zext to i16. |
| 87 define internal i32 @testZextI16(i32 %arg) { | 107 define internal i32 @testZextI16(i32 %arg) { |
| 88 entry: | 108 entry: |
| 89 %arg_i1 = trunc i32 %arg to i1 | 109 %arg_i1 = trunc i32 %arg to i1 |
| 90 %result_i16 = zext i1 %arg_i1 to i16 | 110 %result_i16 = zext i1 %arg_i1 to i16 |
| 91 %result = zext i16 %result_i16 to i32 | 111 %result = zext i16 %result_i16 to i32 |
| 92 ret i32 %result | 112 ret i32 %result |
| 93 } | 113 } |
| 94 ; CHECK-LABEL: testZextI16 | 114 ; CHECK-LABEL: testZextI16 |
| 95 ; match the trunc instruction | 115 ; match the trunc instruction |
| 96 ; CHECK: and {{.*}},0x1 | 116 ; CHECK: and {{.*}},0x1 |
| 97 ; match the zext i1 instruction (note 32-bit reg is used because it's shorter). | 117 ; match the zext i1 instruction (note 32-bit reg is used because it's shorter). |
| 98 ; CHECK: movzx [[REG:e.*]],{{[a-d]l|BYTE PTR}} | 118 ; CHECK: movzx [[REG:e.*]],{{[a-d]l|BYTE PTR}} |
| 99 ; CHECK-NOT: and [[REG]],0x1 | 119 ; CHECK-NOT: and [[REG]],0x1 |
| 100 | 120 |
| 101 ; ARM32-LABEL: testZextI16 | 121 ; ARM32-LABEL: testZextI16 |
| 102 ; ARM32: and {{.*}}, #1 | 122 ; ARM32: and {{.*}}, #1 |
| 103 ; ARM32: uxth | 123 ; ARM32: uxth |
| 104 | 124 |
| 125 ; MIPS32-LABEL: testZextI16 |
| 126 ; MIPS32: andi {{.*}},0x1 |
| 127 ; MIPS32: andi {{.*}},0xffff |
| 128 |
| 105 ; Test zext to i32. | 129 ; Test zext to i32. |
| 106 define internal i32 @testZextI32(i32 %arg) { | 130 define internal i32 @testZextI32(i32 %arg) { |
| 107 entry: | 131 entry: |
| 108 %arg_i1 = trunc i32 %arg to i1 | 132 %arg_i1 = trunc i32 %arg to i1 |
| 109 %result_i32 = zext i1 %arg_i1 to i32 | 133 %result_i32 = zext i1 %arg_i1 to i32 |
| 110 ret i32 %result_i32 | 134 ret i32 %result_i32 |
| 111 } | 135 } |
| 112 ; CHECK-LABEL: testZextI32 | 136 ; CHECK-LABEL: testZextI32 |
| 113 ; match the trunc instruction | 137 ; match the trunc instruction |
| 114 ; CHECK: and {{.*}},0x1 | 138 ; CHECK: and {{.*}},0x1 |
| 115 ; match the zext i1 instruction | 139 ; match the zext i1 instruction |
| 116 ; CHECK: movzx | 140 ; CHECK: movzx |
| 117 ; CHECK-NOT: and {{.*}},0x1 | 141 ; CHECK-NOT: and {{.*}},0x1 |
| 118 ; ARM32-LABEL: testZextI32 | 142 ; ARM32-LABEL: testZextI32 |
| 119 ; ARM32: and {{.*}}, #1 | 143 ; ARM32: and {{.*}}, #1 |
| 144 ; MIPS32-LABEL: testZextI32 |
| 145 ; MIPS32: andi {{.*}},0x1 |
| 120 | 146 |
| 121 ; Test zext to i64. | 147 ; Test zext to i64. |
| 122 define internal i64 @testZextI64(i32 %arg) { | 148 define internal i64 @testZextI64(i32 %arg) { |
| 123 entry: | 149 entry: |
| 124 %arg_i1 = trunc i32 %arg to i1 | 150 %arg_i1 = trunc i32 %arg to i1 |
| 125 %result_i64 = zext i1 %arg_i1 to i64 | 151 %result_i64 = zext i1 %arg_i1 to i64 |
| 126 ret i64 %result_i64 | 152 ret i64 %result_i64 |
| 127 } | 153 } |
| 128 ; CHECK-LABEL: testZextI64 | 154 ; CHECK-LABEL: testZextI64 |
| 129 ; match the trunc instruction | 155 ; match the trunc instruction |
| 130 ; CHECK: and {{.*}},0x1 | 156 ; CHECK: and {{.*}},0x1 |
| 131 ; match the zext i1 instruction | 157 ; match the zext i1 instruction |
| 132 ; CHECK: movzx | 158 ; CHECK: movzx |
| 133 ; CHECK: mov {{.*}},0x0 | 159 ; CHECK: mov {{.*}},0x0 |
| 134 ; ARM32-LABEL: testZextI64 | 160 ; ARM32-LABEL: testZextI64 |
| 135 ; ARM32: and {{.*}}, #1 | 161 ; ARM32: and {{.*}}, #1 |
| 136 ; ARM32: mov {{.*}}, #0 | 162 ; ARM32: mov {{.*}}, #0 |
| 163 ; MIPS32-LABEL: testZextI64 |
| 164 ; MIPS32: andi {{.*}},0x1 |
| 165 ; MIPS32: li {{.*}},0 |
| 166 ; MIPS32: move |
| 167 ; MIPS32: move |
| 137 | 168 |
| 138 ; Test sext to i8. | 169 ; Test sext to i8. |
| 139 define internal i32 @testSextI8(i32 %arg) { | 170 define internal i32 @testSextI8(i32 %arg) { |
| 140 entry: | 171 entry: |
| 141 %arg_i1 = trunc i32 %arg to i1 | 172 %arg_i1 = trunc i32 %arg to i1 |
| 142 %result_i8 = sext i1 %arg_i1 to i8 | 173 %result_i8 = sext i1 %arg_i1 to i8 |
| 143 %result = sext i8 %result_i8 to i32 | 174 %result = sext i8 %result_i8 to i32 |
| 144 ret i32 %result | 175 ret i32 %result |
| 145 } | 176 } |
| 146 ; CHECK-LABEL: testSextI8 | 177 ; CHECK-LABEL: testSextI8 |
| 147 ; match the trunc instruction | 178 ; match the trunc instruction |
| 148 ; CHECK: and {{.*}},0x1 | 179 ; CHECK: and {{.*}},0x1 |
| 149 ; match the sext i1 instruction | 180 ; match the sext i1 instruction |
| 150 ; CHECK: shl [[REG:.*]],0x7 | 181 ; CHECK: shl [[REG:.*]],0x7 |
| 151 ; CHECK-NEXT: sar [[REG]],0x7 | 182 ; CHECK-NEXT: sar [[REG]],0x7 |
| 152 ; | 183 ; |
| 153 ; ARM32-LABEL: testSextI8 | 184 ; ARM32-LABEL: testSextI8 |
| 154 ; ARM32: mov {{.*}}, #0 | 185 ; ARM32: mov {{.*}}, #0 |
| 155 ; ARM32: tst {{.*}}, #1 | 186 ; ARM32: tst {{.*}}, #1 |
| 156 ; ARM32: mvn {{.*}}, #0 | 187 ; ARM32: mvn {{.*}}, #0 |
| 157 ; ARM32: movne | 188 ; ARM32: movne |
| 158 ; ARM32: sxtb | 189 ; ARM32: sxtb |
| 190 ; |
| 191 ; MIPS32-LABEL: testSextI8 |
| 192 ; MIPS32: sll {{.*}},0x1f |
| 193 ; MIPS32: sra {{.*}},0x1f |
| 194 ; MIPS32: sll {{.*}},0x18 |
| 195 ; MIPS32: sra {{.*}},0x18 |
| 159 | 196 |
| 160 ; Test sext to i16. | 197 ; Test sext to i16. |
| 161 define internal i32 @testSextI16(i32 %arg) { | 198 define internal i32 @testSextI16(i32 %arg) { |
| 162 entry: | 199 entry: |
| 163 %arg_i1 = trunc i32 %arg to i1 | 200 %arg_i1 = trunc i32 %arg to i1 |
| 164 %result_i16 = sext i1 %arg_i1 to i16 | 201 %result_i16 = sext i1 %arg_i1 to i16 |
| 165 %result = sext i16 %result_i16 to i32 | 202 %result = sext i16 %result_i16 to i32 |
| 166 ret i32 %result | 203 ret i32 %result |
| 167 } | 204 } |
| 168 ; CHECK-LABEL: testSextI16 | 205 ; CHECK-LABEL: testSextI16 |
| 169 ; match the trunc instruction | 206 ; match the trunc instruction |
| 170 ; CHECK: and {{.*}},0x1 | 207 ; CHECK: and {{.*}},0x1 |
| 171 ; match the sext i1 instruction | 208 ; match the sext i1 instruction |
| 172 ; CHECK: movzx {{e*}}[[REG:.*]],{{[a-d]l|BYTE PTR}} | 209 ; CHECK: movzx {{e*}}[[REG:.*]],{{[a-d]l|BYTE PTR}} |
| 173 ; CHECK-NEXT: shl [[REG]],0xf | 210 ; CHECK-NEXT: shl [[REG]],0xf |
| 174 ; CHECK-NEXT: sar [[REG]],0xf | 211 ; CHECK-NEXT: sar [[REG]],0xf |
| 175 | 212 |
| 176 ; ARM32-LABEL: testSextI16 | 213 ; ARM32-LABEL: testSextI16 |
| 177 ; ARM32: mov {{.*}}, #0 | 214 ; ARM32: mov {{.*}}, #0 |
| 178 ; ARM32: tst {{.*}}, #1 | 215 ; ARM32: tst {{.*}}, #1 |
| 179 ; ARM32: mvn {{.*}}, #0 | 216 ; ARM32: mvn {{.*}}, #0 |
| 180 ; ARM32: movne | 217 ; ARM32: movne |
| 181 ; ARM32: sxth | 218 ; ARM32: sxth |
| 182 | 219 |
| 220 ; MIPS32-LABEL: testSextI16 |
| 221 ; MIPS32: sll {{.*}},0x1f |
| 222 ; MIPS32: sra {{.*}},0x1f |
| 223 ; MIPS32: sll {{.*}},0x10 |
| 224 ; MIPS32: sra {{.*}},0x10 |
| 225 |
| 183 ; Test sext to i32. | 226 ; Test sext to i32. |
| 184 define internal i32 @testSextI32(i32 %arg) { | 227 define internal i32 @testSextI32(i32 %arg) { |
| 185 entry: | 228 entry: |
| 186 %arg_i1 = trunc i32 %arg to i1 | 229 %arg_i1 = trunc i32 %arg to i1 |
| 187 %result_i32 = sext i1 %arg_i1 to i32 | 230 %result_i32 = sext i1 %arg_i1 to i32 |
| 188 ret i32 %result_i32 | 231 ret i32 %result_i32 |
| 189 } | 232 } |
| 190 ; CHECK-LABEL: testSextI32 | 233 ; CHECK-LABEL: testSextI32 |
| 191 ; match the trunc instruction | 234 ; match the trunc instruction |
| 192 ; CHECK: and {{.*}},0x1 | 235 ; CHECK: and {{.*}},0x1 |
| 193 ; match the sext i1 instruction | 236 ; match the sext i1 instruction |
| 194 ; CHECK: movzx [[REG:.*]], | 237 ; CHECK: movzx [[REG:.*]], |
| 195 ; CHECK-NEXT: shl [[REG]],0x1f | 238 ; CHECK-NEXT: shl [[REG]],0x1f |
| 196 ; CHECK-NEXT: sar [[REG]],0x1f | 239 ; CHECK-NEXT: sar [[REG]],0x1f |
| 197 | 240 |
| 198 ; ARM32-LABEL: testSextI32 | 241 ; ARM32-LABEL: testSextI32 |
| 199 ; ARM32: mov {{.*}}, #0 | 242 ; ARM32: mov {{.*}}, #0 |
| 200 ; ARM32: tst {{.*}}, #1 | 243 ; ARM32: tst {{.*}}, #1 |
| 201 ; ARM32: mvn {{.*}}, #0 | 244 ; ARM32: mvn {{.*}}, #0 |
| 202 ; ARM32: movne | 245 ; ARM32: movne |
| 203 | 246 |
| 247 ; MIPS32-LABEL: testSextI32 |
| 248 ; MIPS32: sll {{.*}},0x1f |
| 249 ; MIPS32: sra {{.*}},0x1f |
| 250 |
| 204 ; Test sext to i64. | 251 ; Test sext to i64. |
| 205 define internal i64 @testSextI64(i32 %arg) { | 252 define internal i64 @testSextI64(i32 %arg) { |
| 206 entry: | 253 entry: |
| 207 %arg_i1 = trunc i32 %arg to i1 | 254 %arg_i1 = trunc i32 %arg to i1 |
| 208 %result_i64 = sext i1 %arg_i1 to i64 | 255 %result_i64 = sext i1 %arg_i1 to i64 |
| 209 ret i64 %result_i64 | 256 ret i64 %result_i64 |
| 210 } | 257 } |
| 211 ; CHECK-LABEL: testSextI64 | 258 ; CHECK-LABEL: testSextI64 |
| 212 ; match the trunc instruction | 259 ; match the trunc instruction |
| 213 ; CHECK: and {{.*}},0x1 | 260 ; CHECK: and {{.*}},0x1 |
| 214 ; match the sext i1 instruction | 261 ; match the sext i1 instruction |
| 215 ; CHECK: movzx [[REG:.*]], | 262 ; CHECK: movzx [[REG:.*]], |
| 216 ; CHECK-NEXT: shl [[REG]],0x1f | 263 ; CHECK-NEXT: shl [[REG]],0x1f |
| 217 ; CHECK-NEXT: sar [[REG]],0x1f | 264 ; CHECK-NEXT: sar [[REG]],0x1f |
| 218 | 265 |
| 219 ; ARM32-LABEL: testSextI64 | 266 ; ARM32-LABEL: testSextI64 |
| 220 ; ARM32: mov {{.*}}, #0 | 267 ; ARM32: mov {{.*}}, #0 |
| 221 ; ARM32: tst {{.*}}, #1 | 268 ; ARM32: tst {{.*}}, #1 |
| 222 ; ARM32: mvn {{.*}}, #0 | 269 ; ARM32: mvn {{.*}}, #0 |
| 223 ; ARM32: movne [[REG:r[0-9]+]] | 270 ; ARM32: movne [[REG:r[0-9]+]] |
| 224 ; ARM32: mov {{.*}}, [[REG]] | 271 ; ARM32: mov {{.*}}, [[REG]] |
| 225 | 272 |
| 273 ; MIPS32-LABEL: testSextI64 |
| 274 ; MIPS32: sll {{.*}},0x1f |
| 275 ; MIPS32: sra {{.*}},0x1f |
| 276 ; MIPS32: move |
| 277 ; MIPS32: move |
| 278 |
| 226 ; Kind of like sext i1 to i32, but with an immediate source. On ARM, | 279 ; Kind of like sext i1 to i32, but with an immediate source. On ARM, |
| 227 ; sxtb cannot take an immediate operand, so make sure it's using a reg. | 280 ; sxtb cannot take an immediate operand, so make sure it's using a reg. |
| 228 ; If we had optimized constants, this could just be mov dst, 0xffffffff | 281 ; If we had optimized constants, this could just be mov dst, 0xffffffff |
| 229 ; or mvn dst, #0. | 282 ; or mvn dst, #0. |
| 230 define internal i32 @testSextTrue() { | 283 define internal i32 @testSextTrue() { |
| 231 %result = sext i1 true to i32 | 284 %result = sext i1 true to i32 |
| 232 ret i32 %result | 285 ret i32 %result |
| 233 } | 286 } |
| 234 ; CHECK-LABEL: testSextTrue | 287 ; CHECK-LABEL: testSextTrue |
| 235 ; CHECK: movzx | 288 ; CHECK: movzx |
| 236 ; CHECK-NEXT: shl | 289 ; CHECK-NEXT: shl |
| 237 ; CHECK-NEXT: sar | 290 ; CHECK-NEXT: sar |
| 238 ; ARM32-LABEL: testSextTrue | 291 ; ARM32-LABEL: testSextTrue |
| 239 ; ARM32: mov {{.*}}, #0 | 292 ; ARM32: mov {{.*}}, #0 |
| 240 ; ARM32: tst {{.*}}, #1 | 293 ; ARM32: tst {{.*}}, #1 |
| 241 ; ARM32: mvn {{.*}}, #0 | 294 ; ARM32: mvn {{.*}}, #0 |
| 242 ; ARM32: movne | 295 ; ARM32: movne |
| 296 ; MIPS32-LABEL: testSextTrue |
| 297 ; MIPS32: li {{.*}},1 |
| 298 ; MIPS32: sll {{.*}},0x1f |
| 299 ; MIPS32: sra {{.*}},0x1f |
| 243 | 300 |
| 244 define internal i32 @testZextTrue() { | 301 define internal i32 @testZextTrue() { |
| 245 %result = zext i1 true to i32 | 302 %result = zext i1 true to i32 |
| 246 ret i32 %result | 303 ret i32 %result |
| 247 } | 304 } |
| 248 ; CHECK-LABEL: testZextTrue | 305 ; CHECK-LABEL: testZextTrue |
| 249 ; CHECK: movzx | 306 ; CHECK: movzx |
| 250 ; CHECK-NOT: and {{.*}},0x1 | 307 ; CHECK-NOT: and {{.*}},0x1 |
| 251 ; ARM32-LABEL: testZextTrue | 308 ; ARM32-LABEL: testZextTrue |
| 252 ; ARM32: mov{{.*}}, #1 | 309 ; ARM32: mov{{.*}}, #1 |
| 253 ; ARM32: and {{.*}}, #1 | 310 ; ARM32: and {{.*}}, #1 |
| 311 ; MIPS32-LABEL: testZextTrue |
| 312 ; MIPS32: li {{.*}},1 |
| 313 ; MIPS32: andi {{.*}},0x1 |
| 254 | 314 |
| 255 ; Test fptosi float to i1. | 315 ; Test fptosi float to i1. |
| 256 define internal i32 @testFptosiFloat(float %arg) { | 316 define internal i32 @testFptosiFloat(float %arg) { |
| 257 entry: | 317 entry: |
| 258 %arg_i1 = fptosi float %arg to i1 | 318 %arg_i1 = fptosi float %arg to i1 |
| 259 %result = sext i1 %arg_i1 to i32 | 319 %result = sext i1 %arg_i1 to i32 |
| 260 ret i32 %result | 320 ret i32 %result |
| 261 } | 321 } |
| 262 ; CHECK-LABEL: testFptosiFloat | 322 ; CHECK-LABEL: testFptosiFloat |
| 263 ; CHECK: cvttss2si | 323 ; CHECK: cvttss2si |
| 264 ; CHECK: and {{.*}},0x1 | 324 ; CHECK: and {{.*}},0x1 |
| 265 ; CHECK: movzx [[REG:.*]], | 325 ; CHECK: movzx [[REG:.*]], |
| 266 ; CHECK-NEXT: shl [[REG]],0x1f | 326 ; CHECK-NEXT: shl [[REG]],0x1f |
| 267 ; CHECK-NEXT: sar [[REG]],0x1f | 327 ; CHECK-NEXT: sar [[REG]],0x1f |
| 328 ; MIPS32-LABEL: testFptosiFloat |
| 329 ; MIPS32: trunc.w.s |
| 330 ; MIPS32: mfc1 |
| 331 ; MIPS32: sll {{.*}},0x1f |
| 332 ; MIPS32: sra {{.*}},0x1f |
| 268 | 333 |
| 269 ; Test fptosi double to i1. | 334 ; Test fptosi double to i1. |
| 270 define internal i32 @testFptosiDouble(double %arg) { | 335 define internal i32 @testFptosiDouble(double %arg) { |
| 271 entry: | 336 entry: |
| 272 %arg_i1 = fptosi double %arg to i1 | 337 %arg_i1 = fptosi double %arg to i1 |
| 273 %result = sext i1 %arg_i1 to i32 | 338 %result = sext i1 %arg_i1 to i32 |
| 274 ret i32 %result | 339 ret i32 %result |
| 275 } | 340 } |
| 276 ; CHECK-LABEL: testFptosiDouble | 341 ; CHECK-LABEL: testFptosiDouble |
| 277 ; CHECK: cvttsd2si | 342 ; CHECK: cvttsd2si |
| 278 ; CHECK: and {{.*}},0x1 | 343 ; CHECK: and {{.*}},0x1 |
| 279 ; CHECK: movzx [[REG:.*]], | 344 ; CHECK: movzx [[REG:.*]], |
| 280 ; CHECK-NEXT: shl [[REG]],0x1f | 345 ; CHECK-NEXT: shl [[REG]],0x1f |
| 281 ; CHECK-NEXT: sar [[REG]],0x1f | 346 ; CHECK-NEXT: sar [[REG]],0x1f |
| 347 ; MIPS32-LABEL: testFptosiDouble |
| 348 ; MIPS32: trunc.w.d |
| 349 ; MIPS32: mfc1 |
| 350 ; MIPS32: sll {{.*}},0x1f |
| 351 ; MIPS32: sra {{.*}},0x1f |
| OLD | NEW |