From f2907af68caaec855a16118876492c42ed88d745 Mon Sep 17 00:00:00 2001 From: Hyeongseok Oh Date: Tue, 11 Jul 2017 10:49:55 +0900 Subject: [PATCH] [RyuJIT/ARM32] Internal register candadate for split struct argument Change candidate mask for internal register candidate to not include target registers. On codegen phase, if addrReg is allocated to be destroyed by targetReg, we use internal register as addrReg. --- src/jit/codegenarmarch.cpp | 15 +++++++++++++-- src/jit/lsraarmarch.cpp | 4 +++- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/src/jit/codegenarmarch.cpp b/src/jit/codegenarmarch.cpp index e514644..3339e56 100644 --- a/src/jit/codegenarmarch.cpp +++ b/src/jit/codegenarmarch.cpp @@ -1019,6 +1019,11 @@ void CodeGen::genPutArgSplit(GenTreePutArgSplit* treeNode) // Generate code to load the address that we need into a register genConsumeAddress(addrNode); addrReg = addrNode->gtRegNum; + + // If addrReg equal to baseReg, we use the last target register as alternative baseReg. + // Because the candidate mask for the internal baseReg does not include any of the target register, + // we can ensure that baseReg, addrReg, and the last target register are not all same. + assert(baseReg != addrReg); } // If we have an HFA we can't have any GC pointers, @@ -1062,7 +1067,8 @@ void CodeGen::genPutArgSplit(GenTreePutArgSplit* treeNode) nextIndex += 1; } - // Set registers + // We set up the registers in order, so that we assign the last target register `baseReg` is no longer in use, + // in case we had to reuse the last target register for it. structOffset = 0; for (unsigned idx = 0; idx < treeNode->gtNumRegs; idx++) { @@ -1077,7 +1083,12 @@ void CodeGen::genPutArgSplit(GenTreePutArgSplit* treeNode) else { // check for case of destroying the addrRegister while we still need it - assert(targetReg != addrReg); + if (targetReg == addrReg && idx != treeNode->gtNumRegs - 1) + { + assert(targetReg != baseReg); + emit->emitIns_R_R(INS_mov, emitTypeSize(type), baseReg, addrReg); + addrReg = baseReg; + } // Load from our address expression source emit->emitIns_R_R_I(INS_ldr, emitTypeSize(type), targetReg, addrReg, structOffset); diff --git a/src/jit/lsraarmarch.cpp b/src/jit/lsraarmarch.cpp index a42ef4b..c4f124f 100644 --- a/src/jit/lsraarmarch.cpp +++ b/src/jit/lsraarmarch.cpp @@ -843,9 +843,11 @@ void Lowering::TreeNodeInfoInitPutArgSplit(GenTreePutArgSplit* argNode, TreeNode assert(putArgChild->TypeGet() == TYP_STRUCT); assert(putArgChild->OperGet() == GT_OBJ); - argNode->gtLsraInfo.srcCount = 1; // We could use a ldr/str sequence so we need a internal register + argNode->gtLsraInfo.srcCount = 1; argNode->gtLsraInfo.internalIntCount = 1; + regMaskTP internalMask = RBM_ALLINT & ~argMask; + argNode->gtLsraInfo.setInternalCandidates(m_lsra, internalMask); GenTreePtr objChild = putArgChild->gtOp.gtOp1; if (objChild->OperGet() == GT_LCL_VAR_ADDR) -- 2.7.4