summaryrefslogtreecommitdiff
path: root/compiler/optimizing/instruction_simplifier_riscv64.cc
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/optimizing/instruction_simplifier_riscv64.cc')
-rw-r--r--compiler/optimizing/instruction_simplifier_riscv64.cc74
1 files changed, 47 insertions, 27 deletions
diff --git a/compiler/optimizing/instruction_simplifier_riscv64.cc b/compiler/optimizing/instruction_simplifier_riscv64.cc
index 8f47f66d8b..b12941b37d 100644
--- a/compiler/optimizing/instruction_simplifier_riscv64.cc
+++ b/compiler/optimizing/instruction_simplifier_riscv64.cc
@@ -41,51 +41,60 @@ class InstructionSimplifierRiscv64Visitor final : public HGraphVisitor {
}
}
- bool TryReplaceShiftAddWithOneInstruction(HShl* shl, HAdd* add) {
+ // Replace Add which has Shl with distance of 1 or 2 or 3 with Riscv64ShiftAdd
+ bool TryReplaceAddsWithShiftAdds(HShl* shl) {
// There is no reason to replace Int32 Shl+Add with ShiftAdd because of
// additional sign-extension required.
if (shl->GetType() != DataType::Type::kInt64) {
return false;
}
- if (!shl->GetRight()->IsIntConstant()) {
+ if (!shl->GetRight()->IsConstant()) {
return false;
}
+ // The bytecode does not permit the shift distance to come from a wide variable
+ DCHECK(shl->GetRight()->IsIntConstant());
+
const int32_t distance = shl->GetRight()->AsIntConstant()->GetValue();
- if (distance != 1 && distance != 2 && distance != 3) {
+ if ((distance & ~0x3) != 0) {
return false;
}
- if (!shl->HasOnlyOneNonEnvironmentUse()) {
- return false;
- }
+ bool replaced = false;
- auto* const add_other_input = add->GetLeft() == shl ? add->GetRight() : add->GetLeft();
- auto* const shift_add = new (GetGraph()->GetAllocator())
- HRiscv64ShiftAdd(shl->GetLeft(), add_other_input, distance);
+ for (const HUseListNode<HInstruction*>& use : shl->GetUses()) {
+ HInstruction* user = use.GetUser();
- DCHECK_EQ(add->GetType(), DataType::Type::kInt64)
- << "Riscv64ShiftAdd replacement should have the same 64 bit type";
- add->GetBlock()->ReplaceAndRemoveInstructionWith(add, shift_add);
- shl->GetBlock()->RemoveInstruction(shl);
+ if (!user->IsAdd()) {
+ continue;
+ }
+ HAdd* add = user->AsAdd();
+ HInstruction* left = add->GetLeft();
+ HInstruction* right = add->GetRight();
+ DCHECK_EQ(add->GetType(), DataType::Type::kInt64)
+ << "Replaceable Add must be the same 64 bit type as the input";
+
+ // If the HAdd to replace has both inputs the same HShl<1|2|3>, then
+ // don't perform the optimization. The processor will not be able to execute
+ // these shifts parallel which is the purpose of the replace below.
+ if (left == right) {
+ continue;
+ }
- return true;
- }
+ HInstruction* add_other_input = left == shl ? right : left;
+ HRiscv64ShiftAdd* shift_add = new (GetGraph()->GetAllocator())
+ HRiscv64ShiftAdd(shl->GetLeft(), add_other_input, distance);
- // Replace code looking like
- // SHL tmp, a, 1 or 2 or 3
- // ADD dst, tmp, b
- // with
- // Riscv64ShiftAdd dst, a, b
- void VisitAdd(HAdd* add) override {
- auto* const left = add->GetLeft();
- auto* const right = add->GetRight();
- if (left->IsShl() && TryReplaceShiftAddWithOneInstruction(left->AsShl(), add)) {
- return;
- } else if (right->IsShl() && TryReplaceShiftAddWithOneInstruction(right->AsShl(), add)) {
- return;
+ add->GetBlock()->ReplaceAndRemoveInstructionWith(add, shift_add);
+ replaced = true;
}
+
+ if (!shl->HasUses()) {
+ shl->GetBlock()->RemoveInstruction(shl);
+ }
+
+ return replaced;
}
void VisitAnd(HAnd* inst) override {
@@ -100,6 +109,17 @@ class InstructionSimplifierRiscv64Visitor final : public HGraphVisitor {
}
}
+ // Replace code looking like
+ // SHL tmp, a, 1 or 2 or 3
+ // ADD dst, tmp, b
+ // with
+ // Riscv64ShiftAdd dst, a, b
+ void VisitShl(HShl* inst) override {
+ if (TryReplaceAddsWithShiftAdds(inst)) {
+ RecordSimplification();
+ }
+ }
+
void VisitSub(HSub* inst) override {
if (TryMergeWithAnd(inst)) {
RecordSimplification();