52 #include <boost/graph/topological_sort.hpp> 95 const DesignFlowManagerConstRef _design_flow_manager)
97 TM(_AppM->get_tree_manager()),
98 restart_phi_opt(
false)
109 switch(relationship_type)
113 if(!
parameters->getOption<
int>(OPT_gcc_openmp_simd))
115 relationships.insert(std::make_pair(BITVALUE_RANGE,
SAME_FUNCTION));
117 relationships.insert(std::make_pair(DEAD_CODE_ELIMINATION,
SAME_FUNCTION));
118 relationships.insert(std::make_pair(DEAD_CODE_ELIMINATION_IPA,
WHOLE_APPLICATION));
119 relationships.insert(std::make_pair(DETERMINE_MEMORY_ACCESSES,
SAME_FUNCTION));
120 relationships.insert(std::make_pair(SIMPLE_CODE_MOTION,
SAME_FUNCTION));
121 relationships.insert(std::make_pair(USE_COUNTING,
SAME_FUNCTION));
126 relationships.insert(std::make_pair(IR_LOWERING,
SAME_FUNCTION));
127 relationships.insert(std::make_pair(PHI_OPT,
SAME_FUNCTION));
128 relationships.insert(std::make_pair(SDC_CODE_MOTION,
SAME_FUNCTION));
129 relationships.insert(std::make_pair(UN_COMPARISON_LOWERING,
SAME_FUNCTION));
138 relationships.insert(std::make_pair(DEAD_CODE_ELIMINATION,
SAME_FUNCTION));
141 relationships.insert(std::make_pair(PHI_OPT,
SAME_FUNCTION));
163 return relationships;
169 if(GetPointer<const HLS_manager>(
AppM) && GetPointerS<const HLS_manager>(
AppM)->get_HLS(
function_id) &&
179 if(
parameters->IsParameter(
"disable-cse") &&
parameters->GetParameter<
unsigned int>(
"disable-cse") == 1)
183 bool IR_changed =
false;
186 size_t n_equiv_stmt = 0;
190 std::map<vertex, CustomUnorderedMapStable<CSE_tuple_key_type, tree_nodeRef>> unique_table;
193 const auto fd = GetPointerS<const function_decl>(temp);
194 const auto sl = GetPointerS<const statement_list>(
GET_CONST_NODE(fd->body));
202 for(
const auto&
block : sl->list_of_bloc)
204 inverse_vertex_map[
block.first] =
208 for(
const auto& idx_bb : sl->list_of_bloc)
210 for(
const auto& pred : idx_bb.second->list_of_pred)
212 THROW_ASSERT(inverse_vertex_map.find(pred) != inverse_vertex_map.end(),
213 "BB" +
STR(pred) +
" (successor of BB" +
STR(idx_bb.first) +
") does not exist");
214 GCC_bb_graphs_collection->AddEdge(inverse_vertex_map[pred], inverse_vertex_map[idx_bb.first],
CFG_SELECTOR);
216 for(
const auto& succ : idx_bb.second->list_of_succ)
220 GCC_bb_graphs_collection->AddEdge(inverse_vertex_map[idx_bb.first], inverse_vertex_map[succ],
CFG_SELECTOR);
223 if(idx_bb.second->list_of_succ.empty())
225 GCC_bb_graphs_collection->AddEdge(inverse_vertex_map[idx_bb.first], inverse_vertex_map[
bloc::EXIT_BLOCK_ID],
237 const auto& bb_dominator_map = bb_dominators->get_dominator_map();
240 for(
auto it : bb_dominator_map)
242 if(it.first != inverse_vertex_map[bloc::ENTRY_BLOCK_ID])
244 GCC_bb_graphs_collection->AddEdge(it.second, it.first,
D_SELECTOR);
248 std::deque<vertex> sort_list;
249 boost::topological_sort(*bb_domGraph, std::front_inserter(sort_list));
251 for(
const auto& bb : sort_list)
256 unique_table[bb].clear();
257 if(bb_dominator_map.find(bb) != bb_dominator_map.end())
259 THROW_ASSERT(unique_table.find(bb_dominator_map.at(bb)) != unique_table.end(),
"unexpected condition");
261 "---Adding dominator equiv: " +
264 for(
const auto& key_value_pair : unique_table.at(bb_dominator_map.at(bb)))
266 unique_table.at(bb)[key_value_pair.first] = key_value_pair.second;
270 for(
const auto& stmt :
B->CGetStmtList())
273 if(!
AppM->ApplyNewTransformation())
280 const auto ref_ga = GetPointerS<gimple_assign>(eq_tn);
281 const auto dead_ga = GetPointerS<const gimple_assign>(
GET_CONST_NODE(stmt));
282 const auto ref_ssa = GetPointerS<ssa_name>(
GET_NODE(ref_ga->op0));
283 const auto dead_ssa = GetPointerS<const ssa_name>(
GET_CONST_NODE(dead_ga->op0));
302 if(!ref_ssa->bit_values.empty())
306 if(!dead_ssa->bit_values.empty())
311 bool same_range =
false;
312 if(!
parameters->getOption<
int>(OPT_gcc_openmp_simd))
314 same_range = dead_ssa->bit_values.empty() || ref_ssa->bit_values == dead_ssa->bit_values;
319 if(
GET_CONST_NODE(ga_op_type)->get_kind() == integer_type_K && ref_ssa->min && ref_ssa->max &&
320 dead_ssa->min && dead_ssa->max)
326 if(dead_min == ref_min && dead_max == ref_max)
333 "---replace equivalent statement before: ref_min=" +
STR(ref_min) +
" dead_min=" +
334 STR(dead_min) +
" ref_max=" +
STR(ref_max) +
" dead_max=" +
STR(dead_max));
341 ref_ga->temporary_address = ref_ga->temporary_address && dead_ga->temporary_address;
343 "---ref_ga->temporary_address" +
344 (ref_ga->temporary_address ? std::string(
"T") : std::string(
"F")));
345 if(dead_ssa->use_set && !ref_ssa->use_set)
347 ref_ssa->use_set = dead_ssa->use_set;
350 const auto StmtUses = dead_ssa->CGetUseStmts();
351 for(
const auto& use : StmtUses)
354 "---replace equivalent statement before: " + use.first->ToString());
355 TM->ReplaceTreeNode(use.first, dead_ga->op0, ref_ga->op0);
357 "---replace equivalent statement after: " + use.first->ToString());
359 to_be_removed.insert(stmt);
367 "<--Updated/Removed duplicated statement " +
STR(dead_ga->op0));
375 for(
const auto& stmt : to_be_removed)
378 B->RemoveStmt(stmt,
AppM);
380 if(
B->CGetStmtList().empty() &&
B->CGetPhiList().empty() && !to_be_removed.empty())
384 if(!to_be_removed.empty() &&
schedule)
386 for(
const auto& stmt :
B->CGetStmtList())
409 const auto is_a_vector_bitfield =
410 rhs_kind == bit_field_ref_K &&
413 bool skip_check = rhs_kind == var_decl_K || rhs_kind == string_cst_K || rhs_kind == constructor_K ||
414 (rhs_kind == bit_field_ref_K && !is_a_vector_bitfield) || rhs_kind == component_ref_K ||
415 rhs_kind == indirect_ref_K || rhs_kind == misaligned_indirect_ref_K || rhs_kind == array_ref_K ||
416 rhs_kind == target_mem_ref_K || rhs_kind == target_mem_ref461_K or rhs_kind == mem_ref_K;
417 if(rhs_kind == realpart_expr_K || rhs_kind == imagpart_expr_K)
420 if((code1 == bit_field_ref_K && !is_a_vector_bitfield) || code1 == component_ref_K || code1 == indirect_ref_K ||
421 code1 == bit_field_ref_K || code1 == misaligned_indirect_ref_K || code1 == mem_ref_K || code1 == array_ref_K ||
422 code1 == target_mem_ref_K || code1 == target_mem_ref461_K)
427 GetPointerS<const unary_expr>(
GET_CONST_NODE(ga->
op1))->op)) != fun_mem_data.end())
432 else if(rhs_kind == view_convert_expr_K)
467 if(op0_type && op1_type &&
469 GET_CONST_NODE(op1_type)->get_kind() == record_type_K && rhs_kind != view_convert_expr_K) ||
471 rhs_kind != view_convert_expr_K) ||
485 if(GetPointer<const gimple_node>(tn)->keep)
490 const auto ga = GetPointer<const gimple_assign>(tn);
491 if(ga && (ga->clobber || ga->init_assignment))
500 const auto rhs_kind = rhs->get_kind();
501 if(GetPointer<const binary_expr>(rhs))
505 if(rhs_kind != extract_bit_expr_K && rhs_kind != lut_expr_K &&
parameters->IsParameter(
"CSE_size") &&
506 bitwidth_values <
parameters->GetParameter<
unsigned int>(
"CSE_size"))
519 std::vector<unsigned int> ins;
526 ins.push_back(ga->bb_index);
527 for(
const auto& vuse : ga->vuses)
529 ins.push_back(vuse->index);
532 const auto virtual_sn = GetPointerS<const ssa_name>(
GET_CONST_NODE(vuse));
533 const auto virtual_sn_def = virtual_sn->CGetDefStmt();
534 const auto virtual_sn_gn = GetPointerS<const gimple_node>(
GET_CONST_NODE(virtual_sn_def));
536 if(virtual_sn_gn->bb_index == ga->bb_index)
541 virtual_sn_def->get_kind() == gimple_phi_K ?
542 bb->CGetStmtList().end() :
543 std::find_if(bb->CGetStmtList().begin(), bb->CGetStmtList().end(),
544 [&](
const tree_nodeRef& stmt) {
return stmt->index == virtual_sn_gn->index; });
545 const auto ga_it = std::find_if(vdef_it, bb->CGetStmtList().end(),
546 [&](
const tree_nodeRef& stmt) {
return stmt->index == ga->index; });
547 if(ga_it != bb->CGetStmtList().end())
549 ins.push_back(virtual_sn_def->index);
554 if(rhs_kind == ssa_name_K)
556 ins.push_back(rhs->index);
558 else if(GetPointer<const cst_node>(rhs))
560 ins.push_back(rhs->index);
562 else if(rhs_kind == nop_expr_K || rhs_kind == view_convert_expr_K || rhs_kind == convert_expr_K ||
563 rhs_kind == float_expr_K || rhs_kind == fix_trunc_expr_K)
565 const auto ue = GetPointerS<const unary_expr>(rhs);
568 ins.push_back(type_index);
570 else if(GetPointer<const unary_expr>(rhs))
572 const auto ue = GetPointerS<const unary_expr>(rhs);
575 else if(GetPointer<const binary_expr>(rhs))
577 const auto be = GetPointerS<const binary_expr>(rhs);
581 else if(GetPointer<const ternary_expr>(rhs))
583 const auto te = GetPointerS<const ternary_expr>(rhs);
591 else if(GetPointer<const call_expr>(rhs))
593 const auto ce = GetPointerS<const call_expr>(rhs);
597 const auto ae = GetPointerS<const addr_expr>(addr_node);
599 const auto fd = GetPointerS<const function_decl>(
GET_CONST_NODE(ae->op));
601 if(fd->undefined_flag || fd->writing_memory || fd->reading_memory || ga->vuses.size())
606 for(
const auto&
arg : ce->args)
617 else if(GetPointer<const lut_expr>(rhs))
619 const auto le = GetPointerS<const lut_expr>(rhs);
658 auto signature_message =
"Signature of " +
STR(tn->
index) +
" is ";
659 for(
const auto& temp_sign : ins)
661 signature_message +=
STR(temp_sign) +
"-";
663 signature_message.pop_back();
667 if(unique_table.at(bb_vertex).find(t) != unique_table.at(bb_vertex).end())
671 "--- equivalent with = " + unique_table.at(bb_vertex).at(t)->ToString());
673 THROW_ASSERT(!ga->memdef,
"Unexpected memdef " + ga->memdef->ToString() +
" in " + tn->
ToString());
676 return unique_table.at(bb_vertex).at(t);
680 unique_table.at(bb_vertex)[t] = tn;
#define GET_NODE(t)
Macro used to hide implementation details when accessing a tree_node from another tree_node...
#define DEBUG_LEVEL_VERY_PEDANTIC
extremely verbose debugging print is performed.
Data structure representing the entire HLS information.
#define INDENT_DBG_MEX(dbgLevel, curDbgLevel, mex)
We are producing a debug version of the program, so the message is printed;.
std::string ToString() const
Print this node as string in gimple format.
Step successfully executed.
Definition of the node_info object for the basic_block graph.
#define GET_CLASS(obj)
Macro returning the actual type of an object.
tree_nodeRef op1
The second operand of the binary expression.
This struct specifies the statement_list node.
Definition of the class representing a generic C application.
refcount< tree_manipulation > tree_manipulationRef
static bool IsArrayEquivType(const tree_nodeConstRef &type)
Return true if treenode is an array or it is equivalent to an array (record recursively having a sing...
std::string GetName() const override
Return the name of this design step.
Step successfully executed but without any IR change.
RelationshipType
The relationship type.
Source must be executed to satisfy target.
ScheduleRef schedule
The scheduling solution.
#define D_SELECTOR
Selectors used only in basic block graphs; numbers continue from cdfg_edge_info.hpp.
bool has_memory_access(const gimple_assign *ga) const
check if the gimple assignment is a load, store or a memcpy/memset
tree_nodeRef op0
The first operand of the binary expression.
std::map< unsigned int, blocRef > list_of_bloc
list_of_bloc field is the list of basic block. If this field is null then the list_of_stmt field is n...
static const unsigned int EXIT_BLOCK_ID
constant identifying the exit basic block
void Initialize() override
Initialize the step (i.e., like a constructor, but executed just before exec)
CSE(const ParameterConstRef _parameters, const application_managerRef _AppM, unsigned int function_id, const DesignFlowManagerConstRef design_flow_manager)
Constructor.
Data structure describing a basic block at tree level.
tree_nodeRef hash_check(const tree_nodeRef &tn, vertex bb, const statement_list *sl, std::map< vertex, CustomUnorderedMapStable< CSE_tuple_key_type, tree_nodeRef >> &unique_table) const
check if the statement has an equivalent in the unique table
#define STR(s)
Macro which performs a lexical_cast to a string.
Auxiliary methods for manipulating string.
std::string ToString(ActorGraphBackend_Type actor_graph_backend_type)
Header include.
const tree_managerRef TM
tree manager
#define THROW_UNREACHABLE(str_expr)
helper function used to specify that some points should never be reached
void UpdateTime(const unsigned int operation_index, bool update_cs=true)
Compute the starting and the ending time of a statement.
static unsigned long long Size(const tree_nodeConstRef &tn)
Return the size of a tree object.
Class used to describe a particular graph with basic blocks as nodes.
unsigned map[NUM_VERTICES]
absl::flat_hash_map< T, U, Hash, Eq, Alloc > CustomUnorderedMap
This struct specifies the gimple_assign node (GCC 4.3 tree node).
const CustomUnorderedSet< std::pair< FrontendFlowStepType, FunctionRelationship > > ComputeFrontendRelationships(const DesignFlowStep::RelationshipType relationship_type) const override
Return the set of analyses in relationship with this design step.
Data structure used to store the schedule of the operations.
refcount< BBNodeInfo > BBNodeInfoRef
refcount definition of the class
Information associated with the whole basic-block graph.
const unsigned int index
Represent the index read from the raw file and the index-1 of the vector of tree_node associated to t...
Target must be reexecuted.
boost::graph_traits< graph >::vertex_descriptor vertex
vertex definition.
static bool IsVectorType(const tree_nodeConstRef &type)
Return true if the treenode is a vector.
#define GET_CONST_NODE(t)
std::pair< enum kind, std::vector< unsigned int > > CSE_tuple_key_type
define the type of the unique table key
DesignFlowStep_Status GetStatus() const
Return the status of this design step.
const ParameterConstRef parameters
Set of input parameters.
DesignFlowStep_Status
The status of a step.
Class defining some useful functions to create tree nodes and to manipulate the tree manager...
#define DEBUG_LEVEL_NONE
no debugging print is performed.
This struct specifies the block node.
This file collects some utility functions.
DesignFlowStep_Status InternalExec() override
perform CSE analysis
const unsigned int function_id
The index of the function to be analyzed.
const application_managerRef AppM
The application manager.
~CSE() override
Destructor.
Class specification of the tree_reindex support class.
static const unsigned int ENTRY_BLOCK_ID
constant identifying the entry basic block
Class specification of the basic_block structure.
bool restart_phi_opt
when true PHI_OPT step has to restart
const BBNodeInfoConstRef CGetBBNodeInfo(const vertex node) const
Return the info associated with a basic block.
Template borrowed from the ANTLR library by Terence Parr (http://www.jGuru.com - Software rights: htt...
static tree_nodeConstRef CGetType(const tree_nodeConstRef &node)
Return the treenode of the type of node.
this class is used to manage the command-line or XML options.
absl::node_hash_map< T, U, Hash, Eq, Alloc > CustomUnorderedMapStable
static integer_cst_t GetConstValue(const tree_nodeConstRef &tn, bool is_signed=true)
Get value from integer constant.
int debug_level
The debug level.
#define GET_INDEX_CONST_NODE(t)
#define DEBUG_LEVEL_VERBOSE
verbose debugging print is performed.
static bool IsPointerType(const tree_nodeConstRef &type)
Return true if treenode index is a pointer.
#define CFG_SELECTOR
Control flow graph edge selector.
Data structure definition for high-level synthesis flow.
Step is symbolic and it has already been marked.
refcount< BBGraphInfo > BBGraphInfoRef
refcount definition of the class
This class contains the base representation for a generic frontend flow step which works on the whole...
This class creates a layer to add nodes and to manipulate the tree_nodes manager. ...
Class specification of the manager of the tree structures extracted from the raw file.
A brief description of the C++ Header File.
const FunctionBehaviorRef function_behavior
The function behavior of the function to be analyzed.
This structure defines graphs where nodes are basic_blocks.
#define THROW_ASSERT(cond, str_expr)
helper function used to check an assert and if needed to throw an error in a standard way ...