diff --git a/examples/matrix.cpp b/examples/matrix.cpp index 89d4aa9ec..78c8d7194 100644 --- a/examples/matrix.cpp +++ b/examples/matrix.cpp @@ -35,7 +35,8 @@ int main() { program->codegen(&module); llvm::LLVMContext llvm_context; llvm::Module llvm_module("test", llvm_context); - tdl::codegen::lowering(module, llvm_module); + tdl::codegen::selection selection; + selection.run(module, llvm_module); llvm::PrintModulePass print(llvm::outs()); llvm::AnalysisManager analysis; print.run(llvm_module, analysis); diff --git a/include/codegen/allocation.h b/include/codegen/allocation.h index b2112b20b..d23b98501 100644 --- a/include/codegen/allocation.h +++ b/include/codegen/allocation.h @@ -1,9 +1,45 @@ #ifndef TDL_INCLUDE_IR_CODEGEN_STORAGE_ALLOC_H #define TDL_INCLUDE_IR_CODEGEN_STORAGE_ALLOC_H +#include +#include + namespace tdl{ + +namespace ir{ + class value; + class function; +} + namespace codegen{ +class layout; +class target_tuner; +class liveness; +class loop_info; + +class allocation { +public: + // accessors + unsigned get_num_bytes(ir::value *x) const; + unsigned get_offset(ir::value *x) const { return offsets_.at(x); } + unsigned get_allocated_size() const { return allocated_size_; } + bool has_double_buffer(ir::value *x) const { return double_buffer_.find(x) != double_buffer_.end(); } + + // run + void run(ir::function &fn); + +private: + std::map offsets_; + std::set double_buffer_; + std::map num_bytes_; + size_t allocated_size_; + // dependences + liveness *liveness_; + layout *layout_; + loop_info *loop_info_; +}; + } } diff --git a/include/codegen/layout.h b/include/codegen/layout.h index 40227001c..1fd6deeda 100644 --- a/include/codegen/layout.h +++ b/include/codegen/layout.h @@ -1,9 +1,44 @@ #ifndef TDL_INCLUDE_IR_CODEGEN_LAYOUT_H #define TDL_INCLUDE_IR_CODEGEN_LAYOUT_H -namespace tdl{ +#include +#include + +namespace tdl { + +namespace ir { + class function; + class instruction; + class value; +} + namespace codegen{ +struct shared_view_info{ + ir::value *usr; + bool has_dedicated_storage; +}; + +class layout { +private: + typedef std::vector shared_view_val_t; + + void add_phi_nodes(ir::value *v); + void add_shared_views(ir::value *v); + +public: + // accessors + unsigned get_num_shared_views(ir::value *v); + shared_view_info get_shared_view(ir::value *v, unsigned idx); + + // run + bool run(ir::function &fn); + +private: + std::map shared_views_; +}; + + } } diff --git a/include/codegen/liveness.h b/include/codegen/liveness.h index 9afbc4e46..8a6806c2e 100644 --- a/include/codegen/liveness.h +++ b/include/codegen/liveness.h @@ -1,9 +1,61 @@ #ifndef TDL_INCLUDE_IR_CODEGEN_LIVENESS_H #define TDL_INCLUDE_IR_CODEGEN_LIVENESS_H +#include + namespace tdl{ + +namespace ir{ + class value; + class function; +} + namespace codegen{ +class layout; + +typedef unsigned slot_index; + +struct segment { + slot_index start; + slot_index end; + + bool contains(slot_index idx) const { + return start <= idx && idx < end; + } + + bool intersect(const segment &Other){ + return contains(Other.start) || Other.contains(start); + } +}; + +class liveness { +private: + typedef std::map indices_map_t; + typedef std::map intervals_map_t; + typedef std::map has_storage_map_t; + +public: + /// Intervals iterators... + using iterator = intervals_map_t::iterator; + using const_iterator = intervals_map_t::const_iterator; + +public: + + // accessors + const intervals_map_t& intervals() const { return intervals_; } + segment get_interval(ir::value* v) const { return intervals_.at(v); } + + // run + void run(ir::function *fn); + +private: + has_storage_map_t has_dedicated_storage_; + indices_map_t indices_; + intervals_map_t intervals_; + layout* layouts_; +}; + } } diff --git a/include/codegen/selection.h b/include/codegen/selection.h index 5c2bff41e..b55725c05 100644 --- a/include/codegen/selection.h +++ b/include/codegen/selection.h @@ -9,191 +9,35 @@ #include "ir/type.h" +namespace llvm{ + class Type; + class Value; + class Instruction; + class Constant; + class LLVMContext; +} + namespace tdl{ namespace codegen{ -using namespace llvm; +class selection{ + typedef std::map vmap_t; + typedef std::map bmap_t; -/* convert ir::type to Type */ -Type *llvm_type(ir::type *ty, LLVMContext &ctx) { - // function - if(auto* tt = dynamic_cast(ty)){ - Type *return_ty = llvm_type(tt->get_return_ty(), ctx); - std::vector param_tys; - std::transform(tt->params_begin(), tt->params_end(), std::back_inserter(param_tys), - [&ctx](ir::type* t){ return llvm_type(t, ctx);}); - return FunctionType::get(return_ty, param_tys, false); - } - // pointer - if(ty->is_pointer_ty()){ - Type *elt_ty = llvm_type(ty->get_pointer_element_ty(), ctx); - unsigned addr_space = ty->get_pointer_address_space(); - return PointerType::get(elt_ty, addr_space); - } - // integer - if(ty->is_integer_ty()){ - unsigned bitwidth = ty->get_integer_bitwidth(); - return IntegerType::get(ctx, bitwidth); - } - // primitive types - switch(ty->get_type_id()){ - case ir::type::VoidTyID: return Type::getVoidTy(ctx); - case ir::type::HalfTyID: return Type::getHalfTy(ctx); - case ir::type::FloatTyID: return Type::getFloatTy(ctx); - case ir::type::DoubleTyID: return Type::getDoubleTy(ctx); - case ir::type::X86_FP80TyID: return Type::getX86_FP80Ty(ctx); - case ir::type::PPC_FP128TyID: return Type::getPPC_FP128Ty(ctx); - case ir::type::LabelTyID: return Type::getLabelTy(ctx); - case ir::type::MetadataTyID: return Type::getMetadataTy(ctx); - case ir::type::TokenTyID: return Type::getTokenTy(ctx); - default: break; - } - // unknown type - throw std::runtime_error("unknown conversion from ir::type to Type"); -} +private: + llvm::Type* llvm_type(ir::type *ty, llvm::LLVMContext &ctx); + llvm::Value* llvm_value(ir::value *v,llvm:: LLVMContext &ctx); + llvm::Instruction* llvm_inst(ir::instruction *inst, llvm::LLVMContext &ctx); + llvm::Constant* llvm_constant(ir::constant *cst, llvm::LLVMContext &ctx); -Value* llvm_value(ir::value *v, LLVMContext &ctx, - std::map &vmap, - std::map &bmap); +public: + void run(ir::module &src, llvm::Module &dst); -/* convert ir::constant to Constant */ -Constant *llvm_constant(ir::constant *cst, LLVMContext &ctx) { - Type *dst_ty = llvm_type(cst->get_type(), ctx); - if(auto* cc = dynamic_cast(cst)) - return ConstantInt::get(dst_ty, cc->get_value()); - if(auto* cc = dynamic_cast(cst)) - return ConstantFP::get(dst_ty, cc->get_value()); - // unknown constant - throw std::runtime_error("unknown conversion from ir::constant to Constant"); -} - - -/* convert ir::instruction to Instruction */ -Instruction *llvm_inst(ir::instruction *inst, LLVMContext & ctx, - std::map &vmap, - std::map &bmap) { - auto value = [&](ir::value *x) { return llvm_value(x, ctx, vmap, bmap); }; - auto block = [&](ir::basic_block *x) { return bmap.at(x); }; - auto type = [&](ir::type *x) { return llvm_type(x, ctx); }; - if(auto* ii = dynamic_cast(inst)){ - BasicBlock *true_dest = block(ii->get_true_dest()); - BasicBlock *false_dest = block(ii->get_false_dest()); - Value *cond = value(ii->get_cond()); - return BranchInst::Create(true_dest, false_dest, cond); - } - if(auto* ii = dynamic_cast(inst)){ - BasicBlock *dest = block(ii->get_dest()); - return BranchInst::Create(dest); - } - if(auto* ii = dynamic_cast(inst)){ - Type *ty = type(ii->get_type()); - unsigned num_ops = ii->get_num_operands(); - return PHINode::Create(ty, num_ops, ii->get_name()); - } - if(auto* ii = dynamic_cast(inst)){ - ir::value *ret_val = ii->get_return_value(); - return ReturnInst::Create(ctx, ret_val?value(ret_val):nullptr); - } - if(auto* ii = dynamic_cast(inst)){ - Value *lhs = value(ii->get_operand(0)); - Value *rhs = value(ii->get_operand(1)); - return BinaryOperator::Create(ii->get_op(), lhs, rhs, ii->get_name()); - } - if(auto* ii = dynamic_cast(inst)){ - CmpInst::Predicate pred = ii->get_pred(); - Value *lhs = value(ii->get_operand(0)); - Value *rhs = value(ii->get_operand(1)); - return CmpInst::Create(Instruction::ICmp, pred, lhs, rhs, ii->get_name()); - } - if(auto* ii = dynamic_cast(inst)){ - CmpInst::Predicate pred = ii->get_pred(); - Value *lhs = value(ii->get_operand(0)); - Value *rhs = value(ii->get_operand(1)); - return FCmpInst::Create(Instruction::FCmp, pred, lhs, rhs, ii->get_name()); - } - if(auto* ii = dynamic_cast(inst)){ - Value *arg = value(ii->get_operand(0)); - Type *dst_ty = type(ii->get_type()); - return CastInst::Create(ii->get_op(), arg, dst_ty, ii->get_name()); - } - if(auto* ii = dynamic_cast(inst)){ - std::vector idx_vals; - std::transform(ii->idx_begin(), ii->idx_end(), std::back_inserter(idx_vals), - [&value](ir::value* x){ return value(x);}); - Type *source_ty = type(ii->get_source_elt_ty()); - Value *arg = value(ii->get_operand(0)); - return GetElementPtrInst::Create(source_ty, arg, idx_vals, ii->get_name()); - } - if(ir::load_inst* ii = dynamic_cast(inst)){ - Value *ptr = value(ii->get_pointer_operand()); - return new LoadInst(ptr, ii->get_name()); - } - // unknown instruction - throw std::runtime_error("unknown conversion from ir::type to Type"); -} - -Value* llvm_value(ir::value *v, LLVMContext &ctx, - std::map &vmap, - std::map &bmap) { - if(vmap.find(v) != vmap.end()) - return vmap.at(v); - // create operands - if(auto *uu = dynamic_cast(v)) - for(ir::value* u: uu->ops()) - vmap[u] = llvm_value(u, ctx, vmap, bmap); - if(auto *cc = dynamic_cast(v)) - return llvm_constant(cc, ctx); - // instruction - if(auto *ii = dynamic_cast(v)) - return llvm_inst(ii, ctx, vmap, bmap); - // unknown value - throw std::runtime_error("unknown conversion from ir::value to Value"); -} - -void lowering(ir::module &src, Module &dst){ - std::map vmap; - std::map bmap; - LLVMContext &dst_ctx = dst.getContext(); - IRBuilder<> dst_builder(dst_ctx); - // iterate over functions - for(ir::function *fn: src.get_function_list()) { - // create LLVM function - FunctionType *fn_ty = (FunctionType*)llvm_type(fn->get_fn_type(), dst_ctx); - Function *dst_fn = Function::Create(fn_ty, Function::ExternalLinkage, "kernel", &dst); -// std::cout << ((FunctionType*)fn_ty)->getNumParams() << std::endl; - // map parameters - for(unsigned i = 0; i < fn->args().size(); i++) - vmap[fn->args()[i]] = &*(dst_fn->arg_begin() + i); - // create blocks - for(ir::basic_block *block: fn->blocks()) { - BasicBlock *dst_block = BasicBlock::Create(dst_ctx, block->get_name(), dst_fn); - bmap[block] = dst_block; - } - // iterate through block - for(ir::basic_block *block: fn->blocks()) { - dst_builder.SetInsertPoint(bmap[block]); - for(ir::instruction *inst: block->get_inst_list()) { - Instruction *dst_inst = llvm_inst(inst, dst_ctx, vmap, bmap); - vmap[inst] = dst_inst; - dst_builder.Insert(dst_inst); - } - } - // add phi operands - for(ir::basic_block *block: fn->blocks()) - for(ir::instruction *inst: block->get_inst_list()) - if(auto *phi = dynamic_cast(inst)){ - PHINode *dst_phi = (PHINode*)vmap.at(phi); - for(unsigned i = 0; i < phi->get_num_incoming(); i++){ - ir::value *inc_val = phi->get_incoming_value(i); - ir::basic_block *inc_block = phi->get_incoming_block(i); - Value *llvm_inc_val = llvm_value(inc_val, dst_ctx, vmap, bmap); - BasicBlock *llvm_block = bmap[inc_block]; - dst_phi->addIncoming(llvm_inc_val, llvm_block); - } - } - } -} +private: + vmap_t vmap_; + bmap_t bmap_; +}; } } diff --git a/include/codegen/tune.h b/include/codegen/tune.h index f1871167a..98ba7e327 100644 --- a/include/codegen/tune.h +++ b/include/codegen/tune.h @@ -1,10 +1,56 @@ -#ifndef TDL_INCLUDE_IR_CODEGEN_TUNE_H -#define TDL_INCLUDE_IR_CODEGEN_TUNE_H +//#ifndef TDL_INCLUDE_IR_CODEGEN_TUNE_H +//#define TDL_INCLUDE_IR_CODEGEN_TUNE_H -namespace tdl{ -namespace codegen{ +//namespace tdl{ +//namespace codegen{ -} -} +//// Layout binding pass +//class TLVMAddTunerParams: public FunctionPass { +//private: +// enum CType{ +// Layout = 0, Shape = 1 +// }; +// // Params pool +// SmallVector LParamsPool; +// // Constraints +// typedef std::pair CNodeType; +// typedef DenseMap> CGraphType; +// // Layout constraints +// CGraphType LCGraph; +// DenseSet LCNodes; +// // Shape constraints +// CGraphType SCGraph; +// DenseSet SCNodes; +// // Relational +// std::map, std::function> ExtraParams; +// DenseSet Constants; -#endif +// void addConstraint(CNodeType X, CNodeType Y, CType CT); +// void initCPhi(Instruction *I); +// void initCGraph(Instruction *V); +// void connectedComponents(CNodeType X, ArrayRef Vals, CType CT, DenseSet &Nodes, CGraphType &Graph); + +//public: +// static char ID; +// TLVMAddTunerParams(): FunctionPass(ID){ } + +// void getAnalysisUsage(AnalysisUsage & AU) const override; +// bool runOnFunction(Function &F) override; + +//private: +// std::map, Constant*> KnownParams; +//}; + +//class TLVMAddTunerConstraints: public FunctionPass { +//public: +// static char ID; +// TLVMAddTunerConstraints(): FunctionPass(ID){ } + +// void getAnalysisUsage(AnalysisUsage & AU) const override; +// bool runOnFunction(Function &F) override; +//}; + +//} +//} + +//#endif diff --git a/include/ir/instructions.h b/include/ir/instructions.h index 875b2b0a0..9d390b8cb 100644 --- a/include/ir/instructions.h +++ b/include/ir/instructions.h @@ -332,6 +332,11 @@ public: }; +// matmul + +class matmul_inst: public instruction { + +}; } } diff --git a/include/ir/type.h b/include/ir/type.h index fb268326a..ab7b20ef1 100644 --- a/include/ir/type.h +++ b/include/ir/type.h @@ -51,8 +51,10 @@ public: // type attributes unsigned get_fp_mantissa_width() const; unsigned get_integer_bitwidth() const; + unsigned get_size_in_bits() const; type *get_scalar_ty() const; const std::vector &get_tile_shapes() const; + unsigned get_tile_num_elements() const; type *get_tile_element_ty() const; unsigned get_pointer_address_space() const; type *get_pointer_element_ty() const; @@ -135,6 +137,7 @@ private: public: // accessors const std::vector& get_shapes() const { return shapes_; } + unsigned get_num_elements(); // factory methods static tile_type* get(type *ty, const std::vector &shapes);