diff --git a/src/coreclr/jit/codegenarmarch.cpp b/src/coreclr/jit/codegenarmarch.cpp index 1cb7ae7985c27..cf37ab2802708 100644 --- a/src/coreclr/jit/codegenarmarch.cpp +++ b/src/coreclr/jit/codegenarmarch.cpp @@ -3682,11 +3682,11 @@ void CodeGen::genCallInstruction(GenTreeCall* call) { #ifdef TARGET_ARM // For arm32 we've allocated an internal register to load the target into. - // Loading into lr takes 4 bytes (instead of potentially 2 with another register). + // Loading into IP takes 4 bytes (instead of potentially 2 with another register). targetAddrReg = internalRegisters.GetSingle(call); #else - // For arm64 we just use lr and skip the internal register. - targetAddrReg = REG_LR; + // For arm64 we just use IP0 and skip the internal register. + targetAddrReg = REG_INDIRECT_CALL_TARGET_REG; #endif GetEmitter()->emitIns_R_R(ins_Load(TYP_I_IMPL), emitActualTypeSize(TYP_I_IMPL), targetAddrReg, diff --git a/src/coreclr/jit/lsra.cpp b/src/coreclr/jit/lsra.cpp index 8d1da2dbe4647..cac4c845a2cdc 100644 --- a/src/coreclr/jit/lsra.cpp +++ b/src/coreclr/jit/lsra.cpp @@ -788,6 +788,9 @@ LinearScan::LinearScan(Compiler* theCompiler) regSelector = new (theCompiler, CMK_LSRA) RegisterSelection(this); #ifdef TARGET_ARM64 + // Note: one known reason why we exclude LR is because NativeAOT has dependency on not + // using LR as a GPR. See: https://github.com/dotnet/runtime/issues/101932 + // Once that is addressed, we may consider allowing LR in availableIntRegs. availableIntRegs = (RBM_ALLINT & ~(RBM_PR | RBM_FP | RBM_LR) & ~compiler->codeGen->regSet.rsMaskResvd); #elif defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64) availableIntRegs = (RBM_ALLINT & ~(RBM_FP | RBM_RA) & ~compiler->codeGen->regSet.rsMaskResvd); diff --git a/src/coreclr/jit/lsraarmarch.cpp b/src/coreclr/jit/lsraarmarch.cpp index 64bbe23b06a66..d40e91cdb8c54 100644 --- a/src/coreclr/jit/lsraarmarch.cpp +++ b/src/coreclr/jit/lsraarmarch.cpp @@ -191,9 +191,9 @@ int LinearScan::BuildCall(GenTreeCall* call) } else { - // For arm64 we can use lr for non-tailcalls so we skip the - // internal register as a TP optimization. We could do the same for - // arm32, but loading into lr cannot be encoded in 2 bytes, so + // For arm64 we can use REG_INDIRECT_CALL_TARGET_REG (IP0) for non-tailcalls + // so we skip the internal register as a TP optimization. We could do the same for + // arm32, but loading into IP cannot be encoded in 2 bytes, so // another register is usually better. #ifdef TARGET_ARM buildInternalIntRegisterDefForNode(call);