69 #include <boost/range/adaptor/reversed.hpp> 74 const DesignFlowManagerConstRef _design_flow_manager,
const ParameterConstRef _parameters)
86 switch(relationship_type)
90 relationships.insert(std::make_pair(BLOCK_FIX,
SAME_FUNCTION));
91 relationships.insert(std::make_pair(MULTI_WAY_IF,
SAME_FUNCTION));
92 relationships.insert(std::make_pair(SHORT_CIRCUIT_TAF,
SAME_FUNCTION));
93 relationships.insert(std::make_pair(SWITCH_FIX,
SAME_FUNCTION));
94 relationships.insert(std::make_pair(USE_COUNTING,
SAME_FUNCTION));
110 return relationships;
116 TM =
AppM->get_tree_manager();
119 sl = GetPointerS<statement_list>(
GET_NODE(fd->body));
122 GetPointer<const HLS_manager>(
AppM) && GetPointer<const HLS_manager>(
AppM)->get_HLS(
function_id) and
141 std::list<tree_nodeRef> phis_to_be_removed;
142 for(
const auto&
phi :
block.second->CGetPhiList())
145 const auto sn = GetPointer<const ssa_name>(
GET_CONST_NODE(gp->res));
146 if(sn->CGetUseStmts().empty())
148 phis_to_be_removed.push_back(
phi);
151 for(
const auto&
phi : phis_to_be_removed)
153 if(
AppM->ApplyNewTransformation())
164 auto removePhiOnly = [&]() {
171 if(
block.second->list_of_pred.size() >= 2 &&
block.second->CGetPhiList().size() &&
172 block.second->CGetStmtList().empty())
174 const auto successor =
block.second->list_of_succ.front();
178 const bool common_predecessor = [&]() {
179 for(
auto predecessor :
block.second->list_of_pred)
181 if(std::find(succ_block->list_of_pred.begin(), succ_block->list_of_pred.end(), predecessor) !=
182 succ_block->list_of_pred.end())
189 if(common_predecessor)
196 const bool only_phi_use = [&]() {
198 for(
const auto&
phi :
block.second->CGetPhiList())
201 const auto sn = GetPointer<const ssa_name>(
GET_CONST_NODE(gp->res));
202 for(
const auto& use : sn->CGetUseStmts())
204 const auto gn = GetPointer<const gimple_node>(
GET_CONST_NODE(use.first));
205 if(gn->get_kind() != gimple_phi_K)
209 if(gn->bb_index != successor)
220 "<--Skipped because not used only in the second phi");
224 blocks_to_be_removed.insert(
block.first);
228 for(
auto block_to_be_removed : blocks_to_be_removed)
230 if(
AppM->ApplyNewTransformation())
235 (!
parameters->IsParameter(
"print-dot-FF") ||
parameters->GetParameter<
unsigned int>(
"print-dot-FF")))
239 "---Written BB_During_" +
GetName() +
"_AfterMerge_BB" +
STR(block_to_be_removed) +
252 if(
block.second->list_of_pred.size() == 1 &&
block.second->CGetPhiList().size())
254 if(
AppM->ApplyNewTransformation())
280 if(
block.second->list_of_succ.size() == 1)
282 const auto succ_block =
block.second->list_of_succ.front();
284 "Successor block BB" +
STR(succ_block) +
" does not exist");
287 if(
AppM->ApplyNewTransformation())
309 bool removePhiOnlyP =
false;
315 blocks_to_be_analyzed.insert(
block.first);
319 for(
auto bloc_to_be_analyzed : blocks_to_be_analyzed)
324 "-->Analyzing BB" +
STR(block->number) +
" Stmts= " +
STR(block->CGetStmtList().size()) +
325 " Phis=" +
STR(block->CGetPhiList().size()));
328 if(block->CGetStmtList().size() == 1 &&
329 GET_CONST_NODE(block->CGetStmtList().front())->get_kind() == gimple_nop_K)
331 block->RemoveStmt(block->CGetStmtList().front(),
AppM);
334 if(block->list_of_pred.size() >= 2 && block->CGetPhiList().size() && block->CGetStmtList().empty())
336 removePhiOnlyP =
true;
339 if(block->CGetStmtList().size() || block->CGetPhiList().size())
356 #if HAVE_PRAGMA_BUILT 357 if(
parameters->getOption<
int>(OPT_gcc_openmp_simd))
359 if(block->list_of_pred.size() == 1)
361 const auto pred_block_id = block->list_of_pred.front();
364 if(pred_block->loop_id != block->loop_id)
372 if(!
AppM->ApplyNewTransformation())
380 (!
parameters->IsParameter(
"print-dot-FF") ||
parameters->GetParameter<
unsigned int>(
"print-dot-FF")))
384 "---Written BB_Before_" +
GetName() +
"_Before_BB" +
STR(block->number) +
".dot");
466 for(
const auto& statement :
block.second->CGetStmtList())
468 const auto* ga = GetPointer<const gimple_assign>(
GET_CONST_NODE(statement));
471 const auto* ce = GetPointer<const cond_expr>(
GET_CONST_NODE(ga->op1));
472 if(ce && ce->op1->index == ce->op2->index)
474 ces_to_be_removed.insert(statement);
479 if(!ces_to_be_removed.empty())
483 for(
const auto& ce_to_be_removed : ces_to_be_removed)
503 if(
block.second->list_of_succ.size() == 1)
505 const auto succ_block =
block.second->list_of_succ.front();
507 "Successor block BB" +
STR(succ_block) +
" does not exist");
510 if(
AppM->ApplyNewTransformation())
529 for(
const auto& stmt :
block.second->CGetStmtList())
531 const auto gn = GetPointerS<gimple_node>(
GET_NODE(stmt));
532 if(gn->get_kind() != gimple_nop_K || !gn->vdef ||
533 (gn->vovers.find(gn->vdef) != gn->vovers.end() && gn->vovers.size() > 1) ||
534 (gn->vovers.find(gn->vdef) == gn->vovers.end() && (!gn->vovers.empty())))
536 if(gn->get_kind() == gimple_nop_K)
540 "---skipped gimple nop " +
STR(gn->index) + (!gn->vdef ?
"NOVDEF " :
"VDEF ") +
541 ((gn->vovers.find(gn->vdef) != gn->vovers.end() && gn->vovers.size() > 1) ?
"cond1 " :
543 ((gn->vovers.find(gn->vdef) == gn->vovers.end() && (!gn->vovers.empty())) ?
"cond2 " :
548 if(
AppM->ApplyNewTransformation())
550 const auto virtual_ssa = GetPointerS<ssa_name>(
GET_NODE(gn->vdef));
551 THROW_ASSERT(virtual_ssa && virtual_ssa->virtual_flag,
"unexpected condition");
554 if(gn->vuses.size() == 1)
556 const auto vuse = *(gn->vuses.begin());
557 const auto uses = virtual_ssa->CGetUseStmts();
558 for(
const auto& use : uses)
563 to_be_removeds.insert(stmt);
569 const auto canBeProp = [&]() ->
bool {
570 for(
const auto& use_stmt : virtual_ssa->CGetUseStmts())
586 "-->Virtual ssa " +
GET_CONST_NODE(gn->vdef)->ToString() +
" not used in any phi");
590 to_be_removeds.insert(stmt);
596 for(
const auto& to_be_removed : to_be_removeds)
598 block.second->RemoveStmt(to_be_removed,
AppM);
600 if(!to_be_removeds.empty())
615 const auto& succ_block =
sl->
list_of_bloc.at(curr_block->list_of_succ.front());
616 THROW_ASSERT(std::find(succ_block->list_of_pred.begin(), succ_block->list_of_pred.end(), bb_index) !=
617 succ_block->list_of_pred.end(),
618 "bb_index not included in the list of pred: " +
STR(bb_index) +
" succ: " +
STR(succ_block->number));
619 succ_block->list_of_pred.erase(
620 std::find(succ_block->list_of_pred.begin(), succ_block->list_of_pred.end(), bb_index));
624 for(
auto pred : curr_block->list_of_pred)
629 const auto new_basic_block_index = (
sl->
list_of_bloc.rbegin())->first + 1;
631 "-->Created BB" +
STR(new_basic_block_index) +
" as new successor of BB" +
STR(pred));
632 created_bbs.insert(new_basic_block_index);
633 const auto new_block = blocRef(
new bloc(new_basic_block_index));
636 new_block->loop_id = curr_block->loop_id;
637 new_block->SetSSAUsesComputed();
638 new_block->schedule = pred_block->schedule;
641 new_block->list_of_pred.push_back(pred);
644 new_block->list_of_succ.push_back(succ_block->number);
647 pred_block->list_of_succ.erase(
648 std::find(pred_block->list_of_succ.begin(), pred_block->list_of_succ.end(), bb_index));
649 pred_block->list_of_succ.push_back(new_basic_block_index);
650 if(pred_block->true_edge == bb_index)
652 pred_block->true_edge = new_basic_block_index;
654 if(pred_block->false_edge == bb_index)
656 pred_block->false_edge = new_basic_block_index;
660 succ_block->list_of_pred.push_back(new_basic_block_index);
663 if(pred_block->CGetStmtList().size())
665 auto pred_last_stmt =
GET_NODE(pred_block->CGetStmtList().back());
666 if(pred_last_stmt->get_kind() == gimple_multi_way_if_K)
668 const auto gmwi = GetPointerS<gimple_multi_way_if>(pred_last_stmt);
669 for(
auto& cond : gmwi->list_of_cond)
671 if(cond.second == curr_block->number)
673 cond.second = new_basic_block_index;
683 for(
const auto&
phi : succ_block->CGetPhiList())
685 const auto gp = GetPointerS<gimple_phi>(
GET_NODE(
phi));
689 for(
auto& def : gp->CGetDefEdgesList())
691 if(def.second != curr_block->number)
693 new_list_of_def_edge.push_back(def);
697 curr_value = def.first;
700 for(
auto pred : created_bbs)
702 new_list_of_def_edge.push_back(decltype(new_list_of_def_edge)::value_type(curr_value, pred));
704 gp->SetDefEdgeList(
TM, new_list_of_def_edge);
713 const auto& pred_block =
sl->
list_of_bloc.at(curr_block->list_of_pred.front());
714 const auto& succ_block =
sl->
list_of_bloc.at(curr_block->list_of_succ.front());
716 const auto pred_stmt_list = pred_block->CGetStmtList();
719 const auto true_edge = pred_block->true_edge == bb_index;
725 pred_block->RemoveStmt(pred_stmt_list.back(),
AppM);
729 for(
const auto&
phi : succ_block->CGetPhiList())
738 const auto gp = GetPointerS<gimple_phi>(
GET_NODE(
phi));
743 for(
const auto& def : gp->CGetDefEdgesList())
745 if((true_edge && bb_index == def.second) || (!true_edge && pred_block->number == def.second))
748 true_value = def.first;
750 else if((!true_edge && bb_index == def.second) || (true_edge && pred_block->number == def.second))
753 false_value = def.first;
769 const auto sn1 = GetPointerS<const ssa_name>(
GET_CONST_NODE(true_value));
770 const auto sn2 = GetPointerS<const ssa_name>(
GET_CONST_NODE(false_value));
771 if(sn1->var && sn2->var && sn1->var->index == sn2->var->index)
776 const auto gp_res = GetPointer<const ssa_name>(
GET_CONST_NODE(gp->res));
777 const auto ssa_node =
779 GetPointerS<ssa_name>(
GET_NODE(ssa_node))->bit_values = gp_res->bit_values;
783 std::map<TreeVocabularyTokenTypes_TokenEnum, std::string> gimple_nop_schema;
789 const auto gn = GetPointer<gimple_nop>(
GET_NODE(gimple_node));
790 gn->SetVdef(ssa_node);
791 gn->AddVuse(true_value);
792 gn->AddVuse(false_value);
799 const auto cond_expr_node =
801 (isAVectorType ? vec_cond_expr_K : cond_expr_K));
808 pred_block->PushBack(gimple_node,
AppM);
813 for(
const auto& def : gp->CGetDefEdgesList())
815 if(def.second == pred_block->number)
819 else if(def.second == bb_index)
825 new_list_of_def_edge.push_back(def);
828 gp->SetDefEdgeList(
TM, new_list_of_def_edge);
833 pred_block->list_of_succ.clear();
834 pred_block->true_edge = 0;
835 pred_block->false_edge = 0;
836 pred_block->list_of_succ.push_back(succ_block->number);
839 succ_block->list_of_pred.erase(
840 std::find(succ_block->list_of_pred.begin(), succ_block->list_of_pred.end(), bb_index));
850 const auto& pred_block =
sl->
list_of_bloc.at(curr_block->list_of_pred.front());
851 const auto& succ_block =
sl->
list_of_bloc.at(curr_block->list_of_succ.front());
852 for(
const auto&
phi : succ_block->CGetPhiList())
854 const auto gp = GetPointerS<gimple_phi>(
GET_NODE(
phi));
855 for(
auto& def_edge : gp->CGetDefEdgesList())
857 if(def_edge.second == curr_block->number)
866 if(pred_block->true_edge == bb_index)
868 pred_block->true_edge = succ_block->number;
870 else if(pred_block->false_edge == bb_index)
872 pred_block->false_edge = succ_block->number;
878 pred_block->list_of_succ.clear();
879 pred_block->list_of_succ.push_back(pred_block->true_edge);
880 pred_block->list_of_succ.push_back(pred_block->false_edge);
883 succ_block->list_of_pred.erase(
884 std::find(succ_block->list_of_pred.begin(), succ_block->list_of_pred.end(), bb_index));
885 succ_block->list_of_pred.push_back(pred_block->number);
896 const auto& pred_block =
sl->
list_of_bloc.at(curr_block->list_of_pred.front());
897 const auto& succ_block =
sl->
list_of_bloc.at(curr_block->list_of_succ.front());
898 for(
const auto&
phi : succ_block->CGetPhiList())
900 const auto gp = GetPointer<gimple_phi>(
GET_NODE(
phi));
901 for(
auto& def_edge : gp->CGetDefEdgesList())
903 if(def_edge.second == curr_block->number)
912 pred_block->list_of_succ.erase(
913 std::find(pred_block->list_of_succ.begin(), pred_block->list_of_succ.end(), bb_index));
914 pred_block->list_of_succ.push_back(succ_block->number);
917 succ_block->list_of_pred.erase(
918 std::find(succ_block->list_of_pred.begin(), succ_block->list_of_pred.end(), bb_index));
919 succ_block->list_of_pred.push_back(pred_block->number);
930 const auto& pred_block =
sl->
list_of_bloc.at(curr_block->list_of_pred.front());
931 const auto& succ_block =
sl->
list_of_bloc.at(curr_block->list_of_succ.front());
934 const auto true_edge = pred_block->true_edge == bb_index;
937 THROW_ASSERT(pred_block->CGetStmtList().size(),
"Statement list of predecessor is empty");
940 const auto last_stmt = pred_block->CGetStmtList().back();
942 pred_block->RemoveStmt(last_stmt,
AppM);
946 for(
const auto&
phi : succ_block->CGetPhiList())
955 const auto gp = GetPointerS<gimple_phi>(
GET_NODE(
phi));
960 for(
const auto& def_edge : gp->CGetDefEdgesList())
962 if((true_edge && bb_index == def_edge.second) || (!true_edge && pred_block->number == def_edge.second))
965 true_value = def_edge.first;
967 else if((!true_edge && bb_index == def_edge.second) || (true_edge && pred_block->number == def_edge.second))
969 THROW_ASSERT(!false_value,
"False value already found");
970 false_value = def_edge.first;
974 THROW_UNREACHABLE(std::string(true_edge ?
"BB is on the true edge" :
"BB is on the false edge") +
975 " - Condition comes from BB" +
STR(def_edge.second) +
" - If basic block is BB" +
976 STR((pred_block->number)));
988 const auto virtual_ssa = GetPointerS<ssa_name>(
GET_NODE(gp->res));
989 bool create_gimple_nop =
false;
990 for(
const auto& use_stmt : virtual_ssa->CGetUseStmts())
992 if(
GET_NODE(use_stmt.first)->get_kind() == gimple_phi_K)
994 create_gimple_nop =
true;
997 if(create_gimple_nop)
1001 std::map<TreeVocabularyTokenTypes_TokenEnum, std::string> gimple_nop_schema;
1006 const auto gn = GetPointerS<gimple_nop>(
TM->
GetTreeNode(gimple_node_id));
1007 gn->SetVdef(gp->res);
1008 gn->AddVuse(true_value);
1009 gn->AddVuse(false_value);
1016 for(
const auto& def_edge : gp->CGetDefEdgesList())
1018 new_ssas.insert(def_edge.first);
1029 const auto cond_expr_node =
1031 (isAVectorType ? vec_cond_expr_K : cond_expr_K));
1044 while(succ_block->CGetPhiList().size())
1046 succ_block->RemovePhi(succ_block->CGetPhiList().front());
1050 pred_block->list_of_succ.clear();
1051 pred_block->true_edge = 0;
1052 pred_block->false_edge = 0;
1053 pred_block->list_of_succ.push_back(succ_block->number);
1056 succ_block->list_of_pred.erase(
1057 std::find(succ_block->list_of_pred.begin(), succ_block->list_of_pred.end(), bb_index));
1068 const auto& pred_block =
sl->
list_of_bloc.at(curr_block->list_of_pred.front());
1069 const auto& succ_block =
sl->
list_of_bloc.at(curr_block->list_of_succ.front());
1071 auto& pred_stmt_list = pred_block->CGetStmtList();
1074 auto first_edge =
false;
1078 const auto gmwi = GetPointerS<gimple_multi_way_if>(
GET_NODE(pred_stmt_list.back()));
1081 pred_block->RemoveStmt(pred_stmt_list.back(),
AppM);
1084 auto first_condition = std::pair<tree_nodeRef, unsigned int>(
tree_nodeRef(), 0);
1087 auto second_condition = std::pair<tree_nodeRef, unsigned int>(
tree_nodeRef(), 0);
1089 for(
const auto& cond : gmwi->list_of_cond)
1091 if(cond.second == curr_block->number)
1093 if(!first_condition.first)
1095 first_condition = cond;
1100 second_condition = cond;
1104 else if(cond.second == succ_block->number)
1106 if(!first_condition.first)
1108 first_condition = cond;
1113 second_condition = cond;
1119 const auto new_cond = [&]() ->
unsigned int {
1120 if(second_condition.first)
1122 const auto new_node =
1124 return new_node->
index;
1132 decltype(gmwi->list_of_cond) new_list_of_cond;
1133 for(
const auto& cond : gmwi->list_of_cond)
1135 if(cond == first_condition)
1137 if(second_condition.first)
1146 else if(cond != second_condition)
1150 new_list_of_cond.push_front(cond);
1154 new_list_of_cond.push_back(cond);
1158 gmwi->list_of_cond = new_list_of_cond;
1162 for(
const auto&
phi : succ_block->CGetPhiList())
1176 for(
const auto& def_edge : gp->CGetDefEdgesList())
1178 if((first_edge && bb_index == def_edge.second) || (!first_edge && pred_block->number == def_edge.second))
1180 first_value = def_edge.first;
1182 else if((!first_edge && bb_index == def_edge.second) || (first_edge && pred_block->number == def_edge.second))
1184 second_value = def_edge.first;
1193 const auto sn1 = GetPointer<const ssa_name>(
GET_CONST_NODE(first_value));
1194 const auto sn2 = GetPointer<const ssa_name>(
GET_CONST_NODE(second_value));
1195 if(sn1->var && sn2->var && sn1->var->index == sn2->var->index)
1200 const auto gp_res = GetPointer<const ssa_name>(
GET_NODE(gp->res));
1201 const auto ssa_node =
1203 GetPointer<ssa_name>(
GET_NODE(ssa_node))->bit_values = gp_res->bit_values;
1205 if(gp->virtual_flag)
1208 std::map<TreeVocabularyTokenTypes_TokenEnum, std::string> gimple_nop_schema;
1215 gn->SetVdef(ssa_node);
1216 gn->AddVuse(first_value);
1217 gn->AddVuse(second_value);
1224 const auto cond_expr_node =
1226 BUILTIN_SRCP, (isAVectorType ? vec_cond_expr_K : cond_expr_K));
1235 for(
const auto& def_edge : gp->CGetDefEdgesList())
1237 if(def_edge.second == pred_block->number)
1241 else if(def_edge.second == bb_index)
1247 new_list_of_def_edge.push_back(def_edge);
1250 gp->SetDefEdgeList(
TM, new_list_of_def_edge);
1255 if(gmwi->list_of_cond.size() >= 2)
1261 pred_block->list_of_succ.erase(
1262 std::find(pred_block->list_of_succ.begin(), pred_block->list_of_succ.end(), bb_index));
1265 succ_block->list_of_pred.erase(
1266 std::find(succ_block->list_of_pred.begin(), succ_block->list_of_pred.end(), bb_index));
1277 const auto& pred_block =
sl->
list_of_bloc.at(curr_block->list_of_pred.front());
1278 const auto& succ_block =
sl->
list_of_bloc.at(curr_block->list_of_succ.front());
1280 THROW_ASSERT(
GET_NODE(pred_block->CGetStmtList().back())->get_kind() == gimple_multi_way_if_K,
"");
1281 const auto gmwi = GetPointerS<gimple_multi_way_if>(
GET_NODE(pred_block->CGetStmtList().back()));
1282 for(
auto& cond : gmwi->list_of_cond)
1284 if(cond.second == bb_index)
1286 cond.second = succ_block->number;
1291 for(
const auto&
phi : succ_block->CGetPhiList())
1293 const auto gp = GetPointerS<gimple_phi>(
GET_NODE(
phi));
1294 for(
auto& def_edge : gp->CGetDefEdgesList())
1296 if(def_edge.second == curr_block->number)
1305 pred_block->list_of_succ.erase(
1306 std::find(pred_block->list_of_succ.begin(), pred_block->list_of_succ.end(), bb_index));
1307 pred_block->list_of_succ.push_back(succ_block->number);
1310 succ_block->list_of_pred.erase(
1311 std::find(succ_block->list_of_pred.begin(), succ_block->list_of_pred.end(), bb_index));
1312 succ_block->list_of_pred.push_back(pred_block->number);
1323 const auto& pred_block =
sl->
list_of_bloc.at(curr_block->list_of_pred.front());
1324 const auto& succ_block =
sl->
list_of_bloc.at(curr_block->list_of_succ.front());
1326 const auto& pred_stmt_list = pred_block->CGetStmtList();
1329 auto first_edge =
false;
1333 const auto gmwi = GetPointerS<gimple_multi_way_if>(
GET_NODE(pred_stmt_list.back()));
1337 pred_block->RemoveStmt(pred_stmt_list.back(),
AppM);
1340 auto first_condition = std::pair<tree_nodeRef, unsigned int>(
tree_nodeRef(), 0);
1343 auto second_condition = std::pair<tree_nodeRef, unsigned int>(
tree_nodeRef(), 0);
1345 for(
const auto& cond : gmwi->list_of_cond)
1347 if(cond.second == curr_block->number)
1349 if(!first_condition.first)
1351 first_condition = cond;
1356 second_condition = cond;
1360 else if(cond.second == succ_block->number)
1362 if(!first_condition.first)
1364 first_condition = cond;
1369 second_condition = cond;
1374 THROW_ASSERT(first_condition.first,
"First condition is empty");
1376 if(second_condition.first)
1378 const auto new_node =
1385 decltype(gmwi->list_of_cond) new_list_of_cond;
1386 for(
const auto& cond : gmwi->list_of_cond)
1388 if(cond == first_condition)
1390 if(second_condition.first)
1399 else if(cond != second_condition)
1403 new_list_of_cond.push_front(cond);
1407 new_list_of_cond.push_back(cond);
1411 gmwi->list_of_cond = new_list_of_cond;
1415 for(
const auto&
phi : succ_block->CGetPhiList())
1423 const auto gp = GetPointerS<gimple_phi>(
GET_NODE(
phi));
1428 for(
const auto& def_edge : gp->CGetDefEdgesList())
1430 if((first_edge && bb_index == def_edge.second) || (!first_edge && pred_block->number == def_edge.second))
1432 first_value = def_edge.first;
1434 else if((!first_edge && bb_index == def_edge.second) || (first_edge && pred_block->number == def_edge.second))
1436 second_value = def_edge.first;
1444 bool create_gimple_nop =
false;
1445 if(gp->virtual_flag)
1447 const auto virtual_ssa = GetPointerS<ssa_name>(
GET_NODE(gp->res));
1448 for(
const auto& use_stmt : virtual_ssa->CGetUseStmts())
1452 create_gimple_nop =
true;
1455 if(create_gimple_nop)
1459 std::map<TreeVocabularyTokenTypes_TokenEnum, std::string> gimple_nop_schema;
1464 const auto gn = GetPointerS<gimple_nop>(
GET_NODE(new_gimple_node));
1465 gn->SetVdef(gp->res);
1466 gn->AddVuse(first_value);
1467 gn->AddVuse(second_value);
1472 new_ssas.insert(first_value);
1473 new_ssas.insert(second_value);
1482 const auto cond_expr_node =
1484 BUILTIN_SRCP, (isAVectorType ? vec_cond_expr_K : cond_expr_K));
1489 if(!gp->virtual_flag || create_gimple_nop)
1491 succ_block->PushFront(new_gimple_node,
AppM);
1498 if(gmwi->list_of_cond.size() >= 2)
1503 while(succ_block->CGetPhiList().size())
1505 succ_block->RemovePhi(succ_block->CGetPhiList().front());
1509 pred_block->list_of_succ.erase(
1510 std::find(pred_block->list_of_succ.begin(), pred_block->list_of_succ.end(), bb_index));
1513 succ_block->list_of_pred.clear();
1514 succ_block->list_of_pred.push_back(pred_block->number);
1525 if(curr_block->list_of_pred.size() == 1 && curr_block->list_of_pred.front() ==
bloc::ENTRY_BLOCK_ID)
1530 if(std::find(curr_block->list_of_succ.begin(), curr_block->list_of_succ.end(), bb_index) !=
1531 curr_block->list_of_succ.end())
1536 if(curr_block->CGetStmtList().empty() && curr_block->list_of_pred.size() == 2 &&
1537 curr_block->list_of_succ.size() == 1)
1539 const auto succ_bbi = curr_block->list_of_succ.front();
1540 const auto loop_bb = std::find(curr_block->list_of_pred.begin(), curr_block->list_of_pred.end(), succ_bbi);
1541 const auto infinite_empty_loop =
1542 sl->
list_of_bloc.at(succ_bbi)->CGetStmtList().empty() && loop_bb != curr_block->list_of_pred.end();
1543 if(infinite_empty_loop)
1546 "Infinite empty loop is present in the code in function " +
1552 if(curr_block->list_of_pred.size() != 1)
1557 const auto& succ_block =
sl->
list_of_bloc.at(curr_block->list_of_succ.front());
1559 const auto& pred_block =
sl->
list_of_bloc.at(curr_block->list_of_pred.front());
1560 const auto phi_size = succ_block->list_of_pred.size();
1561 for(
const auto&
phi : succ_block->CGetPhiList())
1564 if(phi_size != gp->CGetDefEdgesList().size())
1567 "<--Unknown because successor contain phi " +
STR(
phi) +
1568 " with different size: " +
STR(phi_size) +
" vs. " +
STR(gp->CGetDefEdgesList().size()));
1572 if(std::find(pred_block->list_of_succ.begin(), pred_block->list_of_succ.end(), succ_block->number) ==
1573 pred_block->list_of_succ.end())
1575 if(pred_block->list_of_succ.size() == 1)
1578 "<--Empty basic block with predecessor with single Exit");
1581 if(pred_block->CGetStmtList().size())
1583 const auto pred_last_stmt =
GET_CONST_NODE(pred_block->CGetStmtList().back());
1584 if(pred_last_stmt->get_kind() == gimple_cond_K)
1587 "<--Basic block dominated by if which can be removed");
1590 if(pred_last_stmt->get_kind() == gimple_multi_way_if_K)
1593 "<--Basic block dominated by multi way if which can be removed");
1597 "<--Unknown because it can be removed but it is controlled by " +
1598 pred_last_stmt->get_kind_text());
1602 "<--Unknown because it can be removed but predecessor is empty");
1618 if(pred_block->CGetStmtList().empty())
1623 const auto pred_last_stmt =
GET_CONST_NODE(pred_block->CGetStmtList().back());
1624 if(pred_last_stmt->get_kind() == gimple_cond_K)
1629 if(pred_last_stmt->get_kind() == gimple_multi_way_if_K)
1635 const auto gmwi = GetPointer<const gimple_multi_way_if>(pred_last_stmt);
1641 for(
const auto& cond : gmwi->list_of_cond)
1643 if(cond.second == curr_block->number || cond.second == succ_block->number)
1645 if(!first_condition)
1647 first_condition = cond.first;
1651 second_condition = cond.first;
1656 "---First condition is " + (first_condition ? first_condition->ToString() :
"default"));
1658 "---Second condition is " + (second_condition ? second_condition->ToString() :
"default"));
1659 if(!first_condition || !second_condition ||
1669 "<--New gimple multi way if would increase basic block latency");
1677 "<--Unknown because dominator of phi is " + pred_last_stmt->ToString());
1680 if(pred_block->CGetStmtList().empty())
1685 const auto pred_last_stmt =
GET_CONST_NODE(pred_block->CGetStmtList().back());
1686 if(pred_last_stmt->get_kind() == gimple_cond_K)
1691 if(pred_last_stmt->get_kind() == gimple_multi_way_if_K)
1694 if(succ_block->CGetStmtList().size() == 1 &&
1695 GetPointer<const gimple_return>(
GET_CONST_NODE(succ_block->CGetStmtList().front())))
1703 "-->Potentially is a path to phi to be merged. Checking timing");
1708 const auto gmwi = GetPointerS<const gimple_multi_way_if>(
GET_CONST_NODE(pred_block->CGetStmtList().back()));
1713 for(
const auto& cond : gmwi->list_of_cond)
1715 if(cond.second == curr_block->number || cond.second == succ_block->number)
1717 condition = cond.first;
1724 const auto& list_of_phi = succ_block->CGetPhiList();
1725 for(
const auto&
phi : list_of_phi)
1734 auto first_edge =
false;
1741 for(
const auto& def_edge : gp->CGetDefEdgesList())
1743 if((first_edge && bb_index == def_edge.second) || (!first_edge && pred_block->number == def_edge.second))
1745 first_value = def_edge.first;
1747 else if((!first_edge && bb_index == def_edge.second) ||
1748 (first_edge && pred_block->number == def_edge.second))
1750 second_value = def_edge.first;
1757 const auto cond_expr_node =
1759 (isAVectorType ? vec_cond_expr_K : cond_expr_K));
1764 const auto gimple_assign_node =
1774 "<--Empty path to phi to be merged, but modifying would increase the latency of predecessor");
1784 "<--Unknown because dominator of phi is " + pred_last_stmt->ToString());
1792 THROW_ASSERT(curr_block->list_of_pred.size() == 1,
"Basic block with single phis but not a single predecessor");
1793 const auto pred_block =
sl->
list_of_bloc.at(curr_block->list_of_pred.front());
1794 for(
const auto&
phi : boost::adaptors::reverse(curr_block->CGetPhiList()))
1798 const auto& left_part = gp->res;
1800 const auto right_part = gp->CGetDefEdgesList().front().first;
1801 const auto left_ssa = GetPointerS<const ssa_name>(
GET_CONST_NODE(gp->res));
1804 for(
const auto& use_stmt : left_ssa->CGetUseStmts())
1806 if(use_stmt.first->index != gp->index)
1808 use_stmts.insert(use_stmt.first);
1813 "-->Replacing " + left_part->ToString() +
" with " + right_part->ToString());
1814 for(
const auto& use_stmt : use_stmts)
1823 while(curr_block->CGetPhiList().size())
1826 "---Removing " + curr_block->CGetPhiList().front()->ToString());
1827 curr_block->RemovePhi(curr_block->CGetPhiList().front());
1835 "-->Applying chaining optimization starting from BB" +
STR(bb_index));
1837 const auto& succ_block =
sl->
list_of_bloc.at(curr_block->list_of_succ.front());
1840 THROW_ASSERT(succ_block->CGetPhiList().empty(),
"Second element of the chain has phi");
1843 while(succ_block->CGetStmtList().size())
1845 const auto statement = succ_block->CGetStmtList().front();
1847 succ_block->RemoveStmt(statement,
AppM);
1848 curr_block->PushBack(statement,
AppM);
1853 curr_block->true_edge = succ_block->true_edge;
1854 curr_block->false_edge = succ_block->false_edge;
1855 curr_block->list_of_succ = succ_block->list_of_succ;
1858 for(
auto succ_succ : succ_block->list_of_succ)
1863 succ_succ_block->list_of_pred.erase(
1864 std::find(succ_succ_block->list_of_pred.begin(), succ_succ_block->list_of_pred.end(), succ_block->number));
1865 succ_succ_block->list_of_pred.push_back(curr_block->number);
1866 for(
const auto&
phi : succ_succ_block->CGetPhiList())
1868 const auto gp = GetPointerS<gimple_phi>(
GET_NODE(
phi));
1869 for(
auto& def_edge : gp->CGetDefEdgesList())
1871 if(def_edge.second == succ_block->number)
1891 "BB" +
STR(bb_index) +
" has " +
STR(curr_block->list_of_succ.size()));
1892 const auto& succ_block =
sl->
list_of_bloc.at(curr_block->list_of_succ.front());
1893 const auto& pred_succ_block = succ_block->list_of_pred;
1896 for(
const auto& predecessor : curr_block->list_of_pred)
1898 if(std::find(pred_succ_block.begin(), pred_succ_block.end(), predecessor) != pred_succ_block.end())
1909 for(
const auto&
phi : succ_block->CGetPhiList())
1914 for(
auto def_edge : gp->CGetDefEdgesList())
1916 if(def_edge.second == bb_index)
1919 "---Found " + def_edge.first->ToString() +
" coming from BB" +
STR(def_edge.second));
1921 if(def_to_be_removed->get_kind() == ssa_name_K)
1923 const auto def_stmt = GetPointerS<const ssa_name>(def_to_be_removed)->CGetDefStmt();
1924 const auto phi_to_be_removed = GetPointer<const gimple_phi>(
GET_CONST_NODE(def_stmt));
1925 if(phi_to_be_removed && phi_to_be_removed->bb_index == bb_index)
1928 "---" + def_edge.first->ToString() +
" comes from a phi to be removed");
1930 if(GetPointerS<const ssa_name>(def_to_be_removed)->CGetNumberUses() == 1)
1932 curr_block->RemovePhi(def_stmt);
1934 for(
const auto& curr_def_edge : phi_to_be_removed->CGetDefEdgesList())
1937 "---Adding from phi of predecessor <" + curr_def_edge.first->ToString() +
", BB" +
1938 STR(curr_def_edge.second) +
">");
1939 new_list_of_def_edge.push_back(curr_def_edge);
1945 "---" + def_edge.first->ToString() +
" is defined in a " +
1948 for(
auto predecessor : curr_block->list_of_pred)
1951 "---Adding from predecessor <" + def_edge.first->ToString() +
", BB" +
1952 STR(predecessor) +
">");
1953 new_list_of_def_edge.push_back(decltype(def_edge)(def_edge.first, predecessor));
1959 for(
auto predecessor : curr_block->list_of_pred)
1962 "---Adding from predecessor <" + def_edge.first->ToString() +
", BB" +
1963 STR(predecessor) +
">");
1964 new_list_of_def_edge.push_back(decltype(def_edge)(def_edge.first, predecessor));
1971 "---Readding <" + def_edge.first->ToString() +
", BB" +
STR(def_edge.second) +
">");
1972 new_list_of_def_edge.push_back(def_edge);
1975 gp->SetDefEdgeList(
TM, new_list_of_def_edge);
1980 const auto curr_phis = curr_block->CGetPhiList();
1981 for(
const auto&
phi : curr_phis)
1983 const auto gp = GetPointerS<gimple_phi>(
GET_NODE(
phi));
1985 for(
auto predecessor : succ_block->list_of_pred)
1987 if(predecessor != bb_index)
1993 gp->bb_index = succ_block->number;
1994 curr_block->RemovePhi(
phi);
1995 succ_block->AddPhi(
phi);
1999 for(
auto predecessor : curr_block->list_of_pred)
2002 pred_block->list_of_succ.erase(
2003 std::find(pred_block->list_of_succ.begin(), pred_block->list_of_succ.end(), bb_index));
2004 pred_block->list_of_succ.push_back(succ_block->number);
2005 if(pred_block->true_edge == bb_index)
2007 pred_block->true_edge = succ_block->number;
2009 if(pred_block->false_edge == bb_index)
2011 pred_block->false_edge = succ_block->number;
2014 if(pred_block->CGetStmtList().size())
2016 const auto& last_stmt = pred_block->CGetStmtList().back();
2017 if(
GET_NODE(last_stmt)->get_kind() == gimple_multi_way_if_K)
2019 const auto gmw = GetPointerS<gimple_multi_way_if>(
GET_NODE(last_stmt));
2020 for(
auto& cond : gmw->list_of_cond)
2022 if(cond.second == bb_index)
2024 cond.second = succ_block->number;
2032 succ_block->list_of_pred.erase(
2033 std::find(succ_block->list_of_pred.begin(), succ_block->list_of_pred.end(), bb_index));
2034 std::copy(curr_block->list_of_pred.begin(), curr_block->list_of_pred.end(),
2035 std::back_inserter(succ_block->list_of_pred));
2046 const auto ga = GetPointerS<const gimple_assign>(
GET_CONST_NODE(statement));
2047 const auto sn = GetPointer<const ssa_name>(
GET_CONST_NODE(ga->op0));
2050 const auto new_sn = GetPointerS<const cond_expr>(
GET_CONST_NODE(ga->op1))->op1;
2051 const auto uses = sn->CGetUseStmts();
2052 for(
const auto& use : uses)
2063 const auto virtual_ssa = GetPointerS<ssa_name>(
GET_NODE(old_vssa));
2064 while(virtual_ssa->CGetUseStmts().size())
2066 const auto use_stmt = virtual_ssa->CGetUseStmts().begin()->first;
2068 const auto gn = GetPointerS<gimple_node>(
GET_NODE(use_stmt));
2069 const auto has_vuses = gn->vuses.find(old_vssa) != gn->vuses.end();
2070 const auto has_vovers = gn->vovers.find(old_vssa) != gn->vovers.end();
2072 old_vssa->
ToString() +
" is not in the vuses/vovers of " + use_stmt->ToString());
2076 gn->vuses.erase(old_vssa);
2080 gn->vovers.erase(old_vssa);
2082 for(
auto uses = virtual_ssa->CGetUseStmts().begin()->second; uses > 0; --uses)
2084 virtual_ssa->RemoveUse(use_stmt);
2086 for(
const auto& vssa : new_vssa)
2091 if(gn->AddVuse(vssa))
2093 GetPointerS<ssa_name>(
GET_NODE(vssa))->AddUseStmt(use_stmt);
2099 if(gn->AddVover(vssa))
2101 GetPointerS<ssa_name>(
GET_NODE(vssa))->AddUseStmt(use_stmt);
#define GET_NODE(t)
Macro used to hide implementation details when accessing a tree_node from another tree_node...
void ChainOptimization(const unsigned int bb_index)
Remove chains of basic blocks.
tree_nodeRef CreateOrExpr(const tree_nodeConstRef &first_condition, const tree_nodeConstRef &second_condition, const blocRef &block, unsigned int function_decl_nid) const
Create an or expression.
void ReplaceVirtualUses(const tree_nodeRef &old_vssa, const TreeNodeSet &new_ssa) const
#define DEBUG_LEVEL_VERY_PEDANTIC
extremely verbose debugging print is performed.
tree_nodeRef ExtractCondition(const tree_nodeRef &condition, const blocRef &block, unsigned int function_decl_nid) const
Extract computation of condition from a gimple_cond.
Data structure representing the entire HLS information.
This struct specifies the field bloc (basic block).
#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.
std::string ToString() const
Print this node as string in gimple format.
#define DEBUG_LEVEL_PEDANTIC
very verbose debugging print is performed.
Step successfully executed.
tree_managerRef TM
The tree manager.
#define GET_CLASS(obj)
Macro returning the actual type of an object.
void ReplaceTreeNode(const tree_nodeRef &stmt, const tree_nodeRef &old_node, const tree_nodeRef &new_node)
Replace the occurrences of tree node old_node with new_node in statement identified by tn...
void ApplyMultiMerge(const unsigned int bb_index)
Transform the control flow graph by merging a gimple_phi dominated by a gimple_multi_way_if.
Definition of the class representing a generic C application.
const int output_level
The output level.
~PhiOpt() override
Destructor.
std::string GetName() const override
Return the name of this design step.
RelationshipType
The relationship type.
Source must be executed to satisfy target.
#define INDENT_OUT_MEX(outLevel, curOutLevel, mex)
std::list< DefEdge > DefEdgeList
The type of the def edge list.
tree_manipulationConstRef tree_man
The tree manipulation.
A simple interface to token object of the raw files.
Analysis step that optimize the phis starting from the IR.
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
bool bb_modified
flag used to restart code motion step
Data structure describing a basic block at tree level.
#define OUTPUT_LEVEL_MINIMUM
minimum debugging print is performed.
#define TOK(token)
Macro used to convert a token symbol into a treeVocabularyTokenTypes.
const tree_nodeConstRef CGetTreeNode(const unsigned int i) const
Phi dominated by gimple_multi_way_if to be merged.
#define STR(s)
Macro which performs a lexical_cast to a string.
Auxiliary methods for manipulating string.
void ApplyMultiRemove(const unsigned int bb_index)
Transform the control flow graph by removing a gimple_phi dominated by a gimple_multi_way_if.
std::string ToString(ActorGraphBackend_Type actor_graph_backend_type)
Header include.
void MergePhi(const unsigned int bb_index)
Remove a basic block composed only of phis my merging with the successor.
#define THROW_UNREACHABLE(str_expr)
helper function used to specify that some points should never be reached
PhiOpt_PatternType IdentifyPattern(const unsigned int bb_index) const
Identify to which pattern an empty basic block belongs.
void SinglePhiOptimization(const unsigned int bb_index)
Transform single input phi in assignment.
Data structure used to store the schedule of the operations.
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.
unsigned int new_tree_node_id(const unsigned int ask=0)
Return a new node id in the intermediate representation.
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 ApplyIfMerge(const unsigned int bb_index)
Transform the control flow graph by merging a gimple_phi dominated by a gimple_cond.
void WriteBBGraphDot(const std::string &filename) const
Write the current version of statement list in dot format.
Phi dominated by gimple_cond to be removed.
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...
void create_tree_node(const unsigned int node_id, enum kind tree_node_type, std::map< TreeVocabularyTokenTypes_TokenEnum, std::string > &tree_node_schema)
Factory method.
Target must be reexecuted.
std::pair< tree_nodeRef, unsigned int > DefEdge
The type of the def edge.
tree_nodeRef GetTreeReindex(const unsigned int i)
Return a tree_reindex wrapping the i-th tree_node.
#define GET_CONST_NODE(t)
PhiOpt(const application_managerRef AppM, unsigned int function_id, const DesignFlowManagerConstRef design_flow_manager, const ParameterConstRef parameters)
Constructor.
refcount< const tree_node > tree_nodeConstRef
Classes specification of the tree_node data structures.
Empty basic block with multiple input.
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.
void ApplyGimpleNothing(const unsigned int bb_index)
Remove an empty basic block dominated by gimple assign.
bool EvaluateCondsMerging(const unsigned statement_index, const unsigned int first_condition, const unsigned second_condition, unsigned int function_decl_nid) const
Check if a further condition can be added to gimple multi way if without increasing basic block laten...
Data structure definition for HLS constraints.
This struct specifies the block node.
This file collects some utility functions.
void Initialize() override
Initialize the step (i.e., like a constructor, but executed just before exec.
tree_nodeRef GetTreeNode(const unsigned int index) const
Return the index-th tree_node (modifiable version)
Basic block dominated by multi way if can be removed without further changes.
void ApplyIfNothing(const unsigned int bb_index)
Transform the control flow graph by eliminating an empty basic block dominated by gimple_cond without...
PhiOpt_PatternType
Identifier of patterns to be transformed by phi_opt.
tree_nodeRef create_ternary_operation(const tree_nodeConstRef &type, const tree_nodeRef &op0, const tree_nodeRef &op1, const tree_nodeRef &op2, const std::string &srcp, enum kind operation_kind) const
Function used to create a ternary expression.
const unsigned int function_id
The index of the function to be analyzed.
DesignFlowStep_Status InternalExec() override
Updates the tree to have a more compliant CFG.
Basic block dominated by if can be removed without further changes.
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
Empty basic block dominated by assign can be removed without further changes.
struct definition of the common part of a gimple with virtual operands
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.
void ApplyDiffNothing(const unsigned int bb_index)
Remove an empty basic block with multiple input edges.
tree_nodeRef create_ssa_name(const tree_nodeConstRef &var, const tree_nodeConstRef &type, const tree_nodeConstRef &min, const tree_nodeConstRef &max, bool volatile_flag=false, bool virtual_flag=false) const
MISCELLANEOUS_OBJ_TREE_NODES.
refcount< tree_node > tree_nodeRef
RefCount type definition of the tree_node class structure.
Phi dominated by gimple_multi_way_if to be removed.
statement_list * sl
The basic block graph of the function.
static bool is_a_vector(const tree_managerConstRef &TM, const unsigned int index)
Return true if the treenode index is a vector.
void RemoveCondExpr(const tree_nodeRef statement)
Remove a redundant cond expr.
ScheduleRef schedule
The scheduling solution.
Transformation blocked by timing.
void ApplyMultiNothing(const unsigned int bb_index)
Transform the control flow graph by eliminating an empty basic block dominated by gimple_multi_way_if...
int debug_level
The debug level.
Edges coming from if to be merged.
#define GET_INDEX_CONST_NODE(t)
Data structure definition for high-level synthesis flow.
tree_nodeRef create_gimple_modify_stmt(const tree_nodeRef &op0, const tree_nodeRef &op1, unsigned int function_decl_nid, const std::string &srcp) const
GIMPLE_ASSIGN.
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.
#define THROW_ASSERT(cond, str_expr)
helper function used to check an assert and if needed to throw an error in a standard way ...
void ApplyIfRemove(const unsigned int bb_index)
Transform the control flow graph by removing a gimple_phi dominated by a gimple_cond.