Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
459c79c
make pending_perm a heap instead of sorted vector in optimizer (#46586)
Sep 1, 2022
5154cf0
Replace Vector with BitSet in optimization passes (#46587)
Sep 2, 2022
e3d30d7
inline final use of sort! in compiler
Sep 8, 2022
5252699
Make Sort a stdlib (big diff)
Sep 10, 2022
bbcbdc4
remove no longer needed using statements
Sep 10, 2022
18debc3
switch from Floats to IEEEFloat
Sep 10, 2022
906c3d9
replace metaprogramming with `unsigned`
Sep 10, 2022
dece402
revert negligible whitespace changes
Sep 10, 2022
9366364
add copyright notice to top of new files
Sep 10, 2022
6350759
update makefile so that `make cleanall && make` passes
Sep 10, 2022
d52cbe7
move docs
Sep 10, 2022
4591ce8
Switch from combsort to heapsort
LilithHafner Sep 12, 2022
fe406a6
make UUID consistent
Sep 13, 2022
673904e
fix whitespace
Sep 13, 2022
ff23137
try to fix docs
Sep 13, 2022
efe23b6
Merge branch 'master' into remove-compiler-sort
LilithHafner Sep 30, 2022
e0a44ad
remove cross references in sorting docs (TODO: Revert this)
Oct 1, 2022
6225a18
add NEWS.md entry
Oct 1, 2022
2d43a09
add compiler sort tests (needs fixup)
Oct 1, 2022
701daeb
stop running base/sorting tests (moved to stdlib/sort) (needs fixup)
Oct 1, 2022
5f000e6
fix test usage of OffsetArrays (following pattern of Random)
Oct 1, 2022
0ec2d02
fixups for tests (remove debug print statements)
Oct 1, 2022
d0d5078
try to fix precompile test
Oct 1, 2022
f26ee61
Revert e0a44ad0 and add explicit @ref targets
Oct 2, 2022
0c5c6a8
fix outdated comment (cf #46877)
Oct 2, 2022
69e4215
Merge branch 'master' into remove-compiler-sort
LilithHafner Oct 2, 2022
702ecd1
Merge branch 'master' into remove-compiler-sort
Oct 4, 2022
14a82e8
Merge branch 'master' into remove-compiler-sort
Oct 4, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,9 @@ Standard library changes
* An "IPython mode" which mimics the behaviour of the prompts and storing the evaluated result in `Out` can be
activated with `REPL.ipython_mode!()`. See the manual for how to enable this at startup.

#### Sort
* `Sort` has moved out of base and is now a standard library. ([#46679])

#### SparseArrays

#### Test
Expand Down
8 changes: 2 additions & 6 deletions base/Base.jl
Original file line number Diff line number Diff line change
Expand Up @@ -346,10 +346,8 @@ include("ordering.jl")
using .Order

# Combinatorics
include("sort.jl")
using .Sort

# BinaryPlatforms, used by Artifacts. Needs `Sort`.
# BinaryPlatforms, used by Artifacts.
include("binaryplatforms.jl")

# Fast math
Expand Down Expand Up @@ -465,8 +463,6 @@ for match = _methods(+, (Int, Int), -1, get_world_counter())
Dict("abc" => Set())["abc"]
pushfirst!([], sum)
get(Base.pkgorigins, Base.PkgId(Base), nothing)
sort!([1,2,3])
unique!([1,2,3])
cumsum([1,2,3])
append!(Int[], BitSet())
isempty(BitSet())
Expand All @@ -477,7 +473,7 @@ for match = _methods(+, (Int, Int), -1, get_world_counter())
any(t->t[1].line > 1, [(LineNumberNode(2,:none), :(1+1))])

# Code loading uses this
sortperm(mtime.(readdir(".")), rev=true)
mtime.(readdir(".", sort=false))
# JLLWrappers uses these
Dict{UUID,Set{String}}()[UUID("692b3bcd-3c85-4b1f-b108-f13ce0eb3210")] = Set{String}()
get!(Set{String}, Dict{UUID,Set{String}}(), UUID("692b3bcd-3c85-4b1f-b108-f13ce0eb3210"))
Expand Down
1 change: 0 additions & 1 deletion base/bitset.jl
Original file line number Diff line number Diff line change
Expand Up @@ -430,4 +430,3 @@ end
minimum(s::BitSet) = first(s)
maximum(s::BitSet) = last(s)
extrema(s::BitSet) = (first(s), last(s))
issorted(s::BitSet) = true
4 changes: 1 addition & 3 deletions base/compiler/compiler.jl
Original file line number Diff line number Diff line change
Expand Up @@ -121,12 +121,10 @@ import Core.Compiler.CoreDocs
Core.atdoc!(CoreDocs.docm)

# sorting
function sort! end
function issorted end
include("ordering.jl")
using .Order
include("sort.jl")
using .Sort
include("compiler/sort.jl")

# We don't include some.jl, but this definition is still useful.
something(x::Nothing, y...) = something(y...)
Expand Down
100 changes: 100 additions & 0 deletions base/compiler/sort.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
# This file is a part of Julia. License is MIT: https://julialang.org/license

# reference on sorted binary search:
# http://www.tbray.org/ongoing/When/200x/2003/03/22/Binary

# index of the first value of vector a that is greater than or equal to x;
# returns lastindex(v)+1 if x is greater than all values in v.
function searchsortedfirst(v::AbstractVector, x, lo::T, hi::T, o::Ordering)::keytype(v) where T<:Integer
hi = hi + T(1)
len = hi - lo
@inbounds while len != 0
half_len = len >>> 0x01
m = lo + half_len
if lt(o, v[m], x)
lo = m + 1
len -= half_len + 1
else
hi = m
len = half_len
end
end
return lo
end

# index of the last value of vector a that is less than or equal to x;
# returns firstindex(v)-1 if x is less than all values of v.
function searchsortedlast(v::AbstractVector, x, lo::T, hi::T, o::Ordering)::keytype(v) where T<:Integer
u = T(1)
lo = lo - u
hi = hi + u
@inbounds while lo < hi - u
m = midpoint(lo, hi)
if lt(o, x, v[m])
hi = m
else
lo = m
end
end
return lo
end

# returns the range of indices of v equal to x
# if v does not contain x, returns a 0-length range
# indicating the insertion point of x
function searchsorted(v::AbstractVector, x, ilo::T, ihi::T, o::Ordering)::UnitRange{keytype(v)} where T<:Integer
u = T(1)
lo = ilo - u
hi = ihi + u
@inbounds while lo < hi - u
m = midpoint(lo, hi)
if lt(o, v[m], x)
lo = m
elseif lt(o, x, v[m])
hi = m
else
a = searchsortedfirst(v, x, max(lo,ilo), m, o)
b = searchsortedlast(v, x, m, min(hi,ihi), o)
return a : b
end
end
return (lo + 1) : (hi - 1)
end

for s in [:searchsortedfirst, :searchsortedlast, :searchsorted]
@eval begin
$s(v::AbstractVector, x, o::Ordering) = $s(v,x,firstindex(v),lastindex(v),o)
$s(v::AbstractVector, x;
lt=isless, by=identity, rev::Union{Bool,Nothing}=nothing, order::Ordering=Forward) =
$s(v,x,ord(lt,by,rev,order))
end
end

# An unstable sorting algorithm for internal use
function sort!(v::Vector; by::Function=identity, (<)::Function=<)
isempty(v) && return v # This branch is hit 95% of the time

# Of the remaining 5%, this branch is hit less than 1% of the time
if length(v) > 200 # Heap sort prevents quadratic runtime
o = ord(<, by, true)
heapify!(v, o)
for i in lastindex(v):-1:2
y = v[i]
v[i] = v[1]
percolate_down!(v, 1, y, o, i-1)
end
return v
end

@inbounds for i in 2:length(v) # Insertion sort
x = v[i]
y = by(x)
while i > 1 && y < by(v[i-1])
v[i] = v[i-1]
i -= 1
end
v[i] = x
end

v
end
33 changes: 10 additions & 23 deletions base/compiler/ssair/ir.jl
Original file line number Diff line number Diff line change
Expand Up @@ -534,16 +534,6 @@ end
insert_node!(ir::IRCode, pos::Int, inst::NewInstruction, attach_after::Bool=false) =
insert_node!(ir, SSAValue(pos), inst, attach_after)

# For bootstrapping
function my_sortperm(v)
p = Vector{Int}(undef, length(v))
for i = 1:length(v)
p[i] = i
end
sort!(p, Sort.DEFAULT_UNSTABLE, Order.Perm(Sort.Forward,v))
p
end

mutable struct IncrementalCompact
ir::IRCode
result::InstructionStream
Expand All @@ -560,9 +550,8 @@ mutable struct IncrementalCompact
# This supports insertion while compacting
new_new_nodes::NewNodeStream # New nodes that were before the compaction point at insertion time
new_new_used_ssas::Vector{Int}
# TODO: Switch these two to a min-heap of some sort
pending_nodes::NewNodeStream # New nodes that were after the compaction point at insertion time
pending_perm::Vector{Int}
pending_perm::Vector{Int} # pending_nodes.info[pending_perm] is in min-heap order by pos

# State
idx::Int
Expand All @@ -574,10 +563,9 @@ mutable struct IncrementalCompact

function IncrementalCompact(code::IRCode, allow_cfg_transforms::Bool=false)
# Sort by position with attach after nodes after regular ones
perm = my_sortperm(Int[let new_node = code.new_nodes.info[i]
(new_node.pos * 2 + Int(new_node.attach_after))
end for i in 1:length(code.new_nodes)])
new_len = length(code.stmts) + length(code.new_nodes)
info = code.new_nodes.info
perm = sort!(collect(eachindex(info)); by=i->(2info[i].pos+info[i].attach_after, i))
new_len = length(code.stmts) + length(info)
result = InstructionStream(new_len)
used_ssas = fill(0, new_len)
new_new_used_ssas = Vector{Int}()
Expand Down Expand Up @@ -629,8 +617,9 @@ mutable struct IncrementalCompact

# For inlining
function IncrementalCompact(parent::IncrementalCompact, code::IRCode, result_offset)
perm = my_sortperm(Int[code.new_nodes.info[i].pos for i in 1:length(code.new_nodes)])
new_len = length(code.stmts) + length(code.new_nodes)
info = code.new_nodes.info
perm = sort!(collect(eachindex(info)); by=i->(info[i].pos, i))
new_len = length(code.stmts) + length(info)
ssa_rename = Any[SSAValue(i) for i = 1:new_len]
bb_rename = Vector{Int}()
pending_nodes = NewNodeStream()
Expand Down Expand Up @@ -769,9 +758,7 @@ end

function add_pending!(compact::IncrementalCompact, pos::Int, attach_after::Bool)
node = add!(compact.pending_nodes, pos, attach_after)
# TODO: switch this to `l = length(pending_nodes); splice!(pending_perm, searchsorted(pending_perm, l), l)`
push!(compact.pending_perm, length(compact.pending_nodes))
sort!(compact.pending_perm, DEFAULT_STABLE, Order.By(x->compact.pending_nodes.info[x].pos, Order.Forward))
heappush!(compact.pending_perm, length(compact.pending_nodes), By(x -> compact.pending_nodes.info[x].pos))
return node
end

Expand Down Expand Up @@ -1456,7 +1443,7 @@ function iterate_compact(compact::IncrementalCompact, (idx, active_bb)::Tuple{In
if !(info.attach_after ? info.pos <= compact.idx - 1 : info.pos <= compact.idx)
break
end
popfirst!(compact.pending_perm)
heappop!(compact.pending_perm, By(x -> compact.pending_nodes.info[x].pos))
end
# Move to next block
compact.idx += 1
Expand All @@ -1481,7 +1468,7 @@ function iterate_compact(compact::IncrementalCompact, (idx, active_bb)::Tuple{In
elseif !isempty(compact.pending_perm) &&
(info = compact.pending_nodes.info[compact.pending_perm[1]];
info.attach_after ? info.pos == idx - 1 : info.pos == idx)
new_idx = popfirst!(compact.pending_perm)
new_idx = heappop!(compact.pending_perm, By(x -> compact.pending_nodes.info[x].pos))
new_node_entry = compact.pending_nodes.stmts[new_idx]
new_node_info = compact.pending_nodes.info[new_idx]
new_idx += length(compact.ir.stmts) + length(compact.ir.new_nodes)
Expand Down
14 changes: 7 additions & 7 deletions base/compiler/ssair/passes.jl
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ function try_compute_fieldidx_stmt(ir::Union{IncrementalCompact,IRCode}, stmt::E
return try_compute_fieldidx(typ, field)
end

function find_curblock(domtree::DomTree, allblocks::Vector{Int}, curblock::Int)
function find_curblock(domtree::DomTree, allblocks::BitSet, curblock::Int)
# TODO: This can be much faster by looking at current level and only
# searching for those blocks in a sorted order
while !(curblock in allblocks) && curblock !== 0
Expand All @@ -92,7 +92,7 @@ function val_for_def_expr(ir::IRCode, def::Int, fidx::Int)
end
end

function compute_value_for_block(ir::IRCode, domtree::DomTree, allblocks::Vector{Int}, du::SSADefUse, phinodes::IdDict{Int, SSAValue}, fidx::Int, curblock::Int)
function compute_value_for_block(ir::IRCode, domtree::DomTree, allblocks::BitSet, du::SSADefUse, phinodes::IdDict{Int, SSAValue}, fidx::Int, curblock::Int)
curblock = find_curblock(domtree, allblocks, curblock)
def = 0
for stmt in du.defs
Expand All @@ -103,7 +103,7 @@ function compute_value_for_block(ir::IRCode, domtree::DomTree, allblocks::Vector
def == 0 ? phinodes[curblock] : val_for_def_expr(ir, def, fidx)
end

function compute_value_for_use(ir::IRCode, domtree::DomTree, allblocks::Vector{Int},
function compute_value_for_use(ir::IRCode, domtree::DomTree, allblocks::BitSet,
du::SSADefUse, phinodes::IdDict{Int, SSAValue}, fidx::Int, use::Int)
def, useblock, curblock = find_def_for_use(ir, domtree, allblocks, du, use)
if def == 0
Expand All @@ -122,7 +122,7 @@ end
# even when the allocation contains an uninitialized field, we try an extra effort to check
# if this load at `idx` have any "safe" `setfield!` calls that define the field
function has_safe_def(
ir::IRCode, domtree::DomTree, allblocks::Vector{Int}, du::SSADefUse,
ir::IRCode, domtree::DomTree, allblocks::BitSet, du::SSADefUse,
newidx::Int, idx::Int)
def, _, _ = find_def_for_use(ir, domtree, allblocks, du, idx)
# will throw since we already checked this `:new` site doesn't define this field
Expand Down Expand Up @@ -157,7 +157,7 @@ end

# find the first dominating def for the given use
function find_def_for_use(
ir::IRCode, domtree::DomTree, allblocks::Vector{Int}, du::SSADefUse, use::Int, inclusive::Bool=false)
ir::IRCode, domtree::DomTree, allblocks::BitSet, du::SSADefUse, use::Int, inclusive::Bool=false)
useblock = block_for_inst(ir.cfg, use)
curblock = find_curblock(domtree, allblocks, useblock)
local def = 0
Expand Down Expand Up @@ -1306,7 +1306,7 @@ function sroa_mutables!(ir::IRCode, defuses::IdDict{Int, Tuple{SPCSet, SSADefUse
# but we should come up with semantics for well defined semantics
# for uninitialized fields first.
ndefuse = length(fielddefuse)
blocks = Vector{Tuple{#=phiblocks=# Vector{Int}, #=allblocks=# Vector{Int}}}(undef, ndefuse)
blocks = Vector{Tuple{#=phiblocks=# Vector{Int}, #=allblocks=# BitSet}}(undef, ndefuse)
for fidx in 1:ndefuse
du = fielddefuse[fidx]
isempty(du.uses) && continue
Expand All @@ -1317,7 +1317,7 @@ function sroa_mutables!(ir::IRCode, defuses::IdDict{Int, Tuple{SPCSet, SSADefUse
else
phiblocks = iterated_dominance_frontier(ir.cfg, ldu, get!(lazydomtree))
end
allblocks = sort!(vcat(phiblocks, ldu.def_bbs); alg=QuickSort)
allblocks = union!(BitSet(phiblocks), ldu.def_bbs)
blocks[fidx] = phiblocks, allblocks
if fidx + 1 > length(defexpr.args)
for i = 1:length(du.uses)
Expand Down
2 changes: 1 addition & 1 deletion base/cpuid.jl
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ let
arch = normalize_arch(String(Sys.ARCH))
if arch in keys(ISAs_by_family)
for isa in ISAs_by_family[arch]
unique!(append!(FEATURES, last(isa).features))
Base._unique!(append!(FEATURES, last(isa).features))
end
end

Expand Down
13 changes: 0 additions & 13 deletions base/range.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1375,19 +1375,6 @@ function _reverse(r::StepRangeLen, ::Colon)
end
_reverse(r::LinRange{T}, ::Colon) where {T} = typeof(r)(r.stop, r.start, length(r))

## sorting ##

issorted(r::AbstractUnitRange) = true
issorted(r::AbstractRange) = length(r) <= 1 || step(r) >= zero(step(r))

sort(r::AbstractUnitRange) = r
sort!(r::AbstractUnitRange) = r

sort(r::AbstractRange) = issorted(r) ? r : reverse(r)

sortperm(r::AbstractUnitRange) = 1:length(r)
sortperm(r::AbstractRange) = issorted(r) ? (1:1:length(r)) : (length(r):-1:1)

function sum(r::AbstractRange{<:Real})
l = length(r)
# note that a little care is required to avoid overflow in l*(l-1)/2
Expand Down
4 changes: 3 additions & 1 deletion base/reflection.jl
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,9 @@ since it is not idiomatic to explicitly export names from `Main`.
See also: [`@locals`](@ref Base.@locals), [`@__MODULE__`](@ref).
"""
names(m::Module; all::Bool = false, imported::Bool = false) =
sort!(ccall(:jl_module_names, Array{Symbol,1}, (Any, Cint, Cint), m, all, imported))
sort!(unsorted_names(m; all, imported))
unsorted_names(m::Module; all::Bool = false, imported::Bool = false) =
ccall(:jl_module_names, Array{Symbol,1}, (Any, Cint, Cint), m, all, imported)

isexported(m::Module, s::Symbol) = ccall(:jl_module_exports_p, Cint, (Any, Any), m, s) != 0
isdeprecated(m::Module, s::Symbol) = ccall(:jl_is_binding_deprecated, Cint, (Any, Any), m, s) != 0
Expand Down
5 changes: 3 additions & 2 deletions base/sysimg.jl
Original file line number Diff line number Diff line change
Expand Up @@ -49,14 +49,15 @@ let
:Distributed,
:Future,
:InteractiveUtils,
:LibGit2,
:Profile,
:SparseArrays,
:Sort,
:UUIDs,

# 3-depth packages
:LibGit2,
:REPL,
:SharedArrays,
:SparseArrays,
:TOML,
:Test,

Expand Down
7 changes: 3 additions & 4 deletions base/util.jl
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,9 @@ const disable_text_style = Dict{Symbol,String}(
# of colors.
let color_syms = collect(Iterators.filter(x -> !isa(x, Integer), keys(text_colors))),
formatting_syms = [:normal, :bold, :default]
global const available_text_colors = cat(
sort!(intersect(color_syms, formatting_syms), rev=true),
sort!(setdiff( color_syms, formatting_syms));
dims=1)
global const available_text_colors = vcat(
Core.Compiler.sort!(intersect(color_syms, formatting_syms); < = >), #reverse
Core.Compiler.sort!( setdiff(color_syms, formatting_syms); <))
end

const available_text_colors_docstring =
Expand Down
4 changes: 2 additions & 2 deletions contrib/print_sorted_stdlibs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ end

project_deps = Dict{String,Set{String}}()
for project_dir in readdir(STDLIB_DIR, join=true)
files = readdir(project_dir)
if "Project.toml" in files
project_file = joinpath(project_dir, "Project.toml")
if isfile(project_file)
project = TOML.parsefile(joinpath(project_dir, "Project.toml"))

if !haskey(project, "name")
Expand Down
1 change: 0 additions & 1 deletion doc/make.jl
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,6 @@ BaseDocs = [
"base/file.md",
"base/io-network.md",
"base/punctuation.md",
"base/sort.md",
"base/iterators.md",
"base/c.md",
"base/libc.md",
Expand Down
Loading