LLVM 19.0.0git
Go to the documentation of this file.
1//===- GlobalSplit.cpp - global variable splitter -------------------------===//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
9// This pass uses inrange annotations on GEP indices to split globals where
10// beneficial. Clang currently attaches these annotations to references to
11// virtual table globals under the Itanium ABI for the benefit of the
12// whole-program virtual call optimization and control flow integrity passes.
19#include "llvm/IR/Constant.h"
20#include "llvm/IR/Constants.h"
21#include "llvm/IR/DataLayout.h"
22#include "llvm/IR/Function.h"
23#include "llvm/IR/GlobalValue.h"
25#include "llvm/IR/Intrinsics.h"
26#include "llvm/IR/LLVMContext.h"
27#include "llvm/IR/Metadata.h"
28#include "llvm/IR/Module.h"
29#include "llvm/IR/Operator.h"
30#include "llvm/IR/Type.h"
31#include "llvm/IR/User.h"
33#include "llvm/Transforms/IPO.h"
34#include <cstdint>
35#include <vector>
37using namespace llvm;
39static bool splitGlobal(GlobalVariable &GV) {
40 // If the address of the global is taken outside of the module, we cannot
41 // apply this transformation.
42 if (!GV.hasLocalLinkage())
43 return false;
45 // We currently only know how to split ConstantStructs.
46 auto *Init = dyn_cast_or_null<ConstantStruct>(GV.getInitializer());
47 if (!Init)
48 return false;
50 // Verify that each user of the global is an inrange getelementptr constant.
51 // From this it follows that any loads from or stores to that global must use
52 // a pointer derived from an inrange getelementptr constant, which is
53 // sufficient to allow us to apply the splitting transform.
54 for (User *U : GV.users()) {
55 if (!isa<Constant>(U))
56 return false;
58 auto *GEP = dyn_cast<GEPOperator>(U);
59 if (!GEP || !GEP->getInRangeIndex() || *GEP->getInRangeIndex() != 1 ||
60 !isa<ConstantInt>(GEP->getOperand(1)) ||
61 !cast<ConstantInt>(GEP->getOperand(1))->isZero() ||
62 !isa<ConstantInt>(GEP->getOperand(2)))
63 return false;
64 }
67 GV.getMetadata(LLVMContext::MD_type, Types);
69 const DataLayout &DL = GV.getParent()->getDataLayout();
70 const StructLayout *SL = DL.getStructLayout(Init->getType());
74 std::vector<GlobalVariable *> SplitGlobals(Init->getNumOperands());
75 for (unsigned I = 0; I != Init->getNumOperands(); ++I) {
76 // Build a global representing this split piece.
77 auto *SplitGV =
78 new GlobalVariable(*GV.getParent(), Init->getOperand(I)->getType(),
80 Init->getOperand(I), GV.getName() + "." + utostr(I));
81 SplitGlobals[I] = SplitGV;
83 unsigned SplitBegin = SL->getElementOffset(I);
84 unsigned SplitEnd = (I == Init->getNumOperands() - 1)
85 ? SL->getSizeInBytes()
86 : SL->getElementOffset(I + 1);
88 // Rebuild type metadata, adjusting by the split offset.
89 // FIXME: See if we can use DW_OP_piece to preserve debug metadata here.
90 for (MDNode *Type : Types) {
91 uint64_t ByteOffset = cast<ConstantInt>(
92 cast<ConstantAsMetadata>(Type->getOperand(0))->getValue())
93 ->getZExtValue();
94 // Type metadata may be attached one byte after the end of the vtable, for
95 // classes without virtual methods in Itanium ABI. AFAIK, it is never
96 // attached to the first byte of a vtable. Subtract one to get the right
97 // slice.
98 // This is making an assumption that vtable groups are the only kinds of
99 // global variables that !type metadata can be attached to, and that they
100 // are either Itanium ABI vtable groups or contain a single vtable (i.e.
101 // Microsoft ABI vtables).
102 uint64_t AttachedTo = (ByteOffset == 0) ? ByteOffset : ByteOffset - 1;
103 if (AttachedTo < SplitBegin || AttachedTo >= SplitEnd)
104 continue;
105 SplitGV->addMetadata(
106 LLVMContext::MD_type,
108 {ConstantAsMetadata::get(
109 ConstantInt::get(Int32Ty, ByteOffset - SplitBegin)),
110 Type->getOperand(1)}));
111 }
113 if (GV.hasMetadata(LLVMContext::MD_vcall_visibility))
114 SplitGV->setVCallVisibilityMetadata(GV.getVCallVisibility());
115 }
117 for (User *U : GV.users()) {
118 auto *GEP = cast<GEPOperator>(U);
119 unsigned I = cast<ConstantInt>(GEP->getOperand(2))->getZExtValue();
120 if (I >= SplitGlobals.size())
121 continue;
124 Ops.push_back(ConstantInt::get(Int32Ty, 0));
125 for (unsigned I = 3; I != GEP->getNumOperands(); ++I)
126 Ops.push_back(GEP->getOperand(I));
128 auto *NewGEP = ConstantExpr::getGetElementPtr(
129 SplitGlobals[I]->getInitializer()->getType(), SplitGlobals[I], Ops,
130 GEP->isInBounds());
131 GEP->replaceAllUsesWith(NewGEP);
132 }
134 // Finally, remove the original global. Any remaining uses refer to invalid
135 // elements of the global, so replace with poison.
136 if (!GV.use_empty())
138 GV.eraseFromParent();
139 return true;
142static bool splitGlobals(Module &M) {
143 // First, see if the module uses either of the llvm.type.test or
144 // llvm.type.checked.load intrinsics, which indicates that splitting globals
145 // may be beneficial.
146 Function *TypeTestFunc =
147 M.getFunction(Intrinsic::getName(Intrinsic::type_test));
148 Function *TypeCheckedLoadFunc =
149 M.getFunction(Intrinsic::getName(Intrinsic::type_checked_load));
150 Function *TypeCheckedLoadRelativeFunc =
151 M.getFunction(Intrinsic::getName(Intrinsic::type_checked_load_relative));
152 if ((!TypeTestFunc || TypeTestFunc->use_empty()) &&
153 (!TypeCheckedLoadFunc || TypeCheckedLoadFunc->use_empty()) &&
154 (!TypeCheckedLoadRelativeFunc ||
155 TypeCheckedLoadRelativeFunc->use_empty()))
156 return false;
158 bool Changed = false;
159 for (GlobalVariable &GV : llvm::make_early_inc_range(M.globals()))
160 Changed |= splitGlobal(GV);
161 return Changed;
165 if (!splitGlobals(M))
166 return PreservedAnalyses::all();
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
This file contains the declarations for the subclasses of Constant, which represent the different fla...
static bool splitGlobals(Module &M)
static bool splitGlobal(GlobalVariable &GV)
Definition: GlobalSplit.cpp:39
Hexagon Common GEP
#define I(x, y, z)
Definition: MD5.cpp:58
This file contains the declarations for metadata subclasses.
Module.h This file contains the declarations for the Module class.
IntegerType * Int32Ty
This file defines the SmallVector class.
This file contains some functions that are useful when dealing with strings.
static SymbolRef::Type getType(const Symbol *Sym)
Definition: TapiFile.cpp:40
A container for analyses that lazily runs them and caches their results.
Definition: PassManager.h:348
static Constant * getGetElementPtr(Type *Ty, Constant *C, ArrayRef< Constant * > IdxList, bool InBounds=false, std::optional< unsigned > InRangeIndex=std::nullopt, Type *OnlyIfReducedTy=nullptr)
Getelementptr form.
Definition: Constants.h:1201
A parsed version of the target data layout string in and methods for querying it.
Definition: DataLayout.h:110
bool hasMetadata() const
Return true if this value has any metadata attached to it.
Definition: Value.h:589
VCallVisibility getVCallVisibility() const
Definition: Metadata.cpp:1813
MDNode * getMetadata(unsigned KindID) const
Get the current metadata attachments for the given kind, if any.
Definition: Value.h:565
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
bool hasLocalLinkage() const
Definition: GlobalValue.h:527
Module * getParent()
Get the module that this global value is contained inside of...
Definition: GlobalValue.h:655
PointerType * getType() const
Global values are always pointers.
Definition: GlobalValue.h:294
@ PrivateLinkage
Like Internal, but omit from symbol table.
Definition: GlobalValue.h:60
const Constant * getInitializer() const
getInitializer - Return the initializer for this global variable.
bool isConstant() const
If the value is a global constant, its value is immutable throughout the runtime execution of the pro...
void eraseFromParent()
eraseFromParent - This method unlinks 'this' from the containing module and deletes it.
Definition: Globals.cpp:455
Class to represent integer types.
Definition: DerivedTypes.h:40
Metadata node.
Definition: Metadata.h:1067
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
Definition: Metadata.h:1541
A Module instance is used to store all the information related to an LLVM module.
Definition: Module.h:65
const DataLayout & getDataLayout() const
Get the data layout for the module's target platform.
Definition: Module.h:275
static PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
Definition: Constants.cpp:1827
A set of analyses that are preserved following a run of a transformation pass.
Definition: Analysis.h:109
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
Definition: Analysis.h:112
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition: Analysis.h:115
void push_back(const T &Elt)
Definition: SmallVector.h:426
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1209
Used to lazily calculate structure layout information for a target machine, based on the DataLayout s...
Definition: DataLayout.h:622
TypeSize getSizeInBytes() const
Definition: DataLayout.h:629
TypeSize getElementOffset(unsigned Idx) const
Definition: DataLayout.h:651
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
static IntegerType * getInt32Ty(LLVMContext &C)
void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
Definition: Value.cpp:534
iterator_range< user_iterator > users()
Definition: Value.h:421
bool use_empty() const
Definition: Value.h:344
LLVMContext & getContext() const
All values hold a context through their type.
Definition: Value.cpp:1074
StringRef getName() const
Return a constant reference to the value's name.
Definition: Value.cpp:309
StringRef getName(ID id)
Return the LLVM name for an intrinsic, such as "llvm.ppc.altivec.lvx".
Definition: Function.cpp:1013
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
Definition: STLExtras.h:665