[llvm] [Mips] Handle division by zero trap on MIPS1 (PR #201133)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Jun 2 07:41:17 PDT 2026
https://github.com/neoto created https://github.com/llvm/llvm-project/pull/201133
LLVM currently emits the `teq` instruction for every arch version, but `teq` is unsupported on MIPS1.
This special cases MIPS1 so that `bne(z)` and `break` are emitted instead.
Compared to https://github.com/llvm/llvm-project/pull/81311, this should also handle liveness as far as I can tell.
I didn't want to add another bool to the argument list so I combined `IsMicroMips` and what was supposed to be `IsMips1` into an enum, which feels much nicer in this case.
Besides that and the main change, I also changed the `hasSideEffects` bit for `PseudoSDIV` and `PseudoUDIV`,
which allows the delay slot to be usefully filled - well, at least with `-O1`+. This seems to be in line with what GCC does:
https://godbolt.org/z/zqcG5ha35
Tested using clang directly and through Zig's LLVM backend.
Closes https://github.com/llvm/llvm-project/issues/80554
Supersedes https://github.com/llvm/llvm-project/pull/81311
>From c296ce82ac8bc4c14e7eac55b851985113a81aa2 Mon Sep 17 00:00:00 2001
From: Leon Lombar <leon at makase.ro>
Date: Tue, 2 Jun 2026 15:56:47 +0200
Subject: [PATCH] [Mips] Handle division by zero trap on MIPS1
Special cases MIPS1 so that LLVM emits `bnez` and `break` instead of `teq`
---
llvm/lib/Target/Mips/MipsISelLowering.cpp | 86 ++++++++++++++++++---
llvm/lib/Target/Mips/MipsInstrInfo.td | 4 +-
llvm/test/CodeGen/Mips/llvm-ir/sdiv.ll | 88 ++++++++++++++++++++++
llvm/test/CodeGen/Mips/llvm-ir/srem.ll | 86 +++++++++++++++++++++
llvm/test/CodeGen/Mips/llvm-ir/udiv.ll | 86 +++++++++++++++++++++
llvm/test/CodeGen/Mips/llvm-ir/urem.ll | 92 +++++++++++++++++++++++
6 files changed, 428 insertions(+), 14 deletions(-)
diff --git a/llvm/lib/Target/Mips/MipsISelLowering.cpp b/llvm/lib/Target/Mips/MipsISelLowering.cpp
index 298b525e48cff..87a97bf345337 100644
--- a/llvm/lib/Target/Mips/MipsISelLowering.cpp
+++ b/llvm/lib/Target/Mips/MipsISelLowering.cpp
@@ -31,6 +31,7 @@
#include "llvm/CodeGen/CallingConvLower.h"
#include "llvm/CodeGen/FunctionLoweringInfo.h"
#include "llvm/CodeGen/ISDOpcodes.h"
+#include "llvm/CodeGen/LivePhysRegs.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
@@ -95,6 +96,12 @@ static const MCPhysReg Mips64DPRegs[8] = {
Mips::D16_64, Mips::D17_64, Mips::D18_64, Mips::D19_64
};
+enum class DivByZeroTrapKind {
+ Break, // MIPS1
+ Teq, // MIPS2+
+ TeqMM, // MicroMips
+};
+
// The MIPS MSA ABI passes vector arguments in the integer register set.
// The number of integer registers used is dependant on the ABI used.
MVT MipsTargetLowering::getRegisterTypeForCallingConv(LLVMContext &Context,
@@ -1279,19 +1286,68 @@ addLiveIn(MachineFunction &MF, unsigned PReg, const TargetRegisterClass *RC)
return VReg;
}
-static MachineBasicBlock *insertDivByZeroTrap(MachineInstr &MI,
- MachineBasicBlock &MBB,
- const TargetInstrInfo &TII,
- bool Is64Bit, bool IsMicroMips) {
+static MachineBasicBlock *
+insertDivByZeroTrap(MachineInstr &MI, MachineBasicBlock &MBB,
+ const TargetInstrInfo &TII, bool Is64Bit,
+ const DivByZeroTrapKind TrapKind) {
if (NoZeroDivCheck)
return &MBB;
- // Insert instruction "teq $divisor_reg, $zero, 7".
MachineBasicBlock::iterator I(MI);
- MachineInstrBuilder MIB;
MachineOperand &Divisor = MI.getOperand(2);
+
+ if (TrapKind == DivByZeroTrapKind::Break) {
+ // Build instructions:
+ // MBB:
+ // bnez $divisor, $zero, SinkMBB
+ // MI $dst, $dividend, $divisor (delay slot)
+ //
+ // BreakMBB:
+ // break 7
+ //
+ // SinkMBB:
+ // fallthrough
+ const DebugLoc DL = MI.getDebugLoc();
+ const BasicBlock *BB = MBB.getBasicBlock();
+ const auto It = std::next(MachineFunction::iterator(&MBB));
+
+ MachineFunction *MF = MBB.getParent();
+ MachineBasicBlock *BreakMBB = MF->CreateMachineBasicBlock(BB);
+ MachineBasicBlock *SinkMBB = MF->CreateMachineBasicBlock(BB);
+ MF->insert(It, BreakMBB);
+ MF->insert(It, SinkMBB);
+
+ // Place all instructions after MI into SinkMBB.
+ SinkMBB->splice(SinkMBB->begin(), &MBB, std::next(I), MBB.end());
+ SinkMBB->transferSuccessorsAndUpdatePHIs(&MBB);
+
+ // Place the branch at the end of the block. Since MI is defined as having
+ // no side effects in TableGen, the filler will place it in the branch delay
+ // slot.
+ BuildMI(&MBB, DL, TII.get(Mips::BNE))
+ .addReg(Divisor.getReg(), getKillRegState(Divisor.isKill()))
+ .addReg(Mips::ZERO)
+ .addMBB(SinkMBB);
+ MBB.addSuccessor(BreakMBB);
+ MBB.addSuccessor(SinkMBB);
+
+ // BreakMBB: break 7
+ BuildMI(BreakMBB, DL, TII.get(Mips::BREAK)).addImm(7).addImm(0);
+ BreakMBB->addSuccessor(SinkMBB);
+
+ LivePhysRegs LiveRegs;
+ computeAndAddLiveIns(LiveRegs, *SinkMBB);
+
+ Divisor.setIsKill(false);
+
+ return SinkMBB;
+ }
+
+ // Insert instruction "teq $divisor_reg, $zero, 7".
+ MachineInstrBuilder MIB;
MIB = BuildMI(MBB, std::next(I), MI.getDebugLoc(),
- TII.get(IsMicroMips ? Mips::TEQ_MM : Mips::TEQ))
+ TII.get(TrapKind == DivByZeroTrapKind::TeqMM ? Mips::TEQ_MM
+ : Mips::TEQ))
.addReg(Divisor.getReg(), getKillRegState(Divisor.isKill()))
.addReg(Mips::ZERO)
.addImm(7);
@@ -1428,9 +1484,13 @@ MipsTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,
case Mips::DIV:
case Mips::DIVU:
case Mips::MOD:
- case Mips::MODU:
+ case Mips::MODU: {
+ const auto TrapKind = Subtarget.hasMips1() && !Subtarget.hasMips2()
+ ? DivByZeroTrapKind::Break
+ : DivByZeroTrapKind::Teq;
return insertDivByZeroTrap(MI, *BB, *Subtarget.getInstrInfo(), false,
- false);
+ TrapKind);
+ }
case Mips::SDIV_MM_Pseudo:
case Mips::UDIV_MM_Pseudo:
case Mips::SDIV_MM:
@@ -1439,14 +1499,16 @@ MipsTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,
case Mips::DIVU_MMR6:
case Mips::MOD_MMR6:
case Mips::MODU_MMR6:
- return insertDivByZeroTrap(MI, *BB, *Subtarget.getInstrInfo(), false, true);
+ return insertDivByZeroTrap(MI, *BB, *Subtarget.getInstrInfo(), false,
+ DivByZeroTrapKind::TeqMM);
case Mips::PseudoDSDIV:
case Mips::PseudoDUDIV:
case Mips::DDIV:
case Mips::DDIVU:
case Mips::DMOD:
case Mips::DMODU:
- return insertDivByZeroTrap(MI, *BB, *Subtarget.getInstrInfo(), true, false);
+ return insertDivByZeroTrap(MI, *BB, *Subtarget.getInstrInfo(), true,
+ DivByZeroTrapKind::Teq);
case Mips::PseudoSELECT_I:
case Mips::PseudoSELECT_I64:
@@ -3873,7 +3935,7 @@ SDValue MipsTargetLowering::LowerFormalArguments(
assert(!VA.needsCustom() && "unexpected custom memory argument");
- // Only arguments pased on the stack should make it here.
+ // Only arguments pased on the stack should make it here.
assert(VA.isMemLoc());
// The stack pointer offset is relative to the caller stack frame.
diff --git a/llvm/lib/Target/Mips/MipsInstrInfo.td b/llvm/lib/Target/Mips/MipsInstrInfo.td
index 4afbc6be00273..f35218709d84c 100644
--- a/llvm/lib/Target/Mips/MipsInstrInfo.td
+++ b/llvm/lib/Target/Mips/MipsInstrInfo.td
@@ -2457,9 +2457,9 @@ def PseudoMSUBU : MAddSubPseudo<MSUBU, MipsMSubu>,
let AdditionalPredicates = [NotInMicroMips] in {
def PseudoSDIV : MultDivPseudo<SDIV, ACC64, GPR32Opnd, MipsDivRem,
- 0, 1, 1>, ISA_MIPS1_NOT_32R6_64R6;
+ 0, 0, 1>, ISA_MIPS1_NOT_32R6_64R6;
def PseudoUDIV : MultDivPseudo<UDIV, ACC64, GPR32Opnd, MipsDivRemU,
- 0, 1, 1>, ISA_MIPS1_NOT_32R6_64R6;
+ 0, 0, 1>, ISA_MIPS1_NOT_32R6_64R6;
def RDHWR : MMRel, ReadHardware<GPR32Opnd, HWRegsOpnd>, RDHWR_FM, ISA_MIPS1;
// TODO: Add '0 < pos+size <= 32' constraint check to ext instruction
def EXT : MMRel, StdMMR6Rel, ExtBase<"ext", GPR32Opnd, uimm5, uimm5_plus1,
diff --git a/llvm/test/CodeGen/Mips/llvm-ir/sdiv.ll b/llvm/test/CodeGen/Mips/llvm-ir/sdiv.ll
index 72cead18f89fa..91a45a88df90a 100644
--- a/llvm/test/CodeGen/Mips/llvm-ir/sdiv.ll
+++ b/llvm/test/CodeGen/Mips/llvm-ir/sdiv.ll
@@ -1,4 +1,6 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc < %s -mtriple=mips -mcpu=mips1 -relocation-model=pic \
+; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefix=MIPS1
; 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 \
@@ -35,6 +37,11 @@
; RUN: FileCheck %s -check-prefix=MMR6
define signext i1 @sdiv_i1(i1 signext %a, i1 signext %b) {
+; MIPS1-LABEL: sdiv_i1:
+; MIPS1: # %bb.0: # %entry
+; MIPS1-NEXT: jr $ra
+; MIPS1-NEXT: move $2, $4
+;
; MIPS2-LABEL: sdiv_i1:
; MIPS2: # %bb.0: # %entry
; MIPS2-NEXT: jr $ra
@@ -80,6 +87,18 @@ entry:
}
define signext i8 @sdiv_i8(i8 signext %a, i8 signext %b) {
+; MIPS1-LABEL: sdiv_i8:
+; MIPS1: # %bb.0: # %entry
+; MIPS1-NEXT: bnez $5, $BB1_2
+; MIPS1-NEXT: div $zero, $4, $5
+; MIPS1-NEXT: # %bb.1: # %entry
+; MIPS1-NEXT: break 7
+; MIPS1-NEXT: $BB1_2: # %entry
+; MIPS1-NEXT: mflo $1
+; MIPS1-NEXT: sll $1, $1, 24
+; MIPS1-NEXT: jr $ra
+; MIPS1-NEXT: sra $2, $1, 24
+;
; MIPS2-LABEL: sdiv_i8:
; MIPS2: # %bb.0: # %entry
; MIPS2-NEXT: div $zero, $4, $5
@@ -166,6 +185,18 @@ entry:
}
define signext i16 @sdiv_i16(i16 signext %a, i16 signext %b) {
+; MIPS1-LABEL: sdiv_i16:
+; MIPS1: # %bb.0: # %entry
+; MIPS1-NEXT: bnez $5, $BB2_2
+; MIPS1-NEXT: div $zero, $4, $5
+; MIPS1-NEXT: # %bb.1: # %entry
+; MIPS1-NEXT: break 7
+; MIPS1-NEXT: $BB2_2: # %entry
+; MIPS1-NEXT: mflo $1
+; MIPS1-NEXT: sll $1, $1, 16
+; MIPS1-NEXT: jr $ra
+; MIPS1-NEXT: sra $2, $1, 16
+;
; MIPS2-LABEL: sdiv_i16:
; MIPS2: # %bb.0: # %entry
; MIPS2-NEXT: div $zero, $4, $5
@@ -252,6 +283,17 @@ entry:
}
define signext i32 @sdiv_i32(i32 signext %a, i32 signext %b) {
+; MIPS1-LABEL: sdiv_i32:
+; MIPS1: # %bb.0: # %entry
+; MIPS1-NEXT: bnez $5, $BB3_2
+; MIPS1-NEXT: div $zero, $4, $5
+; MIPS1-NEXT: # %bb.1: # %entry
+; MIPS1-NEXT: break 7
+; MIPS1-NEXT: $BB3_2: # %entry
+; MIPS1-NEXT: mflo $2
+; MIPS1-NEXT: jr $ra
+; MIPS1-NEXT: nop
+;
; MIPS2-LABEL: sdiv_i32:
; MIPS2: # %bb.0: # %entry
; MIPS2-NEXT: div $zero, $4, $5
@@ -312,6 +354,24 @@ entry:
}
define signext i64 @sdiv_i64(i64 signext %a, i64 signext %b) {
+; MIPS1-LABEL: sdiv_i64:
+; MIPS1: # %bb.0: # %entry
+; MIPS1-NEXT: lui $2, %hi(_gp_disp)
+; MIPS1-NEXT: addiu $2, $2, %lo(_gp_disp)
+; MIPS1-NEXT: addiu $sp, $sp, -24
+; MIPS1-NEXT: .cfi_def_cfa_offset 24
+; MIPS1-NEXT: sw $ra, 20($sp) # 4-byte Folded Spill
+; MIPS1-NEXT: .cfi_offset 31, -4
+; MIPS1-NEXT: addu $gp, $2, $25
+; MIPS1-NEXT: lw $25, %call16(__divdi3)($gp)
+; MIPS1-NEXT: nop
+; MIPS1-NEXT: jalr $25
+; MIPS1-NEXT: nop
+; MIPS1-NEXT: lw $ra, 20($sp) # 4-byte Folded Reload
+; MIPS1-NEXT: nop
+; MIPS1-NEXT: jr $ra
+; MIPS1-NEXT: addiu $sp, $sp, 24
+;
; MIPS2-LABEL: sdiv_i64:
; MIPS2: # %bb.0: # %entry
; MIPS2-NEXT: lui $2, %hi(_gp_disp)
@@ -416,6 +476,34 @@ entry:
}
define signext i128 @sdiv_i128(i128 signext %a, i128 signext %b) {
+; MIPS1-LABEL: sdiv_i128:
+; MIPS1: # %bb.0: # %entry
+; MIPS1-NEXT: lui $2, %hi(_gp_disp)
+; MIPS1-NEXT: addiu $2, $2, %lo(_gp_disp)
+; MIPS1-NEXT: addiu $sp, $sp, -40
+; MIPS1-NEXT: .cfi_def_cfa_offset 40
+; MIPS1-NEXT: sw $ra, 36($sp) # 4-byte Folded Spill
+; MIPS1-NEXT: .cfi_offset 31, -4
+; MIPS1-NEXT: addu $gp, $2, $25
+; MIPS1-NEXT: lw $1, 60($sp)
+; MIPS1-NEXT: lw $2, 64($sp)
+; MIPS1-NEXT: lw $3, 68($sp)
+; MIPS1-NEXT: nop
+; MIPS1-NEXT: sw $3, 28($sp)
+; MIPS1-NEXT: sw $2, 24($sp)
+; MIPS1-NEXT: sw $1, 20($sp)
+; MIPS1-NEXT: lw $1, 56($sp)
+; MIPS1-NEXT: nop
+; MIPS1-NEXT: sw $1, 16($sp)
+; MIPS1-NEXT: lw $25, %call16(__divti3)($gp)
+; MIPS1-NEXT: nop
+; MIPS1-NEXT: jalr $25
+; MIPS1-NEXT: nop
+; MIPS1-NEXT: lw $ra, 36($sp) # 4-byte Folded Reload
+; MIPS1-NEXT: nop
+; MIPS1-NEXT: jr $ra
+; MIPS1-NEXT: addiu $sp, $sp, 40
+;
; MIPS2-LABEL: sdiv_i128:
; MIPS2: # %bb.0: # %entry
; MIPS2-NEXT: lui $2, %hi(_gp_disp)
diff --git a/llvm/test/CodeGen/Mips/llvm-ir/srem.ll b/llvm/test/CodeGen/Mips/llvm-ir/srem.ll
index 72496fcc53a5a..de166d6f26abc 100644
--- a/llvm/test/CodeGen/Mips/llvm-ir/srem.ll
+++ b/llvm/test/CodeGen/Mips/llvm-ir/srem.ll
@@ -1,4 +1,6 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc < %s -mtriple=mips -mcpu=mips1 -relocation-model=pic \
+; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefix=MIPS1
; 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 \
@@ -35,6 +37,11 @@
; RUN: FileCheck %s -check-prefix=MMR6
define signext i1 @srem_i1(i1 signext %a, i1 signext %b) {
+; MIPS1-LABEL: srem_i1:
+; MIPS1: # %bb.0: # %entry
+; MIPS1-NEXT: jr $ra
+; MIPS1-NEXT: addiu $2, $zero, 0
+;
; MIPS2-LABEL: srem_i1:
; MIPS2: # %bb.0: # %entry
; MIPS2-NEXT: jr $ra
@@ -80,6 +87,17 @@ entry:
}
define signext i8 @srem_i8(i8 signext %a, i8 signext %b) {
+; MIPS1-LABEL: srem_i8:
+; MIPS1: # %bb.0: # %entry
+; MIPS1-NEXT: bnez $5, $BB1_2
+; MIPS1-NEXT: div $zero, $4, $5
+; MIPS1-NEXT: # %bb.1: # %entry
+; MIPS1-NEXT: break 7
+; MIPS1-NEXT: $BB1_2: # %entry
+; MIPS1-NEXT: mfhi $2
+; MIPS1-NEXT: jr $ra
+; MIPS1-NEXT: nop
+;
; MIPS2-LABEL: srem_i8:
; MIPS2: # %bb.0: # %entry
; MIPS2-NEXT: div $zero, $4, $5
@@ -140,6 +158,17 @@ entry:
}
define signext i16 @srem_i16(i16 signext %a, i16 signext %b) {
+; MIPS1-LABEL: srem_i16:
+; MIPS1: # %bb.0: # %entry
+; MIPS1-NEXT: bnez $5, $BB2_2
+; MIPS1-NEXT: div $zero, $4, $5
+; MIPS1-NEXT: # %bb.1: # %entry
+; MIPS1-NEXT: break 7
+; MIPS1-NEXT: $BB2_2: # %entry
+; MIPS1-NEXT: mfhi $2
+; MIPS1-NEXT: jr $ra
+; MIPS1-NEXT: nop
+;
; MIPS2-LABEL: srem_i16:
; MIPS2: # %bb.0: # %entry
; MIPS2-NEXT: div $zero, $4, $5
@@ -200,6 +229,17 @@ entry:
}
define signext i32 @srem_i32(i32 signext %a, i32 signext %b) {
+; MIPS1-LABEL: srem_i32:
+; MIPS1: # %bb.0: # %entry
+; MIPS1-NEXT: bnez $5, $BB3_2
+; MIPS1-NEXT: div $zero, $4, $5
+; MIPS1-NEXT: # %bb.1: # %entry
+; MIPS1-NEXT: break 7
+; MIPS1-NEXT: $BB3_2: # %entry
+; MIPS1-NEXT: mfhi $2
+; MIPS1-NEXT: jr $ra
+; MIPS1-NEXT: nop
+;
; MIPS2-LABEL: srem_i32:
; MIPS2: # %bb.0: # %entry
; MIPS2-NEXT: div $zero, $4, $5
@@ -260,6 +300,24 @@ entry:
}
define signext i64 @srem_i64(i64 signext %a, i64 signext %b) {
+; MIPS1-LABEL: srem_i64:
+; MIPS1: # %bb.0: # %entry
+; MIPS1-NEXT: lui $2, %hi(_gp_disp)
+; MIPS1-NEXT: addiu $2, $2, %lo(_gp_disp)
+; MIPS1-NEXT: addiu $sp, $sp, -24
+; MIPS1-NEXT: .cfi_def_cfa_offset 24
+; MIPS1-NEXT: sw $ra, 20($sp) # 4-byte Folded Spill
+; MIPS1-NEXT: .cfi_offset 31, -4
+; MIPS1-NEXT: addu $gp, $2, $25
+; MIPS1-NEXT: lw $25, %call16(__moddi3)($gp)
+; MIPS1-NEXT: nop
+; MIPS1-NEXT: jalr $25
+; MIPS1-NEXT: nop
+; MIPS1-NEXT: lw $ra, 20($sp) # 4-byte Folded Reload
+; MIPS1-NEXT: nop
+; MIPS1-NEXT: jr $ra
+; MIPS1-NEXT: addiu $sp, $sp, 24
+;
; MIPS2-LABEL: srem_i64:
; MIPS2: # %bb.0: # %entry
; MIPS2-NEXT: lui $2, %hi(_gp_disp)
@@ -364,6 +422,34 @@ entry:
}
define signext i128 @srem_i128(i128 signext %a, i128 signext %b) {
+; MIPS1-LABEL: srem_i128:
+; MIPS1: # %bb.0: # %entry
+; MIPS1-NEXT: lui $2, %hi(_gp_disp)
+; MIPS1-NEXT: addiu $2, $2, %lo(_gp_disp)
+; MIPS1-NEXT: addiu $sp, $sp, -40
+; MIPS1-NEXT: .cfi_def_cfa_offset 40
+; MIPS1-NEXT: sw $ra, 36($sp) # 4-byte Folded Spill
+; MIPS1-NEXT: .cfi_offset 31, -4
+; MIPS1-NEXT: addu $gp, $2, $25
+; MIPS1-NEXT: lw $1, 60($sp)
+; MIPS1-NEXT: lw $2, 64($sp)
+; MIPS1-NEXT: lw $3, 68($sp)
+; MIPS1-NEXT: nop
+; MIPS1-NEXT: sw $3, 28($sp)
+; MIPS1-NEXT: sw $2, 24($sp)
+; MIPS1-NEXT: sw $1, 20($sp)
+; MIPS1-NEXT: lw $1, 56($sp)
+; MIPS1-NEXT: nop
+; MIPS1-NEXT: sw $1, 16($sp)
+; MIPS1-NEXT: lw $25, %call16(__modti3)($gp)
+; MIPS1-NEXT: nop
+; MIPS1-NEXT: jalr $25
+; MIPS1-NEXT: nop
+; MIPS1-NEXT: lw $ra, 36($sp) # 4-byte Folded Reload
+; MIPS1-NEXT: nop
+; MIPS1-NEXT: jr $ra
+; MIPS1-NEXT: addiu $sp, $sp, 40
+;
; MIPS2-LABEL: srem_i128:
; MIPS2: # %bb.0: # %entry
; MIPS2-NEXT: lui $2, %hi(_gp_disp)
diff --git a/llvm/test/CodeGen/Mips/llvm-ir/udiv.ll b/llvm/test/CodeGen/Mips/llvm-ir/udiv.ll
index 9451f1e9be096..b15e5869f3584 100644
--- a/llvm/test/CodeGen/Mips/llvm-ir/udiv.ll
+++ b/llvm/test/CodeGen/Mips/llvm-ir/udiv.ll
@@ -1,4 +1,6 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc < %s -mtriple=mips -mcpu=mips1 -relocation-model=pic \
+; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefix=MIPS1
; 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 \
@@ -35,6 +37,11 @@
; RUN: FileCheck %s -check-prefix=MMR6
define zeroext i1 @udiv_i1(i1 zeroext %a, i1 zeroext %b) {
+; MIPS1-LABEL: udiv_i1:
+; MIPS1: # %bb.0: # %entry
+; MIPS1-NEXT: jr $ra
+; MIPS1-NEXT: move $2, $4
+;
; MIPS2-LABEL: udiv_i1:
; MIPS2: # %bb.0: # %entry
; MIPS2-NEXT: jr $ra
@@ -80,6 +87,17 @@ entry:
}
define zeroext i8 @udiv_i8(i8 zeroext %a, i8 zeroext %b) {
+; MIPS1-LABEL: udiv_i8:
+; MIPS1: # %bb.0: # %entry
+; MIPS1-NEXT: bnez $5, $BB1_2
+; MIPS1-NEXT: divu $zero, $4, $5
+; MIPS1-NEXT: # %bb.1: # %entry
+; MIPS1-NEXT: break 7
+; MIPS1-NEXT: $BB1_2: # %entry
+; MIPS1-NEXT: mflo $2
+; MIPS1-NEXT: jr $ra
+; MIPS1-NEXT: nop
+;
; MIPS2-LABEL: udiv_i8:
; MIPS2: # %bb.0: # %entry
; MIPS2-NEXT: divu $zero, $4, $5
@@ -140,6 +158,17 @@ entry:
}
define zeroext i16 @udiv_i16(i16 zeroext %a, i16 zeroext %b) {
+; MIPS1-LABEL: udiv_i16:
+; MIPS1: # %bb.0: # %entry
+; MIPS1-NEXT: bnez $5, $BB2_2
+; MIPS1-NEXT: divu $zero, $4, $5
+; MIPS1-NEXT: # %bb.1: # %entry
+; MIPS1-NEXT: break 7
+; MIPS1-NEXT: $BB2_2: # %entry
+; MIPS1-NEXT: mflo $2
+; MIPS1-NEXT: jr $ra
+; MIPS1-NEXT: nop
+;
; MIPS2-LABEL: udiv_i16:
; MIPS2: # %bb.0: # %entry
; MIPS2-NEXT: divu $zero, $4, $5
@@ -200,6 +229,17 @@ entry:
}
define signext i32 @udiv_i32(i32 signext %a, i32 signext %b) {
+; MIPS1-LABEL: udiv_i32:
+; MIPS1: # %bb.0: # %entry
+; MIPS1-NEXT: bnez $5, $BB3_2
+; MIPS1-NEXT: divu $zero, $4, $5
+; MIPS1-NEXT: # %bb.1: # %entry
+; MIPS1-NEXT: break 7
+; MIPS1-NEXT: $BB3_2: # %entry
+; MIPS1-NEXT: mflo $2
+; MIPS1-NEXT: jr $ra
+; MIPS1-NEXT: nop
+;
; MIPS2-LABEL: udiv_i32:
; MIPS2: # %bb.0: # %entry
; MIPS2-NEXT: divu $zero, $4, $5
@@ -260,6 +300,24 @@ entry:
}
define signext i64 @udiv_i64(i64 signext %a, i64 signext %b) {
+; MIPS1-LABEL: udiv_i64:
+; MIPS1: # %bb.0: # %entry
+; MIPS1-NEXT: lui $2, %hi(_gp_disp)
+; MIPS1-NEXT: addiu $2, $2, %lo(_gp_disp)
+; MIPS1-NEXT: addiu $sp, $sp, -24
+; MIPS1-NEXT: .cfi_def_cfa_offset 24
+; MIPS1-NEXT: sw $ra, 20($sp) # 4-byte Folded Spill
+; MIPS1-NEXT: .cfi_offset 31, -4
+; MIPS1-NEXT: addu $gp, $2, $25
+; MIPS1-NEXT: lw $25, %call16(__udivdi3)($gp)
+; MIPS1-NEXT: nop
+; MIPS1-NEXT: jalr $25
+; MIPS1-NEXT: nop
+; MIPS1-NEXT: lw $ra, 20($sp) # 4-byte Folded Reload
+; MIPS1-NEXT: nop
+; MIPS1-NEXT: jr $ra
+; MIPS1-NEXT: addiu $sp, $sp, 24
+;
; MIPS2-LABEL: udiv_i64:
; MIPS2: # %bb.0: # %entry
; MIPS2-NEXT: lui $2, %hi(_gp_disp)
@@ -364,6 +422,34 @@ entry:
}
define signext i128 @udiv_i128(i128 signext %a, i128 signext %b) {
+; MIPS1-LABEL: udiv_i128:
+; MIPS1: # %bb.0: # %entry
+; MIPS1-NEXT: lui $2, %hi(_gp_disp)
+; MIPS1-NEXT: addiu $2, $2, %lo(_gp_disp)
+; MIPS1-NEXT: addiu $sp, $sp, -40
+; MIPS1-NEXT: .cfi_def_cfa_offset 40
+; MIPS1-NEXT: sw $ra, 36($sp) # 4-byte Folded Spill
+; MIPS1-NEXT: .cfi_offset 31, -4
+; MIPS1-NEXT: addu $gp, $2, $25
+; MIPS1-NEXT: lw $1, 60($sp)
+; MIPS1-NEXT: lw $2, 64($sp)
+; MIPS1-NEXT: lw $3, 68($sp)
+; MIPS1-NEXT: nop
+; MIPS1-NEXT: sw $3, 28($sp)
+; MIPS1-NEXT: sw $2, 24($sp)
+; MIPS1-NEXT: sw $1, 20($sp)
+; MIPS1-NEXT: lw $1, 56($sp)
+; MIPS1-NEXT: nop
+; MIPS1-NEXT: sw $1, 16($sp)
+; MIPS1-NEXT: lw $25, %call16(__udivti3)($gp)
+; MIPS1-NEXT: nop
+; MIPS1-NEXT: jalr $25
+; MIPS1-NEXT: nop
+; MIPS1-NEXT: lw $ra, 36($sp) # 4-byte Folded Reload
+; MIPS1-NEXT: nop
+; MIPS1-NEXT: jr $ra
+; MIPS1-NEXT: addiu $sp, $sp, 40
+;
; MIPS2-LABEL: udiv_i128:
; MIPS2: # %bb.0: # %entry
; MIPS2-NEXT: lui $2, %hi(_gp_disp)
diff --git a/llvm/test/CodeGen/Mips/llvm-ir/urem.ll b/llvm/test/CodeGen/Mips/llvm-ir/urem.ll
index 7bd8df9e48c75..6da5984502d3c 100644
--- a/llvm/test/CodeGen/Mips/llvm-ir/urem.ll
+++ b/llvm/test/CodeGen/Mips/llvm-ir/urem.ll
@@ -1,4 +1,6 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc < %s -mtriple=mips -mcpu=mips1 -relocation-model=pic \
+; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefix=MIPS1
; 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 \
@@ -35,6 +37,11 @@
; RUN: FileCheck %s -check-prefix=MMR6
define signext i1 @urem_i1(i1 signext %a, i1 signext %b) {
+; MIPS1-LABEL: urem_i1:
+; MIPS1: # %bb.0: # %entry
+; MIPS1-NEXT: jr $ra
+; MIPS1-NEXT: addiu $2, $zero, 0
+;
; MIPS2-LABEL: urem_i1:
; MIPS2: # %bb.0: # %entry
; MIPS2-NEXT: jr $ra
@@ -80,6 +87,20 @@ entry:
}
define signext i8 @urem_i8(i8 signext %a, i8 signext %b) {
+; MIPS1-LABEL: urem_i8:
+; MIPS1: # %bb.0: # %entry
+; MIPS1-NEXT: andi $1, $5, 255
+; MIPS1-NEXT: andi $2, $4, 255
+; MIPS1-NEXT: bnez $1, $BB1_2
+; MIPS1-NEXT: divu $zero, $2, $1
+; MIPS1-NEXT: # %bb.1: # %entry
+; MIPS1-NEXT: break 7
+; MIPS1-NEXT: $BB1_2: # %entry
+; MIPS1-NEXT: mfhi $1
+; MIPS1-NEXT: sll $1, $1, 24
+; MIPS1-NEXT: jr $ra
+; MIPS1-NEXT: sra $2, $1, 24
+;
; MIPS2-LABEL: urem_i8:
; MIPS2: # %bb.0: # %entry
; MIPS2-NEXT: andi $1, $5, 255
@@ -186,6 +207,20 @@ entry:
}
define signext i16 @urem_i16(i16 signext %a, i16 signext %b) {
+; MIPS1-LABEL: urem_i16:
+; MIPS1: # %bb.0: # %entry
+; MIPS1-NEXT: andi $1, $5, 65535
+; MIPS1-NEXT: andi $2, $4, 65535
+; MIPS1-NEXT: bnez $1, $BB2_2
+; MIPS1-NEXT: divu $zero, $2, $1
+; MIPS1-NEXT: # %bb.1: # %entry
+; MIPS1-NEXT: break 7
+; MIPS1-NEXT: $BB2_2: # %entry
+; MIPS1-NEXT: mfhi $1
+; MIPS1-NEXT: sll $1, $1, 16
+; MIPS1-NEXT: jr $ra
+; MIPS1-NEXT: sra $2, $1, 16
+;
; MIPS2-LABEL: urem_i16:
; MIPS2: # %bb.0: # %entry
; MIPS2-NEXT: andi $1, $5, 65535
@@ -292,6 +327,17 @@ entry:
}
define signext i32 @urem_i32(i32 signext %a, i32 signext %b) {
+; MIPS1-LABEL: urem_i32:
+; MIPS1: # %bb.0: # %entry
+; MIPS1-NEXT: bnez $5, $BB3_2
+; MIPS1-NEXT: divu $zero, $4, $5
+; MIPS1-NEXT: # %bb.1: # %entry
+; MIPS1-NEXT: break 7
+; MIPS1-NEXT: $BB3_2: # %entry
+; MIPS1-NEXT: mfhi $2
+; MIPS1-NEXT: jr $ra
+; MIPS1-NEXT: nop
+;
; MIPS2-LABEL: urem_i32:
; MIPS2: # %bb.0: # %entry
; MIPS2-NEXT: divu $zero, $4, $5
@@ -352,6 +398,24 @@ entry:
}
define signext i64 @urem_i64(i64 signext %a, i64 signext %b) {
+; MIPS1-LABEL: urem_i64:
+; MIPS1: # %bb.0: # %entry
+; MIPS1-NEXT: lui $2, %hi(_gp_disp)
+; MIPS1-NEXT: addiu $2, $2, %lo(_gp_disp)
+; MIPS1-NEXT: addiu $sp, $sp, -24
+; MIPS1-NEXT: .cfi_def_cfa_offset 24
+; MIPS1-NEXT: sw $ra, 20($sp) # 4-byte Folded Spill
+; MIPS1-NEXT: .cfi_offset 31, -4
+; MIPS1-NEXT: addu $gp, $2, $25
+; MIPS1-NEXT: lw $25, %call16(__umoddi3)($gp)
+; MIPS1-NEXT: nop
+; MIPS1-NEXT: jalr $25
+; MIPS1-NEXT: nop
+; MIPS1-NEXT: lw $ra, 20($sp) # 4-byte Folded Reload
+; MIPS1-NEXT: nop
+; MIPS1-NEXT: jr $ra
+; MIPS1-NEXT: addiu $sp, $sp, 24
+;
; MIPS2-LABEL: urem_i64:
; MIPS2: # %bb.0: # %entry
; MIPS2-NEXT: lui $2, %hi(_gp_disp)
@@ -456,6 +520,34 @@ entry:
}
define signext i128 @urem_i128(i128 signext %a, i128 signext %b) {
+; MIPS1-LABEL: urem_i128:
+; MIPS1: # %bb.0: # %entry
+; MIPS1-NEXT: lui $2, %hi(_gp_disp)
+; MIPS1-NEXT: addiu $2, $2, %lo(_gp_disp)
+; MIPS1-NEXT: addiu $sp, $sp, -40
+; MIPS1-NEXT: .cfi_def_cfa_offset 40
+; MIPS1-NEXT: sw $ra, 36($sp) # 4-byte Folded Spill
+; MIPS1-NEXT: .cfi_offset 31, -4
+; MIPS1-NEXT: addu $gp, $2, $25
+; MIPS1-NEXT: lw $1, 60($sp)
+; MIPS1-NEXT: lw $2, 64($sp)
+; MIPS1-NEXT: lw $3, 68($sp)
+; MIPS1-NEXT: nop
+; MIPS1-NEXT: sw $3, 28($sp)
+; MIPS1-NEXT: sw $2, 24($sp)
+; MIPS1-NEXT: sw $1, 20($sp)
+; MIPS1-NEXT: lw $1, 56($sp)
+; MIPS1-NEXT: nop
+; MIPS1-NEXT: sw $1, 16($sp)
+; MIPS1-NEXT: lw $25, %call16(__umodti3)($gp)
+; MIPS1-NEXT: nop
+; MIPS1-NEXT: jalr $25
+; MIPS1-NEXT: nop
+; MIPS1-NEXT: lw $ra, 36($sp) # 4-byte Folded Reload
+; MIPS1-NEXT: nop
+; MIPS1-NEXT: jr $ra
+; MIPS1-NEXT: addiu $sp, $sp, 40
+;
; MIPS2-LABEL: urem_i128:
; MIPS2: # %bb.0: # %entry
; MIPS2-NEXT: lui $2, %hi(_gp_disp)
More information about the llvm-commits
mailing list