Ensure art::HRor support boolean, byte, short and char inputs.
Also extend tests covering the IntegerRotateLeft,
LongRotateLeft, IntegerRotateRight and LongRotateRight
intrinsics and their translation into an art::HRor
instruction.
Bug: 27682579
Change-Id: I89f6ea6a7315659a172482bf09875cfb7e7422a1
diff --git a/compiler/optimizing/code_generator_arm.cc b/compiler/optimizing/code_generator_arm.cc
index 34fd9ff..c164f2b 100644
--- a/compiler/optimizing/code_generator_arm.cc
+++ b/compiler/optimizing/code_generator_arm.cc
@@ -3273,7 +3273,8 @@
__ Bind(&end);
}
}
-void LocationsBuilderARM::HandleRotate(HRor* ror) {
+
+void LocationsBuilderARM::VisitRor(HRor* ror) {
LocationSummary* locations =
new (GetGraph()->GetArena()) LocationSummary(ror, LocationSummary::kNoCall);
switch (ror->GetResultType()) {
@@ -3300,7 +3301,7 @@
}
}
-void InstructionCodeGeneratorARM::HandleRotate(HRor* ror) {
+void InstructionCodeGeneratorARM::VisitRor(HRor* ror) {
LocationSummary* locations = ror->GetLocations();
Primitive::Type type = ror->GetResultType();
switch (type) {
@@ -3318,14 +3319,6 @@
}
}
-void LocationsBuilderARM::VisitRor(HRor* op) {
- HandleRotate(op);
-}
-
-void InstructionCodeGeneratorARM::VisitRor(HRor* op) {
- HandleRotate(op);
-}
-
void LocationsBuilderARM::HandleShift(HBinaryOperation* op) {
DCHECK(op->IsShl() || op->IsShr() || op->IsUShr());
diff --git a/compiler/optimizing/code_generator_arm.h b/compiler/optimizing/code_generator_arm.h
index 5c0f31c..cc4aa14 100644
--- a/compiler/optimizing/code_generator_arm.h
+++ b/compiler/optimizing/code_generator_arm.h
@@ -174,7 +174,6 @@
void HandleCondition(HCondition* condition);
void HandleIntegerRotate(LocationSummary* locations);
void HandleLongRotate(LocationSummary* locations);
- void HandleRotate(HRor* ror);
void HandleShift(HBinaryOperation* operation);
void HandleFieldSet(HInstruction* instruction, const FieldInfo& field_info);
void HandleFieldGet(HInstruction* instruction, const FieldInfo& field_info);
@@ -222,7 +221,6 @@
void HandleCondition(HCondition* condition);
void HandleIntegerRotate(LocationSummary* locations);
void HandleLongRotate(LocationSummary* locations);
- void HandleRotate(HRor* ror);
void HandleShift(HBinaryOperation* operation);
void GenerateWideAtomicStore(Register addr, uint32_t offset,
diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc
index 9acaa1d..68c10d4 100644
--- a/compiler/optimizing/code_generator_x86.cc
+++ b/compiler/optimizing/code_generator_x86.cc
@@ -3981,8 +3981,7 @@
__ cmovl(kNotEqual, first_reg_hi, first_reg_lo);
__ cmovl(kNotEqual, first_reg_lo, temp_reg);
} else {
- int32_t shift_amt =
- CodeGenerator::GetInt64ValueOf(second.GetConstant()) & kMaxLongShiftValue;
+ int32_t shift_amt = CodeGenerator::GetInt64ValueOf(second.GetConstant()) & kMaxLongShiftValue;
if (shift_amt == 0) {
// Already fine.
return;
diff --git a/compiler/optimizing/common_arm64.h b/compiler/optimizing/common_arm64.h
index 10d8343..6c55194 100644
--- a/compiler/optimizing/common_arm64.h
+++ b/compiler/optimizing/common_arm64.h
@@ -194,7 +194,8 @@
}
static bool CanEncodeConstantAsImmediate(HConstant* constant, HInstruction* instr) {
- DCHECK(constant->IsIntConstant() || constant->IsLongConstant() || constant->IsNullConstant());
+ DCHECK(constant->IsIntConstant() || constant->IsLongConstant() || constant->IsNullConstant())
+ << constant->DebugName();
// 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).
@@ -221,7 +222,8 @@
instr->IsBoundsCheck() ||
instr->IsCompare() ||
instr->IsCondition() ||
- instr->IsSub());
+ 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.
diff --git a/compiler/optimizing/graph_checker.cc b/compiler/optimizing/graph_checker.cc
index 1fbb2d5..11e3689 100644
--- a/compiler/optimizing/graph_checker.cc
+++ b/compiler/optimizing/graph_checker.cc
@@ -945,7 +945,7 @@
Primitive::PrettyDescriptor(result_type)));
}
} else {
- // Use the first input, so that we can also make this check for shift operations.
+ // Use the first input, so that we can also make this check for shift and rotate operations.
if (Primitive::PrimitiveKind(result_type) != Primitive::PrimitiveKind(lhs_type)) {
AddError(StringPrintf("Binary operation %s %d has a result kind different "
"from its input kind: %s vs %s.",
diff --git a/compiler/optimizing/instruction_simplifier.cc b/compiler/optimizing/instruction_simplifier.cc
index dd2977f..4a8186a 100644
--- a/compiler/optimizing/instruction_simplifier.cc
+++ b/compiler/optimizing/instruction_simplifier.cc
@@ -96,7 +96,7 @@
bool CanEnsureNotNullAt(HInstruction* instr, HInstruction* at) const;
- void SimplifyRotate(HInvoke* invoke, bool is_left);
+ void SimplifyRotate(HInvoke* invoke, bool is_left, Primitive::Type type);
void SimplifySystemArrayCopy(HInvoke* invoke);
void SimplifyStringEquals(HInvoke* invoke);
void SimplifyCompare(HInvoke* invoke, bool is_signum, Primitive::Type type);
@@ -262,10 +262,8 @@
bool InstructionSimplifierVisitor::ReplaceRotateWithRor(HBinaryOperation* op,
HUShr* ushr,
HShl* shl) {
- DCHECK(op->IsAdd() || op->IsXor() || op->IsOr());
- HRor* ror = new (GetGraph()->GetArena()) HRor(ushr->GetType(),
- ushr->GetLeft(),
- ushr->GetRight());
+ DCHECK(op->IsAdd() || op->IsXor() || op->IsOr()) << op->DebugName();
+ HRor* ror = new (GetGraph()->GetArena()) HRor(ushr->GetType(), ushr->GetLeft(), ushr->GetRight());
op->GetBlock()->ReplaceAndRemoveInstructionWith(op, ror);
if (!ushr->HasUses()) {
ushr->GetBlock()->RemoveInstruction(ushr);
@@ -1232,7 +1230,7 @@
// with
// SHL dst, src, log2(pow_of_2)
HIntConstant* shift = GetGraph()->GetIntConstant(WhichPowerOf2(factor));
- HShl* shl = new(allocator) HShl(type, input_other, shift);
+ HShl* shl = new (allocator) HShl(type, input_other, shift);
block->ReplaceAndRemoveInstructionWith(instruction, shl);
RecordSimplification();
} else if (IsPowerOfTwo(factor - 1)) {
@@ -1531,7 +1529,9 @@
}
}
-void InstructionSimplifierVisitor::SimplifyRotate(HInvoke* invoke, bool is_left) {
+void InstructionSimplifierVisitor::SimplifyRotate(HInvoke* invoke,
+ bool is_left,
+ Primitive::Type type) {
DCHECK(invoke->IsInvokeStaticOrDirect());
DCHECK_EQ(invoke->GetOriginalInvokeType(), InvokeType::kStatic);
HInstruction* value = invoke->InputAt(0);
@@ -1541,7 +1541,7 @@
distance = new (GetGraph()->GetArena()) HNeg(distance->GetType(), distance);
invoke->GetBlock()->InsertInstructionBefore(distance, invoke);
}
- HRor* ror = new (GetGraph()->GetArena()) HRor(value->GetType(), value, distance);
+ HRor* ror = new (GetGraph()->GetArena()) HRor(type, value, distance);
invoke->GetBlock()->ReplaceAndRemoveInstructionWith(invoke, ror);
// Remove ClinitCheck and LoadClass, if possible.
HInstruction* clinit = invoke->InputAt(invoke->InputCount() - 1);
@@ -1694,12 +1694,16 @@
SimplifySystemArrayCopy(instruction);
break;
case Intrinsics::kIntegerRotateRight:
+ SimplifyRotate(instruction, /* is_left */ false, Primitive::kPrimInt);
+ break;
case Intrinsics::kLongRotateRight:
- SimplifyRotate(instruction, false);
+ SimplifyRotate(instruction, /* is_left */ false, Primitive::kPrimLong);
break;
case Intrinsics::kIntegerRotateLeft:
+ SimplifyRotate(instruction, /* is_left */ true, Primitive::kPrimInt);
+ break;
case Intrinsics::kLongRotateLeft:
- SimplifyRotate(instruction, true);
+ SimplifyRotate(instruction, /* is_left */ true, Primitive::kPrimLong);
break;
case Intrinsics::kIntegerCompare:
SimplifyCompare(instruction, /* is_signum */ false, Primitive::kPrimInt);
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index e2a54f4..46377ee 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -4689,7 +4689,12 @@
class HRor : public HBinaryOperation {
public:
HRor(Primitive::Type result_type, HInstruction* value, HInstruction* distance)
- : HBinaryOperation(result_type, value, distance) {}
+ : HBinaryOperation(result_type, value, distance) {
+ if (kIsDebugBuild) {
+ DCHECK_EQ(result_type, Primitive::PrimitiveKind(value->GetType()));
+ DCHECK_EQ(Primitive::kPrimInt, Primitive::PrimitiveKind(distance->GetType()));
+ }
+ }
template <typename T, typename U, typename V>
T Compute(T x, U y, V max_shift_value) const {