Open Bug 1316818 Opened 3 years ago Updated 12 days ago

Wasm baseline: JoinReg selection and management strategy

Categories

(Core :: Javascript: WebAssembly, task, P3)

task

Tracking

()

People

(Reporter: lth, Unassigned)

References

(Blocks 1 open bug)

Details

Attachments

(1 file, 1 obsolete file)

At the moment we use ReturnReg for JoinReg.  It is possible other choices would lead to better register allocation, as ReturnReg is often first in the register set and will be heavily wanted by the register allocator that uses takeFirst().

Obvious options:

  - pick a register at the back of the register set
  - pick a random register per block (different blocks have different join regs)

On the other hand, we sync() before every block and only the JoinReg is live out of the block.  But on the way out, we currently pop the JoinReg before freeing regs to be discarded, so there is a real risk of some pointless shuffling there.  If we instead integrate the popping of the join reg into the popping of the stack we can just use the JoinReg as it will become available in that process.

It should be easy to try a couple of strategies here, to see if there's anything to gain from it.  This really needs to be driven by code inspection and benchmarks.
Assignee: nobody → lhansen
Status: NEW → ASSIGNED
I created a crude profiling infrastructure and compiled AngryBots.  These are numbers for x64, it is likely that both ARM and x86 will be quite different:

[Profiling] WASM BASELINE SYNC: total=377856 capacity=7 specific=10521 local=575 join=181835 call=184918

total    = total number of sync() calls performed by the compiler (sum of the other fields)

capacity = syncs caused by running out of some register type, ie, a complex nested structure

specific = syncs caused by needing a specific register that is currently in use and on the
           value stack (bug 1316802; and the present bug)

local    = syncs caused by performing a setlocal that matches a latent getlocal on the value
           stack (bug 1316817)

join     = syncs performed before block, loop, and if to simplify control flow joins later
           (bug 1318654)

call     = syncs performed before calls to simplify call generation (bug 1316806)

As far as the present bug is concerned, syncs caused by specific-register conflicts are important but not something that is critical on x64.
Attached patch bug1316818-profiling-code.patch (obsolete) — Splinter Review
Buyer beware: This sits on top of some of the profiling code in bug 1286816 (which may not land).
Splits the join node into categories for block, loop, and if, and counts those ifs that are leaves (contain no nested syncs at all).
Attachment #8812158 - Attachment is obsolete: true
Per policy at https://wiki.mozilla.org/Bug_Triage/Projects/Bug_Handling/Bug_Husbandry#Inactive_Bugs. If this bug is not an enhancement request or a bug not present in a supported release of Firefox, then it may be reopened.
Status: ASSIGNED → RESOLVED
Closed: 2 years ago
Resolution: --- → INACTIVE
Status: RESOLVED → REOPENED
Resolution: INACTIVE → ---
Component: JavaScript Engine: JIT → Javascript: Web Assembly
Assignee: lhansen → nobody
Status: REOPENED → NEW
Type: defect → task

Multi-value changed the code around joinreg (it is now gone) and the multi-value iterator uses the return registers for result registers, but we can still do useful work for this problem -- but it may be work that de-prioritizes some registers during normal register allocation, ie, makes the allocator prioritize other registers than the result register(s).

You need to log in before you can comment on or make changes to this bug.