From: Bruce Forstall Date: Tue, 2 May 2017 00:49:21 +0000 (-0700) Subject: Refactor GT_STOREIND X-Git-Tag: submit/tizen/20210909.063632~11030^2~7048^2~7 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=459b4f42a702d7f0c6a3853f7e9df850ca356372;p=platform%2Fupstream%2Fdotnet%2Fruntime.git Refactor GT_STOREIND Commit migrated from https://github.com/dotnet/coreclr/commit/ab0582bd7c6666e7889f062a9584d7ecf788a883 --- diff --git a/src/coreclr/src/jit/codegenarm.cpp b/src/coreclr/src/jit/codegenarm.cpp index a96e5de..019641e 100644 --- a/src/coreclr/src/jit/codegenarm.cpp +++ b/src/coreclr/src/jit/codegenarm.cpp @@ -549,10 +549,8 @@ void CodeGen::genCodeForTreeNode(GenTreePtr treeNode) break; case GT_INTRINSIC: - { genIntrinsic(treeNode); - } - break; + break; case GT_EQ: case GT_NE: @@ -670,72 +668,8 @@ void CodeGen::genCodeForTreeNode(GenTreePtr treeNode) break; case GT_STOREIND: - { - GenTreeStoreInd* storeInd = treeNode->AsStoreInd(); - GenTree* data = storeInd->Data(); - GenTree* addr = storeInd->Addr(); - var_types targetType = storeInd->TypeGet(); - - assert(!varTypeIsFloating(targetType) || (targetType == data->TypeGet())); - - GCInfo::WriteBarrierForm writeBarrierForm = gcInfo.gcIsWriteBarrierCandidate(treeNode, data); - if (writeBarrierForm != GCInfo::WBF_NoBarrier) - { - // data and addr must be in registers. - // Consume both registers so that any copies of interfering - // registers are taken care of. - genConsumeOperands(storeInd->AsOp()); - -#if NOGC_WRITE_BARRIERS - NYI_ARM("NOGC_WRITE_BARRIERS"); -#else - // At this point, we should not have any interference. - // That is, 'data' must not be in REG_ARG_0, - // as that is where 'addr' must go. - noway_assert(data->gtRegNum != REG_ARG_0); - - // addr goes in REG_ARG_0 - if (addr->gtRegNum != REG_ARG_0) - { - inst_RV_RV(INS_mov, REG_ARG_0, addr->gtRegNum, addr->TypeGet()); - } - - // data goes in REG_ARG_1 - if (data->gtRegNum != REG_ARG_1) - { - inst_RV_RV(INS_mov, REG_ARG_1, data->gtRegNum, data->TypeGet()); - } -#endif // NOGC_WRITE_BARRIERS - - genGCWriteBarrier(storeInd, writeBarrierForm); - } - else // A normal store, not a WriteBarrier store - { - bool reverseOps = ((storeInd->gtFlags & GTF_REVERSE_OPS) != 0); - bool dataIsUnary = false; - - // We must consume the operands in the proper execution order, - // so that liveness is updated appropriately. - if (!reverseOps) - { - genConsumeAddress(addr); - } - - if (!data->isContained()) - { - genConsumeRegs(data); - } - - if (reverseOps) - { - genConsumeAddress(addr); - } - - emit->emitInsLoadStoreOp(ins_Store(targetType), emitTypeSize(storeInd), data->gtRegNum, - treeNode->AsIndir()); - } - } - break; + genCodeForStoreInd(treeNode->AsStoreInd()); + break; case GT_COPY: // This is handled at the time we call genConsumeReg() on the GT_COPY @@ -1643,6 +1577,78 @@ void CodeGen::genLeaInstruction(GenTreeAddrMode* lea) } //------------------------------------------------------------------------ +// genCodeForStoreInd: Produce code for a GT_STOREIND node. +// +// Arguments: +// tree - the GT_STOREIND node +// +void CodeGen::genCodeForStoreInd(GenTreeStoreInd* tree) +{ + GenTree* data = tree->Data(); + GenTree* addr = tree->Addr(); + var_types targetType = tree->TypeGet(); + emitter* emit = getEmitter(); + + assert(!varTypeIsFloating(targetType) || (targetType == data->TypeGet())); + + GCInfo::WriteBarrierForm writeBarrierForm = gcInfo.gcIsWriteBarrierCandidate(tree, data); + if (writeBarrierForm != GCInfo::WBF_NoBarrier) + { + // data and addr must be in registers. + // Consume both registers so that any copies of interfering + // registers are taken care of. + genConsumeOperands(tree); + +#if NOGC_WRITE_BARRIERS + NYI_ARM("NOGC_WRITE_BARRIERS"); +#else + // At this point, we should not have any interference. + // That is, 'data' must not be in REG_ARG_0, + // as that is where 'addr' must go. + noway_assert(data->gtRegNum != REG_ARG_0); + + // addr goes in REG_ARG_0 + if (addr->gtRegNum != REG_ARG_0) + { + inst_RV_RV(INS_mov, REG_ARG_0, addr->gtRegNum, addr->TypeGet()); + } + + // data goes in REG_ARG_1 + if (data->gtRegNum != REG_ARG_1) + { + inst_RV_RV(INS_mov, REG_ARG_1, data->gtRegNum, data->TypeGet()); + } +#endif // NOGC_WRITE_BARRIERS + + genGCWriteBarrier(tree, writeBarrierForm); + } + else // A normal store, not a WriteBarrier store + { + bool reverseOps = ((tree->gtFlags & GTF_REVERSE_OPS) != 0); + bool dataIsUnary = false; + + // We must consume the operands in the proper execution order, + // so that liveness is updated appropriately. + if (!reverseOps) + { + genConsumeAddress(addr); + } + + if (!data->isContained()) + { + genConsumeRegs(data); + } + + if (reverseOps) + { + genConsumeAddress(addr); + } + + emit->emitInsLoadStoreOp(ins_Store(targetType), emitTypeSize(tree), data->gtRegNum, tree); + } +} + +//------------------------------------------------------------------------ // genCompareLong: Generate code for comparing two longs when the result of the compare // is manifested in a register. // diff --git a/src/coreclr/src/jit/codegenarm64.cpp b/src/coreclr/src/jit/codegenarm64.cpp index 96598bb..8deeff3 100644 --- a/src/coreclr/src/jit/codegenarm64.cpp +++ b/src/coreclr/src/jit/codegenarm64.cpp @@ -2460,93 +2460,8 @@ void CodeGen::genCodeForTreeNode(GenTreePtr treeNode) break; case GT_STOREIND: - { - GenTree* data = treeNode->gtOp.gtOp2; - GenTree* addr = treeNode->gtOp.gtOp1; - GCInfo::WriteBarrierForm writeBarrierForm = gcInfo.gcIsWriteBarrierCandidate(treeNode, data); - if (writeBarrierForm != GCInfo::WBF_NoBarrier) - { - // data and addr must be in registers. - // Consume both registers so that any copies of interfering - // registers are taken care of. - genConsumeOperands(treeNode->AsOp()); - -#if NOGC_WRITE_BARRIERS - // At this point, we should not have any interference. - // That is, 'data' must not be in REG_WRITE_BARRIER_DST_BYREF, - // as that is where 'addr' must go. - noway_assert(data->gtRegNum != REG_WRITE_BARRIER_DST_BYREF); - - // 'addr' goes into x14 (REG_WRITE_BARRIER_DST_BYREF) - if (addr->gtRegNum != REG_WRITE_BARRIER_DST_BYREF) - { - inst_RV_RV(INS_mov, REG_WRITE_BARRIER_DST_BYREF, addr->gtRegNum, addr->TypeGet()); - } - - // 'data' goes into x15 (REG_WRITE_BARRIER) - if (data->gtRegNum != REG_WRITE_BARRIER) - { - inst_RV_RV(INS_mov, REG_WRITE_BARRIER, data->gtRegNum, data->TypeGet()); - } -#else - // At this point, we should not have any interference. - // That is, 'data' must not be in REG_ARG_0, - // as that is where 'addr' must go. - noway_assert(data->gtRegNum != REG_ARG_0); - - // addr goes in REG_ARG_0 - if (addr->gtRegNum != REG_ARG_0) - { - inst_RV_RV(INS_mov, REG_ARG_0, addr->gtRegNum, addr->TypeGet()); - } - - // data goes in REG_ARG_1 - if (data->gtRegNum != REG_ARG_1) - { - inst_RV_RV(INS_mov, REG_ARG_1, data->gtRegNum, data->TypeGet()); - } -#endif // NOGC_WRITE_BARRIERS - - genGCWriteBarrier(treeNode, writeBarrierForm); - } - else // A normal store, not a WriteBarrier store - { - bool reverseOps = ((treeNode->gtFlags & GTF_REVERSE_OPS) != 0); - bool dataIsUnary = false; - GenTree* nonRMWsrc = nullptr; - // We must consume the operands in the proper execution order, - // so that liveness is updated appropriately. - if (!reverseOps) - { - genConsumeAddress(addr); - } - - if (!data->isContained()) - { - genConsumeRegs(data); - } - - if (reverseOps) - { - genConsumeAddress(addr); - } - - regNumber dataReg = REG_NA; - if (data->isContainedIntOrIImmed()) - { - assert(data->IsIntegralConst(0)); - dataReg = REG_ZR; - } - else // data is not contained, so evaluate it into a register - { - assert(!data->isContained()); - dataReg = data->gtRegNum; - } - - emit->emitInsLoadStoreOp(ins_Store(targetType), emitTypeSize(treeNode), dataReg, treeNode->AsIndir()); - } - } - break; + genCodeForStoreInd(treeNode->AsStoreInd()); + break; case GT_COPY: // This is handled at the time we call genConsumeReg() on the GT_COPY @@ -4103,6 +4018,104 @@ void CodeGen::genLeaInstruction(GenTreeAddrMode* lea) genProduceReg(lea); } +//------------------------------------------------------------------------ +// genCodeForStoreInd: Produce code for a GT_STOREIND node. +// +// Arguments: +// tree - the GT_STOREIND node +// +void CodeGen::genCodeForStoreInd(GenTreeStoreInd* tree) +{ + GenTree* data = tree->Data(); + GenTree* addr = tree->Addr(); + var_types targetType = tree->TypeGet(); + emitter* emit = getEmitter(); + + GCInfo::WriteBarrierForm writeBarrierForm = gcInfo.gcIsWriteBarrierCandidate(tree, data); + if (writeBarrierForm != GCInfo::WBF_NoBarrier) + { + // data and addr must be in registers. + // Consume both registers so that any copies of interfering + // registers are taken care of. + genConsumeOperands(tree); + +#if NOGC_WRITE_BARRIERS + // At this point, we should not have any interference. + // That is, 'data' must not be in REG_WRITE_BARRIER_DST_BYREF, + // as that is where 'addr' must go. + noway_assert(data->gtRegNum != REG_WRITE_BARRIER_DST_BYREF); + + // 'addr' goes into x14 (REG_WRITE_BARRIER_DST_BYREF) + if (addr->gtRegNum != REG_WRITE_BARRIER_DST_BYREF) + { + inst_RV_RV(INS_mov, REG_WRITE_BARRIER_DST_BYREF, addr->gtRegNum, addr->TypeGet()); + } + + // 'data' goes into x15 (REG_WRITE_BARRIER) + if (data->gtRegNum != REG_WRITE_BARRIER) + { + inst_RV_RV(INS_mov, REG_WRITE_BARRIER, data->gtRegNum, data->TypeGet()); + } +#else + // At this point, we should not have any interference. + // That is, 'data' must not be in REG_ARG_0, + // as that is where 'addr' must go. + noway_assert(data->gtRegNum != REG_ARG_0); + + // addr goes in REG_ARG_0 + if (addr->gtRegNum != REG_ARG_0) + { + inst_RV_RV(INS_mov, REG_ARG_0, addr->gtRegNum, addr->TypeGet()); + } + + // data goes in REG_ARG_1 + if (data->gtRegNum != REG_ARG_1) + { + inst_RV_RV(INS_mov, REG_ARG_1, data->gtRegNum, data->TypeGet()); + } +#endif // NOGC_WRITE_BARRIERS + + genGCWriteBarrier(tree, writeBarrierForm); + } + else // A normal store, not a WriteBarrier store + { + bool reverseOps = ((tree->gtFlags & GTF_REVERSE_OPS) != 0); + bool dataIsUnary = false; + GenTree* nonRMWsrc = nullptr; + // We must consume the operands in the proper execution order, + // so that liveness is updated appropriately. + if (!reverseOps) + { + genConsumeAddress(addr); + } + + if (!data->isContained()) + { + genConsumeRegs(data); + } + + if (reverseOps) + { + genConsumeAddress(addr); + } + + regNumber dataReg = REG_NA; + if (data->isContainedIntOrIImmed()) + { + assert(data->IsIntegralConst(0)); + dataReg = REG_ZR; + } + else // data is not contained, so evaluate it into a register + { + assert(!data->isContained()); + dataReg = data->gtRegNum; + } + + emit->emitInsLoadStoreOp(ins_Store(targetType), emitTypeSize(tree), dataReg, tree); + } +} + + //------------------------------------------------------------------------------------------- // genSetRegToCond: Set a register 'dstReg' to the appropriate one or zero value // corresponding to a binary Relational operator result. diff --git a/src/coreclr/src/jit/codegenlinear.h b/src/coreclr/src/jit/codegenlinear.h index 8e4c8e7..89322a9 100644 --- a/src/coreclr/src/jit/codegenlinear.h +++ b/src/coreclr/src/jit/codegenlinear.h @@ -174,6 +174,8 @@ void genCodeForStoreLclFld(GenTreeLclFld* tree); void genCodeForStoreLclVar(GenTreeLclVar* tree); +void genCodeForStoreInd(GenTreeStoreInd* tree); + void genCodeForCpObj(GenTreeObj* cpObjNode); void genCodeForCpBlk(GenTreeBlk* cpBlkNode);