Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[RISC-V] regArg dependcies unrolling in genFnPrologCalleeRegArgs() #91904

Merged
merged 1 commit into from
Oct 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
265 changes: 94 additions & 171 deletions src/coreclr/jit/codegenriscv64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7578,11 +7578,22 @@ void CodeGen::genFnPrologCalleeRegArgs()
noway_assert(regArgMaskLive != 0);

unsigned varNum;
unsigned regArgMaskIsInt = 0;
unsigned regArgNum = 0;
// Process any circular dependencies
unsigned regArg[MAX_REG_ARG * 2] = {0};
unsigned regArgInit[MAX_REG_ARG * 2] = {0};
unsigned regArgNum = 0;
// Process any rearrangements including circular dependencies.
regNumber regArg[MAX_REG_ARG + MAX_FLOAT_REG_ARG];
regNumber regArgInit[MAX_REG_ARG + MAX_FLOAT_REG_ARG];
emitAttr regArgAttr[MAX_REG_ARG + MAX_FLOAT_REG_ARG];

for (int i = 0; i < MAX_REG_ARG + MAX_FLOAT_REG_ARG; i++)
{
regArg[i] = REG_NA;

#ifdef DEBUG
regArgInit[i] = REG_NA;
regArgAttr[i] = EA_UNKNOWN;
#endif
}

for (varNum = 0; varNum < compiler->lvaCount; ++varNum)
{
LclVarDsc* varDsc = compiler->lvaTable + varNum;
Expand Down Expand Up @@ -7638,20 +7649,19 @@ void CodeGen::genFnPrologCalleeRegArgs()
{
if (genIsValidIntReg(varDsc->GetArgReg()))
{
assert(varDsc->GetArgReg() >= REG_ARG_FIRST && varDsc->GetArgReg() <= REG_ARG_LAST);
assert(isValidIntArgReg(varDsc->GetArgReg()));
regArg[varDsc->GetArgReg() - REG_ARG_FIRST] = varDsc->GetArgReg();
regArgInit[varDsc->GetArgReg() - REG_ARG_FIRST] = varDsc->GetArgInitReg();
if (varDsc->TypeGet() == TYP_INT)
{
regArgMaskIsInt = 1 << (unsigned)varDsc->GetArgReg();
}
regArgAttr[varDsc->GetArgReg() - REG_ARG_FIRST] =
varDsc->TypeGet() == TYP_INT ? EA_4BYTE : EA_PTRSIZE;
}
else
{
assert(genIsValidFloatReg(varDsc->GetArgReg()));
assert(varDsc->GetArgReg() >= REG_ARG_FP_FIRST && varDsc->GetArgReg() <= REG_ARG_FP_LAST);
regArg[(varDsc->GetArgReg() - REG_ARG_FP_FIRST) | 0x8] = varDsc->GetArgReg();
regArgInit[(varDsc->GetArgReg() - REG_ARG_FP_FIRST) | 0x8] = varDsc->GetArgInitReg();
assert(isValidFloatArgReg(varDsc->GetArgReg()));
regArg[varDsc->GetArgReg() - REG_ARG_FP_FIRST + MAX_REG_ARG] = varDsc->GetArgReg();
regArgInit[varDsc->GetArgReg() - REG_ARG_FP_FIRST + MAX_REG_ARG] = varDsc->GetArgInitReg();
regArgAttr[varDsc->GetArgReg() - REG_ARG_FP_FIRST + MAX_REG_ARG] =
varDsc->TypeGet() == TYP_FLOAT ? EA_4BYTE : EA_PTRSIZE;
}
regArgNum++;
}
Expand All @@ -7673,9 +7683,11 @@ void CodeGen::genFnPrologCalleeRegArgs()
}
else
{
assert(genIsValidFloatReg(varDsc->GetArgReg()));
regArg[(varDsc->GetArgReg() & 7) | 0x8] = varDsc->GetArgReg();
regArgInit[(varDsc->GetArgReg() & 7) | 0x8] = varDsc->GetArgInitReg();
assert(isValidFloatArgReg(varDsc->GetArgReg()));
regArg[varDsc->GetArgReg() - REG_ARG_FP_FIRST + MAX_REG_ARG] = varDsc->GetArgReg();
regArgInit[varDsc->GetArgReg() - REG_ARG_FP_FIRST + MAX_REG_ARG] = varDsc->GetArgInitReg();
regArgAttr[varDsc->GetArgReg() - REG_ARG_FP_FIRST + MAX_REG_ARG] =
varDsc->TypeGet() == TYP_FLOAT ? EA_4BYTE : EA_PTRSIZE;
regArgNum++;
}
}
Expand Down Expand Up @@ -7885,193 +7897,104 @@ void CodeGen::genFnPrologCalleeRegArgs()

