[code generation] some more cleaning
This commit is contained in:
@@ -21,17 +21,14 @@ class loop_info;
|
|||||||
class allocation {
|
class allocation {
|
||||||
public:
|
public:
|
||||||
// accessors
|
// accessors
|
||||||
unsigned get_num_bytes(ir::value *x) const;
|
|
||||||
unsigned get_offset(ir::value *x) const { return offsets_.at(x); }
|
unsigned get_offset(ir::value *x) const { return offsets_.at(x); }
|
||||||
unsigned get_allocated_size() const { return allocated_size_; }
|
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
|
// run
|
||||||
void run(ir::function &fn);
|
void run(ir::function &fn);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::map<ir::value*, unsigned> offsets_;
|
std::map<ir::value*, unsigned> offsets_;
|
||||||
std::set<ir::value*> double_buffer_;
|
|
||||||
std::map<ir::value*, unsigned> num_bytes_;
|
std::map<ir::value*, unsigned> num_bytes_;
|
||||||
size_t allocated_size_;
|
size_t allocated_size_;
|
||||||
// dependences
|
// dependences
|
||||||
|
@@ -1,56 +1,45 @@
|
|||||||
//#ifndef TDL_INCLUDE_IR_CODEGEN_TUNE_H
|
#ifndef TDL_INCLUDE_IR_CODEGEN_TUNE_H
|
||||||
//#define TDL_INCLUDE_IR_CODEGEN_TUNE_H
|
#define TDL_INCLUDE_IR_CODEGEN_TUNE_H
|
||||||
|
|
||||||
//namespace tdl{
|
#include <map>
|
||||||
//namespace codegen{
|
#include <set>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
//// Layout binding pass
|
namespace tdl{
|
||||||
//class TLVMAddTunerParams: public FunctionPass {
|
|
||||||
//private:
|
|
||||||
// enum CType{
|
|
||||||
// Layout = 0, Shape = 1
|
|
||||||
// };
|
|
||||||
// // Params pool
|
|
||||||
// SmallVector<MDNode*, 8> LParamsPool;
|
|
||||||
// // Constraints
|
|
||||||
// typedef std::pair<Value*, unsigned> CNodeType;
|
|
||||||
// typedef DenseMap<CNodeType, DenseSet<CNodeType>> CGraphType;
|
|
||||||
// // Layout constraints
|
|
||||||
// CGraphType LCGraph;
|
|
||||||
// DenseSet<CNodeType> LCNodes;
|
|
||||||
// // Shape constraints
|
|
||||||
// CGraphType SCGraph;
|
|
||||||
// DenseSet<CNodeType> SCNodes;
|
|
||||||
// // Relational
|
|
||||||
// std::map<std::pair<Value*, std::string>, std::function<unsigned* ()>> ExtraParams;
|
|
||||||
// DenseSet<unsigned> Constants;
|
|
||||||
|
|
||||||
// void addConstraint(CNodeType X, CNodeType Y, CType CT);
|
namespace ir{
|
||||||
// void initCPhi(Instruction *I);
|
class value;
|
||||||
// void initCGraph(Instruction *V);
|
class module;
|
||||||
// void connectedComponents(CNodeType X, ArrayRef<MDNode *> Vals, CType CT, DenseSet<CNodeType> &Nodes, CGraphType &Graph);
|
class instruction;
|
||||||
|
}
|
||||||
|
|
||||||
//public:
|
namespace codegen{
|
||||||
// static char ID;
|
|
||||||
// TLVMAddTunerParams(): FunctionPass(ID){ }
|
|
||||||
|
|
||||||
// void getAnalysisUsage(AnalysisUsage & AU) const override;
|
class tune {
|
||||||
// bool runOnFunction(Function &F) override;
|
typedef std::pair<ir::value*, unsigned> node_t;
|
||||||
|
typedef std::map <node_t, std::set<node_t>> graph_t;
|
||||||
|
|
||||||
//private:
|
private:
|
||||||
// std::map<std::pair<Instruction*, std::string>, Constant*> KnownParams;
|
void add_constraint(node_t x, node_t y);
|
||||||
//};
|
void init_c_phi(ir::instruction *i);
|
||||||
|
void init_c_graph(ir::instruction *v);
|
||||||
|
void connected_components(node_t x, const std::vector<unsigned*> vals, std::set<node_t> &nodes, graph_t &graph);
|
||||||
|
|
||||||
//class TLVMAddTunerConstraints: public FunctionPass {
|
|
||||||
//public:
|
|
||||||
// static char ID;
|
|
||||||
// TLVMAddTunerConstraints(): FunctionPass(ID){ }
|
|
||||||
|
|
||||||
// void getAnalysisUsage(AnalysisUsage & AU) const override;
|
public:
|
||||||
// bool runOnFunction(Function &F) override;
|
unsigned *get_param(ir::value *value);
|
||||||
//};
|
bool check_constraints(std::map<ir::value*, std::string>& errors);
|
||||||
|
void run(ir::module &mod);
|
||||||
|
|
||||||
//}
|
private:
|
||||||
//}
|
std::map<ir::value*, std::map<std::string, unsigned*>> params_;
|
||||||
|
std::vector<unsigned*> pool_;
|
||||||
|
graph_t dependencies_;
|
||||||
|
std::set<node_t> nodes_;
|
||||||
|
};
|
||||||
|
|
||||||
//#endif
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
@@ -51,7 +51,8 @@ public:
|
|||||||
// type attributes
|
// type attributes
|
||||||
unsigned get_fp_mantissa_width() const;
|
unsigned get_fp_mantissa_width() const;
|
||||||
unsigned get_integer_bitwidth() const;
|
unsigned get_integer_bitwidth() const;
|
||||||
unsigned get_size_in_bits() const;
|
unsigned get_tile_bitwidth() const;
|
||||||
|
unsigned get_primitive_size_in_bits() const;
|
||||||
type *get_scalar_ty() const;
|
type *get_scalar_ty() const;
|
||||||
const std::vector<unsigned> &get_tile_shapes() const;
|
const std::vector<unsigned> &get_tile_shapes() const;
|
||||||
unsigned get_tile_num_elements() const;
|
unsigned get_tile_num_elements() const;
|
||||||
@@ -137,7 +138,8 @@ private:
|
|||||||
public:
|
public:
|
||||||
// accessors
|
// accessors
|
||||||
const std::vector<unsigned>& get_shapes() const { return shapes_; }
|
const std::vector<unsigned>& get_shapes() const { return shapes_; }
|
||||||
unsigned get_num_elements();
|
unsigned get_num_elements() const;
|
||||||
|
unsigned get_bitwidth() const;
|
||||||
|
|
||||||
// factory methods
|
// factory methods
|
||||||
static tile_type* get(type *ty, const std::vector<unsigned> &shapes);
|
static tile_type* get(type *ty, const std::vector<unsigned> &shapes);
|
||||||
|
@@ -1,7 +1,6 @@
|
|||||||
#include "codegen/allocation.h"
|
#include "codegen/allocation.h"
|
||||||
#include "codegen/liveness.h"
|
#include "codegen/liveness.h"
|
||||||
#include "codegen/layout.h"
|
#include "codegen/layout.h"
|
||||||
#include "codegen/loop_info.h"
|
|
||||||
#include "ir/basic_block.h"
|
#include "ir/basic_block.h"
|
||||||
#include "ir/type.h"
|
#include "ir/type.h"
|
||||||
#include "ir/value.h"
|
#include "ir/value.h"
|
||||||
@@ -11,27 +10,15 @@
|
|||||||
namespace tdl{
|
namespace tdl{
|
||||||
namespace codegen{
|
namespace codegen{
|
||||||
|
|
||||||
unsigned allocation::get_num_bytes(ir::value *x) const {
|
|
||||||
ir::type *ty = x->get_type();
|
|
||||||
unsigned num_elements = ty->get_tile_num_elements();
|
|
||||||
if(has_double_buffer(x))
|
|
||||||
num_elements *= 2;
|
|
||||||
return num_elements * ty->get_scalar_ty()->get_size_in_bits();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void allocation::run(ir::function &fn){
|
void allocation::run(ir::function &fn){
|
||||||
using std::max;
|
using std::max;
|
||||||
using std::min;
|
using std::min;
|
||||||
typedef std::multimap<unsigned, segment> triples_map_type;
|
typedef std::multimap<unsigned, segment> triples_map_type;
|
||||||
|
|
||||||
// Fill double buffering info
|
auto get_num_bytes = [&](ir::value *x){
|
||||||
for(ir::basic_block *block: fn.blocks())
|
return x->get_type()->get_tile_bitwidth();
|
||||||
for(ir::instruction *v: block->get_inst_list())
|
};
|
||||||
// If requires shared memory
|
|
||||||
if(layout_->get_num_shared_views(v) &&
|
|
||||||
loop_info_->get_loop_for(block))
|
|
||||||
double_buffer_.insert(v);
|
|
||||||
|
|
||||||
std::vector<ir::value *> I;
|
std::vector<ir::value *> I;
|
||||||
for(auto x: liveness_->intervals())
|
for(auto x: liveness_->intervals())
|
||||||
|
@@ -11,7 +11,6 @@ namespace codegen{
|
|||||||
|
|
||||||
// Entry point
|
// Entry point
|
||||||
void liveness::run(ir::function *fn) {
|
void liveness::run(ir::function *fn) {
|
||||||
|
|
||||||
// Assigns index to each instruction
|
// Assigns index to each instruction
|
||||||
slot_index index = 0;
|
slot_index index = 0;
|
||||||
for(ir::basic_block *block: fn->blocks())
|
for(ir::basic_block *block: fn->blocks())
|
||||||
@@ -19,7 +18,6 @@ void liveness::run(ir::function *fn) {
|
|||||||
index += 1;
|
index += 1;
|
||||||
indices_.insert({instr, index});
|
indices_.insert({instr, index});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Liveness analysis
|
// Liveness analysis
|
||||||
// Creates live intervals
|
// Creates live intervals
|
||||||
for(auto i: indices_){
|
for(auto i: indices_){
|
||||||
|
@@ -1,49 +1,93 @@
|
|||||||
//#include "codegen/tune.h"
|
#include "codegen/tune.h"
|
||||||
|
#include "ir/instructions.h"
|
||||||
|
#include "ir/type.h"
|
||||||
|
#include "ir/module.h"
|
||||||
|
#include "ir/function.h"
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
//namespace tdl{
|
namespace tdl{
|
||||||
//namespace codegen{
|
namespace codegen{
|
||||||
|
|
||||||
|
void tune::add_constraint(node_t x, node_t y) {
|
||||||
|
dependencies_[x].insert(y);
|
||||||
|
dependencies_[y].insert(x);
|
||||||
|
nodes_.insert(x);
|
||||||
|
nodes_.insert(y);
|
||||||
|
}
|
||||||
|
|
||||||
//// Layout binding pass
|
void tune::init_c_phi(ir::instruction *v) {
|
||||||
//class TLVMAddTunerConstraints: public FunctionPass {
|
// Phi Nodes: all the incoming value share the result layout
|
||||||
//public:
|
if(auto *phi = dynamic_cast<ir::phi_node*>(v))
|
||||||
// static char ID;
|
for(ir::value *inc: phi->ops())
|
||||||
// TLVMAddTunerConstraints(): FunctionPass(ID){ }
|
for(unsigned k = 0; k < phi->get_type()->get_tile_shapes().size(); k++)
|
||||||
|
if(dependencies_.find({inc, k}) != dependencies_.end()
|
||||||
|
|| dependencies_.find({phi, k}) != dependencies_.end())
|
||||||
|
add_constraint({phi, k}, {inc, k});
|
||||||
|
}
|
||||||
|
|
||||||
// void getAnalysisUsage(AnalysisUsage & AU) const override;
|
void tune::init_c_graph(ir::instruction *v) {
|
||||||
// bool runOnFunction(Function &F) override;
|
unsigned num_dim = v->get_type()->get_tile_shapes().size();
|
||||||
//};
|
if(dynamic_cast<ir::reshape_inst*>(v)){
|
||||||
|
|
||||||
//// Initialization
|
}
|
||||||
//char TLVMAddTunerConstraints::ID = 0;
|
else if(dynamic_cast<ir::splat_inst*>(v)){
|
||||||
//INITIALIZE_PASS_BEGIN(TLVMAddTunerConstraints, "tlvm-add-tuner-constraints",
|
|
||||||
// "Add Tuner Constraints (TLVM)", false, true)
|
|
||||||
//INITIALIZE_PASS_END(TLVMAddTunerConstraints, "tlvm-add-tuner-constraints",
|
|
||||||
// "Add Tuner Constraints (TLVM)", false, true)
|
|
||||||
//FunctionPass *llvm::createTLVMAddTunerConstraintsPass() { return new TLVMAddTunerConstraints(); }
|
|
||||||
|
|
||||||
//// Analysis usage
|
}
|
||||||
//void TLVMAddTunerConstraints::getAnalysisUsage(AnalysisUsage &AU) const {
|
else if(dynamic_cast<ir::broadcast_inst*>(v)){
|
||||||
// AU.setPreservesAll();
|
|
||||||
// FunctionPass::getAnalysisUsage(AU);
|
|
||||||
//}
|
|
||||||
|
|
||||||
|
}
|
||||||
|
else if(auto *ii = dynamic_cast<ir::matmul_inst*>(v)){
|
||||||
|
ir::value *D = ii->get_operand(2);
|
||||||
|
add_constraint({v, 0}, {D, 0});
|
||||||
|
add_constraint({v, 1}, {D, 1});
|
||||||
|
}
|
||||||
|
else if(dynamic_cast<ir::user*>(v))
|
||||||
|
for(unsigned i = 0; i < num_dim; i ++)
|
||||||
|
for(ir::value* op: v->ops())
|
||||||
|
add_constraint({v, i}, {op, i});
|
||||||
|
}
|
||||||
|
|
||||||
//inline unsigned MDRead(MDNode* Node){
|
void tune::connected_components(node_t x, const std::vector<unsigned *> vals, std::set<node_t> &nodes, graph_t &graph) {
|
||||||
// Metadata *MD = Node->getOperand(0).get();
|
if(nodes.find(x) != nodes.end()){
|
||||||
// Constant *Cst = ((ConstantAsMetadata*)MD)->getValue();
|
nodes.erase(x);
|
||||||
// unsigned Result = Cst->getUniqueInteger().getZExtValue();
|
std::string suffix = ".d" + std::to_string(x.second);
|
||||||
// return Result;
|
if(auto *instr = dynamic_cast<ir::instruction*>(x.first)){
|
||||||
//}
|
params_[instr].insert({"p0" + suffix, vals[0]});
|
||||||
|
params_[instr].insert({"p1" + suffix, vals[1]});
|
||||||
|
params_[instr].insert({"p2" + suffix, vals[2]});
|
||||||
|
}
|
||||||
|
for(const node_t &y: graph[x])
|
||||||
|
connected_components(y, vals, nodes, graph);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void tune::run(ir::module &mod) {
|
||||||
|
for(ir::function *fn: mod.get_function_list()){
|
||||||
|
// Build constraints graph
|
||||||
|
for(ir::basic_block *block: fn->blocks())
|
||||||
|
for(ir::instruction *i : block->get_inst_list())
|
||||||
|
if(i->get_type()->is_tile_ty())
|
||||||
|
init_c_graph(i);
|
||||||
|
// Build phi constraints
|
||||||
|
for(ir::basic_block *block: fn->blocks())
|
||||||
|
for(ir::instruction *i : block->get_inst_list())
|
||||||
|
if(i->get_type()->is_tile_ty())
|
||||||
|
init_c_phi(i);
|
||||||
|
// Layout parameters
|
||||||
|
while(!nodes_.empty()){
|
||||||
|
unsigned *v0 = new unsigned(0);
|
||||||
|
unsigned *v1 = new unsigned(0);
|
||||||
|
unsigned *v2 = new unsigned(0);
|
||||||
|
connected_components(*nodes_.begin(), {v0, v1, v2}, nodes_, dependencies_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool tune::check_constraints(std::map<ir::value *, std::string> &errors) {
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
//inline unsigned getNumGT1Dim(Instruction &I){
|
|
||||||
// unsigned Res = 0;
|
|
||||||
// for(unsigned K = 0; K < I.getType()->getTileNumDimensions(); K++)
|
|
||||||
// if(MDRead(I.getMetadata("nvvm.param.shape.d" + itostr(K))) > 1)
|
|
||||||
// Res++;
|
|
||||||
// return Res;
|
|
||||||
//}
|
|
||||||
//// Run
|
|
||||||
//bool TLVMAddTunerConstraints::runOnFunction(Function &F) {
|
//bool TLVMAddTunerConstraints::runOnFunction(Function &F) {
|
||||||
// LLVMContext &Ctx = F.getContext();
|
// LLVMContext &Ctx = F.getContext();
|
||||||
|
|
||||||
@@ -114,355 +158,5 @@
|
|||||||
//}
|
//}
|
||||||
|
|
||||||
|
|
||||||
//// Layout binding pass
|
}
|
||||||
//class TLVMAddTunerParams: public FunctionPass {
|
}
|
||||||
//private:
|
|
||||||
// enum CType{
|
|
||||||
// Layout = 0, Shape = 1
|
|
||||||
// };
|
|
||||||
// // Params pool
|
|
||||||
// SmallVector<MDNode*, 8> LParamsPool;
|
|
||||||
// // Constraints
|
|
||||||
// typedef std::pair<Value*, unsigned> CNodeType;
|
|
||||||
// typedef DenseMap<CNodeType, DenseSet<CNodeType>> CGraphType;
|
|
||||||
// // Layout constraints
|
|
||||||
// CGraphType LCGraph;
|
|
||||||
// DenseSet<CNodeType> LCNodes;
|
|
||||||
// // Shape constraints
|
|
||||||
// CGraphType SCGraph;
|
|
||||||
// DenseSet<CNodeType> SCNodes;
|
|
||||||
// // Relational
|
|
||||||
// std::map<std::pair<Value*, std::string>, std::function<unsigned* ()>> ExtraParams;
|
|
||||||
// DenseSet<unsigned> Constants;
|
|
||||||
|
|
||||||
// void addConstraint(CNodeType X, CNodeType Y, CType CT);
|
|
||||||
// void initCPhi(Instruction *I);
|
|
||||||
// void initCGraph(Instruction *V);
|
|
||||||
// void connectedComponents(CNodeType X, ArrayRef<MDNode *> Vals, CType CT, DenseSet<CNodeType> &Nodes, CGraphType &Graph);
|
|
||||||
|
|
||||||
//public:
|
|
||||||
// static char ID;
|
|
||||||
// TLVMAddTunerParams(): FunctionPass(ID){ }
|
|
||||||
|
|
||||||
// void getAnalysisUsage(AnalysisUsage & AU) const override;
|
|
||||||
// bool runOnFunction(Function &F) override;
|
|
||||||
|
|
||||||
//private:
|
|
||||||
// std::map<std::pair<Instruction*, std::string>, Constant*> KnownParams;
|
|
||||||
//};
|
|
||||||
|
|
||||||
//// Initialization
|
|
||||||
//char TLVMAddTunerParams::ID = 0;
|
|
||||||
//INITIALIZE_PASS_BEGIN(TLVMAddTunerParams, "tlvm-add-tuner-parameters",
|
|
||||||
// "Add Tuner Parameters (TLVM)", false, true)
|
|
||||||
//INITIALIZE_PASS_END(TLVMAddTunerParams, "tlvm-add-tuner-parameters",
|
|
||||||
// "Add Tuner Parameters (TLVM)", false, true)
|
|
||||||
//FunctionPass *llvm::createTLVMAddTunerParamsPass() { return new TLVMAddTunerParams(); }
|
|
||||||
|
|
||||||
//// Analysis usage
|
|
||||||
//void TLVMAddTunerParams::getAnalysisUsage(AnalysisUsage &AU) const {
|
|
||||||
// AU.setPreservesAll();
|
|
||||||
// FunctionPass::getAnalysisUsage(AU);
|
|
||||||
//}
|
|
||||||
|
|
||||||
//void TLVMAddTunerParams::addConstraint(CNodeType X, CNodeType Y, CType CT){
|
|
||||||
// // Layout Constraint
|
|
||||||
// if(CT == Layout){
|
|
||||||
// LCGraph[X].insert(Y);
|
|
||||||
// LCGraph[Y].insert(X);
|
|
||||||
// LCNodes.insert(X);
|
|
||||||
// LCNodes.insert(Y);
|
|
||||||
// }
|
|
||||||
// if(CT == Shape || CT == Layout){
|
|
||||||
// SCGraph[X].insert(Y);
|
|
||||||
// SCGraph[Y].insert(X);
|
|
||||||
// SCNodes.insert(X);
|
|
||||||
// SCNodes.insert(Y);
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
//void TLVMAddTunerParams::initCPhi(Instruction *I){
|
|
||||||
// unsigned NumDim = 0;
|
|
||||||
// // Phi Nodes: all the incoming value share the result layout
|
|
||||||
// if(PHINode *Phi = dyn_cast<PHINode>(I)){
|
|
||||||
// Type *Ty = Phi->getType();
|
|
||||||
// NumDim = Ty->getTileNumDimensions();
|
|
||||||
// unsigned NumInc = Phi->getNumIncomingValues();
|
|
||||||
// for(unsigned PI = 0; PI < NumInc; PI++){
|
|
||||||
// Value *Inc = Phi->getIncomingValue(PI);
|
|
||||||
// for(unsigned K = 0; K < NumDim; K++){
|
|
||||||
// CType CT = (LCGraph.find({Inc,K}) != LCGraph.end() ||
|
|
||||||
// LCGraph.find({Phi,K}) != LCGraph.end())?Layout:Shape;
|
|
||||||
// addConstraint({Phi, K}, {Inc, K}, CT);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
//void TLVMAddTunerParams::initCGraph(Instruction *I) {
|
|
||||||
// unsigned NumDim = 0;
|
|
||||||
// LLVMContext &Context = I->getContext();
|
|
||||||
// Constant *_1 = ConstantInt::get(Type::getInt32Ty(Context), 1);
|
|
||||||
// // Function call
|
|
||||||
// if(CallInst *Call = dyn_cast<CallInst>(I))
|
|
||||||
// if(Function *Callee = Call->getCalledFunction()){
|
|
||||||
// Intrinsic::ID IntrinsicID = Callee->getIntrinsicID();
|
|
||||||
// switch (IntrinsicID) {
|
|
||||||
// // Outer
|
|
||||||
// case Intrinsic::tlvm_outer_add: LLVM_FALLTHROUGH;
|
|
||||||
// case Intrinsic::tlvm_outer_and: {
|
|
||||||
// addConstraint({Call, 0}, {Call->getOperand(0), 0}, Layout);
|
|
||||||
// addConstraint({Call, 1}, {Call->getOperand(1), 0}, Layout);
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// // Slice
|
|
||||||
// case Intrinsic::tlvm_read_slice_x: LLVM_FALLTHROUGH;
|
|
||||||
// case Intrinsic::tlvm_read_slice_y: {
|
|
||||||
// addConstraint({Call, 0}, {Call->getOperand(0), 0}, Shape);
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// // Range
|
|
||||||
// case Intrinsic::tlvm_range: {
|
|
||||||
// addConstraint({Call, 0}, {Call->getOperand(1), 0}, Shape);
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// // GetTilePtr
|
|
||||||
// case Intrinsic::tlvm_gtp_2d: NumDim++; LLVM_FALLTHROUGH;
|
|
||||||
// case Intrinsic::tlvm_gtp_1d: NumDim++; {
|
|
||||||
// Value *Offset = Call->getOperand(1);
|
|
||||||
// for(unsigned K = 0; K < NumDim; K++){
|
|
||||||
// addConstraint({Call, K}, {Offset, K}, Layout);
|
|
||||||
// }
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// // SlideTilePtr: Pointer shares result layout
|
|
||||||
// case Intrinsic::tlvm_stp_2d: NumDim++; LLVM_FALLTHROUGH;
|
|
||||||
// case Intrinsic::tlvm_stp_1d: NumDim++; {
|
|
||||||
// for(unsigned K = 0; K < NumDim; K++){
|
|
||||||
// addConstraint({Call, K}, {Call->getOperand(0), K}, Layout);
|
|
||||||
// addConstraint({Call, K}, {Call->getOperand(1), K}, Layout);
|
|
||||||
// }
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// // Transpose
|
|
||||||
// case Intrinsic::tlvm_transpose_2d: NumDim++; NumDim++; {
|
|
||||||
// Value *Op = Call->getOperand(0);
|
|
||||||
// addConstraint({Call, 0}, {Op, 1}, Shape);
|
|
||||||
// addConstraint({Call, 1}, {Op, 0}, Shape);
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// // Reshape
|
|
||||||
// case Intrinsic::tlvm_reshape_2d: NumDim++; NumDim++; {
|
|
||||||
// for(unsigned K = 0; K < NumDim; K++)
|
|
||||||
// addConstraint({Call, K}, {Call->getOperand(1 + K), 0}, Shape);
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// // Reshape distributed
|
|
||||||
// case Intrinsic::tlvm_reshape_2d_1d: NumDim++; NumDim++; {
|
|
||||||
// size_t Current = 0;
|
|
||||||
// for(unsigned K = 0; K < NumDim; K++){
|
|
||||||
// if(Call->getOperand(1 + K) == _1)
|
|
||||||
// addConstraint({Call, K}, {_1, 0}, Layout);
|
|
||||||
// else
|
|
||||||
// addConstraint({Call, K}, {Call->getOperand(0), Current++}, Layout);
|
|
||||||
// }
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// // Broadcast
|
|
||||||
// case Intrinsic::tlvm_broadcast_2d: NumDim++; LLVM_FALLTHROUGH;
|
|
||||||
// case Intrinsic::tlvm_broadcast_1d: NumDim++; {
|
|
||||||
// for(unsigned K = 0; K < NumDim; K++)
|
|
||||||
// addConstraint({Call, K}, {Call->getOperand(1 + K), 0}, Shape);
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// // Splat
|
|
||||||
// case Intrinsic::tlvm_splat_2d: NumDim++; LLVM_FALLTHROUGH;
|
|
||||||
// case Intrinsic::tlvm_splat_1d: NumDim++; {
|
|
||||||
// for(unsigned K = 0; K < NumDim; K++)
|
|
||||||
// addConstraint({Call, K}, {Call->getOperand(K), 0}, Shape);
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// case Intrinsic::tlvm_load:{
|
|
||||||
// NumDim = Call->getType()->getTileNumDimensions();
|
|
||||||
// Value *Ptr = Call->getOperand(0);
|
|
||||||
// for(unsigned K = 0; K < NumDim; K++)
|
|
||||||
// addConstraint({Call, K}, {Ptr, K}, Layout);
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // Masked Load
|
|
||||||
// case Intrinsic::tlvm_masked_load: {
|
|
||||||
// NumDim = Call->getType()->getTileNumDimensions();
|
|
||||||
// for(unsigned K = 0; K < NumDim; K++){
|
|
||||||
// addConstraint({Call, K}, {Call->getOperand(0), K}, Layout);
|
|
||||||
// addConstraint({Call, K}, {Call->getOperand(1), K}, Layout);
|
|
||||||
// }
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// // Masked store
|
|
||||||
// case Intrinsic::tlvm_atomic_load_add_f32: LLVM_FALLTHROUGH;
|
|
||||||
// case Intrinsic::tlvm_masked_store: {
|
|
||||||
// Value *Val = Call->getOperand(0);
|
|
||||||
// Value *Ptr = Call->getOperand(1);
|
|
||||||
// Value *Mask = Call->getOperand(2);
|
|
||||||
// NumDim = Val->getType()->getTileNumDimensions();
|
|
||||||
// for(unsigned K = 0; K < NumDim; K++){
|
|
||||||
// addConstraint({Val, K}, {Ptr, K}, Layout);
|
|
||||||
// addConstraint({Val, K}, {Mask, K}, Layout);
|
|
||||||
// }
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// // Set Mask
|
|
||||||
// case Intrinsic::tlvm_set_mask_2d: NumDim++; NumDim++; {
|
|
||||||
// for(unsigned K = 0; K < NumDim; K++){
|
|
||||||
// Value *Op = Call->getOperand(NumDim + K);
|
|
||||||
// addConstraint({Call, K}, {Op, 0}, Layout);
|
|
||||||
// }
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// // MMA
|
|
||||||
// // A shares first axis with C
|
|
||||||
// // B shares last axis with C
|
|
||||||
// case Intrinsic::tlvm_mma_nn:
|
|
||||||
// case Intrinsic::tlvm_mma_nt:
|
|
||||||
// case Intrinsic::tlvm_mma_tn:
|
|
||||||
// case Intrinsic::tlvm_mma_tt:{
|
|
||||||
// bool AT = IntrinsicID == Intrinsic::tlvm_mma_tn || IntrinsicID == Intrinsic::tlvm_mma_tt;
|
|
||||||
// bool BT = IntrinsicID == Intrinsic::tlvm_mma_nt || IntrinsicID == Intrinsic::tlvm_mma_tt;
|
|
||||||
// Value *A = Call->getOperand(0);
|
|
||||||
// Value *B = Call->getOperand(1);
|
|
||||||
// Value *D = Call->getOperand(2);
|
|
||||||
// size_t AOuter = 0, AInner = 1;
|
|
||||||
// size_t BOuter = 1, BInner = 0;
|
|
||||||
// if(AT) std::swap(AOuter, AInner);
|
|
||||||
// if(BT) std::swap(BOuter, BInner);
|
|
||||||
// addConstraint({Call, 0}, {A, AOuter}, Shape);
|
|
||||||
// addConstraint({Call, 1}, {B, BOuter}, Shape);
|
|
||||||
// addConstraint({A, AInner}, {B, BInner}, Shape);
|
|
||||||
// addConstraint({Call, 0}, {D, 0}, Layout);
|
|
||||||
// addConstraint({Call, 1}, {D, 1}, Layout);
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// default:
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// // LoadInst: Pointer shares the result layout
|
|
||||||
// if(LoadInst *Load = dyn_cast<LoadInst>(I)){
|
|
||||||
// NumDim = Load->getType()->getTileNumDimensions();
|
|
||||||
// Value *Ptr = Load->getPointerOperand();
|
|
||||||
// for(unsigned K = 0; K < NumDim; K++)
|
|
||||||
// addConstraint({Load, K}, {Ptr, K}, Layout);
|
|
||||||
// }
|
|
||||||
// // StoreInst: Pointer shares the value layout
|
|
||||||
// if(StoreInst *Store = dyn_cast<StoreInst>(I)){
|
|
||||||
// Value *Ptr = Store->getPointerOperand();
|
|
||||||
// Value *Val = Store->getValueOperand();
|
|
||||||
// NumDim = Val->getType()->getTileNumDimensions();
|
|
||||||
// for(unsigned K = 0; K < NumDim; K++)
|
|
||||||
// addConstraint({Ptr, K}, {Val, K}, Layout);
|
|
||||||
// }
|
|
||||||
// // SelectInst: Selected tensor share layout
|
|
||||||
// if(SelectInst *Select = dyn_cast<SelectInst>(I)){
|
|
||||||
// NumDim = Select->getType()->getTileNumDimensions();
|
|
||||||
// for(unsigned K = 0; K < NumDim; K++){
|
|
||||||
// addConstraint({Select->getTrueValue(), K}, {Select, K}, Layout);
|
|
||||||
// addConstraint({Select->getFalseValue(), K}, {Select, K}, Layout);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// if(isa<CastInst>(I)){
|
|
||||||
// NumDim = I->getType()->getTileNumDimensions();
|
|
||||||
// for(unsigned K = 0; K < NumDim; K++){
|
|
||||||
// addConstraint({I->getOperand(0), K}, {I, K}, Layout);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// // Phi Nodes: all the incoming value share the result layout
|
|
||||||
// if(PHINode *Phi = dyn_cast<PHINode>(I)){
|
|
||||||
// Type *Ty = Phi->getType();
|
|
||||||
// NumDim = Ty->getTileNumDimensions();
|
|
||||||
// unsigned NumInc = Phi->getNumIncomingValues();
|
|
||||||
// for(unsigned PI = 0; PI < NumInc; PI++){
|
|
||||||
// Value *Inc = Phi->getIncomingValue(PI);
|
|
||||||
// for(unsigned K = 0; K < NumDim; K++){
|
|
||||||
// CType CT = (LCGraph.find({Inc,K}) != LCGraph.end() ||
|
|
||||||
// LCGraph.find({Phi,K}) != LCGraph.end())?Layout:Shape;
|
|
||||||
// addConstraint({Phi, K}, {Inc, K}, CT);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// // Binary op: All the arguments share the result layout
|
|
||||||
// Instruction *BinOp = static_cast<Instruction*>(I);
|
|
||||||
// if(isa<BinaryOperator>(BinOp) || isa<CmpInst>(BinOp)){
|
|
||||||
// NumDim = BinOp->getType()->getTileNumDimensions();
|
|
||||||
// Value *A = BinOp->getOperand(0);
|
|
||||||
// Value *B = BinOp->getOperand(1);
|
|
||||||
// for(unsigned K = 0; K < NumDim; K++){
|
|
||||||
// addConstraint({BinOp, K}, {A, K}, Layout);
|
|
||||||
// addConstraint({BinOp, K}, {B, K}, Layout);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
//void TLVMAddTunerParams::connectedComponents(CNodeType X, ArrayRef<llvm::MDNode*> Vals, CType CT,
|
|
||||||
// DenseSet<CNodeType> &Nodes, CGraphType &Graph){
|
|
||||||
// if(Nodes.find(X) != Nodes.end()){
|
|
||||||
// Nodes.erase(X);
|
|
||||||
// std::string Suffix = ".d" + itostr(X.second);
|
|
||||||
// if(Instruction *Instr = dyn_cast<Instruction>(X.first)){
|
|
||||||
// if(CT==Shape){
|
|
||||||
// Instr->setMetadata("nvvm.param.shape" + Suffix, Vals[0]);
|
|
||||||
// }
|
|
||||||
// if(CT==Layout){
|
|
||||||
// Instr->setMetadata("nvvm.param.layout.p0" + Suffix, Vals[0]);
|
|
||||||
// Instr->setMetadata("nvvm.param.layout.p1" + Suffix, Vals[1]);
|
|
||||||
// Instr->setMetadata("nvvm.param.layout.p2" + Suffix, Vals[2]);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// if(ConstantInt *Cst = dyn_cast<ConstantInt>(X.first)){
|
|
||||||
// Metadata *CstMD = ConstantAsMetadata::get(Cst);
|
|
||||||
// if(CT==Shape){
|
|
||||||
// Vals[0]->replaceOperandWith(0, CstMD);
|
|
||||||
// }
|
|
||||||
// if(CT==Layout){
|
|
||||||
// Vals[0]->replaceOperandWith(0, CstMD);
|
|
||||||
// Vals[1]->replaceOperandWith(0, CstMD);
|
|
||||||
// Vals[2]->replaceOperandWith(0, CstMD);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// for(CNodeType &E: Graph[X])
|
|
||||||
// connectedComponents(E, Vals, CT, Nodes, Graph);
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
//// Run
|
|
||||||
//bool TLVMAddTunerParams::runOnFunction(Function &F) {
|
|
||||||
// // Build constraints graph
|
|
||||||
// for(Function::iterator::value_type &BB: F)
|
|
||||||
// for(BasicBlock::iterator::value_type &I : BB)
|
|
||||||
// if(isTLVMValue(&I))
|
|
||||||
// initCGraph(&I);
|
|
||||||
// for(Function::iterator::value_type &BB: F)
|
|
||||||
// for(BasicBlock::iterator::value_type &I : BB)
|
|
||||||
// if(isTLVMValue(&I))
|
|
||||||
// initCPhi(&I);
|
|
||||||
// // Add parameters
|
|
||||||
// LLVMContext &Ctx = F.getContext();
|
|
||||||
// Metadata *UndefMD = ConstantAsMetadata::get(UndefValue::get(Type::getInt32Ty(Ctx)));
|
|
||||||
// // Shape parameters
|
|
||||||
// while(!SCNodes.empty()){
|
|
||||||
// MDNode *V0 = MDNode::getTemporary(Ctx, UndefMD).release();
|
|
||||||
// connectedComponents(*SCNodes.begin(), {V0}, Shape, SCNodes, SCGraph);
|
|
||||||
// }
|
|
||||||
// // Layout parameters
|
|
||||||
// while(!LCNodes.empty()){
|
|
||||||
// MDNode *V0 = MDNode::getTemporary(Ctx, UndefMD).release();
|
|
||||||
// MDNode *V1 = MDNode::getTemporary(Ctx, UndefMD).release();
|
|
||||||
// MDNode *V2 = MDNode::getTemporary(Ctx, UndefMD).release();
|
|
||||||
// connectedComponents(*LCNodes.begin(), {V0, V1, V2}, Layout, LCNodes, LCGraph);
|
|
||||||
// }
|
|
||||||
// return true;
|
|
||||||
//}
|
|
||||||
|
|
||||||
//}
|
|
||||||
//}
|
|
||||||
|
@@ -18,9 +18,26 @@ type *type::get_scalar_ty() const {
|
|||||||
return const_cast<type*>(this);
|
return const_cast<type*>(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned type::get_primitive_size_in_bits() const {
|
||||||
|
switch (id_) {
|
||||||
|
case HalfTyID: return 16;
|
||||||
|
case FloatTyID: return 32;
|
||||||
|
case DoubleTyID: return 64;
|
||||||
|
case X86_FP80TyID: return 80;
|
||||||
|
case FP128TyID: return 128;
|
||||||
|
case PPC_FP128TyID: return 128;
|
||||||
|
case IntegerTyID: return ((integer_type*)(this))->get_bitwidth();
|
||||||
|
case TileTyID: return ((tile_type*)(this))->get_bitwidth();
|
||||||
|
default: return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
unsigned type::get_integer_bitwidth() const
|
unsigned type::get_integer_bitwidth() const
|
||||||
{ return ((integer_type*)(this))->get_bitwidth(); }
|
{ return ((integer_type*)(this))->get_bitwidth(); }
|
||||||
|
|
||||||
|
unsigned type::get_tile_bitwidth() const
|
||||||
|
{ return ((tile_type*)(this))->get_bitwidth(); }
|
||||||
|
|
||||||
unsigned type::get_fp_mantissa_width() const {
|
unsigned type::get_fp_mantissa_width() const {
|
||||||
id_t id = get_scalar_ty()->id_;
|
id_t id = get_scalar_ty()->id_;
|
||||||
assert(is_floating_point_ty() && "Not a floating point type!");
|
assert(is_floating_point_ty() && "Not a floating point type!");
|
||||||
@@ -140,6 +157,17 @@ bool tile_type::is_valid_elt_ty(type *ty) {
|
|||||||
return ty->is_pointer_ty() || ty->is_floating_point_ty() || ty->is_integer_ty();
|
return ty->is_pointer_ty() || ty->is_floating_point_ty() || ty->is_integer_ty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned tile_type::get_num_elements() const {
|
||||||
|
unsigned res = 1;
|
||||||
|
for(unsigned shape: shapes_)
|
||||||
|
shape *= res;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned tile_type::get_bitwidth() const {
|
||||||
|
return get_num_elements() * get_tile_element_ty()->get_primitive_size_in_bits();
|
||||||
|
}
|
||||||
|
|
||||||
tile_type* tile_type::get(type *elt_ty, const std::vector<unsigned> &shapes) {
|
tile_type* tile_type::get(type *elt_ty, const std::vector<unsigned> &shapes) {
|
||||||
assert(elt_ty && "Can't get a tile of <null> type!");
|
assert(elt_ty && "Can't get a tile of <null> type!");
|
||||||
assert(shapes.size() && "Can't create a tile with empty shapes!");
|
assert(shapes.size() && "Can't create a tile with empty shapes!");
|
||||||
|
Reference in New Issue
Block a user