From 197e6619adf3d5b9f7a0c2c1320a0b4bc3363776 Mon Sep 17 00:00:00 2001 From: Joseph Tremoulet Date: Fri, 14 Oct 2016 14:10:10 -0400 Subject: [PATCH 1/2] Add GTF_ICON_SIMD_COUNT flag This flag is used to indicate that an integer constant in the IR is the result of replacing the Vector.Count intrinsic. This can be used to drive heuristics focusing more aggressive optimizations on SIMD code. --- src/jit/gentree.cpp | 7 +++++++ src/jit/gentree.h | 2 ++ src/jit/simd.cpp | 2 ++ 3 files changed, 11 insertions(+) diff --git a/src/jit/gentree.cpp b/src/jit/gentree.cpp index d1e48f0e803a..236edf03fe52 100644 --- a/src/jit/gentree.cpp +++ b/src/jit/gentree.cpp @@ -10716,6 +10716,13 @@ void Compiler::gtDispConst(GenTree* tree) printf(" field offset"); } +#ifdef FEATURE_SIMD + if ((tree->gtFlags & GTF_ICON_SIMD_COUNT) != 0) + { + printf(" Vector.Count"); + } +#endif + if ((tree->IsReuseRegVal()) != 0) { printf(" reuse reg val"); diff --git a/src/jit/gentree.h b/src/jit/gentree.h index 64a6d0065602..5f3e7139e735 100644 --- a/src/jit/gentree.h +++ b/src/jit/gentree.h @@ -933,6 +933,8 @@ struct GenTree #define GTF_ICON_FIELD_OFF 0x08000000 // GT_CNS_INT -- constant is a field offset +#define GTF_ICON_SIMD_COUNT 0x04000000 // GT_CNS_INT -- constant is Vector.Count + #define GTF_BLK_VOLATILE 0x40000000 // GT_ASG, GT_STORE_BLK, GT_STORE_OBJ, GT_STORE_DYNBLK // -- is a volatile block operation #define GTF_BLK_UNALIGNED 0x02000000 // GT_ASG, GT_STORE_BLK, GT_STORE_OBJ, GT_STORE_DYNBLK diff --git a/src/jit/simd.cpp b/src/jit/simd.cpp index 0de38c8398d6..218b69ccb8b4 100644 --- a/src/jit/simd.cpp +++ b/src/jit/simd.cpp @@ -1812,6 +1812,8 @@ GenTreePtr Compiler::impSIMDIntrinsic(OPCODE opcode, int length = getSIMDVectorLength(clsHnd); GenTreeIntCon* intConstTree = new (this, GT_CNS_INT) GenTreeIntCon(TYP_INT, length); retVal = intConstTree; + + intConstTree->gtFlags |= GTF_ICON_SIMD_COUNT; } break; From d2e74ab5dd97c0a93306083c95a9a72d6a105d27 Mon Sep 17 00:00:00 2001 From: Joseph Tremoulet Date: Fri, 14 Oct 2016 14:11:29 -0400 Subject: [PATCH 2/2] Add LPFLG_SIMD_LIMIT flag This flag identifies loops whose limit was a Vector.Count expression. This can be used in heuristics to target more aggressive optimizations at SIMD code. --- src/jit/compiler.h | 1 + src/jit/optimizer.cpp | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/src/jit/compiler.h b/src/jit/compiler.h index 7d049d75dd96..867a8545ef9b 100644 --- a/src/jit/compiler.h +++ b/src/jit/compiler.h @@ -4938,6 +4938,7 @@ class Compiler #define LPFLG_VAR_LIMIT 0x0100 // iterator is compared with a local var (var # found in lpVarLimit) #define LPFLG_CONST_LIMIT 0x0200 // iterator is compared with a constant (found in lpConstLimit) #define LPFLG_ARRLEN_LIMIT 0x0400 // iterator is compared with a.len or a[i].len (found in lpArrLenLimit) +#define LPFLG_SIMD_LIMIT 0x0080 // iterator is compared with Vector.Count (found in lpConstLimit) #define LPFLG_HAS_PREHEAD 0x0800 // lpHead is known to be a preHead for this loop #define LPFLG_REMOVED 0x1000 // has been removed from the loop table (unrolled or optimized away) diff --git a/src/jit/optimizer.cpp b/src/jit/optimizer.cpp index fdcd1d11af23..2781eaca4b29 100644 --- a/src/jit/optimizer.cpp +++ b/src/jit/optimizer.cpp @@ -822,6 +822,10 @@ bool Compiler::optCheckIterInLoopTest( if (limitOp->gtOper == GT_CNS_INT) { optLoopTable[loopInd].lpFlags |= LPFLG_CONST_LIMIT; + if ((limitOp->gtFlags & GTF_ICON_SIMD_COUNT) != 0) + { + optLoopTable[loopInd].lpFlags |= LPFLG_SIMD_LIMIT; + } } else if (limitOp->gtOper == GT_LCL_VAR && !optIsVarAssigned(from, to, nullptr, limitOp->gtLclVarCommon.gtLclNum)) {