How can I make llvm optimize the following floating point equation

I have a small test program that uses llvm to calculate values ​​from some equation. The setup is as follows: I created a bc file containing functions for adding, multiplying, division, subtraction and square double numbers. Now I have installed linear equations with different parameters, combining the functions of addition and multiplication. Then I transform the functions using the optimizers from the kaleidoscope example. This works well - the resulting function takes x as a parameter and only performs 2 floating point calculations (multiply and add). Code to configure these features:

Function* createLinearFunction(const std::string& name, double factor, double summand, Module* module) { LLVMContext& context = getGlobalContext(); Function* func = cast<Function>(module->getOrInsertFunction(name.c_str(),Type::getDoubleTy(context),Type::getDoubleTy(context),(Type *)0)); //add basic block BasicBlock* bb1 = BasicBlock::Create(context,"EntryBlock",func); IRBuilder<> builder(bb1); Argument* x0 = func->arg_begin(); x0->setName("x0"); Value* x1 = ConstantFP::get(context,APFloat(factor)); Value* x2 = ConstantFP::get(context,APFloat(summand)); std::vector<Value*> args1; args1.push_back(x0); args1.push_back(x1); Value* x3 = builder.CreateCall(mul_d_dd,args1,""); std::vector<Value*> args2; args2.push_back(x2); args2.push_back(x3); Value* x4 = builder.CreateCall(add_d_dd,args2,""); builder.CreateRet(x4); return func; } 

Now I want the following: when I generate a function with a coefficient of 1, it must optimize the multiplication and with the term 0 it should optimize the addition. With a coefficient of 0, it should simply return the term. Is there a pass that already does this? I just assume that llvm does not do this due to the reasons mentioned here: Why doesn't LLVM pass in floating point instruction optimizations?

Thanks for the help Tobias


Addition - I tried adding instcombine via createInstructionCombiningPass() , but the optimized code still looks the same:

 define double @Linear0xPlus0(double %x0) { EntryBlock: %0 = call double @mul_d_dd(double %x0, double 0.000000e+00) %1 = call double @add_d_dd(double 0.000000e+00, double %0) ret double %1 } 

Now I tried adding a nested pass using createFuntionInliningPass() - but this causes an assertion error

  FunctionPassManager fpm(module); fpm.add(new DataLayout(module->getDataLayout())); fpm.add(createFunctionInliningPass()); fpm.add(createBasicAliasAnalysisPass()); fpm.add(createInstructionCombiningPass()); fpm.add(createReassociatePass()); fpm.add(createGVNPass()); fpm.add(createCFGSimplificationPass()); fpm.add(createInstructionCombiningPass()); fpm.doInitialization(); 

and get the following error: Assertion failed: !PMS.empty() && "Unable to handle Call Graph Pass"

This error is caused by the fact that inlining is not a function, but a module optimization and should be used in passing module optimization. The setup for this now looks like this:

 PassManagerBuilder pmb; pmb.OptLevel=3; PassManager mpm; pmb.populateModulePassManager(mpm); mpm.add(createFunctionInliningPass()); 

but even performing the second optimization of a function passes through all functions containing instcombine bandwidth, it does not perform the trick

 FunctionPassManager instcombiner(module); instcombiner.add(createInstructionCombiningPass()); instcombiner.doInitialization(); for (auto i=module->begin(); i!=module->end(); ++i) { instcombiner.run(*i); } 
+6
source share
1 answer

instcombine pass must perform these kinds of optimizations even for floating point operations.

An easy way to try this is to run opt -instcombine in your bitcode file and check the output.

+2
source

Source: https://habr.com/ru/post/957020/


All Articles