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

[LoongArch64-RISCV64] Refactor the profiler for LoongArch64 and also fix some errors for RISCV64. #91722

Merged
merged 4 commits into from
Sep 8, 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
82 changes: 52 additions & 30 deletions src/coreclr/jit/codegenloongarch64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7758,35 +7758,6 @@ void CodeGen::instGen_MemoryBarrier(BarrierKind barrierKind)
GetEmitter()->emitIns_I(INS_dbar, EA_4BYTE, INS_BARRIER_FULL);
}

//-----------------------------------------------------------------------------------
// genProfilingLeaveCallback: Generate the profiling function leave or tailcall callback.
// Technically, this is not part of the epilog; it is called when we are generating code for a GT_RETURN node.
//
// Arguments:
// helper - which helper to call. Either CORINFO_HELP_PROF_FCN_LEAVE or CORINFO_HELP_PROF_FCN_TAILCALL
//
// Return Value:
// None
//
void CodeGen::genProfilingLeaveCallback(unsigned helper /*= CORINFO_HELP_PROF_FCN_LEAVE*/)
{
assert((helper == CORINFO_HELP_PROF_FCN_LEAVE) || (helper == CORINFO_HELP_PROF_FCN_TAILCALL));

// Only hook if profiler says it's okay.
if (!compiler->compIsProfilerHookNeeded())
{
return;
}

compiler->info.compProfilerCallback = true;

// Need to save on to the stack level, since the helper call will pop the argument
unsigned saveStackLvl2 = genStackLevel;

/* Restore the stack level */
SetStackLevel(saveStackLvl2);
}

/*-----------------------------------------------------------------------------
*
* Push/Pop any callee-saved registers we have used
Expand Down Expand Up @@ -8662,6 +8633,7 @@ void CodeGen::genFnPrologCalleeRegArgs()
assert(!regArgMaskLive);
}

#ifdef PROFILING_SUPPORTED
//-----------------------------------------------------------------------------------
// genProfilingEnterCallback: Generate the profiling function enter callback.
//
Expand All @@ -8677,10 +8649,60 @@ void CodeGen::genProfilingEnterCallback(regNumber initReg, bool* pInitRegZeroed)
{
assert(compiler->compGeneratingProlog);

// Give profiler a chance to back out of hooking this method
if (!compiler->compIsProfilerHookNeeded())
{
return;
}

assert(!compiler->compProfilerMethHndIndirected);
instGen_Set_Reg_To_Imm(EA_PTRSIZE, REG_PROFILER_ENTER_ARG_FUNC_ID, (ssize_t)compiler->compProfilerMethHnd);

int callerSPOffset = compiler->lvaToCallerSPRelativeOffset(0, isFramePointerUsed());
genInstrWithConstant(INS_addi_d, EA_PTRSIZE, REG_PROFILER_ENTER_ARG_CALLER_SP, genFramePointerReg(),
(ssize_t)(-callerSPOffset), REG_PROFILER_ENTER_ARG_CALLER_SP);

genEmitHelperCall(CORINFO_HELP_PROF_FCN_ENTER, 0, EA_UNKNOWN);

if ((genRegMask(initReg) & RBM_PROFILER_ENTER_TRASH) != RBM_NONE)
{
*pInitRegZeroed = false;
}
}

//-----------------------------------------------------------------------------------
// genProfilingLeaveCallback: Generate the profiling function leave or tailcall callback.
// Technically, this is not part of the epilog; it is called when we are generating code for a GT_RETURN node.
//
// Arguments:
// helper - which helper to call. Either CORINFO_HELP_PROF_FCN_LEAVE or CORINFO_HELP_PROF_FCN_TAILCALL
//
// Return Value:
// None
//
void CodeGen::genProfilingLeaveCallback(unsigned helper /*= CORINFO_HELP_PROF_FCN_LEAVE*/)
{
assert((helper == CORINFO_HELP_PROF_FCN_LEAVE) || (helper == CORINFO_HELP_PROF_FCN_TAILCALL));

if (!compiler->compIsProfilerHookNeeded())
{
return;
}

compiler->info.compProfilerCallback = true;

assert(!compiler->compProfilerMethHndIndirected);
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);

int callerSPOffset = compiler->lvaToCallerSPRelativeOffset(0, isFramePointerUsed());
genInstrWithConstant(INS_addi_d, EA_PTRSIZE, REG_PROFILER_LEAVE_ARG_CALLER_SP, genFramePointerReg(),
(ssize_t)(-callerSPOffset), REG_PROFILER_LEAVE_ARG_CALLER_SP);

