Do C++ performance optimisations apply to Julia?

I have a couple of examples of optimizations.


#simple LUT

julia> function foo(x)
           if x == 1
               7
           elseif x == 2
               8
           elseif x == 3
               9
           elseif x == 4
               10
           elseif x == 5
               11
           elseif x == 6
               12
           elseif x == 7
               13
           elseif x == 8
               14
           elseif x == 9
               15
           elseif x == 10
               16
           elseif x == 11
               17
           else
               0
           end
       end
foo (generic function with 1 method)

julia> @code_llvm foo(4)
;  @ REPL[1]:1 within `foo`
define i64 @julia_foo_102(i64 signext %0) #0 {
top:
;  @ REPL[1]:2 within `foo`
  %switch.tableidx = add i64 %0, -1
  %1 = icmp ult i64 %switch.tableidx, 10
  %.not10 = icmp eq i64 %0, 11
  %. = select i1 %.not10, i64 17, i64 0
  %switch.offset = add i64 %0, 6
  %common.ret.op = select i1 %1, i64 %switch.offset, i64 %.
;  @ REPL[1] within `foo`
  ret i64 %common.ret.op
}

#jump table julia> function foo(x)
           if x == 1
               x * 7
           elseif x == 2
               x * 8
           elseif x == 3
               x * 9
           elseif x == 4
               x * 10
           elseif x == 5
               x * 11
           elseif x == 16
               x * 12
           elseif x == 71
               x * 13
           elseif x == 8
               x * 14
           elseif x == 9
               x * 15
           elseif x == 10
               x * 16
           elseif x == 11
               x * 17
           else
               x * 0
           end
       end
foo (generic function with 1 method)

julia> @code_llvm foo(4)
;  @ REPL[5]:1 within `foo`
define i64 @julia_foo_119(i64 signext %0) #0 {
top:
;  @ REPL[5]:2 within `foo`
  switch i64 %0, label %common.ret [
    i64 1, label %L3
    i64 2, label %L7
    i64 3, label %L11
    i64 4, label %L15
    i64 5, label %L19
    i64 16, label %L23
    i64 71, label %L27
    i64 8, label %L31
    i64 9, label %L35
    i64 10, label %L39
    i64 11, label %L43
  ]

common.ret:                                       ; preds = %L43, %L39, %L35, %L31, %L27, %L23, %L19, %L15, %L11, %L7, %L3, %top
  %common.ret.op = phi i64 [ 7, %L3 ], [ 16, %L7 ], [ 27, %L11 ], [ 40, %L15 ], [ 55, %L19 ], [ 192, %L23 ], [ 923, %L27 ], [ 112, %L31 ], [ 135, %L35 ], [ 160, %L39 ], [ 187, %L43 ], [ 0, %top ]
;  @ REPL[5] within `foo`
  ret i64 %common.ret.op

L3:                                               ; preds = %top
  br label %common.ret

L7:                                               ; preds = %top
  br label %common.ret

L11:                                              ; preds = %top
  br label %common.ret

L15:                                              ; preds = %top
  br label %common.ret

L19:                                              ; preds = %top
  br label %common.ret

L23:                                              ; preds = %top
  br label %common.ret

L27:                                              ; preds = %top
  br label %common.ret

L31:                                              ; preds = %top
  br label %common.ret

L35:                                              ; preds = %top
  br label %common.ret

L39:                                              ; preds = %top
  br label %common.ret

L43:                                              ; preds = %top
  br label %common.ret
}

#more sophisticated LUT

julia> @code_llvm foo(a)
;  @ REPL[9]:1 within `foo`
define i64 @julia_foo_150(i64 signext %0) #0 {
top:
;  @ REPL[9]:2 within `foo`
  %switch.tableidx = add i64 %0, -1
  %1 = icmp ult i64 %switch.tableidx, 10
  br i1 %1, label %switch.lookup, label %L31

switch.lookup:                                    ; preds = %top
  %switch.gep = getelementptr inbounds [10 x i64], [10 x i64]* @switch.table.julia_foo_150, i64 0, i64 %switch.tableidx
  %switch.load = load i64, i64* %switch.gep, align 8
  br label %common.ret

common.ret:                                       ; preds = %L31, %switch.lookup
  %common.ret.op = phi i64 [ %., %L31 ], [ %switch.load, %switch.lookup ]
;  @ REPL[9] within `foo`
  ret i64 %common.ret.op

L31:                                              ; preds = %top
;  @ REPL[9]:22 within `foo`
; ┌ @ promotion.jl:477 within `==`
   %.not10 = icmp eq i64 %0, 11
   %. = select i1 %.not10, i64 17, i64 0
   br label %common.ret
; └
}
2 Likes