Skip to content

Commit

Permalink
Unify set-reg-to-imm functions and optimize with LEA at runtime on x64 (
Browse files Browse the repository at this point in the history
dotnet#60228)

This change
* Unifies the genSetRegToImm and instGen_Set_Reg_To_Imm functions,
  removing the former. genSetRegToImm seems to be a variant that did not
  support relocations/handles, while the latter supported both. We now
  exclusively use the emitAttr to determine this. This was only a change
  in xarch since on ARM architectures the former function just forwarded
  to the latter.
* Generates lea more often for handle GT_CNS_INT nodes on x64.
  Previously the logic generated only lea when a relocation was
  *required*, which is only the case for prejit. In particular, all VSD
  calls load an indirection cell that can use lea instead of the longer
  mov encoding during runtime JIT, which results in a nice code size
  decrease.
* Changes ARM64 and ARM to handle byref-typed GT_CNS_INT nodes. This was
  fixed for xarch a few years back in
  52a8890 but that change was not made
  to ARM architectures.
  • Loading branch information
jakobbotsch committed Oct 15, 2021
1 parent 8076775 commit f40247e
Show file tree
Hide file tree
Showing 8 changed files with 64 additions and 137 deletions.
4 changes: 0 additions & 4 deletions src/coreclr/jit/codegen.h
Original file line number Diff line number Diff line change
Expand Up @@ -1145,10 +1145,6 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
void genConsumeHWIntrinsicOperands(GenTreeHWIntrinsic* tree);
#endif // FEATURE_HW_INTRINSICS
void genEmitGSCookieCheck(bool pushReg);
void genSetRegToIcon(regNumber reg,
ssize_t val,
var_types type = TYP_INT,
insFlags flags = INS_FLAGS_DONT_CARE DEBUGARG(GenTreeFlags gtFlags = GTF_EMPTY));
void genCodeForShift(GenTree* tree);

#if defined(TARGET_X86) || defined(TARGET_ARM)
Expand Down
23 changes: 14 additions & 9 deletions src/coreclr/jit/codegenarm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -236,15 +236,20 @@ void CodeGen::genSetRegToConst(regNumber targetReg, var_types targetType, GenTre
GenTreeIntConCommon* con = tree->AsIntConCommon();
ssize_t cnsVal = con->IconValue();

if (con->ImmedValNeedsReloc(compiler))
emitAttr attr = emitActualTypeSize(targetType);

if (con->IsIconHandle())
{
instGen_Set_Reg_To_Imm(EA_HANDLE_CNS_RELOC, targetReg, cnsVal);
regSet.verifyRegUsed(targetReg);
attr = EA_SET_FLG(attr, EA_CNS_RELOC_FLG);
}
else

if (targetType == TYP_BYREF)
{
genSetRegToIcon(targetReg, cnsVal, targetType);
attr = EA_SET_FLG(attr, EA_BYREF_FLG);
}

instGen_Set_Reg_To_Imm(attr, targetReg, cnsVal);
regSet.verifyRegUsed(targetReg);
}
break;

Expand All @@ -259,7 +264,7 @@ void CodeGen::genSetRegToConst(regNumber targetReg, var_types targetType, GenTre
regNumber tmpReg = tree->GetSingleTempReg();

float f = forceCastToFloat(constValue);
genSetRegToIcon(tmpReg, *((int*)(&f)));
instGen_Set_Reg_To_Imm(EA_4BYTE, tmpReg, *((int*)(&f)));
GetEmitter()->emitIns_Mov(INS_vmov_i2f, EA_4BYTE, targetReg, tmpReg, /* canSkip */ false);
}
else
Expand All @@ -272,8 +277,8 @@ void CodeGen::genSetRegToConst(regNumber targetReg, var_types targetType, GenTre
regNumber tmpReg1 = tree->ExtractTempReg();
regNumber tmpReg2 = tree->GetSingleTempReg();

genSetRegToIcon(tmpReg1, cv[0]);
genSetRegToIcon(tmpReg2, cv[1]);
instGen_Set_Reg_To_Imm(EA_4BYTE, tmpReg1, cv[0]);
instGen_Set_Reg_To_Imm(EA_4BYTE, tmpReg2, cv[1]);

GetEmitter()->emitIns_R_R_R(INS_vmov_i2d, EA_8BYTE, targetReg, tmpReg1, tmpReg2);
}
Expand Down Expand Up @@ -460,7 +465,7 @@ void CodeGen::genLclHeap(GenTree* tree)
}

