[llvm-commits] CVS: llvm/lib/Target/PowerPC/PPCISelLowering.cpp

Chris Lattner lattner at cs.uiuc.edu
Sun Apr 16 23:58:53 PDT 2006



Changes in directory llvm/lib/Target/PowerPC:

PPCISelLowering.cpp updated: 1.157 -> 1.158
---
Log message:

Make some code more general, adding support for constant formation of several
new patterns.


---
Diffs of the changes:  (+78 -22)

 PPCISelLowering.cpp |  100 ++++++++++++++++++++++++++++++++++++++++------------
 1 files changed, 78 insertions(+), 22 deletions(-)


Index: llvm/lib/Target/PowerPC/PPCISelLowering.cpp
diff -u llvm/lib/Target/PowerPC/PPCISelLowering.cpp:1.157 llvm/lib/Target/PowerPC/PPCISelLowering.cpp:1.158
--- llvm/lib/Target/PowerPC/PPCISelLowering.cpp:1.157	Mon Apr 17 01:07:44 2006
+++ llvm/lib/Target/PowerPC/PPCISelLowering.cpp	Mon Apr 17 01:58:41 2006
@@ -1046,6 +1046,10 @@
 static SDOperand BuildSplatI(int Val, unsigned SplatSize, MVT::ValueType VT,
                              SelectionDAG &DAG) {
   assert(Val >= -16 && Val <= 15 && "vsplti is out of range!");
+  
+  // Force vspltis[hw] -1 to vspltisb -1.
+  if (Val == -1) SplatSize = 1;
+  
   static const MVT::ValueType VTys[] = { // canonical VT to use for each size.
     MVT::v16i8, MVT::v8i16, MVT::Other, MVT::v4i32
   };
@@ -1058,6 +1062,14 @@
   return DAG.getNode(ISD::BIT_CONVERT, VT, Res);
 }
 
+/// BuildIntrinsicBinOp - Return a binary operator intrinsic node with the
+/// specified intrinsic ID.
+static SDOperand BuildIntrinsicBinOp(unsigned IID, SDOperand LHS, SDOperand RHS,
+                                     SelectionDAG &DAG) {
+  return DAG.getNode(ISD::INTRINSIC_WO_CHAIN, LHS.getValueType(),
+                     DAG.getConstant(IID, MVT::i32), LHS, RHS);
+}
+
 // If this is a case we can't handle, return null and let the default
 // expansion code take care of it.  If we CAN select this case, and if it
 // selects to a single instruction, return Op.  Otherwise, if we can codegen
@@ -1105,37 +1117,81 @@
       Op = BuildSplatI(SextVal >> 1, SplatSize, Op.getValueType(), DAG);
       return DAG.getNode(ISD::ADD, Op.getValueType(), Op, Op);
     }
-    // Otherwise, in range [17,29]:  (vsplti 15) + (vsplti C).
-    if (SextVal >= 0 && SextVal <= 29) {
-      SDOperand LHS = BuildSplatI(15, SplatSize, Op.getValueType(), DAG);
-      SDOperand RHS = BuildSplatI(SextVal-15, SplatSize, Op.getValueType(),DAG);
-      return DAG.getNode(ISD::ADD, Op.getValueType(), LHS, RHS);
-      
-    }
-
     
     // If this is 0x8000_0000 x 4, turn into vspltisw + vslw.  If it is 
-    // 0x7FFF_FFFF x 4, turn it into not(0x8000_0000).  These are important
+    // 0x7FFF_FFFF x 4, turn it into not(0x8000_0000).  This is important
     // for fneg/fabs.
