[llvm] [ARM] Fold LDR/STR with base update to LDM/STD on Thumb1 (PR #78881)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Jan 25 23:53:34 PST 2024
https://github.com/AtariDreams updated https://github.com/llvm/llvm-project/pull/78881
>From f03acbc01654c9d943f790c020a32a42cb9e4616 Mon Sep 17 00:00:00 2001
From: Rose <83477269+AtariDreams at users.noreply.github.com>
Date: Sat, 20 Jan 2024 12:18:05 -0500
Subject: [PATCH] [ARM] Fold LDR/STR with base update to LDM/STD on Thumb1
This patch causes LLVM to fold Thumb1 base register updates after a store and load to be an LDM or STM. LDR and STR updates do not exist on Thumb1, so LDM/STM with single register is the next best thing.
---
llvm/lib/Target/ARM/ARMLoadStoreOptimizer.cpp | 36 ++++++++++++-------
1 file changed, 23 insertions(+), 13 deletions(-)
diff --git a/llvm/lib/Target/ARM/ARMLoadStoreOptimizer.cpp b/llvm/lib/Target/ARM/ARMLoadStoreOptimizer.cpp
index ed9d30c3c3ab90..2b3177e0d4287b 100644
--- a/llvm/lib/Target/ARM/ARMLoadStoreOptimizer.cpp
+++ b/llvm/lib/Target/ARM/ARMLoadStoreOptimizer.cpp
@@ -1356,7 +1356,7 @@ bool ARMLoadStoreOpt::MergeBaseUpdateLSMultiple(MachineInstr *MI) {
MIB.add(MO);
// Transfer memoperands.
- MIB.setMemRefs(MI->memoperands());
+ MIB.cloneMemRefs(*MI);
LLVM_DEBUG(dbgs() << " Added new load/store: " << *MIB);
MBB.erase(MBBI);
@@ -1366,6 +1366,10 @@ bool ARMLoadStoreOpt::MergeBaseUpdateLSMultiple(MachineInstr *MI) {
static unsigned getPreIndexedLoadStoreOpcode(unsigned Opc,
ARM_AM::AddrOpc Mode) {
switch (Opc) {
+ case ARM::tLDRi:
+ return ARM::tLDMIA_UPD;
+ case ARM::tSTRi:
+ return ARM::tSTMIA_UPD;
case ARM::LDRi12:
return ARM::LDR_PRE_IMM;
case ARM::STRi12:
@@ -1391,6 +1395,10 @@ static unsigned getPreIndexedLoadStoreOpcode(unsigned Opc,
static unsigned getPostIndexedLoadStoreOpcode(unsigned Opc,
ARM_AM::AddrOpc Mode) {
switch (Opc) {
+ case ARM::tLDRi:
+ return ARM::tLDMIA_UPD;
+ case ARM::tSTRi:
+ return ARM::tSTMIA_UPD;
case ARM::LDRi12:
return ARM::LDR_POST_IMM;
case ARM::STRi12:
@@ -1466,9 +1474,6 @@ static unsigned getPostIndexedLoadStoreOpcode(unsigned Opc,
/// Fold proceeding/trailing inc/dec of base register into the
/// LDR/STR/FLD{D|S}/FST{D|S} op when possible:
bool ARMLoadStoreOpt::MergeBaseUpdateLoadStore(MachineInstr *MI) {
- // Thumb1 doesn't have updating LDR/STR.
- // FIXME: Use LDM/STM with single register instead.
- if (isThumb1) return false;
LLVM_DEBUG(dbgs() << "Attempting to merge update of: " << *MI);
Register Base = getLoadStoreBaseOp(*MI).getReg();
@@ -1478,6 +1483,11 @@ bool ARMLoadStoreOpt::MergeBaseUpdateLoadStore(MachineInstr *MI) {
bool isAM5 = (Opcode == ARM::VLDRD || Opcode == ARM::VLDRS ||
Opcode == ARM::VSTRD || Opcode == ARM::VSTRS);
bool isAM2 = (Opcode == ARM::LDRi12 || Opcode == ARM::STRi12);
+ bool isAM2Thumb = (Opcode == ARM::tLDRi || Opcode == ARM::tSTRi);
+
+ // stm and ldm can only be used with hole words in Thumb1
+ if (isThumb1 && !isAM2Thumb)
+ return false;
if (isi32Load(Opcode) || isi32Store(Opcode))
if (MI->getOperand(2).getImm() != 0)
return false;
@@ -1495,8 +1505,8 @@ bool ARMLoadStoreOpt::MergeBaseUpdateLoadStore(MachineInstr *MI) {
MachineBasicBlock &MBB = *MI->getParent();
MachineBasicBlock::iterator MBBI(MI);
int Offset;
- MachineBasicBlock::iterator MergeInstr
- = findIncDecBefore(MBBI, Base, Pred, PredReg, Offset);
+ MachineBasicBlock::iterator MergeInstr =
+ findIncDecBefore(MBBI, Base, Pred, PredReg, Offset);
unsigned NewOpc;
if (!isAM5 && Offset == Bytes) {
NewOpc = getPreIndexedLoadStoreOpcode(Opcode, ARM_AM::add);
@@ -1504,14 +1514,13 @@ bool ARMLoadStoreOpt::MergeBaseUpdateLoadStore(MachineInstr *MI) {
NewOpc = getPreIndexedLoadStoreOpcode(Opcode, ARM_AM::sub);
} else {
MergeInstr = findIncDecAfter(MBBI, Base, Pred, PredReg, Offset, TRI);
- if (MergeInstr == MBB.end())
+ if (MergeInstr == MBB.end() || (isAM5 && Offset != Bytes))
return false;
NewOpc = getPostIndexedLoadStoreOpcode(Opcode, ARM_AM::add);
- if ((isAM5 && Offset != Bytes) ||
- (!isAM5 && !isLegalAddressImm(NewOpc, Offset, TII))) {
+ if (!isAM5 && !isLegalAddressImm(NewOpc, Offset, TII)) {
NewOpc = getPostIndexedLoadStoreOpcode(Opcode, ARM_AM::sub);
- if (isAM5 || !isLegalAddressImm(NewOpc, Offset, TII))
+ if (!isLegalAddressImm(NewOpc, Offset, TII))
return false;
}
}
@@ -1521,15 +1530,16 @@ bool ARMLoadStoreOpt::MergeBaseUpdateLoadStore(MachineInstr *MI) {
ARM_AM::AddrOpc AddSub = Offset < 0 ? ARM_AM::sub : ARM_AM::add;
bool isLd = isLoadSingle(Opcode);
- if (isAM5) {
+ if (isAM5 || isAM2Thumb) {
+ // Thumb1 doesn't have updating LDR/STR.
// VLDM[SD]_UPD, VSTM[SD]_UPD
// (There are no base-updating versions of VLDR/VSTR instructions, but the
// updating load/store-multiple instructions can be used with only one
// register.)
- MachineOperand &MO = MI->getOperand(0);
+ const MachineOperand &MO = getLoadStoreRegOp(*MI);
auto MIB = BuildMI(MBB, MBBI, DL, TII->get(NewOpc))
.addReg(Base, getDefRegState(true)) // WB base register
- .addReg(Base, getKillRegState(isLd ? BaseKill : false))
+ .addReg(Base, getKillRegState(isLd && BaseKill))
.addImm(Pred)
.addReg(PredReg)
.addReg(MO.getReg(), (isLd ? getDefRegState(true)
More information about the llvm-commits
mailing list