From 1b6be2dfdd67ab301e089649920a1049d0cd7b11 Mon Sep 17 00:00:00 2001 From: Mikhail Skvortcov Date: Wed, 12 Apr 2017 09:18:08 +0300 Subject: [PATCH] RyuJIT/ARM32: encodable offsets for ld/st Commit migrated from https://github.com/dotnet/coreclr/commit/21b64422dc80a21eee8dfb8a64b9136ef7a0adcc --- src/coreclr/src/jit/emitarm.cpp | 36 +++++++++++++++++++++++++++++++++--- src/coreclr/src/jit/emitarm.h | 1 + src/coreclr/src/jit/lsraarmarch.cpp | 12 ++---------- 3 files changed, 36 insertions(+), 13 deletions(-) diff --git a/src/coreclr/src/jit/emitarm.cpp b/src/coreclr/src/jit/emitarm.cpp index ebefa27..53ee88b 100644 --- a/src/coreclr/src/jit/emitarm.cpp +++ b/src/coreclr/src/jit/emitarm.cpp @@ -1422,6 +1422,20 @@ DONE: /***************************************************************************** * + * emitIns_valid_imm_for_ldst_offset() returns true when the immediate 'imm' + * can be encoded as the offset in a ldr/str instruction. + */ +/*static*/ bool emitter::emitIns_valid_imm_for_ldst_offset(int imm, emitAttr size) +{ + if ((imm & 0x0fff) == imm) + return true; // encodable using IF_T2_K1 + if (unsigned_abs(imm) <= 0x0ff) + return true; // encodable using IF_T2_H0 + return false; +} + +/***************************************************************************** + * * Add an instruction with no operands. */ @@ -7608,10 +7622,26 @@ void emitter::emitInsLoadStoreOp(instruction ins, emitAttr attr, regNumber dataR } } } - else + else // no Index { - // TODO check offset is valid for encoding - emitIns_R_R_I(ins, attr, dataReg, memBase->gtRegNum, offset); + if (emitIns_valid_imm_for_ldst_offset(offset, attr)) + { + // Then load/store dataReg from/to [memBase + offset] + emitIns_R_R_I(ins, attr, dataReg, memBase->gtRegNum, offset); + } + else + { + // We require a tmpReg to hold the offset + regMaskTP tmpRegMask = indir->gtRsvdRegs; + regNumber tmpReg = genRegNumFromMask(tmpRegMask); + noway_assert(tmpReg != REG_NA); + + // First load/store tmpReg with the large offset constant + codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, tmpReg, offset); + + // Then load/store dataReg from/to [memBase + tmpReg] + emitIns_R_R_R(ins, attr, dataReg, memBase->gtRegNum, tmpReg); + } } } else diff --git a/src/coreclr/src/jit/emitarm.h b/src/coreclr/src/jit/emitarm.h index 4ec1893..d7c8d4d 100644 --- a/src/coreclr/src/jit/emitarm.h +++ b/src/coreclr/src/jit/emitarm.h @@ -243,6 +243,7 @@ static bool emitIns_valid_imm_for_small_mov(regNumber reg, int imm, insFlags fla static bool emitIns_valid_imm_for_add(int imm, insFlags flags); static bool emitIns_valid_imm_for_cmp(int imm, insFlags flags); static bool emitIns_valid_imm_for_add_sp(int imm); +static bool emitIns_valid_imm_for_ldst_offset(int imm, emitAttr size); void emitIns(instruction ins); diff --git a/src/coreclr/src/jit/lsraarmarch.cpp b/src/coreclr/src/jit/lsraarmarch.cpp index 11fc490..7d999d8 100644 --- a/src/coreclr/src/jit/lsraarmarch.cpp +++ b/src/coreclr/src/jit/lsraarmarch.cpp @@ -291,19 +291,13 @@ void Lowering::TreeNodeInfoInitIndir(GenTreePtr indirTree) if (index != nullptr && !modifiedSources) { info->srcCount++; - -#ifdef _TARGET_ARM_ - info->internalIntCount++; -#endif // _TARGET_ARM_ } -#ifdef _TARGET_ARM64_ - - // On ARM64 we may need a single internal register + // On ARM we may need a single internal register // (when both conditions are true then we still only need a single internal register) if ((index != nullptr) && (cns != 0)) { - // ARM64 does not support both Index and offset so we need an internal register + // ARM does not support both Index and offset so we need an internal register info->internalIntCount = 1; } else if (!emitter::emitIns_valid_imm_for_ldst_offset(cns, emitTypeSize(indirTree))) @@ -311,8 +305,6 @@ void Lowering::TreeNodeInfoInitIndir(GenTreePtr indirTree) // This offset can't be contained in the ldr/str instruction, so we need an internal register info->internalIntCount = 1; } - -#endif // _TARGET_ARM64_ } //------------------------------------------------------------------------ -- 2.7.4