@@ -16183,7 +16183,7 @@ bool emitter::IsRedundantLdStr(
16183
16183
// ins - The instruction code
16184
16184
// reg1Attr - The emit attribute for register 1
16185
16185
// reg1 - Register 1
16186
- // reg2 - Encoded register 2
16186
+ // reg2 - Register 2
16187
16187
// imm - Immediate offset, prior to scaling by operand size
16188
16188
// size - Operand size
16189
16189
// fmt - Instruction format
@@ -16194,9 +16194,6 @@ bool emitter::IsRedundantLdStr(
16194
16194
bool emitter::ReplaceLdrStrWithPairInstr(
16195
16195
instruction ins, emitAttr reg1Attr, regNumber reg1, regNumber reg2, ssize_t imm, emitAttr size, insFormat fmt)
16196
16196
{
16197
- // Register 2 needs conversion to unencoded value.
16198
- reg2 = encodingZRtoSP(reg2);
16199
-
16200
16197
RegisterOrder optimizationOrder = IsOptimizableLdrStrWithPair(ins, reg1, reg2, imm, size, fmt);
16201
16198
16202
16199
if (optimizationOrder != eRO_none)
@@ -16367,4 +16364,83 @@ emitter::RegisterOrder emitter::IsOptimizableLdrStrWithPair(
16367
16364
return optimisationOrder;
16368
16365
}
16369
16366
16367
+ //-----------------------------------------------------------------------------------
16368
+ // IsOptimizableLdrToMov: Check if it is possible to optimize a second "ldr"
16369
+ // instruction into a cheaper "mov" instruction.
16370
+ //
16371
+ // Examples: ldr w1, [x20, #0x10]
16372
+ // ldr w2, [x20, #0x10] => mov w1, w2
16373
+ //
16374
+ // Arguments:
16375
+ // ins - The instruction code
16376
+ // reg1 - Register 1 number
16377
+ // reg2 - Register 2 number
16378
+ // imm - Immediate offset, prior to scaling by operand size
16379
+ // size - Operand size
16380
+ // fmt - Instruction format
16381
+ //
16382
+ // Return Value:
16383
+ // true - Optimization of the second instruction is possible
16384
+ //
16385
+ bool emitter::IsOptimizableLdrToMov(
16386
+ instruction ins, regNumber reg1, regNumber reg2, ssize_t imm, emitAttr size, insFormat fmt)
16387
+ {
16388
+ if (ins != INS_ldr)
16389
+ {
16390
+ // This instruction is not an "ldr" instruction.
16391
+ return false;
16392
+ }
16393
+
16394
+ if (ins != emitLastIns->idIns())
16395
+ {
16396
+ // Not successive "ldr" instructions.
16397
+ return false;
16398
+ }
16399
+
16400
+ regNumber prevReg1 = emitLastIns->idReg1();
16401
+ regNumber prevReg2 = emitLastIns->idReg2();
16402
+ insFormat lastInsFmt = emitLastIns->idInsFmt();
16403
+ emitAttr prevSize = emitLastIns->idOpSize();
16404
+ ssize_t prevImm = emitGetInsSC(emitLastIns);
16405
+
16406
+ if ((reg2 != prevReg2) || !isGeneralRegisterOrSP(reg2))
16407
+ {
16408
+ // The "register 2" should be same as previous instruction and
16409
+ // should either be a general register or stack pointer.
16410
+ return false;
16411
+ }
16412
+
16413
+ if (prevImm != imm)
16414
+ {
16415
+ // Then we are loading from a different immediate offset.
16416
+ return false;
16417
+ }
16418
+
16419
+ if (!isGeneralRegister(reg1) || !isGeneralRegister(prevReg1))
16420
+ {
16421
+ // Either register 1 or previous register 1 is not a general register
16422
+ // or the zero register, so we cannot optimise.
16423
+ return false;
16424
+ }
16425
+
16426
+ if (lastInsFmt != fmt)
16427
+ {
16428
+ // The formats of the two instructions differ.
16429
+ return false;
16430
+ }
16431
+
16432
+ if (prevReg1 == prevReg2)
16433
+ {
16434
+ // Then the previous load overwrote the register that we are indexing against.
16435
+ return false;
16436
+ }
16437
+
16438
+ if (prevSize != size)
16439
+ {
16440
+ // Operand sizes differ.
16441
+ return false;
16442
+ }
16443
+
16444
+ return true;
16445
+ }
16370
16446
#endif // defined(TARGET_ARM64)
0 commit comments