数组访问和分配在 clang 生成的 LLVM IR 输出中具有可变对齐大小

Array access and assignment has variable alignment size in LLVM IR output generated by clang

嘿,我正在开发一个编译器项目。 在尝试将数组元素分配实现时,我 运行 到这段 llvm ir 代码中:


define dso_local i32 @main() {
  %1 = alloca [10 x i32], align 16
  %2 = getelementptr inbounds [10 x i32], [10 x i32]* %1, i64 0, i64 0
  store i32 2, i32* %2, align 16
  %3 = getelementptr inbounds [10 x i32], [10 x i32]* %1, i64 0, i64 1
  store i32 4, i32* %3, align 4
  %4 = getelementptr inbounds [10 x i32], [10 x i32]* %1, i64 0, i64 2
  store i32 6, i32* %4, align 8
  %5 = getelementptr inbounds [10 x i32], [10 x i32]* %1, i64 0, i64 3
  store i32 8, i32* %5, align 4
  %6 = getelementptr inbounds [10 x i32], [10 x i32]* %1, i64 0, i64 4
  store i32 10, i32* %6, align 16
  ret i32 0
}

生成自:

int main () {
    int x[10];
    x[0] = 2;
    x[1] = 4;
    x[2] = 6;
    x[3] = 8;
    x[4] = 10;
}

在检查红外输出时,我注意到对齐似乎总是不同 (16-4-8-4)。我对此感到非常困惑,并且不知道为什么对齐方式会发生变化。任何正确方向的提示或推动将不胜感激。

Clang 似乎在使用它对 alloca 的对齐方式和指针偏移量的了解来单独计算每个元素的最大对齐方式。 alloca 与 16B 对齐,因此指向元素 0(无偏移量)的指针将具有该对齐方式。但是由于alloca中数组中的元素大小只有4B(i32),小于16B,所以一旦偏移得到后面的元素,指针对齐就会发生变化

Clang 可以将此处所有内容的对齐设置为 4,但没有规则要求这样做。此外,对数组使用这种 16 的大对齐还有一些好处,例如可以使用 SIMD 指令一次加载 4 个元素 (4 × 4B = 16B)。