Skip to content

Commit fb25de8

Browse files
Remove single-IG prolog restriction
1 parent 9ca7727 commit fb25de8

File tree

8 files changed

+117
-153
lines changed

8 files changed

+117
-153
lines changed

src/coreclr/jit/codegencommon.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5550,7 +5550,7 @@ void CodeGen::genFnProlog()
55505550
// For OSR we may have a zero-length prolog. That's not supported
55515551
// when the method must report a generics context,/ so add a nop if so.
55525552
//
5553-
if (m_compiler->opts.IsOSR() && (GetEmitter()->emitGetPrologOffsetEstimate() == 0) &&
5553+
if (m_compiler->opts.IsOSR() && (GetEmitter()->emitGetCurrentCodeOffsetFrom(nullptr) == 0) &&
55545554
(m_compiler->lvaReportParamTypeArg() || m_compiler->lvaKeepAliveAndReportThis()))
55555555
{
55565556
JITDUMP("OSR: prolog was zero length and has generic context to report: adding nop to pad prolog.\n");

src/coreclr/jit/emit.cpp

Lines changed: 67 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -71,26 +71,6 @@ int emitLocation::GetInsOffset() const
7171
return emitGetInsOfsFromCodePos(codePos);
7272
}
7373

74-
// Get the instruction offset in the current instruction region, which must be a funclet prolog.
75-
// This is used to find an instruction offset used in unwind data.
76-
UNATIVE_OFFSET emitLocation::GetFuncletPrologOffset(emitter* emit) const
77-
{
78-
assert(ig->igFuncIdx != 0);
79-
assert((ig->igFlags & IGF_FUNCLET_PROLOG) != 0);
80-
assert((ig->igFlags & IGF_OUT_OF_ORDER_HEAD) != 0);
81-
assert(GetInsOffset() == 0);
82-
83-
unsigned offset = 0;
84-
insGroup* lastIG = ig;
85-
while (lastIG != emit->emitCurIG)
86-
{
87-
offset += lastIG->igSize;
88-
lastIG = lastIG->igNext;
89-
}
90-
assert((lastIG->igFlags & IGF_FUNCLET_PROLOG) != 0);
91-
92-
return offset + emit->emitCurIGsize;
93-
}
9474
//------------------------------------------------------------------------
9575
// IsPreviousInsNum: Returns true if the emitter is on the next instruction
9676
// of the same group as this emitLocation.
@@ -1284,7 +1264,7 @@ insGroup* emitter::emitSavIG(bool emitAdd)
12841264
if (last != nullptr)
12851265
{
12861266
// Append the jump(s) from this IG to the global list
1287-
bool prologJump = (ig == emitPrologIG);
1267+
bool prologJump = emitIGisInProlog(ig);
12881268
if ((emitJumpList == nullptr) || prologJump)
12891269
{
12901270
last->idjNext = emitJumpList;
@@ -1371,6 +1351,8 @@ void emitter::emitBegFN(bool hasFramePtr
13711351
emitChkAlign = chkAlign;
13721352
#endif
13731353

1354+
emitPrologEndPos.Init();
1355+
13741356
/* We have no epilogs yet */
13751357

13761358
emitEpilogSize = 0;
@@ -1476,7 +1458,8 @@ void emitter::emitBegFN(bool hasFramePtr
14761458

14771459
emitNxtIGnum = 1;
14781460

1479-
emitPrologIG = emitIGlist = emitIGlast = emitCurIG = ig = emitAllocIG();
1461+
emitIGlist = emitIGlast = emitCurIG = ig = emitAllocIG();
1462+
emitCurIG->igFlags |= (IGF_PROLOG | IGF_OUT_OF_ORDER_HEAD);
14801463

14811464
emitLastIns = nullptr;
14821465
emitLastInsIG = nullptr;
@@ -1493,8 +1476,10 @@ void emitter::emitBegFN(bool hasFramePtr
14931476
#endif
14941477

14951478
/* Append another group, to start generating the method body */
1496-
14971479
emitNewIG();
1480+
1481+
/* The group after the placeholder prolog group doesn't get the "propagate" flags */
1482+
emitCurIG->igFlags &= ~IGF_PROPAGATE_MASK;
14981483
}
14991484

15001485
#ifdef PSEUDORANDOM_NOP_INSERTION
@@ -1741,7 +1726,7 @@ void* emitter::emitAllocAnyInstr(size_t sz, emitAttr opsz)
17411726
{
17421727
#ifdef DEBUG
17431728
// Under STRESS_EMITTER, put every instruction in its own instruction group.
1744-
if (m_compiler->compStressCompile(Compiler::STRESS_EMITTER, 1) && emitCurIGinsCnt && !emitIGisInProlog(emitCurIG) &&
1729+
if (m_compiler->compStressCompile(Compiler::STRESS_EMITTER, 1) && (emitCurIGinsCnt != 0) &&
17451730
!emitCurIG->endsWithAlignInstr())
17461731
{
17471732
emitNxtIG(true);
@@ -1935,8 +1920,6 @@ void* emitter::emitAllocAnyInstr(size_t sz, emitAttr opsz)
19351920
//
19361921
void emitter::emitCheckIGList()
19371922
{
1938-
assert(emitPrologIG != nullptr);
1939-
19401923
#if EMIT_BACKWARDS_NAVIGATION
19411924
struct IGIDPair
19421925
{
@@ -1968,17 +1951,18 @@ void emitter::emitCheckIGList()
19681951
assert((currIG->igFlags & IGF_EXTEND) == 0);
19691952

19701953
// First IG must be the function prolog.
1971-
assert(currIG == emitPrologIG);
1954+
assert((currIG->igFlags & IGF_PROLOG) != 0);
19721955
}
19731956

1974-
if (currIG == emitPrologIG)
1957+
if ((currIG->igFlags & IGF_PROLOG) != 0)
19751958
{
19761959
// If we're in the function prolog, we can't be in any other prolog or epilog.
19771960
assert((currIG->igFlags & (IGF_FUNCLET_PROLOG | IGF_FUNCLET_EPILOG | IGF_EPILOG)) == 0);
19781961
}
19791962

19801963
// An IG can have at most one of the prolog and epilog flags set.
1981-
assert(genCountBits((unsigned)currIG->igFlags & (IGF_FUNCLET_PROLOG | IGF_FUNCLET_EPILOG | IGF_EPILOG)) <= 1);
1964+
assert(genCountBits((unsigned)currIG->igFlags &
1965+
(IGF_PROLOG | IGF_FUNCLET_PROLOG | IGF_FUNCLET_EPILOG | IGF_EPILOG)) <= 1);
19821966

19831967
// An IG can't have both IGF_HAS_ALIGN and IGF_REMOVED_ALIGN.
19841968
assert(genCountBits((unsigned)currIG->igFlags & (IGF_HAS_ALIGN | IGF_REMOVED_ALIGN)) <= 1);
@@ -1994,16 +1978,13 @@ void emitter::emitCheckIGList()
19941978
// not be EXTEND groups, and would there be a benefit to that? Since epilogs are NOGC
19951979
// it would help eliminate NOGC EXTEND groups.
19961980
//
1997-
// Note that function prologs must currently exist entirely within one IG and there is
1998-
// no flag to indicate a function prolog (the `emitPrologIG` variable points to the single
1999-
// unique prolog IG).
2000-
//
20011981
// Thus, we can't have this assert:
20021982
// assert((currIG->igFlags & (IGF_FUNCLET_PROLOG | IGF_FUNCLET_EPILOG | IGF_EPILOG)) ==
20031983
// (prevIG->igFlags & (IGF_FUNCLET_PROLOG | IGF_FUNCLET_EPILOG | IGF_EPILOG)));
20041984

2005-
// If this is a funclet prolog IG, then it can only extend another funclet prolog IG.
2006-
assert((currIG->igFlags & IGF_FUNCLET_PROLOG) == (prevIG->igFlags & IGF_FUNCLET_PROLOG));
1985+
// If this is a prolog IG, then it can only extend another prolog IG.
1986+
assert((currIG->igFlags & (IGF_PROLOG | IGF_FUNCLET_PROLOG)) ==
1987+
(prevIG->igFlags & (IGF_PROLOG | IGF_FUNCLET_PROLOG)));
20071988

20081989
// If this is a function epilog IG, it can't extend a funclet prolog or funclet epilog IG.
20091990
if (currIG->igFlags & IGF_EPILOG)
@@ -2102,8 +2083,7 @@ void emitter::emitBegProlog()
21022083
emitForceNewIG = false;
21032084

21042085
/* Switch to the pre-allocated prolog IG */
2105-
2106-
emitGenIG(emitPrologIG);
2086+
emitGenIG(emitGetFirstPrologIG());
21072087

21082088
/* Nothing is live on entry to the prolog */
21092089

@@ -2116,21 +2096,6 @@ void emitter::emitBegProlog()
21162096
emitPrevByrefRegs = RBM_NONE;
21172097
}
21182098

2119-
/*****************************************************************************
2120-
*
2121-
* Return the code offset of the current location in the prolog.
2122-
*/
2123-
2124-
unsigned emitter::emitGetPrologOffsetEstimate()
2125-
{
2126-
/* For now only allow a single prolog ins group */
2127-
2128-
assert(emitPrologIG);
2129-
assert(emitPrologIG == emitCurIG);
2130-
2131-
return emitCurIGsize;
2132-
}
2133-
21342099
/*****************************************************************************
21352100
*
21362101
* Mark the code offset of the current location as the end of the prolog,
@@ -2140,13 +2105,7 @@ unsigned emitter::emitGetPrologOffsetEstimate()
21402105
void emitter::emitMarkPrologEnd()
21412106
{
21422107
assert(m_compiler->compGeneratingProlog);
2143-
2144-
/* For now only allow a single prolog ins group */
2145-
2146-
assert(emitPrologIG);
2147-
assert(emitPrologIG == emitCurIG);
2148-
2149-
emitPrologEndPos = emitCurOffset();
2108+
emitPrologEndPos.CaptureLocation(this);
21502109
}
21512110

21522111
/*****************************************************************************
@@ -2163,7 +2122,7 @@ void emitter::emitEndProlog()
21632122

21642123
/* Save the prolog IG if non-empty or if only one block */
21652124

2166-
if (emitCurIGnonEmpty() || emitCurIG == emitPrologIG)
2125+
if (emitCurIGnonEmpty() || (emitCurIG == emitGetFirstPrologIG()))
21672126
{
21682127
emitSavIG();
21692128
}
@@ -2340,7 +2299,6 @@ void emitter::emitCreatePlaceholderIG(insGroupPlaceholderType igType,
23402299
emitForceStoreGCState = true;
23412300

23422301
/* The group after the placeholder group doesn't get the "propagate" flags */
2343-
23442302
emitCurIG->igFlags &= ~IGF_PROPAGATE_MASK;
23452303
}
23462304

@@ -2467,6 +2425,11 @@ void emitter::emitFinishPrologEpilogGeneration()
24672425
* Common code for prolog / epilog beginning. Convert the placeholder group to actual code IG,
24682426
* and set it as the current group.
24692427
*/
2428+
insGroup* emitter::emitGetFirstPrologIG() const
2429+
{
2430+
assert(emitIGisInProlog(emitIGlist));
2431+
return emitIGlist;
2432+
}
24702433

24712434
void emitter::emitBegPrologEpilog(insGroup* igPh)
24722435
{
@@ -4119,6 +4082,14 @@ void emitter::emitDispIGflags(unsigned flags)
41194082
{
41204083
printf(", byref");
41214084
}
4085+
if (flags & IGF_PROLOG)
4086+
{
4087+
printf(", prolog");
4088+
}
4089+
if (flags & IGF_EPILOG)
4090+
{
4091+
printf(", epilog");
4092+
}
41224093
if (flags & IGF_FUNCLET_PROLOG)
41234094
{
41244095
printf(", funclet prolog");
@@ -4127,10 +4098,6 @@ void emitter::emitDispIGflags(unsigned flags)
41274098
{
41284099
printf(", funclet epilog");
41294100
}
4130-
if (flags & IGF_EPILOG)
4131-
{
4132-
printf(", epilog");
4133-
}
41344101
if (flags & IGF_NOGCINTERRUPT)
41354102
{
41364103
printf(", nogc");
@@ -4317,10 +4284,6 @@ void emitter::emitDispIG(insGroup* ig, bool displayFunc, bool displayInstruction
43174284
{
43184285
printf(" <-- Current IG");
43194286
}
4320-
if (ig == emitPrologIG)
4321-
{
4322-
printf(" <-- Prolog IG");
4323-
}
43244287
}
43254288

43264289
printf("\n");
@@ -5002,9 +4965,6 @@ void emitter::emitJumpDistBind()
50024965
UNATIVE_OFFSET adjIG;
50034966
UNATIVE_OFFSET adjLJ;
50044967
insGroup* lstIG;
5005-
#ifdef DEBUG
5006-
insGroup* prologIG = emitPrologIG;
5007-
#endif // DEBUG
50084968

50094969
int jmp_iteration = 1;
50104970

@@ -5195,7 +5155,7 @@ void emitter::emitJumpDistBind()
51955155
assert(lastLJ == nullptr || lastIG != jmp->idjIG || lastLJ->idjOffs < jmp->idjOffs);
51965156
lastLJ = (lastIG == jmp->idjIG) ? jmp : nullptr;
51975157

5198-
assert(lastIG == nullptr || lastIG->IsBeforeOrEqual(jmp->idjIG) || jmp->idjIG == prologIG);
5158+
assert(lastIG == nullptr || lastIG->IsBeforeOrEqual(jmp->idjIG) || emitIGisInProlog(jmp->idjIG));
51995159
lastIG = jmp->idjIG;
52005160
#endif // DEBUG
52015161

@@ -7817,7 +7777,7 @@ unsigned emitter::emitEndCodeGen(Compiler* comp,
78177777
#endif // DEBUG
78187778

78197779
// Assign the real prolog size
7820-
*prologSize = emitCodeOffset(emitPrologIG, emitPrologEndPos);
7780+
*prologSize = emitPrologEndPos.CodeOffset(this);
78217781

78227782
/* Return the amount of code we've generated */
78237783

@@ -9567,6 +9527,39 @@ UNATIVE_OFFSET emitter::emitCodeOffset(void* blockPtr, unsigned codePos)
95679527
return ig->igOffs + of;
95689528
}
95699529

9530+
//------------------------------------------------------------------------
9531+
// emitGetCurrentCodeOffsetFrom: Get current code offset relative to "ig".
9532+
//
9533+
// This is used to retrieve the current offset within a prolog being generated
9534+
// for unwind info. Thus, the offset we return from here can't later shrink,
9535+
// and overestimating the code size of prolog instructions is fatal.
9536+
//
9537+
// Arguments:
9538+
// ig - IG denoting the start of code, "nullptr" for main function prolog
9539+
//
9540+
// Return Value:
9541+
// Effectively "<current code offset> - ig->igOffs".
9542+
//
9543+
UNATIVE_OFFSET emitter::emitGetCurrentCodeOffsetFrom(insGroup* ig)
9544+
{
9545+
if (ig == nullptr)
9546+
{
9547+
ig = emitGetFirstPrologIG();
9548+
}
9549+
assert((ig->igFlags & IGF_OUT_OF_ORDER_HEAD) != 0);
9550+
9551+
unsigned igKind = ig->igFlags & (IGF_PROLOG | IGF_FUNCLET_PROLOG);
9552+
unsigned offset = 0;
9553+
while (ig != emitCurIG)
9554+
{
9555+
offset += ig->igSize;
9556+
ig = ig->igNext;
9557+
}
9558+
assert((ig->igFlags & igKind) == igKind);
9559+
9560+
return offset + emitCurIGsize;
9561+
}
9562+
95709563
/*****************************************************************************
95719564
*
95729565
* Record the fact that the given register now contains a live GC ref.
@@ -9994,12 +9987,7 @@ void emitter::emitInsertIGAfter(insGroup* insertAfterIG, insGroup* ig)
99949987

99959988
void emitter::emitNxtIG(bool extend)
99969989
{
9997-
/* Right now we don't allow multi-IG prologs */
9998-
9999-
assert(emitCurIG != emitPrologIG);
10000-
100019990
/* First save the current group */
10002-
100039991
emitSavIG(extend);
100049992

100059993
/* Update the GC live sets for the group's start

0 commit comments

Comments
 (0)