Give TargetLowering::getSetCCResultType() a parameter so that ISD::SETCC's
[oota-llvm.git] / lib / CodeGen / SelectionDAG / LegalizeTypesPromote.cpp
index 3dab01a981df6197edc8bbf6bd3838d6dfe959f8..2b1a29d77cccf39953c2ee9f6ed476d68b987341 100644 (file)
@@ -49,6 +49,8 @@ void DAGTypeLegalizer::PromoteResult(SDNode *N, unsigned ResNo) {
   case ISD::FP_TO_UINT:  Result = PromoteResult_FP_TO_XINT(N); break;
   case ISD::SETCC:    Result = PromoteResult_SETCC(N); break;
   case ISD::LOAD:     Result = PromoteResult_LOAD(cast<LoadSDNode>(N)); break;
+  case ISD::BUILD_PAIR:  Result = PromoteResult_BUILD_PAIR(N); break;
+  case ISD::BIT_CONVERT: Result = PromoteResult_BIT_CONVERT(N); break;
 
   case ISD::AND:
   case ISD::OR:
@@ -73,8 +75,12 @@ void DAGTypeLegalizer::PromoteResult(SDNode *N, unsigned ResNo) {
   case ISD::CTLZ:     Result = PromoteResult_CTLZ(N); break;
   case ISD::CTPOP:    Result = PromoteResult_CTPOP(N); break;
   case ISD::CTTZ:     Result = PromoteResult_CTTZ(N); break;
+
+  case ISD::EXTRACT_VECTOR_ELT:
+    Result = PromoteResult_EXTRACT_VECTOR_ELT(N);
+    break;
   }      
-  
+
   // If Result is null, the sub-method took care of registering the result.
   if (Result.Val)
     SetPromotedOp(SDOperand(N, ResNo), Result);
@@ -180,9 +186,10 @@ SDOperand DAGTypeLegalizer::PromoteResult_FP_TO_XINT(SDNode *N) {
 }
 
 SDOperand DAGTypeLegalizer::PromoteResult_SETCC(SDNode *N) {
-  assert(isTypeLegal(TLI.getSetCCResultTy()) && "SetCC type is not legal??");
-  return DAG.getNode(ISD::SETCC, TLI.getSetCCResultTy(), N->getOperand(0),
-                     N->getOperand(1), N->getOperand(2));
+  assert(isTypeLegal(TLI.getSetCCResultType(N->getOperand(0)))
+        && "SetCC type is not legal??");
+  return DAG.getNode(ISD::SETCC, TLI.getSetCCResultType(N->getOperand(0)),
+                    N->getOperand(0), N->getOperand(1), N->getOperand(2));
 }
 
 SDOperand DAGTypeLegalizer::PromoteResult_LOAD(LoadSDNode *N) {
@@ -200,6 +207,78 @@ SDOperand DAGTypeLegalizer::PromoteResult_LOAD(LoadSDNode *N) {
   return Res;
 }
 
+SDOperand DAGTypeLegalizer::PromoteResult_BUILD_PAIR(SDNode *N) {
+  // The pair element type may be legal, or may not promote to the same type as
+  // the result, for example i16 = BUILD_PAIR (i8, i8) when i8 is legal but i16
+  // is not.  Handle all cases.
+  MVT::ValueType LVT = N->getOperand(0).getValueType();
+  MVT::ValueType NVT = TLI.getTypeToTransformTo(N->getValueType(0));
+  SDOperand Lo = DAG.getNode(ISD::ZERO_EXTEND, NVT, N->getOperand(0));
+  SDOperand Hi = DAG.getNode(ISD::ANY_EXTEND, NVT, N->getOperand(1));
+  Hi = DAG.getNode(ISD::SHL, NVT, Hi, DAG.getConstant(MVT::getSizeInBits(LVT),
+                                                      TLI.getShiftAmountTy()));
+  return DAG.getNode(ISD::OR, NVT, Lo, Hi);
+}
+
+SDOperand DAGTypeLegalizer::PromoteResult_BIT_CONVERT(SDNode *N) {
+  SDOperand InOp = N->getOperand(0);
+  MVT::ValueType InVT = InOp.getValueType();
+  MVT::ValueType NInVT = TLI.getTypeToTransformTo(InVT);
+  MVT::ValueType OutVT = TLI.getTypeToTransformTo(N->getValueType(0));
+
+  switch (getTypeAction(InVT)) {
+  default:
+    assert(false && "Unknown type action!");
+    break;
+  case Legal:
+    break;
+  case Promote:
+    if (MVT::getSizeInBits(OutVT) == MVT::getSizeInBits(NInVT))
+      // The input promotes to the same size.  Convert the promoted value.
+      return DAG.getNode(ISD::BIT_CONVERT, OutVT, GetPromotedOp(InOp));
+    break;
+  case Expand:
+    break;
+  case Scalarize:
+    // Convert the element to an integer and promote it by hand.
+    InOp = DAG.getNode(ISD::BIT_CONVERT,
+                       MVT::getIntegerType(MVT::getSizeInBits(InVT)),
+                       GetScalarizedOp(InOp));
+    InOp = DAG.getNode(ISD::ANY_EXTEND,
+                       MVT::getIntegerType(MVT::getSizeInBits(OutVT)), InOp);
+    return DAG.getNode(ISD::BIT_CONVERT, OutVT, InOp);
+  case Split:
+    // For example, i32 = BIT_CONVERT v2i16 on alpha.  Convert the split
+    // pieces of the input into integers and reassemble in the final type.
+    SDOperand Lo, Hi;
+    GetSplitOp(N->getOperand(0), Lo, Hi);
+
+    unsigned LoBits = MVT::getSizeInBits(Lo.getValueType());
+    Lo = DAG.getNode(ISD::BIT_CONVERT, MVT::getIntegerType(LoBits), Lo);
+
+    unsigned HiBits = MVT::getSizeInBits(Hi.getValueType());
+    Hi = DAG.getNode(ISD::BIT_CONVERT, MVT::getIntegerType(HiBits), Hi);
+
+    if (TLI.isBigEndian())
+      std::swap(Lo, Hi);
+
+    MVT::ValueType TargetTy = MVT::getIntegerType(MVT::getSizeInBits(OutVT));
+    Hi = DAG.getNode(ISD::ANY_EXTEND, TargetTy, Hi);
+    Hi = DAG.getNode(ISD::SHL, TargetTy, Hi,
+                     DAG.getConstant(MVT::getSizeInBits(Lo.getValueType()),
+                                     TLI.getShiftAmountTy()));
+    Lo = DAG.getNode(ISD::ZERO_EXTEND, TargetTy, Lo);
+
+    return DAG.getNode(ISD::BIT_CONVERT, OutVT,
+                       DAG.getNode(ISD::OR, TargetTy, Lo, Hi));
+  }
+
+  // Otherwise, lower the bit-convert to a store/load from the stack, then
+  // promote the load.
+  SDOperand Op = CreateStackStoreLoad(InOp, N->getValueType(0));
+  return PromoteResult_LOAD(cast<LoadSDNode>(Op.Val));
+}
+
 SDOperand DAGTypeLegalizer::PromoteResult_SimpleIntBinOp(SDNode *N) {
   // The input may have strange things in the top bits of the registers, but
   // these operations don't care.  They may have weird bits going out, but
@@ -301,6 +380,51 @@ SDOperand DAGTypeLegalizer::PromoteResult_CTTZ(SDNode *N) {
   return DAG.getNode(ISD::CTTZ, NVT, Op);
 }
 
+SDOperand DAGTypeLegalizer::PromoteResult_EXTRACT_VECTOR_ELT(SDNode *N) {
+  MVT::ValueType OldVT = N->getValueType(0);
+  SDOperand OldVec = N->getOperand(0);
+  unsigned OldElts = MVT::getVectorNumElements(OldVec.getValueType());
+
+  if (OldElts == 1) {
+    assert(!isTypeLegal(OldVec.getValueType()) &&
+           "Legal one-element vector of a type needing promotion!");
+    // It is tempting to follow GetScalarizedOp by a call to GetPromotedOp,
+    // but this would be wrong because the scalarized value may not yet have
+    // been processed.
+    return DAG.getNode(ISD::ANY_EXTEND, TLI.getTypeToTransformTo(OldVT),
+                       GetScalarizedOp(OldVec));
+  }
+
+  // Convert to a vector half as long with an element type of twice the width,
+  // for example <4 x i16> -> <2 x i32>.
+  assert(!(OldElts & 1) && "Odd length vectors not supported!");
+  MVT::ValueType NewVT = MVT::getIntegerType(2 * MVT::getSizeInBits(OldVT));
+  assert(!MVT::isExtendedVT(OldVT) && !MVT::isExtendedVT(NewVT));
+
+  SDOperand NewVec = DAG.getNode(ISD::BIT_CONVERT,
+                                 MVT::getVectorType(NewVT, OldElts / 2),
+                                 OldVec);
+
+  // Extract the element at OldIdx / 2 from the new vector.
+  SDOperand OldIdx = N->getOperand(1);
+  SDOperand NewIdx = DAG.getNode(ISD::SRL, OldIdx.getValueType(), OldIdx,
+                                 DAG.getConstant(1, TLI.getShiftAmountTy()));
+  SDOperand Elt = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, NewVT, NewVec, NewIdx);
+
+  // Select the appropriate half of the element: Lo if OldIdx was even,
+  // Hi if it was odd.
+  SDOperand Lo = Elt;
+  SDOperand Hi = DAG.getNode(ISD::SRL, NewVT, Elt,
+                             DAG.getConstant(MVT::getSizeInBits(OldVT),
+                                             TLI.getShiftAmountTy()));
+  if (TLI.isBigEndian())
+    std::swap(Lo, Hi);
+
+  SDOperand Odd = DAG.getNode(ISD::AND, OldIdx.getValueType(), OldIdx,
+                              DAG.getConstant(1, TLI.getShiftAmountTy()));
+  return DAG.getNode(ISD::SELECT, NewVT, Odd, Hi, Lo);
+}
+
 //===----------------------------------------------------------------------===//
 //  Operand Promotion
 //===----------------------------------------------------------------------===//
@@ -329,7 +453,8 @@ bool DAGTypeLegalizer::PromoteOperand(SDNode *N, unsigned OpNo) {
   case ISD::FP_ROUND:    Res = PromoteOperand_FP_ROUND(N); break;
   case ISD::SINT_TO_FP:
   case ISD::UINT_TO_FP:  Res = PromoteOperand_INT_TO_FP(N); break;
-    
+  case ISD::BUILD_PAIR:  Res = PromoteOperand_BUILD_PAIR(N); break;
+
   case ISD::SELECT:      Res = PromoteOperand_SELECT(N, OpNo); break;
   case ISD::BRCOND:      Res = PromoteOperand_BRCOND(N, OpNo); break;
   case ISD::BR_CC:       Res = PromoteOperand_BR_CC(N, OpNo); break;
@@ -340,8 +465,17 @@ bool DAGTypeLegalizer::PromoteOperand(SDNode *N, unsigned OpNo) {
   case ISD::MEMSET:
   case ISD::MEMCPY:
   case ISD::MEMMOVE:     Res = HandleMemIntrinsic(N); break;
+
+  case ISD::BUILD_VECTOR: Res = PromoteOperand_BUILD_VECTOR(N); break;
+  case ISD::INSERT_VECTOR_ELT:
+    Res = PromoteOperand_INSERT_VECTOR_ELT(N, OpNo);
+    break;
+
+  case ISD::RET:         Res = PromoteOperand_RET(N, OpNo); break;
+
+  case ISD::MEMBARRIER:  Res = PromoteOperand_MEMBARRIER(N); break;
   }
-  
+
   // If the result is null, the sub-method took care of registering results etc.
   if (!Res.Val) return false;
   // If the result is N, the sub-method updated N in place.
@@ -349,11 +483,10 @@ bool DAGTypeLegalizer::PromoteOperand(SDNode *N, unsigned OpNo) {
     // Mark N as new and remark N and its operands.  This allows us to correctly
     // revisit N if it needs another step of promotion and allows us to visit
     // any new operands to N.
-    N->setNodeId(NewNode);
-    MarkNewNodes(N);
+    ReanalyzeNode(N);
     return true;
   }
-  
+
   assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 &&
          "Invalid operand expansion");
   
@@ -407,17 +540,30 @@ SDOperand DAGTypeLegalizer::PromoteOperand_INT_TO_FP(SDNode *N) {
   return DAG.UpdateNodeOperands(SDOperand(N, 0), In);
 }
 
+SDOperand DAGTypeLegalizer::PromoteOperand_BUILD_PAIR(SDNode *N) {
+  // Since the result type is legal, the operands must promote to it.
+  MVT::ValueType OVT = N->getOperand(0).getValueType();
+  SDOperand Lo = GetPromotedOp(N->getOperand(0));
+  SDOperand Hi = GetPromotedOp(N->getOperand(1));
+  assert(Lo.getValueType() == N->getValueType(0) && "Operand over promoted?");
+
+  Lo = DAG.getZeroExtendInReg(Lo, OVT);
+  Hi = DAG.getNode(ISD::SHL, N->getValueType(0), Hi,
+                   DAG.getConstant(MVT::getSizeInBits(OVT),
+                                   TLI.getShiftAmountTy()));
+  return DAG.getNode(ISD::OR, N->getValueType(0), Lo, Hi);
+}
+
 SDOperand DAGTypeLegalizer::PromoteOperand_SELECT(SDNode *N, unsigned OpNo) {
   assert(OpNo == 0 && "Only know how to promote condition");
   SDOperand Cond = GetPromotedOp(N->getOperand(0));  // Promote the condition.
 
   // The top bits of the promoted condition are not necessarily zero, ensure
   // that the value is properly zero extended.
+  unsigned BitWidth = Cond.getValueSizeInBits();
   if (!DAG.MaskedValueIsZero(Cond, 
-                             MVT::getIntVTBitMask(Cond.getValueType())^1)) {
+                             APInt::getHighBitsSet(BitWidth, BitWidth-1)))
     Cond = DAG.getZeroExtendInReg(Cond, MVT::i1);
-    MarkNewNodes(Cond.Val); 
-  }
 
   // The chain (Op#0) and basic block destination (Op#2) are always legal types.
   return DAG.UpdateNodeOperands(SDOperand(N, 0), Cond, N->getOperand(1),
@@ -430,12 +576,11 @@ SDOperand DAGTypeLegalizer::PromoteOperand_BRCOND(SDNode *N, unsigned OpNo) {
   
   // The top bits of the promoted condition are not necessarily zero, ensure
   // that the value is properly zero extended.
+  unsigned BitWidth = Cond.getValueSizeInBits();
   if (!DAG.MaskedValueIsZero(Cond, 
-                             MVT::getIntVTBitMask(Cond.getValueType())^1)) {
+                             APInt::getHighBitsSet(BitWidth, BitWidth-1)))
     Cond = DAG.getZeroExtendInReg(Cond, MVT::i1);
-    MarkNewNodes(Cond.Val); 
-  }
-  
+
   // The chain (Op#0) and basic block destination (Op#2) are always legal types.
   return DAG.UpdateNodeOperands(SDOperand(N, 0), N->getOperand(0), Cond,
                                 N->getOperand(2));
@@ -524,3 +669,96 @@ SDOperand DAGTypeLegalizer::PromoteOperand_STORE(StoreSDNode *N, unsigned OpNo){
                            SVOffset, N->getMemoryVT(),
                            isVolatile, Alignment);
 }
