gpt4 book ai didi

c - 使用 GCC + ARM 减少递归期间的堆栈使用

转载 作者:太空狗 更新时间:2023-10-29 17:25:14 26 4
gpt4 key购买 nike

我有一个用于嵌入式 ARM 处理器的递归下降解析器(在 C + GCC 中,用于 ARM Cortex M3)。

在运行它时,我注意到它使用了大量的堆栈空间(甚至比您预期的还要多),经过仔细检查,我发现这种情况正在发生:

extern int bar(int *p);

int foo() {
int z = foo(); // it's an example!

int n[100]; // stack usage
return z+bar(n); // calling bar(n) stops n from being optimised out
}

运行arm-none-eabi-gcc -fomit-frame-pointer -S test.c的结果

foo:
str lr, [sp, #-4]! ; Push link register
sub sp, sp, #412 ; Reserve space on stack, even if we don't need it now!
bl foo ; Recurse
str r0, [sp, #404] ; Store result
...

因此在函数开始时,它将整个堆栈帧压入堆栈。然而,在几次迭代之后,它在堆栈中获得了大量尚未使用的内容。

理想情况下,我希望 GCC 生成:

foo:
str lr, [sp, #-4]! ; Push link register
; Don't reserve space, because we don't need it
bl foo ; Recurse
sub sp, sp, #412 ; Reserve space now
str r0, [sp, #404] ; Store result
...

(这可能不正确,但我希望你明白)

类似这样的事情可以用下面的代码实现,但它真的很讨厌(如果 GCC 内联 fooworker,它又会中断!)。一定有更好的方法吗?

int fooworker(int z) {
int n[100]; // stack usage
return z+bar(n); // calling bar(n) stops n from being optimised out
}


int foo() {
return fooworker(foo());
}

那么有没有一种方法可以告诉 GCC 只在基本 block 的开头扩大堆栈,或者是否有一个“障碍”语句导致在该点添加额外的推送/弹出操作?我猜 GCC 正在使用一种 ARM 标准调用类型——但是有没有办法用另一种调用类型标记这些函数,这种调用类型对堆栈的效率更高一些,或者有没有办法重写函数,使堆栈是使用更明智一点?

请不要告诉我不要使用递归,它不是在回答问题。

最佳答案

int *n = alloca(sizeof(*n) * 100);

它很丑陋,我个人将函数分成两部分,但似乎在我的 gcc on amd64 上的所有优化级别上都能正常工作。

关于c - 使用 GCC + ARM 减少递归期间的堆栈使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13155421/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com