/Users/buildslave/jenkins/sharedspace/clang-stage2-coverage-R@2/llvm/lib/Transforms/IPO/GlobalSplit.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===- GlobalSplit.cpp - global variable splitter -------------------------===// |
2 | | // |
3 | | // The LLVM Compiler Infrastructure |
4 | | // |
5 | | // This file is distributed under the University of Illinois Open Source |
6 | | // License. See LICENSE.TXT for details. |
7 | | // |
8 | | //===----------------------------------------------------------------------===// |
9 | | // |
10 | | // This pass uses inrange annotations on GEP indices to split globals where |
11 | | // beneficial. Clang currently attaches these annotations to references to |
12 | | // virtual table globals under the Itanium ABI for the benefit of the |
13 | | // whole-program virtual call optimization and control flow integrity passes. |
14 | | // |
15 | | //===----------------------------------------------------------------------===// |
16 | | |
17 | | #include "llvm/Transforms/IPO/GlobalSplit.h" |
18 | | #include "llvm/ADT/StringExtras.h" |
19 | | #include "llvm/IR/Constants.h" |
20 | | #include "llvm/IR/GlobalVariable.h" |
21 | | #include "llvm/IR/Intrinsics.h" |
22 | | #include "llvm/IR/Module.h" |
23 | | #include "llvm/IR/Operator.h" |
24 | | #include "llvm/Pass.h" |
25 | | #include "llvm/Transforms/IPO.h" |
26 | | |
27 | | #include <set> |
28 | | |
29 | | using namespace llvm; |
30 | | |
31 | | namespace { |
32 | | |
33 | 5 | bool splitGlobal(GlobalVariable &GV) { |
34 | 5 | // If the address of the global is taken outside of the module, we cannot |
35 | 5 | // apply this transformation. |
36 | 5 | if (!GV.hasLocalLinkage()) |
37 | 3 | return false; |
38 | 2 | |
39 | 2 | // We currently only know how to split ConstantStructs. |
40 | 2 | auto *Init = dyn_cast_or_null<ConstantStruct>(GV.getInitializer()); |
41 | 2 | if (!Init) |
42 | 0 | return false; |
43 | 2 | |
44 | 2 | // Verify that each user of the global is an inrange getelementptr constant. |
45 | 2 | // From this it follows that any loads from or stores to that global must use |
46 | 2 | // a pointer derived from an inrange getelementptr constant, which is |
47 | 2 | // sufficient to allow us to apply the splitting transform. |
48 | 2 | for (User *U : GV.users()) 2 { |
49 | 14 | if (!isa<Constant>(U)) |
50 | 0 | return false; |
51 | 14 | |
52 | 14 | auto *GEP = dyn_cast<GEPOperator>(U); |
53 | 14 | if (!GEP || 14 !GEP->getInRangeIndex()14 || *GEP->getInRangeIndex() != 114 || |
54 | 14 | !isa<ConstantInt>(GEP->getOperand(1)) || |
55 | 14 | !cast<ConstantInt>(GEP->getOperand(1))->isZero() || |
56 | 14 | !isa<ConstantInt>(GEP->getOperand(2))) |
57 | 0 | return false; |
58 | 2 | } |
59 | 2 | |
60 | 2 | SmallVector<MDNode *, 2> Types; |
61 | 2 | GV.getMetadata(LLVMContext::MD_type, Types); |
62 | 2 | |
63 | 2 | const DataLayout &DL = GV.getParent()->getDataLayout(); |
64 | 2 | const StructLayout *SL = DL.getStructLayout(Init->getType()); |
65 | 2 | |
66 | 2 | IntegerType *Int32Ty = Type::getInt32Ty(GV.getContext()); |
67 | 2 | |
68 | 2 | std::vector<GlobalVariable *> SplitGlobals(Init->getNumOperands()); |
69 | 6 | for (unsigned I = 0; I != Init->getNumOperands()6 ; ++I4 ) { |
70 | 4 | // Build a global representing this split piece. |
71 | 4 | auto *SplitGV = |
72 | 4 | new GlobalVariable(*GV.getParent(), Init->getOperand(I)->getType(), |
73 | 4 | GV.isConstant(), GlobalValue::PrivateLinkage, |
74 | 4 | Init->getOperand(I), GV.getName() + "." + utostr(I)); |
75 | 4 | SplitGlobals[I] = SplitGV; |
76 | 4 | |
77 | 4 | unsigned SplitBegin = SL->getElementOffset(I); |
78 | 4 | unsigned SplitEnd = (I == Init->getNumOperands() - 1) |
79 | 2 | ? SL->getSizeInBytes() |
80 | 2 | : SL->getElementOffset(I + 1); |
81 | 4 | |
82 | 4 | // Rebuild type metadata, adjusting by the split offset. |
83 | 4 | // FIXME: See if we can use DW_OP_piece to preserve debug metadata here. |
84 | 20 | for (MDNode *Type : Types) { |
85 | 20 | uint64_t ByteOffset = cast<ConstantInt>( |
86 | 20 | cast<ConstantAsMetadata>(Type->getOperand(0))->getValue()) |
87 | 20 | ->getZExtValue(); |
88 | 20 | // Type metadata may be attached one byte after the end of the vtable, for |
89 | 20 | // classes without virtual methods in Itanium ABI. AFAIK, it is never |
90 | 20 | // attached to the first byte of a vtable. Subtract one to get the right |
91 | 20 | // slice. |
92 | 20 | // This is making an assumption that vtable groups are the only kinds of |
93 | 20 | // global variables that !type metadata can be attached to, and that they |
94 | 20 | // are either Itanium ABI vtable groups or contain a single vtable (i.e. |
95 | 20 | // Microsoft ABI vtables). |
96 | 20 | uint64_t AttachedTo = (ByteOffset == 0) ? ByteOffset4 : ByteOffset - 116 ; |
97 | 20 | if (AttachedTo < SplitBegin || 20 AttachedTo >= SplitEnd14 ) |
98 | 10 | continue; |
99 | 10 | SplitGV->addMetadata( |
100 | 10 | LLVMContext::MD_type, |
101 | 10 | *MDNode::get(GV.getContext(), |
102 | 10 | {ConstantAsMetadata::get( |
103 | 10 | ConstantInt::get(Int32Ty, ByteOffset - SplitBegin)), |
104 | 10 | Type->getOperand(1)})); |
105 | 10 | } |
106 | 4 | } |
107 | 2 | |
108 | 14 | for (User *U : GV.users()) { |
109 | 14 | auto *GEP = cast<GEPOperator>(U); |
110 | 14 | unsigned I = cast<ConstantInt>(GEP->getOperand(2))->getZExtValue(); |
111 | 14 | if (I >= SplitGlobals.size()) |
112 | 0 | continue; |
113 | 14 | |
114 | 14 | SmallVector<Value *, 4> Ops; |
115 | 14 | Ops.push_back(ConstantInt::get(Int32Ty, 0)); |
116 | 28 | for (unsigned I = 3; I != GEP->getNumOperands()28 ; ++I14 ) |
117 | 14 | Ops.push_back(GEP->getOperand(I)); |
118 | 14 | |
119 | 14 | auto *NewGEP = ConstantExpr::getGetElementPtr( |
120 | 14 | SplitGlobals[I]->getInitializer()->getType(), SplitGlobals[I], Ops, |
121 | 14 | GEP->isInBounds()); |
122 | 14 | GEP->replaceAllUsesWith(NewGEP); |
123 | 14 | } |
124 | 2 | |
125 | 2 | // Finally, remove the original global. Any remaining uses refer to invalid |
126 | 2 | // elements of the global, so replace with undef. |
127 | 2 | if (!GV.use_empty()) |
128 | 2 | GV.replaceAllUsesWith(UndefValue::get(GV.getType())); |
129 | 5 | GV.eraseFromParent(); |
130 | 5 | return true; |
131 | 5 | } |
132 | | |
133 | 218 | bool splitGlobals(Module &M) { |
134 | 218 | // First, see if the module uses either of the llvm.type.test or |
135 | 218 | // llvm.type.checked.load intrinsics, which indicates that splitting globals |
136 | 218 | // may be beneficial. |
137 | 218 | Function *TypeTestFunc = |
138 | 218 | M.getFunction(Intrinsic::getName(Intrinsic::type_test)); |
139 | 218 | Function *TypeCheckedLoadFunc = |
140 | 218 | M.getFunction(Intrinsic::getName(Intrinsic::type_checked_load)); |
141 | 218 | if ((!TypeTestFunc || 218 TypeTestFunc->use_empty()3 ) && |
142 | 215 | (!TypeCheckedLoadFunc || 215 TypeCheckedLoadFunc->use_empty()0 )) |
143 | 215 | return false; |
144 | 3 | |
145 | 3 | bool Changed = false; |
146 | 8 | for (auto I = M.global_begin(); I != M.global_end()8 ;) { |
147 | 5 | GlobalVariable &GV = *I; |
148 | 5 | ++I; |
149 | 5 | Changed |= splitGlobal(GV); |
150 | 5 | } |
151 | 218 | return Changed; |
152 | 218 | } |
153 | | |
154 | | struct GlobalSplit : public ModulePass { |
155 | | static char ID; |
156 | 209 | GlobalSplit() : ModulePass(ID) { |
157 | 209 | initializeGlobalSplitPass(*PassRegistry::getPassRegistry()); |
158 | 209 | } |
159 | 209 | bool runOnModule(Module &M) { |
160 | 209 | if (skipModule(M)) |
161 | 0 | return false; |
162 | 209 | |
163 | 209 | return splitGlobals(M); |
164 | 209 | } |
165 | | }; |
166 | | |
167 | | } |
168 | | |
169 | | INITIALIZE_PASS(GlobalSplit, "globalsplit", "Global splitter", false, false) |
170 | | char GlobalSplit::ID = 0; |
171 | | |
172 | 206 | ModulePass *llvm::createGlobalSplitPass() { |
173 | 206 | return new GlobalSplit; |
174 | 206 | } |
175 | | |
176 | 9 | PreservedAnalyses GlobalSplitPass::run(Module &M, ModuleAnalysisManager &AM) { |
177 | 9 | if (!splitGlobals(M)) |
178 | 8 | return PreservedAnalyses::all(); |
179 | 1 | return PreservedAnalyses::none(); |
180 | 1 | } |