[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