Add a GVN dependency 'GC' for garbage collection.

This will be used by incoming architecture specific optimizations. The
dependencies must be conservative. When an HInstruction is created we
may not be sure whether it can trigger GC. In that case the
'ChangesGC' dependency must be set. We control at code-generation time
that HInstructions that can call have the 'ChangesGC' dependency
set.

Change-Id: Iea6a7f430009f37a9599b0a0039207049906e45d
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index ca2c998..dba9233 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -1215,23 +1215,33 @@
 };
 
 /**
- * Side-effects representation for write/read dependences on fields/arrays.
+ * Side-effects representation.
  *
- * The dependence analysis uses type disambiguation (e.g. a float field write
- * cannot modify the value of an integer field read) and the access type (e.g.
- * a reference array write cannot modify the value of a reference field read
- * [although it may modify the reference fetch prior to reading the field,
- * which is represented by its own write/read dependence]). The analysis
- * makes conservative points-to assumptions on reference types (e.g. two same
- * typed arrays are assumed to be the same, and any reference read depends
- * on any reference read without further regard of its type).
+ * For write/read dependences on fields/arrays, the dependence analysis uses
+ * type disambiguation (e.g. a float field write cannot modify the value of an
+ * integer field read) and the access type (e.g.  a reference array write cannot
+ * modify the value of a reference field read [although it may modify the
+ * reference fetch prior to reading the field, which is represented by its own
+ * write/read dependence]). The analysis makes conservative points-to
+ * assumptions on reference types (e.g. two same typed arrays are assumed to be
+ * the same, and any reference read depends on any reference read without
+ * further regard of its type).
  *
- * The internal representation uses the following 36-bit flags assignments:
+ * The internal representation uses 38-bit and is described in the table below.
+ * The first line indicates the side effect, and for field/array accesses the
+ * second line indicates the type of the access (in the order of the
+ * Primitive::Type enum).
+ * The two numbered lines below indicate the bit position in the bitfield (read
+ * vertically).
  *
- *   |ARRAY-R  |FIELD-R  |ARRAY-W  |FIELD-W  |
- *   +---------+---------+---------+---------+
- *   |543210987|654321098|765432109|876543210|
- *   |DFJISCBZL|DFJISCBZL|DFJISCBZL|DFJISCBZL|
+ *   |Depends on GC|ARRAY-R  |FIELD-R  |Can trigger GC|ARRAY-W  |FIELD-W  |
+ *   +-------------+---------+---------+--------------+---------+---------+
+ *   |             |DFJISCBZL|DFJISCBZL|              |DFJISCBZL|DFJISCBZL|
+ *   |      3      |333333322|222222221|       1      |111111110|000000000|
+ *   |      7      |654321098|765432109|       8      |765432109|876543210|
+ *
+ * Note that, to ease the implementation, 'changes' bits are least significant
+ * bits, while 'dependency' bits are most significant bits.
  */
 class SideEffects : public ValueObject {
  public:
@@ -1242,6 +1252,22 @@
   }
 
   static SideEffects All() {
+    return SideEffects(kAllChangeBits | kAllDependOnBits);
+  }
+
+  static SideEffects AllChanges() {
+    return SideEffects(kAllChangeBits);
+  }
+
+  static SideEffects AllDependencies() {
+    return SideEffects(kAllDependOnBits);
+  }
+
+  static SideEffects AllExceptGCDependency() {
+    return AllWritesAndReads().Union(SideEffects::CanTriggerGC());
+  }
+
+  static SideEffects AllWritesAndReads() {
     return SideEffects(kAllWrites | kAllReads);
   }
 
@@ -1255,7 +1281,7 @@
 
   static SideEffects FieldWriteOfType(Primitive::Type type, bool is_volatile) {
     return is_volatile
-        ? All()
+        ? AllWritesAndReads()
         : SideEffects(TypeFlagWithAlias(type, kFieldWriteOffset));
   }
 
@@ -1265,7 +1291,7 @@
 
   static SideEffects FieldReadOfType(Primitive::Type type, bool is_volatile) {
     return is_volatile
-        ? All()
+        ? AllWritesAndReads()
         : SideEffects(TypeFlagWithAlias(type, kFieldReadOffset));
   }
 
@@ -1273,11 +1299,40 @@
     return SideEffects(TypeFlagWithAlias(type, kArrayReadOffset));
   }
 
+  static SideEffects CanTriggerGC() {
+    return SideEffects(1ULL << kCanTriggerGCBit);
+  }
+
+  static SideEffects DependsOnGC() {
+    return SideEffects(1ULL << kDependsOnGCBit);
+  }
+
   // Combines the side-effects of this and the other.
   SideEffects Union(SideEffects other) const {
     return SideEffects(flags_ | other.flags_);
   }
 
