Compile:
authorChris Lattner <sabre@nondot.org>
Mon, 30 Jan 2006 06:14:02 +0000 (06:14 +0000)
committerChris Lattner <sabre@nondot.org>
Mon, 30 Jan 2006 06:14:02 +0000 (06:14 +0000)
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

lib/Target/Sparc/SparcISelDAGToDAG.cpp
lib/Target/Sparc/SparcInstrInfo.td
lib/Target/SparcV8/SparcV8ISelDAGToDAG.cpp
lib/Target/SparcV8/SparcV8InstrInfo.td

index 9718801a8a0001a679b46bad625e8fd5e56fb8df..d9423e224d5c790e7e1af7849b0991a465403dca 100644 (file)
@@ -33,21 +33,20 @@ using namespace llvm;
 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 @@ SparcV8TargetLowering::SparcV8TargetLowering(TargetMachine &TM)
   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 @@ const char *SparcV8TargetLowering::getTargetNodeName(unsigned Opcode) const {
   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";
   }
index bf8d6f4ec09da8d272c91e568b3f1628f8de1c9f..abdbbcc6c08990932d0406fe64ec5331ba27059a 100644 (file)
@@ -764,6 +764,14 @@ let Predicates = [HasV9] in {
                    [(set DFPRegs:$dst, (fabs DFPRegs:$src))]>;
 }
 
+// POPCrr - This does a ctpop of a 64-bit register.  As such, we have to clear
+// the top 32-bits before using it.  To do this clearing, we use a SLLri X,0.
+def POPCrr : F3_1<2, 0b101110, 
+                  (ops IntRegs:$dst, IntRegs:$src),
+                  "popc $src, $dst", []>, Requires<[HasV9]>;
+def : Pat<(ctpop IntRegs:$src),
+          (POPCrr (SLLri IntRegs:$src, 0))>;
+
 //===----------------------------------------------------------------------===//
 // Non-Instruction Patterns
 //===----------------------------------------------------------------------===//
index 9718801a8a0001a679b46bad625e8fd5e56fb8df..d9423e224d5c790e7e1af7849b0991a465403dca 100644 (file)
@@ -33,21 +33,20 @@ using namespace llvm;
 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 @@ SparcV8TargetLowering::SparcV8TargetLowering(TargetMachine &TM)
   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 @@ const char *SparcV8TargetLowering::getTargetNodeName(unsigned Opcode) const {
   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";
   }
index bf8d6f4ec09da8d272c91e568b3f1628f8de1c9f..abdbbcc6c08990932d0406fe64ec5331ba27059a 100644 (file)
@@ -764,6 +764,14 @@ let Predicates = [HasV9] in {
                    [(set DFPRegs:$dst, (fabs DFPRegs:$src))]>;
 }
 
+// POPCrr - This does a ctpop of a 64-bit register.  As such, we have to clear
+// the top 32-bits before using it.  To do this clearing, we use a SLLri X,0.
+def POPCrr : F3_1<2, 0b101110, 
+                  (ops IntRegs:$dst, IntRegs:$src),
+                  "popc $src, $dst", []>, Requires<[HasV9]>;
+def : Pat<(ctpop IntRegs:$src),
+          (POPCrr (SLLri IntRegs:$src, 0))>;
+
 //===----------------------------------------------------------------------===//
 // Non-Instruction Patterns
 //===----------------------------------------------------------------------===//