Add first draft for conditions, conditional branches, etc
authorAnton Korobeynikov <asl@math.spbu.ru>
Sun, 3 May 2009 13:12:06 +0000 (13:12 +0000)
committerAnton Korobeynikov <asl@math.spbu.ru>
Sun, 3 May 2009 13:12:06 +0000 (13:12 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@70743 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/MSP430/MSP430ISelLowering.cpp
lib/Target/MSP430/MSP430ISelLowering.h
lib/Target/MSP430/MSP430InstrInfo.h
lib/Target/MSP430/MSP430InstrInfo.td

index 11b1fb442e95a2982fef2afc3a5dc80ca2e4c28d..2354c8370cecb42515fec7793a5fb520ecf7cfa3 100644 (file)
@@ -70,6 +70,10 @@ MSP430TargetLowering::MSP430TargetLowering(MSP430TargetMachine &tm) :
   setOperationAction(ISD::SRA, MVT::i16, Custom);
   setOperationAction(ISD::RET, MVT::Other, Custom);
   setOperationAction(ISD::GlobalAddress, MVT::i16, Custom);
+  setOperationAction(ISD::BR_CC, MVT::Other, Expand);
+  setOperationAction(ISD::BRCOND, MVT::Other, Custom);
+  setOperationAction(ISD::SETCC, MVT::i8   , Custom);
+  setOperationAction(ISD::SETCC, MVT::i16  , Custom);
 }
 
 SDValue MSP430TargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) {
@@ -79,6 +83,8 @@ SDValue MSP430TargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) {
   case ISD::RET:              return LowerRET(Op, DAG);
   case ISD::CALL:             return LowerCALL(Op, DAG);
   case ISD::GlobalAddress:    return LowerGlobalAddress(Op, DAG);
+  case ISD::SETCC:            return LowerSETCC(Op, DAG);
+  case ISD::BRCOND:           return LowerBRCOND(Op, DAG);
   default:
     assert(0 && "unimplemented operand");
     return SDValue();
@@ -437,6 +443,80 @@ SDValue MSP430TargetLowering::LowerGlobalAddress(SDValue Op, SelectionDAG &DAG)
                      getPointerTy(), Result);
 }
 
+MVT MSP430TargetLowering::getSetCCResultType(MVT VT) const {
+  return MVT::i8;
+}
+
+SDValue MSP430TargetLowering::LowerSETCC(SDValue Op, SelectionDAG &DAG) {
+  assert(Op.getValueType() == MVT::i8 && "SetCC type must be 8-bit integer");
+  SDValue LHS = Op.getOperand(0);
+  SDValue RHS = Op.getOperand(1);
+  DebugLoc dl = Op.getDebugLoc();
+  ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(2))->get();
+
+  // FIXME: Handle bittests someday
+  assert(!LHS.getValueType().isFloatingPoint() && "We don't handle FP yet");
+
+  // FIXME: Handle jump negative someday
+  unsigned TargetCC = 0;
+  switch (CC) {
+  default: assert(0 && "Invalid integer condition!");
+  case ISD::SETEQ:
+    TargetCC = MSP430::COND_E;  // aka COND_Z
+    break;
+  case ISD::SETNE:
+    TargetCC = MSP430::COND_NE; // aka COND_NZ
+    break;
+  case ISD::SETULE:
+    std::swap(LHS, RHS);        // FALLTHROUGH
+  case ISD::SETUGE:
+    TargetCC = MSP430::COND_HS; // aka COND_C
+    break;
+  case ISD::SETUGT:
+    std::swap(LHS, RHS);        // FALLTHROUGH
+  case ISD::SETULT:
+    TargetCC = MSP430::COND_LO; // aka COND_NC
+    break;
+  case ISD::SETLE:
+    std::swap(LHS, RHS);        // FALLTHROUGH
+  case ISD::SETGE:
+    TargetCC = MSP430::COND_GE;
+    break;
+  case ISD::SETGT:
+    std::swap(LHS, RHS);        // FALLTHROUGH
+  case ISD::SETLT:
+    TargetCC = MSP430::COND_L;
+    break;
+  }
+
+  SDValue Cond = DAG.getNode(MSP430ISD::CMP, dl, MVT::i16, LHS, RHS);
+  return DAG.getNode(MSP430ISD::SETCC, dl, MVT::i8,
+                     DAG.getConstant(TargetCC, MVT::i8), Cond);
+}
+
+SDValue MSP430TargetLowering::LowerBRCOND(SDValue Op, SelectionDAG &DAG) {
+  SDValue Chain = Op.getOperand(0);
+  SDValue Cond  = Op.getOperand(1);
+  SDValue Dest  = Op.getOperand(2);
+  DebugLoc dl = Op.getDebugLoc();
+  SDValue CC;
+
+  // Lower condition if not lowered yet
+  if (Cond.getOpcode() == ISD::SETCC)
+    Cond = LowerSETCC(Cond, DAG);
+
+  // If condition flag is set by a MSP430ISD::CMP, then use it as the condition
+  // setting operand in place of the MSP430ISD::SETCC.
+  if (Cond.getOpcode() == MSP430ISD::SETCC) {
+    CC = Cond.getOperand(0);
+    Cond = Cond.getOperand(1);
+  } else
+    assert(0 && "Unimplemented condition!");
+
+  return DAG.getNode(MSP430ISD::BRCOND, dl, Op.getValueType(),
+                     Chain, Dest, CC, Cond);
+}
+
 const char *MSP430TargetLowering::getTargetNodeName(unsigned Opcode) const {
   switch (Opcode) {
   default: return NULL;
@@ -444,5 +524,8 @@ const char *MSP430TargetLowering::getTargetNodeName(unsigned Opcode) const {
   case MSP430ISD::RRA:                return "MSP430ISD::RRA";
   case MSP430ISD::CALL:               return "MSP430ISD::CALL";
   case MSP430ISD::Wrapper:            return "MSP430ISD::Wrapper";
+  case MSP430ISD::BRCOND:             return "MSP430ISD::BRCOND";
+  case MSP430ISD::CMP:                return "MSP430ISD::CMP";
+  case MSP430ISD::SETCC:              return "MSP430ISD::SETCC";
   }
 }
index a1f03ac96336bcd02c7dd77865b0f07a685ce586..c0ababd8b8af768b448d4e03ebac99ff21a6a970 100644 (file)
@@ -36,7 +36,20 @@ namespace llvm {
 
       /// Wrapper - A wrapper node for TargetConstantPool, TargetExternalSymbol,
       /// and TargetGlobalAddress.
-      Wrapper
+      Wrapper,
+
+      /// CMP - Compare instruction.
+      CMP,
+
+      /// SetCC. Operand 0 is condition code, and operand 1 is the flag
+      /// operand produced by a CMP instruction.
+      SETCC,
+
+      /// MSP430 conditional branches. Operand 0 is the chain operand, operand 1
+      /// is the block to branch if condition is true, operand 2 is the
+      /// condition code, and operand 3 is the flag operand produced by a CMP
+      /// instruction.
+      BRCOND
     };
   }
 
