Compiler constant handling rework

In preparation for de-optimization, reworked the constant
handling mechanism.  Also took advantage of knowledge of
constant operands (particularly for long operations).

Significant performance improvements for Mandelbrot
(~60 seconds to ~34 seconds).  Minor improvements in other
benchmarks.

The new constant handling breaks two of the existing
optimization passes: "Skip Large Method" and "Load/Store
Elimization."

I don't intend to update the large method optimization
because it will be superceeded by the upcoming interpreter/
fingerprinting mechanism.  Leaving the code in place for
now in order to compare compile-time improvements with
fingerprinting/interpret.  All related code will be deleted
when that is complete.

The load/store elimination pass needs some rework to handle
uses of multiple-register loads and stores.  It will be
updated & restored in a future CL.

Change-Id: Ia979abaf51b8ae81bbb0428031cbcea854625fac
diff --git a/src/compiler/codegen/gen_common.cc b/src/compiler/codegen/gen_common.cc
index 1d64a71..a4c8d0c 100644
--- a/src/compiler/codegen/gen_common.cc
+++ b/src/compiler/codegen/gen_common.cc
@@ -55,7 +55,7 @@
                             ThrowKind kind)
 {
   LIR* tgt = RawLIR(cu, 0, kPseudoThrowTarget, kind,
-                    cu->current_dalvik_offset);
+                    cu->current_dalvik_offset, reg, imm_val);
   LIR* branch;
   if (c_code == kCondAl) {
     branch = OpUnconditionalBranch(cu, tgt);
@@ -89,23 +89,6 @@
   return branch;
 }
 
-// Convert relation of src1/src2 to src2/src1
-ConditionCode FlipComparisonOrder(ConditionCode before) {
-  ConditionCode res;
-  switch (before) {
-    case kCondEq: res = kCondEq; break;
-    case kCondNe: res = kCondNe; break;
-    case kCondLt: res = kCondGt; break;
-    case kCondGt: res = kCondLt; break;
-    case kCondLe: res = kCondGe; break;
-    case kCondGe: res = kCondLe; break;
-    default:
-      res = static_cast<ConditionCode>(0);
-      LOG(FATAL) << "Unexpected ccode " << before;
-  }
-  return res;
-}
-
 void Codegen::GenCompareAndBranch(CompilationUnit* cu, Instruction::Code opcode,
                                   RegLocation rl_src1, RegLocation rl_src2, LIR* taken,
                                   LIR* fall_through)
@@ -146,12 +129,12 @@
   rl_src1 = LoadValue(cu, rl_src1, kCoreReg);
   // Is this really an immediate comparison?
   if (rl_src2.is_const) {
-    int immval = cu->constant_values[rl_src2.orig_sreg];
     // If it's already live in a register or not easily materialized, just keep going
     RegLocation rl_temp = UpdateLoc(cu, rl_src2);
-    if ((rl_temp.location == kLocDalvikFrame) && InexpensiveConstant(rl_src1.low_reg, immval)) {
+    if ((rl_temp.location == kLocDalvikFrame) &&
+        InexpensiveConstantInt(ConstantValue(cu, rl_src2))) {
       // OK - convert this to a compare immediate and branch
-      OpCmpImmBranch(cu, cond, rl_src1.low_reg, immval, taken);
+      OpCmpImmBranch(cu, cond, rl_src1.low_reg, ConstantValue(cu, rl_src2), taken);
       OpUnconditionalBranch(cu, fall_through);
       return;
     }
@@ -614,6 +597,18 @@
       case kThrowNullPointer:
         func_offset = ENTRYPOINT_OFFSET(pThrowNullPointerFromCode);
         break;
+      case kThrowConstantArrayBounds: // v1 is length reg (for Arm/Mips), v2 constant index
+        // v1 holds the constant array index.  Mips/Arm uses v2 for length, x86 reloads.
+        if (target_x86) {
+          OpRegMem(cu, kOpMov, TargetReg(kArg1), v1, mirror::Array::LengthOffset().Int32Value());
+        } else {
+          OpRegCopy(cu, TargetReg(kArg1), v1);
+        }
+        // Make sure the following LoadConstant doesn't mess with kArg1.
+        LockTemp(cu, TargetReg(kArg1));
+        LoadConstant(cu, TargetReg(kArg0), v2);
+        func_offset = ENTRYPOINT_OFFSET(pThrowArrayBoundsFromCode);
+        break;
       case kThrowArrayBounds:
         // Move v1 (array index) to kArg0 and v2 (array length) to kArg1
         if (v2 != TargetReg(kArg0)) {
@@ -1602,9 +1597,14 @@
       break;
     case Instruction::MUL_LONG:
     case Instruction::MUL_LONG_2ADDR:
-      call_out = true;
-      ret_reg = TargetReg(kRet0);
-      func_offset = ENTRYPOINT_OFFSET(pLmul);
+      if (cu->instruction_set == kThumb2) {
+        GenMulLong(cu, rl_dest, rl_src1, rl_src2);
+        return false;
+      } else {
+        call_out = true;
+        ret_reg = TargetReg(kRet0);
+        func_offset = ENTRYPOINT_OFFSET(pLmul);
+      }
       break;
     case Instruction::DIV_LONG:
     case Instruction::DIV_LONG_2ADDR: