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