<p dir="auto">Julia is thwarting LLVM's CSE when the subexpression occurs in a loop test and loop body.  Here is an example:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="function foo(a, b,c)
    while (a*b+c)==1
        a /= (a*b+c)
    end
    a
end

code_llvm (foo,(Float64,Float64,Float64))"><pre class="notranslate"><code class="notranslate">function foo(a, b,c)
    while (a*b+c)==1
        a /= (a*b+c)
    end
    a
end

code_llvm (foo,(Float64,Float64,Float64))
</code></pre></div>
<p dir="auto">The output is:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="L:                                                ; preds = %L.preheader, %L
  %a.0 = phi double [ %8, %L ], [ %0, %L.preheader ]
  %6 = fmul double %a.0, %1, !dbg !10
  %7 = fadd double %6, %2, !dbg !10
  %8 = fdiv double %a.0, %7, !dbg !10
  %9 = fmul double %8, %1, !dbg !10
  %10 = fadd double %9, %2, !dbg !10
  %11 = fcmp oeq double %10, 1.000000e+00, !dbg !10
  br i1 %11, label %L, label %L3.loopexit, !dbg !10"><pre class="notranslate"><code class="notranslate">L:                                                ; preds = %L.preheader, %L
  %a.0 = phi double [ %8, %L ], [ %0, %L.preheader ]
  %6 = fmul double %a.0, %1, !dbg !10
  %7 = fadd double %6, %2, !dbg !10
  %8 = fdiv double %a.0, %7, !dbg !10
  %9 = fmul double %8, %1, !dbg !10
  %10 = fadd double %9, %2, !dbg !10
  %11 = fcmp oeq double %10, 1.000000e+00, !dbg !10
  br i1 %11, label %L, label %L3.loopexit, !dbg !10
</code></pre></div>
<p dir="auto">Note how <code class="notranslate">a*b+c</code> is evaluated twice in the loop.  A partial iteration has been peeled from the loop, which obscures the fact that <code class="notranslate">a*b+c</code> is being redundantly evaluated.</p>
<p dir="auto">From first glance, it appears that the partial peeling has already happened when LLVM sees the IR.  I'm guessing that it's being done early to improve type inference for the loop test (i.e. poor man's context-sensitivity by cloning code).  It's conceivable that a CSE-like pass could recognize this sort of thing.  Or maybe try to unpeel after type inferencing when types match?</p>
<p dir="auto">See my comments <a href="https://groups.google.com/d/msg/julia-users/_g_hWhg524g/n84XxX-D0W4J" rel="nofollow">here</a> for another example.</p>
<p dir="auto">Consider the following code:</p>
<div class="highlight highlight-source-julia notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="julia&gt; num_dict = Dict(1 =&gt; IntSet(1:2), 2 =&gt; IntSet(1:3))
Dict{Int64,IntSet} with 2 entries:
  2 =&gt; IntSet([1, 2, 3])
  1 =&gt; IntSet([1, 2])

julia&gt; length(values(num_dict))
2

julia&gt; length.(values(num_dict))
2

julia&gt; versioninfo()
Julia Version 0.6.0
Commit 903644385b (2017-06-19 13:05 UTC)
Platform Info:
  OS: macOS (x86_64-apple-darwin13.4.0)
  CPU: Intel(R) Core(TM) i7-4770HQ CPU @ 2.20GHz
  WORD_SIZE: 64
  BLAS: libopenblas (USE64BITINT DYNAMIC_ARCH NO_AFFINITY Haswell)
  LAPACK: libopenblas64_
  LIBM: libopenlibm
  LLVM: libLLVM-3.9.1 (ORCJIT, haswell)"><pre class="notranslate">julia<span class="pl-k">&gt;</span> num_dict <span class="pl-k">=</span> <span class="pl-c1">Dict</span>(<span class="pl-c1">1</span> <span class="pl-k">=&gt;</span> <span class="pl-c1">IntSet</span>(<span class="pl-c1">1</span><span class="pl-k">:</span><span class="pl-c1">2</span>), <span class="pl-c1">2</span> <span class="pl-k">=&gt;</span> <span class="pl-c1">IntSet</span>(<span class="pl-c1">1</span><span class="pl-k">:</span><span class="pl-c1">3</span>))
Dict{Int64,IntSet} with <span class="pl-c1">2</span> entries<span class="pl-k">:</span>
  <span class="pl-c1">2</span> <span class="pl-k">=&gt;</span> <span class="pl-c1">IntSet</span>([<span class="pl-c1">1</span>, <span class="pl-c1">2</span>, <span class="pl-c1">3</span>])
  <span class="pl-c1">1</span> <span class="pl-k">=&gt;</span> <span class="pl-c1">IntSet</span>([<span class="pl-c1">1</span>, <span class="pl-c1">2</span>])

julia<span class="pl-k">&gt;</span> <span class="pl-c1">length</span>(<span class="pl-c1">values</span>(num_dict))
<span class="pl-c1">2</span>

julia<span class="pl-k">&gt;</span> <span class="pl-c1">length</span>.(<span class="pl-c1">values</span>(num_dict))
<span class="pl-c1">2</span>

julia<span class="pl-k">&gt;</span> <span class="pl-c1">versioninfo</span>()
Julia Version <span class="pl-c1">0.6</span>.<span class="pl-c1">0</span>
Commit <span class="pl-c1">903644385</span>b (<span class="pl-c1">2017</span><span class="pl-k">-</span><span class="pl-c1">06</span><span class="pl-k">-</span><span class="pl-c1">19</span> <span class="pl-c1">13</span><span class="pl-k">:</span><span class="pl-c1">05</span> UTC)
Platform Info<span class="pl-k">:</span>
  OS<span class="pl-k">:</span> macOS (x86_64<span class="pl-k">-</span>apple<span class="pl-k">-</span>darwin13.<span class="pl-c1">4.0</span>)
  CPU<span class="pl-k">:</span> <span class="pl-c1">Intel</span>(R) <span class="pl-c1">Core</span>(TM) i7<span class="pl-k">-</span><span class="pl-c1">4770</span>HQ CPU @ <span class="pl-c1">2.20</span>GHz
  WORD_SIZE<span class="pl-k">:</span> <span class="pl-c1">64</span>
  BLAS<span class="pl-k">:</span> libopenblas (USE64BITINT DYNAMIC_ARCH NO_AFFINITY Haswell)
  LAPACK<span class="pl-k">:</span> libopenblas64_
  LIBM<span class="pl-k">:</span> libopenlibm
  LLVM<span class="pl-k">:</span> libLLVM<span class="pl-k">-</span><span class="pl-c1">3.9</span>.<span class="pl-c1">1</span> (ORCJIT, haswell)</pre></div>
<p dir="auto">It seems erroneous to me that in this case <code class="notranslate">length.(values(num_dict))</code> returns <code class="notranslate">2</code> instead of a vector with 3 and 2 as it's elements.</p>