Skip to content

Commit e859b41

Browse files
committed
Add a few convenience utilities
The main advantage these have is a small improvement in performance due to not needing to construct new objects. For Dicts of types, this switches to IdDict. This is both faster (particularly on construction), and safe for precompilation (see https://docs.julialang.org/en/latest/manual/modules/#Module-initialization-and-precompilation-1).
1 parent a31acc4 commit e859b41

File tree

7 files changed

+47
-6
lines changed

7 files changed

+47
-6
lines changed

src/LoopVectorization.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ export LowDimArray, stridedpointer, vectorizable,
2323

2424

2525
include("vectorizationbase_extensions.jl")
26+
include("predicates.jl")
2627
include("map.jl")
2728
include("filter.jl")
2829
include("costs.jl")

src/constructors.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,9 @@ function substitute_broadcast(q::Expr, mod::Symbol)
3030
f = first(ciₙargs)
3131
if ciₙ.head === :(=)
3232
push!(ex.args, Expr(:(=), f, syms[((ciₙargs[2])::Core.SSAValue).id]))
33-
elseif f === GlobalRef(Base, :materialize!)
33+
elseif isglobalref(f, Base, :materialize!)
3434
add_ci_call!(ex, lv(:vmaterialize!), ciₙargs, syms, n, mod)
35-
elseif f === GlobalRef(Base, :materialize)
35+
elseif isglobalref(f, Base, :materialize)
3636
add_ci_call!(ex, lv(:vmaterialize), ciₙargs, syms, n, mod)
3737
else
3838
add_ci_call!(ex, f, ciₙargs, syms, n)

src/costs.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -289,7 +289,7 @@ function isreductcombineinstr(instr::Symbol)
289289
end
290290
isreductcombineinstr(instr::Instruction) = isreductcombineinstr(instr.instr)
291291

292-
const FUNCTIONSYMBOLS = Dict{Type{<:Function},Instruction}(
292+
const FUNCTIONSYMBOLS = IdDict{Type{<:Function},Instruction}(
293293
typeof(+) => :(+),
294294
typeof(SIMDPirates.vadd) => :(+),
295295
typeof(SIMDPirates.vadd!) => :(+),

src/graphs.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ function terminatecondition(
110110
looprange(loop, 1, mangledname)
111111
end
112112

113-
# load/compute/store × isunroled × istiled × pre/post loop × Loop number
113+
# load/compute/store × isunrolled × istiled × pre/post loop × Loop number
114114
struct LoopOrder <: AbstractArray{Vector{Operation},5}
115115
oporder::Vector{Vector{Operation}}
116116
loopnames::Vector{Symbol}
@@ -402,7 +402,7 @@ function register_single_loop!(ls::LoopSet, looprange::Expr)
402402
L = add_loop_bound!(ls, itersym, Expr(:call, :first, N), false)
403403
U = add_loop_bound!(ls, itersym, Expr(:call, :last, N), true)
404404
Loop(itersym, L, U)
405-
elseif f === :OneTo || f == Expr(:(.), :Base, QuoteNode(:OneTo))
405+
elseif f === :OneTo || isscopedname(f, :Base, :OneTo)
406406
otN = r.args[2]
407407
if otN isa Integer
408408
Loop(itersym, 0, otN)

src/predicates.jl

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
"""
2+
isscopedname(ex, modpath, name::Symbol)
3+
4+
Test whether expression `ex` is a module-scoped `name`. Both of these return `true`:
5+
6+
```
7+
isscopedname(:(Base.OneTo), :Base, :OneTo)
8+
isscopedname(:(Base.Checked.checked_add), (:Base, :Checked), :checked_add)
9+
```
10+
"""
11+
function isscopedname(ex, modpath, name::Symbol)
12+
isexpr(ex, :(.), 2) && (a = ex.args[2]; isa(a, QuoteNode) && a.value === name) && hasscope(ex.args[1], modpath)
13+
end
14+
hasscope(modex, mod::Symbol) = modex === mod
15+
hasscope(modex, mod::Tuple{Symbol}) = hasscope(modex, mod[1])
16+
hasscope(modex, modpath::Tuple{Vararg{Symbol}}) = isscopedname(modex, Base.front(modpath), modpath[end])
17+
18+
"""
19+
isglobalref(g, mod, name)
20+
21+
Return true if `g` is equal to `GlobalRef(mod, name)`.
22+
"""
23+
isglobalref(g, mod, name) = isa(g, GlobalRef) && g.mod === mod && g.name === name

test/runtests.jl

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,10 @@ end
1818

1919
@time include("printmethods.jl")
2020

21+
@time include("utils.jl")
22+
2123
@time include("offsetarrays.jl")
22-
24+
2325
@time include("map.jl")
2426

2527
@time include("filter.jl")

test/utils.jl

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
using LoopVectorization
2+
using Test
3+
4+
@testset "Utilities" begin
5+
@test LoopVectorization.isscopedname(:(Base.OneTo), :Base, :OneTo)
6+
@test LoopVectorization.isscopedname(:(A.B.C.D), (:A, :B, :C), :D)
7+
@test !LoopVectorization.isscopedname(:(A.B.D), (:A, :B, :C), :D)
8+
@test !LoopVectorization.isscopedname(:(A.B.C.D), (:A, :B, :C), :E)
9+
@test !LoopVectorization.isscopedname(:hello, :Base, :OneTo)
10+
11+
@test LoopVectorization.isglobalref(GlobalRef(Base, :getindex), Base, :getindex)
12+
@test !LoopVectorization.isglobalref(GlobalRef(Base, :getindex), Base, :setindex!)
13+
@test !LoopVectorization.isglobalref(GlobalRef(Core, :getindex), Base, :getindex)
14+
@test !LoopVectorization.isglobalref(:getindex, Base, :getindex)
15+
end

0 commit comments

Comments
 (0)