[llvm] r238757 - [mips][FastISel] Implement srem/urem and sdiv/udiv instructions.

Vasileios Kalintiris Vasileios.Kalintiris at imgtec.com
Mon Jun 1 09:17:37 PDT 2015


Author: vkalintiris
Date: Mon Jun  1 11:17:37 2015
New Revision: 238757

URL: http://llvm.org/viewvc/llvm-project?rev=238757&view=rev
Log:
[mips][FastISel] Implement srem/urem and sdiv/udiv instructions.

Summary: Implement the LLVM assembly urem/srem and sdiv/udiv instructions in MIPS FastISel.

Based on a patch by Reed Kotler.

Test Plan:
srem1.ll
div1.ll
test-suite at O0/O2 for mips32 r1/r2

Reviewers: dsanders, rkotler

Subscribers: llvm-commits, rfuhler

Differential Revision: http://reviews.llvm.org/D7028

Added:
    llvm/trunk/test/CodeGen/Mips/Fast-ISel/div1.ll
    llvm/trunk/test/CodeGen/Mips/Fast-ISel/rem1.ll
Modified:
    llvm/trunk/lib/Target/Mips/MipsFastISel.cpp

Modified: llvm/trunk/lib/Target/Mips/MipsFastISel.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Mips/MipsFastISel.cpp?rev=238757&r1=238756&r2=238757&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Mips/MipsFastISel.cpp (original)
+++ llvm/trunk/lib/Target/Mips/MipsFastISel.cpp Mon Jun  1 11:17:37 2015
@@ -103,6 +103,7 @@ private:
   bool selectTrunc(const Instruction *I);
   bool selectIntExt(const Instruction *I);
   bool selectShift(const Instruction *I);
+  bool selectDivRem(const Instruction *I, unsigned ISDOpcode);
 
   // Utility helper routines.
   bool isTypeLegal(Type *Ty, MVT &VT);
@@ -1471,6 +1472,50 @@ unsigned MipsFastISel::emitIntExt(MVT Sr
   return Success ? DestReg : 0;
 }
 
