@@ -417,8 +417,10 @@ void Compiler::optRelopImpliesRelop(RelopImplicationInfo* rii)
417
417
const ValueNum relatedVN = vnStore->GetRelatedRelop (rii->domCmpNormVN , vnRelation);
418
418
if ((relatedVN != ValueNumStore::NoVN) && (relatedVN == rii->treeNormVN ))
419
419
{
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);
422
424
return ;
423
425
}
424
426
}
@@ -543,21 +545,40 @@ void Compiler::optRelopImpliesRelop(RelopImplicationInfo* rii)
543
545
// If dom predicate is wrapped in EQ(*,0) then a true dom
544
546
// predicate implies a false branch outcome, and vice versa.
545
547
//
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);
549
550
550
- // We only get partial knowledge in these cases.
551
+ // We only get partial knowledge in the AND/OR cases.
551
552
//
552
553
// AND(p1,p2) = true ==> both p1 and p2 must be true
553
554
// AND(p1,p2) = false ==> don't know p1 or p2
554
555
// OR(p1,p2) = true ==> don't know p1 or p2
555
556
// OR(p1,p2) = false ==> both p1 and p2 must be false
556
557
//
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)
558
567
{
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);
561
582
}
562
583
563
584
JITDUMP (" Inferring predicate value from %s\n " , GenTree::OpName (predOper));
@@ -826,9 +847,6 @@ bool Compiler::optRedundantBranch(BasicBlock* const block)
826
847
JITDUMP (" Redundant compare; current relop:\n " );
827
848
DISPTREE (tree);
828
849
829
- const bool domIsSameRelop = (rii.vnRelation == ValueNumStore::VN_RELATION_KIND::VRK_Same) ||
830
- (rii.vnRelation == ValueNumStore::VN_RELATION_KIND::VRK_Swap);
831
-
832
850
BasicBlock* const trueSuccessor = domBlock->GetTrueTarget ();
833
851
BasicBlock* const falseSuccessor = domBlock->GetFalseTarget ();
834
852
@@ -851,7 +869,7 @@ bool Compiler::optRedundantBranch(BasicBlock* const block)
851
869
// However we may be able to update the flow from block's predecessors so they
852
870
// bypass block and instead transfer control to jump's successors (aka jump threading).
853
871
//
854
- const bool wasThreaded = optJumpThreadDom (block, domBlock, domIsSameRelop );
872
+ const bool wasThreaded = optJumpThreadDom (block, domBlock, !rii. reverseSense );
855
873
856
874
if (wasThreaded)
857
875
{
@@ -862,7 +880,7 @@ bool Compiler::optRedundantBranch(BasicBlock* const block)
862
880
{
863
881
// True path in dominator reaches, false path doesn't; relop must be true/false.
864
882
//
865
- const bool relopIsTrue = rii.reverseSense ^ (domIsSameRelop | domIsInferredRelop) ;
883
+ const bool relopIsTrue = ! rii.reverseSense ;
866
884
JITDUMP (" True successor " FMT_BB " of " FMT_BB " reaches, relop [%06u] must be %s\n " ,
867
885
domBlock->GetTrueTarget ()->bbNum , domBlock->bbNum , dspTreeID (tree),
868
886
relopIsTrue ? " true" : " false" );
@@ -873,7 +891,7 @@ bool Compiler::optRedundantBranch(BasicBlock* const block)
873
891
{
874
892
// False path from dominator reaches, true path doesn't; relop must be false/true.
875
893
//
876
- const bool relopIsFalse = rii.reverseSense ^ (domIsSameRelop | domIsInferredRelop) ;
894
+ const bool relopIsFalse = ! rii.reverseSense ;
877
895
JITDUMP (" False successor " FMT_BB " of " FMT_BB " reaches, relop [%06u] must be %s\n " ,
878
896
domBlock->GetFalseTarget ()->bbNum , domBlock->bbNum , dspTreeID (tree),
879
897
relopIsFalse ? " false" : " true" );
0 commit comments