Если у меня есть следующий код C ++ для сравнения двух 128-битных целых чисел без знака со встроенным 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;
}
Тогда он будет встроен достаточно эффективно, но с одним недостатком. Возвращаемое значение осуществляется через «интерфейс» общего регистра со значением 0 или 1. Это добавляет две или три ненужных дополнительных инструкции и отвлекает от операции сравнения, которая в противном случае была бы полностью оптимизирована. Сгенерированный код будет выглядеть примерно так:
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
Если я использую «sbb% 0,% 0» с возвращаемым значением «int» вместо «setc% 0» с возвращаемым значением «bool», останутся две дополнительные инструкции:
mov r10, [r14]
mov r11, [r14+8]
cmp r10, [r15]
sbb r11, [r15+8]
sbb eax, eax
test eax, eax
jnz is_lessthan
Я хочу вот что:
mov r10, [r14]
mov r11, [r14+8]
cmp r10, [r15]
sbb r11, [r15+8]
jc is_lessthan
В остальном расширенный встроенный asm GCC - это замечательно. Но я хочу, чтобы она была такой же хорошей, как внутренняя функция, во всех смыслах. Я хочу иметь возможность напрямую возвращать логическое значение в виде состояния флага или флагов ЦП, без необходимости «отображать» его в общем регистре.
Возможно ли это, или GCC (и компилятор Intel C ++, который также позволяет использовать эту форму встроенного asm) должны быть изменены или даже переработаны, чтобы сделать это возможным?
Кроме того, пока я занимаюсь этим - есть ли другой способ улучшить мою формулировку оператора сравнения?