- 
                Notifications
    You must be signed in to change notification settings 
- Fork 5.2k
JIT: also run local assertion prop in postorder during morph #115626
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 all commits
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 | 
|---|---|---|
|  | @@ -7106,6 +7106,7 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac, bool* optA | |
| if (optLocalAssertionProp) | ||
| { | ||
| isQmarkColon = true; | ||
| BitVecOps::ClearD(apTraits, apLocalPostorder); | ||
| } | ||
| break; | ||
|  | ||
|  | @@ -7746,6 +7747,40 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac, bool* optA | |
| qmarkOp2 = oldTree->AsOp()->gtOp2->AsOp()->gtOp2; | ||
| } | ||
|  | ||
| // During global morph, give assertion prop another shot at this tree. | ||
| // | ||
| // We need to use the "postorder" assertion set here, because apLocal | ||
| // may reflect results from subtrees that have since been reordered. | ||
| // | ||
| // apLocalPostorder only includes live assertions from prior statements. | ||
| // | ||
| if (fgGlobalMorph && optLocalAssertionProp && (optAssertionCount > 0)) | ||
| { | ||
| GenTree* optimizedTree = tree; | ||
| bool again = JitConfig.JitEnablePostorderLocalAssertionProp() > 0; | ||
| bool didOptimize = false; | ||
|  | ||
| if (!again) | ||
| { | ||
| JITDUMP("*** Postorder assertion prop disabled by config\n"); | ||
| } | ||
|  | ||
| while (again) | ||
| { | ||
| tree = optimizedTree; | ||
| optimizedTree = optAssertionProp(apLocalPostorder, tree, nullptr, nullptr); | ||
| again = (optimizedTree != nullptr); | ||
| didOptimize |= again; | ||
| } | ||
|  | ||
| assert(tree != nullptr); | ||
|  | ||
| if (didOptimize) | ||
| { | ||
| gtUpdateNodeSideEffects(tree); | ||
| } | ||
| } | ||
|  | ||
| // Try to fold it, maybe we get lucky, | ||
| tree = gtFoldExpr(tree); | ||
|  | ||
|  | @@ -11718,13 +11753,12 @@ void Compiler::fgKillDependentAssertionsSingle(unsigned lclNum DEBUGARG(GenTree* | |
| { | ||
| // Active dependent assertions are killed here | ||
| // | ||
| ASSERT_TP killed = BitVecOps::MakeCopy(apTraits, GetAssertionDep(lclNum)); | ||
| BitVecOps::IntersectionD(apTraits, killed, apLocal); | ||
|  | ||
| if (killed) | ||
| { | ||
| ASSERT_TP killed = GetAssertionDep(lclNum); | ||
|  | ||
| #ifdef DEBUG | ||
| bool hasKills = !BitVecOps::IsEmptyIntersection(apTraits, apLocal, killed); | ||
| if (hasKills) | ||
| { | ||
| AssertionIndex index = optAssertionCount; | ||
| while (killed && (index > 0)) | ||
| { | ||
|  | @@ -11744,10 +11778,11 @@ void Compiler::fgKillDependentAssertionsSingle(unsigned lclNum DEBUGARG(GenTree* | |
|  | ||
| index--; | ||
| } | ||
| } | ||
| #endif | ||
|  | ||
|         
                  AndyAyersMS marked this conversation as resolved.
              Show resolved
            Hide resolved | ||
| BitVecOps::DiffD(apTraits, apLocal, killed); | ||
| } | ||
| BitVecOps::DiffD(apTraits, apLocal, killed); | ||
| BitVecOps::DiffD(apTraits, apLocalPostorder, killed); | ||
| } | ||
|  | ||
| //------------------------------------------------------------------------ | ||
|  | @@ -11764,7 +11799,7 @@ void Compiler::fgKillDependentAssertionsSingle(unsigned lclNum DEBUGARG(GenTree* | |
| // | ||
| void Compiler::fgKillDependentAssertions(unsigned lclNum DEBUGARG(GenTree* tree)) | ||
| { | ||
| if (BitVecOps::IsEmpty(apTraits, apLocal)) | ||
| if (BitVecOps::IsEmpty(apTraits, apLocal) && BitVecOps::IsEmpty(apTraits, apLocalPostorder)) | ||
| { | ||
| return; | ||
| } | ||
|  | @@ -12450,6 +12485,11 @@ void Compiler::fgMorphStmts(BasicBlock* block) | |
| compCurStmt = stmt; | ||
| GenTree* oldTree = stmt->GetRootNode(); | ||
|  | ||
| if (optLocalAssertionProp) | ||
| { | ||
| BitVecOps::Assign(apTraits, apLocalPostorder, apLocal); | ||
| } | ||
|  | ||
| #ifdef DEBUG | ||
|  | ||
| unsigned oldHash = verbose ? gtHashValue(oldTree) : DUMMY_INIT(~0); | ||
|  | @@ -12670,7 +12710,8 @@ void Compiler::fgMorphBlock(BasicBlock* block, MorphUnreachableInfo* unreachable | |
| // Each block starts with an empty table, and no available assertions | ||
| // | ||
| optAssertionReset(0); | ||
| apLocal = BitVecOps::MakeEmpty(apTraits); | ||
| BitVecOps::ClearD(apTraits, apLocal); | ||
| BitVecOps::ClearD(apTraits, apLocalPostorder); | ||
| } | ||
| else | ||
| { | ||
|  | @@ -12808,6 +12849,8 @@ void Compiler::fgMorphBlock(BasicBlock* block, MorphUnreachableInfo* unreachable | |
| apLocal = BitVecOps::MakeEmpty(apTraits); | ||
| } | ||
|  | ||
| BitVecOps::Assign(apTraits, apLocalPostorder, apLocal); | ||
|  | ||
| JITDUMPEXEC(optDumpAssertionIndices("Assertions in: ", apLocal)); | ||
| } | ||
| } | ||
|  | @@ -12876,6 +12919,8 @@ PhaseStatus Compiler::fgMorphBlocks() | |
| // Local assertion prop is enabled if we are optimizing. | ||
| // | ||
| optAssertionInit(/* isLocalProp*/ true); | ||
| apLocal = BitVecOps::MakeEmpty(apTraits); | ||
| apLocalPostorder = BitVecOps::MakeEmpty(apTraits); | ||
| } | ||
| else | ||
| { | ||
|  | @@ -13011,10 +13056,12 @@ PhaseStatus Compiler::fgMorphBlocks() | |
|  | ||
| if (optLocalAssertionProp) | ||
| { | ||
| Metrics.LocalAssertionCount = optAssertionCount; | ||
| Metrics.LocalAssertionOverflow = optAssertionOverflow; | ||
| Metrics.MorphTrackedLocals = lvaTrackedCount; | ||
| Metrics.MorphLocals = lvaCount; | ||
| Metrics.LocalAssertionCount = optAssertionCount; | ||
| Metrics.LocalAssertionOverflow = optAssertionOverflow; | ||
| Metrics.MorphTrackedLocals = lvaTrackedCount; | ||
| Metrics.MorphLocals = lvaCount; | ||
| optLocalAssertionProp = false; | ||
| 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. curious - is this something you noticed or it was prevention from getting into weird state, now that we will do another round of assertions with  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 wanted to make sure calls into morph after the global morph phase didn't try and use local assertions. Most uses of local assertions in morph are guarded by  | ||
| optCrossBlockLocalAssertionProp = false; | ||
| } | ||
|  | ||
| // We may have converted a tailcall into a loop, in which case the first BB | ||
|  | ||
Uh oh!
There was an error while loading. Please reload this page.