summaryrefslogtreecommitdiff
path: root/compiler
diff options
context:
space:
mode:
author Anton Romanov <anton.romanov@syntacore.com> 2024-02-19 14:07:25 +0300
committer Anton Romanov <anton.romanov@syntacore.com> 2024-04-04 05:16:22 +0300
commitd923c47f745a96f5916af766dcb1c7152021b960 (patch)
tree2020142ce641350ee44e70847ccf7b8033a0d3b6 /compiler
parentaa2fe78514b1ddd8b3c0ed125ebda80c32599a70 (diff)
riscv64: Create InstructionSimplifierRiscv64, ShiftAdd
Create InstructionSimplifierRiscv64 optimization. Replace Shl (1|2|3) and Add with Riscv64ShiftAdd IR instruction. By compiling with dex2oat all the methods of applications below I got: Facebook: 45 cases TikTok: 26 cases YouTube: 19 cases of the pattern. Test: art/test/testrunner/testrunner.py --target --64 --ndebug --optimizing Change-Id: I88903450d998983bb2a628942112d7518099c3f5
Diffstat (limited to 'compiler')
-rw-r--r--compiler/Android.bp1
-rw-r--r--compiler/optimizing/code_generator_riscv64.cc35
-rw-r--r--compiler/optimizing/graph_visualizer.cc6
-rw-r--r--compiler/optimizing/instruction_simplifier_riscv64.cc99
-rw-r--r--compiler/optimizing/instruction_simplifier_riscv64.h42
-rw-r--r--compiler/optimizing/nodes.h8
-rw-r--r--compiler/optimizing/nodes_riscv64.h65
-rw-r--r--compiler/optimizing/optimization.cc8
-rw-r--r--compiler/optimizing/optimization.h1
-rw-r--r--compiler/optimizing/optimizing_compiler.cc1
10 files changed, 266 insertions, 0 deletions
diff --git a/compiler/Android.bp b/compiler/Android.bp
index e0c1744ce3..993b8970da 100644
--- a/compiler/Android.bp
+++ b/compiler/Android.bp
@@ -236,6 +236,7 @@ art_cc_defaults {
"jni/quick/riscv64/calling_convention_riscv64.cc",
"optimizing/code_generator_riscv64.cc",
"optimizing/critical_native_abi_fixup_riscv64.cc",
+ "optimizing/instruction_simplifier_riscv64.cc",
"optimizing/intrinsics_riscv64.cc",
"utils/riscv64/assembler_riscv64.cc",
"utils/riscv64/jni_macro_assembler_riscv64.cc",
diff --git a/compiler/optimizing/code_generator_riscv64.cc b/compiler/optimizing/code_generator_riscv64.cc
index 22017ed0e9..4a96623cda 100644
--- a/compiler/optimizing/code_generator_riscv64.cc
+++ b/compiler/optimizing/code_generator_riscv64.cc
@@ -5348,6 +5348,41 @@ void InstructionCodeGeneratorRISCV64::VisitXor(HXor* instruction) {
HandleBinaryOp(instruction);
}
+void LocationsBuilderRISCV64::VisitRiscv64ShiftAdd(HRiscv64ShiftAdd* instruction) {
+ DCHECK(codegen_->GetInstructionSetFeatures().HasZba());
+ DCHECK_EQ(instruction->GetType(), DataType::Type::kInt64)
+ << "Unexpected ShiftAdd type: " << instruction->GetType();
+
+ LocationSummary* locations = new (GetGraph()->GetAllocator()) LocationSummary(instruction);
+ locations->SetInAt(0, Location::RequiresRegister());
+ locations->SetInAt(1, Location::RequiresRegister());
+ locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
+}
+
+void InstructionCodeGeneratorRISCV64::VisitRiscv64ShiftAdd(HRiscv64ShiftAdd* instruction) {
+ DCHECK_EQ(instruction->GetType(), DataType::Type::kInt64)
+ << "Unexpected ShiftAdd type: " << instruction->GetType();
+ LocationSummary* locations = instruction->GetLocations();
+ XRegister first = locations->InAt(0).AsRegister<XRegister>();
+ XRegister second = locations->InAt(1).AsRegister<XRegister>();
+ XRegister dest = locations->Out().AsRegister<XRegister>();
+
+ switch (instruction->GetDistance()) {
+ case 1:
+ __ Sh1Add(dest, first, second);
+ break;
+ case 2:
+ __ Sh2Add(dest, first, second);
+ break;
+ case 3:
+ __ Sh3Add(dest, first, second);
+ break;
+ default:
+ LOG(FATAL) << "Unexpected distance of ShiftAdd: " << instruction->GetDistance();
+ UNREACHABLE();
+ }
+}
+
void LocationsBuilderRISCV64::VisitVecReplicateScalar(HVecReplicateScalar* instruction) {
UNUSED(instruction);
LOG(FATAL) << "Unimplemented";
diff --git a/compiler/optimizing/graph_visualizer.cc b/compiler/optimizing/graph_visualizer.cc
index 1e4f71f9a2..5db251cbd3 100644
--- a/compiler/optimizing/graph_visualizer.cc
+++ b/compiler/optimizing/graph_visualizer.cc
@@ -644,6 +644,12 @@ class HGraphVisualizerPrinter final : public HGraphDelegateVisitor {
}
#endif
+#if defined(ART_ENABLE_CODEGEN_riscv64)
+ void VisitRiscv64ShiftAdd(HRiscv64ShiftAdd* instruction) override {
+ StartAttributeStream("distance") << instruction->GetDistance();
+ }
+#endif
+
bool IsPass(const char* name) {
return strcmp(pass_name_, name) == 0;
}
diff --git a/compiler/optimizing/instruction_simplifier_riscv64.cc b/compiler/optimizing/instruction_simplifier_riscv64.cc
new file mode 100644
index 0000000000..0b9f8c58b1
--- /dev/null
+++ b/compiler/optimizing/instruction_simplifier_riscv64.cc
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "instruction_simplifier_riscv64.h"
+
+namespace art HIDDEN {
+
+namespace riscv64 {
+
+class InstructionSimplifierRiscv64Visitor final : public HGraphVisitor {
+ public:
+ InstructionSimplifierRiscv64Visitor(HGraph* graph, OptimizingCompilerStats* stats)
+ : HGraphVisitor(graph), stats_(stats) {}
+
+ private:
+ void RecordSimplification() {
+ MaybeRecordStat(stats_, MethodCompilationStat::kInstructionSimplificationsArch);
+ }
+
+ void VisitBasicBlock(HBasicBlock* block) override {
+ for (HInstructionIterator it(block->GetInstructions()); !it.Done(); it.Advance()) {
+ HInstruction* instruction = it.Current();
+ if (instruction->IsInBlock()) {
+ instruction->Accept(this);
+ }
+ }
+ }
+
+ bool TryReplaceShiftAddWithOneInstruction(HShl* shl, HAdd* add) {
+ // 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()) {
+ return false;
+ }
+
+ const int32_t distance = shl->GetRight()->AsIntConstant()->GetValue();
+ if (distance != 1 && distance != 2 && distance != 3) {
+ return false;
+ }
+
+ if (!shl->HasOnlyOneNonEnvironmentUse()) {
+ return 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);
+
+ 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);
+
+ return true;
+ }
+
+ // 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;
+ }
+ }
+
+ OptimizingCompilerStats* stats_ = nullptr;
+};
+
+bool InstructionSimplifierRiscv64::Run() {
+ auto visitor = InstructionSimplifierRiscv64Visitor(graph_, stats_);
+ visitor.VisitReversePostOrder();
+ return true;
+}
+
+} // namespace riscv64
+} // namespace art
diff --git a/compiler/optimizing/instruction_simplifier_riscv64.h b/compiler/optimizing/instruction_simplifier_riscv64.h
new file mode 100644
index 0000000000..2fbfedddf4
--- /dev/null
+++ b/compiler/optimizing/instruction_simplifier_riscv64.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_COMPILER_OPTIMIZING_INSTRUCTION_SIMPLIFIER_RISCV64_H_
+#define ART_COMPILER_OPTIMIZING_INSTRUCTION_SIMPLIFIER_RISCV64_H_
+
+#include "base/macros.h"
+#include "nodes.h"
+#include "optimization.h"
+
+namespace art HIDDEN {
+
+namespace riscv64 {
+
+class InstructionSimplifierRiscv64 : public HOptimization {
+ public:
+ InstructionSimplifierRiscv64(HGraph* graph, OptimizingCompilerStats* stats)
+ : HOptimization(graph, kInstructionSimplifierRiscv64PassName, stats) {}
+
+ static constexpr const char* kInstructionSimplifierRiscv64PassName =
+ "instruction_simplifier_riscv64";
+
+ bool Run() override;
+};
+
+} // namespace riscv64
+} // namespace art
+
+#endif // ART_COMPILER_OPTIMIZING_INSTRUCTION_SIMPLIFIER_RISCV64_H_
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index 12a96acaa4..37d17478ff 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -1665,7 +1665,11 @@ class HLoopInformationOutwardIterator : public ValueObject {
#define FOR_EACH_CONCRETE_INSTRUCTION_ARM64(M)
+#if defined(ART_ENABLE_CODEGEN_riscv64)
+#define FOR_EACH_CONCRETE_INSTRUCTION_RISCV64(M) M(Riscv64ShiftAdd, Instruction)
+#else
#define FOR_EACH_CONCRETE_INSTRUCTION_RISCV64(M)
+#endif
#ifndef ART_ENABLE_CODEGEN_x86
#define FOR_EACH_CONCRETE_INSTRUCTION_X86(M)
@@ -1692,6 +1696,7 @@ class HLoopInformationOutwardIterator : public ValueObject {
FOR_EACH_CONCRETE_INSTRUCTION_SHARED(M) \
FOR_EACH_CONCRETE_INSTRUCTION_ARM(M) \
FOR_EACH_CONCRETE_INSTRUCTION_ARM64(M) \
+ FOR_EACH_CONCRETE_INSTRUCTION_RISCV64(M) \
FOR_EACH_CONCRETE_INSTRUCTION_X86(M) \
FOR_EACH_CONCRETE_INSTRUCTION_X86_64(M) \
FOR_EACH_CONCRETE_INSTRUCTION_X86_COMMON(M)
@@ -8420,6 +8425,9 @@ class HIntermediateAddress final : public HExpression<2> {
#if defined(ART_ENABLE_CODEGEN_x86) || defined(ART_ENABLE_CODEGEN_x86_64)
#include "nodes_x86.h"
#endif
+#if defined(ART_ENABLE_CODEGEN_riscv64)
+#include "nodes_riscv64.h"
+#endif
namespace art HIDDEN {
diff --git a/compiler/optimizing/nodes_riscv64.h b/compiler/optimizing/nodes_riscv64.h
new file mode 100644
index 0000000000..4916e57944
--- /dev/null
+++ b/compiler/optimizing/nodes_riscv64.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_COMPILER_OPTIMIZING_NODES_RISCV64_H_
+#define ART_COMPILER_OPTIMIZING_NODES_RISCV64_H_
+
+namespace art HIDDEN {
+
+class HRiscv64ShiftAdd final : public HBinaryOperation {
+ public:
+ HRiscv64ShiftAdd(HInstruction* left,
+ HInstruction* right,
+ uint32_t distance,
+ uint32_t dex_pc = kNoDexPc)
+ : HBinaryOperation(
+ kRiscv64ShiftAdd, DataType::Type::kInt64, left, right, SideEffects::None(), dex_pc) {
+ DCHECK_GE(distance, 1u);
+ DCHECK_LE(distance, 3u);
+
+ SetPackedField<DistanceField>(distance);
+ }
+
+ uint32_t GetDistance() const { return GetPackedField<DistanceField>(); }
+
+ bool IsCommutative() const override { return false; }
+ bool InstructionDataEquals(const HInstruction* other) const override {
+ return GetPackedFields() == other->AsRiscv64ShiftAdd()->GetPackedFields();
+ }
+
+ HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const override {
+ const int64_t value = y->GetValue() + (x->GetValue() << GetDistance());
+ return GetBlock()->GetGraph()->GetLongConstant(value, GetDexPc());
+ }
+
+ DECLARE_INSTRUCTION(Riscv64ShiftAdd);
+
+ protected:
+ DEFAULT_COPY_CONSTRUCTOR(Riscv64ShiftAdd);
+
+ private:
+ static constexpr size_t kFieldDistance = kNumberOfGenericPackedBits;
+ static constexpr size_t kFieldDistanceSize = MinimumBitsToStore(3u);
+ static constexpr size_t kNumberOfRiscv64ShiftAddPackedBits =
+ kFieldDistance + kFieldDistanceSize;
+ static_assert(kNumberOfRiscv64ShiftAddPackedBits <= kMaxNumberOfPackedBits,
+ "Too many packed fields.");
+ using DistanceField = BitField<uint32_t, kFieldDistance, kFieldDistanceSize>;
+};
+
+} // namespace art
+
+#endif // ART_COMPILER_OPTIMIZING_NODES_RISCV64_H_
diff --git a/compiler/optimizing/optimization.cc b/compiler/optimizing/optimization.cc
index dd57100d88..ef1f36ab08 100644
--- a/compiler/optimizing/optimization.cc
+++ b/compiler/optimizing/optimization.cc
@@ -25,6 +25,7 @@
#endif
#ifdef ART_ENABLE_CODEGEN_riscv64
#include "critical_native_abi_fixup_riscv64.h"
+#include "instruction_simplifier_riscv64.h"
#endif
#ifdef ART_ENABLE_CODEGEN_x86
#include "pc_relative_fixups_x86.h"
@@ -114,6 +115,8 @@ const char* OptimizationPassName(OptimizationPass pass) {
#ifdef ART_ENABLE_CODEGEN_riscv64
case OptimizationPass::kCriticalNativeAbiFixupRiscv64:
return riscv64::CriticalNativeAbiFixupRiscv64::kCriticalNativeAbiFixupRiscv64PassName;
+ case OptimizationPass::kInstructionSimplifierRiscv64:
+ return riscv64::InstructionSimplifierRiscv64::kInstructionSimplifierRiscv64PassName;
#endif
#ifdef ART_ENABLE_CODEGEN_x86
case OptimizationPass::kPcRelativeFixupsX86:
@@ -163,6 +166,7 @@ OptimizationPass OptimizationPassByName(const std::string& pass_name) {
#endif
#ifdef ART_ENABLE_CODEGEN_riscv64
X(OptimizationPass::kCriticalNativeAbiFixupRiscv64);
+ X(OptimizationPass::kInstructionSimplifierRiscv64);
#endif
#ifdef ART_ENABLE_CODEGEN_x86
X(OptimizationPass::kPcRelativeFixupsX86);
@@ -314,6 +318,10 @@ ArenaVector<HOptimization*> ConstructOptimizations(
DCHECK(alt_name == nullptr) << "arch-specific pass does not support alternative name";
opt = new (allocator) riscv64::CriticalNativeAbiFixupRiscv64(graph, stats);
break;
+ case OptimizationPass::kInstructionSimplifierRiscv64:
+ DCHECK(alt_name == nullptr) << "arch-specific pass does not support alternative name";
+ opt = new (allocator) riscv64::InstructionSimplifierRiscv64(graph, stats);
+ break;
#endif
#ifdef ART_ENABLE_CODEGEN_x86
case OptimizationPass::kPcRelativeFixupsX86:
diff --git a/compiler/optimizing/optimization.h b/compiler/optimizing/optimization.h
index 55aa8f914b..8bc9da49fc 100644
--- a/compiler/optimizing/optimization.h
+++ b/compiler/optimizing/optimization.h
@@ -94,6 +94,7 @@ enum class OptimizationPass {
#endif
#ifdef ART_ENABLE_CODEGEN_riscv64
kCriticalNativeAbiFixupRiscv64,
+ kInstructionSimplifierRiscv64,
#endif
#ifdef ART_ENABLE_CODEGEN_x86
kPcRelativeFixupsX86,
diff --git a/compiler/optimizing/optimizing_compiler.cc b/compiler/optimizing/optimizing_compiler.cc
index f532681527..763dc88e8a 100644
--- a/compiler/optimizing/optimizing_compiler.cc
+++ b/compiler/optimizing/optimizing_compiler.cc
@@ -535,6 +535,7 @@ bool OptimizingCompiler::RunArchOptimizations(HGraph* graph,
#if defined(ART_ENABLE_CODEGEN_riscv64)
case InstructionSet::kRiscv64: {
OptimizationDef riscv64_optimizations[] = {
+ OptDef(OptimizationPass::kInstructionSimplifierRiscv64),
OptDef(OptimizationPass::kSideEffectsAnalysis),
OptDef(OptimizationPass::kGlobalValueNumbering, "GVN$after_arch"),
OptDef(OptimizationPass::kCriticalNativeAbiFixupRiscv64)