【问题标题】:Alignment of vectors in LLVM's amd64 outputLLVM 的 amd64 输出中的向量对齐
【发布时间】:2011-02-21 12:15:22
【问题描述】:

我正在尝试在带有 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 字节对齐,这似乎很浪费,而且也是错误的(AFAIK 向量应该是 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 错误,它不是 128 位,而是以 128 字节对齐向量。

标签: alignment llvm sse x86-64


【解决方案1】:

我认为您的 GEP 对于最好的代码生成器来说有点偏离。下面是一些类似的 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 中甚至更糟,因此错误报告不会在那里出错。

【讨论】:

    猜你喜欢
    • 2015-07-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多