From 458e9c452c103189865632657504174b24b91630 Mon Sep 17 00:00:00 2001 From: JaberwockySeamonstah <76793519+JaberwockySeamonstah@users.noreply.github.com> Date: Tue, 21 Apr 2026 02:32:35 +0100 Subject: [PATCH] Prevent undefined behavior caused by combination of branch and load delay slots on MIPS1 (#185427) Under certain conditions the LLVM `MipsDelaySlotFiller` fills a branch delay slot with an instruction requiring a load delay slot. However the `MipsDelaySlotFiller` does not check the filled instruction for hazard which leads to code like this: ```asm beqz $1, $BB0_5 lbu $2, %lo(_RNvCs5jWYnRsDZoD_3app13CONTROLLERS_A)($2) # --- Some other instructions $BB0_5: andi $1, $2, 1 ``` `lbu` got moved into the branch delay slot but has a load delay slot - so when jumping to `$BB0_5` the value for `$2` will not be ready, which leads to undefined behavior. This PR suggests to declare instructions with a load delay slot to be hazardous for the branch delay slot, only for `MIPS1`. This will prevent the load instructions in the branch delay slot, which has a slight impact on the optimization. Ideally in case of a load instruction in a branch delay slot, we would want to check the target register and check if it is used in the following instruction and at the branch destination instruction. Code for this is already in place from a previous PR (`bool MipsInstrInfo::SafeInLoadDelaySlot(const MachineInstr &MIInSlot, const MachineInstr &LoadMI) const`), however I'm not experienced enough with the LLVM to identify the `MachineInstr` required for that ideal situation. If I could get some feedback about this I might be able to stitch it in. The original issue came from Rust and is described [here rust issue 150676](https://github.com/rust-lang/rust/issues/150676). It was then raised in the LLVM project [here issue 180639](https://github.com/llvm/llvm-project/issues/180639#issuecomment-3874380424) and in the forum [here](https://discourse.llvm.org/t/where-to-start-fixing-an-opt-pass-for-mips1/89857). Co-authored-by: Jaby --- llvm/lib/Target/Mips/MipsDelaySlotFiller.cpp | 211 ++++++++++-- llvm/lib/Target/Mips/MipsInstrInfo.cpp | 3 +- llvm/test/CodeGen/Mips/gprestore.ll | 50 +++ llvm/test/CodeGen/Mips/llvm-ir/load.ll | 305 +++++++++++++----- llvm/test/CodeGen/Mips/llvm-ir/select-dbl.ll | 260 +++++++++++++-- .../CodeGen/Mips/mips1-load-in-delay-slot.ll | 61 ++++ llvm/test/CodeGen/Mips/unalignedload.ll | 68 +++- 7 files changed, 800 insertions(+), 158 deletions(-) create mode 100644 llvm/test/CodeGen/Mips/mips1-load-in-delay-slot.ll diff --git a/llvm/lib/Target/Mips/MipsDelaySlotFiller.cpp b/llvm/lib/Target/Mips/MipsDelaySlotFiller.cpp index f04ce53340c5..bcfaa7cd2ed2 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 #include @@ -87,6 +88,87 @@ namespace { using ReverseIter = MachineBasicBlock::reverse_iterator; using BB2BrMap = SmallDenseMap; + // 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 CurrentSlot, + MachineInstrBundleIterator 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); @@ -197,8 +279,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 @@ -221,7 +309,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); @@ -229,28 +318,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 + template 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. @@ -650,7 +743,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(); bool InMicroMipsMode = STI.inMicroMipsMode(); @@ -678,20 +772,22 @@ bool MipsDelaySlotFiller::runOnMachineBasicBlock(MachineBasicBlock &MBB) { !(InMicroMipsMode && STI.hasMips32r6()) && !SkipForFixR5900) { 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; @@ -745,15 +841,15 @@ bool MipsDelaySlotFiller::runOnMachineBasicBlock(MachineBasicBlock &MBB) { ++FilledSlots; Changed = true; } - return Changed; } template 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; @@ -789,10 +885,10 @@ bool MipsDelaySlotFiller::searchRange(MachineBasicBlock &MBB, IterTy Begin, continue; } - if (delayHasHazard(*CurrI, RegDU, IM)) + const MipsSubtarget &STI = MBB.getParent()->getSubtarget(); + if (delayHasHazard(STI, *CurrI, BranchInfo, RegDU, IM)) continue; - const MipsSubtarget &STI = MBB.getParent()->getSubtarget(); bool InMicroMipsMode = STI.inMicroMipsMode(); const MipsInstrInfo *TII = STI.getInstrInfo(); unsigned Opcode = (*Slot).getOpcode(); @@ -828,8 +924,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; @@ -841,8 +938,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; @@ -854,8 +951,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; @@ -866,7 +964,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; @@ -878,8 +977,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; @@ -913,8 +1013,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); @@ -1000,7 +1100,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() && @@ -1011,6 +1113,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 c08c963a33c7..d1a47750d23d 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 889685022264..674a197ca438 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 f81e1a742e44..834880f1ad74 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: # ; MIPS32R5FP643-NEXT: # ; MIPS32R5FP643-NEXT: # > +; +; MIPS1-PSX-LABEL: f1: +; MIPS1-PSX: # %bb.0: # %entry +; MIPS1-PSX-NEXT: lui $1, %hi(a) # +; MIPS1-PSX-NEXT: # > +; MIPS1-PSX-NEXT: lbu $2, %lo(a)($1) # +; MIPS1-PSX-NEXT: # +; MIPS1-PSX-NEXT: # > +; MIPS1-PSX-NEXT: jr $ra # > +; MIPS1-PSX-NEXT: nop # +; MIPS1-PSX-NEXT: # +; MIPS1-PSX-NEXT: # > entry: %0 = load i8, ptr @a ret i8 %0 @@ -193,7 +210,7 @@ define i32 @f2() { ; MIPS32-NEXT: # > ; MIPS32-NEXT: jr $ra # > -; MIPS32-NEXT: lb $2, %lo(a)($1) # ; MIPS32-NEXT: # ; MIPS32-NEXT: # > @@ -205,7 +222,7 @@ define i32 @f2() { ; MMR3-NEXT: # > ; MMR3-NEXT: jr $ra # > -; MMR3-NEXT: lb $2, %lo(a)($1) # ; MMR3-NEXT: # ; MMR3-NEXT: # > @@ -218,7 +235,7 @@ define i32 @f2() { ; MIPS32R6-NEXT: jr $ra # ; MIPS32R6-NEXT: # > -; MIPS32R6-NEXT: lb $2, %lo(a)($1) # ; MIPS32R6-NEXT: # ; MIPS32R6-NEXT: # > @@ -228,7 +245,7 @@ define i32 @f2() { ; MMR6-NEXT: lui $1, %hi(a) # ; MMR6-NEXT: # > -; MMR6-NEXT: lb $2, %lo(a)($1) # ; MMR6-NEXT: # ; MMR6-NEXT: # > @@ -258,7 +275,7 @@ define i32 @f2() { ; MIPS3-NEXT: # > ; MIPS3-NEXT: jr $ra # > -; MIPS3-NEXT: lb $2, %lo(a)($1) # ; MIPS3-NEXT: # ; MIPS3-NEXT: # > @@ -286,7 +303,7 @@ define i32 @f2() { ; MIPS64-NEXT: # > ; MIPS64-NEXT: jr $ra # > -; MIPS64-NEXT: lb $2, %lo(a)($1) # ; MIPS64-NEXT: # ; MIPS64-NEXT: # > @@ -315,7 +332,7 @@ define i32 @f2() { ; MIPS64R6-NEXT: jr $ra # ; MIPS64R6-NEXT: # > -; MIPS64R6-NEXT: lb $2, %lo(a)($1) # ; MIPS64R6-NEXT: # ; MIPS64R6-NEXT: # > @@ -327,7 +344,7 @@ define i32 @f2() { ; MMR5FP64-NEXT: # > ; MMR5FP64-NEXT: jr $ra # > -; MMR5FP64-NEXT: lb $2, %lo(a)($1) # ; MMR5FP64-NEXT: # ; MMR5FP64-NEXT: # > @@ -339,10 +356,26 @@ define i32 @f2() { ; MIPS32R5FP643-NEXT: # > ; MIPS32R5FP643-NEXT: jr $ra # > -; MIPS32R5FP643-NEXT: lb $2, %lo(a)($1) # ; MIPS32R5FP643-NEXT: # ; MIPS32R5FP643-NEXT: # > +; +; MIPS1-PSX-LABEL: f2: +; MIPS1-PSX: # %bb.0: # %entry +; MIPS1-PSX-NEXT: lui $1, %hi(a) # +; MIPS1-PSX-NEXT: # > +; MIPS1-PSX-NEXT: lb $2, %lo(a)($1) # +; MIPS1-PSX-NEXT: # +; MIPS1-PSX-NEXT: # > +; MIPS1-PSX-NEXT: jr $ra # > +; MIPS1-PSX-NEXT: nop # +; MIPS1-PSX-NEXT: # +; MIPS1-PSX-NEXT: # > entry: %0 = load i8, ptr @a %1 = sext i8 %0 to i32 @@ -357,7 +390,7 @@ define i16 @f3() { ; MIPS32-NEXT: # > ; MIPS32-NEXT: jr $ra # > -; MIPS32-NEXT: lhu $2, %lo(b)($1) # ; MIPS32-NEXT: # ; MIPS32-NEXT: # > @@ -369,7 +402,7 @@ define i16 @f3() { ; MMR3-NEXT: # > ; MMR3-NEXT: jr $ra # > -; MMR3-NEXT: lhu $2, %lo(b)($1) # ; MMR3-NEXT: # ; MMR3-NEXT: # > @@ -382,7 +415,7 @@ define i16 @f3() { ; MIPS32R6-NEXT: jr $ra # ; MIPS32R6-NEXT: # > -; MIPS32R6-NEXT: lhu $2, %lo(b)($1) # ; MIPS32R6-NEXT: # ; MIPS32R6-NEXT: # > @@ -392,7 +425,7 @@ define i16 @f3() { ; MMR6-NEXT: lui $1, %hi(b) # ; MMR6-NEXT: # > -; MMR6-NEXT: lhu $2, %lo(b)($1) # ; MMR6-NEXT: # ; MMR6-NEXT: # > @@ -422,7 +455,7 @@ define i16 @f3() { ; MIPS3-NEXT: # > ; MIPS3-NEXT: jr $ra # > -; MIPS3-NEXT: lhu $2, %lo(b)($1) # ; MIPS3-NEXT: # ; MIPS3-NEXT: # > @@ -450,7 +483,7 @@ define i16 @f3() { ; MIPS64-NEXT: # > ; MIPS64-NEXT: jr $ra # > -; MIPS64-NEXT: lhu $2, %lo(b)($1) # ; MIPS64-NEXT: # ; MIPS64-NEXT: # > @@ -479,7 +512,7 @@ define i16 @f3() { ; MIPS64R6-NEXT: jr $ra # ; MIPS64R6-NEXT: # > -; MIPS64R6-NEXT: lhu $2, %lo(b)($1) # ; MIPS64R6-NEXT: # ; MIPS64R6-NEXT: # > @@ -491,7 +524,7 @@ define i16 @f3() { ; MMR5FP64-NEXT: # > ; MMR5FP64-NEXT: jr $ra # > -; MMR5FP64-NEXT: lhu $2, %lo(b)($1) # ; MMR5FP64-NEXT: # ; MMR5FP64-NEXT: # > @@ -503,10 +536,26 @@ define i16 @f3() { ; MIPS32R5FP643-NEXT: # > ; MIPS32R5FP643-NEXT: jr $ra # > -; MIPS32R5FP643-NEXT: lhu $2, %lo(b)($1) # ; MIPS32R5FP643-NEXT: # ; MIPS32R5FP643-NEXT: # > +; +; MIPS1-PSX-LABEL: f3: +; MIPS1-PSX: # %bb.0: # %entry +; MIPS1-PSX-NEXT: lui $1, %hi(b) # +; MIPS1-PSX-NEXT: # > +; MIPS1-PSX-NEXT: lhu $2, %lo(b)($1) # +; MIPS1-PSX-NEXT: # +; MIPS1-PSX-NEXT: # > +; MIPS1-PSX-NEXT: jr $ra # > +; MIPS1-PSX-NEXT: nop # +; MIPS1-PSX-NEXT: # +; MIPS1-PSX-NEXT: # > entry: %0 = load i16, ptr @b ret i16 %0 @@ -520,7 +569,7 @@ define i32 @f4() { ; MIPS32-NEXT: # > ; MIPS32-NEXT: jr $ra # > -; MIPS32-NEXT: lh $2, %lo(b)($1) # ; MIPS32-NEXT: # ; MIPS32-NEXT: # > @@ -532,7 +581,7 @@ define i32 @f4() { ; MMR3-NEXT: # > ; MMR3-NEXT: jr $ra # > -; MMR3-NEXT: lh $2, %lo(b)($1) # ; MMR3-NEXT: # ; MMR3-NEXT: # > @@ -545,7 +594,7 @@ define i32 @f4() { ; MIPS32R6-NEXT: jr $ra # ; MIPS32R6-NEXT: # > -; MIPS32R6-NEXT: lh $2, %lo(b)($1) # ; MIPS32R6-NEXT: # ; MIPS32R6-NEXT: # > @@ -555,7 +604,7 @@ define i32 @f4() { ; MMR6-NEXT: lui $1, %hi(b) # ; MMR6-NEXT: # > -; MMR6-NEXT: lh $2, %lo(b)($1) # ; MMR6-NEXT: # ; MMR6-NEXT: # > @@ -585,7 +634,7 @@ define i32 @f4() { ; MIPS3-NEXT: # > ; MIPS3-NEXT: jr $ra # > -; MIPS3-NEXT: lh $2, %lo(b)($1) # ; MIPS3-NEXT: # ; MIPS3-NEXT: # > @@ -613,7 +662,7 @@ define i32 @f4() { ; MIPS64-NEXT: # > ; MIPS64-NEXT: jr $ra # > -; MIPS64-NEXT: lh $2, %lo(b)($1) # ; MIPS64-NEXT: # ; MIPS64-NEXT: # > @@ -642,7 +691,7 @@ define i32 @f4() { ; MIPS64R6-NEXT: jr $ra # ; MIPS64R6-NEXT: # > -; MIPS64R6-NEXT: lh $2, %lo(b)($1) # ; MIPS64R6-NEXT: # ; MIPS64R6-NEXT: # > @@ -654,7 +703,7 @@ define i32 @f4() { ; MMR5FP64-NEXT: # > ; MMR5FP64-NEXT: jr $ra # > -; MMR5FP64-NEXT: lh $2, %lo(b)($1) # ; MMR5FP64-NEXT: # ; MMR5FP64-NEXT: # > @@ -666,10 +715,26 @@ define i32 @f4() { ; MIPS32R5FP643-NEXT: # > ; MIPS32R5FP643-NEXT: jr $ra # > -; MIPS32R5FP643-NEXT: lh $2, %lo(b)($1) # ; MIPS32R5FP643-NEXT: # ; MIPS32R5FP643-NEXT: # > +; +; MIPS1-PSX-LABEL: f4: +; MIPS1-PSX: # %bb.0: # %entry +; MIPS1-PSX-NEXT: lui $1, %hi(b) # +; MIPS1-PSX-NEXT: # > +; MIPS1-PSX-NEXT: lh $2, %lo(b)($1) # +; MIPS1-PSX-NEXT: # +; MIPS1-PSX-NEXT: # > +; MIPS1-PSX-NEXT: jr $ra # > +; MIPS1-PSX-NEXT: nop # +; MIPS1-PSX-NEXT: # +; MIPS1-PSX-NEXT: # > entry: %0 = load i16, ptr @b %1 = sext i16 %0 to i32 @@ -684,7 +749,7 @@ define i32 @f5() { ; MIPS32-NEXT: # > ; MIPS32-NEXT: jr $ra # > -; MIPS32-NEXT: lw $2, %lo(c)($1) # ; MIPS32-NEXT: # ; MIPS32-NEXT: # > @@ -696,7 +761,7 @@ define i32 @f5() { ; MMR3-NEXT: # > ; MMR3-NEXT: jr $ra # > -; MMR3-NEXT: lw $2, %lo(c)($1) # ; MMR3-NEXT: # ; MMR3-NEXT: # > @@ -709,7 +774,7 @@ define i32 @f5() { ; MIPS32R6-NEXT: jr $ra # ; MIPS32R6-NEXT: # > -; MIPS32R6-NEXT: lw $2, %lo(c)($1) # ; MIPS32R6-NEXT: # ; MIPS32R6-NEXT: # > @@ -719,7 +784,7 @@ define i32 @f5() { ; MMR6-NEXT: lui $1, %hi(c) # ; MMR6-NEXT: # > -; MMR6-NEXT: lw $2, %lo(c)($1) # ; MMR6-NEXT: # ; MMR6-NEXT: # > @@ -749,7 +814,7 @@ define i32 @f5() { ; MIPS3-NEXT: # > ; MIPS3-NEXT: jr $ra # > -; MIPS3-NEXT: lw $2, %lo(c)($1) # ; MIPS3-NEXT: # ; MIPS3-NEXT: # > @@ -777,7 +842,7 @@ define i32 @f5() { ; MIPS64-NEXT: # > ; MIPS64-NEXT: jr $ra # > -; MIPS64-NEXT: lw $2, %lo(c)($1) # ; MIPS64-NEXT: # ; MIPS64-NEXT: # > @@ -806,7 +871,7 @@ define i32 @f5() { ; MIPS64R6-NEXT: jr $ra # ; MIPS64R6-NEXT: # > -; MIPS64R6-NEXT: lw $2, %lo(c)($1) # ; MIPS64R6-NEXT: # ; MIPS64R6-NEXT: # > @@ -818,7 +883,7 @@ define i32 @f5() { ; MMR5FP64-NEXT: # > ; MMR5FP64-NEXT: jr $ra # > -; MMR5FP64-NEXT: lw $2, %lo(c)($1) # ; MMR5FP64-NEXT: # ; MMR5FP64-NEXT: # > @@ -830,10 +895,26 @@ define i32 @f5() { ; MIPS32R5FP643-NEXT: # > ; MIPS32R5FP643-NEXT: jr $ra # > -; MIPS32R5FP643-NEXT: lw $2, %lo(c)($1) # ; MIPS32R5FP643-NEXT: # ; MIPS32R5FP643-NEXT: # > +; +; MIPS1-PSX-LABEL: f5: +; MIPS1-PSX: # %bb.0: # %entry +; MIPS1-PSX-NEXT: lui $1, %hi(c) # +; MIPS1-PSX-NEXT: # > +; MIPS1-PSX-NEXT: lw $2, %lo(c)($1) # +; MIPS1-PSX-NEXT: # +; MIPS1-PSX-NEXT: # > +; MIPS1-PSX-NEXT: jr $ra # > +; MIPS1-PSX-NEXT: nop # +; MIPS1-PSX-NEXT: # +; MIPS1-PSX-NEXT: # > entry: %0 = load i32, ptr @c ret i32 %0 @@ -845,13 +926,13 @@ define i64 @f6() { ; MIPS32-NEXT: lui $1, %hi(c) # ; MIPS32-NEXT: # > -; MIPS32-NEXT: lw $3, %lo(c)($1) # ; MIPS32-NEXT: # ; MIPS32-NEXT: # > ; MIPS32-NEXT: jr $ra # > -; MIPS32-NEXT: addiu $2, $zero, 0 # ; MIPS32-NEXT: # ; MIPS32-NEXT: # > @@ -861,12 +942,12 @@ define i64 @f6() { ; MMR3-NEXT: lui $1, %hi(c) # ; MMR3-NEXT: # > -; MMR3-NEXT: li16 $2, 0 # ; MMR3-NEXT: # > ; MMR3-NEXT: jr $ra # > -; MMR3-NEXT: lw $3, %lo(c)($1) # ; MMR3-NEXT: # ; MMR3-NEXT: # > @@ -876,14 +957,14 @@ define i64 @f6() { ; MIPS32R6-NEXT: lui $1, %hi(c) # ; MIPS32R6-NEXT: # > -; MIPS32R6-NEXT: lw $3, %lo(c)($1) # ; MIPS32R6-NEXT: # ; MIPS32R6-NEXT: # > ; MIPS32R6-NEXT: jr $ra # ; MIPS32R6-NEXT: # > -; MIPS32R6-NEXT: addiu $2, $zero, 0 # ; MIPS32R6-NEXT: # ; MIPS32R6-NEXT: # > @@ -893,11 +974,11 @@ define i64 @f6() { ; MMR6-NEXT: lui $1, %hi(c) # ; MMR6-NEXT: # > -; MMR6-NEXT: lw $3, %lo(c)($1) # ; MMR6-NEXT: # ; MMR6-NEXT: # > -; MMR6-NEXT: li16 $2, 0 # ; MMR6-NEXT: # > ; MMR6-NEXT: jrc $ra # > ; MIPS3-NEXT: jr $ra # > -; MIPS3-NEXT: lwu $2, %lo(c)($1) # ; MIPS3-NEXT: # ; MIPS3-NEXT: # > @@ -954,7 +1035,7 @@ define i64 @f6() { ; MIPS64-NEXT: # > ; MIPS64-NEXT: jr $ra # > -; MIPS64-NEXT: lwu $2, %lo(c)($1) # ; MIPS64-NEXT: # ; MIPS64-NEXT: # > @@ -983,7 +1064,7 @@ define i64 @f6() { ; MIPS64R6-NEXT: jr $ra # ; MIPS64R6-NEXT: # > -; MIPS64R6-NEXT: lwu $2, %lo(c)($1) # ; MIPS64R6-NEXT: # ; MIPS64R6-NEXT: # > @@ -993,12 +1074,12 @@ define i64 @f6() { ; MMR5FP64-NEXT: lui $1, %hi(c) # ; MMR5FP64-NEXT: # > -; MMR5FP64-NEXT: li16 $2, 0 # ; MMR5FP64-NEXT: # > ; MMR5FP64-NEXT: jr $ra # > -; MMR5FP64-NEXT: lw $3, %lo(c)($1) # ; MMR5FP64-NEXT: # ; MMR5FP64-NEXT: # > @@ -1008,16 +1089,32 @@ define i64 @f6() { ; MIPS32R5FP643-NEXT: lui $1, %hi(c) # ; MIPS32R5FP643-NEXT: # > -; MIPS32R5FP643-NEXT: lw $3, %lo(c)($1) # ; MIPS32R5FP643-NEXT: # ; MIPS32R5FP643-NEXT: # > ; MIPS32R5FP643-NEXT: jr $ra # > -; MIPS32R5FP643-NEXT: addiu $2, $zero, 0 # ; MIPS32R5FP643-NEXT: # ; MIPS32R5FP643-NEXT: # > +; +; MIPS1-PSX-LABEL: f6: +; MIPS1-PSX: # %bb.0: # %entry +; MIPS1-PSX-NEXT: lui $1, %hi(c) # +; MIPS1-PSX-NEXT: # > +; MIPS1-PSX-NEXT: lw $2, %lo(c)($1) # +; MIPS1-PSX-NEXT: # +; MIPS1-PSX-NEXT: # > +; MIPS1-PSX-NEXT: jr $ra # > +; MIPS1-PSX-NEXT: addiu $3, $zero, 0 # +; MIPS1-PSX-NEXT: # +; MIPS1-PSX-NEXT: # > entry: %0 = load i32, ptr @c %1 = zext i32 %0 to i64 @@ -1030,13 +1127,13 @@ define i64 @f7() { ; MIPS32-NEXT: lui $1, %hi(c) # ; MIPS32-NEXT: # > -; MIPS32-NEXT: lw $3, %lo(c)($1) # ; MIPS32-NEXT: # ; MIPS32-NEXT: # > ; MIPS32-NEXT: jr $ra # > -; MIPS32-NEXT: sra $2, $3, 31 # ; MIPS32-NEXT: # ; MIPS32-NEXT: # > @@ -1046,13 +1143,13 @@ define i64 @f7() { ; MMR3-NEXT: lui $1, %hi(c) # ; MMR3-NEXT: # > -; MMR3-NEXT: lw $3, %lo(c)($1) # ; MMR3-NEXT: # ; MMR3-NEXT: # > ; MMR3-NEXT: jr $ra # > -; MMR3-NEXT: sra $2, $3, 31 # ; MMR3-NEXT: # ; MMR3-NEXT: # > @@ -1062,14 +1159,14 @@ define i64 @f7() { ; MIPS32R6-NEXT: lui $1, %hi(c) # ; MIPS32R6-NEXT: # > -; MIPS32R6-NEXT: lw $3, %lo(c)($1) # ; MIPS32R6-NEXT: # ; MIPS32R6-NEXT: # > ; MIPS32R6-NEXT: jr $ra # ; MIPS32R6-NEXT: # > -; MIPS32R6-NEXT: sra $2, $3, 31 # ; MIPS32R6-NEXT: # ; MIPS32R6-NEXT: # > @@ -1079,11 +1176,11 @@ define i64 @f7() { ; MMR6-NEXT: lui $1, %hi(c) # ; MMR6-NEXT: # > -; MMR6-NEXT: lw $3, %lo(c)($1) # ; MMR6-NEXT: # ; MMR6-NEXT: # > -; MMR6-NEXT: sra $2, $3, 31 # ; MMR6-NEXT: # ; MMR6-NEXT: # > @@ -1113,7 +1210,7 @@ define i64 @f7() { ; MIPS3-NEXT: # > ; MIPS3-NEXT: jr $ra # > -; MIPS3-NEXT: lw $2, %lo(c)($1) # ; MIPS3-NEXT: # ; MIPS3-NEXT: # > @@ -1141,7 +1238,7 @@ define i64 @f7() { ; MIPS64-NEXT: # > ; MIPS64-NEXT: jr $ra # > -; MIPS64-NEXT: lw $2, %lo(c)($1) # ; MIPS64-NEXT: # ; MIPS64-NEXT: # > @@ -1170,7 +1267,7 @@ define i64 @f7() { ; MIPS64R6-NEXT: jr $ra # ; MIPS64R6-NEXT: # > -; MIPS64R6-NEXT: lw $2, %lo(c)($1) # ; MIPS64R6-NEXT: # ; MIPS64R6-NEXT: # > @@ -1180,13 +1277,13 @@ define i64 @f7() { ; MMR5FP64-NEXT: lui $1, %hi(c) # ; MMR5FP64-NEXT: # > -; MMR5FP64-NEXT: lw $3, %lo(c)($1) # ; MMR5FP64-NEXT: # ; MMR5FP64-NEXT: # > ; MMR5FP64-NEXT: jr $ra # > -; MMR5FP64-NEXT: sra $2, $3, 31 # ; MMR5FP64-NEXT: # ; MMR5FP64-NEXT: # > @@ -1196,16 +1293,32 @@ define i64 @f7() { ; MIPS32R5FP643-NEXT: lui $1, %hi(c) # ; MIPS32R5FP643-NEXT: # > -; MIPS32R5FP643-NEXT: lw $3, %lo(c)($1) # ; MIPS32R5FP643-NEXT: # ; MIPS32R5FP643-NEXT: # > ; MIPS32R5FP643-NEXT: jr $ra # > -; MIPS32R5FP643-NEXT: sra $2, $3, 31 # ; MIPS32R5FP643-NEXT: # ; MIPS32R5FP643-NEXT: # > +; +; MIPS1-PSX-LABEL: f7: +; MIPS1-PSX: # %bb.0: # %entry +; MIPS1-PSX-NEXT: lui $1, %hi(c) # +; MIPS1-PSX-NEXT: # > +; MIPS1-PSX-NEXT: lw $2, %lo(c)($1) # +; MIPS1-PSX-NEXT: # +; MIPS1-PSX-NEXT: # > +; MIPS1-PSX-NEXT: jr $ra # > +; MIPS1-PSX-NEXT: sra $3, $2, 31 # +; MIPS1-PSX-NEXT: # +; MIPS1-PSX-NEXT: # > entry: %0 = load i32, ptr @c %1 = sext i32 %0 to i64 @@ -1220,7 +1333,7 @@ define float @f8() { ; MIPS32-NEXT: # > ; MIPS32-NEXT: jr $ra # > -; MIPS32-NEXT: lwc1 $f0, %lo(e)($1) # ; MIPS32-NEXT: # ; MIPS32-NEXT: # > @@ -1232,7 +1345,7 @@ define float @f8() { ; MMR3-NEXT: # > ; MMR3-NEXT: jr $ra # > -; MMR3-NEXT: lwc1 $f0, %lo(e)($1) # ; MMR3-NEXT: # ; MMR3-NEXT: # > @@ -1245,7 +1358,7 @@ define float @f8() { ; MIPS32R6-NEXT: jr $ra # ; MIPS32R6-NEXT: # > -; MIPS32R6-NEXT: lwc1 $f0, %lo(e)($1) # ; MIPS32R6-NEXT: # ; MIPS32R6-NEXT: # > @@ -1255,7 +1368,7 @@ define float @f8() { ; MMR6-NEXT: lui $1, %hi(e) # ; MMR6-NEXT: # > -; MMR6-NEXT: lwc1 $f0, %lo(e)($1) # ; MMR6-NEXT: # ; MMR6-NEXT: # > @@ -1285,7 +1398,7 @@ define float @f8() { ; MIPS3-NEXT: # > ; MIPS3-NEXT: jr $ra # > -; MIPS3-NEXT: lwc1 $f0, %lo(e)($1) # ; MIPS3-NEXT: # ; MIPS3-NEXT: # > @@ -1313,7 +1426,7 @@ define float @f8() { ; MIPS64-NEXT: # > ; MIPS64-NEXT: jr $ra # > -; MIPS64-NEXT: lwc1 $f0, %lo(e)($1) # ; MIPS64-NEXT: # ; MIPS64-NEXT: # > @@ -1342,7 +1455,7 @@ define float @f8() { ; MIPS64R6-NEXT: jr $ra # ; MIPS64R6-NEXT: # > -; MIPS64R6-NEXT: lwc1 $f0, %lo(e)($1) # ; MIPS64R6-NEXT: # ; MIPS64R6-NEXT: # > @@ -1354,7 +1467,7 @@ define float @f8() { ; MMR5FP64-NEXT: # > ; MMR5FP64-NEXT: jr $ra # > -; MMR5FP64-NEXT: lwc1 $f0, %lo(e)($1) # ; MMR5FP64-NEXT: # ; MMR5FP64-NEXT: # > @@ -1366,10 +1479,22 @@ define float @f8() { ; MIPS32R5FP643-NEXT: # > ; MIPS32R5FP643-NEXT: jr $ra # > -; MIPS32R5FP643-NEXT: lwc1 $f0, %lo(e)($1) # ; MIPS32R5FP643-NEXT: # ; MIPS32R5FP643-NEXT: # > +; +; MIPS1-PSX-LABEL: f8: +; MIPS1-PSX: # %bb.0: # %entry +; MIPS1-PSX-NEXT: lui $1, %hi(e) # +; MIPS1-PSX-NEXT: # > +; MIPS1-PSX-NEXT: jr $ra # > +; MIPS1-PSX-NEXT: lwc1 $f0, %lo(e)($1) # +; MIPS1-PSX-NEXT: # +; MIPS1-PSX-NEXT: # > entry: %0 = load float, ptr @e ret float %0 @@ -1383,7 +1508,7 @@ define double @f9() { ; MIPS32-NEXT: # > ; MIPS32-NEXT: jr $ra # > -; MIPS32-NEXT: ldc1 $f0, %lo(f)($1) # ; MIPS32-NEXT: # ; MIPS32-NEXT: # > @@ -1395,7 +1520,7 @@ define double @f9() { ; MMR3-NEXT: # > ; MMR3-NEXT: jr $ra # > -; MMR3-NEXT: ldc1 $f0, %lo(f)($1) # ; MMR3-NEXT: # ; MMR3-NEXT: # > @@ -1408,7 +1533,7 @@ define double @f9() { ; MIPS32R6-NEXT: jr $ra # ; MIPS32R6-NEXT: # > -; MIPS32R6-NEXT: ldc1 $f0, %lo(f)($1) # ; MIPS32R6-NEXT: # ; MIPS32R6-NEXT: # > @@ -1418,7 +1543,7 @@ define double @f9() { ; MMR6-NEXT: lui $1, %hi(f) # ; MMR6-NEXT: # > -; MMR6-NEXT: ldc1 $f0, %lo(f)($1) # ; MMR6-NEXT: # ; MMR6-NEXT: # > @@ -1448,7 +1573,7 @@ define double @f9() { ; MIPS3-NEXT: # > ; MIPS3-NEXT: jr $ra # > -; MIPS3-NEXT: ldc1 $f0, %lo(f)($1) # ; MIPS3-NEXT: # ; MIPS3-NEXT: # > @@ -1476,7 +1601,7 @@ define double @f9() { ; MIPS64-NEXT: # > ; MIPS64-NEXT: jr $ra # > -; MIPS64-NEXT: ldc1 $f0, %lo(f)($1) # ; MIPS64-NEXT: # ; MIPS64-NEXT: # > @@ -1505,7 +1630,7 @@ define double @f9() { ; MIPS64R6-NEXT: jr $ra # ; MIPS64R6-NEXT: # > -; MIPS64R6-NEXT: ldc1 $f0, %lo(f)($1) # ; MIPS64R6-NEXT: # ; MIPS64R6-NEXT: # > @@ -1517,7 +1642,7 @@ define double @f9() { ; MMR5FP64-NEXT: # > ; MMR5FP64-NEXT: jr $ra # > -; MMR5FP64-NEXT: ldc1 $f0, %lo(f)($1) # ; MMR5FP64-NEXT: # ; MMR5FP64-NEXT: # > @@ -1529,10 +1654,22 @@ define double @f9() { ; MIPS32R5FP643-NEXT: # > ; MIPS32R5FP643-NEXT: jr $ra # > -; MIPS32R5FP643-NEXT: ldc1 $f0, %lo(f)($1) # ; MIPS32R5FP643-NEXT: # ; MIPS32R5FP643-NEXT: # > +; +; MIPS1-PSX-LABEL: f9: +; MIPS1-PSX: # %bb.0: # %entry +; MIPS1-PSX-NEXT: lui $1, %hi(f) # +; MIPS1-PSX-NEXT: # > +; MIPS1-PSX-NEXT: jr $ra # > +; MIPS1-PSX-NEXT: ldc1 $f0, %lo(f)($1) # +; MIPS1-PSX-NEXT: # +; MIPS1-PSX-NEXT: # > entry: %0 = load double, ptr @f ret double %0 diff --git a/llvm/test/CodeGen/Mips/llvm-ir/select-dbl.ll b/llvm/test/CodeGen/Mips/llvm-ir/select-dbl.ll index 3c1dff3da6aa..f39be636e09d 100644 --- a/llvm/test/CodeGen/Mips/llvm-ir/select-dbl.ll +++ b/llvm/test/CodeGen/Mips/llvm-ir/select-dbl.ll @@ -30,6 +30,8 @@ ; RUN: -check-prefix=MM32R3 ; RUN: llc < %s -mtriple=mips-unknown-linux-gnu -mcpu=mips32r6 -mattr=+micromips -verify-machineinstrs | FileCheck %s \ ; RUN: -check-prefix=MM32R6 +; RUN: llc < %s -mtriple=mipsel-sony-psx -mcpu=mips1 -verify-machineinstrs | FileCheck %s \ +; RUN: -check-prefixes=MIPS1-PSX define double @tst_select_i1_double(i1 signext %s, double %x, double %y) { ; M2-LABEL: tst_select_i1_double: @@ -99,12 +101,28 @@ define double @tst_select_i1_double(i1 signext %s, double %x, double %y) { ; ; MM32R3-LABEL: tst_select_i1_double: ; MM32R3: # %bb.0: # %entry -; MM32R3: mtc1 $7, $f2 # +; MM32R3-NEXT: # > +; MM32R3-NEXT: mthc1 $6, $f2 # +; MM32R3-NEXT: # +; MM32R3-NEXT: # > +; MM32R3-NEXT: andi16 $2, $4, 1 # +; MM32R3-NEXT: # +; MM32R3-NEXT: # > +; MM32R3-NEXT: ldc1 $f0, 16($sp) # +; MM32R3-NEXT: # +; MM32R3-NEXT: # > +; MM32R3-NEXT: jr $ra # > +; MM32R3-NEXT: movn.d $f0, $f2, $2 # +; MM32R3-NEXT: # +; MM32R3-NEXT: # +; MM32R3-NEXT: # > ; ; MM32R6-LABEL: tst_select_i1_double: ; MM32R6: # %bb.0: # %entry @@ -114,6 +132,20 @@ define double @tst_select_i1_double(i1 signext %s, double %x, double %y) { ; MM32R6-NEXT: mtc1 $4, $f0 ; MM32R6-NEXT: sel.d $f0, $f2, $f1 ; MM32R6-NEXT: jrc $ra +; +; MIPS1-PSX-LABEL: tst_select_i1_double: +; MIPS1-PSX: # %bb.0: # %entry +; MIPS1-PSX-NEXT: andi $1, $4, 1 +; MIPS1-PSX-NEXT: bnez $1, $BB0_2 +; MIPS1-PSX-NEXT: nop +; MIPS1-PSX-NEXT: # %bb.1: # %entry +; MIPS1-PSX-NEXT: ldc1 $f0, 16($sp) +; MIPS1-PSX-NEXT: jr $ra +; MIPS1-PSX-NEXT: nop +; MIPS1-PSX-NEXT: $BB0_2: +; MIPS1-PSX-NEXT: mtc1 $6, $f0 +; MIPS1-PSX-NEXT: jr $ra +; MIPS1-PSX-NEXT: mtc1 $7, $f1 entry: %r = select i1 %s, double %x, double %y ret double %r @@ -181,11 +213,24 @@ define double @tst_select_i1_double_reordered(double %x, double %y, ; ; MM32R3-LABEL: tst_select_i1_double_reordered: ; MM32R3: # %bb.0: # %entry -; MM32R3: mov.d $f0, $f14 # +; MM32R3-NEXT: # > +; MM32R3-NEXT: lw $2, 16($sp) # +; MM32R3-NEXT: # +; MM32R3-NEXT: # > +; MM32R3-NEXT: andi16 $2, $2, 1 # +; MM32R3-NEXT: # +; MM32R3-NEXT: # > +; MM32R3-NEXT: jr $ra # > +; MM32R3-NEXT: movn.d $f0, $f12, $2 # +; MM32R3-NEXT: # +; MM32R3-NEXT: # +; MM32R3-NEXT: # > ; ; MM32R6-LABEL: tst_select_i1_double_reordered: ; MM32R6: # %bb.0: # %entry @@ -193,6 +238,19 @@ define double @tst_select_i1_double_reordered(double %x, double %y, ; MM32R6-NEXT: mtc1 $1, $f0 ; MM32R6-NEXT: sel.d $f0, $f14, $f12 ; MM32R6-NEXT: jrc $ra +; +; MIPS1-PSX-LABEL: tst_select_i1_double_reordered: +; MIPS1-PSX: # %bb.0: # %entry +; MIPS1-PSX-NEXT: lw $1, 16($sp) +; MIPS1-PSX-NEXT: nop +; MIPS1-PSX-NEXT: andi $1, $1, 1 +; MIPS1-PSX-NEXT: bnez $1, $BB1_2 +; MIPS1-PSX-NEXT: mov.d $f0, $f12 +; MIPS1-PSX-NEXT: # %bb.1: # %entry +; MIPS1-PSX-NEXT: mov.d $f0, $f14 +; MIPS1-PSX-NEXT: $BB1_2: # %entry +; MIPS1-PSX-NEXT: jr $ra +; MIPS1-PSX-NEXT: nop i1 signext %s) { entry: %r = select i1 %s, double %x, double %y @@ -259,16 +317,38 @@ define double @tst_select_fcmp_olt_double(double %x, double %y) { ; ; MM32R3-LABEL: tst_select_fcmp_olt_double: ; MM32R3: # %bb.0: # %entry -; MM32R3: mov.d $f0, $f14 # +; MM32R3-NEXT: # > +; MM32R3-NEXT: c.olt.d $f12, $f14 # +; MM32R3-NEXT: # +; MM32R3-NEXT: # > +; MM32R3-NEXT: jr $ra # > +; MM32R3-NEXT: movt.d $f0, $f12, $fcc0 # +; MM32R3-NEXT: # +; MM32R3-NEXT: # +; MM32R3-NEXT: # > ; ; MM32R6-LABEL: tst_select_fcmp_olt_double: ; MM32R6: # %bb.0: # %entry ; MM32R6-NEXT: cmp.lt.d $f0, $f12, $f14 ; MM32R6-NEXT: sel.d $f0, $f14, $f12 ; MM32R6-NEXT: jrc $ra +; +; MIPS1-PSX-LABEL: tst_select_fcmp_olt_double: +; MIPS1-PSX: # %bb.0: # %entry +; MIPS1-PSX-NEXT: c.olt.d $f12, $f14 +; MIPS1-PSX-NEXT: nop +; MIPS1-PSX-NEXT: bc1t $BB2_2 +; MIPS1-PSX-NEXT: mov.d $f0, $f12 +; MIPS1-PSX-NEXT: # %bb.1: # %entry +; MIPS1-PSX-NEXT: mov.d $f0, $f14 +; MIPS1-PSX-NEXT: $BB2_2: # %entry +; MIPS1-PSX-NEXT: jr $ra +; MIPS1-PSX-NEXT: nop entry: %s = fcmp olt double %x, %y %r = select i1 %s, double %x, double %y @@ -335,16 +415,38 @@ define double @tst_select_fcmp_ole_double(double %x, double %y) { ; ; MM32R3-LABEL: tst_select_fcmp_ole_double: ; MM32R3: # %bb.0: # %entry -; MM32R3: mov.d $f0, $f14 # +; MM32R3-NEXT: # > +; MM32R3-NEXT: c.ole.d $f12, $f14 # +; MM32R3-NEXT: # +; MM32R3-NEXT: # > +; MM32R3-NEXT: jr $ra # > +; MM32R3-NEXT: movt.d $f0, $f12, $fcc0 # +; MM32R3-NEXT: # +; MM32R3-NEXT: # +; MM32R3-NEXT: # > ; ; MM32R6-LABEL: tst_select_fcmp_ole_double: ; MM32R6: # %bb.0: # %entry ; MM32R6-NEXT: cmp.le.d $f0, $f12, $f14 ; MM32R6-NEXT: sel.d $f0, $f14, $f12 ; MM32R6-NEXT: jrc $ra +; +; MIPS1-PSX-LABEL: tst_select_fcmp_ole_double: +; MIPS1-PSX: # %bb.0: # %entry +; MIPS1-PSX-NEXT: c.ole.d $f12, $f14 +; MIPS1-PSX-NEXT: nop +; MIPS1-PSX-NEXT: bc1t $BB3_2 +; MIPS1-PSX-NEXT: mov.d $f0, $f12 +; MIPS1-PSX-NEXT: # %bb.1: # %entry +; MIPS1-PSX-NEXT: mov.d $f0, $f14 +; MIPS1-PSX-NEXT: $BB3_2: # %entry +; MIPS1-PSX-NEXT: jr $ra +; MIPS1-PSX-NEXT: nop entry: %s = fcmp ole double %x, %y %r = select i1 %s, double %x, double %y @@ -411,16 +513,38 @@ define double @tst_select_fcmp_ogt_double(double %x, double %y) { ; ; MM32R3-LABEL: tst_select_fcmp_ogt_double: ; MM32R3: # %bb.0: # %entry -; MM32R3: mov.d $f0, $f14 # +; MM32R3-NEXT: # > +; MM32R3-NEXT: c.ule.d $f12, $f14 # +; MM32R3-NEXT: # +; MM32R3-NEXT: # > +; MM32R3-NEXT: jr $ra # > +; MM32R3-NEXT: movf.d $f0, $f12, $fcc0 # +; MM32R3-NEXT: # +; MM32R3-NEXT: # +; MM32R3-NEXT: # > ; ; MM32R6-LABEL: tst_select_fcmp_ogt_double: ; MM32R6: # %bb.0: # %entry ; MM32R6-NEXT: cmp.lt.d $f0, $f14, $f12 ; MM32R6-NEXT: sel.d $f0, $f14, $f12 ; MM32R6-NEXT: jrc $ra +; +; MIPS1-PSX-LABEL: tst_select_fcmp_ogt_double: +; MIPS1-PSX: # %bb.0: # %entry +; MIPS1-PSX-NEXT: c.ule.d $f12, $f14 +; MIPS1-PSX-NEXT: nop +; MIPS1-PSX-NEXT: bc1f $BB4_2 +; MIPS1-PSX-NEXT: mov.d $f0, $f12 +; MIPS1-PSX-NEXT: # %bb.1: # %entry +; MIPS1-PSX-NEXT: mov.d $f0, $f14 +; MIPS1-PSX-NEXT: $BB4_2: # %entry +; MIPS1-PSX-NEXT: jr $ra +; MIPS1-PSX-NEXT: nop entry: %s = fcmp ogt double %x, %y %r = select i1 %s, double %x, double %y @@ -487,16 +611,38 @@ define double @tst_select_fcmp_oge_double(double %x, double %y) { ; ; MM32R3-LABEL: tst_select_fcmp_oge_double: ; MM32R3: # %bb.0: # %entry -; MM32R3: mov.d $f0, $f14 # +; MM32R3-NEXT: # > +; MM32R3-NEXT: c.ult.d $f12, $f14 # +; MM32R3-NEXT: # +; MM32R3-NEXT: # > +; MM32R3-NEXT: jr $ra # > +; MM32R3-NEXT: movf.d $f0, $f12, $fcc0 # +; MM32R3-NEXT: # +; MM32R3-NEXT: # +; MM32R3-NEXT: # > ; ; MM32R6-LABEL: tst_select_fcmp_oge_double: ; MM32R6: # %bb.0: # %entry ; MM32R6-NEXT: cmp.le.d $f0, $f14, $f12 ; MM32R6-NEXT: sel.d $f0, $f14, $f12 ; MM32R6-NEXT: jrc $ra +; +; MIPS1-PSX-LABEL: tst_select_fcmp_oge_double: +; MIPS1-PSX: # %bb.0: # %entry +; MIPS1-PSX-NEXT: c.ult.d $f12, $f14 +; MIPS1-PSX-NEXT: nop +; MIPS1-PSX-NEXT: bc1f $BB5_2 +; MIPS1-PSX-NEXT: mov.d $f0, $f12 +; MIPS1-PSX-NEXT: # %bb.1: # %entry +; MIPS1-PSX-NEXT: mov.d $f0, $f14 +; MIPS1-PSX-NEXT: $BB5_2: # %entry +; MIPS1-PSX-NEXT: jr $ra +; MIPS1-PSX-NEXT: nop entry: %s = fcmp oge double %x, %y %r = select i1 %s, double %x, double %y @@ -563,16 +709,38 @@ define double @tst_select_fcmp_oeq_double(double %x, double %y) { ; ; MM32R3-LABEL: tst_select_fcmp_oeq_double: ; MM32R3: # %bb.0: # %entry -; MM32R3: mov.d $f0, $f14 # +; MM32R3-NEXT: # > +; MM32R3-NEXT: c.eq.d $f12, $f14 # +; MM32R3-NEXT: # +; MM32R3-NEXT: # > +; MM32R3-NEXT: jr $ra # > +; MM32R3-NEXT: movt.d $f0, $f12, $fcc0 # +; MM32R3-NEXT: # +; MM32R3-NEXT: # +; MM32R3-NEXT: # > ; ; MM32R6-LABEL: tst_select_fcmp_oeq_double: ; MM32R6: # %bb.0: # %entry ; MM32R6-NEXT: cmp.eq.d $f0, $f12, $f14 ; MM32R6-NEXT: sel.d $f0, $f14, $f12 ; MM32R6-NEXT: jrc $ra +; +; MIPS1-PSX-LABEL: tst_select_fcmp_oeq_double: +; MIPS1-PSX: # %bb.0: # %entry +; MIPS1-PSX-NEXT: c.eq.d $f12, $f14 +; MIPS1-PSX-NEXT: nop +; MIPS1-PSX-NEXT: bc1t $BB6_2 +; MIPS1-PSX-NEXT: mov.d $f0, $f12 +; MIPS1-PSX-NEXT: # %bb.1: # %entry +; MIPS1-PSX-NEXT: mov.d $f0, $f14 +; MIPS1-PSX-NEXT: $BB6_2: # %entry +; MIPS1-PSX-NEXT: jr $ra +; MIPS1-PSX-NEXT: nop entry: %s = fcmp oeq double %x, %y %r = select i1 %s, double %x, double %y @@ -639,16 +807,38 @@ define double @tst_select_fcmp_one_double(double %x, double %y) { ; ; MM32R3-LABEL: tst_select_fcmp_one_double: ; MM32R3: # %bb.0: # %entry -; MM32R3: mov.d $f0, $f14 # +; MM32R3-NEXT: # > +; MM32R3-NEXT: c.ueq.d $f12, $f14 # +; MM32R3-NEXT: # +; MM32R3-NEXT: # > +; MM32R3-NEXT: jr $ra # > +; MM32R3-NEXT: movf.d $f0, $f12, $fcc0 # +; MM32R3-NEXT: # +; MM32R3-NEXT: # +; MM32R3-NEXT: # > ; ; MM32R6-LABEL: tst_select_fcmp_one_double: ; MM32R6: # %bb.0: # %entry ; MM32R6-NEXT: cmp.ueq.d $f0, $f12, $f14 ; MM32R6-NEXT: sel.d $f0, $f12, $f14 ; MM32R6-NEXT: jrc $ra +; +; MIPS1-PSX-LABEL: tst_select_fcmp_one_double: +; MIPS1-PSX: # %bb.0: # %entry +; MIPS1-PSX-NEXT: c.ueq.d $f12, $f14 +; MIPS1-PSX-NEXT: nop +; MIPS1-PSX-NEXT: bc1f $BB7_2 +; MIPS1-PSX-NEXT: mov.d $f0, $f12 +; MIPS1-PSX-NEXT: # %bb.1: # %entry +; MIPS1-PSX-NEXT: mov.d $f0, $f14 +; MIPS1-PSX-NEXT: $BB7_2: # %entry +; MIPS1-PSX-NEXT: jr $ra +; MIPS1-PSX-NEXT: nop entry: %s = fcmp one double %x, %y %r = select i1 %s, double %x, double %y diff --git a/llvm/test/CodeGen/Mips/mips1-load-in-delay-slot.ll b/llvm/test/CodeGen/Mips/mips1-load-in-delay-slot.ll new file mode 100644 index 000000000000..4499dc6123fd --- /dev/null +++ b/llvm/test/CodeGen/Mips/mips1-load-in-delay-slot.ll @@ -0,0 +1,61 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc < %s -mtriple=mipsel-sony-psx -mcpu=mips1 -relocation-model=pic | FileCheck %s -check-prefixes=MIPS1-PSX + +@data = internal global <{ [1 x i8] }> <{ [1 x i8] c"\00" }>, align 4 + +define internal fastcc void @test() unnamed_addr #0 { +; MIPS1-PSX-LABEL: test: +; MIPS1-PSX: # %bb.0: # %start +; MIPS1-PSX-NEXT: lui $2, %hi(_gp_disp) +; MIPS1-PSX-NEXT: addiu $2, $2, %lo(_gp_disp) +; MIPS1-PSX-NEXT: addu $1, $2, $25 +; MIPS1-PSX-NEXT: lw $2, %got(data)($1) +; MIPS1-PSX-NEXT: nop +; MIPS1-PSX-NEXT: addiu $1, $2, %lo(data) +; MIPS1-PSX-NEXT: lbu $1, 2($1) +; MIPS1-PSX-NEXT: addiu $3, $zero, 2 +; MIPS1-PSX-NEXT: bne $1, $3, $BB0_2 +; MIPS1-PSX-NEXT: nop +; MIPS1-PSX-NEXT: $BB0_1: # %unreachable.1 +; MIPS1-PSX-NEXT: .insn +; MIPS1-PSX-NEXT: $BB0_2: # %bb6.i +; MIPS1-PSX-NEXT: lbu $2, %lo(data)($2) +; MIPS1-PSX-NEXT: addiu $1, $zero, 1 +; MIPS1-PSX-NEXT: bnez $1, $BB0_5 +; MIPS1-PSX-NEXT: nop +; MIPS1-PSX-NEXT: # %bb.3: # %bb9.i +; MIPS1-PSX-NEXT: andi $1, $2, 1 +; MIPS1-PSX-NEXT: bnez $1, $BB0_1 +; MIPS1-PSX-NEXT: nop +; MIPS1-PSX-NEXT: # %bb.4: # %bb9.i +; MIPS1-PSX-NEXT: b $BB0_6 +; MIPS1-PSX-NEXT: nop +; MIPS1-PSX-NEXT: $BB0_5: # %bb10.i +; MIPS1-PSX-NEXT: andi $1, $2, 1 +; MIPS1-PSX-NEXT: bnez $1, $BB0_1 +; MIPS1-PSX-NEXT: nop +; MIPS1-PSX-NEXT: $BB0_6: # %unreachable.2 +; MIPS1-PSX-NEXT: .insn +start: + %0 = load i8, ptr getelementptr inbounds nuw (i8, ptr @data, i32 2), align 2, !range !{i8 0, i8 3}, !noundef !{} + %.not.i = icmp eq i8 %0, 2 + br i1 %.not.i, label %unreachable.1, label %bb6.i + +bb6.i: ; preds = %start + %1 = trunc nuw i8 0 to i1 + %2 = load i8, ptr @data, align 4, !range !{i8 0, i8 2}, !noundef !{} + %3 = trunc nuw i8 %2 to i1 + br i1 %1, label %bb9.i, label %bb10.i + +bb9.i: ; preds = %bb6.i + br i1 %3, label %unreachable.1, label %unreachable.2 + +bb10.i: ; preds = %bb6.i + br i1 %3, label %unreachable.1, label %unreachable.2 + +unreachable.1: + unreachable + +unreachable.2: + unreachable +} diff --git a/llvm/test/CodeGen/Mips/unalignedload.ll b/llvm/test/CodeGen/Mips/unalignedload.ll index 5c78519e6481..88fc405f3d19 100644 --- a/llvm/test/CodeGen/Mips/unalignedload.ll +++ b/llvm/test/CodeGen/Mips/unalignedload.ll @@ -1,10 +1,11 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc < %s -mtriple=mipsel-elf -mcpu=mips32 -relocation-model=pic | FileCheck %s -check-prefixes=MIPS32-EL -; RUN: llc < %s -mtriple=mips-elf -mcpu=mips32 -relocation-model=pic | FileCheck %s -check-prefixes=MIPS32-EB -; RUN: llc < %s -mtriple=mipsel-elf -mcpu=mips32r2 -relocation-model=pic | FileCheck %s -check-prefixes=MIPS32-EL -; RUN: llc < %s -mtriple=mips-elf -mcpu=mips32r2 -relocation-model=pic | FileCheck %s -check-prefixes=MIPS32-EB -; RUN: llc < %s -mtriple=mipsel-elf -mcpu=mips32r6 -relocation-model=pic | FileCheck %s -check-prefixes=MIPS32R6-EL -; RUN: llc < %s -mtriple=mips-elf -mcpu=mips32r6 -relocation-model=pic | FileCheck %s -check-prefixes=MIPS32R6-EB +; RUN: llc < %s -mtriple=mipsel-elf -mcpu=mips32 -relocation-model=pic | FileCheck %s -check-prefixes=MIPS32-EL +; RUN: llc < %s -mtriple=mips-elf -mcpu=mips32 -relocation-model=pic | FileCheck %s -check-prefixes=MIPS32-EB +; RUN: llc < %s -mtriple=mipsel-elf -mcpu=mips32r2 -relocation-model=pic | FileCheck %s -check-prefixes=MIPS32-EL +; RUN: llc < %s -mtriple=mips-elf -mcpu=mips32r2 -relocation-model=pic | FileCheck %s -check-prefixes=MIPS32-EB +; RUN: llc < %s -mtriple=mipsel-elf -mcpu=mips32r6 -relocation-model=pic | FileCheck %s -check-prefixes=MIPS32R6-EL +; RUN: llc < %s -mtriple=mips-elf -mcpu=mips32r6 -relocation-model=pic | FileCheck %s -check-prefixes=MIPS32R6-EB +; RUN: llc < %s -mtriple=mipsel-sony-psx -mcpu=mips1 -relocation-model=pic | FileCheck %s -check-prefixes=MIPS1-PSX %struct.S2 = type { %struct.S1, %struct.S1 } %struct.S1 = type { i8, i8 } @@ -89,6 +90,30 @@ define void @bar1() nounwind { ; MIPS32R6-EB-NEXT: lw $ra, 20($sp) # 4-byte Folded Reload ; MIPS32R6-EB-NEXT: jr $ra ; MIPS32R6-EB-NEXT: addiu $sp, $sp, 24 +; +; MIPS1-PSX-LABEL: bar1: +; 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, -24 +; MIPS1-PSX-NEXT: sw $ra, 20($sp) # 4-byte Folded Spill +; MIPS1-PSX-NEXT: addu $gp, $2, $25 +; MIPS1-PSX-NEXT: lw $1, %got(s2)($gp) +; MIPS1-PSX-NEXT: nop +; MIPS1-PSX-NEXT: lbu $2, 2($1) +; MIPS1-PSX-NEXT: lbu $1, 3($1) +; MIPS1-PSX-NEXT: nop +; MIPS1-PSX-NEXT: sll $1, $1, 8 +; MIPS1-PSX-NEXT: lw $25, %call16(foo2)($gp) +; MIPS1-PSX-NEXT: nop +; MIPS1-PSX-NEXT: .reloc $tmp0, R_MIPS_JALR, foo2 +; MIPS1-PSX-NEXT: $tmp0: +; MIPS1-PSX-NEXT: jalr $25 +; MIPS1-PSX-NEXT: or $4, $1, $2 +; MIPS1-PSX-NEXT: lw $ra, 20($sp) # 4-byte Folded Reload +; MIPS1-PSX-NEXT: nop +; MIPS1-PSX-NEXT: jr $ra +; MIPS1-PSX-NEXT: addiu $sp, $sp, 24 entry: tail call void @foo2(ptr byval(%struct.S1) getelementptr inbounds (%struct.S2, ptr @s2, i32 0, i32 1)) nounwind ret void @@ -189,6 +214,37 @@ define void @bar2() nounwind { ; MIPS32R6-EB-NEXT: lw $ra, 20($sp) # 4-byte Folded Reload ; MIPS32R6-EB-NEXT: jr $ra ; MIPS32R6-EB-NEXT: addiu $sp, $sp, 24 +; +; MIPS1-PSX-LABEL: bar2: +; 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, -24 +; MIPS1-PSX-NEXT: sw $ra, 20($sp) # 4-byte Folded Spill +; MIPS1-PSX-NEXT: addu $gp, $2, $25 +; MIPS1-PSX-NEXT: lw $1, %got(s4)($gp) +; MIPS1-PSX-NEXT: nop +; MIPS1-PSX-NEXT: lwl $4, 3($1) +; MIPS1-PSX-NEXT: nop +; MIPS1-PSX-NEXT: lwr $4, 0($1) +; MIPS1-PSX-NEXT: lbu $2, 4($1) +; MIPS1-PSX-NEXT: lbu $3, 5($1) +; MIPS1-PSX-NEXT: nop +; MIPS1-PSX-NEXT: sll $3, $3, 8 +; MIPS1-PSX-NEXT: or $2, $3, $2 +; MIPS1-PSX-NEXT: lbu $1, 6($1) +; MIPS1-PSX-NEXT: nop +; MIPS1-PSX-NEXT: sll $1, $1, 16 +; MIPS1-PSX-NEXT: lw $25, %call16(foo4)($gp) +; MIPS1-PSX-NEXT: nop +; MIPS1-PSX-NEXT: .reloc $tmp1, R_MIPS_JALR, foo4 +; MIPS1-PSX-NEXT: $tmp1: +; MIPS1-PSX-NEXT: jalr $25 +; MIPS1-PSX-NEXT: or $5, $2, $1 +; MIPS1-PSX-NEXT: lw $ra, 20($sp) # 4-byte Folded Reload +; MIPS1-PSX-NEXT: nop +; MIPS1-PSX-NEXT: jr $ra +; MIPS1-PSX-NEXT: addiu $sp, $sp, 24 entry: tail call void @foo4(ptr byval(%struct.S4) @s4) nounwind ret void