source: icGREP/icgrep-devel/icgrep/toolchain/NVPTXDriver.cpp

Last change on this file was 6184, checked in by nmedfort, 10 months ago

Initial version of PipelineKernel? + revised StreamSet? model.

File size: 5.9 KB
Line 
1/*
2 *  Copyright (c) 2016 International Characters.
3 *  This software is licensed to the public under the Open Software License 3.0.
4 *  icgrep is a trademark of International Characters.
5 */
6
7#include "NVPTXDriver.h"
8#include <IR_Gen/idisa_target.h>
9#include <kernels/kernel_builder.h>
10#include <kernels/kernel.h>
11#include <llvm/Transforms/Scalar.h>
12#include <llvm/Transforms/Utils/Local.h>
13#include <toolchain/toolchain.h>
14#include <llvm/Analysis/TargetLibraryInfo.h>
15#include <llvm/CodeGen/MIRParser/MIRParser.h>
16#include <llvm/IR/LegacyPassManager.h>
17#include <llvm/IR/Module.h>
18#include <llvm/Support/FileSystem.h>
19#include <llvm/Support/TargetRegistry.h>
20#include <llvm/Support/TargetSelect.h>
21#include <llvm/Support/ToolOutputFile.h>
22#include <llvm/Target/TargetMachine.h>
23#if LLVM_VERSION_INTEGER >= LLVM_VERSION_CODE(3, 9, 0)
24#include <llvm/Transforms/Scalar/GVN.h>
25#endif
26
27using namespace llvm;
28
29using StreamSetBuffer = kernel::StreamSetBuffer;
30
31NVPTXDriver::NVPTXDriver(std::string && moduleName)
32: BaseDriver(std::move(moduleName)) {
33
34    InitializeAllTargets();
35    InitializeAllTargetMCs();
36    InitializeAllAsmPrinters();
37    InitializeAllAsmParsers();
38
39    PassRegistry * Registry = PassRegistry::getPassRegistry();
40    initializeCore(*Registry);
41    initializeCodeGen(*Registry);
42    initializeLoopStrengthReducePass(*Registry);
43    initializeLowerIntrinsicsPass(*Registry);
44#if LLVM_VERSION_INTEGER < LLVM_VERSION_CODE(3, 9, 0)
45    initializeUnreachableBlockElimPass(*Registry);
46#else
47    initializeUnreachableBlockElimLegacyPassPass(*Registry);
48#endif
49   
50    mMainModule->setDataLayout("e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v16:16:16-v32:32:32-v64:64:64-v128:128:128-n16:32:64");
51    mMainModule->setTargetTriple("nvptx64-nvidia-cuda");
52
53    iBuilder.reset(IDISA::GetIDISA_GPU_Builder(*mContext));
54    iBuilder->setModule(mMainModule);
55    iBuilder->CreateBaseFunctions();
56}
57
58Function * NVPTXDriver::addLinkFunction(Module *, llvm::StringRef, FunctionType *, void *) const {
59    report_fatal_error("NVPTX does not support linked functions");
60}
61
62
63static int llvm2ptx(Module * M, std::string PTXFilename) {
64
65    std::unique_ptr<MIRParser> MIR;
66    Triple TheTriple(M->getTargetTriple());
67
68    if (TheTriple.getTriple().empty())
69        TheTriple.setTriple(sys::getDefaultTargetTriple());
70
71    // Get the target specific parser.
72    std::string Error;
73    const auto TheTarget = TargetRegistry::lookupTarget(codegen::MArch, TheTriple, Error);
74    if (!TheTarget) {
75        report_fatal_error(Error);
76    }
77
78    const auto CPUStr = codegen::getCPUStr();
79    const auto FeaturesStr = codegen::getFeaturesStr();
80
81    std::unique_ptr<TargetMachine> Target(
82                TheTarget->createTargetMachine(TheTriple.getTriple(), CPUStr, FeaturesStr,
83                                               codegen::Options, codegen::RelocModel, codegen::CMModel, codegen::OptLevel));
84
85    assert(Target && "Could not allocate target machine!");
86
87    // Figure out where we are going to send the output.
88    std::error_code EC;
89    sys::fs::OpenFlags OpenFlags = sys::fs::F_None | sys::fs::F_Text;
90    std::unique_ptr<tool_output_file> Out = llvm::make_unique<tool_output_file>(PTXFilename, EC, OpenFlags);
91    if (EC) {
92        errs() << EC.message() << '\n';
93        return 1;
94    }
95
96    // Build up all of the passes that we want to do to the module.
97    legacy::PassManager PM;
98
99    // Add an appropriate TargetLibraryInfo pass for the module's triple.
100    TargetLibraryInfoImpl TLII(Triple(M->getTargetTriple()));
101
102    PM.add(new TargetLibraryInfoWrapperPass(TLII));
103
104    // Add the target data from the target machine, if it exists, or the module.
105    M->setDataLayout(Target->createDataLayout());
106
107    // Override function attributes based on CPUStr, FeaturesStr, and command line
108    // flags.
109    codegen::setFunctionAttributes(CPUStr, FeaturesStr, *M);
110
111    {
112        raw_pwrite_stream *OS = &Out->os();
113
114        AnalysisID StartBeforeID = nullptr;
115        AnalysisID StartAfterID = nullptr;
116        AnalysisID StopAfterID = nullptr;
117        const PassRegistry *PR = PassRegistry::getPassRegistry();
118        // Ask the target to add backend passes as necessary.
119        if (Target->addPassesToEmitFile(PM, *OS, codegen::FileType, false, StartBeforeID,
120                                        StartAfterID, StopAfterID, MIR.get())) {
121            errs() << " target does not support generation of this file type!\n";
122            return 1;
123        }
124
125        PM.run(*M);
126    }
127    // Declare success.
128    Out->keep();
129
130    return 0;
131}
132
133void * NVPTXDriver::finalizeObject(Function * mainMethod) {
134
135    legacy::PassManager PM;
136    PM.add(createPromoteMemoryToRegisterPass()); //Force the use of mem2reg to promote stack variables.
137    PM.add(createReassociatePass());             //Reassociate expressions.
138    PM.add(createGVNPass());                     //Eliminate common subexpressions.
139    PM.add(createInstructionCombiningPass());    //Simple peephole optimizations and bit-twiddling.
140    PM.add(createCFGSimplificationPass());
141
142    for (kernel::Kernel * const kb : mPipeline) {
143        iBuilder->setKernel(kb);
144        kb->generateKernel(iBuilder);
145    }
146
147    Function * mainFunc = mMainModule->getFunction("Main");
148
149    MDNode * Node = MDNode::get(mMainModule->getContext(),
150                                {llvm::ValueAsMetadata::get(mainFunc),
151                                 MDString::get(mMainModule->getContext(), "kernel"), 
152                                 ConstantAsMetadata::get(ConstantInt::get(iBuilder->getInt32Ty(), 1))});
153    NamedMDNode *NMD = mMainModule->getOrInsertNamedMetadata("nvvm.annotations");
154    NMD->addOperand(Node);
155
156    PM.run(*mMainModule); 
157
158    if (LLVM_UNLIKELY(codegen::DebugOptionIsSet(codegen::ShowIR))) {
159        mMainModule->dump();
160    }
161
162    const auto PTXFilename = mMainModule->getModuleIdentifier() + ".ptx";
163
164    llvm2ptx(mMainModule, PTXFilename);
165
166    return nullptr;
167}
168
169NVPTXDriver::~NVPTXDriver() {
170
171}
Note: See TracBrowser for help on using the repository browser.