Skip to content

Commit 318186b

Browse files
authored
[Arm64] Replace pairs of str with stp (#85032)
* Add emitIns_SS_R_R_R_I() * Introduce instrDescStrPair and use it * rename some variables and fix a bug in outputInstr * Rename to instrDescLclVarPair * Add the missing SetIsLclVar() * review feedback * Use same code for GC/non-GC lclVar for stp' * Use same code path for ldp/stp * Just have asending/descending * refactor code around emitOutputInstr() * jit format * Remove the comment * Separate instrDescLclVarPair and instrDescLclVarPairCns * useRsvdReg for assert * add back the assert around `adr + ofs` * Move OptimizeLdrStr() in emitarm64.cpp * Update the assert for offset distance * Rename emitIns_SS_R_R_R_I() to emitIns_R_R_R_I_LdStPair() * jit format * review feedback
1 parent e029183 commit 318186b

File tree

3 files changed

+484
-138
lines changed

3 files changed

+484
-138
lines changed

src/coreclr/jit/emit.h

Lines changed: 103 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -782,17 +782,18 @@ class emitter
782782
unsigned _idNoGC : 1; // Some helpers don't get recorded in GC tables
783783

784784
#ifdef TARGET_ARM64
785-
opSize _idOpSize : 3; // operand size: 0=1 , 1=2 , 2=4 , 3=8, 4=16
786-
insOpts _idInsOpt : 6; // options for instructions
787-
unsigned _idLclVar : 1; // access a local on stack
785+
opSize _idOpSize : 3; // operand size: 0=1 , 1=2 , 2=4 , 3=8, 4=16
786+
insOpts _idInsOpt : 6; // options for instructions
787+
unsigned _idLclVar : 1; // access a local on stack
788+
unsigned _idLclVarPair : 1 // carries information for 2 GC lcl vars.
788789
#endif
789790

790791
#ifdef TARGET_LOONGARCH64
791-
// TODO-LoongArch64: maybe delete on future.
792-
opSize _idOpSize : 3; // operand size: 0=1 , 1=2 , 2=4 , 3=8, 4=16
793-
insOpts _idInsOpt : 6; // loongarch options for special: placeholders. e.g emitIns_R_C, also identifying the
794-
// accessing a local on stack.
795-
unsigned _idLclVar : 1; // access a local on stack.
792+
// TODO-LoongArch64: maybe delete on future.
793+
opSize _idOpSize : 3; // operand size: 0=1 , 1=2 , 2=4 , 3=8, 4=16
794+
insOpts _idInsOpt : 6; // loongarch options for special: placeholders. e.g emitIns_R_C, also identifying the
795+
// accessing a local on stack.
796+
unsigned _idLclVar : 1; // access a local on stack.
796797
#endif
797798

798799
#ifdef TARGET_RISCV64
@@ -815,7 +816,7 @@ class emitter
815816
// x86: 46 bits
816817
// amd64: 46 bits
817818
// arm: 48 bits
818-
// arm64: 49 bits
819+
// arm64: 50 bits
819820
// loongarch64: 46 bits
820821

821822
//
@@ -827,7 +828,7 @@ class emitter
827828
#if defined(TARGET_ARM)
828829
#define ID_EXTRA_BITFIELD_BITS (16)
829830
#elif defined(TARGET_ARM64)
830-
#define ID_EXTRA_BITFIELD_BITS (17)
831+
#define ID_EXTRA_BITFIELD_BITS (18)
831832
#elif defined(TARGET_XARCH) || defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64)
832833
#define ID_EXTRA_BITFIELD_BITS (14)
833834
#else
@@ -867,7 +868,7 @@ class emitter
867868
// x86: 52/48 bits
868869
// amd64: 53/48 bits
869870
// arm: 54/50 bits
870-
// arm64: 56/51 bits
871+
// arm64: 57/52 bits
871872
// loongarch64: 53/48 bits
872873
CLANG_FORMAT_COMMENT_ANCHOR;
873874

@@ -885,7 +886,7 @@ class emitter
885886
// x86: 12/16 bits
886887
// amd64: 11/16 bits
887888
// arm: 10/14 bits
888-
// arm64: 8/13 bits
889+
// arm64: 7/12 bits
889890
// loongarch64: 11/16 bits
890891

891892
unsigned _idSmallCns : ID_BIT_SMALL_CNS;
@@ -1432,6 +1433,16 @@ class emitter
14321433
{
14331434
_idLclVar = 1;
14341435
}
1436+
#ifdef TARGET_ARM64
1437+
bool idIsLclVarPair() const
1438+
{
1439+
return _idLclVarPair != 0;
1440+
}
1441+
void idSetIsLclVarPair()
1442+
{
1443+
_idLclVarPair = 1;
1444+
}
1445+
#endif // TARGET_ARM64
14351446
#endif // TARGET_ARMARCH
14361447

14371448
#if defined(TARGET_ARM)
@@ -1819,6 +1830,22 @@ class emitter
18191830

18201831
#endif // TARGET_XARCH
18211832

1833+
#ifdef TARGET_ARM64
1834+
struct instrDescLclVarPair : instrDesc // contains 2 gc vars to be tracked
1835+
{
1836+
instrDescLclVarPair() = delete;
1837+
1838+
emitLclVarAddr iiaLclVar2;
1839+
};
1840+
1841+
struct instrDescLclVarPairCns : instrDescCns // contains 2 gc vars to be tracked, with large cons
1842+
{
1843+
instrDescLclVarPairCns() = delete;
1844+
1845+
emitLclVarAddr iiaLclVar2;
1846+
};
1847+
#endif
1848+
18221849
struct instrDescCGCA : instrDesc // call with ...
18231850
{
18241851
instrDescCGCA() = delete;
@@ -2600,7 +2627,26 @@ class emitter
26002627
#endif // EMITTER_STATS
26012628
return (instrDescLbl*)emitAllocAnyInstr(sizeof(instrDescLbl), EA_4BYTE);
26022629
}
2603-
#endif // !TARGET_ARM64
2630+
#endif // TARGET_ARM64
2631+
2632+
#if defined(TARGET_ARM64)
2633+
instrDescLclVarPair* emitAllocInstrLclVarPair(emitAttr attr)
2634+
{
2635+
instrDescLclVarPair* result = (instrDescLclVarPair*)emitAllocAnyInstr(sizeof(instrDescLclVarPair), attr);
2636+
result->idSetIsLclVarPair();
2637+
return result;
2638+
}
2639+
2640+
instrDescLclVarPairCns* emitAllocInstrLclVarPairCns(emitAttr attr, cnsval_size_t cns)
2641+
{
2642+
instrDescLclVarPairCns* result =
2643+
(instrDescLclVarPairCns*)emitAllocAnyInstr(sizeof(instrDescLclVarPairCns), attr);
2644+
result->idSetIsLargeCns();
2645+
result->idSetIsLclVarPair();
2646+
result->idcCnsVal = cns;
2647+
return result;
2648+
}
2649+
#endif // TARGET_ARM64
26042650

26052651
instrDescCns* emitAllocInstrCns(emitAttr attr)
26062652
{
@@ -2686,6 +2732,8 @@ class emitter
26862732

26872733
#if !defined(TARGET_ARM64)
26882734
instrDescLbl* emitNewInstrLbl();
2735+
#else
2736+
instrDesc* emitNewInstrLclVarPair(emitAttr attr, cnsval_ssize_t cns);
26892737
#endif // !TARGET_ARM64
26902738

26912739
static const BYTE emitFmtToOps[];
@@ -3249,6 +3297,36 @@ inline emitter::instrDescLbl* emitter::emitNewInstrLbl()
32493297
{
32503298
return emitAllocInstrLbl();
32513299
}
3300+
#else
3301+
inline emitter::instrDesc* emitter::emitNewInstrLclVarPair(emitAttr attr, cnsval_ssize_t cns)
3302+
{
3303+
#if EMITTER_STATS
3304+
emitTotalIDescCnt++;
3305+
emitTotalIDescCnsCnt++;
3306+
#endif // EMITTER_STATS
3307+
3308+
if (instrDesc::fitsInSmallCns(cns))
3309+
{
3310+
instrDescLclVarPair* id = emitAllocInstrLclVarPair(attr);
3311+
id->idSmallCns(cns);
3312+
#if EMITTER_STATS
3313+
emitSmallCnsCnt++;
3314+
if ((cns - ID_MIN_SMALL_CNS) >= (SMALL_CNS_TSZ - 1))
3315+
emitSmallCns[SMALL_CNS_TSZ - 1]++;
3316+
else
3317+
emitSmallCns[cns - ID_MIN_SMALL_CNS]++;
3318+
#endif
3319+
return id;
3320+
}
3321+
else
3322+
{
3323+
instrDescLclVarPairCns* id = emitAllocInstrLclVarPairCns(attr, cns);
3324+
#if EMITTER_STATS
3325+
emitLargeCnsCnt++;
3326+
#endif
3327+
return id;
3328+
}
3329+
}
32523330
#endif // !TARGET_ARM64
32533331

32543332
inline emitter::instrDesc* emitter::emitNewInstrDsp(emitAttr attr, target_ssize_t dsp)
@@ -3329,10 +3407,22 @@ inline size_t emitter::emitGetInstrDescSize(const instrDesc* id)
33293407
}
33303408
else if (id->idIsLargeCns())
33313409
{
3410+
#ifdef TARGET_ARM64
3411+
if (id->idIsLclVarPair())
3412+
{
3413+
return sizeof(instrDescLclVarPairCns);
3414+
}
3415+
#endif
33323416
return sizeof(instrDescCns);
33333417
}
33343418
else
33353419
{
3420+
#ifdef TARGET_ARM64
3421+
if (id->idIsLclVarPair())
3422+
{
3423+
return sizeof(instrDescLclVarPair);
3424+
}
3425+
#endif
33363426
return sizeof(instrDesc);
33373427
}
33383428
}

0 commit comments

Comments
 (0)