Fix thinko - the operand number has nothing to do
[oota-llvm.git] / lib / CodeGen / SelectionDAG / SelectionDAG.cpp
index f75d39293e238cf4516c2e185117564f5168c6d5..758f112f78c6e83e4318b50f7c67da32ed994792 100644 (file)
@@ -216,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
@@ -227,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);
 }
 
@@ -506,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);
 }
 
@@ -561,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;
     
@@ -589,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));
@@ -675,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.
@@ -703,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;
@@ -729,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;
@@ -755,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);
@@ -791,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;
   }
   }
@@ -833,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);
   }
 }
@@ -959,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.
@@ -2017,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();
@@ -3334,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,
@@ -4162,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
@@ -4678,6 +4739,7 @@ void MemSDNode::ANCHOR() {}
 void LoadSDNode::ANCHOR() {}
 void StoreSDNode::ANCHOR() {}
 void AtomicSDNode::ANCHOR() {}
+void MemIntrinsicSDNode::ANCHOR() {}
 void CallSDNode::ANCHOR() {}
 
 HandleSDNode::~HandleSDNode() {
@@ -4685,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
@@ -4707,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 {
@@ -4715,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;
@@ -5255,7 +5333,7 @@ void SDNode::print(raw_ostream &OS, const SelectionDAG *G) const {
     }
   } else if (const GlobalAddressSDNode *GADN =
              dyn_cast<GlobalAddressSDNode>(this)) {
-    int offset = GADN->getOffset();
+    int64_t offset = GADN->getOffset();
     OS << '<';
     WriteAsOperand(OS, GADN->getGlobal());
     OS << '>';