LLVM API Documentation

GlobalStatus.cpp
Go to the documentation of this file.
00001 //===-- GlobalStatus.cpp - Compute status info for globals -----------------==//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 
00010 #include "llvm/ADT/SmallPtrSet.h"
00011 #include "llvm/IR/BasicBlock.h"
00012 #include "llvm/IR/CallSite.h"
00013 #include "llvm/IR/GlobalVariable.h"
00014 #include "llvm/IR/IntrinsicInst.h"
00015 #include "llvm/Transforms/Utils/GlobalStatus.h"
00016 
00017 using namespace llvm;
00018 
00019 /// Return the stronger of the two ordering. If the two orderings are acquire
00020 /// and release, then return AcquireRelease.
00021 ///
00022 static AtomicOrdering strongerOrdering(AtomicOrdering X, AtomicOrdering Y) {
00023   if (X == Acquire && Y == Release)
00024     return AcquireRelease;
00025   if (Y == Acquire && X == Release)
00026     return AcquireRelease;
00027   return (AtomicOrdering)std::max(X, Y);
00028 }
00029 
00030 /// It is safe to destroy a constant iff it is only used by constants itself.
00031 /// Note that constants cannot be cyclic, so this test is pretty easy to
00032 /// implement recursively.
00033 ///
00034 bool llvm::isSafeToDestroyConstant(const Constant *C) {
00035   if (isa<GlobalValue>(C))
00036     return false;
00037 
00038   if (isa<ConstantInt>(C) || isa<ConstantFP>(C))
00039     return false;
00040 
00041   for (const User *U : C->users())
00042     if (const Constant *CU = dyn_cast<Constant>(U)) {
00043       if (!isSafeToDestroyConstant(CU))
00044         return false;
00045     } else
00046       return false;
00047   return true;
00048 }
00049 
00050 static bool analyzeGlobalAux(const Value *V, GlobalStatus &GS,
00051                              SmallPtrSetImpl<const PHINode *> &PhiUsers) {
00052   for (const Use &U : V->uses()) {
00053     const User *UR = U.getUser();
00054     if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(UR)) {
00055       GS.HasNonInstructionUser = true;
00056 
00057       // If the result of the constantexpr isn't pointer type, then we won't
00058       // know to expect it in various places.  Just reject early.
00059       if (!isa<PointerType>(CE->getType()))
00060         return true;
00061 
00062       if (analyzeGlobalAux(CE, GS, PhiUsers))
00063         return true;
00064     } else if (const Instruction *I = dyn_cast<Instruction>(UR)) {
00065       if (!GS.HasMultipleAccessingFunctions) {
00066         const Function *F = I->getParent()->getParent();
00067         if (!GS.AccessingFunction)
00068           GS.AccessingFunction = F;
00069         else if (GS.AccessingFunction != F)
00070           GS.HasMultipleAccessingFunctions = true;
00071       }
00072       if (const LoadInst *LI = dyn_cast<LoadInst>(I)) {
00073         GS.IsLoaded = true;
00074         // Don't hack on volatile loads.
00075         if (LI->isVolatile())
00076           return true;
00077         GS.Ordering = strongerOrdering(GS.Ordering, LI->getOrdering());
00078       } else if (const StoreInst *SI = dyn_cast<StoreInst>(I)) {
00079         // Don't allow a store OF the address, only stores TO the address.
00080         if (SI->getOperand(0) == V)
00081           return true;
00082 
00083         // Don't hack on volatile stores.
00084         if (SI->isVolatile())
00085           return true;
00086 
00087         GS.Ordering = strongerOrdering(GS.Ordering, SI->getOrdering());
00088 
00089         // If this is a direct store to the global (i.e., the global is a scalar
00090         // value, not an aggregate), keep more specific information about
00091         // stores.
00092         if (GS.StoredType != GlobalStatus::Stored) {
00093           if (const GlobalVariable *GV =
00094                   dyn_cast<GlobalVariable>(SI->getOperand(1))) {
00095             Value *StoredVal = SI->getOperand(0);
00096 
00097             if (Constant *C = dyn_cast<Constant>(StoredVal)) {
00098               if (C->isThreadDependent()) {
00099                 // The stored value changes between threads; don't track it.
00100                 return true;
00101               }
00102             }
00103 
00104             if (StoredVal == GV->getInitializer()) {
00105               if (GS.StoredType < GlobalStatus::InitializerStored)
00106                 GS.StoredType = GlobalStatus::InitializerStored;
00107             } else if (isa<LoadInst>(StoredVal) &&
00108                        cast<LoadInst>(StoredVal)->getOperand(0) == GV) {
00109               if (GS.StoredType < GlobalStatus::InitializerStored)
00110                 GS.StoredType = GlobalStatus::InitializerStored;
00111             } else if (GS.StoredType < GlobalStatus::StoredOnce) {
00112               GS.StoredType = GlobalStatus::StoredOnce;
00113               GS.StoredOnceValue = StoredVal;
00114             } else if (GS.StoredType == GlobalStatus::StoredOnce &&
00115                        GS.StoredOnceValue == StoredVal) {
00116               // noop.
00117             } else {
00118               GS.StoredType = GlobalStatus::Stored;
00119             }
00120           } else {
00121             GS.StoredType = GlobalStatus::Stored;
00122           }
00123         }
00124       } else if (isa<BitCastInst>(I)) {
00125         if (analyzeGlobalAux(I, GS, PhiUsers))
00126           return true;
00127       } else if (isa<GetElementPtrInst>(I)) {
00128         if (analyzeGlobalAux(I, GS, PhiUsers))
00129           return true;
00130       } else if (isa<SelectInst>(I)) {
00131         if (analyzeGlobalAux(I, GS, PhiUsers))
00132           return true;
00133       } else if (const PHINode *PN = dyn_cast<PHINode>(I)) {
00134         // PHI nodes we can check just like select or GEP instructions, but we
00135         // have to be careful about infinite recursion.
00136         if (PhiUsers.insert(PN)) // Not already visited.
00137           if (analyzeGlobalAux(I, GS, PhiUsers))
00138             return true;
00139       } else if (isa<CmpInst>(I)) {
00140         GS.IsCompared = true;
00141       } else if (const MemTransferInst *MTI = dyn_cast<MemTransferInst>(I)) {
00142         if (MTI->isVolatile())
00143           return true;
00144         if (MTI->getArgOperand(0) == V)
00145           GS.StoredType = GlobalStatus::Stored;
00146         if (MTI->getArgOperand(1) == V)
00147           GS.IsLoaded = true;
00148       } else if (const MemSetInst *MSI = dyn_cast<MemSetInst>(I)) {
00149         assert(MSI->getArgOperand(0) == V && "Memset only takes one pointer!");
00150         if (MSI->isVolatile())
00151           return true;
00152         GS.StoredType = GlobalStatus::Stored;
00153       } else if (ImmutableCallSite C = I) {
00154         if (!C.isCallee(&U))
00155           return true;
00156         GS.IsLoaded = true;
00157       } else {
00158         return true; // Any other non-load instruction might take address!
00159       }
00160     } else if (const Constant *C = dyn_cast<Constant>(UR)) {
00161       GS.HasNonInstructionUser = true;
00162       // We might have a dead and dangling constant hanging off of here.
00163       if (!isSafeToDestroyConstant(C))
00164         return true;
00165     } else {
00166       GS.HasNonInstructionUser = true;
00167       // Otherwise must be some other user.
00168       return true;
00169     }
00170   }
00171 
00172   return false;
00173 }
00174 
00175 bool GlobalStatus::analyzeGlobal(const Value *V, GlobalStatus &GS) {
00176   SmallPtrSet<const PHINode *, 16> PhiUsers;
00177   return analyzeGlobalAux(V, GS, PhiUsers);
00178 }
00179 
00180 GlobalStatus::GlobalStatus()
00181     : IsCompared(false), IsLoaded(false), StoredType(NotStored),
00182       StoredOnceValue(nullptr), AccessingFunction(nullptr),
00183       HasMultipleAccessingFunctions(false), HasNonInstructionUser(false),
00184       Ordering(NotAtomic) {}