[llvm-commits] [llvm] r59891 - in /llvm/trunk: lib/Target/CellSPU/SPUISelDAGToDAG.cpp lib/Target/CellSPU/SPUISelLowering.cpp lib/Target/CellSPU/SPUISelLowering.h lib/Target/CellSPU/SPUInstrInfo.td lib/Target/CellSPU/SPUNodes.td test/CodeGen/CellSPU/extract_elt.ll

Scott Michel scottm at aero.org
Sat Nov 22 15:50:42 PST 2008


Author: pingbak
Date: Sat Nov 22 17:50:42 2008
New Revision: 59891

URL: http://llvm.org/viewvc/llvm-project?rev=59891&view=rev
Log:
CellSPU: Fix bug 3056. Varadic extract_element was not implemented (nor was it
ever conceived to occur).

Modified:
    llvm/trunk/lib/Target/CellSPU/SPUISelDAGToDAG.cpp
    llvm/trunk/lib/Target/CellSPU/SPUISelLowering.cpp
    llvm/trunk/lib/Target/CellSPU/SPUISelLowering.h
    llvm/trunk/lib/Target/CellSPU/SPUInstrInfo.td
    llvm/trunk/lib/Target/CellSPU/SPUNodes.td
    llvm/trunk/test/CodeGen/CellSPU/extract_elt.ll

Modified: llvm/trunk/lib/Target/CellSPU/SPUISelDAGToDAG.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/CellSPU/SPUISelDAGToDAG.cpp?rev=59891&r1=59890&r2=59891&view=diff

