[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