+
+SDOperand DAGTypeLegalizer::PromoteOperand_BUILD_VECTOR(SDNode *N) {
+  // The vector type is legal but the element type is not.  This implies
+  // that the vector is a power-of-two in length and that the element
+  // type does not have a strange size (eg: it is not i1).
+  MVT::ValueType VecVT = N->getValueType(0);
+  unsigned NumElts = MVT::getVectorNumElements(VecVT);
+  assert(!(NumElts & 1) && "Legal vector of one illegal element?");
+
+  // Build a vector of half the length out of elements of twice the bitwidth.
+  // For example <4 x i16> -> <2 x i32>.
+  MVT::ValueType OldVT = N->getOperand(0).getValueType();
+  MVT::ValueType NewVT = MVT::getIntegerType(2 * MVT::getSizeInBits(OldVT));
+  assert(!MVT::isExtendedVT(OldVT) && !MVT::isExtendedVT(NewVT));
+
+  std::vector<SDOperand> NewElts;
+  NewElts.reserve(NumElts/2);
+
+  for (unsigned i = 0; i < NumElts; i += 2) {
+    // Combine two successive elements into one promoted element.
+    SDOperand Lo = N->getOperand(i);
+    SDOperand Hi = N->getOperand(i+1);
+    if (TLI.isBigEndian())
+      std::swap(Lo, Hi);
+    NewElts.push_back(DAG.getNode(ISD::BUILD_PAIR, NewVT, Lo, Hi));
+  }
+
+  SDOperand NewVec = DAG.getNode(ISD::BUILD_VECTOR,
+                                 MVT::getVectorType(NewVT, NewElts.size()),
+                                 &NewElts[0], NewElts.size());
+
+  // Convert the new vector to the old vector type.
+  return DAG.getNode(ISD::BIT_CONVERT, VecVT, NewVec);
+}
+
+SDOperand DAGTypeLegalizer::PromoteOperand_INSERT_VECTOR_ELT(SDNode *N,
+                                                             unsigned OpNo) {
+  if (OpNo == 1) {
+    // Promote the inserted value.  This is valid because the type does not
+    // have to match the vector element type.
+
+    // Check that any extra bits introduced will be truncated away.
+    assert(MVT::getSizeInBits(N->getOperand(1).getValueType()) >=
+           MVT::getSizeInBits(MVT::getVectorElementType(N->getValueType(0))) &&
+           "Type of inserted value narrower than vector element type!");
+    return DAG.UpdateNodeOperands(SDOperand(N, 0), N->getOperand(0),
+                                  GetPromotedOp(N->getOperand(1)),
+                                  N->getOperand(2));
+  }
+
+  assert(OpNo == 2 && "Different operand and result vector types?");
+
+  // Promote the index.
+  SDOperand Idx = N->getOperand(2);
+  Idx = DAG.getZeroExtendInReg(GetPromotedOp(Idx), Idx.getValueType());
+  return DAG.UpdateNodeOperands(SDOperand(N, 0), N->getOperand(0),
+                                N->getOperand(1), Idx);
+}
+
+SDOperand DAGTypeLegalizer::PromoteOperand_RET(SDNode *N, unsigned OpNo) {
+  assert(!(OpNo & 1) && "Return values should be legally typed!");
+  assert((N->getNumOperands() & 1) && "Wrong number of operands!");
+
+  // It's a flag.  Promote all the flags in one hit, as an optimization.
+  SmallVector<SDOperand, 8> NewValues(N->getNumOperands());
+  NewValues[0] = N->getOperand(0); // The chain
+  for (unsigned i = 1, e = N->getNumOperands(); i < e; i += 2) {
+    // The return value.
+    NewValues[i] = N->getOperand(i);
+
+    // The flag.
+    SDOperand Flag = N->getOperand(i + 1);
+    if (getTypeAction(Flag.getValueType()) == Promote)
+      // The promoted value may have rubbish in the new bits, but that
+      // doesn't matter because those bits aren't queried anyway.
+      Flag = GetPromotedOp(Flag);
+    NewValues[i + 1] = Flag;
+  }
+
+  return DAG.UpdateNodeOperands(SDOperand (N, 0),
+                                &NewValues[0], NewValues.size());
+}
+
+SDOperand DAGTypeLegalizer::PromoteOperand_MEMBARRIER(SDNode *N) {
+  SDOperand NewOps[6];
+  NewOps[0] = N->getOperand(0);
+  for (unsigned i = 1; i < array_lengthof(NewOps); ++i) {
+    SDOperand Flag = GetPromotedOp(N->getOperand(i));
+    NewOps[i] = DAG.getZeroExtendInReg(Flag, MVT::i1);
+  }
+  return DAG.UpdateNodeOperands(SDOperand (N, 0), NewOps,
+                                array_lengthof(NewOps));
+}