Clear some stale GTF_ORDER_SIDEEFF flags#130007
Conversation
|
Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch |
There was a problem hiding this comment.
Pull request overview
This PR adjusts JIT tree side-effect flag maintenance by attempting to clear stale GTF_ORDER_SIDEEFF bits during Compiler::gtUpdateStmtSideEffects, to unblock downstream optimizations that are inhibited by incorrectly-propagated ordering constraints.
Changes:
- Add logic in
gtUpdateStmtSideEffectsto clearGTF_ORDER_SIDEEFFon nodes that don’t support ordering side effects when none of their operands still carry the flag.
| if (((tree->gtFlags & GTF_ORDER_SIDEEFF) != 0) && !tree->OperSupportsOrderingSideEffect()) | ||
| { | ||
| bool hasChildWithOrderSideEff = false; | ||
| tree->VisitOperands([&hasChildWithOrderSideEff](GenTree* operand) -> GenTree::VisitResult { | ||
| if ((operand->gtFlags & GTF_ORDER_SIDEEFF) != 0) |
There was a problem hiding this comment.
seems reasonable
|
link to diffs https://dev.azure.com/dnceng-public/public/_build/results?buildId=1486826&view=ms.vss-build-web.run-extensions-tab Example (more ccmp in a method similar to the motivating example) -4 (-7.14%) : AggregateSymbol:IsRefType():bool:this (FullOpts)@@ -22,30 +22,27 @@ G_M9025_IG02: ; bbWeight=1, gcrefRegs=0001 {x0}, byrefRegs=0000 {}, byref
; gcrRegs +[x0]
ldr w1, [x0, #0x90]
cmp w1, #1
- beq G_M9025_IG04
+ bne G_M9025_IG05
;; size=12 bbWeight=1 PerfScore 4.50
-G_M9025_IG03: ; bbWeight=0.50, gcrefRegs=0000 {}, byrefRegs=0000 {}, byref, isz
+G_M9025_IG03: ; bbWeight=0.50, gcrefRegs=0000 {}, byrefRegs=0000 {}, byref
; gcrRegs -[x0]
- cmp w1, #3
- bne G_M9025_IG06
- ;; size=8 bbWeight=0.50 PerfScore 0.75
-G_M9025_IG04: ; bbWeight=0.50, gcrefRegs=0000 {}, byrefRegs=0000 {}, byref
mov w0, #1
;; size=4 bbWeight=0.50 PerfScore 0.25
-G_M9025_IG05: ; bbWeight=0.50, epilog, nogc, extend
+G_M9025_IG04: ; bbWeight=0.50, epilog, nogc, extend
ldp fp, lr, [sp], #0x10
ret lr
;; size=8 bbWeight=0.50 PerfScore 1.00
-G_M9025_IG06: ; bbWeight=0.50, gcVars=0000000000000000 {}, gcrefRegs=0000 {}, byrefRegs=0000 {}, gcvars, byref
- cmp w1, #2
+G_M9025_IG05: ; bbWeight=0.50, gcVars=0000000000000000 {}, gcrefRegs=0000 {}, byrefRegs=0000 {}, gcvars, byref
+ cmp w1, #3
+ ccmp w1, #2, z, ne
cset x0, eq
- ;; size=8 bbWeight=0.50 PerfScore 0.50
-G_M9025_IG07: ; bbWeight=0.50, epilog, nogc, extend
+ ;; size=12 bbWeight=0.50 PerfScore 0.75
+G_M9025_IG06: ; bbWeight=0.50, epilog, nogc, extend
ldp fp, lr, [sp], #0x10
ret lr
;; size=8 bbWeight=0.50 PerfScore 1.00
-; Total bytes of code 56, prolog size 8, PerfScore 9.50, instruction count 14, allocated bytes for code 56 (MethodHash=4337dcbe) for method Microsoft.CSharp.RuntimeBinder.Semantics.AggregateSymbol:IsRefType():bool:this (FullOpts)
+; Total bytes of code 52, prolog size 8, PerfScore 9.00, instruction count 13, allocated bytes for code 52 (MethodHash=4337dcbe) for method Microsoft.CSharp.RuntimeBinder.Semantics.AggregateSymbol:IsRefType():bool:this (FullOpts)
; ============================================================ |
AndyAyersMS
left a comment
There was a problem hiding this comment.
I assume we end up in this state because we fail to clear the flag when we change the oper?
Should we add an IR check that we never see GTF_ORDER_SIDEEFF on a node where it isn't expected?
| // Attempt to clear stale SIDEEFF bits | ||
| // if this node does indeed need GTF_ORDER_SIDEEFF, then the bit will later be propagated up and re-set | ||
| // during the child's post-order visit | ||
| if (!tree->OperSupportsOrderingSideEffect()) |
There was a problem hiding this comment.
| if (!tree->OperSupportsOrderingSideEffect()) | |
| if (((tree->gtFlags & GTF_ORDER_SIDEEFF) != 0) && !tree->OperSupportsOrderingSideEffect()) |
For TP
I agree it would be nice to make |
@jakobbotsch + @AndyAyersMS sequence of steps here was, null check gets removed on an IND so it + the parent EQ is marked SIDEEFFECT: IND gets CSE'd with a local, but EQ retains the bit (the gtUpdateStmtSideEffects method im changing here is called immediately after the CSE) |
|
Opened #130150 to track the bad diff with the ballooned perfscore |
Clear stale
GTF_ORDER_SIDEEFFflags to enable more if-conversion and optimize bools.Motivating example was
o.GetType() == typeof(int) || o.GetType() == typeof(uint) || o.GetType() == typeof(long)- we couldn't combine intoORbecause leftover side effect bit in one of the blocks.If an op doesn't itself support side effects, and none of node's children have the bit, then the node may have the bit cleared.
Diffs show more optimize bools+if conversion taking place.
One of the bad diffs was block layout changing and causing LSRA to spill slightly different.
Another bad diff exposed an issue where edge-likelihoods weren't recalculated properly after optimize bools, and caused perfscore to balloon. I'm working on a fix for that seperately.