diff options
Diffstat (limited to 'compiler/optimizing')
| -rw-r--r-- | compiler/optimizing/code_generator_riscv64.h | 1 | ||||
| -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.cc | 6 | ||||
| -rw-r--r-- | compiler/optimizing/intrinsics_riscv64.cc | 85 | ||||
| -rw-r--r-- | compiler/optimizing/optimization.cc | 12 | ||||
| -rw-r--r-- | compiler/optimizing/optimization.h | 2 | ||||
| -rw-r--r-- | compiler/optimizing/optimizing_compiler.cc | 2 |
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, |