3

インライン アセンブリをラップするインライン関数定義があります。引数がビルド時にわかっているかどうかに基づいて、別のインライン アセンブリ実装を選択したいと考えています。

私の質問は、C コードまたはインライン アセンブリで、アドレス値がビルド時に既知であり、したがって即値に適合するかどうかを尋ねる方法です。__builtin_constant_p を考えている場合は、先に読んでください。

これが私の意図を示すコードです。「is_immediate」を実装する方法を見つけようとしています。

static char arr[5];

void __attribute__((always_inline)) do_something(char * buf)
{
   if(is_immediate(buf) {

        // Argument is constant, can use immediate form

        asm volatile ("insn1 %0" : : "i"(buf));

   } else {

        // Argument is computed at runtime, use a register

        unsigned long tmp = (unsigned long)buf + 1;

        asm volatile("insn2 %0" : : "r"(tmp));

}


int main(void) 
{
   do_something(&arr);
}

最初の印象では、__builtin_constant_p() は、機能しないことを除いて、まさに必要な魔法のように思えます。

機能しない理由は、リンカーが配列をメモリに配置し、そのアドレスを選択した後に配列のアドレスが認識される (したがって、インライン アセンブリの直接の制約に適合する) ためです。リンク前のコンパイル時に認識されます。

だから、私が探しているのは、「この変数は即値に適していますか?」と尋ねる方法です。「これは定数式ですか?」ではなく。

4

1 に答える 1

0

私の x86 コンパイラ (この insn は結局意味をなさない) によって生成されたものを見ると、次のようになります。

static char arr[5];

void __attribute__((always_inline)) do_something(char * buf)
{

        // Argument is constant, can use immediate form

        asm volatile ("insn1 %0" : : "r"(buf));

        unsigned long tmp = (unsigned long)buf;

        asm volatile("insn2 %0" : : "r"(tmp));

}


int main(void)
{
   char brr[5];
   do_something(arr);
   do_something(brr);
}

に来る

        .file   "inl.c"
        .text
.globl do_something
        .type   do_something, @function
do_something:
        pushl   %ebp
        movl    %esp, %ebp
        movl    8(%ebp), %eax
#APP
# 8 "inl.c" 1
        insn1 %eax
# 0 "" 2
# 12 "inl.c" 1
        insn2 %eax
# 0 "" 2
#NO_APP
        popl    %ebp
        ret
        .size   do_something, .-do_something
.globl main
        .type   main, @function
main:
        pushl   %ebp
        movl    $arr, %eax
        movl    %esp, %ebp
        subl    $16, %esp
#APP
# 8 "inl.c" 1
        insn1 %eax
# 0 "" 2
# 12 "inl.c" 1
        insn2 %eax
# 0 "" 2
#NO_APP
        leal    -5(%ebp), %eax
#APP
# 8 "inl.c" 1
        insn1 %eax
# 0 "" 2
# 12 "inl.c" 1
        insn2 %eax
# 0 "" 2
#NO_APP
        leave
        ret
        .size   main, .-main
        .local  arr
        .comm   arr,5,4
        .ident  "GCC: (SUSE Linux) 4.5.1 20101208 [gcc-4_5-branch revision 167585]"
        .section        .comment.SUSE.OPTs,"MS",@progbits,1
        .string "OSpwg"
        .section        .note.GNU-stack,"",@progbits

$arrしたがって、おそらく即時であるため、即時であることは理にかなっていると思います(そうでleal -5(%ebp), %eaxはありませんが)。おそらく、前述の最適化はサポートされていません。

しかし一方で、

            movl    $arr, %eax
            insn1 %eax

よりもそれほど悪くはありません

            insn1 $arr

それがまだ受け入れられるように、IMHO。

于 2012-11-29T10:45:02.633 に答える