+  SideEffects Exclusion(SideEffects other) const {
+    return SideEffects(flags_ & ~other.flags_);
+  }
+
+  bool Includes(SideEffects other) const {
+    return (other.flags_ & flags_) == other.flags_;
+  }
+
+  bool HasSideEffects() const {
+    return (flags_ & kAllChangeBits);
+  }
+
+  bool HasDependencies() const {
+    return (flags_ & kAllDependOnBits);
+  }
+
+  // Returns true if there are no side effects or dependencies.
+  bool DoesNothing() const {
+    return flags_ == 0;
+  }
+
   // Returns true if something is written.
   bool DoesAnyWrite() const {
     return (flags_ & kAllWrites);
@@ -1288,47 +1343,81 @@
     return (flags_ & kAllReads);
   }
 
-  // Returns true if nothing is written or read.
-  bool DoesNothing() const {
-    return flags_ == 0;
-  }
-
   // Returns true if potentially everything is written and read
   // (every type and every kind of access).
+  bool DoesAllReadWrite() const {
+    return (flags_ & (kAllWrites | kAllReads)) == (kAllWrites | kAllReads);
+  }
+
   bool DoesAll() const {
-    return flags_ == (kAllWrites | kAllReads);
+    return flags_ == (kAllChangeBits | kAllDependOnBits);
   }
 
   // Returns true if this may read something written by other.
   bool MayDependOn(SideEffects other) const {
-    const uint64_t reads = (flags_ & kAllReads) >> kFieldReadOffset;
-    return (other.flags_ & reads);
+    const uint64_t depends_on_flags = (flags_ & kAllDependOnBits) >> kChangeBits;
+    return (other.flags_ & depends_on_flags);
   }
 
   // Returns string representation of flags (for debugging only).
-  // Format: |DFJISCBZL|DFJISCBZL|DFJISCBZL|DFJISCBZL|
+  // Format: |x|DFJISCBZL|DFJISCBZL|y|DFJISCBZL|DFJISCBZL|
   std::string ToString() const {
-    static const char *kDebug = "LZBCSIJFD";
     std::string flags = "|";
-    for (int s = 35; s >= 0; s--) {
-      const int t = s % kBits;
-      if ((flags_ >> s) & 1)
-        flags += kDebug[t];
-      if (t == 0)
+    for (int s = kLastBit; s >= 0; s--) {
+      bool current_bit_is_set = ((flags_ >> s) & 1) != 0;
+      if ((s == kDependsOnGCBit) || (s == kCanTriggerGCBit)) {
+        // This is a bit for the GC side effect.
+        if (current_bit_is_set) {
+          flags += "GC";
+        }
         flags += "|";
+      } else {
+        // This is a bit for the array/field analysis.
+        // The underscore character stands for the 'can trigger GC' bit.
+        static const char *kDebug = "LZBCSIJFDLZBCSIJFD_LZBCSIJFDLZBCSIJFD";
+        if (current_bit_is_set) {
+          flags += kDebug[s];
+        }
+        if ((s == kFieldWriteOffset) || (s == kArrayWriteOffset) ||
+            (s == kFieldReadOffset) || (s == kArrayReadOffset)) {
+          flags += "|";
+        }
+      }
     }
     return flags;
   }
 
- private:
-  static constexpr int kBits = 9;
-  static constexpr int kFieldWriteOffset = 0 * kBits;
-  static constexpr int kArrayWriteOffset = 1 * kBits;
-  static constexpr int kFieldReadOffset  = 2 * kBits;
-  static constexpr int kArrayReadOffset  = 3 * kBits;
+  bool Equals(const SideEffects& other) const { return flags_ == other.flags_; }
 
-  static constexpr uint64_t kAllWrites = 0x0003ffff;
-  static constexpr uint64_t kAllReads  = kAllWrites << kFieldReadOffset;
+ private:
+  static constexpr int kFieldArrayAnalysisBits = 9;
+
+  static constexpr int kFieldWriteOffset = 0;
+  static constexpr int kArrayWriteOffset = kFieldWriteOffset + kFieldArrayAnalysisBits;
+  static constexpr int kLastBitForWrites = kArrayWriteOffset + kFieldArrayAnalysisBits - 1;
+  static constexpr int kCanTriggerGCBit = kLastBitForWrites + 1;
+
+  static constexpr int kChangeBits = kCanTriggerGCBit + 1;
+
+  static constexpr int kFieldReadOffset = kCanTriggerGCBit + 1;
+  static constexpr int kArrayReadOffset = kFieldReadOffset + kFieldArrayAnalysisBits;
+  static constexpr int kLastBitForReads = kArrayReadOffset + kFieldArrayAnalysisBits - 1;
+  static constexpr int kDependsOnGCBit = kLastBitForReads + 1;
+
+  static constexpr int kLastBit = kDependsOnGCBit;
+  static constexpr int kDependOnBits = kLastBit + 1 - kChangeBits;
+
+  // Aliases.
+
+  static_assert(kChangeBits == kDependOnBits,
+                "the 'change' bits should match the 'depend on' bits.");
+
+  static constexpr uint64_t kAllChangeBits = ((1ULL << kChangeBits) - 1);
+  static constexpr uint64_t kAllDependOnBits = ((1ULL << kDependOnBits) - 1) << kChangeBits;
+  static constexpr uint64_t kAllWrites =
+      ((1ULL << (kLastBitForWrites + 1 - kFieldWriteOffset)) - 1) << kFieldWriteOffset;
+  static constexpr uint64_t kAllReads =
+      ((1ULL << (kLastBitForReads + 1 - kFieldReadOffset)) - 1) << kFieldReadOffset;
 
   // Work around the fact that HIR aliases I/F and J/D.
   // TODO: remove this interceptor once HIR types are clean
@@ -1610,6 +1699,7 @@
   virtual bool IsControlFlow() const { return false; }
   virtual bool CanThrow() const { return false; }
 
+  bool HasSideEffects() const { return side_effects_.HasSideEffects(); }
   bool DoesAnyWrite() const { return side_effects_.DoesAnyWrite(); }
 
   // Does not apply for all instructions, but having this at top level greatly
@@ -2302,7 +2392,9 @@
  public:
   HBinaryOperation(Primitive::Type result_type,
                    HInstruction* left,
-                   HInstruction* right) : HExpression(result_type, SideEffects::None()) {
+                   HInstruction* right,
+                   SideEffects side_effects = SideEffects::None())
+      : HExpression(result_type, side_effects) {
     SetRawInputAt(0, left);
     SetRawInputAt(1, right);
   }
@@ -2626,7 +2718,9 @@
            HInstruction* second,
            ComparisonBias bias,
            uint32_t dex_pc)
