diff options
-rw-r--r-- | src/jit/codegenarmarch.cpp | 4 | ||||
-rw-r--r-- | src/jit/codegenlinear.h | 3 | ||||
-rw-r--r-- | src/jit/codegenxarch.cpp | 43 | ||||
-rw-r--r-- | src/jit/gentree.cpp | 12 | ||||
-rw-r--r-- | src/jit/gentree.h | 11 | ||||
-rw-r--r-- | src/jit/gtlist.h | 12 | ||||
-rw-r--r-- | src/jit/gtstructs.h | 2 | ||||
-rw-r--r-- | src/jit/lower.cpp | 2 | ||||
-rw-r--r-- | src/jit/lowerxarch.cpp | 5 | ||||
-rw-r--r-- | src/jit/lsra.cpp | 2 | ||||
-rw-r--r-- | src/jit/lsraxarch.cpp | 15 | ||||
-rw-r--r-- | src/jit/rationalize.cpp | 4 |
12 files changed, 86 insertions, 29 deletions
diff --git a/src/jit/codegenarmarch.cpp b/src/jit/codegenarmarch.cpp index 40fb746ed0..f7edec1bfc 100644 --- a/src/jit/codegenarmarch.cpp +++ b/src/jit/codegenarmarch.cpp @@ -240,7 +240,7 @@ void CodeGen::genCodeForTreeNode(GenTreePtr treeNode) #ifdef _TARGET_ARM_ case GT_JCC: - genCodeForJcc(treeNode->AsJumpCC()); + genCodeForJcc(treeNode->AsCC()); break; #endif // _TARGET_ARM_ @@ -2568,7 +2568,7 @@ void CodeGen::genCodeForJumpTrue(GenTreePtr tree) // Arguments: // tree - the node // -void CodeGen::genCodeForJcc(GenTreeJumpCC* tree) +void CodeGen::genCodeForJcc(GenTreeCC* tree) { assert(compiler->compCurBB->bbJumpKind == BBJ_COND); diff --git a/src/jit/codegenlinear.h b/src/jit/codegenlinear.h index ffcc1d6015..c91d2e76b0 100644 --- a/src/jit/codegenlinear.h +++ b/src/jit/codegenlinear.h @@ -172,7 +172,8 @@ void genCodeForLclFld(GenTreeLclFld* tree); void genCodeForStoreLclFld(GenTreeLclFld* tree); void genCodeForStoreLclVar(GenTreeLclVar* tree); void genCodeForReturnTrap(GenTreeOp* tree); -void genCodeForJcc(GenTreeJumpCC* tree); +void genCodeForJcc(GenTreeCC* tree); +void genCodeForSetcc(GenTreeCC* setcc); void genCodeForStoreInd(GenTreeStoreInd* tree); void genCodeForSwap(GenTreeOp* tree); void genCodeForCpObj(GenTreeObj* cpObjNode); diff --git a/src/jit/codegenxarch.cpp b/src/jit/codegenxarch.cpp index e64928e195..21da989ef1 100644 --- a/src/jit/codegenxarch.cpp +++ b/src/jit/codegenxarch.cpp @@ -1410,14 +1410,14 @@ void CodeGen::genReturn(GenTreePtr treeNode) } //------------------------------------------------------------------------ -// genCodeForCompare: Produce code for a GT_EQ/GT_NE/GT_LT/GT_LE/GT_GE/GT_GT/GT_TEST_EQ/GT_TEST_NE node. +// 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. // // Arguments: // tree - the node // void CodeGen::genCodeForCompare(GenTreeOp* tree) { - assert(tree->OperIs(GT_EQ, GT_NE, GT_LT, GT_LE, GT_GE, GT_GT, GT_TEST_EQ, GT_TEST_NE)); + assert(tree->OperIs(GT_EQ, GT_NE, GT_LT, GT_LE, GT_GE, GT_GT, GT_TEST_EQ, GT_TEST_NE, GT_CMP)); // TODO-XArch-CQ: Check if we can use the currently set flags. // TODO-XArch-CQ: Check for the case where we can simply transfer the carry bit to a register @@ -1520,7 +1520,7 @@ void CodeGen::genCodeForJumpTrue(GenTreePtr tree) // Arguments: // tree - the node // -void CodeGen::genCodeForJcc(GenTreeJumpCC* tree) +void CodeGen::genCodeForJcc(GenTreeCC* tree) { assert(compiler->compCurBB->bbJumpKind == BBJ_COND); @@ -1531,6 +1531,34 @@ void CodeGen::genCodeForJcc(GenTreeJumpCC* tree) } //------------------------------------------------------------------------ +// genCodeForSetcc: Generates a setcc instruction for a GT_SETCC node. +// +// Arguments: +// tree - the GT_SETCC node +// +// Assumptions: +// The condition represents an integer comparison. This code doesn't +// have the necessary logic to deal with floating point comparisons, +// in fact it doesn't even know if the comparison is integer or floating +// point because SETCC nodes do not have any operands. +// + +void CodeGen::genCodeForSetcc(GenTreeCC* setcc) +{ + regNumber dstReg = setcc->gtRegNum; + CompareKind compareKind = setcc->IsUnsigned() ? CK_UNSIGNED : CK_SIGNED; + emitJumpKind jumpKind = genJumpKindForOper(setcc->gtCondition, compareKind); + + assert(genIsValidIntReg(dstReg) && isByteReg(dstReg)); + // Make sure nobody is setting GTF_RELOP_NAN_UN on this node as it is ignored. + assert((setcc->gtFlags & GTF_RELOP_NAN_UN) == 0); + + inst_SET(jumpKind, dstReg); + inst_RV_RV(ins_Move_Extend(TYP_UBYTE, true), dstReg, dstReg, TYP_UBYTE, emitTypeSize(TYP_UBYTE)); + genProduceReg(setcc); +} + +//------------------------------------------------------------------------ // genCodeForReturnTrap: Produce code for a GT_RETURNTRAP node. // // Arguments: @@ -1771,6 +1799,7 @@ void CodeGen::genCodeForTreeNode(GenTreePtr treeNode) case GT_GT: case GT_TEST_EQ: case GT_TEST_NE: + case GT_CMP: genCodeForCompare(treeNode->AsOp()); break; @@ -1779,7 +1808,11 @@ void CodeGen::genCodeForTreeNode(GenTreePtr treeNode) break; case GT_JCC: - genCodeForJcc(treeNode->AsJumpCC()); + genCodeForJcc(treeNode->AsCC()); + break; + + case GT_SETCC: + genCodeForSetcc(treeNode->AsCC()); break; case GT_RETURNTRAP: @@ -6287,7 +6320,7 @@ void CodeGen::genCompareFloat(GenTreePtr treeNode) // None. void CodeGen::genCompareInt(GenTreePtr treeNode) { - assert(treeNode->OperIsCompare()); + assert(treeNode->OperIsCompare() || treeNode->OperIs(GT_CMP)); GenTreeOp* tree = treeNode->AsOp(); GenTreePtr op1 = tree->gtOp1; diff --git a/src/jit/gentree.cpp b/src/jit/gentree.cpp index 2f09590c01..551dcfc91e 100644 --- a/src/jit/gentree.cpp +++ b/src/jit/gentree.cpp @@ -366,7 +366,7 @@ void GenTree::InitNodeSize() static_assert_no_msg(sizeof(GenTreeLclVar) <= TREE_NODE_SZ_SMALL); static_assert_no_msg(sizeof(GenTreeLclFld) <= TREE_NODE_SZ_SMALL); static_assert_no_msg(sizeof(GenTreeRegVar) <= TREE_NODE_SZ_SMALL); - static_assert_no_msg(sizeof(GenTreeJumpCC) <= TREE_NODE_SZ_SMALL); + static_assert_no_msg(sizeof(GenTreeCC) <= TREE_NODE_SZ_SMALL); static_assert_no_msg(sizeof(GenTreeCast) <= TREE_NODE_SZ_LARGE); // *** large node static_assert_no_msg(sizeof(GenTreeBox) <= TREE_NODE_SZ_LARGE); // *** large node static_assert_no_msg(sizeof(GenTreeField) <= TREE_NODE_SZ_LARGE); // *** large node @@ -3447,10 +3447,10 @@ GenTreePtr Compiler::gtReverseCond(GenTree* tree) tree->gtFlags ^= GTF_RELOP_NAN_UN; } } - else if (tree->OperGet() == GT_JCC) + else if (tree->OperIs(GT_JCC, GT_SETCC)) { - GenTreeJumpCC* jcc = tree->AsJumpCC(); - jcc->gtCondition = GenTree::ReverseRelop(jcc->gtCondition); + GenTreeCC* cc = tree->AsCC(); + cc->gtCondition = GenTree::ReverseRelop(cc->gtCondition); } else { @@ -9200,6 +9200,7 @@ GenTreeUseEdgeIterator::GenTreeUseEdgeIterator(GenTree* node) case GT_MEMORYBARRIER: case GT_JMP: case GT_JCC: + case GT_SETCC: case GT_NO_OP: case GT_START_NONGC: case GT_PROF_HOOK: @@ -11182,7 +11183,8 @@ void Compiler::gtDispLeaf(GenTree* tree, IndentStack* indentStack) break; case GT_JCC: - printf(" cond=%s", GenTree::NodeName(tree->AsJumpCC()->gtCondition)); + case GT_SETCC: + printf(" cond=%s", GenTree::NodeName(tree->AsCC()->gtCondition)); break; default: diff --git a/src/jit/gentree.h b/src/jit/gentree.h index d99a05f3ff..65ee25aad1 100644 --- a/src/jit/gentree.h +++ b/src/jit/gentree.h @@ -4981,18 +4981,21 @@ struct GenTreeAllocObj final : public GenTreeUnOp #endif }; -struct GenTreeJumpCC final : public GenTree +// Represents a GT_JCC or GT_SETCC node. + +struct GenTreeCC final : public GenTree { genTreeOps gtCondition; // any relop - GenTreeJumpCC(genTreeOps condition) - : GenTree(GT_JCC, TYP_VOID DEBUGARG(/*largeNode*/ FALSE)), gtCondition(condition) + GenTreeCC(genTreeOps oper, genTreeOps condition, var_types type = TYP_VOID) + : GenTree(oper, type DEBUGARG(/*largeNode*/ FALSE)), gtCondition(condition) { + assert(OperIs(GT_JCC, GT_SETCC)); assert(OperIsCompare(condition)); } #if DEBUGGABLE_GENTREE - GenTreeJumpCC() : GenTree() + GenTreeCC() : GenTree() { } #endif // DEBUGGABLE_GENTREE diff --git a/src/jit/gtlist.h b/src/jit/gtlist.h index 5af2f5bb78..cba2d71a3b 100644 --- a/src/jit/gtlist.h +++ b/src/jit/gtlist.h @@ -214,11 +214,21 @@ GTNODE(SIMD , "simd" ,GenTreeSIMD ,0,GTK_BINOP|GTK_EX #endif // FEATURE_SIMD //----------------------------------------------------------------------------- +// LIR specific compare and conditional branch/set nodes: +//----------------------------------------------------------------------------- + +GTNODE(CMP , "cmp" ,GenTreeOp ,0,GTK_BINOP|GTK_NOVALUE) // Sets the condition flags according to the compare result. + // N.B. Not a relop, it does not produce a value and it cannot be reversed. +GTNODE(JCC , "jcc" ,GenTreeCC ,0,GTK_LEAF|GTK_NOVALUE) // Checks the condition flags and branch if the condition specified + // by GenTreeCC::gtCondition is true. +GTNODE(SETCC , "setcc" ,GenTreeCC ,0,GTK_LEAF) // Checks the condition flags and produces 1 if the condition specified + // by GenTreeCC::gtCondition is true and 0 otherwise. + +//----------------------------------------------------------------------------- // Other nodes that look like unary/binary operators: //----------------------------------------------------------------------------- GTNODE(JTRUE , "jmpTrue" ,GenTreeOp ,0,GTK_UNOP|GTK_NOVALUE) -GTNODE(JCC , "jcc" ,GenTreeJumpCC ,0,GTK_LEAF|GTK_NOVALUE) GTNODE(LIST , "<list>" ,GenTreeArgList ,0,GTK_BINOP|GTK_NOVALUE) GTNODE(FIELD_LIST , "<fldList>" ,GenTreeFieldList ,0,GTK_BINOP) // List of fields of a struct, when passed as an argument diff --git a/src/jit/gtstructs.h b/src/jit/gtstructs.h index c4a4f73e37..898aeec002 100644 --- a/src/jit/gtstructs.h +++ b/src/jit/gtstructs.h @@ -101,7 +101,7 @@ GTSTRUCT_1(PhysReg , GT_PHYSREG) GTSTRUCT_1(SIMD , GT_SIMD) #endif // FEATURE_SIMD GTSTRUCT_1(AllocObj , GT_ALLOCOBJ) -GTSTRUCT_1(JumpCC , GT_JCC) +GTSTRUCT_2(CC , GT_JCC, GT_SETCC) #if !defined(LEGACY_BACKEND) && defined(_TARGET_ARM_) GTSTRUCT_1(MulLong , GT_MUL_LONG) #endif diff --git a/src/jit/lower.cpp b/src/jit/lower.cpp index 3f3dbc101e..c043b03566 100644 --- a/src/jit/lower.cpp +++ b/src/jit/lower.cpp @@ -2217,7 +2217,7 @@ void Lowering::LowerCompare(GenTree* cmp) BasicBlock* newBlock2 = comp->fgSplitBlockAtEnd(newBlock); - GenTree* hiJcc = new (comp, GT_JCC) GenTreeJumpCC(hiCmpOper); + GenTree* hiJcc = new (comp, GT_JCC) GenTreeCC(GT_JCC, hiCmpOper); hiJcc->gtFlags = cmp->gtFlags; LIR::AsRange(newBlock).InsertAfter(nullptr, hiJcc); diff --git a/src/jit/lowerxarch.cpp b/src/jit/lowerxarch.cpp index f887a2a330..cda563479f 100644 --- a/src/jit/lowerxarch.cpp +++ b/src/jit/lowerxarch.cpp @@ -1012,7 +1012,7 @@ bool Lowering::isRMWRegOper(GenTreePtr tree) // For now, We assume that most binary operators are of the RMW form. assert(tree->OperIsBinary()); - if (tree->OperIsCompare()) + if (tree->OperIsCompare() || tree->OperIs(GT_CMP)) { return false; } @@ -1086,7 +1086,7 @@ bool Lowering::IsContainableImmed(GenTree* parentNode, GenTree* childNode) GenTree* Lowering::PreferredRegOptionalOperand(GenTree* tree) { assert(GenTree::OperIsBinary(tree->OperGet())); - assert(tree->OperIsCommutative() || tree->OperIsCompare()); + assert(tree->OperIsCommutative() || tree->OperIsCompare() || tree->OperIs(GT_CMP)); GenTree* op1 = tree->gtGetOp1(); GenTree* op2 = tree->gtGetOp2(); @@ -1161,7 +1161,6 @@ GenTree* Lowering::PreferredRegOptionalOperand(GenTree* tree) else { preferredOp = op1; - ; } } else if (op1->OperGet() == GT_LCL_VAR) diff --git a/src/jit/lsra.cpp b/src/jit/lsra.cpp index 1f86325fe3..03f383bda5 100644 --- a/src/jit/lsra.cpp +++ b/src/jit/lsra.cpp @@ -3419,7 +3419,7 @@ static int ComputeOperandDstCount(GenTree* operand) // If an operand has no destination registers but does have source registers, it must be a store // or a compare. assert(operand->OperIsStore() || operand->OperIsBlkOp() || operand->OperIsPutArgStk() || - operand->OperIsCompare() || operand->IsSIMDEqualityOrInequality()); + operand->OperIsCompare() || operand->OperIs(GT_CMP) || operand->IsSIMDEqualityOrInequality()); return 0; } else if (!operand->OperIsFieldListHead() && (operand->OperIsStore() || operand->TypeGet() == TYP_VOID)) diff --git a/src/jit/lsraxarch.cpp b/src/jit/lsraxarch.cpp index 56f1bd26d6..3fa85cf211 100644 --- a/src/jit/lsraxarch.cpp +++ b/src/jit/lsraxarch.cpp @@ -335,6 +335,14 @@ void Lowering::TreeNodeInfoInit(GenTree* tree) info->dstCount = 0; break; + case GT_SETCC: + info->srcCount = 0; + info->dstCount = 1; +#ifdef _TARGET_X86_ + info->setDstCandidates(m_lsra, RBM_BYTE_REGS); +#endif // _TARGET_X86_ + break; + case GT_JMP: info->srcCount = 0; info->dstCount = 0; @@ -523,6 +531,7 @@ void Lowering::TreeNodeInfoInit(GenTree* tree) case GT_GT: case GT_TEST_EQ: case GT_TEST_NE: + case GT_CMP: TreeNodeInfoInitCmp(tree); break; @@ -3026,12 +3035,12 @@ void Lowering::TreeNodeInfoInitIndir(GenTreePtr indirTree) // void Lowering::TreeNodeInfoInitCmp(GenTreePtr tree) { - assert(tree->OperIsCompare()); + assert(tree->OperIsCompare() || tree->OperIs(GT_CMP)); TreeNodeInfo* info = &(tree->gtLsraInfo); info->srcCount = 2; - info->dstCount = 1; + info->dstCount = tree->OperIs(GT_CMP) ? 0 : 1; #ifdef _TARGET_X86_ // If the compare is used by a jump, we just need to set the condition codes. If not, then we need @@ -3561,7 +3570,7 @@ bool Lowering::ExcludeNonByteableRegisters(GenTree* tree) { return true; } - else if (tree->OperIsCompare()) + else if (tree->OperIsCompare() || tree->OperIs(GT_CMP)) { GenTree* op1 = tree->gtGetOp1(); GenTree* op2 = tree->gtGetOp2(); diff --git a/src/jit/rationalize.cpp b/src/jit/rationalize.cpp index c0fb92486c..adf01f9e29 100644 --- a/src/jit/rationalize.cpp +++ b/src/jit/rationalize.cpp @@ -951,8 +951,8 @@ Compiler::fgWalkResult Rationalizer::RewriteNode(GenTree** useEdge, ArrayStack<G #endif // FEATURE_SIMD default: - // JCC nodes should not be present in HIR. - assert(node->OperGet() != GT_JCC); + // CMP, SETCC and JCC nodes should not be present in HIR. + assert(!node->OperIs(GT_CMP, GT_SETCC, GT_JCC)); break; } |