Compile:

uint %test(uint %X) {
        %Y = call uint %llvm.ctpop.i32(uint %X)
        ret uint %Y
}

to:

test:
        save -96, %o6, %o6
        sll %i0, 0, %l0
        popc %l0, %i0
        restore %g0, %g0, %g0
        retl
        nop

instead of to 40 logical ops.  Note the shift-by-zero that clears the top
part of the 64-bit V9 register.

Testcase here: CodeGen/SparcV8/ctpop.ll


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@25814 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Target/Sparc/SparcISelDAGToDAG.cpp b/lib/Target/Sparc/SparcISelDAGToDAG.cpp
index 9718801..d9423e2 100644
--- a/lib/Target/Sparc/SparcISelDAGToDAG.cpp
+++ b/lib/Target/Sparc/SparcISelDAGToDAG.cpp
@@ -33,21 +33,20 @@
 namespace V8ISD {
   enum {
     FIRST_NUMBER = ISD::BUILTIN_OP_END+V8::INSTRUCTION_LIST_END,
-    CMPICC,   // Compare two GPR operands, set icc.
-    CMPFCC,   // Compare two FP operands, set fcc.
-    BRICC,    // Branch to dest on icc condition
-    BRFCC,    // Branch to dest on fcc condition
+    CMPICC,      // Compare two GPR operands, set icc.
+    CMPFCC,      // Compare two FP operands, set fcc.
+    BRICC,       // Branch to dest on icc condition
+    BRFCC,       // Branch to dest on fcc condition
+    SELECT_ICC,  // Select between two values using the current ICC flags.
+    SELECT_FCC,  // Select between two values using the current FCC flags.
     
-    Hi, Lo,   // Hi/Lo operations, typically on a global address.
+    Hi, Lo,      // Hi/Lo operations, typically on a global address.
     
-    FTOI,     // FP to Int within a FP register.
-    ITOF,     // Int to FP within a FP register.
-    
-    SELECT_ICC, // Select between two values using the current ICC flags.
-    SELECT_FCC, // Select between two values using the current FCC flags.
-    
-    CALL,       // A V8 call instruction.
-    RET_FLAG,   // Return with a flag operand.
+    FTOI,        // FP to Int within a FP register.
+    ITOF,        // Int to FP within a FP register.
+
+    CALL,        // A V8 call instruction.
+    RET_FLAG,    // Return with a flag operand.
   };
 }
 
@@ -173,10 +172,14 @@
   setOperationAction(ISD::VAEND             , MVT::Other, Expand);
   setOperationAction(ISD::STACKSAVE         , MVT::Other, Expand); 
   setOperationAction(ISD::STACKRESTORE      , MVT::Other, Expand);
-  setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32, Expand);
+  setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32  , Expand);
 
   setStackPointerRegisterToSaveRestore(V8::O6);
 
+  if (TM.getSubtarget<SparcV8Subtarget>().isV9()) {
+    setOperationAction(ISD::CTPOP, MVT::i32, Legal);
+  }
+  
   computeRegisterProperties();
 }
 
@@ -187,12 +190,12 @@
   case V8ISD::CMPFCC:     return "V8ISD::CMPFCC";
   case V8ISD::BRICC:      return "V8ISD::BRICC";
   case V8ISD::BRFCC:      return "V8ISD::BRFCC";
+  case V8ISD::SELECT_ICC: return "V8ISD::SELECT_ICC";
+  case V8ISD::SELECT_FCC: return "V8ISD::SELECT_FCC";
   case V8ISD::Hi:         return "V8ISD::Hi";
   case V8ISD::Lo:         return "V8ISD::Lo";
   case V8ISD::FTOI:       return "V8ISD::FTOI";
   case V8ISD::ITOF:       return "V8ISD::ITOF";
-  case V8ISD::SELECT_ICC: return "V8ISD::SELECT_ICC";
-  case V8ISD::SELECT_FCC: return "V8ISD::SELECT_FCC";
   case V8ISD::CALL:       return "V8ISD::CALL";
   case V8ISD::RET_FLAG:   return "V8ISD::RET_FLAG";
   }