Add support for 64-bit divide instructions.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@141024 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Akira Hatanaka 2011-10-03 21:06:13 +00:00
parent 0e6a24d92a
commit dda4a07cd8
4 changed files with 50 additions and 3 deletions

View File

@ -96,6 +96,11 @@ let Defs = [HI64, LO64] in {
class Mul64<bits<6> func, string instr_asm, InstrItinClass itin>:
FR<0x00, func, (outs), (ins CPU64Regs:$a, CPU64Regs:$b),
!strconcat(instr_asm, "\t$a, $b"), [], itin>;
class Div64<SDNode op, bits<6> func, string instr_asm, InstrItinClass itin>:
FR<0x00, func, (outs), (ins CPU64Regs:$a, CPU64Regs:$b),
!strconcat(instr_asm, "\t$$zero, $a, $b"),
[(op CPU64Regs:$a, CPU64Regs:$b)], itin>;
}
// Move from Hi/Lo
@ -150,6 +155,8 @@ let Predicates = [HasMips64r2] in {
/// Multiply and Divide Instructions.
def DMULT : Mul64<0x1c, "dmult", IIImul>;
def DMULTu : Mul64<0x1d, "dmultu", IIImul>;
def DSDIV : Div64<MipsDivRem, 0x1e, "ddiv", IIIdiv>;
def DUDIV : Div64<MipsDivRemU, 0x1f, "ddivu", IIIdiv>;
let Defs = [HI64] in
def MTHI64 : MoveToLOHI64<0x11, "mthi">;

View File

@ -138,6 +138,10 @@ MipsTargetLowering(MipsTargetMachine &TM)
setOperationAction(ISD::SREM, MVT::i32, Expand);
setOperationAction(ISD::UDIV, MVT::i32, Expand);
setOperationAction(ISD::UREM, MVT::i32, Expand);
setOperationAction(ISD::SDIV, MVT::i64, Expand);
setOperationAction(ISD::SREM, MVT::i64, Expand);
setOperationAction(ISD::UDIV, MVT::i64, Expand);
setOperationAction(ISD::UREM, MVT::i64, Expand);
// Operations not directly supported by Mips.
setOperationAction(ISD::BR_JT, MVT::Other, Expand);
@ -413,6 +417,9 @@ static SDValue PerformDivRemCombine(SDNode *N, SelectionDAG& DAG,
if (DCI.isBeforeLegalizeOps())
return SDValue();
EVT Ty = N->getValueType(0);
unsigned LO = (Ty == MVT::i32) ? Mips::LO : Mips::LO64;
unsigned HI = (Ty == MVT::i32) ? Mips::HI : Mips::HI64;
unsigned opc = N->getOpcode() == ISD::SDIVREM ? MipsISD::DivRem :
MipsISD::DivRemU;
DebugLoc dl = N->getDebugLoc();
@ -424,7 +431,7 @@ static SDValue PerformDivRemCombine(SDNode *N, SelectionDAG& DAG,
// insert MFLO
if (N->hasAnyUseOfValue(0)) {
SDValue CopyFromLo = DAG.getCopyFromReg(InChain, dl, Mips::LO, MVT::i32,
SDValue CopyFromLo = DAG.getCopyFromReg(InChain, dl, LO, Ty,
InGlue);
DAG.ReplaceAllUsesOfValueWith(SDValue(N, 0), CopyFromLo);
InChain = CopyFromLo.getValue(1);
@ -434,7 +441,7 @@ static SDValue PerformDivRemCombine(SDNode *N, SelectionDAG& DAG,
// insert MFHI
if (N->hasAnyUseOfValue(1)) {
SDValue CopyFromHi = DAG.getCopyFromReg(InChain, dl,
Mips::HI, MVT::i32, InGlue);
HI, Ty, InGlue);
DAG.ReplaceAllUsesOfValueWith(SDValue(N, 1), CopyFromHi);
}

View File

@ -34,7 +34,7 @@ def SDT_MipsMAddMSub : SDTypeProfile<0, 4,
SDTCisSameAs<1, 2>,
SDTCisSameAs<2, 3>]>;
def SDT_MipsDivRem : SDTypeProfile<0, 2,
[SDTCisVT<0, i32>,
[SDTCisInt<0>,
SDTCisSameAs<0, 1>]>;
def SDT_MipsThreadPointer : SDTypeProfile<1, 0, [SDTCisPtrTy<0>]>;

View File

@ -83,3 +83,36 @@ entry:
%mul = mul i64 %b, %a
ret i64 %mul
}
define i64 @f14(i64 %a, i64 %b) nounwind readnone {
entry:
; CHECK: ddiv $zero
; CHECK: mflo
%div = sdiv i64 %a, %b
ret i64 %div
}
define i64 @f15(i64 %a, i64 %b) nounwind readnone {
entry:
; CHECK: ddivu $zero
; CHECK: mflo
%div = udiv i64 %a, %b
ret i64 %div
}
define i64 @f16(i64 %a, i64 %b) nounwind readnone {
entry:
; CHECK: ddiv $zero
; CHECK: mfhi
%rem = srem i64 %a, %b
ret i64 %rem
}
define i64 @f17(i64 %a, i64 %b) nounwind readnone {
entry:
; CHECK: ddivu $zero
; CHECK: mfhi
%rem = urem i64 %a, %b
ret i64 %rem
}