Skip to content

Commit 1d03a1b

Browse files
committed
[AArch64] Optimize MOV to ORR when load symmetric constants (#51483)
This change looks for cases of symmetric constant loading. `symmetric constant load` is when the upper 32 bits and lower 32 bits of a 64-bit register load the same value. When it finds this, it replaces it with an instruction that loads only the lower 32 bits of the constant and stores it in the upper and lower bits simultaneously. For example: renamable $x8 = MOVZXi 49370, 0 renamable $x8 = MOVKXi $x8, 320, 16 renamable $x8 = MOVKXi $x8, 49370, 32 renamable $x8 = MOVKXi $x8, 320, 48 becomes renamable $x8 = MOVZXi 49370, 0 renamable $x8 = MOVKXi $x8, 320, 16 renamable $x8 = ORRXrs $x8, $x8, 32
1 parent 16bb253 commit 1d03a1b

File tree

3 files changed

+25
-4
lines changed

3 files changed

+25
-4
lines changed

llvm/lib/Target/AArch64/AArch64ExpandImm.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -509,6 +509,16 @@ static inline void expandMOVImmSimple(uint64_t Imm, unsigned BitSize,
509509
Imm = ~Imm;
510510

511511
unsigned Opc = (BitSize == 32 ? AArch64::MOVKWi : AArch64::MOVKXi);
512+
Shift += 16;
513+
Imm16 = (Imm >> Shift) & Mask;
514+
if (Imm16 != (isNeg ? Mask : 0))
515+
Insn.push_back(
516+
{Opc, Imm16, AArch64_AM::getShifterImm(AArch64_AM::LSL, Shift)});
517+
if (Imm != 0 && (Imm >> 32) == (Imm & UINT_MAX)) {
518+
Insn.push_back({BitSize == 32 ? AArch64::ORRWrs : AArch64::ORRXrs, 0, 32});
519+
return;
520+
}
521+
512522
while (Shift < LastShift) {
513523
Shift += 16;
514524
Imm16 = (Imm >> Shift) & Mask;

llvm/lib/Target/AArch64/AArch64ExpandPseudoInsts.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,19 @@ bool AArch64ExpandPseudo::expandMOVImm(MachineBasicBlock &MBB,
168168
.addImm(I->Op2));
169169
}
170170
break;
171+
case AArch64::ORRWrs:
172+
case AArch64::ORRXrs: {
173+
Register DstReg = MI.getOperand(0).getReg();
174+
bool DstIsDead = MI.getOperand(0).isDead();
175+
MIBS.push_back(
176+
BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(I->Opcode))
177+
.addReg(DstReg, RegState::Define |
178+
getDeadRegState(DstIsDead && LastItem) |
179+
RenamableState)
180+
.addReg(DstReg)
181+
.addReg(DstReg)
182+
.addImm(I->Op2));
183+
} break;
171184
case AArch64::ANDXri:
172185
case AArch64::EORXri:
173186
if (I->Op1 == 0) {

llvm/test/CodeGen/AArch64/movimm-expand-ldst.mir

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,7 @@ body: |
1111
; CHECK-NEXT: {{ $}}
1212
; CHECK-NEXT: renamable $x0 = MOVZXi 49370, 0
1313
; CHECK-NEXT: renamable $x0 = MOVKXi $x0, 320, 16
14-
; CHECK-NEXT: renamable $x0 = MOVKXi $x0, 49370, 32
15-
; CHECK-NEXT: renamable $x0 = MOVKXi $x0, 320, 48
14+
; CHECK-NEXT: renamable $x0 = ORRXrs $x0, $x0, 32
1615
; CHECK-NEXT: RET undef $lr, implicit $x0
1716
renamable $x0 = MOVi64imm 90284035103834330
1817
RET_ReallyLR implicit $x0
@@ -28,8 +27,7 @@ body: |
2827
; CHECK-NEXT: {{ $}}
2928
; CHECK-NEXT: renamable $x0 = MOVZXi 320, 0
3029
; CHECK-NEXT: renamable $x0 = MOVKXi $x0, 49370, 16
31-
; CHECK-NEXT: renamable $x0 = MOVKXi $x0, 320, 32
32-
; CHECK-NEXT: renamable $x0 = MOVKXi $x0, 49370, 48
30+
; CHECK-NEXT: renamable $x0 = ORRXrs $x0, $x0, 32
3331
; CHECK-NEXT: RET undef $lr, implicit $x0
3432
renamable $x0 = MOVi64imm -4550323095879417536
3533
RET_ReallyLR implicit $x0

0 commit comments

Comments
 (0)