提交 8da47ec5 编写于 作者: C Carol Eidt

Fix GT_FIELD_LIST double passed as int

Correctly handle a double field passed in int regs under a `GT_FIELD_LIST`, especially in the case of a `PutArgSplit`.
Also, reduce the spew of dump info when `COMPlus_JitStressModeNames` or `COMPlus_JitStressModeNamesNot` are set.
Enhance the dumping of `fgArgInfo`.

Fix dotnet/coreclr#15325


Commit migrated from https://github.com/dotnet/coreclr/commit/e226456a84ba1f1df10e1e7480fafd3e558be1ef
上级 871e4e8c
......@@ -1000,17 +1000,17 @@ void CodeGen::genPutArgSplit(GenTreePutArgSplit* treeNode)
if (source->OperGet() == GT_FIELD_LIST)
{
GenTreeFieldList* fieldListPtr = source->AsFieldList();
// Evaluate each of the GT_FIELD_LIST items into their register
// and store their register into the outgoing argument area
for (unsigned idx = 0; fieldListPtr != nullptr; fieldListPtr = fieldListPtr->Rest(), idx++)
unsigned regIndex = 0;
for (GenTreeFieldList* fieldListPtr = source->AsFieldList(); fieldListPtr != nullptr;
fieldListPtr = fieldListPtr->Rest())
{
GenTreePtr nextArgNode = fieldListPtr->gtGetOp1();
regNumber fieldReg = nextArgNode->gtRegNum;
genConsumeReg(nextArgNode);
if (idx >= treeNode->gtNumRegs)
if (regIndex >= treeNode->gtNumRegs)
{
var_types type = nextArgNode->TypeGet();
emitAttr attr = emitTypeSize(type);
......@@ -1023,14 +1023,32 @@ void CodeGen::genPutArgSplit(GenTreePutArgSplit* treeNode)
}
else
{
var_types type = treeNode->GetRegType(idx);
regNumber argReg = treeNode->GetRegNumByIdx(idx);
var_types type = treeNode->GetRegType(regIndex);
regNumber argReg = treeNode->GetRegNumByIdx(regIndex);
if (type == TYP_LONG)
{
// We should only see long fields for DOUBLEs passed in 2 integer registers, via bitcast.
// All other LONGs should have been decomposed.
// Handle the first INT, and then handle the 2nd below.
assert(nextArgNode->OperIs(GT_BITCAST));
type = TYP_INT;
if (argReg != fieldReg)
{
inst_RV_RV(ins_Copy(type), argReg, fieldReg, type);
}
// Now set up the next register for the 2nd INT
argReg = REG_NEXT(argReg);
regIndex++;
assert(argReg == treeNode->GetRegNumByIdx(regIndex));
fieldReg = nextArgNode->AsMultiRegOp()->GetRegNumByIdx(1);
}
// If child node is not already in the register we need, move it
if (argReg != fieldReg)
{
inst_RV_RV(ins_Copy(type), argReg, fieldReg, type);
}
regIndex++;
}
}
}
......
......@@ -3879,10 +3879,6 @@ bool Compiler::compStressCompile(compStressArea stressArea, unsigned weight)
if ((strStressModeNamesNot != nullptr) &&
(wcsstr(strStressModeNamesNot, s_compStressModeNames[stressArea]) != nullptr))
{
if (verbose)
{
printf("JitStressModeNamesNot contains %ws\n", s_compStressModeNames[stressArea]);
}
doStress = false;
goto _done;
}
......@@ -3893,10 +3889,6 @@ bool Compiler::compStressCompile(compStressArea stressArea, unsigned weight)
{
if (wcsstr(strStressModeNames, s_compStressModeNames[stressArea]) != nullptr)
{
if (verbose)
{
printf("JitStressModeNames contains %ws\n", s_compStressModeNames[stressArea]);
}
doStress = true;
goto _done;
}
......
......@@ -1447,6 +1447,8 @@ public:
// Get the late arg for arg at position argIndex. Caller must ensure this position has a late arg.
GenTreePtr GetLateArg(unsigned argIndex);
void Dump(Compiler* compiler);
};
#ifdef DEBUG
......
......@@ -13337,7 +13337,7 @@ void Compiler::impImportBlockCode(BasicBlock* block)
!(prefixFlags & PREFIX_TAILCALL_EXPLICIT) && // User hasn't set "tail." prefix yet.
verCheckTailCallConstraint(opcode, &resolvedToken,
constraintCall ? &constrainedResolvedToken : nullptr,
true) // Is it legal to do talcall?
true) // Is it legal to do tailcall?
)
{
// Stress the tailcall.
......
......@@ -1488,44 +1488,12 @@ void Lowering::LowerArg(GenTreeCall* call, GenTreePtr* ppArg)
#ifdef _TARGET_ARMARCH_
if (call->IsVarargs() || comp->opts.compUseSoftFP)
{
// For vararg call or on armel, reg args should be all integer.
// Insert a copy to move float value to integer register.
if (varTypeIsFloating(type))
// Insert copies as needed to move float value to integer register.
GenTree* newNode = LowerFloatArg(ppArg, info);
if (newNode != nullptr)
{
#ifdef _TARGET_ARM_
#ifdef DEBUG
if (type == TYP_DOUBLE)
{
unsigned numRegs = info->numRegs;
regNumber regCurr = info->regNum;
assert(numRegs % 2 == 0);
for (unsigned i = 0; i < numRegs;)
{
regNumber regNext = REG_NEXT(regCurr);
// double type arg regs can only be either r0:r1 or r2:r3.
assert((regCurr == REG_R0 && regNext == REG_R1) || (regCurr == REG_R2 && regNext == REG_R3));
i += 2;
regCurr = REG_NEXT(regNext);
}
}
#endif // DEBUG
#endif // _TARGET_ARM_
GenTreePtr intArg = LowerFloatArg(arg, info);
if (intArg != nullptr)
{
if (intArg != arg)
{
ReplaceArgWithPutArgOrBitcast(ppArg, intArg);
arg = intArg;
info->node = intArg;
}
// update local variables.
type = arg->TypeGet();
}
type = newNode->TypeGet();
}
}
#endif // _TARGET_ARMARCH_
......@@ -1544,7 +1512,7 @@ void Lowering::LowerArg(GenTreeCall* call, GenTreePtr* ppArg)
#ifdef _TARGET_ARMARCH_
//------------------------------------------------------------------------
// LowerFloatArg: Lower the float call argument on the arm platform.
// LowerFloatArg: Lower float call arguments on the arm platform.
//
// Arguments:
// arg - The arg node
......@@ -1555,8 +1523,13 @@ void Lowering::LowerArg(GenTreeCall* call, GenTreePtr* ppArg)
// return arg if there was in place transformation;
// return a new tree if the root was changed.
//
GenTree* Lowering::LowerFloatArg(GenTree* arg, fgArgTabEntry* info)
// Notes:
// This must handle scalar float arguments as well as GT_FIELD_LISTs
// with floating point fields.
//
GenTree* Lowering::LowerFloatArg(GenTree** pArg, fgArgTabEntry* info)
{
GenTree* arg = *pArg;
if (info->regNum != REG_STK)
{
if (arg->OperIsFieldList())
......@@ -1565,32 +1538,44 @@ GenTree* Lowering::LowerFloatArg(GenTree* arg, fgArgTabEntry* info)
regNumber currRegNumber = info->regNum;
// Transform fields that are passed as registers in place.
for (unsigned i = 0; i < info->numRegs; ++i)
unsigned fieldRegCount;
for (unsigned i = 0; i < info->numRegs; i += fieldRegCount)
{
assert(currListNode != nullptr);
GenTree* node = currListNode->Current();
GenTree* intNode = LowerFloatArgReg(node, currRegNumber);
assert(intNode != nullptr);
GenTree* node = currListNode->Current();
if (varTypeIsFloating(node))
{
GenTree* intNode = LowerFloatArgReg(node, currRegNumber);
assert(intNode != nullptr);
ReplaceArgWithPutArgOrBitcast(currListNode->pCurrent(), intNode);
currListNode->ChangeType(intNode->TypeGet());
ReplaceArgWithPutArgOrBitcast(currListNode->pCurrent(), intNode);
currListNode->ChangeType(intNode->TypeGet());
}
currListNode = currListNode->Rest();
currRegNumber = REG_NEXT(currRegNumber);
if (node->TypeGet() == TYP_DOUBLE)
{
currRegNumber = REG_NEXT(REG_NEXT(currRegNumber));
fieldRegCount = 2;
}
else
{
currRegNumber = REG_NEXT(currRegNumber);
fieldRegCount = 1;
}
currListNode = currListNode->Rest();
}
// List fields were replaced in place.
return arg;
}
else
else if (varTypeIsFloating(arg))
{
return LowerFloatArgReg(arg, info->regNum);
GenTree* intNode = LowerFloatArgReg(arg, info->regNum);
assert(intNode != nullptr);
ReplaceArgWithPutArgOrBitcast(pArg, intNode);
return *pArg;
}
}
else
{
// Do not change stack nodes.
return nullptr;
}
return nullptr;
}
//------------------------------------------------------------------------
......
......@@ -155,7 +155,7 @@ private:
GenTree* NewPutArg(GenTreeCall* call, GenTreePtr arg, fgArgTabEntryPtr info, var_types type);
void LowerArg(GenTreeCall* call, GenTreePtr* ppTree);
#ifdef _TARGET_ARMARCH_
GenTree* LowerFloatArg(GenTree* arg, fgArgTabEntry* info);
GenTree* LowerFloatArg(GenTree** pArg, fgArgTabEntry* info);
GenTree* LowerFloatArgReg(GenTree* arg, regNumber regNum);
#endif
......
......@@ -737,24 +737,29 @@ void LinearScan::TreeNodeInfoInitPutArgSplit(GenTreePutArgSplit* argNode)
// 1. Consume all of the items in the GT_FIELD_LIST (source)
// 2. Store to target slot and move to target registers (destination) from source
//
unsigned slotCount = 0;
unsigned sourceRegCount = 0;
// To avoid redundant moves, have the argument operand computed in the
// register in which the argument is passed to the call.
GenTreeFieldList* fieldListPtr = putArgChild->AsFieldList();
for (unsigned idx = 0; fieldListPtr != nullptr; fieldListPtr = fieldListPtr->Rest(), idx++)
for (GenTreeFieldList* fieldListPtr = putArgChild->AsFieldList(); fieldListPtr != nullptr;
fieldListPtr = fieldListPtr->Rest())
{
if (idx < argNode->gtNumRegs)
{
GenTreePtr node = fieldListPtr->gtGetOp1();
node->gtLsraInfo.setSrcCandidates(this, genRegMask((regNumber)((unsigned)argReg + idx)));
}
else
GenTreePtr node = fieldListPtr->gtGetOp1();
assert(!node->isContained());
unsigned currentRegCount = node->gtLsraInfo.dstCount;
regMaskTP sourceMask = RBM_NONE;
if (sourceRegCount < argNode->gtNumRegs)
{
slotCount++;
for (unsigned regIndex = 0; regIndex < currentRegCount; regIndex++)
{
sourceMask |= genRegMask((regNumber)((unsigned)argReg + sourceRegCount + regIndex));
}
node->gtLsraInfo.setSrcCandidates(this, sourceMask);
}
sourceRegCount += currentRegCount;
}
argNode->gtLsraInfo.srcCount = argNode->gtNumRegs + slotCount;
argNode->gtLsraInfo.srcCount = sourceRegCount;
assert(putArgChild->isContained());
}
else
......
......@@ -898,6 +898,7 @@ unsigned UpdateGT_LISTFlags(GenTreePtr tree)
void fgArgTabEntry::Dump()
{
printf("fgArgTabEntry[arg %u", argNum);
printf(" %d.%s", node->gtTreeID, GenTree::OpName(node->gtOper));
if (regNum != REG_STK)
{
printf(", %s, regs=%u", getRegName(regNum), numRegs);
......@@ -2133,6 +2134,17 @@ void fgArgInfo::SortArgs()
argsSorted = true;
}
#ifdef DEBUG
void fgArgInfo::Dump(Compiler* compiler)
{
for (unsigned curInx = 0; curInx < ArgCount(); curInx++)
{
fgArgTabEntryPtr curArgEntry = ArgTable()[curInx];
curArgEntry->Dump();
}
}
#endif
//------------------------------------------------------------------------------
// fgMakeTmpArgNode : This function creates a tmp var only if needed.
// We need this to be done in order to enforce ordering
......@@ -4585,15 +4597,9 @@ GenTreeCall* Compiler::fgMorphArgs(GenTreeCall* call)
#ifdef DEBUG
if (verbose)
{
fgArgInfoPtr argInfo = call->fgArgInfo;
for (unsigned curInx = 0; curInx < argInfo->ArgCount(); curInx++)
{
fgArgTabEntryPtr curArgEntry = argInfo->ArgTable()[curInx];
curArgEntry->Dump();
}
call->fgArgInfo->Dump(this);
}
#endif
return call;
}
#ifdef _PREFAST_
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册