Fix ARM Om1 lowering for arithmetic, and test.
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.
diff --git a/src/IceTargetLoweringARM32.cpp b/src/IceTargetLoweringARM32.cpp
index c090075..85294b0 100644
--- a/src/IceTargetLoweringARM32.cpp
+++ b/src/IceTargetLoweringARM32.cpp
@@ -1103,48 +1103,114 @@
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 @@
_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 @@
_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 @@
_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 @@
case InstArithmetic::Fdiv:
case InstArithmetic::Frem:
llvm_unreachable("FP instruction with i64 type");
- break;
+ return;
+ 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;
}
+ return;
} 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);
- 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;
+ }
+ // 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;
}
}
diff --git a/tests_lit/llvm2ice_tests/64bit.pnacl.ll b/tests_lit/llvm2ice_tests/64bit.pnacl.ll
index 2460a24..b88babe 100644
--- a/tests_lit/llvm2ice_tests/64bit.pnacl.ll
+++ b/tests_lit/llvm2ice_tests/64bit.pnacl.ll
@@ -18,6 +18,11 @@
; 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 @@
; 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 @@
; 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 @@
; 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 @@
; 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 @@
; 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 @@
; 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 @@
; 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 @@
; 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) {
diff --git a/tests_lit/llvm2ice_tests/arith.ll b/tests_lit/llvm2ice_tests/arith.ll
index f6318ae..3fbdab6 100644
--- a/tests_lit/llvm2ice_tests/arith.ll
+++ b/tests_lit/llvm2ice_tests/arith.ll
@@ -17,6 +17,11 @@
; 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 @@
; 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 @@
;
; 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
diff --git a/tests_lit/llvm2ice_tests/callindirect.pnacl.ll b/tests_lit/llvm2ice_tests/callindirect.pnacl.ll
index 152d649..9eca74d 100644
--- a/tests_lit/llvm2ice_tests/callindirect.pnacl.ll
+++ b/tests_lit/llvm2ice_tests/callindirect.pnacl.ll
@@ -20,6 +20,11 @@
; 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
diff --git a/tests_lit/llvm2ice_tests/unreachable.ll b/tests_lit/llvm2ice_tests/unreachable.ll
index 1309b6f..383c9be 100644
--- a/tests_lit/llvm2ice_tests/unreachable.ll
+++ b/tests_lit/llvm2ice_tests/unreachable.ll
@@ -12,6 +12,11 @@
; 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: