summaryrefslogtreecommitdiff
path: root/src/core/cpu/program.cpp
blob: 653fb1e1a08344df0746a6d534a7dcbf86755ced (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
#include "program.h"
#include "device.h"
#include "kernel.h"

#include "../program.h"

#include <llvm/PassManager.h>
#include <llvm/Analysis/Passes.h>
#include <llvm/Analysis/Verifier.h>
#include <llvm/Transforms/Scalar.h>
#include <llvm/Transforms/IPO.h>
#include <llvm/ExecutionEngine/ExecutionEngine.h>
#include <llvm/ExecutionEngine/JIT.h>
#include <llvm/ExecutionEngine/Interpreter.h>

#include <string>
#include <iostream>

using namespace Coal;

CPUProgram::CPUProgram(CPUDevice *device, Program *program)
: DeviceProgram(), p_device(device), p_program(program), p_jit(0)
{

}

CPUProgram::~CPUProgram()
{
    if (p_jit)
    {
        // Dont delete the module
        p_jit->removeModule(p_module);

        delete p_jit;
    }
}

bool CPUProgram::linkStdLib() const
{
    return true;
}

void CPUProgram::createOptimizationPasses(llvm::PassManager *manager, bool optimize)
{
    if (optimize)
    {
        /*
         * Inspired by code from "The LLVM Compiler Infrastructure"
         */
        manager->add(llvm::createDeadArgEliminationPass());
        manager->add(llvm::createInstructionCombiningPass());
        manager->add(llvm::createFunctionInliningPass());
        manager->add(llvm::createPruneEHPass());   // Remove dead EH info.
        manager->add(llvm::createGlobalOptimizerPass());
        manager->add(llvm::createGlobalDCEPass()); // Remove dead functions.
        manager->add(llvm::createArgumentPromotionPass());
        manager->add(llvm::createInstructionCombiningPass());
        manager->add(llvm::createJumpThreadingPass());
        manager->add(llvm::createScalarReplAggregatesPass());
        manager->add(llvm::createFunctionAttrsPass()); // Add nocapture.
        manager->add(llvm::createGlobalsModRefPass()); // IP alias analysis.
        manager->add(llvm::createLICMPass());      // Hoist loop invariants.
        manager->add(llvm::createGVNPass());       // Remove redundancies.
        manager->add(llvm::createMemCpyOptPass()); // Remove dead memcpys.
        manager->add(llvm::createDeadStoreEliminationPass());
        manager->add(llvm::createInstructionCombiningPass());
        manager->add(llvm::createJumpThreadingPass());
        manager->add(llvm::createCFGSimplificationPass());
    }
}

bool CPUProgram::build(llvm::Module *module)
{
    // Nothing to build
    p_module = module;

    return true;
}

bool CPUProgram::initJIT()
{
    if (p_jit)
        return true;

    if (!p_module)
        return false;

    // Create the JIT
    std::string err;
    llvm::EngineBuilder builder(p_module);

    builder.setErrorStr(&err);
    builder.setAllocateGVsWithCode(false);

    p_jit = builder.create();

    if (!p_jit)
    {
        std::cout << "Unable to create a JIT: " << err << std::endl;
        return false;
    }

    p_jit->DisableSymbolSearching(true);    // Avoid an enormous security hole (a kernel calling system())
    p_jit->InstallLazyFunctionCreator(&getBuiltin);

    return true;
}

llvm::ExecutionEngine *CPUProgram::jit() const
{
    return p_jit;
}