23 {
"red",
"blue",
"black",
"green",
"yellow",
24 "orange",
"blueviolet",
"cyan",
"cadetblue",
"magenta",
"palegreen",
25 "deeppink",
"indigo",
"olivedrab"};
26 #define print_colour(u) colour_map[u%NB_COLOURS]
29 std::set<event_idt> &visited)
32 file << node_id <<
"[label=\"" << node <<
", " << node.
source_location <<
34 visited.insert(node_id);
36 for(wmm_grapht::edgest::const_iterator
37 it=
po_out(node_id).begin();
38 it!=
po_out(node_id).end(); ++it)
40 file << node_id <<
"->" << it->first <<
"[]\n";
41 file <<
"{rank=same; " << node_id <<
"; " << it->first <<
"}\n";
42 if(visited.find(it->first)==visited.end())
46 for(wmm_grapht::edgest::const_iterator
48 it!=
com_out(node_id).end(); ++it)
50 file << node_id <<
"->" << it->first <<
"[style=\"dotted\"]\n";
51 if(visited.find(it->first)==visited.end())
59 std::set<event_idt> visited;
62 file.open(
"graph.dot");
63 file <<
"digraph G {\n";
64 file <<
"rankdir=LR;\n";
77 if(explored.find(begin)!=explored.end())
80 explored.insert(begin);
85 for(wmm_grapht::edgest::const_iterator it=
po_out(begin).begin();
112 std::set<event_idt> covered;
124 std::map<event_idt, event_idt> orig2copy;
127 for(std::set<event_idt>::const_iterator it=covered.begin();
133 orig2copy[*it]=new_node;
141 for(std::set<event_idt>::const_iterator it_i=covered.begin();
145 for(std::set<event_idt>::const_iterator it_j=covered.begin();
163 for(std::set<event_idt>::const_iterator it_i=covered.begin();
184 return orig2copy[end];
195 for(; AC_it!=
end(); ++AC_it)
212 for(AC_it=
begin(); ; ++AC_it)
246 for(; BC_it!=begin(); --BC_it)
261 if(BC_it==begin() && egraph[back()].thread==first.
thread)
284 bool unsafe_met=
false;
291 unsigned thread=egraph[*begin()].thread;
294 th_it!=end() && thread==egraph[*th_it].thread; ++th_it)
295 thread=egraph[*th_it].thread;
303 for(; it!=end() && next!=end(); ++next, ++it)
351 if(check_AC(s_it, first, second))
354 if(check_BC(it, first, second))
364 && (first.
thread!=second.
thread || egraph.are_po_ordered(*it, *s_it)))
378 after_second=begin();
384 && egraph[*before_first].thread!=first.
thread
385 && egraph[*after_second].thread!=second.
thread)
396 unsafe_pairs.insert(delay);
406 && (first.
thread!=second.
thread || egraph.are_po_ordered(*it, *s_it)))
420 after_second=begin();
426 && egraph[*before_first].thread!=first.
thread
427 && egraph[*after_second].thread!=second.
thread)
438 unsafe_pairs.insert(delay);
483 if(check_AC(s_it, first, second))
486 if(check_BC(begin(), first, second))
494 && (first.
thread!=second.
thread || egraph.are_po_ordered(back(), *s_it)))
496 std::list<event_idt>::const_iterator before_first;
497 std::list<event_idt>::const_iterator after_second;
508 && egraph[*before_first].thread!=first.
thread
509 && egraph[*after_second].thread!=second.
thread)
518 unsafe_pairs.insert(delay);
528 && (first.
thread!=second.
thread || egraph.are_po_ordered(back(), *s_it)))
530 std::list<event_idt>::const_iterator before_first;
531 std::list<event_idt>::const_iterator after_second;
542 && egraph[*before_first].thread!=first.
thread
543 && egraph[*after_second].thread!=second.
thread)
552 unsafe_pairs.insert(delay);
568 bool unsafe_met=
false;
569 unsigned char fences_met=0;
576 unsigned thread=egraph[*begin()].thread;
579 th_it!=end() && thread==egraph[*th_it].thread; ++th_it)
580 thread=egraph[*th_it].thread;
610 fences_met |= egraph[*s_it].fence_value();
641 AC_it!=end() && egraph[*AC_it].thread==second.
thread;
644 && egraph[*AC_it].is_cumul()
645 && egraph[*AC_it].is_corresponding_fence(egraph[*it], egraph[*s_it]))
654 if(AC_it==end() && egraph[front()].thread==second.
thread)
657 !(egraph[*AC_it]==first) && egraph[*AC_it].thread==second.
thread;
660 egraph[*AC_it].is_cumul() &&
661 egraph[*AC_it].is_corresponding_fence(egraph[*it], egraph[*s_it]))
684 BC_it!=begin() && egraph[*BC_it].thread==first.
thread;
688 egraph[*BC_it].is_cumul() &&
689 egraph[*BC_it].is_corresponding_fence(egraph[*it], egraph[*s_it]))
699 if(BC_it==begin() && egraph[back()].thread==first.
thread)
702 !(egraph[*BC_it]==second) && egraph[*BC_it].thread==first.
thread;
705 egraph[*BC_it].is_cumul() &&
706 egraph[*BC_it].is_corresponding_fence(egraph[*it], egraph[*s_it]))
723 && (first.
thread!=second.
thread || egraph.are_po_ordered(*it, *s_it)))
730 unsafe_pairs.insert(delay);
741 && (first.
thread!=second.
thread || egraph.are_po_ordered(*it, *s_it)))
748 unsafe_pairs.insert(delay);
768 fences_met |= egraph[*s_it].fence_value();
796 AC_it!=end() && egraph[*AC_it].thread==second.
thread;
799 && egraph[*AC_it].is_cumul()
800 && egraph[*AC_it].is_corresponding_fence(first, second))
809 if(AC_it==end() && egraph[front()].thread==second.
thread)
812 !(egraph[*AC_it]==first) && egraph[*AC_it].thread==second.
thread;
815 egraph[*AC_it].is_cumul() &&
816 egraph[*AC_it].is_corresponding_fence(first, second))
831 BC_it!=begin() && egraph[*BC_it].thread==first.
thread;
834 && egraph[*BC_it].is_cumul()
835 && egraph[*BC_it].is_corresponding_fence(first, second))
844 if(BC_it==begin() && egraph[back()].thread==first.
thread)
849 !(egraph[*BC_it]==second) && egraph[*BC_it].thread==first.
thread;
852 && egraph[*BC_it].is_cumul()
853 && egraph[*BC_it].is_corresponding_fence(first, second))
868 && (first.
thread!=second.
thread || egraph.are_po_ordered(back(), *s_it)))
873 unsafe_pairs.insert(delay);
882 && (first.
thread!=second.
thread || egraph.are_po_ordered(back(), *s_it)))
887 unsafe_pairs.insert(delay);
901 for(; it!=end(); ++it)
914 const irep_idt &var=egraph[*it].variable;
918 if(!egraph.ignore_arrays &&
id2string(var).find(
"[]")!=std::string::npos)
921 for(; it!=end(); ++it)
939 for(; it!=end(); it++)
952 const irep_idt &var=egraph[*it].variable;
955 for(; it!=end(); prev=it, ++it)
996 if(dep.
dp(current, next))
1013 if(dep.
dp(current, next))
1021 std::string cycle=
"Cycle: ";
1024 return cycle +
" End of cycle.";
1029 std::string name=
"Unsafe pairs: ";
1030 for(std::set<delayt>::const_iterator it=unsafe_pairs.begin();
1031 it!=unsafe_pairs.end();
1076 std::string cycle=
"Cycle: ";
1083 return cycle+
" End of cycle.";
1101 std::map<std::string, std::string> &map_id2var,
1102 std::map<std::string, std::string> &map_var2id)
const
1110 if(map_var2id.find(var_name)!=map_var2id.end())
1113 cycle += map_var2id[var_name] +
") ";
1117 const std::string new_id=
"var@" +
std::to_string(map_var2id.size());
1118 map_var2id[var_name]=new_id;
1119 map_id2var[new_id]=var_name;
1121 cycle += new_id +
") ";
1129 std::map<std::string, std::string> &map_id2var,
1130 std::map<std::string, std::string> &map_var2id,
1131 bool hide_internals)
const
1141 this->hide_internals(reduced);
1142 assert(reduced.
size() > 0);
1143 cycle+=print_detail(reduced, map_id2var, map_var2id);
1145 cycle+=print_name(reduced, model);
1149 cycle+=print_detail(*
this, map_id2var, map_var2id);
1151 cycle+=print_name(*
this, model);
1160 std::set<event_idt> reduced_evts;
1164 for(first_it=begin(); first_it!=end(); ++first_it)
1167 if(prev_it!=end() && egraph[*prev_it].thread!=first.
thread
1172 assert(first_it!=end());
1174 reduced_evts.insert(*first_it);
1188 if(cur.
thread!=egraph[*next_it].thread)
1190 if(reduced_evts.find(*cur_it)==reduced_evts.end())
1193 reduced_evts.insert(*cur_it);
1195 for(; next_it!=end() && egraph[*next_it].is_fence(); ++next_it) {}
1196 assert(next_it!=end());
1197 if(reduced_evts.find(*next_it)==reduced_evts.end())
1200 reduced_evts.insert(*next_it);
1213 assert(next_it!=end());
1215 if(cur.
thread!=egraph[*next_it].thread)
1217 if(reduced_evts.find(*cur_it)==reduced_evts.end())
1220 reduced_evts.insert(*cur_it);
1222 for(; next_it!=end() && egraph[*next_it].is_fence(); ++next_it) {}
1223 assert(next_it!=end());
1224 if(reduced_evts.find(*next_it)==reduced_evts.end())
1227 reduced_evts.insert(*next_it);
1237 assert(reduced.
size()>=2);
1238 unsigned extra_fence_count=0;
1242 bool first_done=
false;
1247 if(prev_it!=reduced.
end())
1255 ++extra_fence_count;
1262 bool wraparound=
false;
1266 if(n_it==reduced.
end())
1268 assert(!wraparound);
1271 ++extra_fence_count;
1272 n_it=reduced.
begin();
1282 ++extra_fence_count;
1287 name += (model==
Power?
" Sync":
" MFence");
1294 std::string cand_name=
" LwSync";
1296 bool wraparound=
false;
1300 if(n_it==reduced.
end())
1302 assert(!wraparound);
1305 ++extra_fence_count;
1306 n_it=reduced.
begin();
1316 cand_name=(model==
Power?
" Sync":
" MFence");
1320 ++extra_fence_count;
1332 std::string cand_name;
1334 cand_name=(model==
Power?
" Sync":
" MFence");
1336 cand_name=
" LwSync";
1338 bool wraparound=
false;
1342 if(n_it==reduced.
end())
1344 assert(!wraparound);
1347 ++extra_fence_count;
1348 n_it=reduced.
begin();
1358 cand_name=(model==
Power?
" Sync":
" MFence");
1362 ++extra_fence_count;
1430 auto n_events=extra_fence_count;
1431 for(std::string::const_iterator it=name.begin();
1436 assert(n_events==reduced.
size());
1452 std::string cand_name=
" LwSync";
1454 for( ; it!=reduced.
end(); ++it)
1465 cand_name=(model==
Power?
" Sync":
" MFence");
1467 assert(it!=reduced.
begin() && it!=reduced.
end());
1508 dep.
dp(last, first))
1527 for(std::string::const_iterator it=name.begin();
1532 assert(n_events==reduced.
size());
1549 str <<
"/* " <<
id <<
" */\n";
1553 str <<
"{" << ev.
variable <<
"} {} @thread" << ev.
thread <<
"\"];\n";
1563 str <<
"/* " <<
id <<
" */\n";
1570 str << prev.
id <<
"->";
1576 n_it!=end() ? egraph[*n_it] : egraph[front()];
1577 str << succ.
id <<
"[label=\"";
1578 str << (model==
Power?
"Sync":
"MFence");
1587 n_it!=end() ? egraph[*n_it] : egraph[front()];
1588 str << succ.
id <<
"[label=\"";
1596 str << cur.
id <<
"[label=\"";
1603 str << cur.
id <<
"[label=\"";
1612 str << cur.
id <<
"[label=\"";
1618 str << cur.
id <<
"[label=\"";
1623 str << cur.
id <<
"[label=\"?";
1635 str <<
"/* " <<
id <<
" */\n";
1638 str << last.
id <<
"->";
1644 str << succ.
id <<
"[label=\"";
1645 str << (model==
Power?
"Sync":
"MFence");
1654 str << succ.
id <<
"[label=\"";
1662 str << first.
id <<
"[label=\"";
1669 str << first.
id <<
"[label=\"";
1678 str << first.
id <<
"[label=\"";
1684 str << first.
id <<
"[label=\"";
1689 str << first.
id <<
"[label=\"?";