diff options
author | Mike Danes <onemihaid@hotmail.com> | 2017-01-07 11:13:23 +0200 |
---|---|---|
committer | Mike Danes <onemihaid@hotmail.com> | 2017-01-19 23:23:48 +0200 |
commit | fb4447a69646dd7e1f492aa543c9485f0ee9b5b9 (patch) | |
tree | 7e8a163b966d8f90d4d77ff760a1b8310d367001 /src/jit/decomposelongs.cpp | |
parent | 39bc5ca53f936b83c1d380cb6076570ec43abcea (diff) | |
download | coreclr-fb4447a69646dd7e1f492aa543c9485f0ee9b5b9.tar.gz coreclr-fb4447a69646dd7e1f492aa543c9485f0ee9b5b9.tar.bz2 coreclr-fb4447a69646dd7e1f492aa543c9485f0ee9b5b9.zip |
Improve int->long cast decomposition
If the cast is used by a GT_MUL then don't decompose it. This avoids producing dead code that's more difficult to remove later.
Diffstat (limited to 'src/jit/decomposelongs.cpp')
-rw-r--r-- | src/jit/decomposelongs.cpp | 37 |
1 files changed, 27 insertions, 10 deletions
diff --git a/src/jit/decomposelongs.cpp b/src/jit/decomposelongs.cpp index 2716631abc..beb193fe56 100644 --- a/src/jit/decomposelongs.cpp +++ b/src/jit/decomposelongs.cpp @@ -574,6 +574,8 @@ GenTree* DecomposeLongs::DecomposeCast(LIR::Use& use) srcType = genUnsignedType(srcType); } + bool skipDecomposition = false; + if (varTypeIsLong(srcType)) { if (cast->gtOverflow() && (varTypeIsUnsigned(srcType) != varTypeIsUnsigned(dstType))) @@ -628,7 +630,20 @@ GenTree* DecomposeLongs::DecomposeCast(LIR::Use& use) } else { - if (varTypeIsUnsigned(srcType)) + if (!use.IsDummyUse() && (use.User()->OperGet() == GT_MUL)) + { + // + // This int->long cast is used by a GT_MUL that will be transformed by DecomposeMul into a + // GT_LONG_MUL and as a result the high operand produced by the cast will become dead. + // Skip cast decomposition so DecomposeMul doesn't need to bother with dead code removal, + // especially in the case of sign extending casts that also introduce new lclvars. + // + + assert((use.User()->gtFlags & GTF_MUL_64RSLT) != 0); + + skipDecomposition = true; + } + else if (varTypeIsUnsigned(srcType)) { loResult = cast->gtGetOp1(); hiResult = m_compiler->gtNewZeroConNode(TYP_INT); @@ -658,6 +673,11 @@ GenTree* DecomposeLongs::DecomposeCast(LIR::Use& use) NYI("Unimplemented cast decomposition"); } + if (skipDecomposition) + { + return cast->gtNext; + } + return FinalizeDecomposition(use, loResult, hiResult, hiResult); } @@ -1480,19 +1500,16 @@ GenTree* DecomposeLongs::DecomposeMul(LIR::Use& use) GenTree* op1 = tree->gtGetOp1(); GenTree* op2 = tree->gtGetOp2(); - GenTree* loOp1 = op1->gtGetOp1(); - GenTree* hiOp1 = op1->gtGetOp2(); - GenTree* loOp2 = op2->gtGetOp1(); - GenTree* hiOp2 = op2->gtGetOp2(); + // We expect both operands to be int->long casts. DecomposeCast specifically + // ignores such casts when they are used by GT_MULs. + assert((op1->OperGet() == GT_CAST) && (op1->TypeGet() == TYP_LONG)); + assert((op2->OperGet() == GT_CAST) && (op2->TypeGet() == TYP_LONG)); - Range().Remove(hiOp1); - Range().Remove(hiOp2); Range().Remove(op1); Range().Remove(op2); - // Get rid of the hi ops. We don't need them. - tree->gtOp.gtOp1 = loOp1; - tree->gtOp.gtOp2 = loOp2; + tree->gtOp.gtOp1 = op1->gtGetOp1(); + tree->gtOp.gtOp2 = op2->gtGetOp1(); tree->SetOperRaw(GT_MUL_LONG); return StoreNodeToVar(use); |