==============================================================================
--- llvm/trunk/lib/Target/CellSPU/SPUISelDAGToDAG.cpp (original)
+++ llvm/trunk/lib/Target/CellSPU/SPUISelDAGToDAG.cpp Sat Nov 22 17:50:42 2008
@@ -591,13 +591,24 @@
                                  SDValue &Index) {
   if (!SelectAFormAddr(Op, N, Base, Index)
       && !SelectDFormAddr(Op, N, Base, Index)) {
-    // default form of a X-form address is r(r) in operands 0 and 1:
+    // Default form of a X-form address is r(r) in operands 0 and 1:
     SDValue Op0 = N.getOperand(0);
     SDValue Op1 = N.getOperand(1);
 
-    if (Op0.getOpcode() == ISD::Register && Op1.getOpcode() == ISD::Register) {
-      Base = Op0;
-      Index = Op1;
+    if ((Op0.getOpcode() == ISD::Register
+         || Op.getOpcode() == ISD::CopyFromReg)
+        && (Op1.getOpcode() == ISD::Register
+            || Op.getOpcode() == ISD::CopyFromReg)) {
+      if (Op.getOpcode() == ISD::Register)
+        Base = Op0;
+      else
+        Base = Op0.getOperand(1);
+
+      if (Op1.getOpcode() == ISD::Register)
+        Index = Op1;
+      else
+        Index = Op1.getOperand(1);
+
       return true;
     }
   }

Modified: llvm/trunk/lib/Target/CellSPU/SPUISelLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/CellSPU/SPUISelLowering.cpp?rev=59891&r1=59890&r2=59891&view=diff

==============================================================================
--- llvm/trunk/lib/Target/CellSPU/SPUISelLowering.cpp (original)
+++ llvm/trunk/lib/Target/CellSPU/SPUISelLowering.cpp Sat Nov 22 17:50:42 2008
@@ -39,8 +39,8 @@
 
   //! MVT mapping to useful data for Cell SPU
   struct valtype_map_s {
-    const MVT        valtype;
-    const int                   prefslot_byte;
+    const MVT   valtype;
+    const int   prefslot_byte;
   };
 
   const valtype_map_s valtype_map[] = {
@@ -171,7 +171,13 @@
   // Expand the jumptable branches
   setOperationAction(ISD::BR_JT,        MVT::Other, Expand);
   setOperationAction(ISD::BR_CC,        MVT::Other, Expand);
+
+  // Custom lower SELECT_CC for most cases, but expand by default
   setOperationAction(ISD::SELECT_CC,    MVT::Other, Expand);
+  setOperationAction(ISD::SELECT_CC,    MVT::i8,    Custom);
+  setOperationAction(ISD::SELECT_CC,    MVT::i16,   Custom);
+  setOperationAction(ISD::SELECT_CC,    MVT::i32,   Custom);
+  setOperationAction(ISD::SELECT_CC,    MVT::i64,   Custom);
 
   // SPU has no intrinsics for these particular operations:
   setOperationAction(ISD::MEMBARRIER, MVT::Other, Expand);
@@ -398,6 +404,9 @@
   setTargetDAGCombine(ISD::ANY_EXTEND);
 
   computeRegisterProperties();
+
+  // Set other properties:
+  setSchedulingPreference(SchedulingForLatency);
 }
 
 const char *
@@ -413,7 +422,7 @@
     node_names[(unsigned) SPUISD::LDRESULT] = "SPUISD::LDRESULT";
     node_names[(unsigned) SPUISD::CALL] = "SPUISD::CALL";
     node_names[(unsigned) SPUISD::SHUFB] = "SPUISD::SHUFB";
-    node_names[(unsigned) SPUISD::INSERT_MASK] = "SPUISD::INSERT_MASK";
+    node_names[(unsigned) SPUISD::SHUFFLE_MASK] = "SPUISD::SHUFFLE_MASK";
     node_names[(unsigned) SPUISD::CNTB] = "SPUISD::CNTB";
     node_names[(unsigned) SPUISD::PROMOTE_SCALAR] = "SPUISD::PROMOTE_SCALAR";
     node_names[(unsigned) SPUISD::EXTRACT_ELT0] = "SPUISD::EXTRACT_ELT0";
@@ -750,7 +759,7 @@
     }
 
     SDValue insertEltOp =
-            DAG.getNode(SPUISD::INSERT_MASK, stVecVT, insertEltPtr);
+            DAG.getNode(SPUISD::SHUFFLE_MASK, stVecVT, insertEltPtr);
     SDValue vectorizeOp =
             DAG.getNode(ISD::SCALAR_TO_VECTOR, vecVT, theValue);
 
@@ -1720,11 +1729,11 @@
 /// which the Cell can operate. The code inspects V3 to ascertain whether the
 /// permutation vector, V3, is monotonically increasing with one "exception"
 /// element, e.g., (0, 1, _, 3). If this is the case, then generate a
-/// INSERT_MASK synthetic instruction. Otherwise, spill V3 to the constant pool.
+/// SHUFFLE_MASK synthetic instruction. Otherwise, spill V3 to the constant pool.
 /// In either case, the net result is going to eventually invoke SHUFB to
 /// permute/shuffle the bytes from V1 and V2.
 /// \note
-/// INSERT_MASK is eventually selected as one of the C*D instructions, generate
+/// SHUFFLE_MASK is eventually selected as one of the C*D instructions, generate
 /// control word for byte/halfword/word insertion. This takes care of a single
 /// element move from V2 into V1.
 /// \note
@@ -1782,9 +1791,9 @@
     // Initialize temporary register to 0
     SDValue InitTempReg =
       DAG.getCopyToReg(DAG.getEntryNode(), VReg, DAG.getConstant(0, PtrVT));
-    // Copy register's contents as index in INSERT_MASK:
+    // Copy register's contents as index in SHUFFLE_MASK:
     SDValue ShufMaskOp =
-      DAG.getNode(SPUISD::INSERT_MASK, V1.getValueType(),
+      DAG.getNode(SPUISD::SHUFFLE_MASK, V1.getValueType(),
                   DAG.getTargetConstant(V2Elt, MVT::i32),
                   DAG.getCopyFromReg(InitTempReg, VReg, PtrVT));
     // Use shuffle mask in SHUFB synthetic instruction:
@@ -2050,82 +2059,200 @@
   MVT VT = Op.getValueType();
   SDValue N = Op.getOperand(0);
   SDValue Elt = Op.getOperand(1);
-  SDValue ShufMask[16];
-  ConstantSDNode *C = dyn_cast<ConstantSDNode>(Elt);
+  SDValue retval;
 
-  assert(C != 0 && "LowerEXTRACT_VECTOR_ELT expecting constant SDNode");
+  if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Elt)) {
+    // Constant argument:
+    int EltNo = (int) C->getZExtValue();
+
+    // sanity checks:
+    if (VT == MVT::i8 && EltNo >= 16)
+      assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i8 extraction slot > 15");
+    else if (VT == MVT::i16 && EltNo >= 8)
+      assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i16 extraction slot > 7");
+    else if (VT == MVT::i32 && EltNo >= 4)
+      assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i32 extraction slot > 4");
+    else if (VT == MVT::i64 && EltNo >= 2)
+      assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i64 extraction slot > 2");
+
+    if (EltNo == 0 && (VT == MVT::i32 || VT == MVT::i64)) {
+      // i32 and i64: Element 0 is the preferred slot
+      return DAG.getNode(SPUISD::EXTRACT_ELT0, VT, N);
+    }
+
+    // Need to generate shuffle mask and extract:
+    int prefslot_begin = -1, prefslot_end = -1;
+    int elt_byte = EltNo * VT.getSizeInBits() / 8;
 
-  int EltNo = (int) C->getZExtValue();
+    switch (VT.getSimpleVT()) {
+    default:
+      assert(false && "Invalid value type!");
+    case MVT::i8: {
+      prefslot_begin = prefslot_end = 3;
+      break;
+    }
+    case MVT::i16: {
+      prefslot_begin = 2; prefslot_end = 3;
+      break;
+    }
+    case MVT::i32:
+    case MVT::f32: {
+      prefslot_begin = 0; prefslot_end = 3;
+      break;
+    }
+    case MVT::i64:
+    case MVT::f64: {
+      prefslot_begin = 0; prefslot_end = 7;
+      break;
+    }
+    }
 
-  // sanity checks:
-  if (VT == MVT::i8 && EltNo >= 16)
-    assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i8 extraction slot > 15");
-  else if (VT == MVT::i16 && EltNo >= 8)
-    assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i16 extraction slot > 7");
-  else if (VT == MVT::i32 && EltNo >= 4)
-    assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i32 extraction slot > 4");
-  else if (VT == MVT::i64 && EltNo >= 2)
-    assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i64 extraction slot > 2");
-
-  if (EltNo == 0 && (VT == MVT::i32 || VT == MVT::i64)) {
-    // i32 and i64: Element 0 is the preferred slot
-    return DAG.getNode(SPUISD::EXTRACT_ELT0, VT, N);
-  }
-
-  // Need to generate shuffle mask and extract:
-  int prefslot_begin = -1, prefslot_end = -1;
-  int elt_byte = EltNo * VT.getSizeInBits() / 8;
+    assert(prefslot_begin != -1 && prefslot_end != -1 &&
+           "LowerEXTRACT_VECTOR_ELT: preferred slots uninitialized");
 
-  switch (VT.getSimpleVT()) {
-  default:
-    assert(false && "Invalid value type!");
-  case MVT::i8: {
-    prefslot_begin = prefslot_end = 3;
-    break;
-  }
-  case MVT::i16: {
-    prefslot_begin = 2; prefslot_end = 3;
-    break;
-  }
-  case MVT::i32:
-  case MVT::f32: {
-    prefslot_begin = 0; prefslot_end = 3;
-    break;
-  }
-  case MVT::i64:
-  case MVT::f64: {
-    prefslot_begin = 0; prefslot_end = 7;
-    break;
-  }
-  }
+    unsigned int ShufBytes[16];
+    for (int i = 0; i < 16; ++i) {
+      // zero fill uppper part of preferred slot, don't care about the
+      // other slots:
+      unsigned int mask_val;
+      if (i <= prefslot_end) {
+        mask_val =
+          ((i < prefslot_begin)
+           ? 0x80
+           : elt_byte + (i - prefslot_begin));
 
-  assert(prefslot_begin != -1 && prefslot_end != -1 &&
-         "LowerEXTRACT_VECTOR_ELT: preferred slots uninitialized");
+        ShufBytes[i] = mask_val;
+      } else
+        ShufBytes[i] = ShufBytes[i % (prefslot_end + 1)];
+    }
 
-  for (int i = 0; i < 16; ++i) {
-    // zero fill uppper part of preferred slot, don't care about the
-    // other slots:
-    unsigned int mask_val;
-    if (i <= prefslot_end) {
-      mask_val =
-        ((i < prefslot_begin)
-         ? 0x80
-         : elt_byte + (i - prefslot_begin));
-
-      ShufMask[i] = DAG.getConstant(mask_val, MVT::i8);
-    } else
-      ShufMask[i] = ShufMask[i % (prefslot_end + 1)];
-  }
-
-  SDValue ShufMaskVec =
-    DAG.getNode(ISD::BUILD_VECTOR, MVT::v16i8,
-                &ShufMask[0],
-                sizeof(ShufMask) / sizeof(ShufMask[0]));
-
-  return DAG.getNode(SPUISD::EXTRACT_ELT0, VT,
-                     DAG.getNode(SPUISD::SHUFB, N.getValueType(),
-                                 N, N, ShufMaskVec));
+    SDValue ShufMask[4];
+    for (unsigned i = 0; i < sizeof(ShufMask)/sizeof(ShufMask[0]); ++i) {
+      unsigned bidx = i / 4;
+      unsigned int bits = ((ShufBytes[bidx] << 24) |
+                           (ShufBytes[bidx+1] << 16) |
+                           (ShufBytes[bidx+2] << 8) |
+                           ShufBytes[bidx+3]);
+      ShufMask[i] = DAG.getConstant(bits, MVT::i32);
+    }
+
+    SDValue ShufMaskVec = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
+                                      &ShufMask[0],
+                                      sizeof(ShufMask) / sizeof(ShufMask[0]));
+
+    retval = DAG.getNode(SPUISD::EXTRACT_ELT0, VT,
+                         DAG.getNode(SPUISD::SHUFB, N.getValueType(),
+                                     N, N, ShufMaskVec));
+  } else {
+    // Variable index: Rotate the requested element into slot 0, then replicate
+    // slot 0 across the vector
+    MVT VecVT = N.getValueType();
+    if (!VecVT.isSimple() || !VecVT.isVector() || !VecVT.is128BitVector()) {
+      cerr << "LowerEXTRACT_VECTOR_ELT: Must have a simple, 128-bit vector type!\n";
+      abort();
+    }
 
+    // Make life easier by making sure the index is zero-extended to i32
+    if (Elt.getValueType() != MVT::i32)
+      Elt = DAG.getNode(ISD::ZERO_EXTEND, MVT::i32, Elt);
+
+    // Scale the index to a bit/byte shift quantity
+    APInt scaleFactor =
+      APInt(32, uint64_t(16 / N.getValueType().getVectorNumElements()), false);
+    SDValue vecShift;
+    
+    switch (VT.getSimpleVT()) {
+    default:
+      cerr << "LowerEXTRACT_VECTOR_ELT(varable): Unhandled vector type\n";
+      abort();
+      /*NOTREACHED*/
+    case MVT::i8: {
+      // Don't need to scale, but we do need to correct for where bytes go in
+      // slot 0:
+      SDValue prefSlot = DAG.getNode(ISD::SUB, MVT::i32,
+                                     Elt, DAG.getConstant(3, MVT::i32));
+      SDValue corrected = DAG.getNode(ISD::ADD, MVT::i32, prefSlot,
+                                      DAG.getConstant(16, MVT::i32));
+
+      SDValue shiftAmt = DAG.getNode(ISD::SELECT_CC, MVT::i32,
+                                     prefSlot, DAG.getConstant(0, MVT::i32),
+                                     prefSlot,          // trueval
+                                     corrected,         // falseval
+                                     DAG.getCondCode(ISD::SETGT));
+      vecShift = DAG.getNode(SPUISD::ROTBYTES_LEFT, VecVT, N, shiftAmt);
+      break;
+    }
+    case MVT::i16: {
+      // Scale the index to bytes, subtract for preferred slot:
+      Elt = DAG.getNode(ISD::SHL, MVT::i32, Elt,
+                        DAG.getConstant(scaleFactor.logBase2(), MVT::i32));
+      SDValue prefSlot = DAG.getNode(ISD::SUB, MVT::i32,
+                                     Elt, DAG.getConstant(2, MVT::i32));
+      SDValue corrected = DAG.getNode(ISD::ADD, MVT::i32, prefSlot,
+                                      DAG.getConstant(16, MVT::i32));
+
+      SDValue shiftAmt = DAG.getNode(ISD::SELECT_CC, MVT::i32,
+                                     prefSlot, DAG.getConstant(0, MVT::i32),
+                                     prefSlot,          // trueval
+                                     corrected,         // falseval
+                                     DAG.getCondCode(ISD::SETGT));
+      vecShift = DAG.getNode(SPUISD::ROTBYTES_LEFT, VecVT, N, shiftAmt);
+      break;
+    }
+    case MVT::i32:
+    case MVT::f32:
+    case MVT::i64:
+    case MVT::f64:
+      // Simple left shift to slot 0
+      Elt = DAG.getNode(ISD::SHL, MVT::i32, Elt,
+                        DAG.getConstant(scaleFactor.logBase2(), MVT::i32));
+      vecShift = DAG.getNode(SPUISD::SHLQUAD_L_BYTES, VecVT, N, Elt);
+      break;
+    }
+
+    // Replicate slot 0 across the entire vector (for consistency with the
+    // notion of a unified register set)
+    SDValue replicate;
+
+    switch (VT.getSimpleVT()) {
+    default:
+      cerr << "LowerEXTRACT_VECTOR_ELT(varable): Unhandled vector type\n";
+      abort();
+      /*NOTREACHED*/
+    case MVT::i8: {
+      SDValue factor = DAG.getConstant(0x03030303, MVT::i32);
+      replicate = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, factor, factor,
+                              factor, factor);
+      break;
+    }
+    case MVT::i16: {
+      SDValue factor = DAG.getConstant(0x02030203, MVT::i32);
+      replicate = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, factor, factor,
+                              factor, factor);
+      break;
+    }
+    case MVT::i32:
+    case MVT::f32: {
+      SDValue factor = DAG.getConstant(0x00010203, MVT::i32);
+      replicate = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, factor, factor,
+                              factor, factor);
+      break;
+    }
+    case MVT::i64:
+    case MVT::f64: {
+      SDValue loFactor = DAG.getConstant(0x00010203, MVT::i32);
+      SDValue hiFactor = DAG.getConstant(0x04050607, MVT::i32);
+      replicate = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, loFactor, hiFactor,
+                              loFactor, hiFactor);
+      break;
+    }
+    }
+
+    retval = DAG.getNode(SPUISD::EXTRACT_ELT0, VT,
+                         DAG.getNode(SPUISD::SHUFB, VecVT, vecShift, vecShift, replicate));
+  }
+
+  return retval;
 }
 
 static SDValue LowerINSERT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) {
@@ -2145,7 +2272,7 @@
     DAG.getNode(SPUISD::SHUFB, VT,
                 DAG.getNode(ISD::SCALAR_TO_VECTOR, VT, ValOp),
                 VecOp,
-                DAG.getNode(SPUISD::INSERT_MASK, VT,
+                DAG.getNode(SPUISD::SHUFFLE_MASK, VT,
                             DAG.getNode(ISD::ADD, PtrVT,
                                         PtrBase,
                                         DAG.getConstant(CN->getZExtValue(),
@@ -2614,8 +2741,39 @@
   return SDValue();
 }
 
-/// LowerOperation - Provide custom lowering hooks for some operations.
-///
+//! Lower ISD::SELECT_CC
+/*!
+  ISD::SELECT_CC can (generally) be implemented directly on the SPU using the
+  SELB instruction.
+
+  \note Need to revisit this in the future: if the code path through the true
+  and false value computations is longer than the latency of a branch (6
+  cycles), then it would be more advantageous to branch and insert a new basic
+  block and branch on the condition. However, this code does not make that
+  assumption, given the simplisitc uses so far.
+ */
+
+static SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) {
+  MVT VT = Op.getValueType();
+  SDValue lhs = Op.getOperand(0);
+  SDValue rhs = Op.getOperand(1);
+  SDValue trueval = Op.getOperand(2);
+  SDValue falseval = Op.getOperand(3);
+  SDValue condition = Op.getOperand(4);
+
+  // Note: Really should be ISD::SELECT instead of SPUISD::SELB, but LLVM's
+  // legalizer insists on combining SETCC/SELECT into SELECT_CC, so we end up
+  // with another "cannot select select_cc" assert:
+
+  SDValue compare = DAG.getNode(ISD::SETCC, VT, lhs, rhs, condition);
+  return DAG.getNode(SPUISD::SELB, VT, trueval, falseval, compare);
+}
+
+//! Custom (target-specific) lowering entry point
+/*!
+  This is where LLVM's DAG selection process calls to do target-specific
+  lowering of nodes.
+ */
 SDValue
 SPUTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG)
 {
@@ -2704,13 +2862,19 @@
   case ISD::FDIV:
     if (VT == MVT::f32 || VT == MVT::v4f32)
       return LowerFDIVf32(Op, DAG);
-//    else if (Op.getValueType() == MVT::f64)
-//      return LowerFDIVf64(Op, DAG);
+#if 0
+    // This is probably a libcall
+    else if (Op.getValueType() == MVT::f64)
+      return LowerFDIVf64(Op, DAG);
+#endif
     else
       assert(0 && "Calling FDIV on unsupported MVT");
 
   case ISD::CTPOP:
     return LowerCTPOP(Op, DAG);
+
+  case ISD::SELECT_CC:
+    return LowerSELECT_CC(Op, DAG);
   }
 
   return SDValue();
@@ -2967,7 +3131,7 @@
 #if 0
   case CALL:
   case SHUFB:
-  case INSERT_MASK:
+  case SHUFFLE_MASK:
   case CNTB:
 #endif
 

Modified: llvm/trunk/lib/Target/CellSPU/SPUISelLowering.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/CellSPU/SPUISelLowering.h?rev=59891&r1=59890&r2=59891&view=diff

==============================================================================
--- llvm/trunk/lib/Target/CellSPU/SPUISelLowering.h (original)
+++ llvm/trunk/lib/Target/CellSPU/SPUISelLowering.h Sat Nov 22 17:50:42 2008
@@ -37,7 +37,7 @@
       LDRESULT,                 ///< Load result (value, chain)
       CALL,                     ///< CALL instruction
       SHUFB,                    ///< Vector shuffle (permute)
-      INSERT_MASK,              ///< Insert element shuffle mask
+      SHUFFLE_MASK,             ///< Shuffle mask
       CNTB,                     ///< Count leading ones in bytes
       PROMOTE_SCALAR,           ///< Promote scalar->vector
       EXTRACT_ELT0,             ///< Extract element 0

Modified: llvm/trunk/lib/Target/CellSPU/SPUInstrInfo.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/CellSPU/SPUInstrInfo.td?rev=59891&r1=59890&r2=59891&view=diff

==============================================================================
--- llvm/trunk/lib/Target/CellSPU/SPUInstrInfo.td (original)
+++ llvm/trunk/lib/Target/CellSPU/SPUInstrInfo.td Sat Nov 22 17:50:42 2008
@@ -272,51 +272,51 @@
 def CBD :
     RI7Form<0b10101111100, (outs VECREG:$rT), (ins memri7:$src),
       "cbd\t$rT, $src", ShuffleOp,
-      [(set (v16i8 VECREG:$rT), (SPUvecinsmask dform2_addr:$src))]>;
+      [(set (v16i8 VECREG:$rT), (SPUshufmask dform2_addr:$src))]>;
 
 def CBX : RRForm<0b00101011100, (outs VECREG:$rT), (ins memrr:$src),
     "cbx\t$rT, $src", ShuffleOp,
-    [(set (v16i8 VECREG:$rT), (SPUvecinsmask xform_addr:$src))]>;
+    [(set (v16i8 VECREG:$rT), (SPUshufmask xform_addr:$src))]>;
 
 def CHD : RI7Form<0b10101111100, (outs VECREG:$rT), (ins memri7:$src),
     "chd\t$rT, $src", ShuffleOp,
-    [(set (v8i16 VECREG:$rT), (SPUvecinsmask dform2_addr:$src))]>;
+    [(set (v8i16 VECREG:$rT), (SPUshufmask dform2_addr:$src))]>;
 
 def CHX : RRForm<0b10101011100, (outs VECREG:$rT), (ins memrr:$src),
     "chx\t$rT, $src", ShuffleOp,
-    [(set (v8i16 VECREG:$rT), (SPUvecinsmask xform_addr:$src))]>;
+    [(set (v8i16 VECREG:$rT), (SPUshufmask xform_addr:$src))]>;
 
 def CWD : RI7Form<0b01101111100, (outs VECREG:$rT), (ins memri7:$src),
     "cwd\t$rT, $src", ShuffleOp,
-    [(set (v4i32 VECREG:$rT), (SPUvecinsmask dform2_addr:$src))]>;
+    [(set (v4i32 VECREG:$rT), (SPUshufmask dform2_addr:$src))]>;
 
 def CWDf32 : RI7Form<0b01101111100, (outs VECREG:$rT), (ins memri7:$src),
     "cwd\t$rT, $src", ShuffleOp,
-    [(set (v4f32 VECREG:$rT), (SPUvecinsmask dform2_addr:$src))]>;
+    [(set (v4f32 VECREG:$rT), (SPUshufmask dform2_addr:$src))]>;
 
 def CWX : RRForm<0b01101011100, (outs VECREG:$rT), (ins memrr:$src),
     "cwx\t$rT, $src", ShuffleOp,
-    [(set (v4i32 VECREG:$rT), (SPUvecinsmask xform_addr:$src))]>;
+    [(set (v4i32 VECREG:$rT), (SPUshufmask xform_addr:$src))]>;
 
 def CWXf32 : RRForm<0b01101011100, (outs VECREG:$rT), (ins memrr:$src),
     "cwx\t$rT, $src", ShuffleOp,
-    [(set (v4f32 VECREG:$rT), (SPUvecinsmask xform_addr:$src))]>;
+    [(set (v4f32 VECREG:$rT), (SPUshufmask xform_addr:$src))]>;
 
 def CDD : RI7Form<0b11101111100, (outs VECREG:$rT), (ins memri7:$src),
     "cdd\t$rT, $src", ShuffleOp,
-    [(set (v2i64 VECREG:$rT), (SPUvecinsmask dform2_addr:$src))]>;
+    [(set (v2i64 VECREG:$rT), (SPUshufmask dform2_addr:$src))]>;
 
 def CDDf64 : RI7Form<0b11101111100, (outs VECREG:$rT), (ins memri7:$src),
     "cdd\t$rT, $src", ShuffleOp,
-    [(set (v2f64 VECREG:$rT), (SPUvecinsmask dform2_addr:$src))]>;
+    [(set (v2f64 VECREG:$rT), (SPUshufmask dform2_addr:$src))]>;
 
 def CDX : RRForm<0b11101011100, (outs VECREG:$rT), (ins memrr:$src),
     "cdx\t$rT, $src", ShuffleOp,
-    [(set (v2i64 VECREG:$rT), (SPUvecinsmask xform_addr:$src))]>;
+    [(set (v2i64 VECREG:$rT), (SPUshufmask xform_addr:$src))]>;
 
 def CDXf64 : RRForm<0b11101011100, (outs VECREG:$rT), (ins memrr:$src),
     "cdx\t$rT, $src", ShuffleOp,
-    [(set (v2f64 VECREG:$rT), (SPUvecinsmask xform_addr:$src))]>;
+    [(set (v2f64 VECREG:$rT), (SPUshufmask xform_addr:$src))]>;
 
 //===----------------------------------------------------------------------===//
 // Constant formation:
@@ -1647,14 +1647,23 @@
 
 defm SELB : SelectBits;
 
-class SPUselbPat<ValueType vectype, SPUInstr inst>:
+class SPUselbPatVec<ValueType vectype, SPUInstr inst>:
    Pat<(SPUselb (vectype VECREG:$rA), (vectype VECREG:$rB), (vectype VECREG:$rC)),
        (inst VECREG:$rA, VECREG:$rB, VECREG:$rC)>;
 
-def : SPUselbPat<v16i8, SELBv16i8>;
-def : SPUselbPat<v8i16, SELBv8i16>;
-def : SPUselbPat<v4i32, SELBv4i32>;
-def : SPUselbPat<v2i64, SELBv2i64>;
+def : SPUselbPatVec<v16i8, SELBv16i8>;
+def : SPUselbPatVec<v8i16, SELBv8i16>;
+def : SPUselbPatVec<v4i32, SELBv4i32>;
+def : SPUselbPatVec<v2i64, SELBv2i64>;
+
+class SPUselbPatReg<RegisterClass rclass, SPUInstr inst>:
+   Pat<(SPUselb rclass:$rA, rclass:$rB, rclass:$rC),
+       (inst rclass:$rA, rclass:$rB, rclass:$rC)>;
+
+def : SPUselbPatReg<R8C,   SELBr8>;
+def : SPUselbPatReg<R16C,  SELBr16>;
+def : SPUselbPatReg<R32C,  SELBr32>;
+def : SPUselbPatReg<R64C,  SELBr64>;
 
 class SelectConditional<RegisterClass rclass, SPUInstr inst>:
     Pat<(select rclass:$rCond, rclass:$rTrue, rclass:$rFalse),
@@ -1811,8 +1820,8 @@
 def : SHUFBVecPat1<v2f64, v16i8, SHUFBv16i8>;
 
 // Shuffle mask is a v4i32 vector:
+def : SHUFBVecPat1<v16i8, v4i32, SHUFBv4i32>;
 def : SHUFBVecPat1<v8i16, v4i32, SHUFBv4i32>;
-def : SHUFBVecPat1<v4i32, v4i32, SHUFBv4i32>;
 def : SHUFBVecPat1<v2i64, v4i32, SHUFBv4i32>;
 def : SHUFBVecPat1<v4f32, v4i32, SHUFBv4i32>;
 def : SHUFBVecPat1<v2f64, v4i32, SHUFBv4i32>;
@@ -1939,7 +1948,9 @@
   def v16i8: SHLQBIVecInst<v16i8>;
   def v8i16: SHLQBIVecInst<v8i16>;
   def v4i32: SHLQBIVecInst<v4i32>;
+  def v4f32: SHLQBIVecInst<v4f32>;
   def v2i64: SHLQBIVecInst<v2i64>;
+  def v2f64: SHLQBIVecInst<v2f64>;
 }
 
 defm SHLQBI : ShiftLeftQuadByBits;
@@ -1960,7 +1971,9 @@
   def v16i8 : SHLQBIIVecInst<v16i8>;
   def v8i16 : SHLQBIIVecInst<v8i16>;
   def v4i32 : SHLQBIIVecInst<v4i32>;
+  def v4f32 : SHLQBIIVecInst<v4f32>;
   def v2i64 : SHLQBIIVecInst<v2i64>;
+  def v2f64 : SHLQBIIVecInst<v2f64>;
 }
 
 defm SHLQBII : ShiftLeftQuadByBitsImm;
@@ -1982,7 +1995,9 @@
   def v16i8: SHLQBYVecInst<v16i8>;
   def v8i16: SHLQBYVecInst<v8i16>;
   def v4i32: SHLQBYVecInst<v4i32>;
+  def v4f32: SHLQBYVecInst<v4f32>;
   def v2i64: SHLQBYVecInst<v2i64>;
+  def v2f64: SHLQBYVecInst<v2f64>;
   def r128: SHLQBYInst<(outs GPRC:$rT), (ins GPRC:$rA, R32C:$rB),
                        [(set GPRC:$rT, (SPUshlquad_l_bytes GPRC:$rA, R32C:$rB))]>;
 }
