Handle logical shift right (at least I hope so :) )
authorAnton Korobeynikov <asl@math.spbu.ru>
Sun, 3 May 2009 13:16:17 +0000 (13:16 +0000)
committerAnton Korobeynikov <asl@math.spbu.ru>
Sun, 3 May 2009 13:16:17 +0000 (13:16 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@70758 91177308-0d34-0410-b5e6-96231b3b80d8

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

index 4ad74db725b870230bda4a5dc0b5c610ff00687f..9301bff7e3f258e3c15c5239e3e221f735e62a73 100644 (file)
@@ -69,6 +69,7 @@ MSP430TargetLowering::MSP430TargetLowering(MSP430TargetMachine &tm) :
 
   setOperationAction(ISD::SRA,              MVT::i16,   Custom);
   setOperationAction(ISD::SHL,              MVT::i16,   Custom);
+  setOperationAction(ISD::SRL,              MVT::i16,   Custom);
   setOperationAction(ISD::RET,              MVT::Other, Custom);
   setOperationAction(ISD::GlobalAddress,    MVT::i16,   Custom);
   setOperationAction(ISD::ExternalSymbol,   MVT::i16,   Custom);
@@ -94,6 +95,7 @@ SDValue MSP430TargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) {
   switch (Op.getOpcode()) {
   case ISD::FORMAL_ARGUMENTS: return LowerFORMAL_ARGUMENTS(Op, DAG);
   case ISD::SHL: // FALLTHROUGH
+  case ISD::SRL:
   case ISD::SRA:              return LowerShifts(Op, DAG);
   case ISD::RET:              return LowerRET(Op, DAG);
   case ISD::CALL:             return LowerCALL(Op, DAG);
@@ -430,8 +432,6 @@ MSP430TargetLowering::LowerCallResult(SDValue Chain, SDValue InFlag,
 SDValue MSP430TargetLowering::LowerShifts(SDValue Op,
                                           SelectionDAG &DAG) {
   unsigned Opc = Op.getOpcode();
-  assert((Opc == ISD::SRA || ISD::SHL) &&
-         "Only SRA and SHL are currently supported.");
   SDNode* N = Op.getNode();
   MVT VT = Op.getValueType();
   DebugLoc dl = N->getDebugLoc();
@@ -446,6 +446,15 @@ SDValue MSP430TargetLowering::LowerShifts(SDValue Op,
   // FIXME: for some shift amounts this might be done better!
   // E.g.: foo >> (8 + N) => sxt(swpb(foo)) >> N
   SDValue Victim = N->getOperand(0);
+
+  if (Opc == ISD::SRL && ShiftAmount) {
+    // Emit a special goodness here:
+    // srl A, 1 => clrc; rrc A
+    SDValue clrc = DAG.getNode(MSP430ISD::CLRC, dl, MVT::Other);
+    Victim = DAG.getNode(MSP430ISD::RRC, dl, VT, Victim, clrc);
+    ShiftAmount -= 1;
+  }
+
   while (ShiftAmount--)
     Victim = DAG.getNode((Opc == ISD::SRA ? MSP430ISD::RRA : MSP430ISD::RLA),
                          dl, VT, Victim);
@@ -586,13 +595,15 @@ const char *MSP430TargetLowering::getTargetNodeName(unsigned Opcode) const {
   default: return NULL;
   case MSP430ISD::RET_FLAG:           return "MSP430ISD::RET_FLAG";
   case MSP430ISD::RRA:                return "MSP430ISD::RRA";
-  case MSP430ISD::RLA:                return "MSP430ISD::RRA";
+  case MSP430ISD::RLA:                return "MSP430ISD::RLA";
+  case MSP430ISD::RRC:                return "MSP430ISD::RRC";
   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";
   case MSP430ISD::SELECT:             return "MSP430ISD::SELECT";
+  case MSP430ISD::CLRC:               return "MSP430ISD::CLRC";
   }
 }
 
index 064cb67c247480b5ca79bb364d7ee61e9af0f268..2903903c26387e61cf8ef0b07439f9b2a7b86c85 100644 (file)
@@ -30,6 +30,9 @@ namespace llvm {
       /// Y = R{R,L}A X, rotate right (left) arithmetically
       RRA, RLA,
 
+      /// Y = RRC X, rotate right via carry
+      RRC,
+
       /// CALL/TAILCALL - These operations represent an abstract call
       /// instruction, which includes a bunch of information.
       CALL,
@@ -53,7 +56,10 @@ namespace llvm {
 
       /// SELECT. Operand 0 and operand 1 are selection variable, operand 3 is
       /// condition code and operand 4 is flag operand.
-      SELECT
+      SELECT,
+
+      /// CLRC - Clear carry bit
+      CLRC
     };
   }
 
index 2c838e31a21dfd9eb3bd8740a552b060092ec3ac..2a7e927e99fe3a051292a4b148d9e228aaf7ec0b 100644 (file)
@@ -33,6 +33,7 @@ def SDT_MSP430BrCond       : SDTypeProfile<0, 3, [SDTCisVT<0, OtherVT>,
                                                   SDTCisVT<1, i8>, SDTCisVT<2, i16>]>;
 def SDT_MSP430Select       : SDTypeProfile<1, 4, [SDTCisSameAs<0, 1>, SDTCisSameAs<1, 2>, 
                                                   SDTCisVT<3, i8>, SDTCisVT<4, i16>]>;
+def SDT_MSP430Clrc         : SDTypeProfile<0, 0, []>;
 
 //===----------------------------------------------------------------------===//
 // MSP430 Specific Node Definitions.
@@ -42,6 +43,7 @@ def MSP430retflag : SDNode<"MSP430ISD::RET_FLAG", SDTNone,
 
 def MSP430rra     : SDNode<"MSP430ISD::RRA", SDTIntUnaryOp, []>;
 def MSP430rla     : SDNode<"MSP430ISD::RLA", SDTIntUnaryOp, []>;
+def MSP430rrc     : SDNode<"MSP430ISD::RRC", SDTIntUnaryOp, [SDNPInFlag]>;
 
 def MSP430call    : SDNode<"MSP430ISD::CALL", SDT_MSP430Call,
                      [SDNPHasChain, SDNPOutFlag, SDNPOptInFlag]>;
@@ -56,6 +58,7 @@ def MSP430setcc   : SDNode<"MSP430ISD::SETCC", SDT_MSP430SetCC>;
 def MSP430cmp     : SDNode<"MSP430ISD::CMP", SDT_MSP430Cmp>;
 def MSP430brcond  : SDNode<"MSP430ISD::BRCOND", SDT_MSP430BrCond, [SDNPHasChain]>;
 def MSP430select  : SDNode<"MSP430ISD::SELECT", SDT_MSP430Select>;
+def MSP430clrc    : SDNode<"MSP430ISD::CLRC", SDT_MSP430Clrc, [SDNPOutFlag]>;
 
 //===----------------------------------------------------------------------===//
 // MSP430 Operand Definitions.
@@ -597,6 +600,11 @@ def SHL16r1 : Pseudo<(outs GR16:$dst), (ins GR16:$src),
                      [(set GR16:$dst, (MSP430rla GR16:$src)),
                       (implicit SRW)]>;
 
+def SAR16r1c : Pseudo<(outs GR16:$dst), (ins GR16:$src),
+                      "rrc.w\t$dst",
+                      [(set GR16:$dst, (MSP430rrc GR16:$src)),
+                       (implicit SRW)]>;
+
 def SEXT16r : Pseudo<(outs GR16:$dst), (ins GR16:$src),
                      "sxt\t$dst",
                      [(set GR16:$dst, (sext_inreg GR16:$src, i8)),
@@ -662,6 +670,10 @@ def OR16mm : Pseudo<(outs), (ins memdst:$dst, memsrc:$src),
 
 } // isTwoAddress = 1
 
+let Defs = [SRW] in
+def CLRC   : Pseudo<(outs), (ins),
+                     "clrc", [(MSP430clrc)]>;
+
 // Integer comparisons
 let Defs = [SRW] in {
 def CMP8rr  : Pseudo<(outs), (ins GR8:$src1, GR8:$src2),