xref: /freebsd-12.1/contrib/llvm/lib/IR/Use.cpp (revision 39d628a0)
1139f7f9bSDimitry Andric //===-- Use.cpp - Implement the Use class ---------------------------------===//
2139f7f9bSDimitry Andric //
3139f7f9bSDimitry Andric //                     The LLVM Compiler Infrastructure
4139f7f9bSDimitry Andric //
5139f7f9bSDimitry Andric // This file is distributed under the University of Illinois Open Source
6139f7f9bSDimitry Andric // License. See LICENSE.TXT for details.
7139f7f9bSDimitry Andric //
8139f7f9bSDimitry Andric //===----------------------------------------------------------------------===//
9139f7f9bSDimitry Andric 
1091bc56edSDimitry Andric #include "llvm/IR/Use.h"
1191bc56edSDimitry Andric #include "llvm/IR/User.h"
12139f7f9bSDimitry Andric #include "llvm/IR/Value.h"
13139f7f9bSDimitry Andric #include <new>
14139f7f9bSDimitry Andric 
15139f7f9bSDimitry Andric namespace llvm {
16139f7f9bSDimitry Andric 
swap(Use & RHS)17139f7f9bSDimitry Andric void Use::swap(Use &RHS) {
1891bc56edSDimitry Andric   if (Val == RHS.Val)
1991bc56edSDimitry Andric     return;
2091bc56edSDimitry Andric 
2191bc56edSDimitry Andric   if (Val)
22139f7f9bSDimitry Andric     removeFromList();
23139f7f9bSDimitry Andric 
2491bc56edSDimitry Andric   Value *OldVal = Val;
2591bc56edSDimitry Andric   if (RHS.Val) {
26139f7f9bSDimitry Andric     RHS.removeFromList();
2791bc56edSDimitry Andric     Val = RHS.Val;
2891bc56edSDimitry Andric     Val->addUse(*this);
29139f7f9bSDimitry Andric   } else {
3091bc56edSDimitry Andric     Val = nullptr;
31139f7f9bSDimitry Andric   }
32139f7f9bSDimitry Andric 
3391bc56edSDimitry Andric   if (OldVal) {
3491bc56edSDimitry Andric     RHS.Val = OldVal;
3591bc56edSDimitry Andric     RHS.Val->addUse(RHS);
36139f7f9bSDimitry Andric   } else {
3791bc56edSDimitry Andric     RHS.Val = nullptr;
38139f7f9bSDimitry Andric   }
39139f7f9bSDimitry Andric }
40139f7f9bSDimitry Andric 
getUser() const4191bc56edSDimitry Andric User *Use::getUser() const {
4291bc56edSDimitry Andric   const Use *End = getImpliedUser();
4391bc56edSDimitry Andric   const UserRef *ref = reinterpret_cast<const UserRef *>(End);
4491bc56edSDimitry Andric   return ref->getInt() ? ref->getPointer()
4591bc56edSDimitry Andric                        : reinterpret_cast<User *>(const_cast<Use *>(End));
4691bc56edSDimitry Andric }
4791bc56edSDimitry Andric 
getOperandNo() const4891bc56edSDimitry Andric unsigned Use::getOperandNo() const {
4991bc56edSDimitry Andric   return this - getUser()->op_begin();
5091bc56edSDimitry Andric }
5191bc56edSDimitry Andric 
5291bc56edSDimitry Andric // Sets up the waymarking algorithm's tags for a series of Uses. See the
5391bc56edSDimitry Andric // algorithm details here:
5491bc56edSDimitry Andric //
55*39d628a0SDimitry Andric //   http://www.llvm.org/docs/ProgrammersManual.html#the-waymarking-algorithm
5691bc56edSDimitry Andric //
initTags(Use * const Start,Use * Stop)5791bc56edSDimitry Andric Use *Use::initTags(Use *const Start, Use *Stop) {
5891bc56edSDimitry Andric   ptrdiff_t Done = 0;
5991bc56edSDimitry Andric   while (Done < 20) {
6091bc56edSDimitry Andric     if (Start == Stop--)
6191bc56edSDimitry Andric       return Start;
6291bc56edSDimitry Andric     static const PrevPtrTag tags[20] = {
6391bc56edSDimitry Andric         fullStopTag,  oneDigitTag,  stopTag,      oneDigitTag, oneDigitTag,
6491bc56edSDimitry Andric         stopTag,      zeroDigitTag, oneDigitTag,  oneDigitTag, stopTag,
6591bc56edSDimitry Andric         zeroDigitTag, oneDigitTag,  zeroDigitTag, oneDigitTag, stopTag,
6691bc56edSDimitry Andric         oneDigitTag,  oneDigitTag,  oneDigitTag,  oneDigitTag, stopTag};
6791bc56edSDimitry Andric     new (Stop) Use(tags[Done++]);
6891bc56edSDimitry Andric   }
6991bc56edSDimitry Andric 
7091bc56edSDimitry Andric   ptrdiff_t Count = Done;
7191bc56edSDimitry Andric   while (Start != Stop) {
7291bc56edSDimitry Andric     --Stop;
7391bc56edSDimitry Andric     if (!Count) {
7491bc56edSDimitry Andric       new (Stop) Use(stopTag);
7591bc56edSDimitry Andric       ++Done;
7691bc56edSDimitry Andric       Count = Done;
7791bc56edSDimitry Andric     } else {
7891bc56edSDimitry Andric       new (Stop) Use(PrevPtrTag(Count & 1));
7991bc56edSDimitry Andric       Count >>= 1;
8091bc56edSDimitry Andric       ++Done;
8191bc56edSDimitry Andric     }
8291bc56edSDimitry Andric   }
8391bc56edSDimitry Andric 
8491bc56edSDimitry Andric   return Start;
8591bc56edSDimitry Andric }
8691bc56edSDimitry Andric 
zap(Use * Start,const Use * Stop,bool del)8791bc56edSDimitry Andric void Use::zap(Use *Start, const Use *Stop, bool del) {
8891bc56edSDimitry Andric   while (Start != Stop)
8991bc56edSDimitry Andric     (--Stop)->~Use();
9091bc56edSDimitry Andric   if (del)
9191bc56edSDimitry Andric     ::operator delete(Start);
9291bc56edSDimitry Andric }
93139f7f9bSDimitry Andric 
getImpliedUser() const94139f7f9bSDimitry Andric const Use *Use::getImpliedUser() const {
95139f7f9bSDimitry Andric   const Use *Current = this;
96139f7f9bSDimitry Andric 
97139f7f9bSDimitry Andric   while (true) {
98139f7f9bSDimitry Andric     unsigned Tag = (Current++)->Prev.getInt();
99139f7f9bSDimitry Andric     switch (Tag) {
100139f7f9bSDimitry Andric     case zeroDigitTag:
101139f7f9bSDimitry Andric     case oneDigitTag:
102139f7f9bSDimitry Andric       continue;
103139f7f9bSDimitry Andric 
104139f7f9bSDimitry Andric     case stopTag: {
105139f7f9bSDimitry Andric       ++Current;
106139f7f9bSDimitry Andric       ptrdiff_t Offset = 1;
107139f7f9bSDimitry Andric       while (true) {
108139f7f9bSDimitry Andric         unsigned Tag = Current->Prev.getInt();
109139f7f9bSDimitry Andric         switch (Tag) {
110139f7f9bSDimitry Andric         case zeroDigitTag:
111139f7f9bSDimitry Andric         case oneDigitTag:
112139f7f9bSDimitry Andric           ++Current;
113139f7f9bSDimitry Andric           Offset = (Offset << 1) + Tag;
114139f7f9bSDimitry Andric           continue;
115139f7f9bSDimitry Andric         default:
116139f7f9bSDimitry Andric           return Current + Offset;
117139f7f9bSDimitry Andric         }
118139f7f9bSDimitry Andric       }
119139f7f9bSDimitry Andric     }
120139f7f9bSDimitry Andric 
121139f7f9bSDimitry Andric     case fullStopTag:
122139f7f9bSDimitry Andric       return Current;
123139f7f9bSDimitry Andric     }
124139f7f9bSDimitry Andric   }
125139f7f9bSDimitry Andric }
126139f7f9bSDimitry Andric 
127139f7f9bSDimitry Andric } // End llvm namespace
128