10b57cec5SDimitry Andric //===- GlobalStatus.h - Compute status info for globals ---------*- C++ -*-===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 90b57cec5SDimitry Andric #ifndef LLVM_TRANSFORMS_UTILS_GLOBALSTATUS_H 100b57cec5SDimitry Andric #define LLVM_TRANSFORMS_UTILS_GLOBALSTATUS_H 110b57cec5SDimitry Andric 12349cc55cSDimitry Andric #include "llvm/IR/Instructions.h" 130b57cec5SDimitry Andric #include "llvm/Support/AtomicOrdering.h" 140b57cec5SDimitry Andric 150b57cec5SDimitry Andric namespace llvm { 160b57cec5SDimitry Andric 170b57cec5SDimitry Andric class Constant; 180b57cec5SDimitry Andric class Function; 190b57cec5SDimitry Andric class Value; 200b57cec5SDimitry Andric 210b57cec5SDimitry Andric /// It is safe to destroy a constant iff it is only used by constants itself. 220b57cec5SDimitry Andric /// Note that constants cannot be cyclic, so this test is pretty easy to 230b57cec5SDimitry Andric /// implement recursively. 240b57cec5SDimitry Andric /// 250b57cec5SDimitry Andric bool isSafeToDestroyConstant(const Constant *C); 260b57cec5SDimitry Andric 27*0fca6ea1SDimitry Andric /// As we analyze each global or thread-local variable, keep track of some 28*0fca6ea1SDimitry Andric /// information about it. If we find out that the address of the global is 29*0fca6ea1SDimitry Andric /// taken, none of this info will be accurate. 300b57cec5SDimitry Andric struct GlobalStatus { 310b57cec5SDimitry Andric /// True if the global's address is used in a comparison. 320b57cec5SDimitry Andric bool IsCompared = false; 330b57cec5SDimitry Andric 340b57cec5SDimitry Andric /// True if the global is ever loaded. If the global isn't ever loaded it 350b57cec5SDimitry Andric /// can be deleted. 360b57cec5SDimitry Andric bool IsLoaded = false; 370b57cec5SDimitry Andric 3881ad6265SDimitry Andric /// Number of stores to the global. 3981ad6265SDimitry Andric unsigned NumStores = 0; 4081ad6265SDimitry Andric 410b57cec5SDimitry Andric /// Keep track of what stores to the global look like. 420b57cec5SDimitry Andric enum StoredType { 430b57cec5SDimitry Andric /// There is no store to this global. It can thus be marked constant. 440b57cec5SDimitry Andric NotStored, 450b57cec5SDimitry Andric 460b57cec5SDimitry Andric /// This global is stored to, but the only thing stored is the constant it 470b57cec5SDimitry Andric /// was initialized with. This is only tracked for scalar globals. 480b57cec5SDimitry Andric InitializerStored, 490b57cec5SDimitry Andric 500b57cec5SDimitry Andric /// This global is stored to, but only its initializer and one other value 510b57cec5SDimitry Andric /// is ever stored to it. If this global isStoredOnce, we track the value 52349cc55cSDimitry Andric /// stored to it via StoredOnceStore below. This is only tracked for scalar 530b57cec5SDimitry Andric /// globals. 540b57cec5SDimitry Andric StoredOnce, 550b57cec5SDimitry Andric 560b57cec5SDimitry Andric /// This global is stored to by multiple values or something else that we 570b57cec5SDimitry Andric /// cannot track. 580b57cec5SDimitry Andric Stored 590b57cec5SDimitry Andric } StoredType = NotStored; 600b57cec5SDimitry Andric 610b57cec5SDimitry Andric /// If only one value (besides the initializer constant) is ever stored to 62349cc55cSDimitry Andric /// this global, keep track of what value it is via the store instruction. 63349cc55cSDimitry Andric const StoreInst *StoredOnceStore = nullptr; 64349cc55cSDimitry Andric 65349cc55cSDimitry Andric /// If only one value (besides the initializer constant) is ever stored to 66349cc55cSDimitry Andric /// this global return the stored value. getStoredOnceValueGlobalStatus67349cc55cSDimitry Andric Value *getStoredOnceValue() const { 68349cc55cSDimitry Andric return (StoredType == StoredOnce && StoredOnceStore) 69349cc55cSDimitry Andric ? StoredOnceStore->getOperand(0) 70349cc55cSDimitry Andric : nullptr; 71349cc55cSDimitry Andric } 720b57cec5SDimitry Andric 730b57cec5SDimitry Andric /// These start out null/false. When the first accessing function is noticed, 740b57cec5SDimitry Andric /// it is recorded. When a second different accessing function is noticed, 750b57cec5SDimitry Andric /// HasMultipleAccessingFunctions is set to true. 760b57cec5SDimitry Andric const Function *AccessingFunction = nullptr; 770b57cec5SDimitry Andric bool HasMultipleAccessingFunctions = false; 780b57cec5SDimitry Andric 790b57cec5SDimitry Andric /// Set to the strongest atomic ordering requirement. 800b57cec5SDimitry Andric AtomicOrdering Ordering = AtomicOrdering::NotAtomic; 810b57cec5SDimitry Andric 820b57cec5SDimitry Andric GlobalStatus(); 830b57cec5SDimitry Andric 840b57cec5SDimitry Andric /// Look at all uses of the global and fill in the GlobalStatus structure. If 850b57cec5SDimitry Andric /// the global has its address taken, return true to indicate we can't do 860b57cec5SDimitry Andric /// anything with it. 870b57cec5SDimitry Andric static bool analyzeGlobal(const Value *V, GlobalStatus &GS); 880b57cec5SDimitry Andric }; 890b57cec5SDimitry Andric 900b57cec5SDimitry Andric } // end namespace llvm 910b57cec5SDimitry Andric 920b57cec5SDimitry Andric #endif // LLVM_TRANSFORMS_UTILS_GLOBALSTATUS_H 93