[llvm] r182306 - [mips] Trap on integer division by zero.

Akira Hatanaka ahatanaka at mips.com
Mon May 20 11:07:43 PDT 2013


Author: ahatanak
Date: Mon May 20 13:07:43 2013
New Revision: 182306

URL: http://llvm.org/viewvc/llvm-project?rev=182306&view=rev
Log:
[mips] Trap on integer division by zero.

By default, a teq instruction is inserted after integer divide. No divide-by-zero
checks are performed if option "-mnocheck-zero-division" is used.


Modified:
    llvm/trunk/lib/Target/Mips/Mips64InstrInfo.td
    llvm/trunk/lib/Target/Mips/MipsISelLowering.cpp
    llvm/trunk/lib/Target/Mips/MipsInstrFormats.td
    llvm/trunk/lib/Target/Mips/MipsInstrInfo.td
    llvm/trunk/test/CodeGen/Mips/divrem.ll
    llvm/trunk/test/CodeGen/Mips/mips64instrs.ll

Modified: llvm/trunk/lib/Target/Mips/Mips64InstrInfo.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Mips/Mips64InstrInfo.td?rev=182306&r1=182305&r2=182306&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Mips/Mips64InstrInfo.td (original)
+++ llvm/trunk/lib/Target/Mips/Mips64InstrInfo.td Mon May 20 13:07:43 2013
@@ -192,9 +192,9 @@ def PseudoDMULTu : MultDivPseudo<DMULTu,
 def DSDIV : Div<"ddiv", IIIdiv, CPU64RegsOpnd, [HI64, LO64]>, MULT_FM<0, 0x1e>;
 def DUDIV : Div<"ddivu", IIIdiv, CPU64RegsOpnd, [HI64, LO64]>, MULT_FM<0, 0x1f>;
 def PseudoDSDIV : MultDivPseudo<DSDIV, ACRegs128, CPU64RegsOpnd, MipsDivRem,
-                                IIIdiv, 0>;
+                                IIIdiv, 0, 1, 1>;
 def PseudoDUDIV : MultDivPseudo<DUDIV, ACRegs128, CPU64RegsOpnd, MipsDivRemU,
-                                IIIdiv, 0>;
+                                IIIdiv, 0, 1, 1>;
 
 def MTHI64 : MoveToLOHI<"mthi", CPU64Regs, [HI64]>, MTLO_FM<0x11>;
 def MTLO64 : MoveToLOHI<"mtlo", CPU64Regs, [LO64]>, MTLO_FM<0x13>;

Modified: llvm/trunk/lib/Target/Mips/MipsISelLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Mips/MipsISelLowering.cpp?rev=182306&r1=182305&r2=182306&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Mips/MipsISelLowering.cpp (original)
+++ llvm/trunk/lib/Target/Mips/MipsISelLowering.cpp Mon May 20 13:07:43 2013
@@ -43,6 +43,11 @@ static cl::opt<bool>
 LargeGOT("mxgot", cl::Hidden,
          cl::desc("MIPS: Enable GOT larger than 64k."), cl::init(false));
 
+static cl::opt<bool>
+NoZeroDivCheck("mnocheck-zero-division", cl::Hidden,
+               cl::desc("MIPS: Don't trap on integer division by zero."),
+               cl::init(false));
+
 static const uint16_t O32IntRegs[4] = {
   Mips::A0, Mips::A1, Mips::A2, Mips::A3
 };
@@ -766,6 +771,26 @@ addLiveIn(MachineFunction &MF, unsigned
   return VReg;
 }
 
+static MachineBasicBlock *expandPseudoDIV(MachineInstr *MI,
+                                          MachineBasicBlock &MBB,
+                                          const TargetInstrInfo &TII,
+                                          bool Is64Bit) {
+  if (NoZeroDivCheck)
+    return &MBB;
+
+  // Insert instruction "teq $divisor_reg, $zero, 7".
+  MachineBasicBlock::iterator I(MI);
+  MachineInstrBuilder MIB;
+  MIB = BuildMI(MBB, llvm::next(I), MI->getDebugLoc(), TII.get(Mips::TEQ))
+    .addOperand(MI->getOperand(2)).addReg(Mips::ZERO).addImm(7);
+
+  // Use the 32-bit sub-register if this is a 64-bit division.
+  if (Is64Bit)
+    MIB->getOperand(0).setSubReg(Mips::sub_32);
+
+  return &MBB;
+}
+
 MachineBasicBlock *
 MipsTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI,
                                                 MachineBasicBlock *BB) const {
@@ -875,6 +900,12 @@ MipsTargetLowering::EmitInstrWithCustomI
   case Mips::ATOMIC_CMP_SWAP_I64:
   case Mips::ATOMIC_CMP_SWAP_I64_P8:
     return emitAtomicCmpSwap(MI, BB, 8);
+  case Mips::PseudoSDIV:
+  case Mips::PseudoUDIV:
+    return expandPseudoDIV(MI, *BB, *getTargetMachine().getInstrInfo(), false);
+  case Mips::PseudoDSDIV:
+  case Mips::PseudoDUDIV:
+    return expandPseudoDIV(MI, *BB, *getTargetMachine().getInstrInfo(), true);
   }
 }
 

