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
7 //===----------------------------------------------------------------------===//
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.
14 //===----------------------------------------------------------------------===//
16 #include "llvm/Transforms/IPO/GlobalSplit.h"
17 #include "llvm/ADT/SmallVector.h"
18 #include "llvm/ADT/StringExtras.h"
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"
24 #include "llvm/IR/GlobalVariable.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"
32 #include "llvm/InitializePasses.h"
33 #include "llvm/Pass.h"
34 #include "llvm/Support/Casting.h"
35 #include "llvm/Transforms/IPO.h"
41 static bool splitGlobal(GlobalVariable
&GV
) {
42 // If the address of the global is taken outside of the module, we cannot
43 // apply this transformation.
44 if (!GV
.hasLocalLinkage())
47 // We currently only know how to split ConstantStructs.
48 auto *Init
= dyn_cast_or_null
<ConstantStruct
>(GV
.getInitializer());
52 // Verify that each user of the global is an inrange getelementptr constant.
53 // From this it follows that any loads from or stores to that global must use
54 // a pointer derived from an inrange getelementptr constant, which is
55 // sufficient to allow us to apply the splitting transform.
56 for (User
*U
: GV
.users()) {
57 if (!isa
<Constant
>(U
))
60 auto *GEP
= dyn_cast
<GEPOperator
>(U
);
61 if (!GEP
|| !GEP
->getInRangeIndex() || *GEP
->getInRangeIndex() != 1 ||
62 !isa
<ConstantInt
>(GEP
->getOperand(1)) ||
63 !cast
<ConstantInt
>(GEP
->getOperand(1))->isZero() ||
64 !isa
<ConstantInt
>(GEP
->getOperand(2)))
68 SmallVector
<MDNode
*, 2> Types
;
69 GV
.getMetadata(LLVMContext::MD_type
, Types
);
71 const DataLayout
&DL
= GV
.getParent()->getDataLayout();
72 const StructLayout
*SL
= DL
.getStructLayout(Init
->getType());
74 IntegerType
*Int32Ty
= Type::getInt32Ty(GV
.getContext());
76 std::vector
<GlobalVariable
*> SplitGlobals(Init
->getNumOperands());
77 for (unsigned I
= 0; I
!= Init
->getNumOperands(); ++I
) {
78 // Build a global representing this split piece.
80 new GlobalVariable(*GV
.getParent(), Init
->getOperand(I
)->getType(),
81 GV
.isConstant(), GlobalValue::PrivateLinkage
,
82 Init
->getOperand(I
), GV
.getName() + "." + utostr(I
));
83 SplitGlobals
[I
] = SplitGV
;
85 unsigned SplitBegin
= SL
->getElementOffset(I
);
86 unsigned SplitEnd
= (I
== Init
->getNumOperands() - 1)
87 ? SL
->getSizeInBytes()
88 : SL
->getElementOffset(I
+ 1);
90 // Rebuild type metadata, adjusting by the split offset.
91 // FIXME: See if we can use DW_OP_piece to preserve debug metadata here.
92 for (MDNode
*Type
: Types
) {
93 uint64_t ByteOffset
= cast
<ConstantInt
>(
94 cast
<ConstantAsMetadata
>(Type
->getOperand(0))->getValue())
96 // Type metadata may be attached one byte after the end of the vtable, for
97 // classes without virtual methods in Itanium ABI. AFAIK, it is never
98 // attached to the first byte of a vtable. Subtract one to get the right
100 // This is making an assumption that vtable groups are the only kinds of
101 // global variables that !type metadata can be attached to, and that they
102 // are either Itanium ABI vtable groups or contain a single vtable (i.e.
103 // Microsoft ABI vtables).
104 uint64_t AttachedTo
= (ByteOffset
== 0) ? ByteOffset
: ByteOffset
- 1;
105 if (AttachedTo
< SplitBegin
|| AttachedTo
>= SplitEnd
)
107 SplitGV
->addMetadata(
108 LLVMContext::MD_type
,
109 *MDNode::get(GV
.getContext(),
110 {ConstantAsMetadata::get(
111 ConstantInt::get(Int32Ty
, ByteOffset
- SplitBegin
)),
112 Type
->getOperand(1)}));
115 if (GV
.hasMetadata(LLVMContext::MD_vcall_visibility
))
116 SplitGV
->setVCallVisibilityMetadata(GV
.getVCallVisibility());
119 for (User
*U
: GV
.users()) {
120 auto *GEP
= cast
<GEPOperator
>(U
);
121 unsigned I
= cast
<ConstantInt
>(GEP
->getOperand(2))->getZExtValue();
122 if (I
>= SplitGlobals
.size())
125 SmallVector
<Value
*, 4> Ops
;
126 Ops
.push_back(ConstantInt::get(Int32Ty
, 0));
127 for (unsigned I
= 3; I
!= GEP
->getNumOperands(); ++I
)
128 Ops
.push_back(GEP
->getOperand(I
));
130 auto *NewGEP
= ConstantExpr::getGetElementPtr(
131 SplitGlobals
[I
]->getInitializer()->getType(), SplitGlobals
[I
], Ops
,
133 GEP
->replaceAllUsesWith(NewGEP
);
136 // Finally, remove the original global. Any remaining uses refer to invalid
137 // elements of the global, so replace with undef.
139 GV
.replaceAllUsesWith(UndefValue::get(GV
.getType()));
140 GV
.eraseFromParent();
144 static bool splitGlobals(Module
&M
) {
145 // First, see if the module uses either of the llvm.type.test or
146 // llvm.type.checked.load intrinsics, which indicates that splitting globals
147 // may be beneficial.
148 Function
*TypeTestFunc
=
149 M
.getFunction(Intrinsic::getName(Intrinsic::type_test
));
150 Function
*TypeCheckedLoadFunc
=
151 M
.getFunction(Intrinsic::getName(Intrinsic::type_checked_load
));
152 if ((!TypeTestFunc
|| TypeTestFunc
->use_empty()) &&
153 (!TypeCheckedLoadFunc
|| TypeCheckedLoadFunc
->use_empty()))
156 bool Changed
= false;
157 for (auto I
= M
.global_begin(); I
!= M
.global_end();) {
158 GlobalVariable
&GV
= *I
;
160 Changed
|= splitGlobal(GV
);
167 struct GlobalSplit
: public ModulePass
{
170 GlobalSplit() : ModulePass(ID
) {
171 initializeGlobalSplitPass(*PassRegistry::getPassRegistry());
174 bool runOnModule(Module
&M
) override
{
178 return splitGlobals(M
);
182 } // end anonymous namespace
184 char GlobalSplit::ID
= 0;
186 INITIALIZE_PASS(GlobalSplit
, "globalsplit", "Global splitter", false, false)
188 ModulePass
*llvm::createGlobalSplitPass() {
189 return new GlobalSplit
;
192 PreservedAnalyses
GlobalSplitPass::run(Module
&M
, ModuleAnalysisManager
&AM
) {
193 if (!splitGlobals(M
))
194 return PreservedAnalyses::all();
195 return PreservedAnalyses::none();