llvm.org GIT mirror llvm / 38b5e86
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 Bruno Cardoso Lopes 9 years ago
5 changed file(s) with 133 addition(s) and 36 deletion(s). Raw diff Collapse all Expand all
361361 /// Mul/Div with two results
362362 case ISD::SDIVREM:
363363 case ISD::UDIVREM:
364 break;
364365 case ISD::SMUL_LOHI:
365366 case ISD::UMUL_LOHI: {
366367 SDValue Op1 = Node->getOperand(0);
367368 SDValue Op2 = Node->getOperand(1);
368369
369370 unsigned Op;
370 if (Opcode == ISD::UMUL_LOHI || Opcode == ISD::SMUL_LOHI)
371 Op = (Opcode == ISD::UMUL_LOHI ? Mips::MULTu : Mips::MULT);
372 else
373 Op = (Opcode == ISD::UDIVREM ? Mips::DIVu : Mips::DIV);
374
375 SDNode *MulDiv = CurDAG->getMachineNode(Op, dl, MVT::Glue, Op1, Op2);
376
377 SDValue InFlag = SDValue(MulDiv, 0);
371 Op = (Opcode == ISD::UMUL_LOHI ? Mips::MULTu : Mips::MULT);
372
373 SDNode *Mul = CurDAG->getMachineNode(Op, dl, MVT::Glue, Op1, Op2);
374
375 SDValue InFlag = SDValue(Mul, 0);
378376 SDNode *Lo = CurDAG->getMachineNode(Mips::MFLO, dl, MVT::i32,
379377 MVT::Glue, InFlag);
380378 InFlag = SDValue(Lo,1);
414412 case ISD::SREM:
415413 case ISD::UREM:
416414 case ISD::SDIV:
417 case ISD::UDIV: {
418 SDValue Op1 = Node->getOperand(0);
419 SDValue Op2 = Node->getOperand(1);
420
421 unsigned Op, MOp;
422 if (Opcode == ISD::SDIV || Opcode == ISD::UDIV) {
423 Op = (Opcode == ISD::SDIV ? Mips::DIV : Mips::DIVu);
424 MOp = Mips::MFLO;
425 } else {
426 Op = (Opcode == ISD::SREM ? Mips::DIV : Mips::DIVu);
427 MOp = Mips::MFHI;
428 }
429 SDNode *Node = CurDAG->getMachineNode(Op, dl, MVT::Glue, Op1, Op2);
430
431 SDValue InFlag = SDValue(Node, 0);
432 return CurDAG->getMachineNode(MOp, dl, MVT::i32, InFlag);
433 }
415 case ISD::UDIV:
416 break;
434417
435418 // Get target GOT address.
436419 case ISD::GLOBAL_OFFSET_TABLE:
4949 case MipsISD::MAddu : return "MipsISD::MAddu";
5050 case MipsISD::MSub : return "MipsISD::MSub";
5151 case MipsISD::MSubu : return "MipsISD::MSubu";
52 case MipsISD::DivRem : return "MipsISD::DivRem";
53 case MipsISD::DivRemU : return "MipsISD::DivRemU";
5254 default : return NULL;
5355 }
5456 }
109111 setOperationAction(ISD::AND, MVT::i32, Custom);
110112 setOperationAction(ISD::OR, MVT::i32, Custom);
111113
114 setOperationAction(ISD::SDIV, MVT::i32, Expand);
115 setOperationAction(ISD::SREM, MVT::i32, Expand);
116 setOperationAction(ISD::UDIV, MVT::i32, Expand);
117 setOperationAction(ISD::UREM, MVT::i32, Expand);
118
112119 // Operations not directly supported by Mips.
113120 setOperationAction(ISD::BR_JT, MVT::Other, Expand);
114121 setOperationAction(ISD::BR_CC, MVT::Other, Expand);
162169
163170 setTargetDAGCombine(ISD::ADDE);
164171 setTargetDAGCombine(ISD::SUBE);
172 setTargetDAGCombine(ISD::SDIVREM);
173 setTargetDAGCombine(ISD::UDIVREM);
165174
166175 setStackPointerRegisterToSaveRestore(Mips::SP);
167176 computeRegisterProperties();
348357 return SDValue();
349358 }
350359
360 static SDValue PerformDivRemCombine(SDNode *N, SelectionDAG& DAG,
361 TargetLowering::DAGCombinerInfo &DCI,
362 const MipsSubtarget* Subtarget) {
363 if (DCI.isBeforeLegalizeOps())
364 return SDValue();
365
366 unsigned opc = N->getOpcode() == ISD::SDIVREM ? MipsISD::DivRem :
367 MipsISD::DivRemU;
368 DebugLoc dl = N->getDebugLoc();
369
370 SDValue DivRem = DAG.getNode(opc, dl, MVT::Glue,
371 N->getOperand(0), N->getOperand(1));
372 SDValue InChain = DAG.getEntryNode();
373 SDValue InGlue = DivRem;
374
375 // insert MFLO
376 if (N->hasAnyUseOfValue(0)) {
377 SDValue CopyFromLo = DAG.getCopyFromReg(InChain, dl, Mips::LO, MVT::i32,
378 InGlue);
379 DAG.ReplaceAllUsesOfValueWith(SDValue(N, 0), CopyFromLo);
380 InChain = CopyFromLo.getValue(1);
381 InGlue = CopyFromLo.getValue(2);
382 }
383
384 // insert MFHI
385 if (N->hasAnyUseOfValue(1)) {
386 SDValue CopyFromHi = DAG.getCopyFromReg(InChain, dl,
387 Mips::HI, MVT::i32, InGlue);
388 DAG.ReplaceAllUsesOfValueWith(SDValue(N, 1), CopyFromHi);
389 }
390
391 return SDValue();
392 }
393
351394 SDValue MipsTargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI)
352395 const {
353396 SelectionDAG &DAG = DCI.DAG;
359402 return PerformADDECombine(N, DAG, DCI, Subtarget);
360403 case ISD::SUBE:
361404 return PerformSUBECombine(N, DAG, DCI, Subtarget);
405 case ISD::SDIVREM:
406 case ISD::UDIVREM:
407 return PerformDivRemCombine(N, DAG, DCI, Subtarget);
362408 }
363409
364410 return SDValue();
6161 MAdd,
6262 MAddu,
6363 MSub,
64 MSubu
64 MSubu,
65
66 // DivRem(u)
67 DivRem,
68 DivRemU
6569 };
6670 }
6771
2929 [SDTCisVT<0, i32>, SDTCisSameAs<0, 1>,
3030 SDTCisSameAs<1, 2>,
3131 SDTCisSameAs<2, 3>]>;
32
32 def SDT_MipsDivRem : SDTypeProfile<0, 2,
33 [SDTCisVT<0, i32>,
34 SDTCisSameAs<0, 1>]>;
3335
3436 // Call
3537 def MipsJmpLink : SDNode<"MipsISD::JmpLink",SDT_MipsJmpLink,
6567 [SDNPOptInGlue, SDNPOutGlue]>;
6668 def MipsMSubu : SDNode<"MipsISD::MSubu", SDT_MipsMAddMSub,
6769 [SDNPOptInGlue, SDNPOutGlue]>;
70
71 // DivRem(u) nodes
72 def MipsDivRem : SDNode<"MipsISD::DivRem", SDT_MipsDivRem,
73 [SDNPOutGlue]>;
74 def MipsDivRemU : SDNode<"MipsISD::DivRemU", SDT_MipsDivRem,
75 [SDNPOutGlue]>;
6876
6977 //===----------------------------------------------------------------------===//
7078 // Mips Instruction Predicate Definitions.
282290 }
283291
284292 // Mul, Div
285 class MulDiv func, string instr_asm, InstrItinClass itin>:
286 FR<0x00, func, (outs), (ins CPURegs:$a, CPURegs:$b),
287 !strconcat(instr_asm, "\t$a, $b"), [], itin>;
293 let Defs = [HI, LO] in {
294 class Mul func, string instr_asm, InstrItinClass itin>:
295 FR<0x00, func, (outs), (ins CPURegs:$a, CPURegs:$b),
296 !strconcat(instr_asm, "\t$a, $b"), [], itin>;
297
298 class Div func, string instr_asm, InstrItinClass itin>:
299 FR<0x00, func, (outs), (ins CPURegs:$a, CPURegs:$b),
300 !strconcat(instr_asm, "\t$$zero, $a, $b"),
301 [(op CPURegs:$a, CPURegs:$b)], itin>;
302 }
288303
289304 // Move from Hi/Lo
290305 class MoveFromLOHI func, string instr_asm>:
451466 "jr\t$target", [(MipsRet CPURegs:$target)], IIBranch>;
452467
453468 /// Multiply and Divide Instructions.
454 let Defs = [HI, LO] in {
455 def MULT : MulDiv<0x18, "mult", IIImul>;
456 def MULTu : MulDiv<0x19, "multu", IIImul>;
457 def DIV : MulDiv<0x1a, "div", IIIdiv>;
458 def DIVu : MulDiv<0x1b, "divu", IIIdiv>;
459 }
469 def MULT : Mul<0x18, "mult", IIImul>;
470 def MULTu : Mul<0x19, "multu", IIImul>;
471 def SDIV : Div;
472 def UDIV : Div;
460473
461474 let Defs = [HI] in
462475 def MTHI : MoveToLOHI<0x11, "mthi">;
0 ; RUN: llc -march=mips < %s | FileCheck %s
1
2 ; CHECK: div $zero,
3 define i32 @sdiv1(i32 %a0, i32 %a1) nounwind readnone {
4 entry:
5 %div = sdiv i32 %a0, %a1
6 ret i32 %div
7 }
8
9 ; CHECK: div $zero,
10 define i32 @srem1(i32 %a0, i32 %a1) nounwind readnone {
11 entry:
12 %rem = srem i32 %a0, %a1
13 ret i32 %rem
14 }
15
16 ; CHECK: divu $zero,
17 define i32 @udiv1(i32 %a0, i32 %a1) nounwind readnone {
18 entry:
19 %div = udiv i32 %a0, %a1
20 ret i32 %div
21 }
22
23 ; CHECK: divu $zero,
24 define i32 @urem1(i32 %a0, i32 %a1) nounwind readnone {
25 entry:
26 %rem = urem i32 %a0, %a1
27 ret i32 %rem
28 }
29
30 ; CHECK: div $zero,
31 define i32 @sdivrem1(i32 %a0, i32 %a1, i32* nocapture %r) nounwind {
32 entry:
33 %rem = srem i32 %a0, %a1
34 store i32 %rem, i32* %r, align 4, !tbaa !0
35 %div = sdiv i32 %a0, %a1
36 ret i32 %div
37 }
38
39 ; CHECK: divu $zero,
40 define i32 @udivrem1(i32 %a0, i32 %a1, i32* nocapture %r) nounwind {
41 entry:
42 %rem = urem i32 %a0, %a1
43 store i32 %rem, i32* %r, align 4, !tbaa !0
44 %div = udiv i32 %a0, %a1
45 ret i32 %div
46 }
47
48 !0 = metadata !{metadata !"int", metadata !1}
49 !1 = metadata !{metadata !"omnipotent char", metadata !2}
50 !2 = metadata !{metadata !"Simple C/C++ TBAA", null}