gcInfo.gcMarkRegSetNpt(RBM_PROFILER_LEAVE_ARG_CALLER_SP);

genEmitHelperCall(helper, 0, EA_UNKNOWN);
}
#endif // PROFILING_SUPPORTED

#endif // TARGET_LOONGARCH64
33 changes: 16 additions & 17 deletions src/coreclr/jit/emitloongarch64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2507,10 +2507,10 @@ unsigned emitter::emitOutputCall(insGroup* ig, BYTE* dst, instrDesc* id, code_t
{
// pc + offset_38bits
//
// pcaddu18i t2, addr-hi20
// jilr r0/1,t2,addr-lo18
// pcaddu18i t4, addr-hi20
// jilr r0/1,t4,addr-lo18

emitOutput_Instr(dst, 0x1e00000e);
emitOutput_Instr(dst, 0x1e000000 | (int)REG_DEFAULT_HELPER_CALL_TARGET);

size_t addr = (size_t)(id->idAddr()->iiaAddr); // get addr.

Expand All @@ -2521,25 +2521,24 @@ unsigned emitter::emitOutputCall(insGroup* ig, BYTE* dst, instrDesc* id, code_t
assert((addr & 3) == 0);

dst += 4;
emitGCregDeadUpd(REG_T2, dst);
emitGCregDeadUpd(REG_DEFAULT_HELPER_CALL_TARGET, dst);

#ifdef DEBUG
code = emitInsCode(INS_pcaddu18i);
assert((code | (14)) == 0x1e00000e);
assert((int)REG_T2 == 14);
assert(code == 0x1e000000);
code = emitInsCode(INS_jirl);
assert(code == 0x4c000000);
#endif
emitOutput_Instr(dst, 0x4c000000 | (14 << 5) | reg2);
emitOutput_Instr(dst, 0x4c000000 | ((int)REG_DEFAULT_HELPER_CALL_TARGET << 5) | reg2);

emitRecordRelocation(dst - 4, (BYTE*)addr, IMAGE_REL_LOONGARCH64_JIR);
}
else
{
// lu12i_w t2, addr_bits[31:12] // TODO-LoongArch64: maybe optimize.
// ori t2, t2, addr_bits[11:0]
// lu32i_d t2, addr_bits[50:32]
// jirl t2
// lu12i_w t4, addr_bits[31:12] // TODO-LoongArch64: maybe optimize.
// ori t4, t4, addr_bits[11:0]
// lu32i_d t4, addr_bits[50:32]
// jirl t4

ssize_t imm = (ssize_t)(id->idAddr()->iiaAddr);
assert((uint64_t)(imm >> 32) <= 0x7ffff); // In fact max is <= 0xffff.
Expand All @@ -2548,30 +2547,30 @@ unsigned emitter::emitOutputCall(insGroup* ig, BYTE* dst, instrDesc* id, code_t
imm -= reg2;

code = emitInsCode(INS_lu12i_w);
code |= (code_t)REG_T2;
code |= (code_t)REG_DEFAULT_HELPER_CALL_TARGET;
code |= ((code_t)(imm >> 12) & 0xfffff) << 5;

emitOutput_Instr(dst, code);
dst += 4;
emitGCregDeadUpd(REG_T2, dst);
emitGCregDeadUpd(REG_DEFAULT_HELPER_CALL_TARGET, dst);

code = emitInsCode(INS_ori);
code |= (code_t)REG_T2;
code |= (code_t)REG_T2 << 5;
code |= (code_t)REG_DEFAULT_HELPER_CALL_TARGET;
code |= (code_t)REG_DEFAULT_HELPER_CALL_TARGET << 5;
code |= (code_t)(imm & 0xfff) << 10;
emitOutput_Instr(dst, code);
dst += 4;

code = emitInsCode(INS_lu32i_d);
code |= (code_t)REG_T2;
code |= (code_t)REG_DEFAULT_HELPER_CALL_TARGET;
code |= ((imm >> 32) & 0x7ffff) << 5;

emitOutput_Instr(dst, code);
dst += 4;

code = emitInsCode(INS_jirl);
code |= (code_t)reg2;
code |= (code_t)REG_T2 << 5;
code |= (code_t)REG_DEFAULT_HELPER_CALL_TARGET << 5;
// the offset default is 0;
emitOutput_Instr(dst, code);
}
Expand Down
20 changes: 10 additions & 10 deletions src/coreclr/jit/targetloongarch64.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,8 @@
#define RBM_CALLEE_SAVED (RBM_INT_CALLEE_SAVED | RBM_FLT_CALLEE_SAVED)
#define RBM_CALLEE_TRASH (RBM_INT_CALLEE_TRASH | RBM_FLT_CALLEE_TRASH)

#define REG_DEFAULT_HELPER_CALL_TARGET REG_T2
#define RBM_DEFAULT_HELPER_CALL_TARGET RBM_T2
#define REG_DEFAULT_HELPER_CALL_TARGET REG_T4
#define RBM_DEFAULT_HELPER_CALL_TARGET RBM_T4

#define RBM_ALLINT (RBM_INT_CALLEE_SAVED | RBM_INT_CALLEE_TRASH)
#define RBM_ALLFLOAT (RBM_FLT_CALLEE_SAVED | RBM_FLT_CALLEE_TRASH)
Expand Down Expand Up @@ -212,14 +212,14 @@
#define REG_PREV(reg) ((regNumber)((unsigned)(reg) - 1))

// The following registers are used in emitting Enter/Leave/Tailcall profiler callbacks
#define REG_PROFILER_ENTER_ARG_FUNC_ID REG_R10
#define RBM_PROFILER_ENTER_ARG_FUNC_ID RBM_R10
#define REG_PROFILER_ENTER_ARG_CALLER_SP REG_R11
#define RBM_PROFILER_ENTER_ARG_CALLER_SP RBM_R11
#define REG_PROFILER_LEAVE_ARG_FUNC_ID REG_R10
#define RBM_PROFILER_LEAVE_ARG_FUNC_ID RBM_R10
#define REG_PROFILER_LEAVE_ARG_CALLER_SP REG_R11
#define RBM_PROFILER_LEAVE_ARG_CALLER_SP RBM_R11
#define REG_PROFILER_ENTER_ARG_FUNC_ID REG_T1
#define RBM_PROFILER_ENTER_ARG_FUNC_ID RBM_T1
#define REG_PROFILER_ENTER_ARG_CALLER_SP REG_T2
#define RBM_PROFILER_ENTER_ARG_CALLER_SP RBM_T2
#define REG_PROFILER_LEAVE_ARG_FUNC_ID REG_PROFILER_ENTER_ARG_FUNC_ID
#define RBM_PROFILER_LEAVE_ARG_FUNC_ID RBM_PROFILER_ENTER_ARG_FUNC_ID
#define REG_PROFILER_LEAVE_ARG_CALLER_SP REG_PROFILER_ENTER_ARG_CALLER_SP
#define RBM_PROFILER_LEAVE_ARG_CALLER_SP RBM_PROFILER_ENTER_ARG_CALLER_SP

// The registers trashed by profiler enter/leave/tailcall hook
#define RBM_PROFILER_ENTER_TRASH (RBM_CALLEE_TRASH & ~(RBM_ARG_REGS|RBM_FLTARG_REGS|RBM_FP))
Expand Down
1 change: 1 addition & 0 deletions src/coreclr/vm/arm64/asmconstants.h
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,7 @@ ASMCONSTANTS_C_ASSERT(CallCountingStubData__TargetForThresholdReached == offseto

#define SIZEOF__PROFILE_PLATFORM_SPECIFIC_DATA 320
ASMCONSTANTS_C_ASSERT(SIZEOF__PROFILE_PLATFORM_SPECIFIC_DATA == sizeof(PROFILE_PLATFORM_SPECIFIC_DATA))
ASMCONSTANTS_C_ASSERT((SIZEOF__PROFILE_PLATFORM_SPECIFIC_DATA & 0xf) == 0)

#define ASMCONSTANTS_C_ASSERT_OFFSET(type, field) \
ASMCONSTANTS_C_ASSERT(type##__##field == offsetof(type, field))
Expand Down
50 changes: 23 additions & 27 deletions src/coreclr/vm/loongarch64/asmconstants.h
Original file line number Diff line number Diff line change
Expand Up @@ -255,43 +255,39 @@ ASMCONSTANTS_C_ASSERT(CallCountingStubData__TargetForMethod == offsetof(CallCoun
ASMCONSTANTS_C_ASSERT(CallCountingStubData__TargetForThresholdReached == offsetof(CallCountingStubData, TargetForThresholdReached))

#ifdef PROFILING_SUPPORTED
#define PROFILE_ENTER 1
#define PROFILE_LEAVE 2
#define PROFILE_TAILCALL 4

#define SIZEOF__PROFILE_PLATFORM_SPECIFIC_DATA 272
ASMCONSTANTS_C_ASSERT(SIZEOF__PROFILE_PLATFORM_SPECIFIC_DATA == sizeof(PROFILE_PLATFORM_SPECIFIC_DATA))
#define PROFILE_ENTER 1
#define PROFILE_LEAVE 2
#define PROFILE_TAILCALL 4

// NOTE: this should be 16-byte aligned as stack size.
#define SIZEOF__PROFILE_PLATFORM_SPECIFIC_DATA 0x140
ASMCONSTANTS_C_ASSERT(SIZEOF__PROFILE_PLATFORM_SPECIFIC_DATA == (sizeof(PROFILE_PLATFORM_SPECIFIC_DATA)+8))
ASMCONSTANTS_C_ASSERT((SIZEOF__PROFILE_PLATFORM_SPECIFIC_DATA & 0xf) == 0)

#define PROFILE_PLATFORM_SPECIFIC_DATA__Fp 0
#define PROFILE_PLATFORM_SPECIFIC_DATA__Pc 8
#define PROFILE_PLATFORM_SPECIFIC_DATA__probeSp 16
#define PROFILE_PLATFORM_SPECIFIC_DATA__profiledSp 24
#define PROFILE_PLATFORM_SPECIFIC_DATA__hiddenArg 32
#define PROFILE_PLATFORM_SPECIFIC_DATA__functionId 40
#define PROFILE_PLATFORM_SPECIFIC_DATA__flags 48
#define PROFILE_PLATFORM_SPECIFIC_DATA__argumentRegisters 56
#define PROFILE_PLATFORM_SPECIFIC_DATA__floatArgumentRegisters 120

#define ASMCONSTANTS_C_ASSERT_OFFSET(type, field) \
ASMCONSTANTS_C_ASSERT(type##__##field == offsetof(type, field))

#define PROFILE_PLATFORM_SPECIFIC_DATA__Fp 0
ASMCONSTANTS_C_ASSERT_OFFSET(PROFILE_PLATFORM_SPECIFIC_DATA, Fp)
#define PROFILE_PLATFORM_SPECIFIC_DATA__Pc 8
ASMCONSTANTS_C_ASSERT_OFFSET(PROFILE_PLATFORM_SPECIFIC_DATA, Pc)
#define PROFILE_PLATFORM_SPECIFIC_DATA__x8 16
ASMCONSTANTS_C_ASSERT_OFFSET(PROFILE_PLATFORM_SPECIFIC_DATA, x8)
#define PROFILE_PLATFORM_SPECIFIC_DATA__argumentRegisters 24
ASMCONSTANTS_C_ASSERT_OFFSET(PROFILE_PLATFORM_SPECIFIC_DATA, argumentRegisters)
#define PROFILE_PLATFORM_SPECIFIC_DATA__functionId 88
ASMCONSTANTS_C_ASSERT_OFFSET(PROFILE_PLATFORM_SPECIFIC_DATA, functionId)
#define PROFILE_PLATFORM_SPECIFIC_DATA__floatArgumentRegisters 96
ASMCONSTANTS_C_ASSERT_OFFSET(PROFILE_PLATFORM_SPECIFIC_DATA, floatArgumentRegisters)
#define PROFILE_PLATFORM_SPECIFIC_DATA__probeSp 224
ASMCONSTANTS_C_ASSERT_OFFSET(PROFILE_PLATFORM_SPECIFIC_DATA, probeSp)
#define PROFILE_PLATFORM_SPECIFIC_DATA__profiledSp 232
ASMCONSTANTS_C_ASSERT_OFFSET(PROFILE_PLATFORM_SPECIFIC_DATA, profiledSp)
#define PROFILE_PLATFORM_SPECIFIC_DATA__hiddenArg 240
ASMCONSTANTS_C_ASSERT_OFFSET(PROFILE_PLATFORM_SPECIFIC_DATA, hiddenArg)
#define PROFILE_PLATFORM_SPECIFIC_DATA__flags 248
ASMCONSTANTS_C_ASSERT_OFFSET(PROFILE_PLATFORM_SPECIFIC_DATA, functionId)
ASMCONSTANTS_C_ASSERT_OFFSET(PROFILE_PLATFORM_SPECIFIC_DATA, flags)
#define PROFILE_PLATFORM_SPECIFIC_DATA__unused 252
ASMCONSTANTS_C_ASSERT_OFFSET(PROFILE_PLATFORM_SPECIFIC_DATA, unused)
#define PROFILE_PLATFORM_SPECIFIC_DATA__buffer 256
ASMCONSTANTS_C_ASSERT_OFFSET(PROFILE_PLATFORM_SPECIFIC_DATA, buffer)

ASMCONSTANTS_C_ASSERT_OFFSET(PROFILE_PLATFORM_SPECIFIC_DATA, argumentRegisters)
ASMCONSTANTS_C_ASSERT_OFFSET(PROFILE_PLATFORM_SPECIFIC_DATA, floatArgumentRegisters)
#undef ASMCONSTANTS_C_ASSERT_OFFSET
#endif

#endif // PROFILING_SUPPORTED

#undef ASMCONSTANTS_RUNTIME_ASSERT
#undef ASMCONSTANTS_C_ASSERT
28 changes: 13 additions & 15 deletions src/coreclr/vm/loongarch64/asmhelpers.S
Original file line number Diff line number Diff line change
Expand Up @@ -1078,29 +1078,27 @@ NESTED_ENTRY \helper\()Naked, _TEXT, NoHandler
// Values of $a0-$a7, $fa0-$fa7, $fp are preserved.
// Values of other volatile registers are not preserved.

// $fp,$ra
// $fp,$ra
PROLOG_SAVE_REG_PAIR_INDEXED 22, 1, SIZEOF__PROFILE_PLATFORM_SPECIFIC_DATA // Allocate space and save Fp, Pc.
// Please validate, SAVE_ARGUMENT_REGISTERS doesn't save $t0
SAVE_ARGUMENT_REGISTERS $sp, PROFILE_PLATFORM_SPECIFIC_DATA__argumentRegisters // Save $t0 and argument registers ($a0-$a7).
st.d $zero, $sp, PROFILE_PLATFORM_SPECIFIC_DATA__functionId // Clear functionId.

SAVE_ARGUMENT_REGISTERS $sp, PROFILE_PLATFORM_SPECIFIC_DATA__argumentRegisters
SAVE_FLOAT_ARGUMENT_REGISTERS $sp, PROFILE_PLATFORM_SPECIFIC_DATA__floatArgumentRegisters
addi.d $t3, $fp, SIZEOF__PROFILE_PLATFORM_SPECIFIC_DATA // Compute probeSp - initial value of Sp on entry to the helper.
st.d $t3, $sp, PROFILE_PLATFORM_SPECIFIC_DATA__probeSp
st.d $t2, $sp, PROFILE_PLATFORM_SPECIFIC_DATA__profiledSp
st.d $zero, $sp, PROFILE_PLATFORM_SPECIFIC_DATA__functionId
addi.d $t3, $sp, SIZEOF__PROFILE_PLATFORM_SPECIFIC_DATA // Compute probeSp - initial value of Sp on entry to the helper.
st.d $t3, $sp, PROFILE_PLATFORM_SPECIFIC_DATA__probeSp
st.d $t2, $sp, PROFILE_PLATFORM_SPECIFIC_DATA__profiledSp

st.d $zero, $sp, PROFILE_PLATFORM_SPECIFIC_DATA__hiddenArg // Clear hiddenArg.
addi.d $t3, $zero, \flags
st.d $zero, $sp, PROFILE_PLATFORM_SPECIFIC_DATA__hiddenArg
addi.w $t3, $zero, \flags
st.w $t3, $sp, PROFILE_PLATFORM_SPECIFIC_DATA__flags
st.d $zero, $sp, PROFILE_PLATFORM_SPECIFIC_DATA__unused

ori $a1, $t1, 0
ori $a2, $sp, 0
ori $a0, $t1, 0
ori $a1, $sp, 0
bl C_FUNC(\helper)

// Please validate, RESTORE_ARGUMENT_REGISTERS doesn't restore $t0
RESTORE_ARGUMENT_REGISTERS $sp, PROFILE_PLATFORM_SPECIFIC_DATA__argumentRegisters // Restore $t0 and argument registers.
RESTORE_ARGUMENT_REGISTERS $sp, PROFILE_PLATFORM_SPECIFIC_DATA__argumentRegisters
RESTORE_FLOAT_ARGUMENT_REGISTERS $sp, PROFILE_PLATFORM_SPECIFIC_DATA__floatArgumentRegisters
// $fp, $ra
// $fp, $ra
EPILOG_RESTORE_REG_PAIR_INDEXED 22, 1, SIZEOF__PROFILE_PLATFORM_SPECIFIC_DATA
EPILOG_RETURN

Expand Down
Loading
Loading