[llvm-commits] [llvm] r91175 - in /llvm/trunk: lib/Target/MSP430/MSP430ISelLowering.cpp lib/Target/MSP430/MSP430ISelLowering.h test/CodeGen/MSP430/setcc.ll

Anton Korobeynikov asl at math.spbu.ru
Fri Dec 11 15:01:30 PST 2009


Author: asl
Date: Fri Dec 11 17:01:29 2009
New Revision: 91175

URL: http://llvm.org/viewvc/llvm-project?rev=91175&view=rev
Log:
Lower setcc branchless, if this is profitable.
Based on the patch by Brian Lucas!

Added:
    llvm/trunk/test/CodeGen/MSP430/setcc.ll
Modified:
    llvm/trunk/lib/Target/MSP430/MSP430ISelLowering.cpp
    llvm/trunk/lib/Target/MSP430/MSP430ISelLowering.h

Modified: llvm/trunk/lib/Target/MSP430/MSP430ISelLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/MSP430/MSP430ISelLowering.cpp?rev=91175&r1=91174&r2=91175&view=diff

==============================================================================
--- llvm/trunk/lib/Target/MSP430/MSP430ISelLowering.cpp (original)
+++ llvm/trunk/lib/Target/MSP430/MSP430ISelLowering.cpp Fri Dec 11 17:01:29 2009
@@ -115,8 +115,8 @@
   setOperationAction(ISD::BR_CC,            MVT::i8,    Custom);
   setOperationAction(ISD::BR_CC,            MVT::i16,   Custom);
   setOperationAction(ISD::BRCOND,           MVT::Other, Expand);
-  setOperationAction(ISD::SETCC,            MVT::i8,    Expand);
-  setOperationAction(ISD::SETCC,            MVT::i16,   Expand);
+  setOperationAction(ISD::SETCC,            MVT::i8,    Custom);
+  setOperationAction(ISD::SETCC,            MVT::i16,   Custom);
   setOperationAction(ISD::SELECT,           MVT::i8,    Expand);
   setOperationAction(ISD::SELECT,           MVT::i16,   Expand);
   setOperationAction(ISD::SELECT_CC,        MVT::i8,    Custom);
@@ -183,6 +183,7 @@
   case ISD::SRA:              return LowerShifts(Op, DAG);
   case ISD::GlobalAddress:    return LowerGlobalAddress(Op, DAG);
   case ISD::ExternalSymbol:   return LowerExternalSymbol(Op, DAG);
+  case ISD::SETCC:            return LowerSETCC(Op, DAG);
   case ISD::BR_CC:            return LowerBR_CC(Op, DAG);
   case ISD::SELECT_CC:        return LowerSELECT_CC(Op, DAG);
   case ISD::SIGN_EXTEND:      return LowerSIGN_EXTEND(Op, DAG);
@@ -701,6 +702,88 @@
                      Chain, Dest, TargetCC, Flag);
 }
 