// regCnt will be the total number of bytes to locAlloc
genSetRegToIcon(regCnt, amount, TYP_INT);
instGen_Set_Reg_To_Imm(EA_4BYTE, regCnt, amount);
}
else
{
Expand Down
24 changes: 14 additions & 10 deletions src/coreclr/jit/codegenarm64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1697,17 +1697,21 @@ void CodeGen::genSetRegToConst(regNumber targetReg, var_types targetType, GenTre
GenTreeIntConCommon* con = tree->AsIntConCommon();
ssize_t cnsVal = con->IconValue();

if (con->ImmedValNeedsReloc(compiler))
emitAttr attr = emitActualTypeSize(targetType);
if (con->IsIconHandle())
{
instGen_Set_Reg_To_Imm(EA_HANDLE_CNS_RELOC, targetReg, cnsVal,
INS_FLAGS_DONT_CARE DEBUGARG(tree->AsIntCon()->gtTargetHandle)
DEBUGARG(tree->AsIntCon()->gtFlags));
regSet.verifyRegUsed(targetReg);
attr = EA_SET_FLG(attr, EA_CNS_RELOC_FLG);
}
else

if (targetType == TYP_BYREF)
{
genSetRegToIcon(targetReg, cnsVal, targetType);
attr = EA_SET_FLG(attr, EA_BYREF_FLG);
}

instGen_Set_Reg_To_Imm(attr, targetReg, cnsVal,
INS_FLAGS_DONT_CARE DEBUGARG(tree->AsIntCon()->gtTargetHandle)
DEBUGARG(tree->AsIntCon()->gtFlags));
regSet.verifyRegUsed(targetReg);
}
break;

Expand Down Expand Up @@ -2279,7 +2283,7 @@ void CodeGen::genLclHeap(GenTree* tree)
{
regCnt = tree->ExtractTempReg();
}
genSetRegToIcon(regCnt, amount, ((unsigned int)amount == amount) ? TYP_INT : TYP_LONG);
instGen_Set_Reg_To_Imm(((unsigned int)amount == amount) ? EA_4BYTE : EA_8BYTE, regCnt, amount);
}

if (compiler->info.compInitMem)
Expand Down Expand Up @@ -4623,7 +4627,7 @@ void CodeGen::genProfilingEnterCallback(regNumber initReg, bool* pInitRegZeroed)
}
else
{
genSetRegToIcon(REG_PROFILER_ENTER_ARG_FUNC_ID, (ssize_t)compiler->compProfilerMethHnd, TYP_I_IMPL);
instGen_Set_Reg_To_Imm(EA_PTRSIZE, REG_PROFILER_ENTER_ARG_FUNC_ID, (ssize_t)compiler->compProfilerMethHnd);
}

int callerSPOffset = compiler->lvaToCallerSPRelativeOffset(0, isFramePointerUsed());
Expand Down Expand Up @@ -4667,7 +4671,7 @@ void CodeGen::genProfilingLeaveCallback(unsigned helper)
}
else
{
genSetRegToIcon(REG_PROFILER_LEAVE_ARG_FUNC_ID, (ssize_t)compiler->compProfilerMethHnd, TYP_I_IMPL);
instGen_Set_Reg_To_Imm(EA_PTRSIZE, REG_PROFILER_LEAVE_ARG_FUNC_ID, (ssize_t)compiler->compProfilerMethHnd);
}

gcInfo.gcMarkRegSetNpt(RBM_PROFILER_LEAVE_ARG_FUNC_ID);
Expand Down
20 changes: 2 additions & 18 deletions src/coreclr/jit/codegenarmarch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -553,22 +553,6 @@ void CodeGen::genCodeForTreeNode(GenTree* treeNode)
}
}