if (regArgNum > 0)
{
for (int i = MAX_REG_ARG - 1; i >= 0; i--)
for (int i = MAX_REG_ARG + MAX_FLOAT_REG_ARG - 1; i >= 0; i--)
{
if (regArg[i] > 0 && (regArgInit[i] <= REG_S1 || regArgInit[i] > REG_A7))
if (regArg[i] != REG_NA && !isValidIntArgReg(regArgInit[i]) && !isValidFloatArgReg(regArgInit[i]))
{
instruction ins;
if ((regArgMaskIsInt & (1 << regArg[i])) != 0)
{
ins = INS_slliw;
}
else
{
ins = INS_ori;
}
GetEmitter()->emitIns_R_R_I(ins, EA_PTRSIZE, (regNumber)regArgInit[i], (regNumber)regArg[i], 0);
regArgMaskLive &= ~genRegMask((regNumber)regArg[i]);
regArg[i] = 0;
assert(regArg[i] != regArgInit[i]);
assert(isValidIntArgReg(regArg[i]) || isValidFloatArgReg(regArg[i]));

GetEmitter()->emitIns_Mov(regArgAttr[i], regArgInit[i], regArg[i], false);

regArgMaskLive &= ~genRegMask(regArg[i]);
regArg[i] = REG_NA;
regArgNum -= 1;
}
}
}

