In the extended built-in asm in the GCC style, you can display a "virtualized" logical value, for example. carry flag?

If I have the following C ++ code to compare two 128 bit unsigned integers, with inline amd-64 asm:

struct uint128_t {
    uint64_t lo, hi;
};
inline bool operator< (const uint128_t &a, const uint128_t &b)
{
    uint64_t temp;
    bool result;
    __asm__(
        "cmpq %3, %2;"
        "sbbq %4, %1;"
        "setc %0;"
        : // outputs:
        /*0*/"=r,1,2"(result),
        /*1*/"=r,r,r"(temp)
        : // inputs:
        /*2*/"r,r,r"(a.lo),
        /*3*/"emr,emr,emr"(b.lo),
        /*4*/"emr,emr,emr"(b.hi),
        "1"(a.hi));
    return result;
}

Then it will be installed very efficiently, but with one drawback. The return value is executed through the "interface" of the general register with the value 0 or 1. This adds two or three extra additional instructions and distracts from the comparison operation, which otherwise would have been completely optimized. The generated code will look something like this:

    mov    r10, [r14]
    mov    r11, [r14+8]
    cmp    r10, [r15]
    sbb    r11, [r15+8]
    setc   al
    movzx  eax, al
    test   eax, eax
    jnz    is_lessthan

If I use "sbb% 0,% 0" with a return value of "int" instead of "setc% 0" with a return value of "bool", there are two additional instructions:

    mov    r10, [r14]
    mov    r11, [r14+8]
    cmp    r10, [r15]
    sbb    r11, [r15+8]
    sbb    eax, eax
    test   eax, eax
    jnz    is_lessthan

I want it:

    mov    r10, [r14]
    mov    r11, [r14+8]
    cmp    r10, [r15]
    sbb    r11, [r15+8]
    jc     is_lessthan

GCC asm , . , , . "" .

, GCC ( Intel ++, asm), , ?

, - , ?

+5
2

7 , YES, gcc, , " " ( 6.1.0, ~ 2016 ). , , , :

/* Test if bit 0 is set in 'value' */
char a;

asm("bt $0, %1"
    : "=@ccc" (a)
    : "r" (value) );

if (a)
   blah;

=@ccc: ( =) @cc, ( c ).

, ( gcc 128- ), ( ) 1 326 . , .

, asm . , , () "" .

FWIW.

+3

, . :

inline bool operator< (const uint128_t &a, const uint128_t &b)
{
    register uint64_t temp = a.hi;
    __asm__(
        "cmpq %2, %1;"
        "sbbq $0, %0;"
        : // outputs:
        /*0*/"=r"(temp)
        : // inputs:
        /*1*/"r"(a.lo),
        /*2*/"mr"(b.lo),
        "0"(temp));

    return temp < b.hi;
}

- :

mov    rdx, [r14]
mov    rax, [r14+8]
cmp    rdx, [r15]
sbb    rax, 0
cmp    rax, [r15+8]
jc is_lessthan
+4

All Articles