blob: 7a2dc7d3d90985cbe02cd56e30aa9100508d130e [file] [log] [blame]
David Neto22f144c2017-06-12 14:26:21 -04001// Copyright 2017 The Clspv Authors. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
David Neto862b7d82018-06-14 18:48:37 -040015#include "llvm/IR/IRBuilder.h"
16#include "llvm/IR/Instructions.h"
17#include "llvm/IR/Module.h"
18#include "llvm/Pass.h"
19#include "llvm/Support/raw_ostream.h"
David Neto22f144c2017-06-12 14:26:21 -040020
Diego Novilloa4c44fa2019-04-11 10:56:15 -040021#include "Passes.h"
22
David Neto22f144c2017-06-12 14:26:21 -040023using namespace llvm;
24
25#define DEBUG_TYPE "SimplifyPointerBitcast"
26
27namespace {
28struct SimplifyPointerBitcastPass : public ModulePass {
29 static char ID;
30 SimplifyPointerBitcastPass() : ModulePass(ID) {}
31
32 bool runOnModule(Module &M) override;
33
David Neto973e6a82017-05-30 13:48:18 -040034 bool runOnTrivialBitcast(Module &M) const;
David Neto22f144c2017-06-12 14:26:21 -040035 bool runOnBitcastFromBitcast(Module &M) const;
36 bool runOnBitcastFromGEP(Module &M) const;
37 bool runOnGEPFromGEP(Module &M) const;
38};
Diego Novillo3cc8d7a2019-04-10 13:30:34 -040039} // namespace
David Neto22f144c2017-06-12 14:26:21 -040040
41char SimplifyPointerBitcastPass::ID = 0;
Diego Novilloa4c44fa2019-04-11 10:56:15 -040042INITIALIZE_PASS(SimplifyPointerBitcastPass, "SimplifyPointerBitcast",
43 "Simplify Pointer Bitcast Pass", false, false)
David Neto22f144c2017-06-12 14:26:21 -040044
45namespace clspv {
46llvm::ModulePass *createSimplifyPointerBitcastPass() {
47 return new SimplifyPointerBitcastPass();
48}
Diego Novillo3cc8d7a2019-04-10 13:30:34 -040049} // namespace clspv
David Neto22f144c2017-06-12 14:26:21 -040050
51bool SimplifyPointerBitcastPass::runOnModule(Module &M) {
52 bool Changed = false;
53
54 // Loop through our individual simplification passes until they stop changing
55 // things.
56 for (bool localChanged = true; localChanged; Changed |= localChanged) {
57 localChanged = false;
58
David Neto973e6a82017-05-30 13:48:18 -040059 localChanged |= runOnTrivialBitcast(M);
David Neto22f144c2017-06-12 14:26:21 -040060 localChanged |= runOnBitcastFromGEP(M);
61 localChanged |= runOnBitcastFromBitcast(M);
62 localChanged |= runOnGEPFromGEP(M);
63 }
64
65 return Changed;
66}
67
David Neto973e6a82017-05-30 13:48:18 -040068bool SimplifyPointerBitcastPass::runOnTrivialBitcast(Module &M) const {
69 // Remove things like:
70 // bitcast i32 addrspace(1)* %ptr to i32 addrspace(1)*
71
72 SmallVector<BitCastInst *, 16> WorkList;
73 for (Function &F : M) {
74 for (BasicBlock &BB : F) {
75 for (Instruction &I : BB) {
76 // If we have a bitcast instruction...
77 if (auto Bitcast = dyn_cast<BitCastInst>(&I)) {
78 // ... whose source type is the same as the destination type.
79 auto Source = Bitcast->getOperand(0);
80 if (Source->getType() == Bitcast->getType()) {
81 // ... record the bitcast as something we need to process.
82 WorkList.push_back(Bitcast);
83 }
84 }
85 }
86 }
87 }
88
89 const bool Changed = !WorkList.empty();
90
91 for (auto Bitcast : WorkList) {
92 auto Source = Bitcast->getOperand(0);
93 Bitcast->replaceAllUsesWith(Source);
94
95 // Remove the bitcast as it has no users now.
96 Bitcast->eraseFromParent();
97
98 // Check if the source value is an instruction and had no other users...
99 if (auto SourceInst = dyn_cast<Instruction>(Source)) {
100 if (0 == SourceInst->getNumUses()) {
101 // ... and remove it if we were its only user.
102 SourceInst->eraseFromParent();
103 }
104 }
105 }
106
107 return Changed;
108}
109
David Neto22f144c2017-06-12 14:26:21 -0400110bool SimplifyPointerBitcastPass::runOnBitcastFromGEP(Module &M) const {
111 SmallVector<BitCastInst *, 16> WorkList;
112 for (Function &F : M) {
113 for (BasicBlock &BB : F) {
114 for (Instruction &I : BB) {
115 // If we have a bitcast instruction...
116 if (auto Bitcast = dyn_cast<BitCastInst>(&I)) {
117 // ... whose source is a GEP instruction...
118 if (auto GEP = dyn_cast<GetElementPtrInst>(Bitcast->getOperand(0))) {
119 // ... where the GEP is retrieving an element of the same type...
120 if (GEP->getSourceElementType() == GEP->getResultElementType()) {
121 auto GEPTy = GEP->getResultElementType();
122 auto BitcastTy = Bitcast->getType()->getPointerElementType();
123 // ... and the types have a known compile time size...
124 if ((0 != GEPTy->getPrimitiveSizeInBits()) &&
125 (0 != BitcastTy->getPrimitiveSizeInBits())) {
126 // ... record the bitcast as something we need to process.
127 WorkList.push_back(Bitcast);
128 }
129 }
130 }
131 }
132 }
133 }
134 }
135
136 const bool Changed = !WorkList.empty();
137
138 for (auto Bitcast : WorkList) {
139 auto BitcastTy = Bitcast->getType();
140 auto BitcastElementTy = BitcastTy->getPointerElementType();
141
142 auto GEP = cast<GetElementPtrInst>(Bitcast->getOperand(0));
143
144 auto SrcTySize = GEP->getResultElementType()->getPrimitiveSizeInBits();
145 auto DstTySize = BitcastElementTy->getPrimitiveSizeInBits();
146
147 SmallVector<Value *, 4> GEPArgs(GEP->idx_begin(), GEP->idx_end());
148
149 // If the source type is smaller than the destination type...
150 if (SrcTySize < DstTySize) {
151 // ... we need to divide the last index of the GEP by the size difference.
152 auto LastIndex = GEPArgs.back();
153 GEPArgs.back() = BinaryOperator::Create(
154 Instruction::SDiv, LastIndex,
155 ConstantInt::get(LastIndex->getType(), DstTySize / SrcTySize), "",
156 Bitcast);
157 } else if (SrcTySize > DstTySize) {
158 // ... we need to multiply the last index of the GEP by the size
159 // difference.
160 auto LastIndex = GEPArgs.back();
161 GEPArgs.back() = BinaryOperator::Create(
162 Instruction::Mul, LastIndex,
163 ConstantInt::get(LastIndex->getType(), SrcTySize / DstTySize), "",
164 Bitcast);
165 } else {
166 // ... the arguments are the same size, nothing to do!
167 }
168
169 // Create a new bitcast from the GEP argument to the bitcast type.
170 auto NewBitcast = CastInst::CreatePointerCast(GEP->getPointerOperand(),
171 BitcastTy, "", Bitcast);
172
173 // Create a new GEP from the (maybe modified) GEPArgs.
174 auto NewGEP = GetElementPtrInst::Create(BitcastElementTy, NewBitcast,
175 GEPArgs, "", Bitcast);
176
177 // And replace the original bitcast with our replacement GEP.
178 Bitcast->replaceAllUsesWith(NewGEP);
179
180 // Remove the bitcast as it has no users now.
181 Bitcast->eraseFromParent();
182
183 // Check if the old GEP had no other users...
184 if (0 == GEP->getNumUses()) {
185 // ... and remove it if we were its only user.
186 GEP->eraseFromParent();
187 }
188 }
189
190 return Changed;
191}
192
193bool SimplifyPointerBitcastPass::runOnBitcastFromBitcast(Module &M) const {
194 SmallVector<BitCastInst *, 16> WorkList;
195 for (Function &F : M) {
196 for (BasicBlock &BB : F) {
197 for (Instruction &I : BB) {
198 // If we have a bitcast instruction...
199 if (auto Bitcast = dyn_cast<BitCastInst>(&I)) {
200 // ... whose source is a bitcast instruction...
201 if (isa<BitCastInst>(Bitcast->getOperand(0))) {
202 // ... record the bitcast as something we need to process.
203 WorkList.push_back(Bitcast);
204 }
205 }
206 }
207 }
208 }
209
210 const bool Changed = !WorkList.empty();
211
212 for (auto Bitcast : WorkList) {
213 auto OtherBitcast = cast<BitCastInst>(Bitcast->getOperand(0));
214
David Neto973e6a82017-05-30 13:48:18 -0400215 if (OtherBitcast->getType() == Bitcast->getType()) {
216 Bitcast->replaceAllUsesWith(OtherBitcast);
217 } else {
218 // Create a new bitcast from the other bitcasts argument to our type.
219 auto NewBitcast = CastInst::CreatePointerCast(
220 OtherBitcast->getOperand(0), Bitcast->getType(), "", Bitcast);
David Neto22f144c2017-06-12 14:26:21 -0400221
David Neto973e6a82017-05-30 13:48:18 -0400222 // And replace the original bitcast with our replacement bitcast.
223 Bitcast->replaceAllUsesWith(NewBitcast);
224 }
David Neto22f144c2017-06-12 14:26:21 -0400225
226 // Remove the bitcast as it has no users now.
227 Bitcast->eraseFromParent();
228
229 // Check if the other bitcast had no other users...
230 if (0 == OtherBitcast->getNumUses()) {
231 // ... and remove it if we were its only user.
232 OtherBitcast->eraseFromParent();
233 }
234 }
235
236 return Changed;
237}
238
239bool SimplifyPointerBitcastPass::runOnGEPFromGEP(Module &M) const {
240 SmallVector<GetElementPtrInst *, 16> WorkList;
241 for (Function &F : M) {
242 for (BasicBlock &BB : F) {
243 for (Instruction &I : BB) {
244 // If we have a GEP instruction...
245 if (auto GEP = dyn_cast<GetElementPtrInst>(&I)) {
246 // ... whose operand is also a GEP instruction...
247 if (isa<GetElementPtrInst>(GEP->getPointerOperand())) {
248 // ... record the GEP as something we need to process.
249 WorkList.push_back(GEP);
250 }
251 }
252 }
253 }
254 }
255
256 const bool Changed = !WorkList.empty();
257
258 for (GetElementPtrInst *GEP : WorkList) {
259 IRBuilder<> Builder(GEP);
260
261 auto OtherGEP = cast<GetElementPtrInst>(GEP->getPointerOperand());
262
263 SmallVector<Value *, 8> Idxs;
264
265 Value *SrcLastIdxOp = OtherGEP->getOperand(OtherGEP->getNumOperands() - 1);
David Neto862b7d82018-06-14 18:48:37 -0400266
David Neto22f144c2017-06-12 14:26:21 -0400267 Value *GEPIdxOp = GEP->getOperand(1);
David Neto862b7d82018-06-14 18:48:37 -0400268 Value *MergedIdx = GEPIdxOp;
269
270 // Add the indices together, if the last one from before is not zero.
271 bool last_idx_is_zero = false;
272 if (auto *constant = dyn_cast<ConstantInt>(SrcLastIdxOp)) {
273 last_idx_is_zero = constant->isZero();
274 }
275 if (!last_idx_is_zero) {
276 MergedIdx = Builder.CreateAdd(SrcLastIdxOp, GEPIdxOp);
277 }
David Neto22f144c2017-06-12 14:26:21 -0400278
279 Idxs.append(OtherGEP->op_begin() + 1, OtherGEP->op_end() - 1);
280 Idxs.push_back(MergedIdx);
281 Idxs.append(GEP->op_begin() + 2, GEP->op_end());
282
283 Value *NewGEP = nullptr;
David Neto862b7d82018-06-14 18:48:37 -0400284 // Create the new GEP. If we used the Builder it will do some folding
285 // that we don't want. In particular, if the first GEP is to an LLVM
286 // constant then the combined GEP will become a ConstantExpr and it
287 // will hide the pointer from subsequent passes. So bypass the Builder
288 // and create the GEP instruction directly.
David Neto22f144c2017-06-12 14:26:21 -0400289 if (GEP->isInBounds() && OtherGEP->isInBounds()) {
David Neto862b7d82018-06-14 18:48:37 -0400290 NewGEP = GetElementPtrInst::CreateInBounds(
291 nullptr, OtherGEP->getPointerOperand(), Idxs, "", GEP);
David Neto22f144c2017-06-12 14:26:21 -0400292 } else {
David Neto862b7d82018-06-14 18:48:37 -0400293 NewGEP = GetElementPtrInst::Create(nullptr, OtherGEP->getPointerOperand(),
294 Idxs, "", GEP);
David Neto22f144c2017-06-12 14:26:21 -0400295 }
296
297 // And replace the original GEP with our replacement GEP.
298 GEP->replaceAllUsesWith(NewGEP);
299
300 // Remove the GEP as it has no users now.
301 GEP->eraseFromParent();
302
303 // Check if the other GEP had no other users...
304 if (0 == OtherGEP->getNumUses()) {
305 // ... and remove it if we were its only user.
306 OtherGEP->eraseFromParent();
307 }
308 }
309
310 return Changed;
311}