[LLVMbugs] [Bug 24226] New: Constant not propagated into inline assembly, results in "constraint 'I' expects an integer constant expression"
bugzilla-daemon at llvm.org
bugzilla-daemon at llvm.org
Wed Jul 22 21:28:29 PDT 2015
https://llvm.org/bugs/show_bug.cgi?id=24226
Bug ID: 24226
Summary: Constant not propagated into inline assembly, results
in "constraint 'I' expects an integer constant
expression"
Product: clang
Version: 3.6
Hardware: All
OS: All
Status: NEW
Severity: normal
Priority: P
Component: Driver
Assignee: unassignedclangbugs at nondot.org
Reporter: noloader at gmail.com
CC: llvmbugs at cs.uiuc.edu
Classification: Unclassified
Attempting to compile the following program using the integrated assembler
results in:
$ clang++ -g2 -O3 clang-test.cpp -o clang-test.exe
clang-test.cpp:16:11: error: invalid operand for inline asm constraint 'I'
__asm__ ("rorl %1, %0" : "+mq" (value) : "I" ((unsigned char)(rot...
^
1 error generated.
It appears the integrated assembler does not receive the const value "2". Even
2%32 is constant because the preprocessor can perform the math.
The program is OK on other Linux OS's using GCC/GAS.
**********
// clang++ -g2 -O3 clang-test.cpp -o clang-test.exe
unsigned int RightRotate(unsigned int value, unsigned int rotate);
int main(int argc, char* argv[])
{
return RightRotate(argc, 2);
}
unsigned int RightRotate(unsigned int value, unsigned int rotate)
{
// x = value; y = rotate
// The I constraint ensures we use the immediate-8 variant of the
// rotate amount y. However, y must be in [0, 31] inclusive. We
// rely on the preprocessor to propagate the constant and perform
// the modular reduction so the assembler generates the instruction.
__asm__ ("rorl %1, %0" : "+mq" (value) : "I" ((unsigned char)(rotate%32)));
return value;
}
**********
Applies to both:
$ /usr/local/bin/clang++ -v
clang version 3.6.0 (tags/RELEASE_360/final)
Target: x86_64-apple-darwin12.6.0
And
$ clang++ -v
Apple LLVM version 5.1 (clang-503.0.40) (based on LLVM 3.4svn)
Target: x86_64-apple-darwin12.6.0
**********
We are jumping through these hoops because the cryptographers often call out
specs that are not sympathetic to hardware and standards.
**********
The real code is hairier, and it involves a well defined template
implementations that avoids branching (i.e., all instructions always execute
and it C/C++ avoids undefined behavior):
// Well defined for all y, near constant time
template <class T> inline T rotrImmediateMod(T x, unsigned int y)
{
static const unsigned int THIS_SIZE = sizeof(T)*8;
y %= THIS_SIZE;
return T((x>>y) | (x<<((THIS_SIZE-y) % THIS_SIZE)));
}
Combined with specializations:
template<> inline word32 rotrImmediateMod<word32>(word32 x, unsigned int y)
{
__asm__ ("rorl %1, %0" : "+g" (x) : "I" ((unsigned char)(y%32)));
return x;
}
**********
I'll send a case of Heinekens anywhere in the world to the first person who
provides a near constant time intrinsic for left- and right-rotate. I'm amazed
Clang does not provide one
(http://llvm.org/docs/LangRef.html#intrinsic-functions).
With the intrinsic, we avoid all the C/C++ undefined behavior, we avoid the
branching, we get the 1 ASM instruction speedup, and we avoid all the hassles
of inline assembly.
--
You are receiving this mail because:
You are on the CC list for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-bugs/attachments/20150723/73bf042f/attachment.html>
More information about the llvm-bugs
mailing list