Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

LLVM optimizer can't handle simple case?

I wrote a .cpp file shown below

int main() {
  int a, b;
  scanf( "%d", &b );

  for ( int i = 0 ; i < 1000 ; i++ ) {
    a = 0;
    if ( b > 10 )
      a = 3;
  }
  return a;
}

then I compiled this code by clang with -O3 option, the output .ll file is

define i32 @main() #0 {
entry:
  %b = alloca i32, align 4
  %call = call i32 (i8*, ...)* @scanf(i8* getelementptr inbounds ([3 x i8]* @.str, i32 0, i32 0), i32* %b)
  %0 = load i32* %b, align 4, !tbaa !1
  %cmp1 = icmp sgt i32 %0, 10
  %. = select i1 %cmp1, i32 3, i32 0
  ret i32 %.
}
attributes #0 = { nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }

This output is good. LLVM optimizer stripped the meaningless forloop from the code, and then assigned three or zero to return value directly.

Now I try another case like

int main() {
  int a, b;
  scanf( "%d", &b );

  for ( int i = 0 ; i < 1000 ; i++ ) {
    a = 0;
    if ( true ) // I modified here only
      a = 3;
  }
  return a;
}

and the output file is

define i32 @main() #0 {
entry:
  %b = alloca i32, align 4
  %call = call i32 (i8*, ...)* @scanf(i8* getelementptr inbounds ([3 x i8]* @.str, i32 0, i32 0), i32* %b)
  br label %for.cond

for.cond:                                         ; preds = %for.cond, %entry
  %a.0 = phi i32 [ 0, %entry ], [ 3, %for.cond ]
  %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.cond ]
  %inc = add nsw i32 %i.0, 1
  %exitcond = icmp eq i32 %inc, 1001
  br i1 %exitcond, label %for.end, label %for.cond

for.end:                                          ; preds = %for.cond
 ret i32 %a.0
}
attributes #0 = { nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }

Even though this code is easier to analyze (branch is always taken), LLVM optimizer doesn't strip meaningless forloop

If I was optimizer, I would like to generate this optimized code like

define i32 @main() #0 {
entry:
  %b = alloca i32, align 4
  %call = call i32 (i8*, ...)* @scanf(i8* getelementptr inbounds ([3 x i8]* @.str, i32 0, i32 0), i32* %b)
  ret i32 3
}

Can anyone tells me why the optimizer can't analyze a simpler code?

like image 660
hwliu Avatar asked May 02 '16 07:05

hwliu


1 Answers

I've tested your code snippet with llvm 3.9 and it generates:

define i32 @main() #0 {
  %1 = alloca i32, align 4
  %2 = bitcast i32* %1 to i8*
  call void @llvm.lifetime.start(i64 4, i8* %2) #3
  %3 = call i32 (i8*, ...) @scanf(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @.str, i64 0, i64 0), i32* nonnull %1)
  call void @llvm.lifetime.end(i64 4, i8* %2) #3
  ret i32 3
}

As hinted by MikeMB, I guess it is a bug in the optimizer that has now been fixed. What was your llvm version?

like image 145
Stringer Avatar answered Nov 09 '22 01:11

Stringer