@@ -2003,7 +2018,9 @@
   def v16i8: SHLQBYIVecInst<v16i8>;
   def v8i16: SHLQBYIVecInst<v8i16>;
   def v4i32: SHLQBYIVecInst<v4i32>;
+  def v4f32: SHLQBYIVecInst<v4f32>;
   def v2i64: SHLQBYIVecInst<v2i64>;
+  def v2f64: SHLQBYIVecInst<v2f64>;
   def r128:  SHLQBYIInst<(outs GPRC:$rT), (ins GPRC:$rA, u7imm_i32:$val),
                          [(set GPRC:$rT,
                                (SPUshlquad_l_bytes GPRC:$rA, (i32 uimm7:$val)))]>;

Modified: llvm/trunk/lib/Target/CellSPU/SPUNodes.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/CellSPU/SPUNodes.td?rev=59891&r1=59890&r2=59891&view=diff

==============================================================================
--- llvm/trunk/lib/Target/CellSPU/SPUNodes.td (original)
+++ llvm/trunk/lib/Target/CellSPU/SPUNodes.td Sat Nov 22 17:50:42 2008
@@ -16,7 +16,7 @@
 
 // SPU_GenControl: Type profile for generating control words for insertions
 def SPU_GenControl : SDTypeProfile<1, 1, []>;
