isOnStack = info->regNum == REG_STK;
#endif // !FEATURE_UNIX_AMD64_STRUCT_PASSING
+#ifdef _TARGET_ARMARCH_
+ if (varTypeIsStruct(type))
+ {
+ arg->SetContained();
+ if ((arg->OperGet() == GT_OBJ) && (arg->AsObj()->Addr()->OperGet() == GT_LCL_VAR_ADDR))
+ {
+ MakeSrcContained(arg, arg->AsObj()->Addr());
+ }
+ }
+#endif
+
#ifdef _TARGET_ARM_
// Struct can be split into register(s) and stack on ARM
if (info->isSplit)
putArg = new (comp, GT_PUTARG_SPLIT)
GenTreePutArgSplit(arg, info->slotNum PUT_STRUCT_ARG_STK_ONLY_ARG(info->numSlots), info->numRegs,
call->IsFastTailCall(), call);
+ putArg->gtRegNum = info->regNum;
// If struct argument is morphed to GT_FIELD_LIST node(s),
// we can know GC info by type of each GT_FIELD_LIST node.
GenTreePtr argLo = arg->gtGetOp1();
GenTreePtr argHi = arg->gtGetOp2();
- GenTreeFieldList* fieldList = new (comp, GT_FIELD_LIST) GenTreeFieldList(argLo, 0, TYP_INT, nullptr);
- (void)new (comp, GT_FIELD_LIST) GenTreeFieldList(argHi, 4, TYP_INT, fieldList);
+ GenTreeFieldList* fieldListLow = new (comp, GT_FIELD_LIST) GenTreeFieldList(argLo, 0, TYP_INT, nullptr);
+ GenTreeFieldList* fieldListHigh =
+ new (comp, GT_FIELD_LIST) GenTreeFieldList(argHi, 4, TYP_INT, fieldListLow);
- putArg = NewPutArg(call, fieldList, info, TYP_VOID);
+ putArg = NewPutArg(call, fieldListLow, info, TYP_INT);
putArg->gtRegNum = info->regNum;
BlockRange().InsertBefore(arg, putArg);
BlockRange().Remove(arg);
- *ppArg = fieldList;
- info->node = fieldList;
+ *ppArg = fieldListLow;
+ info->node = fieldListLow;
+
+ // Clear the register assignments on the fieldList nodes, as these are contained.
+ fieldListLow->gtRegNum = REG_NA;
+ fieldListHigh->gtRegNum = REG_NA;
}
else
{
}
}
}
+ ContainCheckStoreLoc(storeLoc);
}
//------------------------------------------------------------------------
tree->gtOp.gtOp1 = tmp;
BlockRange().InsertAfter(op1, tmp);
}
+
+ // Now determine if we have operands that should be contained.
+ ContainCheckCast(tree->AsCast());
}
//------------------------------------------------------------------------
}
}
}
- GenTreePtr args = call->gtCallArgs;
- while (args)
- {
- GenTreePtr arg = args->gtOp.gtOp1;
- if (!(args->gtFlags & GTF_LATE_ARG))
- {
- TreeNodeInfo* argInfo = &(arg->gtLsraInfo);
- if (arg->gtOper == GT_PUTARG_STK)
- {
- GenTreePtr putArgChild = arg->gtOp.gtOp1;
- if (putArgChild->OperGet() == GT_FIELD_LIST)
- {
- MakeSrcContained(arg, putArgChild);
- }
- else if (putArgChild->OperGet() == GT_OBJ)
- {
- MakeSrcContained(arg, putArgChild);
- GenTreePtr objChild = putArgChild->gtOp.gtOp1;
- if (objChild->OperGet() == GT_LCL_VAR_ADDR)
- {
- // We will generate all of the code for the GT_PUTARG_STK, the GT_OBJ and the GT_LCL_VAR_ADDR
- // as one contained operation
- //
- MakeSrcContained(putArgChild, objChild);
- }
- }
- }
- }
- args = args->gtOp.gtOp2;
- }
}
//------------------------------------------------------------------------
//
void Lowering::TreeNodeInfoInitReturn(GenTree* tree)
{
- ContainCheckRet(tree->AsOp());
-
TreeNodeInfo* info = &(tree->gtLsraInfo);
LinearScan* l = m_lsra;
Compiler* compiler = comp;
void Lowering::TreeNodeInfoInitLclHeap(GenTree* tree)
{
- ContainCheckLclHeap(tree->AsOp());
-
TreeNodeInfo* info = &(tree->gtLsraInfo);
LinearScan* l = m_lsra;
Compiler* compiler = comp;
case GT_CAST:
{
- ContainCheckCast(tree->AsCast());
info->srcCount = 1;
assert(info->dstCount == 1);
case GT_AND:
case GT_OR:
case GT_XOR:
- ContainCheckBinary(tree->AsOp());
info->srcCount = tree->gtOp.gtOp2->isContained() ? 1 : 2;
assert(info->dstCount == 1);
break;
break;
case GT_ARR_OFFSET:
- ContainCheckArrOffset(tree->AsArrOffs());
// This consumes the offset, if any, the arrObj and the effective index,
// and produces the flattened offset for this dimension.
assert(info->dstCount == 1);
break;
case GT_LOCKADD:
- ContainCheckBinary(tree->AsOp());
info->srcCount = tree->gtOp.gtOp2->isContained() ? 1 : 2;
assert(info->dstCount == 1);
break;
case GT_LCLHEAP:
{
- ContainCheckLclHeap(tree->AsOp());
assert(info->dstCount == 1);
// Need a variable number of temp regs (see genLclHeap() in codegenamd64.cpp):
break;
case GT_ARR_OFFSET:
- ContainCheckArrOffset(tree->AsArrOffs());
// This consumes the offset, if any, the arrObj and the effective index,
// and produces the flattened offset for this dimension.
info->srcCount = tree->gtArrOffs.gtOffset->isContained() ? 2 : 3;
//
void Lowering::TreeNodeInfoInitReturn(GenTree* tree)
{
- ContainCheckRet(tree->AsOp());
-
TreeNodeInfo* info = &(tree->gtLsraInfo);
LinearScan* l = m_lsra;
Compiler* compiler = comp;
//
void Lowering::TreeNodeInfoInitShiftRotate(GenTree* tree)
{
- ContainCheckShiftRotate(tree->AsOp());
-
TreeNodeInfo* info = &(tree->gtLsraInfo);
LinearScan* l = m_lsra;
else if (argNode->OperGet() == GT_PUTARG_SPLIT)
{
fgArgTabEntryPtr curArgTabEntry = compiler->gtArgEntryByNode(call, argNode);
+ info->srcCount += argNode->AsPutArgSplit()->gtNumRegs;
}
#endif
else
}
}
- // We will generate all of the code for the GT_PUTARG_STK and it's child node
+ // We will generate all of the code for the GT_PUTARG_STK and its child node
// as one contained operation
//
argNode->gtLsraInfo.srcCount = putArgChild->gtLsraInfo.srcCount;
{
// The block size argument is a third argument to GT_STORE_DYN_BLK
assert(blkNode->gtOper == GT_STORE_DYN_BLK);
- blkNode->gtLsraInfo.setSrcCount(3);
+ blkNode->gtLsraInfo.srcCount++;
GenTree* blockSize = blkNode->AsDynBlk()->gtDynamicSize;
blockSize->gtLsraInfo.setSrcCandidates(l, RBM_ARG_2);
}