Tighten art::HNeg type constraints on its input.

Ensure art::HNeg is only passed a type having the kind of
its input.  For a boolean, byte, short, or char input, it
means HNeg's type should be int.

Bug: 27684275
Change-Id: Ic8442c62090a8ab65590754874a14a0deb7acd8d
diff --git a/compiler/optimizing/graph_checker.cc b/compiler/optimizing/graph_checker.cc
index 11e3689..9c1ded2 100644
--- a/compiler/optimizing/graph_checker.cc
+++ b/compiler/optimizing/graph_checker.cc
@@ -917,6 +917,19 @@
   }
 }
 
+void GraphChecker::VisitNeg(HNeg* instruction) {
+  VisitInstruction(instruction);
+  Primitive::Type input_type = instruction->InputAt(0)->GetType();
+  Primitive::Type result_type = instruction->GetType();
+  if (result_type != Primitive::PrimitiveKind(input_type)) {
+    AddError(StringPrintf("Binary operation %s %d has a result type different "
+                          "from its input kind: %s vs %s.",
+                          instruction->DebugName(), instruction->GetId(),
+                          Primitive::PrettyDescriptor(result_type),
+                          Primitive::PrettyDescriptor(input_type)));
+  }
+}
+
 void GraphChecker::VisitBinaryOperation(HBinaryOperation* op) {
   VisitInstruction(op);
   Primitive::Type lhs_type = op->InputAt(0)->GetType();
diff --git a/compiler/optimizing/graph_checker.h b/compiler/optimizing/graph_checker.h
index 52252cd..a835084 100644
--- a/compiler/optimizing/graph_checker.h
+++ b/compiler/optimizing/graph_checker.h
@@ -56,6 +56,7 @@
   void VisitInstanceOf(HInstanceOf* check) OVERRIDE;
   void VisitInvokeStaticOrDirect(HInvokeStaticOrDirect* invoke) OVERRIDE;
   void VisitLoadException(HLoadException* load) OVERRIDE;
+  void VisitNeg(HNeg* instruction) OVERRIDE;
   void VisitPackedSwitch(HPackedSwitch* instruction) OVERRIDE;
   void VisitReturn(HReturn* ret) OVERRIDE;
   void VisitReturnVoid(HReturnVoid* ret) OVERRIDE;
diff --git a/compiler/optimizing/instruction_simplifier.cc b/compiler/optimizing/instruction_simplifier.cc
index 4a8186a..820c696 100644
--- a/compiler/optimizing/instruction_simplifier.cc
+++ b/compiler/optimizing/instruction_simplifier.cc
@@ -1538,7 +1538,10 @@
   HInstruction* distance = invoke->InputAt(1);
   // Replace the invoke with an HRor.
   if (is_left) {
-    distance = new (GetGraph()->GetArena()) HNeg(distance->GetType(), distance);
+    // Unconditionally set the type of the negated distance to `int`,
+    // as shift and rotate operations expect a 32-bit (or narrower)
+    // value for their distance input.
+    distance = new (GetGraph()->GetArena()) HNeg(Primitive::kPrimInt, distance);
     invoke->GetBlock()->InsertInstructionBefore(distance, invoke);
   }
   HRor* ror = new (GetGraph()->GetArena()) HRor(type, value, distance);
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index 46377ee..f63d661 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -4148,7 +4148,9 @@
 class HNeg : public HUnaryOperation {
  public:
   HNeg(Primitive::Type result_type, HInstruction* input, uint32_t dex_pc = kNoDexPc)
-      : HUnaryOperation(result_type, input, dex_pc) {}
+      : HUnaryOperation(result_type, input, dex_pc) {
+    DCHECK_EQ(result_type, Primitive::PrimitiveKind(input->GetType()));
+  }
 
   template <typename T> T Compute(T x) const { return -x; }