Small refactor of MIN/MAX compiler code.

Integrate instruction code generation and location creation with
HandleBinaryOp. Code generation has been improved for constant
inputs 0, 1 and -1.

Test: 679-checker-minmax
Test: test-art-host, test-art-target.

Change-Id: Ib34eb8a4b29d22a2491d21656e1f64011ef9f986
diff --git a/compiler/optimizing/common_arm64.h b/compiler/optimizing/common_arm64.h
index ed2f8e9..5191ee2 100644
--- a/compiler/optimizing/common_arm64.h
+++ b/compiler/optimizing/common_arm64.h
@@ -234,6 +234,13 @@
   }
 }
 
+inline bool AddSubCanEncodeAsImmediate(int64_t value) {
+  // If `value` does not fit but `-value` does, VIXL will automatically use
+  // the 'opposite' instruction.
+  return vixl::aarch64::Assembler::IsImmAddSub(value)
+      || vixl::aarch64::Assembler::IsImmAddSub(-value);
+}
+
 inline bool Arm64CanEncodeConstantAsImmediate(HConstant* constant, HInstruction* instr) {
   int64_t value = CodeGenerator::GetInt64ValueOf(constant);
 
@@ -249,6 +256,20 @@
     return IsUint<8>(value);
   }
 
+  // Code generation for Min/Max:
+  //    Cmp left_op, right_op
+  //    Csel dst, left_op, right_op, cond
+  if (instr->IsMin() || instr->IsMax()) {
+    if (constant->GetUses().HasExactlyOneElement()) {
+      // If value can be encoded as immediate for the Cmp, then let VIXL handle
+      // the constant generation for the Csel.
+      return AddSubCanEncodeAsImmediate(value);
+    }
+    // These values are encodable as immediates for Cmp and VIXL will use csinc and csinv
+    // with the zr register as right_op, hence no constant generation is required.
+    return constant->IsZeroBitPattern() || constant->IsOne() || constant->IsMinusOne();
+  }
+
   // For single uses we let VIXL handle the constant generation since it will
   // use registers that are not managed by the register allocator (wip0, wip1).
   if (constant->GetUses().HasExactlyOneElement()) {
@@ -275,10 +296,7 @@
            instr->IsSub())
         << instr->DebugName();
     // Uses aliases of ADD/SUB instructions.
-    // If `value` does not fit but `-value` does, VIXL will automatically use
-    // the 'opposite' instruction.
-    return vixl::aarch64::Assembler::IsImmAddSub(value)
-        || vixl::aarch64::Assembler::IsImmAddSub(-value);
+    return AddSubCanEncodeAsImmediate(value);
   }
 }