[llvm-commits] CVS: llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp PPCISelLowering.cpp PPCISelLowering.h PPCInstrInfo.td

Chris Lattner lattner at cs.uiuc.edu
Fri Mar 24 22:12:20 PST 2006



Changes in directory llvm/lib/Target/PowerPC:

PPCAsmPrinter.cpp updated: 1.161 -> 1.162
PPCISelLowering.cpp updated: 1.110 -> 1.111
PPCISelLowering.h updated: 1.32 -> 1.33
PPCInstrInfo.td updated: 1.207 -> 1.208
---
Log message:

Codegen things like:
 <int -1, int -1, int -1, int -1>
and 
 <int 65537, int 65537, int 65537, int 65537>

Using things like:
  vspltisb v0, -1
and:
  vspltish v0, 1

instead of using constant pool loads.

This implements CodeGen/PowerPC/vec_splat.ll:splat_imm_i{32|16}.



---
Diffs of the changes:  (+123 -2)

 PPCAsmPrinter.cpp   |    5 ++++
 PPCISelLowering.cpp |   63 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 PPCISelLowering.h   |    5 ++++
 PPCInstrInfo.td     |   52 +++++++++++++++++++++++++++++++++++++++++-
 4 files changed, 123 insertions(+), 2 deletions(-)


Index: llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
diff -u llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp:1.161 llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp:1.162
--- llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp:1.161	Thu Mar 23 12:09:44 2006
+++ llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp	Sat Mar 25 00:12:06 2006
@@ -102,6 +102,11 @@
                                unsigned AsmVariant, const char *ExtraCode);
     
     
+    void printS5ImmOperand(const MachineInstr *MI, unsigned OpNo) {
+      char value = MI->getOperand(OpNo).getImmedValue();
+      value = (value << (32-5)) >> (32-5);
+      O << (int)value;
+    }
     void printU5ImmOperand(const MachineInstr *MI, unsigned OpNo) {
       unsigned char value = MI->getOperand(OpNo).getImmedValue();
       assert(value <= 31 && "Invalid u5imm argument!");


Index: llvm/lib/Target/PowerPC/PPCISelLowering.cpp
diff -u llvm/lib/Target/PowerPC/PPCISelLowering.cpp:1.110 llvm/lib/Target/PowerPC/PPCISelLowering.cpp:1.111
--- llvm/lib/Target/PowerPC/PPCISelLowering.cpp:1.110	Fri Mar 24 01:53:47 2006
+++ llvm/lib/Target/PowerPC/PPCISelLowering.cpp	Sat Mar 25 00:12:06 2006
@@ -301,6 +301,63 @@
   return true;
 }
 
