0

假设我想在设置标志时更改变量的值。一个明显的方法如下。

int a = 1, b = 2;
if(Flag)
    {
    a=b;
    Flag = false;
    }

然而,WRT 为执行操作而生成的代码是非常低效的。我发现以下生成的代码减少了 40% 来执行操作。

a = ((!Flag)*a)+((Flag)*b);
Flag = false;

我的问题:我宁愿不使用乘法“*”运算符,因为乘法/除法运算符在我的目标上执行速度较慢。在不增加代码空间的情况下,我还能用什么来加快速度?

编辑:目标设备是在 kHz 范围内运行的 MSP430。代码空间和执行时间至关重要。编译器是 IAR C

4

4 回答 4

1

我会这样写,不考虑微优化:

int b = 2, a = Flag ? b : 1;

Flag = false;

看看效率如何。

于 2012-10-22T18:30:52.610 回答
1

以下内容无需使用乘法或任何条件即可实现您想要的逻辑:

unsigned int mask = Flag-1;
a = (mask & a) | (~mask & b);

所以当 Flag==1 你得到

a = (0x0 & a) | (0xffff & b);

当 Flag==0 你得到

a = (0xffff & a) | (0x0 & b);

(你也不需要一个单独的变量来掩码。你可以做--Flag并使用Flag而不是mask,我只是认为它会使解决方案更清晰一些。)

于 2012-10-22T17:28:49.617 回答
1

您的编译器能够比此hack更好地优化您的代码(检查生成的程序集)。除了在比较慢的处理器上(例如 PowerPC),你应该避免它。无论如何,看看这里,如果你仍然有动力。

于 2012-10-22T17:18:11.823 回答
0

您的初始代码尽可能有效。如果您能够通过其他一些晦涩难懂的混淆生成更有效的代码,那么您的编译器的优化要么配置不正确,要么写得不好。前者更有可能,但如果是后者,请询问 IAR 为什么他们的编译器会生成错误的代码。不要试图通过编写混淆代码来修复他们的编译器。

您不需要使用条件 ?: 运算符,它应该生成完全相同的代码。

此外,我对 MSP430 了解不多,但它平均为 16 位,并且没有任何超高级指令缓存或分支预测,如果你认为它有,你只是在自欺欺人。即使有,您仍然不应该混淆您的代码。

于 2012-10-22T19:28:12.950 回答