diff options
author | Andy Ayers <andya@microsoft.com> | 2019-04-11 16:45:30 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-04-11 16:45:30 -0700 |
commit | 759e3777aad6e711c6c6171ee738df9f38e877a0 (patch) | |
tree | 72a55e59d675d726ac9f762d617b662591a724a5 /src/jit/gentree.cpp | |
parent | bf20ae796436e04a6c2f13231fee54468c524688 (diff) | |
download | coreclr-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.cpp | 25 |
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. // |