-def SPUvecinsmask : SDNode<"SPUISD::INSERT_MASK", SPU_GenControl, []>;
+def SPUshufmask    : SDNode<"SPUISD::SHUFFLE_MASK", SPU_GenControl, []>;
 
 def callseq_start : SDNode<"ISD::CALLSEQ_START", SDT_SPUCallSeq,
                            [SDNPHasChain, SDNPOutFlag]>;

Modified: llvm/trunk/test/CodeGen/CellSPU/extract_elt.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/CellSPU/extract_elt.ll?rev=59891&r1=59890&r2=59891&view=diff

==============================================================================
--- llvm/trunk/test/CodeGen/CellSPU/extract_elt.ll (original)
+++ llvm/trunk/test/CodeGen/CellSPU/extract_elt.ll Sat Nov 22 17:50:42 2008
@@ -1,10 +1,36 @@
 ; RUN: llvm-as -o - %s | llc -march=cellspu > %t1.s
-; RUN: llvm-as -o - %s | llc -march=cellspu -mattr=large_mem > %t2.s
-; RUN: grep shufb %t1.s | count 27
-; RUN: grep   lqa %t1.s | count 27
-; RUN: grep   lqd %t2.s | count 27
-; RUN: grep space %t1.s | count 8
-; RUN: grep  byte %t1.s | count 424
+; RUN: grep shufb   %t1.s | count 39
+; RUN: grep ilhu    %t1.s | count 31
+; RUN: grep iohl    %t1.s | count 31
+; RUN: grep lqa     %t1.s | count 10
+; RUN: grep shlqbyi %t1.s | count 8
+; RUN: grep selb    %t1.s | count 4
+; RUN: grep cgti    %t1.s | count 4
+; RUN: grep   515   %t1.s | count 5
+; RUN: grep  1029   %t1.s | count 2
+; RUN: grep  1543   %t1.s | count 2
+; RUN: grep  2057   %t1.s | count 2
+; RUN: grep  2571   %t1.s | count 2
+; RUN: grep  3085   %t1.s | count 2
+; RUN: grep  3599   %t1.s | count 2
+; RUN: grep 32768   %t1.s | count 1
+; RUN: grep 32769   %t1.s | count 1
+; RUN: grep 32770   %t1.s | count 1
+; RUN: grep 32771   %t1.s | count 1
+; RUN: grep 32772   %t1.s | count 1
+; RUN: grep 32773   %t1.s | count 1
+; RUN: grep 32774   %t1.s | count 1
+; RUN: grep 32775   %t1.s | count 1
+; RUN: grep 32776   %t1.s | count 1
+; RUN: grep 32777   %t1.s | count 1
+; RUN: grep 32778   %t1.s | count 1
+; RUN: grep 32779   %t1.s | count 1
+; RUN: grep 32780   %t1.s | count 1
+; RUN: grep 32781   %t1.s | count 1
+; RUN: grep 32782   %t1.s | count 1
+; RUN: grep 32783   %t1.s | count 1
+; RUN: grep 32896   %t1.s | count 24
+
 target datalayout = "E-p:32:32:128-f64:64:128-f32:32:128-i64:32:128-i32:32:128-i16:16:128-i8:8:128-i1:8:128-a0:0:128-v128:128:128-s0:128:128"
 target triple = "spu"
 