+/// isVecSplatImm - Return true if this is a build_vector of constants which
+/// can be formed by using a vspltis[bhw] instruction.  The ByteSize field
+/// indicates the number of bytes of each element [124] -> [bhw].
+bool PPC::isVecSplatImm(SDNode *N, unsigned ByteSize, char *Val) {
+  SDOperand OpVal(0, 0);
+  // Check to see if this buildvec has a single non-undef value in its elements.
+  for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) {
+    if (N->getOperand(i).getOpcode() == ISD::UNDEF) continue;
+    if (OpVal.Val == 0)
+      OpVal = N->getOperand(i);
+    else if (OpVal != N->getOperand(i))
+      return false;
+  }
+  
+  if (OpVal.Val == 0) return false;  // All UNDEF: use implicit def.
+  
+  unsigned ValSizeInBytes;
+  uint64_t Value;
+  if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(OpVal)) {
+    Value = CN->getValue();
+    ValSizeInBytes = MVT::getSizeInBits(CN->getValueType(0))/8;
+  } else if (ConstantFPSDNode *CN = dyn_cast<ConstantFPSDNode>(OpVal)) {
+    assert(CN->getValueType(0) == MVT::f32 && "Only one legal FP vector type!");
+    Value = FloatToBits(CN->getValue());
+    ValSizeInBytes = 4;
+  }
+
+  // If the splat value is larger than the element value, then we can never do
+  // this splat.  The only case that we could fit the replicated bits into our
+  // immediate field for would be zero, and we prefer to use vxor for it.
+  if (ValSizeInBytes < ByteSize) return false;
+  
+  // If the element value is larger than the splat value, cut it in half and
+  // check to see if the two halves are equal.  Continue doing this until we
+  // get to ByteSize.  This allows us to handle 0x01010101 as 0x01.
+  while (ValSizeInBytes > ByteSize) {
+    ValSizeInBytes >>= 1;
+    
+    // If the top half equals the bottom half, we're still ok.
+    if (((Value >> (ValSizeInBytes*8)) & ((8 << ValSizeInBytes)-1)) !=
+         (Value                        & ((8 << ValSizeInBytes)-1)))
+      return false;
+  }
+
+  // Properly sign extend the value.
+  int ShAmt = (4-ByteSize)*8;
+  int MaskVal = ((int)Value << ShAmt) >> ShAmt;
+  
+  // If this is zero, don't match, zero matches isZeroVector.
+  if (MaskVal == 0) return false;
+
+  if (Val) *Val = MaskVal;
+
+  // Finally, if this value fits in a 5 bit sext field, return true.
+  return ((MaskVal << (32-5)) >> (32-5)) == MaskVal; 
+}
+
 
 /// LowerOperation - Provide custom lowering hooks for some operations.
 ///
@@ -668,6 +725,12 @@
     // FIXME: We should handle splat(-0.0), and other cases here.
     if (PPC::isZeroVector(Op.Val))
       return Op;
+    
+    if (PPC::isVecSplatImm(Op.Val, 1) ||    // vspltisb
+        PPC::isVecSplatImm(Op.Val, 2) ||    // vspltish
+        PPC::isVecSplatImm(Op.Val, 4))      // vspltisw
+      return Op;
+      
     return SDOperand();
     
   case ISD::VECTOR_SHUFFLE: {


Index: llvm/lib/Target/PowerPC/PPCISelLowering.h
diff -u llvm/lib/Target/PowerPC/PPCISelLowering.h:1.32 llvm/lib/Target/PowerPC/PPCISelLowering.h:1.33
--- llvm/lib/Target/PowerPC/PPCISelLowering.h:1.32	Fri Mar 24 01:48:08 2006
+++ llvm/lib/Target/PowerPC/PPCISelLowering.h	Sat Mar 25 00:12:06 2006
@@ -105,6 +105,11 @@
     /// isZeroVector - Return true if this build_vector is an all-zero vector.
     ///
     bool isZeroVector(SDNode *N);
+    
+    /// isVecSplatImm - Return true if this is a build_vector of constants which
+    /// can be formed by using a vspltis[bhw] instruction.  The ByteSize field
+    /// indicates the number of bytes of each element [124] -> [bhw].
+    bool isVecSplatImm(SDNode *N, unsigned ByteSize, char *Val = 0);
   }
   
   class PPCTargetLowering : public TargetLowering {


Index: llvm/lib/Target/PowerPC/PPCInstrInfo.td
diff -u llvm/lib/Target/PowerPC/PPCInstrInfo.td:1.207 llvm/lib/Target/PowerPC/PPCInstrInfo.td:1.208
--- llvm/lib/Target/PowerPC/PPCInstrInfo.td:1.207	Fri Mar 24 12:24:43 2006
+++ llvm/lib/Target/PowerPC/PPCInstrInfo.td	Sat Mar 25 00:12:06 2006
@@ -140,6 +140,37 @@
 }]>;
 
 
