7

I have a small test program that uses llvm to calculate the values from some equation. The setup is as follows: I have created a bc file containing functions to add, multiply, divide, subtract and square double numbers. Now I set up linear equations with different parameters by combining the add & multiply functions. Then I transform the functions using the optimizers from the kaleidoscope example. This works nicely - the resulting function takes x as parameter and does simply 2 floating point calculations (multiply and add). The code for setting up these functions is:

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;
}

What I now want is the following - when I generate a function with factor 1, it should optimize the multiplication away and with summand 0 it should optimize the addition away. With factor 0, it should just return the summand. Is there a pass that does already do that? I just assume that llvm does not do that because of the reasons mentioned here: Why don't LLVM passes optimize floating point instructions?

Thank you for your help Tobias


Addition - I tried out 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
}

I now tried adding an inlining 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 must be used in a module optimization pass. The set-up for that now looks like this:

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

but even running a second function optimization pass over all functions that contains the instcombine pass does not do the trick

FunctionPassManager instcombiner(module);
instcombiner.add(createInstructionCombiningPass());
instcombiner.doInitialization();
for (auto i=module->begin(); i!=module->end(); ++i)
{
    instcombiner.run(*i);
}
Community
  • 1
  • 1
Tobias Langner
  • 10,634
  • 6
  • 46
  • 76

1 Answers1

3

The instcombine pass should perform these sorts of optimizations, even for floating-point operations.

A simple way to try it is to run opt -instcombine on your bitcode file and check out the output.

Oak
  • 26,231
  • 8
  • 93
  • 152
  • thank you - that was worth a try. I assume it doesn't combine it due to floating point issues (overflow, non-normalized representation, rounding or whatever else could occur - I don't know) – Tobias Langner Oct 30 '13 at 13:14
  • @TobiasLangner regarding your edit - since the operations are hiding inside functions, you probably need to [inline](http://llvm.org/docs/Passes.html#inline-function-integration-inlining) those first. – Oak Oct 30 '13 at 13:17
  • as you can see from the ll code that I posted above, the functions are already inlined. I added the instcombine pass as last pass. – Tobias Langner Oct 30 '13 at 13:33
  • 2
    @TobiasLangner unless I misunderstood you, the functions are most certainly not inlined - you see calls to them, instead of their content - `fmul`, `fadd`, etc. – Oak Oct 30 '13 at 13:41
  • yes, I was wrong there. Sorry. I'll have a deeper look. Thank you. – Tobias Langner Oct 30 '13 at 13:55