Modified: llvm/trunk/lib/Target/Mips/MipsInstrFormats.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Mips/MipsInstrFormats.td?rev=182306&r1=182305&r2=182306&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Mips/MipsInstrFormats.td (original)
+++ llvm/trunk/lib/Target/Mips/MipsInstrFormats.td Mon May 20 13:07:43 2013
@@ -476,6 +476,20 @@ class RDHWR_FM {
   let Inst{5-0}   = 0x3b;
 }
 
+class TEQ_FM<bits<6> funct> {
+  bits<5> rs;
+  bits<5> rt;
+  bits<10> code_;
+
+  bits<32> Inst;
+
+  let Inst{31-26} = 0;
+  let Inst{25-21} = rs;
+  let Inst{20-16} = rt;
+  let Inst{15-6}  = code_;
+  let Inst{5-0}   = funct;
+}
+
 //===----------------------------------------------------------------------===//
 //
 //  FLOATING POINT INSTRUCTION FORMATS

Modified: llvm/trunk/lib/Target/Mips/MipsInstrInfo.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Mips/MipsInstrInfo.td?rev=182306&r1=182305&r2=182306&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Mips/MipsInstrInfo.td (original)
+++ llvm/trunk/lib/Target/Mips/MipsInstrInfo.td Mon May 20 13:07:43 2013
@@ -640,6 +640,11 @@ class SYNC_FT :
   InstSE<(outs), (ins i32imm:$stype), "sync $stype", [(MipsSync imm:$stype)],
          NoItinerary, FrmOther>;
 
+let hasSideEffects = 1 in
+class TEQ_FT<string opstr, RegisterOperand RO> :
+  InstSE<(outs), (ins RO:$rs, RO:$rt, uimm16:$code_),
+         !strconcat(opstr, "\t$rs, $rt, $code_"), [], NoItinerary, FrmI>;
+
 // Mul, Div
 class Mult<string opstr, InstrItinClass itin, RegisterOperand RO,
            list<Register> DefRegs> :
@@ -654,12 +659,14 @@ class Mult<string opstr, InstrItinClass
 // operands.
 class MultDivPseudo<Instruction RealInst, RegisterClass R0, RegisterOperand R1,
                     SDPatternOperator OpNode, InstrItinClass Itin,
-                    bit IsComm = 1, bit HasSideEffects = 0> :
+                    bit IsComm = 1, bit HasSideEffects = 0,
+                    bit UsesCustomInserter = 0> :
   PseudoSE<(outs R0:$ac), (ins R1:$rs, R1:$rt),
            [(set R0:$ac, (OpNode R1:$rs, R1:$rt))], Itin>,
   PseudoInstExpansion<(RealInst R1:$rs, R1:$rt)> {
   let isCommutable = IsComm;
   let hasSideEffects = HasSideEffects;
+  let usesCustomInserter = UsesCustomInserter;
 }
 
 // Pseudo multiply add/sub instruction with explicit accumulator register
@@ -926,6 +933,7 @@ defm SWL : StoreLeftRightM<"swl", MipsSW
 defm SWR : StoreLeftRightM<"swr", MipsSWR, CPURegs>, LW_FM<0x2e>;
 
 def SYNC : SYNC_FT, SYNC_FM;
