diff options
author | Pat Gavlin <pagavlin@microsoft.com> | 2017-02-24 11:19:27 -0800 |
---|---|---|
committer | Pat Gavlin <pagavlin@microsoft.com> | 2017-02-25 09:55:03 -0800 |
commit | 350020d9b6a2bda08cf2e416d959c1801a717734 (patch) | |
tree | 276a6fe1b5dbfc88c196b25bd95b2da2bad59f4f /src | |
parent | 3392356945aabd5a3ebac5317ff4a0e0361dc9ad (diff) | |
download | coreclr-350020d9b6a2bda08cf2e416d959c1801a717734.tar.gz coreclr-350020d9b6a2bda08cf2e416d959c1801a717734.tar.bz2 coreclr-350020d9b6a2bda08cf2e416d959c1801a717734.zip |
Refactor isContained().
This changes isContained to terminate early if it is not possible for the node in question
to ever be contained. There are many nodes that are statically non-containable: any node
that is not a value may not be contained along with a small number of value nodes. To avoid
the need for a `switch` to identify the latter, their node kinds have been marked with a
new flag, `GTK_NOCONTAIN`. The checks for identifying non-containable nodes are encapsulated
withing a new function, `canBeContained`.
Diffstat (limited to 'src')
-rw-r--r-- | src/jit/gentree.cpp | 92 | ||||
-rw-r--r-- | src/jit/gentree.h | 4 | ||||
-rw-r--r-- | src/jit/gtlist.h | 10 | ||||
-rw-r--r-- | src/jit/lower.cpp | 3 |
4 files changed, 41 insertions, 68 deletions
diff --git a/src/jit/gentree.cpp b/src/jit/gentree.cpp index 7af500f877..57c59085ef 100644 --- a/src/jit/gentree.cpp +++ b/src/jit/gentree.cpp @@ -15787,6 +15787,20 @@ unsigned GenTree::IsLclVarUpdateTree(GenTree** pOtherTree, genTreeOps* pOper) } //------------------------------------------------------------------------ +// 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. +bool GenTree::canBeContained() const +{ + assert(IsLIR()); + + // It is not possible for nodes that do not produce values or that are not containable values + // to be contained. + return (OperKind() & (GTK_NOVALUE | GTK_NOCONTAIN)) == 0; +} + +//------------------------------------------------------------------------ // isContained: check whether this tree node is a subcomponent of its parent for codegen purposes // // Return Value: @@ -15801,14 +15815,16 @@ unsigned GenTree::IsLclVarUpdateTree(GenTree** pOtherTree, genTreeOps* pOper) // bool GenTree::isContained() const { - if (gtHasReg()) + assert(IsLIR()); + + if (!canBeContained() || gtHasReg()) { return false; } // 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 - if (OperKind() & GTK_RELOP) + if ((OperKind() & GTK_RELOP) != 0) { return false; } @@ -15819,75 +15835,25 @@ bool GenTree::isContained() const return false; } - switch (OperGet()) - { - case GT_STOREIND: - case GT_JTRUE: - case GT_JCC: - case GT_RETURN: - case GT_RETFILT: - case GT_STORE_LCL_FLD: - case GT_STORE_LCL_VAR: - case GT_ARR_BOUNDS_CHECK: - case GT_LOCKADD: - case GT_NOP: - case GT_NO_OP: - case GT_START_NONGC: - case GT_PROF_HOOK: - case GT_RETURNTRAP: - case GT_COMMA: - case GT_PINVOKE_PROLOG: - case GT_PHYSREGDST: - case GT_PUTARG_STK: - case GT_MEMORYBARRIER: - case GT_STORE_BLK: - case GT_STORE_OBJ: - case GT_STORE_DYN_BLK: - case GT_SWITCH: -#ifndef LEGACY_BACKEND - case GT_JMPTABLE: -#endif - case GT_SWITCH_TABLE: - case GT_SWAP: - case GT_LCLHEAP: - case GT_CKFINITE: - case GT_JMP: - case GT_IL_OFFSET: -#ifdef FEATURE_SIMD - case GT_SIMD_CHK: -#endif // FEATURE_SIMD - -#if !FEATURE_EH_FUNCLETS - case GT_END_LFIN: -#endif - return false; - #if !defined(LEGACY_BACKEND) && !defined(_TARGET_64BIT_) - case GT_LONG: - // GT_LONG nodes are normally contained. The only exception is when the result - // of a TYP_LONG operation is not used and this can only happen if the GT_LONG - // is the last node in the statement (in linear order). - return gtNext != nullptr; + if (OperGet() == GT_LONG) + { + // GT_LONG nodes are normally contained. The only exception is when the result + // of a TYP_LONG operation is not used and this can only happen if the GT_LONG + // is the last node in the statement (in linear order). + return gtNext != nullptr; + } #endif - case GT_CALL: - // Note: if you hit this assert you are probably calling isContained() - // before the LSRA phase has allocated physical register to the tree nodes - // - assert(gtType == TYP_VOID); - return false; - - default: - // if it's contained it better have a parent - assert(gtNext || OperIsLocal()); - return true; - } + // if it's contained it better have a user + assert((gtNext != nullptr) || OperIsLocal()); + return true; } // return true if node is contained and an indir bool GenTree::isContainedIndir() const { - return isContained() && isIndir(); + return isIndir() && isContained(); } bool GenTree::isIndirAddrMode() diff --git a/src/jit/gentree.h b/src/jit/gentree.h index eaca7a097d..cd1034de21 100644 --- a/src/jit/gentree.h +++ b/src/jit/gentree.h @@ -120,6 +120,8 @@ enum genTreeKinds GTK_NOVALUE = 0x0400, // node does not produce a value GTK_NOTLIR = 0x0800, // node is not allowed in LIR + 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) @@ -555,6 +557,8 @@ public: __declspec(property(get = GetRegNum, put = SetRegNum)) regNumber gtRegNum; + bool canBeContained() const; + // for codegen purposes, is this node a subnode of its parent bool isContained() const; diff --git a/src/jit/gtlist.h b/src/jit/gtlist.h index 2d9255b6ce..826eaf1207 100644 --- a/src/jit/gtlist.h +++ b/src/jit/gtlist.h @@ -46,7 +46,7 @@ GTNODE(CNS_STR , "sconst" ,GenTreeStrCon ,0,GTK_LEAF|GTK_CON //----------------------------------------------------------------------------- GTNODE(NOT , "~" ,GenTreeOp ,0,GTK_UNOP) -GTNODE(NOP , "nop" ,GenTree ,0,GTK_UNOP) +GTNODE(NOP , "nop" ,GenTree ,0,GTK_UNOP|GTK_NOCONTAIN) GTNODE(NEG , "unary -" ,GenTreeOp ,0,GTK_UNOP) GTNODE(COPY , "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. @@ -65,8 +65,8 @@ GTNODE(CMPXCHG , "cmpxchg" ,GenTreeCmpXchg ,0,GTK_SPECIAL) GTNODE(MEMORYBARRIER , "memoryBarrier",GenTree ,0,GTK_LEAF|GTK_NOVALUE) GTNODE(CAST , "cast" ,GenTreeCast ,0,GTK_UNOP|GTK_EXOP) // conversion to another type -GTNODE(CKFINITE , "ckfinite" ,GenTreeOp ,0,GTK_UNOP) // Check for NaN -GTNODE(LCLHEAP , "lclHeap" ,GenTreeOp ,0,GTK_UNOP) // alloca() +GTNODE(CKFINITE , "ckfinite" ,GenTreeOp ,0,GTK_UNOP|GTK_NOCONTAIN) // Check for NaN +GTNODE(LCLHEAP , "lclHeap" ,GenTreeOp ,0,GTK_UNOP|GTK_NOCONTAIN) // alloca() GTNODE(JMP , "jump" ,GenTreeVal ,0,GTK_LEAF|GTK_NOVALUE) // Jump to another function GTNODE(ADDR , "addr" ,GenTreeOp ,0,GTK_UNOP) // address of @@ -226,7 +226,7 @@ GTNODE(FIELD , "field" ,GenTreeField ,0,GTK_SPECIAL) GTNODE(ARR_ELEM , "arrMD&" ,GenTreeArrElem ,0,GTK_SPECIAL) // Multi-dimensional array-element address GTNODE(ARR_INDEX , "arrMDIdx" ,GenTreeArrIndex ,0,GTK_BINOP|GTK_EXOP) // Effective, bounds-checked index for one dimension of a multi-dimensional array element GTNODE(ARR_OFFSET , "arrMDOffs" ,GenTreeArrOffs ,0,GTK_SPECIAL) // Flattened offset of multi-dimensional array element -GTNODE(CALL , "call()" ,GenTreeCall ,0,GTK_SPECIAL) +GTNODE(CALL , "call()" ,GenTreeCall ,0,GTK_SPECIAL|GTK_NOCONTAIN) //----------------------------------------------------------------------------- // Statement operator nodes: @@ -261,7 +261,7 @@ GTNODE(PHI_ARG , "phiArg" ,GenTreePhiArg ,0,GTK_LEAF|GTK_LOC //----------------------------------------------------------------------------- #ifndef LEGACY_BACKEND -GTNODE(JMPTABLE , "jumpTable" ,GenTreeJumpTable ,0, GTK_LEAF) // Generates the jump table for switches +GTNODE(JMPTABLE , "jumpTable" ,GenTreeJumpTable ,0, GTK_LEAF|GTK_NOCONTAIN) // Generates the jump table for switches #endif GTNODE(SWITCH_TABLE , "tableSwitch" ,GenTreeOp ,0, GTK_BINOP|GTK_NOVALUE) // Jump Table based switch construct diff --git a/src/jit/lower.cpp b/src/jit/lower.cpp index 2113e08aa3..33931c6d92 100644 --- a/src/jit/lower.cpp +++ b/src/jit/lower.cpp @@ -42,9 +42,12 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX void Lowering::MakeSrcContained(GenTreePtr parentNode, GenTreePtr childNode) { assert(!parentNode->OperIsLeaf()); + assert(childNode->canBeContained()); + int srcCount = childNode->gtLsraInfo.srcCount; assert(srcCount >= 0); m_lsra->clearOperandCounts(childNode); + assert(parentNode->gtLsraInfo.srcCount > 0); parentNode->gtLsraInfo.srcCount += srcCount - 1; } |