Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Compress operand kinds array and optimize OperIsLocal #63253

Merged
merged 8 commits into from
Jan 16, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 4 additions & 5 deletions src/coreclr/jit/assertionprop.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2189,7 +2189,7 @@ AssertionIndex Compiler::optCreateJtrueAssertions(GenTree* op1
AssertionInfo Compiler::optCreateJTrueBoundsAssertion(GenTree* tree)
{
GenTree* relop = tree->gtGetOp1();
if ((relop->OperKind() & GTK_RELOP) == 0)
if (!relop->OperIsCompare())
{
return NO_ASSERTION_INDEX;
}
Expand Down Expand Up @@ -2349,7 +2349,7 @@ AssertionInfo Compiler::optAssertionGenJtrue(GenTree* tree)
}

GenTree* relop = tree->AsOp()->gtOp1;
if ((relop->OperKind() & GTK_RELOP) == 0)
if (!relop->OperIsCompare())
{
return NO_ASSERTION_INDEX;
}
Expand Down Expand Up @@ -2392,8 +2392,7 @@ AssertionInfo Compiler::optAssertionGenJtrue(GenTree* tree)
ValueNum op1VN = vnStore->VNConservativeNormalValue(op1->gtVNPair);
ValueNum op2VN = vnStore->VNConservativeNormalValue(op2->gtVNPair);
// If op1 is lcl and op2 is const or lcl, create assertion.
if ((op1->gtOper == GT_LCL_VAR) &&
((op2->OperKind() & GTK_CONST) || (op2->gtOper == GT_LCL_VAR))) // Fix for Dev10 851483
if ((op1->gtOper == GT_LCL_VAR) && (op2->OperIsConst() || (op2->gtOper == GT_LCL_VAR))) // Fix for Dev10 851483
{
return optCreateJtrueAssertions(op1, op2, assertionKind);
}
Expand Down Expand Up @@ -3608,7 +3607,7 @@ AssertionIndex Compiler::optGlobalAssertionIsEqualOrNotEqualZero(ASSERT_VALARG_T

GenTree* Compiler::optAssertionProp_RelOp(ASSERT_VALARG_TP assertions, GenTree* tree, Statement* stmt)
{
assert(tree->OperKind() & GTK_RELOP);
assert(tree->OperIsCompare());

if (!optLocalAssertionProp)
{
Expand Down
4 changes: 2 additions & 2 deletions src/coreclr/jit/flowgraph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1269,7 +1269,7 @@ bool Compiler::fgCastNeeded(GenTree* tree, var_types toType)
// If tree is a relop and we need an 4-byte integer
// then we never need to insert a cast
//
if ((tree->OperKind() & GTK_RELOP) && (genActualType(toType) == TYP_INT))
if (tree->OperIsCompare() && (genActualType(toType) == TYP_INT))
{
return false;
}
Expand Down Expand Up @@ -3920,7 +3920,7 @@ void Compiler::fgSetTreeSeqHelper(GenTree* tree, bool isLIR)

/* Is this a leaf/constant node? */

if (kind & (GTK_CONST | GTK_LEAF))
if (kind & GTK_LEAF)
{
fgSetTreeSeqFinish(tree, isLIR);
return;
Expand Down
40 changes: 20 additions & 20 deletions src/coreclr/jit/gentree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

/*****************************************************************************/

const unsigned short GenTree::gtOperKindTable[] = {
const unsigned char GenTree::gtOperKindTable[] = {
#define GTNODE(en, st, cm, ok) (ok) + GTK_COMMUTE *cm,
#include "gtlist.h"
};
Expand Down Expand Up @@ -1316,7 +1316,7 @@ bool GenTree::Compare(GenTree* op1, GenTree* op2, bool swapOK)

/* Is this a constant node? */

if (kind & GTK_CONST)
if (op1->OperIsConst())
{
switch (oper)
{
Expand Down Expand Up @@ -1774,9 +1774,9 @@ unsigned Compiler::gtHashValue(GenTree* tree)

hash = genTreeHashAdd(hash, oper);

/* Is this a constant or leaf node? */
/* Is this a leaf node? */

if (kind & (GTK_CONST | GTK_LEAF))
if (kind & GTK_LEAF)
{
size_t add;

Expand Down Expand Up @@ -3219,9 +3219,9 @@ unsigned Compiler::gtSetEvalOrder(GenTree* tree)
costSz = -1;
#endif

/* Is this a constant or a leaf node? */
/* Is this a leaf node? */

if (kind & (GTK_LEAF | GTK_CONST))
if (kind & GTK_LEAF)
{
switch (oper)
{
Expand Down Expand Up @@ -4191,7 +4191,7 @@ unsigned Compiler::gtSetEvalOrder(GenTree* tree)
break;
}
}
else if (kind & GTK_RELOP)
else if (GenTree::OperIsCompare(oper))
{
/* Float compares remove both operands from the FP stack */
/* Also FP comparison uses EAX for flags */
Expand Down Expand Up @@ -4265,7 +4265,7 @@ unsigned Compiler::gtSetEvalOrder(GenTree* tree)
such cases, both sides have a level of 0. So encourage constants
to be evaluated last in such cases */

if ((level == 0) && (level == lvl2) && (op1->OperKind() & GTK_CONST) &&
if ((level == 0) && (level == lvl2) && op1->OperIsConst() &&
(tree->OperIsCommutative() || tree->OperIsCompare()))
{
lvl2++;
Expand Down Expand Up @@ -4325,7 +4325,7 @@ unsigned Compiler::gtSetEvalOrder(GenTree* tree)

// Try to force extra swapping when in the stress mode:
if (compStressCompile(STRESS_REVERSE_FLAG, 60) && ((tree->gtFlags & GTF_REVERSE_OPS) == 0) &&
((op2->OperKind() & GTK_CONST) == 0))
!op2->OperIsConst())
{
tryToSwap = true;
}
Expand Down Expand Up @@ -7182,9 +7182,9 @@ GenTree* Compiler::gtCloneExpr(
unsigned kind = tree->OperKind();
GenTree* copy;

/* Is this a constant or leaf node? */
/* Is this a leaf node? */

if (kind & (GTK_CONST | GTK_LEAF))
if (kind & GTK_LEAF)
{
switch (oper)
{
Expand Down Expand Up @@ -10063,7 +10063,7 @@ void Compiler::gtDispClassLayout(ClassLayout* layout, var_types type)
/*****************************************************************************/
void Compiler::gtDispConst(GenTree* tree)
{
assert(tree->OperKind() & GTK_CONST);
assert(tree->OperIsConst());

switch (tree->gtOper)
{
Expand Down Expand Up @@ -10274,7 +10274,7 @@ void Compiler::gtDispFieldSeq(FieldSeqNode* pfsn)

void Compiler::gtDispLeaf(GenTree* tree, IndentStack* indentStack)
{
if (tree->OperKind() & GTK_CONST)
if (tree->OperIsConst())
{
gtDispConst(tree);
return;
Expand Down Expand Up @@ -11590,7 +11590,7 @@ GenTree* Compiler::gtFoldExpr(GenTree* tree)

if ((kind & GTK_UNOP) && op1)
{
if (op1->OperKind() & GTK_CONST)
if (op1->OperIsConst())
{
return gtFoldExprConst(tree);
}
Expand All @@ -11603,12 +11603,12 @@ GenTree* Compiler::gtFoldExpr(GenTree* tree)

// The atomic operations are exempted here because they are never computable statically;
// one of their arguments is an address.
if (((op1->OperKind() & op2->OperKind()) & GTK_CONST) && !tree->OperIsAtomicOp())
if (op1->OperIsConst() && op2->OperIsConst() && !tree->OperIsAtomicOp())
{
/* both nodes are constants - fold the expression */
return gtFoldExprConst(tree);
}
else if ((op1->OperKind() | op2->OperKind()) & GTK_CONST)
else if (op1->OperIsConst() || op2->OperIsConst())
{
/* at least one is a constant - see if we have a
* special operator that can use only one constant
Expand Down Expand Up @@ -12360,14 +12360,14 @@ GenTree* Compiler::gtFoldExprSpecial(GenTree* tree)

case GT_DIV:
case GT_UDIV:
if ((op2 == cons) && (val == 1) && !(op1->OperKind() & GTK_CONST))
if ((op2 == cons) && (val == 1) && !op1->OperIsConst())
{
goto DONE_FOLD;
}
break;

case GT_SUB:
if ((op2 == cons) && (val == 0) && !(op1->OperKind() & GTK_CONST))
if ((op2 == cons) && (val == 0) && !op1->OperIsConst())
{
goto DONE_FOLD;
}
Expand Down Expand Up @@ -13984,7 +13984,7 @@ GenTree* Compiler::gtFoldExprConst(GenTree* tree)
{
JITDUMP("Double operator(s) is NaN\n");

if (tree->OperIsRelop())
if (tree->OperIsCompare())
{
if (tree->gtFlags & GTF_RELOP_NAN_UN)
{
Expand Down Expand Up @@ -15699,7 +15699,7 @@ bool GenTree::isContained() const
// these actually produce a register (the flags reg, we just don't model it)
// and are a separate instruction from the branch that consumes the result.
// They can only produce a result if the child is a SIMD equality comparison.
else if (OperKind() & GTK_RELOP)
else if (OperIsCompare())
{
assert(isMarkedContained == false);
}
Expand Down
104 changes: 38 additions & 66 deletions src/coreclr/jit/gentree.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,45 +82,25 @@ enum genTreeOps : BYTE
#endif
};

/*****************************************************************************
*
* The following enum defines a set of bit flags that can be used
* to classify expression tree nodes. Note that some operators will
* have more than one bit set, as follows:
*
* GTK_CONST implies GTK_LEAF
* GTK_RELOP implies GTK_BINOP
* GTK_LOGOP implies GTK_BINOP
*/

// The following enum defines a set of bit flags that can be used
// to classify expression tree nodes.
//
enum genTreeKinds
{
GTK_SPECIAL = 0x0000, // unclassified operator (special handling reqd)

GTK_CONST = 0x0001, // constant operator
GTK_LEAF = 0x0002, // leaf operator
GTK_UNOP = 0x0004, // unary operator
GTK_BINOP = 0x0008, // binary operator
GTK_RELOP = 0x0010, // comparison operator
GTK_LOGOP = 0x0020, // logical operator

GTK_KINDMASK = 0x007F, // operator kind mask

GTK_COMMUTE = 0x0080, // commutative operator

GTK_EXOP = 0x0100, // Indicates that an oper for a node type that extends GenTreeOp (or GenTreeUnOp)
// by adding non-node fields to unary or binary operator.

GTK_LOCAL = 0x0200, // is a local access (load, store, phi)
GTK_SPECIAL = 0x00, // special operator
GTK_LEAF = 0x01, // leaf operator
GTK_UNOP = 0x02, // unary operator
GTK_BINOP = 0x04, // binary operator

GTK_NOVALUE = 0x0400, // node does not produce a value
GTK_NOTLIR = 0x0800, // node is not allowed in LIR
GTK_KINDMASK = (GTK_SPECIAL | GTK_LEAF | GTK_UNOP | GTK_BINOP), // operator kind mask
GTK_SMPOP = (GTK_UNOP | GTK_BINOP),

GTK_NOCONTAIN = 0x1000, // this node is a value, but may not be contained

/* Define composite value(s) */

GTK_SMPOP = (GTK_UNOP | GTK_BINOP | GTK_RELOP | GTK_LOGOP)
GTK_COMMUTE = 0x08, // commutative operator
GTK_EXOP = 0x10, // Indicates that an oper for a node type that extends GenTreeOp (or GenTreeUnOp)
// by adding non-node fields to unary or binary operator.
GTK_NOVALUE = 0x20, // node does not produce a value
GTK_NOTLIR = 0x40, // node is not allowed in LIR
GTK_NOCONTAIN = 0x80, // this node is a value, but may not be contained
};

/*****************************************************************************/
Expand Down Expand Up @@ -686,6 +666,17 @@ inline GenTreeDebugFlags& operator &=(GenTreeDebugFlags& a, GenTreeDebugFlags b)

// clang-format on

constexpr bool OpersAreContiguous(genTreeOps firstOper, genTreeOps secondOper)
{
return (firstOper + 1) == secondOper;
}

template <typename... Opers>
constexpr bool OpersAreContiguous(genTreeOps firstOper, genTreeOps secondOper, Opers... otherOpers)
{
return OpersAreContiguous(firstOper, secondOper) && OpersAreContiguous(secondOper, otherOpers...);
}

#ifndef HOST_64BIT
#include <pshpack4.h>
#endif
Expand Down Expand Up @@ -1043,7 +1034,7 @@ struct GenTree
int gtUseNum; // use-ordered traversal within the function
#endif

static const unsigned short gtOperKindTable[];
static const unsigned char gtOperKindTable[];

static unsigned OperKind(unsigned gtOper)
{
Expand Down Expand Up @@ -1160,12 +1151,13 @@ struct GenTree

static bool OperIsConst(genTreeOps gtOper)
{
return (OperKind(gtOper) & GTK_CONST) != 0;
static_assert_no_msg(OpersAreContiguous(GT_CNS_INT, GT_CNS_LNG, GT_CNS_DBL, GT_CNS_STR));
return (GT_CNS_INT <= gtOper) && (gtOper <= GT_CNS_STR);
}

bool OperIsConst() const
{
return (OperKind(gtOper) & GTK_CONST) != 0;
return OperIsConst(gtOper);
}

static bool OperIsLeaf(genTreeOps gtOper)
Expand All @@ -1178,17 +1170,11 @@ struct GenTree
return (OperKind(gtOper) & GTK_LEAF) != 0;
}

static bool OperIsCompare(genTreeOps gtOper)
{
return (OperKind(gtOper) & GTK_RELOP) != 0;
}

static bool OperIsLocal(genTreeOps gtOper)
{
bool result = (OperKind(gtOper) & GTK_LOCAL) != 0;
assert(result == (gtOper == GT_LCL_VAR || gtOper == GT_PHI_ARG || gtOper == GT_LCL_FLD ||
gtOper == GT_STORE_LCL_VAR || gtOper == GT_STORE_LCL_FLD));
return result;
static_assert_no_msg(
OpersAreContiguous(GT_PHI_ARG, GT_LCL_VAR, GT_LCL_FLD, GT_STORE_LCL_VAR, GT_STORE_LCL_FLD));
return (GT_PHI_ARG <= gtOper) && (gtOper <= GT_STORE_LCL_FLD);
}

static bool OperIsLocalAddr(genTreeOps gtOper)
Expand Down Expand Up @@ -1364,19 +1350,15 @@ struct GenTree
return OperIsLocalRead(OperGet());
}

bool OperIsCompare() const
{
return (OperKind(gtOper) & GTK_RELOP) != 0;
}

static bool OperIsLogical(genTreeOps gtOper)
static bool OperIsCompare(genTreeOps gtOper)
{
return (OperKind(gtOper) & GTK_LOGOP) != 0;
static_assert_no_msg(OpersAreContiguous(GT_EQ, GT_NE, GT_LT, GT_LE, GT_GE, GT_GT, GT_TEST_EQ, GT_TEST_NE));
return (GT_EQ <= gtOper) && (gtOper <= GT_TEST_NE);
}

bool OperIsLogical() const
bool OperIsCompare() const
{
return (OperKind(gtOper) & GTK_LOGOP) != 0;
return OperIsCompare(OperGet());
}

static bool OperIsShift(genTreeOps gtOper)
Expand Down Expand Up @@ -1498,16 +1480,6 @@ struct GenTree
return OperIsSimple(gtOper);
}

static bool OperIsRelop(genTreeOps gtOper)
{
return (OperKind(gtOper) & GTK_RELOP) != 0;
}

bool OperIsRelop() const
{
return OperIsRelop(gtOper);
}

#ifdef FEATURE_SIMD
bool isCommutativeSIMDIntrinsic();
#else // !
Expand Down
Loading