• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2016, The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "RSSPIRVWriter.h"
18 
19 #include "Builtin.h"
20 #include "Context.h"
21 #include "GlobalAllocPass.h"
22 #include "GlobalAllocSPIRITPass.h"
23 #include "GlobalMergePass.h"
24 #include "InlinePreparationPass.h"
25 #include "RemoveNonkernelsPass.h"
26 #include "SPIRVModule.h"
27 #include "Wrapper.h"
28 #include "bcinfo/MetadataExtractor.h"
29 #include "pass_queue.h"
30 
31 #include "llvm/ADT/Triple.h"
32 #include "llvm/IR/LegacyPassManager.h"
33 #include "llvm/IR/Module.h"
34 #include "llvm/Support/CommandLine.h"
35 #include "llvm/Support/Debug.h"
36 #include "llvm/Support/SPIRV.h"
37 #include "llvm/Support/raw_ostream.h"
38 #include "llvm/Transforms/IPO.h"
39 #include "llvm/Transforms/Scalar.h"
40 
41 #define DEBUG_TYPE "rs2spirv-writer"
42 
43 using namespace llvm;
44 using namespace SPIRV;
45 
46 namespace rs2spirv {
47 
addPassesForRS2SPIRV(llvm::legacy::PassManager & PassMgr)48 void addPassesForRS2SPIRV(llvm::legacy::PassManager &PassMgr) {
49   PassMgr.add(createGlobalMergePass());
50 
51   PassMgr.add(createInlinePreparationPass());
52   PassMgr.add(createAlwaysInlinerPass());
53   PassMgr.add(createRemoveNonkernelsPass());
54   // Delete unreachable globals.
55   PassMgr.add(createGlobalDCEPass());
56   // Remove dead debug info.
57   PassMgr.add(createStripDeadDebugInfoPass());
58   // Remove dead func decls.
59   PassMgr.add(createStripDeadPrototypesPass());
60   // Transform global allocations and accessors (rs[GS]etElementAt)
61   PassMgr.add(createGlobalAllocPass());
62   // Removed dead MemCpys in 64-bit targets after global alloc pass
63   PassMgr.add(createDeadStoreEliminationPass());
64   PassMgr.add(createAggressiveDCEPass());
65   // Delete unreachable globals (after removing global allocations)
66   PassMgr.add(createRemoveAllGlobalAllocPass());
67   PassMgr.add(createPromoteMemoryToRegisterPass());
68   PassMgr.add(createTransOCLMD());
69   // TODO: investigate removal of OCLTypeToSPIRV pass.
70   PassMgr.add(createOCLTypeToSPIRV());
71   PassMgr.add(createSPIRVRegularizeLLVM());
72   PassMgr.add(createSPIRVLowerConstExpr());
73   PassMgr.add(createSPIRVLowerBool());
74 }
75 
WriteSPIRV(Context & Ctxt,Module * M,llvm::raw_ostream & OS,std::string & ErrMsg)76 bool WriteSPIRV(Context &Ctxt, Module *M,
77                 llvm::raw_ostream &OS, std::string &ErrMsg) {
78   llvm::legacy::PassManager PassMgr;
79   addPassesForRS2SPIRV(PassMgr);
80 
81   std::unique_ptr<SPIRVModule> BM(SPIRVModule::createSPIRVModule());
82 
83   PassMgr.add(createLLVMToSPIRV(BM.get()));
84   PassMgr.run(*M);
85   DEBUG(M->dump());
86 
87   if (BM->getError(ErrMsg) != SPIRVEC_Success) {
88     return false;
89   }
90 
91   llvm::SmallString<4096> O;
92   llvm::raw_svector_ostream SVOS(O);
93 
94   SVOS << *BM;
95 
96   llvm::StringRef str = SVOS.str();
97   std::vector<uint32_t> words(str.size() / 4);
98 
99   memcpy(words.data(), str.data(), str.size());
100 
101   android::spirit::PassQueue spiritPasses;
102   spiritPasses.append(CreateWrapperPass(*M));
103   spiritPasses.append(CreateBuiltinPass());
104   spiritPasses.append(CreateGAPass());
105 
106   int error;
107   auto wordsOut = spiritPasses.run(words, &error);
108 
109   if (error != 0) {
110     OS << *BM;
111     ErrMsg = "Failed to generate wrappers for kernels";
112     return false;
113   }
114 
115   OS.write(reinterpret_cast<const char *>(wordsOut.data()),
116            wordsOut.size() * 4);
117 
118   return true;
119 }
120 
121 } // namespace rs2spirv
122