@@ -417,8 +417,10 @@ void Compiler::optRelopImpliesRelop(RelopImplicationInfo* rii)
417417 const ValueNum relatedVN = vnStore->GetRelatedRelop (rii->domCmpNormVN , vnRelation);
418418 if ((relatedVN != ValueNumStore::NoVN) && (relatedVN == rii->treeNormVN ))
419419 {
420- rii->canInfer = true ;
421- rii->vnRelation = vnRelation;
420+ rii->canInfer = true ;
421+ rii->vnRelation = vnRelation;
422+ rii->reverseSense = (rii->vnRelation == ValueNumStore::VN_RELATION_KIND::VRK_Reverse) ||
423+ (rii->vnRelation == ValueNumStore::VN_RELATION_KIND::VRK_SwapReverse);
422424 return ;
423425 }
424426 }
@@ -543,21 +545,40 @@ void Compiler::optRelopImpliesRelop(RelopImplicationInfo* rii)
543545 // If dom predicate is wrapped in EQ(*,0) then a true dom
544546 // predicate implies a false branch outcome, and vice versa.
545547 //
546- // And if the dom predicate is GT_NOT we reverse yet again.
547- //
548- rii->reverseSense = (oper == GT_EQ) ^ (predOper == GT_NOT);
548+ rii->reverseSense = (rii->vnRelation == ValueNumStore::VN_RELATION_KIND::VRK_Reverse) ||
549+ (rii->vnRelation == ValueNumStore::VN_RELATION_KIND::VRK_SwapReverse);
549550
550- // We only get partial knowledge in these cases.
551+ // We only get partial knowledge in the AND/OR cases.
551552 //
552553 // AND(p1,p2) = true ==> both p1 and p2 must be true
553554 // AND(p1,p2) = false ==> don't know p1 or p2
554555 // OR(p1,p2) = true ==> don't know p1 or p2
555556 // OR(p1,p2) = false ==> both p1 and p2 must be false
556557 //
557- if (predOper != GT_NOT)
558+ if (predOper == GT_AND)
559+ {
560+ // EQ(AND, 0) false ==> AND true ==> AND operands true
561+ rii->canInferFromFalse = (oper == GT_EQ);
562+ // NE(AND, 0) true ==> AND true ==> AND operands true
563+ rii->canInferFromTrue = (oper == GT_NE);
564+ rii->reverseSense ^= (oper == GT_EQ);
565+ }
566+ else if (predOper == GT_OR)
558567 {
559- rii->canInferFromFalse = rii->reverseSense ^ (predOper == GT_OR);
560- rii->canInferFromTrue = rii->reverseSense ^ (predOper == GT_AND);
568+ // NE(OR, 0) false ==> OR false ==> OR operands false
569+ rii->canInferFromFalse = (oper == GT_NE);
570+ // EQ(OR, 0) true ==> OR false ==> OR operands false
571+ rii->canInferFromTrue = (oper == GT_EQ);
572+ rii->reverseSense ^= (oper == GT_EQ);
573+ }
574+ else
575+ {
576+ assert (predOper == GT_NOT);
577+ // NE(NOT(x), 0) ==> NOT(X)
578+ // EQ(NOT(x), 0) ==> X
579+ rii->canInferFromTrue = true ;
580+ rii->canInferFromFalse = true ;
581+ rii->reverseSense ^= (oper == GT_NE);
561582 }
562583
563584 JITDUMP (" Inferring predicate value from %s\n " , GenTree::OpName (predOper));
@@ -826,9 +847,6 @@ bool Compiler::optRedundantBranch(BasicBlock* const block)
826847 JITDUMP (" Redundant compare; current relop:\n " );
827848 DISPTREE (tree);
828849
829- const bool domIsSameRelop = (rii.vnRelation == ValueNumStore::VN_RELATION_KIND::VRK_Same) ||
830- (rii.vnRelation == ValueNumStore::VN_RELATION_KIND::VRK_Swap);
831-
832850 BasicBlock* const trueSuccessor = domBlock->GetTrueTarget ();
833851 BasicBlock* const falseSuccessor = domBlock->GetFalseTarget ();
834852
@@ -851,7 +869,7 @@ bool Compiler::optRedundantBranch(BasicBlock* const block)
851869 // However we may be able to update the flow from block's predecessors so they
852870 // bypass block and instead transfer control to jump's successors (aka jump threading).
853871 //
854- const bool wasThreaded = optJumpThreadDom (block, domBlock, domIsSameRelop );
872+ const bool wasThreaded = optJumpThreadDom (block, domBlock, !rii. reverseSense );
855873
856874 if (wasThreaded)
857875 {
@@ -862,7 +880,7 @@ bool Compiler::optRedundantBranch(BasicBlock* const block)
862880 {
863881 // True path in dominator reaches, false path doesn't; relop must be true/false.
864882 //
865- const bool relopIsTrue = rii.reverseSense ^ (domIsSameRelop | domIsInferredRelop) ;
883+ const bool relopIsTrue = ! rii.reverseSense ;
866884 JITDUMP (" True successor " FMT_BB " of " FMT_BB " reaches, relop [%06u] must be %s\n " ,
867885 domBlock->GetTrueTarget ()->bbNum , domBlock->bbNum , dspTreeID (tree),
868886 relopIsTrue ? " true" : " false" );
@@ -873,7 +891,7 @@ bool Compiler::optRedundantBranch(BasicBlock* const block)
873891 {
874892 // False path from dominator reaches, true path doesn't; relop must be false/true.
875893 //
876- const bool relopIsFalse = rii.reverseSense ^ (domIsSameRelop | domIsInferredRelop) ;
894+ const bool relopIsFalse = ! rii.reverseSense ;
877895 JITDUMP (" False successor " FMT_BB " of " FMT_BB " reaches, relop [%06u] must be %s\n " ,
878896 domBlock->GetFalseTarget ()->bbNum , domBlock->bbNum , dspTreeID (tree),
879897 relopIsFalse ? " false" : " true" );
0 commit comments