2つの128ビット符号なし整数をインラインamd-64asmと比較する次のC++コードがある場合:
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;
}
次に、非常に効率的にインライン化されますが、1つの欠陥があります。戻り値は、値が0または1の汎用レジスタの「インターフェイス」を介して行われます。これにより、2つまたは3つの不要な余分な命令が追加され、完全に最適化される比較操作が損なわれます。生成されたコードは次のようになります。
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
「bool」の戻り値を持つ「setc%0」の代わりに「int」の戻り値を持つ「sbb%0、%0」を使用する場合でも、2つの追加の命令があります。
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拡張インラインasmは素晴らしいです。しかし、あらゆる点で、組み込み関数と同じくらい優れていることを望んでいます。ブール値を汎用レジスタに「レンダリング」することなく、CPUフラグの状態の形式で直接返すことができるようにしたいと考えています。
これは可能ですか、それともGCC(およびこの形式のインラインasmの使用も可能にするIntel C ++コンパイラ)を変更するか、リファクタリングする必要がありますか?
また、私がそれに取り組んでいる間、比較演算子の定式化を改善できる他の方法はありますか?