-      : HBinaryOperation(Primitive::kPrimInt, first, second), bias_(bias), dex_pc_(dex_pc) {
+      : HBinaryOperation(Primitive::kPrimInt, first, second, SideEffectsForArchRuntimeCalls(type)),
+        bias_(bias),
+        dex_pc_(dex_pc) {
     DCHECK_EQ(type, first->GetType());
     DCHECK_EQ(type, second->GetType());
   }
@@ -2649,7 +2743,12 @@
 
   bool IsGtBias() { return bias_ == ComparisonBias::kGtBias; }
 
-  uint32_t GetDexPc() const { return dex_pc_; }
+  uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
+
+  static SideEffects SideEffectsForArchRuntimeCalls(Primitive::Type type) {
+    // MIPS64 uses a runtime call for FP comparisons.
+    return Primitive::IsFloatingPointType(type) ? SideEffects::CanTriggerGC() : SideEffects::None();
+  }
 
   DECLARE_INSTRUCTION(Compare);
 
@@ -2851,7 +2950,8 @@
           uint32_t dex_pc,
           uint32_t dex_method_index,
           InvokeType original_invoke_type)
-    : HInstruction(SideEffects::All()),  // assume write/read on all fields/arrays
+    : HInstruction(
+          SideEffects::AllExceptGCDependency()),  // Assume write/read on all fields/arrays.
       number_of_arguments_(number_of_arguments),
       inputs_(arena, number_of_arguments),
       return_type_(return_type),
@@ -3068,7 +3168,7 @@
                uint16_t type_index,
                const DexFile& dex_file,
                QuickEntrypointEnum entrypoint)
-      : HExpression(Primitive::kPrimNot, SideEffects::None()),
+      : HExpression(Primitive::kPrimNot, SideEffects::CanTriggerGC()),
         dex_pc_(dex_pc),
         type_index_(type_index),
         dex_file_(dex_file),
@@ -3131,7 +3231,7 @@
             uint16_t type_index,
             const DexFile& dex_file,
             QuickEntrypointEnum entrypoint)
-      : HExpression(Primitive::kPrimNot, SideEffects::None()),
+      : HExpression(Primitive::kPrimNot, SideEffects::CanTriggerGC()),
         dex_pc_(dex_pc),
         type_index_(type_index),
         dex_file_(dex_file),
