Skip to content

Commit

Permalink
add experimental aliasscopes API
Browse files Browse the repository at this point in the history
  • Loading branch information
vchuravy committed Apr 11, 2019
1 parent 50ec39c commit d222248
Show file tree
Hide file tree
Showing 5 changed files with 143 additions and 25 deletions.
3 changes: 3 additions & 0 deletions base/Base.jl
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,9 @@ include("util.jl")

include("asyncmap.jl")

# experimental API's
include("experimental.jl")

# deprecated functions
include("deprecated.jl")

Expand Down
52 changes: 52 additions & 0 deletions base/experimental.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# This file is a part of Julia. License is MIT: https://julialang.org/license

"""
Experimental
!!! warning
Types, methods, or macros defined in this module are experimental and subject
to change and will not have deprecations. Caveat emptor.
"""
module Experimental

"""
Const(A::Array)
Mark an Array as constant/read-only. The invariant guaranteed is that you will not
modify an Array (through another reference) within an `@aliasscope` scope.
!!! warning
Experimental API. Subject to change without deprecation.
"""
struct Const{T,N} <: DenseArray{T,N}
a::Array{T,N}
end

Base.IndexStyle(::Type{<:Const}) = IndexLinear()
Base.size(C::Const) = size(C.a)
Base.axes(C::Const) = axes(C.a)
@eval Base.getindex(A::Const, i1::Int) =
(Base.@_inline_meta; Core.const_arrayref($(Expr(:boundscheck)), A.a, i1))
@eval Base.getindex(A::Const, i1::Int, i2::Int, I::Int...) =
(Base.@_inline_meta; Core.const_arrayref($(Expr(:boundscheck)), A.a, i1, i2, I...))

"""
@aliasscope expr
Allows the compiler to assume that all `Const`s are not being modified through stores
within this scope, even if the compiler can't prove this to be the case.
!!! warning
Experimental API. Subject to change without deprecation.
"""
macro aliasscope(body)
sym = gensym()
quote
$(Expr(:aliasscope))
$sym = $(esc(body))
$(Expr(:popaliasscope))
$sym
end
end

end
61 changes: 61 additions & 0 deletions test/llvmpasses/aliasscopes.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# This file is a part of Julia. License is MIT: https://julialang.org/license

# RUN: julia --startup-file=no %s %t && llvm-link -S %t/* -o %t/module.ll
# RUN: cat %t/module.ll | FileCheck %s

## Notes:
# This script uses the `emit` function (defined llvmpasses.jl) to emit either
# optimized or unoptimized LLVM IR. Each function is emitted individually and
# `llvm-link` is used to create a single module that can be passed to opt.
# The order in which files are emitted and linked is important since `lit` will
# process the test cases in order.

include(joinpath("..", "testhelpers", "llvmpasses.jl"))

import Base.Experimental: Const, @aliasscope

# CHECK-LABEL: @julia_simple
function simple(A, B)
@aliasscope @inbounds for I in eachindex(A, B)
A[I] = Const(B)[I]
# CHECK: load double, {{.*}} !alias.scope [[SCOPE:![0-9]+]]
# CHECK: store double {{.*}} !noalias [[SCOPE]]
end
return 0 # return nothing causes japi1
end

# CHECK-LABEL: @julia_constargs
function constargs(A, B::Const)
@aliasscope @inbounds for I in eachindex(A, B)
A[I] = B[I]
# CHECK: load double, {{.*}} !alias.scope [[SCOPE2:![0-9]+]]
# CHECK: store double {{.*}} !noalias [[SCOPE2]]
end
return 0
end

# CHECK-LABEL: @"julia_micro_ker!
function micro_ker!(AB, Ac, Bc, kc, offSetA, offSetB)
MR = 8; NR = 6;
@inbounds @aliasscope for k in 1:kc
for j in 1:NR, i in 1:MR
AB[i+(j-1)*MR] = muladd(Const(Ac)[offSetA+i], Const(Bc)[offSetB+j], Const(AB)[i+(j-1)*MR])
# CHECK: load double, {{.*}} !alias.scope [[SCOPE3:![0-9]+]]
# CHECK: load double, {{.*}} !alias.scope [[SCOPE3]]
# CHECK: load double, {{.*}} !alias.scope [[SCOPE3]]
# CHECK: store double {{.*}} !noalias [[SCOPE3]]
end
offSetA += MR
offSetB += NR
end
return
end

