Skip to content
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Solve most of the regressions
In morph, when narrowing the AND operand, only
insert casts if necessary - prefer to use "optNarrowTree".
Otherwise we end up with redundant register shuffling.
  • Loading branch information
SingleAccretion committed Jun 22, 2021
commit 3b61c12892cd19876f17cee1abbe734ec0852442
64 changes: 37 additions & 27 deletions src/coreclr/jit/morph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13789,44 +13789,54 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac)

noway_assert(op1->TypeGet() == TYP_LONG && op1->OperGet() == GT_AND);

/* Is the result of the mask effectively an INT ? */

GenTree* andMask;
andMask = op1->AsOp()->gtOp2;
if (andMask->gtOper != GT_CNS_NATIVELONG)
{
goto COMPARE;
}
if ((andMask->AsIntConCommon()->LngValue() >> 32) != 0)
// The transform below cannot preserve VNs.
if (fgGlobalMorph)
{
goto COMPARE;
}
// Is the result of the mask effectively an INT ?

/* Now we know that we can cast AsOp()->gtOp1 of AND to int */
GenTree* andMask = op1->AsOp()->gtOp2;

if (andMask->gtOper != GT_CNS_NATIVELONG)
{
goto COMPARE;
}
if ((andMask->AsIntConCommon()->LngValue() >> 32) != 0)
{
goto COMPARE;
}

op1->AsOp()->gtOp1 = gtNewCastNode(TYP_INT, op1->AsOp()->gtOp1, false, TYP_INT);
// Now we narrow AsOp()->gtOp1 of AND to int.
if (optNarrowTree(op1->AsOp()->gtGetOp1(), TYP_LONG, TYP_INT, ValueNumPair(), false))
{
optNarrowTree(op1->AsOp()->gtGetOp1(), TYP_LONG, TYP_INT, ValueNumPair(), true);
}
else
{
op1->AsOp()->gtOp1 = gtNewCastNode(TYP_INT, op1->AsOp()->gtGetOp1(), false, TYP_INT);
}

/* now replace the mask node (AsOp()->gtOp2 of AND node) */
// now replace the mask node (AsOp()->gtOp2 of AND node).

noway_assert(andMask == op1->AsOp()->gtOp2);
noway_assert(andMask == op1->AsOp()->gtOp2);

ival1 = (int)andMask->AsIntConCommon()->LngValue();
andMask->SetOper(GT_CNS_INT);
andMask->gtType = TYP_INT;
andMask->AsIntCon()->gtIconVal = ival1;
ival1 = (int)andMask->AsIntConCommon()->LngValue();
andMask->SetOper(GT_CNS_INT);
andMask->gtType = TYP_INT;
andMask->AsIntCon()->gtIconVal = ival1;

/* now change the type of the AND node */
// now change the type of the AND node.

op1->gtType = TYP_INT;
op1->gtType = TYP_INT;

/* finally we replace the comparand */
// finally we replace the comparand.

ival2 = (int)cns2->AsIntConCommon()->LngValue();
cns2->SetOper(GT_CNS_INT);
cns2->gtType = TYP_INT;
ival2 = (int)cns2->AsIntConCommon()->LngValue();
cns2->SetOper(GT_CNS_INT);
cns2->gtType = TYP_INT;

noway_assert(cns2 == op2);
cns2->AsIntCon()->gtIconVal = ival2;
noway_assert(cns2 == op2);
cns2->AsIntCon()->gtIconVal = ival2;
}

goto COMPARE;

Expand Down