/Users/buildslave/jenkins/sharedspace/clang-stage2-coverage-R@2/llvm/lib/Target/NVPTX/NVPTXLowerAlloca.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===-- NVPTXLowerAlloca.cpp - Make alloca to use local memory =====--===// |
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 | | // For all alloca instructions, and add a pair of cast to local address for |
11 | | // each of them. For example, |
12 | | // |
13 | | // %A = alloca i32 |
14 | | // store i32 0, i32* %A ; emits st.u32 |
15 | | // |
16 | | // will be transformed to |
17 | | // |
18 | | // %A = alloca i32 |
19 | | // %Local = addrspacecast i32* %A to i32 addrspace(5)* |
20 | | // %Generic = addrspacecast i32 addrspace(5)* %A to i32* |
21 | | // store i32 0, i32 addrspace(5)* %Generic ; emits st.local.u32 |
22 | | // |
23 | | // And we will rely on NVPTXInferAddressSpaces to combine the last two |
24 | | // instructions. |
25 | | // |
26 | | //===----------------------------------------------------------------------===// |
27 | | |
28 | | #include "NVPTX.h" |
29 | | #include "NVPTXUtilities.h" |
30 | | #include "llvm/IR/Function.h" |
31 | | #include "llvm/IR/Instructions.h" |
32 | | #include "llvm/IR/IntrinsicInst.h" |
33 | | #include "llvm/IR/Module.h" |
34 | | #include "llvm/IR/Type.h" |
35 | | #include "llvm/Pass.h" |
36 | | |
37 | | using namespace llvm; |
38 | | |
39 | | namespace llvm { |
40 | | void initializeNVPTXLowerAllocaPass(PassRegistry &); |
41 | | } |
42 | | |
43 | | namespace { |
44 | | class NVPTXLowerAlloca : public BasicBlockPass { |
45 | | bool runOnBasicBlock(BasicBlock &BB) override; |
46 | | |
47 | | public: |
48 | | static char ID; // Pass identification, replacement for typeid |
49 | 207 | NVPTXLowerAlloca() : BasicBlockPass(ID) {} |
50 | 0 | StringRef getPassName() const override { |
51 | 0 | return "convert address space of alloca'ed memory to local"; |
52 | 0 | } |
53 | | }; |
54 | | } // namespace |
55 | | |
56 | | char NVPTXLowerAlloca::ID = 1; |
57 | | |
58 | | INITIALIZE_PASS(NVPTXLowerAlloca, "nvptx-lower-alloca", |
59 | | "Lower Alloca", false, false) |
60 | | |
61 | | // ============================================================================= |
62 | | // Main function for this pass. |
63 | | // ============================================================================= |
64 | 1.05k | bool NVPTXLowerAlloca::runOnBasicBlock(BasicBlock &BB) { |
65 | 1.05k | if (skipBasicBlock(BB)) |
66 | 0 | return false; |
67 | 1.05k | |
68 | 1.05k | bool Changed = false; |
69 | 3.66k | for (auto &I : BB) { |
70 | 3.66k | if (auto allocaInst3.66k = dyn_cast<AllocaInst>(&I)) { |
71 | 14 | Changed = true; |
72 | 14 | auto PTy = dyn_cast<PointerType>(allocaInst->getType()); |
73 | 14 | auto ETy = PTy->getElementType(); |
74 | 14 | auto LocalAddrTy = PointerType::get(ETy, ADDRESS_SPACE_LOCAL); |
75 | 14 | auto NewASCToLocal = new AddrSpaceCastInst(allocaInst, LocalAddrTy, ""); |
76 | 14 | auto GenericAddrTy = PointerType::get(ETy, ADDRESS_SPACE_GENERIC); |
77 | 14 | auto NewASCToGeneric = new AddrSpaceCastInst(NewASCToLocal, |
78 | 14 | GenericAddrTy, ""); |
79 | 14 | NewASCToLocal->insertAfter(allocaInst); |
80 | 14 | NewASCToGeneric->insertAfter(NewASCToLocal); |
81 | 14 | for (Value::use_iterator UI = allocaInst->use_begin(), |
82 | 14 | UE = allocaInst->use_end(); |
83 | 55 | UI != UE55 ; ) { |
84 | 41 | // Check Load, Store, GEP, and BitCast Uses on alloca and make them |
85 | 41 | // use the converted generic address, in order to expose non-generic |
86 | 41 | // addrspacecast to NVPTXInferAddressSpaces. For other types |
87 | 41 | // of instructions this is unnecessary and may introduce redundant |
88 | 41 | // address cast. |
89 | 41 | const auto &AllocaUse = *UI++; |
90 | 41 | auto LI = dyn_cast<LoadInst>(AllocaUse.getUser()); |
91 | 41 | if (LI && 41 LI->getPointerOperand() == allocaInst0 && !LI->isVolatile()0 ) { |
92 | 0 | LI->setOperand(LI->getPointerOperandIndex(), NewASCToGeneric); |
93 | 0 | continue; |
94 | 0 | } |
95 | 41 | auto SI = dyn_cast<StoreInst>(AllocaUse.getUser()); |
96 | 41 | if (SI && 41 SI->getPointerOperand() == allocaInst11 && !SI->isVolatile()11 ) { |
97 | 9 | SI->setOperand(SI->getPointerOperandIndex(), NewASCToGeneric); |
98 | 9 | continue; |
99 | 9 | } |
100 | 32 | auto GI = dyn_cast<GetElementPtrInst>(AllocaUse.getUser()); |
101 | 32 | if (GI && 32 GI->getPointerOperand() == allocaInst4 ) { |
102 | 4 | GI->setOperand(GI->getPointerOperandIndex(), NewASCToGeneric); |
103 | 4 | continue; |
104 | 4 | } |
105 | 28 | auto BI = dyn_cast<BitCastInst>(AllocaUse.getUser()); |
106 | 28 | if (BI && 28 BI->getOperand(0) == allocaInst3 ) { |
107 | 3 | BI->setOperand(0, NewASCToGeneric); |
108 | 3 | continue; |
109 | 3 | } |
110 | 41 | } |
111 | 14 | } |
112 | 3.66k | } |
113 | 1.05k | return Changed; |
114 | 1.05k | } |
115 | | |
116 | 206 | BasicBlockPass *llvm::createNVPTXLowerAllocaPass() { |
117 | 206 | return new NVPTXLowerAlloca(); |
118 | 206 | } |