【发布时间】:2015-07-23 03:18:46
【问题描述】:
这与How to force const propagation through an inline function? Clang 有一个集成的汇编器有关;并且它不使用系统的汇编程序(通常是 GNU AS (GAS))。 Non-Clang 很早就完成了数学运算,一切都“正常运行”。
我说“早”是因为@n.m。反对将其描述为“由预处理器执行的数学运算”。但想法是该值在编译时是已知的,并且应该尽早评估它,就像预处理器评估 #if (X % 32 == 0) 时一样。
下面,Clang 3.6 抱怨违反了约束。看来该常量并未在整个过程中传播:
$ export CXX=/usr/local/bin/clang++
$ $CXX --version
clang version 3.6.0 (tags/RELEASE_360/final)
Target: x86_64-apple-darwin12.6.0
...
$ make
/usr/local/bin/clang++ -DNDEBUG -g2 -O3 -Wall -fPIC -arch i386 -arch x86_64 -pipe -Wno-tautological-compare -c integer.cpp
In file included from integer.cpp:8:
In file included from ./integer.h:7:
In file included from ./secblock.h:7:
./misc.h:941:44: error: constraint 'I' expects an integer constant expression
__asm__ ("rolb %1, %0" : "+mq" (x) : "I" ((unsigned char)(y%8)));
^~~~~~~~~~~~~~~~~~~~
./misc.h:951:44: error: constraint 'I' expects an integer constant expression
...
上面的函数是内联模板特化:
template<> inline byte rotrFixed<byte>(byte x, unsigned int y)
{
// The I constraint ensures we use the immediate-8 variant of the
// shift amount y. However, y must be in [0, 31] inclusive. We
// rely on the preprocessor to propoagte the constant and perform
// the modular reduction so the assembler generates the instruction.
__asm__ ("rorb %1, %0" : "+mq" (x) : "I" ((unsigned char)(y%8)));
return x;
}
它们是使用 const 值调用的,因此旋转量在编译时是已知的。一个典型的调用者可能看起来像:
unsigned int x1 = rotrFixed<byte>(1, 4);
unsigned int x2 = rotrFixed<byte>(1, 32);
如果GCC 或Clang 提供了执行rotate in near constant time 的内在函数,则不需要这些[可疑] 技巧。我什至会满足于“执行旋转”,因为他们甚至没有。
让 Clang 恢复执行 const 值的预处理需要什么技巧?
精明的读者会认识到,如果使用传统的 C/C++ 循环,rotrFixed<byte>(1, 32) 可能是未定义的行为。所以我们进入汇编程序以避免 C/C++ 的限制并享受 1 指令加速。
好奇的读者可能想知道我们为什么要这样做。密码学家提出了规范,有时这些规范并不赞同底层硬件或标准机构。我们没有更改密码学家的规范,而是尝试逐字提供以使审计更容易。
我不知道 Clang 有什么保证,但我知道编译器和集成汇编器声称与 GCC 和 GNU 的汇编器兼容。而GCC和GAS提供了常数值的传播。
【问题讨论】:
-
您一直在谈论预处理算法,但您的代码中没有任何#define 常量。
-
您可以通过
-no-integrated-as使用系统汇编器。 -
如果
y在comoile时间是已知的,为什么不把它作为模板参数呢? -
@n.m. - 两个原因。首先,这会改变 ABI。 (我们正在为过去的罪孽付出代价)。其次,它不一定适用于 Clang/LLVM。对于 (2),请参阅 Sean 在LLVM Bug 24226 的评论。 (Sean 是 LLVM 维护者之一)。
-
无论如何它是内联和模板。这里没有 ABI 问题。 API 可能。