blob: 3a77732c85e7d8a2f0b97b3e849b72bfe70b7272 [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
21using namespace llvm;
22
23#define DEBUG_TYPE "SimplifyPointerBitcast"
24
25namespace {
26struct SimplifyPointerBitcastPass : public ModulePass {
27 static char ID;
28 SimplifyPointerBitcastPass() : ModulePass(ID) {}
29
30 bool runOnModule(Module &M) override;
31
David Neto973e6a82017-05-30 13:48:18 -040032 bool runOnTrivialBitcast(Module &M) const;
David Neto22f144c2017-06-12 14:26:21 -040033 bool runOnBitcastFromBitcast(Module &M) const;
34 bool runOnBitcastFromGEP(Module &M) const;
35 bool runOnGEPFromGEP(Module &M) const;
36};
37}
38
39char SimplifyPointerBitcastPass::ID = 0;
40static RegisterPass<SimplifyPointerBitcastPass>
41 X("SimplifyPointerBitcast", "Simplify Pointer Bitcast Pass");
42
43namespace clspv {
44llvm::ModulePass *createSimplifyPointerBitcastPass() {
45 return new SimplifyPointerBitcastPass();
46}
47}
48
49bool SimplifyPointerBitcastPass::runOnModule(Module &M) {
50 bool Changed = false;
51
52 // Loop through our individual simplification passes until they stop changing
53 // things.
54 for (bool localChanged = true; localChanged; Changed |= localChanged) {
55 localChanged = false;
56
David Neto973e6a82017-05-30 13:48:18 -040057 localChanged |= runOnTrivialBitcast(M);
David Neto22f144c2017-06-12 14:26:21 -040058 localChanged |= runOnBitcastFromGEP(M);
59 localChanged |= runOnBitcastFromBitcast(M);
60 localChanged |= runOnGEPFromGEP(M);
61 }
62
63 return Changed;
64}
65
David Neto973e6a82017-05-30 13:48:18 -040066bool SimplifyPointerBitcastPass::runOnTrivialBitcast(Module &M) const {
67 // Remove things like:
68 // bitcast i32 addrspace(1)* %ptr to i32 addrspace(1)*
69
70 SmallVector<BitCastInst *, 16> WorkList;
71 for (Function &F : M) {
72 for (BasicBlock &BB : F) {
73 for (Instruction &I : BB) {
74 // If we have a bitcast instruction...
75 if (auto Bitcast = dyn_cast<BitCastInst>(&I)) {
76 // ... whose source type is the same as the destination type.
77 auto Source = Bitcast->getOperand(0);
78 if (Source->getType() == Bitcast->getType()) {
79 // ... record the bitcast as something we need to process.
80 WorkList.push_back(Bitcast);
81 }
82 }
83 }
84 }
85 }
86
87 const bool Changed = !WorkList.empty();
88
89 for (auto Bitcast : WorkList) {
90 auto Source = Bitcast->getOperand(0);
91 Bitcast->replaceAllUsesWith(Source);
92
93 // Remove the bitcast as it has no users now.
94 Bitcast->eraseFromParent();
95
96 // Check if the source value is an instruction and had no other users...
97 if (auto SourceInst = dyn_cast<Instruction>(Source)) {
98 if (0 == SourceInst->getNumUses()) {
99 // ... and remove it if we were its only user.
100 SourceInst->eraseFromParent();
101 }
102 }
103 }
104
105 return Changed;
106}
107
David Neto22f144c2017-06-12 14:26:21 -0400108bool SimplifyPointerBitcastPass::runOnBitcastFromGEP(Module &M) const {
109 SmallVector<BitCastInst *, 16> WorkList;
110 for (Function &F : M) {
111 for (BasicBlock &BB : F) {
112 for (Instruction &I : BB) {
113 // If we have a bitcast instruction...
114 if (auto Bitcast = dyn_cast<BitCastInst>(&I)) {
115 // ... whose source is a GEP instruction...
116 if (auto GEP = dyn_cast<GetElementPtrInst>(Bitcast->getOperand(0))) {
117 // ... where the GEP is retrieving an element of the same type...
118 if (GEP->getSourceElementType() == GEP->getResultElementType()) {
119 auto GEPTy = GEP->getResultElementType();
120 auto BitcastTy = Bitcast->getType()->getPointerElementType();
121 // ... and the types have a known compile time size...
122 if ((0 != GEPTy->getPrimitiveSizeInBits()) &&
123 (0 != BitcastTy->getPrimitiveSizeInBits())) {
124 // ... record the bitcast as something we need to process.
125 WorkList.push_back(Bitcast);
126 }
127 }
128 }
129 }
130 }
131 }
132 }
133
134 const bool Changed = !WorkList.empty();
135
136 for (auto Bitcast : WorkList) {
137 auto BitcastTy = Bitcast->getType();
138 auto BitcastElementTy = BitcastTy->getPointerElementType();
139
140 auto GEP = cast<GetElementPtrInst>(Bitcast->getOperand(0));
141
142 auto SrcTySize = GEP->getResultElementType()->getPrimitiveSizeInBits();
143 auto DstTySize = BitcastElementTy->getPrimitiveSizeInBits();
144
145 SmallVector<Value *, 4> GEPArgs(GEP->idx_begin(), GEP->idx_end());
146
147 // If the source type is smaller than the destination type...
148 if (SrcTySize < DstTySize) {
149 // ... we need to divide the last index of the GEP by the size difference.
150 auto LastIndex = GEPArgs.back();
151 GEPArgs.back() = BinaryOperator::Create(
152 Instruction::SDiv, LastIndex,
153 ConstantInt::get(LastIndex->getType(), DstTySize / SrcTySize), "",
154 Bitcast);
155 } else if (SrcTySize > DstTySize) {
156 // ... we need to multiply the last index of the GEP by the size
157 // difference.
158 auto LastIndex = GEPArgs.back();
159 GEPArgs.back() = BinaryOperator::Create(
160 Instruction::Mul, LastIndex,
161 ConstantInt::get(LastIndex->getType(), SrcTySize / DstTySize), "",
162 Bitcast);
163 } else {
164 // ... the arguments are the same size, nothing to do!
165 }
166
167 // Create a new bitcast from the GEP argument to the bitcast type.
168 auto NewBitcast = CastInst::CreatePointerCast(GEP->getPointerOperand(),
169 BitcastTy, "", Bitcast);
170
171 // Create a new GEP from the (maybe modified) GEPArgs.
172 auto NewGEP = GetElementPtrInst::Create(BitcastElementTy, NewBitcast,
173 GEPArgs, "", Bitcast);
174
175 // And replace the original bitcast with our replacement GEP.
176 Bitcast->replaceAllUsesWith(NewGEP);
177
178 // Remove the bitcast as it has no users now.
179 Bitcast->eraseFromParent();
180
181 // Check if the old GEP had no other users...
182 if (0 == GEP->getNumUses()) {
183 // ... and remove it if we were its only user.
184 GEP->eraseFromParent();
185 }
186 }
187
188 return Changed;
189}
190
191bool SimplifyPointerBitcastPass::runOnBitcastFromBitcast(Module &M) const {
192 SmallVector<BitCastInst *, 16> WorkList;
193 for (Function &F : M) {
194 for (BasicBlock &BB : F) {
195 for (Instruction &I : BB) {
196 // If we have a bitcast instruction...
197 if (auto Bitcast = dyn_cast<BitCastInst>(&I)) {
198 // ... whose source is a bitcast instruction...
199 if (isa<BitCastInst>(Bitcast->getOperand(0))) {
200 // ... record the bitcast as something we need to process.
201 WorkList.push_back(Bitcast);
202 }
203 }
204 }
205 }
206 }
207
208 const bool Changed = !WorkList.empty();
209
210 for (auto Bitcast : WorkList) {
211 auto OtherBitcast = cast<BitCastInst>(Bitcast->getOperand(0));
212
David Neto973e6a82017-05-30 13:48:18 -0400213 if (OtherBitcast->getType() == Bitcast->getType()) {
214 Bitcast->replaceAllUsesWith(OtherBitcast);
215 } else {
216 // Create a new bitcast from the other bitcasts argument to our type.
217 auto NewBitcast = CastInst::CreatePointerCast(
218 OtherBitcast->getOperand(0), Bitcast->getType(), "", Bitcast);
David Neto22f144c2017-06-12 14:26:21 -0400219
David Neto973e6a82017-05-30 13:48:18 -0400220 // And replace the original bitcast with our replacement bitcast.
221 Bitcast->replaceAllUsesWith(NewBitcast);
222 }
David Neto22f144c2017-06-12 14:26:21 -0400223
224 // Remove the bitcast as it has no users now.
225 Bitcast->eraseFromParent();
226
227 // Check if the other bitcast had no other users...
228 if (0 == OtherBitcast->getNumUses()) {
229 // ... and remove it if we were its only user.
230 OtherBitcast->eraseFromParent();
231 }
232 }
233
234 return Changed;
235}
236
237bool SimplifyPointerBitcastPass::runOnGEPFromGEP(Module &M) const {
238 SmallVector<GetElementPtrInst *, 16> WorkList;
239 for (Function &F : M) {
240 for (BasicBlock &BB : F) {
241 for (Instruction &I : BB) {
242 // If we have a GEP instruction...
243 if (auto GEP = dyn_cast<GetElementPtrInst>(&I)) {
244 // ... whose operand is also a GEP instruction...
245 if (isa<GetElementPtrInst>(GEP->getPointerOperand())) {
246 // ... record the GEP as something we need to process.
247 WorkList.push_back(GEP);
248 }
249 }
250 }
251 }
252 }
253
254 const bool Changed = !WorkList.empty();
255
256 for (GetElementPtrInst *GEP : WorkList) {
257 IRBuilder<> Builder(GEP);
258
259 auto OtherGEP = cast<GetElementPtrInst>(GEP->getPointerOperand());
260
261 SmallVector<Value *, 8> Idxs;
262
263 Value *SrcLastIdxOp = OtherGEP->getOperand(OtherGEP->getNumOperands() - 1);
David Neto862b7d82018-06-14 18:48:37 -0400264
David Neto22f144c2017-06-12 14:26:21 -0400265 Value *GEPIdxOp = GEP->getOperand(1);
David Neto862b7d82018-06-14 18:48:37 -0400266 Value *MergedIdx = GEPIdxOp;
267
268 // Add the indices together, if the last one from before is not zero.
269 bool last_idx_is_zero = false;
270 if (auto *constant = dyn_cast<ConstantInt>(SrcLastIdxOp)) {
271 last_idx_is_zero = constant->isZero();
272 }
273 if (!last_idx_is_zero) {
274 MergedIdx = Builder.CreateAdd(SrcLastIdxOp, GEPIdxOp);
275 }
David Neto22f144c2017-06-12 14:26:21 -0400276
277 Idxs.append(OtherGEP->op_begin() + 1, OtherGEP->op_end() - 1);
278 Idxs.push_back(MergedIdx);
279 Idxs.append(GEP->op_begin() + 2, GEP->op_end());
280
281 Value *NewGEP = nullptr;
David Neto862b7d82018-06-14 18:48:37 -0400282 // Create the new GEP. If we used the Builder it will do some folding
283 // that we don't want. In particular, if the first GEP is to an LLVM
284 // constant then the combined GEP will become a ConstantExpr and it
285 // will hide the pointer from subsequent passes. So bypass the Builder
286 // and create the GEP instruction directly.
David Neto22f144c2017-06-12 14:26:21 -0400287 if (GEP->isInBounds() && OtherGEP->isInBounds()) {
David Neto862b7d82018-06-14 18:48:37 -0400288 NewGEP = GetElementPtrInst::CreateInBounds(
289 nullptr, OtherGEP->getPointerOperand(), Idxs, "", GEP);
David Neto22f144c2017-06-12 14:26:21 -0400290 } else {
David Neto862b7d82018-06-14 18:48:37 -0400291 NewGEP = GetElementPtrInst::Create(nullptr, OtherGEP->getPointerOperand(),
292 Idxs, "", GEP);
David Neto22f144c2017-06-12 14:26:21 -0400293 }
294
295 // And replace the original GEP with our replacement GEP.
296 GEP->replaceAllUsesWith(NewGEP);
297
298 // Remove the GEP as it has no users now.
299 GEP->eraseFromParent();
300
301 // Check if the other GEP had no other users...
302 if (0 == OtherGEP->getNumUses()) {
303 // ... and remove it if we were its only user.
304 OtherGEP->eraseFromParent();
305 }
306 }
307
308 return Changed;
309}