如何在 x86 上使用 llvm-clang 将 neon 内在函数转换为 llvm-IR
How to translate neon intrinsics to llvm-IR using llvm-clang on x86
使用clang我们可以编译C程序生成IR:
clang -S -emit-llvm hello.c -o hello.ll
我想将 neon intrinsic 翻译成 llvm-IR,代码如下:
/* neon_example.c - Neon intrinsics example program */
#include <stdint.h>
#include <stdio.h>
#include <assert.h>
#include <arm_neon.h>
/* fill array with increasing integers beginning with 0 */
void fill_array(int16_t *array, int size)
{ int i;
for (i = 0; i < size; i++)
{
array[i] = i;
}
}
/* return the sum of all elements in an array. This works by calculating 4 totals (one for each lane) and adding those at the end to get the final total */
int sum_array(int16_t *array, int size)
{
/* initialize the accumulator vector to zero */
int16x4_t acc = vdup_n_s16(0);
int32x2_t acc1;
int64x1_t acc2;
/* this implementation assumes the size of the array is a multiple of 4 */
assert((size % 4) == 0);
/* counting backwards gives better code */
for (; size != 0; size -= 4)
{
int16x4_t vec;
/* load 4 values in parallel from the array */
vec = vld1_s16(array);
/* increment the array pointer to the next element */
array += 4;
/* add the vector to the accumulator vector */
acc = vadd_s16(acc, vec);
}
/* calculate the total */
acc1 = vpaddl_s16(acc);
acc2 = vpaddl_s32(acc1);
/* return the total as an integer */
return (int)vget_lane_s64(acc2, 0);
}
/* main function */
int main()
{
int16_t my_array[100];
fill_array(my_array, 100);
printf("Sum was %d\n", sum_array(my_array, 100));
return 0;
}
但它不支持 neon intrinsic,并打印如下错误消息:
/home/user/llvm-proj/build/bin/../lib/clang/4.0.0/include/arm_neon.h:65:24: error:
'neon_vector_type' attribute is not supported for this target
typedef __attribute__((neon_vector_type(8))) float16_t float16x8_t;
^
我认为原因是我的主机在 x86 上,但目标在 ARM 上。
而且我不知道 how to Cross-compilation using Clang 转换为 llvm-IR(ubuntu 14.04 上的 clang 版本是 4.0)。
是否有任何目标选项命令或其他工具有用?
SSE 和 neon llvm-IR 有什么区别?
使用 ELLCC,一个预打包的基于 clang 的工具链 (http://ellcc.org),我能够通过添加 -mfpu=neon:
来编译和 运行 你的程序
rich@dev:~$ ~/ellcc/bin/ecc -target arm32v7-linux -mfpu=neon neon.c
rich@dev:~$ ./a.
a.exe a.out
rich@dev:~$ file a.out
a.out: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), statically linked, BuildID[sha1]=613c22f6bbc277a8d577dab7bb27cd64443eb390, not stripped
rich@dev:~$ ./a.out
Sum was 4950
rich@dev:~$
它是在 x86 上编译的,我 运行 它使用 QEMU。
使用普通的 clang,您还需要适用于 ARM 的适当 -target 选项。 ELLCC 使用略有不同的 -target 选项。
使用clang我们可以编译C程序生成IR:
clang -S -emit-llvm hello.c -o hello.ll
我想将 neon intrinsic 翻译成 llvm-IR,代码如下:
/* neon_example.c - Neon intrinsics example program */
#include <stdint.h>
#include <stdio.h>
#include <assert.h>
#include <arm_neon.h>
/* fill array with increasing integers beginning with 0 */
void fill_array(int16_t *array, int size)
{ int i;
for (i = 0; i < size; i++)
{
array[i] = i;
}
}
/* return the sum of all elements in an array. This works by calculating 4 totals (one for each lane) and adding those at the end to get the final total */
int sum_array(int16_t *array, int size)
{
/* initialize the accumulator vector to zero */
int16x4_t acc = vdup_n_s16(0);
int32x2_t acc1;
int64x1_t acc2;
/* this implementation assumes the size of the array is a multiple of 4 */
assert((size % 4) == 0);
/* counting backwards gives better code */
for (; size != 0; size -= 4)
{
int16x4_t vec;
/* load 4 values in parallel from the array */
vec = vld1_s16(array);
/* increment the array pointer to the next element */
array += 4;
/* add the vector to the accumulator vector */
acc = vadd_s16(acc, vec);
}
/* calculate the total */
acc1 = vpaddl_s16(acc);
acc2 = vpaddl_s32(acc1);
/* return the total as an integer */
return (int)vget_lane_s64(acc2, 0);
}
/* main function */
int main()
{
int16_t my_array[100];
fill_array(my_array, 100);
printf("Sum was %d\n", sum_array(my_array, 100));
return 0;
}
但它不支持 neon intrinsic,并打印如下错误消息:
/home/user/llvm-proj/build/bin/../lib/clang/4.0.0/include/arm_neon.h:65:24: error:
'neon_vector_type' attribute is not supported for this target
typedef __attribute__((neon_vector_type(8))) float16_t float16x8_t;
^
我认为原因是我的主机在 x86 上,但目标在 ARM 上。 而且我不知道 how to Cross-compilation using Clang 转换为 llvm-IR(ubuntu 14.04 上的 clang 版本是 4.0)。 是否有任何目标选项命令或其他工具有用? SSE 和 neon llvm-IR 有什么区别?
使用 ELLCC,一个预打包的基于 clang 的工具链 (http://ellcc.org),我能够通过添加 -mfpu=neon:
来编译和 运行 你的程序 rich@dev:~$ ~/ellcc/bin/ecc -target arm32v7-linux -mfpu=neon neon.c
rich@dev:~$ ./a.
a.exe a.out
rich@dev:~$ file a.out
a.out: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), statically linked, BuildID[sha1]=613c22f6bbc277a8d577dab7bb27cd64443eb390, not stripped
rich@dev:~$ ./a.out
Sum was 4950
rich@dev:~$
它是在 x86 上编译的,我 运行 它使用 QEMU。
使用普通的 clang,您还需要适用于 ARM 的适当 -target 选项。 ELLCC 使用略有不同的 -target 选项。