diff options
author | Steve MacLean, Qualcomm Datacenter Technologies, Inc <sdmaclea@qti.qualcomm.com> | 2017-05-01 19:10:37 +0000 |
---|---|---|
committer | Steve MacLean, Qualcomm Datacenter Technologies, Inc <sdmaclea@qti.qualcomm.com> | 2017-05-08 16:23:46 +0000 |
commit | 16ca06c4b68502b39c105367f27a8f62368959d4 (patch) | |
tree | c0726741f850682fd48230679ecba9bce542c1fb | |
parent | 494f00cb881cc68426718b32a62464d4c7c48007 (diff) | |
download | coreclr-16ca06c4b68502b39c105367f27a8f62368959d4.tar.gz coreclr-16ca06c4b68502b39c105367f27a8f62368959d4.tar.bz2 coreclr-16ca06c4b68502b39c105367f27a8f62368959d4.zip |
[Arm64] Add emitIns_R_R_S_S
-rw-r--r-- | src/jit/codegenarm64.cpp | 4 | ||||
-rw-r--r-- | src/jit/codegenarmarch.cpp | 29 | ||||
-rw-r--r-- | src/jit/emitarm64.cpp | 95 | ||||
-rw-r--r-- | src/jit/emitarm64.h | 3 |
4 files changed, 104 insertions, 27 deletions
diff --git a/src/jit/codegenarm64.cpp b/src/jit/codegenarm64.cpp index 0e536cd445..88240409e6 100644 --- a/src/jit/codegenarm64.cpp +++ b/src/jit/codegenarm64.cpp @@ -2597,9 +2597,7 @@ void CodeGen::genCodeForLoadPairOffset(regNumber dst, regNumber dst2, GenTree* b if (base->gtOper == GT_LCL_FLD_ADDR) offset += base->gtLclFld.gtLclOffs; - // TODO-ARM64-CQ: Implement support for using a ldp instruction with a varNum (see emitIns_R_S) - emit->emitIns_R_S(INS_ldr, EA_8BYTE, dst, base->gtLclVarCommon.gtLclNum, offset); - emit->emitIns_R_S(INS_ldr, EA_8BYTE, dst2, base->gtLclVarCommon.gtLclNum, offset + REGSIZE_BYTES); + emit->emitIns_R_R_S_S(INS_ldp, EA_8BYTE, EA_8BYTE, dst, dst2, base->gtLclVarCommon.gtLclNum, offset); } else { diff --git a/src/jit/codegenarmarch.cpp b/src/jit/codegenarmarch.cpp index 61b9309bb9..d71a0b776e 100644 --- a/src/jit/codegenarmarch.cpp +++ b/src/jit/codegenarmarch.cpp @@ -686,28 +686,9 @@ void CodeGen::genPutArgStk(GenTreePutArgStk* treeNode) noway_assert(structSize <= MAX_PASS_MULTIREG_BYTES); - // For a 16-byte structSize with GC pointers we will use two ldr and two str instructions - // ldr x2, [x0] - // ldr x3, [x0, #8] - // str x2, [sp, #16] - // str x3, [sp, #24] - // - // For a 16-byte structSize with no GC pointers we will use a ldp and two str instructions - // ldp x2, x3, [x0] - // str x2, [sp, #16] - // str x3, [sp, #24] - // - // For a 32-byte structSize with no GC pointers we will use two ldp and four str instructions - // ldp x2, x3, [x0] - // str x2, [sp, #16] - // str x3, [sp, #24] + // For a >= 16-byte structSize we will generate a ldp and stp instruction each loop // ldp x2, x3, [x0] - // str x2, [sp, #32] - // str x3, [sp, #40] - // - // Note that when loading from a varNode we currently can't use the ldp instruction - // TODO-ARM64-CQ: Implement support for using a ldp instruction with a varNum (see emitIns_R_S) - // + // stp x2, x3, [sp, #16] int remainingSize = structSize; unsigned structOffset = 0; @@ -720,9 +701,9 @@ void CodeGen::genPutArgStk(GenTreePutArgStk* treeNode) if (varNode != nullptr) { - // Load from our varNumImp source, currently we can't use a ldp instruction to do this - emit->emitIns_R_S(ins_Load(type0), emitTypeSize(type0), loReg, varNumInp, 0); - emit->emitIns_R_S(ins_Load(type1), emitTypeSize(type1), hiReg, varNumInp, TARGET_POINTER_SIZE); + // Load from our varNumImp source + emit->emitIns_R_R_S_S(INS_ldp, emitTypeSize(type0), emitTypeSize(type1), loReg, hiReg, varNumInp, + 0); } else { diff --git a/src/jit/emitarm64.cpp b/src/jit/emitarm64.cpp index c979c240a4..d398b2f833 100644 --- a/src/jit/emitarm64.cpp +++ b/src/jit/emitarm64.cpp @@ -6110,6 +6110,101 @@ void emitter::emitIns_R_S(instruction ins, emitAttr attr, regNumber reg1, int va /***************************************************************************** * + * Add an instruction referencing two register and consectutive stack-based local variable slots. + */ +void emitter::emitIns_R_R_S_S( + instruction ins, emitAttr attr1, emitAttr attr2, regNumber reg1, regNumber reg2, int varx, int offs) +{ + assert((ins == INS_ldp) || (ins == INS_ldnp)); + assert(EA_8BYTE == EA_SIZE(attr1)); + assert(EA_8BYTE == EA_SIZE(attr2)); + assert(isGeneralRegisterOrZR(reg1)); + assert(isGeneralRegisterOrZR(reg2)); + assert(offs >= 0); + + emitAttr size = EA_SIZE(attr1); + insFormat fmt = IF_LS_3B; + int disp = 0; + const unsigned scale = 3; + + /* Figure out the variable's frame position */ + int base; + bool FPbased; + + base = emitComp->lvaFrameAddress(varx, &FPbased); + disp = base + offs; + + // TODO-ARM64-CQ: with compLocallocUsed, should we use REG_SAVED_LOCALLOC_SP instead? + regNumber reg3 = FPbased ? REG_FPBASE : REG_SPBASE; + reg3 = encodingSPtoZR(reg3); + + bool useRegForAdr = true; + ssize_t imm = disp; + ssize_t mask = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate + if (imm == 0) + { + useRegForAdr = false; + } + else + { + if ((imm & mask) == 0) + { + ssize_t immShift = imm >> scale; // The immediate is scaled by the size of the ld/st + + if ((immShift >= -64) && (immShift <= 63)) + { + fmt = IF_LS_3C; + useRegForAdr = false; + imm = immShift; + } + } + } + + if (useRegForAdr) + { + regNumber rsvd = codeGen->rsGetRsvdReg(); + emitIns_R_R_Imm(INS_add, EA_8BYTE, rsvd, reg3, imm); + reg3 = rsvd; + imm = 0; + } + + assert(fmt != IF_NONE); + + instrDesc* id = emitNewInstrCns(attr1, imm); + + id->idIns(ins); + id->idInsFmt(fmt); + id->idInsOpt(INS_OPTS_NONE); + + if (EA_IS_GCREF(attr2)) + { + /* A special value indicates a GCref pointer value */ + + id->idGCrefReg2(GCT_GCREF); + } + else if (EA_IS_BYREF(attr2)) + { + /* A special value indicates a Byref pointer value */ + + id->idGCrefReg2(GCT_BYREF); + } + + id->idReg1(reg1); + id->idReg2(reg2); + id->idReg3(reg3); + id->idAddr()->iiaLclVar.initLclVarAddr(varx, offs); + id->idSetIsLclVar(); + +#ifdef DEBUG + id->idDebugOnlyInfo()->idVarRefOffs = emitVarRefOffs; +#endif + + dispIns(id); + appendToCurIG(id); +} + +/***************************************************************************** + * * Add an instruction referencing a stack-based local variable and a register */ void emitter::emitIns_S_R(instruction ins, emitAttr attr, regNumber reg1, int varx, int offs) diff --git a/src/jit/emitarm64.h b/src/jit/emitarm64.h index 87caa22638..09158fb796 100644 --- a/src/jit/emitarm64.h +++ b/src/jit/emitarm64.h @@ -763,6 +763,9 @@ void emitIns_S_S_R_R( void emitIns_R_S(instruction ins, emitAttr attr, regNumber ireg, int varx, int offs); +void emitIns_R_R_S_S( + instruction ins, emitAttr attr, emitAttr attr2, regNumber ireg, regNumber ireg2, int varx, int offs); + void emitIns_S_I(instruction ins, emitAttr attr, int varx, int offs, int val); void emitIns_R_C( |