提问人:imakak 提问时间:3/13/2021 最后编辑:imakak 更新时间:9/26/2021 访问量:262
C (MIPS) - 如何判断编译器加载单精度浮点数与 GPR 的模拟?
C (MIPS) - How to tell compiler load single-precision floats immidiates with GPRs?
问:
最近,我正在尝试使用 gcc 为 n64 编写一些实用程序,但它的优化策略存在一些问题。
请考虑以下示例:
// cctest.c
extern struct {
float x;
float y;
float z;
} var;
void *test() {
float t;
t = 5.0;
var.x = var.x + t;
var.y = 10.0;
var.z = 60.0;
return (void*)&var;
}
我的 except 输出是这样的:
lui $2, %hi(var)
lui $1, 0x40A0
addiu $2,$2,%lo(var)
mtc1 $1, $f2
lwc1 $f0, 0x0($2)
lui $3, 0x4120
lui $4, 0x4270
sw $3, 0x4($2)
add.s $f0, $f0, $f2
sw $4, 0x8($2)
jr $31
swc1 $f0, 0x0($2)
但是,编译器会生成:
; cctest.s
; In .text
lui $3,%hi(var)
lui $2,%hi($LC0)
lwc1 $f0,%lo(var)($3)
lwc1 $f2,%lo($LC0)($2)
lui $5,%hi($LC1)
add.s $f0,$f0,$f2
addiu $2,$3,%lo(var)
lui $4,%hi($LC2)
swc1 $f0,%lo(var)($3)
lwc1 $f0,%lo($LC1)($5)
swc1 $f0,4($2)
lwc1 $f0,%lo($LC2)($4)
jr $31
swc1 $f0,8($2)
; In .rodata
.align 2
$LC0:
.word 1084227584
.align 2
$LC1:
.word 1092616192
.align 2
$LC2:
.word 1114636288
并给出以下标志:
-G0 -fomit-frame-pointer -fno-PIC -mips3 -march=vr4300 -mtune=vr4300 -mabi=32 -mlong32 -mno-shared -mgp32 -mhard-float -mno-check-zero-division -fno-stack-protector -fno-common -fno-zero-initialized-in-bss -mno-abicalls -mno-memcpy -mbranch-likely -O3
我对 mips3 不是很有经验;但是由于目标计算机 (n64) 的 RAM 和 DCache 非常有限,我认为将所有内容放入内存似乎不是一个好主意。
我去了 gcc 的 MIPS 选项页面,但没有找到任何帮助。
环境是 mingw64(msys2) 和 gcc-10.2.0(mips64-elf),其中 gcc 配置了
--build=x86_64-w64-mingw32 \
--host=x86_64-w64-mingw32 \
--prefix="./" \
--target=mips64-elf --with-arch=vr4300 \
--enable-languages=c,c++ --without-headers --with-newlib \
--with-gnu-as=./bin/mips64-elf-as.exe \
--with-gnu-ld=./bin/mips64-elf-ld.exe \
--enable-checking=release \
--enable-shared \
--enable-shared-libgcc \
--disable-decimal-float \
--disable-gold \
--disable-libatomic \
--disable-libgomp \
--disable-libitm \
--disable-libquadmath \
--disable-libquadmath-support \
--disable-libsanitizer \
--disable-libssp \
--disable-libunwind-exceptions \
--disable-libvtv \
--disable-multilib \
--disable-nls \
--disable-rpath \
--disable-symvers \
--disable-threads \
--disable-win32-registry \
--enable-lto \
--enable-plugin \
--enable-static \
--without-included-gettext
有没有办法告诉 gcc 将这种单精度浮点常数放在 GPR 而不是内存中,以防它们的下 16 位为零?
编辑1
尝试使用带有标志的 clang (11.0)
clang -S --target=mips-none-elf -O2 -G0 -ffreestanding -fomit-frame-pointer -ffast-math -mabi=o32 -mno-check-zero-division -mfp32
输出为:
; cctest.llvm.s
; In .rodata ...
$CPI0_0:
.4byte 0x40a00000
; In .text ...
lui $1, %hi(var)
addiu $2, $1, %lo(var)
lui $3, 17008
sw $3, 8($2)
lui $3, 16672
sw $3, 4($2)
lui $3, %hi($CPI0_0)
lwc1 $f0, %lo($CPI0_0)($3)
lwc1 $f1, %lo(var)($1)
add.s $f0, $f1, $f0
jr $ra
swc1 $f0, %lo(var)($1)
与 gcc 相比,它仍然在内存中,但它用于加载到 和 到 。5.0
$3
10.0
var.y
60.0
var.z
请注意,clang 在 64 位处理器上缺乏对 o32 ABI 的支持,并且对特定处理器进行了修复。
编辑2
我注意到旧版本的 gcc 能够严格优化这一点:
; egcs-mips-linux-1.1.2-4.i386
; binutils-mips-linux-2.9.5-3.i386
;
; cctest.egcs112.s
; -O2 -non_shared -mips3 -G 0 -mcpu=4300
; .text
.set noreorder
.cpload $25 ; GPT with -G 0? no idea why
.set reorder ; Allow as to reorder instructions
la $2,var
li.s $f6,5.00000000000000000000e0 ; This pseudo op will expand to lui + mtc0
l.s $f0,0($2)
li.s $f2,1.00000000000000000000e1
li.s $f4,6.00000000000000000000e1
add.s $f0,$f0,$f6
s.s $f2,4($2)
s.s $f4,8($2)
.set noreorder
.set nomacro
j $31
s.s $f0,0($2)
.set macro
.set reorder
事实证明,在添加的 64 位支持中,在某个时候放弃了一些优化。
目前,在 gcc source 中,mips.c 和 mips.md 中定义的直接传输的唯一方法是通过内存加载;我不确定这是一个错误还是有意为之,因为在某些情况下,一些古老的 gcc 版本能够生成高效的代码。
总之,使用 gcc 的现代官方版本无法执行此类优化;但是,这可以通过切换回 199x 版本或进行自定义构建以手动添加支持来完成。
答: 暂无答案
评论