LCOV - code coverage report
Current view: top level - lib/IR - User.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 72 75 96.0 %
Date: 2017-09-14 15:23:50 Functions: 8 9 88.9 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13