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. 25define internal i32 @testAndTrue(i32 %arg) { 26entry: 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. 40define internal i32 @testOrTrue(i32 %arg) { 41entry: 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. 55define internal i32 @testXorTrue(i32 %arg) { 56entry: 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. 70define internal i32 @testTrunc(i32 %arg) { 71entry: 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. 84define internal i32 @testZextI8(i32 %arg) { 85entry: 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. 104define internal i32 @testZextI16(i32 %arg) { 105entry: 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. 127define internal i32 @testZextI32(i32 %arg) { 128entry: 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. 145define internal i64 @testZextI64(i32 %arg) { 146entry: 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. 167define internal i32 @testSextI8(i32 %arg) { 168entry: 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. 195define internal i32 @testSextI16(i32 %arg) { 196entry: 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. 224define internal i32 @testSextI32(i32 %arg) { 225entry: 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. 249define internal i64 @testSextI64(i32 %arg) { 250entry: 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. 280define 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 298define 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. 313define internal i32 @testFptosiFloat(float %arg) { 314entry: 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. 332define internal i32 @testFptosiDouble(double %arg) { 333entry: 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