OSDN Git Service

Fix ARM Om1 lowering for arithmetic, and test.
authorJan Voung <jvoung@chromium.org>
Mon, 6 Jul 2015 21:01:25 +0000 (14:01 -0700)
committerJan Voung <jvoung@chromium.org>
Mon, 6 Jul 2015 21:01:25 +0000 (14:01 -0700)
The original arithmetic lowering was introducing some
unused mov instructions from legalization (e.g., the upper
part of shift num bits -- which should be 0 anyway), and
div helper calls don't actually use the legalized
parameters (handled separately by lowerCall). These unused
instructions cause the Om1 allocator to assert that LRBegin
exists but LREnd does not.

BUG= https://code.google.com/p/nativeclient/issues/detail?id=4076
R=kschimpf@google.com

Review URL: https://codereview.chromium.org/1210073017.

src/IceTargetLoweringARM32.cpp
tests_lit/llvm2ice_tests/64bit.pnacl.ll
tests_lit/llvm2ice_tests/arith.ll
tests_lit/llvm2ice_tests/callindirect.pnacl.ll
tests_lit/llvm2ice_tests/unreachable.ll

index c090075..85294b0 100644 (file)
@@ -1103,48 +1103,114 @@ void TargetARM32::lowerArithmetic(const InstArithmetic *Inst) {
   Operand *Src0 = Inst->getSrc(0);
   Operand *Src1 = Inst->getSrc(1);
   if (Dest->getType() == IceType_i64) {
+    // These helper-call-involved instructions are lowered in this
+    // separate switch. This is because we would otherwise assume that
+    // we need to legalize Src0 to Src0RLo and Src0Hi. However, those go unused
+    // with helper calls, and such unused/redundant instructions will fail
+    // liveness analysis under -Om1 setting.
+    switch (Inst->getOp()) {
+    default:
+      break;
+    case InstArithmetic::Udiv:
+    case InstArithmetic::Sdiv:
+    case InstArithmetic::Urem:
+    case InstArithmetic::Srem: {
+      // Check for divide by 0 (ARM normally doesn't trap, but we want it
+      // to trap for NaCl). Src1Lo and Src1Hi may have already been legalized
+      // to a register, which will hide a constant source operand.
+      // Instead, check the not-yet-legalized Src1 to optimize-out a divide
+      // by 0 check.
+      if (auto *C64 = llvm::dyn_cast<ConstantInteger64>(Src1)) {
+        if (C64->getValue() == 0) {
+          _trap();
+          return;
+        }
+      } else {
+        Operand *Src1Lo = legalize(loOperand(Src1), Legal_Reg | Legal_Flex);
+        Operand *Src1Hi = legalize(hiOperand(Src1), Legal_Reg | Legal_Flex);
+        div0Check(IceType_i64, Src1Lo, Src1Hi);
+      }
+      // Technically, ARM has their own aeabi routines, but we can use the
+      // non-aeabi routine as well.  LLVM uses __aeabi_ldivmod for div,
+      // but uses the more standard __moddi3 for rem.
+      const char *HelperName = "";
+      switch (Inst->getOp()) {
+      default:
+        llvm_unreachable("Should have only matched div ops.");
+        break;
+      case InstArithmetic::Udiv:
+        HelperName = H_udiv_i64;
+        break;
+      case InstArithmetic::Sdiv:
+        HelperName = H_sdiv_i64;
+        break;
+      case InstArithmetic::Urem:
+        HelperName = H_urem_i64;
+        break;
+      case InstArithmetic::Srem:
+        HelperName = H_srem_i64;
+        break;
+      }
+      constexpr SizeT MaxSrcs = 2;
+      InstCall *Call = makeHelperCall(HelperName, Dest, MaxSrcs);
+      Call->addArg(Src0);
+      Call->addArg(Src1);
+      lowerCall(Call);
+      return;
+    }
+    }
     Variable *DestLo = llvm::cast<Variable>(loOperand(Dest));
     Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest));
     Variable *Src0RLo = legalizeToVar(loOperand(Src0));
     Variable *Src0RHi = legalizeToVar(hiOperand(Src0));
