From c66363075a386514dde8ea3632c4ecbfdd9554e7 Mon Sep 17 00:00:00 2001 From: Carol Eidt Date: Thu, 11 Jun 2020 17:24:04 -0700 Subject: [PATCH] For arm32, kill REG_PROFILER_RET_SCRATCH for LSRA but not for GC Reworking of #37969. Block LSRA from using R2 around the profiler leave callback, but don't kill GC refs in R2, since late codegen will use R2 to temporarily hold return values around the callback. Fixes #37223. --- src/coreclr/src/jit/emit.cpp | 5 +++++ src/coreclr/src/jit/lsraarm.cpp | 2 ++ src/coreclr/src/jit/target.h | 4 +++- 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/coreclr/src/jit/emit.cpp b/src/coreclr/src/jit/emit.cpp index cc12dabc5492eb..ab1c281ea5eb99 100644 --- a/src/coreclr/src/jit/emit.cpp +++ b/src/coreclr/src/jit/emit.cpp @@ -7692,7 +7692,12 @@ regMaskTP emitter::emitGetGCRegsKilledByNoGCCall(CorInfoHelpFunc helper) break; case CORINFO_HELP_PROF_FCN_LEAVE: +#if defined(TARGET_ARM) + // profiler scratch remains gc live + result = RBM_PROFILER_LEAVE_TRASH & ~RBM_PROFILER_RET_SCRATCH; +#else result = RBM_PROFILER_LEAVE_TRASH; +#endif break; case CORINFO_HELP_PROF_FCN_TAILCALL: diff --git a/src/coreclr/src/jit/lsraarm.cpp b/src/coreclr/src/jit/lsraarm.cpp index b9b4d0f6d3e6ad..8402bcdefc0fe4 100644 --- a/src/coreclr/src/jit/lsraarm.cpp +++ b/src/coreclr/src/jit/lsraarm.cpp @@ -491,6 +491,8 @@ int LinearScan::BuildNode(GenTree* tree) case GT_RETURN: srcCount = BuildReturn(tree); + killMask = getKillSetForReturn(); + BuildDefsWithKills(tree, 0, RBM_NONE, killMask); break; case GT_RETFILT: diff --git a/src/coreclr/src/jit/target.h b/src/coreclr/src/jit/target.h index 17ecc23c0a16c6..5eac47184cdd16 100644 --- a/src/coreclr/src/jit/target.h +++ b/src/coreclr/src/jit/target.h @@ -1106,7 +1106,9 @@ typedef unsigned char regNumberSmall; // The registers trashed by profiler enter/leave/tailcall hook // See vm\arm\asmhelpers.asm for more details. #define RBM_PROFILER_ENTER_TRASH RBM_NONE - #define RBM_PROFILER_LEAVE_TRASH RBM_NONE + // While REG_PROFILER_RET_SCRATCH is not trashed by the method, the register allocator must + // consider it killed by the return. + #define RBM_PROFILER_LEAVE_TRASH RBM_PROFILER_RET_SCRATCH #define RBM_PROFILER_TAILCALL_TRASH RBM_NONE // Which register are int and long values returned in ?