Skip to content
2 changes: 1 addition & 1 deletion src/coreclr/jit/gentree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20082,7 +20082,7 @@ bool GenTree::SupportsSettingZeroFlag()
}
#endif
#elif defined(TARGET_ARM64)
if (OperIs(GT_AND, GT_AND_NOT))
if (OperIs(GT_AND, GT_AND_NOT, GT_NEG))
{
return true;
}
Expand Down
77 changes: 41 additions & 36 deletions src/coreclr/jit/lower.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4358,6 +4358,26 @@ GenTree* Lowering::OptimizeConstCompare(GenTree* cmp)
}
}

// Optimize EQ/NE(op_that_sets_zf, 0) into op_that_sets_zf with GTF_SET_FLAGS + SETCC.
LIR::Use use;
if (cmp->OperIs(GT_EQ, GT_NE) && op2->IsIntegralConst(0) && op1->SupportsSettingZeroFlag() &&
BlockRange().TryGetUse(cmp, &use))
{
op1->gtFlags |= GTF_SET_FLAGS;
op1->SetUnusedValue();

GenTree* next = cmp->gtNext;
BlockRange().Remove(cmp);
BlockRange().Remove(op2);

GenCondition cmpCondition = GenCondition::FromRelop(cmp);
GenTreeCC* setcc = comp->gtNewCC(GT_SETCC, cmp->TypeGet(), cmpCondition);
BlockRange().InsertAfter(op1, setcc);

use.ReplaceWith(setcc);
return next;
}

return cmp;
}

Expand Down Expand Up @@ -4622,50 +4642,35 @@ bool Lowering::TryLowerConditionToFlagsNode(GenTree* parent, GenTree* condition,
}
#endif

// Optimize EQ/NE(op_that_sets_zf, 0) into op_that_sets_zf with GTF_SET_FLAGS.
if (optimizing && relop->OperIs(GT_EQ, GT_NE) && relopOp2->IsIntegralConst(0) &&
relopOp1->SupportsSettingZeroFlag() && IsInvariantInRange(relopOp1, parent))
{
relopOp1->gtFlags |= GTF_SET_FLAGS;
relopOp1->SetUnusedValue();
relop->gtType = TYP_VOID;
relop->gtFlags |= GTF_SET_FLAGS;

BlockRange().Remove(relopOp1);
BlockRange().InsertBefore(parent, relopOp1);
BlockRange().Remove(relop);
BlockRange().Remove(relopOp2);
}
else
if (relop->OperIs(GT_EQ, GT_NE, GT_LT, GT_LE, GT_GE, GT_GT))
{
relop->gtType = TYP_VOID;
relop->gtFlags |= GTF_SET_FLAGS;
relop->SetOper(GT_CMP);

if (relop->OperIs(GT_EQ, GT_NE, GT_LT, GT_LE, GT_GE, GT_GT))
if (cond->PreferSwap())
{
relop->SetOper(GT_CMP);

if (cond->PreferSwap())
{
std::swap(relop->gtOp1, relop->gtOp2);
*cond = GenCondition::Swap(*cond);
}
std::swap(relop->gtOp1, relop->gtOp2);
*cond = GenCondition::Swap(*cond);
}
}
#ifdef TARGET_XARCH
else if (relop->OperIs(GT_BITTEST_EQ, GT_BITTEST_NE))
{
relop->SetOper(GT_BT);
}
else if (relop->OperIs(GT_BITTEST_EQ, GT_BITTEST_NE))
{
relop->SetOper(GT_BT);
}
#endif
else
{
assert(relop->OperIs(GT_TEST_EQ, GT_TEST_NE));
relop->SetOper(GT_TEST);
}
else
{
assert(relop->OperIs(GT_TEST_EQ, GT_TEST_NE));
relop->SetOper(GT_TEST);
}

if (relop->gtNext != parent)
{
BlockRange().Remove(relop);
BlockRange().InsertBefore(parent, relop);
}
if (relop->gtNext != parent)
{
BlockRange().Remove(relop);
BlockRange().InsertBefore(parent, relop);
}

return true;
Expand Down
53 changes: 53 additions & 0 deletions src/tests/JIT/opt/InstructionCombining/Add.cs
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,26 @@ public static int CheckAdd()
fail = true;
}

if (!AddsSingleLine(-5, 5))
{
fail = true;
}

if (!AddsSingleLineLSL(-0x70, 0x7))
{
fail = true;
}

if (AddsBinOp(-5, 5, 2, -2) != 1)
{
fail = true;
}

if (!AddsBinOpSingleLine(-5, 5, 4, -2))
{
fail = true;
}

if (AddExtendedB(0, 0x101) != 1)
{
fail = true;
Expand Down Expand Up @@ -283,5 +303,38 @@ static long AddsLargeShift64Bit(long a, long b)
}
return -1;
}

[MethodImpl(MethodImplOptions.NoInlining)]
static bool AddsSingleLine(int a, int b)
{
//ARM64-FULL-LINE: adds {{w[0-9]+}}, {{w[0-9]+}}, {{w[0-9]+}}
return a + b == 0;
}

[MethodImpl(MethodImplOptions.NoInlining)]
static bool AddsSingleLineLSL(int a, int b)
{
//ARM64-FULL-LINE: adds {{w[0-9]+}}, {{w[0-9]+}}, {{w[0-9]+}}, LSL #4
return a + (b<<4) == 0;
}

