From 8f8d061a6727bc6c69803760732fb067b5945e90 Mon Sep 17 00:00:00 2001 From: Wraith2 Date: Tue, 5 Apr 2022 21:33:48 +0100 Subject: [PATCH 1/5] initial implementation --- src/coreclr/jit/emit.cpp | 125 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 124 insertions(+), 1 deletion(-) diff --git a/src/coreclr/jit/emit.cpp b/src/coreclr/jit/emit.cpp index dd17b6febd6109..55a7b544fbcd65 100644 --- a/src/coreclr/jit/emit.cpp +++ b/src/coreclr/jit/emit.cpp @@ -4139,6 +4139,10 @@ void emitter::emitJumpDistBind() #endif // DEBUG int jmp_iteration = 1; +#ifdef TARGET_XARCH + int jmp_removal = 1; + bool jmpRemoved = false; +#endif /*****************************************************************************/ /* If we iterate to look for more jumps to shorten, we start again here. */ @@ -4165,6 +4169,108 @@ void emitter::emitJumpDistBind() adjIG = 0; minShortExtra = (UNATIVE_OFFSET)-1; + +#ifdef TARGET_XARCH + // try to remove unconditional jumps at the end of a group to the next group + + jmp = emitJumpList; + instrDescJmp* previousJmp = nullptr; + while (jmp) + { + // if the jump is unconditional then it is a candidate + if (jmp->idInsFmt() == IF_LABEL && emitIsUncondJump(jmp) && !jmp->idjKeepLong) + { + // target group is not bound yet so use the cookie to fetch it + insGroup* targetGroup = (insGroup*)emitCodeGetCookie(jmp->idAddr()->iiaBBlabel); + + // if the target group is the next instruction group + if (targetGroup != nullptr && jmp->idjIG->igNext == targetGroup) + { + insGroup* group = jmp->idjIG; + unsigned instructionCount = group->igInsCnt; + + if (instructionCount) + { + BYTE* dataPtr = group->igData; + instrDesc* instructionDescriptor = nullptr; + unsigned foundCount = 0; + + do + { + instructionDescriptor = (instrDesc*)dataPtr; + if (instructionDescriptor->idIns() == jmp->idIns()) + { + foundCount += 1; + } + dataPtr += emitSizeOfInsDsc(instructionDescriptor); + } while (--instructionCount && foundCount < 2); + + if (foundCount == 1 && instructionDescriptor != nullptr && + instructionDescriptor->idIns() == jmp->idIns()) + { + assert(jmp == instructionDescriptor); + + // the last instruction in the group is the only occurence of the jmp + // and it jumps to the next instruction group so we don't really need it + + if (EMITVERBOSE) + { + printf("Removing jump [%08X/%03u]\n", dspPtr(jmp), jmp->idDebugOnlyInfo()->idNum); + } + + UNATIVE_OFFSET sizeRemoved = instructionDescriptor->idCodeSize(); + + // set state needed at the end of the loop in ADJUST_GROUP + adjIG = sizeRemoved; + lstIG = group; + jmpRemoved = true; + + // unlink the jump + if (previousJmp != nullptr) + { + previousJmp->idjNext = jmp->idjNext; + } + else + { + assert(jmp == emitJumpList); + emitJumpList = jmp->idjNext; + } + jmp->idjNext = nullptr; + + // clear the instruction data +//#if DEBUG +// memset((BYTE*)instructionDescriptor, 0, instructionDescriptor->idCodeSize()); +//#endif + // remove the instruction from the group + group->igInsCnt -= 1; + group->igSize -= sizeRemoved; + emitTotalCodeSize -= sizeRemoved; + + // cleanup + instructionDescriptor = nullptr; + jmp = nullptr; + + // jump to adjusting the size + goto ADJUST_GROUP; + } + } + } + + } + + previousJmp = jmp; + if (jmp != nullptr) + { + jmp = jmp->idjNext; + } + } + + jmp = nullptr; + lstIG = nullptr; + adjLJ = 0; + adjIG = 0; +#endif + #if defined(TARGET_ARM) minMediumExtra = (UNATIVE_OFFSET)-1; #endif // TARGET_ARM @@ -4785,7 +4891,9 @@ void emitter::emitJumpDistBind() } // end for each jump /* Did we shorten any jumps? */ - +#ifdef TARGET_XARCH + ADJUST_GROUP: +#endif if (adjIG) { /* Adjust offsets of any remaining blocks */ @@ -4846,6 +4954,21 @@ void emitter::emitJumpDistBind() goto AGAIN; } +#ifdef TARGET_XARCH + if (jmpRemoved) + { + + jmp_removal++; +#ifdef DEBUG + if (EMITVERBOSE) + { + printf("Iterating branch removal. Iteration = %d\n", jmp_removal); + } +#endif + jmpRemoved = false; + goto AGAIN; + } +#endif } #ifdef DEBUG if (EMIT_INSTLIST_VERBOSE) From 80e08d0ca14b55bcf9110cf0dfce22c89e0bd34e Mon Sep 17 00:00:00 2001 From: Wraith2 Date: Sat, 16 Apr 2022 02:52:06 +0100 Subject: [PATCH 2/5] add live range group reference count patching --- src/coreclr/jit/codegen.h | 2 +- src/coreclr/jit/codegencommon.cpp | 71 +++++++++- src/coreclr/jit/emit.cpp | 210 ++++++++++++++++-------------- src/coreclr/jit/emit.h | 2 + 4 files changed, 187 insertions(+), 98 deletions(-) diff --git a/src/coreclr/jit/codegen.h b/src/coreclr/jit/codegen.h index eebe47377666b6..1b4b4789279d03 100644 --- a/src/coreclr/jit/codegen.h +++ b/src/coreclr/jit/codegen.h @@ -623,7 +623,7 @@ class CodeGen final : public CodeGenInterface } #endif // !FEATURE_EH_FUNCLETS - + void genUpdateLiveRangesForTruncatedIGs(); void genGeneratePrologsAndEpilogs(); #if defined(DEBUG) && defined(TARGET_ARM64) diff --git a/src/coreclr/jit/codegencommon.cpp b/src/coreclr/jit/codegencommon.cpp index 0eccb2abfc8e5e..f45d18657c5371 100644 --- a/src/coreclr/jit/codegencommon.cpp +++ b/src/coreclr/jit/codegencommon.cpp @@ -1969,6 +1969,8 @@ void CodeGen::genGenerateMachineCode() GetEmitter()->emitJumpDistBind(); + genUpdateLiveRangesForTruncatedIGs(); + #if FEATURE_LOOP_ALIGN /* Perform alignment adjustments */ @@ -1978,6 +1980,74 @@ void CodeGen::genGenerateMachineCode() /* The code is now complete and final; it should not change after this. */ } +void CodeGen::genUpdateLiveRangesForTruncatedIGs() +{ + bool updatedGroup = false; + emitter* emit = GetEmitter(); + + if (compiler->lvaCount > 0) + { + insGroup* ig = emit->emitIGlist; + while (ig != nullptr) + { + if (ig->igFlags & IGF_UPD_ICOUNT) + { + if (varLiveKeeper->getLiveRangesCount() > 0) + { + for (unsigned int varNum = 0; varNum < compiler->lvaCount; varNum++) + { + if (compiler->compMap2ILvarNum(varNum) == (unsigned int)ICorDebugInfo::UNKNOWN_ILNUM) + { + continue; + } + + for (int rangeIndex = 0; rangeIndex < 2; rangeIndex++) + { + VariableLiveKeeper::LiveRangeList* liveRanges; + if (rangeIndex == 0) + { + liveRanges = varLiveKeeper->getLiveRangesForVarForProlog(varNum); + } + else + { + liveRanges = varLiveKeeper->getLiveRangesForVarForBody(varNum); + } + + for (VariableLiveKeeper::VariableLiveRange& liveRange : *liveRanges) + { + if (liveRange.m_StartEmitLocation.GetIG()->igNum == ig->igNum && + liveRange.m_StartEmitLocation.GetInsNum() > ig->igInsCnt) + { + liveRange.m_StartEmitLocation.SetInsNum(ig->igInsCnt); + assert(liveRange.m_StartEmitLocation.GetInsNum() == ig->igInsCnt); + updatedGroup = true; + } + + if (liveRange.m_EndEmitLocation.GetIG()->igNum == ig->igNum && + liveRange.m_EndEmitLocation.GetInsNum() > ig->igInsCnt) + { + liveRange.m_EndEmitLocation.SetInsNum(ig->igInsCnt); + assert(liveRange.m_EndEmitLocation.GetInsNum() == ig->igInsCnt); + updatedGroup = true; + } + } + } + } + } + + ig->igFlags ^= IGF_UPD_ICOUNT; + } + + ig = ig->igNext; + } + } + + if (updatedGroup && verbose) + { + compiler->lvaTableDump(); + } +} + //---------------------------------------------------------------------- // genEmitMachineCode -- emit the actual machine instruction code // @@ -7174,7 +7244,6 @@ void CodeGen::genSetScopeInfoUsingVariableRanges() reportRange(curLoc, curStart, curEnd); } } - compiler->eeVarsCount = liveRangeIndex; } #endif // USING_VARIABLE_LIVE_RANGE diff --git a/src/coreclr/jit/emit.cpp b/src/coreclr/jit/emit.cpp index 55a7b544fbcd65..f477edb706b02f 100644 --- a/src/coreclr/jit/emit.cpp +++ b/src/coreclr/jit/emit.cpp @@ -29,7 +29,6 @@ void emitLocation::CaptureLocation(emitter* emit) { ig = emit->emitCurIG; codePos = emit->emitCurOffset(); - assert(Valid()); } @@ -50,6 +49,13 @@ int emitLocation::GetInsNum() const return emitGetInsNumFromCodePos(codePos); } +void emitLocation::SetInsNum(int insNum) +{ + assert((unsigned int)insNum == emitGetInsNumFromCodePos(insNum)); + codePos = emitGetInsNumFromCodePos(insNum) + (emitGetInsOfsFromCodePos(codePos) << 16); + assert(Valid()); +} + // Get the instruction offset in the current instruction group, which must be a funclet prolog group. // This is used to find an instruction offset used in unwind data. // TODO-AMD64-Bug?: We only support a single main function prolog group, but allow for multiple funclet prolog @@ -3613,6 +3619,10 @@ void emitter::emitDispIGflags(unsigned flags) { printf(", isz"); } + if (flags & IGF_UPD_ICOUNT) + { + printf(", ict"); + } if (flags & IGF_EXTEND) { printf(", extend"); @@ -4172,103 +4182,108 @@ void emitter::emitJumpDistBind() #ifdef TARGET_XARCH // try to remove unconditional jumps at the end of a group to the next group - - jmp = emitJumpList; - instrDescJmp* previousJmp = nullptr; - while (jmp) + { - // if the jump is unconditional then it is a candidate - if (jmp->idInsFmt() == IF_LABEL && emitIsUncondJump(jmp) && !jmp->idjKeepLong) + jmp = emitJumpList; + instrDescJmp* previousJmp = nullptr; + while (jmp) { - // target group is not bound yet so use the cookie to fetch it - insGroup* targetGroup = (insGroup*)emitCodeGetCookie(jmp->idAddr()->iiaBBlabel); - - // if the target group is the next instruction group - if (targetGroup != nullptr && jmp->idjIG->igNext == targetGroup) + // if the jump is unconditional then it is a candidate + if (jmp->idInsFmt() == IF_LABEL && emitIsUncondJump(jmp) && !jmp->idjKeepLong) { - insGroup* group = jmp->idjIG; - unsigned instructionCount = group->igInsCnt; + // target group is not bound yet so use the cookie to fetch it + insGroup* targetGroup = (insGroup*)emitCodeGetCookie(jmp->idAddr()->iiaBBlabel); - if (instructionCount) + // if the target group is the next instruction group + if (targetGroup != nullptr && jmp->idjIG->igNext == targetGroup && + (targetGroup->igFlags & (IGF_EPILOG | IGF_FUNCLET_PROLOG | IGF_FUNCLET_EPILOG)) == 0) { - BYTE* dataPtr = group->igData; - instrDesc* instructionDescriptor = nullptr; - unsigned foundCount = 0; + insGroup* group = jmp->idjIG; + unsigned instructionCount = group->igInsCnt; - do + if (instructionCount > 1) { - instructionDescriptor = (instrDesc*)dataPtr; - if (instructionDescriptor->idIns() == jmp->idIns()) - { - foundCount += 1; - } - dataPtr += emitSizeOfInsDsc(instructionDescriptor); - } while (--instructionCount && foundCount < 2); - - if (foundCount == 1 && instructionDescriptor != nullptr && - instructionDescriptor->idIns() == jmp->idIns()) - { - assert(jmp == instructionDescriptor); - - // the last instruction in the group is the only occurence of the jmp - // and it jumps to the next instruction group so we don't really need it - - if (EMITVERBOSE) - { - printf("Removing jump [%08X/%03u]\n", dspPtr(jmp), jmp->idDebugOnlyInfo()->idNum); - } - - UNATIVE_OFFSET sizeRemoved = instructionDescriptor->idCodeSize(); - - // set state needed at the end of the loop in ADJUST_GROUP - adjIG = sizeRemoved; - lstIG = group; - jmpRemoved = true; + BYTE* dataPtr = group->igData; + instrDesc* instructionDescriptor = nullptr; + unsigned foundCount = 0; - // unlink the jump - if (previousJmp != nullptr) + do { - previousJmp->idjNext = jmp->idjNext; - } - else + instructionDescriptor = (instrDesc*)dataPtr; + if (instructionDescriptor->idIns() == jmp->idIns()) + { + foundCount += 1; + } + dataPtr += emitSizeOfInsDsc(instructionDescriptor); + } while (--instructionCount && foundCount < 2); + + if (foundCount == 1 && instructionDescriptor != nullptr && + instructionDescriptor->idIns() == jmp->idIns()) { - assert(jmp == emitJumpList); - emitJumpList = jmp->idjNext; + assert(jmp == instructionDescriptor); + + // the last instruction in the group is the only occurence of the jmp + // and it jumps to the next instruction group so we don't really need it + + if (EMITVERBOSE) + { + printf("Removing jump [%08X/%03u] in %s\n", dspPtr(jmp), jmp->idDebugOnlyInfo()->idNum, + emitComp->impInlineRoot()->info.compFullName); + } + + UNATIVE_OFFSET sizeRemoved = instructionDescriptor->idCodeSize(); + + // set state needed at the end of the loop in ADJUST_GROUP + adjIG = sizeRemoved; + lstIG = group; + jmpRemoved = true; + + // unlink the jump + if (previousJmp != nullptr) + { + previousJmp->idjNext = jmp->idjNext; + } + else + { + assert(jmp == emitJumpList); + emitJumpList = jmp->idjNext; + } + jmp->idjNext = nullptr; + + // clear the instruction data + //#if DEBUG + // memset((BYTE*)instructionDescriptor, 0, + // instructionDescriptor->idCodeSize()); + //#endif + // remove the instruction from the group + group->igInsCnt -= 1; + group->igSize -= sizeRemoved; + group->igFlags |= (IGF_UPD_ISZ | IGF_UPD_ICOUNT); + emitTotalCodeSize -= sizeRemoved; + + // cleanup + instructionDescriptor = nullptr; + jmp = nullptr; + + // jump to adjusting the size + goto ADJUST_GROUP; } - jmp->idjNext = nullptr; - - // clear the instruction data -//#if DEBUG -// memset((BYTE*)instructionDescriptor, 0, instructionDescriptor->idCodeSize()); -//#endif - // remove the instruction from the group - group->igInsCnt -= 1; - group->igSize -= sizeRemoved; - emitTotalCodeSize -= sizeRemoved; - - // cleanup - instructionDescriptor = nullptr; - jmp = nullptr; - - // jump to adjusting the size - goto ADJUST_GROUP; } } } + previousJmp = jmp; + if (jmp != nullptr) + { + jmp = jmp->idjNext; + } } - previousJmp = jmp; - if (jmp != nullptr) - { - jmp = jmp->idjNext; - } + jmp = nullptr; + lstIG = nullptr; + adjLJ = 0; + adjIG = 0; } - - jmp = nullptr; - lstIG = nullptr; - adjLJ = 0; - adjIG = 0; #endif #if defined(TARGET_ARM) @@ -4890,10 +4905,11 @@ void emitter::emitJumpDistBind() } // end for each jump - /* Did we shorten any jumps? */ #ifdef TARGET_XARCH ADJUST_GROUP: #endif + + /* Did we shorten any jumps? */ if (adjIG) { /* Adjust offsets of any remaining blocks */ @@ -4937,6 +4953,22 @@ void emitter::emitJumpDistBind() #endif #endif +#ifdef TARGET_XARCH + if (jmpRemoved) + { + + jmp_removal++; +#ifdef DEBUG + if (EMITVERBOSE) + { + printf("Iterating branch removal. Iteration = %d\n", jmp_removal); + } +#endif + jmpRemoved = false; + goto AGAIN; + } +#endif + if ((minShortExtra <= adjIG) #if defined(TARGET_ARM) || (minMediumExtra <= adjIG) @@ -4954,21 +4986,7 @@ void emitter::emitJumpDistBind() goto AGAIN; } -#ifdef TARGET_XARCH - if (jmpRemoved) - { - - jmp_removal++; -#ifdef DEBUG - if (EMITVERBOSE) - { - printf("Iterating branch removal. Iteration = %d\n", jmp_removal); - } -#endif - jmpRemoved = false; - goto AGAIN; - } -#endif + } #ifdef DEBUG if (EMIT_INSTLIST_VERBOSE) diff --git a/src/coreclr/jit/emit.h b/src/coreclr/jit/emit.h index e06b9552f7e81d..8ec1a20f6c4926 100644 --- a/src/coreclr/jit/emit.h +++ b/src/coreclr/jit/emit.h @@ -160,6 +160,7 @@ class emitLocation } int GetInsNum() const; + void SetInsNum(int insNum); bool operator!=(const emitLocation& other) const { @@ -277,6 +278,7 @@ struct insGroup // and the emitter should continue to track GC info as if there was no new block. #define IGF_HAS_ALIGN 0x0400 // this group contains an alignment instruction(s) at the end to align either the next // IG, or, if this IG contains with an unconditional branch, some subsequent IG. +#define IGF_UPD_ICOUNT 0x0800 // instruction was removed from the marked group and the live range end will not match this ig instruction count // Mask of IGF_* flags that should be propagated to new blocks when they are created. // This allows prologs and epilogs to be any number of IGs, but still be From 81bbbc03f88b74a994c45105110cf8d8edeba982 Mon Sep 17 00:00:00 2001 From: Wraith2 Date: Sat, 16 Apr 2022 22:20:21 +0100 Subject: [PATCH 3/5] fix live range caluclations cleanup and add dump comments --- src/coreclr/jit/codegencommon.cpp | 67 ++++++++++++++++++++++++++---- src/coreclr/jit/codegeninterface.h | 1 + src/coreclr/jit/emit.cpp | 40 +++++++++--------- 3 files changed, 80 insertions(+), 28 deletions(-) diff --git a/src/coreclr/jit/codegencommon.cpp b/src/coreclr/jit/codegencommon.cpp index f45d18657c5371..ab4e27f23a26bb 100644 --- a/src/coreclr/jit/codegencommon.cpp +++ b/src/coreclr/jit/codegencommon.cpp @@ -1982,19 +1982,30 @@ void CodeGen::genGenerateMachineCode() void CodeGen::genUpdateLiveRangesForTruncatedIGs() { - bool updatedGroup = false; - emitter* emit = GetEmitter(); +#ifdef DEBUG + if (verbose) + { + printf("*************** In genUpdateLiveRangesForTruncatedIGs()\n"); + } +#endif + bool updatedGroup = false; if (compiler->lvaCount > 0) { - insGroup* ig = emit->emitIGlist; + insGroup* ig = GetEmitter()->emitIGlist; while (ig != nullptr) { if (ig->igFlags & IGF_UPD_ICOUNT) { - if (varLiveKeeper->getLiveRangesCount() > 0) + + unsigned int liveVarCount = varLiveKeeper->getVarCount(); + if (liveVarCount > 0) { - for (unsigned int varNum = 0; varNum < compiler->lvaCount; varNum++) + if (compiler->verbose) + { + JITDUMP("IG%02u is marked with IGF_UPD_ICOUNT and has %d live variables\n", ig->igNum, liveVarCount); + } + for (unsigned int varNum = 0; varNum < liveVarCount; varNum++) { if (compiler->compMap2ILvarNum(varNum) == (unsigned int)ICorDebugInfo::UNKNOWN_ILNUM) { @@ -2012,12 +2023,17 @@ void CodeGen::genUpdateLiveRangesForTruncatedIGs() { liveRanges = varLiveKeeper->getLiveRangesForVarForBody(varNum); } - + for (VariableLiveKeeper::VariableLiveRange& liveRange : *liveRanges) { if (liveRange.m_StartEmitLocation.GetIG()->igNum == ig->igNum && liveRange.m_StartEmitLocation.GetInsNum() > ig->igInsCnt) { + if (compiler->verbose) + { + JITDUMP("IG%02u varNum %d StartEmitLocation InsCnt changed from %d to %d\n", ig, + liveVarCount, liveRange.m_StartEmitLocation.GetInsNum(), ig->igInsCnt); + } liveRange.m_StartEmitLocation.SetInsNum(ig->igInsCnt); assert(liveRange.m_StartEmitLocation.GetInsNum() == ig->igInsCnt); updatedGroup = true; @@ -2027,6 +2043,11 @@ void CodeGen::genUpdateLiveRangesForTruncatedIGs() liveRange.m_EndEmitLocation.GetInsNum() > ig->igInsCnt) { liveRange.m_EndEmitLocation.SetInsNum(ig->igInsCnt); + if (compiler->verbose) + { + JITDUMP("IG%02u varNum %d EndEmitLocation InsCnt changed from %d to %d\n", ig, + liveVarCount, liveRange.m_StartEmitLocation.GetInsNum(), ig->igInsCnt); + } assert(liveRange.m_EndEmitLocation.GetInsNum() == ig->igInsCnt); updatedGroup = true; } @@ -2034,6 +2055,13 @@ void CodeGen::genUpdateLiveRangesForTruncatedIGs() } } } + else + { + if (compiler->verbose) + { + JITDUMP("IG%02u is marked with IGF_UPD_ICOUNT but has no live variables\n", ig); + } + } ig->igFlags ^= IGF_UPD_ICOUNT; } @@ -2044,6 +2072,7 @@ void CodeGen::genUpdateLiveRangesForTruncatedIGs() if (updatedGroup && verbose) { + printf("\nlvaTable after genUpdateLiveRangesForTruncatedIGs\n"); compiler->lvaTableDump(); } } @@ -9348,7 +9377,7 @@ CodeGenInterface::VariableLiveKeeper::LiveRangeList* CodeGenInterface::VariableL } //------------------------------------------------------------------------ -// getLiveRangesCount: Returns the count of variable locations reported for the tracked +// getLiveRangesCount: Returns the size of variable locations reported for the tracked // variables, which are arguments, special arguments, and local IL variables. // // Return Value: @@ -9380,6 +9409,30 @@ size_t CodeGenInterface::VariableLiveKeeper::getLiveRangesCount() const return liveRangesCount; } +//------------------------------------------------------------------------ +// getVarCount: Returns the count of variable locations reported for the tracked +// variables, which are arguments, special arguments, and local IL variables. +// +// Return Value: +// unsigned int - the count of variables +// +unsigned int CodeGenInterface::VariableLiveKeeper::getVarCount() const +{ + unsigned int liveRangesCount = 0; + + if (m_Compiler->opts.compDbgInfo) + { + for (unsigned int varNum = 0; varNum < m_LiveDscCount; varNum++) + { + if (m_Compiler->compMap2ILvarNum(varNum) != (unsigned int)ICorDebugInfo::UNKNOWN_ILNUM) + { + liveRangesCount += 1; + } + } + } + return liveRangesCount; +}; + //------------------------------------------------------------------------ // psiStartVariableLiveRange: Reports the given variable as being born. // diff --git a/src/coreclr/jit/codegeninterface.h b/src/coreclr/jit/codegeninterface.h index dbd53ffbad46f7..a8566e5f71ca6c 100644 --- a/src/coreclr/jit/codegeninterface.h +++ b/src/coreclr/jit/codegeninterface.h @@ -744,6 +744,7 @@ class CodeGenInterface LiveRangeList* getLiveRangesForVarForBody(unsigned int varNum) const; LiveRangeList* getLiveRangesForVarForProlog(unsigned int varNum) const; size_t getLiveRangesCount() const; + unsigned int getVarCount() const; // For parameters locations on prolog void psiStartVariableLiveRange(CodeGenInterface::siVarLoc varLocation, unsigned int varNum); diff --git a/src/coreclr/jit/emit.cpp b/src/coreclr/jit/emit.cpp index f477edb706b02f..7380a06c9b9c54 100644 --- a/src/coreclr/jit/emit.cpp +++ b/src/coreclr/jit/emit.cpp @@ -4195,40 +4195,36 @@ void emitter::emitJumpDistBind() insGroup* targetGroup = (insGroup*)emitCodeGetCookie(jmp->idAddr()->iiaBBlabel); // if the target group is the next instruction group - if (targetGroup != nullptr && jmp->idjIG->igNext == targetGroup && - (targetGroup->igFlags & (IGF_EPILOG | IGF_FUNCLET_PROLOG | IGF_FUNCLET_EPILOG)) == 0) + if (targetGroup != nullptr && jmp->idjIG->igNext == targetGroup) { insGroup* group = jmp->idjIG; unsigned instructionCount = group->igInsCnt; - if (instructionCount > 1) + if (instructionCount > 0) { BYTE* dataPtr = group->igData; instrDesc* instructionDescriptor = nullptr; - unsigned foundCount = 0; do { instructionDescriptor = (instrDesc*)dataPtr; - if (instructionDescriptor->idIns() == jmp->idIns()) - { - foundCount += 1; - } dataPtr += emitSizeOfInsDsc(instructionDescriptor); - } while (--instructionCount && foundCount < 2); + } while (--instructionCount); - if (foundCount == 1 && instructionDescriptor != nullptr && - instructionDescriptor->idIns() == jmp->idIns()) - { - assert(jmp == instructionDescriptor); + assert(instructionDescriptor != nullptr); + // instructionDescriptor is now the last instruction in the group - // the last instruction in the group is the only occurence of the jmp + if (instructionDescriptor->idIns() == jmp->idIns() && + jmp == instructionDescriptor) + { + // the last instruction in the group is the jmp we're looking for // and it jumps to the next instruction group so we don't really need it if (EMITVERBOSE) { - printf("Removing jump [%08X/%03u] in %s\n", dspPtr(jmp), jmp->idDebugOnlyInfo()->idNum, - emitComp->impInlineRoot()->info.compFullName); + printf("Removing unconditional jump [%08X/%03u] from the last instruction in IG%02u to the next IG IG%02u label %s\n", + dspPtr(jmp), jmp->idDebugOnlyInfo()->idNum, group->igNum, targetGroup->igNum, + emitLabelString(targetGroup)); } UNATIVE_OFFSET sizeRemoved = instructionDescriptor->idCodeSize(); @@ -4250,17 +4246,19 @@ void emitter::emitJumpDistBind() } jmp->idjNext = nullptr; +#if DEBUG // clear the instruction data - //#if DEBUG - // memset((BYTE*)instructionDescriptor, 0, - // instructionDescriptor->idCodeSize()); - //#endif + memset((BYTE*)instructionDescriptor, 0, instructionDescriptor->idCodeSize()); +#endif + // remove the instruction from the group group->igInsCnt -= 1; group->igSize -= sizeRemoved; - group->igFlags |= (IGF_UPD_ISZ | IGF_UPD_ICOUNT); emitTotalCodeSize -= sizeRemoved; + // flag the group as resized and recounted + group->igFlags |= (IGF_UPD_ISZ | IGF_UPD_ICOUNT); + // cleanup instructionDescriptor = nullptr; jmp = nullptr; From 87809aade0bb72fb61a6f5047c5180d98b61f735 Mon Sep 17 00:00:00 2001 From: Wraith2 Date: Sat, 16 Apr 2022 22:28:25 +0100 Subject: [PATCH 4/5] apply jit format --- src/coreclr/jit/codegencommon.cpp | 9 +++++---- src/coreclr/jit/codegeninterface.h | 2 +- src/coreclr/jit/emit.cpp | 22 ++++++++++------------ src/coreclr/jit/emit.h | 6 ++++-- 4 files changed, 20 insertions(+), 19 deletions(-) diff --git a/src/coreclr/jit/codegencommon.cpp b/src/coreclr/jit/codegencommon.cpp index ab4e27f23a26bb..cd5fc046928e2b 100644 --- a/src/coreclr/jit/codegencommon.cpp +++ b/src/coreclr/jit/codegencommon.cpp @@ -1989,7 +1989,7 @@ void CodeGen::genUpdateLiveRangesForTruncatedIGs() } #endif bool updatedGroup = false; - + if (compiler->lvaCount > 0) { insGroup* ig = GetEmitter()->emitIGlist; @@ -2003,7 +2003,8 @@ void CodeGen::genUpdateLiveRangesForTruncatedIGs() { if (compiler->verbose) { - JITDUMP("IG%02u is marked with IGF_UPD_ICOUNT and has %d live variables\n", ig->igNum, liveVarCount); + JITDUMP("IG%02u is marked with IGF_UPD_ICOUNT and has %d live variables\n", ig->igNum, + liveVarCount); } for (unsigned int varNum = 0; varNum < liveVarCount; varNum++) { @@ -2023,7 +2024,7 @@ void CodeGen::genUpdateLiveRangesForTruncatedIGs() { liveRanges = varLiveKeeper->getLiveRangesForVarForBody(varNum); } - + for (VariableLiveKeeper::VariableLiveRange& liveRange : *liveRanges) { if (liveRange.m_StartEmitLocation.GetIG()->igNum == ig->igNum && @@ -2065,7 +2066,7 @@ void CodeGen::genUpdateLiveRangesForTruncatedIGs() ig->igFlags ^= IGF_UPD_ICOUNT; } - + ig = ig->igNext; } } diff --git a/src/coreclr/jit/codegeninterface.h b/src/coreclr/jit/codegeninterface.h index a8566e5f71ca6c..a452549c7c9cef 100644 --- a/src/coreclr/jit/codegeninterface.h +++ b/src/coreclr/jit/codegeninterface.h @@ -743,7 +743,7 @@ class CodeGenInterface LiveRangeList* getLiveRangesForVarForBody(unsigned int varNum) const; LiveRangeList* getLiveRangesForVarForProlog(unsigned int varNum) const; - size_t getLiveRangesCount() const; + size_t getLiveRangesCount() const; unsigned int getVarCount() const; // For parameters locations on prolog diff --git a/src/coreclr/jit/emit.cpp b/src/coreclr/jit/emit.cpp index 7380a06c9b9c54..fdf4b3206fa2b2 100644 --- a/src/coreclr/jit/emit.cpp +++ b/src/coreclr/jit/emit.cpp @@ -4150,8 +4150,8 @@ void emitter::emitJumpDistBind() int jmp_iteration = 1; #ifdef TARGET_XARCH - int jmp_removal = 1; - bool jmpRemoved = false; + int jmp_removal = 1; + bool jmpRemoved = false; #endif /*****************************************************************************/ @@ -4179,7 +4179,6 @@ void emitter::emitJumpDistBind() adjIG = 0; minShortExtra = (UNATIVE_OFFSET)-1; - #ifdef TARGET_XARCH // try to remove unconditional jumps at the end of a group to the next group @@ -4214,21 +4213,21 @@ void emitter::emitJumpDistBind() assert(instructionDescriptor != nullptr); // instructionDescriptor is now the last instruction in the group - if (instructionDescriptor->idIns() == jmp->idIns() && - jmp == instructionDescriptor) + if (instructionDescriptor->idIns() == jmp->idIns() && jmp == instructionDescriptor) { // the last instruction in the group is the jmp we're looking for // and it jumps to the next instruction group so we don't really need it if (EMITVERBOSE) { - printf("Removing unconditional jump [%08X/%03u] from the last instruction in IG%02u to the next IG IG%02u label %s\n", + printf("Removing unconditional jump [%08X/%03u] from the last instruction in IG%02u to " + "the next IG IG%02u label %s\n", dspPtr(jmp), jmp->idDebugOnlyInfo()->idNum, group->igNum, targetGroup->igNum, emitLabelString(targetGroup)); } - + UNATIVE_OFFSET sizeRemoved = instructionDescriptor->idCodeSize(); - + // set state needed at the end of the loop in ADJUST_GROUP adjIG = sizeRemoved; lstIG = group; @@ -4258,7 +4257,7 @@ void emitter::emitJumpDistBind() // flag the group as resized and recounted group->igFlags |= (IGF_UPD_ISZ | IGF_UPD_ICOUNT); - + // cleanup instructionDescriptor = nullptr; jmp = nullptr; @@ -4904,7 +4903,7 @@ void emitter::emitJumpDistBind() } // end for each jump #ifdef TARGET_XARCH - ADJUST_GROUP: +ADJUST_GROUP: #endif /* Did we shorten any jumps? */ @@ -4954,7 +4953,7 @@ void emitter::emitJumpDistBind() #ifdef TARGET_XARCH if (jmpRemoved) { - + jmp_removal++; #ifdef DEBUG if (EMITVERBOSE) @@ -4984,7 +4983,6 @@ void emitter::emitJumpDistBind() goto AGAIN; } - } #ifdef DEBUG if (EMIT_INSTLIST_VERBOSE) diff --git a/src/coreclr/jit/emit.h b/src/coreclr/jit/emit.h index 8ec1a20f6c4926..7b0fb7230e797f 100644 --- a/src/coreclr/jit/emit.h +++ b/src/coreclr/jit/emit.h @@ -159,7 +159,7 @@ class emitLocation return ig; } - int GetInsNum() const; + int GetInsNum() const; void SetInsNum(int insNum); bool operator!=(const emitLocation& other) const @@ -278,7 +278,9 @@ struct insGroup // and the emitter should continue to track GC info as if there was no new block. #define IGF_HAS_ALIGN 0x0400 // this group contains an alignment instruction(s) at the end to align either the next // IG, or, if this IG contains with an unconditional branch, some subsequent IG. -#define IGF_UPD_ICOUNT 0x0800 // instruction was removed from the marked group and the live range end will not match this ig instruction count +#define IGF_UPD_ICOUNT \ + 0x0800 // instruction was removed from the marked group and the live range end will not match this ig instruction + // count // Mask of IGF_* flags that should be propagated to new blocks when they are created. // This allows prologs and epilogs to be any number of IGs, but still be From 108b72c586939ef15e8e872a04d187d1a05674ed Mon Sep 17 00:00:00 2001 From: Wraith2 Date: Sun, 17 Apr 2022 02:49:43 +0100 Subject: [PATCH 5/5] fixjit dump statements in release builds --- src/coreclr/jit/codegencommon.cpp | 11 ++++++++++- src/coreclr/jit/emit.cpp | 8 ++++---- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/coreclr/jit/codegencommon.cpp b/src/coreclr/jit/codegencommon.cpp index cd5fc046928e2b..c2cd239b2225b7 100644 --- a/src/coreclr/jit/codegencommon.cpp +++ b/src/coreclr/jit/codegencommon.cpp @@ -2001,11 +2001,13 @@ void CodeGen::genUpdateLiveRangesForTruncatedIGs() unsigned int liveVarCount = varLiveKeeper->getVarCount(); if (liveVarCount > 0) { +#ifdef DEBUG if (compiler->verbose) { JITDUMP("IG%02u is marked with IGF_UPD_ICOUNT and has %d live variables\n", ig->igNum, liveVarCount); } +#endif for (unsigned int varNum = 0; varNum < liveVarCount; varNum++) { if (compiler->compMap2ILvarNum(varNum) == (unsigned int)ICorDebugInfo::UNKNOWN_ILNUM) @@ -2030,11 +2032,13 @@ void CodeGen::genUpdateLiveRangesForTruncatedIGs() if (liveRange.m_StartEmitLocation.GetIG()->igNum == ig->igNum && liveRange.m_StartEmitLocation.GetInsNum() > ig->igInsCnt) { +#ifdef DEBUG if (compiler->verbose) { JITDUMP("IG%02u varNum %d StartEmitLocation InsCnt changed from %d to %d\n", ig, liveVarCount, liveRange.m_StartEmitLocation.GetInsNum(), ig->igInsCnt); } +#endif liveRange.m_StartEmitLocation.SetInsNum(ig->igInsCnt); assert(liveRange.m_StartEmitLocation.GetInsNum() == ig->igInsCnt); updatedGroup = true; @@ -2044,11 +2048,13 @@ void CodeGen::genUpdateLiveRangesForTruncatedIGs() liveRange.m_EndEmitLocation.GetInsNum() > ig->igInsCnt) { liveRange.m_EndEmitLocation.SetInsNum(ig->igInsCnt); +#ifdef DEBUG if (compiler->verbose) { JITDUMP("IG%02u varNum %d EndEmitLocation InsCnt changed from %d to %d\n", ig, liveVarCount, liveRange.m_StartEmitLocation.GetInsNum(), ig->igInsCnt); } +#endif assert(liveRange.m_EndEmitLocation.GetInsNum() == ig->igInsCnt); updatedGroup = true; } @@ -2058,10 +2064,12 @@ void CodeGen::genUpdateLiveRangesForTruncatedIGs() } else { +#ifdef DEBUG if (compiler->verbose) { JITDUMP("IG%02u is marked with IGF_UPD_ICOUNT but has no live variables\n", ig); } +#endif } ig->igFlags ^= IGF_UPD_ICOUNT; @@ -2070,12 +2078,13 @@ void CodeGen::genUpdateLiveRangesForTruncatedIGs() ig = ig->igNext; } } - +#ifdef DEBUG if (updatedGroup && verbose) { printf("\nlvaTable after genUpdateLiveRangesForTruncatedIGs\n"); compiler->lvaTableDump(); } +#endif } //---------------------------------------------------------------------- diff --git a/src/coreclr/jit/emit.cpp b/src/coreclr/jit/emit.cpp index fdf4b3206fa2b2..f87f7328556a17 100644 --- a/src/coreclr/jit/emit.cpp +++ b/src/coreclr/jit/emit.cpp @@ -4215,9 +4215,9 @@ void emitter::emitJumpDistBind() if (instructionDescriptor->idIns() == jmp->idIns() && jmp == instructionDescriptor) { - // the last instruction in the group is the jmp we're looking for - // and it jumps to the next instruction group so we don't really need it - +// the last instruction in the group is the jmp we're looking for +// and it jumps to the next instruction group so we don't really need it +#ifdef DEBUG if (EMITVERBOSE) { printf("Removing unconditional jump [%08X/%03u] from the last instruction in IG%02u to " @@ -4225,7 +4225,7 @@ void emitter::emitJumpDistBind() dspPtr(jmp), jmp->idDebugOnlyInfo()->idNum, group->igNum, targetGroup->igNum, emitLabelString(targetGroup)); } - +#endif UNATIVE_OFFSET sizeRemoved = instructionDescriptor->idCodeSize(); // set state needed at the end of the loop in ADJUST_GROUP