@@ -3203,18 +3203,175 @@ GenTree* Compiler::optAssertionProp_RelOp(ASSERT_VALARG_TP assertions, GenTree*
32033203 return optAssertionPropLocal_RelOp (assertions, tree, stmt);
32043204}
32053205
3206- /* ************************************************************************************
3207- *
3208- * Given the set of "assertions" to look up a relop assertion about the relop "tree",
3209- * perform Value numbering based relop assertion propagation on the tree.
3210- *
3211- */
3206+ // ------------------------------------------------------------------------
3207+ // optAssertionProp: try and optimize a relop via assertion propagation
3208+ // (and dominator based redundant branch elimination)
3209+ //
3210+ // Arguments:
3211+ // assertions - set of live assertions
3212+ // tree - tree to possibly optimize
3213+ // stmt - statement containing the tree
3214+ //
3215+ // Returns:
3216+ // The modified tree, or nullptr if no assertion prop took place.
3217+ //
3218+ // Notes:
3219+ // Redundant branch elimination doesn't rely on assertions currently,
3220+ // it is done here out of convenience.
3221+ //
32123222GenTree* Compiler::optAssertionPropGlobal_RelOp (ASSERT_VALARG_TP assertions, GenTree* tree, Statement* stmt)
32133223{
32143224 GenTree* newTree = tree;
32153225 GenTree* op1 = tree->AsOp ()->gtOp1 ;
32163226 GenTree* op2 = tree->AsOp ()->gtOp2 ;
32173227
3228+ // First, walk up the dom tree and see if any dominating block has branched on
3229+ // exactly this tree's VN...
3230+ //
3231+ BasicBlock* prevBlock = compCurBB;
3232+ BasicBlock* domBlock = compCurBB->bbIDom ;
3233+ int relopValue = -1 ;
3234+
3235+ while (domBlock != nullptr )
3236+ {
3237+ if (prevBlock == compCurBB)
3238+ {
3239+ JITDUMP (" \n VN relop, checking " FMT_BB " for redundancy\n " , compCurBB->bbNum );
3240+ }
3241+
3242+ // Check the current dominator
3243+ //
3244+ JITDUMP (" ... checking dom " FMT_BB " \n " , domBlock->bbNum );
3245+
3246+ if (domBlock->bbJumpKind == BBJ_COND)
3247+ {
3248+ Statement* const domJumpStmt = domBlock->lastStmt ();
3249+ GenTree* const domJumpTree = domJumpStmt->GetRootNode ();
3250+ assert (domJumpTree->OperIs (GT_JTRUE));
3251+ GenTree* const domCmpTree = domJumpTree->AsOp ()->gtGetOp1 ();
3252+
3253+ if (domCmpTree->OperKind () & GTK_RELOP)
3254+ {
3255+ ValueNum domCmpVN = domCmpTree->GetVN (VNK_Conservative);
3256+
3257+ // Note we could also infer the tree relop's value from similar relops higher in the dom tree.
3258+ // For example, (x >= 0) dominating (x > 0), or (x < 0) dominating (x > 0).
3259+ //
3260+ // That is left as a future enhancement.
3261+ //
3262+ if (domCmpVN == tree->GetVN (VNK_Conservative))
3263+ {
3264+ // Thes compare in "tree" is redundant.
3265+ // Is there a unique path from the dominating compare?
3266+ JITDUMP (" Redundant compare; current relop:\n " );
3267+ DISPTREE (tree);
3268+ JITDUMP (" dominating relop in " FMT_BB " with same VN:\n " , domBlock->bbNum );
3269+ DISPTREE (domCmpTree);
3270+
3271+ BasicBlock* trueSuccessor = domBlock->bbJumpDest ;
3272+ BasicBlock* falseSuccessor = domBlock->bbNext ;
3273+
3274+ const bool trueReaches = fgReachable (trueSuccessor, compCurBB);
3275+ const bool falseReaches = fgReachable (falseSuccessor, compCurBB);
3276+
3277+ if (trueReaches && falseReaches)
3278+ {
3279+ // Both dominating compare outcomes reach the current block so we can't infer the
3280+ // value of the relop.
3281+ //
3282+ // If the dominating compare is close to the current compare, this may be a missed
3283+ // opportunity to tail duplicate.
3284+ //
3285+ JITDUMP (" Both successors of " FMT_BB " reach, can't optimize\n " , domBlock->bbNum );
3286+
3287+ if ((trueSuccessor->GetUniqueSucc () == compCurBB) ||
3288+ (falseSuccessor->GetUniqueSucc () == compCurBB))
3289+ {
3290+ JITDUMP (" Perhaps we should have tail duplicated " FMT_BB " \n " , compCurBB->bbNum );
3291+ }
3292+ }
3293+ else if (trueReaches)
3294+ {
3295+ // Taken jump in dominator reaches, fall through doesn't; relop must be true.
3296+ //
3297+ JITDUMP (" Jump successor " FMT_BB " of " FMT_BB " reaches, relop must be true\n " ,
3298+ domBlock->bbJumpDest ->bbNum , domBlock->bbNum );
3299+ relopValue = 1 ;
3300+ break ;
3301+ }
3302+ else if (falseReaches)
3303+ {
3304+ // Fall through from dominator reaches, taken jump doesn't; relop must be false.
3305+ //
3306+ JITDUMP (" Fall through successor " FMT_BB " of " FMT_BB " reaches, relop must be false\n " ,
3307+ domBlock->bbNext ->bbNum , domBlock->bbNum );
3308+ relopValue = 0 ;
3309+ break ;
3310+ }
3311+ else
3312+ {
3313+ // No apparent path from the dominating BB.
3314+ //
3315+ // If domBlock or compCurBB is in an EH handler we may fail to find a path.
3316+ // Just ignore those cases.
3317+ //
3318+ // No point in looking further up the tree.
3319+ //
3320+ break ;
3321+ }
3322+ }
3323+ }
3324+ }
3325+
3326+ // Keep looking higher up in the tree
3327+ //
3328+ prevBlock = domBlock;
3329+ domBlock = domBlock->bbIDom ;
3330+ }
3331+
3332+ // Did we determine the relop value via dominance checks? If so, optimize.
3333+ //
3334+ if (relopValue == -1 )
3335+ {
3336+ JITDUMP (" Failed to find a suitable dominating compare, so we won't optimize\n " );
3337+ }
3338+ else
3339+ {
3340+ // Bail out if tree is has certain side effects
3341+ //
3342+ // Note we really shouldn't get here if the tree has non-exception effects,
3343+ // as they should have impacted the value number.
3344+ //
3345+ if ((tree->gtFlags & GTF_SIDE_EFFECT) != 0 )
3346+ {
3347+ // Bail if there is a non-exception effect.
3348+ //
3349+ if ((tree->gtFlags & GTF_SIDE_EFFECT) != GTF_EXCEPT)
3350+ {
3351+ JITDUMP (" Current relop has non-exception side effects, so we won't optimize\n " );
3352+ return nullptr ;
3353+ }
3354+
3355+ // Be conservative if there is an exception effect and we're in an EH region
3356+ // as we might not model the full extent of EH flow.
3357+ //
3358+ if (compCurBB->hasTryIndex ())
3359+ {
3360+ JITDUMP (" Current relop has exception side effect and is in a try, so we won't optimize\n " );
3361+ return nullptr ;
3362+ }
3363+ }
3364+
3365+ JITDUMP (" \n VN relop based redundant branch opt in " FMT_BB " :\n " , compCurBB->bbNum );
3366+
3367+ tree->ChangeOperConst (GT_CNS_INT);
3368+ tree->AsIntCon ()->gtIconVal = relopValue;
3369+
3370+ newTree = fgMorphTree (tree);
3371+ DISPTREE (newTree);
3372+ return optAssertionProp_Update (newTree, tree, stmt);
3373+ }
3374+
32183375 // Look for assertions of the form (tree EQ/NE 0)
32193376 AssertionIndex index = optGlobalAssertionIsEqualOrNotEqualZero (assertions, tree);
32203377
0 commit comments