]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/lib/Target/NVPTX/NVPTXLowerStructArgs.cpp
Merge llvm 3.6.0rc1 from ^/vendor/llvm/dist, merge clang 3.6.0rc1 from
[FreeBSD/FreeBSD.git] / contrib / llvm / lib / Target / NVPTX / NVPTXLowerStructArgs.cpp
1 //===-- NVPTXLowerStructArgs.cpp - Copy struct args to 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 // Copy struct args to local memory. This is needed for kernel functions only.
11 // This is a preparation for handling cases like
12 //
13 // kernel void foo(struct A arg, ...)
14 // {
15 //     struct A *p = &arg;
16 //     ...
17 //     ... = p->filed1 ...  (this is no generic address for .param)
18 //     p->filed2 = ...      (this is no write access to .param)
19 // }
20 //
21 //===----------------------------------------------------------------------===//
22
23 #include "NVPTX.h"
24 #include "NVPTXUtilities.h"
25 #include "llvm/IR/Function.h"
26 #include "llvm/IR/Instructions.h"
27 #include "llvm/IR/IntrinsicInst.h"
28 #include "llvm/IR/Module.h"
29 #include "llvm/IR/Type.h"
30 #include "llvm/Pass.h"
31
32 using namespace llvm;
33
34 namespace llvm {
35 void initializeNVPTXLowerStructArgsPass(PassRegistry &);
36 }
37
38 class LLVM_LIBRARY_VISIBILITY NVPTXLowerStructArgs : public FunctionPass {
39   bool runOnFunction(Function &F) override;
40
41   void handleStructPtrArgs(Function &);
42   void handleParam(Argument *);
43
44 public:
45   static char ID; // Pass identification, replacement for typeid
46   NVPTXLowerStructArgs() : FunctionPass(ID) {}
47   const char *getPassName() const override {
48     return "Copy structure (byval *) arguments to stack";
49   }
50 };
51
52 char NVPTXLowerStructArgs::ID = 1;
53
54 INITIALIZE_PASS(NVPTXLowerStructArgs, "nvptx-lower-struct-args",
55                 "Lower structure arguments (NVPTX)", false, false)
56
57 void NVPTXLowerStructArgs::handleParam(Argument *Arg) {
58   Function *Func = Arg->getParent();
59   Instruction *FirstInst = &(Func->getEntryBlock().front());
60   PointerType *PType = dyn_cast<PointerType>(Arg->getType());
61
62   assert(PType && "Expecting pointer type in handleParam");
63
64   Type *StructType = PType->getElementType();
65   AllocaInst *AllocA = new AllocaInst(StructType, Arg->getName(), FirstInst);
66
67   /* Set the alignment to alignment of the byval parameter. This is because,
68    * later load/stores assume that alignment, and we are going to replace
69    * the use of the byval parameter with this alloca instruction.
70    */
71   AllocA->setAlignment(Func->getParamAlignment(Arg->getArgNo() + 1));
72
73   Arg->replaceAllUsesWith(AllocA);
74
75   // Get the cvt.gen.to.param intrinsic
76   Type *CvtTypes[] = {
77       Type::getInt8PtrTy(Func->getParent()->getContext(), ADDRESS_SPACE_PARAM),
78       Type::getInt8PtrTy(Func->getParent()->getContext(),
79                          ADDRESS_SPACE_GENERIC)};
80   Function *CvtFunc = Intrinsic::getDeclaration(
81       Func->getParent(), Intrinsic::nvvm_ptr_gen_to_param, CvtTypes);
82
83   Value *BitcastArgs[] = {
84       new BitCastInst(Arg, Type::getInt8PtrTy(Func->getParent()->getContext(),
85                                               ADDRESS_SPACE_GENERIC),
86                       Arg->getName(), FirstInst)};
87   CallInst *CallCVT =
88       CallInst::Create(CvtFunc, BitcastArgs, "cvt_to_param", FirstInst);
89
90   BitCastInst *BitCast = new BitCastInst(
91       CallCVT, PointerType::get(StructType, ADDRESS_SPACE_PARAM),
92       Arg->getName(), FirstInst);
93   LoadInst *LI = new LoadInst(BitCast, Arg->getName(), FirstInst);
94   new StoreInst(LI, AllocA, FirstInst);
95 }
96
97 // =============================================================================
98 // If the function had a struct ptr arg, say foo(%struct.x *byval %d), then
99 // add the following instructions to the first basic block :
100 //
101 // %temp = alloca %struct.x, align 8
102 // %tt1 = bitcast %struct.x * %d to i8 *
103 // %tt2 = llvm.nvvm.cvt.gen.to.param %tt2
104 // %tempd = bitcast i8 addrspace(101) * to %struct.x addrspace(101) *
105 // %tv = load %struct.x addrspace(101) * %tempd
106 // store %struct.x %tv, %struct.x * %temp, align 8
107 //
108 // The above code allocates some space in the stack and copies the incoming
109 // struct from param space to local space.
110 // Then replace all occurences of %d by %temp.
111 // =============================================================================
112 void NVPTXLowerStructArgs::handleStructPtrArgs(Function &F) {
113   for (Argument &Arg : F.args()) {
114     if (Arg.getType()->isPointerTy() && Arg.hasByValAttr()) {
115       handleParam(&Arg);
116     }
117   }
118 }
119
120 // =============================================================================
121 // Main function for this pass.
122 // =============================================================================
123 bool NVPTXLowerStructArgs::runOnFunction(Function &F) {
124   // Skip non-kernels. See the comments at the top of this file.
125   if (!isKernelFunction(F))
126     return false;
127
128   handleStructPtrArgs(F);
129   return true;
130 }
131
132 FunctionPass *llvm::createNVPTXLowerStructArgsPass() {
133   return new NVPTXLowerStructArgs();
134 }