# CHECK: [[SCOPE]] = !{[[ALIASSCOPE:![0-9]+]]}
# CHECK: [[ALIASSCOPE]] = !{!"aliasscope", [[MDNODE:![0-9]+]]}
# CHECK: [[MDNODE]] = !{!"simple"}

emit(simple, Vector{Float64}, Vector{Float64})
emit(constargs, Vector{Float64}, Const{Float64, 1})
emit(micro_ker!, Matrix{Float64}, Vector{Float64}, Vector{Float64}, Int64, Int64, Int64)

27 changes: 2 additions & 25 deletions test/llvmpasses/loopinfo.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,9 @@
# RUN: cat %t/module.ll | opt -load libjulia%shlibext -LowerSIMDLoop -S - | FileCheck %s -check-prefix=LOWER
# RUN: julia --startup-file=no %s %t -O && llvm-link -S %t/* -o %t/module.ll
# RUN: cat %t/module.ll | FileCheck %s -check-prefix=FINAL
using InteractiveUtils
using Printf

## Notes:
# This script uses the `emit` function (defined at the end) to emit either
# This script uses the `emit` function (defined llvmpasses.jl) to emit either
# optimized or unoptimized LLVM IR. Each function is emitted individually and
# `llvm-link` is used to create a single module that can be passed to opt.
# The order in which files are emitted and linked is important since `lit` will
Expand All @@ -19,17 +17,7 @@ using Printf
# - `CHECK`: Checks the result of codegen
# - `LOWER`: Checks the result of -LowerSIMDLoop
# - `FINAL`: Checks the result of running the entire pipeline

# get a temporary directory
dir = ARGS[1]
rm(dir, force=true, recursive=true)
mkdir(dir)

# toggle between unoptimized (CHECK/LOWER) and optimized IR (FINAL).
optimize=false
if length(ARGS) >= 2
optimize = ARGS[2]=="-O"
end
include(joinpath("..", "testhelpers", "llvmpasses.jl"))

# CHECK-LABEL: @julia_simdf_
# LOWER-LABEL: @julia_simdf_
Expand Down Expand Up @@ -142,17 +130,6 @@ end
# LOWER: [[LOOPID4]] = distinct !{[[LOOPID4]], [[LOOPUNROLL2:![0-9]+]]}
# LOWER: [[LOOPUNROLL2]] = !{!"llvm.loop.unroll.full"}

# Emit LLVM IR to dir
counter = 0
function emit(f, tt...)
global counter
name = nameof(f)
open(joinpath(dir, @sprintf("%05d-%s.ll", counter, name)), "w") do io
code_llvm(io, f, tt, raw=true, optimize=optimize, dump_module=true, debuginfo=:none)
end
counter+=1
end

# Maintaining the order is important
emit(simdf, Vector{Float64})
emit(simdf2, Vector{Float64})
Expand Down
25 changes: 25 additions & 0 deletions test/testhelpers/llvmpasses.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using InteractiveUtils
using Printf

# get a temporary directory
dir = ARGS[1]
rm(dir, force=true, recursive=true)
mkdir(dir)

# toggle between unoptimized (CHECK/LOWER) and optimized IR (FINAL).
optimize=false
if length(ARGS) >= 2
optimize = ARGS[2]=="-O"
end

# Emit LLVM IR to dir
counter = 0
function emit(f, tt...)
global counter
name = nameof(f)
open(joinpath(dir, @sprintf("%05d-%s.ll", counter, name)), "w") do io
code_llvm(io, f, tt, raw=true, optimize=optimize, dump_module=true, debuginfo=:none)
end
counter+=1
end

0 comments on commit d222248

Please sign in to comment.