if (regArgNum > 0)
{
instruction ins;
for (int i = MAX_REG_ARG - 1; i >= 0; i--)
for (int i = MAX_REG_ARG + MAX_FLOAT_REG_ARG - 1; i >= 0; i--)
{
if (regArg[i] > 0)
if (regArg[i] != REG_NA)
{
assert(genIsValidIntReg((regNumber)regArg[i]));
assert(genIsValidIntReg((regNumber)regArgInit[i]));
assert(regArg[i] != regArgInit[i]);

regArgNum--;
regArgMaskLive &= ~genRegMask((regNumber)regArg[i]);
if ((regArgMaskIsInt & (1 << regArg[i])) != 0)
{
ins = INS_slliw;
}
else
{
ins = INS_ori;
}
// regArg indexes list
unsigned indexList[MAX_REG_ARG + MAX_FLOAT_REG_ARG];
int count = 0; // Number of nodes in list
bool loop = false; // List has a loop

if (regArgNum == 0)
{
GetEmitter()->emitIns_R_R_I(ins, EA_PTRSIZE, (regNumber)regArgInit[i], (regNumber)regArg[i], 0);
break;
}
else if (regArgInit[i] > regArg[i])
{
GetEmitter()->emitIns_R_R_I(ins, EA_PTRSIZE, (regNumber)regArgInit[i], (regNumber)regArg[i], 0);
}
else
for (unsigned cur = i; regArg[cur] != REG_NA; count++)
{
assert(i > 0);
assert(regArgNum > 0);
if (cur == i && count > 0)
{
loop = true;
break;
}

indexList[count] = cur;

for (int count2 = 0; count2 < count; count2++)
{
// The list could not have backlinks except last to first case which handled above.
assert(cur != indexList[count2] && "Attempt to move several values on same register.");
}
assert(cur < MAX_REG_ARG + MAX_FLOAT_REG_ARG);
assert(isValidIntArgReg(regArg[cur]) || isValidFloatArgReg(regArg[cur]));

int j = regArgInit[i] - REG_ARG_FIRST;
assert((j >= 0) && (j < MAX_REG_ARG));
if (regArg[j] == 0)
if (isValidIntArgReg(regArgInit[cur]))
{
GetEmitter()->emitIns_R_R_I(ins, EA_PTRSIZE, (regNumber)regArgInit[i], (regNumber)regArg[i], 0);
cur = regArgInit[cur] - REG_ARG_FIRST;
}
else if (isValidFloatArgReg(regArgInit[cur]))
{
cur = regArgInit[cur] - REG_ARG_FP_FIRST + MAX_REG_ARG;
}
else
{
int k = regArgInit[j] - REG_ARG_FIRST;
// assert((k >= 0) && (k < MAX_REG_ARG));
instruction ins2 = (regArgMaskIsInt & (1 << regArg[j])) != 0 ? INS_slliw : INS_ori;
if ((regArg[k] == 0) || (k > i) || k < 0)
{
GetEmitter()->emitIns_R_R_I(ins2, EA_PTRSIZE, (regNumber)regArgInit[j],
(regNumber)regArg[j], 0);
GetEmitter()->emitIns_R_R_I(ins, EA_PTRSIZE, (regNumber)regArgInit[i], (regNumber)regArg[i],
0);
regArgNum--;
regArgMaskLive &= ~genRegMask((regNumber)regArg[j]);
regArg[j] = 0;
}
else if (k == i)
{
GetEmitter()->emitIns_R_R_I(ins, EA_PTRSIZE, rsGetRsvdReg(), (regNumber)regArg[i], 0);
GetEmitter()->emitIns_R_R_I(ins2, EA_PTRSIZE, (regNumber)regArgInit[j],
(regNumber)regArg[j], 0);
GetEmitter()->emitIns_R_R_I(INS_ori, EA_PTRSIZE, (regNumber)regArgInit[i], rsGetRsvdReg(),
0);
regArgNum--;
regArgMaskLive &= ~genRegMask((regNumber)regArg[j]);
regArg[j] = 0;
}
else
{
NYI_RISCV64("-----------CodeGen::genFnPrologCalleeRegArgs() error!--");
}

if (regArgNum == 0)
{
break;
}
assert(!"Argument register is neither valid float nor valid int argument register");
}
}
}
}

if (regArgNum > 0)
{
for (int i = MAX_REG_ARG + MAX_FLOAT_REG_ARG - 1; i >= MAX_REG_ARG; i--)
{
if (regArg[i] > 0)
if (loop)
{
unsigned tmpArg = indexList[count - 1];

GetEmitter()->emitIns_Mov(regArgAttr[tmpArg], rsGetRsvdReg(), regArg[tmpArg], false);
count--; // Decrease count to not access last node which regArgInit points to start node i
assert(count > 0);
}

for (int cur = count - 1; cur >= 0; cur--)
{
assert(genIsValidFloatReg((regNumber)regArg[i]));
unsigned tmpArg = indexList[cur];

instruction ins = genIsValidIntReg((regNumber)regArgInit[i]) ? INS_fmv_x_d : INS_fsgnj_d;
GetEmitter()->emitIns_Mov(regArgAttr[tmpArg], regArgInit[tmpArg], regArg[tmpArg], false);

regArgMaskLive &= ~genRegMask(regArg[tmpArg]);
regArg[tmpArg] = REG_NA;
regArgNum--;
regArgMaskLive &= ~genRegMask((regNumber)regArg[i]);
if (regArgNum == 0)
{
GetEmitter()->emitIns_Mov(ins, EA_PTRSIZE, (regNumber)regArgInit[i], (regNumber)regArg[i],
true);
break;
}
else if (regArgInit[i] > regArg[i] || (regArgInit[i] <= REG_F9))
{
GetEmitter()->emitIns_R_R_R(INS_fsgnj_d, EA_PTRSIZE, (regNumber)regArgInit[i],
(regNumber)regArg[i], (regNumber)regArg[i]);
}
else
{
assert(i > MAX_REG_ARG);
assert(regArgNum > 0);
assert(regArgNum >= 0);
};

int j = genIsValidIntReg((regNumber)regArgInit[i])
? (regArgInit[i] - REG_ARG_FIRST)
: ((((int)regArgInit[i]) - REG_ARG_FP_FIRST) + 0x8);
if (j < MAX_REG_ARG || regArg[j] == 0)
{
GetEmitter()->emitIns_Mov(ins, EA_PTRSIZE, (regNumber)regArgInit[i], (regNumber)regArg[i],
true);
}
else
{
// NOTE: Not support the int-register case.
assert(genIsValidFloatReg((regNumber)regArg[j]));
assert(genIsValidFloatReg((regNumber)regArgInit[j]));
if (loop)
{
unsigned tmpArg = indexList[count]; // count was decreased for loop case

int k = (((int)regArgInit[j]) - REG_ARG_FP_FIRST) + 0x8;
if ((regArg[k] == 0) || (k > i) || (k < MAX_REG_ARG))
{
GetEmitter()->emitIns_R_R_R(INS_fsgnj_d, EA_PTRSIZE, (regNumber)regArgInit[j],
(regNumber)regArg[j], (regNumber)regArg[j]);
GetEmitter()->emitIns_R_R_R(INS_fsgnj_d, EA_PTRSIZE, (regNumber)regArgInit[i],
(regNumber)regArg[i], (regNumber)regArg[i]);
regArgNum--;
regArgMaskLive &= ~genRegMask((regNumber)regArg[j]);
regArg[j] = 0;
if (regArgNum == 0)
{
break;
}
}
else if (k == i)
{
GetEmitter()->emitIns_R_R_R(INS_fsgnj_d, EA_PTRSIZE, REG_SCRATCH_FLT,
(regNumber)regArg[i], (regNumber)regArg[i]);
GetEmitter()->emitIns_R_R_R(INS_fsgnj_d, EA_PTRSIZE, (regNumber)regArgInit[j],
(regNumber)regArg[j], (regNumber)regArg[j]);
GetEmitter()->emitIns_R_R_R(INS_fsgnj_d, EA_PTRSIZE, (regNumber)regArgInit[i],
REG_SCRATCH_FLT, REG_SCRATCH_FLT);
regArgNum--;
regArgMaskLive &= ~genRegMask((regNumber)regArg[j]);
regArg[j] = 0;
if (regArgNum == 0)
{
break;
}
}
else
{
NYI_RISCV64("-----------CodeGen::genFnPrologCalleeRegArgs() error!--");
}
}
}
GetEmitter()->emitIns_Mov(regArgAttr[i], regArg[tmpArg], rsGetRsvdReg(), false);

regArgMaskLive &= ~genRegMask(regArg[tmpArg]);
regArg[tmpArg] = REG_NA;
regArgNum--;
}
assert(regArgNum >= 0);
}
}
assert(regArgNum == 0);
}

