[llvm] [Mips][ASM] Optimize SW+ADDIU (PR #144997)
via llvm-commits
llvm-commits at lists.llvm.org
Fri Jun 20 01:43:34 PDT 2025
https://github.com/yingopq created https://github.com/llvm/llvm-project/pull/144997
We want to optimize
`sw $4, 0($2)
addiu $2, $2, 4
bne $2, $3, $BB0_1`
to
`addiu $2, $2, 4
sw $4, -4($2)
bne $2, $3, $BB0_1`,
so that the sw can be placed into delay slot.
Fix #132685.
>From 1c055e8ca72274a13a906d77b7e7d272eaf009ed Mon Sep 17 00:00:00 2001
From: Ying Huang <ying.huang at oss.cipunited.com>
Date: Fri, 20 Jun 2025 04:34:53 -0400
Subject: [PATCH] [Mips][ASM] Optimize SW+ADDIU
We want to optimize
`sw $4, 0($2)
addiu $2, $2, 4
bne $2, $3, $BB0_1`
to
`addiu $2, $2, 4
sw $4, -4($2)
bne $2, $3, $BB0_1`,
so that the sw can be placed into delay slot.
Fix #132685.
---
.../Target/Mips/AsmParser/MipsAsmParser.cpp | 124 +++++++++++++++++-
llvm/test/MC/Mips/sw-add-bne.s | 13 ++
2 files changed, 135 insertions(+), 2 deletions(-)
create mode 100644 llvm/test/MC/Mips/sw-add-bne.s
diff --git a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
index 640ae52d05dd1..2aeb868ad3794 100644
--- a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
+++ b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
@@ -146,6 +146,19 @@ class MipsAsmParser : public MCTargetAsmParser {
// nullptr, which indicates that no function is currently
// selected. This usually happens after an '.end func'
// directive.
+ // Because we want do `sw $4, 0($2)
+ // addiu $2, $2, 4
+ // bne $2, $3, $BB0_1`
+ // to
+ // `addiu $2, $2, 4
+ // sw $4, -4($2)
+ // bne $2, $3, $BB0_1`,
+ // so that the sw can be placed into delay slot.
+ // If true, reprents inst `addiu` following inst `sw`, and save inst
+ // `sw`. Later we will check if inst 'bne' following inst `addiu`.
+ bool saveCurInst;
+ MCInst CurInst;
+
bool IsLittleEndian;
bool IsPicEnabled;
bool IsCpRestoreSet;
@@ -351,6 +364,9 @@ class MipsAsmParser : public MCTargetAsmParser {
bool expandSaaAddr(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
const MCSubtargetInfo *STI);
+ MipsAsmParser::MacroExpanderResultTy expandSW(MCInst &Inst, SMLoc IDLoc,
+ MCStreamer &Out,
+ const MCSubtargetInfo *STI);
bool reportParseError(const Twine &ErrorMsg);
bool reportParseError(SMLoc Loc, const Twine &ErrorMsg);
@@ -550,6 +566,7 @@ class MipsAsmParser : public MCTargetAsmParser {
report_fatal_error("-mno-odd-spreg requires the O32 ABI");
CurrentFn = nullptr;
+ saveCurInst = false;
CurForbiddenSlotAttr = false;
IsPicEnabled = getContext().getObjectFileInfo()->isPositionIndependent();
@@ -2572,8 +2589,82 @@ MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
int64_t ImmValue = Inst.getOperand(2).getImm();
- if (isInt<16>(ImmValue))
- return MER_NotAMacro;
+ if (isInt<16>(ImmValue)) {
+ if (saveCurInst == true) {
+ AsmToken ID = getTok();
+ saveCurInst = false;
+ bool doLex = false;
+
+ // If this is a line comment we can drop it safely.
+ while (getLexer().is(AsmToken::EndOfStatement)) {
+ doLex = true;
+ getLexer().Lex();
+ }
+
+ // Get last inst `sw` register info and offset value.
+ MipsTargetStreamer &TOut = getTargetStreamer();
+ MCRegister FirstReg = CurInst.getOperand(0).getReg();
+ MCRegister BaseReg = CurInst.getOperand(1).getReg();
+ MCOperand &OffsetImmOp = CurInst.getOperand(2);
+ unsigned OffsetValue = OffsetImmOp.getImm();
+
+ // Optimize `sw $4, 0($2)
+ // addiu $2, $2, 4
+ // bne $2, $3, $BB0_1`
+ // to
+ // `addiu $2, $2, 4
+ // sw $4, -4($2)
+ // bne $2, $3, $BB0_1`.
+ // If match sw+addiu+bne, then emit addiu+sw.
+ if (getTok().getString() == "bne") {
+ if (OffsetValue != 0) {
+ // Back to initial location before return.
+ if (doLex == true)
+ getLexer().UnLex(ID);
+ // If not match, we need to emit the last reserved instruction
+ // `sw`.
+ TOut.emitRRI(CurInst.getOpcode(), FirstReg, BaseReg, OffsetValue,
+ IDLoc, STI);
+ return MER_NotAMacro;
+ }
+
+ // Get inst `addiu` register info and imm value.
+ MCRegister destReg = Inst.getOperand(0).getReg();
+ MCRegister srcReg = Inst.getOperand(1).getReg();
+ unsigned addImm = Inst.getOperand(2).getImm();
+
+ if (destReg == srcReg && BaseReg == destReg && addImm == 4) {
+ // Emit addiu+sw.
+ TOut.emitRRI(Inst.getOpcode(), destReg, srcReg, addImm, IDLoc,
+ STI);
+ TOut.emitRRI(CurInst.getOpcode(), FirstReg, BaseReg,
+ OffsetValue - addImm, IDLoc, STI);
+ // Back to initial location before return.
+ if (doLex == true)
+ getLexer().UnLex(ID);
+ return MER_Success;
+ } else {
+ // Back to initial location before return.
+ if (doLex == true)
+ getLexer().UnLex(ID);
+ // If not match, we need to emit the last reserved instruction
+ // `sw`.
+ TOut.emitRRI(CurInst.getOpcode(), FirstReg, BaseReg, OffsetValue,
+ IDLoc, STI);
+ return MER_NotAMacro;
+ }
+ } else {
+ // Back to initial location before return.
+ if (doLex == true)
+ getLexer().UnLex(ID);
+ // If not match, we need to emit the last reserved instruction `sw`.
+ TOut.emitRRI(CurInst.getOpcode(), FirstReg, BaseReg, OffsetValue,
+ IDLoc, STI);
+ return MER_NotAMacro;
+ }
+ } else
+ return MER_NotAMacro;
+ }
return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail
: MER_Success;
}
@@ -2646,6 +2737,8 @@ MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
case Mips::SaaAddr:
case Mips::SaadAddr:
return expandSaaAddr(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
+ case Mips::SW:
+ return expandSW(Inst, IDLoc, Out, STI);
}
}
@@ -5280,6 +5373,33 @@ bool MipsAsmParser::expandDMULMacro(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
return false;
}
+// Check if match sw+addiu.
+MipsAsmParser::MacroExpanderResultTy
+MipsAsmParser::expandSW(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
+ const MCSubtargetInfo *STI) {
+ AsmToken ID = getTok();
+ bool doLex = false;
+
+ // If this is a line comment we can drop it safely.
+ while (getLexer().is(AsmToken::EndOfStatement)) {
+ getLexer().Lex();
+ doLex = true;
+ }
+ // If match sw+addiu, then save current Inst,
+ // and back to initial location before return.
+ if (getTok().getString() == "addiu") {
+ if (doLex == true)
+ getLexer().UnLex(ID);
+ CurInst = Inst;
+ saveCurInst = true;
+ return MER_Success;
+ } else {
+ if (doLex == true)
+ getLexer().UnLex(ID);
+ return MER_NotAMacro;
+ }
+}
+
// Expand 'ld $<reg> offset($reg2)' to 'lw $<reg>, offset($reg2);
// lw $<reg+1>>, offset+4($reg2)'
// or expand 'sd $<reg> offset($reg2)' to 'sw $<reg>, offset($reg2);
diff --git a/llvm/test/MC/Mips/sw-add-bne.s b/llvm/test/MC/Mips/sw-add-bne.s
new file mode 100644
index 0000000000000..b4a739db7419b
--- /dev/null
+++ b/llvm/test/MC/Mips/sw-add-bne.s
@@ -0,0 +1,13 @@
+# RUN: llvm-mc -assemble -mcpu=mips32r6 -arch=mipsel -filetype=obj %s -o tmp.o
+# RUN: llvm-objdump -d tmp.o | FileCheck %s --check-prefix=MIPSELR6
+
+# MIPSELR6: 00000000 <xxx>:
+# MIPSELR6-NEXT: addiu $2, $2, 0x4 <xxx+0x4>
+# MIPSELR6-NEXT: sw $4, -0x4($2)
+# MIPSELR6-NEXT: bne $2, $3, 0x0 <xxx>
+# MIPSELR6-NEXT: nop <xxx>
+xxx:
+$BB0_1: # %for.body
+ sw $4, 0($2)
+ addiu $2, $2, 4
+ bne $2, $3, $BB0_1
More information about the llvm-commits
mailing list