如果有的话,更换你的编译器吧!对于这种问题,我使用
Try Out LLVM页面进行测试。这是LLVM的旧版本(仍然使用gcc前端),但这些都是老套路。以下是我的小样本程序(你的简化版本):
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
int main (int argc, char* argv[]) {
int N = atoi(argv[0]);
int a = 0, d = 0, b = atoi(argv[1]), c = atoi(argv[2]);
int i;
for(i = 0; i < N; i++)
{
a = i & 1;
if(a) a = b+i; else a = c+i;
}
for(i = 0; i < N; i++)
{
d = i & 1;
d = d ? b+i : c+i;
}
printf("%d %d", a, d);
return 0;
}
以下是对应的LLVM IR代码生成:
define i32 @main(i32 %argc, i8** nocapture %argv) nounwind {
entry:
%0 = load i8** %argv, align 8 ; <i8*> [#uses=1]
%N = tail call i32 @atoi(i8* %0) nounwind readonly ; <i32> [#uses=5]
%2 = getelementptr inbounds i8** %argv, i64 1 ; <i8**> [#uses=1]
%3 = load i8** %2, align 8 ; <i8*> [#uses=1]
%b = tail call i32 @atoi(i8* %3) nounwind readonly ; <i32> [#uses=2]
%5 = getelementptr inbounds i8** %argv, i64 2 ; <i8**> [#uses=1]
%6 = load i8** %5, align 8 ; <i8*> [#uses=1]
%c = tail call i32 @atoi(i8* %6) nounwind readonly ; <i32> [#uses=2]
%8 = icmp sgt i32 %N, 0 ; <i1> [#uses=2]
br i1 %8, label %bb, label %bb11
bb: ; preds = %bb, %entry
%9 = phi i32 [ %10, %bb ], [ 0, %entry ] ; <i32> [#uses=2]
%10 = add nsw i32 %9, 1 ; <i32> [#uses=2]
%exitcond22 = icmp eq i32 %10, %N ; <i1> [#uses=1]
br i1 %exitcond22, label %bb10.preheader, label %bb
bb10.preheader: ; preds = %bb
%11 = and i32 %9, 1 ; <i32> [#uses=1]
%12 = icmp eq i32 %11, 0 ; <i1> [#uses=1]
%.pn13 = select i1 %12, i32 %c, i32 %b ; <i32> [#uses=1]
%tmp21 = add i32 %N, -1 ; <i32> [#uses=1]
%a.1 = add i32 %.pn13, %tmp21 ; <i32> [#uses=2]
br i1 %8, label %bb6, label %bb11
bb6: ; preds = %bb6, %bb10.preheader
%13 = phi i32 [ %14, %bb6 ], [ 0, %bb10.preheader ] ; <i32> [#uses=2]
%14 = add nsw i32 %13, 1 ; <i32> [#uses=2]
%exitcond = icmp eq i32 %14, %N ; <i1> [#uses=1]
br i1 %exitcond, label %bb10.bb11_crit_edge, label %bb6
bb10.bb11_crit_edge: ; preds = %bb6
%15 = and i32 %13, 1 ; <i32> [#uses=1]
%16 = icmp eq i32 %15, 0 ; <i1> [#uses=1]
%.pn = select i1 %16, i32 %c, i32 %b ; <i32> [#uses=1]
%tmp = add i32 %N, -1 ; <i32> [#uses=1]
%d.1 = add i32 %.pn, %tmp ; <i32> [#uses=1]
br label %bb11
bb11: ; preds = %bb10.bb11_crit_edge, %bb10.preheader, %entry
%a.0 = phi i32 [ %a.1, %bb10.bb11_crit_edge ], [ %a.1, %bb10.preheader ], [ 0, %entry ] ; <i32> [#uses=1]
%d.0 = phi i32 [ %d.1, %bb10.bb11_crit_edge ], [ 0, %bb10.preheader ], [ 0, %entry ] ; <i32> [#uses=1]
%17 = tail call i32 (i8*, ...)* @printf(i8* noalias getelementptr inbounds ([6 x i8]* @.str, i64 0, i64 0), i32 %a.0, i32 %d.0) nounwind ; <i32> [#uses=0]
ret i32 0
}
好的,所以很可能是中文,尽管我已经重命名了一些变量以使其更易于阅读。
重要的部分是这两个块:
%.pn13 = select i1 %12, i32 %c, i32 %b ; <i32> [#uses=1]
%tmp21 = add i32 %N, -1 ; <i32> [#uses=1]
%a.1 = add i32 %.pn13, %tmp21 ; <i32> [#uses=2]
%.pn = select i1 %16, i32 %c, i32 %b ; <i32> [#uses=1]
%tmp = add i32 %N, -1 ; <i32> [#uses=1]
%d.1 = add i32 %.pn, %tmp ; <i32> [#uses=1]
分别设置了a
和d
。
结论是:没有区别
注意:在一个更简单的例子中,这两个变量实际上被合并了,但似乎优化器没有检测到相似性...
-O1
,我怀疑你根本看不出任何差异。在未经优化的代码中看到性能差异没有太大意义。 - T.J. Crowder