xref: /freebsd/contrib/llvm-project/llvm/include/llvm/Transforms/Utils/GlobalStatus.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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