对基本块中的表达式 y=a*b+a*b 建立 DAG。若两次 a*b 的操作数和值都相同,DAG 的典型处理是()。
DAG 允许一个结点被多个父结点引用。两次 a*b 在操作符和操作数均相同、且中间没有对 a 或 b 重新赋值时,计算结果相同,可以用同一个乘法结点表示;加法结点的两个输入都指向该结点。
选项分析
错误。这是普通语法树式的重复表示,没有利用 DAG 的共享能力。
正确。共享乘法结点体现了相同公共子表达式只计算一次。
错误。原表达式需要把两个相同结果相加,不能连外层加法一起删除。
错误。a 和 b 是不同变量叶结点,不能因为参与同一运算就合并。
本题为什么容易错
看到“公共子表达式消除”容易误以为把重复部分直接删掉。优化的真实含义是复用第一次计算结果,凡是使用该结果的地方仍要保留数据依赖。
简短答案
DAG 为什么能表示公共子表达式共享,正确答案是 B(让两个加法输入共享同一个乘法结点)。DAG 允许一个结点被多个父结点引用。两次 a*b 在操作符和操作数均相同、且中间没有对 a 或 b 重新赋值时,计算结果相同,可以用同一个乘法结点表示;加法结点的两个输入都指向该结点。
易混淆概念对比表
| 概念 | 本题判断 | 区别要点 | 记忆提示 |
|---|---|---|---|
| 无条件建立两个完全独立的乘法结点 | 本题干扰项 | 错误。这是普通语法树式的重复表示,没有利用 DAG 的共享能力。 | 看到该词不要急着选,先判断是否真正解决题干问题 |
| 让两个加法输入共享同一个乘法结点 | 本题正确答案 | 正确。共享乘法结点体现了相同公共子表达式只计算一次。 | 看到题干核心场景时优先联想到它 |
| 删除加法,只保留一次 a*b | 本题干扰项 | 错误。原表达式需要把两个相同结果相加,不能连外层加法一起删除。 | 看到该词不要急着选,先判断是否真正解决题干问题 |
| 把 a 和 b 合并成同一个叶结点 | 本题干扰项 | 错误。a 和 b 是不同变量叶结点,不能因为参与同一运算就合并。 | 看到该词不要急着选,先判断是否真正解决题干问题 |
本题易混淆选项怎么区分
- 无条件建立两个完全独立的乘法结点:错误。这是普通语法树式的重复表示,没有利用 DAG 的共享能力。
- 删除加法,只保留一次 a*b:错误。原表达式需要把两个相同结果相加,不能连外层加法一起删除。
- 把 a 和 b 合并成同一个叶结点:错误。a 和 b 是不同变量叶结点,不能因为参与同一运算就合并。
知识点详解
抽象语法树中每次语法出现通常对应独立子树,而 DAG 可以让多条边指向同一结点,表示多个表达式使用同一个值。基本块优化常借助 DAG 发现公共子表达式、无用赋值和名称等价关系。若某个操作数在两次表达式之间被重新定义,即使文字仍写成 a*b,也不再代表同一个值,不能盲目共享。
备考速记
同操作、同输入、值没变,DAG 才共享;共享计算,不删除用途。
DAG 在局部优化场景中的作用
DAG在本题中的核心价值,是解决“对基本块中的表达式 y=a*b+a*b 建立 DAG。若两次 a*b 的操作数和值都相同,DAG 的典型处理是()”这个场景问题。复习时不要只背选项名称,还要理解它为什么适用于该场景,以及它能解决哪类安全、流程或管理问题。
同类题怎么考
- 给出基本块三地址码,画 DAG 并找出公共子表达式。
- 判断变量重新赋值后,原公共子表达式是否还能复用。
- 比较语法树与 DAG 在结点共享和优化表示上的差异。
DAG 在软件设计师软考中的考法
软考选择题通常不会只考概念定义,还会把DAG放到局部优化场景中,要求判断它的作用、适用范围或与相近概念的区别。遇到这类题时,先抓住题干中的业务场景,再看哪个选项最能解决该场景下的核心问题。
解题思路
语法树会老老实实画两棵 a*b;DAG 会先问:第二次乘法和前一次是不是同一件事?如果 a、b 都没被改写,就不必再造一个乘法结点,让两条边指向旧结点即可。注意这里只省掉重复乘法,外层加法仍然存在。
考点定位
DAG 与普通语法树的关键差异是允许共享子结点,因此能显式表示基本块内的公共子表达式,但共享前必须确认操作数的值没有改变。
易错提醒
- 共享前没有检查变量是否在两次计算之间被重新定义。
- 把重复子表达式和整个表达式混为一谈,错误删除外层运算。
- 把 DAG 的共享理解成变量结点合并,而不是相同运算结果结点复用。
备考提示
- 画 DAG 时先为变量建叶结点,再查找是否已有相同操作符且孩子相同的内部结点。
- 遇到赋值语句要更新变量标签,重新判断旧结点中的值是否仍代表当前变量。
你可能还想了解
- DAG 与抽象语法树的主要区别是什么?
- 变量重新赋值后为什么不能继续共享旧结点?
- 公共子表达式消除是不是直接删除第二个表达式?
- 基本块 DAG 还能用于哪些局部优化?
本文小结
在 a、b 的值没有变化时,两次 a*b 产生同一结果,DAG 可让外层加法的两个输入共享一个乘法结点。它复用的是计算结果,外层加法和数据依赖不能被删除。