+
+SDValue MSP430TargetLowering::LowerSETCC(SDValue Op, SelectionDAG &DAG) {
+  SDValue LHS   = Op.getOperand(0);
+  SDValue RHS   = Op.getOperand(1);
+  DebugLoc dl   = Op.getDebugLoc();
+
+  // If we are doing an AND and testing against zero, then the CMP
+  // will not be generated.  The AND (or BIT) will generate the condition codes,
+  // but they are different from CMP.
+  bool andCC = false;
+  if (ConstantSDNode *RHSC = dyn_cast<ConstantSDNode>(RHS)) {
+    if (RHSC->isNullValue() && LHS.hasOneUse() &&
+        (LHS.getOpcode() == ISD::AND ||
+         (LHS.getOpcode() == ISD::TRUNCATE &&
+          LHS.getOperand(0).getOpcode() == ISD::AND))) {
+      andCC = true;
+    }
+  }
+  ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(2))->get();
+  SDValue TargetCC;
+  SDValue Flag = EmitCMP(LHS, RHS, TargetCC, CC, dl, DAG);
+
+  // Get the condition codes directly from the status register, if its easy.
+  // Otherwise a branch will be generated.  Note that the AND and BIT
+  // instructions generate different flags than CMP, the carry bit can be used
+  // for NE/EQ.
+  bool Invert = false;
+  bool Shift = false;
+  bool Convert = true;
+  switch (cast<ConstantSDNode>(TargetCC)->getZExtValue()) {
+   default:
+    Convert = false;
+    break;
+   case MSP430CC::COND_HS:
+     // Res = SRW & 1, no processing is required
+     break;
+    case MSP430CC::COND_LO:
+     // Res = ~(SRW & 1)
+     Invert = true;
+     break;
+    case MSP430CC::COND_NE:
+     if (andCC) {
+       // C = ~Z, thus Res = SRW & 1, no processing is required
+     } else {
+       // Res = (SRW >> 1) & 1
+       Shift = true;
+     }
+     break;
+    case MSP430CC::COND_E:
+     if (andCC) {
+       // C = ~Z, thus Res = ~(SRW & 1)
+     } else {
+       // Res = ~((SRW >> 1) & 1)
+       Shift = true;
+     }
+     Invert = true;
+     break;
+  }
+  EVT VT = Op.getValueType();
+  SDValue One  = DAG.getConstant(1, VT);
+  if (Convert) {
+    SDValue SR = DAG.getCopyFromReg(DAG.getEntryNode(), dl, MSP430::SRW,
+                                     MVT::i16, Flag);
+    if (Shift)
+      // FIXME: somewhere this is turned into a SRL, lower it MSP specific?
+      SR = DAG.getNode(ISD::SRA, dl, MVT::i16, SR, One);
+    SR = DAG.getNode(ISD::AND, dl, MVT::i16, SR, One);
+    if (Invert)
+      SR = DAG.getNode(ISD::XOR, dl, MVT::i16, SR, One);
+    return SR;
+  } else {
+    SDValue Zero = DAG.getConstant(0, VT);
+    SDVTList VTs = DAG.getVTList(Op.getValueType(), MVT::Flag);
+    SmallVector<SDValue, 4> Ops;
+    Ops.push_back(One);
+    Ops.push_back(Zero);
+    Ops.push_back(TargetCC);
+    Ops.push_back(Flag);
+    return DAG.getNode(MSP430ISD::SELECT_CC, dl, VTs, &Ops[0], Ops.size());
+  }
+}
+
 SDValue MSP430TargetLowering::LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) {
   SDValue LHS    = Op.getOperand(0);
   SDValue RHS    = Op.getOperand(1);

Modified: llvm/trunk/lib/Target/MSP430/MSP430ISelLowering.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/MSP430/MSP430ISelLowering.h?rev=91175&r1=91174&r2=91175&view=diff

==============================================================================
--- llvm/trunk/lib/Target/MSP430/MSP430ISelLowering.h (original)
+++ llvm/trunk/lib/Target/MSP430/MSP430ISelLowering.h Fri Dec 11 17:01:29 2009
@@ -84,6 +84,7 @@
     SDValue LowerGlobalAddress(SDValue Op, SelectionDAG &DAG);
     SDValue LowerExternalSymbol(SDValue Op, SelectionDAG &DAG);
     SDValue LowerBR_CC(SDValue Op, SelectionDAG &DAG);
+    SDValue LowerSETCC(SDValue Op, SelectionDAG &DAG);
     SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG);
     SDValue LowerSIGN_EXTEND(SDValue Op, SelectionDAG &DAG);
     SDValue LowerRETURNADDR(SDValue Op, SelectionDAG &DAG);

Added: llvm/trunk/test/CodeGen/MSP430/setcc.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/MSP430/setcc.ll?rev=91175&view=auto

