LLVM的amd64输出中向量的对齐问题

3

我正在尝试在LLVM中使用结构体内的向量。我有以下C结构体定义:

struct Foo
{
    uint32_t len;
    uint32_t data[32] __attribute__ ((aligned (16)));
};

这里有一些LLVM代码,用于将42添加到data字段的第3个元素中:

%Foo = type { i32, <32 x i32> }

define void @process(%Foo*) {
_L1:
  %data = getelementptr %Foo* %0, i32 0, i32 1
  %vec = load <32 x i32>* %data
  %x = extractelement <32 x i32> %vec, i32 3
  %xNew = add i32 42, %x
  %vecNew = insertelement <32 x i32> %vec, i32 %xNew, i32 3
  store <32 x i32> %vecNew, <32 x i32>* %data
  ret void
}

然而,llc的输出似乎需要将向量对齐到128字节,这似乎很浪费,并且也是错误的(据我所知,向量应该是16字节对齐的):

    .file   "process.bc"
    .text
    .globl  process
    .align  16, 0x90
    .type   process,@function
process:                                # @process
.Leh_func_begin0:
# BB#0:                                 # %_L1
    movdqa  128(%rdi), %xmm0
    pextrd  $3, %xmm0, %eax
    addl    $42, %eax
    pinsrd  $3, %eax, %xmm0
    movdqa  %xmm0, 128(%rdi)
    ret
.Ltmp0:
    .size   process, .Ltmp0-process
.Leh_func_end0:

当然,如果我也将C定义更改为在128字节处对齐数据字段,那么它就可以工作了,但是浪费124字节(与使用16字节对齐相比仅浪费12字节)似乎是不正确的。那么这里发生了什么?

我刚刚意识到16字节=128位,所以也许这是一个LLVM的bug,它将向量对齐到128字节而不是128位。 - Cactus
1个回答

2

我认为你的GEPs对于最佳代码生成有些偏差。这里有一些类似的C代码:

#include <stdint.h>

struct Foo
{
  uint32_t len;
  uint32_t data[32] __attribute__ ((aligned (16)));
};

void foo(struct Foo *F)
{
  F->data[3] = 4;
}

这将被clang转换为:

; ModuleID = 'foo.c'
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
target triple = "x86_64-apple-darwin10.0.0"

%struct.Foo = type { i32, [12 x i8], [32 x i32] }

define void @foo(%struct.Foo* %F) nounwind ssp {
  %1 = alloca %struct.Foo*, align 8
  store %struct.Foo* %F, %struct.Foo** %1, align 8
  %2 = load %struct.Foo** %1, align 8
  %3 = getelementptr inbounds %struct.Foo* %2, i32 0, i32 2
  %4 = getelementptr inbounds [32 x i32]* %3, i32 0, i64 3
  store i32 4, i32* %4
  ret void
}

以及相应的漂亮代码,你所期望的:

_foo:                                   ## @foo
Leh_func_begin0:
## BB#0:
    pushq   %rbp
Ltmp0:
    movq    %rsp, %rbp
Ltmp1:
    movl    $4, 28(%rdi)
    popq    %rbp
    ret
Leh_func_end0:

话虽如此,您那里的代码不正确,应该是:

_process:                               ## @process
Leh_func_begin1:
## BB#0:                                ## %_L1
        movaps  16(%rdi), %xmm0
        pextrd  $3, %xmm0, %eax
        addl    $42, %eax
        pinsrd  $3, %eax, %xmm0
        movaps  %xmm0, 16(%rdi)
        ret

在ToT中情况更糟,因此提交错误报告会更好。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接