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/code_generator_mips64.cc b/compiler/optimizing/code_generator_mips64.cc
index 1a08503..eb20291 100644
--- a/compiler/optimizing/code_generator_mips64.cc
+++ b/compiler/optimizing/code_generator_mips64.cc
@@ -1778,6 +1778,9 @@
     return;
   }
 
+  // TODO: generalize to long
+  DCHECK_NE(instruction->InputAt(0)->GetType(), Primitive::kPrimLong);
+
   LocationSummary* locations = instruction->GetLocations();
 
   GpuRegister dst = locations->Out().AsRegister<GpuRegister>();
@@ -1855,6 +1858,48 @@
         }
       }
       break;
+
+    case kCondB:
+    case kCondAE:
+      if (use_imm && 0 <= rhs_imm && rhs_imm <= 0x7fff) {
+        __ Sltiu(dst, lhs, rhs_imm);
+      } else {
+        if (use_imm) {
+          rhs_reg = TMP;
+          __ LoadConst32(rhs_reg, rhs_imm);
+        }
+        __ Sltu(dst, lhs, rhs_reg);
+      }
+      if (if_cond == kCondAE) {
+        // Simulate lhs >= rhs via !(lhs < rhs) since there's
+        // only the sltu instruction but no sgeu.
+        __ Xori(dst, dst, 1);
+      }
+      break;
+
+    case kCondBE:
+    case kCondA:
+      if (use_imm && 0 <= rhs_imm && rhs_imm <= 0x7ffe) {
+        // Simulate lhs <= rhs via lhs < rhs + 1.
+        __ Sltiu(dst, lhs, rhs_imm + 1);
+        if (if_cond == kCondA) {
+          // Simulate lhs > rhs via !(lhs <= rhs) since there's
+          // only the sltiu instruction but no sgtiu.
+          __ Xori(dst, dst, 1);
+        }
+      } else {
+        if (use_imm) {
+          rhs_reg = TMP;
+          __ LoadConst32(rhs_reg, rhs_imm);
+        }
+        __ Sltu(dst, rhs_reg, lhs);
+        if (if_cond == kCondBE) {
+          // Simulate lhs <= rhs via !(rhs < lhs) since there's
+          // only the sltu instruction but no sleu.
+          __ Xori(dst, dst, 1);
+        }
+      }
+      break;
   }
 }
 
@@ -2072,6 +2117,17 @@
         case kCondGT:
           __ Bgtzc(lhs, true_target);
           break;
+        case kCondB:
+          break;  // always false
+        case kCondBE:
+          __ Beqzc(lhs, true_target);  // <= 0 if zero
+          break;
+        case kCondA:
+          __ Bnezc(lhs, true_target);  // > 0 if non-zero
+          break;
+        case kCondAE:
+          __ B(true_target);  // always true
+          break;
       }
     } else {
       if (use_imm) {
@@ -2086,12 +2142,16 @@
           case kCondEQ:
           case kCondGE:
           case kCondLE:
+          case kCondBE:
+          case kCondAE:
             // if lhs == rhs for a positive condition, then it is a branch
             __ B(true_target);
             break;
           case kCondNE:
           case kCondLT:
           case kCondGT:
+          case kCondB:
+          case kCondA:
             // if lhs == rhs for a negative condition, then it is a NOP
             break;
         }
@@ -2115,6 +2175,18 @@
           case kCondGT:
             __ Bltc(rhs_reg, lhs, true_target);
             break;
+          case kCondB:
+            __ Bltuc(lhs, rhs_reg, true_target);
+            break;
+          case kCondAE:
+            __ Bgeuc(lhs, rhs_reg, true_target);
+            break;
+          case kCondBE:
+            __ Bgeuc(rhs_reg, lhs, true_target);
+            break;
+          case kCondA:
+            __ Bltuc(rhs_reg, lhs, true_target);
+            break;
         }
       }
     }
@@ -3462,6 +3534,38 @@
   VisitCondition(comp);
 }
 
+void LocationsBuilderMIPS64::VisitBelow(HBelow* comp) {
+  VisitCondition(comp);
+}
+
+void InstructionCodeGeneratorMIPS64::VisitBelow(HBelow* comp) {
+  VisitCondition(comp);
+}
+
+void LocationsBuilderMIPS64::VisitBelowOrEqual(HBelowOrEqual* comp) {
+  VisitCondition(comp);
+}
+
+void InstructionCodeGeneratorMIPS64::VisitBelowOrEqual(HBelowOrEqual* comp) {
+  VisitCondition(comp);
+}
+
+void LocationsBuilderMIPS64::VisitAbove(HAbove* comp) {
+  VisitCondition(comp);
+}
+
+void InstructionCodeGeneratorMIPS64::VisitAbove(HAbove* comp) {
+  VisitCondition(comp);
+}
+
+void LocationsBuilderMIPS64::VisitAboveOrEqual(HAboveOrEqual* comp) {
+  VisitCondition(comp);
+}
+
+void InstructionCodeGeneratorMIPS64::VisitAboveOrEqual(HAboveOrEqual* comp) {
+  VisitCondition(comp);
+}
+
 void LocationsBuilderMIPS64::VisitFakeString(HFakeString* instruction) {
   DCHECK(codegen_->IsBaseline());
   LocationSummary* locations =