Added custom SELECT_CC lowering
authorBruno Cardoso Lopes <bruno.cardoso@gmail.com>
Fri, 6 Jun 2008 00:58:26 +0000 (00:58 +0000)
committerBruno Cardoso Lopes <bruno.cardoso@gmail.com>
Fri, 6 Jun 2008 00:58:26 +0000 (00:58 +0000)
Added special isel for ADDE,SUBE and new patterns to match SUBC,ADDC

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

lib/Target/Mips/MipsISelDAGToDAG.cpp
lib/Target/Mips/MipsISelLowering.cpp
lib/Target/Mips/MipsISelLowering.h
lib/Target/Mips/MipsInstrFormats.td
lib/Target/Mips/MipsInstrInfo.td

index b2ad66670bb1e74ef54766f7fce8dfa94cb82273..8043f7b173bd10f5d9f3a7c5fc3f0695beb7a4df 100644 (file)
@@ -226,6 +226,52 @@ Select(SDOperand N)
 
     default: break;
 
+    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 LHS = Node->getOperand(0);
+      SDOperand RHS = Node->getOperand(1);
+      AddToISelQueue(LHS);
+      AddToISelQueue(RHS);
+
+      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);
+
+      return CurDAG->SelectNodeTo(N.Val, Mips::ADDu, 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) };
+
+      SDOperand LHS = Node->getOperand(0);
+      SDOperand RHS = Node->getOperand(1);
+      AddToISelQueue(LHS);
+      AddToISelQueue(RHS);
+
+      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);
+
+      return CurDAG->SelectNodeTo(N.Val, Mips::SUBu, VT, MVT::Flag, 
+                                  LHS, SDOperand(AddCarry,0));
+    }
+
     /// Special Mul operations
     case ISD::MULHS:
     case ISD::MULHU: {
index 441f2126d0cb1738d7374c46c3728d7590319e9a..0e233c71f079fb66739640865a9660668b6c006e 100644 (file)
@@ -39,11 +39,12 @@ getTargetNodeName(unsigned Opcode) const
 {
   switch (Opcode) 
   {
-    case MipsISD::JmpLink : return "MipsISD::JmpLink";
-    case MipsISD::Hi      : return "MipsISD::Hi";
-    case MipsISD::Lo      : return "MipsISD::Lo";
-    case MipsISD::Ret     : return "MipsISD::Ret";
-    default               : return NULL;
+    case MipsISD::JmpLink   : return "MipsISD::JmpLink";
+    case MipsISD::Hi        : return "MipsISD::Hi";
+    case MipsISD::Lo        : return "MipsISD::Lo";
+    case MipsISD::Ret       : return "MipsISD::Ret";
+    case MipsISD::SelectCC  : return "MipsISD::SelectCC";
+    default                 : return NULL;
   }
 }
 
@@ -65,6 +66,7 @@ MipsTargetLowering(MipsTargetMachine &TM): TargetLowering(TM)
   setOperationAction(ISD::GlobalTLSAddress, MVT::i32, Custom);
   setOperationAction(ISD::RET, MVT::Other, Custom);
   setOperationAction(ISD::JumpTable, MVT::i32, Custom);
+  setOperationAction(ISD::SELECT_CC, MVT::i32, Custom);
 
   // Load extented operations for i1 types must be promoted 
   setLoadXAction(ISD::EXTLOAD,  MVT::i1,  Promote);
@@ -75,7 +77,6 @@ MipsTargetLowering(MipsTargetMachine &TM): TargetLowering(TM)
   setOperationAction(ISD::BR_JT,     MVT::Other, Expand);
   setOperationAction(ISD::BR_CC,     MVT::Other, Expand);
   setOperationAction(ISD::SELECT_CC, MVT::Other, Expand);
-  setOperationAction(ISD::SELECT_CC, MVT::i32,   Expand);
   setOperationAction(ISD::SELECT,    MVT::i32,   Expand);
   setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand);
 
