102 unsigned int _function_id,
const DesignFlowManagerConstRef _design_flow_manager)
114 switch(relationship_type)
118 relationships.insert(std::make_pair(BLOCK_FIX,
SAME_FUNCTION));
119 relationships.insert(std::make_pair(SWITCH_FIX,
SAME_FUNCTION));
120 relationships.insert(std::make_pair(USE_COUNTING,
SAME_FUNCTION));
121 relationships.insert(std::make_pair(UN_COMPARISON_LOWERING,
SAME_FUNCTION));
125 relationships.insert(std::make_pair(UPDATE_SCHEDULE,
SAME_FUNCTION));
128 if(!
parameters->getOption<
int>(OPT_gcc_openmp_simd))
130 relationships.insert(std::make_pair(BITVALUE_RANGE,
SAME_FUNCTION));
140 GetPointer<const HLS_manager>(
AppM) and GetPointer<const HLS_manager>(
AppM)->get_HLS(
function_id) and
150 design_flow_graph->CGetDesignFlowStepInfo(update_schedule)->design_flow_step;
151 if(GetPointer<const FunctionFrontendFlowStep>(design_flow_step)->
CGetBBVersion() !=
154 relationships.insert(std::make_pair(UPDATE_SCHEDULE,
SAME_FUNCTION));
162 relationships.insert(std::make_pair(EXTRACT_GIMPLE_COND_OP,
SAME_FUNCTION));
168 relationships.insert(std::make_pair(DETERMINE_MEMORY_ACCESSES,
SAME_FUNCTION));
170 relationships.insert(std::make_pair(REMOVE_CLOBBER_GA,
SAME_FUNCTION));
171 relationships.insert(std::make_pair(EXTRACT_GIMPLE_COND_OP,
SAME_FUNCTION));
179 return relationships;
188 const auto TM =
AppM->get_tree_manager();
190 const auto fd = GetPointer<const function_decl>(temp);
191 const auto sl = GetPointer<statement_list>(
GET_NODE(fd->body));
195 for(
const auto& idx_bb : sl->list_of_bloc)
201 unsigned int n_pred_bb = 0;
202 if(idx_bb.second->list_of_pred.size() <= 1)
207 for(
auto const pred : idx_bb.second->list_of_pred)
210 if(pred !=
bloc::ENTRY_BLOCK_ID && idx_bb.first != pred && sl->list_of_bloc.at(pred)->CGetStmtList().size() &&
211 GET_CONST_NODE(sl->list_of_bloc.at(pred)->CGetStmtList().back())->get_kind() == gimple_cond_K)
221 if(n_pred_bb > 1 &&
check_phis(idx_bb.first, sl->list_of_bloc))
223 merging_candidates.insert(idx_bb.first);
231 if(!merging_candidates.empty())
241 auto bb1 =
static_cast<unsigned int>(-1), bb2 = static_cast<unsigned int>(-1), merging_candidate = 0
U;
242 bool bb1_true =
false;
243 bool bb2_true =
false;
244 bool mergeable_pair_found;
245 bool something_change =
false;
250 mergeable_pair_found =
false;
251 const auto it_mc_end = merging_candidates.cend();
252 for(
auto it_mc = merging_candidates.cbegin(); !mergeable_pair_found && it_mc != it_mc_end; ++it_mc)
254 merging_candidate = *it_mc;
255 mergeable_pair_found =
258 if(!
AppM->ApplyNewTransformation())
262 if(mergeable_pair_found)
265 if(
create_gimple_cond(bb1, bb2, bb1_true, sl->list_of_bloc, bb2_true, merging_candidate))
267 something_change =
true;
269 merging_candidates.erase(bb1);
272 merging_candidates.erase(merging_candidate);
275 (!
parameters->IsParameter(
"print-dot-FF") ||
parameters->GetParameter<
unsigned int>(
"print-dot-FF")))
283 merging_candidates.erase(merging_candidate);
286 }
while(mergeable_pair_found);
300 bool& bb1_true,
bool& bb2_true,
301 const std::map<unsigned int, blocRef>& list_of_bloc)
304 bool mergeable_pair_found =
false;
306 THROW_ASSERT(list_of_bloc.find(merging_candidate) != list_of_bloc.end(),
307 "merging_candidate is not included in list_of_bloc");
308 const auto it_pred_end = list_of_bloc.at(merging_candidate)->list_of_pred.end();
309 for(
auto it_bb1_pred = list_of_bloc.at(merging_candidate)->list_of_pred.begin();
310 !mergeable_pair_found && it_pred_end != it_bb1_pred; ++it_bb1_pred)
317 if(list_of_bloc.at(bb1)->CGetStmtList().empty())
321 if(
GET_CONST_NODE(list_of_bloc.at(bb1)->CGetStmtList().back())->get_kind() != gimple_cond_K)
326 "-->Examining merging candidate predecessor BB" +
STR(bb1));
328 "bb1 has to be an if statement " +
STR(bb1) +
" " +
STR(merging_candidate));
329 if(list_of_bloc.at(bb1)->true_edge == merging_candidate)
338 for(
auto it_bb2_pred = list_of_bloc.at(merging_candidate)->list_of_pred.begin();
339 !mergeable_pair_found && it_pred_end != it_bb2_pred; ++it_bb2_pred)
343 "Examining merging candidate nested predecessor " +
STR(bb2));
348 if(list_of_bloc.at(bb2)->list_of_pred.size() > 1)
352 if(list_of_bloc.at(bb2)->CGetStmtList().size() != 1)
356 if(list_of_bloc.at(bb2)->CGetPhiList().size() != 0)
360 if(
GET_CONST_NODE(list_of_bloc.at(bb2)->CGetStmtList().back())->get_kind() != gimple_cond_K)
365 "bb2 has to be an if statement " +
STR(bb2) +
" " +
STR(merging_candidate));
367 if(list_of_bloc.at(bb2)->true_edge == bb1 || list_of_bloc.at(bb2)->false_edge == bb1)
371 if(bb1_true && list_of_bloc.at(bb1)->false_edge == bb2)
373 if(list_of_bloc.at(bb2)->true_edge == merging_candidate)
382 mergeable_pair_found =
true;
386 "bb1 T " +
STR(bb1) +
" bb2 T " +
STR(bb2) +
" MC " +
STR(merging_candidate));
391 "bb1 T " +
STR(bb1) +
" bb2 F " +
STR(bb2) +
" MC " +
STR(merging_candidate));
394 else if(!bb1_true && list_of_bloc.at(bb1)->true_edge == bb2)
396 if(list_of_bloc.at(bb2)->true_edge == merging_candidate)
404 mergeable_pair_found =
true;
409 "bb1 F " +
STR(bb1) +
" bb2 T " +
STR(bb2) +
" MC " +
STR(merging_candidate));
414 "bb1 F " +
STR(bb1) +
" bb2 F " +
STR(bb2) +
" MC " +
STR(merging_candidate));
421 return mergeable_pair_found;
425 const std::map<unsigned int, blocRef>& list_of_bloc,
bool or_type,
426 unsigned int merging_candidate)
431 "Creating new cond expr: " +
STR(bb1) +
" is the first basic block, " +
STR(bb2) +
432 " is the second basic block");
435 if(list_of_bloc.at(bb2)->CGetStmtList().size() != 1)
439 const auto list_of_stmt_cond2 = list_of_bloc.at(bb2)->CGetStmtList();
442 const auto& list_of_stmt_cond1 = list_of_bloc.at(bb1)->CGetStmtList();
444 const auto cond_statement = list_of_stmt_cond1.back();
445 list_of_bloc.at(bb1)->RemoveStmt(cond_statement,
AppM);
448 const auto ce1 = GetPointer<const gimple_cond>(
GET_CONST_NODE(cond_statement));
449 auto cond1 = ce1->op0;
458 const auto cond1_created_stmt =
460 const auto ssa1_cond_node = GetPointer<const gimple_assign>(
GET_CONST_NODE(cond1_created_stmt))->op0;
462 list_of_bloc.at(bb1)->PushBack(cond1_created_stmt,
AppM);
464 "---Created statement in BB" +
STR(bb1) +
" - " +
STR(cond1_created_stmt));
465 cond1 = ssa1_cond_node;
468 if(list_of_bloc.at(merging_candidate)->CGetPhiList().size())
470 for(
const auto&
phi : list_of_bloc.at(merging_candidate)->CGetPhiList())
472 const auto mc_phi = GetPointer<gimple_phi>(
GET_NODE(
phi));
473 std::pair<tree_nodeRef, unsigned int> def_edge_to_be_removed(
tree_nodeRef(), 0);
474 std::pair<tree_nodeRef, unsigned int> def_edge_to_be_updated(
tree_nodeRef(), 0);
475 for(
const auto& def_edge : mc_phi->CGetDefEdgesList())
477 if(def_edge.second == bb1)
479 def_edge_to_be_removed = def_edge;
481 else if(def_edge.second == bb2)
483 def_edge_to_be_updated = def_edge;
486 THROW_ASSERT(def_edge_to_be_removed.first,
"unexpected condition");
487 THROW_ASSERT(def_edge_to_be_updated.first,
"unexpected condition");
488 auto op1 = def_edge_to_be_removed.first;
489 auto op2 = def_edge_to_be_updated.first;
499 const auto cond_expr_node = tree_man->create_ternary_operation(
500 res_type, cond1, op1, op2,
BUILTIN_SRCP, (isAVectorType ? vec_cond_expr_K : cond_expr_K));
501 const auto created_stmt =
503 const auto ssa_cond_node = GetPointer<const gimple_assign>(
GET_CONST_NODE(created_stmt))->op0;
508 list_of_bloc.at(bb1)->PushBack(created_stmt,
AppM);
510 mc_phi->ReplaceDefEdge(TM, def_edge_to_be_updated,
513 mc_phi->RemoveDefEdge(TM, def_edge_to_be_removed);
518 if((bb1_true && !or_type) || (!bb1_true && or_type))
521 const auto not_cond1 = tree_man->create_unary_operation(
type_node, cond1,
BUILTIN_SRCP, truth_not_expr_K);
522 const auto created_stmt =
524 cond1 = GetPointer<const gimple_assign>(
GET_CONST_NODE(created_stmt))->op0;
526 list_of_bloc.at(bb1)->PushBack(created_stmt,
AppM);
529 THROW_ASSERT(list_of_bloc.at(bb2)->CGetPhiList().size() == 0,
"not expected phi nodes");
533 const auto second_stmt = list_of_stmt_cond2.front();
535 auto ce2 = GetPointer<gimple_cond>(
GET_NODE(second_stmt));
536 auto cond2 = ce2->op0;
539 const auto cond2_created_stmt =
541 cond2 = GetPointer<const gimple_assign>(
GET_CONST_NODE(cond2_created_stmt))->op0;
543 list_of_bloc.at(bb1)->PushBack(cond2_created_stmt,
AppM);
548 list_of_bloc.at(bb2)->RemoveStmt(second_stmt,
AppM);
551 (or_type ? truth_or_expr_K : truth_and_expr_K));
554 list_of_bloc.at(bb2)->PushBack(second_stmt,
AppM);
557 while(list_of_stmt_cond1.size())
559 const auto stmt = list_of_stmt_cond1.back();
560 list_of_bloc.at(bb1)->RemoveStmt(stmt,
AppM);
561 list_of_bloc.at(bb2)->PushFront(stmt,
AppM);
565 const auto& bb1_phi_list = list_of_bloc.at(bb1)->CGetPhiList();
566 while(bb1_phi_list.size())
568 const auto phi = bb1_phi_list.back();
569 list_of_bloc.at(bb1)->RemovePhi(
phi);
570 list_of_bloc.at(bb2)->AddPhi(
phi);
579 std::map<unsigned int, blocRef>& list_of_bloc)
582 std::vector<unsigned int>::iterator pos;
583 for(
const auto& bb1_pred : list_of_bloc.at(bb1)->list_of_pred)
585 list_of_bloc.at(bb2)->list_of_pred.push_back(bb1_pred);
586 pos = std::find(list_of_bloc.at(bb1_pred)->list_of_succ.begin(), list_of_bloc.at(bb1_pred)->list_of_succ.end(),
589 if(list_of_bloc.at(bb1_pred)->true_edge == bb1)
591 list_of_bloc.at(bb1_pred)->true_edge = bb2;
593 else if(list_of_bloc.at(bb1_pred)->false_edge == bb1)
595 list_of_bloc.at(bb1_pred)->false_edge = bb2;
598 pos = std::find(list_of_bloc.at(bb2)->list_of_pred.begin(), list_of_bloc.at(bb2)->list_of_pred.end(), bb1);
599 list_of_bloc.at(bb2)->list_of_pred.erase(pos);
601 pos = std::find(list_of_bloc.at(merging_candidate)->list_of_pred.begin(),
602 list_of_bloc.at(merging_candidate)->list_of_pred.end(), bb1);
603 list_of_bloc.at(merging_candidate)->list_of_pred.erase(pos);
606 for(
const auto& pred : list_of_bloc.at(bb1)->list_of_pred)
608 const auto list_of_pred_stmt = list_of_bloc.at(pred)->CGetStmtList();
609 const auto cond_statement =
610 list_of_pred_stmt.begin() != list_of_pred_stmt.end() ? list_of_pred_stmt.back() :
tree_nodeRef();
611 const auto cond_statement_node = cond_statement ?
GET_NODE(cond_statement) : cond_statement;
612 if(cond_statement_node && GetPointer<gimple_multi_way_if>(cond_statement_node))
614 const auto gmwi = GetPointerS<gimple_multi_way_if>(cond_statement_node);
615 for(
auto& cond : gmwi->list_of_cond)
617 if(cond.second == bb1)
624 list_of_bloc.erase(bb1);
629 for(
const auto&
phi : list_of_bloc.at(curr_bb)->CGetPhiList())
632 if(cb_phi->virtual_flag)
650 if(GetPointer<const HLS_manager>(
AppM) and GetPointer<const HLS_manager>(
AppM)->get_HLS(
function_id) and
660 design_flow_graph->CGetDesignFlowStepInfo(update_schedule)->design_flow_step;
661 if(GetPointer<const FunctionFrontendFlowStep>(design_flow_step)->
CGetBBVersion() !=
#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;.
File containing functions and utilities to support the printing of debug messagges.
#define PRINT_DBG_MEX(dbgLevel, curDbgLevel, mex)
We are producing a debug version of the program, so the message is printed;.
#define DEBUG_LEVEL_PEDANTIC
very verbose debugging print is performed.
Step successfully executed.
#define GET_CLASS(obj)
Macro returning the actual type of an object.
Analysis step rebuilding a short circuit in a single gimple_cond with the condition in three address ...
Definition of the class representing a generic C application.
std::string GetName() const override
Return the name of this design step.
RelationshipType
The relationship type.
Source must be executed to satisfy target.
A simple interface to token object of the raw files.
Analysis step that optimize the phis starting from the IR.
static const unsigned int EXIT_BLOCK_ID
constant identifying the exit basic block
bool HasToBeExecuted() const override
Check if this step has actually to be executed.
Data structure describing a basic block at tree level.
#define STR(s)
Macro which performs a lexical_cast to a string.
Auxiliary methods for manipulating string.
bool HasToBeExecuted() const override
Check if this step has actually to be executed.
std::string ToString(ActorGraphBackend_Type actor_graph_backend_type)
Header include.
#define THROW_UNREACHABLE(str_expr)
helper function used to specify that some points should never be reached
static bool IsBooleanType(const tree_nodeConstRef &type)
Return true if the treenode is of bool type.
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.
void WriteBBGraphDot(const std::string &filename) const
Write the current version of statement list in dot format.
Classes to describe design flow graph.
Target must be reexecuted.
std::pair< tree_nodeRef, unsigned int > DefEdge
The type of the def edge.
redefinition of set to manage ordered/unordered structures
bool check_phis(unsigned int curr_bb, const std::map< unsigned int, blocRef > &list_of_bloc)
check if phi could create problem to the short circuit collapsing
Factory for technology flow step.
const Wrefcount< const DesignFlowManager > design_flow_manager
The design flow manager.
unsigned int CGetBBVersion() const
#define GET_CONST_NODE(t)
refcount< const tree_node > tree_nodeConstRef
DesignFlowStep_Status GetStatus() const
Return the status of this design step.
Classes specification of the tree_node data structures.
~short_circuit_taf() override
Destructor.
const ParameterConstRef parameters
Set of input parameters.
DesignFlowStep_Status
The status of a step.
void restructure_CFG(unsigned int bb1, unsigned int bb2, unsigned int merging_candidate, std::map< unsigned int, blocRef > &list_of_bloc)
restructure the CFG eliminating all BBs not needed after short circuit collapsing ...
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 file collects some utility functions.
DesignFlowStep_Status InternalExec() override
Restructures the unstructured code.
refcount< T > lock() const
const unsigned int function_id
The index of the function to be analyzed.
const application_managerRef AppM
The application manager.
struct definition of the type node structures.
Class specification of the tree_reindex support class.
static const unsigned int ENTRY_BLOCK_ID
constant identifying the entry basic block
bool check_merging_candidate(unsigned int &bb1, unsigned int &bb2, unsigned int merging_candidate, bool &bb1_true, bool &bb2_true, const std::map< unsigned int, blocRef > &list_of_bloc)
Check if a basic block is a merging BB for a short circuit.
void Initialize() override
Initialize the step (i.e., like a constructor, but executed just before exec.
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.
short_circuit_taf(const ParameterConstRef _Param, const application_managerRef _AppM, unsigned int function_id, const DesignFlowManagerConstRef design_flow_manager)
Constructor.
refcount< const tree_manipulation > tree_manipulationConstRef
Classes specification of the tree_node data structures not present in the gcc.
this class is used to manage the command-line or XML options.
refcount< tree_node > tree_nodeRef
RefCount type definition of the tree_node class structure.
static bool is_a_vector(const tree_managerConstRef &TM, const unsigned int index)
Return true if the treenode index is a vector.
int debug_level
The debug level.
#define GET_INDEX_CONST_NODE(t)
bool create_gimple_cond(unsigned int bb1, unsigned int bb2, bool bb1_true, const std::map< unsigned int, blocRef > &list_of_bloc, bool or_type, unsigned int merging_candidate)
create the or/and expression required by short circuit collapsing
Data structure definition for high-level synthesis flow.
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.
Base class for technology flow steps.
A brief description of the C++ Header File.
const FunctionBehaviorRef function_behavior
The function behavior of the function to be analyzed.
static const std::string ComputeSignature(const FrontendFlowStepType frontend_flow_step_type, const unsigned int function_id)
Compute the signature of a function frontend flow step.
#define THROW_ASSERT(cond, str_expr)
helper function used to check an assert and if needed to throw an error in a standard way ...