[llvm] Prevent undefined behavior caused by combination of branch and load delay slots on MIPS1 (PR #185427)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Mar 9 07:34:28 PDT 2026
https://github.com/JaberwockySeamonstah updated https://github.com/llvm/llvm-project/pull/185427
>From ddefd20de74620fc9fcc7092fe47d8b1452aa7a4 Mon Sep 17 00:00:00 2001
From: Jaby <jaby at william.zone>
Date: Sat, 7 Mar 2026 18:30:38 +0000
Subject: [PATCH] Disable filling delay slots with load delay slots commands
under MIPS1
---
llvm/lib/Target/Mips/MipsDelaySlotFiller.cpp | 29 ++++++++++++++++----
1 file changed, 24 insertions(+), 5 deletions(-)
diff --git a/llvm/lib/Target/Mips/MipsDelaySlotFiller.cpp b/llvm/lib/Target/Mips/MipsDelaySlotFiller.cpp
index f04ce53340c5d..d3965d3671e66 100644
--- a/llvm/lib/Target/Mips/MipsDelaySlotFiller.cpp
+++ b/llvm/lib/Target/Mips/MipsDelaySlotFiller.cpp
@@ -229,8 +229,8 @@ namespace {
/// This function checks if it is valid to move Candidate to the delay slot
/// and returns true if it isn't. It also updates memory and register
/// dependence information.
- bool delayHasHazard(const MachineInstr &Candidate, RegDefsUses &RegDU,
- InspectMemInstr &IM) const;
+ bool delayHasHazard(const MipsSubtarget& STI, const MachineInstr &Candidate,
+ RegDefsUses &RegDU, InspectMemInstr &IM) const;
/// This function searches range [Begin, End) for an instruction that can be
/// moved to the delay slot. Returns true on success.
@@ -789,10 +789,11 @@ bool MipsDelaySlotFiller::searchRange(MachineBasicBlock &MBB, IterTy Begin,
continue;
}
- if (delayHasHazard(*CurrI, RegDU, IM))
+ const MipsSubtarget &STI = MBB.getParent()->getSubtarget<MipsSubtarget>();
+
+ if (delayHasHazard(STI, *CurrI, RegDU, IM))
continue;
- const MipsSubtarget &STI = MBB.getParent()->getSubtarget<MipsSubtarget>();
bool InMicroMipsMode = STI.inMicroMipsMode();
const MipsInstrInfo *TII = STI.getInstrInfo();
unsigned Opcode = (*Slot).getOpcode();
@@ -1000,7 +1001,8 @@ bool MipsDelaySlotFiller::examinePred(MachineBasicBlock &Pred,
return true;
}
-bool MipsDelaySlotFiller::delayHasHazard(const MachineInstr &Candidate,
+bool MipsDelaySlotFiller::delayHasHazard(const MipsSubtarget& STI,
+ const MachineInstr &Candidate,
RegDefsUses &RegDU,
InspectMemInstr &IM) const {
assert(!Candidate.isKill() &&
@@ -1011,6 +1013,23 @@ bool MipsDelaySlotFiller::delayHasHazard(const MachineInstr &Candidate,
HasHazard |= IM.hasHazard(Candidate);
HasHazard |= RegDU.update(Candidate, 0, Candidate.getNumOperands());
+ if(STI.hasMips1()) {
+ const MipsInstrInfo* TII = STI.getInstrInfo();
+ const bool HasLoadDelaySlot = TII->HasLoadDelaySlot(Candidate);
+
+ // Having an instruction with a load delay slot in the branch delay slot
+ // seems to not check the load delay slots for hazards.
+ // Not allowing load delay slot commands in branch delays produces always
+ // valid code but may reduce optimization slightly.
+ //
+ // TODO: Ideally we would want to check the register being used in this command
+ // with the registers of the next command and for the jump target. If we can not
+ // locate the jump target, then we assume hazard.
+ if(HasLoadDelaySlot) {
+ return true;
+ }
+ }
+
return HasHazard;
}
More information about the llvm-commits
mailing list