44 #pragma GCC diagnostic ignored "-Woverloaded-virtual" 99 unsigned int _function_id,
const DesignFlowManagerConstRef _design_flow_manager)
101 restart_ifmwi_opt(
false),
105 (
parameters->IsParameter(
"enable-conservative-sdc") &&
107 parameters->isOption(OPT_scheduling_algorithm) and
125 switch(relationship_type)
129 relationships.insert(std::make_pair(PREDICATE_STATEMENTS,
SAME_FUNCTION));
130 relationships.insert(std::make_pair(USE_COUNTING,
SAME_FUNCTION));
131 relationships.insert(std::make_pair(BLOCK_FIX,
SAME_FUNCTION));
132 relationships.insert(std::make_pair(SWITCH_FIX,
SAME_FUNCTION));
138 relationships.insert(std::make_pair(SDC_CODE_MOTION,
SAME_FUNCTION));
140 relationships.insert(std::make_pair(DEAD_CODE_ELIMINATION_IPA,
WHOLE_APPLICATION));
149 relationships.insert(std::make_pair(SHORT_CIRCUIT_TAF,
SAME_FUNCTION));
150 relationships.insert(std::make_pair(PHI_OPT,
SAME_FUNCTION));
151 relationships.insert(std::make_pair(MULTI_WAY_IF,
SAME_FUNCTION));
161 return relationships;
167 if(GetPointer<const HLS_manager>(
AppM) && GetPointer<const HLS_manager>(
AppM)->get_HLS(
function_id) &&
170 if(
parameters->isOption(OPT_scheduling_algorithm) &&
173 const auto TM =
AppM->get_tree_manager();
179 for(
const auto block : sl->list_of_bloc)
202 auto* ga = GetPointer<gimple_assign>(tn);
205 "-->Checking if " +
STR(ga->index) +
" - " + ga->ToString() +
" can be moved in BB" +
STR(bb_index));
207 if(!GetPointer<ssa_name>(left))
210 "<--No because of " + left->get_kind_text() +
" in left part");
214 if(
GET_NODE(ga->op1)->get_kind() == call_expr_K ||
GET_NODE(ga->op1)->get_kind() == aggr_init_expr_K)
224 if(
GET_NODE(ga->op0)->get_kind() == ssa_name_K &&
GET_NODE(ga->op1)->get_kind() == constructor_K)
229 if(
GET_NODE(ga->op0)->get_kind() == ssa_name_K &&
GET_NODE(ga->op1)->get_kind() == ssa_name_K)
238 if(rhs_ssa_uses.empty() && right->
get_kind() != call_expr_K && right->
get_kind() != aggr_init_expr_K &&
242 "<--Yes because there is not any use of ssa in right part");
266 case view_convert_expr_K:
290 auto* be = GetPointer<binary_expr>(right);
294 if(n_bit > 9 && !is_constant)
312 auto* te = GetPointer<ternary_expr>(right);
315 if(n_bit > 9 && !is_constant)
324 case mult_highpart_expr_K:
325 case widen_mult_expr_K:
332 auto* be = GetPointer<binary_expr>(right);
335 const auto ic = GetPointer<integer_cst>(
GET_NODE(be->op1));
339 if(!(v && !(v & (v - 1))))
356 "<--No because is a multiplication with non constant args");
361 auto* ne = GetPointer<nop_expr>(right);
366 if(is_realR || is_realL)
383 case truth_and_expr_K:
384 case truth_andif_expr_K:
385 case truth_or_expr_K:
386 case truth_orif_expr_K:
387 case truth_xor_expr_K:
389 case truth_not_expr_K:
404 case bit_ior_concat_expr_K:
409 case extractvalue_expr_K:
410 case insertvalue_expr_K:
411 case extract_bit_expr_K:
412 case extractelement_expr_K:
413 case insertelement_expr_K:
424 case pointer_plus_expr_K:
425 case postdecrement_expr_K:
426 case postincrement_expr_K:
427 case predecrement_expr_K:
428 case preincrement_expr_K:
429 case sat_plus_expr_K:
430 case sat_minus_expr_K:
444 auto* be = GetPointer<binary_expr>(right);
450 const bool is_gimple_cond_input = [&]()
452 const auto sn = GetPointer<const ssa_name>(left);
455 const auto use_stmts = sn->CGetUseStmts();
456 if(use_stmts.size() != 1)
458 const auto use_stmt = *(use_stmts.begin());
459 if(
GET_NODE(use_stmt.first)->get_kind() != gimple_cond_K)
464 if((n_bit > 9 && !is_constant && n_bit_min != 1) || n_bit > 16)
472 case ternary_plus_expr_K:
473 case ternary_pm_expr_K:
474 case ternary_mp_expr_K:
475 case ternary_mm_expr_K:
484 auto* be = GetPointer<ternary_expr>(right);
491 if((n_bit > 9 && !is_constant && n_bit_min != 1) || n_bit > 16)
501 auto* ne = GetPointer<negate_expr>(right);
504 if((n_bit > 9 && !is_constant) || n_bit > 16)
517 case exact_div_expr_K:
518 case trunc_div_expr_K:
519 case trunc_mod_expr_K:
521 auto* be = GetPointer<binary_expr>(right);
524 auto ic = GetPointer<integer_cst>(
GET_NODE(be->op1));
530 if(!(v && !(v & (v - 1))))
555 case ceil_div_expr_K:
556 case ceil_mod_expr_K:
558 case compound_expr_K:
559 case eh_filter_expr_K:
561 case floor_div_expr_K:
562 case floor_mod_expr_K:
563 case goto_subroutine_K:
570 case round_div_expr_K:
571 case round_mod_expr_K:
573 case try_catch_expr_K:
581 case unordered_expr_K:
582 case widen_sum_expr_K:
583 case with_size_expr_K:
584 case vec_lshift_expr_K:
585 case vec_rshift_expr_K:
586 case widen_mult_hi_expr_K:
587 case widen_mult_lo_expr_K:
588 case vec_pack_trunc_expr_K:
589 case vec_pack_sat_expr_K:
590 case vec_pack_fix_trunc_expr_K:
591 case vec_extracteven_expr_K:
592 case vec_extractodd_expr_K:
593 case vec_interleavehigh_expr_K:
594 case vec_interleavelow_expr_K:
599 case component_ref_K:
600 case bit_field_ref_K:
602 case with_cleanup_expr_K:
605 case vec_cond_expr_K:
606 case vec_perm_expr_K:
607 case dot_prod_expr_K:
609 case aggr_init_expr_K:
613 case case_label_expr_K:
614 case target_mem_ref_K:
617 case identifier_node_K:
619 case statement_list_K:
628 case cleanup_point_expr_K:
631 case fix_ceil_expr_K:
632 case fix_floor_expr_K:
633 case fix_round_expr_K:
634 case fix_trunc_expr_K:
635 case imagpart_expr_K:
637 case misaligned_indirect_ref_K:
639 case non_lvalue_expr_K:
640 case realpart_expr_K:
641 case reference_expr_K:
642 case reinterpret_cast_expr_K:
644 case static_cast_expr_K:
648 case reduc_max_expr_K:
649 case reduc_min_expr_K:
650 case reduc_plus_expr_K:
651 case vec_unpack_hi_expr_K:
652 case vec_unpack_lo_expr_K:
653 case vec_unpack_float_hi_expr_K:
654 case vec_unpack_float_lo_expr_K:
656 case target_mem_ref461_K:
674 const auto TM =
AppM->get_tree_manager();
675 bool modified =
false;
678 const auto fd = GetPointerS<const function_decl>(TM->CGetTreeNode(
function_id));
679 const auto sl = GetPointerS<const statement_list>(
GET_CONST_NODE(fd->body));
681 const auto isFunctionPipelined =
AppM->CGetFunctionBehavior(
function_id)->is_simple_pipeline();
690 const auto& list_of_bloc = sl->list_of_bloc;
691 for(
const auto&
block : list_of_bloc)
693 inverse_vertex_map[
block.first] =
695 direct_vertex_map[inverse_vertex_map[
block.first]] =
block.first;
698 for(
const auto& bbi_bb : list_of_bloc)
700 const auto& bbi = bbi_bb.first;
701 const auto& bb = bbi_bb.second;
702 for(
const auto& pred : bb->list_of_pred)
705 "BB" +
STR(pred) +
" (predecessor of " +
STR(bbi) +
") does not exist");
707 GCC_bb_graphs_collection->AddEdge(inverse_vertex_map.at(pred), inverse_vertex_map.at(bbi),
CFG_SELECTOR);
709 for(
const auto& succ : bb->list_of_succ)
713 GCC_bb_graphs_collection->AddEdge(inverse_vertex_map.at(bbi), inverse_vertex_map.at(succ),
CFG_SELECTOR);
716 if(bb->list_of_succ.empty())
718 GCC_bb_graphs_collection->AddEdge(inverse_vertex_map.at(bbi), inverse_vertex_map.at(
bloc::EXIT_BLOCK_ID),
728 std::list<vertex> bb_sorted_vertices;
732 (!
parameters->IsParameter(
"print-dot-FF") ||
parameters->GetParameter<
unsigned int>(
"print-dot-FF")))
734 GCC_bb_graph->
WriteDot(
"BB_simple_code_motion_" +
STR(counter) +
".dot");
736 "---Written BB_simple_code_motion_" +
STR(counter) +
".dot");
740 std::unique_ptr<dominance<BBGraph>> bb_dominators(
744 const auto& bb_dominator_map = bb_dominators->get_dominator_map();
752 for(
const auto&
block : list_of_bloc)
755 for(
const auto& statement :
block.second->CGetStmtList())
757 const auto* gp = GetPointer<const gimple_pragma>(
GET_NODE(statement));
758 if(gp && GetPointer<const omp_pragma>(
GET_NODE(gp->scope)) &&
759 GetPointer<const omp_simd_pragma>(
GET_NODE(gp->directive)))
761 THROW_ASSERT(boost::out_degree(inverse_vertex_map[
block.first], *GCC_bb_graph) == 1,
762 "OpenMP simd pragma block has more than one successor");
765 boost::tie(oe, oe_end) = boost::out_edges(inverse_vertex_map[
block.first], *GCC_bb_graph);
781 for(
const auto simd_loop_header : simd_loop_headers)
784 const auto loop_id = list_of_bloc.at(direct_vertex_map[simd_loop_header)]->loop_id;
786 std::list<vertex> to_be_processed;
788 for(boost::tie(ie, ie_end) = boost::in_edges(simd_loop_header, *GCC_bb_graph); ie != ie_end; ie++)
790 const vertex source = boost::source(*ie, *GCC_bb_graph);
792 if(list_of_bloc.at(direct_vertex_map[source)]->loop_id >= loop_id)
794 to_be_processed.push_front(source);
797 while(to_be_processed.size())
799 vertex current = to_be_processed.front();
800 to_be_processed.pop_front();
801 already_processed.insert(current);
802 return_value.insert(current);
804 for(boost::tie(ie, ie_end) = boost::in_edges(current, *GCC_bb_graph); ie != ie_end; ie++)
806 const vertex source = boost::source(*ie, *GCC_bb_graph);
807 if(already_processed.find(source) != already_processed.end() or current == simd_loop_header)
811 const auto source_loop_id = list_of_bloc.at(direct_vertex_map[source)]->loop_id;
813 if(source_loop_id > loop_id)
814 to_be_processed.push_front(source);
816 to_be_processed.push_back(source);
829 for(
const auto bb_vertex : bb_sorted_vertices)
831 const auto curr_bb = direct_vertex_map.at(bb_vertex);
832 bool parallel_bb = to_be_parallelized.find(bb_vertex) != to_be_parallelized.end();
842 bool have_multi_way_if_pred =
false;
844 for(
const auto pred : list_of_bloc.at(curr_bb)->list_of_pred)
846 if(!list_of_bloc.at(pred)->list_of_stmt.empty())
849 if(GetPointer<gimple_multi_way_if>(last))
850 have_multi_way_if_pred =
true;
853 if(have_multi_way_if_pred)
857 "-->Analyzing BB" +
STR(curr_bb) + (parallel_bb ?
"(Parallel)" :
""));
858 bool restart_bb_code_motion =
false;
862 (!
parameters->IsParameter(
"print-dot-FF") ||
parameters->GetParameter<
unsigned int>(
"print-dot-FF")))
864 GCC_bb_graph->
WriteDot(
"BB_simple_code_motion_" +
STR(counter) +
".dot");
866 "---Written BB_simple_code_motion_" +
STR(counter) +
".dot");
869 const auto& list_of_stmt = list_of_bloc.at(curr_bb)->CGetStmtList();
870 std::list<tree_nodeRef> to_be_removed;
872 std::list<tree_nodeRef> to_be_added_back;
873 std::list<tree_nodeRef> to_be_added_front;
875 for(
auto statement = list_of_stmt.begin(); statement != list_of_stmt.end(); statement++)
880 auto* gn = GetPointer<gimple_node>(tn);
883 if(!isFunctionPipelined && !parallel_bb && gn->vdef)
890 if(!GetPointer<gimple_assign>(tn) && !GetPointer<gimple_nop>(tn))
899 for(
const auto& vo : gn->vovers)
907 for(
auto stmt0 = list_of_stmt.begin(); stmt0 != list_of_stmt.end() && *stmt0 != *statement && gn->vdef;
911 const auto gn0 = GetPointerS<gimple_node>(tn0);
912 if(gn0->vuses.find(gn->vdef) != gn0->vuses.end())
914 BB_def.insert(curr_bb);
918 const auto ssu_it_end = stmt_ssa_uses.cend();
919 for(
auto ssu_it = stmt_ssa_uses.cbegin(); ssu_it != ssu_it_end; ++ssu_it)
921 const auto sn = *ssu_it;
923 for(
auto const& def_stmt : sn->CGetDefStmts())
925 auto* def_gn = GetPointer<gimple_node>(
GET_NODE(def_stmt));
926 THROW_ASSERT(def_gn->get_kind() == gimple_nop_K or def_gn->index,
927 sn->ToString() +
" is defined in entry");
929 (def_gn->get_kind() == gimple_assign_K &&
930 GetPointer<const gimple_assign>(
GET_NODE(def_stmt))->clobber) or
931 def_gn->bb_index or sn->virtual_flag,
932 "Definition " + def_gn->ToString() +
" of " + sn->ToString() +
" is in BB" +
933 STR(def_gn->bb_index));
934 if(statement == list_of_stmt.begin() && list_of_bloc.at(curr_bb)->list_of_pred.size() == 1 &&
935 def_gn->bb_index == curr_bb && def_gn->get_kind() != gimple_phi_K)
939 "--- no constraint because is the first one");
944 "--- Adding BB" +
STR(def_gn->bb_index) +
" because of " + def_gn->ToString());
945 BB_def.insert(def_gn->bb_index);
950 if(BB_def.find(curr_bb) != BB_def.end())
953 bool can_be_pipelined = list_of_bloc.at(curr_bb)->loop_id != 0;
954 const auto Lop_it_end = list_of_bloc.at(curr_bb)->list_of_pred.end();
955 for(
auto Lop_it = list_of_bloc.at(curr_bb)->list_of_pred.begin();
956 Lop_it != Lop_it_end && can_be_pipelined; ++Lop_it)
958 can_be_pipelined = list_of_bloc.at(curr_bb)->loop_id >= list_of_bloc.at(*Lop_it)->loop_id;
961 bool zero_delay =
true;
962 if(can_be_pipelined && (gn->vuses.size() ||
CheckMovable(curr_bb, tn, zero_delay, TM) ==
965 THROW_ASSERT(bb_dominator_map.find(bb_vertex) != bb_dominator_map.end(),
"unexpected condition");
968 "<--Skipped because uses ssa defined in the same block");
971 if((gn->vuses.size() || (GetPointer<gimple_assign>(tn) &&
972 (
GET_NODE(GetPointer<gimple_assign>(tn)->op1)->get_kind() == call_expr_K ||
973 GET_NODE(GetPointer<gimple_assign>(tn)->op1)->get_kind() == mem_ref_K))) &&
974 !isFunctionPipelined && !parallel_bb)
981 auto dest_bb_index = curr_bb;
982 auto prev_dest_bb_index = curr_bb;
983 if(gn->vdef || gn->vuses.size() ||
984 (tn->get_kind() == gimple_assign_K &&
985 GET_NODE(GetPointer<gimple_assign>(tn)->op1)->get_kind() == mem_ref_K))
987 if(list_of_bloc.at(curr_bb)->list_of_pred.size() == 1 &&
989 ((tn->get_kind() == gimple_assign_K &&
990 (
GET_NODE(GetPointer<gimple_assign>(tn)->op0)->get_kind() == mem_ref_K ||
991 GET_NODE(GetPointer<gimple_assign>(tn)->op1)->get_kind() == mem_ref_K)) ||
992 tn->get_kind() == gimple_nop_K) &&
993 list_of_bloc.at(list_of_bloc.at(curr_bb)->list_of_pred.front())->loop_id ==
994 list_of_bloc.at(curr_bb)->loop_id)
996 dest_bb_index = list_of_bloc.at(curr_bb)->list_of_pred.front();
1001 "<--Skipped because is not a store/load or because we do not know the condition under " 1002 "which the store/load is done");
1009 vertex dom_bb = bb_vertex;
1010 if(bb_dominator_map.find(dom_bb) != bb_dominator_map.end())
1012 dom_bb = bb_dominator_map.find(dom_bb)->second;
1014 "---Considering its dominator BB" +
STR(direct_vertex_map[dom_bb]));
1015 auto dom_bb_index = direct_vertex_map[dom_bb];
1018 unsigned loop_idU = list_of_bloc.at(dom_bb_index)->loop_id;
1019 unsigned loop_idC = list_of_bloc.at(curr_bb)->loop_id;
1020 if(loop_idC >= loop_idU)
1022 prev_dest_bb_index = dest_bb_index;
1023 dest_bb_index = dom_bb_index;
1024 bool internLoopDep =
false;
1025 for(
auto BBdef : BB_def)
1027 if(list_of_bloc.at(BBdef)->loop_id > loop_idU && list_of_bloc.at(BBdef)->loop_id <= loop_idC)
1029 internLoopDep =
true;
1035 "---the statement depends on values defined at inner level than dest BB" +
1036 STR(dest_bb_index));
1037 dest_bb_index = curr_bb;
1041 "---Going up one level. Considering now BB" +
STR(dest_bb_index));
1043 if(BB_def.find(dom_bb_index) != BB_def.end())
1046 "---It contains the definition of one SSA used by the statement to be moved");
1049 if(bb_dominator_map.find(dom_bb) == bb_dominator_map.end())
1053 dom_bb = bb_dominator_map.find(dom_bb)->second;
1054 dom_bb_index = direct_vertex_map[dom_bb];
1061 if(dest_bb_index == curr_bb)
1064 "<--Skipped (1) because destination would be the same bb");
1068 bool is_controlling_condition_constant =
true;
1069 const auto Lop_it_end = list_of_bloc.at(curr_bb)->list_of_pred.end();
1070 for(
auto Lop_it = list_of_bloc.at(curr_bb)->list_of_pred.begin();
1071 Lop_it != Lop_it_end && is_controlling_condition_constant; ++Lop_it)
1073 if(sl->list_of_bloc.at(*Lop_it)->CGetStmtList().empty())
1075 is_controlling_condition_constant =
false;
1079 auto last_statement = sl->list_of_bloc.at(*Lop_it)->CGetStmtList().back();
1080 if(
GET_NODE(last_statement)->get_kind() == gimple_cond_K)
1082 auto* gc = GetPointer<gimple_cond>(
GET_NODE(last_statement));
1083 if(
GET_NODE(gc->op0)->get_kind() != integer_cst_K)
1085 is_controlling_condition_constant =
false;
1088 else if(
GET_NODE(last_statement)->get_kind() == gimple_multi_way_if_K)
1090 is_controlling_condition_constant =
false;
1094 is_controlling_condition_constant =
false;
1098 bool zero_delay =
true;
1099 auto check_movable =
CheckMovable(dest_bb_index, tn, zero_delay, TM);
1109 if(!
AppM->ApplyNewTransformation())
1112 "<--Skipped because reached limit of CFG transformations");
1119 bool only_phis =
true;
1120 for(
const auto sn : stmt_ssa_uses)
1123 for(
auto const& def_stmt : sn->CGetDefStmts())
1125 auto* def_gn = GetPointer<gimple_node>(
GET_NODE(def_stmt));
1127 if(def_gn->bb_index == dest_bb_index && def_gn->get_kind() != gimple_phi_K &&
1128 zero_delay_stmts.find(def_stmt->index) == zero_delay_stmts.end())
1136 if(only_phis && zero_delay)
1143 "---Going down of one level because of non-zero delay");
1144 dest_bb_index = prev_dest_bb_index;
1148 if(dest_bb_index == curr_bb)
1151 "<--Skipped (2) because destination would be the same bb");
1155 AppM->RegisterTransformation(
GetName(), *statement);
1158 if(tn->get_kind() == gimple_assign_K &&
1159 (
GET_NODE(GetPointer<gimple_assign>(tn)->op0)->get_kind() == mem_ref_K ||
1160 GET_NODE(GetPointer<gimple_assign>(tn)->op1)->get_kind() == mem_ref_K))
1162 if(list_of_bloc.at(dest_bb_index)->CGetStmtList().empty())
1168 const auto& lastStmt = *(list_of_bloc.at(dest_bb_index)->CGetStmtList().rbegin());
1169 auto lastStmtNode =
GET_NODE(lastStmt);
1170 auto ga = GetPointer<gimple_assign>(tn);
1171 if(lastStmtNode->get_kind() == gimple_cond_K)
1173 if(ga->predicate &&
GET_NODE(ga->predicate)->get_kind() == integer_cst_K)
1178 if(list_of_bloc.at(dest_bb_index)->true_edge == curr_bb)
1180 TM->ReplaceTreeNode(*statement, ga->predicate,
1181 GetPointer<gimple_cond>(lastStmtNode)->op0);
1186 auto not_cond = tree_man->CreateNotExpr(GetPointer<gimple_cond>(lastStmtNode)->op0,
1188 TM->ReplaceTreeNode(*statement, ga->predicate, not_cond);
1194 if(list_of_bloc.at(dest_bb_index)->true_edge == curr_bb)
1197 tree_man->CreateAndExpr(GetPointer<gimple_cond>(lastStmtNode)->op0, ga->predicate,
1199 TM->ReplaceTreeNode(*statement, ga->predicate, and_cond);
1203 auto not_cond = tree_man->CreateNotExpr(GetPointer<gimple_cond>(lastStmtNode)->op0,
1205 auto and_cond = tree_man->CreateAndExpr(not_cond, ga->predicate,
1207 TM->ReplaceTreeNode(*statement, ga->predicate, and_cond);
1211 else if(lastStmtNode->get_kind() == gimple_multi_way_if_K)
1213 auto gmwi = GetPointer<gimple_multi_way_if>(lastStmtNode);
1214 bool found_condition =
false;
1215 for(
const auto& gmwicond : gmwi->list_of_cond)
1217 if(gmwicond.second == curr_bb)
1219 found_condition =
true;
1223 auto firstCond =
true;
1225 for(
const auto& gmwicond0 : gmwi->list_of_cond)
1231 Cur = gmwicond0.first;
1236 Cur = tree_man->CreateOrExpr(Cur, gmwicond0.first,
1241 Cur = tree_man->CreateNotExpr(Cur, list_of_bloc.at(dest_bb_index),
function_id);
1242 if(ga->predicate &&
GET_NODE(ga->predicate)->get_kind() == integer_cst_K)
1247 TM->ReplaceTreeNode(*statement, ga->predicate, Cur);
1252 auto and_cond = tree_man->CreateAndExpr(Cur, ga->predicate,
1254 TM->ReplaceTreeNode(*statement, ga->predicate, and_cond);
1259 if(ga->predicate &&
GET_NODE(ga->predicate)->get_kind() == integer_cst_K)
1264 TM->ReplaceTreeNode(*statement, ga->predicate, gmwicond.first);
1269 auto and_cond = tree_man->CreateAndExpr(gmwicond.first, ga->predicate,
1271 TM->ReplaceTreeNode(*statement, ga->predicate, and_cond);
1277 if(!found_condition)
1279 THROW_ERROR(
"node not supported: " + lastStmtNode->get_kind_text() +
" " +
1280 lastStmtNode->ToString());
1283 else if(list_of_bloc.at(dest_bb_index)->list_of_succ.size() == 1 &&
1284 list_of_bloc.at(dest_bb_index)->loop_id == list_of_bloc.at(curr_bb)->loop_id)
1290 THROW_ERROR(
"node not supported: " + lastStmtNode->get_kind_text() +
" " +
1291 lastStmtNode->ToString());
1295 const auto temp_statement = *statement;
1297 auto tmp_it = statement;
1300 list_of_bloc.at(curr_bb)->RemoveStmt(temp_statement,
AppM);
1301 if(list_of_bloc.at(curr_bb)->CGetStmtList().empty() && list_of_bloc.at(curr_bb)->CGetPhiList().empty())
1305 list_of_bloc.at(dest_bb_index)->PushBack(temp_statement,
AppM);
1312 for(
const auto& removing : to_be_removed)
1315 "---Removing " + removing->ToString() +
" from BB" +
STR(curr_bb));
1316 list_of_bloc.at(curr_bb)->RemoveStmt(removing,
AppM);
1318 if(!to_be_removed.empty() && list_of_bloc.at(curr_bb)->CGetStmtList().empty() &&
1319 list_of_bloc.at(curr_bb)->CGetPhiList().empty())
1323 for(
const auto& adding_back : to_be_added_back)
1326 "---Adding back " + adding_back->ToString() +
" from BB" +
STR(curr_bb));
1327 list_of_bloc.at(curr_bb)->PushBack(adding_back,
AppM);
1329 for(
const auto& adding_front : to_be_added_front)
1332 "---Adding front " + adding_front->ToString() +
" from BB" +
STR(curr_bb));
1333 list_of_bloc.at(curr_bb)->PushFront(adding_front,
AppM);
1335 restart_bb_code_motion = (!to_be_added_back.empty()) or (!to_be_added_front.empty());
1337 (!
parameters->IsParameter(
"print-dot-FF") ||
parameters->GetParameter<
unsigned int>(
"print-dot-FF")))
1339 GCC_bb_graph->
WriteDot(
"BB_simple_code_motion_" +
STR(counter) +
".dot");
1341 "---Written BB_simple_code_motion_" +
STR(counter) +
".dot");
1344 if(restart_bb_code_motion)
1347 "---Restart Analyzing BB" +
STR(curr_bb) + (parallel_bb ?
"(Parallel)" :
""));
1349 }
while(restart_bb_code_motion);
#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;.
boost::graph_traits< graph >::out_edge_iterator OutEdgeIterator
out_edge_iterator definition.
File containing functions and utilities to support the printing of debug messagges.
Step successfully executed.
static bool IsConstant(const tree_nodeConstRef &node)
Return if a tree node is a constant object.
Definition of the node_info object for the basic_block graph.
#define GET_CLASS(obj)
Macro returning the actual type of an object.
Operation cannot be moved.
This struct specifies the statement_list node.
Definition of the class representing a generic C application.
#define CASE_DECL_NODES
NOTE that cast_expr is a unary expression but it could not be included in the CASE_UNARY_EXPRESSION b...
std::string GetName() const override
Return the name of this design step.
static bool is_real(const tree_managerConstRef &TM, const unsigned int index)
Return true if the treenode is of real type.
void WriteDot(const std::string &file_name, const int detail_level=0) const
Writes this graph in dot format.
ScheduleRef schedule
The scheduling solution.
RelationshipType
The relationship type.
struct definition of the function_decl tree node.
Source must be executed to satisfy target.
mathematical utility function not provided by standard libraries
boost::graph_traits< graph >::in_edge_iterator InEdgeIterator
in_edge_iterator definition.
A simple interface to token object of the raw files.
static const unsigned int EXIT_BLOCK_ID
constant identifying the exit basic block
DesignFlowStep_Status InternalExec() override
Updates the tree to have a more compliant CFG.
#define GET_INDEX_NODE(t)
Macro used to hide implementation details when accessing a tree_node from another tree_node...
Data structure describing a basic block at tree level.
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.
~simple_code_motion() override
Destructor.
FunctionFrontendFlowStep_Movable CheckMovable(const unsigned int dest_bb_index, tree_nodeRef tn, bool &zero_delay, const tree_managerRef TM)
Check if a statement can be moved in a basic block.
virtual enum kind get_kind() const =0
Virtual function returning the type of the actual class.
#define STR(s)
Macro which performs a lexical_cast to a string.
Auxiliary methods for manipulating string.
bool conservative
True if only zero delay statement can be moved.
#define THROW_UNREACHABLE(str_expr)
helper function used to specify that some points should never be reached
virtual std::string get_kind_text() const =0
Virtual function returning the name of the actual class.
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.
absl::flat_hash_map< T, U, Hash, Eq, Alloc > CustomUnorderedMap
Data structure used to store the schedule of the operations.
static void compute_ssa_uses_rec_ptr(const tree_nodeConstRef &tn, CustomOrderedSet< const ssa_name *> &ssa_uses)
recursively compute the pointers to the ssa_name variables used in a statement
#define CASE_QUATERNARY_EXPRESSION
This macro collects all case labels for quaternary_expr objects.
FunctionFrontendFlowStep_Movable CanBeMoved(const unsigned int statement_index, const unsigned int basic_block) const
Check if a statement can be moved at the end of a basic block.
void cyclic_topological_sort(VertexListGraph &g, OutputIterator result, const boost::bgl_named_params< P, T, R > ¶ms)
refcount< BBNodeInfo > BBNodeInfoRef
refcount definition of the class
Information associated with the whole basic-block graph.
Classes to describe design flow graph.
tree_nodeRef body
body field is the saved representation of the body of the entire function.
Target must be reexecuted.
boost::graph_traits< graph >::vertex_descriptor vertex
vertex definition.
#define GET_CONST_NODE(t)
DesignFlowStep_Status GetStatus() const
Return the status of this design step.
Classes specification of the tree_node data structures.
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.
#define THROW_ERROR(str_expr)
helper function used to throw an error in a standard way
This struct specifies the block node.
#define CASE_TYPE_NODES
This macro collects all case labels for type objects.
This file collects some utility functions.
FunctionFrontendFlowStep_Movable
Enum class used to specify if a statement can be moved.
const unsigned int function_id
The index of the function to be analyzed.
Analysis step that performs some simple code motions over the IR.
#define CASE_CST_NODES
This macro collects all case labels for cast nodes.
const application_managerRef AppM
The application manager.
Class specification of the tree_reindex support class.
static const unsigned int ENTRY_BLOCK_ID
constant identifying the entry basic block
#define CASE_FAKE_NODES
This macro collects all case labels for fake or empty nodes.
File used to compute the topological sort in a cyclic graph.
Class specification of the basic_block structure.
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.
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.
#define CASE_CPP_NODES
This macro collects all case labels for cpp nodes.
bool IsScheduleBased() const
Return true if the last run of this step was based on scheduling.
unsigned counter[N_THREADS]
simple_code_motion(const ParameterConstRef parameters, const application_managerRef AppM, unsigned int function_id, const DesignFlowManagerConstRef design_flow_manager)
Constructor.
#define CASE_GIMPLE_NODES
This macro collects all cases labels for gimple nodes.
static integer_cst_t GetConstValue(const tree_nodeConstRef &tn, bool is_signed=true)
Get value from integer constant.
int debug_level
The debug level.
static bool is_constant(const tree_managerConstRef &TM, const unsigned int index)
Return if a tree node is a constant object.
#define CFG_SELECTOR
Control flow graph edge selector.
Data structure definition for high-level synthesis flow.
Operation cannot be moved because of timing.
refcount< BBGraphInfo > BBGraphInfoRef
refcount definition of the class
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.
static bool IsRealType(const tree_nodeConstRef &type)
Return true if the treenode is of real type.
const FunctionBehaviorRef function_behavior
The function behavior of the function to be analyzed.
#define CASE_PRAGMA_NODES
This macro collects all case labels for pragma objects.
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 ...