Uh oh!
There was an error while loading. Please reload this page.
JIT: Produce less convoluted IR for boolean isinst checks - #103391
Conversation
Currently the IR for boolean `isinst` checks ends up being something like `(typecheck(x) ? x : null) != null`, which the JIT ends up having a hard time clean up early. With object stack allocation this pattern usually leads to unnecessary address exposure. This adds a simple pattern match during import to produce less convoluted IR in the common cases where the `isinst` is just used as a boolean check.
Uh oh!
There was an error while loading. Please reload this page.
EgorBo
commented
Jun 13, 2024
Should close #36649 |
Looks like it, your [MethodImpl(MethodImplOptions.NoInlining)]publicstaticboolIs_Slow(objectobj)=>objisint;Base: ; Method C:Is_Slow(System.Object):ubyte (FullOpts)G_M38459_IG01: ;; offset=0x0000 ;; size=0 bbWeight=1 PerfScore 0.00G_M38459_IG02: ;; offset=0x0000testrcx,rcxje SHORT G_M38459_IG05 ;; size=5 bbWeight=1 PerfScore 1.25G_M38459_IG03: ;; offset=0x0005movrax,0x7FFB89FA1C00 ; System.Int32cmp qword ptr [rcx],raxjne SHORT G_M38459_IG05 ;; size=15 bbWeight=0.25 PerfScore 1.06G_M38459_IG04: ;; offset=0x0014jmp SHORT G_M38459_IG06 ;; size=2 bbWeight=0.12 PerfScore 0.25G_M38459_IG05: ;; offset=0x0016xorrcx,rcx ;; size=2 bbWeight=0.25 PerfScore 0.06G_M38459_IG06: ;; offset=0x0018testrcx,rcx setne almovzxrax,al ;; size=9 bbWeight=1 PerfScore 1.50G_M38459_IG07: ;; offset=0x0021ret ;; size=1 bbWeight=1 PerfScore 1.00; Total bytes of code: 34Diff: ; Method C:Is_Slow(System.Object):ubyte (FullOpts)G_M38459_IG01: ;; offset=0x0000 ;; size=0 bbWeight=1 PerfScore 0.00G_M38459_IG02: ;; offset=0x0000testrcx,rcxje SHORT G_M38459_IG05 ;; size=5 bbWeight=1 PerfScore 1.25G_M38459_IG03: ;; offset=0x0005movrax,0x7FFB89FC1C00 ; System.Int32cmp qword ptr [rcx],raxjne SHORT G_M38459_IG05 ;; size=15 bbWeight=0.25 PerfScore 1.06G_M38459_IG04: ;; offset=0x0014moveax,1jmp SHORT G_M38459_IG06 ;; size=7 bbWeight=0.12 PerfScore 0.28G_M38459_IG05: ;; offset=0x001Bxoreax,eax ;; size=2 bbWeight=0.25 PerfScore 0.06G_M38459_IG06: ;; offset=0x001Dret ;; size=1 bbWeight=1 PerfScore 1.00; Total bytes of code: 30 |
jakobbotsch
commented
Jun 17, 2024
/azp run runtime |
|
Azure Pipelines successfully started running 1 pipeline(s). |
Uh oh!
There was an error while loading. Please reload this page.
Overall the IR created by this PR is not really any less convoluted than the existing IR. Instead of Of course it would be better if we could create the more natural control flow, but that's hard given the representation through |
EgorBo
commented
Jun 17, 2024
I initially hoped we'd enable JitOptRepeat and I could move the late-cast expansion to the JitOptRepeat loop and the 2nd iteration of it would clean most of the regressions I hit just fine 😞 |
jakobbotsch
commented
Jun 17, 2024
cc @dotnet/jit-contrib PTAL @EgorBo@AndyAyersMS |
| if (*booleanCheck) | ||
| { | ||
| GenTreeOp* condMT = gtNewOperNode(GT_NE, TYP_INT, gtNewMethodTableLookup(op1Clone), op2); | ||
| GenTreeOp* condNull = gtNewOperNode(GT_EQ, TYP_INT, gtClone(op1), gtNewNull()); |
There was a problem hiding this comment.
nit: looks like these two branches have a lot of common code, e.g. condMT and condNull are the same.
EgorBo
left a comment
There was a problem hiding this comment.
LGTM, minor clean up comment, probably, not worth re-running CI for
Currently the IR for boolean
isinstchecks ends up being something like(typecheck(x) ? x : null) != null, which the JIT ends up having a hard time clean up early. With object stack allocation this pattern usually leads to unnecessary address exposure.This adds a simple pattern match during import to produce less convoluted IR in the common cases where the
isinstis just used as a boolean check.Example from #36649:
Fix#36649