|
1 | 1 |
|
2 | | -mulexprcost(::Number) = 0 |
3 | | -mulexprcost(::Symbol) = 1 |
4 | | -function mulexprcost(ex::Expr) |
5 | | - base = ex.head === :call ? 10 : 1 |
6 | | - base + length(ex.args) |
| 2 | +const ProdArg = Union{Symbol,Expr,Number} |
| 3 | +function mulexprcost(@nospecialize(x::ProdArg))::Int |
| 4 | + if x isa Number |
| 5 | + return 0 |
| 6 | + elseif x isa Symbol |
| 7 | + return 1 |
| 8 | + else |
| 9 | + ex = x::Expr |
| 10 | + base = ex.head === :call ? 10 : 1 |
| 11 | + return base + length(ex.args) |
| 12 | + end |
7 | 13 | end |
8 | | -function mul_fast_expr(args) |
| 14 | +function mul_fast_expr( |
| 15 | + args::SubArray{Any,1,Vector{Any},Tuple{UnitRange{Int}},true} |
| 16 | +)::Expr |
9 | 17 | b = Expr(:call, :mul_fast) |
10 | 18 | for i ∈ 2:length(args) |
11 | 19 | push!(b.args, args[i]) |
12 | 20 | end |
13 | 21 | b |
14 | 22 | end |
15 | | -function mulexpr(mulexargs) |
16 | | - a = (mulexargs[1])::Union{Symbol,Expr,Number} |
17 | | - if length(mulexargs) == 2 |
18 | | - return (a, mulexargs[2]::Union{Symbol,Expr,Number}) |
19 | | - elseif length(mulexargs) == 3 |
20 | | - # We'll calc the product between the guesstimated cheaper two args first, for better out of order execution |
21 | | - b = (mulexargs[2])::Union{Symbol,Expr,Number} |
22 | | - c = (mulexargs[3])::Union{Symbol,Expr,Number} |
23 | | - ac = mulexprcost(a) |
24 | | - bc = mulexprcost(b) |
25 | | - cc = mulexprcost(c) |
26 | | - maxc = max(ac, bc, cc) |
27 | | - if ac == maxc |
28 | | - return (a, Expr(:call, :mul_fast, b, c)) |
29 | | - elseif bc == maxc |
30 | | - return (b, Expr(:call, :mul_fast, a, c)) |
31 | | - else |
32 | | - return (c, Expr(:call, :mul_fast, a, b)) |
33 | | - end |
34 | | - else |
35 | | - return (a, mul_fast_expr(mulexargs)) |
36 | | - end |
37 | | - a = (mulexargs[1])::Union{Symbol,Expr,Number} |
38 | | - b = if length(mulexargs) == 2 # two arg mul |
39 | | - (mulexargs[2])::Union{Symbol,Expr,Number} |
40 | | - else |
41 | | - mul_fast_expr(mulexargs) |
42 | | - end |
43 | | - a, b |
| 23 | +function mulexpr( |
| 24 | + mulexargs::SubArray{Any,1,Vector{Any},Tuple{UnitRange{Int}},true} |
| 25 | +)::Tuple{ProdArg,ProdArg} |
| 26 | + a = (mulexargs[1])::ProdArg |
| 27 | + Nexpr = length(mulexargs) |
| 28 | + Nexpr == 2 && return (a, mulexargs[2]::ProdArg) |
| 29 | + Nexpr != 3 && return (a, mul_fast_expr(mulexargs)) |
| 30 | + # We'll calc the product between the guesstimated cheaper two args first, for better out of order execution |
| 31 | + b = (mulexargs[2])::ProdArg |
| 32 | + c = (mulexargs[3])::ProdArg |
| 33 | + ac = mulexprcost(a) |
| 34 | + bc = mulexprcost(b) |
| 35 | + cc = mulexprcost(c) |
| 36 | + maxc = max(ac, bc, cc) |
| 37 | + ac == maxc && return (a, Expr(:call, :mul_fast, b, c)) |
| 38 | + bc == maxc && return (b, Expr(:call, :mul_fast, c, a)) |
| 39 | + return (c, Expr(:call, :mul_fast, a, b)) |
44 | 40 | end |
45 | 41 | function append_args_skip!(call, args, i, mod) |
46 | 42 | for j ∈ eachindex(args) |
@@ -222,7 +218,8 @@ function capture_a_muladd(ex::Expr, mod) |
222 | 218 | end |
223 | 219 | true, call |
224 | 220 | end |
225 | | -capture_muladd(ex::Expr, mod) = while true |
| 221 | +capture_muladd(ex::Expr, mod) = |
| 222 | + while true |
226 | 223 | ex.head === :ref && return ex |
227 | 224 | if Meta.isexpr(ex, :call, 2) |
228 | 225 | if (ex.args[1] === :(-)) |
|
0 commit comments