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

Commit 4843262

Browse files
committed
Support GT_TEST_EQ/NE and GT_JCC
1 parent f291f5c commit 4843262

File tree

9 files changed

+81
-23
lines changed

9 files changed

+81
-23
lines changed

src/jit/codegenxarch.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1281,14 +1281,14 @@ void CodeGen::genFloatReturn(GenTree* treeNode)
12811281
#endif // _TARGET_X86_
12821282

12831283
//------------------------------------------------------------------------
1284-
// genCodeForCompare: Produce code for a GT_EQ/GT_NE/GT_LT/GT_LE/GT_GE/GT_GT/GT_TEST_EQ/GT_TEST_NE/GT_CMP node.
1284+
// genCodeForCompare: Produce code for a relop/GT_CMP/GT_TEST node.
12851285
//
12861286
// Arguments:
12871287
// tree - the node
12881288
//
12891289
void CodeGen::genCodeForCompare(GenTreeOp* tree)
12901290
{
1291-
assert(tree->OperIs(GT_EQ, GT_NE, GT_LT, GT_LE, GT_GE, GT_GT, GT_TEST_EQ, GT_TEST_NE, GT_CMP));
1291+
assert(tree->OperIsCompare() || tree->OperIs(GT_CMP, GT_TEST));
12921292

12931293
// TODO-XArch-CQ: Check if we can use the currently set flags.
12941294
// TODO-XArch-CQ: Check for the case where we can simply transfer the carry bit to a register
@@ -1799,6 +1799,7 @@ void CodeGen::genCodeForTreeNode(GenTree* treeNode)
17991799
case GT_TEST_EQ:
18001800
case GT_TEST_NE:
18011801
case GT_CMP:
1802+
case GT_TEST:
18021803
genCodeForCompare(treeNode->AsOp());
18031804
break;
18041805

@@ -5962,7 +5963,7 @@ void CodeGen::genCompareFloat(GenTree* treeNode)
59625963
// None.
59635964
void CodeGen::genCompareInt(GenTree* treeNode)
59645965
{
5965-
assert(treeNode->OperIsCompare() || treeNode->OperIs(GT_CMP));
5966+
assert(treeNode->OperIsCompare() || treeNode->OperIs(GT_CMP, GT_TEST));
59665967

59675968
GenTreeOp* tree = treeNode->AsOp();
59685969
GenTree* op1 = tree->gtOp1;
@@ -5979,7 +5980,7 @@ void CodeGen::genCompareInt(GenTree* treeNode)
59795980
instruction ins;
59805981
var_types type = TYP_UNKNOWN;
59815982

5982-
if (tree->OperIs(GT_TEST_EQ, GT_TEST_NE))
5983+
if (tree->OperIs(GT_TEST_EQ, GT_TEST_NE, GT_TEST))
59835984
{
59845985
ins = INS_test;
59855986

src/jit/gentree.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5797,6 +5797,13 @@ struct GenCondition
57975797
}
57985798
}
57995799

5800+
static genTreeOps LowerRelopOper(genTreeOps oper)
5801+
{
5802+
assert(GenTree::OperIsCompare(oper));
5803+
5804+
return ((oper == GT_TEST_EQ) || (oper == GT_TEST_NE)) ? GT_TEST : GT_CMP;
5805+
}
5806+
58005807
static GenCondition FromFloatRelop(GenTree* relop)
58015808
{
58025809
assert(varTypeIsFloating(relop->gtGetOp1()) && varTypeIsFloating(relop->gtGetOp2()));

src/jit/gtlist.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,8 @@ GTNODE(HWIntrinsic , GenTreeHWIntrinsic ,0,GTK_BINOP|GTK_EXOP)
210210

211211
GTNODE(CMP , GenTreeOp ,0,GTK_BINOP|GTK_NOVALUE) // Sets the condition flags according to the compare result.
212212
// N.B. Not a relop, it does not produce a value and it cannot be reversed.
213+
GTNODE(TEST , GenTreeOp ,0,GTK_BINOP|GTK_NOVALUE) // Sets the condition flags according to the test result.
214+
// N.B. Not a relop, it does not produce a value and it cannot be reversed.
213215
GTNODE(JCMP , GenTreeOp ,0,GTK_BINOP|GTK_NOVALUE) // Makes a comparison and jump if the condition specified. Does not set flags
214216
GTNODE(JCC , GenTreeCC ,0,GTK_LEAF|GTK_NOVALUE) // Checks the condition flags and branch if the condition specified
215217
// by GenTreeCC::gtCondition is true.

src/jit/lower.cpp

Lines changed: 59 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,9 @@ GenTree* Lowering::LowerNode(GenTree* node)
181181
case GT_JTRUE:
182182
return LowerJTrue(node->AsOp());
183183

184+
case GT_JCC:
185+
return LowerJCC(node->AsCC());
186+
184187
case GT_SELCC:
185188
return LowerSelCC(node->AsOpCC());
186189

@@ -3358,8 +3361,8 @@ class IfConversion
33583361

33593362
GenTreeOpCC* TryIfConversion(GenTreeOp* relop, GenTree* jtrue)
33603363
{
3361-
assert(relop->OperIsCompare());
3362-
assert(jtrue->OperIs(GT_JTRUE));
3364+
assert(relop->OperIsCompare() || (relop->gtFlags & GTF_SET_FLAGS));
3365+
assert(jtrue->OperIs(GT_JTRUE, GT_JCC));
33633366

33643367
HammockKind kind = MakeHammock();
33653368

@@ -3372,18 +3375,28 @@ class IfConversion
33723375
return nullptr;
33733376
}
33743377

3375-
GenCondition condition = GenCondition::FromRelop(relop);
3376-
condition = GenCondition::Reverse(condition);
3378+
GenCondition condition;
3379+
3380+
if (relop->OperIsCompare())
3381+
{
3382+
condition = GenCondition::FromRelop(relop);
3383+
relop->ChangeOper(GenCondition::LowerRelopOper(relop->OperGet()));
3384+
relop->gtType = TYP_VOID;
3385+
relop->gtFlags |= GTF_SET_FLAGS;
3386+
}
3387+
else
3388+
{
3389+
condition = jtrue->AsCC()->gtCondition;
3390+
}
33773391

3378-
relop->ChangeOper(GT_CMP);
3379-
relop->gtType = TYP_VOID;
33803392
jtrue->ChangeOper(GT_SELCC);
3393+
jtrue->gtFlags |= GTF_USE_FLAGS;
33813394
GenTreeOpCC* selcc = jtrue->AsOpCC();
33823395

33833396
GenTree* trueSrc = summary.CloneOpSrc(m_comp, selcc);
33843397
GenTree* falseSrc = summary.CloneOpAsLclVar(m_comp, selcc);
33853398

3386-
selcc->gtCondition = condition;
3399+
selcc->gtCondition = GenCondition::Reverse(condition);
33873400
selcc->gtConditionDef = relop;
33883401
selcc->gtType = falseSrc->TypeGet();
33893402
selcc->gtOp1 = falseSrc;
@@ -3413,11 +3426,23 @@ class IfConversion
34133426
return nullptr;
34143427
}
34153428

3416-
GenCondition condition = GenCondition::FromRelop(relop);
3429+
GenCondition condition;
3430+
3431+
if (relop->OperIsCompare())
3432+
{
3433+
condition = GenCondition::FromRelop(relop);
3434+
3435+
relop->ChangeOper(GenCondition::LowerRelopOper(relop->OperGet()));
3436+
relop->gtType = TYP_VOID;
3437+
relop->gtFlags |= GTF_SET_FLAGS;
3438+
}
3439+
else
3440+
{
3441+
condition = jtrue->AsCC()->gtCondition;
3442+
}
34173443

3418-
relop->ChangeOper(GT_CMP);
3419-
relop->gtType = TYP_VOID;
34203444
jtrue->ChangeOper(GT_SELCC);
3445+
jtrue->gtFlags |= GTF_USE_FLAGS;
34213446
GenTreeOpCC* selcc = jtrue->AsOpCC();
34223447

34233448
falseSummary.CloneCopies(m_comp, selcc);
@@ -3500,7 +3525,7 @@ GenTree* Lowering::LowerJTrue(GenTreeOp* jtrue)
35003525

35013526
#ifdef _TARGET_AMD64_
35023527
GenTreeOp* relop = jtrue->gtGetOp1()->AsOp();
3503-
if (!relop->OperIs(GT_TEST_EQ, GT_TEST_NE))
3528+
// if (!relop->OperIs(GT_TEST_NE, GT_TEST_EQ))
35043529
{
35053530
IfConversion ifConversion(comp, m_block);
35063531
GenTreeOpCC* selcc = ifConversion.TryIfConversion(relop, jtrue);
@@ -3513,14 +3538,14 @@ GenTree* Lowering::LowerJTrue(GenTreeOp* jtrue)
35133538
{
35143539
// Prefer FGT and FGE to FLT and FLE, they generate a single CMOV.
35153540
std::swap(relop->gtOp1, relop->gtOp2);
3516-
selcc->gtCondition.Swap();
3541+
selcc->gtCondition = GenCondition::Swap(selcc->gtCondition);
35173542
}
35183543
else if (selcc->gtCondition.Is(GenCondition::FEQ))
35193544
{
35203545
// Prefer FNEU to FEQ, FEQ requires a branch for the unordered case
35213546
// but FNEU can be implemented with 2 CMOVs.
35223547
std::swap(selcc->gtOp1, selcc->gtOp2);
3523-
selcc->gtCondition.Reverse();
3548+
selcc->gtCondition = GenCondition::Reverse(selcc->gtCondition);
35243549
}
35253550

35263551
// Floating point CMP has different containment rules
@@ -3540,6 +3565,26 @@ GenTree* Lowering::LowerJTrue(GenTreeOp* jtrue)
35403565
return nullptr;
35413566
}
35423567

3568+
GenTree* Lowering::LowerJCC(GenTreeCC* jcc)
3569+
{
3570+
#ifdef _TARGET_AMD64_
3571+
GenTree* relop = jcc->gtPrev;
3572+
if ((relop->gtFlags & GTF_SET_FLAGS) != 0)
3573+
{
3574+
IfConversion ifConversion(comp, m_block);
3575+
GenTreeOpCC* selcc = ifConversion.TryIfConversion(relop->AsOp(), jcc);
3576+
3577+
if (selcc != nullptr)
3578+
{
3579+
return selcc;
3580+
}
3581+
}
3582+
#endif
3583+
3584+
assert(jcc->gtNext == nullptr);
3585+
return nullptr;
3586+
}
3587+
35433588
// Lower "jmp <method>" tail call to insert PInvoke method epilog if required.
35443589
void Lowering::LowerJmpMethod(GenTree* jmp)
35453590
{
@@ -6153,6 +6198,7 @@ void Lowering::ContainCheckNode(GenTree* node)
61536198
case GT_TEST_EQ:
61546199
case GT_TEST_NE:
61556200
case GT_CMP:
6201+
case GT_TEST:
61566202
case GT_JCMP:
61576203
ContainCheckCompare(node->AsOp());
61586204
break;

src/jit/lower.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ class Lowering : public Phase
130130
GenTree* OptimizeConstCompare(GenTree* cmp);
131131
GenTree* LowerCompare(GenTree* cmp);
132132
GenTree* LowerJTrue(GenTreeOp* jtrue);
133+
GenTree* LowerJCC(GenTreeCC* jcc);
133134
void LowerJmpMethod(GenTree* jmp);
134135
void LowerRet(GenTree* ret);
135136
GenTree* LowerDelegateInvoke(GenTreeCall* call);

src/jit/lowerxarch.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1281,7 +1281,7 @@ bool Lowering::IsContainableImmed(GenTree* parentNode, GenTree* childNode)
12811281
GenTree* Lowering::PreferredRegOptionalOperand(GenTree* tree)
12821282
{
12831283
assert(GenTree::OperIsBinary(tree->OperGet()));
1284-
assert(tree->OperIsCommutative() || tree->OperIsCompare() || tree->OperIs(GT_CMP));
1284+
assert(tree->OperIsCommutative() || tree->OperIsCompare() || tree->OperIs(GT_CMP, GT_TEST));
12851285

12861286
GenTree* op1 = tree->gtGetOp1();
12871287
GenTree* op2 = tree->gtGetOp2();
@@ -1873,7 +1873,7 @@ void Lowering::ContainCheckCast(GenTreeCast* node)
18731873
//
18741874
void Lowering::ContainCheckCompare(GenTreeOp* cmp)
18751875
{
1876-
assert(cmp->OperIsCompare() || cmp->OperIs(GT_CMP));
1876+
assert(cmp->OperIsCompare() || cmp->OperIs(GT_CMP, GT_TEST));
18771877

18781878
GenTree* op1 = cmp->gtOp.gtOp1;
18791879
GenTree* op2 = cmp->gtOp.gtOp2;

src/jit/lsrabuild.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1444,7 +1444,7 @@ int LinearScan::ComputeOperandDstCount(GenTree* operand)
14441444
// Stores and void-typed operands may be encountered when processing call nodes, which contain
14451445
// pointers to argument setup stores.
14461446
assert(operand->OperIsStore() || operand->OperIsBlkOp() || operand->OperIsPutArgStk() ||
1447-
operand->OperIsCompare() || operand->OperIs(GT_CMP) || operand->IsSIMDEqualityOrInequality() ||
1447+
operand->OperIsCompare() || operand->OperIs(GT_CMP, GT_TEST) || operand->IsSIMDEqualityOrInequality() ||
14481448
operand->TypeGet() == TYP_VOID);
14491449
return 0;
14501450
}
@@ -3260,7 +3260,7 @@ int LinearScan::BuildGCWriteBarrier(GenTree* tree)
32603260
//
32613261
int LinearScan::BuildCmp(GenTree* tree)
32623262
{
3263-
assert(tree->OperIsCompare() || tree->OperIs(GT_CMP) || tree->OperIs(GT_JCMP));
3263+
assert(tree->OperIsCompare() || tree->OperIs(GT_CMP, GT_TEST, GT_JCMP));
32643264
regMaskTP dstCandidates = RBM_NONE;
32653265
regMaskTP op1Candidates = RBM_NONE;
32663266
regMaskTP op2Candidates = RBM_NONE;

src/jit/lsraxarch.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -430,6 +430,7 @@ int LinearScan::BuildNode(GenTree* tree)
430430
case GT_TEST_EQ:
431431
case GT_TEST_NE:
432432
case GT_CMP:
433+
case GT_TEST:
433434
srcCount = BuildCmp(tree);
434435
break;
435436

@@ -748,7 +749,7 @@ bool LinearScan::isRMWRegOper(GenTree* tree)
748749
// For now, We assume that most binary operators are of the RMW form.
749750
assert(tree->OperIsBinary());
750751

751-
if (tree->OperIsCompare() || tree->OperIs(GT_CMP) || tree->OperIs(GT_BT))
752+
if (tree->OperIsCompare() || tree->OperIs(GT_CMP, GT_TEST, GT_BT))
752753
{
753754
return false;
754755
}

src/jit/rationalize.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -850,7 +850,7 @@ Compiler::fgWalkResult Rationalizer::RewriteNode(GenTree** useEdge, ArrayStack<G
850850

851851
default:
852852
// These nodes should not be present in HIR.
853-
assert(!node->OperIs(GT_CMP, GT_SETCC, GT_JCC, GT_JCMP, GT_LOCKADD));
853+
assert(!node->OperIs(GT_BT, GT_CMP, GT_TEST, GT_SETCC, GT_JCC, GT_JCMP, GT_LOCKADD));
854854
break;
855855
}
856856

0 commit comments

Comments
 (0)