From: Bruno Cardoso Lopes Date: Fri, 4 Mar 2011 21:03:24 +0000 (+0000) Subject: Improve div/rem node handling on mips. Patch by Akira Hatanaka X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=commitdiff_plain;h=38b5e86b9c67f601f354f8bcc11f5a515e200315 Improve div/rem node handling on mips. Patch by Akira Hatanaka git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@127034 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Target/Mips/MipsISelDAGToDAG.cpp b/lib/Target/Mips/MipsISelDAGToDAG.cpp index c0b09229d12..f2e53a85d1e 100644 --- a/lib/Target/Mips/MipsISelDAGToDAG.cpp +++ b/lib/Target/Mips/MipsISelDAGToDAG.cpp @@ -362,20 +362,18 @@ SDNode* MipsDAGToDAGISel::Select(SDNode *Node) { /// Mul/Div with two results case ISD::SDIVREM: case ISD::UDIVREM: + break; case ISD::SMUL_LOHI: case ISD::UMUL_LOHI: { SDValue Op1 = Node->getOperand(0); SDValue Op2 = Node->getOperand(1); unsigned Op; - if (Opcode == ISD::UMUL_LOHI || Opcode == ISD::SMUL_LOHI) - Op = (Opcode == ISD::UMUL_LOHI ? Mips::MULTu : Mips::MULT); - else - Op = (Opcode == ISD::UDIVREM ? Mips::DIVu : Mips::DIV); + Op = (Opcode == ISD::UMUL_LOHI ? Mips::MULTu : Mips::MULT); - SDNode *MulDiv = CurDAG->getMachineNode(Op, dl, MVT::Glue, Op1, Op2); + SDNode *Mul = CurDAG->getMachineNode(Op, dl, MVT::Glue, Op1, Op2); - SDValue InFlag = SDValue(MulDiv, 0); + SDValue InFlag = SDValue(Mul, 0); SDNode *Lo = CurDAG->getMachineNode(Mips::MFLO, dl, MVT::i32, MVT::Glue, InFlag); InFlag = SDValue(Lo,1); @@ -415,23 +413,8 @@ SDNode* MipsDAGToDAGISel::Select(SDNode *Node) { case ISD::SREM: case ISD::UREM: case ISD::SDIV: - case ISD::UDIV: { - SDValue Op1 = Node->getOperand(0); - SDValue Op2 = Node->getOperand(1); - - unsigned Op, MOp; - if (Opcode == ISD::SDIV || Opcode == ISD::UDIV) { - Op = (Opcode == ISD::SDIV ? Mips::DIV : Mips::DIVu); - MOp = Mips::MFLO; - } else { - Op = (Opcode == ISD::SREM ? Mips::DIV : Mips::DIVu); - MOp = Mips::MFHI; - } - SDNode *Node = CurDAG->getMachineNode(Op, dl, MVT::Glue, Op1, Op2); - - SDValue InFlag = SDValue(Node, 0); - return CurDAG->getMachineNode(MOp, dl, MVT::i32, InFlag); - } + case ISD::UDIV: + break; // Get target GOT address. case ISD::GLOBAL_OFFSET_TABLE: diff --git a/lib/Target/Mips/MipsISelLowering.cpp b/lib/Target/Mips/MipsISelLowering.cpp index 4de1548b4e9..163f71b81af 100644 --- a/lib/Target/Mips/MipsISelLowering.cpp +++ b/lib/Target/Mips/MipsISelLowering.cpp @@ -50,6 +50,8 @@ const char *MipsTargetLowering::getTargetNodeName(unsigned Opcode) const { case MipsISD::MAddu : return "MipsISD::MAddu"; case MipsISD::MSub : return "MipsISD::MSub"; case MipsISD::MSubu : return "MipsISD::MSubu"; + case MipsISD::DivRem : return "MipsISD::DivRem"; + case MipsISD::DivRemU : return "MipsISD::DivRemU"; default : return NULL; } } @@ -110,6 +112,11 @@ MipsTargetLowering(MipsTargetMachine &TM) setOperationAction(ISD::AND, MVT::i32, Custom); setOperationAction(ISD::OR, MVT::i32, Custom); + setOperationAction(ISD::SDIV, MVT::i32, Expand); + setOperationAction(ISD::SREM, MVT::i32, Expand); + setOperationAction(ISD::UDIV, MVT::i32, Expand); + setOperationAction(ISD::UREM, MVT::i32, Expand); + // Operations not directly supported by Mips. setOperationAction(ISD::BR_JT, MVT::Other, Expand); setOperationAction(ISD::BR_CC, MVT::Other, Expand); @@ -163,6 +170,8 @@ MipsTargetLowering(MipsTargetMachine &TM) setTargetDAGCombine(ISD::ADDE); setTargetDAGCombine(ISD::SUBE); + setTargetDAGCombine(ISD::SDIVREM); + setTargetDAGCombine(ISD::UDIVREM); setStackPointerRegisterToSaveRestore(Mips::SP); computeRegisterProperties(); @@ -349,6 +358,40 @@ static SDValue PerformSUBECombine(SDNode *N, SelectionDAG& DAG, return SDValue(); } +static SDValue PerformDivRemCombine(SDNode *N, SelectionDAG& DAG, + TargetLowering::DAGCombinerInfo &DCI, + const MipsSubtarget* Subtarget) { + if (DCI.isBeforeLegalizeOps()) + return SDValue(); + + unsigned opc = N->getOpcode() == ISD::SDIVREM ? MipsISD::DivRem : + MipsISD::DivRemU; + DebugLoc dl = N->getDebugLoc(); + + SDValue DivRem = DAG.getNode(opc, dl, MVT::Glue, + N->getOperand(0), N->getOperand(1)); + SDValue InChain = DAG.getEntryNode(); + SDValue InGlue = DivRem; + + // insert MFLO + if (N->hasAnyUseOfValue(0)) { + SDValue CopyFromLo = DAG.getCopyFromReg(InChain, dl, Mips::LO, MVT::i32, + InGlue); + DAG.ReplaceAllUsesOfValueWith(SDValue(N, 0), CopyFromLo); + InChain = CopyFromLo.getValue(1); + InGlue = CopyFromLo.getValue(2); + } + + // insert MFHI + if (N->hasAnyUseOfValue(1)) { + SDValue CopyFromHi = DAG.getCopyFromReg(InChain, dl, + Mips::HI, MVT::i32, InGlue); + DAG.ReplaceAllUsesOfValueWith(SDValue(N, 1), CopyFromHi); + } + + return SDValue(); +} + SDValue MipsTargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const { SelectionDAG &DAG = DCI.DAG; @@ -360,6 +403,9 @@ SDValue MipsTargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) return PerformADDECombine(N, DAG, DCI, Subtarget); case ISD::SUBE: return PerformSUBECombine(N, DAG, DCI, Subtarget); + case ISD::SDIVREM: + case ISD::UDIVREM: + return PerformDivRemCombine(N, DAG, DCI, Subtarget); } return SDValue(); diff --git a/lib/Target/Mips/MipsISelLowering.h b/lib/Target/Mips/MipsISelLowering.h index 720b6f4d7d0..06c88d77f0d 100644 --- a/lib/Target/Mips/MipsISelLowering.h +++ b/lib/Target/Mips/MipsISelLowering.h @@ -62,7 +62,11 @@ namespace llvm { MAdd, MAddu, MSub, - MSubu + MSubu, + + // DivRem(u) + DivRem, + DivRemU }; } diff --git a/lib/Target/Mips/MipsInstrInfo.td b/lib/Target/Mips/MipsInstrInfo.td index 75f7189456e..ceaf75f70a9 100644 --- a/lib/Target/Mips/MipsInstrInfo.td +++ b/lib/Target/Mips/MipsInstrInfo.td @@ -30,7 +30,9 @@ def SDT_MipsMAddMSub : SDTypeProfile<0, 4, [SDTCisVT<0, i32>, SDTCisSameAs<0, 1>, SDTCisSameAs<1, 2>, SDTCisSameAs<2, 3>]>; - +def SDT_MipsDivRem : SDTypeProfile<0, 2, + [SDTCisVT<0, i32>, + SDTCisSameAs<0, 1>]>; // Call def MipsJmpLink : SDNode<"MipsISD::JmpLink",SDT_MipsJmpLink, @@ -67,6 +69,12 @@ def MipsMSub : SDNode<"MipsISD::MSub", SDT_MipsMAddMSub, def MipsMSubu : SDNode<"MipsISD::MSubu", SDT_MipsMAddMSub, [SDNPOptInGlue, SDNPOutGlue]>; +// DivRem(u) nodes +def MipsDivRem : SDNode<"MipsISD::DivRem", SDT_MipsDivRem, + [SDNPOutGlue]>; +def MipsDivRemU : SDNode<"MipsISD::DivRemU", SDT_MipsDivRem, + [SDNPOutGlue]>; + //===----------------------------------------------------------------------===// // Mips Instruction Predicate Definitions. //===----------------------------------------------------------------------===// @@ -283,9 +291,16 @@ let isCall=1, hasDelaySlot=1, } // Mul, Div -class MulDiv func, string instr_asm, InstrItinClass itin>: - FR<0x00, func, (outs), (ins CPURegs:$a, CPURegs:$b), - !strconcat(instr_asm, "\t$a, $b"), [], itin>; +let Defs = [HI, LO] in { + class Mul func, string instr_asm, InstrItinClass itin>: + FR<0x00, func, (outs), (ins CPURegs:$a, CPURegs:$b), + !strconcat(instr_asm, "\t$a, $b"), [], itin>; + + class Div func, string instr_asm, InstrItinClass itin>: + FR<0x00, func, (outs), (ins CPURegs:$a, CPURegs:$b), + !strconcat(instr_asm, "\t$$zero, $a, $b"), + [(op CPURegs:$a, CPURegs:$b)], itin>; +} // Move from Hi/Lo class MoveFromLOHI func, string instr_asm>: @@ -452,12 +467,10 @@ let isReturn=1, isTerminator=1, hasDelaySlot=1, "jr\t$target", [(MipsRet CPURegs:$target)], IIBranch>; /// Multiply and Divide Instructions. -let Defs = [HI, LO] in { - def MULT : MulDiv<0x18, "mult", IIImul>; - def MULTu : MulDiv<0x19, "multu", IIImul>; - def DIV : MulDiv<0x1a, "div", IIIdiv>; - def DIVu : MulDiv<0x1b, "divu", IIIdiv>; -} +def MULT : Mul<0x18, "mult", IIImul>; +def MULTu : Mul<0x19, "multu", IIImul>; +def SDIV : Div; +def UDIV : Div; let Defs = [HI] in def MTHI : MoveToLOHI<0x11, "mthi">; diff --git a/test/CodeGen/Mips/divrem.ll b/test/CodeGen/Mips/divrem.ll new file mode 100644 index 00000000000..398d1b78bd4 --- /dev/null +++ b/test/CodeGen/Mips/divrem.ll @@ -0,0 +1,51 @@ +; RUN: llc -march=mips < %s | FileCheck %s + +; CHECK: div $zero, +define i32 @sdiv1(i32 %a0, i32 %a1) nounwind readnone { +entry: + %div = sdiv i32 %a0, %a1 + ret i32 %div +} + +; CHECK: div $zero, +define i32 @srem1(i32 %a0, i32 %a1) nounwind readnone { +entry: + %rem = srem i32 %a0, %a1 + ret i32 %rem +} + +; CHECK: divu $zero, +define i32 @udiv1(i32 %a0, i32 %a1) nounwind readnone { +entry: + %div = udiv i32 %a0, %a1 + ret i32 %div +} + +; CHECK: divu $zero, +define i32 @urem1(i32 %a0, i32 %a1) nounwind readnone { +entry: + %rem = urem i32 %a0, %a1 + ret i32 %rem +} + +; CHECK: div $zero, +define i32 @sdivrem1(i32 %a0, i32 %a1, i32* nocapture %r) nounwind { +entry: + %rem = srem i32 %a0, %a1 + store i32 %rem, i32* %r, align 4, !tbaa !0 + %div = sdiv i32 %a0, %a1 + ret i32 %div +} + +; CHECK: divu $zero, +define i32 @udivrem1(i32 %a0, i32 %a1, i32* nocapture %r) nounwind { +entry: + %rem = urem i32 %a0, %a1 + store i32 %rem, i32* %r, align 4, !tbaa !0 + %div = udiv i32 %a0, %a1 + ret i32 %div +} + +!0 = metadata !{metadata !"int", metadata !1} +!1 = metadata !{metadata !"omnipotent char", metadata !2} +!2 = metadata !{metadata !"Simple C/C++ TBAA", null}