/home/runner/work/DirectXShaderCompiler/DirectXShaderCompiler/lib/IR/User.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===-- User.cpp - Implement the User class -------------------------------===// |
2 | | // |
3 | | // The LLVM Compiler Infrastructure |
4 | | // |
5 | | // This file is distributed under the University of Illinois Open Source |
6 | | // License. See LICENSE.TXT for details. |
7 | | // |
8 | | //===----------------------------------------------------------------------===// |
9 | | |
10 | | #include "llvm/IR/User.h" |
11 | | #include "llvm/IR/Constant.h" |
12 | | #include "llvm/IR/GlobalValue.h" |
13 | | #include "llvm/IR/Operator.h" |
14 | | |
15 | | namespace llvm { |
16 | | class BasicBlock; |
17 | | |
18 | | //===----------------------------------------------------------------------===// |
19 | | // User Class |
20 | | //===----------------------------------------------------------------------===// |
21 | | |
22 | 0 | void User::anchor() {} |
23 | | |
24 | 53.6k | void User::replaceUsesOfWith(Value *From, Value *To) { |
25 | 53.6k | if (From == To) return0 ; // Duh what? |
26 | | |
27 | 53.6k | assert((!isa<Constant>(this) || isa<GlobalValue>(this)) && |
28 | 53.6k | "Cannot call User::replaceUsesOfWith on a constant!"); |
29 | | |
30 | 187k | for (unsigned i = 0, E = getNumOperands(); i != E; ++i133k ) |
31 | 133k | if (getOperand(i) == From) { // Is This operand is pointing to oldval? |
32 | | // The side effects of this setOperand call include linking to |
33 | | // "To", adding "this" to the uses list of To, and |
34 | | // most importantly, removing "this" from the use list of "From". |
35 | 53.6k | setOperand(i, To); // Fix it now... |
36 | 53.6k | } |
37 | 53.6k | } |
38 | | |
39 | | //===----------------------------------------------------------------------===// |
40 | | // User allocHungoffUses Implementation |
41 | | //===----------------------------------------------------------------------===// |
42 | | |
43 | 471k | void User::allocHungoffUses(unsigned N, bool IsPhi) { |
44 | 471k | assert(HasHungOffUses && "alloc must have hung off uses"); |
45 | | |
46 | 471k | static_assert(AlignOf<Use>::Alignment >= AlignOf<Use::UserRef>::Alignment, |
47 | 471k | "Alignment is insufficient for 'hung-off-uses' pieces"); |
48 | 471k | static_assert(AlignOf<Use::UserRef>::Alignment >= |
49 | 471k | AlignOf<BasicBlock *>::Alignment, |
50 | 471k | "Alignment is insufficient for 'hung-off-uses' pieces"); |
51 | | |
52 | | // Allocate the array of Uses, followed by a pointer (with bottom bit set) to |
53 | | // the User. |
54 | 471k | size_t size = N * sizeof(Use) + sizeof(Use::UserRef); |
55 | 471k | if (IsPhi) |
56 | 469k | size += N * sizeof(BasicBlock *); |
57 | 471k | Use *Begin = static_cast<Use*>(::operator new(size)); |
58 | 471k | Use *End = Begin + N; |
59 | 471k | (void) new(End) Use::UserRef(const_cast<User*>(this), 1); |
60 | 471k | setOperandList(Use::initTags(Begin, End)); |
61 | 471k | } |
62 | | |
63 | 37.7k | void User::growHungoffUses(unsigned NewNumUses, bool IsPhi) { |
64 | 37.7k | assert(HasHungOffUses && "realloc must have hung off uses"); |
65 | | |
66 | 37.7k | unsigned OldNumUses = getNumOperands(); |
67 | | |
68 | | // We don't support shrinking the number of uses. We wouldn't have enough |
69 | | // space to copy the old uses in to the new space. |
70 | 37.7k | assert(NewNumUses > OldNumUses && "realloc must grow num uses"); |
71 | | |
72 | 37.7k | Use *OldOps = getOperandList(); |
73 | 37.7k | allocHungoffUses(NewNumUses, IsPhi); |
74 | 37.7k | Use *NewOps = getOperandList(); |
75 | | |
76 | | // Now copy from the old operands list to the new one. |
77 | 37.7k | std::copy(OldOps, OldOps + OldNumUses, NewOps); |
78 | | |
79 | | // If this is a Phi, then we need to copy the BB pointers too. |
80 | 37.7k | if (IsPhi) { |
81 | 37.7k | auto *OldPtr = |
82 | 37.7k | reinterpret_cast<char *>(OldOps + OldNumUses) + sizeof(Use::UserRef); |
83 | 37.7k | auto *NewPtr = |
84 | 37.7k | reinterpret_cast<char *>(NewOps + NewNumUses) + sizeof(Use::UserRef); |
85 | 37.7k | std::copy(OldPtr, OldPtr + (OldNumUses * sizeof(BasicBlock *)), NewPtr); |
86 | 37.7k | } |
87 | 37.7k | Use::zap(OldOps, OldOps + OldNumUses, true); |
88 | 37.7k | } |
89 | | |
90 | | //===----------------------------------------------------------------------===// |
91 | | // User operator new Implementations |
92 | | //===----------------------------------------------------------------------===// |
93 | | |
94 | 17.1M | void *User::operator new(size_t Size, unsigned Us) { |
95 | 17.1M | assert(Us < (1u << NumUserOperandsBits) && "Too many operands"); |
96 | 17.1M | void *Storage = ::operator new(Size + sizeof(Use) * Us); |
97 | 17.1M | Use *Start = static_cast<Use*>(Storage); |
98 | 17.1M | Use *End = Start + Us; |
99 | 17.1M | User *Obj = reinterpret_cast<User*>(End); |
100 | 17.1M | Obj->NumUserOperands = Us; |
101 | 17.1M | Obj->HasHungOffUses = false; |
102 | 17.1M | Use::initTags(Start, End); |
103 | 17.1M | return Obj; |
104 | 17.1M | } |
105 | | |
106 | 433k | void *User::operator new(size_t Size) { |
107 | | // Allocate space for a single Use* |
108 | 433k | void *Storage = ::operator new(Size + sizeof(Use *)); |
109 | 433k | Use **HungOffOperandList = static_cast<Use **>(Storage); |
110 | 433k | User *Obj = reinterpret_cast<User *>(HungOffOperandList + 1); |
111 | 433k | Obj->NumUserOperands = 0; |
112 | 433k | Obj->HasHungOffUses = true; |
113 | 433k | *HungOffOperandList = nullptr; |
114 | 433k | return Obj; |
115 | 433k | } |
116 | | |
117 | | //===----------------------------------------------------------------------===// |
118 | | // User operator delete Implementation |
119 | | //===----------------------------------------------------------------------===// |
120 | | |
121 | 17.3M | void User::operator delete(void *Usr) { |
122 | | // Hung off uses use a single Use* before the User, while other subclasses |
123 | | // use a Use[] allocated prior to the user. |
124 | 17.3M | User *Obj = static_cast<User *>(Usr); |
125 | 17.3M | if (Obj->HasHungOffUses) { |
126 | 433k | Use **HungOffOperandList = static_cast<Use **>(Usr) - 1; |
127 | | // drop the hung off uses. |
128 | 433k | Use::zap(*HungOffOperandList, *HungOffOperandList + Obj->NumUserOperands, |
129 | 433k | /* Delete */ true); |
130 | 433k | ::operator delete(HungOffOperandList); |
131 | 16.9M | } else { |
132 | 16.9M | Use *Storage = static_cast<Use *>(Usr) - Obj->NumUserOperands; |
133 | 16.9M | Use::zap(Storage, Storage + Obj->NumUserOperands, |
134 | 16.9M | /* Delete */ false); |
135 | 16.9M | ::operator delete(Storage); |
136 | 16.9M | } |
137 | 17.3M | } |
138 | | |
139 | | // HLSL Change Starts |
140 | 155k | void User::operator delete(void *Usr, unsigned NumUserOperands) { |
141 | | // Fun fact: during construction Obj->NumUserOperands is overwritten |
142 | 155k | Use *Storage = static_cast<Use *>(Usr) - NumUserOperands; |
143 | 155k | Use::zap(Storage, Storage + NumUserOperands, /* Delete */ false); |
144 | 155k | ::operator delete(Storage); |
145 | 155k | } |
146 | | // HLSL Change Ends |
147 | | |
148 | | //===----------------------------------------------------------------------===// |
149 | | // Operator Class |
150 | | //===----------------------------------------------------------------------===// |
151 | | |
152 | 0 | Operator::~Operator() { |
153 | 0 | llvm_unreachable("should never destroy an Operator"); |
154 | 0 | } |
155 | | |
156 | | } // End llvm namespace |