Avoid Cache*LoweringInfo pass when there's no GET/PUT/INVOKE.

Add new data flow flags indicating instance/static field
access. Record merged flags of all insns and use them to skip
the CacheFieldLoweringInfo pass if the method uses no fields
and the CacheMethodLoweringInfo pass if it has no invokes.

Change-Id: I36a36b438ca9b0f104a7baddc0497d736495cc3c
diff --git a/compiler/dex/bb_optimizations.h b/compiler/dex/bb_optimizations.h
index 1a90ca8..1ad4958 100644
--- a/compiler/dex/bb_optimizations.h
+++ b/compiler/dex/bb_optimizations.h
@@ -34,6 +34,10 @@
   void Start(CompilationUnit* cUnit) const {
     cUnit->mir_graph->DoCacheFieldLoweringInfo();
   }
+
+  bool Gate(const CompilationUnit *cUnit) const {
+    return cUnit->mir_graph->HasFieldAccess();
+  }
 };
 
 /**
@@ -48,6 +52,10 @@
   void Start(CompilationUnit* cUnit) const {
     cUnit->mir_graph->DoCacheMethodLoweringInfo();
   }
+
+  bool Gate(const CompilationUnit *cUnit) const {
+    return cUnit->mir_graph->HasInvokes();
+  }
 };
 
 /**
diff --git a/compiler/dex/mir_dataflow.cc b/compiler/dex/mir_dataflow.cc
index c3954fe..1c0205d 100644
--- a/compiler/dex/mir_dataflow.cc
+++ b/compiler/dex/mir_dataflow.cc
@@ -277,88 +277,88 @@
   DF_UA | DF_UB | DF_UC | DF_NULL_CHK_1 | DF_RANGE_CHK_2 | DF_REF_B | DF_CORE_C | DF_LVN,
 
   // 52 IGET vA, vB, field@CCCC
-  DF_DA | DF_UB | DF_NULL_CHK_0 | DF_REF_B | DF_LVN,
+  DF_DA | DF_UB | DF_NULL_CHK_0 | DF_REF_B | DF_IFIELD | DF_LVN,
 
   // 53 IGET_WIDE vA, vB, field@CCCC
-  DF_DA | DF_A_WIDE | DF_UB | DF_NULL_CHK_0 | DF_REF_B | DF_LVN,
+  DF_DA | DF_A_WIDE | DF_UB | DF_NULL_CHK_0 | DF_REF_B | DF_IFIELD | DF_LVN,
 
   // 54 IGET_OBJECT vA, vB, field@CCCC
-  DF_DA | DF_UB | DF_NULL_CHK_0 | DF_REF_A | DF_REF_B | DF_LVN,
+  DF_DA | DF_UB | DF_NULL_CHK_0 | DF_REF_A | DF_REF_B | DF_IFIELD | DF_LVN,
 
   // 55 IGET_BOOLEAN vA, vB, field@CCCC
-  DF_DA | DF_UB | DF_NULL_CHK_0 | DF_REF_B | DF_LVN,
+  DF_DA | DF_UB | DF_NULL_CHK_0 | DF_REF_B | DF_IFIELD | DF_LVN,
 
   // 56 IGET_BYTE vA, vB, field@CCCC
-  DF_DA | DF_UB | DF_NULL_CHK_0 | DF_REF_B | DF_LVN,
+  DF_DA | DF_UB | DF_NULL_CHK_0 | DF_REF_B | DF_IFIELD | DF_LVN,
 
   // 57 IGET_CHAR vA, vB, field@CCCC
-  DF_DA | DF_UB | DF_NULL_CHK_0 | DF_REF_B | DF_LVN,
+  DF_DA | DF_UB | DF_NULL_CHK_0 | DF_REF_B | DF_IFIELD | DF_LVN,
 
   // 58 IGET_SHORT vA, vB, field@CCCC
-  DF_DA | DF_UB | DF_NULL_CHK_0 | DF_REF_B | DF_LVN,
+  DF_DA | DF_UB | DF_NULL_CHK_0 | DF_REF_B | DF_IFIELD | DF_LVN,
 
   // 59 IPUT vA, vB, field@CCCC
-  DF_UA | DF_UB | DF_NULL_CHK_1 | DF_REF_B | DF_LVN,
+  DF_UA | DF_UB | DF_NULL_CHK_1 | DF_REF_B | DF_IFIELD | DF_LVN,
 
   // 5A IPUT_WIDE vA, vB, field@CCCC
-  DF_UA | DF_A_WIDE | DF_UB | DF_NULL_CHK_2 | DF_REF_B | DF_LVN,
+  DF_UA | DF_A_WIDE | DF_UB | DF_NULL_CHK_2 | DF_REF_B | DF_IFIELD | DF_LVN,
 
   // 5B IPUT_OBJECT vA, vB, field@CCCC
-  DF_UA | DF_UB | DF_NULL_CHK_1 | DF_REF_A | DF_REF_B | DF_LVN,
+  DF_UA | DF_UB | DF_NULL_CHK_1 | DF_REF_A | DF_REF_B | DF_IFIELD | DF_LVN,
 
   // 5C IPUT_BOOLEAN vA, vB, field@CCCC
-  DF_UA | DF_UB | DF_NULL_CHK_1 | DF_REF_B | DF_LVN,
+  DF_UA | DF_UB | DF_NULL_CHK_1 | DF_REF_B | DF_IFIELD | DF_LVN,
 
   // 5D IPUT_BYTE vA, vB, field@CCCC
-  DF_UA | DF_UB | DF_NULL_CHK_1 | DF_REF_B | DF_LVN,
+  DF_UA | DF_UB | DF_NULL_CHK_1 | DF_REF_B | DF_IFIELD | DF_LVN,
 
   // 5E IPUT_CHAR vA, vB, field@CCCC
-  DF_UA | DF_UB | DF_NULL_CHK_1 | DF_REF_B | DF_LVN,
+  DF_UA | DF_UB | DF_NULL_CHK_1 | DF_REF_B | DF_IFIELD | DF_LVN,
 
   // 5F IPUT_SHORT vA, vB, field@CCCC
-  DF_UA | DF_UB | DF_NULL_CHK_1 | DF_REF_B | DF_LVN,
+  DF_UA | DF_UB | DF_NULL_CHK_1 | DF_REF_B | DF_IFIELD | DF_LVN,
 
   // 60 SGET vAA, field@BBBB
-  DF_DA | DF_UMS,
+  DF_DA | DF_SFIELD | DF_UMS,
 
   // 61 SGET_WIDE vAA, field@BBBB
-  DF_DA | DF_A_WIDE | DF_UMS,
+  DF_DA | DF_A_WIDE | DF_SFIELD | DF_UMS,
 
   // 62 SGET_OBJECT vAA, field@BBBB
-  DF_DA | DF_REF_A | DF_UMS,
+  DF_DA | DF_REF_A | DF_SFIELD | DF_UMS,
 
   // 63 SGET_BOOLEAN vAA, field@BBBB
-  DF_DA | DF_UMS,
+  DF_DA | DF_SFIELD | DF_UMS,
 
   // 64 SGET_BYTE vAA, field@BBBB
-  DF_DA | DF_UMS,
+  DF_DA | DF_SFIELD | DF_UMS,
 
   // 65 SGET_CHAR vAA, field@BBBB
-  DF_DA | DF_UMS,
+  DF_DA | DF_SFIELD | DF_UMS,
 
   // 66 SGET_SHORT vAA, field@BBBB
-  DF_DA | DF_UMS,
+  DF_DA | DF_SFIELD | DF_UMS,
 
   // 67 SPUT vAA, field@BBBB
-  DF_UA | DF_UMS,
+  DF_UA | DF_SFIELD | DF_UMS,
 
   // 68 SPUT_WIDE vAA, field@BBBB
-  DF_UA | DF_A_WIDE | DF_UMS,
+  DF_UA | DF_A_WIDE | DF_SFIELD | DF_UMS,
 
   // 69 SPUT_OBJECT vAA, field@BBBB
-  DF_UA | DF_REF_A | DF_UMS,
+  DF_UA | DF_REF_A | DF_SFIELD | DF_UMS,
 
   // 6A SPUT_BOOLEAN vAA, field@BBBB
-  DF_UA | DF_UMS,
+  DF_UA | DF_SFIELD | DF_UMS,
 
   // 6B SPUT_BYTE vAA, field@BBBB
-  DF_UA | DF_UMS,
+  DF_UA | DF_SFIELD | DF_UMS,
 
   // 6C SPUT_CHAR vAA, field@BBBB
-  DF_UA | DF_UMS,
+  DF_UA | DF_SFIELD | DF_UMS,
 
   // 6D SPUT_SHORT vAA, field@BBBB
-  DF_UA | DF_UMS,
+  DF_UA | DF_SFIELD | DF_UMS,
 
   // 6E INVOKE_VIRTUAL {vD, vE, vF, vG, vA}
   DF_FORMAT_35C | DF_NULL_CHK_OUT0 | DF_UMS,
@@ -712,31 +712,31 @@
   DF_DA | DF_UB | DF_CORE_A | DF_CORE_B,
 
   // E3 IGET_VOLATILE
-  DF_DA | DF_UB | DF_NULL_CHK_0 | DF_REF_B | DF_LVN,
+  DF_DA | DF_UB | DF_NULL_CHK_0 | DF_REF_B | DF_IFIELD | DF_LVN,
 
   // E4 IPUT_VOLATILE
-  DF_UA | DF_UB | DF_NULL_CHK_1 | DF_REF_B | DF_LVN,
+  DF_UA | DF_UB | DF_NULL_CHK_1 | DF_REF_B | DF_IFIELD | DF_LVN,
 
   // E5 SGET_VOLATILE
-  DF_DA | DF_UMS,
+  DF_DA | DF_SFIELD | DF_UMS,
 
   // E6 SPUT_VOLATILE
-  DF_UA | DF_UMS,
+  DF_UA | DF_SFIELD | DF_UMS,
 
   // E7 IGET_OBJECT_VOLATILE
-  DF_DA | DF_UB | DF_NULL_CHK_0 | DF_REF_A | DF_REF_B | DF_LVN,
+  DF_DA | DF_UB | DF_NULL_CHK_0 | DF_REF_A | DF_REF_B | DF_IFIELD | DF_LVN,
 
   // E8 IGET_WIDE_VOLATILE
-  DF_DA | DF_A_WIDE | DF_UB | DF_NULL_CHK_0 | DF_REF_B | DF_LVN,
+  DF_DA | DF_A_WIDE | DF_UB | DF_NULL_CHK_0 | DF_REF_B | DF_IFIELD | DF_LVN,
 
   // E9 IPUT_WIDE_VOLATILE
-  DF_UA | DF_A_WIDE | DF_UB | DF_NULL_CHK_2 | DF_REF_B | DF_LVN,
+  DF_UA | DF_A_WIDE | DF_UB | DF_NULL_CHK_2 | DF_REF_B | DF_IFIELD | DF_LVN,
 
   // EA SGET_WIDE_VOLATILE
-  DF_DA | DF_A_WIDE | DF_UMS,
+  DF_DA | DF_A_WIDE | DF_SFIELD | DF_UMS,
 
   // EB SPUT_WIDE_VOLATILE
-  DF_UA | DF_A_WIDE | DF_UMS,
+  DF_UA | DF_A_WIDE | DF_SFIELD | DF_UMS,
 
   // EC BREAKPOINT
   DF_NOP,
@@ -757,22 +757,22 @@
   DF_NOP,
 
   // F2 IGET_QUICK
-  DF_DA | DF_UB | DF_NULL_CHK_0 | DF_LVN,
+  DF_DA | DF_UB | DF_NULL_CHK_0 | DF_IFIELD | DF_LVN,
 
   // F3 IGET_WIDE_QUICK
-  DF_DA | DF_A_WIDE | DF_UB | DF_NULL_CHK_0 | DF_LVN,
+  DF_DA | DF_A_WIDE | DF_UB | DF_NULL_CHK_0 | DF_IFIELD | DF_LVN,
 
   // F4 IGET_OBJECT_QUICK
-  DF_DA | DF_UB | DF_NULL_CHK_0 | DF_LVN,
+  DF_DA | DF_UB | DF_NULL_CHK_0 | DF_IFIELD | DF_LVN,
 
   // F5 IPUT_QUICK
-  DF_UA | DF_UB | DF_NULL_CHK_1 | DF_LVN,
+  DF_UA | DF_UB | DF_NULL_CHK_1 | DF_IFIELD | DF_LVN,
 
   // F6 IPUT_WIDE_QUICK
-  DF_UA | DF_A_WIDE | DF_UB | DF_NULL_CHK_2 | DF_LVN,
+  DF_UA | DF_A_WIDE | DF_UB | DF_NULL_CHK_2 | DF_IFIELD | DF_LVN,
 
   // F7 IPUT_OBJECT_QUICK
-  DF_UA | DF_UB | DF_NULL_CHK_1 | DF_LVN,
+  DF_UA | DF_UB | DF_NULL_CHK_1 | DF_IFIELD | DF_LVN,
 
   // F8 INVOKE_VIRTUAL_QUICK
   DF_FORMAT_35C | DF_NULL_CHK_OUT0 | DF_UMS,
@@ -787,13 +787,13 @@
   DF_FORMAT_3RC | DF_NULL_CHK_OUT0 | DF_UMS,
 
   // FC IPUT_OBJECT_VOLATILE
-  DF_UA | DF_UB | DF_NULL_CHK_1 | DF_REF_A | DF_REF_B | DF_LVN,
+  DF_UA | DF_UB | DF_NULL_CHK_1 | DF_REF_A | DF_REF_B | DF_IFIELD | DF_LVN,
 
   // FD SGET_OBJECT_VOLATILE
-  DF_DA | DF_REF_A | DF_UMS,
+  DF_DA | DF_REF_A | DF_SFIELD | DF_UMS,
 
   // FE SPUT_OBJECT_VOLATILE
-  DF_UA | DF_REF_A | DF_UMS,
+  DF_UA | DF_REF_A | DF_SFIELD | DF_UMS,
 
   // FF UNUSED_FF
   DF_NOP,
diff --git a/compiler/dex/mir_graph.cc b/compiler/dex/mir_graph.cc
index 0b50e2f..8bb5615 100644
--- a/compiler/dex/mir_graph.cc
+++ b/compiler/dex/mir_graph.cc
@@ -88,6 +88,7 @@
       num_non_special_compiler_temps_(0),
       max_available_non_special_compiler_temps_(0),
       punt_to_interpreter_(false),
+      merged_df_flags_(0u),
       ifield_lowering_infos_(arena, 0u),
       sfield_lowering_infos_(arena, 0u),
       method_lowering_infos_(arena, 0u) {
@@ -598,9 +599,11 @@
   entry_block_->fall_through = cur_block->id;
   cur_block->predecessors->Insert(entry_block_->id);
 
-    /* Identify code range in try blocks and set up the empty catch blocks */
+  /* Identify code range in try blocks and set up the empty catch blocks */
   ProcessTryCatchBlocks();
 
