[LLVMdev] Additional Optimization I'm Missing?
Owen Anderson
resistor at mac.com
Mon Mar 31 23:18:15 PDT 2008
Other people have already addressed the specific case of this example,
but, in general, the passes use by the opt tool in -std-compile-opts
are considered to be a good set for unit-at-a-time optimization, and
similarly the ones used in llvm-ld are considered good (in addition to
the single-unit ones) for whole-program optimization.
Also note that predsimplify is incomplete and has some known bugs. I
would recommend against using it.
--Owen
On Mar 31, 2008, at 6:46 PM, Bobby Powers wrote:
> Hello, I'm working on using the LLVM JIT for a little project of
> mine, amazing work first off! I have a question about optimization
> passes. I initially have this function I've created, in python it
> looks like this:
>
> OS_end = 50
> OS_start = 0
> OS_timestep = 1
> birth_rate = .3
> population = 30.0
>
> for time in range(OS_start, OS_end, OS_timestep):
> births = birth_rate * population
> deaths = 0.1 * population
> population_NEXT = population + births - deaths
>
> #generally put print statements here
>
> #updating stocks
> population = population_NEXT
>
> Then I can turn it into LLVM IR:
>
> define void @simulate() {
> entry:
> %time = alloca double ; <double*> [#uses=4]
> %population_next = alloca double ; <double*> [#uses=2]
> %population = alloca double ; <double*> [#uses=5]
> %net_change = alloca double ; <double*> [#uses=2]
> %deaths = alloca double ; <double*> [#uses=2]
> %births = alloca double ; <double*> [#uses=2]
> %birth_rate = alloca double ; <double*> [#uses=2]
> %OS_timestep = alloca double ; <double*> [#uses=2]
> %OS_start = alloca double ; <double*> [#uses=2]
> %OS_end = alloca double ; <double*> [#uses=2]
> store double 5.000000e+01, double* %OS_end
> store double 0.000000e+00, double* %OS_start
> store double 1.000000e+00, double* %OS_timestep
> store double 3.000000e-01, double* %birth_rate
> store double 3.000000e+01, double* %population
> %OS_start1 = load double* %OS_start ; <double> [#uses=1]
> store double %OS_start1, double* %time
> br label %forcond
>
> forcond: ; preds = %forinc, %entry
> %time2 = load double* %time ; <double> [#uses=1]
> %OS_end3 = load double* %OS_end ; <double> [#uses=1]
> %forcond4 = fcmp olt double %time2, %OS_end3 ; <i1> [#uses=1]
> br i1 %forcond4, label %forbody, label %forafter
>
> forbody: ; preds = %forcond
> %birth_rate5 = load double* %birth_rate ; <double> [#uses=1]
> %population6 = load double* %population ; <double> [#uses=1]
> %multmp = mul double %birth_rate5, %population6 ; <double> [#uses=1]
> store double %multmp, double* %births
> %population7 = load double* %population ; <double> [#uses=1]
> %multmp8 = mul double 1.000000e-01, %population7 ; <double>
> [#uses=1]
> store double %multmp8, double* %deaths
> %births9 = load double* %births ; <double> [#uses=1]
> %deaths10 = load double* %deaths ; <double> [#uses=1]
> %subtmp = sub double %births9, %deaths10 ; <double> [#uses=1]
> store double %subtmp, double* %net_change
> %population11 = load double* %population ; <double> [#uses=1]
> %net_change12 = load double* %net_change ; <double> [#uses=1]
> %addtmp = add double %population11, %net_change12 ; <double>
> [#uses=1]
> store double %addtmp, double* %population_next
> br label %updatestocks
>
> updatestocks: ; preds = %forbody
> %population_next13 = load double* %population_next ; <double>
> [#uses=1]
> store double %population_next13, double* %population
> br label %forinc
>
> forinc: ; preds = %updatestocks
> %time14 = load double* %time ; <double> [#uses=1]
> %OS_timestep15 = load double* %OS_timestep ; <double> [#uses=1]
> %new_time = add double %time14, %OS_timestep15 ; <double> [#uses=1]
> store double %new_time, double* %time
> br label %forcond
>
> forafter: ; preds = %forcond
> ret void
> }
>
>
> And then I run the optimizations from the Kaleidoscope tutorial
> (mem2reg, predsimplify, instcombine, reassociate, gvn, simplifycfg)
> and get the following:
>
> define void @simulate() {
> entry:
> br label %forcond
>
> forcond: ; preds = %forbody, %entry
> %population.0 = phi double [ 3.000000e+01, %entry ], [ %addtmp,
> %forbody ] ; <double> [#uses=3]
> %time.0 = phi double [ 0.000000e+00, %entry ], [ %new_time,
> %forbody ] ; <double> [#uses=2]
> %forcond4 = fcmp olt double %time.0, 5.000000e+01 ; <i1> [#uses=1]
> br i1 %forcond4, label %forbody, label %forafter
>
> forbody: ; preds = %forcond
> %multmp = mul double %population.0, 3.000000e-01 ; <double>
> [#uses=1]
> %multmp8 = mul double %population.0, 1.000000e-01 ; <double>
> [#uses=1]
> %subtmp = sub double %multmp, %multmp8 ; <double> [#uses=1]
> %addtmp = add double %population.0, %subtmp ; <double> [#uses=1]
> %new_time = add double %time.0, 1.000000e+00 ; <double> [#uses=1]
> br label %forcond
>
> forafter: ; preds = %forcond
> ret void
> }
>
>
> The thing is, in forbody it is still doing:
> subtmp = population + (population * .3) - (population * .1)
>
>
> ideally I would love to see it reduced to:
> subtmp = 1.2 * population
>
>
>
> I've played around with adding a bunch of optimizations that sound
> good from [http://www.llvm.org/docs/Passes.html], but I must admit
> I'm a bit over my head here. Does anyone have any suggestions? Am
> I missing passes, do I need to restructure the IR, or am I missing
> some concept?
>
> thanks! (keep up the amazing work)
> yours,
> Bobby Powers
> _______________________________________________
> LLVM Developers mailing list
> LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20080401/acb1e845/attachment.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: smime.p7s
Type: application/pkcs7-signature
Size: 2555 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20080401/acb1e845/attachment.bin>
More information about the llvm-dev
mailing list