==============================================================================
--- llvm/trunk/test/CodeGen/MSP430/setcc.ll (added)
+++ llvm/trunk/test/CodeGen/MSP430/setcc.ll Fri Dec 11 17:01:29 2009
@@ -0,0 +1,116 @@
+; RUN: llc -march=msp430 < %s | FileCheck %s
+target datalayout = "e-p:16:16:16-i1:8:8-i8:8:8-i16:16:16-i32:16:32"
+target triple = "msp430-generic-generic"
+
+define i16 @sccweqand(i16 %a, i16 %b) nounwind {
+	%t1 = and i16 %a, %b
+	%t2 = icmp eq i16 %t1, 0
+	%t3 = zext i1 %t2 to i16
+	ret i16 %t3
+}
+; CHECK: sccweqand:
+; CHECK:	bit.w	r14, r15
+; CHECK-NEXT:	mov.w	r2, r15
+; CHECK-NEXT:	and.w	#1, r15
+; CHECK-NEXT:	xor.w	#1, r15
+
+define i16 @sccwneand(i16 %a, i16 %b) nounwind {
+	%t1 = and i16 %a, %b
+	%t2 = icmp ne i16 %t1, 0
+	%t3 = zext i1 %t2 to i16
+	ret i16 %t3
+}
+; CHECK: sccwneand:
+; CHECK: 	bit.w	r14, r15
+; CHECK-NEXT:	mov.w	r2, r15
+; CHECK-NEXT:	and.w	#1, r15
+
+define i16 @sccwne(i16 %a, i16 %b) nounwind {
+	%t1 = icmp ne i16 %a, %b
+	%t2 = zext i1 %t1 to i16
+	ret i16 %t2
+}
+; CHECK:sccwne:
+; CHECK:	cmp.w	r15, r14
+; CHECK-NEXT:	mov.w	r2, r15
+; CHECK-NEXT:	rra.w	r15
+; CHECK-NEXT:	and.w	#1, r15
+
+define i16 @sccweq(i16 %a, i16 %b) nounwind {
+	%t1 = icmp eq i16 %a, %b
+	%t2 = zext i1 %t1 to i16
+	ret i16 %t2
+}
+; CHECK:sccweq:
+; CHECK:	cmp.w	r15, r14
+; CHECK-NEXT:	mov.w	r2, r15
+; CHECK-NEXT:	rra.w	r15
+; CHECK-NEXT:	and.w	#1, r15
+; CHECK-NEXT:	xor.w	#1, r15
+
+define i16 @sccwugt(i16 %a, i16 %b) nounwind {
+	%t1 = icmp ugt i16 %a, %b
+	%t2 = zext i1 %t1 to i16
+	ret i16 %t2
+}
+; CHECK:sccwugt:
+; CHECK:	cmp.w	r14, r15
+; CHECK-NEXT:	mov.w	r2, r15
+; CHECK-NEXT:	and.w	#1, r15
+; CHECK-NEXT:	xor.w	#1, r15
+
+define i16 @sccwuge(i16 %a, i16 %b) nounwind {
+	%t1 = icmp uge i16 %a, %b
+	%t2 = zext i1 %t1 to i16
+	ret i16 %t2
+}
+; CHECK:sccwuge:
+; CHECK:	cmp.w	r15, r14
+; CHECK-NEXT:	mov.w	r2, r15
+; CHECK-NEXT:	and.w	#1, r15
+
+define i16 @sccwult(i16 %a, i16 %b) nounwind {
+	%t1 = icmp ult i16 %a, %b
+	%t2 = zext i1 %t1 to i16
+	ret i16 %t2
+}
+; CHECK:sccwult:
+; CHECK:	cmp.w	r15, r14
+; CHECK-NEXT:	mov.w	r2, r15
+; CHECK-NEXT:	and.w	#1, r15
+; CHECK-NEXT:	xor.w	#1, r15
+
+define i16 @sccwule(i16 %a, i16 %b) nounwind {
+	%t1 = icmp ule i16 %a, %b
+	%t2 = zext i1 %t1 to i16
+	ret i16 %t2
+}
+; CHECK:sccwule:
+; CHECK:	cmp.w	r14, r15
+; CHECK-NEXT:	mov.w	r2, r15
+; CHECK-NEXT:	and.w	#1, r15
+
+define i16 @sccwsgt(i16 %a, i16 %b) nounwind {
+	%t1 = icmp sgt i16 %a, %b
+	%t2 = zext i1 %t1 to i16
+	ret i16 %t2
+}
+
+define i16 @sccwsge(i16 %a, i16 %b) nounwind {
+	%t1 = icmp sge i16 %a, %b
+	%t2 = zext i1 %t1 to i16
+	ret i16 %t2
+}
+
+define i16 @sccwslt(i16 %a, i16 %b) nounwind {
+	%t1 = icmp slt i16 %a, %b
+	%t2 = zext i1 %t1 to i16
+	ret i16 %t2
+}
+
+define i16 @sccwsle(i16 %a, i16 %b) nounwind {
+	%t1 = icmp sle i16 %a, %b
+	%t2 = zext i1 %t1 to i16
+	ret i16 %t2
+}
+





More information about the llvm-commits mailing list