When the result of a TYP_LONG operation is not used the GT_LONG node inserted during decomposition remains in the tree and unlike other GT_LONG nodes is not contained and needs special handling.
This usually happens with arithmetic operations that require overflow checks, the result of the operation may be ignored but the operation itself cannot be eliminated because it has a side-effect.
Commit migrated from https://github.com/dotnet/coreclr/commit/
6f8f2154825b1cf17fbbba8ccb365069e2d7d15f
genProduceReg(treeNode);
break;
+#if !defined(_TARGET_64BIT_)
+ case GT_LONG:
+ assert(!treeNode->isContained());
+ genConsumeRegs(treeNode);
+ break;
+#endif
+
default:
{
#ifdef DEBUG
#endif
return false;
+#if !defined(LEGACY_BACKEND) && !defined(_TARGET_64BIT_)
+ case GT_LONG:
+ // GT_LONG nodes are normally contained. The only exception is when the result
+ // of a TYP_LONG operation is not used and this can only happen if the GT_LONG
+ // is the last node in the statement (in linear order).
+ return gtNext != nullptr;
+#endif
+
case GT_CALL:
// Note: if you hit this assert you are probably calling isContained()
// before the LSRA phase has allocated physical register to the tree nodes
#if !defined(_TARGET_64BIT_)
case GT_LONG:
- // Passthrough
- info->srcCount = 0;
+ if (tree->gtNext == nullptr)
+ {
+ // An uncontained GT_LONG node needs to consume its source operands
+ info->srcCount = 2;
+ }
+ else
+ {
+ // Passthrough
+ info->srcCount = 0;
+ }
info->dstCount = 0;
break;