mirror of
https://github.com/VSadov/Satori.git
synced 2025-06-12 02:30:29 +09:00
Save 260k in InitValueNumStoreStatics (#85945)
It appears that the big #define for the intrinsics is causing InitValueNumStoreStatics to get big enough that C++ optimization ends up being disabled, which means a lot of constant operations aren't folded. This rewrites it as a const table. It adds some redundant information to the tables that we #include/#define in several places but currently includes many assertions that the old and new values match. Local size change of release clrjit_win_x64_x64.dll: 2,001,920 -> 1,735,680. InitValueNumStoreStatics (261k) is replaced by 1.2k of static data. Resolves #85953
This commit is contained in:
parent
2bf8f1aa83
commit
9f8f6531b7
12 changed files with 2184 additions and 2106 deletions
|
@ -1329,7 +1329,7 @@ void Compiler::compStartup()
|
|||
emitter::emitInit();
|
||||
|
||||
// Static vars of ValueNumStore
|
||||
ValueNumStore::InitValueNumStoreStatics();
|
||||
ValueNumStore::ValidateValueNumStoreStatics();
|
||||
|
||||
compDisplayStaticSizes(jitstdout);
|
||||
}
|
||||
|
|
|
@ -21,13 +21,13 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
|||
/*****************************************************************************/
|
||||
|
||||
const unsigned char GenTree::gtOperKindTable[] = {
|
||||
#define GTNODE(en, st, cm, ok) ((ok)>K_MASK) + GTK_COMMUTE *cm,
|
||||
#define GTNODE(en, st, cm, ivn, ok) ((ok)>K_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),
|
||||
#define GTNODE(en, st, cm, ivn, ok) static_cast<GenTreeDebugOperKind>((ok)&DBK_MASK),
|
||||
#include "gtlist.h"
|
||||
};
|
||||
#endif // DEBUG
|
||||
|
@ -171,7 +171,7 @@ static void printIndent(IndentStack* indentStack)
|
|||
#if defined(DEBUG) || NODEBASH_STATS || MEASURE_NODE_SIZE || COUNT_AST_OPERS || DUMP_FLOWGRAPHS
|
||||
|
||||
static const char* opNames[] = {
|
||||
#define GTNODE(en, st, cm, ok) #en,
|
||||
#define GTNODE(en, st, cm, ivn, ok) #en,
|
||||
#include "gtlist.h"
|
||||
};
|
||||
|
||||
|
@ -187,7 +187,7 @@ const char* GenTree::OpName(genTreeOps op)
|
|||
#if MEASURE_NODE_SIZE
|
||||
|
||||
static const char* opStructNames[] = {
|
||||
#define GTNODE(en, st, cm, ok) #st,
|
||||
#define GTNODE(en, st, cm, ivn, ok) #st,
|
||||
#include "gtlist.h"
|
||||
};
|
||||
|
||||
|
@ -214,7 +214,7 @@ unsigned char GenTree::s_gtNodeSizes[GT_COUNT + 1];
|
|||
#if NODEBASH_STATS || MEASURE_NODE_SIZE || COUNT_AST_OPERS
|
||||
|
||||
unsigned char GenTree::s_gtTrueSizes[GT_COUNT + 1]{
|
||||
#define GTNODE(en, st, cm, ok) sizeof(st),
|
||||
#define GTNODE(en, st, cm, ivn, ok) sizeof(st),
|
||||
#include "gtlist.h"
|
||||
};
|
||||
|
||||
|
|
|
@ -1087,7 +1087,7 @@ public:
|
|||
return TypeIs(type) || TypeIs(rest...);
|
||||
}
|
||||
|
||||
static bool StaticOperIs(genTreeOps operCompare, genTreeOps oper)
|
||||
static constexpr bool StaticOperIs(genTreeOps operCompare, genTreeOps oper)
|
||||
{
|
||||
return operCompare == oper;
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
enum genTreeOps : BYTE
|
||||
{
|
||||
#define GTNODE(en, st, cm, ok) GT_##en,
|
||||
#define GTNODE(en, st, cm, ivn, ok) GT_##en,
|
||||
#include "gtlist.h"
|
||||
|
||||
GT_COUNT,
|
||||
|
|
|
@ -11,164 +11,165 @@
|
|||
// Node enum
|
||||
// , GenTree struct flavor
|
||||
// ,commutative
|
||||
// ,oper kind | DEBUG oper kind
|
||||
// ,illegal as VN func
|
||||
// ,oper kind | DEBUG oper kind
|
||||
|
||||
GTNODE(NONE , char ,0,GTK_SPECIAL)
|
||||
GTNODE(NONE , char ,0,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_EXOP|GTK_NOVALUE|GTK_STORE) // store to local variable
|
||||
GTNODE(STORE_LCL_FLD , GenTreeLclFld ,0,GTK_UNOP|GTK_EXOP|GTK_NOVALUE|GTK_STORE) // store to a part of the variable
|
||||
GTNODE(LCL_ADDR , GenTreeLclFld ,0,GTK_LEAF) // local address
|
||||
GTNODE(PHI , GenTreePhi ,0,0,GTK_SPECIAL) // phi node for ssa.
|
||||
GTNODE(PHI_ARG , GenTreePhiArg ,0,0,GTK_LEAF) // phi(phiarg, phiarg, phiarg)
|
||||
GTNODE(LCL_VAR , GenTreeLclVar ,0,0,GTK_LEAF) // local variable
|
||||
GTNODE(LCL_FLD , GenTreeLclFld ,0,0,GTK_LEAF) // field in a non-primitive variable
|
||||
GTNODE(STORE_LCL_VAR , GenTreeLclVar ,0,1,GTK_UNOP|GTK_EXOP|GTK_NOVALUE|GTK_STORE) // store to local variable
|
||||
GTNODE(STORE_LCL_FLD , GenTreeLclFld ,0,1,GTK_UNOP|GTK_EXOP|GTK_NOVALUE|GTK_STORE) // store to a part of the variable
|
||||
GTNODE(LCL_ADDR , GenTreeLclFld ,0,0,GTK_LEAF) // local address
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// 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(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|DBK_NOTLIR) // Place holder for the return expression from an inline candidate
|
||||
GTNODE(CATCH_ARG , GenTree ,0,0,GTK_LEAF) // Exception object in a catch block
|
||||
GTNODE(LABEL , GenTree ,0,0,GTK_LEAF) // Jump-target
|
||||
GTNODE(JMP , GenTreeVal ,0,0,GTK_LEAF|GTK_NOVALUE) // Jump to another function
|
||||
GTNODE(FTN_ADDR , GenTreeFptrVal ,0,0,GTK_LEAF) // Address of a function
|
||||
GTNODE(RET_EXPR , GenTreeRetExpr ,0,0,GTK_LEAF|DBK_NOTLIR) // Place holder for the return expression from an inline candidate
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Constant nodes:
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
GTNODE(CNS_INT , GenTreeIntCon ,0,GTK_LEAF)
|
||||
GTNODE(CNS_LNG , GenTreeLngCon ,0,GTK_LEAF)
|
||||
GTNODE(CNS_DBL , GenTreeDblCon ,0,GTK_LEAF)
|
||||
GTNODE(CNS_STR , GenTreeStrCon ,0,GTK_LEAF)
|
||||
GTNODE(CNS_VEC , GenTreeVecCon ,0,GTK_LEAF)
|
||||
GTNODE(CNS_INT , GenTreeIntCon ,0,0,GTK_LEAF)
|
||||
GTNODE(CNS_LNG , GenTreeLngCon ,0,0,GTK_LEAF)
|
||||
GTNODE(CNS_DBL , GenTreeDblCon ,0,0,GTK_LEAF)
|
||||
GTNODE(CNS_STR , GenTreeStrCon ,0,0,GTK_LEAF)
|
||||
GTNODE(CNS_VEC , GenTreeVecCon ,0,0,GTK_LEAF)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Unary operators (1 operand):
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
GTNODE(NOT , GenTreeOp ,0,GTK_UNOP)
|
||||
GTNODE(NOP , GenTree ,0,GTK_UNOP|DBK_NOCONTAIN)
|
||||
GTNODE(NEG , GenTreeOp ,0,GTK_UNOP)
|
||||
GTNODE(NOT , GenTreeOp ,0,0,GTK_UNOP)
|
||||
GTNODE(NOP , GenTree ,0,0,GTK_UNOP|DBK_NOCONTAIN)
|
||||
GTNODE(NEG , GenTreeOp ,0,0,GTK_UNOP)
|
||||
|
||||
GTNODE(INTRINSIC , GenTreeIntrinsic ,0,GTK_BINOP|GTK_EXOP)
|
||||
GTNODE(INTRINSIC , GenTreeIntrinsic ,0,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)
|
||||
GTNODE(XCHG , GenTreeOp ,0,GTK_BINOP)
|
||||
GTNODE(CMPXCHG , GenTreeCmpXchg ,0,GTK_SPECIAL)
|
||||
GTNODE(MEMORYBARRIER , GenTree ,0,GTK_LEAF|GTK_NOVALUE)
|
||||
GTNODE(LOCKADD , GenTreeOp ,0,1,GTK_BINOP|GTK_NOVALUE|DBK_NOTHIR)
|
||||
GTNODE(XAND , GenTreeOp ,0,1,GTK_BINOP)
|
||||
GTNODE(XORR , GenTreeOp ,0,1,GTK_BINOP)
|
||||
GTNODE(XADD , GenTreeOp ,0,1,GTK_BINOP)
|
||||
GTNODE(XCHG , GenTreeOp ,0,1,GTK_BINOP)
|
||||
GTNODE(CMPXCHG , GenTreeCmpXchg ,0,1,GTK_SPECIAL)
|
||||
GTNODE(MEMORYBARRIER , GenTree ,0,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,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,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
|
||||
GTNODE(BITCAST , GenTreeMultiRegOp ,0,1,GTK_UNOP) // reinterpretation of bits as another type
|
||||
#else
|
||||
GTNODE(BITCAST , GenTreeOp ,0,GTK_UNOP) // reinterpretation of bits as another type
|
||||
GTNODE(BITCAST , GenTreeOp ,0,1,GTK_UNOP) // reinterpretation of bits as another type
|
||||
#endif
|
||||
GTNODE(CKFINITE , GenTreeOp ,0,GTK_UNOP|DBK_NOCONTAIN) // Check for NaN
|
||||
GTNODE(LCLHEAP , GenTreeOp ,0,GTK_UNOP|DBK_NOCONTAIN) // alloca()
|
||||
GTNODE(CKFINITE , GenTreeOp ,0,1,GTK_UNOP|DBK_NOCONTAIN) // Check for NaN
|
||||
GTNODE(LCLHEAP , GenTreeOp ,0,1,GTK_UNOP|DBK_NOCONTAIN) // alloca()
|
||||
|
||||
GTNODE(BOUNDS_CHECK , GenTreeBoundsChk ,0,GTK_BINOP|GTK_EXOP|GTK_NOVALUE) // a bounds check - for arrays/spans/SIMDs/HWINTRINSICs
|
||||
GTNODE(BOUNDS_CHECK , GenTreeBoundsChk ,0,1,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_EXOP|GTK_NOVALUE|GTK_STORE) // Store indirection
|
||||
GTNODE(BLK , GenTreeBlk ,0,GTK_UNOP|GTK_EXOP) // Struct load
|
||||
GTNODE(STORE_BLK , GenTreeBlk ,0,GTK_BINOP|GTK_EXOP|GTK_NOVALUE|GTK_STORE) // Struct store
|
||||
GTNODE(STORE_DYN_BLK , GenTreeStoreDynBlk ,0,GTK_SPECIAL|GTK_NOVALUE) // Dynamically sized block store, with native uint size
|
||||
GTNODE(NULLCHECK , GenTreeIndir ,0,GTK_UNOP|GTK_NOVALUE) // Null checks the source
|
||||
GTNODE(IND , GenTreeIndir ,0,1,GTK_UNOP) // Load indirection
|
||||
GTNODE(STOREIND , GenTreeStoreInd ,0,1,GTK_BINOP|GTK_EXOP|GTK_NOVALUE|GTK_STORE) // Store indirection
|
||||
GTNODE(BLK , GenTreeBlk ,0,1,GTK_UNOP|GTK_EXOP) // Struct load
|
||||
GTNODE(STORE_BLK , GenTreeBlk ,0,1,GTK_BINOP|GTK_EXOP|GTK_NOVALUE|GTK_STORE) // Struct store
|
||||
GTNODE(STORE_DYN_BLK , GenTreeStoreDynBlk ,0,1,GTK_SPECIAL|GTK_NOVALUE) // Dynamically sized block store, with native uint size
|
||||
GTNODE(NULLCHECK , GenTreeIndir ,0,1,GTK_UNOP|GTK_NOVALUE) // Null checks the source
|
||||
|
||||
GTNODE(ARR_LENGTH , GenTreeArrLen ,0,GTK_UNOP|GTK_EXOP) // single-dimension (SZ) array length
|
||||
GTNODE(MDARR_LENGTH , GenTreeMDArr ,0,GTK_UNOP|GTK_EXOP) // multi-dimension (MD) array length of a specific dimension
|
||||
GTNODE(MDARR_LOWER_BOUND, GenTreeMDArr ,0,GTK_UNOP|GTK_EXOP) // multi-dimension (MD) array lower bound of a specific dimension
|
||||
GTNODE(FIELD_ADDR , GenTreeFieldAddr ,0,GTK_UNOP|GTK_EXOP|DBK_NOTLIR) // Field address
|
||||
GTNODE(ALLOCOBJ , GenTreeAllocObj ,0,GTK_UNOP|GTK_EXOP|DBK_NOTLIR) // object allocator
|
||||
GTNODE(ARR_LENGTH , GenTreeArrLen ,0,0,GTK_UNOP|GTK_EXOP) // single-dimension (SZ) array length
|
||||
GTNODE(MDARR_LENGTH , GenTreeMDArr ,0,1,GTK_UNOP|GTK_EXOP) // multi-dimension (MD) array length of a specific dimension
|
||||
GTNODE(MDARR_LOWER_BOUND, GenTreeMDArr ,0,1,GTK_UNOP|GTK_EXOP) // multi-dimension (MD) array lower bound of a specific dimension
|
||||
GTNODE(FIELD_ADDR , GenTreeFieldAddr ,0,0,GTK_UNOP|GTK_EXOP|DBK_NOTLIR) // Field address
|
||||
GTNODE(ALLOCOBJ , GenTreeAllocObj ,0,0,GTK_UNOP|GTK_EXOP|DBK_NOTLIR) // object allocator
|
||||
|
||||
GTNODE(INIT_VAL , GenTreeOp ,0,GTK_UNOP) // Initialization value for an initBlk
|
||||
GTNODE(INIT_VAL , GenTreeOp ,0,1,GTK_UNOP) // Initialization value for an initBlk
|
||||
|
||||
GTNODE(BOX , GenTreeBox ,0,GTK_UNOP|GTK_EXOP|DBK_NOTLIR) // Marks its first operands (a local) as being a box
|
||||
GTNODE(RUNTIMELOOKUP , GenTreeRuntimeLookup, 0,GTK_UNOP|GTK_EXOP|DBK_NOTLIR) // Runtime handle lookup
|
||||
GTNODE(ARR_ADDR , GenTreeArrAddr ,0,GTK_UNOP|GTK_EXOP|DBK_NOTLIR) // Wraps an array address expression
|
||||
GTNODE(BOX , GenTreeBox ,0,1,GTK_UNOP|GTK_EXOP|DBK_NOTLIR) // Marks its first operands (a local) as being a box
|
||||
GTNODE(RUNTIMELOOKUP , GenTreeRuntimeLookup, 0,0,GTK_UNOP|GTK_EXOP|DBK_NOTLIR) // Runtime handle lookup
|
||||
GTNODE(ARR_ADDR , GenTreeArrAddr ,0,1,GTK_UNOP|GTK_EXOP|DBK_NOTLIR) // Wraps an array address expression
|
||||
|
||||
GTNODE(BSWAP , GenTreeOp ,0,GTK_UNOP) // Byte swap (32-bit or 64-bit)
|
||||
GTNODE(BSWAP16 , GenTreeOp ,0,GTK_UNOP) // Byte swap lower 16-bits and zero upper 16 bits
|
||||
GTNODE(BSWAP , GenTreeOp ,0,0,GTK_UNOP) // Byte swap (32-bit or 64-bit)
|
||||
GTNODE(BSWAP16 , GenTreeOp ,0,0,GTK_UNOP) // Byte swap lower 16-bits and zero upper 16 bits
|
||||
|
||||
GTNODE(LZCNT , GenTreeOp ,0,GTK_UNOP) // Leading Zero Count - Only used for SIMD VN evaluation today
|
||||
GTNODE(LZCNT , GenTreeOp ,0,0,GTK_UNOP) // Leading Zero Count - Only used for SIMD VN evaluation today
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Binary operators (2 operands):
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
GTNODE(ADD , GenTreeOp ,1,GTK_BINOP)
|
||||
GTNODE(SUB , GenTreeOp ,0,GTK_BINOP)
|
||||
GTNODE(MUL , GenTreeOp ,1,GTK_BINOP)
|
||||
GTNODE(DIV , GenTreeOp ,0,GTK_BINOP)
|
||||
GTNODE(MOD , GenTreeOp ,0,GTK_BINOP)
|
||||
GTNODE(ADD , GenTreeOp ,1,0,GTK_BINOP)
|
||||
GTNODE(SUB , GenTreeOp ,0,0,GTK_BINOP)
|
||||
GTNODE(MUL , GenTreeOp ,1,0,GTK_BINOP)
|
||||
GTNODE(DIV , GenTreeOp ,0,0,GTK_BINOP)
|
||||
GTNODE(MOD , GenTreeOp ,0,0,GTK_BINOP)
|
||||
|
||||
GTNODE(UDIV , GenTreeOp ,0,GTK_BINOP)
|
||||
GTNODE(UMOD , GenTreeOp ,0,GTK_BINOP)
|
||||
GTNODE(UDIV , GenTreeOp ,0,0,GTK_BINOP)
|
||||
GTNODE(UMOD , GenTreeOp ,0,0,GTK_BINOP)
|
||||
|
||||
GTNODE(OR , GenTreeOp ,1,GTK_BINOP)
|
||||
GTNODE(XOR , GenTreeOp ,1,GTK_BINOP)
|
||||
GTNODE(AND , GenTreeOp ,1,GTK_BINOP)
|
||||
GTNODE(OR , GenTreeOp ,1,0,GTK_BINOP)
|
||||
GTNODE(XOR , GenTreeOp ,1,0,GTK_BINOP)
|
||||
GTNODE(AND , GenTreeOp ,1,0,GTK_BINOP)
|
||||
|
||||
GTNODE(LSH , GenTreeOp ,0,GTK_BINOP)
|
||||
GTNODE(RSH , GenTreeOp ,0,GTK_BINOP)
|
||||
GTNODE(RSZ , GenTreeOp ,0,GTK_BINOP)
|
||||
GTNODE(ROL , GenTreeOp ,0,GTK_BINOP)
|
||||
GTNODE(ROR , GenTreeOp ,0,GTK_BINOP)
|
||||
GTNODE(LSH , GenTreeOp ,0,0,GTK_BINOP)
|
||||
GTNODE(RSH , GenTreeOp ,0,0,GTK_BINOP)
|
||||
GTNODE(RSZ , GenTreeOp ,0,0,GTK_BINOP)
|
||||
GTNODE(ROL , GenTreeOp ,0,0,GTK_BINOP)
|
||||
GTNODE(ROR , GenTreeOp ,0,0,GTK_BINOP)
|
||||
|
||||
GTNODE(EQ , GenTreeOp ,0,GTK_BINOP)
|
||||
GTNODE(NE , GenTreeOp ,0,GTK_BINOP)
|
||||
GTNODE(LT , GenTreeOp ,0,GTK_BINOP)
|
||||
GTNODE(LE , GenTreeOp ,0,GTK_BINOP)
|
||||
GTNODE(GE , GenTreeOp ,0,GTK_BINOP)
|
||||
GTNODE(GT , GenTreeOp ,0,GTK_BINOP)
|
||||
GTNODE(EQ , GenTreeOp ,0,0,GTK_BINOP)
|
||||
GTNODE(NE , GenTreeOp ,0,0,GTK_BINOP)
|
||||
GTNODE(LT , GenTreeOp ,0,0,GTK_BINOP)
|
||||
GTNODE(LE , GenTreeOp ,0,0,GTK_BINOP)
|
||||
GTNODE(GE , GenTreeOp ,0,0,GTK_BINOP)
|
||||
GTNODE(GT , GenTreeOp ,0,0,GTK_BINOP)
|
||||
|
||||
// These implement EQ/NE(AND(x, y), 0). They always produce a value (GT_TEST is the version that does not).
|
||||
GTNODE(TEST_EQ , GenTreeOp ,0,GTK_BINOP|DBK_NOTHIR)
|
||||
GTNODE(TEST_NE , GenTreeOp ,0,GTK_BINOP|DBK_NOTHIR)
|
||||
GTNODE(TEST_EQ , GenTreeOp ,0,0,GTK_BINOP|DBK_NOTHIR)
|
||||
GTNODE(TEST_NE , GenTreeOp ,0,0,GTK_BINOP|DBK_NOTHIR)
|
||||
|
||||
#ifdef TARGET_XARCH
|
||||
// BITTEST_EQ/NE(a, n) == EQ/NE(AND(a, LSH(1, n)), 0), but only used in xarch that has the BT instruction
|
||||
GTNODE(BITTEST_EQ , GenTreeOp ,0,(GTK_BINOP|DBK_NOTHIR))
|
||||
GTNODE(BITTEST_NE , GenTreeOp ,0,(GTK_BINOP|DBK_NOTHIR))
|
||||
GTNODE(BITTEST_EQ , GenTreeOp ,0,0,(GTK_BINOP|DBK_NOTHIR))
|
||||
GTNODE(BITTEST_NE , GenTreeOp ,0,0,(GTK_BINOP|DBK_NOTHIR))
|
||||
#endif
|
||||
|
||||
// Conditional select with 3 operands: condition, true value, false value
|
||||
GTNODE(SELECT , GenTreeConditional ,0,GTK_SPECIAL)
|
||||
GTNODE(SELECT , GenTreeConditional ,0,0,GTK_SPECIAL)
|
||||
|
||||
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(COMMA , GenTreeOp ,0,1,GTK_BINOP|DBK_NOTLIR)
|
||||
GTNODE(QMARK , GenTreeQmark ,0,1,GTK_BINOP|GTK_EXOP|DBK_NOTLIR)
|
||||
GTNODE(COLON , GenTreeColon ,0,1,GTK_BINOP|DBK_NOTLIR)
|
||||
|
||||
GTNODE(INDEX_ADDR , GenTreeIndexAddr ,0,GTK_BINOP|GTK_EXOP) // Address of SZ-array-element.
|
||||
GTNODE(MKREFANY , GenTreeOp ,0,GTK_BINOP|DBK_NOTLIR)
|
||||
GTNODE(LEA , GenTreeAddrMode ,0,GTK_BINOP|GTK_EXOP|DBK_NOTHIR)
|
||||
GTNODE(INDEX_ADDR , GenTreeIndexAddr ,0,0,GTK_BINOP|GTK_EXOP) // Address of SZ-array-element.
|
||||
GTNODE(MKREFANY , GenTreeOp ,0,0,GTK_BINOP|DBK_NOTLIR)
|
||||
GTNODE(LEA , GenTreeAddrMode ,0,0,GTK_BINOP|GTK_EXOP|DBK_NOTHIR)
|
||||
|
||||
#if !defined(TARGET_64BIT)
|
||||
// A GT_LONG node simply represents the long value produced by the concatenation
|
||||
// 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|DBK_NOTHIR)
|
||||
GTNODE(LONG , GenTreeOp ,0,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|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)
|
||||
GTNODE(ADD_LO , GenTreeOp ,1,0,GTK_BINOP|DBK_NOTHIR)
|
||||
GTNODE(ADD_HI , GenTreeOp ,1,0,GTK_BINOP|DBK_NOTHIR)
|
||||
GTNODE(SUB_LO , GenTreeOp ,0,0,GTK_BINOP|DBK_NOTHIR)
|
||||
GTNODE(SUB_HI , GenTreeOp ,0,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
|
||||
|
@ -177,13 +178,13 @@ GTNODE(SUB_HI , GenTreeOp ,0,GTK_BINOP|DBK_NOTHIR)
|
|||
// 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|DBK_NOTHIR)
|
||||
GTNODE(RSH_LO , GenTreeOp ,0,GTK_BINOP|DBK_NOTHIR)
|
||||
GTNODE(LSH_HI , GenTreeOp ,0,0,GTK_BINOP|DBK_NOTHIR)
|
||||
GTNODE(RSH_LO , GenTreeOp ,0,0,GTK_BINOP|DBK_NOTHIR)
|
||||
|
||||
#endif // !defined(TARGET_64BIT)
|
||||
|
||||
#ifdef FEATURE_HW_INTRINSICS
|
||||
GTNODE(HWINTRINSIC , GenTreeHWIntrinsic ,0,GTK_SPECIAL) // hardware intrinsics
|
||||
GTNODE(HWINTRINSIC , GenTreeHWIntrinsic ,0,0,GTK_SPECIAL) // hardware intrinsics
|
||||
#endif // FEATURE_HW_INTRINSICS
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -191,13 +192,13 @@ GTNODE(HWINTRINSIC , GenTreeHWIntrinsic ,0,GTK_SPECIAL) // ha
|
|||
//-----------------------------------------------------------------------------
|
||||
|
||||
// Saturating increment, used in division by a constant (LowerUnsignedDivOrMod).
|
||||
GTNODE(INC_SATURATE , GenTreeOp ,0,GTK_UNOP|DBK_NOTHIR)
|
||||
GTNODE(INC_SATURATE , GenTreeOp ,0,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|DBK_NOTHIR)
|
||||
GTNODE(MULHI , GenTreeOp ,1,0,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,
|
||||
|
@ -206,15 +207,15 @@ GTNODE(MULHI , GenTreeOp ,1,GTK_BINOP|DBK_NOTHIR)
|
|||
// 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|DBK_NOTHIR)
|
||||
GTNODE(MUL_LONG , GenTreeMultiRegOp ,1,0,GTK_BINOP|DBK_NOTHIR)
|
||||
#elif defined(TARGET_ARM64)
|
||||
GTNODE(MUL_LONG , GenTreeOp ,1,GTK_BINOP|DBK_NOTHIR)
|
||||
GTNODE(MUL_LONG , GenTreeOp ,1,0,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)
|
||||
GTNODE(AND_NOT , GenTreeOp ,0,0,GTK_BINOP|DBK_NOTHIR)
|
||||
|
||||
#ifdef TARGET_ARM64
|
||||
GTNODE(BFIZ , GenTreeOp ,0,GTK_BINOP|DBK_NOTHIR) // Bitfield Insert in Zero.
|
||||
GTNODE(BFIZ , GenTreeOp ,0,0,GTK_BINOP|DBK_NOTHIR) // Bitfield Insert in Zero.
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -222,102 +223,102 @@ GTNODE(BFIZ , GenTreeOp ,0,GTK_BINOP|DBK_NOTHIR) // Bitfiel
|
|||
//-----------------------------------------------------------------------------
|
||||
|
||||
// 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,0,GTK_BINOP|GTK_NOVALUE|DBK_NOTHIR)
|
||||
// Generate a test instruction; sets the CPU flags according to (a & b) and does not produce a value.
|
||||
GTNODE(TEST , GenTreeOp ,0,GTK_BINOP|GTK_NOVALUE|DBK_NOTHIR)
|
||||
GTNODE(TEST , GenTreeOp ,0,0,GTK_BINOP|GTK_NOVALUE|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))
|
||||
GTNODE(BT , GenTreeOp ,0,0,(GTK_BINOP|GTK_NOVALUE|DBK_NOTHIR))
|
||||
#endif
|
||||
// Makes a comparison and jumps if the condition specified by gtCondition is true. Does not set flags.
|
||||
GTNODE(JCMP , GenTreeOpCC ,0,GTK_BINOP|GTK_NOVALUE|DBK_NOTHIR)
|
||||
GTNODE(JCMP , GenTreeOpCC ,0,0,GTK_BINOP|GTK_NOVALUE|DBK_NOTHIR)
|
||||
// Do a bit test and jump if set/not set.
|
||||
GTNODE(JTEST , GenTreeOpCC ,0,GTK_BINOP|GTK_NOVALUE|DBK_NOTHIR)
|
||||
GTNODE(JTEST , GenTreeOpCC ,0,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,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)
|
||||
GTNODE(SETCC , GenTreeCC ,0,0,GTK_LEAF|DBK_NOTHIR)
|
||||
// Variant of SELECT that reuses flags computed by a previous node with the specified condition.
|
||||
GTNODE(SELECTCC , GenTreeOpCC ,0,GTK_BINOP|DBK_NOTHIR)
|
||||
GTNODE(SELECTCC , GenTreeOpCC ,0,0,GTK_BINOP|DBK_NOTHIR)
|
||||
#ifdef TARGET_ARM64
|
||||
// The arm64 ccmp instruction. If the specified condition is true, compares two
|
||||
// operands and sets the condition flags according to the result. Otherwise
|
||||
// sets the condition flags to the specified immediate value.
|
||||
GTNODE(CCMP , GenTreeCCMP ,0,GTK_BINOP|GTK_NOVALUE|DBK_NOTHIR)
|
||||
GTNODE(CCMP , GenTreeCCMP ,0,0,GTK_BINOP|GTK_NOVALUE|DBK_NOTHIR)
|
||||
// Maps to arm64 csinc/cinc instruction. Computes result = condition ? op1 : op2 + 1.
|
||||
// If op2 is null, computes result = condition ? op1 + 1 : op1.
|
||||
GTNODE(SELECT_INC , GenTreeOp ,0,GTK_BINOP|DBK_NOTHIR)
|
||||
GTNODE(SELECT_INC , GenTreeOp ,0,0,GTK_BINOP|DBK_NOTHIR)
|
||||
// Variant of SELECT_INC that reuses flags computed by a previous node with the specified condition.
|
||||
GTNODE(SELECT_INCCC , GenTreeOpCC ,0,GTK_BINOP|DBK_NOTHIR)
|
||||
GTNODE(SELECT_INCCC , GenTreeOpCC ,0,0,GTK_BINOP|DBK_NOTHIR)
|
||||
// Maps to arm64 csinv/cinv instruction. Computes result = condition ? op1 : ~op2.
|
||||
// If op2 is null, computes result = condition ? ~op1 : op1.
|
||||
GTNODE(SELECT_INV , GenTreeOp ,0,GTK_BINOP|DBK_NOTHIR)
|
||||
GTNODE(SELECT_INV , GenTreeOp ,0,0,GTK_BINOP|DBK_NOTHIR)
|
||||
// Variant of SELECT_INV that reuses flags computed by a previous node with the specified condition.
|
||||
GTNODE(SELECT_INVCC , GenTreeOpCC ,0,GTK_BINOP|DBK_NOTHIR)
|
||||
GTNODE(SELECT_INVCC , GenTreeOpCC ,0,0,GTK_BINOP|DBK_NOTHIR)
|
||||
// Maps to arm64 csneg/cneg instruction.. Computes result = condition ? op1 : -op2.
|
||||
// If op2 is null, computes result = condition ? -op1 : op1.
|
||||
GTNODE(SELECT_NEG , GenTreeOp ,0,GTK_BINOP|DBK_NOTHIR)
|
||||
GTNODE(SELECT_NEG , GenTreeOp ,0,0,GTK_BINOP|DBK_NOTHIR)
|
||||
// Variant of SELECT_NEG that reuses flags computed by a previous node with the specified condition.
|
||||
GTNODE(SELECT_NEGCC , GenTreeOpCC ,0,GTK_BINOP|DBK_NOTHIR)
|
||||
GTNODE(SELECT_NEGCC , GenTreeOpCC ,0,0,GTK_BINOP|DBK_NOTHIR)
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Other nodes that look like unary/binary operators:
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
GTNODE(JTRUE , GenTreeOp ,0,GTK_UNOP|GTK_NOVALUE)
|
||||
GTNODE(JTRUE , GenTreeOp ,0,1,GTK_UNOP|GTK_NOVALUE)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Other nodes that have special structure:
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
GTNODE(ARR_ELEM , GenTreeArrElem ,0,GTK_SPECIAL) // Multi-dimensional array-element address
|
||||
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(ARR_ELEM , GenTreeArrElem ,0,0,GTK_SPECIAL) // Multi-dimensional array-element address
|
||||
GTNODE(CALL , GenTreeCall ,0,0,GTK_SPECIAL|DBK_NOCONTAIN)
|
||||
GTNODE(FIELD_LIST , GenTreeFieldList ,0,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,1,GTK_UNOP|GTK_NOVALUE)
|
||||
GTNODE(SWITCH , GenTreeOp ,0,1,GTK_UNOP|GTK_NOVALUE)
|
||||
GTNODE(NO_OP , GenTree ,0,0,GTK_LEAF|GTK_NOVALUE) // A NOP that cannot be deleted.
|
||||
|
||||
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(START_NONGC , GenTree ,0,0,GTK_LEAF|GTK_NOVALUE|DBK_NOTHIR) // Starts a new instruction group that will be non-gc interruptible.
|
||||
GTNODE(START_PREEMPTGC , GenTree ,0,0,GTK_LEAF|GTK_NOVALUE|DBK_NOTHIR) // Starts a new instruction group where preemptive GC is enabled.
|
||||
GTNODE(PROF_HOOK , GenTree ,0,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,1,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,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
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
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
|
||||
GTNODE(JMPTABLE , GenTree ,0,0,GTK_LEAF|DBK_NOCONTAIN|DBK_NOTHIR) // Generates the jump table for switches
|
||||
GTNODE(SWITCH_TABLE , GenTreeOp ,0,0,GTK_BINOP|GTK_NOVALUE|DBK_NOTHIR) // Jump Table based switch construct
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Nodes used only within the code generator:
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
GTNODE(CLS_VAR_ADDR , GenTreeClsVar ,0,GTK_LEAF|DBK_NOTHIR) // static data member address
|
||||
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
|
||||
GTNODE(CLS_VAR_ADDR , GenTreeClsVar ,0,0,GTK_LEAF|DBK_NOTHIR) // static data member address
|
||||
GTNODE(PHYSREG , GenTreePhysReg ,0,0,GTK_LEAF|DBK_NOTHIR) // read from a physical register
|
||||
GTNODE(EMITNOP , GenTree ,0,0,GTK_LEAF|GTK_NOVALUE|DBK_NOTHIR) // emitter-placed nop
|
||||
GTNODE(PINVOKE_PROLOG , GenTree ,0,0,GTK_LEAF|GTK_NOVALUE|DBK_NOTHIR) // pinvoke prolog seq
|
||||
GTNODE(PINVOKE_EPILOG , GenTree ,0,0,GTK_LEAF|GTK_NOVALUE|DBK_NOTHIR) // pinvoke epilog seq
|
||||
GTNODE(RETURNTRAP , GenTreeOp ,0,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
|
||||
GTNODE(PUTARG_REG , GenTreeMultiRegOp ,0,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
|
||||
GTNODE(PUTARG_REG , GenTreeOp ,0,0,GTK_UNOP|DBK_NOTHIR) // operator that places outgoing arg in register
|
||||
#endif
|
||||
GTNODE(PUTARG_STK , GenTreePutArgStk ,0,GTK_UNOP|GTK_NOVALUE|DBK_NOTHIR) // operator that places outgoing arg in stack
|
||||
GTNODE(PUTARG_STK , GenTreePutArgStk ,0,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)
|
||||
GTNODE(PUTARG_SPLIT , GenTreePutArgSplit ,0,0,GTK_UNOP|DBK_NOTHIR) // operator that places outgoing arg in registers with stack (split struct in ARM32)
|
||||
#endif // FEATURE_ARG_SPLIT
|
||||
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
|
||||
GTNODE(SWAP , GenTreeOp ,0,0,GTK_BINOP|GTK_NOVALUE|DBK_NOTHIR) // op1 and op2 swap (registers)
|
||||
GTNODE(COPY , GenTreeCopyOrReload,0,0,GTK_UNOP|DBK_NOTHIR) // Copies a variable from its current location to a register that satisfies
|
||||
GTNODE(RELOAD , GenTreeCopyOrReload,0,0,GTK_UNOP|DBK_NOTHIR) // code generation constraints. The operand is the actual lclVar node.
|
||||
GTNODE(IL_OFFSET , GenTreeILOffset ,0,0,GTK_LEAF|GTK_NOVALUE|DBK_NOTHIR) // marks an IL offset for debugging purposes
|
||||
|
||||
/*****************************************************************************/
|
||||
#undef GTNODE
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
static const HWIntrinsicInfo hwIntrinsicInfoArray[] = {
|
||||
// clang-format off
|
||||
#if defined(TARGET_XARCH)
|
||||
#define HARDWARE_INTRINSIC(isa, name, size, numarg, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, category, flag) \
|
||||
#define HARDWARE_INTRINSIC(isa, name, size, numarg, extra, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, category, flag) \
|
||||
{ \
|
||||
/* name */ #name, \
|
||||
/* flags */ static_cast<HWIntrinsicFlag>(flag), \
|
||||
|
@ -22,7 +22,7 @@ static const HWIntrinsicInfo hwIntrinsicInfoArray[] = {
|
|||
},
|
||||
#include "hwintrinsiclistxarch.h"
|
||||
#elif defined (TARGET_ARM64)
|
||||
#define HARDWARE_INTRINSIC(isa, name, size, numarg, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, category, flag) \
|
||||
#define HARDWARE_INTRINSIC(isa, name, size, numarg, extra, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, category, flag) \
|
||||
{ \
|
||||
/* name */ #name, \
|
||||
/* flags */ static_cast<HWIntrinsicFlag>(flag), \
|
||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -126,11 +126,11 @@ enum NamedIntrinsic : unsigned short
|
|||
#ifdef FEATURE_HW_INTRINSICS
|
||||
NI_HW_INTRINSIC_START,
|
||||
#if defined(TARGET_XARCH)
|
||||
#define HARDWARE_INTRINSIC(isa, name, size, numarg, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, category, flag) \
|
||||
#define HARDWARE_INTRINSIC(isa, name, size, numarg, extra, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, category, flag) \
|
||||
NI_##isa##_##name,
|
||||
#include "hwintrinsiclistxarch.h"
|
||||
#elif defined(TARGET_ARM64)
|
||||
#define HARDWARE_INTRINSIC(isa, name, size, numarg, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, category, flag) \
|
||||
#define HARDWARE_INTRINSIC(isa, name, size, numarg, extra, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, category, flag) \
|
||||
NI_##isa##_##name,
|
||||
#include "hwintrinsiclistarm64.h"
|
||||
#endif // !defined(TARGET_XARCH) && !defined(TARGET_ARM64)
|
||||
|
|
|
@ -8852,7 +8852,65 @@ void ValueNumStore::vnDumpZeroObj(Compiler* comp, VNFuncApp* zeroObj)
|
|||
#endif // DEBUG
|
||||
|
||||
// Static fields, methods.
|
||||
static UINT8 vnfOpAttribs[VNF_COUNT];
|
||||
|
||||
#define ValueNumFuncDef(vnf, arity, commute, knownNonNull, sharedStatic, extra) \
|
||||
static_assert((arity) >= 0 || !(extra), "valuenumfuncs.h has EncodesExtraTypeArg==true and arity<0 for " #vnf);
|
||||
#include "valuenumfuncs.h"
|
||||
|
||||
#ifdef FEATURE_HW_INTRINSICS
|
||||
|
||||
#define HARDWARE_INTRINSIC(isa, name, size, argCount, extra, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, category, flag) \
|
||||
static_assert((size) != 0 || !(extra), \
|
||||
"hwintrinsicslist<arch>.h has EncodesExtraTypeArg==true and size==0 for " #isa " " #name);
|
||||
#if defined(TARGET_XARCH)
|
||||
#include "hwintrinsiclistxarch.h"
|
||||
#elif defined(TARGET_ARM64)
|
||||
#include "hwintrinsiclistarm64.h"
|
||||
#else
|
||||
#error Unsupported platform
|
||||
#endif
|
||||
|
||||
#endif // FEATURE_HW_INTRINSICS
|
||||
|
||||
/* static */ constexpr uint8_t ValueNumStore::GetOpAttribsForArity(genTreeOps oper, GenTreeOperKind kind)
|
||||
{
|
||||
return ((GenTree::StaticOperIs(oper, GT_SELECT) ? 3 : (((kind & GTK_UNOP) >> 1) | ((kind & GTK_BINOP) >> 1)))
|
||||
<< VNFOA_ArityShift) &
|
||||
VNFOA_ArityMask;
|
||||
}
|
||||
|
||||
/* static */ constexpr uint8_t ValueNumStore::GetOpAttribsForGenTree(genTreeOps oper,
|
||||
bool commute,
|
||||
bool illegalAsVNFunc,
|
||||
GenTreeOperKind kind)
|
||||
{
|
||||
return GetOpAttribsForArity(oper, kind) | (static_cast<uint8_t>(commute) << VNFOA_CommutativeShift) |
|
||||
(static_cast<uint8_t>(illegalAsVNFunc) << VNFOA_IllegalGenTreeOpShift);
|
||||
}
|
||||
|
||||
/* static */ constexpr uint8_t ValueNumStore::GetOpAttribsForFunc(int arity,
|
||||
bool commute,
|
||||
bool knownNonNull,
|
||||
bool sharedStatic)
|
||||
{
|
||||
return (static_cast<uint8_t>(commute) << VNFOA_CommutativeShift) |
|
||||
(static_cast<uint8_t>(knownNonNull) << VNFOA_KnownNonNullShift) |
|
||||
(static_cast<uint8_t>(sharedStatic) << VNFOA_SharedStaticShift) |
|
||||
((static_cast<uint8_t>(arity & ~(arity >> 31)) << VNFOA_ArityShift) & VNFOA_ArityMask);
|
||||
}
|
||||
|
||||
const uint8_t ValueNumStore::s_vnfOpAttribs[VNF_COUNT] = {
|
||||
#define GTNODE(en, st, cm, ivn, ok) \
|
||||
GetOpAttribsForGenTree(static_cast<genTreeOps>(GT_##en), cm, ivn, static_cast<GenTreeOperKind>(ok)),
|
||||
#include "gtlist.h"
|
||||
|
||||
0, // VNF_Boundary
|
||||
|
||||
#define ValueNumFuncDef(vnf, arity, commute, knownNonNull, sharedStatic, extra) \
|
||||
GetOpAttribsForFunc((arity) + static_cast<int>(extra), commute, knownNonNull, sharedStatic),
|
||||
#include "valuenumfuncs.h"
|
||||
};
|
||||
|
||||
static genTreeOps genTreeOpsIllegalAsVNFunc[] = {GT_IND, // When we do heap memory.
|
||||
GT_NULLCHECK, GT_QMARK, GT_COLON, GT_LOCKADD, GT_XADD, GT_XCHG,
|
||||
GT_CMPXCHG, GT_LCLHEAP, GT_BOX, GT_XORR, GT_XAND, GT_STORE_DYN_BLK,
|
||||
|
@ -8869,15 +8927,10 @@ static genTreeOps genTreeOpsIllegalAsVNFunc[] = {GT_IND, // When we do heap memo
|
|||
// These control-flow operations need no values.
|
||||
GT_JTRUE, GT_RETURN, GT_SWITCH, GT_RETFILT, GT_CKFINITE};
|
||||
|
||||
UINT8* ValueNumStore::s_vnfOpAttribs = nullptr;
|
||||
|
||||
void ValueNumStore::InitValueNumStoreStatics()
|
||||
void ValueNumStore::ValidateValueNumStoreStatics()
|
||||
{
|
||||
// Make sure we have the constants right...
|
||||
assert(unsigned(VNFOA_Arity1) == (1 << VNFOA_ArityShift));
|
||||
assert(VNFOA_ArityMask == (VNFOA_MaxArity << VNFOA_ArityShift));
|
||||
|
||||
s_vnfOpAttribs = &vnfOpAttribs[0];
|
||||
#if DEBUG
|
||||
uint8_t arr[VNF_COUNT] = {};
|
||||
for (unsigned i = 0; i < GT_COUNT; i++)
|
||||
{
|
||||
genTreeOps gtOper = static_cast<genTreeOps>(i);
|
||||
|
@ -8895,11 +8948,11 @@ void ValueNumStore::InitValueNumStoreStatics()
|
|||
arity = 3;
|
||||
}
|
||||
|
||||
vnfOpAttribs[i] |= ((arity << VNFOA_ArityShift) & VNFOA_ArityMask);
|
||||
arr[i] |= ((arity << VNFOA_ArityShift) & VNFOA_ArityMask);
|
||||
|
||||
if (GenTree::OperIsCommutative(gtOper))
|
||||
{
|
||||
vnfOpAttribs[i] |= VNFOA_Commutative;
|
||||
arr[i] |= VNFOA_Commutative;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -8907,25 +8960,24 @@ void ValueNumStore::InitValueNumStoreStatics()
|
|||
|
||||
int vnfNum = VNF_Boundary + 1; // The macro definition below will update this after using it.
|
||||
|
||||
#define ValueNumFuncDef(vnf, arity, commute, knownNonNull, sharedStatic) \
|
||||
#define ValueNumFuncDef(vnf, arity, commute, knownNonNull, sharedStatic, extra) \
|
||||
if (commute) \
|
||||
vnfOpAttribs[vnfNum] |= VNFOA_Commutative; \
|
||||
arr[vnfNum] |= VNFOA_Commutative; \
|
||||
if (knownNonNull) \
|
||||
vnfOpAttribs[vnfNum] |= VNFOA_KnownNonNull; \
|
||||
arr[vnfNum] |= VNFOA_KnownNonNull; \
|
||||
if (sharedStatic) \
|
||||
vnfOpAttribs[vnfNum] |= VNFOA_SharedStatic; \
|
||||
arr[vnfNum] |= VNFOA_SharedStatic; \
|
||||
if (arity > 0) \
|
||||
vnfOpAttribs[vnfNum] |= ((arity << VNFOA_ArityShift) & VNFOA_ArityMask); \
|
||||
arr[vnfNum] |= ((arity << VNFOA_ArityShift) & VNFOA_ArityMask); \
|
||||
vnfNum++;
|
||||
|
||||
#include "valuenumfuncs.h"
|
||||
#undef ValueNumFuncDef
|
||||
|
||||
assert(vnfNum == VNF_COUNT);
|
||||
|
||||
#define ValueNumFuncSetArity(vnfNum, arity) \
|
||||
vnfOpAttribs[vnfNum] &= ~VNFOA_ArityMask; /* clear old arity value */ \
|
||||
vnfOpAttribs[vnfNum] |= ((arity << VNFOA_ArityShift) & VNFOA_ArityMask) /* set the new arity value */
|
||||
arr[vnfNum] &= ~VNFOA_ArityMask; /* clear old arity value */ \
|
||||
arr[vnfNum] |= ((arity << VNFOA_ArityShift) & VNFOA_ArityMask) /* set the new arity value */
|
||||
|
||||
#ifdef FEATURE_HW_INTRINSICS
|
||||
|
||||
|
@ -8939,7 +8991,7 @@ void ValueNumStore::InitValueNumStoreStatics()
|
|||
// These HW_Intrinsic's have an extra VNF_SimdType arg.
|
||||
//
|
||||
VNFunc func = VNFunc(VNF_HWI_FIRST + (id - NI_HW_INTRINSIC_START - 1));
|
||||
unsigned oldArity = VNFuncArity(func);
|
||||
unsigned oldArity = (arr[func] & VNFOA_ArityMask) >> VNFOA_ArityShift;
|
||||
unsigned newArity = oldArity + 1;
|
||||
|
||||
ValueNumFuncSetArity(func, newArity);
|
||||
|
@ -8948,7 +9000,7 @@ void ValueNumStore::InitValueNumStoreStatics()
|
|||
if (HWIntrinsicInfo::IsCommutative(id))
|
||||
{
|
||||
VNFunc func = VNFunc(VNF_HWI_FIRST + (id - NI_HW_INTRINSIC_START - 1));
|
||||
vnfOpAttribs[func] |= VNFOA_Commutative;
|
||||
arr[func] |= VNFOA_Commutative;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -8958,17 +9010,23 @@ void ValueNumStore::InitValueNumStoreStatics()
|
|||
|
||||
for (unsigned i = 0; i < ArrLen(genTreeOpsIllegalAsVNFunc); i++)
|
||||
{
|
||||
vnfOpAttribs[genTreeOpsIllegalAsVNFunc[i]] |= VNFOA_IllegalGenTreeOp;
|
||||
arr[genTreeOpsIllegalAsVNFunc[i]] |= VNFOA_IllegalGenTreeOp;
|
||||
}
|
||||
|
||||
assert(ArrLen(arr) == ArrLen(s_vnfOpAttribs));
|
||||
for (unsigned i = 0; i < ArrLen(arr); i++)
|
||||
{
|
||||
assert(arr[i] == s_vnfOpAttribs[i]);
|
||||
}
|
||||
#endif // DEBUG
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
// Define the name array.
|
||||
#define ValueNumFuncDef(vnf, arity, commute, knownNonNull, sharedStatic) #vnf,
|
||||
#define ValueNumFuncDef(vnf, arity, commute, knownNonNull, sharedStatic, extra) #vnf,
|
||||
|
||||
const char* ValueNumStore::VNFuncNameArr[] = {
|
||||
#include "valuenumfuncs.h"
|
||||
#undef ValueNumFuncDef
|
||||
};
|
||||
|
||||
/* static */ const char* ValueNumStore::VNFuncName(VNFunc vnf)
|
||||
|
|
|
@ -167,7 +167,7 @@ enum VNFunc
|
|||
{
|
||||
// Implicitly, elements of genTreeOps here.
|
||||
VNF_Boundary = GT_COUNT,
|
||||
#define ValueNumFuncDef(nm, arity, commute, knownNonNull, sharedStatic) VNF_##nm,
|
||||
#define ValueNumFuncDef(nm, arity, commute, knownNonNull, sharedStatic, extra) VNF_##nm,
|
||||
#include "valuenumfuncs.h"
|
||||
VNF_COUNT
|
||||
};
|
||||
|
@ -275,10 +275,21 @@ private:
|
|||
VNFOA_SharedStatic = 0x40, // 1 iff this VNF is represent one of the shared static jit helpers
|
||||
};
|
||||
|
||||
static const unsigned VNFOA_ArityShift = 2;
|
||||
static const unsigned VNFOA_ArityBits = 3;
|
||||
static const unsigned VNFOA_MaxArity = (1 << VNFOA_ArityBits) - 1; // Max arity we can represent.
|
||||
static const unsigned VNFOA_ArityMask = (VNFOA_Arity4 | VNFOA_Arity2 | VNFOA_Arity1);
|
||||
static const unsigned VNFOA_IllegalGenTreeOpShift = 0;
|
||||
static const unsigned VNFOA_CommutativeShift = 1;
|
||||
static const unsigned VNFOA_ArityShift = 2;
|
||||
static const unsigned VNFOA_ArityBits = 3;
|
||||
static const unsigned VNFOA_MaxArity = (1 << VNFOA_ArityBits) - 1; // Max arity we can represent.
|
||||
static const unsigned VNFOA_ArityMask = (VNFOA_Arity4 | VNFOA_Arity2 | VNFOA_Arity1);
|
||||
static const unsigned VNFOA_KnownNonNullShift = 5;
|
||||
static const unsigned VNFOA_SharedStaticShift = 6;
|
||||
|
||||
static_assert(unsigned(VNFOA_IllegalGenTreeOp) == (1 << VNFOA_IllegalGenTreeOpShift));
|
||||
static_assert(unsigned(VNFOA_Commutative) == (1 << VNFOA_CommutativeShift));
|
||||
static_assert(unsigned(VNFOA_Arity1) == (1 << VNFOA_ArityShift));
|
||||
static_assert(VNFOA_ArityMask == (VNFOA_MaxArity << VNFOA_ArityShift));
|
||||
static_assert(unsigned(VNFOA_KnownNonNull) == (1 << VNFOA_KnownNonNullShift));
|
||||
static_assert(unsigned(VNFOA_SharedStatic) == (1 << VNFOA_SharedStaticShift));
|
||||
|
||||
// These enum constants are used to encode the cast operation in the lowest bits by VNForCastOper
|
||||
enum VNFCastAttrib
|
||||
|
@ -289,8 +300,14 @@ private:
|
|||
VCA_ReservedBits = 0x01, // i.e. (VCA_UnsignedSrc)
|
||||
};
|
||||
|
||||
// An array of length GT_COUNT, mapping genTreeOp values to their VNFOpAttrib.
|
||||
static UINT8* s_vnfOpAttribs;
|
||||
// Helpers and an array of length GT_COUNT, mapping genTreeOp values to their VNFOpAttrib.
|
||||
static constexpr uint8_t GetOpAttribsForArity(genTreeOps oper, GenTreeOperKind kind);
|
||||
static constexpr uint8_t GetOpAttribsForGenTree(genTreeOps oper,
|
||||
bool commute,
|
||||
bool illegalAsVNFunc,
|
||||
GenTreeOperKind kind);
|
||||
static constexpr uint8_t GetOpAttribsForFunc(int arity, bool commute, bool knownNonNull, bool sharedStatic);
|
||||
static const uint8_t s_vnfOpAttribs[];
|
||||
|
||||
// Returns "true" iff gtOper is a legal value number function.
|
||||
// (Requires InitValueNumStoreStatics to have been run.)
|
||||
|
@ -383,8 +400,8 @@ private:
|
|||
GenTreeFlags GetFoldedArithOpResultHandleFlags(ValueNum vn);
|
||||
|
||||
public:
|
||||
// Initializes any static variables of ValueNumStore.
|
||||
static void InitValueNumStoreStatics();
|
||||
// Validate that the new initializer for s_vnfOpAttribs matches the old code.
|
||||
static void ValidateValueNumStoreStatics();
|
||||
|
||||
// Initialize an empty ValueNumStore.
|
||||
ValueNumStore(Compiler* comp, CompAllocator allocator);
|
||||
|
|
|
@ -3,180 +3,180 @@
|
|||
|
||||
// Defines the functions understood by the value-numbering system.
|
||||
// ValueNumFuncDef(<name of function>, <arity (1-4)>, <is-commutative (for arity = 2)>, <non-null (for gc functions)>,
|
||||
// <is-shared-static>)
|
||||
// <is-shared-static>, <encodes-extra-type-arg>)
|
||||
|
||||
// clang-format off
|
||||
ValueNumFuncDef(MemOpaque, 1, false, false, false) // Args: 0: loop num
|
||||
ValueNumFuncDef(MapSelect, 2, false, false, false) // Args: 0: map, 1: key.
|
||||
ValueNumFuncDef(MapStore, 4, false, false, false) // Args: 0: map, 1: index (e. g. field handle), 2: value being stored, 3: loop num.
|
||||
ValueNumFuncDef(MapPhysicalStore, 3, false, false, false) // Args: 0: map, 1: "physical selector": offset and size, 2: value being stored
|
||||
ValueNumFuncDef(BitCast, 2, false, false, false) // Args: 0: VN of the arg, 1: VN of the target type
|
||||
ValueNumFuncDef(ZeroObj, 1, false, false, false) // Args: 0: VN of the class handle.
|
||||
ValueNumFuncDef(PhiDef, 3, false, false, false) // Args: 0: local var # (or -1 for memory), 1: SSA #, 2: VN of definition.
|
||||
ValueNumFuncDef(PhiMemoryDef, 2, false, false, false) // Args: 0: VN for basic block pointer, 1: VN of definition
|
||||
ValueNumFuncDef(Phi, 2, false, false, false) // A phi function. Only occurs as arg of PhiDef or PhiMemoryDef. Arguments are SSA numbers of var being defined.
|
||||
ValueNumFuncDef(MemOpaque, 1, false, false, false, false) // Args: 0: loop num
|
||||
ValueNumFuncDef(MapSelect, 2, false, false, false, false) // Args: 0: map, 1: key.
|
||||
ValueNumFuncDef(MapStore, 4, false, false, false, false) // Args: 0: map, 1: index (e. g. field handle), 2: value being stored, 3: loop num.
|
||||
ValueNumFuncDef(MapPhysicalStore, 3, false, false, false, false) // Args: 0: map, 1: "physical selector": offset and size, 2: value being stored
|
||||
ValueNumFuncDef(BitCast, 2, false, false, false, false) // Args: 0: VN of the arg, 1: VN of the target type
|
||||
ValueNumFuncDef(ZeroObj, 1, false, false, false, false) // Args: 0: VN of the class handle.
|
||||
ValueNumFuncDef(PhiDef, 3, false, false, false, false) // Args: 0: local var # (or -1 for memory), 1: SSA #, 2: VN of definition.
|
||||
ValueNumFuncDef(PhiMemoryDef, 2, false, false, false, false) // Args: 0: VN for basic block pointer, 1: VN of definition
|
||||
ValueNumFuncDef(Phi, 2, false, false, false, false) // A phi function. Only occurs as arg of PhiDef or PhiMemoryDef. Arguments are SSA numbers of var being defined.
|
||||
|
||||
ValueNumFuncDef(PtrToLoc, 2, false, true, false) // Pointer (byref) to a local variable. Args: VN's of: 0: local's number, 1: offset.
|
||||
ValueNumFuncDef(PtrToArrElem, 4, false, false, false) // Pointer (byref) to an array element. Args: 0: array elem type eq class var_types value, VN's of: 1: array, 2: index, 3: offset.
|
||||
ValueNumFuncDef(PtrToStatic, 3, false, true, false) // Pointer (byref) to a static variable (or possibly a field thereof, if the static variable is a struct).
|
||||
// Args: 0: (VN of) the box's address if the static is "boxed",
|
||||
// 1: (VN of) the field sequence,
|
||||
// 2: (VN of) offset for the constituent struct fields
|
||||
ValueNumFuncDef(PtrToLoc, 2, false, true, false, false) // Pointer (byref) to a local variable. Args: VN's of: 0: local's number, 1: offset.
|
||||
ValueNumFuncDef(PtrToArrElem, 4, false, false, false, false) // Pointer (byref) to an array element. Args: 0: array elem type eq class var_types value, VN's of: 1: array, 2: index, 3: offset.
|
||||
ValueNumFuncDef(PtrToStatic, 3, false, true, false, false) // Pointer (byref) to a static variable (or possibly a field thereof, if the static variable is a struct).
|
||||
// Args: 0: (VN of) the box's address if the static is "boxed",
|
||||
// 1: (VN of) the field sequence,
|
||||
// 2: (VN of) offset for the constituent struct fields
|
||||
|
||||
ValueNumFuncDef(MDArrLength, 2, false, false, false) // MD array len, Args: 0: array, 1: dimension
|
||||
ValueNumFuncDef(MDArrLowerBound, 2, false, false, false) // MD array lower bound, Args: 0: array, 1: dimension
|
||||
ValueNumFuncDef(MDArrLength, 2, false, false, false, false) // MD array len, Args: 0: array, 1: dimension
|
||||
ValueNumFuncDef(MDArrLowerBound, 2, false, false, false, false) // MD array lower bound, Args: 0: array, 1: dimension
|
||||
|
||||
ValueNumFuncDef(InitVal, 1, false, false, false) // An input arg, or init val of a local Args: 0: a constant VN.
|
||||
ValueNumFuncDef(InitVal, 1, false, false, false, false) // An input arg, or init val of a local Args: 0: a constant VN.
|
||||
|
||||
ValueNumFuncDef(Cast, 2, false, false, false) // VNF_Cast: Cast Operation changes the representations size and unsigned-ness.
|
||||
// Args: 0: Source for the cast operation.
|
||||
// 1: Constant integer representing the operation .
|
||||
// Use VNForCastOper() to construct.
|
||||
ValueNumFuncDef(CastOvf, 2, false, false, false) // Same as a VNF_Cast but also can throw an overflow exception.
|
||||
ValueNumFuncDef(Cast, 2, false, false, false, false) // VNF_Cast: Cast Operation changes the representations size and unsigned-ness.
|
||||
// Args: 0: Source for the cast operation.
|
||||
// 1: Constant integer representing the operation .
|
||||
// Use VNForCastOper() to construct.
|
||||
ValueNumFuncDef(CastOvf, 2, false, false, false, false) // Same as a VNF_Cast but also can throw an overflow exception.
|
||||
|
||||
ValueNumFuncDef(CastClass, 2, false, false, false) // Args: 0: Handle of class being cast to, 1: object being cast.
|
||||
ValueNumFuncDef(IsInstanceOf, 2, false, false, false) // Args: 0: Handle of class being queried, 1: object being queried.
|
||||
ValueNumFuncDef(ReadyToRunCastClass, 2, false, false, false) // Args: 0: Helper stub address, 1: object being cast.
|
||||
ValueNumFuncDef(ReadyToRunIsInstanceOf, 2, false, false, false) // Args: 0: Helper stub address, 1: object being queried.
|
||||
ValueNumFuncDef(TypeHandleToRuntimeType, 1, false, false, false) // Args: 0: TypeHandle to translate
|
||||
ValueNumFuncDef(TypeHandleToRuntimeTypeHandle, 1, false, false, false) // Args: 0: TypeHandle to translate
|
||||
ValueNumFuncDef(CastClass, 2, false, false, false, false) // Args: 0: Handle of class being cast to, 1: object being cast.
|
||||
ValueNumFuncDef(IsInstanceOf, 2, false, false, false, false) // Args: 0: Handle of class being queried, 1: object being queried.
|
||||
ValueNumFuncDef(ReadyToRunCastClass, 2, false, false, false, false) // Args: 0: Helper stub address, 1: object being cast.
|
||||
ValueNumFuncDef(ReadyToRunIsInstanceOf, 2, false, false, false, false) // Args: 0: Helper stub address, 1: object being queried.
|
||||
ValueNumFuncDef(TypeHandleToRuntimeType, 1, false, false, false, false) // Args: 0: TypeHandle to translate
|
||||
ValueNumFuncDef(TypeHandleToRuntimeTypeHandle, 1, false, false, false, false) // Args: 0: TypeHandle to translate
|
||||
|
||||
ValueNumFuncDef(LdElemA, 3, false, false, false) // Args: 0: array value; 1: index value; 2: type handle of element.
|
||||
ValueNumFuncDef(LdElemA, 3, false, false, false, false) // Args: 0: array value; 1: index value; 2: type handle of element.
|
||||
|
||||
ValueNumFuncDef(ByrefExposedLoad, 3, false, false, false) // Args: 0: type handle/id, 1: pointer value; 2: ByrefExposed heap value
|
||||
ValueNumFuncDef(ByrefExposedLoad, 3, false, false, false, false) // Args: 0: type handle/id, 1: pointer value; 2: ByrefExposed heap value
|
||||
|
||||
ValueNumFuncDef(GetRefanyVal, 2, false, false, false) // Args: 0: type handle; 1: typedref value. Returns the value (asserting that the type is right).
|
||||
ValueNumFuncDef(GetRefanyVal, 2, false, false, false, false) // Args: 0: type handle; 1: typedref value. Returns the value (asserting that the type is right).
|
||||
|
||||
ValueNumFuncDef(GetClassFromMethodParam, 1, false, true, false) // Args: 0: method generic argument.
|
||||
ValueNumFuncDef(GetSyncFromClassHandle, 1, false, true, false) // Args: 0: class handle.
|
||||
ValueNumFuncDef(LoopCloneChoiceAddr, 0, false, true, false)
|
||||
ValueNumFuncDef(GetClassFromMethodParam, 1, false, true, false, false) // Args: 0: method generic argument.
|
||||
ValueNumFuncDef(GetSyncFromClassHandle, 1, false, true, false, false) // Args: 0: class handle.
|
||||
ValueNumFuncDef(LoopCloneChoiceAddr, 0, false, true, false, false)
|
||||
|
||||
// How we represent values of expressions with exceptional side effects:
|
||||
ValueNumFuncDef(ValWithExc, 2, false, false, false) // Args: 0: value number from normal execution; 1: VN for set of possible exceptions.
|
||||
ValueNumFuncDef(ExcSetCons, 2, false, false, false) // Args: 0: exception; 1: exception set (including EmptyExcSet). Invariant: "car"s are always in ascending order.
|
||||
ValueNumFuncDef(ValWithExc, 2, false, false, false, false) // Args: 0: value number from normal execution; 1: VN for set of possible exceptions.
|
||||
ValueNumFuncDef(ExcSetCons, 2, false, false, false, false) // Args: 0: exception; 1: exception set (including EmptyExcSet). Invariant: "car"s are always in ascending order.
|
||||
|
||||
// Various functions that are used to indicate that an exceptions may occur
|
||||
// Curremtly when the execution is always thrown, the value VNForVoid() is used as Arg0 by OverflowExc and DivideByZeroExc
|
||||
//
|
||||
ValueNumFuncDef(NullPtrExc, 1, false, false, false) // Null pointer exception check. Args: 0: address value, throws when it is null
|
||||
ValueNumFuncDef(ArithmeticExc, 2, false, false, false) // Arithmetic exception check, ckfinite and integer division overflow, Args: 0: expression value,
|
||||
ValueNumFuncDef(OverflowExc, 1, false, false, false) // Integer overflow check. used for checked add,sub and mul Args: 0: expression value, throws when it overflows
|
||||
ValueNumFuncDef(ConvOverflowExc, 2, false, false, false) // Cast conversion overflow check. Args: 0: input value; 1: var_types of the target type
|
||||
ValueNumFuncDef(NullPtrExc, 1, false, false, false, false) // Null pointer exception check. Args: 0: address value, throws when it is null
|
||||
ValueNumFuncDef(ArithmeticExc, 2, false, false, false, false) // Arithmetic exception check, ckfinite and integer division overflow, Args: 0: expression value,
|
||||
ValueNumFuncDef(OverflowExc, 1, false, false, false, false) // Integer overflow check. used for checked add,sub and mul Args: 0: expression value, throws when it overflows
|
||||
ValueNumFuncDef(ConvOverflowExc, 2, false, false, false, false) // Cast conversion overflow check. Args: 0: input value; 1: var_types of the target type
|
||||
// - (shifted left one bit; low bit encode whether source is unsigned.)
|
||||
ValueNumFuncDef(DivideByZeroExc, 1, false, false, false) // Division by zero check. Args: 0: divisor value, throws when it is zero
|
||||
ValueNumFuncDef(IndexOutOfRangeExc, 2, false, false, false) // Array bounds check, Args: 0: array length; 1: index value, throws when the bounds check fails.
|
||||
ValueNumFuncDef(InvalidCastExc, 2, false, false, false) // CastClass check, Args: 0: ref value being cast; 1: handle of type being cast to, throws when the cast fails.
|
||||
ValueNumFuncDef(NewArrOverflowExc, 1, false, false, false) // Raises Integer overflow when Arg 0 is negative
|
||||
ValueNumFuncDef(HelperMultipleExc, 0, false, false, false) // Represents one or more different exceptions that could be thrown by a Jit Helper method
|
||||
ValueNumFuncDef(DivideByZeroExc, 1, false, false, false, false) // Division by zero check. Args: 0: divisor value, throws when it is zero
|
||||
ValueNumFuncDef(IndexOutOfRangeExc, 2, false, false, false, false) // Array bounds check, Args: 0: array length; 1: index value, throws when the bounds check fails.
|
||||
ValueNumFuncDef(InvalidCastExc, 2, false, false, false, false) // CastClass check, Args: 0: ref value being cast; 1: handle of type being cast to, throws when the cast fails.
|
||||
ValueNumFuncDef(NewArrOverflowExc, 1, false, false, false, false) // Raises Integer overflow when Arg 0 is negative
|
||||
ValueNumFuncDef(HelperMultipleExc, 0, false, false, false, false) // Represents one or more different exceptions that could be thrown by a Jit Helper method
|
||||
|
||||
ValueNumFuncDef(FltRound, 1, false, false, false)
|
||||
ValueNumFuncDef(DblRound, 1, false, false, false)
|
||||
ValueNumFuncDef(FltRound, 1, false, false, false, false)
|
||||
ValueNumFuncDef(DblRound, 1, false, false, false, false)
|
||||
|
||||
ValueNumFuncDef(Abs, 1, false, false, false)
|
||||
ValueNumFuncDef(Acos, 1, false, false, false)
|
||||
ValueNumFuncDef(Acosh, 1, false, false, false)
|
||||
ValueNumFuncDef(Asin, 1, false, false, false)
|
||||
ValueNumFuncDef(Asinh, 1, false, false, false)
|
||||
ValueNumFuncDef(Atan, 1, false, false, false)
|
||||
ValueNumFuncDef(Atanh, 1, false, false, false)
|
||||
ValueNumFuncDef(Atan2, 2, false, false, false)
|
||||
ValueNumFuncDef(Cbrt, 1, false, false, false)
|
||||
ValueNumFuncDef(Ceiling, 1, false, false, false)
|
||||
ValueNumFuncDef(Cos, 1, false, false, false)
|
||||
ValueNumFuncDef(Cosh, 1, false, false, false)
|
||||
ValueNumFuncDef(Exp, 1, false, false, false)
|
||||
ValueNumFuncDef(Floor, 1, false, false, false)
|
||||
ValueNumFuncDef(FMod, 2, false, false, false)
|
||||
ValueNumFuncDef(ILogB, 1, false, false, false)
|
||||
ValueNumFuncDef(Log, 1, false, false, false)
|
||||
ValueNumFuncDef(Log2, 1, false, false, false)
|
||||
ValueNumFuncDef(Log10, 1, false, false, false)
|
||||
ValueNumFuncDef(Max, 2, false, false, false)
|
||||
ValueNumFuncDef(Min, 2, false, false, false)
|
||||
ValueNumFuncDef(Pow, 2, false, false, false)
|
||||
ValueNumFuncDef(RoundDouble, 1, false, false, false)
|
||||
ValueNumFuncDef(RoundInt32, 1, false, false, false)
|
||||
ValueNumFuncDef(RoundSingle, 1, false, false, false)
|
||||
ValueNumFuncDef(Sin, 1, false, false, false)
|
||||
ValueNumFuncDef(Sinh, 1, false, false, false)
|
||||
ValueNumFuncDef(Sqrt, 1, false, false, false)
|
||||
ValueNumFuncDef(Tan, 1, false, false, false)
|
||||
ValueNumFuncDef(Tanh, 1, false, false, false)
|
||||
ValueNumFuncDef(Truncate, 1, false, false, false)
|
||||
ValueNumFuncDef(Abs, 1, false, false, false, false)
|
||||
ValueNumFuncDef(Acos, 1, false, false, false, false)
|
||||
ValueNumFuncDef(Acosh, 1, false, false, false, false)
|
||||
ValueNumFuncDef(Asin, 1, false, false, false, false)
|
||||
ValueNumFuncDef(Asinh, 1, false, false, false, false)
|
||||
ValueNumFuncDef(Atan, 1, false, false, false, false)
|
||||
ValueNumFuncDef(Atanh, 1, false, false, false, false)
|
||||
ValueNumFuncDef(Atan2, 2, false, false, false, false)
|
||||
ValueNumFuncDef(Cbrt, 1, false, false, false, false)
|
||||
ValueNumFuncDef(Ceiling, 1, false, false, false, false)
|
||||
ValueNumFuncDef(Cos, 1, false, false, false, false)
|
||||
ValueNumFuncDef(Cosh, 1, false, false, false, false)
|
||||
ValueNumFuncDef(Exp, 1, false, false, false, false)
|
||||
ValueNumFuncDef(Floor, 1, false, false, false, false)
|
||||
ValueNumFuncDef(FMod, 2, false, false, false, false)
|
||||
ValueNumFuncDef(ILogB, 1, false, false, false, false)
|
||||
ValueNumFuncDef(Log, 1, false, false, false, false)
|
||||
ValueNumFuncDef(Log2, 1, false, false, false, false)
|
||||
ValueNumFuncDef(Log10, 1, false, false, false, false)
|
||||
ValueNumFuncDef(Max, 2, false, false, false, false)
|
||||
ValueNumFuncDef(Min, 2, false, false, false, false)
|
||||
ValueNumFuncDef(Pow, 2, false, false, false, false)
|
||||
ValueNumFuncDef(RoundDouble, 1, false, false, false, false)
|
||||
ValueNumFuncDef(RoundInt32, 1, false, false, false, false)
|
||||
ValueNumFuncDef(RoundSingle, 1, false, false, false, false)
|
||||
ValueNumFuncDef(Sin, 1, false, false, false, false)
|
||||
ValueNumFuncDef(Sinh, 1, false, false, false, false)
|
||||
ValueNumFuncDef(Sqrt, 1, false, false, false, false)
|
||||
ValueNumFuncDef(Tan, 1, false, false, false, false)
|
||||
ValueNumFuncDef(Tanh, 1, false, false, false, false)
|
||||
ValueNumFuncDef(Truncate, 1, false, false, false, false)
|
||||
|
||||
ValueNumFuncDef(ManagedThreadId, 0, false, false, false)
|
||||
ValueNumFuncDef(ManagedThreadId, 0, false, false, false, false)
|
||||
|
||||
ValueNumFuncDef(ObjGetType, 1, false, true, false)
|
||||
ValueNumFuncDef(GetgenericsGcstaticBase, 1, false, true, true)
|
||||
ValueNumFuncDef(GetgenericsNongcstaticBase, 1, false, true, true)
|
||||
ValueNumFuncDef(GetsharedGcstaticBase, 2, false, true, true)
|
||||
ValueNumFuncDef(GetsharedNongcstaticBase, 2, false, true, true)
|
||||
ValueNumFuncDef(GetsharedGcstaticBaseNoctor, 1, false, true, true)
|
||||
ValueNumFuncDef(GetsharedNongcstaticBaseNoctor, 1, false, true, true)
|
||||
ValueNumFuncDef(ReadyToRunStaticBaseGC, 1, false, true, true)
|
||||
ValueNumFuncDef(ReadyToRunStaticBaseNonGC, 1, false, true, true)
|
||||
ValueNumFuncDef(ReadyToRunStaticBaseThread, 1, false, true, true)
|
||||
ValueNumFuncDef(ReadyToRunStaticBaseThreadNonGC, 1, false, true, true)
|
||||
ValueNumFuncDef(ReadyToRunGenericStaticBase, 2, false, true, true)
|
||||
ValueNumFuncDef(GetsharedGcstaticBaseDynamicclass, 2, false, true, true)
|
||||
ValueNumFuncDef(GetsharedNongcstaticBaseDynamicclass, 2, false, true, true)
|
||||
ValueNumFuncDef(GetgenericsGcthreadstaticBase, 1, false, true, true)
|
||||
ValueNumFuncDef(GetgenericsNongcthreadstaticBase, 1, false, true, true)
|
||||
ValueNumFuncDef(GetsharedGcthreadstaticBase, 2, false, true, true)
|
||||
ValueNumFuncDef(GetsharedNongcthreadstaticBase, 2, false, true, true)
|
||||
ValueNumFuncDef(GetsharedGcthreadstaticBaseNoctor, 2, false, true, true)
|
||||
ValueNumFuncDef(GetsharedGcthreadstaticBaseNoctorOptimized, 1, false, true, true)
|
||||
ValueNumFuncDef(GetsharedNongcthreadstaticBaseNoctor, 2, false, true, true)
|
||||
ValueNumFuncDef(GetsharedNongcthreadstaticBaseNoctorOptimized, 1, false, true, true)
|
||||
ValueNumFuncDef(GetsharedGcthreadstaticBaseDynamicclass, 2, false, true, true)
|
||||
ValueNumFuncDef(GetsharedNongcthreadstaticBaseDynamicclass, 2, false, true, true)
|
||||
ValueNumFuncDef(ObjGetType, 1, false, true, false, false)
|
||||
ValueNumFuncDef(GetgenericsGcstaticBase, 1, false, true, true, false)
|
||||
ValueNumFuncDef(GetgenericsNongcstaticBase, 1, false, true, true, false)
|
||||
ValueNumFuncDef(GetsharedGcstaticBase, 2, false, true, true, false)
|
||||
ValueNumFuncDef(GetsharedNongcstaticBase, 2, false, true, true, false)
|
||||
ValueNumFuncDef(GetsharedGcstaticBaseNoctor, 1, false, true, true, false)
|
||||
ValueNumFuncDef(GetsharedNongcstaticBaseNoctor, 1, false, true, true, false)
|
||||
ValueNumFuncDef(ReadyToRunStaticBaseGC, 1, false, true, true, false)
|
||||
ValueNumFuncDef(ReadyToRunStaticBaseNonGC, 1, false, true, true, false)
|
||||
ValueNumFuncDef(ReadyToRunStaticBaseThread, 1, false, true, true, false)
|
||||
ValueNumFuncDef(ReadyToRunStaticBaseThreadNonGC, 1, false, true, true, false)
|
||||
ValueNumFuncDef(ReadyToRunGenericStaticBase, 2, false, true, true, false)
|
||||
ValueNumFuncDef(GetsharedGcstaticBaseDynamicclass, 2, false, true, true, false)
|
||||
ValueNumFuncDef(GetsharedNongcstaticBaseDynamicclass, 2, false, true, true, false)
|
||||
ValueNumFuncDef(GetgenericsGcthreadstaticBase, 1, false, true, true, false)
|
||||
ValueNumFuncDef(GetgenericsNongcthreadstaticBase, 1, false, true, true, false)
|
||||
ValueNumFuncDef(GetsharedGcthreadstaticBase, 2, false, true, true, false)
|
||||
ValueNumFuncDef(GetsharedNongcthreadstaticBase, 2, false, true, true, false)
|
||||
ValueNumFuncDef(GetsharedGcthreadstaticBaseNoctor, 2, false, true, true, false)
|
||||
ValueNumFuncDef(GetsharedGcthreadstaticBaseNoctorOptimized, 1, false, true, true, false)
|
||||
ValueNumFuncDef(GetsharedNongcthreadstaticBaseNoctor, 2, false, true, true, false)
|
||||
ValueNumFuncDef(GetsharedNongcthreadstaticBaseNoctorOptimized, 1, false, true, true, false)
|
||||
ValueNumFuncDef(GetsharedGcthreadstaticBaseDynamicclass, 2, false, true, true, false)
|
||||
ValueNumFuncDef(GetsharedNongcthreadstaticBaseDynamicclass, 2, false, true, true, false)
|
||||
|
||||
ValueNumFuncDef(ClassinitSharedDynamicclass, 2, false, false, false)
|
||||
ValueNumFuncDef(RuntimeHandleMethod, 2, false, true, false)
|
||||
ValueNumFuncDef(RuntimeHandleClass, 2, false, true, false)
|
||||
ValueNumFuncDef(ReadyToRunGenericHandle, 2, false, true, false)
|
||||
ValueNumFuncDef(ClassinitSharedDynamicclass, 2, false, false, false, false)
|
||||
ValueNumFuncDef(RuntimeHandleMethod, 2, false, true, false, false)
|
||||
ValueNumFuncDef(RuntimeHandleClass, 2, false, true, false, false)
|
||||
ValueNumFuncDef(ReadyToRunGenericHandle, 2, false, true, false, false)
|
||||
|
||||
ValueNumFuncDef(GetStaticAddrTLS, 1, false, true, false)
|
||||
ValueNumFuncDef(GetStaticAddrTLS, 1, false, true, false, false)
|
||||
|
||||
ValueNumFuncDef(JitNew, 2, false, true, false)
|
||||
ValueNumFuncDef(JitNewArr, 3, false, true, false)
|
||||
ValueNumFuncDef(JitNewMdArr, 4, false, true, false)
|
||||
ValueNumFuncDef(JitReadyToRunNew, 2, false, true, false)
|
||||
ValueNumFuncDef(JitReadyToRunNewArr, 3, false, true, false)
|
||||
ValueNumFuncDef(Box, 3, false, false, false)
|
||||
ValueNumFuncDef(BoxNullable, 3, false, false, false)
|
||||
ValueNumFuncDef(JitNew, 2, false, true, false, false)
|
||||
ValueNumFuncDef(JitNewArr, 3, false, true, false, false)
|
||||
ValueNumFuncDef(JitNewMdArr, 4, false, true, false, false)
|
||||
ValueNumFuncDef(JitReadyToRunNew, 2, false, true, false, false)
|
||||
ValueNumFuncDef(JitReadyToRunNewArr, 3, false, true, false, false)
|
||||
ValueNumFuncDef(Box, 3, false, false, false, false)
|
||||
ValueNumFuncDef(BoxNullable, 3, false, false, false, false)
|
||||
|
||||
ValueNumFuncDef(LazyStrCns, 2, false, true, false) // Lazy-initialized string literal (helper)
|
||||
ValueNumFuncDef(InvariantLoad, 1, false, false, false) // Args: 0: (VN of) the address.
|
||||
ValueNumFuncDef(InvariantNonNullLoad, 1, false, true, false) // Args: 0: (VN of) the address.
|
||||
ValueNumFuncDef(Unbox, 2, false, true, false)
|
||||
ValueNumFuncDef(LazyStrCns, 2, false, true, false, false) // Lazy-initialized string literal (helper)
|
||||
ValueNumFuncDef(InvariantLoad, 1, false, false, false, false) // Args: 0: (VN of) the address.
|
||||
ValueNumFuncDef(InvariantNonNullLoad, 1, false, true, false, false) // Args: 0: (VN of) the address.
|
||||
ValueNumFuncDef(Unbox, 2, false, true, false, false)
|
||||
|
||||
ValueNumFuncDef(LT_UN, 2, false, false, false) // unsigned or unordered comparisons
|
||||
ValueNumFuncDef(LE_UN, 2, false, false, false)
|
||||
ValueNumFuncDef(GE_UN, 2, false, false, false)
|
||||
ValueNumFuncDef(GT_UN, 2, false, false, false)
|
||||
ValueNumFuncDef(LT_UN, 2, false, false, false, false) // unsigned or unordered comparisons
|
||||
ValueNumFuncDef(LE_UN, 2, false, false, false, false)
|
||||
ValueNumFuncDef(GE_UN, 2, false, false, false, false)
|
||||
ValueNumFuncDef(GT_UN, 2, false, false, false, false)
|
||||
|
||||
ValueNumFuncDef(ADD_OVF, 2, true, false, false) // overflow checking operations
|
||||
ValueNumFuncDef(SUB_OVF, 2, false, false, false)
|
||||
ValueNumFuncDef(MUL_OVF, 2, true, false, false)
|
||||
ValueNumFuncDef(ADD_OVF, 2, true, false, false, false) // overflow checking operations
|
||||
ValueNumFuncDef(SUB_OVF, 2, false, false, false, false)
|
||||
ValueNumFuncDef(MUL_OVF, 2, true, false, false, false)
|
||||
|
||||
ValueNumFuncDef(ADD_UN_OVF, 2, true, false, false) // unsigned overflow checking operations
|
||||
ValueNumFuncDef(SUB_UN_OVF, 2, false, false, false)
|
||||
ValueNumFuncDef(MUL_UN_OVF, 2, true, false, false)
|
||||
ValueNumFuncDef(ADD_UN_OVF, 2, true, false, false, false) // unsigned overflow checking operations
|
||||
ValueNumFuncDef(SUB_UN_OVF, 2, false, false, false, false)
|
||||
ValueNumFuncDef(MUL_UN_OVF, 2, true, false, false, false)
|
||||
|
||||
#ifdef FEATURE_SIMD
|
||||
ValueNumFuncDef(SimdType, 2, false, false, false) // A value number function to compose a SIMD type
|
||||
ValueNumFuncDef(SimdType, 2, false, false, false, false) // A value number function to compose a SIMD type
|
||||
#endif
|
||||
|
||||
#if defined(TARGET_XARCH)
|
||||
#define HARDWARE_INTRINSIC(isa, name, size, argCount, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, category, flag) \
|
||||
ValueNumFuncDef(HWI_##isa##_##name, argCount, false, false, false) // All of the HARDWARE_INTRINSICS for x86/x64
|
||||
#define HARDWARE_INTRINSIC(isa, name, size, argCount, extra, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, category, flag) \
|
||||
ValueNumFuncDef(HWI_##isa##_##name, argCount, ((flag) & HW_Flag_Commutative) >> 0, false, false, extra) // All of the HARDWARE_INTRINSICS for x86/x64
|
||||
#include "hwintrinsiclistxarch.h"
|
||||
#define VNF_HWI_FIRST VNF_HWI_Vector128_Abs
|
||||
|
||||
#elif defined (TARGET_ARM64)
|
||||
#define HARDWARE_INTRINSIC(isa, name, size, argCount, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, category, flag) \
|
||||
ValueNumFuncDef(HWI_##isa##_##name, argCount, false, false, false) // All of the HARDWARE_INTRINSICS for arm64
|
||||
#define HARDWARE_INTRINSIC(isa, name, size, argCount, extra, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, category, flag) \
|
||||
ValueNumFuncDef(HWI_##isa##_##name, argCount, ((flag) & HW_Flag_Commutative) >> 0, false, false, extra) // All of the HARDWARE_INTRINSICS for arm64
|
||||
#include "hwintrinsiclistarm64.h"
|
||||
#define VNF_HWI_FIRST VNF_HWI_Vector64_Abs
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue