-sroa: Scalar Replacement of Aggregates

Description

-sroa pass 尝试将复杂变量(比如 array, struct)的 alloca 给变成一系列 scalar 变量(比如 double , int , char )的 alloca 。 如果有可能的话,还会帮助优化成更 clean 的 SSA form。这些都可以帮助 code 变得更 clean,也可以提升其他 pass 的优化效率(比如 -sroa-mem2reg 一起食用效果会更好)。

alloca struct 听起来很怪,不过这个在 LLVM IR 上有很多应用,这里举个例子比如 LLVM 3.4 compile 的 XSBench 程序里, %low = alloca %struct.NuclideGridPoint*, align 8 。 这也是 -sora target transformation 的地方。

Code Example

这里为了便捷只给 Code after -sora transformation 的例子,我们可以看到 Person 这个 struct 的 initialization 变成了两个 scalar( %i%sum_age )的 alloca

%struct.Person = type { i32, double }

define double @calculate_average(%struct.Person* %people, i32 %num_people) {
entry:
    %sum_age = alloca double
    %i = alloca i32
    store double 0.0, double* %sum_age
    store i32 0, i32* %i

for.cond:                             ; Loop condition
    %1 = load i32, i32* %i
    %2 = icmp slt i32 %1, %num_people
    br i1 %2, label %for.body, label %for.end

for.body:                             ; Loop body
    %3 = load double, double* %sum_age
    %4 = load i32, i32* %i
    %person_ptr = getelementptr %struct.Person, %struct.Person* %people, i32 %4
    %age_ptr = getelementptr i32, i32* %person_ptr, i32 0       ; Access the age directly
    %age = load i32, i32* %age_ptr
    %age_double = sitofp i32 %age to double
    %5 = fadd double %3, %age_double
    store double %5, double* %sum_age
    %6 = add i32 %4, 1
    store i32 %6, i32* %i
    br label %for.cond

for.end:                              ; Loop exit
    %7 = load double, double* %sum_age
    %average = fdiv double %7, double %num_people
    ret double %average
}