title: What is difference between clang -O1 and opt -O1?
body: <p>What is the difference between <code>clang -O1</code> and <code>opt -O1</code>?
  I observed that these two commands behave in a significantly different way.</p>
  
  <h2>Context</h2>
  
  <p>I would like to test LLVM optimization passes. More specifically, I would like to pick a subset of <code>-O1</code> passes so that 1) the subset's performance is as good as the whole <code>-O1</code>, and 2) the selected passes are easy to reason about their correctness.</p>
  
  <p>To test the performance of subset, I wrote a shell script like:</p>
  
  <pre><code>clang -o a.bc -emit-llvm -c a.c
  opt (..., optmizations like -adce, ...) a.bc &gt;a.opt.bc
  clang -o a a.opt.bc
  </code></pre>
  
  <p>After a lot of tries, I figured out that:</p>
  
  <pre><code>clang -o a.bc -emit-llvm -c a.c
  opt -O1 a.bc &gt;a.opt.bc
  clang -o a a.opt.bc
  </code></pre>
  
  <p>and
      clang -O1 -o a a.c</p>
  
  <p>emit significantly different binary. The latter is much more efficient, for e.g., for an example program the former takes 49 secs to run, while the latter takes 29 secs.</p>
  
  <h2>Tried Approaches</h2>
  
  <ul>
  <li><p>I searched what does it mean for <code>clang -O1</code>, and found some references like <a href="https://stackoverflow.com/questions/15548023/clang-optimization-levels">Clang optimization levels</a>, but the article is really about <code>opt</code>, not <code>clang</code>.</p></li>
  <li><p>I tried to find official documentation for <code>clang</code>, but it was unfruitful.</p></li>
  <li><p>I tried to understand <code>clang</code> source code, but I could not...</p></li>
  </ul>
  
  <h2>Found Facts</h2>
  
  <ul>
  <li><p>I tried with</p>
  
  <p>clang -o a.bc -emit-llvm -c a.c
  opt -mem2reg -O1 a.bc >a.opt.bc
  clang -o a a.opt.bc</p></li>
  </ul>
  
  <p>since a reference(<a href="https://stackoverflow.com/questions/15548023/clang-optimization-levels">Clang optimization levels</a>) said that <code>opt -O1</code> does not contain <code>mem2reg</code> pass. It helped to close some gap, but not completely. (49 secs -> 40 secs) That means, I guess, <code>clang -O1</code> performs some preliminary optimizations, such as <code>mem2reg</code>, before <code>-O1</code> does something else.</p>
  
  <ul>
  <li><p>I tried with</p>
  
  <p>clang -o a.bc -emit-llvm -c a.c
  opt -mem2reg -O1 a.bc >a.opt.bc
  clang -O1 -o a a.opt.bc</p></li>
  </ul>
  
  <p>since I expect some target-dependent optimizations after LLVM IR passes. Actually it worked. (40 secs -> 26 secs, even faster than just <code>clang -O1</code>'s 29 secs)</p>
  
  <h2>Conclusion</h2>
  
  <p>In conclusion, I guess there is a pre- and post- LLVM IR passes in <code>clang -O1</code> which is not present in <code>opt -O1</code>. So is there anyone who knows the difference between <code>clang -O1</code> and <code>opt -O1</code>? Any reference to official docs or source code, or ways to solve my initial problem will be much appreciated.</p>