+  uint64_t merged_df_flags = 0u;
+
   /* Parse all instructions and put them into containing basic blocks */
   while (code_ptr < code_end) {
     MIR *insn = static_cast<MIR *>(arena_->Alloc(sizeof(MIR), kArenaAllocMIR));
@@ -617,6 +620,7 @@
     int verify_flags = Instruction::VerifyFlagsOf(insn->dalvikInsn.opcode);
 
     uint64_t df_flags = oat_data_flow_attributes_[insn->dalvikInsn.opcode];
+    merged_df_flags |= df_flags;
 
     if (df_flags & DF_HAS_DEFS) {
       def_count_ += (df_flags & DF_A_WIDE) ? 2 : 1;
@@ -715,6 +719,7 @@
       cur_block = next_block;
     }
   }
+  merged_df_flags_ = merged_df_flags;
 
   if (cu_->enable_debug & (1 << kDebugDumpCFG)) {
     DumpCFG("/sdcard/1_post_parse_cfg/", true);
diff --git a/compiler/dex/mir_graph.h b/compiler/dex/mir_graph.h
index 2abc0cc..80311ec 100644
--- a/compiler/dex/mir_graph.h
+++ b/compiler/dex/mir_graph.h
@@ -98,6 +98,8 @@
   kRefB,
   kRefC,
   kUsesMethodStar,       // Implicit use of Method*.
+  kUsesIField,           // Accesses an instance field (IGET/IPUT).
+  kUsesSField,           // Accesses a static field (SGET/SPUT).
   kDoLVN,                // Worth computing local value numbers.
 };
 
