[llvm] [Mips] Fix mfhi/mflo hazard miscompilation about div and mult (PR #91449)
via llvm-commits
llvm-commits at lists.llvm.org
Sat Sep 14 00:56:28 PDT 2024
https://github.com/yingopq updated https://github.com/llvm/llvm-project/pull/91449
>From 4852febcc1eb78aff84b40c1a45e8698a8745b1d Mon Sep 17 00:00:00 2001
From: Ying Huang <ying.huang at oss.cipunited.com>
Date: Wed, 8 May 2024 04:50:41 -0400
Subject: [PATCH] [Mips] Fix mfhi/mflo hazard miscompilation about div and mult
Fix issue1: In mips1-4, require a minimum of 2 instructions between
a mflo/mfhi and the next mul/dmult/div/ddiv/divu/ddivu instruction.
Fix issue2: In mips1-4, should not put mflo into the delay slot for
the return.
Fix #81291
---
llvm/lib/Target/Mips/Mips.h | 11 ++
llvm/lib/Target/Mips/MipsBranchExpansion.cpp | 70 ++++++++-
llvm/lib/Target/Mips/MipsDelaySlotFiller.cpp | 6 +
llvm/lib/Target/Mips/MipsInstrInfo.cpp | 15 ++
llvm/lib/Target/Mips/MipsInstrInfo.h | 4 +
llvm/test/CodeGen/Mips/llvm-ir/sdiv.ll | 135 ++++++++++++++++-
llvm/test/CodeGen/Mips/llvm-ir/srem.ll | 131 +++++++++++++++-
.../Mips/llvm-ir/two-consecutive-mult.ll | 60 ++++++++
.../Mips/llvm-ir/two-consecutive-sdiv.ll | 133 ++++++++++++++++
.../Mips/llvm-ir/two-consecutive-srem.ll | 133 ++++++++++++++++
.../Mips/llvm-ir/two-consecutive-udiv.ll | 133 ++++++++++++++++
.../Mips/llvm-ir/two-consecutive-urem.ll | 133 ++++++++++++++++
llvm/test/CodeGen/Mips/llvm-ir/udiv.ll | 131 +++++++++++++++-
llvm/test/CodeGen/Mips/llvm-ir/urem.ll | 143 +++++++++++++++++-
14 files changed, 1224 insertions(+), 14 deletions(-)
create mode 100644 llvm/test/CodeGen/Mips/llvm-ir/two-consecutive-mult.ll
create mode 100644 llvm/test/CodeGen/Mips/llvm-ir/two-consecutive-sdiv.ll
create mode 100644 llvm/test/CodeGen/Mips/llvm-ir/two-consecutive-srem.ll
create mode 100644 llvm/test/CodeGen/Mips/llvm-ir/two-consecutive-udiv.ll
create mode 100644 llvm/test/CodeGen/Mips/llvm-ir/two-consecutive-urem.ll
diff --git a/llvm/lib/Target/Mips/Mips.h b/llvm/lib/Target/Mips/Mips.h
index f0cf039928c172..32df648f21b654 100644
--- a/llvm/lib/Target/Mips/Mips.h
+++ b/llvm/lib/Target/Mips/Mips.h
@@ -17,6 +17,17 @@
#include "MCTargetDesc/MipsMCTargetDesc.h"
#include "llvm/Target/TargetMachine.h"
+#define IsMFLOMFHI(instr) \
+ (instr == Mips::MFLO || instr == Mips::MFLO64 || instr == Mips::MFHI || \
+ instr == Mips::MFHI64)
+#define IsDIVMULT(instr) \
+ (instr == Mips::SDIV || instr == Mips::PseudoSDIV || instr == Mips::DSDIV || \
+ instr == Mips::PseudoDSDIV || instr == Mips::UDIV || \
+ instr == Mips::PseudoUDIV || instr == Mips::DUDIV || \
+ instr == Mips::PseudoDUDIV || instr == Mips::MULT || \
+ instr == Mips::PseudoMULT || instr == Mips::DMULT || \
+ instr == Mips::PseudoDMULT)
+
namespace llvm {
class FunctionPass;
class InstructionSelector;
diff --git a/llvm/lib/Target/Mips/MipsBranchExpansion.cpp b/llvm/lib/Target/Mips/MipsBranchExpansion.cpp
index 721e525331c6ce..5d01c698b3e04e 100644
--- a/llvm/lib/Target/Mips/MipsBranchExpansion.cpp
+++ b/llvm/lib/Target/Mips/MipsBranchExpansion.cpp
@@ -167,6 +167,9 @@ class MipsBranchExpansion : public MachineFunctionPass {
bool handleFPUDelaySlot();
bool handleLoadDelaySlot();
bool handlePossibleLongBranch();
+ bool handleMFLO();
+ template <typename Pred, typename Safe>
+ bool handleMFLOSlot(Pred Predicate, Safe SafeInSlot);
const MipsSubtarget *STI;
const MipsInstrInfo *TII;
@@ -741,6 +744,53 @@ static void emitGPDisp(MachineFunction &F, const MipsInstrInfo *TII) {
MBB.removeLiveIn(Mips::V0);
}
+template <typename Pred, typename Safe>
+bool MipsBranchExpansion::handleMFLOSlot(Pred Predicate, Safe SafeInSlot) {
+ bool Changed = false;
+ bool hasPendingMFLO = false;
+
+ for (MachineFunction::iterator FI = MFp->begin(); FI != MFp->end(); ++FI) {
+ for (Iter I = FI->begin(); I != FI->end(); ++I) {
+
+ if (!Predicate(*I) && !hasPendingMFLO) {
+ continue;
+ }
+
+ Iter IInSlot;
+ bool LastInstInFunction =
+ std::next(I) == FI->end() && std::next(FI) == MFp->end();
+ // We need process several situations:
+ // mflo is last instruction, do not process;
+ // mflo + div, add two nop between them;
+ // mflo + none-div + none-div, do not process;
+ // mflo + none-div + div, add nop between none-div and div.
+ if (!LastInstInFunction) {
+ std::pair<Iter, bool> Res = getNextMachineInstr(std::next(I), &*FI);
+ LastInstInFunction |= Res.second;
+ IInSlot = Res.first;
+ if (!SafeInSlot(*IInSlot, *I)) {
+ Changed = true;
+ TII->insertNop(*(I->getParent()), std::next(I), I->getDebugLoc())
+ ->bundleWithPred();
+ NumInsertedNops++;
+ if (IsMFLOMFHI(I->getOpcode())) {
+ TII->insertNop(*(I->getParent()), std::next(I), I->getDebugLoc())
+ ->bundleWithPred();
+ NumInsertedNops++;
+ }
+ if (hasPendingMFLO)
+ hasPendingMFLO = false;
+ } else if (hasPendingMFLO)
+ hasPendingMFLO = false;
+ else if (IsMFLOMFHI(I->getOpcode()))
+ hasPendingMFLO = true;
+ }
+ }
+ }
+
+ return Changed;
+}
+
template <typename Pred, typename Safe>
bool MipsBranchExpansion::handleSlot(Pred Predicate, Safe SafeInSlot) {
bool Changed = false;
@@ -777,6 +827,19 @@ bool MipsBranchExpansion::handleSlot(Pred Predicate, Safe SafeInSlot) {
return Changed;
}
+bool MipsBranchExpansion::handleMFLO() {
+ // mips1-4 require a minimum of 2 instructions between a mflo/mfhi
+ // and the next mul/div instruction.
+ if (STI->hasMips32() || STI->hasMips5())
+ return false;
+
+ return handleMFLOSlot(
+ [this](auto &I) -> bool { return TII->IsMfloOrMfhi(I); },
+ [this](auto &IInSlot, auto &I) -> bool {
+ return TII->SafeAfterMflo(IInSlot);
+ });
+}
+
bool MipsBranchExpansion::handleForbiddenSlot() {
// Forbidden slot hazards are only defined for MIPSR6 but not microMIPSR6.
if (!STI->hasMips32r6() || STI->inMicroMipsMode())
@@ -893,16 +956,19 @@ bool MipsBranchExpansion::runOnMachineFunction(MachineFunction &MF) {
bool forbiddenSlotChanged = handleForbiddenSlot();
bool fpuDelaySlotChanged = handleFPUDelaySlot();
bool loadDelaySlotChanged = handleLoadDelaySlot();
+ bool MfloChanged = handleMFLO();
bool Changed = longBranchChanged || forbiddenSlotChanged ||
- fpuDelaySlotChanged || loadDelaySlotChanged;
+ fpuDelaySlotChanged || loadDelaySlotChanged || MfloChanged;
// Then run them alternatively while there are changes.
while (forbiddenSlotChanged) {
longBranchChanged = handlePossibleLongBranch();
fpuDelaySlotChanged = handleFPUDelaySlot();
loadDelaySlotChanged = handleLoadDelaySlot();
- if (!longBranchChanged && !fpuDelaySlotChanged && !loadDelaySlotChanged)
+ MfloChanged = handleMFLO();
+ if (!longBranchChanged && !fpuDelaySlotChanged && !loadDelaySlotChanged &&
+ !MfloChanged)
break;
forbiddenSlotChanged = handleForbiddenSlot();
}
diff --git a/llvm/lib/Target/Mips/MipsDelaySlotFiller.cpp b/llvm/lib/Target/Mips/MipsDelaySlotFiller.cpp
index cb98c04ff4e501..aa0d29b12e07ce 100644
--- a/llvm/lib/Target/Mips/MipsDelaySlotFiller.cpp
+++ b/llvm/lib/Target/Mips/MipsDelaySlotFiller.cpp
@@ -743,6 +743,12 @@ bool MipsDelaySlotFiller::searchRange(MachineBasicBlock &MBB, IterTy Begin,
bool InMicroMipsMode = STI.inMicroMipsMode();
const MipsInstrInfo *TII = STI.getInstrInfo();
unsigned Opcode = (*Slot).getOpcode();
+
+ // In mips1-4, should not put mflo into the delay slot for the return.
+ if ((IsMFLOMFHI(CurrI->getOpcode())) &&
+ (!STI.hasMips32() && !STI.hasMips5()))
+ continue;
+
// This is complicated by the tail call optimization. For non-PIC code
// there is only a 32bit sized unconditional branch which can be assumed
// to be able to reach the target. b16 only has a range of +/- 1 KB.
diff --git a/llvm/lib/Target/Mips/MipsInstrInfo.cpp b/llvm/lib/Target/Mips/MipsInstrInfo.cpp
index 392cc15d7943af..663be430a2c713 100644
--- a/llvm/lib/Target/Mips/MipsInstrInfo.cpp
+++ b/llvm/lib/Target/Mips/MipsInstrInfo.cpp
@@ -13,6 +13,7 @@
#include "MipsInstrInfo.h"
#include "MCTargetDesc/MipsBaseInfo.h"
#include "MCTargetDesc/MipsMCTargetDesc.h"
+#include "Mips.h"
#include "MipsSubtarget.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
@@ -571,6 +572,13 @@ unsigned MipsInstrInfo::getEquivalentCompactForm(
return 0;
}
+bool MipsInstrInfo::SafeAfterMflo(const MachineInstr &MI) const {
+ if (IsDIVMULT(MI.getOpcode()))
+ return false;
+
+ return true;
+}
+
/// Predicate for distingushing between control transfer instructions and all
/// other instructions for handling forbidden slots. Consider inline assembly
/// as unsafe as well.
@@ -623,6 +631,13 @@ bool MipsInstrInfo::SafeInLoadDelaySlot(const MachineInstr &MIInSlot,
});
}
+bool MipsInstrInfo::IsMfloOrMfhi(const MachineInstr &MI) const {
+ if (IsMFLOMFHI(MI.getOpcode()))
+ return true;
+
+ return false;
+}
+
/// Predicate for distingushing instructions that have forbidden slots.
bool MipsInstrInfo::HasForbiddenSlot(const MachineInstr &MI) const {
return (MI.getDesc().TSFlags & MipsII::HasForbiddenSlot) != 0;
diff --git a/llvm/lib/Target/Mips/MipsInstrInfo.h b/llvm/lib/Target/Mips/MipsInstrInfo.h
index dc4b9d99b39d2a..bd6aed6f22665f 100644
--- a/llvm/lib/Target/Mips/MipsInstrInfo.h
+++ b/llvm/lib/Target/Mips/MipsInstrInfo.h
@@ -89,6 +89,8 @@ class MipsInstrInfo : public MipsGenInstrInfo {
bool isBranchOffsetInRange(unsigned BranchOpc,
int64_t BrOffset) const override;
+ bool SafeAfterMflo(const MachineInstr &MI) const;
+
/// Predicate to determine if an instruction can go in a forbidden slot.
bool SafeInForbiddenSlot(const MachineInstr &MI) const;
@@ -100,6 +102,8 @@ class MipsInstrInfo : public MipsGenInstrInfo {
bool SafeInLoadDelaySlot(const MachineInstr &MIInSlot,
const MachineInstr &LoadMI) const;
+ bool IsMfloOrMfhi(const MachineInstr &MI) const;
+
/// Predicate to determine if an instruction has a forbidden slot.
bool HasForbiddenSlot(const MachineInstr &MI) const;
diff --git a/llvm/test/CodeGen/Mips/llvm-ir/sdiv.ll b/llvm/test/CodeGen/Mips/llvm-ir/sdiv.ll
index af3d4f50f3fe4f..8d548861f43936 100644
--- a/llvm/test/CodeGen/Mips/llvm-ir/sdiv.ll
+++ b/llvm/test/CodeGen/Mips/llvm-ir/sdiv.ll
@@ -1,6 +1,6 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc < %s -mtriple=mips -mcpu=mips2 -relocation-model=pic \
-; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP32,GP32R0R2
+; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=MIPS2
; RUN: llc < %s -mtriple=mips -mcpu=mips32 -relocation-model=pic \
; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP32,GP32R0R2
; RUN: llc < %s -mtriple=mips -mcpu=mips32r2 -relocation-model=pic \
@@ -13,9 +13,9 @@
; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefix=GP32R6
; RUN: llc < %s -mtriple=mips64 -mcpu=mips3 -relocation-model=pic \
-; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP64,GP64R0R1
+; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=MIPS3
; RUN: llc < %s -mtriple=mips64 -mcpu=mips4 -relocation-model=pic \
-; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP64,GP64R0R1
+; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=MIPS3
; RUN: llc < %s -mtriple=mips64 -mcpu=mips64 -relocation-model=pic \
; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP64,GP64R0R1
; RUN: llc < %s -mtriple=mips64 -mcpu=mips64r2 -relocation-model=pic \
@@ -35,6 +35,11 @@
; RUN: FileCheck %s -check-prefix=MMR6
define signext i1 @sdiv_i1(i1 signext %a, i1 signext %b) {
+; MIPS2-LABEL: sdiv_i1:
+; MIPS2: # %bb.0: # %entry
+; MIPS2-NEXT: jr $ra
+; MIPS2-NEXT: move $2, $4
+;
; GP32-LABEL: sdiv_i1:
; GP32: # %bb.0: # %entry
; GP32-NEXT: jr $ra
@@ -45,6 +50,11 @@ define signext i1 @sdiv_i1(i1 signext %a, i1 signext %b) {
; GP32R6-NEXT: jr $ra
; GP32R6-NEXT: move $2, $4
;
+; MIPS3-LABEL: sdiv_i1:
+; MIPS3: # %bb.0: # %entry
+; MIPS3-NEXT: jr $ra
+; MIPS3-NEXT: move $2, $4
+;
; GP64-LABEL: sdiv_i1:
; GP64: # %bb.0: # %entry
; GP64-NEXT: jr $ra
@@ -70,6 +80,15 @@ entry:
}
define signext i8 @sdiv_i8(i8 signext %a, i8 signext %b) {
+; MIPS2-LABEL: sdiv_i8:
+; MIPS2: # %bb.0: # %entry
+; MIPS2-NEXT: div $zero, $4, $5
+; MIPS2-NEXT: teq $5, $zero, 7
+; MIPS2-NEXT: mflo $1
+; MIPS2-NEXT: sll $1, $1, 24
+; MIPS2-NEXT: jr $ra
+; MIPS2-NEXT: sra $2, $1, 24
+;
; GP32R0R2-LABEL: sdiv_i8:
; GP32R0R2: # %bb.0: # %entry
; GP32R0R2-NEXT: div $zero, $4, $5
@@ -94,6 +113,15 @@ define signext i8 @sdiv_i8(i8 signext %a, i8 signext %b) {
; GP32R6-NEXT: jr $ra
; GP32R6-NEXT: seb $2, $1
;
+; MIPS3-LABEL: sdiv_i8:
+; MIPS3: # %bb.0: # %entry
+; MIPS3-NEXT: div $zero, $4, $5
+; MIPS3-NEXT: teq $5, $zero, 7
+; MIPS3-NEXT: mflo $1
+; MIPS3-NEXT: sll $1, $1, 24
+; MIPS3-NEXT: jr $ra
+; MIPS3-NEXT: sra $2, $1, 24
+;
; GP64R0R1-LABEL: sdiv_i8:
; GP64R0R1: # %bb.0: # %entry
; GP64R0R1-NEXT: div $zero, $4, $5
@@ -138,6 +166,15 @@ entry:
}
define signext i16 @sdiv_i16(i16 signext %a, i16 signext %b) {
+; MIPS2-LABEL: sdiv_i16:
+; MIPS2: # %bb.0: # %entry
+; MIPS2-NEXT: div $zero, $4, $5
+; MIPS2-NEXT: teq $5, $zero, 7
+; MIPS2-NEXT: mflo $1
+; MIPS2-NEXT: sll $1, $1, 16
+; MIPS2-NEXT: jr $ra
+; MIPS2-NEXT: sra $2, $1, 16
+;
; GP32R0R2-LABEL: sdiv_i16:
; GP32R0R2: # %bb.0: # %entry
; GP32R0R2-NEXT: div $zero, $4, $5
@@ -162,6 +199,15 @@ define signext i16 @sdiv_i16(i16 signext %a, i16 signext %b) {
; GP32R6-NEXT: jr $ra
; GP32R6-NEXT: seh $2, $1
;
+; MIPS3-LABEL: sdiv_i16:
+; MIPS3: # %bb.0: # %entry
+; MIPS3-NEXT: div $zero, $4, $5
+; MIPS3-NEXT: teq $5, $zero, 7
+; MIPS3-NEXT: mflo $1
+; MIPS3-NEXT: sll $1, $1, 16
+; MIPS3-NEXT: jr $ra
+; MIPS3-NEXT: sra $2, $1, 16
+;
; GP64R0R1-LABEL: sdiv_i16:
; GP64R0R1: # %bb.0: # %entry
; GP64R0R1-NEXT: div $zero, $4, $5
@@ -206,6 +252,14 @@ entry:
}
define signext i32 @sdiv_i32(i32 signext %a, i32 signext %b) {
+; MIPS2-LABEL: sdiv_i32:
+; MIPS2: # %bb.0: # %entry
+; MIPS2-NEXT: div $zero, $4, $5
+; MIPS2-NEXT: teq $5, $zero, 7
+; MIPS2-NEXT: mflo $2
+; MIPS2-NEXT: jr $ra
+; MIPS2-NEXT: nop
+;
; GP32-LABEL: sdiv_i32:
; GP32: # %bb.0: # %entry
; GP32-NEXT: div $zero, $4, $5
@@ -219,6 +273,14 @@ define signext i32 @sdiv_i32(i32 signext %a, i32 signext %b) {
; GP32R6-NEXT: teq $5, $zero, 7
; GP32R6-NEXT: jrc $ra
;
+; MIPS3-LABEL: sdiv_i32:
+; MIPS3: # %bb.0: # %entry
+; MIPS3-NEXT: div $zero, $4, $5
+; MIPS3-NEXT: teq $5, $zero, 7
+; MIPS3-NEXT: mflo $2
+; MIPS3-NEXT: jr $ra
+; MIPS3-NEXT: nop
+;
; GP64-LABEL: sdiv_i32:
; GP64: # %bb.0: # %entry
; GP64-NEXT: div $zero, $4, $5
@@ -250,6 +312,22 @@ entry:
}
define signext i64 @sdiv_i64(i64 signext %a, i64 signext %b) {
+; MIPS2-LABEL: sdiv_i64:
+; MIPS2: # %bb.0: # %entry
+; MIPS2-NEXT: lui $2, %hi(_gp_disp)
+; MIPS2-NEXT: addiu $2, $2, %lo(_gp_disp)
+; MIPS2-NEXT: addiu $sp, $sp, -24
+; MIPS2-NEXT: .cfi_def_cfa_offset 24
+; MIPS2-NEXT: sw $ra, 20($sp) # 4-byte Folded Spill
+; MIPS2-NEXT: .cfi_offset 31, -4
+; MIPS2-NEXT: addu $gp, $2, $25
+; MIPS2-NEXT: lw $25, %call16(__divdi3)($gp)
+; MIPS2-NEXT: jalr $25
+; MIPS2-NEXT: nop
+; MIPS2-NEXT: lw $ra, 20($sp) # 4-byte Folded Reload
+; MIPS2-NEXT: jr $ra
+; MIPS2-NEXT: addiu $sp, $sp, 24
+;
; GP32-LABEL: sdiv_i64:
; GP32: # %bb.0: # %entry
; GP32-NEXT: lui $2, %hi(_gp_disp)
@@ -281,6 +359,14 @@ define signext i64 @sdiv_i64(i64 signext %a, i64 signext %b) {
; GP32R6-NEXT: jr $ra
; GP32R6-NEXT: addiu $sp, $sp, 24
;
+; MIPS3-LABEL: sdiv_i64:
+; MIPS3: # %bb.0: # %entry
+; MIPS3-NEXT: ddiv $zero, $4, $5
+; MIPS3-NEXT: teq $5, $zero, 7
+; MIPS3-NEXT: mflo $2
+; MIPS3-NEXT: jr $ra
+; MIPS3-NEXT: nop
+;
; GP64-LABEL: sdiv_i64:
; GP64: # %bb.0: # %entry
; GP64-NEXT: ddiv $zero, $4, $5
@@ -332,6 +418,30 @@ entry:
}
define signext i128 @sdiv_i128(i128 signext %a, i128 signext %b) {
+; MIPS2-LABEL: sdiv_i128:
+; MIPS2: # %bb.0: # %entry
+; MIPS2-NEXT: lui $2, %hi(_gp_disp)
+; MIPS2-NEXT: addiu $2, $2, %lo(_gp_disp)
+; MIPS2-NEXT: addiu $sp, $sp, -40
+; MIPS2-NEXT: .cfi_def_cfa_offset 40
+; MIPS2-NEXT: sw $ra, 36($sp) # 4-byte Folded Spill
+; MIPS2-NEXT: .cfi_offset 31, -4
+; MIPS2-NEXT: addu $gp, $2, $25
+; MIPS2-NEXT: lw $1, 60($sp)
+; MIPS2-NEXT: lw $2, 64($sp)
+; MIPS2-NEXT: lw $3, 68($sp)
+; MIPS2-NEXT: sw $3, 28($sp)
+; MIPS2-NEXT: sw $2, 24($sp)
+; MIPS2-NEXT: sw $1, 20($sp)
+; MIPS2-NEXT: lw $1, 56($sp)
+; MIPS2-NEXT: sw $1, 16($sp)
+; MIPS2-NEXT: lw $25, %call16(__divti3)($gp)
+; MIPS2-NEXT: jalr $25
+; MIPS2-NEXT: nop
+; MIPS2-NEXT: lw $ra, 36($sp) # 4-byte Folded Reload
+; MIPS2-NEXT: jr $ra
+; MIPS2-NEXT: addiu $sp, $sp, 40
+;
; GP32-LABEL: sdiv_i128:
; GP32: # %bb.0: # %entry
; GP32-NEXT: lui $2, %hi(_gp_disp)
@@ -379,6 +489,25 @@ define signext i128 @sdiv_i128(i128 signext %a, i128 signext %b) {
; GP32R6-NEXT: jr $ra
; GP32R6-NEXT: addiu $sp, $sp, 40
;
+; MIPS3-LABEL: sdiv_i128:
+; MIPS3: # %bb.0: # %entry
+; MIPS3-NEXT: daddiu $sp, $sp, -16
+; MIPS3-NEXT: .cfi_def_cfa_offset 16
+; MIPS3-NEXT: sd $ra, 8($sp) # 8-byte Folded Spill
+; MIPS3-NEXT: sd $gp, 0($sp) # 8-byte Folded Spill
+; MIPS3-NEXT: .cfi_offset 31, -8
+; MIPS3-NEXT: .cfi_offset 28, -16
+; MIPS3-NEXT: lui $1, %hi(%neg(%gp_rel(sdiv_i128)))
+; MIPS3-NEXT: daddu $1, $1, $25
+; MIPS3-NEXT: daddiu $gp, $1, %lo(%neg(%gp_rel(sdiv_i128)))
+; MIPS3-NEXT: ld $25, %call16(__divti3)($gp)
+; MIPS3-NEXT: jalr $25
+; MIPS3-NEXT: nop
+; MIPS3-NEXT: ld $gp, 0($sp) # 8-byte Folded Reload
+; MIPS3-NEXT: ld $ra, 8($sp) # 8-byte Folded Reload
+; MIPS3-NEXT: jr $ra
+; MIPS3-NEXT: daddiu $sp, $sp, 16
+;
; GP64-LABEL: sdiv_i128:
; GP64: # %bb.0: # %entry
; GP64-NEXT: daddiu $sp, $sp, -16
diff --git a/llvm/test/CodeGen/Mips/llvm-ir/srem.ll b/llvm/test/CodeGen/Mips/llvm-ir/srem.ll
index 6349d5c64ab429..29cb34b8d970f1 100644
--- a/llvm/test/CodeGen/Mips/llvm-ir/srem.ll
+++ b/llvm/test/CodeGen/Mips/llvm-ir/srem.ll
@@ -1,6 +1,6 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc < %s -mtriple=mips -mcpu=mips2 -relocation-model=pic \
-; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP32
+; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=MIPS2
; RUN: llc < %s -mtriple=mips -mcpu=mips32 -relocation-model=pic \
; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP32
; RUN: llc < %s -mtriple=mips -mcpu=mips32r2 -relocation-model=pic \
@@ -13,9 +13,9 @@
; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefix=GP32R6
; RUN: llc < %s -mtriple=mips64 -mcpu=mips3 -relocation-model=pic \
-; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP64
+; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=MIPS3
; RUN: llc < %s -mtriple=mips64 -mcpu=mips4 -relocation-model=pic \
-; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP64
+; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=MIPS3
; RUN: llc < %s -mtriple=mips64 -mcpu=mips64 -relocation-model=pic \
; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP64
; RUN: llc < %s -mtriple=mips64 -mcpu=mips64r2 -relocation-model=pic \
@@ -35,6 +35,11 @@
; RUN: FileCheck %s -check-prefix=MMR6
define signext i1 @srem_i1(i1 signext %a, i1 signext %b) {
+; MIPS2-LABEL: srem_i1:
+; MIPS2: # %bb.0: # %entry
+; MIPS2-NEXT: jr $ra
+; MIPS2-NEXT: addiu $2, $zero, 0
+;
; GP32-LABEL: srem_i1:
; GP32: # %bb.0: # %entry
; GP32-NEXT: jr $ra
@@ -45,6 +50,11 @@ define signext i1 @srem_i1(i1 signext %a, i1 signext %b) {
; GP32R6-NEXT: jr $ra
; GP32R6-NEXT: addiu $2, $zero, 0
;
+; MIPS3-LABEL: srem_i1:
+; MIPS3: # %bb.0: # %entry
+; MIPS3-NEXT: jr $ra
+; MIPS3-NEXT: addiu $2, $zero, 0
+;
; GP64-LABEL: srem_i1:
; GP64: # %bb.0: # %entry
; GP64-NEXT: jr $ra
@@ -70,6 +80,14 @@ entry:
}
define signext i8 @srem_i8(i8 signext %a, i8 signext %b) {
+; MIPS2-LABEL: srem_i8:
+; MIPS2: # %bb.0: # %entry
+; MIPS2-NEXT: div $zero, $4, $5
+; MIPS2-NEXT: teq $5, $zero, 7
+; MIPS2-NEXT: mfhi $2
+; MIPS2-NEXT: jr $ra
+; MIPS2-NEXT: nop
+;
; GP32-LABEL: srem_i8:
; GP32: # %bb.0: # %entry
; GP32-NEXT: div $zero, $4, $5
@@ -83,6 +101,14 @@ define signext i8 @srem_i8(i8 signext %a, i8 signext %b) {
; GP32R6-NEXT: teq $5, $zero, 7
; GP32R6-NEXT: jrc $ra
;
+; MIPS3-LABEL: srem_i8:
+; MIPS3: # %bb.0: # %entry
+; MIPS3-NEXT: div $zero, $4, $5
+; MIPS3-NEXT: teq $5, $zero, 7
+; MIPS3-NEXT: mfhi $2
+; MIPS3-NEXT: jr $ra
+; MIPS3-NEXT: nop
+;
; GP64-LABEL: srem_i8:
; GP64: # %bb.0: # %entry
; GP64-NEXT: div $zero, $4, $5
@@ -114,6 +140,14 @@ entry:
}
define signext i16 @srem_i16(i16 signext %a, i16 signext %b) {
+; MIPS2-LABEL: srem_i16:
+; MIPS2: # %bb.0: # %entry
+; MIPS2-NEXT: div $zero, $4, $5
+; MIPS2-NEXT: teq $5, $zero, 7
+; MIPS2-NEXT: mfhi $2
+; MIPS2-NEXT: jr $ra
+; MIPS2-NEXT: nop
+;
; GP32-LABEL: srem_i16:
; GP32: # %bb.0: # %entry
; GP32-NEXT: div $zero, $4, $5
@@ -127,6 +161,14 @@ define signext i16 @srem_i16(i16 signext %a, i16 signext %b) {
; GP32R6-NEXT: teq $5, $zero, 7
; GP32R6-NEXT: jrc $ra
;
+; MIPS3-LABEL: srem_i16:
+; MIPS3: # %bb.0: # %entry
+; MIPS3-NEXT: div $zero, $4, $5
+; MIPS3-NEXT: teq $5, $zero, 7
+; MIPS3-NEXT: mfhi $2
+; MIPS3-NEXT: jr $ra
+; MIPS3-NEXT: nop
+;
; GP64-LABEL: srem_i16:
; GP64: # %bb.0: # %entry
; GP64-NEXT: div $zero, $4, $5
@@ -158,6 +200,14 @@ entry:
}
define signext i32 @srem_i32(i32 signext %a, i32 signext %b) {
+; MIPS2-LABEL: srem_i32:
+; MIPS2: # %bb.0: # %entry
+; MIPS2-NEXT: div $zero, $4, $5
+; MIPS2-NEXT: teq $5, $zero, 7
+; MIPS2-NEXT: mfhi $2
+; MIPS2-NEXT: jr $ra
+; MIPS2-NEXT: nop
+;
; GP32-LABEL: srem_i32:
; GP32: # %bb.0: # %entry
; GP32-NEXT: div $zero, $4, $5
@@ -171,6 +221,14 @@ define signext i32 @srem_i32(i32 signext %a, i32 signext %b) {
; GP32R6-NEXT: teq $5, $zero, 7
; GP32R6-NEXT: jrc $ra
;
+; MIPS3-LABEL: srem_i32:
+; MIPS3: # %bb.0: # %entry
+; MIPS3-NEXT: div $zero, $4, $5
+; MIPS3-NEXT: teq $5, $zero, 7
+; MIPS3-NEXT: mfhi $2
+; MIPS3-NEXT: jr $ra
+; MIPS3-NEXT: nop
+;
; GP64-LABEL: srem_i32:
; GP64: # %bb.0: # %entry
; GP64-NEXT: div $zero, $4, $5
@@ -202,6 +260,22 @@ entry:
}
define signext i64 @srem_i64(i64 signext %a, i64 signext %b) {
+; MIPS2-LABEL: srem_i64:
+; MIPS2: # %bb.0: # %entry
+; MIPS2-NEXT: lui $2, %hi(_gp_disp)
+; MIPS2-NEXT: addiu $2, $2, %lo(_gp_disp)
+; MIPS2-NEXT: addiu $sp, $sp, -24
+; MIPS2-NEXT: .cfi_def_cfa_offset 24
+; MIPS2-NEXT: sw $ra, 20($sp) # 4-byte Folded Spill
+; MIPS2-NEXT: .cfi_offset 31, -4
+; MIPS2-NEXT: addu $gp, $2, $25
+; MIPS2-NEXT: lw $25, %call16(__moddi3)($gp)
+; MIPS2-NEXT: jalr $25
+; MIPS2-NEXT: nop
+; MIPS2-NEXT: lw $ra, 20($sp) # 4-byte Folded Reload
+; MIPS2-NEXT: jr $ra
+; MIPS2-NEXT: addiu $sp, $sp, 24
+;
; GP32-LABEL: srem_i64:
; GP32: # %bb.0: # %entry
; GP32-NEXT: lui $2, %hi(_gp_disp)
@@ -233,6 +307,14 @@ define signext i64 @srem_i64(i64 signext %a, i64 signext %b) {
; GP32R6-NEXT: jr $ra
; GP32R6-NEXT: addiu $sp, $sp, 24
;
+; MIPS3-LABEL: srem_i64:
+; MIPS3: # %bb.0: # %entry
+; MIPS3-NEXT: ddiv $zero, $4, $5
+; MIPS3-NEXT: teq $5, $zero, 7
+; MIPS3-NEXT: mfhi $2
+; MIPS3-NEXT: jr $ra
+; MIPS3-NEXT: nop
+;
; GP64-LABEL: srem_i64:
; GP64: # %bb.0: # %entry
; GP64-NEXT: ddiv $zero, $4, $5
@@ -284,6 +366,30 @@ entry:
}
define signext i128 @srem_i128(i128 signext %a, i128 signext %b) {
+; MIPS2-LABEL: srem_i128:
+; MIPS2: # %bb.0: # %entry
+; MIPS2-NEXT: lui $2, %hi(_gp_disp)
+; MIPS2-NEXT: addiu $2, $2, %lo(_gp_disp)
+; MIPS2-NEXT: addiu $sp, $sp, -40
+; MIPS2-NEXT: .cfi_def_cfa_offset 40
+; MIPS2-NEXT: sw $ra, 36($sp) # 4-byte Folded Spill
+; MIPS2-NEXT: .cfi_offset 31, -4
+; MIPS2-NEXT: addu $gp, $2, $25
+; MIPS2-NEXT: lw $1, 60($sp)
+; MIPS2-NEXT: lw $2, 64($sp)
+; MIPS2-NEXT: lw $3, 68($sp)
+; MIPS2-NEXT: sw $3, 28($sp)
+; MIPS2-NEXT: sw $2, 24($sp)
+; MIPS2-NEXT: sw $1, 20($sp)
+; MIPS2-NEXT: lw $1, 56($sp)
+; MIPS2-NEXT: sw $1, 16($sp)
+; MIPS2-NEXT: lw $25, %call16(__modti3)($gp)
+; MIPS2-NEXT: jalr $25
+; MIPS2-NEXT: nop
+; MIPS2-NEXT: lw $ra, 36($sp) # 4-byte Folded Reload
+; MIPS2-NEXT: jr $ra
+; MIPS2-NEXT: addiu $sp, $sp, 40
+;
; GP32-LABEL: srem_i128:
; GP32: # %bb.0: # %entry
; GP32-NEXT: lui $2, %hi(_gp_disp)
@@ -331,6 +437,25 @@ define signext i128 @srem_i128(i128 signext %a, i128 signext %b) {
; GP32R6-NEXT: jr $ra
; GP32R6-NEXT: addiu $sp, $sp, 40
;
+; MIPS3-LABEL: srem_i128:
+; MIPS3: # %bb.0: # %entry
+; MIPS3-NEXT: daddiu $sp, $sp, -16
+; MIPS3-NEXT: .cfi_def_cfa_offset 16
+; MIPS3-NEXT: sd $ra, 8($sp) # 8-byte Folded Spill
+; MIPS3-NEXT: sd $gp, 0($sp) # 8-byte Folded Spill
+; MIPS3-NEXT: .cfi_offset 31, -8
+; MIPS3-NEXT: .cfi_offset 28, -16
+; MIPS3-NEXT: lui $1, %hi(%neg(%gp_rel(srem_i128)))
+; MIPS3-NEXT: daddu $1, $1, $25
+; MIPS3-NEXT: daddiu $gp, $1, %lo(%neg(%gp_rel(srem_i128)))
+; MIPS3-NEXT: ld $25, %call16(__modti3)($gp)
+; MIPS3-NEXT: jalr $25
+; MIPS3-NEXT: nop
+; MIPS3-NEXT: ld $gp, 0($sp) # 8-byte Folded Reload
+; MIPS3-NEXT: ld $ra, 8($sp) # 8-byte Folded Reload
+; MIPS3-NEXT: jr $ra
+; MIPS3-NEXT: daddiu $sp, $sp, 16
+;
; GP64-LABEL: srem_i128:
; GP64: # %bb.0: # %entry
; GP64-NEXT: daddiu $sp, $sp, -16
diff --git a/llvm/test/CodeGen/Mips/llvm-ir/two-consecutive-mult.ll b/llvm/test/CodeGen/Mips/llvm-ir/two-consecutive-mult.ll
new file mode 100644
index 00000000000000..db2c660e9bc79b
--- /dev/null
+++ b/llvm/test/CodeGen/Mips/llvm-ir/two-consecutive-mult.ll
@@ -0,0 +1,60 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc < %s -mtriple=mips -mcpu=mips2 -O3 -relocation-model=pic \
+; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=MIPS2
+; RUN: llc < %s -mtriple=mips -mcpu=mips32 -O3 -relocation-model=pic \
+; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=MIPS32
+
+; RUN: llc < %s -mtriple=mips64 -mcpu=mips3 -O3 -relocation-model=pic \
+; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=MIPS3
+; RUN: llc < %s -mtriple=mips64 -mcpu=mips64 -O3 -relocation-model=pic \
+; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=MIPS64
+
+define signext i32 @mult_i32(i32 signext %a, i32 signext %b, i32 signext %c) {
+; MIPS2-LABEL: mult_i32:
+; MIPS2: # %bb.0: # %entry
+; MIPS2-NEXT: mult $4, $5
+; MIPS2-NEXT: mflo $1
+; MIPS2-NEXT: nop
+; MIPS2-NEXT: nop
+; MIPS2-NEXT: mult $1, $6
+; MIPS2-NEXT: mflo $2
+; MIPS2-NEXT: jr $ra
+; MIPS2-NEXT: nop
+;
+; MIPS32-LABEL: mult_i32:
+; MIPS32: # %bb.0: # %entry
+; MIPS32-NEXT: mul $1, $4, $5
+; MIPS32-NEXT: jr $ra
+; MIPS32-NEXT: mul $2, $1, $6
+;
+entry:
+ %mul = mul nsw i32 %a, %b
+ %mul1 = mul nsw i32 %mul, %c
+ ret i32 %mul1
+}
+
+define signext i64 @mul_i64(i64 signext %a, i64 signext %b, i64 signext %c) {
+; MIPS3-LABEL: mul_i64:
+; MIPS3: # %bb.0: # %entry
+; MIPS3-NEXT: dmult $4, $5
+; MIPS3-NEXT: mflo $1
+; MIPS3-NEXT: nop
+; MIPS3-NEXT: nop
+; MIPS3-NEXT: dmult $1, $6
+; MIPS3-NEXT: mflo $2
+; MIPS3-NEXT: jr $ra
+; MIPS3-NEXT: nop
+;
+; MIPS64-LABEL: mul_i64:
+; MIPS64: # %bb.0: # %entry
+; MIPS64-NEXT: dmult $4, $5
+; MIPS64-NEXT: mflo $1
+; MIPS64-NEXT: dmult $1, $6
+; MIPS64-NEXT: jr $ra
+; MIPS64-NEXT: mflo $2
+;
+entry:
+ %mul = mul i64 %a, %b
+ %mul1 = mul i64 %mul, %c
+ ret i64 %mul1
+}
diff --git a/llvm/test/CodeGen/Mips/llvm-ir/two-consecutive-sdiv.ll b/llvm/test/CodeGen/Mips/llvm-ir/two-consecutive-sdiv.ll
new file mode 100644
index 00000000000000..4ec5ecc9e2f17d
--- /dev/null
+++ b/llvm/test/CodeGen/Mips/llvm-ir/two-consecutive-sdiv.ll
@@ -0,0 +1,133 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc < %s -mtriple=mips -mcpu=mips2 -relocation-model=pic \
+; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=MIPS2
+; RUN: llc < %s -mtriple=mips -mcpu=mips32 -relocation-model=pic \
+; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=MIPS32
+
+; RUN: llc < %s -mtriple=mips64 -mcpu=mips3 -relocation-model=pic \
+; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=MIPS3
+; RUN: llc < %s -mtriple=mips64 -mcpu=mips64 -relocation-model=pic \
+; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=MIPS64
+
+; RUN: llc < %s -mtriple=mips -mcpu=mips2 -O0 -relocation-model=pic \
+; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=MIPS2-O0
+; RUN: llc < %s -mtriple=mips -mcpu=mips32 -O0 -relocation-model=pic \
+; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=MIPS32-O0
+
+define signext i32 @sdiv_i32(i32 signext %a, i32 signext %b, i32 signext %c) {
+; MIPS2-LABEL: sdiv_i32:
+; MIPS2: # %bb.0: # %entry
+; MIPS2-NEXT: div $zero, $4, $5
+; MIPS2-NEXT: teq $5, $zero, 7
+; MIPS2-NEXT: mflo $1
+; MIPS2-NEXT: nop
+; MIPS2-NEXT: nop
+; MIPS2-NEXT: div $zero, $1, $6
+; MIPS2-NEXT: teq $6, $zero, 7
+; MIPS2-NEXT: mflo $2
+; MIPS2-NEXT: jr $ra
+; MIPS2-NEXT: nop
+;
+; MIPS32-LABEL: sdiv_i32:
+; MIPS32: # %bb.0: # %entry
+; MIPS32-NEXT: div $zero, $4, $5
+; MIPS32-NEXT: teq $5, $zero, 7
+; MIPS32-NEXT: mflo $1
+; MIPS32-NEXT: div $zero, $1, $6
+; MIPS32-NEXT: teq $6, $zero, 7
+; MIPS32-NEXT: jr $ra
+; MIPS32-NEXT: mflo $2
+;
+entry:
+ %sdiv = sdiv i32 %a, %b
+ %sdiv1 = sdiv i32 %sdiv, %c
+ ret i32 %sdiv1
+}
+
+define signext i64 @sdiv_i64(i64 signext %a, i64 signext %b, i64 signext %c) {
+; MIPS3-LABEL: sdiv_i64:
+; MIPS3: # %bb.0: # %entry
+; MIPS3-NEXT: ddiv $zero, $4, $5
+; MIPS3-NEXT: teq $5, $zero, 7
+; MIPS3-NEXT: mflo $1
+; MIPS3-NEXT: nop
+; MIPS3-NEXT: nop
+; MIPS3-NEXT: ddiv $zero, $1, $6
+; MIPS3-NEXT: teq $6, $zero, 7
+; MIPS3-NEXT: mflo $2
+; MIPS3-NEXT: jr $ra
+; MIPS3-NEXT: nop
+;
+; MIPS64-LABEL: sdiv_i64:
+; MIPS64: # %bb.0: # %entry
+; MIPS64-NEXT: ddiv $zero, $4, $5
+; MIPS64-NEXT: teq $5, $zero, 7
+; MIPS64-NEXT: mflo $1
+; MIPS64-NEXT: ddiv $zero, $1, $6
+; MIPS64-NEXT: teq $6, $zero, 7
+; MIPS64-NEXT: jr $ra
+; MIPS64-NEXT: mflo $2
+;
+entry:
+ %sdiv = sdiv i64 %a, %b
+ %sdiv1 = sdiv i64 %sdiv, %c
+ ret i64 %sdiv1
+}
+
+define signext i32 @sdiv_lw_sdiv_i32(i32 signext %a, i32 signext %b, i32 signext %c) {
+; MIPS2-O0-LABEL: sdiv_lw_sdiv_i32:
+; MIPS2-O0: # %bb.0: # %entry
+; MIPS2-O0-NEXT: addiu $sp, $sp, -16
+; MIPS2-O0-NEXT: .cfi_def_cfa_offset 16
+; MIPS2-O0-NEXT: sw $4, 12($sp)
+; MIPS2-O0-NEXT: sw $5, 8($sp)
+; MIPS2-O0-NEXT: sw $6, 4($sp)
+; MIPS2-O0-NEXT: lw $2, 12($sp)
+; MIPS2-O0-NEXT: lw $1, 8($sp)
+; MIPS2-O0-NEXT: div $zero, $2, $1
+; MIPS2-O0-NEXT: teq $1, $zero, 7
+; MIPS2-O0-NEXT: mflo $2
+; MIPS2-O0-NEXT: lw $1, 4($sp)
+; MIPS2-O0-NEXT: nop
+; MIPS2-O0-NEXT: div $zero, $2, $1
+; MIPS2-O0-NEXT: teq $1, $zero, 7
+; MIPS2-O0-NEXT: mflo $2
+; MIPS2-O0-NEXT: addiu $sp, $sp, 16
+; MIPS2-O0-NEXT: jr $ra
+; MIPS2-O0-NEXT: nop
+;
+; MIPS32-O0-LABEL: sdiv_lw_sdiv_i32:
+; MIPS32-O0: # %bb.0: # %entry
+; MIPS32-O0-NEXT: addiu $sp, $sp, -16
+; MIPS32-O0-NEXT: .cfi_def_cfa_offset 16
+; MIPS32-O0-NEXT: sw $4, 12($sp)
+; MIPS32-O0-NEXT: sw $5, 8($sp)
+; MIPS32-O0-NEXT: sw $6, 4($sp)
+; MIPS32-O0-NEXT: lw $2, 12($sp)
+; MIPS32-O0-NEXT: lw $1, 8($sp)
+; MIPS32-O0-NEXT: div $zero, $2, $1
+; MIPS32-O0-NEXT: teq $1, $zero, 7
+; MIPS32-O0-NEXT: mflo $2
+; MIPS32-O0-NEXT: lw $1, 4($sp)
+; MIPS32-O0-NEXT: div $zero, $2, $1
+; MIPS32-O0-NEXT: teq $1, $zero, 7
+; MIPS32-O0-NEXT: mflo $2
+; MIPS32-O0-NEXT: addiu $sp, $sp, 16
+; MIPS32-O0-NEXT: jr $ra
+; MIPS32-O0-NEXT: nop
+;
+entry:
+ %a.addr = alloca i32, align 4
+ %b.addr = alloca i32, align 4
+ %c.addr = alloca i32, align 4
+ store i32 %a, ptr %a.addr, align 4
+ store i32 %b, ptr %b.addr, align 4
+ store i32 %c, ptr %c.addr, align 4
+ %0 = load i32, ptr %a.addr, align 4
+ %1 = load i32, ptr %b.addr, align 4
+ %sdiv = sdiv i32 %0, %1
+ %2 = load i32, ptr %c.addr, align 4
+ %sdiv1 = sdiv i32 %sdiv, %2
+ ret i32 %sdiv1
+}
+
diff --git a/llvm/test/CodeGen/Mips/llvm-ir/two-consecutive-srem.ll b/llvm/test/CodeGen/Mips/llvm-ir/two-consecutive-srem.ll
new file mode 100644
index 00000000000000..4f729b015b2822
--- /dev/null
+++ b/llvm/test/CodeGen/Mips/llvm-ir/two-consecutive-srem.ll
@@ -0,0 +1,133 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc < %s -mtriple=mips -mcpu=mips2 -relocation-model=pic \
+; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=MIPS2
+; RUN: llc < %s -mtriple=mips -mcpu=mips32 -relocation-model=pic \
+; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=MIPS32
+
+; RUN: llc < %s -mtriple=mips64 -mcpu=mips3 -relocation-model=pic \
+; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=MIPS3
+; RUN: llc < %s -mtriple=mips64 -mcpu=mips64 -relocation-model=pic \
+; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=MIPS64
+
+; RUN: llc < %s -mtriple=mips -mcpu=mips2 -O0 -relocation-model=pic \
+; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=MIPS2-O0
+; RUN: llc < %s -mtriple=mips -mcpu=mips32 -O0 -relocation-model=pic \
+; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=MIPS32-O0
+
+define signext i32 @srem_i32(i32 signext %a, i32 signext %b, i32 signext %c) {
+; MIPS2-LABEL: srem_i32:
+; MIPS2: # %bb.0: # %entry
+; MIPS2-NEXT: div $zero, $4, $5
+; MIPS2-NEXT: teq $5, $zero, 7
+; MIPS2-NEXT: mfhi $1
+; MIPS2-NEXT: nop
+; MIPS2-NEXT: nop
+; MIPS2-NEXT: div $zero, $1, $6
+; MIPS2-NEXT: teq $6, $zero, 7
+; MIPS2-NEXT: mfhi $2
+; MIPS2-NEXT: jr $ra
+; MIPS2-NEXT: nop
+;
+; MIPS32-LABEL: srem_i32:
+; MIPS32: # %bb.0: # %entry
+; MIPS32-NEXT: div $zero, $4, $5
+; MIPS32-NEXT: teq $5, $zero, 7
+; MIPS32-NEXT: mfhi $1
+; MIPS32-NEXT: div $zero, $1, $6
+; MIPS32-NEXT: teq $6, $zero, 7
+; MIPS32-NEXT: jr $ra
+; MIPS32-NEXT: mfhi $2
+;
+entry:
+ %rem = srem i32 %a, %b
+ %rem1 = srem i32 %rem, %c
+ ret i32 %rem1
+}
+
+define signext i64 @srem_i64(i64 signext %a, i64 signext %b, i64 signext %c) {
+; MIPS3-LABEL: srem_i64:
+; MIPS3: # %bb.0: # %entry
+; MIPS3-NEXT: ddiv $zero, $4, $5
+; MIPS3-NEXT: teq $5, $zero, 7
+; MIPS3-NEXT: mfhi $1
+; MIPS3-NEXT: nop
+; MIPS3-NEXT: nop
+; MIPS3-NEXT: ddiv $zero, $1, $6
+; MIPS3-NEXT: teq $6, $zero, 7
+; MIPS3-NEXT: mfhi $2
+; MIPS3-NEXT: jr $ra
+; MIPS3-NEXT: nop
+;
+; MIPS64-LABEL: srem_i64:
+; MIPS64: # %bb.0: # %entry
+; MIPS64-NEXT: ddiv $zero, $4, $5
+; MIPS64-NEXT: teq $5, $zero, 7
+; MIPS64-NEXT: mfhi $1
+; MIPS64-NEXT: ddiv $zero, $1, $6
+; MIPS64-NEXT: teq $6, $zero, 7
+; MIPS64-NEXT: jr $ra
+; MIPS64-NEXT: mfhi $2
+;
+entry:
+ %rem = srem i64 %a, %b
+ %rem1 = srem i64 %rem, %c
+ ret i64 %rem1
+}
+
+define signext i32 @srem_lw_srem_i32(i32 signext %a, i32 signext %b, i32 signext %c) {
+; MIPS2-O0-LABEL: srem_lw_srem_i32:
+; MIPS2-O0: # %bb.0: # %entry
+; MIPS2-O0-NEXT: addiu $sp, $sp, -16
+; MIPS2-O0-NEXT: .cfi_def_cfa_offset 16
+; MIPS2-O0-NEXT: sw $4, 12($sp)
+; MIPS2-O0-NEXT: sw $5, 8($sp)
+; MIPS2-O0-NEXT: sw $6, 4($sp)
+; MIPS2-O0-NEXT: lw $2, 12($sp)
+; MIPS2-O0-NEXT: lw $1, 8($sp)
+; MIPS2-O0-NEXT: div $zero, $2, $1
+; MIPS2-O0-NEXT: teq $1, $zero, 7
+; MIPS2-O0-NEXT: mfhi $2
+; MIPS2-O0-NEXT: lw $1, 4($sp)
+; MIPS2-O0-NEXT: nop
+; MIPS2-O0-NEXT: div $zero, $2, $1
+; MIPS2-O0-NEXT: teq $1, $zero, 7
+; MIPS2-O0-NEXT: mfhi $2
+; MIPS2-O0-NEXT: addiu $sp, $sp, 16
+; MIPS2-O0-NEXT: jr $ra
+; MIPS2-O0-NEXT: nop
+;
+; MIPS32-O0-LABEL: srem_lw_srem_i32:
+; MIPS32-O0: # %bb.0: # %entry
+; MIPS32-O0-NEXT: addiu $sp, $sp, -16
+; MIPS32-O0-NEXT: .cfi_def_cfa_offset 16
+; MIPS32-O0-NEXT: sw $4, 12($sp)
+; MIPS32-O0-NEXT: sw $5, 8($sp)
+; MIPS32-O0-NEXT: sw $6, 4($sp)
+; MIPS32-O0-NEXT: lw $2, 12($sp)
+; MIPS32-O0-NEXT: lw $1, 8($sp)
+; MIPS32-O0-NEXT: div $zero, $2, $1
+; MIPS32-O0-NEXT: teq $1, $zero, 7
+; MIPS32-O0-NEXT: mfhi $2
+; MIPS32-O0-NEXT: lw $1, 4($sp)
+; MIPS32-O0-NEXT: div $zero, $2, $1
+; MIPS32-O0-NEXT: teq $1, $zero, 7
+; MIPS32-O0-NEXT: mfhi $2
+; MIPS32-O0-NEXT: addiu $sp, $sp, 16
+; MIPS32-O0-NEXT: jr $ra
+; MIPS32-O0-NEXT: nop
+;
+entry:
+ %a.addr = alloca i32, align 4
+ %b.addr = alloca i32, align 4
+ %c.addr = alloca i32, align 4
+ store i32 %a, ptr %a.addr, align 4
+ store i32 %b, ptr %b.addr, align 4
+ store i32 %c, ptr %c.addr, align 4
+ %0 = load i32, ptr %a.addr, align 4
+ %1 = load i32, ptr %b.addr, align 4
+ %rem = srem i32 %0, %1
+ %2 = load i32, ptr %c.addr, align 4
+ %rem1 = srem i32 %rem, %2
+ ret i32 %rem1
+}
+
diff --git a/llvm/test/CodeGen/Mips/llvm-ir/two-consecutive-udiv.ll b/llvm/test/CodeGen/Mips/llvm-ir/two-consecutive-udiv.ll
new file mode 100644
index 00000000000000..97ac0d8031cf55
--- /dev/null
+++ b/llvm/test/CodeGen/Mips/llvm-ir/two-consecutive-udiv.ll
@@ -0,0 +1,133 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc < %s -mtriple=mips -mcpu=mips2 -relocation-model=pic \
+; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=MIPS2
+; RUN: llc < %s -mtriple=mips -mcpu=mips32 -relocation-model=pic \
+; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=MIPS32
+
+; RUN: llc < %s -mtriple=mips64 -mcpu=mips3 -relocation-model=pic \
+; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=MIPS3
+; RUN: llc < %s -mtriple=mips64 -mcpu=mips64 -relocation-model=pic \
+; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=MIPS64
+
+; RUN: llc < %s -mtriple=mips -mcpu=mips2 -O0 -relocation-model=pic \
+; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=MIPS2-O0
+; RUN: llc < %s -mtriple=mips -mcpu=mips32 -O0 -relocation-model=pic \
+; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=MIPS32-O0
+
+define signext i32 @udiv_i32(i32 signext %a, i32 signext %b, i32 signext %c) {
+; MIPS2-LABEL: udiv_i32:
+; MIPS2: # %bb.0: # %entry
+; MIPS2-NEXT: divu $zero, $4, $5
+; MIPS2-NEXT: teq $5, $zero, 7
+; MIPS2-NEXT: mflo $1
+; MIPS2-NEXT: nop
+; MIPS2-NEXT: nop
+; MIPS2-NEXT: divu $zero, $1, $6
+; MIPS2-NEXT: teq $6, $zero, 7
+; MIPS2-NEXT: mflo $2
+; MIPS2-NEXT: jr $ra
+; MIPS2-NEXT: nop
+;
+; MIPS32-LABEL: udiv_i32:
+; MIPS32: # %bb.0: # %entry
+; MIPS32-NEXT: divu $zero, $4, $5
+; MIPS32-NEXT: teq $5, $zero, 7
+; MIPS32-NEXT: mflo $1
+; MIPS32-NEXT: divu $zero, $1, $6
+; MIPS32-NEXT: teq $6, $zero, 7
+; MIPS32-NEXT: jr $ra
+; MIPS32-NEXT: mflo $2
+;
+entry:
+ %udiv = udiv i32 %a, %b
+ %udiv1 = udiv i32 %udiv, %c
+ ret i32 %udiv1
+}
+
+define signext i64 @udiv_i64(i64 signext %a, i64 signext %b, i64 signext %c) {
+; MIPS3-LABEL: udiv_i64:
+; MIPS3: # %bb.0: # %entry
+; MIPS3-NEXT: ddivu $zero, $4, $5
+; MIPS3-NEXT: teq $5, $zero, 7
+; MIPS3-NEXT: mflo $1
+; MIPS3-NEXT: nop
+; MIPS3-NEXT: nop
+; MIPS3-NEXT: ddivu $zero, $1, $6
+; MIPS3-NEXT: teq $6, $zero, 7
+; MIPS3-NEXT: mflo $2
+; MIPS3-NEXT: jr $ra
+; MIPS3-NEXT: nop
+;
+; MIPS64-LABEL: udiv_i64:
+; MIPS64: # %bb.0: # %entry
+; MIPS64-NEXT: ddivu $zero, $4, $5
+; MIPS64-NEXT: teq $5, $zero, 7
+; MIPS64-NEXT: mflo $1
+; MIPS64-NEXT: ddivu $zero, $1, $6
+; MIPS64-NEXT: teq $6, $zero, 7
+; MIPS64-NEXT: jr $ra
+; MIPS64-NEXT: mflo $2
+;
+entry:
+ %udiv = udiv i64 %a, %b
+ %udiv1 = udiv i64 %udiv, %c
+ ret i64 %udiv1
+}
+
+define signext i32 @udiv_lw_udiv_i32(i32 signext %a, i32 signext %b, i32 signext %c) {
+; MIPS2-O0-LABEL: udiv_lw_udiv_i32:
+; MIPS2-O0: # %bb.0: # %entry
+; MIPS2-O0-NEXT: addiu $sp, $sp, -16
+; MIPS2-O0-NEXT: .cfi_def_cfa_offset 16
+; MIPS2-O0-NEXT: sw $4, 12($sp)
+; MIPS2-O0-NEXT: sw $5, 8($sp)
+; MIPS2-O0-NEXT: sw $6, 4($sp)
+; MIPS2-O0-NEXT: lw $2, 12($sp)
+; MIPS2-O0-NEXT: lw $1, 8($sp)
+; MIPS2-O0-NEXT: divu $zero, $2, $1
+; MIPS2-O0-NEXT: teq $1, $zero, 7
+; MIPS2-O0-NEXT: mflo $2
+; MIPS2-O0-NEXT: lw $1, 4($sp)
+; MIPS2-O0-NEXT: nop
+; MIPS2-O0-NEXT: divu $zero, $2, $1
+; MIPS2-O0-NEXT: teq $1, $zero, 7
+; MIPS2-O0-NEXT: mflo $2
+; MIPS2-O0-NEXT: addiu $sp, $sp, 16
+; MIPS2-O0-NEXT: jr $ra
+; MIPS2-O0-NEXT: nop
+;
+; MIPS32-O0-LABEL: udiv_lw_udiv_i32:
+; MIPS32-O0: # %bb.0: # %entry
+; MIPS32-O0-NEXT: addiu $sp, $sp, -16
+; MIPS32-O0-NEXT: .cfi_def_cfa_offset 16
+; MIPS32-O0-NEXT: sw $4, 12($sp)
+; MIPS32-O0-NEXT: sw $5, 8($sp)
+; MIPS32-O0-NEXT: sw $6, 4($sp)
+; MIPS32-O0-NEXT: lw $2, 12($sp)
+; MIPS32-O0-NEXT: lw $1, 8($sp)
+; MIPS32-O0-NEXT: divu $zero, $2, $1
+; MIPS32-O0-NEXT: teq $1, $zero, 7
+; MIPS32-O0-NEXT: mflo $2
+; MIPS32-O0-NEXT: lw $1, 4($sp)
+; MIPS32-O0-NEXT: divu $zero, $2, $1
+; MIPS32-O0-NEXT: teq $1, $zero, 7
+; MIPS32-O0-NEXT: mflo $2
+; MIPS32-O0-NEXT: addiu $sp, $sp, 16
+; MIPS32-O0-NEXT: jr $ra
+; MIPS32-O0-NEXT: nop
+;
+entry:
+ %a.addr = alloca i32, align 4
+ %b.addr = alloca i32, align 4
+ %c.addr = alloca i32, align 4
+ store i32 %a, ptr %a.addr, align 4
+ store i32 %b, ptr %b.addr, align 4
+ store i32 %c, ptr %c.addr, align 4
+ %0 = load i32, ptr %a.addr, align 4
+ %1 = load i32, ptr %b.addr, align 4
+ %udiv = udiv i32 %0, %1
+ %2 = load i32, ptr %c.addr, align 4
+ %udiv1 = udiv i32 %udiv, %2
+ ret i32 %udiv1
+}
+
diff --git a/llvm/test/CodeGen/Mips/llvm-ir/two-consecutive-urem.ll b/llvm/test/CodeGen/Mips/llvm-ir/two-consecutive-urem.ll
new file mode 100644
index 00000000000000..e1819f1d57b7db
--- /dev/null
+++ b/llvm/test/CodeGen/Mips/llvm-ir/two-consecutive-urem.ll
@@ -0,0 +1,133 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc < %s -mtriple=mips -mcpu=mips2 -relocation-model=pic \
+; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=MIPS2
+; RUN: llc < %s -mtriple=mips -mcpu=mips32 -relocation-model=pic \
+; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=MIPS32
+
+; RUN: llc < %s -mtriple=mips64 -mcpu=mips3 -relocation-model=pic \
+; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=MIPS3
+; RUN: llc < %s -mtriple=mips64 -mcpu=mips64 -relocation-model=pic \
+; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=MIPS64
+
+; RUN: llc < %s -mtriple=mips -mcpu=mips2 -O0 -relocation-model=pic \
+; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=MIPS2-O0
+; RUN: llc < %s -mtriple=mips -mcpu=mips32 -O0 -relocation-model=pic \
+; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=MIPS32-O0
+
+define signext i32 @urem_i32(i32 signext %a, i32 signext %b, i32 signext %c) {
+; MIPS2-LABEL: urem_i32:
+; MIPS2: # %bb.0: # %entry
+; MIPS2-NEXT: divu $zero, $4, $5
+; MIPS2-NEXT: teq $5, $zero, 7
+; MIPS2-NEXT: mfhi $1
+; MIPS2-NEXT: nop
+; MIPS2-NEXT: nop
+; MIPS2-NEXT: divu $zero, $1, $6
+; MIPS2-NEXT: teq $6, $zero, 7
+; MIPS2-NEXT: mfhi $2
+; MIPS2-NEXT: jr $ra
+; MIPS2-NEXT: nop
+;
+; MIPS32-LABEL: urem_i32:
+; MIPS32: # %bb.0: # %entry
+; MIPS32-NEXT: divu $zero, $4, $5
+; MIPS32-NEXT: teq $5, $zero, 7
+; MIPS32-NEXT: mfhi $1
+; MIPS32-NEXT: divu $zero, $1, $6
+; MIPS32-NEXT: teq $6, $zero, 7
+; MIPS32-NEXT: jr $ra
+; MIPS32-NEXT: mfhi $2
+;
+entry:
+ %urem = urem i32 %a, %b
+ %urem1 = urem i32 %urem, %c
+ ret i32 %urem1
+}
+
+define signext i64 @urem_i64(i64 signext %a, i64 signext %b, i64 signext %c) {
+; MIPS3-LABEL: urem_i64:
+; MIPS3: # %bb.0: # %entry
+; MIPS3-NEXT: ddivu $zero, $4, $5
+; MIPS3-NEXT: teq $5, $zero, 7
+; MIPS3-NEXT: mfhi $1
+; MIPS3-NEXT: nop
+; MIPS3-NEXT: nop
+; MIPS3-NEXT: ddivu $zero, $1, $6
+; MIPS3-NEXT: teq $6, $zero, 7
+; MIPS3-NEXT: mfhi $2
+; MIPS3-NEXT: jr $ra
+; MIPS3-NEXT: nop
+;
+; MIPS64-LABEL: urem_i64:
+; MIPS64: # %bb.0: # %entry
+; MIPS64-NEXT: ddivu $zero, $4, $5
+; MIPS64-NEXT: teq $5, $zero, 7
+; MIPS64-NEXT: mfhi $1
+; MIPS64-NEXT: ddivu $zero, $1, $6
+; MIPS64-NEXT: teq $6, $zero, 7
+; MIPS64-NEXT: jr $ra
+; MIPS64-NEXT: mfhi $2
+;
+entry:
+ %urem = urem i64 %a, %b
+ %urem1 = urem i64 %urem, %c
+ ret i64 %urem1
+}
+
+define signext i32 @urem_lw_urem_i32(i32 signext %a, i32 signext %b, i32 signext %c) {
+; MIPS2-O0-LABEL: urem_lw_urem_i32:
+; MIPS2-O0: # %bb.0: # %entry
+; MIPS2-O0-NEXT: addiu $sp, $sp, -16
+; MIPS2-O0-NEXT: .cfi_def_cfa_offset 16
+; MIPS2-O0-NEXT: sw $4, 12($sp)
+; MIPS2-O0-NEXT: sw $5, 8($sp)
+; MIPS2-O0-NEXT: sw $6, 4($sp)
+; MIPS2-O0-NEXT: lw $2, 12($sp)
+; MIPS2-O0-NEXT: lw $1, 8($sp)
+; MIPS2-O0-NEXT: divu $zero, $2, $1
+; MIPS2-O0-NEXT: teq $1, $zero, 7
+; MIPS2-O0-NEXT: mfhi $2
+; MIPS2-O0-NEXT: lw $1, 4($sp)
+; MIPS2-O0-NEXT: nop
+; MIPS2-O0-NEXT: divu $zero, $2, $1
+; MIPS2-O0-NEXT: teq $1, $zero, 7
+; MIPS2-O0-NEXT: mfhi $2
+; MIPS2-O0-NEXT: addiu $sp, $sp, 16
+; MIPS2-O0-NEXT: jr $ra
+; MIPS2-O0-NEXT: nop
+;
+; MIPS32-O0-LABEL: urem_lw_urem_i32:
+; MIPS32-O0: # %bb.0: # %entry
+; MIPS32-O0-NEXT: addiu $sp, $sp, -16
+; MIPS32-O0-NEXT: .cfi_def_cfa_offset 16
+; MIPS32-O0-NEXT: sw $4, 12($sp)
+; MIPS32-O0-NEXT: sw $5, 8($sp)
+; MIPS32-O0-NEXT: sw $6, 4($sp)
+; MIPS32-O0-NEXT: lw $2, 12($sp)
+; MIPS32-O0-NEXT: lw $1, 8($sp)
+; MIPS32-O0-NEXT: divu $zero, $2, $1
+; MIPS32-O0-NEXT: teq $1, $zero, 7
+; MIPS32-O0-NEXT: mfhi $2
+; MIPS32-O0-NEXT: lw $1, 4($sp)
+; MIPS32-O0-NEXT: divu $zero, $2, $1
+; MIPS32-O0-NEXT: teq $1, $zero, 7
+; MIPS32-O0-NEXT: mfhi $2
+; MIPS32-O0-NEXT: addiu $sp, $sp, 16
+; MIPS32-O0-NEXT: jr $ra
+; MIPS32-O0-NEXT: nop
+;
+entry:
+ %a.addr = alloca i32, align 4
+ %b.addr = alloca i32, align 4
+ %c.addr = alloca i32, align 4
+ store i32 %a, ptr %a.addr, align 4
+ store i32 %b, ptr %b.addr, align 4
+ store i32 %c, ptr %c.addr, align 4
+ %0 = load i32, ptr %a.addr, align 4
+ %1 = load i32, ptr %b.addr, align 4
+ %rem = urem i32 %0, %1
+ %2 = load i32, ptr %c.addr, align 4
+ %urem1 = urem i32 %rem, %2
+ ret i32 %urem1
+}
+
diff --git a/llvm/test/CodeGen/Mips/llvm-ir/udiv.ll b/llvm/test/CodeGen/Mips/llvm-ir/udiv.ll
index e3dd347e723bc8..cc2c6614e69c8f 100644
--- a/llvm/test/CodeGen/Mips/llvm-ir/udiv.ll
+++ b/llvm/test/CodeGen/Mips/llvm-ir/udiv.ll
@@ -1,6 +1,6 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc < %s -mtriple=mips -mcpu=mips2 -relocation-model=pic \
-; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP32
+; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=MIPS2
; RUN: llc < %s -mtriple=mips -mcpu=mips32 -relocation-model=pic \
; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP32
; RUN: llc < %s -mtriple=mips -mcpu=mips32r2 -relocation-model=pic \
@@ -13,9 +13,9 @@
; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefix=GP32R6
; RUN: llc < %s -mtriple=mips64 -mcpu=mips3 -relocation-model=pic \
-; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP64
+; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=MIPS3
; RUN: llc < %s -mtriple=mips64 -mcpu=mips4 -relocation-model=pic \
-; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP64
+; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=MIPS3
; RUN: llc < %s -mtriple=mips64 -mcpu=mips64 -relocation-model=pic \
; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP64
; RUN: llc < %s -mtriple=mips64 -mcpu=mips64r2 -relocation-model=pic \
@@ -35,6 +35,11 @@
; RUN: FileCheck %s -check-prefix=MMR6
define zeroext i1 @udiv_i1(i1 zeroext %a, i1 zeroext %b) {
+; MIPS2-LABEL: udiv_i1:
+; MIPS2: # %bb.0: # %entry
+; MIPS2-NEXT: jr $ra
+; MIPS2-NEXT: move $2, $4
+;
; GP32-LABEL: udiv_i1:
; GP32: # %bb.0: # %entry
; GP32-NEXT: jr $ra
@@ -45,6 +50,11 @@ define zeroext i1 @udiv_i1(i1 zeroext %a, i1 zeroext %b) {
; GP32R6-NEXT: jr $ra
; GP32R6-NEXT: move $2, $4
;
+; MIPS3-LABEL: udiv_i1:
+; MIPS3: # %bb.0: # %entry
+; MIPS3-NEXT: jr $ra
+; MIPS3-NEXT: move $2, $4
+;
; GP64-LABEL: udiv_i1:
; GP64: # %bb.0: # %entry
; GP64-NEXT: jr $ra
@@ -70,6 +80,14 @@ entry:
}
define zeroext i8 @udiv_i8(i8 zeroext %a, i8 zeroext %b) {
+; MIPS2-LABEL: udiv_i8:
+; MIPS2: # %bb.0: # %entry
+; MIPS2-NEXT: divu $zero, $4, $5
+; MIPS2-NEXT: teq $5, $zero, 7
+; MIPS2-NEXT: mflo $2
+; MIPS2-NEXT: jr $ra
+; MIPS2-NEXT: nop
+;
; GP32-LABEL: udiv_i8:
; GP32: # %bb.0: # %entry
; GP32-NEXT: divu $zero, $4, $5
@@ -83,6 +101,14 @@ define zeroext i8 @udiv_i8(i8 zeroext %a, i8 zeroext %b) {
; GP32R6-NEXT: teq $5, $zero, 7
; GP32R6-NEXT: jrc $ra
;
+; MIPS3-LABEL: udiv_i8:
+; MIPS3: # %bb.0: # %entry
+; MIPS3-NEXT: divu $zero, $4, $5
+; MIPS3-NEXT: teq $5, $zero, 7
+; MIPS3-NEXT: mflo $2
+; MIPS3-NEXT: jr $ra
+; MIPS3-NEXT: nop
+;
; GP64-LABEL: udiv_i8:
; GP64: # %bb.0: # %entry
; GP64-NEXT: divu $zero, $4, $5
@@ -114,6 +140,14 @@ entry:
}
define zeroext i16 @udiv_i16(i16 zeroext %a, i16 zeroext %b) {
+; MIPS2-LABEL: udiv_i16:
+; MIPS2: # %bb.0: # %entry
+; MIPS2-NEXT: divu $zero, $4, $5
+; MIPS2-NEXT: teq $5, $zero, 7
+; MIPS2-NEXT: mflo $2
+; MIPS2-NEXT: jr $ra
+; MIPS2-NEXT: nop
+;
; GP32-LABEL: udiv_i16:
; GP32: # %bb.0: # %entry
; GP32-NEXT: divu $zero, $4, $5
@@ -127,6 +161,14 @@ define zeroext i16 @udiv_i16(i16 zeroext %a, i16 zeroext %b) {
; GP32R6-NEXT: teq $5, $zero, 7
; GP32R6-NEXT: jrc $ra
;
+; MIPS3-LABEL: udiv_i16:
+; MIPS3: # %bb.0: # %entry
+; MIPS3-NEXT: divu $zero, $4, $5
+; MIPS3-NEXT: teq $5, $zero, 7
+; MIPS3-NEXT: mflo $2
+; MIPS3-NEXT: jr $ra
+; MIPS3-NEXT: nop
+;
; GP64-LABEL: udiv_i16:
; GP64: # %bb.0: # %entry
; GP64-NEXT: divu $zero, $4, $5
@@ -158,6 +200,14 @@ entry:
}
define signext i32 @udiv_i32(i32 signext %a, i32 signext %b) {
+; MIPS2-LABEL: udiv_i32:
+; MIPS2: # %bb.0: # %entry
+; MIPS2-NEXT: divu $zero, $4, $5
+; MIPS2-NEXT: teq $5, $zero, 7
+; MIPS2-NEXT: mflo $2
+; MIPS2-NEXT: jr $ra
+; MIPS2-NEXT: nop
+;
; GP32-LABEL: udiv_i32:
; GP32: # %bb.0: # %entry
; GP32-NEXT: divu $zero, $4, $5
@@ -171,6 +221,14 @@ define signext i32 @udiv_i32(i32 signext %a, i32 signext %b) {
; GP32R6-NEXT: teq $5, $zero, 7
; GP32R6-NEXT: jrc $ra
;
+; MIPS3-LABEL: udiv_i32:
+; MIPS3: # %bb.0: # %entry
+; MIPS3-NEXT: divu $zero, $4, $5
+; MIPS3-NEXT: teq $5, $zero, 7
+; MIPS3-NEXT: mflo $2
+; MIPS3-NEXT: jr $ra
+; MIPS3-NEXT: nop
+;
; GP64-LABEL: udiv_i32:
; GP64: # %bb.0: # %entry
; GP64-NEXT: divu $zero, $4, $5
@@ -202,6 +260,22 @@ entry:
}
define signext i64 @udiv_i64(i64 signext %a, i64 signext %b) {
+; MIPS2-LABEL: udiv_i64:
+; MIPS2: # %bb.0: # %entry
+; MIPS2-NEXT: lui $2, %hi(_gp_disp)
+; MIPS2-NEXT: addiu $2, $2, %lo(_gp_disp)
+; MIPS2-NEXT: addiu $sp, $sp, -24
+; MIPS2-NEXT: .cfi_def_cfa_offset 24
+; MIPS2-NEXT: sw $ra, 20($sp) # 4-byte Folded Spill
+; MIPS2-NEXT: .cfi_offset 31, -4
+; MIPS2-NEXT: addu $gp, $2, $25
+; MIPS2-NEXT: lw $25, %call16(__udivdi3)($gp)
+; MIPS2-NEXT: jalr $25
+; MIPS2-NEXT: nop
+; MIPS2-NEXT: lw $ra, 20($sp) # 4-byte Folded Reload
+; MIPS2-NEXT: jr $ra
+; MIPS2-NEXT: addiu $sp, $sp, 24
+;
; GP32-LABEL: udiv_i64:
; GP32: # %bb.0: # %entry
; GP32-NEXT: lui $2, %hi(_gp_disp)
@@ -233,6 +307,14 @@ define signext i64 @udiv_i64(i64 signext %a, i64 signext %b) {
; GP32R6-NEXT: jr $ra
; GP32R6-NEXT: addiu $sp, $sp, 24
;
+; MIPS3-LABEL: udiv_i64:
+; MIPS3: # %bb.0: # %entry
+; MIPS3-NEXT: ddivu $zero, $4, $5
+; MIPS3-NEXT: teq $5, $zero, 7
+; MIPS3-NEXT: mflo $2
+; MIPS3-NEXT: jr $ra
+; MIPS3-NEXT: nop
+;
; GP64-LABEL: udiv_i64:
; GP64: # %bb.0: # %entry
; GP64-NEXT: ddivu $zero, $4, $5
@@ -284,6 +366,30 @@ entry:
}
define signext i128 @udiv_i128(i128 signext %a, i128 signext %b) {
+; MIPS2-LABEL: udiv_i128:
+; MIPS2: # %bb.0: # %entry
+; MIPS2-NEXT: lui $2, %hi(_gp_disp)
+; MIPS2-NEXT: addiu $2, $2, %lo(_gp_disp)
+; MIPS2-NEXT: addiu $sp, $sp, -40
+; MIPS2-NEXT: .cfi_def_cfa_offset 40
+; MIPS2-NEXT: sw $ra, 36($sp) # 4-byte Folded Spill
+; MIPS2-NEXT: .cfi_offset 31, -4
+; MIPS2-NEXT: addu $gp, $2, $25
+; MIPS2-NEXT: lw $1, 60($sp)
+; MIPS2-NEXT: lw $2, 64($sp)
+; MIPS2-NEXT: lw $3, 68($sp)
+; MIPS2-NEXT: sw $3, 28($sp)
+; MIPS2-NEXT: sw $2, 24($sp)
+; MIPS2-NEXT: sw $1, 20($sp)
+; MIPS2-NEXT: lw $1, 56($sp)
+; MIPS2-NEXT: sw $1, 16($sp)
+; MIPS2-NEXT: lw $25, %call16(__udivti3)($gp)
+; MIPS2-NEXT: jalr $25
+; MIPS2-NEXT: nop
+; MIPS2-NEXT: lw $ra, 36($sp) # 4-byte Folded Reload
+; MIPS2-NEXT: jr $ra
+; MIPS2-NEXT: addiu $sp, $sp, 40
+;
; GP32-LABEL: udiv_i128:
; GP32: # %bb.0: # %entry
; GP32-NEXT: lui $2, %hi(_gp_disp)
@@ -331,6 +437,25 @@ define signext i128 @udiv_i128(i128 signext %a, i128 signext %b) {
; GP32R6-NEXT: jr $ra
; GP32R6-NEXT: addiu $sp, $sp, 40
;
+; MIPS3-LABEL: udiv_i128:
+; MIPS3: # %bb.0: # %entry
+; MIPS3-NEXT: daddiu $sp, $sp, -16
+; MIPS3-NEXT: .cfi_def_cfa_offset 16
+; MIPS3-NEXT: sd $ra, 8($sp) # 8-byte Folded Spill
+; MIPS3-NEXT: sd $gp, 0($sp) # 8-byte Folded Spill
+; MIPS3-NEXT: .cfi_offset 31, -8
+; MIPS3-NEXT: .cfi_offset 28, -16
+; MIPS3-NEXT: lui $1, %hi(%neg(%gp_rel(udiv_i128)))
+; MIPS3-NEXT: daddu $1, $1, $25
+; MIPS3-NEXT: daddiu $gp, $1, %lo(%neg(%gp_rel(udiv_i128)))
+; MIPS3-NEXT: ld $25, %call16(__udivti3)($gp)
+; MIPS3-NEXT: jalr $25
+; MIPS3-NEXT: nop
+; MIPS3-NEXT: ld $gp, 0($sp) # 8-byte Folded Reload
+; MIPS3-NEXT: ld $ra, 8($sp) # 8-byte Folded Reload
+; MIPS3-NEXT: jr $ra
+; MIPS3-NEXT: daddiu $sp, $sp, 16
+;
; GP64-LABEL: udiv_i128:
; GP64: # %bb.0: # %entry
; GP64-NEXT: daddiu $sp, $sp, -16
diff --git a/llvm/test/CodeGen/Mips/llvm-ir/urem.ll b/llvm/test/CodeGen/Mips/llvm-ir/urem.ll
index 4105d67da6f1ac..5da1f614b8f157 100644
--- a/llvm/test/CodeGen/Mips/llvm-ir/urem.ll
+++ b/llvm/test/CodeGen/Mips/llvm-ir/urem.ll
@@ -1,6 +1,6 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc < %s -mtriple=mips -mcpu=mips2 -relocation-model=pic \
-; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP32,GP32R0R2
+; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=MIPS2
; RUN: llc < %s -mtriple=mips -mcpu=mips32 -relocation-model=pic \
; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP32,GP32R0R2
; RUN: llc < %s -mtriple=mips -mcpu=mips32r2 -relocation-model=pic \
@@ -13,9 +13,9 @@
; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefix=GP32R6
; RUN: llc < %s -mtriple=mips64 -mcpu=mips3 -relocation-model=pic \
-; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP64,GP64R0R1
+; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=MIPS3
; RUN: llc < %s -mtriple=mips64 -mcpu=mips4 -relocation-model=pic \
-; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP64,GP64R0R1
+; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=MIPS3
; RUN: llc < %s -mtriple=mips64 -mcpu=mips64 -relocation-model=pic \
; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP64,GP64R0R1
; RUN: llc < %s -mtriple=mips64 -mcpu=mips64r2 -relocation-model=pic \
@@ -35,6 +35,11 @@
; RUN: FileCheck %s -check-prefix=MMR6
define signext i1 @urem_i1(i1 signext %a, i1 signext %b) {
+; MIPS2-LABEL: urem_i1:
+; MIPS2: # %bb.0: # %entry
+; MIPS2-NEXT: jr $ra
+; MIPS2-NEXT: addiu $2, $zero, 0
+;
; GP32-LABEL: urem_i1:
; GP32: # %bb.0: # %entry
; GP32-NEXT: jr $ra
@@ -45,6 +50,11 @@ define signext i1 @urem_i1(i1 signext %a, i1 signext %b) {
; GP32R6-NEXT: jr $ra
; GP32R6-NEXT: addiu $2, $zero, 0
;
+; MIPS3-LABEL: urem_i1:
+; MIPS3: # %bb.0: # %entry
+; MIPS3-NEXT: jr $ra
+; MIPS3-NEXT: addiu $2, $zero, 0
+;
; GP64-LABEL: urem_i1:
; GP64: # %bb.0: # %entry
; GP64-NEXT: jr $ra
@@ -70,6 +80,17 @@ entry:
}
define signext i8 @urem_i8(i8 signext %a, i8 signext %b) {
+; MIPS2-LABEL: urem_i8:
+; MIPS2: # %bb.0: # %entry
+; MIPS2-NEXT: andi $1, $5, 255
+; MIPS2-NEXT: andi $2, $4, 255
+; MIPS2-NEXT: divu $zero, $2, $1
+; MIPS2-NEXT: teq $1, $zero, 7
+; MIPS2-NEXT: mfhi $1
+; MIPS2-NEXT: sll $1, $1, 24
+; MIPS2-NEXT: jr $ra
+; MIPS2-NEXT: sra $2, $1, 24
+;
; GP32R0R2-LABEL: urem_i8:
; GP32R0R2: # %bb.0: # %entry
; GP32R0R2-NEXT: andi $1, $5, 255
@@ -100,6 +121,17 @@ define signext i8 @urem_i8(i8 signext %a, i8 signext %b) {
; GP32R6-NEXT: jr $ra
; GP32R6-NEXT: seb $2, $2
;
+; MIPS3-LABEL: urem_i8:
+; MIPS3: # %bb.0: # %entry
+; MIPS3-NEXT: andi $1, $5, 255
+; MIPS3-NEXT: andi $2, $4, 255
+; MIPS3-NEXT: divu $zero, $2, $1
+; MIPS3-NEXT: teq $1, $zero, 7
+; MIPS3-NEXT: mfhi $1
+; MIPS3-NEXT: sll $1, $1, 24
+; MIPS3-NEXT: jr $ra
+; MIPS3-NEXT: sra $2, $1, 24
+;
; GP64R0R1-LABEL: urem_i8:
; GP64R0R1: # %bb.0: # %entry
; GP64R0R1-NEXT: andi $1, $5, 255
@@ -154,6 +186,17 @@ entry:
}
define signext i16 @urem_i16(i16 signext %a, i16 signext %b) {
+; MIPS2-LABEL: urem_i16:
+; MIPS2: # %bb.0: # %entry
+; MIPS2-NEXT: andi $1, $5, 65535
+; MIPS2-NEXT: andi $2, $4, 65535
+; MIPS2-NEXT: divu $zero, $2, $1
+; MIPS2-NEXT: teq $1, $zero, 7
+; MIPS2-NEXT: mfhi $1
+; MIPS2-NEXT: sll $1, $1, 16
+; MIPS2-NEXT: jr $ra
+; MIPS2-NEXT: sra $2, $1, 16
+;
; GP32R0R2-LABEL: urem_i16:
; GP32R0R2: # %bb.0: # %entry
; GP32R0R2-NEXT: andi $1, $5, 65535
@@ -184,6 +227,17 @@ define signext i16 @urem_i16(i16 signext %a, i16 signext %b) {
; GP32R6-NEXT: jr $ra
; GP32R6-NEXT: seh $2, $2
;
+; MIPS3-LABEL: urem_i16:
+; MIPS3: # %bb.0: # %entry
+; MIPS3-NEXT: andi $1, $5, 65535
+; MIPS3-NEXT: andi $2, $4, 65535
+; MIPS3-NEXT: divu $zero, $2, $1
+; MIPS3-NEXT: teq $1, $zero, 7
+; MIPS3-NEXT: mfhi $1
+; MIPS3-NEXT: sll $1, $1, 16
+; MIPS3-NEXT: jr $ra
+; MIPS3-NEXT: sra $2, $1, 16
+;
; GP64R0R1-LABEL: urem_i16:
; GP64R0R1: # %bb.0: # %entry
; GP64R0R1-NEXT: andi $1, $5, 65535
@@ -238,6 +292,14 @@ entry:
}
define signext i32 @urem_i32(i32 signext %a, i32 signext %b) {
+; MIPS2-LABEL: urem_i32:
+; MIPS2: # %bb.0: # %entry
+; MIPS2-NEXT: divu $zero, $4, $5
+; MIPS2-NEXT: teq $5, $zero, 7
+; MIPS2-NEXT: mfhi $2
+; MIPS2-NEXT: jr $ra
+; MIPS2-NEXT: nop
+;
; GP32-LABEL: urem_i32:
; GP32: # %bb.0: # %entry
; GP32-NEXT: divu $zero, $4, $5
@@ -251,6 +313,14 @@ define signext i32 @urem_i32(i32 signext %a, i32 signext %b) {
; GP32R6-NEXT: teq $5, $zero, 7
; GP32R6-NEXT: jrc $ra
;
+; MIPS3-LABEL: urem_i32:
+; MIPS3: # %bb.0: # %entry
+; MIPS3-NEXT: divu $zero, $4, $5
+; MIPS3-NEXT: teq $5, $zero, 7
+; MIPS3-NEXT: mfhi $2
+; MIPS3-NEXT: jr $ra
+; MIPS3-NEXT: nop
+;
; GP64-LABEL: urem_i32:
; GP64: # %bb.0: # %entry
; GP64-NEXT: divu $zero, $4, $5
@@ -282,6 +352,22 @@ entry:
}
define signext i64 @urem_i64(i64 signext %a, i64 signext %b) {
+; MIPS2-LABEL: urem_i64:
+; MIPS2: # %bb.0: # %entry
+; MIPS2-NEXT: lui $2, %hi(_gp_disp)
+; MIPS2-NEXT: addiu $2, $2, %lo(_gp_disp)
+; MIPS2-NEXT: addiu $sp, $sp, -24
+; MIPS2-NEXT: .cfi_def_cfa_offset 24
+; MIPS2-NEXT: sw $ra, 20($sp) # 4-byte Folded Spill
+; MIPS2-NEXT: .cfi_offset 31, -4
+; MIPS2-NEXT: addu $gp, $2, $25
+; MIPS2-NEXT: lw $25, %call16(__umoddi3)($gp)
+; MIPS2-NEXT: jalr $25
+; MIPS2-NEXT: nop
+; MIPS2-NEXT: lw $ra, 20($sp) # 4-byte Folded Reload
+; MIPS2-NEXT: jr $ra
+; MIPS2-NEXT: addiu $sp, $sp, 24
+;
; GP32-LABEL: urem_i64:
; GP32: # %bb.0: # %entry
; GP32-NEXT: lui $2, %hi(_gp_disp)
@@ -313,6 +399,14 @@ define signext i64 @urem_i64(i64 signext %a, i64 signext %b) {
; GP32R6-NEXT: jr $ra
; GP32R6-NEXT: addiu $sp, $sp, 24
;
+; MIPS3-LABEL: urem_i64:
+; MIPS3: # %bb.0: # %entry
+; MIPS3-NEXT: ddivu $zero, $4, $5
+; MIPS3-NEXT: teq $5, $zero, 7
+; MIPS3-NEXT: mfhi $2
+; MIPS3-NEXT: jr $ra
+; MIPS3-NEXT: nop
+;
; GP64-LABEL: urem_i64:
; GP64: # %bb.0: # %entry
; GP64-NEXT: ddivu $zero, $4, $5
@@ -364,6 +458,30 @@ entry:
}
define signext i128 @urem_i128(i128 signext %a, i128 signext %b) {
+; MIPS2-LABEL: urem_i128:
+; MIPS2: # %bb.0: # %entry
+; MIPS2-NEXT: lui $2, %hi(_gp_disp)
+; MIPS2-NEXT: addiu $2, $2, %lo(_gp_disp)
+; MIPS2-NEXT: addiu $sp, $sp, -40
+; MIPS2-NEXT: .cfi_def_cfa_offset 40
+; MIPS2-NEXT: sw $ra, 36($sp) # 4-byte Folded Spill
+; MIPS2-NEXT: .cfi_offset 31, -4
+; MIPS2-NEXT: addu $gp, $2, $25
+; MIPS2-NEXT: lw $1, 60($sp)
+; MIPS2-NEXT: lw $2, 64($sp)
+; MIPS2-NEXT: lw $3, 68($sp)
+; MIPS2-NEXT: sw $3, 28($sp)
+; MIPS2-NEXT: sw $2, 24($sp)
+; MIPS2-NEXT: sw $1, 20($sp)
+; MIPS2-NEXT: lw $1, 56($sp)
+; MIPS2-NEXT: sw $1, 16($sp)
+; MIPS2-NEXT: lw $25, %call16(__umodti3)($gp)
+; MIPS2-NEXT: jalr $25
+; MIPS2-NEXT: nop
+; MIPS2-NEXT: lw $ra, 36($sp) # 4-byte Folded Reload
+; MIPS2-NEXT: jr $ra
+; MIPS2-NEXT: addiu $sp, $sp, 40
+;
; GP32-LABEL: urem_i128:
; GP32: # %bb.0: # %entry
; GP32-NEXT: lui $2, %hi(_gp_disp)
@@ -411,6 +529,25 @@ define signext i128 @urem_i128(i128 signext %a, i128 signext %b) {
; GP32R6-NEXT: jr $ra
; GP32R6-NEXT: addiu $sp, $sp, 40
;
+; MIPS3-LABEL: urem_i128:
+; MIPS3: # %bb.0: # %entry
+; MIPS3-NEXT: daddiu $sp, $sp, -16
+; MIPS3-NEXT: .cfi_def_cfa_offset 16
+; MIPS3-NEXT: sd $ra, 8($sp) # 8-byte Folded Spill
+; MIPS3-NEXT: sd $gp, 0($sp) # 8-byte Folded Spill
+; MIPS3-NEXT: .cfi_offset 31, -8
+; MIPS3-NEXT: .cfi_offset 28, -16
+; MIPS3-NEXT: lui $1, %hi(%neg(%gp_rel(urem_i128)))
+; MIPS3-NEXT: daddu $1, $1, $25
+; MIPS3-NEXT: daddiu $gp, $1, %lo(%neg(%gp_rel(urem_i128)))
+; MIPS3-NEXT: ld $25, %call16(__umodti3)($gp)
+; MIPS3-NEXT: jalr $25
+; MIPS3-NEXT: nop
+; MIPS3-NEXT: ld $gp, 0($sp) # 8-byte Folded Reload
+; MIPS3-NEXT: ld $ra, 8($sp) # 8-byte Folded Reload
+; MIPS3-NEXT: jr $ra
+; MIPS3-NEXT: daddiu $sp, $sp, 16
+;
; GP64-LABEL: urem_i128:
; GP64: # %bb.0: # %entry
; GP64-NEXT: daddiu $sp, $sp, -16
More information about the llvm-commits
mailing list