//------------------------------------------------------------------------
// genSetRegToIcon: Generate code that will set the given register to the integer constant.
//
void CodeGen::genSetRegToIcon(regNumber reg, ssize_t val, var_types type, insFlags flags DEBUGARG(GenTreeFlags gtFlags))
{
// Reg cannot be a FP reg
assert(!genIsValidFloatReg(reg));

// The only TYP_REF constant that can come this path is a managed 'null' since it is not
// relocatable. Other ref type constants (e.g. string objects) go through a different
// code path.
noway_assert(type != TYP_REF || val == 0);

instGen_Set_Reg_To_Imm(emitActualTypeSize(type), reg, val, flags);
}

//---------------------------------------------------------------------
// genSetGSSecurityCookie: Set the "GS" security cookie in the prolog.
//
Expand All @@ -593,7 +577,7 @@ void CodeGen::genSetGSSecurityCookie(regNumber initReg, bool* pInitRegZeroed)
{
noway_assert(compiler->gsGlobalSecurityCookieVal != 0);
// initReg = #GlobalSecurityCookieVal; [frame.GSSecurityCookie] = initReg
genSetRegToIcon(initReg, compiler->gsGlobalSecurityCookieVal, TYP_I_IMPL);
instGen_Set_Reg_To_Imm(EA_PTRSIZE, initReg, compiler->gsGlobalSecurityCookieVal);
GetEmitter()->emitIns_S_R(INS_str, EA_PTRSIZE, initReg, compiler->lvaGSSecurityCookie, 0);
}
else
Expand Down Expand Up @@ -1817,7 +1801,7 @@ void CodeGen::genCodeForIndexAddr(GenTreeIndexAddr* node)
else // we have to load the element size and use a MADD (multiply-add) instruction
{
// tmpReg = element size
CodeGen::genSetRegToIcon(tmpReg, (ssize_t)node->gtElemSize, TYP_INT);
instGen_Set_Reg_To_Imm(EA_4BYTE, tmpReg, (ssize_t)node->gtElemSize);

// dest = index * tmpReg + base
GetEmitter()->emitIns_R_R_R_R(INS_MULADD, emitActualTypeSize(node), node->GetRegNum(), index->GetRegNum(),
Expand Down
6 changes: 3 additions & 3 deletions src/coreclr/jit/codegencommon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1794,7 +1794,7 @@ void CodeGen::genEmitGSCookieCheck(bool pushReg)
{
// load the GS cookie constant into a reg
//
genSetRegToIcon(regGSConst, compiler->gsGlobalSecurityCookieVal, TYP_I_IMPL);
instGen_Set_Reg_To_Imm(EA_PTRSIZE, regGSConst, compiler->gsGlobalSecurityCookieVal);
}
else
{
Expand Down Expand Up @@ -12614,9 +12614,9 @@ void CodeGen::genPoisonFrame(regMaskTP regLiveIn)
if (!hasPoisonImm)
{
#ifdef TARGET_64BIT
genSetRegToIcon(REG_SCRATCH, (ssize_t)0xcdcdcdcdcdcdcdcd, TYP_LONG);
instGen_Set_Reg_To_Imm(EA_8BYTE, REG_SCRATCH, (ssize_t)0xcdcdcdcdcdcdcdcd);
#else
genSetRegToIcon(REG_SCRATCH, (ssize_t)0xcdcdcdcd, TYP_INT);
instGen_Set_Reg_To_Imm(EA_4BYTE, REG_SCRATCH, (ssize_t)0xcdcdcdcd);
#endif
hasPoisonImm = true;
}
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/jit/codegenlinear.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1898,7 +1898,7 @@ void CodeGen::genSetBlockSize(GenTreeBlk* blkNode, regNumber sizeReg)
if (!blkNode->OperIs(GT_STORE_DYN_BLK))
{
assert((blkNode->gtRsvdRegs & genRegMask(sizeReg)) != 0);
genSetRegToIcon(sizeReg, blockSize);
instGen_Set_Reg_To_Imm(EA_4BYTE, sizeReg, blockSize);
}
else
{
Expand Down
Loading

0 comments on commit f40247e

Please sign in to comment.