@@ -3232,7 +3332,8 @@
 class HDiv : public HBinaryOperation {
  public:
   HDiv(Primitive::Type result_type, HInstruction* left, HInstruction* right, uint32_t dex_pc)
-      : HBinaryOperation(result_type, left, right), dex_pc_(dex_pc) {}
+      : HBinaryOperation(result_type, left, right, SideEffectsForArchRuntimeCalls()),
+        dex_pc_(dex_pc) {}
 
   template <typename T>
   T Compute(T x, T y) const {
@@ -3252,6 +3353,11 @@
 
   uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
 
+  static SideEffects SideEffectsForArchRuntimeCalls() {
+    // The generated code can use a runtime call.
+    return SideEffects::CanTriggerGC();
+  }
+
   DECLARE_INSTRUCTION(Div);
 
  private:
@@ -3263,7 +3369,8 @@
 class HRem : public HBinaryOperation {
  public:
   HRem(Primitive::Type result_type, HInstruction* left, HInstruction* right, uint32_t dex_pc)
-      : HBinaryOperation(result_type, left, right), dex_pc_(dex_pc) {}
+      : HBinaryOperation(result_type, left, right, SideEffectsForArchRuntimeCalls()),
+        dex_pc_(dex_pc) {}
 
   template <typename T>
   T Compute(T x, T y) const {
@@ -3283,6 +3390,10 @@
 
   uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
 
+  static SideEffects SideEffectsForArchRuntimeCalls() {
+    return SideEffects::CanTriggerGC();
+  }
+
   DECLARE_INSTRUCTION(Rem);
 
  private:
@@ -3593,7 +3704,8 @@
  public:
   // Instantiate a type conversion of `input` to `result_type`.
   HTypeConversion(Primitive::Type result_type, HInstruction* input, uint32_t dex_pc)
-      : HExpression(result_type, SideEffects::None()), dex_pc_(dex_pc) {
+      : HExpression(result_type, SideEffectsForArchRuntimeCalls(input->GetType(), result_type)),
+        dex_pc_(dex_pc) {
     SetRawInputAt(0, input);
     DCHECK_NE(input->GetType(), result_type);
   }
@@ -3613,6 +3725,19 @@
   // containing the result.  If the input cannot be converted, return nullptr.
   HConstant* TryStaticEvaluation() const;
 
+  static SideEffects SideEffectsForArchRuntimeCalls(Primitive::Type input_type,
+                                                    Primitive::Type result_type) {
+    // Some architectures may not require the 'GC' side effects, but at this point
+    // in the compilation process we do not know what architecture we will
+    // generate code for, so we must be conservative.
+    if (((input_type == Primitive::kPrimFloat || input_type == Primitive::kPrimDouble)
+         && result_type == Primitive::kPrimLong)
+        || (input_type == Primitive::kPrimLong && result_type == Primitive::kPrimFloat)) {
+      return SideEffects::CanTriggerGC();
+    }
+    return SideEffects::None();
+  }
+
   DECLARE_INSTRUCTION(TypeConversion);
 
  private:
@@ -3879,7 +4004,9 @@
             HInstruction* value,
             Primitive::Type expected_component_type,
             uint32_t dex_pc)
-      : HTemplateInstruction(SideEffects::ArrayWriteOfType(expected_component_type)),
+      : HTemplateInstruction(
+            SideEffects::ArrayWriteOfType(expected_component_type).Union(
+                SideEffectsForArchRuntimeCalls(value->GetType()))),
         dex_pc_(dex_pc),
         expected_component_type_(expected_component_type),
         needs_type_check_(value->GetType() == Primitive::kPrimNot),
@@ -3932,6 +4059,10 @@
         : expected_component_type_;
   }
 
+  static SideEffects SideEffectsForArchRuntimeCalls(Primitive::Type value_type) {
+    return (value_type == Primitive::kPrimNot) ? SideEffects::CanTriggerGC() : SideEffects::None();
+  }
+
   DECLARE_INSTRUCTION(ArraySet);
 
  private:
@@ -4026,7 +4157,7 @@
 class HSuspendCheck : public HTemplateInstruction<0> {
  public:
   explicit HSuspendCheck(uint32_t dex_pc)
-      : HTemplateInstruction(SideEffects::None()), dex_pc_(dex_pc), slow_path_(nullptr) {}
+      : HTemplateInstruction(SideEffects::CanTriggerGC()), dex_pc_(dex_pc), slow_path_(nullptr) {}
 
   bool NeedsEnvironment() const OVERRIDE {
     return true;
@@ -4058,7 +4189,7 @@
              const DexFile& dex_file,
              bool is_referrers_class,
              uint32_t dex_pc)
-      : HExpression(Primitive::kPrimNot, SideEffects::None()),
+      : HExpression(Primitive::kPrimNot, SideEffectsForArchRuntimeCalls()),
         type_index_(type_index),
         dex_file_(dex_file),
         is_referrers_class_(is_referrers_class),
@@ -4119,6 +4250,10 @@
 
   bool NeedsDexCache() const OVERRIDE { return !is_referrers_class_; }
 
+  static SideEffects SideEffectsForArchRuntimeCalls() {
+    return SideEffects::CanTriggerGC();
+  }
+
   DECLARE_INSTRUCTION(LoadClass);
 
  private:
@@ -4138,7 +4273,7 @@
 class HLoadString : public HExpression<1> {
  public:
   HLoadString(HCurrentMethod* current_method, uint32_t string_index, uint32_t dex_pc)
-      : HExpression(Primitive::kPrimNot, SideEffects::None()),
+      : HExpression(Primitive::kPrimNot, SideEffectsForArchRuntimeCalls()),
         string_index_(string_index),
         dex_pc_(dex_pc) {
     SetRawInputAt(0, current_method);
@@ -4159,6 +4294,10 @@
   bool NeedsEnvironment() const OVERRIDE { return false; }
   bool NeedsDexCache() const OVERRIDE { return true; }
 
+  static SideEffects SideEffectsForArchRuntimeCalls() {
+    return SideEffects::CanTriggerGC();
+  }
+
   DECLARE_INSTRUCTION(LoadString);
 
  private:
@@ -4175,8 +4314,8 @@
  public:
   explicit HClinitCheck(HLoadClass* constant, uint32_t dex_pc)
       : HExpression(
-          Primitive::kPrimNot,
-          SideEffects::AllWrites()),  // assume write on all fields/arrays
+            Primitive::kPrimNot,
+            SideEffects::AllChanges()),  // Assume write/read on all fields/arrays.
         dex_pc_(dex_pc) {
     SetRawInputAt(0, constant);
   }
@@ -4305,7 +4444,7 @@
 class HThrow : public HTemplateInstruction<1> {
  public:
   HThrow(HInstruction* exception, uint32_t dex_pc)
-      : HTemplateInstruction(SideEffects::None()), dex_pc_(dex_pc) {
+      : HTemplateInstruction(SideEffects::CanTriggerGC()), dex_pc_(dex_pc) {
     SetRawInputAt(0, exception);
   }
 
@@ -4331,7 +4470,7 @@
               HLoadClass* constant,
               bool class_is_final,
               uint32_t dex_pc)
-      : HExpression(Primitive::kPrimBoolean, SideEffects::None()),
+      : HExpression(Primitive::kPrimBoolean, SideEffectsForArchRuntimeCalls(class_is_final)),
         class_is_final_(class_is_final),
         must_do_null_check_(true),
         dex_pc_(dex_pc) {
@@ -4357,6 +4496,10 @@
   bool MustDoNullCheck() const { return must_do_null_check_; }
   void ClearMustDoNullCheck() { must_do_null_check_ = false; }
 
+  static SideEffects SideEffectsForArchRuntimeCalls(bool class_is_final) {
+    return class_is_final ? SideEffects::None() : SideEffects::CanTriggerGC();
+  }
+
   DECLARE_INSTRUCTION(InstanceOf);
 
  private:
@@ -4416,7 +4559,7 @@
              HLoadClass* constant,
              bool class_is_final,
              uint32_t dex_pc)
-      : HTemplateInstruction(SideEffects::None()),
+      : HTemplateInstruction(SideEffects::CanTriggerGC()),
         class_is_final_(class_is_final),
         must_do_null_check_(true),
         dex_pc_(dex_pc) {
@@ -4458,7 +4601,7 @@
  public:
   explicit HMemoryBarrier(MemBarrierKind barrier_kind)
       : HTemplateInstruction(
-          SideEffects::All()),  // assume write/read on all fields/arrays
+            SideEffects::AllWritesAndReads()),  // Assume write/read on all fields/arrays.
         barrier_kind_(barrier_kind) {}
 
   MemBarrierKind GetBarrierKind() { return barrier_kind_; }
@@ -4479,7 +4622,8 @@
   };
 
   HMonitorOperation(HInstruction* object, OperationKind kind, uint32_t dex_pc)
-    : HTemplateInstruction(SideEffects::All()),  // assume write/read on all fields/arrays
+    : HTemplateInstruction(
+          SideEffects::AllExceptGCDependency()),  // Assume write/read on all fields/arrays.
       kind_(kind), dex_pc_(dex_pc) {
     SetRawInputAt(0, object);
   }