summaryrefslogtreecommitdiff
path: root/compiler/optimizing
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/optimizing')
-rw-r--r--compiler/optimizing/code_generator_riscv64.h1
-rw-r--r--compiler/optimizing/control_flow_simplifier.cc (renamed from compiler/optimizing/code_flow_simplifier.cc)16
-rw-r--r--compiler/optimizing/control_flow_simplifier.h (renamed from compiler/optimizing/code_flow_simplifier.h)18
-rw-r--r--compiler/optimizing/control_flow_simplifier_test.cc (renamed from compiler/optimizing/code_flow_simplifier_test.cc)28
-rw-r--r--compiler/optimizing/dead_code_elimination.cc6
-rw-r--r--compiler/optimizing/intrinsics_riscv64.cc85
-rw-r--r--compiler/optimizing/optimization.cc12
-rw-r--r--compiler/optimizing/optimization.h2
-rw-r--r--compiler/optimizing/optimizing_compiler.cc2
9 files changed, 127 insertions, 43 deletions
diff --git a/compiler/optimizing/code_generator_riscv64.h b/compiler/optimizing/code_generator_riscv64.h
index 588243e86d..1945cacb6f 100644
--- a/compiler/optimizing/code_generator_riscv64.h
+++ b/compiler/optimizing/code_generator_riscv64.h
@@ -88,7 +88,6 @@ static constexpr int32_t kFClassNaNMinValue = 0x100;
V(CRC32Update) \
V(CRC32UpdateBytes) \
V(CRC32UpdateByteBuffer) \
- V(MethodHandleInvokeExact) \
V(MethodHandleInvoke) \
V(UnsafeArrayBaseOffset) \
V(JdkUnsafeArrayBaseOffset) \
diff --git a/compiler/optimizing/code_flow_simplifier.cc b/compiler/optimizing/control_flow_simplifier.cc
index 855da3e959..3e1c0ac0fc 100644
--- a/compiler/optimizing/code_flow_simplifier.cc
+++ b/compiler/optimizing/control_flow_simplifier.cc
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "code_flow_simplifier.h"
+#include "control_flow_simplifier.h"
#include "optimizing/nodes.h"
#include "reference_type_propagation.h"
@@ -23,9 +23,9 @@ namespace art HIDDEN {
static constexpr size_t kMaxInstructionsInBranch = 1u;
-HCodeFlowSimplifier::HCodeFlowSimplifier(HGraph* graph,
- OptimizingCompilerStats* stats,
- const char* name)
+HControlFlowSimplifier::HControlFlowSimplifier(HGraph* graph,
+ OptimizingCompilerStats* stats,
+ const char* name)
: HOptimization(graph, name, stats) {
}
@@ -95,7 +95,7 @@ static std::pair<bool, HPhi*> HasAtMostOnePhiWithDifferentInputs(HBasicBlock* bl
return {true, select_phi};
}
-bool HCodeFlowSimplifier::TryGenerateSelectSimpleDiamondPattern(
+bool HControlFlowSimplifier::TryGenerateSelectSimpleDiamondPattern(
HBasicBlock* block, ScopedArenaSafeMap<HInstruction*, HSelect*>* cache) {
DCHECK(block->GetLastInstruction()->IsIf());
HIf* if_instruction = block->GetLastInstruction()->AsIf();
@@ -230,7 +230,7 @@ bool HCodeFlowSimplifier::TryGenerateSelectSimpleDiamondPattern(
return true;
}
-HBasicBlock* HCodeFlowSimplifier::TryFixupDoubleDiamondPattern(HBasicBlock* block) {
+HBasicBlock* HControlFlowSimplifier::TryFixupDoubleDiamondPattern(HBasicBlock* block) {
DCHECK(block->GetLastInstruction()->IsIf());
HIf* if_instruction = block->GetLastInstruction()->AsIf();
HBasicBlock* true_block = if_instruction->IfTrueSuccessor();
@@ -323,12 +323,12 @@ HBasicBlock* HCodeFlowSimplifier::TryFixupDoubleDiamondPattern(HBasicBlock* bloc
return inner_if_block;
}
-bool HCodeFlowSimplifier::Run() {
+bool HControlFlowSimplifier::Run() {
bool did_select = false;
// Select cache with local allocator.
ScopedArenaAllocator allocator(graph_->GetArenaStack());
ScopedArenaSafeMap<HInstruction*, HSelect*> cache(
- std::less<HInstruction*>(), allocator.Adapter(kArenaAllocCodeFlowSimplifier));
+ std::less<HInstruction*>(), allocator.Adapter(kArenaAllocControlFlowSimplifier));
// Iterate in post order in the unlikely case that removing one occurrence of
// the selection pattern empties a branch block of another occurrence.
diff --git a/compiler/optimizing/code_flow_simplifier.h b/compiler/optimizing/control_flow_simplifier.h
index 36d8d3d95b..0c74ec299f 100644
--- a/compiler/optimizing/code_flow_simplifier.h
+++ b/compiler/optimizing/control_flow_simplifier.h
@@ -54,8 +54,8 @@
* run after the instruction simplifier has removed redundant suspend checks.
*/
-#ifndef ART_COMPILER_OPTIMIZING_CODE_FLOW_SIMPLIFIER_H_
-#define ART_COMPILER_OPTIMIZING_CODE_FLOW_SIMPLIFIER_H_
+#ifndef ART_COMPILER_OPTIMIZING_CONTROL_FLOW_SIMPLIFIER_H_
+#define ART_COMPILER_OPTIMIZING_CONTROL_FLOW_SIMPLIFIER_H_
#include "base/macros.h"
#include "base/scoped_arena_containers.h"
@@ -64,15 +64,15 @@
namespace art HIDDEN {
-class HCodeFlowSimplifier : public HOptimization {
+class HControlFlowSimplifier : public HOptimization {
public:
- HCodeFlowSimplifier(HGraph* graph,
- OptimizingCompilerStats* stats,
- const char* name = kCodeFlowSimplifierPassName);
+ HControlFlowSimplifier(HGraph* graph,
+ OptimizingCompilerStats* stats,
+ const char* name = kControlFlowSimplifierPassName);
bool Run() override;
- static constexpr const char* kCodeFlowSimplifierPassName = "code_flow_simplifier";
+ static constexpr const char* kControlFlowSimplifierPassName = "control_flow_simplifier";
private:
bool TryGenerateSelectSimpleDiamondPattern(HBasicBlock* block,
@@ -112,9 +112,9 @@ class HCodeFlowSimplifier : public HOptimization {
// when that gets resolved we get another one with the outer if.
HBasicBlock* TryFixupDoubleDiamondPattern(HBasicBlock* block);
- DISALLOW_COPY_AND_ASSIGN(HCodeFlowSimplifier);
+ DISALLOW_COPY_AND_ASSIGN(HControlFlowSimplifier);
};
} // namespace art
-#endif // ART_COMPILER_OPTIMIZING_CODE_FLOW_SIMPLIFIER_H_
+#endif // ART_COMPILER_OPTIMIZING_CONTROL_FLOW_SIMPLIFIER_H_
diff --git a/compiler/optimizing/code_flow_simplifier_test.cc b/compiler/optimizing/control_flow_simplifier_test.cc
index 8945e03619..2e88c6c77b 100644
--- a/compiler/optimizing/code_flow_simplifier_test.cc
+++ b/compiler/optimizing/control_flow_simplifier_test.cc
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "code_flow_simplifier.h"
+#include "control_flow_simplifier.h"
#include "base/arena_allocator.h"
#include "base/macros.h"
@@ -25,7 +25,7 @@
namespace art HIDDEN {
-class CodeFlowSimplifierTest : public OptimizingUnitTest {
+class ControlFlowSimplifierTest : public OptimizingUnitTest {
protected:
HPhi* ConstructBasicGraphForSelect(HBasicBlock* return_block, HInstruction* instr) {
HParameterValue* bool_param = MakeParam(DataType::Type::kBool);
@@ -38,18 +38,18 @@ class CodeFlowSimplifierTest : public OptimizingUnitTest {
return phi;
}
- bool CheckGraphAndTryCodeFlowSimplifier() {
+ bool CheckGraphAndTryControlFlowSimplifier() {
graph_->BuildDominatorTree();
EXPECT_TRUE(CheckGraph());
SideEffectsAnalysis side_effects(graph_);
side_effects.Run();
- return HCodeFlowSimplifier(graph_, /*handles*/ nullptr, /*stats*/ nullptr).Run();
+ return HControlFlowSimplifier(graph_, /*handles*/ nullptr, /*stats*/ nullptr).Run();
}
};
// HDivZeroCheck might throw and should not be hoisted from the conditional to an unconditional.
-TEST_F(CodeFlowSimplifierTest, testZeroCheckPreventsSelect) {
+TEST_F(ControlFlowSimplifierTest, testZeroCheckPreventsSelect) {
HBasicBlock* return_block = InitEntryMainExitGraphWithReturnVoid();
HParameterValue* param = MakeParam(DataType::Type::kInt32);
HDivZeroCheck* instr = new (GetAllocator()) HDivZeroCheck(param, 0);
@@ -57,22 +57,22 @@ TEST_F(CodeFlowSimplifierTest, testZeroCheckPreventsSelect) {
ManuallyBuildEnvFor(instr, {param, graph_->GetIntConstant(1)});
- EXPECT_FALSE(CheckGraphAndTryCodeFlowSimplifier());
+ EXPECT_FALSE(CheckGraphAndTryControlFlowSimplifier());
EXPECT_INS_RETAINED(phi);
}
-// Test that CodeFlowSimplifier succeeds with HAdd.
-TEST_F(CodeFlowSimplifierTest, testSelectWithAdd) {
+// Test that ControlFlowSimplifier succeeds with HAdd.
+TEST_F(ControlFlowSimplifierTest, testSelectWithAdd) {
HBasicBlock* return_block = InitEntryMainExitGraphWithReturnVoid();
HParameterValue* param = MakeParam(DataType::Type::kInt32);
HAdd* instr = new (GetAllocator()) HAdd(DataType::Type::kInt32, param, param, /*dex_pc=*/ 0);
HPhi* phi = ConstructBasicGraphForSelect(return_block, instr);
- EXPECT_TRUE(CheckGraphAndTryCodeFlowSimplifier());
+ EXPECT_TRUE(CheckGraphAndTryControlFlowSimplifier());
EXPECT_INS_REMOVED(phi);
}
-// Test that CodeFlowSimplifier succeeds if there is an additional `HPhi` with identical inputs.
-TEST_F(CodeFlowSimplifierTest, testSelectWithAddAndExtraPhi) {
+// Test that ControlFlowSimplifier succeeds if there is an additional `HPhi` with identical inputs.
+TEST_F(ControlFlowSimplifierTest, testSelectWithAddAndExtraPhi) {
// Create a graph with three blocks merging to the `return_block`.
HBasicBlock* return_block = InitEntryMainExitGraphWithReturnVoid();
HParameterValue* bool_param1 = MakeParam(DataType::Type::kBool);
@@ -96,7 +96,7 @@ TEST_F(CodeFlowSimplifierTest, testSelectWithAddAndExtraPhi) {
// Prevent second `HSelect` match. Do not rely on the "instructions per branch" limit.
MakeInvokeStatic(left, DataType::Type::kVoid, {}, {});
- EXPECT_TRUE(CheckGraphAndTryCodeFlowSimplifier());
+ EXPECT_TRUE(CheckGraphAndTryControlFlowSimplifier());
ASSERT_BLOCK_RETAINED(left);
ASSERT_BLOCK_REMOVED(mid);
@@ -110,7 +110,7 @@ TEST_F(CodeFlowSimplifierTest, testSelectWithAddAndExtraPhi) {
}
// Test `HSelect` optimization in an irreducible loop.
-TEST_F(CodeFlowSimplifierTest, testSelectInIrreducibleLoop) {
+TEST_F(ControlFlowSimplifierTest, testSelectInIrreducibleLoop) {
HBasicBlock* return_block = InitEntryMainExitGraphWithReturnVoid();
auto [split, left_header, right_header, body] = CreateIrreducibleLoop(return_block);
@@ -130,7 +130,7 @@ TEST_F(CodeFlowSimplifierTest, testSelectInIrreducibleLoop) {
auto [if_block, then_block, else_block] = CreateDiamondPattern(body, bool_param);
HPhi* phi = MakePhi(body, {const1, const0});
- EXPECT_TRUE(CheckGraphAndTryCodeFlowSimplifier());
+ EXPECT_TRUE(CheckGraphAndTryControlFlowSimplifier());
HLoopInformation* loop_info = left_header->GetLoopInformation();
ASSERT_TRUE(loop_info != nullptr);
ASSERT_TRUE(loop_info->IsIrreducible());
diff --git a/compiler/optimizing/dead_code_elimination.cc b/compiler/optimizing/dead_code_elimination.cc
index ede909526d..c5ec0b93b2 100644
--- a/compiler/optimizing/dead_code_elimination.cc
+++ b/compiler/optimizing/dead_code_elimination.cc
@@ -526,10 +526,10 @@ void HDeadCodeElimination::MaybeAddPhi(HBasicBlock* block) {
// |
// 8
// `7` (which would be `block` in this example), and `6` will come from both the true path and
- // the false path of `1`. We bumped into something similar in `HCodeFlowSimplifier`. See
- // `HCodeFlowSimplifier::TryFixupDoubleDiamondPattern()`.
+ // the false path of `1`. We bumped into something similar in `HControlFlowSimplifier`. See
+ // `HControlFlowSimplifier::TryFixupDoubleDiamondPattern()`.
// TODO(solanes): Figure out if we can fix up the graph into a double diamond in a generic way
- // so that `HDeadCodeElimination` and `HCodeFlowSimplifier` can take advantage of it.
+ // so that `HDeadCodeElimination` and `HControlFlowSimplifier` can take advantage of it.
if (!same_input) {
// `1` and `7` having the opposite condition is a case we are missing. We could potentially
diff --git a/compiler/optimizing/intrinsics_riscv64.cc b/compiler/optimizing/intrinsics_riscv64.cc
index 65776236c1..385ac0e857 100644
--- a/compiler/optimizing/intrinsics_riscv64.cc
+++ b/compiler/optimizing/intrinsics_riscv64.cc
@@ -90,6 +90,39 @@ class ReadBarrierSystemArrayCopySlowPathRISCV64 : public SlowPathCodeRISCV64 {
DISALLOW_COPY_AND_ASSIGN(ReadBarrierSystemArrayCopySlowPathRISCV64);
};
+// The MethodHandle.invokeExact intrinsic sets up arguments to match the target method call. If we
+// need to go to the slow path, we call art_quick_invoke_polymorphic_with_hidden_receiver, which
+// expects the MethodHandle object in a0 (in place of the actual ArtMethod).
+class InvokePolymorphicSlowPathRISCV64 : public SlowPathCodeRISCV64 {
+ public:
+ InvokePolymorphicSlowPathRISCV64(HInstruction* instruction, XRegister method_handle)
+ : SlowPathCodeRISCV64(instruction), method_handle_(method_handle) {
+ DCHECK(instruction->IsInvokePolymorphic());
+ }
+
+ void EmitNativeCode(CodeGenerator* codegen_in) override {
+ CodeGeneratorRISCV64* codegen = down_cast<CodeGeneratorRISCV64*>(codegen_in);
+ Riscv64Assembler* assembler = codegen->GetAssembler();
+ __ Bind(GetEntryLabel());
+
+ SaveLiveRegisters(codegen, instruction_->GetLocations());
+ // Passing `MethodHandle` object as hidden argument.
+ __ Mv(A0, method_handle_);
+ codegen->InvokeRuntime(QuickEntrypointEnum::kQuickInvokePolymorphicWithHiddenReceiver,
+ instruction_,
+ instruction_->GetDexPc());
+
+ RestoreLiveRegisters(codegen, instruction_->GetLocations());
+ __ J(GetExitLabel());
+ }
+
+ const char* GetDescription() const override { return "InvokePolymorphicSlowPathRISCV64"; }
+
+ private:
+ const XRegister method_handle_;
+ DISALLOW_COPY_AND_ASSIGN(InvokePolymorphicSlowPathRISCV64);
+};
+
bool IntrinsicLocationsBuilderRISCV64::TryDispatch(HInvoke* invoke) {
Dispatch(invoke);
LocationSummary* res = invoke->GetLocations();
@@ -5733,6 +5766,58 @@ void IntrinsicCodeGeneratorRISCV64::VisitMathCopySignFloat(HInvoke* invoke) {
GenMathCopySign(codegen_, invoke, DataType::Type::kFloat32);
}
+void IntrinsicLocationsBuilderRISCV64::VisitMethodHandleInvokeExact(HInvoke* invoke) {
+ ArenaAllocator* allocator = invoke->GetBlock()->GetGraph()->GetAllocator();
+ LocationSummary* locations = new (allocator)
+ LocationSummary(invoke, LocationSummary::kCallOnMainAndSlowPath, kIntrinsified);
+
+ InvokeDexCallingConventionVisitorRISCV64 calling_convention;
+ locations->SetOut(calling_convention.GetReturnLocation(invoke->GetType()));
+ locations->SetInAt(0, Location::RequiresRegister());
+
+ // Accomodating LocationSummary for underlying invoke-* call.
+ uint32_t number_of_args = invoke->GetNumberOfArguments();
+ for (uint32_t i = 1; i < number_of_args; ++i) {
+ locations->SetInAt(i, calling_convention.GetNextLocation(invoke->InputAt(i)->GetType()));
+ }
+
+ // The last input is MethodType object corresponding to the call-site.
+ locations->SetInAt(number_of_args, Location::RequiresRegister());
+
+ locations->AddTemp(Location::RequiresRegister());
+ locations->AddTemp(calling_convention.GetMethodLocation());
+}
+
+void IntrinsicCodeGeneratorRISCV64::VisitMethodHandleInvokeExact(HInvoke* invoke) {
+ LocationSummary* locations = invoke->GetLocations();
+ XRegister method_handle = locations->InAt(0).AsRegister<XRegister>();
+ SlowPathCodeRISCV64* slow_path =
+ new (codegen_->GetScopedAllocator()) InvokePolymorphicSlowPathRISCV64(invoke, method_handle);
+
+ codegen_->AddSlowPath(slow_path);
+ Riscv64Assembler* assembler = GetAssembler();
+ XRegister call_site_type =
+ locations->InAt(invoke->GetNumberOfArguments()).AsRegister<XRegister>();
+
+ // Call site should match with MethodHandle's type.
+ XRegister temp = locations->GetTemp(0).AsRegister<XRegister>();
+ __ Loadwu(temp, method_handle, mirror::MethodHandle::MethodTypeOffset().Int32Value());
+ codegen_->MaybeUnpoisonHeapReference(temp);
+ __ Bne(call_site_type, temp, slow_path->GetEntryLabel());
+
+ __ Loadwu(temp, method_handle, mirror::MethodHandle::HandleKindOffset().Int32Value());
+ __ AddConst32(temp, temp, -mirror::MethodHandle::Kind::kInvokeStatic);
+ __ Bnez(temp, slow_path->GetEntryLabel());
+
+ XRegister method = locations->GetTemp(1).AsRegister<XRegister>();
+ __ Loadd(method, method_handle, mirror::MethodHandle::ArtFieldOrMethodOffset().Int32Value());
+ Offset entry_point = ArtMethod::EntryPointFromQuickCompiledCodeOffset(kRiscv64PointerSize);
+ __ Loadd(RA, method, entry_point.SizeValue());
+ __ Jalr(RA);
+ codegen_->RecordPcInfo(invoke, invoke->GetDexPc(), slow_path);
+ __ Bind(slow_path->GetExitLabel());
+}
+
#define MARK_UNIMPLEMENTED(Name) UNIMPLEMENTED_INTRINSIC(RISCV64, Name)
UNIMPLEMENTED_INTRINSIC_LIST_RISCV64(MARK_UNIMPLEMENTED);
#undef MARK_UNIMPLEMENTED
diff --git a/compiler/optimizing/optimization.cc b/compiler/optimizing/optimization.cc
index c876254050..31780739bc 100644
--- a/compiler/optimizing/optimization.cc
+++ b/compiler/optimizing/optimization.cc
@@ -40,10 +40,10 @@
#include "bounds_check_elimination.h"
#include "cha_guard_optimization.h"
-#include "code_flow_simplifier.h"
#include "code_sinking.h"
#include "constant_folding.h"
#include "constructor_fence_redundancy_elimination.h"
+#include "control_flow_simplifier.h"
#include "dead_code_elimination.h"
#include "dex/code_item_accessors-inl.h"
#include "driver/compiler_options.h"
@@ -88,8 +88,8 @@ const char* OptimizationPassName(OptimizationPass pass) {
return HDeadCodeElimination::kDeadCodeEliminationPassName;
case OptimizationPass::kInliner:
return HInliner::kInlinerPassName;
- case OptimizationPass::kCodeFlowSimplifier:
- return HCodeFlowSimplifier::kCodeFlowSimplifierPassName;
+ case OptimizationPass::kControlFlowSimplifier:
+ return HControlFlowSimplifier::kControlFlowSimplifierPassName;
case OptimizationPass::kAggressiveInstructionSimplifier:
case OptimizationPass::kInstructionSimplifier:
return InstructionSimplifier::kInstructionSimplifierPassName;
@@ -146,10 +146,10 @@ const char* OptimizationPassName(OptimizationPass pass) {
OptimizationPass OptimizationPassByName(const std::string& pass_name) {
X(OptimizationPass::kBoundsCheckElimination);
X(OptimizationPass::kCHAGuardOptimization);
- X(OptimizationPass::kCodeFlowSimplifier);
X(OptimizationPass::kCodeSinking);
X(OptimizationPass::kConstantFolding);
X(OptimizationPass::kConstructorFenceRedundancyElimination);
+ X(OptimizationPass::kControlFlowSimplifier);
X(OptimizationPass::kDeadCodeElimination);
X(OptimizationPass::kGlobalValueNumbering);
X(OptimizationPass::kInductionVarAnalysis);
@@ -266,8 +266,8 @@ ArenaVector<HOptimization*> ConstructOptimizations(
pass_name);
break;
}
- case OptimizationPass::kCodeFlowSimplifier:
- opt = new (allocator) HCodeFlowSimplifier(graph, stats, pass_name);
+ case OptimizationPass::kControlFlowSimplifier:
+ opt = new (allocator) HControlFlowSimplifier(graph, stats, pass_name);
break;
case OptimizationPass::kInstructionSimplifier:
opt = new (allocator) InstructionSimplifier(graph, codegen, stats, pass_name);
diff --git a/compiler/optimizing/optimization.h b/compiler/optimizing/optimization.h
index 395c45e3f7..0f0a15f7c9 100644
--- a/compiler/optimizing/optimization.h
+++ b/compiler/optimizing/optimization.h
@@ -70,10 +70,10 @@ enum class OptimizationPass {
kAggressiveInstructionSimplifier,
kBoundsCheckElimination,
kCHAGuardOptimization,
- kCodeFlowSimplifier,
kCodeSinking,
kConstantFolding,
kConstructorFenceRedundancyElimination,
+ kControlFlowSimplifier,
kDeadCodeElimination,
kGlobalValueNumbering,
kInductionVarAnalysis,
diff --git a/compiler/optimizing/optimizing_compiler.cc b/compiler/optimizing/optimizing_compiler.cc
index 5067872ee4..76c201d6a9 100644
--- a/compiler/optimizing/optimizing_compiler.cc
+++ b/compiler/optimizing/optimizing_compiler.cc
@@ -666,7 +666,7 @@ void OptimizingCompiler::RunOptimizations(HGraph* graph,
"reference_type_propagation$after_gvn",
OptimizationPass::kGlobalValueNumbering),
// Simplification (TODO: only if GVN occurred).
- OptDef(OptimizationPass::kCodeFlowSimplifier),
+ OptDef(OptimizationPass::kControlFlowSimplifier),
OptDef(OptimizationPass::kConstantFolding,
"constant_folding$after_gvn"),
OptDef(OptimizationPass::kInstructionSimplifier,