Skip to content

Commit a9506e7

Browse files
Fix jumps encoded as "+/- <instr count>"
By deleting them.
1 parent 12e3774 commit a9506e7

15 files changed

Lines changed: 182 additions & 342 deletions

src/coreclr/jit/codegenarm.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2659,9 +2659,11 @@ void CodeGen::genZeroInitFrameUsingBlockInit(int untrLclHi, int untrLclLo, regNu
26592659
}
26602660
else
26612661
{
2662+
BasicBlock* loopHead = genCreateTempLabel();
2663+
genDefineInlineTempLabel(loopHead);
26622664
GetEmitter()->emitIns_R_I(INS_stm, EA_PTRSIZE, rAddr, stmImm); // zero stack slots
26632665
GetEmitter()->emitIns_R_I(INS_sub, EA_PTRSIZE, rCnt, 1, INS_FLAGS_SET);
2664-
GetEmitter()->emitIns_J(INS_bhi, NULL, -3);
2666+
GetEmitter()->emitIns_ShortJ(INS_bhi, loopHead);
26652667
uCntBytes %= REGSIZE_BYTES * 2;
26662668
}
26672669

src/coreclr/jit/codegenarm64.cpp

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1957,10 +1957,12 @@ void CodeGen::genZeroInitFrameUsingBlockInit(int untrLclHi, int untrLclLo, regNu
19571957
GetEmitter()->emitIns_R_R_I_I(INS_bfm, EA_PTRSIZE, addrReg, REG_ZR, 0, 5);
19581958
// addrReg points at the beginning of a cache line.
19591959

1960+
BasicBlock* loopHead = genCreateTempLabel();
1961+
genDefineInlineTempLabel(loopHead);
19601962
GetEmitter()->emitIns_R(INS_dczva, EA_PTRSIZE, addrReg);
19611963
GetEmitter()->emitIns_R_R_I(INS_add, EA_PTRSIZE, addrReg, addrReg, 64);
19621964
GetEmitter()->emitIns_R_R(INS_cmp, EA_PTRSIZE, addrReg, endAddrReg);
1963-
GetEmitter()->emitIns_J(INS_blo, NULL, -4);
1965+
GetEmitter()->emitIns_ShortJ(INS_blo, loopHead);
19641966

19651967
addrReg = endAddrReg;
19661968
bytesToWrite = 64;
@@ -1979,12 +1981,14 @@ void CodeGen::genZeroInitFrameUsingBlockInit(int untrLclHi, int untrLclLo, regNu
19791981

19801982
instGen_Set_Reg_To_Imm(EA_PTRSIZE, countReg, bytesToWrite - 64);
19811983

1984+
BasicBlock* loopHead = genCreateTempLabel();
1985+
genDefineInlineTempLabel(loopHead);
19821986
GetEmitter()->emitIns_R_R_R_I(INS_stp, EA_16BYTE, zeroSimdReg, zeroSimdReg, addrReg, 32);
19831987
GetEmitter()->emitIns_R_R_R_I(INS_stp, EA_16BYTE, zeroSimdReg, zeroSimdReg, addrReg, 64,
19841988
INS_OPTS_PRE_INDEX);
19851989

19861990
GetEmitter()->emitIns_R_R_I(INS_subs, EA_PTRSIZE, countReg, countReg, 64);
1987-
GetEmitter()->emitIns_J(INS_bge, NULL, -4);
1991+
GetEmitter()->emitIns_ShortJ(INS_bge, loopHead);
19881992

19891993
bytesToWrite %= 64;
19901994
}
@@ -5914,13 +5918,12 @@ void CodeGen::genAllocLclFrame(unsigned frameSize, regNumber initReg, bool* pIni
59145918
instGen_Set_Reg_To_Imm(EA_PTRSIZE, rOffset, -(ssize_t)pageSize);
59155919
instGen_Set_Reg_To_Imm(EA_PTRSIZE, rLimit, -(ssize_t)frameSize);
59165920

5917-
// There's a "virtual" label here. But we can't create a label in the prolog, so we use the magic
5918-
// `emitIns_J` with a negative `instrCount` to branch back a specific number of instructions.
5919-
5921+
BasicBlock* loopHead = genCreateTempLabel();
5922+
genDefineInlineTempLabel(loopHead);
59205923
GetEmitter()->emitIns_R_R_R(INS_ldr, EA_4BYTE, REG_ZR, REG_SPBASE, rOffset);
59215924
GetEmitter()->emitIns_R_R_I(INS_sub, EA_PTRSIZE, rOffset, rOffset, pageSize);
59225925
GetEmitter()->emitIns_R_R(INS_cmp, EA_PTRSIZE, rLimit, rOffset); // If equal, we need to probe again
5923-
GetEmitter()->emitIns_J(INS_bls, NULL, -4);
5926+
GetEmitter()->emitIns_ShortJ(INS_bls, loopHead);
59245927

59255928
*pInitRegZeroed = false; // The initReg does not contain zero
59265929

src/coreclr/jit/codegencommon.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6026,6 +6026,7 @@ void CodeGen::genGeneratePrologsAndEpilogs()
60266026

60276027
GetEmitter()->emitStartPrologEpilogGeneration();
60286028

6029+
m_compiler->compCurBB = m_compiler->fgFirstBB; // Set the current BB for label creation.
60296030
gcInfo.gcResetForBB();
60306031
genFnProlog();
60316032

@@ -6053,6 +6054,8 @@ void CodeGen::genGeneratePrologsAndEpilogs()
60536054

60546055
GetEmitter()->emitFinishPrologEpilogGeneration();
60556056

6057+
m_compiler->compCurBB = nullptr;
6058+
60566059
#ifdef DEBUG
60576060
if (verbose)
60586061
{

src/coreclr/jit/codegenriscv64.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -822,14 +822,15 @@ void CodeGen::genZeroInitFrameUsingBlockInit(int untrLclHi, int untrLclLo, regNu
822822
GetEmitter()->emitIns_R_R_R(INS_add, EA_PTRSIZE, rEndAddr, rEndAddr, rAddr);
823823
}
824824

825-
// TODO-RISCV64-RVC: Remove hardcoded branch offset here
825+
BasicBlock* loopHead = genCreateTempLabel();
826+
genDefineInlineTempLabel(loopHead);
826827
GetEmitter()->emitIns_R_R_I(INS_sd, EA_PTRSIZE, REG_R0, rAddr, padding);
827828
GetEmitter()->emitIns_R_R_I(INS_sd, EA_PTRSIZE, REG_R0, rAddr, padding + REGSIZE_BYTES);
828829
GetEmitter()->emitIns_R_R_I(INS_sd, EA_PTRSIZE, REG_R0, rAddr, padding + 2 * REGSIZE_BYTES);
829830
GetEmitter()->emitIns_R_R_I(INS_sd, EA_PTRSIZE, REG_R0, rAddr, padding + 3 * REGSIZE_BYTES);
830831

831832
GetEmitter()->emitIns_R_R_I(INS_addi, EA_PTRSIZE, rAddr, rAddr, 4 * REGSIZE_BYTES);
832-
GetEmitter()->emitIns_R_R_I(INS_bltu, EA_PTRSIZE, rAddr, rEndAddr, -5 << 2);
833+
GetEmitter()->emitIns_J_cond_la(INS_bltu, loopHead, rAddr, rEndAddr);
833834

834835
uLclBytes -= uLoopBytes;
835836
uAddrCurr = 0;

src/coreclr/jit/codegenxarch.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1685,7 +1685,7 @@ void CodeGen::inst_JMP(emitJumpKind jmp, BasicBlock* tgtBlock, bool isRemovableJ
16851685
#endif
16861686
#endif // !FEATURE_FIXED_OUT_ARGS
16871687

1688-
GetEmitter()->emitIns_J(emitter::emitJumpKindToIns(jmp), tgtBlock, 0, isRemovableJmpCandidate);
1688+
GetEmitter()->emitIns_J(emitter::emitJumpKindToIns(jmp), tgtBlock, isRemovableJmpCandidate);
16891689
}
16901690

16911691
//------------------------------------------------------------------------
@@ -11301,7 +11301,10 @@ void CodeGen::genZeroInitFrameUsingBlockInit(int untrLclHi, int untrLclLo, regNu
1130111301

1130211302
// Set loop counter
1130311303
emit->emitIns_R_I(INS_mov, EA_PTRSIZE, initReg, -(ssize_t)blkSize);
11304+
1130411305
// Loop start
11306+
BasicBlock* loopHead = genCreateTempLabel();
11307+
genDefineInlineTempLabel(loopHead);
1130511308
emit->emitIns_ARX_R(simdMov, EA_ATTR(XMM_REGSIZE_BYTES), zeroSIMDReg, frameReg, initReg, 1, alignedLclHi);
1130611309
emit->emitIns_ARX_R(simdMov, EA_ATTR(XMM_REGSIZE_BYTES), zeroSIMDReg, frameReg, initReg, 1,
1130711310
alignedLclHi + XMM_REGSIZE_BYTES);
@@ -11310,7 +11313,7 @@ void CodeGen::genZeroInitFrameUsingBlockInit(int untrLclHi, int untrLclLo, regNu
1131011313

1131111314
emit->emitIns_R_I(INS_add, EA_PTRSIZE, initReg, XMM_REGSIZE_BYTES * 3);
1131211315
// Loop until counter is 0
11313-
emit->emitIns_J(INS_jne, nullptr, -5);
11316+
emit->emitIns_ShortJ(INS_jne, loopHead);
1131411317

1131511318
// initReg will be zero at end of the loop
1131611319
*pInitRegZeroed = true;

src/coreclr/jit/emit.cpp

Lines changed: 91 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1238,16 +1238,14 @@ insGroup* emitter::emitSavIG(bool emitAdd)
12381238

12391239
assert(last == nullptr || last->idjOffs > nj->idjOffs);
12401240

1241-
if (ig->igFlags & IGF_FUNCLET_PROLOG)
1241+
if ((ig->igFlags & IGF_OUT_OF_ORDER_MASK) != 0)
12421242
{
1243-
// Our funclet prologs have short jumps, if the prolog would ever have
1244-
// long jumps, then we'd have to insert the list in sorted order than
1245-
// just append to the emitJumpList.
1246-
noway_assert(nj->idjShort);
1247-
if (nj->idjShort)
1248-
{
1249-
continue;
1250-
}
1243+
// Our out of order groups have short jumps. If we ever need the shortening capability
1244+
// for these jumps, we'll need to insert them at the appropriate place in emitJumpList.
1245+
nj->idjNext = emitFixedSizeJumpList;
1246+
emitFixedSizeJumpList = nj;
1247+
assert(nj->idjShort);
1248+
continue;
12511249
}
12521250

12531251
// Append the new jump to the list
@@ -1264,8 +1262,7 @@ insGroup* emitter::emitSavIG(bool emitAdd)
12641262
if (last != nullptr)
12651263
{
12661264
// Append the jump(s) from this IG to the global list
1267-
bool prologJump = emitIGisInProlog(ig);
1268-
if ((emitJumpList == nullptr) || prologJump)
1265+
if (emitJumpList == nullptr)
12691266
{
12701267
last->idjNext = emitJumpList;
12711268
emitJumpList = list;
@@ -1276,10 +1273,7 @@ insGroup* emitter::emitSavIG(bool emitAdd)
12761273
emitJumpLast->idjNext = list;
12771274
}
12781275

1279-
if (!prologJump || (emitJumpLast == nullptr))
1280-
{
1281-
emitJumpLast = last;
1282-
}
1276+
emitJumpLast = last;
12831277
}
12841278
}
12851279

@@ -1372,6 +1366,7 @@ void emitter::emitBegFN(bool hasFramePtr
13721366
/* We don't have any jumps */
13731367

13741368
emitJumpList = emitJumpLast = nullptr;
1369+
emitFixedSizeJumpList = nullptr;
13751370
emitCurIGjmpList = nullptr;
13761371

13771372
emitFwdJumps = false;
@@ -2416,14 +2411,15 @@ void emitter::emitBegPrologEpilog(insGroup* igPh)
24162411
emitThisGCrefRegs = emitInitGCrefRegs = igPh->igPhData->igPhInitGCrefRegs;
24172412
emitThisByrefRegs = emitInitByrefRegs = igPh->igPhData->igPhInitByrefRegs;
24182413

2414+
// Set the current BB for label creation.
2415+
m_compiler->compCurBB = igPh->igPhData->igPhBB;
2416+
24192417
igPh->igPhData = nullptr;
24202418

24212419
/* Create a non-placeholder group pointer that we'll now use */
2422-
24232420
insGroup* ig = igPh;
24242421

24252422
/* Set the current function using the function index we stored */
2426-
24272423
m_compiler->funSetCurrentFunc(ig->igFuncIdx);
24282424

24292425
/* Set the new IG as the place to generate code */
@@ -3602,6 +3598,26 @@ void emitter::emitSetSecondRetRegGCType(instrDescCGCA* id, emitAttr secondRetSiz
36023598
#endif // MULTIREG_HAS_SECOND_GC_RET
36033599

36043600
#ifndef TARGET_WASM
3601+
//------------------------------------------------------------------------
3602+
// emitIns_ShortJ: Emit a 'forced' short jump.
3603+
//
3604+
// Jumps in prologs are hardcoded to be short since we don't shorten
3605+
// them in binding.
3606+
//
3607+
// Arguments:
3608+
// ins - The jump instruction
3609+
// dst - The destination label (must already be bound to an IG)
3610+
//
3611+
void emitter::emitIns_ShortJ(instruction ins, BasicBlock* dst)
3612+
{
3613+
assert((emitCurIG->igFlags & IGF_OUT_OF_ORDER_MASK) != 0);
3614+
3615+
// We currently have a limitation where all jumps in the prolog must be short.
3616+
// This is mostly because we the prolog can't change size in emission, as we
3617+
// currently hardcode offsets from it into the unwind info during IG building.
3618+
// We also don't insert the jumps into the jump list in layout order.
3619+
emitIns_J(ins, dst, /* keepShort */ true);
3620+
}
36053621

36063622
/*****************************************************************************
36073623
*
@@ -4903,6 +4919,15 @@ void emitter::emitJumpDistBind()
49034919
}
49044920
#endif
49054921

4922+
// For the fixed-size jumps, we only need to bind them.
4923+
for (instrDescJmp* jmp = emitFixedSizeJumpList; jmp != nullptr; jmp = jmp->idjNext)
4924+
{
4925+
if (!jmp->idIsBound())
4926+
{
4927+
emitBindJump(jmp);
4928+
}
4929+
}
4930+
49064931
instrDescJmp* jmp;
49074932

49084933
UNATIVE_OFFSET minShortExtra; // The smallest offset greater than that required for a jump to be converted
@@ -5220,40 +5245,7 @@ void emitter::emitJumpDistBind()
52205245
else
52215246
{
52225247
/* First time we've seen this label, convert its target */
5223-
5224-
#ifdef DEBUG
5225-
if (EMITVERBOSE)
5226-
{
5227-
printf("Binding: ");
5228-
emitDispIns(jmp, false, false, false);
5229-
printf("Binding L_M%03u_" FMT_BB, m_compiler->compMethodID, jmp->idAddr()->iiaBBlabel->bbNum);
5230-
}
5231-
#endif // DEBUG
5232-
5233-
tgtIG = (insGroup*)emitCodeGetCookie(jmp->idAddr()->iiaBBlabel);
5234-
5235-
#ifdef DEBUG
5236-
if (EMITVERBOSE)
5237-
{
5238-
if (tgtIG)
5239-
{
5240-
printf(" to %s\n", emitLabelString(tgtIG));
5241-
}
5242-
else
5243-
{
5244-
printf("-- ERROR, no emitter cookie for " FMT_BB "; it is probably missing BBF_HAS_LABEL.\n",
5245-
jmp->idAddr()->iiaBBlabel->bbNum);
5246-
}
5247-
}
5248-
#endif // DEBUG
5249-
5250-
assert(jmp->idAddr()->iiaBBlabel->HasFlag(BBF_HAS_LABEL));
5251-
assert(tgtIG);
5252-
5253-
/* Record the bound target */
5254-
5255-
jmp->idAddr()->iiaIGlabel = tgtIG;
5256-
jmp->idSetIsBound();
5248+
tgtIG = emitBindJump(jmp);
52575249
}
52585250

52595251
// We should not be jumping/branching across funclets/functions
@@ -5674,6 +5666,54 @@ void emitter::emitJumpDistBind()
56745666
emitCheckIGList();
56755667
#endif // DEBUG
56765668
}
5669+
5670+
//------------------------------------------------------------------------
5671+
// emitBindJump: 'Bind' a jump by assigning its target label field.
5672+
//
5673+
// Arguments:
5674+
// jmp - The jump instruction
5675+
//
5676+
// Return Value:
5677+
// The target IG "jmp" was bound to.
5678+
//
5679+
insGroup* emitter::emitBindJump(instrDescJmp* jmp)
5680+
{
5681+
assert(!jmp->idIsBound());
5682+
5683+
#ifdef DEBUG
5684+
if (EMITVERBOSE)
5685+
{
5686+
printf("Binding: ");
5687+
emitDispIns(jmp, false, false, false);
5688+
printf("Binding L_M%03u_" FMT_BB, m_compiler->compMethodID, jmp->idAddr()->iiaBBlabel->bbNum);
5689+
}
5690+
#endif // DEBUG
5691+
5692+
insGroup* tgtIG = (insGroup*)emitCodeGetCookie(jmp->idAddr()->iiaBBlabel);
5693+
5694+
#ifdef DEBUG
5695+
if (EMITVERBOSE)
5696+
{
5697+
if (tgtIG)
5698+
{
5699+
printf(" to %s\n", emitLabelString(tgtIG));
5700+
}
5701+
else
5702+
{
5703+
printf("-- ERROR, no emitter cookie for " FMT_BB "; it is probably missing BBF_HAS_LABEL.\n",
5704+
jmp->idAddr()->iiaBBlabel->bbNum);
5705+
}
5706+
}
5707+
#endif // DEBUG
5708+
5709+
assert(jmp->idAddr()->iiaBBlabel->HasFlag(BBF_HAS_LABEL));
5710+
assert(tgtIG != nullptr);
5711+
5712+
/* Record the bound target */
5713+
jmp->idAddr()->iiaIGlabel = tgtIG;
5714+
jmp->idSetIsBound();
5715+
return tgtIG;
5716+
}
56775717
#endif
56785718

56795719
#if FEATURE_LOOP_ALIGN
@@ -6604,13 +6644,6 @@ void emitter::emitCheckFuncletBranch(instrDesc* jmp, insGroup* jmpIG)
66046644
}
66056645
#endif
66066646

6607-
if (jmp->idAddr()->iiaHasInstrCount())
6608-
{
6609-
// Too hard to figure out funclets from just an instruction count
6610-
// You're on your own!
6611-
return;
6612-
}
6613-
66146647
#ifdef TARGET_ARM64
66156648
// No interest if it's not jmp.
66166649
if (emitIsLoadLabel(jmp) || emitIsLoadConstant(jmp))
@@ -7634,7 +7667,6 @@ unsigned emitter::emitEndCodeGen(Compiler* comp,
76347667
// Presumably we could also just call "emitOutputLJ(NULL, adr, jmp)", like for long jumps?
76357668
*(short int*)(adr + writeableOffset) -= (short)adj;
76367669
#elif defined(TARGET_ARM64)
7637-
assert(!jmp->idAddr()->iiaHasInstrCount());
76387670
emitOutputLJ(NULL, adr, jmp);
76397671
#elif defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64)
76407672
// For LoongArch64 and RiscV64 `emitFwdJumps` is always false.
@@ -7651,7 +7683,6 @@ unsigned emitter::emitEndCodeGen(Compiler* comp,
76517683
#if defined(TARGET_XARCH)
76527684
*(int*)(adr + writeableOffset) -= adj;
76537685
#elif defined(TARGET_ARMARCH)
7654-
assert(!jmp->idAddr()->iiaHasInstrCount());
76557686
emitOutputLJ(NULL, adr, jmp);
76567687
#elif defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64)
76577688
// For LoongArch64 and RiscV64 `emitFwdJumps` is always false.

0 commit comments

Comments
 (0)