Fix thinko - the operand number has nothing to do
[oota-llvm.git] / lib / CodeGen / SelectionDAG / SelectionDAG.cpp
index 37297d6dccd448bfb2cbf625d7be26bfdbb21661..758f112f78c6e83e4318b50f7c67da32ed994792 100644 (file)
 #include <cmath>
 using namespace llvm;
 
-static cl::opt<bool>
-NoBuiltin("no-builtin", cl::init(false),
-           cl::desc("Don't recognize built-in functions that do not begin "
-                    "with `__builtin_' as prefix"));
-
 /// makeVTList - Return an instance of the SDVTList struct initialized with the
 /// specified members.
 static SDVTList makeVTList(const MVT *VTs, unsigned NumVTs) {
@@ -89,8 +84,10 @@ bool ConstantFPSDNode::isValueValidForType(MVT VT,
   
   // convert modifies in place, so make a copy.
   APFloat Val2 = APFloat(Val);
-  return Val2.convert(*MVTToAPFloatSemantics(VT),
-                      APFloat::rmNearestTiesToEven) == APFloat::opOK;
+  bool losesInfo;
+  (void) Val2.convert(*MVTToAPFloatSemantics(VT), APFloat::rmNearestTiesToEven,
+                      &losesInfo);
+  return !losesInfo;
 }
 
 //===----------------------------------------------------------------------===//
@@ -123,7 +120,7 @@ bool ISD::isBuildVectorAllOnes(const SDNode *N) {
       return false;
   } else if (isa<ConstantFPSDNode>(NotZero)) {
     if (!cast<ConstantFPSDNode>(NotZero)->getValueAPF().
-                convertToAPInt().isAllOnesValue())
+                bitcastToAPInt().isAllOnesValue())
       return false;
   } else
     return false;
@@ -219,7 +216,7 @@ ISD::CondCode ISD::getSetCCSwappedOperands(ISD::CondCode Operation) {
   unsigned OldG = (Operation >> 1) & 1;
   return ISD::CondCode((Operation & ~6) |  // Keep the N, U, E bits
                        (OldL << 1) |       // New G bit
-                       (OldG << 2));        // New L bit.
+                       (OldG << 2));       // New L bit.
 }
 
 /// getSetCCInverse - Return the operation corresponding to !(X op Y), where
@@ -230,8 +227,10 @@ ISD::CondCode ISD::getSetCCInverse(ISD::CondCode Op, bool isInteger) {
     Operation ^= 7;   // Flip L, G, E bits, but not U.
   else
     Operation ^= 15;  // Flip all of the condition bits.
+
   if (Operation > ISD::SETTRUE2)
-    Operation &= ~8;     // Don't let N and U bits get set.
+    Operation &= ~8;  // Don't let N and U bits get set.
+
   return ISD::CondCode(Operation);
 }
 
