如何防止声明为局部变量的对象被分配到堆栈中?

时间:2016-11-12 17:21:56

标签: c++ optimization arm embedded

在使用ARM / Keil编译器为小型ARM处理器编译C ++时,我正在努力解决性能问题。

在执行某些处理的函数中,我有以下结构的代码:

{
    MyClass temp = global_variable_input;

    Operation 1 on temp;
    Operation 2 on temp;
    ...
    Operation N on temp;

    global_variable_output = temp;
}

MyClass用于建模数学对象,唯一的成员是32位整数(即,对象的完整大小为4个字节)。

所有操作都涉及使用重载运算符或MyClass方法,并将“temp”的值更改为结果。有些操作很简单,内联(在类中内联声明的方法),有些操作更复杂,需要生成对方法的调用。

看一下编译器为我的例程生成的汇编程序代码,我注意到编译器为堆栈中的“temp”分配空间,并且每个操作(也是内联的!)都将操作的结果存储在放在堆栈中,然后继续使用上次操作中存储在寄存器中的值。对于非内联类型,编译器将指针传递给寄存器r1中的对象(this)和指向堆栈中创建的另一个对象的指针,以将结果存储在寄存器r0中。

代码实现了一个信号处理算法,您可以将其想象为temp上的一系列算术运算,因此在每次单个操作(可能只是一个操作码)之后,使用这个额外的“store”指令和相应的内存访问在实施过程中引入了巨大的性能损失。

理想情况下,我希望编译器仅使用寄存器来完成操作,而不是保持每次操作后需要更新的“temp”的堆叠版本。

另一个愿望是它将对象的当前值简单地使用寄存器传递给方法(就像ARM C调用约定为普通C函数指定的那样)并以相同的方式获得结果,而不是使用指针到记忆位置。

我要求的太多了吗?如何让我的ARM / Keil编译器以这种方式工作?

PS:这个函数很简单,所以它不像编译器需要在堆栈中分配我的变量,因为它用完了寄存器。我怀疑它之所以这样做是因为它需要有一个指针传递给非内联方法,然后认为有必要保持堆栈中的值始终是最新的。

非常感谢!

2 个答案:

答案 0 :(得分:1)

使用像

这样的参考
MyClass& temp = global_variable_input;

会避免在堆栈(本地存储)上分配MyClass的完整副本

虽然有

Operation 1 on temp;
Operation 2 on temp;
// ...

也会影响原始global_variable_input

答案 1 :(得分:-2)

您可以将您的班级更改为结构。它将存储在堆栈而不是堆中。