【发布时间】:2012-03-22 10:43:33
【问题描述】:
我正在构建一个 PowerPC 解释器,它运行良好。在 Power 架构中,条件寄存器 CR0(x86 上的 EFLAGS)几乎在任何指令上都会更新。它是这样设置的。 CR0的值为1,如果最后一个结果为负,如果最后一个结果为正,则为2,否则为4。
我的第一个天真的解释方法是:
if (n < 0)
cr0 = 1
else if (n > 0)
cr0 = 2;
else
cr0 = 4;
但是我知道所有这些分支都不会是最佳的,每秒运行数百万次。我已经看到一些关于 SO 的黑客攻击,但似乎没有一个是过激的。例如,我发现很多例子可以根据符号或 0 将数字转换为 -1、0 或 1。但是如何使 -1 = 1、1 = 2、0 = 4? 我正在寻求 Bit Hackers 的帮助...
提前致谢
更新: 首先:谢谢大家,你们太棒了。我会仔细测试你所有的代码的速度,你会第一个知道谁是赢家。
@jalf:关于你的第一个建议,我实际上并没有在每条指令上计算 CR0。我宁愿保留一个 lastResult 变量,当(如果)以下指令要求一个标志时,进行比较。三个主要动机让我回到了“每次”更新:
- 在 PPC 上,您不必像在 x86 上那样强制更新 CR0(其中 ADD 总是更改 EFLAGS,即使不需要),您有两种类型的 ADD,一种是更新。如果编译器选择使用更新的,这意味着它会在某个时候使用 CR0,所以延迟没有意义......
- 有一个特别痛苦的指令叫做 mtcrf,它可以让你任意改变 CR0。您甚至可以将其设置为 7,没有算术意义...这只会破坏保留“lastResult”变量的可能性。
【问题讨论】:
-
你怎么知道比特旋转会更快?
-
作为对回答者的说明,我们是否可以尝试写出不仅仅是“不要问这个问题”的答案?我们是否可以要么假设 OP 对自己实现这一点感到好奇,而不是依赖编译器,或者无论出于何种原因,编译器生成的代码已经过尝试和检查,但发现速度太慢了?或者,如果做不到这一点,给出一个更好的理由来忽略这个问题,而不仅仅是“你应该闭上眼睛,相信编译器并希望最好”
-
您的解释器在哪个 CPU 上运行?如果您想要接近最佳解决方案的任何东西,可能需要了解指令集
-
+1。很好的问题,还有很多有趣的答案。您可以尝试所有这些并发布一个小基准吗?
-
请注意,即使他这样做了,基准也不一定能告诉您任何事情。你的编译器、你的 CPU,甚至你的操作系统都可能导致不同的结果
标签: c++ bit-manipulation bit bit-shift