{
assert(IsLIR());
+ if (gtHasReg())
+ {
+ return false;
+ }
+
// It is not possible for nodes that do not produce values or that are not containable values
// to be contained.
- return (OperKind() & (GTK_NOVALUE | GTK_NOCONTAIN)) == 0;
+ if ((OperKind() & (GTK_NOVALUE | GTK_NOCONTAIN)) != 0)
+ {
+ return false;
+ }
+
+ return true;
}
//------------------------------------------------------------------------
const bool isMarkedContained = ((gtFlags & GTF_CONTAINED) != 0);
#ifdef DEBUG
- if (!canBeContained() || gtHasReg())
+ if (!canBeContained())
{
assert(!isMarkedContained);
}
// if it's contained it better have a user
if (isMarkedContained)
{
- assert((gtNext != nullptr) || OperIsLocal());
+ assert(gtNext != nullptr);
}
#endif // DEBUG
return isMarkedContained;
GTNODE(REG_VAR , GenTreeLclVar ,0,GTK_LEAF|GTK_LOCAL) // register variable
GTNODE(CLS_VAR , GenTreeClsVar ,0,GTK_LEAF) // static data member
GTNODE(CLS_VAR_ADDR , GenTreeClsVar ,0,GTK_LEAF) // static data member address
-GTNODE(ARGPLACE , GenTreeArgPlace ,0,GTK_LEAF) // placeholder for a register arg
+GTNODE(ARGPLACE , GenTreeArgPlace ,0,GTK_LEAF|GTK_NOVALUE) // placeholder for a register arg
GTNODE(NULLCHECK , GenTreeOp ,0,GTK_UNOP|GTK_NOVALUE) // null checks the source
GTNODE(PHYSREG , GenTreePhysReg ,0,GTK_LEAF) // read from a physical register
GTNODE(EMITNOP , GenTree ,0,GTK_LEAF|GTK_NOVALUE) // emitter-placed nop
assert(!(checkUnusedValues && def->IsUnusedValue()) && "operands should never be marked as unused values");
- if (def->OperGet() == GT_ARGPLACE)
- {
- // ARGPLACE nodes are not represented in the LIR sequence. Ignore them.
- continue;
- }
- else if (!def->IsValue())
+ if (!def->IsValue())
{
// Stack arguments do not produce a value, but they are considered children of the call.
// It may be useful to remove these from being call operands, but that may also impact
// other code that relies on being able to reach all the operands from a call node.
// The GT_NOP case is because sometimes we eliminate stack argument stores as dead, but
// instead of removing them we replace with a NOP.
+ // ARGPLACE nodes are not represented in the LIR sequence. Ignore them.
assert((node->OperGet() == GT_CALL) &&
- (def->OperIsStore() || (def->OperGet() == GT_PUTARG_STK) || (def->OperGet() == GT_NOP)));
+ (def->OperIsStore() || def->OperIs(GT_PUTARG_STK, GT_NOP, GT_ARGPLACE)));
continue;
}
assert(!parentNode->OperIsLeaf());
assert(childNode->canBeContained());
childNode->SetContained();
+ assert(childNode->isContained());
}
//------------------------------------------------------------------------
//
void Lowering::ContainCheckCallOperands(GenTreeCall* call)
{
- GenTree* ctrlExpr = call->gtControlExpr;
- // If there is an explicit this pointer, we don't want that node to produce anything
- // as it is redundant
- if (call->gtCallObjp != nullptr)
- {
- GenTreePtr thisPtrNode = call->gtCallObjp;
-
- if (thisPtrNode->canBeContained())
- {
- MakeSrcContained(call, thisPtrNode);
- if (thisPtrNode->gtOper == GT_PUTARG_REG)
- {
- MakeSrcContained(call, thisPtrNode->gtOp.gtOp1);
- }
- }
- }
+ // There are no contained operands for arm.
}
//------------------------------------------------------------------------
#endif // _TARGET_X86_
if (ctrlExpr->isIndir())
{
- MakeSrcContained(call, ctrlExpr);
// We may have cases where we have set a register target on the ctrlExpr, but if it
// contained we must clear it.
ctrlExpr->gtRegNum = REG_NA;
- }
- }
- }
- // If there is an explicit this pointer, we don't want that node to produce anything
- // as it is redundant
- if (call->gtCallObjp != nullptr)
- {
- GenTreePtr thisPtrNode = call->gtCallObjp;
-
- if (thisPtrNode->canBeContained())
- {
- MakeSrcContained(call, thisPtrNode);
- if (thisPtrNode->gtOper == GT_PUTARG_REG)
- {
- MakeSrcContained(call, thisPtrNode->gtOp.gtOp1);
+ MakeSrcContained(call, ctrlExpr);
}
}
}