1; Assembly test for simple arithmetic operations. 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_ARM32 \ 8; RUN: --command %p2i --filetype=obj --disassemble --target arm32 \ 9; RUN: -i %s --args -O2 \ 10; RUN: | %if --need=target_ARM32 \ 11; RUN: --command FileCheck --check-prefix ARM32 --check-prefix ARM-OPT2 %s 12; RUN: %if --need=target_ARM32 \ 13; RUN: --command %p2i --filetype=obj --disassemble --target arm32 \ 14; RUN: -i %s --args -O2 --mattr=hwdiv-arm \ 15; RUN: | %if --need=target_ARM32 \ 16; RUN: --command FileCheck --check-prefix ARM32HWDIV %s 17; RUN: %if --need=target_ARM32 \ 18; RUN: --command %p2i --filetype=obj --disassemble --target arm32 \ 19; RUN: -i %s --args -Om1 \ 20; RUN: | %if --need=target_ARM32 \ 21; RUN: --command FileCheck --check-prefix ARM32 --check-prefix ARM32-OPTM1 %s 22; 23; RUN: %if --need=target_MIPS32 --need=allow_dump \ 24; RUN: --command %p2i --filetype=asm --assemble --disassemble --target mips32\ 25; RUN: -i %s --args -O2 \ 26; RUN: | %if --need=target_MIPS32 --need=allow_dump \ 27; RUN: --command FileCheck --check-prefix MIPS32 %s 28 29; RUN: %if --need=target_MIPS32 --need=allow_dump \ 30; RUN: --command %p2i --filetype=asm --assemble --disassemble --target mips32\ 31; RUN: -i %s --args -Om1 \ 32; RUN: | %if --need=target_MIPS32 --need=allow_dump \ 33; RUN: --command FileCheck --check-prefix MIPS32 %s 34 35define internal i32 @Add(i32 %a, i32 %b) { 36entry: 37 %add = add i32 %b, %a 38 ret i32 %add 39} 40; CHECK-LABEL: Add 41; CHECK: add e 42; ARM32-LABEL: Add 43; ARM32: add r 44; MIPS32-LABEL: Add 45; MIPS32: add 46 47define internal i32 @And(i32 %a, i32 %b) { 48entry: 49 %and = and i32 %b, %a 50 ret i32 %and 51} 52; CHECK-LABEL: And 53; CHECK: and e 54; ARM32-LABEL: And 55; ARM32: and r 56; MIPS32-LABEL: And 57; MIPS32: and 58 59define internal i32 @Or(i32 %a, i32 %b) { 60entry: 61 %or = or i32 %b, %a 62 ret i32 %or 63} 64; CHECK-LABEL: Or 65; CHECK: or e 66; ARM32-LABEL: Or 67; ARM32: orr r 68; MIPS32-LABEL: Or 69; MIPS32: or 70 71define internal i32 @Xor(i32 %a, i32 %b) { 72entry: 73 %xor = xor i32 %b, %a 74 ret i32 %xor 75} 76; CHECK-LABEL: Xor 77; CHECK: xor e 78; ARM32-LABEL: Xor 79; ARM32: eor r 80; MIPS32-LABEL: Xor 81; MIPS32: xor 82 83define internal i32 @Sub(i32 %a, i32 %b) { 84entry: 85 %sub = sub i32 %a, %b 86 ret i32 %sub 87} 88; CHECK-LABEL: Sub 89; CHECK: sub e 90; ARM32-LABEL: Sub 91; ARM32: sub r 92; MIPS32-LABEL: Sub 93; MIPS32: sub 94 95define internal i32 @Mul(i32 %a, i32 %b) { 96entry: 97 %mul = mul i32 %b, %a 98 ret i32 %mul 99} 100; CHECK-LABEL: Mul 101; CHECK: imul e 102; ARM32-LABEL: Mul 103; ARM32: mul r 104; MIPS32-LABEL: Mul 105; MIPS32: mul 106 107; Check for a valid ARM mul instruction where operands have to be registers. 108; On the other hand x86-32 does allow an immediate. 109define internal i32 @MulImm(i32 %a, i32 %b) { 110entry: 111 %mul = mul i32 %a, 99 112 ret i32 %mul 113} 114; CHECK-LABEL: MulImm 115; CHECK: imul e{{.*}},e{{.*}},0x63 116; ARM32-LABEL: MulImm 117; ARM32-OPTM1: mov {{.*}}, #99 118; ARM32-OPTM1: mul r{{.*}}, r{{.*}}, r{{.*}} 119; ARM32-OPT2: rsb [[T:r[0-9]+]], [[S:r[0-9]+]], [[S]], lsl #2 120; ARM32-OPT2-DAG: add [[T]], [[T]], [[S]], lsl #7 121; ARM32-OPT2-DAG: sub [[T]], [[T]], [[S]], lsl #5 122; MIPS32-LABEL: MulImm 123; MIPS32: mul 124 125; Check for a valid addressing mode in the x86-32 mul instruction when 126; the second source operand is an immediate. 127define internal i64 @MulImm64(i64 %a) { 128entry: 129 %mul = mul i64 %a, 99 130 ret i64 %mul 131} 132; NOTE: the lowering is currently a bit inefficient for small 64-bit constants. 133; The top bits of the immediate are 0, but the instructions modeling that 134; multiply by 0 are not eliminated (see expanded 64-bit ARM lowering). 135; CHECK-LABEL: MulImm64 136; CHECK: mov {{.*}},0x63 137; CHECK: mov {{.*}},0x0 138; CHECK-NOT: mul {{[0-9]+}} 139; 140; ARM32-LABEL: MulImm64 141; ARM32: mov {{.*}}, #99 142; ARM32: mov {{.*}}, #0 143; ARM32: mul r 144; ARM32: mla r 145; ARM32: umull r 146; ARM32: add r 147 148; MIPS32-LABEL: MulImm64 149 150define internal i32 @Sdiv(i32 %a, i32 %b) { 151entry: 152 %div = sdiv i32 %a, %b 153 ret i32 %div 154} 155; CHECK-LABEL: Sdiv 156; CHECK: cdq 157; CHECK: idiv e 158; 159; ARM32-LABEL: Sdiv 160; ARM32: tst [[DENOM:r.*]], [[DENOM]] 161; ARM32: bne 162; The following instruction is ".word 0xe7fedef0 = udf #60896 ; 0xede0". 163; ARM32: e7fedef0 164; ARM32: bl {{.*}} __divsi3 165; ARM32HWDIV-LABEL: Sdiv 166; ARM32HWDIV: tst 167; ARM32HWDIV: bne 168; ARM32HWDIV: sdiv 169 170; MIPS32-LABEL: Sdiv 171; MIPS32: div zero,{{.*}},[[REG:.*]] 172; MIPS32: teq [[REG]],zero,0x7 173; MIPS32: mflo 174 175define internal i32 @SdivConst(i32 %a) { 176entry: 177 %div = sdiv i32 %a, 219 178 ret i32 %div 179} 180; CHECK-LABEL: SdivConst 181; CHECK: cdq 182; CHECK: idiv e 183; 184; ARM32-LABEL: SdivConst 185; ARM32-NOT: tst 186; ARM32: bl {{.*}} __divsi3 187; ARM32HWDIV-LABEL: SdivConst 188; ARM32HWDIV-NOT: tst 189; ARM32HWDIV: sdiv 190 191; MIPS32-LABEL: SdivConst 192; MIPS32: div zero,{{.*}},[[REG:.*]] 193; MIPS32: teq [[REG]],zero,0x7 194; MIPS32: mflo 195 196define internal i32 @Srem(i32 %a, i32 %b) { 197entry: 198 %rem = srem i32 %a, %b 199 ret i32 %rem 200} 201; CHECK-LABEL: Srem 202; CHECK: cdq 203; CHECK: idiv e 204; 205; ARM32-LABEL: Srem 206; ARM32: tst [[DENOM:r.*]], [[DENOM]] 207; ARM32: bne 208; ARM32: bl {{.*}} __modsi3 209; ARM32HWDIV-LABEL: Srem 210; ARM32HWDIV: tst 211; ARM32HWDIV: bne 212; ARM32HWDIV: sdiv 213; ARM32HWDIV: mls 214 215; MIPS32-LABEL: Srem 216; MIPS32: div zero,{{.*}},[[REG:.*]] 217; MIPS32: teq [[REG]],zero,0x7 218; MIPS32: mfhi 219 220define internal i32 @Udiv(i32 %a, i32 %b) { 221entry: 222 %div = udiv i32 %a, %b 223 ret i32 %div 224} 225; CHECK-LABEL: Udiv 226; CHECK: div e 227; 228; ARM32-LABEL: Udiv 229; ARM32: tst [[DENOM:r.*]], [[DENOM]] 230; ARM32: bne 231; ARM32: bl {{.*}} __udivsi3 232; ARM32HWDIV-LABEL: Udiv 233; ARM32HWDIV: tst 234; ARM32HWDIV: bne 235; ARM32HWDIV: udiv 236 237; MIPS32-LABEL: Udiv 238; MIPS32: divu zero,{{.*}},[[REG:.*]] 239; MIPS32: teq [[REG]],zero,0x7 240; MIPS32: mflo 241 242define internal i32 @Urem(i32 %a, i32 %b) { 243entry: 244 %rem = urem i32 %a, %b 245 ret i32 %rem 246} 247; CHECK-LABEL: Urem 248; CHECK: div e 249; 250; ARM32-LABEL: Urem 251; ARM32: tst [[DENOM:r.*]], [[DENOM]] 252; ARM32: bne 253; ARM32: bl {{.*}} __umodsi3 254; ARM32HWDIV-LABEL: Urem 255; ARM32HWDIV: tst 256; ARM32HWDIV: bne 257; ARM32HWDIV: udiv 258; ARM32HWDIV: mls 259 260; MIPS32-LABEL: Urem 261; MIPS32: divu zero,{{.*}},[[REG:.*]] 262; MIPS32: teq [[REG]],zero,0x7 263; MIPS32: mfhi 264 265; The following tests check that shift instructions don't try to use a 266; ConstantRelocatable as an immediate operand. 267 268@G = internal global [4 x i8] zeroinitializer, align 4 269 270define internal i32 @ShlReloc(i32 %a) { 271entry: 272 %opnd = ptrtoint [4 x i8]* @G to i32 273 %result = shl i32 %a, %opnd 274 ret i32 %result 275} 276; CHECK-LABEL: ShlReloc 277; CHECK: shl {{.*}},cl 278 279; MIPS32-LABEL: ShlReloc 280; MIPS32: lui [[REG:.*]],{{.*}} R_MIPS_HI16 G 281; MIPS32: addiu [[REG]],[[REG]],{{.*}} R_MIPS_LO16 G 282; MIPS32: sllv {{.*}},{{.*}},[[REG]] 283 284define internal i32 @LshrReloc(i32 %a) { 285entry: 286 %opnd = ptrtoint [4 x i8]* @G to i32 287 %result = lshr i32 %a, %opnd 288 ret i32 %result 289} 290; CHECK-LABEL: LshrReloc 291; CHECK: shr {{.*}},cl 292 293; MIPS32-LABEL: LshrReloc 294; MIPS32: lui [[REG:.*]],{{.*}} R_MIPS_HI16 G 295; MIPS32: addiu [[REG]],[[REG]],{{.*}} R_MIPS_LO16 G 296; MIPS32: srlv {{.*}},{{.*}},[[REG]] 297 298define internal i32 @AshrReloc(i32 %a) { 299entry: 300 %opnd = ptrtoint [4 x i8]* @G to i32 301 %result = ashr i32 %a, %opnd 302 ret i32 %result 303} 304; CHECK-LABEL: AshrReloc 305; CHECK: sar {{.*}},cl 306 307; MIPS32-LABEL: AshrReloc 308; MIPS32: lui [[REG:.*]],{{.*}} R_MIPS_HI16 G 309; MIPS32: addiu [[REG]],[[REG]],{{.*}} R_MIPS_LO16 G 310; MIPS32: srav {{.*}},{{.*}},[[REG]] 311