Hello list, I'm currently investigating the use of LLVM for a project. For example, if I have a function like int a(int x, int y) { if (P == 0) { return x - y; } else { return y - x; } } and P could be considered constant, one of the code paths could be optimized out. Now I want to load a compiled bitcode file into a CFG, replace all occurrences of P with the value (either 0 or 1), run the optimization and JIT-compile into a anonymous function on the heap. Is that possible and if yes how? Basically I thought of declaring the parameter P as "extern const" and when the CFG is created, also create a constant node with the actual value and run a "replace-symbol (P, const_instr)". After that everything should be as easy as in the JIT compiler tutorial. Is something like that feasible? And how? I would appreciate any suggestions. Thanks in advance, Andreas
Hi Andreas,> I'm currently investigating the use of LLVM for a project. For example, > if I have a function like > > int a(int x, int y) { > if (P == 0) { > return x - y; > } else { > return y - x; > } > } > > and P could be considered constant, one of the code paths could be > optimized out. Now I want to load a compiled bitcode file into a CFG, > replace all occurrences of P with the value (either 0 or 1), run the > optimization and JIT-compile into a anonymous function on the heap. > Is that possible and if yes how?It is. For example you can declare a new global constant P2 with the appropriate initial value (0 or 1), then do: P->replaceAllUsesWith(P2). At that you can erase (i.e. delete) P. Running the instcombine pass on the module should then propagate the information into all functions; following that by a run of the simplifycfg pass will get rid of dead basic blocks. Basically I thought of declaring the> parameter P as "extern const" and when the CFG is created, also create a > constant node with the actual value and run a "replace-symbol (P, > const_instr)". After that everything should be as easy as in the JIT > compiler tutorial.Yup, that's a good approach. Ciao, Duncan.> > Is something like that feasible? And how? I would appreciate any > suggestions. > > Thanks in advance, > > Andreas > > _______________________________________________ > LLVM Developers mailing list > LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
Hi Duncan, thanks for your response. Meanwhile I got a quick and dirty version working.> It is. For example you can declare a new global constant P2 with the > appropriate initial value (0 or 1), then do: > P->replaceAllUsesWith(P2). > At that you can erase (i.e. delete) P.I'm currently using a global variable, set it's initializer to a freshly created constant value, declare the variable as itself being constant and set it's linkage to internal.> Running the instcombine pass on > the module should then propagate the information into all functions; > following that by a run of the simplifycfg pass will get rid of dead > basic blocks.I used a complete set of standard optimizations copy-pasted from some tutorials. I was surprised that's all I had to do. Pretty cool and fast :) So everything ends up in something like: bc = MemoryBuffer::getFile ("test.bc"); mod = ParseBitcodeFile (bc, Context); GlobalVariable *val; ConstantInt *const_val; val = mod->getNamedGlobal ("P"); const_val = ConstantInt::get (Context, APInt (32, 1234)); val->setInitializer (const_val); val->setConstant (true); val->setLinkage (GlobalValue::InternalLinkage); FunctionPassManager fpm (mod); fpm.add (createInstructionCombiningPass()); fpm.add (createCFGSimplificationPass ()); fpm.doInitialization (); Function *f = mod->getFunction ("t"); fpm.run (*f); This allows me to write in C: int P; float t (float a, float b) { if (P == 0) return a - b; else return b - a; } compiling this with: clang -O3 -x c test.c -emit-llvm -c -o test.bc results in: @P = common global i32 0, align 4 ; <i32*> [#uses=1] define float @t(float %a, float %b) nounwind readonly { %1 = load i32* @P ; <i32> [#uses=1] %2 = icmp eq i32 %1, 0 ; <i1> [#uses=1] br i1 %2, label %3, label %5 ; <label>:3 ; preds = %0 %4 = fsub float %a, %b ; <float> [#uses=1] ret float %4 ; <label>:5 ; preds = %0 %6 = fsub float %b, %a ; <float> [#uses=1] ret float %6 } and after replacing the global with a constant and run the optimizations I get a simple: define float @t(float %a, float %b) nounwind readnone { %1 = fsub float %a, %b ; <float> [#uses=1] ret float %1 } That is what I wanted. LLVM is really pretty cool stuff...