-    Operand *Src1Lo = legalize(loOperand(Src1), Legal_Reg | Legal_Flex);
-    Operand *Src1Hi = legalize(hiOperand(Src1), Legal_Reg | Legal_Flex);
+    Operand *Src1Lo = loOperand(Src1);
+    Operand *Src1Hi = hiOperand(Src1);
     Variable *T_Lo = makeReg(DestLo->getType());
     Variable *T_Hi = makeReg(DestHi->getType());
     switch (Inst->getOp()) {
     case InstArithmetic::_num:
       llvm_unreachable("Unknown arithmetic operator");
-      break;
+      return;
     case InstArithmetic::Add:
+      Src1Lo = legalize(Src1Lo, Legal_Reg | Legal_Flex);
+      Src1Hi = legalize(Src1Hi, Legal_Reg | Legal_Flex);
       _adds(T_Lo, Src0RLo, Src1Lo);
       _mov(DestLo, T_Lo);
       _adc(T_Hi, Src0RHi, Src1Hi);
       _mov(DestHi, T_Hi);
-      break;
+      return;
     case InstArithmetic::And:
+      Src1Lo = legalize(Src1Lo, Legal_Reg | Legal_Flex);
+      Src1Hi = legalize(Src1Hi, Legal_Reg | Legal_Flex);
       _and(T_Lo, Src0RLo, Src1Lo);
       _mov(DestLo, T_Lo);
       _and(T_Hi, Src0RHi, Src1Hi);
       _mov(DestHi, T_Hi);
-      break;
+      return;
     case InstArithmetic::Or:
+      Src1Lo = legalize(Src1Lo, Legal_Reg | Legal_Flex);
+      Src1Hi = legalize(Src1Hi, Legal_Reg | Legal_Flex);
       _orr(T_Lo, Src0RLo, Src1Lo);
       _mov(DestLo, T_Lo);
       _orr(T_Hi, Src0RHi, Src1Hi);
       _mov(DestHi, T_Hi);
-      break;
+      return;
     case InstArithmetic::Xor:
+      Src1Lo = legalize(Src1Lo, Legal_Reg | Legal_Flex);
+      Src1Hi = legalize(Src1Hi, Legal_Reg | Legal_Flex);
       _eor(T_Lo, Src0RLo, Src1Lo);
       _mov(DestLo, T_Lo);
       _eor(T_Hi, Src0RHi, Src1Hi);
       _mov(DestHi, T_Hi);
-      break;
+      return;
     case InstArithmetic::Sub:
+      Src1Lo = legalize(Src1Lo, Legal_Reg | Legal_Flex);
+      Src1Hi = legalize(Src1Hi, Legal_Reg | Legal_Flex);
       _subs(T_Lo, Src0RLo, Src1Lo);
       _mov(DestLo, T_Lo);
       _sbc(T_Hi, Src0RHi, Src1Hi);
       _mov(DestHi, T_Hi);
-      break;
+      return;
     case InstArithmetic::Mul: {
       // GCC 4.8 does:
       // a=b*c ==>
@@ -1176,7 +1242,8 @@ void TargetARM32::lowerArithmetic(const InstArithmetic *Inst) {
       _add(T_Hi, T_Hi1, T_Acc1);
       _mov(DestLo, T_Lo);
       _mov(DestHi, T_Hi);
-    } break;
+      return;
+    }
     case InstArithmetic::Shl: {
       // a=b<<c ==>
       // GCC 4.8 does:
@@ -1214,7 +1281,8 @@ void TargetARM32::lowerArithmetic(const InstArithmetic *Inst) {
       _mov(T_Lo, OperandARM32FlexReg::create(Func, IceType_i32, Src0RLo,
                                              OperandARM32::LSL, Src1RLo));
       _mov(DestLo, T_Lo);
-    } break;
+      return;
+    }
     case InstArithmetic::Lshr:
     // a=b>>c (unsigned) ==>
     // GCC 4.8 does:
@@ -1260,49 +1328,6 @@ void TargetARM32::lowerArithmetic(const InstArithmetic *Inst) {
       _mov(T_Hi, OperandARM32FlexReg::create(Func, IceType_i32, Src0RHi,
                                              RShiftKind, Src1RLo));
       _mov(DestHi, T_Hi);
-    } break;
-    case InstArithmetic::Udiv:
-    case InstArithmetic::Sdiv:
-    case InstArithmetic::Urem:
-    case InstArithmetic::Srem: {
-      // Check for divide by 0 (ARM normally doesn't trap, but we want it
-      // to trap for NaCl). Src1Lo and Src1Hi may have already been legalized
-      // to a register, which will hide a constant source operand.
-      // Instead, check the not-yet-legalized Src1 to optimize-out a divide
-      // by 0 check.
-      if (auto *C64 = llvm::dyn_cast<ConstantInteger64>(Src1)) {
-        if (C64->getValue() == 0) {
-          div0Check(IceType_i64, Src1Lo, Src1Hi);
-        }
-      } else {
-        div0Check(IceType_i64, Src1Lo, Src1Hi);
-      }
-      // Technically, ARM has their own aeabi routines, but we can use the
-      // non-aeabi routine as well.  LLVM uses __aeabi_ldivmod for div,
-      // but uses the more standard __moddi3 for rem.
-      const char *HelperName = "";
-      switch (Inst->getOp()) {
-      case InstArithmetic::Udiv:
-        HelperName = H_udiv_i64;
-        break;
-      case InstArithmetic::Sdiv:
-        HelperName = H_sdiv_i64;
-        break;
-      case InstArithmetic::Urem:
-        HelperName = H_urem_i64;
-        break;
-      case InstArithmetic::Srem:
-        HelperName = H_srem_i64;
-        break;
-      default:
-        llvm_unreachable("Should have only matched div ops.");
-        break;
-      }
-      constexpr SizeT MaxSrcs = 2;
-      InstCall *Call = makeHelperCall(HelperName, Dest, MaxSrcs);
-      Call->addArg(Inst->getSrc(0));
-      Call->addArg(Inst->getSrc(1));
-      lowerCall(Call);
       return;
     }
     case InstArithmetic::Fadd:
@@ -1311,95 +1336,119 @@ void TargetARM32::lowerArithmetic(const InstArithmetic *Inst) {
     case InstArithmetic::Fdiv:
     case InstArithmetic::Frem:
       llvm_unreachable("FP instruction with i64 type");
-      break;
-    }
-  } else if (isVectorType(Dest->getType())) {
-    UnimplementedError(Func->getContext()->getFlags());
-  } else { // Dest->getType() is non-i64 scalar
-    Variable *Src0R = legalizeToVar(Inst->getSrc(0));
-    Operand *Src1RF = legalize(Inst->getSrc(1), Legal_Reg | Legal_Flex);
-    Variable *T = makeReg(Dest->getType());
-    switch (Inst->getOp()) {
-    case InstArithmetic::_num:
-      llvm_unreachable("Unknown arithmetic operator");
-      break;
-    case InstArithmetic::Add: {
-      _add(T, Src0R, Src1RF);
-      _mov(Dest, T);
-    } break;
-    case InstArithmetic::And: {
-      _and(T, Src0R, Src1RF);
-      _mov(Dest, T);
-    } break;
-    case InstArithmetic::Or: {
-      _orr(T, Src0R, Src1RF);
-      _mov(Dest, T);
-    } break;
-    case InstArithmetic::Xor: {
-      _eor(T, Src0R, Src1RF);
-      _mov(Dest, T);
-    } break;
-    case InstArithmetic::Sub: {
-      _sub(T, Src0R, Src1RF);
-      _mov(Dest, T);
-    } break;
-    case InstArithmetic::Mul: {
-      Variable *Src1R = legalizeToVar(Src1RF);
-      _mul(T, Src0R, Src1R);
-      _mov(Dest, T);
-    } break;
-    case InstArithmetic::Shl:
-      _lsl(T, Src0R, Src1RF);
-      _mov(Dest, T);
-      break;
-    case InstArithmetic::Lshr:
-      _lsr(T, Src0R, Src1RF);
-      _mov(Dest, T);
-      break;
-    case InstArithmetic::Ashr:
-      _asr(T, Src0R, Src1RF);
-      _mov(Dest, T);
-      break;
-    case InstArithmetic::Udiv: {
-      constexpr bool IsRemainder = false;
-      lowerIDivRem(Dest, T, Src0R, Src1, &TargetARM32::_uxt,
-                   &TargetARM32::_udiv, H_udiv_i32, IsRemainder);
       return;
-    }
-    case InstArithmetic::Sdiv: {
-      constexpr bool IsRemainder = false;
-      lowerIDivRem(Dest, T, Src0R, Src1, &TargetARM32::_sxt,
-                   &TargetARM32::_sdiv, H_sdiv_i32, IsRemainder);
-      return;
-    }
-    case InstArithmetic::Urem: {
-      constexpr bool IsRemainder = true;
-      lowerIDivRem(Dest, T, Src0R, Src1, &TargetARM32::_uxt,
-                   &TargetARM32::_udiv, H_urem_i32, IsRemainder);
-      return;
-    }
-    case InstArithmetic::Srem: {
-      constexpr bool IsRemainder = true;
-      lowerIDivRem(Dest, T, Src0R, Src1, &TargetARM32::_sxt,
-                   &TargetARM32::_sdiv, H_srem_i32, IsRemainder);
+    case InstArithmetic::Udiv:
+    case InstArithmetic::Sdiv:
+    case InstArithmetic::Urem:
+    case InstArithmetic::Srem:
+      llvm_unreachable("Call-helper-involved instruction for i64 type "
+                       "should have already been handled before");
       return;
     }
-    case InstArithmetic::Fadd:
-      UnimplementedError(Func->getContext()->getFlags());
-      break;
-    case InstArithmetic::Fsub:
-      UnimplementedError(Func->getContext()->getFlags());
-      break;
-    case InstArithmetic::Fmul:
-      UnimplementedError(Func->getContext()->getFlags());
-      break;
-    case InstArithmetic::Fdiv:
-      UnimplementedError(Func->getContext()->getFlags());
-      break;
-    case InstArithmetic::Frem:
-      UnimplementedError(Func->getContext()->getFlags());
-      break;
-    }
+    return;
+  } else if (isVectorType(Dest->getType())) {
+    UnimplementedError(Func->getContext()->getFlags());
+    return;
+  }
+  // Dest->getType() is a non-i64 scalar.
+  Variable *Src0R = legalizeToVar(Src0);
+  Variable *T = makeReg(Dest->getType());
+  // Handle div/rem separately. They require a non-legalized Src1 to inspect
+  // whether or not Src1 is a non-zero constant. Once legalized it is more
+  // difficult to determine (constant may be moved to a register).
+  switch (Inst->getOp()) {
+  default:
+    break;
+  case InstArithmetic::Udiv: {
+    constexpr bool IsRemainder = false;
+    lowerIDivRem(Dest, T, Src0R, Src1, &TargetARM32::_uxt, &TargetARM32::_udiv,
+                 H_udiv_i32, IsRemainder);
+    return;
+  }
+  case InstArithmetic::Sdiv: {
+    constexpr bool IsRemainder = false;
+    lowerIDivRem(Dest, T, Src0R, Src1, &TargetARM32::_sxt, &TargetARM32::_sdiv,
+                 H_sdiv_i32, IsRemainder);
+    return;
+  }
+  case InstArithmetic::Urem: {
+    constexpr bool IsRemainder = true;
+    lowerIDivRem(Dest, T, Src0R, Src1, &TargetARM32::_uxt, &TargetARM32::_udiv,
+                 H_urem_i32, IsRemainder);
+    return;
+  }
+  case InstArithmetic::Srem: {
+    constexpr bool IsRemainder = true;
+    lowerIDivRem(Dest, T, Src0R, Src1, &TargetARM32::_sxt, &TargetARM32::_sdiv,
+                 H_srem_i32, IsRemainder);
+    return;
+  }
+  }
+
+  Operand *Src1RF = legalize(Src1, Legal_Reg | Legal_Flex);
+  switch (Inst->getOp()) {
+  case InstArithmetic::_num:
+    llvm_unreachable("Unknown arithmetic operator");
+    return;
+  case InstArithmetic::Add:
+    _add(T, Src0R, Src1RF);
+    _mov(Dest, T);
+    return;
+  case InstArithmetic::And:
+    _and(T, Src0R, Src1RF);
+    _mov(Dest, T);
+    return;
+  case InstArithmetic::Or:
+    _orr(T, Src0R, Src1RF);
+    _mov(Dest, T);
+    return;
+  case InstArithmetic::Xor:
+    _eor(T, Src0R, Src1RF);
+    _mov(Dest, T);
+    return;
+  case InstArithmetic::Sub:
+    _sub(T, Src0R, Src1RF);
+    _mov(Dest, T);
+    return;
+  case InstArithmetic::Mul: {
+    Variable *Src1R = legalizeToVar(Src1RF);
+    _mul(T, Src0R, Src1R);
+    _mov(Dest, T);
+    return;
+  }
+  case InstArithmetic::Shl:
+    _lsl(T, Src0R, Src1RF);
+    _mov(Dest, T);
+    return;
+  case InstArithmetic::Lshr:
+    _lsr(T, Src0R, Src1RF);
+    _mov(Dest, T);
+    return;
+  case InstArithmetic::Ashr:
+    _asr(T, Src0R, Src1RF);
+    _mov(Dest, T);
+    return;
+  case InstArithmetic::Udiv:
+  case InstArithmetic::Sdiv:
+  case InstArithmetic::Urem:
+  case InstArithmetic::Srem:
+    llvm_unreachable("Integer div/rem should have been handled earlier.");
+    return;
+  case InstArithmetic::Fadd:
+    UnimplementedError(Func->getContext()->getFlags());
+    return;
+  case InstArithmetic::Fsub:
+    UnimplementedError(Func->getContext()->getFlags());
+    return;
+  case InstArithmetic::Fmul:
+    UnimplementedError(Func->getContext()->getFlags());
+    return;
+  case InstArithmetic::Fdiv:
+    UnimplementedError(Func->getContext()->getFlags());
+    return;
+  case InstArithmetic::Frem:
+    UnimplementedError(Func->getContext()->getFlags());
+    return;
   }
 }
 
