1249259Sdim//===-- Use.cpp - Implement the Use class ---------------------------------===// 2249259Sdim// 3249259Sdim// The LLVM Compiler Infrastructure 4249259Sdim// 5249259Sdim// This file is distributed under the University of Illinois Open Source 6249259Sdim// License. See LICENSE.TXT for details. 7249259Sdim// 8249259Sdim//===----------------------------------------------------------------------===// 9249259Sdim// 10249259Sdim// This file implements the algorithm for finding the User of a Use. 11249259Sdim// 12249259Sdim//===----------------------------------------------------------------------===// 13249259Sdim 14249259Sdim#include "llvm/IR/Value.h" 15249259Sdim#include <new> 16249259Sdim 17249259Sdimnamespace llvm { 18249259Sdim 19249259Sdim//===----------------------------------------------------------------------===// 20249259Sdim// Use swap Implementation 21249259Sdim//===----------------------------------------------------------------------===// 22249259Sdim 23249259Sdimvoid Use::swap(Use &RHS) { 24249259Sdim Value *V1(Val); 25249259Sdim Value *V2(RHS.Val); 26249259Sdim if (V1 != V2) { 27249259Sdim if (V1) { 28249259Sdim removeFromList(); 29249259Sdim } 30249259Sdim 31249259Sdim if (V2) { 32249259Sdim RHS.removeFromList(); 33249259Sdim Val = V2; 34249259Sdim V2->addUse(*this); 35249259Sdim } else { 36249259Sdim Val = 0; 37249259Sdim } 38249259Sdim 39249259Sdim if (V1) { 40249259Sdim RHS.Val = V1; 41249259Sdim V1->addUse(RHS); 42249259Sdim } else { 43249259Sdim RHS.Val = 0; 44249259Sdim } 45249259Sdim } 46249259Sdim} 47249259Sdim 48249259Sdim//===----------------------------------------------------------------------===// 49249259Sdim// Use getImpliedUser Implementation 50249259Sdim//===----------------------------------------------------------------------===// 51249259Sdim 52249259Sdimconst Use *Use::getImpliedUser() const { 53249259Sdim const Use *Current = this; 54249259Sdim 55249259Sdim while (true) { 56249259Sdim unsigned Tag = (Current++)->Prev.getInt(); 57249259Sdim switch (Tag) { 58249259Sdim case zeroDigitTag: 59249259Sdim case oneDigitTag: 60249259Sdim continue; 61249259Sdim 62249259Sdim case stopTag: { 63249259Sdim ++Current; 64249259Sdim ptrdiff_t Offset = 1; 65249259Sdim while (true) { 66249259Sdim unsigned Tag = Current->Prev.getInt(); 67249259Sdim switch (Tag) { 68249259Sdim case zeroDigitTag: 69249259Sdim case oneDigitTag: 70249259Sdim ++Current; 71249259Sdim Offset = (Offset << 1) + Tag; 72249259Sdim continue; 73249259Sdim default: 74249259Sdim return Current + Offset; 75249259Sdim } 76249259Sdim } 77249259Sdim } 78249259Sdim 79249259Sdim case fullStopTag: 80249259Sdim return Current; 81249259Sdim } 82249259Sdim } 83249259Sdim} 84249259Sdim 85249259Sdim//===----------------------------------------------------------------------===// 86249259Sdim// Use initTags Implementation 87249259Sdim//===----------------------------------------------------------------------===// 88249259Sdim 89249259SdimUse *Use::initTags(Use * const Start, Use *Stop) { 90249259Sdim ptrdiff_t Done = 0; 91249259Sdim while (Done < 20) { 92249259Sdim if (Start == Stop--) 93249259Sdim return Start; 94249259Sdim static const PrevPtrTag tags[20] = { fullStopTag, oneDigitTag, stopTag, 95249259Sdim oneDigitTag, oneDigitTag, stopTag, 96249259Sdim zeroDigitTag, oneDigitTag, oneDigitTag, 97249259Sdim stopTag, zeroDigitTag, oneDigitTag, 98249259Sdim zeroDigitTag, oneDigitTag, stopTag, 99249259Sdim oneDigitTag, oneDigitTag, oneDigitTag, 100249259Sdim oneDigitTag, stopTag 101249259Sdim }; 102249259Sdim new(Stop) Use(tags[Done++]); 103249259Sdim } 104249259Sdim 105249259Sdim ptrdiff_t Count = Done; 106249259Sdim while (Start != Stop) { 107249259Sdim --Stop; 108249259Sdim if (!Count) { 109249259Sdim new(Stop) Use(stopTag); 110249259Sdim ++Done; 111249259Sdim Count = Done; 112249259Sdim } else { 113249259Sdim new(Stop) Use(PrevPtrTag(Count & 1)); 114249259Sdim Count >>= 1; 115249259Sdim ++Done; 116249259Sdim } 117249259Sdim } 118249259Sdim 119249259Sdim return Start; 120249259Sdim} 121249259Sdim 122249259Sdim//===----------------------------------------------------------------------===// 123249259Sdim// Use zap Implementation 124249259Sdim//===----------------------------------------------------------------------===// 125249259Sdim 126249259Sdimvoid Use::zap(Use *Start, const Use *Stop, bool del) { 127249259Sdim while (Start != Stop) 128249259Sdim (--Stop)->~Use(); 129249259Sdim if (del) 130249259Sdim ::operator delete(Start); 131249259Sdim} 132249259Sdim 133249259Sdim//===----------------------------------------------------------------------===// 134249259Sdim// Use getUser Implementation 135249259Sdim//===----------------------------------------------------------------------===// 136249259Sdim 137249259SdimUser *Use::getUser() const { 138249259Sdim const Use *End = getImpliedUser(); 139249259Sdim const UserRef *ref = reinterpret_cast<const UserRef*>(End); 140249259Sdim return ref->getInt() 141249259Sdim ? ref->getPointer() 142249259Sdim : reinterpret_cast<User*>(const_cast<Use*>(End)); 143249259Sdim} 144249259Sdim 145249259Sdim} // End llvm namespace 146