Added support for unsigned comparisons

Rationale: even though not directly supported in input graph,
           having the ability to express unsigned comparisons
           in HIR is useful for all sorts of optimizations.

Change-Id: I4543c96a8c1895c3d33aaf85685afbf80fe27d72
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index c126b59..4cd5133 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -81,12 +81,19 @@
 static constexpr uint32_t kNoDexPc = -1;
 
 enum IfCondition {
-  kCondEQ,
-  kCondNE,
-  kCondLT,
-  kCondLE,
-  kCondGT,
-  kCondGE,
+  // All types.
+  kCondEQ,  // ==
+  kCondNE,  // !=
+  // Signed integers and floating-point numbers.
+  kCondLT,  // <
+  kCondLE,  // <=
+  kCondGT,  // >
+  kCondGE,  // >=
+  // Unsigned integers.
+  kCondB,   // <
+  kCondBE,  // <=
+  kCondA,   // >
+  kCondAE,  // >=
 };
 
 class HInstructionList : public ValueObject {
@@ -988,11 +995,15 @@
 };
 
 #define FOR_EACH_CONCRETE_INSTRUCTION_COMMON(M)                         \
+  M(Above, Condition)                                                   \
+  M(AboveOrEqual, Condition)                                            \
   M(Add, BinaryOperation)                                               \
   M(And, BinaryOperation)                                               \
   M(ArrayGet, Instruction)                                              \
   M(ArrayLength, Instruction)                                           \
   M(ArraySet, Instruction)                                              \
+  M(Below, Condition)                                                   \
+  M(BelowOrEqual, Condition)                                            \
   M(BooleanNot, UnaryOperation)                                         \
   M(BoundsCheck, Instruction)                                           \
   M(BoundType, Instruction)                                             \
@@ -2631,8 +2642,6 @@
 
   bool IsCommutative() const OVERRIDE { return true; }
 
-  template <typename T> bool Compute(T x, T y) const { return x == y; }
-
   HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
     return GetBlock()->GetGraph()->GetIntConstant(
         Compute(x->GetValue(), y->GetValue()), GetDexPc());
@@ -2653,6 +2662,8 @@
   }
 
  private:
+  template <typename T> bool Compute(T x, T y) const { return x == y; }
+
   DISALLOW_COPY_AND_ASSIGN(HEqual);
 };
 
@@ -2663,8 +2674,6 @@
 
   bool IsCommutative() const OVERRIDE { return true; }
 
-  template <typename T> bool Compute(T x, T y) const { return x != y; }
-
   HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
     return GetBlock()->GetGraph()->GetIntConstant(
         Compute(x->GetValue(), y->GetValue()), GetDexPc());
@@ -2685,6 +2694,8 @@
   }
 
  private:
+  template <typename T> bool Compute(T x, T y) const { return x != y; }
+
   DISALLOW_COPY_AND_ASSIGN(HNotEqual);
 };
 
@@ -2693,8 +2704,6 @@
   HLessThan(HInstruction* first, HInstruction* second, uint32_t dex_pc = kNoDexPc)
       : HCondition(first, second, dex_pc) {}
 
-  template <typename T> bool Compute(T x, T y) const { return x < y; }
-
   HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
     return GetBlock()->GetGraph()->GetIntConstant(
         Compute(x->GetValue(), y->GetValue()), GetDexPc());
@@ -2715,6 +2724,8 @@
   }
 
  private:
+  template <typename T> bool Compute(T x, T y) const { return x < y; }
+
   DISALLOW_COPY_AND_ASSIGN(HLessThan);
 };
 
@@ -2723,8 +2734,6 @@
   HLessThanOrEqual(HInstruction* first, HInstruction* second, uint32_t dex_pc = kNoDexPc)
       : HCondition(first, second, dex_pc) {}
 
-  template <typename T> bool Compute(T x, T y) const { return x <= y; }
-
   HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
     return GetBlock()->GetGraph()->GetIntConstant(
         Compute(x->GetValue(), y->GetValue()), GetDexPc());
@@ -2745,6 +2754,8 @@
   }
 
  private:
+  template <typename T> bool Compute(T x, T y) const { return x <= y; }
+
   DISALLOW_COPY_AND_ASSIGN(HLessThanOrEqual);
 };
 
@@ -2753,8 +2764,6 @@
   HGreaterThan(HInstruction* first, HInstruction* second, uint32_t dex_pc = kNoDexPc)
       : HCondition(first, second, dex_pc) {}
 
-  template <typename T> bool Compute(T x, T y) const { return x > y; }
-
   HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
     return GetBlock()->GetGraph()->GetIntConstant(
         Compute(x->GetValue(), y->GetValue()), GetDexPc());
@@ -2775,6 +2784,8 @@
   }
 
  private:
+  template <typename T> bool Compute(T x, T y) const { return x > y; }
+
   DISALLOW_COPY_AND_ASSIGN(HGreaterThan);
 };
 
@@ -2783,8 +2794,6 @@
   HGreaterThanOrEqual(HInstruction* first, HInstruction* second, uint32_t dex_pc = kNoDexPc)
       : HCondition(first, second, dex_pc) {}
 