@@ -124,10 +125,75 @@ LowerOperation(SDOperand Op, SelectionDAG &DAG)
     case ISD::GlobalAddress:    return LowerGlobalAddress(Op, DAG);
     case ISD::GlobalTLSAddress: return LowerGlobalTLSAddress(Op, DAG);
     case ISD::JumpTable:        return LowerJumpTable(Op, DAG);
+    case ISD::SELECT_CC:        return LowerSELECT_CC(Op, DAG);
   }
   return SDOperand();
 }
 
+MachineBasicBlock *
+MipsTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI,
+                                                MachineBasicBlock *BB) 
+{
+  const TargetInstrInfo *TII = getTargetMachine().getInstrInfo();
+  switch (MI->getOpcode()) {
+  default: assert(false && "Unexpected instr type to insert");
+  case Mips::Select_CC: {
+    // To "insert" a SELECT_CC instruction, we actually have to insert the
+    // diamond control-flow pattern.  The incoming instruction knows the
+    // destination vreg to set, the condition code register to branch on, the
+    // true/false values to select between, and a branch opcode to use.
+    const BasicBlock *LLVM_BB = BB->getBasicBlock();
+    ilist<MachineBasicBlock>::iterator It = BB;
+    ++It;
+
+    //  thisMBB:
+    //  ...
+    //   TrueVal = ...
+    //   setcc r1, r2, r3
+    //   bNE   r1, r0, copy1MBB
+    //   fallthrough --> copy0MBB
+    MachineBasicBlock *thisMBB  = BB;
+    MachineBasicBlock *copy0MBB = new MachineBasicBlock(LLVM_BB);
+    MachineBasicBlock *sinkMBB  = new MachineBasicBlock(LLVM_BB);
+    BuildMI(BB, TII->get(Mips::BNE)).addReg(MI->getOperand(1).getReg())
+      .addReg(Mips::ZERO).addMBB(sinkMBB);
+    MachineFunction *F = BB->getParent();
+    F->getBasicBlockList().insert(It, copy0MBB);
+    F->getBasicBlockList().insert(It, sinkMBB);
+    // Update machine-CFG edges by first adding all successors of the current
+    // block to the new block which will contain the Phi node for the select.
+    for(MachineBasicBlock::succ_iterator i = BB->succ_begin(),
+        e = BB->succ_end(); i != e; ++i)
+      sinkMBB->addSuccessor(*i);
+    // Next, remove all successors of the current block, and add the true
+    // and fallthrough blocks as its successors.
+    while(!BB->succ_empty())
+      BB->removeSuccessor(BB->succ_begin());
+    BB->addSuccessor(copy0MBB);
+    BB->addSuccessor(sinkMBB);
+
+    //  copy0MBB:
+    //   %FalseValue = ...
+    //   # fallthrough to sinkMBB
+    BB = copy0MBB;
+
+    // Update machine-CFG edges
+    BB->addSuccessor(sinkMBB);
+
+    //  sinkMBB:
+    //   %Result = phi [ %FalseValue, copy0MBB ], [ %TrueValue, thisMBB ]
+    //  ...
+    BB = sinkMBB;
+    BuildMI(BB, TII->get(Mips::PHI), MI->getOperand(0).getReg())
+      .addReg(MI->getOperand(2).getReg()).addMBB(copy0MBB)
+      .addReg(MI->getOperand(3).getReg()).addMBB(thisMBB);
+
+    delete MI;   // The pseudo instruction is gone now.
+    return BB;
+  }
+  }
+}
+
 //===----------------------------------------------------------------------===//
 //  Lower helper functions
 //===----------------------------------------------------------------------===//
@@ -181,6 +247,23 @@ LowerGlobalTLSAddress(SDOperand Op, SelectionDAG &DAG)
   return SDOperand(); // Not reached
 }
 
