Clang LLVM IR代码中是否需要align指令?

Clang LLVM IR代码中是否需要align指令?,clang,llvm,jit,llvm-ir,Clang,Llvm,Jit,Llvm Ir,当使用clang++生成IR代码时,它将包含align x指令,并且变量和结构的内存是对齐的。例如: struct-CT{ 字符c1; 布尔b1; int i1; 双d1;//8 字符c2; int i2; }; int main(){ 字符c1='a'; inti1=2; 字符c2='b'; char c3='c'; int i2=4; printf(“c1的地址=%p;\n”、&c1); printf(“i1的地址=%p;\n”、&i1); printf(“c2的地址=%p;\n”、&c2)

当使用clang++生成IR代码时,它将包含
align x
指令,并且变量和结构的内存是对齐的。例如:

struct-CT{
字符c1;
布尔b1;
int i1;
双d1;//8
字符c2;
int i2;
};
int main(){
字符c1='a';
inti1=2;
字符c2='b';
char c3='c';
int i2=4;
printf(“c1的地址=%p;\n”、&c1);
printf(“i1的地址=%p;\n”、&i1);
printf(“c2的地址=%p;\n”、&c2);
printf(“c3的地址=%p;\n”、&c3);
printf(“i2的地址=%p;\n”、&i2);
返回0;
}
它将生成IR代码(带有对齐说明):

source\u filename=“oper.cpp”
目标数据布局=“e-m:o-i64:64-f80:128-n8:16:32:64-S128”
target triple=“x86_64-apple-macosx10.15.0”
@.str=private unnamed_addr常量[22 x i8]c“c1的地址=%p;\0A\00”,对齐1
@.str.1=私有未命名地址常量[22 x i8]c“i1的地址=%p;\0A\00”,对齐1
@.str.2=私有未命名地址常量[22 x i8]c“c2地址=%p;\0A\00”,对齐1
@.str.3=私有未命名地址常量[22 x i8]c“c3地址=%p;\0A\00”,对齐1
@.str.4=私有未命名地址常量[22 x i8]c“i2的地址=%p;\0A\00”,对齐1
; 函数属性:noinline norecurse optnone ssp uwtable
定义i32@main()#0{
%1=alloca i32,对齐4
%2=alloca i8,对齐1
%3=alloca i32,对齐4
%4=alloca i8,对齐1
%5=alloca i8,对齐1
%6=alloca i32,对齐4
存储i32 0,i32*%1,对齐4
存储i8 97,i8*%2,对齐1
存储i32 2,i32*%3,对齐4
存储i8 98,i8*%4,对齐1
存储i8 99,i8*%5,对齐1
存储i32 4,i32*%6,对齐4
%7=调用i32(i8*,…)@printf(i8*getelementptr-inbounds([22 x i8],[22 x i8]*@.str,i64 0,i64 0),i8*%2)
%8=调用i32(i8*,…)@printf(i8*getelementptr-inbounds([22 x i8],[22 x i8]*@.str.1,i64 0,i64 0),i32*%3)
%9=调用i32(i8*,…)@printf(i8*getelementptr-inbounds([22 x i8],[22 x i8]*@.str.2,i64 0,i64 0),i8*%4)
%10=调用i32(i8*,…)@printf(i8*getelementptr-inbounds([22 x i8],[22 x i8]*@.str.3,i64 0,i64 0),i8*%5)
%11=调用i32(i8*,…)@printf(i8*getelementptr-inbounds([22 x i8],[22 x i8]*@.str.4,i64 0,i64 0),i32*%6)
ret i32 0
}
声明i32@printf(i8*,…)#1
这将输出:

c1的地址=0x7ffee900328b; i1的地址=0x7ffee9003284; c2地址=0x7ffee9003283; c3的地址=0x7ffee9003282; i2的地址=0x7ffee900327c; 我们可以看到变量的内存是对齐的

但是如果删除IR代码的align指令,它也会正确运行,并且变量的内存也会对齐。如以下IR代码:

source\u filename=“oper.cpp”
目标数据布局=“e-m:o-i64:64-f80:128-n8:16:32:64-S128”
target triple=“x86_64-apple-macosx10.15.0”
@.str=私有未命名地址常量[22 x i8]c“c1的地址=%p;\0A\00”
@.str.1=私有未命名地址常量[22 x i8]c“i1的地址=%p;\0A\00”
@.str.2=私有未命名地址常量[22 x i8]c“c2的地址=%p;\0A\00”
@.str.3=私有未命名地址常量[22 x i8]c“c3的地址=%p;\0A\00”
@.str.4=私有未命名地址常量[22 x i8]c“i2的地址=%p;\0A\00”
; 函数属性:noinline norecurse optnone ssp uwtable
定义i32@main()#0{
%1=alloca i32
%2=alloca i8
%3=alloca i32
%4=alloca i8
%5=alloca i8
%6=alloca i32
存储i32 0,i32*%1
存储i8 97,i8*%2
存储i32 2,i32*%3
存储i8 98,i8*%4
存储i8 99,i8*%5
存储i32 4,i32*%6
%7=调用i32(i8*,…)@printf(i8*getelementptr-inbounds([22 x i8],[22 x i8]*@.str,i64 0,i64 0),i8*%2)
%8=调用i32(i8*,…)@printf(i8*getelementptr-inbounds([22 x i8],[22 x i8]*@.str.1,i64 0,i64 0),i32*%3)
%9=调用i32(i8*,…)@printf(i8*getelementptr-inbounds([22 x i8],[22 x i8]*@.str.2,i64 0,i64 0),i8*%4)
%10=调用i32(i8*,…)@printf(i8*getelementptr-inbounds([22 x i8],[22 x i8]*@.str.3,i64 0,i64 0),i8*%5)
%11=调用i32(i8*,…)@printf(i8*getelementptr-inbounds([22 x i8],[22 x i8]*@.str.4,i64 0,i64 0),i32*%6)
ret i32 0
}
声明i32@printf(i8*,…)#1
这也将输出变量的对齐地址,无论您使用clang命令还是LLJIT(LLVM的工具API)


我的问题:

  • 我们无法将align指令添加到IR代码?LLVM JIT会自动添加它吗

  • 根据目标布局中的指定,LLVM具有每个数据类型的可配置对齐方式。但是,您也可以在alloca指令中指定对齐方式,这有时很有用,因为并非每种源语言的每一条规则都清晰地映射到目标布局系统。有时编译器会生成冗余输出,并且通过两种方式指定相同的效果。这似乎是其中的一次。明白了,谢谢回复。LLVM根据目标布局中指定的数据类型具有可配置的对齐方式。但是,您也可以在alloca指令中指定对齐方式,这有时很有用,因为并非每种源语言的每一条规则都清晰地映射到目标布局系统。有时编译器会生成冗余输出,并且通过两种方式指定相同的效果。这似乎是其中一次。明白了,谢谢回复。