52    explicit CallGraph(std::string_view name) : name(name) {}
 
   54    const cstring &getName()
 const { 
return name; }
 
   60        if (nodes.find(caller) != nodes.end()) 
return;
 
   61        LOG1(name << 
": " << cgMakeString(caller));
 
   62        out_edges[caller] = 
new std::vector<T>();
 
   63        in_edges[caller] = 
new std::vector<T>();
 
   64        nodes.emplace(caller);
 
   66    void calls(T caller, T callee) {
 
   67        LOG1(name << 
": " << cgMakeString(callee) << 
" is called by " << cgMakeString(caller));
 
   70        out_edges[caller]->push_back(callee);
 
   71        in_edges[callee]->push_back(caller);
 
   74        auto n = nodes.find(node);
 
   75        BUG_CHECK(n != nodes.end(), 
"%1%: Node not in graph", node);
 
   77        auto in = in_edges.find(node);
 
   78        if (in != in_edges.end()) {
 
   80            for (
auto n : *in->second) {
 
   81                auto out = out_edges[n];
 
   83                auto oe = std::find(out->begin(), out->end(), node);
 
   88        auto it = out_edges.find(node);
 
   89        if (it != out_edges.end()) {
 
   91            for (
auto n : *it->second) {
 
   92                auto in = in_edges[n];
 
   94                auto ie = std::find(in->begin(), in->end(), node);
 
  103    bool isCallee(T callee)
 const {
 
  104        auto callees = ::get(in_edges, callee);
 
  105        return callees != 
nullptr && !callees->empty();
 
  107    bool isCaller(T caller)
 const {
 
  108        auto edges = ::get(out_edges, caller);
 
  109        if (edges == 
nullptr) 
return false;
 
  110        return !edges->empty();
 
  113    const_iterator begin()
 const { 
return out_edges.cbegin(); }
 
  114    const_iterator end()
 const { 
return out_edges.cend(); }
 
  115    std::vector<T> *getCallees(T caller) { 
return out_edges[caller]; }
 
  116    std::vector<T> *getCallers(T callee) { 
return in_edges[callee]; }
 
  118    void getCallees(T caller, std::set<T> &toAppend) {
 
  119        if (isCaller(caller)) toAppend.insert(out_edges[caller]->begin(), out_edges[caller]->end());
 
  121    size_t size()
 const { 
return nodes.size(); }
 
  123    void reachable(T start, std::set<T> &out)
 const {
 
  126        while (!work.empty()) {
 
  127            T node = *work.begin();
 
  129            if (out.find(node) != out.end()) 
continue;
 
  131            auto edges = out_edges.find(node);
 
  132            if (edges == out_edges.end()) 
continue;
 
  133            for (
auto c : *(edges->second)) work.emplace(c);
 
  137    void restrict(
const std::set<T> &to) {
 
  138        std::vector<T> toRemove;
 
  140            if (to.find(n) == to.end()) toRemove.push_back(n);
 
  141        for (
auto n : toRemove) remove(n);
 
  144    typedef std::unordered_set<T> Set;
 
  150    void dominators(T start, std::map<T, Set> &dominators) {
 
  152        for (
auto n : nodes) {
 
  154                dominators[n].emplace(start);
 
  156                dominators[n].insert(nodes.begin(), nodes.end());
 
  163            for (
auto node : nodes) {
 
  164                auto vec = in_edges[node];
 
  165                if (vec == 
nullptr) 
continue;
 
  166                auto size = dominators[node].size();
 
  167                for (
auto c : *vec) insersectWith(dominators[node], dominators[c]);
 
  168                dominators[node].emplace(node);
 
  169                if (dominators[node].size() != size) changes = 
true;
 
  179        std::set<T> back_edge_heads;
 
  181        explicit Loop(T entry) : entry(entry) {}
 
 
  186        std::vector<Loop *> loops;
 
  190        int isLoopEntryPoint(T node)
 const {
 
  191            for (
size_t i = 0; i < loops.size(); i++) {
 
  192                auto loop = loops.at(i);
 
  193                if (loop->entry == node) 
return i;
 
  197        bool isInLoop(
int loopIndex, T node)
 const {
 
  198            if (loopIndex == -1) 
return false;
 
  199            auto loop = loops.at(loopIndex);
 
  200            return (loop->body.find(node) != loop->body.end());
 
 
  204    Loops *compute_loops(T start) {
 
  205        auto result = 
new Loops();
 
  206        std::map<T, Set> dom;
 
  207        dominators(start, dom);
 
  209        std::map<T, Loop *> entryToLoop;
 
  211        for (
auto e : nodes) {
 
  212            auto next = out_edges[e];
 
  214            for (
auto n : *next) {
 
  215                if (dome.find(n) != dome.end()) {
 
  217                    auto loop = get(entryToLoop, n);
 
  218                    if (loop == 
nullptr) {
 
  220                        entryToLoop[n] = loop;
 
  221                        result->loops.push_back(loop);
 
  223                    loop->back_edge_heads.emplace(e);
 
  228                    while (!work.empty()) {
 
  229                        auto crt = *work.begin();
 
  231                        loop->body.emplace(crt);
 
  232                        if (crt == n) 
continue;
 
  233                        for (
auto i : *in_edges[crt])
 
  234                            if (loop->body.find(i) == loop->body.end()) work.emplace(i);
 
  244    static void insersectWith(Set &set, Set &with) {
 
  245        std::vector<T> toRemove;
 
  247            if (with.find(e) == with.end()) toRemove.push_back(e);
 
  248        for (
auto e : toRemove) set.erase(e);
 
  255        std::vector<T> stack;
 
  257        std::map<T, unsigned> index;
 
  258        std::map<T, unsigned> lowlink;
 
  262            stack.push_back(node);
 
  263            onStack.emplace(node);
 
  265        bool isOnStack(T node) { 
return onStack.count(node) != 0; }
 
  266        bool unknown(T node) { 
return index.count(node) == 0; }
 
  267        void setLowLink(T node, 
unsigned value) {
 
  268            lowlink[node] = value;
 
  269            LOG1(node << 
".lowlink = " << value << 
" = " << get(lowlink, node));
 
  271        void setLowLink(T node, T successor) {
 
  272            unsigned nlink = get(lowlink, node);
 
  273            unsigned slink = get(lowlink, successor);
 
  274            if (slink < nlink) setLowLink(node, slink);
 
  277            T result = stack.back();
 
  279            onStack.erase(result);
 
 
  285    bool strongConnect(T node, 
sccInfo &helper, std::vector<T> &out) {
 
  288        LOG1(
"scc " << cgMakeString(node));
 
  289        helper.index.emplace(node, helper.crtIndex);
 
  290        helper.setLowLink(node, helper.crtIndex);
 
  293        auto oe = out_edges[node];
 
  295            for (
auto next : *oe) {
 
  296                LOG1(cgMakeString(node) << 
" => " << cgMakeString(next));
 
  297                if (helper.unknown(next)) {
 
  298                    bool l = strongConnect(next, helper, out);
 
  300                    helper.setLowLink(node, next);
 
  301                } 
else if (helper.isOnStack(next)) {
 
  302                    helper.setLowLink(node, next);
 
  310        if (get(helper.lowlink, node) == get(helper.index, node)) {
 
  311            LOG1(cgMakeString(node) << 
" index=" << get(helper.index, node)
 
  312                                    << 
" lowlink=" << get(helper.lowlink, node));
 
  314                T sccMember = helper.pop();
 
  315                LOG1(
"Scc order " << cgMakeString(sccMember) << 
"[" << cgMakeString(node) << 
"]");
 
  316                out.push_back(sccMember);
 
  317                if (sccMember == node) 
break;
 
  330    bool sccSort(T start, std::vector<T> &out) {
 
  332        return strongConnect(start, helper, out);
 
  334    bool sort(std::vector<T> &start, std::vector<T> &out) {
 
  337        for (
auto n : start) {
 
  338            if (std::find(out.begin(), out.end(), n) == out.end()) {
 
  339                bool c = strongConnect(n, helper, out);
 
  340                cycles = cycles || c;
 
  345    bool sort(std::vector<T> &out) {
 
  348        for (
auto n : nodes) {
 
  349            if (std::find(out.begin(), out.end(), n) == out.end()) {
 
  350                bool c = strongConnect(n, helper, out);
 
  351                cycles = cycles || c;