Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
Please login to access the resource
home:Ledest:erlang:26
erlang
1139-AArch64-Enhance-optimizations-of-two-move-...
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 1139-AArch64-Enhance-optimizations-of-two-move-instructio.patch of Package erlang
From 77cfe46376058624d82314f4b16fc183ebf6e88c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= <bjorn@erlang.org> Date: Wed, 27 Sep 2023 08:01:32 +0200 Subject: [PATCH 19/25] AArch64: Enhance optimizations of two move instructions * Replace the instructions `store_two_xregs` and `move_two_yregs` with the more general `store_two_values`, which also supports storing any value into Y registers. * Replace an `init_yreg` instruction that initializes a single register with a `move` instruction. That give more opportunities for optimizations, such as combining it with another `move` instruction or with a `trim` instruction. --- erts/emulator/beam/jit/arm/generators.tab | 15 +++++++++++ erts/emulator/beam/jit/arm/instr_common.cpp | 30 +++------------------ erts/emulator/beam/jit/arm/ops.tab | 30 +++++++++------------ 3 files changed, 31 insertions(+), 44 deletions(-) diff --git a/erts/emulator/beam/jit/arm/generators.tab b/erts/emulator/beam/jit/arm/generators.tab index 9e0a686ea6..7a4aa84028 100644 --- a/erts/emulator/beam/jit/arm/generators.tab +++ b/erts/emulator/beam/jit/arm/generators.tab @@ -450,6 +450,21 @@ gen.func_end(Func_Label, Entry_Label) { return op; } +gen.init_yregs_move(Size, Rest) { + BeamOp* op; + + ASSERT(Size.val == 1); + + $NewBeamOp(S, op); + $BeamOpNameArity(op, move, 2); + op->next = NULL; + op->a[0].type = TAG_n; + op->a[0].val = 0; + op->a[1] = Rest[0]; + + return op; +} + gen.create_bin(Fail, Alloc, Live, Unit, Dst, N, Segments) { BeamOp* op; int fixed_args; diff --git a/erts/emulator/beam/jit/arm/instr_common.cpp b/erts/emulator/beam/jit/arm/instr_common.cpp index 63214821db..755124dcf9 100644 --- a/erts/emulator/beam/jit/arm/instr_common.cpp +++ b/erts/emulator/beam/jit/arm/instr_common.cpp @@ -558,10 +558,10 @@ void BeamModuleAssembler::emit_move_trim(const ArgSource &Src, } } -void BeamModuleAssembler::emit_store_two_xregs(const ArgXRegister &Src1, - const ArgYRegister &Dst1, - const ArgXRegister &Src2, - const ArgYRegister &Dst2) { +void BeamModuleAssembler::emit_store_two_values(const ArgSource &Src1, + const ArgYRegister &Dst1, + const ArgSource &Src2, + const ArgYRegister &Dst2) { auto [src1, src2] = load_sources(Src1, TMP1, Src2, TMP2); auto dst1 = init_destination(Dst1, src1.reg); auto dst2 = init_destination(Dst2, src2.reg); @@ -582,28 +582,6 @@ void BeamModuleAssembler::emit_load_two_xregs(const ArgYRegister &Src1, flush_vars(dst1, dst2); } -void BeamModuleAssembler::emit_move_two_yregs(const ArgYRegister &Src1, - const ArgYRegister &Dst1, - const ArgYRegister &Src2, - const ArgYRegister &Dst2) { - /* Optimize fetching of source Y registers. */ - switch (ArgVal::memory_relation(Src1, Src2)) { - case ArgVal::Relation::consecutive: - safe_ldp(TMP1, TMP2, Src1, Src2); - break; - case ArgVal::Relation::reverse_consecutive: - safe_ldp(TMP2, TMP1, Src2, Src1); - break; - case ArgVal::Relation::none: - a.ldr(TMP1, getArgRef(Src1)); - a.ldr(TMP2, getArgRef(Src2)); - break; - } - - /* Destination registers are always in consecutive order. */ - safe_stp(TMP1, TMP2, Dst1, Dst2); -} - void BeamModuleAssembler::emit_swap(const ArgRegister &R1, const ArgRegister &R2) { if (isRegisterBacked(R1)) { diff --git a/erts/emulator/beam/jit/arm/ops.tab b/erts/emulator/beam/jit/arm/ops.tab index 5e75154e81..cd22696347 100644 --- a/erts/emulator/beam/jit/arm/ops.tab +++ b/erts/emulator/beam/jit/arm/ops.tab @@ -95,6 +95,11 @@ trim t t allocate_zero Ns Live => allocate_heap_zero Ns u Live allocate_heap_zero Ns Nh Live => allocate_heap_zero(Ns, Nh, Live) +# Use a move instruction for initializating a single Y register, since +# that can open up more optimizations (for example, combining a move + +# trim to move_trim). +init_yregs Size=u==1 Regs=* => init_yregs_move(Size, Regs) + init_yregs I * # Selecting values. @@ -321,19 +326,10 @@ system_limit_body # # Optimize moves of consecutive memory addresses. # -move Src=c Dst => i_move Src Dst move Src SrcDst | move SrcDst2 Dst | equal(SrcDst, SrcDst2) => i_move Src SrcDst | move SrcDst Dst -# Optimize two moves from X registers to Y registers when destination -# Y registers are consecutive. - -move S1=x D1=y | move S2=x D2=y | consecutive_words(D1, D2) => - store_two_xregs S1 D1 S2 D2 -move S1=x D1=y | move S2=x D2=y | consecutive_words(D2, D1) => - store_two_xregs S2 D2 S1 D1 - # Optimize two moves from Y registers to X registers when source Y # registers are consecutive. @@ -347,14 +343,13 @@ move S1=y D1=x | move S2=y D2=x | distinct(D1, D2) => load_two_xregs S2 D2 S1 D1 -# Optimize two moves of Y registers when destinations are consecutive. -move S1=y D1=y | move S2=y D2=y | - consecutive_words(D1, D2) => - move_two_yregs S1 D1 S2 D2 +# Optimize storing two values in Y registers when destination Y +# registers are consecutive. -move S1=y D1=y | move S2=y D2=y | - consecutive_words(D2, D1) => - move_two_yregs S2 D2 S1 D1 +move S1 D1=y | move S2 D2=y | consecutive_words(D1, D2) => + store_two_values S1 D1 S2 D2 +move S1 D1=y | move S2 D2=y | consecutive_words(D2, D1) => + store_two_values S2 D2 S1 D1 move Src Dst | trim N u => move_trim Src Dst N @@ -363,9 +358,8 @@ move_trim s d t move Src Dst => i_move Src Dst i_move s d -store_two_xregs x y x y +store_two_values s y s y load_two_xregs y x y x -move_two_yregs y y y y # # Swap instructions. -- 2.35.3
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor