Skip to content

Commit 309ff86

Browse files
Fix jumps encoded as "+/- <instr count>"
By deleting them.
1 parent fb25de8 commit 309ff86

File tree

15 files changed

+165
-333
lines changed

15 files changed

+165
-333
lines changed

src/coreclr/jit/codegenarm.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2627,9 +2627,11 @@ void CodeGen::genZeroInitFrameUsingBlockInit(int untrLclHi, int untrLclLo, regNu
26272627
}
26282628
else
26292629
{
2630+
BasicBlock* loopHead = genCreateTempLabel();
2631+
genDefineInlineTempLabel(loopHead);
26302632
GetEmitter()->emitIns_R_I(INS_stm, EA_PTRSIZE, rAddr, stmImm); // zero stack slots
26312633
GetEmitter()->emitIns_R_I(INS_sub, EA_PTRSIZE, rCnt, 1, INS_FLAGS_SET);
2632-
GetEmitter()->emitIns_J(INS_bhi, NULL, -3);
2634+
GetEmitter()->emitIns_ShortJ(INS_bhi, loopHead);
26332635
uCntBytes %= REGSIZE_BYTES * 2;
26342636
}
26352637

src/coreclr/jit/codegenarm64.cpp

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

1923+
BasicBlock* loopHead = genCreateTempLabel();
1924+
genDefineInlineTempLabel(loopHead);
19231925
GetEmitter()->emitIns_R(INS_dczva, EA_PTRSIZE, addrReg);
19241926
GetEmitter()->emitIns_R_R_I(INS_add, EA_PTRSIZE, addrReg, addrReg, 64);
19251927
GetEmitter()->emitIns_R_R(INS_cmp, EA_PTRSIZE, addrReg, endAddrReg);
1926-
GetEmitter()->emitIns_J(INS_blo, NULL, -4);
1928+
GetEmitter()->emitIns_ShortJ(INS_blo, loopHead);
19271929

