summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPat Gavlin <pagavlin@microsoft.com>2017-07-13 12:59:29 -0700
committerPat Gavlin <pagavlin@microsoft.com>2017-08-09 08:12:39 -0700
commit61dc4c01f046812b1341eecaccdce951f11d02b8 (patch)
tree2c5b2fd50243f913244201117efa28fd1ca3ada4 /src
parentd98f9272f5acae92279f9fa1f83320e78a6e5201 (diff)
downloadcoreclr-61dc4c01f046812b1341eecaccdce951f11d02b8.tar.gz
coreclr-61dc4c01f046812b1341eecaccdce951f11d02b8.tar.bz2
coreclr-61dc4c01f046812b1341eecaccdce951f11d02b8.zip
Fix VSO 462269.
When decomposing a long compare on 32-bit platforms, the operands to the decomposed compare must be sign- or zero-extended appropriately.
Diffstat (limited to 'src')
-rw-r--r--src/jit/decomposelongs.cpp44
-rw-r--r--src/jit/decomposelongs.h1
2 files changed, 43 insertions, 2 deletions
diff --git a/src/jit/decomposelongs.cpp b/src/jit/decomposelongs.cpp
index 96d3b0bb71..7cf1049ef4 100644
--- a/src/jit/decomposelongs.cpp
+++ b/src/jit/decomposelongs.cpp
@@ -607,7 +607,8 @@ GenTree* DecomposeLongs::DecomposeCast(LIR::Use& use)
// check provided by codegen.
//
- loResult = loSrcOp;
+ const bool signExtend = (cast->gtFlags & GTF_UNSIGNED) == 0;
+ loResult = EnsureIntSized(loSrcOp, signExtend);
hiResult = cast;
hiResult->gtType = TYP_INT;
@@ -657,7 +658,9 @@ GenTree* DecomposeLongs::DecomposeCast(LIR::Use& use)
}
else if (varTypeIsUnsigned(srcType))
{
- loResult = cast->gtGetOp1();
+ const bool signExtend = (cast->gtFlags & GTF_UNSIGNED) == 0;
+ loResult = EnsureIntSized(cast->gtGetOp1(), signExtend);
+
hiResult = m_compiler->gtNewZeroConNode(TYP_INT);
Range().InsertAfter(cast, hiResult);
@@ -1918,6 +1921,43 @@ GenTree* DecomposeLongs::RepresentOpAsLocalVar(GenTree* op, GenTree* user, GenTr
}
//------------------------------------------------------------------------
+// DecomposeLongs::EnsureIntSized:
+// Checks to see if the given node produces an int-sized value and
+// performs the appropriate widening if it does not.
+//
+// Arguments:
+// node - The node that may need to be widened.
+// signExtend - True if the value should be sign-extended; false if it
+// should be zero-extended.
+//
+// Return Value:
+// The node that produces the widened value.
+GenTree* DecomposeLongs::EnsureIntSized(GenTree* node, bool signExtend)
+{
+ assert(node != nullptr);
+ if (!varTypeIsSmall(node))
+ {
+ assert(genTypeSize(node) == genTypeSize(TYP_INT));
+ return node;
+ }
+
+ if (node->OperIs(GT_LCL_VAR) && !m_compiler->lvaTable[node->AsLclVarCommon()->gtLclNum].lvNormalizeOnLoad())
+ {
+ node->gtType = TYP_INT;
+ return node;
+ }
+
+ GenTree* const cast = m_compiler->gtNewCastNode(TYP_INT, node, node->TypeGet());
+ if (!signExtend)
+ {
+ cast->gtFlags |= GTF_UNSIGNED;
+ }
+
+ Range().InsertAfter(node, cast);
+ return cast;
+}
+
+//------------------------------------------------------------------------
// GetHiOper: Convert arithmetic operator to "high half" operator of decomposed node.
//
// Arguments:
diff --git a/src/jit/decomposelongs.h b/src/jit/decomposelongs.h
index ff4f4ac880..7a0d6ff5ba 100644
--- a/src/jit/decomposelongs.h
+++ b/src/jit/decomposelongs.h
@@ -61,6 +61,7 @@ private:
// Helper functions
GenTree* FinalizeDecomposition(LIR::Use& use, GenTree* loResult, GenTree* hiResult, GenTree* insertResultAfter);
GenTree* RepresentOpAsLocalVar(GenTree* op, GenTree* user, GenTree** edge);
+ GenTree* EnsureIntSized(GenTree* node, bool signExtend);
GenTree* StoreNodeToVar(LIR::Use& use);
static genTreeOps GetHiOper(genTreeOps oper);