-
Notifications
You must be signed in to change notification settings - Fork 5.3k
Eliminate redundant test instruction #53214
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
Changes from 1 commit
06dda15
b6f80ea
8867374
01fb6ba
81eb9eb
53c4325
7ded469
e7e04b7
b1e0fc3
068fb15
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
- Loading branch information
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -159,6 +159,69 @@ bool emitter::IsWriteZFFlags(instruction ins) | |
| return (CodeGenInterface::instInfo[ins] & INS_FLAGS_WritesZF) != 0; | ||
| } | ||
|
|
||
|
|
||
| //------------------------------------------------------------------------ | ||
| // IsFlagsModified: check if the instruction modifies the flags. | ||
| // | ||
| // Arguments: | ||
| // id - instruction to test | ||
| // | ||
| // Return Value: | ||
| // true if instruction modified any flag, false otherwise. | ||
| // | ||
| bool emitter::IsFlagsModified(instrDesc* id) | ||
| { | ||
| instruction ins = id->idIns(); | ||
| insFormat fmt = id->idInsFmt(); | ||
|
|
||
| if (fmt == IF_RRW_SHF) | ||
| { | ||
| if (id->idIsLargeCns()) | ||
| { | ||
| return true; | ||
| } | ||
| else if (id->idSmallCns() == 0) | ||
| { | ||
| switch (ins) | ||
| { | ||
| // If shift-amount for below instructions is 0, then flags are unaffected. | ||
| case INS_rcl_N: | ||
| case INS_rcr_N: | ||
| case INS_rol_N: | ||
| case INS_ror_N: | ||
| case INS_shl_N: | ||
| case INS_shr_N: | ||
| case INS_sar_N: | ||
| return false; | ||
| default: | ||
| return true; | ||
|
|
||
| } | ||
| } | ||
| } | ||
| else if (fmt == IF_RRW) | ||
| { | ||
| switch (ins) | ||
| { | ||
| // If shift-amount for below instructions is 0, then flags are unaffected. | ||
| // So, to be conservative, do not optimize if the instruction has register | ||
| // as the shift-amount operand. | ||
| case INS_rcl: | ||
| case INS_rcr: | ||
| case INS_rol: | ||
| case INS_ror: | ||
| case INS_shl: | ||
| case INS_shr: | ||
| case INS_sar: | ||
| return false; | ||
|
Member
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 think this might require some careful considerations. For the purposes of this PR, this is fine and is simply used as a "did the previous instruction set the flag and therefore a However, for future improvements we may consider more advanced analysis such as: Then, this will become problematic. The latter happens in Clang/MSVC in various places and are one of the reasons that
Member
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. Perhaps we can return some ternary state here representing "yes", "no", and "it depends"?
Contributor
Author
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. Today, we only track prevInstruction (
Member
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. Right, it's not something I think we need to be concerned with "today", but rather something I could see being problematic in the future for certain optimizations. The method implies boolean state but in practice its slightly more nuanced and one of the answers is "maybe", so it may end up confusing callers.
Contributor
Author
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.
Exactly - what are callers supposed to do with "maybe". So for now, I will leave it as-is.
Member
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 think that is contextual. In the case of this PR, you care "did the last instruction definitely set the flag I care about" and so you would treat In other cases, optimizations may care "did the last instruction definitely not set the flag I care about" and so they would treat it as
Contributor
Author
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. Renamed the method to |
||
| default: | ||
| return true; | ||
| } | ||
| } | ||
|
|
||
| return true; | ||
| } | ||
|
|
||
| //------------------------------------------------------------------------ | ||
| // AreUpper32BitsZero: check if some previously emitted | ||
| // instruction set the upper 32 bits of reg to zero. | ||
|
|
@@ -276,7 +339,6 @@ bool emitter::AreFlagsSetToZeroCmp(regNumber reg, emitAttr opSize, genTreeOps tr | |
| case IF_RRD: | ||
| case IF_RRW: | ||
| break; | ||
|
|
||
| default: | ||
| return false; | ||
| } | ||
|
|
@@ -294,7 +356,7 @@ bool emitter::AreFlagsSetToZeroCmp(regNumber reg, emitAttr opSize, genTreeOps tr | |
|
|
||
| if ((treeOps == GT_EQ) || (treeOps == GT_NE)) | ||
| { | ||
| if (IsWriteZFFlags(lastIns)) | ||
| if (IsWriteZFFlags(lastIns) && IsFlagsModified(id)) | ||
| { | ||
| return id->idOpSize() == opSize; | ||
| } | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.