Skip to content

Fix issue where resolution move would overwrite the source of operand of JCMP - #48833

Merged
kunalspathak merged 3 commits into
dotnet:mainfrom
kunalspathak:lsra-fixes5
Mar 3, 2021
Merged

Fix issue where resolution move would overwrite the source of operand of JCMP#48833
kunalspathak merged 3 commits into
dotnet:mainfrom
kunalspathak:lsra-fixes5

Conversation

@kunalspathak

Copy link
Copy Markdown
Contributor

@ghostghost added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Feb 26, 2021
@kunalspathak

Copy link
Copy Markdown
ContributorAuthor

@dotnet/jit-contrib

@sandreenko
sandreenko self-requested a review February 26, 2021 18:36
Base automatically changed from master to mainMarch 1, 2021 09:08
@kunalspathak

Copy link
Copy Markdown
ContributorAuthor

@AndyAyersMS or @BruceForstall - can you please review this?

Comment threadsrc/coreclr/jit/lsra.cpp Outdated
GenTree* op1 = lastNode->gtGetOp1();
switchRegs |= genRegMask(op1->GetRegNum());

if (op1->OperIs(GT_COPY))

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are locals and copies the only special cases that might happen here?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also switch_regs is not as descriptive as one might like, given that we now set it for things that are not switches.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's the only ones I could think of. COPY are special because we defer the code generation until the consuming node like here:

caseGT_COPY:
// This is handled at the time we call genConsumeReg() on the GT_COPY
break;

So in the test that I was investigating, the GT_COPY node's generation get deferred and happens after the generation of resolution move, at the time when the JCMP is generated.

Generating: N787 ( 34, 17) [000046] --CXGO------ t46 = * CALLV vt-ind int MiniBench.MyChannelWriter`1[Int32][System.Int32].TryWrite REG x0 $218
GC regs: 100001 {x0 x20} => 100000 {x20}
Call: GCvars=0000000000000008 {V00}, gcrefRegs=100000 {x20}, byrefRegs=80000 {x19}
[15] Rec call GC vars = 0000000000000008
IN000f: blr x21
/--* t46 int Generating: [000930] --CXGO------ t930 = * COPY int REG x21 (currently: ***not unused***, should be unused)
Generating: N789 ( 1, 2) [000047] -c---------- t47 = CNS_INT int 0 REG NA $40
; Generating: N001 ( 1, 1) [000937] ------------ t937 = LCL_VAR byref V00 this x19 REG x19
/--* t937 byref Generating: N002 ( 2, 2) [000938] ------------ t938 = * COPY byref REG x0 (currently: ***unused***, should be notunused)
IN0010: mov x0, x19
V00 in reg x19 is becoming dead [000937]
Live regs: 180000 {x19 x20} => 100000 {x20}
Byref regs: 80000 {x19} => 0000 {}
V00 in reg x0 is becoming live [000938]
Live regs: 100000 {x20} => 100001 {x0 x20}
Byref regs: 0000 {} => 0001 {x0}
/--* t930 int +--* t47 int Generating: N791 ( 36, 20) [000048] CNE---XGO-N---- * JCMP void REG NA
IN0011: mov w21, w0
IN0012: cbnz (LARGEJMP)L_M2478_BB37

Regarding switchRegs, I will rename it to consumedRegs.

// call METHOD
// ; mov w0, w19 <-- should not resolve in w0 here.
// mov w21, w0
// JCMP w21, BRANCH

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not obvious to me why the copy needs special casing here -- could we not insert the resolution move between the copy and jump?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inserting the resolution move between the copy and jump should be fine for some cases, for example:

mov w21, w0mov x0, x19 ; <-- resolution movecbnz w21, G_M2478_IG37

but when we generate code for JCMP, it is tied with the copy and so the resolution move happens before the copy/jmp, like this:

mov x0, x20 ldr x21,[x20] ldr x21,[x21,#72] ldr x21,[x21,#40] blr x21mov x0, x19 ; move resolution overwrites `x0` before it gets copied.mov w21, w0 cbnz w21, G_M2478_IG37G_M2478_IG05: mov x19, x0 ....

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe add a comment that the GT_COPY gets special handling in codegen and is conceptually merged with the operation that consumes its result, so both its input and output regs must be excluded from the set available for resolution.

And only switches and jcmp have input regs (and so can be fed by copies), so those are the only block-ending branches that need special handling.

Which makes me wonder if we might need similar logic for switches. It looks like we don't check if the input regs for switches come from GT_COPY. Switches are rare enough that we might not have good stress coverage.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe add a comment

Done.

wonder if we might need similar logic for switches

Possibly, but I am not confident to make that change before seeing a scenario, so lets postpone it for now.

@kunalspathak
kunalspathak merged commit 30560e2 into dotnet:mainMar 3, 2021
@ghostghost locked as resolved and limited conversation to collaborators Apr 2, 2021
@JulieLeeMSFTJulieLeeMSFT added this to the 6.0.0 milestone Apr 15, 2021
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@kunalspathak@AndyAyersMS@JulieLeeMSFT