xref: /freebsd/contrib/llvm-project/llvm/lib/IR/Use.cpp (revision 6966ac055c3b7a39266fb982493330df7a097997)
1 //===-- Use.cpp - Implement the Use class ---------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "llvm/IR/Use.h"
10 #include "llvm/IR/User.h"
11 #include "llvm/IR/Value.h"
12 #include <new>
13 
14 namespace llvm {
15 
16 void Use::swap(Use &RHS) {
17   if (Val == RHS.Val)
18     return;
19 
20   if (Val)
21     removeFromList();
22 
23   Value *OldVal = Val;
24   if (RHS.Val) {
25     RHS.removeFromList();
26     Val = RHS.Val;
27     Val->addUse(*this);
28   } else {
29     Val = nullptr;
30   }
31 
32   if (OldVal) {
33     RHS.Val = OldVal;
34     RHS.Val->addUse(RHS);
35   } else {
36     RHS.Val = nullptr;
37   }
38 }
39 
40 User *Use::getUser() const {
41   const Use *End = getImpliedUser();
42   const UserRef *ref = reinterpret_cast<const UserRef *>(End);
43   return ref->getInt() ? ref->getPointer()
44                        : reinterpret_cast<User *>(const_cast<Use *>(End));
45 }
46 
47 unsigned Use::getOperandNo() const {
48   return this - getUser()->op_begin();
49 }
50 
51 // Sets up the waymarking algorithm's tags for a series of Uses. See the
52 // algorithm details here:
53 //
54 //   http://www.llvm.org/docs/ProgrammersManual.html#the-waymarking-algorithm
55 //
56 Use *Use::initTags(Use *const Start, Use *Stop) {
57   ptrdiff_t Done = 0;
58   while (Done < 20) {
59     if (Start == Stop--)
60       return Start;
61     static const PrevPtrTag tags[20] = {
62         fullStopTag,  oneDigitTag,  stopTag,      oneDigitTag, oneDigitTag,
63         stopTag,      zeroDigitTag, oneDigitTag,  oneDigitTag, stopTag,
64         zeroDigitTag, oneDigitTag,  zeroDigitTag, oneDigitTag, stopTag,
65         oneDigitTag,  oneDigitTag,  oneDigitTag,  oneDigitTag, stopTag};
66     new (Stop) Use(tags[Done++]);
67   }
68 
69   ptrdiff_t Count = Done;
70   while (Start != Stop) {
71     --Stop;
72     if (!Count) {
73       new (Stop) Use(stopTag);
74       ++Done;
75       Count = Done;
76     } else {
77       new (Stop) Use(PrevPtrTag(Count & 1));
78       Count >>= 1;
79       ++Done;
80     }
81   }
82 
83   return Start;
84 }
85 
86 void Use::zap(Use *Start, const Use *Stop, bool del) {
87   while (Start != Stop)
88     (--Stop)->~Use();
89   if (del)
90     ::operator delete(Start);
91 }
92 
93 const Use *Use::getImpliedUser() const {
94   const Use *Current = this;
95 
96   while (true) {
97     unsigned Tag = (Current++)->Prev.getInt();
98     switch (Tag) {
99     case zeroDigitTag:
100     case oneDigitTag:
101       continue;
102 
103     case stopTag: {
104       ++Current;
105       ptrdiff_t Offset = 1;
106       while (true) {
107         unsigned Tag = Current->Prev.getInt();
108         switch (Tag) {
109         case zeroDigitTag:
110         case oneDigitTag:
111           ++Current;
112           Offset = (Offset << 1) + Tag;
113           continue;
114         default:
115           return Current + Offset;
116         }
117       }
118     }
119 
120     case fullStopTag:
121       return Current;
122     }
123   }
124 }
125 
126 } // End llvm namespace
127