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
; └
}