From acbccab7af8aecbc914adc3cf6c54b1cddf5d364 Mon Sep 17 00:00:00 2001 From: SingleAccretion Date: Sat, 29 Jan 2022 18:34:48 +0300 Subject: [PATCH 1/6] Introducing GenTreeDebugOperKind To track invariants related to opers in asserts without increasing the size of the primary oper kind table. Some shuffling of the oper table to make it look better. --- src/coreclr/jit/fgstmt.cpp | 6 +- src/coreclr/jit/gentree.cpp | 9 ++- src/coreclr/jit/gentree.h | 32 +++++++- src/coreclr/jit/gtlist.h | 139 +++++++++++++++++--------------- src/coreclr/jit/rationalize.cpp | 4 +- 5 files changed, 116 insertions(+), 74 deletions(-) diff --git a/src/coreclr/jit/fgstmt.cpp b/src/coreclr/jit/fgstmt.cpp index f5f07399a1d371..0730540d175e67 100644 --- a/src/coreclr/jit/fgstmt.cpp +++ b/src/coreclr/jit/fgstmt.cpp @@ -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) diff --git a/src/coreclr/jit/gentree.cpp b/src/coreclr/jit/gentree.cpp index 1b99f5171cef08..ca5e674e3c5d3d 100644 --- a/src/coreclr/jit/gentree.cpp +++ b/src/coreclr/jit/gentree.cpp @@ -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((ok) & DBK_MASK), +#include "gtlist.h" +}; +#endif // DEBUG + /***************************************************************************** * * The types of different GenTree nodes diff --git a/src/coreclr/jit/gentree.h b/src/coreclr/jit/gentree.h index b023c2bb8c52d4..bb067f29a3d86e 100644 --- a/src/coreclr/jit/gentree.h +++ b/src/coreclr/jit/gentree.h @@ -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 @@ -101,6 +101,22 @@ enum genTreeKinds 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_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 +{ + DBK_FIRST_FLAG = GTK_MASK + 1, + + DBK_NOTHIR = DBK_FIRST_FLAG, // This oper is not supported in HIR (before rationalization). + + DBK_MASK = ~GTK_MASK }; /*****************************************************************************/ @@ -1645,6 +1661,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()); diff --git a/src/coreclr/jit/gtlist.h b/src/coreclr/jit/gtlist.h index 9b40861fef0fd0..64cc05f907b7d3 100644 --- a/src/coreclr/jit/gtlist.h +++ b/src/coreclr/jit/gtlist.h @@ -11,7 +11,7 @@ // Node enum // , GenTree struct flavor // ,commutative -// ,operKind +// ,oper kind | DEBUG oper kind GTNODE(NONE , char ,0,GTK_SPECIAL) @@ -53,13 +53,16 @@ GTNODE(CNS_STR , GenTreeStrCon ,0,GTK_LEAF) GTNODE(NOT , GenTreeOp ,0,GTK_UNOP) GTNODE(NOP , GenTree ,0,(GTK_UNOP|GTK_NOCONTAIN)) GTNODE(NEG , GenTreeOp ,0,GTK_UNOP) -GTNODE(COPY , GenTreeCopyOrReload,0,GTK_UNOP) // Copies a variable from its current location to a register that satisfies - // code generation constraints. The child is the actual lclVar node. -GTNODE(RELOAD , GenTreeCopyOrReload,0,GTK_UNOP) -GTNODE(ARR_LENGTH , GenTreeArrLen ,0,(GTK_UNOP|GTK_EXOP)) // array-length -GTNODE(INTRINSIC , GenTreeIntrinsic ,0,(GTK_BINOP|GTK_EXOP)) // intrinsics -GTNODE(LOCKADD , GenTreeOp ,0,(GTK_BINOP|GTK_NOVALUE)) +// Copies a variable from its current location to a register that satisfies +// code generation constraints. The operand is the actual lclVar node. +GTNODE(COPY , GenTreeCopyOrReload,0,GTK_UNOP|DBK_NOTHIR) +GTNODE(RELOAD , GenTreeCopyOrReload,0,GTK_UNOP|DBK_NOTHIR) + +GTNODE(ARR_LENGTH , GenTreeArrLen ,0,(GTK_UNOP|GTK_EXOP)) +GTNODE(INTRINSIC , GenTreeIntrinsic ,0,(GTK_BINOP|GTK_EXOP)) + +GTNODE(LOCKADD , GenTreeOp ,0,(GTK_BINOP|GTK_NOVALUE|DBK_NOTHIR)) GTNODE(XAND , GenTreeOp ,0,GTK_BINOP) GTNODE(XORR , GenTreeOp ,0,GTK_BINOP) GTNODE(XADD , GenTreeOp ,0,GTK_BINOP) @@ -79,7 +82,7 @@ GTNODE(CKFINITE , GenTreeOp ,0,(GTK_UNOP|GTK_NOCONTAIN)) // Che GTNODE(LCLHEAP , GenTreeOp ,0,(GTK_UNOP|GTK_NOCONTAIN)) // alloca() GTNODE(JMP , GenTreeVal ,0,(GTK_LEAF|GTK_NOVALUE)) // Jump to another function -GTNODE(ADDR , GenTreeOp ,0,GTK_UNOP) // address of +GTNODE(ADDR , GenTreeOp ,0,GTK_UNOP|GTK_NOTLIR) // address of GTNODE(IND , GenTreeIndir ,0,GTK_UNOP) // load indirection GTNODE(STOREIND , GenTreeStoreInd ,0,(GTK_BINOP|GTK_NOVALUE)) // store indirection @@ -93,12 +96,12 @@ GTNODE(STORE_BLK , GenTreeBlk ,0,(GTK_BINOP|GTK_EXOP|GTK_NOVALUE) GTNODE(STORE_DYN_BLK , GenTreeStoreDynBlk ,0,(GTK_SPECIAL|GTK_NOVALUE)) // Dynamically sized block store GTNODE(BOX , GenTreeBox ,0,(GTK_UNOP|GTK_EXOP|GTK_NOTLIR)) -GTNODE(FIELD , GenTreeField ,0,(GTK_UNOP|GTK_EXOP)) // Member-field -GTNODE(ALLOCOBJ , GenTreeAllocObj ,0,(GTK_UNOP|GTK_EXOP)) // object allocator +GTNODE(FIELD , GenTreeField ,0,(GTK_UNOP|GTK_EXOP|GTK_NOTLIR)) // Member-field +GTNODE(ALLOCOBJ , GenTreeAllocObj ,0,(GTK_UNOP|GTK_EXOP|GTK_NOTLIR)) // object allocator -GTNODE(INIT_VAL , GenTreeOp ,0,GTK_UNOP) // Initialization value for an initBlk +GTNODE(INIT_VAL , GenTreeOp ,0,GTK_UNOP) // Initialization value for an initBlk -GTNODE(RUNTIMELOOKUP , GenTreeRuntimeLookup, 0,(GTK_UNOP|GTK_EXOP)) // Runtime handle lookup +GTNODE(RUNTIMELOOKUP , GenTreeRuntimeLookup, 0,(GTK_UNOP|GTK_EXOP|GTK_NOTLIR)) // Runtime handle lookup GTNODE(BSWAP , GenTreeOp ,0,GTK_UNOP) // Byte swap (32-bit or 64-bit) GTNODE(BSWAP16 , GenTreeOp ,0,GTK_UNOP) // Byte swap (16-bit) @@ -141,8 +144,8 @@ GTNODE(GT , GenTreeOp ,0,GTK_BINOP) // codegen which emits a "test reg, reg" instruction, that would be more difficult to do // during lowering because the source operand is used twice so it has to be a lclvar. // Because of this there is no need to also add GT_TEST_LT/LE/GE/GT opers. -GTNODE(TEST_EQ , GenTreeOp ,0,GTK_BINOP) -GTNODE(TEST_NE , GenTreeOp ,0,GTK_BINOP) +GTNODE(TEST_EQ , GenTreeOp ,0,GTK_BINOP|DBK_NOTHIR) +GTNODE(TEST_NE , GenTreeOp ,0,GTK_BINOP|DBK_NOTHIR) GTNODE(COMMA , GenTreeOp ,0,(GTK_BINOP|GTK_NOTLIR)) @@ -162,17 +165,17 @@ GTNODE(LEA , GenTreeAddrMode ,0,(GTK_BINOP|GTK_EXOP)) // of its two (lower and upper half) operands. Some GT_LONG nodes are transient, // during the decomposing of longs; others are handled by codegen as operands of // nodes such as calls, returns and stores of long lclVars. -GTNODE(LONG , GenTreeOp ,0,GTK_BINOP) +GTNODE(LONG , GenTreeOp ,0,GTK_BINOP|DBK_NOTHIR) // The following are nodes representing x86/arm32 specific long operators, including // high operators of a 64-bit operations that requires a carry/borrow, which are // named GT_XXX_HI for consistency, low operators of 64-bit operations that need // to not be modified in phases post-decompose, and operators that return 64-bit // results in one instruction. -GTNODE(ADD_LO , GenTreeOp ,1,GTK_BINOP) -GTNODE(ADD_HI , GenTreeOp ,1,GTK_BINOP) -GTNODE(SUB_LO , GenTreeOp ,0,GTK_BINOP) -GTNODE(SUB_HI , GenTreeOp ,0,GTK_BINOP) +GTNODE(ADD_LO , GenTreeOp ,1,GTK_BINOP|DBK_NOTHIR) +GTNODE(ADD_HI , GenTreeOp ,1,GTK_BINOP|DBK_NOTHIR) +GTNODE(SUB_LO , GenTreeOp ,0,GTK_BINOP|DBK_NOTHIR) +GTNODE(SUB_HI , GenTreeOp ,0,GTK_BINOP|DBK_NOTHIR) // The following are nodes that specify shifts that take a GT_LONG op1. The GT_LONG // contains the hi and lo parts of three operand shift form where one op will be @@ -181,8 +184,8 @@ GTNODE(SUB_HI , GenTreeOp ,0,GTK_BINOP) // will shift the lo bits of the high operand into the lo operand). LSH_HI // represents the high operation of a 64-bit left shift by a constant int, and // RSH_LO represents the lo operation of a 64-bit right shift by a constant int. -GTNODE(LSH_HI , GenTreeOp ,0,GTK_BINOP) -GTNODE(RSH_LO , GenTreeOp ,0,GTK_BINOP) +GTNODE(LSH_HI , GenTreeOp ,0,GTK_BINOP|DBK_NOTHIR) +GTNODE(RSH_LO , GenTreeOp ,0,GTK_BINOP|DBK_NOTHIR) #endif // !defined(TARGET_64BIT) #ifdef FEATURE_SIMD @@ -197,13 +200,14 @@ GTNODE(HWINTRINSIC , GenTreeHWIntrinsic ,0,GTK_SPECIAL) // ha // Backend-specific arithmetic nodes: //----------------------------------------------------------------------------- -GTNODE(INC_SATURATE , GenTreeOp ,0,GTK_UNOP) // saturating increment, used in division by a constant (LowerUnsignedDivOrMod) +// Saturating increment, used in division by a constant (LowerUnsignedDivOrMod). +GTNODE(INC_SATURATE , GenTreeOp ,0,GTK_UNOP|DBK_NOTHIR) // Returns high bits (top N bits of the 2N bit result of an NxN multiply) // GT_MULHI is used in division by a constant (LowerUnsignedDivOrMod). We turn // the div into a MULHI + some adjustments. In codegen, we only use the // results of the high register, and we drop the low results. -GTNODE(MULHI , GenTreeOp ,1,GTK_BINOP) +GTNODE(MULHI , GenTreeOp ,1,GTK_BINOP|DBK_NOTHIR) // A mul that returns the 2N bit result of an NxN multiply. This op is used for // multiplies that take two ints and return a long result. For 32 bit targets, @@ -212,26 +216,27 @@ GTNODE(MULHI , GenTreeOp ,1,GTK_BINOP) // part of the result, whereas GT_MUL_LONG keeps both parts of the result. // MUL_LONG is also used on ARM64, where 64 bit multiplication is more expensive. #if !defined(TARGET_64BIT) -GTNODE(MUL_LONG , GenTreeMultiRegOp ,1,GTK_BINOP) +GTNODE(MUL_LONG , GenTreeMultiRegOp ,1,GTK_BINOP|DBK_NOTHIR) #elif defined(TARGET_ARM64) -GTNODE(MUL_LONG , GenTreeOp ,1,GTK_BINOP) +GTNODE(MUL_LONG , GenTreeOp ,1,GTK_BINOP|DBK_NOTHIR) #endif // AndNot - emitted on ARM/ARM64 as the BIC instruction. Also used for creating AndNot HWINTRINSIC vector nodes in a cross-ISA manner. -GTNODE(AND_NOT , GenTreeOp ,0,GTK_BINOP) +GTNODE(AND_NOT , GenTreeOp ,0,GTK_BINOP|DBK_NOTHIR) //----------------------------------------------------------------------------- // LIR specific compare and conditional branch/set nodes: //----------------------------------------------------------------------------- -GTNODE(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(JCMP , GenTreeOp ,0,(GTK_BINOP|GTK_NOVALUE)) // Makes a comparison and jump if the condition specified. Does not set flags -GTNODE(JCC , GenTreeCC ,0,(GTK_LEAF|GTK_NOVALUE)) // Checks the condition flags and branch if the condition specified - // by GenTreeCC::gtCondition is true. -GTNODE(SETCC , GenTreeCC ,0,GTK_LEAF) // Checks the condition flags and produces 1 if the condition specified - // by GenTreeCC::gtCondition is true and 0 otherwise. +// 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(CMP , GenTreeOp ,0,(GTK_BINOP|GTK_NOVALUE|DBK_NOTHIR)) +// Makes a comparison and jump if the condition specified. Does not set flags. +GTNODE(JCMP , GenTreeOp ,0,(GTK_BINOP|GTK_NOVALUE|DBK_NOTHIR)) +// Checks the condition flags and branch if the condition specified by GenTreeCC::gtCondition is true. +GTNODE(JCC , GenTreeCC ,0,(GTK_LEAF|GTK_NOVALUE|DBK_NOTHIR)) +// Checks the condition flags and produces 1 if the condition specified by GenTreeCC::gtCondition is true and 0 otherwise. +GTNODE(SETCC , GenTreeCC ,0,GTK_LEAF|DBK_NOTHIR) #ifdef TARGET_XARCH -GTNODE(BT , GenTreeOp ,0,(GTK_BINOP|GTK_NOVALUE)) // The XARCH BT instruction. Like CMP, this sets the condition flags (CF - // to be precise) and does not produce a value. +// The XARCH BT instruction. Like CMP, this sets the condition flags (CF to be precise) and does not produce a value. +GTNODE(BT , GenTreeOp ,0,(GTK_BINOP|GTK_NOVALUE|DBK_NOTHIR)) #endif //----------------------------------------------------------------------------- // Other nodes that look like unary/binary operators: @@ -249,20 +254,20 @@ GTNODE(ARR_OFFSET , GenTreeArrOffs ,0,GTK_SPECIAL) // Flatt GTNODE(CALL , GenTreeCall ,0,(GTK_SPECIAL|GTK_NOCONTAIN)) GTNODE(FIELD_LIST , GenTreeFieldList ,0,GTK_SPECIAL) // List of fields of a struct, when passed as an argument -GTNODE(RETURN , GenTreeOp ,0,(GTK_UNOP|GTK_NOVALUE)) // return from current function -GTNODE(SWITCH , GenTreeOp ,0,(GTK_UNOP|GTK_NOVALUE)) // switch - -GTNODE(NO_OP , GenTree ,0,(GTK_LEAF|GTK_NOVALUE)) // nop! - -GTNODE(START_NONGC , GenTree ,0,(GTK_LEAF|GTK_NOVALUE)) // starts a new instruction group that will be non-gc interruptible - -GTNODE(START_PREEMPTGC , GenTree ,0,(GTK_LEAF|GTK_NOVALUE)) // starts a new instruction group where preemptive GC is enabled +GTNODE(RETURN , GenTreeOp ,0,(GTK_UNOP|GTK_NOVALUE)) +GTNODE(SWITCH , GenTreeOp ,0,(GTK_UNOP|GTK_NOVALUE)) +GTNODE(NO_OP , GenTree ,0,(GTK_LEAF|GTK_NOVALUE)) // A NOP that cannot be deleted. -GTNODE(PROF_HOOK , GenTree ,0,(GTK_LEAF|GTK_NOVALUE)) // profiler Enter/Leave/TailCall hook +// Starts a new instruction group that will be non-gc interruptible. +GTNODE(START_NONGC , GenTree ,0,(GTK_LEAF|GTK_NOVALUE|DBK_NOTHIR)) +// Starts a new instruction group where preemptive GC is enabled. +GTNODE(START_PREEMPTGC , GenTree ,0,(GTK_LEAF|GTK_NOVALUE|DBK_NOTHIR)) +// Profiler Enter/Leave/TailCall hook. +GTNODE(PROF_HOOK , GenTree ,0,(GTK_LEAF|GTK_NOVALUE|DBK_NOTHIR)) -GTNODE(RETFILT , GenTreeOp ,0,(GTK_UNOP|GTK_NOVALUE)) // end filter with TYP_I_IMPL return value +GTNODE(RETFILT , GenTreeOp ,0,(GTK_UNOP|GTK_NOVALUE)) // End filter with TYP_I_IMPL return value. #if !defined(FEATURE_EH_FUNCLETS) -GTNODE(END_LFIN , GenTreeVal ,0,(GTK_LEAF|GTK_NOVALUE)) // end locally-invoked finally +GTNODE(END_LFIN , GenTreeVal ,0,(GTK_LEAF|GTK_NOVALUE)) // End locally-invoked finally. #endif // !FEATURE_EH_FUNCLETS //----------------------------------------------------------------------------- @@ -270,42 +275,42 @@ GTNODE(END_LFIN , GenTreeVal ,0,(GTK_LEAF|GTK_NOVALUE)) // end //----------------------------------------------------------------------------- #ifdef TARGET_ARM64 -GTNODE(MADD , GenTreeOp ,0, GTK_BINOP) // Generates the Multiply-Add instruction (madd/msub) +GTNODE(MADD , GenTreeOp ,0, GTK_BINOP|DBK_NOTHIR) // Generates the Multiply-Add instruction (madd/msub) // In future, we might consider enabling it for both armarch and xarch // for floating-point MADD "unsafe" math #endif -GTNODE(JMPTABLE , GenTree ,0, (GTK_LEAF|GTK_NOCONTAIN)) // Generates the jump table for switches -GTNODE(SWITCH_TABLE , GenTreeOp ,0, (GTK_BINOP|GTK_NOVALUE)) // Jump Table based switch construct +GTNODE(JMPTABLE , GenTree ,0, (GTK_LEAF|GTK_NOCONTAIN|DBK_NOTHIR)) // Generates the jump table for switches +GTNODE(SWITCH_TABLE , GenTreeOp ,0, (GTK_BINOP|GTK_NOVALUE|DBK_NOTHIR)) // Jump Table based switch construct #ifdef TARGET_ARM64 -GTNODE(ADDEX, GenTreeOp ,0, GTK_BINOP) // Add with sign/zero extension -GTNODE(BFIZ , GenTreeOp ,0, GTK_BINOP) // Bitfield Insert in Zero +GTNODE(ADDEX, GenTreeOp ,0, GTK_BINOP|DBK_NOTHIR) // Add with sign/zero extension +GTNODE(BFIZ , GenTreeOp ,0, GTK_BINOP|DBK_NOTHIR) // Bitfield Insert in Zero #endif //----------------------------------------------------------------------------- // Nodes used only within the code generator: //----------------------------------------------------------------------------- -GTNODE(CLS_VAR , GenTreeClsVar ,0,GTK_LEAF) // static data member -GTNODE(CLS_VAR_ADDR , GenTreeClsVar ,0,GTK_LEAF) // static data member address -GTNODE(ARGPLACE , GenTreeArgPlace ,0,GTK_LEAF|GTK_NOVALUE|GTK_NOTLIR) // placeholder for a register arg -GTNODE(NULLCHECK , GenTreeIndir ,0,GTK_UNOP|GTK_NOVALUE) // null checks the source -GTNODE(PHYSREG , GenTreePhysReg ,0,GTK_LEAF) // read from a physical register -GTNODE(EMITNOP , GenTree ,0,GTK_LEAF|GTK_NOVALUE) // emitter-placed nop -GTNODE(PINVOKE_PROLOG , GenTree ,0,GTK_LEAF|GTK_NOVALUE) // pinvoke prolog seq -GTNODE(PINVOKE_EPILOG , GenTree ,0,GTK_LEAF|GTK_NOVALUE) // pinvoke epilog seq +GTNODE(CLS_VAR , GenTreeClsVar ,0,GTK_LEAF) // static data member +GTNODE(CLS_VAR_ADDR , GenTreeClsVar ,0,GTK_LEAF|DBK_NOTHIR) // static data member address +GTNODE(ARGPLACE , GenTreeArgPlace ,0,GTK_LEAF|GTK_NOVALUE|GTK_NOTLIR) // placeholder for a register arg +GTNODE(NULLCHECK , GenTreeIndir ,0,GTK_UNOP|GTK_NOVALUE) // null checks the source +GTNODE(PHYSREG , GenTreePhysReg ,0,GTK_LEAF|DBK_NOTHIR) // read from a physical register +GTNODE(EMITNOP , GenTree ,0,GTK_LEAF|GTK_NOVALUE|DBK_NOTHIR) // emitter-placed nop +GTNODE(PINVOKE_PROLOG , GenTree ,0,GTK_LEAF|GTK_NOVALUE|DBK_NOTHIR) // pinvoke prolog seq +GTNODE(PINVOKE_EPILOG , GenTree ,0,GTK_LEAF|GTK_NOVALUE|DBK_NOTHIR) // pinvoke epilog seq #if defined(TARGET_ARM) -GTNODE(PUTARG_REG , GenTreeMultiRegOp ,0,GTK_UNOP) // operator that places outgoing arg in register +GTNODE(PUTARG_REG , GenTreeMultiRegOp ,0,GTK_UNOP|DBK_NOTHIR) // operator that places outgoing arg in register #else -GTNODE(PUTARG_REG , GenTreeOp ,0,GTK_UNOP) // operator that places outgoing arg in register +GTNODE(PUTARG_REG , GenTreeOp ,0,GTK_UNOP|DBK_NOTHIR) // operator that places outgoing arg in register #endif -GTNODE(PUTARG_TYPE , GenTreeOp ,0,GTK_UNOP|GTK_NOTLIR) // operator that places saves argument type between importation and morph -GTNODE(PUTARG_STK , GenTreePutArgStk ,0,GTK_UNOP|GTK_NOVALUE) // operator that places outgoing arg in stack +GTNODE(PUTARG_TYPE , GenTreeOp ,0,GTK_UNOP|GTK_NOTLIR) // operator that saves argument type between importation and morph +GTNODE(PUTARG_STK , GenTreePutArgStk ,0,GTK_UNOP|GTK_NOVALUE|DBK_NOTHIR) // operator that places outgoing arg in stack #if FEATURE_ARG_SPLIT -GTNODE(PUTARG_SPLIT , GenTreePutArgSplit ,0,GTK_UNOP) // operator that places outgoing arg in registers with stack (split struct in ARM32) +GTNODE(PUTARG_SPLIT , GenTreePutArgSplit ,0,GTK_UNOP|DBK_NOTHIR) // operator that places outgoing arg in registers with stack (split struct in ARM32) #endif // FEATURE_ARG_SPLIT -GTNODE(RETURNTRAP , GenTreeOp ,0,GTK_UNOP|GTK_NOVALUE) // a conditional call to wait on gc -GTNODE(SWAP , GenTreeOp ,0,GTK_BINOP|GTK_NOVALUE) // op1 and op2 swap (registers) -GTNODE(IL_OFFSET , Statement ,0,GTK_LEAF|GTK_NOVALUE) // marks an IL offset for debugging purposes +GTNODE(RETURNTRAP , GenTreeOp ,0,GTK_UNOP|GTK_NOVALUE|DBK_NOTHIR) // a conditional call to wait on gc +GTNODE(SWAP , GenTreeOp ,0,GTK_BINOP|GTK_NOVALUE|DBK_NOTHIR) // op1 and op2 swap (registers) +GTNODE(IL_OFFSET , GenTreeILOffset ,0,GTK_LEAF|GTK_NOVALUE|DBK_NOTHIR) // marks an IL offset for debugging purposes /*****************************************************************************/ #undef GTNODE diff --git a/src/coreclr/jit/rationalize.cpp b/src/coreclr/jit/rationalize.cpp index 72c1591c6d4251..5eacf657ad8b7b 100644 --- a/src/coreclr/jit/rationalize.cpp +++ b/src/coreclr/jit/rationalize.cpp @@ -803,8 +803,8 @@ Compiler::fgWalkResult Rationalizer::RewriteNode(GenTree** useEdge, Compiler::Ge #endif // FEATURE_HW_INTRINSICS default: - // These nodes should not be present in HIR. - assert(!node->OperIs(GT_CMP, GT_SETCC, GT_JCC, GT_JCMP, GT_LOCKADD)); + // Check that we don't have nodes not allowed in HIR here. + assert((node->DebugOperKind() & DBK_NOTHIR) == 0); break; } From 4f8352741a824ad076c969d99b20930ef6768e3a Mon Sep 17 00:00:00 2001 From: SingleAccretion Date: Sat, 29 Jan 2022 19:03:01 +0300 Subject: [PATCH 2/6] More "gtlist.h" cleanup Put all OperIsIdir opers together, fix up formatting, move opers around to more logical places. --- src/coreclr/jit/gtlist.h | 159 ++++++++++++++++++--------------------- 1 file changed, 75 insertions(+), 84 deletions(-) diff --git a/src/coreclr/jit/gtlist.h b/src/coreclr/jit/gtlist.h index 64cc05f907b7d3..9574ae46e496ae 100644 --- a/src/coreclr/jit/gtlist.h +++ b/src/coreclr/jit/gtlist.h @@ -19,23 +19,27 @@ GTNODE(NONE , char ,0,GTK_SPECIAL) // Nodes related to locals: //----------------------------------------------------------------------------- -GTNODE(PHI , GenTreePhi ,0,GTK_SPECIAL) // phi node for ssa. -GTNODE(PHI_ARG , GenTreePhiArg ,0,GTK_LEAF) // phi(phiarg, phiarg, phiarg) -GTNODE(LCL_VAR , GenTreeLclVar ,0,GTK_LEAF) // local variable -GTNODE(LCL_FLD , GenTreeLclFld ,0,GTK_LEAF) // field in a non-primitive variable -GTNODE(STORE_LCL_VAR , GenTreeLclVar ,0,(GTK_UNOP|GTK_NOVALUE)) // store to local variable -GTNODE(STORE_LCL_FLD , GenTreeLclFld ,0,(GTK_UNOP|GTK_NOVALUE)) // store to a part of the variable -GTNODE(LCL_VAR_ADDR , GenTreeLclVar ,0,GTK_LEAF) // address of local variable -GTNODE(LCL_FLD_ADDR , GenTreeLclFld ,0,GTK_LEAF) // address of field in a non-primitive variable +GTNODE(PHI , GenTreePhi ,0,GTK_SPECIAL) // phi node for ssa. +GTNODE(PHI_ARG , GenTreePhiArg ,0,GTK_LEAF) // phi(phiarg, phiarg, phiarg) +GTNODE(LCL_VAR , GenTreeLclVar ,0,GTK_LEAF) // local variable +GTNODE(LCL_FLD , GenTreeLclFld ,0,GTK_LEAF) // field in a non-primitive variable +GTNODE(STORE_LCL_VAR , GenTreeLclVar ,0,GTK_UNOP|GTK_NOVALUE) // store to local variable +GTNODE(STORE_LCL_FLD , GenTreeLclFld ,0,GTK_UNOP|GTK_NOVALUE) // store to a part of the variable +GTNODE(LCL_VAR_ADDR , GenTreeLclVar ,0,GTK_LEAF) // address of local variable +GTNODE(LCL_FLD_ADDR , GenTreeLclFld ,0,GTK_LEAF) // address of field in a non-primitive variable //----------------------------------------------------------------------------- // Leaf nodes (i.e. these nodes have no sub-operands): //----------------------------------------------------------------------------- -GTNODE(CATCH_ARG , GenTree ,0,GTK_LEAF) // Exception object in a catch block -GTNODE(LABEL , GenTree ,0,GTK_LEAF) // Jump-target -GTNODE(FTN_ADDR , GenTreeFptrVal ,0,GTK_LEAF) // Address of a function -GTNODE(RET_EXPR , GenTreeRetExpr ,0,GTK_LEAF|GTK_NOTLIR) // Place holder for the return expression from an inline candidate +GTNODE(CATCH_ARG , GenTree ,0,GTK_LEAF) // Exception object in a catch block +GTNODE(LABEL , GenTree ,0,GTK_LEAF) // Jump-target +GTNODE(JMP , GenTreeVal ,0,GTK_LEAF|GTK_NOVALUE) // Jump to another function +GTNODE(FTN_ADDR , GenTreeFptrVal ,0,GTK_LEAF) // Address of a function +GTNODE(RET_EXPR , GenTreeRetExpr ,0,GTK_LEAF|GTK_NOTLIR) // Place holder for the return expression from an inline candidate +GTNODE(CLS_VAR , GenTreeClsVar ,0,GTK_LEAF) // Static data member + +GTNODE(ARGPLACE , GenTreeArgPlace ,0,GTK_LEAF|GTK_NOVALUE|GTK_NOTLIR) // Placeholder for a "late arg" in the original arg list. //----------------------------------------------------------------------------- // Constant nodes: @@ -51,57 +55,52 @@ GTNODE(CNS_STR , GenTreeStrCon ,0,GTK_LEAF) //----------------------------------------------------------------------------- GTNODE(NOT , GenTreeOp ,0,GTK_UNOP) -GTNODE(NOP , GenTree ,0,(GTK_UNOP|GTK_NOCONTAIN)) +GTNODE(NOP , GenTree ,0,GTK_UNOP|GTK_NOCONTAIN) GTNODE(NEG , GenTreeOp ,0,GTK_UNOP) -// Copies a variable from its current location to a register that satisfies -// code generation constraints. The operand is the actual lclVar node. -GTNODE(COPY , GenTreeCopyOrReload,0,GTK_UNOP|DBK_NOTHIR) -GTNODE(RELOAD , GenTreeCopyOrReload,0,GTK_UNOP|DBK_NOTHIR) - -GTNODE(ARR_LENGTH , GenTreeArrLen ,0,(GTK_UNOP|GTK_EXOP)) -GTNODE(INTRINSIC , GenTreeIntrinsic ,0,(GTK_BINOP|GTK_EXOP)) +GTNODE(INTRINSIC , GenTreeIntrinsic ,0,GTK_BINOP|GTK_EXOP) -GTNODE(LOCKADD , GenTreeOp ,0,(GTK_BINOP|GTK_NOVALUE|DBK_NOTHIR)) +GTNODE(LOCKADD , GenTreeOp ,0,GTK_BINOP|GTK_NOVALUE|DBK_NOTHIR) GTNODE(XAND , GenTreeOp ,0,GTK_BINOP) GTNODE(XORR , GenTreeOp ,0,GTK_BINOP) GTNODE(XADD , GenTreeOp ,0,GTK_BINOP) GTNODE(XCHG , GenTreeOp ,0,GTK_BINOP) GTNODE(CMPXCHG , GenTreeCmpXchg ,0,GTK_SPECIAL) -GTNODE(MEMORYBARRIER , GenTree ,0,(GTK_LEAF|GTK_NOVALUE)) +GTNODE(MEMORYBARRIER , GenTree ,0,GTK_LEAF|GTK_NOVALUE) -GTNODE(KEEPALIVE , GenTree ,0,(GTK_UNOP|GTK_NOVALUE)) // keep operand alive, generate no code, produce no result +GTNODE(KEEPALIVE , GenTree ,0,GTK_UNOP|GTK_NOVALUE) // keep operand alive, generate no code, produce no result -GTNODE(CAST , GenTreeCast ,0,(GTK_UNOP|GTK_EXOP)) // conversion to another type +GTNODE(CAST , GenTreeCast ,0,GTK_UNOP|GTK_EXOP) // conversion to another type #if defined(TARGET_ARM) GTNODE(BITCAST , GenTreeMultiRegOp ,0,GTK_UNOP) // reinterpretation of bits as another type #else GTNODE(BITCAST , GenTreeOp ,0,GTK_UNOP) // reinterpretation of bits as another type #endif -GTNODE(CKFINITE , GenTreeOp ,0,(GTK_UNOP|GTK_NOCONTAIN)) // Check for NaN -GTNODE(LCLHEAP , GenTreeOp ,0,(GTK_UNOP|GTK_NOCONTAIN)) // alloca() -GTNODE(JMP , GenTreeVal ,0,(GTK_LEAF|GTK_NOVALUE)) // Jump to another function +GTNODE(CKFINITE , GenTreeOp ,0,GTK_UNOP|GTK_NOCONTAIN) // Check for NaN +GTNODE(LCLHEAP , GenTreeOp ,0,GTK_UNOP|GTK_NOCONTAIN) // alloca() -GTNODE(ADDR , GenTreeOp ,0,GTK_UNOP|GTK_NOTLIR) // address of +GTNODE(ADDR , GenTreeOp ,0,GTK_UNOP|GTK_NOTLIR) // address of -GTNODE(IND , GenTreeIndir ,0,GTK_UNOP) // load indirection -GTNODE(STOREIND , GenTreeStoreInd ,0,(GTK_BINOP|GTK_NOVALUE)) // store indirection +GTNODE(BOUNDS_CHECK , GenTreeBoundsChk ,0,GTK_BINOP|GTK_EXOP|GTK_NOVALUE) // a bounds check - for arrays/spans/SIMDs/HWINTRINSICs -GTNODE(BOUNDS_CHECK , GenTreeBoundsChk ,0,(GTK_BINOP|GTK_EXOP|GTK_NOVALUE)) // a bounds check - for arrays/spans/SIMDs/HWINTRINSICs +GTNODE(IND , GenTreeIndir ,0,GTK_UNOP) // Load indirection +GTNODE(STOREIND , GenTreeStoreInd ,0,GTK_BINOP|GTK_NOVALUE) // Store indirection +GTNODE(OBJ , GenTreeObj ,0,GTK_UNOP|GTK_EXOP) // Object that MAY have gc pointers, and thus includes the relevant gc layout info. +GTNODE(STORE_OBJ , GenTreeObj ,0,GTK_BINOP|GTK_EXOP|GTK_NOVALUE) // Object that MAY have gc pointers, and thus includes the relevant gc layout info. +GTNODE(BLK , GenTreeBlk ,0,GTK_UNOP|GTK_EXOP) // Block/object with no gc pointers, and with a known size (e.g. a struct with no gc fields) +GTNODE(STORE_BLK , GenTreeBlk ,0,GTK_BINOP|GTK_EXOP|GTK_NOVALUE) // Block/object with no gc pointers, and with a known size (e.g. a struct with no gc fields) +GTNODE(STORE_DYN_BLK , GenTreeStoreDynBlk ,0,GTK_SPECIAL|GTK_NOVALUE) // Dynamically sized block store +GTNODE(NULLCHECK , GenTreeIndir ,0,GTK_UNOP|GTK_NOVALUE) // Null checks the source -GTNODE(OBJ , GenTreeObj ,0,(GTK_UNOP|GTK_EXOP)) // Object that MAY have gc pointers, and thus includes the relevant gc layout info. -GTNODE(STORE_OBJ , GenTreeObj ,0,(GTK_BINOP|GTK_EXOP|GTK_NOVALUE)) // Object that MAY have gc pointers, and thus includes the relevant gc layout info. -GTNODE(BLK , GenTreeBlk ,0,(GTK_UNOP|GTK_EXOP)) // Block/object with no gc pointers, and with a known size (e.g. a struct with no gc fields) -GTNODE(STORE_BLK , GenTreeBlk ,0,(GTK_BINOP|GTK_EXOP|GTK_NOVALUE)) // Block/object with no gc pointers, and with a known size (e.g. a struct with no gc fields) -GTNODE(STORE_DYN_BLK , GenTreeStoreDynBlk ,0,(GTK_SPECIAL|GTK_NOVALUE)) // Dynamically sized block store - -GTNODE(BOX , GenTreeBox ,0,(GTK_UNOP|GTK_EXOP|GTK_NOTLIR)) -GTNODE(FIELD , GenTreeField ,0,(GTK_UNOP|GTK_EXOP|GTK_NOTLIR)) // Member-field -GTNODE(ALLOCOBJ , GenTreeAllocObj ,0,(GTK_UNOP|GTK_EXOP|GTK_NOTLIR)) // object allocator +GTNODE(ARR_LENGTH , GenTreeArrLen ,0,GTK_UNOP|GTK_EXOP) +GTNODE(FIELD , GenTreeField ,0,GTK_UNOP|GTK_EXOP|GTK_NOTLIR) // Member-field +GTNODE(ALLOCOBJ , GenTreeAllocObj ,0,GTK_UNOP|GTK_EXOP|GTK_NOTLIR) // object allocator GTNODE(INIT_VAL , GenTreeOp ,0,GTK_UNOP) // Initialization value for an initBlk -GTNODE(RUNTIMELOOKUP , GenTreeRuntimeLookup, 0,(GTK_UNOP|GTK_EXOP|GTK_NOTLIR)) // Runtime handle lookup +GTNODE(BOX , GenTreeBox ,0,GTK_UNOP|GTK_EXOP|GTK_NOTLIR) // Marks its first operands (a local) as being a box +GTNODE(PUTARG_TYPE , GenTreeOp ,0,GTK_UNOP|GTK_NOTLIR) // Saves argument type between importation and morph +GTNODE(RUNTIMELOOKUP , GenTreeRuntimeLookup, 0,GTK_UNOP|GTK_EXOP|GTK_NOTLIR) // Runtime handle lookup GTNODE(BSWAP , GenTreeOp ,0,GTK_UNOP) // Byte swap (32-bit or 64-bit) GTNODE(BSWAP16 , GenTreeOp ,0,GTK_UNOP) // Byte swap (16-bit) @@ -129,7 +128,7 @@ GTNODE(RSZ , GenTreeOp ,0,GTK_BINOP) GTNODE(ROL , GenTreeOp ,0,GTK_BINOP) GTNODE(ROR , GenTreeOp ,0,GTK_BINOP) -GTNODE(ASG , GenTreeOp ,0,(GTK_BINOP|GTK_NOTLIR)) +GTNODE(ASG , GenTreeOp ,0,GTK_BINOP|GTK_NOTLIR) GTNODE(EQ , GenTreeOp ,0,GTK_BINOP) GTNODE(NE , GenTreeOp ,0,GTK_BINOP) GTNODE(LT , GenTreeOp ,0,GTK_BINOP) @@ -147,18 +146,15 @@ GTNODE(GT , GenTreeOp ,0,GTK_BINOP) GTNODE(TEST_EQ , GenTreeOp ,0,GTK_BINOP|DBK_NOTHIR) GTNODE(TEST_NE , GenTreeOp ,0,GTK_BINOP|DBK_NOTHIR) -GTNODE(COMMA , GenTreeOp ,0,(GTK_BINOP|GTK_NOTLIR)) - -GTNODE(QMARK , GenTreeQmark ,0,(GTK_BINOP|GTK_EXOP|GTK_NOTLIR)) -GTNODE(COLON , GenTreeColon ,0,(GTK_BINOP|GTK_NOTLIR)) +GTNODE(COMMA , GenTreeOp ,0,GTK_BINOP|GTK_NOTLIR) +GTNODE(QMARK , GenTreeQmark ,0,GTK_BINOP|GTK_EXOP|GTK_NOTLIR) +GTNODE(COLON , GenTreeColon ,0,GTK_BINOP|GTK_NOTLIR) -GTNODE(INDEX , GenTreeIndex ,0,(GTK_BINOP|GTK_EXOP|GTK_NOTLIR)) // SZ-array-element -GTNODE(INDEX_ADDR , GenTreeIndexAddr ,0,(GTK_BINOP|GTK_EXOP)) // addr of SZ-array-element; - // used when aiming to minimize compile times. +GTNODE(INDEX , GenTreeIndex ,0,GTK_BINOP|GTK_EXOP|GTK_NOTLIR) // SZ-array-element. +GTNODE(INDEX_ADDR , GenTreeIndexAddr ,0,GTK_BINOP|GTK_EXOP) // Addr of SZ-array-element; used when aiming to minimize compile times. GTNODE(MKREFANY , GenTreeOp ,0,GTK_BINOP|GTK_NOTLIR) - -GTNODE(LEA , GenTreeAddrMode ,0,(GTK_BINOP|GTK_EXOP)) +GTNODE(LEA , GenTreeAddrMode ,0,GTK_BINOP|GTK_EXOP) #if !defined(TARGET_64BIT) // A GT_LONG node simply represents the long value produced by the concatenation @@ -222,94 +218,89 @@ GTNODE(MUL_LONG , GenTreeOp ,1,GTK_BINOP|DBK_NOTHIR) #endif // AndNot - emitted on ARM/ARM64 as the BIC instruction. Also used for creating AndNot HWINTRINSIC vector nodes in a cross-ISA manner. GTNODE(AND_NOT , GenTreeOp ,0,GTK_BINOP|DBK_NOTHIR) + +#ifdef TARGET_ARM64 +GTNODE(MADD , GenTreeOp ,0,GTK_BINOP|DBK_NOTHIR) // Generates the Multiply-Add instruction (madd/msub) In the future, we might consider + // enabling it for both armarch and xarch for floating-point MADD "unsafe" math. +GTNODE(ADDEX, GenTreeOp ,0,GTK_BINOP|DBK_NOTHIR) // Add with sign/zero extension. +GTNODE(BFIZ , GenTreeOp ,0,GTK_BINOP|DBK_NOTHIR) // Bitfield Insert in Zero. +#endif + //----------------------------------------------------------------------------- // LIR specific compare and conditional branch/set nodes: //----------------------------------------------------------------------------- // 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(CMP , GenTreeOp ,0,(GTK_BINOP|GTK_NOVALUE|DBK_NOTHIR)) +GTNODE(CMP , GenTreeOp ,0,GTK_BINOP|GTK_NOVALUE|DBK_NOTHIR) // Makes a comparison and jump if the condition specified. Does not set flags. -GTNODE(JCMP , GenTreeOp ,0,(GTK_BINOP|GTK_NOVALUE|DBK_NOTHIR)) +GTNODE(JCMP , GenTreeOp ,0,GTK_BINOP|GTK_NOVALUE|DBK_NOTHIR) // Checks the condition flags and branch if the condition specified by GenTreeCC::gtCondition is true. -GTNODE(JCC , GenTreeCC ,0,(GTK_LEAF|GTK_NOVALUE|DBK_NOTHIR)) +GTNODE(JCC , GenTreeCC ,0,GTK_LEAF|GTK_NOVALUE|DBK_NOTHIR) // Checks the condition flags and produces 1 if the condition specified by GenTreeCC::gtCondition is true and 0 otherwise. GTNODE(SETCC , GenTreeCC ,0,GTK_LEAF|DBK_NOTHIR) #ifdef TARGET_XARCH // The XARCH BT instruction. Like CMP, this sets the condition flags (CF to be precise) and does not produce a value. GTNODE(BT , GenTreeOp ,0,(GTK_BINOP|GTK_NOVALUE|DBK_NOTHIR)) #endif + //----------------------------------------------------------------------------- // Other nodes that look like unary/binary operators: //----------------------------------------------------------------------------- -GTNODE(JTRUE , GenTreeOp ,0,(GTK_UNOP|GTK_NOVALUE)) +GTNODE(JTRUE , GenTreeOp ,0,GTK_UNOP|GTK_NOVALUE) //----------------------------------------------------------------------------- // Other nodes that have special structure: //----------------------------------------------------------------------------- GTNODE(ARR_ELEM , GenTreeArrElem ,0,GTK_SPECIAL) // Multi-dimensional array-element address -GTNODE(ARR_INDEX , GenTreeArrIndex ,0,(GTK_BINOP|GTK_EXOP)) // Effective, bounds-checked index for one dimension of a multi-dimensional array element +GTNODE(ARR_INDEX , GenTreeArrIndex ,0,GTK_BINOP|GTK_EXOP) // Effective, bounds-checked index for one dimension of a multi-dimensional array element GTNODE(ARR_OFFSET , GenTreeArrOffs ,0,GTK_SPECIAL) // Flattened offset of multi-dimensional array element -GTNODE(CALL , GenTreeCall ,0,(GTK_SPECIAL|GTK_NOCONTAIN)) +GTNODE(CALL , GenTreeCall ,0,GTK_SPECIAL|GTK_NOCONTAIN) GTNODE(FIELD_LIST , GenTreeFieldList ,0,GTK_SPECIAL) // List of fields of a struct, when passed as an argument -GTNODE(RETURN , GenTreeOp ,0,(GTK_UNOP|GTK_NOVALUE)) -GTNODE(SWITCH , GenTreeOp ,0,(GTK_UNOP|GTK_NOVALUE)) -GTNODE(NO_OP , GenTree ,0,(GTK_LEAF|GTK_NOVALUE)) // A NOP that cannot be deleted. +GTNODE(RETURN , GenTreeOp ,0,GTK_UNOP|GTK_NOVALUE) +GTNODE(SWITCH , GenTreeOp ,0,GTK_UNOP|GTK_NOVALUE) +GTNODE(NO_OP , GenTree ,0,GTK_LEAF|GTK_NOVALUE) // A NOP that cannot be deleted. -// Starts a new instruction group that will be non-gc interruptible. -GTNODE(START_NONGC , GenTree ,0,(GTK_LEAF|GTK_NOVALUE|DBK_NOTHIR)) -// Starts a new instruction group where preemptive GC is enabled. -GTNODE(START_PREEMPTGC , GenTree ,0,(GTK_LEAF|GTK_NOVALUE|DBK_NOTHIR)) -// Profiler Enter/Leave/TailCall hook. -GTNODE(PROF_HOOK , GenTree ,0,(GTK_LEAF|GTK_NOVALUE|DBK_NOTHIR)) +GTNODE(START_NONGC , GenTree ,0,GTK_LEAF|GTK_NOVALUE|DBK_NOTHIR) // Starts a new instruction group that will be non-gc interruptible. +GTNODE(START_PREEMPTGC , GenTree ,0,GTK_LEAF|GTK_NOVALUE|DBK_NOTHIR) // Starts a new instruction group where preemptive GC is enabled. +GTNODE(PROF_HOOK , GenTree ,0,GTK_LEAF|GTK_NOVALUE|DBK_NOTHIR) // Profiler Enter/Leave/TailCall hook. -GTNODE(RETFILT , GenTreeOp ,0,(GTK_UNOP|GTK_NOVALUE)) // End filter with TYP_I_IMPL return value. +GTNODE(RETFILT , GenTreeOp ,0,GTK_UNOP|GTK_NOVALUE) // End filter with TYP_I_IMPL return value. #if !defined(FEATURE_EH_FUNCLETS) -GTNODE(END_LFIN , GenTreeVal ,0,(GTK_LEAF|GTK_NOVALUE)) // End locally-invoked finally. +GTNODE(END_LFIN , GenTreeVal ,0,GTK_LEAF|GTK_NOVALUE) // End locally-invoked finally. #endif // !FEATURE_EH_FUNCLETS //----------------------------------------------------------------------------- // Nodes used by Lower to generate a closer CPU representation of other nodes //----------------------------------------------------------------------------- -#ifdef TARGET_ARM64 -GTNODE(MADD , GenTreeOp ,0, GTK_BINOP|DBK_NOTHIR) // Generates the Multiply-Add instruction (madd/msub) - // In future, we might consider enabling it for both armarch and xarch - // for floating-point MADD "unsafe" math -#endif -GTNODE(JMPTABLE , GenTree ,0, (GTK_LEAF|GTK_NOCONTAIN|DBK_NOTHIR)) // Generates the jump table for switches -GTNODE(SWITCH_TABLE , GenTreeOp ,0, (GTK_BINOP|GTK_NOVALUE|DBK_NOTHIR)) // Jump Table based switch construct -#ifdef TARGET_ARM64 -GTNODE(ADDEX, GenTreeOp ,0, GTK_BINOP|DBK_NOTHIR) // Add with sign/zero extension -GTNODE(BFIZ , GenTreeOp ,0, GTK_BINOP|DBK_NOTHIR) // Bitfield Insert in Zero -#endif +GTNODE(JMPTABLE , GenTree ,0,GTK_LEAF|GTK_NOCONTAIN|DBK_NOTHIR) // Generates the jump table for switches +GTNODE(SWITCH_TABLE , GenTreeOp ,0,GTK_BINOP|GTK_NOVALUE|DBK_NOTHIR) // Jump Table based switch construct //----------------------------------------------------------------------------- // Nodes used only within the code generator: //----------------------------------------------------------------------------- -GTNODE(CLS_VAR , GenTreeClsVar ,0,GTK_LEAF) // static data member GTNODE(CLS_VAR_ADDR , GenTreeClsVar ,0,GTK_LEAF|DBK_NOTHIR) // static data member address -GTNODE(ARGPLACE , GenTreeArgPlace ,0,GTK_LEAF|GTK_NOVALUE|GTK_NOTLIR) // placeholder for a register arg -GTNODE(NULLCHECK , GenTreeIndir ,0,GTK_UNOP|GTK_NOVALUE) // null checks the source GTNODE(PHYSREG , GenTreePhysReg ,0,GTK_LEAF|DBK_NOTHIR) // read from a physical register GTNODE(EMITNOP , GenTree ,0,GTK_LEAF|GTK_NOVALUE|DBK_NOTHIR) // emitter-placed nop GTNODE(PINVOKE_PROLOG , GenTree ,0,GTK_LEAF|GTK_NOVALUE|DBK_NOTHIR) // pinvoke prolog seq GTNODE(PINVOKE_EPILOG , GenTree ,0,GTK_LEAF|GTK_NOVALUE|DBK_NOTHIR) // pinvoke epilog seq +GTNODE(RETURNTRAP , GenTreeOp ,0,GTK_UNOP|GTK_NOVALUE|DBK_NOTHIR) // a conditional call to wait on gc #if defined(TARGET_ARM) GTNODE(PUTARG_REG , GenTreeMultiRegOp ,0,GTK_UNOP|DBK_NOTHIR) // operator that places outgoing arg in register #else GTNODE(PUTARG_REG , GenTreeOp ,0,GTK_UNOP|DBK_NOTHIR) // operator that places outgoing arg in register #endif -GTNODE(PUTARG_TYPE , GenTreeOp ,0,GTK_UNOP|GTK_NOTLIR) // operator that saves argument type between importation and morph GTNODE(PUTARG_STK , GenTreePutArgStk ,0,GTK_UNOP|GTK_NOVALUE|DBK_NOTHIR) // operator that places outgoing arg in stack #if FEATURE_ARG_SPLIT GTNODE(PUTARG_SPLIT , GenTreePutArgSplit ,0,GTK_UNOP|DBK_NOTHIR) // operator that places outgoing arg in registers with stack (split struct in ARM32) #endif // FEATURE_ARG_SPLIT -GTNODE(RETURNTRAP , GenTreeOp ,0,GTK_UNOP|GTK_NOVALUE|DBK_NOTHIR) // a conditional call to wait on gc GTNODE(SWAP , GenTreeOp ,0,GTK_BINOP|GTK_NOVALUE|DBK_NOTHIR) // op1 and op2 swap (registers) +GTNODE(COPY , GenTreeCopyOrReload,0,GTK_UNOP|DBK_NOTHIR) // Copies a variable from its current location to a register that satisfies +GTNODE(RELOAD , GenTreeCopyOrReload,0,GTK_UNOP|DBK_NOTHIR) // code generation constraints. The operand is the actual lclVar node. GTNODE(IL_OFFSET , GenTreeILOffset ,0,GTK_LEAF|GTK_NOVALUE|DBK_NOTHIR) // marks an IL offset for debugging purposes /*****************************************************************************/ From 06259c2b6491d4dc43c863a9d6b18a5891b4f47f Mon Sep 17 00:00:00 2001 From: SingleAccretion Date: Sat, 29 Jan 2022 19:08:35 +0300 Subject: [PATCH 3/6] Remove redundant asserts --- src/coreclr/jit/assertionprop.cpp | 5 ----- src/coreclr/jit/valuenum.cpp | 4 ---- 2 files changed, 9 deletions(-) diff --git a/src/coreclr/jit/assertionprop.cpp b/src/coreclr/jit/assertionprop.cpp index 4e0e708be326c6..dd3f0907af8e60 100644 --- a/src/coreclr/jit/assertionprop.cpp +++ b/src/coreclr/jit/assertionprop.cpp @@ -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; diff --git a/src/coreclr/jit/valuenum.cpp b/src/coreclr/jit/valuenum.cpp index 4be6e1a93a4cdb..8243764c11b394 100644 --- a/src/coreclr/jit/valuenum.cpp +++ b/src/coreclr/jit/valuenum.cpp @@ -9062,10 +9062,6 @@ void Compiler::fgValueNumberTree(GenTree* tree) } break; - case GT_LOCKADD: // Binop - noway_assert("LOCKADD should not appear before lowering"); - break; - case GT_XORR: // Binop case GT_XAND: // Binop case GT_XADD: // Binop From 2cf442525d18403814e333975bbe5f5b717a9440 Mon Sep 17 00:00:00 2001 From: SingleAccretion Date: Sat, 29 Jan 2022 19:39:41 +0300 Subject: [PATCH 4/6] GTK_NOTLIR -> DBK_NOTLIR There is not a lot of point in this being a "release" oper kind, as it is really only useful for debug checks. --- src/coreclr/jit/gentree.cpp | 4 ++-- src/coreclr/jit/gentree.h | 45 +++++++++++------------------------ src/coreclr/jit/gtlist.h | 28 +++++++++++----------- src/coreclr/jit/lir.cpp | 8 +++---- src/coreclr/jit/lsra.cpp | 2 +- src/coreclr/jit/lsrabuild.cpp | 6 ++--- 6 files changed, 38 insertions(+), 55 deletions(-) diff --git a/src/coreclr/jit/gentree.cpp b/src/coreclr/jit/gentree.cpp index ca5e674e3c5d3d..fcf3d627acc09c 100644 --- a/src/coreclr/jit/gentree.cpp +++ b/src/coreclr/jit/gentree.cpp @@ -15606,7 +15606,7 @@ unsigned GenTree::IsLclVarUpdateTree(GenTree** pOtherTree, genTreeOps* pOper) // Return value: returns true if it is possible to contain this node and false otherwise. bool GenTree::canBeContained() const { - assert(IsLIR()); + assert(OperIsLIR()); if (gtHasReg()) { @@ -15638,7 +15638,7 @@ bool GenTree::canBeContained() const // bool GenTree::isContained() const { - assert(IsLIR()); + assert(OperIsLIR()); const bool isMarkedContained = ((gtFlags & GTF_CONTAINED) != 0); #ifdef DEBUG diff --git a/src/coreclr/jit/gentree.h b/src/coreclr/jit/gentree.h index bb067f29a3d86e..613348773e90ef 100644 --- a/src/coreclr/jit/gentree.h +++ b/src/coreclr/jit/gentree.h @@ -99,8 +99,7 @@ enum GenTreeOperKind 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_NOCONTAIN = 0x40, // this node is a value, but may not be contained GTK_MASK = 0xFF }; @@ -114,7 +113,8 @@ enum GenTreeDebugOperKind { DBK_FIRST_FLAG = GTK_MASK + 1, - DBK_NOTHIR = DBK_FIRST_FLAG, // This oper is not supported in HIR (before rationalization). + DBK_NOTHIR = DBK_FIRST_FLAG, // This oper is not supported in HIR (before rationalization). + DBK_NOTLIR = DBK_FIRST_FLAG << 1, // This oper is not supported in LIR (after rationalization). DBK_MASK = ~GTK_MASK }; @@ -1089,34 +1089,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 // @@ -1713,6 +1685,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(); diff --git a/src/coreclr/jit/gtlist.h b/src/coreclr/jit/gtlist.h index 9574ae46e496ae..51cf6b95c2db94 100644 --- a/src/coreclr/jit/gtlist.h +++ b/src/coreclr/jit/gtlist.h @@ -36,10 +36,10 @@ GTNODE(CATCH_ARG , GenTree ,0,GTK_LEAF) // Excepti GTNODE(LABEL , GenTree ,0,GTK_LEAF) // Jump-target GTNODE(JMP , GenTreeVal ,0,GTK_LEAF|GTK_NOVALUE) // Jump to another function GTNODE(FTN_ADDR , GenTreeFptrVal ,0,GTK_LEAF) // Address of a function -GTNODE(RET_EXPR , GenTreeRetExpr ,0,GTK_LEAF|GTK_NOTLIR) // Place holder for the return expression from an inline candidate +GTNODE(RET_EXPR , GenTreeRetExpr ,0,GTK_LEAF|DBK_NOTLIR) // Place holder for the return expression from an inline candidate GTNODE(CLS_VAR , GenTreeClsVar ,0,GTK_LEAF) // Static data member -GTNODE(ARGPLACE , GenTreeArgPlace ,0,GTK_LEAF|GTK_NOVALUE|GTK_NOTLIR) // Placeholder for a "late arg" in the original arg list. +GTNODE(ARGPLACE , GenTreeArgPlace ,0,GTK_LEAF|GTK_NOVALUE|DBK_NOTLIR) // Placeholder for a "late arg" in the original arg list. //----------------------------------------------------------------------------- // Constant nodes: @@ -79,7 +79,7 @@ GTNODE(BITCAST , GenTreeOp ,0,GTK_UNOP) // reint GTNODE(CKFINITE , GenTreeOp ,0,GTK_UNOP|GTK_NOCONTAIN) // Check for NaN GTNODE(LCLHEAP , GenTreeOp ,0,GTK_UNOP|GTK_NOCONTAIN) // alloca() -GTNODE(ADDR , GenTreeOp ,0,GTK_UNOP|GTK_NOTLIR) // address of +GTNODE(ADDR , GenTreeOp ,0,GTK_UNOP|DBK_NOTLIR) // address of GTNODE(BOUNDS_CHECK , GenTreeBoundsChk ,0,GTK_BINOP|GTK_EXOP|GTK_NOVALUE) // a bounds check - for arrays/spans/SIMDs/HWINTRINSICs @@ -93,14 +93,14 @@ GTNODE(STORE_DYN_BLK , GenTreeStoreDynBlk ,0,GTK_SPECIAL|GTK_NOVALUE) GTNODE(NULLCHECK , GenTreeIndir ,0,GTK_UNOP|GTK_NOVALUE) // Null checks the source GTNODE(ARR_LENGTH , GenTreeArrLen ,0,GTK_UNOP|GTK_EXOP) -GTNODE(FIELD , GenTreeField ,0,GTK_UNOP|GTK_EXOP|GTK_NOTLIR) // Member-field -GTNODE(ALLOCOBJ , GenTreeAllocObj ,0,GTK_UNOP|GTK_EXOP|GTK_NOTLIR) // object allocator +GTNODE(FIELD , GenTreeField ,0,GTK_UNOP|GTK_EXOP|DBK_NOTLIR) // Member-field +GTNODE(ALLOCOBJ , GenTreeAllocObj ,0,GTK_UNOP|GTK_EXOP|DBK_NOTLIR) // object allocator GTNODE(INIT_VAL , GenTreeOp ,0,GTK_UNOP) // Initialization value for an initBlk -GTNODE(BOX , GenTreeBox ,0,GTK_UNOP|GTK_EXOP|GTK_NOTLIR) // Marks its first operands (a local) as being a box -GTNODE(PUTARG_TYPE , GenTreeOp ,0,GTK_UNOP|GTK_NOTLIR) // Saves argument type between importation and morph -GTNODE(RUNTIMELOOKUP , GenTreeRuntimeLookup, 0,GTK_UNOP|GTK_EXOP|GTK_NOTLIR) // Runtime handle lookup +GTNODE(BOX , GenTreeBox ,0,GTK_UNOP|GTK_EXOP|DBK_NOTLIR) // Marks its first operands (a local) as being a box +GTNODE(PUTARG_TYPE , GenTreeOp ,0,GTK_UNOP|DBK_NOTLIR) // Saves argument type between importation and morph +GTNODE(RUNTIMELOOKUP , GenTreeRuntimeLookup, 0,GTK_UNOP|GTK_EXOP|DBK_NOTLIR) // Runtime handle lookup GTNODE(BSWAP , GenTreeOp ,0,GTK_UNOP) // Byte swap (32-bit or 64-bit) GTNODE(BSWAP16 , GenTreeOp ,0,GTK_UNOP) // Byte swap (16-bit) @@ -128,7 +128,7 @@ GTNODE(RSZ , GenTreeOp ,0,GTK_BINOP) GTNODE(ROL , GenTreeOp ,0,GTK_BINOP) GTNODE(ROR , GenTreeOp ,0,GTK_BINOP) -GTNODE(ASG , GenTreeOp ,0,GTK_BINOP|GTK_NOTLIR) +GTNODE(ASG , GenTreeOp ,0,GTK_BINOP|DBK_NOTLIR) GTNODE(EQ , GenTreeOp ,0,GTK_BINOP) GTNODE(NE , GenTreeOp ,0,GTK_BINOP) GTNODE(LT , GenTreeOp ,0,GTK_BINOP) @@ -146,14 +146,14 @@ GTNODE(GT , GenTreeOp ,0,GTK_BINOP) GTNODE(TEST_EQ , GenTreeOp ,0,GTK_BINOP|DBK_NOTHIR) GTNODE(TEST_NE , GenTreeOp ,0,GTK_BINOP|DBK_NOTHIR) -GTNODE(COMMA , GenTreeOp ,0,GTK_BINOP|GTK_NOTLIR) -GTNODE(QMARK , GenTreeQmark ,0,GTK_BINOP|GTK_EXOP|GTK_NOTLIR) -GTNODE(COLON , GenTreeColon ,0,GTK_BINOP|GTK_NOTLIR) +GTNODE(COMMA , GenTreeOp ,0,GTK_BINOP|DBK_NOTLIR) +GTNODE(QMARK , GenTreeQmark ,0,GTK_BINOP|GTK_EXOP|DBK_NOTLIR) +GTNODE(COLON , GenTreeColon ,0,GTK_BINOP|DBK_NOTLIR) -GTNODE(INDEX , GenTreeIndex ,0,GTK_BINOP|GTK_EXOP|GTK_NOTLIR) // SZ-array-element. +GTNODE(INDEX , GenTreeIndex ,0,GTK_BINOP|GTK_EXOP|DBK_NOTLIR) // SZ-array-element. GTNODE(INDEX_ADDR , GenTreeIndexAddr ,0,GTK_BINOP|GTK_EXOP) // Addr of SZ-array-element; used when aiming to minimize compile times. -GTNODE(MKREFANY , GenTreeOp ,0,GTK_BINOP|GTK_NOTLIR) +GTNODE(MKREFANY , GenTreeOp ,0,GTK_BINOP|DBK_NOTLIR) GTNODE(LEA , GenTreeAddrMode ,0,GTK_BINOP|GTK_EXOP) #if !defined(TARGET_64BIT) diff --git a/src/coreclr/jit/lir.cpp b/src/coreclr/jit/lir.cpp index 2f5b762214ef17..93344854c5b1a4 100644 --- a/src/coreclr/jit/lir.cpp +++ b/src/coreclr/jit/lir.cpp @@ -1415,12 +1415,12 @@ class CheckLclVarSemanticsHelper { for (GenTree* operand : node->Operands()) { - if (!operand->IsLIR()) + // ARGPLACE nodes are not represented in the LIR sequence. Ignore them. + if (operand->OperIs(GT_ARGPLACE)) { - // ARGPLACE nodes are not represented in the LIR sequence. Ignore them. - assert(operand->OperIs(GT_ARGPLACE)); continue; } + if (operand->isContained()) { UseNodeOperands(operand); @@ -1524,7 +1524,7 @@ bool LIR::Range::CheckLIR(Compiler* compiler, bool checkUnusedValues) const for (Iterator node = begin(), end = this->end(); node != end; prev = *node, ++node) { // Verify that the node is allowed in LIR. - assert(node->IsLIR()); + assert(node->OperIsLIR()); // Some nodes should never be marked unused, as they must be contained in the backend. // These may be marked as unused during dead code elimination traversal, but they *must* be subsequently diff --git a/src/coreclr/jit/lsra.cpp b/src/coreclr/jit/lsra.cpp index 88f137ab65764d..73fd12e4690de2 100644 --- a/src/coreclr/jit/lsra.cpp +++ b/src/coreclr/jit/lsra.cpp @@ -9400,7 +9400,7 @@ void LinearScan::DumpOperandDefs( { assert(operand != nullptr); assert(operandString != nullptr); - if (!operand->IsLIR()) + if (operand->OperIs(GT_ARGPLACE)) { return; } diff --git a/src/coreclr/jit/lsrabuild.cpp b/src/coreclr/jit/lsrabuild.cpp index d58f1996091fae..5d020d9e3dc533 100644 --- a/src/coreclr/jit/lsrabuild.cpp +++ b/src/coreclr/jit/lsrabuild.cpp @@ -1619,12 +1619,12 @@ void LinearScan::buildUpperVectorRestoreRefPosition(Interval* lclVarInterval, Ls int LinearScan::ComputeOperandDstCount(GenTree* operand) { // GT_ARGPLACE is the only non-LIR node that is currently in the trees at this stage, though - // note that it is not in the linear order. It seems best to check for !IsLIR() rather than - // GT_ARGPLACE directly, since it's that characteristic that makes it irrelevant for this method. - if (!operand->IsLIR()) + // note that it is not in the linear order. + if (operand->OperIs(GT_ARGPLACE)) { return 0; } + if (operand->isContained()) { int dstCount = 0; From 98b25b2b3484de75008454343cba496eaafea6e6 Mon Sep 17 00:00:00 2001 From: SingleAccretion Date: Sun, 30 Jan 2022 00:31:56 +0300 Subject: [PATCH 5/6] GTK_NOCONTAIN -> DBK_NOCONTAIN --- src/coreclr/jit/gentree.cpp | 11 +++++++---- src/coreclr/jit/gentree.h | 10 ++++++---- src/coreclr/jit/gtlist.h | 10 +++++----- 3 files changed, 18 insertions(+), 13 deletions(-) diff --git a/src/coreclr/jit/gentree.cpp b/src/coreclr/jit/gentree.cpp index fcf3d627acc09c..c2e7a9be8b9b25 100644 --- a/src/coreclr/jit/gentree.cpp +++ b/src/coreclr/jit/gentree.cpp @@ -15599,11 +15599,14 @@ 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(OperIsLIR()); @@ -15613,15 +15616,15 @@ bool GenTree::canBeContained() const 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 diff --git a/src/coreclr/jit/gentree.h b/src/coreclr/jit/gentree.h index 613348773e90ef..c7036da0d30353 100644 --- a/src/coreclr/jit/gentree.h +++ b/src/coreclr/jit/gentree.h @@ -98,8 +98,7 @@ enum GenTreeOperKind 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_NOCONTAIN = 0x40, // this node is a value, but may not be contained + GTK_NOVALUE = 0x20, // node does not produce a value GTK_MASK = 0xFF }; @@ -113,8 +112,9 @@ enum GenTreeDebugOperKind { DBK_FIRST_FLAG = GTK_MASK + 1, - DBK_NOTHIR = DBK_FIRST_FLAG, // This oper is not supported in HIR (before rationalization). - DBK_NOTLIR = DBK_FIRST_FLAG << 1, // This oper is not supported in LIR (after rationalization). + DBK_NOTHIR = DBK_FIRST_FLAG, // This oper is not supported in HIR (before rationalization). + 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 }; @@ -895,7 +895,9 @@ struct GenTree // 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. +#ifdef DEBUG bool canBeContained() const; +#endif // for codegen purposes, is this node a subnode of its parent bool isContained() const; diff --git a/src/coreclr/jit/gtlist.h b/src/coreclr/jit/gtlist.h index 51cf6b95c2db94..1d0be8bd167664 100644 --- a/src/coreclr/jit/gtlist.h +++ b/src/coreclr/jit/gtlist.h @@ -55,7 +55,7 @@ GTNODE(CNS_STR , GenTreeStrCon ,0,GTK_LEAF) //----------------------------------------------------------------------------- GTNODE(NOT , GenTreeOp ,0,GTK_UNOP) -GTNODE(NOP , GenTree ,0,GTK_UNOP|GTK_NOCONTAIN) +GTNODE(NOP , GenTree ,0,GTK_UNOP|DBK_NOCONTAIN) GTNODE(NEG , GenTreeOp ,0,GTK_UNOP) GTNODE(INTRINSIC , GenTreeIntrinsic ,0,GTK_BINOP|GTK_EXOP) @@ -76,8 +76,8 @@ GTNODE(BITCAST , GenTreeMultiRegOp ,0,GTK_UNOP) // reint #else GTNODE(BITCAST , GenTreeOp ,0,GTK_UNOP) // reinterpretation of bits as another type #endif -GTNODE(CKFINITE , GenTreeOp ,0,GTK_UNOP|GTK_NOCONTAIN) // Check for NaN -GTNODE(LCLHEAP , GenTreeOp ,0,GTK_UNOP|GTK_NOCONTAIN) // alloca() +GTNODE(CKFINITE , GenTreeOp ,0,GTK_UNOP|DBK_NOCONTAIN) // Check for NaN +GTNODE(LCLHEAP , GenTreeOp ,0,GTK_UNOP|DBK_NOCONTAIN) // alloca() GTNODE(ADDR , GenTreeOp ,0,GTK_UNOP|DBK_NOTLIR) // address of @@ -256,7 +256,7 @@ GTNODE(JTRUE , GenTreeOp ,0,GTK_UNOP|GTK_NOVALUE) GTNODE(ARR_ELEM , GenTreeArrElem ,0,GTK_SPECIAL) // Multi-dimensional array-element address GTNODE(ARR_INDEX , GenTreeArrIndex ,0,GTK_BINOP|GTK_EXOP) // Effective, bounds-checked index for one dimension of a multi-dimensional array element GTNODE(ARR_OFFSET , GenTreeArrOffs ,0,GTK_SPECIAL) // Flattened offset of multi-dimensional array element -GTNODE(CALL , GenTreeCall ,0,GTK_SPECIAL|GTK_NOCONTAIN) +GTNODE(CALL , GenTreeCall ,0,GTK_SPECIAL|DBK_NOCONTAIN) GTNODE(FIELD_LIST , GenTreeFieldList ,0,GTK_SPECIAL) // List of fields of a struct, when passed as an argument GTNODE(RETURN , GenTreeOp ,0,GTK_UNOP|GTK_NOVALUE) @@ -276,7 +276,7 @@ GTNODE(END_LFIN , GenTreeVal ,0,GTK_LEAF|GTK_NOVALUE) // End loc // Nodes used by Lower to generate a closer CPU representation of other nodes //----------------------------------------------------------------------------- -GTNODE(JMPTABLE , GenTree ,0,GTK_LEAF|GTK_NOCONTAIN|DBK_NOTHIR) // Generates the jump table for switches +GTNODE(JMPTABLE , GenTree ,0,GTK_LEAF|DBK_NOCONTAIN|DBK_NOTHIR) // Generates the jump table for switches GTNODE(SWITCH_TABLE , GenTreeOp ,0,GTK_BINOP|GTK_NOVALUE|DBK_NOTHIR) // Jump Table based switch construct //----------------------------------------------------------------------------- From 61a26680e19a4f421a3841e759416090c101f2e7 Mon Sep 17 00:00:00 2001 From: SingleAccretion Date: Sun, 30 Jan 2022 01:27:20 +0300 Subject: [PATCH 6/6] Fix formatting... --- src/coreclr/jit/gentree.cpp | 4 ++-- src/coreclr/jit/gentree.h | 9 +++++---- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/coreclr/jit/gentree.cpp b/src/coreclr/jit/gentree.cpp index c2e7a9be8b9b25..ad05a1a45d774e 100644 --- a/src/coreclr/jit/gentree.cpp +++ b/src/coreclr/jit/gentree.cpp @@ -21,13 +21,13 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX /*****************************************************************************/ const unsigned char GenTree::gtOperKindTable[] = { -#define GTNODE(en, st, cm, ok) ((ok) & GTK_MASK) + GTK_COMMUTE *cm, +#define GTNODE(en, st, cm, ok) ((ok)>K_MASK) + GTK_COMMUTE *cm, #include "gtlist.h" }; #ifdef DEBUG const GenTreeDebugOperKind GenTree::gtDebugOperKindTable[] = { -#define GTNODE(en, st, cm, ok) static_cast((ok) & DBK_MASK), +#define GTNODE(en, st, cm, ok) static_cast((ok)&DBK_MASK), #include "gtlist.h" }; #endif // DEBUG diff --git a/src/coreclr/jit/gentree.h b/src/coreclr/jit/gentree.h index c7036da0d30353..46909dbd87194b 100644 --- a/src/coreclr/jit/gentree.h +++ b/src/coreclr/jit/gentree.h @@ -95,10 +95,10 @@ enum GenTreeOperKind 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_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 }; @@ -894,6 +894,7 @@ 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;