summaryrefslogtreecommitdiff
path: root/src/jit/gentree.cpp
diff options
context:
space:
mode:
authorAndy Ayers <andya@microsoft.com>2019-04-11 16:45:30 -0700
committerGitHub <noreply@github.com>2019-04-11 16:45:30 -0700
commit759e3777aad6e711c6c6171ee738df9f38e877a0 (patch)
tree72a55e59d675d726ac9f762d617b662591a724a5 /src/jit/gentree.cpp
parentbf20ae796436e04a6c2f13231fee54468c524688 (diff)
downloadcoreclr-759e3777aad6e711c6c6171ee738df9f38e877a0.tar.gz
coreclr-759e3777aad6e711c6c6171ee738df9f38e877a0.tar.bz2
coreclr-759e3777aad6e711c6c6171ee738df9f38e877a0.zip
JIT: fix assert when there are mixed types in Enum.HasFlags optimization (#23902)
In some cases the pre-boxed nodes may differ in type. Bail if they don't have the same stack type, then compute the result using the stack type. Extended the hasflags test with a case that shows this issue. Closes #23847
Diffstat (limited to 'src/jit/gentree.cpp')
-rw-r--r--src/jit/gentree.cpp25
1 files changed, 18 insertions, 7 deletions
diff --git a/src/jit/gentree.cpp b/src/jit/gentree.cpp
index 45cc22e261..be064c285a 100644
--- a/src/jit/gentree.cpp
+++ b/src/jit/gentree.cpp
@@ -12920,7 +12920,8 @@ GenTree* Compiler::gtOptimizeEnumHasFlag(GenTree* thisOp, GenTree* flagOp)
return nullptr;
}
- GenTree* flagVal = gtTryRemoveBoxUpstreamEffects(flagOp, BR_REMOVE_BUT_NOT_NARROW);
+ // Do likewise with flagOp.
+ GenTree* flagVal = gtTryRemoveBoxUpstreamEffects(flagOp, BR_DONT_REMOVE);
if (flagVal == nullptr)
{
// Note we may fail here if the flag operand comes from
@@ -12929,19 +12930,29 @@ GenTree* Compiler::gtOptimizeEnumHasFlag(GenTree* thisOp, GenTree* flagOp)
return nullptr;
}
+ // Only proceed when both box sources have the same actual type.
+ // (this rules out long/int mismatches)
+ if (genActualType(thisVal->TypeGet()) != genActualType(flagVal->TypeGet()))
+ {
+ JITDUMP("bailing, pre-boxed values have different types\n");
+ return nullptr;
+ }
+
// Yes, both boxes can be cleaned up. Optimize.
JITDUMP("Optimizing call to Enum.HasFlag\n");
- // Undo the boxing of thisOp and prepare to operate directly
- // on the original enum values.
+ // Undo the boxing of the Ops and prepare to operate directly
+ // on the pre-boxed values.
thisVal = gtTryRemoveBoxUpstreamEffects(thisOp, BR_REMOVE_BUT_NOT_NARROW);
+ flagVal = gtTryRemoveBoxUpstreamEffects(flagOp, BR_REMOVE_BUT_NOT_NARROW);
- // Our trial removal above should guarantee successful removal here.
+ // Our trial removals above should guarantee successful removals here.
assert(thisVal != nullptr);
+ assert(flagVal != nullptr);
+ assert(genActualType(thisVal->TypeGet()) == genActualType(flagVal->TypeGet()));
- // We should have a consistent view of the type
- var_types type = thisVal->TypeGet();
- assert(type == flagVal->TypeGet());
+ // Type to use for optimized check
+ var_types type = genActualType(thisVal->TypeGet());
// The thisVal and flagVal trees come from earlier statements.
//