@@ -175,3 +201,79 @@
   %a = extractelement <16 x i8> %v, i32 15
   ret i8 %a
 }
+
+;;--------------------------------------------------------------------------
+;; extract element, variable index:
+;;--------------------------------------------------------------------------
+
+define i8 @extract_varadic_i8(i32 %i) nounwind readnone {
+entry:
+        %0 = extractelement <16 x i8> < i8 0, i8 1, i8 2, i8 3, i8 4, i8 5, i8 6, i8 7, i8 8, i8 9, i8 10, i8 11, i8 12, i8 13, i8 14, i8 15>, i32 %i
+        ret i8 %0
+}
+
+define i8 @extract_varadic_i8_1(<16 x i8> %v, i32 %i) nounwind readnone {
+entry:
+        %0 = extractelement <16 x i8> %v, i32 %i
+        ret i8 %0
+}
+
+define i16 @extract_varadic_i16(i32 %i) nounwind readnone {
+entry:
+        %0 = extractelement <8 x i16> < i16 0, i16 1, i16 2, i16 3, i16 4, i16 5, i16 6, i16 7>, i32 %i
+        ret i16 %0
+}
+
+define i16 @extract_varadic_i16_1(<8 x i16> %v, i32 %i) nounwind readnone {
+entry:
+        %0 = extractelement <8 x i16> %v, i32 %i
+        ret i16 %0
+}
+
+define i32 @extract_varadic_i32(i32 %i) nounwind readnone {
+entry:
+        %0 = extractelement <4 x i32> < i32 0, i32 1, i32 2, i32 3>, i32 %i
+        ret i32 %0
+}
+
+define i32 @extract_varadic_i32_1(<4 x i32> %v, i32 %i) nounwind readnone {
+entry:
+        %0 = extractelement <4 x i32> %v, i32 %i
+        ret i32 %0
+}
+
+define float @extract_varadic_f32(i32 %i) nounwind readnone {
+entry:
+        %0 = extractelement <4 x float> < float 1.000000e+00, float 2.000000e+00, float 3.000000e+00, float 4.000000e+00 >, i32 %i
+        ret float %0
+}
+
+define float @extract_varadic_f32_1(<4 x float> %v, i32 %i) nounwind readnone {
+entry:
+        %0 = extractelement <4 x float> %v, i32 %i
+        ret float %0
+}
+
+define i64 @extract_varadic_i64(i32 %i) nounwind readnone {
+entry:
+        %0 = extractelement <2 x i64> < i64 0, i64 1>, i32 %i
+        ret i64 %0
+}
+
+define i64 @extract_varadic_i64_1(<2 x i64> %v, i32 %i) nounwind readnone {
+entry:
+        %0 = extractelement <2 x i64> %v, i32 %i
+        ret i64 %0
+}
+
+define double @extract_varadic_f64(i32 %i) nounwind readnone {
+entry:
+        %0 = extractelement <2 x double> < double 1.000000e+00, double 2.000000e+00>, i32 %i
+        ret double %0
+}
+
+define double @extract_varadic_f64_1(<2 x double> %v, i32 %i) nounwind readnone {
+entry:
+        %0 = extractelement <2 x double> %v, i32 %i
+        ret double %0
+}





More information about the llvm-commits mailing list