+bool MipsFastISel::selectDivRem(const Instruction *I, unsigned ISDOpcode) {
+  EVT DestEVT = TLI.getValueType(I->getType(), true);
+  if (!DestEVT.isSimple())
+    return false;
+
+  MVT DestVT = DestEVT.getSimpleVT();
+  if (DestVT != MVT::i32)
+    return false;
+
+  unsigned DivOpc;
+  switch (ISDOpcode) {
+  default:
+    return false;
+  case ISD::SDIV:
+  case ISD::SREM:
+    DivOpc = Mips::SDIV;
+    break;
+  case ISD::UDIV:
+  case ISD::UREM:
+    DivOpc = Mips::UDIV;
+    break;
+  }
+
+  unsigned Src0Reg = getRegForValue(I->getOperand(0));
+  unsigned Src1Reg = getRegForValue(I->getOperand(1));
+  if (!Src0Reg || !Src1Reg)
+    return false;
+
+  emitInst(DivOpc).addReg(Src0Reg).addReg(Src1Reg);
+  emitInst(Mips::TEQ).addReg(Src1Reg).addReg(Mips::ZERO).addImm(7);
+
+  unsigned ResultReg = createResultReg(&Mips::GPR32RegClass);
+  if (!ResultReg)
+    return false;
+
+  unsigned MFOpc = (ISDOpcode == ISD::SREM || ISDOpcode == ISD::UREM)
+                       ? Mips::MFHI
+                       : Mips::MFLO;
+  emitInst(MFOpc, ResultReg);
+
+  updateValueMap(I, ResultReg);
+  return true;
+}
+
 bool MipsFastISel::selectShift(const Instruction *I) {
   MVT RetVT;
 
@@ -1556,6 +1601,22 @@ bool MipsFastISel::fastSelectInstruction
     return selectLoad(I);
   case Instruction::Store:
     return selectStore(I);
+  case Instruction::SDiv:
+    if (!selectBinaryOp(I, ISD::SDIV))
+      return selectDivRem(I, ISD::SDIV);
+    return true;
+  case Instruction::UDiv:
+    if (!selectBinaryOp(I, ISD::UDIV))
+      return selectDivRem(I, ISD::UDIV);
+    return true;
+  case Instruction::SRem:
+    if (!selectBinaryOp(I, ISD::SREM))
+      return selectDivRem(I, ISD::SREM);
+    return true;
+  case Instruction::URem:
+    if (!selectBinaryOp(I, ISD::UREM))
+      return selectDivRem(I, ISD::UREM);
+    return true;
   case Instruction::Shl:
   case Instruction::LShr:
   case Instruction::AShr:

Added: llvm/trunk/test/CodeGen/Mips/Fast-ISel/div1.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/Mips/Fast-ISel/div1.ll?rev=238757&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/Mips/Fast-ISel/div1.ll (added)
+++ llvm/trunk/test/CodeGen/Mips/Fast-ISel/div1.ll Mon Jun  1 11:17:37 2015
@@ -0,0 +1,55 @@
+; RUN: llc < %s -march=mipsel -mcpu=mips32 -O0 -relocation-model=pic \
+; RUN:      -fast-isel=true -mips-fast-isel -fast-isel-abort=1 | FileCheck %s
+; RUN: llc < %s -march=mipsel -mcpu=mips32r2 -O0 -relocation-model=pic \
+; RUN:      -fast-isel=true -mips-fast-isel -fast-isel-abort=1 | FileCheck %s
+
+ at sj = global i32 200000, align 4
+ at sk = global i32 -47, align 4
+ at uj = global i32 200000, align 4
+ at uk = global i32 43, align 4
+ at si = common global i32 0, align 4
+ at ui = common global i32 0, align 4
+
+define void @divs() {
+  ; CHECK-LABEL:  divs:
+
+  ; CHECK:        lui     $[[GOT1:[0-9]+]], %hi(_gp_disp)
+  ; CHECK:        addiu   $[[GOT2:[0-9]+]], $[[GOT1]], %lo(_gp_disp)
+  ; CHECK:        addu    $[[GOT:[0-9]+]], $[[GOT2:[0-9]+]], $25
+  ; CHECK-DAG:    lw      $[[I_ADDR:[0-9]+]], %got(si)($[[GOT]])
+  ; CHECK-DAG:    lw      $[[K_ADDR:[0-9]+]], %got(sk)($[[GOT]])
+  ; CHECK-DAG:    lw      $[[J_ADDR:[0-9]+]], %got(sj)($[[GOT]])
+  ; CHECK-DAG:    lw      $[[J:[0-9]+]], 0($[[J_ADDR]])
+  ; CHECK-DAG:    lw      $[[K:[0-9]+]], 0($[[K_ADDR]])
+  ; CHECK-DAG:    div     $zero, $[[J]], $[[K]]
+  ; CHECK_DAG:    teq     $[[K]], $zero, 7
+  ; CHECK-DAG:    mflo    $[[RESULT:[0-9]+]]
+  ; CHECK:        sw      $[[RESULT]], 0($[[I_ADDR]])
+  %1 = load i32, i32* @sj, align 4
+  %2 = load i32, i32* @sk, align 4
+  %div = sdiv i32 %1, %2
+  store i32 %div, i32* @si, align 4
+  ret void
+}
+
+define void @divu() {
+  ; CHECK-LABEL:  divu:
+
+  ; CHECK:            lui     $[[GOT1:[0-9]+]], %hi(_gp_disp)
+  ; CHECK:            addiu   $[[GOT2:[0-9]+]], $[[GOT1]], %lo(_gp_disp)
+  ; CHECK:            addu    $[[GOT:[0-9]+]], $[[GOT2:[0-9]+]], $25
+  ; CHECK-DAG:        lw      $[[I_ADDR:[0-9]+]], %got(ui)($[[GOT]])
+  ; CHECK-DAG:        lw      $[[K_ADDR:[0-9]+]], %got(uk)($[[GOT]])
+  ; CHECK-DAG:        lw      $[[J_ADDR:[0-9]+]], %got(uj)($[[GOT]])
+  ; CHECK-DAG:        lw      $[[J:[0-9]+]], 0($[[J_ADDR]])
+  ; CHECK-DAG:        lw      $[[K:[0-9]+]], 0($[[K_ADDR]])
+  ; CHECK-DAG:        divu    $zero, $[[J]], $[[K]]
+  ; CHECK_DAG:        teq     $[[K]], $zero, 7
+  ; CHECK-DAG:        mflo    $[[RESULT:[0-9]+]]
+  ; CHECK:            sw      $[[RESULT]], 0($[[I_ADDR]])
+  %1 = load i32, i32* @uj, align 4
+  %2 = load i32, i32* @uk, align 4
+  %div = udiv i32 %1, %2
+  store i32 %div, i32* @ui, align 4
+  ret void
+}

Added: llvm/trunk/test/CodeGen/Mips/Fast-ISel/rem1.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/Mips/Fast-ISel/rem1.ll?rev=238757&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/Mips/Fast-ISel/rem1.ll (added)
+++ llvm/trunk/test/CodeGen/Mips/Fast-ISel/rem1.ll Mon Jun  1 11:17:37 2015
@@ -0,0 +1,56 @@
+; RUN: llc < %s -march=mipsel -mcpu=mips32 -O0 -relocation-model=pic \
+; RUN:      -fast-isel=true -mips-fast-isel -fast-isel-abort=1 | FileCheck %s
+; RUN: llc < %s -march=mipsel -mcpu=mips32r2 -O0 -relocation-model=pic \
+; RUN:      -fast-isel=true -mips-fast-isel -fast-isel-abort=1 | FileCheck %s
+
+ at sj = global i32 200, align 4
+ at sk = global i32 -47, align 4
+ at uj = global i32 200, align 4
+ at uk = global i32 43, align 4
+ at si = common global i32 0, align 4
+ at ui = common global i32 0, align 4
+
+define void @rems() {
+  ; CHECK-LABEL:  rems:
+
+  ; CHECK:            lui     $[[GOT1:[0-9]+]], %hi(_gp_disp)
+  ; CHECK:            addiu   $[[GOT2:[0-9]+]], $[[GOT1]], %lo(_gp_disp)
+  ; CHECK:            addu    $[[GOT:[0-9]+]], $[[GOT2:[0-9]+]], $25
+  ; CHECK-DAG:        lw      $[[I_ADDR:[0-9]+]], %got(si)($[[GOT]])
+  ; CHECK-DAG:        lw      $[[K_ADDR:[0-9]+]], %got(sk)($[[GOT]])
+  ; CHECK-DAG:        lw      $[[J_ADDR:[0-9]+]], %got(sj)($[[GOT]])
+  ; CHECK-DAG:        lw      $[[J:[0-9]+]], 0($[[J_ADDR]])
+  ; CHECK-DAG:        lw      $[[K:[0-9]+]], 0($[[K_ADDR]])
+  ; CHECK-DAG:        div     $zero, $[[J]], $[[K]]
+  ; CHECK_DAG:        teq     $[[K]], $zero, 7
+  ; CHECK-DAG:        mfhi    $[[RESULT:[0-9]+]]
+  ; CHECK:            sw      $[[RESULT]], 0($[[I_ADDR]])
+  %1 = load i32, i32* @sj, align 4
+  %2 = load i32, i32* @sk, align 4
+  %rem = srem i32 %1, %2
+  store i32 %rem, i32* @si, align 4
+  ret void
+}
+
+; Function Attrs: noinline nounwind
+define void @remu() {
+  ; CHECK-LABEL:  remu:
+
+  ; CHECK:            lui     $[[GOT1:[0-9]+]], %hi(_gp_disp)
+  ; CHECK:            addiu   $[[GOT2:[0-9]+]], $[[GOT1]], %lo(_gp_disp)
+  ; CHECK:            addu    $[[GOT:[0-9]+]], $[[GOT2:[0-9]+]], $25
+  ; CHECK-DAG:        lw      $[[I_ADDR:[0-9]+]], %got(ui)($[[GOT]])
+  ; CHECK-DAG:        lw      $[[K_ADDR:[0-9]+]], %got(uk)($[[GOT]])
+  ; CHECK-DAG:        lw      $[[J_ADDR:[0-9]+]], %got(uj)($[[GOT]])
+  ; CHECK-DAG:        lw      $[[J:[0-9]+]], 0($[[J_ADDR]])
+  ; CHECK-DAG:        lw      $[[K:[0-9]+]], 0($[[K_ADDR]])
+  ; CHECK-DAG:        divu    $zero, $[[J]], $[[K]]
+  ; CHECK_DAG:        teq     $[[K]], $zero, 7
+  ; CHECK-DAG:        mfhi    $[[RESULT:[0-9]+]]
+  ; CHECK:            sw      $[[RESULT]], 0($[[I_ADDR]])
+  %1 = load i32, i32* @uj, align 4
+  %2 = load i32, i32* @uk, align 4
+  %rem = urem i32 %1, %2
+  store i32 %rem, i32* @ui, align 4
+  ret void
+}





More information about the llvm-commits mailing list