Skip to content

Commit cedf4e2

Browse files
authored
JIT: revise optRelopImpliesRelop to always set reverseSense (#111803)
Update clients to rely on `reverseSense` rather than parsing `vnRelation`. Also revised the and/or inference slightly as I found it hard to follow; hopefully it's clearer now. Fixes an issue that came up in testing #111766.
1 parent f0de80d commit cedf4e2

File tree

2 files changed

+35
-21
lines changed

2 files changed

+35
-21
lines changed

src/coreclr/jit/redundantbranchopts.cpp

Lines changed: 33 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -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");

src/coreclr/jit/scev.cpp

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1559,22 +1559,18 @@ RelopEvaluationResult ScalarEvolutionContext::EvaluateRelop(ValueNum vn)
15591559
continue;
15601560
}
15611561

1562-
bool domIsInferredRelop = (rii.vnRelation == ValueNumStore::VN_RELATION_KIND::VRK_Inferred);
1563-
bool domIsSameRelop = (rii.vnRelation == ValueNumStore::VN_RELATION_KIND::VRK_Same) ||
1564-
(rii.vnRelation == ValueNumStore::VN_RELATION_KIND::VRK_Swap);
1565-
15661562
bool trueReaches = m_comp->optReachable(idom->GetTrueTarget(), m_loop->GetHeader(), idom);
15671563
bool falseReaches = m_comp->optReachable(idom->GetFalseTarget(), m_loop->GetHeader(), idom);
15681564

15691565
if (trueReaches && !falseReaches && rii.canInferFromTrue)
15701566
{
1571-
bool relopIsTrue = rii.reverseSense ^ (domIsSameRelop | domIsInferredRelop);
1567+
bool relopIsTrue = !rii.reverseSense;
15721568
return relopIsTrue ? RelopEvaluationResult::True : RelopEvaluationResult::False;
15731569
}
15741570

15751571
if (falseReaches && !trueReaches && rii.canInferFromFalse)
15761572
{
1577-
bool relopIsFalse = rii.reverseSense ^ (domIsSameRelop | domIsInferredRelop);
1573+
bool relopIsFalse = !rii.reverseSense;
15781574
return relopIsFalse ? RelopEvaluationResult::False : RelopEvaluationResult::True;
15791575
}
15801576
}

0 commit comments

Comments
 (0)