Rewrite kMirOpSelect for all IF_ccZ opcodes.
Also improve special cases for ARM and add tests.
Change-Id: I06f575b9c7b547dbc431dbfadf2b927151fe16b9
diff --git a/compiler/dex/quick/arm/int_arm.cc b/compiler/dex/quick/arm/int_arm.cc
index 94c8844..fb2096f 100644
--- a/compiler/dex/quick/arm/int_arm.cc
+++ b/compiler/dex/quick/arm/int_arm.cc
@@ -172,19 +172,33 @@
RegLocation rl_src = mir_graph_->GetSrc(mir, 0);
RegLocation rl_dest = mir_graph_->GetDest(mir);
rl_src = LoadValue(rl_src, kCoreReg);
+ ConditionCode ccode = mir->meta.ccode;
if (mir->ssa_rep->num_uses == 1) {
// CONST case
int true_val = mir->dalvikInsn.vB;
int false_val = mir->dalvikInsn.vC;
rl_result = EvalLoc(rl_dest, kCoreReg, true);
- if ((true_val == 1) && (false_val == 0)) {
- OpRegRegImm(kOpRsub, rl_result.reg.GetReg(), rl_src.reg.GetReg(), 1);
- OpIT(kCondUlt, "");
- LoadConstant(rl_result.reg.GetReg(), 0);
+ // Change kCondNe to kCondEq for the special cases below.
+ if (ccode == kCondNe) {
+ ccode = kCondEq;
+ std::swap(true_val, false_val);
+ }
+ bool cheap_false_val = InexpensiveConstantInt(false_val);
+ if (cheap_false_val && ccode == kCondEq && (true_val == 0 || true_val == -1)) {
+ OpRegRegImm(kOpSub, rl_result.reg.GetReg(), rl_src.reg.GetReg(), -true_val);
+ DCHECK(last_lir_insn_->u.m.def_mask & ENCODE_CCODE);
+ OpIT(true_val == 0 ? kCondNe : kCondUge, "");
+ LoadConstant(rl_result.reg.GetReg(), false_val);
GenBarrier(); // Add a scheduling barrier to keep the IT shadow intact
- } else if (InexpensiveConstantInt(true_val) && InexpensiveConstantInt(false_val)) {
+ } else if (cheap_false_val && ccode == kCondEq && true_val == 1) {
+ OpRegRegImm(kOpRsub, rl_result.reg.GetReg(), rl_src.reg.GetReg(), 1);
+ DCHECK(last_lir_insn_->u.m.def_mask & ENCODE_CCODE);
+ OpIT(kCondLs, "");
+ LoadConstant(rl_result.reg.GetReg(), false_val);
+ GenBarrier(); // Add a scheduling barrier to keep the IT shadow intact
+ } else if (cheap_false_val && InexpensiveConstantInt(true_val)) {
OpRegImm(kOpCmp, rl_src.reg.GetReg(), 0);
- OpIT(kCondEq, "E");
+ OpIT(ccode, "E");
LoadConstant(rl_result.reg.GetReg(), true_val);
LoadConstant(rl_result.reg.GetReg(), false_val);
GenBarrier(); // Add a scheduling barrier to keep the IT shadow intact
@@ -195,7 +209,7 @@
LoadConstant(t_reg1, true_val);
LoadConstant(t_reg2, false_val);
OpRegImm(kOpCmp, rl_src.reg.GetReg(), 0);
- OpIT(kCondEq, "E");
+ OpIT(ccode, "E");
OpRegCopy(rl_result.reg.GetReg(), t_reg1);
OpRegCopy(rl_result.reg.GetReg(), t_reg2);
GenBarrier(); // Add a scheduling barrier to keep the IT shadow intact
@@ -209,13 +223,13 @@
rl_result = EvalLoc(rl_dest, kCoreReg, true);
OpRegImm(kOpCmp, rl_src.reg.GetReg(), 0);
if (rl_result.reg.GetReg() == rl_true.reg.GetReg()) { // Is the "true" case already in place?
- OpIT(kCondNe, "");
+ OpIT(NegateComparison(ccode), "");
OpRegCopy(rl_result.reg.GetReg(), rl_false.reg.GetReg());
} else if (rl_result.reg.GetReg() == rl_false.reg.GetReg()) { // False case in place?
- OpIT(kCondEq, "");
+ OpIT(ccode, "");
OpRegCopy(rl_result.reg.GetReg(), rl_true.reg.GetReg());
} else { // Normal - select between the two.
- OpIT(kCondEq, "E");
+ OpIT(ccode, "E");
OpRegCopy(rl_result.reg.GetReg(), rl_true.reg.GetReg());
OpRegCopy(rl_result.reg.GetReg(), rl_false.reg.GetReg());
}