@@ -54,12 +67,16 @@ namespace llvm {
     /// DAG node.
     virtual const char *getTargetNodeName(unsigned Opcode) const;
 
+    virtual MVT getSetCCResultType(MVT VT) const;
+
     SDValue LowerFORMAL_ARGUMENTS(SDValue Op, SelectionDAG &DAG);
     SDValue LowerCALL(SDValue Op, SelectionDAG &DAG);
     SDValue LowerRET(SDValue Op, SelectionDAG &DAG);
     SDValue LowerCCCArguments(SDValue Op, SelectionDAG &DAG);
     SDValue LowerShifts(SDValue Op, SelectionDAG &DAG);
     SDValue LowerGlobalAddress(SDValue Op, SelectionDAG &DAG);
+    SDValue LowerSETCC(SDValue Op, SelectionDAG &DAG);
+    SDValue LowerBRCOND(SDValue Op, SelectionDAG &DAG);
 
     SDValue LowerCCCCallTo(SDValue Op, SelectionDAG &DAG,
                            unsigned CC);
index 02287d5c206eb75ba6fd8f065bf0651ad8f8a092..0803e2d77cd22e5efea048465952daacdd8fa557 100644 (file)
@@ -21,6 +21,21 @@ namespace llvm {
 
 class MSP430TargetMachine;
 
+namespace MSP430 {
+  // MSP430 specific condition code. These correspond to MSP430_*_COND in
+  // MSP430InstrInfo.td. They must be kept in synch.
+  enum CondCode {
+    COND_E  = 0,  // aka COND_Z
+    COND_NE = 1,  // aka COND_NZ
+    COND_HS = 2,  // aka COND_C
+    COND_LO = 3,  // aka COND_NC
+    COND_GE = 4,
+    COND_L  = 5,
+
+    COND_INVALID
+  };
+}
+
 class MSP430InstrInfo : public TargetInstrInfoImpl {
   const MSP430RegisterInfo RI;
   MSP430TargetMachine &TM;
index 8ab41ad46cd9655f816e70a9c72231a9acb06618..83a236e8532f3e73babd74de569d5c8b507cc323 100644 (file)
@@ -26,6 +26,11 @@ def SDT_MSP430Call         : SDTypeProfile<0, -1, [SDTCisVT<0, iPTR>]>;
 def SDT_MSP430CallSeqStart : SDCallSeqStart<[SDTCisVT<0, i16>]>;
 def SDT_MSP430CallSeqEnd   : SDCallSeqEnd<[SDTCisVT<0, i16>, SDTCisVT<1, i16>]>;
 def SDT_MSP430Wrapper      : SDTypeProfile<1, 1, [SDTCisSameAs<0, 1>, SDTCisPtrTy<0>]>;
+def SDT_MSP430SetCC        : SDTypeProfile<1, 2, [SDTCisVT<0, i8>,
+                                                  SDTCisVT<1, i8>, SDTCisVT<2, i16>]>;
+def SDT_MSP430Cmp          : SDTypeProfile<0, 2, [SDTCisSameAs<0, 1>]>;
+def SDT_MSP430BrCond       : SDTypeProfile<0, 3, [SDTCisVT<0, OtherVT>,
+                                                  SDTCisVT<1, i8>, SDTCisVT<2, i16>]>;
 
 //===----------------------------------------------------------------------===//
 // MSP430 Specific Node Definitions.
@@ -43,7 +48,10 @@ def MSP430callseq_start :
 def MSP430callseq_end :
                  SDNode<"ISD::CALLSEQ_END",   SDT_MSP430CallSeqEnd,
                         [SDNPHasChain, SDNPOptInFlag, SDNPOutFlag]>;
-def MSP430Wrapper : SDNode<"MSP430ISD::Wrapper",     SDT_MSP430Wrapper>;
+def MSP430Wrapper : SDNode<"MSP430ISD::Wrapper", SDT_MSP430Wrapper>;
+def MSP430setcc   : SDNode<"MSP430ISD::SETCC", SDT_MSP430SetCC>;
+def MSP430cmp     : SDNode<"MSP430ISD::CMP", SDT_MSP430Cmp>;
+def MSP430brcond  : SDNode<"MSP430ISD::BRCOND", SDT_MSP430BrCond, [SDNPHasChain]>;
 
 //===----------------------------------------------------------------------===//
 // MSP430 Operand Definitions.
@@ -60,6 +68,9 @@ def memdst : Operand<i16> {
   let MIOperandInfo = (ops GR16, i16imm);
 }
 
+// Branch targets have OtherVT type.
+def brtarget : Operand<OtherVT>;
+
 //===----------------------------------------------------------------------===//
 // MSP430 Complex Pattern Definitions.
 //===----------------------------------------------------------------------===//
@@ -71,6 +82,15 @@ def addr : ComplexPattern<iPTR, 2, "SelectAddr", [], []>;
 def zextloadi16i8 : PatFrag<(ops node:$ptr), (i16 (zextloadi8 node:$ptr))>;
 def  extloadi16i8 : PatFrag<(ops node:$ptr), (i16 ( extloadi8 node:$ptr))>;
 
+// MSP430 specific condition code. These correspond to CondCode in
+// MSP430InstrInfo.h. They must be kept in synch.
+def MSP430_COND_E   : PatLeaf<(i8 0)>;  // aka COND_Z
+def MSP430_COND_NE  : PatLeaf<(i8 1)>;  // aka COND_NZ
+def MSP430_COND_HS  : PatLeaf<(i8 2)>;  // aka COND_C
+def MSP430_COND_LO  : PatLeaf<(i8 3)>;  // aka COND_NC
+def MSP430_COND_GE  : PatLeaf<(i8 4)>;
+def MSP430_COND_L   : PatLeaf<(i8 5)>;
+
 //===----------------------------------------------------------------------===//
 // Instruction list..
 
@@ -92,11 +112,31 @@ def ADJCALLSTACKUP   : Pseudo<(outs), (ins i16imm:$amt1, i16imm:$amt2),
 let neverHasSideEffects = 1 in
 def NOP : Pseudo<(outs), (ins), "nop", []>;
 
+//===----------------------------------------------------------------------===//
+//  Control Flow Instructions...
+//
+
 // FIXME: Provide proper encoding!
 let isReturn = 1, isTerminator = 1 in {
   def RET : Pseudo<(outs), (ins), "ret", [(MSP430retflag)]>;
 }
 
+// Conditional branches
+let isBranch = 1, isTerminator = 1, Uses = [SRW] in {
+def JE  : Pseudo<(outs), (ins brtarget:$dst), "je\t$dst",
+              [(MSP430brcond bb:$dst, MSP430_COND_E, SRW)]>;
+def JNE : Pseudo<(outs), (ins brtarget:$dst), "jne\t$dst",
+              [(MSP430brcond bb:$dst, MSP430_COND_NE, SRW)]>;
+def JHS : Pseudo<(outs), (ins brtarget:$dst), "jhs\t$dst",
+              [(MSP430brcond bb:$dst, MSP430_COND_HS, SRW)]>;
+def JLO : Pseudo<(outs), (ins brtarget:$dst), "jlo\t$dst",
+              [(MSP430brcond bb:$dst, MSP430_COND_LO, SRW)]>;
+def JGE : Pseudo<(outs), (ins brtarget:$dst), "jge\t$dst",
+              [(MSP430brcond bb:$dst, MSP430_COND_GE, SRW)]>;
+def JL  : Pseudo<(outs), (ins brtarget:$dst), "jl\t$dst",
+              [(MSP430brcond bb:$dst, MSP430_COND_L, SRW)]>;
+} // Uses = [SRW]
+
 //===----------------------------------------------------------------------===//
 //  Call Instructions...
 //
@@ -613,6 +653,51 @@ def OR16mm : Pseudo<(outs), (ins memdst:$dst, memsrc:$src),
 
 } // isTwoAddress = 1
 
+// Integer comparisons
+let Defs = [SRW] in {
+def CMP8rr  : Pseudo<(outs), (ins GR8:$src1, GR8:$src2),
+                     "cmp.b\t{$src2, $src1|$src1, $src2}",
+                     [(MSP430cmp GR8:$src1, GR8:$src2), (implicit SRW)]>;
+def CMP16rr : Pseudo<(outs), (ins GR16:$src1, GR16:$src2),
+                     "cmp.w\t{$src2, $src1|$src1, $src2}",
+                     [(MSP430cmp GR16:$src1, GR16:$src2), (implicit SRW)]>;
+
+def CMP8ri  : Pseudo<(outs), (ins GR8:$src1, i8imm:$src2),
+                     "cmp.b\t{$src2, $src1|$src1, $src2}",
+                     [(MSP430cmp GR8:$src1, imm:$src2), (implicit SRW)]>;
+def CMP16ri : Pseudo<(outs), (ins GR16:$src1, i16imm:$src2),
+                     "cmp.w\t{$src2, $src1|$src1, $src2}",
+                     [(MSP430cmp GR16:$src1, imm:$src2), (implicit SRW)]>;
+
+def CMP8rm  : Pseudo<(outs), (ins GR8:$src1, memsrc:$src2),
+                     "cmp.b\t{$src2, $src1|$src1, $src2}",
+                     [(MSP430cmp GR8:$src1, (load addr:$src2)), (implicit SRW)]>;
+def CMP16rm : Pseudo<(outs), (ins GR16:$src1, memsrc:$src2),
+                     "cmp.w\t{$src2, $src1|$src1, $src2}",
+                     [(MSP430cmp GR16:$src1, (load addr:$src2)), (implicit SRW)]>;
+
+def CMP8mr  : Pseudo<(outs), (ins memsrc:$src1, GR8:$src2),
+                "cmp.b\t{$src2, $src1|$src1, $src2}",
+                [(MSP430cmp (load addr:$src1), GR8:$src2), (implicit SRW)]>;
+def CMP16mr : Pseudo<(outs), (ins memsrc:$src1, GR16:$src2),
+                "cmp.w\t{$src2, $src1|$src1, $src2}",
+                [(MSP430cmp (load addr:$src1), GR16:$src2), (implicit SRW)]>;
+
+def CMP8mi  : Pseudo<(outs), (ins memsrc:$src1, i8imm:$src2),
+                "cmp.b\t{$src2, $src1|$src1, $src2}",
+                [(MSP430cmp (load addr:$src1), (i8 imm:$src2)), (implicit SRW)]>;
+def CMP16mi : Pseudo<(outs), (ins memsrc:$src1, i16imm:$src2),
+                "cmp.w\t{$src2, $src1|$src1, $src2}",
+                [(MSP430cmp (load addr:$src1), (i16 imm:$src2)), (implicit SRW)]>;
+
+def CMP8mm  : Pseudo<(outs), (ins memsrc:$src1, memsrc:$src2),
+                "cmp.b\t{$src2, $src1|$src1, $src2}",
+                [(MSP430cmp (load addr:$src1), (i8 (load addr:$src2))), (implicit SRW)]>;
+def CMP16mm : Pseudo<(outs), (ins memsrc:$src1, memsrc:$src2),
+                "cmp.w\t{$src2, $src1|$src1, $src2}",
+                [(MSP430cmp (load addr:$src1), (i16 (load addr:$src2))), (implicit SRW)]>;
+} // Defs = [SRW]
+
 //===----------------------------------------------------------------------===//
 // Non-Instruction Patterns