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