【问题标题】:Getting rid of temporal variables after optimizing code in compiler在编译器中优化代码后摆脱时间变量
【发布时间】:2017-01-08 01:26:19
【问题描述】:

我正在按照经典书籍Compilers 的说明创建编译器静态分析模块。 Ullman 等人的原则、技术和工具

我将 AST 表示转换为三地址代码表示进行优化(现在基本上是死代码消除和复制传播),然后我转换为类似的三地址代码表示(更适合转换为字节码)。

为此,我必须创建时间变量,以便我的代码表示如下所示:

t = IntLit(0)
t1 = left < right
t2 = !t1
cjump if t2 to L0:
t3 = number[right]
v = t3
t4 = left - IntLit(1)
i = t4
j = right
cont01 = True()
L2:
t5 = !cont01
cjump if t5 to L3:
cont02 = True()
L4:
t6 = !cont02
cjump if t6 to L5:
t7 = i + IntLit(1)
i = t7
t8 = number[t7]
Removed dead code: aux03 = t8
t10 = t8 < v
t9 = !t10
t11 = !t9
cjump if t11 to L6:
cont02 = False()
jump L7:
L6:
cont02 = True()
L7:
jump L4:
L5:
cont02 = True()
L8:
t12 = !cont02
cjump if t12 to L9:
t13 = j - IntLit(1)
j = t13
t14 = number[t13]
Removed dead code: aux03 = t14
t16 = v < t14
t15 = !t16
t17 = !t15
cjump if t17 to L10:
cont02 = False()
jump L11:
L10:
cont02 = True()
L11:
jump L8:
L9:
t18 = number[i]
t = t18
t19 = number[j]
number[i] = t19
number[j] = t18
t21 = i + IntLit(1)
t20 = j < t21
t22 = !t20
cjump if t22 to L12:
cont01 = False()
jump L13:
L12:
cont01 = True()
L13:
jump L2:
L3:
t23 = number[i]
number[j] = t23
t24 = number[right]
number[i] = t24
number[right] = t
t25 = i - IntLit(1)
t26 = This().Sort(left,t25)
Removed dead code: nt = t26
t27 = i + IntLit(1)
t28 = This().Sort(t27,right)
Removed dead code: nt = t28
jump L1:
L0:
Removed dead code: nt = IntLit(0)
L1:
return IntLit(0)

我想摆脱用于代码生成的时间变量,但我似乎做不到。考虑以下方法:

  def printing() : Int = {
    var i : Int;
    var j : Int;
    var z : Int;

    i = this.printing1();
    z = i;
    println(z);

    return i;
  }

我得到以下代码:

t1 = This().printing1()
Removed dead code: i = t1
Removed dead code: z = t1
println(t1)
return t1

我正在做的删除时间变量是提前传播它们的值。在正常情况下,我只需要提前一份。但是,通过复制传播,我可能需要做几次。

这应该没问题,但结合代码消除,我不能保证方法调用被分配给非时间变量(查看上面的代码)。

因此,当时间变量存储方法调用结果只有一次发生时,我显然可以将方法调用复制到它并结束。如果没有,我可以使用 POP 指令从堆栈中消除结果。但是当出现不止一次时,我无法复制指令,因为我会接到几个电话。

我的结论是我需要保留时间变量。

是否有另一种策略可以帮助我了解时间变量?

【问题讨论】:

  • 这看起来不是问题,临时变量正在完成这项工作。也许更多的上下文会有所帮助,你需要这个做什么?
  • @harold 我认为摆脱时间变量会更好,因为如果我不这样做,我的代码会比原始代码生成更多的 java 字节码,因此它“显然”效率更低(实际上有是一堆额外的加载存储指令)。如果涉及时间,也很难处理堆栈...

标签: optimization compiler-construction


【解决方案1】:

我不知道是否可以使用您当前的内部表示(即 AST)删除所有临时变量,但您可以使用寄存器分配算法减少它们的数量。

根据您的代码,您每次都会生成一个新的时间变量。这类似于编译器假设(为简单起见)CPU 具有无限寄存器时的问题。然后它必须生成实际使用架构所具有的有限数量的寄存器的代码。为了从无限的寄存器/变量减少到更小的有限集,使用了寄存器分配算法。

您可以在Engineering a Compiler by Keith Cooper 书中找到有关该主题的整章 (13)。

how this is done in real compilers like GCC.也有很多信息

我想到的是将变量视为寄存器,然后使用寄存器分配算法将它们的数量减少到最低限度。

这个想法显然只是我的十美分。设计编译器确实是一个非常复杂的问题,需要深入协作才能解决您的实际问题。

【讨论】:

    猜你喜欢
    • 2021-08-09
    • 2011-10-27
    • 2016-02-14
    • 1970-01-01
    • 2011-08-27
    • 2019-01-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多