-
Notifications
You must be signed in to change notification settings - Fork 2.7k
Fixes for tracking struct field sequences #23932
Conversation
@dotnet-build-bot Test Ubuntu arm Cross Checked crossgen_comparison Build and Test |
/azp run coreclr-outerloop |
Azure Pipelines successfully started running 1 pipeline(s). |
@dotnet-build-bot Test Windows_NT arm64 Cross Checked Innerloop Build and Test |
@dotnet/jit-contrib PTAL |
@AndyAyersMS this fixes one leg of |
19e896e
to
3af4338
Compare
@briansull - can you characterize the kind of code that led to this issue? It seems counter-intuitive that a |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would appreciate a bit more background here.
- Was this a regression?
- If so, do we know what caused it?
- Does it cause bad codegen or just asserts?
- Does this cause diffs on Core?
- If no diff, can we get test cases or describe the situations where we get asserts?
This sequence requires a zero-field annotation on a GT_LCL_VAR during morph before it can reach the final GT_LCL_FLD with a two field sequence:
|
Where is the zero-field annotation (on which node)? And what IL sequence (or prior transform) causes it? |
@AndyAyersMS Since I know that there are potential issues I want to fix them for 3.0, I also saw this in my work on the desktop bug 837706 the PMI run with JItStress=2 and JItStressReg where we were hitting an assert. I have posted the diffs that I got on Core (see comment #3 above). Almost all were improvements, |
@CarolEidt
into |
The tree was produced from this IL during inlining:
|
I am willing to believe this too, but it would be good to understand exactly how it leads to bugs. Presumably the diffs you are showing above are from better codegen, not from fixing buggy codegen? Does the desktop assert case lead to bad codegen in release? How do we know we're still not missing cases? The field sequence and zero offset field map maintenance seems easy to overlook. Finally, is this related in any way to #22900? |
69373ce
to
524d284
Compare
Original AsmDiffs were incorrect. Here are the actual AsmDiff for this change:
|
@dotnet-build-bot Test Windows_NT arm Cross Checked Innerloop Build and Test |
@dotnet/jit-contrib PTAL |
@briansull - could you respond to the questions that @AndyAyersMS has asked? |
Yes, This is an change that improves our ability to track what is happening when we record the zero offset fields.. It adds an important assert so that we don't create incorrect duplicate field sequences (which we are currently doing)
My original set of diffs were against an incorrect baseline. There are now very few actual diffs for this change. The few diffs that we do see involve making CSE's using struct address calculations with zero offset fields.
It resulted in an assert with the checked compiler.
Yes, I agree and that is the primary purpose of this chnage. With this change we now print out in the JitDump every modification involving the Zero Offset tracking. Making it much easier to follow what is happening here.
No, This isn't directly related to that issue, although this change will made debugging that issue and other similar issues much easier going forwards.
I believe that with this refactoring we will not be dropping the Zero Field sequence information. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I still find this a bit confusing in a couple of places.
src/jit/morph.cpp
Outdated
{ | ||
temp->ChangeOper(GT_LCL_FLD); // Note that this makes the gtFieldSeq "NotAField"... | ||
assert(temp->OperGet() == GT_LCL_VAR); | ||
temp->ChangeOper(GT_LCL_FLD); // Note that this typically makes the gtFieldSeq "NotAField"... |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In what case would this not be NotAField
- is this the zero-offset case?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, the code that I added with this change will set this: (see the compiler.hpp
diff)
// Set the zeroFieldSeq in the GT_LCL_FLD node
gtLclFld.gtFieldSeq = zeroFieldSeq;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Might be worth adding that, e.g.
// Note that this typically makes the gtFieldSeq "NotAField", unless we have a zero-offset FieldSeq
or something like that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I still think it would be good to explain why it sometimes doesn't make it NotAField
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure I will add a comment explaining that case
#ifdef DEBUG | ||
if (verbose) | ||
{ | ||
printf("\nBefore calling fgAddFieldSeqForZeroOffset:\n"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems redundant because fgAddFieldSeqForZeroOffset
also does a "before" dump.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually This will print the whole tree (and it occurs after the call to fgMorphSmpOp
)
It is helpful to see the final version of the tree to verify that the field sequences are correct and non of them went missing during the call to fgMorphSmpOp
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you want, I could change this to always print the final result of Compiler::fgMorphField
.
That might be better, since the morphing of a GT_FIELD produces a new more complex tree.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That makes sense to me
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Carol after my last change the assert can now be changed to simply check that the type is BYREF or I_IMPL.
// We expect 'addr' to be an address at this point.
assert(addr->TypeGet() == TYP_BYREF || addr->TypeGet() == TYP_I_IMPL);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's great!
- A GT_LCL_VAR may have a zeroOffset field - Add an assert to prevent building field sequences with duplicates - Fix fgMorphField when we have a zero offset field Improve fgAddFieldSeqForZeroOffset - Add JItDump info - Handle GT_LCL_FLD Changing the sign of an int constant also remove any field sequence information. Added method header comment for fgAddFieldSeqForZeroOffset Changed when we call fgAddFieldSeqForZeroOffset to be before the call to fgMorphSmpOp. Prefer calling fgAddFieldSeqForZeroOffset() to GetZeroOffsetFieldMap()->Set()
524d284
to
22028dc
Compare
@dotnet-build-bot Test Windows_NT arm Cross Checked Innerloop Build and Test |
ping @dotnet/jit-contrib PTAL |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM - thanks for the extra comment
temp->ChangeOper(GT_LCL_FLD); // Note that this typically makes the gtFieldSeq "NotAField"... | ||
temp->AsLclFld()->gtLclOffs = (unsigned short)ival1; | ||
temp->ChangeOper(GT_LCL_FLD); // Note that this typically makes the gtFieldSeq "NotAField", | ||
// unless there is a zero filed offset associated with 'temp'. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The formatting here is weird, but it's not a big deal I guess.
Fixes for tracking struct field sequences Commit migrated from dotnet/coreclr@e7ecfec
Fixes for Zero Offset field sequence tracking
Improve fgAddFieldSeqForZeroOffset