+SDOperand MipsTargetLowering::
+LowerSELECT_CC(SDOperand Op, SelectionDAG &DAG) 
+{
+  SDOperand LHS   = Op.getOperand(0); 
+  SDOperand RHS   = Op.getOperand(1); 
+  SDOperand True  = Op.getOperand(2);
+  SDOperand False = Op.getOperand(3);
+  SDOperand CC    = Op.getOperand(4);
+
+  const MVT::ValueType *VTs = DAG.getNodeValueTypes(MVT::i32);
+  SDOperand Ops[] = { LHS, RHS, CC };
+  SDOperand SetCCRes = DAG.getNode(ISD::SETCC, VTs, 1, Ops, 3); 
+
+  return DAG.getNode(MipsISD::SelectCC, True.getValueType(), 
+                     SetCCRes, True, False);
+}
+
 SDOperand MipsTargetLowering::
 LowerJumpTable(SDOperand Op, SelectionDAG &DAG) 
 {
index e2b4b3f4a89c8c02ff207b9f081e973438e9a531..cda36acb3724322564f2e4294de83ab0b88a546d 100644 (file)
@@ -37,6 +37,9 @@ namespace llvm {
       // No relation with Mips Lo register
       Lo, 
 
+      // Select CC Pseudo Instruction
+      SelectCC,
+
       // Return 
       Ret
     };
@@ -80,6 +83,10 @@ namespace llvm {
     SDOperand LowerGlobalAddress(SDOperand Op, SelectionDAG &DAG);
     SDOperand LowerGlobalTLSAddress(SDOperand Op, SelectionDAG &DAG);
     SDOperand LowerJumpTable(SDOperand Op, SelectionDAG &DAG);
+    SDOperand LowerSELECT_CC(SDOperand Op, SelectionDAG &DAG);
+
+    virtual MachineBasicBlock *EmitInstrWithCustomInserter(MachineInstr *MI,
+                                                        MachineBasicBlock *MBB);
 
     // Inline asm support
     ConstraintType getConstraintType(const std::string &Constraint) const;
index caeabd5b5e7ef437329649d5cc4a506b5f0d88cf..e84dd26856194e39e4dc426faf119c89c0ba7c3b 100644 (file)
@@ -43,7 +43,7 @@ class MipsInst<dag outs, dag ins, string asmstr, list<dag> pattern,
 }
 
 // Mips Pseudo Instructions Format
-class PseudoInstMips<dag outs, dag ins, string asmstr, list<dag> pattern>:
+class MipsPseudo<dag outs, dag ins, string asmstr, list<dag> pattern>:
       MipsInst<outs, ins, asmstr, pattern, IIPseudo>;
 
 //===----------------------------------------------------------------------===//
index 239542309984e3e0f3550c3e5121d961035d9f4e..b469167824c64e04f6d8e38c3cc74861cad24129 100644 (file)
@@ -43,6 +43,11 @@ def callseq_start   : SDNode<"ISD::CALLSEQ_START", SDT_MipsCallSeqStart,
 def callseq_end     : SDNode<"ISD::CALLSEQ_END", SDT_MipsCallSeqEnd,
                              [SDNPHasChain, SDNPOptInFlag, SDNPOutFlag]>;
 
+// Select CC
+def SDT_MipsSelectCC : SDTypeProfile<1, 3, [SDTCisSameAs<0, 1>, 
+                                            SDTCisSameAs<1, 2>, SDTCisInt<3>]>;
+def MipsSelectCC : SDNode<"MipsISD::SelectCC", SDT_MipsSelectCC>;
+
 //===----------------------------------------------------------------------===//
 // Mips Instruction Predicate Definitions.
 //===----------------------------------------------------------------------===//
@@ -346,10 +351,10 @@ class EffectiveAddress<string instr_asm> :
 
 // As stack alignment is always done with addiu, we need a 16-bit immediate
 let Defs = [SP], Uses = [SP] in {
-def ADJCALLSTACKDOWN : PseudoInstMips<(outs), (ins uimm16:$amt),
+def ADJCALLSTACKDOWN : MipsPseudo<(outs), (ins uimm16:$amt),
                                       "!ADJCALLSTACKDOWN $amt",
                                       [(callseq_start imm:$amt)]>;
-def ADJCALLSTACKUP   : PseudoInstMips<(outs), (ins uimm16:$amt1, uimm16:$amt2),
+def ADJCALLSTACKUP   : MipsPseudo<(outs), (ins uimm16:$amt1, uimm16:$amt2),
                                       "!ADJCALLSTACKUP $amt1",
                                       [(callseq_end imm:$amt1, imm:$amt2)]>;
 }
@@ -358,10 +363,22 @@ def ADJCALLSTACKUP   : PseudoInstMips<(outs), (ins uimm16:$amt1, uimm16:$amt2),
 // directives. If the real instructions corresponding these directives
 // are used, we have the same behavior, but get also a bunch of warnings
 // from the assembler.
-def CPLOAD: PseudoInstMips<(outs), (ins CPURegs:$reg),
-                          ".set noreorder\n\t.cpload $reg\n\t.set reorder\n", []>;
-def CPRESTORE: PseudoInstMips<(outs), (ins uimm16:$loc),
-                              ".cprestore $loc\n", []>;
+def CPLOAD : MipsPseudo<(outs), (ins CPURegs:$reg),
+                            ".set noreorder\n\t.cpload $reg\n\t.set reorder\n", 
+                            []>;
+def CPRESTORE : MipsPseudo<(outs), (ins uimm16:$loc),
+                               ".cprestore $loc\n", []>;
+
+// The supported Mips ISAs dont have any instruction close to the SELECT_CC 
+// operation. The solution is to create a Mips pseudo SELECT_CC instruction
+// (MipsSelectCC), use LowerSELECT_CC to generate this instruction and finally 
+// replace it for real supported nodes into EmitInstrWithCustomInserter
+let usesCustomDAGSchedInserter = 1 in {
+  def Select_CC : MipsPseudo<(outs CPURegs:$dst), 
+    (ins CPURegs:$CmpRes, CPURegs:$T, CPURegs:$F), "# MipsSelect_CC", 
+    [(set CPURegs:$dst, (MipsSelectCC CPURegs:$CmpRes, 
+                                      CPURegs:$T, CPURegs:$F))]>;
+}
 
 //===----------------------------------------------------------------------===//
 // Instruction definition
@@ -502,6 +519,14 @@ def : Pat<(i32 immZExt16:$in),
 def : Pat<(i32 imm:$imm),
           (ORi (LUi (HI16 imm:$imm)), (LO16 imm:$imm))>;
 
+// Carry patterns
+def : Pat<(subc CPURegs:$lhs, CPURegs:$rhs),
+          (SUBu CPURegs:$lhs, CPURegs:$rhs)>;
+def : Pat<(addc CPURegs:$lhs, CPURegs:$rhs),
+          (ADDu CPURegs:$lhs, CPURegs:$rhs)>;
+def : Pat<(addc  CPURegs:$src, imm:$imm),
+          (ADDiu CPURegs:$src, imm:$imm)>;
+
 // Call
 def : Pat<(MipsJmpLink (i32 tglobaladdr:$dst)),
           (JAL tglobaladdr:$dst)>;
@@ -529,7 +554,7 @@ def : Pat<(i32 (extloadi1  addr:$src)), (LBu addr:$src)>;
 def : Pat<(i32 (extloadi8  addr:$src)), (LBu addr:$src)>;
 def : Pat<(i32 (extloadi16 addr:$src)), (LHu addr:$src)>;
 
-// some peepholes
+// peepholes
 def : Pat<(store (i32 0), addr:$dst), (SW ZERO, addr:$dst)>;
 
 ///