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 43using namespace llvm; 44using namespace SPIRV; 45 46namespace rs2spirv { 47 48void 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 76bool 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