Skip to content

Commit a741dfe

Browse files
vtjnashstaticfloat
authored andcommitted
implement with fewer afoldl methods (#39414)
With constant-propagation, inference (and Varargs runtime) is likely better able to handle this version now (and it removes the n^2 behavior definitions for semi-low argument counts). Now we also need to force Vararg specialization up to 16 arguments manually, so we do that explicitly (and slightly hack-y). Fixes regression in #39175 (cherry picked from commit 5cd1e3e)
1 parent 434641e commit a741dfe

File tree

2 files changed

+31
-9
lines changed

2 files changed

+31
-9
lines changed

base/operators.jl

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -520,17 +520,37 @@ xor(x::Integer) = x
520520

521521
const = xor
522522

523-
# foldl for argument lists. expand recursively up to a point, then
524-
# switch to a loop. this allows small cases like `a+b+c+d` to be inlined
523+
# foldl for argument lists. expand fully up to a point, then
524+
# switch to a loop. this allows small cases like `a+b+c+d` to be managed
525525
# efficiently, without a major slowdown for `+(x...)` when `x` is big.
526-
afoldl(op,a) = a
527-
afoldl(op,a,b) = op(a,b)
528-
afoldl(op,a,b,c...) = afoldl(op, op(a,b), c...)
529-
function afoldl(op,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,qs...)
530-
y = op(op(op(op(op(op(op(op(op(op(op(op(op(op(op(a,b),c),d),e),f),g),h),i),j),k),l),m),n),o),p)
531-
for x in qs; y = op(y,x); end
532-
y
526+
# n.b.: keep this method count small, so it can be inferred without hitting the
527+
# method count limit in inference
528+
afoldl(op, a) = a
529+
function afoldl(op, a, bs...)
530+
l = length(bs)
531+
i = 0; y = a; l == i && return y
532+
#@nexprs 15 i -> (y = op(y, bs[i]); l == i && return y)
533+
i = 1; y = op(y, bs[i]); l == i && return y
534+
i = 2; y = op(y, bs[i]); l == i && return y
535+
i = 3; y = op(y, bs[i]); l == i && return y
536+
i = 4; y = op(y, bs[i]); l == i && return y
537+
i = 5; y = op(y, bs[i]); l == i && return y
538+
i = 6; y = op(y, bs[i]); l == i && return y
539+
i = 7; y = op(y, bs[i]); l == i && return y
540+
i = 8; y = op(y, bs[i]); l == i && return y
541+
i = 9; y = op(y, bs[i]); l == i && return y
542+
i = 10; y = op(y, bs[i]); l == i && return y
543+
i = 11; y = op(y, bs[i]); l == i && return y
544+
i = 12; y = op(y, bs[i]); l == i && return y
545+
i = 13; y = op(y, bs[i]); l == i && return y
546+
i = 14; y = op(y, bs[i]); l == i && return y
547+
i = 15; y = op(y, bs[i]); l == i && return y
548+
for i in (i + 1):l
549+
y = op(y, bs[i])
550+
end
551+
return y
533552
end
553+
typeof(afoldl).name.mt.max_args = 18
534554

535555
for op in (:+, :*, :&, :|, :xor, :min, :max, :kron)
536556
@eval begin

test/operators.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,3 +255,5 @@ end
255255

256256
a = rand(3, 3)
257257
@test transpose(a) === a'
258+
259+
@test [Base.afoldl(+, 1:i...) for i = 1:40] == [i * (i + 1) ÷ 2 for i = 1:40]

0 commit comments

Comments
 (0)