Next: , Previous: LCSSA, Up: Loop Analysis and Representation


14.5 标量演化

标量演化(SCEV)用来表示在GIMPLE之上的归纳变量分析结果。它使得我们能够通过简单一致的方式来表示具有复杂性为的变量(我们只使用它来表示多项式归纳变量的值,但是是可以进一步扩展的)。SCEV分析的接口声明在tree-scalar-evolution.h中。要使用标量演化分析,则必须使用scev_initialize。要停止使用SCEV,则使用scev_finalize。为了节省时间和内存,SCEV分析会缓存结果。但是这些缓存会被大多数循环转换变为无效,包括代码移除。如果执行了这样的转换,则必须调用scev_reset来清除缓存。

给定一个SSA名字, 能够使用analyze_scalar_evolution函数来分析它在循环中的行为。然而返回的SCEV不需要被完全分析,并且它可以包含对其它定义在循环中的SSA名字的引用。必须使用instantiate_parameters或者resolve_mixers函数来解决这些(潜在的递归)引用。当你将SCEV的结果只用于某种分析时,并且一次工作于整个循环嵌套时,instantiate_parameters会很有用。它将尝试替换所有的SSA名字,用它们在所有循环中的SCEV,包括当前循环的外层循环,因此提供了在循环嵌套中的变量行为的完全信息。当你一次只工作于一个循环,并且可能需要根据归约变量的值来创建代码时,resolve_mixers会很有用。它会只解决定义在当前循环中的SSA名字,而保留外面定义的SSA名字不变,即使它们在外循环中的演化是已知的。

SCEV是一个标准的树表达式,除去实际上它可以包含多个特定的树节点。SCEV_NOT_KNOWN为其中之一,用于值无法被表示的SSA名字。另一个是POLYNOMIAL_CHREC。多项式chrec有三个参数—— base,step和loop(base和step都可以进一步包含多项式chrecs)。表达式,base和step的类型必须相同。在下面的例子中,如果变量(在特定的循环中)等于x_1,则具有演化POLYNOMIAL_CHREC(base, step, loop)

     while (...)
       {
         x_1 = phi (base, x_2);
         x_2 = x_1 + step;
       }

注意这包括操作数上的语言限制。例如,如果我们编译C代码,并且x具有有符号类型,那么加法溢出将会产生未定义行为,并且我们可以假设这并没有发生。因此,SCEV的值不能溢出。

许多情况下,只是想放射归约变量。这时,额外的SCEV的表达式幂就没有用处,并且可能会使优化变得复杂。这时,可以使用simple_iv函数来分析一个值——结果为循环不变量base和step。