Implement InexpensiveConstantInt(., opcode) for ARM.

Fix kThumb2{Add,Sub}RRI12 to be used for their full range.
Add ORN for completeness.

Change-Id: I49a51541fa9ea085d4674b9131d8dd94da5337f3
diff --git a/compiler/dex/quick/arm/utility_arm.cc b/compiler/dex/quick/arm/utility_arm.cc
index 7168b9f..117d8f0 100644
--- a/compiler/dex/quick/arm/utility_arm.cc
+++ b/compiler/dex/quick/arm/utility_arm.cc
@@ -97,31 +97,11 @@
   return load_pc_rel;
 }
 
-static int LeadingZeros(uint32_t val) {
-  uint32_t alt;
-  int32_t n;
-  int32_t count;
-
-  count = 16;
-  n = 32;
-  do {
-    alt = val >> count;
-    if (alt != 0) {
-      n = n - count;
-      val = alt;
-    }
-    count >>= 1;
-  } while (count);
-  return n - val;
-}
-
 /*
  * Determine whether value can be encoded as a Thumb2 modified
  * immediate.  If not, return -1.  If so, return i:imm3:a:bcdefgh form.
  */
 int ArmMir2Lir::ModifiedImmediate(uint32_t value) {
-  int32_t z_leading;
-  int32_t z_trailing;
   uint32_t b0 = value & 0xff;
 
   /* Note: case of value==0 must use 0:000:0:0000000 encoding */
@@ -135,8 +115,8 @@
   if (value == ((b0 << 24) | (b0 << 8)))
     return (0x2 << 8) | b0; /* 0:010:a:bcdefgh */
   /* Can we do it with rotation? */
-  z_leading = LeadingZeros(value);
-  z_trailing = 32 - LeadingZeros(~value & (value - 1));
+  int z_leading = CLZ(value);
+  int z_trailing = CTZ(value);
   /* A run of eight or fewer active bits? */
   if ((z_leading + z_trailing) < 24)
     return -1;  /* No - bail */
@@ -152,6 +132,64 @@
   return (ModifiedImmediate(value) >= 0) || (ModifiedImmediate(~value) >= 0);
 }
 
+bool ArmMir2Lir::InexpensiveConstantInt(int32_t value, Instruction::Code opcode) {
+  switch (opcode) {
+    case Instruction::ADD_INT:
+    case Instruction::ADD_INT_2ADDR:
+    case Instruction::SUB_INT:
+    case Instruction::SUB_INT_2ADDR:
+      if ((value >> 12) == (value >> 31)) {  // Signed 12-bit, RRI12 versions of ADD/SUB.
+        return true;
+      }
+      FALLTHROUGH_INTENDED;
+    case Instruction::IF_EQ:
+    case Instruction::IF_NE:
+    case Instruction::IF_LT:
+    case Instruction::IF_GE:
+    case Instruction::IF_GT:
+    case Instruction::IF_LE:
+      return (ModifiedImmediate(value) >= 0) || (ModifiedImmediate(-value) >= 0);
+    case Instruction::SHL_INT:
+    case Instruction::SHL_INT_2ADDR:
+    case Instruction::SHR_INT:
+    case Instruction::SHR_INT_2ADDR:
+    case Instruction::USHR_INT:
+    case Instruction::USHR_INT_2ADDR:
+      return true;
+    case Instruction::AND_INT:
+    case Instruction::AND_INT_2ADDR:
+    case Instruction::AND_INT_LIT16:
+    case Instruction::AND_INT_LIT8:
+    case Instruction::OR_INT:
+    case Instruction::OR_INT_2ADDR:
+    case Instruction::OR_INT_LIT16:
+    case Instruction::OR_INT_LIT8:
+      return (ModifiedImmediate(value) >= 0) || (ModifiedImmediate(~value) >= 0);
+    case Instruction::XOR_INT:
+    case Instruction::XOR_INT_2ADDR:
+    case Instruction::XOR_INT_LIT16:
+    case Instruction::XOR_INT_LIT8:
+      return (ModifiedImmediate(value) >= 0);
+    case Instruction::MUL_INT:
+    case Instruction::MUL_INT_2ADDR:
+    case Instruction::MUL_INT_LIT8:
+    case Instruction::MUL_INT_LIT16:
+    case Instruction::DIV_INT:
+    case Instruction::DIV_INT_2ADDR:
+    case Instruction::DIV_INT_LIT8:
+    case Instruction::DIV_INT_LIT16:
+    case Instruction::REM_INT:
+    case Instruction::REM_INT_2ADDR:
+    case Instruction::REM_INT_LIT8:
+    case Instruction::REM_INT_LIT16: {
+      EasyMultiplyOp ops[2];
+      return GetEasyMultiplyTwoOps(value, ops);
+    }
+    default:
+      return false;
+  }
+}
+
 bool ArmMir2Lir::InexpensiveConstantFloat(int32_t value) {
   return EncodeImmSingle(value) >= 0;
 }
@@ -510,7 +548,7 @@
           op = (op == kOpAdd) ? kOpSub : kOpAdd;
         }
       }
-      if (mod_imm < 0 && (abs_value & 0x3ff) == abs_value) {
+      if (mod_imm < 0 && (abs_value >> 12) == 0) {
         // This is deliberately used only if modified immediate encoding is inadequate since
         // we sometimes actually use the flags for small values but not necessarily low regs.
         if (op == kOpAdd)
@@ -542,6 +580,12 @@
     case kOpOr:
       opcode = kThumb2OrrRRI8M;
       alt_opcode = kThumb2OrrRRR;
+      if (mod_imm < 0) {
+        mod_imm = ModifiedImmediate(~value);
+        if (mod_imm >= 0) {
+          opcode = kThumb2OrnRRI8M;
+        }
+      }
       break;
     case kOpAnd:
       if (mod_imm < 0) {