diff options
author | Pat Gavlin <pagavlin@microsoft.com> | 2017-07-13 12:59:29 -0700 |
---|---|---|
committer | Pat Gavlin <pagavlin@microsoft.com> | 2017-08-09 08:12:39 -0700 |
commit | 61dc4c01f046812b1341eecaccdce951f11d02b8 (patch) | |
tree | 2c5b2fd50243f913244201117efa28fd1ca3ada4 /src | |
parent | d98f9272f5acae92279f9fa1f83320e78a6e5201 (diff) | |
download | coreclr-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.cpp | 44 | ||||
-rw-r--r-- | src/jit/decomposelongs.h | 1 |
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); |