Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit 9ef7e18

Browse files
committed
Convert some "constant" SELCCs to SETCC
1 parent 0a0f2a9 commit 9ef7e18

File tree

1 file changed

+93
-0
lines changed

1 file changed

+93
-0
lines changed

src/jit/lower.cpp

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6566,6 +6566,99 @@ GenTree* Lowering::LowerSelCC(GenTreeOpCC* selcc)
65666566
GenTree* falseOp = selcc->gtGetOp1();
65676567
GenTree* trueOp = selcc->gtGetOp2();
65686568

6569+
if (falseOp->OperIs(GT_CNS_INT) && trueOp->OperIs(GT_CNS_INT))
6570+
{
6571+
//
6572+
// SELCC(c1, c2) can sometimes be replaced with SETCC which avoids the need for 2 registers
6573+
// to load the constants:
6574+
// - SELCC(0, 1) -> SETCC
6575+
// - SELCC(0, -1) -> NEG(SETCC)
6576+
// - SELCC(3, 4) -> SETCC + 3
6577+
// - SELCC(0, 2) -> RSH(SETCC, 1)
6578+
//
6579+
6580+
var_types type = genActualType(selcc->TypeGet());
6581+
GenCondition condition = selcc->gtCondition;
6582+
size_t falseValue = static_cast<size_t>(falseOp->AsIntCon()->IconValue());
6583+
size_t trueValue = static_cast<size_t>(trueOp->AsIntCon()->IconValue());
6584+
6585+
if (falseValue > trueValue)
6586+
{
6587+
std::swap(falseValue, trueValue);
6588+
condition.Reverse();
6589+
}
6590+
6591+
LIR::Use use;
6592+
bool isUsed = BlockRange().TryGetUse(selcc, &use);
6593+
GenTree* result = nullptr;
6594+
6595+
if ((falseValue == 0) && (trueValue == SIZE_T_MAX))
6596+
{
6597+
result = comp->gtNewOperNode(GT_NEG, type, selcc);
6598+
BlockRange().InsertAfter(selcc, result);
6599+
}
6600+
else
6601+
{
6602+
size_t zeroOffset = 0;
6603+
6604+
if (falseValue != 0)
6605+
{
6606+
zeroOffset = falseValue;
6607+
falseValue = 0;
6608+
trueValue -= zeroOffset;
6609+
}
6610+
6611+
if (isPow2(trueValue) && ((zeroOffset == 0) || (genLog2(trueValue) <= 3)))
6612+
{
6613+
if (zeroOffset > 0)
6614+
{
6615+
if (trueValue == 1)
6616+
{
6617+
GenTree* offset = comp->gtNewIconNode(zeroOffset, type);
6618+
result = comp->gtNewOperNode(GT_ADD, type, selcc, offset);
6619+
BlockRange().InsertAfter(selcc, offset, result);
6620+
}
6621+
else
6622+
{
6623+
result =
6624+
new (comp, GT_LEA) GenTreeAddrMode(type, nullptr, selcc, static_cast<unsigned>(trueValue),
6625+
static_cast<unsigned>(zeroOffset));
6626+
BlockRange().InsertAfter(selcc, result);
6627+
}
6628+
}
6629+
else if (trueValue > 1)
6630+
{
6631+
GenTree* shiftBy = comp->gtNewIconNode(genLog2(trueValue), type);
6632+
result = comp->gtNewOperNode(GT_LSH, type, selcc, shiftBy);
6633+
BlockRange().InsertAfter(selcc, shiftBy, result);
6634+
}
6635+
else
6636+
{
6637+
result = selcc;
6638+
}
6639+
}
6640+
}
6641+
6642+
if (result != nullptr)
6643+
{
6644+
selcc->ChangeOper(GT_SETCC);
6645+
6646+
GenTreeCC* setcc = selcc->AsCC();
6647+
setcc->gtType = type;
6648+
setcc->gtCondition = condition;
6649+
6650+
BlockRange().Remove(falseOp);
6651+
BlockRange().Remove(trueOp);
6652+
6653+
if (isUsed && (result != selcc))
6654+
{
6655+
use.ReplaceWith(comp, result);
6656+
}
6657+
6658+
return selcc->gtNext;
6659+
}
6660+
}
6661+
65696662
// Put constants in the second operand, this appears to improve register allocation.
65706663

65716664
if (falseOp->IsIntegralConst() && !trueOp->IsIntegralConst())

0 commit comments

Comments
 (0)