+// VSPLTISB_get_imm xform function: convert build_vector to VSPLTISB imm.
+def VSPLTISB_get_imm : SDNodeXForm<build_vector, [{
+  char Val;
+  PPC::isVecSplatImm(N, 1, &Val);
+  return getI32Imm(Val);
+}]>;
+def vecspltisb : PatLeaf<(build_vector), [{
+  return PPC::isVecSplatImm(N, 1);
+}], VSPLTISB_get_imm>;
+
+// VSPLTISH_get_imm xform function: convert build_vector to VSPLTISH imm.
+def VSPLTISH_get_imm : SDNodeXForm<build_vector, [{
+  char Val;
+  PPC::isVecSplatImm(N, 2, &Val);
+  return getI32Imm(Val);
+}]>;
+def vecspltish : PatLeaf<(build_vector), [{
+  return PPC::isVecSplatImm(N, 2);
+}], VSPLTISH_get_imm>;
+
+// VSPLTISW_get_imm xform function: convert build_vector to VSPLTISW imm.
+def VSPLTISW_get_imm : SDNodeXForm<build_vector, [{
+  char Val;
+  PPC::isVecSplatImm(N, 4, &Val);
+  return getI32Imm(Val);
+}]>;
+def vecspltisw : PatLeaf<(build_vector), [{
+  return PPC::isVecSplatImm(N, 4);
+}], VSPLTISW_get_imm>;
+
+
 //===----------------------------------------------------------------------===//
 // PowerPC Flag Definitions.
 
@@ -155,6 +186,9 @@
 //===----------------------------------------------------------------------===//
 // PowerPC Operand Definitions.
 
+def s5imm   : Operand<i32> {
+  let PrintMethod = "printS5ImmOperand";
+}
 def u5imm   : Operand<i32> {
   let PrintMethod = "printU5ImmOperand";
 }
@@ -1055,12 +1089,21 @@
 def VSPLTH : VXForm_1<588, (ops VRRC:$vD, u5imm:$UIMM, VRRC:$vB),
                       "vsplth $vD, $vB, $UIMM", VecPerm,
                       []>;
-                      
 def VSPLTW : VXForm_1<652, (ops VRRC:$vD, u5imm:$UIMM, VRRC:$vB),
                       "vspltw $vD, $vB, $UIMM", VecPerm,
                       [(set VRRC:$vD, (vector_shuffle (v4f32 VRRC:$vB), (undef),
                                       VSPLT_shuffle_mask:$UIMM))]>;
-                      // FIXME: ALSO ADD SUPPORT FOR v4i32!
+
+def VSPLTISB : VXForm_1<780, (ops VRRC:$vD, s5imm:$SIMM),
+                      "vspltisb $vD, $SIMM", VecPerm,
+                      [(set VRRC:$vD, (v4f32 vecspltisb:$SIMM))]>;
+def VSPLTISH : VXForm_1<844, (ops VRRC:$vD, s5imm:$SIMM),
+                      "vspltish $vD, $SIMM", VecPerm,
+                      [(set VRRC:$vD, (v4f32 vecspltish:$SIMM))]>;
+def VSPLTISW : VXForm_1<908, (ops VRRC:$vD, s5imm:$SIMM),
+                      "vspltisw $vD, $SIMM", VecPerm,
+                      [(set VRRC:$vD, (v4f32 vecspltisw:$SIMM))]>;
+
                       
 // VX-Form Pseudo Instructions
 
@@ -1216,6 +1259,11 @@
 def : Pat<(v4i32 (undef)), (v4i32 (IMPLICIT_DEF_VRRC))>;
 def : Pat<(v4i32 vecimm0), (v4i32 (V_SET0))>;
 
+def : Pat<(v4i32 vecspltisb:$invec), (v4i32 (VSPLTISB vecspltisb:$invec))>;
+def : Pat<(v4i32 vecspltish:$invec), (v4i32 (VSPLTISH vecspltish:$invec))>;
+def : Pat<(v4i32 vecspltisw:$invec), (v4i32 (VSPLTISW vecspltisw:$invec))>;
+
+
 // bit_convert
 def : Pat<(v4i32 (bitconvert (v4f32 VRRC:$src))), (v4i32 VRRC:$src)>;
 def : Pat<(v4f32 (bitconvert (v4i32 VRRC:$src))), (v4f32 VRRC:$src)>;






More information about the llvm-commits mailing list