我是一个学生学习编译器,现在我对SSA形式的问题感到困惑。
如许多语言,例如C,存在许多范围。当前范围中的变量可能会在其他范围中修改,例如,调用函数后可以更改全局变量的值,这使一些优化不正确。此外,可以使用指针修改当前范围中的变量。
我们应该如何处理这种情况?
您所描述的问题的简单,保守的解决方案涉及一个价值的副本,如果它可能以难以或不可能推理的方式变化。
那我到底是什么意思?考虑以下C片段:
void bar(void);
int unsafe;
void foo(void) {
unsafe++; // 1
bar();
printf("%dn", unsafe); // 2
}
假设该代码是使用不执行外位性优化或分析的编译器编译的。显然,因此,编译器不可能知道bar
的调用是否会突变unsafe
。因此,编译器不得在 bar
的呼叫中保留unsafe
的副本。相反,该值应从点1的记忆中读取并立即写回内存,并在第2点的内存中读取。
底线:如果您不能确定证明在程序执行的某些部分期间保留全局变量的副本是安全的,则必须在每次访问时都会从和/或写入和/或写入内存。p>正如您所建议的那样,与本地变量有关的一个类似的问题是:
void qux(void) {
int x;
int *px = &x;
x = 10;
*px = 100;
printf("%dn", x);
}
一个幼稚的编译器,无法检测到x
是混蛋,可能会错误地输出10而不是100。保守解决方案在这里相似:如果您有一个局部变量,其地址已被带走, never 保持副本周围 - 始终将其溢出到堆栈框架上,并根据需要加载/存储其值。此外,您无论如何都必须这样做才能使x
首先具有一个地址!
请注意,此处没有SSA表格。无论您的中间表示形式是否以SSA形式。