From 342af96cd123860b3fbe0fe9b0669627cefca1cc Mon Sep 17 00:00:00 2001 From: Tuowen Zhao Date: Mon, 3 Oct 2016 14:39:24 -0600 Subject: doc --- CMakeLists.txt | 2 +- include/dep.hh | 19 +- include/ir_code.hh | 124 +++--- include/irtools.hh | 57 ++- include/loop.hh | 109 ++++-- lib/codegen/include/code_gen/CG.h | 8 - lib/codegen/include/code_gen/CG_outputBuilder.h | 500 +++++++++++++++--------- lib/codegen/include/code_gen/CG_outputRepr.h | 6 +- src/irtools.cc | 8 +- src/transformations/loop.cc | 5 +- 10 files changed, 538 insertions(+), 300 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5c6226a..e7e8822 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -67,7 +67,7 @@ set(clang_libs set(COMMON_FLAGS "-DCHILL_BUILD_DATE=\"${build_date}\" -DCHILL_BUILD_VERSION=\"\\\"${CHILL_VERSION}\\\"\"") -set(CMAKE_CXX_FLAGS "-std=c++11 ${COMMON_FLAGS} ${CMAKE_CXX_FLAGS}") +set(CMAKE_CXX_FLAGS "-std=gnu++11 ${COMMON_FLAGS} ${CMAKE_CXX_FLAGS}") if (DEFINED OMEGAHOME) link_directories(${OMEGAHOME}/lib) diff --git a/include/dep.hh b/include/dep.hh index ffd2db5..035d382 100644 --- a/include/dep.hh +++ b/include/dep.hh @@ -6,6 +6,19 @@ #include "ir_code.hh" #include "chill_error.hh" +/*! + * \file + * \brief Data dependence vector and graph. + * + * All dependence vectors are normalized, i.e., the first non-zero distance + * must be positve. Thus the correct dependence meaning can be given based on + * source/destination pair's read/write type. Suppose for a dependence vector + * 1, 0~5, -3), we want to permute the first and the second dimension, + * the result would be two dependence vectors (0, 1, -3) and (1~5, 1, -3). + * All operations on dependence vectors are non-destructive, i.e., new + * dependence vectors are returned. + */ + enum DependenceType { DEP_W2R, DEP_R2W, DEP_W2W, DEP_R2R, DEP_CONTROL, DEP_UNKNOWN }; @@ -21,8 +34,8 @@ struct DependenceVector { bool from_same_stmt; // Manu bool is_reduction_cand; // Manu - bool is_reduction; // used to identify a class of flow dependence - // that can be broken + bool is_reduction; //!< used to identify a class of flow dependencies that can be broken + std::vector lbounds; std::vector ubounds; @@ -54,7 +67,7 @@ struct DependenceVector { bool has_been_carried_before(int dim) const; - // the following functions will be cleaned up or removed later + // TODO the following functions will be cleaned up or removed later bool isZero() const; bool isPositive() const; diff --git a/include/ir_code.hh b/include/ir_code.hh index 8de0f01..b56ce41 100644 --- a/include/ir_code.hh +++ b/include/ir_code.hh @@ -23,40 +23,48 @@ #define IR_CODE_HH #include - #include - #include - -// needed for omega::coef_t below -#include // in omega ... why is this not in CG_output*.h? - #include #include +/*! + * \file + * \brief CHiLL's compiler intermediate representation interface that extends Omega's builder interface to accomodate compiler analyses and extra code generation. + * + * Unlike CG_outputRepr, IR_Symbol,IR_Ref and IR_Control are place holders + * to the underlying code, thus deleting or duplicating them does not affect + * the actual code. Similar to Omega builder's memory allocation strategy, + * all non-const pointer parameters of CG_outputRepr/IR_Symbol/IR_Ref/IR_Control + * are destroyed after the call. + */ class IR_Code; // forward declaration - -// Base abstract class for scalar and array symbols. This is a place -// holder for related declaration in IR code. +/*! + * @brief Base abstract class for scalar and array symbols. + * + * This is a place holder for related declaration in IR code. + */ struct IR_Symbol { const IR_Code *ir_; - virtual ~IR_Symbol() {/* ir_ is not the responsibility of this object */} + //! ir_ is not the responsibility of this object + virtual ~IR_Symbol() { } - virtual int n_dim() const = 0; // IR_Symbol + virtual int n_dim() const = 0; virtual std::string name() const = 0; virtual bool operator==(const IR_Symbol &that) const = 0; virtual bool operator!=(const IR_Symbol &that) const { return !(*this == that); } - virtual IR_Symbol *clone() const = 0; /* shallow copy */ + //! shallow copy + virtual IR_Symbol *clone() const = 0; - virtual bool isScalar() const { return false; } // default - virtual bool isArray() const { return false; } // default - virtual bool isPointer() const { return false; } // default + virtual bool isScalar() const { return false; } + virtual bool isArray() const { return false; } + virtual bool isPointer() const { return false; } //IR_SYMBOL_TYPE symtype; // base type: int, float, double, struct, .... typedef'd something //IR_SYMBOL_TYPE getDatatype() ; @@ -87,7 +95,6 @@ struct IR_ArraySymbol : public IR_Symbol { bool isArray() const { return true; } }; - struct IR_PointerSymbol : public IR_Symbol { virtual ~IR_PointerSymbol() {} @@ -100,14 +107,18 @@ struct IR_PointerSymbol : public IR_Symbol { bool isPointer() const { return true; } }; -// Base abstract class for scalar and array references. This is a -// place holder for related code in IR code. + +/*! + * @brief Base abstract class for scalar and array references. + * + * This is a place holder for related code in IR code. + */ struct IR_Ref { const IR_Code *ir_; + //! ir_ is not the responsibility of this object + virtual ~IR_Ref() { } - virtual ~IR_Ref() {/* ir_ is not the responsibility of this object */} - - virtual int n_dim() const = 0; // IR_Ref + virtual int n_dim() const = 0; virtual bool is_write() const = 0; virtual std::string name() const = 0; @@ -118,7 +129,8 @@ struct IR_Ref { virtual omega::CG_outputRepr *convert() = 0; - virtual IR_Ref *clone() const = 0; /* shallow copy */ + //! shallow copy + virtual IR_Ref *clone() const = 0; virtual void Dump() const { fprintf(stderr, "some IR_*Ref needs to implement Dump()\n"); int *i = 0; @@ -236,15 +248,17 @@ struct IR_PointerArrayRef : public IR_Ref { struct IR_Block; -// Base abstract class for code structures. This is a place holder -// for the actual structure in the IR code. However, in cases that -// original source code may be transformed during loop initialization -// such as converting a while loop to a for loop or reconstructing the -// loop from low level IR code, the helper loop class (NOT -// IMPLEMENTED) must contain the transformed code that needs to be -// freed when out of service. +//! Base abstract class for code structures. +/*! + * This is a place holder for the actual structure in the IR code. + * However, in cases that original source code may be transformed during + * loop initialization such as converting a while loop to a for loop or + * reconstructing the loop from low level IR code, the helper loop class (NOT + * IMPLEMENTED) must contain the transformed code that needs to be + * freed when out of service. + */ struct IR_Control { - const IR_Code *ir_; // hate this + const IR_Code *ir_; virtual ~IR_Control() {/* ir_ is not the responsibility of this object */} @@ -306,16 +320,14 @@ struct IR_While : public IR_Control { }; -// Abstract class for compiler IR. // TODO made a lot of definition to pass instantiation for IR_clangCode +//! Abstract class for compiler IR. class IR_Code { protected: - // the only data members in IR_Code are Omega classes - omega::CG_outputBuilder *ocg_; // Omega Code Gen + omega::CG_outputBuilder *ocg_; omega::CG_outputRepr *init_code_; omega::CG_outputRepr *cleanup_code_; - // OK, I lied static int ir_pointer_counter; static int ir_array_counter; @@ -338,8 +350,7 @@ public: return ir_array_counter - 1; } - // if all flavors of ir_code use chillAST internally ... - chillAST_FunctionDecl *func_defn; // the function we're modifying + chillAST_FunctionDecl *func_defn; //!< the function we're modifying chillAST_FunctionDecl *GetChillFuncDefinition() { return func_defn; }; IR_Code() { @@ -355,8 +366,11 @@ public: omega::CG_outputRepr *init_code() { return init_code_; } - // memory_type is for differentiating the location of where the new memory is allocated. - // this is useful for processors with heterogeneous memory hierarchy. + /*! + * \param memory_type is for differentiating the location of + * where the new memory is allocated. this is useful for + * processors with heterogeneous memory hierarchy. + */ virtual IR_ScalarSymbol *CreateScalarSymbol(const IR_Symbol *sym, int memory_type) = 0; virtual IR_ScalarSymbol *CreateScalarSymbol(IR_CONSTANT_TYPE type, int memory_type, std::string name = "") { @@ -441,11 +455,15 @@ public: CHILL_ERROR("NOT IMPLEMENTED\n"); return NULL; } - - // Array references should be returned in their accessing order. - // e.g. s1: A[i] = A[i-1] - // s2: B[C[i]] = D[i] + E[i] - // return A[i-1], A[i], D[i], E[i], C[i], B[C[i]] in this order. + /*! + * Array references should be returned in their accessing order. + * + * ~~~ + * e.g. s1: A[i] = A[i-1] + * s2: B[C[i]] = D[i] + E[i] + * return A[i-1], A[i], D[i], E[i], C[i], B[C[i]] in this order. + * ~~~ + */ virtual std::vector FindArrayRef(const omega::CG_outputRepr *repr) const = 0; virtual std::vector FindPointerArrayRef(const omega::CG_outputRepr *repr) const { @@ -461,13 +479,15 @@ public: CHILL_ERROR("NOT IMPLEMENTED\n"); return false; } - - // If there is no sub structure interesting inside the block, return empty, - // so we know when to stop looking inside. + /*! + * If there is no sub structure interesting inside the block, return empty, + * so we know when to stop looking inside. + */ virtual std::vector FindOneLevelControlStructure(const IR_Block *block) const = 0; - - // All controls must be in the same block, at the same level and in - // contiguous lexical order as appeared in parameter vector. + /*! + * All controls must be in the same block, at the same level and in + * contiguous lexical order as appeared in parameter vector. + */ virtual IR_Block *MergeNeighboringControlStructures(const std::vector &controls) const = 0; virtual IR_Block *GetCode() const = 0; @@ -552,11 +572,7 @@ public: return NULL; } - //void Dump() { ocg_->Dump(); }; - //--------------------------------------------------------------------------- - // CC Omega code builder interface here - - //--------------------------------------------------------------------------- + //! Codegen Omega code builder interface omega::CG_outputBuilder *builder() const { return ocg_; } }; diff --git a/include/irtools.hh b/include/irtools.hh index c4a78ed..66b3144 100644 --- a/include/irtools.hh +++ b/include/irtools.hh @@ -9,15 +9,23 @@ #define DEP_DEBUG 0 -// IR tree is used to initialize a loop. For a loop node, payload is -// its mapped iteration space dimension. For a simple block node, -// payload is its mapped statement number. Normal if-else is split -// into two nodes where the one with odd payload represents then-part and -// the one with even payload represents else-part. +/*! + * \file + * \brief Useful tools to analyze code in compiler IR format. + */ + +//! It is used to initialize a loop. struct ir_tree_node { IR_Control *content; ir_tree_node *parent; std::vector children; + /*! + * * For a loop node, payload is its mapped iteration space dimension. + * * For a simple block node, payload is its mapped statement number. + * * Normal if-else is splitted into two nodes + * * the one with odd payload represents then-part and + * * the one with even payload represents else-part. + */ int payload; ~ir_tree_node() { @@ -26,16 +34,49 @@ struct ir_tree_node { delete content; } }; - +/*! + * @brief Build IR tree from the source code + * + * Block type node can only be leaf, i.e., there is no further stuctures inside a block allowed + * + * @param control + * @param parent + * @return + */ std::vector build_ir_tree(IR_Control *control, ir_tree_node *parent = NULL); - +/*! + * @brief Extract statements from IR tree + * + * Statements returned are ordered in lexical order in the source code + * + * @param ir_tree + * @return + */ std::vector extract_ir_stmts( const std::vector &ir_tree); bool is_dependence_valid(ir_tree_node *src_node, ir_tree_node *dst_node, const DependenceVector &dv, bool before); - +/*! + * @brief test data dependeces between two statements + * + * The first statement in parameter must be lexically before the second statement in parameter. + * Returned dependences are all lexicographically positive + * + * @param ir + * @param repr1 + * @param IS1 + * @param repr2 + * @param IS2 + * @param freevar + * @param index + * @param i + * @param j + * @param uninterpreted_symbols + * @param uninterpreted_symbols_stringrepr + * @return + */ std::pair, std::vector > test_data_dependences( IR_Code *ir, const omega::CG_outputRepr *repr1, const omega::Relation &IS1, const omega::CG_outputRepr *repr2, diff --git a/include/loop.hh b/include/loop.hh index 554b005..7c746f6 100644 --- a/include/loop.hh +++ b/include/loop.hh @@ -15,24 +15,44 @@ #include "stencil.hh" +/*! + * \file + * \brief Core loop transformation functionality. + * + * "level" (starting from 1) means loop level and it corresponds to "dim" + * (starting from 0) in transformed iteration space [c_1,l_1,c_2,l_2,...., + * c_n,l_n,c_(n+1)], e.g., l_2 is loop level 2 in generated code, dim 3 + * in transformed iteration space, and variable 4 in Omega relation. + * All c's are constant numbers only and they will not show up as actual loops. + * + * Formula: + * + * ~~~ + * dim = 2*level - 1 + * var = dim + 1 + * ~~~ + */ class IR_Code; enum TilingMethodType { StridedTile, CountedTile }; enum LoopLevelType { LoopLevelOriginal, LoopLevelTile, LoopLevelUnknown }; - -// Describes properties of each loop level of a statement. "payload" -// for LoopLevelOriginal means iteration space dimension, for -// LoopLevelTile means tiled loop level. Special value -1 for -// LoopLevelTile means purely derived loop. For dependence dimension -// payloads, the values must be in an increasing order. -// "parallel_level" will be used by code generation to support -// multi-level parallelization (default 0 means sequential loop under -// the current parallelization level). +//! Describes properties of each loop level of a statement. struct LoopLevel { LoopLevelType type; - int payload; + /*! + * For LoopLevelOriginal means iteration space dimension + * For LoopLevelTile means tiled loop level. Special value -1 for + * LoopLevelTile means purely derived loop. For dependence dimension + * payloads, the values must be in an increasing order. + */ + int payload; + /*! + * Used by code generation to support + * multi-level parallelization (default 0 means sequential loop under + * the current parallelization level). + */ int parallel_level; bool segreducible; std::string segment_descriptor; @@ -46,14 +66,15 @@ struct Statement { std::vector loop_level; ir_tree_node *ir_stmt_node; bool has_inspector; - int reduction; // Manu:: 0 == reduction not possible, 1 == reduction possible, 2 == reduction with some processing + /*! + * @brief Whether reduction is possible + * + * 0 == reduction not possible, 1 == reduction possible, 2 == reduction with some processing + */ + int reduction; IR_OPERATION_TYPE reductionOp; // Manu class stencilInfo *statementStencil; - - //protonu--temporarily putting this back here - //omega::Tuple nonSplitLevels; - //end--protonu. }; @@ -118,7 +139,6 @@ public: ~Loop(); omega::CG_outputRepr *getCode(int effort = 1) const; // TODO was 1 - //chillAST_Node* getCode(int effort, std::set stmts) const; void stencilASEPadded(int stmt_num); @@ -133,15 +153,12 @@ public: void dump() const; std::vector > sort_by_same_loops(std::set active, int level); - // - // legacy unimodular transformations for perfectly nested loops - // e.g. M*(i,j)^T = (i',j')^T or M*(i,j,1)^T = (i',j')^T - // + //! legacy unimodular transformations for perfectly nested loops + /*! + * e.g. \f$M*(i,j)^T = (i',j')^T or M*(i,j,1)^T = (i',j')^T\f$ + */ bool nonsingular(const std::vector > &M); - // - // high-level loop transformations - // void permute(const std::set &active, const std::vector &pi); void permute(int stmt_num, int level, const std::vector &pi); void permute(const std::vector &pi); @@ -150,14 +167,43 @@ public: void tile(int stmt_num, int level, int tile_size, int outer_level = 1, TilingMethodType method = StridedTile, int alignment_offset = 0, int alignment_multiple = 1); std::set split(int stmt_num, int level, const omega::Relation &cond); std::set unroll(int stmt_num, int level, int unroll_amount, std::vector< std::vector >idxNames= std::vector< std::vector >(), int cleanup_split_level = 0); - + + //! Datacopy function by reffering arrays by numbers + /*! + * for example + * ~~~ + * A[i] = A[i-1] + B[i]; + * ~~~ + * parameter array_ref_num=[0,2] means to copy data touched by A[i-1] and A[i] + * + * @param array_ref_nums + * @param level + * @param allow_extra_read + * @param fastest_changing_dimension + * @param padding_stride + * @param padding_alignment + * @param memory_type + * @return + */ bool datacopy(const std::vector > > &array_ref_nums, int level, bool allow_extra_read = false, int fastest_changing_dimension = -1, int padding_stride = 1, int padding_alignment = 4, int memory_type = 0); + //! Datacopy function by reffering arrays by name + /*! + * parameter array_name=A means to copy data touched by A[i-1] and A[i] + * @param stmt_num + * @param level + * @param array_name + * @param allow_extra_read + * @param fastest_changing_dimension + * @param padding_stride + * @param padding_alignment + * @param memory_type + * @return + */ bool datacopy(int stmt_num, int level, const std::string &array_name, bool allow_extra_read = false, int fastest_changing_dimension = -1, int padding_stride = 1, int padding_alignment = 4, int memory_type = 0); bool datacopy_privatized(int stmt_num, int level, const std::string &array_name, const std::vector &privatized_levels, bool allow_extra_read = false, int fastest_changing_dimension = -1, int padding_stride = 1, int padding_alignment = 1, int memory_type = 0); bool datacopy_privatized(const std::vector > > &array_ref_nums, int level, const std::vector &privatized_levels, bool allow_extra_read = false, int fastest_changing_dimension = -1, int padding_stride = 1, int padding_alignment = 1, int memory_type = 0); bool datacopy_privatized(const std::vector > > &stmt_refs, int level, const std::vector &privatized_levels, bool allow_extra_read, int fastest_changing_dimension, int padding_stride, int padding_alignment, int memory_type = 0); - //std::set scalar_replacement_inner(int stmt_num); - bool find_stencil_shape( int stmt_num ); + bool find_stencil_shape( int stmt_num ); Graph, bool> construct_induced_graph_at_level(std::vector > s, DependenceGraph dep, int dep_dim); @@ -170,9 +216,6 @@ public: void scale(const std::set &stmt_nums, int level, int scale_amount); void reverse(const std::set &stmt_nums, int level); void peel(int stmt_num, int level, int peel_amount = 1); - // - // more fancy loop transformations - // void modular_shift(int stmt_num, int level, int shift_amount) {} void diagonal_map(int stmt_num, const std::pair &levels, int offset) {} void modular_partition(int stmt_num, int level, int stride) {} @@ -183,9 +226,6 @@ public: - // - // derived loop transformations - // void shift_to(int stmt_num, int level, int absolute_position); std::set unroll_extra(int stmt_num, int level, int unroll_amount, int cleanup_split_level = 0); bool is_dependence_valid_based_on_lex_order(int i, int j, @@ -193,7 +233,6 @@ public: void split_with_alignment(int stmt_num, int level, int alignment, int direction=0); - // Manu:: reduction operation void reduce(int stmt_num, std::vector &level, int param, std::string func_name, std::vector &seq_levels, std::vector cudaized_levels = std::vector(), int bound_level = -1); void scalar_expand(int stmt_num, const std::vector &levels, std::string arrName, int memory_type =0, int padding_alignment=0, int assign_then_accumulate = 1, int padding_stride = 0); void ELLify(int stmt_num, std::vector arrays_to_pad, int pad_to, bool dense_pad = false, std::string dense_pad_pos_array = ""); @@ -203,11 +242,7 @@ public: void set_array_size(std::string name, int size ); omega::CG_outputRepr * iegen_parser(std::string &str, std::vector &index_names); - // - // other public operations - // void pragma(int stmt_num, int level, const std::string &pragmaText); void prefetch(int stmt_num, int level, const std::string &arrName, int hint); - //void prefetch(int stmt_num, int level, const std::string &arrName, const std::string &indexName, int offset, int hint); }; #endif diff --git a/lib/codegen/include/code_gen/CG.h b/lib/codegen/include/code_gen/CG.h index 4dd629c..3db3a7f 100644 --- a/lib/codegen/include/code_gen/CG.h +++ b/lib/codegen/include/code_gen/CG.h @@ -26,9 +26,6 @@ struct CG_result { CG_outputRepr *printRepr(CG_outputBuilder *ocg, const std::vector &stmts, std::vector > >uninterpreted_symbols, bool printString = false) const; std::string printString(std::vector > >uninterpreted_symbols = std::vector > >()) const; - //virtual CG_outputRepr *printRepr(int indent, CG_outputBuilder *ocg, const std::vector &stmts, const std::vector > &assigned_on_the_fly) const = 0; - //CG_outputRepr *printRepr(CG_outputBuilder *ocg, const std::vector &stmts) const; - //std::string printString() const; int num_level() const; virtual CG_result *clone() const = 0; virtual void dump(int indent) const {} @@ -57,7 +54,6 @@ struct CG_split: public CG_result { Relation hoistGuard(); void removeGuard(const Relation &guard); CG_outputRepr *printRepr(int indent, CG_outputBuilder *ocg, const std::vector &stmts, const std::vector > &assigned_on_the_fly, std::vector > > unin, bool printString=false) const; - // CG_outputRepr *printRepr(int indent, CG_outputBuilder *ocg, const std::vector &stmts, const std::vector > &assigned_on_the_fly) const; CG_result *clone() const; void dump(int indent) const; @@ -92,9 +88,6 @@ struct CG_loop: public CG_result { void removeGuard(const Relation &guard); CG_outputRepr *printRepr(int indent, CG_outputBuilder *ocg, const std::vector &stmts, const std::vector > &assigned_on_the_fly,std::vector > >unin, bool printString = false) const; CG_outputRepr *printRepr(bool do_print_guard, int indent, CG_outputBuilder *ocg, const std::vector &stmts, const std::vector > &assigned_on_the_fly, std::vector > > unin, bool printString = false) const; - - // CG_outputRepr *printRepr(int indent, CG_outputBuilder *ocg, const std::vector &stmts, const std::vector > &assigned_on_the_fly) const; - //CG_outputRepr *printRepr(bool do_print_guard, int indent, CG_outputBuilder *ocg, const std::vector &stmts, const std::vector > &assigned_on_the_fly) const; CG_result *clone() const; void dump(int indent) const; }; @@ -117,7 +110,6 @@ struct CG_leaf: public CG_result { Relation hoistGuard(); void removeGuard(const Relation &guard); CG_outputRepr *printRepr(int indent, CG_outputBuilder *ocg, const std::vector &stmts, const std::vector > &assigned_on_the_fly, std::vector > > unin, bool printString = false) const; - // CG_outputRepr *printRepr(int indent, CG_outputBuilder *ocg, const std::vector &stmts, const std::vector > &assigned_on_the_fly) const; CG_result *clone() const; void dump(int indent) const; }; diff --git a/lib/codegen/include/code_gen/CG_outputBuilder.h b/lib/codegen/include/code_gen/CG_outputBuilder.h index ce86c91..cb0cd5d 100644 --- a/lib/codegen/include/code_gen/CG_outputBuilder.h +++ b/lib/codegen/include/code_gen/CG_outputBuilder.h @@ -29,187 +29,327 @@ namespace omega { -class CG_outputBuilder { -private: - -public: - - CG_outputBuilder() {} - virtual ~CG_outputBuilder() {} - - - virtual CG_outputRepr *CreateStruct(const std::string class_name, - std::vector class_data_members, // why not just vector< CG_outputRepr> subparts; - std::vector class_data_types )=0; - virtual CG_outputRepr *CreateClassInstance(std::string name , CG_outputRepr *class_def)=0; - virtual CG_outputRepr *lookup_member_data(CG_outputRepr* scope, std::string varName, CG_outputRepr *instance)=0; - virtual CG_outputRepr* CreatePointer(std::string &name) const = 0; - virtual CG_outputRepr* ObtainInspectorRange(const std::string &_s, const std::string &_name) const=0; - - - - //--------------------------------------------------------------------------- - // substitute variables in stmt - //--------------------------------------------------------------------------- - virtual CG_outputRepr *CreateSubstitutedStmt(int indent, - CG_outputRepr *stmt, - const std::vector &vars, - std::vector &subs, - bool actuallyPrint =true) const = 0; - - //--------------------------------------------------------------------------- - // assignment stmt generation - //--------------------------------------------------------------------------- - virtual CG_outputRepr *CreateAssignment(int indent, - CG_outputRepr *lhs, - CG_outputRepr *rhs) const = 0; - - virtual CG_outputRepr *CreatePlusAssignment(int indent, - CG_outputRepr *lhs, - CG_outputRepr *rhs) const = 0; - - //--------------------------------------------------------------------------- - // function invocation generation - //--------------------------------------------------------------------------- - virtual CG_outputRepr *CreateInvoke(const std::string &funcName, - std::vector &argList, - bool is_array=false) const = 0; - - //--------------------------------------------------------------------------- - // comment generation - //--------------------------------------------------------------------------- - virtual CG_outputRepr *CreateComment(int indent, - const std::string &commentText) const = 0; - - //--------------------------------------------------------------------------- - // Attribute generation - //--------------------------------------------------------------------------- - virtual CG_outputRepr* CreateAttribute(CG_outputRepr *control, + //! abstract base class of compiler IR code builder + class CG_outputBuilder { + private: + + public: + + CG_outputBuilder() {} + + virtual ~CG_outputBuilder() {} + + virtual CG_outputRepr *CreateStruct(const std::string class_name, + std::vector class_data_members, // why not just vector< CG_outputRepr> subparts; + std::vector class_data_types)=0; + + virtual CG_outputRepr *CreateClassInstance(std::string name, CG_outputRepr *class_def)=0; + + virtual CG_outputRepr *lookup_member_data(CG_outputRepr *scope, std::string varName, CG_outputRepr *instance)=0; + + virtual CG_outputRepr *CreatePointer(std::string &name) const = 0; + + virtual CG_outputRepr *ObtainInspectorRange(const std::string &_s, const std::string &_name) const =0; + + /*! + * \brief substitute variable in stmt + * + * @param indent + * @param stmt + * @param vars + * @param subs + * @param actuallyPrint + * @return + */ + virtual CG_outputRepr *CreateSubstitutedStmt(int indent, + CG_outputRepr *stmt, + const std::vector &vars, + std::vector &subs, + bool actuallyPrint = true) const = 0; + + /*! + * @brief assignment stmt generation + * @param indent + * @param lhs + * @param rhs + * @return + */ + virtual CG_outputRepr *CreateAssignment(int indent, + CG_outputRepr *lhs, + CG_outputRepr *rhs) const = 0; + /*! + * @brief Plus assignment stmt generation + * @param indent + * @param lhs + * @param rhs + * @return CG_outputRepr + */ + virtual CG_outputRepr *CreatePlusAssignment(int indent, + CG_outputRepr *lhs, + CG_outputRepr *rhs) const = 0; + /*! + * @brief function invoation generation + * @param funcName + * @param argList + * @param is_array + * @return + */ + virtual CG_outputRepr *CreateInvoke(const std::string &funcName, + std::vector &argList, + bool is_array = false) const = 0; + /*! + * @brief comment generation + * @param indent + * @param commentText + * @return + */ + virtual CG_outputRepr *CreateComment(int indent, + const std::string &commentText) const = 0; + /*! + * @brief Attribute Generation + * @param control + * @param commentText + * @return + */ + virtual CG_outputRepr *CreateAttribute(CG_outputRepr *control, const std::string &commentText) const = 0; - //--------------------------------------------------------------------------- - // Pragma Attribute - // -------------------------------------------------------------------------- - virtual CG_outputRepr* CreatePragmaAttribute(CG_outputRepr *scopeStmt, int looplevel, const std::string &pragmaText) const = 0; - - //--------------------------------------------------------------------------- - // Prefetch Attribute - //--------------------------------------------------------------------------- - virtual CG_outputRepr* CreatePrefetchAttribute(CG_outputRepr *scopeStmt, int looplevel, const std::string &arrName, int hint) const = 0; - - //--------------------------------------------------------------------------- - // generate if stmt, true/false stmt can be NULL but not the condition - //--------------------------------------------------------------------------- - virtual CG_outputRepr *CreateIf(int indent, CG_outputRepr *guardCondition, - CG_outputRepr *true_stmtList, - CG_outputRepr *false_stmtList) const = 0; - - //--------------------------------------------------------------------------- - // generate loop inductive variable (loop control structure) - //--------------------------------------------------------------------------- - virtual CG_outputRepr *CreateInductive(CG_outputRepr *index, - CG_outputRepr *lower, - CG_outputRepr *upper, - CG_outputRepr *step) const = 0; - - //--------------------------------------------------------------------------- - // generate loop stmt from loop control and loop body, NULL parameter allowed - //--------------------------------------------------------------------------- - virtual CG_outputRepr *CreateLoop(int indent, CG_outputRepr *control, - CG_outputRepr *stmtList) const = 0; - - //--------------------------------------------------------------------------- - // copy operation, NULL parameter allowed. this function makes pointer - // handling uniform regardless NULL status - //--------------------------------------------------------------------------- - virtual CG_outputRepr *CreateCopy(CG_outputRepr *original) const { - if (original == NULL) - return NULL; - else - return original->clone(); - } - - //--------------------------------------------------------------------------- - // basic integer number creation - //--------------------------------------------------------------------------- - virtual CG_outputRepr *CreateInt(int num) const = 0; - virtual CG_outputRepr *CreateFloat(float num) const = 0; - virtual CG_outputRepr *CreateDouble(double num) const = 0; - - virtual bool isInteger(CG_outputRepr *op) const = 0; - virtual bool QueryInspectorType(const std::string &varName) const = 0; - - //--------------------------------------------------------------------------- - // basic identity/variable creation - //--------------------------------------------------------------------------- - virtual CG_outputRepr *CreateIdent(const std::string &varName) const = 0; - virtual CG_outputRepr* CreateDotExpression(CG_outputRepr *lop, - CG_outputRepr *rop) const =0; - virtual CG_outputRepr* CreateArrayRefExpression(const std::string &_s, - CG_outputRepr *rop) const =0; - virtual CG_outputRepr* CreateArrayRefExpression(CG_outputRepr *lop, - CG_outputRepr *rop) const=0; - virtual CG_outputRepr* ObtainInspectorData(const std::string &_s, const std::string &member_name) const=0; - virtual CG_outputRepr* CreateNullStatement() const=0; - - //--------------------------------------------------------------------------- - // binary arithmetic operations, NULL parameter means 0, - // Note: - // integer division truncation method undefined, only use when lop is known - // to be multiple of rop, otherwise use integer floor instead - //--------------------------------------------------------------------------- - virtual CG_outputRepr *CreatePlus(CG_outputRepr *lop, CG_outputRepr *rop) const = 0; - virtual CG_outputRepr *CreateMinus(CG_outputRepr *lop, CG_outputRepr *rop) const = 0; - virtual CG_outputRepr *CreateTimes(CG_outputRepr *lop, CG_outputRepr *rop) const = 0; - virtual CG_outputRepr *CreateDivide(CG_outputRepr *lop, CG_outputRepr *rop) const { - return CreateIntegerFloor(lop, rop); - } - - //--------------------------------------------------------------------------- - // integer arithmetic functions, NULL parameter means 0, second parameter - // must be postive (i.e. b > 0 below), otherwise function undefined - // Note: - // ceil(a, b) = -floor(-a, b) or floor(a+b-1, b) or floor(a-1, b)+1 - // mod(a, b) = a-b*floor(a, b) - // where result must lie in range [0,b) - // floor(a, b) = a/b if a >= 0 - // (a-b+1)/b if a < 0 - // where native '/' operator behaves as 5/2 = 2, (-5)/2 = -2 - //--------------------------------------------------------------------------- - virtual CG_outputRepr *CreateIntegerFloor(CG_outputRepr *lop, CG_outputRepr *rop) const = 0; - virtual CG_outputRepr *CreateIntegerMod(CG_outputRepr *lop, CG_outputRepr *rop) const { - CG_outputRepr *lop2 = CreateCopy(lop); - CG_outputRepr *rop2 = CreateCopy(rop); - return CreateMinus(lop2, CreateTimes(rop2, CreateIntegerFloor(lop, rop))); - } - virtual CG_outputRepr *CreateIntegerCeil(CG_outputRepr *lop, CG_outputRepr *rop) const { - return CreateMinus(NULL, CreateIntegerFloor(CreateMinus(NULL, lop), rop)); - } - - //--------------------------------------------------------------------------- - // binary logical operation, NULL parameter means TRUE - //--------------------------------------------------------------------------- - virtual CG_outputRepr *CreateAnd(CG_outputRepr *lop, CG_outputRepr *rop) const = 0; - - //--------------------------------------------------------------------------- - // binary condition operations - //--------------------------------------------------------------------------- - virtual CG_outputRepr *CreateGE(CG_outputRepr *lop, CG_outputRepr *rop) const { - return CreateLE(rop, lop); - } - virtual CG_outputRepr *CreateLE(CG_outputRepr *lop, CG_outputRepr *rop) const = 0; - virtual CG_outputRepr *CreateEQ(CG_outputRepr *lop, CG_outputRepr *rop) const = 0; - virtual CG_outputRepr *CreateNEQ(CG_outputRepr *lop, CG_outputRepr *rop) const = 0; - virtual CG_outputRepr *CreateAddressOf(CG_outputRepr *op) const = 0; - virtual CG_outputRepr *CreateBreakStatement(void) const = 0; - - //--------------------------------------------------------------------------- - // join stmts together, NULL parameter allowed - //--------------------------------------------------------------------------- - virtual CG_outputRepr *StmtListAppend(CG_outputRepr *list1, CG_outputRepr *list2) const = 0; - virtual CG_outputRepr *CreateStatementFromExpression(CG_outputRepr *exp) const = 0; - - virtual const char *ClassName() { return "UNKNOWN"; } -}; + /*! + * @brief pragma attribute + * @param scopeStmt + * @param looplevel + * @param pragmaText + * @return + */ + virtual CG_outputRepr * + CreatePragmaAttribute(CG_outputRepr *scopeStmt, int looplevel, const std::string &pragmaText) const = 0; + /*! + * @brief Prefetch attribute + * @param scopeStmt + * @param looplevel + * @param arrName + * @param hint + * @return + */ + virtual CG_outputRepr * + CreatePrefetchAttribute(CG_outputRepr *scopeStmt, int looplevel, const std::string &arrName, int hint) const = 0; + /*! + * @brief generate if stmt, true/false stmt can be NULL but not the condition + * @param indent + * @param guardCondition + * @param true_stmtList + * @param false_stmtList + * @return + */ + virtual CG_outputRepr *CreateIf(int indent, CG_outputRepr *guardCondition, + CG_outputRepr *true_stmtList, + CG_outputRepr *false_stmtList) const = 0; + /*! + * @brief generate loop inductive variable (loop control structure) + * @param index + * @param lower + * @param upper + * @param step + * @return + */ + virtual CG_outputRepr *CreateInductive(CG_outputRepr *index, + CG_outputRepr *lower, + CG_outputRepr *upper, + CG_outputRepr *step) const = 0; + /*! + * @brief generate loop stmt from loop control and loop body, NULL parameter allowed + * @param indent + * @param control + * @param stmtList + * @return + */ + virtual CG_outputRepr *CreateLoop(int indent, CG_outputRepr *control, + CG_outputRepr *stmtList) const = 0; + /*! + * @brief copy operation, NULL parameter allowed + * + * this function makes pointer handling uniform regardless NULL status + * + * @param original + * @return + */ + virtual CG_outputRepr *CreateCopy(CG_outputRepr *original) const { + if (original == NULL) + return NULL; + else + return original->clone(); + } + + //! basic interger number creation + virtual CG_outputRepr *CreateInt(int num) const = 0; + + //! basic single precision float number creation + virtual CG_outputRepr *CreateFloat(float num) const = 0; + + //! basic double precision float number creation + virtual CG_outputRepr *CreateDouble(double num) const = 0; + + /*! + * @brief check if op is integer literal + * @param op + * @return + */ + virtual bool isInteger(CG_outputRepr *op) const = 0; + + /*! + * @brief DOC needed + * @param varName + * @return + */ + virtual bool QueryInspectorType(const std::string &varName) const = 0; + /*! + * @brief basic identity/variable creation + * @param varName + * @return + */ + virtual CG_outputRepr *CreateIdent(const std::string &varName) const = 0; + /*! + * @brief member access creation? + * @param lop + * @param rop + * @return + */ + virtual CG_outputRepr *CreateDotExpression(CG_outputRepr *lop, + CG_outputRepr *rop) const =0; + /*! + * @brief Create array reference expression starting with a string + * @param _s + * @param rop + * @return + */ + virtual CG_outputRepr *CreateArrayRefExpression(const std::string &_s, + CG_outputRepr *rop) const =0; + /*! + * @brief Create array reference expression starting with a expresion + * @param lop + * @param rop + * @return + */ + virtual CG_outputRepr *CreateArrayRefExpression(CG_outputRepr *lop, + CG_outputRepr *rop) const =0; + /*! + * @brief TODO DOC NEEDED + * @param _s + * @param member_name + * @return + */ + virtual CG_outputRepr *ObtainInspectorData(const std::string &_s, const std::string &member_name) const =0; + /*! + * @brief TODO USAGE NEEDED + * @return + */ + virtual CG_outputRepr *CreateNullStatement() const =0; + /*! + * @brief Addition operations, NULL parameter means 0 + * @param lop + * @param rop + * @return + */ + virtual CG_outputRepr *CreatePlus(CG_outputRepr *lop, CG_outputRepr *rop) const = 0; + /*! + * @brief Subtraction operations, NULL parameter means 0 + * @param lop + * @param rop + * @return + */ + virtual CG_outputRepr *CreateMinus(CG_outputRepr *lop, CG_outputRepr *rop) const = 0; + /*! + * @brief Multiplication operations, NULL parameter means 0 + * @param lop + * @param rop + * @return + */ + virtual CG_outputRepr *CreateTimes(CG_outputRepr *lop, CG_outputRepr *rop) const = 0; + /*! + * @brief Division operations, NULL parameter means 0 + * + * integer division truncation method undefined, only use when lop is known + * to be multiple of rop, otherwise use integer floor instead + * + * @param lop + * @param rop + * @return + */ + virtual CG_outputRepr *CreateDivide(CG_outputRepr *lop, CG_outputRepr *rop) const { + return CreateIntegerFloor(lop, rop); + } + /*! + * @brief integer floor functions, NULL parameter means 0 + * + * second parameter must be postive (i.e. b > 0 below), otherwise function undefined + * + * floor(a, b) + * * = a/b if a >= 0 + * * = (a-b+1)/b if a < 0 + * + * @param lop + * @param rop + * @return + */ + virtual CG_outputRepr *CreateIntegerFloor(CG_outputRepr *lop, CG_outputRepr *rop) const = 0; + /*! + * @brief integer mod functions, NULL parameter means 0 + * + * second parameter must be postive (i.e. b > 0 below), otherwise function undefined + * + * mod(a, b) = a-b*floor(a, b) where result must lie in range [0,b) + * + * @param lop + * @param rop + * @return + */ + virtual CG_outputRepr *CreateIntegerMod(CG_outputRepr *lop, CG_outputRepr *rop) const { + CG_outputRepr *lop2 = CreateCopy(lop); + CG_outputRepr *rop2 = CreateCopy(rop); + return CreateMinus(lop2, CreateTimes(rop2, CreateIntegerFloor(lop, rop))); + } + /*! + * @brief integer ceil functions, NULL parameter means 0 + * + * second parameter must be postive (i.e. b > 0 below), otherwise function undefined + * + * ceil(a, b) = -floor(-a, b) or floor(a+b-1, b) or floor(a-1, b)+1 + * + * @param lop + * @param rop + * @return + */ + virtual CG_outputRepr *CreateIntegerCeil(CG_outputRepr *lop, CG_outputRepr *rop) const { + return CreateMinus(NULL, CreateIntegerFloor(CreateMinus(NULL, lop), rop)); + } + + //! binary logical operation, NULL parameter means TRUE + virtual CG_outputRepr *CreateAnd(CG_outputRepr *lop, CG_outputRepr *rop) const = 0; + + //! binary conditional greater than or equal to + virtual CG_outputRepr *CreateGE(CG_outputRepr *lop, CG_outputRepr *rop) const { + return CreateLE(rop, lop); + } + + //! binary conditional less than or equal to + virtual CG_outputRepr *CreateLE(CG_outputRepr *lop, CG_outputRepr *rop) const = 0; + + //! binary conditional equal to + virtual CG_outputRepr *CreateEQ(CG_outputRepr *lop, CG_outputRepr *rop) const = 0; + + //! binary conditional not equal to + virtual CG_outputRepr *CreateNEQ(CG_outputRepr *lop, CG_outputRepr *rop) const = 0; + //! address of operator + virtual CG_outputRepr *CreateAddressOf(CG_outputRepr *op) const = 0; + //! create a break statement + virtual CG_outputRepr *CreateBreakStatement(void) const = 0; + + //! join stmts together, NULL parameter allowed + virtual CG_outputRepr *StmtListAppend(CG_outputRepr *list1, CG_outputRepr *list2) const = 0; + //! Wraps a expression into a statement. TODO DOC NEEDED + virtual CG_outputRepr *CreateStatementFromExpression(CG_outputRepr *exp) const = 0; + //! TODO USAGE AND DOC + virtual const char *ClassName() { return "UNKNOWN"; } + }; } diff --git a/lib/codegen/include/code_gen/CG_outputRepr.h b/lib/codegen/include/code_gen/CG_outputRepr.h index d72ae6f..80f8ec5 100644 --- a/lib/codegen/include/code_gen/CG_outputRepr.h +++ b/lib/codegen/include/code_gen/CG_outputRepr.h @@ -23,9 +23,11 @@ class CG_outputRepr { public: CG_outputRepr() {} - virtual ~CG_outputRepr() { /* shallow delete */ } + //! shallow delete + virtual ~CG_outputRepr() { } virtual CG_outputRepr *clone() const = 0; - virtual void clear() { /* delete actual IR code wrapped inside */ } + //! delete actual IR code wrapped inside + virtual void clear() { } virtual void dump() const {} virtual char *type() const = 0; }; diff --git a/src/irtools.cc b/src/irtools.cc index 55ef57f..31747a1 100644 --- a/src/irtools.cc +++ b/src/irtools.cc @@ -412,7 +412,7 @@ test_data_dependences(IR_Code *ir, // Manu:: check if the array references belong to the same statement // If yes, set the flag in the dependence vector //---------------------------------------------- - if (DEP_DEBUG) { + CHILL_DEBUG_BEGIN std::cout << "Size of the dependence vector '" << a->name().c_str() << "' -- " << dv.first.size() << "\n"; std::cout << "------------ Printing dependence vector START ---------------\n"; @@ -446,7 +446,7 @@ test_data_dependences(IR_Code *ir, } } std::cout << "------------ Printing dependence vector END---------------\n"; - } + CHILL_DEBUG_END checkReductionDependence(i, j, nestLeveli, lbound, ubound, ref2Stmt, rMap, dv, trMap, nrStmts); //---------------------------------------------- @@ -708,10 +708,10 @@ checkReductionDependence(int i, int j, int nestLeveli, omega::coef_t lbound[], o } // if ((rMap.find(ref2Stmt[i])->second).size() == 3) { - if (DEP_DEBUG) { + CHILL_DEBUG_BEGIN std::cout << "lbounds: " << lbound[0] << ", " << lbound[1] << ", " << lbound[2] << "\n"; std::cout << "ubounds: " << ubound[0] << ", " << ubound[1] << ", " << ubound[2] << "\n"; - } + CHILL_DEBUG_END if (((rMap.find(ref2Stmt[i])->second).size() == 3) && (lbound[0] == lbound[1]) && (lbound[1] == lbound[2]) && (ubound[0] == ubound[1]) && (ubound[1] == ubound[2])) { // std::cout << "Manu:: All dependences present 1 \n"; diff --git a/src/transformations/loop.cc b/src/transformations/loop.cc index d34f415..3e040fd 100644 --- a/src/transformations/loop.cc +++ b/src/transformations/loop.cc @@ -1002,8 +1002,7 @@ Loop::Loop(const IR_Control *control) { } // printing out stuff for debugging - - if (DEP_DEBUG) { + CHILL_DEBUG_BEGIN std::cout << "STATEMENTS THAT CAN BE REDUCED: \n"; for (int i = 0; i < canReduce.size(); i++) { std::cout << "------- " << canReduce[i] << " ------- " @@ -1020,7 +1019,7 @@ Loop::Loop(const IR_Control *control) { else std::cout << "Unknown reduction type\n"; } - } + CHILL_DEBUG_END // cleanup the IR tree fprintf(stderr, "init dumb transformation relations\n"); -- cgit v1.2.3-70-g09d2