assert(regArgNum == 0);
assert(!regArgMaskLive);
}

Expand Down
28 changes: 28 additions & 0 deletions src/coreclr/jit/emitriscv64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -561,6 +561,34 @@ void emitter::emitIns_Mov(
}
}

void emitter::emitIns_Mov(emitAttr attr, regNumber dstReg, regNumber srcReg, bool canSkip)
{
if (!canSkip || dstReg != srcReg)
{
assert(attr == EA_4BYTE || attr == EA_PTRSIZE);
if (isGeneralRegisterOrR0(dstReg) && isGeneralRegisterOrR0(srcReg))
{
emitIns_R_R_I(attr == EA_4BYTE ? INS_addiw : INS_addi, attr, dstReg, srcReg, 0);
}
else if (isGeneralRegisterOrR0(dstReg) && genIsValidFloatReg(srcReg))
{
emitIns_R_R(attr == EA_4BYTE ? INS_fmv_x_w : INS_fmv_x_d, attr, dstReg, srcReg);
}
else if (genIsValidFloatReg(dstReg) && isGeneralRegisterOrR0(srcReg))
{
emitIns_R_R(attr == EA_4BYTE ? INS_fmv_w_x : INS_fmv_d_x, attr, dstReg, srcReg);
}
else if (genIsValidFloatReg(dstReg) && genIsValidFloatReg(srcReg))
{
emitIns_R_R_R(attr == EA_4BYTE ? INS_fsgnj_s : INS_fsgnj_d, attr, dstReg, srcReg, srcReg);
}
else
{
assert(!"Invalid registers in emitIns_Mov()\n");
}
}
}

/*****************************************************************************
*
* Add an instruction referencing two registers
Expand Down
2 changes: 2 additions & 0 deletions src/coreclr/jit/emitriscv64.h
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,8 @@ void emitIns_R_I(instruction ins, emitAttr attr, regNumber reg, ssize_t imm, ins
void emitIns_Mov(
instruction ins, emitAttr attr, regNumber dstReg, regNumber srcReg, bool canSkip, insOpts opt = INS_OPTS_NONE);

void emitIns_Mov(emitAttr attr, regNumber dstReg, regNumber srcReg, bool canSkip = false);

void emitIns_R_R(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, insOpts opt = INS_OPTS_NONE);

void emitIns_R_R(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, insFlags flags)
Expand Down