title: LLVM API optimisation run
body: <p>I am trying to perform -O2 optimisation with LLVM IR obtained by calling CLANG API. Unfortunately, optimisation works only with IR created with manual calls. I have the following function:</p>
  
  <pre><code>int mult_add(int x, int y){
      if(x &gt; 2){
          return y + 1 + 2;
      } else {
          return y - 1 + 2;
      }
  }
  </code></pre>
  
  <p>And with these calls:</p>
  
  <pre><code>clang -S -emit-llvm main.cpp
  opt main.ll -o opt.ll -S -O2
  </code></pre>
  
  <p>I get the correct result:</p>
  
  <pre><code> define i32 @_Z8mult_addii(i32, i32) local_unnamed_addr #0 {
    %3 = icmp sgt i32 %0, 2
    %.sink = select i1 %3, i32 3, i32 1
    %4 = add nsw i32 %.sink, %1
    ret i32 %4
  }
  </code></pre>
  
  <p>Unfortunately, when I do it through LLVM API with legacy::PassManager and legacy::FunctionPassManager optimisation simply does not work and got long ugly code:</p>
  
  <pre><code>define i32 @_Z8mult_addii(i32, i32) #0 {
    %3 = alloca i32, align 4
    %4 = alloca i32, align 4
    %5 = alloca i32, align 4
    store i32 %0, i32* %4, align 4
    store i32 %1, i32* %5, align 4
    %6 = load i32, i32* %4, align 4
    %7 = icmp sgt i32 %6, 2
    br i1 %7, label %8, label %12
  
  ; &lt;label&gt;:8:                                      ; preds = %2
    %9 = load i32, i32* %5, align 4
    %10 = add nsw i32 %9, 1
    %11 = add nsw i32 %10, 2
    store i32 %11, i32* %3, align 4
    br label %16
  
  ; &lt;label&gt;:12:                                     ; preds = %2
    %13 = load i32, i32* %5, align 4
    %14 = sub nsw i32 %13, 1
    %15 = add nsw i32 %14, 2
    store i32 %15, i32* %3, align 4
    br label %16
  
  ; &lt;label&gt;:16:                                     ; preds = %12, %8
    %17 = load i32, i32* %3, align 4
    ret i32 %17
  }
  </code></pre>
  
  <p>Seems like CLANG creates IR in some unoptimisable state? Because running the passes on a manual created IR works fine.</p>
  
  <p>By the way, PMBuilder.populateModulePassManager is called, here is the code:</p>
  
  <pre><code>legacy::PassManager Passes;
  legacy::FunctionPassManager FPasses(M2.get());
  AddOptimizationPasses(Passes, FPasses, &amp;(TheJIT-&gt;getTargetMachine()), 2, 0);
  Passes.add(createPrintModulePass(outs()));
  Passes.run(*M2);
  </code></pre>
  
  <p>And AddOptimizationPasses is stolen and simplified from opt utility:</p>
  
  <pre><code>static void AddOptimizationPasses(legacy::PassManagerBase &amp;MPM,
                                    legacy::FunctionPassManager &amp;FPM,
                                    TargetMachine *TM, unsigned OptLevel,
                                    unsigned SizeLevel) {
      FPM.add(createVerifierPass());
  
    PassManagerBuilder Builder;
    Builder.OptLevel = OptLevel;
    Builder.SizeLevel = SizeLevel;
  
    Builder.Inliner = createFunctionInliningPass(50);
    Builder.DisableUnitAtATime = true;//!UnitAtATime;
    Builder.DisableUnrollLoops = false;
  
    if (TM)
      TM-&gt;adjustPassManager(Builder);
  
    //Builder.populateFunctionPassManager(FPM);
    Builder.populateModulePassManager(MPM);
  }
  By the way, initialisation is following:
  
  InitializeAllTargets();
  InitializeAllTargetMCs();
  InitializeAllAsmPrinters();
  </code></pre>
  
  <p>Unfortunately, it does not work.</p>