23 #include <llvm/ExecutionEngine/MCJIT.h> 24 #include <llvm/IR/BasicBlock.h> 25 #include <llvm/IR/Function.h> 26 #include <llvm/IR/IRBuilder.h> 27 #include <llvm/IR/Module.h> 28 #include <llvm/IR/Type.h> 29 #include <llvm/IR/Verifier.h> 30 #include <llvm/Support/TargetSelect.h> 31 #include <llvm/Support/raw_os_ostream.h> 36 extern "C" void print_iterators(
const int64_t i,
const int64_t j,
const int64_t k) {
37 printf(
"%ld, %ld, %ld\n", i, j, k);
45 std::stringstream err_ss;
46 llvm::raw_os_ostream err_os(err_ss);
47 if (llvm::verifyFunction(*func, &err_os)) {
48 func->print(llvm::outs());
55 const std::vector<llvm::Value*>
args,
57 llvm::IRBuilder<>& builder) {
58 std::vector<llvm::Type*> arg_types;
59 for (
const auto arg : args) {
60 arg_types.push_back(arg->getType());
62 auto func_ty = llvm::FunctionType::get(ret_type, arg_types,
false);
63 auto func_p = module->getOrInsertFunction(fname, func_ty);
65 llvm::Value*
result = builder.CreateCall(func_p, args);
67 CHECK_EQ(result->getType(), ret_type);
73 const std::vector<JoinLoop>& join_loops) {
74 std::vector<llvm::Type*> argument_types;
76 llvm::FunctionType::get(llvm::Type::getVoidTy(context), argument_types,
false);
77 const auto func = llvm::Function::Create(
78 ft, llvm::Function::ExternalLinkage,
"loop_test_func", module);
79 const auto entry_bb = llvm::BasicBlock::Create(context,
"entry", func);
80 const auto exit_bb = llvm::BasicBlock::Create(context,
"exit", func);
81 llvm::IRBuilder<> builder(context);
82 builder.SetInsertPoint(exit_bb);
83 builder.CreateRetVoid();
86 [&builder, module](
const std::vector<llvm::Value*>& iterators) {
87 const auto loop_body_bb = llvm::BasicBlock::Create(
88 builder.getContext(),
"loop_body", builder.GetInsertBlock()->getParent());
89 builder.SetInsertPoint(loop_body_bb);
90 const std::vector<llvm::Value*>
args(iterators.begin() + 1, iterators.end());
92 llvm::Type::getVoidTy(builder.getContext()),
101 builder.SetInsertPoint(entry_bb);
102 builder.CreateBr(loop_body_bb);
108 return std::make_unique<llvm::Module>(
"Nested loops JIT",
g_global_context);
112 std::unique_ptr<llvm::Module>& module,
113 llvm::Function* func) {
114 llvm::ExecutionEngine* execution_engine{
nullptr};
116 auto init_err = llvm::InitializeNativeTarget();
119 llvm::InitializeAllTargetMCs();
120 llvm::InitializeNativeTargetAsmPrinter();
121 llvm::InitializeNativeTargetAsmParser();
124 llvm::EngineBuilder eb(std::move(module));
125 eb.setErrorStr(&err_str);
126 eb.setEngineKind(llvm::EngineKind::JIT);
127 llvm::TargetOptions to;
128 to.EnableFastISel =
true;
129 eb.setTargetOptions(to);
130 execution_engine = eb.create();
131 CHECK(execution_engine);
133 execution_engine->finalizeObject();
134 auto native_code = execution_engine->getPointerToFunction(func);
137 return {native_code, std::unique_ptr<llvm::ExecutionEngine>(execution_engine)};
141 const unsigned cond_mask,
143 std::vector<JoinLoop> join_loops;
145 for (
size_t i = 0; i < upper_bounds.size(); ++i) {
146 if (mask & (1 << i)) {
147 const bool cond_is_true = cond_mask & (1 << cond_idx);
148 join_loops.emplace_back(
151 [i, cond_is_true](
const std::vector<llvm::Value*>& v) {
156 ?
ll_int(int64_t(99), g_global_context)
157 :
ll_int(int64_t(-1), g_global_context);
167 join_loops.emplace_back(
170 [i,
upper_bound](
const std::vector<llvm::Value*>& v) {
190 for (
unsigned mask = 0; mask < static_cast<unsigned>(1 <<
upper_bounds.size());
193 for (
unsigned cond_mask = 0; cond_mask < static_cast<unsigned>(1 <<
mask_bitcount);
197 const auto function =
200 reinterpret_cast<int64_t (*)()
>(func_and_ee.first)();
llvm::Value * emit_external_call(const std::string &fname, llvm::Type *ret_type, const std::vector< llvm::Value *> args, llvm::Module *module, llvm::IRBuilder<> &builder)
llvm::LLVMContext g_global_context
llvm::ConstantInt * ll_int(const T v, llvm::LLVMContext &context)
void print_iterators(const int64_t i, const int64_t j, const int64_t k)
llvm::Function * create_loop_test_function(llvm::LLVMContext &context, llvm::Module *module, const std::vector< JoinLoop > &join_loops)
DEVICE auto upper_bound(ARGS &&... args)
static llvm::BasicBlock * codegen(const std::vector< JoinLoop > &join_loops, const std::function< llvm::BasicBlock *(const std::vector< llvm::Value *> &)> &body_codegen, llvm::Value *outer_iter, llvm::BasicBlock *exit_bb, CgenState *cgen_state)
llvm::Value * slot_lookup_result
llvm::Value * upper_bound
std::unique_ptr< llvm::Module > create_loop_test_module()
void verify_function_ir(const llvm::Function *func)
std::vector< JoinLoop > generate_descriptors(const unsigned mask, const unsigned cond_mask, const std::vector< int64_t > &upper_bounds)
std::pair< void *, std::unique_ptr< llvm::ExecutionEngine > > native_codegen(std::unique_ptr< llvm::Module > &module, llvm::Function *func)