Coverage Report

Created: 2017-10-03 07:32

/Users/buildslave/jenkins/sharedspace/clang-stage2-coverage-R@2/llvm/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
2.90M
void User::replaceUsesOfWith(Value *From, Value *To) {
23
2.90M
  if (
From == To2.90M
)
return105k
; // Duh what?
24
2.79M
25
2.90M
  assert((!isa<Constant>(this) || isa<GlobalValue>(this)) &&
26
2.79M
         "Cannot call User::replaceUsesOfWith on a constant!");
27
2.79M
28
9.89M
  for (unsigned i = 0, E = getNumOperands(); 
i != E9.89M
;
++i7.09M
)
29
7.09M
    
if (7.09M
getOperand(i) == From7.09M
) { // Is This operand is pointing to oldval?
30
2.79M
      // The side effects of this setOperand call include linking to
31
2.79M
      // "To", adding "this" to the uses list of To, and
32
2.79M
      // most importantly, removing "this" from the use list of "From".
33
2.79M
      setOperand(i, To); // Fix it now...
34
2.79M
    }
35
2.90M
}
36
37
//===----------------------------------------------------------------------===//
38
//                         User allocHungoffUses Implementation
39
//===----------------------------------------------------------------------===//
40
41
6.32M
void User::allocHungoffUses(unsigned N, bool IsPhi) {
42
6.32M
  assert(HasHungOffUses && "alloc must have hung off uses");
43
6.32M
44
6.32M
  static_assert(alignof(Use) >= alignof(Use::UserRef),
45
6.32M
                "Alignment is insufficient for 'hung-off-uses' pieces");
46
6.32M
  static_assert(alignof(Use::UserRef) >= alignof(BasicBlock *),
47
6.32M
                "Alignment is insufficient for 'hung-off-uses' pieces");
48
6.32M
49
6.32M
  // Allocate the array of Uses, followed by a pointer (with bottom bit set) to
50
6.32M
  // the User.
51
6.32M
  size_t size = N * sizeof(Use) + sizeof(Use::UserRef);
52
6.32M
  if (IsPhi)
53
6.22M
    size += N * sizeof(BasicBlock *);
54
6.32M
  Use *Begin = static_cast<Use*>(::operator new(size));
55
6.32M
  Use *End = Begin + N;
56
6.32M
  (void) new(End) Use::UserRef(const_cast<User*>(this), 1);
57
6.32M
  setOperandList(Use::initTags(Begin, End));
58
6.32M
}
59
60
1.55M
void User::growHungoffUses(unsigned NewNumUses, bool IsPhi) {
61
1.55M
  assert(HasHungOffUses && "realloc must have hung off uses");
62
1.55M
63
1.55M
  unsigned OldNumUses = getNumOperands();
64
1.55M
65
1.55M
  // We don't support shrinking the number of uses.  We wouldn't have enough
66
1.55M
  // space to copy the old uses in to the new space.
67
1.55M
  assert(NewNumUses > OldNumUses && "realloc must grow num uses");
68
1.55M
69
1.55M
  Use *OldOps = getOperandList();
70
1.55M
  allocHungoffUses(NewNumUses, IsPhi);
71
1.55M
  Use *NewOps = getOperandList();
72
1.55M
73
1.55M
  // Now copy from the old operands list to the new one.
74
1.55M
  std::copy(OldOps, OldOps + OldNumUses, NewOps);
75
1.55M
76
1.55M
  // If this is a Phi, then we need to copy the BB pointers too.
77
1.55M
  if (
IsPhi1.55M
) {
78
1.55M
    auto *OldPtr =
79
1.55M
        reinterpret_cast<char *>(OldOps + OldNumUses) + sizeof(Use::UserRef);
80
1.55M
    auto *NewPtr =
81
1.55M
        reinterpret_cast<char *>(NewOps + NewNumUses) + sizeof(Use::UserRef);
82
1.55M
    std::copy(OldPtr, OldPtr + (OldNumUses * sizeof(BasicBlock *)), NewPtr);
83
1.55M
  }
84
1.55M
  Use::zap(OldOps, OldOps + OldNumUses, true);
85
1.55M
}
86
87
88
// This is a private struct used by `User` to track the co-allocated descriptor
89
// section.
90
struct DescriptorInfo {
91
  intptr_t SizeInBytes;
92
};
93
94
0
ArrayRef<const uint8_t> User::getDescriptor() const {
95
0
  auto MutableARef = const_cast<User *>(this)->getDescriptor();
96
0
  return {MutableARef.begin(), MutableARef.end()};
97
0
}
98
99
62.4k
MutableArrayRef<uint8_t> User::getDescriptor() {
100
62.4k
  assert(HasDescriptor && "Don't call otherwise!");
101
62.4k
  assert(!HasHungOffUses && "Invariant!");
102
62.4k
103
62.4k
  auto *DI = reinterpret_cast<DescriptorInfo *>(getIntrusiveOperands()) - 1;
104
62.4k
  assert(DI->SizeInBytes != 0 && "Should not have had a descriptor otherwise!");
105
62.4k
106
62.4k
  return MutableArrayRef<uint8_t>(
107
62.4k
      reinterpret_cast<uint8_t *>(DI) - DI->SizeInBytes, DI->SizeInBytes);
108
62.4k
}
109
110
//===----------------------------------------------------------------------===//
111
//                         User operator new Implementations
112
//===----------------------------------------------------------------------===//
113
114
void *User::allocateFixedOperandUser(size_t Size, unsigned Us,
115
66.9M
                                     unsigned DescBytes) {
116
66.9M
  assert(Us < (1u << NumUserOperandsBits) && "Too many operands");
117
66.9M
118
66.9M
  static_assert(sizeof(DescriptorInfo) % sizeof(void *) == 0, "Required below");
119
66.9M
120
66.9M
  unsigned DescBytesToAllocate =
121
66.9M
      DescBytes == 0 ? 
066.9M
:
(DescBytes + sizeof(DescriptorInfo))1.24k
;
122
66.9M
  assert(DescBytesToAllocate % sizeof(void *) == 0 &&
123
66.9M
         "We need this to satisfy alignment constraints for Uses");
124
66.9M
125
66.9M
  uint8_t *Storage = static_cast<uint8_t *>(
126
66.9M
      ::operator new(Size + sizeof(Use) * Us + DescBytesToAllocate));
127
66.9M
  Use *Start = reinterpret_cast<Use *>(Storage + DescBytesToAllocate);
128
66.9M
  Use *End = Start + Us;
129
66.9M
  User *Obj = reinterpret_cast<User*>(End);
130
66.9M
  Obj->NumUserOperands = Us;
131
66.9M
  Obj->HasHungOffUses = false;
132
66.9M
  Obj->HasDescriptor = DescBytes != 0;
133
66.9M
  Use::initTags(Start, End);
134
66.9M
135
66.9M
  if (
DescBytes != 066.9M
) {
136
1.24k
    auto *DescInfo = reinterpret_cast<DescriptorInfo *>(Storage + DescBytes);
137
1.24k
    DescInfo->SizeInBytes = DescBytes;
138
1.24k
  }
139
66.9M
140
66.9M
  return Obj;
141
66.9M
}
142
143
62.4M
void *User::operator new(size_t Size, unsigned Us) {
144
62.4M
  return allocateFixedOperandUser(Size, Us, 0);
145
62.4M
}
146
147
4.48M
void *User::operator new(size_t Size, unsigned Us, unsigned DescBytes) {
148
4.48M
  return allocateFixedOperandUser(Size, Us, DescBytes);
149
4.48M
}
150
151
7.61M
void *User::operator new(size_t Size) {
152
7.61M
  // Allocate space for a single Use*
153
7.61M
  void *Storage = ::operator new(Size + sizeof(Use *));
154
7.61M
  Use **HungOffOperandList = static_cast<Use **>(Storage);
155
7.61M
  User *Obj = reinterpret_cast<User *>(HungOffOperandList + 1);
156
7.61M
  Obj->NumUserOperands = 0;
157
7.61M
  Obj->HasHungOffUses = true;
158
7.61M
  Obj->HasDescriptor = false;
159
7.61M
  *HungOffOperandList = nullptr;
160
7.61M
  return Obj;
161
7.61M
}
162
163
//===----------------------------------------------------------------------===//
164
//                         User operator delete Implementation
165
//===----------------------------------------------------------------------===//
166
167
46.3M
void User::operator delete(void *Usr) {
168
46.3M
  // Hung off uses use a single Use* before the User, while other subclasses
169
46.3M
  // use a Use[] allocated prior to the user.
170
46.3M
  User *Obj = static_cast<User *>(Usr);
171
46.3M
  if (
Obj->HasHungOffUses46.3M
) {
172
5.92M
    assert(!Obj->HasDescriptor && "not supported!");
173
5.92M
174
5.92M
    Use **HungOffOperandList = static_cast<Use **>(Usr) - 1;
175
5.92M
    // drop the hung off uses.
176
5.92M
    Use::zap(*HungOffOperandList, *HungOffOperandList + Obj->NumUserOperands,
177
5.92M
             /* Delete */ true);
178
5.92M
    ::operator delete(HungOffOperandList);
179
46.3M
  } else 
if (40.4M
Obj->HasDescriptor40.4M
) {
180
1.24k
    Use *UseBegin = static_cast<Use *>(Usr) - Obj->NumUserOperands;
181
1.24k
    Use::zap(UseBegin, UseBegin + Obj->NumUserOperands, /* Delete */ false);
182
1.24k
183
1.24k
    auto *DI = reinterpret_cast<DescriptorInfo *>(UseBegin) - 1;
184
1.24k
    uint8_t *Storage = reinterpret_cast<uint8_t *>(DI) - DI->SizeInBytes;
185
1.24k
    ::operator delete(Storage);
186
40.4M
  } else {
187
40.4M
    Use *Storage = static_cast<Use *>(Usr) - Obj->NumUserOperands;
188
40.4M
    Use::zap(Storage, Storage + Obj->NumUserOperands,
189
40.4M
             /* Delete */ false);
190
40.4M
    ::operator delete(Storage);
191
40.4M
  }
192
46.3M
}
193
194
} // End llvm namespace