summaryrefslogtreecommitdiff
path: root/src/jit
diff options
context:
space:
mode:
authorJan Kotas <jkotas@microsoft.com>2019-04-01 16:20:55 -0700
committerGitHub <noreply@github.com>2019-04-01 16:20:55 -0700
commit13bc9b70459936da9c01c6774af6ac46431a11d2 (patch)
tree70726e19630ae0aec9188281a39f1a2dc9656146 /src/jit
parent8b0dae626f6bff194f31ba04840075344d89b4c3 (diff)
downloadcoreclr-13bc9b70459936da9c01c6774af6ac46431a11d2.tar.gz
coreclr-13bc9b70459936da9c01c6774af6ac46431a11d2.tar.bz2
coreclr-13bc9b70459936da9c01c6774af6ac46431a11d2.zip
Match BOX idioms early in the importer (#23550)
Diffstat (limited to 'src/jit')
-rw-r--r--src/jit/compiler.h1
-rw-r--r--src/jit/importer.cpp140
2 files changed, 123 insertions, 18 deletions
diff --git a/src/jit/compiler.h b/src/jit/compiler.h
index 80b2e550f6..400e61b1f3 100644
--- a/src/jit/compiler.h
+++ b/src/jit/compiler.h
@@ -3569,6 +3569,7 @@ protected:
GenTree* impImportLdvirtftn(GenTree* thisPtr, CORINFO_RESOLVED_TOKEN* pResolvedToken, CORINFO_CALL_INFO* pCallInfo);
+ int impBoxPatternMatch(CORINFO_RESOLVED_TOKEN* pResolvedToken, const BYTE* codeAddr, const BYTE* codeEndp);
void impImportAndPushBox(CORINFO_RESOLVED_TOKEN* pResolvedToken);
void impImportNewObjArray(CORINFO_RESOLVED_TOKEN* pResolvedToken, CORINFO_CALL_INFO* pCallInfo);
diff --git a/src/jit/importer.cpp b/src/jit/importer.cpp
index a69d5589a9..244605cf09 100644
--- a/src/jit/importer.cpp
+++ b/src/jit/importer.cpp
@@ -5693,6 +5693,122 @@ GenTree* Compiler::impImportLdvirtftn(GenTree* thisPtr,
}
//------------------------------------------------------------------------
+// impBoxPatternMatch: match and import common box idioms
+//
+// Arguments:
+// pResolvedToken - resolved token from the box operation
+// codeAddr - position in IL stream after the box instruction
+// codeEndp - end of IL stream
+//
+// Return Value:
+// Number of IL bytes matched and imported, -1 otherwise
+//
+
+int Compiler::impBoxPatternMatch(CORINFO_RESOLVED_TOKEN* pResolvedToken, const BYTE* codeAddr, const BYTE* codeEndp)
+{
+ if (codeAddr >= codeEndp)
+ {
+ return -1;
+ }
+
+ switch (codeAddr[0])
+ {
+ case CEE_UNBOX_ANY:
+ // box + unbox.any
+ if (codeAddr + 1 + sizeof(mdToken) <= codeEndp)
+ {
+ CORINFO_RESOLVED_TOKEN unboxResolvedToken;
+
+ impResolveToken(codeAddr + 1, &unboxResolvedToken, CORINFO_TOKENKIND_Class);
+
+ // See if the resolved tokens describe types that are equal.
+ const TypeCompareState compare =
+ info.compCompHnd->compareTypesForEquality(unboxResolvedToken.hClass, pResolvedToken->hClass);
+
+ // If so, box/unbox.any is a nop.
+ if (compare == TypeCompareState::Must)
+ {
+ JITDUMP("\n Importing BOX; UNBOX.ANY as NOP\n");
+ // Skip the next unbox.any instruction
+ return 1 + sizeof(mdToken);
+ }
+ }
+ break;
+
+ case CEE_BRTRUE:
+ case CEE_BRTRUE_S:
+ case CEE_BRFALSE:
+ case CEE_BRFALSE_S:
+ // box + br_true/false
+ if ((codeAddr + ((codeAddr[0] >= CEE_BRFALSE) ? 5 : 2)) <= codeEndp)
+ {
+ if (!(impStackTop().val->gtFlags & GTF_SIDE_EFFECT))
+ {
+ CorInfoHelpFunc boxHelper = info.compCompHnd->getBoxHelper(pResolvedToken->hClass);
+ if (boxHelper == CORINFO_HELP_BOX)
+ {
+ JITDUMP("\n Importing BOX; BR_TRUE/FALSE as constant\n");
+ impPopStack();
+
+ impPushOnStack(gtNewIconNode(1), typeInfo(TI_INT));
+ return 0;
+ }
+ }
+ }
+ break;
+
+ case CEE_ISINST:
+ // box + isinst + br_true/false
+ if (codeAddr + 1 + sizeof(mdToken) + 1 <= codeEndp)
+ {
+ const BYTE* nextCodeAddr = codeAddr + 1 + sizeof(mdToken);
+
+ switch (nextCodeAddr[0])
+ {
+ case CEE_BRTRUE:
+ case CEE_BRTRUE_S:
+ case CEE_BRFALSE:
+ case CEE_BRFALSE_S:
+ if ((nextCodeAddr + ((nextCodeAddr[0] >= CEE_BRFALSE) ? 5 : 2)) <= codeEndp)
+ {
+ if (!(impStackTop().val->gtFlags & GTF_SIDE_EFFECT))
+ {
+ CorInfoHelpFunc boxHelper = info.compCompHnd->getBoxHelper(pResolvedToken->hClass);
+ if (boxHelper == CORINFO_HELP_BOX)
+ {
+ CORINFO_RESOLVED_TOKEN isInstResolvedToken;
+
+ impResolveToken(codeAddr + 1, &isInstResolvedToken, CORINFO_TOKENKIND_Casting);
+
+ TypeCompareState castResult =
+ info.compCompHnd->compareTypesForCast(pResolvedToken->hClass,
+ isInstResolvedToken.hClass);
+ if (castResult != TypeCompareState::May)
+ {
+ JITDUMP("\n Importing BOX; ISINST; BR_TRUE/FALSE as constant\n");
+ impPopStack();
+
+ impPushOnStack(gtNewIconNode((castResult == TypeCompareState::Must) ? 1 : 0),
+ typeInfo(TI_INT));
+
+ // Skip the next isinst instruction
+ return 1 + sizeof(mdToken);
+ }
+ }
+ }
+ }
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return -1;
+}
+
+//------------------------------------------------------------------------
// impImportAndPushBox: build and import a value-type box
//
// Arguments:
@@ -15163,25 +15279,13 @@ void Compiler::impImportBlockCode(BasicBlock* block)
break;
}
- // Look ahead for unbox.any
- if (codeAddr + (sz + 1 + sizeof(mdToken)) <= codeEndp && codeAddr[sz] == CEE_UNBOX_ANY)
+ // Look ahead for box idioms
+ int matched = impBoxPatternMatch(&resolvedToken, codeAddr + sz, codeEndp);
+ if (matched >= 0)
{
- CORINFO_RESOLVED_TOKEN unboxResolvedToken;
-
- impResolveToken(codeAddr + (sz + 1), &unboxResolvedToken, CORINFO_TOKENKIND_Class);
-
- // See if the resolved tokens describe types that are equal.
- const TypeCompareState compare =
- info.compCompHnd->compareTypesForEquality(unboxResolvedToken.hClass, resolvedToken.hClass);
-
- // If so, box/unbox.any is a nop.
- if (compare == TypeCompareState::Must)
- {
- JITDUMP("\n Importing BOX; UNBOX.ANY as NOP\n");
- // Skip the next unbox.any instruction
- sz += sizeof(mdToken) + 1;
- break;
- }
+ // Skip the matched IL instructions
+ sz += matched;
+ break;
}
impImportAndPushBox(&resolvedToken);