-
Notifications
You must be signed in to change notification settings - Fork 4.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
JIT: Make effect handling in lowering less conservative #92710
Changes from 1 commit
68321b2
25324a2
d28c644
a4d40cd
52e0247
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6731,7 +6731,7 @@ GenTree* GenTree::gtGetParent(GenTree*** pUse) | |
// of the children's flags. | ||
// | ||
|
||
bool GenTree::OperRequiresAsgFlag() | ||
bool GenTree::OperRequiresAsgFlag() const | ||
{ | ||
switch (OperGet()) | ||
{ | ||
|
@@ -6769,8 +6769,7 @@ bool GenTree::OperRequiresAsgFlag() | |
// OperRequiresCallFlag : Check whether the operation requires GTF_CALL flag regardless | ||
// of the children's flags. | ||
// | ||
|
||
bool GenTree::OperRequiresCallFlag(Compiler* comp) | ||
bool GenTree::OperRequiresCallFlag(Compiler* comp) const | ||
{ | ||
switch (gtOper) | ||
{ | ||
|
@@ -7026,6 +7025,153 @@ bool GenTree::OperMayThrow(Compiler* comp) | |
return OperExceptions(comp) != ExceptionSetFlags::None; | ||
} | ||
|
||
//------------------------------------------------------------------------------ | ||
// OperRequiresGlobRefFlag : Check whether the operation requires GTF_GLOB_REF | ||
// flag regardless of the children's flags. | ||
// | ||
// Arguments: | ||
// comp - Compiler instance | ||
// | ||
// Return Value: | ||
// True if the given operator requires GTF_GLOB_REF | ||
// | ||
// Remarks: | ||
// Only valid after local morph. | ||
// | ||
bool GenTree::OperRequiresGlobRefFlag(Compiler* comp) const | ||
{ | ||
switch (OperGet()) | ||
{ | ||
case GT_LCL_VAR: | ||
case GT_LCL_FLD: | ||
case GT_STORE_LCL_VAR: | ||
case GT_STORE_LCL_FLD: | ||
return comp->lvaGetDesc(AsLclVarCommon())->IsAddressExposed(); | ||
|
||
case GT_IND: | ||
case GT_BLK: | ||
if (AsIndir()->IsInvariantLoad()) | ||
{ | ||
return false; | ||
} | ||
FALLTHROUGH; | ||
|
||
case GT_STOREIND: | ||
case GT_STORE_BLK: | ||
case GT_STORE_DYN_BLK: | ||
case GT_XADD: | ||
case GT_XORR: | ||
case GT_XAND: | ||
case GT_XCHG: | ||
case GT_LOCKADD: | ||
case GT_CMPXCHG: | ||
case GT_MEMORYBARRIER: | ||
case GT_KEEPALIVE: | ||
return true; | ||
|
||
case GT_CALL: | ||
return AsCall()->HasSideEffects(comp, /* ignoreExceptions */ true); | ||
Comment on lines
+7078
to
+7079
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This was apparently in my second commit - |
||
|
||
#if defined(FEATURE_HW_INTRINSICS) | ||
case GT_HWINTRINSIC: | ||
return AsHWIntrinsic()->OperRequiresGlobRefFlag(); | ||
#endif // FEATURE_HW_INTRINSICS | ||
|
||
default: | ||
assert(!OperRequiresCallFlag(comp) || OperIs(GT_INTRINSIC)); | ||
assert((!OperIsIndir() || OperIs(GT_NULLCHECK)) && !OperRequiresAsgFlag()); | ||
return false; | ||
} | ||
} | ||
|
||
//------------------------------------------------------------------------------ | ||
// OperSupportsOrderingSideEffect : Check whether the operation supports the | ||
// GTF_ORDER_SIDEEFF flag. | ||
// | ||
// Return Value: | ||
// True if the given operator supports GTF_ORDER_SIDEEFF. | ||
// | ||
// Remarks: | ||
// A node will still have this flag set if an operand has it set, even if the | ||
// parent does not support it. This situation indicates that reordering the | ||
// parent may be ok as long as it does not break ordering dependencies of the | ||
// operand. | ||
// | ||
bool GenTree::OperSupportsOrderingSideEffect() const | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do you have ideas on how to make sure that this method does not silently drop ordering effects when we start using it for new nodes? For example, say someone is implementing non-null assertion propagation for Perhaps add a setter for There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I can add assert in fgdiagnostic to ensure that There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Doing this requires making sure we propagate/unset these flags in all the same places as the other flags... That's probably a good thing to do down the road, but I think for now I will skip it and think about doing that separately. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Doing this did make me notice that I missed |
||
{ | ||
if (TypeIs(TYP_BYREF)) | ||
{ | ||
// Forming byrefs may only be legal due to previous checks. | ||
return true; | ||
} | ||
|
||
switch (OperGet()) | ||
{ | ||
case GT_BOUNDS_CHECK: | ||
case GT_IND: | ||
case GT_BLK: | ||
case GT_STOREIND: | ||
case GT_STORE_BLK: | ||
case GT_STORE_DYN_BLK: | ||
case GT_XADD: | ||
case GT_XORR: | ||
case GT_XAND: | ||
case GT_XCHG: | ||
case GT_LOCKADD: | ||
case GT_CMPXCHG: | ||
case GT_MEMORYBARRIER: | ||
case GT_CATCH_ARG: | ||
#if defined(FEATURE_HW_INTRINSICS) | ||
case GT_HWINTRINSIC: | ||
#endif | ||
jakobbotsch marked this conversation as resolved.
Show resolved
Hide resolved
|
||
return true; | ||
} | ||
|
||
return false; | ||
} | ||
|
||
//------------------------------------------------------------------------------ | ||
// OperEffects: Compute effect flags that are relevant to this node only, | ||
// excluding its children. | ||
// | ||
// Arguments: | ||
// comp - Compiler instance | ||
// | ||
// Return Value: | ||
// The effect flags. | ||
// | ||
GenTreeFlags GenTree::OperEffects(Compiler* comp) | ||
{ | ||
GenTreeFlags flags = gtFlags & GTF_ALL_EFFECT; | ||
|
||
if (((flags & GTF_ASG) != 0) && !OperRequiresAsgFlag()) | ||
{ | ||
flags &= ~GTF_ASG; | ||
} | ||
|
||
if (((flags & GTF_CALL) != 0) && !OperRequiresCallFlag(comp)) | ||
{ | ||
flags &= ~GTF_CALL; | ||
} | ||
|
||
if (((flags & GTF_EXCEPT) != 0) && !OperMayThrow(comp)) | ||
{ | ||
flags &= ~GTF_EXCEPT; | ||
} | ||
|
||
if (((flags & GTF_GLOB_REF) != 0) && !OperRequiresGlobRefFlag(comp)) | ||
{ | ||
flags &= ~GTF_GLOB_REF; | ||
} | ||
|
||
if ((flags & GTF_ORDER_SIDEEFF) != 0 && !OperSupportsOrderingSideEffect()) | ||
jakobbotsch marked this conversation as resolved.
Show resolved
Hide resolved
|
||
{ | ||
flags &= ~GTF_ORDER_SIDEEFF; | ||
} | ||
|
||
return flags; | ||
} | ||
|
||
//----------------------------------------------------------------------------------- | ||
// GetFieldCount: Return the register count for a multi-reg lclVar. | ||
// | ||
|
@@ -25345,6 +25491,15 @@ bool GenTreeHWIntrinsic::OperRequiresCallFlag() const | |
return false; | ||
} | ||
|
||
//------------------------------------------------------------------------------ | ||
// OperRequiresCallFlag : Check whether the operation requires GTF_GLOB_REF flag regardless | ||
jakobbotsch marked this conversation as resolved.
Show resolved
Hide resolved
|
||
// of the children's flags. | ||
// | ||
bool GenTreeHWIntrinsic::OperRequiresGlobRefFlag() const | ||
{ | ||
return OperIsMemoryLoad() || OperRequiresAsgFlag() || OperRequiresCallFlag(); | ||
} | ||
|
||
//------------------------------------------------------------------------ | ||
// GetLayout: Get the layout for this TYP_STRUCT HWI node. | ||
// | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1852,12 +1852,19 @@ struct GenTree | |
// Returns true if it is a GT_COPY or GT_RELOAD of a multi-reg call node | ||
inline bool IsCopyOrReloadOfMultiRegCall() const; | ||
|
||
bool OperRequiresAsgFlag(); | ||
bool OperRequiresAsgFlag() const; | ||
|
||
bool OperRequiresCallFlag(Compiler* comp); | ||
bool OperRequiresCallFlag(Compiler* comp) const; | ||
|
||
bool OperMayThrow(Compiler* comp); | ||
ExceptionSetFlags OperExceptions(Compiler* comp); | ||
bool OperMayThrow(Compiler* comp); | ||
|
||
bool OperRequiresGlobRefFlag(Compiler* comp) const; | ||
|
||
bool OperSupportsOrderingSideEffect() const; | ||
|
||
// Compute effect flags that only pertain to this node excluding its children. | ||
jakobbotsch marked this conversation as resolved.
Show resolved
Hide resolved
|
||
GenTreeFlags OperEffects(Compiler* comp); | ||
|
||
unsigned GetScaleIndexMul(); | ||
unsigned GetScaleIndexShf(); | ||
|
@@ -6249,6 +6256,7 @@ struct GenTreeHWIntrinsic : public GenTreeJitIntrinsic | |
|
||
bool OperRequiresAsgFlag() const; | ||
bool OperRequiresCallFlag() const; | ||
bool OperRequiresGlobRefFlag() const; | ||
|
||
unsigned GetResultOpNumForRmwIntrinsic(GenTree* use, GenTree* op1, GenTree* op2, GenTree* op3); | ||
|
||
|
@@ -7177,6 +7185,12 @@ struct GenTreeIndir : public GenTreeOp | |
return (gtFlags & GTF_IND_UNALIGNED) != 0; | ||
} | ||
|
||
// True if this indirection is invariant. | ||
bool IsInvariantLoad() const | ||
{ | ||
return (gtFlags & GTF_IND_INVARIANT) != 0; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I also had an There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added it |
||
} | ||
|
||
#if DEBUGGABLE_GENTREE | ||
// Used only for GenTree::GetVtableForOper() | ||
GenTreeIndir() : GenTreeOp() | ||
|
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.
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.
Expanded on this a bit in the remarks.