@@ -509,7 +508,8 @@ static void AddNodeIDNode(FoldingSetNodeID &ID, const SDNode *N) {
 /// encodeMemSDNodeFlags - Generic routine for computing a value for use in
 /// the CSE map that carries both alignment and volatility information.
 ///
-static unsigned encodeMemSDNodeFlags(bool isVolatile, unsigned Alignment) {
+static inline unsigned
+encodeMemSDNodeFlags(bool isVolatile, unsigned Alignment) {
   return isVolatile | ((Log2_32(Alignment) + 1) << 1);
 }
 
@@ -564,9 +564,10 @@ void SelectionDAG::RemoveDeadNodes(SmallVectorImpl<SDNode *> &DeadNodes,
       if (Operand->use_empty())
         DeadNodes.push_back(Operand);
     }
-    if (N->OperandsNeedDelete) {
+
+    if (N->OperandsNeedDelete)
       delete[] N->OperandList;
-    }
+
     N->OperandList = 0;
     N->NumOperands = 0;
     
@@ -592,12 +593,14 @@ void SelectionDAG::DeleteNode(SDNode *N) {
 }
 
 void SelectionDAG::DeleteNodeNotInCSEMaps(SDNode *N) {
-
   // Drop all of the operands and decrement used node's use counts.
   for (SDNode::op_iterator I = N->op_begin(), E = N->op_end(); I != E; ++I)
     I->getVal()->removeUser(std::distance(N->op_begin(), I), N);
-  if (N->OperandsNeedDelete)
+
+  if (N->OperandsNeedDelete) {
     delete[] N->OperandList;
+    N->OperandList = 0;
+  }
   
   assert(N != AllNodes.begin());
   NodeAllocator.Deallocate(AllNodes.remove(N));
@@ -678,13 +681,13 @@ SDNode *SelectionDAG::AddNonLeafNodeToCSEMaps(SDNode *N) {
   case ISD::DBG_STOPPOINT:
   case ISD::EH_LABEL:
   case ISD::DECLARE:
-    return 0;    // Never add these nodes.
+    return 0;   // Never add these nodes.
   }
   
   // Check that remaining values produced are not flags.
   for (unsigned i = 1, e = N->getNumValues(); i != e; ++i)
     if (N->getValueType(i) == MVT::Flag)
-      return 0;   // Never CSE anything that produces a flag.
+      return 0; // Never CSE anything that produces a flag.
   
   SDNode *New = CSEMap.GetOrInsertNode(N);
   if (New != N) return New;  // Node already existed.
@@ -706,13 +709,13 @@ SDNode *SelectionDAG::FindModifiedNodeSlot(SDNode *N, SDValue Op,
   case ISD::DBG_LABEL:
   case ISD::DBG_STOPPOINT:
   case ISD::EH_LABEL:
-    return 0;    // Never add these nodes.
+    return 0;   // Never add these nodes.
   }
   
   // Check that remaining values produced are not flags.
   for (unsigned i = 1, e = N->getNumValues(); i != e; ++i)
     if (N->getValueType(i) == MVT::Flag)
-      return 0;   // Never CSE anything that produces a flag.
+      return 0; // Never CSE anything that produces a flag.
   
   SDValue Ops[] = { Op };
   FoldingSetNodeID ID;
@@ -732,7 +735,7 @@ SDNode *SelectionDAG::FindModifiedNodeSlot(SDNode *N,
   // Check that remaining values produced are not flags.
   for (unsigned i = 1, e = N->getNumValues(); i != e; ++i)
     if (N->getValueType(i) == MVT::Flag)
-      return 0;   // Never CSE anything that produces a flag.
+      return 0; // Never CSE anything that produces a flag.
                                               
   SDValue Ops[] = { Op1, Op2 };
   FoldingSetNodeID ID;
@@ -758,13 +761,13 @@ SDNode *SelectionDAG::FindModifiedNodeSlot(SDNode *N,
   case ISD::DBG_STOPPOINT:
   case ISD::EH_LABEL:
   case ISD::DECLARE:
-    return 0;    // Never add these nodes.
+    return 0;   // Never add these nodes.
   }
   
   // Check that remaining values produced are not flags.
   for (unsigned i = 1, e = N->getNumValues(); i != e; ++i)
     if (N->getValueType(i) == MVT::Flag)
-      return 0;   // Never CSE anything that produces a flag.
+      return 0; // Never CSE anything that produces a flag.
   
   FoldingSetNodeID ID;
   AddNodeIDNode(ID, N->getOpcode(), N->getVTList(), Ops, NumOps);
@@ -794,10 +797,14 @@ void SelectionDAG::VerifyNode(SDNode *N) {
     assert(N->getValueType(0).isVector() && "Wrong BUILD_VECTOR return type!");
     assert(N->getNumOperands() == N->getValueType(0).getVectorNumElements() &&
            "Wrong number of BUILD_VECTOR operands!");
-    MVT EltVT = N->getValueType(0).getVectorElementType();
-    for (SDNode::op_iterator I = N->op_begin(), E = N->op_end(); I != E; ++I)
-      assert(I->getSDValue().getValueType() == EltVT &&
-             "Wrong BUILD_VECTOR operand type!");
+    // FIXME: Change vector_shuffle to a variadic node with mask elements being
+    // operands of the node.  Currently the mask is a BUILD_VECTOR passed as an
+    // operand, and it is not always possible to legalize it.  Turning off the
+    // following checks at least makes it possible to legalize most of the time.
+//    MVT EltVT = N->getValueType(0).getVectorElementType();
+//    for (SDNode::op_iterator I = N->op_begin(), E = N->op_end(); I != E; ++I)
+//      assert(I->getSDValue().getValueType() == EltVT &&
+//             "Wrong BUILD_VECTOR operand type!");
     break;
   }
   }
@@ -836,8 +843,12 @@ void SelectionDAG::allnodes_clear() {
   while (!AllNodes.empty()) {
     SDNode *N = AllNodes.remove(AllNodes.begin());
     N->SetNextInBucket(0);
-    if (N->OperandsNeedDelete)
+
+    if (N->OperandsNeedDelete) {
       delete [] N->OperandList;
+      N->OperandList = 0;
+    }
+
     NodeAllocator.Deallocate(N);
   }
 }
@@ -962,10 +973,15 @@ SDValue SelectionDAG::getConstantFP(double Val, MVT VT, bool isTarget) {
 }
 
 SDValue SelectionDAG::getGlobalAddress(const GlobalValue *GV,
-                                       MVT VT, int Offset,
+                                       MVT VT, int64_t Offset,
                                        bool isTargetGA) {
   unsigned Opc;
 
+  // Truncate (with sign-extension) the offset value to the pointer size.
+  unsigned BitWidth = TLI.getPointerTy().getSizeInBits();
+  if (BitWidth < 64)
+    Offset = (Offset << (64 - BitWidth) >> (64 - BitWidth));
+
   const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV);
   if (!GVar) {
     // If GV is an alias then use the aliasee for determining thread-localness.
@@ -2020,6 +2036,7 @@ unsigned SelectionDAG::ComputeNumSignBits(SDValue Op, unsigned Depth) const{
 bool SelectionDAG::isVerifiedDebugInfoDesc(SDValue Op) const {
   GlobalAddressSDNode *GA = dyn_cast<GlobalAddressSDNode>(Op);
   if (!GA) return false;
+  if (GA->getOffset() != 0) return false;
   GlobalVariable *GV = dyn_cast<GlobalVariable>(GA->getGlobal());
   if (!GV) return false;
   MachineModuleInfo *MMI = getMachineModuleInfo();
@@ -2129,29 +2146,32 @@ SDValue SelectionDAG::getNode(unsigned Opcode, MVT VT, SDValue Operand) {
         V.clearSign();
         return getConstantFP(V, VT);
       case ISD::FP_ROUND:
-      case ISD::FP_EXTEND:
+      case ISD::FP_EXTEND: {
+        bool ignored;
         // This can return overflow, underflow, or inexact; we don't care.
         // FIXME need to be more flexible about rounding mode.
         (void)V.convert(*MVTToAPFloatSemantics(VT),
-                        APFloat::rmNearestTiesToEven);
+                        APFloat::rmNearestTiesToEven, &ignored);
         return getConstantFP(V, VT);
+      }
       case ISD::FP_TO_SINT:
       case ISD::FP_TO_UINT: {
         integerPart x;
+        bool ignored;
         assert(integerPartWidth >= 64);
         // FIXME need to be more flexible about rounding mode.
         APFloat::opStatus s = V.convertToInteger(&x, 64U,
                               Opcode==ISD::FP_TO_SINT,
-                              APFloat::rmTowardZero);
+                              APFloat::rmTowardZero, &ignored);
         if (s==APFloat::opInvalidOp)     // inexact is OK, in fact usual
           break;
         return getConstant(x, VT);
       }
       case ISD::BIT_CONVERT:
         if (VT == MVT::i32 && C->getValueType(0) == MVT::f32)
-          return getConstant((uint32_t)V.convertToAPInt().getZExtValue(), VT);
+          return getConstant((uint32_t)V.bitcastToAPInt().getZExtValue(), VT);
         else if (VT == MVT::i64 && C->getValueType(0) == MVT::f64)
-          return getConstant(V.convertToAPInt().getZExtValue(), VT);
+          return getConstant(V.bitcastToAPInt().getZExtValue(), VT);
         break;
       }
     }
@@ -2325,6 +2345,7 @@ SDValue SelectionDAG::getNode(unsigned Opcode, MVT VT,
     // Fold trivial token factors.
     if (N1.getOpcode() == ISD::EntryToken) return N2;
     if (N2.getOpcode() == ISD::EntryToken) return N1;
+    if (N1 == N2) return N1;
     break;
   case ISD::CONCAT_VECTORS:
     // A CONCAT_VECTOR with all operands BUILD_VECTOR can be simplified to
@@ -2931,7 +2952,7 @@ static SDValue getMemcpyLoadsAndStores(SelectionDAG &DAG,
   // Expand memcpy to a series of load and store ops if the size operand falls
   // below a certain threshold.
   std::vector<MVT> MemOps;
-  uint64_t Limit = -1;
+  uint64_t Limit = -1ULL;
   if (!AlwaysInline)
     Limit = TLI.getMaxStoresPerMemcpy();
   unsigned DstAlign = Align;  // Destination alignment can change.
@@ -2989,7 +3010,7 @@ static SDValue getMemmoveLoadsAndStores(SelectionDAG &DAG,
   // Expand memmove to a series of load and store ops if the size operand falls
   // below a certain threshold.
   std::vector<MVT> MemOps;
-  uint64_t Limit = -1;
+  uint64_t Limit = -1ULL;
   if (!AlwaysInline)
     Limit = TLI.getMaxStoresPerMemmove();
   unsigned DstAlign = Align;  // Destination alignment can change.
@@ -3195,7 +3216,7 @@ SDValue SelectionDAG::getMemset(SDValue Chain, SDValue Dst,
   // code. If the target chooses to do this, this is the next best.
   SDValue Result =
     TLI.EmitTargetCodeForMemset(*this, Chain, Dst, Src, Size, Align,
-                                DstSV, DstSVOff, NoBuiltin);
+                                DstSV, DstSVOff);
   if (Result.getNode())
     return Result;
 
@@ -3333,6 +3354,46 @@ SDValue SelectionDAG::getMergeValues(const SDValue *Ops, unsigned NumOps,
   return getNode(ISD::MERGE_VALUES, getVTList(&VTs[0], NumOps), Ops, NumOps);
 }
 
+SDValue
+SelectionDAG::getMemIntrinsicNode(unsigned Opcode,
+                                  const MVT *VTs, unsigned NumVTs,
+                                  const SDValue *Ops, unsigned NumOps,
+                                  MVT MemVT, const Value *srcValue, int SVOff,
+                                  unsigned Align, bool Vol,
+                                  bool ReadMem, bool WriteMem) {
+  return getMemIntrinsicNode(Opcode, makeVTList(VTs, NumVTs), Ops, NumOps,
+                             MemVT, srcValue, SVOff, Align, Vol,
+                             ReadMem, WriteMem);
+}
+
+SDValue
+SelectionDAG::getMemIntrinsicNode(unsigned Opcode, SDVTList VTList,
+                                  const SDValue *Ops, unsigned NumOps,
+                                  MVT MemVT, const Value *srcValue, int SVOff,
+                                  unsigned Align, bool Vol,
+                                  bool ReadMem, bool WriteMem) {
+  // Memoize the node unless it returns a flag.
+  MemIntrinsicSDNode *N;
+  if (VTList.VTs[VTList.NumVTs-1] != MVT::Flag) {
+    FoldingSetNodeID ID;
+    AddNodeIDNode(ID, Opcode, VTList, Ops, NumOps);
+    void *IP = 0;
+    if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP))
+      return SDValue(E, 0);
+    
+    N = NodeAllocator.Allocate<MemIntrinsicSDNode>();
+    new (N) MemIntrinsicSDNode(Opcode, VTList, Ops, NumOps, MemVT,
+                               srcValue, SVOff, Align, Vol, ReadMem, WriteMem);
+    CSEMap.InsertNode(N, IP);
+  } else {
+    N = NodeAllocator.Allocate<MemIntrinsicSDNode>();
+    new (N) MemIntrinsicSDNode(Opcode, VTList, Ops, NumOps, MemVT,
+                               srcValue, SVOff, Align, Vol, ReadMem, WriteMem);
+  }
+  AllNodes.push_back(N);
+  return SDValue(N, 0);
+}
+
 SDValue
 SelectionDAG::getCall(unsigned CallingConv, bool IsVarArgs, bool IsTailCall,
                       bool IsInreg, SDVTList VTs,
@@ -4161,6 +4222,7 @@ SDNode *SelectionDAG::MorphNodeTo(SDNode *N, unsigned Opc,
   if (NumOps > N->NumOperands) {
     if (N->OperandsNeedDelete)
       delete[] N->OperandList;
+
     if (N->isMachineOpcode()) {
       // We're creating a final node that will live unmorphed for the
       // remainder of the current SelectionDAG iteration, so we can allocate
@@ -4677,6 +4739,7 @@ void MemSDNode::ANCHOR() {}
 void LoadSDNode::ANCHOR() {}
 void StoreSDNode::ANCHOR() {}
 void AtomicSDNode::ANCHOR() {}
+void MemIntrinsicSDNode::ANCHOR() {}
 void CallSDNode::ANCHOR() {}
 
 HandleSDNode::~HandleSDNode() {
@@ -4684,7 +4747,7 @@ HandleSDNode::~HandleSDNode() {
 }
 
 GlobalAddressSDNode::GlobalAddressSDNode(bool isTarget, const GlobalValue *GA,
-                                         MVT VT, int o)
+                                         MVT VT, int64_t o)
   : SDNode(isa<GlobalVariable>(GA) &&
            cast<GlobalVariable>(GA)->isThreadLocal() ?
            // Thread Local
@@ -4706,6 +4769,17 @@ MemSDNode::MemSDNode(unsigned Opc, SDVTList VTs, MVT memvt,
   assert(isVolatile() == vol && "Volatile representation error!");
 }
 
+MemSDNode::MemSDNode(unsigned Opc, SDVTList VTs, const SDValue *Ops,
+                     unsigned NumOps, MVT memvt, const Value *srcValue,
+                     int SVO, unsigned alignment, bool vol)
+   : SDNode(Opc, VTs, Ops, NumOps),
+     MemoryVT(memvt), SrcValue(srcValue), SVOffset(SVO),
+     Flags(vol | ((Log2_32(alignment) + 1) << 1)) {
+  assert(isPowerOf2_32(alignment) && "Alignment is not a power of 2!");
+  assert(getAlignment() == alignment && "Alignment representation error!");
+  assert(isVolatile() == vol && "Volatile representation error!");
+}
+
 /// getMemOperand - Return a MachineMemOperand object describing the memory
 /// reference performed by this memory reference.
 MachineMemOperand MemSDNode::getMemOperand() const {
@@ -4714,10 +4788,15 @@ MachineMemOperand MemSDNode::getMemOperand() const {
     Flags = MachineMemOperand::MOLoad;
   else if (isa<StoreSDNode>(this))
     Flags = MachineMemOperand::MOStore;
-  else {
-    assert(isa<AtomicSDNode>(this) && "Unknown MemSDNode opcode!");
+  else if (isa<AtomicSDNode>(this)) {
     Flags = MachineMemOperand::MOLoad | MachineMemOperand::MOStore;
   }
+  else {
+    const MemIntrinsicSDNode* MemIntrinNode = dyn_cast<MemIntrinsicSDNode>(this);
+    assert(MemIntrinNode && "Unknown MemSDNode opcode!");
+    if (MemIntrinNode->readMem()) Flags |= MachineMemOperand::MOLoad;
+    if (MemIntrinNode->writeMem()) Flags |= MachineMemOperand::MOStore;
+  }
 
   int Size = (getMemoryVT().getSizeInBits() + 7) >> 3;
   if (isVolatile()) Flags |= MachineMemOperand::MOVolatile;
@@ -5249,12 +5328,12 @@ void SDNode::print(raw_ostream &OS, const SelectionDAG *G) const {
       OS << '<' << CSDN->getValueAPF().convertToDouble() << '>';
     else {
       OS << "<APFloat(";
-      CSDN->getValueAPF().convertToAPInt().dump();
+      CSDN->getValueAPF().bitcastToAPInt().dump();
       OS << ")>";
     }
   } else if (const GlobalAddressSDNode *GADN =
              dyn_cast<GlobalAddressSDNode>(this)) {
-    int offset = GADN->getOffset();
+    int64_t offset = GADN->getOffset();
     OS << '<';
     WriteAsOperand(OS, GADN->getGlobal());
     OS << '>';