-  template <typename T> bool Compute(T x, T y) const { return x >= y; }
-
   HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
     return GetBlock()->GetGraph()->GetIntConstant(
         Compute(x->GetValue(), y->GetValue()), GetDexPc());
@@ -2805,9 +2814,138 @@
   }
 
  private:
+  template <typename T> bool Compute(T x, T y) const { return x >= y; }
+
   DISALLOW_COPY_AND_ASSIGN(HGreaterThanOrEqual);
 };
 
+class HBelow : public HCondition {
+ public:
+  HBelow(HInstruction* first, HInstruction* second, uint32_t dex_pc = kNoDexPc)
+      : HCondition(first, second, dex_pc) {}
+
+  HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
+    return GetBlock()->GetGraph()->GetIntConstant(
+        Compute(static_cast<uint32_t>(x->GetValue()),
+                static_cast<uint32_t>(y->GetValue())), GetDexPc());
+  }
+  HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const OVERRIDE {
+    return GetBlock()->GetGraph()->GetIntConstant(
+        Compute(static_cast<uint64_t>(x->GetValue()),
+                static_cast<uint64_t>(y->GetValue())), GetDexPc());
+  }
+
+  DECLARE_INSTRUCTION(Below);
+
+  IfCondition GetCondition() const OVERRIDE {
+    return kCondB;
+  }
+
+  IfCondition GetOppositeCondition() const OVERRIDE {
+    return kCondAE;
+  }
+
+ private:
+  template <typename T> bool Compute(T x, T y) const { return x < y; }
+
+  DISALLOW_COPY_AND_ASSIGN(HBelow);
+};
+
+class HBelowOrEqual : public HCondition {
+ public:
+  HBelowOrEqual(HInstruction* first, HInstruction* second, uint32_t dex_pc = kNoDexPc)
+      : HCondition(first, second, dex_pc) {}
+
+  HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
+    return GetBlock()->GetGraph()->GetIntConstant(
+        Compute(static_cast<uint32_t>(x->GetValue()),
+                static_cast<uint32_t>(y->GetValue())), GetDexPc());
+  }
+  HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const OVERRIDE {
+    return GetBlock()->GetGraph()->GetIntConstant(
+        Compute(static_cast<uint64_t>(x->GetValue()),
+                static_cast<uint64_t>(y->GetValue())), GetDexPc());
+  }
+
+  DECLARE_INSTRUCTION(BelowOrEqual);
+
+  IfCondition GetCondition() const OVERRIDE {
+    return kCondBE;
+  }
+
+  IfCondition GetOppositeCondition() const OVERRIDE {
+    return kCondA;
+  }
+
+ private:
+  template <typename T> bool Compute(T x, T y) const { return x <= y; }
+
+  DISALLOW_COPY_AND_ASSIGN(HBelowOrEqual);
+};
+
+class HAbove : public HCondition {
+ public:
+  HAbove(HInstruction* first, HInstruction* second, uint32_t dex_pc = kNoDexPc)
+      : HCondition(first, second, dex_pc) {}
+
+  HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
+    return GetBlock()->GetGraph()->GetIntConstant(
+        Compute(static_cast<uint32_t>(x->GetValue()),
+                static_cast<uint32_t>(y->GetValue())), GetDexPc());
+  }
+  HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const OVERRIDE {
+    return GetBlock()->GetGraph()->GetIntConstant(
+        Compute(static_cast<uint64_t>(x->GetValue()),
+                static_cast<uint64_t>(y->GetValue())), GetDexPc());
+  }
+
+  DECLARE_INSTRUCTION(Above);
+
+  IfCondition GetCondition() const OVERRIDE {
+    return kCondA;
+  }
+
+  IfCondition GetOppositeCondition() const OVERRIDE {
+    return kCondBE;
+  }
+
+ private:
+  template <typename T> bool Compute(T x, T y) const { return x > y; }
+
+  DISALLOW_COPY_AND_ASSIGN(HAbove);
+};
+
+class HAboveOrEqual : public HCondition {
+ public:
+  HAboveOrEqual(HInstruction* first, HInstruction* second, uint32_t dex_pc = kNoDexPc)
+      : HCondition(first, second, dex_pc) {}
+
+  HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
+    return GetBlock()->GetGraph()->GetIntConstant(
+        Compute(static_cast<uint32_t>(x->GetValue()),
+                static_cast<uint32_t>(y->GetValue())), GetDexPc());
+  }
+  HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const OVERRIDE {
+    return GetBlock()->GetGraph()->GetIntConstant(
+        Compute(static_cast<uint64_t>(x->GetValue()),
+                static_cast<uint64_t>(y->GetValue())), GetDexPc());
+  }
+
+  DECLARE_INSTRUCTION(AboveOrEqual);
+
+  IfCondition GetCondition() const OVERRIDE {
+    return kCondAE;
+  }
+
+  IfCondition GetOppositeCondition() const OVERRIDE {
+    return kCondB;
+  }
+
+ private:
+  template <typename T> bool Compute(T x, T y) const { return x >= y; }
+
+  DISALLOW_COPY_AND_ASSIGN(HAboveOrEqual);
+};
 
 // Instruction to check how two inputs compare to each other.
 // Result is 0 if input0 == input1, 1 if input0 > input1, or -1 if input0 < input1.