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

Generated by: LCOV version 1.13