2017-02-27 14 views
3

ほとんどのプラットフォームでは、allocaは、スタックポインタのインライン調整(たとえば、x64上のrspから、スタックアライメントを維持するための少しのロジックを足したもの)まで低下します。gccのallocaの扱いはどうですか?

私はgccがallocaのために生成するコードを見ていて、かなり変です。これは、次のアセンブリにコンパイル

#include <alloca.h> 
#include <stddef.h> 

volatile void *psink; 

void func(size_t x) { 
    psink = alloca(x); 
} 

-O2で:いくつかの混乱のものがここにあります

func(unsigned long): 
     push rbp 
     add  rdi, 30 
     and  rdi, -16 
     mov  rbp, rsp 
     sub  rsp, rdi 
     lea  rax, [rsp+15] 
     and  rax, -16 
     mov  QWORD PTR psink[rip], rax 
     leave 
     ret 

次の簡単な例してください。私はgccが(スタックの整列を維持するために)割り当てられたサイズを16の倍数に丸める必要があることを理解しています。通常の方法は(size + 15) & ~0xFですが、代わりにadd rdi, 30に30を追加しますか?どうしたの?

第2に、私はちょうどallocaの結果が新しいrspの値であることを期待しています。これは既によく整列されています。代わりに、gccがこれを行います:

allocaの結果として使用する rspの値を「再編成」しているように見える
lea  rax, [rsp+15] 
    and  rax, -16 

- しかし、我々はすでに最初の16バイト境界にrspを揃えるために仕事をしました場所。

何がありますか?

コードon godboltでプレーすることができます。 clangiccは、少なくともx86では「期待していること」を実行することに注意する価値があります。 VLAでは、gccclangは問題ありませんが、iccは偽物を生成します。


1ここで、psinkへの割り当ては、そうでない場合、コンパイラはそれを完全に省略するのでallocaの結果を消費するだけです。

+0

コメントは議論の対象外です。この会話は[チャットに移動]されています(http://chat.stackoverflow.com/rooms/136822/discussion-on-question-by-beeonrope-whats-up-with-gccs-handling-of-alloca)。 –

答えて

7

これは非常に古い、通常の優先度bugです。コードは正しく動作します。サイズが1バイトより大きい場合、16バイト以上が不必要に割り当てられます。だから、それは正当性のバグではない、それはマイナーな効率のバグです。

+0

@BeeOnRope:私は、この答えは実際には "それはどういうこと?"という質問に答えていると思います。 。コンパイラには非効率なコードを生成する既知のバグがあります。 –

+0

@BeeOnRope私はちょうど正しさを強調しています。パフォーマンスに関しては、どのコンパイラも最適なコードを生成しません。 clangとiccは不要なmov命令を生成します。これらの余分な命令が実行時に及ぼす影響がどのようなものであっても、現代のプロセッサでは非常に小さくなります。余分なスタックスペースは、allocaを使用して配列の要素または多くの小さなオブジェクトを割り当てるときに問題になります。あなたはスタックを使い果たすかもしれません。 –

関連する問題