<p dir="auto">Fallout of <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="54437366" data-permission-text="Title is private" data-url="https://github.com/rust-lang/rust/issues/21191" data-hovercard-type="pull_request" data-hovercard-url="/rust-lang/rust/pull/21191/hovercard" href="https://github.com/rust-lang/rust/pull/21191">#21191</a>. <code class="notranslate">-C opt-level=2</code> sets <code class="notranslate">CodegenOptions::opt_level</code> but <code class="notranslate">-O</code> doesn't, and <code class="notranslate">-C lto</code> path only looks at that. Due to the fallback from LTO path, <code class="notranslate">-O -C lto</code> is currently same to <code class="notranslate">-C opt-level=0 -C lto</code> (!).</p>
<p dir="auto"><code class="notranslate">-O</code> seems to function like an alias for <code class="notranslate">-C opt-level=2</code>, but <code class="notranslate">-O</code> does not enable certain LTO LLVM optimizations (inlining?), whereas <code class="notranslate">-C opt-level=2</code> does.  This seems like a mistake.</p>
<p dir="auto">The problem is this code in <code class="notranslate">librustc_trans/back/lto.rs</code>:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="    let opt = sess.opts.cg.opt_level.unwrap_or(0) as libc::c_uint;

    let builder = llvm::LLVMPassManagerBuilderCreate();
    llvm::LLVMPassManagerBuilderSetOptLevel(builder, opt);
    llvm::LLVMPassManagerBuilderPopulateLTOPassManager(builder, pm,
        /* Internalize = */ False,
        /* RunInliner = */ True);
    llvm::LLVMPassManagerBuilderDispose(builder);"><pre class="notranslate"><code class="notranslate">    let opt = sess.opts.cg.opt_level.unwrap_or(0) as libc::c_uint;

    let builder = llvm::LLVMPassManagerBuilderCreate();
    llvm::LLVMPassManagerBuilderSetOptLevel(builder, opt);
    llvm::LLVMPassManagerBuilderPopulateLTOPassManager(builder, pm,
        /* Internalize = */ False,
        /* RunInliner = */ True);
    llvm::LLVMPassManagerBuilderDispose(builder);
</code></pre></div>
<p dir="auto"><code class="notranslate">sess.opts.cg.opt_level</code> is the <code class="notranslate">-C opt-level</code> setting, which is <code class="notranslate">None</code> with <code class="notranslate">-O</code>.</p>
<p dir="auto">test.rs:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="pub fn test() {}"><pre class="notranslate"><code class="notranslate">pub fn test() {}
</code></pre></div>
<p dir="auto">output:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="$ rustc test.rs --crate-type staticlib --emit llvm-ir -C lto -O
$ ls -l test.ll
-rw-rw-r-- 1 rprichard rprichard 36920440 Feb 19 00:25 test.ll
$ rustc test.rs --crate-type staticlib --emit llvm-ir -C lto -C opt-level=2
$ ls -l test.ll 
-rw-rw-r-- 1 rprichard rprichard 1312070 Feb 19 00:25 test.ll"><pre class="notranslate"><code class="notranslate">$ rustc test.rs --crate-type staticlib --emit llvm-ir -C lto -O
$ ls -l test.ll
-rw-rw-r-- 1 rprichard rprichard 36920440 Feb 19 00:25 test.ll
$ rustc test.rs --crate-type staticlib --emit llvm-ir -C lto -C opt-level=2
$ ls -l test.ll 
-rw-rw-r-- 1 rprichard rprichard 1312070 Feb 19 00:25 test.ll
</code></pre></div>
<p dir="auto">I think we should base the LLVM optimization level on <code class="notranslate">sess.opts.optimize</code>.  (Maybe it ought to use <code class="notranslate">write::get_llvm_opt_level</code>?)</p>