[llvm-branch-commits] [llvm] release/22.x: Prevent undefined behavior caused by combination of branch and load delay slots on MIPS1 (#185427) (PR #194224)

via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Sun Apr 26 02:59:07 PDT 2026


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-mips

Author: llvmbot

<details>
<summary>Changes</summary>

Backport 458e9c452c103189865632657504174b24b91630

Requested by: @<!-- -->RKSimon

---

Patch is 84.71 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/194224.diff


7 Files Affected:

- (modified) llvm/lib/Target/Mips/MipsDelaySlotFiller.cpp (+179-32) 
- (modified) llvm/lib/Target/Mips/MipsInstrInfo.cpp (+2-1) 
- (modified) llvm/test/CodeGen/Mips/gprestore.ll (+50) 
- (modified) llvm/test/CodeGen/Mips/llvm-ir/load.ll (+221-84) 
- (modified) llvm/test/CodeGen/Mips/llvm-ir/select-dbl.ll (+225-35) 
- (added) llvm/test/CodeGen/Mips/mips1-load-in-delay-slot.ll (+61) 
- (modified) llvm/test/CodeGen/Mips/unalignedload.ll (+62-6) 


``````````diff
diff --git a/llvm/lib/Target/Mips/MipsDelaySlotFiller.cpp b/llvm/lib/Target/Mips/MipsDelaySlotFiller.cpp
index 850d3b59be5de..7e52cf985f795 100644
--- a/llvm/lib/Target/Mips/MipsDelaySlotFiller.cpp
+++ b/llvm/lib/Target/Mips/MipsDelaySlotFiller.cpp
@@ -39,6 +39,7 @@
 #include "llvm/Support/CodeGen.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/raw_ostream.h"
 #include "llvm/Target/TargetMachine.h"
 #include <cassert>
 #include <iterator>
@@ -85,6 +86,87 @@ namespace {
   using ReverseIter = MachineBasicBlock::reverse_iterator;
   using BB2BrMap = SmallDenseMap<MachineBasicBlock *, MachineInstr *, 2>;
 
+  // Holds information about one branch instruction
+  // This is used by the MIPS1 target to easily find all paths of a branch to
+  // then check the first instruction for possible load delay hazards
+  class BranchInformation {
+  private:
+    // The pointer to the actual branch instruction
+    const MachineInstr *BranchInstr = nullptr;
+    // The pointer to the instruction after the branch (= the `else` case)
+    const MachineInstr *ElseBranchInstr = nullptr;
+
+    // Check if `Adr` is a pseudo instruction and if so, then treat it as non
+    // existing
+    static const MachineInstr *filterPseudoInstr(const MachineInstr *Adr) {
+      if (Adr && !Adr->isPseudo()) {
+        return Adr;
+      }
+      return nullptr;
+    }
+
+  public:
+    // Creates a new `BranchInformation` from the branch candidate `CurrentSlot`
+    // together with the end (`MBBEnd`) of the current MBB and the first
+    // instruction of the next MBB `NextMBBInstr`
+    BranchInformation(MachineInstrBundleIterator<MachineInstr> CurrentSlot,
+                      MachineInstrBundleIterator<MachineInstr> MBBEnd,
+                      const MachineInstr *NextMBBInstr)
+        : BranchInstr(
+              CurrentSlot->isBranch()
+                  ? BranchInformation::filterPseudoInstr(&(*CurrentSlot))
+                  : nullptr),
+          ElseBranchInstr(
+              (++CurrentSlot) == MBBEnd
+                  ? BranchInformation::filterPseudoInstr(NextMBBInstr)
+                  : BranchInformation::filterPseudoInstr(&(*CurrentSlot))) {}
+
+    // Checks if we have a branch
+    constexpr bool hasBranchInstr() const { return this->BranchInstr; }
+
+    // Checks if we have an else branch
+    constexpr bool hasBranchElseInstr() const { return this->ElseBranchInstr; }
+
+    // Checks if we have an indirect branch
+    constexpr bool isIndirectBranch() const {
+      if (this->BranchInstr) {
+        return this->BranchInstr->isIndirectBranch();
+      }
+      return false;
+    }
+
+    // Checks if we have an unconditional branch
+    constexpr bool isUnconditionalBranch() const {
+      if (this->BranchInstr) {
+        return this->BranchInstr->isUnconditionalBranch();
+      }
+      return false;
+    }
+
+    // Accesses the branch instruction
+    const MachineInstr *getBranchInstr() const { return this->BranchInstr; }
+
+    // Accesses the instruction after the branch
+    const MachineInstr *getBranchElseInstr() const {
+      return this->ElseBranchInstr;
+    }
+
+    // Gets the target of the branch
+    const MachineBasicBlock *getBranchTarget() const {
+      if (this->isIndirectBranch() || !this->hasBranchInstr()) {
+        // Indirect branch has no known target
+        return nullptr;
+      }
+
+      for (const MachineOperand &MO : this->BranchInstr->operands()) {
+        if (MO.isMBB()) {
+          return MO.getMBB();
+        }
+      }
+      return nullptr;
+    }
+  };
+
   class RegDefsUses {
   public:
     RegDefsUses(const TargetRegisterInfo &TRI);
@@ -195,8 +277,14 @@ namespace {
     bool runOnMachineFunction(MachineFunction &F) override {
       TM = &F.getTarget();
       bool Changed = false;
-      for (MachineBasicBlock &MBB : F)
-        Changed |= runOnMachineBasicBlock(MBB);
+      for (auto MBB = F.begin(); MBB != F.end();) {
+        auto curMBB = MBB;
+        MBB++;
+
+        Changed |= runOnMachineBasicBlock(
+            *curMBB, (MBB != F.end() && !(*MBB).empty()) ? &(*MBB).instr_front()
+                                                         : nullptr);
+      }
 
       // This pass invalidates liveness information when it reorders
       // instructions to fill delay slot. Without this, -verify-machineinstrs
@@ -219,7 +307,8 @@ namespace {
     static char ID;
 
   private:
-    bool runOnMachineBasicBlock(MachineBasicBlock &MBB);
+    bool runOnMachineBasicBlock(MachineBasicBlock &MBB,
+                                MachineInstr *FirstNextMBBInstr);
 
     Iter replaceWithCompactBranch(MachineBasicBlock &MBB, Iter Branch,
                                   const DebugLoc &DL);
@@ -227,28 +316,32 @@ 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,
+    bool delayHasHazard(const MipsSubtarget &STI, const MachineInstr &Candidate,
+                        const BranchInformation &BranchInfo, 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.
-    template<typename IterTy>
+    template <typename IterTy>
     bool searchRange(MachineBasicBlock &MBB, IterTy Begin, IterTy End,
-                     RegDefsUses &RegDU, InspectMemInstr &IM, Iter Slot,
-                     IterTy &Filler) const;
+                     const BranchInformation &BranchInfo, RegDefsUses &RegDU,
+                     InspectMemInstr &IM, Iter Slot, IterTy &Filler) const;
 
     /// This function searches in the backward direction for an instruction that
     /// can be moved to the delay slot. Returns true on success.
-    bool searchBackward(MachineBasicBlock &MBB, MachineInstr &Slot) const;
+    bool searchBackward(MachineBasicBlock &MBB, MachineInstr &Slot,
+                        const BranchInformation &BranchInfo) const;
 
     /// This function searches MBB in the forward direction for an instruction
     /// that can be moved to the delay slot. Returns true on success.
-    bool searchForward(MachineBasicBlock &MBB, Iter Slot) const;
+    bool searchForward(MachineBasicBlock &MBB, Iter Slot,
+                       const BranchInformation &BranchInfo) const;
 
     /// This function searches one of MBB's successor blocks for an instruction
     /// that can be moved to the delay slot and inserts clones of the
     /// instruction into the successor's predecessor blocks.
-    bool searchSuccBBs(MachineBasicBlock &MBB, Iter Slot) const;
+    bool searchSuccBBs(MachineBasicBlock &MBB, Iter Slot,
+                       const BranchInformation &BranchInfo) const;
 
     /// Pick a successor block of MBB. Return NULL if MBB doesn't have a
     /// successor block that is not a landing pad.
@@ -577,7 +670,8 @@ static int getEquivalentCallShort(int Opcode) {
 
 /// runOnMachineBasicBlock - Fill in delay slots for the given basic block.
 /// We assume there is only one delay slot per delayed instruction.
-bool MipsDelaySlotFiller::runOnMachineBasicBlock(MachineBasicBlock &MBB) {
+bool MipsDelaySlotFiller::runOnMachineBasicBlock(
+    MachineBasicBlock &MBB, MachineInstr *FirstNextMBBInstr) {
   bool Changed = false;
   const MipsSubtarget &STI = MBB.getParent()->getSubtarget<MipsSubtarget>();
   bool InMicroMipsMode = STI.inMicroMipsMode();
@@ -593,20 +687,22 @@ bool MipsDelaySlotFiller::runOnMachineBasicBlock(MachineBasicBlock &MBB) {
         !(InMicroMipsMode && STI.hasMips32r6())) {
 
       bool Filled = false;
+      const auto BranchInfo =
+          BranchInformation(I, MBB.end(), FirstNextMBBInstr);
 
       if (MipsCompactBranchPolicy.getValue() != CB_Always ||
            !TII->getEquivalentCompactForm(I)) {
-        if (searchBackward(MBB, *I)) {
+        if (searchBackward(MBB, *I, BranchInfo)) {
           LLVM_DEBUG(dbgs() << DEBUG_TYPE ": found instruction for delay slot"
                                           " in backwards search.\n");
           Filled = true;
         } else if (I->isTerminator()) {
-          if (searchSuccBBs(MBB, I)) {
+          if (searchSuccBBs(MBB, I, BranchInfo)) {
             Filled = true;
             LLVM_DEBUG(dbgs() << DEBUG_TYPE ": found instruction for delay slot"
                                             " in successor BB search.\n");
           }
-        } else if (searchForward(MBB, I)) {
+        } else if (searchForward(MBB, I, BranchInfo)) {
           LLVM_DEBUG(dbgs() << DEBUG_TYPE ": found instruction for delay slot"
                                           " in forwards search.\n");
           Filled = true;
@@ -660,15 +756,15 @@ bool MipsDelaySlotFiller::runOnMachineBasicBlock(MachineBasicBlock &MBB) {
     ++FilledSlots;
     Changed = true;
   }
-
   return Changed;
 }
 
 template <typename IterTy>
 bool MipsDelaySlotFiller::searchRange(MachineBasicBlock &MBB, IterTy Begin,
-                                      IterTy End, RegDefsUses &RegDU,
-                                      InspectMemInstr &IM, Iter Slot,
-                                      IterTy &Filler) const {
+                                      IterTy End,
+                                      const BranchInformation &BranchInfo,
+                                      RegDefsUses &RegDU, InspectMemInstr &IM,
+                                      Iter Slot, IterTy &Filler) const {
   for (IterTy I = Begin; I != End;) {
     IterTy CurrI = I;
     ++I;
@@ -704,10 +800,10 @@ bool MipsDelaySlotFiller::searchRange(MachineBasicBlock &MBB, IterTy Begin,
       continue;
     }
 
-    if (delayHasHazard(*CurrI, RegDU, IM))
+    const MipsSubtarget &STI = MBB.getParent()->getSubtarget<MipsSubtarget>();
+    if (delayHasHazard(STI, *CurrI, BranchInfo, RegDU, IM))
       continue;
 
-    const MipsSubtarget &STI = MBB.getParent()->getSubtarget<MipsSubtarget>();
     bool InMicroMipsMode = STI.inMicroMipsMode();
     const MipsInstrInfo *TII = STI.getInstrInfo();
     unsigned Opcode = (*Slot).getOpcode();
@@ -743,8 +839,9 @@ bool MipsDelaySlotFiller::searchRange(MachineBasicBlock &MBB, IterTy Begin,
   return false;
 }
 
-bool MipsDelaySlotFiller::searchBackward(MachineBasicBlock &MBB,
-                                         MachineInstr &Slot) const {
+bool MipsDelaySlotFiller::searchBackward(
+    MachineBasicBlock &MBB, MachineInstr &Slot,
+    const BranchInformation &BranchInfo) const {
   if (DisableBackwardSearch)
     return false;
 
@@ -756,8 +853,8 @@ bool MipsDelaySlotFiller::searchBackward(MachineBasicBlock &MBB,
   RegDU.init(Slot);
 
   MachineBasicBlock::iterator SlotI = Slot;
-  if (!searchRange(MBB, ++SlotI.getReverse(), MBB.rend(), RegDU, MemDU, Slot,
-                   Filler)) {
+  if (!searchRange(MBB, ++SlotI.getReverse(), MBB.rend(), BranchInfo, RegDU,
+                   MemDU, Slot, Filler)) {
     LLVM_DEBUG(dbgs() << DEBUG_TYPE ": could not find instruction for delay "
                                     "slot using backwards search.\n");
     return false;
@@ -769,8 +866,9 @@ bool MipsDelaySlotFiller::searchBackward(MachineBasicBlock &MBB,
   return true;
 }
 
-bool MipsDelaySlotFiller::searchForward(MachineBasicBlock &MBB,
-                                        Iter Slot) const {
+bool MipsDelaySlotFiller::searchForward(
+    MachineBasicBlock &MBB, Iter Slot,
+    const BranchInformation &BranchInfo) const {
   // Can handle only calls.
   if (DisableForwardSearch || !Slot->isCall())
     return false;
@@ -781,7 +879,8 @@ bool MipsDelaySlotFiller::searchForward(MachineBasicBlock &MBB,
 
   RegDU.setCallerSaved(*Slot);
 
-  if (!searchRange(MBB, std::next(Slot), MBB.end(), RegDU, NM, Slot, Filler)) {
+  if (!searchRange(MBB, std::next(Slot), MBB.end(), BranchInfo, RegDU, NM, Slot,
+                   Filler)) {
     LLVM_DEBUG(dbgs() << DEBUG_TYPE ": could not find instruction for delay "
                                     "slot using forwards search.\n");
     return false;
@@ -793,8 +892,9 @@ bool MipsDelaySlotFiller::searchForward(MachineBasicBlock &MBB,
   return true;
 }
 
-bool MipsDelaySlotFiller::searchSuccBBs(MachineBasicBlock &MBB,
-                                        Iter Slot) const {
+bool MipsDelaySlotFiller::searchSuccBBs(
+    MachineBasicBlock &MBB, Iter Slot,
+    const BranchInformation &BranchInfo) const {
   if (DisableSuccBBSearch)
     return false;
 
@@ -828,8 +928,8 @@ bool MipsDelaySlotFiller::searchSuccBBs(MachineBasicBlock &MBB,
     IM.reset(new MemDefsUses(&MFI));
   }
 
-  if (!searchRange(MBB, SuccBB->begin(), SuccBB->end(), RegDU, *IM, Slot,
-                   Filler))
+  if (!searchRange(MBB, SuccBB->begin(), SuccBB->end(), BranchInfo, RegDU, *IM,
+                   Slot, Filler))
     return false;
 
   insertDelayFiller(Filler, BrMap);
@@ -915,7 +1015,9 @@ bool MipsDelaySlotFiller::examinePred(MachineBasicBlock &Pred,
   return true;
 }
 
-bool MipsDelaySlotFiller::delayHasHazard(const MachineInstr &Candidate,
+bool MipsDelaySlotFiller::delayHasHazard(const MipsSubtarget &STI,
+                                         const MachineInstr &Candidate,
+                                         const BranchInformation &BranchInfo,
                                          RegDefsUses &RegDU,
                                          InspectMemInstr &IM) const {
   assert(!Candidate.isKill() &&
@@ -926,6 +1028,51 @@ bool MipsDelaySlotFiller::delayHasHazard(const MachineInstr &Candidate,
   HasHazard |= IM.hasHazard(Candidate);
   HasHazard |= RegDU.update(Candidate, 0, Candidate.getNumOperands());
 
+  // This only matters for MIPS1 and only if we do not have a hazard already
+  if (STI.hasMips1() && !STI.hasMips2() && !HasHazard) {
+    const MipsInstrInfo *TII = STI.getInstrInfo();
+    const bool HasLoadDelaySlot = TII->HasLoadDelaySlot(Candidate);
+
+    // We only need to act if the candidate is having a load delay slot
+    if (HasLoadDelaySlot) {
+      // We have no branch so we can not determine a hazard
+      // Assume the worst
+      if (!BranchInfo.hasBranchInstr()) {
+        return true;
+      }
+
+      // Being an indirect branch means we can not tell if we are a hazard
+      // Assume the worst
+      if (BranchInfo.isIndirectBranch()) {
+        return true;
+      }
+
+      // If this is a direct branch we should find a MBB operand for the jump
+      // target
+      const MachineBasicBlock *TargetMBB = BranchInfo.getBranchTarget();
+      if (!TargetMBB || TargetMBB->empty()) {
+        return true;
+      }
+
+      const auto &BranchTargetInstr = TargetMBB->instr_front();
+      bool HasNewHazard =
+          !TII->SafeInLoadDelaySlot(BranchTargetInstr, Candidate);
+      // If the branch is unconditional then we do not need to bother to check
+      // the next instruction after the branch
+      if (!BranchInfo.isUnconditionalBranch()) {
+        // We are a conditional branch so we should have an `else` branch
+        if (BranchInfo.hasBranchElseInstr()) {
+          HasNewHazard |= !TII->SafeInLoadDelaySlot(
+              *BranchInfo.getBranchElseInstr(), Candidate);
+        } else {
+          // Without the `else` branch we need to assume the worst
+          HasNewHazard = true;
+        }
+      }
+      return HasNewHazard;
+    }
+  }
+
   return HasHazard;
 }
 
diff --git a/llvm/lib/Target/Mips/MipsInstrInfo.cpp b/llvm/lib/Target/Mips/MipsInstrInfo.cpp
index c879c46e49dd4..6683408983acb 100644
--- a/llvm/lib/Target/Mips/MipsInstrInfo.cpp
+++ b/llvm/lib/Target/Mips/MipsInstrInfo.cpp
@@ -636,7 +636,8 @@ bool MipsInstrInfo::SafeInLoadDelaySlot(const MachineInstr &MIInSlot,
     return false;
 
   return !llvm::any_of(LoadMI.defs(), [&](const MachineOperand &Op) {
-    return Op.isReg() && MIInSlot.readsRegister(Op.getReg(), /*TRI=*/nullptr);
+    return Op.isReg() && MIInSlot.readsRegister(Op.getReg(), /*TRI=*/nullptr) &&
+           !MIInSlot.hasRegisterImplicitUseOperand(Op.getReg());
   });
 }
 
diff --git a/llvm/test/CodeGen/Mips/gprestore.ll b/llvm/test/CodeGen/Mips/gprestore.ll
index 889685022264b..674a197ca438f 100644
--- a/llvm/test/CodeGen/Mips/gprestore.ll
+++ b/llvm/test/CodeGen/Mips/gprestore.ll
@@ -5,6 +5,7 @@
 ; RUN: llc -mtriple=mips-mti-linux-gnu < %s -relocation-model=pic -O3 -mips-jalr-reloc=false | FileCheck %s --check-prefix=O3O32
 ; RUN: llc -mtriple=mips64-mti-linux-gnu < %s -relocation-model=pic -O3 -mips-jalr-reloc=false | FileCheck %s --check-prefix=O3N64
 ; RUN: llc -mtriple=mips64-mti-linux-gnu < %s -relocation-model=pic -target-abi n32 -O3 -mips-jalr-reloc=false | FileCheck %s --check-prefix=O3N32
+; RUN: llc -mtriple=mipsel-sony-psx -mcpu=mips1 < %s -relocation-model=pic | FileCheck %s -check-prefixes=MIPS1-PSX
 
 ; Test that PIC calls use the $25 register. This is an ABI requirement.
 
@@ -208,6 +209,55 @@ define void @f0() nounwind {
 ; O3N32-NEXT:    ld $ra, 24($sp) # 8-byte Folded Reload
 ; O3N32-NEXT:    jr $ra
 ; O3N32-NEXT:    addiu $sp, $sp, 32
+;
+; MIPS1-PSX-LABEL: f0:
+; MIPS1-PSX:       # %bb.0: # %entry
+; MIPS1-PSX-NEXT:    lui $2, %hi(_gp_disp)
+; MIPS1-PSX-NEXT:    addiu $2, $2, %lo(_gp_disp)
+; MIPS1-PSX-NEXT:    addiu $sp, $sp, -32
+; MIPS1-PSX-NEXT:    sw $ra, 28($sp) # 4-byte Folded Spill
+; MIPS1-PSX-NEXT:    sw $17, 24($sp) # 4-byte Folded Spill
+; MIPS1-PSX-NEXT:    sw $16, 20($sp) # 4-byte Folded Spill
+; MIPS1-PSX-NEXT:    addu $16, $2, $25
+; MIPS1-PSX-NEXT:    lw $25, %call16(f1)($16)
+; MIPS1-PSX-NEXT:    nop
+; MIPS1-PSX-NEXT:    .reloc $tmp0, R_MIPS_JALR, f1
+; MIPS1-PSX-NEXT:  $tmp0:
+; MIPS1-PSX-NEXT:    jalr $25
+; MIPS1-PSX-NEXT:    move $gp, $16
+; MIPS1-PSX-NEXT:    lw $1, %got(p)($16)
+; MIPS1-PSX-NEXT:    nop
+; MIPS1-PSX-NEXT:    lw $4, 0($1)
+; MIPS1-PSX-NEXT:    lw $25, %call16(f2)($16)
+; MIPS1-PSX-NEXT:    nop
+; MIPS1-PSX-NEXT:    .reloc $tmp1, R_MIPS_JALR, f2
+; MIPS1-PSX-NEXT:  $tmp1:
+; MIPS1-PSX-NEXT:    jalr $25
+; MIPS1-PSX-NEXT:    move $gp, $16
+; MIPS1-PSX-NEXT:    lw $1, %got(q)($16)
+; MIPS1-PSX-NEXT:    nop
+; MIPS1-PSX-NEXT:    lw $17, 0($1)
+; MIPS1-PSX-NEXT:    lw $25, %call16(f2)($16)
+; MIPS1-PSX-NEXT:    nop
+; MIPS1-PSX-NEXT:    .reloc $tmp2, R_MIPS_JALR, f2
+; MIPS1-PSX-NEXT:  $tmp2:
+; MIPS1-PSX-NEXT:    jalr $25
+; MIPS1-PSX-NEXT:    move $4, $17
+; MIPS1-PSX-NEXT:    lw $1, %got(r)($16)
+; MIPS1-PSX-NEXT:    nop
+; MIPS1-PSX-NEXT:    lw $5, 0($1)
+; MIPS1-PSX-NEXT:    lw $25, %call16(f3)($16)
+; MIPS1-PSX-NEXT:    move $4, $17
+; MIPS1-PSX-NEXT:    .reloc $tmp3, R_MIPS_JALR, f3
+; MIPS1-PSX-NEXT:  $tmp3:
+; MIPS1-PSX-NEXT:    jalr $25
+; MIPS1-PSX-NEXT:    move $gp, $16
+; MIPS1-PSX-NEXT:    lw $16, 20($sp) # 4-byte Folded Reload
+; MIPS1-PSX-NEXT:    lw $17, 24($sp) # 4-byte Folded Reload
+; MIPS1-PSX-NEXT:    lw $ra, 28($sp) # 4-byte Folded Reload
+; MIPS1-PSX-NEXT:    nop
+; MIPS1-PSX-NEXT:    jr $ra
+; MIPS1-PSX-NEXT:    addiu $sp, $sp, 32
 entry:
   tail call void @f1() nounwind
   %tmp = load i32, ptr @p, align 4
diff --git a/llvm/test/CodeGen/Mips/llvm-ir/load.ll b/llvm/test/CodeGen/Mips/llvm-ir/load.ll
index f81e1a742e44c..834880f1ad74e 100644
--- a/llvm/test/CodeGen/Mips/llvm-ir/load.ll
+++ b/llvm/test/CodeGen/Mips/llvm-ir/load.ll
@@ -8,6 +8,7 @@
 ; RUN: llc -mtriple=mips64-img-linux-gnu -mcpu=mips64r6 < %s -asm-show-inst | FileCheck %s --check-prefix=MIPS64R6
 ; RUN: llc -mtriple=mips-mti-linux-gnu -mcpu=mips32r2 -mattr=+micromips,+fp64 < %s -asm-show-inst | FileCheck %s --check-prefix=MMR5FP64
 ; RUN: llc -mtriple=mips-mti-linux-gnu -mcpu=mips32r5 -mattr=+fp64 < %s -asm-show-inst | FileCheck %s --check-prefix=MIPS32R5FP643
+; RUN: llc -mtriple=mipsel-sony-psx -mcpu=mips1 < %s -asm-show-inst | FileCheck %s -check-prefixes=MIPS1-PSX
 
 ; Test subword and word loads. We use -asm-show-inst to test that the produced
 ; instructions match the expected ISA.
@@ -180,6 +181,22 @@ define i8 @f1() {
 ; MIPS32R5FP643-NEXT:    # <MCOperand Reg:V0>
 ; MIPS32R5FP643-NEXT:    # <MCOperand Reg:AT>
 ; MIPS32R5FP643-NEXT:    # <MCOperand Expr:%lo(a)>>
+;
+; MIPS1-PSX-LABEL: f1:
+; MIPS1-PSX:       # %bb.0: # %entry
+; MIPS1-PSX-NEXT:    lui $1, %hi(a) # <MCInst #[[#MCINST1:]] LUi
+; MIPS1-PSX-NEXT:    # <MCOperand Reg:AT>
+; MIPS1-PSX-NEXT:    # <MCOperand Expr:%hi(a)>>
+; MIPS1-PSX-NE...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/194224


More information about the llvm-branch-commits mailing list