mirror of
https://github.com/VSadov/Satori.git
synced 2025-06-11 10:18:21 +09:00
JIT: Add an emitter peephole for post-indexed addressing (#105181)
This transforms sequences like ```asm ldr x0, [x1] add x1, x1, #8 ``` into the equivalent ```asm ldr x0, [x1], #8 ```
This commit is contained in:
parent
894f22d768
commit
fcb9b1825c
2 changed files with 160 additions and 0 deletions
|
@ -5844,6 +5844,12 @@ void emitter::emitIns_R_R_I(instruction ins,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((reg1 == reg2) && (EA_SIZE(attr) == EA_PTRSIZE) && emitComp->opts.OptimizationEnabled() &&
|
||||||
|
OptimizePostIndexed(ins, reg1, imm, attr))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
reg1 = encodingSPtoZR(reg1);
|
reg1 = encodingSPtoZR(reg1);
|
||||||
reg2 = encodingSPtoZR(reg2);
|
reg2 = encodingSPtoZR(reg2);
|
||||||
}
|
}
|
||||||
|
@ -11070,6 +11076,37 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp)
|
||||||
code |= ((code_t)imm << 12); // iiiiiiiii
|
code |= ((code_t)imm << 12); // iiiiiiiii
|
||||||
code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
|
code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
|
||||||
dst += emitOutput_Instr(dst, code);
|
dst += emitOutput_Instr(dst, code);
|
||||||
|
|
||||||
|
// With pre or post-indexing we may have a second GC register to
|
||||||
|
// update.
|
||||||
|
if (insOptsIndexed(id->idInsOpt()) && !id->idIsSmallDsc())
|
||||||
|
{
|
||||||
|
if (emitInsIsLoad(ins))
|
||||||
|
{
|
||||||
|
// Load will write the destination (reg1).
|
||||||
|
if (id->idGCref() != GCT_NONE)
|
||||||
|
{
|
||||||
|
emitGCregLiveUpd(id->idGCref(), id->idReg1(), dst);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
emitGCregDeadUpd(id->idReg1(), dst);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// We will always write reg2.
|
||||||
|
if (id->idGCrefReg2() != GCT_NONE)
|
||||||
|
{
|
||||||
|
emitGCregLiveUpd(id->idGCrefReg2(), id->idReg2(), dst);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
emitGCregDeadUpd(id->idReg2(), dst);
|
||||||
|
}
|
||||||
|
|
||||||
|
goto SKIP_GC_UPDATE;
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IF_LS_2D: // LS_2D .Q.............. ....ssnnnnnttttt Vt Rn
|
case IF_LS_2D: // LS_2D .Q.............. ....ssnnnnnttttt Vt Rn
|
||||||
|
@ -17150,6 +17187,127 @@ bool emitter::IsOptimizableLdrToMov(
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------------
|
||||||
|
// OptimizePostIndexed: Optimize an addition/subtraction from a register by
|
||||||
|
// replacing the previous instruction with a post-indexed addressing form if
|
||||||
|
// possible.
|
||||||
|
//
|
||||||
|
// Arguments:
|
||||||
|
// ins - Whether this is an add or subtraction
|
||||||
|
// reg - The register that is being updated
|
||||||
|
// imm - Immediate that is being added/subtracted
|
||||||
|
//
|
||||||
|
// Returns:
|
||||||
|
// True if the previous instruction was optimized to perform the add/sub.
|
||||||
|
//
|
||||||
|
bool emitter::OptimizePostIndexed(instruction ins, regNumber reg, ssize_t imm, emitAttr regAttr)
|
||||||
|
{
|
||||||
|
assert((ins == INS_add) || (ins == INS_sub));
|
||||||
|
|
||||||
|
if (!emitCanPeepholeLastIns() || !emitInsIsLoadOrStore(emitLastIns->idIns()))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((emitLastIns->idInsFmt() != IF_LS_2A) || emitLastIns->idIsTlsGD())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cannot allow post indexing if the load itself is already modifying the
|
||||||
|
// register.
|
||||||
|
regNumber loadStoreDataReg = emitLastIns->idReg1();
|
||||||
|
if (loadStoreDataReg == reg)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We must be updating the same register that the addressing is happening
|
||||||
|
// on. The SP register is stored as ZR, so make sure to normalize that too.
|
||||||
|
regNumber loadStoreAddrReg = encodingZRtoSP(emitLastIns->idReg2());
|
||||||
|
if (loadStoreAddrReg != reg)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only some stores/loads are eligible
|
||||||
|
switch (emitLastIns->idIns())
|
||||||
|
{
|
||||||
|
case INS_ldrb:
|
||||||
|
case INS_strb:
|
||||||
|
case INS_ldurb:
|
||||||
|
case INS_sturb:
|
||||||
|
case INS_ldrh:
|
||||||
|
case INS_strh:
|
||||||
|
case INS_ldurh:
|
||||||
|
case INS_sturh:
|
||||||
|
case INS_ldrsb:
|
||||||
|
case INS_ldursb:
|
||||||
|
case INS_ldrsh:
|
||||||
|
case INS_ldursh:
|
||||||
|
case INS_ldrsw:
|
||||||
|
case INS_ldursw:
|
||||||
|
case INS_ldr:
|
||||||
|
case INS_str:
|
||||||
|
case INS_ldur:
|
||||||
|
case INS_stur:
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ins == INS_sub)
|
||||||
|
{
|
||||||
|
imm = -imm;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only some post-indexing offsets can be represented.
|
||||||
|
if ((imm < -256) || (imm >= 256))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
instruction newIns = emitLastIns->idIns();
|
||||||
|
emitAttr newAttr;
|
||||||
|
|
||||||
|
switch (emitLastIns->idGCref())
|
||||||
|
{
|
||||||
|
case GCT_BYREF:
|
||||||
|
newAttr = EA_BYREF;
|
||||||
|
break;
|
||||||
|
case GCT_GCREF:
|
||||||
|
newAttr = EA_GCREF;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
newAttr = emitLastIns->idOpSize();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
emitRemoveLastInstruction();
|
||||||
|
|
||||||
|
instrDesc* id = emitNewInstrCns(newAttr, imm);
|
||||||
|
id->idIns(newIns);
|
||||||
|
id->idInsFmt(IF_LS_2C);
|
||||||
|
id->idInsOpt(INS_OPTS_POST_INDEX);
|
||||||
|
|
||||||
|
id->idReg1(loadStoreDataReg);
|
||||||
|
id->idReg2(encodingSPtoZR(loadStoreAddrReg));
|
||||||
|
|
||||||
|
if (EA_IS_BYREF(regAttr))
|
||||||
|
{
|
||||||
|
id->idGCrefReg2(GCT_BYREF);
|
||||||
|
}
|
||||||
|
else if (EA_IS_GCREF(regAttr))
|
||||||
|
{
|
||||||
|
id->idGCrefReg2(GCT_GCREF);
|
||||||
|
}
|
||||||
|
|
||||||
|
dispIns(id);
|
||||||
|
appendToCurIG(id);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(FEATURE_SIMD)
|
#if defined(FEATURE_SIMD)
|
||||||
//-----------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------
|
||||||
// emitStoreSimd12ToLclOffset: store SIMD12 value from dataReg to varNum+offset.
|
// emitStoreSimd12ToLclOffset: store SIMD12 value from dataReg to varNum+offset.
|
||||||
|
|
|
@ -193,6 +193,8 @@ FORCEINLINE bool OptimizeLdrStr(instruction ins,
|
||||||
int varx = -1,
|
int varx = -1,
|
||||||
int offs = -1 DEBUG_ARG(bool useRsvdReg = false));
|
int offs = -1 DEBUG_ARG(bool useRsvdReg = false));
|
||||||
|
|
||||||
|
bool OptimizePostIndexed(instruction ins, regNumber reg, ssize_t imm, emitAttr regAttr);
|
||||||
|
|
||||||
emitLclVarAddr* emitGetLclVarPairLclVar2(instrDesc* id)
|
emitLclVarAddr* emitGetLclVarPairLclVar2(instrDesc* id)
|
||||||
{
|
{
|
||||||
assert(id->idIsLclVarPair());
|
assert(id->idIsLclVarPair());
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue