mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-03 13:31:05 +00:00
[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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@182306 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
08f92c98ac
commit
f894199a14
@ -192,9 +192,9 @@ def PseudoDMULTu : MultDivPseudo<DMULTu, ACRegs128, CPU64RegsOpnd, MipsMultu,
|
||||
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>;
|
||||
|
@ -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 PReg, const TargetRegisterClass *RC)
|
||||
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::EmitInstrWithCustomInserter(MachineInstr *MI,
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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 itin, RegisterOperand RO,
|
||||
// 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", MipsSWL, CPURegs>, LW_FM<0x2a>;
|
||||
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, ACRegs, CPURegsOpnd, MipsMultu, IIImul>;
|
||||
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>;
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user