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 35 define internal i32 @Add(i32 %a, i32 %b) { 36 entry: 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 47 define internal i32 @And(i32 %a, i32 %b) { 48 entry: 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 59 define internal i32 @Or(i32 %a, i32 %b) { 60 entry: 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 71 define internal i32 @Xor(i32 %a, i32 %b) { 72 entry: 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 83 define internal i32 @Sub(i32 %a, i32 %b) { 84 entry: 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 95 define internal i32 @Mul(i32 %a, i32 %b) { 96 entry: 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. 109 define internal i32 @MulImm(i32 %a, i32 %b) { 110 entry: 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. 127 define internal i64 @MulImm64(i64 %a) { 128 entry: 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 150 define internal i32 @Sdiv(i32 %a, i32 %b) { 151 entry: 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 175 define internal i32 @SdivConst(i32 %a) { 176 entry: 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 196 define internal i32 @Srem(i32 %a, i32 %b) { 197 entry: 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 220 define internal i32 @Udiv(i32 %a, i32 %b) { 221 entry: 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 242 define internal i32 @Urem(i32 %a, i32 %b) { 243 entry: 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 270 define internal i32 @ShlReloc(i32 %a) { 271 entry: 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 284 define internal i32 @LshrReloc(i32 %a) { 285 entry: 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 298 define internal i32 @AshrReloc(i32 %a) { 299 entry: 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