To test the performance feature of an assembly language feature, I would like to use it inside a C program with inline assembly to replace existing functionality.
My GNU GAS assembler already recognizes the instruction with an appropriate -march
.
How to make GCC generate code that accepts such inline assembly instructions that is cannot yet emit and does not recognize?
For example, the ARM SVE extensions were more or less recently added to the ARM architecture.
So in a minimal useless inline SVE assembly example I try:
main.c
int main(void) {
__asm__ __volatile__ ("ld1d z1.d, p0/z, [x0, x4, lsl 3]");
}
and I try to compile with:
aarch64-linux-gnu-gcc -c -o main.o --save-temps -v main.c
but assembly fails with:
main.s: Assembler messages:
main.s:10: Error: selected processor does not support `ld1d z1.d,p0/z,[x0,x4,lsl 3]'
The verbose output contains:
/usr/lib/gcc-cross/aarch64-linux-gnu/7/../../../../aarch64-linux-gnu/bin/as -v -EL -mabi=lp64 -o main.o main.s
and main.s
contains:
.arch armv8-a
.file "main.c"
.text
.align 2
.global main
.type main, %function
main:
#APP
// 2 "main.c" 1
ld1d z1.d, p0/z, [x0, x4, lsl 3]
// 0 "" 2
#NO_APP
mov w0, 0
ret
.size main, .-main
.ident "GCC: (Ubuntu/Linaro 7.4.0-1ubuntu1~18.04.1) 7.4.0"
.section .note.GNU-stack,"",@progbits
However, my assembler is new enough to assemble that, since I managed to get it to assemble by either:
- replacing
.arch armv8-a
in the generatedmain.s
file manually with.arch armv8-a+sve
- removing
.arch armv8-a
inmain.s
and adding-march=all
or-march=armv8-a+sve
on the GAS CLI (TODO.arch all
does not exist unfortunately, I wonder why?)
However, if I try to add -march=armv8-a+sve
or -march=all
to the GCC CLI, it complains respectively with:
cc1: error: invalid feature modifier in ‘-march=armv8-a+sve’
cc1: error: unknown value ‘all’ for -march
I also tried to add -Xassembler -march=all
to the GCC CLI:
aarch64-linux-gnu-gcc -Xassembler -march=all -c -o main.o --save-temps -v main.c
and the option does get forwarded to the assembler according to -v
, but it still fails, because the .arch armv8-a
that GCC puts into the assembly file takes precedence.
Out of desperation, I finally tried to modify my C example to:
int main(void) {
__asm__ __volatile__ (".arch armv8-a+sve\nld1d z1.d, p0/z, [x0, x4, lsl 3]");
}
and that did work, but I think it is too insane to be usable. Notably, the .arch armv8-a+sve
stays in effect even after my inline assembly statement, and I don't know how to revert to the previous default GCC .arch
.
I also looked for GCC -masm
options which might be useful like this one but could not find anything interesting.
Tested in Ubuntu 18.04, aarch64-linux-gnu-gcc 7.4.0, aarch64-linux-gnu-as 2.30.