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

Introduce GenTreeDebugOperKind #64498

Merged
merged 6 commits into from
Feb 11, 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
5 changes: 0 additions & 5 deletions src/coreclr/jit/assertionprop.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5599,11 +5599,6 @@ Compiler::fgWalkResult Compiler::optVNConstantPropCurStmt(BasicBlock* block, Sta
case GT_INTRINSIC:
break;

case GT_INC_SATURATE:
case GT_MULHI:
assert(false && "Unexpected GT_INC_SATURATE/GT_MULHI node encountered before lowering");
break;

case GT_JTRUE:
break;

Expand Down
6 changes: 3 additions & 3 deletions src/coreclr/jit/fgstmt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -511,9 +511,9 @@ void Compiler::fgRemoveStmt(BasicBlock* block, Statement* stmt DEBUGARG(bool isU
}

/******************************************************************************/
// Returns true if the operator is involved in control-flow
// TODO-Cleanup: Move this into genTreeKinds in genTree.h

// Returns true if the operator is involved in control-flow.
// TODO-Cleanup: Make this a GenTreeOperKind.
//
inline bool OperIsControlFlow(genTreeOps oper)
{
switch (oper)
Expand Down
24 changes: 17 additions & 7 deletions src/coreclr/jit/gentree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,17 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
/*****************************************************************************/

const unsigned char GenTree::gtOperKindTable[] = {
#define GTNODE(en, st, cm, ok) (ok) + GTK_COMMUTE *cm,
#define GTNODE(en, st, cm, ok) ((ok)&GTK_MASK) + GTK_COMMUTE *cm,
#include "gtlist.h"
};

#ifdef DEBUG
const GenTreeDebugOperKind GenTree::gtDebugOperKindTable[] = {
#define GTNODE(en, st, cm, ok) static_cast<GenTreeDebugOperKind>((ok)&DBK_MASK),
#include "gtlist.h"
};
#endif // DEBUG

/*****************************************************************************
*
* The types of different GenTree nodes
Expand Down Expand Up @@ -15592,29 +15599,32 @@ unsigned GenTree::IsLclVarUpdateTree(GenTree** pOtherTree, genTreeOps* pOper)
return lclNum;
}

#ifdef DEBUG
//------------------------------------------------------------------------
// canBeContained: check whether this tree node may be a subcomponent of its parent for purposes
// of code generation.
//
// Return value: returns true if it is possible to contain this node and false otherwise.
// Return Value:
// True if it is possible to contain this node and false otherwise.
//
bool GenTree::canBeContained() const
{
assert(IsLIR());
assert(OperIsLIR());

if (gtHasReg())
{
return false;
}

// It is not possible for nodes that do not produce values or that are not containable values
// to be contained.
if (((OperKind() & (GTK_NOVALUE | GTK_NOCONTAIN)) != 0) || (OperIsHWIntrinsic() && !isContainableHWIntrinsic()))
// It is not possible for nodes that do not produce values or that are not containable values to be contained.
if (!IsValue() || ((DebugOperKind() & DBK_NOCONTAIN) != 0) || (OperIsHWIntrinsic() && !isContainableHWIntrinsic()))
{
return false;
}

return true;
}
#endif // DEBUG

//------------------------------------------------------------------------
// isContained: check whether this tree node is a subcomponent of its parent for codegen purposes
Expand All @@ -15631,7 +15641,7 @@ bool GenTree::canBeContained() const
//
bool GenTree::isContained() const
{
assert(IsLIR());
assert(OperIsLIR());
const bool isMarkedContained = ((gtFlags & GTF_CONTAINED) != 0);

#ifdef DEBUG
Expand Down
86 changes: 51 additions & 35 deletions src/coreclr/jit/gentree.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ enum genTreeOps : BYTE
// The following enum defines a set of bit flags that can be used
// to classify expression tree nodes.
//
enum genTreeKinds
enum GenTreeOperKind
{
GTK_SPECIAL = 0x00, // special operator
GTK_LEAF = 0x01, // leaf operator
Expand All @@ -95,12 +95,28 @@ enum genTreeKinds
GTK_KINDMASK = (GTK_SPECIAL | GTK_LEAF | GTK_UNOP | GTK_BINOP), // operator kind mask
GTK_SMPOP = (GTK_UNOP | GTK_BINOP),

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
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_MASK = 0xFF
};

// The following enum defines a set of bit flags that describe opers for the purposes
// of DEBUG-only checks. This is separate from the above "GenTreeOperKind"s to avoid
// making the table for those larger in Release builds. However, it resides in the same
// "namespace" and so all values here must be distinct from those in "GenTreeOperKind".
//
enum GenTreeDebugOperKind
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would have been possible to make the values here part of GenTreeOperKind, but I think having a separate enum is clearer overall.

{
DBK_FIRST_FLAG = GTK_MASK + 1,

DBK_NOTHIR = DBK_FIRST_FLAG, // This oper is not supported in HIR (before rationalization).
Copy link
Contributor Author

@SingleAccretion SingleAccretion Jan 29, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We also have "early HIR" in the compiler, i. e. HIR before morph: GT_FIELD, GT_PUTARG_TYPE, GT_RET_EXPR, GT_RUNTIMELOOKUP, GT_CNS_STR, GT_FTN_ADDR, GT_INDEX, so something like DBK_EHIR can now be easily added, if people feel like it is valuable (I personally do not see a lot of value).

DBK_NOTLIR = DBK_FIRST_FLAG << 1, // This oper is not supported in LIR (after rationalization).
DBK_NOCONTAIN = DBK_FIRST_FLAG << 2, // This oper produces a value, but may not be contained.

DBK_MASK = ~GTK_MASK
};

/*****************************************************************************/
Expand Down Expand Up @@ -878,8 +894,11 @@ struct GenTree
public:
// The register number is stored in a small format (8 bits), but the getters return and the setters take
// a full-size (unsigned) format, to localize the casts here.
CLANG_FORMAT_COMMENT_ANCHOR;

#ifdef DEBUG
bool canBeContained() const;
#endif

// for codegen purposes, is this node a subnode of its parent
bool isContained() const;
Expand Down Expand Up @@ -1073,34 +1092,6 @@ struct GenTree
return true;
}

bool IsLIR() const
{
if ((OperKind(gtOper) & GTK_NOTLIR) != 0)
{
return false;
}

switch (gtOper)
{
case GT_NOP:
// NOPs may only be present in LIR if they do not produce a value.
return IsNothingNode();

case GT_ADDR:
{
// ADDR ndoes may only be present in LIR if the location they refer to is not a
// local, class variable, or IND node.
GenTree* location = gtGetOp1();
genTreeOps locationOp = location->OperGet();
return !location->IsLocal() && (locationOp != GT_CLS_VAR) && (locationOp != GT_IND);
}

default:
// All other nodes are assumed to be correct.
return true;
}
}

// LIR flags
// These helper methods, along with the flag values they manipulate, are defined in lir.h
//
Expand Down Expand Up @@ -1645,6 +1636,20 @@ struct GenTree
}

#ifdef DEBUG
static const GenTreeDebugOperKind gtDebugOperKindTable[];

static GenTreeDebugOperKind DebugOperKind(genTreeOps oper)
{
assert(oper < GT_COUNT);

return gtDebugOperKindTable[oper];
}

GenTreeDebugOperKind DebugOperKind() const
{
return DebugOperKind(OperGet());
}

bool NullOp1Legal() const
{
assert(OperIsSimple());
Expand Down Expand Up @@ -1683,6 +1688,17 @@ struct GenTree
}
}

bool OperIsLIR() const
{
if (OperIs(GT_NOP))
{
// NOPs may only be present in LIR if they do not produce a value.
return IsNothingNode();
}

return (DebugOperKind() & DBK_NOTLIR) == 0;
}

bool OperSupportsReverseOps() const;
static bool RequiresNonNullOp2(genTreeOps oper);
bool IsValidCallArgument();
Expand Down
Loading