お気に入りのコンパイラに質問してみませんか?簡単なために与え
~/projects$ clang++ -O2 -c -I/usr/lib/Boost/1-39-0-1/include/ test.cpp -emit-llvm
~/projects$ llvm-dis test.o -show-annotations
::私たちはLLVM IR取得これらのコマンドで
#include <cstring>
#include <cstdio>
#include <boost/foreach.hpp>
char const* HelloWorld = "Hello, world!\n";
void simplefor() {
for(char const* it = HelloWorld, *end = HelloWorld + strlen(HelloWorld);
it != end;
++it)
{
printf("%c", *it);
}
}
void foreach() {
BOOST_FOREACH(char ch, HelloWorld)
{
printf("%c", ch);
}
}
:
define void @_Z9simpleforv() nounwind uwtable {
%1 = load i8** @HelloWorld, align 8, !tbaa !0 ; [#uses=3 type=i8*]
%2 = tail call i64 @strlen(i8* %1) nounwind readonly ; [#uses=2 type=i64]
%3 = getelementptr inbounds i8* %1, i64 %2 ; [#uses=1 type=i8*]
%4 = icmp eq i64 %2, 0 ; [#uses=1 type=i1]
br i1 %4, label %._crit_edge, label %.lr.ph
.lr.ph: ; preds = %.lr.ph, %0
%it.01 = phi i8* [ %7, %.lr.ph ], [ %1, %0 ] ; [#uses=2 type=i8*]
%5 = load i8* %it.01, align 1, !tbaa !1 ; [#uses=1 type=i8]
%6 = sext i8 %5 to i32 ; [#uses=1 type=i32]
%putchar = tail call i32 @putchar(i32 %6) nounwind ; [#uses=0 type=i32]
%7 = getelementptr inbounds i8* %it.01, i64 1 ; [#uses=2 type=i8*]
%8 = icmp eq i8* %7, %3 ; [#uses=1 type=i1]
br i1 %8, label %._crit_edge, label %.lr.ph
._crit_edge: ; preds = %.lr.ph, %0
ret void
}
私たちは(混乱を避けるために)簡単なテストケースを使用してみましょう
およびBOOST_FOREACH
の場合:
; [#uses=0]
define void @_Z7foreachv() nounwind uwtable {
%1 = load i8** @HelloWorld, align 8, !tbaa !0 ; [#uses=1 type=i8*]
br label %2
; <label>:2 ; preds = %.preheader, %0
%.in = phi i8* [ %6, %.preheader ], [ %1, %0 ] ; [#uses=2 type=i8*]
%3 = load i8* %.in, align 1, !tbaa !1 ; [#uses=2 type=i8]
%4 = icmp eq i8 %3, 0 ; [#uses=1 type=i1]
br i1 %4, label %.critedge, label %.preheader
.preheader: ; preds = %2
%5 = sext i8 %3 to i32 ; [#uses=1 type=i32]
%putchar = tail call i32 @putchar(i32 %5) nounwind ; [#uses=0 type=i32]
%6 = getelementptr inbounds i8* %.in, i64 1 ; [#uses=1 type=i8*]
br label %2
.critedge: ; preds = %2
ret void
}
私はシンプルなケースではなく、より少ないブランチ(2つではなく反復ごとに1つ)について説明していますが、そこからパフォーマンスをピン止めするのは難しいでしょう。
もちろん...それはもはや重要ではありません!雹C++ 11:あなたは(定数)参照を使用する場合、コンパイラは、いくつかの変数がないエイリアスを行うことを考え出す難しく時間を持っており、より少ない生成:
void bestfor() {
for(char const ch: HelloWorld) {
printf("%c", ch);
}
}
ちょうどノートでは、 'typeof'演算子は移植性がありません。 – fredoverflow
ポータブルではないとはどういう意味ですか?私はそれが標準の一部ではないことを知っています。 – balki
私はオプティマイザがそのステートメントに追いついているかもしれないと思います。 BOOST_FOREACHを使用して、同等のforループを使用してもう少しパフォーマンスを絞り込めるかどうかを確認するコードをベンチマークしました。 BOOST_FOREACHコードはわずかに速かった(つまり、おそらく誤差の範囲内) – Ferruccio