[MethodImpl(MethodImplOptions.NoInlining)]
static int AddsBinOp(int a, int b, int c, int d)
{
//ARM64-FULL-LINE: adds {{w[0-9]+}}, {{w[0-9]+}}, {{w[0-9]+}}
//ARM64-FULL-LINE: adds {{w[0-9]+}}, {{w[0-9]+}}, {{w[0-9]+}}
if ((a + b == 0) == (c + d == 0)) {
return 1;
}
return -1;
}

[MethodImpl(MethodImplOptions.NoInlining)]
static bool AddsBinOpSingleLine(int a, int b, int c, int d)
{
//ARM64-FULL-LINE: adds {{w[0-9]+}}, {{w[0-9]+}}, {{w[0-9]+}}
//ARM64-FULL-LINE: adds {{w[0-9]+}}, {{w[0-9]+}}, {{w[0-9]+}}
return (a + b == 0) | (c + d == 0);
}
}
}
53 changes: 53 additions & 0 deletions src/tests/JIT/opt/InstructionCombining/And.cs
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,26 @@ public static int CheckAnd()
fail = true;
}

if (!AndsSingleLine(6, 10))
{
fail = true;
}

if (!AndsSingleLineLSR(0xB00, 8))
{
fail = true;
}

if (AndsBinOp(4, 1, 0x3000, 4) != 1)
{
fail = true;
}

if (!AndsBinOpSingleLine(1, 2, 4, 12))
{
fail = true;
}

if (fail)
{
return 101;
Expand Down Expand Up @@ -211,5 +231,38 @@ static int AndsLargeShift64Bit(ulong a, ulong b)
}
return -1;
}

[MethodImpl(MethodImplOptions.NoInlining)]
static bool AndsSingleLine(uint a, uint b)
{
//ARM64-FULL-LINE: tst {{w[0-9]+}}, {{w[0-9]+}}
return (a & b) != 0;
}

[MethodImpl(MethodImplOptions.NoInlining)]
static bool AndsSingleLineLSR(uint a, uint b)
{
//ARM64-FULL-LINE: tst {{w[0-9]+}}, {{w[0-9]+}}, LSR #8
return ((a>>8) & b) != 0;
}

[MethodImpl(MethodImplOptions.NoInlining)]
static int AndsBinOp(uint a, uint b, uint c, uint d)
{
//ARM64-FULL-LINE: tst {{w[0-9]+}}, {{w[0-9]+}}, LSL #2
//ARM64-FULL-LINE: tst {{w[0-9]+}}, {{w[0-9]+}}, LSR #10
if (((a & (b<<2)) == 0) == (((c>>10) & d) == 0)) {
return 1;
}
return -1;
}

[MethodImpl(MethodImplOptions.NoInlining)]
static bool AndsBinOpSingleLine(uint a, uint b, uint c, uint d)
{
//ARM64-FULL-LINE: tst {{w[0-9]+}}, {{w[0-9]+}}
//ARM64-FULL-LINE: tst {{w[0-9]+}}, {{w[0-9]+}}
return ((a & b) == 0) | ((c & d) == 0);
}
}
}
53 changes: 53 additions & 0 deletions src/tests/JIT/opt/InstructionCombining/BitwiseClearShift.cs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,26 @@ public static int CheckBitwiseClearShift()
fail = true;
}

if (!BicsSingleLine(0x22446688, 0x22446688))
{
fail = true;
}

if (!BicsSingleLineLSL(0xABC, 0xFFFEA87F))
{
fail = true;
}

if (BicsBinOp(0xFF012FFF, 0xFED, 0xFFDDBB99, 0xFF002244) != 1)
{
fail = true;
}

if (!BicsBinOpSingleLine(0x66665555, 0x9999AAAA, 0xFFFFFFFD, 0x2))
{
fail = true;
}

if (fail)
{
return 101;
Expand Down Expand Up @@ -213,5 +233,38 @@ static int BicsLargeShift64Bit(ulong a, ulong b)
}
return 1;
}

[MethodImpl(MethodImplOptions.NoInlining)]
static bool BicsSingleLine(uint a, uint b)
{
//ARM64-FULL-LINE: bics {{w[0-9]+}}, {{w[0-9]+}}, {{w[0-9]+}}
return (a & ~b) == 0;
}

[MethodImpl(MethodImplOptions.NoInlining)]
static bool BicsSingleLineLSL(uint a, uint b)
{
//ARM64-FULL-LINE: bics {{w[0-9]+}}, {{w[0-9]+}}, {{w[0-9]+}}, LSL #5
return (~(a<<5) & b) != 0;
}

[MethodImpl(MethodImplOptions.NoInlining)]
static int BicsBinOp(uint a, uint b, uint c, uint d)
{
//ARM64-FULL-LINE: bics {{w[0-9]+}}, {{w[0-9]+}}, {{w[0-9]+}}, LSR #8
//ARM64-FULL-LINE: bics {{w[0-9]+}}, {{w[0-9]+}}, {{w[0-9]+}}, LSL #12
if (((a & ~(b<<12)) == 0) == ((~(c>>8) & d) == 0)) {
return 1;
}
return -1;
}

[MethodImpl(MethodImplOptions.NoInlining)]
static bool BicsBinOpSingleLine(uint a, uint b, uint c, uint d)
{
//ARM64-FULL-LINE: bics {{w[0-9]+}}, {{w[0-9]+}}, {{w[0-9]+}}
//ARM64-FULL-LINE: bics {{w[0-9]+}}, {{w[0-9]+}}, {{w[0-9]+}}
return ((~a & b) != 0) & ((c & ~d) != 0);
}
}
}
Loading
Loading