llvm.org GIT mirror llvm / 9d5771a
Merging r294786: ------------------------------------------------------------------------ r294786 | yaxunl | 2017-02-10 16:46:07 -0500 (Fri, 10 Feb 2017) | 24 lines Fix invalid addrspacecast due to combining alloca with global var For function-scope variables with large initialisation list, FE usually generates a global variable to hold the initializer, then generates memcpy intrinsic to initialize the alloca. InstCombiner::visitAllocaInst identifies such allocas which are accessed only by reading and replaces them with the global variable. This is done by casting the global variable to the type of the alloca and replacing all references. However, when the global variable is in a different address space which is disjoint with addr space 0 (e.g. for IR generated from OpenCL, global variable cannot be in private addr space i.e. addr space 0), casting the global variable to addr space 0 results in invalid IR for certain targets (e.g. amdgpu). To fix this issue, when the global variable is not in addr space 0, instead of casting it to addr space 0, this patch chases down the uses of alloca until reaching the load instructions, then replaces load from alloca with load from the global variable. If during the chasing bitcast and GEP are encountered, new bitcast and GEP based on the global variable are generated and used in the load instructions. Differential Revision: https://reviews.llvm.org/D27283 ------------------------------------------------------------------------ git-svn-id: https://llvm.org/svn/llvm-project/llvm/branches/release_40@301452 91177308-0d34-0410-b5e6-96231b3b80d8 Tom Stellard 2 years ago
3 changed file(s) with 185 addition(s) and 7 deletion(s). Raw diff Collapse all Expand all
312312 bool replacedSelectWithOperand(SelectInst *SI, const ICmpInst *Icmp,
313313 const unsigned SIOpd);
314314
315 /// Try to replace instruction \p I with value \p V which are pointers
316 /// in different address space.
317 /// \return true if successful.
318 bool replacePointer(Instruction &I, Value *V);
319
315320 private:
316321 bool ShouldChangeType(unsigned FromBitWidth, unsigned ToBitWidth) const;
317322 bool ShouldChangeType(Type *From, Type *To) const;
1111 //===----------------------------------------------------------------------===//
1212
1313 #include "InstCombineInternal.h"
14 #include "llvm/ADT/MapVector.h"
1415 #include "llvm/ADT/SmallString.h"
1516 #include "llvm/ADT/Statistic.h"
1617 #include "llvm/Analysis/Loads.h"
1718 #include "llvm/IR/ConstantRange.h"
1819 #include "llvm/IR/DataLayout.h"
20 #include "llvm/IR/IntrinsicInst.h"
1921 #include "llvm/IR/LLVMContext.h"
20 #include "llvm/IR/IntrinsicInst.h"
2122 #include "llvm/IR/MDBuilder.h"
2223 #include "llvm/Transforms/Utils/BasicBlockUtils.h"
2324 #include "llvm/Transforms/Utils/Local.h"
220221 }
221222
222223 return nullptr;
224 }
225
226 // If I and V are pointers in different address space, it is not allowed to
227 // use replaceAllUsesWith since I and V have different types. A
228 // non-target-specific transformation should not use addrspacecast on V since
229 // the two address space may be disjoint depending on target.
230 //
231 // This class chases down uses of the old pointer until reaching the load
232 // instructions, then replaces the old pointer in the load instructions with
233 // the new pointer. If during the chasing it sees bitcast or GEP, it will
234 // create new bitcast or GEP with the new pointer and use them in the load
235 // instruction.
236 class PointerReplacer {
237 public:
238 PointerReplacer(InstCombiner &IC) : IC(IC) {}
239 void replacePointer(Instruction &I, Value *V);
240
241 private:
242 void findLoadAndReplace(Instruction &I);
243 void replace(Instruction *I);
244 Value *getReplacement(Value *I);
245
246 SmallVector Path;
247 MapVector WorkMap;
248 InstCombiner ⁣
249 };
250
251 void PointerReplacer::findLoadAndReplace(Instruction &I) {
252 for (auto U : I.users()) {
253 auto *Inst = dyn_cast(&*U);
254 if (!Inst)
255 return;
256 DEBUG(dbgs() << "Found pointer user: " << *U << '\n');
257 if (isa(Inst)) {
258 for (auto P : Path)
259 replace(P);
260 replace(Inst);
261 } else if (isa(Inst) || isa(Inst)) {
262 Path.push_back(Inst);
263 findLoadAndReplace(*Inst);
264 Path.pop_back();
265 } else {
266 return;
267 }
268 }
269 }
270
271 Value *PointerReplacer::getReplacement(Value *V) {
272 auto Loc = WorkMap.find(V);
273 if (Loc != WorkMap.end())
274 return Loc->second;
275 return nullptr;
276 }
277
278 void PointerReplacer::replace(Instruction *I) {
279 if (getReplacement(I))
280 return;
281
282 if (auto *LT = dyn_cast(I)) {
283 auto *V = getReplacement(LT->getPointerOperand());
284 assert(V && "Operand not replaced");
285 auto *NewI = new LoadInst(V);
286 NewI->takeName(LT);
287 IC.InsertNewInstWith(NewI, *LT);
288 IC.replaceInstUsesWith(*LT, NewI);
289 WorkMap[LT] = NewI;
290 } else if (auto *GEP = dyn_cast(I)) {
291 auto *V = getReplacement(GEP->getPointerOperand());
292 assert(V && "Operand not replaced");
293 SmallVector Indices;
294 Indices.append(GEP->idx_begin(), GEP->idx_end());
295 auto *NewI = GetElementPtrInst::Create(
296 V->getType()->getPointerElementType(), V, Indices);
297 IC.InsertNewInstWith(NewI, *GEP);
298 NewI->takeName(GEP);
299 WorkMap[GEP] = NewI;
300 } else if (auto *BC = dyn_cast(I)) {
301 auto *V = getReplacement(BC->getOperand(0));
302 assert(V && "Operand not replaced");
303 auto *NewT = PointerType::get(BC->getType()->getPointerElementType(),
304 V->getType()->getPointerAddressSpace());
305 auto *NewI = new BitCastInst(V, NewT);
306 IC.InsertNewInstWith(NewI, *BC);
307 NewI->takeName(BC);
308 WorkMap[GEP] = NewI;
309 } else {
310 llvm_unreachable("should never reach here");
311 }
312 }
313
314 void PointerReplacer::replacePointer(Instruction &I, Value *V) {
315 auto *PT = cast(I.getType());
316 auto *NT = cast(V->getType());
317 assert(PT != NT && PT->getElementType() == NT->getElementType() &&
318 "Invalid usage");
319 WorkMap[&I] = V;
320 findLoadAndReplace(I);
223321 }
224322
225323 Instruction *InstCombiner::visitAllocaInst(AllocaInst &AI) {
292390 for (unsigned i = 0, e = ToDelete.size(); i != e; ++i)
293391 eraseInstFromFunction(*ToDelete[i]);
294392 Constant *TheSrc = cast(Copy->getSource());
295 Constant *Cast
296 = ConstantExpr::getPointerBitCastOrAddrSpaceCast(TheSrc, AI.getType());
297 Instruction *NewI = replaceInstUsesWith(AI, Cast);
298 eraseInstFromFunction(*Copy);
299 ++NumGlobalCopies;
300 return NewI;
393 auto *SrcTy = TheSrc->getType();
394 auto *DestTy = PointerType::get(AI.getType()->getPointerElementType(),
395 SrcTy->getPointerAddressSpace());
396 Constant *Cast =
397 ConstantExpr::getPointerBitCastOrAddrSpaceCast(TheSrc, DestTy);
398 if (AI.getType()->getPointerAddressSpace() ==
399 SrcTy->getPointerAddressSpace()) {
400 Instruction *NewI = replaceInstUsesWith(AI, Cast);
401 eraseInstFromFunction(*Copy);
402 ++NumGlobalCopies;
403 return NewI;
404 } else {
405 PointerReplacer PtrReplacer(*this);
406 PtrReplacer.replacePointer(AI, Cast);
407 ++NumGlobalCopies;
408 }
301409 }
302410 }
303411 }
0 ; RUN: opt < %s -instcombine -S | FileCheck %s
1
2 @test.data = private unnamed_addr addrspace(2) constant [8 x i32] [i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7], align 4
3
4 ; CHECK-LABEL: test_load
5 ; CHECK: %[[GEP:.*]] = getelementptr [8 x i32], [8 x i32] addrspace(2)* @test.data, i64 0, i64 %x
6 ; CHECK: %{{.*}} = load i32, i32 addrspace(2)* %[[GEP]]
7 ; CHECK-NOT: alloca
8 ; CHECK-NOT: call void @llvm.memcpy.p0i8.p2i8.i64
9 ; CHECK-NOT: addrspacecast
10 ; CHECK-NOT: load i32, i32*
11 define void @test_load(i32 addrspace(1)* %out, i64 %x) {
12 entry:
13 %data = alloca [8 x i32], align 4
14 %0 = bitcast [8 x i32]* %data to i8*
15 call void @llvm.memcpy.p0i8.p2i8.i64(i8* %0, i8 addrspace(2)* bitcast ([8 x i32] addrspace(2)* @test.data to i8 addrspace(2)*), i64 32, i32 4, i1 false)
16 %arrayidx = getelementptr inbounds [8 x i32], [8 x i32]* %data, i64 0, i64 %x
17 %1 = load i32, i32* %arrayidx, align 4
18 %arrayidx1 = getelementptr inbounds i32, i32 addrspace(1)* %out, i64 %x
19 store i32 %1, i32 addrspace(1)* %arrayidx1, align 4
20 ret void
21 }
22
23 ; CHECK-LABEL: test_call
24 ; CHECK: alloca
25 ; CHECK: call void @llvm.memcpy.p0i8.p2i8.i64
26 ; CHECK-NOT: addrspacecast
27 ; CHECK: call i32 @foo(i32* %{{.*}})
28 define void @test_call(i32 addrspace(1)* %out, i64 %x) {
29 entry:
30 %data = alloca [8 x i32], align 4
31 %0 = bitcast [8 x i32]* %data to i8*
32 call void @llvm.memcpy.p0i8.p2i8.i64(i8* %0, i8 addrspace(2)* bitcast ([8 x i32] addrspace(2)* @test.data to i8 addrspace(2)*), i64 32, i32 4, i1 false)
33 %arrayidx = getelementptr inbounds [8 x i32], [8 x i32]* %data, i64 0, i64 %x
34 %1 = call i32 @foo(i32* %arrayidx)
35 %arrayidx1 = getelementptr inbounds i32, i32 addrspace(1)* %out, i64 %x
36 store i32 %1, i32 addrspace(1)* %arrayidx1, align 4
37 ret void
38 }
39
40 ; CHECK-LABEL: test_load_and_call
41 ; CHECK: alloca
42 ; CHECK: call void @llvm.memcpy.p0i8.p2i8.i64
43 ; CHECK: load i32, i32* %{{.*}}
44 ; CHECK: call i32 @foo(i32* %{{.*}})
45 ; CHECK-NOT: addrspacecast
46 ; CHECK-NOT: load i32, i32 addrspace(2)*
47 define void @test_load_and_call(i32 addrspace(1)* %out, i64 %x, i64 %y) {
48 entry:
49 %data = alloca [8 x i32], align 4
50 %0 = bitcast [8 x i32]* %data to i8*
51 call void @llvm.memcpy.p0i8.p2i8.i64(i8* %0, i8 addrspace(2)* bitcast ([8 x i32] addrspace(2)* @test.data to i8 addrspace(2)*), i64 32, i32 4, i1 false)
52 %arrayidx = getelementptr inbounds [8 x i32], [8 x i32]* %data, i64 0, i64 %x
53 %1 = load i32, i32* %arrayidx, align 4
54 %arrayidx1 = getelementptr inbounds i32, i32 addrspace(1)* %out, i64 %x
55 store i32 %1, i32 addrspace(1)* %arrayidx1, align 4
56 %2 = call i32 @foo(i32* %arrayidx)
57 %arrayidx2 = getelementptr inbounds i32, i32 addrspace(1)* %out, i64 %y
58 store i32 %2, i32 addrspace(1)* %arrayidx2, align 4
59 ret void
60 }
61
62
63 declare void @llvm.memcpy.p0i8.p2i8.i64(i8* nocapture writeonly, i8 addrspace(2)* nocapture readonly, i64, i32, i1)
64 declare i32 @foo(i32* %x)