From 528b1faea03cebabae6a9971c9bcf935f515cb99 Mon Sep 17 00:00:00 2001 From: Mike Danes Date: Sat, 8 Jul 2017 08:51:15 +0300 Subject: [PATCH 1/3] Split emitter::emitInsMov into separate functions None of this function's callers need it to figure out what kind of "mov" to emit, the callers already know what they need and they should call the appropiate function. Copy & paste code, no actual changes. --- src/jit/codegenxarch.cpp | 8 +- src/jit/emit.h | 4 +- src/jit/emitxarch.cpp | 242 +++++++++++++++++++++------------------ 3 files changed, 140 insertions(+), 114 deletions(-) diff --git a/src/jit/codegenxarch.cpp b/src/jit/codegenxarch.cpp index 57a9adcc3f42..ed37c604e3a6 100644 --- a/src/jit/codegenxarch.cpp +++ b/src/jit/codegenxarch.cpp @@ -4436,8 +4436,8 @@ void CodeGen::genCodeForStoreLclVar(GenTreeLclVar* tree) if (targetReg == REG_NA) { // stack store - emit->emitInsMov(ins_Store(targetType, compiler->isSIMDTypeLocalAligned(lclNum)), emitTypeSize(targetType), - tree); + emit->emitInsStoreLcl(ins_Store(targetType, compiler->isSIMDTypeLocalAligned(lclNum)), + emitTypeSize(targetType), tree); varDsc->lvRegNum = REG_STK; } else @@ -4512,7 +4512,7 @@ void CodeGen::genCodeForIndir(GenTreeIndir* tree) else { genConsumeAddress(addr); - emit->emitInsMov(ins_Load(targetType), emitTypeSize(tree), tree); + emit->emitInsLoadInd(ins_Load(targetType), emitTypeSize(tree), tree); } genProduceReg(tree); @@ -4774,7 +4774,7 @@ void CodeGen::genCodeForStoreInd(GenTreeStoreInd* tree) } else { - getEmitter()->emitInsMov(ins_Store(data->TypeGet()), emitTypeSize(tree), tree); + getEmitter()->emitInsStoreInd(ins_Store(data->TypeGet()), emitTypeSize(tree), tree); } } } diff --git a/src/jit/emit.h b/src/jit/emit.h index cfad5c60d713..f9134f26fefa 100644 --- a/src/jit/emit.h +++ b/src/jit/emit.h @@ -1718,7 +1718,9 @@ class emitter CORINFO_FIELD_HANDLE emitFltOrDblConst(GenTreeDblCon* tree, emitAttr attr = EA_UNKNOWN); regNumber emitInsBinary(instruction ins, emitAttr attr, GenTree* dst, GenTree* src); regNumber emitInsTernary(instruction ins, emitAttr attr, GenTree* dst, GenTree* src1, GenTree* src2); - void emitInsMov(instruction ins, emitAttr attr, GenTree* node); + void emitInsLoadInd(instruction ins, emitAttr attr, GenTree* node); + void emitInsStoreInd(instruction ins, emitAttr attr, GenTree* node); + void emitInsStoreLcl(instruction ins, emitAttr attr, GenTree* node); insFormat emitMapFmtForIns(insFormat fmt, instruction ins); insFormat emitMapFmtAtoM(insFormat fmt); void emitHandleMemOp(GenTreeIndir* indir, instrDesc* id, insFormat fmt, instruction ins); diff --git a/src/jit/emitxarch.cpp b/src/jit/emitxarch.cpp index fe20e9e297bb..e34cd660c33e 100644 --- a/src/jit/emitxarch.cpp +++ b/src/jit/emitxarch.cpp @@ -2639,132 +2639,156 @@ void emitter::spillIntArgRegsToShadowSlots() } } -// this is very similar to emitInsBinary and probably could be folded in to same -// except the requirements on the incoming parameter are different, -// ex: the memory op in storeind case must NOT be contained -void emitter::emitInsMov(instruction ins, emitAttr attr, GenTree* node) +//------------------------------------------------------------------------ +// emitInsLoadInd: Emits a "mov reg, [mem]" (or a variant such as "movzx" or "movss") +// instruction for a GT_IND node. +// +// Arguments: +// ins - the instruction to emit +// attr - the instruction operand size +// node - the GT_IND node +// +void emitter::emitInsLoadInd(instruction ins, emitAttr attr, GenTree* node) { + assert(node->OperIs(GT_IND)); + UNATIVE_OFFSET sz; instrDesc* id; - switch (node->OperGet()) + GenTreeIndir* mem = node->AsIndir(); + GenTreePtr addr = mem->Addr(); + + if (addr->OperGet() == GT_CLS_VAR_ADDR) { - case GT_IND: - { - GenTreeIndir* mem = node->AsIndir(); - GenTreePtr addr = mem->Addr(); + emitIns_R_C(ins, attr, mem->gtRegNum, addr->gtClsVar.gtClsVarHnd, 0); + return; + } + else if (addr->OperGet() == GT_LCL_VAR_ADDR) + { + GenTreeLclVarCommon* varNode = addr->AsLclVarCommon(); + emitIns_R_S(ins, attr, mem->gtRegNum, varNode->GetLclNum(), 0); + codeGen->genUpdateLife(varNode); + return; + } + else + { + assert(addr->OperIsAddrMode() || (addr->IsCnsIntOrI() && addr->isContained()) || !addr->isContained()); + size_t offset = mem->Offset(); + id = emitNewInstrAmd(attr, offset); + id->idIns(ins); + id->idReg1(mem->gtRegNum); + emitHandleMemOp(mem, id, IF_RWR_ARD, ins); + sz = emitInsSizeAM(id, insCodeRM(ins)); + id->idCodeSize(sz); + } - if (addr->OperGet() == GT_CLS_VAR_ADDR) - { - emitIns_R_C(ins, attr, mem->gtRegNum, addr->gtClsVar.gtClsVarHnd, 0); - return; - } - else if (addr->OperGet() == GT_LCL_VAR_ADDR) - { - GenTreeLclVarCommon* varNode = addr->AsLclVarCommon(); - emitIns_R_S(ins, attr, mem->gtRegNum, varNode->GetLclNum(), 0); - codeGen->genUpdateLife(varNode); - return; - } - else - { - assert(addr->OperIsAddrMode() || (addr->IsCnsIntOrI() && addr->isContained()) || !addr->isContained()); - size_t offset = mem->Offset(); - id = emitNewInstrAmd(attr, offset); - id->idIns(ins); - id->idReg1(mem->gtRegNum); - emitHandleMemOp(mem, id, IF_RWR_ARD, ins); - sz = emitInsSizeAM(id, insCodeRM(ins)); - id->idCodeSize(sz); - } - } - break; + dispIns(id); + emitCurIGsize += sz; +} - case GT_STOREIND: - { - GenTreeStoreInd* mem = node->AsStoreInd(); - GenTreePtr addr = mem->Addr(); - size_t offset = mem->Offset(); - GenTree* data = mem->Data(); +//------------------------------------------------------------------------ +// emitInsStoreInd: Emits a "mov [mem], reg/imm" (or a variant such as "movss") +// instruction for a GT_STOREIND node. +// +// Arguments: +// ins - the instruction to emit +// attr - the instruction operand size +// node - the GT_STOREIND node +// +void emitter::emitInsStoreInd(instruction ins, emitAttr attr, GenTree* node) +{ + assert(node->OperIs(GT_STOREIND)); - if (addr->OperGet() == GT_CLS_VAR_ADDR) - { - if (data->isContainedIntOrIImmed()) - { - emitIns_C_I(ins, attr, addr->gtClsVar.gtClsVarHnd, 0, (int)data->AsIntConCommon()->IconValue()); - } - else - { - assert(!data->isContained()); - emitIns_C_R(ins, attr, addr->gtClsVar.gtClsVarHnd, data->gtRegNum, 0); - } - return; - } - else if (addr->OperGet() == GT_LCL_VAR_ADDR) - { - GenTreeLclVarCommon* varNode = addr->AsLclVarCommon(); - if (data->isContainedIntOrIImmed()) - { - emitIns_S_I(ins, attr, varNode->GetLclNum(), 0, (int)data->AsIntConCommon()->IconValue()); - } - else - { - assert(!data->isContained()); - emitIns_S_R(ins, attr, data->gtRegNum, varNode->GetLclNum(), 0); - } - codeGen->genUpdateLife(varNode); - return; - } - else if (data->isContainedIntOrIImmed()) - { - int icon = (int)data->AsIntConCommon()->IconValue(); - id = emitNewInstrAmdCns(attr, offset, icon); - id->idIns(ins); - emitHandleMemOp(mem, id, IF_AWR_CNS, ins); - sz = emitInsSizeAM(id, insCodeMI(ins), icon); - id->idCodeSize(sz); - } - else - { - assert(!data->isContained()); - id = emitNewInstrAmd(attr, offset); - id->idIns(ins); - emitHandleMemOp(mem, id, IF_AWR_RRD, ins); - id->idReg1(data->gtRegNum); - sz = emitInsSizeAM(id, insCodeMR(ins)); - id->idCodeSize(sz); - } - } - break; + UNATIVE_OFFSET sz; + instrDesc* id; - case GT_STORE_LCL_VAR: - { - GenTreeLclVarCommon* varNode = node->AsLclVarCommon(); - GenTree* data = varNode->gtOp.gtOp1; - codeGen->inst_set_SV_var(varNode); - assert(varNode->gtRegNum == REG_NA); // stack store + GenTreeStoreInd* mem = node->AsStoreInd(); + GenTreePtr addr = mem->Addr(); + size_t offset = mem->Offset(); + GenTree* data = mem->Data(); - if (data->isContainedIntOrIImmed()) - { - emitIns_S_I(ins, attr, varNode->GetLclNum(), 0, (int)data->AsIntConCommon()->IconValue()); - } - else - { - assert(!data->isContained()); - emitIns_S_R(ins, attr, data->gtRegNum, varNode->GetLclNum(), 0); - } - codeGen->genUpdateLife(varNode); + if (addr->OperGet() == GT_CLS_VAR_ADDR) + { + if (data->isContainedIntOrIImmed()) + { + emitIns_C_I(ins, attr, addr->gtClsVar.gtClsVarHnd, 0, (int)data->AsIntConCommon()->IconValue()); } - return; - - default: - unreached(); + else + { + assert(!data->isContained()); + emitIns_C_R(ins, attr, addr->gtClsVar.gtClsVarHnd, data->gtRegNum, 0); + } + return; + } + else if (addr->OperGet() == GT_LCL_VAR_ADDR) + { + GenTreeLclVarCommon* varNode = addr->AsLclVarCommon(); + if (data->isContainedIntOrIImmed()) + { + emitIns_S_I(ins, attr, varNode->GetLclNum(), 0, (int)data->AsIntConCommon()->IconValue()); + } + else + { + assert(!data->isContained()); + emitIns_S_R(ins, attr, data->gtRegNum, varNode->GetLclNum(), 0); + } + codeGen->genUpdateLife(varNode); + return; + } + else if (data->isContainedIntOrIImmed()) + { + int icon = (int)data->AsIntConCommon()->IconValue(); + id = emitNewInstrAmdCns(attr, offset, icon); + id->idIns(ins); + emitHandleMemOp(mem, id, IF_AWR_CNS, ins); + sz = emitInsSizeAM(id, insCodeMI(ins), icon); + id->idCodeSize(sz); + } + else + { + assert(!data->isContained()); + id = emitNewInstrAmd(attr, offset); + id->idIns(ins); + emitHandleMemOp(mem, id, IF_AWR_RRD, ins); + id->idReg1(data->gtRegNum); + sz = emitInsSizeAM(id, insCodeMR(ins)); + id->idCodeSize(sz); } dispIns(id); emitCurIGsize += sz; } +//------------------------------------------------------------------------ +// emitInsStoreLcl: Emits a "mov [mem], reg/imm" (or a variant such as "movss") +// instruction for a GT_STORE_LCL_VAR node. +// +// Arguments: +// ins - the instruction to emit +// attr - the instruction operand size +// node - the GT_STORE_LCL_VAR node +// +void emitter::emitInsStoreLcl(instruction ins, emitAttr attr, GenTree* node) +{ + assert(node->OperIs(GT_STORE_LCL_VAR)); + + GenTreeLclVarCommon* varNode = node->AsLclVarCommon(); + GenTree* data = varNode->gtOp.gtOp1; + codeGen->inst_set_SV_var(varNode); + assert(varNode->gtRegNum == REG_NA); // stack store + + if (data->isContainedIntOrIImmed()) + { + emitIns_S_I(ins, attr, varNode->GetLclNum(), 0, (int)data->AsIntConCommon()->IconValue()); + } + else + { + assert(!data->isContained()); + emitIns_S_R(ins, attr, data->gtRegNum, varNode->GetLclNum(), 0); + } + codeGen->genUpdateLife(varNode); +} + CORINFO_FIELD_HANDLE emitter::emitLiteralConst(ssize_t cnsValIn, emitAttr attr /*= EA_8BYTE*/) { NYI("emitLiteralConst"); From c354a1fbd791c415d3c08be3a816baf7c113e172 Mon Sep 17 00:00:00 2001 From: Mike Danes Date: Sat, 8 Jul 2017 10:19:06 +0300 Subject: [PATCH 2/3] Pass the destination register to emitInsLoadInd This way it can be used for contained indirs where the destination register is set on the parent node. --- src/jit/codegenxarch.cpp | 2 +- src/jit/emit.h | 2 +- src/jit/emitxarch.cpp | 9 +++++---- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/jit/codegenxarch.cpp b/src/jit/codegenxarch.cpp index ed37c604e3a6..a0931db8d3a7 100644 --- a/src/jit/codegenxarch.cpp +++ b/src/jit/codegenxarch.cpp @@ -4512,7 +4512,7 @@ void CodeGen::genCodeForIndir(GenTreeIndir* tree) else { genConsumeAddress(addr); - emit->emitInsLoadInd(ins_Load(targetType), emitTypeSize(tree), tree); + emit->emitInsLoadInd(ins_Load(targetType), emitTypeSize(tree), tree->gtRegNum, tree); } genProduceReg(tree); diff --git a/src/jit/emit.h b/src/jit/emit.h index f9134f26fefa..1dc711f91505 100644 --- a/src/jit/emit.h +++ b/src/jit/emit.h @@ -1718,7 +1718,7 @@ class emitter CORINFO_FIELD_HANDLE emitFltOrDblConst(GenTreeDblCon* tree, emitAttr attr = EA_UNKNOWN); regNumber emitInsBinary(instruction ins, emitAttr attr, GenTree* dst, GenTree* src); regNumber emitInsTernary(instruction ins, emitAttr attr, GenTree* dst, GenTree* src1, GenTree* src2); - void emitInsLoadInd(instruction ins, emitAttr attr, GenTree* node); + void emitInsLoadInd(instruction ins, emitAttr attr, regNumber dstReg, GenTree* node); void emitInsStoreInd(instruction ins, emitAttr attr, GenTree* node); void emitInsStoreLcl(instruction ins, emitAttr attr, GenTree* node); insFormat emitMapFmtForIns(insFormat fmt, instruction ins); diff --git a/src/jit/emitxarch.cpp b/src/jit/emitxarch.cpp index e34cd660c33e..5b1320120205 100644 --- a/src/jit/emitxarch.cpp +++ b/src/jit/emitxarch.cpp @@ -2646,9 +2646,10 @@ void emitter::spillIntArgRegsToShadowSlots() // Arguments: // ins - the instruction to emit // attr - the instruction operand size +// dstReg - the destination register // node - the GT_IND node // -void emitter::emitInsLoadInd(instruction ins, emitAttr attr, GenTree* node) +void emitter::emitInsLoadInd(instruction ins, emitAttr attr, regNumber dstReg, GenTree* node) { assert(node->OperIs(GT_IND)); @@ -2660,13 +2661,13 @@ void emitter::emitInsLoadInd(instruction ins, emitAttr attr, GenTree* node) if (addr->OperGet() == GT_CLS_VAR_ADDR) { - emitIns_R_C(ins, attr, mem->gtRegNum, addr->gtClsVar.gtClsVarHnd, 0); + emitIns_R_C(ins, attr, dstReg, addr->gtClsVar.gtClsVarHnd, 0); return; } else if (addr->OperGet() == GT_LCL_VAR_ADDR) { GenTreeLclVarCommon* varNode = addr->AsLclVarCommon(); - emitIns_R_S(ins, attr, mem->gtRegNum, varNode->GetLclNum(), 0); + emitIns_R_S(ins, attr, dstReg, varNode->GetLclNum(), 0); codeGen->genUpdateLife(varNode); return; } @@ -2676,7 +2677,7 @@ void emitter::emitInsLoadInd(instruction ins, emitAttr attr, GenTree* node) size_t offset = mem->Offset(); id = emitNewInstrAmd(attr, offset); id->idIns(ins); - id->idReg1(mem->gtRegNum); + id->idReg1(dstReg); emitHandleMemOp(mem, id, IF_RWR_ARD, ins); sz = emitInsSizeAM(id, insCodeRM(ins)); id->idCodeSize(sz); From 137613b1487127a9fe960ffa0a41c00137af578d Mon Sep 17 00:00:00 2001 From: Mike Danes Date: Wed, 19 Jul 2017 20:09:36 +0300 Subject: [PATCH 3/3] Cleanup emitInsLoadInd/emitInsStoreInd/emitInsStoreLcl --- src/jit/emit.h | 6 ++-- src/jit/emitxarch.cpp | 70 ++++++++++++++++++++----------------------- 2 files changed, 35 insertions(+), 41 deletions(-) diff --git a/src/jit/emit.h b/src/jit/emit.h index 1dc711f91505..a9dc076958ff 100644 --- a/src/jit/emit.h +++ b/src/jit/emit.h @@ -1718,9 +1718,9 @@ class emitter CORINFO_FIELD_HANDLE emitFltOrDblConst(GenTreeDblCon* tree, emitAttr attr = EA_UNKNOWN); regNumber emitInsBinary(instruction ins, emitAttr attr, GenTree* dst, GenTree* src); regNumber emitInsTernary(instruction ins, emitAttr attr, GenTree* dst, GenTree* src1, GenTree* src2); - void emitInsLoadInd(instruction ins, emitAttr attr, regNumber dstReg, GenTree* node); - void emitInsStoreInd(instruction ins, emitAttr attr, GenTree* node); - void emitInsStoreLcl(instruction ins, emitAttr attr, GenTree* node); + void emitInsLoadInd(instruction ins, emitAttr attr, regNumber dstReg, GenTreeIndir* mem); + void emitInsStoreInd(instruction ins, emitAttr attr, GenTreeStoreInd* mem); + void emitInsStoreLcl(instruction ins, emitAttr attr, GenTreeLclVarCommon* varNode); insFormat emitMapFmtForIns(insFormat fmt, instruction ins); insFormat emitMapFmtAtoM(insFormat fmt); void emitHandleMemOp(GenTreeIndir* indir, instrDesc* id, insFormat fmt, instruction ins); diff --git a/src/jit/emitxarch.cpp b/src/jit/emitxarch.cpp index 5b1320120205..2463e42ed1fb 100644 --- a/src/jit/emitxarch.cpp +++ b/src/jit/emitxarch.cpp @@ -2647,42 +2647,36 @@ void emitter::spillIntArgRegsToShadowSlots() // ins - the instruction to emit // attr - the instruction operand size // dstReg - the destination register -// node - the GT_IND node +// mem - the GT_IND node // -void emitter::emitInsLoadInd(instruction ins, emitAttr attr, regNumber dstReg, GenTree* node) +void emitter::emitInsLoadInd(instruction ins, emitAttr attr, regNumber dstReg, GenTreeIndir* mem) { - assert(node->OperIs(GT_IND)); + assert(mem->OperIs(GT_IND)); - UNATIVE_OFFSET sz; - instrDesc* id; - - GenTreeIndir* mem = node->AsIndir(); - GenTreePtr addr = mem->Addr(); + GenTree* addr = mem->Addr(); if (addr->OperGet() == GT_CLS_VAR_ADDR) { emitIns_R_C(ins, attr, dstReg, addr->gtClsVar.gtClsVarHnd, 0); return; } - else if (addr->OperGet() == GT_LCL_VAR_ADDR) + + if (addr->OperGet() == GT_LCL_VAR_ADDR) { GenTreeLclVarCommon* varNode = addr->AsLclVarCommon(); emitIns_R_S(ins, attr, dstReg, varNode->GetLclNum(), 0); codeGen->genUpdateLife(varNode); return; } - else - { - assert(addr->OperIsAddrMode() || (addr->IsCnsIntOrI() && addr->isContained()) || !addr->isContained()); - size_t offset = mem->Offset(); - id = emitNewInstrAmd(attr, offset); - id->idIns(ins); - id->idReg1(dstReg); - emitHandleMemOp(mem, id, IF_RWR_ARD, ins); - sz = emitInsSizeAM(id, insCodeRM(ins)); - id->idCodeSize(sz); - } + assert(addr->OperIsAddrMode() || (addr->IsCnsIntOrI() && addr->isContained()) || !addr->isContained()); + size_t offset = mem->Offset(); + instrDesc* id = emitNewInstrAmd(attr, offset); + id->idIns(ins); + id->idReg1(dstReg); + emitHandleMemOp(mem, id, IF_RWR_ARD, ins); + UNATIVE_OFFSET sz = emitInsSizeAM(id, insCodeRM(ins)); + id->idCodeSize(sz); dispIns(id); emitCurIGsize += sz; } @@ -2694,19 +2688,14 @@ void emitter::emitInsLoadInd(instruction ins, emitAttr attr, regNumber dstReg, G // Arguments: // ins - the instruction to emit // attr - the instruction operand size -// node - the GT_STOREIND node +// mem - the GT_STOREIND node // -void emitter::emitInsStoreInd(instruction ins, emitAttr attr, GenTree* node) +void emitter::emitInsStoreInd(instruction ins, emitAttr attr, GenTreeStoreInd* mem) { - assert(node->OperIs(GT_STOREIND)); - - UNATIVE_OFFSET sz; - instrDesc* id; + assert(mem->OperIs(GT_STOREIND)); - GenTreeStoreInd* mem = node->AsStoreInd(); - GenTreePtr addr = mem->Addr(); - size_t offset = mem->Offset(); - GenTree* data = mem->Data(); + GenTree* addr = mem->Addr(); + GenTree* data = mem->Data(); if (addr->OperGet() == GT_CLS_VAR_ADDR) { @@ -2721,7 +2710,8 @@ void emitter::emitInsStoreInd(instruction ins, emitAttr attr, GenTree* node) } return; } - else if (addr->OperGet() == GT_LCL_VAR_ADDR) + + if (addr->OperGet() == GT_LCL_VAR_ADDR) { GenTreeLclVarCommon* varNode = addr->AsLclVarCommon(); if (data->isContainedIntOrIImmed()) @@ -2736,7 +2726,12 @@ void emitter::emitInsStoreInd(instruction ins, emitAttr attr, GenTree* node) codeGen->genUpdateLife(varNode); return; } - else if (data->isContainedIntOrIImmed()) + + size_t offset = mem->Offset(); + UNATIVE_OFFSET sz; + instrDesc* id; + + if (data->isContainedIntOrIImmed()) { int icon = (int)data->AsIntConCommon()->IconValue(); id = emitNewInstrAmdCns(attr, offset, icon); @@ -2767,16 +2762,15 @@ void emitter::emitInsStoreInd(instruction ins, emitAttr attr, GenTree* node) // Arguments: // ins - the instruction to emit // attr - the instruction operand size -// node - the GT_STORE_LCL_VAR node +// varNode - the GT_STORE_LCL_VAR node // -void emitter::emitInsStoreLcl(instruction ins, emitAttr attr, GenTree* node) +void emitter::emitInsStoreLcl(instruction ins, emitAttr attr, GenTreeLclVarCommon* varNode) { - assert(node->OperIs(GT_STORE_LCL_VAR)); + assert(varNode->OperIs(GT_STORE_LCL_VAR)); + assert(varNode->gtRegNum == REG_NA); // stack store - GenTreeLclVarCommon* varNode = node->AsLclVarCommon(); - GenTree* data = varNode->gtOp.gtOp1; + GenTree* data = varNode->gtGetOp1(); codeGen->inst_set_SV_var(varNode); - assert(varNode->gtRegNum == REG_NA); // stack store if (data->isContainedIntOrIImmed()) {