LLVM 有常量表达式的概念,https://llvm.org/docs/LangRef.html#constant-expressions
这些是一种将算术和逻辑等各种运算应用于常量操作数的方法,其语法与指令中这些运算的使用类似,但不相同,例如它将
( )
放在操作数周围。
您可能认为它们会用于 C 源代码中的常量表达式,例如
1 + 2
,但事实并非如此。这些只是由编译器立即评估。
那么 LLVM 常量表达式有什么用呢?它们用于仅在链接或加载时值是已知常量的情况,例如
int a[100];
int *b = a + 30;
编译为
@a = dso_local global [100 x i32] zeroinitializer, align 16
@b = dso_local global ptr getelementptr (i8, ptr @a, i64 120), align 8
因此专门使用了
getelementptr
常量表达式。
是否有任何源构造可以让 Clang 或任何其他基于 LLVM 的编译器使用
getelementptr
以外的操作发出 LLVM 常量表达式?
LLVN 常量用于在解析源语言结束时需要常量的情况。您已经了解了 getelementptr,它的某些参数需要常量。
它们不会被用在其他地方,尽管没有什么禁止,因为 LLVM 通常试图使源语言的解析变得简单。 LLVM 的生活方式是前端解析、生成 IR,并且不过多考虑 IR 是什么。后来LLVM通过苦思如何优化IR。
源语言解析器可以通过多种方式发现和使用优化机会。使用 LLVM 的编译器通常不会这样做。例如,Clang 经常在函数开始时生成一条死指令,因为解析器不知道该指令是否还活着。