• 深度为主生成树:将图中所有的结点和那些构成深度为主次序的边表示为树的形式,并将其他的边(这些边不是深度为主次序的一部分)用一种有别于树的方式来表示(我们用虚线而不是实线表示它们)

    • 属于深度为主生成树的边称为树边(tree edge)
    • 不属于深度为主生成树的那些边分为三类:
      • 前向边(forward edge):从一个结点到一个直接后裔并且不是树边的边(用F标识),主编号由小到大
      • 后向边(back edge):从一个结点到树中它的一个祖先的边(用B标识),主编号由大到小
      • 横向边(cross edge):连接两个在树中互不是祖先的结点的边(用C标识),主编号由大到小

  • GCC在计算深度为主搜索树时,使用的是非递归算法。利用stack先入后出的特点,完成树的深度优先遍历。为了使得代码逻辑更清晰,删除了CDI_POST_DOMINATORS模式相关的代码。
  • 遍历过程中一共生成3张映射表:
    • bb的index --> bb的深度为主编号:保存在映射表m_dfs_order
    • bb的深度为主编号 --> bb的index:保存在映射表m_dfs_to_bb
    • bb的深度为主编号 --> 在深度为主生成树中,bb的父节点的深度为主编号:保存在m_dfs_parent
/* The nonrecursive variant of creating a DFS tree.  BB is the starting basic
block for this tree and m_reverse is true, if predecessors should be visited
instead of successors of a node. After this is done all nodes reachable
from BB were visited, have assigned their dfs number and are linked together
to form a tree. */ void
dom_info::calc_dfs_tree_nonrec (basic_block bb)
{
edge_iterator *stack = new edge_iterator[m_n_basic_blocks + 1];
int sp = 0;
unsigned d_i = dom_convert_dir_to_idx (CDI_DOMINATORS); /* Initialize the first edge. */
edge_iterator ei = ei_start (bb->succs); /* When the stack is empty we break out of this loop. */
while (1)
{
basic_block bn;
edge_iterator einext; /* This loop traverses edges e in depth first manner, and fills the
stack. */
while (!ei_end_p (ei))
{
edge e = ei_edge (ei); /* Deduce from E the current and the next block (BB and BN), and the
next edge. */
bb = e->src;
bn = e->dest;
/* 三种情况下跳过当前节点:
1. BN是end block,对于CDI_DOMINATORS模式来说,即exit block.
2. 没有给BN分配保存dominance information的空间.
3. 已经被访问过的节点. */
if (bn == m_end_block || bn->dom[d_i] == NULL
|| m_dfs_order[bn->index])
{
ei_next (&ei);
continue;
} /* 深度优先,遍历BN的后继节点. */
einext = ei_start (bn->succs); gcc_assert (bn != m_start_block);
/* Fill the DFS tree info calculatable _before_ recursing. */
/* my_i 是BB的深度为主编号.
child_i 是BN的深度为主编号. */
TBB my_i;
if (bb != m_start_block)
my_i = m_dfs_order[bb->index];
else
my_i = *m_dfs_last;
/* 将BN和child_i的映射关系存入表m_dfs_order. */
TBB child_i = m_dfs_order[bn->index] = m_dfsnum++;
/* 将child_i和BN的映射关系存入表m_dfs_to_bb. */
m_dfs_to_bb[child_i] = bn;
/* 将BB和BN的父子节点关系写入表m_dfs_parent. */
m_dfs_parent[child_i] = my_i; /* Save the current point in the CFG on the stack, and recurse. */
stack[sp++] = ei;
ei = einext;
} if (!sp)
break;
ei = stack[--sp]; /* OK. The edge-list was exhausted, meaning normally we would
end the recursion. After returning from the recursive call,
there were (may be) other statements which were run after a
child node was completely considered by DFS. Here is the
point to do it in the non-recursive variant.
E.g. The block just completed is in e->dest for forward DFS,
the block not yet completed (the parent of the one above)
in e->src. This could be used e.g. for computing the number of
descendants or the tree depth. */
ei_next (&ei);
}
delete[] stack;
}