-    if (SplatSize == 4 &&
-        SplatBits == 0x80000000 || SplatBits == (0x7FFFFFFF&~SplatUndef)) {
+    if (SplatSize == 4 && SplatBits == (0x7FFFFFFF&~SplatUndef)) {
       // Make -1 and vspltisw -1:
-      SDOperand OnesI = DAG.getConstant(~0U, MVT::i32);
-      SDOperand OnesV = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
-                                    OnesI, OnesI, OnesI, OnesI);
+      SDOperand OnesV = BuildSplatI(-1, 4, MVT::v4i32, DAG);
       
       // Make the VSLW intrinsic, computing 0x8000_0000.
-      SDOperand Res
-        = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, MVT::v4i32,
-                      DAG.getConstant(Intrinsic::ppc_altivec_vslw, MVT::i32),
-                      OnesV, OnesV);
-      
-      // If this is 0x7FFF_FFFF, xor by OnesV to invert it.
-      if (SplatBits == 0x80000000)
-        Res = DAG.getNode(ISD::XOR, MVT::v4i32, Res, OnesV);
+      SDOperand Res = BuildIntrinsicBinOp(Intrinsic::ppc_altivec_vslw, OnesV, 
+                                          OnesV, DAG);
       
+      // xor by OnesV to invert it.
+      Res = DAG.getNode(ISD::XOR, MVT::v4i32, Res, OnesV);
       return DAG.getNode(ISD::BIT_CONVERT, Op.getValueType(), Res);
     }
+
+    // Check to see if this is a wide variety of vsplti*, binop self cases.
+    unsigned SplatBitSize = SplatSize*8;
+    static const char SplatCsts[] = {
+      -1, 1, -2, 2, -3, 3, -4, 4, -5, 5, -6, 6, -7, 7,
+      -8, 8, -9, 9, -10, 10, -11, 11, -12, 12, -13, 14, -15
+    };
+    for (unsigned idx = 0; idx < sizeof(SplatCsts)/sizeof(SplatCsts[0]); ++idx){
+      // Indirect through the SplatCsts array so that we favor 'vsplti -1' for
+      // cases which are ambiguous (e.g. formation of 0x8000_0000).  'vsplti -1'
+      int i = SplatCsts[idx];
+      
+      // Figure out what shift amount will be used by altivec if shifted by i in
+      // this splat size.
+      unsigned TypeShiftAmt = i & (SplatBitSize-1);
+      
+      // vsplti + shl self.
+      if (SextVal == (i << (int)TypeShiftAmt)) {
+        Op = BuildSplatI(i, SplatSize, Op.getValueType(), DAG);
+        static const unsigned IIDs[] = { // Intrinsic to use for each size.
+          Intrinsic::ppc_altivec_vslb, Intrinsic::ppc_altivec_vslh, 0,
+          Intrinsic::ppc_altivec_vslw
+        };
+        return BuildIntrinsicBinOp(IIDs[SplatSize-1], Op, Op, DAG);
+      }
+      
+      // vsplti + srl self.
+      if (SextVal == (int)((unsigned)i >> TypeShiftAmt)) {
+        Op = BuildSplatI(i, SplatSize, Op.getValueType(), DAG);
+        static const unsigned IIDs[] = { // Intrinsic to use for each size.
+          Intrinsic::ppc_altivec_vsrb, Intrinsic::ppc_altivec_vsrh, 0,
+          Intrinsic::ppc_altivec_vsrw
+        };
+        return BuildIntrinsicBinOp(IIDs[SplatSize-1], Op, Op, DAG);
+      }
+      
+      // vsplti + sra self.
+      if (SextVal == (int)((unsigned)i >> TypeShiftAmt)) {
+        Op = BuildSplatI(i, SplatSize, Op.getValueType(), DAG);
+        static const unsigned IIDs[] = { // Intrinsic to use for each size.
+          Intrinsic::ppc_altivec_vsrab, Intrinsic::ppc_altivec_vsrah, 0,
+          Intrinsic::ppc_altivec_vsraw
+        };
+        return BuildIntrinsicBinOp(IIDs[SplatSize-1], Op, Op, DAG);
+      }
+      
+      // TODO: ROL.
+    }
+    
+    
+    
+    // Three instruction sequences.
+    
+    // Otherwise, in range [17,29]:  (vsplti 15) + (vsplti C).
+    if (SextVal >= 0 && SextVal <= 29) {
+      SDOperand LHS = BuildSplatI(15, SplatSize, Op.getValueType(), DAG);
+      SDOperand RHS = BuildSplatI(SextVal-15, SplatSize, Op.getValueType(),DAG);
+      return DAG.getNode(ISD::ADD, Op.getValueType(), LHS, RHS);
+    }
   }
     
   return SDOperand();






More information about the llvm-commits mailing list