@@ -128,23 +128,42 @@ bool Compiler::optRedundantBranch(BasicBlock* const block)
128128
129129 if (domCmpTree->OperKind () & GTK_RELOP)
130130 {
131- // We can use liberal VNs as bounds checks are not yet
131+ // We can use liberal VNs here, as bounds checks are not yet
132132 // manifest explicitly as relops.
133133 //
134- ValueNum domCmpVN = domCmpTree->GetVN (VNK_Liberal);
135-
136- // Note we could also infer the tree relop's value from similar relops higher in the dom tree.
137- // For example, (x >= 0) dominating (x > 0), or (x < 0) dominating (x > 0).
134+ // Look for an exact match and also try the various swapped/reversed forms.
135+ //
136+ const ValueNum treeVN = tree->GetVN (VNK_Liberal);
137+ const ValueNum domCmpVN = domCmpTree->GetVN (VNK_Liberal);
138+ const ValueNum domCmpSwpVN =
139+ vnStore->GetRelatedRelop (domCmpVN, ValueNumStore::VN_RELATION_KIND::VRK_Swap);
140+ const ValueNum domCmpRevVN =
141+ vnStore->GetRelatedRelop (domCmpVN, ValueNumStore::VN_RELATION_KIND::VRK_Reverse);
142+ const ValueNum domCmpSwpRevVN =
143+ vnStore->GetRelatedRelop (domCmpVN, ValueNumStore::VN_RELATION_KIND::VRK_SwapReverse);
144+
145+ const bool matchCmp = ((domCmpVN != ValueNumStore::NoVN) && (domCmpVN == treeVN));
146+ const bool matchSwp = ((domCmpSwpVN != ValueNumStore::NoVN) && (domCmpSwpVN == treeVN));
147+ const bool matchRev = ((domCmpRevVN != ValueNumStore::NoVN) && (domCmpRevVN == treeVN));
148+ const bool matchSwpRev = ((domCmpSwpRevVN != ValueNumStore::NoVN) && (domCmpSwpRevVN == treeVN));
149+ const bool domIsSameRelop = matchCmp || matchSwp;
150+ const bool domIsRevRelop = matchRev || matchSwpRev;
151+
152+ // Note we could also infer the tree relop's value from relops higher in the dom tree
153+ // that involve the same operands but are not swaps or reverses.
154+ //
155+ // For example, (x >= 0) dominating (x > 0).
138156 //
139157 // That is left as a future enhancement.
140158 //
141- if (domCmpVN == tree-> GetVN (VNK_Liberal) )
159+ if (domIsSameRelop || domIsRevRelop )
142160 {
143161 // The compare in "tree" is redundant.
144162 // Is there a unique path from the dominating compare?
145163 //
146- JITDUMP (" \n Dominator " FMT_BB " of " FMT_BB " has relop with same liberal VN:\n " , domBlock->bbNum ,
147- block->bbNum );
164+ JITDUMP (" \n Dominator " FMT_BB " of " FMT_BB " has %srelop with %s liberal VN\n " , domBlock->bbNum ,
165+ block->bbNum , matchSwp || matchSwpRev ? " swapped " : " " ,
166+ domIsSameRelop ? " the same" : " a reverse" );
148167 DISPTREE (domCmpTree);
149168 JITDUMP (" Redundant compare; current relop:\n " );
150169 DISPTREE (tree);
@@ -162,7 +181,7 @@ bool Compiler::optRedundantBranch(BasicBlock* const block)
162181 // However we may be able to update the flow from block's predecessors so they
163182 // bypass block and instead transfer control to jump's successors (aka jump threading).
164183 //
165- const bool wasThreaded = optJumpThread (block, domBlock);
184+ const bool wasThreaded = optJumpThread (block, domBlock, domIsSameRelop );
166185
167186 if (wasThreaded)
168187 {
@@ -171,20 +190,20 @@ bool Compiler::optRedundantBranch(BasicBlock* const block)
171190 }
172191 else if (trueReaches)
173192 {
174- // Taken jump in dominator reaches, fall through doesn't; relop must be true.
193+ // Taken jump in dominator reaches, fall through doesn't; relop must be true/false .
175194 //
176- JITDUMP (" Jump successor " FMT_BB " of " FMT_BB " reaches, relop must be true \n " ,
177- domBlock->bbJumpDest ->bbNum , domBlock->bbNum );
178- relopValue = 1 ;
195+ JITDUMP (" Jump successor " FMT_BB " of " FMT_BB " reaches, relop must be %s \n " ,
196+ domBlock->bbJumpDest ->bbNum , domBlock->bbNum , domIsSameRelop ? " true " : " false " );
197+ relopValue = domIsSameRelop ? 1 : 0 ;
179198 break ;
180199 }
181200 else if (falseReaches)
182201 {
183- // Fall through from dominator reaches, taken jump doesn't; relop must be false.
202+ // Fall through from dominator reaches, taken jump doesn't; relop must be false/true .
184203 //
185- JITDUMP (" Fall through successor " FMT_BB " of " FMT_BB " reaches, relop must be false \n " ,
186- domBlock->bbNext ->bbNum , domBlock->bbNum );
187- relopValue = 0 ;
204+ JITDUMP (" Fall through successor " FMT_BB " of " FMT_BB " reaches, relop must be %s \n " ,
205+ domBlock->bbNext ->bbNum , domBlock->bbNum , domIsSameRelop ? " false " : " true " );
206+ relopValue = domIsSameRelop ? 0 : 1 ;
188207 break ;
189208 }
190209 else
@@ -259,6 +278,8 @@ bool Compiler::optRedundantBranch(BasicBlock* const block)
259278// Arguments:
260279// block - block with branch to optimize
261280// domBlock - a dominating block that has an equivalent branch
281+ // domIsSameRelop - if true, dominating block does the same compare;
282+ // if false, dominating block does a reverse compare
262283//
263284// Returns:
264285// True if the branch was optimized.
@@ -273,7 +294,7 @@ bool Compiler::optRedundantBranch(BasicBlock* const block)
273294// / \ | |
274295// C D C D
275296//
276- bool Compiler::optJumpThread (BasicBlock* const block, BasicBlock* const domBlock)
297+ bool Compiler::optJumpThread (BasicBlock* const block, BasicBlock* const domBlock, bool domIsSameRelop )
277298{
278299 assert (block->bbJumpKind == BBJ_COND);
279300 assert (domBlock->bbJumpKind == BBJ_COND);
@@ -370,8 +391,13 @@ bool Compiler::optJumpThread(BasicBlock* const block, BasicBlock* const domBlock
370391 // are correlated exclusively with a true value for block's relop, and which
371392 // are correlated exclusively with a false value (aka true preds and false preds).
372393 //
373- // To do this we try and follow the flow from domBlock to block; any block pred
374- // reachable from domBlock's true edge is a true pred, and vice versa.
394+ // To do this we try and follow the flow from domBlock to block. When domIsSameRelop
395+ // is true, any block pred reachable from domBlock's true edge is a true pred of block,
396+ // and any block pred reachable from domBlock's false edge is a false pred of block.
397+ //
398+ // If domIsSameRelop is false, then the roles of the of the paths from domBlock swap:
399+ // any block pred reachable from domBlock's true edge is a false pred of block,
400+ // and any block pred reachable from domBlock's false edge is a true pred of block.
375401 //
376402 // However, there are some exceptions:
377403 //
@@ -400,8 +426,8 @@ bool Compiler::optJumpThread(BasicBlock* const block, BasicBlock* const domBlock
400426 int numTruePreds = 0 ;
401427 int numFalsePreds = 0 ;
402428 BasicBlock* fallThroughPred = nullptr ;
403- BasicBlock* const trueSuccessor = domBlock->bbJumpDest ;
404- BasicBlock* const falseSuccessor = domBlock->bbNext ;
429+ BasicBlock* const trueSuccessor = domIsSameRelop ? domBlock->bbJumpDest : domBlock-> bbNext ;
430+ BasicBlock* const falseSuccessor = domIsSameRelop ? domBlock->bbNext : domBlock-> bbJumpDest ;
405431 BasicBlock* const trueTarget = block->bbJumpDest ;
406432 BasicBlock* const falseTarget = block->bbNext ;
407433 BlockSet truePreds = BlockSetOps::MakeEmpty (this );
0 commit comments