【GCC编译器】计算支配树信息 Part1 - 求CFG的深度为主搜索树的更多相关文章

  1. 康复计划#4 快速构造支配树的Lengauer-Tarjan算法

    本篇口胡写给我自己这样的老是证错东西的口胡选手 以及那些想学支配树,又不想啃论文原文的人- 大概会讲的东西是求支配树时需要用到的一些性质,以及构造支配树的算法实现- 最后讲一下把只有路径压缩的并查集卡 ...

  2. GCC编译器原理(一)------交叉编译器制作和GCC组件及命令

    1.1 交叉编译器制作 默认安装的 GCC 编译系统所产生的代码适用于本机,即运行 GCC 的机器,但也可将 GCC 安装成能够生成其他的机器代码.安装一些必须的模块,就可产生多种目标机器代码,而且可 ...

  3. POJ2299Ultra-QuickSort(归并排序 + 树状数组求逆序对)

    树状数组求逆序对   转载http://www.cnblogs.com/shenshuyang/archive/2012/07/14/2591859.html 转载: 树状数组,具体的说是 离散化+树 ...

  4. GCC编译器基础入门

    导语 GCC(GNU Compiler Collection,GNU 编译器套件) 是由 GNU 开发的编程语言编译器,支持C.C++.Objective-C.Fortran.Java.Ada和Go语 ...

  5. 洛谷 P7520 - [省选联考 2021 A 卷] 支配(支配树)

    洛谷题面传送门 真·支配树不 sb 的题. 首先题面已经疯狂暗示咱们建出支配树对吧,那咱就老老实实建呗.由于这题数据范围允许 \(n^2\)​ 算法通过,因此可以考虑 \(\mathcal O(n^2 ...

  6. 在CentOS 7.2下升级gcc编译器的版本

    默认情况下,CentOS 7.2预装的gcc版本是4.8.x,通过执行命令 gcc -v 可以看到,一般情况下这个版本的编译器已经满足需要了,但是某些特殊的时候为了支持C++更高的特性,需要对gcc编 ...

  7. GCC编译器使用

    一.GCC简介 通常所说的GCC是GUN Compiler Collection的简称,除了编译程序之外,它还含其他相关工具,所以它能把易于人类使用的高级语言编写的源代码构建成计算机能够直接执行的二进 ...

  8. GCC编译器和GDB调试器常用选项

    http://blog.csdn.net/u014328976/article/details/46745349 GCC编译器 gcc hello.c -o hello                 ...

  9. 临时改GCC编译器,重启后失效

    临时改GCC编译器,重启后失效.例如,用如下命令: export CROSS_COMPILE= <gcc 文件所在的目录>/arm-linux-gnueabihf- 本例中使用的命令如下: ...

随机推荐

  1. 【.NET 与树莓派】LED 数码管驱动模块——TM1638

    LED 数码管,你可以将它看做是 N 个发光二级管的组合,一个灯负责显示一个段,七个段组合一位数字,再加一个小数点,这么一来,一位数码管就有八段.一般,按照顺时针的方向给每个段编号. 上图中的 h 就 ...

  2. 中文NER的那些事儿3. SoftLexicon等词汇增强详解&代码实现

    前两章我们分别介绍了NER的基线模型Bert-Bilstm-crf, 以及多任务和对抗学习在解决词边界和跨领域迁移的解决方案.这一章我们就词汇增强这个中文NER的核心问题之一来看看都有哪些解决方案.以 ...

  3. 【春节歌曲回味 | STM32小音乐盒 】PWM+定时器驱动无源蜂鸣器(STM32 HAL库)

    l  STM32通过PWM与定时器方式控制无源蜂鸣器鸣响 l  STM32小音乐盒,歌曲进度条图形显示与百分比显示,歌曲切换 l  编程使用STM32 HAL库 l  IIC OLED界面编程,动画实 ...

  4. drf-序列化器serializer

    目录 一.序列化器-serializer 二.序列化器的使用 简单使用 高级使用 source **SerializerMethodField( ) ** 通用参数 三.反序列化数据校验 字段属性 局 ...

  5. 创建Akamai cdn api授权

    注:通过Akamai Cli purge和通过Akamai API进行刷新之前,都要事先创建类似于如下的刷新的凭据,这两种刷新方式所创建的凭据是相同的. 目的:创建Akamai CDN API授权以便 ...

  6. 诸多改进!Superset 1.2.0 正式发布!

    Apache Superset 是一个现代的.企业级的轻量BI平台,提供了大量数据可视化组件. 距离superset上一个版本发布已经过了近三个月的时间,我们终于等到了1.2.0版本. 之前就曾提到过 ...

  7. 2、linux防火墙的使用(firewalld)

    2.1.说明: 1.在 RHEL7 里有几种防火墙共存,firewalld.iptables,默认是使用 firewalld 来管理 netfilter 子系统,不过底层调用的命令仍然是 iptabl ...

  8. CentOS-Docker搭建Nacos-v1.3.2(单点)

    说明:从v1.3.1版本开始支持自定义mysql-8.x 通用属性配置(v1.3.2) name description option MODE cluster模式/standalone模式 clus ...

  9. base64文件解码

    $str = str_replace(' ', '+', $str); //替换空字符串为+$str = str_replace('\n', '',$str); //置空换行符$str = str_r ...

  10. Vue使用PrintJs自定义打印表格模板

    这俩天客户提了个需求,需要打印俩个自定义的表格模板,一开始想到的是打印Json表格,但是发现表格样式不符合要求,后来想着打印html,自己生成html模板然后打印,基本可以满足客户的需求,废话不多说, ...