#ifndef HALIDE_CODEGEN_LLVM_H
#define HALIDE_CODEGEN_LLVM_H
namespace llvm {
class Value;
class Module;
class Function;
#if LLVM_VERSION >= 39
class IRBuilderDefaultInserter;
#else
template<bool> class IRBuilderDefaultInserter;
#endif
class ConstantFolder;
#if LLVM_VERSION >= 39
template<typename, typename> class IRBuilder;
#else
template<bool, typename, typename> class IRBuilder;
#endif
class LLVMContext;
class Type;
class StructType;
class Instruction;
class CallInst;
class ExecutionEngine;
class AllocaInst;
class Constant;
class Triple;
class MDNode;
class NamedMDNode;
class DataLayout;
class BasicBlock;
class GlobalVariable;
}
#include <map>
#include <string>
#include <vector>
#include <memory>
#include "IRVisitor.h"
#include "Module.h"
#include "Scope.h"
#include "ModulusRemainder.h"
#include "Target.h"
namespace Halide {
namespace Internal {
class CodeGen_LLVM : public IRVisitor {
public:
static CodeGen_LLVM *new_for_target(const Target &target,
llvm::LLVMContext &context);
virtual ~CodeGen_LLVM();
virtual std::unique_ptr<llvm::Module> compile(const Module &module);
const Target &get_target() const { return target; }
void set_context(llvm::LLVMContext &context);
static void initialize_llvm();
protected:
CodeGen_LLVM(Target t);
virtual void compile_func(const LoweredFunc &func, const std::string &simple_name, const std::string &extern_name);
virtual void compile_buffer(const Buffer<> &buffer);
virtual void begin_func(LoweredFunc::LinkageType linkage, const std::string &simple_name,
const std::string &extern_name, const std::vector<LoweredArgument> &args);
virtual void end_func(const std::vector<LoweredArgument> &args);
virtual std::string mcpu() const = 0;
virtual std::string mattrs() const = 0;
virtual bool use_soft_float_abi() const = 0;
virtual bool promote_indices() const {return true;}
virtual int native_vector_bits() const = 0;
static bool llvm_initialized;
static bool llvm_X86_enabled;
static bool llvm_ARM_enabled;
static bool llvm_Hexagon_enabled;
static bool llvm_AArch64_enabled;
static bool llvm_NVPTX_enabled;
static bool llvm_Mips_enabled;
static bool llvm_PowerPC_enabled;
const Module *input_module;
std::unique_ptr<llvm::Module> module;
llvm::Function *function;
llvm::LLVMContext *context;
#if LLVM_VERSION >= 39
llvm::IRBuilder<llvm::ConstantFolder, llvm::IRBuilderDefaultInserter> *builder;
#else
llvm::IRBuilder<true, llvm::ConstantFolder, llvm::IRBuilderDefaultInserter<true>> *builder;
#endif
llvm::Value *value;
llvm::MDNode *very_likely_branch;
std::vector<LoweredArgument> current_function_args;
Halide::Target target;
virtual void init_context();
virtual void init_module();
void add_external_code(const Module &halide_module);
void optimize_module();
void sym_push(const std::string &name, llvm::Value *value);
void sym_pop(const std::string &name);
llvm::Value* sym_get(const std::string &name,
bool must_succeed = true) const;
bool sym_exists(const std::string &name) const;
llvm::Type *void_t, *i1_t, *i8_t, *i16_t, *i32_t, *i64_t, *f16_t, *f32_t, *f64_t;
llvm::StructType *buffer_t_type,
*type_t_type,
*dimension_t_type,
*metadata_t_type,
*argument_t_type,
*scalar_value_t_type,
*device_interface_t_type;
llvm::Type *i8x8, *i8x16, *i8x32;
llvm::Type *i16x4, *i16x8, *i16x16;
llvm::Type *i32x2, *i32x4, *i32x8;
llvm::Type *i64x2, *i64x4;
llvm::Type *f32x2, *f32x4, *f32x8;
llvm::Type *f64x2, *f64x4;
Expr wild_i8x8, wild_i16x4, wild_i32x2;
Expr wild_u8x8, wild_u16x4, wild_u32x2;
Expr wild_i8x16, wild_i16x8, wild_i32x4, wild_i64x2;
Expr wild_u8x16, wild_u16x8, wild_u32x4, wild_u64x2;
Expr wild_i8x32, wild_i16x16, wild_i32x8, wild_i64x4;
Expr wild_u8x32, wild_u16x16, wild_u32x8, wild_u64x4;
Expr wild_f32x2;
Expr wild_f32x4, wild_f64x2;
Expr wild_f32x8, wild_f64x4;
Expr wild_u1x_, wild_i8x_, wild_u8x_, wild_i16x_, wild_u16x_;
Expr wild_i32x_, wild_u32x_, wild_i64x_, wild_u64x_;
Expr wild_f32x_, wild_f64x_;
Expr min_i8, max_i8, max_u8;
Expr min_i16, max_i16, max_u16;
Expr min_i32, max_i32, max_u32;
Expr min_i64, max_i64, max_u64;
Expr min_f32, max_f32, min_f64, max_f64;
llvm::Value *codegen(Expr);
void codegen(Stmt);
void scalarize(Expr);
enum DestructorType {Always, OnError, OnSuccess};
llvm::Value *register_destructor(llvm::Function *destructor_fn, llvm::Value *obj, DestructorType when);
void trigger_destructor(llvm::Function *destructor_fn, llvm::Value *stack_slot);
llvm::BasicBlock *get_destructor_block();
void create_assertion(llvm::Value *condition, Expr message, llvm::Value *error_code = nullptr);
void return_with_error_code(llvm::Value *error_code);
llvm::Constant *create_string_constant(const std::string &str);
llvm::Constant *create_binary_blob(const std::vector<char> &data, const std::string &name, bool constant = true);
llvm::Value *create_broadcast(llvm::Value *, int lanes);
llvm::Value *codegen_buffer_pointer(std::string buffer, Type type, llvm::Value *index);
llvm::Value *codegen_buffer_pointer(std::string buffer, Type type, Expr index);
llvm::Value *codegen_buffer_pointer(llvm::Value *base_address, Type type, Expr index);
llvm::Value *codegen_buffer_pointer(llvm::Value *base_address, Type type, llvm::Value *index);
llvm::Value *make_halide_type_t(Type);
void add_tbaa_metadata(llvm::Instruction *inst, std::string buffer, Expr index);
virtual std::string get_allocation_name(const std::string &n) {return n;}
virtual Expr mulhi_shr(Expr a, Expr b, int shr);
virtual Expr sorted_avg(Expr a, Expr b);
using IRVisitor::visit;
virtual void visit(const IntImm *);
virtual void visit(const UIntImm *);
virtual void visit(const FloatImm *);
virtual void visit(const StringImm *);
virtual void visit(const Cast *);
virtual void visit(const Variable *);
virtual void visit(const Add *);
virtual void visit(const Sub *);
virtual void visit(const Mul *);
virtual void visit(const Div *);
virtual void visit(const Mod *);
virtual void visit(const Min *);
virtual void visit(const Max *);
virtual void visit(const EQ *);
virtual void visit(const NE *);
virtual void visit(const LT *);
virtual void visit(const LE *);
virtual void visit(const GT *);
virtual void visit(const GE *);
virtual void visit(const And *);
virtual void visit(const Or *);
virtual void visit(const Not *);
virtual void visit(const Select *);
virtual void visit(const Load *);
virtual void visit(const Ramp *);
virtual void visit(const Broadcast *);
virtual void visit(const Call *);
virtual void visit(const Let *);
virtual void visit(const LetStmt *);
virtual void visit(const AssertStmt *);
virtual void visit(const ProducerConsumer *);
virtual void visit(const For *);
virtual void visit(const Store *);
virtual void visit(const Block *);
virtual void visit(const IfThenElse *);
virtual void visit(const Evaluate *);
virtual void visit(const Shuffle *);
virtual void visit(const Prefetch *);
virtual void visit(const Allocate *) = 0;
virtual void visit(const Free *) = 0;
virtual void visit(const Provide *);
virtual void visit(const Realize *);
virtual void prepare_for_early_exit() {}
llvm::Type *llvm_type_of(Type);
llvm::Value *create_alloca_at_entry(llvm::Type *type, int n,
bool zero_initialize = false,
const std::string &name = "");
std::set<std::string> external_buffer;
llvm::Value *get_user_context() const;
virtual llvm::Value *interleave_vectors(const std::vector<llvm::Value *> &);
llvm::Value *call_intrin(Type t, int intrin_lanes,
const std::string &name, std::vector<Expr>);
llvm::Value *call_intrin(llvm::Type *t, int intrin_lanes,
const std::string &name, std::vector<llvm::Value *>);
virtual llvm::Value *slice_vector(llvm::Value *vec, int start, int extent);
virtual llvm::Value *concat_vectors(const std::vector<llvm::Value *> &);
virtual llvm::Value *shuffle_vectors(llvm::Value *a, llvm::Value *b,
const std::vector<int> &indices);
llvm::Value *shuffle_vectors(llvm::Value *v, const std::vector<int> &indices);
std::pair<llvm::Function *, int> find_vector_runtime_function(const std::string &name, int lanes);
ModulusRemainder get_alignment_info(Expr e);
private:
Scope<llvm::Value *> symbol_table;
Scope<ModulusRemainder> alignment_info;
std::map<std::string, llvm::Constant *> string_constants;
llvm::BasicBlock *destructor_block;
llvm::Function* embed_metadata_getter(const std::string &metadata_getter_name,
const std::string &function_name, const std::vector<LoweredArgument> &args);
llvm::Constant *embed_constant_expr(Expr e);
llvm::Function *add_argv_wrapper(const std::string &name);
llvm::Value *codegen_dense_vector_load(const Load *load, llvm::Value *vpred = nullptr);
virtual void codegen_predicated_vector_load(const Load *op);
virtual void codegen_predicated_vector_store(const Store *op);
};
}
EXPORT std::unique_ptr<llvm::Module> codegen_llvm(const Module &module,
llvm::LLVMContext &context);
}
#endif