@@ -134,6 +136,8 @@
 #define DF_REF_B                (UINT64_C(1) << kRefB)
 #define DF_REF_C                (UINT64_C(1) << kRefC)
 #define DF_UMS                  (UINT64_C(1) << kUsesMethodStar)
+#define DF_IFIELD               (UINT64_C(1) << kUsesIField)
+#define DF_SFIELD               (UINT64_C(1) << kUsesSField)
 #define DF_LVN                  (UINT64_C(1) << kDoLVN)
 
 #define DF_HAS_USES             (DF_UA | DF_UB | DF_UC)
@@ -485,14 +489,23 @@
    */
   void DumpCFG(const char* dir_prefix, bool all_blocks, const char* suffix = nullptr);
 
+  bool HasFieldAccess() const {
+    return (merged_df_flags_ & (DF_IFIELD | DF_SFIELD)) != 0u;
+  }
+
+  bool HasInvokes() const {
+    // NOTE: These formats include the rare filled-new-array/range.
+    return (merged_df_flags_ & (DF_FORMAT_35C | DF_FORMAT_3RC)) != 0u;
+  }
+
   void DoCacheFieldLoweringInfo();
 
-  const MirIFieldLoweringInfo& GetIFieldLoweringInfo(MIR* mir) {
+  const MirIFieldLoweringInfo& GetIFieldLoweringInfo(MIR* mir) const {
     DCHECK_LT(mir->meta.ifield_lowering_info, ifield_lowering_infos_.Size());
     return ifield_lowering_infos_.GetRawStorage()[mir->meta.ifield_lowering_info];
   }
 
-  const MirSFieldLoweringInfo& GetSFieldLoweringInfo(MIR* mir) {
+  const MirSFieldLoweringInfo& GetSFieldLoweringInfo(MIR* mir) const {
     DCHECK_LT(mir->meta.sfield_lowering_info, sfield_lowering_infos_.Size());
     return sfield_lowering_infos_.GetRawStorage()[mir->meta.sfield_lowering_info];
   }
@@ -961,6 +974,7 @@
   size_t max_available_non_special_compiler_temps_;
   size_t max_available_special_compiler_temps_;
   bool punt_to_interpreter_;                    // Difficult or not worthwhile - just interpret.
+  uint64_t merged_df_flags_;
   GrowableArray<MirIFieldLoweringInfo> ifield_lowering_infos_;
   GrowableArray<MirSFieldLoweringInfo> sfield_lowering_infos_;
   GrowableArray<MirMethodLoweringInfo> method_lowering_infos_;