summaryrefslogtreecommitdiff
path: root/src/jit/decomposelongs.cpp
diff options
context:
space:
mode:
authorMike Danes <onemihaid@hotmail.com>2017-01-07 11:13:23 +0200
committerMike Danes <onemihaid@hotmail.com>2017-01-19 23:23:48 +0200
commitfb4447a69646dd7e1f492aa543c9485f0ee9b5b9 (patch)
tree7e8a163b966d8f90d4d77ff760a1b8310d367001 /src/jit/decomposelongs.cpp
parent39bc5ca53f936b83c1d380cb6076570ec43abcea (diff)
downloadcoreclr-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.cpp37
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);