index 2460a24..b88babe 100644 (file)
 ; RUN:   --disassemble --target arm32 -i %s --args -O2 --skip-unimplemented \
 ; RUN:   | %if --need=target_ARM32 --need=allow_dump \
 ; RUN:   --command FileCheck --check-prefix ARM32 %s
+; RUN: %if --need=target_ARM32 --need=allow_dump \
+; RUN:   --command %p2i --filetype=asm --assemble --disassemble --target arm32 \
+; RUN:   -i %s --args -Om1 --skip-unimplemented \
+; RUN:   | %if --need=target_ARM32 --need=allow_dump \
+; RUN:   --command FileCheck --check-prefix ARM32 %s
 
 @__init_array_start = internal constant [0 x i8] zeroinitializer, align 4
 @__fini_array_start = internal constant [0 x i8] zeroinitializer, align 4
@@ -94,16 +99,16 @@ entry:
 ; ARM32:      sub     sp, {{.*}} #16
 ; ARM32:      str     {{.*}}, [sp, #4]
 ; ARM32:      str     {{.*}}, [sp]
-; ARM32:      mov     r0
-; ARM32:      mov     r1
+; ARM32:      {{mov|ldr}} r0
+; ARM32:      {{mov|ldr}} r1
 ; ARM32:      movw    r2, #123
 ; ARM32:      bl      {{.*}} ignore64BitArgNoInline
 ; ARM32:      add     sp, {{.*}} #16
 ; ARM32:      sub     sp, {{.*}} #16
 ; ARM32:      str     {{.*}}, [sp, #4]
 ; ARM32:      str     {{.*}}, [sp]
-; ARM32:      mov     r0
-; ARM32:      mov     r1
+; ARM32:      {{mov|ldr}} r0
+; ARM32:      {{mov|ldr}} r1
 ; ARM32:      movw    r2, #123
 ; ARM32:      bl      {{.*}} ignore64BitArgNoInline
 ; ARM32:      add     sp, {{.*}} #16
@@ -147,27 +152,28 @@ entry:
 ; ARM32:      movt    [[REG2:r.*]], {{.*}} ; 0x1234
 ; ARM32:      str     [[REG1]], [sp, #4]
 ; ARM32:      str     [[REG2]], [sp]
-; ARM32:      mov     r0, r2
-; ARM32:      mov     r1, r3
+; ARM32:      {{mov|ldr}} r0
+; ARM32:      {{mov|ldr}} r1
 ; ARM32:      movw    r2, #123
 ; ARM32:      bl      {{.*}} ignore64BitArgNoInline
 ; ARM32:      add     sp, {{.*}} #16
 
-define internal i64 @return64BitArg(i64 %a) {
+define internal i64 @return64BitArg(i64 %padding, i64 %a) {
 entry:
   ret i64 %a
 }
 ; CHECK-LABEL: return64BitArg
-; CHECK: mov     {{.*}},DWORD PTR [esp+0x4]
-; CHECK: mov     {{.*}},DWORD PTR [esp+0x8]
+; CHECK: mov     {{.*}},DWORD PTR [esp+0xc]
+; CHECK: mov     {{.*}},DWORD PTR [esp+0x10]
 ;
 ; OPTM1-LABEL: return64BitArg
-; OPTM1: mov     {{.*}},DWORD PTR [esp+0x4]
-; OPTM1: mov     {{.*}},DWORD PTR [esp+0x8]
+; OPTM1: mov     {{.*}},DWORD PTR [esp+0xc]
+; OPTM1: mov     {{.*}},DWORD PTR [esp+0x10]
 
-; Nothing to do for ARM O2 -- arg and return value are in r0,r1.
 ; ARM32-LABEL: return64BitArg
-; ARM32-NEXT: bx lr
+; ARM32: mov {{.*}}, r2
+; ARM32: mov {{.*}}, r3
+; ARM32: bx lr
 
 define internal i64 @return64BitConst() {
 entry:
@@ -1002,13 +1008,11 @@ if.end3:                                          ; preds = %if.then2, %if.end
 ; ARM32: cmpeq
 ; ARM32: moveq
 ; ARM32: movne
-; ARM32: beq
 ; ARM32: bl
 ; ARM32: cmp
 ; ARM32: cmpeq
 ; ARM32: moveq
 ; ARM32: movne
-; ARM32: beq
 ; ARM32: bl
 
 declare void @func()
@@ -1054,13 +1058,11 @@ if.end3:                                          ; preds = %if.end, %if.then2
 ; ARM32: cmpeq
 ; ARM32: movne
 ; ARM32: moveq
-; ARM32: beq
 ; ARM32: bl
 ; ARM32: cmp
 ; ARM32: cmpeq
 ; ARM32: movne
 ; ARM32: moveq
-; ARM32: beq
 ; ARM32: bl
 
 define internal void @icmpGt64(i64 %a, i64 %b, i64 %c, i64 %d) {
@@ -1108,13 +1110,11 @@ if.end3:                                          ; preds = %if.then2, %if.end
 ; ARM32: cmpeq
 ; ARM32: movhi
 ; ARM32: movls
-; ARM32: beq
 ; ARM32: bl
 ; ARM32: cmp
 ; ARM32: sbcs
 ; ARM32: movlt
 ; ARM32: movge
-; ARM32: beq
 ; ARM32: bl
 
 define internal void @icmpGe64(i64 %a, i64 %b, i64 %c, i64 %d) {
@@ -1162,13 +1162,11 @@ if.end3:                                          ; preds = %if.end, %if.then2
 ; ARM32: cmpeq
 ; ARM32: movcs
 ; ARM32: movcc
-; ARM32: beq
 ; ARM32: bl
 ; ARM32: cmp
 ; ARM32: sbcs
 ; ARM32: movge
 ; ARM32: movlt
-; ARM32: beq
 ; ARM32: bl
 
 define internal void @icmpLt64(i64 %a, i64 %b, i64 %c, i64 %d) {
@@ -1216,13 +1214,11 @@ if.end3:                                          ; preds = %if.then2, %if.end
 ; ARM32: cmpeq
 ; ARM32: movcc
 ; ARM32: movcs
-; ARM32: beq
 ; ARM32: bl
 ; ARM32: cmp
 ; ARM32: sbcs
 ; ARM32: movlt
 ; ARM32: movge
-; ARM32: beq
 ; ARM32: bl
 
 define internal void @icmpLe64(i64 %a, i64 %b, i64 %c, i64 %d) {
@@ -1270,13 +1266,11 @@ if.end3:                                          ; preds = %if.end, %if.then2
 ; ARM32: cmpeq
 ; ARM32: movls
 ; ARM32: movhi
-; ARM32: beq
 ; ARM32: bl
 ; ARM32: cmp
 ; ARM32: sbcs
 ; ARM32: movge
 ; ARM32: movlt
-; ARM32: beq
 ; ARM32: bl
 
 define internal i32 @icmpEq64Bool(i64 %a, i64 %b) {
index f6318ae..3fbdab6 100644 (file)
 ; RUN:   -i %s --args -O2 --mattr=hwdiv-arm --skip-unimplemented \
 ; RUN:   | %if --need=target_ARM32 --need=allow_dump \
 ; RUN:   --command FileCheck --check-prefix ARM32HWDIV %s
+; RUN: %if --need=target_ARM32 --need=allow_dump \
+; RUN:   --command %p2i --filetype=asm --assemble --disassemble --target arm32 \
+; RUN:   -i %s --args -Om1 --skip-unimplemented \
+; RUN:   | %if --need=target_ARM32 --need=allow_dump \
+; RUN:   --command FileCheck --check-prefix ARM32 %s
 
 define i32 @Add(i32 %a, i32 %b) {
 entry:
@@ -107,8 +112,8 @@ entry:
 ; CHECK-NOT: mul {{[0-9]+}}
 ;
 ; ARM32-LABEL: MulImm64
-; ARM32: mov {{.*}}, #99
-; ARM32: mov {{.*}}, #0
+; ARM32: movw {{.*}}, #99
+; ARM32: movw {{.*}}, #0
 ; ARM32: mul r
 ; ARM32: mla r
 ; ARM32: umull r
@@ -125,9 +130,9 @@ entry:
 ;
 ; ARM32-LABEL: Sdiv
 ; ARM32: tst [[DENOM:r.*]], [[DENOM]]
-; ARM32: bne [[LABEL:[0-9a-f]+]]
+; ARM32: bne
 ; ARM32: .word 0xe7fedef0
-; ARM32: [[LABEL]]: {{.*}} bl {{.*}} __divsi3
+; ARM32: {{.*}} bl {{.*}} __divsi3
 ; ARM32HWDIV-LABEL: Sdiv
 ; ARM32HWDIV: tst
 ; ARM32HWDIV: bne
index 152d649..9eca74d 100644 (file)
 ; RUN:   --disassemble --target arm32 -i %s --args -O2 --skip-unimplemented \
 ; RUN:   | %if --need=target_ARM32 --need=allow_dump \
 ; RUN:   --command FileCheck --check-prefix ARM32 %s
+; RUN: %if --need=target_ARM32 --need=allow_dump \
+; RUN:   --command %p2i --filetype=asm --assemble \
+; RUN:   --disassemble --target arm32 -i %s --args -Om1 --skip-unimplemented \
+; RUN:   | %if --need=target_ARM32 --need=allow_dump \
+; RUN:   --command FileCheck --check-prefix ARM32 %s
 
 @__init_array_start = internal constant [0 x i8] zeroinitializer, align 4
 @__fini_array_start = internal constant [0 x i8] zeroinitializer, align 4
index 1309b6f..383c9be 100644 (file)
 ; RUN:   --disassemble --target arm32 -i %s --args -O2 --skip-unimplemented \
 ; RUN:   | %if --need=target_ARM32 --need=allow_dump \
 ; RUN:   --command FileCheck --check-prefix ARM32 %s
+; RUN: %if --need=target_ARM32 --need=allow_dump \
+; RUN:   --command %p2i --filetype=asm --assemble \
+; RUN:   --disassemble --target arm32 -i %s --args -Om1 --skip-unimplemented \
+; RUN:   | %if --need=target_ARM32 --need=allow_dump \
+; RUN:   --command FileCheck --check-prefix ARM32 %s
 
 define internal i32 @divide(i32 %num, i32 %den) {
 entry: