More compile-time tuning

Small, but measurable, improvement.

Change-Id: Ie3c7180f9f9cbfb1729588e7a4b2cf6c6d291c95
diff --git a/compiler/dex/arena_bit_vector.cc b/compiler/dex/arena_bit_vector.cc
index 3fa9295..b921f61 100644
--- a/compiler/dex/arena_bit_vector.cc
+++ b/compiler/dex/arena_bit_vector.cc
@@ -87,12 +87,6 @@
   storage_[num >> 5] &= ~check_masks[num & 0x1f];
 }
 
-// Copy a whole vector to the other. Sizes must match.
-void ArenaBitVector::Copy(ArenaBitVector* src) {
-  DCHECK_EQ(storage_size_, src->GetStorageSize());
-  memcpy(storage_, src->GetRawStorage(), sizeof(uint32_t) * storage_size_);
-}
-
 // Intersect with another bit vector.  Sizes and expandability must be the same.
 void ArenaBitVector::Intersect(const ArenaBitVector* src) {
   DCHECK_EQ(storage_size_, src->GetStorageSize());
diff --git a/compiler/dex/arena_bit_vector.h b/compiler/dex/arena_bit_vector.h
index 8bcd628..24a7ce9 100644
--- a/compiler/dex/arena_bit_vector.h
+++ b/compiler/dex/arena_bit_vector.h
@@ -44,7 +44,7 @@
           DCHECK_EQ(bit_size_, p_bits_->GetStorageSize() * sizeof(uint32_t) * 8);
           DCHECK_EQ(bit_storage_, p_bits_->GetRawStorage());
 
-          if (bit_index_ >= bit_size_) return -1;
+          if (UNLIKELY(bit_index_ >= bit_size_)) return -1;
 
           uint32_t word_index = bit_index_ / 32;
           uint32_t word = bit_storage_[word_index];
@@ -54,7 +54,7 @@
             bit_index_ &= ~0x1f;
             do {
               word_index++;
-              if ((word_index * 32) >= bit_size_) {
+              if (UNLIKELY((word_index * 32) >= bit_size_)) {
                 bit_index_ = bit_size_;
                 return -1;
               }
@@ -95,7 +95,9 @@
     bool IsBitSet(unsigned int num);
     void ClearAllBits();
     void SetInitialBits(unsigned int num_bits);
-    void Copy(ArenaBitVector* src);
+    void Copy(ArenaBitVector* src) {
+      memcpy(storage_, src->GetRawStorage(), sizeof(uint32_t) * storage_size_);
+    }
     void Intersect(const ArenaBitVector* src2);
     void Union(const ArenaBitVector* src);
     // Are we equal to another bit vector?  Note: expandability attributes must also match.
diff --git a/compiler/dex/mir_graph.h b/compiler/dex/mir_graph.h
index 28ab283..15e15c3 100644
--- a/compiler/dex/mir_graph.h
+++ b/compiler/dex/mir_graph.h
@@ -580,11 +580,34 @@
   void SSATransformation();
   void CheckForDominanceFrontier(BasicBlock* dom_bb, const BasicBlock* succ_bb);
   void NullCheckElimination();
+  /*
+   * Type inference handling helpers.  Because Dalvik's bytecode is not fully typed,
+   * we have to do some work to figure out the sreg type.  For some operations it is
+   * clear based on the opcode (i.e. ADD_FLOAT v0, v1, v2), but for others (MOVE), we
+   * may never know the "real" type.
+   *
+   * We perform the type inference operation by using an iterative  walk over
+   * the graph, propagating types "defined" by typed opcodes to uses and defs in
+   * non-typed opcodes (such as MOVE).  The Setxx(index) helpers are used to set defined
+   * types on typed opcodes (such as ADD_INT).  The Setxx(index, is_xx) form is used to
+   * propagate types through non-typed opcodes such as PHI and MOVE.  The is_xx flag
+   * tells whether our guess of the type is based on a previously typed definition.
+   * If so, the defined type takes precedence.  Note that it's possible to have the same sreg
+   * show multiple defined types because dx treats constants as untyped bit patterns.
+   * The return value of the Setxx() helpers says whether or not the Setxx() action changed
+   * the current guess, and is used to know when to terminate the iterative walk.
+   */
   bool SetFp(int index, bool is_fp);
+  bool SetFp(int index);
   bool SetCore(int index, bool is_core);
+  bool SetCore(int index);
   bool SetRef(int index, bool is_ref);
+  bool SetRef(int index);
   bool SetWide(int index, bool is_wide);
+  bool SetWide(int index);
   bool SetHigh(int index, bool is_high);
+  bool SetHigh(int index);
+
   void AppendMIR(BasicBlock* bb, MIR* mir);
   void PrependMIR(BasicBlock* bb, MIR* mir);
   void InsertMIRAfter(BasicBlock* bb, MIR* current_mir, MIR* new_mir);
diff --git a/compiler/dex/quick/codegen_util.cc b/compiler/dex/quick/codegen_util.cc
index 9e0159e..e9db6a6 100644
--- a/compiler/dex/quick/codegen_util.cc
+++ b/compiler/dex/quick/codegen_util.cc
@@ -696,11 +696,11 @@
 
   for (lir = first_lir_insn_; lir != NULL; lir = NEXT_LIR(lir)) {
     lir->offset = offset;
-    if (lir->opcode >= 0) {
+    if (LIKELY(lir->opcode >= 0)) {
       if (!lir->flags.is_nop) {
         offset += lir->flags.size;
       }
-    } else if (lir->opcode == kPseudoPseudoAlign4) {
+    } else if (UNLIKELY(lir->opcode == kPseudoPseudoAlign4)) {
       if (offset & 0x2) {
         offset += 2;
         lir->operands[0] = 1;
diff --git a/compiler/dex/vreg_analysis.cc b/compiler/dex/vreg_analysis.cc
index 2551068..32fac0b 100644
--- a/compiler/dex/vreg_analysis.cc
+++ b/compiler/dex/vreg_analysis.cc
@@ -29,6 +29,16 @@
   return change;
 }
 
+bool MIRGraph::SetFp(int index) {
+  bool change = false;
+  if (!reg_location_[index].fp) {
+    reg_location_[index].fp = true;
+    reg_location_[index].defined = true;
+    change = true;
+  }
+  return change;
+}
+
 bool MIRGraph::SetCore(int index, bool is_core) {
   bool change = false;
   if (is_core && !reg_location_[index].defined) {
@@ -39,6 +49,16 @@
   return change;
 }
 
+bool MIRGraph::SetCore(int index) {
+  bool change = false;
+  if (!reg_location_[index].defined) {
+    reg_location_[index].core = true;
+    reg_location_[index].defined = true;
+    change = true;
+  }
+  return change;
+}
+
 bool MIRGraph::SetRef(int index, bool is_ref) {
   bool change = false;
   if (is_ref && !reg_location_[index].defined) {
@@ -49,6 +69,16 @@
   return change;
 }
 
+bool MIRGraph::SetRef(int index) {
+  bool change = false;
+  if (!reg_location_[index].defined) {
+    reg_location_[index].ref = true;
+    reg_location_[index].defined = true;
+    change = true;
+  }
+  return change;
+}
+
 bool MIRGraph::SetWide(int index, bool is_wide) {
   bool change = false;
   if (is_wide && !reg_location_[index].wide) {
@@ -58,6 +88,15 @@
   return change;
 }
 
+bool MIRGraph::SetWide(int index) {
+  bool change = false;
+  if (!reg_location_[index].wide) {
+    reg_location_[index].wide = true;
+    change = true;
+  }
+  return change;
+}
+
 bool MIRGraph::SetHigh(int index, bool is_high) {
   bool change = false;
   if (is_high && !reg_location_[index].high_word) {
@@ -67,6 +106,16 @@
   return change;
 }
 
+bool MIRGraph::SetHigh(int index) {
+  bool change = false;
+  if (!reg_location_[index].high_word) {
+    reg_location_[index].high_word = true;
+    change = true;
+  }
+  return change;
+}
+
+
 /*
  * Infer types and sizes.  We don't need to track change on sizes,
  * as it doesn't propagate.  We're guaranteed at least one pass through
@@ -84,21 +133,23 @@
     SSARepresentation *ssa_rep = mir->ssa_rep;
     if (ssa_rep) {
       int attrs = oat_data_flow_attributes_[mir->dalvikInsn.opcode];
+      const int* uses = ssa_rep->uses;
+      const int* defs = ssa_rep->defs;
 
       // Handle defs
       if (attrs & DF_DA) {
         if (attrs & DF_CORE_A) {
-          changed |= SetCore(ssa_rep->defs[0], true);
+          changed |= SetCore(defs[0]);
         }
         if (attrs & DF_REF_A) {
-          changed |= SetRef(ssa_rep->defs[0], true);
+          changed |= SetRef(defs[0]);
         }
         if (attrs & DF_A_WIDE) {
-          reg_location_[ssa_rep->defs[0]].wide = true;
-          reg_location_[ssa_rep->defs[1]].wide = true;
-          reg_location_[ssa_rep->defs[1]].high_word = true;
-          DCHECK_EQ(SRegToVReg(ssa_rep->defs[0])+1,
-          SRegToVReg(ssa_rep->defs[1]));
+          reg_location_[defs[0]].wide = true;
+          reg_location_[defs[1]].wide = true;
+          reg_location_[defs[1]].high_word = true;
+          DCHECK_EQ(SRegToVReg(defs[0])+1,
+          SRegToVReg(defs[1]));
         }
       }
 
@@ -106,17 +157,17 @@
       int next = 0;
       if (attrs & DF_UA) {
         if (attrs & DF_CORE_A) {
-          changed |= SetCore(ssa_rep->uses[next], true);
+          changed |= SetCore(uses[next]);
         }
         if (attrs & DF_REF_A) {
-          changed |= SetRef(ssa_rep->uses[next], true);
+          changed |= SetRef(uses[next]);
         }
         if (attrs & DF_A_WIDE) {
-          reg_location_[ssa_rep->uses[next]].wide = true;
-          reg_location_[ssa_rep->uses[next + 1]].wide = true;
-          reg_location_[ssa_rep->uses[next + 1]].high_word = true;
-          DCHECK_EQ(SRegToVReg(ssa_rep->uses[next])+1,
-          SRegToVReg(ssa_rep->uses[next + 1]));
+          reg_location_[uses[next]].wide = true;
+          reg_location_[uses[next + 1]].wide = true;
+          reg_location_[uses[next + 1]].high_word = true;
+          DCHECK_EQ(SRegToVReg(uses[next])+1,
+          SRegToVReg(uses[next + 1]));
           next += 2;
         } else {
           next++;
@@ -124,17 +175,17 @@
       }
       if (attrs & DF_UB) {
         if (attrs & DF_CORE_B) {
-          changed |= SetCore(ssa_rep->uses[next], true);
+          changed |= SetCore(uses[next]);
         }
         if (attrs & DF_REF_B) {
-          changed |= SetRef(ssa_rep->uses[next], true);
+          changed |= SetRef(uses[next]);
         }
         if (attrs & DF_B_WIDE) {
-          reg_location_[ssa_rep->uses[next]].wide = true;
-          reg_location_[ssa_rep->uses[next + 1]].wide = true;
-          reg_location_[ssa_rep->uses[next + 1]].high_word = true;
-          DCHECK_EQ(SRegToVReg(ssa_rep->uses[next])+1,
-                               SRegToVReg(ssa_rep->uses[next + 1]));
+          reg_location_[uses[next]].wide = true;
+          reg_location_[uses[next + 1]].wide = true;
+          reg_location_[uses[next + 1]].high_word = true;
+          DCHECK_EQ(SRegToVReg(uses[next])+1,
+                               SRegToVReg(uses[next + 1]));
           next += 2;
         } else {
           next++;
@@ -142,17 +193,17 @@
       }
       if (attrs & DF_UC) {
         if (attrs & DF_CORE_C) {
-          changed |= SetCore(ssa_rep->uses[next], true);
+          changed |= SetCore(uses[next]);
         }
         if (attrs & DF_REF_C) {
-          changed |= SetRef(ssa_rep->uses[next], true);
+          changed |= SetRef(uses[next]);
         }
         if (attrs & DF_C_WIDE) {
-          reg_location_[ssa_rep->uses[next]].wide = true;
-          reg_location_[ssa_rep->uses[next + 1]].wide = true;
-          reg_location_[ssa_rep->uses[next + 1]].high_word = true;
-          DCHECK_EQ(SRegToVReg(ssa_rep->uses[next])+1,
-          SRegToVReg(ssa_rep->uses[next + 1]));
+          reg_location_[uses[next]].wide = true;
+          reg_location_[uses[next + 1]].wide = true;
+          reg_location_[uses[next + 1]].high_word = true;
+          DCHECK_EQ(SRegToVReg(uses[next])+1,
+          SRegToVReg(uses[next + 1]));
         }
       }
 
@@ -162,27 +213,27 @@
           (mir->dalvikInsn.opcode == Instruction::RETURN_OBJECT)) {
         switch (cu_->shorty[0]) {
             case 'I':
-              changed |= SetCore(ssa_rep->uses[0], true);
+              changed |= SetCore(uses[0]);
               break;
             case 'J':
-              changed |= SetCore(ssa_rep->uses[0], true);
-              changed |= SetCore(ssa_rep->uses[1], true);
-              reg_location_[ssa_rep->uses[0]].wide = true;
-              reg_location_[ssa_rep->uses[1]].wide = true;
-              reg_location_[ssa_rep->uses[1]].high_word = true;
+              changed |= SetCore(uses[0]);
+              changed |= SetCore(uses[1]);
+              reg_location_[uses[0]].wide = true;
+              reg_location_[uses[1]].wide = true;
+              reg_location_[uses[1]].high_word = true;
               break;
             case 'F':
-              changed |= SetFp(ssa_rep->uses[0], true);
+              changed |= SetFp(uses[0]);
               break;
             case 'D':
-              changed |= SetFp(ssa_rep->uses[0], true);
-              changed |= SetFp(ssa_rep->uses[1], true);
-              reg_location_[ssa_rep->uses[0]].wide = true;
-              reg_location_[ssa_rep->uses[1]].wide = true;
-              reg_location_[ssa_rep->uses[1]].high_word = true;
+              changed |= SetFp(uses[0]);
+              changed |= SetFp(uses[1]);
+              reg_location_[uses[0]].wide = true;
+              reg_location_[uses[1]].wide = true;
+              reg_location_[uses[1]].high_word = true;
               break;
             case 'L':
-              changed |= SetRef(ssa_rep->uses[0], true);
+              changed |= SetRef(uses[0]);
               break;
             default: break;
         }
@@ -206,10 +257,10 @@
             SSARepresentation* tgt_rep = move_result_mir->ssa_rep;
             DCHECK(tgt_rep != NULL);
             tgt_rep->fp_def[0] = true;
-            changed |= SetFp(tgt_rep->defs[0], true);
+            changed |= SetFp(tgt_rep->defs[0]);
             if (shorty[0] == 'D') {
               tgt_rep->fp_def[1] = true;
-              changed |= SetFp(tgt_rep->defs[1], true);
+              changed |= SetFp(tgt_rep->defs[1]);
             }
           }
         }
@@ -217,8 +268,8 @@
         // If this is a non-static invoke, mark implicit "this"
         if (((mir->dalvikInsn.opcode != Instruction::INVOKE_STATIC) &&
             (mir->dalvikInsn.opcode != Instruction::INVOKE_STATIC_RANGE))) {
-          reg_location_[ssa_rep->uses[next]].defined = true;
-          reg_location_[ssa_rep->uses[next]].ref = true;
+          reg_location_[uses[next]].defined = true;
+          reg_location_[uses[next]].ref = true;
           next++;
         }
         uint32_t cpos = 1;
@@ -229,28 +280,28 @@
               case 'D':
                 ssa_rep->fp_use[i] = true;
                 ssa_rep->fp_use[i+1] = true;
-                reg_location_[ssa_rep->uses[i]].wide = true;
-                reg_location_[ssa_rep->uses[i+1]].wide = true;
-                reg_location_[ssa_rep->uses[i+1]].high_word = true;
-                DCHECK_EQ(SRegToVReg(ssa_rep->uses[i])+1, SRegToVReg(ssa_rep->uses[i+1]));
+                reg_location_[uses[i]].wide = true;
+                reg_location_[uses[i+1]].wide = true;
+                reg_location_[uses[i+1]].high_word = true;
+                DCHECK_EQ(SRegToVReg(uses[i])+1, SRegToVReg(uses[i+1]));
                 i++;
                 break;
               case 'J':
-                reg_location_[ssa_rep->uses[i]].wide = true;
-                reg_location_[ssa_rep->uses[i+1]].wide = true;
-                reg_location_[ssa_rep->uses[i+1]].high_word = true;
-                DCHECK_EQ(SRegToVReg(ssa_rep->uses[i])+1, SRegToVReg(ssa_rep->uses[i+1]));
-                changed |= SetCore(ssa_rep->uses[i], true);
+                reg_location_[uses[i]].wide = true;
+                reg_location_[uses[i+1]].wide = true;
+                reg_location_[uses[i+1]].high_word = true;
+                DCHECK_EQ(SRegToVReg(uses[i])+1, SRegToVReg(uses[i+1]));
+                changed |= SetCore(uses[i]);
                 i++;
                 break;
               case 'F':
                 ssa_rep->fp_use[i] = true;
                 break;
               case 'L':
-                changed |= SetRef(ssa_rep->uses[i], true);
+                changed |= SetRef(uses[i]);
                 break;
               default:
-                changed |= SetCore(ssa_rep->uses[i], true);
+                changed |= SetCore(uses[i]);
                 break;
             }
             i++;
@@ -260,11 +311,11 @@
 
       for (int i = 0; ssa_rep->fp_use && i< ssa_rep->num_uses; i++) {
         if (ssa_rep->fp_use[i])
-          changed |= SetFp(ssa_rep->uses[i], true);
+          changed |= SetFp(uses[i]);
         }
       for (int i = 0; ssa_rep->fp_def && i< ssa_rep->num_defs; i++) {
         if (ssa_rep->fp_def[i])
-          changed |= SetFp(ssa_rep->defs[i], true);
+          changed |= SetFp(defs[i]);
         }
       // Special-case handling for moves & Phi
       if (attrs & (DF_IS_MOVE | DF_NULL_TRANSFER_N)) {
@@ -276,14 +327,14 @@
          */
         bool is_phi = (static_cast<int>(mir->dalvikInsn.opcode) ==
                       kMirOpPhi);
-        RegLocation rl_temp = reg_location_[ssa_rep->defs[0]];
+        RegLocation rl_temp = reg_location_[defs[0]];
         bool defined_fp = rl_temp.defined && rl_temp.fp;
         bool defined_core = rl_temp.defined && rl_temp.core;
         bool defined_ref = rl_temp.defined && rl_temp.ref;
         bool is_wide = rl_temp.wide || ((attrs & DF_A_WIDE) != 0);
         bool is_high = is_phi && rl_temp.wide && rl_temp.high_word;
         for (int i = 0; i < ssa_rep->num_uses; i++) {
-          rl_temp = reg_location_[ssa_rep->uses[i]];
+          rl_temp = reg_location_[uses[i]];
           defined_fp |= rl_temp.defined && rl_temp.fp;
           defined_core |= rl_temp.defined && rl_temp.core;
           defined_ref |= rl_temp.defined && rl_temp.ref;
@@ -303,26 +354,26 @@
                        << " has both fp and core/ref uses for same def.";
           cu_->disable_opt |= (1 << kPromoteRegs);
         }
-        changed |= SetFp(ssa_rep->defs[0], defined_fp);
-        changed |= SetCore(ssa_rep->defs[0], defined_core);
-        changed |= SetRef(ssa_rep->defs[0], defined_ref);
-        changed |= SetWide(ssa_rep->defs[0], is_wide);
-        changed |= SetHigh(ssa_rep->defs[0], is_high);
+        changed |= SetFp(defs[0], defined_fp);
+        changed |= SetCore(defs[0], defined_core);
+        changed |= SetRef(defs[0], defined_ref);
+        changed |= SetWide(defs[0], is_wide);
+        changed |= SetHigh(defs[0], is_high);
         if (attrs & DF_A_WIDE) {
-          changed |= SetWide(ssa_rep->defs[1], true);
-          changed |= SetHigh(ssa_rep->defs[1], true);
+          changed |= SetWide(defs[1]);
+          changed |= SetHigh(defs[1]);
         }
         for (int i = 0; i < ssa_rep->num_uses; i++) {
-          changed |= SetFp(ssa_rep->uses[i], defined_fp);
-          changed |= SetCore(ssa_rep->uses[i], defined_core);
-          changed |= SetRef(ssa_rep->uses[i], defined_ref);
-          changed |= SetWide(ssa_rep->uses[i], is_wide);
-          changed |= SetHigh(ssa_rep->uses[i], is_high);
+          changed |= SetFp(uses[i], defined_fp);
+          changed |= SetCore(uses[i], defined_core);
+          changed |= SetRef(uses[i], defined_ref);
+          changed |= SetWide(uses[i], is_wide);
+          changed |= SetHigh(uses[i], is_high);
         }
         if (attrs & DF_A_WIDE) {
           DCHECK_EQ(ssa_rep->num_uses, 2);
-          changed |= SetWide(ssa_rep->uses[1], true);
-          changed |= SetHigh(ssa_rep->uses[1], true);
+          changed |= SetWide(uses[1]);
+          changed |= SetHigh(uses[1]);
         }
       }
     }