@@ -16183,7 +16183,7 @@ bool emitter::IsRedundantLdStr(
1618316183// ins - The instruction code
1618416184// reg1Attr - The emit attribute for register 1
1618516185// reg1 - Register 1
16186- // reg2 - Encoded register 2
16186+ // reg2 - Register 2
1618716187// imm - Immediate offset, prior to scaling by operand size
1618816188// size - Operand size
1618916189// fmt - Instruction format
@@ -16194,9 +16194,6 @@ bool emitter::IsRedundantLdStr(
1619416194bool emitter::ReplaceLdrStrWithPairInstr(
1619516195 instruction ins, emitAttr reg1Attr, regNumber reg1, regNumber reg2, ssize_t imm, emitAttr size, insFormat fmt)
1619616196{
16197- // Register 2 needs conversion to unencoded value.
16198- reg2 = encodingZRtoSP(reg2);
16199-
1620016197 RegisterOrder optimizationOrder = IsOptimizableLdrStrWithPair(ins, reg1, reg2, imm, size, fmt);
1620116198
1620216199 if (optimizationOrder != eRO_none)
@@ -16367,4 +16364,83 @@ emitter::RegisterOrder emitter::IsOptimizableLdrStrWithPair(
1636716364 return optimisationOrder;
1636816365}
1636916366
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+ }
1637016446#endif // defined(TARGET_ARM64)
0 commit comments