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

Commit 4b5b426

Browse files
committed
Convert some "constant" SELCCs to SETCC
1 parent 8f676bb commit 4b5b426

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
@@ -6610,6 +6610,99 @@ GenTree* Lowering::LowerSelCC(GenTreeOpCC* selcc)
66106610
GenTree* falseOp = selcc->gtGetOp1();
66116611
GenTree* trueOp = selcc->gtGetOp2();
66126612

6613+
if (falseOp->OperIs(GT_CNS_INT) && trueOp->OperIs(GT_CNS_INT))
6614+
{
6615+
//
6616+
// SELCC(c1, c2) can sometimes be replaced with SETCC which avoids the need for 2 registers
6617+
// to load the constants:
6618+
// - SELCC(0, 1) -> SETCC
6619+
// - SELCC(0, -1) -> NEG(SETCC)
6620+
// - SELCC(3, 4) -> SETCC + 3
6621+
// - SELCC(0, 2) -> RSH(SETCC, 1)
6622+
//
6623+
6624+
var_types type = genActualType(selcc->TypeGet());
6625+
GenCondition condition = selcc->gtCondition;
6626+
size_t falseValue = static_cast<size_t>(falseOp->AsIntCon()->IconValue());
6627+
size_t trueValue = static_cast<size_t>(trueOp->AsIntCon()->IconValue());
6628+
6629+
if (falseValue > trueValue)
6630+
{
6631+
std::swap(falseValue, trueValue);
6632+
condition.Reverse();
6633+
}
6634+
6635+
LIR::Use use;
6636+
bool isUsed = BlockRange().TryGetUse(selcc, &use);
6637+
GenTree* result = nullptr;
6638+
6639+
if ((falseValue == 0) && (trueValue == SIZE_T_MAX))
6640+
{
6641+
result = comp->gtNewOperNode(GT_NEG, type, selcc);
6642+
BlockRange().InsertAfter(selcc, result);
6643+
}
6644+
else
6645+
{
6646+
size_t zeroOffset = 0;
6647+
6648+
if (falseValue != 0)
6649+
{
6650+
zeroOffset = falseValue;
6651+
falseValue = 0;
6652+
trueValue -= zeroOffset;
6653+
}
6654+
6655+
if (isPow2(trueValue) && ((zeroOffset == 0) || (genLog2(trueValue) <= 3)))
6656+
{
6657+
if (zeroOffset > 0)
6658+
{
6659+
if (trueValue == 1)
6660+
{
6661+
GenTree* offset = comp->gtNewIconNode(zeroOffset, type);
6662+
result = comp->gtNewOperNode(GT_ADD, type, selcc, offset);
6663+
BlockRange().InsertAfter(selcc, offset, result);
6664+
}
6665+
else
6666+
{
6667+
result =
6668+
new (comp, GT_LEA) GenTreeAddrMode(type, nullptr, selcc, static_cast<unsigned>(trueValue),
6669+
static_cast<unsigned>(zeroOffset));
6670+
BlockRange().InsertAfter(selcc, result);
6671+
}
6672+
}
6673+
else if (trueValue > 1)
6674+
{
6675+
GenTree* shiftBy = comp->gtNewIconNode(genLog2(trueValue), type);
6676+
result = comp->gtNewOperNode(GT_LSH, type, selcc, shiftBy);
6677+
BlockRange().InsertAfter(selcc, shiftBy, result);
6678+
}
6679+
else
6680+
{
6681+
result = selcc;
6682+
}
6683+
}
6684+
}
6685+
6686+
if (result != nullptr)
6687+
{
6688+
selcc->ChangeOper(GT_SETCC);
6689+
6690+
GenTreeCC* setcc = selcc->AsCC();
6691+
setcc->gtType = type;
6692+
setcc->gtCondition = condition;
6693+
6694+
BlockRange().Remove(falseOp);
6695+
BlockRange().Remove(trueOp);
6696+
6697+
if (isUsed && (result != selcc))
6698+
{
6699+
use.ReplaceWith(comp, result);
6700+
}
6701+
6702+
return selcc->gtNext;
6703+
}
6704+
}
6705+
66136706
// Put constants in the second operand, this appears to improve register allocation.
66146707

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

0 commit comments

Comments
 (0)