Added custom isel for MUL, SDIVREM, UDIVREM, SMUL_LOHI and UMUL_LOHI nodes
authorBruno Cardoso Lopes <bruno.cardoso@gmail.com>
Fri, 6 Jun 2008 06:37:31 +0000 (06:37 +0000)
committerBruno Cardoso Lopes <bruno.cardoso@gmail.com>
Fri, 6 Jun 2008 06:37:31 +0000 (06:37 +0000)
MUL is not anymore directly matched because its a pseudoinstruction.
LogicI class fixed to zero-extend immediates.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@52036 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/Mips/MipsISelDAGToDAG.cpp
lib/Target/Mips/MipsInstrInfo.td

index 8043f7b173bd10f5d9f3a7c5fc3f0695beb7a4df..ceb4bed30f4916a339ba3e9a11fcd9544934137e 100644 (file)
@@ -226,14 +226,24 @@ Select(SDOperand N)
 
     default: break;
 
+    case ISD::SUBE: 
     case ISD::ADDE: {
-      // ADDE is usally attached with a ADDC instruction, we must
-      // compare ADDC operands and set a register if we have a carry.
-      SDOperand InFlag = Node->getOperand(2);
-      unsigned Opc = InFlag.getOpcode();
-      assert((Opc == ISD::ADDC || Opc == ISD::ADDE) &&  
-             "ADDE flag operand must come from a ADDC or ADDE");
-      SDOperand Ops[] = { InFlag.getValue(0), InFlag.getOperand(1) };
+      SDOperand InFlag = Node->getOperand(2), CmpLHS;
+      unsigned Opc = InFlag.getOpcode(), MOp;
+
+      assert(((Opc == ISD::ADDC || Opc == ISD::ADDE) || 
+              (Opc == ISD::SUBC || Opc == ISD::SUBE)) &&  
+             "(ADD|SUB)E flag operand must come from (ADD|SUB)C/E insn");
+
+      if (Opcode == ISD::ADDE) {
+        CmpLHS = InFlag.getValue(0);
+        MOp = Mips::ADDu;
+      } else { 
+        CmpLHS = InFlag.getOperand(0);
+        MOp = Mips::SUBu;
+      }
+
+      SDOperand Ops[] = { CmpLHS, InFlag.getOperand(1) };
 
       SDOperand LHS = Node->getOperand(0);
       SDOperand RHS = Node->getOperand(1);
@@ -245,34 +255,45 @@ Select(SDOperand N)
       SDNode *AddCarry = CurDAG->getTargetNode(Mips::ADDu, VT, 
                                                SDOperand(Carry,0), RHS);
 
-      return CurDAG->SelectNodeTo(N.Val, Mips::ADDu, VT, MVT::Flag, 
+      return CurDAG->SelectNodeTo(N.Val, MOp, VT, MVT::Flag, 
                                   LHS, SDOperand(AddCarry,0));
     }
 
-    case ISD::SUBE: {
-      // SUBE is usally attached with a SUBC instruction, we must
-      // compare SUBC operands and set a register if we have a carry.
-      SDOperand InFlag = Node->getOperand(2);
-      unsigned Opc = InFlag.getOpcode();
-      assert((Opc == ISD::SUBC || Opc == ISD::SUBE) &&  
-             "SUBE flag operand must come from a SUBC or SUBE");
-      SDOperand Ops[] = { InFlag.getOperand(0), InFlag.getOperand(1) };
+    /// Mul/Div with two results
+    case ISD::SDIVREM:
+    case ISD::UDIVREM:
+    case ISD::SMUL_LOHI:
+    case ISD::UMUL_LOHI: {
+      SDOperand Op1 = Node->getOperand(0);
+      SDOperand Op2 = Node->getOperand(1);
+      AddToISelQueue(Op1);
+      AddToISelQueue(Op2);
 
-      SDOperand LHS = Node->getOperand(0);
-      SDOperand RHS = Node->getOperand(1);
-      AddToISelQueue(LHS);
-      AddToISelQueue(RHS);
+      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);
 
-      MVT::ValueType VT = LHS.getValueType();
-      SDNode *Carry = CurDAG->getTargetNode(Mips::SLTu, VT, Ops, 2);
-      SDNode *AddCarry = CurDAG->getTargetNode(Mips::ADDu, VT, 
-                                               SDOperand(Carry,0), RHS);
+      SDNode *Node = CurDAG->getTargetNode(Op, MVT::Flag, Op1, Op2);
 
-      return CurDAG->SelectNodeTo(N.Val, Mips::SUBu, VT, MVT::Flag, 
-                                  LHS, SDOperand(AddCarry,0));
+      SDOperand InFlag = SDOperand(Node, 0);
+      SDNode *Lo = CurDAG->getTargetNode(Mips::MFLO, MVT::i32, MVT::Flag, InFlag);
+
+      InFlag = SDOperand(Lo,1);
+      SDNode *Hi = CurDAG->getTargetNode(Mips::MFHI, MVT::i32, InFlag);
+
+      if (!N.getValue(0).use_empty()) 
+        ReplaceUses(N.getValue(0), SDOperand(Lo,0));
+
+      if (!N.getValue(1).use_empty()) 
+        ReplaceUses(N.getValue(1), SDOperand(Hi,0));
+
+      return NULL;
     }
 
-    /// Special Mul operations
+    /// Special Muls
+    case ISD::MUL: 
     case ISD::MULHS:
     case ISD::MULHU: {
       SDOperand MulOp1 = Node->getOperand(0);
@@ -283,38 +304,36 @@ Select(SDOperand N)
       unsigned MulOp  = (Opcode == ISD::MULHU ? Mips::MULTu : Mips::MULT);
       SDNode *MulNode = CurDAG->getTargetNode(MulOp, MVT::Flag, MulOp1, MulOp2);
 
-      SDOperand MFInFlag = SDOperand(MulNode, 0);
-      return CurDAG->getTargetNode(Mips::MFHI, MVT::i32, MFInFlag);
+      SDOperand InFlag = SDOperand(MulNode, 0);
+
+      if (MulOp == ISD::MUL)
+        return CurDAG->getTargetNode(Mips::MFLO, MVT::i32, InFlag);
+      else
+        return CurDAG->getTargetNode(Mips::MFHI, MVT::i32, InFlag);
     }
 
-    /// Div operations
+    /// Div/Rem operations
+    case ISD::SREM:
+    case ISD::UREM:
     case ISD::SDIV: 
     case ISD::UDIV: {
-      SDOperand DivOp1 = Node->getOperand(0);
-      SDOperand DivOp2 = Node->getOperand(1);
-      AddToISelQueue(DivOp1);
-      AddToISelQueue(DivOp2);
-
-      unsigned DivOp  = (Opcode == ISD::SDIV ? Mips::DIV : Mips::DIVu);
-      SDNode *DivNode = CurDAG->getTargetNode(DivOp, MVT::Flag, DivOp1, DivOp2);
-
-      SDOperand MFInFlag = SDOperand(DivNode, 0);
-      return CurDAG->getTargetNode(Mips::MFLO, MVT::i32, MFInFlag);
-    }
+      SDOperand Op1 = Node->getOperand(0);
+      SDOperand Op2 = Node->getOperand(1);
+      AddToISelQueue(Op1);
+      AddToISelQueue(Op2);
+
+      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->getTargetNode(Op, MVT::Flag, Op1, Op2);
 
-    /// Rem operations
-    case ISD::SREM: 
-    case ISD::UREM: {
-      SDOperand RemOp1 = Node->getOperand(0);
-      SDOperand RemOp2 = Node->getOperand(1);
-      AddToISelQueue(RemOp1);
-      AddToISelQueue(RemOp2);
-      
-      unsigned RemOp  = (Opcode == ISD::SREM ? Mips::DIV : Mips::DIVu);
-      SDNode *RemNode = CurDAG->getTargetNode(RemOp, MVT::Flag, RemOp1, RemOp2);
-
-      SDOperand MFInFlag = SDOperand(RemNode, 0);
-      return CurDAG->getTargetNode(Mips::MFHI, MVT::i32, MFInFlag);
+      SDOperand InFlag = SDOperand(Node, 0);
+      return CurDAG->getTargetNode(MOp, MVT::i32, InFlag);
     }
 
     // Get target GOT address.
index b469167824c64e04f6d8e38c3cc74861cad24129..57f24ad395b325eef5afa956520b1d53978a84cb 100644 (file)
@@ -172,7 +172,7 @@ class LogicI<bits<6> op, string instr_asm, SDNode OpNode>:
       (outs CPURegs:$dst),
       (ins CPURegs:$b, uimm16:$c),
       !strconcat(instr_asm, " $dst, $b, $c"),
-      [(set CPURegs:$dst, (OpNode CPURegs:$b, immSExt16:$c))], IIAlu>;
+      [(set CPURegs:$dst, (OpNode CPURegs:$b, immZExt16:$c))], IIAlu>;
 
 class LogicNOR<bits<6> op, bits<6> func, string instr_asm>:
   FR< op,
@@ -392,9 +392,10 @@ let usesCustomDAGSchedInserter = 1 in {
 
 // ADDiu just accept 16-bit immediates but we handle this on Pat's.
 // immZExt32 is used here so it can match GlobalAddress immediates.
+// MUL is a assembly macro in the current used ISAs.
 def ADDiu   : ArithI<0x09, "addiu", add, uimm16, immZExt16>;
 def ADDi    : ArithI<0x08, "addi",  add, simm16, immSExt16>;
-def MUL     : ArithR<0x1c, 0x02, "mul", mul, IIImul>;
+//def MUL     : ArithR<0x1c, 0x02, "mul", mul, IIImul>;
 def ADDu    : ArithR<0x00, 0x21, "addu", add, IIAlu>;
 def SUBu    : ArithR<0x00, 0x23, "subu", sub, IIAlu>;
 def ADD     : ArithOverflowR<0x00, 0x20, "add">;