19281930
addrReg = endAddrReg;
19291931
bytesToWrite = 64;
@@ -1942,12 +1944,14 @@ void CodeGen::genZeroInitFrameUsingBlockInit(int untrLclHi, int untrLclLo, regNu
19421944

19431945
instGen_Set_Reg_To_Imm(EA_PTRSIZE, countReg, bytesToWrite - 64);
19441946

1947+
BasicBlock* loopHead = genCreateTempLabel();
1948+
genDefineInlineTempLabel(loopHead);
19451949
GetEmitter()->emitIns_R_R_R_I(INS_stp, EA_16BYTE, zeroSimdReg, zeroSimdReg, addrReg, 32);
19461950
GetEmitter()->emitIns_R_R_R_I(INS_stp, EA_16BYTE, zeroSimdReg, zeroSimdReg, addrReg, 64,
19471951
INS_OPTS_PRE_INDEX);
19481952

19491953
GetEmitter()->emitIns_R_R_I(INS_subs, EA_PTRSIZE, countReg, countReg, 64);
1950-
GetEmitter()->emitIns_J(INS_bge, NULL, -4);
1954+
GetEmitter()->emitIns_ShortJ(INS_bge, loopHead);
19511955

19521956
bytesToWrite %= 64;
19531957
}
@@ -5760,13 +5764,12 @@ void CodeGen::genAllocLclFrame(unsigned frameSize, regNumber initReg, bool* pIni
57605764
instGen_Set_Reg_To_Imm(EA_PTRSIZE, rOffset, -(ssize_t)pageSize);
57615765
instGen_Set_Reg_To_Imm(EA_PTRSIZE, rLimit, -(ssize_t)frameSize);
57625766

5763-
// There's a "virtual" label here. But we can't create a label in the prolog, so we use the magic
5764-
// `emitIns_J` with a negative `instrCount` to branch back a specific number of instructions.
5765-
5767+
BasicBlock* loopHead = genCreateTempLabel();
5768+
genDefineInlineTempLabel(loopHead);
57665769
GetEmitter()->emitIns_R_R_R(INS_ldr, EA_4BYTE, REG_ZR, REG_SPBASE, rOffset);
57675770
GetEmitter()->emitIns_R_R_I(INS_sub, EA_PTRSIZE, rOffset, rOffset, pageSize);
57685771
GetEmitter()->emitIns_R_R(INS_cmp, EA_PTRSIZE, rLimit, rOffset); // If equal, we need to probe again
5769-
GetEmitter()->emitIns_J(INS_bls, NULL, -4);
5772+
GetEmitter()->emitIns_ShortJ(INS_bls, loopHead);
57705773

57715774
*pInitRegZeroed = false; // The initReg does not contain zero
57725775

src/coreclr/jit/codegencommon.cpp

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

60146014
GetEmitter()->emitStartPrologEpilogGeneration();
60156015

6016+
m_compiler->compCurBB = m_compiler->fgFirstBB; // Set the current BB for label creation.
60166017
gcInfo.gcResetForBB();
60176018
genFnProlog();
60186019

@@ -6040,6 +6041,8 @@ void CodeGen::genGeneratePrologsAndEpilogs()
60406041

60416042
GetEmitter()->emitFinishPrologEpilogGeneration();
60426043

6044+
m_compiler->compCurBB = nullptr;
6045+
60436046
#ifdef DEBUG
60446047
if (verbose)
60456048
{

src/coreclr/jit/codegenriscv64.cpp

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

795-
// TODO-RISCV64-RVC: Remove hardcoded branch offset here
795+
BasicBlock* loopHead = genCreateTempLabel();
796+
genDefineInlineTempLabel(loopHead);
796797
GetEmitter()->emitIns_R_R_I(INS_sd, EA_PTRSIZE, REG_R0, rAddr, padding);
797798
GetEmitter()->emitIns_R_R_I(INS_sd, EA_PTRSIZE, REG_R0, rAddr, padding + REGSIZE_BYTES);
798799
GetEmitter()->emitIns_R_R_I(INS_sd, EA_PTRSIZE, REG_R0, rAddr, padding + 2 * REGSIZE_BYTES);
799800
GetEmitter()->emitIns_R_R_I(INS_sd, EA_PTRSIZE, REG_R0, rAddr, padding + 3 * REGSIZE_BYTES);
800801

801802
GetEmitter()->emitIns_R_R_I(INS_addi, EA_PTRSIZE, rAddr, rAddr, 4 * REGSIZE_BYTES);
802-
GetEmitter()->emitIns_R_R_I(INS_bltu, EA_PTRSIZE, rAddr, rEndAddr, -5 << 2);
803+
GetEmitter()->emitIns_J_cond_la(INS_bltu, loopHead, rAddr, rEndAddr);
803804

804805
uLclBytes -= uLoopBytes;
805806
uAddrCurr = 0;

src/coreclr/jit/codegenxarch.cpp

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

1694-
GetEmitter()->emitIns_J(emitter::emitJumpKindToIns(jmp), tgtBlock, 0, isRemovableJmpCandidate);
1694+
GetEmitter()->emitIns_J(emitter::emitJumpKindToIns(jmp), tgtBlock, isRemovableJmpCandidate);
16951695
}
16961696

16971697
//------------------------------------------------------------------------
@@ -11281,7 +11281,10 @@ void CodeGen::genZeroInitFrameUsingBlockInit(int untrLclHi, int untrLclLo, regNu
1128111281

1128211282
// Set loop counter
1128311283
emit->emitIns_R_I(INS_mov, EA_PTRSIZE, initReg, -(ssize_t)blkSize);
11284+
1128411285
// Loop start
11286+
BasicBlock* loopHead = genCreateTempLabel();
11287+
genDefineInlineTempLabel(loopHead);
1128511288
emit->emitIns_ARX_R(simdMov, EA_ATTR(XMM_REGSIZE_BYTES), zeroSIMDReg, frameReg, initReg, 1, alignedLclHi);
1128611289
emit->emitIns_ARX_R(simdMov, EA_ATTR(XMM_REGSIZE_BYTES), zeroSIMDReg, frameReg, initReg, 1,
1128711290
alignedLclHi + XMM_REGSIZE_BYTES);
@@ -11290,7 +11293,7 @@ void CodeGen::genZeroInitFrameUsingBlockInit(int untrLclHi, int untrLclLo, regNu
1129011293

1129111294
emit->emitIns_R_I(INS_add, EA_PTRSIZE, initReg, XMM_REGSIZE_BYTES * 3);
1129211295
// Loop until counter is 0
11293-
emit->emitIns_J(INS_jne, nullptr, -5);
11296+
emit->emitIns_ShortJ(INS_jne, loopHead);
1129411297

1129511298
// initReg will be zero at end of the loop
1129611299
*pInitRegZeroed = true;

src/coreclr/jit/emit.cpp

Lines changed: 95 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;
@@ -2465,14 +2460,15 @@ void emitter::emitBegPrologEpilog(insGroup* igPh)
24652460
emitThisGCrefRegs = emitInitGCrefRegs = igPh->igPhData->igPhInitGCrefRegs;
24662461
emitThisByrefRegs = emitInitByrefRegs = igPh->igPhData->igPhInitByrefRegs;
24672462

2463+
// Set the current BB for label creation.
2464+
m_compiler->compCurBB = igPh->igPhData->igPhBB;
2465+
24682466
igPh->igPhData = nullptr;
24692467

24702468
/* Create a non-placeholder group pointer that we'll now use */
2471-
24722469
insGroup* ig = igPh;
24732470

24742471
/* Set the current function using the function index we stored */
2475-
24762472
m_compiler->funSetCurrentFunc(ig->igFuncIdx);
24772473

24782474
/* Set the new IG as the place to generate code */
@@ -3651,6 +3647,30 @@ void emitter::emitSetSecondRetRegGCType(instrDescCGCA* id, emitAttr secondRetSiz
36513647
#endif // MULTIREG_HAS_SECOND_GC_RET
36523648

36533649
#ifndef TARGET_WASM
3650+
//------------------------------------------------------------------------
3651+
// emitIns_ShortJ: Emit a 'forced' short jump.
3652+
//
3653+
// Jumps in prologs are hardcoded to be short since we don't shorten
3654+
// them in binding.
3655+
//
3656+
// Arguments:
3657+
// ins - The jump instruction
3658+
// dst - The destination label (must already be bound to an IG)
3659+
//
3660+
void emitter::emitIns_ShortJ(instruction ins, BasicBlock* dst)
3661+
{
3662+
assert((emitCurIG->igFlags & IGF_OUT_OF_ORDER_MASK) != 0);
3663+
3664+
emitIns_J(ins, dst);
3665+
3666+
// We currently have a limitation where all jumps in the prolog must be short.
3667+
// This is mostly because we the prolog can't change size in emission, as we
3668+
// currently hardcode offsets from it into the unwind info during IG building.
3669+
// We also don't insert the jumps into the jump list in layout order.
3670+
instrDescJmp* jumpId = static_cast<instrDescJmp*>(emitLastIns);
3671+
jumpId->idjKeepLong = false;
3672+
emitSetShortJump(jumpId);
3673+
}
36543674

36553675
/*****************************************************************************
36563676
*
@@ -4952,6 +4972,15 @@ void emitter::emitJumpDistBind()
49524972
}
49534973
#endif
49544974

4975+
// For the fixed-size jumps, we only need to bind them.
4976+
for (instrDescJmp* jmp = emitFixedSizeJumpList; jmp != nullptr; jmp = jmp->idjNext)
4977+
{
4978+
if (!jmp->idIsBound())
4979+
{
4980+
emitBindJump(jmp);
4981+
}
4982+
}
4983+
49554984
instrDescJmp* jmp;
49564985

49574986
UNATIVE_OFFSET minShortExtra; // The smallest offset greater than that required for a jump to be converted
@@ -5269,40 +5298,7 @@ void emitter::emitJumpDistBind()
52695298
else
52705299
{
52715300
/* First time we've seen this label, convert its target */
5272-
5273-
#ifdef DEBUG
5274-
if (EMITVERBOSE)
5275-
{
5276-
printf("Binding: ");
5277-
emitDispIns(jmp, false, false, false);
5278-
printf("Binding L_M%03u_" FMT_BB, m_compiler->compMethodID, jmp->idAddr()->iiaBBlabel->bbNum);
5279-
}
5280-
#endif // DEBUG
5281-
5282-
tgtIG = (insGroup*)emitCodeGetCookie(jmp->idAddr()->iiaBBlabel);
5283-
5284-
#ifdef DEBUG
5285-
if (EMITVERBOSE)
5286-
{
5287-
if (tgtIG)
5288-
{
5289-
printf(" to %s\n", emitLabelString(tgtIG));
5290-
}
5291-
else
5292-
{
5293-
printf("-- ERROR, no emitter cookie for " FMT_BB "; it is probably missing BBF_HAS_LABEL.\n",
5294-
jmp->idAddr()->iiaBBlabel->bbNum);
5295-
}
5296-
}
5297-
#endif // DEBUG
5298-
5299-
assert(jmp->idAddr()->iiaBBlabel->HasFlag(BBF_HAS_LABEL));
5300-
assert(tgtIG);
5301-
5302-
/* Record the bound target */
5303-
5304-
jmp->idAddr()->iiaIGlabel = tgtIG;
5305-
jmp->idSetIsBound();
5301+
tgtIG = emitBindJump(jmp);
53065302
}
53075303

53085304
// We should not be jumping/branching across funclets/functions
@@ -5723,6 +5719,54 @@ void emitter::emitJumpDistBind()
57235719
emitCheckIGList();
57245720
#endif // DEBUG
57255721
}
5722+
5723+
//------------------------------------------------------------------------
5724+
// emitBindJump: 'Bind' a jump by assigning its target label field.
5725+
//
5726+
// Arguments:
5727+
// jmp - The jump instruction
5728+
//
5729+
// Return Value:
5730+
// The target IG "jmp" was bound to.
5731+
//
5732+
insGroup* emitter::emitBindJump(instrDescJmp* jmp)
5733+
{
5734+
assert(!jmp->idIsBound());
5735+
5736+
#ifdef DEBUG
5737+
if (EMITVERBOSE)
5738+
{
5739+
printf("Binding: ");
5740+
emitDispIns(jmp, false, false, false);
5741+
printf("Binding L_M%03u_" FMT_BB, m_compiler->compMethodID, jmp->idAddr()->iiaBBlabel->bbNum);
5742+
}
5743+
#endif // DEBUG
5744+
5745+
insGroup* tgtIG = (insGroup*)emitCodeGetCookie(jmp->idAddr()->iiaBBlabel);
5746+
5747+
#ifdef DEBUG
5748+
if (EMITVERBOSE)
5749+
{
5750+
if (tgtIG)
5751+
{
5752+
printf(" to %s\n", emitLabelString(tgtIG));
5753+
}
5754+
else
5755+
{
5756+
printf("-- ERROR, no emitter cookie for " FMT_BB "; it is probably missing BBF_HAS_LABEL.\n",
5757+
jmp->idAddr()->iiaBBlabel->bbNum);
5758+
}
5759+
}
5760+
#endif // DEBUG
5761+
5762+
assert(jmp->idAddr()->iiaBBlabel->HasFlag(BBF_HAS_LABEL));
5763+
assert(tgtIG != nullptr);
5764+
5765+
/* Record the bound target */
5766+
jmp->idAddr()->iiaIGlabel = tgtIG;
5767+
jmp->idSetIsBound();
5768+
return tgtIG;
5769+
}
57265770
#endif
57275771

57285772
#if FEATURE_LOOP_ALIGN
@@ -6653,13 +6697,6 @@ void emitter::emitCheckFuncletBranch(instrDesc* jmp, insGroup* jmpIG)
66536697
}
66546698
#endif
66556699

6656-
if (jmp->idAddr()->iiaHasInstrCount())
6657-
{
6658-
// Too hard to figure out funclets from just an instruction count
6659-
// You're on your own!
6660-
return;
6661-
}
6662-
66636700
#ifdef TARGET_ARM64
66646701
// No interest if it's not jmp.
66656702
if (emitIsLoadLabel(jmp) || emitIsLoadConstant(jmp))
@@ -7683,7 +7720,6 @@ unsigned emitter::emitEndCodeGen(Compiler* comp,
76837720
// Presumably we could also just call "emitOutputLJ(NULL, adr, jmp)", like for long jumps?
76847721
*(short int*)(adr + writeableOffset) -= (short)adj;
76857722
#elif defined(TARGET_ARM64)
7686-
assert(!jmp->idAddr()->iiaHasInstrCount());
76877723
emitOutputLJ(NULL, adr, jmp);
76887724
#elif defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64)
76897725
// For LoongArch64 and RiscV64 `emitFwdJumps` is always false.
@@ -7700,7 +7736,6 @@ unsigned emitter::emitEndCodeGen(Compiler* comp,
77007736
#if defined(TARGET_XARCH)
77017737
*(int*)(adr + writeableOffset) -= adj;
77027738
#elif defined(TARGET_ARMARCH)
7703-
assert(!jmp->idAddr()->iiaHasInstrCount());
77047739
emitOutputLJ(NULL, adr, jmp);
77057740
#elif defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64)
77067741
// For LoongArch64 and RiscV64 `emitFwdJumps` is always false.

0 commit comments

Comments
 (0)