CellSPU:
- Rename fcmp.ll test to fcmp32.ll, start adding new double tests to fcmp64.ll
- Fix select_bits.ll test
- Capitulate to the DAGCombiner and move i64 constant loads to instruction
  selection (SPUISelDAGtoDAG.cpp).

  <rant>DAGCombiner will insert all kinds of 64-bit optimizations after
  operation legalization occurs and now we have to do most of the work that
  instruction selection should be doing twice (once to determine if v2i64
  build_vector can be handled by SelectCode(), which then runs all of the
  predicates a second time to select the necessary instructions.) But,
  CellSPU is a good citizen.</rant>


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@62990 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Target/CellSPU/SPUISelDAGToDAG.cpp b/lib/Target/CellSPU/SPUISelDAGToDAG.cpp
index 0fc7aec..6d7f40d 100644
--- a/lib/Target/CellSPU/SPUISelDAGToDAG.cpp
+++ b/lib/Target/CellSPU/SPUISelDAGToDAG.cpp
@@ -254,26 +254,56 @@
   /// getSmallIPtrImm - Return a target constant of pointer type.
   inline SDValue getSmallIPtrImm(unsigned Imm) {
     return CurDAG->getTargetConstant(Imm, SPUtli.getPointerTy());
-  }
+    }
 
   SDNode *emitBuildVector(SDValue build_vec) {
+    MVT vecVT = build_vec.getValueType();
+    SDNode *bvNode = build_vec.getNode();
+    bool canBeSelected = false;
+
+    // Check to see if this vector can be represented as a CellSPU immediate
+    // constant.
+    if (vecVT == MVT::v8i16) {
+      if (SPU::get_vec_i16imm(bvNode, *CurDAG, MVT::i16).getNode() != 0) {
+        canBeSelected = true;
+      }
+    } else if (vecVT == MVT::v4i32) {
+      if ((SPU::get_vec_i16imm(bvNode, *CurDAG, MVT::i32).getNode() != 0)
+          || (SPU::get_ILHUvec_imm(bvNode, *CurDAG, MVT::i32).getNode() != 0)
+          || (SPU::get_vec_u18imm(bvNode, *CurDAG, MVT::i32).getNode() != 0)
+          || (SPU::get_v4i32_imm(bvNode, *CurDAG).getNode() != 0)) {
+        canBeSelected = true;
+      }
+    } else if (vecVT == MVT::v2i64) {
+      if ((SPU::get_vec_i16imm(bvNode, *CurDAG, MVT::i64).getNode() != 0)
+          || (SPU::get_ILHUvec_imm(bvNode, *CurDAG, MVT::i64).getNode() != 0)
+          || (SPU::get_vec_u18imm(bvNode, *CurDAG, MVT::i64).getNode() != 0)) {
+        canBeSelected = true;
+      }
+    }
+
+    if (canBeSelected) {
+      return Select(build_vec);
+    }
+
+    // No, need to emit a constant pool spill:
     std::vector<Constant*> CV;
 
     for (size_t i = 0; i < build_vec.getNumOperands(); ++i) {
-      ConstantSDNode *V = dyn_cast<ConstantSDNode>(build_vec.getOperand(i));
-      CV.push_back(const_cast<ConstantInt *>(V->getConstantIntValue()));
+      ConstantSDNode *V = dyn_cast<ConstantSDNode > (build_vec.getOperand(i));
+      CV.push_back(const_cast<ConstantInt *> (V->getConstantIntValue()));
     }
 
     Constant *CP = ConstantVector::get(CV);
     SDValue CPIdx = CurDAG->getConstantPool(CP, SPUtli.getPointerTy());
-    unsigned Alignment = 1 << cast<ConstantPoolSDNode>(CPIdx)->getAlignment();
+    unsigned Alignment = 1 << cast<ConstantPoolSDNode > (CPIdx)->getAlignment();
     SDValue CGPoolOffset =
             SPU::LowerConstantPool(CPIdx, *CurDAG,
                                    SPUtli.getSPUTargetMachine());
     return SelectCode(CurDAG->getLoad(build_vec.getValueType(),
-                      CurDAG->getEntryNode(), CGPoolOffset,
-                      PseudoSourceValue::getConstantPool(), 0,
-                      false, Alignment));
+                                      CurDAG->getEntryNode(), CGPoolOffset,
+                                      PseudoSourceValue::getConstantPool(), 0,
+                                      false, Alignment));
   }
 
   /// Select - Convert the specified operand from a target-independent to a
