Если у меня есть следующий код C ++ для сравнения двух 128-разрядных целых чисел без знака со встроенным asm-64 amd:
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
Расширенные встроенные ассемблеры GCC замечательны, в противном случае. Но я хочу, чтобы это было так же хорошо, как встроенная функция, во всех отношениях. Я хочу иметь возможность напрямую возвращать логическое значение в форме состояния флага или флагов ЦП без необходимости «рендеринга» его в общий регистр.
Возможно ли это, или GCC (и компилятор Intel C ++, который также позволяет использовать эту форму встроенного ассемблера) придется изменить или даже изменить, чтобы сделать это возможным?
Кроме того, пока я занимаюсь этим - можно ли как-нибудь улучшить мою формулировку оператора сравнения?