+def TEQ : TEQ_FT<"teq", CPURegsOpnd>, TEQ_FM<0x34>;
 
 /// Load-linked, Store-conditional
 let Predicates = [NotN64, HasStdEnc] in {
@@ -993,9 +1001,9 @@ def PseudoMULTu : MultDivPseudo<MULTu, A
 def SDIV  : Div<"div", IIIdiv, CPURegsOpnd, [HI, LO]>, MULT_FM<0, 0x1a>;
 def UDIV  : Div<"divu", IIIdiv, CPURegsOpnd, [HI, LO]>, MULT_FM<0, 0x1b>;
 def PseudoSDIV : MultDivPseudo<SDIV, ACRegs, CPURegsOpnd, MipsDivRem, IIIdiv,
-                               0>;
+                               0, 1, 1>;
 def PseudoUDIV : MultDivPseudo<UDIV, ACRegs, CPURegsOpnd, MipsDivRemU, IIIdiv,
-                               0>;
+                               0, 1, 1>;
 
 def MTHI : MoveToLOHI<"mthi", CPURegs, [HI]>, MTLO_FM<0x11>;
 def MTLO : MoveToLOHI<"mtlo", CPURegs, [LO]>, MTLO_FM<0x13>;

Modified: llvm/trunk/test/CodeGen/Mips/divrem.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/Mips/divrem.ll?rev=182306&r1=182305&r2=182306&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/Mips/divrem.ll (original)
+++ llvm/trunk/test/CodeGen/Mips/divrem.ll Mon May 20 13:07:43 2013
@@ -1,34 +1,56 @@
-; RUN: llc -march=mips < %s | FileCheck %s
+; RUN: llc -march=mips < %s | FileCheck %s -check-prefix=TRAP
+; RUN: llc -march=mips -mnocheck-zero-division < %s |\
+; RUN: FileCheck %s -check-prefix=NOCHECK
+
+; TRAP: sdiv1:
+; TRAP: div $zero, ${{[0-9]+}}, $[[R0:[0-9]+]]
+; TRAP: teq $[[R0]], $zero, 7
+; TRAP: mflo
+
+; NOCHECK: sdiv1:
+; NOCHECK-NOT: teq
+; NOCHECK: .end sdiv1
 
-; CHECK: div $zero,
 define i32 @sdiv1(i32 %a0, i32 %a1) nounwind readnone {
 entry:
   %div = sdiv i32 %a0, %a1
   ret i32 %div
 }
 
-; CHECK: div $zero,
+; TRAP: srem1:
+; TRAP: div $zero, ${{[0-9]+}}, $[[R0:[0-9]+]]
+; TRAP: teq $[[R0]], $zero, 7
+; TRAP: mfhi
+
 define i32 @srem1(i32 %a0, i32 %a1) nounwind readnone {
 entry:
   %rem = srem i32 %a0, %a1
   ret i32 %rem
 }
 
-; CHECK: divu $zero,
+; TRAP: udiv1:
+; TRAP: divu $zero, ${{[0-9]+}}, $[[R0:[0-9]+]]
+; TRAP: teq $[[R0]], $zero, 7
+; TRAP: mflo
+
 define i32 @udiv1(i32 %a0, i32 %a1) nounwind readnone {
 entry:
   %div = udiv i32 %a0, %a1
   ret i32 %div
 }
 
-; CHECK: divu $zero,
+; TRAP: urem1:
+; TRAP: divu $zero, ${{[0-9]+}}, $[[R0:[0-9]+]]
+; TRAP: teq $[[R0]], $zero, 7
+; TRAP: mfhi
+
 define i32 @urem1(i32 %a0, i32 %a1) nounwind readnone {
 entry:
   %rem = urem i32 %a0, %a1
   ret i32 %rem
 }
 
-; CHECK: div $zero,
+; TRAP: div $zero,
 define i32 @sdivrem1(i32 %a0, i32 %a1, i32* nocapture %r) nounwind {
 entry:
   %rem = srem i32 %a0, %a1
@@ -37,7 +59,7 @@ entry:
   ret i32 %div
 }
 
-; CHECK: divu $zero,
+; TRAP: divu $zero,
 define i32 @udivrem1(i32 %a0, i32 %a1, i32* nocapture %r) nounwind {
 entry:
   %rem = urem i32 %a0, %a1

Modified: llvm/trunk/test/CodeGen/Mips/mips64instrs.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/Mips/mips64instrs.ll?rev=182306&r1=182305&r2=182306&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/Mips/mips64instrs.ll (original)
+++ llvm/trunk/test/CodeGen/Mips/mips64instrs.ll Mon May 20 13:07:43 2013
@@ -86,7 +86,9 @@ entry:
 
 define i64 @f14(i64 %a, i64 %b) nounwind readnone {
 entry:
-; CHECK: ddiv $zero
+; CHECK: f14:
+; CHECK: ddiv $zero, ${{[0-9]+}}, $[[R0:[0-9]+]]
+; CHECK: teq $[[R0]], $zero, 7
 ; CHECK: mflo
   %div = sdiv i64 %a, %b
   ret i64 %div
@@ -94,7 +96,9 @@ entry:
 
 define i64 @f15(i64 %a, i64 %b) nounwind readnone {
 entry:
-; CHECK: ddivu $zero
+; CHECK: f15:
+; CHECK: ddivu $zero, ${{[0-9]+}}, $[[R0:[0-9]+]]
+; CHECK: teq $[[R0]], $zero, 7
 ; CHECK: mflo
   %div = udiv i64 %a, %b
   ret i64 %div
@@ -102,7 +106,9 @@ entry:
 
 define i64 @f16(i64 %a, i64 %b) nounwind readnone {
 entry:
-; CHECK: ddiv $zero
+; CHECK: f16:
+; CHECK: ddiv $zero, ${{[0-9]+}}, $[[R0:[0-9]+]]
+; CHECK: teq $[[R0]], $zero, 7
 ; CHECK: mfhi
   %rem = srem i64 %a, %b
   ret i64 %rem
@@ -110,7 +116,9 @@ entry:
 
 define i64 @f17(i64 %a, i64 %b) nounwind readnone {
 entry:
-; CHECK: ddivu $zero
+; CHECK: f17:
+; CHECK: ddivu $zero, ${{[0-9]+}}, $[[R0:[0-9]+]]
+; CHECK: teq $[[R0]], $zero, 7
 ; CHECK: mfhi
   %rem = urem i64 %a, %b
   ret i64 %rem





More information about the llvm-commits mailing list