@@ -289,6 +319,9 @@
   //! Emit the instruction sequence for i64 sra
   SDNode *SelectSRAi64(SDValue &Op, MVT OpVT);
 
+  //! Emit the necessary sequence for loading i64 constants:
+  SDNode *SelectI64Constant(SDValue &Op, MVT OpVT);
+
   //! Returns true if the address N is an A-form (local store) address
   bool SelectAFormAddr(SDValue Op, SDValue N, SDValue &Base,
                        SDValue &Index);
@@ -652,7 +685,9 @@
 
   if (N->isMachineOpcode()) {
     return NULL;   // Already selected.
-  } else if (Opc == ISD::FrameIndex) {
+  }
+
+  if (Opc == ISD::FrameIndex) {
     int FI = cast<FrameIndexSDNode>(N)->getIndex();
     SDValue TFI = CurDAG->getTargetFrameIndex(FI, Op.getValueType());
     SDValue Imm0 = CurDAG->getTargetConstant(0, Op.getValueType());
@@ -669,6 +704,11 @@
                                              TFI, Imm0), 0);
       n_ops = 2;
     }
+  } else if (Opc == ISD::Constant && OpVT == MVT::i64) {
+    // Catch the i64 constants that end up here. Note: The backend doesn't
+    // attempt to legalize the constant (it's useless because DAGCombiner
+    // will insert 64-bit constants and we can't stop it).
+    return SelectI64Constant(Op, OpVT);
   } else if ((Opc == ISD::ZERO_EXTEND || Opc == ISD::ANY_EXTEND)
              && OpVT == MVT::i64) {
     SDValue Op0 = Op.getOperand(0);
@@ -745,27 +785,38 @@
     return SelectCode(CurDAG->getNode(SPUISD::MUL64_MARKER, OpVT,
                                       Op.getOperand(0), Op.getOperand(1),
                                       SDValue(CGLoad, 0)));
-  } else if (Opc == ISD::ADD && (OpVT == MVT::i64 || OpVT == MVT::v2i64)) {
-    SDNode *CGLoad =
-            emitBuildVector(SPU::getCarryGenerateShufMask(*CurDAG));
+  } else if (Opc == ISD::TRUNCATE) {
+    SDValue Op0 = Op.getOperand(0);
+    if ((Op0.getOpcode() == ISD::SRA || Op0.getOpcode() == ISD::SRL)
+        && OpVT == MVT::i32
+        && Op0.getValueType() == MVT::i64) {
+      // Catch the (truncate:i32 ([sra|srl]:i64 arg, c), where c >= 32 to
+      // take advantage of the fact that the upper 32 bits are in the
+      // i32 preferred slot and avoid all kinds of other shuffle gymnastics:
+      ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Op0.getOperand(1));
+      if (CN != 0) {
+        unsigned shift_amt = unsigned(CN->getZExtValue());
 
-    return SelectCode(CurDAG->getNode(SPUISD::ADD64_MARKER, OpVT,
-                                      Op.getOperand(0), Op.getOperand(1),
-                                      SDValue(CGLoad, 0)));
-  } else if (Opc == ISD::SUB && (OpVT == MVT::i64 || OpVT == MVT::v2i64)) {
-    SDNode *CGLoad =
-            emitBuildVector(SPU::getBorrowGenerateShufMask(*CurDAG));
+        if (shift_amt >= 32) {
+          SDNode *hi32 =
+                  CurDAG->getTargetNode(SPU::ORr32_r64, OpVT, Op0.getOperand(0));
 
-    return SelectCode(CurDAG->getNode(SPUISD::SUB64_MARKER, OpVT,
-                                      Op.getOperand(0), Op.getOperand(1),
-                                      SDValue(CGLoad, 0)));
-  } else if (Opc == ISD::MUL && (OpVT == MVT::i64 || OpVT == MVT::v2i64)) {
-    SDNode *CGLoad =
-            emitBuildVector(SPU::getCarryGenerateShufMask(*CurDAG));
+          shift_amt -= 32;
+          if (shift_amt > 0) {
+            // Take care of the additional shift, if present:
+            SDValue shift = CurDAG->getTargetConstant(shift_amt, MVT::i32);
+            unsigned Opc = SPU::ROTMAIr32_i32;
+          
+            if (Op0.getOpcode() == ISD::SRL)
+              Opc = SPU::ROTMr32;
 
-    return SelectCode(CurDAG->getNode(SPUISD::MUL64_MARKER, OpVT,
-                                      Op.getOperand(0), Op.getOperand(1),
-                                      SDValue(CGLoad, 0)));
+            hi32 = CurDAG->getTargetNode(Opc, OpVT, SDValue(hi32, 0), shift);
+          }
+
+          return hi32;
+        }
+      }
+    }
   } else if (Opc == ISD::SHL) {
     if (OpVT == MVT::i64) {
       return SelectSHLi64(Op, OpVT);
@@ -1046,6 +1097,70 @@
   return CurDAG->getTargetNode(SPU::ORi64_v2i64, OpVT, SDValue(Shift, 0));
 }
 
+/*!
+ Do the necessary magic necessary to load a i64 constant
+ */
+SDNode *SPUDAGToDAGISel::SelectI64Constant(SDValue& Op, MVT OpVT) {
+  ConstantSDNode *CN = cast<ConstantSDNode>(Op.getNode());
+  MVT OpVecVT = MVT::getVectorVT(OpVT, 2);
+  SDValue i64vec =
+          SPU::LowerSplat_v2i64(OpVecVT, *CurDAG, CN->getZExtValue());
+
+  // Here's where it gets interesting, because we have to parse out the
+  // subtree handed back in i64vec:
+
+  if (i64vec.getOpcode() == ISD::BIT_CONVERT) {
+    // The degenerate case where the upper and lower bits in the splat are
+    // identical:
+    SDValue Op0 = i64vec.getOperand(0);
+    ReplaceUses(i64vec, Op0);
+
+    return CurDAG->getTargetNode(SPU::ORi64_v2i64, OpVT,
+                                 SDValue(emitBuildVector(Op0), 0));
+  } else if (i64vec.getOpcode() == SPUISD::SHUFB) {
+    SDValue lhs = i64vec.getOperand(0);
+    SDValue rhs = i64vec.getOperand(1);
+    SDValue shufmask = i64vec.getOperand(2);
+
+    if (lhs.getOpcode() == ISD::BIT_CONVERT) {
+      ReplaceUses(lhs, lhs.getOperand(0));
+      lhs = lhs.getOperand(0);
+    }
+
+    SDNode *lhsNode = (lhs.getNode()->isMachineOpcode()
+                       ? lhs.getNode()
+                       : emitBuildVector(lhs));
+
+    if (rhs.getOpcode() == ISD::BIT_CONVERT) {
+      ReplaceUses(rhs, rhs.getOperand(0));
+      rhs = rhs.getOperand(0);
+    }
+
+    SDNode *rhsNode = (rhs.getNode()->isMachineOpcode()
+                       ? rhs.getNode()
+                       : emitBuildVector(rhs));
+    
+    if (shufmask.getOpcode() == ISD::BIT_CONVERT) {
+      ReplaceUses(shufmask, shufmask.getOperand(0));
+      shufmask = shufmask.getOperand(0);
+    }
+
+    SDNode *shufMaskNode = (shufmask.getNode()->isMachineOpcode()
+                            ? shufmask.getNode()
+                            : emitBuildVector(shufmask));
+
+    SDNode *shufNode =
+            Select(CurDAG->getNode(SPUISD::SHUFB, OpVecVT,
+                                   SDValue(lhsNode, 0), SDValue(rhsNode, 0),
+                                   SDValue(shufMaskNode, 0)));
+
+    return CurDAG->getTargetNode(SPU::ORi64_v2i64, OpVT, SDValue(shufNode, 0));
+  } else {
+    cerr << "SPUDAGToDAGISel::SelectI64Constant: Unhandled i64vec condition\n";
+    abort();
+  }
+}
+
 /// createSPUISelDag - This pass converts a legalized DAG into a
 /// SPU-specific DAG, ready for instruction scheduling.
 ///