opts do not occur in some situations?

Hi, I'm trying to understand the optimization passes. I was wondering
why some seemingly obvious optimizations don't occur in some
situations. For example, the attached file, main.opt.cpp compiles to
main.opt.ll ( after running opt -std-compile-opts ).

  %0 = tail call double @_Z9factorialIdET_S0_(double 0.000000e+000) ;
<double> [#uses=1]

which could easily be determined as 1. And then multiplying the
remaining numbers manually?

  %phitmp93 = mul double %0, 2.000000e+000 ; <double> [#uses=1]
  %phitmp94 = mul double %phitmp93, 3.000000e+000 ; <double> [#uses=1]
...
...
  %phitmp108 = mul double %phitmp107, 1.800000e+001 ; <double> [#uses=1]
  %phitmp109 = mul double %phitmp108, 1.900000e+001 ; <double> [#uses=1]
  %1 = tail call i32 (i8*, ...)* @printf(i8* getelementptr ([29 x i8]*
@.str, i32 0, i32 0), double %phitmp109) nounwind ; <i32> [#uses=0]

This only occurs when using factorial( (double)19 ). factorial(
(double)18 ) results in the much shorter:

  %0 = tail call i32 (i8*, ...)* @printf(i8* getelementptr ([29 x i8]*
@.str, i32 0, i32 0), double 0x4336BEECCA730000) nounwind ; <i32>
[#uses=0]

I am just wondering whats going on over here.

Thank you.

main.opt.cpp (274 Bytes)

main.opt.ll (5.21 KB)

Hi Azriel,

Sorry for the delay in responding.

You're hitting a serious problem we have with llvm-gcc, which is that the GCC inliner is going crazy and inlining functions it should definitely not be inlining (such as recursive functions like this). I filed this bug about it:
http://llvm.org/bugs/show_bug.cgi?id=3232

The other impact that you're seeing is that floating point math is not commutative, so tail recursion elimination cannot be done. If you change this to pass 19 as an int, and use this command:

$ llvm-gcc main.opt.cpp -S -o - -emit-llvm -O0 | llvm-as | opt -std-compile-opts | llvm-dis

You'll see that it gets completely constant folded into a call to printf.

-Chris