From 11c1d1d477635042cb41fb13125acc8301ca887d Mon Sep 17 00:00:00 2001 From: Klaus Crusius Date: Tue, 7 Aug 2018 17:27:59 +0200 Subject: [PATCH 01/26] added sparse multiplication and division for triangular matrices. Fix #28451 --- stdlib/SparseArrays/src/linalg.jl | 351 +++++++++++++++++++++++------ stdlib/SparseArrays/test/sparse.jl | 37 ++- 2 files changed, 316 insertions(+), 72 deletions(-) diff --git a/stdlib/SparseArrays/src/linalg.jl b/stdlib/SparseArrays/src/linalg.jl index 6e9a751dd4306..4e6c3fb3a9b85 100644 --- a/stdlib/SparseArrays/src/linalg.jl +++ b/stdlib/SparseArrays/src/linalg.jl @@ -234,16 +234,226 @@ function dot(A::SparseMatrixCSC{T1,S1},B::SparseMatrixCSC{T2,S2}) where {T1,T2,S return r end -## solvers -function fwdTriSolve!(A::SparseMatrixCSCUnion, B::AbstractVecOrMat) -# forward substitution for CSC matrices +## triangular sparse handling +abstract type UnitDiagonal end +struct UnitDiagonalYes <:UnitDiagonal end +struct UnitDiagonalNo <:UnitDiagonal end +abstract type AdjointElement end +struct AdjointElementYes <:AdjointElement end +struct AdjointElementNo <:AdjointElement end + +possible_adjoint(adj::AdjointElementYes, a ) = adjoint(a) +possible_adjoint(adj::AdjointElementNo, a ) = a +AdjointElement(::Adjoint) = AdjointElementYes() +AdjointElement(::Any) = AdjointElementNo() +UnitDiagonal(::UnitUpperTriangular) = UnitDiagonalYes() +UnitDiagonal(::UnitLowerTriangular) = UnitDiagonalYes() +UnitDiagonal(::Any) = UnitDiagonalNo() + +const LowerTriangularPlain{T} = Union{ + LowerTriangular{T,<:SparseMatrixCSCUnion{T}}, + UnitLowerTriangular{T,<:SparseMatrixCSCUnion{T}}} + +const LowerTriangularWrapped{T} = Union{ + Adjoint{T,<:UpperTriangular{T,<:SparseMatrixCSCUnion{T}}}, + Adjoint{T,<:UnitUpperTriangular{T,<:SparseMatrixCSCUnion{T}}}, + Transpose{T,<:UpperTriangular{T,<:SparseMatrixCSCUnion{T}}}, + Transpose{T,<:UnitUpperTriangular{T,<:SparseMatrixCSCUnion{T}}}} where T + +const UpperTriangularPlain{T} = Union{ + UpperTriangular{T,<:SparseMatrixCSCUnion{T}}, + UnitUpperTriangular{T,<:SparseMatrixCSCUnion{T}}} + +const UpperTriangularWrapped{T} = Union{ + Adjoint{T,<:LowerTriangular{T,<:SparseMatrixCSCUnion{T}}}, + Adjoint{T,<:UnitLowerTriangular{T,<:SparseMatrixCSCUnion{T}}}, + Transpose{T,<:LowerTriangular{T,<:SparseMatrixCSCUnion{T}}}, + Transpose{T,<:UnitLowerTriangular{T,<:SparseMatrixCSCUnion{T}}}} where T + +const UpperTriangularSparse{T} = Union{ + UpperTriangularWrapped{T}, UpperTriangularPlain{T}} where T + +const LowerTriangularSparse{T} = Union{ + LowerTriangularWrapped{T}, LowerTriangularPlain{T}} where T + +const TriangularSparse{T} = Union{ + LowerTriangularSparse{T}, UpperTriangularSparse{T}} where T + +## triangular multipliers +function fwdTriMul!(A::SparseMatrixCSCUnion, B::AbstractVecOrMat, unit::UnitDiagonal) +# forward substitution for UpperTriangular SparseCSC matrices + nrowB, ncolB = size(B, 1), size(B, 2) + aa = getnzval(A) + ja = getrowval(A) + ia = getcolptr(A) + + joff = 0 + for k = 1:ncolB + for j = 1:nrowB + i1 = ia[j] + i2 = ia[j + 1] - 1 + done = unit isa UnitDiagonalYes + + bj = B[joff + j] + for ii = i1:i2 + jai = ja[ii] + aii = aa[ii] + if jai < j + B[joff + jai] += aii * bj + elseif jai == j + if unit isa UnitDiagonalNo + B[joff + j] *= aii + done = true + end + else + break + end + end + if !done + B[joff + j] -= B[joff + j] + end + end + joff += nrowB + end + B +end + +function bwdTriMul!(A::SparseMatrixCSCUnion, B::AbstractVecOrMat, unit::UnitDiagonal) +# backward substitution for LowerTriangular SparseCSC matrices + nrowB, ncolB = size(B, 1), size(B, 2) + aa = getnzval(A) + ja = getrowval(A) + ia = getcolptr(A) + + joff = 0 + for k = 1:ncolB + for j = nrowB:-1:1 + i1 = ia[j] + i2 = ia[j + 1] - 1 + done = unit isa UnitDiagonalYes + + bj = B[joff + j] + for ii = i2:-1:i1 + jai = ja[ii] + aii = aa[ii] + if jai > j + B[joff + jai] += aii * bj + elseif jai == j + if unit isa UnitDiagonalNo + B[joff + j] *= aii + done = true + end + else + break + end + end + if !done + B[joff + j] -= B[joff + j] + end + end + joff += nrowB + end + B +end + +function _fwdTriMul!(A::SparseMatrixCSCUnion, B::AbstractVecOrMat, unit::UnitDiagonal, adj::AdjointElement) +# forward substitution for adjoint and transpose of LowerTriangular CSC matrices + nrowB, ncolB = size(B, 1), size(B, 2) + aa = getnzval(A) + ja = getrowval(A) + ia = getcolptr(A) + Z = zero(eltype(A)) + + joff = 0 + for k = 1:ncolB + for j = 1:nrowB + i1 = ia[j] + i2 = ia[j + 1] - 1 + akku = Z + j0 = unit isa UnitDiagonalNo ? j : j + 1 + + # loop through column j of A - only structural non-zeros + for ii = i2:-1:i1 + jai = ja[ii] + if jai >= j0 + aai = possible_adjoint(adj, aa[ii]) + akku += B[joff + jai] * aai + else + break + end + end + if unit isa UnitDiagonalYes + akku += B[joff + j] + end + B[joff + j] = akku + end + joff += nrowB + end + B +end + +function _bwdTriMul!(A::SparseMatrixCSCUnion, B::AbstractVecOrMat, unit::UnitDiagonal, adj::AdjointElement) +# multiply with adjoint and transpose of LowerTriangular CSC matrices + nrowB, ncolB = size(B, 1), size(B, 2) + aa = getnzval(A) + ja = getrowval(A) + ia = getcolptr(A) + Z = zero(eltype(A)) + + joff = 0 + for k = 1:ncolB + for j = nrowB:-1:1 + i1 = ia[j] + i2 = ia[j + 1] - 1 + akku = Z + j0 = unit isa UnitDiagonalNo ? j : j - 1 + + # loop through column j of A - only structural non-zeros + for ii = i1:i2 + jai = ja[ii] + if jai <= j0 + aai = possible_adjoint(adj, aa[ii]) + akku += B[joff + jai] * aai + else + break + end + end + if unit isa UnitDiagonalYes + akku += B[joff + j] + end + B[joff + j] = akku + end + joff += nrowB + end + B +end + +function lmul!(A::TriangularSparse{T}, B::StridedVecOrMat{T}) where T @assert !has_offset_axes(A, B) nrowB, ncolB = size(B, 1), size(B, 2) ncol = LinearAlgebra.checksquare(A) if nrowB != ncol throw(DimensionMismatch("A is $(ncol) columns and B has $(nrowB) rows")) end + _lmul!(A, B) +end + +_lmul!(L::LowerTriangularPlain, B::StridedVecOrMat) = + bwdTriMul!(L.data, B, UnitDiagonal(L)) +_lmul!(L::LowerTriangularWrapped, B::StridedVecOrMat) = + _bwdTriMul!(L.parent.data, B, UnitDiagonal(L.parent), AdjointElement(L)) + +_lmul!(U::UpperTriangularPlain, B::StridedVecOrMat) = + fwdTriMul!(U.data, B, UnitDiagonal(U)) + +_lmul!(U::UpperTriangularWrapped, B::StridedVecOrMat) = + _fwdTriMul!(U.parent.data, B, UnitDiagonal(U.parent), AdjointElement(U)) + +## triangular solvers +function fwdTriSolve!(A::SparseMatrixCSCUnion, B::AbstractVecOrMat, unit::UnitDiagonal) +# forward substitution for LowerTriangular CSC matrices + nrowB, ncolB = size(B, 1), size(B, 2) aa = getnzval(A) ja = getrowval(A) ia = getcolptr(A) @@ -262,18 +472,21 @@ function fwdTriSolve!(A::SparseMatrixCSCUnion, B::AbstractVecOrMat) jai = ja[ii] end + bj = B[joff + j] # check for zero pivot and divide with pivot if jai == j - bj = B[joff + jai]/aa[ii] - B[joff + jai] = bj + if unit isa UnitDiagonalNo + bj /= aa[ii] + B[joff + j] = bj + end ii += 1 - else + elseif unit isa UnitDiagonalNo throw(LinearAlgebra.SingularException(j)) end # update remaining part for i = ii:i2 - B[joff + ja[i]] -= bj*aa[i] + B[joff + ja[i]] -= bj * aa[i] end end joff += nrowB @@ -281,15 +494,9 @@ function fwdTriSolve!(A::SparseMatrixCSCUnion, B::AbstractVecOrMat) B end -function bwdTriSolve!(A::SparseMatrixCSCUnion, B::AbstractVecOrMat) -# backward substitution for CSC matrices - @assert !has_offset_axes(A, B) +function bwdTriSolve!(A::SparseMatrixCSCUnion, B::AbstractVecOrMat, unit::UnitDiagonal) +# backward substitution for UpperTriangular CSC matrices nrowB, ncolB = size(B, 1), size(B, 2) - ncol = LinearAlgebra.checksquare(A) - if nrowB != ncol - throw(DimensionMismatch("A is $(ncol) columns and B has $(nrowB) rows")) - end - aa = getnzval(A) ja = getrowval(A) ia = getcolptr(A) @@ -308,18 +515,21 @@ function bwdTriSolve!(A::SparseMatrixCSCUnion, B::AbstractVecOrMat) jai = ja[ii] end + bj = B[joff + j] # check for zero pivot and divide with pivot if jai == j - bj = B[joff + jai]/aa[ii] - B[joff + jai] = bj + if unit isa UnitDiagonalNo + bj /= aa[ii] + B[joff + j] = bj + end ii -= 1 - else + elseif unit isa UnitDiagonalNo throw(LinearAlgebra.SingularException(j)) end # update remaining part for i = ii:-1:i1 - B[joff + ja[i]] -= bj*aa[i] + B[joff + ja[i]] -= bj * aa[i] end end joff += nrowB @@ -327,21 +537,9 @@ function bwdTriSolve!(A::SparseMatrixCSCUnion, B::AbstractVecOrMat) B end -fwdTriSolve!(aA::Adjoint{<:Any,<:SparseMatrixCSCUnion}, B::AbstractVecOrMat) = - _fwdTriSolve!(aA.parent, B, true) - -fwdTriSolve!(aA::Transpose{<:Any,<:SparseMatrixCSCUnion}, B::AbstractVecOrMat) = - _fwdTriSolve!(aA.parent, B, false) - -function _fwdTriSolve!(A::SparseMatrixCSCUnion, B::AbstractVecOrMat, adj::Bool) -# forward substitution for adjoints of CSC matrices - @assert !has_offset_axes(A, B) +function _fwdTriSolve!(A::SparseMatrixCSCUnion, B::AbstractVecOrMat, unit::UnitDiagonal, adj::AdjointElement) +# forward substitution for adjoint and transpose of UpperTriangular CSC matrices nrowB, ncolB = size(B, 1), size(B, 2) - ncol = LinearAlgebra.checksquare(A) - if nrowB != ncol - throw(DimensionMismatch("A is $(ncol) columns and B has $(nrowB) rows")) - end - aa = getnzval(A) ja = getrowval(A) ia = getcolptr(A) @@ -357,39 +555,33 @@ function _fwdTriSolve!(A::SparseMatrixCSCUnion, B::AbstractVecOrMat, adj::Bool) # loop through column j of A - only structural non-zeros for ip = i1:i2 i = ja[ip] - aai = adj ? aa[ip]' : aa[ip] if i < j + aai = possible_adjoint(adj, aa[ip]) akku -= B[joff + i] * aai elseif i == j - B[joff + j] = akku / aai + if unit isa UnitDiagonalNo + aai = possible_adjoint(adj, aa[ip]) + akku /= aai + end done = true break + else + break end end - if !done + if !done && unit isa UnitDiagonalNo throw(LinearAlgebra.SingularException(j)) end + B[joff + j] = akku end joff += nrowB end B end -bwdTriSolve!(aA::Adjoint{<:Any,<:SparseMatrixCSCUnion}, B::AbstractVecOrMat) = - _bwdTriSolve!(aA.parent, B, true) - -bwdTriSolve!(aA::Transpose{<:Any,<:SparseMatrixCSCUnion}, B::AbstractVecOrMat) = - _bwdTriSolve!(aA.parent, B, false) - -function _bwdTriSolve!(A::SparseMatrixCSCUnion, B::AbstractVecOrMat, adj::Bool) -# forward substitution for adjoints of CSC matrices - @assert !has_offset_axes(A, B) - nrowB, ncolB = size(B, 1), size(B, 2) - ncol = LinearAlgebra.checksquare(A) - if nrowB != ncol - throw(DimensionMismatch("A is $(ncol) columns and B has $(nrowB) rows")) - end - +function _bwdTriSolve!(A::SparseMatrixCSCUnion, B::AbstractVecOrMat, unit::UnitDiagonal, adj::AdjointElement) +# backward substitution for adjoint and transpose of LowerTriangular CSC matrices + nrowB, ncolB = size(B, 1), size(B, 2) aa = getnzval(A) ja = getrowval(A) ia = getcolptr(A) @@ -405,41 +597,56 @@ function _bwdTriSolve!(A::SparseMatrixCSCUnion, B::AbstractVecOrMat, adj::Bool) # loop through column j of A - only structural non-zeros for ip = i2:-1:i1 i = ja[ip] - aai = adj ? aa[ip]' : aa[ip] if i > j + aai = possible_adjoint(adj, aa[ip]) akku -= B[joff + i] * aai elseif i == j - B[joff + j] = akku / aai + if unit isa UnitDiagonalNo + aai = possible_adjoint(adj, aa[ip]) + akku /= aai + end done = true break + else + break end end - if !done + if !done && unit isa UnitDiagonalNo throw(LinearAlgebra.SingularException(j)) end + B[joff + j] = akku end joff += nrowB end B end -ldiv!(L::LowerTriangular{T,<:SparseMatrixCSCUnion{T}}, B::StridedVecOrMat) where {T} = fwdTriSolve!(L.data, B) -ldiv!(L::Adjoint{T,<:UpperTriangular{T,<:SparseMatrixCSCUnion{T}}}, B::StridedVecOrMat) where {T} = _fwdTriSolve!(L.parent.data, B, true) -ldiv!(L::Transpose{T,<:UpperTriangular{T,<:SparseMatrixCSCUnion{T}}}, B::StridedVecOrMat) where {T} = _fwdTriSolve!(L.parent.data, B, false) +function ldiv!(A::TriangularSparse{T}, B::StridedVecOrMat{T}) where T + @assert !has_offset_axes(A, B) + nrowB, ncolB = size(B, 1), size(B, 2) + ncol = LinearAlgebra.checksquare(A) + if nrowB != ncol + throw(DimensionMismatch("A is $(ncol) columns and B has $(nrowB) rows")) + end + _ldiv!(A, B) +end + +_ldiv!(L::LowerTriangularPlain, B::StridedVecOrMat) = + fwdTriSolve!(L.data, B, UnitDiagonal(L)) -ldiv!(U::UpperTriangular{T,<:SparseMatrixCSCUnion{T}}, B::StridedVecOrMat) where {T} = bwdTriSolve!(U.data, B) -ldiv!(L::Adjoint{T,<:LowerTriangular{T,<:SparseMatrixCSCUnion{T}}}, B::StridedVecOrMat) where {T} = _bwdTriSolve!(L.parent.data, B, true) -ldiv!(L::Transpose{T,<:LowerTriangular{T,<:SparseMatrixCSCUnion{T}}}, B::StridedVecOrMat) where {T} = _bwdTriSolve!(L.parent.data, B, false) +_ldiv!(L::LowerTriangularWrapped, B::StridedVecOrMat) = + _fwdTriSolve!(L.parent.data, B, UnitDiagonal(L.parent), AdjointElement(L)) -(\)(L::Union{LowerTriangular{T,<:SparseMatrixCSCUnion{T}}, - Adjoint{T,<:UpperTriangular{T,<:SparseMatrixCSCUnion{T}}}, - Transpose{T,<:UpperTriangular{T,<:SparseMatrixCSCUnion{T}}}}, - B::SparseMatrixCSC) where {T} = ldiv!(L, Array(B)) +_ldiv!(U::UpperTriangularPlain, B::StridedVecOrMat) = + bwdTriSolve!(U.data, B, UnitDiagonal(U)) -(\)(U::Union{UpperTriangular{T,<:SparseMatrixCSCUnion{T}}, - Adjoint{T,<:LowerTriangular{T,<:SparseMatrixCSCUnion{T}}}, - Transpose{T,<:LowerTriangular{T,<:SparseMatrixCSCUnion{T}}}}, - B::SparseMatrixCSC) where {T} = ldiv!(U, Array(B)) +_ldiv!(U::UpperTriangularWrapped, B::StridedVecOrMat) = + _bwdTriSolve!(U.parent.data, B, UnitDiagonal(U.parent), AdjointElement(U)) + +(\)(L::TriangularSparse, B::SparseMatrixCSC) = ldiv!(L, Array(B)) +(*)(L::TriangularSparse, B::SparseMatrixCSC) = lmul!(L, Array(B)) + +## end of triangular \(A::Transpose{<:Real,<:Hermitian{<:Real,<:SparseMatrixCSC}}, B::Vector) = A.parent \ B \(A::Transpose{<:Complex,<:Hermitian{<:Complex,<:SparseMatrixCSC}}, B::Vector) = copy(A) \ B @@ -472,6 +679,10 @@ rdiv!(A::SparseMatrixCSC{T}, transD::Transpose{<:Any,<:Diagonal{T}}) where {T} = function triu(S::SparseMatrixCSC{Tv,Ti}, k::Integer=0) where {Tv,Ti} m,n = size(S) + if !(-m + 1 <= k <= n + 1) + throw(ArgumentError(string("the requested diagonal, $k, must be at least ", + "$(-m + 1) and at most $(n + 1) in an $m-by-$n matrix"))) + end colptr = Vector{Ti}(undef, n+1) nnz = 0 for col = 1 : min(max(k+1,1), n+1) @@ -500,6 +711,10 @@ end function tril(S::SparseMatrixCSC{Tv,Ti}, k::Integer=0) where {Tv,Ti} m,n = size(S) + if !(-m - 1 <= k <= n - 1) + throw(ArgumentError(string("the requested diagonal, $k, must be at least ", + "$(-m - 1) and at most $(n - 1) in an $m-by-$n matrix"))) + end colptr = Vector{Ti}(undef, n+1) nnz = 0 colptr[1] = 1 diff --git a/stdlib/SparseArrays/test/sparse.jl b/stdlib/SparseArrays/test/sparse.jl index f88c6dde06493..78ede06a1b8ce 100644 --- a/stdlib/SparseArrays/test/sparse.jl +++ b/stdlib/SparseArrays/test/sparse.jl @@ -1553,10 +1553,14 @@ end @test Array(tril(A,1)) == tril(AF,1) @test Array(triu!(copy(A), 2)) == triu(AF,2) @test Array(tril!(copy(A), 2)) == tril(AF,2) - @test tril(A, -n - 2) == zero(A) - @test tril(A, n) == A - @test triu(A, -n) == A - @test triu(A, n + 2) == zero(A) + @test_throws ArgumentError tril(A, -n - 2) + @test_throws ArgumentError tril(A, n) + @test_throws ArgumentError triu(A, -n) + @test_throws ArgumentError triu(A, n + 2) + @test_throws ArgumentError tril!(sparse([1,2,3], [1,2,3], [1,2,3], 3, 4), -5) + @test_throws ArgumentError tril!(sparse([1,2,3], [1,2,3], [1,2,3], 3, 4), 4) + @test_throws ArgumentError triu!(sparse([1,2,3], [1,2,3], [1,2,3], 3, 4), -3) + @test_throws ArgumentError triu!(sparse([1,2,3], [1,2,3], [1,2,3], 3, 4), 6) # fkeep trim option @test isequal(length(tril!(sparse([1,2,3], [1,2,3], [1,2,3], 3, 4), -1).rowval), 0) @@ -2289,4 +2293,29 @@ end @test adjoint(MC) == copy(adjoint(SC)) end +@testset "Triangular matrices" begin + rng = Random.MersenneTwister(0) + n = 1000 + A = sprand(rng, n, n, 0.01) + B = ones(n) + MA = Matrix(A) + for tr in (identity, adjoint, transpose) + for wr in (UpperTriangular, LowerTriangular, UnitUpperTriangular, UnitLowerTriangular) + AW = tr(wr(A)) + MAW = tr(wr(MA)) + @test AW * B ≈ MAW * B + end + end + A = A - Diagonal(diag(A)) + A += 2I + MA = Matrix(A) + for tr in (identity, adjoint, transpose) + for wr in (UpperTriangular, LowerTriangular, UnitUpperTriangular, UnitLowerTriangular) + AW = tr(wr(A)) + MAW = tr(wr(MA)) + @test AW \ B ≈ MAW \ B + end + end +end + end # module From da262ec3fea2f87db104ef1b9eec0918d771062f Mon Sep 17 00:00:00 2001 From: Klaus Crusius Date: Tue, 7 Aug 2018 18:11:07 +0200 Subject: [PATCH 02/26] merge with master --- stdlib/SparseArrays/src/linalg.jl | 8 -------- stdlib/SparseArrays/test/sparse.jl | 12 ++++-------- 2 files changed, 4 insertions(+), 16 deletions(-) diff --git a/stdlib/SparseArrays/src/linalg.jl b/stdlib/SparseArrays/src/linalg.jl index 4e6c3fb3a9b85..d2541fae0ccf5 100644 --- a/stdlib/SparseArrays/src/linalg.jl +++ b/stdlib/SparseArrays/src/linalg.jl @@ -679,10 +679,6 @@ rdiv!(A::SparseMatrixCSC{T}, transD::Transpose{<:Any,<:Diagonal{T}}) where {T} = function triu(S::SparseMatrixCSC{Tv,Ti}, k::Integer=0) where {Tv,Ti} m,n = size(S) - if !(-m + 1 <= k <= n + 1) - throw(ArgumentError(string("the requested diagonal, $k, must be at least ", - "$(-m + 1) and at most $(n + 1) in an $m-by-$n matrix"))) - end colptr = Vector{Ti}(undef, n+1) nnz = 0 for col = 1 : min(max(k+1,1), n+1) @@ -711,10 +707,6 @@ end function tril(S::SparseMatrixCSC{Tv,Ti}, k::Integer=0) where {Tv,Ti} m,n = size(S) - if !(-m - 1 <= k <= n - 1) - throw(ArgumentError(string("the requested diagonal, $k, must be at least ", - "$(-m - 1) and at most $(n - 1) in an $m-by-$n matrix"))) - end colptr = Vector{Ti}(undef, n+1) nnz = 0 colptr[1] = 1 diff --git a/stdlib/SparseArrays/test/sparse.jl b/stdlib/SparseArrays/test/sparse.jl index 78ede06a1b8ce..64c3f985f20bb 100644 --- a/stdlib/SparseArrays/test/sparse.jl +++ b/stdlib/SparseArrays/test/sparse.jl @@ -1553,14 +1553,10 @@ end @test Array(tril(A,1)) == tril(AF,1) @test Array(triu!(copy(A), 2)) == triu(AF,2) @test Array(tril!(copy(A), 2)) == tril(AF,2) - @test_throws ArgumentError tril(A, -n - 2) - @test_throws ArgumentError tril(A, n) - @test_throws ArgumentError triu(A, -n) - @test_throws ArgumentError triu(A, n + 2) - @test_throws ArgumentError tril!(sparse([1,2,3], [1,2,3], [1,2,3], 3, 4), -5) - @test_throws ArgumentError tril!(sparse([1,2,3], [1,2,3], [1,2,3], 3, 4), 4) - @test_throws ArgumentError triu!(sparse([1,2,3], [1,2,3], [1,2,3], 3, 4), -3) - @test_throws ArgumentError triu!(sparse([1,2,3], [1,2,3], [1,2,3], 3, 4), 6) + @test ArgumentError tril(A, -n - 2) == zero(A) + @test ArgumentError tril(A, n) == A + @test ArgumentError triu(A, -n) == A + @test ArgumentError triu(A, n + 2) == zero(A) # fkeep trim option @test isequal(length(tril!(sparse([1,2,3], [1,2,3], [1,2,3], 3, 4), -1).rowval), 0) From b0b36886d7723de18e9c4f35bf67e5f0a34b3551 Mon Sep 17 00:00:00 2001 From: Klaus Crusius Date: Tue, 7 Aug 2018 18:22:12 +0200 Subject: [PATCH 03/26] merge with master 2 --- stdlib/SparseArrays/test/sparse.jl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/stdlib/SparseArrays/test/sparse.jl b/stdlib/SparseArrays/test/sparse.jl index 64c3f985f20bb..ac91d66614fa5 100644 --- a/stdlib/SparseArrays/test/sparse.jl +++ b/stdlib/SparseArrays/test/sparse.jl @@ -1553,10 +1553,10 @@ end @test Array(tril(A,1)) == tril(AF,1) @test Array(triu!(copy(A), 2)) == triu(AF,2) @test Array(tril!(copy(A), 2)) == tril(AF,2) - @test ArgumentError tril(A, -n - 2) == zero(A) - @test ArgumentError tril(A, n) == A - @test ArgumentError triu(A, -n) == A - @test ArgumentError triu(A, n + 2) == zero(A) + @test tril(A, -n - 2) == zero(A) + @test tril(A, n) == A + @test triu(A, -n) == A + @test triu(A, n + 2) == zero(A) # fkeep trim option @test isequal(length(tril!(sparse([1,2,3], [1,2,3], [1,2,3], 3, 4), -1).rowval), 0) From 7c8da66e9edbde3e6813cc5f202840083ad37bb9 Mon Sep 17 00:00:00 2001 From: Marco Cognetta Date: Wed, 8 Aug 2018 19:41:48 +0900 Subject: [PATCH 04/26] fixed symtridiagonal + bidiagonal --- stdlib/LinearAlgebra/src/special.jl | 21 ++++++++++++++------- stdlib/LinearAlgebra/test/special.jl | 22 ++++++++++++++++++++++ 2 files changed, 36 insertions(+), 7 deletions(-) diff --git a/stdlib/LinearAlgebra/src/special.jl b/stdlib/LinearAlgebra/src/special.jl index 7bb4349cf2b9a..3e831e8eeec3e 100644 --- a/stdlib/LinearAlgebra/src/special.jl +++ b/stdlib/LinearAlgebra/src/special.jl @@ -99,13 +99,19 @@ for op in (:+, :-) end end - for matrixtype1 in (:Diagonal, :Bidiagonal) # matrixtype1 is the sparser matrix type - for matrixtype2 in (:SymTridiagonal,) # matrixtype2 is the denser matrix type - @eval begin - ($op)(A::($matrixtype1), B::($matrixtype2)) = ($op)(convert(($matrixtype2), A), B) - ($op)(A::($matrixtype2), B::($matrixtype1)) = ($op)(A, convert(($matrixtype2), B)) - end - end + # todo check if these conversion methods are optimal + # we should be able to do these structured conversions really quickly + + # Diagonal +/- SymTridiagonal (and reverse) will always be SymTridiagonal + @eval begin + ($op)(A::SymTridiagonal, B::Diagonal) = ($op)(A, convert(SymTridiagonal, B)) + ($op)(A::Diagonal, B::SymTridiagonal) = ($op)(convert(SymTridiagonal, A), B) + end + + # Bidiagonal +/- SymTridiagonal (and reverse) will always be Tridiagonal + @eval begin + ($op)(A::SymTridiagonal, B::Bidiagonal) = ($op)(convert(Tridiagonal, A), B) + ($op)(A::Bidiagonal, B::SymTridiagonal) = ($op)(A, convert(Tridiagonal, B)) end for matrixtype1 in (:Diagonal,) @@ -119,6 +125,7 @@ for op in (:+, :-) end end end + for matrixtype in (:SymTridiagonal,:Tridiagonal,:Bidiagonal,:Matrix) @eval begin ($op)(A::AbstractTriangular, B::($matrixtype)) = ($op)(copyto!(similar(parent(A)), A), B) diff --git a/stdlib/LinearAlgebra/test/special.jl b/stdlib/LinearAlgebra/test/special.jl index e63929d9497f1..cfbac21b5141a 100644 --- a/stdlib/LinearAlgebra/test/special.jl +++ b/stdlib/LinearAlgebra/test/special.jl @@ -109,6 +109,28 @@ end @test Matrix(convert(Spectype,A) - D) ≈ Matrix(A - D) end end + + for uplo in ('U', 'L') + E = Bidiagonal(a, fill(1., n-1), uplo) + @test E + B ≈ Matrix(E) + Matrix(B) + @test B + E ≈ Matrix(B) + Matrix(E) + @test E - B ≈ Matrix(E) - Matrix(B) + @test B - E ≈ Matrix(B) - Matrix(E) + end +end + +# more need to be added here but for now only a few operation/type combinations output the optimal type +@testset "output type of binary ops on triangular/diagonal matrices" begin + a=[1.0:n;] + sym = SymTridiagonal(a, fill(1., n-1)) + + for uplo in ('U', 'L') + bi = Bidiagonal(a, fill(1., n-1), uplo) + @test typeof(sym+bi) == LinearAlgebra.Tridiagonal{Float64,Array{Float64,1}} + @test typeof(bi+sym) == LinearAlgebra.Tridiagonal{Float64,Array{Float64,1}} + @test typeof(sym-bi) == LinearAlgebra.Tridiagonal{Float64,Array{Float64,1}} + @test typeof(bi-sym) == LinearAlgebra.Tridiagonal{Float64,Array{Float64,1}} + end end @testset "Triangular Types and QR" begin From 70c8b73b7c7b3bf313a4e932dbf93bff79773b18 Mon Sep 17 00:00:00 2001 From: Klaus Crusius Date: Wed, 8 Aug 2018 16:53:43 +0200 Subject: [PATCH 05/26] improved find diagonal part --- stdlib/SparseArrays/src/linalg.jl | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/stdlib/SparseArrays/src/linalg.jl b/stdlib/SparseArrays/src/linalg.jl index d2541fae0ccf5..b470a8d92789c 100644 --- a/stdlib/SparseArrays/src/linalg.jl +++ b/stdlib/SparseArrays/src/linalg.jl @@ -464,13 +464,10 @@ function fwdTriSolve!(A::SparseMatrixCSCUnion, B::AbstractVecOrMat, unit::UnitDi i1 = ia[j] i2 = ia[j + 1] - 1 - # loop through the structural zeros - ii = i1 + # find diagonal element + ii = searchsortedfirst(ja, j, i1, i2, Base.Order.Forward) + ii > i2 && ( ii = i1) jai = ja[ii] - while ii <= i2 && jai < j - ii += 1 - jai = ja[ii] - end bj = B[joff + j] # check for zero pivot and divide with pivot @@ -507,13 +504,10 @@ function bwdTriSolve!(A::SparseMatrixCSCUnion, B::AbstractVecOrMat, unit::UnitDi i1 = ia[j] i2 = ia[j + 1] - 1 - # loop through the structural zeros - ii = i2 + # find diagonal element + ii = searchsortedlast(ja, j, i1, i2, Base.Order.Forward) + ii < i1 && ( ii = i2) jai = ja[ii] - while ii >= i1 && jai > j - ii -= 1 - jai = ja[ii] - end bj = B[joff + j] # check for zero pivot and divide with pivot From 4307da6d1f77e6bf076fdd310dc77f8e267f3894 Mon Sep 17 00:00:00 2001 From: Klaus Crusius Date: Wed, 8 Aug 2018 17:43:59 +0200 Subject: [PATCH 06/26] refactored to purge name space of SparseArrays --- stdlib/SparseArrays/src/linalg.jl | 181 +++++++++++++++--------------- 1 file changed, 88 insertions(+), 93 deletions(-) diff --git a/stdlib/SparseArrays/src/linalg.jl b/stdlib/SparseArrays/src/linalg.jl index b470a8d92789c..86ab4b78f50f0 100644 --- a/stdlib/SparseArrays/src/linalg.jl +++ b/stdlib/SparseArrays/src/linalg.jl @@ -235,20 +235,11 @@ function dot(A::SparseMatrixCSC{T1,S1},B::SparseMatrixCSC{T2,S2}) where {T1,T2,S end ## triangular sparse handling -abstract type UnitDiagonal end -struct UnitDiagonalYes <:UnitDiagonal end -struct UnitDiagonalNo <:UnitDiagonal end -abstract type AdjointElement end -struct AdjointElementYes <:AdjointElement end -struct AdjointElementNo <:AdjointElement end - -possible_adjoint(adj::AdjointElementYes, a ) = adjoint(a) -possible_adjoint(adj::AdjointElementNo, a ) = a -AdjointElement(::Adjoint) = AdjointElementYes() -AdjointElement(::Any) = AdjointElementNo() -UnitDiagonal(::UnitUpperTriangular) = UnitDiagonalYes() -UnitDiagonal(::UnitLowerTriangular) = UnitDiagonalYes() -UnitDiagonal(::Any) = UnitDiagonalNo() + +possible_adjoint(adj::Bool, a::Real ) = a +possible_adjoint(adj::Bool, a ) = adj ? adjoint(a) : a + +const UnitDiagonalTriangular = Union{UnitUpperTriangular,UnitLowerTriangular} const LowerTriangularPlain{T} = Union{ LowerTriangular{T,<:SparseMatrixCSCUnion{T}}, @@ -280,8 +271,21 @@ const TriangularSparse{T} = Union{ LowerTriangularSparse{T}, UpperTriangularSparse{T}} where T ## triangular multipliers -function fwdTriMul!(A::SparseMatrixCSCUnion, B::AbstractVecOrMat, unit::UnitDiagonal) -# forward substitution for UpperTriangular SparseCSC matrices +function lmul!(A::TriangularSparse{T}, B::StridedVecOrMat{T}) where T + @assert !has_offset_axes(A, B) + nrowB, ncolB = size(B, 1), size(B, 2) + ncol = LinearAlgebra.checksquare(A) + if nrowB != ncol + throw(DimensionMismatch("A is $(ncol) columns and B has $(nrowB) rows")) + end + _lmul!(A, B) +end + +# forward multiplication for UpperTriangular SparseCSC matrices +function _lmul!(U::UpperTriangularPlain, B::StridedVecOrMat) + A = U.data + unit = U isa UnitDiagonalTriangular + nrowB, ncolB = size(B, 1), size(B, 2) aa = getnzval(A) ja = getrowval(A) @@ -292,7 +296,7 @@ function fwdTriMul!(A::SparseMatrixCSCUnion, B::AbstractVecOrMat, unit::UnitDiag for j = 1:nrowB i1 = ia[j] i2 = ia[j + 1] - 1 - done = unit isa UnitDiagonalYes + done = unit bj = B[joff + j] for ii = i1:i2 @@ -301,7 +305,7 @@ function fwdTriMul!(A::SparseMatrixCSCUnion, B::AbstractVecOrMat, unit::UnitDiag if jai < j B[joff + jai] += aii * bj elseif jai == j - if unit isa UnitDiagonalNo + if !unit B[joff + j] *= aii done = true end @@ -318,8 +322,11 @@ function fwdTriMul!(A::SparseMatrixCSCUnion, B::AbstractVecOrMat, unit::UnitDiag B end -function bwdTriMul!(A::SparseMatrixCSCUnion, B::AbstractVecOrMat, unit::UnitDiagonal) -# backward substitution for LowerTriangular SparseCSC matrices +# backward multiplication for LowerTriangular SparseCSC matrices +function _lmul!(L::LowerTriangularPlain, B::StridedVecOrMat) + A = L.data + unit = L isa UnitDiagonalTriangular + nrowB, ncolB = size(B, 1), size(B, 2) aa = getnzval(A) ja = getrowval(A) @@ -330,7 +337,7 @@ function bwdTriMul!(A::SparseMatrixCSCUnion, B::AbstractVecOrMat, unit::UnitDiag for j = nrowB:-1:1 i1 = ia[j] i2 = ia[j + 1] - 1 - done = unit isa UnitDiagonalYes + done = unit bj = B[joff + j] for ii = i2:-1:i1 @@ -339,7 +346,7 @@ function bwdTriMul!(A::SparseMatrixCSCUnion, B::AbstractVecOrMat, unit::UnitDiag if jai > j B[joff + jai] += aii * bj elseif jai == j - if unit isa UnitDiagonalNo + if !unit B[joff + j] *= aii done = true end @@ -356,8 +363,12 @@ function bwdTriMul!(A::SparseMatrixCSCUnion, B::AbstractVecOrMat, unit::UnitDiag B end -function _fwdTriMul!(A::SparseMatrixCSCUnion, B::AbstractVecOrMat, unit::UnitDiagonal, adj::AdjointElement) -# forward substitution for adjoint and transpose of LowerTriangular CSC matrices +# forward multiplication for adjoint and transpose of LowerTriangular CSC matrices +function _lmul!(U::UpperTriangularWrapped, B::StridedVecOrMat) + A = U.parent.data + unit = U.parent isa UnitDiagonalTriangular + adj = U isa Adjoint + nrowB, ncolB = size(B, 1), size(B, 2) aa = getnzval(A) ja = getrowval(A) @@ -370,7 +381,7 @@ function _fwdTriMul!(A::SparseMatrixCSCUnion, B::AbstractVecOrMat, unit::UnitDia i1 = ia[j] i2 = ia[j + 1] - 1 akku = Z - j0 = unit isa UnitDiagonalNo ? j : j + 1 + j0 = !unit ? j : j + 1 # loop through column j of A - only structural non-zeros for ii = i2:-1:i1 @@ -382,7 +393,7 @@ function _fwdTriMul!(A::SparseMatrixCSCUnion, B::AbstractVecOrMat, unit::UnitDia break end end - if unit isa UnitDiagonalYes + if unit akku += B[joff + j] end B[joff + j] = akku @@ -392,8 +403,12 @@ function _fwdTriMul!(A::SparseMatrixCSCUnion, B::AbstractVecOrMat, unit::UnitDia B end -function _bwdTriMul!(A::SparseMatrixCSCUnion, B::AbstractVecOrMat, unit::UnitDiagonal, adj::AdjointElement) -# multiply with adjoint and transpose of LowerTriangular CSC matrices +# backward multiplication with adjoint and transpose of LowerTriangular CSC matrices +function _lmul!(L::LowerTriangularWrapped, B::StridedVecOrMat) + A = L.parent.data + unit = L.parent isa UnitDiagonalTriangular + adj = L isa Adjoint + nrowB, ncolB = size(B, 1), size(B, 2) aa = getnzval(A) ja = getrowval(A) @@ -406,7 +421,7 @@ function _bwdTriMul!(A::SparseMatrixCSCUnion, B::AbstractVecOrMat, unit::UnitDia i1 = ia[j] i2 = ia[j + 1] - 1 akku = Z - j0 = unit isa UnitDiagonalNo ? j : j - 1 + j0 = !unit ? j : j - 1 # loop through column j of A - only structural non-zeros for ii = i1:i2 @@ -418,7 +433,7 @@ function _bwdTriMul!(A::SparseMatrixCSCUnion, B::AbstractVecOrMat, unit::UnitDia break end end - if unit isa UnitDiagonalYes + if unit akku += B[joff + j] end B[joff + j] = akku @@ -428,31 +443,22 @@ function _bwdTriMul!(A::SparseMatrixCSCUnion, B::AbstractVecOrMat, unit::UnitDia B end -function lmul!(A::TriangularSparse{T}, B::StridedVecOrMat{T}) where T +## triangular solvers +function ldiv!(A::TriangularSparse{T}, B::StridedVecOrMat{T}) where T @assert !has_offset_axes(A, B) nrowB, ncolB = size(B, 1), size(B, 2) ncol = LinearAlgebra.checksquare(A) if nrowB != ncol throw(DimensionMismatch("A is $(ncol) columns and B has $(nrowB) rows")) end - _lmul!(A, B) + _ldiv!(A, B) end -_lmul!(L::LowerTriangularPlain, B::StridedVecOrMat) = - bwdTriMul!(L.data, B, UnitDiagonal(L)) - -_lmul!(L::LowerTriangularWrapped, B::StridedVecOrMat) = - _bwdTriMul!(L.parent.data, B, UnitDiagonal(L.parent), AdjointElement(L)) - -_lmul!(U::UpperTriangularPlain, B::StridedVecOrMat) = - fwdTriMul!(U.data, B, UnitDiagonal(U)) - -_lmul!(U::UpperTriangularWrapped, B::StridedVecOrMat) = - _fwdTriMul!(U.parent.data, B, UnitDiagonal(U.parent), AdjointElement(U)) - -## triangular solvers -function fwdTriSolve!(A::SparseMatrixCSCUnion, B::AbstractVecOrMat, unit::UnitDiagonal) # forward substitution for LowerTriangular CSC matrices +function _ldiv!(L::LowerTriangularPlain, B::StridedVecOrMat) + A = L.data + unit = L isa UnitDiagonalTriangular + nrowB, ncolB = size(B, 1), size(B, 2) aa = getnzval(A) ja = getrowval(A) @@ -472,12 +478,12 @@ function fwdTriSolve!(A::SparseMatrixCSCUnion, B::AbstractVecOrMat, unit::UnitDi bj = B[joff + j] # check for zero pivot and divide with pivot if jai == j - if unit isa UnitDiagonalNo + if !unit bj /= aa[ii] B[joff + j] = bj end ii += 1 - elseif unit isa UnitDiagonalNo + elseif !unit throw(LinearAlgebra.SingularException(j)) end @@ -491,8 +497,11 @@ function fwdTriSolve!(A::SparseMatrixCSCUnion, B::AbstractVecOrMat, unit::UnitDi B end -function bwdTriSolve!(A::SparseMatrixCSCUnion, B::AbstractVecOrMat, unit::UnitDiagonal) # backward substitution for UpperTriangular CSC matrices +function _ldiv!(U::UpperTriangularPlain, B::StridedVecOrMat) + A = U.data + unit = U isa UnitDiagonalTriangular + nrowB, ncolB = size(B, 1), size(B, 2) aa = getnzval(A) ja = getrowval(A) @@ -512,12 +521,12 @@ function bwdTriSolve!(A::SparseMatrixCSCUnion, B::AbstractVecOrMat, unit::UnitDi bj = B[joff + j] # check for zero pivot and divide with pivot if jai == j - if unit isa UnitDiagonalNo + if !unit bj /= aa[ii] B[joff + j] = bj end ii -= 1 - elseif unit isa UnitDiagonalNo + elseif !unit throw(LinearAlgebra.SingularException(j)) end @@ -531,8 +540,12 @@ function bwdTriSolve!(A::SparseMatrixCSCUnion, B::AbstractVecOrMat, unit::UnitDi B end -function _fwdTriSolve!(A::SparseMatrixCSCUnion, B::AbstractVecOrMat, unit::UnitDiagonal, adj::AdjointElement) # forward substitution for adjoint and transpose of UpperTriangular CSC matrices +function _ldiv!(L::LowerTriangularWrapped, B::StridedVecOrMat) + A = L.parent.data + unit = L.parent isa UnitDiagonalTriangular + adj = L isa Adjoint + nrowB, ncolB = size(B, 1), size(B, 2) aa = getnzval(A) ja = getrowval(A) @@ -547,14 +560,14 @@ function _fwdTriSolve!(A::SparseMatrixCSCUnion, B::AbstractVecOrMat, unit::UnitD done = false # loop through column j of A - only structural non-zeros - for ip = i1:i2 - i = ja[ip] - if i < j - aai = possible_adjoint(adj, aa[ip]) - akku -= B[joff + i] * aai - elseif i == j - if unit isa UnitDiagonalNo - aai = possible_adjoint(adj, aa[ip]) + for ii = i1:i2 + jai = ja[ii] + if jai < j + aai = possible_adjoint(adj, aa[ii]) + akku -= B[joff + jai] * aai + elseif jai == j + if !unit + aai = possible_adjoint(adj, aa[ii]) akku /= aai end done = true @@ -563,7 +576,7 @@ function _fwdTriSolve!(A::SparseMatrixCSCUnion, B::AbstractVecOrMat, unit::UnitD break end end - if !done && unit isa UnitDiagonalNo + if !done && !unit throw(LinearAlgebra.SingularException(j)) end B[joff + j] = akku @@ -573,8 +586,12 @@ function _fwdTriSolve!(A::SparseMatrixCSCUnion, B::AbstractVecOrMat, unit::UnitD B end -function _bwdTriSolve!(A::SparseMatrixCSCUnion, B::AbstractVecOrMat, unit::UnitDiagonal, adj::AdjointElement) # backward substitution for adjoint and transpose of LowerTriangular CSC matrices +function _ldiv!(U::UpperTriangularWrapped, B::StridedVecOrMat) + A = U.parent.data + unit = U.parent isa UnitDiagonalTriangular + adj = U isa Adjoint + nrowB, ncolB = size(B, 1), size(B, 2) aa = getnzval(A) ja = getrowval(A) @@ -589,14 +606,14 @@ function _bwdTriSolve!(A::SparseMatrixCSCUnion, B::AbstractVecOrMat, unit::UnitD done = false # loop through column j of A - only structural non-zeros - for ip = i2:-1:i1 - i = ja[ip] - if i > j - aai = possible_adjoint(adj, aa[ip]) - akku -= B[joff + i] * aai - elseif i == j - if unit isa UnitDiagonalNo - aai = possible_adjoint(adj, aa[ip]) + for ii = i2:-1:i1 + jai = ja[ii] + if jai > j + aai = possible_adjoint(adj, aa[ii]) + akku -= B[joff + jai] * aai + elseif jai == j + if !unit + aai = possible_adjoint(adj, aa[ii]) akku /= aai end done = true @@ -605,7 +622,7 @@ function _bwdTriSolve!(A::SparseMatrixCSCUnion, B::AbstractVecOrMat, unit::UnitD break end end - if !done && unit isa UnitDiagonalNo + if !done && !unit throw(LinearAlgebra.SingularException(j)) end B[joff + j] = akku @@ -615,28 +632,6 @@ function _bwdTriSolve!(A::SparseMatrixCSCUnion, B::AbstractVecOrMat, unit::UnitD B end -function ldiv!(A::TriangularSparse{T}, B::StridedVecOrMat{T}) where T - @assert !has_offset_axes(A, B) - nrowB, ncolB = size(B, 1), size(B, 2) - ncol = LinearAlgebra.checksquare(A) - if nrowB != ncol - throw(DimensionMismatch("A is $(ncol) columns and B has $(nrowB) rows")) - end - _ldiv!(A, B) -end - -_ldiv!(L::LowerTriangularPlain, B::StridedVecOrMat) = - fwdTriSolve!(L.data, B, UnitDiagonal(L)) - -_ldiv!(L::LowerTriangularWrapped, B::StridedVecOrMat) = - _fwdTriSolve!(L.parent.data, B, UnitDiagonal(L.parent), AdjointElement(L)) - -_ldiv!(U::UpperTriangularPlain, B::StridedVecOrMat) = - bwdTriSolve!(U.data, B, UnitDiagonal(U)) - -_ldiv!(U::UpperTriangularWrapped, B::StridedVecOrMat) = - _bwdTriSolve!(U.parent.data, B, UnitDiagonal(U.parent), AdjointElement(U)) - (\)(L::TriangularSparse, B::SparseMatrixCSC) = ldiv!(L, Array(B)) (*)(L::TriangularSparse, B::SparseMatrixCSC) = lmul!(L, Array(B)) From 21592db0ed0dec1750db5a153a761133c0d2dd9e Mon Sep 17 00:00:00 2001 From: Klaus Crusius Date: Wed, 8 Aug 2018 23:22:34 +0200 Subject: [PATCH 07/26] additional test cases and bug fix --- stdlib/SparseArrays/src/linalg.jl | 6 ++---- stdlib/SparseArrays/test/sparse.jl | 7 +++++++ 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/stdlib/SparseArrays/src/linalg.jl b/stdlib/SparseArrays/src/linalg.jl index 86ab4b78f50f0..9be76da96dc98 100644 --- a/stdlib/SparseArrays/src/linalg.jl +++ b/stdlib/SparseArrays/src/linalg.jl @@ -472,8 +472,7 @@ function _ldiv!(L::LowerTriangularPlain, B::StridedVecOrMat) # find diagonal element ii = searchsortedfirst(ja, j, i1, i2, Base.Order.Forward) - ii > i2 && ( ii = i1) - jai = ja[ii] + jai = ii > i2 ? zero(eltype(ja)) : ja[ii] bj = B[joff + j] # check for zero pivot and divide with pivot @@ -515,8 +514,7 @@ function _ldiv!(U::UpperTriangularPlain, B::StridedVecOrMat) # find diagonal element ii = searchsortedlast(ja, j, i1, i2, Base.Order.Forward) - ii < i1 && ( ii = i2) - jai = ja[ii] + jai = ii < i1 ? zero(eltype(ja)) : ja[ii] bj = B[joff + j] # check for zero pivot and divide with pivot diff --git a/stdlib/SparseArrays/test/sparse.jl b/stdlib/SparseArrays/test/sparse.jl index ac91d66614fa5..fd13fc9189233 100644 --- a/stdlib/SparseArrays/test/sparse.jl +++ b/stdlib/SparseArrays/test/sparse.jl @@ -2312,6 +2312,13 @@ end @test AW \ B ≈ MAW \ B end end + + A = LowerTriangular(sparse([0 2.0;0 1])) + @test_throws SingularException(1) A \ ones(2) + A = UpperTriangular(sparse([1.0 0;0 0])) + @test_throws SingularException(2) A \ ones(2) + + end end # module From 136a6a7b9c421e7ed77e59e603ec041a65ee4679 Mon Sep 17 00:00:00 2001 From: mcognetta Date: Sat, 25 Aug 2018 03:32:02 +0900 Subject: [PATCH 08/26] specializing some structured matrix operations --- stdlib/LinearAlgebra/src/bidiag.jl | 95 ++++++++++++++++++++++++- stdlib/LinearAlgebra/src/triangular.jl | 2 +- stdlib/SparseArrays/src/SparseArrays.jl | 3 + 3 files changed, 97 insertions(+), 3 deletions(-) diff --git a/stdlib/LinearAlgebra/src/bidiag.jl b/stdlib/LinearAlgebra/src/bidiag.jl index 90b2dc55498ce..8a5200d21edd4 100644 --- a/stdlib/LinearAlgebra/src/bidiag.jl +++ b/stdlib/LinearAlgebra/src/bidiag.jl @@ -488,8 +488,99 @@ end const SpecialMatrix = Union{Bidiagonal,SymTridiagonal,Tridiagonal} # to avoid ambiguity warning, but shouldn't be necessary -*(A::AbstractTriangular, B::SpecialMatrix) = Array(A) * Array(B) -*(A::SpecialMatrix, B::SpecialMatrix) = Array(A) * Array(B) +#*(A::AbstractTriangular, B::SpecialMatrix) = Array(A) * Array(B) +#*(A::SpecialMatrix, B::SpecialMatrix) = Array(A) * Array(B) + +# moving several to SparseArrays since they call sparse matrix constructors + +# *(A::SymTridiagonal, B::BiTriSym) = A_mul_B_td!(zeros(eltype(A), size(A)...), A, B) + +# *(A::BiTri, B::BiTriSym) = A_mul_B_td!(zeros(size(A)...), A, B) +# *(A::BiTriSym, B::BiTriSym) = A_mul_B_td!(zero(A), A, B) + +# here we are going to specialize when the uplo values match +# *(A::AbstractTriangular, B::BiTriSym) = A_mul_B_td!(zeros(size(A)...), A, B) +# function *(A::AbstractTriangular, B::BiTri) +# if A.uplo == B.uplo +# A_mul_B_td!(zero(A), A, B) +# else +# A_mul_B_td!(zeros(size(A)...), A, B) +# end +# end + +# TS = promote_op(matprod, eltype(A), eltype(B)) +# mul!(similar(B, TS, (size(A,2), size(B,2))), adjoint(A), B) + +# function *(A::AbstractMatrix, B::Diagonal) +# TS = promote_op(matprod, eltype(A), eltype(B)) +# A_mul_B_td!(similar(A, TS), A, B) +# end + +function *(A::AbstractTriangular, B::Union{SymTridiagonal, Tridiagonal}) + TS = promote_op(matprod, eltype(A), eltype(B)) + A_mul_B_td!(zeros(TS, size(A)...), A, B) +end + +function *(A::UpperTriangular, B::Bidiagonal) + TS = promote_op(matprod, eltype(A), eltype(B)) + if B.uplo == 'U' + A_mul_B_td!(similar(A, TS), A, B) + else + A_mul_B_td!(zeros(TS, size(A)...), A, B) + end +end + +function *(A::LowerTriangular, B::Bidiagonal) + TS = promote_op(matprod, eltype(A), eltype(B)) + if B.uplo == 'L' + A_mul_B_td!(similar(A, TS), A, B) + else + A_mul_B_td!(zeros(TS, size(A)...), A, B) + end +end + +function *(A::Union{SymTridiagonal, Tridiagonal}, B::AbstractTriangular) + TS = promote_op(matprod, eltype(A), eltype(B)) + A_mul_B_td!(zeros(eltype(A), size(A)...), A, B) +end + +function *(A::Bidiagonal, B::UpperTriangular) + TS = promote_op(matprod, eltype(A), eltype(B)) + if A.uplo == 'U' + A_mul_B_td!(similar(B, TS), A, B) + else + A_mul_B_td!(zeros(TS, size(A)...), A, B) + end +end + +function *(A::Bidiagonal, B::LowerTriangular) + TS = promote_op(matprod, eltype(A), eltype(B)) + if A.uplo == 'L' + A_mul_B_td!(similar(B, TS), A, B) + else + A_mul_B_td!(zeros(TS, size(A)...), A, B) + end +end + +function *(A::Diagonal, B::BiTri) + TS = promote_op(matprod, eltype(A), eltype(B)) + A_mul_B_td!(imilar(B, TS), A, B) +end + +function *(A::Diagonal, B::SymTridiagonal) + TS = promote_op(matprod, eltype(A), eltype(B)) + A_mul_B_td!(Tridiagonal(zeros(TS, size(A)...)), A, B) +end + +function *(A::SymTridiagonal, B::Diagonal) + TS = promote_op(matprod, eltype(A), eltype(B)) + A_mul_B_td!(Tridiagonal(zeros(TS, size(A)...)), A, B) +end + +*(A::Adjoint{<:Any,<:Diagonal}, B::BiTriSym) = A_mul_B_td!(zeros(eltype(A), size(A)...), A, B) +*(A::Transpose{<:Any,<:Diagonal}, B::BiTriSym) = A_mul_B_td!(zeros(eltype(A), size(A)...), A, B) +*(A::Adjoint{<:Any,<:AbstractTriangular}, B::BiTriSym) = A_mul_B_td!(zeros(eltype(A), size(A)...), A, B) +*(A::Transpose{<:Any,<:AbstractTriangular}, B::BiTriSym) = A_mul_B_td!(zeros(eltype(A), size(A)...), A, B) #Generic multiplication *(A::Bidiagonal{T}, B::AbstractVector{T}) where {T} = *(Array(A), B) diff --git a/stdlib/LinearAlgebra/src/triangular.jl b/stdlib/LinearAlgebra/src/triangular.jl index ca5f4d2e0e014..8855c8340e6e9 100644 --- a/stdlib/LinearAlgebra/src/triangular.jl +++ b/stdlib/LinearAlgebra/src/triangular.jl @@ -1599,7 +1599,7 @@ rdiv!(A::LowerTriangular, transB::Transpose{<:Any,<:Union{UpperTriangular,UnitUp ## Some Triangular-Triangular cases. We might want to write tailored methods ## for these cases, but I'm not sure it is worth it. -(*)(A::Union{Tridiagonal,SymTridiagonal}, B::AbstractTriangular) = rmul!(Matrix(A), B) +# (*)(A::Union{Tridiagonal,SymTridiagonal}, B::AbstractTriangular) = rmul!(Matrix(A), B) for (f, f2!) in ((:*, :lmul!), (:\, :ldiv!)) @eval begin diff --git a/stdlib/SparseArrays/src/SparseArrays.jl b/stdlib/SparseArrays/src/SparseArrays.jl index 724b9865782a6..f202d4e9e9660 100644 --- a/stdlib/SparseArrays/src/SparseArrays.jl +++ b/stdlib/SparseArrays/src/SparseArrays.jl @@ -51,4 +51,7 @@ similar(D::Diagonal, ::Type{T}, dims::Union{Dims{1},Dims{2}}) where {T} = spzero similar(S::SymTridiagonal, ::Type{T}, dims::Union{Dims{1},Dims{2}}) where {T} = spzeros(T, dims...) similar(M::Tridiagonal, ::Type{T}, dims::Union{Dims{1},Dims{2}}) where {T} = spzeros(T, dims...) +const BiTriSym = Union{Bidiagonal,SymTridiagonal,Tridiagonal} +*(A::BiTriSym, B::BiTriSym) = mul!(spzeros(eltype(A),size(A)...), A, B) + end From 336d9c3101c2cccc7aa48db39862eb66fa137147 Mon Sep 17 00:00:00 2001 From: mcognetta Date: Mon, 27 Aug 2018 23:19:54 +0900 Subject: [PATCH 09/26] added constructors for Triangular(::Diagonal). Removed redundant code from binops of special.jl so that broadcasting takes over. Cleaned up some of the tests for special.jl --- stdlib/LinearAlgebra/src/special.jl | 75 ++++++++++------------------ stdlib/LinearAlgebra/test/special.jl | 36 ++++++------- 2 files changed, 43 insertions(+), 68 deletions(-) diff --git a/stdlib/LinearAlgebra/src/special.jl b/stdlib/LinearAlgebra/src/special.jl index a4253c6ebe255..207d4d4d1ace6 100644 --- a/stdlib/LinearAlgebra/src/special.jl +++ b/stdlib/LinearAlgebra/src/special.jl @@ -56,9 +56,15 @@ SymTridiagonal(A::AbstractTriangular) = SymTridiagonal(Tridiagonal(A)) Tridiagonal(A::AbstractTriangular) = isbanded(A, -1, 1) ? Tridiagonal(diag(A, -1), diag(A, 0), diag(A, 1)) : # is tridiagonal throw(ArgumentError("matrix cannot be represented as Tridiagonal")) - +UpperTriangular(A::Bidiagonal) = + A.uplo == 'U' ? UpperTriangular{eltype(A), typeof(A)}(A) : + throw(ArgumentError("matrix cannot be represented as UpperTriangular")) +LowerTriangular(A::Bidiagonal) = + A.uplo == 'L' ? LowerTriangular{eltype(A), typeof(A)}(A) : + throw(ArgumentError("matrix cannot be represented as LowerTriangular")) const ConvertibleSpecialMatrix = Union{Diagonal,Bidiagonal,SymTridiagonal,Tridiagonal,AbstractTriangular} +const PossibleTriangularMatrix = Union{Diagonal, Bidiagonal, AbstractTriangular} convert(T::Type{<:Diagonal}, m::ConvertibleSpecialMatrix) = m isa T ? m : T(m) convert(T::Type{<:SymTridiagonal}, m::ConvertibleSpecialMatrix) = m isa T ? m : T(m) @@ -67,6 +73,9 @@ convert(T::Type{<:Tridiagonal}, m::ConvertibleSpecialMatrix) = m isa T ? m : convert(T::Type{<:LowerTriangular}, m::Union{LowerTriangular,UnitLowerTriangular}) = m isa T ? m : T(m) convert(T::Type{<:UpperTriangular}, m::Union{UpperTriangular,UnitUpperTriangular}) = m isa T ? m : T(m) +convert(T::Type{<:LowerTriangular}, m::PossibleTriangularMatrix) = m isa T ? m : T(m) +convert(T::Type{<:UpperTriangular}, m::PossibleTriangularMatrix) = m isa T ? m : T(m) + # Constructs two method definitions taking into account (assumed) commutativity # e.g. @commutative f(x::S, y::T) where {S,T} = x+y is the same is defining # f(x::S, y::T) where {S,T} = x+y @@ -80,58 +89,28 @@ macro commutative(myexpr) end for op in (:+, :-) - SpecialMatrices = [:Diagonal, :Bidiagonal, :Tridiagonal, :Matrix] - for (idx, matrixtype1) in enumerate(SpecialMatrices) # matrixtype1 is the sparser matrix type - for matrixtype2 in SpecialMatrices[idx+1:end] # matrixtype2 is the denser matrix type - @eval begin # TODO quite a few of these conversions are NOT defined - ($op)(A::($matrixtype1), B::($matrixtype2)) = ($op)(convert(($matrixtype2), A), B) - ($op)(A::($matrixtype2), B::($matrixtype1)) = ($op)(A, convert(($matrixtype2), B)) - end - end - end - - for matrixtype1 in (:SymTridiagonal,) # matrixtype1 is the sparser matrix type - for matrixtype2 in (:Tridiagonal, :Matrix) # matrixtype2 is the denser matrix type - @eval begin - ($op)(A::($matrixtype1), B::($matrixtype2)) = ($op)(convert(($matrixtype2), A), B) - ($op)(A::($matrixtype2), B::($matrixtype1)) = ($op)(A, convert(($matrixtype2), B)) + for (matrixtype, uplo, converttype) in ((:UpperTriangular, 'U', :UpperTriangular), + (:UnitUpperTriangular, 'U', :UpperTriangular), + (:LowerTriangular, 'L', :LowerTriangular), + (:UnitLowerTriangular, 'L', :LowerTriangular)) + @eval begin + function ($op)(A::$matrixtype, B::Bidiagonal) + if B.uplo == $uplo + ($op)(A, convert($converttype, B)) + else + ($op).(A, B) + end end - end - end - # todo check if these conversion methods are optimal - # we should be able to do these structured conversions really quickly - - # Diagonal +/- SymTridiagonal (and reverse) will always be SymTridiagonal - @eval begin - ($op)(A::SymTridiagonal, B::Diagonal) = ($op)(A, convert(SymTridiagonal, B)) - ($op)(A::Diagonal, B::SymTridiagonal) = ($op)(convert(SymTridiagonal, A), B) - end - - # Bidiagonal +/- SymTridiagonal (and reverse) will always be Tridiagonal - @eval begin - ($op)(A::SymTridiagonal, B::Bidiagonal) = ($op)(convert(Tridiagonal, A), B) - ($op)(A::Bidiagonal, B::SymTridiagonal) = ($op)(A, convert(Tridiagonal, B)) - end - - for matrixtype1 in (:Diagonal,) - for (matrixtype2,matrixtype3) in ((:UpperTriangular,:UpperTriangular), - (:UnitUpperTriangular,:UpperTriangular), - (:LowerTriangular,:LowerTriangular), - (:UnitLowerTriangular,:LowerTriangular)) - @eval begin - ($op)(A::($matrixtype1), B::($matrixtype2)) = ($op)(($matrixtype3)(A), B) - ($op)(A::($matrixtype2), B::($matrixtype1)) = ($op)(A, ($matrixtype3)(B)) + function ($op)(A::Bidiagonal, B::$matrixtype) + if A.uplo == $uplo + ($op)(convert($converttype, A), B) + else + ($op).(A, B) + end end end end - - for matrixtype in (:SymTridiagonal,:Tridiagonal,:Bidiagonal,:Matrix) - @eval begin - ($op)(A::AbstractTriangular, B::($matrixtype)) = ($op)(copyto!(similar(parent(A)), A), B) - ($op)(A::($matrixtype), B::AbstractTriangular) = ($op)(A, copyto!(similar(parent(B)), B)) - end - end end rmul!(A::AbstractTriangular, adjB::Adjoint{<:Any,<:Union{QRCompactWYQ,QRPackedQ}}) = diff --git a/stdlib/LinearAlgebra/test/special.jl b/stdlib/LinearAlgebra/test/special.jl index 0670da55d91b4..300a4b847ecaa 100644 --- a/stdlib/LinearAlgebra/test/special.jl +++ b/stdlib/LinearAlgebra/test/special.jl @@ -109,27 +109,23 @@ end @test Matrix(convert(Spectype,A) - D) ≈ Matrix(A - D) end end + + UpTri = UpperTriangular(rand(20,20)) + LoTri = LowerTriangular(rand(20,20)) + Diag = Diagonal(rand(20,20)) + Tridiag = Tridiagonal(rand(20, 20)) + UpBi = Bidiagonal(rand(20,20), :U) + LoBi = Bidiagonal(rand(20,20), :L) + Sym = SymTridiagonal(rand(20), rand(19)) + Dense = rand(20, 20) + mats = [UpTri, LoTri, Diag, Tridiag, UpBi, LoBi, Sym, Dense] - for uplo in ('U', 'L') - E = Bidiagonal(a, fill(1., n-1), uplo) - @test E + B ≈ Matrix(E) + Matrix(B) - @test B + E ≈ Matrix(B) + Matrix(E) - @test E - B ≈ Matrix(E) - Matrix(B) - @test B - E ≈ Matrix(B) - Matrix(E) - end -end - -# more need to be added here but for now only a few operation/type combinations output the optimal type -@testset "output type of binary ops on triangular/diagonal matrices" begin - a=[1.0:n;] - sym = SymTridiagonal(a, fill(1., n-1)) - - for uplo in ('U', 'L') - bi = Bidiagonal(a, fill(1., n-1), uplo) - @test typeof(sym+bi) == LinearAlgebra.Tridiagonal{Float64,Array{Float64,1}} - @test typeof(bi+sym) == LinearAlgebra.Tridiagonal{Float64,Array{Float64,1}} - @test typeof(sym-bi) == LinearAlgebra.Tridiagonal{Float64,Array{Float64,1}} - @test typeof(bi-sym) == LinearAlgebra.Tridiagonal{Float64,Array{Float64,1}} + for op in (+, -) + for A in mats + for B in mats + @test (op)(A, B) ≈ (op)(Matrix(A), Matrix(B)) ≈ Matrix((op)(A, B)) + end + end end end From cb8baae6c39fde0331189316bf78c062e965f0e8 Mon Sep 17 00:00:00 2001 From: mcognetta Date: Mon, 27 Aug 2018 23:39:58 +0900 Subject: [PATCH 10/26] fix whitespace --- stdlib/LinearAlgebra/src/special.jl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/stdlib/LinearAlgebra/src/special.jl b/stdlib/LinearAlgebra/src/special.jl index 207d4d4d1ace6..4a16a2fff539d 100644 --- a/stdlib/LinearAlgebra/src/special.jl +++ b/stdlib/LinearAlgebra/src/special.jl @@ -56,11 +56,11 @@ SymTridiagonal(A::AbstractTriangular) = SymTridiagonal(Tridiagonal(A)) Tridiagonal(A::AbstractTriangular) = isbanded(A, -1, 1) ? Tridiagonal(diag(A, -1), diag(A, 0), diag(A, 1)) : # is tridiagonal throw(ArgumentError("matrix cannot be represented as Tridiagonal")) -UpperTriangular(A::Bidiagonal) = - A.uplo == 'U' ? UpperTriangular{eltype(A), typeof(A)}(A) : +UpperTriangular(A::Bidiagonal) = + A.uplo == 'U' ? UpperTriangular{eltype(A), typeof(A)}(A) : throw(ArgumentError("matrix cannot be represented as UpperTriangular")) -LowerTriangular(A::Bidiagonal) = - A.uplo == 'L' ? LowerTriangular{eltype(A), typeof(A)}(A) : +LowerTriangular(A::Bidiagonal) = + A.uplo == 'L' ? LowerTriangular{eltype(A), typeof(A)}(A) : throw(ArgumentError("matrix cannot be represented as LowerTriangular")) const ConvertibleSpecialMatrix = Union{Diagonal,Bidiagonal,SymTridiagonal,Tridiagonal,AbstractTriangular} From 0ca26c952c0a94d90db949a92bc737b1aaf227ae Mon Sep 17 00:00:00 2001 From: mcognetta Date: Tue, 28 Aug 2018 08:34:35 +0900 Subject: [PATCH 11/26] actually fixed whitespace --- stdlib/LinearAlgebra/src/special.jl | 4 ++-- stdlib/LinearAlgebra/test/special.jl | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/stdlib/LinearAlgebra/src/special.jl b/stdlib/LinearAlgebra/src/special.jl index 4a16a2fff539d..347442ddbf3c3 100644 --- a/stdlib/LinearAlgebra/src/special.jl +++ b/stdlib/LinearAlgebra/src/special.jl @@ -74,7 +74,7 @@ convert(T::Type{<:LowerTriangular}, m::Union{LowerTriangular,UnitLowerTriangular convert(T::Type{<:UpperTriangular}, m::Union{UpperTriangular,UnitUpperTriangular}) = m isa T ? m : T(m) convert(T::Type{<:LowerTriangular}, m::PossibleTriangularMatrix) = m isa T ? m : T(m) -convert(T::Type{<:UpperTriangular}, m::PossibleTriangularMatrix) = m isa T ? m : T(m) +convert(T::Type{<:UpperTriangular}, m::PossibleTriangularMatrix) = m isa T ? m : T(m) # Constructs two method definitions taking into account (assumed) commutativity # e.g. @commutative f(x::S, y::T) where {S,T} = x+y is the same is defining @@ -89,7 +89,7 @@ macro commutative(myexpr) end for op in (:+, :-) - for (matrixtype, uplo, converttype) in ((:UpperTriangular, 'U', :UpperTriangular), + for (matrixtype, uplo, converttype) in ((:UpperTriangular, 'U', :UpperTriangular), (:UnitUpperTriangular, 'U', :UpperTriangular), (:LowerTriangular, 'L', :LowerTriangular), (:UnitLowerTriangular, 'L', :LowerTriangular)) diff --git a/stdlib/LinearAlgebra/test/special.jl b/stdlib/LinearAlgebra/test/special.jl index 300a4b847ecaa..1927d313c8cf6 100644 --- a/stdlib/LinearAlgebra/test/special.jl +++ b/stdlib/LinearAlgebra/test/special.jl @@ -109,7 +109,7 @@ end @test Matrix(convert(Spectype,A) - D) ≈ Matrix(A - D) end end - + UpTri = UpperTriangular(rand(20,20)) LoTri = LowerTriangular(rand(20,20)) Diag = Diagonal(rand(20,20)) From 981e0efd2dcaaf7daf1a933605aee2da5544a75f Mon Sep 17 00:00:00 2001 From: mcognetta Date: Fri, 31 Aug 2018 06:51:12 +0900 Subject: [PATCH 12/26] fixed a typo in Diagonal*Bi/Tridiag. Changed the multiplication methods to more explicit constructors so that matrices with BigFloat dont error --- stdlib/LinearAlgebra/src/bidiag.jl | 37 ++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/stdlib/LinearAlgebra/src/bidiag.jl b/stdlib/LinearAlgebra/src/bidiag.jl index 8a5200d21edd4..cb93807fefff0 100644 --- a/stdlib/LinearAlgebra/src/bidiag.jl +++ b/stdlib/LinearAlgebra/src/bidiag.jl @@ -524,7 +524,7 @@ end function *(A::UpperTriangular, B::Bidiagonal) TS = promote_op(matprod, eltype(A), eltype(B)) if B.uplo == 'U' - A_mul_B_td!(similar(A, TS), A, B) + A_mul_B_td!(UpperTriangular(zeros(TS, size(A)...)), A, B) else A_mul_B_td!(zeros(TS, size(A)...), A, B) end @@ -533,7 +533,7 @@ end function *(A::LowerTriangular, B::Bidiagonal) TS = promote_op(matprod, eltype(A), eltype(B)) if B.uplo == 'L' - A_mul_B_td!(similar(A, TS), A, B) + A_mul_B_td!(LowerTriangular(zeros(TS, size(A)...)), A, B) else A_mul_B_td!(zeros(TS, size(A)...), A, B) end @@ -541,13 +541,13 @@ end function *(A::Union{SymTridiagonal, Tridiagonal}, B::AbstractTriangular) TS = promote_op(matprod, eltype(A), eltype(B)) - A_mul_B_td!(zeros(eltype(A), size(A)...), A, B) + A_mul_B_td!(zeros(TS, size(A)...), A, B) end function *(A::Bidiagonal, B::UpperTriangular) TS = promote_op(matprod, eltype(A), eltype(B)) if A.uplo == 'U' - A_mul_B_td!(similar(B, TS), A, B) + A_mul_B_td!(UpperTriangular(zeros(TS, size(A)...)), A, B) else A_mul_B_td!(zeros(TS, size(A)...), A, B) end @@ -556,7 +556,7 @@ end function *(A::Bidiagonal, B::LowerTriangular) TS = promote_op(matprod, eltype(A), eltype(B)) if A.uplo == 'L' - A_mul_B_td!(similar(B, TS), A, B) + A_mul_B_td!(LowerTriangular(zeros(TS, size(A)...)), A, B) else A_mul_B_td!(zeros(TS, size(A)...), A, B) end @@ -564,7 +564,7 @@ end function *(A::Diagonal, B::BiTri) TS = promote_op(matprod, eltype(A), eltype(B)) - A_mul_B_td!(imilar(B, TS), A, B) + A_mul_B_td!(similar(B, TS), A, B) end function *(A::Diagonal, B::SymTridiagonal) @@ -577,10 +577,27 @@ function *(A::SymTridiagonal, B::Diagonal) A_mul_B_td!(Tridiagonal(zeros(TS, size(A)...)), A, B) end -*(A::Adjoint{<:Any,<:Diagonal}, B::BiTriSym) = A_mul_B_td!(zeros(eltype(A), size(A)...), A, B) -*(A::Transpose{<:Any,<:Diagonal}, B::BiTriSym) = A_mul_B_td!(zeros(eltype(A), size(A)...), A, B) -*(A::Adjoint{<:Any,<:AbstractTriangular}, B::BiTriSym) = A_mul_B_td!(zeros(eltype(A), size(A)...), A, B) -*(A::Transpose{<:Any,<:AbstractTriangular}, B::BiTriSym) = A_mul_B_td!(zeros(eltype(A), size(A)...), A, B) +# todo update the specialized output types here. +# right now I am just fixing it so the eltype is correct +function *(A::Adjoint{<:Any,<:Diagonal}, B::BiTriSym) + TS = promote_op(matprod, eltype(A), eltype(B)) + A_mul_B_td!(zeros(TS, size(A)...), A, B) +end + +function *(A::Transpose{<:Any,<:Diagonal}, B::BiTriSym) + TS = promote_op(matprod, eltype(A), eltype(B)) + A_mul_B_td!(zeros(TS, size(A)...), A, B) +end + +function *(A::Adjoint{<:Any,<:AbstractTriangular}, B::BiTriSym) + TS = promote_op(matprod, eltype(A), eltype(B)) + A_mul_B_td!(zeros(TS, size(A)...), A, B) +end + +function *(A::Transpose{<:Any,<:AbstractTriangular}, B::BiTriSym) + TS = promote_op(matprod, eltype(A), eltype(B)) + A_mul_B_td!(zeros(TS, size(A)...), A, B) +end #Generic multiplication *(A::Bidiagonal{T}, B::AbstractVector{T}) where {T} = *(Array(A), B) From dd2615d11c2f387792f7093191ef4f9487542bfb Mon Sep 17 00:00:00 2001 From: mcognetta Date: Thu, 13 Sep 2018 00:07:22 +0900 Subject: [PATCH 13/26] fixed bidiag+/-diag speed regression --- stdlib/LinearAlgebra/src/special.jl | 7 +++++++ stdlib/LinearAlgebra/test/special.jl | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/stdlib/LinearAlgebra/src/special.jl b/stdlib/LinearAlgebra/src/special.jl index 347442ddbf3c3..3028ecd32bb86 100644 --- a/stdlib/LinearAlgebra/src/special.jl +++ b/stdlib/LinearAlgebra/src/special.jl @@ -111,8 +111,15 @@ for op in (:+, :-) end end end + # todo add the others that had regressions end ++(A::Bidiagonal, B::Diagonal) = Bidiagonal(broadcast(+, A.dv, B.diag), A.ev, A.uplo) +-(A::Bidiagonal, B::Diagonal) = Bidiagonal(broadcast(-, A.dv, B.diag), A.ev, A.uplo) ++(A::Diagonal, B::Bidiagonal) = Bidiagonal(broadcast(+, A.diag, B.dv), B.ev, B.uplo) +-(A::Diagonal, B::Bidiagonal) = Bidiagonal(broadcast(-, A.diag, B.dv), -B.ev, B.uplo) + + rmul!(A::AbstractTriangular, adjB::Adjoint{<:Any,<:Union{QRCompactWYQ,QRPackedQ}}) = (B = adjB.parent; rmul!(full!(A), adjoint(B))) *(A::AbstractTriangular, adjB::Adjoint{<:Any,<:Union{QRCompactWYQ,QRPackedQ}}) = diff --git a/stdlib/LinearAlgebra/test/special.jl b/stdlib/LinearAlgebra/test/special.jl index 1927d313c8cf6..59ddf847e4dbd 100644 --- a/stdlib/LinearAlgebra/test/special.jl +++ b/stdlib/LinearAlgebra/test/special.jl @@ -120,7 +120,7 @@ end Dense = rand(20, 20) mats = [UpTri, LoTri, Diag, Tridiag, UpBi, LoBi, Sym, Dense] - for op in (+, -) + for op in (+,-) for A in mats for B in mats @test (op)(A, B) ≈ (op)(Matrix(A), Matrix(B)) ≈ Matrix((op)(A, B)) From 167b9357321948e393316b26fb5551ec508185c0 Mon Sep 17 00:00:00 2001 From: mcognetta Date: Thu, 13 Sep 2018 14:34:20 +0900 Subject: [PATCH 14/26] fixed +/- regressions for the other structured matrix types (bidiag, tridiag, symtridiag, diag) --- stdlib/LinearAlgebra/src/special.jl | 38 +++++++++++++++++++++++++---- 1 file changed, 33 insertions(+), 5 deletions(-) diff --git a/stdlib/LinearAlgebra/src/special.jl b/stdlib/LinearAlgebra/src/special.jl index 3028ecd32bb86..7dae2c4893921 100644 --- a/stdlib/LinearAlgebra/src/special.jl +++ b/stdlib/LinearAlgebra/src/special.jl @@ -114,11 +114,39 @@ for op in (:+, :-) # todo add the others that had regressions end -+(A::Bidiagonal, B::Diagonal) = Bidiagonal(broadcast(+, A.dv, B.diag), A.ev, A.uplo) --(A::Bidiagonal, B::Diagonal) = Bidiagonal(broadcast(-, A.dv, B.diag), A.ev, A.uplo) -+(A::Diagonal, B::Bidiagonal) = Bidiagonal(broadcast(+, A.diag, B.dv), B.ev, B.uplo) --(A::Diagonal, B::Bidiagonal) = Bidiagonal(broadcast(-, A.diag, B.dv), -B.ev, B.uplo) - +# specialized +/- for structured matrices. If these are removed, it falls +# back to broadcasting which has ~2-10x speed regressions. +# For the other structure matrix pairs, broadcasting works well. + ++(A::Bidiagonal, B::Diagonal) = Bidiagonal(A.dv+B.diag, A.ev, A.uplo) +-(A::Bidiagonal, B::Diagonal) = Bidiagonal(A.dv-B.diag, A.ev, A.uplo) ++(A::Diagonal, B::Bidiagonal) = Bidiagonal(A.diag+B.dv, B.ev, B.uplo) +-(A::Diagonal, B::Bidiagonal) = Bidiagonal(A.diag-B.dv, -B.ev, B.uplo) + ++(A::Diagonal, B::SymTridiagonal) = SymTridiagonal(A.diag+B.dv, B.ev) +-(A::Diagonal, B::SymTridiagonal) = SymTridiagonal(A.diag-B.dv, -B.ev) ++(A::SymTridiagonal, B::Diagonal) = SymTridiagonal(A.dv+B.diag, A.ev) +-(A::SymTridiagonal, B::Diagonal) = SymTridiagonal(A.dv-B.diag, A.ev) + ++(A::Tridiagonal, B::SymTridiagonal) = Tridiagonal(A.dl+B.ev, A.d+B.dv, A.du+B.ev) +-(A::Tridiagonal, B::SymTridiagonal) = Tridiagonal(A.dl-B.ev, A.d-B.dv, A.du-B.ev) ++(A::SymTridiagonal, B::Tridiagonal) = Tridiagonal(A.ev+B.dl, A.dv+B.d, A.ev+B.du) +-(A::SymTridiagonal, B::Tridiagonal) = Tridiagonal(A.ev-B.dl, A.dv-B.d, A.ev-B.du) + ++(A::Diagonal, B::Tridiagonal) = Tridiagonal(B.dl, A.diag+B.d, B.du) +-(A::Diagonal, B::Tridiagonal) = Tridiagonal(-B.dl, A.diag-B.d, -B.du) ++(A::Tridiagonal, B::Diagonal) = Tridiagonal(A.dl, A.d+B.diag, A.du) +-(A::Tridiagonal, B::Diagonal) = Tridiagonal(A.dl, A.d-B.diag, A.du) + ++(A::Bidiagonal, B::Tridiagonal) = Tridiagonal((A.uplo == 'U' ? (B.dl, A.dv+B.d, A.ev+B.du) : (A.ev+B.dl, A.dv+B.d, B.du))...) +-(A::Bidiagonal, B::Tridiagonal) = Tridiagonal((A.uplo == 'U' ? (-B.dl, A.dv-B.d, A.ev-B.du) : (A.ev-B.dl, A.dv-B.d, -B.du))...) ++(A::Tridiagonal, B::Bidiagonal) = Tridiagonal((B.uplo == 'U' ? (A.dl, A.d+B.dv, A.du+B.ev) : (A.dl+B.ev, A.d+B.dv, A.du))...) +-(A::Tridiagonal, B::Bidiagonal) = Tridiagonal((B.uplo == 'U' ? (A.dl, A.d-B.dv, A.du-B.ev) : (A.dl-B.ev, A.d-B.dv, A.du))...) + ++(A::Bidiagonal, B::SymTridiagonal) = Tridiagonal((A.uplo == 'U' ? (B.ev, A.dv+B.dv, A.ev+B.ev) : (A.ev+B.ev, A.dv+B.dv, B.ev))...) +-(A::Bidiagonal, B::SymTridiagonal) = Tridiagonal((A.uplo == 'U' ? (-B.ev, A.dv-B.dv, A.ev-B.ev) : (A.ev-B.ev, A.dv-B.dv, -B.ev))...) ++(A::SymTridiagonal, B::Bidiagonal) = Tridiagonal((B.uplo == 'U' ? (A.ev, A.dv+B.dv, A.ev+B.ev) : (A.ev+B.ev, A.dv+B.dv, A.ev))...) +-(A::SymTridiagonal, B::Bidiagonal) = Tridiagonal((B.uplo == 'U' ? (A.ev, A.dv-B.dv, A.ev-B.ev) : (A.ev-B.ev, A.dv-B.dv, A.ev))...) rmul!(A::AbstractTriangular, adjB::Adjoint{<:Any,<:Union{QRCompactWYQ,QRPackedQ}}) = (B = adjB.parent; rmul!(full!(A), adjoint(B))) From 050b2c27d99a6d7ced925ade4f2ebb4d7d01a391 Mon Sep 17 00:00:00 2001 From: mcognetta Date: Sat, 15 Sep 2018 16:44:13 +0900 Subject: [PATCH 15/26] Revert "merged with master" This reverts commit 3a589088a848d7c3f90f77413654bfb2a3ed11fc, reversing changes made to 0facd1db5ca30a0c1e93d3299f9dc634ef50e4b4. --- NEWS.md | 24 +- base/Enums.jl | 3 - base/abstractset.jl | 17 +- base/atomics.jl | 9 +- base/broadcast.jl | 24 - base/cartesian.jl | 2 +- base/checked.jl | 4 + base/client.jl | 2 +- base/compiler/ssair/show.jl | 6 +- base/compiler/typelimits.jl | 3 - base/docs/Docs.jl | 2 +- base/essentials.jl | 2 +- base/gmp.jl | 8 +- base/indices.jl | 33 +- base/initdefs.jl | 3 +- base/int.jl | 15 +- base/intfuncs.jl | 16 +- base/iterators.jl | 6 +- base/loading.jl | 5 +- base/math.jl | 20 +- base/multimedia.jl | 28 +- base/parse.jl | 24 +- base/printf.jl | 6 +- base/process.jl | 10 - base/promotion.jl | 10 +- base/regex.jl | 12 - base/reinterpretarray.jl | 34 +- base/reshapedarray.jl | 2 +- base/sort.jl | 60 - base/special/log.jl | 8 +- base/special/rem_pio2.jl | 2 +- base/strings/basic.jl | 2 +- base/strings/io.jl | 46 +- base/strings/substring.jl | 31 +- base/subarray.jl | 15 +- base/tuple.jl | 2 +- base/util.jl | 2 +- base/uuid.jl | 21 +- contrib/generate_precompile.jl | 150 +- contrib/julia.appdata.xml | 17 +- contrib/precompile_explicit.jl | 732 +++ deps/Versions.make | 4 +- deps/checksums/llvm-6.0.0.src.tar.xz/md5 | 1 + deps/checksums/llvm-6.0.0.src.tar.xz/sha512 | 1 + deps/checksums/llvm-6.0.1.src.tar.xz/md5 | 1 - deps/checksums/llvm-6.0.1.src.tar.xz/sha512 | 1 - deps/llvm.mk | 116 +- .../compiler_rt-3.9-glibc_2.25.90.patch | 118 + deps/patches/lldb-3.7.1.patch | 41 + deps/patches/llvm-3.9-c_api_nullptr.patch | 39 + deps/patches/llvm-3.9-osx-10.12.patch | 33 + .../llvm-3.9.0-D37576-NVPTX-sm_70.patch | 62 + deps/patches/llvm-3.9.0_D27296-libssp.patch | 47 + deps/patches/llvm-3.9.0_threads.patch | 5545 +++++++++++++++++ .../llvm-3.9.0_win64-reloc-dwarf.patch | 183 + .../llvm-4.0.0-D37576-NVPTX-sm_70.patch | 62 + deps/patches/llvm-4.0.0_threads.patch | 2032 ++++++ deps/patches/llvm-5.0-NVPTX-addrspaces.patch | 30 + deps/patches/llvm-5.0.0_threads.patch | 2072 ++++++ deps/patches/llvm-D23597_sdag_names.patch | 796 +++ deps/patches/llvm-D24300_ptx_intrinsics.patch | 506 ++ deps/patches/llvm-D25865-cmakeshlib.patch | 83 + deps/patches/llvm-D27389.patch | 66 + deps/patches/llvm-D27397.patch | 101 + .../patches/llvm-D27609-AArch64-UABS_G3.patch | 311 + .../llvm-D27629-AArch64-large_model.patch | 100 + ...lvm-D27629-AArch64-large_model_6.0.1.patch | 53 - deps/patches/llvm-D28009.patch | 68 + deps/patches/llvm-D28215_FreeBSD_shlib.patch | 13 + deps/patches/llvm-D28221-avx512.patch | 22 + ...vm-D28476-musl-targetlibraryinfo_3.9.patch | 3955 ++++++++++++ ...vm-D28476-musl-targetlibraryinfo_4.0.patch | 4480 +++++++++++++ deps/patches/llvm-D28759-loopclearance.patch | 480 ++ deps/patches/llvm-D28786-callclearance.patch | 344 + .../llvm-D28786-callclearance_4.0.patch | 344 + deps/patches/llvm-D30114.patch | 92 + deps/patches/llvm-D30478-VNCoercion.patch | 1139 ++++ deps/patches/llvm-D31524-sovers_4.0.patch | 82 + .../llvm-D32196-LIR-non-integral.patch | 95 + .../llvm-D32203-SORA-non-integral.patch | 99 + .../llvm-D32208-coerce-non-integral.patch | 137 + deps/patches/llvm-D32593.patch | 83 + .../llvm-D32623-GVN-non-integral.patch | 94 + ...llvm-D33110-codegen-prepare-inttoptr.patch | 119 + ...lvm-D33129-scevexpander-non-integral.patch | 153 + deps/patches/llvm-D33179.patch | 64 + ...vm-D37939-Mem2Reg-Also-handle-memcpy.patch | 365 ++ deps/patches/llvm-D38765-gvn_5.0.patch | 51 + ...llvm-D39297-musl-dynamiclibrary-pre5.patch | 40 + .../llvm-D39297-musl-dynamiclibrary.patch | 40 + .../llvm-D9168_argument_alignment.patch | 98 + deps/patches/llvm-NVPTX-addrspaces.patch | 30 + deps/patches/llvm-PR22923.patch | 151 + deps/patches/llvm-PR276266.patch | 51 + deps/patches/llvm-PR277939.patch | 169 + deps/patches/llvm-PR278088.patch | 224 + deps/patches/llvm-PR278321.patch | 1409 +++++ deps/patches/llvm-PR278923.patch | 69 + deps/patches/llvm-PR29010-i386-xmm.patch | 80 + deps/patches/llvm-PR36292-5.0.patch | 97 + deps/patches/llvm-PR36292.patch | 96 + deps/patches/llvm-VNCoercion-signatures.patch | 60 + deps/patches/llvm-VNCoercion-template.patch | 410 ++ deps/patches/llvm-Yet-another-fix.patch | 40 + deps/patches/llvm-arm-fix-prel31.patch | 60 + deps/patches/llvm-loadcse-addrspace_4.0.patch | 61 + deps/patches/llvm-loadcse-addrspace_5.0.patch | 104 + deps/patches/llvm-rL293230-icc17-cmake.patch | 35 + deps/patches/llvm-rL326967-aligned-load.patch | 301 - doc/make.jl | 32 +- doc/src/base/arrays.md | 2 - doc/src/base/numbers.md | 16 +- doc/src/base/sort.md | 12 +- doc/src/devdocs/backtraces.md | 4 +- doc/src/devdocs/gc-sa.md | 10 +- doc/src/devdocs/llvm.md | 2 +- doc/src/devdocs/object.md | 2 +- doc/src/index.md | 21 +- doc/src/manual/environment-variables.md | 9 - doc/src/manual/functions.md | 7 +- doc/src/manual/index.md | 39 + .../integers-and-floating-point-numbers.md | 4 +- doc/src/manual/modules.md | 11 +- doc/src/manual/noteworthy-differences.md | 2 +- doc/src/manual/parallel-computing.md | 20 +- doc/src/manual/performance-tips.md | 2 +- doc/src/manual/style-guide.md | 4 +- doc/src/manual/types.md | 3 + doc/src/manual/variables-and-scoping.md | 4 +- src/APInt-C.cpp | 6 + src/APInt-C.h | 4 + src/array.c | 15 +- src/ast.c | 101 +- src/builtins.c | 32 +- src/ccall.cpp | 72 +- src/cgutils.cpp | 29 +- src/codegen.cpp | 87 +- src/codegen_shared.h | 24 + src/datatype.c | 25 +- src/debuginfo.cpp | 14 + src/disasm.cpp | 17 + src/dump.c | 115 +- src/gc.c | 78 +- src/gc.h | 32 +- src/gf.c | 107 +- src/init.c | 3 - src/interpreter.c | 23 +- src/intrinsics.cpp | 23 + src/jitlayers.cpp | 216 +- src/jitlayers.h | 23 +- src/jlapi.c | 2 - src/jltypes.c | 56 +- src/julia-syntax.scm | 18 +- src/julia.h | 87 +- src/julia_internal.h | 51 +- src/julia_threads.h | 13 - src/llvm-alloc-opt.cpp | 27 + src/llvm-lower-handlers.cpp | 7 + src/llvm-muladd.cpp | 34 + src/llvm-ptls.cpp | 5 + src/llvm-simdloop.cpp | 4 + src/llvm-version.h | 4 +- src/macroexpand.scm | 36 +- src/method.c | 14 +- src/module.c | 49 +- src/precompile.c | 6 +- src/processor_arm.cpp | 2 +- src/processor_x86.cpp | 11 + src/rtutils.c | 26 +- src/runtime_intrinsics.c | 39 +- src/signals-unix.c | 1 + src/stackwalk.c | 2 +- src/staticdata.c | 23 +- src/subtype.c | 77 +- src/support/analyzer_annotations.h | 14 +- src/support/arraylist.h | 4 +- src/support/dtypes.h | 3 +- src/support/hashing.h | 21 +- src/support/htable.h | 16 +- src/support/ios.h | 17 +- src/support/utf8.h | 4 +- src/task.c | 15 +- src/threading.c | 17 +- src/tls.h | 4 +- src/toplevel.c | 25 +- src/typemap.c | 186 +- stdlib/Distributed/src/cluster.jl | 3 +- stdlib/Distributed/src/macros.jl | 2 +- stdlib/Distributed/test/distributed_exec.jl | 10 - stdlib/LinearAlgebra/src/LinearAlgebra.jl | 2 + stdlib/LinearAlgebra/src/cholesky.jl | 6 +- stdlib/LinearAlgebra/src/diagonal.jl | 6 +- stdlib/LinearAlgebra/src/generic.jl | 4 +- stdlib/LinearAlgebra/src/uniformscaling.jl | 3 +- stdlib/LinearAlgebra/test/ambiguous_exec.jl | 4 - stdlib/LinearAlgebra/test/matmul.jl | 8 - stdlib/LinearAlgebra/test/uniformscaling.jl | 7 - stdlib/Pkg/src/Pkg.jl | 11 +- stdlib/Pkg/src/precompile.jl | 431 ++ stdlib/REPL/docs/src/index.md | 2 +- stdlib/REPL/src/REPL.jl | 6 +- stdlib/REPL/src/Terminals.jl | 2 - stdlib/REPL/test/replcompletions.jl | 5 - stdlib/Random/src/Random.jl | 4 +- stdlib/Random/src/misc.jl | 1 - stdlib/Random/test/runtests.jl | 8 - stdlib/SparseArrays/src/sparsematrix.jl | 1 - stdlib/SparseArrays/test/sparse.jl | 6 +- stdlib/Statistics/src/Statistics.jl | 10 +- test/arrayops.jl | 8 +- test/bigint.jl | 24 - test/compiler/compiler.jl | 13 - test/core.jl | 11 - test/docs.jl | 7 - test/llvmcall.jl | 22 +- test/loading.jl | 16 - test/misc.jl | 8 - test/sets.jl | 13 - test/strings/basic.jl | 1 - test/syntax.jl | 27 - 220 files changed, 30613 insertions(+), 1977 deletions(-) create mode 100644 contrib/precompile_explicit.jl create mode 100644 deps/checksums/llvm-6.0.0.src.tar.xz/md5 create mode 100644 deps/checksums/llvm-6.0.0.src.tar.xz/sha512 delete mode 100644 deps/checksums/llvm-6.0.1.src.tar.xz/md5 delete mode 100644 deps/checksums/llvm-6.0.1.src.tar.xz/sha512 create mode 100644 deps/patches/compiler_rt-3.9-glibc_2.25.90.patch create mode 100644 deps/patches/lldb-3.7.1.patch create mode 100644 deps/patches/llvm-3.9-c_api_nullptr.patch create mode 100644 deps/patches/llvm-3.9-osx-10.12.patch create mode 100644 deps/patches/llvm-3.9.0-D37576-NVPTX-sm_70.patch create mode 100644 deps/patches/llvm-3.9.0_D27296-libssp.patch create mode 100644 deps/patches/llvm-3.9.0_threads.patch create mode 100644 deps/patches/llvm-3.9.0_win64-reloc-dwarf.patch create mode 100644 deps/patches/llvm-4.0.0-D37576-NVPTX-sm_70.patch create mode 100644 deps/patches/llvm-4.0.0_threads.patch create mode 100644 deps/patches/llvm-5.0-NVPTX-addrspaces.patch create mode 100644 deps/patches/llvm-5.0.0_threads.patch create mode 100644 deps/patches/llvm-D23597_sdag_names.patch create mode 100644 deps/patches/llvm-D24300_ptx_intrinsics.patch create mode 100644 deps/patches/llvm-D25865-cmakeshlib.patch create mode 100644 deps/patches/llvm-D27389.patch create mode 100644 deps/patches/llvm-D27397.patch create mode 100644 deps/patches/llvm-D27609-AArch64-UABS_G3.patch create mode 100644 deps/patches/llvm-D27629-AArch64-large_model.patch delete mode 100644 deps/patches/llvm-D27629-AArch64-large_model_6.0.1.patch create mode 100644 deps/patches/llvm-D28009.patch create mode 100644 deps/patches/llvm-D28215_FreeBSD_shlib.patch create mode 100644 deps/patches/llvm-D28221-avx512.patch create mode 100644 deps/patches/llvm-D28476-musl-targetlibraryinfo_3.9.patch create mode 100644 deps/patches/llvm-D28476-musl-targetlibraryinfo_4.0.patch create mode 100644 deps/patches/llvm-D28759-loopclearance.patch create mode 100644 deps/patches/llvm-D28786-callclearance.patch create mode 100644 deps/patches/llvm-D28786-callclearance_4.0.patch create mode 100644 deps/patches/llvm-D30114.patch create mode 100644 deps/patches/llvm-D30478-VNCoercion.patch create mode 100644 deps/patches/llvm-D31524-sovers_4.0.patch create mode 100644 deps/patches/llvm-D32196-LIR-non-integral.patch create mode 100644 deps/patches/llvm-D32203-SORA-non-integral.patch create mode 100644 deps/patches/llvm-D32208-coerce-non-integral.patch create mode 100644 deps/patches/llvm-D32593.patch create mode 100644 deps/patches/llvm-D32623-GVN-non-integral.patch create mode 100644 deps/patches/llvm-D33110-codegen-prepare-inttoptr.patch create mode 100644 deps/patches/llvm-D33129-scevexpander-non-integral.patch create mode 100644 deps/patches/llvm-D33179.patch create mode 100644 deps/patches/llvm-D37939-Mem2Reg-Also-handle-memcpy.patch create mode 100644 deps/patches/llvm-D38765-gvn_5.0.patch create mode 100644 deps/patches/llvm-D39297-musl-dynamiclibrary-pre5.patch create mode 100644 deps/patches/llvm-D39297-musl-dynamiclibrary.patch create mode 100644 deps/patches/llvm-D9168_argument_alignment.patch create mode 100644 deps/patches/llvm-NVPTX-addrspaces.patch create mode 100644 deps/patches/llvm-PR22923.patch create mode 100644 deps/patches/llvm-PR276266.patch create mode 100644 deps/patches/llvm-PR277939.patch create mode 100644 deps/patches/llvm-PR278088.patch create mode 100644 deps/patches/llvm-PR278321.patch create mode 100644 deps/patches/llvm-PR278923.patch create mode 100644 deps/patches/llvm-PR29010-i386-xmm.patch create mode 100644 deps/patches/llvm-PR36292-5.0.patch create mode 100644 deps/patches/llvm-PR36292.patch create mode 100644 deps/patches/llvm-VNCoercion-signatures.patch create mode 100644 deps/patches/llvm-VNCoercion-template.patch create mode 100644 deps/patches/llvm-Yet-another-fix.patch create mode 100644 deps/patches/llvm-arm-fix-prel31.patch create mode 100644 deps/patches/llvm-loadcse-addrspace_4.0.patch create mode 100644 deps/patches/llvm-loadcse-addrspace_5.0.patch create mode 100644 deps/patches/llvm-rL293230-icc17-cmake.patch delete mode 100644 deps/patches/llvm-rL326967-aligned-load.patch create mode 100644 doc/src/manual/index.md delete mode 100644 stdlib/LinearAlgebra/test/ambiguous_exec.jl create mode 100644 stdlib/Pkg/src/precompile.jl diff --git a/NEWS.md b/NEWS.md index fcbf0ef996f5f..ac7b3ae5f2605 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,15 +1,20 @@ Julia v1.0.0 Release Notes ========================== -Julia v1.0 is identical to the v0.7 release, with the exception that -it removes all deprecations and deprecation related warnings. When -upgrading a codebase from v0.6, the process is to first get the code -to work on v0.7, and fix all the deprecation warnings. Once the code -runs on v0.7 without warnings, it should be good to run on v1.0. +New language features +--------------------- + +Language changes +---------------- + +Breaking changes +---------------- -Refer to the [Release Notes for -v0.7](https://github.com/JuliaLang/julia/blob/master/HISTORY.md) for a -detailed list of changes from Julia v0.6. +Library improvements +-------------------- + +Compiler/Runtime improvements +----------------------------- Deprecated or removed --------------------- @@ -17,5 +22,8 @@ Deprecated or removed The old package manager (now called `OldPkg`) has been moved to a separate repository at https://github.com/JuliaArchive/OldPkg.jl ([#27930]) +Command-line option changes +--------------------------- + [#27930]: https://github.com/JuliaLang/julia/issues/27930 diff --git a/base/Enums.jl b/base/Enums.jl index 4c457443f678d..021c8c4bea561 100644 --- a/base/Enums.jl +++ b/base/Enums.jl @@ -44,9 +44,6 @@ f (generic function with 1 method) julia> f(apple) "I'm a Fruit with value: 1" - -julia> Fruit(1) -apple::Fruit = 1 ``` Values can also be specified inside a `begin` block, e.g. diff --git a/base/abstractset.jl b/base/abstractset.jl index 100383a126a1d..2c2ec47c0c041 100644 --- a/base/abstractset.jl +++ b/base/abstractset.jl @@ -226,15 +226,14 @@ end <=(l::AbstractSet, r::AbstractSet) = l ⊆ r function issubset(l, r) - if haslength(r) - rlen = length(r) - #This threshold was empirically determined by repeatedly - #sampling using these two methods (see #26198) - lenthresh = 70 - - if rlen > lenthresh && !isa(r, AbstractSet) - return issubset(l, Set(r)) - end + + rlen = length(r) + #This threshold was empirically determined by repeatedly + #sampling using these two methods. + lenthresh = 70 + + if rlen > lenthresh && !isa(r, AbstractSet) + return issubset(l, Set(r)) end for elt in l diff --git a/base/atomics.jl b/base/atomics.jl index 1d93f48a1def4..d98bed0742639 100644 --- a/base/atomics.jl +++ b/base/atomics.jl @@ -14,8 +14,11 @@ export atomic_max!, atomic_min!, atomic_fence +# Disable 128-bit types on 32-bit Intel systems due to LLVM problems; +# see (fixed on LLVM 3.9) # 128-bit atomics do not exist on AArch32. -if startswith(string(ARCH), "arm") +if (Base.libllvm_version < v"3.9-" && ARCH === :i686) || + startswith(string(ARCH), "arm") const inttypes = (Int8, Int16, Int32, Int64, UInt8, UInt16, UInt32, UInt64) else @@ -342,8 +345,8 @@ gc_alignment(::Type{T}) where {T} = ccall(:jl_alignment, Cint, (Csize_t,), sizeo for typ in atomictypes lt = llvmtypes[typ] ilt = llvmtypes[inttype(typ)] - rt = "$lt, $lt*" - irt = "$ilt, $ilt*" + rt = Base.libllvm_version >= v"3.6" ? "$lt, $lt*" : "$lt*" + irt = Base.libllvm_version >= v"3.6" ? "$ilt, $ilt*" : "$ilt*" @eval getindex(x::Atomic{$typ}) = llvmcall($""" %ptr = inttoptr i$WORD_SIZE %0 to $lt* diff --git a/base/broadcast.jl b/base/broadcast.jl index a95cc8bbfed29..88d83d2377e19 100644 --- a/base/broadcast.jl +++ b/base/broadcast.jl @@ -713,30 +713,6 @@ Like [`broadcast`](@ref), but store the result of Note that `dest` is only used to store the result, and does not supply arguments to `f` unless it is also listed in the `As`, as in `broadcast!(f, A, A, B)` to perform `A[:] = broadcast(f, A, B)`. - -# Examples -```jldoctest -julia> A = [1.0; 0.0]; B = [0.0; 0.0]; - -julia> broadcast!(+, B, A, (0, -2.0)); - -julia> B -2-element Array{Float64,1}: - 1.0 - -2.0 - -julia> A -2-element Array{Float64,1}: - 1.0 - 0.0 - -julia> broadcast!(+, A, A, (0, -2.0)); - -julia> A -2-element Array{Float64,1}: - 1.0 - -2.0 -``` """ broadcast!(f::Tf, dest, As::Vararg{Any,N}) where {Tf,N} = (materialize!(dest, broadcasted(f, As...)); dest) diff --git a/base/cartesian.jl b/base/cartesian.jl index 865b766664708..526cff67bd706 100644 --- a/base/cartesian.jl +++ b/base/cartesian.jl @@ -32,7 +32,7 @@ would generate: end end -If you want just a post-expression, supply [`nothing`](@ref) for the pre-expression. Using +If you want just a post-expression, supply `nothing` for the pre-expression. Using parentheses and semicolons, you can supply multi-statement expressions. """ macro nloops(N, itersym, rangeexpr, args...) diff --git a/base/checked.jl b/base/checked.jl index 9b11e13caf796..794ce295e0c60 100644 --- a/base/checked.jl +++ b/base/checked.jl @@ -64,6 +64,10 @@ if Core.sizeof(Ptr{Cvoid}) == 4 brokenSignedIntMul = Union{brokenSignedIntMul, Int64} brokenUnsignedIntMul = Union{brokenUnsignedIntMul, UInt64} end +if llvm_version < 30500 + brokenSignedIntMul = Union{brokenSignedIntMul, Int8} + brokenUnsignedIntMul = Union{brokenUnsignedIntMul, UInt8} +end const BrokenSignedInt = brokenSignedInt const BrokenUnsignedInt = brokenUnsignedInt const BrokenSignedIntMul = brokenSignedIntMul diff --git a/base/client.jl b/base/client.jl index 5c5894fc7c8a3..7f568d39d143d 100644 --- a/base/client.jl +++ b/base/client.jl @@ -56,7 +56,7 @@ function repl_cmd(cmd, out) # If it's intended to simulate `cd`, it should instead be doing # more nearly `cd $dir && printf %s \$PWD` (with appropriate quoting), # since shell `cd` does more than just `echo` the result. - dir = read(`$shell -c "printf '%s' $(shell_escape_posixly(dir))"`, String) + dir = read(`$shell -c "printf %s $(shell_escape_posixly(dir))"`, String) end cd(dir) end diff --git a/base/compiler/ssair/show.jl b/base/compiler/ssair/show.jl index 97d74be275702..c1b396f22a6ab 100644 --- a/base/compiler/ssair/show.jl +++ b/base/compiler/ssair/show.jl @@ -327,7 +327,7 @@ function show_ir(io::IO, code::IRCode, expr_type_printer=default_expr_type_print bb_idx = 1 new_nodes = code.new_nodes if any(i -> !isassigned(code.new_nodes, i), 1:length(code.new_nodes)) - printstyled(io, "ERROR: New node array has unset entry\n", color=:red) + printstyled(io, :red, "ERROR: New node array has unset entry\n") new_nodes = new_nodes[filter(i -> isassigned(code.new_nodes, i), 1:length(code.new_nodes))] end for nn in new_nodes @@ -354,7 +354,7 @@ function show_ir(io::IO, code::IRCode, expr_type_printer=default_expr_type_print if !isassigned(stmts, idx) # This is invalid, but do something useful rather # than erroring, to make debugging easier - printstyled(io, "#UNDEF\n", color=:red) + printstyled(io, :red, "#UNDEF\n") continue end stmt = stmts[idx] @@ -495,7 +495,7 @@ function show_ir(io::IO, code::CodeInfo, expr_type_printer=default_expr_type_pri if !isassigned(stmts, idx) # This is invalid, but do something useful rather # than erroring, to make debugging easier - printstyled(io, "#UNDEF\n", color=:red) + printstyled(io, :red, "#UNDEF\n") continue end stmt = stmts[idx] diff --git a/base/compiler/typelimits.jl b/base/compiler/typelimits.jl index f8220375e4518..83ca2a386b119 100644 --- a/base/compiler/typelimits.jl +++ b/base/compiler/typelimits.jl @@ -412,9 +412,6 @@ function tuplemerge(a::DataType, b::DataType) for loop_b = (false, true) for i = (lt + 1):(loop_b ? lbr : lar) ti = unwrapva(loop_b ? bp[i] : ap[i]) - while ti isa TypeVar - ti = ti.ub - end # compare (ti <-> tail), (wrapper ti <-> tail), (ti <-> wrapper tail), then (wrapper ti <-> wrapper tail) # until we find the first element that contains the other in the pair # TODO: this result would be more stable (and more associative and more commutative) diff --git a/base/docs/Docs.jl b/base/docs/Docs.jl index d409eea9a6ca8..c9de490bcb67f 100644 --- a/base/docs/Docs.jl +++ b/base/docs/Docs.jl @@ -281,7 +281,7 @@ function astname(x::Expr, ismacro::Bool) ismacro ? macroname(x) : x # Call overloading, e.g. `(a::A)(b) = b` or `function (a::A)(b) b end` should document `A(b)` elseif (isexpr(x, :function) || isexpr(x, :(=))) && isexpr(x.args[1], :call) && isexpr(x.args[1].args[1], :(::)) - return astname(x.args[1].args[1].args[end], ismacro) + return astname(x.args[1].args[1].args[2], ismacro) else n = isexpr(x, (:module, :struct)) ? 2 : 1 astname(x.args[n], ismacro) diff --git a/base/essentials.jl b/base/essentials.jl index edd7e75d2f949..3bf9ecfad81d3 100644 --- a/base/essentials.jl +++ b/base/essentials.jl @@ -795,7 +795,7 @@ isdone(itr, state...) = missing iterate(iter [, state]) -> Union{Nothing, Tuple{Any, Any}} Advance the iterator to obtain the next element. If no elements -remain, `nothing` should be returned. Otherwise, a 2-tuple of the +remain, nothing should be returned. Otherwise, a 2-tuple of the next element and the new iteration state should be returned. """ function iterate end diff --git a/base/gmp.jl b/base/gmp.jl index 4a7f6945e050d..d80182646732e 100644 --- a/base/gmp.jl +++ b/base/gmp.jl @@ -487,13 +487,13 @@ count_ones_abs(x::BigInt) = iszero(x) ? 0 : MPZ.mpn_popcount(x) divrem(x::BigInt, y::BigInt) = MPZ.tdiv_qr(x, y) -cmp(x::BigInt, y::BigInt) = sign(MPZ.cmp(x, y)) -cmp(x::BigInt, y::ClongMax) = sign(MPZ.cmp_si(x, y)) -cmp(x::BigInt, y::CulongMax) = sign(MPZ.cmp_ui(x, y)) +cmp(x::BigInt, y::BigInt) = MPZ.cmp(x, y) +cmp(x::BigInt, y::ClongMax) = MPZ.cmp_si(x, y) +cmp(x::BigInt, y::CulongMax) = MPZ.cmp_ui(x, y) cmp(x::BigInt, y::Integer) = cmp(x, big(y)) cmp(x::Integer, y::BigInt) = -cmp(y, x) -cmp(x::BigInt, y::CdoubleMax) = isnan(y) ? -1 : sign(MPZ.cmp_d(x, y)) +cmp(x::BigInt, y::CdoubleMax) = isnan(y) ? -1 : MPZ.cmp_d(x, y) cmp(x::CdoubleMax, y::BigInt) = -cmp(y, x) isqrt(x::BigInt) = MPZ.sqrt(x) diff --git a/base/indices.jl b/base/indices.jl index 800280c90f57e..adec164f080b5 100644 --- a/base/indices.jl +++ b/base/indices.jl @@ -13,32 +13,7 @@ Indices{N} = NTuple{N,AbstractUnitRange} ## Traits for array types ## abstract type IndexStyle end -""" - IndexLinear() - -Subtype of [`IndexStyle`](@ref) used to describe arrays which -are optimally indexed by one linear index. - -A linear indexing style uses one integer to describe the position in the array -(even if it's a multidimensional array) and column-major -ordering is used to access the elements. For example, -if `A` were a `(2, 3)` custom matrix type with linear indexing, -and we referenced `A[5]` (using linear style), this would -be equivalent to referencing `A[1, 3]` (since `2*1 + 3 = 5`). -See also [`IndexCartesian`](@ref). -""" struct IndexLinear <: IndexStyle end -""" - IndexCartesian() - -Subtype of [`IndexStyle`](@ref) used to describe arrays which -are optimally indexed by a Cartesian index. - -A cartesian indexing style uses multiple integers/indices to describe the position in the array. -For example, if `A` were a `(2, 3, 4)` custom matrix type with cartesian indexing, -we could reference `A[2, 1, 3]` and Julia would automatically convert this into the -correct location in the underlying memory. See also [`IndexLinear`](@ref). -""" struct IndexCartesian <: IndexStyle end """ @@ -46,14 +21,14 @@ struct IndexCartesian <: IndexStyle end IndexStyle(typeof(A)) `IndexStyle` specifies the "native indexing style" for array `A`. When -you define a new [`AbstractArray`](@ref) type, you can choose to implement -either linear indexing (with [`IndexLinear`](@ref)) or cartesian indexing. -If you decide to implement linear indexing, then you must set this trait for your array +you define a new `AbstractArray` type, you can choose to implement +either linear indexing or cartesian indexing. If you decide to +implement linear indexing, then you must set this trait for your array type: Base.IndexStyle(::Type{<:MyArray}) = IndexLinear() -The default is [`IndexCartesian()`](@ref). +The default is `IndexCartesian()`. Julia's internal indexing machinery will automatically (and invisibly) convert all indexing operations into the preferred style. This allows users diff --git a/base/initdefs.jl b/base/initdefs.jl index d93590af4d63c..0846a47534886 100644 --- a/base/initdefs.jl +++ b/base/initdefs.jl @@ -138,9 +138,8 @@ function init_load_path() unsafe_string(Base.JLOptions().project) : get(ENV, "JULIA_PROJECT", nothing)) HOME_PROJECT[] = - project == nothing ? nothing : project == "" ? nothing : - project == "@." ? current_project() : abspath(project) + project == "@." ? current_project() : project append!(empty!(LOAD_PATH), paths) end diff --git a/base/int.jl b/base/int.jl index 718542e0e13ea..e6610e9af4774 100644 --- a/base/int.jl +++ b/base/int.jl @@ -579,18 +579,9 @@ end @big_str str @big_str(str) -Parse a string into a [`BigInt`](@ref) or [`BigFloat`](@ref), -and throw an `ArgumentError` if the string is not a valid number. -For integers `_` is allowed in the string as a separator. - -# Examples -```jldoctest -julia> big"123_456" -123456 - -julia> big"7891.5" -7.8915e+03 -``` +`@big_str` parses a string into a BigInt +Throws an `ArgumentError` if the string is not a valid integer +Removes all underscores `_` from the string """ macro big_str(s) if '_' in s diff --git a/base/intfuncs.jl b/base/intfuncs.jl index 2b75f09ac62e7..c3ec78eeb31e9 100644 --- a/base/intfuncs.jl +++ b/base/intfuncs.jl @@ -543,11 +543,11 @@ function bin(x::Unsigned, pad::Int, neg::Bool) i = neg + max(pad,sizeof(x)<<3-leading_zeros(x)) a = StringVector(i) while i > neg - @inbounds a[i] = 48+(x&0x1) + a[i] = '0'+(x&0x1) x >>= 1 i -= 1 end - if neg; @inbounds a[1]=0x2d; end + if neg; a[1]='-'; end String(a) end @@ -555,11 +555,11 @@ function oct(x::Unsigned, pad::Int, neg::Bool) i = neg + max(pad,div((sizeof(x)<<3)-leading_zeros(x)+2,3)) a = StringVector(i) while i > neg - @inbounds a[i] = 48+(x&0x7) + a[i] = '0'+(x&0x7) x >>= 3 i -= 1 end - if neg; @inbounds a[1]=0x2d; end + if neg; a[1]='-'; end String(a) end @@ -567,11 +567,11 @@ function dec(x::Unsigned, pad::Int, neg::Bool) i = neg + ndigits(x, base=10, pad=pad) a = StringVector(i) while i > neg - @inbounds a[i] = 48+rem(x,10) + a[i] = '0'+rem(x,10) x = oftype(x,div(x,10)) i -= 1 end - if neg; @inbounds a[1]=0x2d; end + if neg; a[1]='-'; end String(a) end @@ -580,11 +580,11 @@ function hex(x::Unsigned, pad::Int, neg::Bool) a = StringVector(i) while i > neg d = x & 0xf - @inbounds a[i] = 48+d+39*(d>9) + a[i] = '0'+d+39*(d>9) x >>= 4 i -= 1 end - if neg; @inbounds a[1]=0x2d; end + if neg; a[1]='-'; end String(a) end diff --git a/base/iterators.jl b/base/iterators.jl index 1564ffa1be9a1..396b1744482f7 100644 --- a/base/iterators.jl +++ b/base/iterators.jl @@ -181,9 +181,9 @@ Also similar to `enumerate(A)`, except `i` will be a valid index for `A`, while `enumerate` always counts from 1 regardless of the indices of `A`. -Specifying [`IndexLinear()`](@ref) ensures that `i` will be an integer; -specifying [`IndexCartesian()`](@ref) ensures that `i` will be a -[`CartesianIndex`](@ref); specifying `IndexStyle(A)` chooses whichever has +Specifying `IndexLinear()` ensures that `i` will be an integer; +specifying `IndexCartesian()` ensures that `i` will be a +`CartesianIndex`; specifying `IndexStyle(A)` chooses whichever has been defined as the native indexing style for array `A`. Mutation of the bounds of the underlying array will invalidate this iterator. diff --git a/base/loading.jl b/base/loading.jl index 18a8765d68480..7feb1cdd26d85 100644 --- a/base/loading.jl +++ b/base/loading.jl @@ -254,9 +254,6 @@ locate_package(::Nothing) = nothing Return the path of `m.jl` file that was used to `import` module `m`, or `nothing` if `m` was not imported from a package. - -Use [`dirname`](@ref) to get the directory part and [`basename`](@ref) -to get the file name part of the path. """ function pathof(m::Module) pkgid = get(Base.module_keys, m, nothing) @@ -819,7 +816,7 @@ function require(into::Module, mod::Symbol) if where.uuid === nothing throw(ArgumentError(""" Package $mod not found in current path: - - Run `import Pkg; Pkg.add($(repr(String(mod))))` to install the $mod package. + - Run `Pkg.add($(repr(String(mod))))` to install the $mod package. """)) else s = """ diff --git a/base/math.jl b/base/math.jl index 2d58744d61b0d..6e758cf7b83e2 100644 --- a/base/math.jl +++ b/base/math.jl @@ -27,7 +27,7 @@ using Core.Intrinsics: sqrt_llvm using .Base: IEEEFloat -@noinline function throw_complex_domainerror(f::Symbol, x) +@noinline function throw_complex_domainerror(f, x) throw(DomainError(x, string("$f will only return a complex result if called with a ", "complex argument. Try $f(Complex(x))."))) end @@ -198,17 +198,17 @@ julia> log(4,2) 0.5 julia> log(-2, 3) -ERROR: DomainError with -2.0: -log will only return a complex result if called with a complex argument. Try log(Complex(x)). +ERROR: DomainError with log: +-2.0 will only return a complex result if called with a complex argument. Try -2.0(Complex(x)). Stacktrace: - [1] throw_complex_domainerror(::Symbol, ::Float64) at ./math.jl:31 + [1] throw_complex_domainerror(::Float64, ::Symbol) at ./math.jl:31 [...] julia> log(2, -3) -ERROR: DomainError with -3.0: -log will only return a complex result if called with a complex argument. Try log(Complex(x)). +ERROR: DomainError with log: +-3.0 will only return a complex result if called with a complex argument. Try -3.0(Complex(x)). Stacktrace: - [1] throw_complex_domainerror(::Symbol, ::Float64) at ./math.jl:31 + [1] throw_complex_domainerror(::Float64, ::Symbol) at ./math.jl:31 [...] ``` @@ -459,10 +459,10 @@ julia> log1p(0) 0.0 julia> log1p(-2) -ERROR: DomainError with -2.0: -log1p will only return a complex result if called with a complex argument. Try log1p(Complex(x)). +ERROR: DomainError with log1p: +-2.0 will only return a complex result if called with a complex argument. Try -2.0(Complex(x)). Stacktrace: - [1] throw_complex_domainerror(::Symbol, ::Float64) at ./math.jl:31 + [1] throw_complex_domainerror(::Float64, ::Symbol) at ./math.jl:31 [...] ``` """ diff --git a/base/multimedia.jl b/base/multimedia.jl index 9e17f05d7312b..3ec70cc12b663 100644 --- a/base/multimedia.jl +++ b/base/multimedia.jl @@ -43,8 +43,8 @@ julia> showable("img/png", rand(5)) false ``` """ -showable(::MIME{mime}, @nospecialize x) where {mime} = hasmethod(show, Tuple{IO, MIME{mime}, typeof(x)}) -showable(m::AbstractString, @nospecialize x) = showable(MIME(m), x) +showable(::MIME{mime}, x) where {mime} = hasmethod(show, Tuple{IO, MIME{mime}, typeof(x)}) +showable(m::AbstractString, x) = showable(MIME(m), x) """ show(io, mime, x) @@ -175,8 +175,8 @@ end abstract type AbstractDisplay end # it is convenient to accept strings instead of ::MIME -display(d::AbstractDisplay, mime::AbstractString, @nospecialize x) = display(d, MIME(mime), x) -display(mime::AbstractString, @nospecialize x) = display(MIME(mime), x) +display(d::AbstractDisplay, mime::AbstractString, x) = display(d, MIME(mime), x) +display(mime::AbstractString, x) = display(MIME(mime), x) """ displayable(mime) -> Bool @@ -201,12 +201,12 @@ objects are printed in the Julia REPL.) struct TextDisplay <: AbstractDisplay io::IO end -display(d::TextDisplay, M::MIME"text/plain", @nospecialize x) = show(d.io, M, x) -display(d::TextDisplay, @nospecialize x) = display(d, MIME"text/plain"(), x) +display(d::TextDisplay, M::MIME"text/plain", x) = show(d.io, M, x) +display(d::TextDisplay, x) = display(d, MIME"text/plain"(), x) # if you explicitly call display("text/foo", x), it should work on a TextDisplay: displayable(d::TextDisplay, M::MIME) = istextmime(M) -function display(d::TextDisplay, M::MIME, @nospecialize x) +function display(d::TextDisplay, M::MIME, x) displayable(d, M) || throw(MethodError(display, (d, M, x))) show(d.io, M, x) end @@ -254,7 +254,7 @@ function reinit_displays() pushdisplay(TextDisplay(stdout)) end -xdisplayable(D::AbstractDisplay, @nospecialize args...) = applicable(display, D, args...) +xdisplayable(D::AbstractDisplay, args...) = applicable(display, D, args...) """ display(x) @@ -280,7 +280,7 @@ variants, one can also supply the "raw" data in the requested MIME type by passi `x::AbstractString` (for MIME types with text-based storage, such as text/html or application/postscript) or `x::Vector{UInt8}` (for binary MIME types). """ -function display(@nospecialize x) +function display(x) for i = length(displays):-1:1 if xdisplayable(displays[i], x) try @@ -294,7 +294,7 @@ function display(@nospecialize x) throw(MethodError(display, (x,))) end -function display(m::MIME, @nospecialize x) +function display(m::MIME, x) for i = length(displays):-1:1 if xdisplayable(displays[i], m, x) try @@ -339,7 +339,7 @@ Using `redisplay` is also a hint to the backend that `x` may be redisplayed several times, and the backend may choose to defer the display until (for example) the next interactive prompt. """ -function redisplay(@nospecialize x) +function redisplay(x) for i = length(displays):-1:1 if xdisplayable(displays[i], x) try @@ -353,7 +353,7 @@ function redisplay(@nospecialize x) throw(MethodError(redisplay, (x,))) end -function redisplay(m::Union{MIME,AbstractString}, @nospecialize x) +function redisplay(m::Union{MIME,AbstractString}, x) for i = length(displays):-1:1 if xdisplayable(displays[i], m, x) try @@ -368,8 +368,8 @@ function redisplay(m::Union{MIME,AbstractString}, @nospecialize x) end # default redisplay is simply to call display -redisplay(d::AbstractDisplay, @nospecialize x) = display(d, x) -redisplay(d::AbstractDisplay, m::Union{MIME,AbstractString}, @nospecialize x) = display(d, m, x) +redisplay(d::AbstractDisplay, x) = display(d, x) +redisplay(d::AbstractDisplay, m::Union{MIME,AbstractString}, x) = display(d, m, x) ########################################################################### diff --git a/base/parse.jl b/base/parse.jl index 50b76e0577eb1..d0037ca6a6574 100644 --- a/base/parse.jl +++ b/base/parse.jl @@ -106,21 +106,14 @@ function tryparse_internal(::Type{T}, s::AbstractString, startpos::Int, endpos:: return nothing end - base = convert(T, base) - m::T = div(typemax(T) - base + 1, base) + base = convert(T,base) + m::T = div(typemax(T)-base+1,base) n::T = 0 a::Int = base <= 36 ? 10 : 36 - _0 = UInt32('0') - _9 = UInt32('9') - _A = UInt32('A') - _a = UInt32('a') - _Z = UInt32('Z') - _z = UInt32('z') while n <= m - _c = UInt32(c) - d::T = _0 <= _c <= _9 ? _c-_0 : - _A <= _c <= _Z ? _c-_A+ UInt32(10) : - _a <= _c <= _z ? _c-_a+a : base + d::T = '0' <= c <= '9' ? c-'0' : + 'A' <= c <= 'Z' ? c-'A'+10 : + 'a' <= c <= 'z' ? c-'a'+a : base if d >= base raise && throw(ArgumentError("invalid base $base digit $(repr(c)) in $(repr(SubString(s,startpos,endpos)))")) return nothing @@ -136,10 +129,9 @@ function tryparse_internal(::Type{T}, s::AbstractString, startpos::Int, endpos:: end (T <: Signed) && (n *= sgn) while !isspace(c) - _c = UInt32(c) - d::T = _0 <= _c <= _9 ? _c-_0 : - _A <= _c <= _Z ? _c-_A+ UInt32(10) : - _a <= _c <= _z ? _c-_a+a : base + d::T = '0' <= c <= '9' ? c-'0' : + 'A' <= c <= 'Z' ? c-'A'+10 : + 'a' <= c <= 'z' ? c-'a'+a : base if d >= base raise && throw(ArgumentError("invalid base $base digit $(repr(c)) in $(repr(SubString(s,startpos,endpos)))")) return nothing diff --git a/base/printf.jl b/base/printf.jl index 85a066be43bca..5010503949819 100644 --- a/base/printf.jl +++ b/base/printf.jl @@ -863,7 +863,7 @@ function decode_oct(d::Integer) @handle_zero x digits pt = i = div((sizeof(x)<<3)-leading_zeros(x)+2,3) while i > 0 - digits[i] = 48+(x&0x7) + digits[i] = '0'+(x&0x7) x >>= 3 i -= 1 end @@ -876,7 +876,7 @@ function decode_0ct(d::Integer) pt = i = div((sizeof(x)<<3)-leading_zeros(x)+5,3) digits = DIGITSs[Threads.threadid()] while i > 0 - digits[i] = 48+(x&0x7) + digits[i] = '0'+(x&0x7) x >>= 3 i -= 1 end @@ -889,7 +889,7 @@ function decode_dec(d::Integer) @handle_zero x digits pt = i = Base.ndigits0z(x) while i > 0 - digits[i] = 48+rem(x,10) + digits[i] = '0'+rem(x,10) x = div(x,10) i -= 1 end diff --git a/base/process.jl b/base/process.jl index ef690c454d263..d9b15b2e5bfe3 100644 --- a/base/process.jl +++ b/base/process.jl @@ -625,11 +625,6 @@ function open(f::Function, cmds::AbstractCmd, args...) return ret end -""" - read(command::Cmd) - -Run `command` and return the resulting output as an array of bytes. -""" function read(cmd::AbstractCmd) procs = open(cmd, "r", devnull) bytes = read(procs.out) @@ -637,11 +632,6 @@ function read(cmd::AbstractCmd) return bytes end -""" - read(command::Cmd, String) - -Run `command` and return the resulting output as a `String`. -""" read(cmd::AbstractCmd, ::Type{String}) = String(read(cmd)) """ diff --git a/base/promotion.jl b/base/promotion.jl index 319284beaaaf9..78a1954da55eb 100644 --- a/base/promotion.jl +++ b/base/promotion.jl @@ -14,11 +14,7 @@ typejoin(@nospecialize(t)) = (@_pure_meta; t) typejoin(@nospecialize(t), ts...) = (@_pure_meta; typejoin(t, typejoin(ts...))) function typejoin(@nospecialize(a), @nospecialize(b)) @_pure_meta - if isa(a, TypeVar) - return typejoin(a.ub, b) - elseif isa(b, TypeVar) - return typejoin(a, b.ub) - elseif a <: b + if a <: b return b elseif b <: a return a @@ -26,6 +22,10 @@ function typejoin(@nospecialize(a), @nospecialize(b)) return UnionAll(a.var, typejoin(a.body, b)) elseif isa(b, UnionAll) return UnionAll(b.var, typejoin(a, b.body)) + elseif isa(a, TypeVar) + return typejoin(a.ub, b) + elseif isa(b, TypeVar) + return typejoin(a, b.ub) elseif isa(a, Union) return typejoin(typejoin(a.a, a.b), b) elseif isa(b, Union) diff --git a/base/regex.jl b/base/regex.jl index 384d6ca3dfa21..41745eddd2a21 100644 --- a/base/regex.jl +++ b/base/regex.jl @@ -7,16 +7,6 @@ include("pcre.jl") const DEFAULT_COMPILER_OPTS = PCRE.UTF | PCRE.NO_UTF_CHECK | PCRE.ALT_BSUX | PCRE.UCP const DEFAULT_MATCH_OPTS = PCRE.NO_UTF_CHECK -""" - Regex(pattern[, flags]) - -A type representing a regular expression. `Regex` objects can be used to match strings -with [`match`](@ref). - -`Regex` objects can be created using the [`@r_str`](@ref) string macro. The -`Regex(pattern[, flags])` constructor is usually used if the `pattern` string needs -to be interpolated. See the documentation of the string macro for details on flags. -""" mutable struct Regex pattern::String compile_options::UInt32 @@ -91,8 +81,6 @@ listed after the ending quote, to change its behaviour: `\\s`, `\\W`, `\\w`, etc. match based on Unicode character properties. With this option, these sequences only match ASCII characters. -See `Regex` if interpolation is needed. - # Examples ```jldoctest julia> match(r"a+.*b+.*?d\$"ism, "Goodbye,\\nOh, angry,\\nBad world\\n") diff --git a/base/reinterpretarray.jl b/base/reinterpretarray.jl index 60b268465c14a..2cde44e9a386d 100644 --- a/base/reinterpretarray.jl +++ b/base/reinterpretarray.jl @@ -104,8 +104,6 @@ end _getindex_ra(a, inds[1], tail(inds)) end -@inline _memcpy!(dst, src, n) = ccall(:memcpy, Cvoid, (Ptr{UInt8}, Ptr{UInt8}, Csize_t), dst, src, n) - @inline @propagate_inbounds function _getindex_ra(a::ReinterpretArray{T,N,S}, i1::Int, tailinds::TT) where {T,N,S,TT} # Make sure to match the scalar reinterpret if that is applicable if sizeof(T) == sizeof(S) && (fieldcount(T) + fieldcount(S)) == 0 @@ -125,9 +123,11 @@ end # once it knows the data layout while nbytes_copied < sizeof(T) s[] = a.parent[ind_start + i, tailinds...] - nb = min(sizeof(S) - sidx, sizeof(T)-nbytes_copied) - _memcpy!(tptr + nbytes_copied, sptr + sidx, nb) - nbytes_copied += nb + while nbytes_copied < sizeof(T) && sidx < sizeof(S) + unsafe_store!(tptr, unsafe_load(sptr, sidx + 1), nbytes_copied + 1) + sidx += 1 + nbytes_copied += 1 + end sidx = 0 i += 1 end @@ -173,26 +173,34 @@ end # element from the original array and overwrite the relevant parts if sidx != 0 s[] = a.parent[ind_start + i, tailinds...] - nb = min(sizeof(S) - sidx, sizeof(T)) - _memcpy!(sptr + sidx, tptr, nb) - nbytes_copied += nb + while nbytes_copied < sizeof(T) && sidx < sizeof(S) + unsafe_store!(sptr, unsafe_load(tptr, nbytes_copied + 1), sidx + 1) + sidx += 1 + nbytes_copied += 1 + end a.parent[ind_start + i, tailinds...] = s[] i += 1 sidx = 0 end # Deal with the main body of elements while nbytes_copied < sizeof(T) && (sizeof(T) - nbytes_copied) > sizeof(S) - nb = min(sizeof(S), sizeof(T) - nbytes_copied) - _memcpy!(sptr, tptr + nbytes_copied, nb) - nbytes_copied += nb + while nbytes_copied < sizeof(T) && sidx < sizeof(S) + unsafe_store!(sptr, unsafe_load(tptr, nbytes_copied + 1), sidx + 1) + sidx += 1 + nbytes_copied += 1 + end a.parent[ind_start + i, tailinds...] = s[] i += 1 + sidx = 0 end # Deal with trailing partial elements if nbytes_copied < sizeof(T) s[] = a.parent[ind_start + i, tailinds...] - nb = min(sizeof(S), sizeof(T) - nbytes_copied) - _memcpy!(sptr, tptr + nbytes_copied, nb) + while nbytes_copied < sizeof(T) && sidx < sizeof(S) + unsafe_store!(sptr, unsafe_load(tptr, nbytes_copied + 1), sidx + 1) + sidx += 1 + nbytes_copied += 1 + end a.parent[ind_start + i, tailinds...] = s[] end end diff --git a/base/reshapedarray.jl b/base/reshapedarray.jl index 18b2008f2c4d1..ebd2efba68b36 100644 --- a/base/reshapedarray.jl +++ b/base/reshapedarray.jl @@ -222,7 +222,7 @@ end I = ind2sub_rs(axes(A.parent), A.mi, i) _unsafe_getindex_rs(parent(A), I) end -@inline _unsafe_getindex_rs(A, i::Integer) = (@inbounds ret = A[i]; ret) +_unsafe_getindex_rs(A, i::Integer) = (@inbounds ret = A[i]; ret) @inline _unsafe_getindex_rs(A, I) = (@inbounds ret = A[I...]; ret) @inline function setindex!(A::ReshapedArrayLF, val, index::Int) diff --git a/base/sort.jl b/base/sort.jl index e04829a3191c4..c5cd7232e65c4 100644 --- a/base/sort.jl +++ b/base/sort.jl @@ -370,20 +370,6 @@ struct InsertionSortAlg <: Algorithm end struct QuickSortAlg <: Algorithm end struct MergeSortAlg <: Algorithm end -""" - PartialQuickSort{T <: Union{Int,OrdinalRange}} - -Indicate that a sorting function should use the partial quick sort -algorithm. Partial quick sort returns the smallest `k` elements sorted from smallest -to largest, finding them and sorting them using [`QuickSort`](@ref). - -Characteristics: - * *not stable*: does not preserve the ordering of elements which - compare equal (e.g. "a" and "A" in a sort of letters which - ignores case). - * *in-place* in memory. - * *divide-and-conquer*: sort strategy similar to [`MergeSort`](@ref). -""" struct PartialQuickSort{T <: Union{Int,OrdinalRange}} <: Algorithm k::T end @@ -393,54 +379,8 @@ Base.last(a::PartialQuickSort{Int}) = a.k Base.first(a::PartialQuickSort) = first(a.k) Base.last(a::PartialQuickSort) = last(a.k) -""" - InsertionSort - -Indicate that a sorting function should use the insertion sort -algorithm. Insertion sort traverses the collection one element -at a time, inserting each element into its correct, sorted position in -the output list. - -Characteristics: - * *stable*: preserves the ordering of elements which - compare equal (e.g. "a" and "A" in a sort of letters - which ignores case). - * *in-place* in memory. - * *quadratic performance* in the number of elements to be sorted: - it is well-suited to small collections but should not be used for large ones. -""" const InsertionSort = InsertionSortAlg() -""" - QuickSort - -Indicate that a sorting function should use the quick sort -algorithm, which is *not* stable. - -Characteristics: - * *not stable*: does not preserve the ordering of elements which - compare equal (e.g. "a" and "A" in a sort of letters which - ignores case). - * *in-place* in memory. - * *divide-and-conquer*: sort strategy similar to [`MergeSort`](@ref). - * *good performance* for large collections. -""" const QuickSort = QuickSortAlg() -""" - MergeSort - -Indicate that a sorting function should use the merge sort -algorithm. Merge sort divides the collection into -subcollections and repeatedly merges them, sorting each -subcollection at each step, until the entire -collection has been recombined in sorted form. - -Characteristics: - * *stable*: preserves the ordering of elements which compare - equal (e.g. "a" and "A" in a sort of letters which ignores - case). - * *not in-place* in memory. - * *divide-and-conquer* sort strategy. -""" const MergeSort = MergeSortAlg() const DEFAULT_UNSTABLE = QuickSort diff --git a/base/special/log.jl b/base/special/log.jl index 4b6429adf7c2d..7e52c39c2a5d9 100644 --- a/base/special/log.jl +++ b/base/special/log.jl @@ -282,7 +282,7 @@ function log(x::Float64) elseif isnan(x) NaN else - throw_complex_domainerror(:log, x) + throw_complex_domainerror(x, :log) end end @@ -318,7 +318,7 @@ function log(x::Float32) elseif isnan(x) NaN32 else - throw_complex_domainerror(:log, x) + throw_complex_domainerror(x, :log) end end @@ -353,7 +353,7 @@ function log1p(x::Float64) elseif isnan(x) NaN else - throw_complex_domainerror(:log1p, x) + throw_complex_domainerror(x, :log1p) end end @@ -386,7 +386,7 @@ function log1p(x::Float32) elseif isnan(x) NaN32 else - throw_complex_domainerror(:log1p, x) + throw_complex_domainerror(x, :log1p) end end diff --git a/base/special/rem_pio2.jl b/base/special/rem_pio2.jl index c8d1018cd7881..67cb067955f7a 100644 --- a/base/special/rem_pio2.jl +++ b/base/special/rem_pio2.jl @@ -208,7 +208,7 @@ function paynehanek(x::Float64) end """ - rem_pio2_kernel(x) + rem_pio2_kernel(x, xhp) Return the remainder of `x` modulo π/2 as a double-double pair, along with a `k` such that ``k \\mod 3 == K \\mod 3`` where ``K*π/2 = x - rem``. Note, that it is diff --git a/base/strings/basic.jl b/base/strings/basic.jl index 603e13c8beee9..37117e3910846 100644 --- a/base/strings/basic.jl +++ b/base/strings/basic.jl @@ -326,7 +326,7 @@ isless(a::Symbol, b::Symbol) = cmp(a, b) < 0 The number of characters in string `s` from indices `i` through `j`. This is computed as the number of code unit indices from `i` to `j` which are valid -character indices. With only a single string argument, this computes the +character indices. Without only a single string argument, this computes the number of characters in the entire string. With `i` and `j` arguments it computes the number of indices between `i` and `j` inclusive that are valid indices in the string `s`. In addition to in-bounds values, `i` may take the diff --git a/base/strings/io.jl b/base/strings/io.jl index e2a759c473189..bd82fd37494b3 100644 --- a/base/strings/io.jl +++ b/base/strings/io.jl @@ -11,7 +11,7 @@ of values `xs` if there is one, otherwise call [`show`](@ref). The representation used by `print` includes minimal formatting and tries to avoid Julia-specific details. -Printing `nothing` is not allowed and throws an error. +Printing `nothing` is deprecated and will throw an error in the future. # Examples ```jldoctest @@ -81,7 +81,7 @@ of the buffer (in bytes). The optional keyword argument `context` can be set to `:key=>value` pair or an `IO` or [`IOContext`](@ref) object whose attributes are used for the I/O -stream passed to `f`. The optional `sizehint` is a suggested size (in bytes) +stream passed to `f`. The optional `sizehint` is a suggersted (in bytes) to allocate for the buffer used to write the string. # Examples @@ -103,48 +103,36 @@ function sprint(f::Function, args...; context=nothing, sizehint::Integer=0) String(resize!(s.data, s.size)) end -tostr_sizehint(x) = 8 +tostr_sizehint(x) = 0 tostr_sizehint(x::AbstractString) = lastindex(x) tostr_sizehint(x::Float64) = 20 tostr_sizehint(x::Float32) = 12 -function print_to_string(xs...) +function print_to_string(xs...; env=nothing) if isempty(xs) return "" end - siz = 0 - for x in xs - siz += tostr_sizehint(x) - end # specialized for performance reasons - s = IOBuffer(sizehint=siz) - for x in xs - print(s, x) + s = IOBuffer(sizehint=tostr_sizehint(xs[1])) + if env !== nothing + env_io = IOContext(s, env) + for x in xs + print(env_io, x) + end + else + for x in xs + print(s, x) + end end String(resize!(s.data, s.size)) end -function string_with_env(env, xs...) - if isempty(xs) - return "" - end - siz = 0 - for x in xs - siz += tostr_sizehint(x) - end - # specialized for performance reasons - s = IOBuffer(sizehint=siz) - env_io = IOContext(s, env) - for x in xs - print(env_io, x) - end - String(resize!(s.data, s.size)) -end +string_with_env(env, xs...) = print_to_string(xs...; env=env) """ string(xs...) -Create a string from any values, except `nothing`, using the [`print`](@ref) function. +Create a string from any values using the [`print`](@ref) function. # Examples ```jldoctest @@ -235,7 +223,7 @@ IOBuffer(s::SubString{String}) = IOBuffer(view(unsafe_wrap(Vector{UInt8}, s.stri Join an array of `strings` into a single string, inserting the given delimiter between adjacent strings. If `last` is given, it will be used instead of `delim` between the last two strings. If `io` is given, the result is written to `io` rather than returned as -as a `String`. +as a `String`. For example, # Examples ```jldoctest diff --git a/base/strings/substring.jl b/base/strings/substring.jl index 9b9e0d1e7424b..d6fba1b41c9bf 100644 --- a/base/strings/substring.jl +++ b/base/strings/substring.jl @@ -142,32 +142,19 @@ function reverse(s::Union{String,SubString{String}})::String end end -string(a::String) = String(a) -string(a::SubString{String}) = String(a) - -function string(a::Union{Char, String, SubString{String}}...) +function string(a::Union{String, SubString{String}}...) + if length(a) == 1 + return String(a[1]) + end n = 0 - for v in a - if v isa Char - n += codelen(v) - else - n += sizeof(v) - end + for str in a + n += sizeof(str) end out = _string_n(n) offs = 1 - for v in a - if v isa Char - x = bswap(reinterpret(UInt32, v)) - for j in 1:codelen(v) - unsafe_store!(pointer(out, offs), x % UInt8) - offs += 1 - x >>= 8 - end - else - unsafe_copyto!(pointer(out,offs), pointer(v), sizeof(v)) - offs += sizeof(v) - end + for str in a + unsafe_copyto!(pointer(out,offs), pointer(str), sizeof(str)) + offs += sizeof(str) end return out end diff --git a/base/subarray.jl b/base/subarray.jl index ff640b3e73db4..b74290ba26e1e 100644 --- a/base/subarray.jl +++ b/base/subarray.jl @@ -66,20 +66,7 @@ parentindices(V::SubArray) = V.indices """ parentindices(A) -Return the indices in the [`parent`](@ref) which correspond to the array view `A`. - -# Examples -```jldoctest -julia> A = [1 2; 3 4]; - -julia> V = view(A, 1, :) -2-element view(::Array{Int64,2}, 1, :) with eltype Int64: - 1 - 2 - -julia> parentindices(V) -(1, Base.Slice(Base.OneTo(2))) -``` +From an array view `A`, returns the corresponding indices in the parent. """ parentindices(a::AbstractArray) = map(OneTo, size(a)) diff --git a/base/tuple.jl b/base/tuple.jl index 518715644f677..987b6764f1401 100644 --- a/base/tuple.jl +++ b/base/tuple.jl @@ -38,7 +38,7 @@ _setindex(v, i::Integer) = () ## iterating ## -iterate(@nospecialize(t::Tuple), i::Int=1) = 1 <= i <= length(t) ? (@inbounds t[i], i+1) : nothing +iterate(t::Tuple, i::Int=1) = length(t) < i ? nothing : (t[i], i+1) keys(@nospecialize t::Tuple) = OneTo(length(t)) diff --git a/base/util.jl b/base/util.jl index 80c790770af74..e3423491aa84d 100644 --- a/base/util.jl +++ b/base/util.jl @@ -476,7 +476,7 @@ function getpass(input::TTY, output::IO, prompt::AbstractString) write(s, c) end end - return seekstart(s) + return s end else function getpass(input::TTY, output::IO, prompt::AbstractString) diff --git a/base/uuid.jl b/base/uuid.jl index 75bf21d4697cb..cf422724eb928 100644 --- a/base/uuid.jl +++ b/base/uuid.jl @@ -1,10 +1,5 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license -""" - Represents a Universally Unique Identifier (UUID). - Can be built from one `UInt128` (all byte values), two `UInt64`, or four `UInt32`. - Conversion from a string will check the UUID validity. -""" struct UUID value::UInt128 end @@ -13,18 +8,18 @@ UUID(u::NTuple{4, UInt32}) = UUID((UInt128(u[1]) << 96) | (UInt128(u[2]) << 64) (UInt128(u[3]) << 32) | UInt128(u[4])) function convert(::Type{NTuple{2, UInt64}}, uuid::UUID) - bytes = uuid.value - hi = UInt64((bytes >> 64) & 0xffffffffffffffff) - lo = UInt64(bytes & 0xffffffffffffffff) + uuid = uuid.value + hi = UInt64((uuid >> 64) & 0xffffffffffffffff) + lo = UInt64(uuid & 0xffffffffffffffff) return (hi, lo) end function convert(::Type{NTuple{4, UInt32}}, uuid::UUID) - bytes = uuid.value - hh = UInt32((bytes >> 96) & 0xffffffff) - hl = UInt32((bytes >> 64) & 0xffffffff) - lh = UInt32((bytes >> 32) & 0xffffffff) - ll = UInt32(bytes & 0xffffffff) + uuid = uuid.value + hh = UInt32((uuid >> 96) & 0xffffffff) + hl = UInt32((uuid >> 64) & 0xffffffff) + lh = UInt32((uuid >> 32) & 0xffffffff) + ll = UInt32(uuid & 0xffffffff) return (hh, hl, lh, ll) end diff --git a/contrib/generate_precompile.jl b/contrib/generate_precompile.jl index cd1778568851f..67885582754f8 100644 --- a/contrib/generate_precompile.jl +++ b/contrib/generate_precompile.jl @@ -8,7 +8,7 @@ if !isdefined(Base, :uv_eventloop) Base.reinit_stdio() end Base.include(@__MODULE__, joinpath(Sys.BINDIR, "..", "share", "julia", "test", "testhelpers", "FakePTYs.jl")) -import .FakePTYs: open_fake_pty +import .FakePTYs: with_fake_pty CTRL_C = '\x03' UP_ARROW = "\e[A" @@ -43,12 +43,6 @@ if Pkg !== nothing precompile_script *= Pkg.precompile_script end -push!(LOAD_PATH, Sys.STDLIB) -using Sockets -Sockets.__init__() -using Libdl -empty!(LOAD_PATH) - function generate_precompile_statements() start_time = time() @@ -68,94 +62,82 @@ function generate_precompile_statements() empty!(DEPOT_PATH) end - print("Generating precompile statements...") - sysimg = isempty(ARGS) ? joinpath(dirname(Sys.BINDIR), "lib", "julia", "sys." * Libdl.dlext) : ARGS[1] - - mktemp() do precompile_file, _ - # Run a repl process and replay our script - repl_output_buffer = IOBuffer() - @static if Sys.iswindows() - # Fake being cygwin - pipename = """\\\\?\\pipe\\cygwin-$("0"^16)-pty10-abcdef""" - server = listen(pipename) - slave = connect(pipename) - @assert ccall(:jl_ispty, Cint, (Ptr{Cvoid},), slave.handle) == 1 - master = accept(server) - else - slave, master = open_fake_pty() + # Create a staging area where all the loaded packages are available + PrecompileStagingArea = Module() + for (_pkgid, _mod) in Base.loaded_modules + if !(_pkgid.name in ("Main", "Core", "Base")) + eval(PrecompileStagingArea, :($(Symbol(_mod)) = $_mod)) end - done = false - withenv("JULIA_HISTORY" => tempname(), "JULIA_PROJECT" => nothing, - "TERM" => "") do - p = run(`$(julia_cmd()) -O0 --trace-compile=$precompile_file --sysimage $sysimg - --compile=all --startup-file=no --color=yes - -e 'import REPL; REPL.Terminals.is_precompiling[] = true' - -i`, - slave, slave, slave; wait=false) - readuntil(master, "julia>", keep=true) - @async begin - while true - done && break - write(repl_output_buffer, readavailable(master)) - end - end - if have_repl - for l in split(precompile_script, '\n'; keepempty=false) - write(master, l, '\n') + end + + # TODO: Implement REPL replayer for Windows + @static if !Sys.iswindows() + print("Generating precompile statements...") + sysimg = isempty(ARGS) ? joinpath(dirname(Sys.BINDIR), "lib", "julia", "sys.ji") : ARGS[1] + + mktemp() do precompile_file, _ + # Run a repl process and replay our script + stdout_accumulator, stderr_accumulator = IOBuffer(), IOBuffer() + with_fake_pty() do slave, master + with_fake_pty() do slave_err, master_err + done = false + withenv("JULIA_HISTORY" => tempname(), "JULIA_PROJECT" => nothing, + "TERM" => "") do + p = run(`$(julia_cmd()) -O0 --trace-compile=$precompile_file --sysimage $sysimg + --startup-file=no --color=yes`, + slave, slave, slave_err; wait=false) + readuntil(master, "julia>", keep=true) + for (tty, accumulator) in (master => stdout_accumulator, + master_err => stderr_accumulator) + @async begin + while true + done && break + write(accumulator, readavailable(tty)) + end + end + end + if have_repl + for l in split(precompile_script, '\n'; keepempty=false) + write(master, l, '\n') + end + end + write(master, "exit()\n") + wait(p) + done = true + end end end - # TODO Figure out why exit() on Windows doesn't exit the process - if Sys.iswindows() - print(master, "ccall(:_exit, Cvoid, (Cint,), 0)\n") - else - write(master, "exit()\n") - end - wait(p) - done = true - end - close(master) - # Check what the REPL displayed - # repl_output = String(take!(repl_output_buffer)) - # println(repl_output) + # Check what the REPL displayed + # stdout_output = String(take!(stdout_accumulator)) + # println(stdout_output) - # Extract the precompile statements from stderr - statements = Set{String}() - for statement in split(read(precompile_file, String), '\n') - occursin("Main.", statement) && continue - push!(statements, statement) - end - - if have_repl - # Seems like a reasonable number right now, adjust as needed - # comment out if debugging script - @assert length(statements) > 700 - end - - # Create a staging area where all the loaded packages are available - PrecompileStagingArea = Module() - for (_pkgid, _mod) in Base.loaded_modules - if !(_pkgid.name in ("Main", "Core", "Base")) - eval(PrecompileStagingArea, :($(Symbol(_mod)) = $_mod)) + # Extract the precompile statements from stderr + statements = Set{String}() + for statement in split(read(precompile_file, String), '\n') + occursin("Main.", statement) && continue + push!(statements, statement) end - end - # Execute the collected precompile statements - include_time = @elapsed for statement in sort(collect(statements)) - # println(statement) - try - Base.include_string(PrecompileStagingArea, statement) - catch ex - @error "Failed to precompile $statement" - rethrow(ex) + # Load the precompile statements + statements_ordered = join(sort(collect(statements)), '\n') + # println(statements_ordered) + if have_repl + # Seems like a reasonable number right now, adjust as needed + @assert length(statements) > 700 end + + Base.include_string(PrecompileStagingArea, statements_ordered) + print(" $(length(statements)) generated in ") + Base.time_print((time() - start_time) * 10^9) + println() end - print(" $(length(statements)) generated in ") - tot_time = time() - start_time - Base.time_print(tot_time * 10^9) - print(" (overhead "); Base.time_print((tot_time - include_time) * 10^9); println(")") end + # Fall back to explicit list on Windows, might as well include them + # for everyone though + Base.include(PrecompileStagingArea, "precompile_explicit.jl") + return end diff --git a/contrib/julia.appdata.xml b/contrib/julia.appdata.xml index 3d451197098b2..576d88358ee7c 100644 --- a/contrib/julia.appdata.xml +++ b/contrib/julia.appdata.xml @@ -1,15 +1,9 @@ - - org.julialang.julia - Julia - julia.desktop + + julia.desktop CC-BY-SA-3.0 MIT and LGPL-2.1+ and GPL-2.0+ - High-performance programming language for technical computing - - julia -

Julia is a high-level, high-performance dynamic programming language for @@ -27,9 +21,8 @@

- - https://julialang.org/images/julia-gnome.png - + https://julialang.org/images/julia-gnome.png https://julialang.org/ -
+ julia-dev@googlegroups.com + diff --git a/contrib/precompile_explicit.jl b/contrib/precompile_explicit.jl new file mode 100644 index 0000000000000..a95b3cb8ddc34 --- /dev/null +++ b/contrib/precompile_explicit.jl @@ -0,0 +1,732 @@ +# This file is a part of Julia. License is MIT: https://julialang.org/license + +# Steps to regenerate this file: +# 1. Remove all `precompile` calls +# 2. Rebuild system image +# 3. Start julia with `--trace-compile=precompiles.txt and do some stuff +# 5. Run `grep -v '#[0-9]' precompiles.txt >> contrib/precompile_explicit.jl` +# (filters out closures, which might have different generated names in different environments) +# This list is only used on Windows, otherwise precompile statements are generated dynamically. + +precompile(Tuple{Type{Array{Base.StackTraces.StackFrame, 1}}, UndefInitializer, Int64}) +precompile(Tuple{Type{Array{Union{Nothing, String}, 1}}, UndefInitializer, Int64}) +precompile(Tuple{Type{Base.CoreLogging.LogState}, Logging.ConsoleLogger}) +precompile(Tuple{Type{Base.Dict{Any, Any}}}) +precompile(Tuple{Type{Base.Dict{Any, Int64}}}) +precompile(Tuple{Type{Base.Dict{Char, Any}}}) +precompile(Tuple{Type{Base.Dict{Symbol, Any}}, Base.Pair{Symbol, REPL.LineEdit.Prompt}, Base.Pair{Symbol, REPL.LineEdit.Prompt}, Base.Pair{Symbol, REPL.LineEdit.Prompt}}) +precompile(Tuple{Type{Base.Dict{Symbol, Any}}, Base.Pair{Symbol, REPL.LineEdit.Prompt}, Vararg{Base.Pair{Symbol, REPL.LineEdit.Prompt}, N} where N}) +precompile(Tuple{Type{Base.Dict{Symbol, Any}}}) +precompile(Tuple{Type{Base.GC_Diff}, Base.GC_Num, Base.GC_Num}) +precompile(Tuple{Type{Base.Generator{I, F} where F where I}, typeof(Base.names), Array{Any, 1}}) +precompile(Tuple{Type{Base.IOContext{IO_t} where IO_t<:IO}, Base.GenericIOBuffer{Array{UInt8, 1}}, Base.IOStream}) +precompile(Tuple{Type{Base.IOContext{IO_t} where IO_t<:IO}, REPL.Terminals.TTYTerminal, Base.Pair{Symbol, Bool}}) +precompile(Tuple{Type{Base.InterpreterIP}, Core.CodeInfo, Ptr{Nothing}}) +precompile(Tuple{Type{Base.IteratorSize}, Array{Any, 1}}) +precompile(Tuple{Type{Base.LinearIndices{N, R} where R<:Tuple{Vararg{Base.AbstractUnitRange{Int64}, N}} where N}, Array{Method, 1}}) +precompile(Tuple{Type{Base.MIME{Symbol("text/plain")}}}) +precompile(Tuple{Type{Base.Multimedia.TextDisplay}, Base.TTY}) +precompile(Tuple{Type{Base.Order.Perm{O, V} where V<:(AbstractArray{T, 1} where T) where O<:Base.Order.Ordering}, Base.Order.ForwardOrdering, Array{Tuple{Float64, Int64}, 1}}) +precompile(Tuple{Type{Base.Pair{A, B} where B where A}, Base.PkgId, UInt64}) +precompile(Tuple{Type{Base.Pair{A, B} where B where A}, Int64, Int64}) +precompile(Tuple{Type{Base.PkgId}, String}) +precompile(Tuple{Type{Base.StackTraces.StackFrame}, Symbol, Symbol, Int64, Core.CodeInfo, Bool, Bool, Int64}) +precompile(Tuple{Type{Base.StackTraces.StackFrame}, Symbol, Symbol, Int64, Core.MethodInstance, Bool, Bool, Ptr{Nothing}}) +precompile(Tuple{Type{Base.StackTraces.StackFrame}, Symbol, Symbol, Int64, Nothing, Bool, Bool, Ptr{Nothing}}) +precompile(Tuple{Type{Base.SubString{T} where T<:AbstractString}, String, Int64}) +precompile(Tuple{Type{Base.Val{2}}}) +precompile(Tuple{Type{Base.Val{3}}}) +precompile(Tuple{Type{Logging.ConsoleLogger}, Base.IOStream}) +precompile(Tuple{Type{Logging.ConsoleLogger}, Base.TTY}) +precompile(Tuple{Type{Markdown.Header{1}}, Array{Any, 1}}) +precompile(Tuple{Type{Markdown.MD}, Markdown.MD, Markdown.MD}) +precompile(Tuple{Type{NamedTuple{(), T} where T<:Tuple}, Tuple{}}) +precompile(Tuple{Type{NamedTuple{(:bold, :color), Tuple{Bool, Symbol}}}, Tuple{Bool, Symbol}}) +precompile(Tuple{Type{NamedTuple{(:bold, :color), T} where T<:Tuple}, Tuple{Bool, Symbol}}) +precompile(Tuple{Type{NamedTuple{(:create,), T} where T<:Tuple}, Tuple{Bool}}) +precompile(Tuple{Type{NamedTuple{(:merge,), T} where T<:Tuple}, Tuple{Bool}}) +precompile(Tuple{Type{NamedTuple{(:prompt_prefix, :prompt_suffix, :complete, :sticky), Tuple{String, String, Pkg.REPLMode.PkgCompletionProvider, Bool}}}, Tuple{String, String, Pkg.REPLMode.PkgCompletionProvider, Bool}}) +precompile(Tuple{Type{NamedTuple{(:prompt_prefix, :prompt_suffix, :complete, :sticky), T} where T<:Tuple}, Tuple{String, String, Pkg.REPLMode.PkgCompletionProvider, Bool}}) +precompile(Tuple{Type{NamedTuple{(:prompt_prefix, :prompt_suffix, :repl, :complete, :on_enter), Tuple{String, typeof(Base.input_color), REPL.LineEditREPL, REPL.REPLCompletionProvider, typeof(REPL.return_callback)}}}, Tuple{String, typeof(Base.input_color), REPL.LineEditREPL, REPL.REPLCompletionProvider, typeof(REPL.return_callback)}}) +precompile(Tuple{Type{NamedTuple{(:prompt_prefix, :prompt_suffix, :repl, :complete, :on_enter), T} where T<:Tuple}, Tuple{String, typeof(Base.input_color), REPL.LineEditREPL, REPL.REPLCompletionProvider, typeof(REPL.return_callback)}}) +precompile(Tuple{Type{NamedTuple{(:stderr,), Tuple{Base.IOStream}}}, Tuple{Base.IOStream}}) +precompile(Tuple{Type{REPL.LineEditREPL}, REPL.Terminals.TTYTerminal, Bool, Bool}) +precompile(Tuple{Type{REPL.LineEditREPL}, REPL.Terminals.TTYTerminal, Bool, String, String, String, String, String, Bool, Bool, Bool, Bool}) +precompile(Tuple{Type{REPL.REPLDisplay{R} where R<:REPL.AbstractREPL}, REPL.LineEditREPL}) +precompile(Tuple{Type{REPL.Terminals.TTYTerminal}, String, Base.PipeEndpoint, Base.TTY, Base.IOStream}) +precompile(Tuple{Type{REPL.Terminals.TTYTerminal}, String, Base.TTY, Base.TTY, Base.IOStream}) +precompile(Tuple{Type{REPL.Terminals.TTYTerminal}, String, Base.TTY, Base.TTY, Base.TTY}) +precompile(Tuple{Type{String}, Array{UInt8, 1}}) +precompile(Tuple{Type{UInt32}, UInt8}) +precompile(Tuple{Type{UnionAll}, TypeVar, Any}) +precompile(Tuple{getfield(Base, Symbol("#@time")), LineNumberNode, Module, Expr}) +precompile(Tuple{getfield(Base, Symbol("#kw##_spawn")), NamedTuple{(:chain,), Tuple{Nothing}}, typeof(Base._spawn), Base.Cmd, Tuple{Base.Pipe, Base.TTY, Base.IOStream}}) +precompile(Tuple{getfield(Base, Symbol("#kw##pipeline")), NamedTuple{(:stderr,), Tuple{Base.IOStream}}, typeof(Base.pipeline), Base.Cmd}) +precompile(Tuple{getfield(Base, Symbol("#kw##printstyled")), NamedTuple{(:bold, :color), Tuple{Bool, Symbol}}, typeof(Base.printstyled), Base.IOContext{Base.GenericIOBuffer{Array{UInt8, 1}}}, String, String}) +precompile(Tuple{getfield(Base, Symbol("#kw##printstyled")), NamedTuple{(:bold, :color), Tuple{Bool, Symbol}}, typeof(Base.printstyled), Base.IOContext{Base.GenericIOBuffer{Array{UInt8, 1}}}, String}) +precompile(Tuple{getfield(Base, Symbol("#kw##printstyled")), NamedTuple{(:bold, :color), Tuple{Bool, Symbol}}, typeof(Base.printstyled), REPL.Terminals.TTYTerminal, String}) +precompile(Tuple{getfield(Base, Symbol("#kw##printstyled")), NamedTuple{(:color,), Tuple{Symbol}}, typeof(Base.printstyled), Base.IOContext{Base.GenericIOBuffer{Array{UInt8, 1}}}, String}) +precompile(Tuple{getfield(Base, Symbol("#kw##show_trace_entry")), NamedTuple{(:prefix,), Tuple{String}}, typeof(Base.show_trace_entry), Base.IOContext{REPL.Terminals.TTYTerminal}, Base.StackTraces.StackFrame, Int64}) +precompile(Tuple{getfield(Base, Symbol("#kw##sort!")), NamedTuple{(:by,), Tuple{typeof(REPL.REPLCompletions.completion_text)}}, typeof(Base.sort!), Array{REPL.REPLCompletions.Completion, 1}}) +precompile(Tuple{getfield(Base, Symbol("#kw##with_output_color")), NamedTuple{(:bold,), Tuple{Bool}}, typeof(Base.with_output_color), typeof(Base.print), Symbol, Base.IOContext{Base.GenericIOBuffer{Array{UInt8, 1}}}, String, String}) +precompile(Tuple{getfield(Base.Cartesian, Symbol("#@ncall")), LineNumberNode, Module, Int64, Symbol, Symbol, Expr}) +precompile(Tuple{getfield(Base.Cartesian, Symbol("#@nexprs")), LineNumberNode, Module, Int64, Expr}) +precompile(Tuple{getfield(Base.Meta, Symbol("#kw##parse")), NamedTuple{(:raise, :depwarn), Tuple{Bool, Bool}}, typeof(Base.Meta.parse), String, Int64}) +precompile(Tuple{getfield(Core, Symbol("#@doc")), LineNumberNode, Module, Symbol}) +precompile(Tuple{getfield(Core, Symbol("#kw#Type")), NamedTuple{(:prompt_prefix, :prompt_suffix, :complete, :sticky), Tuple{String, String, Pkg.REPLMode.PkgCompletionProvider, Bool}}, Type{REPL.LineEdit.Prompt}, typeof(Pkg.REPLMode.promptf)}) +precompile(Tuple{getfield(Core, Symbol("#kw#Type")), NamedTuple{(:prompt_prefix, :prompt_suffix, :repl, :complete, :on_enter), Tuple{String, typeof(Base.input_color), REPL.LineEditREPL, REPL.REPLCompletionProvider, typeof(REPL.return_callback)}}, Type{REPL.LineEdit.Prompt}, String}) +precompile(Tuple{getfield(REPL, Symbol("#@repl")), LineNumberNode, Module, Base.TTY, Symbol}) +precompile(Tuple{getfield(REPL, Symbol("#kw##printmatches")), NamedTuple{(:cols,), Tuple{Int64}}, typeof(REPL.printmatches), Base.TTY, String, Array{String, 1}}) +precompile(Tuple{getfield(REPL.LineEdit, Symbol("#kw##add_nested_key!")), NamedTuple{(:override,), Tuple{Bool}}, typeof(REPL.LineEdit.add_nested_key!), Base.Dict{Char, Any}, Char, Function}) +precompile(Tuple{getfield(REPL.LineEdit, Symbol("#kw##refresh_multi_line")), NamedTuple{(:beeping,), Tuple{Bool}}, typeof(REPL.LineEdit.refresh_multi_line), REPL.Terminals.TTYTerminal, REPL.LineEdit.PromptState}) +precompile(Tuple{typeof(Base.:(!=)), Char, Char}) +precompile(Tuple{typeof(Base.:(!=)), Int64, Int64}) +precompile(Tuple{typeof(Base.:(!=)), Int8, Int64}) +precompile(Tuple{typeof(Base.:(!=)), Nothing, Nothing}) +precompile(Tuple{typeof(Base.:(!=)), REPL.LineEdit.Prompt, Nothing}) +precompile(Tuple{typeof(Base.:(!=)), String, Nothing}) +precompile(Tuple{typeof(Base.:(!=)), String, String}) +precompile(Tuple{typeof(Base.:(!=)), UInt8, UInt8}) +precompile(Tuple{typeof(Base.:(*)), Base.SubString{String}, String}) +precompile(Tuple{typeof(Base.:(+)), Int64, Bool}) +precompile(Tuple{typeof(Base.:(<<)), UInt32, Int64}) +precompile(Tuple{typeof(Base.:(<=)), Int64, Int64}) +precompile(Tuple{typeof(Base.:(==)), Base.Multimedia.TextDisplay, REPL.REPLDisplay{REPL.LineEditREPL}}) +precompile(Tuple{typeof(Base.:(==)), Int8, Int64}) +precompile(Tuple{typeof(Base.:(==)), Module, Module}) +precompile(Tuple{typeof(Base.:(==)), Nothing, String}) +precompile(Tuple{typeof(Base.:(==)), REPL.REPLDisplay{REPL.LineEditREPL}, REPL.REPLDisplay{REPL.LineEditREPL}}) +precompile(Tuple{typeof(Base.:(>)), UInt64, Int64}) +precompile(Tuple{typeof(Base.:(^)), Char, Int64}) +precompile(Tuple{typeof(Base.:(|>)), Array{Any, 1}, typeof(Base.unique)}) +precompile(Tuple{typeof(Base.:(|>)), Array{Any, 1}, typeof(REPL.filtervalid)}) +precompile(Tuple{typeof(Base.CoreLogging.global_logger), Logging.ConsoleLogger}) +precompile(Tuple{typeof(Base.CoreLogging.global_logger)}) +precompile(Tuple{typeof(Base.CoreLogging.logmsg_shim), Int64, String, Nothing, Symbol, Symbol, Symbol, Int64, Array{Any, 1}}) +precompile(Tuple{typeof(Base.Docs.catdoc), Markdown.MD, Markdown.MD}) +precompile(Tuple{typeof(Base.Docs.doc), Base.Docs.Binding, Type{Union{}}}) +precompile(Tuple{typeof(Base.Docs.doc), Base.Docs.Binding}) +precompile(Tuple{typeof(Base.Docs.docm), LineNumberNode, Module, Symbol}) +precompile(Tuple{typeof(Base.Docs.formatdoc), Base.GenericIOBuffer{Array{UInt8, 1}}, Base.Docs.DocStr, String}) +precompile(Tuple{typeof(Base.Filesystem.basename), String}) +precompile(Tuple{typeof(Base.Filesystem.isdir), String}) +precompile(Tuple{typeof(Base.Filesystem.pwd)}) +precompile(Tuple{typeof(Base.Filesystem.splitdir), String}) +precompile(Tuple{typeof(Base.Filesystem.splitext), String}) +precompile(Tuple{typeof(Base.Meta.isexpr), Symbol, Symbol, Int64}) +precompile(Tuple{typeof(Base.Meta.parse), String}) +precompile(Tuple{typeof(Base.Multimedia.display), Int64}) +precompile(Tuple{typeof(Base.Multimedia.display), Markdown.MD}) +precompile(Tuple{typeof(Base.Multimedia.display), REPL.REPLDisplay{REPL.LineEditREPL}, Array{Float64, 1}}) +precompile(Tuple{typeof(Base.Multimedia.display), REPL.REPLDisplay{REPL.LineEditREPL}, Array{Float64, 2}}) +precompile(Tuple{typeof(Base.Multimedia.display), REPL.REPLDisplay{REPL.LineEditREPL}, Array{Int64, 1}}) +precompile(Tuple{typeof(Base.Multimedia.display), REPL.REPLDisplay{REPL.LineEditREPL}, Float64}) +precompile(Tuple{typeof(Base.Multimedia.display), REPL.REPLDisplay{REPL.LineEditREPL}, Int64}) +precompile(Tuple{typeof(Base.Multimedia.display), REPL.REPLDisplay{REPL.LineEditREPL}, Markdown.MD}) +precompile(Tuple{typeof(Base.Multimedia.display), REPL.REPLDisplay{REPL.LineEditREPL}, String}) +precompile(Tuple{typeof(Base.Multimedia.pushdisplay), REPL.REPLDisplay{REPL.LineEditREPL}}) +precompile(Tuple{typeof(Base.Order.ord), typeof(Base.isless), typeof(Base.identity), Nothing, Base.Order.ForwardOrdering}) +precompile(Tuple{typeof(Base.Printf.decode_dec), Base.TTY, Float64, String, Int64, Int64, Char}) +precompile(Tuple{typeof(Base.StackTraces.lookup), Base.InterpreterIP}) +precompile(Tuple{typeof(Base.Unicode.textwidth), String}) +precompile(Tuple{typeof(Base.__atreplinit), REPL.LineEditREPL}) +precompile(Tuple{typeof(Base.__precompile__)}) +precompile(Tuple{typeof(Base._atexit)}) +precompile(Tuple{typeof(Base._compute_eltype), Type{Tuple{Int64, String}}}) +precompile(Tuple{typeof(Base._iterate), Base.Dict{Symbol, Any}, Int64}) +precompile(Tuple{typeof(Base._promote_typejoin), Type{Int64}, Type{String}}) +precompile(Tuple{typeof(Base._promote_typejoin), Type{Nothing}, Type{String}}) +precompile(Tuple{typeof(Base._promote_typejoin), Type{Union{}}, Type{Int64}}) +precompile(Tuple{typeof(Base._reformat_bt), Array{Ptr{Nothing}, 1}, Array{Any, 1}}) +precompile(Tuple{typeof(Base._similar_for), Array{Any, 1}, Type{String}, Base.Generator{Array{Any, 1}, typeof(Base.string)}, Base.HasShape{1}}) +precompile(Tuple{typeof(Base._similar_for), Array{Base.Docs.DocStr, 1}, Type{Markdown.MD}, Base.Generator{Array{Base.Docs.DocStr, 1}, typeof(Base.Docs.parsedoc)}, Base.HasShape{1}}) +precompile(Tuple{typeof(Base._similar_for), Array{Union{Ptr{Nothing}, Base.InterpreterIP}, 1}, Type{Array{Base.StackTraces.StackFrame, 1}}, Base.Generator{Array{Union{Ptr{Nothing}, Base.InterpreterIP}, 1}, typeof(Base.StackTraces.lookup)}, Base.HasShape{1}}) +precompile(Tuple{typeof(Base._spawn), Base.CmdRedirect, Tuple{Base.Pipe, Base.TTY, Base.IOStream}}) +precompile(Tuple{typeof(Base._start)}) +precompile(Tuple{typeof(Base._typed_vcat), Type{Any}, Tuple{Array{Symbol, 1}, Array{Symbol, 1}, Array{Symbol, 1}, Array{Symbol, 1}, Array{String, 1}}}) +precompile(Tuple{typeof(Base._uv_hook_close), Base.PipeEndpoint}) +precompile(Tuple{typeof(Base._uv_hook_close), Base.Process}) +precompile(Tuple{typeof(Base._uv_hook_close), Base.Timer}) +precompile(Tuple{typeof(Base.alignment), Base.IOContext{REPL.Terminals.TTYTerminal}, Array{Float64, 1}, Base.OneTo{Int64}, Base.OneTo{Int64}, Int64, Int64, Int64}) +precompile(Tuple{typeof(Base.alignment), Base.IOContext{REPL.Terminals.TTYTerminal}, Array{Float64, 2}, Base.OneTo{Int64}, Base.OneTo{Int64}, Int64, Int64, Int64}) +precompile(Tuple{typeof(Base.alignment), Base.IOContext{REPL.Terminals.TTYTerminal}, Array{Int64, 1}, Base.OneTo{Int64}, Base.OneTo{Int64}, Int64, Int64, Int64}) +precompile(Tuple{typeof(Base.alloc_buf_hook), Base.PipeEndpoint, UInt64}) +precompile(Tuple{typeof(Base.alloc_buf_hook), Base.TTY, UInt64}) +precompile(Tuple{typeof(Base.append!), Array{String, 1}, Array{String, 1}}) +precompile(Tuple{typeof(Base.arg_gen), Base.Cmd}) +precompile(Tuple{typeof(Base.arg_gen), String}) +precompile(Tuple{typeof(Base.axes), Array{Any, 1}}) +precompile(Tuple{typeof(Base.bytesavailable), Base.GenericIOBuffer{Array{UInt8, 1}}}) +precompile(Tuple{typeof(Base.catch_backtrace)}) +precompile(Tuple{typeof(Base.check_open), Base.TTY}) +precompile(Tuple{typeof(Base.close), Base.Pipe}) +precompile(Tuple{typeof(Base.collect_similar), Array{Any, 1}, Base.Generator{Array{Any, 1}, typeof(Base.names)}}) +precompile(Tuple{typeof(Base.collect_to_with_first!), Array{Array{Base.StackTraces.StackFrame, 1}, 1}, Array{Base.StackTraces.StackFrame, 1}, Base.Generator{Array{Union{Ptr{Nothing}, Base.InterpreterIP}, 1}, typeof(Base.StackTraces.lookup)}, Int64}) +precompile(Tuple{typeof(Base.collect_to_with_first!), Array{Markdown.MD, 1}, Markdown.MD, Base.Generator{Array{Base.Docs.DocStr, 1}, typeof(Base.Docs.parsedoc)}, Int64}) +precompile(Tuple{typeof(Base.collect_to_with_first!), Array{String, 1}, String, Base.Generator{Array{Any, 1}, typeof(Base.string)}, Int64}) +precompile(Tuple{typeof(Base.collect_to_with_first!), Array{String, 1}, String, Base.Generator{Array{REPL.REPLCompletions.Completion, 1}, typeof(REPL.REPLCompletions.completion_text)}, Int64}) +precompile(Tuple{typeof(Base.convert), Type{Array{String, 1}}, Array{Any, 1}}) +precompile(Tuple{typeof(Base.convert), Type{Base.Dict{Char, V} where V}, Base.Dict{Char, Any}}) +precompile(Tuple{typeof(Base.convert), Type{Base.Dict{K, V} where V where K}, Base.Dict{String, Any}}) +precompile(Tuple{typeof(Base.convert), Type{Base.GenericIOBuffer{Array{UInt8, 1}}}, Base.GenericIOBuffer{Array{UInt8, 1}}}) +precompile(Tuple{typeof(Base.convert), Type{Bool}, Bool}) +precompile(Tuple{typeof(Base.convert), Type{Int64}, Int64}) +precompile(Tuple{typeof(Base.convert), Type{Ptr{Nothing}}, Ptr{Nothing}}) +precompile(Tuple{typeof(Base.convert), Type{Ptr{Nothing}}, Ptr{UInt8}}) +precompile(Tuple{typeof(Base.convert), Type{REPL.LineEdit.InputAreaState}, REPL.LineEdit.InputAreaState}) +precompile(Tuple{typeof(Base.convert), Type{REPL.LineEdit.MIState}, REPL.LineEdit.MIState}) +precompile(Tuple{typeof(Base.convert), Type{REPL.LineEdit.Prompt}, REPL.LineEdit.Prompt}) +precompile(Tuple{typeof(Base.convert), Type{Union{Base.UUID, Bool}}, Bool}) +precompile(Tuple{typeof(Base.convert), Type{Union{Function, String}}, String}) +precompile(Tuple{typeof(Base.convert), Type{Union{Nothing, REPL.LineEdit.Prompt}}, REPL.LineEdit.Prompt}) +precompile(Tuple{typeof(Base.convert), Type{Union{Nothing, Type{T} where T}}, Nothing}) +precompile(Tuple{typeof(Base.copy), Array{Any, 1}}) +precompile(Tuple{typeof(Base.copy), Base.GenericIOBuffer{Array{UInt8, 1}}}) +precompile(Tuple{typeof(Base.copymutable), Array{String, 1}}) +precompile(Tuple{typeof(Base.copyto!), Array{Union{Nothing, String}, 1}, Int64, Array{Nothing, 1}, Int64, Int64}) +precompile(Tuple{typeof(Base.delete!), Base.Set{Any}, Char}) +precompile(Tuple{typeof(Base.diff_names), Tuple{Symbol, Symbol, Symbol, Symbol, Symbol}, Tuple{Symbol, Symbol, Symbol, Symbol, Symbol, Symbol, Symbol, Symbol, Symbol}}) +precompile(Tuple{typeof(Base.diff_names), Tuple{Symbol, Symbol, Symbol}, Tuple{Symbol, Symbol, Symbol, Symbol, Symbol}}) +precompile(Tuple{typeof(Base.diff_names), Tuple{Symbol}, Tuple{Symbol, Symbol, Symbol, Symbol, Symbol, Symbol, Symbol}}) +precompile(Tuple{typeof(Base.diff_names), Tuple{Symbol}, Tuple{Symbol}}) +precompile(Tuple{typeof(Base.display_error), REPL.Terminals.TTYTerminal, ErrorException, Array{Union{Ptr{Nothing}, Base.InterpreterIP}, 1}}) +precompile(Tuple{typeof(Base.display_error), REPL.Terminals.TTYTerminal, MethodError, Array{Union{Ptr{Nothing}, Base.InterpreterIP}, 1}}) +precompile(Tuple{typeof(Base.display_error), REPL.Terminals.TTYTerminal, UndefVarError, Array{Union{Ptr{Nothing}, Base.InterpreterIP}, 1}}) +precompile(Tuple{typeof(Base.displaysize), Base.IOStream}) +precompile(Tuple{typeof(Base.displaysize), Base.TTY}) +precompile(Tuple{typeof(Base.displaysize), REPL.Terminals.TTYTerminal}) +precompile(Tuple{typeof(Base.divrem), Int64, Int64}) +precompile(Tuple{typeof(Base.eachline), String}) +precompile(Tuple{typeof(Base.empty!), Array{Base.Pair{Base.PkgId, UInt64}, 1}}) +precompile(Tuple{typeof(Base.ensure_rescheduled), Task}) +precompile(Tuple{typeof(Base.eof), Base.PipeEndpoint}) +precompile(Tuple{typeof(Base.eof), Base.TTY}) +precompile(Tuple{typeof(Base.error), String}) +precompile(Tuple{typeof(Base.findlast), String, String}) +precompile(Tuple{typeof(Base.findprev), Base.Fix2{typeof(Base.in), Array{Char, 1}}, String, Int64}) +precompile(Tuple{typeof(Base.findprev), String, String, Int64}) +precompile(Tuple{typeof(Base.first), Base.OneTo{Int64}}) +precompile(Tuple{typeof(Base.first), Base.UnitRange{Int64}}) +precompile(Tuple{typeof(Base.firstindex), String}) +precompile(Tuple{typeof(Base.flush), Base.IOStream}) +precompile(Tuple{typeof(Base.gc_alloc_count), Base.GC_Diff}) +precompile(Tuple{typeof(Base.gc_num)}) +precompile(Tuple{typeof(Base.get), Base.Dict{Char, Any}, Char, Nothing}) +precompile(Tuple{typeof(Base.getindex), Array{AbstractString, 1}, Base.UnitRange{Int64}}) +precompile(Tuple{typeof(Base.getindex), Array{AbstractString, 1}, Int64}) +precompile(Tuple{typeof(Base.getindex), Array{Any, 1}, Int32}) +precompile(Tuple{typeof(Base.getindex), Array{Int32, 1}, UInt64}) +precompile(Tuple{typeof(Base.getindex), Array{String, 1}, Int64}) +precompile(Tuple{typeof(Base.getindex), Array{UInt8, 1}, Int64}) +precompile(Tuple{typeof(Base.getindex), Base.Dict{Any, Any}, Char}) +precompile(Tuple{typeof(Base.getindex), Base.Dict{String, Any}, String}) +precompile(Tuple{typeof(Base.getindex), Base.Dict{Symbol, Any}, Symbol}) +precompile(Tuple{typeof(Base.getindex), Core.SimpleVector, Base.UnitRange{Int64}}) +precompile(Tuple{typeof(Base.getindex), String, Base.UnitRange{Int64}}) +precompile(Tuple{typeof(Base.getindex), Tuple{Base.GenericIOBuffer{Array{UInt8, 1}}, Int64}, Int64}) +precompile(Tuple{typeof(Base.getindex), Tuple{Base.StackTraces.StackFrame, Int64}, Int64}) +precompile(Tuple{typeof(Base.getindex), Tuple{Int64, Int64}, Int64}) +precompile(Tuple{typeof(Base.getindex), Tuple{Symbol, Symbol, Symbol}, Base.UnitRange{Int64}}) +precompile(Tuple{typeof(Base.getindex), Tuple{Symbol}, Base.UnitRange{Int64}}) +precompile(Tuple{typeof(Base.getindex), Tuple{Symbol}, Int64}) +precompile(Tuple{typeof(Base.getproperty), Base.CoreLogging.LogState, Symbol}) +precompile(Tuple{typeof(Base.getproperty), Base.GC_Diff, Symbol}) +precompile(Tuple{typeof(Base.getproperty), Base.GenericIOBuffer{Array{UInt8, 1}}, Symbol}) +precompile(Tuple{typeof(Base.getproperty), Base.Process, Symbol}) +precompile(Tuple{typeof(Base.getproperty), Base.StackTraces.StackFrame, Symbol}) +precompile(Tuple{typeof(Base.getproperty), Core.CodeInfo, Symbol}) +precompile(Tuple{typeof(Base.getproperty), Core.LineInfoNode, Symbol}) +precompile(Tuple{typeof(Base.getproperty), Core.MethodTable, Symbol}) +precompile(Tuple{typeof(Base.getproperty), Method, Symbol}) +precompile(Tuple{typeof(Base.getproperty), REPL.LineEdit.HistoryPrompt, Symbol}) +precompile(Tuple{typeof(Base.getproperty), REPL.LineEdit.ModalInterface, Symbol}) +precompile(Tuple{typeof(Base.getproperty), REPL.LineEdit.PrefixHistoryPrompt, Symbol}) +precompile(Tuple{typeof(Base.getproperty), REPL.LineEdit.PrefixSearchState, Symbol}) +precompile(Tuple{typeof(Base.getproperty), REPL.LineEdit.Prompt, Symbol}) +precompile(Tuple{typeof(Base.getproperty), REPL.LineEdit.PromptState, Symbol}) +precompile(Tuple{typeof(Base.getproperty), REPL.LineEdit.SearchState, Symbol}) +precompile(Tuple{typeof(Base.getproperty), REPL.LineEditREPL, Symbol}) +precompile(Tuple{typeof(Base.getproperty), REPL.Options, Symbol}) +precompile(Tuple{typeof(Base.getproperty), REPL.REPLHistoryProvider, Symbol}) +precompile(Tuple{typeof(Base.getproperty), REPL.Terminals.TTYTerminal, Symbol}) +precompile(Tuple{typeof(Base.haskey), Base.Dict{String, Any}, String}) +precompile(Tuple{typeof(Base.haskey), Base.Dict{Symbol, Any}, Symbol}) +precompile(Tuple{typeof(Base.haskey), Base.Dict{Symbol, Function}, Symbol}) +precompile(Tuple{typeof(Base.haskey), Base.IdDict{Any, Any}, Base.Docs.Binding}) +precompile(Tuple{typeof(Base.hvcat), Tuple{Int64, Int64}, Float64, Float64, Float64, Float64}) +precompile(Tuple{typeof(Base.identity), Char}) +precompile(Tuple{typeof(Base.in), Char, Tuple{Char, Char, Char}}) +precompile(Tuple{typeof(Base.in), String, Base.Set{Any}}) +precompile(Tuple{typeof(Base.in), String, Tuple{String, String}}) +precompile(Tuple{typeof(Base.in), Symbol, Base.Set{Any}}) +precompile(Tuple{typeof(Base.incomplete_tag), Symbol}) +precompile(Tuple{typeof(Base.indexed_iterate), Base.Pair{String, String}, Int64, Int64}) +precompile(Tuple{typeof(Base.indexed_iterate), Base.Pair{String, String}, Int64}) +precompile(Tuple{typeof(Base.indexed_iterate), Tuple{ArgumentError, Array{Union{Ptr{Nothing}, Base.InterpreterIP}, 1}}, Int64, Int64}) +precompile(Tuple{typeof(Base.indexed_iterate), Tuple{ArgumentError, Array{Union{Ptr{Nothing}, Base.InterpreterIP}, 1}}, Int64}) +precompile(Tuple{typeof(Base.indexed_iterate), Tuple{Array{Float64, 1}, Nothing}, Int64, Int64}) +precompile(Tuple{typeof(Base.indexed_iterate), Tuple{Array{Float64, 1}, Nothing}, Int64}) +precompile(Tuple{typeof(Base.indexed_iterate), Tuple{Array{Float64, 2}, Nothing}, Int64, Int64}) +precompile(Tuple{typeof(Base.indexed_iterate), Tuple{Array{Float64, 2}, Nothing}, Int64}) +precompile(Tuple{typeof(Base.indexed_iterate), Tuple{Array{Int64, 1}, Nothing}, Int64, Int64}) +precompile(Tuple{typeof(Base.indexed_iterate), Tuple{Array{Int64, 1}, Nothing}, Int64}) +precompile(Tuple{typeof(Base.indexed_iterate), Tuple{Array{String, 1}, String, Bool}, Int64, Int64}) +precompile(Tuple{typeof(Base.indexed_iterate), Tuple{Array{String, 1}, String, Bool}, Int64}) +precompile(Tuple{typeof(Base.indexed_iterate), Tuple{Base.GenericIOBuffer{Array{UInt8, 1}}, Bool, Bool}, Int64, Int64}) +precompile(Tuple{typeof(Base.indexed_iterate), Tuple{Base.GenericIOBuffer{Array{UInt8, 1}}, Bool, Bool}, Int64}) +precompile(Tuple{typeof(Base.indexed_iterate), Tuple{Base.StackTraces.StackFrame, Int64}, Int64, Int64}) +precompile(Tuple{typeof(Base.indexed_iterate), Tuple{Base.StackTraces.StackFrame, Int64}, Int64}) +precompile(Tuple{typeof(Base.indexed_iterate), Tuple{ErrorException, Array{Union{Ptr{Nothing}, Base.InterpreterIP}, 1}}, Int64, Int64}) +precompile(Tuple{typeof(Base.indexed_iterate), Tuple{ErrorException, Array{Union{Ptr{Nothing}, Base.InterpreterIP}, 1}}, Int64}) +precompile(Tuple{typeof(Base.indexed_iterate), Tuple{Expr, Int64}, Int64, Int64}) +precompile(Tuple{typeof(Base.indexed_iterate), Tuple{Expr, Int64}, Int64}) +precompile(Tuple{typeof(Base.indexed_iterate), Tuple{Float64, Nothing}, Int64, Int64}) +precompile(Tuple{typeof(Base.indexed_iterate), Tuple{Float64, Nothing}, Int64}) +precompile(Tuple{typeof(Base.indexed_iterate), Tuple{Int64, Nothing}, Int64, Int64}) +precompile(Tuple{typeof(Base.indexed_iterate), Tuple{Int64, Nothing}, Int64}) +precompile(Tuple{typeof(Base.indexed_iterate), Tuple{Markdown.MD, Nothing}, Int64, Int64}) +precompile(Tuple{typeof(Base.indexed_iterate), Tuple{Markdown.MD, Nothing}, Int64}) +precompile(Tuple{typeof(Base.indexed_iterate), Tuple{MethodError, Array{Union{Ptr{Nothing}, Base.InterpreterIP}, 1}}, Int64, Int64}) +precompile(Tuple{typeof(Base.indexed_iterate), Tuple{MethodError, Array{Union{Ptr{Nothing}, Base.InterpreterIP}, 1}}, Int64}) +precompile(Tuple{typeof(Base.indexed_iterate), Tuple{Nothing, Nothing}, Int64, Int64}) +precompile(Tuple{typeof(Base.indexed_iterate), Tuple{Nothing, Nothing}, Int64}) +precompile(Tuple{typeof(Base.indexed_iterate), Tuple{String, Nothing}, Int64, Int64}) +precompile(Tuple{typeof(Base.indexed_iterate), Tuple{String, Nothing}, Int64}) +precompile(Tuple{typeof(Base.indexed_iterate), Tuple{Symbol, String, String}, Int64, Int64}) +precompile(Tuple{typeof(Base.indexed_iterate), Tuple{Symbol, String, String}, Int64}) +precompile(Tuple{typeof(Base.indexed_iterate), Tuple{UndefVarError, Array{Union{Ptr{Nothing}, Base.InterpreterIP}, 1}}, Int64, Int64}) +precompile(Tuple{typeof(Base.indexed_iterate), Tuple{UndefVarError, Array{Union{Ptr{Nothing}, Base.InterpreterIP}, 1}}, Int64}) +precompile(Tuple{typeof(Base.init_stdio), Ptr{Nothing}}) +precompile(Tuple{typeof(Base.isempty), Array{Base.Docs.DocStr, 1}}) +precompile(Tuple{typeof(Base.isempty), Array{String, 1}}) +precompile(Tuple{typeof(Base.isempty), Core.SimpleVector}) +precompile(Tuple{typeof(Base.isempty), NamedTuple{(), Tuple{}}}) +precompile(Tuple{typeof(Base.isempty), Nothing}) +precompile(Tuple{typeof(Base.isempty), REPL.LineEdit.PromptState}) +precompile(Tuple{typeof(Base.isempty), String}) +precompile(Tuple{typeof(Base.isequal), REPL.LineEdit.Prompt, REPL.LineEdit.Prompt}) +precompile(Tuple{typeof(Base.isequal), String, Symbol}) +precompile(Tuple{typeof(Base.issingletontype), Type{Base.Regex}}) +precompile(Tuple{typeof(Base.iterate), Array{AbstractString, 1}, Int64}) +precompile(Tuple{typeof(Base.iterate), Array{AbstractString, 1}}) +precompile(Tuple{typeof(Base.iterate), Array{Base.StackTraces.StackFrame, 1}, Int64}) +precompile(Tuple{typeof(Base.iterate), Array{Base.StackTraces.StackFrame, 1}}) +precompile(Tuple{typeof(Base.iterate), Array{REPL.LineEdit.TextInterface, 1}, Int64}) +precompile(Tuple{typeof(Base.iterate), Array{REPL.LineEdit.TextInterface, 1}}) +precompile(Tuple{typeof(Base.iterate), Base.Dict{String, String}, Int64}) +precompile(Tuple{typeof(Base.iterate), Base.Dict{String, String}}) +precompile(Tuple{typeof(Base.iterate), Base.OneTo{Int64}, Int64}) +precompile(Tuple{typeof(Base.iterate), Base.OneTo{Int64}}) +precompile(Tuple{typeof(Base.iterate), Nothing}) +precompile(Tuple{typeof(Base.iterate), Tuple{Int64, Int64}, Int64}) +precompile(Tuple{typeof(Base.iterate), Tuple{Int64, Int64}}) +precompile(Tuple{typeof(Base.last), Base.OneTo{Int64}}) +precompile(Tuple{typeof(Base.lastindex), Array{AbstractString, 1}}) +precompile(Tuple{typeof(Base.lastindex), Array{String, 1}}) +precompile(Tuple{typeof(Base.lastindex), Core.SimpleVector}) +precompile(Tuple{typeof(Base.lastindex), String}) +precompile(Tuple{typeof(Base.lastindex), Tuple{Symbol}}) +precompile(Tuple{typeof(Base.leading_ones), UInt8}) +precompile(Tuple{typeof(Base.length), Array{AbstractString, 1}}) +precompile(Tuple{typeof(Base.length), Array{Int32, 1}}) +precompile(Tuple{typeof(Base.length), Array{Symbol, 1}}) +precompile(Tuple{typeof(Base.length), Tuple{DataType, DataType}}) +precompile(Tuple{typeof(Base.map), typeof(Base.names), Array{Any, 1}}) +precompile(Tuple{typeof(Base.merge), Base.Dict{String, Any}, Base.Dict{String, Any}}) +precompile(Tuple{typeof(Base.merge), NamedTuple{(), Tuple{}}, NamedTuple{(), Tuple{}}}) +precompile(Tuple{typeof(Base.min), Int64, Int64}) +precompile(Tuple{typeof(Base.nextind), String, Int64}) +precompile(Tuple{typeof(Base.occursin), Base.Regex, Base.SubString{String}}) +precompile(Tuple{typeof(Base.occursin), String, String}) +precompile(Tuple{typeof(Base.open), Base.CmdRedirect, String, Base.TTY}) +precompile(Tuple{typeof(Base.open), String, String}) +precompile(Tuple{typeof(Base.poptask)}) +precompile(Tuple{typeof(Base.position), Base.GenericIOBuffer{Array{UInt8, 1}}}) +precompile(Tuple{typeof(Base.precompilableerror), LoadError, Bool}) +precompile(Tuple{typeof(Base.preserve_handle), Base.Timer}) +precompile(Tuple{typeof(Base.prevind), String, Int64}) +precompile(Tuple{typeof(Base.print), Base.GenericIOBuffer{Array{UInt8, 1}}, Base.UUID}) +precompile(Tuple{typeof(Base.print), Base.GenericIOBuffer{Array{UInt8, 1}}, String, Base.SubString{String}, String}) +precompile(Tuple{typeof(Base.print), Base.GenericIOBuffer{Array{UInt8, 1}}, String, String, String, String, String, String, String}) +precompile(Tuple{typeof(Base.print), Base.GenericIOBuffer{Array{UInt8, 1}}, Type{Int64}}) +precompile(Tuple{typeof(Base.print), Base.IOContext{Base.GenericIOBuffer{Array{UInt8, 1}}}, Base.SubString{String}}) +precompile(Tuple{typeof(Base.print), Base.IOContext{Base.GenericIOBuffer{Array{UInt8, 1}}}, Char, String, String}) +precompile(Tuple{typeof(Base.print), Base.IOContext{Base.GenericIOBuffer{Array{UInt8, 1}}}, Char}) +precompile(Tuple{typeof(Base.print), Base.IOContext{Base.GenericIOBuffer{Array{UInt8, 1}}}, Module, String, Symbol}) +precompile(Tuple{typeof(Base.print), Base.IOContext{Base.GenericIOBuffer{Array{UInt8, 1}}}, String, String}) +precompile(Tuple{typeof(Base.print), Base.IOContext{Base.GenericIOBuffer{Array{UInt8, 1}}}, String, Symbol, String, Int32}) +precompile(Tuple{typeof(Base.print), Base.IOContext{Base.GenericIOBuffer{Array{UInt8, 1}}}, String, Symbol}) +precompile(Tuple{typeof(Base.print), Base.IOContext{Base.GenericIOBuffer{Array{UInt8, 1}}}, String}) +precompile(Tuple{typeof(Base.print), Base.IOContext{Base.GenericIOBuffer{Array{UInt8, 1}}}, Symbol}) +precompile(Tuple{typeof(Base.print), Base.IOContext{REPL.Terminals.TTYTerminal}, Char, String, String}) +precompile(Tuple{typeof(Base.print), Base.IOContext{REPL.Terminals.TTYTerminal}, Char}) +precompile(Tuple{typeof(Base.print), Base.IOContext{REPL.Terminals.TTYTerminal}, String, String, String, String}) +precompile(Tuple{typeof(Base.print), Base.IOContext{REPL.Terminals.TTYTerminal}, String, Type{Module}}) +precompile(Tuple{typeof(Base.print), Base.IOContext{REPL.Terminals.TTYTerminal}, String}) +precompile(Tuple{typeof(Base.print), Base.IOContext{REPL.Terminals.TTYTerminal}, Type{Module}}) +precompile(Tuple{typeof(Base.print), Base.IOStream, Char}) +precompile(Tuple{typeof(Base.print), Base.IOStream, String}) +precompile(Tuple{typeof(Base.print), Base.TTY, Char}) +precompile(Tuple{typeof(Base.print), Base.TTY, String}) +precompile(Tuple{typeof(Base.print), REPL.Terminals.TTYTerminal, String}) +precompile(Tuple{typeof(Base.print_matrix_row), Base.IOContext{REPL.Terminals.TTYTerminal}, Array{Float64, 1}, Array{Tuple{Int64, Int64}, 1}, Int64, Base.OneTo{Int64}, String}) +precompile(Tuple{typeof(Base.print_matrix_row), Base.IOContext{REPL.Terminals.TTYTerminal}, Array{Float64, 2}, Array{Tuple{Int64, Int64}, 1}, Int64, Base.OneTo{Int64}, String}) +precompile(Tuple{typeof(Base.print_matrix_row), Base.IOContext{REPL.Terminals.TTYTerminal}, Array{Int64, 1}, Array{Tuple{Int64, Int64}, 1}, Int64, Base.OneTo{Int64}, String}) +precompile(Tuple{typeof(Base.print_to_string), Type{Any}}) +precompile(Tuple{typeof(Base.println), Base.TTY}) +precompile(Tuple{typeof(Base.println), REPL.Terminals.TTYTerminal}) +precompile(Tuple{typeof(Base.println), String}) +precompile(Tuple{typeof(Base.promote_eltype), Array{Symbol, 1}, Array{String, 1}}) +precompile(Tuple{typeof(Base.promote_eltype), Array{Symbol, 1}, Array{Symbol, 1}, Array{Symbol, 1}, Array{Symbol, 1}, Array{Symbol, 1}, Array{String, 1}}) +precompile(Tuple{typeof(Base.push!), Array{Base.Docs.DocStr, 1}, Base.Docs.DocStr}) +precompile(Tuple{typeof(Base.push!), Array{Base.Docs.MultiDoc, 1}, Base.Docs.MultiDoc}) +precompile(Tuple{typeof(Base.push!), Array{Base.Pair{Base.PkgId, UInt64}, 1}, Base.Pair{Base.PkgId, UInt64}}) +precompile(Tuple{typeof(Base.push!), Array{Char, 1}, Char}) +precompile(Tuple{typeof(Base.push!), Array{Symbol, 1}, Symbol}) +precompile(Tuple{typeof(Base.push!), Array{Tuple{String, Int64}, 1}, Tuple{String, Int64}}) +precompile(Tuple{typeof(Base.push!), Base.Set{Any}, Char}) +precompile(Tuple{typeof(Base.push!), Base.Set{Any}, Tuple{Module, String, Float64}}) +precompile(Tuple{typeof(Base.push!), Base.Set{REPL.REPLCompletions.Completion}, REPL.REPLCompletions.PackageCompletion}) +precompile(Tuple{typeof(Base.push!), Base.Set{String}, Base.SubString{String}}) +precompile(Tuple{typeof(Base.put!), Base.Channel{Any}, Tuple{ArgumentError, Array{Union{Ptr{Nothing}, Base.InterpreterIP}, 1}}}) +precompile(Tuple{typeof(Base.put!), Base.Channel{Any}, Tuple{Array{Float64, 1}, Nothing}}) +precompile(Tuple{typeof(Base.put!), Base.Channel{Any}, Tuple{Array{Float64, 2}, Nothing}}) +precompile(Tuple{typeof(Base.put!), Base.Channel{Any}, Tuple{Array{Int64, 1}, Nothing}}) +precompile(Tuple{typeof(Base.put!), Base.Channel{Any}, Tuple{ErrorException, Array{Union{Ptr{Nothing}, Base.InterpreterIP}, 1}}}) +precompile(Tuple{typeof(Base.put!), Base.Channel{Any}, Tuple{Float64, Nothing}}) +precompile(Tuple{typeof(Base.put!), Base.Channel{Any}, Tuple{Int64, Nothing}}) +precompile(Tuple{typeof(Base.put!), Base.Channel{Any}, Tuple{Markdown.MD, Nothing}}) +precompile(Tuple{typeof(Base.put!), Base.Channel{Any}, Tuple{MethodError, Array{Union{Ptr{Nothing}, Base.InterpreterIP}, 1}}}) +precompile(Tuple{typeof(Base.put!), Base.Channel{Any}, Tuple{Nothing, Nothing}}) +precompile(Tuple{typeof(Base.put!), Base.Channel{Any}, Tuple{String, Nothing}}) +precompile(Tuple{typeof(Base.put!), Base.Channel{Any}, Tuple{UndefVarError, Array{Union{Ptr{Nothing}, Base.InterpreterIP}, 1}}}) +precompile(Tuple{typeof(Base.rand), Int64, Int64}) +precompile(Tuple{typeof(Base.rand), Int64}) +precompile(Tuple{typeof(Base.rand), Random.RandomDevice, Type{UInt32}, Int64}) +precompile(Tuple{typeof(Base.rand)}) +precompile(Tuple{typeof(Base.read!), Base.GenericIOBuffer{Array{UInt8, 1}}, Array{UInt8, 1}}) +precompile(Tuple{typeof(Base.read), Base.TTY, Type{UInt8}}) +precompile(Tuple{typeof(Base.readuntil), Base.PipeEndpoint, Char}) +precompile(Tuple{typeof(Base.readuntil), Base.TTY, String}) +precompile(Tuple{typeof(Base.readuntil), REPL.Terminals.TTYTerminal, String}) +precompile(Tuple{typeof(Base.reinterpret), Type{Char}, UInt32}) +precompile(Tuple{typeof(Base.replace), Base.SubString{String}, Base.Pair{Base.Regex, String}}) +precompile(Tuple{typeof(Base.resize!), Array{Tuple{String, Int64}, 1}, Int64}) +precompile(Tuple{typeof(Base.rethrow)}) +precompile(Tuple{typeof(Base.seek), Base.GenericIOBuffer{Array{UInt8, 1}}, Int64}) +precompile(Tuple{typeof(Base.setindex!), Array{Any, 1}, Array{String, 1}, Base.UnitRange{Int64}}) +precompile(Tuple{typeof(Base.setindex!), Array{Any, 1}, Array{Symbol, 1}, Base.UnitRange{Int64}}) +precompile(Tuple{typeof(Base.setindex!), Array{Base.StackTraces.StackFrame, 1}, Base.StackTraces.StackFrame, Int64}) +precompile(Tuple{typeof(Base.setindex!), Array{Method, 1}, Method, Int64}) +precompile(Tuple{typeof(Base.setindex!), Array{String, 1}, String, Int64}) +precompile(Tuple{typeof(Base.setindex!), Array{Symbol, 1}, Symbol, Int64}) +precompile(Tuple{typeof(Base.setindex!), Array{Union{Nothing, String}, 1}, String, Int64}) +precompile(Tuple{typeof(Base.setindex!), Base.Dict{Any, Any}, Char, Char}) +precompile(Tuple{typeof(Base.setindex!), Base.Dict{Any, Any}, Char, String}) +precompile(Tuple{typeof(Base.setindex!), Base.Dict{Any, Any}, Module, Symbol}) +precompile(Tuple{typeof(Base.setindex!), Base.Dict{Any, Any}, Type{Union{}}, Symbol}) +precompile(Tuple{typeof(Base.setindex!), Base.Dict{Symbol, Any}, REPL.LineEdit.Prompt, Symbol}) +precompile(Tuple{typeof(Base.setindex!), Base.RefValue{Bool}, Bool}) +precompile(Tuple{typeof(Base.setproperty!), Base.Iterators.Stateful{Tuple{String, String}, Any}, Symbol, Tuple{String, Int64}}) +precompile(Tuple{typeof(Base.setproperty!), Base.Process, Symbol, Ptr{Nothing}}) +precompile(Tuple{typeof(Base.setproperty!), Base.Process, Symbol, Symbol}) +precompile(Tuple{typeof(Base.setproperty!), REPL.LineEdit.MIState, Symbol, Symbol}) +precompile(Tuple{typeof(Base.setproperty!), REPL.LineEdit.PrefixHistoryPrompt, Symbol, REPL.LineEdit.Prompt}) +precompile(Tuple{typeof(Base.setproperty!), REPL.LineEdit.PrefixSearchState, Symbol, Int64}) +precompile(Tuple{typeof(Base.setproperty!), REPL.LineEdit.PrefixSearchState, Symbol, REPL.LineEdit.MIState}) +precompile(Tuple{typeof(Base.setproperty!), REPL.LineEdit.PrefixSearchState, Symbol, REPL.LineEdit.Prompt}) +precompile(Tuple{typeof(Base.setproperty!), REPL.LineEdit.PrefixSearchState, Symbol, String}) +precompile(Tuple{typeof(Base.setproperty!), REPL.LineEdit.Prompt, Symbol, Base.Dict{Char, Any}}) +precompile(Tuple{typeof(Base.setproperty!), REPL.LineEdit.PromptState, Symbol, Base.GenericIOBuffer{Array{UInt8, 1}}}) +precompile(Tuple{typeof(Base.setproperty!), REPL.LineEdit.PromptState, Symbol, REPL.LineEdit.InputAreaState}) +precompile(Tuple{typeof(Base.setproperty!), REPL.LineEdit.SearchState, Symbol, Bool}) +precompile(Tuple{typeof(Base.setproperty!), REPL.LineEdit.SearchState, Symbol, REPL.LineEdit.Prompt}) +precompile(Tuple{typeof(Base.setproperty!), REPL.LineEditREPL, Symbol, Bool}) +precompile(Tuple{typeof(Base.setproperty!), REPL.REPLHistoryProvider, Symbol, Base.GenericIOBuffer{Array{UInt8, 1}}}) +precompile(Tuple{typeof(Base.setproperty!), REPL.REPLHistoryProvider, Symbol, REPL.LineEdit.Prompt}) +precompile(Tuple{typeof(Base.show), Base.GenericIOBuffer{Array{UInt8, 1}}, Array{String, 1}}) +precompile(Tuple{typeof(Base.show), Base.GenericIOBuffer{Array{UInt8, 1}}, String}) +precompile(Tuple{typeof(Base.show), Base.GenericIOBuffer{Array{UInt8, 1}}, Type{Any}}) +precompile(Tuple{typeof(Base.show), Base.GenericIOBuffer{Array{UInt8, 1}}, UInt64}) +precompile(Tuple{typeof(Base.show), Base.IOContext{Base.GenericIOBuffer{Array{UInt8, 1}}}, Array{Any, 1}}) +precompile(Tuple{typeof(Base.show), Base.IOContext{Base.GenericIOBuffer{Array{UInt8, 1}}}, Int64}) +precompile(Tuple{typeof(Base.show), Base.IOContext{Base.GenericIOBuffer{Array{UInt8, 1}}}, String}) +precompile(Tuple{typeof(Base.show), Base.IOContext{REPL.Terminals.TTYTerminal}, Base.MIME{Symbol("text/plain")}, Array{Float64, 1}}) +precompile(Tuple{typeof(Base.show), Base.IOContext{REPL.Terminals.TTYTerminal}, Base.MIME{Symbol("text/plain")}, Array{Float64, 2}}) +precompile(Tuple{typeof(Base.show), Base.IOContext{REPL.Terminals.TTYTerminal}, Base.MIME{Symbol("text/plain")}, Array{Int64, 1}}) +precompile(Tuple{typeof(Base.show), Base.IOContext{REPL.Terminals.TTYTerminal}, Base.MIME{Symbol("text/plain")}, Float64}) +precompile(Tuple{typeof(Base.show), Base.IOContext{REPL.Terminals.TTYTerminal}, Base.MIME{Symbol("text/plain")}, Int64}) +precompile(Tuple{typeof(Base.show), Base.IOContext{REPL.Terminals.TTYTerminal}, Base.MIME{Symbol("text/plain")}, Markdown.MD}) +precompile(Tuple{typeof(Base.show), Base.IOContext{REPL.Terminals.TTYTerminal}, Base.MIME{Symbol("text/plain")}, String}) +precompile(Tuple{typeof(Base.show), Base.IOContext{REPL.Terminals.TTYTerminal}, Int64}) +precompile(Tuple{typeof(Base.show), Base.IOContext{REPL.Terminals.TTYTerminal}, Type{Module}}) +precompile(Tuple{typeof(Base.show_datatype), Base.IOContext{REPL.Terminals.TTYTerminal}, Type{Module}}) +precompile(Tuple{typeof(Base.show_tuple_as_call), Base.IOContext{REPL.Terminals.TTYTerminal}, Symbol, Type{Tuple{typeof(Base.require), Module, Symbol}}}) +precompile(Tuple{typeof(Base.showerror), Base.IOContext{REPL.Terminals.TTYTerminal}, ArgumentError, Array{Union{Ptr{Nothing}, Base.InterpreterIP}, 1}}) +precompile(Tuple{typeof(Base.showerror), Base.IOContext{REPL.Terminals.TTYTerminal}, ErrorException, Array{Union{Ptr{Nothing}, Base.InterpreterIP}, 1}}) +precompile(Tuple{typeof(Base.showerror), Base.IOContext{REPL.Terminals.TTYTerminal}, MethodError, Array{Union{Ptr{Nothing}, Base.InterpreterIP}, 1}}) +precompile(Tuple{typeof(Base.showerror), Base.IOContext{REPL.Terminals.TTYTerminal}, UndefVarError, Array{Union{Ptr{Nothing}, Base.InterpreterIP}, 1}}) +precompile(Tuple{typeof(Base.similar), Array{Any, 1}, Type{Nothing}, Tuple{Base.OneTo{Int64}}}) +precompile(Tuple{typeof(Base.similar), Array{Base.Docs.DocStr, 1}, Type{Markdown.MD}, Tuple{Base.OneTo{Int64}}}) +precompile(Tuple{typeof(Base.similar), Array{REPL.REPLCompletions.Completion, 1}, Type{String}, Tuple{Base.OneTo{Int64}}}) +precompile(Tuple{typeof(Base.similar), Array{Union{Ptr{Nothing}, Base.InterpreterIP}, 1}, Type{Array{Base.StackTraces.StackFrame, 1}}, Tuple{Base.OneTo{Int64}}}) +precompile(Tuple{typeof(Base.similar), Type{Array{Method, N} where N}, Tuple{Base.OneTo{Int64}}}) +precompile(Tuple{typeof(Base.sizeof), String}) +precompile(Tuple{typeof(Base.skip_deleted_floor!), Base.Dict{Symbol, Any}}) +precompile(Tuple{typeof(Base.sort!), Array{Int64, 1}, Base.Sort.QuickSortAlg, Base.Order.Perm{Base.Order.ForwardOrdering, Array{Tuple{Float64, Int64}, 1}}}) +precompile(Tuple{typeof(Base.startswith), Base.SubString{String}, String}) +precompile(Tuple{typeof(Base.startswith), String, Char}) +precompile(Tuple{typeof(Base.stream_wait), Base.Timer, Base.Condition}) +precompile(Tuple{typeof(Base.string), String, Nothing, String, String, String, Int64}) +precompile(Tuple{typeof(Base.string), String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, Base.VersionNumber, String, String, String, String, String, String, String, String, String, String, String, String, String, String}) +precompile(Tuple{typeof(Base.string), String, Type{Int64}}) +precompile(Tuple{typeof(Base.string), Type{Any}}) +precompile(Tuple{typeof(Base.strip), String}) +precompile(Tuple{typeof(Base.take!), Base.Channel{Any}}) +precompile(Tuple{typeof(Base.take!), Base.GenericIOBuffer{Array{UInt8, 1}}}) +precompile(Tuple{typeof(Base.task_done_hook), Task}) +precompile(Tuple{typeof(Base.time_print), UInt64, Int64, Int64, Int64}) +precompile(Tuple{typeof(Base.truncate), Base.GenericIOBuffer{Array{UInt8, 1}}, Int64}) +precompile(Tuple{typeof(Base.try_yieldto), typeof(Base.ensure_rescheduled), Base.RefValue{Task}}) +precompile(Tuple{typeof(Base.tuple_type_head), Type{Tuple{Vararg{Int64, N}} where N}}) +precompile(Tuple{typeof(Base.tuple_type_tail), Type{Tuple{Vararg{Int64, N}} where N}}) +precompile(Tuple{typeof(Base.typed_vcat), Type{Any}, Array{Symbol, 1}, Array{Symbol, 1}, Array{Symbol, 1}, Array{Symbol, 1}, Array{Symbol, 1}, Array{String, 1}}) +precompile(Tuple{typeof(Base.typeinfo_eltype), Type{Any}}) +precompile(Tuple{typeof(Base.typesof), Int64, Int64}) +precompile(Tuple{typeof(Base.unique), Array{Any, 1}}) +precompile(Tuple{typeof(Base.unlock), Base.Threads.RecursiveTatasLock}) +precompile(Tuple{typeof(Base.unpreserve_handle), Base.Timer}) +precompile(Tuple{typeof(Base.unsafe_convert), Type{Ptr{Int64}}, Base.Threads.Atomic{Int64}}) +precompile(Tuple{typeof(Base.unsafe_convert), Type{Ptr{Nothing}}, Ptr{Nothing}}) +precompile(Tuple{typeof(Base.unsafe_convert), Type{Ptr{UInt64}}, Base.Threads.Atomic{UInt64}}) +precompile(Tuple{typeof(Base.unsafe_write), Base.Pipe, Ptr{UInt8}, UInt64}) +precompile(Tuple{typeof(Base.unsafe_write), Base.TTY, Ptr{UInt8}, Int32}) +precompile(Tuple{typeof(Base.unsafe_write), Base.TTY, Ptr{UInt8}, UInt64}) +precompile(Tuple{typeof(Base.uvfinalize), Base.PipeEndpoint}) +precompile(Tuple{typeof(Base.uvfinalize), Base.Process}) +precompile(Tuple{typeof(Base.uvfinalize), Base.TTY}) +precompile(Tuple{typeof(Base.uvfinalize), Base.Timer}) +precompile(Tuple{typeof(Base.vcat), Array{Any, 1}, String, String}) +precompile(Tuple{typeof(Base.vcat), Array{Base.StackTraces.StackFrame, 1}, Array{Base.StackTraces.StackFrame, 1}, Array{Base.StackTraces.StackFrame, 1}, Array{Base.StackTraces.StackFrame, 1}, Array{Base.StackTraces.StackFrame, 1}, Array{Base.StackTraces.StackFrame, 1}, Array{Base.StackTraces.StackFrame, 1}, Array{Base.StackTraces.StackFrame, 1}, Array{Base.StackTraces.StackFrame, 1}, Array{Base.StackTraces.StackFrame, 1}, Array{Base.StackTraces.StackFrame, 1}, Array{Base.StackTraces.StackFrame, 1}}) +precompile(Tuple{typeof(Base.vcat), Array{Symbol, 1}, Array{Symbol, 1}, Array{Symbol, 1}, Array{Symbol, 1}, Array{Symbol, 1}, Array{String, 1}}) +precompile(Tuple{typeof(Base.vcat), Markdown.MD, Markdown.MD}) +precompile(Tuple{typeof(Base.vcat), Markdown.MD}) +precompile(Tuple{typeof(Base.vect), Symbol, Vararg{Symbol, N} where N}) +precompile(Tuple{typeof(Base.wait), Base.Condition}) +precompile(Tuple{typeof(Base.wait), Base.Timer}) +precompile(Tuple{typeof(Base.wait)}) +precompile(Tuple{typeof(Base.write), Base.GenericIOBuffer{Array{UInt8, 1}}, String}) +precompile(Tuple{typeof(Base.write), Base.IOStream, Array{UInt8, 1}}) +precompile(Tuple{typeof(Base.write), Base.Pipe, String}) +precompile(Tuple{typeof(Base.write), Base.Process, String}) +precompile(Tuple{typeof(Base.write), Base.TTY, Char}) +precompile(Tuple{typeof(Base.write), Base.TTY, String}) +precompile(Tuple{typeof(Base.write), Base.TTY, UInt8}) +precompile(Tuple{typeof(Base.write), REPL.Terminals.TTYTerminal, String}) +precompile(Tuple{typeof(Base.write), REPL.Terminals.TerminalBuffer, Base.Missing}) +precompile(Tuple{typeof(Base.write), REPL.Terminals.TerminalBuffer, String}) +precompile(Tuple{typeof(Core.Compiler.:(!=)), Type{Any}, Core.Compiler.Const}) +precompile(Tuple{typeof(Core.Compiler.getindex), Array{DataType, 1}, Int64}) +precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{Array{Bool, 0}}, Int64}) +precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{Array{String, 1}}, Int64}) +precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{Base.Broadcast.DefaultArrayStyle{0}, typeof(Base.identity), Int64}, Int64}) +precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{Base.Colon}, Int64}) +precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{Base.Iterators.Pairs{Union{}, Union{}, Tuple{}, NamedTuple{(), Tuple{}}}, typeof(Base.invokelatest), typeof(Base.Multimedia.display)}, Int64}) +precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{Base.Iterators.Pairs{Union{}, Union{}, Tuple{}, NamedTuple{(), Tuple{}}}, typeof(Base.invokelatest), typeof(Base.__atreplinit)}, Int64}) +precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{Base.Iterators.Pairs{Union{}, Union{}, Tuple{}, NamedTuple{(), Tuple{}}}, typeof(Base.invokelatest), typeof(Base.display_error)}, Int64}) +precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{Base.Iterators.Pairs{Union{}, Union{}, Tuple{}, NamedTuple{(), Tuple{}}}, typeof(Base.invokelatest), typeof(Base.show)}, Int64}) +precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{Base.Iterators.Pairs{Union{}, Union{}, Tuple{}, NamedTuple{(), Tuple{}}}, typeof(Base.invokelatest), typeof(REPL.helpmode)}, Int64}) +precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{Base.Val{1}, Union}, Int64}) +precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{Char, Char}, Int64}) +precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{Core.Compiler.IndexLinear, Array{Bool, 0}}, Int64}) +precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{Nothing, Nothing}, Int64}) +precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{Nothing, typeof(Base.replace), Nothing}, Int64}) +precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{QuoteNode, Int64}, Int64}) +precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{String, Int64}, Int64}) +precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{Symbol, Bool}, Int64}) +precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{Symbol, GlobalRef}, Int64}) +precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{typeof(Base.:(*)), Int64}, Int64}) +precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{typeof(Base.Multimedia.display), Int64}, Int64}) +precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{typeof(Base.convert), Int64}, Int64}) +precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{typeof(Base.convert), typeof(Base.getindex), typeof(Base.setindex!)}, Int64}) +precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{typeof(Base.getindex), typeof(Base.setindex!)}, Int64}) +precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{typeof(Base.open_flags)}, Int64}) +precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{typeof(Base.setindex!)}, Int64}) +precompile(Tuple{typeof(Core.Compiler.getindex), Type{Any}, Core.SSAValue, Char, Core.SSAValue}) +precompile(Tuple{typeof(Core.Compiler.getindex), Type{Any}, Core.SSAValue, Core.Compiler.Argument, Core.Compiler.Argument, Core.SSAValue, Core.SSAValue}) +precompile(Tuple{typeof(Core.Compiler.getindex), Type{Any}, Core.SSAValue, Core.SSAValue, Int64, Core.SSAValue, Core.SSAValue}) +precompile(Tuple{typeof(Core.Compiler.getindex), Type{Any}, Core.SSAValue, Core.SSAValue, String, Core.SSAValue}) +precompile(Tuple{typeof(Core.Compiler.getindex), Type{Any}, Core.SSAValue, Int64, Core.SSAValue}) +precompile(Tuple{typeof(Core.Compiler.getindex), Type{Any}, Core.SSAValue, UInt8, Core.SSAValue}) +precompile(Tuple{typeof(Core.Compiler.getindex), Type{Any}, Tuple{Symbol}, Tuple{Symbol, Symbol, Symbol, Symbol, Symbol, Symbol, Symbol}}) +precompile(Tuple{typeof(Core.Compiler.getindex), Type{Any}, getfield(Markdown, Symbol("#kw##print_wrapped")), Core.SSAValue, Core.SSAValue, Core.SSAValue, Core.Compiler.Argument, Core.SSAValue}) +precompile(Tuple{typeof(Core.Compiler.instanceof_tfunc), Any}) +precompile(Tuple{typeof(Core.Compiler.length), Tuple{Array{Bool, 0}}}) +precompile(Tuple{typeof(Core.Compiler.length), Tuple{Array{String, 1}}}) +precompile(Tuple{typeof(Core.Compiler.length), Tuple{Base.Broadcast.DefaultArrayStyle{0}, typeof(Base.identity), Int64}}) +precompile(Tuple{typeof(Core.Compiler.length), Tuple{Base.Colon}}) +precompile(Tuple{typeof(Core.Compiler.length), Tuple{Base.Iterators.Pairs{Union{}, Union{}, Tuple{}, NamedTuple{(), Tuple{}}}, typeof(Base.invokelatest), typeof(Base.Multimedia.display)}}) +precompile(Tuple{typeof(Core.Compiler.length), Tuple{Base.Iterators.Pairs{Union{}, Union{}, Tuple{}, NamedTuple{(), Tuple{}}}, typeof(Base.invokelatest), typeof(Base.__atreplinit)}}) +precompile(Tuple{typeof(Core.Compiler.length), Tuple{Base.Iterators.Pairs{Union{}, Union{}, Tuple{}, NamedTuple{(), Tuple{}}}, typeof(Base.invokelatest), typeof(Base.display_error)}}) +precompile(Tuple{typeof(Core.Compiler.length), Tuple{Base.Iterators.Pairs{Union{}, Union{}, Tuple{}, NamedTuple{(), Tuple{}}}, typeof(Base.invokelatest), typeof(Base.show)}}) +precompile(Tuple{typeof(Core.Compiler.length), Tuple{Base.Iterators.Pairs{Union{}, Union{}, Tuple{}, NamedTuple{(), Tuple{}}}, typeof(Base.invokelatest), typeof(REPL.helpmode)}}) +precompile(Tuple{typeof(Core.Compiler.length), Tuple{Base.Val{1}, Union}}) +precompile(Tuple{typeof(Core.Compiler.length), Tuple{Char, Char}}) +precompile(Tuple{typeof(Core.Compiler.length), Tuple{Core.Compiler.IndexLinear, Array{Bool, 0}}}) +precompile(Tuple{typeof(Core.Compiler.length), Tuple{Nothing, Nothing}}) +precompile(Tuple{typeof(Core.Compiler.length), Tuple{Nothing, typeof(Base.replace), Nothing}}) +precompile(Tuple{typeof(Core.Compiler.length), Tuple{Symbol, Bool}}) +precompile(Tuple{typeof(Core.Compiler.length), Tuple{Symbol, GlobalRef}}) +precompile(Tuple{typeof(Core.Compiler.length), Tuple{typeof(Base.:(*)), Int64}}) +precompile(Tuple{typeof(Core.Compiler.length), Tuple{typeof(Base.open_flags)}}) +precompile(Tuple{typeof(Core.Compiler.rewrap_unionall), Any, Any}) +precompile(Tuple{typeof(Core.Compiler.vect), Type{typeof(typeassert)}}) +precompile(Tuple{typeof(Distributed.flush_gc_msgs), Distributed.Worker}) +precompile(Tuple{typeof(Distributed.flush_gc_msgs)}) +precompile(Tuple{typeof(Distributed.terminate_all_workers)}) +precompile(Tuple{typeof(LibGit2.ensure_initialized)}) +precompile(Tuple{typeof(LibGit2.initialize)}) +precompile(Tuple{typeof(Logging.__init__)}) +precompile(Tuple{typeof(Logging.default_metafmt), Base.CoreLogging.LogLevel, Module, Symbol, Symbol, String, Int64}) +precompile(Tuple{typeof(Logging.default_metafmt), Base.CoreLogging.LogLevel, Nothing, Symbol, Symbol, String, Int64}) +precompile(Tuple{typeof(Markdown.ansi_length), Base.SubString{String}}) +precompile(Tuple{typeof(Markdown.ansi_length), String}) +precompile(Tuple{typeof(Markdown.footnote_link), Base.GenericIOBuffer{Array{UInt8, 1}}, Markdown.MD}) +precompile(Tuple{typeof(Markdown.link), Base.GenericIOBuffer{Array{UInt8, 1}}, Markdown.MD}) +precompile(Tuple{typeof(Markdown.term), Base.IOContext{REPL.Terminals.TTYTerminal}, Markdown.Code, Int64}) +precompile(Tuple{typeof(Markdown.term), Base.IOContext{REPL.Terminals.TTYTerminal}, Markdown.Header{1}, Int64}) +precompile(Tuple{typeof(Markdown.term), Base.IOContext{REPL.Terminals.TTYTerminal}, Markdown.HorizontalRule, Int64}) +precompile(Tuple{typeof(Markdown.term), Base.IOContext{REPL.Terminals.TTYTerminal}, Markdown.MD, Int64}) +precompile(Tuple{typeof(Markdown.term), Base.IOContext{REPL.Terminals.TTYTerminal}, Markdown.Paragraph, Int64}) +precompile(Tuple{typeof(Markdown.terminline), Base.IOContext{Base.GenericIOBuffer{Array{UInt8, 1}}}, Array{Any, 1}}) +precompile(Tuple{typeof(Markdown.terminline), Base.IOContext{Base.GenericIOBuffer{Array{UInt8, 1}}}, Markdown.Code}) +precompile(Tuple{typeof(Markdown.terminline), Base.IOContext{Base.GenericIOBuffer{Array{UInt8, 1}}}, Markdown.Link}) +precompile(Tuple{typeof(Markdown.terminline), Base.IOContext{Base.GenericIOBuffer{Array{UInt8, 1}}}, String}) +precompile(Tuple{typeof(Markdown.terminline_string), Base.IOContext{Base.GenericIOBuffer{Array{UInt8, 1}}}, Array{Any, 1}}) +precompile(Tuple{typeof(Markdown.terminline_string), Base.IOContext{REPL.Terminals.TTYTerminal}, Array{Any, 1}}) +precompile(Tuple{typeof(Pkg.REPLMode.create_mode), REPL.LineEditREPL, REPL.LineEdit.Prompt}) +precompile(Tuple{typeof(Pkg.REPLMode.repl_init), REPL.LineEditREPL}) +precompile(Tuple{typeof(REPL.LineEdit.accept_result), REPL.LineEdit.MIState, REPL.LineEdit.PrefixHistoryPrompt}) +precompile(Tuple{typeof(REPL.LineEdit.activate), REPL.LineEdit.HistoryPrompt, REPL.LineEdit.SearchState, REPL.Terminals.TerminalBuffer, REPL.Terminals.TTYTerminal}) +precompile(Tuple{typeof(REPL.LineEdit.activate), REPL.LineEdit.PrefixHistoryPrompt, REPL.LineEdit.PrefixSearchState, REPL.Terminals.TerminalBuffer, REPL.Terminals.TTYTerminal}) +precompile(Tuple{typeof(REPL.LineEdit.activate), REPL.LineEdit.Prompt, REPL.LineEdit.MIState, REPL.Terminals.TTYTerminal, REPL.Terminals.TTYTerminal}) +precompile(Tuple{typeof(REPL.LineEdit.activate), REPL.LineEdit.Prompt, REPL.LineEdit.PromptState, REPL.Terminals.TTYTerminal, REPL.Terminals.TTYTerminal}) +precompile(Tuple{typeof(REPL.LineEdit.activate), REPL.LineEdit.Prompt, REPL.LineEdit.PromptState, REPL.Terminals.TerminalBuffer, REPL.Terminals.TTYTerminal}) +precompile(Tuple{typeof(REPL.LineEdit.activate_region), REPL.LineEdit.MIState, Symbol}) +precompile(Tuple{typeof(REPL.LineEdit.buffer), REPL.LineEdit.MIState}) +precompile(Tuple{typeof(REPL.LineEdit.buffer), REPL.LineEdit.PromptState}) +precompile(Tuple{typeof(REPL.LineEdit.cancel_beep), REPL.LineEdit.MIState}) +precompile(Tuple{typeof(REPL.LineEdit.cancel_beep), REPL.LineEdit.PrefixSearchState}) +precompile(Tuple{typeof(REPL.LineEdit.cancel_beep), REPL.LineEdit.PromptState}) +precompile(Tuple{typeof(REPL.LineEdit.cancel_beep), REPL.LineEdit.SearchState}) +precompile(Tuple{typeof(REPL.LineEdit.commit_changes), REPL.Terminals.TTYTerminal, REPL.Terminals.TerminalBuffer}) +precompile(Tuple{typeof(REPL.LineEdit.common_prefix), Array{String, 1}}) +precompile(Tuple{typeof(REPL.LineEdit.complete_line), REPL.LineEdit.PromptState, Int64}) +precompile(Tuple{typeof(REPL.LineEdit.complete_line), REPL.REPLCompletionProvider, REPL.LineEdit.PromptState}) +precompile(Tuple{typeof(REPL.LineEdit.deactivate), REPL.LineEdit.HistoryPrompt, REPL.LineEdit.SearchState, REPL.Terminals.TerminalBuffer, REPL.Terminals.TTYTerminal}) +precompile(Tuple{typeof(REPL.LineEdit.deactivate), REPL.LineEdit.PrefixHistoryPrompt, REPL.LineEdit.PrefixSearchState, REPL.Terminals.TerminalBuffer, REPL.Terminals.TTYTerminal}) +precompile(Tuple{typeof(REPL.LineEdit.deactivate), REPL.LineEdit.Prompt, REPL.LineEdit.PromptState, REPL.Terminals.TerminalBuffer, REPL.Terminals.TTYTerminal}) +precompile(Tuple{typeof(REPL.LineEdit.deactivate_region), REPL.LineEdit.MIState}) +precompile(Tuple{typeof(REPL.LineEdit.deactivate_region), REPL.LineEdit.PromptState}) +precompile(Tuple{typeof(REPL.LineEdit.default_enter_cb), REPL.LineEdit.PromptState}) +precompile(Tuple{typeof(REPL.LineEdit.edit_abort), REPL.LineEdit.MIState}) +precompile(Tuple{typeof(REPL.LineEdit.edit_backspace), REPL.LineEdit.PromptState, Bool, Bool}) +precompile(Tuple{typeof(REPL.LineEdit.edit_delete), Base.GenericIOBuffer{Array{UInt8, 1}}}) +precompile(Tuple{typeof(REPL.LineEdit.edit_delete), REPL.LineEdit.MIState}) +precompile(Tuple{typeof(REPL.LineEdit.edit_insert), Base.GenericIOBuffer{Array{UInt8, 1}}, Base.SubString{String}}) +precompile(Tuple{typeof(REPL.LineEdit.edit_splice!), REPL.LineEdit.PromptState, Base.Pair{Int64, Int64}, String}) +precompile(Tuple{typeof(REPL.LineEdit.eval), Module, Expr}) +precompile(Tuple{typeof(REPL.LineEdit.history_next_prefix), REPL.LineEdit.PrefixSearchState, REPL.REPLHistoryProvider, String}) +precompile(Tuple{typeof(REPL.LineEdit.history_prev_prefix), REPL.LineEdit.PrefixSearchState, REPL.REPLHistoryProvider, String}) +precompile(Tuple{typeof(REPL.LineEdit.init_state), REPL.Terminals.TTYTerminal, REPL.LineEdit.HistoryPrompt}) +precompile(Tuple{typeof(REPL.LineEdit.init_state), REPL.Terminals.TTYTerminal, REPL.LineEdit.ModalInterface}) +precompile(Tuple{typeof(REPL.LineEdit.init_state), REPL.Terminals.TTYTerminal, REPL.LineEdit.PrefixHistoryPrompt}) +precompile(Tuple{typeof(REPL.LineEdit.is_region_active), REPL.LineEdit.MIState}) +precompile(Tuple{typeof(REPL.LineEdit.keymap), REPL.LineEdit.PrefixSearchState, REPL.LineEdit.PrefixHistoryPrompt}) +precompile(Tuple{typeof(REPL.LineEdit.keymap), REPL.LineEdit.SearchState, REPL.LineEdit.HistoryPrompt}) +precompile(Tuple{typeof(REPL.LineEdit.keymap_data), REPL.LineEdit.PrefixSearchState, REPL.LineEdit.PrefixHistoryPrompt}) +precompile(Tuple{typeof(REPL.LineEdit.keymap_data), REPL.LineEdit.SearchState, REPL.LineEdit.HistoryPrompt}) +precompile(Tuple{typeof(REPL.LineEdit.match_input), Base.Dict{Char, Any}, REPL.LineEdit.MIState, Base.GenericIOBuffer{Array{UInt8, 1}}}) +precompile(Tuple{typeof(REPL.LineEdit.match_input), Base.Dict{Char, Any}, REPL.LineEdit.MIState, REPL.Terminals.TTYTerminal, Array{Char, 1}, Base.Dict{Char, Any}}) +precompile(Tuple{typeof(REPL.LineEdit.match_input), Base.Dict{Char, Any}, REPL.LineEdit.MIState}) +precompile(Tuple{typeof(REPL.LineEdit.match_input), Function, REPL.LineEdit.MIState, REPL.Terminals.TTYTerminal, Array{Char, 1}, Base.Dict{Char, Any}}) +precompile(Tuple{typeof(REPL.LineEdit.mode), REPL.LineEdit.PromptState}) +precompile(Tuple{typeof(REPL.LineEdit.options), REPL.LineEdit.MIState}) +precompile(Tuple{typeof(REPL.LineEdit.options), REPL.LineEdit.PromptState}) +precompile(Tuple{typeof(REPL.LineEdit.pop_undo), REPL.LineEdit.MIState}) +precompile(Tuple{typeof(REPL.LineEdit.prompt_string), typeof(Base.input_color)}) +precompile(Tuple{typeof(REPL.LineEdit.push_undo), REPL.LineEdit.MIState}) +precompile(Tuple{typeof(REPL.LineEdit.refresh_multi_line), REPL.LineEdit.MIState}) +precompile(Tuple{typeof(REPL.LineEdit.refresh_multi_line), REPL.LineEdit.PromptState}) +precompile(Tuple{typeof(REPL.LineEdit.refresh_multi_line), REPL.Terminals.TTYTerminal, REPL.LineEdit.PrefixSearchState}) +precompile(Tuple{typeof(REPL.LineEdit.refresh_multi_line), REPL.Terminals.TTYTerminal, REPL.LineEdit.PromptState}) +precompile(Tuple{typeof(REPL.LineEdit.refresh_multi_line), REPL.Terminals.TTYTerminal, REPL.LineEdit.SearchState}) +precompile(Tuple{typeof(REPL.LineEdit.refresh_multi_line), REPL.Terminals.TerminalBuffer, REPL.Terminals.TTYTerminal, Base.GenericIOBuffer{Array{UInt8, 1}}, REPL.LineEdit.InputAreaState, String}) +precompile(Tuple{typeof(REPL.LineEdit.refresh_multi_line), REPL.Terminals.TerminalBuffer, REPL.Terminals.TTYTerminal, REPL.LineEdit.PrefixSearchState}) +precompile(Tuple{typeof(REPL.LineEdit.refresh_multi_line), REPL.Terminals.TerminalBuffer, REPL.Terminals.TTYTerminal, REPL.LineEdit.PromptState}) +precompile(Tuple{typeof(REPL.LineEdit.region_active), REPL.LineEdit.MIState}) +precompile(Tuple{typeof(REPL.LineEdit.replace_line), REPL.LineEdit.MIState, String}) +precompile(Tuple{typeof(REPL.LineEdit.replace_line), REPL.LineEdit.PromptState, Base.GenericIOBuffer{Array{UInt8, 1}}}) +precompile(Tuple{typeof(REPL.LineEdit.reset_state), REPL.LineEdit.MIState}) +precompile(Tuple{typeof(REPL.LineEdit.reset_state), REPL.LineEdit.PrefixSearchState}) +precompile(Tuple{typeof(REPL.LineEdit.reset_state), REPL.LineEdit.PromptState}) +precompile(Tuple{typeof(REPL.LineEdit.reset_state), REPL.LineEdit.SearchState}) +precompile(Tuple{typeof(REPL.LineEdit.reset_state), REPL.REPLHistoryProvider}) +precompile(Tuple{typeof(REPL.LineEdit.run_interface), REPL.Terminals.TTYTerminal, REPL.LineEdit.ModalInterface, REPL.LineEdit.MIState}) +precompile(Tuple{typeof(REPL.LineEdit.set_action!), REPL.LineEdit.MIState, Symbol}) +precompile(Tuple{typeof(REPL.LineEdit.setmark), REPL.LineEdit.MIState, Bool}) +precompile(Tuple{typeof(REPL.LineEdit.setup_prefix_keymap), REPL.REPLHistoryProvider, REPL.LineEdit.Prompt}) +precompile(Tuple{typeof(REPL.LineEdit.setup_search_keymap), REPL.REPLHistoryProvider}) +precompile(Tuple{typeof(REPL.LineEdit.show_completions), REPL.LineEdit.PromptState, Array{String, 1}}) +precompile(Tuple{typeof(REPL.LineEdit.terminal), REPL.LineEdit.MIState}) +precompile(Tuple{typeof(REPL.LineEdit.terminal), REPL.LineEdit.PrefixSearchState}) +precompile(Tuple{typeof(REPL.LineEdit.terminal), REPL.LineEdit.PromptState}) +precompile(Tuple{typeof(REPL.LineEdit.terminal), REPL.LineEdit.SearchState}) +precompile(Tuple{typeof(REPL.REPLCompletions.completion_text), REPL.REPLCompletions.PackageCompletion}) +precompile(Tuple{typeof(REPL.REPLCompletions.completions), String, Int64, Module}) +precompile(Tuple{typeof(REPL.REPLCompletions.get_type), Symbol, Module}) +precompile(Tuple{typeof(REPL.REPLCompletions.get_value), Symbol, Module}) +precompile(Tuple{typeof(REPL.Terminals.beep), REPL.LineEdit.MIState}) +precompile(Tuple{typeof(REPL.Terminals.beep), REPL.LineEdit.PromptState, Float64, Float64, Float64}) +precompile(Tuple{typeof(REPL.Terminals.beep), REPL.LineEdit.SearchState}) +precompile(Tuple{typeof(REPL.Terminals.cmove_col), REPL.Terminals.TTYTerminal, Int64}) +precompile(Tuple{typeof(REPL.Terminals.cmove_down), REPL.Terminals.TTYTerminal, Int64}) +precompile(Tuple{typeof(REPL.Terminals.hascolor), REPL.Terminals.TTYTerminal}) +precompile(Tuple{typeof(REPL.Terminals.width), REPL.Terminals.TTYTerminal}) +precompile(Tuple{typeof(Base.banner), REPL.Terminals.TTYTerminal}) +precompile(Tuple{typeof(REPL.ends_with_semicolon), String}) +precompile(Tuple{typeof(REPL.eval), Module, Expr}) +precompile(Tuple{typeof(REPL.eval), Module, String}) +precompile(Tuple{typeof(REPL.eval_user_input), Any, REPL.REPLBackend}) +precompile(Tuple{typeof(REPL.eval_user_input), Expr, REPL.REPLBackend}) +precompile(Tuple{typeof(REPL.filtervalid), Array{Any, 1}}) +precompile(Tuple{typeof(REPL.fuzzysort), String, Array{String, 1}}) +precompile(Tuple{typeof(REPL.helpmode), Base.TTY, String}) +precompile(Tuple{typeof(REPL.helpmode), String}) +precompile(Tuple{typeof(REPL.hist_from_file), REPL.REPLHistoryProvider, Base.IOStream, String}) +precompile(Tuple{typeof(REPL.insert_hlines), Base.TTY, Markdown.MD}) +precompile(Tuple{typeof(REPL.lookup_doc), Symbol}) +precompile(Tuple{typeof(REPL.mode_idx), REPL.REPLHistoryProvider, REPL.LineEdit.Prompt}) +precompile(Tuple{typeof(REPL.prepare_next), REPL.LineEditREPL}) +precompile(Tuple{typeof(REPL.print_response), REPL.LineEditREPL, ArgumentError, Array{Union{Ptr{Nothing}, Base.InterpreterIP}, 1}, Bool, Bool}) +precompile(Tuple{typeof(REPL.print_response), REPL.LineEditREPL, Markdown.MD, Nothing, Bool, Bool}) +precompile(Tuple{typeof(REPL.print_response), REPL.Terminals.TTYTerminal, ArgumentError, Array{Union{Ptr{Nothing}, Base.InterpreterIP}, 1}, Bool, Bool, Nothing}) +precompile(Tuple{typeof(REPL.print_response), REPL.Terminals.TTYTerminal, Markdown.MD, Nothing, Bool, Bool, Nothing}) +precompile(Tuple{typeof(REPL.repl), Base.TTY, Symbol}) +precompile(Tuple{typeof(REPL.repl_latex), Base.TTY, String}) +precompile(Tuple{typeof(REPL.repl_search), Base.TTY, String}) +precompile(Tuple{typeof(REPL.reset), REPL.LineEditREPL}) +precompile(Tuple{typeof(REPL.return_callback), REPL.LineEdit.PromptState}) +precompile(Tuple{typeof(REPL.run_repl), REPL.LineEditREPL, typeof(x->nothing)}) +precompile(Tuple{typeof(REPL.send_to_backend), Expr, Base.Channel{Any}, Base.Channel{Any}}) +precompile(Tuple{typeof(REPL.send_to_backend), Expr, REPL.REPLBackendRef}) +precompile(Tuple{typeof(REPL.send_to_backend), String, Base.Channel{Any}, Base.Channel{Any}}) +precompile(Tuple{typeof(REPL.send_to_backend), String, REPL.REPLBackendRef}) +precompile(Tuple{typeof(REPL.send_to_backend), Symbol, Base.Channel{Any}, Base.Channel{Any}}) +precompile(Tuple{typeof(REPL.send_to_backend), Symbol, REPL.REPLBackendRef}) +precompile(Tuple{typeof(REPL.setup_interface), REPL.LineEditREPL, Bool, Array{Base.Dict{Any, Any}, 1}}) +precompile(Tuple{typeof(REPL.setup_interface), REPL.LineEditREPL, Bool, Base.Dict{Any, Any}}) +precompile(Tuple{typeof(REPL.setup_interface), REPL.LineEditREPL}) +precompile(Tuple{typeof(REPL.start_repl_backend), Base.Channel{Any}, Base.Channel{Any}}) +precompile(Tuple{typeof(Random.__init__)}) +precompile(Tuple{typeof(eval), Module, Expr}) diff --git a/deps/Versions.make b/deps/Versions.make index f40fd4d84c8f8..fa58087b065f7 100644 --- a/deps/Versions.make +++ b/deps/Versions.make @@ -1,5 +1,5 @@ -LLVM_VER = 6.0.1 -LLVM_BB_REL = 1 +LLVM_VER = 6.0.0 +LLVM_BB_REL = 6 PCRE_VER = 10.30 DSFMT_VER = 2.2.3 LAPACK_VER = 3.5.0 diff --git a/deps/checksums/llvm-6.0.0.src.tar.xz/md5 b/deps/checksums/llvm-6.0.0.src.tar.xz/md5 new file mode 100644 index 0000000000000..f2f552adb296b --- /dev/null +++ b/deps/checksums/llvm-6.0.0.src.tar.xz/md5 @@ -0,0 +1 @@ +788a11a35fa62eb008019b37187d09d2 diff --git a/deps/checksums/llvm-6.0.0.src.tar.xz/sha512 b/deps/checksums/llvm-6.0.0.src.tar.xz/sha512 new file mode 100644 index 0000000000000..5d40c04e3e347 --- /dev/null +++ b/deps/checksums/llvm-6.0.0.src.tar.xz/sha512 @@ -0,0 +1 @@ +a71fdd5ddc46f01327ad891cfcc198febdbe10769c57f14d8a4fb7d514621ee4080e1a641200d3353c16a16731d390270499ec6cd3dc98fadc570f3eb6b52b8c diff --git a/deps/checksums/llvm-6.0.1.src.tar.xz/md5 b/deps/checksums/llvm-6.0.1.src.tar.xz/md5 deleted file mode 100644 index 0c7151e84b867..0000000000000 --- a/deps/checksums/llvm-6.0.1.src.tar.xz/md5 +++ /dev/null @@ -1 +0,0 @@ -c88c98709300ce2c285391f387fecce0 diff --git a/deps/checksums/llvm-6.0.1.src.tar.xz/sha512 b/deps/checksums/llvm-6.0.1.src.tar.xz/sha512 deleted file mode 100644 index 2e0ff6e648c08..0000000000000 --- a/deps/checksums/llvm-6.0.1.src.tar.xz/sha512 +++ /dev/null @@ -1 +0,0 @@ -cbbb00eb99cfeb4aff623ee1a5ba075e7b5a76fc00c5f9f539ff28c108598f5708a0369d5bd92683def5a20c2fe60cab7827b42d628dbfcc79b57e0e91b84dd9 diff --git a/deps/llvm.mk b/deps/llvm.mk index e3c9f6c5823a1..4f350aa443b25 100644 --- a/deps/llvm.mk +++ b/deps/llvm.mk @@ -384,35 +384,120 @@ $$(LLVM_BUILDDIR_withtype)/build-compiled: $$(LLVM_SRC_DIR)/$1.patch-applied LLVM_PATCH_PREV := $$(LLVM_SRC_DIR)/$1.patch-applied endef -ifeq ($(LLVM_VER_SHORT),6.0) -ifeq ($(LLVM_VER_PATCH), 0) +ifeq ($(LLVM_VER_SHORT),3.9) +$(eval $(call LLVM_PATCH,llvm-PR22923)) # Remove for 4.0 +$(eval $(call LLVM_PATCH,llvm-arm-fix-prel31)) # Remove for 4.0 +$(eval $(call LLVM_PATCH,llvm-D25865-cmakeshlib)) # Remove for 4.0 +# Cygwin and openSUSE still use win32-threads mingw, https://llvm.org/bugs/show_bug.cgi?id=26365 +$(eval $(call LLVM_PATCH,llvm-3.9.0_threads)) +$(eval $(call LLVM_PATCH,llvm-3.9.0_win64-reloc-dwarf)) # modified version applied as R290809, Remove for 4.0 +$(eval $(call LLVM_PATCH,llvm-3.9.0_D27296-libssp)) +$(eval $(call LLVM_PATCH,llvm-D27609-AArch64-UABS_G3)) # Remove for 4.0 +$(eval $(call LLVM_PATCH,llvm-D27629-AArch64-large_model)) +$(eval $(call LLVM_PATCH,llvm-NVPTX-addrspaces)) # NVPTX +$(eval $(call LLVM_PATCH,llvm-D9168_argument_alignment)) # NVPTX, Remove for 4.0 +$(eval $(call LLVM_PATCH,llvm-D23597_sdag_names)) # NVPTX, Remove for 4.0 +$(eval $(call LLVM_PATCH,llvm-D24300_ptx_intrinsics)) # NVPTX, Remove for 4.0 +$(eval $(call LLVM_PATCH,llvm-D27389)) # Julia issue #19792, Remove for 4.0 +$(eval $(call LLVM_PATCH,llvm-D27397)) # Julia issue #19792, Remove for 4.0 +$(eval $(call LLVM_PATCH,llvm-D28009)) # Julia issue #19792, Remove for 4.0 +$(eval $(call LLVM_PATCH,llvm-D28215_FreeBSD_shlib)) +$(eval $(call LLVM_PATCH,llvm-D28221-avx512)) # mentioned in issue #19797 +$(eval $(call LLVM_PATCH,llvm-PR276266)) # Issue #19976, Remove for 4.0 +$(eval $(call LLVM_PATCH,llvm-PR278088)) # Issue #19976, Remove for 4.0 +$(eval $(call LLVM_PATCH,llvm-PR277939)) # Issue #19976, Remove for 4.0 +$(eval $(call LLVM_PATCH,llvm-PR278321)) # Issue #19976, Remove for 4.0 +$(eval $(call LLVM_PATCH,llvm-PR278923)) # Issue #19976, Remove for 4.0 +$(eval $(call LLVM_PATCH,llvm-D28759-loopclearance)) +$(eval $(call LLVM_PATCH,llvm-D28786-callclearance)) +$(eval $(call LLVM_PATCH,llvm-rL293230-icc17-cmake)) # Remove for 4.0 +$(eval $(call LLVM_PATCH,llvm-D32593)) +$(eval $(call LLVM_PATCH,llvm-D33179)) +$(eval $(call LLVM_PATCH,llvm-PR29010-i386-xmm)) # Remove for 4.0 +$(eval $(call LLVM_PATCH,llvm-3.9.0-D37576-NVPTX-sm_70)) # NVPTX, Remove for 6.0 +$(eval $(call LLVM_PATCH,llvm-D37939-Mem2Reg-Also-handle-memcpy)) +$(eval $(call LLVM_PATCH,llvm-D31524-sovers_4.0)) # Remove for 5.0 +$(eval $(call LLVM_PATCH,llvm-D42262-jumpthreading-not-i1)) +$(eval $(call LLVM_PATCH,llvm-3.9-c_api_nullptr)) +$(eval $(call LLVM_PATCH,llvm-PPC-addrspaces)) # PPC +$(eval $(call LLVM_PATCH,llvm-D30114)) # PPC remove for 5.0 +$(eval $(call LLVM_PATCH,llvm-PR36292)) # PPC fixes #26249, remove for 6.0 +$(eval $(call LLVM_PATCH,llvm-D39297-musl-dynamiclibrary-pre5)) # Remove for 6.0 +$(eval $(call LLVM_PATCH,llvm-D28476-musl-targetlibraryinfo_3.9)) # Remove for 5.0 +$(eval $(call LLVM_PATCH,llvm-D46460)) +ifeq ($(BUILD_LLVM_CLANG),1) +$(eval $(call LLVM_PATCH,compiler_rt-3.9-glibc_2.25.90)) # Remove for 5.0 +$(eval $(call LLVM_PATCH,clang-D28477)) # Remove for 5.0 +endif +else ifeq ($(LLVM_VER_SHORT),4.0) +# Cygwin and openSUSE still use win32-threads mingw, https://llvm.org/bugs/show_bug.cgi?id=26365 +$(eval $(call LLVM_PATCH,llvm-4.0.0_threads)) +$(eval $(call LLVM_PATCH,llvm-3.9.0_D27296-libssp)) $(eval $(call LLVM_PATCH,llvm-D27629-AArch64-large_model_4.0)) -else -$(eval $(call LLVM_PATCH,llvm-D27629-AArch64-large_model_6.0.1)) +$(eval $(call LLVM_PATCH,llvm-D28215_FreeBSD_shlib)) # Remove for 5.0 +$(eval $(call LLVM_PATCH,llvm-D28759-loopclearance)) # Remove for 5.0 +$(eval $(call LLVM_PATCH,llvm-D28786-callclearance_4.0)) # Remove for 5.0 +$(eval $(call LLVM_PATCH,llvm-D32593)) # Remove for 5.0 +$(eval $(call LLVM_PATCH,llvm-D33179)) # Remove for 5.0 +$(eval $(call LLVM_PATCH,llvm-D32203-SORA-non-integral)) # Remove for 5.0 +$(eval $(call LLVM_PATCH,llvm-D33110-codegen-prepare-inttoptr)) +$(eval $(call LLVM_PATCH,llvm-D30478-VNCoercion)) # Remove for 5.0 +$(eval $(call LLVM_PATCH,llvm-VNCoercion-signatures)) # Remove for 5.0 +$(eval $(call LLVM_PATCH,llvm-VNCoercion-template)) # Remove for 5.0 +$(eval $(call LLVM_PATCH,llvm-D32196-LIR-non-integral)) # Remove for 5.0 +$(eval $(call LLVM_PATCH,llvm-D32208-coerce-non-integral)) # Remove for 5.0 +$(eval $(call LLVM_PATCH,llvm-D32623-GVN-non-integral)) # Remove for 5.0 +$(eval $(call LLVM_PATCH,llvm-D33129-scevexpander-non-integral)) # Remove for 5.0 +$(eval $(call LLVM_PATCH,llvm-Yet-another-fix)) +$(eval $(call LLVM_PATCH,llvm-NVPTX-addrspaces)) # NVPTX +$(eval $(call LLVM_PATCH,llvm-4.0.0-D37576-NVPTX-sm_70)) # NVPTX, Remove for 6.0 +$(eval $(call LLVM_PATCH,llvm-loadcse-addrspace_4.0)) +$(eval $(call LLVM_PATCH,llvm-D31524-sovers_4.0)) # Remove for 5.0 +$(eval $(call LLVM_PATCH,llvm-D42262-jumpthreading-not-i1)) +$(eval $(call LLVM_PATCH,llvm-PPC-addrspaces)) # PPC +$(eval $(call LLVM_PATCH,llvm-D30114)) # PPC remove for 5.0 +$(eval $(call LLVM_PATCH,llvm-PR36292)) # PPC fixes #26249, remove for 6.0 +$(eval $(call LLVM_PATCH,llvm-D39297-musl-dynamiclibrary-pre5)) # Remove for 6.0 +$(eval $(call LLVM_PATCH,llvm-D28476-musl-targetlibraryinfo_4.0)) # Remove for 5.0 +$(eval $(call LLVM_PATCH,llvm-D46460)) +ifeq ($(BUILD_LLVM_CLANG),1) +$(eval $(call LLVM_PATCH,compiler_rt-3.9-glibc_2.25.90)) # Remove for 5.0 +$(eval $(call LLVM_PATCH,clang-D28477)) # Remove for 5.0 endif +else ifeq ($(LLVM_VER_SHORT),5.0) +# Cygwin and openSUSE still use win32-threads mingw, https://llvm.org/bugs/show_bug.cgi?id=26365 +$(eval $(call LLVM_PATCH,llvm-5.0.0_threads)) +$(eval $(call LLVM_PATCH,llvm-3.9.0_D27296-libssp)) +$(eval $(call LLVM_PATCH,llvm-D27629-AArch64-large_model_4.0)) +$(eval $(call LLVM_PATCH,llvm-loadcse-addrspace_5.0)) +$(eval $(call LLVM_PATCH,llvm-D34078-vectorize-fdiv)) +$(eval $(call LLVM_PATCH,llvm-5.0-NVPTX-addrspaces)) # NVPTX +$(eval $(call LLVM_PATCH,llvm-4.0.0-D37576-NVPTX-sm_70)) # NVPTX, Remove for 6.0 +$(eval $(call LLVM_PATCH,llvm-D38765-gvn_5.0)) # Remove for 6.0 +$(eval $(call LLVM_PATCH,llvm-D42262-jumpthreading-not-i1)) # remove for 7.0 +$(eval $(call LLVM_PATCH,llvm-PPC-addrspaces)) # PPC +$(eval $(call LLVM_PATCH,llvm-PR36292-5.0)) # PPC fixes #26249, remove for 6.0 +$(eval $(call LLVM_PATCH,llvm-D39297-musl-dynamiclibrary)) # Remove for 6.0 +$(eval $(call LLVM_PATCH,llvm-D46460)) +else ifeq ($(LLVM_VER_SHORT),6.0) +$(eval $(call LLVM_PATCH,llvm-D27629-AArch64-large_model_4.0)) $(eval $(call LLVM_PATCH,llvm-D34078-vectorize-fdiv)) $(eval $(call LLVM_PATCH,llvm-6.0-NVPTX-addrspaces)) # NVPTX $(eval $(call LLVM_PATCH,llvm-D42262-jumpthreading-not-i1)) # remove for 7.0 $(eval $(call LLVM_PATCH,llvm-PPC-addrspaces)) # remove for 7.0 -ifeq ($(LLVM_VER_PATCH), 0) $(eval $(call LLVM_PATCH,llvm-D42260)) # remove for 7.0 $(eval $(call LLVM_PATCH,llvm-rL326843-missing-header)) # remove for 7.0 $(eval $(call LLVM_PATCH,llvm-6.0-r327540)) # remove for 7.0 -endif $(eval $(call LLVM_PATCH,llvm-6.0.0_D27296-libssp)) # remove for 7.0 $(eval $(call LLVM_PATCH,llvm-6.0-D44650)) # mingw32 build fix -ifeq ($(LLVM_VER_PATCH), 0) $(eval $(call LLVM_PATCH,llvm-D45008)) # remove for 7.0 $(eval $(call LLVM_PATCH,llvm-D45070)) # remove for 7.0 $(eval $(call LLVM_PATCH,llvm-6.0.0-ifconv-D45819)) # remove for 7.0 -endif $(eval $(call LLVM_PATCH,llvm-D46460)) -ifeq ($(LLVM_VER_PATCH), 0) $(eval $(call LLVM_PATCH,llvm-rL332680)) # remove for 7.0 $(eval $(call LLVM_PATCH,llvm-rL332682)) # remove for 7.0 $(eval $(call LLVM_PATCH,llvm-rL332302)) # remove for 7.0 $(eval $(call LLVM_PATCH,llvm-rL332694)) # remove for 7.0 -endif $(eval $(call LLVM_PATCH,llvm-rL327898)) # remove for 7.0 $(eval $(call LLVM_PATCH,llvm-6.0-DISABLE_ABI_CHECKS)) $(eval $(call LLVM_PATCH,llvm-OProfile-line-num)) @@ -421,13 +506,18 @@ $(eval $(call LLVM_PATCH,llvm-D49832-SCEVPred)) # Remove for 7.0 $(eval $(call LLVM_PATCH,llvm-rL323946-LSRTy)) # Remove for 7.0 $(eval $(call LLVM_PATCH,llvm-D50010-VNCoercion-ni)) $(eval $(call LLVM_PATCH,llvm-D50167-scev-umin)) -$(eval $(call LLVM_PATCH,llvm-rL326967-aligned-load)) # remove for 7.0 -ifeq ($(LLVM_VER_PATCH), 0) $(eval $(call LLVM_PATCH,llvm-windows-race)) -endif endif # LLVM_VER +# Remove hardcoded OS X requirements in compilter-rt cmake build +ifeq ($(LLVM_VER_SHORT),3.9) +ifeq ($(BUILD_LLVM_CLANG),1) +$(eval $(call LLVM_PATCH,llvm-3.9-osx-10.12)) +endif +endif + # Independent to the llvm version add a JL prefix to the version map +# Depends on `llvm-D31524-sovers_4.0` for LLVM_VER==3.9 $(eval $(call LLVM_PATCH,llvm-symver-jlprefix)) # DO NOT REMOVE diff --git a/deps/patches/compiler_rt-3.9-glibc_2.25.90.patch b/deps/patches/compiler_rt-3.9-glibc_2.25.90.patch new file mode 100644 index 0000000000000..8fe993a637512 --- /dev/null +++ b/deps/patches/compiler_rt-3.9-glibc_2.25.90.patch @@ -0,0 +1,118 @@ +From 8a5e425a68de4d2c80ff00a97bbcb3722a4716da Mon Sep 17 00:00:00 2001 +From: Kostya Serebryany +Date: Thu, 13 Jul 2017 21:59:01 +0000 +Subject: [PATCH] Fix sanitizer build against latest glibc + +Summary: +libsanitizer doesn't build against latest glibc anymore, see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81066 for details. +One of the changes is that stack_t changed from typedef struct sigaltstack { ... } stack_t; to typedef struct { ... } stack_t; for conformance reasons. +And the other change is that the glibc internal __need_res_state macro is now ignored, so when doing +``` +#define __need_res_state +#include +``` +the effect is now the same as just +``` +#include +``` +and thus one doesn't get just the +``` +struct __res_state { ... }; +``` +definition, but newly also the +``` +extern struct __res_state *__res_state(void) __attribute__ ((__const__)); +``` +prototype. So __res_state is no longer a type, but a function. + +Reviewers: kcc, ygribov + +Reviewed By: kcc + +Subscribers: kubamracek + +Differential Revision: https://reviews.llvm.org/D35246 + +git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@307969 91177308-0d34-0410-b5e6-96231b3b80d8 +--- + lib/sanitizer_common/sanitizer_linux.cc | 3 +-- + lib/sanitizer_common/sanitizer_linux.h | 4 +--- + lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc | 2 +- + lib/tsan/rtl/tsan_platform_linux.cc | 2 +- + 4 files changed, 4 insertions(+), 7 deletions(-) + +diff --git a/projects/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc b/projects/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc +index a79a2a155..8c3c1e5d6 100644 +--- a/projects/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc ++++ b/projects/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc +@@ -629,8 +629,7 @@ uptr internal_prctl(int option, uptr arg2, uptr arg3, uptr arg4, uptr arg5) { + } + #endif + +-uptr internal_sigaltstack(const struct sigaltstack *ss, +- struct sigaltstack *oss) { ++uptr internal_sigaltstack(const void *ss, void *oss) { + return internal_syscall(SYSCALL(sigaltstack), (uptr)ss, (uptr)oss); + } + +diff --git a/projects/compiler-rt/lib/sanitizer_common/sanitizer_linux.h b/projects/compiler-rt/lib/sanitizer_common/sanitizer_linux.h +index ee336f7dd..11cad6b80 100644 +--- a/projects/compiler-rt/lib/sanitizer_common/sanitizer_linux.h ++++ b/projects/compiler-rt/lib/sanitizer_common/sanitizer_linux.h +@@ -21,7 +21,6 @@ + #include "sanitizer_platform_limits_posix.h" + + struct link_map; // Opaque type returned by dlopen(). +-struct sigaltstack; + + namespace __sanitizer { + // Dirent structure for getdents(). Note that this structure is different from +@@ -30,8 +29,7 @@ struct linux_dirent; + + // Syscall wrappers. + uptr internal_getdents(fd_t fd, struct linux_dirent *dirp, unsigned int count); +-uptr internal_sigaltstack(const struct sigaltstack* ss, +- struct sigaltstack* oss); ++uptr internal_sigaltstack(const void* ss, void* oss); + uptr internal_sigprocmask(int how, __sanitizer_sigset_t *set, + __sanitizer_sigset_t *oldset); + +diff --git a/projects/compiler-rt/lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc b/projects/compiler-rt/lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc +index 03f73ae88..d7fa5f645 100644 +--- a/projects/compiler-rt/lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc ++++ b/projects/compiler-rt/lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc +@@ -287,7 +287,7 @@ static int TracerThread(void* argument) { + + // Alternate stack for signal handling. + InternalScopedBuffer handler_stack_memory(kHandlerStackSize); +- struct sigaltstack handler_stack; ++ stack_t handler_stack; + internal_memset(&handler_stack, 0, sizeof(handler_stack)); + handler_stack.ss_sp = handler_stack_memory.data(); + handler_stack.ss_size = kHandlerStackSize; +diff --git a/projects/compiler-rt/lib/tsan/rtl/tsan_platform_linux.cc b/projects/compiler-rt/lib/tsan/rtl/tsan_platform_linux.cc +index 0ba01babe..ead1e5704 100644 +--- a/projects/compiler-rt/lib/tsan/rtl/tsan_platform_linux.cc ++++ b/projects/compiler-rt/lib/tsan/rtl/tsan_platform_linux.cc +@@ -286,7 +286,7 @@ void InitializePlatform() { + int ExtractResolvFDs(void *state, int *fds, int nfd) { + #if SANITIZER_LINUX && !SANITIZER_ANDROID + int cnt = 0; +- __res_state *statp = (__res_state*)state; ++ struct __res_state *statp = (struct __res_state*)state; + for (int i = 0; i < MAXNS && cnt < nfd; i++) { + if (statp->_u._ext.nsaddrs[i] && statp->_u._ext.nssocks[i] != -1) + fds[cnt++] = statp->_u._ext.nssocks[i]; +diff --git a/projects/compiler-rt/lib/esan/esan_sideline_linux.cpp b/projects/compiler-rt/lib/esan/esan_sideline_linux.cpp +index d04f5909d6a2..bc272dfe49f8 100644 +--- a/projects/compiler-rt/lib/esan/esan_sideline_linux.cpp ++++ b/projects/compiler-rt/lib/esan/esan_sideline_linux.cpp +@@ -70,7 +70,7 @@ int SidelineThread::runSideline(void *Arg) { + + // Set up a signal handler on an alternate stack for safety. + InternalScopedBuffer StackMap(SigAltStackSize); +- struct sigaltstack SigAltStack; ++ stack_t SigAltStack; + SigAltStack.ss_sp = StackMap.data(); + SigAltStack.ss_size = SigAltStackSize; + SigAltStack.ss_flags = 0; diff --git a/deps/patches/lldb-3.7.1.patch b/deps/patches/lldb-3.7.1.patch new file mode 100644 index 0000000000000..15ace008c4991 --- /dev/null +++ b/deps/patches/lldb-3.7.1.patch @@ -0,0 +1,41 @@ +diff --git a/tools/lldb/source/Host/Makefile b/tools/lldb/source/Host/Makefile +index a8e4260..da90c8c 100644 +--- a/tools/lldb/source/Host/Makefile ++++ b/tools/lldb/source/Host/Makefile +@@ -14,7 +14,7 @@ include $(LEVEL)/Makefile.config + + define DIR_SOURCES + SOURCES += $$(addprefix $(1)/,$$(notdir $$(wildcard $$(PROJ_SRC_DIR)/$(1)/*.cpp \ +- $$(PROJ_SRC_DIR)/*.cc $$(PROJ_SRC_DIR)/$(1)/*.c))) ++ $$(PROJ_SRC_DIR)/*.cc $$(PROJ_SRC_DIR)/$(1)/*.c $$(PROJ_SRC_DIR)/$(1)/*.mm))) + endef + + $(eval $(call DIR_SOURCES,common)) +@@ -22,6 +22,15 @@ $(eval $(call DIR_SOURCES,common)) + ifeq ($(HOST_OS),Darwin) + $(eval $(call DIR_SOURCES,posix)) + $(eval $(call DIR_SOURCES,macosx)) ++CFCPP_SOURCES = \ ++ $(addprefix macosx/cfcpp/,$(notdir $(wildcard $(PROJ_SRC_DIR)/macosx/cfcpp/*.cpp))) ++SOURCES += $(CFCPP_SOURCES) ++ ++CFCPP_BaseNameSources := $(sort $(basename $(CFCPP_SOURCES))) ++CFCPP_OBJECTS := $(CFCPP_BaseNameSources:%=$(ObjDir)/%.o) ++ ++# Make sure the cfcpp output directory exists ++$(CFCPP_OBJECTS): $(ObjDir)/cfcpp/.dir + endif + + ifeq ($(HOST_OS),Linux) +@@ -34,6 +43,11 @@ $(eval $(call DIR_SOURCES,posix)) + $(eval $(call DIR_SOURCES,freebsd)) + endif + ++ifeq ($(HOST_OS),NetBSD) ++$(eval $(call DIR_SOURCES,posix)) ++$(eval $(call DIR_SOURCES,netbsd)) ++endif ++ + ifeq ($(HOST_OS),MingW) + $(eval $(call DIR_SOURCES,windows)) + endif diff --git a/deps/patches/llvm-3.9-c_api_nullptr.patch b/deps/patches/llvm-3.9-c_api_nullptr.patch new file mode 100644 index 0000000000000..606d2944deddd --- /dev/null +++ b/deps/patches/llvm-3.9-c_api_nullptr.patch @@ -0,0 +1,39 @@ +diff --git a/lib/IR/Core.cpp b/lib/IR/Core.cpp +index 1cf17b1f311..a969e08cabc 100644 +--- a/lib/IR/Core.cpp ++++ b/lib/IR/Core.cpp +@@ -1842,12 +1842,16 @@ void LLVMAddAttributeAtIndex(LLVMValueRef F, LLVMAttributeIndex Idx, + + unsigned LLVMGetAttributeCountAtIndex(LLVMValueRef F, LLVMAttributeIndex Idx) { + auto *ASN = AttributeSetNode::get(unwrap(F)->getAttributes(), Idx); ++ if (!ASN) ++ return 0; + return ASN->getNumAttributes(); + } + + void LLVMGetAttributesAtIndex(LLVMValueRef F, LLVMAttributeIndex Idx, + LLVMAttributeRef *Attrs) { + auto *ASN = AttributeSetNode::get(unwrap(F)->getAttributes(), Idx); ++ if (!ASN) ++ return; + for (auto A: make_range(ASN->begin(), ASN->end())) + *Attrs++ = wrap(A); + } +@@ -2173,6 +2177,8 @@ unsigned LLVMGetCallSiteAttributeCount(LLVMValueRef C, + LLVMAttributeIndex Idx) { + auto CS = CallSite(unwrap(C)); + auto *ASN = AttributeSetNode::get(CS.getAttributes(), Idx); ++ if (!ASN) ++ return 0; + return ASN->getNumAttributes(); + } + +@@ -2180,6 +2186,8 @@ void LLVMGetCallSiteAttributes(LLVMValueRef C, LLVMAttributeIndex Idx, + LLVMAttributeRef *Attrs) { + auto CS = CallSite(unwrap(C)); + auto *ASN = AttributeSetNode::get(CS.getAttributes(), Idx); ++ if (!ASN) ++ return; + for (auto A: make_range(ASN->begin(), ASN->end())) + *Attrs++ = wrap(A); + } diff --git a/deps/patches/llvm-3.9-osx-10.12.patch b/deps/patches/llvm-3.9-osx-10.12.patch new file mode 100644 index 0000000000000..a9148e5e947e7 --- /dev/null +++ b/deps/patches/llvm-3.9-osx-10.12.patch @@ -0,0 +1,33 @@ +--- a/projects/compiler-rt/cmake/builtin-config-ix.cmake ++++ b/projects/compiler-rt/cmake/builtin-config-ix.cmake +@@ -57,9 +57,6 @@ + find_darwin_sdk_dir(DARWIN_tvos_SYSROOT appletvos) + + set(DARWIN_EMBEDDED_PLATFORMS) +- set(DARWIN_osx_BUILTIN_MIN_VER 10.5) +- set(DARWIN_osx_BUILTIN_MIN_VER_FLAG +- -mmacosx-version-min=${DARWIN_osx_BUILTIN_MIN_VER}) + + if(COMPILER_RT_ENABLE_IOS) + list(APPEND DARWIN_EMBEDDED_PLATFORMS ios) +@@ -101,20 +98,6 @@ + set(CAN_TARGET_${arch} 1) + endforeach() + +- # Need to build a 10.4 compatible libclang_rt +- set(DARWIN_10.4_SYSROOT ${DARWIN_osx_SYSROOT}) +- set(DARWIN_10.4_BUILTIN_MIN_VER 10.4) +- set(DARWIN_10.4_BUILTIN_MIN_VER_FLAG +- -mmacosx-version-min=${DARWIN_10.4_BUILTIN_MIN_VER}) +- set(DARWIN_10.4_SKIP_CC_KEXT On) +- darwin_test_archs(10.4 DARWIN_10.4_ARCHS i386 x86_64) +- message(STATUS "OSX 10.4 supported builtin arches: ${DARWIN_10.4_ARCHS}") +- if(DARWIN_10.4_ARCHS) +- # don't include the Haswell slice in the 10.4 compatibility library +- list(REMOVE_ITEM DARWIN_10.4_ARCHS x86_64h) +- list(APPEND BUILTIN_SUPPORTED_OS 10.4) +- endif() +- + foreach(platform ${DARWIN_EMBEDDED_PLATFORMS}) + if(DARWIN_${platform}sim_SYSROOT) + set(DARWIN_${platform}sim_BUILTIN_MIN_VER diff --git a/deps/patches/llvm-3.9.0-D37576-NVPTX-sm_70.patch b/deps/patches/llvm-3.9.0-D37576-NVPTX-sm_70.patch new file mode 100644 index 0000000000000..0ac8e44cc5c64 --- /dev/null +++ b/deps/patches/llvm-3.9.0-D37576-NVPTX-sm_70.patch @@ -0,0 +1,62 @@ +From 4059d374ce981827223ab6b1dae7af4ec5f8e74a Mon Sep 17 00:00:00 2001 +From: Artem Belevich +Date: Thu, 7 Sep 2017 18:14:32 +0000 +Subject: [PATCH] [CUDA] Added rudimentary support for CUDA-9 and sm_70. + +For now CUDA-9 is not included in the list of CUDA versions clang +searches for, so the path to CUDA-9 must be explicitly passed +via --cuda-path=. + +On LLVM side NVPTX added sm_70 GPU type which bumps required +PTX version to 6.0, but otherwise is equivalent to sm_62 at the moment. + +Differential Revision: https://reviews.llvm.org/D37576 + +git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@312734 91177308-0d34-0410-b5e6-96231b3b80d8 +--- + lib/Target/NVPTX/NVPTX.td | 5 +++++ + test/CodeGen/NVPTX/sm-version-70.ll | 5 +++++ + 2 files changed, 10 insertions(+) + create mode 100644 test/CodeGen/NVPTX/sm-version-70.ll + +diff --git a/lib/Target/NVPTX/NVPTX.td b/lib/Target/NVPTX/NVPTX.td +index c77ddbc9978..aba37d36359 100644 +--- a/lib/Target/NVPTX/NVPTX.td ++++ b/lib/Target/NVPTX/NVPTX.td +@@ -50,6 +50,8 @@ def SM61 : SubtargetFeature<"sm_61", "SmVersion", "61", + "Target SM 6.1">; + def SM62 : SubtargetFeature<"sm_62", "SmVersion", "62", + "Target SM 6.2">; ++def SM70 : SubtargetFeature<"sm_70", "SmVersion", "70", ++ "Target SM 7.0">; + + def SATOM : SubtargetFeature<"satom", "HasAtomScope", "true", + "Atomic operations with scope">; +@@ -67,6 +69,8 @@ def PTX43 : SubtargetFeature<"ptx43", "PTXVersion", "43", + "Use PTX version 4.3">; + def PTX50 : SubtargetFeature<"ptx50", "PTXVersion", "50", + "Use PTX version 5.0">; ++def PTX60 : SubtargetFeature<"ptx60", "PTXVersion", "60", ++ "Use PTX version 6.0">; + + //===----------------------------------------------------------------------===// + // NVPTX supported processors. +@@ -87,6 +91,7 @@ def : Proc<"sm_53", [SM53, PTX42]>; + def : Proc<"sm_60", [SM60, PTX50]>; + def : Proc<"sm_61", [SM61, PTX50]>; + def : Proc<"sm_62", [SM62, PTX50]>; ++def : Proc<"sm_70", [SM70, PTX60]>; + + def NVPTXInstrInfo : InstrInfo { + } +diff --git a/test/CodeGen/NVPTX/sm-version-70.ll b/test/CodeGen/NVPTX/sm-version-70.ll +new file mode 100644 +index 00000000000..8b72d50747a +--- /dev/null ++++ b/test/CodeGen/NVPTX/sm-version-70.ll +@@ -0,0 +1,5 @@ ++; RUN: llc < %s -march=nvptx -mcpu=sm_70 | FileCheck %s ++; RUN: llc < %s -march=nvptx64 -mcpu=sm_70 | FileCheck %s ++ ++; CHECK: .version 6.0 ++; CHECK: .target sm_70 diff --git a/deps/patches/llvm-3.9.0_D27296-libssp.patch b/deps/patches/llvm-3.9.0_D27296-libssp.patch new file mode 100644 index 0000000000000..7bdfa67f80034 --- /dev/null +++ b/deps/patches/llvm-3.9.0_D27296-libssp.patch @@ -0,0 +1,47 @@ +From e95516f77127ca534775d5f8d8cbb6e2e9c3f993 Mon Sep 17 00:00:00 2001 +From: Valentin Churavy +Date: Thu, 1 Dec 2016 18:48:30 +0900 +Subject: [PATCH] Don't assume mingw is providing SSP functions + +Summary: +Mingw is indirectly targeting msvcrt*.dll and we can't guarantee that +these functions will be available during JIT'ing. + +Differential Revision: https://reviews.llvm.org/D27296 +--- + lib/Target/X86/X86ISelLowering.cpp | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp +index 44eae35..a932792 100644 +--- a/lib/Target/X86/X86ISelLowering.cpp ++++ b/lib/Target/X86/X86ISelLowering.cpp +@@ -2016,7 +2016,7 @@ Value *X86TargetLowering::getIRStackGuard(IRBuilder<> &IRB) const { + + void X86TargetLowering::insertSSPDeclarations(Module &M) const { + // MSVC CRT provides functionalities for stack protection. +- if (Subtarget.getTargetTriple().isOSMSVCRT()) { ++ if (Subtarget.getTargetTriple().isWindowsMSVCEnvironment()) { + // MSVC CRT has a global variable holding security cookie. + M.getOrInsertGlobal("__security_cookie", + Type::getInt8PtrTy(M.getContext())); +@@ -2038,14 +2038,14 @@ void X86TargetLowering::insertSSPDeclarations(Module &M) const { + + Value *X86TargetLowering::getSDagStackGuard(const Module &M) const { + // MSVC CRT has a global variable holding security cookie. +- if (Subtarget.getTargetTriple().isOSMSVCRT()) ++ if (Subtarget.getTargetTriple().isWindowsMSVCEnvironment()) + return M.getGlobalVariable("__security_cookie"); + return TargetLowering::getSDagStackGuard(M); + } + + Value *X86TargetLowering::getSSPStackGuardCheck(const Module &M) const { + // MSVC CRT has a function to validate security cookie. +- if (Subtarget.getTargetTriple().isOSMSVCRT()) ++ if (Subtarget.getTargetTriple().isWindowsMSVCEnvironment()) + return M.getFunction("__security_check_cookie"); + return TargetLowering::getSSPStackGuardCheck(M); + } +-- +2.10.2 + diff --git a/deps/patches/llvm-3.9.0_threads.patch b/deps/patches/llvm-3.9.0_threads.patch new file mode 100644 index 0000000000000..1b28f8131322d --- /dev/null +++ b/deps/patches/llvm-3.9.0_threads.patch @@ -0,0 +1,5545 @@ +From d1cc48989b13780f21c408fef17dceb104a09c9d Mon Sep 17 00:00:00 2001 +From: Alex Crichton +Date: Thu, 28 Jan 2016 20:44:50 -0800 +Subject: [PATCH] Don't compile usage of std::thread + +As of the time of this writing it's not actually used anywhere meaningfullly +throughout the LLVM repo that we need, and it unfortunately uses `std::thread` +which isn't available in mingw-w64 toolchains with the win32 threading model +(the one that we use). + +The change made to achive this was to just always use the single-threaded +support in `include/llvm/Support/thread.h`, and hopefuly that'll be enough... + +For reference, the upstream LLVM bug has been reported [1] + +[1]: https://llvm.org/bugs/show_bug.cgi?id=26365 +--- + include/llvm/ExecutionEngine/Orc/RPCChannel.h | 13 - + include/llvm/ExecutionEngine/Orc/RPCUtils.h | 16 +- + include/llvm/Support/ThreadPool.h | 4 + + include/llvm/Support/thread.h | 2 +- + lib/CodeGen/ParallelCG.cpp | 2 + + lib/LTO/ThinLTOCodeGenerator.cpp | 4 +- + lib/Support/ThreadPool.cpp | 6 +- + test/CMakeLists.txt | 1 - + tools/lli/CMakeLists.txt | 5 - + tools/lli/ChildTarget/CMakeLists.txt | 10 - + tools/lli/ChildTarget/ChildTarget.cpp | 78 -- + tools/lli/ChildTarget/LLVMBuild.txt | 21 - + tools/lli/LLVMBuild.txt | 3 - + tools/lli/OrcLazyJIT.cpp | 158 ---- + tools/lli/OrcLazyJIT.h | 163 ---- + tools/lli/RemoteJITUtils.h | 152 --- + tools/lli/lli.cpp | 7 + + tools/llvm-cov/CMakeLists.txt | 18 +- + tools/llvm-cov/CodeCoverage.cpp | 727 --------------- + tools/llvm-cov/CoverageFilters.cpp | 59 -- + tools/llvm-cov/CoverageFilters.h | 127 --- + tools/llvm-cov/CoverageReport.cpp | 235 ----- + tools/llvm-cov/CoverageReport.h | 41 - + tools/llvm-cov/CoverageSummaryInfo.cpp | 71 -- + tools/llvm-cov/CoverageSummaryInfo.h | 162 ---- + tools/llvm-cov/CoverageViewOptions.h | 52 -- + tools/llvm-cov/RenderingSupport.h | 61 -- + tools/llvm-cov/SourceCoverageView.cpp | 233 ----- + tools/llvm-cov/SourceCoverageView.h | 285 ------ + tools/llvm-cov/SourceCoverageViewHTML.cpp | 436 --------- + tools/llvm-cov/SourceCoverageViewHTML.h | 83 -- + tools/llvm-cov/SourceCoverageViewText.cpp | 213 ----- + tools/llvm-cov/SourceCoverageViewText.h | 83 -- + tools/llvm-cov/TestingSupport.cpp | 92 -- + tools/llvm-cov/gcov.cpp | 145 --- + tools/llvm-cov/llvm-cov.cpp | 79 -- + tools/sancov/sancov.cc | 1244 +------------------------ + 37 files changed, 43 insertions(+), 5048 deletions(-) + delete mode 100644 tools/lli/ChildTarget/CMakeLists.txt + delete mode 100644 tools/lli/ChildTarget/ChildTarget.cpp + delete mode 100644 tools/lli/ChildTarget/LLVMBuild.txt + delete mode 100644 tools/lli/OrcLazyJIT.cpp + delete mode 100644 tools/lli/OrcLazyJIT.h + delete mode 100644 tools/lli/RemoteJITUtils.h + delete mode 100644 tools/llvm-cov/CodeCoverage.cpp + delete mode 100644 tools/llvm-cov/CoverageFilters.cpp + delete mode 100644 tools/llvm-cov/CoverageFilters.h + delete mode 100644 tools/llvm-cov/CoverageReport.cpp + delete mode 100644 tools/llvm-cov/CoverageReport.h + delete mode 100644 tools/llvm-cov/CoverageSummaryInfo.cpp + delete mode 100644 tools/llvm-cov/CoverageSummaryInfo.h + delete mode 100644 tools/llvm-cov/CoverageViewOptions.h + delete mode 100644 tools/llvm-cov/RenderingSupport.h + delete mode 100644 tools/llvm-cov/SourceCoverageView.cpp + delete mode 100644 tools/llvm-cov/SourceCoverageView.h + delete mode 100644 tools/llvm-cov/SourceCoverageViewHTML.cpp + delete mode 100644 tools/llvm-cov/SourceCoverageViewHTML.h + delete mode 100644 tools/llvm-cov/SourceCoverageViewText.cpp + delete mode 100644 tools/llvm-cov/SourceCoverageViewText.h + delete mode 100644 tools/llvm-cov/TestingSupport.cpp + delete mode 100644 tools/llvm-cov/gcov.cpp + +diff --git a/include/llvm/ExecutionEngine/Orc/RPCChannel.h b/include/llvm/ExecutionEngine/Orc/RPCChannel.h +index c569e3c..9fb0141 100644 +--- a/include/llvm/ExecutionEngine/Orc/RPCChannel.h ++++ b/include/llvm/ExecutionEngine/Orc/RPCChannel.h +@@ -40,42 +40,29 @@ class RPCChannel { + + /// Flush the stream if possible. + virtual Error send() = 0; +- +- /// Get the lock for stream reading. +- std::mutex &getReadLock() { return readLock; } +- +- /// Get the lock for stream writing. +- std::mutex &getWriteLock() { return writeLock; } +- +-private: +- std::mutex readLock, writeLock; + }; + + /// Notify the channel that we're starting a message send. + /// Locks the channel for writing. + inline Error startSendMessage(RPCChannel &C) { +- C.getWriteLock().lock(); + return Error::success(); + } + + /// Notify the channel that we're ending a message send. + /// Unlocks the channel for writing. + inline Error endSendMessage(RPCChannel &C) { +- C.getWriteLock().unlock(); + return Error::success(); + } + + /// Notify the channel that we're starting a message receive. + /// Locks the channel for reading. + inline Error startReceiveMessage(RPCChannel &C) { +- C.getReadLock().lock(); + return Error::success(); + } + + /// Notify the channel that we're ending a message receive. + /// Unlocks the channel for reading. + inline Error endReceiveMessage(RPCChannel &C) { +- C.getReadLock().unlock(); + return Error::success(); + } + +diff --git a/include/llvm/ExecutionEngine/Orc/RPCUtils.h b/include/llvm/ExecutionEngine/Orc/RPCUtils.h +index 966a496..b6c8ebd 100644 +--- a/include/llvm/ExecutionEngine/Orc/RPCUtils.h ++++ b/include/llvm/ExecutionEngine/Orc/RPCUtils.h +@@ -102,6 +102,7 @@ class RPCBase { + + template + static Error readResult(ChannelT &C, std::promise &P) { ++#if 0 + RetT Val; + auto Err = deserialize(C, Val); + auto Err2 = endReceiveMessage(C); +@@ -112,11 +113,14 @@ class RPCBase { + return Err; + } + P.set_value(std::move(Val)); ++#endif + return Error::success(); + } + + static void abandon(std::promise &P) { ++#if 0 + P.set_value(OptionalReturn()); ++#endif + } + + template +@@ -159,11 +163,17 @@ class RPCBase { + template + static Error readResult(ChannelT &C, std::promise &P) { + // Void functions don't have anything to deserialize, so we're good. ++#if 0 + P.set_value(true); ++#endif + return endReceiveMessage(C); + } + +- static void abandon(std::promise &P) { P.set_value(false); } ++ static void abandon(std::promise &P) { ++#if 0 ++ P.set_value(false); ++#endif ++ } + + template + static Error respond(ChannelT &C, SequenceNumberT SeqNo, +@@ -617,13 +627,11 @@ class RPC : public RPCBase { + } + + void reset() { +- std::lock_guard Lock(SeqNoLock); + NextSequenceNumber = 0; + FreeSequenceNumbers.clear(); + } + + SequenceNumberT getSequenceNumber() { +- std::lock_guard Lock(SeqNoLock); + if (FreeSequenceNumbers.empty()) + return NextSequenceNumber++; + auto SequenceNumber = FreeSequenceNumbers.back(); +@@ -632,12 +640,10 @@ class RPC : public RPCBase { + } + + void releaseSequenceNumber(SequenceNumberT SequenceNumber) { +- std::lock_guard Lock(SeqNoLock); + FreeSequenceNumbers.push_back(SequenceNumber); + } + + private: +- std::mutex SeqNoLock; + SequenceNumberT NextSequenceNumber = 0; + std::vector FreeSequenceNumbers; + }; +diff --git a/include/llvm/Support/ThreadPool.h b/include/llvm/Support/ThreadPool.h +index 665cec2..c3aa64d 100644 +--- a/include/llvm/Support/ThreadPool.h ++++ b/include/llvm/Support/ThreadPool.h +@@ -16,6 +16,8 @@ + + #include "llvm/Support/thread.h" + ++# if 0 ++ + #ifdef _MSC_VER + // concrt.h depends on eh.h for __uncaught_exception declaration + // even if we disable exceptions. +@@ -134,4 +136,6 @@ class ThreadPool { + }; + } + ++# endif ++ + #endif // LLVM_SUPPORT_THREAD_POOL_H +diff --git a/include/llvm/Support/thread.h b/include/llvm/Support/thread.h +index 9c45418..27d42d2 100644 +--- a/include/llvm/Support/thread.h ++++ b/include/llvm/Support/thread.h +@@ -19,7 +19,7 @@ + + #include "llvm/Config/llvm-config.h" + +-#if LLVM_ENABLE_THREADS ++#if LLVM_ENABLE_THREADS && 0 + + #ifdef _MSC_VER + // concrt.h depends on eh.h for __uncaught_exception declaration +diff --git a/lib/CodeGen/ParallelCG.cpp b/lib/CodeGen/ParallelCG.cpp +index ccdaec1..1f35590 100644 +--- a/lib/CodeGen/ParallelCG.cpp ++++ b/lib/CodeGen/ParallelCG.cpp +@@ -49,6 +49,7 @@ std::unique_ptr llvm::splitCodeGen( + return M; + } + ++#if 0 + // Create ThreadPool in nested scope so that threads will be joined + // on destruction. + { +@@ -95,5 +96,6 @@ std::unique_ptr llvm::splitCodeGen( + PreserveLocals); + } + ++#endif + return {}; + } +diff --git a/lib/LTO/ThinLTOCodeGenerator.cpp b/lib/LTO/ThinLTOCodeGenerator.cpp +index bfb0980..e4f9977 100644 +--- a/lib/LTO/ThinLTOCodeGenerator.cpp ++++ b/lib/LTO/ThinLTOCodeGenerator.cpp +@@ -64,7 +64,7 @@ extern cl::opt LTODiscardValueNames; + namespace { + + static cl::opt ThreadCount("threads", +- cl::init(std::thread::hardware_concurrency())); ++ cl::init(1)); + + static void diagnosticHandler(const DiagnosticInfo &DI) { + DiagnosticPrinterRawOStream DP(errs()); +@@ -667,6 +667,7 @@ std::unique_ptr ThinLTOCodeGenerator::codegen(Module &TheModule) { + + // Main entry point for the ThinLTO processing + void ThinLTOCodeGenerator::run() { ++#if 0 + if (CodeGenOnly) { + // Perform only parallel codegen and return. + ThreadPool Pool; +@@ -832,4 +833,5 @@ void ThinLTOCodeGenerator::run() { + // If statistics were requested, print them out now. + if (llvm::AreStatisticsEnabled()) + llvm::PrintStatistics(); ++#endif + } +diff --git a/lib/Support/ThreadPool.cpp b/lib/Support/ThreadPool.cpp +index db03a4d..71f4933 100644 +--- a/lib/Support/ThreadPool.cpp ++++ b/lib/Support/ThreadPool.cpp +@@ -11,6 +11,8 @@ + // + //===----------------------------------------------------------------------===// + ++#if 0 ++ + #include "llvm/Support/ThreadPool.h" + + #include "llvm/Config/llvm-config.h" +@@ -18,7 +20,7 @@ + + using namespace llvm; + +-#if LLVM_ENABLE_THREADS ++#if LLVM_ENABLE_THREADS && 0 + + // Default to std::thread::hardware_concurrency + ThreadPool::ThreadPool() : ThreadPool(std::thread::hardware_concurrency()) {} +@@ -156,3 +158,5 @@ ThreadPool::~ThreadPool() { + } + + #endif ++ ++#endif +diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt +index e5773bd..40122bd 100644 +--- a/test/CMakeLists.txt ++++ b/test/CMakeLists.txt +@@ -27,7 +27,6 @@ set(LLVM_TEST_DEPENDS + count + llc + lli +- lli-child-target + llvm-ar + llvm-as + llvm-bcanalyzer +diff --git a/tools/lli/CMakeLists.txt b/tools/lli/CMakeLists.txt +index 2bdd066..8a4c9d0 100644 +--- a/tools/lli/CMakeLists.txt ++++ b/tools/lli/CMakeLists.txt +@@ -1,7 +1,3 @@ +-if ( LLVM_INCLUDE_UTILS ) +- add_subdirectory(ChildTarget) +-endif() +- + set(LLVM_LINK_COMPONENTS + CodeGen + Core +diff --git a/tools/lli/ChildTarget/CMakeLists.txt b/tools/lli/ChildTarget/CMakeLists.txt +deleted file mode 100644 +index e4fe0c7..0000000 +--- a/tools/lli/ChildTarget/CMakeLists.txt ++++ /dev/null +@@ -1,10 +0,0 @@ +-set(LLVM_LINK_COMPONENTS +- OrcJIT +- RuntimeDyld +- Support +- ) +- +-add_llvm_utility(lli-child-target +- ChildTarget.cpp +-) +- +diff --git a/tools/lli/ChildTarget/ChildTarget.cpp b/tools/lli/ChildTarget/ChildTarget.cpp +deleted file mode 100644 +index f6d2413..0000000 +--- a/tools/lli/ChildTarget/ChildTarget.cpp ++++ /dev/null +@@ -1,78 +0,0 @@ +-#include "llvm/ExecutionEngine/Orc/OrcABISupport.h" +-#include "llvm/ExecutionEngine/Orc/OrcRemoteTargetServer.h" +-#include "llvm/Support/Debug.h" +-#include "llvm/Support/DynamicLibrary.h" +-#include "llvm/Support/Process.h" +-#include +- +-#include "../RemoteJITUtils.h" +- +-using namespace llvm; +-using namespace llvm::orc; +-using namespace llvm::sys; +- +-#ifdef __x86_64__ +-typedef OrcX86_64_SysV HostOrcArch; +-#else +-typedef OrcGenericABI HostOrcArch; +-#endif +- +-ExitOnError ExitOnErr; +- +-int main(int argc, char *argv[]) { +- +- if (argc != 3) { +- errs() << "Usage: " << argv[0] << " \n"; +- return 1; +- } +- +- ExitOnErr.setBanner(std::string(argv[0]) + ":"); +- +- int InFD; +- int OutFD; +- { +- std::istringstream InFDStream(argv[1]), OutFDStream(argv[2]); +- InFDStream >> InFD; +- OutFDStream >> OutFD; +- } +- +- if (sys::DynamicLibrary::LoadLibraryPermanently(nullptr)) { +- errs() << "Error loading program symbols.\n"; +- return 1; +- } +- +- auto SymbolLookup = [](const std::string &Name) { +- return RTDyldMemoryManager::getSymbolAddressInProcess(Name); +- }; +- +- auto RegisterEHFrames = [](uint8_t *Addr, uint32_t Size) { +- RTDyldMemoryManager::registerEHFramesInProcess(Addr, Size); +- }; +- +- auto DeregisterEHFrames = [](uint8_t *Addr, uint32_t Size) { +- RTDyldMemoryManager::deregisterEHFramesInProcess(Addr, Size); +- }; +- +- FDRPCChannel Channel(InFD, OutFD); +- typedef remote::OrcRemoteTargetServer JITServer; +- JITServer Server(Channel, SymbolLookup, RegisterEHFrames, DeregisterEHFrames); +- +- while (1) { +- uint32_t RawId; +- ExitOnErr(Server.startReceivingFunction(Channel, RawId)); +- auto Id = static_cast(RawId); +- switch (Id) { +- case JITServer::TerminateSessionId: +- ExitOnErr(Server.handleTerminateSession()); +- return 0; +- default: +- ExitOnErr(Server.handleKnownFunction(Id)); +- break; +- } +- } +- +- close(InFD); +- close(OutFD); +- +- return 0; +-} +diff --git a/tools/lli/ChildTarget/LLVMBuild.txt b/tools/lli/ChildTarget/LLVMBuild.txt +deleted file mode 100644 +index daf6df1..0000000 +--- a/tools/lli/ChildTarget/LLVMBuild.txt ++++ /dev/null +@@ -1,21 +0,0 @@ +-;===- ./tools/lli/ChildTarget/LLVMBuild.txt --------------------*- Conf -*--===; +-; +-; The LLVM Compiler Infrastructure +-; +-; This file is distributed under the University of Illinois Open Source +-; License. See LICENSE.TXT for details. +-; +-;===------------------------------------------------------------------------===; +-; +-; This is an LLVMBuild description file for the components in this subdirectory. +-; +-; For more information on the LLVMBuild system, please see: +-; +-; http://llvm.org/docs/LLVMBuild.html +-; +-;===------------------------------------------------------------------------===; +- +-[component_0] +-type = Tool +-name = lli-child-target +-parent = lli +diff --git a/tools/lli/LLVMBuild.txt b/tools/lli/LLVMBuild.txt +index 9d889bf..4738504 100644 +--- a/tools/lli/LLVMBuild.txt ++++ b/tools/lli/LLVMBuild.txt +@@ -15,9 +15,6 @@ + ; + ;===------------------------------------------------------------------------===; + +-[common] +-subdirectories = ChildTarget +- + [component_0] + type = Tool + name = lli +diff --git a/tools/lli/OrcLazyJIT.cpp b/tools/lli/OrcLazyJIT.cpp +index b13e769..8b13789 100644 +--- a/tools/lli/OrcLazyJIT.cpp ++++ b/tools/lli/OrcLazyJIT.cpp +@@ -1,158 +1 @@ +-//===------ OrcLazyJIT.cpp - Basic Orc-based JIT for lazy execution -------===// +-// +-// The LLVM Compiler Infrastructure +-// +-// This file is distributed under the University of Illinois Open Source +-// License. See LICENSE.TXT for details. +-// +-//===----------------------------------------------------------------------===// +- +-#include "OrcLazyJIT.h" +-#include "llvm/ExecutionEngine/Orc/OrcABISupport.h" +-#include "llvm/Support/Debug.h" +-#include "llvm/Support/DynamicLibrary.h" +-#include +-#include +- +-using namespace llvm; +- +-namespace { +- +- enum class DumpKind { NoDump, DumpFuncsToStdOut, DumpModsToStdErr, +- DumpModsToDisk }; +- +- cl::opt OrcDumpKind("orc-lazy-debug", +- cl::desc("Debug dumping for the orc-lazy JIT."), +- cl::init(DumpKind::NoDump), +- cl::values( +- clEnumValN(DumpKind::NoDump, "no-dump", +- "Don't dump anything."), +- clEnumValN(DumpKind::DumpFuncsToStdOut, +- "funcs-to-stdout", +- "Dump function names to stdout."), +- clEnumValN(DumpKind::DumpModsToStdErr, +- "mods-to-stderr", +- "Dump modules to stderr."), +- clEnumValN(DumpKind::DumpModsToDisk, +- "mods-to-disk", +- "Dump modules to the current " +- "working directory. (WARNING: " +- "will overwrite existing files)."), +- clEnumValEnd), +- cl::Hidden); +- +- cl::opt OrcInlineStubs("orc-lazy-inline-stubs", +- cl::desc("Try to inline stubs"), +- cl::init(true), cl::Hidden); +-} +- +-OrcLazyJIT::TransformFtor OrcLazyJIT::createDebugDumper() { +- +- switch (OrcDumpKind) { +- case DumpKind::NoDump: +- return [](std::unique_ptr M) { return M; }; +- +- case DumpKind::DumpFuncsToStdOut: +- return [](std::unique_ptr M) { +- printf("[ "); +- +- for (const auto &F : *M) { +- if (F.isDeclaration()) +- continue; +- +- if (F.hasName()) { +- std::string Name(F.getName()); +- printf("%s ", Name.c_str()); +- } else +- printf(" "); +- } +- +- printf("]\n"); +- return M; +- }; +- +- case DumpKind::DumpModsToStdErr: +- return [](std::unique_ptr M) { +- dbgs() << "----- Module Start -----\n" << *M +- << "----- Module End -----\n"; +- +- return M; +- }; +- +- case DumpKind::DumpModsToDisk: +- return [](std::unique_ptr M) { +- std::error_code EC; +- raw_fd_ostream Out(M->getModuleIdentifier() + ".ll", EC, +- sys::fs::F_Text); +- if (EC) { +- errs() << "Couldn't open " << M->getModuleIdentifier() +- << " for dumping.\nError:" << EC.message() << "\n"; +- exit(1); +- } +- Out << *M; +- return M; +- }; +- } +- llvm_unreachable("Unknown DumpKind"); +-} +- +-// Defined in lli.cpp. +-CodeGenOpt::Level getOptLevel(); +- +- +-template +-static PtrTy fromTargetAddress(orc::TargetAddress Addr) { +- return reinterpret_cast(static_cast(Addr)); +-} +- +-int llvm::runOrcLazyJIT(std::unique_ptr M, int ArgC, char* ArgV[]) { +- // Add the program's symbols into the JIT's search space. +- if (sys::DynamicLibrary::LoadLibraryPermanently(nullptr)) { +- errs() << "Error loading program symbols.\n"; +- return 1; +- } +- +- // Grab a target machine and try to build a factory function for the +- // target-specific Orc callback manager. +- EngineBuilder EB; +- EB.setOptLevel(getOptLevel()); +- auto TM = std::unique_ptr(EB.selectTarget()); +- Triple T(TM->getTargetTriple()); +- auto CompileCallbackMgr = orc::createLocalCompileCallbackManager(T, 0); +- +- // If we couldn't build the factory function then there must not be a callback +- // manager for this target. Bail out. +- if (!CompileCallbackMgr) { +- errs() << "No callback manager available for target '" +- << TM->getTargetTriple().str() << "'.\n"; +- return 1; +- } +- +- auto IndirectStubsMgrBuilder = orc::createLocalIndirectStubsManagerBuilder(T); +- +- // If we couldn't build a stubs-manager-builder for this target then bail out. +- if (!IndirectStubsMgrBuilder) { +- errs() << "No indirect stubs manager available for target '" +- << TM->getTargetTriple().str() << "'.\n"; +- return 1; +- } +- +- // Everything looks good. Build the JIT. +- OrcLazyJIT J(std::move(TM), std::move(CompileCallbackMgr), +- std::move(IndirectStubsMgrBuilder), +- OrcInlineStubs); +- +- // Add the module, look up main and run it. +- auto MainHandle = J.addModule(std::move(M)); +- auto MainSym = J.findSymbolIn(MainHandle, "main"); +- +- if (!MainSym) { +- errs() << "Could not find main function.\n"; +- return 1; +- } +- +- typedef int (*MainFnPtr)(int, char*[]); +- auto Main = fromTargetAddress(MainSym.getAddress()); +- return Main(ArgC, ArgV); +-} + +diff --git a/tools/lli/OrcLazyJIT.h b/tools/lli/OrcLazyJIT.h +deleted file mode 100644 +index 733bdd8..0000000 +--- a/tools/lli/OrcLazyJIT.h ++++ /dev/null +@@ -1,163 +0,0 @@ +-//===--- OrcLazyJIT.h - Basic Orc-based JIT for lazy execution --*- C++ -*-===// +-// +-// The LLVM Compiler Infrastructure +-// +-// This file is distributed under the University of Illinois Open Source +-// License. See LICENSE.TXT for details. +-// +-//===----------------------------------------------------------------------===// +-// +-// Simple Orc-based JIT. Uses the compile-on-demand layer to break up and +-// lazily compile modules. +-// +-//===----------------------------------------------------------------------===// +- +-#ifndef LLVM_TOOLS_LLI_ORCLAZYJIT_H +-#define LLVM_TOOLS_LLI_ORCLAZYJIT_H +- +-#include "llvm/ADT/Triple.h" +-#include "llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h" +-#include "llvm/ExecutionEngine/Orc/CompileUtils.h" +-#include "llvm/ExecutionEngine/Orc/ExecutionUtils.h" +-#include "llvm/ExecutionEngine/Orc/IRCompileLayer.h" +-#include "llvm/ExecutionEngine/Orc/IRTransformLayer.h" +-#include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h" +-#include "llvm/ExecutionEngine/RTDyldMemoryManager.h" +- +-namespace llvm { +- +-class OrcLazyJIT { +-public: +- +- typedef orc::JITCompileCallbackManager CompileCallbackMgr; +- typedef orc::ObjectLinkingLayer<> ObjLayerT; +- typedef orc::IRCompileLayer CompileLayerT; +- typedef std::function(std::unique_ptr)> +- TransformFtor; +- typedef orc::IRTransformLayer IRDumpLayerT; +- typedef orc::CompileOnDemandLayer CODLayerT; +- typedef CODLayerT::IndirectStubsManagerBuilderT +- IndirectStubsManagerBuilder; +- typedef CODLayerT::ModuleSetHandleT ModuleHandleT; +- +- OrcLazyJIT(std::unique_ptr TM, +- std::unique_ptr CCMgr, +- IndirectStubsManagerBuilder IndirectStubsMgrBuilder, +- bool InlineStubs) +- : TM(std::move(TM)), DL(this->TM->createDataLayout()), +- CCMgr(std::move(CCMgr)), +- ObjectLayer(), +- CompileLayer(ObjectLayer, orc::SimpleCompiler(*this->TM)), +- IRDumpLayer(CompileLayer, createDebugDumper()), +- CODLayer(IRDumpLayer, extractSingleFunction, *this->CCMgr, +- std::move(IndirectStubsMgrBuilder), InlineStubs), +- CXXRuntimeOverrides( +- [this](const std::string &S) { return mangle(S); }) {} +- +- ~OrcLazyJIT() { +- // Run any destructors registered with __cxa_atexit. +- CXXRuntimeOverrides.runDestructors(); +- // Run any IR destructors. +- for (auto &DtorRunner : IRStaticDestructorRunners) +- DtorRunner.runViaLayer(CODLayer); +- } +- +- ModuleHandleT addModule(std::unique_ptr M) { +- // Attach a data-layout if one isn't already present. +- if (M->getDataLayout().isDefault()) +- M->setDataLayout(DL); +- +- // Record the static constructors and destructors. We have to do this before +- // we hand over ownership of the module to the JIT. +- std::vector CtorNames, DtorNames; +- for (auto Ctor : orc::getConstructors(*M)) +- CtorNames.push_back(mangle(Ctor.Func->getName())); +- for (auto Dtor : orc::getDestructors(*M)) +- DtorNames.push_back(mangle(Dtor.Func->getName())); +- +- // Symbol resolution order: +- // 1) Search the JIT symbols. +- // 2) Check for C++ runtime overrides. +- // 3) Search the host process (LLI)'s symbol table. +- auto Resolver = +- orc::createLambdaResolver( +- [this](const std::string &Name) { +- if (auto Sym = CODLayer.findSymbol(Name, true)) +- return Sym.toRuntimeDyldSymbol(); +- if (auto Sym = CXXRuntimeOverrides.searchOverrides(Name)) +- return Sym; +- +- if (auto Addr = +- RTDyldMemoryManager::getSymbolAddressInProcess(Name)) +- return RuntimeDyld::SymbolInfo(Addr, JITSymbolFlags::Exported); +- +- return RuntimeDyld::SymbolInfo(nullptr); +- }, +- [](const std::string &Name) { +- return RuntimeDyld::SymbolInfo(nullptr); +- } +- ); +- +- // Add the module to the JIT. +- std::vector> S; +- S.push_back(std::move(M)); +- auto H = CODLayer.addModuleSet(std::move(S), +- llvm::make_unique(), +- std::move(Resolver)); +- +- // Run the static constructors, and save the static destructor runner for +- // execution when the JIT is torn down. +- orc::CtorDtorRunner CtorRunner(std::move(CtorNames), H); +- CtorRunner.runViaLayer(CODLayer); +- +- IRStaticDestructorRunners.emplace_back(std::move(DtorNames), H); +- +- return H; +- } +- +- orc::JITSymbol findSymbol(const std::string &Name) { +- return CODLayer.findSymbol(mangle(Name), true); +- } +- +- orc::JITSymbol findSymbolIn(ModuleHandleT H, const std::string &Name) { +- return CODLayer.findSymbolIn(H, mangle(Name), true); +- } +- +-private: +- +- std::string mangle(const std::string &Name) { +- std::string MangledName; +- { +- raw_string_ostream MangledNameStream(MangledName); +- Mangler::getNameWithPrefix(MangledNameStream, Name, DL); +- } +- return MangledName; +- } +- +- static std::set extractSingleFunction(Function &F) { +- std::set Partition; +- Partition.insert(&F); +- return Partition; +- } +- +- static TransformFtor createDebugDumper(); +- +- std::unique_ptr TM; +- DataLayout DL; +- SectionMemoryManager CCMgrMemMgr; +- +- std::unique_ptr CCMgr; +- ObjLayerT ObjectLayer; +- CompileLayerT CompileLayer; +- IRDumpLayerT IRDumpLayer; +- CODLayerT CODLayer; +- +- orc::LocalCXXRuntimeOverrides CXXRuntimeOverrides; +- std::vector> IRStaticDestructorRunners; +-}; +- +-int runOrcLazyJIT(std::unique_ptr M, int ArgC, char* ArgV[]); +- +-} // end namespace llvm +- +-#endif +diff --git a/tools/lli/RemoteJITUtils.h b/tools/lli/RemoteJITUtils.h +deleted file mode 100644 +index 15068d2..0000000 +--- a/tools/lli/RemoteJITUtils.h ++++ /dev/null +@@ -1,152 +0,0 @@ +-//===-- RemoteJITUtils.h - Utilities for remote-JITing with LLI -*- C++ -*-===// +-// +-// The LLVM Compiler Infrastructure +-// +-// This file is distributed under the University of Illinois Open Source +-// License. See LICENSE.TXT for details. +-// +-//===----------------------------------------------------------------------===// +-// +-// Utilities for remote-JITing with LLI. +-// +-//===----------------------------------------------------------------------===// +- +-#ifndef LLVM_TOOLS_LLI_REMOTEJITUTILS_H +-#define LLVM_TOOLS_LLI_REMOTEJITUTILS_H +- +-#include "llvm/ExecutionEngine/Orc/RPCChannel.h" +-#include "llvm/ExecutionEngine/RTDyldMemoryManager.h" +-#include +- +-#if !defined(_MSC_VER) && !defined(__MINGW32__) +-#include +-#else +-#include +-#endif +- +-/// RPC channel that reads from and writes from file descriptors. +-class FDRPCChannel final : public llvm::orc::remote::RPCChannel { +-public: +- FDRPCChannel(int InFD, int OutFD) : InFD(InFD), OutFD(OutFD) {} +- +- llvm::Error readBytes(char *Dst, unsigned Size) override { +- assert(Dst && "Attempt to read into null."); +- ssize_t Completed = 0; +- while (Completed < static_cast(Size)) { +- ssize_t Read = ::read(InFD, Dst + Completed, Size - Completed); +- if (Read <= 0) { +- auto ErrNo = errno; +- if (ErrNo == EAGAIN || ErrNo == EINTR) +- continue; +- else +- return llvm::errorCodeToError( +- std::error_code(errno, std::generic_category())); +- } +- Completed += Read; +- } +- return llvm::Error::success(); +- } +- +- llvm::Error appendBytes(const char *Src, unsigned Size) override { +- assert(Src && "Attempt to append from null."); +- ssize_t Completed = 0; +- while (Completed < static_cast(Size)) { +- ssize_t Written = ::write(OutFD, Src + Completed, Size - Completed); +- if (Written < 0) { +- auto ErrNo = errno; +- if (ErrNo == EAGAIN || ErrNo == EINTR) +- continue; +- else +- return llvm::errorCodeToError( +- std::error_code(errno, std::generic_category())); +- } +- Completed += Written; +- } +- return llvm::Error::success(); +- } +- +- llvm::Error send() override { return llvm::Error::success(); } +- +-private: +- int InFD, OutFD; +-}; +- +-// launch the remote process (see lli.cpp) and return a channel to it. +-std::unique_ptr launchRemote(); +- +-namespace llvm { +- +-// ForwardingMM - Adapter to connect MCJIT to Orc's Remote memory manager. +-class ForwardingMemoryManager : public llvm::RTDyldMemoryManager { +-public: +- void setMemMgr(std::unique_ptr MemMgr) { +- this->MemMgr = std::move(MemMgr); +- } +- +- void setResolver(std::unique_ptr Resolver) { +- this->Resolver = std::move(Resolver); +- } +- +- uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment, +- unsigned SectionID, +- StringRef SectionName) override { +- return MemMgr->allocateCodeSection(Size, Alignment, SectionID, SectionName); +- } +- +- uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment, +- unsigned SectionID, StringRef SectionName, +- bool IsReadOnly) override { +- return MemMgr->allocateDataSection(Size, Alignment, SectionID, SectionName, +- IsReadOnly); +- } +- +- void reserveAllocationSpace(uintptr_t CodeSize, uint32_t CodeAlign, +- uintptr_t RODataSize, uint32_t RODataAlign, +- uintptr_t RWDataSize, +- uint32_t RWDataAlign) override { +- MemMgr->reserveAllocationSpace(CodeSize, CodeAlign, RODataSize, RODataAlign, +- RWDataSize, RWDataAlign); +- } +- +- bool needsToReserveAllocationSpace() override { +- return MemMgr->needsToReserveAllocationSpace(); +- } +- +- void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr, +- size_t Size) override { +- MemMgr->registerEHFrames(Addr, LoadAddr, Size); +- } +- +- void deregisterEHFrames(uint8_t *Addr, uint64_t LoadAddr, +- size_t Size) override { +- MemMgr->deregisterEHFrames(Addr, LoadAddr, Size); +- } +- +- bool finalizeMemory(std::string *ErrMsg = nullptr) override { +- return MemMgr->finalizeMemory(ErrMsg); +- } +- +- void notifyObjectLoaded(RuntimeDyld &RTDyld, +- const object::ObjectFile &Obj) override { +- MemMgr->notifyObjectLoaded(RTDyld, Obj); +- } +- +- // Don't hide the sibling notifyObjectLoaded from RTDyldMemoryManager. +- using RTDyldMemoryManager::notifyObjectLoaded; +- +- RuntimeDyld::SymbolInfo findSymbol(const std::string &Name) override { +- return Resolver->findSymbol(Name); +- } +- +- RuntimeDyld::SymbolInfo +- findSymbolInLogicalDylib(const std::string &Name) override { +- return Resolver->findSymbolInLogicalDylib(Name); +- } +- +-private: +- std::unique_ptr MemMgr; +- std::unique_ptr Resolver; +-}; +-} +- +-#endif +diff --git a/tools/lli/lli.cpp b/tools/lli/lli.cpp +index 92de5da..7203af2 100644 +--- a/tools/lli/lli.cpp ++++ b/tools/lli/lli.cpp +@@ -13,6 +13,8 @@ + // + //===----------------------------------------------------------------------===// + ++#if 0 ++ + #include "OrcLazyJIT.h" + #include "RemoteJITUtils.h" + #include "llvm/IR/LLVMContext.h" +@@ -751,3 +753,8 @@ std::unique_ptr launchRemote() { + return llvm::make_unique(PipeFD[1][0], PipeFD[0][1]); + #endif + } ++#endif ++ ++int main(int argc, char **argv, char * const *envp) { ++ return 0; ++} +diff --git a/tools/llvm-cov/CodeCoverage.cpp b/tools/llvm-cov/CodeCoverage.cpp +index 0a4d1a6..8b13789 100644 +--- a/tools/llvm-cov/CodeCoverage.cpp ++++ b/tools/llvm-cov/CodeCoverage.cpp +@@ -1,727 +1 @@ +-//===- CodeCoverage.cpp - Coverage tool based on profiling instrumentation-===// +-// +-// The LLVM Compiler Infrastructure +-// +-// This file is distributed under the University of Illinois Open Source +-// License. See LICENSE.TXT for details. +-// +-//===----------------------------------------------------------------------===// +-// +-// The 'CodeCoverageTool' class implements a command line tool to analyze and +-// report coverage information using the profiling instrumentation and code +-// coverage mapping. +-// +-//===----------------------------------------------------------------------===// + +-#include "CoverageFilters.h" +-#include "CoverageReport.h" +-#include "CoverageViewOptions.h" +-#include "RenderingSupport.h" +-#include "SourceCoverageView.h" +-#include "llvm/ADT/SmallString.h" +-#include "llvm/ADT/StringRef.h" +-#include "llvm/ADT/Triple.h" +-#include "llvm/ProfileData/Coverage/CoverageMapping.h" +-#include "llvm/ProfileData/InstrProfReader.h" +-#include "llvm/Support/CommandLine.h" +-#include "llvm/Support/FileSystem.h" +-#include "llvm/Support/Format.h" +-#include "llvm/Support/MemoryBuffer.h" +-#include "llvm/Support/Path.h" +-#include "llvm/Support/Process.h" +-#include "llvm/Support/Program.h" +-#include "llvm/Support/ThreadPool.h" +-#include "llvm/Support/ToolOutputFile.h" +-#include +-#include +- +-using namespace llvm; +-using namespace coverage; +- +-namespace { +-/// \brief The implementation of the coverage tool. +-class CodeCoverageTool { +-public: +- enum Command { +- /// \brief The show command. +- Show, +- /// \brief The report command. +- Report +- }; +- +- /// \brief Print the error message to the error output stream. +- void error(const Twine &Message, StringRef Whence = ""); +- +- /// \brief Record (but do not print) an error message in a thread-safe way. +- void deferError(const Twine &Message, StringRef Whence = ""); +- +- /// \brief Record (but do not print) a warning message in a thread-safe way. +- void deferWarning(const Twine &Message, StringRef Whence = ""); +- +- /// \brief Print (and then clear) all deferred error and warning messages. +- void consumeDeferredMessages(); +- +- /// \brief Append a reference to a private copy of \p Path into SourceFiles. +- void addCollectedPath(const std::string &Path); +- +- /// \brief Return a memory buffer for the given source file. +- ErrorOr getSourceFile(StringRef SourceFile); +- +- /// \brief Create source views for the expansions of the view. +- void attachExpansionSubViews(SourceCoverageView &View, +- ArrayRef Expansions, +- const CoverageMapping &Coverage); +- +- /// \brief Create the source view of a particular function. +- std::unique_ptr +- createFunctionView(const FunctionRecord &Function, +- const CoverageMapping &Coverage); +- +- /// \brief Create the main source view of a particular source file. +- std::unique_ptr +- createSourceFileView(StringRef SourceFile, const CoverageMapping &Coverage); +- +- /// \brief Load the coverage mapping data. Return nullptr if an error occured. +- std::unique_ptr load(); +- +- /// \brief If a demangler is available, demangle all symbol names. +- void demangleSymbols(const CoverageMapping &Coverage); +- +- /// \brief Demangle \p Sym if possible. Otherwise, just return \p Sym. +- StringRef getSymbolForHumans(StringRef Sym) const; +- +- int run(Command Cmd, int argc, const char **argv); +- +- typedef llvm::function_ref CommandLineParserType; +- +- int show(int argc, const char **argv, +- CommandLineParserType commandLineParser); +- +- int report(int argc, const char **argv, +- CommandLineParserType commandLineParser); +- +- std::string ObjectFilename; +- CoverageViewOptions ViewOpts; +- std::string PGOFilename; +- CoverageFiltersMatchAll Filters; +- std::vector SourceFiles; +- bool CompareFilenamesOnly; +- StringMap RemappedFilenames; +- std::string CoverageArch; +- +-private: +- /// A cache for demangled symbol names. +- StringMap DemangledNames; +- +- /// File paths (absolute, or otherwise) to input source files. +- std::vector CollectedPaths; +- +- /// Errors and warnings which have not been printed. +- std::mutex DeferredMessagesLock; +- std::vector DeferredMessages; +- +- /// A container for input source file buffers. +- std::mutex LoadedSourceFilesLock; +- std::vector>> +- LoadedSourceFiles; +-}; +-} +- +-static std::string getErrorString(const Twine &Message, StringRef Whence, +- bool Warning) { +- std::string Str = (Warning ? "warning" : "error"); +- Str += ": "; +- if (!Whence.empty()) +- Str += Whence.str() + ": "; +- Str += Message.str() + "\n"; +- return Str; +-} +- +-void CodeCoverageTool::error(const Twine &Message, StringRef Whence) { +- errs() << getErrorString(Message, Whence, false); +-} +- +-void CodeCoverageTool::deferError(const Twine &Message, StringRef Whence) { +- std::unique_lock Guard{DeferredMessagesLock}; +- DeferredMessages.emplace_back(getErrorString(Message, Whence, false)); +-} +- +-void CodeCoverageTool::deferWarning(const Twine &Message, StringRef Whence) { +- std::unique_lock Guard{DeferredMessagesLock}; +- DeferredMessages.emplace_back(getErrorString(Message, Whence, true)); +-} +- +-void CodeCoverageTool::consumeDeferredMessages() { +- std::unique_lock Guard{DeferredMessagesLock}; +- for (const std::string &Message : DeferredMessages) +- ViewOpts.colored_ostream(errs(), raw_ostream::RED) << Message; +- DeferredMessages.clear(); +-} +- +-void CodeCoverageTool::addCollectedPath(const std::string &Path) { +- CollectedPaths.push_back(Path); +- SourceFiles.emplace_back(CollectedPaths.back()); +-} +- +-ErrorOr +-CodeCoverageTool::getSourceFile(StringRef SourceFile) { +- // If we've remapped filenames, look up the real location for this file. +- std::unique_lock Guard{LoadedSourceFilesLock}; +- if (!RemappedFilenames.empty()) { +- auto Loc = RemappedFilenames.find(SourceFile); +- if (Loc != RemappedFilenames.end()) +- SourceFile = Loc->second; +- } +- for (const auto &Files : LoadedSourceFiles) +- if (sys::fs::equivalent(SourceFile, Files.first)) +- return *Files.second; +- auto Buffer = MemoryBuffer::getFile(SourceFile); +- if (auto EC = Buffer.getError()) { +- deferError(EC.message(), SourceFile); +- return EC; +- } +- LoadedSourceFiles.emplace_back(SourceFile, std::move(Buffer.get())); +- return *LoadedSourceFiles.back().second; +-} +- +-void CodeCoverageTool::attachExpansionSubViews( +- SourceCoverageView &View, ArrayRef Expansions, +- const CoverageMapping &Coverage) { +- if (!ViewOpts.ShowExpandedRegions) +- return; +- for (const auto &Expansion : Expansions) { +- auto ExpansionCoverage = Coverage.getCoverageForExpansion(Expansion); +- if (ExpansionCoverage.empty()) +- continue; +- auto SourceBuffer = getSourceFile(ExpansionCoverage.getFilename()); +- if (!SourceBuffer) +- continue; +- +- auto SubViewExpansions = ExpansionCoverage.getExpansions(); +- auto SubView = +- SourceCoverageView::create(Expansion.Function.Name, SourceBuffer.get(), +- ViewOpts, std::move(ExpansionCoverage)); +- attachExpansionSubViews(*SubView, SubViewExpansions, Coverage); +- View.addExpansion(Expansion.Region, std::move(SubView)); +- } +-} +- +-std::unique_ptr +-CodeCoverageTool::createFunctionView(const FunctionRecord &Function, +- const CoverageMapping &Coverage) { +- auto FunctionCoverage = Coverage.getCoverageForFunction(Function); +- if (FunctionCoverage.empty()) +- return nullptr; +- auto SourceBuffer = getSourceFile(FunctionCoverage.getFilename()); +- if (!SourceBuffer) +- return nullptr; +- +- auto Expansions = FunctionCoverage.getExpansions(); +- auto View = SourceCoverageView::create(getSymbolForHumans(Function.Name), +- SourceBuffer.get(), ViewOpts, +- std::move(FunctionCoverage)); +- attachExpansionSubViews(*View, Expansions, Coverage); +- +- return View; +-} +- +-std::unique_ptr +-CodeCoverageTool::createSourceFileView(StringRef SourceFile, +- const CoverageMapping &Coverage) { +- auto SourceBuffer = getSourceFile(SourceFile); +- if (!SourceBuffer) +- return nullptr; +- auto FileCoverage = Coverage.getCoverageForFile(SourceFile); +- if (FileCoverage.empty()) +- return nullptr; +- +- auto Expansions = FileCoverage.getExpansions(); +- auto View = SourceCoverageView::create(SourceFile, SourceBuffer.get(), +- ViewOpts, std::move(FileCoverage)); +- attachExpansionSubViews(*View, Expansions, Coverage); +- +- for (const auto *Function : Coverage.getInstantiations(SourceFile)) { +- auto SubViewCoverage = Coverage.getCoverageForFunction(*Function); +- auto SubViewExpansions = SubViewCoverage.getExpansions(); +- auto SubView = SourceCoverageView::create( +- getSymbolForHumans(Function->Name), SourceBuffer.get(), ViewOpts, +- std::move(SubViewCoverage)); +- attachExpansionSubViews(*SubView, SubViewExpansions, Coverage); +- +- if (SubView) { +- unsigned FileID = Function->CountedRegions.front().FileID; +- unsigned Line = 0; +- for (const auto &CR : Function->CountedRegions) +- if (CR.FileID == FileID) +- Line = std::max(CR.LineEnd, Line); +- View->addInstantiation(Function->Name, Line, std::move(SubView)); +- } +- } +- return View; +-} +- +-static bool modifiedTimeGT(StringRef LHS, StringRef RHS) { +- sys::fs::file_status Status; +- if (sys::fs::status(LHS, Status)) +- return false; +- auto LHSTime = Status.getLastModificationTime(); +- if (sys::fs::status(RHS, Status)) +- return false; +- auto RHSTime = Status.getLastModificationTime(); +- return LHSTime > RHSTime; +-} +- +-std::unique_ptr CodeCoverageTool::load() { +- if (modifiedTimeGT(ObjectFilename, PGOFilename)) +- errs() << "warning: profile data may be out of date - object is newer\n"; +- auto CoverageOrErr = CoverageMapping::load(ObjectFilename, PGOFilename, +- CoverageArch); +- if (Error E = CoverageOrErr.takeError()) { +- colored_ostream(errs(), raw_ostream::RED) +- << "error: Failed to load coverage: " << toString(std::move(E)) << "\n"; +- return nullptr; +- } +- auto Coverage = std::move(CoverageOrErr.get()); +- unsigned Mismatched = Coverage->getMismatchedCount(); +- if (Mismatched) { +- colored_ostream(errs(), raw_ostream::RED) +- << "warning: " << Mismatched << " functions have mismatched data. "; +- errs() << "\n"; +- } +- +- if (CompareFilenamesOnly) { +- auto CoveredFiles = Coverage.get()->getUniqueSourceFiles(); +- for (auto &SF : SourceFiles) { +- StringRef SFBase = sys::path::filename(SF); +- for (const auto &CF : CoveredFiles) +- if (SFBase == sys::path::filename(CF)) { +- RemappedFilenames[CF] = SF; +- SF = CF; +- break; +- } +- } +- } +- +- demangleSymbols(*Coverage); +- +- return Coverage; +-} +- +-void CodeCoverageTool::demangleSymbols(const CoverageMapping &Coverage) { +- if (!ViewOpts.hasDemangler()) +- return; +- +- // Pass function names to the demangler in a temporary file. +- int InputFD; +- SmallString<256> InputPath; +- std::error_code EC = +- sys::fs::createTemporaryFile("demangle-in", "list", InputFD, InputPath); +- if (EC) { +- error(InputPath, EC.message()); +- return; +- } +- tool_output_file InputTOF{InputPath, InputFD}; +- +- unsigned NumSymbols = 0; +- for (const auto &Function : Coverage.getCoveredFunctions()) { +- InputTOF.os() << Function.Name << '\n'; +- ++NumSymbols; +- } +- InputTOF.os().close(); +- +- // Use another temporary file to store the demangler's output. +- int OutputFD; +- SmallString<256> OutputPath; +- EC = sys::fs::createTemporaryFile("demangle-out", "list", OutputFD, +- OutputPath); +- if (EC) { +- error(OutputPath, EC.message()); +- return; +- } +- tool_output_file OutputTOF{OutputPath, OutputFD}; +- OutputTOF.os().close(); +- +- // Invoke the demangler. +- std::vector ArgsV; +- for (const std::string &Arg : ViewOpts.DemanglerOpts) +- ArgsV.push_back(Arg.c_str()); +- ArgsV.push_back(nullptr); +- StringRef InputPathRef = InputPath.str(); +- StringRef OutputPathRef = OutputPath.str(); +- StringRef StderrRef; +- const StringRef *Redirects[] = {&InputPathRef, &OutputPathRef, &StderrRef}; +- std::string ErrMsg; +- int RC = sys::ExecuteAndWait(ViewOpts.DemanglerOpts[0], ArgsV.data(), +- /*env=*/nullptr, Redirects, /*secondsToWait=*/0, +- /*memoryLimit=*/0, &ErrMsg); +- if (RC) { +- error(ErrMsg, ViewOpts.DemanglerOpts[0]); +- return; +- } +- +- // Parse the demangler's output. +- auto BufOrError = MemoryBuffer::getFile(OutputPath); +- if (!BufOrError) { +- error(OutputPath, BufOrError.getError().message()); +- return; +- } +- +- std::unique_ptr DemanglerBuf = std::move(*BufOrError); +- +- SmallVector Symbols; +- StringRef DemanglerData = DemanglerBuf->getBuffer(); +- DemanglerData.split(Symbols, '\n', /*MaxSplit=*/NumSymbols, +- /*KeepEmpty=*/false); +- if (Symbols.size() != NumSymbols) { +- error("Demangler did not provide expected number of symbols"); +- return; +- } +- +- // Cache the demangled names. +- unsigned I = 0; +- for (const auto &Function : Coverage.getCoveredFunctions()) +- DemangledNames[Function.Name] = Symbols[I++]; +-} +- +-StringRef CodeCoverageTool::getSymbolForHumans(StringRef Sym) const { +- const auto DemangledName = DemangledNames.find(Sym); +- if (DemangledName == DemangledNames.end()) +- return Sym; +- return DemangledName->getValue(); +-} +- +-int CodeCoverageTool::run(Command Cmd, int argc, const char **argv) { +- cl::opt ObjectFilename( +- cl::Positional, cl::Required, cl::location(this->ObjectFilename), +- cl::desc("Covered executable or object file.")); +- +- cl::list InputSourceFiles( +- cl::Positional, cl::desc(""), cl::ZeroOrMore); +- +- cl::opt PGOFilename( +- "instr-profile", cl::Required, cl::location(this->PGOFilename), +- cl::desc( +- "File with the profile data obtained after an instrumented run")); +- +- cl::opt Arch( +- "arch", cl::desc("architecture of the coverage mapping binary")); +- +- cl::opt DebugDump("dump", cl::Optional, +- cl::desc("Show internal debug dump")); +- +- cl::opt Format( +- "format", cl::desc("Output format for line-based coverage reports"), +- cl::values(clEnumValN(CoverageViewOptions::OutputFormat::Text, "text", +- "Text output"), +- clEnumValN(CoverageViewOptions::OutputFormat::HTML, "html", +- "HTML output"), +- clEnumValEnd), +- cl::init(CoverageViewOptions::OutputFormat::Text)); +- +- cl::opt FilenameEquivalence( +- "filename-equivalence", cl::Optional, +- cl::desc("Treat source files as equivalent to paths in the coverage data " +- "when the file names match, even if the full paths do not")); +- +- cl::OptionCategory FilteringCategory("Function filtering options"); +- +- cl::list NameFilters( +- "name", cl::Optional, +- cl::desc("Show code coverage only for functions with the given name"), +- cl::ZeroOrMore, cl::cat(FilteringCategory)); +- +- cl::list NameRegexFilters( +- "name-regex", cl::Optional, +- cl::desc("Show code coverage only for functions that match the given " +- "regular expression"), +- cl::ZeroOrMore, cl::cat(FilteringCategory)); +- +- cl::opt RegionCoverageLtFilter( +- "region-coverage-lt", cl::Optional, +- cl::desc("Show code coverage only for functions with region coverage " +- "less than the given threshold"), +- cl::cat(FilteringCategory)); +- +- cl::opt RegionCoverageGtFilter( +- "region-coverage-gt", cl::Optional, +- cl::desc("Show code coverage only for functions with region coverage " +- "greater than the given threshold"), +- cl::cat(FilteringCategory)); +- +- cl::opt LineCoverageLtFilter( +- "line-coverage-lt", cl::Optional, +- cl::desc("Show code coverage only for functions with line coverage less " +- "than the given threshold"), +- cl::cat(FilteringCategory)); +- +- cl::opt LineCoverageGtFilter( +- "line-coverage-gt", cl::Optional, +- cl::desc("Show code coverage only for functions with line coverage " +- "greater than the given threshold"), +- cl::cat(FilteringCategory)); +- +- cl::opt UseColor( +- "use-color", cl::desc("Emit colored output (default=autodetect)"), +- cl::init(cl::BOU_UNSET)); +- +- cl::list DemanglerOpts( +- "Xdemangler", cl::desc("|")); +- +- auto commandLineParser = [&, this](int argc, const char **argv) -> int { +- cl::ParseCommandLineOptions(argc, argv, "LLVM code coverage tool\n"); +- ViewOpts.Debug = DebugDump; +- CompareFilenamesOnly = FilenameEquivalence; +- +- ViewOpts.Format = Format; +- switch (ViewOpts.Format) { +- case CoverageViewOptions::OutputFormat::Text: +- ViewOpts.Colors = UseColor == cl::BOU_UNSET +- ? sys::Process::StandardOutHasColors() +- : UseColor == cl::BOU_TRUE; +- break; +- case CoverageViewOptions::OutputFormat::HTML: +- if (UseColor == cl::BOU_FALSE) +- error("Color output cannot be disabled when generating html."); +- ViewOpts.Colors = true; +- break; +- } +- +- // If a demangler is supplied, check if it exists and register it. +- if (DemanglerOpts.size()) { +- auto DemanglerPathOrErr = sys::findProgramByName(DemanglerOpts[0]); +- if (!DemanglerPathOrErr) { +- error("Could not find the demangler!", +- DemanglerPathOrErr.getError().message()); +- return 1; +- } +- DemanglerOpts[0] = *DemanglerPathOrErr; +- ViewOpts.DemanglerOpts.swap(DemanglerOpts); +- } +- +- // Create the function filters +- if (!NameFilters.empty() || !NameRegexFilters.empty()) { +- auto NameFilterer = new CoverageFilters; +- for (const auto &Name : NameFilters) +- NameFilterer->push_back(llvm::make_unique(Name)); +- for (const auto &Regex : NameRegexFilters) +- NameFilterer->push_back( +- llvm::make_unique(Regex)); +- Filters.push_back(std::unique_ptr(NameFilterer)); +- } +- if (RegionCoverageLtFilter.getNumOccurrences() || +- RegionCoverageGtFilter.getNumOccurrences() || +- LineCoverageLtFilter.getNumOccurrences() || +- LineCoverageGtFilter.getNumOccurrences()) { +- auto StatFilterer = new CoverageFilters; +- if (RegionCoverageLtFilter.getNumOccurrences()) +- StatFilterer->push_back(llvm::make_unique( +- RegionCoverageFilter::LessThan, RegionCoverageLtFilter)); +- if (RegionCoverageGtFilter.getNumOccurrences()) +- StatFilterer->push_back(llvm::make_unique( +- RegionCoverageFilter::GreaterThan, RegionCoverageGtFilter)); +- if (LineCoverageLtFilter.getNumOccurrences()) +- StatFilterer->push_back(llvm::make_unique( +- LineCoverageFilter::LessThan, LineCoverageLtFilter)); +- if (LineCoverageGtFilter.getNumOccurrences()) +- StatFilterer->push_back(llvm::make_unique( +- RegionCoverageFilter::GreaterThan, LineCoverageGtFilter)); +- Filters.push_back(std::unique_ptr(StatFilterer)); +- } +- +- if (!Arch.empty() && +- Triple(Arch).getArch() == llvm::Triple::ArchType::UnknownArch) { +- errs() << "error: Unknown architecture: " << Arch << "\n"; +- return 1; +- } +- CoverageArch = Arch; +- +- for (const auto &File : InputSourceFiles) { +- SmallString<128> Path(File); +- if (!CompareFilenamesOnly) +- if (std::error_code EC = sys::fs::make_absolute(Path)) { +- errs() << "error: " << File << ": " << EC.message(); +- return 1; +- } +- addCollectedPath(Path.str()); +- } +- return 0; +- }; +- +- switch (Cmd) { +- case Show: +- return show(argc, argv, commandLineParser); +- case Report: +- return report(argc, argv, commandLineParser); +- } +- return 0; +-} +- +-int CodeCoverageTool::show(int argc, const char **argv, +- CommandLineParserType commandLineParser) { +- +- cl::OptionCategory ViewCategory("Viewing options"); +- +- cl::opt ShowLineExecutionCounts( +- "show-line-counts", cl::Optional, +- cl::desc("Show the execution counts for each line"), cl::init(true), +- cl::cat(ViewCategory)); +- +- cl::opt ShowRegions( +- "show-regions", cl::Optional, +- cl::desc("Show the execution counts for each region"), +- cl::cat(ViewCategory)); +- +- cl::opt ShowBestLineRegionsCounts( +- "show-line-counts-or-regions", cl::Optional, +- cl::desc("Show the execution counts for each line, or the execution " +- "counts for each region on lines that have multiple regions"), +- cl::cat(ViewCategory)); +- +- cl::opt ShowExpansions("show-expansions", cl::Optional, +- cl::desc("Show expanded source regions"), +- cl::cat(ViewCategory)); +- +- cl::opt ShowInstantiations("show-instantiations", cl::Optional, +- cl::desc("Show function instantiations"), +- cl::cat(ViewCategory)); +- +- cl::opt ShowOutputDirectory( +- "output-dir", cl::init(""), +- cl::desc("Directory in which coverage information is written out")); +- cl::alias ShowOutputDirectoryA("o", cl::desc("Alias for --output-dir"), +- cl::aliasopt(ShowOutputDirectory)); +- +- auto Err = commandLineParser(argc, argv); +- if (Err) +- return Err; +- +- ViewOpts.ShowLineNumbers = true; +- ViewOpts.ShowLineStats = ShowLineExecutionCounts.getNumOccurrences() != 0 || +- !ShowRegions || ShowBestLineRegionsCounts; +- ViewOpts.ShowRegionMarkers = ShowRegions || ShowBestLineRegionsCounts; +- ViewOpts.ShowLineStatsOrRegionMarkers = ShowBestLineRegionsCounts; +- ViewOpts.ShowExpandedRegions = ShowExpansions; +- ViewOpts.ShowFunctionInstantiations = ShowInstantiations; +- ViewOpts.ShowOutputDirectory = ShowOutputDirectory; +- +- if (ViewOpts.hasOutputDirectory()) { +- if (auto E = sys::fs::create_directories(ViewOpts.ShowOutputDirectory)) { +- error("Could not create output directory!", E.message()); +- return 1; +- } +- } +- +- auto Coverage = load(); +- if (!Coverage) +- return 1; +- +- auto Printer = CoveragePrinter::create(ViewOpts); +- +- if (!Filters.empty()) { +- auto OSOrErr = Printer->createViewFile("functions", /*InToplevel=*/true); +- if (Error E = OSOrErr.takeError()) { +- error("Could not create view file!", toString(std::move(E))); +- return 1; +- } +- auto OS = std::move(OSOrErr.get()); +- +- // Show functions. +- for (const auto &Function : Coverage->getCoveredFunctions()) { +- if (!Filters.matches(Function)) +- continue; +- +- auto mainView = createFunctionView(Function, *Coverage); +- if (!mainView) { +- ViewOpts.colored_ostream(errs(), raw_ostream::RED) +- << "warning: Could not read coverage for '" << Function.Name << "'." +- << "\n"; +- continue; +- } +- +- mainView->print(*OS.get(), /*WholeFile=*/false, /*ShowSourceName=*/true); +- } +- +- Printer->closeViewFile(std::move(OS)); +- return 0; +- } +- +- // Show files +- bool ShowFilenames = SourceFiles.size() != 1; +- +- if (SourceFiles.empty()) +- // Get the source files from the function coverage mapping. +- for (StringRef Filename : Coverage->getUniqueSourceFiles()) +- SourceFiles.push_back(Filename); +- +- // Create an index out of the source files. +- if (ViewOpts.hasOutputDirectory()) { +- if (Error E = Printer->createIndexFile(SourceFiles)) { +- error("Could not create index file!", toString(std::move(E))); +- return 1; +- } +- } +- +- // In -output-dir mode, it's safe to use multiple threads to print files. +- unsigned ThreadCount = 1; +- if (ViewOpts.hasOutputDirectory()) +- ThreadCount = std::thread::hardware_concurrency(); +- ThreadPool Pool(ThreadCount); +- +- for (StringRef SourceFile : SourceFiles) { +- Pool.async([this, SourceFile, &Coverage, &Printer, ShowFilenames] { +- auto View = createSourceFileView(SourceFile, *Coverage); +- if (!View) { +- deferWarning("The file '" + SourceFile.str() + "' isn't covered."); +- return; +- } +- +- auto OSOrErr = Printer->createViewFile(SourceFile, /*InToplevel=*/false); +- if (Error E = OSOrErr.takeError()) { +- deferError("Could not create view file!", toString(std::move(E))); +- return; +- } +- auto OS = std::move(OSOrErr.get()); +- +- View->print(*OS.get(), /*Wholefile=*/true, +- /*ShowSourceName=*/ShowFilenames); +- Printer->closeViewFile(std::move(OS)); +- }); +- } +- +- Pool.wait(); +- +- consumeDeferredMessages(); +- +- return 0; +-} +- +-int CodeCoverageTool::report(int argc, const char **argv, +- CommandLineParserType commandLineParser) { +- auto Err = commandLineParser(argc, argv); +- if (Err) +- return Err; +- +- if (ViewOpts.Format == CoverageViewOptions::OutputFormat::HTML) +- error("HTML output for summary reports is not yet supported."); +- +- auto Coverage = load(); +- if (!Coverage) +- return 1; +- +- CoverageReport Report(ViewOpts, std::move(Coverage)); +- if (SourceFiles.empty()) +- Report.renderFileReports(llvm::outs()); +- else +- Report.renderFunctionReports(SourceFiles, llvm::outs()); +- return 0; +-} +- +-int showMain(int argc, const char *argv[]) { +- CodeCoverageTool Tool; +- return Tool.run(CodeCoverageTool::Show, argc, argv); +-} +- +-int reportMain(int argc, const char *argv[]) { +- CodeCoverageTool Tool; +- return Tool.run(CodeCoverageTool::Report, argc, argv); +-} +diff --git a/tools/llvm-cov/CoverageFilters.cpp b/tools/llvm-cov/CoverageFilters.cpp +index 325dd72..8b13789 100644 +--- a/tools/llvm-cov/CoverageFilters.cpp ++++ b/tools/llvm-cov/CoverageFilters.cpp +@@ -1,59 +1 @@ +-//===- CoverageFilters.cpp - Function coverage mapping filters ------------===// +-// +-// The LLVM Compiler Infrastructure +-// +-// This file is distributed under the University of Illinois Open Source +-// License. See LICENSE.TXT for details. +-// +-//===----------------------------------------------------------------------===// +-// +-// These classes provide filtering for function coverage mapping records. +-// +-//===----------------------------------------------------------------------===// + +-#include "CoverageFilters.h" +-#include "CoverageSummaryInfo.h" +-#include "llvm/Support/Regex.h" +- +-using namespace llvm; +- +-bool NameCoverageFilter::matches(const coverage::FunctionRecord &Function) { +- StringRef FuncName = Function.Name; +- return FuncName.find(Name) != StringRef::npos; +-} +- +-bool +-NameRegexCoverageFilter::matches(const coverage::FunctionRecord &Function) { +- return llvm::Regex(Regex).match(Function.Name); +-} +- +-bool RegionCoverageFilter::matches(const coverage::FunctionRecord &Function) { +- return PassesThreshold(FunctionCoverageSummary::get(Function) +- .RegionCoverage.getPercentCovered()); +-} +- +-bool LineCoverageFilter::matches(const coverage::FunctionRecord &Function) { +- return PassesThreshold( +- FunctionCoverageSummary::get(Function).LineCoverage.getPercentCovered()); +-} +- +-void CoverageFilters::push_back(std::unique_ptr Filter) { +- Filters.push_back(std::move(Filter)); +-} +- +-bool CoverageFilters::matches(const coverage::FunctionRecord &Function) { +- for (const auto &Filter : Filters) { +- if (Filter->matches(Function)) +- return true; +- } +- return false; +-} +- +-bool +-CoverageFiltersMatchAll::matches(const coverage::FunctionRecord &Function) { +- for (const auto &Filter : Filters) { +- if (!Filter->matches(Function)) +- return false; +- } +- return true; +-} +diff --git a/tools/llvm-cov/CoverageFilters.h b/tools/llvm-cov/CoverageFilters.h +deleted file mode 100644 +index 756c4b4..0000000 +--- a/tools/llvm-cov/CoverageFilters.h ++++ /dev/null +@@ -1,127 +0,0 @@ +-//===- CoverageFilters.h - Function coverage mapping filters --------------===// +-// +-// The LLVM Compiler Infrastructure +-// +-// This file is distributed under the University of Illinois Open Source +-// License. See LICENSE.TXT for details. +-// +-//===----------------------------------------------------------------------===// +-// +-// These classes provide filtering for function coverage mapping records. +-// +-//===----------------------------------------------------------------------===// +- +-#ifndef LLVM_COV_COVERAGEFILTERS_H +-#define LLVM_COV_COVERAGEFILTERS_H +- +-#include "llvm/ProfileData/Coverage/CoverageMapping.h" +-#include +-#include +- +-namespace llvm { +- +-/// \brief Matches specific functions that pass the requirement of this filter. +-class CoverageFilter { +-public: +- virtual ~CoverageFilter() {} +- +- /// \brief Return true if the function passes the requirements of this filter. +- virtual bool matches(const coverage::FunctionRecord &Function) { +- return true; +- } +-}; +- +-/// \brief Matches functions that contain a specific string in their name. +-class NameCoverageFilter : public CoverageFilter { +- StringRef Name; +- +-public: +- NameCoverageFilter(StringRef Name) : Name(Name) {} +- +- bool matches(const coverage::FunctionRecord &Function) override; +-}; +- +-/// \brief Matches functions whose name matches a certain regular expression. +-class NameRegexCoverageFilter : public CoverageFilter { +- StringRef Regex; +- +-public: +- NameRegexCoverageFilter(StringRef Regex) : Regex(Regex) {} +- +- bool matches(const coverage::FunctionRecord &Function) override; +-}; +- +-/// \brief Matches numbers that pass a certain threshold. +-template class StatisticThresholdFilter { +-public: +- enum Operation { LessThan, GreaterThan }; +- +-protected: +- Operation Op; +- T Threshold; +- +- StatisticThresholdFilter(Operation Op, T Threshold) +- : Op(Op), Threshold(Threshold) {} +- +- /// \brief Return true if the given number is less than +- /// or greater than the certain threshold. +- bool PassesThreshold(T Value) const { +- switch (Op) { +- case LessThan: +- return Value < Threshold; +- case GreaterThan: +- return Value > Threshold; +- } +- return false; +- } +-}; +- +-/// \brief Matches functions whose region coverage percentage +-/// is above/below a certain percentage. +-class RegionCoverageFilter : public CoverageFilter, +- public StatisticThresholdFilter { +-public: +- RegionCoverageFilter(Operation Op, double Threshold) +- : StatisticThresholdFilter(Op, Threshold) {} +- +- bool matches(const coverage::FunctionRecord &Function) override; +-}; +- +-/// \brief Matches functions whose line coverage percentage +-/// is above/below a certain percentage. +-class LineCoverageFilter : public CoverageFilter, +- public StatisticThresholdFilter { +-public: +- LineCoverageFilter(Operation Op, double Threshold) +- : StatisticThresholdFilter(Op, Threshold) {} +- +- bool matches(const coverage::FunctionRecord &Function) override; +-}; +- +-/// \brief A collection of filters. +-/// Matches functions that match any filters contained +-/// in an instance of this class. +-class CoverageFilters : public CoverageFilter { +-protected: +- std::vector> Filters; +- +-public: +- /// \brief Append a filter to this collection. +- void push_back(std::unique_ptr Filter); +- +- bool empty() const { return Filters.empty(); } +- +- bool matches(const coverage::FunctionRecord &Function) override; +-}; +- +-/// \brief A collection of filters. +-/// Matches functions that match all of the filters contained +-/// in an instance of this class. +-class CoverageFiltersMatchAll : public CoverageFilters { +-public: +- bool matches(const coverage::FunctionRecord &Function) override; +-}; +- +-} // namespace llvm +- +-#endif // LLVM_COV_COVERAGEFILTERS_H +diff --git a/tools/llvm-cov/CoverageReport.cpp b/tools/llvm-cov/CoverageReport.cpp +index 10e53b3..8b13789 100644 +--- a/tools/llvm-cov/CoverageReport.cpp ++++ b/tools/llvm-cov/CoverageReport.cpp +@@ -1,235 +1 @@ +-//===- CoverageReport.cpp - Code coverage report -------------------------===// +-// +-// The LLVM Compiler Infrastructure +-// +-// This file is distributed under the University of Illinois Open Source +-// License. See LICENSE.TXT for details. +-// +-//===----------------------------------------------------------------------===// +-// +-// This class implements rendering of a code coverage report. +-// +-//===----------------------------------------------------------------------===// + +-#include "CoverageReport.h" +-#include "RenderingSupport.h" +-#include "llvm/Support/FileSystem.h" +-#include "llvm/Support/Format.h" +- +-using namespace llvm; +-namespace { +-/// \brief Helper struct which prints trimmed and aligned columns. +-struct Column { +- enum TrimKind { NoTrim, WidthTrim, LeftTrim, RightTrim }; +- +- enum AlignmentKind { LeftAlignment, RightAlignment }; +- +- StringRef Str; +- unsigned Width; +- TrimKind Trim; +- AlignmentKind Alignment; +- +- Column(StringRef Str, unsigned Width) +- : Str(Str), Width(Width), Trim(WidthTrim), Alignment(LeftAlignment) {} +- +- Column &set(TrimKind Value) { +- Trim = Value; +- return *this; +- } +- +- Column &set(AlignmentKind Value) { +- Alignment = Value; +- return *this; +- } +- +- void render(raw_ostream &OS) const; +-}; +- +-raw_ostream &operator<<(raw_ostream &OS, const Column &Value) { +- Value.render(OS); +- return OS; +-} +-} +- +-void Column::render(raw_ostream &OS) const { +- if (Str.size() <= Width) { +- if (Alignment == RightAlignment) { +- OS.indent(Width - Str.size()); +- OS << Str; +- return; +- } +- OS << Str; +- OS.indent(Width - Str.size()); +- return; +- } +- +- switch (Trim) { +- case NoTrim: +- OS << Str; +- break; +- case WidthTrim: +- OS << Str.substr(0, Width); +- break; +- case LeftTrim: +- OS << "..." << Str.substr(Str.size() - Width + 3); +- break; +- case RightTrim: +- OS << Str.substr(0, Width - 3) << "..."; +- break; +- } +-} +- +-static Column column(StringRef Str, unsigned Width) { +- return Column(Str, Width); +-} +- +-template +-static Column column(StringRef Str, unsigned Width, const T &Value) { +- return Column(Str, Width).set(Value); +-} +- +-static size_t FileReportColumns[] = {25, 10, 8, 8, 10, 10}; +-static size_t FunctionReportColumns[] = {25, 10, 8, 8, 10, 8, 8}; +- +-/// \brief Adjust column widths to fit long file paths and function names. +-static void adjustColumnWidths(coverage::CoverageMapping *CM) { +- for (StringRef Filename : CM->getUniqueSourceFiles()) { +- FileReportColumns[0] = std::max(FileReportColumns[0], Filename.size()); +- for (const auto &F : CM->getCoveredFunctions(Filename)) { +- FunctionReportColumns[0] = +- std::max(FunctionReportColumns[0], F.Name.size()); +- } +- } +-} +- +-/// \brief Prints a horizontal divider which spans across the given columns. +-template +-static void renderDivider(T (&Columns)[N], raw_ostream &OS) { +- unsigned Length = 0; +- for (unsigned I = 0; I < N; ++I) +- Length += Columns[I]; +- for (unsigned I = 0; I < Length; ++I) +- OS << '-'; +-} +- +-/// \brief Return the color which correponds to the coverage +-/// percentage of a certain metric. +-template +-static raw_ostream::Colors determineCoveragePercentageColor(const T &Info) { +- if (Info.isFullyCovered()) +- return raw_ostream::GREEN; +- return Info.getPercentCovered() >= 80.0 ? raw_ostream::YELLOW +- : raw_ostream::RED; +-} +- +-void CoverageReport::render(const FileCoverageSummary &File, raw_ostream &OS) { +- OS << column(File.Name, FileReportColumns[0], Column::NoTrim) +- << format("%*u", FileReportColumns[1], +- (unsigned)File.RegionCoverage.NumRegions); +- Options.colored_ostream(OS, File.RegionCoverage.isFullyCovered() +- ? raw_ostream::GREEN +- : raw_ostream::RED) +- << format("%*u", FileReportColumns[2], (unsigned)File.RegionCoverage.NotCovered); +- Options.colored_ostream(OS, +- determineCoveragePercentageColor(File.RegionCoverage)) +- << format("%*.2f", FileReportColumns[3] - 1, +- File.RegionCoverage.getPercentCovered()) << '%'; +- OS << format("%*u", FileReportColumns[4], +- (unsigned)File.FunctionCoverage.NumFunctions); +- Options.colored_ostream( +- OS, determineCoveragePercentageColor(File.FunctionCoverage)) +- << format("%*.2f", FileReportColumns[5] - 1, +- File.FunctionCoverage.getPercentCovered()) << '%'; +- OS << "\n"; +-} +- +-void CoverageReport::render(const FunctionCoverageSummary &Function, +- raw_ostream &OS) { +- OS << column(Function.Name, FunctionReportColumns[0], Column::RightTrim) +- << format("%*u", FunctionReportColumns[1], +- (unsigned)Function.RegionCoverage.NumRegions); +- Options.colored_ostream(OS, Function.RegionCoverage.isFullyCovered() +- ? raw_ostream::GREEN +- : raw_ostream::RED) +- << format("%*u", FunctionReportColumns[2], +- (unsigned)Function.RegionCoverage.NotCovered); +- Options.colored_ostream( +- OS, determineCoveragePercentageColor(Function.RegionCoverage)) +- << format("%*.2f", FunctionReportColumns[3] - 1, +- Function.RegionCoverage.getPercentCovered()) << '%'; +- OS << format("%*u", FunctionReportColumns[4], +- (unsigned)Function.LineCoverage.NumLines); +- Options.colored_ostream(OS, Function.LineCoverage.isFullyCovered() +- ? raw_ostream::GREEN +- : raw_ostream::RED) +- << format("%*u", FunctionReportColumns[5], +- (unsigned)Function.LineCoverage.NotCovered); +- Options.colored_ostream( +- OS, determineCoveragePercentageColor(Function.LineCoverage)) +- << format("%*.2f", FunctionReportColumns[6] - 1, +- Function.LineCoverage.getPercentCovered()) << '%'; +- OS << "\n"; +-} +- +-void CoverageReport::renderFunctionReports(ArrayRef Files, +- raw_ostream &OS) { +- adjustColumnWidths(Coverage.get()); +- bool isFirst = true; +- for (StringRef Filename : Files) { +- if (isFirst) +- isFirst = false; +- else +- OS << "\n"; +- OS << "File '" << Filename << "':\n"; +- OS << column("Name", FunctionReportColumns[0]) +- << column("Regions", FunctionReportColumns[1], Column::RightAlignment) +- << column("Miss", FunctionReportColumns[2], Column::RightAlignment) +- << column("Cover", FunctionReportColumns[3], Column::RightAlignment) +- << column("Lines", FunctionReportColumns[4], Column::RightAlignment) +- << column("Miss", FunctionReportColumns[5], Column::RightAlignment) +- << column("Cover", FunctionReportColumns[6], Column::RightAlignment); +- OS << "\n"; +- renderDivider(FunctionReportColumns, OS); +- OS << "\n"; +- FunctionCoverageSummary Totals("TOTAL"); +- for (const auto &F : Coverage->getCoveredFunctions(Filename)) { +- FunctionCoverageSummary Function = FunctionCoverageSummary::get(F); +- ++Totals.ExecutionCount; +- Totals.RegionCoverage += Function.RegionCoverage; +- Totals.LineCoverage += Function.LineCoverage; +- render(Function, OS); +- } +- if (Totals.ExecutionCount) { +- renderDivider(FunctionReportColumns, OS); +- OS << "\n"; +- render(Totals, OS); +- } +- } +-} +- +-void CoverageReport::renderFileReports(raw_ostream &OS) { +- adjustColumnWidths(Coverage.get()); +- OS << column("Filename", FileReportColumns[0]) +- << column("Regions", FileReportColumns[1], Column::RightAlignment) +- << column("Miss", FileReportColumns[2], Column::RightAlignment) +- << column("Cover", FileReportColumns[3], Column::RightAlignment) +- << column("Functions", FileReportColumns[4], Column::RightAlignment) +- << column("Executed", FileReportColumns[5], Column::RightAlignment) +- << "\n"; +- renderDivider(FileReportColumns, OS); +- OS << "\n"; +- +- FileCoverageSummary Totals("TOTAL"); +- for (StringRef Filename : Coverage->getUniqueSourceFiles()) { +- FileCoverageSummary Summary(Filename); +- for (const auto &F : Coverage->getCoveredFunctions(Filename)) { +- FunctionCoverageSummary Function = FunctionCoverageSummary::get(F); +- Summary.addFunction(Function); +- Totals.addFunction(Function); +- } +- render(Summary, OS); +- } +- renderDivider(FileReportColumns, OS); +- OS << "\n"; +- render(Totals, OS); +-} +diff --git a/tools/llvm-cov/CoverageReport.h b/tools/llvm-cov/CoverageReport.h +deleted file mode 100644 +index bb3d734..0000000 +--- a/tools/llvm-cov/CoverageReport.h ++++ /dev/null +@@ -1,41 +0,0 @@ +-//===- CoverageReport.h - Code coverage report ---------------------------===// +-// +-// The LLVM Compiler Infrastructure +-// +-// This file is distributed under the University of Illinois Open Source +-// License. See LICENSE.TXT for details. +-// +-//===----------------------------------------------------------------------===// +-// +-// This class implements rendering of a code coverage report. +-// +-//===----------------------------------------------------------------------===// +- +-#ifndef LLVM_COV_COVERAGEREPORT_H +-#define LLVM_COV_COVERAGEREPORT_H +- +-#include "CoverageSummaryInfo.h" +-#include "CoverageViewOptions.h" +- +-namespace llvm { +- +-/// \brief Displays the code coverage report. +-class CoverageReport { +- const CoverageViewOptions &Options; +- std::unique_ptr Coverage; +- +- void render(const FileCoverageSummary &File, raw_ostream &OS); +- void render(const FunctionCoverageSummary &Function, raw_ostream &OS); +- +-public: +- CoverageReport(const CoverageViewOptions &Options, +- std::unique_ptr Coverage) +- : Options(Options), Coverage(std::move(Coverage)) {} +- +- void renderFunctionReports(ArrayRef Files, raw_ostream &OS); +- +- void renderFileReports(raw_ostream &OS); +-}; +-} +- +-#endif // LLVM_COV_COVERAGEREPORT_H +diff --git a/tools/llvm-cov/CoverageSummaryInfo.cpp b/tools/llvm-cov/CoverageSummaryInfo.cpp +index de89750..8b13789 100644 +--- a/tools/llvm-cov/CoverageSummaryInfo.cpp ++++ b/tools/llvm-cov/CoverageSummaryInfo.cpp +@@ -1,71 +1 @@ +-//===- CoverageSummaryInfo.cpp - Coverage summary for function/file -------===// +-// +-// The LLVM Compiler Infrastructure +-// +-// This file is distributed under the University of Illinois Open Source +-// License. See LICENSE.TXT for details. +-// +-//===----------------------------------------------------------------------===// +-// +-// These structures are used to represent code coverage metrics +-// for functions/files. +-// +-//===----------------------------------------------------------------------===// + +-#include "CoverageSummaryInfo.h" +- +-using namespace llvm; +-using namespace coverage; +- +-FunctionCoverageSummary +-FunctionCoverageSummary::get(const coverage::FunctionRecord &Function) { +- // Compute the region coverage +- size_t NumCodeRegions = 0, CoveredRegions = 0; +- for (auto &CR : Function.CountedRegions) { +- if (CR.Kind != CounterMappingRegion::CodeRegion) +- continue; +- ++NumCodeRegions; +- if (CR.ExecutionCount != 0) +- ++CoveredRegions; +- } +- +- // Compute the line coverage +- size_t NumLines = 0, CoveredLines = 0; +- for (unsigned FileID = 0, E = Function.Filenames.size(); FileID < E; +- ++FileID) { +- // Find the line start and end of the function's source code +- // in that particular file +- unsigned LineStart = std::numeric_limits::max(); +- unsigned LineEnd = 0; +- for (auto &CR : Function.CountedRegions) { +- if (CR.FileID != FileID) +- continue; +- LineStart = std::min(LineStart, CR.LineStart); +- LineEnd = std::max(LineEnd, CR.LineEnd); +- } +- unsigned LineCount = LineEnd - LineStart + 1; +- +- // Get counters +- llvm::SmallVector ExecutionCounts; +- ExecutionCounts.resize(LineCount, 0); +- for (auto &CR : Function.CountedRegions) { +- if (CR.FileID != FileID) +- continue; +- // Ignore the lines that were skipped by the preprocessor. +- auto ExecutionCount = CR.ExecutionCount; +- if (CR.Kind == CounterMappingRegion::SkippedRegion) { +- LineCount -= CR.LineEnd - CR.LineStart + 1; +- ExecutionCount = 1; +- } +- for (unsigned I = CR.LineStart; I <= CR.LineEnd; ++I) +- ExecutionCounts[I - LineStart] = ExecutionCount; +- } +- CoveredLines += LineCount - std::count(ExecutionCounts.begin(), +- ExecutionCounts.end(), 0); +- NumLines += LineCount; +- } +- return FunctionCoverageSummary( +- Function.Name, Function.ExecutionCount, +- RegionCoverageInfo(CoveredRegions, NumCodeRegions), +- LineCoverageInfo(CoveredLines, 0, NumLines)); +-} +diff --git a/tools/llvm-cov/CoverageSummaryInfo.h b/tools/llvm-cov/CoverageSummaryInfo.h +deleted file mode 100644 +index 822742b..0000000 +--- a/tools/llvm-cov/CoverageSummaryInfo.h ++++ /dev/null +@@ -1,162 +0,0 @@ +-//===- CoverageSummaryInfo.h - Coverage summary for function/file ---------===// +-// +-// The LLVM Compiler Infrastructure +-// +-// This file is distributed under the University of Illinois Open Source +-// License. See LICENSE.TXT for details. +-// +-//===----------------------------------------------------------------------===// +-// +-// These structures are used to represent code coverage metrics +-// for functions/files. +-// +-//===----------------------------------------------------------------------===// +- +-#ifndef LLVM_COV_COVERAGESUMMARYINFO_H +-#define LLVM_COV_COVERAGESUMMARYINFO_H +- +-#include "llvm/ProfileData/Coverage/CoverageMapping.h" +-#include "llvm/Support/raw_ostream.h" +- +-namespace llvm { +- +-/// \brief Provides information about region coverage for a function/file. +-struct RegionCoverageInfo { +- /// \brief The number of regions that were executed at least once. +- size_t Covered; +- +- /// \brief The number of regions that weren't executed. +- size_t NotCovered; +- +- /// \brief The total number of regions in a function/file. +- size_t NumRegions; +- +- RegionCoverageInfo() : Covered(0), NotCovered(0), NumRegions(0) {} +- +- RegionCoverageInfo(size_t Covered, size_t NumRegions) +- : Covered(Covered), NotCovered(NumRegions - Covered), +- NumRegions(NumRegions) {} +- +- RegionCoverageInfo &operator+=(const RegionCoverageInfo &RHS) { +- Covered += RHS.Covered; +- NotCovered += RHS.NotCovered; +- NumRegions += RHS.NumRegions; +- return *this; +- } +- +- bool isFullyCovered() const { return Covered == NumRegions; } +- +- double getPercentCovered() const { +- if (NumRegions == 0) +- return 0.0; +- return double(Covered) / double(NumRegions) * 100.0; +- } +-}; +- +-/// \brief Provides information about line coverage for a function/file. +-struct LineCoverageInfo { +- /// \brief The number of lines that were executed at least once. +- size_t Covered; +- +- /// \brief The number of lines that weren't executed. +- size_t NotCovered; +- +- /// \brief The number of lines that aren't code. +- size_t NonCodeLines; +- +- /// \brief The total number of lines in a function/file. +- size_t NumLines; +- +- LineCoverageInfo() +- : Covered(0), NotCovered(0), NonCodeLines(0), NumLines(0) {} +- +- LineCoverageInfo(size_t Covered, size_t NumNonCodeLines, size_t NumLines) +- : Covered(Covered), NotCovered(NumLines - NumNonCodeLines - Covered), +- NonCodeLines(NumNonCodeLines), NumLines(NumLines) {} +- +- LineCoverageInfo &operator+=(const LineCoverageInfo &RHS) { +- Covered += RHS.Covered; +- NotCovered += RHS.NotCovered; +- NonCodeLines += RHS.NonCodeLines; +- NumLines += RHS.NumLines; +- return *this; +- } +- +- bool isFullyCovered() const { return Covered == (NumLines - NonCodeLines); } +- +- double getPercentCovered() const { +- if (NumLines - NonCodeLines == 0) +- return 0.0; +- return double(Covered) / double(NumLines - NonCodeLines) * 100.0; +- } +-}; +- +-/// \brief Provides information about function coverage for a file. +-struct FunctionCoverageInfo { +- /// \brief The number of functions that were executed. +- size_t Executed; +- +- /// \brief The total number of functions in this file. +- size_t NumFunctions; +- +- FunctionCoverageInfo() : Executed(0), NumFunctions(0) {} +- +- FunctionCoverageInfo(size_t Executed, size_t NumFunctions) +- : Executed(Executed), NumFunctions(NumFunctions) {} +- +- void addFunction(bool Covered) { +- if (Covered) +- ++Executed; +- ++NumFunctions; +- } +- +- bool isFullyCovered() const { return Executed == NumFunctions; } +- +- double getPercentCovered() const { +- if (NumFunctions == 0) +- return 0.0; +- return double(Executed) / double(NumFunctions) * 100.0; +- } +-}; +- +-/// \brief A summary of function's code coverage. +-struct FunctionCoverageSummary { +- StringRef Name; +- uint64_t ExecutionCount; +- RegionCoverageInfo RegionCoverage; +- LineCoverageInfo LineCoverage; +- +- FunctionCoverageSummary(StringRef Name) : Name(Name), ExecutionCount(0) {} +- +- FunctionCoverageSummary(StringRef Name, uint64_t ExecutionCount, +- const RegionCoverageInfo &RegionCoverage, +- const LineCoverageInfo &LineCoverage) +- : Name(Name), ExecutionCount(ExecutionCount), +- RegionCoverage(RegionCoverage), LineCoverage(LineCoverage) { +- } +- +- /// \brief Compute the code coverage summary for the given function coverage +- /// mapping record. +- static FunctionCoverageSummary +- get(const coverage::FunctionRecord &Function); +-}; +- +-/// \brief A summary of file's code coverage. +-struct FileCoverageSummary { +- StringRef Name; +- RegionCoverageInfo RegionCoverage; +- LineCoverageInfo LineCoverage; +- FunctionCoverageInfo FunctionCoverage; +- +- FileCoverageSummary(StringRef Name) : Name(Name) {} +- +- void addFunction(const FunctionCoverageSummary &Function) { +- RegionCoverage += Function.RegionCoverage; +- LineCoverage += Function.LineCoverage; +- FunctionCoverage.addFunction(/*Covered=*/Function.ExecutionCount > 0); +- } +-}; +- +-} // namespace llvm +- +-#endif // LLVM_COV_COVERAGESUMMARYINFO_H +diff --git a/tools/llvm-cov/CoverageViewOptions.h b/tools/llvm-cov/CoverageViewOptions.h +deleted file mode 100644 +index 350c264..0000000 +--- a/tools/llvm-cov/CoverageViewOptions.h ++++ /dev/null +@@ -1,52 +0,0 @@ +-//===- CoverageViewOptions.h - Code coverage display options -------------===// +-// +-// The LLVM Compiler Infrastructure +-// +-// This file is distributed under the University of Illinois Open Source +-// License. See LICENSE.TXT for details. +-// +-//===----------------------------------------------------------------------===// +- +-#ifndef LLVM_COV_COVERAGEVIEWOPTIONS_H +-#define LLVM_COV_COVERAGEVIEWOPTIONS_H +- +-#include "RenderingSupport.h" +-#include +- +-namespace llvm { +- +-/// \brief The options for displaying the code coverage information. +-struct CoverageViewOptions { +- enum class OutputFormat { +- Text, +- HTML +- }; +- +- bool Debug; +- bool Colors; +- bool ShowLineNumbers; +- bool ShowLineStats; +- bool ShowRegionMarkers; +- bool ShowLineStatsOrRegionMarkers; +- bool ShowExpandedRegions; +- bool ShowFunctionInstantiations; +- bool ShowFullFilenames; +- OutputFormat Format; +- std::string ShowOutputDirectory; +- std::vector DemanglerOpts; +- +- /// \brief Change the output's stream color if the colors are enabled. +- ColoredRawOstream colored_ostream(raw_ostream &OS, +- raw_ostream::Colors Color) const { +- return llvm::colored_ostream(OS, Color, Colors); +- } +- +- /// \brief Check if an output directory has been specified. +- bool hasOutputDirectory() const { return !ShowOutputDirectory.empty(); } +- +- /// \brief Check if a demangler has been specified. +- bool hasDemangler() const { return !DemanglerOpts.empty(); } +-}; +-} +- +-#endif // LLVM_COV_COVERAGEVIEWOPTIONS_H +diff --git a/tools/llvm-cov/RenderingSupport.h b/tools/llvm-cov/RenderingSupport.h +deleted file mode 100644 +index aa70fbc..0000000 +--- a/tools/llvm-cov/RenderingSupport.h ++++ /dev/null +@@ -1,61 +0,0 @@ +-//===- RenderingSupport.h - output stream rendering support functions ----===// +-// +-// The LLVM Compiler Infrastructure +-// +-// This file is distributed under the University of Illinois Open Source +-// License. See LICENSE.TXT for details. +-// +-//===----------------------------------------------------------------------===// +- +-#ifndef LLVM_COV_RENDERINGSUPPORT_H +-#define LLVM_COV_RENDERINGSUPPORT_H +- +-#include "llvm/Support/raw_ostream.h" +-#include +- +-namespace llvm { +- +-/// \brief A helper class that resets the output stream's color if needed +-/// when destroyed. +-class ColoredRawOstream { +- ColoredRawOstream(const ColoredRawOstream &OS) = delete; +- +-public: +- raw_ostream &OS; +- bool IsColorUsed; +- +- ColoredRawOstream(raw_ostream &OS, bool IsColorUsed) +- : OS(OS), IsColorUsed(IsColorUsed) {} +- +- ColoredRawOstream(ColoredRawOstream &&Other) +- : OS(Other.OS), IsColorUsed(Other.IsColorUsed) { +- // Reset the other IsColorUsed so that the other object won't reset the +- // color when destroyed. +- Other.IsColorUsed = false; +- } +- +- ~ColoredRawOstream() { +- if (IsColorUsed) +- OS.resetColor(); +- } +-}; +- +-template +-inline raw_ostream &operator<<(const ColoredRawOstream &OS, T &&Value) { +- return OS.OS << std::forward(Value); +-} +- +-/// \brief Change the color of the output stream if the `IsColorUsed` flag +-/// is true. Returns an object that resets the color when destroyed. +-inline ColoredRawOstream colored_ostream(raw_ostream &OS, +- raw_ostream::Colors Color, +- bool IsColorUsed = true, +- bool Bold = false, bool BG = false) { +- if (IsColorUsed) +- OS.changeColor(Color, Bold, BG); +- return ColoredRawOstream(OS, IsColorUsed); +-} +- +-} // namespace llvm +- +-#endif // LLVM_COV_RENDERINGSUPPORT_H +diff --git a/tools/llvm-cov/SourceCoverageView.cpp b/tools/llvm-cov/SourceCoverageView.cpp +index baf7c14..8b13789 100644 +--- a/tools/llvm-cov/SourceCoverageView.cpp ++++ b/tools/llvm-cov/SourceCoverageView.cpp +@@ -1,233 +1 @@ +-//===- SourceCoverageView.cpp - Code coverage view for source code --------===// +-// +-// The LLVM Compiler Infrastructure +-// +-// This file is distributed under the University of Illinois Open Source +-// License. See LICENSE.TXT for details. +-// +-//===----------------------------------------------------------------------===// +-/// +-/// \file This class implements rendering for code coverage of source code. +-/// +-//===----------------------------------------------------------------------===// + +-#include "SourceCoverageView.h" +-#include "SourceCoverageViewHTML.h" +-#include "SourceCoverageViewText.h" +-#include "llvm/ADT/SmallString.h" +-#include "llvm/ADT/StringExtras.h" +-#include "llvm/Support/FileSystem.h" +-#include "llvm/Support/LineIterator.h" +-#include "llvm/Support/Path.h" +- +-using namespace llvm; +- +-void CoveragePrinter::StreamDestructor::operator()(raw_ostream *OS) const { +- if (OS == &outs()) +- return; +- delete OS; +-} +- +-std::string CoveragePrinter::getOutputPath(StringRef Path, StringRef Extension, +- bool InToplevel, bool Relative) { +- assert(Extension.size() && "The file extension may not be empty"); +- +- SmallString<256> FullPath; +- +- if (!Relative) +- FullPath.append(Opts.ShowOutputDirectory); +- +- if (!InToplevel) +- sys::path::append(FullPath, getCoverageDir()); +- +- SmallString<256> ParentPath = sys::path::parent_path(Path); +- sys::path::remove_dots(ParentPath, /*remove_dot_dots=*/true); +- sys::path::append(FullPath, sys::path::relative_path(ParentPath)); +- +- auto PathFilename = (sys::path::filename(Path) + "." + Extension).str(); +- sys::path::append(FullPath, PathFilename); +- +- return FullPath.str(); +-} +- +-Expected +-CoveragePrinter::createOutputStream(StringRef Path, StringRef Extension, +- bool InToplevel) { +- if (!Opts.hasOutputDirectory()) +- return OwnedStream(&outs()); +- +- std::string FullPath = getOutputPath(Path, Extension, InToplevel, false); +- +- auto ParentDir = sys::path::parent_path(FullPath); +- if (auto E = sys::fs::create_directories(ParentDir)) +- return errorCodeToError(E); +- +- std::error_code E; +- raw_ostream *RawStream = new raw_fd_ostream(FullPath, E, sys::fs::F_RW); +- auto OS = CoveragePrinter::OwnedStream(RawStream); +- if (E) +- return errorCodeToError(E); +- return std::move(OS); +-} +- +-std::unique_ptr +-CoveragePrinter::create(const CoverageViewOptions &Opts) { +- switch (Opts.Format) { +- case CoverageViewOptions::OutputFormat::Text: +- return llvm::make_unique(Opts); +- case CoverageViewOptions::OutputFormat::HTML: +- return llvm::make_unique(Opts); +- } +- llvm_unreachable("Unknown coverage output format!"); +-} +- +-std::string SourceCoverageView::formatCount(uint64_t N) { +- std::string Number = utostr(N); +- int Len = Number.size(); +- if (Len <= 3) +- return Number; +- int IntLen = Len % 3 == 0 ? 3 : Len % 3; +- std::string Result(Number.data(), IntLen); +- if (IntLen != 3) { +- Result.push_back('.'); +- Result += Number.substr(IntLen, 3 - IntLen); +- } +- Result.push_back(" kMGTPEZY"[(Len - 1) / 3]); +- return Result; +-} +- +-bool SourceCoverageView::shouldRenderRegionMarkers( +- bool LineHasMultipleRegions) const { +- return getOptions().ShowRegionMarkers && +- (!getOptions().ShowLineStatsOrRegionMarkers || LineHasMultipleRegions); +-} +- +-bool SourceCoverageView::hasSubViews() const { +- return !ExpansionSubViews.empty() || !InstantiationSubViews.empty(); +-} +- +-std::unique_ptr +-SourceCoverageView::create(StringRef SourceName, const MemoryBuffer &File, +- const CoverageViewOptions &Options, +- coverage::CoverageData &&CoverageInfo) { +- switch (Options.Format) { +- case CoverageViewOptions::OutputFormat::Text: +- return llvm::make_unique(SourceName, File, Options, +- std::move(CoverageInfo)); +- case CoverageViewOptions::OutputFormat::HTML: +- return llvm::make_unique(SourceName, File, Options, +- std::move(CoverageInfo)); +- } +- llvm_unreachable("Unknown coverage output format!"); +-} +- +-void SourceCoverageView::addExpansion( +- const coverage::CounterMappingRegion &Region, +- std::unique_ptr View) { +- ExpansionSubViews.emplace_back(Region, std::move(View)); +-} +- +-void SourceCoverageView::addInstantiation( +- StringRef FunctionName, unsigned Line, +- std::unique_ptr View) { +- InstantiationSubViews.emplace_back(FunctionName, Line, std::move(View)); +-} +- +-void SourceCoverageView::print(raw_ostream &OS, bool WholeFile, +- bool ShowSourceName, unsigned ViewDepth) { +- if (ShowSourceName) +- renderSourceName(OS); +- +- renderViewHeader(OS); +- +- // We need the expansions and instantiations sorted so we can go through them +- // while we iterate lines. +- std::sort(ExpansionSubViews.begin(), ExpansionSubViews.end()); +- std::sort(InstantiationSubViews.begin(), InstantiationSubViews.end()); +- auto NextESV = ExpansionSubViews.begin(); +- auto EndESV = ExpansionSubViews.end(); +- auto NextISV = InstantiationSubViews.begin(); +- auto EndISV = InstantiationSubViews.end(); +- +- // Get the coverage information for the file. +- auto NextSegment = CoverageInfo.begin(); +- auto EndSegment = CoverageInfo.end(); +- +- unsigned FirstLine = NextSegment != EndSegment ? NextSegment->Line : 0; +- const coverage::CoverageSegment *WrappedSegment = nullptr; +- SmallVector LineSegments; +- for (line_iterator LI(File, /*SkipBlanks=*/false); !LI.is_at_eof(); ++LI) { +- // If we aren't rendering the whole file, we need to filter out the prologue +- // and epilogue. +- if (!WholeFile) { +- if (NextSegment == EndSegment) +- break; +- else if (LI.line_number() < FirstLine) +- continue; +- } +- +- // Collect the coverage information relevant to this line. +- if (LineSegments.size()) +- WrappedSegment = LineSegments.back(); +- LineSegments.clear(); +- while (NextSegment != EndSegment && NextSegment->Line == LI.line_number()) +- LineSegments.push_back(&*NextSegment++); +- +- // Calculate a count to be for the line as a whole. +- LineCoverageStats LineCount; +- if (WrappedSegment && WrappedSegment->HasCount) +- LineCount.addRegionCount(WrappedSegment->Count); +- for (const auto *S : LineSegments) +- if (S->HasCount && S->IsRegionEntry) +- LineCount.addRegionStartCount(S->Count); +- +- renderLinePrefix(OS, ViewDepth); +- if (getOptions().ShowLineStats) +- renderLineCoverageColumn(OS, LineCount); +- if (getOptions().ShowLineNumbers) +- renderLineNumberColumn(OS, LI.line_number()); +- +- // If there are expansion subviews, we want to highlight the first one. +- unsigned ExpansionColumn = 0; +- if (NextESV != EndESV && NextESV->getLine() == LI.line_number() && +- getOptions().Colors) +- ExpansionColumn = NextESV->getStartCol(); +- +- // Display the source code for the current line. +- renderLine(OS, {*LI, LI.line_number()}, WrappedSegment, LineSegments, +- ExpansionColumn, ViewDepth); +- +- // Show the region markers. +- if (shouldRenderRegionMarkers(LineCount.hasMultipleRegions())) +- renderRegionMarkers(OS, LineSegments, ViewDepth); +- +- // Show the expansions and instantiations for this line. +- bool RenderedSubView = false; +- for (; NextESV != EndESV && NextESV->getLine() == LI.line_number(); +- ++NextESV) { +- renderViewDivider(OS, ViewDepth + 1); +- +- // Re-render the current line and highlight the expansion range for +- // this subview. +- if (RenderedSubView) { +- ExpansionColumn = NextESV->getStartCol(); +- renderExpansionSite(OS, {*LI, LI.line_number()}, WrappedSegment, +- LineSegments, ExpansionColumn, ViewDepth); +- renderViewDivider(OS, ViewDepth + 1); +- } +- +- renderExpansionView(OS, *NextESV, ViewDepth + 1); +- RenderedSubView = true; +- } +- for (; NextISV != EndISV && NextISV->Line == LI.line_number(); ++NextISV) { +- renderViewDivider(OS, ViewDepth + 1); +- renderInstantiationView(OS, *NextISV, ViewDepth + 1); +- RenderedSubView = true; +- } +- if (RenderedSubView) +- renderViewDivider(OS, ViewDepth + 1); +- renderLineSuffix(OS, ViewDepth); +- } +- +- renderViewFooter(OS); +-} +diff --git a/tools/llvm-cov/SourceCoverageView.h b/tools/llvm-cov/SourceCoverageView.h +deleted file mode 100644 +index feef959..0000000 +--- a/tools/llvm-cov/SourceCoverageView.h ++++ /dev/null +@@ -1,285 +0,0 @@ +-//===- SourceCoverageView.h - Code coverage view for source code ----------===// +-// +-// The LLVM Compiler Infrastructure +-// +-// This file is distributed under the University of Illinois Open Source +-// License. See LICENSE.TXT for details. +-// +-//===----------------------------------------------------------------------===// +-/// +-/// \file This class implements rendering for code coverage of source code. +-/// +-//===----------------------------------------------------------------------===// +- +-#ifndef LLVM_COV_SOURCECOVERAGEVIEW_H +-#define LLVM_COV_SOURCECOVERAGEVIEW_H +- +-#include "CoverageViewOptions.h" +-#include "llvm/ProfileData/Coverage/CoverageMapping.h" +-#include "llvm/Support/MemoryBuffer.h" +-#include +- +-namespace llvm { +- +-class SourceCoverageView; +- +-/// \brief A view that represents a macro or include expansion. +-struct ExpansionView { +- coverage::CounterMappingRegion Region; +- std::unique_ptr View; +- +- ExpansionView(const coverage::CounterMappingRegion &Region, +- std::unique_ptr View) +- : Region(Region), View(std::move(View)) {} +- ExpansionView(ExpansionView &&RHS) +- : Region(std::move(RHS.Region)), View(std::move(RHS.View)) {} +- ExpansionView &operator=(ExpansionView &&RHS) { +- Region = std::move(RHS.Region); +- View = std::move(RHS.View); +- return *this; +- } +- +- unsigned getLine() const { return Region.LineStart; } +- unsigned getStartCol() const { return Region.ColumnStart; } +- unsigned getEndCol() const { return Region.ColumnEnd; } +- +- friend bool operator<(const ExpansionView &LHS, const ExpansionView &RHS) { +- return LHS.Region.startLoc() < RHS.Region.startLoc(); +- } +-}; +- +-/// \brief A view that represents a function instantiation. +-struct InstantiationView { +- StringRef FunctionName; +- unsigned Line; +- std::unique_ptr View; +- +- InstantiationView(StringRef FunctionName, unsigned Line, +- std::unique_ptr View) +- : FunctionName(FunctionName), Line(Line), View(std::move(View)) {} +- InstantiationView(InstantiationView &&RHS) +- : FunctionName(std::move(RHS.FunctionName)), Line(std::move(RHS.Line)), +- View(std::move(RHS.View)) {} +- InstantiationView &operator=(InstantiationView &&RHS) { +- FunctionName = std::move(RHS.FunctionName); +- Line = std::move(RHS.Line); +- View = std::move(RHS.View); +- return *this; +- } +- +- friend bool operator<(const InstantiationView &LHS, +- const InstantiationView &RHS) { +- return LHS.Line < RHS.Line; +- } +-}; +- +-/// \brief Coverage statistics for a single line. +-struct LineCoverageStats { +- uint64_t ExecutionCount; +- unsigned RegionCount; +- bool Mapped; +- +- LineCoverageStats() : ExecutionCount(0), RegionCount(0), Mapped(false) {} +- +- bool isMapped() const { return Mapped; } +- +- bool hasMultipleRegions() const { return RegionCount > 1; } +- +- void addRegionStartCount(uint64_t Count) { +- // The max of all region starts is the most interesting value. +- addRegionCount(RegionCount ? std::max(ExecutionCount, Count) : Count); +- ++RegionCount; +- } +- +- void addRegionCount(uint64_t Count) { +- Mapped = true; +- ExecutionCount = Count; +- } +-}; +- +-/// \brief A file manager that handles format-aware file creation. +-class CoveragePrinter { +- const CoverageViewOptions &Opts; +- +-public: +- struct StreamDestructor { +- void operator()(raw_ostream *OS) const; +- }; +- +- using OwnedStream = std::unique_ptr; +- +-protected: +- CoveragePrinter(const CoverageViewOptions &Opts) : Opts(Opts) {} +- +- /// \brief Return `OutputDir/ToplevelDir/Path.Extension`. If \p InToplevel is +- /// false, skip the ToplevelDir component. If \p Relative is false, skip the +- /// OutputDir component. +- std::string getOutputPath(StringRef Path, StringRef Extension, +- bool InToplevel, bool Relative = true); +- +- /// \brief If directory output is enabled, create a file in that directory +- /// at the path given by getOutputPath(). Otherwise, return stdout. +- Expected createOutputStream(StringRef Path, StringRef Extension, +- bool InToplevel); +- +- /// \brief Return the sub-directory name for file coverage reports. +- static StringRef getCoverageDir() { return "coverage"; } +- +-public: +- static std::unique_ptr +- create(const CoverageViewOptions &Opts); +- +- virtual ~CoveragePrinter() {} +- +- /// @name File Creation Interface +- /// @{ +- +- /// \brief Create a file to print a coverage view into. +- virtual Expected createViewFile(StringRef Path, +- bool InToplevel) = 0; +- +- /// \brief Close a file which has been used to print a coverage view. +- virtual void closeViewFile(OwnedStream OS) = 0; +- +- /// \brief Create an index which lists reports for the given source files. +- virtual Error createIndexFile(ArrayRef SourceFiles) = 0; +- +- /// @} +-}; +- +-/// \brief A code coverage view of a source file or function. +-/// +-/// A source coverage view and its nested sub-views form a file-oriented +-/// representation of code coverage data. This view can be printed out by a +-/// renderer which implements the Rendering Interface. +-class SourceCoverageView { +- /// A function or file name. +- StringRef SourceName; +- +- /// A memory buffer backing the source on display. +- const MemoryBuffer &File; +- +- /// Various options to guide the coverage renderer. +- const CoverageViewOptions &Options; +- +- /// Complete coverage information about the source on display. +- coverage::CoverageData CoverageInfo; +- +- /// A container for all expansions (e.g macros) in the source on display. +- std::vector ExpansionSubViews; +- +- /// A container for all instantiations (e.g template functions) in the source +- /// on display. +- std::vector InstantiationSubViews; +- +-protected: +- struct LineRef { +- StringRef Line; +- int64_t LineNo; +- +- LineRef(StringRef Line, int64_t LineNo) : Line(Line), LineNo(LineNo) {} +- }; +- +- using CoverageSegmentArray = ArrayRef; +- +- /// @name Rendering Interface +- /// @{ +- +- /// \brief Render a header for the view. +- virtual void renderViewHeader(raw_ostream &OS) = 0; +- +- /// \brief Render a footer for the view. +- virtual void renderViewFooter(raw_ostream &OS) = 0; +- +- /// \brief Render the source name for the view. +- virtual void renderSourceName(raw_ostream &OS) = 0; +- +- /// \brief Render the line prefix at the given \p ViewDepth. +- virtual void renderLinePrefix(raw_ostream &OS, unsigned ViewDepth) = 0; +- +- /// \brief Render the line suffix at the given \p ViewDepth. +- virtual void renderLineSuffix(raw_ostream &OS, unsigned ViewDepth) = 0; +- +- /// \brief Render a view divider at the given \p ViewDepth. +- virtual void renderViewDivider(raw_ostream &OS, unsigned ViewDepth) = 0; +- +- /// \brief Render a source line with highlighting. +- virtual void renderLine(raw_ostream &OS, LineRef L, +- const coverage::CoverageSegment *WrappedSegment, +- CoverageSegmentArray Segments, unsigned ExpansionCol, +- unsigned ViewDepth) = 0; +- +- /// \brief Render the line's execution count column. +- virtual void renderLineCoverageColumn(raw_ostream &OS, +- const LineCoverageStats &Line) = 0; +- +- /// \brief Render the line number column. +- virtual void renderLineNumberColumn(raw_ostream &OS, unsigned LineNo) = 0; +- +- /// \brief Render all the region's execution counts on a line. +- virtual void renderRegionMarkers(raw_ostream &OS, +- CoverageSegmentArray Segments, +- unsigned ViewDepth) = 0; +- +- /// \brief Render the site of an expansion. +- virtual void +- renderExpansionSite(raw_ostream &OS, LineRef L, +- const coverage::CoverageSegment *WrappedSegment, +- CoverageSegmentArray Segments, unsigned ExpansionCol, +- unsigned ViewDepth) = 0; +- +- /// \brief Render an expansion view and any nested views. +- virtual void renderExpansionView(raw_ostream &OS, ExpansionView &ESV, +- unsigned ViewDepth) = 0; +- +- /// \brief Render an instantiation view and any nested views. +- virtual void renderInstantiationView(raw_ostream &OS, InstantiationView &ISV, +- unsigned ViewDepth) = 0; +- +- /// @} +- +- /// \brief Format a count using engineering notation with 3 significant +- /// digits. +- static std::string formatCount(uint64_t N); +- +- /// \brief Check if region marker output is expected for a line. +- bool shouldRenderRegionMarkers(bool LineHasMultipleRegions) const; +- +- /// \brief Check if there are any sub-views attached to this view. +- bool hasSubViews() const; +- +- SourceCoverageView(StringRef SourceName, const MemoryBuffer &File, +- const CoverageViewOptions &Options, +- coverage::CoverageData &&CoverageInfo) +- : SourceName(SourceName), File(File), Options(Options), +- CoverageInfo(std::move(CoverageInfo)) {} +- +-public: +- static std::unique_ptr +- create(StringRef SourceName, const MemoryBuffer &File, +- const CoverageViewOptions &Options, +- coverage::CoverageData &&CoverageInfo); +- +- virtual ~SourceCoverageView() {} +- +- StringRef getSourceName() const { return SourceName; } +- +- const CoverageViewOptions &getOptions() const { return Options; } +- +- /// \brief Add an expansion subview to this view. +- void addExpansion(const coverage::CounterMappingRegion &Region, +- std::unique_ptr View); +- +- /// \brief Add a function instantiation subview to this view. +- void addInstantiation(StringRef FunctionName, unsigned Line, +- std::unique_ptr View); +- +- /// \brief Print the code coverage information for a specific portion of a +- /// source file to the output stream. +- void print(raw_ostream &OS, bool WholeFile, bool ShowSourceName, +- unsigned ViewDepth = 0); +-}; +- +-} // namespace llvm +- +-#endif // LLVM_COV_SOURCECOVERAGEVIEW_H +diff --git a/tools/llvm-cov/SourceCoverageViewHTML.cpp b/tools/llvm-cov/SourceCoverageViewHTML.cpp +index 81963e5..8b13789 100644 +--- a/tools/llvm-cov/SourceCoverageViewHTML.cpp ++++ b/tools/llvm-cov/SourceCoverageViewHTML.cpp +@@ -1,436 +1 @@ +-//===- SourceCoverageViewHTML.cpp - A html code coverage view -------------===// +-// +-// The LLVM Compiler Infrastructure +-// +-// This file is distributed under the University of Illinois Open Source +-// License. See LICENSE.TXT for details. +-// +-//===----------------------------------------------------------------------===// +-/// +-/// \file This file implements the html coverage renderer. +-/// +-//===----------------------------------------------------------------------===// + +-#include "SourceCoverageViewHTML.h" +-#include "llvm/ADT/Optional.h" +-#include "llvm/ADT/SmallString.h" +-#include "llvm/ADT/StringExtras.h" +-#include "llvm/Support/Path.h" +- +-using namespace llvm; +- +-namespace { +- +-const char *BeginHeader = +- "" +- "" +- ""; +- +-const char *CSSForCoverage = +- ""; +- +-const char *EndHeader = ""; +- +-const char *BeginCenteredDiv = "
"; +- +-const char *EndCenteredDiv = "
"; +- +-const char *BeginSourceNameDiv = "
"; +- +-const char *EndSourceNameDiv = "
"; +- +-const char *BeginCodeTD = ""; +- +-const char *EndCodeTD = ""; +- +-const char *BeginPre = "
";
+-
+-const char *EndPre = "
"; +- +-const char *BeginExpansionDiv = "
"; +- +-const char *EndExpansionDiv = "
"; +- +-const char *BeginTable = ""; +- +-const char *EndTable = "
"; +- +-void emitPrelude(raw_ostream &OS) { +- OS << "" +- "" +- << BeginHeader << CSSForCoverage << EndHeader << "" +- << BeginCenteredDiv; +-} +- +-void emitEpilog(raw_ostream &OS) { +- OS << EndCenteredDiv << "" +- ""; +-} +- +-// Return a string with the special characters in \p Str escaped. +-std::string escape(StringRef Str) { +- std::string Result; +- for (char C : Str) { +- if (C == '&') +- Result += "&"; +- else if (C == '<') +- Result += "<"; +- else if (C == '>') +- Result += ">"; +- else if (C == '\"') +- Result += """; +- else +- Result += C; +- } +- return Result; +-} +- +-// Create a \p Name tag around \p Str, and optionally set its \p ClassName. +-std::string tag(const std::string &Name, const std::string &Str, +- const std::string &ClassName = "") { +- std::string Tag = "<" + Name; +- if (ClassName != "") +- Tag += " class='" + ClassName + "'"; +- return Tag + ">" + Str + ""; +-} +- +-// Create an anchor to \p Link with the label \p Str. +-std::string a(const std::string &Link, const std::string &Str) { +- return "" + Str + ""; +-} +- +-} // anonymous namespace +- +-Expected +-CoveragePrinterHTML::createViewFile(StringRef Path, bool InToplevel) { +- auto OSOrErr = createOutputStream(Path, "html", InToplevel); +- if (!OSOrErr) +- return OSOrErr; +- +- OwnedStream OS = std::move(OSOrErr.get()); +- emitPrelude(*OS.get()); +- return std::move(OS); +-} +- +-void CoveragePrinterHTML::closeViewFile(OwnedStream OS) { +- emitEpilog(*OS.get()); +-} +- +-Error CoveragePrinterHTML::createIndexFile(ArrayRef SourceFiles) { +- auto OSOrErr = createOutputStream("index", "html", /*InToplevel=*/true); +- if (Error E = OSOrErr.takeError()) +- return E; +- auto OS = std::move(OSOrErr.get()); +- raw_ostream &OSRef = *OS.get(); +- +- // Emit a table containing links to reports for each file in the covmapping. +- emitPrelude(OSRef); +- OSRef << BeginSourceNameDiv << "Index" << EndSourceNameDiv; +- OSRef << BeginTable; +- for (StringRef SF : SourceFiles) { +- std::string LinkText = escape(sys::path::relative_path(SF)); +- std::string LinkTarget = +- escape(getOutputPath(SF, "html", /*InToplevel=*/false)); +- OSRef << tag("tr", tag("td", tag("pre", a(LinkTarget, LinkText), "code"))); +- } +- OSRef << EndTable; +- emitEpilog(OSRef); +- +- return Error::success(); +-} +- +-void SourceCoverageViewHTML::renderViewHeader(raw_ostream &OS) { +- OS << BeginTable; +-} +- +-void SourceCoverageViewHTML::renderViewFooter(raw_ostream &OS) { +- OS << EndTable; +-} +- +-void SourceCoverageViewHTML::renderSourceName(raw_ostream &OS) { +- OS << BeginSourceNameDiv << tag("pre", escape(getSourceName())) +- << EndSourceNameDiv; +-} +- +-void SourceCoverageViewHTML::renderLinePrefix(raw_ostream &OS, unsigned) { +- OS << ""; +-} +- +-void SourceCoverageViewHTML::renderLineSuffix(raw_ostream &OS, unsigned) { +- // If this view has sub-views, renderLine() cannot close the view's cell. +- // Take care of it here, after all sub-views have been rendered. +- if (hasSubViews()) +- OS << EndCodeTD; +- OS << ""; +-} +- +-void SourceCoverageViewHTML::renderViewDivider(raw_ostream &, unsigned) { +- // The table-based output makes view dividers unnecessary. +-} +- +-void SourceCoverageViewHTML::renderLine( +- raw_ostream &OS, LineRef L, const coverage::CoverageSegment *WrappedSegment, +- CoverageSegmentArray Segments, unsigned ExpansionCol, unsigned) { +- StringRef Line = L.Line; +- +- // Steps for handling text-escaping, highlighting, and tooltip creation: +- // +- // 1. Split the line into N+1 snippets, where N = |Segments|. The first +- // snippet starts from Col=1 and ends at the start of the first segment. +- // The last snippet starts at the last mapped column in the line and ends +- // at the end of the line. Both are required but may be empty. +- +- SmallVector Snippets; +- +- unsigned LCol = 1; +- auto Snip = [&](unsigned Start, unsigned Len) { +- assert(Start + Len <= Line.size() && "Snippet extends past the EOL"); +- Snippets.push_back(Line.substr(Start, Len)); +- LCol += Len; +- }; +- +- Snip(LCol - 1, Segments.empty() ? 0 : (Segments.front()->Col - 1)); +- +- for (unsigned I = 1, E = Segments.size(); I < E; ++I) { +- assert(LCol == Segments[I - 1]->Col && "Snippet start position is wrong"); +- Snip(LCol - 1, Segments[I]->Col - LCol); +- } +- +- // |Line| + 1 is needed to avoid underflow when, e.g |Line| = 0 and LCol = 1. +- Snip(LCol - 1, Line.size() + 1 - LCol); +- assert(LCol == Line.size() + 1 && "Final snippet doesn't reach the EOL"); +- +- // 2. Escape all of the snippets. +- +- for (unsigned I = 0, E = Snippets.size(); I < E; ++I) +- Snippets[I] = escape(Snippets[I]); +- +- // 3. Use \p WrappedSegment to set the highlight for snippets 0 and 1. Use +- // segment 1 to set the highlight for snippet 2, segment 2 to set the +- // highlight for snippet 3, and so on. +- +- Optional Color; +- auto Highlight = [&](const std::string &Snippet) { +- return tag("span", Snippet, Color.getValue()); +- }; +- +- auto CheckIfUncovered = [](const coverage::CoverageSegment *S) { +- return S && S->HasCount && S->Count == 0; +- }; +- +- if (CheckIfUncovered(WrappedSegment) || +- CheckIfUncovered(Segments.empty() ? nullptr : Segments.front())) { +- Color = "red"; +- Snippets[0] = Highlight(Snippets[0]); +- Snippets[1] = Highlight(Snippets[1]); +- } +- +- for (unsigned I = 1, E = Segments.size(); I < E; ++I) { +- const auto *CurSeg = Segments[I]; +- if (CurSeg->Col == ExpansionCol) +- Color = "cyan"; +- else if (CheckIfUncovered(CurSeg)) +- Color = "red"; +- else +- Color = None; +- +- if (Color.hasValue()) +- Snippets[I + 1] = Highlight(Snippets[I + 1]); +- } +- +- // 4. Snippets[1:N+1] correspond to \p Segments[0:N]: use these to generate +- // sub-line region count tooltips if needed. +- +- bool HasMultipleRegions = [&] { +- unsigned RegionCount = 0; +- for (const auto *S : Segments) +- if (S->HasCount && S->IsRegionEntry) +- if (++RegionCount > 1) +- return true; +- return false; +- }(); +- +- if (shouldRenderRegionMarkers(HasMultipleRegions)) { +- for (unsigned I = 0, E = Segments.size(); I < E; ++I) { +- const auto *CurSeg = Segments[I]; +- if (!CurSeg->IsRegionEntry || !CurSeg->HasCount) +- continue; +- +- Snippets[I + 1] = +- tag("div", Snippets[I + 1] + tag("span", formatCount(CurSeg->Count), +- "tooltip-content"), +- "tooltip"); +- } +- } +- +- OS << BeginCodeTD; +- OS << BeginPre; +- for (const auto &Snippet : Snippets) +- OS << Snippet; +- OS << EndPre; +- +- // If there are no sub-views left to attach to this cell, end the cell. +- // Otherwise, end it after the sub-views are rendered (renderLineSuffix()). +- if (!hasSubViews()) +- OS << EndCodeTD; +-} +- +-void SourceCoverageViewHTML::renderLineCoverageColumn( +- raw_ostream &OS, const LineCoverageStats &Line) { +- std::string Count = ""; +- if (Line.isMapped()) +- Count = tag("pre", formatCount(Line.ExecutionCount)); +- std::string CoverageClass = +- (Line.ExecutionCount > 0) ? "covered-line" : "uncovered-line"; +- OS << tag("td", Count, CoverageClass); +-} +- +-void SourceCoverageViewHTML::renderLineNumberColumn(raw_ostream &OS, +- unsigned LineNo) { +- OS << tag("td", tag("pre", utostr(uint64_t(LineNo))), "line-number"); +-} +- +-void SourceCoverageViewHTML::renderRegionMarkers(raw_ostream &, +- CoverageSegmentArray, +- unsigned) { +- // Region markers are rendered in-line using tooltips. +-} +- +-void SourceCoverageViewHTML::renderExpansionSite( +- raw_ostream &OS, LineRef L, const coverage::CoverageSegment *WrappedSegment, +- CoverageSegmentArray Segments, unsigned ExpansionCol, unsigned ViewDepth) { +- // Render the line containing the expansion site. No extra formatting needed. +- renderLine(OS, L, WrappedSegment, Segments, ExpansionCol, ViewDepth); +-} +- +-void SourceCoverageViewHTML::renderExpansionView(raw_ostream &OS, +- ExpansionView &ESV, +- unsigned ViewDepth) { +- OS << BeginExpansionDiv; +- ESV.View->print(OS, /*WholeFile=*/false, /*ShowSourceName=*/false, +- ViewDepth + 1); +- OS << EndExpansionDiv; +-} +- +-void SourceCoverageViewHTML::renderInstantiationView(raw_ostream &OS, +- InstantiationView &ISV, +- unsigned ViewDepth) { +- OS << BeginExpansionDiv; +- ISV.View->print(OS, /*WholeFile=*/false, /*ShowSourceName=*/true, ViewDepth); +- OS << EndExpansionDiv; +-} +diff --git a/tools/llvm-cov/SourceCoverageViewHTML.h b/tools/llvm-cov/SourceCoverageViewHTML.h +deleted file mode 100644 +index 50ecf2b..0000000 +--- a/tools/llvm-cov/SourceCoverageViewHTML.h ++++ /dev/null +@@ -1,83 +0,0 @@ +-//===- SourceCoverageViewHTML.h - A html code coverage view ---------------===// +-// +-// The LLVM Compiler Infrastructure +-// +-// This file is distributed under the University of Illinois Open Source +-// License. See LICENSE.TXT for details. +-// +-//===----------------------------------------------------------------------===// +-/// +-/// \file This file defines the interface to the html coverage renderer. +-/// +-//===----------------------------------------------------------------------===// +- +-#ifndef LLVM_COV_SOURCECOVERAGEVIEWHTML_H +-#define LLVM_COV_SOURCECOVERAGEVIEWHTML_H +- +-#include "SourceCoverageView.h" +- +-namespace llvm { +- +-/// \brief A coverage printer for html output. +-class CoveragePrinterHTML : public CoveragePrinter { +-public: +- Expected createViewFile(StringRef Path, +- bool InToplevel) override; +- +- void closeViewFile(OwnedStream OS) override; +- +- Error createIndexFile(ArrayRef SourceFiles) override; +- +- CoveragePrinterHTML(const CoverageViewOptions &Opts) +- : CoveragePrinter(Opts) {} +-}; +- +-/// \brief A code coverage view which supports html-based rendering. +-class SourceCoverageViewHTML : public SourceCoverageView { +- void renderViewHeader(raw_ostream &OS) override; +- +- void renderViewFooter(raw_ostream &OS) override; +- +- void renderSourceName(raw_ostream &OS) override; +- +- void renderLinePrefix(raw_ostream &OS, unsigned ViewDepth) override; +- +- void renderLineSuffix(raw_ostream &OS, unsigned ViewDepth) override; +- +- void renderViewDivider(raw_ostream &OS, unsigned ViewDepth) override; +- +- void renderLine(raw_ostream &OS, LineRef L, +- const coverage::CoverageSegment *WrappedSegment, +- CoverageSegmentArray Segments, unsigned ExpansionCol, +- unsigned ViewDepth) override; +- +- void renderExpansionSite(raw_ostream &OS, LineRef L, +- const coverage::CoverageSegment *WrappedSegment, +- CoverageSegmentArray Segments, unsigned ExpansionCol, +- unsigned ViewDepth) override; +- +- void renderExpansionView(raw_ostream &OS, ExpansionView &ESV, +- unsigned ViewDepth) override; +- +- void renderInstantiationView(raw_ostream &OS, InstantiationView &ISV, +- unsigned ViewDepth) override; +- +- void renderLineCoverageColumn(raw_ostream &OS, +- const LineCoverageStats &Line) override; +- +- void renderLineNumberColumn(raw_ostream &OS, unsigned LineNo) override; +- +- void renderRegionMarkers(raw_ostream &OS, CoverageSegmentArray Segments, +- unsigned ViewDepth) override; +- +-public: +- SourceCoverageViewHTML(StringRef SourceName, const MemoryBuffer &File, +- const CoverageViewOptions &Options, +- coverage::CoverageData &&CoverageInfo) +- : SourceCoverageView(SourceName, File, Options, std::move(CoverageInfo)) { +- } +-}; +- +-} // namespace llvm +- +-#endif // LLVM_COV_SOURCECOVERAGEVIEWHTML_H +diff --git a/tools/llvm-cov/SourceCoverageViewText.cpp b/tools/llvm-cov/SourceCoverageViewText.cpp +index ae9d6da..8b13789 100644 +--- a/tools/llvm-cov/SourceCoverageViewText.cpp ++++ b/tools/llvm-cov/SourceCoverageViewText.cpp +@@ -1,213 +1 @@ +-//===- SourceCoverageViewText.cpp - A text-based code coverage view -------===// +-// +-// The LLVM Compiler Infrastructure +-// +-// This file is distributed under the University of Illinois Open Source +-// License. See LICENSE.TXT for details. +-// +-//===----------------------------------------------------------------------===// +-/// +-/// \file This file implements the text-based coverage renderer. +-/// +-//===----------------------------------------------------------------------===// + +-#include "SourceCoverageViewText.h" +-#include "llvm/ADT/Optional.h" +-#include "llvm/ADT/SmallString.h" +-#include "llvm/ADT/StringExtras.h" +- +-using namespace llvm; +- +-Expected +-CoveragePrinterText::createViewFile(StringRef Path, bool InToplevel) { +- return createOutputStream(Path, "txt", InToplevel); +-} +- +-void CoveragePrinterText::closeViewFile(OwnedStream OS) { +- OS->operator<<('\n'); +-} +- +-Error CoveragePrinterText::createIndexFile(ArrayRef SourceFiles) { +- auto OSOrErr = createOutputStream("index", "txt", /*InToplevel=*/true); +- if (Error E = OSOrErr.takeError()) +- return E; +- auto OS = std::move(OSOrErr.get()); +- raw_ostream &OSRef = *OS.get(); +- +- for (StringRef SF : SourceFiles) +- OSRef << getOutputPath(SF, "txt", /*InToplevel=*/false) << '\n'; +- +- return Error::success(); +-} +- +-namespace { +- +-static const unsigned LineCoverageColumnWidth = 7; +-static const unsigned LineNumberColumnWidth = 5; +- +-/// \brief Get the width of the leading columns. +-unsigned getCombinedColumnWidth(const CoverageViewOptions &Opts) { +- return (Opts.ShowLineStats ? LineCoverageColumnWidth + 1 : 0) + +- (Opts.ShowLineNumbers ? LineNumberColumnWidth + 1 : 0); +-} +- +-/// \brief The width of the line that is used to divide between the view and +-/// the subviews. +-unsigned getDividerWidth(const CoverageViewOptions &Opts) { +- return getCombinedColumnWidth(Opts) + 4; +-} +- +-} // anonymous namespace +- +-void SourceCoverageViewText::renderViewHeader(raw_ostream &) {} +- +-void SourceCoverageViewText::renderViewFooter(raw_ostream &) {} +- +-void SourceCoverageViewText::renderSourceName(raw_ostream &OS) { +- getOptions().colored_ostream(OS, raw_ostream::CYAN) << getSourceName() +- << ":\n"; +-} +- +-void SourceCoverageViewText::renderLinePrefix(raw_ostream &OS, +- unsigned ViewDepth) { +- for (unsigned I = 0; I < ViewDepth; ++I) +- OS << " |"; +-} +- +-void SourceCoverageViewText::renderLineSuffix(raw_ostream &, unsigned) {} +- +-void SourceCoverageViewText::renderViewDivider(raw_ostream &OS, +- unsigned ViewDepth) { +- assert(ViewDepth != 0 && "Cannot render divider at top level"); +- renderLinePrefix(OS, ViewDepth - 1); +- OS.indent(2); +- unsigned Length = getDividerWidth(getOptions()); +- for (unsigned I = 0; I < Length; ++I) +- OS << '-'; +- OS << '\n'; +-} +- +-void SourceCoverageViewText::renderLine( +- raw_ostream &OS, LineRef L, +- const coverage::CoverageSegment *WrappedSegment, +- CoverageSegmentArray Segments, unsigned ExpansionCol, unsigned ViewDepth) { +- StringRef Line = L.Line; +- unsigned LineNumber = L.LineNo; +- +- Optional Highlight; +- SmallVector, 2> HighlightedRanges; +- +- // The first segment overlaps from a previous line, so we treat it specially. +- if (WrappedSegment && WrappedSegment->HasCount && WrappedSegment->Count == 0) +- Highlight = raw_ostream::RED; +- +- // Output each segment of the line, possibly highlighted. +- unsigned Col = 1; +- for (const auto *S : Segments) { +- unsigned End = std::min(S->Col, static_cast(Line.size()) + 1); +- colored_ostream(OS, Highlight ? *Highlight : raw_ostream::SAVEDCOLOR, +- getOptions().Colors && Highlight, /*Bold=*/false, +- /*BG=*/true) +- << Line.substr(Col - 1, End - Col); +- if (getOptions().Debug && Highlight) +- HighlightedRanges.push_back(std::make_pair(Col, End)); +- Col = End; +- if (Col == ExpansionCol) +- Highlight = raw_ostream::CYAN; +- else if (S->HasCount && S->Count == 0) +- Highlight = raw_ostream::RED; +- else +- Highlight = None; +- } +- +- // Show the rest of the line. +- colored_ostream(OS, Highlight ? *Highlight : raw_ostream::SAVEDCOLOR, +- getOptions().Colors && Highlight, /*Bold=*/false, /*BG=*/true) +- << Line.substr(Col - 1, Line.size() - Col + 1); +- OS << '\n'; +- +- if (getOptions().Debug) { +- for (const auto &Range : HighlightedRanges) +- errs() << "Highlighted line " << LineNumber << ", " << Range.first +- << " -> " << Range.second << '\n'; +- if (Highlight) +- errs() << "Highlighted line " << LineNumber << ", " << Col << " -> ?\n"; +- } +-} +- +-void SourceCoverageViewText::renderLineCoverageColumn( +- raw_ostream &OS, const LineCoverageStats &Line) { +- if (!Line.isMapped()) { +- OS.indent(LineCoverageColumnWidth) << '|'; +- return; +- } +- std::string C = formatCount(Line.ExecutionCount); +- OS.indent(LineCoverageColumnWidth - C.size()); +- colored_ostream(OS, raw_ostream::MAGENTA, +- Line.hasMultipleRegions() && getOptions().Colors) +- << C; +- OS << '|'; +-} +- +-void SourceCoverageViewText::renderLineNumberColumn(raw_ostream &OS, +- unsigned LineNo) { +- SmallString<32> Buffer; +- raw_svector_ostream BufferOS(Buffer); +- BufferOS << LineNo; +- auto Str = BufferOS.str(); +- // Trim and align to the right. +- Str = Str.substr(0, std::min(Str.size(), (size_t)LineNumberColumnWidth)); +- OS.indent(LineNumberColumnWidth - Str.size()) << Str << '|'; +-} +- +-void SourceCoverageViewText::renderRegionMarkers( +- raw_ostream &OS, CoverageSegmentArray Segments, unsigned ViewDepth) { +- renderLinePrefix(OS, ViewDepth); +- OS.indent(getCombinedColumnWidth(getOptions())); +- +- unsigned PrevColumn = 1; +- for (const auto *S : Segments) { +- if (!S->IsRegionEntry) +- continue; +- // Skip to the new region. +- if (S->Col > PrevColumn) +- OS.indent(S->Col - PrevColumn); +- PrevColumn = S->Col + 1; +- std::string C = formatCount(S->Count); +- PrevColumn += C.size(); +- OS << '^' << C; +- } +- OS << '\n'; +- +- if (getOptions().Debug) +- for (const auto *S : Segments) +- errs() << "Marker at " << S->Line << ":" << S->Col << " = " +- << formatCount(S->Count) << (S->IsRegionEntry ? "\n" : " (pop)\n"); +-} +- +-void SourceCoverageViewText::renderExpansionSite( +- raw_ostream &OS, LineRef L, const coverage::CoverageSegment *WrappedSegment, +- CoverageSegmentArray Segments, unsigned ExpansionCol, unsigned ViewDepth) { +- renderLinePrefix(OS, ViewDepth); +- OS.indent(getCombinedColumnWidth(getOptions()) + (ViewDepth == 0 ? 0 : 1)); +- renderLine(OS, L, WrappedSegment, Segments, ExpansionCol, ViewDepth); +-} +- +-void SourceCoverageViewText::renderExpansionView(raw_ostream &OS, +- ExpansionView &ESV, +- unsigned ViewDepth) { +- // Render the child subview. +- if (getOptions().Debug) +- errs() << "Expansion at line " << ESV.getLine() << ", " << ESV.getStartCol() +- << " -> " << ESV.getEndCol() << '\n'; +- ESV.View->print(OS, /*WholeFile=*/false, /*ShowSourceName=*/false, +- ViewDepth + 1); +-} +- +-void SourceCoverageViewText::renderInstantiationView(raw_ostream &OS, +- InstantiationView &ISV, +- unsigned ViewDepth) { +- renderLinePrefix(OS, ViewDepth); +- OS << ' '; +- ISV.View->print(OS, /*WholeFile=*/false, /*ShowSourceName=*/true, ViewDepth); +-} +diff --git a/tools/llvm-cov/SourceCoverageViewText.h b/tools/llvm-cov/SourceCoverageViewText.h +deleted file mode 100644 +index b233124..0000000 +--- a/tools/llvm-cov/SourceCoverageViewText.h ++++ /dev/null +@@ -1,83 +0,0 @@ +-//===- SourceCoverageViewText.h - A text-based code coverage view ---------===// +-// +-// The LLVM Compiler Infrastructure +-// +-// This file is distributed under the University of Illinois Open Source +-// License. See LICENSE.TXT for details. +-// +-//===----------------------------------------------------------------------===// +-/// +-/// \file This file defines the interface to the text-based coverage renderer. +-/// +-//===----------------------------------------------------------------------===// +- +-#ifndef LLVM_COV_SOURCECOVERAGEVIEWTEXT_H +-#define LLVM_COV_SOURCECOVERAGEVIEWTEXT_H +- +-#include "SourceCoverageView.h" +- +-namespace llvm { +- +-/// \brief A coverage printer for text output. +-class CoveragePrinterText : public CoveragePrinter { +-public: +- Expected createViewFile(StringRef Path, +- bool InToplevel) override; +- +- void closeViewFile(OwnedStream OS) override; +- +- Error createIndexFile(ArrayRef SourceFiles) override; +- +- CoveragePrinterText(const CoverageViewOptions &Opts) +- : CoveragePrinter(Opts) {} +-}; +- +-/// \brief A code coverage view which supports text-based rendering. +-class SourceCoverageViewText : public SourceCoverageView { +- void renderViewHeader(raw_ostream &OS) override; +- +- void renderViewFooter(raw_ostream &OS) override; +- +- void renderSourceName(raw_ostream &OS) override; +- +- void renderLinePrefix(raw_ostream &OS, unsigned ViewDepth) override; +- +- void renderLineSuffix(raw_ostream &OS, unsigned ViewDepth) override; +- +- void renderViewDivider(raw_ostream &OS, unsigned ViewDepth) override; +- +- void renderLine(raw_ostream &OS, LineRef L, +- const coverage::CoverageSegment *WrappedSegment, +- CoverageSegmentArray Segments, unsigned ExpansionCol, +- unsigned ViewDepth) override; +- +- void renderExpansionSite(raw_ostream &OS, LineRef L, +- const coverage::CoverageSegment *WrappedSegment, +- CoverageSegmentArray Segments, unsigned ExpansionCol, +- unsigned ViewDepth) override; +- +- void renderExpansionView(raw_ostream &OS, ExpansionView &ESV, +- unsigned ViewDepth) override; +- +- void renderInstantiationView(raw_ostream &OS, InstantiationView &ISV, +- unsigned ViewDepth) override; +- +- void renderLineCoverageColumn(raw_ostream &OS, +- const LineCoverageStats &Line) override; +- +- void renderLineNumberColumn(raw_ostream &OS, unsigned LineNo) override; +- +- void renderRegionMarkers(raw_ostream &OS, CoverageSegmentArray Segments, +- unsigned ViewDepth) override; +- +-public: +- SourceCoverageViewText(StringRef SourceName, const MemoryBuffer &File, +- const CoverageViewOptions &Options, +- coverage::CoverageData &&CoverageInfo) +- : SourceCoverageView(SourceName, File, Options, std::move(CoverageInfo)) { +- } +-}; +- +-} // namespace llvm +- +-#endif // LLVM_COV_SOURCECOVERAGEVIEWTEXT_H +diff --git a/tools/llvm-cov/TestingSupport.cpp b/tools/llvm-cov/TestingSupport.cpp +index 72768f4..8b13789 100644 +--- a/tools/llvm-cov/TestingSupport.cpp ++++ b/tools/llvm-cov/TestingSupport.cpp +@@ -1,92 +1 @@ +-//===- TestingSupport.cpp - Convert objects files into test files --------===// +-// +-// The LLVM Compiler Infrastructure +-// +-// This file is distributed under the University of Illinois Open Source +-// License. See LICENSE.TXT for details. +-// +-//===----------------------------------------------------------------------===// + +-#include "llvm/Object/ObjectFile.h" +-#include "llvm/ProfileData/InstrProf.h" +-#include "llvm/Support/CommandLine.h" +-#include "llvm/Support/LEB128.h" +-#include "llvm/Support/raw_ostream.h" +-#include +-#include +- +-using namespace llvm; +-using namespace object; +- +-int convertForTestingMain(int argc, const char *argv[]) { +- cl::opt InputSourceFile(cl::Positional, cl::Required, +- cl::desc("")); +- +- cl::opt OutputFilename( +- "o", cl::Required, +- cl::desc( +- "File with the profile data obtained after an instrumented run")); +- +- cl::ParseCommandLineOptions(argc, argv, "LLVM code coverage tool\n"); +- +- auto ObjErr = llvm::object::ObjectFile::createObjectFile(InputSourceFile); +- if (!ObjErr) { +- std::string Buf; +- raw_string_ostream OS(Buf); +- logAllUnhandledErrors(ObjErr.takeError(), OS, ""); +- OS.flush(); +- errs() << "error: " << Buf; +- return 1; +- } +- ObjectFile *OF = ObjErr.get().getBinary(); +- auto BytesInAddress = OF->getBytesInAddress(); +- if (BytesInAddress != 8) { +- errs() << "error: 64 bit binary expected\n"; +- return 1; +- } +- +- // Look for the sections that we are interested in. +- int FoundSectionCount = 0; +- SectionRef ProfileNames, CoverageMapping; +- for (const auto &Section : OF->sections()) { +- StringRef Name; +- if (Section.getName(Name)) +- return 1; +- if (Name == llvm::getInstrProfNameSectionName(false)) { +- ProfileNames = Section; +- } else if (Name == llvm::getInstrProfCoverageSectionName(false)) { +- CoverageMapping = Section; +- } else +- continue; +- ++FoundSectionCount; +- } +- if (FoundSectionCount != 2) +- return 1; +- +- // Get the contents of the given sections. +- uint64_t ProfileNamesAddress = ProfileNames.getAddress(); +- StringRef CoverageMappingData; +- StringRef ProfileNamesData; +- if (CoverageMapping.getContents(CoverageMappingData) || +- ProfileNames.getContents(ProfileNamesData)) +- return 1; +- +- int FD; +- if (auto Err = +- sys::fs::openFileForWrite(OutputFilename, FD, sys::fs::F_None)) { +- errs() << "error: " << Err.message() << "\n"; +- return 1; +- } +- +- raw_fd_ostream OS(FD, true); +- OS << "llvmcovmtestdata"; +- encodeULEB128(ProfileNamesData.size(), OS); +- encodeULEB128(ProfileNamesAddress, OS); +- OS << ProfileNamesData; +- // Coverage mapping data is expected to have an alignment of 8. +- for (unsigned Pad = OffsetToAlignment(OS.tell(), 8); Pad; --Pad) +- OS.write(uint8_t(0)); +- OS << CoverageMappingData; +- +- return 0; +-} +diff --git a/tools/llvm-cov/gcov.cpp b/tools/llvm-cov/gcov.cpp +index 4652fed..8b13789 100644 +--- a/tools/llvm-cov/gcov.cpp ++++ b/tools/llvm-cov/gcov.cpp +@@ -1,145 +1 @@ +-//===- gcov.cpp - GCOV compatible LLVM coverage tool ----------------------===// +-// +-// The LLVM Compiler Infrastructure +-// +-// This file is distributed under the University of Illinois Open Source +-// License. See LICENSE.TXT for details. +-// +-//===----------------------------------------------------------------------===// +-// +-// llvm-cov is a command line tools to analyze and report coverage information. +-// +-//===----------------------------------------------------------------------===// + +-#include "llvm/ADT/SmallString.h" +-#include "llvm/Support/CommandLine.h" +-#include "llvm/Support/Errc.h" +-#include "llvm/Support/FileSystem.h" +-#include "llvm/Support/GCOV.h" +-#include "llvm/Support/Path.h" +-#include +-using namespace llvm; +- +-static void reportCoverage(StringRef SourceFile, StringRef ObjectDir, +- const std::string &InputGCNO, +- const std::string &InputGCDA, bool DumpGCOV, +- const GCOV::Options &Options) { +- SmallString<128> CoverageFileStem(ObjectDir); +- if (CoverageFileStem.empty()) { +- // If no directory was specified with -o, look next to the source file. +- CoverageFileStem = sys::path::parent_path(SourceFile); +- sys::path::append(CoverageFileStem, sys::path::stem(SourceFile)); +- } else if (sys::fs::is_directory(ObjectDir)) +- // A directory name was given. Use it and the source file name. +- sys::path::append(CoverageFileStem, sys::path::stem(SourceFile)); +- else +- // A file was given. Ignore the source file and look next to this file. +- sys::path::replace_extension(CoverageFileStem, ""); +- +- std::string GCNO = InputGCNO.empty() +- ? std::string(CoverageFileStem.str()) + ".gcno" +- : InputGCNO; +- std::string GCDA = InputGCDA.empty() +- ? std::string(CoverageFileStem.str()) + ".gcda" +- : InputGCDA; +- GCOVFile GF; +- +- ErrorOr> GCNO_Buff = +- MemoryBuffer::getFileOrSTDIN(GCNO); +- if (std::error_code EC = GCNO_Buff.getError()) { +- errs() << GCNO << ": " << EC.message() << "\n"; +- return; +- } +- GCOVBuffer GCNO_GB(GCNO_Buff.get().get()); +- if (!GF.readGCNO(GCNO_GB)) { +- errs() << "Invalid .gcno File!\n"; +- return; +- } +- +- ErrorOr> GCDA_Buff = +- MemoryBuffer::getFileOrSTDIN(GCDA); +- if (std::error_code EC = GCDA_Buff.getError()) { +- if (EC != errc::no_such_file_or_directory) { +- errs() << GCDA << ": " << EC.message() << "\n"; +- return; +- } +- // Clear the filename to make it clear we didn't read anything. +- GCDA = "-"; +- } else { +- GCOVBuffer GCDA_GB(GCDA_Buff.get().get()); +- if (!GF.readGCDA(GCDA_GB)) { +- errs() << "Invalid .gcda File!\n"; +- return; +- } +- } +- +- if (DumpGCOV) +- GF.dump(); +- +- FileInfo FI(Options); +- GF.collectLineCounts(FI); +- FI.print(llvm::outs(), SourceFile, GCNO, GCDA); +-} +- +-int gcovMain(int argc, const char *argv[]) { +- cl::list SourceFiles(cl::Positional, cl::OneOrMore, +- cl::desc("SOURCEFILE")); +- +- cl::opt AllBlocks("a", cl::Grouping, cl::init(false), +- cl::desc("Display all basic blocks")); +- cl::alias AllBlocksA("all-blocks", cl::aliasopt(AllBlocks)); +- +- cl::opt BranchProb("b", cl::Grouping, cl::init(false), +- cl::desc("Display branch probabilities")); +- cl::alias BranchProbA("branch-probabilities", cl::aliasopt(BranchProb)); +- +- cl::opt BranchCount("c", cl::Grouping, cl::init(false), +- cl::desc("Display branch counts instead " +- "of percentages (requires -b)")); +- cl::alias BranchCountA("branch-counts", cl::aliasopt(BranchCount)); +- +- cl::opt LongNames("l", cl::Grouping, cl::init(false), +- cl::desc("Prefix filenames with the main file")); +- cl::alias LongNamesA("long-file-names", cl::aliasopt(LongNames)); +- +- cl::opt FuncSummary("f", cl::Grouping, cl::init(false), +- cl::desc("Show coverage for each function")); +- cl::alias FuncSummaryA("function-summaries", cl::aliasopt(FuncSummary)); +- +- cl::opt NoOutput("n", cl::Grouping, cl::init(false), +- cl::desc("Do not output any .gcov files")); +- cl::alias NoOutputA("no-output", cl::aliasopt(NoOutput)); +- +- cl::opt ObjectDir( +- "o", cl::value_desc("DIR|FILE"), cl::init(""), +- cl::desc("Find objects in DIR or based on FILE's path")); +- cl::alias ObjectDirA("object-directory", cl::aliasopt(ObjectDir)); +- cl::alias ObjectDirB("object-file", cl::aliasopt(ObjectDir)); +- +- cl::opt PreservePaths("p", cl::Grouping, cl::init(false), +- cl::desc("Preserve path components")); +- cl::alias PreservePathsA("preserve-paths", cl::aliasopt(PreservePaths)); +- +- cl::opt UncondBranch("u", cl::Grouping, cl::init(false), +- cl::desc("Display unconditional branch info " +- "(requires -b)")); +- cl::alias UncondBranchA("unconditional-branches", cl::aliasopt(UncondBranch)); +- +- cl::OptionCategory DebugCat("Internal and debugging options"); +- cl::opt DumpGCOV("dump", cl::init(false), cl::cat(DebugCat), +- cl::desc("Dump the gcov file to stderr")); +- cl::opt InputGCNO("gcno", cl::cat(DebugCat), cl::init(""), +- cl::desc("Override inferred gcno file")); +- cl::opt InputGCDA("gcda", cl::cat(DebugCat), cl::init(""), +- cl::desc("Override inferred gcda file")); +- +- cl::ParseCommandLineOptions(argc, argv, "LLVM code coverage tool\n"); +- +- GCOV::Options Options(AllBlocks, BranchProb, BranchCount, FuncSummary, +- PreservePaths, UncondBranch, LongNames, NoOutput); +- +- for (const auto &SourceFile : SourceFiles) +- reportCoverage(SourceFile, ObjectDir, InputGCNO, InputGCDA, DumpGCOV, +- Options); +- return 0; +-} +diff --git a/tools/llvm-cov/llvm-cov.cpp b/tools/llvm-cov/llvm-cov.cpp +index ba60cd9..aa1f228 100644 +--- a/tools/llvm-cov/llvm-cov.cpp ++++ b/tools/llvm-cov/llvm-cov.cpp +@@ -10,85 +10,6 @@ + // llvm-cov is a command line tools to analyze and report coverage information. + // + //===----------------------------------------------------------------------===// +- +-#include "llvm/ADT/StringRef.h" +-#include "llvm/ADT/StringSwitch.h" +-#include "llvm/Support/CommandLine.h" +-#include "llvm/Support/ManagedStatic.h" +-#include "llvm/Support/Path.h" +-#include "llvm/Support/PrettyStackTrace.h" +-#include "llvm/Support/Process.h" +-#include "llvm/Support/Signals.h" +-#include "llvm/Support/raw_ostream.h" +-#include +- +-using namespace llvm; +- +-/// \brief The main entry point for the 'show' subcommand. +-int showMain(int argc, const char *argv[]); +- +-/// \brief The main entry point for the 'report' subcommand. +-int reportMain(int argc, const char *argv[]); +- +-/// \brief The main entry point for the 'convert-for-testing' subcommand. +-int convertForTestingMain(int argc, const char *argv[]); +- +-/// \brief The main entry point for the gcov compatible coverage tool. +-int gcovMain(int argc, const char *argv[]); +- +-/// \brief Top level help. +-static int helpMain(int argc, const char *argv[]) { +- errs() << "Usage: llvm-cov {gcov|report|show} [OPTION]...\n\n" +- << "Shows code coverage information.\n\n" +- << "Subcommands:\n" +- << " gcov: Work with the gcov format.\n" +- << " show: Annotate source files using instrprof style coverage.\n" +- << " report: Summarize instrprof style coverage information.\n"; +- return 0; +-} +- +-/// \brief Top level version information. +-static int versionMain(int argc, const char *argv[]) { +- cl::PrintVersionMessage(); +- return 0; +-} +- + int main(int argc, const char **argv) { +- // Print a stack trace if we signal out. +- sys::PrintStackTraceOnErrorSignal(argv[0]); +- PrettyStackTraceProgram X(argc, argv); +- llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. +- +- // If argv[0] is or ends with 'gcov', always be gcov compatible +- if (sys::path::stem(argv[0]).endswith_lower("gcov")) +- return gcovMain(argc, argv); +- +- // Check if we are invoking a specific tool command. +- if (argc > 1) { +- typedef int (*MainFunction)(int, const char *[]); +- MainFunction Func = StringSwitch(argv[1]) +- .Case("convert-for-testing", convertForTestingMain) +- .Case("gcov", gcovMain) +- .Case("report", reportMain) +- .Case("show", showMain) +- .Cases("-h", "-help", "--help", helpMain) +- .Cases("-version", "--version", versionMain) +- .Default(nullptr); +- +- if (Func) { +- std::string Invocation = std::string(argv[0]) + " " + argv[1]; +- argv[1] = Invocation.c_str(); +- return Func(argc - 1, argv + 1); +- } +- } +- +- if (argc > 1) { +- if (sys::Process::StandardErrHasColors()) +- errs().changeColor(raw_ostream::RED); +- errs() << "Unrecognized command: " << argv[1] << ".\n\n"; +- if (sys::Process::StandardErrHasColors()) +- errs().resetColor(); +- } +- helpMain(argc, argv); + return 1; + } +diff --git a/tools/sancov/sancov.cc b/tools/sancov/sancov.cc +index 55b0370..c869a73 100644 +--- a/tools/sancov/sancov.cc ++++ b/tools/sancov/sancov.cc +@@ -10,1249 +10,7 @@ + // This file is a command-line tool for reading and analyzing sanitizer + // coverage. + //===----------------------------------------------------------------------===// +-#include "llvm/ADT/STLExtras.h" +-#include "llvm/ADT/Twine.h" +-#include "llvm/DebugInfo/Symbolize/Symbolize.h" +-#include "llvm/MC/MCAsmInfo.h" +-#include "llvm/MC/MCContext.h" +-#include "llvm/MC/MCDisassembler/MCDisassembler.h" +-#include "llvm/MC/MCInst.h" +-#include "llvm/MC/MCInstPrinter.h" +-#include "llvm/MC/MCInstrAnalysis.h" +-#include "llvm/MC/MCInstrInfo.h" +-#include "llvm/MC/MCObjectFileInfo.h" +-#include "llvm/MC/MCRegisterInfo.h" +-#include "llvm/MC/MCSubtargetInfo.h" +-#include "llvm/Object/Archive.h" +-#include "llvm/Object/Binary.h" +-#include "llvm/Object/ELFObjectFile.h" +-#include "llvm/Object/ObjectFile.h" +-#include "llvm/Support/Casting.h" +-#include "llvm/Support/CommandLine.h" +-#include "llvm/Support/Errc.h" +-#include "llvm/Support/ErrorOr.h" +-#include "llvm/Support/FileSystem.h" +-#include "llvm/Support/LineIterator.h" +-#include "llvm/Support/MD5.h" +-#include "llvm/Support/ManagedStatic.h" +-#include "llvm/Support/MemoryBuffer.h" +-#include "llvm/Support/Path.h" +-#include "llvm/Support/PrettyStackTrace.h" +-#include "llvm/Support/Regex.h" +-#include "llvm/Support/Signals.h" +-#include "llvm/Support/SpecialCaseList.h" +-#include "llvm/Support/TargetRegistry.h" +-#include "llvm/Support/TargetSelect.h" +-#include "llvm/Support/ToolOutputFile.h" +-#include "llvm/Support/raw_ostream.h" +- +-#include +-#include +-#include +-#include +-#include +-#include +- +-using namespace llvm; +- +-namespace { +- +-// --------- COMMAND LINE FLAGS --------- +- +-enum ActionType { +- PrintAction, +- PrintCovPointsAction, +- CoveredFunctionsAction, +- NotCoveredFunctionsAction, +- HtmlReportAction, +- StatsAction +-}; +- +-cl::opt Action( +- cl::desc("Action (required)"), cl::Required, +- cl::values(clEnumValN(PrintAction, "print", "Print coverage addresses"), +- clEnumValN(PrintCovPointsAction, "print-coverage-pcs", +- "Print coverage instrumentation points addresses."), +- clEnumValN(CoveredFunctionsAction, "covered-functions", +- "Print all covered funcions."), +- clEnumValN(NotCoveredFunctionsAction, "not-covered-functions", +- "Print all not covered funcions."), +- clEnumValN(HtmlReportAction, "html-report", +- "Print HTML coverage report."), +- clEnumValN(StatsAction, "print-coverage-stats", +- "Print coverage statistics."), +- clEnumValEnd)); +- +-static cl::list +- ClInputFiles(cl::Positional, cl::OneOrMore, +- cl::desc("(|<.sancov file>)...")); +- +-static cl::opt ClDemangle("demangle", cl::init(true), +- cl::desc("Print demangled function name.")); +- +-static cl::opt ClStripPathPrefix( +- "strip_path_prefix", cl::init(""), +- cl::desc("Strip this prefix from file paths in reports.")); +- +-static cl::opt +- ClBlacklist("blacklist", cl::init(""), +- cl::desc("Blacklist file (sanitizer blacklist format).")); +- +-static cl::opt ClUseDefaultBlacklist( +- "use_default_blacklist", cl::init(true), cl::Hidden, +- cl::desc("Controls if default blacklist should be used.")); +- +-static const char *const DefaultBlacklistStr = "fun:__sanitizer_.*\n" +- "src:/usr/include/.*\n" +- "src:.*/libc\\+\\+/.*\n"; +- +-// --------- FORMAT SPECIFICATION --------- +- +-struct FileHeader { +- uint32_t Bitness; +- uint32_t Magic; +-}; +- +-static const uint32_t BinCoverageMagic = 0xC0BFFFFF; +-static const uint32_t Bitness32 = 0xFFFFFF32; +-static const uint32_t Bitness64 = 0xFFFFFF64; +- +-// --------- ERROR HANDLING --------- +- +-static void Fail(const llvm::Twine &E) { +- errs() << "Error: " << E << "\n"; +- exit(1); +-} +- +-static void FailIfError(std::error_code Error) { +- if (!Error) +- return; +- errs() << "Error: " << Error.message() << "(" << Error.value() << ")\n"; +- exit(1); +-} +- +-template static void FailIfError(const ErrorOr &E) { +- FailIfError(E.getError()); +-} +- +-static void FailIfError(Error Err) { +- if (Err) { +- logAllUnhandledErrors(std::move(Err), errs(), "Error: "); +- exit(1); +- } +-} +- +-template static void FailIfError(Expected &E) { +- FailIfError(E.takeError()); +-} +- +-static void FailIfNotEmpty(const llvm::Twine &E) { +- if (E.str().empty()) +- return; +- Fail(E); +-} +- +-template +-static void FailIfEmpty(const std::unique_ptr &Ptr, +- const std::string &Message) { +- if (Ptr.get()) +- return; +- Fail(Message); +-} +- +-// --------- +- +-// Produces std::map> grouping input +-// elements by FuncTy result. +-template +-static inline auto group_by(const RangeTy &R, FuncTy F) +- -> std::map::type, +- std::vector::type>> { +- std::map::type, +- std::vector::type>> +- Result; +- for (const auto &E : R) { +- Result[F(E)].push_back(E); +- } +- return Result; +-} +- +-template +-static void readInts(const char *Start, const char *End, +- std::set *Ints) { +- const T *S = reinterpret_cast(Start); +- const T *E = reinterpret_cast(End); +- std::copy(S, E, std::inserter(*Ints, Ints->end())); +-} +- +-struct FileLoc { +- bool operator<(const FileLoc &RHS) const { +- return std::tie(FileName, Line) < std::tie(RHS.FileName, RHS.Line); +- } +- +- std::string FileName; +- uint32_t Line; +-}; +- +-struct FileFn { +- bool operator<(const FileFn &RHS) const { +- return std::tie(FileName, FunctionName) < +- std::tie(RHS.FileName, RHS.FunctionName); +- } +- +- std::string FileName; +- std::string FunctionName; +-}; +- +-struct FnLoc { +- bool operator<(const FnLoc &RHS) const { +- return std::tie(Loc, FunctionName) < std::tie(RHS.Loc, RHS.FunctionName); +- } +- +- FileLoc Loc; +- std::string FunctionName; +-}; +- +-std::string stripPathPrefix(std::string Path) { +- if (ClStripPathPrefix.empty()) +- return Path; +- size_t Pos = Path.find(ClStripPathPrefix); +- if (Pos == std::string::npos) +- return Path; +- return Path.substr(Pos + ClStripPathPrefix.size()); +-} +- +-static std::unique_ptr createSymbolizer() { +- symbolize::LLVMSymbolizer::Options SymbolizerOptions; +- SymbolizerOptions.Demangle = ClDemangle; +- SymbolizerOptions.UseSymbolTable = true; +- return std::unique_ptr( +- new symbolize::LLVMSymbolizer(SymbolizerOptions)); +-} +- +-// A DILineInfo with address. +-struct AddrInfo : public DILineInfo { +- uint64_t Addr; +- +- AddrInfo(const DILineInfo &DI, uint64_t Addr) : DILineInfo(DI), Addr(Addr) { +- FileName = normalizeFilename(FileName); +- } +- +-private: +- static std::string normalizeFilename(const std::string &FileName) { +- SmallString<256> S(FileName); +- sys::path::remove_dots(S, /* remove_dot_dot */ true); +- return S.str().str(); +- } +-}; +- +-class Blacklists { +-public: +- Blacklists() +- : DefaultBlacklist(createDefaultBlacklist()), +- UserBlacklist(createUserBlacklist()) {} +- +- // AddrInfo contains normalized filename. It is important to check it rather +- // than DILineInfo. +- bool isBlacklisted(const AddrInfo &AI) { +- if (DefaultBlacklist && DefaultBlacklist->inSection("fun", AI.FunctionName)) +- return true; +- if (DefaultBlacklist && DefaultBlacklist->inSection("src", AI.FileName)) +- return true; +- if (UserBlacklist && UserBlacklist->inSection("fun", AI.FunctionName)) +- return true; +- if (UserBlacklist && UserBlacklist->inSection("src", AI.FileName)) +- return true; +- return false; +- } +- +-private: +- static std::unique_ptr createDefaultBlacklist() { +- if (!ClUseDefaultBlacklist) +- return std::unique_ptr(); +- std::unique_ptr MB = +- MemoryBuffer::getMemBuffer(DefaultBlacklistStr); +- std::string Error; +- auto Blacklist = SpecialCaseList::create(MB.get(), Error); +- FailIfNotEmpty(Error); +- return Blacklist; +- } +- +- static std::unique_ptr createUserBlacklist() { +- if (ClBlacklist.empty()) +- return std::unique_ptr(); +- +- return SpecialCaseList::createOrDie({{ClBlacklist}}); +- } +- std::unique_ptr DefaultBlacklist; +- std::unique_ptr UserBlacklist; +-}; +- +-// Collect all debug info for given addresses. +-static std::vector getAddrInfo(const std::string &ObjectFile, +- const std::set &Addrs, +- bool InlinedCode) { +- std::vector Result; +- auto Symbolizer(createSymbolizer()); +- Blacklists B; +- +- for (auto Addr : Addrs) { +- auto LineInfo = Symbolizer->symbolizeCode(ObjectFile, Addr); +- FailIfError(LineInfo); +- auto LineAddrInfo = AddrInfo(*LineInfo, Addr); +- if (B.isBlacklisted(LineAddrInfo)) +- continue; +- Result.push_back(LineAddrInfo); +- if (InlinedCode) { +- auto InliningInfo = Symbolizer->symbolizeInlinedCode(ObjectFile, Addr); +- FailIfError(InliningInfo); +- for (uint32_t I = 0; I < InliningInfo->getNumberOfFrames(); ++I) { +- auto FrameInfo = InliningInfo->getFrame(I); +- auto FrameAddrInfo = AddrInfo(FrameInfo, Addr); +- if (B.isBlacklisted(FrameAddrInfo)) +- continue; +- Result.push_back(FrameAddrInfo); +- } +- } +- } +- +- return Result; +-} +- +-// Locate __sanitizer_cov* function addresses that are used for coverage +-// reporting. +-static std::set +-findSanitizerCovFunctions(const object::ObjectFile &O) { +- std::set Result; +- +- for (const object::SymbolRef &Symbol : O.symbols()) { +- Expected AddressOrErr = Symbol.getAddress(); +- FailIfError(errorToErrorCode(AddressOrErr.takeError())); +- +- Expected NameOrErr = Symbol.getName(); +- FailIfError(errorToErrorCode(NameOrErr.takeError())); +- StringRef Name = NameOrErr.get(); +- +- if (Name == "__sanitizer_cov" || Name == "__sanitizer_cov_with_check" || +- Name == "__sanitizer_cov_trace_func_enter") { +- if (!(Symbol.getFlags() & object::BasicSymbolRef::SF_Undefined)) +- Result.insert(AddressOrErr.get()); +- } +- } +- +- return Result; +-} +- +-// Locate addresses of all coverage points in a file. Coverage point +-// is defined as the 'address of instruction following __sanitizer_cov +-// call - 1'. +-static void getObjectCoveragePoints(const object::ObjectFile &O, +- std::set *Addrs) { +- Triple TheTriple("unknown-unknown-unknown"); +- TheTriple.setArch(Triple::ArchType(O.getArch())); +- auto TripleName = TheTriple.getTriple(); +- +- std::string Error; +- const Target *TheTarget = TargetRegistry::lookupTarget(TripleName, Error); +- FailIfNotEmpty(Error); +- +- std::unique_ptr STI( +- TheTarget->createMCSubtargetInfo(TripleName, "", "")); +- FailIfEmpty(STI, "no subtarget info for target " + TripleName); +- +- std::unique_ptr MRI( +- TheTarget->createMCRegInfo(TripleName)); +- FailIfEmpty(MRI, "no register info for target " + TripleName); +- +- std::unique_ptr AsmInfo( +- TheTarget->createMCAsmInfo(*MRI, TripleName)); +- FailIfEmpty(AsmInfo, "no asm info for target " + TripleName); +- +- std::unique_ptr MOFI(new MCObjectFileInfo); +- MCContext Ctx(AsmInfo.get(), MRI.get(), MOFI.get()); +- std::unique_ptr DisAsm( +- TheTarget->createMCDisassembler(*STI, Ctx)); +- FailIfEmpty(DisAsm, "no disassembler info for target " + TripleName); +- +- std::unique_ptr MII(TheTarget->createMCInstrInfo()); +- FailIfEmpty(MII, "no instruction info for target " + TripleName); +- +- std::unique_ptr MIA( +- TheTarget->createMCInstrAnalysis(MII.get())); +- FailIfEmpty(MIA, "no instruction analysis info for target " + TripleName); +- +- auto SanCovAddrs = findSanitizerCovFunctions(O); +- if (SanCovAddrs.empty()) +- Fail("__sanitizer_cov* functions not found"); +- +- for (object::SectionRef Section : O.sections()) { +- if (Section.isVirtual() || !Section.isText()) // llvm-objdump does the same. +- continue; +- uint64_t SectionAddr = Section.getAddress(); +- uint64_t SectSize = Section.getSize(); +- if (!SectSize) +- continue; +- +- StringRef BytesStr; +- FailIfError(Section.getContents(BytesStr)); +- ArrayRef Bytes(reinterpret_cast(BytesStr.data()), +- BytesStr.size()); +- +- for (uint64_t Index = 0, Size = 0; Index < Section.getSize(); +- Index += Size) { +- MCInst Inst; +- if (!DisAsm->getInstruction(Inst, Size, Bytes.slice(Index), +- SectionAddr + Index, nulls(), nulls())) { +- if (Size == 0) +- Size = 1; +- continue; +- } +- uint64_t Addr = Index + SectionAddr; +- // Sanitizer coverage uses the address of the next instruction - 1. +- uint64_t CovPoint = Addr + Size - 1; +- uint64_t Target; +- if (MIA->isCall(Inst) && +- MIA->evaluateBranch(Inst, SectionAddr + Index, Size, Target) && +- SanCovAddrs.find(Target) != SanCovAddrs.end()) +- Addrs->insert(CovPoint); +- } +- } +-} +- +-static void +-visitObjectFiles(const object::Archive &A, +- function_ref Fn) { +- Error Err; +- for (auto &C : A.children(Err)) { +- Expected> ChildOrErr = C.getAsBinary(); +- FailIfError(errorToErrorCode(ChildOrErr.takeError())); +- if (auto *O = dyn_cast(&*ChildOrErr.get())) +- Fn(*O); +- else +- FailIfError(object::object_error::invalid_file_type); +- } +- FailIfError(std::move(Err)); +-} +- +-static void +-visitObjectFiles(const std::string &FileName, +- function_ref Fn) { +- Expected> BinaryOrErr = +- object::createBinary(FileName); +- if (!BinaryOrErr) +- FailIfError(errorToErrorCode(BinaryOrErr.takeError())); +- +- object::Binary &Binary = *BinaryOrErr.get().getBinary(); +- if (object::Archive *A = dyn_cast(&Binary)) +- visitObjectFiles(*A, Fn); +- else if (object::ObjectFile *O = dyn_cast(&Binary)) +- Fn(*O); +- else +- FailIfError(object::object_error::invalid_file_type); +-} +- +-std::set findSanitizerCovFunctions(const std::string &FileName) { +- std::set Result; +- visitObjectFiles(FileName, [&](const object::ObjectFile &O) { +- auto Addrs = findSanitizerCovFunctions(O); +- Result.insert(Addrs.begin(), Addrs.end()); +- }); +- return Result; +-} +- +-// Locate addresses of all coverage points in a file. Coverage point +-// is defined as the 'address of instruction following __sanitizer_cov +-// call - 1'. +-std::set getCoveragePoints(const std::string &FileName) { +- std::set Result; +- visitObjectFiles(FileName, [&](const object::ObjectFile &O) { +- getObjectCoveragePoints(O, &Result); +- }); +- return Result; +-} +- +-static void printCovPoints(const std::string &ObjFile, raw_ostream &OS) { +- for (uint64_t Addr : getCoveragePoints(ObjFile)) { +- OS << "0x"; +- OS.write_hex(Addr); +- OS << "\n"; +- } +-} +- +-static std::string escapeHtml(const std::string &S) { +- std::string Result; +- Result.reserve(S.size()); +- for (char Ch : S) { +- switch (Ch) { +- case '&': +- Result.append("&"); +- break; +- case '\'': +- Result.append("'"); +- break; +- case '"': +- Result.append("""); +- break; +- case '<': +- Result.append("<"); +- break; +- case '>': +- Result.append(">"); +- break; +- default: +- Result.push_back(Ch); +- break; +- } +- } +- return Result; +-} +- +-// Adds leading zeroes wrapped in 'lz' style. +-// Leading zeroes help locate 000% coverage. +-static std::string formatHtmlPct(size_t Pct) { +- Pct = std::max(std::size_t{0}, std::min(std::size_t{100}, Pct)); +- +- std::string Num = std::to_string(Pct); +- std::string Zeroes(3 - Num.size(), '0'); +- if (!Zeroes.empty()) +- Zeroes = "" + Zeroes + ""; +- +- return Zeroes + Num; +-} +- +-static std::string anchorName(const std::string &Anchor) { +- llvm::MD5 Hasher; +- llvm::MD5::MD5Result Hash; +- Hasher.update(Anchor); +- Hasher.final(Hash); +- +- SmallString<32> HexString; +- llvm::MD5::stringifyResult(Hash, HexString); +- return HexString.str().str(); +-} +- +-static ErrorOr isCoverageFile(const std::string &FileName) { +- ErrorOr> BufOrErr = +- MemoryBuffer::getFile(FileName); +- if (!BufOrErr) { +- errs() << "Warning: " << BufOrErr.getError().message() << "(" +- << BufOrErr.getError().value() +- << "), filename: " << llvm::sys::path::filename(FileName) << "\n"; +- return BufOrErr.getError(); +- } +- std::unique_ptr Buf = std::move(BufOrErr.get()); +- if (Buf->getBufferSize() < 8) { +- return false; +- } +- const FileHeader *Header = +- reinterpret_cast(Buf->getBufferStart()); +- return Header->Magic == BinCoverageMagic; +-} +- +-struct CoverageStats { +- CoverageStats() : AllPoints(0), CovPoints(0), AllFns(0), CovFns(0) {} +- +- size_t AllPoints; +- size_t CovPoints; +- size_t AllFns; +- size_t CovFns; +-}; +- +-static raw_ostream &operator<<(raw_ostream &OS, const CoverageStats &Stats) { +- OS << "all-edges: " << Stats.AllPoints << "\n"; +- OS << "cov-edges: " << Stats.CovPoints << "\n"; +- OS << "all-functions: " << Stats.AllFns << "\n"; +- OS << "cov-functions: " << Stats.CovFns << "\n"; +- return OS; +-} +- +-class CoverageData { +-public: +- // Read single file coverage data. +- static ErrorOr> +- read(const std::string &FileName) { +- ErrorOr> BufOrErr = +- MemoryBuffer::getFile(FileName); +- if (!BufOrErr) +- return BufOrErr.getError(); +- std::unique_ptr Buf = std::move(BufOrErr.get()); +- if (Buf->getBufferSize() < 8) { +- errs() << "File too small (<8): " << Buf->getBufferSize(); +- return make_error_code(errc::illegal_byte_sequence); +- } +- const FileHeader *Header = +- reinterpret_cast(Buf->getBufferStart()); +- +- if (Header->Magic != BinCoverageMagic) { +- errs() << "Wrong magic: " << Header->Magic; +- return make_error_code(errc::illegal_byte_sequence); +- } +- +- auto Addrs = llvm::make_unique>(); +- +- switch (Header->Bitness) { +- case Bitness64: +- readInts(Buf->getBufferStart() + 8, Buf->getBufferEnd(), +- Addrs.get()); +- break; +- case Bitness32: +- readInts(Buf->getBufferStart() + 8, Buf->getBufferEnd(), +- Addrs.get()); +- break; +- default: +- errs() << "Unsupported bitness: " << Header->Bitness; +- return make_error_code(errc::illegal_byte_sequence); +- } +- +- return std::unique_ptr(new CoverageData(std::move(Addrs))); +- } +- +- // Merge multiple coverage data together. +- static std::unique_ptr +- merge(const std::vector> &Covs) { +- auto Addrs = llvm::make_unique>(); +- +- for (const auto &Cov : Covs) +- Addrs->insert(Cov->Addrs->begin(), Cov->Addrs->end()); +- +- return std::unique_ptr(new CoverageData(std::move(Addrs))); +- } +- +- // Read list of files and merges their coverage info. +- static ErrorOr> +- readAndMerge(const std::vector &FileNames) { +- std::vector> Covs; +- for (const auto &FileName : FileNames) { +- auto Cov = read(FileName); +- if (!Cov) +- return Cov.getError(); +- Covs.push_back(std::move(Cov.get())); +- } +- return merge(Covs); +- } +- +- // Print coverage addresses. +- void printAddrs(raw_ostream &OS) { +- for (auto Addr : *Addrs) { +- OS << "0x"; +- OS.write_hex(Addr); +- OS << "\n"; +- } +- } +- +-protected: +- explicit CoverageData(std::unique_ptr> Addrs) +- : Addrs(std::move(Addrs)) {} +- +- friend class CoverageDataWithObjectFile; +- +- std::unique_ptr> Addrs; +-}; +- +-// Coverage data translated into source code line-level information. +-// Fetches debug info in constructor and calculates various information per +-// request. +-class SourceCoverageData { +-public: +- enum LineStatus { +- // coverage information for the line is not available. +- // default value in maps. +- UNKNOWN = 0, +- // the line is fully covered. +- COVERED = 1, +- // the line is fully uncovered. +- NOT_COVERED = 2, +- // some points in the line a covered, some are not. +- MIXED = 3 +- }; +- +- SourceCoverageData(std::string ObjectFile, const std::set &Addrs) +- : AllCovPoints(getCoveragePoints(ObjectFile)) { +- if (!std::includes(AllCovPoints.begin(), AllCovPoints.end(), Addrs.begin(), +- Addrs.end())) { +- Fail("Coverage points in binary and .sancov file do not match."); +- } +- +- AllAddrInfo = getAddrInfo(ObjectFile, AllCovPoints, true); +- CovAddrInfo = getAddrInfo(ObjectFile, Addrs, true); +- } +- +- // Compute number of coverage points hit/total in a file. +- // file_name -> +- std::map> computeFileCoverage() { +- std::map> FileCoverage; +- auto AllCovPointsByFile = +- group_by(AllAddrInfo, [](const AddrInfo &AI) { return AI.FileName; }); +- auto CovPointsByFile = +- group_by(CovAddrInfo, [](const AddrInfo &AI) { return AI.FileName; }); +- +- for (const auto &P : AllCovPointsByFile) { +- const std::string &FileName = P.first; +- +- FileCoverage[FileName] = +- std::make_pair(CovPointsByFile[FileName].size(), +- AllCovPointsByFile[FileName].size()); +- } +- return FileCoverage; +- } +- +- // line_number -> line_status. +- typedef std::map LineStatusMap; +- // file_name -> LineStatusMap +- typedef std::map FileLineStatusMap; +- +- // fills in the {file_name -> {line_no -> status}} map. +- FileLineStatusMap computeLineStatusMap() { +- FileLineStatusMap StatusMap; +- +- auto AllLocs = group_by(AllAddrInfo, [](const AddrInfo &AI) { +- return FileLoc{AI.FileName, AI.Line}; +- }); +- auto CovLocs = group_by(CovAddrInfo, [](const AddrInfo &AI) { +- return FileLoc{AI.FileName, AI.Line}; +- }); +- +- for (const auto &P : AllLocs) { +- const FileLoc &Loc = P.first; +- auto I = CovLocs.find(Loc); +- +- if (I == CovLocs.end()) { +- StatusMap[Loc.FileName][Loc.Line] = NOT_COVERED; +- } else { +- StatusMap[Loc.FileName][Loc.Line] = +- (I->second.size() == P.second.size()) ? COVERED : MIXED; +- } +- } +- return StatusMap; +- } +- +- std::set computeAllFunctions() const { +- std::set Fns; +- for (const auto &AI : AllAddrInfo) { +- Fns.insert(FileFn{AI.FileName, AI.FunctionName}); +- } +- return Fns; +- } +- +- std::set computeCoveredFunctions() const { +- std::set Fns; +- auto CovFns = group_by(CovAddrInfo, [](const AddrInfo &AI) { +- return FileFn{AI.FileName, AI.FunctionName}; +- }); +- +- for (const auto &P : CovFns) { +- Fns.insert(P.first); +- } +- return Fns; +- } +- +- std::set computeNotCoveredFunctions() const { +- std::set Fns; +- +- auto AllFns = group_by(AllAddrInfo, [](const AddrInfo &AI) { +- return FileFn{AI.FileName, AI.FunctionName}; +- }); +- auto CovFns = group_by(CovAddrInfo, [](const AddrInfo &AI) { +- return FileFn{AI.FileName, AI.FunctionName}; +- }); +- +- for (const auto &P : AllFns) { +- if (CovFns.find(P.first) == CovFns.end()) { +- Fns.insert(P.first); +- } +- } +- return Fns; +- } +- +- // Compute % coverage for each function. +- std::map computeFunctionsCoverage() const { +- std::map FnCoverage; +- auto AllFns = group_by(AllAddrInfo, [](const AddrInfo &AI) { +- return FileFn{AI.FileName, AI.FunctionName}; +- }); +- +- auto CovFns = group_by(CovAddrInfo, [](const AddrInfo &AI) { +- return FileFn{AI.FileName, AI.FunctionName}; +- }); +- +- for (const auto &P : AllFns) { +- FileFn F = P.first; +- FnCoverage[F] = CovFns[F].size() * 100 / P.second.size(); +- } +- +- return FnCoverage; +- } +- +- typedef std::map> FunctionLocs; +- // finds first line number in a file for each function. +- FunctionLocs resolveFunctions(const std::set &Fns) const { +- std::vector FnAddrs; +- for (const auto &AI : AllAddrInfo) { +- if (Fns.find(FileFn{AI.FileName, AI.FunctionName}) != Fns.end()) +- FnAddrs.push_back(AI); +- } +- +- auto GroupedAddrs = group_by(FnAddrs, [](const AddrInfo &AI) { +- return FnLoc{FileLoc{AI.FileName, AI.Line}, AI.FunctionName}; +- }); +- +- FunctionLocs Result; +- std::string LastFileName; +- std::set ProcessedFunctions; +- +- for (const auto &P : GroupedAddrs) { +- const FnLoc &Loc = P.first; +- std::string FileName = Loc.Loc.FileName; +- std::string FunctionName = Loc.FunctionName; +- +- if (LastFileName != FileName) +- ProcessedFunctions.clear(); +- LastFileName = FileName; +- +- if (!ProcessedFunctions.insert(FunctionName).second) +- continue; +- +- auto FLoc = FileLoc{FileName, Loc.Loc.Line}; +- Result[FLoc].insert(FunctionName); +- } +- return Result; +- } +- +- std::set files() const { +- std::set Files; +- for (const auto &AI : AllAddrInfo) { +- Files.insert(AI.FileName); +- } +- return Files; +- } +- +- void collectStats(CoverageStats *Stats) const { +- Stats->AllPoints += AllCovPoints.size(); +- Stats->AllFns += computeAllFunctions().size(); +- Stats->CovFns += computeCoveredFunctions().size(); +- } +- +-private: +- const std::set AllCovPoints; +- +- std::vector AllAddrInfo; +- std::vector CovAddrInfo; +-}; +- +-static void printFunctionLocs(const SourceCoverageData::FunctionLocs &FnLocs, +- raw_ostream &OS) { +- for (const auto &Fns : FnLocs) { +- for (const auto &Fn : Fns.second) { +- OS << stripPathPrefix(Fns.first.FileName) << ":" << Fns.first.Line << " " +- << Fn << "\n"; +- } +- } +-} +- +-// Holder for coverage data + filename of corresponding object file. +-class CoverageDataWithObjectFile : public CoverageData { +-public: +- static ErrorOr> +- readAndMerge(const std::string &ObjectFile, +- const std::vector &FileNames) { +- auto MergedDataOrError = CoverageData::readAndMerge(FileNames); +- if (!MergedDataOrError) +- return MergedDataOrError.getError(); +- return std::unique_ptr( +- new CoverageDataWithObjectFile(ObjectFile, +- std::move(MergedDataOrError.get()))); +- } +- +- std::string object_file() const { return ObjectFile; } +- +- // Print list of covered functions. +- // Line format: : +- void printCoveredFunctions(raw_ostream &OS) const { +- SourceCoverageData SCovData(ObjectFile, *Addrs); +- auto CoveredFns = SCovData.computeCoveredFunctions(); +- printFunctionLocs(SCovData.resolveFunctions(CoveredFns), OS); +- } +- +- // Print list of not covered functions. +- // Line format: : +- void printNotCoveredFunctions(raw_ostream &OS) const { +- SourceCoverageData SCovData(ObjectFile, *Addrs); +- auto NotCoveredFns = SCovData.computeNotCoveredFunctions(); +- printFunctionLocs(SCovData.resolveFunctions(NotCoveredFns), OS); +- } +- +- void printReport(raw_ostream &OS) const { +- SourceCoverageData SCovData(ObjectFile, *Addrs); +- auto LineStatusMap = SCovData.computeLineStatusMap(); +- +- std::set AllFns = SCovData.computeAllFunctions(); +- // file_loc -> set[function_name] +- auto AllFnsByLoc = SCovData.resolveFunctions(AllFns); +- auto FileCoverage = SCovData.computeFileCoverage(); +- +- auto FnCoverage = SCovData.computeFunctionsCoverage(); +- auto FnCoverageByFile = +- group_by(FnCoverage, [](const std::pair &FileFn) { +- return FileFn.first.FileName; +- }); +- +- // TOC +- +- size_t NotCoveredFilesCount = 0; +- std::set Files = SCovData.files(); +- +- // Covered Files. +- OS << "
Touched Files\n"; +- OS << "\n"; +- OS << ""; +- OS << "\n"; +- for (const auto &FileName : Files) { +- std::pair FC = FileCoverage[FileName]; +- if (FC.first == 0) { +- NotCoveredFilesCount++; +- continue; +- } +- size_t CovPct = FC.second == 0 ? 100 : 100 * FC.first / FC.second; +- +- OS << "" +- << "" +- << "\n"; +- } +- OS << "
FileCoverage %Hit (Total) Fns
" +- << stripPathPrefix(FileName) << "" << formatHtmlPct(CovPct) << "%" << FC.first << " (" << FC.second << ")" +- << "
\n"; +- OS << "
\n"; +- +- // Not covered files. +- if (NotCoveredFilesCount) { +- OS << "
Not Touched Files\n"; +- OS << "\n"; +- for (const auto &FileName : Files) { +- std::pair FC = FileCoverage[FileName]; +- if (FC.first == 0) +- OS << "\n"; +- } +- OS << "
" << stripPathPrefix(FileName) << "
\n"; +- OS << "
\n"; +- } else { +- OS << "

Congratulations! All source files are touched.

\n"; +- } +- +- // Source +- for (const auto &FileName : Files) { +- std::pair FC = FileCoverage[FileName]; +- if (FC.first == 0) +- continue; +- OS << "\n"; +- OS << "

" << stripPathPrefix(FileName) << "

\n"; +- OS << "
Function Coverage"; +- OS << "
\n"; +- +- auto &FileFnCoverage = FnCoverageByFile[FileName]; +- +- for (const auto &P : FileFnCoverage) { +- std::string FunctionName = P.first.FunctionName; +- +- OS << "
"; +- OS << "" << formatHtmlPct(P.second) +- << "% "; +- OS << ""; +- OS << escapeHtml(FunctionName) << ""; +- OS << "
\n"; +- } +- OS << "
\n"; +- +- ErrorOr> BufOrErr = +- MemoryBuffer::getFile(FileName); +- if (!BufOrErr) { +- OS << "Error reading file: " << FileName << " : " +- << BufOrErr.getError().message() << "(" +- << BufOrErr.getError().value() << ")\n"; +- continue; +- } +- +- OS << "
\n";
+-      const auto &LineStatuses = LineStatusMap[FileName];
+-      for (line_iterator I = line_iterator(*BufOrErr.get(), false);
+-           !I.is_at_eof(); ++I) {
+-        uint32_t Line = I.line_number();
+-        { // generate anchors (if any);
+-          FileLoc Loc = FileLoc{FileName, Line};
+-          auto It = AllFnsByLoc.find(Loc);
+-          if (It != AllFnsByLoc.end()) {
+-            for (const std::string &Fn : It->second) {
+-              OS << "";
+-            };
+-          }
+-        }
+-
+-        OS << "second
+-                                                  : SourceCoverageData::UNKNOWN;
+-        switch (Status) {
+-        case SourceCoverageData::UNKNOWN:
+-          OS << "class=unknown";
+-          break;
+-        case SourceCoverageData::COVERED:
+-          OS << "class=covered";
+-          break;
+-        case SourceCoverageData::NOT_COVERED:
+-          OS << "class=notcovered";
+-          break;
+-        case SourceCoverageData::MIXED:
+-          OS << "class=mixed";
+-          break;
+-        }
+-        OS << ">";
+-        OS << escapeHtml(*I) << "\n";
+-      }
+-      OS << "
\n"; +- } +- } +- +- void collectStats(CoverageStats *Stats) const { +- Stats->CovPoints += Addrs->size(); +- +- SourceCoverageData SCovData(ObjectFile, *Addrs); +- SCovData.collectStats(Stats); +- } +- +-private: +- CoverageDataWithObjectFile(std::string ObjectFile, +- std::unique_ptr Coverage) +- : CoverageData(std::move(Coverage->Addrs)), +- ObjectFile(std::move(ObjectFile)) {} +- const std::string ObjectFile; +-}; +- +-// Multiple coverage files data organized by object file. +-class CoverageDataSet { +-public: +- static ErrorOr> +- readCmdArguments(std::vector FileNames) { +- // Short name => file name. +- std::map ObjFiles; +- std::string FirstObjFile; +- std::set CovFiles; +- +- // Partition input values into coverage/object files. +- for (const auto &FileName : FileNames) { +- auto ErrorOrIsCoverage = isCoverageFile(FileName); +- if (!ErrorOrIsCoverage) +- continue; +- if (ErrorOrIsCoverage.get()) { +- CovFiles.insert(FileName); +- } else { +- auto ShortFileName = llvm::sys::path::filename(FileName); +- if (ObjFiles.find(ShortFileName) != ObjFiles.end()) { +- Fail("Duplicate binary file with a short name: " + ShortFileName); +- } +- +- ObjFiles[ShortFileName] = FileName; +- if (FirstObjFile.empty()) +- FirstObjFile = FileName; +- } +- } +- +- Regex SancovRegex("(.*)\\.[0-9]+\\.sancov"); +- SmallVector Components; +- +- // Object file => list of corresponding coverage file names. +- auto CoverageByObjFile = group_by(CovFiles, [&](std::string FileName) { +- auto ShortFileName = llvm::sys::path::filename(FileName); +- auto Ok = SancovRegex.match(ShortFileName, &Components); +- if (!Ok) { +- Fail("Can't match coverage file name against " +- "..sancov pattern: " + +- FileName); +- } +- +- auto Iter = ObjFiles.find(Components[1]); +- if (Iter == ObjFiles.end()) { +- Fail("Object file for coverage not found: " + FileName); +- } +- return Iter->second; +- }); +- +- // Read coverage. +- std::vector> MergedCoverage; +- for (const auto &Pair : CoverageByObjFile) { +- if (findSanitizerCovFunctions(Pair.first).empty()) { +- for (const auto &FileName : Pair.second) { +- CovFiles.erase(FileName); +- } +- +- errs() +- << "Ignoring " << Pair.first +- << " and its coverage because __sanitizer_cov* functions were not " +- "found.\n"; +- continue; +- } +- +- auto DataOrError = +- CoverageDataWithObjectFile::readAndMerge(Pair.first, Pair.second); +- FailIfError(DataOrError); +- MergedCoverage.push_back(std::move(DataOrError.get())); +- } +- +- return std::unique_ptr( +- new CoverageDataSet(FirstObjFile, &MergedCoverage, CovFiles)); +- } +- +- void printCoveredFunctions(raw_ostream &OS) const { +- for (const auto &Cov : Coverage) { +- Cov->printCoveredFunctions(OS); +- } +- } +- +- void printNotCoveredFunctions(raw_ostream &OS) const { +- for (const auto &Cov : Coverage) { +- Cov->printNotCoveredFunctions(OS); +- } +- } +- +- void printStats(raw_ostream &OS) const { +- CoverageStats Stats; +- for (const auto &Cov : Coverage) { +- Cov->collectStats(&Stats); +- } +- OS << Stats; +- } +- +- void printReport(raw_ostream &OS) const { +- auto Title = +- (llvm::sys::path::filename(MainObjFile) + " Coverage Report").str(); +- +- OS << "\n"; +- OS << "\n"; +- +- // Stylesheet +- OS << "\n"; +- OS << "" << Title << "\n"; +- OS << "\n"; +- OS << "\n"; +- +- // Title +- OS << "

" << Title << "

\n"; +- +- // Modules TOC. +- if (Coverage.size() > 1) { +- for (const auto &CovData : Coverage) { +- OS << "
  • object_file()) +- << "\">" << llvm::sys::path::filename(CovData->object_file()) +- << "
  • \n"; +- } +- } +- +- for (const auto &CovData : Coverage) { +- if (Coverage.size() > 1) { +- OS << "

    " << llvm::sys::path::filename(CovData->object_file()) +- << "

    \n"; +- } +- OS << "object_file()) +- << "\">\n"; +- CovData->printReport(OS); +- } +- +- // About +- OS << "
    About\n"; +- OS << "Coverage files:
      "; +- for (const auto &InputFile : CoverageFiles) { +- llvm::sys::fs::file_status Status; +- llvm::sys::fs::status(InputFile, Status); +- OS << "
    • " << stripPathPrefix(InputFile) << " (" +- << Status.getLastModificationTime().str() << ")
    • \n"; +- } +- OS << "
    \n"; +- +- OS << "\n"; +- OS << "\n"; +- } +- +- bool empty() const { return Coverage.empty(); } +- +-private: +- explicit CoverageDataSet( +- const std::string &MainObjFile, +- std::vector> *Data, +- const std::set &CoverageFiles) +- : MainObjFile(MainObjFile), CoverageFiles(CoverageFiles) { +- Data->swap(this->Coverage); +- } +- +- const std::string MainObjFile; +- std::vector> Coverage; +- const std::set CoverageFiles; +-}; +- +-} // namespace + + int main(int argc, char **argv) { +- // Print stack trace if we signal out. +- sys::PrintStackTraceOnErrorSignal(argv[0]); +- PrettyStackTraceProgram X(argc, argv); +- llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. +- +- llvm::InitializeAllTargetInfos(); +- llvm::InitializeAllTargetMCs(); +- llvm::InitializeAllDisassemblers(); +- +- cl::ParseCommandLineOptions(argc, argv, "Sanitizer Coverage Processing Tool"); +- +- // -print doesn't need object files. +- if (Action == PrintAction) { +- auto CovData = CoverageData::readAndMerge(ClInputFiles); +- FailIfError(CovData); +- CovData.get()->printAddrs(outs()); +- return 0; +- } else if (Action == PrintCovPointsAction) { +- // -print-coverage-points doesn't need coverage files. +- for (const std::string &ObjFile : ClInputFiles) { +- printCovPoints(ObjFile, outs()); +- } +- return 0; +- } +- +- auto CovDataSet = CoverageDataSet::readCmdArguments(ClInputFiles); +- FailIfError(CovDataSet); +- +- if (CovDataSet.get()->empty()) { +- Fail("No coverage files specified."); +- } +- +- switch (Action) { +- case CoveredFunctionsAction: { +- CovDataSet.get()->printCoveredFunctions(outs()); +- return 0; +- } +- case NotCoveredFunctionsAction: { +- CovDataSet.get()->printNotCoveredFunctions(outs()); +- return 0; +- } +- case HtmlReportAction: { +- CovDataSet.get()->printReport(outs()); +- return 0; +- } +- case StatsAction: { +- CovDataSet.get()->printStats(outs()); +- return 0; +- } +- case PrintAction: +- case PrintCovPointsAction: +- llvm_unreachable("unsupported action"); +- } ++ return 0; + } +diff --git a/unittests/Support/ThreadPool.cpp b/unittests/Support/ThreadPool.cpp +index 69a24bc..b185859 100644 +--- a/unittests/Support/ThreadPool.cpp ++++ b/unittests/Support/ThreadPool.cpp +@@ -7,6 +7,8 @@ + // + //===----------------------------------------------------------------------===// + ++#if 0 ++ + #include "llvm/Support/ThreadPool.h" + + #include "llvm/ADT/STLExtras.h" +@@ -166,3 +168,5 @@ TEST_F(ThreadPoolTest, PoolDestruction) { + } + ASSERT_EQ(5, checked_in); + } ++ ++#endif diff --git a/deps/patches/llvm-3.9.0_win64-reloc-dwarf.patch b/deps/patches/llvm-3.9.0_win64-reloc-dwarf.patch new file mode 100644 index 0000000000000..e7908c31a4e78 --- /dev/null +++ b/deps/patches/llvm-3.9.0_win64-reloc-dwarf.patch @@ -0,0 +1,183 @@ +diff --git a/include/llvm/MC/MCStreamer.h b/include/llvm/MC/MCStreamer.h +index cd710ee..7cae156 100644 +--- a/include/llvm/MC/MCStreamer.h ++++ b/include/llvm/MC/MCStreamer.h +@@ -470,7 +470,7 @@ public: + /// \brief Emits a COFF section relative relocation. + /// + /// \param Symbol - Symbol the section relative relocation should point to. +- virtual void EmitCOFFSecRel32(MCSymbol const *Symbol); ++ virtual void EmitCOFFSecRel32(MCSymbol const *Symbol, uint64_t Offset); + + /// \brief Emit an ELF .size directive. + /// +diff --git a/include/llvm/MC/MCWinCOFFStreamer.h b/include/llvm/MC/MCWinCOFFStreamer.h +index fe1ada9..63e44f2 100644 +--- a/include/llvm/MC/MCWinCOFFStreamer.h ++++ b/include/llvm/MC/MCWinCOFFStreamer.h +@@ -52,7 +52,7 @@ public: + void EndCOFFSymbolDef() override; + void EmitCOFFSafeSEH(MCSymbol const *Symbol) override; + void EmitCOFFSectionIndex(MCSymbol const *Symbol) override; +- void EmitCOFFSecRel32(MCSymbol const *Symbol) override; ++ void EmitCOFFSecRel32(MCSymbol const *Symbol, uint64_t Offset) override; + void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlignment) override; + void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, +diff --git a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +index 272bace..9df876f 100644 +--- a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp ++++ b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +@@ -1699,7 +1699,7 @@ void AsmPrinter::EmitLabelPlusOffset(const MCSymbol *Label, uint64_t Offset, + unsigned Size, + bool IsSectionRelative) const { + if (MAI->needsDwarfSectionOffsetDirective() && IsSectionRelative) { +- OutStreamer->EmitCOFFSecRel32(Label); ++ OutStreamer->EmitCOFFSecRel32(Label, Offset); + return; + } + +diff --git a/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp b/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp +index 60f40d0..1ff4e6e 100644 +--- a/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp ++++ b/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp +@@ -150,7 +150,7 @@ void AsmPrinter::emitDwarfSymbolReference(const MCSymbol *Label, + if (!ForceOffset) { + // On COFF targets, we have to emit the special .secrel32 directive. + if (MAI->needsDwarfSectionOffsetDirective()) { +- OutStreamer->EmitCOFFSecRel32(Label); ++ OutStreamer->EmitCOFFSecRel32(Label, /*Offset=*/0); + return; + } + +diff --git a/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp b/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp +index ebf80de..13cba28 100644 +--- a/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp ++++ b/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp +@@ -667,7 +667,7 @@ void CodeViewDebug::emitDebugInfoForFunction(const Function *GV, + OS.AddComment("Function type index"); + OS.EmitIntValue(getFuncIdForSubprogram(GV->getSubprogram()).getIndex(), 4); + OS.AddComment("Function section relative address"); +- OS.EmitCOFFSecRel32(Fn); ++ OS.EmitCOFFSecRel32(Fn, /*Offset=*/0); + OS.AddComment("Function section index"); + OS.EmitCOFFSectionIndex(Fn); + OS.AddComment("Flags"); +@@ -2066,7 +2066,7 @@ void CodeViewDebug::emitDebugInfoForGlobal(const DIGlobalVariable *DIGV, + OS.AddComment("Type"); + OS.EmitIntValue(getCompleteTypeIndex(DIGV->getType()).getIndex(), 4); + OS.AddComment("DataOffset"); +- OS.EmitCOFFSecRel32(GVSym); ++ OS.EmitCOFFSecRel32(GVSym, /*Offset=*/0); + OS.AddComment("Segment"); + OS.EmitCOFFSectionIndex(GVSym); + OS.AddComment("Name"); +diff --git a/lib/CodeGen/AsmPrinter/DIE.cpp b/lib/CodeGen/AsmPrinter/DIE.cpp +index 2aaa85a..6b625ca 100644 +--- a/lib/CodeGen/AsmPrinter/DIE.cpp ++++ b/lib/CodeGen/AsmPrinter/DIE.cpp +@@ -454,7 +454,7 @@ void DIEEntry::EmitValue(const AsmPrinter *AP, dwarf::Form Form) const { + Addr += CU->getDebugInfoOffset(); + if (AP->MAI->doesDwarfUseRelocationsAcrossSections()) + AP->EmitLabelPlusOffset(CU->getSectionSym(), Addr, +- DIEEntry::getRefAddrSize(AP)); ++ DIEEntry::getRefAddrSize(AP), true); + else + AP->OutStreamer->EmitIntValue(Addr, DIEEntry::getRefAddrSize(AP)); + } else +diff --git a/lib/MC/MCAsmStreamer.cpp b/lib/MC/MCAsmStreamer.cpp +index ef2f781..00419ac 100644 +--- a/lib/MC/MCAsmStreamer.cpp ++++ b/lib/MC/MCAsmStreamer.cpp +@@ -149,7 +149,7 @@ public: + void EndCOFFSymbolDef() override; + void EmitCOFFSafeSEH(MCSymbol const *Symbol) override; + void EmitCOFFSectionIndex(MCSymbol const *Symbol) override; +- void EmitCOFFSecRel32(MCSymbol const *Symbol) override; ++ void EmitCOFFSecRel32(MCSymbol const *Symbol, uint64_t Offset) override; + void emitELFSize(MCSymbolELF *Symbol, const MCExpr *Value) override; + void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlignment) override; +@@ -602,7 +602,7 @@ void MCAsmStreamer::EmitCOFFSectionIndex(MCSymbol const *Symbol) { + EmitEOL(); + } + +-void MCAsmStreamer::EmitCOFFSecRel32(MCSymbol const *Symbol) { ++void MCAsmStreamer::EmitCOFFSecRel32(MCSymbol const *Symbol, uint64_t Offset) { + OS << "\t.secrel32\t"; + Symbol->print(OS, MAI); + EmitEOL(); +diff --git a/lib/MC/MCCodeView.cpp b/lib/MC/MCCodeView.cpp +index 65cff41..5dab392 100644 +--- a/lib/MC/MCCodeView.cpp ++++ b/lib/MC/MCCodeView.cpp +@@ -156,7 +156,7 @@ void CodeViewContext::emitLineTableForFunction(MCObjectStreamer &OS, + OS.EmitIntValue(unsigned(ModuleSubstreamKind::Lines), 4); + OS.emitAbsoluteSymbolDiff(LineEnd, LineBegin, 4); + OS.EmitLabel(LineBegin); +- OS.EmitCOFFSecRel32(FuncBegin); ++ OS.EmitCOFFSecRel32(FuncBegin, /*Offset=*/0); + OS.EmitCOFFSectionIndex(FuncBegin); + + // Actual line info. +diff --git a/lib/MC/MCParser/COFFAsmParser.cpp b/lib/MC/MCParser/COFFAsmParser.cpp +index 653627a..f717f05 100644 +--- a/lib/MC/MCParser/COFFAsmParser.cpp ++++ b/lib/MC/MCParser/COFFAsmParser.cpp +@@ -450,7 +450,7 @@ bool COFFAsmParser::ParseDirectiveSecRel32(StringRef, SMLoc) { + MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID); + + Lex(); +- getStreamer().EmitCOFFSecRel32(Symbol); ++ getStreamer().EmitCOFFSecRel32(Symbol, /*Offset=*/0); + return false; + } + +diff --git a/lib/MC/MCStreamer.cpp b/lib/MC/MCStreamer.cpp +index 6c8828f..9927473 100644 +--- a/lib/MC/MCStreamer.cpp ++++ b/lib/MC/MCStreamer.cpp +@@ -124,7 +124,7 @@ void MCStreamer::EmitSymbolValue(const MCSymbol *Sym, unsigned Size, + if (!IsSectionRelative) + EmitValueImpl(MCSymbolRefExpr::create(Sym, getContext()), Size); + else +- EmitCOFFSecRel32(Sym); ++ EmitCOFFSecRel32(Sym, /*Offset=*/0); + } + + void MCStreamer::EmitGPRel64Value(const MCExpr *Value) { +@@ -647,7 +647,7 @@ void MCStreamer::EmitCOFFSafeSEH(MCSymbol const *Symbol) { + void MCStreamer::EmitCOFFSectionIndex(MCSymbol const *Symbol) { + } + +-void MCStreamer::EmitCOFFSecRel32(MCSymbol const *Symbol) { ++void MCStreamer::EmitCOFFSecRel32(MCSymbol const *Symbol, uint64_t Offset) { + } + + /// EmitRawText - If this file is backed by an assembly streamer, this dumps +diff --git a/lib/MC/WinCOFFStreamer.cpp b/lib/MC/WinCOFFStreamer.cpp +index 5c6407e..1444394 100644 +--- a/lib/MC/WinCOFFStreamer.cpp ++++ b/lib/MC/WinCOFFStreamer.cpp +@@ -195,11 +195,18 @@ void MCWinCOFFStreamer::EmitCOFFSectionIndex(MCSymbol const *Symbol) { + DF->getContents().resize(DF->getContents().size() + 2, 0); + } + +-void MCWinCOFFStreamer::EmitCOFFSecRel32(MCSymbol const *Symbol) { ++void MCWinCOFFStreamer::EmitCOFFSecRel32(MCSymbol const *Symbol, uint64_t Offset) { + MCDataFragment *DF = getOrCreateDataFragment(); +- const MCSymbolRefExpr *SRE = MCSymbolRefExpr::create(Symbol, getContext()); +- MCFixup Fixup = MCFixup::create(DF->getContents().size(), SRE, FK_SecRel_4); ++ // Create Symbol A for the relocation relative reference. ++ const MCExpr *MCE = MCSymbolRefExpr::create(Symbol, getContext()); ++ // Add the constant offset, if given ++ if (Offset) ++ MCE = MCBinaryExpr::createAdd(MCE, MCConstantExpr::create(Offset, getContext()), getContext()); ++ // Build the secrel32 relocation. ++ MCFixup Fixup = MCFixup::create(DF->getContents().size(), MCE, FK_SecRel_4); ++ // Record the relocation. + DF->getFixups().push_back(Fixup); ++ // Emit 4 bytes (zeros) to the object file. + DF->getContents().resize(DF->getContents().size() + 4, 0); + } + diff --git a/deps/patches/llvm-4.0.0-D37576-NVPTX-sm_70.patch b/deps/patches/llvm-4.0.0-D37576-NVPTX-sm_70.patch new file mode 100644 index 0000000000000..9fee1f36e2a95 --- /dev/null +++ b/deps/patches/llvm-4.0.0-D37576-NVPTX-sm_70.patch @@ -0,0 +1,62 @@ +From 4059d374ce981827223ab6b1dae7af4ec5f8e74a Mon Sep 17 00:00:00 2001 +From: Artem Belevich +Date: Thu, 7 Sep 2017 18:14:32 +0000 +Subject: [PATCH] [CUDA] Added rudimentary support for CUDA-9 and sm_70. + +For now CUDA-9 is not included in the list of CUDA versions clang +searches for, so the path to CUDA-9 must be explicitly passed +via --cuda-path=. + +On LLVM side NVPTX added sm_70 GPU type which bumps required +PTX version to 6.0, but otherwise is equivalent to sm_62 at the moment. + +Differential Revision: https://reviews.llvm.org/D37576 + +git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@312734 91177308-0d34-0410-b5e6-96231b3b80d8 +--- + lib/Target/NVPTX/NVPTX.td | 5 +++++ + test/CodeGen/NVPTX/sm-version-70.ll | 5 +++++ + 2 files changed, 10 insertions(+) + create mode 100644 test/CodeGen/NVPTX/sm-version-70.ll + +diff --git a/lib/Target/NVPTX/NVPTX.td b/lib/Target/NVPTX/NVPTX.td +index c77ddbc9978..aba37d36359 100644 +--- a/lib/Target/NVPTX/NVPTX.td ++++ b/lib/Target/NVPTX/NVPTX.td +@@ -50,6 +50,8 @@ def SM61 : SubtargetFeature<"sm_61", "SmVersion", "61", + "Target SM 6.1">; + def SM62 : SubtargetFeature<"sm_62", "SmVersion", "62", + "Target SM 6.2">; ++def SM70 : SubtargetFeature<"sm_70", "SmVersion", "70", ++ "Target SM 7.0">; + + def SATOM : SubtargetFeature<"satom", "HasAtomScope", "true", + "Atomic operations with scope">; +@@ -67,6 +69,8 @@ def PTX43 : SubtargetFeature<"ptx43", "PTXVersion", "43", + "Use PTX version 4.3">; + def PTX50 : SubtargetFeature<"ptx50", "PTXVersion", "50", + "Use PTX version 5.0">; ++def PTX60 : SubtargetFeature<"ptx60", "PTXVersion", "60", ++ "Use PTX version 6.0">; + + //===----------------------------------------------------------------------===// + // NVPTX supported processors. +@@ -87,6 +91,7 @@ def : Proc<"sm_53", [SM53, PTX42]>; + def : Proc<"sm_60", [SM60, PTX50, SATOM]>; + def : Proc<"sm_61", [SM61, PTX50, SATOM]>; + def : Proc<"sm_62", [SM62, PTX50, SATOM]>; ++def : Proc<"sm_70", [SM70, PTX60, SATOM]>; + + def NVPTXInstrInfo : InstrInfo { + } +diff --git a/test/CodeGen/NVPTX/sm-version-70.ll b/test/CodeGen/NVPTX/sm-version-70.ll +new file mode 100644 +index 00000000000..8b72d50747a +--- /dev/null ++++ b/test/CodeGen/NVPTX/sm-version-70.ll +@@ -0,0 +1,5 @@ ++; RUN: llc < %s -march=nvptx -mcpu=sm_70 | FileCheck %s ++; RUN: llc < %s -march=nvptx64 -mcpu=sm_70 | FileCheck %s ++ ++; CHECK: .version 6.0 ++; CHECK: .target sm_70 diff --git a/deps/patches/llvm-4.0.0_threads.patch b/deps/patches/llvm-4.0.0_threads.patch new file mode 100644 index 0000000000000..d3ed7ee7931b9 --- /dev/null +++ b/deps/patches/llvm-4.0.0_threads.patch @@ -0,0 +1,2032 @@ +From dfead72dc82a76a62433c4f0ed2262407ef51bf0 Mon Sep 17 00:00:00 2001 +From: Alex Crichton +Date: Thu, 28 Jan 2016 20:44:50 -0800 +Subject: [PATCH] Don't compile usage of std::thread + +As of the time of this writing it's not actually used anywhere meaningfullly +throughout the LLVM repo that we need, and it unfortunately uses `std::thread` +which isn't available in mingw-w64 toolchains with the win32 threading model +(the one that we use). + +The change made to achive this was to just always use the single-threaded +support in `include/llvm/Support/thread.h`, and hopefuly that'll be enough... + +For reference, the upstream LLVM bug has been reported [1] + +[1]: https://llvm.org/bugs/show_bug.cgi?id=26365 +--- + include/llvm/Support/ThreadPool.h | 4 + + include/llvm/Support/thread.h | 2 +- + lib/CodeGen/ParallelCG.cpp | 2 + + lib/LTO/LTO.cpp | 6 +- + lib/LTO/LTOBackend.cpp | 2 + + lib/LTO/ThinLTOCodeGenerator.cpp | 6 +- + lib/Support/ThreadPool.cpp | 6 +- + test/CMakeLists.txt | 1 - + tools/lli/CMakeLists.txt | 4 - + tools/lli/ChildTarget/CMakeLists.txt | 13 -- + tools/lli/ChildTarget/ChildTarget.cpp | 67 ------- + tools/lli/ChildTarget/LLVMBuild.txt | 21 --- + tools/lli/LLVMBuild.txt | 3 - + tools/lli/OrcLazyJIT.cpp | 3 +- + tools/lli/OrcLazyJIT.h | 175 ------------------ + tools/lli/RemoteJITUtils.h | 153 ---------------- + tools/lli/lli.cpp | 7 + + tools/llvm-cov/CodeCoverage.cpp | 4 + + tools/llvm-cov/CoverageExporterJson.cpp | 2 + + tools/llvm-cov/CoverageFilters.cpp | 2 + + tools/llvm-cov/CoverageFilters.h | 127 ------------- + tools/llvm-cov/CoverageReport.cpp | 2 + + tools/llvm-cov/CoverageReport.h | 51 ------ + tools/llvm-cov/CoverageSummaryInfo.cpp | 2 + + tools/llvm-cov/CoverageSummaryInfo.h | 165 ----------------- + tools/llvm-cov/CoverageViewOptions.h | 68 ------- + tools/llvm-cov/RenderingSupport.h | 61 ------- + tools/llvm-cov/SourceCoverageView.cpp | 2 + + tools/llvm-cov/SourceCoverageView.h | 289 ------------------------------ + tools/llvm-cov/SourceCoverageViewHTML.cpp | 3 + + tools/llvm-cov/SourceCoverageViewHTML.h | 96 ---------- + tools/llvm-cov/SourceCoverageViewText.cpp | 3 + + tools/llvm-cov/SourceCoverageViewText.h | 89 --------- + tools/llvm-cov/TestingSupport.cpp | 2 + + tools/llvm-cov/gcov.cpp | 2 + + tools/llvm-cov/llvm-cov.cpp | 4 + + tools/llvm-profdata/llvm-profdata.cpp | 5 + + tools/sancov/sancov.cc | 5 + + unittests/Support/ThreadPool.cpp | 4 + + 39 files changed, 73 insertions(+), 1390 deletions(-) + delete mode 100644 tools/lli/ChildTarget/CMakeLists.txt + delete mode 100644 tools/lli/ChildTarget/ChildTarget.cpp + delete mode 100644 tools/lli/ChildTarget/LLVMBuild.txt + delete mode 100644 tools/lli/OrcLazyJIT.h + delete mode 100644 tools/lli/RemoteJITUtils.h + delete mode 100644 tools/llvm-cov/CoverageFilters.h + delete mode 100644 tools/llvm-cov/CoverageReport.h + delete mode 100644 tools/llvm-cov/CoverageSummaryInfo.h + delete mode 100644 tools/llvm-cov/CoverageViewOptions.h + delete mode 100644 tools/llvm-cov/RenderingSupport.h + delete mode 100644 tools/llvm-cov/SourceCoverageView.h + delete mode 100644 tools/llvm-cov/SourceCoverageViewHTML.h + delete mode 100644 tools/llvm-cov/SourceCoverageViewText.h + +diff --git a/include/llvm/Support/ThreadPool.h b/include/llvm/Support/ThreadPool.h +index 665cec2465b..c3aa64de8cc 100644 +--- a/include/llvm/Support/ThreadPool.h ++++ b/include/llvm/Support/ThreadPool.h +@@ -16,6 +16,8 @@ + + #include "llvm/Support/thread.h" + ++# if 0 ++ + #ifdef _MSC_VER + // concrt.h depends on eh.h for __uncaught_exception declaration + // even if we disable exceptions. +@@ -134,4 +136,6 @@ private: + }; + } + ++# endif ++ + #endif // LLVM_SUPPORT_THREAD_POOL_H +diff --git a/include/llvm/Support/thread.h b/include/llvm/Support/thread.h +index 9c45418df55..27d42d23f61 100644 +--- a/include/llvm/Support/thread.h ++++ b/include/llvm/Support/thread.h +@@ -19,7 +19,7 @@ + + #include "llvm/Config/llvm-config.h" + +-#if LLVM_ENABLE_THREADS ++#if LLVM_ENABLE_THREADS && 0 + + #ifdef _MSC_VER + // concrt.h depends on eh.h for __uncaught_exception declaration +diff --git a/lib/CodeGen/ParallelCG.cpp b/lib/CodeGen/ParallelCG.cpp +index 50dd44fa659..e91898e0fa7 100644 +--- a/lib/CodeGen/ParallelCG.cpp ++++ b/lib/CodeGen/ParallelCG.cpp +@@ -50,6 +50,7 @@ std::unique_ptr llvm::splitCodeGen( + return M; + } + ++#if 0 + // Create ThreadPool in nested scope so that threads will be joined + // on destruction. + { +@@ -96,5 +97,6 @@ std::unique_ptr llvm::splitCodeGen( + PreserveLocals); + } + ++#endif + return {}; + } +diff --git a/lib/LTO/LTO.cpp b/lib/LTO/LTO.cpp +index e3e2f9f806c..530946c03bb 100644 +--- a/lib/LTO/LTO.cpp ++++ b/lib/LTO/LTO.cpp +@@ -630,7 +630,6 @@ public: + + namespace { + class InProcessThinBackend : public ThinBackendProc { +- ThreadPool BackendThreadPool; + AddStreamFn AddStream; + NativeObjectCache Cache; + +@@ -644,7 +643,6 @@ public: + const StringMap &ModuleToDefinedGVSummaries, + AddStreamFn AddStream, NativeObjectCache Cache) + : ThinBackendProc(Conf, CombinedIndex, ModuleToDefinedGVSummaries), +- BackendThreadPool(ThinLTOParallelismLevel), + AddStream(std::move(AddStream)), Cache(std::move(Cache)) {} + + Error runThinLTOBackendThread( +@@ -690,6 +688,7 @@ public: + const FunctionImporter::ExportSetTy &ExportList, + const std::map &ResolvedODR, + MapVector &ModuleMap) override { ++#if 0 + StringRef ModulePath = BM.getModuleIdentifier(); + assert(ModuleToDefinedGVSummaries.count(ModulePath)); + const GVSummaryMapTy &DefinedGlobals = +@@ -716,11 +715,14 @@ public: + BM, std::ref(CombinedIndex), std::ref(ImportList), + std::ref(ExportList), std::ref(ResolvedODR), std::ref(DefinedGlobals), + std::ref(ModuleMap)); ++#endif + return Error::success(); + } + + Error wait() override { ++#if 0 + BackendThreadPool.wait(); ++#endif + if (Err) + return std::move(*Err); + else +diff --git a/lib/LTO/LTOBackend.cpp b/lib/LTO/LTOBackend.cpp +index 809db80bc91..73a355ecf1a 100644 +--- a/lib/LTO/LTOBackend.cpp ++++ b/lib/LTO/LTOBackend.cpp +@@ -216,6 +216,7 @@ void codegen(Config &Conf, TargetMachine *TM, AddStreamFn AddStream, + void splitCodeGen(Config &C, TargetMachine *TM, AddStreamFn AddStream, + unsigned ParallelCodeGenParallelismLevel, + std::unique_ptr Mod) { ++#if 0 + ThreadPool CodegenThreadPool(ParallelCodeGenParallelismLevel); + unsigned ThreadCount = 0; + const Target *T = &TM->getTarget(); +@@ -259,6 +260,7 @@ void splitCodeGen(Config &C, TargetMachine *TM, AddStreamFn AddStream, + // variables, we need to wait for the worker threads to terminate before we + // can leave the function scope. + CodegenThreadPool.wait(); ++#endif + } + + Expected initAndLookupTarget(Config &C, Module &Mod) { +diff --git a/lib/LTO/ThinLTOCodeGenerator.cpp b/lib/LTO/ThinLTOCodeGenerator.cpp +index 40537e4fa78..470e9e57df5 100644 +--- a/lib/LTO/ThinLTOCodeGenerator.cpp ++++ b/lib/LTO/ThinLTOCodeGenerator.cpp +@@ -70,8 +70,8 @@ extern cl::opt LTOPassRemarksWithHotness; + + namespace { + +-static cl::opt +- ThreadCount("threads", cl::init(llvm::heavyweight_hardware_concurrency())); ++static cl::opt ThreadCount("threads", ++ cl::init(1)); + + Expected> + setupOptimizationRemarks(LLVMContext &Ctx, int Count) { +@@ -830,6 +830,7 @@ static std::string writeGeneratedObject(int count, StringRef CacheEntryPath, + + // Main entry point for the ThinLTO processing + void ThinLTOCodeGenerator::run() { ++#if 0 + // Prepare the resulting object vector + assert(ProducedBinaries.empty() && "The generator should not be reused"); + if (SavedObjectsDirectoryPath.empty()) +@@ -1052,4 +1053,5 @@ void ThinLTOCodeGenerator::run() { + // If statistics were requested, print them out now. + if (llvm::AreStatisticsEnabled()) + llvm::PrintStatistics(); ++#endif + } +diff --git a/lib/Support/ThreadPool.cpp b/lib/Support/ThreadPool.cpp +index db03a4d6240..71f49330f91 100644 +--- a/lib/Support/ThreadPool.cpp ++++ b/lib/Support/ThreadPool.cpp +@@ -11,6 +11,8 @@ + // + //===----------------------------------------------------------------------===// + ++#if 0 ++ + #include "llvm/Support/ThreadPool.h" + + #include "llvm/Config/llvm-config.h" +@@ -18,7 +20,7 @@ + + using namespace llvm; + +-#if LLVM_ENABLE_THREADS ++#if LLVM_ENABLE_THREADS && 0 + + // Default to std::thread::hardware_concurrency + ThreadPool::ThreadPool() : ThreadPool(std::thread::hardware_concurrency()) {} +@@ -156,3 +158,5 @@ ThreadPool::~ThreadPool() { + } + + #endif ++ ++#endif +diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt +index c1667049f80..aa7d7f105b2 100644 +--- a/test/CMakeLists.txt ++++ b/test/CMakeLists.txt +@@ -35,7 +35,6 @@ set(LLVM_TEST_DEPENDS + count + llc + lli +- lli-child-target + llvm-ar + llvm-as + llvm-bcanalyzer +diff --git a/tools/lli/CMakeLists.txt b/tools/lli/CMakeLists.txt +index f02e19313b7..ca2e82abcd0 100644 +--- a/tools/lli/CMakeLists.txt ++++ b/tools/lli/CMakeLists.txt +@@ -1,7 +1,3 @@ +-if ( LLVM_INCLUDE_UTILS ) +- add_subdirectory(ChildTarget) +-endif() +- + set(LLVM_LINK_COMPONENTS + CodeGen + Core +diff --git a/tools/lli/ChildTarget/CMakeLists.txt b/tools/lli/ChildTarget/CMakeLists.txt +deleted file mode 100644 +index f08ce57c295..00000000000 +--- a/tools/lli/ChildTarget/CMakeLists.txt ++++ /dev/null +@@ -1,13 +0,0 @@ +-set(LLVM_LINK_COMPONENTS +- OrcJIT +- RuntimeDyld +- Support +- ) +- +-add_llvm_utility(lli-child-target +- ChildTarget.cpp +- +- DEPENDS +- intrinsics_gen +-) +- +diff --git a/tools/lli/ChildTarget/ChildTarget.cpp b/tools/lli/ChildTarget/ChildTarget.cpp +deleted file mode 100644 +index 77b1d47a946..00000000000 +--- a/tools/lli/ChildTarget/ChildTarget.cpp ++++ /dev/null +@@ -1,67 +0,0 @@ +-#include "llvm/ExecutionEngine/Orc/OrcABISupport.h" +-#include "llvm/ExecutionEngine/Orc/OrcRemoteTargetServer.h" +-#include "llvm/Support/Debug.h" +-#include "llvm/Support/DynamicLibrary.h" +-#include "llvm/Support/Process.h" +-#include +- +-#include "../RemoteJITUtils.h" +- +-using namespace llvm; +-using namespace llvm::orc; +-using namespace llvm::sys; +- +-#ifdef __x86_64__ +-typedef OrcX86_64_SysV HostOrcArch; +-#else +-typedef OrcGenericABI HostOrcArch; +-#endif +- +-ExitOnError ExitOnErr; +- +-int main(int argc, char *argv[]) { +- +- if (argc != 3) { +- errs() << "Usage: " << argv[0] << " \n"; +- return 1; +- } +- +- ExitOnErr.setBanner(std::string(argv[0]) + ":"); +- +- int InFD; +- int OutFD; +- { +- std::istringstream InFDStream(argv[1]), OutFDStream(argv[2]); +- InFDStream >> InFD; +- OutFDStream >> OutFD; +- } +- +- if (sys::DynamicLibrary::LoadLibraryPermanently(nullptr)) { +- errs() << "Error loading program symbols.\n"; +- return 1; +- } +- +- auto SymbolLookup = [](const std::string &Name) { +- return RTDyldMemoryManager::getSymbolAddressInProcess(Name); +- }; +- +- auto RegisterEHFrames = [](uint8_t *Addr, uint32_t Size) { +- RTDyldMemoryManager::registerEHFramesInProcess(Addr, Size); +- }; +- +- auto DeregisterEHFrames = [](uint8_t *Addr, uint32_t Size) { +- RTDyldMemoryManager::deregisterEHFramesInProcess(Addr, Size); +- }; +- +- FDRawChannel Channel(InFD, OutFD); +- typedef remote::OrcRemoteTargetServer JITServer; +- JITServer Server(Channel, SymbolLookup, RegisterEHFrames, DeregisterEHFrames); +- +- while (!Server.receivedTerminate()) +- ExitOnErr(Server.handleOne()); +- +- close(InFD); +- close(OutFD); +- +- return 0; +-} +diff --git a/tools/lli/ChildTarget/LLVMBuild.txt b/tools/lli/ChildTarget/LLVMBuild.txt +deleted file mode 100644 +index daf6df11324..00000000000 +--- a/tools/lli/ChildTarget/LLVMBuild.txt ++++ /dev/null +@@ -1,21 +0,0 @@ +-;===- ./tools/lli/ChildTarget/LLVMBuild.txt --------------------*- Conf -*--===; +-; +-; The LLVM Compiler Infrastructure +-; +-; This file is distributed under the University of Illinois Open Source +-; License. See LICENSE.TXT for details. +-; +-;===------------------------------------------------------------------------===; +-; +-; This is an LLVMBuild description file for the components in this subdirectory. +-; +-; For more information on the LLVMBuild system, please see: +-; +-; http://llvm.org/docs/LLVMBuild.html +-; +-;===------------------------------------------------------------------------===; +- +-[component_0] +-type = Tool +-name = lli-child-target +-parent = lli +diff --git a/tools/lli/LLVMBuild.txt b/tools/lli/LLVMBuild.txt +index 9d889bf4c2e..47385048e08 100644 +--- a/tools/lli/LLVMBuild.txt ++++ b/tools/lli/LLVMBuild.txt +@@ -15,9 +15,6 @@ + ; + ;===------------------------------------------------------------------------===; + +-[common] +-subdirectories = ChildTarget +- + [component_0] + type = Tool + name = lli +diff --git a/tools/lli/OrcLazyJIT.cpp b/tools/lli/OrcLazyJIT.cpp +index ec61ce5e154..640cfd9b6ef 100644 +--- a/tools/lli/OrcLazyJIT.cpp ++++ b/tools/lli/OrcLazyJIT.cpp +@@ -1,3 +1,4 @@ ++#if 0 + //===------ OrcLazyJIT.cpp - Basic Orc-based JIT for lazy execution -------===// + // + // The LLVM Compiler Infrastructure +@@ -158,4 +159,4 @@ int llvm::runOrcLazyJIT(std::vector> Ms, + auto Main = fromTargetAddress(MainSym.getAddress()); + return Main(ArgV.size(), (const char**)ArgV.data()); + } +- ++#endif +diff --git a/tools/lli/OrcLazyJIT.h b/tools/lli/OrcLazyJIT.h +deleted file mode 100644 +index 05319c34548..00000000000 +--- a/tools/lli/OrcLazyJIT.h ++++ /dev/null +@@ -1,175 +0,0 @@ +-//===--- OrcLazyJIT.h - Basic Orc-based JIT for lazy execution --*- C++ -*-===// +-// +-// The LLVM Compiler Infrastructure +-// +-// This file is distributed under the University of Illinois Open Source +-// License. See LICENSE.TXT for details. +-// +-//===----------------------------------------------------------------------===// +-// +-// Simple Orc-based JIT. Uses the compile-on-demand layer to break up and +-// lazily compile modules. +-// +-//===----------------------------------------------------------------------===// +- +-#ifndef LLVM_TOOLS_LLI_ORCLAZYJIT_H +-#define LLVM_TOOLS_LLI_ORCLAZYJIT_H +- +-#include "llvm/ADT/Triple.h" +-#include "llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h" +-#include "llvm/ExecutionEngine/Orc/CompileUtils.h" +-#include "llvm/ExecutionEngine/Orc/ExecutionUtils.h" +-#include "llvm/ExecutionEngine/Orc/IRCompileLayer.h" +-#include "llvm/ExecutionEngine/Orc/IRTransformLayer.h" +-#include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h" +-#include "llvm/ExecutionEngine/RTDyldMemoryManager.h" +- +-namespace llvm { +- +-class OrcLazyJIT { +-public: +- +- typedef orc::JITCompileCallbackManager CompileCallbackMgr; +- typedef orc::ObjectLinkingLayer<> ObjLayerT; +- typedef orc::IRCompileLayer CompileLayerT; +- typedef std::function(std::unique_ptr)> +- TransformFtor; +- typedef orc::IRTransformLayer IRDumpLayerT; +- typedef orc::CompileOnDemandLayer CODLayerT; +- typedef CODLayerT::IndirectStubsManagerBuilderT +- IndirectStubsManagerBuilder; +- typedef CODLayerT::ModuleSetHandleT ModuleSetHandleT; +- +- OrcLazyJIT(std::unique_ptr TM, +- std::unique_ptr CCMgr, +- IndirectStubsManagerBuilder IndirectStubsMgrBuilder, +- bool InlineStubs) +- : TM(std::move(TM)), DL(this->TM->createDataLayout()), +- CCMgr(std::move(CCMgr)), +- ObjectLayer(), +- CompileLayer(ObjectLayer, orc::SimpleCompiler(*this->TM)), +- IRDumpLayer(CompileLayer, createDebugDumper()), +- CODLayer(IRDumpLayer, extractSingleFunction, *this->CCMgr, +- std::move(IndirectStubsMgrBuilder), InlineStubs), +- CXXRuntimeOverrides( +- [this](const std::string &S) { return mangle(S); }) {} +- +- ~OrcLazyJIT() { +- // Run any destructors registered with __cxa_atexit. +- CXXRuntimeOverrides.runDestructors(); +- // Run any IR destructors. +- for (auto &DtorRunner : IRStaticDestructorRunners) +- DtorRunner.runViaLayer(CODLayer); +- } +- +- ModuleSetHandleT addModuleSet(std::vector> Ms) { +- // Attach a data-layouts if they aren't already present. +- for (auto &M : Ms) +- if (M->getDataLayout().isDefault()) +- M->setDataLayout(DL); +- +- // Rename, bump linkage and record static constructors and destructors. +- // We have to do this before we hand over ownership of the module to the +- // JIT. +- std::vector CtorNames, DtorNames; +- { +- unsigned CtorId = 0, DtorId = 0; +- for (auto &M : Ms) { +- for (auto Ctor : orc::getConstructors(*M)) { +- std::string NewCtorName = ("$static_ctor." + Twine(CtorId++)).str(); +- Ctor.Func->setName(NewCtorName); +- Ctor.Func->setLinkage(GlobalValue::ExternalLinkage); +- Ctor.Func->setVisibility(GlobalValue::HiddenVisibility); +- CtorNames.push_back(mangle(NewCtorName)); +- } +- for (auto Dtor : orc::getDestructors(*M)) { +- std::string NewDtorName = ("$static_dtor." + Twine(DtorId++)).str(); +- Dtor.Func->setLinkage(GlobalValue::ExternalLinkage); +- Dtor.Func->setVisibility(GlobalValue::HiddenVisibility); +- DtorNames.push_back(mangle(Dtor.Func->getName())); +- Dtor.Func->setName(NewDtorName); +- } +- } +- } +- +- // Symbol resolution order: +- // 1) Search the JIT symbols. +- // 2) Check for C++ runtime overrides. +- // 3) Search the host process (LLI)'s symbol table. +- auto Resolver = +- orc::createLambdaResolver( +- [this](const std::string &Name) -> JITSymbol { +- if (auto Sym = CODLayer.findSymbol(Name, true)) +- return Sym; +- return CXXRuntimeOverrides.searchOverrides(Name); +- }, +- [](const std::string &Name) { +- if (auto Addr = +- RTDyldMemoryManager::getSymbolAddressInProcess(Name)) +- return JITSymbol(Addr, JITSymbolFlags::Exported); +- return JITSymbol(nullptr); +- } +- ); +- +- // Add the module to the JIT. +- auto H = CODLayer.addModuleSet(std::move(Ms), +- llvm::make_unique(), +- std::move(Resolver)); +- +- // Run the static constructors, and save the static destructor runner for +- // execution when the JIT is torn down. +- orc::CtorDtorRunner CtorRunner(std::move(CtorNames), H); +- CtorRunner.runViaLayer(CODLayer); +- +- IRStaticDestructorRunners.emplace_back(std::move(DtorNames), H); +- +- return H; +- } +- +- JITSymbol findSymbol(const std::string &Name) { +- return CODLayer.findSymbol(mangle(Name), true); +- } +- +- JITSymbol findSymbolIn(ModuleSetHandleT H, const std::string &Name) { +- return CODLayer.findSymbolIn(H, mangle(Name), true); +- } +- +-private: +- +- std::string mangle(const std::string &Name) { +- std::string MangledName; +- { +- raw_string_ostream MangledNameStream(MangledName); +- Mangler::getNameWithPrefix(MangledNameStream, Name, DL); +- } +- return MangledName; +- } +- +- static std::set extractSingleFunction(Function &F) { +- std::set Partition; +- Partition.insert(&F); +- return Partition; +- } +- +- static TransformFtor createDebugDumper(); +- +- std::unique_ptr TM; +- DataLayout DL; +- SectionMemoryManager CCMgrMemMgr; +- +- std::unique_ptr CCMgr; +- ObjLayerT ObjectLayer; +- CompileLayerT CompileLayer; +- IRDumpLayerT IRDumpLayer; +- CODLayerT CODLayer; +- +- orc::LocalCXXRuntimeOverrides CXXRuntimeOverrides; +- std::vector> IRStaticDestructorRunners; +-}; +- +-int runOrcLazyJIT(std::vector> Ms, +- const std::vector &Args); +- +-} // end namespace llvm +- +-#endif +diff --git a/tools/lli/RemoteJITUtils.h b/tools/lli/RemoteJITUtils.h +deleted file mode 100644 +index 89a51420256..00000000000 +--- a/tools/lli/RemoteJITUtils.h ++++ /dev/null +@@ -1,153 +0,0 @@ +-//===-- RemoteJITUtils.h - Utilities for remote-JITing with LLI -*- C++ -*-===// +-// +-// The LLVM Compiler Infrastructure +-// +-// This file is distributed under the University of Illinois Open Source +-// License. See LICENSE.TXT for details. +-// +-//===----------------------------------------------------------------------===// +-// +-// Utilities for remote-JITing with LLI. +-// +-//===----------------------------------------------------------------------===// +- +-#ifndef LLVM_TOOLS_LLI_REMOTEJITUTILS_H +-#define LLVM_TOOLS_LLI_REMOTEJITUTILS_H +- +-#include "llvm/ExecutionEngine/Orc/RawByteChannel.h" +-#include "llvm/ExecutionEngine/RTDyldMemoryManager.h" +-#include +- +-#if !defined(_MSC_VER) && !defined(__MINGW32__) +-#include +-#else +-#include +-#endif +- +-/// RPC channel that reads from and writes from file descriptors. +-class FDRawChannel final : public llvm::orc::rpc::RawByteChannel { +-public: +- FDRawChannel(int InFD, int OutFD) : InFD(InFD), OutFD(OutFD) {} +- +- llvm::Error readBytes(char *Dst, unsigned Size) override { +- assert(Dst && "Attempt to read into null."); +- ssize_t Completed = 0; +- while (Completed < static_cast(Size)) { +- ssize_t Read = ::read(InFD, Dst + Completed, Size - Completed); +- if (Read <= 0) { +- auto ErrNo = errno; +- if (ErrNo == EAGAIN || ErrNo == EINTR) +- continue; +- else +- return llvm::errorCodeToError( +- std::error_code(errno, std::generic_category())); +- } +- Completed += Read; +- } +- return llvm::Error::success(); +- } +- +- llvm::Error appendBytes(const char *Src, unsigned Size) override { +- assert(Src && "Attempt to append from null."); +- ssize_t Completed = 0; +- while (Completed < static_cast(Size)) { +- ssize_t Written = ::write(OutFD, Src + Completed, Size - Completed); +- if (Written < 0) { +- auto ErrNo = errno; +- if (ErrNo == EAGAIN || ErrNo == EINTR) +- continue; +- else +- return llvm::errorCodeToError( +- std::error_code(errno, std::generic_category())); +- } +- Completed += Written; +- } +- return llvm::Error::success(); +- } +- +- llvm::Error send() override { return llvm::Error::success(); } +- +-private: +- int InFD, OutFD; +-}; +- +-// launch the remote process (see lli.cpp) and return a channel to it. +-std::unique_ptr launchRemote(); +- +-namespace llvm { +- +-// ForwardingMM - Adapter to connect MCJIT to Orc's Remote8 +-// memory manager. +-class ForwardingMemoryManager : public llvm::RTDyldMemoryManager { +-public: +- void setMemMgr(std::unique_ptr MemMgr) { +- this->MemMgr = std::move(MemMgr); +- } +- +- void setResolver(std::unique_ptr Resolver) { +- this->Resolver = std::move(Resolver); +- } +- +- uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment, +- unsigned SectionID, +- StringRef SectionName) override { +- return MemMgr->allocateCodeSection(Size, Alignment, SectionID, SectionName); +- } +- +- uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment, +- unsigned SectionID, StringRef SectionName, +- bool IsReadOnly) override { +- return MemMgr->allocateDataSection(Size, Alignment, SectionID, SectionName, +- IsReadOnly); +- } +- +- void reserveAllocationSpace(uintptr_t CodeSize, uint32_t CodeAlign, +- uintptr_t RODataSize, uint32_t RODataAlign, +- uintptr_t RWDataSize, +- uint32_t RWDataAlign) override { +- MemMgr->reserveAllocationSpace(CodeSize, CodeAlign, RODataSize, RODataAlign, +- RWDataSize, RWDataAlign); +- } +- +- bool needsToReserveAllocationSpace() override { +- return MemMgr->needsToReserveAllocationSpace(); +- } +- +- void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr, +- size_t Size) override { +- MemMgr->registerEHFrames(Addr, LoadAddr, Size); +- } +- +- void deregisterEHFrames(uint8_t *Addr, uint64_t LoadAddr, +- size_t Size) override { +- MemMgr->deregisterEHFrames(Addr, LoadAddr, Size); +- } +- +- bool finalizeMemory(std::string *ErrMsg = nullptr) override { +- return MemMgr->finalizeMemory(ErrMsg); +- } +- +- void notifyObjectLoaded(RuntimeDyld &RTDyld, +- const object::ObjectFile &Obj) override { +- MemMgr->notifyObjectLoaded(RTDyld, Obj); +- } +- +- // Don't hide the sibling notifyObjectLoaded from RTDyldMemoryManager. +- using RTDyldMemoryManager::notifyObjectLoaded; +- +- JITSymbol findSymbol(const std::string &Name) override { +- return Resolver->findSymbol(Name); +- } +- +- JITSymbol +- findSymbolInLogicalDylib(const std::string &Name) override { +- return Resolver->findSymbolInLogicalDylib(Name); +- } +- +-private: +- std::unique_ptr MemMgr; +- std::unique_ptr Resolver; +-}; +-} +- +-#endif +diff --git a/tools/lli/lli.cpp b/tools/lli/lli.cpp +index 0823ff469de..8e9b9f87577 100644 +--- a/tools/lli/lli.cpp ++++ b/tools/lli/lli.cpp +@@ -13,6 +13,8 @@ + // + //===----------------------------------------------------------------------===// + ++#if 0 ++ + #include "OrcLazyJIT.h" + #include "RemoteJITUtils.h" + #include "llvm/IR/LLVMContext.h" +@@ -758,3 +760,8 @@ std::unique_ptr launchRemote() { + return llvm::make_unique(PipeFD[1][0], PipeFD[0][1]); + #endif + } ++#endif ++ ++int main(int argc, char **argv, char * const *envp) { ++ return 0; ++} +diff --git a/tools/llvm-cov/CodeCoverage.cpp b/tools/llvm-cov/CodeCoverage.cpp +index 0a9807ab003..0b7ffd366b9 100644 +--- a/tools/llvm-cov/CodeCoverage.cpp ++++ b/tools/llvm-cov/CodeCoverage.cpp +@@ -1,3 +1,4 @@ ++#if 0 + //===- CodeCoverage.cpp - Coverage tool based on profiling instrumentation-===// + // + // The LLVM Compiler Infrastructure +@@ -864,7 +865,10 @@ int reportMain(int argc, const char *argv[]) { + return Tool.run(CodeCoverageTool::Report, argc, argv); + } + ++ + int exportMain(int argc, const char *argv[]) { + CodeCoverageTool Tool; + return Tool.run(CodeCoverageTool::Export, argc, argv); + } ++ ++#endif +diff --git a/tools/llvm-cov/CoverageExporterJson.cpp b/tools/llvm-cov/CoverageExporterJson.cpp +index ef50bba2123..d3d0a8f5f01 100644 +--- a/tools/llvm-cov/CoverageExporterJson.cpp ++++ b/tools/llvm-cov/CoverageExporterJson.cpp +@@ -1,3 +1,4 @@ ++#if 0 + //===- CoverageExporterJson.cpp - Code coverage export --------------------===// + // + // The LLVM Compiler Infrastructure +@@ -419,3 +420,4 @@ void exportCoverageDataToJson(const CoverageMapping &CoverageMapping, + + Exporter.print(); + } ++#endif +diff --git a/tools/llvm-cov/CoverageFilters.cpp b/tools/llvm-cov/CoverageFilters.cpp +index 325dd723578..8a41ba8c1d8 100644 +--- a/tools/llvm-cov/CoverageFilters.cpp ++++ b/tools/llvm-cov/CoverageFilters.cpp +@@ -1,3 +1,4 @@ ++#if 0 + //===- CoverageFilters.cpp - Function coverage mapping filters ------------===// + // + // The LLVM Compiler Infrastructure +@@ -57,3 +58,4 @@ CoverageFiltersMatchAll::matches(const coverage::FunctionRecord &Function) { + } + return true; + } ++#endif +diff --git a/tools/llvm-cov/CoverageFilters.h b/tools/llvm-cov/CoverageFilters.h +deleted file mode 100644 +index 756c4b47872..00000000000 +--- a/tools/llvm-cov/CoverageFilters.h ++++ /dev/null +@@ -1,127 +0,0 @@ +-//===- CoverageFilters.h - Function coverage mapping filters --------------===// +-// +-// The LLVM Compiler Infrastructure +-// +-// This file is distributed under the University of Illinois Open Source +-// License. See LICENSE.TXT for details. +-// +-//===----------------------------------------------------------------------===// +-// +-// These classes provide filtering for function coverage mapping records. +-// +-//===----------------------------------------------------------------------===// +- +-#ifndef LLVM_COV_COVERAGEFILTERS_H +-#define LLVM_COV_COVERAGEFILTERS_H +- +-#include "llvm/ProfileData/Coverage/CoverageMapping.h" +-#include +-#include +- +-namespace llvm { +- +-/// \brief Matches specific functions that pass the requirement of this filter. +-class CoverageFilter { +-public: +- virtual ~CoverageFilter() {} +- +- /// \brief Return true if the function passes the requirements of this filter. +- virtual bool matches(const coverage::FunctionRecord &Function) { +- return true; +- } +-}; +- +-/// \brief Matches functions that contain a specific string in their name. +-class NameCoverageFilter : public CoverageFilter { +- StringRef Name; +- +-public: +- NameCoverageFilter(StringRef Name) : Name(Name) {} +- +- bool matches(const coverage::FunctionRecord &Function) override; +-}; +- +-/// \brief Matches functions whose name matches a certain regular expression. +-class NameRegexCoverageFilter : public CoverageFilter { +- StringRef Regex; +- +-public: +- NameRegexCoverageFilter(StringRef Regex) : Regex(Regex) {} +- +- bool matches(const coverage::FunctionRecord &Function) override; +-}; +- +-/// \brief Matches numbers that pass a certain threshold. +-template class StatisticThresholdFilter { +-public: +- enum Operation { LessThan, GreaterThan }; +- +-protected: +- Operation Op; +- T Threshold; +- +- StatisticThresholdFilter(Operation Op, T Threshold) +- : Op(Op), Threshold(Threshold) {} +- +- /// \brief Return true if the given number is less than +- /// or greater than the certain threshold. +- bool PassesThreshold(T Value) const { +- switch (Op) { +- case LessThan: +- return Value < Threshold; +- case GreaterThan: +- return Value > Threshold; +- } +- return false; +- } +-}; +- +-/// \brief Matches functions whose region coverage percentage +-/// is above/below a certain percentage. +-class RegionCoverageFilter : public CoverageFilter, +- public StatisticThresholdFilter { +-public: +- RegionCoverageFilter(Operation Op, double Threshold) +- : StatisticThresholdFilter(Op, Threshold) {} +- +- bool matches(const coverage::FunctionRecord &Function) override; +-}; +- +-/// \brief Matches functions whose line coverage percentage +-/// is above/below a certain percentage. +-class LineCoverageFilter : public CoverageFilter, +- public StatisticThresholdFilter { +-public: +- LineCoverageFilter(Operation Op, double Threshold) +- : StatisticThresholdFilter(Op, Threshold) {} +- +- bool matches(const coverage::FunctionRecord &Function) override; +-}; +- +-/// \brief A collection of filters. +-/// Matches functions that match any filters contained +-/// in an instance of this class. +-class CoverageFilters : public CoverageFilter { +-protected: +- std::vector> Filters; +- +-public: +- /// \brief Append a filter to this collection. +- void push_back(std::unique_ptr Filter); +- +- bool empty() const { return Filters.empty(); } +- +- bool matches(const coverage::FunctionRecord &Function) override; +-}; +- +-/// \brief A collection of filters. +-/// Matches functions that match all of the filters contained +-/// in an instance of this class. +-class CoverageFiltersMatchAll : public CoverageFilters { +-public: +- bool matches(const coverage::FunctionRecord &Function) override; +-}; +- +-} // namespace llvm +- +-#endif // LLVM_COV_COVERAGEFILTERS_H +diff --git a/tools/llvm-cov/CoverageReport.cpp b/tools/llvm-cov/CoverageReport.cpp +index e88cb186acd..67fdaa6f57e 100644 +--- a/tools/llvm-cov/CoverageReport.cpp ++++ b/tools/llvm-cov/CoverageReport.cpp +@@ -1,3 +1,4 @@ ++#if 0 + //===- CoverageReport.cpp - Code coverage report -------------------------===// + // + // The LLVM Compiler Infrastructure +@@ -353,3 +354,4 @@ void CoverageReport::renderFileReports(raw_ostream &OS, + } + + } // end namespace llvm ++#endif +diff --git a/tools/llvm-cov/CoverageReport.h b/tools/llvm-cov/CoverageReport.h +deleted file mode 100644 +index 7a416497e25..00000000000 +--- a/tools/llvm-cov/CoverageReport.h ++++ /dev/null +@@ -1,51 +0,0 @@ +-//===- CoverageReport.h - Code coverage report ---------------------------===// +-// +-// The LLVM Compiler Infrastructure +-// +-// This file is distributed under the University of Illinois Open Source +-// License. See LICENSE.TXT for details. +-// +-//===----------------------------------------------------------------------===// +-// +-// This class implements rendering of a code coverage report. +-// +-//===----------------------------------------------------------------------===// +- +-#ifndef LLVM_COV_COVERAGEREPORT_H +-#define LLVM_COV_COVERAGEREPORT_H +- +-#include "CoverageSummaryInfo.h" +-#include "CoverageViewOptions.h" +- +-namespace llvm { +- +-/// \brief Displays the code coverage report. +-class CoverageReport { +- const CoverageViewOptions &Options; +- const coverage::CoverageMapping &Coverage; +- +- void render(const FileCoverageSummary &File, raw_ostream &OS) const; +- void render(const FunctionCoverageSummary &Function, raw_ostream &OS) const; +- +-public: +- CoverageReport(const CoverageViewOptions &Options, +- const coverage::CoverageMapping &Coverage) +- : Options(Options), Coverage(Coverage) {} +- +- void renderFunctionReports(ArrayRef Files, raw_ostream &OS); +- +- /// Prepare file reports for the files specified in \p Files. +- static std::vector +- prepareFileReports(const coverage::CoverageMapping &Coverage, +- FileCoverageSummary &Totals, ArrayRef Files); +- +- /// Render file reports for every unique file in the coverage mapping. +- void renderFileReports(raw_ostream &OS) const; +- +- /// Render file reports for the files specified in \p Files. +- void renderFileReports(raw_ostream &OS, ArrayRef Files) const; +-}; +- +-} // end namespace llvm +- +-#endif // LLVM_COV_COVERAGEREPORT_H +diff --git a/tools/llvm-cov/CoverageSummaryInfo.cpp b/tools/llvm-cov/CoverageSummaryInfo.cpp +index 21aa7ff73a0..5a325b40cf8 100644 +--- a/tools/llvm-cov/CoverageSummaryInfo.cpp ++++ b/tools/llvm-cov/CoverageSummaryInfo.cpp +@@ -1,3 +1,4 @@ ++#if 0 + //===- CoverageSummaryInfo.cpp - Coverage summary for function/file -------===// + // + // The LLVM Compiler Infrastructure +@@ -81,3 +82,4 @@ void FunctionCoverageSummary::update(const FunctionCoverageSummary &Summary) { + LineCoverage.NotCovered = + std::min(LineCoverage.NotCovered, Summary.LineCoverage.NotCovered); + } ++#endif +diff --git a/tools/llvm-cov/CoverageSummaryInfo.h b/tools/llvm-cov/CoverageSummaryInfo.h +deleted file mode 100644 +index c04a4d42ccd..00000000000 +--- a/tools/llvm-cov/CoverageSummaryInfo.h ++++ /dev/null +@@ -1,165 +0,0 @@ +-//===- CoverageSummaryInfo.h - Coverage summary for function/file ---------===// +-// +-// The LLVM Compiler Infrastructure +-// +-// This file is distributed under the University of Illinois Open Source +-// License. See LICENSE.TXT for details. +-// +-//===----------------------------------------------------------------------===// +-// +-// These structures are used to represent code coverage metrics +-// for functions/files. +-// +-//===----------------------------------------------------------------------===// +- +-#ifndef LLVM_COV_COVERAGESUMMARYINFO_H +-#define LLVM_COV_COVERAGESUMMARYINFO_H +- +-#include "llvm/ProfileData/Coverage/CoverageMapping.h" +-#include "llvm/Support/raw_ostream.h" +- +-namespace llvm { +- +-/// \brief Provides information about region coverage for a function/file. +-struct RegionCoverageInfo { +- /// \brief The number of regions that were executed at least once. +- size_t Covered; +- +- /// \brief The number of regions that weren't executed. +- size_t NotCovered; +- +- /// \brief The total number of regions in a function/file. +- size_t NumRegions; +- +- RegionCoverageInfo() : Covered(0), NotCovered(0), NumRegions(0) {} +- +- RegionCoverageInfo(size_t Covered, size_t NumRegions) +- : Covered(Covered), NotCovered(NumRegions - Covered), +- NumRegions(NumRegions) {} +- +- RegionCoverageInfo &operator+=(const RegionCoverageInfo &RHS) { +- Covered += RHS.Covered; +- NotCovered += RHS.NotCovered; +- NumRegions += RHS.NumRegions; +- return *this; +- } +- +- bool isFullyCovered() const { return Covered == NumRegions; } +- +- double getPercentCovered() const { +- if (NumRegions == 0) +- return 0.0; +- return double(Covered) / double(NumRegions) * 100.0; +- } +-}; +- +-/// \brief Provides information about line coverage for a function/file. +-struct LineCoverageInfo { +- /// \brief The number of lines that were executed at least once. +- size_t Covered; +- +- /// \brief The number of lines that weren't executed. +- size_t NotCovered; +- +- /// \brief The total number of lines in a function/file. +- size_t NumLines; +- +- LineCoverageInfo() : Covered(0), NotCovered(0), NumLines(0) {} +- +- LineCoverageInfo(size_t Covered, size_t NumLines) +- : Covered(Covered), NotCovered(NumLines - Covered), NumLines(NumLines) {} +- +- LineCoverageInfo &operator+=(const LineCoverageInfo &RHS) { +- Covered += RHS.Covered; +- NotCovered += RHS.NotCovered; +- NumLines += RHS.NumLines; +- return *this; +- } +- +- bool isFullyCovered() const { return Covered == NumLines; } +- +- double getPercentCovered() const { +- if (NumLines == 0) +- return 0.0; +- return double(Covered) / double(NumLines) * 100.0; +- } +-}; +- +-/// \brief Provides information about function coverage for a file. +-struct FunctionCoverageInfo { +- /// \brief The number of functions that were executed. +- size_t Executed; +- +- /// \brief The total number of functions in this file. +- size_t NumFunctions; +- +- FunctionCoverageInfo() : Executed(0), NumFunctions(0) {} +- +- FunctionCoverageInfo(size_t Executed, size_t NumFunctions) +- : Executed(Executed), NumFunctions(NumFunctions) {} +- +- void addFunction(bool Covered) { +- if (Covered) +- ++Executed; +- ++NumFunctions; +- } +- +- bool isFullyCovered() const { return Executed == NumFunctions; } +- +- double getPercentCovered() const { +- if (NumFunctions == 0) +- return 0.0; +- return double(Executed) / double(NumFunctions) * 100.0; +- } +-}; +- +-/// \brief A summary of function's code coverage. +-struct FunctionCoverageSummary { +- StringRef Name; +- uint64_t ExecutionCount; +- RegionCoverageInfo RegionCoverage; +- LineCoverageInfo LineCoverage; +- +- FunctionCoverageSummary(StringRef Name) : Name(Name), ExecutionCount(0) {} +- +- FunctionCoverageSummary(StringRef Name, uint64_t ExecutionCount, +- const RegionCoverageInfo &RegionCoverage, +- const LineCoverageInfo &LineCoverage) +- : Name(Name), ExecutionCount(ExecutionCount), +- RegionCoverage(RegionCoverage), LineCoverage(LineCoverage) { +- } +- +- /// \brief Compute the code coverage summary for the given function coverage +- /// mapping record. +- static FunctionCoverageSummary +- get(const coverage::FunctionRecord &Function); +- +- /// \brief Update the summary with information from another instantiation +- /// of this function. +- void update(const FunctionCoverageSummary &Summary); +-}; +- +-/// \brief A summary of file's code coverage. +-struct FileCoverageSummary { +- StringRef Name; +- RegionCoverageInfo RegionCoverage; +- LineCoverageInfo LineCoverage; +- FunctionCoverageInfo FunctionCoverage; +- FunctionCoverageInfo InstantiationCoverage; +- +- FileCoverageSummary(StringRef Name) : Name(Name) {} +- +- void addFunction(const FunctionCoverageSummary &Function) { +- RegionCoverage += Function.RegionCoverage; +- LineCoverage += Function.LineCoverage; +- FunctionCoverage.addFunction(/*Covered=*/Function.ExecutionCount > 0); +- } +- +- void addInstantiation(const FunctionCoverageSummary &Function) { +- InstantiationCoverage.addFunction(/*Covered=*/Function.ExecutionCount > 0); +- } +-}; +- +-} // namespace llvm +- +-#endif // LLVM_COV_COVERAGESUMMARYINFO_H +diff --git a/tools/llvm-cov/CoverageViewOptions.h b/tools/llvm-cov/CoverageViewOptions.h +deleted file mode 100644 +index 266b380b7d3..00000000000 +--- a/tools/llvm-cov/CoverageViewOptions.h ++++ /dev/null +@@ -1,68 +0,0 @@ +-//===- CoverageViewOptions.h - Code coverage display options -------------===// +-// +-// The LLVM Compiler Infrastructure +-// +-// This file is distributed under the University of Illinois Open Source +-// License. See LICENSE.TXT for details. +-// +-//===----------------------------------------------------------------------===// +- +-#ifndef LLVM_COV_COVERAGEVIEWOPTIONS_H +-#define LLVM_COV_COVERAGEVIEWOPTIONS_H +- +-#include "RenderingSupport.h" +-#include +- +-namespace llvm { +- +-/// \brief The options for displaying the code coverage information. +-struct CoverageViewOptions { +- enum class OutputFormat { +- Text, +- HTML +- }; +- +- bool Debug; +- bool Colors; +- bool ShowLineNumbers; +- bool ShowLineStats; +- bool ShowRegionMarkers; +- bool ShowLineStatsOrRegionMarkers; +- bool ShowExpandedRegions; +- bool ShowFunctionInstantiations; +- bool ShowFullFilenames; +- OutputFormat Format; +- std::string ShowOutputDirectory; +- std::vector DemanglerOpts; +- uint32_t TabSize; +- std::string ProjectTitle; +- std::string CreatedTimeStr; +- +- /// \brief Change the output's stream color if the colors are enabled. +- ColoredRawOstream colored_ostream(raw_ostream &OS, +- raw_ostream::Colors Color) const { +- return llvm::colored_ostream(OS, Color, Colors); +- } +- +- /// \brief Check if an output directory has been specified. +- bool hasOutputDirectory() const { return !ShowOutputDirectory.empty(); } +- +- /// \brief Check if a demangler has been specified. +- bool hasDemangler() const { return !DemanglerOpts.empty(); } +- +- /// \brief Check if a project title has been specified. +- bool hasProjectTitle() const { return !ProjectTitle.empty(); } +- +- /// \brief Check if the created time of the profile data file is available. +- bool hasCreatedTime() const { return !CreatedTimeStr.empty(); } +- +- /// \brief Get the LLVM version string. +- std::string getLLVMVersionString() const { +- std::string VersionString = "Generated by llvm-cov -- llvm version "; +- VersionString += LLVM_VERSION_STRING; +- return VersionString; +- } +-}; +-} +- +-#endif // LLVM_COV_COVERAGEVIEWOPTIONS_H +diff --git a/tools/llvm-cov/RenderingSupport.h b/tools/llvm-cov/RenderingSupport.h +deleted file mode 100644 +index aa70fbc23e3..00000000000 +--- a/tools/llvm-cov/RenderingSupport.h ++++ /dev/null +@@ -1,61 +0,0 @@ +-//===- RenderingSupport.h - output stream rendering support functions ----===// +-// +-// The LLVM Compiler Infrastructure +-// +-// This file is distributed under the University of Illinois Open Source +-// License. See LICENSE.TXT for details. +-// +-//===----------------------------------------------------------------------===// +- +-#ifndef LLVM_COV_RENDERINGSUPPORT_H +-#define LLVM_COV_RENDERINGSUPPORT_H +- +-#include "llvm/Support/raw_ostream.h" +-#include +- +-namespace llvm { +- +-/// \brief A helper class that resets the output stream's color if needed +-/// when destroyed. +-class ColoredRawOstream { +- ColoredRawOstream(const ColoredRawOstream &OS) = delete; +- +-public: +- raw_ostream &OS; +- bool IsColorUsed; +- +- ColoredRawOstream(raw_ostream &OS, bool IsColorUsed) +- : OS(OS), IsColorUsed(IsColorUsed) {} +- +- ColoredRawOstream(ColoredRawOstream &&Other) +- : OS(Other.OS), IsColorUsed(Other.IsColorUsed) { +- // Reset the other IsColorUsed so that the other object won't reset the +- // color when destroyed. +- Other.IsColorUsed = false; +- } +- +- ~ColoredRawOstream() { +- if (IsColorUsed) +- OS.resetColor(); +- } +-}; +- +-template +-inline raw_ostream &operator<<(const ColoredRawOstream &OS, T &&Value) { +- return OS.OS << std::forward(Value); +-} +- +-/// \brief Change the color of the output stream if the `IsColorUsed` flag +-/// is true. Returns an object that resets the color when destroyed. +-inline ColoredRawOstream colored_ostream(raw_ostream &OS, +- raw_ostream::Colors Color, +- bool IsColorUsed = true, +- bool Bold = false, bool BG = false) { +- if (IsColorUsed) +- OS.changeColor(Color, Bold, BG); +- return ColoredRawOstream(OS, IsColorUsed); +-} +- +-} // namespace llvm +- +-#endif // LLVM_COV_RENDERINGSUPPORT_H +diff --git a/tools/llvm-cov/SourceCoverageView.cpp b/tools/llvm-cov/SourceCoverageView.cpp +index 52b8ff1747f..84c2cb7e8d6 100644 +--- a/tools/llvm-cov/SourceCoverageView.cpp ++++ b/tools/llvm-cov/SourceCoverageView.cpp +@@ -1,3 +1,4 @@ ++#if 0 + //===- SourceCoverageView.cpp - Code coverage view for source code --------===// + // + // The LLVM Compiler Infrastructure +@@ -265,3 +266,4 @@ void SourceCoverageView::print(raw_ostream &OS, bool WholeFile, + + renderViewFooter(OS); + } ++#endif +diff --git a/tools/llvm-cov/SourceCoverageView.h b/tools/llvm-cov/SourceCoverageView.h +deleted file mode 100644 +index 9cb608fed60..00000000000 +--- a/tools/llvm-cov/SourceCoverageView.h ++++ /dev/null +@@ -1,289 +0,0 @@ +-//===- SourceCoverageView.h - Code coverage view for source code ----------===// +-// +-// The LLVM Compiler Infrastructure +-// +-// This file is distributed under the University of Illinois Open Source +-// License. See LICENSE.TXT for details. +-// +-//===----------------------------------------------------------------------===// +-/// +-/// \file This class implements rendering for code coverage of source code. +-/// +-//===----------------------------------------------------------------------===// +- +-#ifndef LLVM_COV_SOURCECOVERAGEVIEW_H +-#define LLVM_COV_SOURCECOVERAGEVIEW_H +- +-#include "CoverageViewOptions.h" +-#include "llvm/ProfileData/Coverage/CoverageMapping.h" +-#include "llvm/Support/MemoryBuffer.h" +-#include +- +-namespace llvm { +- +-class SourceCoverageView; +- +-/// \brief A view that represents a macro or include expansion. +-struct ExpansionView { +- coverage::CounterMappingRegion Region; +- std::unique_ptr View; +- +- ExpansionView(const coverage::CounterMappingRegion &Region, +- std::unique_ptr View) +- : Region(Region), View(std::move(View)) {} +- ExpansionView(ExpansionView &&RHS) +- : Region(std::move(RHS.Region)), View(std::move(RHS.View)) {} +- ExpansionView &operator=(ExpansionView &&RHS) { +- Region = std::move(RHS.Region); +- View = std::move(RHS.View); +- return *this; +- } +- +- unsigned getLine() const { return Region.LineStart; } +- unsigned getStartCol() const { return Region.ColumnStart; } +- unsigned getEndCol() const { return Region.ColumnEnd; } +- +- friend bool operator<(const ExpansionView &LHS, const ExpansionView &RHS) { +- return LHS.Region.startLoc() < RHS.Region.startLoc(); +- } +-}; +- +-/// \brief A view that represents a function instantiation. +-struct InstantiationView { +- StringRef FunctionName; +- unsigned Line; +- std::unique_ptr View; +- +- InstantiationView(StringRef FunctionName, unsigned Line, +- std::unique_ptr View) +- : FunctionName(FunctionName), Line(Line), View(std::move(View)) {} +- +- friend bool operator<(const InstantiationView &LHS, +- const InstantiationView &RHS) { +- return LHS.Line < RHS.Line; +- } +-}; +- +-/// \brief Coverage statistics for a single line. +-struct LineCoverageStats { +- uint64_t ExecutionCount; +- unsigned RegionCount; +- bool Mapped; +- +- LineCoverageStats() : ExecutionCount(0), RegionCount(0), Mapped(false) {} +- +- bool isMapped() const { return Mapped; } +- +- bool hasMultipleRegions() const { return RegionCount > 1; } +- +- void addRegionStartCount(uint64_t Count) { +- // The max of all region starts is the most interesting value. +- addRegionCount(RegionCount ? std::max(ExecutionCount, Count) : Count); +- ++RegionCount; +- } +- +- void addRegionCount(uint64_t Count) { +- Mapped = true; +- ExecutionCount = Count; +- } +-}; +- +-/// \brief A file manager that handles format-aware file creation. +-class CoveragePrinter { +-public: +- struct StreamDestructor { +- void operator()(raw_ostream *OS) const; +- }; +- +- using OwnedStream = std::unique_ptr; +- +-protected: +- const CoverageViewOptions &Opts; +- +- CoveragePrinter(const CoverageViewOptions &Opts) : Opts(Opts) {} +- +- /// \brief Return `OutputDir/ToplevelDir/Path.Extension`. If \p InToplevel is +- /// false, skip the ToplevelDir component. If \p Relative is false, skip the +- /// OutputDir component. +- std::string getOutputPath(StringRef Path, StringRef Extension, +- bool InToplevel, bool Relative = true) const; +- +- /// \brief If directory output is enabled, create a file in that directory +- /// at the path given by getOutputPath(). Otherwise, return stdout. +- Expected createOutputStream(StringRef Path, StringRef Extension, +- bool InToplevel) const; +- +- /// \brief Return the sub-directory name for file coverage reports. +- static StringRef getCoverageDir() { return "coverage"; } +- +-public: +- static std::unique_ptr +- create(const CoverageViewOptions &Opts); +- +- virtual ~CoveragePrinter() {} +- +- /// @name File Creation Interface +- /// @{ +- +- /// \brief Create a file to print a coverage view into. +- virtual Expected createViewFile(StringRef Path, +- bool InToplevel) = 0; +- +- /// \brief Close a file which has been used to print a coverage view. +- virtual void closeViewFile(OwnedStream OS) = 0; +- +- /// \brief Create an index which lists reports for the given source files. +- virtual Error createIndexFile(ArrayRef SourceFiles, +- const coverage::CoverageMapping &Coverage) = 0; +- +- /// @} +-}; +- +-/// \brief A code coverage view of a source file or function. +-/// +-/// A source coverage view and its nested sub-views form a file-oriented +-/// representation of code coverage data. This view can be printed out by a +-/// renderer which implements the Rendering Interface. +-class SourceCoverageView { +- /// A function or file name. +- StringRef SourceName; +- +- /// A memory buffer backing the source on display. +- const MemoryBuffer &File; +- +- /// Various options to guide the coverage renderer. +- const CoverageViewOptions &Options; +- +- /// Complete coverage information about the source on display. +- coverage::CoverageData CoverageInfo; +- +- /// A container for all expansions (e.g macros) in the source on display. +- std::vector ExpansionSubViews; +- +- /// A container for all instantiations (e.g template functions) in the source +- /// on display. +- std::vector InstantiationSubViews; +- +- /// Get the first uncovered line number for the source file. +- unsigned getFirstUncoveredLineNo(); +- +-protected: +- struct LineRef { +- StringRef Line; +- int64_t LineNo; +- +- LineRef(StringRef Line, int64_t LineNo) : Line(Line), LineNo(LineNo) {} +- }; +- +- using CoverageSegmentArray = ArrayRef; +- +- /// @name Rendering Interface +- /// @{ +- +- /// \brief Render a header for the view. +- virtual void renderViewHeader(raw_ostream &OS) = 0; +- +- /// \brief Render a footer for the view. +- virtual void renderViewFooter(raw_ostream &OS) = 0; +- +- /// \brief Render the source name for the view. +- virtual void renderSourceName(raw_ostream &OS, bool WholeFile) = 0; +- +- /// \brief Render the line prefix at the given \p ViewDepth. +- virtual void renderLinePrefix(raw_ostream &OS, unsigned ViewDepth) = 0; +- +- /// \brief Render the line suffix at the given \p ViewDepth. +- virtual void renderLineSuffix(raw_ostream &OS, unsigned ViewDepth) = 0; +- +- /// \brief Render a view divider at the given \p ViewDepth. +- virtual void renderViewDivider(raw_ostream &OS, unsigned ViewDepth) = 0; +- +- /// \brief Render a source line with highlighting. +- virtual void renderLine(raw_ostream &OS, LineRef L, +- const coverage::CoverageSegment *WrappedSegment, +- CoverageSegmentArray Segments, unsigned ExpansionCol, +- unsigned ViewDepth) = 0; +- +- /// \brief Render the line's execution count column. +- virtual void renderLineCoverageColumn(raw_ostream &OS, +- const LineCoverageStats &Line) = 0; +- +- /// \brief Render the line number column. +- virtual void renderLineNumberColumn(raw_ostream &OS, unsigned LineNo) = 0; +- +- /// \brief Render all the region's execution counts on a line. +- virtual void renderRegionMarkers(raw_ostream &OS, +- CoverageSegmentArray Segments, +- unsigned ViewDepth) = 0; +- +- /// \brief Render the site of an expansion. +- virtual void +- renderExpansionSite(raw_ostream &OS, LineRef L, +- const coverage::CoverageSegment *WrappedSegment, +- CoverageSegmentArray Segments, unsigned ExpansionCol, +- unsigned ViewDepth) = 0; +- +- /// \brief Render an expansion view and any nested views. +- virtual void renderExpansionView(raw_ostream &OS, ExpansionView &ESV, +- unsigned ViewDepth) = 0; +- +- /// \brief Render an instantiation view and any nested views. +- virtual void renderInstantiationView(raw_ostream &OS, InstantiationView &ISV, +- unsigned ViewDepth) = 0; +- +- /// \brief Render \p Title, a project title if one is available, and the +- /// created time. +- virtual void renderTitle(raw_ostream &OS, StringRef CellText) = 0; +- +- /// \brief Render the table header for a given source file. +- virtual void renderTableHeader(raw_ostream &OS, unsigned FirstUncoveredLineNo, +- unsigned IndentLevel) = 0; +- +- /// @} +- +- /// \brief Format a count using engineering notation with 3 significant +- /// digits. +- static std::string formatCount(uint64_t N); +- +- /// \brief Check if region marker output is expected for a line. +- bool shouldRenderRegionMarkers(bool LineHasMultipleRegions) const; +- +- /// \brief Check if there are any sub-views attached to this view. +- bool hasSubViews() const; +- +- SourceCoverageView(StringRef SourceName, const MemoryBuffer &File, +- const CoverageViewOptions &Options, +- coverage::CoverageData &&CoverageInfo) +- : SourceName(SourceName), File(File), Options(Options), +- CoverageInfo(std::move(CoverageInfo)) {} +- +-public: +- static std::unique_ptr +- create(StringRef SourceName, const MemoryBuffer &File, +- const CoverageViewOptions &Options, +- coverage::CoverageData &&CoverageInfo); +- +- virtual ~SourceCoverageView() {} +- +- /// \brief Return the source name formatted for the host OS. +- std::string getSourceName() const; +- +- const CoverageViewOptions &getOptions() const { return Options; } +- +- /// \brief Add an expansion subview to this view. +- void addExpansion(const coverage::CounterMappingRegion &Region, +- std::unique_ptr View); +- +- /// \brief Add a function instantiation subview to this view. +- void addInstantiation(StringRef FunctionName, unsigned Line, +- std::unique_ptr View); +- +- /// \brief Print the code coverage information for a specific portion of a +- /// source file to the output stream. +- void print(raw_ostream &OS, bool WholeFile, bool ShowSourceName, +- unsigned ViewDepth = 0); +-}; +- +-} // namespace llvm +- +-#endif // LLVM_COV_SOURCECOVERAGEVIEW_H +diff --git a/tools/llvm-cov/SourceCoverageViewHTML.cpp b/tools/llvm-cov/SourceCoverageViewHTML.cpp +index 64b888e89d7..929b224b66b 100644 +--- a/tools/llvm-cov/SourceCoverageViewHTML.cpp ++++ b/tools/llvm-cov/SourceCoverageViewHTML.cpp +@@ -1,3 +1,4 @@ ++#if 0 + //===- SourceCoverageViewHTML.cpp - A html code coverage view -------------===// + // + // The LLVM Compiler Infrastructure +@@ -636,3 +637,5 @@ void SourceCoverageViewHTML::renderTableHeader(raw_ostream &OS, + << SourceLabel; + renderLineSuffix(OS, ViewDepth); + } ++ ++#endif +diff --git a/tools/llvm-cov/SourceCoverageViewHTML.h b/tools/llvm-cov/SourceCoverageViewHTML.h +deleted file mode 100644 +index 94b08a5e7fc..00000000000 +--- a/tools/llvm-cov/SourceCoverageViewHTML.h ++++ /dev/null +@@ -1,96 +0,0 @@ +-//===- SourceCoverageViewHTML.h - A html code coverage view ---------------===// +-// +-// The LLVM Compiler Infrastructure +-// +-// This file is distributed under the University of Illinois Open Source +-// License. See LICENSE.TXT for details. +-// +-//===----------------------------------------------------------------------===// +-/// +-/// \file This file defines the interface to the html coverage renderer. +-/// +-//===----------------------------------------------------------------------===// +- +-#ifndef LLVM_COV_SOURCECOVERAGEVIEWHTML_H +-#define LLVM_COV_SOURCECOVERAGEVIEWHTML_H +- +-#include "SourceCoverageView.h" +- +-namespace llvm { +- +-struct FileCoverageSummary; +- +-/// \brief A coverage printer for html output. +-class CoveragePrinterHTML : public CoveragePrinter { +-public: +- Expected createViewFile(StringRef Path, +- bool InToplevel) override; +- +- void closeViewFile(OwnedStream OS) override; +- +- Error createIndexFile(ArrayRef SourceFiles, +- const coverage::CoverageMapping &Coverage) override; +- +- CoveragePrinterHTML(const CoverageViewOptions &Opts) +- : CoveragePrinter(Opts) {} +- +-private: +- void emitFileSummary(raw_ostream &OS, StringRef SF, +- const FileCoverageSummary &FCS, +- bool IsTotals = false) const; +-}; +- +-/// \brief A code coverage view which supports html-based rendering. +-class SourceCoverageViewHTML : public SourceCoverageView { +- void renderViewHeader(raw_ostream &OS) override; +- +- void renderViewFooter(raw_ostream &OS) override; +- +- void renderSourceName(raw_ostream &OS, bool WholeFile) override; +- +- void renderLinePrefix(raw_ostream &OS, unsigned ViewDepth) override; +- +- void renderLineSuffix(raw_ostream &OS, unsigned ViewDepth) override; +- +- void renderViewDivider(raw_ostream &OS, unsigned ViewDepth) override; +- +- void renderLine(raw_ostream &OS, LineRef L, +- const coverage::CoverageSegment *WrappedSegment, +- CoverageSegmentArray Segments, unsigned ExpansionCol, +- unsigned ViewDepth) override; +- +- void renderExpansionSite(raw_ostream &OS, LineRef L, +- const coverage::CoverageSegment *WrappedSegment, +- CoverageSegmentArray Segments, unsigned ExpansionCol, +- unsigned ViewDepth) override; +- +- void renderExpansionView(raw_ostream &OS, ExpansionView &ESV, +- unsigned ViewDepth) override; +- +- void renderInstantiationView(raw_ostream &OS, InstantiationView &ISV, +- unsigned ViewDepth) override; +- +- void renderLineCoverageColumn(raw_ostream &OS, +- const LineCoverageStats &Line) override; +- +- void renderLineNumberColumn(raw_ostream &OS, unsigned LineNo) override; +- +- void renderRegionMarkers(raw_ostream &OS, CoverageSegmentArray Segments, +- unsigned ViewDepth) override; +- +- void renderTitle(raw_ostream &OS, StringRef Title) override; +- +- void renderTableHeader(raw_ostream &OS, unsigned FirstUncoveredLineNo, +- unsigned IndentLevel) override; +- +-public: +- SourceCoverageViewHTML(StringRef SourceName, const MemoryBuffer &File, +- const CoverageViewOptions &Options, +- coverage::CoverageData &&CoverageInfo) +- : SourceCoverageView(SourceName, File, Options, std::move(CoverageInfo)) { +- } +-}; +- +-} // namespace llvm +- +-#endif // LLVM_COV_SOURCECOVERAGEVIEWHTML_H +diff --git a/tools/llvm-cov/SourceCoverageViewText.cpp b/tools/llvm-cov/SourceCoverageViewText.cpp +index 4ad120f642e..03422a36a37 100644 +--- a/tools/llvm-cov/SourceCoverageViewText.cpp ++++ b/tools/llvm-cov/SourceCoverageViewText.cpp +@@ -1,3 +1,4 @@ ++#if 0 + //===- SourceCoverageViewText.cpp - A text-based code coverage view -------===// + // + // The LLVM Compiler Infrastructure +@@ -237,3 +238,5 @@ void SourceCoverageViewText::renderTitle(raw_ostream &OS, StringRef Title) { + + void SourceCoverageViewText::renderTableHeader(raw_ostream &, unsigned, + unsigned) {} ++ ++#endif +diff --git a/tools/llvm-cov/SourceCoverageViewText.h b/tools/llvm-cov/SourceCoverageViewText.h +deleted file mode 100644 +index c3f20de9297..00000000000 +--- a/tools/llvm-cov/SourceCoverageViewText.h ++++ /dev/null +@@ -1,89 +0,0 @@ +-//===- SourceCoverageViewText.h - A text-based code coverage view ---------===// +-// +-// The LLVM Compiler Infrastructure +-// +-// This file is distributed under the University of Illinois Open Source +-// License. See LICENSE.TXT for details. +-// +-//===----------------------------------------------------------------------===// +-/// +-/// \file This file defines the interface to the text-based coverage renderer. +-/// +-//===----------------------------------------------------------------------===// +- +-#ifndef LLVM_COV_SOURCECOVERAGEVIEWTEXT_H +-#define LLVM_COV_SOURCECOVERAGEVIEWTEXT_H +- +-#include "SourceCoverageView.h" +- +-namespace llvm { +- +-/// \brief A coverage printer for text output. +-class CoveragePrinterText : public CoveragePrinter { +-public: +- Expected createViewFile(StringRef Path, +- bool InToplevel) override; +- +- void closeViewFile(OwnedStream OS) override; +- +- Error createIndexFile(ArrayRef SourceFiles, +- const coverage::CoverageMapping &Coverage) override; +- +- CoveragePrinterText(const CoverageViewOptions &Opts) +- : CoveragePrinter(Opts) {} +-}; +- +-/// \brief A code coverage view which supports text-based rendering. +-class SourceCoverageViewText : public SourceCoverageView { +- void renderViewHeader(raw_ostream &OS) override; +- +- void renderViewFooter(raw_ostream &OS) override; +- +- void renderSourceName(raw_ostream &OS, bool WholeFile) override; +- +- void renderLinePrefix(raw_ostream &OS, unsigned ViewDepth) override; +- +- void renderLineSuffix(raw_ostream &OS, unsigned ViewDepth) override; +- +- void renderViewDivider(raw_ostream &OS, unsigned ViewDepth) override; +- +- void renderLine(raw_ostream &OS, LineRef L, +- const coverage::CoverageSegment *WrappedSegment, +- CoverageSegmentArray Segments, unsigned ExpansionCol, +- unsigned ViewDepth) override; +- +- void renderExpansionSite(raw_ostream &OS, LineRef L, +- const coverage::CoverageSegment *WrappedSegment, +- CoverageSegmentArray Segments, unsigned ExpansionCol, +- unsigned ViewDepth) override; +- +- void renderExpansionView(raw_ostream &OS, ExpansionView &ESV, +- unsigned ViewDepth) override; +- +- void renderInstantiationView(raw_ostream &OS, InstantiationView &ISV, +- unsigned ViewDepth) override; +- +- void renderLineCoverageColumn(raw_ostream &OS, +- const LineCoverageStats &Line) override; +- +- void renderLineNumberColumn(raw_ostream &OS, unsigned LineNo) override; +- +- void renderRegionMarkers(raw_ostream &OS, CoverageSegmentArray Segments, +- unsigned ViewDepth) override; +- +- void renderTitle(raw_ostream &OS, StringRef Title) override; +- +- void renderTableHeader(raw_ostream &OS, unsigned FirstUncoveredLineNo, +- unsigned IndentLevel) override; +- +-public: +- SourceCoverageViewText(StringRef SourceName, const MemoryBuffer &File, +- const CoverageViewOptions &Options, +- coverage::CoverageData &&CoverageInfo) +- : SourceCoverageView(SourceName, File, Options, std::move(CoverageInfo)) { +- } +-}; +- +-} // namespace llvm +- +-#endif // LLVM_COV_SOURCECOVERAGEVIEWTEXT_H +diff --git a/tools/llvm-cov/TestingSupport.cpp b/tools/llvm-cov/TestingSupport.cpp +index 72768f4fd58..89111d87b6e 100644 +--- a/tools/llvm-cov/TestingSupport.cpp ++++ b/tools/llvm-cov/TestingSupport.cpp +@@ -1,3 +1,4 @@ ++#if 0 + //===- TestingSupport.cpp - Convert objects files into test files --------===// + // + // The LLVM Compiler Infrastructure +@@ -90,3 +91,4 @@ int convertForTestingMain(int argc, const char *argv[]) { + + return 0; + } ++#endif +diff --git a/tools/llvm-cov/gcov.cpp b/tools/llvm-cov/gcov.cpp +index 4652fed2a38..ee742efdc15 100644 +--- a/tools/llvm-cov/gcov.cpp ++++ b/tools/llvm-cov/gcov.cpp +@@ -1,3 +1,4 @@ ++#if 0 + //===- gcov.cpp - GCOV compatible LLVM coverage tool ----------------------===// + // + // The LLVM Compiler Infrastructure +@@ -143,3 +144,4 @@ int gcovMain(int argc, const char *argv[]) { + Options); + return 0; + } ++#endif +diff --git a/tools/llvm-cov/llvm-cov.cpp b/tools/llvm-cov/llvm-cov.cpp +index 15841587025..5103688cd7c 100644 +--- a/tools/llvm-cov/llvm-cov.cpp ++++ b/tools/llvm-cov/llvm-cov.cpp +@@ -11,6 +11,7 @@ + // + //===----------------------------------------------------------------------===// + ++#if 0 + #include "llvm/ADT/StringRef.h" + #include "llvm/ADT/StringSwitch.h" + #include "llvm/Support/CommandLine.h" +@@ -57,8 +58,10 @@ static int versionMain(int argc, const char *argv[]) { + cl::PrintVersionMessage(); + return 0; + } ++#endif + + int main(int argc, const char **argv) { ++#if 0 + // Print a stack trace if we signal out. + sys::PrintStackTraceOnErrorSignal(argv[0]); + PrettyStackTraceProgram X(argc, argv); +@@ -96,5 +99,6 @@ int main(int argc, const char **argv) { + errs().resetColor(); + } + helpMain(argc, argv); ++#endif + return 1; + } +diff --git a/tools/llvm-profdata/llvm-profdata.cpp b/tools/llvm-profdata/llvm-profdata.cpp +index 6715566a166..cfcebbbb082 100644 +--- a/tools/llvm-profdata/llvm-profdata.cpp ++++ b/tools/llvm-profdata/llvm-profdata.cpp +@@ -11,6 +11,8 @@ + // + //===----------------------------------------------------------------------===// + ++#if 0 ++ + #include "llvm/ADT/SmallSet.h" + #include "llvm/ADT/SmallVector.h" + #include "llvm/ADT/StringRef.h" +@@ -652,8 +654,10 @@ static int show_main(int argc, const char *argv[]) { + return showSampleProfile(Filename, ShowCounts, ShowAllFunctions, + ShowFunction, OS); + } ++#endif + + int main(int argc, const char *argv[]) { ++#if 0 + // Print a stack trace if we signal out. + sys::PrintStackTraceOnErrorSignal(argv[0]); + PrettyStackTraceProgram X(argc, argv); +@@ -692,5 +696,6 @@ int main(int argc, const char *argv[]) { + errs() << ProgName << ": Unknown command!\n"; + + errs() << "USAGE: " << ProgName << " [args...]\n"; ++#endif + return 1; + } +diff --git a/tools/sancov/sancov.cc b/tools/sancov/sancov.cc +index ff2039de35e..abb924c3644 100644 +--- a/tools/sancov/sancov.cc ++++ b/tools/sancov/sancov.cc +@@ -10,6 +10,7 @@ + // This file is a command-line tool for reading and analyzing sanitizer + // coverage. + //===----------------------------------------------------------------------===// ++#if 0 + #include "llvm/ADT/STLExtras.h" + #include "llvm/ADT/StringExtras.h" + #include "llvm/ADT/Twine.h" +@@ -1181,8 +1182,10 @@ readSymbolizeAndMergeCmdArguments(std::vector FileNames) { + } + + } // namespace ++#endif + + int main(int Argc, char **Argv) { ++#if 0 + // Print stack trace if we signal out. + sys::PrintStackTraceOnErrorSignal(Argv[0]); + PrettyStackTraceProgram X(Argc, Argv); +@@ -1236,4 +1239,6 @@ int main(int Argc, char **Argv) { + case PrintCovPointsAction: + llvm_unreachable("unsupported action"); + } ++#endif ++ return 1; + } +diff --git a/unittests/Support/ThreadPool.cpp b/unittests/Support/ThreadPool.cpp +index 8e03aacfb1e..6ee0055c1ff 100644 +--- a/unittests/Support/ThreadPool.cpp ++++ b/unittests/Support/ThreadPool.cpp +@@ -7,6 +7,8 @@ + // + //===----------------------------------------------------------------------===// + ++#if 0 ++ + #include "llvm/Support/ThreadPool.h" + + #include "llvm/ADT/STLExtras.h" +@@ -164,3 +166,5 @@ TEST_F(ThreadPoolTest, PoolDestruction) { + } + ASSERT_EQ(5, checked_in); + } ++ ++#endif +-- +2.13.1 + diff --git a/deps/patches/llvm-5.0-NVPTX-addrspaces.patch b/deps/patches/llvm-5.0-NVPTX-addrspaces.patch new file mode 100644 index 0000000000000..0b04631242ccf --- /dev/null +++ b/deps/patches/llvm-5.0-NVPTX-addrspaces.patch @@ -0,0 +1,30 @@ +diff -ru llvm-5.0.0.orig/lib/Target/NVPTX/NVPTXISelLowering.cpp llvm-5.0.0/lib/Target/NVPTX/NVPTXISelLowering.cpp +--- llvm-5.0.0.orig/lib/Target/NVPTX/NVPTXISelLowering.cpp 2017-07-12 22:49:21.000000000 +0200 ++++ llvm-5.0.0/lib/Target/NVPTX/NVPTXISelLowering.cpp 2018-01-13 09:08:17.275987874 +0100 +@@ -1235,6 +1235,14 @@ + } + } + ++bool NVPTXTargetLowering::isNoopAddrSpaceCast(unsigned SrcAS, ++ unsigned DestAS) const { ++ assert(SrcAS != DestAS && "Expected different address spaces!"); ++ ++ return (SrcAS == ADDRESS_SPACE_GENERIC || SrcAS > ADDRESS_SPACE_LOCAL) && ++ (DestAS == ADDRESS_SPACE_GENERIC || DestAS > ADDRESS_SPACE_LOCAL); ++} ++ + SDValue + NVPTXTargetLowering::LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const { + SDLoc dl(Op); +diff -ru llvm-5.0.0.orig/lib/Target/NVPTX/NVPTXISelLowering.h llvm-5.0.0/lib/Target/NVPTX/NVPTXISelLowering.h +--- llvm-5.0.0.orig/lib/Target/NVPTX/NVPTXISelLowering.h 2018-01-13 09:07:48.839643576 +0100 ++++ llvm-5.0.0/lib/Target/NVPTX/NVPTXISelLowering.h 2018-01-13 09:06:18.658551692 +0100 +@@ -443,6 +443,8 @@ + const NVPTXSubtarget &STI); + SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override; + ++ bool isNoopAddrSpaceCast(unsigned SrcAS, unsigned DestAS) const override; ++ + SDValue LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const; + + const char *getTargetNodeName(unsigned Opcode) const override; diff --git a/deps/patches/llvm-5.0.0_threads.patch b/deps/patches/llvm-5.0.0_threads.patch new file mode 100644 index 0000000000000..ec94a1b17e7df --- /dev/null +++ b/deps/patches/llvm-5.0.0_threads.patch @@ -0,0 +1,2072 @@ +From 069fcb1fd3871ea14c8567763226464d605a90f3 Mon Sep 17 00:00:00 2001 +From: Alex Crichton +Date: Thu, 28 Jan 2016 20:44:50 -0800 +Subject: [PATCH] Don't compile usage of std::thread + +As of the time of this writing it's not actually used anywhere meaningfullly +throughout the LLVM repo that we need, and it unfortunately uses `std::thread` +which isn't available in mingw-w64 toolchains with the win32 threading model +(the one that we use). + +The change made to achive this was to just always use the single-threaded +support in `include/llvm/Support/thread.h`, and hopefuly that'll be enough... + +For reference, the upstream LLVM bug has been reported [1] + +[1]: https://llvm.org/bugs/show_bug.cgi?id=26365 +--- + include/llvm/Support/ThreadPool.h | 4 + + include/llvm/Support/thread.h | 2 +- + lib/CodeGen/ParallelCG.cpp | 2 + + lib/LTO/LTO.cpp | 6 +- + lib/LTO/LTOBackend.cpp | 2 + + lib/LTO/ThinLTOCodeGenerator.cpp | 6 +- + lib/Support/ThreadPool.cpp | 6 +- + test/CMakeLists.txt | 1 - + tools/lli/CMakeLists.txt | 4 - + tools/lli/ChildTarget/CMakeLists.txt | 13 -- + tools/lli/ChildTarget/ChildTarget.cpp | 67 ------- + tools/lli/ChildTarget/LLVMBuild.txt | 21 --- + tools/lli/LLVMBuild.txt | 3 - + tools/lli/OrcLazyJIT.cpp | 2 + + tools/lli/OrcLazyJIT.h | 201 --------------------- + tools/lli/RemoteJITUtils.h | 152 ---------------- + tools/lli/lli.cpp | 7 + + tools/llvm-cov/CodeCoverage.cpp | 4 + + tools/llvm-cov/CoverageExporterJson.cpp | 2 + + tools/llvm-cov/CoverageFilters.cpp | 2 + + tools/llvm-cov/CoverageFilters.h | 127 ------------- + tools/llvm-cov/CoverageReport.cpp | 2 + + tools/llvm-cov/CoverageReport.h | 53 ------ + tools/llvm-cov/CoverageSummaryInfo.cpp | 2 + + tools/llvm-cov/CoverageSummaryInfo.h | 178 ------------------ + tools/llvm-cov/CoverageViewOptions.h | 68 ------- + tools/llvm-cov/RenderingSupport.h | 61 ------- + tools/llvm-cov/SourceCoverageView.cpp | 2 + + tools/llvm-cov/SourceCoverageView.h | 289 ------------------------------ + tools/llvm-cov/SourceCoverageViewHTML.cpp | 3 + + tools/llvm-cov/SourceCoverageViewHTML.h | 96 ---------- + tools/llvm-cov/SourceCoverageViewText.cpp | 3 + + tools/llvm-cov/SourceCoverageViewText.h | 89 --------- + tools/llvm-cov/TestingSupport.cpp | 2 + + tools/llvm-cov/gcov.cpp | 2 + + tools/llvm-cov/llvm-cov.cpp | 4 + + tools/llvm-profdata/llvm-profdata.cpp | 5 + + tools/sancov/sancov.cc | 5 + + unittests/Support/ThreadPool.cpp | 4 + + 39 files changed, 73 insertions(+), 1429 deletions(-) + delete mode 100644 tools/lli/ChildTarget/CMakeLists.txt + delete mode 100644 tools/lli/ChildTarget/ChildTarget.cpp + delete mode 100644 tools/lli/ChildTarget/LLVMBuild.txt + delete mode 100644 tools/lli/OrcLazyJIT.h + delete mode 100644 tools/lli/RemoteJITUtils.h + delete mode 100644 tools/llvm-cov/CoverageFilters.h + delete mode 100644 tools/llvm-cov/CoverageReport.h + delete mode 100644 tools/llvm-cov/CoverageSummaryInfo.h + delete mode 100644 tools/llvm-cov/CoverageViewOptions.h + delete mode 100644 tools/llvm-cov/RenderingSupport.h + delete mode 100644 tools/llvm-cov/SourceCoverageView.h + delete mode 100644 tools/llvm-cov/SourceCoverageViewHTML.h + delete mode 100644 tools/llvm-cov/SourceCoverageViewText.h + +diff --git a/include/llvm/Support/ThreadPool.h b/include/llvm/Support/ThreadPool.h +index 9ada946c6da..c62e5917a2a 100644 +--- a/include/llvm/Support/ThreadPool.h ++++ b/include/llvm/Support/ThreadPool.h +@@ -16,6 +16,8 @@ + + #include "llvm/Support/thread.h" + ++# if 0 ++ + #include + + #include +@@ -97,4 +99,6 @@ private: + }; + } + ++# endif ++ + #endif // LLVM_SUPPORT_THREAD_POOL_H +diff --git a/include/llvm/Support/thread.h b/include/llvm/Support/thread.h +index 787a513d601..6668edb1887 100644 +--- a/include/llvm/Support/thread.h ++++ b/include/llvm/Support/thread.h +@@ -19,7 +19,7 @@ + + #include "llvm/Config/llvm-config.h" + +-#if LLVM_ENABLE_THREADS ++#if LLVM_ENABLE_THREADS && 0 + + #include + +diff --git a/lib/CodeGen/ParallelCG.cpp b/lib/CodeGen/ParallelCG.cpp +index 50dd44fa659..e91898e0fa7 100644 +--- a/lib/CodeGen/ParallelCG.cpp ++++ b/lib/CodeGen/ParallelCG.cpp +@@ -50,6 +50,7 @@ std::unique_ptr llvm::splitCodeGen( + return M; + } + ++#if 0 + // Create ThreadPool in nested scope so that threads will be joined + // on destruction. + { +@@ -96,5 +97,6 @@ std::unique_ptr llvm::splitCodeGen( + PreserveLocals); + } + ++#endif + return {}; + } +diff --git a/lib/LTO/LTO.cpp b/lib/LTO/LTO.cpp +index 19973946ac5..fbb899c88f7 100644 +--- a/lib/LTO/LTO.cpp ++++ b/lib/LTO/LTO.cpp +@@ -808,7 +808,6 @@ public: + + namespace { + class InProcessThinBackend : public ThinBackendProc { +- ThreadPool BackendThreadPool; + AddStreamFn AddStream; + NativeObjectCache Cache; + TypeIdSummariesByGuidTy TypeIdSummariesByGuid; +@@ -823,7 +822,6 @@ public: + const StringMap &ModuleToDefinedGVSummaries, + AddStreamFn AddStream, NativeObjectCache Cache) + : ThinBackendProc(Conf, CombinedIndex, ModuleToDefinedGVSummaries), +- BackendThreadPool(ThinLTOParallelismLevel), + AddStream(std::move(AddStream)), Cache(std::move(Cache)) { + // Create a mapping from type identifier GUIDs to type identifier summaries. + // This allows backends to use the type identifier GUIDs stored in the +@@ -877,6 +875,7 @@ public: + const FunctionImporter::ExportSetTy &ExportList, + const std::map &ResolvedODR, + MapVector &ModuleMap) override { ++#if 0 + StringRef ModulePath = BM.getModuleIdentifier(); + assert(ModuleToDefinedGVSummaries.count(ModulePath)); + const GVSummaryMapTy &DefinedGlobals = +@@ -904,11 +903,14 @@ public: + BM, std::ref(CombinedIndex), std::ref(ImportList), std::ref(ExportList), + std::ref(ResolvedODR), std::ref(DefinedGlobals), std::ref(ModuleMap), + std::ref(TypeIdSummariesByGuid)); ++#endif + return Error::success(); + } + + Error wait() override { ++#if 0 + BackendThreadPool.wait(); ++#endif + if (Err) + return std::move(*Err); + else +diff --git a/lib/LTO/LTOBackend.cpp b/lib/LTO/LTOBackend.cpp +index 3f72e446cdf..fad7c163959 100644 +--- a/lib/LTO/LTOBackend.cpp ++++ b/lib/LTO/LTOBackend.cpp +@@ -283,6 +283,7 @@ void codegen(Config &Conf, TargetMachine *TM, AddStreamFn AddStream, + void splitCodeGen(Config &C, TargetMachine *TM, AddStreamFn AddStream, + unsigned ParallelCodeGenParallelismLevel, + std::unique_ptr Mod) { ++#if 0 + ThreadPool CodegenThreadPool(ParallelCodeGenParallelismLevel); + unsigned ThreadCount = 0; + const Target *T = &TM->getTarget(); +@@ -326,6 +327,7 @@ void splitCodeGen(Config &C, TargetMachine *TM, AddStreamFn AddStream, + // variables, we need to wait for the worker threads to terminate before we + // can leave the function scope. + CodegenThreadPool.wait(); ++#endif + } + + Expected initAndLookupTarget(Config &C, Module &Mod) { +diff --git a/lib/LTO/ThinLTOCodeGenerator.cpp b/lib/LTO/ThinLTOCodeGenerator.cpp +index 1efd481b246..6b7b525f010 100644 +--- a/lib/LTO/ThinLTOCodeGenerator.cpp ++++ b/lib/LTO/ThinLTOCodeGenerator.cpp +@@ -68,8 +68,8 @@ extern cl::opt LTOStripInvalidDebugInfo; + + namespace { + +-static cl::opt +- ThreadCount("threads", cl::init(llvm::heavyweight_hardware_concurrency())); ++static cl::opt ThreadCount("threads", ++ cl::init(1)); + + // Simple helper to save temporary files for debug. + static void saveTempBitcode(const Module &TheModule, StringRef TempDir, +@@ -832,6 +832,7 @@ static std::string writeGeneratedObject(int count, StringRef CacheEntryPath, + + // Main entry point for the ThinLTO processing + void ThinLTOCodeGenerator::run() { ++#if 0 + // Prepare the resulting object vector + assert(ProducedBinaries.empty() && "The generator should not be reused"); + if (SavedObjectsDirectoryPath.empty()) +@@ -1052,4 +1053,5 @@ void ThinLTOCodeGenerator::run() { + if (llvm::AreStatisticsEnabled()) + llvm::PrintStatistics(); + reportAndResetTimings(); ++#endif + } +diff --git a/lib/Support/ThreadPool.cpp b/lib/Support/ThreadPool.cpp +index 22b7550d497..985403442e4 100644 +--- a/lib/Support/ThreadPool.cpp ++++ b/lib/Support/ThreadPool.cpp +@@ -11,6 +11,8 @@ + // + //===----------------------------------------------------------------------===// + ++#if 0 ++ + #include "llvm/Support/ThreadPool.h" + + #include "llvm/Config/llvm-config.h" +@@ -18,7 +20,7 @@ + + using namespace llvm; + +-#if LLVM_ENABLE_THREADS ++#if LLVM_ENABLE_THREADS && 0 + + // Default to std::thread::hardware_concurrency + ThreadPool::ThreadPool() : ThreadPool(std::thread::hardware_concurrency()) {} +@@ -143,3 +145,5 @@ ThreadPool::~ThreadPool() { + } + + #endif ++ ++#endif +diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt +index 124f0c72fd7..853adf6cf8a 100644 +--- a/test/CMakeLists.txt ++++ b/test/CMakeLists.txt +@@ -35,7 +35,6 @@ set(LLVM_TEST_DEPENDS + count + llc + lli +- lli-child-target + llvm-ar + llvm-as + llvm-bcanalyzer +diff --git a/tools/lli/CMakeLists.txt b/tools/lli/CMakeLists.txt +index f02e19313b7..ca2e82abcd0 100644 +--- a/tools/lli/CMakeLists.txt ++++ b/tools/lli/CMakeLists.txt +@@ -1,7 +1,3 @@ +-if ( LLVM_INCLUDE_UTILS ) +- add_subdirectory(ChildTarget) +-endif() +- + set(LLVM_LINK_COMPONENTS + CodeGen + Core +diff --git a/tools/lli/ChildTarget/CMakeLists.txt b/tools/lli/ChildTarget/CMakeLists.txt +deleted file mode 100644 +index f08ce57c295..00000000000 +--- a/tools/lli/ChildTarget/CMakeLists.txt ++++ /dev/null +@@ -1,13 +0,0 @@ +-set(LLVM_LINK_COMPONENTS +- OrcJIT +- RuntimeDyld +- Support +- ) +- +-add_llvm_utility(lli-child-target +- ChildTarget.cpp +- +- DEPENDS +- intrinsics_gen +-) +- +diff --git a/tools/lli/ChildTarget/ChildTarget.cpp b/tools/lli/ChildTarget/ChildTarget.cpp +deleted file mode 100644 +index 77b1d47a946..00000000000 +--- a/tools/lli/ChildTarget/ChildTarget.cpp ++++ /dev/null +@@ -1,67 +0,0 @@ +-#include "llvm/ExecutionEngine/Orc/OrcABISupport.h" +-#include "llvm/ExecutionEngine/Orc/OrcRemoteTargetServer.h" +-#include "llvm/Support/Debug.h" +-#include "llvm/Support/DynamicLibrary.h" +-#include "llvm/Support/Process.h" +-#include +- +-#include "../RemoteJITUtils.h" +- +-using namespace llvm; +-using namespace llvm::orc; +-using namespace llvm::sys; +- +-#ifdef __x86_64__ +-typedef OrcX86_64_SysV HostOrcArch; +-#else +-typedef OrcGenericABI HostOrcArch; +-#endif +- +-ExitOnError ExitOnErr; +- +-int main(int argc, char *argv[]) { +- +- if (argc != 3) { +- errs() << "Usage: " << argv[0] << " \n"; +- return 1; +- } +- +- ExitOnErr.setBanner(std::string(argv[0]) + ":"); +- +- int InFD; +- int OutFD; +- { +- std::istringstream InFDStream(argv[1]), OutFDStream(argv[2]); +- InFDStream >> InFD; +- OutFDStream >> OutFD; +- } +- +- if (sys::DynamicLibrary::LoadLibraryPermanently(nullptr)) { +- errs() << "Error loading program symbols.\n"; +- return 1; +- } +- +- auto SymbolLookup = [](const std::string &Name) { +- return RTDyldMemoryManager::getSymbolAddressInProcess(Name); +- }; +- +- auto RegisterEHFrames = [](uint8_t *Addr, uint32_t Size) { +- RTDyldMemoryManager::registerEHFramesInProcess(Addr, Size); +- }; +- +- auto DeregisterEHFrames = [](uint8_t *Addr, uint32_t Size) { +- RTDyldMemoryManager::deregisterEHFramesInProcess(Addr, Size); +- }; +- +- FDRawChannel Channel(InFD, OutFD); +- typedef remote::OrcRemoteTargetServer JITServer; +- JITServer Server(Channel, SymbolLookup, RegisterEHFrames, DeregisterEHFrames); +- +- while (!Server.receivedTerminate()) +- ExitOnErr(Server.handleOne()); +- +- close(InFD); +- close(OutFD); +- +- return 0; +-} +diff --git a/tools/lli/ChildTarget/LLVMBuild.txt b/tools/lli/ChildTarget/LLVMBuild.txt +deleted file mode 100644 +index daf6df11324..00000000000 +--- a/tools/lli/ChildTarget/LLVMBuild.txt ++++ /dev/null +@@ -1,21 +0,0 @@ +-;===- ./tools/lli/ChildTarget/LLVMBuild.txt --------------------*- Conf -*--===; +-; +-; The LLVM Compiler Infrastructure +-; +-; This file is distributed under the University of Illinois Open Source +-; License. See LICENSE.TXT for details. +-; +-;===------------------------------------------------------------------------===; +-; +-; This is an LLVMBuild description file for the components in this subdirectory. +-; +-; For more information on the LLVMBuild system, please see: +-; +-; http://llvm.org/docs/LLVMBuild.html +-; +-;===------------------------------------------------------------------------===; +- +-[component_0] +-type = Tool +-name = lli-child-target +-parent = lli +diff --git a/tools/lli/LLVMBuild.txt b/tools/lli/LLVMBuild.txt +index 9d889bf4c2e..47385048e08 100644 +--- a/tools/lli/LLVMBuild.txt ++++ b/tools/lli/LLVMBuild.txt +@@ -15,9 +15,6 @@ + ; + ;===------------------------------------------------------------------------===; + +-[common] +-subdirectories = ChildTarget +- + [component_0] + type = Tool + name = lli +diff --git a/tools/lli/OrcLazyJIT.cpp b/tools/lli/OrcLazyJIT.cpp +index f1a752e0790..adc0e0db3f8 100644 +--- a/tools/lli/OrcLazyJIT.cpp ++++ b/tools/lli/OrcLazyJIT.cpp +@@ -1,4 +1,5 @@ + //===- OrcLazyJIT.cpp - Basic Orc-based JIT for lazy execution ------------===// ++#if 0 + // + // The LLVM Compiler Infrastructure + // +@@ -164,3 +165,4 @@ int llvm::runOrcLazyJIT(std::vector> Ms, + + return 1; + } ++#endif +diff --git a/tools/lli/OrcLazyJIT.h b/tools/lli/OrcLazyJIT.h +deleted file mode 100644 +index 47a2acc4d7e..00000000000 +--- a/tools/lli/OrcLazyJIT.h ++++ /dev/null +@@ -1,201 +0,0 @@ +-//===- OrcLazyJIT.h - Basic Orc-based JIT for lazy execution ----*- C++ -*-===// +-// +-// The LLVM Compiler Infrastructure +-// +-// This file is distributed under the University of Illinois Open Source +-// License. See LICENSE.TXT for details. +-// +-//===----------------------------------------------------------------------===// +-// +-// Simple Orc-based JIT. Uses the compile-on-demand layer to break up and +-// lazily compile modules. +-// +-//===----------------------------------------------------------------------===// +- +-#ifndef LLVM_TOOLS_LLI_ORCLAZYJIT_H +-#define LLVM_TOOLS_LLI_ORCLAZYJIT_H +- +-#include "llvm/ADT/STLExtras.h" +-#include "llvm/ADT/Twine.h" +-#include "llvm/ExecutionEngine/JITSymbol.h" +-#include "llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h" +-#include "llvm/ExecutionEngine/Orc/CompileUtils.h" +-#include "llvm/ExecutionEngine/Orc/ExecutionUtils.h" +-#include "llvm/ExecutionEngine/Orc/IndirectionUtils.h" +-#include "llvm/ExecutionEngine/Orc/IRCompileLayer.h" +-#include "llvm/ExecutionEngine/Orc/IRTransformLayer.h" +-#include "llvm/ExecutionEngine/Orc/LambdaResolver.h" +-#include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h" +-#include "llvm/ExecutionEngine/RTDyldMemoryManager.h" +-#include "llvm/ExecutionEngine/SectionMemoryManager.h" +-#include "llvm/IR/DataLayout.h" +-#include "llvm/IR/GlobalValue.h" +-#include "llvm/IR/Mangler.h" +-#include "llvm/IR/Module.h" +-#include "llvm/Support/raw_ostream.h" +-#include "llvm/Target/TargetMachine.h" +-#include +-#include +-#include +-#include +-#include +-#include +- +-namespace llvm { +- +-class OrcLazyJIT { +-public: +- +- using CompileCallbackMgr = orc::JITCompileCallbackManager; +- using ObjLayerT = orc::RTDyldObjectLinkingLayer; +- using CompileLayerT = orc::IRCompileLayer; +- using TransformFtor = +- std::function(std::shared_ptr)>; +- using IRDumpLayerT = orc::IRTransformLayer; +- using CODLayerT = orc::CompileOnDemandLayer; +- using IndirectStubsManagerBuilder = CODLayerT::IndirectStubsManagerBuilderT; +- using ModuleHandleT = CODLayerT::ModuleHandleT; +- +- OrcLazyJIT(std::unique_ptr TM, +- std::unique_ptr CCMgr, +- IndirectStubsManagerBuilder IndirectStubsMgrBuilder, +- bool InlineStubs) +- : TM(std::move(TM)), DL(this->TM->createDataLayout()), +- CCMgr(std::move(CCMgr)), +- ObjectLayer([]() { return std::make_shared(); }), +- CompileLayer(ObjectLayer, orc::SimpleCompiler(*this->TM)), +- IRDumpLayer(CompileLayer, createDebugDumper()), +- CODLayer(IRDumpLayer, extractSingleFunction, *this->CCMgr, +- std::move(IndirectStubsMgrBuilder), InlineStubs), +- CXXRuntimeOverrides( +- [this](const std::string &S) { return mangle(S); }) {} +- +- ~OrcLazyJIT() { +- // Run any destructors registered with __cxa_atexit. +- CXXRuntimeOverrides.runDestructors(); +- // Run any IR destructors. +- for (auto &DtorRunner : IRStaticDestructorRunners) +- if (auto Err = DtorRunner.runViaLayer(CODLayer)) { +- // FIXME: OrcLazyJIT should probably take a "shutdownError" callback to +- // report these errors on. +- report_fatal_error(std::move(Err)); +- } +- } +- +- Error addModule(std::shared_ptr M) { +- if (M->getDataLayout().isDefault()) +- M->setDataLayout(DL); +- +- // Rename, bump linkage and record static constructors and destructors. +- // We have to do this before we hand over ownership of the module to the +- // JIT. +- std::vector CtorNames, DtorNames; +- { +- unsigned CtorId = 0, DtorId = 0; +- for (auto Ctor : orc::getConstructors(*M)) { +- std::string NewCtorName = ("$static_ctor." + Twine(CtorId++)).str(); +- Ctor.Func->setName(NewCtorName); +- Ctor.Func->setLinkage(GlobalValue::ExternalLinkage); +- Ctor.Func->setVisibility(GlobalValue::HiddenVisibility); +- CtorNames.push_back(mangle(NewCtorName)); +- } +- for (auto Dtor : orc::getDestructors(*M)) { +- std::string NewDtorName = ("$static_dtor." + Twine(DtorId++)).str(); +- Dtor.Func->setLinkage(GlobalValue::ExternalLinkage); +- Dtor.Func->setVisibility(GlobalValue::HiddenVisibility); +- DtorNames.push_back(mangle(Dtor.Func->getName())); +- Dtor.Func->setName(NewDtorName); +- } +- } +- +- // Symbol resolution order: +- // 1) Search the JIT symbols. +- // 2) Check for C++ runtime overrides. +- // 3) Search the host process (LLI)'s symbol table. +- if (ModulesHandle == CODLayerT::ModuleHandleT()) { +- auto Resolver = +- orc::createLambdaResolver( +- [this](const std::string &Name) -> JITSymbol { +- if (auto Sym = CODLayer.findSymbol(Name, true)) +- return Sym; +- return CXXRuntimeOverrides.searchOverrides(Name); +- }, +- [](const std::string &Name) { +- if (auto Addr = +- RTDyldMemoryManager::getSymbolAddressInProcess(Name)) +- return JITSymbol(Addr, JITSymbolFlags::Exported); +- return JITSymbol(nullptr); +- } +- ); +- +- // Add the module to the JIT. +- if (auto ModulesHandleOrErr = +- CODLayer.addModule(std::move(M), std::move(Resolver))) +- ModulesHandle = std::move(*ModulesHandleOrErr); +- else +- return ModulesHandleOrErr.takeError(); +- +- } else +- if (auto Err = CODLayer.addExtraModule(ModulesHandle, std::move(M))) +- return Err; +- +- // Run the static constructors, and save the static destructor runner for +- // execution when the JIT is torn down. +- orc::CtorDtorRunner CtorRunner(std::move(CtorNames), +- ModulesHandle); +- if (auto Err = CtorRunner.runViaLayer(CODLayer)) +- return Err; +- +- IRStaticDestructorRunners.emplace_back(std::move(DtorNames), +- ModulesHandle); +- +- return Error::success(); +- } +- +- JITSymbol findSymbol(const std::string &Name) { +- return CODLayer.findSymbol(mangle(Name), true); +- } +- +- JITSymbol findSymbolIn(ModuleHandleT H, const std::string &Name) { +- return CODLayer.findSymbolIn(H, mangle(Name), true); +- } +- +-private: +- std::string mangle(const std::string &Name) { +- std::string MangledName; +- { +- raw_string_ostream MangledNameStream(MangledName); +- Mangler::getNameWithPrefix(MangledNameStream, Name, DL); +- } +- return MangledName; +- } +- +- static std::set extractSingleFunction(Function &F) { +- std::set Partition; +- Partition.insert(&F); +- return Partition; +- } +- +- static TransformFtor createDebugDumper(); +- +- std::unique_ptr TM; +- DataLayout DL; +- SectionMemoryManager CCMgrMemMgr; +- +- std::unique_ptr CCMgr; +- ObjLayerT ObjectLayer; +- CompileLayerT CompileLayer; +- IRDumpLayerT IRDumpLayer; +- CODLayerT CODLayer; +- +- orc::LocalCXXRuntimeOverrides CXXRuntimeOverrides; +- std::vector> IRStaticDestructorRunners; +- CODLayerT::ModuleHandleT ModulesHandle; +-}; +- +-int runOrcLazyJIT(std::vector> Ms, +- const std::vector &Args); +- +-} // end namespace llvm +- +-#endif // LLVM_TOOLS_LLI_ORCLAZYJIT_H +diff --git a/tools/lli/RemoteJITUtils.h b/tools/lli/RemoteJITUtils.h +deleted file mode 100644 +index 4e948413865..00000000000 +--- a/tools/lli/RemoteJITUtils.h ++++ /dev/null +@@ -1,152 +0,0 @@ +-//===-- RemoteJITUtils.h - Utilities for remote-JITing with LLI -*- C++ -*-===// +-// +-// The LLVM Compiler Infrastructure +-// +-// This file is distributed under the University of Illinois Open Source +-// License. See LICENSE.TXT for details. +-// +-//===----------------------------------------------------------------------===// +-// +-// Utilities for remote-JITing with LLI. +-// +-//===----------------------------------------------------------------------===// +- +-#ifndef LLVM_TOOLS_LLI_REMOTEJITUTILS_H +-#define LLVM_TOOLS_LLI_REMOTEJITUTILS_H +- +-#include "llvm/ExecutionEngine/Orc/RawByteChannel.h" +-#include "llvm/ExecutionEngine/RTDyldMemoryManager.h" +-#include +- +-#if !defined(_MSC_VER) && !defined(__MINGW32__) +-#include +-#else +-#include +-#endif +- +-/// RPC channel that reads from and writes from file descriptors. +-class FDRawChannel final : public llvm::orc::rpc::RawByteChannel { +-public: +- FDRawChannel(int InFD, int OutFD) : InFD(InFD), OutFD(OutFD) {} +- +- llvm::Error readBytes(char *Dst, unsigned Size) override { +- assert(Dst && "Attempt to read into null."); +- ssize_t Completed = 0; +- while (Completed < static_cast(Size)) { +- ssize_t Read = ::read(InFD, Dst + Completed, Size - Completed); +- if (Read <= 0) { +- auto ErrNo = errno; +- if (ErrNo == EAGAIN || ErrNo == EINTR) +- continue; +- else +- return llvm::errorCodeToError( +- std::error_code(errno, std::generic_category())); +- } +- Completed += Read; +- } +- return llvm::Error::success(); +- } +- +- llvm::Error appendBytes(const char *Src, unsigned Size) override { +- assert(Src && "Attempt to append from null."); +- ssize_t Completed = 0; +- while (Completed < static_cast(Size)) { +- ssize_t Written = ::write(OutFD, Src + Completed, Size - Completed); +- if (Written < 0) { +- auto ErrNo = errno; +- if (ErrNo == EAGAIN || ErrNo == EINTR) +- continue; +- else +- return llvm::errorCodeToError( +- std::error_code(errno, std::generic_category())); +- } +- Completed += Written; +- } +- return llvm::Error::success(); +- } +- +- llvm::Error send() override { return llvm::Error::success(); } +- +-private: +- int InFD, OutFD; +-}; +- +-// launch the remote process (see lli.cpp) and return a channel to it. +-std::unique_ptr launchRemote(); +- +-namespace llvm { +- +-// ForwardingMM - Adapter to connect MCJIT to Orc's Remote8 +-// memory manager. +-class ForwardingMemoryManager : public llvm::RTDyldMemoryManager { +-public: +- void setMemMgr(std::unique_ptr MemMgr) { +- this->MemMgr = std::move(MemMgr); +- } +- +- void setResolver(std::shared_ptr Resolver) { +- this->Resolver = std::move(Resolver); +- } +- +- uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment, +- unsigned SectionID, +- StringRef SectionName) override { +- return MemMgr->allocateCodeSection(Size, Alignment, SectionID, SectionName); +- } +- +- uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment, +- unsigned SectionID, StringRef SectionName, +- bool IsReadOnly) override { +- return MemMgr->allocateDataSection(Size, Alignment, SectionID, SectionName, +- IsReadOnly); +- } +- +- void reserveAllocationSpace(uintptr_t CodeSize, uint32_t CodeAlign, +- uintptr_t RODataSize, uint32_t RODataAlign, +- uintptr_t RWDataSize, +- uint32_t RWDataAlign) override { +- MemMgr->reserveAllocationSpace(CodeSize, CodeAlign, RODataSize, RODataAlign, +- RWDataSize, RWDataAlign); +- } +- +- bool needsToReserveAllocationSpace() override { +- return MemMgr->needsToReserveAllocationSpace(); +- } +- +- void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr, +- size_t Size) override { +- MemMgr->registerEHFrames(Addr, LoadAddr, Size); +- } +- +- void deregisterEHFrames() override { +- MemMgr->deregisterEHFrames(); +- } +- +- bool finalizeMemory(std::string *ErrMsg = nullptr) override { +- return MemMgr->finalizeMemory(ErrMsg); +- } +- +- void notifyObjectLoaded(RuntimeDyld &RTDyld, +- const object::ObjectFile &Obj) override { +- MemMgr->notifyObjectLoaded(RTDyld, Obj); +- } +- +- // Don't hide the sibling notifyObjectLoaded from RTDyldMemoryManager. +- using RTDyldMemoryManager::notifyObjectLoaded; +- +- JITSymbol findSymbol(const std::string &Name) override { +- return Resolver->findSymbol(Name); +- } +- +- JITSymbol +- findSymbolInLogicalDylib(const std::string &Name) override { +- return Resolver->findSymbolInLogicalDylib(Name); +- } +- +-private: +- std::unique_ptr MemMgr; +- std::shared_ptr Resolver; +-}; +-} +- +-#endif +diff --git a/tools/lli/lli.cpp b/tools/lli/lli.cpp +index 091ca22b4e8..77ff6d4a01c 100644 +--- a/tools/lli/lli.cpp ++++ b/tools/lli/lli.cpp +@@ -13,6 +13,8 @@ + // + //===----------------------------------------------------------------------===// + ++#if 0 ++ + #include "OrcLazyJIT.h" + #include "RemoteJITUtils.h" + #include "llvm/IR/LLVMContext.h" +@@ -757,3 +759,8 @@ std::unique_ptr launchRemote() { + return llvm::make_unique(PipeFD[1][0], PipeFD[0][1]); + #endif + } ++#endif ++ ++int main(int argc, char **argv, char * const *envp) { ++ return 0; ++} +diff --git a/tools/llvm-cov/CodeCoverage.cpp b/tools/llvm-cov/CodeCoverage.cpp +index 3cbd6591134..2b270a35edb 100644 +--- a/tools/llvm-cov/CodeCoverage.cpp ++++ b/tools/llvm-cov/CodeCoverage.cpp +@@ -1,3 +1,4 @@ ++#if 0 + //===- CodeCoverage.cpp - Coverage tool based on profiling instrumentation-===// + // + // The LLVM Compiler Infrastructure +@@ -879,7 +880,10 @@ int reportMain(int argc, const char *argv[]) { + return Tool.run(CodeCoverageTool::Report, argc, argv); + } + ++ + int exportMain(int argc, const char *argv[]) { + CodeCoverageTool Tool; + return Tool.run(CodeCoverageTool::Export, argc, argv); + } ++ ++#endif +diff --git a/tools/llvm-cov/CoverageExporterJson.cpp b/tools/llvm-cov/CoverageExporterJson.cpp +index ef50bba2123..d3d0a8f5f01 100644 +--- a/tools/llvm-cov/CoverageExporterJson.cpp ++++ b/tools/llvm-cov/CoverageExporterJson.cpp +@@ -1,3 +1,4 @@ ++#if 0 + //===- CoverageExporterJson.cpp - Code coverage export --------------------===// + // + // The LLVM Compiler Infrastructure +@@ -419,3 +420,4 @@ void exportCoverageDataToJson(const CoverageMapping &CoverageMapping, + + Exporter.print(); + } ++#endif +diff --git a/tools/llvm-cov/CoverageFilters.cpp b/tools/llvm-cov/CoverageFilters.cpp +index 325dd723578..8a41ba8c1d8 100644 +--- a/tools/llvm-cov/CoverageFilters.cpp ++++ b/tools/llvm-cov/CoverageFilters.cpp +@@ -1,3 +1,4 @@ ++#if 0 + //===- CoverageFilters.cpp - Function coverage mapping filters ------------===// + // + // The LLVM Compiler Infrastructure +@@ -57,3 +58,4 @@ CoverageFiltersMatchAll::matches(const coverage::FunctionRecord &Function) { + } + return true; + } ++#endif +diff --git a/tools/llvm-cov/CoverageFilters.h b/tools/llvm-cov/CoverageFilters.h +deleted file mode 100644 +index 756c4b47872..00000000000 +--- a/tools/llvm-cov/CoverageFilters.h ++++ /dev/null +@@ -1,127 +0,0 @@ +-//===- CoverageFilters.h - Function coverage mapping filters --------------===// +-// +-// The LLVM Compiler Infrastructure +-// +-// This file is distributed under the University of Illinois Open Source +-// License. See LICENSE.TXT for details. +-// +-//===----------------------------------------------------------------------===// +-// +-// These classes provide filtering for function coverage mapping records. +-// +-//===----------------------------------------------------------------------===// +- +-#ifndef LLVM_COV_COVERAGEFILTERS_H +-#define LLVM_COV_COVERAGEFILTERS_H +- +-#include "llvm/ProfileData/Coverage/CoverageMapping.h" +-#include +-#include +- +-namespace llvm { +- +-/// \brief Matches specific functions that pass the requirement of this filter. +-class CoverageFilter { +-public: +- virtual ~CoverageFilter() {} +- +- /// \brief Return true if the function passes the requirements of this filter. +- virtual bool matches(const coverage::FunctionRecord &Function) { +- return true; +- } +-}; +- +-/// \brief Matches functions that contain a specific string in their name. +-class NameCoverageFilter : public CoverageFilter { +- StringRef Name; +- +-public: +- NameCoverageFilter(StringRef Name) : Name(Name) {} +- +- bool matches(const coverage::FunctionRecord &Function) override; +-}; +- +-/// \brief Matches functions whose name matches a certain regular expression. +-class NameRegexCoverageFilter : public CoverageFilter { +- StringRef Regex; +- +-public: +- NameRegexCoverageFilter(StringRef Regex) : Regex(Regex) {} +- +- bool matches(const coverage::FunctionRecord &Function) override; +-}; +- +-/// \brief Matches numbers that pass a certain threshold. +-template class StatisticThresholdFilter { +-public: +- enum Operation { LessThan, GreaterThan }; +- +-protected: +- Operation Op; +- T Threshold; +- +- StatisticThresholdFilter(Operation Op, T Threshold) +- : Op(Op), Threshold(Threshold) {} +- +- /// \brief Return true if the given number is less than +- /// or greater than the certain threshold. +- bool PassesThreshold(T Value) const { +- switch (Op) { +- case LessThan: +- return Value < Threshold; +- case GreaterThan: +- return Value > Threshold; +- } +- return false; +- } +-}; +- +-/// \brief Matches functions whose region coverage percentage +-/// is above/below a certain percentage. +-class RegionCoverageFilter : public CoverageFilter, +- public StatisticThresholdFilter { +-public: +- RegionCoverageFilter(Operation Op, double Threshold) +- : StatisticThresholdFilter(Op, Threshold) {} +- +- bool matches(const coverage::FunctionRecord &Function) override; +-}; +- +-/// \brief Matches functions whose line coverage percentage +-/// is above/below a certain percentage. +-class LineCoverageFilter : public CoverageFilter, +- public StatisticThresholdFilter { +-public: +- LineCoverageFilter(Operation Op, double Threshold) +- : StatisticThresholdFilter(Op, Threshold) {} +- +- bool matches(const coverage::FunctionRecord &Function) override; +-}; +- +-/// \brief A collection of filters. +-/// Matches functions that match any filters contained +-/// in an instance of this class. +-class CoverageFilters : public CoverageFilter { +-protected: +- std::vector> Filters; +- +-public: +- /// \brief Append a filter to this collection. +- void push_back(std::unique_ptr Filter); +- +- bool empty() const { return Filters.empty(); } +- +- bool matches(const coverage::FunctionRecord &Function) override; +-}; +- +-/// \brief A collection of filters. +-/// Matches functions that match all of the filters contained +-/// in an instance of this class. +-class CoverageFiltersMatchAll : public CoverageFilters { +-public: +- bool matches(const coverage::FunctionRecord &Function) override; +-}; +- +-} // namespace llvm +- +-#endif // LLVM_COV_COVERAGEFILTERS_H +diff --git a/tools/llvm-cov/CoverageReport.cpp b/tools/llvm-cov/CoverageReport.cpp +index c68bb9048df..b17831bcaa8 100644 +--- a/tools/llvm-cov/CoverageReport.cpp ++++ b/tools/llvm-cov/CoverageReport.cpp +@@ -1,3 +1,4 @@ ++#if 0 + //===- CoverageReport.cpp - Code coverage report -------------------------===// + // + // The LLVM Compiler Infrastructure +@@ -386,3 +387,4 @@ void CoverageReport::renderFileReports(raw_ostream &OS, + } + + } // end namespace llvm ++#endif +diff --git a/tools/llvm-cov/CoverageReport.h b/tools/llvm-cov/CoverageReport.h +deleted file mode 100644 +index 071be2e2159..00000000000 +--- a/tools/llvm-cov/CoverageReport.h ++++ /dev/null +@@ -1,53 +0,0 @@ +-//===- CoverageReport.h - Code coverage report ---------------------------===// +-// +-// The LLVM Compiler Infrastructure +-// +-// This file is distributed under the University of Illinois Open Source +-// License. See LICENSE.TXT for details. +-// +-//===----------------------------------------------------------------------===// +-// +-// This class implements rendering of a code coverage report. +-// +-//===----------------------------------------------------------------------===// +- +-#ifndef LLVM_COV_COVERAGEREPORT_H +-#define LLVM_COV_COVERAGEREPORT_H +- +-#include "CoverageSummaryInfo.h" +-#include "CoverageViewOptions.h" +- +-namespace llvm { +- +-/// \brief Displays the code coverage report. +-class CoverageReport { +- const CoverageViewOptions &Options; +- const coverage::CoverageMapping &Coverage; +- +- void render(const FileCoverageSummary &File, raw_ostream &OS) const; +- void render(const FunctionCoverageSummary &Function, const DemangleCache &DC, +- raw_ostream &OS) const; +- +-public: +- CoverageReport(const CoverageViewOptions &Options, +- const coverage::CoverageMapping &Coverage) +- : Options(Options), Coverage(Coverage) {} +- +- void renderFunctionReports(ArrayRef Files, +- const DemangleCache &DC, raw_ostream &OS); +- +- /// Prepare file reports for the files specified in \p Files. +- static std::vector +- prepareFileReports(const coverage::CoverageMapping &Coverage, +- FileCoverageSummary &Totals, ArrayRef Files); +- +- /// Render file reports for every unique file in the coverage mapping. +- void renderFileReports(raw_ostream &OS) const; +- +- /// Render file reports for the files specified in \p Files. +- void renderFileReports(raw_ostream &OS, ArrayRef Files) const; +-}; +- +-} // end namespace llvm +- +-#endif // LLVM_COV_COVERAGEREPORT_H +diff --git a/tools/llvm-cov/CoverageSummaryInfo.cpp b/tools/llvm-cov/CoverageSummaryInfo.cpp +index 21aa7ff73a0..5a325b40cf8 100644 +--- a/tools/llvm-cov/CoverageSummaryInfo.cpp ++++ b/tools/llvm-cov/CoverageSummaryInfo.cpp +@@ -1,3 +1,4 @@ ++#if 0 + //===- CoverageSummaryInfo.cpp - Coverage summary for function/file -------===// + // + // The LLVM Compiler Infrastructure +@@ -81,3 +82,4 @@ void FunctionCoverageSummary::update(const FunctionCoverageSummary &Summary) { + LineCoverage.NotCovered = + std::min(LineCoverage.NotCovered, Summary.LineCoverage.NotCovered); + } ++#endif +diff --git a/tools/llvm-cov/CoverageSummaryInfo.h b/tools/llvm-cov/CoverageSummaryInfo.h +deleted file mode 100644 +index 680fc375768..00000000000 +--- a/tools/llvm-cov/CoverageSummaryInfo.h ++++ /dev/null +@@ -1,178 +0,0 @@ +-//===- CoverageSummaryInfo.h - Coverage summary for function/file ---------===// +-// +-// The LLVM Compiler Infrastructure +-// +-// This file is distributed under the University of Illinois Open Source +-// License. See LICENSE.TXT for details. +-// +-//===----------------------------------------------------------------------===// +-// +-// These structures are used to represent code coverage metrics +-// for functions/files. +-// +-//===----------------------------------------------------------------------===// +- +-#ifndef LLVM_COV_COVERAGESUMMARYINFO_H +-#define LLVM_COV_COVERAGESUMMARYINFO_H +- +-#include "llvm/ProfileData/Coverage/CoverageMapping.h" +-#include "llvm/Support/raw_ostream.h" +- +-namespace llvm { +- +-/// \brief Provides information about region coverage for a function/file. +-struct RegionCoverageInfo { +- /// \brief The number of regions that were executed at least once. +- size_t Covered; +- +- /// \brief The number of regions that weren't executed. +- size_t NotCovered; +- +- /// \brief The total number of regions in a function/file. +- size_t NumRegions; +- +- RegionCoverageInfo() : Covered(0), NotCovered(0), NumRegions(0) {} +- +- RegionCoverageInfo(size_t Covered, size_t NumRegions) +- : Covered(Covered), NotCovered(NumRegions - Covered), +- NumRegions(NumRegions) {} +- +- RegionCoverageInfo &operator+=(const RegionCoverageInfo &RHS) { +- Covered += RHS.Covered; +- NotCovered += RHS.NotCovered; +- NumRegions += RHS.NumRegions; +- return *this; +- } +- +- bool isFullyCovered() const { return Covered == NumRegions; } +- +- double getPercentCovered() const { +- if (NumRegions == 0) +- return 0.0; +- return double(Covered) / double(NumRegions) * 100.0; +- } +-}; +- +-/// \brief Provides information about line coverage for a function/file. +-struct LineCoverageInfo { +- /// \brief The number of lines that were executed at least once. +- size_t Covered; +- +- /// \brief The number of lines that weren't executed. +- size_t NotCovered; +- +- /// \brief The total number of lines in a function/file. +- size_t NumLines; +- +- LineCoverageInfo() : Covered(0), NotCovered(0), NumLines(0) {} +- +- LineCoverageInfo(size_t Covered, size_t NumLines) +- : Covered(Covered), NotCovered(NumLines - Covered), NumLines(NumLines) {} +- +- LineCoverageInfo &operator+=(const LineCoverageInfo &RHS) { +- Covered += RHS.Covered; +- NotCovered += RHS.NotCovered; +- NumLines += RHS.NumLines; +- return *this; +- } +- +- bool isFullyCovered() const { return Covered == NumLines; } +- +- double getPercentCovered() const { +- if (NumLines == 0) +- return 0.0; +- return double(Covered) / double(NumLines) * 100.0; +- } +-}; +- +-/// \brief Provides information about function coverage for a file. +-struct FunctionCoverageInfo { +- /// \brief The number of functions that were executed. +- size_t Executed; +- +- /// \brief The total number of functions in this file. +- size_t NumFunctions; +- +- FunctionCoverageInfo() : Executed(0), NumFunctions(0) {} +- +- FunctionCoverageInfo(size_t Executed, size_t NumFunctions) +- : Executed(Executed), NumFunctions(NumFunctions) {} +- +- void addFunction(bool Covered) { +- if (Covered) +- ++Executed; +- ++NumFunctions; +- } +- +- bool isFullyCovered() const { return Executed == NumFunctions; } +- +- double getPercentCovered() const { +- if (NumFunctions == 0) +- return 0.0; +- return double(Executed) / double(NumFunctions) * 100.0; +- } +-}; +- +-/// \brief A summary of function's code coverage. +-struct FunctionCoverageSummary { +- StringRef Name; +- uint64_t ExecutionCount; +- RegionCoverageInfo RegionCoverage; +- LineCoverageInfo LineCoverage; +- +- FunctionCoverageSummary(StringRef Name) : Name(Name), ExecutionCount(0) {} +- +- FunctionCoverageSummary(StringRef Name, uint64_t ExecutionCount, +- const RegionCoverageInfo &RegionCoverage, +- const LineCoverageInfo &LineCoverage) +- : Name(Name), ExecutionCount(ExecutionCount), +- RegionCoverage(RegionCoverage), LineCoverage(LineCoverage) { +- } +- +- /// \brief Compute the code coverage summary for the given function coverage +- /// mapping record. +- static FunctionCoverageSummary +- get(const coverage::FunctionRecord &Function); +- +- /// \brief Update the summary with information from another instantiation +- /// of this function. +- void update(const FunctionCoverageSummary &Summary); +-}; +- +-/// \brief A summary of file's code coverage. +-struct FileCoverageSummary { +- StringRef Name; +- RegionCoverageInfo RegionCoverage; +- LineCoverageInfo LineCoverage; +- FunctionCoverageInfo FunctionCoverage; +- FunctionCoverageInfo InstantiationCoverage; +- +- FileCoverageSummary(StringRef Name) : Name(Name) {} +- +- void addFunction(const FunctionCoverageSummary &Function) { +- RegionCoverage += Function.RegionCoverage; +- LineCoverage += Function.LineCoverage; +- FunctionCoverage.addFunction(/*Covered=*/Function.ExecutionCount > 0); +- } +- +- void addInstantiation(const FunctionCoverageSummary &Function) { +- InstantiationCoverage.addFunction(/*Covered=*/Function.ExecutionCount > 0); +- } +-}; +- +-/// \brief A cache for demangled symbols. +-struct DemangleCache { +- StringMap DemangledNames; +- +- /// \brief Demangle \p Sym if possible. Otherwise, just return \p Sym. +- StringRef demangle(StringRef Sym) const { +- const auto DemangledName = DemangledNames.find(Sym); +- if (DemangledName == DemangledNames.end()) +- return Sym; +- return DemangledName->getValue(); +- } +-}; +- +-} // namespace llvm +- +-#endif // LLVM_COV_COVERAGESUMMARYINFO_H +diff --git a/tools/llvm-cov/CoverageViewOptions.h b/tools/llvm-cov/CoverageViewOptions.h +deleted file mode 100644 +index 266b380b7d3..00000000000 +--- a/tools/llvm-cov/CoverageViewOptions.h ++++ /dev/null +@@ -1,68 +0,0 @@ +-//===- CoverageViewOptions.h - Code coverage display options -------------===// +-// +-// The LLVM Compiler Infrastructure +-// +-// This file is distributed under the University of Illinois Open Source +-// License. See LICENSE.TXT for details. +-// +-//===----------------------------------------------------------------------===// +- +-#ifndef LLVM_COV_COVERAGEVIEWOPTIONS_H +-#define LLVM_COV_COVERAGEVIEWOPTIONS_H +- +-#include "RenderingSupport.h" +-#include +- +-namespace llvm { +- +-/// \brief The options for displaying the code coverage information. +-struct CoverageViewOptions { +- enum class OutputFormat { +- Text, +- HTML +- }; +- +- bool Debug; +- bool Colors; +- bool ShowLineNumbers; +- bool ShowLineStats; +- bool ShowRegionMarkers; +- bool ShowLineStatsOrRegionMarkers; +- bool ShowExpandedRegions; +- bool ShowFunctionInstantiations; +- bool ShowFullFilenames; +- OutputFormat Format; +- std::string ShowOutputDirectory; +- std::vector DemanglerOpts; +- uint32_t TabSize; +- std::string ProjectTitle; +- std::string CreatedTimeStr; +- +- /// \brief Change the output's stream color if the colors are enabled. +- ColoredRawOstream colored_ostream(raw_ostream &OS, +- raw_ostream::Colors Color) const { +- return llvm::colored_ostream(OS, Color, Colors); +- } +- +- /// \brief Check if an output directory has been specified. +- bool hasOutputDirectory() const { return !ShowOutputDirectory.empty(); } +- +- /// \brief Check if a demangler has been specified. +- bool hasDemangler() const { return !DemanglerOpts.empty(); } +- +- /// \brief Check if a project title has been specified. +- bool hasProjectTitle() const { return !ProjectTitle.empty(); } +- +- /// \brief Check if the created time of the profile data file is available. +- bool hasCreatedTime() const { return !CreatedTimeStr.empty(); } +- +- /// \brief Get the LLVM version string. +- std::string getLLVMVersionString() const { +- std::string VersionString = "Generated by llvm-cov -- llvm version "; +- VersionString += LLVM_VERSION_STRING; +- return VersionString; +- } +-}; +-} +- +-#endif // LLVM_COV_COVERAGEVIEWOPTIONS_H +diff --git a/tools/llvm-cov/RenderingSupport.h b/tools/llvm-cov/RenderingSupport.h +deleted file mode 100644 +index aa70fbc23e3..00000000000 +--- a/tools/llvm-cov/RenderingSupport.h ++++ /dev/null +@@ -1,61 +0,0 @@ +-//===- RenderingSupport.h - output stream rendering support functions ----===// +-// +-// The LLVM Compiler Infrastructure +-// +-// This file is distributed under the University of Illinois Open Source +-// License. See LICENSE.TXT for details. +-// +-//===----------------------------------------------------------------------===// +- +-#ifndef LLVM_COV_RENDERINGSUPPORT_H +-#define LLVM_COV_RENDERINGSUPPORT_H +- +-#include "llvm/Support/raw_ostream.h" +-#include +- +-namespace llvm { +- +-/// \brief A helper class that resets the output stream's color if needed +-/// when destroyed. +-class ColoredRawOstream { +- ColoredRawOstream(const ColoredRawOstream &OS) = delete; +- +-public: +- raw_ostream &OS; +- bool IsColorUsed; +- +- ColoredRawOstream(raw_ostream &OS, bool IsColorUsed) +- : OS(OS), IsColorUsed(IsColorUsed) {} +- +- ColoredRawOstream(ColoredRawOstream &&Other) +- : OS(Other.OS), IsColorUsed(Other.IsColorUsed) { +- // Reset the other IsColorUsed so that the other object won't reset the +- // color when destroyed. +- Other.IsColorUsed = false; +- } +- +- ~ColoredRawOstream() { +- if (IsColorUsed) +- OS.resetColor(); +- } +-}; +- +-template +-inline raw_ostream &operator<<(const ColoredRawOstream &OS, T &&Value) { +- return OS.OS << std::forward(Value); +-} +- +-/// \brief Change the color of the output stream if the `IsColorUsed` flag +-/// is true. Returns an object that resets the color when destroyed. +-inline ColoredRawOstream colored_ostream(raw_ostream &OS, +- raw_ostream::Colors Color, +- bool IsColorUsed = true, +- bool Bold = false, bool BG = false) { +- if (IsColorUsed) +- OS.changeColor(Color, Bold, BG); +- return ColoredRawOstream(OS, IsColorUsed); +-} +- +-} // namespace llvm +- +-#endif // LLVM_COV_RENDERINGSUPPORT_H +diff --git a/tools/llvm-cov/SourceCoverageView.cpp b/tools/llvm-cov/SourceCoverageView.cpp +index 52b8ff1747f..84c2cb7e8d6 100644 +--- a/tools/llvm-cov/SourceCoverageView.cpp ++++ b/tools/llvm-cov/SourceCoverageView.cpp +@@ -1,3 +1,4 @@ ++#if 0 + //===- SourceCoverageView.cpp - Code coverage view for source code --------===// + // + // The LLVM Compiler Infrastructure +@@ -265,3 +266,4 @@ void SourceCoverageView::print(raw_ostream &OS, bool WholeFile, + + renderViewFooter(OS); + } ++#endif +diff --git a/tools/llvm-cov/SourceCoverageView.h b/tools/llvm-cov/SourceCoverageView.h +deleted file mode 100644 +index 9cb608fed60..00000000000 +--- a/tools/llvm-cov/SourceCoverageView.h ++++ /dev/null +@@ -1,289 +0,0 @@ +-//===- SourceCoverageView.h - Code coverage view for source code ----------===// +-// +-// The LLVM Compiler Infrastructure +-// +-// This file is distributed under the University of Illinois Open Source +-// License. See LICENSE.TXT for details. +-// +-//===----------------------------------------------------------------------===// +-/// +-/// \file This class implements rendering for code coverage of source code. +-/// +-//===----------------------------------------------------------------------===// +- +-#ifndef LLVM_COV_SOURCECOVERAGEVIEW_H +-#define LLVM_COV_SOURCECOVERAGEVIEW_H +- +-#include "CoverageViewOptions.h" +-#include "llvm/ProfileData/Coverage/CoverageMapping.h" +-#include "llvm/Support/MemoryBuffer.h" +-#include +- +-namespace llvm { +- +-class SourceCoverageView; +- +-/// \brief A view that represents a macro or include expansion. +-struct ExpansionView { +- coverage::CounterMappingRegion Region; +- std::unique_ptr View; +- +- ExpansionView(const coverage::CounterMappingRegion &Region, +- std::unique_ptr View) +- : Region(Region), View(std::move(View)) {} +- ExpansionView(ExpansionView &&RHS) +- : Region(std::move(RHS.Region)), View(std::move(RHS.View)) {} +- ExpansionView &operator=(ExpansionView &&RHS) { +- Region = std::move(RHS.Region); +- View = std::move(RHS.View); +- return *this; +- } +- +- unsigned getLine() const { return Region.LineStart; } +- unsigned getStartCol() const { return Region.ColumnStart; } +- unsigned getEndCol() const { return Region.ColumnEnd; } +- +- friend bool operator<(const ExpansionView &LHS, const ExpansionView &RHS) { +- return LHS.Region.startLoc() < RHS.Region.startLoc(); +- } +-}; +- +-/// \brief A view that represents a function instantiation. +-struct InstantiationView { +- StringRef FunctionName; +- unsigned Line; +- std::unique_ptr View; +- +- InstantiationView(StringRef FunctionName, unsigned Line, +- std::unique_ptr View) +- : FunctionName(FunctionName), Line(Line), View(std::move(View)) {} +- +- friend bool operator<(const InstantiationView &LHS, +- const InstantiationView &RHS) { +- return LHS.Line < RHS.Line; +- } +-}; +- +-/// \brief Coverage statistics for a single line. +-struct LineCoverageStats { +- uint64_t ExecutionCount; +- unsigned RegionCount; +- bool Mapped; +- +- LineCoverageStats() : ExecutionCount(0), RegionCount(0), Mapped(false) {} +- +- bool isMapped() const { return Mapped; } +- +- bool hasMultipleRegions() const { return RegionCount > 1; } +- +- void addRegionStartCount(uint64_t Count) { +- // The max of all region starts is the most interesting value. +- addRegionCount(RegionCount ? std::max(ExecutionCount, Count) : Count); +- ++RegionCount; +- } +- +- void addRegionCount(uint64_t Count) { +- Mapped = true; +- ExecutionCount = Count; +- } +-}; +- +-/// \brief A file manager that handles format-aware file creation. +-class CoveragePrinter { +-public: +- struct StreamDestructor { +- void operator()(raw_ostream *OS) const; +- }; +- +- using OwnedStream = std::unique_ptr; +- +-protected: +- const CoverageViewOptions &Opts; +- +- CoveragePrinter(const CoverageViewOptions &Opts) : Opts(Opts) {} +- +- /// \brief Return `OutputDir/ToplevelDir/Path.Extension`. If \p InToplevel is +- /// false, skip the ToplevelDir component. If \p Relative is false, skip the +- /// OutputDir component. +- std::string getOutputPath(StringRef Path, StringRef Extension, +- bool InToplevel, bool Relative = true) const; +- +- /// \brief If directory output is enabled, create a file in that directory +- /// at the path given by getOutputPath(). Otherwise, return stdout. +- Expected createOutputStream(StringRef Path, StringRef Extension, +- bool InToplevel) const; +- +- /// \brief Return the sub-directory name for file coverage reports. +- static StringRef getCoverageDir() { return "coverage"; } +- +-public: +- static std::unique_ptr +- create(const CoverageViewOptions &Opts); +- +- virtual ~CoveragePrinter() {} +- +- /// @name File Creation Interface +- /// @{ +- +- /// \brief Create a file to print a coverage view into. +- virtual Expected createViewFile(StringRef Path, +- bool InToplevel) = 0; +- +- /// \brief Close a file which has been used to print a coverage view. +- virtual void closeViewFile(OwnedStream OS) = 0; +- +- /// \brief Create an index which lists reports for the given source files. +- virtual Error createIndexFile(ArrayRef SourceFiles, +- const coverage::CoverageMapping &Coverage) = 0; +- +- /// @} +-}; +- +-/// \brief A code coverage view of a source file or function. +-/// +-/// A source coverage view and its nested sub-views form a file-oriented +-/// representation of code coverage data. This view can be printed out by a +-/// renderer which implements the Rendering Interface. +-class SourceCoverageView { +- /// A function or file name. +- StringRef SourceName; +- +- /// A memory buffer backing the source on display. +- const MemoryBuffer &File; +- +- /// Various options to guide the coverage renderer. +- const CoverageViewOptions &Options; +- +- /// Complete coverage information about the source on display. +- coverage::CoverageData CoverageInfo; +- +- /// A container for all expansions (e.g macros) in the source on display. +- std::vector ExpansionSubViews; +- +- /// A container for all instantiations (e.g template functions) in the source +- /// on display. +- std::vector InstantiationSubViews; +- +- /// Get the first uncovered line number for the source file. +- unsigned getFirstUncoveredLineNo(); +- +-protected: +- struct LineRef { +- StringRef Line; +- int64_t LineNo; +- +- LineRef(StringRef Line, int64_t LineNo) : Line(Line), LineNo(LineNo) {} +- }; +- +- using CoverageSegmentArray = ArrayRef; +- +- /// @name Rendering Interface +- /// @{ +- +- /// \brief Render a header for the view. +- virtual void renderViewHeader(raw_ostream &OS) = 0; +- +- /// \brief Render a footer for the view. +- virtual void renderViewFooter(raw_ostream &OS) = 0; +- +- /// \brief Render the source name for the view. +- virtual void renderSourceName(raw_ostream &OS, bool WholeFile) = 0; +- +- /// \brief Render the line prefix at the given \p ViewDepth. +- virtual void renderLinePrefix(raw_ostream &OS, unsigned ViewDepth) = 0; +- +- /// \brief Render the line suffix at the given \p ViewDepth. +- virtual void renderLineSuffix(raw_ostream &OS, unsigned ViewDepth) = 0; +- +- /// \brief Render a view divider at the given \p ViewDepth. +- virtual void renderViewDivider(raw_ostream &OS, unsigned ViewDepth) = 0; +- +- /// \brief Render a source line with highlighting. +- virtual void renderLine(raw_ostream &OS, LineRef L, +- const coverage::CoverageSegment *WrappedSegment, +- CoverageSegmentArray Segments, unsigned ExpansionCol, +- unsigned ViewDepth) = 0; +- +- /// \brief Render the line's execution count column. +- virtual void renderLineCoverageColumn(raw_ostream &OS, +- const LineCoverageStats &Line) = 0; +- +- /// \brief Render the line number column. +- virtual void renderLineNumberColumn(raw_ostream &OS, unsigned LineNo) = 0; +- +- /// \brief Render all the region's execution counts on a line. +- virtual void renderRegionMarkers(raw_ostream &OS, +- CoverageSegmentArray Segments, +- unsigned ViewDepth) = 0; +- +- /// \brief Render the site of an expansion. +- virtual void +- renderExpansionSite(raw_ostream &OS, LineRef L, +- const coverage::CoverageSegment *WrappedSegment, +- CoverageSegmentArray Segments, unsigned ExpansionCol, +- unsigned ViewDepth) = 0; +- +- /// \brief Render an expansion view and any nested views. +- virtual void renderExpansionView(raw_ostream &OS, ExpansionView &ESV, +- unsigned ViewDepth) = 0; +- +- /// \brief Render an instantiation view and any nested views. +- virtual void renderInstantiationView(raw_ostream &OS, InstantiationView &ISV, +- unsigned ViewDepth) = 0; +- +- /// \brief Render \p Title, a project title if one is available, and the +- /// created time. +- virtual void renderTitle(raw_ostream &OS, StringRef CellText) = 0; +- +- /// \brief Render the table header for a given source file. +- virtual void renderTableHeader(raw_ostream &OS, unsigned FirstUncoveredLineNo, +- unsigned IndentLevel) = 0; +- +- /// @} +- +- /// \brief Format a count using engineering notation with 3 significant +- /// digits. +- static std::string formatCount(uint64_t N); +- +- /// \brief Check if region marker output is expected for a line. +- bool shouldRenderRegionMarkers(bool LineHasMultipleRegions) const; +- +- /// \brief Check if there are any sub-views attached to this view. +- bool hasSubViews() const; +- +- SourceCoverageView(StringRef SourceName, const MemoryBuffer &File, +- const CoverageViewOptions &Options, +- coverage::CoverageData &&CoverageInfo) +- : SourceName(SourceName), File(File), Options(Options), +- CoverageInfo(std::move(CoverageInfo)) {} +- +-public: +- static std::unique_ptr +- create(StringRef SourceName, const MemoryBuffer &File, +- const CoverageViewOptions &Options, +- coverage::CoverageData &&CoverageInfo); +- +- virtual ~SourceCoverageView() {} +- +- /// \brief Return the source name formatted for the host OS. +- std::string getSourceName() const; +- +- const CoverageViewOptions &getOptions() const { return Options; } +- +- /// \brief Add an expansion subview to this view. +- void addExpansion(const coverage::CounterMappingRegion &Region, +- std::unique_ptr View); +- +- /// \brief Add a function instantiation subview to this view. +- void addInstantiation(StringRef FunctionName, unsigned Line, +- std::unique_ptr View); +- +- /// \brief Print the code coverage information for a specific portion of a +- /// source file to the output stream. +- void print(raw_ostream &OS, bool WholeFile, bool ShowSourceName, +- unsigned ViewDepth = 0); +-}; +- +-} // namespace llvm +- +-#endif // LLVM_COV_SOURCECOVERAGEVIEW_H +diff --git a/tools/llvm-cov/SourceCoverageViewHTML.cpp b/tools/llvm-cov/SourceCoverageViewHTML.cpp +index 64b888e89d7..929b224b66b 100644 +--- a/tools/llvm-cov/SourceCoverageViewHTML.cpp ++++ b/tools/llvm-cov/SourceCoverageViewHTML.cpp +@@ -1,3 +1,4 @@ ++#if 0 + //===- SourceCoverageViewHTML.cpp - A html code coverage view -------------===// + // + // The LLVM Compiler Infrastructure +@@ -636,3 +637,5 @@ void SourceCoverageViewHTML::renderTableHeader(raw_ostream &OS, + << SourceLabel; + renderLineSuffix(OS, ViewDepth); + } ++ ++#endif +diff --git a/tools/llvm-cov/SourceCoverageViewHTML.h b/tools/llvm-cov/SourceCoverageViewHTML.h +deleted file mode 100644 +index 94b08a5e7fc..00000000000 +--- a/tools/llvm-cov/SourceCoverageViewHTML.h ++++ /dev/null +@@ -1,96 +0,0 @@ +-//===- SourceCoverageViewHTML.h - A html code coverage view ---------------===// +-// +-// The LLVM Compiler Infrastructure +-// +-// This file is distributed under the University of Illinois Open Source +-// License. See LICENSE.TXT for details. +-// +-//===----------------------------------------------------------------------===// +-/// +-/// \file This file defines the interface to the html coverage renderer. +-/// +-//===----------------------------------------------------------------------===// +- +-#ifndef LLVM_COV_SOURCECOVERAGEVIEWHTML_H +-#define LLVM_COV_SOURCECOVERAGEVIEWHTML_H +- +-#include "SourceCoverageView.h" +- +-namespace llvm { +- +-struct FileCoverageSummary; +- +-/// \brief A coverage printer for html output. +-class CoveragePrinterHTML : public CoveragePrinter { +-public: +- Expected createViewFile(StringRef Path, +- bool InToplevel) override; +- +- void closeViewFile(OwnedStream OS) override; +- +- Error createIndexFile(ArrayRef SourceFiles, +- const coverage::CoverageMapping &Coverage) override; +- +- CoveragePrinterHTML(const CoverageViewOptions &Opts) +- : CoveragePrinter(Opts) {} +- +-private: +- void emitFileSummary(raw_ostream &OS, StringRef SF, +- const FileCoverageSummary &FCS, +- bool IsTotals = false) const; +-}; +- +-/// \brief A code coverage view which supports html-based rendering. +-class SourceCoverageViewHTML : public SourceCoverageView { +- void renderViewHeader(raw_ostream &OS) override; +- +- void renderViewFooter(raw_ostream &OS) override; +- +- void renderSourceName(raw_ostream &OS, bool WholeFile) override; +- +- void renderLinePrefix(raw_ostream &OS, unsigned ViewDepth) override; +- +- void renderLineSuffix(raw_ostream &OS, unsigned ViewDepth) override; +- +- void renderViewDivider(raw_ostream &OS, unsigned ViewDepth) override; +- +- void renderLine(raw_ostream &OS, LineRef L, +- const coverage::CoverageSegment *WrappedSegment, +- CoverageSegmentArray Segments, unsigned ExpansionCol, +- unsigned ViewDepth) override; +- +- void renderExpansionSite(raw_ostream &OS, LineRef L, +- const coverage::CoverageSegment *WrappedSegment, +- CoverageSegmentArray Segments, unsigned ExpansionCol, +- unsigned ViewDepth) override; +- +- void renderExpansionView(raw_ostream &OS, ExpansionView &ESV, +- unsigned ViewDepth) override; +- +- void renderInstantiationView(raw_ostream &OS, InstantiationView &ISV, +- unsigned ViewDepth) override; +- +- void renderLineCoverageColumn(raw_ostream &OS, +- const LineCoverageStats &Line) override; +- +- void renderLineNumberColumn(raw_ostream &OS, unsigned LineNo) override; +- +- void renderRegionMarkers(raw_ostream &OS, CoverageSegmentArray Segments, +- unsigned ViewDepth) override; +- +- void renderTitle(raw_ostream &OS, StringRef Title) override; +- +- void renderTableHeader(raw_ostream &OS, unsigned FirstUncoveredLineNo, +- unsigned IndentLevel) override; +- +-public: +- SourceCoverageViewHTML(StringRef SourceName, const MemoryBuffer &File, +- const CoverageViewOptions &Options, +- coverage::CoverageData &&CoverageInfo) +- : SourceCoverageView(SourceName, File, Options, std::move(CoverageInfo)) { +- } +-}; +- +-} // namespace llvm +- +-#endif // LLVM_COV_SOURCECOVERAGEVIEWHTML_H +diff --git a/tools/llvm-cov/SourceCoverageViewText.cpp b/tools/llvm-cov/SourceCoverageViewText.cpp +index 4ad120f642e..03422a36a37 100644 +--- a/tools/llvm-cov/SourceCoverageViewText.cpp ++++ b/tools/llvm-cov/SourceCoverageViewText.cpp +@@ -1,3 +1,4 @@ ++#if 0 + //===- SourceCoverageViewText.cpp - A text-based code coverage view -------===// + // + // The LLVM Compiler Infrastructure +@@ -237,3 +238,5 @@ void SourceCoverageViewText::renderTitle(raw_ostream &OS, StringRef Title) { + + void SourceCoverageViewText::renderTableHeader(raw_ostream &, unsigned, + unsigned) {} ++ ++#endif +diff --git a/tools/llvm-cov/SourceCoverageViewText.h b/tools/llvm-cov/SourceCoverageViewText.h +deleted file mode 100644 +index c3f20de9297..00000000000 +--- a/tools/llvm-cov/SourceCoverageViewText.h ++++ /dev/null +@@ -1,89 +0,0 @@ +-//===- SourceCoverageViewText.h - A text-based code coverage view ---------===// +-// +-// The LLVM Compiler Infrastructure +-// +-// This file is distributed under the University of Illinois Open Source +-// License. See LICENSE.TXT for details. +-// +-//===----------------------------------------------------------------------===// +-/// +-/// \file This file defines the interface to the text-based coverage renderer. +-/// +-//===----------------------------------------------------------------------===// +- +-#ifndef LLVM_COV_SOURCECOVERAGEVIEWTEXT_H +-#define LLVM_COV_SOURCECOVERAGEVIEWTEXT_H +- +-#include "SourceCoverageView.h" +- +-namespace llvm { +- +-/// \brief A coverage printer for text output. +-class CoveragePrinterText : public CoveragePrinter { +-public: +- Expected createViewFile(StringRef Path, +- bool InToplevel) override; +- +- void closeViewFile(OwnedStream OS) override; +- +- Error createIndexFile(ArrayRef SourceFiles, +- const coverage::CoverageMapping &Coverage) override; +- +- CoveragePrinterText(const CoverageViewOptions &Opts) +- : CoveragePrinter(Opts) {} +-}; +- +-/// \brief A code coverage view which supports text-based rendering. +-class SourceCoverageViewText : public SourceCoverageView { +- void renderViewHeader(raw_ostream &OS) override; +- +- void renderViewFooter(raw_ostream &OS) override; +- +- void renderSourceName(raw_ostream &OS, bool WholeFile) override; +- +- void renderLinePrefix(raw_ostream &OS, unsigned ViewDepth) override; +- +- void renderLineSuffix(raw_ostream &OS, unsigned ViewDepth) override; +- +- void renderViewDivider(raw_ostream &OS, unsigned ViewDepth) override; +- +- void renderLine(raw_ostream &OS, LineRef L, +- const coverage::CoverageSegment *WrappedSegment, +- CoverageSegmentArray Segments, unsigned ExpansionCol, +- unsigned ViewDepth) override; +- +- void renderExpansionSite(raw_ostream &OS, LineRef L, +- const coverage::CoverageSegment *WrappedSegment, +- CoverageSegmentArray Segments, unsigned ExpansionCol, +- unsigned ViewDepth) override; +- +- void renderExpansionView(raw_ostream &OS, ExpansionView &ESV, +- unsigned ViewDepth) override; +- +- void renderInstantiationView(raw_ostream &OS, InstantiationView &ISV, +- unsigned ViewDepth) override; +- +- void renderLineCoverageColumn(raw_ostream &OS, +- const LineCoverageStats &Line) override; +- +- void renderLineNumberColumn(raw_ostream &OS, unsigned LineNo) override; +- +- void renderRegionMarkers(raw_ostream &OS, CoverageSegmentArray Segments, +- unsigned ViewDepth) override; +- +- void renderTitle(raw_ostream &OS, StringRef Title) override; +- +- void renderTableHeader(raw_ostream &OS, unsigned FirstUncoveredLineNo, +- unsigned IndentLevel) override; +- +-public: +- SourceCoverageViewText(StringRef SourceName, const MemoryBuffer &File, +- const CoverageViewOptions &Options, +- coverage::CoverageData &&CoverageInfo) +- : SourceCoverageView(SourceName, File, Options, std::move(CoverageInfo)) { +- } +-}; +- +-} // namespace llvm +- +-#endif // LLVM_COV_SOURCECOVERAGEVIEWTEXT_H +diff --git a/tools/llvm-cov/TestingSupport.cpp b/tools/llvm-cov/TestingSupport.cpp +index 4713d75f17d..5c2916220dc 100644 +--- a/tools/llvm-cov/TestingSupport.cpp ++++ b/tools/llvm-cov/TestingSupport.cpp +@@ -1,3 +1,4 @@ ++#if 0 + //===- TestingSupport.cpp - Convert objects files into test files --------===// + // + // The LLVM Compiler Infrastructure +@@ -93,3 +94,4 @@ int convertForTestingMain(int argc, const char *argv[]) { + + return 0; + } ++#endif +diff --git a/tools/llvm-cov/gcov.cpp b/tools/llvm-cov/gcov.cpp +index 4df7f015fd1..7790789b522 100644 +--- a/tools/llvm-cov/gcov.cpp ++++ b/tools/llvm-cov/gcov.cpp +@@ -1,3 +1,4 @@ ++#if 0 + //===- gcov.cpp - GCOV compatible LLVM coverage tool ----------------------===// + // + // The LLVM Compiler Infrastructure +@@ -143,3 +144,4 @@ int gcovMain(int argc, const char *argv[]) { + Options); + return 0; + } ++#endif +diff --git a/tools/llvm-cov/llvm-cov.cpp b/tools/llvm-cov/llvm-cov.cpp +index 15841587025..5103688cd7c 100644 +--- a/tools/llvm-cov/llvm-cov.cpp ++++ b/tools/llvm-cov/llvm-cov.cpp +@@ -11,6 +11,7 @@ + // + //===----------------------------------------------------------------------===// + ++#if 0 + #include "llvm/ADT/StringRef.h" + #include "llvm/ADT/StringSwitch.h" + #include "llvm/Support/CommandLine.h" +@@ -57,8 +58,10 @@ static int versionMain(int argc, const char *argv[]) { + cl::PrintVersionMessage(); + return 0; + } ++#endif + + int main(int argc, const char **argv) { ++#if 0 + // Print a stack trace if we signal out. + sys::PrintStackTraceOnErrorSignal(argv[0]); + PrettyStackTraceProgram X(argc, argv); +@@ -96,5 +99,6 @@ int main(int argc, const char **argv) { + errs().resetColor(); + } + helpMain(argc, argv); ++#endif + return 1; + } +diff --git a/tools/llvm-profdata/llvm-profdata.cpp b/tools/llvm-profdata/llvm-profdata.cpp +index eee242107da..595dc0e2c64 100644 +--- a/tools/llvm-profdata/llvm-profdata.cpp ++++ b/tools/llvm-profdata/llvm-profdata.cpp +@@ -11,6 +11,8 @@ + // + //===----------------------------------------------------------------------===// + ++#if 0 ++ + #include "llvm/ADT/SmallSet.h" + #include "llvm/ADT/SmallVector.h" + #include "llvm/ADT/StringRef.h" +@@ -754,8 +756,10 @@ static int show_main(int argc, const char *argv[]) { + return showSampleProfile(Filename, ShowCounts, ShowAllFunctions, + ShowFunction, OS); + } ++#endif + + int main(int argc, const char *argv[]) { ++#if 0 + // Print a stack trace if we signal out. + sys::PrintStackTraceOnErrorSignal(argv[0]); + PrettyStackTraceProgram X(argc, argv); +@@ -794,5 +798,6 @@ int main(int argc, const char *argv[]) { + errs() << ProgName << ": Unknown command!\n"; + + errs() << "USAGE: " << ProgName << " [args...]\n"; ++#endif + return 1; + } +diff --git a/tools/sancov/sancov.cc b/tools/sancov/sancov.cc +index 7f103ebb904..31de719f8c8 100644 +--- a/tools/sancov/sancov.cc ++++ b/tools/sancov/sancov.cc +@@ -10,6 +10,7 @@ + // This file is a command-line tool for reading and analyzing sanitizer + // coverage. + //===----------------------------------------------------------------------===// ++#if 0 + #include "llvm/ADT/STLExtras.h" + #include "llvm/ADT/StringExtras.h" + #include "llvm/ADT/Twine.h" +@@ -1199,8 +1200,10 @@ readSymbolizeAndMergeCmdArguments(std::vector FileNames) { + } + + } // namespace ++#endif + + int main(int Argc, char **Argv) { ++#if 0 + // Print stack trace if we signal out. + sys::PrintStackTraceOnErrorSignal(Argv[0]); + PrettyStackTraceProgram X(Argc, Argv); +@@ -1264,4 +1267,6 @@ int main(int Argc, char **Argv) { + case PrintCovPointsAction: + llvm_unreachable("unsupported action"); + } ++#endif ++ return 1; + } +diff --git a/unittests/Support/ThreadPool.cpp b/unittests/Support/ThreadPool.cpp +index 0da33ad50c0..50287484f29 100644 +--- a/unittests/Support/ThreadPool.cpp ++++ b/unittests/Support/ThreadPool.cpp +@@ -7,6 +7,8 @@ + // + //===----------------------------------------------------------------------===// + ++#if 0 ++ + #include "llvm/Support/ThreadPool.h" + + #include "llvm/ADT/STLExtras.h" +@@ -164,3 +166,5 @@ TEST_F(ThreadPoolTest, PoolDestruction) { + } + ASSERT_EQ(5, checked_in); + } ++ ++#endif +-- +2.14.1 + diff --git a/deps/patches/llvm-D23597_sdag_names.patch b/deps/patches/llvm-D23597_sdag_names.patch new file mode 100644 index 0000000000000..9eea510f7d62f --- /dev/null +++ b/deps/patches/llvm-D23597_sdag_names.patch @@ -0,0 +1,796 @@ +Index: include/llvm/Target/TargetSelectionDAG.td +=================================================================== +--- a/include/llvm/Target/TargetSelectionDAG.td ++++ b/include/llvm/Target/TargetSelectionDAG.td +@@ -450,10 +450,10 @@ + def fceil : SDNode<"ISD::FCEIL" , SDTFPUnaryOp>; + def ffloor : SDNode<"ISD::FFLOOR" , SDTFPUnaryOp>; + def fnearbyint : SDNode<"ISD::FNEARBYINT" , SDTFPUnaryOp>; +-def frnd : SDNode<"ISD::FROUND" , SDTFPUnaryOp>; ++def fround : SDNode<"ISD::FROUND" , SDTFPUnaryOp>; + +-def fround : SDNode<"ISD::FP_ROUND" , SDTFPRoundOp>; +-def fextend : SDNode<"ISD::FP_EXTEND" , SDTFPExtendOp>; ++def fpround : SDNode<"ISD::FP_ROUND" , SDTFPRoundOp>; ++def fpextend : SDNode<"ISD::FP_EXTEND" , SDTFPExtendOp>; + def fcopysign : SDNode<"ISD::FCOPYSIGN" , SDTFPSignOp>; + + def sint_to_fp : SDNode<"ISD::SINT_TO_FP" , SDTIntToFPOp>; +Index: lib/Target/AArch64/AArch64InstrFormats.td +=================================================================== +--- a/lib/Target/AArch64/AArch64InstrFormats.td ++++ b/lib/Target/AArch64/AArch64InstrFormats.td +@@ -3936,27 +3936,27 @@ + multiclass FPConversion { + // Double-precision to Half-precision + def HDr : BaseFPConversion<0b01, 0b11, FPR16, FPR64, asm, +- [(set FPR16:$Rd, (fround FPR64:$Rn))]>; ++ [(set FPR16:$Rd, (fpround FPR64:$Rn))]>; + + // Double-precision to Single-precision + def SDr : BaseFPConversion<0b01, 0b00, FPR32, FPR64, asm, +- [(set FPR32:$Rd, (fround FPR64:$Rn))]>; ++ [(set FPR32:$Rd, (fpround FPR64:$Rn))]>; + + // Half-precision to Double-precision + def DHr : BaseFPConversion<0b11, 0b01, FPR64, FPR16, asm, +- [(set FPR64:$Rd, (fextend FPR16:$Rn))]>; ++ [(set FPR64:$Rd, (fpextend FPR16:$Rn))]>; + + // Half-precision to Single-precision + def SHr : BaseFPConversion<0b11, 0b00, FPR32, FPR16, asm, +- [(set FPR32:$Rd, (fextend FPR16:$Rn))]>; ++ [(set FPR32:$Rd, (fpextend FPR16:$Rn))]>; + + // Single-precision to Double-precision + def DSr : BaseFPConversion<0b00, 0b01, FPR64, FPR32, asm, +- [(set FPR64:$Rd, (fextend FPR32:$Rn))]>; ++ [(set FPR64:$Rd, (fpextend FPR32:$Rn))]>; + + // Single-precision to Half-precision + def HSr : BaseFPConversion<0b00, 0b11, FPR16, FPR32, asm, +- [(set FPR16:$Rd, (fround FPR32:$Rn))]>; ++ [(set FPR16:$Rd, (fpround FPR32:$Rn))]>; + } + + //--- +Index: lib/Target/AArch64/AArch64InstrInfo.td +=================================================================== +--- a/lib/Target/AArch64/AArch64InstrInfo.td ++++ b/lib/Target/AArch64/AArch64InstrInfo.td +@@ -2545,8 +2545,8 @@ + defm : FPToIntegerPats; + defm : FPToIntegerPats; + defm : FPToIntegerPats; +-defm : FPToIntegerPats; +-defm : FPToIntegerPats; ++defm : FPToIntegerPats; ++defm : FPToIntegerPats; + + //===----------------------------------------------------------------------===// + // Scaled integer to floating point conversion instructions. +@@ -2582,7 +2582,7 @@ + defm FABS : SingleOperandFPData<0b0001, "fabs", fabs>; + defm FMOV : SingleOperandFPData<0b0000, "fmov">; + defm FNEG : SingleOperandFPData<0b0010, "fneg", fneg>; +-defm FRINTA : SingleOperandFPData<0b1100, "frinta", frnd>; ++defm FRINTA : SingleOperandFPData<0b1100, "frinta", fround>; + defm FRINTI : SingleOperandFPData<0b1111, "frinti", fnearbyint>; + defm FRINTM : SingleOperandFPData<0b1010, "frintm", ffloor>; + defm FRINTN : SingleOperandFPData<0b1000, "frintn", int_aarch64_neon_frintn>; +@@ -2788,13 +2788,13 @@ + def : Pat<(v4f32 (int_aarch64_neon_vcvthf2fp (extract_subvector (v8i16 V128:$Rn), + (i64 4)))), + (FCVTLv8i16 V128:$Rn)>; +-def : Pat<(v2f64 (fextend (v2f32 V64:$Rn))), (FCVTLv2i32 V64:$Rn)>; +-def : Pat<(v2f64 (fextend (v2f32 (extract_subvector (v4f32 V128:$Rn), ++def : Pat<(v2f64 (fpextend (v2f32 V64:$Rn))), (FCVTLv2i32 V64:$Rn)>; ++def : Pat<(v2f64 (fpextend (v2f32 (extract_subvector (v4f32 V128:$Rn), + (i64 2))))), + (FCVTLv4i32 V128:$Rn)>; + +-def : Pat<(v4f32 (fextend (v4f16 V64:$Rn))), (FCVTLv4i16 V64:$Rn)>; +-def : Pat<(v4f32 (fextend (v4f16 (extract_subvector (v8f16 V128:$Rn), ++def : Pat<(v4f32 (fpextend (v4f16 V64:$Rn))), (FCVTLv4i16 V64:$Rn)>; ++def : Pat<(v4f32 (fpextend (v4f16 (extract_subvector (v8f16 V128:$Rn), + (i64 4))))), + (FCVTLv8i16 V128:$Rn)>; + +@@ -2808,9 +2808,9 @@ + def : Pat<(concat_vectors V64:$Rd, + (v4i16 (int_aarch64_neon_vcvtfp2hf (v4f32 V128:$Rn)))), + (FCVTNv8i16 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>; +-def : Pat<(v2f32 (fround (v2f64 V128:$Rn))), (FCVTNv2i32 V128:$Rn)>; +-def : Pat<(v4f16 (fround (v4f32 V128:$Rn))), (FCVTNv4i16 V128:$Rn)>; +-def : Pat<(concat_vectors V64:$Rd, (v2f32 (fround (v2f64 V128:$Rn)))), ++def : Pat<(v2f32 (fpround (v2f64 V128:$Rn))), (FCVTNv2i32 V128:$Rn)>; ++def : Pat<(v4f16 (fpround (v4f32 V128:$Rn))), (FCVTNv4i16 V128:$Rn)>; ++def : Pat<(concat_vectors V64:$Rd, (v2f32 (fpround (v2f64 V128:$Rn)))), + (FCVTNv4i32 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>; + defm FCVTPS : SIMDTwoVectorFPToInt<0,1,0b11010, "fcvtps",int_aarch64_neon_fcvtps>; + defm FCVTPU : SIMDTwoVectorFPToInt<1,1,0b11010, "fcvtpu",int_aarch64_neon_fcvtpu>; +@@ -2833,7 +2833,7 @@ + + defm FNEG : SIMDTwoVectorFP<1, 1, 0b01111, "fneg", fneg>; + defm FRECPE : SIMDTwoVectorFP<0, 1, 0b11101, "frecpe", int_aarch64_neon_frecpe>; +-defm FRINTA : SIMDTwoVectorFP<1, 0, 0b11000, "frinta", frnd>; ++defm FRINTA : SIMDTwoVectorFP<1, 0, 0b11000, "frinta", fround>; + defm FRINTI : SIMDTwoVectorFP<1, 1, 0b11001, "frinti", fnearbyint>; + defm FRINTM : SIMDTwoVectorFP<0, 0, 0b11001, "frintm", ffloor>; + defm FRINTN : SIMDTwoVectorFP<0, 0, 0b11000, "frintn", int_aarch64_neon_frintn>; +Index: lib/Target/AMDGPU/SIInstructions.td +=================================================================== +--- a/lib/Target/AMDGPU/SIInstructions.td ++++ b/lib/Target/AMDGPU/SIInstructions.td +@@ -1107,10 +1107,10 @@ + VOP_I32_F32, cvt_flr_i32_f32>; + defm V_CVT_OFF_F32_I4 : VOP1Inst , "v_cvt_off_f32_i4", VOP_F32_I32>; + defm V_CVT_F32_F64 : VOP1Inst , "v_cvt_f32_f64", +- VOP_F32_F64, fround ++ VOP_F32_F64, fpround + >; + defm V_CVT_F64_F32 : VOP1Inst , "v_cvt_f64_f32", +- VOP_F64_F32, fextend ++ VOP_F64_F32, fpextend + >; + defm V_CVT_F32_UBYTE0 : VOP1Inst , "v_cvt_f32_ubyte0", + VOP_F32_I32, AMDGPUcvt_f32_ubyte0 +Index: lib/Target/ARM/ARMInstrVFP.td +=================================================================== +--- a/lib/Target/ARM/ARMInstrVFP.td ++++ b/lib/Target/ARM/ARMInstrVFP.td +@@ -624,7 +624,7 @@ + def VCVTDS : ASuI<0b11101, 0b11, 0b0111, 0b11, 0, + (outs DPR:$Dd), (ins SPR:$Sm), + IIC_fpCVTDS, "vcvt", ".f64.f32\t$Dd, $Sm", +- [(set DPR:$Dd, (fextend SPR:$Sm))]> { ++ [(set DPR:$Dd, (fpextend SPR:$Sm))]> { + // Instruction operands. + bits<5> Dd; + bits<5> Sm; +@@ -641,7 +641,7 @@ + // Special case encoding: bits 11-8 is 0b1011. + def VCVTSD : VFPAI<(outs SPR:$Sd), (ins DPR:$Dm), VFPUnaryFrm, + IIC_fpCVTSD, "vcvt", ".f32.f64\t$Sd, $Dm", +- [(set SPR:$Sd, (fround DPR:$Dm))]> { ++ [(set SPR:$Sd, (fpround DPR:$Dm))]> { + // Instruction operands. + bits<5> Sd; + bits<5> Dm; +@@ -838,7 +838,7 @@ + } + } + +-defm VCVTA : vcvt_inst<"a", 0b00, frnd>; ++defm VCVTA : vcvt_inst<"a", 0b00, fround>; + defm VCVTN : vcvt_inst<"n", 0b01>; + defm VCVTP : vcvt_inst<"p", 0b10, fceil>; + defm VCVTM : vcvt_inst<"m", 0b11, ffloor>; +@@ -938,7 +938,7 @@ + Requires<[HasFPARMv8,HasDPVFP]>; + } + +-defm VRINTA : vrint_inst_anpm<"a", 0b00, frnd>; ++defm VRINTA : vrint_inst_anpm<"a", 0b00, fround>; + defm VRINTN : vrint_inst_anpm<"n", 0b01>; + defm VRINTP : vrint_inst_anpm<"p", 0b10, fceil>; + defm VRINTM : vrint_inst_anpm<"m", 0b11, ffloor>; +Index: lib/Target/Hexagon/HexagonISelLowering.cpp +=================================================================== +--- a/lib/Target/Hexagon/HexagonISelLowering.cpp ++++ b/lib/Target/Hexagon/HexagonISelLowering.cpp +@@ -1906,7 +1906,7 @@ + } + // Turn FP truncstore into trunc + store. + setTruncStoreAction(MVT::f64, MVT::f32, Expand); +- // Turn FP extload into load/fextend. ++ // Turn FP extload into load/fpextend. + for (MVT VT : MVT::fp_valuetypes()) + setLoadExtAction(ISD::EXTLOAD, VT, MVT::f32, Expand); + +Index: lib/Target/Hexagon/HexagonInstrInfoV5.td +=================================================================== +--- a/lib/Target/Hexagon/HexagonInstrInfoV5.td ++++ b/lib/Target/Hexagon/HexagonInstrInfoV5.td +@@ -564,10 +564,10 @@ + + // Convert single precision to double precision and vice-versa. + def F2_conv_sf2df : F2_RDD_RS_CONVERT <"convert_sf2df", 0b000, +- fextend, F64, F32>; ++ fpextend, F64, F32>; + + def F2_conv_df2sf : F2_RD_RSS_CONVERT <"convert_df2sf", 0b000, +- fround, F32, F64>; ++ fpround, F32, F64>; + + // Convert Integer to Floating Point. + def F2_conv_d2sf : F2_RD_RSS_CONVERT <"convert_d2sf", 0b010, +Index: lib/Target/Mips/MipsInstrFPU.td +=================================================================== +--- a/lib/Target/Mips/MipsInstrFPU.td ++++ b/lib/Target/Mips/MipsInstrFPU.td +@@ -635,9 +635,9 @@ + (PseudoCVT_D32_W GPR32Opnd:$src)>, FGR_32; + def : MipsPat<(MipsTruncIntFP AFGR64Opnd:$src), + (TRUNC_W_D32 AFGR64Opnd:$src)>, FGR_32; +-def : MipsPat<(f32 (fround AFGR64Opnd:$src)), ++def : MipsPat<(f32 (fpround AFGR64Opnd:$src)), + (CVT_S_D32 AFGR64Opnd:$src)>, FGR_32; +-def : MipsPat<(f64 (fextend FGR32Opnd:$src)), ++def : MipsPat<(f64 (fpextend FGR32Opnd:$src)), + (CVT_D32_S FGR32Opnd:$src)>, FGR_32; + + def : MipsPat<(f64 fpimm0), (DMTC1 ZERO_64)>, FGR_64; +@@ -657,9 +657,9 @@ + def : MipsPat<(MipsTruncIntFP FGR64Opnd:$src), + (TRUNC_L_D64 FGR64Opnd:$src)>, FGR_64; + +-def : MipsPat<(f32 (fround FGR64Opnd:$src)), ++def : MipsPat<(f32 (fpround FGR64Opnd:$src)), + (CVT_S_D64 FGR64Opnd:$src)>, FGR_64; +-def : MipsPat<(f64 (fextend FGR32Opnd:$src)), ++def : MipsPat<(f64 (fpextend FGR32Opnd:$src)), + (CVT_D64_S FGR32Opnd:$src)>, FGR_64; + + // Patterns for loads/stores with a reg+imm operand. +Index: lib/Target/NVPTX/NVPTXISelLowering.cpp +=================================================================== +--- a/lib/Target/NVPTX/NVPTXISelLowering.cpp ++++ b/lib/Target/NVPTX/NVPTXISelLowering.cpp +@@ -206,7 +206,7 @@ + // intrinsics. + setOperationAction(ISD::INTRINSIC_W_CHAIN, MVT::Other, Custom); + +- // Turn FP extload into load/fextend ++ // Turn FP extload into load/fpextend + setLoadExtAction(ISD::EXTLOAD, MVT::f32, MVT::f16, Expand); + setLoadExtAction(ISD::EXTLOAD, MVT::f64, MVT::f16, Expand); + setLoadExtAction(ISD::EXTLOAD, MVT::f64, MVT::f32, Expand); +Index: lib/Target/NVPTX/NVPTXInstrInfo.td +=================================================================== +--- a/lib/Target/NVPTX/NVPTXInstrInfo.td ++++ b/lib/Target/NVPTX/NVPTXInstrInfo.td +@@ -2613,16 +2613,16 @@ + def : Pat<(ctpop Int16Regs:$a), + (CVT_u16_u32 (POPCr32 (CVT_u32_u16 Int16Regs:$a, CvtNONE)), CvtNONE)>; + +-// fround f64 -> f32 +-def : Pat<(f32 (fround Float64Regs:$a)), ++// fpround f64 -> f32 ++def : Pat<(f32 (fpround Float64Regs:$a)), + (CVT_f32_f64 Float64Regs:$a, CvtRN_FTZ)>, Requires<[doF32FTZ]>; +-def : Pat<(f32 (fround Float64Regs:$a)), ++def : Pat<(f32 (fpround Float64Regs:$a)), + (CVT_f32_f64 Float64Regs:$a, CvtRN)>; + +-// fextend f32 -> f64 +-def : Pat<(f64 (fextend Float32Regs:$a)), ++// fpextend f32 -> f64 ++def : Pat<(f64 (fpextend Float32Regs:$a)), + (CVT_f64_f32 Float32Regs:$a, CvtNONE_FTZ)>, Requires<[doF32FTZ]>; +-def : Pat<(f64 (fextend Float32Regs:$a)), ++def : Pat<(f64 (fpextend Float32Regs:$a)), + (CVT_f64_f32 Float32Regs:$a, CvtNONE)>; + + def retflag : SDNode<"NVPTXISD::RET_FLAG", SDTNone, +Index: lib/Target/PowerPC/PPCInstrInfo.td +=================================================================== +--- a/lib/Target/PowerPC/PPCInstrInfo.td ++++ b/lib/Target/PowerPC/PPCInstrInfo.td +@@ -2110,15 +2110,15 @@ + + defm FRSP : XForm_26r<63, 12, (outs f4rc:$frD), (ins f8rc:$frB), + "frsp", "$frD, $frB", IIC_FPGeneral, +- [(set f32:$frD, (fround f64:$frB))]>; ++ [(set f32:$frD, (fpround f64:$frB))]>; + + let Interpretation64Bit = 1, isCodeGenOnly = 1 in + defm FRIND : XForm_26r<63, 392, (outs f8rc:$frD), (ins f8rc:$frB), + "frin", "$frD, $frB", IIC_FPGeneral, +- [(set f64:$frD, (frnd f64:$frB))]>; ++ [(set f64:$frD, (fround f64:$frB))]>; + defm FRINS : XForm_26r<63, 392, (outs f4rc:$frD), (ins f4rc:$frB), + "frin", "$frD, $frB", IIC_FPGeneral, +- [(set f32:$frD, (frnd f32:$frB))]>; ++ [(set f32:$frD, (fround f32:$frB))]>; + } + + let hasSideEffects = 0 in { +@@ -2856,7 +2856,7 @@ + def : Pat<(f64 (extloadf32 xaddr:$src)), + (COPY_TO_REGCLASS (LFSX xaddr:$src), F8RC)>; + +-def : Pat<(f64 (fextend f32:$src)), ++def : Pat<(f64 (fpextend f32:$src)), + (COPY_TO_REGCLASS $src, F8RC)>; + + // Only seq_cst fences require the heavyweight sync (SYNC 0). +Index: lib/Target/PowerPC/PPCInstrQPX.td +=================================================================== +--- a/lib/Target/PowerPC/PPCInstrQPX.td ++++ b/lib/Target/PowerPC/PPCInstrQPX.td +@@ -88,11 +88,11 @@ + return cast(N)->getMemoryVT() == MVT::v4f32; + }]>; + +-def fround_inexact : PatFrag<(ops node:$val), (fround node:$val), [{ ++def fround_inexact : PatFrag<(ops node:$val), (fpround node:$val), [{ + return cast(N->getOperand(1))->getZExtValue() == 0; + }]>; + +-def fround_exact : PatFrag<(ops node:$val), (fround node:$val), [{ ++def fround_exact : PatFrag<(ops node:$val), (fpround node:$val), [{ + return cast(N->getOperand(1))->getZExtValue() == 1; + }]>; + +@@ -311,11 +311,11 @@ + + def QVFRIN : XForm_19<4, 392, (outs qfrc:$FRT), (ins qfrc:$FRB), + "qvfrin $FRT, $FRB", IIC_FPGeneral, +- [(set v4f64:$FRT, (frnd v4f64:$FRB))]>; ++ [(set v4f64:$FRT, (fround v4f64:$FRB))]>; + let isCodeGenOnly = 1 in + def QVFRINs : XForm_19<4, 392, (outs qsrc:$FRT), (ins qsrc:$FRB), + "qvfrin $FRT, $FRB", IIC_FPGeneral, +- [(set v4f32:$FRT, (frnd v4f32:$FRB))]>; ++ [(set v4f32:$FRT, (fround v4f32:$FRB))]>; + + def QVFRIP : XForm_19<4, 456, (outs qfrc:$FRT), (ins qfrc:$FRB), + "qvfrip $FRT, $FRB", IIC_FPGeneral, +@@ -1103,7 +1103,7 @@ + def : Pat<(not v4i1:$FRA), + (QVFLOGICALb $FRA, $FRA, (i32 10))>; + +-def : Pat<(v4f64 (fextend v4f32:$src)), ++def : Pat<(v4f64 (fpextend v4f32:$src)), + (COPY_TO_REGCLASS $src, QFRC)>; + + def : Pat<(v4f32 (fround_exact v4f64:$src)), +Index: lib/Target/PowerPC/PPCInstrVSX.td +=================================================================== +--- a/lib/Target/PowerPC/PPCInstrVSX.td ++++ b/lib/Target/PowerPC/PPCInstrVSX.td +@@ -634,7 +634,7 @@ + def XSRDPI : XX2Form<60, 73, + (outs vsfrc:$XT), (ins vsfrc:$XB), + "xsrdpi $XT, $XB", IIC_VecFP, +- [(set f64:$XT, (frnd f64:$XB))]>; ++ [(set f64:$XT, (fround f64:$XB))]>; + def XSRDPIC : XX2Form<60, 107, + (outs vsfrc:$XT), (ins vsfrc:$XB), + "xsrdpic $XT, $XB", IIC_VecFP, +@@ -655,7 +655,7 @@ + def XVRDPI : XX2Form<60, 201, + (outs vsrc:$XT), (ins vsrc:$XB), + "xvrdpi $XT, $XB", IIC_VecFP, +- [(set v2f64:$XT, (frnd v2f64:$XB))]>; ++ [(set v2f64:$XT, (fround v2f64:$XB))]>; + def XVRDPIC : XX2Form<60, 235, + (outs vsrc:$XT), (ins vsrc:$XB), + "xvrdpic $XT, $XB", IIC_VecFP, +@@ -676,7 +676,7 @@ + def XVRSPI : XX2Form<60, 137, + (outs vsrc:$XT), (ins vsrc:$XB), + "xvrspi $XT, $XB", IIC_VecFP, +- [(set v4f32:$XT, (frnd v4f32:$XB))]>; ++ [(set v4f32:$XT, (fround v4f32:$XB))]>; + def XVRSPIC : XX2Form<60, 171, + (outs vsrc:$XT), (ins vsrc:$XB), + "xvrspic $XT, $XB", IIC_VecFP, +@@ -1108,7 +1108,7 @@ + + def : Pat<(f64 (extloadf32 xoaddr:$src)), + (COPY_TO_REGCLASS (LXSSPX xoaddr:$src), VSFRC)>; +- def : Pat<(f64 (fextend f32:$src)), ++ def : Pat<(f64 (fpextend f32:$src)), + (COPY_TO_REGCLASS $src, VSFRC)>; + + def : Pat<(f32 (selectcc i1:$lhs, i1:$rhs, f32:$tval, f32:$fval, SETLT)), +Index: lib/Target/Sparc/SparcISelLowering.cpp +=================================================================== +--- a/lib/Target/Sparc/SparcISelLowering.cpp ++++ b/lib/Target/Sparc/SparcISelLowering.cpp +@@ -1508,7 +1508,7 @@ + // AddPromotedToType(ISD::STORE, MVT::i64, MVT::v2i32); + } + +- // Turn FP extload into load/fextend ++ // Turn FP extload into load/fpextend + for (MVT VT : MVT::fp_valuetypes()) { + setLoadExtAction(ISD::EXTLOAD, VT, MVT::f32, Expand); + setLoadExtAction(ISD::EXTLOAD, VT, MVT::f64, Expand); +Index: lib/Target/Sparc/SparcInstrInfo.td +=================================================================== +--- a/lib/Target/Sparc/SparcInstrInfo.td ++++ b/lib/Target/Sparc/SparcInstrInfo.td +@@ -1131,32 +1131,32 @@ + def FSTOD : F3_3u<2, 0b110100, 0b011001001, + (outs DFPRegs:$rd), (ins FPRegs:$rs2), + "fstod $rs2, $rd", +- [(set f64:$rd, (fextend f32:$rs2))], ++ [(set f64:$rd, (fpextend f32:$rs2))], + IIC_fpu_stod>; + def FSTOQ : F3_3u<2, 0b110100, 0b011001101, + (outs QFPRegs:$rd), (ins FPRegs:$rs2), + "fstoq $rs2, $rd", +- [(set f128:$rd, (fextend f32:$rs2))]>, ++ [(set f128:$rd, (fpextend f32:$rs2))]>, + Requires<[HasHardQuad]>; + def FDTOS : F3_3u<2, 0b110100, 0b011000110, + (outs FPRegs:$rd), (ins DFPRegs:$rs2), + "fdtos $rs2, $rd", +- [(set f32:$rd, (fround f64:$rs2))], ++ [(set f32:$rd, (fpround f64:$rs2))], + IIC_fpu_fast_instr>; + def FDTOQ : F3_3u<2, 0b110100, 0b011001110, + (outs QFPRegs:$rd), (ins DFPRegs:$rs2), + "fdtoq $rs2, $rd", +- [(set f128:$rd, (fextend f64:$rs2))]>, ++ [(set f128:$rd, (fpextend f64:$rs2))]>, + Requires<[HasHardQuad]>; + def FQTOS : F3_3u<2, 0b110100, 0b011000111, + (outs FPRegs:$rd), (ins QFPRegs:$rs2), + "fqtos $rs2, $rd", +- [(set f32:$rd, (fround f128:$rs2))]>, ++ [(set f32:$rd, (fpround f128:$rs2))]>, + Requires<[HasHardQuad]>; + def FQTOD : F3_3u<2, 0b110100, 0b011001011, + (outs DFPRegs:$rd), (ins QFPRegs:$rs2), + "fqtod $rs2, $rd", +- [(set f64:$rd, (fround f128:$rs2))]>, ++ [(set f64:$rd, (fpround f128:$rs2))]>, + Requires<[HasHardQuad]>; + + // Floating-point Move Instructions, p. 144 +@@ -1255,14 +1255,14 @@ + def FSMULD : F3_3<2, 0b110100, 0b001101001, + (outs DFPRegs:$rd), (ins FPRegs:$rs1, FPRegs:$rs2), + "fsmuld $rs1, $rs2, $rd", +- [(set f64:$rd, (fmul (fextend f32:$rs1), +- (fextend f32:$rs2)))], ++ [(set f64:$rd, (fmul (fpextend f32:$rs1), ++ (fpextend f32:$rs2)))], + IIC_fpu_muld>; + def FDMULQ : F3_3<2, 0b110100, 0b001101110, + (outs QFPRegs:$rd), (ins DFPRegs:$rs1, DFPRegs:$rs2), + "fdmulq $rs1, $rs2, $rd", +- [(set f128:$rd, (fmul (fextend f64:$rs1), +- (fextend f64:$rs2)))]>, ++ [(set f128:$rd, (fmul (fpextend f64:$rs1), ++ (fpextend f64:$rs2)))]>, + Requires<[HasHardQuad]>; + + // FDIVS generates an erratum on LEON processors, so by disabling this instruction +Index: lib/Target/SystemZ/SystemZISelLowering.cpp +=================================================================== +--- a/lib/Target/SystemZ/SystemZISelLowering.cpp ++++ b/lib/Target/SystemZ/SystemZISelLowering.cpp +@@ -4995,8 +4995,8 @@ + + SDValue SystemZTargetLowering::combineFP_ROUND( + SDNode *N, DAGCombinerInfo &DCI) const { +- // (fround (extract_vector_elt X 0)) +- // (fround (extract_vector_elt X 1)) -> ++ // (fpround (extract_vector_elt X 0)) ++ // (fpround (extract_vector_elt X 1)) -> + // (extract_vector_elt (VROUND X) 0) + // (extract_vector_elt (VROUND X) 1) + // +Index: lib/Target/SystemZ/SystemZInstrFP.td +=================================================================== +--- a/lib/Target/SystemZ/SystemZInstrFP.td ++++ b/lib/Target/SystemZ/SystemZInstrFP.td +@@ -154,7 +154,7 @@ + // Convert floating-point values to narrower representations, rounding + // according to the current mode. The destination of LEXBR and LDXBR + // is a 128-bit value, but only the first register of the pair is used. +-def LEDBR : UnaryRRE<"ledb", 0xB344, fround, FP32, FP64>; ++def LEDBR : UnaryRRE<"ledb", 0xB344, fpround, FP32, FP64>; + def LEXBR : UnaryRRE<"lexb", 0xB346, null_frag, FP128, FP128>; + def LDXBR : UnaryRRE<"ldxb", 0xB345, null_frag, FP128, FP128>; + +@@ -165,15 +165,15 @@ + def LDXBRA : UnaryRRF4<"ldxbra", 0xB345, FP128, FP128>, + Requires<[FeatureFPExtension]>; + +-def : Pat<(f32 (fround FP128:$src)), ++def : Pat<(f32 (fpround FP128:$src)), + (EXTRACT_SUBREG (LEXBR FP128:$src), subreg_hr32)>; +-def : Pat<(f64 (fround FP128:$src)), ++def : Pat<(f64 (fpround FP128:$src)), + (EXTRACT_SUBREG (LDXBR FP128:$src), subreg_h64)>; + + // Extend register floating-point values to wider representations. +-def LDEBR : UnaryRRE<"ldeb", 0xB304, fextend, FP64, FP32>; +-def LXEBR : UnaryRRE<"lxeb", 0xB306, fextend, FP128, FP32>; +-def LXDBR : UnaryRRE<"lxdb", 0xB305, fextend, FP128, FP64>; ++def LDEBR : UnaryRRE<"ldeb", 0xB304, fpextend, FP64, FP32>; ++def LXEBR : UnaryRRE<"lxeb", 0xB306, fpextend, FP128, FP32>; ++def LXDBR : UnaryRRE<"lxdb", 0xB305, fpextend, FP128, FP64>; + + // Extend memory floating-point values to wider representations. + def LDEB : UnaryRXE<"ldeb", 0xED04, extloadf32, FP64, 4>; +@@ -347,9 +347,9 @@ + + // Same idea for round, where mode 1 is round towards nearest with + // ties away from zero. +- def : Pat<(frnd FP32:$src), (FIEBRA 1, FP32:$src, 4)>; +- def : Pat<(frnd FP64:$src), (FIDBRA 1, FP64:$src, 4)>; +- def : Pat<(frnd FP128:$src), (FIXBRA 1, FP128:$src, 4)>; ++ def : Pat<(fround FP32:$src), (FIEBRA 1, FP32:$src, 4)>; ++ def : Pat<(fround FP64:$src), (FIDBRA 1, FP64:$src, 4)>; ++ def : Pat<(fround FP128:$src), (FIXBRA 1, FP128:$src, 4)>; + } + + //===----------------------------------------------------------------------===// +@@ -388,26 +388,26 @@ + + // f64 multiplication of two FP32 registers. + def MDEBR : BinaryRRE<"mdeb", 0xB30C, null_frag, FP64, FP32>; +-def : Pat<(fmul (f64 (fextend FP32:$src1)), (f64 (fextend FP32:$src2))), ++def : Pat<(fmul (f64 (fpextend FP32:$src1)), (f64 (fpextend FP32:$src2))), + (MDEBR (INSERT_SUBREG (f64 (IMPLICIT_DEF)), + FP32:$src1, subreg_r32), FP32:$src2)>; + + // f64 multiplication of an FP32 register and an f32 memory. + def MDEB : BinaryRXE<"mdeb", 0xED0C, null_frag, FP64, load, 4>; +-def : Pat<(fmul (f64 (fextend FP32:$src1)), ++def : Pat<(fmul (f64 (fpextend FP32:$src1)), + (f64 (extloadf32 bdxaddr12only:$addr))), + (MDEB (INSERT_SUBREG (f64 (IMPLICIT_DEF)), FP32:$src1, subreg_r32), + bdxaddr12only:$addr)>; + + // f128 multiplication of two FP64 registers. + def MXDBR : BinaryRRE<"mxdb", 0xB307, null_frag, FP128, FP64>; +-def : Pat<(fmul (f128 (fextend FP64:$src1)), (f128 (fextend FP64:$src2))), ++def : Pat<(fmul (f128 (fpextend FP64:$src1)), (f128 (fpextend FP64:$src2))), + (MXDBR (INSERT_SUBREG (f128 (IMPLICIT_DEF)), + FP64:$src1, subreg_h64), FP64:$src2)>; + + // f128 multiplication of an FP64 register and an f64 memory. + def MXDB : BinaryRXE<"mxdb", 0xED07, null_frag, FP128, load, 8>; +-def : Pat<(fmul (f128 (fextend FP64:$src1)), ++def : Pat<(fmul (f128 (fpextend FP64:$src1)), + (f128 (extloadf64 bdxaddr12only:$addr))), + (MXDB (INSERT_SUBREG (f128 (IMPLICIT_DEF)), FP64:$src1, subreg_h64), + bdxaddr12only:$addr)>; +Index: lib/Target/SystemZ/SystemZInstrVector.td +=================================================================== +--- a/lib/Target/SystemZ/SystemZInstrVector.td ++++ b/lib/Target/SystemZ/SystemZInstrVector.td +@@ -798,7 +798,7 @@ + def : FPConversion; + def : FPConversion; + def : FPConversion; +- def : FPConversion; ++ def : FPConversion; + } + + let Predicates = [FeatureVector] in { +@@ -840,13 +840,13 @@ + + // Load lengthened. + def VLDEB : UnaryVRRa<"vldeb", 0xE7C4, z_vextend, v128db, v128eb, 2, 0>; +- def WLDEB : UnaryVRRa<"wldeb", 0xE7C4, fextend, v64db, v32eb, 2, 8>; ++ def WLDEB : UnaryVRRa<"wldeb", 0xE7C4, fpextend, v64db, v32eb, 2, 8>; + + // Load rounded, + def VLEDB : TernaryVRRa<"vledb", 0xE7C5, null_frag, v128eb, v128db, 3, 0>; + def WLEDB : TernaryVRRa<"wledb", 0xE7C5, null_frag, v32eb, v64db, 3, 8>; + def : Pat<(v4f32 (z_vround (v2f64 VR128:$src))), (VLEDB VR128:$src, 0, 0)>; +- def : FPConversion; ++ def : FPConversion; + + // Multiply. + def VFMDB : BinaryVRRc<"vfmdb", 0xE7E7, fmul, v128db, v128db, 3, 0>; +Index: lib/Target/WebAssembly/WebAssemblyInstrConv.td +=================================================================== +--- a/lib/Target/WebAssembly/WebAssemblyInstrConv.td ++++ b/lib/Target/WebAssembly/WebAssemblyInstrConv.td +@@ -89,10 +89,10 @@ + "f64.convert_u/i64\t$dst, $src">; + + def F64_PROMOTE_F32 : I<(outs F64:$dst), (ins F32:$src), +- [(set F64:$dst, (fextend F32:$src))], ++ [(set F64:$dst, (fpextend F32:$src))], + "f64.promote/f32\t$dst, $src">; + def F32_DEMOTE_F64 : I<(outs F32:$dst), (ins F64:$src), +- [(set F32:$dst, (fround F64:$src))], ++ [(set F32:$dst, (fpround F64:$src))], + "f32.demote/f64\t$dst, $src">; + + def I32_REINTERPRET_F32 : I<(outs I32:$dst), (ins F32:$src), +Index: lib/Target/X86/X86InstrAVX512.td +=================================================================== +--- a/lib/Target/X86/X86InstrAVX512.td ++++ b/lib/Target/X86/X86InstrAVX512.td +@@ -5595,11 +5595,11 @@ + defm VCVTSS2SD : avx512_cvt_fp_scalar_ss2sd<0x5A, "vcvtss2sd", X86fpext, + X86fpextRnd,f32x_info, f64x_info >; + +-def : Pat<(f64 (fextend FR32X:$src)), ++def : Pat<(f64 (fpextend FR32X:$src)), + (COPY_TO_REGCLASS (VCVTSS2SDZrr (COPY_TO_REGCLASS FR32X:$src, VR128X), + (COPY_TO_REGCLASS FR32X:$src, VR128X)), VR128X)>, + Requires<[HasAVX512]>; +-def : Pat<(f64 (fextend (loadf32 addr:$src))), ++def : Pat<(f64 (fpextend (loadf32 addr:$src))), + (COPY_TO_REGCLASS (VCVTSS2SDZrm (v4f32 (IMPLICIT_DEF)), addr:$src), VR128X)>, + Requires<[HasAVX512]>; + +@@ -5612,7 +5612,7 @@ + (COPY_TO_REGCLASS (VMOVSSZrm addr:$src), VR128X)), VR128X)>, + Requires<[HasAVX512, OptForSpeed]>; + +-def : Pat<(f32 (fround FR64X:$src)), ++def : Pat<(f32 (fpround FR64X:$src)), + (COPY_TO_REGCLASS (VCVTSD2SSZrr (COPY_TO_REGCLASS FR64X:$src, VR128X), + (COPY_TO_REGCLASS FR64X:$src, VR128X)), VR128X)>, + Requires<[HasAVX512]>; +@@ -5666,29 +5666,29 @@ + // Extend Float to Double + multiclass avx512_cvtps2pd opc, string OpcodeStr> { + let Predicates = [HasAVX512] in { +- defm Z : avx512_vcvt_fp, ++ defm Z : avx512_vcvt_fp, + avx512_vcvt_fp_sae, EVEX_V512; + } + let Predicates = [HasVLX] in { + defm Z128 : avx512_vcvt_fp, EVEX_V128; +- defm Z256 : avx512_vcvt_fp, ++ defm Z256 : avx512_vcvt_fp, + EVEX_V256; + } + } + + // Truncate Double to Float + multiclass avx512_cvtpd2ps opc, string OpcodeStr> { + let Predicates = [HasAVX512] in { +- defm Z : avx512_vcvt_fp, ++ defm Z : avx512_vcvt_fp, + avx512_vcvt_fp_rc, EVEX_V512; + } + let Predicates = [HasVLX] in { + defm Z128 : avx512_vcvt_fp, EVEX_V128; +- defm Z256 : avx512_vcvt_fp, EVEX_V256; + } + } +@@ -6025,7 +6025,7 @@ + } + + let Predicates = [HasAVX512] in { +- def : Pat<(v8f32 (fround (loadv8f64 addr:$src))), ++ def : Pat<(v8f32 (fpround (loadv8f64 addr:$src))), + (VCVTPD2PSZrm addr:$src)>; + def : Pat<(v8f64 (extloadv8f32 addr:$src)), + (VCVTPS2PDZrm addr:$src)>; +Index: lib/Target/X86/X86InstrFPStack.td +=================================================================== +--- a/lib/Target/X86/X86InstrFPStack.td ++++ b/lib/Target/X86/X86InstrFPStack.td +@@ -711,19 +711,19 @@ + + // FP extensions map onto simple pseudo-value conversions if they are to/from + // the FP stack. +-def : Pat<(f64 (fextend RFP32:$src)), (COPY_TO_REGCLASS RFP32:$src, RFP64)>, ++def : Pat<(f64 (fpextend RFP32:$src)), (COPY_TO_REGCLASS RFP32:$src, RFP64)>, + Requires<[FPStackf32]>; +-def : Pat<(f80 (fextend RFP32:$src)), (COPY_TO_REGCLASS RFP32:$src, RFP80)>, ++def : Pat<(f80 (fpextend RFP32:$src)), (COPY_TO_REGCLASS RFP32:$src, RFP80)>, + Requires<[FPStackf32]>; +-def : Pat<(f80 (fextend RFP64:$src)), (COPY_TO_REGCLASS RFP64:$src, RFP80)>, ++def : Pat<(f80 (fpextend RFP64:$src)), (COPY_TO_REGCLASS RFP64:$src, RFP80)>, + Requires<[FPStackf64]>; + + // FP truncations map onto simple pseudo-value conversions if they are to/from + // the FP stack. We have validated that only value-preserving truncations make + // it through isel. +-def : Pat<(f32 (fround RFP64:$src)), (COPY_TO_REGCLASS RFP64:$src, RFP32)>, ++def : Pat<(f32 (fpround RFP64:$src)), (COPY_TO_REGCLASS RFP64:$src, RFP32)>, + Requires<[FPStackf32]>; +-def : Pat<(f32 (fround RFP80:$src)), (COPY_TO_REGCLASS RFP80:$src, RFP32)>, ++def : Pat<(f32 (fpround RFP80:$src)), (COPY_TO_REGCLASS RFP80:$src, RFP32)>, + Requires<[FPStackf32]>; +-def : Pat<(f64 (fround RFP80:$src)), (COPY_TO_REGCLASS RFP80:$src, RFP64)>, ++def : Pat<(f64 (fpround RFP80:$src)), (COPY_TO_REGCLASS RFP80:$src, RFP64)>, + Requires<[FPStackf64]>; +Index: lib/Target/X86/X86InstrSSE.td +=================================================================== +--- a/lib/Target/X86/X86InstrSSE.td ++++ b/lib/Target/X86/X86InstrSSE.td +@@ -1799,16 +1799,16 @@ + Sched<[WriteCvtF2FLd, ReadAfterLd]>; + } + +-def : Pat<(f32 (fround FR64:$src)), (VCVTSD2SSrr FR64:$src, FR64:$src)>, ++def : Pat<(f32 (fpround FR64:$src)), (VCVTSD2SSrr FR64:$src, FR64:$src)>, + Requires<[UseAVX]>; + + def CVTSD2SSrr : SDI<0x5A, MRMSrcReg, (outs FR32:$dst), (ins FR64:$src), + "cvtsd2ss\t{$src, $dst|$dst, $src}", +- [(set FR32:$dst, (fround FR64:$src))], ++ [(set FR32:$dst, (fpround FR64:$src))], + IIC_SSE_CVT_Scalar_RR>, Sched<[WriteCvtF2F]>; + def CVTSD2SSrm : I<0x5A, MRMSrcMem, (outs FR32:$dst), (ins f64mem:$src), + "cvtsd2ss\t{$src, $dst|$dst, $src}", +- [(set FR32:$dst, (fround (loadf64 addr:$src)))], ++ [(set FR32:$dst, (fpround (loadf64 addr:$src)))], + IIC_SSE_CVT_Scalar_RM>, + XD, + Requires<[UseSSE2, OptForSize]>, Sched<[WriteCvtF2FLd]>; +@@ -1865,9 +1865,9 @@ + Sched<[WriteCvtF2FLd, ReadAfterLd]>; + } + +-def : Pat<(f64 (fextend FR32:$src)), ++def : Pat<(f64 (fpextend FR32:$src)), + (VCVTSS2SDrr FR32:$src, FR32:$src)>, Requires<[UseAVX]>; +-def : Pat<(fextend (loadf32 addr:$src)), ++def : Pat<(fpextend (loadf32 addr:$src)), + (VCVTSS2SDrm (f32 (IMPLICIT_DEF)), addr:$src)>, Requires<[UseAVX]>; + + def : Pat<(extloadf32 addr:$src), +@@ -1879,21 +1879,21 @@ + + def CVTSS2SDrr : I<0x5A, MRMSrcReg, (outs FR64:$dst), (ins FR32:$src), + "cvtss2sd\t{$src, $dst|$dst, $src}", +- [(set FR64:$dst, (fextend FR32:$src))], ++ [(set FR64:$dst, (fpextend FR32:$src))], + IIC_SSE_CVT_Scalar_RR>, XS, + Requires<[UseSSE2]>, Sched<[WriteCvtF2F]>; + def CVTSS2SDrm : I<0x5A, MRMSrcMem, (outs FR64:$dst), (ins f32mem:$src), + "cvtss2sd\t{$src, $dst|$dst, $src}", + [(set FR64:$dst, (extloadf32 addr:$src))], + IIC_SSE_CVT_Scalar_RM>, XS, + Requires<[UseSSE2, OptForSize]>, Sched<[WriteCvtF2FLd]>; + +-// extload f32 -> f64. This matches load+fextend because we have a hack in ++// extload f32 -> f64. This matches load+fpextend because we have a hack in + // the isel (PreprocessForFPConvert) that can introduce loads after dag + // combine. +-// Since these loads aren't folded into the fextend, we have to match it ++// Since these loads aren't folded into the fpextend, we have to match it + // explicitly here. +-def : Pat<(fextend (loadf32 addr:$src)), ++def : Pat<(fpextend (loadf32 addr:$src)), + (CVTSS2SDrm addr:$src)>, Requires<[UseSSE2]>; + def : Pat<(extloadf32 addr:$src), + (CVTSS2SDrr (MOVSSrm addr:$src))>, Requires<[UseSSE2, OptForSpeed]>; +@@ -2269,26 +2269,26 @@ + } + + let Predicates = [HasAVX, NoVLX] in { +- // Match fround and fextend for 128/256-bit conversions ++ // Match fpround and fpextend for 128/256-bit conversions + def : Pat<(v4f32 (X86vfpround (v2f64 VR128:$src))), + (VCVTPD2PSrr VR128:$src)>; + def : Pat<(v4f32 (X86vfpround (loadv2f64 addr:$src))), + (VCVTPD2PSXrm addr:$src)>; +- def : Pat<(v4f32 (fround (v4f64 VR256:$src))), ++ def : Pat<(v4f32 (fpround (v4f64 VR256:$src))), + (VCVTPD2PSYrr VR256:$src)>; +- def : Pat<(v4f32 (fround (loadv4f64 addr:$src))), ++ def : Pat<(v4f32 (fpround (loadv4f64 addr:$src))), + (VCVTPD2PSYrm addr:$src)>; + + def : Pat<(v2f64 (X86vfpext (v4f32 VR128:$src))), + (VCVTPS2PDrr VR128:$src)>; +- def : Pat<(v4f64 (fextend (v4f32 VR128:$src))), ++ def : Pat<(v4f64 (fpextend (v4f32 VR128:$src))), + (VCVTPS2PDYrr VR128:$src)>; + def : Pat<(v4f64 (extloadv4f32 addr:$src)), + (VCVTPS2PDYrm addr:$src)>; + } + + let Predicates = [UseSSE2] in { +- // Match fround and fextend for 128 conversions ++ // Match fpround and fpextend for 128 conversions + def : Pat<(v4f32 (X86vfpround (v2f64 VR128:$src))), + (CVTPD2PSrr VR128:$src)>; + def : Pat<(v4f32 (X86vfpround (memopv2f64 addr:$src))), diff --git a/deps/patches/llvm-D24300_ptx_intrinsics.patch b/deps/patches/llvm-D24300_ptx_intrinsics.patch new file mode 100644 index 0000000000000..e0c1e5a286c56 --- /dev/null +++ b/deps/patches/llvm-D24300_ptx_intrinsics.patch @@ -0,0 +1,506 @@ +Index: lib/Target/NVPTX/NVPTXISelLowering.cpp +=================================================================== +--- a/lib/Target/NVPTX/NVPTXISelLowering.cpp ++++ b/lib/Target/NVPTX/NVPTXISelLowering.cpp +@@ -279,6 +279,28 @@ + setTargetDAGCombine(ISD::SHL); + setTargetDAGCombine(ISD::SELECT); + ++ // Library functions. These default to Expand, but we have instructions ++ // for them. ++ setOperationAction(ISD::FCEIL, MVT::f32, Legal); ++ setOperationAction(ISD::FCEIL, MVT::f64, Legal); ++ setOperationAction(ISD::FFLOOR, MVT::f32, Legal); ++ setOperationAction(ISD::FFLOOR, MVT::f64, Legal); ++ setOperationAction(ISD::FNEARBYINT, MVT::f32, Legal); ++ setOperationAction(ISD::FNEARBYINT, MVT::f64, Legal); ++ setOperationAction(ISD::FRINT, MVT::f32, Legal); ++ setOperationAction(ISD::FRINT, MVT::f64, Legal); ++ setOperationAction(ISD::FROUND, MVT::f32, Legal); ++ setOperationAction(ISD::FROUND, MVT::f64, Legal); ++ setOperationAction(ISD::FTRUNC, MVT::f32, Legal); ++ setOperationAction(ISD::FTRUNC, MVT::f64, Legal); ++ setOperationAction(ISD::FMINNUM, MVT::f32, Legal); ++ setOperationAction(ISD::FMINNUM, MVT::f64, Legal); ++ setOperationAction(ISD::FMAXNUM, MVT::f32, Legal); ++ setOperationAction(ISD::FMAXNUM, MVT::f64, Legal); ++ ++ // No FEXP2, FLOG2. The PTX ex2 and log2 functions are always approximate. ++ // No FPOW or FREM in PTX. ++ + // Now deduce the information based on the above mentioned + // actions + computeRegisterProperties(STI.getRegisterInfo()); +Index: lib/Target/NVPTX/NVPTXInstrInfo.td +=================================================================== +--- a/lib/Target/NVPTX/NVPTXInstrInfo.td ++++ b/lib/Target/NVPTX/NVPTXInstrInfo.td +@@ -207,15 +207,63 @@ + } + + // Template for instructions which take three fp64 or fp32 args. The +-// instructions are named ".f" (e.g. "add.f64"). ++// instructions are named ".f" (e.g. "min.f64"). + // + // Also defines ftz (flush subnormal inputs and results to sign-preserving + // zero) variants for fp32 functions. ++// ++// This multiclass should be used for nodes that cannot be folded into FMAs. ++// For nodes that can be folded into FMAs (i.e. adds and muls), use ++// F3_fma_component. + multiclass F3 { + def f64rr : + NVPTXInst<(outs Float64Regs:$dst), + (ins Float64Regs:$a, Float64Regs:$b), + !strconcat(OpcStr, ".f64 \t$dst, $a, $b;"), ++ [(set Float64Regs:$dst, (OpNode Float64Regs:$a, Float64Regs:$b))]>; ++ def f64ri : ++ NVPTXInst<(outs Float64Regs:$dst), ++ (ins Float64Regs:$a, f64imm:$b), ++ !strconcat(OpcStr, ".f64 \t$dst, $a, $b;"), ++ [(set Float64Regs:$dst, (OpNode Float64Regs:$a, fpimm:$b))]>; ++ def f32rr_ftz : ++ NVPTXInst<(outs Float32Regs:$dst), ++ (ins Float32Regs:$a, Float32Regs:$b), ++ !strconcat(OpcStr, ".ftz.f32 \t$dst, $a, $b;"), ++ [(set Float32Regs:$dst, (OpNode Float32Regs:$a, Float32Regs:$b))]>, ++ Requires<[doF32FTZ]>; ++ def f32ri_ftz : ++ NVPTXInst<(outs Float32Regs:$dst), ++ (ins Float32Regs:$a, f32imm:$b), ++ !strconcat(OpcStr, ".ftz.f32 \t$dst, $a, $b;"), ++ [(set Float32Regs:$dst, (OpNode Float32Regs:$a, fpimm:$b))]>, ++ Requires<[doF32FTZ]>; ++ def f32rr : ++ NVPTXInst<(outs Float32Regs:$dst), ++ (ins Float32Regs:$a, Float32Regs:$b), ++ !strconcat(OpcStr, ".f32 \t$dst, $a, $b;"), ++ [(set Float32Regs:$dst, (OpNode Float32Regs:$a, Float32Regs:$b))]>; ++ def f32ri : ++ NVPTXInst<(outs Float32Regs:$dst), ++ (ins Float32Regs:$a, f32imm:$b), ++ !strconcat(OpcStr, ".f32 \t$dst, $a, $b;"), ++ [(set Float32Regs:$dst, (OpNode Float32Regs:$a, fpimm:$b))]>; ++} ++ ++// Template for instructions which take three fp64 or fp32 args. The ++// instructions are named ".f" (e.g. "add.f64"). ++// ++// Also defines ftz (flush subnormal inputs and results to sign-preserving ++// zero) variants for fp32 functions. ++// ++// This multiclass should be used for nodes that can be folded to make fma ops. ++// In this case, we use the ".rn" variant when FMA is disabled, as this behaves ++// just like the non ".rn" op, but prevents ptxas from creating FMAs. ++multiclass F3_fma_component { ++ def f64rr : ++ NVPTXInst<(outs Float64Regs:$dst), ++ (ins Float64Regs:$a, Float64Regs:$b), ++ !strconcat(OpcStr, ".f64 \t$dst, $a, $b;"), + [(set Float64Regs:$dst, (OpNode Float64Regs:$a, Float64Regs:$b))]>, + Requires<[allowFMA]>; + def f64ri : +@@ -248,41 +296,39 @@ + !strconcat(OpcStr, ".f32 \t$dst, $a, $b;"), + [(set Float32Regs:$dst, (OpNode Float32Regs:$a, fpimm:$b))]>, + Requires<[allowFMA]>; +-} + +-// Same as F3, but defines ".rn" variants (round to nearest even). +-multiclass F3_rn { +- def f64rr : ++ // These have strange names so we don't perturb existing mir tests. ++ def _rnf64rr : + NVPTXInst<(outs Float64Regs:$dst), + (ins Float64Regs:$a, Float64Regs:$b), + !strconcat(OpcStr, ".rn.f64 \t$dst, $a, $b;"), + [(set Float64Regs:$dst, (OpNode Float64Regs:$a, Float64Regs:$b))]>, + Requires<[noFMA]>; +- def f64ri : ++ def _rnf64ri : + NVPTXInst<(outs Float64Regs:$dst), + (ins Float64Regs:$a, f64imm:$b), + !strconcat(OpcStr, ".rn.f64 \t$dst, $a, $b;"), + [(set Float64Regs:$dst, (OpNode Float64Regs:$a, fpimm:$b))]>, + Requires<[noFMA]>; +- def f32rr_ftz : ++ def _rnf32rr_ftz : + NVPTXInst<(outs Float32Regs:$dst), + (ins Float32Regs:$a, Float32Regs:$b), + !strconcat(OpcStr, ".rn.ftz.f32 \t$dst, $a, $b;"), + [(set Float32Regs:$dst, (OpNode Float32Regs:$a, Float32Regs:$b))]>, + Requires<[noFMA, doF32FTZ]>; +- def f32ri_ftz : ++ def _rnf32ri_ftz : + NVPTXInst<(outs Float32Regs:$dst), + (ins Float32Regs:$a, f32imm:$b), + !strconcat(OpcStr, ".rn.ftz.f32 \t$dst, $a, $b;"), + [(set Float32Regs:$dst, (OpNode Float32Regs:$a, fpimm:$b))]>, + Requires<[noFMA, doF32FTZ]>; +- def f32rr : ++ def _rnf32rr : + NVPTXInst<(outs Float32Regs:$dst), + (ins Float32Regs:$a, Float32Regs:$b), + !strconcat(OpcStr, ".rn.f32 \t$dst, $a, $b;"), + [(set Float32Regs:$dst, (OpNode Float32Regs:$a, Float32Regs:$b))]>, + Requires<[noFMA]>; +- def f32ri : ++ def _rnf32ri : + NVPTXInst<(outs Float32Regs:$dst), + (ins Float32Regs:$a, f32imm:$b), + !strconcat(OpcStr, ".rn.f32 \t$dst, $a, $b;"), +@@ -713,13 +759,12 @@ + N->getValueAPF().convertToDouble() == 1.0; + }]>; + +-defm FADD : F3<"add", fadd>; +-defm FSUB : F3<"sub", fsub>; +-defm FMUL : F3<"mul", fmul>; +- +-defm FADD_rn : F3_rn<"add", fadd>; +-defm FSUB_rn : F3_rn<"sub", fsub>; +-defm FMUL_rn : F3_rn<"mul", fmul>; ++defm FADD : F3_fma_component<"add", fadd>; ++defm FSUB : F3_fma_component<"sub", fsub>; ++defm FMUL : F3_fma_component<"mul", fmul>; ++ ++defm FMIN : F3<"min", fminnum>; ++defm FMAX : F3<"max", fmaxnum>; + + defm FABS : F2<"abs", fabs>; + defm FNEG : F2<"neg", fneg>; +@@ -2628,6 +2673,55 @@ + def retflag : SDNode<"NVPTXISD::RET_FLAG", SDTNone, + [SDNPHasChain, SDNPOptInGlue]>; + ++// fceil, ffloor, fround, ftrunc. ++ ++def : Pat<(fceil Float32Regs:$a), ++ (CVT_f32_f32 Float32Regs:$a, CvtRPI_FTZ)>, Requires<[doF32FTZ]>; ++def : Pat<(fceil Float32Regs:$a), ++ (CVT_f32_f32 Float32Regs:$a, CvtRPI)>, Requires<[doNoF32FTZ]>; ++def : Pat<(fceil Float64Regs:$a), ++ (CVT_f64_f64 Float64Regs:$a, CvtRPI)>; ++ ++def : Pat<(ffloor Float32Regs:$a), ++ (CVT_f32_f32 Float32Regs:$a, CvtRMI_FTZ)>, Requires<[doF32FTZ]>; ++def : Pat<(ffloor Float32Regs:$a), ++ (CVT_f32_f32 Float32Regs:$a, CvtRMI)>, Requires<[doNoF32FTZ]>; ++def : Pat<(ffloor Float64Regs:$a), ++ (CVT_f64_f64 Float64Regs:$a, CvtRMI)>; ++ ++def : Pat<(fround Float32Regs:$a), ++ (CVT_f32_f32 Float32Regs:$a, CvtRNI_FTZ)>, Requires<[doF32FTZ]>; ++def : Pat<(f32 (fround Float32Regs:$a)), ++ (CVT_f32_f32 Float32Regs:$a, CvtRNI)>, Requires<[doNoF32FTZ]>; ++def : Pat<(f64 (fround Float64Regs:$a)), ++ (CVT_f64_f64 Float64Regs:$a, CvtRNI)>; ++ ++def : Pat<(ftrunc Float32Regs:$a), ++ (CVT_f32_f32 Float32Regs:$a, CvtRZI_FTZ)>, Requires<[doF32FTZ]>; ++def : Pat<(ftrunc Float32Regs:$a), ++ (CVT_f32_f32 Float32Regs:$a, CvtRZI)>, Requires<[doNoF32FTZ]>; ++def : Pat<(ftrunc Float64Regs:$a), ++ (CVT_f64_f64 Float64Regs:$a, CvtRZI)>; ++ ++// nearbyint and rint are implemented as rounding to nearest even. This isn't ++// strictly correct, because it causes us to ignore the rounding mode. But it ++// matches what CUDA's "libm" does. ++ ++def : Pat<(fnearbyint Float32Regs:$a), ++ (CVT_f32_f32 Float32Regs:$a, CvtRNI_FTZ)>, Requires<[doF32FTZ]>; ++def : Pat<(fnearbyint Float32Regs:$a), ++ (CVT_f32_f32 Float32Regs:$a, CvtRNI)>, Requires<[doNoF32FTZ]>; ++def : Pat<(fnearbyint Float64Regs:$a), ++ (CVT_f64_f64 Float64Regs:$a, CvtRNI)>; ++ ++def : Pat<(frint Float32Regs:$a), ++ (CVT_f32_f32 Float32Regs:$a, CvtRNI_FTZ)>, Requires<[doF32FTZ]>; ++def : Pat<(frint Float32Regs:$a), ++ (CVT_f32_f32 Float32Regs:$a, CvtRNI)>, Requires<[doNoF32FTZ]>; ++def : Pat<(frint Float64Regs:$a), ++ (CVT_f64_f64 Float64Regs:$a, CvtRNI)>; ++ ++ + //----------------------------------- + // Control-flow + //----------------------------------- +Index: test/CodeGen/NVPTX/bug22322.ll +=================================================================== +--- a/test/CodeGen/NVPTX/bug22322.ll ++++ b/test/CodeGen/NVPTX/bug22322.ll +@@ -22,7 +22,7 @@ + %8 = icmp eq i32 %7, 0 + %9 = select i1 %8, float 0.000000e+00, float -1.000000e+00 + store float %9, float* %ret_vec.sroa.8.i, align 4 +-; CHECK: setp.lt.f32 %p{{[0-9]+}}, %f{{[0-9]+}}, 0f00000000 ++; CHECK: max.f32 %f{{[0-9]+}}, %f{{[0-9]+}}, 0f00000000 + %10 = fcmp olt float %9, 0.000000e+00 + %ret_vec.sroa.8.i.val = load float, float* %ret_vec.sroa.8.i, align 4 + %11 = select i1 %10, float 0.000000e+00, float %ret_vec.sroa.8.i.val +Index: test/CodeGen/NVPTX/math-intrins.ll +=================================================================== +--- a/test/CodeGen/NVPTX/math-intrins.ll ++++ b/test/CodeGen/NVPTX/math-intrins.ll +@@ -0,0 +1,261 @@ ++; RUN: llc < %s | FileCheck %s ++target triple = "nvptx64-nvidia-cuda" ++ ++; Checks that llvm intrinsics for math functions are correctly lowered to PTX. ++ ++declare float @llvm.ceil.f32(float) #0 ++declare double @llvm.ceil.f64(double) #0 ++declare float @llvm.floor.f32(float) #0 ++declare double @llvm.floor.f64(double) #0 ++declare float @llvm.round.f32(float) #0 ++declare double @llvm.round.f64(double) #0 ++declare float @llvm.nearbyint.f32(float) #0 ++declare double @llvm.nearbyint.f64(double) #0 ++declare float @llvm.rint.f32(float) #0 ++declare double @llvm.rint.f64(double) #0 ++declare float @llvm.trunc.f32(float) #0 ++declare double @llvm.trunc.f64(double) #0 ++declare float @llvm.fabs.f32(float) #0 ++declare double @llvm.fabs.f64(double) #0 ++declare float @llvm.minnum.f32(float, float) #0 ++declare double @llvm.minnum.f64(double, double) #0 ++declare float @llvm.maxnum.f32(float, float) #0 ++declare double @llvm.maxnum.f64(double, double) #0 ++ ++; ---- ceil ---- ++ ++; CHECK-LABEL: ceil_float ++define float @ceil_float(float %a) { ++ ; CHECK: cvt.rpi.f32.f32 ++ %b = call float @llvm.ceil.f32(float %a) ++ ret float %b ++} ++ ++; CHECK-LABEL: ceil_float_ftz ++define float @ceil_float_ftz(float %a) #1 { ++ ; CHECK: cvt.rpi.ftz.f32.f32 ++ %b = call float @llvm.ceil.f32(float %a) ++ ret float %b ++} ++ ++; CHECK-LABEL: ceil_double ++define double @ceil_double(double %a) { ++ ; CHECK: cvt.rpi.f64.f64 ++ %b = call double @llvm.ceil.f64(double %a) ++ ret double %b ++} ++ ++; ---- floor ---- ++ ++; CHECK-LABEL: floor_float ++define float @floor_float(float %a) { ++ ; CHECK: cvt.rmi.f32.f32 ++ %b = call float @llvm.floor.f32(float %a) ++ ret float %b ++} ++ ++; CHECK-LABEL: floor_float_ftz ++define float @floor_float_ftz(float %a) #1 { ++ ; CHECK: cvt.rmi.ftz.f32.f32 ++ %b = call float @llvm.floor.f32(float %a) ++ ret float %b ++} ++ ++; CHECK-LABEL: floor_double ++define double @floor_double(double %a) { ++ ; CHECK: cvt.rmi.f64.f64 ++ %b = call double @llvm.floor.f64(double %a) ++ ret double %b ++} ++ ++; ---- round ---- ++ ++; CHECK-LABEL: round_float ++define float @round_float(float %a) { ++ ; CHECK: cvt.rni.f32.f32 ++ %b = call float @llvm.round.f32(float %a) ++ ret float %b ++} ++ ++; CHECK-LABEL: round_float_ftz ++define float @round_float_ftz(float %a) #1 { ++ ; CHECK: cvt.rni.ftz.f32.f32 ++ %b = call float @llvm.round.f32(float %a) ++ ret float %b ++} ++ ++; CHECK-LABEL: round_double ++define double @round_double(double %a) { ++ ; CHECK: cvt.rni.f64.f64 ++ %b = call double @llvm.round.f64(double %a) ++ ret double %b ++} ++ ++; ---- nearbyint ---- ++ ++; CHECK-LABEL: nearbyint_float ++define float @nearbyint_float(float %a) { ++ ; CHECK: cvt.rni.f32.f32 ++ %b = call float @llvm.nearbyint.f32(float %a) ++ ret float %b ++} ++ ++; CHECK-LABEL: nearbyint_float_ftz ++define float @nearbyint_float_ftz(float %a) #1 { ++ ; CHECK: cvt.rni.ftz.f32.f32 ++ %b = call float @llvm.nearbyint.f32(float %a) ++ ret float %b ++} ++ ++; CHECK-LABEL: nearbyint_double ++define double @nearbyint_double(double %a) { ++ ; CHECK: cvt.rni.f64.f64 ++ %b = call double @llvm.nearbyint.f64(double %a) ++ ret double %b ++} ++ ++; ---- rint ---- ++ ++; CHECK-LABEL: rint_float ++define float @rint_float(float %a) { ++ ; CHECK: cvt.rni.f32.f32 ++ %b = call float @llvm.rint.f32(float %a) ++ ret float %b ++} ++ ++; CHECK-LABEL: rint_float_ftz ++define float @rint_float_ftz(float %a) #1 { ++ ; CHECK: cvt.rni.ftz.f32.f32 ++ %b = call float @llvm.rint.f32(float %a) ++ ret float %b ++} ++ ++; CHECK-LABEL: rint_double ++define double @rint_double(double %a) { ++ ; CHECK: cvt.rni.f64.f64 ++ %b = call double @llvm.rint.f64(double %a) ++ ret double %b ++} ++ ++; ---- trunc ---- ++ ++; CHECK-LABEL: trunc_float ++define float @trunc_float(float %a) { ++ ; CHECK: cvt.rzi.f32.f32 ++ %b = call float @llvm.trunc.f32(float %a) ++ ret float %b ++} ++ ++; CHECK-LABEL: trunc_float_ftz ++define float @trunc_float_ftz(float %a) #1 { ++ ; CHECK: cvt.rzi.ftz.f32.f32 ++ %b = call float @llvm.trunc.f32(float %a) ++ ret float %b ++} ++ ++; CHECK-LABEL: trunc_double ++define double @trunc_double(double %a) { ++ ; CHECK: cvt.rzi.f64.f64 ++ %b = call double @llvm.trunc.f64(double %a) ++ ret double %b ++} ++ ++; ---- abs ---- ++ ++; CHECK-LABEL: abs_float ++define float @abs_float(float %a) { ++ ; CHECK: abs.f32 ++ %b = call float @llvm.fabs.f32(float %a) ++ ret float %b ++} ++ ++; CHECK-LABEL: abs_float_ftz ++define float @abs_float_ftz(float %a) #1 { ++ ; CHECK: abs.ftz.f32 ++ %b = call float @llvm.fabs.f32(float %a) ++ ret float %b ++} ++ ++; CHECK-LABEL: abs_double ++define double @abs_double(double %a) { ++ ; CHECK: abs.f64 ++ %b = call double @llvm.fabs.f64(double %a) ++ ret double %b ++} ++ ++; ---- min ---- ++ ++; CHECK-LABEL: min_float ++define float @min_float(float %a, float %b) { ++ ; CHECK: min.f32 ++ %x = call float @llvm.minnum.f32(float %a, float %b) ++ ret float %x ++} ++ ++; CHECK-LABEL: min_imm1 ++define float @min_imm1(float %a) { ++ ; CHECK: min.f32 ++ %x = call float @llvm.minnum.f32(float %a, float 0.0) ++ ret float %x ++} ++ ++; CHECK-LABEL: min_imm2 ++define float @min_imm2(float %a) { ++ ; CHECK: min.f32 ++ %x = call float @llvm.minnum.f32(float 0.0, float %a) ++ ret float %x ++} ++ ++; CHECK-LABEL: min_float_ftz ++define float @min_float_ftz(float %a, float %b) #1 { ++ ; CHECK: min.ftz.f32 ++ %x = call float @llvm.minnum.f32(float %a, float %b) ++ ret float %x ++} ++ ++; CHECK-LABEL: min_double ++define double @min_double(double %a, double %b) { ++ ; CHECK: min.f64 ++ %x = call double @llvm.minnum.f64(double %a, double %b) ++ ret double %x ++} ++ ++; ---- max ---- ++ ++; CHECK-LABEL: max_imm1 ++define float @max_imm1(float %a) { ++ ; CHECK: max.f32 ++ %x = call float @llvm.maxnum.f32(float %a, float 0.0) ++ ret float %x ++} ++ ++; CHECK-LABEL: max_imm2 ++define float @max_imm2(float %a) { ++ ; CHECK: max.f32 ++ %x = call float @llvm.maxnum.f32(float 0.0, float %a) ++ ret float %x ++} ++ ++; CHECK-LABEL: max_float ++define float @max_float(float %a, float %b) { ++ ; CHECK: max.f32 ++ %x = call float @llvm.maxnum.f32(float %a, float %b) ++ ret float %x ++} ++ ++; CHECK-LABEL: max_float_ftz ++define float @max_float_ftz(float %a, float %b) #1 { ++ ; CHECK: max.ftz.f32 ++ %x = call float @llvm.maxnum.f32(float %a, float %b) ++ ret float %x ++} ++ ++; CHECK-LABEL: max_double ++define double @max_double(double %a, double %b) { ++ ; CHECK: max.f64 ++ %x = call double @llvm.maxnum.f64(double %a, double %b) ++ ret double %x ++} ++ ++attributes #0 = { nounwind readnone } ++attributes #1 = { "nvptx-f32ftz" = "true" } diff --git a/deps/patches/llvm-D25865-cmakeshlib.patch b/deps/patches/llvm-D25865-cmakeshlib.patch new file mode 100644 index 0000000000000..1f982665facf0 --- /dev/null +++ b/deps/patches/llvm-D25865-cmakeshlib.patch @@ -0,0 +1,83 @@ +From 417001588d232151050db2d32df443e2d073ebbf Mon Sep 17 00:00:00 2001 +From: Valentin Churavy +Date: Fri, 21 Oct 2016 17:25:04 +0900 +Subject: [PATCH] Fix llvm-shlib cmake build + +Summary: +This fixes a few things that used to work with a Makefile build, but were broken in cmake. + +1. Treat MINGW like a Linux system. +2. The shlib should never contain other shared libraries. + +Subscribers: beanz, mgorny + +Differential Revision: https://reviews.llvm.org/D25865 +--- + tools/llvm-shlib/CMakeLists.txt | 42 ++++++++++++++++++++--------------------- + 1 file changed, 20 insertions(+), 22 deletions(-) + +diff --git a/tools/llvm-shlib/CMakeLists.txt b/tools/llvm-shlib/CMakeLists.txt +index 3fe672d..edadb82 100644 +--- a/tools/llvm-shlib/CMakeLists.txt ++++ b/tools/llvm-shlib/CMakeLists.txt +@@ -8,29 +8,27 @@ set(SOURCES + + llvm_map_components_to_libnames(LIB_NAMES ${LLVM_DYLIB_COMPONENTS}) + +-if(LLVM_LINK_LLVM_DYLIB) +- if(LLVM_DYLIB_EXPORTED_SYMBOL_FILE) +- message(WARNING "Using LLVM_LINK_LLVM_DYLIB with LLVM_DYLIB_EXPORTED_SYMBOL_FILE may not work. Use at your own risk.") +- endif() +- +- # libLLVM.so should not have any dependencies on any other LLVM +- # shared libraries. When using the "all" pseudo-component, +- # LLVM_AVAILABLE_LIBS is added to the dependencies, which may +- # contain shared libraries (e.g. libLTO). +- # +- # Also exclude libLLVMTableGen for the following reasons: +- # - it is only used by internal *-tblgen utilities; +- # - it pollutes the global options space. +- foreach(lib ${LIB_NAMES}) +- get_target_property(t ${lib} TYPE) +- if("${lib}" STREQUAL "LLVMTableGen") +- elseif("x${t}" STREQUAL "xSTATIC_LIBRARY") +- list(APPEND FILTERED_LIB_NAMES ${lib}) +- endif() +- endforeach() +- set(LIB_NAMES ${FILTERED_LIB_NAMES}) ++if(LLVM_LINK_LLVM_DYLIB AND LLVM_DYLIB_EXPORTED_SYMBOL_FILE) ++ message(WARNING "Using LLVM_LINK_LLVM_DYLIB with LLVM_DYLIB_EXPORTED_SYMBOL_FILE may not work. Use at your own risk.") + endif() + ++# libLLVM.so should not have any dependencies on any other LLVM ++# shared libraries. When using the "all" pseudo-component, ++# LLVM_AVAILABLE_LIBS is added to the dependencies, which may ++# contain shared libraries (e.g. libLTO). ++# ++# Also exclude libLLVMTableGen for the following reasons: ++# - it is only used by internal *-tblgen utilities; ++# - it pollutes the global options space. ++foreach(lib ${LIB_NAMES}) ++ get_target_property(t ${lib} TYPE) ++ if("${lib}" STREQUAL "LLVMTableGen") ++ elseif("x${t}" STREQUAL "xSTATIC_LIBRARY") ++ list(APPEND FILTERED_LIB_NAMES ${lib}) ++ endif() ++endforeach() ++set(LIB_NAMES ${FILTERED_LIB_NAMES}) ++ + if(LLVM_DYLIB_EXPORTED_SYMBOL_FILE) + set(LLVM_EXPORTED_SYMBOL_FILE ${LLVM_DYLIB_EXPORTED_SYMBOL_FILE}) + add_custom_target(libLLVMExports DEPENDS ${LLVM_EXPORTED_SYMBOL_FILE}) +@@ -39,7 +37,7 @@ endif() + add_llvm_library(LLVM SHARED DISABLE_LLVM_LINK_LLVM_DYLIB SONAME ${SOURCES}) + + list(REMOVE_DUPLICATES LIB_NAMES) +-if("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux") # FIXME: It should be "GNU ld for elf" ++if("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux" OR MINGW) # FIXME: It should be "GNU ld for elf" + # GNU ld doesn't resolve symbols in the version script. + set(LIB_NAMES -Wl,--whole-archive ${LIB_NAMES} -Wl,--no-whole-archive) + elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "Darwin") +-- +2.10.1 + diff --git a/deps/patches/llvm-D27389.patch b/deps/patches/llvm-D27389.patch new file mode 100644 index 0000000000000..6ddc6e71e3b60 --- /dev/null +++ b/deps/patches/llvm-D27389.patch @@ -0,0 +1,66 @@ +commit 83dc06334ff95ad18a951d0bb540290510f2f81a +Author: Keno Fischer +Date: Thu Dec 8 17:22:35 2016 +0000 + + ConstantFolding: Don't crash when encountering vector GEP + + ConstantFolding tried to cast one of the scalar indices to a vector + type. Instead, use the vector type only for the first index (which + is the only one allowed to be a vector) and use its scalar type + otherwise. + + Fixes PR31250. + + Reviewers: majnemer + Differential Revision: https://reviews.llvm.org/D27389 + + git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@289073 91177308-0d34-0410-b5e6-96231b3b80d8 + +diff --git a/lib/Analysis/ConstantFolding.cpp b/lib/Analysis/ConstantFolding.cpp +index 2d1edfe..1c0bf01a 100644 +--- a/lib/Analysis/ConstantFolding.cpp ++++ b/lib/Analysis/ConstantFolding.cpp +@@ -692,14 +692,15 @@ Constant *CastGEPIndices(Type *SrcElemTy, ArrayRef Ops, + Type *ResultTy, const DataLayout &DL, + const TargetLibraryInfo *TLI) { + Type *IntPtrTy = DL.getIntPtrType(ResultTy); ++ Type *IntPtrScalarTy = IntPtrTy->getScalarType(); + + bool Any = false; + SmallVector NewIdxs; + for (unsigned i = 1, e = Ops.size(); i != e; ++i) { + if ((i == 1 || +- !isa(GetElementPtrInst::getIndexedType(SrcElemTy, +- Ops.slice(1, i - 1)))) && +- Ops[i]->getType() != IntPtrTy) { ++ !isa(GetElementPtrInst::getIndexedType( ++ SrcElemTy, Ops.slice(1, i - 1)))) && ++ Ops[i]->getType() != (i == 1 ? IntPtrTy : IntPtrScalarTy)) { + Any = true; + NewIdxs.push_back(ConstantExpr::getCast(CastInst::getCastOpcode(Ops[i], + true, +diff --git a/test/Analysis/ConstantFolding/vectorgep-crash.ll b/test/Analysis/ConstantFolding/vectorgep-crash.ll +new file mode 100644 +index 0000000..bcc96b2 +--- /dev/null ++++ b/test/Analysis/ConstantFolding/vectorgep-crash.ll +@@ -0,0 +1,19 @@ ++; RUN: opt -instcombine -S -o - %s | FileCheck %s ++; Tests that we don't crash upon encountering a vector GEP ++ ++target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" ++target triple = "x86_64-unknown-linux-gnu" ++ ++%Dual = type { %Dual.72, %Partials.73 } ++%Dual.72 = type { double, %Partials } ++%Partials = type { [2 x double] } ++%Partials.73 = type { [2 x %Dual.72] } ++ ++; Function Attrs: sspreq ++define <8 x i64*> @"julia_axpy!_65480"(%Dual* %arg1, <8 x i64> %arg2) { ++top: ++; CHECK: %VectorGep14 = getelementptr inbounds %Dual, %Dual* %arg1, <8 x i64> %arg2, i32 1, i32 0, i64 0, i32 1, i32 0, i64 0 ++ %VectorGep14 = getelementptr inbounds %Dual, %Dual* %arg1, <8 x i64> %arg2, i32 1, i32 0, i64 0, i32 1, i32 0, i64 0 ++ %0 = bitcast <8 x double*> %VectorGep14 to <8 x i64*> ++ ret <8 x i64*> %0 ++} diff --git a/deps/patches/llvm-D27397.patch b/deps/patches/llvm-D27397.patch new file mode 100644 index 0000000000000..fd18b3f3634b4 --- /dev/null +++ b/deps/patches/llvm-D27397.patch @@ -0,0 +1,101 @@ +commit 99ca52276f9ee1386866d6dff6179cfa64824621 +Author: Keno Fischer +Date: Mon Dec 5 21:25:03 2016 +0000 + + [LAA] Prevent invalid IR for loop-invariant bound in loop body + + Summary: + If LAA expands a bound that is loop invariant, but not hoisted out + of the loop body, it used to use that value anyway, causing a + non-domination error, because the memcheck block is of course not + dominated by the scalar loop body. Detect this situation and expand + the SCEV expression instead. + + Fixes PR31251 + + Reviewers: anemet + Subscribers: mzolotukhin, llvm-commits + + Differential Revision: https://reviews.llvm.org/D27397 + + git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@288705 91177308-0d34-0410-b5e6-96231b3b80d8 + +diff --git a/lib/Analysis/LoopAccessAnalysis.cpp b/lib/Analysis/LoopAccessAnalysis.cpp +index 01a2f46..2f3dca3 100644 +--- a/lib/Analysis/LoopAccessAnalysis.cpp ++++ b/lib/Analysis/LoopAccessAnalysis.cpp +@@ -1870,18 +1870,24 @@ expandBounds(const RuntimePointerChecking::CheckingPtrGroup *CG, Loop *TheLoop, + Value *Ptr = PtrRtChecking.Pointers[CG->Members[0]].PointerValue; + const SCEV *Sc = SE->getSCEV(Ptr); + ++ unsigned AS = Ptr->getType()->getPointerAddressSpace(); ++ LLVMContext &Ctx = Loc->getContext(); ++ ++ // Use this type for pointer arithmetic. ++ Type *PtrArithTy = Type::getInt8PtrTy(Ctx, AS); ++ + if (SE->isLoopInvariant(Sc, TheLoop)) { + DEBUG(dbgs() << "LAA: Adding RT check for a loop invariant ptr:" << *Ptr + << "\n"); +- return {Ptr, Ptr}; ++ // Ptr could be in the loop body. If so, expand a new one at the correct ++ // location. ++ Instruction *Inst = dyn_cast(Ptr); ++ Value *NewPtr = (Inst && TheLoop->contains(Inst)) ++ ? Exp.expandCodeFor(Sc, PtrArithTy, Loc) ++ : Ptr; ++ return {NewPtr, NewPtr}; + } else { +- unsigned AS = Ptr->getType()->getPointerAddressSpace(); +- LLVMContext &Ctx = Loc->getContext(); +- +- // Use this type for pointer arithmetic. +- Type *PtrArithTy = Type::getInt8PtrTy(Ctx, AS); + Value *Start = nullptr, *End = nullptr; +- + DEBUG(dbgs() << "LAA: Adding RT check for range:\n"); + Start = Exp.expandCodeFor(CG->Low, PtrArithTy, Loc); + End = Exp.expandCodeFor(CG->High, PtrArithTy, Loc); +diff --git a/test/Transforms/LoopVersioning/loop-invariant-bound.ll b/test/Transforms/LoopVersioning/loop-invariant-bound.ll +new file mode 100644 +index 0000000..3411adb +--- /dev/null ++++ b/test/Transforms/LoopVersioning/loop-invariant-bound.ll +@@ -0,0 +1,37 @@ ++; RUN: opt -loop-versioning -S < %s | FileCheck %s ++; Checks that when introducing check, we don't accidentally introduce non-dominating instructions ++target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" ++ ++%Dual.212 = type { %Dual.213, %Partials.215 } ++%Dual.213 = type { double, %Partials.214 } ++%Partials.214 = type { [2 x double] } ++%Partials.215 = type { [2 x %Dual.213] } ++ ++; Function Attrs: sspreq ++define void @"julia_axpy!_65480"(%Dual.212*) { ++top: ++ br label %if24 ++ ++; CHECK-NOT: %bc = bitcast i64* %v2.sroa.0.0..sroa_cast ++; CHECK: %bound0 ++ ++if24: ; preds = %if24, %top ++ %"#temp#1.sroa.3.02" = phi i64 [ undef, %top ], [ %2, %if24 ] ++ %"#temp#1.sroa.0.01" = phi i64 [ undef, %top ], [ %1, %if24 ] ++ %1 = add i64 %"#temp#1.sroa.0.01", 1 ++ %2 = add i64 %"#temp#1.sroa.3.02", 1 ++ ; This pointer is loop invariant. LAA used to re-use it from memcheck, even though it didn't dominate. ++ %v2.sroa.0.0..sroa_cast = bitcast %Dual.212* %0 to i64* ++ %v2.sroa.0.0.copyload = load i64, i64* %v2.sroa.0.0..sroa_cast, align 1 ++ %3 = add i64 %"#temp#1.sroa.0.01", -1 ++ %4 = getelementptr inbounds %Dual.212, %Dual.212* undef, i64 %3, i32 1, i32 0, i64 0, i32 1, i32 0, i64 0 ++ %5 = bitcast double* %4 to i64* ++ store i64 undef, i64* %5, align 8 ++ %notlhs27 = icmp eq i64 %2, undef ++ %notrhs28 = icmp eq i64 %1, undef ++ %6 = or i1 %notrhs28, %notlhs27 ++ br i1 %6, label %L41.L335_crit_edge, label %if24 ++ ++L41.L335_crit_edge: ; preds = %if24 ++ ret void ++} diff --git a/deps/patches/llvm-D27609-AArch64-UABS_G3.patch b/deps/patches/llvm-D27609-AArch64-UABS_G3.patch new file mode 100644 index 0000000000000..ba4a1b76d5804 --- /dev/null +++ b/deps/patches/llvm-D27609-AArch64-UABS_G3.patch @@ -0,0 +1,311 @@ +From df0ce05530fd3a0e4c283af817f4446d439647ea Mon Sep 17 00:00:00 2001 +From: yuyichao +Date: Thu, 15 Dec 2016 22:36:53 +0000 +Subject: [PATCH 1/2] Fix R_AARCH64_MOVW_UABS_G3 relocation + +Summary: The relocation is missing mask so an address that has non-zero bits in 47:43 may overwrite the register number. (Frequently shows up as target register changed to `xzr`....) + +Reviewers: t.p.northover, lhames + +Subscribers: davide, aemerson, rengolin, llvm-commits + +Differential Revision: https://reviews.llvm.org/D27609 + +git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@289880 91177308-0d34-0410-b5e6-96231b3b80d8 +--- + include/llvm/Object/ELFObjectFile.h | 2 +- + include/llvm/Object/RelocVisitor.h | 1 + + lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp | 72 +++++++++++++++------- + .../RuntimeDyld/AArch64/ELF_ARM64_BE-relocations.s | 34 ++++++++++ + .../RuntimeDyld/AArch64/ELF_ARM64_relocations.s | 33 ++++++++++ + 5 files changed, 118 insertions(+), 24 deletions(-) + create mode 100644 test/ExecutionEngine/RuntimeDyld/AArch64/ELF_ARM64_BE-relocations.s + create mode 100644 test/ExecutionEngine/RuntimeDyld/AArch64/ELF_ARM64_relocations.s + +diff --git a/include/llvm/Object/ELFObjectFile.h b/include/llvm/Object/ELFObjectFile.h +index 4209da8..69987d4 100644 +--- a/include/llvm/Object/ELFObjectFile.h ++++ b/include/llvm/Object/ELFObjectFile.h +@@ -972,7 +972,7 @@ unsigned ELFObjectFile::getArch() const { + case ELF::EM_X86_64: + return Triple::x86_64; + case ELF::EM_AARCH64: +- return Triple::aarch64; ++ return IsLittleEndian ? Triple::aarch64 : Triple::aarch64_be; + case ELF::EM_ARM: + return Triple::arm; + case ELF::EM_AVR: +diff --git a/include/llvm/Object/RelocVisitor.h b/include/llvm/Object/RelocVisitor.h +index e1926aa..3510d29 100644 +--- a/include/llvm/Object/RelocVisitor.h ++++ b/include/llvm/Object/RelocVisitor.h +@@ -86,6 +86,7 @@ private: + return RelocToApply(); + } + case Triple::aarch64: ++ case Triple::aarch64_be: + switch (RelocType) { + case llvm::ELF::R_AARCH64_ABS32: + return visitELF_AARCH64_ABS32(R, Value); +diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp +index c70e81a..a977dce 100644 +--- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp ++++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp +@@ -325,6 +325,8 @@ void RuntimeDyldELF::resolveAArch64Relocation(const SectionEntry &Section, + uint32_t *TargetPtr = + reinterpret_cast(Section.getAddressWithOffset(Offset)); + uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset); ++ // Data should use target endian. Code should always use little endian. ++ bool isBE = Arch == Triple::aarch64_be; + + DEBUG(dbgs() << "resolveAArch64Relocation, LocalAddress: 0x" + << format("%llx", Section.getAddressWithOffset(Offset)) +@@ -340,14 +342,22 @@ void RuntimeDyldELF::resolveAArch64Relocation(const SectionEntry &Section, + case ELF::R_AARCH64_ABS64: { + uint64_t *TargetPtr = + reinterpret_cast(Section.getAddressWithOffset(Offset)); +- *TargetPtr = Value + Addend; ++ if (isBE) ++ support::ubig64_t::ref{TargetPtr} = Value + Addend; ++ else ++ support::ulittle64_t::ref{TargetPtr} = Value + Addend; + break; + } + case ELF::R_AARCH64_PREL32: { + uint64_t Result = Value + Addend - FinalAddress; + assert(static_cast(Result) >= INT32_MIN && + static_cast(Result) <= UINT32_MAX); +- *TargetPtr = static_cast(Result & 0xffffffffU); ++ if (isBE) ++ support::ubig32_t::ref{TargetPtr} = ++ static_cast(Result & 0xffffffffU); ++ else ++ support::ulittle32_t::ref{TargetPtr} = ++ static_cast(Result & 0xffffffffU); + break; + } + case ELF::R_AARCH64_CALL26: // fallthrough +@@ -355,104 +365,120 @@ void RuntimeDyldELF::resolveAArch64Relocation(const SectionEntry &Section, + // Operation: S+A-P. Set Call or B immediate value to bits fff_fffc of the + // calculation. + uint64_t BranchImm = Value + Addend - FinalAddress; ++ uint32_t TargetValue = support::ulittle32_t::ref{TargetPtr}; + + // "Check that -2^27 <= result < 2^27". + assert(isInt<28>(BranchImm)); + + // AArch64 code is emitted with .rela relocations. The data already in any + // bits affected by the relocation on entry is garbage. +- *TargetPtr &= 0xfc000000U; ++ TargetValue &= 0xfc000000U; + // Immediate goes in bits 25:0 of B and BL. +- *TargetPtr |= static_cast(BranchImm & 0xffffffcU) >> 2; ++ TargetValue |= static_cast(BranchImm & 0xffffffcU) >> 2; ++ support::ulittle32_t::ref{TargetPtr} = TargetValue; + break; + } + case ELF::R_AARCH64_MOVW_UABS_G3: { + uint64_t Result = Value + Addend; ++ uint32_t TargetValue = support::ulittle32_t::ref{TargetPtr}; + + // AArch64 code is emitted with .rela relocations. The data already in any + // bits affected by the relocation on entry is garbage. +- *TargetPtr &= 0xffe0001fU; ++ TargetValue &= 0xffe0001fU; + // Immediate goes in bits 20:5 of MOVZ/MOVK instruction +- *TargetPtr |= Result >> (48 - 5); ++ TargetValue |= ((Result & 0xffff000000000000ULL) >> (48 - 5)); + // Shift must be "lsl #48", in bits 22:21 +- assert((*TargetPtr >> 21 & 0x3) == 3 && "invalid shift for relocation"); ++ assert((TargetValue >> 21 & 0x3) == 3 && "invalid shift for relocation"); ++ support::ulittle32_t::ref{TargetPtr} = TargetValue; + break; + } + case ELF::R_AARCH64_MOVW_UABS_G2_NC: { + uint64_t Result = Value + Addend; ++ uint32_t TargetValue = support::ulittle32_t::ref{TargetPtr}; + + // AArch64 code is emitted with .rela relocations. The data already in any + // bits affected by the relocation on entry is garbage. +- *TargetPtr &= 0xffe0001fU; ++ TargetValue &= 0xffe0001fU; + // Immediate goes in bits 20:5 of MOVZ/MOVK instruction +- *TargetPtr |= ((Result & 0xffff00000000ULL) >> (32 - 5)); ++ TargetValue |= ((Result & 0xffff00000000ULL) >> (32 - 5)); + // Shift must be "lsl #32", in bits 22:21 +- assert((*TargetPtr >> 21 & 0x3) == 2 && "invalid shift for relocation"); ++ assert((TargetValue >> 21 & 0x3) == 2 && "invalid shift for relocation"); ++ support::ulittle32_t::ref{TargetPtr} = TargetValue; + break; + } + case ELF::R_AARCH64_MOVW_UABS_G1_NC: { + uint64_t Result = Value + Addend; ++ uint32_t TargetValue = support::ulittle32_t::ref{TargetPtr}; + + // AArch64 code is emitted with .rela relocations. The data already in any + // bits affected by the relocation on entry is garbage. +- *TargetPtr &= 0xffe0001fU; ++ TargetValue &= 0xffe0001fU; + // Immediate goes in bits 20:5 of MOVZ/MOVK instruction +- *TargetPtr |= ((Result & 0xffff0000U) >> (16 - 5)); ++ TargetValue |= ((Result & 0xffff0000U) >> (16 - 5)); + // Shift must be "lsl #16", in bits 22:2 +- assert((*TargetPtr >> 21 & 0x3) == 1 && "invalid shift for relocation"); ++ assert((TargetValue >> 21 & 0x3) == 1 && "invalid shift for relocation"); ++ support::ulittle32_t::ref{TargetPtr} = TargetValue; + break; + } + case ELF::R_AARCH64_MOVW_UABS_G0_NC: { + uint64_t Result = Value + Addend; ++ uint32_t TargetValue = support::ulittle32_t::ref{TargetPtr}; + + // AArch64 code is emitted with .rela relocations. The data already in any + // bits affected by the relocation on entry is garbage. +- *TargetPtr &= 0xffe0001fU; ++ TargetValue &= 0xffe0001fU; + // Immediate goes in bits 20:5 of MOVZ/MOVK instruction +- *TargetPtr |= ((Result & 0xffffU) << 5); ++ TargetValue |= ((Result & 0xffffU) << 5); + // Shift must be "lsl #0", in bits 22:21. +- assert((*TargetPtr >> 21 & 0x3) == 0 && "invalid shift for relocation"); ++ assert((TargetValue >> 21 & 0x3) == 0 && "invalid shift for relocation"); ++ support::ulittle32_t::ref{TargetPtr} = TargetValue; + break; + } + case ELF::R_AARCH64_ADR_PREL_PG_HI21: { + // Operation: Page(S+A) - Page(P) + uint64_t Result = + ((Value + Addend) & ~0xfffULL) - (FinalAddress & ~0xfffULL); ++ uint32_t TargetValue = support::ulittle32_t::ref{TargetPtr}; + + // Check that -2^32 <= X < 2^32 + assert(isInt<33>(Result) && "overflow check failed for relocation"); + + // AArch64 code is emitted with .rela relocations. The data already in any + // bits affected by the relocation on entry is garbage. +- *TargetPtr &= 0x9f00001fU; ++ TargetValue &= 0x9f00001fU; + // Immediate goes in bits 30:29 + 5:23 of ADRP instruction, taken + // from bits 32:12 of X. +- *TargetPtr |= ((Result & 0x3000U) << (29 - 12)); +- *TargetPtr |= ((Result & 0x1ffffc000ULL) >> (14 - 5)); ++ TargetValue |= ((Result & 0x3000U) << (29 - 12)); ++ TargetValue |= ((Result & 0x1ffffc000ULL) >> (14 - 5)); ++ support::ulittle32_t::ref{TargetPtr} = TargetValue; + break; + } + case ELF::R_AARCH64_LDST32_ABS_LO12_NC: { + // Operation: S + A + uint64_t Result = Value + Addend; ++ uint32_t TargetValue = support::ulittle32_t::ref{TargetPtr}; + + // AArch64 code is emitted with .rela relocations. The data already in any + // bits affected by the relocation on entry is garbage. +- *TargetPtr &= 0xffc003ffU; ++ TargetValue &= 0xffc003ffU; + // Immediate goes in bits 21:10 of LD/ST instruction, taken + // from bits 11:2 of X +- *TargetPtr |= ((Result & 0xffc) << (10 - 2)); ++ TargetValue |= ((Result & 0xffc) << (10 - 2)); ++ support::ulittle32_t::ref{TargetPtr} = TargetValue; + break; + } + case ELF::R_AARCH64_LDST64_ABS_LO12_NC: { + // Operation: S + A + uint64_t Result = Value + Addend; ++ uint32_t TargetValue = support::ulittle32_t::ref{TargetPtr}; + + // AArch64 code is emitted with .rela relocations. The data already in any + // bits affected by the relocation on entry is garbage. +- *TargetPtr &= 0xffc003ffU; ++ TargetValue &= 0xffc003ffU; + // Immediate goes in bits 21:10 of LD/ST instruction, taken + // from bits 11:3 of X +- *TargetPtr |= ((Result & 0xff8) << (10 - 3)); ++ TargetValue |= ((Result & 0xff8) << (10 - 3)); ++ support::ulittle32_t::ref{TargetPtr} = TargetValue; + break; + } + } +diff --git a/test/ExecutionEngine/RuntimeDyld/AArch64/ELF_ARM64_BE-relocations.s b/test/ExecutionEngine/RuntimeDyld/AArch64/ELF_ARM64_BE-relocations.s +new file mode 100644 +index 0000000..3ba95e4 +--- /dev/null ++++ b/test/ExecutionEngine/RuntimeDyld/AArch64/ELF_ARM64_BE-relocations.s +@@ -0,0 +1,34 @@ ++# RUN: llvm-mc -triple=aarch64_be-none-linux-gnu -filetype=obj -o %T/be-reloc.o %s ++# RUN: llvm-rtdyld -triple=aarch64_be-none-linux-gnu -verify -dummy-extern f=0x0123456789abcdef -check=%s %T/be-reloc.o ++ ++ .text ++ .globl g ++ .p2align 2 ++ .type g,@function ++g: ++# R_AARCH64_MOVW_UABS_G3 ++ movz x0, #:abs_g3:f ++# R_AARCH64_MOVW_UABS_G2_NC ++ movk x0, #:abs_g2_nc:f ++# R_AARCH64_MOVW_UABS_G1_NC ++ movk x0, #:abs_g1_nc:f ++# R_AARCH64_MOVW_UABS_G0_NC ++ movk x0, #:abs_g0_nc:f ++ ret ++ .Lfunc_end0: ++ .size g, .Lfunc_end0-g ++ ++ .type k,@object ++ .data ++ .globl k ++ .p2align 3 ++k: ++ .xword f ++ .size k, 8 ++ ++# LE instructions read as BE ++# rtdyld-check: *{4}(g) = 0x6024e0d2 ++# rtdyld-check: *{4}(g + 4) = 0xe0acc8f2 ++# rtdyld-check: *{4}(g + 8) = 0x6035b1f2 ++# rtdyld-check: *{4}(g + 12) = 0xe0bd99f2 ++# rtdyld-check: *{8}k = f +diff --git a/test/ExecutionEngine/RuntimeDyld/AArch64/ELF_ARM64_relocations.s b/test/ExecutionEngine/RuntimeDyld/AArch64/ELF_ARM64_relocations.s +new file mode 100644 +index 0000000..f83f6bf +--- /dev/null ++++ b/test/ExecutionEngine/RuntimeDyld/AArch64/ELF_ARM64_relocations.s +@@ -0,0 +1,33 @@ ++# RUN: llvm-mc -triple=arm64-none-linux-gnu -filetype=obj -o %T/reloc.o %s ++# RUN: llvm-rtdyld -triple=arm64-none-linux-gnu -verify -dummy-extern f=0x0123456789abcdef -check=%s %T/reloc.o ++ ++ .text ++ .globl g ++ .p2align 2 ++ .type g,@function ++g: ++# R_AARCH64_MOVW_UABS_G3 ++ movz x0, #:abs_g3:f ++# R_AARCH64_MOVW_UABS_G2_NC ++ movk x0, #:abs_g2_nc:f ++# R_AARCH64_MOVW_UABS_G1_NC ++ movk x0, #:abs_g1_nc:f ++# R_AARCH64_MOVW_UABS_G0_NC ++ movk x0, #:abs_g0_nc:f ++ ret ++ .Lfunc_end0: ++ .size g, .Lfunc_end0-g ++ ++ .type k,@object ++ .data ++ .globl k ++ .p2align 3 ++k: ++ .xword f ++ .size k, 8 ++ ++# rtdyld-check: *{4}(g) = 0xd2e02460 ++# rtdyld-check: *{4}(g + 4) = 0xf2c8ace0 ++# rtdyld-check: *{4}(g + 8) = 0xf2b13560 ++# rtdyld-check: *{4}(g + 12) = 0xf299bde0 ++# rtdyld-check: *{8}k = f +-- +2.10.2 + diff --git a/deps/patches/llvm-D27629-AArch64-large_model.patch b/deps/patches/llvm-D27629-AArch64-large_model.patch new file mode 100644 index 0000000000000..ed288534f0690 --- /dev/null +++ b/deps/patches/llvm-D27629-AArch64-large_model.patch @@ -0,0 +1,100 @@ +From 073a3b4c0e422396016ddea15181411e45c96af5 Mon Sep 17 00:00:00 2001 +From: Yichao Yu +Date: Fri, 9 Dec 2016 15:59:46 -0500 +Subject: [PATCH 2/2] Fix unwind info relocation with large code model on + AArch64 + +--- + lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp | 10 ++++++++++ + lib/MC/MCObjectFileInfo.cpp | 2 ++ + .../AArch64/ELF_ARM64_BE-large-relocations.s | 18 ++++++++++++++++++ + .../RuntimeDyld/AArch64/ELF_ARM64_large-relocations.s | 18 ++++++++++++++++++ + 4 files changed, 48 insertions(+) + create mode 100644 test/ExecutionEngine/RuntimeDyld/AArch64/ELF_ARM64_BE-large-relocations.s + create mode 100644 test/ExecutionEngine/RuntimeDyld/AArch64/ELF_ARM64_large-relocations.s + +diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp +index a977dce..2a832f8 100644 +--- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp ++++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp +@@ -360,6 +360,16 @@ void RuntimeDyldELF::resolveAArch64Relocation(const SectionEntry &Section, + static_cast(Result & 0xffffffffU); + break; + } ++ case ELF::R_AARCH64_PREL64: { ++ uint64_t *TargetPtr = ++ reinterpret_cast(Section.getAddressWithOffset(Offset)); ++ uint64_t Result = Value + Addend - FinalAddress; ++ if (isBE) ++ support::ubig64_t::ref{TargetPtr} = Result; ++ else ++ support::ulittle64_t::ref{TargetPtr} = Result; ++ break; ++ } + case ELF::R_AARCH64_CALL26: // fallthrough + case ELF::R_AARCH64_JUMP26: { + // Operation: S+A-P. Set Call or B immediate value to bits fff_fffc of the +diff --git a/lib/MC/MCObjectFileInfo.cpp b/lib/MC/MCObjectFileInfo.cpp +index 8fd71f6..bcf774e 100644 +--- a/lib/MC/MCObjectFileInfo.cpp ++++ b/lib/MC/MCObjectFileInfo.cpp +@@ -279,6 +279,8 @@ void MCObjectFileInfo::initELFMCObjectFileInfo(const Triple &T) { + case Triple::mips64el: + FDECFIEncoding = dwarf::DW_EH_PE_sdata8; + break; ++ case Triple::aarch64: ++ case Triple::aarch64_be: + case Triple::x86_64: + FDECFIEncoding = dwarf::DW_EH_PE_pcrel | + ((CMModel == CodeModel::Large) ? dwarf::DW_EH_PE_sdata8 +diff --git a/test/ExecutionEngine/RuntimeDyld/AArch64/ELF_ARM64_BE-large-relocations.s b/test/ExecutionEngine/RuntimeDyld/AArch64/ELF_ARM64_BE-large-relocations.s +new file mode 100644 +index 0000000..e3eeb02 +--- /dev/null ++++ b/test/ExecutionEngine/RuntimeDyld/AArch64/ELF_ARM64_BE-large-relocations.s +@@ -0,0 +1,18 @@ ++# RUN: llvm-mc -triple=aarch64_be-none-linux-gnu -code-model=large -filetype=obj -o %T/be-large-reloc.o %s ++# RUN: llvm-rtdyld -triple=aarch64_be-none-linux-gnu -verify -map-section be-large-reloc.o,.eh_frame=0x10000 -map-section be-large-reloc.o,.text=0xffff000000000000 -check=%s %T/be-large-reloc.o ++ ++ .text ++ .globl g ++ .p2align 2 ++ .type g,@function ++g: ++ .cfi_startproc ++ mov x0, xzr ++ ret ++ .Lfunc_end0: ++ .size g, .Lfunc_end0-g ++ .cfi_endproc ++ ++# Skip the CIE and load the 8 bytes PC begin pointer. ++# Assuming the CIE and the FDE length are both 4 bytes. ++# rtdyld-check: *{8}(section_addr(be-large-reloc.o, .eh_frame) + (*{4}(section_addr(be-large-reloc.o, .eh_frame))) + 0xc) = g - (section_addr(be-large-reloc.o, .eh_frame) + (*{4}(section_addr(be-large-reloc.o, .eh_frame))) + 0xc) +diff --git a/test/ExecutionEngine/RuntimeDyld/AArch64/ELF_ARM64_large-relocations.s b/test/ExecutionEngine/RuntimeDyld/AArch64/ELF_ARM64_large-relocations.s +new file mode 100644 +index 0000000..ec30f19 +--- /dev/null ++++ b/test/ExecutionEngine/RuntimeDyld/AArch64/ELF_ARM64_large-relocations.s +@@ -0,0 +1,18 @@ ++# RUN: llvm-mc -triple=arm64-none-linux-gnu -code-model=large -filetype=obj -o %T/large-reloc.o %s ++# RUN: llvm-rtdyld -triple=arm64-none-linux-gnu -verify -map-section large-reloc.o,.eh_frame=0x10000 -map-section large-reloc.o,.text=0xffff000000000000 -check=%s %T/large-reloc.o ++ ++ .text ++ .globl g ++ .p2align 2 ++ .type g,@function ++g: ++ .cfi_startproc ++ mov x0, xzr ++ ret ++ .Lfunc_end0: ++ .size g, .Lfunc_end0-g ++ .cfi_endproc ++ ++# Skip the CIE and load the 8 bytes PC begin pointer. ++# Assuming the CIE and the FDE length are both 4 bytes. ++# rtdyld-check: *{8}(section_addr(large-reloc.o, .eh_frame) + (*{4}(section_addr(large-reloc.o, .eh_frame))) + 0xc) = g - (section_addr(large-reloc.o, .eh_frame) + (*{4}(section_addr(large-reloc.o, .eh_frame))) + 0xc) +-- +2.10.2 + diff --git a/deps/patches/llvm-D27629-AArch64-large_model_6.0.1.patch b/deps/patches/llvm-D27629-AArch64-large_model_6.0.1.patch deleted file mode 100644 index 89beefdd157e5..0000000000000 --- a/deps/patches/llvm-D27629-AArch64-large_model_6.0.1.patch +++ /dev/null @@ -1,53 +0,0 @@ -From f76abe65e6d07fea5e838c4f8c9a9421c16debb0 Mon Sep 17 00:00:00 2001 -From: Valentin Churavy -Date: Thu, 5 Jul 2018 12:37:50 -0400 -Subject: [PATCH] Fix unwind info relocation with large code model on AArch64 - ---- - lib/MC/MCObjectFileInfo.cpp | 2 ++ - .../AArch64/ELF_ARM64_large-relocations.s | 20 +++++++++++++++++++ - 2 files changed, 22 insertions(+) - create mode 100644 test/ExecutionEngine/RuntimeDyld/AArch64/ELF_ARM64_large-relocations.s - -diff --git a/lib/MC/MCObjectFileInfo.cpp b/lib/MC/MCObjectFileInfo.cpp -index 328f000f37c..938b35f20d1 100644 ---- a/lib/MC/MCObjectFileInfo.cpp -+++ b/lib/MC/MCObjectFileInfo.cpp -@@ -291,6 +291,8 @@ void MCObjectFileInfo::initELFMCObjectFileInfo(const Triple &T, bool Large) { - break; - case Triple::ppc64: - case Triple::ppc64le: -+ case Triple::aarch64: -+ case Triple::aarch64_be: - case Triple::x86_64: - FDECFIEncoding = dwarf::DW_EH_PE_pcrel | - (Large ? dwarf::DW_EH_PE_sdata8 : dwarf::DW_EH_PE_sdata4); -diff --git a/test/ExecutionEngine/RuntimeDyld/AArch64/ELF_ARM64_large-relocations.s b/test/ExecutionEngine/RuntimeDyld/AArch64/ELF_ARM64_large-relocations.s -new file mode 100644 -index 00000000000..66f28dabd79 ---- /dev/null -+++ b/test/ExecutionEngine/RuntimeDyld/AArch64/ELF_ARM64_large-relocations.s -@@ -0,0 +1,20 @@ -+# RUN: llvm-mc -triple=arm64-none-linux-gnu -large-code-model -filetype=obj -o %T/large-reloc.o %s -+# RUN: llvm-rtdyld -triple=arm64-none-linux-gnu -verify -map-section large-reloc.o,.eh_frame=0x10000 -map-section large-reloc.o,.text=0xffff000000000000 -check=%s %T/large-reloc.o -+# RUN-BE: llvm-mc -triple=aarch64_be-none-linux-gnu -large-code-model -filetype=obj -o %T/be-large-reloc.o %s -+# RUN-BE: llvm-rtdyld -triple=aarch64_be-none-linux-gnu -verify -map-section be-large-reloc.o,.eh_frame=0x10000 -map-section be-large-reloc.o,.text=0xffff000000000000 -check=%s %T/be-large-reloc.o -+ -+ .text -+ .globl g -+ .p2align 2 -+ .type g,@function -+g: -+ .cfi_startproc -+ mov x0, xzr -+ ret -+ .Lfunc_end0: -+ .size g, .Lfunc_end0-g -+ .cfi_endproc -+ -+# Skip the CIE and load the 8 bytes PC begin pointer. -+# Assuming the CIE and the FDE length are both 4 bytes. -+# rtdyld-check: *{8}(section_addr(large-reloc.o, .eh_frame) + (*{4}(section_addr(large-reloc.o, .eh_frame))) + 0xc) = g - (section_addr(large-reloc.o, .eh_frame) + (*{4}(section_addr(large-reloc.o, .eh_frame))) + 0xc) --- -2.18.0 - diff --git a/deps/patches/llvm-D28009.patch b/deps/patches/llvm-D28009.patch new file mode 100644 index 0000000000000..ceba0b1900130 --- /dev/null +++ b/deps/patches/llvm-D28009.patch @@ -0,0 +1,68 @@ +commit 57ab82784ddb8d21eb0041d52f8490d8fd404e29 +Author: Michael Kuperstein +Date: Wed Dec 21 17:34:21 2016 +0000 + + [ConstantFolding] Fix vector GEPs harder + + For vector GEPs, CastGEPIndices can end up in an infinite recursion, because + we compare the vector type to the scalar pointer type, find them different, + and then try to cast a type to itself. + + Differential Revision: https://reviews.llvm.org/D28009 + + + git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@290260 91177308-0d34-0410-b5e6-96231b3b80d8 + +diff --git a/lib/Analysis/ConstantFolding.cpp b/lib/Analysis/ConstantFolding.cpp +index cf0d5e4..9e521e1 100644 +--- a/lib/Analysis/ConstantFolding.cpp ++++ b/lib/Analysis/ConstantFolding.cpp +@@ -742,13 +742,16 @@ Constant *CastGEPIndices(Type *SrcElemTy, ArrayRef Ops, + if ((i == 1 || + !isa(GetElementPtrInst::getIndexedType( + SrcElemTy, Ops.slice(1, i - 1)))) && +- Ops[i]->getType() != (i == 1 ? IntPtrTy : IntPtrScalarTy)) { ++ Ops[i]->getType()->getScalarType() != IntPtrScalarTy) { + Any = true; ++ Type *NewType = Ops[i]->getType()->isVectorTy() ++ ? IntPtrTy ++ : IntPtrTy->getScalarType(); + NewIdxs.push_back(ConstantExpr::getCast(CastInst::getCastOpcode(Ops[i], + true, +- IntPtrTy, ++ NewType, + true), +- Ops[i], IntPtrTy)); ++ Ops[i], NewType)); + } else + NewIdxs.push_back(Ops[i]); + } +diff --git a/test/Analysis/ConstantFolding/vectorgep-crash.ll b/test/Analysis/ConstantFolding/vectorgep-crash.ll +index bcc96b2..e7a5117 100644 +--- a/test/Analysis/ConstantFolding/vectorgep-crash.ll ++++ b/test/Analysis/ConstantFolding/vectorgep-crash.ll +@@ -17,3 +17,24 @@ top: + %0 = bitcast <8 x double*> %VectorGep14 to <8 x i64*> + ret <8 x i64*> %0 + } ++ ++%struct.A = type { i32, %struct.B* } ++%struct.B = type { i64, %struct.C* } ++%struct.C = type { i64 } ++ ++@G = internal global [65 x %struct.A] zeroinitializer, align 16 ++; CHECK-LABEL: @test ++; CHECK: ret <16 x i32*> getelementptr ([65 x %struct.A], [65 x %struct.A]* @G, <16 x i64> zeroinitializer, <16 x i64> , <16 x i32> zeroinitializer) ++define <16 x i32*> @test() { ++vector.body: ++ %VectorGep = getelementptr [65 x %struct.A], [65 x %struct.A]* @G, <16 x i64> zeroinitializer, <16 x i64> , <16 x i32> zeroinitializer ++ ret <16 x i32*> %VectorGep ++} ++ ++; CHECK-LABEL: @test2 ++; CHECK: ret <16 x i32*> getelementptr ([65 x %struct.A], [65 x %struct.A]* @G, <16 x i64> zeroinitializer, <16 x i64> @test2() { ++vector.body: ++ %VectorGep = getelementptr [65 x %struct.A], [65 x %struct.A]* @G, <16 x i32> zeroinitializer, <16 x i64> , <16 x i32> zeroinitializer ++ ret <16 x i32*> %VectorGep ++} diff --git a/deps/patches/llvm-D28215_FreeBSD_shlib.patch b/deps/patches/llvm-D28215_FreeBSD_shlib.patch new file mode 100644 index 0000000000000..aa06a6a428db9 --- /dev/null +++ b/deps/patches/llvm-D28215_FreeBSD_shlib.patch @@ -0,0 +1,13 @@ +Index: tools/llvm-shlib/CMakeLists.txt +=================================================================== +--- a/tools/llvm-shlib/CMakeLists.txt ++++ b/tools/llvm-shlib/CMakeLists.txt +@@ -37,7 +37,7 @@ + add_llvm_library(LLVM SHARED DISABLE_LLVM_LINK_LLVM_DYLIB SONAME ${SOURCES}) + + list(REMOVE_DUPLICATES LIB_NAMES) +-if("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux" OR MINGW) # FIXME: It should be "GNU ld for elf" ++if(("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux") OR (MINGW) OR ("${CMAKE_SYSTEM_NAME}" STREQUAL "FreeBSD") OR ("${CMAKE_SYSTEM_NAME}" STREQUAL "DragonFly")) # FIXME: It should be "GNU ld for elf" + # GNU ld doesn't resolve symbols in the version script. + set(LIB_NAMES -Wl,--whole-archive ${LIB_NAMES} -Wl,--no-whole-archive) + elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "Darwin") diff --git a/deps/patches/llvm-D28221-avx512.patch b/deps/patches/llvm-D28221-avx512.patch new file mode 100644 index 0000000000000..659c814a37ebe --- /dev/null +++ b/deps/patches/llvm-D28221-avx512.patch @@ -0,0 +1,22 @@ +Index: lib/Support/Host.cpp +=================================================================== +--- a/lib/Support/Host.cpp ++++ b/lib/Support/Host.cpp +@@ -475,13 +475,14 @@ + + // Skylake: + case 0x4e: +- *Type = INTEL_COREI7; // "skylake-avx512" +- *Subtype = INTEL_COREI7_SKYLAKE_AVX512; +- break; + case 0x5e: + *Type = INTEL_COREI7; // "skylake" + *Subtype = INTEL_COREI7_SKYLAKE; + break; ++ case 0x55: ++ *Type = INTEL_COREI7; // "skylake-avx512" ++ *Subtype = INTEL_COREI7_SKYLAKE_AVX512; ++ break; + + case 0x1c: // Most 45 nm Intel Atom processors + case 0x26: // 45 nm Atom Lincroft diff --git a/deps/patches/llvm-D28476-musl-targetlibraryinfo_3.9.patch b/deps/patches/llvm-D28476-musl-targetlibraryinfo_3.9.patch new file mode 100644 index 0000000000000..764512f5066a6 --- /dev/null +++ b/deps/patches/llvm-D28476-musl-targetlibraryinfo_3.9.patch @@ -0,0 +1,3955 @@ +commit 30f85ead353e6606db51b73908dd9862b005385b +Author: David L. Jones +Date: Mon Jan 23 23:16:46 2017 +0000 + + [Analysis] Add LibFunc_ prefix to enums in TargetLibraryInfo. (NFC) + + Summary: + The LibFunc::Func enum holds enumerators named for libc functions. + Unfortunately, there are real situations, including libc implementations, where + function names are actually macros (musl uses "#define fopen64 fopen", for + example; any other transitively visible macro would have similar effects). + + Strictly speaking, a conforming C++ Standard Library should provide any such + macros as functions instead (via ). However, there are some "library" + functions which are not part of the standard, and thus not subject to this + rule (fopen64, for example). So, in order to be both portable and consistent, + the enum should not use the bare function names. + + The old enum naming used a namespace LibFunc and an enum Func, with bare + enumerators. This patch changes LibFunc to be an enum with enumerators prefixed + with "LibFFunc_". (Unfortunately, a scoped enum is not sufficient to override + macros.) + + There are additional changes required in clang. + + Reviewers: rsmith + + Subscribers: mehdi_amini, mzolotukhin, nemanjai, llvm-commits + + Differential Revision: https://reviews.llvm.org/D28476 + + git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@292848 91177308-0d34-0410-b5e6-96231b3b80d8 + +diff --git a/include/llvm/Analysis/TargetLibraryInfo.def b/include/llvm/Analysis/TargetLibraryInfo.def +index b2a593d67dc..775e2f31733 100644 +--- a/include/llvm/Analysis/TargetLibraryInfo.def ++++ b/include/llvm/Analysis/TargetLibraryInfo.def +@@ -20,7 +20,7 @@ + // One of TLI_DEFINE_ENUM/STRING are defined. + + #if defined(TLI_DEFINE_ENUM) +-#define TLI_DEFINE_ENUM_INTERNAL(enum_variant) enum_variant, ++#define TLI_DEFINE_ENUM_INTERNAL(enum_variant) LibFunc_##enum_variant, + #define TLI_DEFINE_STRING_INTERNAL(string_repr) + #else + #define TLI_DEFINE_ENUM_INTERNAL(enum_variant) +diff --git a/include/llvm/Analysis/TargetLibraryInfo.h b/include/llvm/Analysis/TargetLibraryInfo.h +index 7efa6f05970..48156de1c3b 100644 +--- a/include/llvm/Analysis/TargetLibraryInfo.h ++++ b/include/llvm/Analysis/TargetLibraryInfo.h +@@ -30,14 +30,12 @@ struct VecDesc { + unsigned VectorizationFactor; + }; + +- namespace LibFunc { +- enum Func { ++ enum LibFunc { + #define TLI_DEFINE_ENUM + #include "llvm/Analysis/TargetLibraryInfo.def" + +- NumLibFuncs +- }; +- } ++ NumLibFuncs ++ }; + + /// Implementation of the target library information. + /// +@@ -48,20 +46,20 @@ struct VecDesc { + class TargetLibraryInfoImpl { + friend class TargetLibraryInfo; + +- unsigned char AvailableArray[(LibFunc::NumLibFuncs+3)/4]; ++ unsigned char AvailableArray[(NumLibFuncs+3)/4]; + llvm::DenseMap CustomNames; +- static const char *const StandardNames[LibFunc::NumLibFuncs]; ++ static const char *const StandardNames[NumLibFuncs]; + + enum AvailabilityState { + StandardName = 3, // (memset to all ones) + CustomName = 1, + Unavailable = 0 // (memset to all zeros) + }; +- void setState(LibFunc::Func F, AvailabilityState State) { ++ void setState(LibFunc F, AvailabilityState State) { + AvailableArray[F/4] &= ~(3 << 2*(F&3)); + AvailableArray[F/4] |= State << 2*(F&3); + } +- AvailabilityState getState(LibFunc::Func F) const { ++ AvailabilityState getState(LibFunc F) const { + return static_cast((AvailableArray[F/4] >> 2*(F&3)) & 3); + } + +@@ -73,7 +71,7 @@ class TargetLibraryInfoImpl { + + /// Return true if the function type FTy is valid for the library function + /// F, regardless of whether the function is available. +- bool isValidProtoForLibFunc(const FunctionType &FTy, LibFunc::Func F, ++ bool isValidProtoForLibFunc(const FunctionType &FTy, LibFunc F, + const DataLayout *DL) const; + + public: +@@ -102,28 +100,28 @@ public: + /// + /// If it is one of the known library functions, return true and set F to the + /// corresponding value. +- bool getLibFunc(StringRef funcName, LibFunc::Func &F) const; ++ bool getLibFunc(StringRef funcName, LibFunc &F) const; + + /// Searches for a particular function name, also checking that its type is + /// valid for the library function matching that name. + /// + /// If it is one of the known library functions, return true and set F to the + /// corresponding value. +- bool getLibFunc(const Function &FDecl, LibFunc::Func &F) const; ++ bool getLibFunc(const Function &FDecl, LibFunc &F) const; + + /// Forces a function to be marked as unavailable. +- void setUnavailable(LibFunc::Func F) { ++ void setUnavailable(LibFunc F) { + setState(F, Unavailable); + } + + /// Forces a function to be marked as available. +- void setAvailable(LibFunc::Func F) { ++ void setAvailable(LibFunc F) { + setState(F, StandardName); + } + + /// Forces a function to be marked as available and provide an alternate name + /// that must be used. +- void setAvailableWithName(LibFunc::Func F, StringRef Name) { ++ void setAvailableWithName(LibFunc F, StringRef Name) { + if (StandardNames[F] != Name) { + setState(F, CustomName); + CustomNames[F] = Name; +@@ -203,16 +201,16 @@ public: + /// + /// If it is one of the known library functions, return true and set F to the + /// corresponding value. +- bool getLibFunc(StringRef funcName, LibFunc::Func &F) const { ++ bool getLibFunc(StringRef funcName, LibFunc &F) const { + return Impl->getLibFunc(funcName, F); + } + +- bool getLibFunc(const Function &FDecl, LibFunc::Func &F) const { ++ bool getLibFunc(const Function &FDecl, LibFunc &F) const { + return Impl->getLibFunc(FDecl, F); + } + + /// Tests whether a library function is available. +- bool has(LibFunc::Func F) const { ++ bool has(LibFunc F) const { + return Impl->getState(F) != TargetLibraryInfoImpl::Unavailable; + } + bool isFunctionVectorizable(StringRef F, unsigned VF) const { +@@ -227,37 +225,37 @@ public: + + /// Tests if the function is both available and a candidate for optimized code + /// generation. +- bool hasOptimizedCodeGen(LibFunc::Func F) const { ++ bool hasOptimizedCodeGen(LibFunc F) const { + if (Impl->getState(F) == TargetLibraryInfoImpl::Unavailable) + return false; + switch (F) { + default: break; +- case LibFunc::copysign: case LibFunc::copysignf: case LibFunc::copysignl: +- case LibFunc::fabs: case LibFunc::fabsf: case LibFunc::fabsl: +- case LibFunc::sin: case LibFunc::sinf: case LibFunc::sinl: +- case LibFunc::cos: case LibFunc::cosf: case LibFunc::cosl: +- case LibFunc::sqrt: case LibFunc::sqrtf: case LibFunc::sqrtl: +- case LibFunc::sqrt_finite: case LibFunc::sqrtf_finite: +- case LibFunc::sqrtl_finite: +- case LibFunc::fmax: case LibFunc::fmaxf: case LibFunc::fmaxl: +- case LibFunc::fmin: case LibFunc::fminf: case LibFunc::fminl: +- case LibFunc::floor: case LibFunc::floorf: case LibFunc::floorl: +- case LibFunc::nearbyint: case LibFunc::nearbyintf: case LibFunc::nearbyintl: +- case LibFunc::ceil: case LibFunc::ceilf: case LibFunc::ceill: +- case LibFunc::rint: case LibFunc::rintf: case LibFunc::rintl: +- case LibFunc::round: case LibFunc::roundf: case LibFunc::roundl: +- case LibFunc::trunc: case LibFunc::truncf: case LibFunc::truncl: +- case LibFunc::log2: case LibFunc::log2f: case LibFunc::log2l: +- case LibFunc::exp2: case LibFunc::exp2f: case LibFunc::exp2l: +- case LibFunc::memcmp: case LibFunc::strcmp: case LibFunc::strcpy: +- case LibFunc::stpcpy: case LibFunc::strlen: case LibFunc::strnlen: +- case LibFunc::memchr: ++ case LibFunc_copysign: case LibFunc_copysignf: case LibFunc_copysignl: ++ case LibFunc_fabs: case LibFunc_fabsf: case LibFunc_fabsl: ++ case LibFunc_sin: case LibFunc_sinf: case LibFunc_sinl: ++ case LibFunc_cos: case LibFunc_cosf: case LibFunc_cosl: ++ case LibFunc_sqrt: case LibFunc_sqrtf: case LibFunc_sqrtl: ++ case LibFunc_sqrt_finite: case LibFunc_sqrtf_finite: ++ case LibFunc_sqrtl_finite: ++ case LibFunc_fmax: case LibFunc_fmaxf: case LibFunc_fmaxl: ++ case LibFunc_fmin: case LibFunc_fminf: case LibFunc_fminl: ++ case LibFunc_floor: case LibFunc_floorf: case LibFunc_floorl: ++ case LibFunc_nearbyint: case LibFunc_nearbyintf: case LibFunc_nearbyintl: ++ case LibFunc_ceil: case LibFunc_ceilf: case LibFunc_ceill: ++ case LibFunc_rint: case LibFunc_rintf: case LibFunc_rintl: ++ case LibFunc_round: case LibFunc_roundf: case LibFunc_roundl: ++ case LibFunc_trunc: case LibFunc_truncf: case LibFunc_truncl: ++ case LibFunc_log2: case LibFunc_log2f: case LibFunc_log2l: ++ case LibFunc_exp2: case LibFunc_exp2f: case LibFunc_exp2l: ++ case LibFunc_memcmp: case LibFunc_strcmp: case LibFunc_strcpy: ++ case LibFunc_stpcpy: case LibFunc_strlen: case LibFunc_strnlen: ++ case LibFunc_memchr: + return true; + } + return false; + } + +- StringRef getName(LibFunc::Func F) const { ++ StringRef getName(LibFunc F) const { + auto State = Impl->getState(F); + if (State == TargetLibraryInfoImpl::Unavailable) + return StringRef(); +diff --git a/include/llvm/Transforms/Utils/SimplifyLibCalls.h b/include/llvm/Transforms/Utils/SimplifyLibCalls.h +index 92ee2463395..a294ebae4b6 100644 +--- a/include/llvm/Transforms/Utils/SimplifyLibCalls.h ++++ b/include/llvm/Transforms/Utils/SimplifyLibCalls.h +@@ -56,8 +56,8 @@ private: + Value *optimizeMemSetChk(CallInst *CI, IRBuilder<> &B); + + // Str/Stp cpy are similar enough to be handled in the same functions. +- Value *optimizeStrpCpyChk(CallInst *CI, IRBuilder<> &B, LibFunc::Func Func); +- Value *optimizeStrpNCpyChk(CallInst *CI, IRBuilder<> &B, LibFunc::Func Func); ++ Value *optimizeStrpCpyChk(CallInst *CI, IRBuilder<> &B, LibFunc Func); ++ Value *optimizeStrpNCpyChk(CallInst *CI, IRBuilder<> &B, LibFunc Func); + + /// \brief Checks whether the call \p CI to a fortified libcall is foldable + /// to the non-fortified version. +diff --git a/lib/Analysis/BasicAliasAnalysis.cpp b/lib/Analysis/BasicAliasAnalysis.cpp +index 43d5c3ccf90..cce9aa5c2c0 100644 +--- a/lib/Analysis/BasicAliasAnalysis.cpp ++++ b/lib/Analysis/BasicAliasAnalysis.cpp +@@ -619,9 +619,9 @@ static bool isWriteOnlyParam(ImmutableCallSite CS, unsigned ArgIdx, + // whenever possible. + // FIXME Consider handling this in InferFunctionAttr.cpp together with other + // attributes. +- LibFunc::Func F; ++ LibFunc F; + if (CS.getCalledFunction() && TLI.getLibFunc(*CS.getCalledFunction(), F) && +- F == LibFunc::memset_pattern16 && TLI.has(F)) ++ F == LibFunc_memset_pattern16 && TLI.has(F)) + if (ArgIdx == 0) + return true; + +diff --git a/lib/Analysis/ConstantFolding.cpp b/lib/Analysis/ConstantFolding.cpp +index c9adaa7b111..9672dcfdf97 100644 +--- a/lib/Analysis/ConstantFolding.cpp ++++ b/lib/Analysis/ConstantFolding.cpp +@@ -1554,51 +1554,51 @@ Constant *ConstantFoldScalarCall(StringRef Name, unsigned IntrinsicID, Type *Ty, + + switch (Name[0]) { + case 'a': +- if ((Name == "acos" && TLI->has(LibFunc::acos)) || +- (Name == "acosf" && TLI->has(LibFunc::acosf))) ++ if ((Name == "acos" && TLI->has(LibFunc_acos)) || ++ (Name == "acosf" && TLI->has(LibFunc_acosf))) + return ConstantFoldFP(acos, V, Ty); +- else if ((Name == "asin" && TLI->has(LibFunc::asin)) || +- (Name == "asinf" && TLI->has(LibFunc::asinf))) ++ else if ((Name == "asin" && TLI->has(LibFunc_asin)) || ++ (Name == "asinf" && TLI->has(LibFunc_asinf))) + return ConstantFoldFP(asin, V, Ty); +- else if ((Name == "atan" && TLI->has(LibFunc::atan)) || +- (Name == "atanf" && TLI->has(LibFunc::atanf))) ++ else if ((Name == "atan" && TLI->has(LibFunc_atan)) || ++ (Name == "atanf" && TLI->has(LibFunc_atanf))) + return ConstantFoldFP(atan, V, Ty); + break; + case 'c': +- if ((Name == "ceil" && TLI->has(LibFunc::ceil)) || +- (Name == "ceilf" && TLI->has(LibFunc::ceilf))) ++ if ((Name == "ceil" && TLI->has(LibFunc_ceil)) || ++ (Name == "ceilf" && TLI->has(LibFunc_ceilf))) + return ConstantFoldFP(ceil, V, Ty); +- else if ((Name == "cos" && TLI->has(LibFunc::cos)) || +- (Name == "cosf" && TLI->has(LibFunc::cosf))) ++ else if ((Name == "cos" && TLI->has(LibFunc_cos)) || ++ (Name == "cosf" && TLI->has(LibFunc_cosf))) + return ConstantFoldFP(cos, V, Ty); +- else if ((Name == "cosh" && TLI->has(LibFunc::cosh)) || +- (Name == "coshf" && TLI->has(LibFunc::coshf))) ++ else if ((Name == "cosh" && TLI->has(LibFunc_cosh)) || ++ (Name == "coshf" && TLI->has(LibFunc_coshf))) + return ConstantFoldFP(cosh, V, Ty); + break; + case 'e': +- if ((Name == "exp" && TLI->has(LibFunc::exp)) || +- (Name == "expf" && TLI->has(LibFunc::expf))) ++ if ((Name == "exp" && TLI->has(LibFunc_exp)) || ++ (Name == "expf" && TLI->has(LibFunc_expf))) + return ConstantFoldFP(exp, V, Ty); +- if ((Name == "exp2" && TLI->has(LibFunc::exp2)) || +- (Name == "exp2f" && TLI->has(LibFunc::exp2f))) ++ if ((Name == "exp2" && TLI->has(LibFunc_exp2)) || ++ (Name == "exp2f" && TLI->has(LibFunc_exp2f))) + // Constant fold exp2(x) as pow(2,x) in case the host doesn't have a + // C99 library. + return ConstantFoldBinaryFP(pow, 2.0, V, Ty); + break; + case 'f': +- if ((Name == "fabs" && TLI->has(LibFunc::fabs)) || +- (Name == "fabsf" && TLI->has(LibFunc::fabsf))) ++ if ((Name == "fabs" && TLI->has(LibFunc_fabs)) || ++ (Name == "fabsf" && TLI->has(LibFunc_fabsf))) + return ConstantFoldFP(fabs, V, Ty); +- else if ((Name == "floor" && TLI->has(LibFunc::floor)) || +- (Name == "floorf" && TLI->has(LibFunc::floorf))) ++ else if ((Name == "floor" && TLI->has(LibFunc_floor)) || ++ (Name == "floorf" && TLI->has(LibFunc_floorf))) + return ConstantFoldFP(floor, V, Ty); + break; + case 'l': +- if ((Name == "log" && V > 0 && TLI->has(LibFunc::log)) || +- (Name == "logf" && V > 0 && TLI->has(LibFunc::logf))) ++ if ((Name == "log" && V > 0 && TLI->has(LibFunc_log)) || ++ (Name == "logf" && V > 0 && TLI->has(LibFunc_logf))) + return ConstantFoldFP(log, V, Ty); +- else if ((Name == "log10" && V > 0 && TLI->has(LibFunc::log10)) || +- (Name == "log10f" && V > 0 && TLI->has(LibFunc::log10f))) ++ else if ((Name == "log10" && V > 0 && TLI->has(LibFunc_log10)) || ++ (Name == "log10f" && V > 0 && TLI->has(LibFunc_log10f))) + return ConstantFoldFP(log10, V, Ty); + else if (IntrinsicID == Intrinsic::sqrt && + (Ty->isHalfTy() || Ty->isFloatTy() || Ty->isDoubleTy())) { +@@ -1615,22 +1615,22 @@ Constant *ConstantFoldScalarCall(StringRef Name, unsigned IntrinsicID, Type *Ty, + } + break; + case 's': +- if ((Name == "sin" && TLI->has(LibFunc::sin)) || +- (Name == "sinf" && TLI->has(LibFunc::sinf))) ++ if ((Name == "sin" && TLI->has(LibFunc_sin)) || ++ (Name == "sinf" && TLI->has(LibFunc_sinf))) + return ConstantFoldFP(sin, V, Ty); +- else if ((Name == "sinh" && TLI->has(LibFunc::sinh)) || +- (Name == "sinhf" && TLI->has(LibFunc::sinhf))) ++ else if ((Name == "sinh" && TLI->has(LibFunc_sinh)) || ++ (Name == "sinhf" && TLI->has(LibFunc_sinhf))) + return ConstantFoldFP(sinh, V, Ty); +- else if ((Name == "sqrt" && V >= 0 && TLI->has(LibFunc::sqrt)) || +- (Name == "sqrtf" && V >= 0 && TLI->has(LibFunc::sqrtf))) ++ else if ((Name == "sqrt" && V >= 0 && TLI->has(LibFunc_sqrt)) || ++ (Name == "sqrtf" && V >= 0 && TLI->has(LibFunc_sqrtf))) + return ConstantFoldFP(sqrt, V, Ty); + break; + case 't': +- if ((Name == "tan" && TLI->has(LibFunc::tan)) || +- (Name == "tanf" && TLI->has(LibFunc::tanf))) ++ if ((Name == "tan" && TLI->has(LibFunc_tan)) || ++ (Name == "tanf" && TLI->has(LibFunc_tanf))) + return ConstantFoldFP(tan, V, Ty); +- else if ((Name == "tanh" && TLI->has(LibFunc::tanh)) || +- (Name == "tanhf" && TLI->has(LibFunc::tanhf))) ++ else if ((Name == "tanh" && TLI->has(LibFunc_tanh)) || ++ (Name == "tanhf" && TLI->has(LibFunc_tanhf))) + return ConstantFoldFP(tanh, V, Ty); + break; + default: +@@ -1735,14 +1735,14 @@ Constant *ConstantFoldScalarCall(StringRef Name, unsigned IntrinsicID, Type *Ty, + + if (!TLI) + return nullptr; +- if ((Name == "pow" && TLI->has(LibFunc::pow)) || +- (Name == "powf" && TLI->has(LibFunc::powf))) ++ if ((Name == "pow" && TLI->has(LibFunc_pow)) || ++ (Name == "powf" && TLI->has(LibFunc_powf))) + return ConstantFoldBinaryFP(pow, Op1V, Op2V, Ty); +- if ((Name == "fmod" && TLI->has(LibFunc::fmod)) || +- (Name == "fmodf" && TLI->has(LibFunc::fmodf))) ++ if ((Name == "fmod" && TLI->has(LibFunc_fmod)) || ++ (Name == "fmodf" && TLI->has(LibFunc_fmodf))) + return ConstantFoldBinaryFP(fmod, Op1V, Op2V, Ty); +- if ((Name == "atan2" && TLI->has(LibFunc::atan2)) || +- (Name == "atan2f" && TLI->has(LibFunc::atan2f))) ++ if ((Name == "atan2" && TLI->has(LibFunc_atan2)) || ++ (Name == "atan2f" && TLI->has(LibFunc_atan2f))) + return ConstantFoldBinaryFP(atan2, Op1V, Op2V, Ty); + } else if (auto *Op2C = dyn_cast(Operands[1])) { + if (IntrinsicID == Intrinsic::powi && Ty->isHalfTy()) +diff --git a/lib/Analysis/MemoryBuiltins.cpp b/lib/Analysis/MemoryBuiltins.cpp +index f23477622be..89e7a358d4b 100644 +--- a/lib/Analysis/MemoryBuiltins.cpp ++++ b/lib/Analysis/MemoryBuiltins.cpp +@@ -50,30 +50,30 @@ struct AllocFnsTy { + + // FIXME: certain users need more information. E.g., SimplifyLibCalls needs to + // know which functions are nounwind, noalias, nocapture parameters, etc. +-static const std::pair AllocationFnData[] = { +- {LibFunc::malloc, {MallocLike, 1, 0, -1}}, +- {LibFunc::valloc, {MallocLike, 1, 0, -1}}, +- {LibFunc::Znwj, {OpNewLike, 1, 0, -1}}, // new(unsigned int) +- {LibFunc::ZnwjRKSt9nothrow_t, {MallocLike, 2, 0, -1}}, // new(unsigned int, nothrow) +- {LibFunc::Znwm, {OpNewLike, 1, 0, -1}}, // new(unsigned long) +- {LibFunc::ZnwmRKSt9nothrow_t, {MallocLike, 2, 0, -1}}, // new(unsigned long, nothrow) +- {LibFunc::Znaj, {OpNewLike, 1, 0, -1}}, // new[](unsigned int) +- {LibFunc::ZnajRKSt9nothrow_t, {MallocLike, 2, 0, -1}}, // new[](unsigned int, nothrow) +- {LibFunc::Znam, {OpNewLike, 1, 0, -1}}, // new[](unsigned long) +- {LibFunc::ZnamRKSt9nothrow_t, {MallocLike, 2, 0, -1}}, // new[](unsigned long, nothrow) +- {LibFunc::msvc_new_int, {OpNewLike, 1, 0, -1}}, // new(unsigned int) +- {LibFunc::msvc_new_int_nothrow, {MallocLike, 2, 0, -1}}, // new(unsigned int, nothrow) +- {LibFunc::msvc_new_longlong, {OpNewLike, 1, 0, -1}}, // new(unsigned long long) +- {LibFunc::msvc_new_longlong_nothrow, {MallocLike, 2, 0, -1}}, // new(unsigned long long, nothrow) +- {LibFunc::msvc_new_array_int, {OpNewLike, 1, 0, -1}}, // new[](unsigned int) +- {LibFunc::msvc_new_array_int_nothrow, {MallocLike, 2, 0, -1}}, // new[](unsigned int, nothrow) +- {LibFunc::msvc_new_array_longlong, {OpNewLike, 1, 0, -1}}, // new[](unsigned long long) +- {LibFunc::msvc_new_array_longlong_nothrow, {MallocLike, 2, 0, -1}}, // new[](unsigned long long, nothrow) +- {LibFunc::calloc, {CallocLike, 2, 0, 1}}, +- {LibFunc::realloc, {ReallocLike, 2, 1, -1}}, +- {LibFunc::reallocf, {ReallocLike, 2, 1, -1}}, +- {LibFunc::strdup, {StrDupLike, 1, -1, -1}}, +- {LibFunc::strndup, {StrDupLike, 2, 1, -1}} ++static const std::pair AllocationFnData[] = { ++ {LibFunc_malloc, {MallocLike, 1, 0, -1}}, ++ {LibFunc_valloc, {MallocLike, 1, 0, -1}}, ++ {LibFunc_Znwj, {OpNewLike, 1, 0, -1}}, // new(unsigned int) ++ {LibFunc_ZnwjRKSt9nothrow_t, {MallocLike, 2, 0, -1}}, // new(unsigned int, nothrow) ++ {LibFunc_Znwm, {OpNewLike, 1, 0, -1}}, // new(unsigned long) ++ {LibFunc_ZnwmRKSt9nothrow_t, {MallocLike, 2, 0, -1}}, // new(unsigned long, nothrow) ++ {LibFunc_Znaj, {OpNewLike, 1, 0, -1}}, // new[](unsigned int) ++ {LibFunc_ZnajRKSt9nothrow_t, {MallocLike, 2, 0, -1}}, // new[](unsigned int, nothrow) ++ {LibFunc_Znam, {OpNewLike, 1, 0, -1}}, // new[](unsigned long) ++ {LibFunc_ZnamRKSt9nothrow_t, {MallocLike, 2, 0, -1}}, // new[](unsigned long, nothrow) ++ {LibFunc_msvc_new_int, {OpNewLike, 1, 0, -1}}, // new(unsigned int) ++ {LibFunc_msvc_new_int_nothrow, {MallocLike, 2, 0, -1}}, // new(unsigned int, nothrow) ++ {LibFunc_msvc_new_longlong, {OpNewLike, 1, 0, -1}}, // new(unsigned long long) ++ {LibFunc_msvc_new_longlong_nothrow, {MallocLike, 2, 0, -1}}, // new(unsigned long long, nothrow) ++ {LibFunc_msvc_new_array_int, {OpNewLike, 1, 0, -1}}, // new[](unsigned int) ++ {LibFunc_msvc_new_array_int_nothrow, {MallocLike, 2, 0, -1}}, // new[](unsigned int, nothrow) ++ {LibFunc_msvc_new_array_longlong, {OpNewLike, 1, 0, -1}}, // new[](unsigned long long) ++ {LibFunc_msvc_new_array_longlong_nothrow, {MallocLike, 2, 0, -1}}, // new[](unsigned long long, nothrow) ++ {LibFunc_calloc, {CallocLike, 2, 0, 1}}, ++ {LibFunc_realloc, {ReallocLike, 2, 1, -1}}, ++ {LibFunc_reallocf, {ReallocLike, 2, 1, -1}}, ++ {LibFunc_strdup, {StrDupLike, 1, -1, -1}}, ++ {LibFunc_strndup, {StrDupLike, 2, 1, -1}} + // TODO: Handle "int posix_memalign(void **, size_t, size_t)" + }; + +@@ -130,13 +130,13 @@ static Optional getAllocationData(const Value *V, AllocType AllocTy, + + // Make sure that the function is available. + StringRef FnName = Callee->getName(); +- LibFunc::Func TLIFn; ++ LibFunc TLIFn; + if (!TLI || !TLI->getLibFunc(FnName, TLIFn) || !TLI->has(TLIFn)) + return None; + + const auto *Iter = + std::find_if(std::begin(AllocationFnData), std::end(AllocationFnData), +- [TLIFn](const std::pair &P) { ++ [TLIFn](const std::pair &P) { + return P.first == TLIFn; + }); + +@@ -316,33 +316,33 @@ const CallInst *llvm::isFreeCall(const Value *I, const TargetLibraryInfo *TLI) { + return nullptr; + + StringRef FnName = Callee->getName(); +- LibFunc::Func TLIFn; ++ LibFunc TLIFn; + if (!TLI || !TLI->getLibFunc(FnName, TLIFn) || !TLI->has(TLIFn)) + return nullptr; + + unsigned ExpectedNumParams; +- if (TLIFn == LibFunc::free || +- TLIFn == LibFunc::ZdlPv || // operator delete(void*) +- TLIFn == LibFunc::ZdaPv || // operator delete[](void*) +- TLIFn == LibFunc::msvc_delete_ptr32 || // operator delete(void*) +- TLIFn == LibFunc::msvc_delete_ptr64 || // operator delete(void*) +- TLIFn == LibFunc::msvc_delete_array_ptr32 || // operator delete[](void*) +- TLIFn == LibFunc::msvc_delete_array_ptr64) // operator delete[](void*) ++ if (TLIFn == LibFunc_free || ++ TLIFn == LibFunc_ZdlPv || // operator delete(void*) ++ TLIFn == LibFunc_ZdaPv || // operator delete[](void*) ++ TLIFn == LibFunc_msvc_delete_ptr32 || // operator delete(void*) ++ TLIFn == LibFunc_msvc_delete_ptr64 || // operator delete(void*) ++ TLIFn == LibFunc_msvc_delete_array_ptr32 || // operator delete[](void*) ++ TLIFn == LibFunc_msvc_delete_array_ptr64) // operator delete[](void*) + ExpectedNumParams = 1; +- else if (TLIFn == LibFunc::ZdlPvj || // delete(void*, uint) +- TLIFn == LibFunc::ZdlPvm || // delete(void*, ulong) +- TLIFn == LibFunc::ZdlPvRKSt9nothrow_t || // delete(void*, nothrow) +- TLIFn == LibFunc::ZdaPvj || // delete[](void*, uint) +- TLIFn == LibFunc::ZdaPvm || // delete[](void*, ulong) +- TLIFn == LibFunc::ZdaPvRKSt9nothrow_t || // delete[](void*, nothrow) +- TLIFn == LibFunc::msvc_delete_ptr32_int || // delete(void*, uint) +- TLIFn == LibFunc::msvc_delete_ptr64_longlong || // delete(void*, ulonglong) +- TLIFn == LibFunc::msvc_delete_ptr32_nothrow || // delete(void*, nothrow) +- TLIFn == LibFunc::msvc_delete_ptr64_nothrow || // delete(void*, nothrow) +- TLIFn == LibFunc::msvc_delete_array_ptr32_int || // delete[](void*, uint) +- TLIFn == LibFunc::msvc_delete_array_ptr64_longlong || // delete[](void*, ulonglong) +- TLIFn == LibFunc::msvc_delete_array_ptr32_nothrow || // delete[](void*, nothrow) +- TLIFn == LibFunc::msvc_delete_array_ptr64_nothrow) // delete[](void*, nothrow) ++ else if (TLIFn == LibFunc_ZdlPvj || // delete(void*, uint) ++ TLIFn == LibFunc_ZdlPvm || // delete(void*, ulong) ++ TLIFn == LibFunc_ZdlPvRKSt9nothrow_t || // delete(void*, nothrow) ++ TLIFn == LibFunc_ZdaPvj || // delete[](void*, uint) ++ TLIFn == LibFunc_ZdaPvm || // delete[](void*, ulong) ++ TLIFn == LibFunc_ZdaPvRKSt9nothrow_t || // delete[](void*, nothrow) ++ TLIFn == LibFunc_msvc_delete_ptr32_int || // delete(void*, uint) ++ TLIFn == LibFunc_msvc_delete_ptr64_longlong || // delete(void*, ulonglong) ++ TLIFn == LibFunc_msvc_delete_ptr32_nothrow || // delete(void*, nothrow) ++ TLIFn == LibFunc_msvc_delete_ptr64_nothrow || // delete(void*, nothrow) ++ TLIFn == LibFunc_msvc_delete_array_ptr32_int || // delete[](void*, uint) ++ TLIFn == LibFunc_msvc_delete_array_ptr64_longlong || // delete[](void*, ulonglong) ++ TLIFn == LibFunc_msvc_delete_array_ptr32_nothrow || // delete[](void*, nothrow) ++ TLIFn == LibFunc_msvc_delete_array_ptr64_nothrow) // delete[](void*, nothrow) + ExpectedNumParams = 2; + else + return nullptr; +diff --git a/lib/Analysis/MemoryLocation.cpp b/lib/Analysis/MemoryLocation.cpp +index a0ae72f1415..9db6c499129 100644 +--- a/lib/Analysis/MemoryLocation.cpp ++++ b/lib/Analysis/MemoryLocation.cpp +@@ -142,9 +142,9 @@ MemoryLocation MemoryLocation::getForArgument(ImmutableCallSite CS, + // for memcpy/memset. This is particularly important because the + // LoopIdiomRecognizer likes to turn loops into calls to memset_pattern16 + // whenever possible. +- LibFunc::Func F; ++ LibFunc F; + if (CS.getCalledFunction() && TLI.getLibFunc(*CS.getCalledFunction(), F) && +- F == LibFunc::memset_pattern16 && TLI.has(F)) { ++ F == LibFunc_memset_pattern16 && TLI.has(F)) { + assert((ArgIdx == 0 || ArgIdx == 1) && + "Invalid argument index for memset_pattern16"); + if (ArgIdx == 1) +diff --git a/lib/Analysis/TargetLibraryInfo.cpp b/lib/Analysis/TargetLibraryInfo.cpp +index 93d537ad3ab..0895b8a6cfa 100644 +--- a/lib/Analysis/TargetLibraryInfo.cpp ++++ b/lib/Analysis/TargetLibraryInfo.cpp +@@ -62,24 +62,24 @@ static void initialize(TargetLibraryInfoImpl &TLI, const Triple &T, + + if (T.getArch() == Triple::r600 || + T.getArch() == Triple::amdgcn) { +- TLI.setUnavailable(LibFunc::ldexp); +- TLI.setUnavailable(LibFunc::ldexpf); +- TLI.setUnavailable(LibFunc::ldexpl); +- TLI.setUnavailable(LibFunc::exp10); +- TLI.setUnavailable(LibFunc::exp10f); +- TLI.setUnavailable(LibFunc::exp10l); +- TLI.setUnavailable(LibFunc::log10); +- TLI.setUnavailable(LibFunc::log10f); +- TLI.setUnavailable(LibFunc::log10l); ++ TLI.setUnavailable(LibFunc_ldexp); ++ TLI.setUnavailable(LibFunc_ldexpf); ++ TLI.setUnavailable(LibFunc_ldexpl); ++ TLI.setUnavailable(LibFunc_exp10); ++ TLI.setUnavailable(LibFunc_exp10f); ++ TLI.setUnavailable(LibFunc_exp10l); ++ TLI.setUnavailable(LibFunc_log10); ++ TLI.setUnavailable(LibFunc_log10f); ++ TLI.setUnavailable(LibFunc_log10l); + } + + // There are no library implementations of mempcy and memset for AMD gpus and + // these can be difficult to lower in the backend. + if (T.getArch() == Triple::r600 || + T.getArch() == Triple::amdgcn) { +- TLI.setUnavailable(LibFunc::memcpy); +- TLI.setUnavailable(LibFunc::memset); +- TLI.setUnavailable(LibFunc::memset_pattern16); ++ TLI.setUnavailable(LibFunc_memcpy); ++ TLI.setUnavailable(LibFunc_memset); ++ TLI.setUnavailable(LibFunc_memset_pattern16); + return; + } + +@@ -87,21 +87,21 @@ static void initialize(TargetLibraryInfoImpl &TLI, const Triple &T, + // All versions of watchOS support it. + if (T.isMacOSX()) { + if (T.isMacOSXVersionLT(10, 5)) +- TLI.setUnavailable(LibFunc::memset_pattern16); ++ TLI.setUnavailable(LibFunc_memset_pattern16); + } else if (T.isiOS()) { + if (T.isOSVersionLT(3, 0)) +- TLI.setUnavailable(LibFunc::memset_pattern16); ++ TLI.setUnavailable(LibFunc_memset_pattern16); + } else if (!T.isWatchOS()) { +- TLI.setUnavailable(LibFunc::memset_pattern16); ++ TLI.setUnavailable(LibFunc_memset_pattern16); + } + + if (!hasSinCosPiStret(T)) { +- TLI.setUnavailable(LibFunc::sinpi); +- TLI.setUnavailable(LibFunc::sinpif); +- TLI.setUnavailable(LibFunc::cospi); +- TLI.setUnavailable(LibFunc::cospif); +- TLI.setUnavailable(LibFunc::sincospi_stret); +- TLI.setUnavailable(LibFunc::sincospif_stret); ++ TLI.setUnavailable(LibFunc_sinpi); ++ TLI.setUnavailable(LibFunc_sinpif); ++ TLI.setUnavailable(LibFunc_cospi); ++ TLI.setUnavailable(LibFunc_cospif); ++ TLI.setUnavailable(LibFunc_sincospi_stret); ++ TLI.setUnavailable(LibFunc_sincospif_stret); + } + + if (T.isMacOSX() && T.getArch() == Triple::x86 && +@@ -111,179 +111,179 @@ static void initialize(TargetLibraryInfoImpl &TLI, const Triple &T, + // has a $UNIX2003 suffix. The two implementations are identical except + // for the return value in some edge cases. However, we don't want to + // generate code that depends on the old symbols. +- TLI.setAvailableWithName(LibFunc::fwrite, "fwrite$UNIX2003"); +- TLI.setAvailableWithName(LibFunc::fputs, "fputs$UNIX2003"); ++ TLI.setAvailableWithName(LibFunc_fwrite, "fwrite$UNIX2003"); ++ TLI.setAvailableWithName(LibFunc_fputs, "fputs$UNIX2003"); + } + + // iprintf and friends are only available on XCore and TCE. + if (T.getArch() != Triple::xcore && T.getArch() != Triple::tce) { +- TLI.setUnavailable(LibFunc::iprintf); +- TLI.setUnavailable(LibFunc::siprintf); +- TLI.setUnavailable(LibFunc::fiprintf); ++ TLI.setUnavailable(LibFunc_iprintf); ++ TLI.setUnavailable(LibFunc_siprintf); ++ TLI.setUnavailable(LibFunc_fiprintf); + } + + if (T.isOSWindows() && !T.isOSCygMing()) { + // Win32 does not support long double +- TLI.setUnavailable(LibFunc::acosl); +- TLI.setUnavailable(LibFunc::asinl); +- TLI.setUnavailable(LibFunc::atanl); +- TLI.setUnavailable(LibFunc::atan2l); +- TLI.setUnavailable(LibFunc::ceill); +- TLI.setUnavailable(LibFunc::copysignl); +- TLI.setUnavailable(LibFunc::cosl); +- TLI.setUnavailable(LibFunc::coshl); +- TLI.setUnavailable(LibFunc::expl); +- TLI.setUnavailable(LibFunc::fabsf); // Win32 and Win64 both lack fabsf +- TLI.setUnavailable(LibFunc::fabsl); +- TLI.setUnavailable(LibFunc::floorl); +- TLI.setUnavailable(LibFunc::fmaxl); +- TLI.setUnavailable(LibFunc::fminl); +- TLI.setUnavailable(LibFunc::fmodl); +- TLI.setUnavailable(LibFunc::frexpl); +- TLI.setUnavailable(LibFunc::ldexpf); +- TLI.setUnavailable(LibFunc::ldexpl); +- TLI.setUnavailable(LibFunc::logl); +- TLI.setUnavailable(LibFunc::modfl); +- TLI.setUnavailable(LibFunc::powl); +- TLI.setUnavailable(LibFunc::sinl); +- TLI.setUnavailable(LibFunc::sinhl); +- TLI.setUnavailable(LibFunc::sqrtl); +- TLI.setUnavailable(LibFunc::tanl); +- TLI.setUnavailable(LibFunc::tanhl); ++ TLI.setUnavailable(LibFunc_acosl); ++ TLI.setUnavailable(LibFunc_asinl); ++ TLI.setUnavailable(LibFunc_atanl); ++ TLI.setUnavailable(LibFunc_atan2l); ++ TLI.setUnavailable(LibFunc_ceill); ++ TLI.setUnavailable(LibFunc_copysignl); ++ TLI.setUnavailable(LibFunc_cosl); ++ TLI.setUnavailable(LibFunc_coshl); ++ TLI.setUnavailable(LibFunc_expl); ++ TLI.setUnavailable(LibFunc_fabsf); // Win32 and Win64 both lack fabsf ++ TLI.setUnavailable(LibFunc_fabsl); ++ TLI.setUnavailable(LibFunc_floorl); ++ TLI.setUnavailable(LibFunc_fmaxl); ++ TLI.setUnavailable(LibFunc_fminl); ++ TLI.setUnavailable(LibFunc_fmodl); ++ TLI.setUnavailable(LibFunc_frexpl); ++ TLI.setUnavailable(LibFunc_ldexpf); ++ TLI.setUnavailable(LibFunc_ldexpl); ++ TLI.setUnavailable(LibFunc_logl); ++ TLI.setUnavailable(LibFunc_modfl); ++ TLI.setUnavailable(LibFunc_powl); ++ TLI.setUnavailable(LibFunc_sinl); ++ TLI.setUnavailable(LibFunc_sinhl); ++ TLI.setUnavailable(LibFunc_sqrtl); ++ TLI.setUnavailable(LibFunc_tanl); ++ TLI.setUnavailable(LibFunc_tanhl); + + // Win32 only has C89 math +- TLI.setUnavailable(LibFunc::acosh); +- TLI.setUnavailable(LibFunc::acoshf); +- TLI.setUnavailable(LibFunc::acoshl); +- TLI.setUnavailable(LibFunc::asinh); +- TLI.setUnavailable(LibFunc::asinhf); +- TLI.setUnavailable(LibFunc::asinhl); +- TLI.setUnavailable(LibFunc::atanh); +- TLI.setUnavailable(LibFunc::atanhf); +- TLI.setUnavailable(LibFunc::atanhl); +- TLI.setUnavailable(LibFunc::cbrt); +- TLI.setUnavailable(LibFunc::cbrtf); +- TLI.setUnavailable(LibFunc::cbrtl); +- TLI.setUnavailable(LibFunc::exp2); +- TLI.setUnavailable(LibFunc::exp2f); +- TLI.setUnavailable(LibFunc::exp2l); +- TLI.setUnavailable(LibFunc::expm1); +- TLI.setUnavailable(LibFunc::expm1f); +- TLI.setUnavailable(LibFunc::expm1l); +- TLI.setUnavailable(LibFunc::log2); +- TLI.setUnavailable(LibFunc::log2f); +- TLI.setUnavailable(LibFunc::log2l); +- TLI.setUnavailable(LibFunc::log1p); +- TLI.setUnavailable(LibFunc::log1pf); +- TLI.setUnavailable(LibFunc::log1pl); +- TLI.setUnavailable(LibFunc::logb); +- TLI.setUnavailable(LibFunc::logbf); +- TLI.setUnavailable(LibFunc::logbl); +- TLI.setUnavailable(LibFunc::nearbyint); +- TLI.setUnavailable(LibFunc::nearbyintf); +- TLI.setUnavailable(LibFunc::nearbyintl); +- TLI.setUnavailable(LibFunc::rint); +- TLI.setUnavailable(LibFunc::rintf); +- TLI.setUnavailable(LibFunc::rintl); +- TLI.setUnavailable(LibFunc::round); +- TLI.setUnavailable(LibFunc::roundf); +- TLI.setUnavailable(LibFunc::roundl); +- TLI.setUnavailable(LibFunc::trunc); +- TLI.setUnavailable(LibFunc::truncf); +- TLI.setUnavailable(LibFunc::truncl); ++ TLI.setUnavailable(LibFunc_acosh); ++ TLI.setUnavailable(LibFunc_acoshf); ++ TLI.setUnavailable(LibFunc_acoshl); ++ TLI.setUnavailable(LibFunc_asinh); ++ TLI.setUnavailable(LibFunc_asinhf); ++ TLI.setUnavailable(LibFunc_asinhl); ++ TLI.setUnavailable(LibFunc_atanh); ++ TLI.setUnavailable(LibFunc_atanhf); ++ TLI.setUnavailable(LibFunc_atanhl); ++ TLI.setUnavailable(LibFunc_cbrt); ++ TLI.setUnavailable(LibFunc_cbrtf); ++ TLI.setUnavailable(LibFunc_cbrtl); ++ TLI.setUnavailable(LibFunc_exp2); ++ TLI.setUnavailable(LibFunc_exp2f); ++ TLI.setUnavailable(LibFunc_exp2l); ++ TLI.setUnavailable(LibFunc_expm1); ++ TLI.setUnavailable(LibFunc_expm1f); ++ TLI.setUnavailable(LibFunc_expm1l); ++ TLI.setUnavailable(LibFunc_log2); ++ TLI.setUnavailable(LibFunc_log2f); ++ TLI.setUnavailable(LibFunc_log2l); ++ TLI.setUnavailable(LibFunc_log1p); ++ TLI.setUnavailable(LibFunc_log1pf); ++ TLI.setUnavailable(LibFunc_log1pl); ++ TLI.setUnavailable(LibFunc_logb); ++ TLI.setUnavailable(LibFunc_logbf); ++ TLI.setUnavailable(LibFunc_logbl); ++ TLI.setUnavailable(LibFunc_nearbyint); ++ TLI.setUnavailable(LibFunc_nearbyintf); ++ TLI.setUnavailable(LibFunc_nearbyintl); ++ TLI.setUnavailable(LibFunc_rint); ++ TLI.setUnavailable(LibFunc_rintf); ++ TLI.setUnavailable(LibFunc_rintl); ++ TLI.setUnavailable(LibFunc_round); ++ TLI.setUnavailable(LibFunc_roundf); ++ TLI.setUnavailable(LibFunc_roundl); ++ TLI.setUnavailable(LibFunc_trunc); ++ TLI.setUnavailable(LibFunc_truncf); ++ TLI.setUnavailable(LibFunc_truncl); + + // Win32 provides some C99 math with mangled names +- TLI.setAvailableWithName(LibFunc::copysign, "_copysign"); ++ TLI.setAvailableWithName(LibFunc_copysign, "_copysign"); + + if (T.getArch() == Triple::x86) { + // Win32 on x86 implements single-precision math functions as macros +- TLI.setUnavailable(LibFunc::acosf); +- TLI.setUnavailable(LibFunc::asinf); +- TLI.setUnavailable(LibFunc::atanf); +- TLI.setUnavailable(LibFunc::atan2f); +- TLI.setUnavailable(LibFunc::ceilf); +- TLI.setUnavailable(LibFunc::copysignf); +- TLI.setUnavailable(LibFunc::cosf); +- TLI.setUnavailable(LibFunc::coshf); +- TLI.setUnavailable(LibFunc::expf); +- TLI.setUnavailable(LibFunc::floorf); +- TLI.setUnavailable(LibFunc::fminf); +- TLI.setUnavailable(LibFunc::fmaxf); +- TLI.setUnavailable(LibFunc::fmodf); +- TLI.setUnavailable(LibFunc::logf); +- TLI.setUnavailable(LibFunc::log10f); +- TLI.setUnavailable(LibFunc::modff); +- TLI.setUnavailable(LibFunc::powf); +- TLI.setUnavailable(LibFunc::sinf); +- TLI.setUnavailable(LibFunc::sinhf); +- TLI.setUnavailable(LibFunc::sqrtf); +- TLI.setUnavailable(LibFunc::tanf); +- TLI.setUnavailable(LibFunc::tanhf); ++ TLI.setUnavailable(LibFunc_acosf); ++ TLI.setUnavailable(LibFunc_asinf); ++ TLI.setUnavailable(LibFunc_atanf); ++ TLI.setUnavailable(LibFunc_atan2f); ++ TLI.setUnavailable(LibFunc_ceilf); ++ TLI.setUnavailable(LibFunc_copysignf); ++ TLI.setUnavailable(LibFunc_cosf); ++ TLI.setUnavailable(LibFunc_coshf); ++ TLI.setUnavailable(LibFunc_expf); ++ TLI.setUnavailable(LibFunc_floorf); ++ TLI.setUnavailable(LibFunc_fminf); ++ TLI.setUnavailable(LibFunc_fmaxf); ++ TLI.setUnavailable(LibFunc_fmodf); ++ TLI.setUnavailable(LibFunc_logf); ++ TLI.setUnavailable(LibFunc_log10f); ++ TLI.setUnavailable(LibFunc_modff); ++ TLI.setUnavailable(LibFunc_powf); ++ TLI.setUnavailable(LibFunc_sinf); ++ TLI.setUnavailable(LibFunc_sinhf); ++ TLI.setUnavailable(LibFunc_sqrtf); ++ TLI.setUnavailable(LibFunc_tanf); ++ TLI.setUnavailable(LibFunc_tanhf); + } + + // Win32 does *not* provide provide these functions, but they are + // generally available on POSIX-compliant systems: +- TLI.setUnavailable(LibFunc::access); +- TLI.setUnavailable(LibFunc::bcmp); +- TLI.setUnavailable(LibFunc::bcopy); +- TLI.setUnavailable(LibFunc::bzero); +- TLI.setUnavailable(LibFunc::chmod); +- TLI.setUnavailable(LibFunc::chown); +- TLI.setUnavailable(LibFunc::closedir); +- TLI.setUnavailable(LibFunc::ctermid); +- TLI.setUnavailable(LibFunc::fdopen); +- TLI.setUnavailable(LibFunc::ffs); +- TLI.setUnavailable(LibFunc::fileno); +- TLI.setUnavailable(LibFunc::flockfile); +- TLI.setUnavailable(LibFunc::fseeko); +- TLI.setUnavailable(LibFunc::fstat); +- TLI.setUnavailable(LibFunc::fstatvfs); +- TLI.setUnavailable(LibFunc::ftello); +- TLI.setUnavailable(LibFunc::ftrylockfile); +- TLI.setUnavailable(LibFunc::funlockfile); +- TLI.setUnavailable(LibFunc::getc_unlocked); +- TLI.setUnavailable(LibFunc::getitimer); +- TLI.setUnavailable(LibFunc::getlogin_r); +- TLI.setUnavailable(LibFunc::getpwnam); +- TLI.setUnavailable(LibFunc::gettimeofday); +- TLI.setUnavailable(LibFunc::htonl); +- TLI.setUnavailable(LibFunc::htons); +- TLI.setUnavailable(LibFunc::lchown); +- TLI.setUnavailable(LibFunc::lstat); +- TLI.setUnavailable(LibFunc::memccpy); +- TLI.setUnavailable(LibFunc::mkdir); +- TLI.setUnavailable(LibFunc::ntohl); +- TLI.setUnavailable(LibFunc::ntohs); +- TLI.setUnavailable(LibFunc::open); +- TLI.setUnavailable(LibFunc::opendir); +- TLI.setUnavailable(LibFunc::pclose); +- TLI.setUnavailable(LibFunc::popen); +- TLI.setUnavailable(LibFunc::pread); +- TLI.setUnavailable(LibFunc::pwrite); +- TLI.setUnavailable(LibFunc::read); +- TLI.setUnavailable(LibFunc::readlink); +- TLI.setUnavailable(LibFunc::realpath); +- TLI.setUnavailable(LibFunc::rmdir); +- TLI.setUnavailable(LibFunc::setitimer); +- TLI.setUnavailable(LibFunc::stat); +- TLI.setUnavailable(LibFunc::statvfs); +- TLI.setUnavailable(LibFunc::stpcpy); +- TLI.setUnavailable(LibFunc::stpncpy); +- TLI.setUnavailable(LibFunc::strcasecmp); +- TLI.setUnavailable(LibFunc::strncasecmp); +- TLI.setUnavailable(LibFunc::times); +- TLI.setUnavailable(LibFunc::uname); +- TLI.setUnavailable(LibFunc::unlink); +- TLI.setUnavailable(LibFunc::unsetenv); +- TLI.setUnavailable(LibFunc::utime); +- TLI.setUnavailable(LibFunc::utimes); +- TLI.setUnavailable(LibFunc::write); ++ TLI.setUnavailable(LibFunc_access); ++ TLI.setUnavailable(LibFunc_bcmp); ++ TLI.setUnavailable(LibFunc_bcopy); ++ TLI.setUnavailable(LibFunc_bzero); ++ TLI.setUnavailable(LibFunc_chmod); ++ TLI.setUnavailable(LibFunc_chown); ++ TLI.setUnavailable(LibFunc_closedir); ++ TLI.setUnavailable(LibFunc_ctermid); ++ TLI.setUnavailable(LibFunc_fdopen); ++ TLI.setUnavailable(LibFunc_ffs); ++ TLI.setUnavailable(LibFunc_fileno); ++ TLI.setUnavailable(LibFunc_flockfile); ++ TLI.setUnavailable(LibFunc_fseeko); ++ TLI.setUnavailable(LibFunc_fstat); ++ TLI.setUnavailable(LibFunc_fstatvfs); ++ TLI.setUnavailable(LibFunc_ftello); ++ TLI.setUnavailable(LibFunc_ftrylockfile); ++ TLI.setUnavailable(LibFunc_funlockfile); ++ TLI.setUnavailable(LibFunc_getc_unlocked); ++ TLI.setUnavailable(LibFunc_getitimer); ++ TLI.setUnavailable(LibFunc_getlogin_r); ++ TLI.setUnavailable(LibFunc_getpwnam); ++ TLI.setUnavailable(LibFunc_gettimeofday); ++ TLI.setUnavailable(LibFunc_htonl); ++ TLI.setUnavailable(LibFunc_htons); ++ TLI.setUnavailable(LibFunc_lchown); ++ TLI.setUnavailable(LibFunc_lstat); ++ TLI.setUnavailable(LibFunc_memccpy); ++ TLI.setUnavailable(LibFunc_mkdir); ++ TLI.setUnavailable(LibFunc_ntohl); ++ TLI.setUnavailable(LibFunc_ntohs); ++ TLI.setUnavailable(LibFunc_open); ++ TLI.setUnavailable(LibFunc_opendir); ++ TLI.setUnavailable(LibFunc_pclose); ++ TLI.setUnavailable(LibFunc_popen); ++ TLI.setUnavailable(LibFunc_pread); ++ TLI.setUnavailable(LibFunc_pwrite); ++ TLI.setUnavailable(LibFunc_read); ++ TLI.setUnavailable(LibFunc_readlink); ++ TLI.setUnavailable(LibFunc_realpath); ++ TLI.setUnavailable(LibFunc_rmdir); ++ TLI.setUnavailable(LibFunc_setitimer); ++ TLI.setUnavailable(LibFunc_stat); ++ TLI.setUnavailable(LibFunc_statvfs); ++ TLI.setUnavailable(LibFunc_stpcpy); ++ TLI.setUnavailable(LibFunc_stpncpy); ++ TLI.setUnavailable(LibFunc_strcasecmp); ++ TLI.setUnavailable(LibFunc_strncasecmp); ++ TLI.setUnavailable(LibFunc_times); ++ TLI.setUnavailable(LibFunc_uname); ++ TLI.setUnavailable(LibFunc_unlink); ++ TLI.setUnavailable(LibFunc_unsetenv); ++ TLI.setUnavailable(LibFunc_utime); ++ TLI.setUnavailable(LibFunc_utimes); ++ TLI.setUnavailable(LibFunc_write); + + // Win32 does *not* provide provide these functions, but they are + // specified by C99: +- TLI.setUnavailable(LibFunc::atoll); +- TLI.setUnavailable(LibFunc::frexpf); +- TLI.setUnavailable(LibFunc::llabs); ++ TLI.setUnavailable(LibFunc_atoll); ++ TLI.setUnavailable(LibFunc_frexpf); ++ TLI.setUnavailable(LibFunc_llabs); + } + + switch (T.getOS()) { +@@ -291,28 +291,28 @@ static void initialize(TargetLibraryInfoImpl &TLI, const Triple &T, + // exp10 and exp10f are not available on OS X until 10.9 and iOS until 7.0 + // and their names are __exp10 and __exp10f. exp10l is not available on + // OS X or iOS. +- TLI.setUnavailable(LibFunc::exp10l); ++ TLI.setUnavailable(LibFunc_exp10l); + if (T.isMacOSXVersionLT(10, 9)) { +- TLI.setUnavailable(LibFunc::exp10); +- TLI.setUnavailable(LibFunc::exp10f); ++ TLI.setUnavailable(LibFunc_exp10); ++ TLI.setUnavailable(LibFunc_exp10f); + } else { +- TLI.setAvailableWithName(LibFunc::exp10, "__exp10"); +- TLI.setAvailableWithName(LibFunc::exp10f, "__exp10f"); ++ TLI.setAvailableWithName(LibFunc_exp10, "__exp10"); ++ TLI.setAvailableWithName(LibFunc_exp10f, "__exp10f"); + } + break; + case Triple::IOS: + case Triple::TvOS: + case Triple::WatchOS: +- TLI.setUnavailable(LibFunc::exp10l); ++ TLI.setUnavailable(LibFunc_exp10l); + if (!T.isWatchOS() && (T.isOSVersionLT(7, 0) || + (T.isOSVersionLT(9, 0) && + (T.getArch() == Triple::x86 || + T.getArch() == Triple::x86_64)))) { +- TLI.setUnavailable(LibFunc::exp10); +- TLI.setUnavailable(LibFunc::exp10f); ++ TLI.setUnavailable(LibFunc_exp10); ++ TLI.setUnavailable(LibFunc_exp10f); + } else { +- TLI.setAvailableWithName(LibFunc::exp10, "__exp10"); +- TLI.setAvailableWithName(LibFunc::exp10f, "__exp10f"); ++ TLI.setAvailableWithName(LibFunc_exp10, "__exp10"); ++ TLI.setAvailableWithName(LibFunc_exp10f, "__exp10f"); + } + break; + case Triple::Linux: +@@ -323,9 +323,9 @@ static void initialize(TargetLibraryInfoImpl &TLI, const Triple &T, + // + // Fall through to disable all of them. + default: +- TLI.setUnavailable(LibFunc::exp10); +- TLI.setUnavailable(LibFunc::exp10f); +- TLI.setUnavailable(LibFunc::exp10l); ++ TLI.setUnavailable(LibFunc_exp10); ++ TLI.setUnavailable(LibFunc_exp10f); ++ TLI.setUnavailable(LibFunc_exp10l); + } + + // ffsl is available on at least Darwin, Mac OS X, iOS, FreeBSD, and +@@ -343,7 +343,7 @@ static void initialize(TargetLibraryInfoImpl &TLI, const Triple &T, + case Triple::Linux: + break; + default: +- TLI.setUnavailable(LibFunc::ffsl); ++ TLI.setUnavailable(LibFunc_ffsl); + } + + // ffsll is available on at least FreeBSD and Linux (GLIBC): +@@ -359,7 +359,7 @@ static void initialize(TargetLibraryInfoImpl &TLI, const Triple &T, + case Triple::Linux: + break; + default: +- TLI.setUnavailable(LibFunc::ffsll); ++ TLI.setUnavailable(LibFunc_ffsll); + } + + // The following functions are available on at least FreeBSD: +@@ -367,30 +367,30 @@ static void initialize(TargetLibraryInfoImpl &TLI, const Triple &T, + // http://svn.freebsd.org/base/head/lib/libc/string/flsl.c + // http://svn.freebsd.org/base/head/lib/libc/string/flsll.c + if (!T.isOSFreeBSD()) { +- TLI.setUnavailable(LibFunc::fls); +- TLI.setUnavailable(LibFunc::flsl); +- TLI.setUnavailable(LibFunc::flsll); ++ TLI.setUnavailable(LibFunc_fls); ++ TLI.setUnavailable(LibFunc_flsl); ++ TLI.setUnavailable(LibFunc_flsll); + } + + // The following functions are available on at least Linux: + if (!T.isOSLinux()) { +- TLI.setUnavailable(LibFunc::dunder_strdup); +- TLI.setUnavailable(LibFunc::dunder_strtok_r); +- TLI.setUnavailable(LibFunc::dunder_isoc99_scanf); +- TLI.setUnavailable(LibFunc::dunder_isoc99_sscanf); +- TLI.setUnavailable(LibFunc::under_IO_getc); +- TLI.setUnavailable(LibFunc::under_IO_putc); +- TLI.setUnavailable(LibFunc::memalign); +- TLI.setUnavailable(LibFunc::fopen64); +- TLI.setUnavailable(LibFunc::fseeko64); +- TLI.setUnavailable(LibFunc::fstat64); +- TLI.setUnavailable(LibFunc::fstatvfs64); +- TLI.setUnavailable(LibFunc::ftello64); +- TLI.setUnavailable(LibFunc::lstat64); +- TLI.setUnavailable(LibFunc::open64); +- TLI.setUnavailable(LibFunc::stat64); +- TLI.setUnavailable(LibFunc::statvfs64); +- TLI.setUnavailable(LibFunc::tmpfile64); ++ TLI.setUnavailable(LibFunc_dunder_strdup); ++ TLI.setUnavailable(LibFunc_dunder_strtok_r); ++ TLI.setUnavailable(LibFunc_dunder_isoc99_scanf); ++ TLI.setUnavailable(LibFunc_dunder_isoc99_sscanf); ++ TLI.setUnavailable(LibFunc_under_IO_getc); ++ TLI.setUnavailable(LibFunc_under_IO_putc); ++ TLI.setUnavailable(LibFunc_memalign); ++ TLI.setUnavailable(LibFunc_fopen64); ++ TLI.setUnavailable(LibFunc_fseeko64); ++ TLI.setUnavailable(LibFunc_fstat64); ++ TLI.setUnavailable(LibFunc_fstatvfs64); ++ TLI.setUnavailable(LibFunc_ftello64); ++ TLI.setUnavailable(LibFunc_lstat64); ++ TLI.setUnavailable(LibFunc_open64); ++ TLI.setUnavailable(LibFunc_stat64); ++ TLI.setUnavailable(LibFunc_statvfs64); ++ TLI.setUnavailable(LibFunc_tmpfile64); + } + + // As currently implemented in clang, NVPTX code has no standard library to +@@ -406,9 +406,9 @@ static void initialize(TargetLibraryInfoImpl &TLI, const Triple &T, + // optimizations, so this situation should be fixed. + if (T.isNVPTX()) { + TLI.disableAllFunctions(); +- TLI.setAvailable(LibFunc::nvvm_reflect); ++ TLI.setAvailable(LibFunc_nvvm_reflect); + } else { +- TLI.setUnavailable(LibFunc::nvvm_reflect); ++ TLI.setUnavailable(LibFunc_nvvm_reflect); + } + + TLI.addVectorizableFunctionsFromVecLib(ClVectorLibrary); +@@ -468,9 +468,9 @@ static StringRef sanitizeFunctionName(StringRef funcName) { + } + + bool TargetLibraryInfoImpl::getLibFunc(StringRef funcName, +- LibFunc::Func &F) const { ++ LibFunc &F) const { + const char *const *Start = &StandardNames[0]; +- const char *const *End = &StandardNames[LibFunc::NumLibFuncs]; ++ const char *const *End = &StandardNames[NumLibFuncs]; + + funcName = sanitizeFunctionName(funcName); + if (funcName.empty()) +@@ -481,14 +481,14 @@ bool TargetLibraryInfoImpl::getLibFunc(StringRef funcName, + return std::strncmp(LHS, RHS.data(), RHS.size()) < 0; + }); + if (I != End && *I == funcName) { +- F = (LibFunc::Func)(I - Start); ++ F = (LibFunc)(I - Start); + return true; + } + return false; + } + + bool TargetLibraryInfoImpl::isValidProtoForLibFunc(const FunctionType &FTy, +- LibFunc::Func F, ++ LibFunc F, + const DataLayout *DL) const { + LLVMContext &Ctx = FTy.getContext(); + Type *PCharTy = Type::getInt8PtrTy(Ctx); +@@ -499,488 +499,488 @@ bool TargetLibraryInfoImpl::isValidProtoForLibFunc(const FunctionType &FTy, + unsigned NumParams = FTy.getNumParams(); + + switch (F) { +- case LibFunc::strlen: ++ case LibFunc_strlen: + return (NumParams == 1 && FTy.getParamType(0)->isPointerTy() && + FTy.getReturnType()->isIntegerTy()); + +- case LibFunc::strchr: +- case LibFunc::strrchr: ++ case LibFunc_strchr: ++ case LibFunc_strrchr: + return (NumParams == 2 && FTy.getReturnType()->isPointerTy() && + FTy.getParamType(0) == FTy.getReturnType() && + FTy.getParamType(1)->isIntegerTy()); + +- case LibFunc::strtol: +- case LibFunc::strtod: +- case LibFunc::strtof: +- case LibFunc::strtoul: +- case LibFunc::strtoll: +- case LibFunc::strtold: +- case LibFunc::strtoull: ++ case LibFunc_strtol: ++ case LibFunc_strtod: ++ case LibFunc_strtof: ++ case LibFunc_strtoul: ++ case LibFunc_strtoll: ++ case LibFunc_strtold: ++ case LibFunc_strtoull: + return ((NumParams == 2 || NumParams == 3) && + FTy.getParamType(0)->isPointerTy() && + FTy.getParamType(1)->isPointerTy()); +- case LibFunc::strcat: ++ case LibFunc_strcat: + return (NumParams == 2 && FTy.getReturnType()->isPointerTy() && + FTy.getParamType(0) == FTy.getReturnType() && + FTy.getParamType(1) == FTy.getReturnType()); + +- case LibFunc::strncat: ++ case LibFunc_strncat: + return (NumParams == 3 && FTy.getReturnType()->isPointerTy() && + FTy.getParamType(0) == FTy.getReturnType() && + FTy.getParamType(1) == FTy.getReturnType() && + FTy.getParamType(2)->isIntegerTy()); + +- case LibFunc::strcpy_chk: +- case LibFunc::stpcpy_chk: ++ case LibFunc_strcpy_chk: ++ case LibFunc_stpcpy_chk: + --NumParams; + if (!IsSizeTTy(FTy.getParamType(NumParams))) + return false; + // fallthrough +- case LibFunc::strcpy: +- case LibFunc::stpcpy: ++ case LibFunc_strcpy: ++ case LibFunc_stpcpy: + return (NumParams == 2 && FTy.getReturnType() == FTy.getParamType(0) && + FTy.getParamType(0) == FTy.getParamType(1) && + FTy.getParamType(0) == PCharTy); + +- case LibFunc::strncpy_chk: +- case LibFunc::stpncpy_chk: ++ case LibFunc_strncpy_chk: ++ case LibFunc_stpncpy_chk: + --NumParams; + if (!IsSizeTTy(FTy.getParamType(NumParams))) + return false; + // fallthrough +- case LibFunc::strncpy: +- case LibFunc::stpncpy: ++ case LibFunc_strncpy: ++ case LibFunc_stpncpy: + return (NumParams == 3 && FTy.getReturnType() == FTy.getParamType(0) && + FTy.getParamType(0) == FTy.getParamType(1) && + FTy.getParamType(0) == PCharTy && + FTy.getParamType(2)->isIntegerTy()); + +- case LibFunc::strxfrm: ++ case LibFunc_strxfrm: + return (NumParams == 3 && FTy.getParamType(0)->isPointerTy() && + FTy.getParamType(1)->isPointerTy()); + +- case LibFunc::strcmp: ++ case LibFunc_strcmp: + return (NumParams == 2 && FTy.getReturnType()->isIntegerTy(32) && + FTy.getParamType(0)->isPointerTy() && + FTy.getParamType(0) == FTy.getParamType(1)); + +- case LibFunc::strncmp: ++ case LibFunc_strncmp: + return (NumParams == 3 && FTy.getReturnType()->isIntegerTy(32) && + FTy.getParamType(0)->isPointerTy() && + FTy.getParamType(0) == FTy.getParamType(1) && + FTy.getParamType(2)->isIntegerTy()); + +- case LibFunc::strspn: +- case LibFunc::strcspn: ++ case LibFunc_strspn: ++ case LibFunc_strcspn: + return (NumParams == 2 && FTy.getParamType(0)->isPointerTy() && + FTy.getParamType(0) == FTy.getParamType(1) && + FTy.getReturnType()->isIntegerTy()); + +- case LibFunc::strcoll: +- case LibFunc::strcasecmp: +- case LibFunc::strncasecmp: ++ case LibFunc_strcoll: ++ case LibFunc_strcasecmp: ++ case LibFunc_strncasecmp: + return (NumParams >= 2 && FTy.getParamType(0)->isPointerTy() && + FTy.getParamType(1)->isPointerTy()); + +- case LibFunc::strstr: ++ case LibFunc_strstr: + return (NumParams == 2 && FTy.getReturnType()->isPointerTy() && + FTy.getParamType(0)->isPointerTy() && + FTy.getParamType(1)->isPointerTy()); + +- case LibFunc::strpbrk: ++ case LibFunc_strpbrk: + return (NumParams == 2 && FTy.getParamType(0)->isPointerTy() && + FTy.getReturnType() == FTy.getParamType(0) && + FTy.getParamType(0) == FTy.getParamType(1)); + +- case LibFunc::strtok: +- case LibFunc::strtok_r: ++ case LibFunc_strtok: ++ case LibFunc_strtok_r: + return (NumParams >= 2 && FTy.getParamType(1)->isPointerTy()); +- case LibFunc::scanf: +- case LibFunc::setbuf: +- case LibFunc::setvbuf: ++ case LibFunc_scanf: ++ case LibFunc_setbuf: ++ case LibFunc_setvbuf: + return (NumParams >= 1 && FTy.getParamType(0)->isPointerTy()); +- case LibFunc::strdup: +- case LibFunc::strndup: ++ case LibFunc_strdup: ++ case LibFunc_strndup: + return (NumParams >= 1 && FTy.getReturnType()->isPointerTy() && + FTy.getParamType(0)->isPointerTy()); +- case LibFunc::sscanf: +- case LibFunc::stat: +- case LibFunc::statvfs: +- case LibFunc::sprintf: ++ case LibFunc_sscanf: ++ case LibFunc_stat: ++ case LibFunc_statvfs: ++ case LibFunc_sprintf: + return (NumParams >= 2 && FTy.getParamType(0)->isPointerTy() && + FTy.getParamType(1)->isPointerTy()); +- case LibFunc::snprintf: ++ case LibFunc_snprintf: + return (NumParams == 3 && FTy.getParamType(0)->isPointerTy() && + FTy.getParamType(2)->isPointerTy()); +- case LibFunc::setitimer: ++ case LibFunc_setitimer: + return (NumParams == 3 && FTy.getParamType(1)->isPointerTy() && + FTy.getParamType(2)->isPointerTy()); +- case LibFunc::system: ++ case LibFunc_system: + return (NumParams == 1 && FTy.getParamType(0)->isPointerTy()); +- case LibFunc::malloc: ++ case LibFunc_malloc: + return (NumParams == 1 && FTy.getReturnType()->isPointerTy()); +- case LibFunc::memcmp: ++ case LibFunc_memcmp: + return (NumParams == 3 && FTy.getParamType(0)->isPointerTy() && + FTy.getParamType(1)->isPointerTy() && + FTy.getReturnType()->isIntegerTy(32)); + +- case LibFunc::memchr: +- case LibFunc::memrchr: ++ case LibFunc_memchr: ++ case LibFunc_memrchr: + return (NumParams == 3 && FTy.getParamType(0)->isPointerTy() && + FTy.getParamType(1)->isIntegerTy(32) && + FTy.getParamType(2)->isIntegerTy() && + FTy.getReturnType()->isPointerTy()); +- case LibFunc::modf: +- case LibFunc::modff: +- case LibFunc::modfl: ++ case LibFunc_modf: ++ case LibFunc_modff: ++ case LibFunc_modfl: + return (NumParams >= 2 && FTy.getParamType(1)->isPointerTy()); + +- case LibFunc::memcpy_chk: +- case LibFunc::memmove_chk: ++ case LibFunc_memcpy_chk: ++ case LibFunc_memmove_chk: + --NumParams; + if (!IsSizeTTy(FTy.getParamType(NumParams))) + return false; + // fallthrough +- case LibFunc::memcpy: +- case LibFunc::memmove: ++ case LibFunc_memcpy: ++ case LibFunc_memmove: + return (NumParams == 3 && FTy.getReturnType() == FTy.getParamType(0) && + FTy.getParamType(0)->isPointerTy() && + FTy.getParamType(1)->isPointerTy() && + IsSizeTTy(FTy.getParamType(2))); + +- case LibFunc::memset_chk: ++ case LibFunc_memset_chk: + --NumParams; + if (!IsSizeTTy(FTy.getParamType(NumParams))) + return false; + // fallthrough +- case LibFunc::memset: ++ case LibFunc_memset: + return (NumParams == 3 && FTy.getReturnType() == FTy.getParamType(0) && + FTy.getParamType(0)->isPointerTy() && + FTy.getParamType(1)->isIntegerTy() && + IsSizeTTy(FTy.getParamType(2))); + +- case LibFunc::memccpy: ++ case LibFunc_memccpy: + return (NumParams >= 2 && FTy.getParamType(1)->isPointerTy()); +- case LibFunc::memalign: ++ case LibFunc_memalign: + return (FTy.getReturnType()->isPointerTy()); +- case LibFunc::realloc: ++ case LibFunc_realloc: + return (NumParams == 2 && FTy.getParamType(0)->isPointerTy() && + FTy.getReturnType()->isPointerTy()); +- case LibFunc::read: ++ case LibFunc_read: + return (NumParams == 3 && FTy.getParamType(1)->isPointerTy()); +- case LibFunc::rewind: +- case LibFunc::rmdir: +- case LibFunc::remove: +- case LibFunc::realpath: ++ case LibFunc_rewind: ++ case LibFunc_rmdir: ++ case LibFunc_remove: ++ case LibFunc_realpath: + return (NumParams >= 1 && FTy.getParamType(0)->isPointerTy()); +- case LibFunc::rename: ++ case LibFunc_rename: + return (NumParams >= 2 && FTy.getParamType(0)->isPointerTy() && + FTy.getParamType(1)->isPointerTy()); +- case LibFunc::readlink: ++ case LibFunc_readlink: + return (NumParams >= 2 && FTy.getParamType(0)->isPointerTy() && + FTy.getParamType(1)->isPointerTy()); +- case LibFunc::write: ++ case LibFunc_write: + return (NumParams == 3 && FTy.getParamType(1)->isPointerTy()); +- case LibFunc::bcopy: +- case LibFunc::bcmp: ++ case LibFunc_bcopy: ++ case LibFunc_bcmp: + return (NumParams == 3 && FTy.getParamType(0)->isPointerTy() && + FTy.getParamType(1)->isPointerTy()); +- case LibFunc::bzero: ++ case LibFunc_bzero: + return (NumParams == 2 && FTy.getParamType(0)->isPointerTy()); +- case LibFunc::calloc: ++ case LibFunc_calloc: + return (NumParams == 2 && FTy.getReturnType()->isPointerTy()); + +- case LibFunc::atof: +- case LibFunc::atoi: +- case LibFunc::atol: +- case LibFunc::atoll: +- case LibFunc::ferror: +- case LibFunc::getenv: +- case LibFunc::getpwnam: +- case LibFunc::pclose: +- case LibFunc::perror: +- case LibFunc::printf: +- case LibFunc::puts: +- case LibFunc::uname: +- case LibFunc::under_IO_getc: +- case LibFunc::unlink: +- case LibFunc::unsetenv: ++ case LibFunc_atof: ++ case LibFunc_atoi: ++ case LibFunc_atol: ++ case LibFunc_atoll: ++ case LibFunc_ferror: ++ case LibFunc_getenv: ++ case LibFunc_getpwnam: ++ case LibFunc_pclose: ++ case LibFunc_perror: ++ case LibFunc_printf: ++ case LibFunc_puts: ++ case LibFunc_uname: ++ case LibFunc_under_IO_getc: ++ case LibFunc_unlink: ++ case LibFunc_unsetenv: + return (NumParams == 1 && FTy.getParamType(0)->isPointerTy()); + +- case LibFunc::chmod: +- case LibFunc::chown: +- case LibFunc::clearerr: +- case LibFunc::closedir: +- case LibFunc::ctermid: +- case LibFunc::fclose: +- case LibFunc::feof: +- case LibFunc::fflush: +- case LibFunc::fgetc: +- case LibFunc::fileno: +- case LibFunc::flockfile: +- case LibFunc::free: +- case LibFunc::fseek: +- case LibFunc::fseeko64: +- case LibFunc::fseeko: +- case LibFunc::fsetpos: +- case LibFunc::ftell: +- case LibFunc::ftello64: +- case LibFunc::ftello: +- case LibFunc::ftrylockfile: +- case LibFunc::funlockfile: +- case LibFunc::getc: +- case LibFunc::getc_unlocked: +- case LibFunc::getlogin_r: +- case LibFunc::mkdir: +- case LibFunc::mktime: +- case LibFunc::times: ++ case LibFunc_chmod: ++ case LibFunc_chown: ++ case LibFunc_clearerr: ++ case LibFunc_closedir: ++ case LibFunc_ctermid: ++ case LibFunc_fclose: ++ case LibFunc_feof: ++ case LibFunc_fflush: ++ case LibFunc_fgetc: ++ case LibFunc_fileno: ++ case LibFunc_flockfile: ++ case LibFunc_free: ++ case LibFunc_fseek: ++ case LibFunc_fseeko64: ++ case LibFunc_fseeko: ++ case LibFunc_fsetpos: ++ case LibFunc_ftell: ++ case LibFunc_ftello64: ++ case LibFunc_ftello: ++ case LibFunc_ftrylockfile: ++ case LibFunc_funlockfile: ++ case LibFunc_getc: ++ case LibFunc_getc_unlocked: ++ case LibFunc_getlogin_r: ++ case LibFunc_mkdir: ++ case LibFunc_mktime: ++ case LibFunc_times: + return (NumParams != 0 && FTy.getParamType(0)->isPointerTy()); + +- case LibFunc::access: ++ case LibFunc_access: + return (NumParams == 2 && FTy.getParamType(0)->isPointerTy()); +- case LibFunc::fopen: ++ case LibFunc_fopen: + return (NumParams == 2 && FTy.getReturnType()->isPointerTy() && + FTy.getParamType(0)->isPointerTy() && + FTy.getParamType(1)->isPointerTy()); +- case LibFunc::fdopen: ++ case LibFunc_fdopen: + return (NumParams == 2 && FTy.getReturnType()->isPointerTy() && + FTy.getParamType(1)->isPointerTy()); +- case LibFunc::fputc: +- case LibFunc::fstat: +- case LibFunc::frexp: +- case LibFunc::frexpf: +- case LibFunc::frexpl: +- case LibFunc::fstatvfs: ++ case LibFunc_fputc: ++ case LibFunc_fstat: ++ case LibFunc_frexp: ++ case LibFunc_frexpf: ++ case LibFunc_frexpl: ++ case LibFunc_fstatvfs: + return (NumParams == 2 && FTy.getParamType(1)->isPointerTy()); +- case LibFunc::fgets: ++ case LibFunc_fgets: + return (NumParams == 3 && FTy.getParamType(0)->isPointerTy() && + FTy.getParamType(2)->isPointerTy()); +- case LibFunc::fread: ++ case LibFunc_fread: + return (NumParams == 4 && FTy.getParamType(0)->isPointerTy() && + FTy.getParamType(3)->isPointerTy()); +- case LibFunc::fwrite: ++ case LibFunc_fwrite: + return (NumParams == 4 && FTy.getReturnType()->isIntegerTy() && + FTy.getParamType(0)->isPointerTy() && + FTy.getParamType(1)->isIntegerTy() && + FTy.getParamType(2)->isIntegerTy() && + FTy.getParamType(3)->isPointerTy()); +- case LibFunc::fputs: ++ case LibFunc_fputs: + return (NumParams >= 2 && FTy.getParamType(0)->isPointerTy() && + FTy.getParamType(1)->isPointerTy()); +- case LibFunc::fscanf: +- case LibFunc::fprintf: ++ case LibFunc_fscanf: ++ case LibFunc_fprintf: + return (NumParams >= 2 && FTy.getParamType(0)->isPointerTy() && + FTy.getParamType(1)->isPointerTy()); +- case LibFunc::fgetpos: ++ case LibFunc_fgetpos: + return (NumParams >= 2 && FTy.getParamType(0)->isPointerTy() && + FTy.getParamType(1)->isPointerTy()); +- case LibFunc::gets: +- case LibFunc::getchar: +- case LibFunc::getitimer: ++ case LibFunc_gets: ++ case LibFunc_getchar: ++ case LibFunc_getitimer: + return (NumParams == 2 && FTy.getParamType(1)->isPointerTy()); +- case LibFunc::ungetc: ++ case LibFunc_ungetc: + return (NumParams == 2 && FTy.getParamType(1)->isPointerTy()); +- case LibFunc::utime: +- case LibFunc::utimes: ++ case LibFunc_utime: ++ case LibFunc_utimes: + return (NumParams == 2 && FTy.getParamType(0)->isPointerTy() && + FTy.getParamType(1)->isPointerTy()); +- case LibFunc::putc: ++ case LibFunc_putc: + return (NumParams == 2 && FTy.getParamType(1)->isPointerTy()); +- case LibFunc::pread: +- case LibFunc::pwrite: ++ case LibFunc_pread: ++ case LibFunc_pwrite: + return (NumParams == 4 && FTy.getParamType(1)->isPointerTy()); +- case LibFunc::popen: ++ case LibFunc_popen: + return (NumParams == 2 && FTy.getReturnType()->isPointerTy() && + FTy.getParamType(0)->isPointerTy() && + FTy.getParamType(1)->isPointerTy()); +- case LibFunc::vscanf: ++ case LibFunc_vscanf: + return (NumParams == 2 && FTy.getParamType(1)->isPointerTy()); +- case LibFunc::vsscanf: ++ case LibFunc_vsscanf: + return (NumParams == 3 && FTy.getParamType(1)->isPointerTy() && + FTy.getParamType(2)->isPointerTy()); +- case LibFunc::vfscanf: ++ case LibFunc_vfscanf: + return (NumParams == 3 && FTy.getParamType(1)->isPointerTy() && + FTy.getParamType(2)->isPointerTy()); +- case LibFunc::valloc: ++ case LibFunc_valloc: + return (FTy.getReturnType()->isPointerTy()); +- case LibFunc::vprintf: ++ case LibFunc_vprintf: + return (NumParams == 2 && FTy.getParamType(0)->isPointerTy()); +- case LibFunc::vfprintf: +- case LibFunc::vsprintf: ++ case LibFunc_vfprintf: ++ case LibFunc_vsprintf: + return (NumParams == 3 && FTy.getParamType(0)->isPointerTy() && + FTy.getParamType(1)->isPointerTy()); +- case LibFunc::vsnprintf: ++ case LibFunc_vsnprintf: + return (NumParams == 4 && FTy.getParamType(0)->isPointerTy() && + FTy.getParamType(2)->isPointerTy()); +- case LibFunc::open: ++ case LibFunc_open: + return (NumParams >= 2 && FTy.getParamType(0)->isPointerTy()); +- case LibFunc::opendir: ++ case LibFunc_opendir: + return (NumParams == 1 && FTy.getReturnType()->isPointerTy() && + FTy.getParamType(0)->isPointerTy()); +- case LibFunc::tmpfile: ++ case LibFunc_tmpfile: + return (FTy.getReturnType()->isPointerTy()); +- case LibFunc::htonl: +- case LibFunc::htons: +- case LibFunc::ntohl: +- case LibFunc::ntohs: +- case LibFunc::lstat: ++ case LibFunc_htonl: ++ case LibFunc_htons: ++ case LibFunc_ntohl: ++ case LibFunc_ntohs: ++ case LibFunc_lstat: + return (NumParams == 2 && FTy.getParamType(0)->isPointerTy() && + FTy.getParamType(1)->isPointerTy()); +- case LibFunc::lchown: ++ case LibFunc_lchown: + return (NumParams == 3 && FTy.getParamType(0)->isPointerTy()); +- case LibFunc::qsort: ++ case LibFunc_qsort: + return (NumParams == 4 && FTy.getParamType(3)->isPointerTy()); +- case LibFunc::dunder_strdup: +- case LibFunc::dunder_strndup: ++ case LibFunc_dunder_strdup: ++ case LibFunc_dunder_strndup: + return (NumParams >= 1 && FTy.getReturnType()->isPointerTy() && + FTy.getParamType(0)->isPointerTy()); +- case LibFunc::dunder_strtok_r: ++ case LibFunc_dunder_strtok_r: + return (NumParams == 3 && FTy.getParamType(1)->isPointerTy()); +- case LibFunc::under_IO_putc: ++ case LibFunc_under_IO_putc: + return (NumParams == 2 && FTy.getParamType(1)->isPointerTy()); +- case LibFunc::dunder_isoc99_scanf: ++ case LibFunc_dunder_isoc99_scanf: + return (NumParams >= 1 && FTy.getParamType(0)->isPointerTy()); +- case LibFunc::stat64: +- case LibFunc::lstat64: +- case LibFunc::statvfs64: ++ case LibFunc_stat64: ++ case LibFunc_lstat64: ++ case LibFunc_statvfs64: + return (NumParams >= 1 && FTy.getParamType(0)->isPointerTy() && + FTy.getParamType(1)->isPointerTy()); +- case LibFunc::dunder_isoc99_sscanf: ++ case LibFunc_dunder_isoc99_sscanf: + return (NumParams >= 1 && FTy.getParamType(0)->isPointerTy() && + FTy.getParamType(1)->isPointerTy()); +- case LibFunc::fopen64: ++ case LibFunc_fopen64: + return (NumParams == 2 && FTy.getReturnType()->isPointerTy() && + FTy.getParamType(0)->isPointerTy() && + FTy.getParamType(1)->isPointerTy()); +- case LibFunc::tmpfile64: ++ case LibFunc_tmpfile64: + return (FTy.getReturnType()->isPointerTy()); +- case LibFunc::fstat64: +- case LibFunc::fstatvfs64: ++ case LibFunc_fstat64: ++ case LibFunc_fstatvfs64: + return (NumParams == 2 && FTy.getParamType(1)->isPointerTy()); +- case LibFunc::open64: ++ case LibFunc_open64: + return (NumParams >= 2 && FTy.getParamType(0)->isPointerTy()); +- case LibFunc::gettimeofday: ++ case LibFunc_gettimeofday: + return (NumParams == 2 && FTy.getParamType(0)->isPointerTy() && + FTy.getParamType(1)->isPointerTy()); + +- case LibFunc::Znwj: // new(unsigned int); +- case LibFunc::Znwm: // new(unsigned long); +- case LibFunc::Znaj: // new[](unsigned int); +- case LibFunc::Znam: // new[](unsigned long); +- case LibFunc::msvc_new_int: // new(unsigned int); +- case LibFunc::msvc_new_longlong: // new(unsigned long long); +- case LibFunc::msvc_new_array_int: // new[](unsigned int); +- case LibFunc::msvc_new_array_longlong: // new[](unsigned long long); ++ case LibFunc_Znwj: // new(unsigned int); ++ case LibFunc_Znwm: // new(unsigned long); ++ case LibFunc_Znaj: // new[](unsigned int); ++ case LibFunc_Znam: // new[](unsigned long); ++ case LibFunc_msvc_new_int: // new(unsigned int); ++ case LibFunc_msvc_new_longlong: // new(unsigned long long); ++ case LibFunc_msvc_new_array_int: // new[](unsigned int); ++ case LibFunc_msvc_new_array_longlong: // new[](unsigned long long); + return (NumParams == 1); + +- case LibFunc::memset_pattern16: ++ case LibFunc_memset_pattern16: + return (!FTy.isVarArg() && NumParams == 3 && + isa(FTy.getParamType(0)) && + isa(FTy.getParamType(1)) && + isa(FTy.getParamType(2))); + + // int __nvvm_reflect(const char *); +- case LibFunc::nvvm_reflect: ++ case LibFunc_nvvm_reflect: + return (NumParams == 1 && isa(FTy.getParamType(0))); + +- case LibFunc::sin: +- case LibFunc::sinf: +- case LibFunc::sinl: +- case LibFunc::cos: +- case LibFunc::cosf: +- case LibFunc::cosl: +- case LibFunc::tan: +- case LibFunc::tanf: +- case LibFunc::tanl: +- case LibFunc::exp: +- case LibFunc::expf: +- case LibFunc::expl: +- case LibFunc::exp2: +- case LibFunc::exp2f: +- case LibFunc::exp2l: +- case LibFunc::log: +- case LibFunc::logf: +- case LibFunc::logl: +- case LibFunc::log10: +- case LibFunc::log10f: +- case LibFunc::log10l: +- case LibFunc::log2: +- case LibFunc::log2f: +- case LibFunc::log2l: +- case LibFunc::fabs: +- case LibFunc::fabsf: +- case LibFunc::fabsl: +- case LibFunc::floor: +- case LibFunc::floorf: +- case LibFunc::floorl: +- case LibFunc::ceil: +- case LibFunc::ceilf: +- case LibFunc::ceill: +- case LibFunc::trunc: +- case LibFunc::truncf: +- case LibFunc::truncl: +- case LibFunc::rint: +- case LibFunc::rintf: +- case LibFunc::rintl: +- case LibFunc::nearbyint: +- case LibFunc::nearbyintf: +- case LibFunc::nearbyintl: +- case LibFunc::round: +- case LibFunc::roundf: +- case LibFunc::roundl: +- case LibFunc::sqrt: +- case LibFunc::sqrtf: +- case LibFunc::sqrtl: ++ case LibFunc_sin: ++ case LibFunc_sinf: ++ case LibFunc_sinl: ++ case LibFunc_cos: ++ case LibFunc_cosf: ++ case LibFunc_cosl: ++ case LibFunc_tan: ++ case LibFunc_tanf: ++ case LibFunc_tanl: ++ case LibFunc_exp: ++ case LibFunc_expf: ++ case LibFunc_expl: ++ case LibFunc_exp2: ++ case LibFunc_exp2f: ++ case LibFunc_exp2l: ++ case LibFunc_log: ++ case LibFunc_logf: ++ case LibFunc_logl: ++ case LibFunc_log10: ++ case LibFunc_log10f: ++ case LibFunc_log10l: ++ case LibFunc_log2: ++ case LibFunc_log2f: ++ case LibFunc_log2l: ++ case LibFunc_fabs: ++ case LibFunc_fabsf: ++ case LibFunc_fabsl: ++ case LibFunc_floor: ++ case LibFunc_floorf: ++ case LibFunc_floorl: ++ case LibFunc_ceil: ++ case LibFunc_ceilf: ++ case LibFunc_ceill: ++ case LibFunc_trunc: ++ case LibFunc_truncf: ++ case LibFunc_truncl: ++ case LibFunc_rint: ++ case LibFunc_rintf: ++ case LibFunc_rintl: ++ case LibFunc_nearbyint: ++ case LibFunc_nearbyintf: ++ case LibFunc_nearbyintl: ++ case LibFunc_round: ++ case LibFunc_roundf: ++ case LibFunc_roundl: ++ case LibFunc_sqrt: ++ case LibFunc_sqrtf: ++ case LibFunc_sqrtl: + return (NumParams == 1 && FTy.getReturnType()->isFloatingPointTy() && + FTy.getReturnType() == FTy.getParamType(0)); + +- case LibFunc::fmin: +- case LibFunc::fminf: +- case LibFunc::fminl: +- case LibFunc::fmax: +- case LibFunc::fmaxf: +- case LibFunc::fmaxl: +- case LibFunc::copysign: +- case LibFunc::copysignf: +- case LibFunc::copysignl: +- case LibFunc::pow: +- case LibFunc::powf: +- case LibFunc::powl: ++ case LibFunc_fmin: ++ case LibFunc_fminf: ++ case LibFunc_fminl: ++ case LibFunc_fmax: ++ case LibFunc_fmaxf: ++ case LibFunc_fmaxl: ++ case LibFunc_copysign: ++ case LibFunc_copysignf: ++ case LibFunc_copysignl: ++ case LibFunc_pow: ++ case LibFunc_powf: ++ case LibFunc_powl: + return (NumParams == 2 && FTy.getReturnType()->isFloatingPointTy() && + FTy.getReturnType() == FTy.getParamType(0) && + FTy.getReturnType() == FTy.getParamType(1)); + +- case LibFunc::ffs: +- case LibFunc::ffsl: +- case LibFunc::ffsll: +- case LibFunc::isdigit: +- case LibFunc::isascii: +- case LibFunc::toascii: ++ case LibFunc_ffs: ++ case LibFunc_ffsl: ++ case LibFunc_ffsll: ++ case LibFunc_isdigit: ++ case LibFunc_isascii: ++ case LibFunc_toascii: + return (NumParams == 1 && FTy.getReturnType()->isIntegerTy(32) && + FTy.getParamType(0)->isIntegerTy()); + +- case LibFunc::fls: +- case LibFunc::flsl: +- case LibFunc::flsll: +- case LibFunc::abs: +- case LibFunc::labs: +- case LibFunc::llabs: ++ case LibFunc_fls: ++ case LibFunc_flsl: ++ case LibFunc_flsll: ++ case LibFunc_abs: ++ case LibFunc_labs: ++ case LibFunc_llabs: + return (NumParams == 1 && FTy.getReturnType()->isIntegerTy() && + FTy.getReturnType() == FTy.getParamType(0)); + +- case LibFunc::cxa_atexit: ++ case LibFunc_cxa_atexit: + return (NumParams == 3 && FTy.getReturnType()->isIntegerTy() && + FTy.getParamType(0)->isPointerTy() && + FTy.getParamType(1)->isPointerTy() && + FTy.getParamType(2)->isPointerTy()); + +- case LibFunc::sinpi: +- case LibFunc::cospi: ++ case LibFunc_sinpi: ++ case LibFunc_cospi: + return (NumParams == 1 && FTy.getReturnType()->isDoubleTy() && + FTy.getReturnType() == FTy.getParamType(0)); + +- case LibFunc::sinpif: +- case LibFunc::cospif: ++ case LibFunc_sinpif: ++ case LibFunc_cospif: + return (NumParams == 1 && FTy.getReturnType()->isFloatTy() && + FTy.getReturnType() == FTy.getParamType(0)); + +@@ -992,7 +992,7 @@ bool TargetLibraryInfoImpl::isValidProtoForLibFunc(const FunctionType &FTy, + } + + bool TargetLibraryInfoImpl::getLibFunc(const Function &FDecl, +- LibFunc::Func &F) const { ++ LibFunc &F) const { + const DataLayout *DL = + FDecl.getParent() ? &FDecl.getParent()->getDataLayout() : nullptr; + return getLibFunc(FDecl.getName(), F) && +diff --git a/lib/Analysis/ValueTracking.cpp b/lib/Analysis/ValueTracking.cpp +index f2b40787443..4dcf08b1c81 100644 +--- a/lib/Analysis/ValueTracking.cpp ++++ b/lib/Analysis/ValueTracking.cpp +@@ -2304,7 +2304,7 @@ Intrinsic::ID llvm::getIntrinsicForCallSite(ImmutableCallSite ICS, + if (!TLI) + return Intrinsic::not_intrinsic; + +- LibFunc::Func Func; ++ LibFunc Func; + // We're going to make assumptions on the semantics of the functions, check + // that the target knows that it's available in this environment and it does + // not have local linkage. +@@ -2319,81 +2319,81 @@ Intrinsic::ID llvm::getIntrinsicForCallSite(ImmutableCallSite ICS, + switch (Func) { + default: + break; +- case LibFunc::sin: +- case LibFunc::sinf: +- case LibFunc::sinl: ++ case LibFunc_sin: ++ case LibFunc_sinf: ++ case LibFunc_sinl: + return Intrinsic::sin; +- case LibFunc::cos: +- case LibFunc::cosf: +- case LibFunc::cosl: ++ case LibFunc_cos: ++ case LibFunc_cosf: ++ case LibFunc_cosl: + return Intrinsic::cos; +- case LibFunc::exp: +- case LibFunc::expf: +- case LibFunc::expl: ++ case LibFunc_exp: ++ case LibFunc_expf: ++ case LibFunc_expl: + return Intrinsic::exp; +- case LibFunc::exp2: +- case LibFunc::exp2f: +- case LibFunc::exp2l: ++ case LibFunc_exp2: ++ case LibFunc_exp2f: ++ case LibFunc_exp2l: + return Intrinsic::exp2; +- case LibFunc::log: +- case LibFunc::logf: +- case LibFunc::logl: ++ case LibFunc_log: ++ case LibFunc_logf: ++ case LibFunc_logl: + return Intrinsic::log; +- case LibFunc::log10: +- case LibFunc::log10f: +- case LibFunc::log10l: ++ case LibFunc_log10: ++ case LibFunc_log10f: ++ case LibFunc_log10l: + return Intrinsic::log10; +- case LibFunc::log2: +- case LibFunc::log2f: +- case LibFunc::log2l: ++ case LibFunc_log2: ++ case LibFunc_log2f: ++ case LibFunc_log2l: + return Intrinsic::log2; +- case LibFunc::fabs: +- case LibFunc::fabsf: +- case LibFunc::fabsl: ++ case LibFunc_fabs: ++ case LibFunc_fabsf: ++ case LibFunc_fabsl: + return Intrinsic::fabs; +- case LibFunc::fmin: +- case LibFunc::fminf: +- case LibFunc::fminl: ++ case LibFunc_fmin: ++ case LibFunc_fminf: ++ case LibFunc_fminl: + return Intrinsic::minnum; +- case LibFunc::fmax: +- case LibFunc::fmaxf: +- case LibFunc::fmaxl: ++ case LibFunc_fmax: ++ case LibFunc_fmaxf: ++ case LibFunc_fmaxl: + return Intrinsic::maxnum; +- case LibFunc::copysign: +- case LibFunc::copysignf: +- case LibFunc::copysignl: ++ case LibFunc_copysign: ++ case LibFunc_copysignf: ++ case LibFunc_copysignl: + return Intrinsic::copysign; +- case LibFunc::floor: +- case LibFunc::floorf: +- case LibFunc::floorl: ++ case LibFunc_floor: ++ case LibFunc_floorf: ++ case LibFunc_floorl: + return Intrinsic::floor; +- case LibFunc::ceil: +- case LibFunc::ceilf: +- case LibFunc::ceill: ++ case LibFunc_ceil: ++ case LibFunc_ceilf: ++ case LibFunc_ceill: + return Intrinsic::ceil; +- case LibFunc::trunc: +- case LibFunc::truncf: +- case LibFunc::truncl: ++ case LibFunc_trunc: ++ case LibFunc_truncf: ++ case LibFunc_truncl: + return Intrinsic::trunc; +- case LibFunc::rint: +- case LibFunc::rintf: +- case LibFunc::rintl: ++ case LibFunc_rint: ++ case LibFunc_rintf: ++ case LibFunc_rintl: + return Intrinsic::rint; +- case LibFunc::nearbyint: +- case LibFunc::nearbyintf: +- case LibFunc::nearbyintl: ++ case LibFunc_nearbyint: ++ case LibFunc_nearbyintf: ++ case LibFunc_nearbyintl: + return Intrinsic::nearbyint; +- case LibFunc::round: +- case LibFunc::roundf: +- case LibFunc::roundl: ++ case LibFunc_round: ++ case LibFunc_roundf: ++ case LibFunc_roundl: + return Intrinsic::round; +- case LibFunc::pow: +- case LibFunc::powf: +- case LibFunc::powl: ++ case LibFunc_pow: ++ case LibFunc_powf: ++ case LibFunc_powl: + return Intrinsic::pow; +- case LibFunc::sqrt: +- case LibFunc::sqrtf: +- case LibFunc::sqrtl: ++ case LibFunc_sqrt: ++ case LibFunc_sqrtf: ++ case LibFunc_sqrtl: + if (ICS->hasNoNaNs()) + return Intrinsic::sqrt; + return Intrinsic::not_intrinsic; +diff --git a/lib/CodeGen/SelectionDAG/FastISel.cpp b/lib/CodeGen/SelectionDAG/FastISel.cpp +index b10da002fcf..35ee744b943 100644 +--- a/lib/CodeGen/SelectionDAG/FastISel.cpp ++++ b/lib/CodeGen/SelectionDAG/FastISel.cpp +@@ -1383,7 +1383,7 @@ bool FastISel::selectInstruction(const Instruction *I) { + + if (const auto *Call = dyn_cast(I)) { + const Function *F = Call->getCalledFunction(); +- LibFunc::Func Func; ++ LibFunc Func; + + // As a special case, don't handle calls to builtin library functions that + // may be translated directly to target instructions. +diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +index e03282cad6b..d96677e7795 100644 +--- a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp ++++ b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +@@ -6222,15 +6222,15 @@ void SelectionDAGBuilder::visitCall(const CallInst &I) { + // Check for well-known libc/libm calls. If the function is internal, it + // can't be a library call. Don't do the check if marked as nobuiltin for + // some reason. +- LibFunc::Func Func; ++ LibFunc Func; + if (!I.isNoBuiltin() && !F->hasLocalLinkage() && F->hasName() && + LibInfo->getLibFunc(F->getName(), Func) && + LibInfo->hasOptimizedCodeGen(Func)) { + switch (Func) { + default: break; +- case LibFunc::copysign: +- case LibFunc::copysignf: +- case LibFunc::copysignl: ++ case LibFunc_copysign: ++ case LibFunc_copysignf: ++ case LibFunc_copysignl: + if (I.getNumArgOperands() == 2 && // Basic sanity checks. + I.getArgOperand(0)->getType()->isFloatingPointTy() && + I.getType() == I.getArgOperand(0)->getType() && +@@ -6243,118 +6243,118 @@ void SelectionDAGBuilder::visitCall(const CallInst &I) { + return; + } + break; +- case LibFunc::fabs: +- case LibFunc::fabsf: +- case LibFunc::fabsl: ++ case LibFunc_fabs: ++ case LibFunc_fabsf: ++ case LibFunc_fabsl: + if (visitUnaryFloatCall(I, ISD::FABS)) + return; + break; +- case LibFunc::fmin: +- case LibFunc::fminf: +- case LibFunc::fminl: ++ case LibFunc_fmin: ++ case LibFunc_fminf: ++ case LibFunc_fminl: + if (visitBinaryFloatCall(I, ISD::FMINNUM)) + return; + break; +- case LibFunc::fmax: +- case LibFunc::fmaxf: +- case LibFunc::fmaxl: ++ case LibFunc_fmax: ++ case LibFunc_fmaxf: ++ case LibFunc_fmaxl: + if (visitBinaryFloatCall(I, ISD::FMAXNUM)) + return; + break; +- case LibFunc::sin: +- case LibFunc::sinf: +- case LibFunc::sinl: ++ case LibFunc_sin: ++ case LibFunc_sinf: ++ case LibFunc_sinl: + if (visitUnaryFloatCall(I, ISD::FSIN)) + return; + break; +- case LibFunc::cos: +- case LibFunc::cosf: +- case LibFunc::cosl: ++ case LibFunc_cos: ++ case LibFunc_cosf: ++ case LibFunc_cosl: + if (visitUnaryFloatCall(I, ISD::FCOS)) + return; + break; +- case LibFunc::sqrt: +- case LibFunc::sqrtf: +- case LibFunc::sqrtl: +- case LibFunc::sqrt_finite: +- case LibFunc::sqrtf_finite: +- case LibFunc::sqrtl_finite: ++ case LibFunc_sqrt: ++ case LibFunc_sqrtf: ++ case LibFunc_sqrtl: ++ case LibFunc_sqrt_finite: ++ case LibFunc_sqrtf_finite: ++ case LibFunc_sqrtl_finite: + if (visitUnaryFloatCall(I, ISD::FSQRT)) + return; + break; +- case LibFunc::floor: +- case LibFunc::floorf: +- case LibFunc::floorl: ++ case LibFunc_floor: ++ case LibFunc_floorf: ++ case LibFunc_floorl: + if (visitUnaryFloatCall(I, ISD::FFLOOR)) + return; + break; +- case LibFunc::nearbyint: +- case LibFunc::nearbyintf: +- case LibFunc::nearbyintl: ++ case LibFunc_nearbyint: ++ case LibFunc_nearbyintf: ++ case LibFunc_nearbyintl: + if (visitUnaryFloatCall(I, ISD::FNEARBYINT)) + return; + break; +- case LibFunc::ceil: +- case LibFunc::ceilf: +- case LibFunc::ceill: ++ case LibFunc_ceil: ++ case LibFunc_ceilf: ++ case LibFunc_ceill: + if (visitUnaryFloatCall(I, ISD::FCEIL)) + return; + break; +- case LibFunc::rint: +- case LibFunc::rintf: +- case LibFunc::rintl: ++ case LibFunc_rint: ++ case LibFunc_rintf: ++ case LibFunc_rintl: + if (visitUnaryFloatCall(I, ISD::FRINT)) + return; + break; +- case LibFunc::round: +- case LibFunc::roundf: +- case LibFunc::roundl: ++ case LibFunc_round: ++ case LibFunc_roundf: ++ case LibFunc_roundl: + if (visitUnaryFloatCall(I, ISD::FROUND)) + return; + break; +- case LibFunc::trunc: +- case LibFunc::truncf: +- case LibFunc::truncl: ++ case LibFunc_trunc: ++ case LibFunc_truncf: ++ case LibFunc_truncl: + if (visitUnaryFloatCall(I, ISD::FTRUNC)) + return; + break; +- case LibFunc::log2: +- case LibFunc::log2f: +- case LibFunc::log2l: ++ case LibFunc_log2: ++ case LibFunc_log2f: ++ case LibFunc_log2l: + if (visitUnaryFloatCall(I, ISD::FLOG2)) + return; + break; +- case LibFunc::exp2: +- case LibFunc::exp2f: +- case LibFunc::exp2l: ++ case LibFunc_exp2: ++ case LibFunc_exp2f: ++ case LibFunc_exp2l: + if (visitUnaryFloatCall(I, ISD::FEXP2)) + return; + break; +- case LibFunc::memcmp: ++ case LibFunc_memcmp: + if (visitMemCmpCall(I)) + return; + break; +- case LibFunc::memchr: ++ case LibFunc_memchr: + if (visitMemChrCall(I)) + return; + break; +- case LibFunc::strcpy: ++ case LibFunc_strcpy: + if (visitStrCpyCall(I, false)) + return; + break; +- case LibFunc::stpcpy: ++ case LibFunc_stpcpy: + if (visitStrCpyCall(I, true)) + return; + break; +- case LibFunc::strcmp: ++ case LibFunc_strcmp: + if (visitStrCmpCall(I)) + return; + break; +- case LibFunc::strlen: ++ case LibFunc_strlen: + if (visitStrLenCall(I)) + return; + break; +- case LibFunc::strnlen: ++ case LibFunc_strnlen: + if (visitStrNLenCall(I)) + return; + break; +diff --git a/lib/LTO/UpdateCompilerUsed.cpp b/lib/LTO/UpdateCompilerUsed.cpp +index a574db6fb5a..3af239b7549 100644 +--- a/lib/LTO/UpdateCompilerUsed.cpp ++++ b/lib/LTO/UpdateCompilerUsed.cpp +@@ -64,7 +64,7 @@ private: + // target. + for (unsigned I = 0, E = static_cast(LibFunc::NumLibFuncs); + I != E; ++I) { +- LibFunc::Func F = static_cast(I); ++ LibFunc F = static_cast(I); + if (TLI.has(F)) + Libcalls.insert(TLI.getName(F)); + } +diff --git a/lib/Target/PowerPC/PPCCTRLoops.cpp b/lib/Target/PowerPC/PPCCTRLoops.cpp +index 87522663591..ad7bcd9d752 100644 +--- a/lib/Target/PowerPC/PPCCTRLoops.cpp ++++ b/lib/Target/PowerPC/PPCCTRLoops.cpp +@@ -315,7 +315,7 @@ bool PPCCTRLoops::mightUseCTR(const Triple &TT, BasicBlock *BB) { + // (i.e. soft float or atomics). If adapting for targets that do, + // additional care is required here. + +- LibFunc::Func Func; ++ LibFunc Func; + if (!F->hasLocalLinkage() && F->hasName() && LibInfo && + LibInfo->getLibFunc(F->getName(), Func) && + LibInfo->hasOptimizedCodeGen(Func)) { +@@ -329,50 +329,50 @@ bool PPCCTRLoops::mightUseCTR(const Triple &TT, BasicBlock *BB) { + + switch (Func) { + default: return true; +- case LibFunc::copysign: +- case LibFunc::copysignf: ++ case LibFunc_copysign: ++ case LibFunc_copysignf: + continue; // ISD::FCOPYSIGN is never a library call. +- case LibFunc::copysignl: ++ case LibFunc_copysignl: + return true; +- case LibFunc::fabs: +- case LibFunc::fabsf: +- case LibFunc::fabsl: ++ case LibFunc_fabs: ++ case LibFunc_fabsf: ++ case LibFunc_fabsl: + continue; // ISD::FABS is never a library call. +- case LibFunc::sqrt: +- case LibFunc::sqrtf: +- case LibFunc::sqrtl: ++ case LibFunc_sqrt: ++ case LibFunc_sqrtf: ++ case LibFunc_sqrtl: + Opcode = ISD::FSQRT; break; +- case LibFunc::floor: +- case LibFunc::floorf: +- case LibFunc::floorl: ++ case LibFunc_floor: ++ case LibFunc_floorf: ++ case LibFunc_floorl: + Opcode = ISD::FFLOOR; break; +- case LibFunc::nearbyint: +- case LibFunc::nearbyintf: +- case LibFunc::nearbyintl: ++ case LibFunc_nearbyint: ++ case LibFunc_nearbyintf: ++ case LibFunc_nearbyintl: + Opcode = ISD::FNEARBYINT; break; +- case LibFunc::ceil: +- case LibFunc::ceilf: +- case LibFunc::ceill: ++ case LibFunc_ceil: ++ case LibFunc_ceilf: ++ case LibFunc_ceill: + Opcode = ISD::FCEIL; break; +- case LibFunc::rint: +- case LibFunc::rintf: +- case LibFunc::rintl: ++ case LibFunc_rint: ++ case LibFunc_rintf: ++ case LibFunc_rintl: + Opcode = ISD::FRINT; break; +- case LibFunc::round: +- case LibFunc::roundf: +- case LibFunc::roundl: ++ case LibFunc_round: ++ case LibFunc_roundf: ++ case LibFunc_roundl: + Opcode = ISD::FROUND; break; +- case LibFunc::trunc: +- case LibFunc::truncf: +- case LibFunc::truncl: ++ case LibFunc_trunc: ++ case LibFunc_truncf: ++ case LibFunc_truncl: + Opcode = ISD::FTRUNC; break; +- case LibFunc::fmin: +- case LibFunc::fminf: +- case LibFunc::fminl: ++ case LibFunc_fmin: ++ case LibFunc_fminf: ++ case LibFunc_fminl: + Opcode = ISD::FMINNUM; break; +- case LibFunc::fmax: +- case LibFunc::fmaxf: +- case LibFunc::fmaxl: ++ case LibFunc_fmax: ++ case LibFunc_fmaxf: ++ case LibFunc_fmaxl: + Opcode = ISD::FMAXNUM; break; + } + } +diff --git a/lib/Transforms/IPO/GlobalOpt.cpp b/lib/Transforms/IPO/GlobalOpt.cpp +index 99b12d4db0d..3fd706f4914 100644 +--- a/lib/Transforms/IPO/GlobalOpt.cpp ++++ b/lib/Transforms/IPO/GlobalOpt.cpp +@@ -2403,7 +2403,7 @@ OptimizeGlobalAliases(Module &M, + } + + static Function *FindCXAAtExit(Module &M, TargetLibraryInfo *TLI) { +- LibFunc::Func F = LibFunc::cxa_atexit; ++ LibFunc F = LibFunc_cxa_atexit; + if (!TLI->has(F)) + return nullptr; + +@@ -2412,7 +2412,7 @@ static Function *FindCXAAtExit(Module &M, TargetLibraryInfo *TLI) { + return nullptr; + + // Make sure that the function has the correct prototype. +- if (!TLI->getLibFunc(*Fn, F) || F != LibFunc::cxa_atexit) ++ if (!TLI->getLibFunc(*Fn, F) || F != LibFunc_cxa_atexit) + return nullptr; + + return Fn; +diff --git a/lib/Transforms/Scalar/DeadStoreElimination.cpp b/lib/Transforms/Scalar/DeadStoreElimination.cpp +index ed58a87ae1a..c2052042253 100644 +--- a/lib/Transforms/Scalar/DeadStoreElimination.cpp ++++ b/lib/Transforms/Scalar/DeadStoreElimination.cpp +@@ -130,13 +130,13 @@ static bool hasMemoryWrite(Instruction *I, const TargetLibraryInfo &TLI) { + if (auto CS = CallSite(I)) { + if (Function *F = CS.getCalledFunction()) { + StringRef FnName = F->getName(); +- if (TLI.has(LibFunc::strcpy) && FnName == TLI.getName(LibFunc::strcpy)) ++ if (TLI.has(LibFunc_strcpy) && FnName == TLI.getName(LibFunc_strcpy)) + return true; +- if (TLI.has(LibFunc::strncpy) && FnName == TLI.getName(LibFunc::strncpy)) ++ if (TLI.has(LibFunc_strncpy) && FnName == TLI.getName(LibFunc_strncpy)) + return true; +- if (TLI.has(LibFunc::strcat) && FnName == TLI.getName(LibFunc::strcat)) ++ if (TLI.has(LibFunc_strcat) && FnName == TLI.getName(LibFunc_strcat)) + return true; +- if (TLI.has(LibFunc::strncat) && FnName == TLI.getName(LibFunc::strncat)) ++ if (TLI.has(LibFunc_strncat) && FnName == TLI.getName(LibFunc_strncat)) + return true; + } + } +diff --git a/lib/Transforms/Scalar/LoopIdiomRecognize.cpp b/lib/Transforms/Scalar/LoopIdiomRecognize.cpp +index 1468676a354..43c33ec7a52 100644 +--- a/lib/Transforms/Scalar/LoopIdiomRecognize.cpp ++++ b/lib/Transforms/Scalar/LoopIdiomRecognize.cpp +@@ -229,9 +229,9 @@ bool LoopIdiomRecognize::runOnLoop(Loop *L) { + if (Name == "memset" || Name == "memcpy") + return false; + +- HasMemset = TLI->has(LibFunc::memset); +- HasMemsetPattern = TLI->has(LibFunc::memset_pattern16); +- HasMemcpy = TLI->has(LibFunc::memcpy); ++ HasMemset = TLI->has(LibFunc_memset); ++ HasMemsetPattern = TLI->has(LibFunc_memset_pattern16); ++ HasMemcpy = TLI->has(LibFunc_memcpy); + + if (HasMemset || HasMemsetPattern || HasMemcpy) + if (SE->hasLoopInvariantBackedgeTakenCount(L)) +diff --git a/lib/Transforms/Scalar/MemCpyOptimizer.cpp b/lib/Transforms/Scalar/MemCpyOptimizer.cpp +index d64c658f843..6c45e9e1e2b 100644 +--- a/lib/Transforms/Scalar/MemCpyOptimizer.cpp ++++ b/lib/Transforms/Scalar/MemCpyOptimizer.cpp +@@ -1233,7 +1233,7 @@ bool MemCpyOptPass::processMemCpy(MemCpyInst *M) { + bool MemCpyOptPass::processMemMove(MemMoveInst *M) { + AliasAnalysis &AA = LookupAliasAnalysis(); + +- if (!TLI->has(LibFunc::memmove)) ++ if (!TLI->has(LibFunc_memmove)) + return false; + + // See if the pointers alias. +@@ -1407,7 +1407,7 @@ bool MemCpyOptPass::runImpl( + // If we don't have at least memset and memcpy, there is little point of doing + // anything here. These are required by a freestanding implementation, so if + // even they are disabled, there is no point in trying hard. +- if (!TLI->has(LibFunc::memset) || !TLI->has(LibFunc::memcpy)) ++ if (!TLI->has(LibFunc_memset) || !TLI->has(LibFunc_memcpy)) + return false; + + while (1) { +diff --git a/lib/Transforms/Scalar/PartiallyInlineLibCalls.cpp b/lib/Transforms/Scalar/PartiallyInlineLibCalls.cpp +index c4b3e3464f4..b66859d9eee 100644 +--- a/lib/Transforms/Scalar/PartiallyInlineLibCalls.cpp ++++ b/lib/Transforms/Scalar/PartiallyInlineLibCalls.cpp +@@ -98,14 +98,14 @@ static bool runPartiallyInlineLibCalls(Function &F, TargetLibraryInfo *TLI, + + // Skip if function either has local linkage or is not a known library + // function. +- LibFunc::Func LibFunc; ++ LibFunc LF; + if (CalledFunc->hasLocalLinkage() || !CalledFunc->hasName() || +- !TLI->getLibFunc(CalledFunc->getName(), LibFunc)) ++ !TLI->getLibFunc(CalledFunc->getName(), LF)) + continue; + +- switch (LibFunc) { +- case LibFunc::sqrtf: +- case LibFunc::sqrt: ++ switch (LF) { ++ case LibFunc_sqrtf: ++ case LibFunc_sqrt: + if (TTI->haveFastSqrt(Call->getType()) && + optimizeSQRT(Call, CalledFunc, *CurrBB, BB)) + break; +diff --git a/lib/Transforms/Utils/BuildLibCalls.cpp b/lib/Transforms/Utils/BuildLibCalls.cpp +index f4260a9ff98..740fb31c1de 100644 +--- a/lib/Transforms/Utils/BuildLibCalls.cpp ++++ b/lib/Transforms/Utils/BuildLibCalls.cpp +@@ -107,254 +107,254 @@ static bool setNonNull(Function &F, unsigned n) { + } + + bool llvm::inferLibFuncAttributes(Function &F, const TargetLibraryInfo &TLI) { +- LibFunc::Func TheLibFunc; ++ LibFunc TheLibFunc; + if (!(TLI.getLibFunc(F, TheLibFunc) && TLI.has(TheLibFunc))) + return false; + + bool Changed = false; + switch (TheLibFunc) { +- case LibFunc::strlen: ++ case LibFunc_strlen: + Changed |= setOnlyReadsMemory(F); + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 1); + return Changed; +- case LibFunc::strchr: +- case LibFunc::strrchr: ++ case LibFunc_strchr: ++ case LibFunc_strrchr: + Changed |= setOnlyReadsMemory(F); + Changed |= setDoesNotThrow(F); + return Changed; +- case LibFunc::strtol: +- case LibFunc::strtod: +- case LibFunc::strtof: +- case LibFunc::strtoul: +- case LibFunc::strtoll: +- case LibFunc::strtold: +- case LibFunc::strtoull: ++ case LibFunc_strtol: ++ case LibFunc_strtod: ++ case LibFunc_strtof: ++ case LibFunc_strtoul: ++ case LibFunc_strtoll: ++ case LibFunc_strtold: ++ case LibFunc_strtoull: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 2); + Changed |= setOnlyReadsMemory(F, 1); + return Changed; +- case LibFunc::strcpy: +- case LibFunc::stpcpy: +- case LibFunc::strcat: +- case LibFunc::strncat: +- case LibFunc::strncpy: +- case LibFunc::stpncpy: ++ case LibFunc_strcpy: ++ case LibFunc_stpcpy: ++ case LibFunc_strcat: ++ case LibFunc_strncat: ++ case LibFunc_strncpy: ++ case LibFunc_stpncpy: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 2); + Changed |= setOnlyReadsMemory(F, 2); + return Changed; +- case LibFunc::strxfrm: ++ case LibFunc_strxfrm: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 1); + Changed |= setDoesNotCapture(F, 2); + Changed |= setOnlyReadsMemory(F, 2); + return Changed; +- case LibFunc::strcmp: // 0,1 +- case LibFunc::strspn: // 0,1 +- case LibFunc::strncmp: // 0,1 +- case LibFunc::strcspn: // 0,1 +- case LibFunc::strcoll: // 0,1 +- case LibFunc::strcasecmp: // 0,1 +- case LibFunc::strncasecmp: // ++ case LibFunc_strcmp: // 0,1 ++ case LibFunc_strspn: // 0,1 ++ case LibFunc_strncmp: // 0,1 ++ case LibFunc_strcspn: // 0,1 ++ case LibFunc_strcoll: // 0,1 ++ case LibFunc_strcasecmp: // 0,1 ++ case LibFunc_strncasecmp: // + Changed |= setOnlyReadsMemory(F); + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 1); + Changed |= setDoesNotCapture(F, 2); + return Changed; +- case LibFunc::strstr: +- case LibFunc::strpbrk: ++ case LibFunc_strstr: ++ case LibFunc_strpbrk: + Changed |= setOnlyReadsMemory(F); + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 2); + return Changed; +- case LibFunc::strtok: +- case LibFunc::strtok_r: ++ case LibFunc_strtok: ++ case LibFunc_strtok_r: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 2); + Changed |= setOnlyReadsMemory(F, 2); + return Changed; +- case LibFunc::scanf: ++ case LibFunc_scanf: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 1); + Changed |= setOnlyReadsMemory(F, 1); + return Changed; +- case LibFunc::setbuf: +- case LibFunc::setvbuf: ++ case LibFunc_setbuf: ++ case LibFunc_setvbuf: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 1); + return Changed; +- case LibFunc::strdup: +- case LibFunc::strndup: ++ case LibFunc_strdup: ++ case LibFunc_strndup: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotAlias(F, 0); + Changed |= setDoesNotCapture(F, 1); + Changed |= setOnlyReadsMemory(F, 1); + return Changed; +- case LibFunc::stat: +- case LibFunc::statvfs: ++ case LibFunc_stat: ++ case LibFunc_statvfs: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 1); + Changed |= setDoesNotCapture(F, 2); + Changed |= setOnlyReadsMemory(F, 1); + return Changed; +- case LibFunc::sscanf: ++ case LibFunc_sscanf: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 1); + Changed |= setDoesNotCapture(F, 2); + Changed |= setOnlyReadsMemory(F, 1); + Changed |= setOnlyReadsMemory(F, 2); + return Changed; +- case LibFunc::sprintf: ++ case LibFunc_sprintf: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 1); + Changed |= setDoesNotCapture(F, 2); + Changed |= setOnlyReadsMemory(F, 2); + return Changed; +- case LibFunc::snprintf: ++ case LibFunc_snprintf: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 1); + Changed |= setDoesNotCapture(F, 3); + Changed |= setOnlyReadsMemory(F, 3); + return Changed; +- case LibFunc::setitimer: ++ case LibFunc_setitimer: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 2); + Changed |= setDoesNotCapture(F, 3); + Changed |= setOnlyReadsMemory(F, 2); + return Changed; +- case LibFunc::system: ++ case LibFunc_system: + // May throw; "system" is a valid pthread cancellation point. + Changed |= setDoesNotCapture(F, 1); + Changed |= setOnlyReadsMemory(F, 1); + return Changed; +- case LibFunc::malloc: ++ case LibFunc_malloc: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotAlias(F, 0); + return Changed; +- case LibFunc::memcmp: ++ case LibFunc_memcmp: + Changed |= setOnlyReadsMemory(F); + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 1); + Changed |= setDoesNotCapture(F, 2); + return Changed; +- case LibFunc::memchr: +- case LibFunc::memrchr: ++ case LibFunc_memchr: ++ case LibFunc_memrchr: + Changed |= setOnlyReadsMemory(F); + Changed |= setDoesNotThrow(F); + return Changed; +- case LibFunc::modf: +- case LibFunc::modff: +- case LibFunc::modfl: ++ case LibFunc_modf: ++ case LibFunc_modff: ++ case LibFunc_modfl: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 2); + return Changed; +- case LibFunc::memcpy: +- case LibFunc::memccpy: +- case LibFunc::memmove: ++ case LibFunc_memcpy: ++ case LibFunc_memccpy: ++ case LibFunc_memmove: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 2); + Changed |= setOnlyReadsMemory(F, 2); + return Changed; +- case LibFunc::memcpy_chk: ++ case LibFunc_memcpy_chk: + Changed |= setDoesNotThrow(F); + return Changed; +- case LibFunc::memalign: ++ case LibFunc_memalign: + Changed |= setDoesNotAlias(F, 0); + return Changed; +- case LibFunc::mkdir: ++ case LibFunc_mkdir: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 1); + Changed |= setOnlyReadsMemory(F, 1); + return Changed; +- case LibFunc::mktime: ++ case LibFunc_mktime: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 1); + return Changed; +- case LibFunc::realloc: ++ case LibFunc_realloc: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotAlias(F, 0); + Changed |= setDoesNotCapture(F, 1); + return Changed; +- case LibFunc::read: ++ case LibFunc_read: + // May throw; "read" is a valid pthread cancellation point. + Changed |= setDoesNotCapture(F, 2); + return Changed; +- case LibFunc::rewind: ++ case LibFunc_rewind: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 1); + return Changed; +- case LibFunc::rmdir: +- case LibFunc::remove: +- case LibFunc::realpath: ++ case LibFunc_rmdir: ++ case LibFunc_remove: ++ case LibFunc_realpath: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 1); + Changed |= setOnlyReadsMemory(F, 1); + return Changed; +- case LibFunc::rename: ++ case LibFunc_rename: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 1); + Changed |= setDoesNotCapture(F, 2); + Changed |= setOnlyReadsMemory(F, 1); + Changed |= setOnlyReadsMemory(F, 2); + return Changed; +- case LibFunc::readlink: ++ case LibFunc_readlink: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 1); + Changed |= setDoesNotCapture(F, 2); + Changed |= setOnlyReadsMemory(F, 1); + return Changed; +- case LibFunc::write: ++ case LibFunc_write: + // May throw; "write" is a valid pthread cancellation point. + Changed |= setDoesNotCapture(F, 2); + Changed |= setOnlyReadsMemory(F, 2); + return Changed; +- case LibFunc::bcopy: ++ case LibFunc_bcopy: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 1); + Changed |= setDoesNotCapture(F, 2); + Changed |= setOnlyReadsMemory(F, 1); + return Changed; +- case LibFunc::bcmp: ++ case LibFunc_bcmp: + Changed |= setDoesNotThrow(F); + Changed |= setOnlyReadsMemory(F); + Changed |= setDoesNotCapture(F, 1); + Changed |= setDoesNotCapture(F, 2); + return Changed; +- case LibFunc::bzero: ++ case LibFunc_bzero: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 1); + return Changed; +- case LibFunc::calloc: ++ case LibFunc_calloc: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotAlias(F, 0); + return Changed; +- case LibFunc::chmod: +- case LibFunc::chown: ++ case LibFunc_chmod: ++ case LibFunc_chown: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 1); + Changed |= setOnlyReadsMemory(F, 1); + return Changed; +- case LibFunc::ctermid: +- case LibFunc::clearerr: +- case LibFunc::closedir: ++ case LibFunc_ctermid: ++ case LibFunc_clearerr: ++ case LibFunc_closedir: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 1); + return Changed; +- case LibFunc::atoi: +- case LibFunc::atol: +- case LibFunc::atof: +- case LibFunc::atoll: ++ case LibFunc_atoi: ++ case LibFunc_atol: ++ case LibFunc_atof: ++ case LibFunc_atoll: + Changed |= setDoesNotThrow(F); + Changed |= setOnlyReadsMemory(F); + Changed |= setDoesNotCapture(F, 1); + return Changed; +- case LibFunc::access: ++ case LibFunc_access: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 1); + Changed |= setOnlyReadsMemory(F, 1); + return Changed; +- case LibFunc::fopen: ++ case LibFunc_fopen: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotAlias(F, 0); + Changed |= setDoesNotCapture(F, 1); +@@ -362,150 +362,150 @@ bool llvm::inferLibFuncAttributes(Function &F, const TargetLibraryInfo &TLI) { + Changed |= setOnlyReadsMemory(F, 1); + Changed |= setOnlyReadsMemory(F, 2); + return Changed; +- case LibFunc::fdopen: ++ case LibFunc_fdopen: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotAlias(F, 0); + Changed |= setDoesNotCapture(F, 2); + Changed |= setOnlyReadsMemory(F, 2); + return Changed; +- case LibFunc::feof: +- case LibFunc::free: +- case LibFunc::fseek: +- case LibFunc::ftell: +- case LibFunc::fgetc: +- case LibFunc::fseeko: +- case LibFunc::ftello: +- case LibFunc::fileno: +- case LibFunc::fflush: +- case LibFunc::fclose: +- case LibFunc::fsetpos: +- case LibFunc::flockfile: +- case LibFunc::funlockfile: +- case LibFunc::ftrylockfile: ++ case LibFunc_feof: ++ case LibFunc_free: ++ case LibFunc_fseek: ++ case LibFunc_ftell: ++ case LibFunc_fgetc: ++ case LibFunc_fseeko: ++ case LibFunc_ftello: ++ case LibFunc_fileno: ++ case LibFunc_fflush: ++ case LibFunc_fclose: ++ case LibFunc_fsetpos: ++ case LibFunc_flockfile: ++ case LibFunc_funlockfile: ++ case LibFunc_ftrylockfile: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 1); + return Changed; +- case LibFunc::ferror: ++ case LibFunc_ferror: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 1); + Changed |= setOnlyReadsMemory(F); + return Changed; +- case LibFunc::fputc: +- case LibFunc::fstat: +- case LibFunc::frexp: +- case LibFunc::frexpf: +- case LibFunc::frexpl: +- case LibFunc::fstatvfs: ++ case LibFunc_fputc: ++ case LibFunc_fstat: ++ case LibFunc_frexp: ++ case LibFunc_frexpf: ++ case LibFunc_frexpl: ++ case LibFunc_fstatvfs: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 2); + return Changed; +- case LibFunc::fgets: ++ case LibFunc_fgets: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 3); + return Changed; +- case LibFunc::fread: ++ case LibFunc_fread: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 1); + Changed |= setDoesNotCapture(F, 4); + return Changed; +- case LibFunc::fwrite: ++ case LibFunc_fwrite: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 1); + Changed |= setDoesNotCapture(F, 4); + // FIXME: readonly #1? + return Changed; +- case LibFunc::fputs: ++ case LibFunc_fputs: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 1); + Changed |= setDoesNotCapture(F, 2); + Changed |= setOnlyReadsMemory(F, 1); + return Changed; +- case LibFunc::fscanf: +- case LibFunc::fprintf: ++ case LibFunc_fscanf: ++ case LibFunc_fprintf: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 1); + Changed |= setDoesNotCapture(F, 2); + Changed |= setOnlyReadsMemory(F, 2); + return Changed; +- case LibFunc::fgetpos: ++ case LibFunc_fgetpos: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 1); + Changed |= setDoesNotCapture(F, 2); + return Changed; +- case LibFunc::getc: +- case LibFunc::getlogin_r: +- case LibFunc::getc_unlocked: ++ case LibFunc_getc: ++ case LibFunc_getlogin_r: ++ case LibFunc_getc_unlocked: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 1); + return Changed; +- case LibFunc::getenv: ++ case LibFunc_getenv: + Changed |= setDoesNotThrow(F); + Changed |= setOnlyReadsMemory(F); + Changed |= setDoesNotCapture(F, 1); + return Changed; +- case LibFunc::gets: +- case LibFunc::getchar: ++ case LibFunc_gets: ++ case LibFunc_getchar: + Changed |= setDoesNotThrow(F); + return Changed; +- case LibFunc::getitimer: ++ case LibFunc_getitimer: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 2); + return Changed; +- case LibFunc::getpwnam: ++ case LibFunc_getpwnam: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 1); + Changed |= setOnlyReadsMemory(F, 1); + return Changed; +- case LibFunc::ungetc: ++ case LibFunc_ungetc: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 2); + return Changed; +- case LibFunc::uname: ++ case LibFunc_uname: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 1); + return Changed; +- case LibFunc::unlink: ++ case LibFunc_unlink: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 1); + Changed |= setOnlyReadsMemory(F, 1); + return Changed; +- case LibFunc::unsetenv: ++ case LibFunc_unsetenv: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 1); + Changed |= setOnlyReadsMemory(F, 1); + return Changed; +- case LibFunc::utime: +- case LibFunc::utimes: ++ case LibFunc_utime: ++ case LibFunc_utimes: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 1); + Changed |= setDoesNotCapture(F, 2); + Changed |= setOnlyReadsMemory(F, 1); + Changed |= setOnlyReadsMemory(F, 2); + return Changed; +- case LibFunc::putc: ++ case LibFunc_putc: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 2); + return Changed; +- case LibFunc::puts: +- case LibFunc::printf: +- case LibFunc::perror: ++ case LibFunc_puts: ++ case LibFunc_printf: ++ case LibFunc_perror: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 1); + Changed |= setOnlyReadsMemory(F, 1); + return Changed; +- case LibFunc::pread: ++ case LibFunc_pread: + // May throw; "pread" is a valid pthread cancellation point. + Changed |= setDoesNotCapture(F, 2); + return Changed; +- case LibFunc::pwrite: ++ case LibFunc_pwrite: + // May throw; "pwrite" is a valid pthread cancellation point. + Changed |= setDoesNotCapture(F, 2); + Changed |= setOnlyReadsMemory(F, 2); + return Changed; +- case LibFunc::putchar: ++ case LibFunc_putchar: + Changed |= setDoesNotThrow(F); + return Changed; +- case LibFunc::popen: ++ case LibFunc_popen: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotAlias(F, 0); + Changed |= setDoesNotCapture(F, 1); +@@ -513,132 +513,132 @@ bool llvm::inferLibFuncAttributes(Function &F, const TargetLibraryInfo &TLI) { + Changed |= setOnlyReadsMemory(F, 1); + Changed |= setOnlyReadsMemory(F, 2); + return Changed; +- case LibFunc::pclose: ++ case LibFunc_pclose: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 1); + return Changed; +- case LibFunc::vscanf: ++ case LibFunc_vscanf: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 1); + Changed |= setOnlyReadsMemory(F, 1); + return Changed; +- case LibFunc::vsscanf: ++ case LibFunc_vsscanf: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 1); + Changed |= setDoesNotCapture(F, 2); + Changed |= setOnlyReadsMemory(F, 1); + Changed |= setOnlyReadsMemory(F, 2); + return Changed; +- case LibFunc::vfscanf: ++ case LibFunc_vfscanf: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 1); + Changed |= setDoesNotCapture(F, 2); + Changed |= setOnlyReadsMemory(F, 2); + return Changed; +- case LibFunc::valloc: ++ case LibFunc_valloc: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotAlias(F, 0); + return Changed; +- case LibFunc::vprintf: ++ case LibFunc_vprintf: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 1); + Changed |= setOnlyReadsMemory(F, 1); + return Changed; +- case LibFunc::vfprintf: +- case LibFunc::vsprintf: ++ case LibFunc_vfprintf: ++ case LibFunc_vsprintf: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 1); + Changed |= setDoesNotCapture(F, 2); + Changed |= setOnlyReadsMemory(F, 2); + return Changed; +- case LibFunc::vsnprintf: ++ case LibFunc_vsnprintf: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 1); + Changed |= setDoesNotCapture(F, 3); + Changed |= setOnlyReadsMemory(F, 3); + return Changed; +- case LibFunc::open: ++ case LibFunc_open: + // May throw; "open" is a valid pthread cancellation point. + Changed |= setDoesNotCapture(F, 1); + Changed |= setOnlyReadsMemory(F, 1); + return Changed; +- case LibFunc::opendir: ++ case LibFunc_opendir: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotAlias(F, 0); + Changed |= setDoesNotCapture(F, 1); + Changed |= setOnlyReadsMemory(F, 1); + return Changed; +- case LibFunc::tmpfile: ++ case LibFunc_tmpfile: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotAlias(F, 0); + return Changed; +- case LibFunc::times: ++ case LibFunc_times: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 1); + return Changed; +- case LibFunc::htonl: +- case LibFunc::htons: +- case LibFunc::ntohl: +- case LibFunc::ntohs: ++ case LibFunc_htonl: ++ case LibFunc_htons: ++ case LibFunc_ntohl: ++ case LibFunc_ntohs: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotAccessMemory(F); + return Changed; +- case LibFunc::lstat: ++ case LibFunc_lstat: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 1); + Changed |= setDoesNotCapture(F, 2); + Changed |= setOnlyReadsMemory(F, 1); + return Changed; +- case LibFunc::lchown: ++ case LibFunc_lchown: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 1); + Changed |= setOnlyReadsMemory(F, 1); + return Changed; +- case LibFunc::qsort: ++ case LibFunc_qsort: + // May throw; places call through function pointer. + Changed |= setDoesNotCapture(F, 4); + return Changed; +- case LibFunc::dunder_strdup: +- case LibFunc::dunder_strndup: ++ case LibFunc_dunder_strdup: ++ case LibFunc_dunder_strndup: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotAlias(F, 0); + Changed |= setDoesNotCapture(F, 1); + Changed |= setOnlyReadsMemory(F, 1); + return Changed; +- case LibFunc::dunder_strtok_r: ++ case LibFunc_dunder_strtok_r: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 2); + Changed |= setOnlyReadsMemory(F, 2); + return Changed; +- case LibFunc::under_IO_getc: ++ case LibFunc_under_IO_getc: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 1); + return Changed; +- case LibFunc::under_IO_putc: ++ case LibFunc_under_IO_putc: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 2); + return Changed; +- case LibFunc::dunder_isoc99_scanf: ++ case LibFunc_dunder_isoc99_scanf: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 1); + Changed |= setOnlyReadsMemory(F, 1); + return Changed; +- case LibFunc::stat64: +- case LibFunc::lstat64: +- case LibFunc::statvfs64: ++ case LibFunc_stat64: ++ case LibFunc_lstat64: ++ case LibFunc_statvfs64: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 1); + Changed |= setDoesNotCapture(F, 2); + Changed |= setOnlyReadsMemory(F, 1); + return Changed; +- case LibFunc::dunder_isoc99_sscanf: ++ case LibFunc_dunder_isoc99_sscanf: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 1); + Changed |= setDoesNotCapture(F, 2); + Changed |= setOnlyReadsMemory(F, 1); + Changed |= setOnlyReadsMemory(F, 2); + return Changed; +- case LibFunc::fopen64: ++ case LibFunc_fopen64: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotAlias(F, 0); + Changed |= setDoesNotCapture(F, 1); +@@ -646,26 +646,26 @@ bool llvm::inferLibFuncAttributes(Function &F, const TargetLibraryInfo &TLI) { + Changed |= setOnlyReadsMemory(F, 1); + Changed |= setOnlyReadsMemory(F, 2); + return Changed; +- case LibFunc::fseeko64: +- case LibFunc::ftello64: ++ case LibFunc_fseeko64: ++ case LibFunc_ftello64: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 1); + return Changed; +- case LibFunc::tmpfile64: ++ case LibFunc_tmpfile64: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotAlias(F, 0); + return Changed; +- case LibFunc::fstat64: +- case LibFunc::fstatvfs64: ++ case LibFunc_fstat64: ++ case LibFunc_fstatvfs64: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 2); + return Changed; +- case LibFunc::open64: ++ case LibFunc_open64: + // May throw; "open" is a valid pthread cancellation point. + Changed |= setDoesNotCapture(F, 1); + Changed |= setOnlyReadsMemory(F, 1); + return Changed; +- case LibFunc::gettimeofday: ++ case LibFunc_gettimeofday: + // Currently some platforms have the restrict keyword on the arguments to + // gettimeofday. To be conservative, do not add noalias to gettimeofday's + // arguments. +@@ -673,29 +673,29 @@ bool llvm::inferLibFuncAttributes(Function &F, const TargetLibraryInfo &TLI) { + Changed |= setDoesNotCapture(F, 1); + Changed |= setDoesNotCapture(F, 2); + return Changed; +- case LibFunc::Znwj: // new(unsigned int) +- case LibFunc::Znwm: // new(unsigned long) +- case LibFunc::Znaj: // new[](unsigned int) +- case LibFunc::Znam: // new[](unsigned long) +- case LibFunc::msvc_new_int: // new(unsigned int) +- case LibFunc::msvc_new_longlong: // new(unsigned long long) +- case LibFunc::msvc_new_array_int: // new[](unsigned int) +- case LibFunc::msvc_new_array_longlong: // new[](unsigned long long) ++ case LibFunc_Znwj: // new(unsigned int) ++ case LibFunc_Znwm: // new(unsigned long) ++ case LibFunc_Znaj: // new[](unsigned int) ++ case LibFunc_Znam: // new[](unsigned long) ++ case LibFunc_msvc_new_int: // new(unsigned int) ++ case LibFunc_msvc_new_longlong: // new(unsigned long long) ++ case LibFunc_msvc_new_array_int: // new[](unsigned int) ++ case LibFunc_msvc_new_array_longlong: // new[](unsigned long long) + // Operator new always returns a nonnull noalias pointer + Changed |= setNonNull(F, AttributeSet::ReturnIndex); + Changed |= setDoesNotAlias(F, AttributeSet::ReturnIndex); + return Changed; + //TODO: add LibFunc entries for: +- //case LibFunc::memset_pattern4: +- //case LibFunc::memset_pattern8: +- case LibFunc::memset_pattern16: ++ //case LibFunc_memset_pattern4: ++ //case LibFunc_memset_pattern8: ++ case LibFunc_memset_pattern16: + Changed |= setOnlyAccessesArgMemory(F); + Changed |= setDoesNotCapture(F, 1); + Changed |= setDoesNotCapture(F, 2); + Changed |= setOnlyReadsMemory(F, 2); + return Changed; + // int __nvvm_reflect(const char *) +- case LibFunc::nvvm_reflect: ++ case LibFunc_nvvm_reflect: + Changed |= setDoesNotAccessMemory(F); + Changed |= setDoesNotThrow(F); + return Changed; +@@ -716,7 +716,7 @@ Value *llvm::castToCStr(Value *V, IRBuilder<> &B) { + + Value *llvm::emitStrLen(Value *Ptr, IRBuilder<> &B, const DataLayout &DL, + const TargetLibraryInfo *TLI) { +- if (!TLI->has(LibFunc::strlen)) ++ if (!TLI->has(LibFunc_strlen)) + return nullptr; + + Module *M = B.GetInsertBlock()->getModule(); +@@ -733,7 +733,7 @@ Value *llvm::emitStrLen(Value *Ptr, IRBuilder<> &B, const DataLayout &DL, + + Value *llvm::emitStrChr(Value *Ptr, char C, IRBuilder<> &B, + const TargetLibraryInfo *TLI) { +- if (!TLI->has(LibFunc::strchr)) ++ if (!TLI->has(LibFunc_strchr)) + return nullptr; + + Module *M = B.GetInsertBlock()->getModule(); +@@ -751,7 +751,7 @@ Value *llvm::emitStrChr(Value *Ptr, char C, IRBuilder<> &B, + + Value *llvm::emitStrNCmp(Value *Ptr1, Value *Ptr2, Value *Len, IRBuilder<> &B, + const DataLayout &DL, const TargetLibraryInfo *TLI) { +- if (!TLI->has(LibFunc::strncmp)) ++ if (!TLI->has(LibFunc_strncmp)) + return nullptr; + + Module *M = B.GetInsertBlock()->getModule(); +@@ -771,7 +771,7 @@ Value *llvm::emitStrNCmp(Value *Ptr1, Value *Ptr2, Value *Len, IRBuilder<> &B, + + Value *llvm::emitStrCpy(Value *Dst, Value *Src, IRBuilder<> &B, + const TargetLibraryInfo *TLI, StringRef Name) { +- if (!TLI->has(LibFunc::strcpy)) ++ if (!TLI->has(LibFunc_strcpy)) + return nullptr; + + Module *M = B.GetInsertBlock()->getModule(); +@@ -787,7 +787,7 @@ Value *llvm::emitStrCpy(Value *Dst, Value *Src, IRBuilder<> &B, + + Value *llvm::emitStrNCpy(Value *Dst, Value *Src, Value *Len, IRBuilder<> &B, + const TargetLibraryInfo *TLI, StringRef Name) { +- if (!TLI->has(LibFunc::strncpy)) ++ if (!TLI->has(LibFunc_strncpy)) + return nullptr; + + Module *M = B.GetInsertBlock()->getModule(); +@@ -805,7 +805,7 @@ Value *llvm::emitStrNCpy(Value *Dst, Value *Src, Value *Len, IRBuilder<> &B, + Value *llvm::emitMemCpyChk(Value *Dst, Value *Src, Value *Len, Value *ObjSize, + IRBuilder<> &B, const DataLayout &DL, + const TargetLibraryInfo *TLI) { +- if (!TLI->has(LibFunc::memcpy_chk)) ++ if (!TLI->has(LibFunc_memcpy_chk)) + return nullptr; + + Module *M = B.GetInsertBlock()->getModule(); +@@ -827,7 +827,7 @@ Value *llvm::emitMemCpyChk(Value *Dst, Value *Src, Value *Len, Value *ObjSize, + + Value *llvm::emitMemChr(Value *Ptr, Value *Val, Value *Len, IRBuilder<> &B, + const DataLayout &DL, const TargetLibraryInfo *TLI) { +- if (!TLI->has(LibFunc::memchr)) ++ if (!TLI->has(LibFunc_memchr)) + return nullptr; + + Module *M = B.GetInsertBlock()->getModule(); +@@ -846,7 +846,7 @@ Value *llvm::emitMemChr(Value *Ptr, Value *Val, Value *Len, IRBuilder<> &B, + + Value *llvm::emitMemCmp(Value *Ptr1, Value *Ptr2, Value *Len, IRBuilder<> &B, + const DataLayout &DL, const TargetLibraryInfo *TLI) { +- if (!TLI->has(LibFunc::memcmp)) ++ if (!TLI->has(LibFunc_memcmp)) + return nullptr; + + Module *M = B.GetInsertBlock()->getModule(); +@@ -913,7 +913,7 @@ Value *llvm::emitBinaryFloatFnCall(Value *Op1, Value *Op2, StringRef Name, + + Value *llvm::emitPutChar(Value *Char, IRBuilder<> &B, + const TargetLibraryInfo *TLI) { +- if (!TLI->has(LibFunc::putchar)) ++ if (!TLI->has(LibFunc_putchar)) + return nullptr; + + Module *M = B.GetInsertBlock()->getModule(); +@@ -933,7 +933,7 @@ Value *llvm::emitPutChar(Value *Char, IRBuilder<> &B, + + Value *llvm::emitPutS(Value *Str, IRBuilder<> &B, + const TargetLibraryInfo *TLI) { +- if (!TLI->has(LibFunc::puts)) ++ if (!TLI->has(LibFunc_puts)) + return nullptr; + + Module *M = B.GetInsertBlock()->getModule(); +@@ -948,7 +948,7 @@ Value *llvm::emitPutS(Value *Str, IRBuilder<> &B, + + Value *llvm::emitFPutC(Value *Char, Value *File, IRBuilder<> &B, + const TargetLibraryInfo *TLI) { +- if (!TLI->has(LibFunc::fputc)) ++ if (!TLI->has(LibFunc_fputc)) + return nullptr; + + Module *M = B.GetInsertBlock()->getModule(); +@@ -967,11 +967,11 @@ Value *llvm::emitFPutC(Value *Char, Value *File, IRBuilder<> &B, + + Value *llvm::emitFPutS(Value *Str, Value *File, IRBuilder<> &B, + const TargetLibraryInfo *TLI) { +- if (!TLI->has(LibFunc::fputs)) ++ if (!TLI->has(LibFunc_fputs)) + return nullptr; + + Module *M = B.GetInsertBlock()->getModule(); +- StringRef FPutsName = TLI->getName(LibFunc::fputs); ++ StringRef FPutsName = TLI->getName(LibFunc_fputs); + Constant *F = M->getOrInsertFunction( + FPutsName, B.getInt32Ty(), B.getInt8PtrTy(), File->getType(), nullptr); + if (File->getType()->isPointerTy()) +@@ -985,12 +985,12 @@ Value *llvm::emitFPutS(Value *Str, Value *File, IRBuilder<> &B, + + Value *llvm::emitFWrite(Value *Ptr, Value *Size, Value *File, IRBuilder<> &B, + const DataLayout &DL, const TargetLibraryInfo *TLI) { +- if (!TLI->has(LibFunc::fwrite)) ++ if (!TLI->has(LibFunc_fwrite)) + return nullptr; + + Module *M = B.GetInsertBlock()->getModule(); + LLVMContext &Context = B.GetInsertBlock()->getContext(); +- StringRef FWriteName = TLI->getName(LibFunc::fwrite); ++ StringRef FWriteName = TLI->getName(LibFunc_fwrite); + Constant *F = M->getOrInsertFunction( + FWriteName, DL.getIntPtrType(Context), B.getInt8PtrTy(), + DL.getIntPtrType(Context), DL.getIntPtrType(Context), File->getType(), +diff --git a/lib/Transforms/Utils/Local.cpp b/lib/Transforms/Utils/Local.cpp +index f1838d89146..7667312bb0e 100644 +--- a/lib/Transforms/Utils/Local.cpp ++++ b/lib/Transforms/Utils/Local.cpp +@@ -1957,19 +1957,19 @@ bool llvm::recognizeBSwapOrBitReverseIdiom( + void llvm::maybeMarkSanitizerLibraryCallNoBuiltin(CallInst *CI, + const TargetLibraryInfo *TLI) { + Function *F = CI->getCalledFunction(); +- LibFunc::Func Func; ++ LibFunc Func; + if (!F || F->hasLocalLinkage() || !F->hasName() || + !TLI->getLibFunc(F->getName(), Func)) + return; + switch (Func) { + default: break; +- case LibFunc::memcmp: +- case LibFunc::memchr: +- case LibFunc::strcpy: +- case LibFunc::stpcpy: +- case LibFunc::strcmp: +- case LibFunc::strlen: +- case LibFunc::strnlen: ++ case LibFunc_memcmp: ++ case LibFunc_memchr: ++ case LibFunc_strcpy: ++ case LibFunc_stpcpy: ++ case LibFunc_strcmp: ++ case LibFunc_strlen: ++ case LibFunc_strnlen: + CI->addAttribute(AttributeSet::FunctionIndex, Attribute::NoBuiltin); + break; + } +diff --git a/lib/Transforms/Utils/SimplifyLibCalls.cpp b/lib/Transforms/Utils/SimplifyLibCalls.cpp +index c2986951e48..69ac831fcfd 100644 +--- a/lib/Transforms/Utils/SimplifyLibCalls.cpp ++++ b/lib/Transforms/Utils/SimplifyLibCalls.cpp +@@ -51,9 +51,9 @@ static cl::opt + // Helper Functions + //===----------------------------------------------------------------------===// + +-static bool ignoreCallingConv(LibFunc::Func Func) { +- return Func == LibFunc::abs || Func == LibFunc::labs || +- Func == LibFunc::llabs || Func == LibFunc::strlen; ++static bool ignoreCallingConv(LibFunc Func) { ++ return Func == LibFunc_abs || Func == LibFunc_labs || ++ Func == LibFunc_llabs || Func == LibFunc_strlen; + } + + /// Return true if it only matters that the value is equal or not-equal to zero. +@@ -91,8 +91,8 @@ static bool callHasFloatingPointArgument(const CallInst *CI) { + /// \brief Check whether the overloaded unary floating point function + /// corresponding to \a Ty is available. + static bool hasUnaryFloatFn(const TargetLibraryInfo *TLI, Type *Ty, +- LibFunc::Func DoubleFn, LibFunc::Func FloatFn, +- LibFunc::Func LongDoubleFn) { ++ LibFunc DoubleFn, LibFunc FloatFn, ++ LibFunc LongDoubleFn) { + switch (Ty->getTypeID()) { + case Type::FloatTyID: + return TLI->has(FloatFn); +@@ -779,7 +779,7 @@ Value *LibCallSimplifier::optimizeMemMove(CallInst *CI, IRBuilder<> &B) { + // functions be moved here? + static Value *emitCalloc(Value *Num, Value *Size, const AttributeSet &Attrs, + IRBuilder<> &B, const TargetLibraryInfo &TLI) { +- LibFunc::Func Func; ++ LibFunc Func; + if (!TLI.getLibFunc("calloc", Func) || !TLI.has(Func)) + return nullptr; + +@@ -814,9 +814,9 @@ static Value *foldMallocMemset(CallInst *Memset, IRBuilder<> &B, + + // Is the inner call really malloc()? + Function *InnerCallee = Malloc->getCalledFunction(); +- LibFunc::Func Func; ++ LibFunc Func; + if (!TLI.getLibFunc(*InnerCallee, Func) || !TLI.has(Func) || +- Func != LibFunc::malloc) ++ Func != LibFunc_malloc) + return nullptr; + + // The memset must cover the same number of bytes that are malloc'd. +@@ -999,15 +999,15 @@ Value *LibCallSimplifier::optimizePow(CallInst *CI, IRBuilder<> &B) { + return Op1C; + // pow(2.0, x) -> exp2(x) + if (Op1C->isExactlyValue(2.0) && +- hasUnaryFloatFn(TLI, Op1->getType(), LibFunc::exp2, LibFunc::exp2f, +- LibFunc::exp2l)) +- return emitUnaryFloatFnCall(Op2, TLI->getName(LibFunc::exp2), B, ++ hasUnaryFloatFn(TLI, Op1->getType(), LibFunc_exp2, LibFunc_exp2f, ++ LibFunc_exp2l)) ++ return emitUnaryFloatFnCall(Op2, TLI->getName(LibFunc_exp2), B, + Callee->getAttributes()); + // pow(10.0, x) -> exp10(x) + if (Op1C->isExactlyValue(10.0) && +- hasUnaryFloatFn(TLI, Op1->getType(), LibFunc::exp10, LibFunc::exp10f, +- LibFunc::exp10l)) +- return emitUnaryFloatFnCall(Op2, TLI->getName(LibFunc::exp10), B, ++ hasUnaryFloatFn(TLI, Op1->getType(), LibFunc_exp10, LibFunc_exp10f, ++ LibFunc_exp10l)) ++ return emitUnaryFloatFnCall(Op2, TLI->getName(LibFunc_exp10), B, + Callee->getAttributes()); + } + +@@ -1019,10 +1019,10 @@ Value *LibCallSimplifier::optimizePow(CallInst *CI, IRBuilder<> &B) { + // pow(exp(x), y) = pow(inf, 0.001) = inf, whereas exp(x*y) = exp(1). + auto *OpC = dyn_cast(Op1); + if (OpC && OpC->hasUnsafeAlgebra() && CI->hasUnsafeAlgebra()) { +- LibFunc::Func Func; ++ LibFunc Func; + Function *OpCCallee = OpC->getCalledFunction(); + if (OpCCallee && TLI->getLibFunc(OpCCallee->getName(), Func) && +- TLI->has(Func) && (Func == LibFunc::exp || Func == LibFunc::exp2)) { ++ TLI->has(Func) && (Func == LibFunc_exp || Func == LibFunc_exp2)) { + IRBuilder<>::FastMathFlagGuard Guard(B); + B.setFastMathFlags(CI->getFastMathFlags()); + Value *FMul = B.CreateFMul(OpC->getArgOperand(0), Op2, "mul"); +@@ -1039,16 +1039,16 @@ Value *LibCallSimplifier::optimizePow(CallInst *CI, IRBuilder<> &B) { + return ConstantFP::get(CI->getType(), 1.0); + + if (Op2C->isExactlyValue(0.5) && +- hasUnaryFloatFn(TLI, Op2->getType(), LibFunc::sqrt, LibFunc::sqrtf, +- LibFunc::sqrtl) && +- hasUnaryFloatFn(TLI, Op2->getType(), LibFunc::fabs, LibFunc::fabsf, +- LibFunc::fabsl)) { ++ hasUnaryFloatFn(TLI, Op2->getType(), LibFunc_sqrt, LibFunc_sqrtf, ++ LibFunc_sqrtl) && ++ hasUnaryFloatFn(TLI, Op2->getType(), LibFunc_fabs, LibFunc_fabsf, ++ LibFunc_fabsl)) { + + // In -ffast-math, pow(x, 0.5) -> sqrt(x). + if (CI->hasUnsafeAlgebra()) { + IRBuilder<>::FastMathFlagGuard Guard(B); + B.setFastMathFlags(CI->getFastMathFlags()); +- return emitUnaryFloatFnCall(Op1, TLI->getName(LibFunc::sqrt), B, ++ return emitUnaryFloatFnCall(Op1, TLI->getName(LibFunc_sqrt), B, + Callee->getAttributes()); + } + +@@ -1113,11 +1113,11 @@ Value *LibCallSimplifier::optimizeExp2(CallInst *CI, IRBuilder<> &B) { + Value *Op = CI->getArgOperand(0); + // Turn exp2(sitofp(x)) -> ldexp(1.0, sext(x)) if sizeof(x) <= 32 + // Turn exp2(uitofp(x)) -> ldexp(1.0, zext(x)) if sizeof(x) < 32 +- LibFunc::Func LdExp = LibFunc::ldexpl; ++ LibFunc LdExp = LibFunc_ldexpl; + if (Op->getType()->isFloatTy()) +- LdExp = LibFunc::ldexpf; ++ LdExp = LibFunc_ldexpf; + else if (Op->getType()->isDoubleTy()) +- LdExp = LibFunc::ldexp; ++ LdExp = LibFunc_ldexp; + + if (TLI->has(LdExp)) { + Value *LdExpArg = nullptr; +@@ -1228,17 +1228,17 @@ Value *LibCallSimplifier::optimizeLog(CallInst *CI, IRBuilder<> &B) { + FMF.setUnsafeAlgebra(); + B.setFastMathFlags(FMF); + +- LibFunc::Func Func; ++ LibFunc Func; + Function *F = OpC->getCalledFunction(); + if (F && ((TLI->getLibFunc(F->getName(), Func) && TLI->has(Func) && +- Func == LibFunc::pow) || F->getIntrinsicID() == Intrinsic::pow)) ++ Func == LibFunc_pow) || F->getIntrinsicID() == Intrinsic::pow)) + return B.CreateFMul(OpC->getArgOperand(1), + emitUnaryFloatFnCall(OpC->getOperand(0), Callee->getName(), B, + Callee->getAttributes()), "mul"); + + // log(exp2(y)) -> y*log(2) + if (F && Name == "log" && TLI->getLibFunc(F->getName(), Func) && +- TLI->has(Func) && Func == LibFunc::exp2) ++ TLI->has(Func) && Func == LibFunc_exp2) + return B.CreateFMul( + OpC->getArgOperand(0), + emitUnaryFloatFnCall(ConstantFP::get(CI->getType(), 2.0), +@@ -1250,8 +1250,8 @@ Value *LibCallSimplifier::optimizeLog(CallInst *CI, IRBuilder<> &B) { + Value *LibCallSimplifier::optimizeSqrt(CallInst *CI, IRBuilder<> &B) { + Function *Callee = CI->getCalledFunction(); + Value *Ret = nullptr; +- if (TLI->has(LibFunc::sqrtf) && (Callee->getName() == "sqrt" || +- Callee->getIntrinsicID() == Intrinsic::sqrt)) ++ if (TLI->has(LibFunc_sqrtf) && (Callee->getName() == "sqrt" || ++ Callee->getIntrinsicID() == Intrinsic::sqrt)) + Ret = optimizeUnaryDoubleFP(CI, B, true); + + if (!CI->hasUnsafeAlgebra()) +@@ -1333,12 +1333,12 @@ Value *LibCallSimplifier::optimizeTan(CallInst *CI, IRBuilder<> &B) { + // tan(atan(x)) -> x + // tanf(atanf(x)) -> x + // tanl(atanl(x)) -> x +- LibFunc::Func Func; ++ LibFunc Func; + Function *F = OpC->getCalledFunction(); + if (F && TLI->getLibFunc(F->getName(), Func) && TLI->has(Func) && +- ((Func == LibFunc::atan && Callee->getName() == "tan") || +- (Func == LibFunc::atanf && Callee->getName() == "tanf") || +- (Func == LibFunc::atanl && Callee->getName() == "tanl"))) ++ ((Func == LibFunc_atan && Callee->getName() == "tan") || ++ (Func == LibFunc_atanf && Callee->getName() == "tanf") || ++ (Func == LibFunc_atanl && Callee->getName() == "tanl"))) + Ret = OpC->getArgOperand(0); + return Ret; + } +@@ -1450,24 +1450,24 @@ void LibCallSimplifier::classifyArgUse( + return; + + Function *Callee = CI->getCalledFunction(); +- LibFunc::Func Func; ++ LibFunc Func; + if (!Callee || !TLI->getLibFunc(*Callee, Func) || !TLI->has(Func) || + !isTrigLibCall(CI)) + return; + + if (IsFloat) { +- if (Func == LibFunc::sinpif) ++ if (Func == LibFunc_sinpif) + SinCalls.push_back(CI); +- else if (Func == LibFunc::cospif) ++ else if (Func == LibFunc_cospif) + CosCalls.push_back(CI); +- else if (Func == LibFunc::sincospif_stret) ++ else if (Func == LibFunc_sincospif_stret) + SinCosCalls.push_back(CI); + } else { +- if (Func == LibFunc::sinpi) ++ if (Func == LibFunc_sinpi) + SinCalls.push_back(CI); +- else if (Func == LibFunc::cospi) ++ else if (Func == LibFunc_cospi) + CosCalls.push_back(CI); +- else if (Func == LibFunc::sincospi_stret) ++ else if (Func == LibFunc_sincospi_stret) + SinCosCalls.push_back(CI); + } + } +@@ -1645,7 +1645,7 @@ Value *LibCallSimplifier::optimizePrintF(CallInst *CI, IRBuilder<> &B) { + + // printf(format, ...) -> iprintf(format, ...) if no floating point + // arguments. +- if (TLI->has(LibFunc::iprintf) && !callHasFloatingPointArgument(CI)) { ++ if (TLI->has(LibFunc_iprintf) && !callHasFloatingPointArgument(CI)) { + Module *M = B.GetInsertBlock()->getParent()->getParent(); + Constant *IPrintFFn = + M->getOrInsertFunction("iprintf", FT, Callee->getAttributes()); +@@ -1726,7 +1726,7 @@ Value *LibCallSimplifier::optimizeSPrintF(CallInst *CI, IRBuilder<> &B) { + + // sprintf(str, format, ...) -> siprintf(str, format, ...) if no floating + // point arguments. +- if (TLI->has(LibFunc::siprintf) && !callHasFloatingPointArgument(CI)) { ++ if (TLI->has(LibFunc_siprintf) && !callHasFloatingPointArgument(CI)) { + Module *M = B.GetInsertBlock()->getParent()->getParent(); + Constant *SIPrintFFn = + M->getOrInsertFunction("siprintf", FT, Callee->getAttributes()); +@@ -1796,7 +1796,7 @@ Value *LibCallSimplifier::optimizeFPrintF(CallInst *CI, IRBuilder<> &B) { + + // fprintf(stream, format, ...) -> fiprintf(stream, format, ...) if no + // floating point arguments. +- if (TLI->has(LibFunc::fiprintf) && !callHasFloatingPointArgument(CI)) { ++ if (TLI->has(LibFunc_fiprintf) && !callHasFloatingPointArgument(CI)) { + Module *M = B.GetInsertBlock()->getParent()->getParent(); + Constant *FIPrintFFn = + M->getOrInsertFunction("fiprintf", FT, Callee->getAttributes()); +@@ -1875,7 +1875,7 @@ Value *LibCallSimplifier::optimizePuts(CallInst *CI, IRBuilder<> &B) { + } + + bool LibCallSimplifier::hasFloatVersion(StringRef FuncName) { +- LibFunc::Func Func; ++ LibFunc Func; + SmallString<20> FloatFuncName = FuncName; + FloatFuncName += 'f'; + if (TLI->getLibFunc(FloatFuncName, Func)) +@@ -1885,7 +1885,7 @@ bool LibCallSimplifier::hasFloatVersion(StringRef FuncName) { + + Value *LibCallSimplifier::optimizeStringMemoryLibCall(CallInst *CI, + IRBuilder<> &Builder) { +- LibFunc::Func Func; ++ LibFunc Func; + Function *Callee = CI->getCalledFunction(); + // Check for string/memory library functions. + if (TLI->getLibFunc(*Callee, Func) && TLI->has(Func)) { +@@ -1894,51 +1894,51 @@ Value *LibCallSimplifier::optimizeStringMemoryLibCall(CallInst *CI, + CI->getCallingConv() == llvm::CallingConv::C) && + "Optimizing string/memory libcall would change the calling convention"); + switch (Func) { +- case LibFunc::strcat: ++ case LibFunc_strcat: + return optimizeStrCat(CI, Builder); +- case LibFunc::strncat: ++ case LibFunc_strncat: + return optimizeStrNCat(CI, Builder); +- case LibFunc::strchr: ++ case LibFunc_strchr: + return optimizeStrChr(CI, Builder); +- case LibFunc::strrchr: ++ case LibFunc_strrchr: + return optimizeStrRChr(CI, Builder); +- case LibFunc::strcmp: ++ case LibFunc_strcmp: + return optimizeStrCmp(CI, Builder); +- case LibFunc::strncmp: ++ case LibFunc_strncmp: + return optimizeStrNCmp(CI, Builder); +- case LibFunc::strcpy: ++ case LibFunc_strcpy: + return optimizeStrCpy(CI, Builder); +- case LibFunc::stpcpy: ++ case LibFunc_stpcpy: + return optimizeStpCpy(CI, Builder); +- case LibFunc::strncpy: ++ case LibFunc_strncpy: + return optimizeStrNCpy(CI, Builder); +- case LibFunc::strlen: ++ case LibFunc_strlen: + return optimizeStrLen(CI, Builder); +- case LibFunc::strpbrk: ++ case LibFunc_strpbrk: + return optimizeStrPBrk(CI, Builder); +- case LibFunc::strtol: +- case LibFunc::strtod: +- case LibFunc::strtof: +- case LibFunc::strtoul: +- case LibFunc::strtoll: +- case LibFunc::strtold: +- case LibFunc::strtoull: ++ case LibFunc_strtol: ++ case LibFunc_strtod: ++ case LibFunc_strtof: ++ case LibFunc_strtoul: ++ case LibFunc_strtoll: ++ case LibFunc_strtold: ++ case LibFunc_strtoull: + return optimizeStrTo(CI, Builder); +- case LibFunc::strspn: ++ case LibFunc_strspn: + return optimizeStrSpn(CI, Builder); +- case LibFunc::strcspn: ++ case LibFunc_strcspn: + return optimizeStrCSpn(CI, Builder); +- case LibFunc::strstr: ++ case LibFunc_strstr: + return optimizeStrStr(CI, Builder); +- case LibFunc::memchr: ++ case LibFunc_memchr: + return optimizeMemChr(CI, Builder); +- case LibFunc::memcmp: ++ case LibFunc_memcmp: + return optimizeMemCmp(CI, Builder); +- case LibFunc::memcpy: ++ case LibFunc_memcpy: + return optimizeMemCpy(CI, Builder); +- case LibFunc::memmove: ++ case LibFunc_memmove: + return optimizeMemMove(CI, Builder); +- case LibFunc::memset: ++ case LibFunc_memset: + return optimizeMemSet(CI, Builder); + default: + break; +@@ -1951,7 +1951,7 @@ Value *LibCallSimplifier::optimizeCall(CallInst *CI) { + if (CI->isNoBuiltin()) + return nullptr; + +- LibFunc::Func Func; ++ LibFunc Func; + Function *Callee = CI->getCalledFunction(); + StringRef FuncName = Callee->getName(); + +@@ -2013,110 +2013,110 @@ Value *LibCallSimplifier::optimizeCall(CallInst *CI) { + if (Value *V = optimizeStringMemoryLibCall(CI, Builder)) + return V; + switch (Func) { +- case LibFunc::cosf: +- case LibFunc::cos: +- case LibFunc::cosl: ++ case LibFunc_cosf: ++ case LibFunc_cos: ++ case LibFunc_cosl: + return optimizeCos(CI, Builder); +- case LibFunc::sinpif: +- case LibFunc::sinpi: +- case LibFunc::cospif: +- case LibFunc::cospi: ++ case LibFunc_sinpif: ++ case LibFunc_sinpi: ++ case LibFunc_cospif: ++ case LibFunc_cospi: + return optimizeSinCosPi(CI, Builder); +- case LibFunc::powf: +- case LibFunc::pow: +- case LibFunc::powl: ++ case LibFunc_powf: ++ case LibFunc_pow: ++ case LibFunc_powl: + return optimizePow(CI, Builder); +- case LibFunc::exp2l: +- case LibFunc::exp2: +- case LibFunc::exp2f: ++ case LibFunc_exp2l: ++ case LibFunc_exp2: ++ case LibFunc_exp2f: + return optimizeExp2(CI, Builder); +- case LibFunc::fabsf: +- case LibFunc::fabs: +- case LibFunc::fabsl: ++ case LibFunc_fabsf: ++ case LibFunc_fabs: ++ case LibFunc_fabsl: + return optimizeFabs(CI, Builder); +- case LibFunc::sqrtf: +- case LibFunc::sqrt: +- case LibFunc::sqrtl: ++ case LibFunc_sqrtf: ++ case LibFunc_sqrt: ++ case LibFunc_sqrtl: + return optimizeSqrt(CI, Builder); +- case LibFunc::ffs: +- case LibFunc::ffsl: +- case LibFunc::ffsll: ++ case LibFunc_ffs: ++ case LibFunc_ffsl: ++ case LibFunc_ffsll: + return optimizeFFS(CI, Builder); +- case LibFunc::abs: +- case LibFunc::labs: +- case LibFunc::llabs: ++ case LibFunc_abs: ++ case LibFunc_labs: ++ case LibFunc_llabs: + return optimizeAbs(CI, Builder); +- case LibFunc::isdigit: ++ case LibFunc_isdigit: + return optimizeIsDigit(CI, Builder); +- case LibFunc::isascii: ++ case LibFunc_isascii: + return optimizeIsAscii(CI, Builder); +- case LibFunc::toascii: ++ case LibFunc_toascii: + return optimizeToAscii(CI, Builder); +- case LibFunc::printf: ++ case LibFunc_printf: + return optimizePrintF(CI, Builder); +- case LibFunc::sprintf: ++ case LibFunc_sprintf: + return optimizeSPrintF(CI, Builder); +- case LibFunc::fprintf: ++ case LibFunc_fprintf: + return optimizeFPrintF(CI, Builder); +- case LibFunc::fwrite: ++ case LibFunc_fwrite: + return optimizeFWrite(CI, Builder); +- case LibFunc::fputs: ++ case LibFunc_fputs: + return optimizeFPuts(CI, Builder); +- case LibFunc::log: +- case LibFunc::log10: +- case LibFunc::log1p: +- case LibFunc::log2: +- case LibFunc::logb: ++ case LibFunc_log: ++ case LibFunc_log10: ++ case LibFunc_log1p: ++ case LibFunc_log2: ++ case LibFunc_logb: + return optimizeLog(CI, Builder); +- case LibFunc::puts: ++ case LibFunc_puts: + return optimizePuts(CI, Builder); +- case LibFunc::tan: +- case LibFunc::tanf: +- case LibFunc::tanl: ++ case LibFunc_tan: ++ case LibFunc_tanf: ++ case LibFunc_tanl: + return optimizeTan(CI, Builder); +- case LibFunc::perror: ++ case LibFunc_perror: + return optimizeErrorReporting(CI, Builder); +- case LibFunc::vfprintf: +- case LibFunc::fiprintf: ++ case LibFunc_vfprintf: ++ case LibFunc_fiprintf: + return optimizeErrorReporting(CI, Builder, 0); +- case LibFunc::fputc: ++ case LibFunc_fputc: + return optimizeErrorReporting(CI, Builder, 1); +- case LibFunc::ceil: +- case LibFunc::floor: +- case LibFunc::rint: +- case LibFunc::round: +- case LibFunc::nearbyint: +- case LibFunc::trunc: ++ case LibFunc_ceil: ++ case LibFunc_floor: ++ case LibFunc_rint: ++ case LibFunc_round: ++ case LibFunc_nearbyint: ++ case LibFunc_trunc: + if (hasFloatVersion(FuncName)) + return optimizeUnaryDoubleFP(CI, Builder, false); + return nullptr; +- case LibFunc::acos: +- case LibFunc::acosh: +- case LibFunc::asin: +- case LibFunc::asinh: +- case LibFunc::atan: +- case LibFunc::atanh: +- case LibFunc::cbrt: +- case LibFunc::cosh: +- case LibFunc::exp: +- case LibFunc::exp10: +- case LibFunc::expm1: +- case LibFunc::sin: +- case LibFunc::sinh: +- case LibFunc::tanh: ++ case LibFunc_acos: ++ case LibFunc_acosh: ++ case LibFunc_asin: ++ case LibFunc_asinh: ++ case LibFunc_atan: ++ case LibFunc_atanh: ++ case LibFunc_cbrt: ++ case LibFunc_cosh: ++ case LibFunc_exp: ++ case LibFunc_exp10: ++ case LibFunc_expm1: ++ case LibFunc_sin: ++ case LibFunc_sinh: ++ case LibFunc_tanh: + if (UnsafeFPShrink && hasFloatVersion(FuncName)) + return optimizeUnaryDoubleFP(CI, Builder, true); + return nullptr; +- case LibFunc::copysign: ++ case LibFunc_copysign: + if (hasFloatVersion(FuncName)) + return optimizeBinaryDoubleFP(CI, Builder); + return nullptr; +- case LibFunc::fminf: +- case LibFunc::fmin: +- case LibFunc::fminl: +- case LibFunc::fmaxf: +- case LibFunc::fmax: +- case LibFunc::fmaxl: ++ case LibFunc_fminf: ++ case LibFunc_fmin: ++ case LibFunc_fminl: ++ case LibFunc_fmaxf: ++ case LibFunc_fmax: ++ case LibFunc_fmaxl: + return optimizeFMinFMax(CI, Builder); + default: + return nullptr; +@@ -2242,7 +2242,7 @@ Value *FortifiedLibCallSimplifier::optimizeMemSetChk(CallInst *CI, + + Value *FortifiedLibCallSimplifier::optimizeStrpCpyChk(CallInst *CI, + IRBuilder<> &B, +- LibFunc::Func Func) { ++ LibFunc Func) { + Function *Callee = CI->getCalledFunction(); + StringRef Name = Callee->getName(); + const DataLayout &DL = CI->getModule()->getDataLayout(); +@@ -2250,7 +2250,7 @@ Value *FortifiedLibCallSimplifier::optimizeStrpCpyChk(CallInst *CI, + *ObjSize = CI->getArgOperand(2); + + // __stpcpy_chk(x,x,...) -> x+strlen(x) +- if (Func == LibFunc::stpcpy_chk && !OnlyLowerUnknownSize && Dst == Src) { ++ if (Func == LibFunc_stpcpy_chk && !OnlyLowerUnknownSize && Dst == Src) { + Value *StrLen = emitStrLen(Src, B, DL, TLI); + return StrLen ? B.CreateInBoundsGEP(B.getInt8Ty(), Dst, StrLen) : nullptr; + } +@@ -2276,14 +2276,14 @@ Value *FortifiedLibCallSimplifier::optimizeStrpCpyChk(CallInst *CI, + Value *Ret = emitMemCpyChk(Dst, Src, LenV, ObjSize, B, DL, TLI); + // If the function was an __stpcpy_chk, and we were able to fold it into + // a __memcpy_chk, we still need to return the correct end pointer. +- if (Ret && Func == LibFunc::stpcpy_chk) ++ if (Ret && Func == LibFunc_stpcpy_chk) + return B.CreateGEP(B.getInt8Ty(), Dst, ConstantInt::get(SizeTTy, Len - 1)); + return Ret; + } + + Value *FortifiedLibCallSimplifier::optimizeStrpNCpyChk(CallInst *CI, + IRBuilder<> &B, +- LibFunc::Func Func) { ++ LibFunc Func) { + Function *Callee = CI->getCalledFunction(); + StringRef Name = Callee->getName(); + if (isFortifiedCallFoldable(CI, 3, 2, false)) { +@@ -2308,7 +2308,7 @@ Value *FortifiedLibCallSimplifier::optimizeCall(CallInst *CI) { + // + // PR23093. + +- LibFunc::Func Func; ++ LibFunc Func; + Function *Callee = CI->getCalledFunction(); + + SmallVector OpBundles; +@@ -2326,17 +2326,17 @@ Value *FortifiedLibCallSimplifier::optimizeCall(CallInst *CI) { + return nullptr; + + switch (Func) { +- case LibFunc::memcpy_chk: ++ case LibFunc_memcpy_chk: + return optimizeMemCpyChk(CI, Builder); +- case LibFunc::memmove_chk: ++ case LibFunc_memmove_chk: + return optimizeMemMoveChk(CI, Builder); +- case LibFunc::memset_chk: ++ case LibFunc_memset_chk: + return optimizeMemSetChk(CI, Builder); +- case LibFunc::stpcpy_chk: +- case LibFunc::strcpy_chk: ++ case LibFunc_stpcpy_chk: ++ case LibFunc_strcpy_chk: + return optimizeStrpCpyChk(CI, Builder, Func); +- case LibFunc::stpncpy_chk: +- case LibFunc::strncpy_chk: ++ case LibFunc_stpncpy_chk: ++ case LibFunc_strncpy_chk: + return optimizeStrpNCpyChk(CI, Builder, Func); + default: + break; diff --git a/deps/patches/llvm-D28476-musl-targetlibraryinfo_4.0.patch b/deps/patches/llvm-D28476-musl-targetlibraryinfo_4.0.patch new file mode 100644 index 0000000000000..96da9b768d134 --- /dev/null +++ b/deps/patches/llvm-D28476-musl-targetlibraryinfo_4.0.patch @@ -0,0 +1,4480 @@ +commit fb2d72885243ce2c1c4b7db559d1ae72fa85b792 +Author: David L. Jones +Date: Mon Jan 23 23:16:46 2017 +0000 + + [Analysis] Add LibFunc_ prefix to enums in TargetLibraryInfo. (NFC) + + Summary: + The LibFunc::Func enum holds enumerators named for libc functions. + Unfortunately, there are real situations, including libc implementations, where + function names are actually macros (musl uses "#define fopen64 fopen", for + example; any other transitively visible macro would have similar effects). + + Strictly speaking, a conforming C++ Standard Library should provide any such + macros as functions instead (via ). However, there are some "library" + functions which are not part of the standard, and thus not subject to this + rule (fopen64, for example). So, in order to be both portable and consistent, + the enum should not use the bare function names. + + The old enum naming used a namespace LibFunc and an enum Func, with bare + enumerators. This patch changes LibFunc to be an enum with enumerators prefixed + with "LibFFunc_". (Unfortunately, a scoped enum is not sufficient to override + macros.) + + There are additional changes required in clang. + + Reviewers: rsmith + + Subscribers: mehdi_amini, mzolotukhin, nemanjai, llvm-commits + + Differential Revision: https://reviews.llvm.org/D28476 + + git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@292848 91177308-0d34-0410-b5e6-96231b3b80d8 + +diff --git a/include/llvm/Analysis/TargetLibraryInfo.def b/include/llvm/Analysis/TargetLibraryInfo.def +index 5d5e5b127e6..637fc7ed30d 100644 +--- a/include/llvm/Analysis/TargetLibraryInfo.def ++++ b/include/llvm/Analysis/TargetLibraryInfo.def +@@ -20,7 +20,7 @@ + // One of TLI_DEFINE_ENUM/STRING are defined. + + #if defined(TLI_DEFINE_ENUM) +-#define TLI_DEFINE_ENUM_INTERNAL(enum_variant) enum_variant, ++#define TLI_DEFINE_ENUM_INTERNAL(enum_variant) LibFunc_##enum_variant, + #define TLI_DEFINE_STRING_INTERNAL(string_repr) + #else + #define TLI_DEFINE_ENUM_INTERNAL(enum_variant) +diff --git a/include/llvm/Analysis/TargetLibraryInfo.h b/include/llvm/Analysis/TargetLibraryInfo.h +index 8675882431d..944250cfd6a 100644 +--- a/include/llvm/Analysis/TargetLibraryInfo.h ++++ b/include/llvm/Analysis/TargetLibraryInfo.h +@@ -30,14 +30,12 @@ struct VecDesc { + unsigned VectorizationFactor; + }; + +- namespace LibFunc { +- enum Func { ++ enum LibFunc { + #define TLI_DEFINE_ENUM + #include "llvm/Analysis/TargetLibraryInfo.def" + +- NumLibFuncs +- }; +- } ++ NumLibFuncs ++ }; + + /// Implementation of the target library information. + /// +@@ -48,9 +46,9 @@ struct VecDesc { + class TargetLibraryInfoImpl { + friend class TargetLibraryInfo; + +- unsigned char AvailableArray[(LibFunc::NumLibFuncs+3)/4]; ++ unsigned char AvailableArray[(NumLibFuncs+3)/4]; + llvm::DenseMap CustomNames; +- static StringRef const StandardNames[LibFunc::NumLibFuncs]; ++ static StringRef const StandardNames[NumLibFuncs]; + bool ShouldExtI32Param, ShouldExtI32Return, ShouldSignExtI32Param; + + enum AvailabilityState { +@@ -58,11 +56,11 @@ class TargetLibraryInfoImpl { + CustomName = 1, + Unavailable = 0 // (memset to all zeros) + }; +- void setState(LibFunc::Func F, AvailabilityState State) { ++ void setState(LibFunc F, AvailabilityState State) { + AvailableArray[F/4] &= ~(3 << 2*(F&3)); + AvailableArray[F/4] |= State << 2*(F&3); + } +- AvailabilityState getState(LibFunc::Func F) const { ++ AvailabilityState getState(LibFunc F) const { + return static_cast((AvailableArray[F/4] >> 2*(F&3)) & 3); + } + +@@ -74,7 +72,7 @@ class TargetLibraryInfoImpl { + + /// Return true if the function type FTy is valid for the library function + /// F, regardless of whether the function is available. +- bool isValidProtoForLibFunc(const FunctionType &FTy, LibFunc::Func F, ++ bool isValidProtoForLibFunc(const FunctionType &FTy, LibFunc F, + const DataLayout *DL) const; + + public: +@@ -104,28 +102,28 @@ public: + /// + /// If it is one of the known library functions, return true and set F to the + /// corresponding value. +- bool getLibFunc(StringRef funcName, LibFunc::Func &F) const; ++ bool getLibFunc(StringRef funcName, LibFunc &F) const; + + /// Searches for a particular function name, also checking that its type is + /// valid for the library function matching that name. + /// + /// If it is one of the known library functions, return true and set F to the + /// corresponding value. +- bool getLibFunc(const Function &FDecl, LibFunc::Func &F) const; ++ bool getLibFunc(const Function &FDecl, LibFunc &F) const; + + /// Forces a function to be marked as unavailable. +- void setUnavailable(LibFunc::Func F) { ++ void setUnavailable(LibFunc F) { + setState(F, Unavailable); + } + + /// Forces a function to be marked as available. +- void setAvailable(LibFunc::Func F) { ++ void setAvailable(LibFunc F) { + setState(F, StandardName); + } + + /// Forces a function to be marked as available and provide an alternate name + /// that must be used. +- void setAvailableWithName(LibFunc::Func F, StringRef Name) { ++ void setAvailableWithName(LibFunc F, StringRef Name) { + if (StandardNames[F] != Name) { + setState(F, CustomName); + CustomNames[F] = Name; +@@ -225,16 +223,16 @@ public: + /// + /// If it is one of the known library functions, return true and set F to the + /// corresponding value. +- bool getLibFunc(StringRef funcName, LibFunc::Func &F) const { ++ bool getLibFunc(StringRef funcName, LibFunc &F) const { + return Impl->getLibFunc(funcName, F); + } + +- bool getLibFunc(const Function &FDecl, LibFunc::Func &F) const { ++ bool getLibFunc(const Function &FDecl, LibFunc &F) const { + return Impl->getLibFunc(FDecl, F); + } + + /// Tests whether a library function is available. +- bool has(LibFunc::Func F) const { ++ bool has(LibFunc F) const { + return Impl->getState(F) != TargetLibraryInfoImpl::Unavailable; + } + bool isFunctionVectorizable(StringRef F, unsigned VF) const { +@@ -249,37 +247,37 @@ public: + + /// Tests if the function is both available and a candidate for optimized code + /// generation. +- bool hasOptimizedCodeGen(LibFunc::Func F) const { ++ bool hasOptimizedCodeGen(LibFunc F) const { + if (Impl->getState(F) == TargetLibraryInfoImpl::Unavailable) + return false; + switch (F) { + default: break; +- case LibFunc::copysign: case LibFunc::copysignf: case LibFunc::copysignl: +- case LibFunc::fabs: case LibFunc::fabsf: case LibFunc::fabsl: +- case LibFunc::sin: case LibFunc::sinf: case LibFunc::sinl: +- case LibFunc::cos: case LibFunc::cosf: case LibFunc::cosl: +- case LibFunc::sqrt: case LibFunc::sqrtf: case LibFunc::sqrtl: +- case LibFunc::sqrt_finite: case LibFunc::sqrtf_finite: +- case LibFunc::sqrtl_finite: +- case LibFunc::fmax: case LibFunc::fmaxf: case LibFunc::fmaxl: +- case LibFunc::fmin: case LibFunc::fminf: case LibFunc::fminl: +- case LibFunc::floor: case LibFunc::floorf: case LibFunc::floorl: +- case LibFunc::nearbyint: case LibFunc::nearbyintf: case LibFunc::nearbyintl: +- case LibFunc::ceil: case LibFunc::ceilf: case LibFunc::ceill: +- case LibFunc::rint: case LibFunc::rintf: case LibFunc::rintl: +- case LibFunc::round: case LibFunc::roundf: case LibFunc::roundl: +- case LibFunc::trunc: case LibFunc::truncf: case LibFunc::truncl: +- case LibFunc::log2: case LibFunc::log2f: case LibFunc::log2l: +- case LibFunc::exp2: case LibFunc::exp2f: case LibFunc::exp2l: +- case LibFunc::memcmp: case LibFunc::strcmp: case LibFunc::strcpy: +- case LibFunc::stpcpy: case LibFunc::strlen: case LibFunc::strnlen: +- case LibFunc::memchr: case LibFunc::mempcpy: ++ case LibFunc_copysign: case LibFunc_copysignf: case LibFunc_copysignl: ++ case LibFunc_fabs: case LibFunc_fabsf: case LibFunc_fabsl: ++ case LibFunc_sin: case LibFunc_sinf: case LibFunc_sinl: ++ case LibFunc_cos: case LibFunc_cosf: case LibFunc_cosl: ++ case LibFunc_sqrt: case LibFunc_sqrtf: case LibFunc_sqrtl: ++ case LibFunc_sqrt_finite: case LibFunc_sqrtf_finite: ++ case LibFunc_sqrtl_finite: ++ case LibFunc_fmax: case LibFunc_fmaxf: case LibFunc_fmaxl: ++ case LibFunc_fmin: case LibFunc_fminf: case LibFunc_fminl: ++ case LibFunc_floor: case LibFunc_floorf: case LibFunc_floorl: ++ case LibFunc_nearbyint: case LibFunc_nearbyintf: case LibFunc_nearbyintl: ++ case LibFunc_ceil: case LibFunc_ceilf: case LibFunc_ceill: ++ case LibFunc_rint: case LibFunc_rintf: case LibFunc_rintl: ++ case LibFunc_round: case LibFunc_roundf: case LibFunc_roundl: ++ case LibFunc_trunc: case LibFunc_truncf: case LibFunc_truncl: ++ case LibFunc_log2: case LibFunc_log2f: case LibFunc_log2l: ++ case LibFunc_exp2: case LibFunc_exp2f: case LibFunc_exp2l: ++ case LibFunc_memcmp: case LibFunc_strcmp: case LibFunc_strcpy: ++ case LibFunc_stpcpy: case LibFunc_strlen: case LibFunc_strnlen: ++ case LibFunc_memchr: case LibFunc_mempcpy: + return true; + } + return false; + } + +- StringRef getName(LibFunc::Func F) const { ++ StringRef getName(LibFunc F) const { + auto State = Impl->getState(F); + if (State == TargetLibraryInfoImpl::Unavailable) + return StringRef(); +diff --git a/include/llvm/Transforms/Utils/SimplifyLibCalls.h b/include/llvm/Transforms/Utils/SimplifyLibCalls.h +index 5e217adf198..fbeea5bd95e 100644 +--- a/include/llvm/Transforms/Utils/SimplifyLibCalls.h ++++ b/include/llvm/Transforms/Utils/SimplifyLibCalls.h +@@ -56,8 +56,8 @@ private: + Value *optimizeMemSetChk(CallInst *CI, IRBuilder<> &B); + + // Str/Stp cpy are similar enough to be handled in the same functions. +- Value *optimizeStrpCpyChk(CallInst *CI, IRBuilder<> &B, LibFunc::Func Func); +- Value *optimizeStrpNCpyChk(CallInst *CI, IRBuilder<> &B, LibFunc::Func Func); ++ Value *optimizeStrpCpyChk(CallInst *CI, IRBuilder<> &B, LibFunc Func); ++ Value *optimizeStrpNCpyChk(CallInst *CI, IRBuilder<> &B, LibFunc Func); + + /// \brief Checks whether the call \p CI to a fortified libcall is foldable + /// to the non-fortified version. +diff --git a/lib/Analysis/BasicAliasAnalysis.cpp b/lib/Analysis/BasicAliasAnalysis.cpp +index c8d05794949..55f40a34839 100644 +--- a/lib/Analysis/BasicAliasAnalysis.cpp ++++ b/lib/Analysis/BasicAliasAnalysis.cpp +@@ -644,9 +644,9 @@ static bool isWriteOnlyParam(ImmutableCallSite CS, unsigned ArgIdx, + // whenever possible. + // FIXME Consider handling this in InferFunctionAttr.cpp together with other + // attributes. +- LibFunc::Func F; ++ LibFunc F; + if (CS.getCalledFunction() && TLI.getLibFunc(*CS.getCalledFunction(), F) && +- F == LibFunc::memset_pattern16 && TLI.has(F)) ++ F == LibFunc_memset_pattern16 && TLI.has(F)) + if (ArgIdx == 0) + return true; + +diff --git a/lib/Analysis/ConstantFolding.cpp b/lib/Analysis/ConstantFolding.cpp +index 73867279abe..1bd51f62a43 100644 +--- a/lib/Analysis/ConstantFolding.cpp ++++ b/lib/Analysis/ConstantFolding.cpp +@@ -1637,51 +1637,51 @@ Constant *ConstantFoldScalarCall(StringRef Name, unsigned IntrinsicID, Type *Ty, + + switch (Name[0]) { + case 'a': +- if ((Name == "acos" && TLI->has(LibFunc::acos)) || +- (Name == "acosf" && TLI->has(LibFunc::acosf))) ++ if ((Name == "acos" && TLI->has(LibFunc_acos)) || ++ (Name == "acosf" && TLI->has(LibFunc_acosf))) + return ConstantFoldFP(acos, V, Ty); +- else if ((Name == "asin" && TLI->has(LibFunc::asin)) || +- (Name == "asinf" && TLI->has(LibFunc::asinf))) ++ else if ((Name == "asin" && TLI->has(LibFunc_asin)) || ++ (Name == "asinf" && TLI->has(LibFunc_asinf))) + return ConstantFoldFP(asin, V, Ty); +- else if ((Name == "atan" && TLI->has(LibFunc::atan)) || +- (Name == "atanf" && TLI->has(LibFunc::atanf))) ++ else if ((Name == "atan" && TLI->has(LibFunc_atan)) || ++ (Name == "atanf" && TLI->has(LibFunc_atanf))) + return ConstantFoldFP(atan, V, Ty); + break; + case 'c': +- if ((Name == "ceil" && TLI->has(LibFunc::ceil)) || +- (Name == "ceilf" && TLI->has(LibFunc::ceilf))) ++ if ((Name == "ceil" && TLI->has(LibFunc_ceil)) || ++ (Name == "ceilf" && TLI->has(LibFunc_ceilf))) + return ConstantFoldFP(ceil, V, Ty); +- else if ((Name == "cos" && TLI->has(LibFunc::cos)) || +- (Name == "cosf" && TLI->has(LibFunc::cosf))) ++ else if ((Name == "cos" && TLI->has(LibFunc_cos)) || ++ (Name == "cosf" && TLI->has(LibFunc_cosf))) + return ConstantFoldFP(cos, V, Ty); +- else if ((Name == "cosh" && TLI->has(LibFunc::cosh)) || +- (Name == "coshf" && TLI->has(LibFunc::coshf))) ++ else if ((Name == "cosh" && TLI->has(LibFunc_cosh)) || ++ (Name == "coshf" && TLI->has(LibFunc_coshf))) + return ConstantFoldFP(cosh, V, Ty); + break; + case 'e': +- if ((Name == "exp" && TLI->has(LibFunc::exp)) || +- (Name == "expf" && TLI->has(LibFunc::expf))) ++ if ((Name == "exp" && TLI->has(LibFunc_exp)) || ++ (Name == "expf" && TLI->has(LibFunc_expf))) + return ConstantFoldFP(exp, V, Ty); +- if ((Name == "exp2" && TLI->has(LibFunc::exp2)) || +- (Name == "exp2f" && TLI->has(LibFunc::exp2f))) ++ if ((Name == "exp2" && TLI->has(LibFunc_exp2)) || ++ (Name == "exp2f" && TLI->has(LibFunc_exp2f))) + // Constant fold exp2(x) as pow(2,x) in case the host doesn't have a + // C99 library. + return ConstantFoldBinaryFP(pow, 2.0, V, Ty); + break; + case 'f': +- if ((Name == "fabs" && TLI->has(LibFunc::fabs)) || +- (Name == "fabsf" && TLI->has(LibFunc::fabsf))) ++ if ((Name == "fabs" && TLI->has(LibFunc_fabs)) || ++ (Name == "fabsf" && TLI->has(LibFunc_fabsf))) + return ConstantFoldFP(fabs, V, Ty); +- else if ((Name == "floor" && TLI->has(LibFunc::floor)) || +- (Name == "floorf" && TLI->has(LibFunc::floorf))) ++ else if ((Name == "floor" && TLI->has(LibFunc_floor)) || ++ (Name == "floorf" && TLI->has(LibFunc_floorf))) + return ConstantFoldFP(floor, V, Ty); + break; + case 'l': +- if ((Name == "log" && V > 0 && TLI->has(LibFunc::log)) || +- (Name == "logf" && V > 0 && TLI->has(LibFunc::logf))) ++ if ((Name == "log" && V > 0 && TLI->has(LibFunc_log)) || ++ (Name == "logf" && V > 0 && TLI->has(LibFunc_logf))) + return ConstantFoldFP(log, V, Ty); +- else if ((Name == "log10" && V > 0 && TLI->has(LibFunc::log10)) || +- (Name == "log10f" && V > 0 && TLI->has(LibFunc::log10f))) ++ else if ((Name == "log10" && V > 0 && TLI->has(LibFunc_log10)) || ++ (Name == "log10f" && V > 0 && TLI->has(LibFunc_log10f))) + return ConstantFoldFP(log10, V, Ty); + else if (IntrinsicID == Intrinsic::sqrt && + (Ty->isHalfTy() || Ty->isFloatTy() || Ty->isDoubleTy())) { +@@ -1698,26 +1698,26 @@ Constant *ConstantFoldScalarCall(StringRef Name, unsigned IntrinsicID, Type *Ty, + } + break; + case 'r': +- if ((Name == "round" && TLI->has(LibFunc::round)) || +- (Name == "roundf" && TLI->has(LibFunc::roundf))) ++ if ((Name == "round" && TLI->has(LibFunc_round)) || ++ (Name == "roundf" && TLI->has(LibFunc_roundf))) + return ConstantFoldFP(round, V, Ty); + case 's': +- if ((Name == "sin" && TLI->has(LibFunc::sin)) || +- (Name == "sinf" && TLI->has(LibFunc::sinf))) ++ if ((Name == "sin" && TLI->has(LibFunc_sin)) || ++ (Name == "sinf" && TLI->has(LibFunc_sinf))) + return ConstantFoldFP(sin, V, Ty); +- else if ((Name == "sinh" && TLI->has(LibFunc::sinh)) || +- (Name == "sinhf" && TLI->has(LibFunc::sinhf))) ++ else if ((Name == "sinh" && TLI->has(LibFunc_sinh)) || ++ (Name == "sinhf" && TLI->has(LibFunc_sinhf))) + return ConstantFoldFP(sinh, V, Ty); +- else if ((Name == "sqrt" && V >= 0 && TLI->has(LibFunc::sqrt)) || +- (Name == "sqrtf" && V >= 0 && TLI->has(LibFunc::sqrtf))) ++ else if ((Name == "sqrt" && V >= 0 && TLI->has(LibFunc_sqrt)) || ++ (Name == "sqrtf" && V >= 0 && TLI->has(LibFunc_sqrtf))) + return ConstantFoldFP(sqrt, V, Ty); + break; + case 't': +- if ((Name == "tan" && TLI->has(LibFunc::tan)) || +- (Name == "tanf" && TLI->has(LibFunc::tanf))) ++ if ((Name == "tan" && TLI->has(LibFunc_tan)) || ++ (Name == "tanf" && TLI->has(LibFunc_tanf))) + return ConstantFoldFP(tan, V, Ty); +- else if ((Name == "tanh" && TLI->has(LibFunc::tanh)) || +- (Name == "tanhf" && TLI->has(LibFunc::tanhf))) ++ else if ((Name == "tanh" && TLI->has(LibFunc_tanh)) || ++ (Name == "tanhf" && TLI->has(LibFunc_tanhf))) + return ConstantFoldFP(tanh, V, Ty); + break; + default: +@@ -1822,14 +1822,14 @@ Constant *ConstantFoldScalarCall(StringRef Name, unsigned IntrinsicID, Type *Ty, + + if (!TLI) + return nullptr; +- if ((Name == "pow" && TLI->has(LibFunc::pow)) || +- (Name == "powf" && TLI->has(LibFunc::powf))) ++ if ((Name == "pow" && TLI->has(LibFunc_pow)) || ++ (Name == "powf" && TLI->has(LibFunc_powf))) + return ConstantFoldBinaryFP(pow, Op1V, Op2V, Ty); +- if ((Name == "fmod" && TLI->has(LibFunc::fmod)) || +- (Name == "fmodf" && TLI->has(LibFunc::fmodf))) ++ if ((Name == "fmod" && TLI->has(LibFunc_fmod)) || ++ (Name == "fmodf" && TLI->has(LibFunc_fmodf))) + return ConstantFoldBinaryFP(fmod, Op1V, Op2V, Ty); +- if ((Name == "atan2" && TLI->has(LibFunc::atan2)) || +- (Name == "atan2f" && TLI->has(LibFunc::atan2f))) ++ if ((Name == "atan2" && TLI->has(LibFunc_atan2)) || ++ (Name == "atan2f" && TLI->has(LibFunc_atan2f))) + return ConstantFoldBinaryFP(atan2, Op1V, Op2V, Ty); + } else if (auto *Op2C = dyn_cast(Operands[1])) { + if (IntrinsicID == Intrinsic::powi && Ty->isHalfTy()) +@@ -2022,7 +2022,7 @@ bool llvm::isMathLibCallNoop(CallSite CS, const TargetLibraryInfo *TLI) { + if (!F) + return false; + +- LibFunc::Func Func; ++ LibFunc Func; + if (!TLI || !TLI->getLibFunc(*F, Func)) + return false; + +@@ -2030,20 +2030,20 @@ bool llvm::isMathLibCallNoop(CallSite CS, const TargetLibraryInfo *TLI) { + if (ConstantFP *OpC = dyn_cast(CS.getArgOperand(0))) { + const APFloat &Op = OpC->getValueAPF(); + switch (Func) { +- case LibFunc::logl: +- case LibFunc::log: +- case LibFunc::logf: +- case LibFunc::log2l: +- case LibFunc::log2: +- case LibFunc::log2f: +- case LibFunc::log10l: +- case LibFunc::log10: +- case LibFunc::log10f: ++ case LibFunc_logl: ++ case LibFunc_log: ++ case LibFunc_logf: ++ case LibFunc_log2l: ++ case LibFunc_log2: ++ case LibFunc_log2f: ++ case LibFunc_log10l: ++ case LibFunc_log10: ++ case LibFunc_log10f: + return Op.isNaN() || (!Op.isZero() && !Op.isNegative()); + +- case LibFunc::expl: +- case LibFunc::exp: +- case LibFunc::expf: ++ case LibFunc_expl: ++ case LibFunc_exp: ++ case LibFunc_expf: + // FIXME: These boundaries are slightly conservative. + if (OpC->getType()->isDoubleTy()) + return Op.compare(APFloat(-745.0)) != APFloat::cmpLessThan && +@@ -2053,9 +2053,9 @@ bool llvm::isMathLibCallNoop(CallSite CS, const TargetLibraryInfo *TLI) { + Op.compare(APFloat(88.0f)) != APFloat::cmpGreaterThan; + break; + +- case LibFunc::exp2l: +- case LibFunc::exp2: +- case LibFunc::exp2f: ++ case LibFunc_exp2l: ++ case LibFunc_exp2: ++ case LibFunc_exp2f: + // FIXME: These boundaries are slightly conservative. + if (OpC->getType()->isDoubleTy()) + return Op.compare(APFloat(-1074.0)) != APFloat::cmpLessThan && +@@ -2065,17 +2065,17 @@ bool llvm::isMathLibCallNoop(CallSite CS, const TargetLibraryInfo *TLI) { + Op.compare(APFloat(127.0f)) != APFloat::cmpGreaterThan; + break; + +- case LibFunc::sinl: +- case LibFunc::sin: +- case LibFunc::sinf: +- case LibFunc::cosl: +- case LibFunc::cos: +- case LibFunc::cosf: ++ case LibFunc_sinl: ++ case LibFunc_sin: ++ case LibFunc_sinf: ++ case LibFunc_cosl: ++ case LibFunc_cos: ++ case LibFunc_cosf: + return !Op.isInfinity(); + +- case LibFunc::tanl: +- case LibFunc::tan: +- case LibFunc::tanf: { ++ case LibFunc_tanl: ++ case LibFunc_tan: ++ case LibFunc_tanf: { + // FIXME: Stop using the host math library. + // FIXME: The computation isn't done in the right precision. + Type *Ty = OpC->getType(); +@@ -2086,23 +2086,23 @@ bool llvm::isMathLibCallNoop(CallSite CS, const TargetLibraryInfo *TLI) { + break; + } + +- case LibFunc::asinl: +- case LibFunc::asin: +- case LibFunc::asinf: +- case LibFunc::acosl: +- case LibFunc::acos: +- case LibFunc::acosf: ++ case LibFunc_asinl: ++ case LibFunc_asin: ++ case LibFunc_asinf: ++ case LibFunc_acosl: ++ case LibFunc_acos: ++ case LibFunc_acosf: + return Op.compare(APFloat(Op.getSemantics(), "-1")) != + APFloat::cmpLessThan && + Op.compare(APFloat(Op.getSemantics(), "1")) != + APFloat::cmpGreaterThan; + +- case LibFunc::sinh: +- case LibFunc::cosh: +- case LibFunc::sinhf: +- case LibFunc::coshf: +- case LibFunc::sinhl: +- case LibFunc::coshl: ++ case LibFunc_sinh: ++ case LibFunc_cosh: ++ case LibFunc_sinhf: ++ case LibFunc_coshf: ++ case LibFunc_sinhl: ++ case LibFunc_coshl: + // FIXME: These boundaries are slightly conservative. + if (OpC->getType()->isDoubleTy()) + return Op.compare(APFloat(-710.0)) != APFloat::cmpLessThan && +@@ -2112,9 +2112,9 @@ bool llvm::isMathLibCallNoop(CallSite CS, const TargetLibraryInfo *TLI) { + Op.compare(APFloat(89.0f)) != APFloat::cmpGreaterThan; + break; + +- case LibFunc::sqrtl: +- case LibFunc::sqrt: +- case LibFunc::sqrtf: ++ case LibFunc_sqrtl: ++ case LibFunc_sqrt: ++ case LibFunc_sqrtf: + return Op.isNaN() || Op.isZero() || !Op.isNegative(); + + // FIXME: Add more functions: sqrt_finite, atanh, expm1, log1p, +@@ -2133,9 +2133,9 @@ bool llvm::isMathLibCallNoop(CallSite CS, const TargetLibraryInfo *TLI) { + const APFloat &Op1 = Op1C->getValueAPF(); + + switch (Func) { +- case LibFunc::powl: +- case LibFunc::pow: +- case LibFunc::powf: { ++ case LibFunc_powl: ++ case LibFunc_pow: ++ case LibFunc_powf: { + // FIXME: Stop using the host math library. + // FIXME: The computation isn't done in the right precision. + Type *Ty = Op0C->getType(); +@@ -2149,9 +2149,9 @@ bool llvm::isMathLibCallNoop(CallSite CS, const TargetLibraryInfo *TLI) { + break; + } + +- case LibFunc::fmodl: +- case LibFunc::fmod: +- case LibFunc::fmodf: ++ case LibFunc_fmodl: ++ case LibFunc_fmod: ++ case LibFunc_fmodf: + return Op0.isNaN() || Op1.isNaN() || + (!Op0.isInfinity() && !Op1.isZero()); + +diff --git a/lib/Analysis/MemoryBuiltins.cpp b/lib/Analysis/MemoryBuiltins.cpp +index 2d8274040d3..e9d27b5e367 100644 +--- a/lib/Analysis/MemoryBuiltins.cpp ++++ b/lib/Analysis/MemoryBuiltins.cpp +@@ -50,30 +50,30 @@ struct AllocFnsTy { + + // FIXME: certain users need more information. E.g., SimplifyLibCalls needs to + // know which functions are nounwind, noalias, nocapture parameters, etc. +-static const std::pair AllocationFnData[] = { +- {LibFunc::malloc, {MallocLike, 1, 0, -1}}, +- {LibFunc::valloc, {MallocLike, 1, 0, -1}}, +- {LibFunc::Znwj, {OpNewLike, 1, 0, -1}}, // new(unsigned int) +- {LibFunc::ZnwjRKSt9nothrow_t, {MallocLike, 2, 0, -1}}, // new(unsigned int, nothrow) +- {LibFunc::Znwm, {OpNewLike, 1, 0, -1}}, // new(unsigned long) +- {LibFunc::ZnwmRKSt9nothrow_t, {MallocLike, 2, 0, -1}}, // new(unsigned long, nothrow) +- {LibFunc::Znaj, {OpNewLike, 1, 0, -1}}, // new[](unsigned int) +- {LibFunc::ZnajRKSt9nothrow_t, {MallocLike, 2, 0, -1}}, // new[](unsigned int, nothrow) +- {LibFunc::Znam, {OpNewLike, 1, 0, -1}}, // new[](unsigned long) +- {LibFunc::ZnamRKSt9nothrow_t, {MallocLike, 2, 0, -1}}, // new[](unsigned long, nothrow) +- {LibFunc::msvc_new_int, {OpNewLike, 1, 0, -1}}, // new(unsigned int) +- {LibFunc::msvc_new_int_nothrow, {MallocLike, 2, 0, -1}}, // new(unsigned int, nothrow) +- {LibFunc::msvc_new_longlong, {OpNewLike, 1, 0, -1}}, // new(unsigned long long) +- {LibFunc::msvc_new_longlong_nothrow, {MallocLike, 2, 0, -1}}, // new(unsigned long long, nothrow) +- {LibFunc::msvc_new_array_int, {OpNewLike, 1, 0, -1}}, // new[](unsigned int) +- {LibFunc::msvc_new_array_int_nothrow, {MallocLike, 2, 0, -1}}, // new[](unsigned int, nothrow) +- {LibFunc::msvc_new_array_longlong, {OpNewLike, 1, 0, -1}}, // new[](unsigned long long) +- {LibFunc::msvc_new_array_longlong_nothrow, {MallocLike, 2, 0, -1}}, // new[](unsigned long long, nothrow) +- {LibFunc::calloc, {CallocLike, 2, 0, 1}}, +- {LibFunc::realloc, {ReallocLike, 2, 1, -1}}, +- {LibFunc::reallocf, {ReallocLike, 2, 1, -1}}, +- {LibFunc::strdup, {StrDupLike, 1, -1, -1}}, +- {LibFunc::strndup, {StrDupLike, 2, 1, -1}} ++static const std::pair AllocationFnData[] = { ++ {LibFunc_malloc, {MallocLike, 1, 0, -1}}, ++ {LibFunc_valloc, {MallocLike, 1, 0, -1}}, ++ {LibFunc_Znwj, {OpNewLike, 1, 0, -1}}, // new(unsigned int) ++ {LibFunc_ZnwjRKSt9nothrow_t, {MallocLike, 2, 0, -1}}, // new(unsigned int, nothrow) ++ {LibFunc_Znwm, {OpNewLike, 1, 0, -1}}, // new(unsigned long) ++ {LibFunc_ZnwmRKSt9nothrow_t, {MallocLike, 2, 0, -1}}, // new(unsigned long, nothrow) ++ {LibFunc_Znaj, {OpNewLike, 1, 0, -1}}, // new[](unsigned int) ++ {LibFunc_ZnajRKSt9nothrow_t, {MallocLike, 2, 0, -1}}, // new[](unsigned int, nothrow) ++ {LibFunc_Znam, {OpNewLike, 1, 0, -1}}, // new[](unsigned long) ++ {LibFunc_ZnamRKSt9nothrow_t, {MallocLike, 2, 0, -1}}, // new[](unsigned long, nothrow) ++ {LibFunc_msvc_new_int, {OpNewLike, 1, 0, -1}}, // new(unsigned int) ++ {LibFunc_msvc_new_int_nothrow, {MallocLike, 2, 0, -1}}, // new(unsigned int, nothrow) ++ {LibFunc_msvc_new_longlong, {OpNewLike, 1, 0, -1}}, // new(unsigned long long) ++ {LibFunc_msvc_new_longlong_nothrow, {MallocLike, 2, 0, -1}}, // new(unsigned long long, nothrow) ++ {LibFunc_msvc_new_array_int, {OpNewLike, 1, 0, -1}}, // new[](unsigned int) ++ {LibFunc_msvc_new_array_int_nothrow, {MallocLike, 2, 0, -1}}, // new[](unsigned int, nothrow) ++ {LibFunc_msvc_new_array_longlong, {OpNewLike, 1, 0, -1}}, // new[](unsigned long long) ++ {LibFunc_msvc_new_array_longlong_nothrow, {MallocLike, 2, 0, -1}}, // new[](unsigned long long, nothrow) ++ {LibFunc_calloc, {CallocLike, 2, 0, 1}}, ++ {LibFunc_realloc, {ReallocLike, 2, 1, -1}}, ++ {LibFunc_reallocf, {ReallocLike, 2, 1, -1}}, ++ {LibFunc_strdup, {StrDupLike, 1, -1, -1}}, ++ {LibFunc_strndup, {StrDupLike, 2, 1, -1}} + // TODO: Handle "int posix_memalign(void **, size_t, size_t)" + }; + +@@ -106,12 +106,12 @@ getAllocationDataForFunction(const Function *Callee, AllocType AllocTy, + const TargetLibraryInfo *TLI) { + // Make sure that the function is available. + StringRef FnName = Callee->getName(); +- LibFunc::Func TLIFn; ++ LibFunc TLIFn; + if (!TLI || !TLI->getLibFunc(FnName, TLIFn) || !TLI->has(TLIFn)) + return None; + + const auto *Iter = find_if( +- AllocationFnData, [TLIFn](const std::pair &P) { ++ AllocationFnData, [TLIFn](const std::pair &P) { + return P.first == TLIFn; + }); + +@@ -333,33 +333,33 @@ const CallInst *llvm::isFreeCall(const Value *I, const TargetLibraryInfo *TLI) { + return nullptr; + + StringRef FnName = Callee->getName(); +- LibFunc::Func TLIFn; ++ LibFunc TLIFn; + if (!TLI || !TLI->getLibFunc(FnName, TLIFn) || !TLI->has(TLIFn)) + return nullptr; + + unsigned ExpectedNumParams; +- if (TLIFn == LibFunc::free || +- TLIFn == LibFunc::ZdlPv || // operator delete(void*) +- TLIFn == LibFunc::ZdaPv || // operator delete[](void*) +- TLIFn == LibFunc::msvc_delete_ptr32 || // operator delete(void*) +- TLIFn == LibFunc::msvc_delete_ptr64 || // operator delete(void*) +- TLIFn == LibFunc::msvc_delete_array_ptr32 || // operator delete[](void*) +- TLIFn == LibFunc::msvc_delete_array_ptr64) // operator delete[](void*) ++ if (TLIFn == LibFunc_free || ++ TLIFn == LibFunc_ZdlPv || // operator delete(void*) ++ TLIFn == LibFunc_ZdaPv || // operator delete[](void*) ++ TLIFn == LibFunc_msvc_delete_ptr32 || // operator delete(void*) ++ TLIFn == LibFunc_msvc_delete_ptr64 || // operator delete(void*) ++ TLIFn == LibFunc_msvc_delete_array_ptr32 || // operator delete[](void*) ++ TLIFn == LibFunc_msvc_delete_array_ptr64) // operator delete[](void*) + ExpectedNumParams = 1; +- else if (TLIFn == LibFunc::ZdlPvj || // delete(void*, uint) +- TLIFn == LibFunc::ZdlPvm || // delete(void*, ulong) +- TLIFn == LibFunc::ZdlPvRKSt9nothrow_t || // delete(void*, nothrow) +- TLIFn == LibFunc::ZdaPvj || // delete[](void*, uint) +- TLIFn == LibFunc::ZdaPvm || // delete[](void*, ulong) +- TLIFn == LibFunc::ZdaPvRKSt9nothrow_t || // delete[](void*, nothrow) +- TLIFn == LibFunc::msvc_delete_ptr32_int || // delete(void*, uint) +- TLIFn == LibFunc::msvc_delete_ptr64_longlong || // delete(void*, ulonglong) +- TLIFn == LibFunc::msvc_delete_ptr32_nothrow || // delete(void*, nothrow) +- TLIFn == LibFunc::msvc_delete_ptr64_nothrow || // delete(void*, nothrow) +- TLIFn == LibFunc::msvc_delete_array_ptr32_int || // delete[](void*, uint) +- TLIFn == LibFunc::msvc_delete_array_ptr64_longlong || // delete[](void*, ulonglong) +- TLIFn == LibFunc::msvc_delete_array_ptr32_nothrow || // delete[](void*, nothrow) +- TLIFn == LibFunc::msvc_delete_array_ptr64_nothrow) // delete[](void*, nothrow) ++ else if (TLIFn == LibFunc_ZdlPvj || // delete(void*, uint) ++ TLIFn == LibFunc_ZdlPvm || // delete(void*, ulong) ++ TLIFn == LibFunc_ZdlPvRKSt9nothrow_t || // delete(void*, nothrow) ++ TLIFn == LibFunc_ZdaPvj || // delete[](void*, uint) ++ TLIFn == LibFunc_ZdaPvm || // delete[](void*, ulong) ++ TLIFn == LibFunc_ZdaPvRKSt9nothrow_t || // delete[](void*, nothrow) ++ TLIFn == LibFunc_msvc_delete_ptr32_int || // delete(void*, uint) ++ TLIFn == LibFunc_msvc_delete_ptr64_longlong || // delete(void*, ulonglong) ++ TLIFn == LibFunc_msvc_delete_ptr32_nothrow || // delete(void*, nothrow) ++ TLIFn == LibFunc_msvc_delete_ptr64_nothrow || // delete(void*, nothrow) ++ TLIFn == LibFunc_msvc_delete_array_ptr32_int || // delete[](void*, uint) ++ TLIFn == LibFunc_msvc_delete_array_ptr64_longlong || // delete[](void*, ulonglong) ++ TLIFn == LibFunc_msvc_delete_array_ptr32_nothrow || // delete[](void*, nothrow) ++ TLIFn == LibFunc_msvc_delete_array_ptr64_nothrow) // delete[](void*, nothrow) + ExpectedNumParams = 2; + else + return nullptr; +diff --git a/lib/Analysis/MemoryLocation.cpp b/lib/Analysis/MemoryLocation.cpp +index a0ae72f1415..9db6c499129 100644 +--- a/lib/Analysis/MemoryLocation.cpp ++++ b/lib/Analysis/MemoryLocation.cpp +@@ -142,9 +142,9 @@ MemoryLocation MemoryLocation::getForArgument(ImmutableCallSite CS, + // for memcpy/memset. This is particularly important because the + // LoopIdiomRecognizer likes to turn loops into calls to memset_pattern16 + // whenever possible. +- LibFunc::Func F; ++ LibFunc F; + if (CS.getCalledFunction() && TLI.getLibFunc(*CS.getCalledFunction(), F) && +- F == LibFunc::memset_pattern16 && TLI.has(F)) { ++ F == LibFunc_memset_pattern16 && TLI.has(F)) { + assert((ArgIdx == 0 || ArgIdx == 1) && + "Invalid argument index for memset_pattern16"); + if (ArgIdx == 1) +diff --git a/lib/Analysis/TargetLibraryInfo.cpp b/lib/Analysis/TargetLibraryInfo.cpp +index 450901aca7d..775abfd18c1 100644 +--- a/lib/Analysis/TargetLibraryInfo.cpp ++++ b/lib/Analysis/TargetLibraryInfo.cpp +@@ -82,24 +82,24 @@ static void initialize(TargetLibraryInfoImpl &TLI, const Triple &T, + + if (T.getArch() == Triple::r600 || + T.getArch() == Triple::amdgcn) { +- TLI.setUnavailable(LibFunc::ldexp); +- TLI.setUnavailable(LibFunc::ldexpf); +- TLI.setUnavailable(LibFunc::ldexpl); +- TLI.setUnavailable(LibFunc::exp10); +- TLI.setUnavailable(LibFunc::exp10f); +- TLI.setUnavailable(LibFunc::exp10l); +- TLI.setUnavailable(LibFunc::log10); +- TLI.setUnavailable(LibFunc::log10f); +- TLI.setUnavailable(LibFunc::log10l); ++ TLI.setUnavailable(LibFunc_ldexp); ++ TLI.setUnavailable(LibFunc_ldexpf); ++ TLI.setUnavailable(LibFunc_ldexpl); ++ TLI.setUnavailable(LibFunc_exp10); ++ TLI.setUnavailable(LibFunc_exp10f); ++ TLI.setUnavailable(LibFunc_exp10l); ++ TLI.setUnavailable(LibFunc_log10); ++ TLI.setUnavailable(LibFunc_log10f); ++ TLI.setUnavailable(LibFunc_log10l); + } + + // There are no library implementations of mempcy and memset for AMD gpus and + // these can be difficult to lower in the backend. + if (T.getArch() == Triple::r600 || + T.getArch() == Triple::amdgcn) { +- TLI.setUnavailable(LibFunc::memcpy); +- TLI.setUnavailable(LibFunc::memset); +- TLI.setUnavailable(LibFunc::memset_pattern16); ++ TLI.setUnavailable(LibFunc_memcpy); ++ TLI.setUnavailable(LibFunc_memset); ++ TLI.setUnavailable(LibFunc_memset_pattern16); + return; + } + +@@ -107,21 +107,21 @@ static void initialize(TargetLibraryInfoImpl &TLI, const Triple &T, + // All versions of watchOS support it. + if (T.isMacOSX()) { + if (T.isMacOSXVersionLT(10, 5)) +- TLI.setUnavailable(LibFunc::memset_pattern16); ++ TLI.setUnavailable(LibFunc_memset_pattern16); + } else if (T.isiOS()) { + if (T.isOSVersionLT(3, 0)) +- TLI.setUnavailable(LibFunc::memset_pattern16); ++ TLI.setUnavailable(LibFunc_memset_pattern16); + } else if (!T.isWatchOS()) { +- TLI.setUnavailable(LibFunc::memset_pattern16); ++ TLI.setUnavailable(LibFunc_memset_pattern16); + } + + if (!hasSinCosPiStret(T)) { +- TLI.setUnavailable(LibFunc::sinpi); +- TLI.setUnavailable(LibFunc::sinpif); +- TLI.setUnavailable(LibFunc::cospi); +- TLI.setUnavailable(LibFunc::cospif); +- TLI.setUnavailable(LibFunc::sincospi_stret); +- TLI.setUnavailable(LibFunc::sincospif_stret); ++ TLI.setUnavailable(LibFunc_sinpi); ++ TLI.setUnavailable(LibFunc_sinpif); ++ TLI.setUnavailable(LibFunc_cospi); ++ TLI.setUnavailable(LibFunc_cospif); ++ TLI.setUnavailable(LibFunc_sincospi_stret); ++ TLI.setUnavailable(LibFunc_sincospif_stret); + } + + if (T.isMacOSX() && T.getArch() == Triple::x86 && +@@ -131,179 +131,179 @@ static void initialize(TargetLibraryInfoImpl &TLI, const Triple &T, + // has a $UNIX2003 suffix. The two implementations are identical except + // for the return value in some edge cases. However, we don't want to + // generate code that depends on the old symbols. +- TLI.setAvailableWithName(LibFunc::fwrite, "fwrite$UNIX2003"); +- TLI.setAvailableWithName(LibFunc::fputs, "fputs$UNIX2003"); ++ TLI.setAvailableWithName(LibFunc_fwrite, "fwrite$UNIX2003"); ++ TLI.setAvailableWithName(LibFunc_fputs, "fputs$UNIX2003"); + } + + // iprintf and friends are only available on XCore and TCE. + if (T.getArch() != Triple::xcore && T.getArch() != Triple::tce) { +- TLI.setUnavailable(LibFunc::iprintf); +- TLI.setUnavailable(LibFunc::siprintf); +- TLI.setUnavailable(LibFunc::fiprintf); ++ TLI.setUnavailable(LibFunc_iprintf); ++ TLI.setUnavailable(LibFunc_siprintf); ++ TLI.setUnavailable(LibFunc_fiprintf); + } + + if (T.isOSWindows() && !T.isOSCygMing()) { + // Win32 does not support long double +- TLI.setUnavailable(LibFunc::acosl); +- TLI.setUnavailable(LibFunc::asinl); +- TLI.setUnavailable(LibFunc::atanl); +- TLI.setUnavailable(LibFunc::atan2l); +- TLI.setUnavailable(LibFunc::ceill); +- TLI.setUnavailable(LibFunc::copysignl); +- TLI.setUnavailable(LibFunc::cosl); +- TLI.setUnavailable(LibFunc::coshl); +- TLI.setUnavailable(LibFunc::expl); +- TLI.setUnavailable(LibFunc::fabsf); // Win32 and Win64 both lack fabsf +- TLI.setUnavailable(LibFunc::fabsl); +- TLI.setUnavailable(LibFunc::floorl); +- TLI.setUnavailable(LibFunc::fmaxl); +- TLI.setUnavailable(LibFunc::fminl); +- TLI.setUnavailable(LibFunc::fmodl); +- TLI.setUnavailable(LibFunc::frexpl); +- TLI.setUnavailable(LibFunc::ldexpf); +- TLI.setUnavailable(LibFunc::ldexpl); +- TLI.setUnavailable(LibFunc::logl); +- TLI.setUnavailable(LibFunc::modfl); +- TLI.setUnavailable(LibFunc::powl); +- TLI.setUnavailable(LibFunc::sinl); +- TLI.setUnavailable(LibFunc::sinhl); +- TLI.setUnavailable(LibFunc::sqrtl); +- TLI.setUnavailable(LibFunc::tanl); +- TLI.setUnavailable(LibFunc::tanhl); ++ TLI.setUnavailable(LibFunc_acosl); ++ TLI.setUnavailable(LibFunc_asinl); ++ TLI.setUnavailable(LibFunc_atanl); ++ TLI.setUnavailable(LibFunc_atan2l); ++ TLI.setUnavailable(LibFunc_ceill); ++ TLI.setUnavailable(LibFunc_copysignl); ++ TLI.setUnavailable(LibFunc_cosl); ++ TLI.setUnavailable(LibFunc_coshl); ++ TLI.setUnavailable(LibFunc_expl); ++ TLI.setUnavailable(LibFunc_fabsf); // Win32 and Win64 both lack fabsf ++ TLI.setUnavailable(LibFunc_fabsl); ++ TLI.setUnavailable(LibFunc_floorl); ++ TLI.setUnavailable(LibFunc_fmaxl); ++ TLI.setUnavailable(LibFunc_fminl); ++ TLI.setUnavailable(LibFunc_fmodl); ++ TLI.setUnavailable(LibFunc_frexpl); ++ TLI.setUnavailable(LibFunc_ldexpf); ++ TLI.setUnavailable(LibFunc_ldexpl); ++ TLI.setUnavailable(LibFunc_logl); ++ TLI.setUnavailable(LibFunc_modfl); ++ TLI.setUnavailable(LibFunc_powl); ++ TLI.setUnavailable(LibFunc_sinl); ++ TLI.setUnavailable(LibFunc_sinhl); ++ TLI.setUnavailable(LibFunc_sqrtl); ++ TLI.setUnavailable(LibFunc_tanl); ++ TLI.setUnavailable(LibFunc_tanhl); + + // Win32 only has C89 math +- TLI.setUnavailable(LibFunc::acosh); +- TLI.setUnavailable(LibFunc::acoshf); +- TLI.setUnavailable(LibFunc::acoshl); +- TLI.setUnavailable(LibFunc::asinh); +- TLI.setUnavailable(LibFunc::asinhf); +- TLI.setUnavailable(LibFunc::asinhl); +- TLI.setUnavailable(LibFunc::atanh); +- TLI.setUnavailable(LibFunc::atanhf); +- TLI.setUnavailable(LibFunc::atanhl); +- TLI.setUnavailable(LibFunc::cbrt); +- TLI.setUnavailable(LibFunc::cbrtf); +- TLI.setUnavailable(LibFunc::cbrtl); +- TLI.setUnavailable(LibFunc::exp2); +- TLI.setUnavailable(LibFunc::exp2f); +- TLI.setUnavailable(LibFunc::exp2l); +- TLI.setUnavailable(LibFunc::expm1); +- TLI.setUnavailable(LibFunc::expm1f); +- TLI.setUnavailable(LibFunc::expm1l); +- TLI.setUnavailable(LibFunc::log2); +- TLI.setUnavailable(LibFunc::log2f); +- TLI.setUnavailable(LibFunc::log2l); +- TLI.setUnavailable(LibFunc::log1p); +- TLI.setUnavailable(LibFunc::log1pf); +- TLI.setUnavailable(LibFunc::log1pl); +- TLI.setUnavailable(LibFunc::logb); +- TLI.setUnavailable(LibFunc::logbf); +- TLI.setUnavailable(LibFunc::logbl); +- TLI.setUnavailable(LibFunc::nearbyint); +- TLI.setUnavailable(LibFunc::nearbyintf); +- TLI.setUnavailable(LibFunc::nearbyintl); +- TLI.setUnavailable(LibFunc::rint); +- TLI.setUnavailable(LibFunc::rintf); +- TLI.setUnavailable(LibFunc::rintl); +- TLI.setUnavailable(LibFunc::round); +- TLI.setUnavailable(LibFunc::roundf); +- TLI.setUnavailable(LibFunc::roundl); +- TLI.setUnavailable(LibFunc::trunc); +- TLI.setUnavailable(LibFunc::truncf); +- TLI.setUnavailable(LibFunc::truncl); ++ TLI.setUnavailable(LibFunc_acosh); ++ TLI.setUnavailable(LibFunc_acoshf); ++ TLI.setUnavailable(LibFunc_acoshl); ++ TLI.setUnavailable(LibFunc_asinh); ++ TLI.setUnavailable(LibFunc_asinhf); ++ TLI.setUnavailable(LibFunc_asinhl); ++ TLI.setUnavailable(LibFunc_atanh); ++ TLI.setUnavailable(LibFunc_atanhf); ++ TLI.setUnavailable(LibFunc_atanhl); ++ TLI.setUnavailable(LibFunc_cbrt); ++ TLI.setUnavailable(LibFunc_cbrtf); ++ TLI.setUnavailable(LibFunc_cbrtl); ++ TLI.setUnavailable(LibFunc_exp2); ++ TLI.setUnavailable(LibFunc_exp2f); ++ TLI.setUnavailable(LibFunc_exp2l); ++ TLI.setUnavailable(LibFunc_expm1); ++ TLI.setUnavailable(LibFunc_expm1f); ++ TLI.setUnavailable(LibFunc_expm1l); ++ TLI.setUnavailable(LibFunc_log2); ++ TLI.setUnavailable(LibFunc_log2f); ++ TLI.setUnavailable(LibFunc_log2l); ++ TLI.setUnavailable(LibFunc_log1p); ++ TLI.setUnavailable(LibFunc_log1pf); ++ TLI.setUnavailable(LibFunc_log1pl); ++ TLI.setUnavailable(LibFunc_logb); ++ TLI.setUnavailable(LibFunc_logbf); ++ TLI.setUnavailable(LibFunc_logbl); ++ TLI.setUnavailable(LibFunc_nearbyint); ++ TLI.setUnavailable(LibFunc_nearbyintf); ++ TLI.setUnavailable(LibFunc_nearbyintl); ++ TLI.setUnavailable(LibFunc_rint); ++ TLI.setUnavailable(LibFunc_rintf); ++ TLI.setUnavailable(LibFunc_rintl); ++ TLI.setUnavailable(LibFunc_round); ++ TLI.setUnavailable(LibFunc_roundf); ++ TLI.setUnavailable(LibFunc_roundl); ++ TLI.setUnavailable(LibFunc_trunc); ++ TLI.setUnavailable(LibFunc_truncf); ++ TLI.setUnavailable(LibFunc_truncl); + + // Win32 provides some C99 math with mangled names +- TLI.setAvailableWithName(LibFunc::copysign, "_copysign"); ++ TLI.setAvailableWithName(LibFunc_copysign, "_copysign"); + + if (T.getArch() == Triple::x86) { + // Win32 on x86 implements single-precision math functions as macros +- TLI.setUnavailable(LibFunc::acosf); +- TLI.setUnavailable(LibFunc::asinf); +- TLI.setUnavailable(LibFunc::atanf); +- TLI.setUnavailable(LibFunc::atan2f); +- TLI.setUnavailable(LibFunc::ceilf); +- TLI.setUnavailable(LibFunc::copysignf); +- TLI.setUnavailable(LibFunc::cosf); +- TLI.setUnavailable(LibFunc::coshf); +- TLI.setUnavailable(LibFunc::expf); +- TLI.setUnavailable(LibFunc::floorf); +- TLI.setUnavailable(LibFunc::fminf); +- TLI.setUnavailable(LibFunc::fmaxf); +- TLI.setUnavailable(LibFunc::fmodf); +- TLI.setUnavailable(LibFunc::logf); +- TLI.setUnavailable(LibFunc::log10f); +- TLI.setUnavailable(LibFunc::modff); +- TLI.setUnavailable(LibFunc::powf); +- TLI.setUnavailable(LibFunc::sinf); +- TLI.setUnavailable(LibFunc::sinhf); +- TLI.setUnavailable(LibFunc::sqrtf); +- TLI.setUnavailable(LibFunc::tanf); +- TLI.setUnavailable(LibFunc::tanhf); ++ TLI.setUnavailable(LibFunc_acosf); ++ TLI.setUnavailable(LibFunc_asinf); ++ TLI.setUnavailable(LibFunc_atanf); ++ TLI.setUnavailable(LibFunc_atan2f); ++ TLI.setUnavailable(LibFunc_ceilf); ++ TLI.setUnavailable(LibFunc_copysignf); ++ TLI.setUnavailable(LibFunc_cosf); ++ TLI.setUnavailable(LibFunc_coshf); ++ TLI.setUnavailable(LibFunc_expf); ++ TLI.setUnavailable(LibFunc_floorf); ++ TLI.setUnavailable(LibFunc_fminf); ++ TLI.setUnavailable(LibFunc_fmaxf); ++ TLI.setUnavailable(LibFunc_fmodf); ++ TLI.setUnavailable(LibFunc_logf); ++ TLI.setUnavailable(LibFunc_log10f); ++ TLI.setUnavailable(LibFunc_modff); ++ TLI.setUnavailable(LibFunc_powf); ++ TLI.setUnavailable(LibFunc_sinf); ++ TLI.setUnavailable(LibFunc_sinhf); ++ TLI.setUnavailable(LibFunc_sqrtf); ++ TLI.setUnavailable(LibFunc_tanf); ++ TLI.setUnavailable(LibFunc_tanhf); + } + + // Win32 does *not* provide provide these functions, but they are + // generally available on POSIX-compliant systems: +- TLI.setUnavailable(LibFunc::access); +- TLI.setUnavailable(LibFunc::bcmp); +- TLI.setUnavailable(LibFunc::bcopy); +- TLI.setUnavailable(LibFunc::bzero); +- TLI.setUnavailable(LibFunc::chmod); +- TLI.setUnavailable(LibFunc::chown); +- TLI.setUnavailable(LibFunc::closedir); +- TLI.setUnavailable(LibFunc::ctermid); +- TLI.setUnavailable(LibFunc::fdopen); +- TLI.setUnavailable(LibFunc::ffs); +- TLI.setUnavailable(LibFunc::fileno); +- TLI.setUnavailable(LibFunc::flockfile); +- TLI.setUnavailable(LibFunc::fseeko); +- TLI.setUnavailable(LibFunc::fstat); +- TLI.setUnavailable(LibFunc::fstatvfs); +- TLI.setUnavailable(LibFunc::ftello); +- TLI.setUnavailable(LibFunc::ftrylockfile); +- TLI.setUnavailable(LibFunc::funlockfile); +- TLI.setUnavailable(LibFunc::getc_unlocked); +- TLI.setUnavailable(LibFunc::getitimer); +- TLI.setUnavailable(LibFunc::getlogin_r); +- TLI.setUnavailable(LibFunc::getpwnam); +- TLI.setUnavailable(LibFunc::gettimeofday); +- TLI.setUnavailable(LibFunc::htonl); +- TLI.setUnavailable(LibFunc::htons); +- TLI.setUnavailable(LibFunc::lchown); +- TLI.setUnavailable(LibFunc::lstat); +- TLI.setUnavailable(LibFunc::memccpy); +- TLI.setUnavailable(LibFunc::mkdir); +- TLI.setUnavailable(LibFunc::ntohl); +- TLI.setUnavailable(LibFunc::ntohs); +- TLI.setUnavailable(LibFunc::open); +- TLI.setUnavailable(LibFunc::opendir); +- TLI.setUnavailable(LibFunc::pclose); +- TLI.setUnavailable(LibFunc::popen); +- TLI.setUnavailable(LibFunc::pread); +- TLI.setUnavailable(LibFunc::pwrite); +- TLI.setUnavailable(LibFunc::read); +- TLI.setUnavailable(LibFunc::readlink); +- TLI.setUnavailable(LibFunc::realpath); +- TLI.setUnavailable(LibFunc::rmdir); +- TLI.setUnavailable(LibFunc::setitimer); +- TLI.setUnavailable(LibFunc::stat); +- TLI.setUnavailable(LibFunc::statvfs); +- TLI.setUnavailable(LibFunc::stpcpy); +- TLI.setUnavailable(LibFunc::stpncpy); +- TLI.setUnavailable(LibFunc::strcasecmp); +- TLI.setUnavailable(LibFunc::strncasecmp); +- TLI.setUnavailable(LibFunc::times); +- TLI.setUnavailable(LibFunc::uname); +- TLI.setUnavailable(LibFunc::unlink); +- TLI.setUnavailable(LibFunc::unsetenv); +- TLI.setUnavailable(LibFunc::utime); +- TLI.setUnavailable(LibFunc::utimes); +- TLI.setUnavailable(LibFunc::write); ++ TLI.setUnavailable(LibFunc_access); ++ TLI.setUnavailable(LibFunc_bcmp); ++ TLI.setUnavailable(LibFunc_bcopy); ++ TLI.setUnavailable(LibFunc_bzero); ++ TLI.setUnavailable(LibFunc_chmod); ++ TLI.setUnavailable(LibFunc_chown); ++ TLI.setUnavailable(LibFunc_closedir); ++ TLI.setUnavailable(LibFunc_ctermid); ++ TLI.setUnavailable(LibFunc_fdopen); ++ TLI.setUnavailable(LibFunc_ffs); ++ TLI.setUnavailable(LibFunc_fileno); ++ TLI.setUnavailable(LibFunc_flockfile); ++ TLI.setUnavailable(LibFunc_fseeko); ++ TLI.setUnavailable(LibFunc_fstat); ++ TLI.setUnavailable(LibFunc_fstatvfs); ++ TLI.setUnavailable(LibFunc_ftello); ++ TLI.setUnavailable(LibFunc_ftrylockfile); ++ TLI.setUnavailable(LibFunc_funlockfile); ++ TLI.setUnavailable(LibFunc_getc_unlocked); ++ TLI.setUnavailable(LibFunc_getitimer); ++ TLI.setUnavailable(LibFunc_getlogin_r); ++ TLI.setUnavailable(LibFunc_getpwnam); ++ TLI.setUnavailable(LibFunc_gettimeofday); ++ TLI.setUnavailable(LibFunc_htonl); ++ TLI.setUnavailable(LibFunc_htons); ++ TLI.setUnavailable(LibFunc_lchown); ++ TLI.setUnavailable(LibFunc_lstat); ++ TLI.setUnavailable(LibFunc_memccpy); ++ TLI.setUnavailable(LibFunc_mkdir); ++ TLI.setUnavailable(LibFunc_ntohl); ++ TLI.setUnavailable(LibFunc_ntohs); ++ TLI.setUnavailable(LibFunc_open); ++ TLI.setUnavailable(LibFunc_opendir); ++ TLI.setUnavailable(LibFunc_pclose); ++ TLI.setUnavailable(LibFunc_popen); ++ TLI.setUnavailable(LibFunc_pread); ++ TLI.setUnavailable(LibFunc_pwrite); ++ TLI.setUnavailable(LibFunc_read); ++ TLI.setUnavailable(LibFunc_readlink); ++ TLI.setUnavailable(LibFunc_realpath); ++ TLI.setUnavailable(LibFunc_rmdir); ++ TLI.setUnavailable(LibFunc_setitimer); ++ TLI.setUnavailable(LibFunc_stat); ++ TLI.setUnavailable(LibFunc_statvfs); ++ TLI.setUnavailable(LibFunc_stpcpy); ++ TLI.setUnavailable(LibFunc_stpncpy); ++ TLI.setUnavailable(LibFunc_strcasecmp); ++ TLI.setUnavailable(LibFunc_strncasecmp); ++ TLI.setUnavailable(LibFunc_times); ++ TLI.setUnavailable(LibFunc_uname); ++ TLI.setUnavailable(LibFunc_unlink); ++ TLI.setUnavailable(LibFunc_unsetenv); ++ TLI.setUnavailable(LibFunc_utime); ++ TLI.setUnavailable(LibFunc_utimes); ++ TLI.setUnavailable(LibFunc_write); + + // Win32 does *not* provide provide these functions, but they are + // specified by C99: +- TLI.setUnavailable(LibFunc::atoll); +- TLI.setUnavailable(LibFunc::frexpf); +- TLI.setUnavailable(LibFunc::llabs); ++ TLI.setUnavailable(LibFunc_atoll); ++ TLI.setUnavailable(LibFunc_frexpf); ++ TLI.setUnavailable(LibFunc_llabs); + } + + switch (T.getOS()) { +@@ -311,28 +311,28 @@ static void initialize(TargetLibraryInfoImpl &TLI, const Triple &T, + // exp10 and exp10f are not available on OS X until 10.9 and iOS until 7.0 + // and their names are __exp10 and __exp10f. exp10l is not available on + // OS X or iOS. +- TLI.setUnavailable(LibFunc::exp10l); ++ TLI.setUnavailable(LibFunc_exp10l); + if (T.isMacOSXVersionLT(10, 9)) { +- TLI.setUnavailable(LibFunc::exp10); +- TLI.setUnavailable(LibFunc::exp10f); ++ TLI.setUnavailable(LibFunc_exp10); ++ TLI.setUnavailable(LibFunc_exp10f); + } else { +- TLI.setAvailableWithName(LibFunc::exp10, "__exp10"); +- TLI.setAvailableWithName(LibFunc::exp10f, "__exp10f"); ++ TLI.setAvailableWithName(LibFunc_exp10, "__exp10"); ++ TLI.setAvailableWithName(LibFunc_exp10f, "__exp10f"); + } + break; + case Triple::IOS: + case Triple::TvOS: + case Triple::WatchOS: +- TLI.setUnavailable(LibFunc::exp10l); ++ TLI.setUnavailable(LibFunc_exp10l); + if (!T.isWatchOS() && (T.isOSVersionLT(7, 0) || + (T.isOSVersionLT(9, 0) && + (T.getArch() == Triple::x86 || + T.getArch() == Triple::x86_64)))) { +- TLI.setUnavailable(LibFunc::exp10); +- TLI.setUnavailable(LibFunc::exp10f); ++ TLI.setUnavailable(LibFunc_exp10); ++ TLI.setUnavailable(LibFunc_exp10f); + } else { +- TLI.setAvailableWithName(LibFunc::exp10, "__exp10"); +- TLI.setAvailableWithName(LibFunc::exp10f, "__exp10f"); ++ TLI.setAvailableWithName(LibFunc_exp10, "__exp10"); ++ TLI.setAvailableWithName(LibFunc_exp10f, "__exp10f"); + } + break; + case Triple::Linux: +@@ -344,9 +344,9 @@ static void initialize(TargetLibraryInfoImpl &TLI, const Triple &T, + // Fall through to disable all of them. + LLVM_FALLTHROUGH; + default: +- TLI.setUnavailable(LibFunc::exp10); +- TLI.setUnavailable(LibFunc::exp10f); +- TLI.setUnavailable(LibFunc::exp10l); ++ TLI.setUnavailable(LibFunc_exp10); ++ TLI.setUnavailable(LibFunc_exp10f); ++ TLI.setUnavailable(LibFunc_exp10l); + } + + // ffsl is available on at least Darwin, Mac OS X, iOS, FreeBSD, and +@@ -364,7 +364,7 @@ static void initialize(TargetLibraryInfoImpl &TLI, const Triple &T, + case Triple::Linux: + break; + default: +- TLI.setUnavailable(LibFunc::ffsl); ++ TLI.setUnavailable(LibFunc_ffsl); + } + + // ffsll is available on at least FreeBSD and Linux (GLIBC): +@@ -380,7 +380,7 @@ static void initialize(TargetLibraryInfoImpl &TLI, const Triple &T, + case Triple::Linux: + break; + default: +- TLI.setUnavailable(LibFunc::ffsll); ++ TLI.setUnavailable(LibFunc_ffsll); + } + + // The following functions are available on at least FreeBSD: +@@ -388,30 +388,30 @@ static void initialize(TargetLibraryInfoImpl &TLI, const Triple &T, + // http://svn.freebsd.org/base/head/lib/libc/string/flsl.c + // http://svn.freebsd.org/base/head/lib/libc/string/flsll.c + if (!T.isOSFreeBSD()) { +- TLI.setUnavailable(LibFunc::fls); +- TLI.setUnavailable(LibFunc::flsl); +- TLI.setUnavailable(LibFunc::flsll); ++ TLI.setUnavailable(LibFunc_fls); ++ TLI.setUnavailable(LibFunc_flsl); ++ TLI.setUnavailable(LibFunc_flsll); + } + + // The following functions are available on at least Linux: + if (!T.isOSLinux()) { +- TLI.setUnavailable(LibFunc::dunder_strdup); +- TLI.setUnavailable(LibFunc::dunder_strtok_r); +- TLI.setUnavailable(LibFunc::dunder_isoc99_scanf); +- TLI.setUnavailable(LibFunc::dunder_isoc99_sscanf); +- TLI.setUnavailable(LibFunc::under_IO_getc); +- TLI.setUnavailable(LibFunc::under_IO_putc); +- TLI.setUnavailable(LibFunc::memalign); +- TLI.setUnavailable(LibFunc::fopen64); +- TLI.setUnavailable(LibFunc::fseeko64); +- TLI.setUnavailable(LibFunc::fstat64); +- TLI.setUnavailable(LibFunc::fstatvfs64); +- TLI.setUnavailable(LibFunc::ftello64); +- TLI.setUnavailable(LibFunc::lstat64); +- TLI.setUnavailable(LibFunc::open64); +- TLI.setUnavailable(LibFunc::stat64); +- TLI.setUnavailable(LibFunc::statvfs64); +- TLI.setUnavailable(LibFunc::tmpfile64); ++ TLI.setUnavailable(LibFunc_dunder_strdup); ++ TLI.setUnavailable(LibFunc_dunder_strtok_r); ++ TLI.setUnavailable(LibFunc_dunder_isoc99_scanf); ++ TLI.setUnavailable(LibFunc_dunder_isoc99_sscanf); ++ TLI.setUnavailable(LibFunc_under_IO_getc); ++ TLI.setUnavailable(LibFunc_under_IO_putc); ++ TLI.setUnavailable(LibFunc_memalign); ++ TLI.setUnavailable(LibFunc_fopen64); ++ TLI.setUnavailable(LibFunc_fseeko64); ++ TLI.setUnavailable(LibFunc_fstat64); ++ TLI.setUnavailable(LibFunc_fstatvfs64); ++ TLI.setUnavailable(LibFunc_ftello64); ++ TLI.setUnavailable(LibFunc_lstat64); ++ TLI.setUnavailable(LibFunc_open64); ++ TLI.setUnavailable(LibFunc_stat64); ++ TLI.setUnavailable(LibFunc_statvfs64); ++ TLI.setUnavailable(LibFunc_tmpfile64); + } + + // As currently implemented in clang, NVPTX code has no standard library to +@@ -427,9 +427,9 @@ static void initialize(TargetLibraryInfoImpl &TLI, const Triple &T, + // optimizations, so this situation should be fixed. + if (T.isNVPTX()) { + TLI.disableAllFunctions(); +- TLI.setAvailable(LibFunc::nvvm_reflect); ++ TLI.setAvailable(LibFunc_nvvm_reflect); + } else { +- TLI.setUnavailable(LibFunc::nvvm_reflect); ++ TLI.setUnavailable(LibFunc_nvvm_reflect); + } + + TLI.addVectorizableFunctionsFromVecLib(ClVectorLibrary); +@@ -500,9 +500,9 @@ static StringRef sanitizeFunctionName(StringRef funcName) { + } + + bool TargetLibraryInfoImpl::getLibFunc(StringRef funcName, +- LibFunc::Func &F) const { ++ LibFunc &F) const { + StringRef const *Start = &StandardNames[0]; +- StringRef const *End = &StandardNames[LibFunc::NumLibFuncs]; ++ StringRef const *End = &StandardNames[NumLibFuncs]; + + funcName = sanitizeFunctionName(funcName); + if (funcName.empty()) +@@ -513,14 +513,14 @@ bool TargetLibraryInfoImpl::getLibFunc(StringRef funcName, + return LHS < RHS; + }); + if (I != End && *I == funcName) { +- F = (LibFunc::Func)(I - Start); ++ F = (LibFunc)(I - Start); + return true; + } + return false; + } + + bool TargetLibraryInfoImpl::isValidProtoForLibFunc(const FunctionType &FTy, +- LibFunc::Func F, ++ LibFunc F, + const DataLayout *DL) const { + LLVMContext &Ctx = FTy.getContext(); + Type *PCharTy = Type::getInt8PtrTy(Ctx); +@@ -531,493 +531,493 @@ bool TargetLibraryInfoImpl::isValidProtoForLibFunc(const FunctionType &FTy, + unsigned NumParams = FTy.getNumParams(); + + switch (F) { +- case LibFunc::strlen: ++ case LibFunc_strlen: + return (NumParams == 1 && FTy.getParamType(0)->isPointerTy() && + FTy.getReturnType()->isIntegerTy()); + +- case LibFunc::strchr: +- case LibFunc::strrchr: ++ case LibFunc_strchr: ++ case LibFunc_strrchr: + return (NumParams == 2 && FTy.getReturnType()->isPointerTy() && + FTy.getParamType(0) == FTy.getReturnType() && + FTy.getParamType(1)->isIntegerTy()); + +- case LibFunc::strtol: +- case LibFunc::strtod: +- case LibFunc::strtof: +- case LibFunc::strtoul: +- case LibFunc::strtoll: +- case LibFunc::strtold: +- case LibFunc::strtoull: ++ case LibFunc_strtol: ++ case LibFunc_strtod: ++ case LibFunc_strtof: ++ case LibFunc_strtoul: ++ case LibFunc_strtoll: ++ case LibFunc_strtold: ++ case LibFunc_strtoull: + return ((NumParams == 2 || NumParams == 3) && + FTy.getParamType(0)->isPointerTy() && + FTy.getParamType(1)->isPointerTy()); +- case LibFunc::strcat: ++ case LibFunc_strcat: + return (NumParams == 2 && FTy.getReturnType()->isPointerTy() && + FTy.getParamType(0) == FTy.getReturnType() && + FTy.getParamType(1) == FTy.getReturnType()); + +- case LibFunc::strncat: ++ case LibFunc_strncat: + return (NumParams == 3 && FTy.getReturnType()->isPointerTy() && + FTy.getParamType(0) == FTy.getReturnType() && + FTy.getParamType(1) == FTy.getReturnType() && + FTy.getParamType(2)->isIntegerTy()); + +- case LibFunc::strcpy_chk: +- case LibFunc::stpcpy_chk: ++ case LibFunc_strcpy_chk: ++ case LibFunc_stpcpy_chk: + --NumParams; + if (!IsSizeTTy(FTy.getParamType(NumParams))) + return false; + LLVM_FALLTHROUGH; +- case LibFunc::strcpy: +- case LibFunc::stpcpy: ++ case LibFunc_strcpy: ++ case LibFunc_stpcpy: + return (NumParams == 2 && FTy.getReturnType() == FTy.getParamType(0) && + FTy.getParamType(0) == FTy.getParamType(1) && + FTy.getParamType(0) == PCharTy); + +- case LibFunc::strncpy_chk: +- case LibFunc::stpncpy_chk: ++ case LibFunc_strncpy_chk: ++ case LibFunc_stpncpy_chk: + --NumParams; + if (!IsSizeTTy(FTy.getParamType(NumParams))) + return false; + LLVM_FALLTHROUGH; +- case LibFunc::strncpy: +- case LibFunc::stpncpy: ++ case LibFunc_strncpy: ++ case LibFunc_stpncpy: + return (NumParams == 3 && FTy.getReturnType() == FTy.getParamType(0) && + FTy.getParamType(0) == FTy.getParamType(1) && + FTy.getParamType(0) == PCharTy && + FTy.getParamType(2)->isIntegerTy()); + +- case LibFunc::strxfrm: ++ case LibFunc_strxfrm: + return (NumParams == 3 && FTy.getParamType(0)->isPointerTy() && + FTy.getParamType(1)->isPointerTy()); + +- case LibFunc::strcmp: ++ case LibFunc_strcmp: + return (NumParams == 2 && FTy.getReturnType()->isIntegerTy(32) && + FTy.getParamType(0)->isPointerTy() && + FTy.getParamType(0) == FTy.getParamType(1)); + +- case LibFunc::strncmp: ++ case LibFunc_strncmp: + return (NumParams == 3 && FTy.getReturnType()->isIntegerTy(32) && + FTy.getParamType(0)->isPointerTy() && + FTy.getParamType(0) == FTy.getParamType(1) && + FTy.getParamType(2)->isIntegerTy()); + +- case LibFunc::strspn: +- case LibFunc::strcspn: ++ case LibFunc_strspn: ++ case LibFunc_strcspn: + return (NumParams == 2 && FTy.getParamType(0)->isPointerTy() && + FTy.getParamType(0) == FTy.getParamType(1) && + FTy.getReturnType()->isIntegerTy()); + +- case LibFunc::strcoll: +- case LibFunc::strcasecmp: +- case LibFunc::strncasecmp: ++ case LibFunc_strcoll: ++ case LibFunc_strcasecmp: ++ case LibFunc_strncasecmp: + return (NumParams >= 2 && FTy.getParamType(0)->isPointerTy() && + FTy.getParamType(1)->isPointerTy()); + +- case LibFunc::strstr: ++ case LibFunc_strstr: + return (NumParams == 2 && FTy.getReturnType()->isPointerTy() && + FTy.getParamType(0)->isPointerTy() && + FTy.getParamType(1)->isPointerTy()); + +- case LibFunc::strpbrk: ++ case LibFunc_strpbrk: + return (NumParams == 2 && FTy.getParamType(0)->isPointerTy() && + FTy.getReturnType() == FTy.getParamType(0) && + FTy.getParamType(0) == FTy.getParamType(1)); + +- case LibFunc::strtok: +- case LibFunc::strtok_r: ++ case LibFunc_strtok: ++ case LibFunc_strtok_r: + return (NumParams >= 2 && FTy.getParamType(1)->isPointerTy()); +- case LibFunc::scanf: +- case LibFunc::setbuf: +- case LibFunc::setvbuf: ++ case LibFunc_scanf: ++ case LibFunc_setbuf: ++ case LibFunc_setvbuf: + return (NumParams >= 1 && FTy.getParamType(0)->isPointerTy()); +- case LibFunc::strdup: +- case LibFunc::strndup: ++ case LibFunc_strdup: ++ case LibFunc_strndup: + return (NumParams >= 1 && FTy.getReturnType()->isPointerTy() && + FTy.getParamType(0)->isPointerTy()); +- case LibFunc::sscanf: +- case LibFunc::stat: +- case LibFunc::statvfs: +- case LibFunc::sprintf: ++ case LibFunc_sscanf: ++ case LibFunc_stat: ++ case LibFunc_statvfs: ++ case LibFunc_sprintf: + return (NumParams >= 2 && FTy.getParamType(0)->isPointerTy() && + FTy.getParamType(1)->isPointerTy()); +- case LibFunc::snprintf: ++ case LibFunc_snprintf: + return (NumParams == 3 && FTy.getParamType(0)->isPointerTy() && + FTy.getParamType(2)->isPointerTy()); +- case LibFunc::setitimer: ++ case LibFunc_setitimer: + return (NumParams == 3 && FTy.getParamType(1)->isPointerTy() && + FTy.getParamType(2)->isPointerTy()); +- case LibFunc::system: ++ case LibFunc_system: + return (NumParams == 1 && FTy.getParamType(0)->isPointerTy()); +- case LibFunc::malloc: ++ case LibFunc_malloc: + return (NumParams == 1 && FTy.getReturnType()->isPointerTy()); +- case LibFunc::memcmp: ++ case LibFunc_memcmp: + return (NumParams == 3 && FTy.getParamType(0)->isPointerTy() && + FTy.getParamType(1)->isPointerTy() && + FTy.getReturnType()->isIntegerTy(32)); + +- case LibFunc::memchr: +- case LibFunc::memrchr: ++ case LibFunc_memchr: ++ case LibFunc_memrchr: + return (NumParams == 3 && FTy.getParamType(0)->isPointerTy() && + FTy.getParamType(1)->isIntegerTy(32) && + FTy.getParamType(2)->isIntegerTy() && + FTy.getReturnType()->isPointerTy()); +- case LibFunc::modf: +- case LibFunc::modff: +- case LibFunc::modfl: ++ case LibFunc_modf: ++ case LibFunc_modff: ++ case LibFunc_modfl: + return (NumParams >= 2 && FTy.getParamType(1)->isPointerTy()); + +- case LibFunc::memcpy_chk: +- case LibFunc::memmove_chk: ++ case LibFunc_memcpy_chk: ++ case LibFunc_memmove_chk: + --NumParams; + if (!IsSizeTTy(FTy.getParamType(NumParams))) + return false; + LLVM_FALLTHROUGH; +- case LibFunc::memcpy: +- case LibFunc::mempcpy: +- case LibFunc::memmove: ++ case LibFunc_memcpy: ++ case LibFunc_mempcpy: ++ case LibFunc_memmove: + return (NumParams == 3 && FTy.getReturnType() == FTy.getParamType(0) && + FTy.getParamType(0)->isPointerTy() && + FTy.getParamType(1)->isPointerTy() && + IsSizeTTy(FTy.getParamType(2))); + +- case LibFunc::memset_chk: ++ case LibFunc_memset_chk: + --NumParams; + if (!IsSizeTTy(FTy.getParamType(NumParams))) + return false; + LLVM_FALLTHROUGH; +- case LibFunc::memset: ++ case LibFunc_memset: + return (NumParams == 3 && FTy.getReturnType() == FTy.getParamType(0) && + FTy.getParamType(0)->isPointerTy() && + FTy.getParamType(1)->isIntegerTy() && + IsSizeTTy(FTy.getParamType(2))); + +- case LibFunc::memccpy: ++ case LibFunc_memccpy: + return (NumParams >= 2 && FTy.getParamType(1)->isPointerTy()); +- case LibFunc::memalign: ++ case LibFunc_memalign: + return (FTy.getReturnType()->isPointerTy()); +- case LibFunc::realloc: ++ case LibFunc_realloc: + return (NumParams == 2 && FTy.getParamType(0)->isPointerTy() && + FTy.getReturnType()->isPointerTy()); +- case LibFunc::read: ++ case LibFunc_read: + return (NumParams == 3 && FTy.getParamType(1)->isPointerTy()); +- case LibFunc::rewind: +- case LibFunc::rmdir: +- case LibFunc::remove: +- case LibFunc::realpath: ++ case LibFunc_rewind: ++ case LibFunc_rmdir: ++ case LibFunc_remove: ++ case LibFunc_realpath: + return (NumParams >= 1 && FTy.getParamType(0)->isPointerTy()); +- case LibFunc::rename: ++ case LibFunc_rename: + return (NumParams >= 2 && FTy.getParamType(0)->isPointerTy() && + FTy.getParamType(1)->isPointerTy()); +- case LibFunc::readlink: ++ case LibFunc_readlink: + return (NumParams >= 2 && FTy.getParamType(0)->isPointerTy() && + FTy.getParamType(1)->isPointerTy()); +- case LibFunc::write: ++ case LibFunc_write: + return (NumParams == 3 && FTy.getParamType(1)->isPointerTy()); +- case LibFunc::bcopy: +- case LibFunc::bcmp: ++ case LibFunc_bcopy: ++ case LibFunc_bcmp: + return (NumParams == 3 && FTy.getParamType(0)->isPointerTy() && + FTy.getParamType(1)->isPointerTy()); +- case LibFunc::bzero: ++ case LibFunc_bzero: + return (NumParams == 2 && FTy.getParamType(0)->isPointerTy()); +- case LibFunc::calloc: ++ case LibFunc_calloc: + return (NumParams == 2 && FTy.getReturnType()->isPointerTy()); + +- case LibFunc::atof: +- case LibFunc::atoi: +- case LibFunc::atol: +- case LibFunc::atoll: +- case LibFunc::ferror: +- case LibFunc::getenv: +- case LibFunc::getpwnam: +- case LibFunc::pclose: +- case LibFunc::perror: +- case LibFunc::printf: +- case LibFunc::puts: +- case LibFunc::uname: +- case LibFunc::under_IO_getc: +- case LibFunc::unlink: +- case LibFunc::unsetenv: ++ case LibFunc_atof: ++ case LibFunc_atoi: ++ case LibFunc_atol: ++ case LibFunc_atoll: ++ case LibFunc_ferror: ++ case LibFunc_getenv: ++ case LibFunc_getpwnam: ++ case LibFunc_pclose: ++ case LibFunc_perror: ++ case LibFunc_printf: ++ case LibFunc_puts: ++ case LibFunc_uname: ++ case LibFunc_under_IO_getc: ++ case LibFunc_unlink: ++ case LibFunc_unsetenv: + return (NumParams == 1 && FTy.getParamType(0)->isPointerTy()); + +- case LibFunc::chmod: +- case LibFunc::chown: +- case LibFunc::clearerr: +- case LibFunc::closedir: +- case LibFunc::ctermid: +- case LibFunc::fclose: +- case LibFunc::feof: +- case LibFunc::fflush: +- case LibFunc::fgetc: +- case LibFunc::fileno: +- case LibFunc::flockfile: +- case LibFunc::free: +- case LibFunc::fseek: +- case LibFunc::fseeko64: +- case LibFunc::fseeko: +- case LibFunc::fsetpos: +- case LibFunc::ftell: +- case LibFunc::ftello64: +- case LibFunc::ftello: +- case LibFunc::ftrylockfile: +- case LibFunc::funlockfile: +- case LibFunc::getc: +- case LibFunc::getc_unlocked: +- case LibFunc::getlogin_r: +- case LibFunc::mkdir: +- case LibFunc::mktime: +- case LibFunc::times: ++ case LibFunc_chmod: ++ case LibFunc_chown: ++ case LibFunc_clearerr: ++ case LibFunc_closedir: ++ case LibFunc_ctermid: ++ case LibFunc_fclose: ++ case LibFunc_feof: ++ case LibFunc_fflush: ++ case LibFunc_fgetc: ++ case LibFunc_fileno: ++ case LibFunc_flockfile: ++ case LibFunc_free: ++ case LibFunc_fseek: ++ case LibFunc_fseeko64: ++ case LibFunc_fseeko: ++ case LibFunc_fsetpos: ++ case LibFunc_ftell: ++ case LibFunc_ftello64: ++ case LibFunc_ftello: ++ case LibFunc_ftrylockfile: ++ case LibFunc_funlockfile: ++ case LibFunc_getc: ++ case LibFunc_getc_unlocked: ++ case LibFunc_getlogin_r: ++ case LibFunc_mkdir: ++ case LibFunc_mktime: ++ case LibFunc_times: + return (NumParams != 0 && FTy.getParamType(0)->isPointerTy()); + +- case LibFunc::access: ++ case LibFunc_access: + return (NumParams == 2 && FTy.getParamType(0)->isPointerTy()); +- case LibFunc::fopen: ++ case LibFunc_fopen: + return (NumParams == 2 && FTy.getReturnType()->isPointerTy() && + FTy.getParamType(0)->isPointerTy() && + FTy.getParamType(1)->isPointerTy()); +- case LibFunc::fdopen: ++ case LibFunc_fdopen: + return (NumParams == 2 && FTy.getReturnType()->isPointerTy() && + FTy.getParamType(1)->isPointerTy()); +- case LibFunc::fputc: +- case LibFunc::fstat: +- case LibFunc::frexp: +- case LibFunc::frexpf: +- case LibFunc::frexpl: +- case LibFunc::fstatvfs: ++ case LibFunc_fputc: ++ case LibFunc_fstat: ++ case LibFunc_frexp: ++ case LibFunc_frexpf: ++ case LibFunc_frexpl: ++ case LibFunc_fstatvfs: + return (NumParams == 2 && FTy.getParamType(1)->isPointerTy()); +- case LibFunc::fgets: ++ case LibFunc_fgets: + return (NumParams == 3 && FTy.getParamType(0)->isPointerTy() && + FTy.getParamType(2)->isPointerTy()); +- case LibFunc::fread: ++ case LibFunc_fread: + return (NumParams == 4 && FTy.getParamType(0)->isPointerTy() && + FTy.getParamType(3)->isPointerTy()); +- case LibFunc::fwrite: ++ case LibFunc_fwrite: + return (NumParams == 4 && FTy.getReturnType()->isIntegerTy() && + FTy.getParamType(0)->isPointerTy() && + FTy.getParamType(1)->isIntegerTy() && + FTy.getParamType(2)->isIntegerTy() && + FTy.getParamType(3)->isPointerTy()); +- case LibFunc::fputs: ++ case LibFunc_fputs: + return (NumParams >= 2 && FTy.getParamType(0)->isPointerTy() && + FTy.getParamType(1)->isPointerTy()); +- case LibFunc::fscanf: +- case LibFunc::fprintf: ++ case LibFunc_fscanf: ++ case LibFunc_fprintf: + return (NumParams >= 2 && FTy.getParamType(0)->isPointerTy() && + FTy.getParamType(1)->isPointerTy()); +- case LibFunc::fgetpos: ++ case LibFunc_fgetpos: + return (NumParams >= 2 && FTy.getParamType(0)->isPointerTy() && + FTy.getParamType(1)->isPointerTy()); +- case LibFunc::gets: +- case LibFunc::getchar: +- case LibFunc::getitimer: ++ case LibFunc_gets: ++ case LibFunc_getchar: ++ case LibFunc_getitimer: + return (NumParams == 2 && FTy.getParamType(1)->isPointerTy()); +- case LibFunc::ungetc: ++ case LibFunc_ungetc: + return (NumParams == 2 && FTy.getParamType(1)->isPointerTy()); +- case LibFunc::utime: +- case LibFunc::utimes: ++ case LibFunc_utime: ++ case LibFunc_utimes: + return (NumParams == 2 && FTy.getParamType(0)->isPointerTy() && + FTy.getParamType(1)->isPointerTy()); +- case LibFunc::putc: ++ case LibFunc_putc: + return (NumParams == 2 && FTy.getParamType(1)->isPointerTy()); +- case LibFunc::pread: +- case LibFunc::pwrite: ++ case LibFunc_pread: ++ case LibFunc_pwrite: + return (NumParams == 4 && FTy.getParamType(1)->isPointerTy()); +- case LibFunc::popen: ++ case LibFunc_popen: + return (NumParams == 2 && FTy.getReturnType()->isPointerTy() && + FTy.getParamType(0)->isPointerTy() && + FTy.getParamType(1)->isPointerTy()); +- case LibFunc::vscanf: ++ case LibFunc_vscanf: + return (NumParams == 2 && FTy.getParamType(1)->isPointerTy()); +- case LibFunc::vsscanf: ++ case LibFunc_vsscanf: + return (NumParams == 3 && FTy.getParamType(1)->isPointerTy() && + FTy.getParamType(2)->isPointerTy()); +- case LibFunc::vfscanf: ++ case LibFunc_vfscanf: + return (NumParams == 3 && FTy.getParamType(1)->isPointerTy() && + FTy.getParamType(2)->isPointerTy()); +- case LibFunc::valloc: ++ case LibFunc_valloc: + return (FTy.getReturnType()->isPointerTy()); +- case LibFunc::vprintf: ++ case LibFunc_vprintf: + return (NumParams == 2 && FTy.getParamType(0)->isPointerTy()); +- case LibFunc::vfprintf: +- case LibFunc::vsprintf: ++ case LibFunc_vfprintf: ++ case LibFunc_vsprintf: + return (NumParams == 3 && FTy.getParamType(0)->isPointerTy() && + FTy.getParamType(1)->isPointerTy()); +- case LibFunc::vsnprintf: ++ case LibFunc_vsnprintf: + return (NumParams == 4 && FTy.getParamType(0)->isPointerTy() && + FTy.getParamType(2)->isPointerTy()); +- case LibFunc::open: ++ case LibFunc_open: + return (NumParams >= 2 && FTy.getParamType(0)->isPointerTy()); +- case LibFunc::opendir: ++ case LibFunc_opendir: + return (NumParams == 1 && FTy.getReturnType()->isPointerTy() && + FTy.getParamType(0)->isPointerTy()); +- case LibFunc::tmpfile: ++ case LibFunc_tmpfile: + return (FTy.getReturnType()->isPointerTy()); +- case LibFunc::htonl: +- case LibFunc::htons: +- case LibFunc::ntohl: +- case LibFunc::ntohs: +- case LibFunc::lstat: ++ case LibFunc_htonl: ++ case LibFunc_htons: ++ case LibFunc_ntohl: ++ case LibFunc_ntohs: ++ case LibFunc_lstat: + return (NumParams == 2 && FTy.getParamType(0)->isPointerTy() && + FTy.getParamType(1)->isPointerTy()); +- case LibFunc::lchown: ++ case LibFunc_lchown: + return (NumParams == 3 && FTy.getParamType(0)->isPointerTy()); +- case LibFunc::qsort: ++ case LibFunc_qsort: + return (NumParams == 4 && FTy.getParamType(3)->isPointerTy()); +- case LibFunc::dunder_strdup: +- case LibFunc::dunder_strndup: ++ case LibFunc_dunder_strdup: ++ case LibFunc_dunder_strndup: + return (NumParams >= 1 && FTy.getReturnType()->isPointerTy() && + FTy.getParamType(0)->isPointerTy()); +- case LibFunc::dunder_strtok_r: ++ case LibFunc_dunder_strtok_r: + return (NumParams == 3 && FTy.getParamType(1)->isPointerTy()); +- case LibFunc::under_IO_putc: ++ case LibFunc_under_IO_putc: + return (NumParams == 2 && FTy.getParamType(1)->isPointerTy()); +- case LibFunc::dunder_isoc99_scanf: ++ case LibFunc_dunder_isoc99_scanf: + return (NumParams >= 1 && FTy.getParamType(0)->isPointerTy()); +- case LibFunc::stat64: +- case LibFunc::lstat64: +- case LibFunc::statvfs64: ++ case LibFunc_stat64: ++ case LibFunc_lstat64: ++ case LibFunc_statvfs64: + return (NumParams == 2 && FTy.getParamType(0)->isPointerTy() && + FTy.getParamType(1)->isPointerTy()); +- case LibFunc::dunder_isoc99_sscanf: ++ case LibFunc_dunder_isoc99_sscanf: + return (NumParams >= 2 && FTy.getParamType(0)->isPointerTy() && + FTy.getParamType(1)->isPointerTy()); +- case LibFunc::fopen64: ++ case LibFunc_fopen64: + return (NumParams == 2 && FTy.getReturnType()->isPointerTy() && + FTy.getParamType(0)->isPointerTy() && + FTy.getParamType(1)->isPointerTy()); +- case LibFunc::tmpfile64: ++ case LibFunc_tmpfile64: + return (FTy.getReturnType()->isPointerTy()); +- case LibFunc::fstat64: +- case LibFunc::fstatvfs64: ++ case LibFunc_fstat64: ++ case LibFunc_fstatvfs64: + return (NumParams == 2 && FTy.getParamType(1)->isPointerTy()); +- case LibFunc::open64: ++ case LibFunc_open64: + return (NumParams >= 2 && FTy.getParamType(0)->isPointerTy()); +- case LibFunc::gettimeofday: ++ case LibFunc_gettimeofday: + return (NumParams == 2 && FTy.getParamType(0)->isPointerTy() && + FTy.getParamType(1)->isPointerTy()); + +- case LibFunc::Znwj: // new(unsigned int); +- case LibFunc::Znwm: // new(unsigned long); +- case LibFunc::Znaj: // new[](unsigned int); +- case LibFunc::Znam: // new[](unsigned long); +- case LibFunc::msvc_new_int: // new(unsigned int); +- case LibFunc::msvc_new_longlong: // new(unsigned long long); +- case LibFunc::msvc_new_array_int: // new[](unsigned int); +- case LibFunc::msvc_new_array_longlong: // new[](unsigned long long); ++ case LibFunc_Znwj: // new(unsigned int); ++ case LibFunc_Znwm: // new(unsigned long); ++ case LibFunc_Znaj: // new[](unsigned int); ++ case LibFunc_Znam: // new[](unsigned long); ++ case LibFunc_msvc_new_int: // new(unsigned int); ++ case LibFunc_msvc_new_longlong: // new(unsigned long long); ++ case LibFunc_msvc_new_array_int: // new[](unsigned int); ++ case LibFunc_msvc_new_array_longlong: // new[](unsigned long long); + return (NumParams == 1); + +- case LibFunc::memset_pattern16: ++ case LibFunc_memset_pattern16: + return (!FTy.isVarArg() && NumParams == 3 && + isa(FTy.getParamType(0)) && + isa(FTy.getParamType(1)) && + isa(FTy.getParamType(2))); + + // int __nvvm_reflect(const char *); +- case LibFunc::nvvm_reflect: ++ case LibFunc_nvvm_reflect: + return (NumParams == 1 && isa(FTy.getParamType(0))); + +- case LibFunc::sin: +- case LibFunc::sinf: +- case LibFunc::sinl: +- case LibFunc::cos: +- case LibFunc::cosf: +- case LibFunc::cosl: +- case LibFunc::tan: +- case LibFunc::tanf: +- case LibFunc::tanl: +- case LibFunc::exp: +- case LibFunc::expf: +- case LibFunc::expl: +- case LibFunc::exp2: +- case LibFunc::exp2f: +- case LibFunc::exp2l: +- case LibFunc::log: +- case LibFunc::logf: +- case LibFunc::logl: +- case LibFunc::log10: +- case LibFunc::log10f: +- case LibFunc::log10l: +- case LibFunc::log1p: +- case LibFunc::log2: +- case LibFunc::log2f: +- case LibFunc::log2l: +- case LibFunc::fabs: +- case LibFunc::fabsf: +- case LibFunc::fabsl: +- case LibFunc::floor: +- case LibFunc::floorf: +- case LibFunc::floorl: +- case LibFunc::ceil: +- case LibFunc::ceilf: +- case LibFunc::ceill: +- case LibFunc::trunc: +- case LibFunc::truncf: +- case LibFunc::truncl: +- case LibFunc::rint: +- case LibFunc::rintf: +- case LibFunc::rintl: +- case LibFunc::nearbyint: +- case LibFunc::nearbyintf: +- case LibFunc::nearbyintl: +- case LibFunc::round: +- case LibFunc::roundf: +- case LibFunc::roundl: +- case LibFunc::sqrt: +- case LibFunc::sqrtf: +- case LibFunc::sqrtl: ++ case LibFunc_sin: ++ case LibFunc_sinf: ++ case LibFunc_sinl: ++ case LibFunc_cos: ++ case LibFunc_cosf: ++ case LibFunc_cosl: ++ case LibFunc_tan: ++ case LibFunc_tanf: ++ case LibFunc_tanl: ++ case LibFunc_exp: ++ case LibFunc_expf: ++ case LibFunc_expl: ++ case LibFunc_exp2: ++ case LibFunc_exp2f: ++ case LibFunc_exp2l: ++ case LibFunc_log: ++ case LibFunc_logf: ++ case LibFunc_logl: ++ case LibFunc_log10: ++ case LibFunc_log10f: ++ case LibFunc_log10l: ++ case LibFunc_log1p: ++ case LibFunc_log2: ++ case LibFunc_log2f: ++ case LibFunc_log2l: ++ case LibFunc_fabs: ++ case LibFunc_fabsf: ++ case LibFunc_fabsl: ++ case LibFunc_floor: ++ case LibFunc_floorf: ++ case LibFunc_floorl: ++ case LibFunc_ceil: ++ case LibFunc_ceilf: ++ case LibFunc_ceill: ++ case LibFunc_trunc: ++ case LibFunc_truncf: ++ case LibFunc_truncl: ++ case LibFunc_rint: ++ case LibFunc_rintf: ++ case LibFunc_rintl: ++ case LibFunc_nearbyint: ++ case LibFunc_nearbyintf: ++ case LibFunc_nearbyintl: ++ case LibFunc_round: ++ case LibFunc_roundf: ++ case LibFunc_roundl: ++ case LibFunc_sqrt: ++ case LibFunc_sqrtf: ++ case LibFunc_sqrtl: + return (NumParams == 1 && FTy.getReturnType()->isFloatingPointTy() && + FTy.getReturnType() == FTy.getParamType(0)); + +- case LibFunc::fmin: +- case LibFunc::fminf: +- case LibFunc::fminl: +- case LibFunc::fmax: +- case LibFunc::fmaxf: +- case LibFunc::fmaxl: +- case LibFunc::copysign: +- case LibFunc::copysignf: +- case LibFunc::copysignl: +- case LibFunc::pow: +- case LibFunc::powf: +- case LibFunc::powl: ++ case LibFunc_fmin: ++ case LibFunc_fminf: ++ case LibFunc_fminl: ++ case LibFunc_fmax: ++ case LibFunc_fmaxf: ++ case LibFunc_fmaxl: ++ case LibFunc_copysign: ++ case LibFunc_copysignf: ++ case LibFunc_copysignl: ++ case LibFunc_pow: ++ case LibFunc_powf: ++ case LibFunc_powl: + return (NumParams == 2 && FTy.getReturnType()->isFloatingPointTy() && + FTy.getReturnType() == FTy.getParamType(0) && + FTy.getReturnType() == FTy.getParamType(1)); + +- case LibFunc::ffs: +- case LibFunc::ffsl: +- case LibFunc::ffsll: +- case LibFunc::fls: +- case LibFunc::flsl: +- case LibFunc::flsll: ++ case LibFunc_ffs: ++ case LibFunc_ffsl: ++ case LibFunc_ffsll: ++ case LibFunc_fls: ++ case LibFunc_flsl: ++ case LibFunc_flsll: + return (NumParams == 1 && FTy.getReturnType()->isIntegerTy(32) && + FTy.getParamType(0)->isIntegerTy()); + +- case LibFunc::isdigit: +- case LibFunc::isascii: +- case LibFunc::toascii: ++ case LibFunc_isdigit: ++ case LibFunc_isascii: ++ case LibFunc_toascii: + return (NumParams == 1 && FTy.getReturnType()->isIntegerTy(32) && + FTy.getReturnType() == FTy.getParamType(0)); + +- case LibFunc::abs: +- case LibFunc::labs: +- case LibFunc::llabs: ++ case LibFunc_abs: ++ case LibFunc_labs: ++ case LibFunc_llabs: + return (NumParams == 1 && FTy.getReturnType()->isIntegerTy() && + FTy.getReturnType() == FTy.getParamType(0)); + +- case LibFunc::cxa_atexit: ++ case LibFunc_cxa_atexit: + return (NumParams == 3 && FTy.getReturnType()->isIntegerTy() && + FTy.getParamType(0)->isPointerTy() && + FTy.getParamType(1)->isPointerTy() && + FTy.getParamType(2)->isPointerTy()); + +- case LibFunc::sinpi: +- case LibFunc::cospi: ++ case LibFunc_sinpi: ++ case LibFunc_cospi: + return (NumParams == 1 && FTy.getReturnType()->isDoubleTy() && + FTy.getReturnType() == FTy.getParamType(0)); + +- case LibFunc::sinpif: +- case LibFunc::cospif: ++ case LibFunc_sinpif: ++ case LibFunc_cospif: + return (NumParams == 1 && FTy.getReturnType()->isFloatTy() && + FTy.getReturnType() == FTy.getParamType(0)); + +@@ -1029,7 +1029,7 @@ bool TargetLibraryInfoImpl::isValidProtoForLibFunc(const FunctionType &FTy, + } + + bool TargetLibraryInfoImpl::getLibFunc(const Function &FDecl, +- LibFunc::Func &F) const { ++ LibFunc &F) const { + const DataLayout *DL = + FDecl.getParent() ? &FDecl.getParent()->getDataLayout() : nullptr; + return getLibFunc(FDecl.getName(), F) && +diff --git a/lib/Analysis/ValueTracking.cpp b/lib/Analysis/ValueTracking.cpp +index b79370baad1..55f1e676a74 100644 +--- a/lib/Analysis/ValueTracking.cpp ++++ b/lib/Analysis/ValueTracking.cpp +@@ -2436,7 +2436,7 @@ Intrinsic::ID llvm::getIntrinsicForCallSite(ImmutableCallSite ICS, + if (!TLI) + return Intrinsic::not_intrinsic; + +- LibFunc::Func Func; ++ LibFunc Func; + // We're going to make assumptions on the semantics of the functions, check + // that the target knows that it's available in this environment and it does + // not have local linkage. +@@ -2451,81 +2451,81 @@ Intrinsic::ID llvm::getIntrinsicForCallSite(ImmutableCallSite ICS, + switch (Func) { + default: + break; +- case LibFunc::sin: +- case LibFunc::sinf: +- case LibFunc::sinl: ++ case LibFunc_sin: ++ case LibFunc_sinf: ++ case LibFunc_sinl: + return Intrinsic::sin; +- case LibFunc::cos: +- case LibFunc::cosf: +- case LibFunc::cosl: ++ case LibFunc_cos: ++ case LibFunc_cosf: ++ case LibFunc_cosl: + return Intrinsic::cos; +- case LibFunc::exp: +- case LibFunc::expf: +- case LibFunc::expl: ++ case LibFunc_exp: ++ case LibFunc_expf: ++ case LibFunc_expl: + return Intrinsic::exp; +- case LibFunc::exp2: +- case LibFunc::exp2f: +- case LibFunc::exp2l: ++ case LibFunc_exp2: ++ case LibFunc_exp2f: ++ case LibFunc_exp2l: + return Intrinsic::exp2; +- case LibFunc::log: +- case LibFunc::logf: +- case LibFunc::logl: ++ case LibFunc_log: ++ case LibFunc_logf: ++ case LibFunc_logl: + return Intrinsic::log; +- case LibFunc::log10: +- case LibFunc::log10f: +- case LibFunc::log10l: ++ case LibFunc_log10: ++ case LibFunc_log10f: ++ case LibFunc_log10l: + return Intrinsic::log10; +- case LibFunc::log2: +- case LibFunc::log2f: +- case LibFunc::log2l: ++ case LibFunc_log2: ++ case LibFunc_log2f: ++ case LibFunc_log2l: + return Intrinsic::log2; +- case LibFunc::fabs: +- case LibFunc::fabsf: +- case LibFunc::fabsl: ++ case LibFunc_fabs: ++ case LibFunc_fabsf: ++ case LibFunc_fabsl: + return Intrinsic::fabs; +- case LibFunc::fmin: +- case LibFunc::fminf: +- case LibFunc::fminl: ++ case LibFunc_fmin: ++ case LibFunc_fminf: ++ case LibFunc_fminl: + return Intrinsic::minnum; +- case LibFunc::fmax: +- case LibFunc::fmaxf: +- case LibFunc::fmaxl: ++ case LibFunc_fmax: ++ case LibFunc_fmaxf: ++ case LibFunc_fmaxl: + return Intrinsic::maxnum; +- case LibFunc::copysign: +- case LibFunc::copysignf: +- case LibFunc::copysignl: ++ case LibFunc_copysign: ++ case LibFunc_copysignf: ++ case LibFunc_copysignl: + return Intrinsic::copysign; +- case LibFunc::floor: +- case LibFunc::floorf: +- case LibFunc::floorl: ++ case LibFunc_floor: ++ case LibFunc_floorf: ++ case LibFunc_floorl: + return Intrinsic::floor; +- case LibFunc::ceil: +- case LibFunc::ceilf: +- case LibFunc::ceill: ++ case LibFunc_ceil: ++ case LibFunc_ceilf: ++ case LibFunc_ceill: + return Intrinsic::ceil; +- case LibFunc::trunc: +- case LibFunc::truncf: +- case LibFunc::truncl: ++ case LibFunc_trunc: ++ case LibFunc_truncf: ++ case LibFunc_truncl: + return Intrinsic::trunc; +- case LibFunc::rint: +- case LibFunc::rintf: +- case LibFunc::rintl: ++ case LibFunc_rint: ++ case LibFunc_rintf: ++ case LibFunc_rintl: + return Intrinsic::rint; +- case LibFunc::nearbyint: +- case LibFunc::nearbyintf: +- case LibFunc::nearbyintl: ++ case LibFunc_nearbyint: ++ case LibFunc_nearbyintf: ++ case LibFunc_nearbyintl: + return Intrinsic::nearbyint; +- case LibFunc::round: +- case LibFunc::roundf: +- case LibFunc::roundl: ++ case LibFunc_round: ++ case LibFunc_roundf: ++ case LibFunc_roundl: + return Intrinsic::round; +- case LibFunc::pow: +- case LibFunc::powf: +- case LibFunc::powl: ++ case LibFunc_pow: ++ case LibFunc_powf: ++ case LibFunc_powl: + return Intrinsic::pow; +- case LibFunc::sqrt: +- case LibFunc::sqrtf: +- case LibFunc::sqrtl: ++ case LibFunc_sqrt: ++ case LibFunc_sqrtf: ++ case LibFunc_sqrtl: + if (ICS->hasNoNaNs()) + return Intrinsic::sqrt; + return Intrinsic::not_intrinsic; +diff --git a/lib/CodeGen/SelectionDAG/FastISel.cpp b/lib/CodeGen/SelectionDAG/FastISel.cpp +index 62de8bf2015..cb1a5ce8be1 100644 +--- a/lib/CodeGen/SelectionDAG/FastISel.cpp ++++ b/lib/CodeGen/SelectionDAG/FastISel.cpp +@@ -1364,7 +1364,7 @@ bool FastISel::selectInstruction(const Instruction *I) { + + if (const auto *Call = dyn_cast(I)) { + const Function *F = Call->getCalledFunction(); +- LibFunc::Func Func; ++ LibFunc Func; + + // As a special case, don't handle calls to builtin library functions that + // may be translated directly to target instructions. +diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +index 95e31a3eaf6..5dad37cd5a1 100644 +--- a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp ++++ b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +@@ -6334,15 +6334,15 @@ void SelectionDAGBuilder::visitCall(const CallInst &I) { + // Check for well-known libc/libm calls. If the function is internal, it + // can't be a library call. Don't do the check if marked as nobuiltin for + // some reason. +- LibFunc::Func Func; ++ LibFunc Func; + if (!I.isNoBuiltin() && !F->hasLocalLinkage() && F->hasName() && + LibInfo->getLibFunc(F->getName(), Func) && + LibInfo->hasOptimizedCodeGen(Func)) { + switch (Func) { + default: break; +- case LibFunc::copysign: +- case LibFunc::copysignf: +- case LibFunc::copysignl: ++ case LibFunc_copysign: ++ case LibFunc_copysignf: ++ case LibFunc_copysignl: + if (I.getNumArgOperands() == 2 && // Basic sanity checks. + I.getArgOperand(0)->getType()->isFloatingPointTy() && + I.getType() == I.getArgOperand(0)->getType() && +@@ -6355,122 +6355,122 @@ void SelectionDAGBuilder::visitCall(const CallInst &I) { + return; + } + break; +- case LibFunc::fabs: +- case LibFunc::fabsf: +- case LibFunc::fabsl: ++ case LibFunc_fabs: ++ case LibFunc_fabsf: ++ case LibFunc_fabsl: + if (visitUnaryFloatCall(I, ISD::FABS)) + return; + break; +- case LibFunc::fmin: +- case LibFunc::fminf: +- case LibFunc::fminl: ++ case LibFunc_fmin: ++ case LibFunc_fminf: ++ case LibFunc_fminl: + if (visitBinaryFloatCall(I, ISD::FMINNUM)) + return; + break; +- case LibFunc::fmax: +- case LibFunc::fmaxf: +- case LibFunc::fmaxl: ++ case LibFunc_fmax: ++ case LibFunc_fmaxf: ++ case LibFunc_fmaxl: + if (visitBinaryFloatCall(I, ISD::FMAXNUM)) + return; + break; +- case LibFunc::sin: +- case LibFunc::sinf: +- case LibFunc::sinl: ++ case LibFunc_sin: ++ case LibFunc_sinf: ++ case LibFunc_sinl: + if (visitUnaryFloatCall(I, ISD::FSIN)) + return; + break; +- case LibFunc::cos: +- case LibFunc::cosf: +- case LibFunc::cosl: ++ case LibFunc_cos: ++ case LibFunc_cosf: ++ case LibFunc_cosl: + if (visitUnaryFloatCall(I, ISD::FCOS)) + return; + break; +- case LibFunc::sqrt: +- case LibFunc::sqrtf: +- case LibFunc::sqrtl: +- case LibFunc::sqrt_finite: +- case LibFunc::sqrtf_finite: +- case LibFunc::sqrtl_finite: ++ case LibFunc_sqrt: ++ case LibFunc_sqrtf: ++ case LibFunc_sqrtl: ++ case LibFunc_sqrt_finite: ++ case LibFunc_sqrtf_finite: ++ case LibFunc_sqrtl_finite: + if (visitUnaryFloatCall(I, ISD::FSQRT)) + return; + break; +- case LibFunc::floor: +- case LibFunc::floorf: +- case LibFunc::floorl: ++ case LibFunc_floor: ++ case LibFunc_floorf: ++ case LibFunc_floorl: + if (visitUnaryFloatCall(I, ISD::FFLOOR)) + return; + break; +- case LibFunc::nearbyint: +- case LibFunc::nearbyintf: +- case LibFunc::nearbyintl: ++ case LibFunc_nearbyint: ++ case LibFunc_nearbyintf: ++ case LibFunc_nearbyintl: + if (visitUnaryFloatCall(I, ISD::FNEARBYINT)) + return; + break; +- case LibFunc::ceil: +- case LibFunc::ceilf: +- case LibFunc::ceill: ++ case LibFunc_ceil: ++ case LibFunc_ceilf: ++ case LibFunc_ceill: + if (visitUnaryFloatCall(I, ISD::FCEIL)) + return; + break; +- case LibFunc::rint: +- case LibFunc::rintf: +- case LibFunc::rintl: ++ case LibFunc_rint: ++ case LibFunc_rintf: ++ case LibFunc_rintl: + if (visitUnaryFloatCall(I, ISD::FRINT)) + return; + break; +- case LibFunc::round: +- case LibFunc::roundf: +- case LibFunc::roundl: ++ case LibFunc_round: ++ case LibFunc_roundf: ++ case LibFunc_roundl: + if (visitUnaryFloatCall(I, ISD::FROUND)) + return; + break; +- case LibFunc::trunc: +- case LibFunc::truncf: +- case LibFunc::truncl: ++ case LibFunc_trunc: ++ case LibFunc_truncf: ++ case LibFunc_truncl: + if (visitUnaryFloatCall(I, ISD::FTRUNC)) + return; + break; +- case LibFunc::log2: +- case LibFunc::log2f: +- case LibFunc::log2l: ++ case LibFunc_log2: ++ case LibFunc_log2f: ++ case LibFunc_log2l: + if (visitUnaryFloatCall(I, ISD::FLOG2)) + return; + break; +- case LibFunc::exp2: +- case LibFunc::exp2f: +- case LibFunc::exp2l: ++ case LibFunc_exp2: ++ case LibFunc_exp2f: ++ case LibFunc_exp2l: + if (visitUnaryFloatCall(I, ISD::FEXP2)) + return; + break; +- case LibFunc::memcmp: ++ case LibFunc_memcmp: + if (visitMemCmpCall(I)) + return; + break; +- case LibFunc::mempcpy: ++ case LibFunc_mempcpy: + if (visitMemPCpyCall(I)) + return; + break; +- case LibFunc::memchr: ++ case LibFunc_memchr: + if (visitMemChrCall(I)) + return; + break; +- case LibFunc::strcpy: ++ case LibFunc_strcpy: + if (visitStrCpyCall(I, false)) + return; + break; +- case LibFunc::stpcpy: ++ case LibFunc_stpcpy: + if (visitStrCpyCall(I, true)) + return; + break; +- case LibFunc::strcmp: ++ case LibFunc_strcmp: + if (visitStrCmpCall(I)) + return; + break; +- case LibFunc::strlen: ++ case LibFunc_strlen: + if (visitStrLenCall(I)) + return; + break; +- case LibFunc::strnlen: ++ case LibFunc_strnlen: + if (visitStrNLenCall(I)) + return; + break; +diff --git a/lib/LTO/UpdateCompilerUsed.cpp b/lib/LTO/UpdateCompilerUsed.cpp +index b67d9ea5989..5165cc96503 100644 +--- a/lib/LTO/UpdateCompilerUsed.cpp ++++ b/lib/LTO/UpdateCompilerUsed.cpp +@@ -65,7 +65,7 @@ private: + // target. + for (unsigned I = 0, E = static_cast(LibFunc::NumLibFuncs); + I != E; ++I) { +- LibFunc::Func F = static_cast(I); ++ LibFunc F = static_cast(I); + if (TLI.has(F)) + Libcalls.insert(TLI.getName(F)); + } +diff --git a/lib/Target/PowerPC/PPCCTRLoops.cpp b/lib/Target/PowerPC/PPCCTRLoops.cpp +index 2c62a0f1d90..197be8b7db9 100644 +--- a/lib/Target/PowerPC/PPCCTRLoops.cpp ++++ b/lib/Target/PowerPC/PPCCTRLoops.cpp +@@ -315,7 +315,7 @@ bool PPCCTRLoops::mightUseCTR(const Triple &TT, BasicBlock *BB) { + // (i.e. soft float or atomics). If adapting for targets that do, + // additional care is required here. + +- LibFunc::Func Func; ++ LibFunc Func; + if (!F->hasLocalLinkage() && F->hasName() && LibInfo && + LibInfo->getLibFunc(F->getName(), Func) && + LibInfo->hasOptimizedCodeGen(Func)) { +@@ -329,50 +329,50 @@ bool PPCCTRLoops::mightUseCTR(const Triple &TT, BasicBlock *BB) { + + switch (Func) { + default: return true; +- case LibFunc::copysign: +- case LibFunc::copysignf: ++ case LibFunc_copysign: ++ case LibFunc_copysignf: + continue; // ISD::FCOPYSIGN is never a library call. +- case LibFunc::copysignl: ++ case LibFunc_copysignl: + return true; +- case LibFunc::fabs: +- case LibFunc::fabsf: +- case LibFunc::fabsl: ++ case LibFunc_fabs: ++ case LibFunc_fabsf: ++ case LibFunc_fabsl: + continue; // ISD::FABS is never a library call. +- case LibFunc::sqrt: +- case LibFunc::sqrtf: +- case LibFunc::sqrtl: ++ case LibFunc_sqrt: ++ case LibFunc_sqrtf: ++ case LibFunc_sqrtl: + Opcode = ISD::FSQRT; break; +- case LibFunc::floor: +- case LibFunc::floorf: +- case LibFunc::floorl: ++ case LibFunc_floor: ++ case LibFunc_floorf: ++ case LibFunc_floorl: + Opcode = ISD::FFLOOR; break; +- case LibFunc::nearbyint: +- case LibFunc::nearbyintf: +- case LibFunc::nearbyintl: ++ case LibFunc_nearbyint: ++ case LibFunc_nearbyintf: ++ case LibFunc_nearbyintl: + Opcode = ISD::FNEARBYINT; break; +- case LibFunc::ceil: +- case LibFunc::ceilf: +- case LibFunc::ceill: ++ case LibFunc_ceil: ++ case LibFunc_ceilf: ++ case LibFunc_ceill: + Opcode = ISD::FCEIL; break; +- case LibFunc::rint: +- case LibFunc::rintf: +- case LibFunc::rintl: ++ case LibFunc_rint: ++ case LibFunc_rintf: ++ case LibFunc_rintl: + Opcode = ISD::FRINT; break; +- case LibFunc::round: +- case LibFunc::roundf: +- case LibFunc::roundl: ++ case LibFunc_round: ++ case LibFunc_roundf: ++ case LibFunc_roundl: + Opcode = ISD::FROUND; break; +- case LibFunc::trunc: +- case LibFunc::truncf: +- case LibFunc::truncl: ++ case LibFunc_trunc: ++ case LibFunc_truncf: ++ case LibFunc_truncl: + Opcode = ISD::FTRUNC; break; +- case LibFunc::fmin: +- case LibFunc::fminf: +- case LibFunc::fminl: ++ case LibFunc_fmin: ++ case LibFunc_fminf: ++ case LibFunc_fminl: + Opcode = ISD::FMINNUM; break; +- case LibFunc::fmax: +- case LibFunc::fmaxf: +- case LibFunc::fmaxl: ++ case LibFunc_fmax: ++ case LibFunc_fmaxf: ++ case LibFunc_fmaxl: + Opcode = ISD::FMAXNUM; break; + } + } +diff --git a/lib/Transforms/IPO/GlobalOpt.cpp b/lib/Transforms/IPO/GlobalOpt.cpp +index 5b0d5e3bc01..484fdbed0cb 100644 +--- a/lib/Transforms/IPO/GlobalOpt.cpp ++++ b/lib/Transforms/IPO/GlobalOpt.cpp +@@ -2387,7 +2387,7 @@ OptimizeGlobalAliases(Module &M, + } + + static Function *FindCXAAtExit(Module &M, TargetLibraryInfo *TLI) { +- LibFunc::Func F = LibFunc::cxa_atexit; ++ LibFunc F = LibFunc_cxa_atexit; + if (!TLI->has(F)) + return nullptr; + +@@ -2396,7 +2396,7 @@ static Function *FindCXAAtExit(Module &M, TargetLibraryInfo *TLI) { + return nullptr; + + // Make sure that the function has the correct prototype. +- if (!TLI->getLibFunc(*Fn, F) || F != LibFunc::cxa_atexit) ++ if (!TLI->getLibFunc(*Fn, F) || F != LibFunc_cxa_atexit) + return nullptr; + + return Fn; +diff --git a/lib/Transforms/Scalar/DeadStoreElimination.cpp b/lib/Transforms/Scalar/DeadStoreElimination.cpp +index 4d4c3baef3f..a1e995aca22 100644 +--- a/lib/Transforms/Scalar/DeadStoreElimination.cpp ++++ b/lib/Transforms/Scalar/DeadStoreElimination.cpp +@@ -135,13 +135,13 @@ static bool hasMemoryWrite(Instruction *I, const TargetLibraryInfo &TLI) { + if (auto CS = CallSite(I)) { + if (Function *F = CS.getCalledFunction()) { + StringRef FnName = F->getName(); +- if (TLI.has(LibFunc::strcpy) && FnName == TLI.getName(LibFunc::strcpy)) ++ if (TLI.has(LibFunc_strcpy) && FnName == TLI.getName(LibFunc_strcpy)) + return true; +- if (TLI.has(LibFunc::strncpy) && FnName == TLI.getName(LibFunc::strncpy)) ++ if (TLI.has(LibFunc_strncpy) && FnName == TLI.getName(LibFunc_strncpy)) + return true; +- if (TLI.has(LibFunc::strcat) && FnName == TLI.getName(LibFunc::strcat)) ++ if (TLI.has(LibFunc_strcat) && FnName == TLI.getName(LibFunc_strcat)) + return true; +- if (TLI.has(LibFunc::strncat) && FnName == TLI.getName(LibFunc::strncat)) ++ if (TLI.has(LibFunc_strncat) && FnName == TLI.getName(LibFunc_strncat)) + return true; + } + } +diff --git a/lib/Transforms/Scalar/LoopIdiomRecognize.cpp b/lib/Transforms/Scalar/LoopIdiomRecognize.cpp +index 5fec51c095d..d509f2928b1 100644 +--- a/lib/Transforms/Scalar/LoopIdiomRecognize.cpp ++++ b/lib/Transforms/Scalar/LoopIdiomRecognize.cpp +@@ -236,9 +236,9 @@ bool LoopIdiomRecognize::runOnLoop(Loop *L) { + ApplyCodeSizeHeuristics = + L->getHeader()->getParent()->optForSize() && UseLIRCodeSizeHeurs; + +- HasMemset = TLI->has(LibFunc::memset); +- HasMemsetPattern = TLI->has(LibFunc::memset_pattern16); +- HasMemcpy = TLI->has(LibFunc::memcpy); ++ HasMemset = TLI->has(LibFunc_memset); ++ HasMemsetPattern = TLI->has(LibFunc_memset_pattern16); ++ HasMemcpy = TLI->has(LibFunc_memcpy); + + if (HasMemset || HasMemsetPattern || HasMemcpy) + if (SE->hasLoopInvariantBackedgeTakenCount(L)) +diff --git a/lib/Transforms/Scalar/MemCpyOptimizer.cpp b/lib/Transforms/Scalar/MemCpyOptimizer.cpp +index 8355f952e31..b84f4780442 100644 +--- a/lib/Transforms/Scalar/MemCpyOptimizer.cpp ++++ b/lib/Transforms/Scalar/MemCpyOptimizer.cpp +@@ -1240,7 +1240,7 @@ bool MemCpyOptPass::processMemCpy(MemCpyInst *M) { + bool MemCpyOptPass::processMemMove(MemMoveInst *M) { + AliasAnalysis &AA = LookupAliasAnalysis(); + +- if (!TLI->has(LibFunc::memmove)) ++ if (!TLI->has(LibFunc_memmove)) + return false; + + // See if the pointers alias. +@@ -1419,7 +1419,7 @@ bool MemCpyOptPass::runImpl( + // If we don't have at least memset and memcpy, there is little point of doing + // anything here. These are required by a freestanding implementation, so if + // even they are disabled, there is no point in trying hard. +- if (!TLI->has(LibFunc::memset) || !TLI->has(LibFunc::memcpy)) ++ if (!TLI->has(LibFunc_memset) || !TLI->has(LibFunc_memcpy)) + return false; + + while (1) { +diff --git a/lib/Transforms/Scalar/PartiallyInlineLibCalls.cpp b/lib/Transforms/Scalar/PartiallyInlineLibCalls.cpp +index 1a7ddc9585b..5494356a60b 100644 +--- a/lib/Transforms/Scalar/PartiallyInlineLibCalls.cpp ++++ b/lib/Transforms/Scalar/PartiallyInlineLibCalls.cpp +@@ -98,14 +98,14 @@ static bool runPartiallyInlineLibCalls(Function &F, TargetLibraryInfo *TLI, + + // Skip if function either has local linkage or is not a known library + // function. +- LibFunc::Func LibFunc; ++ LibFunc LF; + if (CalledFunc->hasLocalLinkage() || !CalledFunc->hasName() || +- !TLI->getLibFunc(CalledFunc->getName(), LibFunc)) ++ !TLI->getLibFunc(CalledFunc->getName(), LF)) + continue; + +- switch (LibFunc) { +- case LibFunc::sqrtf: +- case LibFunc::sqrt: ++ switch (LF) { ++ case LibFunc_sqrtf: ++ case LibFunc_sqrt: + if (TTI->haveFastSqrt(Call->getType()) && + optimizeSQRT(Call, CalledFunc, *CurrBB, BB)) + break; +diff --git a/lib/Transforms/Utils/BuildLibCalls.cpp b/lib/Transforms/Utils/BuildLibCalls.cpp +index e61b04fbdd5..4f6bfcfe524 100644 +--- a/lib/Transforms/Utils/BuildLibCalls.cpp ++++ b/lib/Transforms/Utils/BuildLibCalls.cpp +@@ -107,255 +107,255 @@ static bool setNonNull(Function &F, unsigned n) { + } + + bool llvm::inferLibFuncAttributes(Function &F, const TargetLibraryInfo &TLI) { +- LibFunc::Func TheLibFunc; ++ LibFunc TheLibFunc; + if (!(TLI.getLibFunc(F, TheLibFunc) && TLI.has(TheLibFunc))) + return false; + + bool Changed = false; + switch (TheLibFunc) { +- case LibFunc::strlen: ++ case LibFunc_strlen: + Changed |= setOnlyReadsMemory(F); + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 1); + return Changed; +- case LibFunc::strchr: +- case LibFunc::strrchr: ++ case LibFunc_strchr: ++ case LibFunc_strrchr: + Changed |= setOnlyReadsMemory(F); + Changed |= setDoesNotThrow(F); + return Changed; +- case LibFunc::strtol: +- case LibFunc::strtod: +- case LibFunc::strtof: +- case LibFunc::strtoul: +- case LibFunc::strtoll: +- case LibFunc::strtold: +- case LibFunc::strtoull: ++ case LibFunc_strtol: ++ case LibFunc_strtod: ++ case LibFunc_strtof: ++ case LibFunc_strtoul: ++ case LibFunc_strtoll: ++ case LibFunc_strtold: ++ case LibFunc_strtoull: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 2); + Changed |= setOnlyReadsMemory(F, 1); + return Changed; +- case LibFunc::strcpy: +- case LibFunc::stpcpy: +- case LibFunc::strcat: +- case LibFunc::strncat: +- case LibFunc::strncpy: +- case LibFunc::stpncpy: ++ case LibFunc_strcpy: ++ case LibFunc_stpcpy: ++ case LibFunc_strcat: ++ case LibFunc_strncat: ++ case LibFunc_strncpy: ++ case LibFunc_stpncpy: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 2); + Changed |= setOnlyReadsMemory(F, 2); + return Changed; +- case LibFunc::strxfrm: ++ case LibFunc_strxfrm: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 1); + Changed |= setDoesNotCapture(F, 2); + Changed |= setOnlyReadsMemory(F, 2); + return Changed; +- case LibFunc::strcmp: // 0,1 +- case LibFunc::strspn: // 0,1 +- case LibFunc::strncmp: // 0,1 +- case LibFunc::strcspn: // 0,1 +- case LibFunc::strcoll: // 0,1 +- case LibFunc::strcasecmp: // 0,1 +- case LibFunc::strncasecmp: // ++ case LibFunc_strcmp: // 0,1 ++ case LibFunc_strspn: // 0,1 ++ case LibFunc_strncmp: // 0,1 ++ case LibFunc_strcspn: // 0,1 ++ case LibFunc_strcoll: // 0,1 ++ case LibFunc_strcasecmp: // 0,1 ++ case LibFunc_strncasecmp: // + Changed |= setOnlyReadsMemory(F); + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 1); + Changed |= setDoesNotCapture(F, 2); + return Changed; +- case LibFunc::strstr: +- case LibFunc::strpbrk: ++ case LibFunc_strstr: ++ case LibFunc_strpbrk: + Changed |= setOnlyReadsMemory(F); + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 2); + return Changed; +- case LibFunc::strtok: +- case LibFunc::strtok_r: ++ case LibFunc_strtok: ++ case LibFunc_strtok_r: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 2); + Changed |= setOnlyReadsMemory(F, 2); + return Changed; +- case LibFunc::scanf: ++ case LibFunc_scanf: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 1); + Changed |= setOnlyReadsMemory(F, 1); + return Changed; +- case LibFunc::setbuf: +- case LibFunc::setvbuf: ++ case LibFunc_setbuf: ++ case LibFunc_setvbuf: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 1); + return Changed; +- case LibFunc::strdup: +- case LibFunc::strndup: ++ case LibFunc_strdup: ++ case LibFunc_strndup: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotAlias(F, 0); + Changed |= setDoesNotCapture(F, 1); + Changed |= setOnlyReadsMemory(F, 1); + return Changed; +- case LibFunc::stat: +- case LibFunc::statvfs: ++ case LibFunc_stat: ++ case LibFunc_statvfs: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 1); + Changed |= setDoesNotCapture(F, 2); + Changed |= setOnlyReadsMemory(F, 1); + return Changed; +- case LibFunc::sscanf: ++ case LibFunc_sscanf: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 1); + Changed |= setDoesNotCapture(F, 2); + Changed |= setOnlyReadsMemory(F, 1); + Changed |= setOnlyReadsMemory(F, 2); + return Changed; +- case LibFunc::sprintf: ++ case LibFunc_sprintf: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 1); + Changed |= setDoesNotCapture(F, 2); + Changed |= setOnlyReadsMemory(F, 2); + return Changed; +- case LibFunc::snprintf: ++ case LibFunc_snprintf: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 1); + Changed |= setDoesNotCapture(F, 3); + Changed |= setOnlyReadsMemory(F, 3); + return Changed; +- case LibFunc::setitimer: ++ case LibFunc_setitimer: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 2); + Changed |= setDoesNotCapture(F, 3); + Changed |= setOnlyReadsMemory(F, 2); + return Changed; +- case LibFunc::system: ++ case LibFunc_system: + // May throw; "system" is a valid pthread cancellation point. + Changed |= setDoesNotCapture(F, 1); + Changed |= setOnlyReadsMemory(F, 1); + return Changed; +- case LibFunc::malloc: ++ case LibFunc_malloc: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotAlias(F, 0); + return Changed; +- case LibFunc::memcmp: ++ case LibFunc_memcmp: + Changed |= setOnlyReadsMemory(F); + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 1); + Changed |= setDoesNotCapture(F, 2); + return Changed; +- case LibFunc::memchr: +- case LibFunc::memrchr: ++ case LibFunc_memchr: ++ case LibFunc_memrchr: + Changed |= setOnlyReadsMemory(F); + Changed |= setDoesNotThrow(F); + return Changed; +- case LibFunc::modf: +- case LibFunc::modff: +- case LibFunc::modfl: ++ case LibFunc_modf: ++ case LibFunc_modff: ++ case LibFunc_modfl: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 2); + return Changed; +- case LibFunc::memcpy: +- case LibFunc::mempcpy: +- case LibFunc::memccpy: +- case LibFunc::memmove: ++ case LibFunc_memcpy: ++ case LibFunc_mempcpy: ++ case LibFunc_memccpy: ++ case LibFunc_memmove: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 2); + Changed |= setOnlyReadsMemory(F, 2); + return Changed; +- case LibFunc::memcpy_chk: ++ case LibFunc_memcpy_chk: + Changed |= setDoesNotThrow(F); + return Changed; +- case LibFunc::memalign: ++ case LibFunc_memalign: + Changed |= setDoesNotAlias(F, 0); + return Changed; +- case LibFunc::mkdir: ++ case LibFunc_mkdir: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 1); + Changed |= setOnlyReadsMemory(F, 1); + return Changed; +- case LibFunc::mktime: ++ case LibFunc_mktime: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 1); + return Changed; +- case LibFunc::realloc: ++ case LibFunc_realloc: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotAlias(F, 0); + Changed |= setDoesNotCapture(F, 1); + return Changed; +- case LibFunc::read: ++ case LibFunc_read: + // May throw; "read" is a valid pthread cancellation point. + Changed |= setDoesNotCapture(F, 2); + return Changed; +- case LibFunc::rewind: ++ case LibFunc_rewind: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 1); + return Changed; +- case LibFunc::rmdir: +- case LibFunc::remove: +- case LibFunc::realpath: ++ case LibFunc_rmdir: ++ case LibFunc_remove: ++ case LibFunc_realpath: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 1); + Changed |= setOnlyReadsMemory(F, 1); + return Changed; +- case LibFunc::rename: ++ case LibFunc_rename: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 1); + Changed |= setDoesNotCapture(F, 2); + Changed |= setOnlyReadsMemory(F, 1); + Changed |= setOnlyReadsMemory(F, 2); + return Changed; +- case LibFunc::readlink: ++ case LibFunc_readlink: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 1); + Changed |= setDoesNotCapture(F, 2); + Changed |= setOnlyReadsMemory(F, 1); + return Changed; +- case LibFunc::write: ++ case LibFunc_write: + // May throw; "write" is a valid pthread cancellation point. + Changed |= setDoesNotCapture(F, 2); + Changed |= setOnlyReadsMemory(F, 2); + return Changed; +- case LibFunc::bcopy: ++ case LibFunc_bcopy: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 1); + Changed |= setDoesNotCapture(F, 2); + Changed |= setOnlyReadsMemory(F, 1); + return Changed; +- case LibFunc::bcmp: ++ case LibFunc_bcmp: + Changed |= setDoesNotThrow(F); + Changed |= setOnlyReadsMemory(F); + Changed |= setDoesNotCapture(F, 1); + Changed |= setDoesNotCapture(F, 2); + return Changed; +- case LibFunc::bzero: ++ case LibFunc_bzero: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 1); + return Changed; +- case LibFunc::calloc: ++ case LibFunc_calloc: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotAlias(F, 0); + return Changed; +- case LibFunc::chmod: +- case LibFunc::chown: ++ case LibFunc_chmod: ++ case LibFunc_chown: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 1); + Changed |= setOnlyReadsMemory(F, 1); + return Changed; +- case LibFunc::ctermid: +- case LibFunc::clearerr: +- case LibFunc::closedir: ++ case LibFunc_ctermid: ++ case LibFunc_clearerr: ++ case LibFunc_closedir: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 1); + return Changed; +- case LibFunc::atoi: +- case LibFunc::atol: +- case LibFunc::atof: +- case LibFunc::atoll: ++ case LibFunc_atoi: ++ case LibFunc_atol: ++ case LibFunc_atof: ++ case LibFunc_atoll: + Changed |= setDoesNotThrow(F); + Changed |= setOnlyReadsMemory(F); + Changed |= setDoesNotCapture(F, 1); + return Changed; +- case LibFunc::access: ++ case LibFunc_access: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 1); + Changed |= setOnlyReadsMemory(F, 1); + return Changed; +- case LibFunc::fopen: ++ case LibFunc_fopen: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotAlias(F, 0); + Changed |= setDoesNotCapture(F, 1); +@@ -363,150 +363,150 @@ bool llvm::inferLibFuncAttributes(Function &F, const TargetLibraryInfo &TLI) { + Changed |= setOnlyReadsMemory(F, 1); + Changed |= setOnlyReadsMemory(F, 2); + return Changed; +- case LibFunc::fdopen: ++ case LibFunc_fdopen: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotAlias(F, 0); + Changed |= setDoesNotCapture(F, 2); + Changed |= setOnlyReadsMemory(F, 2); + return Changed; +- case LibFunc::feof: +- case LibFunc::free: +- case LibFunc::fseek: +- case LibFunc::ftell: +- case LibFunc::fgetc: +- case LibFunc::fseeko: +- case LibFunc::ftello: +- case LibFunc::fileno: +- case LibFunc::fflush: +- case LibFunc::fclose: +- case LibFunc::fsetpos: +- case LibFunc::flockfile: +- case LibFunc::funlockfile: +- case LibFunc::ftrylockfile: ++ case LibFunc_feof: ++ case LibFunc_free: ++ case LibFunc_fseek: ++ case LibFunc_ftell: ++ case LibFunc_fgetc: ++ case LibFunc_fseeko: ++ case LibFunc_ftello: ++ case LibFunc_fileno: ++ case LibFunc_fflush: ++ case LibFunc_fclose: ++ case LibFunc_fsetpos: ++ case LibFunc_flockfile: ++ case LibFunc_funlockfile: ++ case LibFunc_ftrylockfile: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 1); + return Changed; +- case LibFunc::ferror: ++ case LibFunc_ferror: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 1); + Changed |= setOnlyReadsMemory(F); + return Changed; +- case LibFunc::fputc: +- case LibFunc::fstat: +- case LibFunc::frexp: +- case LibFunc::frexpf: +- case LibFunc::frexpl: +- case LibFunc::fstatvfs: ++ case LibFunc_fputc: ++ case LibFunc_fstat: ++ case LibFunc_frexp: ++ case LibFunc_frexpf: ++ case LibFunc_frexpl: ++ case LibFunc_fstatvfs: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 2); + return Changed; +- case LibFunc::fgets: ++ case LibFunc_fgets: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 3); + return Changed; +- case LibFunc::fread: ++ case LibFunc_fread: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 1); + Changed |= setDoesNotCapture(F, 4); + return Changed; +- case LibFunc::fwrite: ++ case LibFunc_fwrite: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 1); + Changed |= setDoesNotCapture(F, 4); + // FIXME: readonly #1? + return Changed; +- case LibFunc::fputs: ++ case LibFunc_fputs: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 1); + Changed |= setDoesNotCapture(F, 2); + Changed |= setOnlyReadsMemory(F, 1); + return Changed; +- case LibFunc::fscanf: +- case LibFunc::fprintf: ++ case LibFunc_fscanf: ++ case LibFunc_fprintf: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 1); + Changed |= setDoesNotCapture(F, 2); + Changed |= setOnlyReadsMemory(F, 2); + return Changed; +- case LibFunc::fgetpos: ++ case LibFunc_fgetpos: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 1); + Changed |= setDoesNotCapture(F, 2); + return Changed; +- case LibFunc::getc: +- case LibFunc::getlogin_r: +- case LibFunc::getc_unlocked: ++ case LibFunc_getc: ++ case LibFunc_getlogin_r: ++ case LibFunc_getc_unlocked: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 1); + return Changed; +- case LibFunc::getenv: ++ case LibFunc_getenv: + Changed |= setDoesNotThrow(F); + Changed |= setOnlyReadsMemory(F); + Changed |= setDoesNotCapture(F, 1); + return Changed; +- case LibFunc::gets: +- case LibFunc::getchar: ++ case LibFunc_gets: ++ case LibFunc_getchar: + Changed |= setDoesNotThrow(F); + return Changed; +- case LibFunc::getitimer: ++ case LibFunc_getitimer: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 2); + return Changed; +- case LibFunc::getpwnam: ++ case LibFunc_getpwnam: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 1); + Changed |= setOnlyReadsMemory(F, 1); + return Changed; +- case LibFunc::ungetc: ++ case LibFunc_ungetc: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 2); + return Changed; +- case LibFunc::uname: ++ case LibFunc_uname: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 1); + return Changed; +- case LibFunc::unlink: ++ case LibFunc_unlink: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 1); + Changed |= setOnlyReadsMemory(F, 1); + return Changed; +- case LibFunc::unsetenv: ++ case LibFunc_unsetenv: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 1); + Changed |= setOnlyReadsMemory(F, 1); + return Changed; +- case LibFunc::utime: +- case LibFunc::utimes: ++ case LibFunc_utime: ++ case LibFunc_utimes: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 1); + Changed |= setDoesNotCapture(F, 2); + Changed |= setOnlyReadsMemory(F, 1); + Changed |= setOnlyReadsMemory(F, 2); + return Changed; +- case LibFunc::putc: ++ case LibFunc_putc: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 2); + return Changed; +- case LibFunc::puts: +- case LibFunc::printf: +- case LibFunc::perror: ++ case LibFunc_puts: ++ case LibFunc_printf: ++ case LibFunc_perror: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 1); + Changed |= setOnlyReadsMemory(F, 1); + return Changed; +- case LibFunc::pread: ++ case LibFunc_pread: + // May throw; "pread" is a valid pthread cancellation point. + Changed |= setDoesNotCapture(F, 2); + return Changed; +- case LibFunc::pwrite: ++ case LibFunc_pwrite: + // May throw; "pwrite" is a valid pthread cancellation point. + Changed |= setDoesNotCapture(F, 2); + Changed |= setOnlyReadsMemory(F, 2); + return Changed; +- case LibFunc::putchar: ++ case LibFunc_putchar: + Changed |= setDoesNotThrow(F); + return Changed; +- case LibFunc::popen: ++ case LibFunc_popen: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotAlias(F, 0); + Changed |= setDoesNotCapture(F, 1); +@@ -514,132 +514,132 @@ bool llvm::inferLibFuncAttributes(Function &F, const TargetLibraryInfo &TLI) { + Changed |= setOnlyReadsMemory(F, 1); + Changed |= setOnlyReadsMemory(F, 2); + return Changed; +- case LibFunc::pclose: ++ case LibFunc_pclose: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 1); + return Changed; +- case LibFunc::vscanf: ++ case LibFunc_vscanf: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 1); + Changed |= setOnlyReadsMemory(F, 1); + return Changed; +- case LibFunc::vsscanf: ++ case LibFunc_vsscanf: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 1); + Changed |= setDoesNotCapture(F, 2); + Changed |= setOnlyReadsMemory(F, 1); + Changed |= setOnlyReadsMemory(F, 2); + return Changed; +- case LibFunc::vfscanf: ++ case LibFunc_vfscanf: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 1); + Changed |= setDoesNotCapture(F, 2); + Changed |= setOnlyReadsMemory(F, 2); + return Changed; +- case LibFunc::valloc: ++ case LibFunc_valloc: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotAlias(F, 0); + return Changed; +- case LibFunc::vprintf: ++ case LibFunc_vprintf: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 1); + Changed |= setOnlyReadsMemory(F, 1); + return Changed; +- case LibFunc::vfprintf: +- case LibFunc::vsprintf: ++ case LibFunc_vfprintf: ++ case LibFunc_vsprintf: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 1); + Changed |= setDoesNotCapture(F, 2); + Changed |= setOnlyReadsMemory(F, 2); + return Changed; +- case LibFunc::vsnprintf: ++ case LibFunc_vsnprintf: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 1); + Changed |= setDoesNotCapture(F, 3); + Changed |= setOnlyReadsMemory(F, 3); + return Changed; +- case LibFunc::open: ++ case LibFunc_open: + // May throw; "open" is a valid pthread cancellation point. + Changed |= setDoesNotCapture(F, 1); + Changed |= setOnlyReadsMemory(F, 1); + return Changed; +- case LibFunc::opendir: ++ case LibFunc_opendir: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotAlias(F, 0); + Changed |= setDoesNotCapture(F, 1); + Changed |= setOnlyReadsMemory(F, 1); + return Changed; +- case LibFunc::tmpfile: ++ case LibFunc_tmpfile: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotAlias(F, 0); + return Changed; +- case LibFunc::times: ++ case LibFunc_times: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 1); + return Changed; +- case LibFunc::htonl: +- case LibFunc::htons: +- case LibFunc::ntohl: +- case LibFunc::ntohs: ++ case LibFunc_htonl: ++ case LibFunc_htons: ++ case LibFunc_ntohl: ++ case LibFunc_ntohs: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotAccessMemory(F); + return Changed; +- case LibFunc::lstat: ++ case LibFunc_lstat: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 1); + Changed |= setDoesNotCapture(F, 2); + Changed |= setOnlyReadsMemory(F, 1); + return Changed; +- case LibFunc::lchown: ++ case LibFunc_lchown: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 1); + Changed |= setOnlyReadsMemory(F, 1); + return Changed; +- case LibFunc::qsort: ++ case LibFunc_qsort: + // May throw; places call through function pointer. + Changed |= setDoesNotCapture(F, 4); + return Changed; +- case LibFunc::dunder_strdup: +- case LibFunc::dunder_strndup: ++ case LibFunc_dunder_strdup: ++ case LibFunc_dunder_strndup: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotAlias(F, 0); + Changed |= setDoesNotCapture(F, 1); + Changed |= setOnlyReadsMemory(F, 1); + return Changed; +- case LibFunc::dunder_strtok_r: ++ case LibFunc_dunder_strtok_r: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 2); + Changed |= setOnlyReadsMemory(F, 2); + return Changed; +- case LibFunc::under_IO_getc: ++ case LibFunc_under_IO_getc: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 1); + return Changed; +- case LibFunc::under_IO_putc: ++ case LibFunc_under_IO_putc: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 2); + return Changed; +- case LibFunc::dunder_isoc99_scanf: ++ case LibFunc_dunder_isoc99_scanf: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 1); + Changed |= setOnlyReadsMemory(F, 1); + return Changed; +- case LibFunc::stat64: +- case LibFunc::lstat64: +- case LibFunc::statvfs64: ++ case LibFunc_stat64: ++ case LibFunc_lstat64: ++ case LibFunc_statvfs64: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 1); + Changed |= setDoesNotCapture(F, 2); + Changed |= setOnlyReadsMemory(F, 1); + return Changed; +- case LibFunc::dunder_isoc99_sscanf: ++ case LibFunc_dunder_isoc99_sscanf: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 1); + Changed |= setDoesNotCapture(F, 2); + Changed |= setOnlyReadsMemory(F, 1); + Changed |= setOnlyReadsMemory(F, 2); + return Changed; +- case LibFunc::fopen64: ++ case LibFunc_fopen64: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotAlias(F, 0); + Changed |= setDoesNotCapture(F, 1); +@@ -647,26 +647,26 @@ bool llvm::inferLibFuncAttributes(Function &F, const TargetLibraryInfo &TLI) { + Changed |= setOnlyReadsMemory(F, 1); + Changed |= setOnlyReadsMemory(F, 2); + return Changed; +- case LibFunc::fseeko64: +- case LibFunc::ftello64: ++ case LibFunc_fseeko64: ++ case LibFunc_ftello64: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 1); + return Changed; +- case LibFunc::tmpfile64: ++ case LibFunc_tmpfile64: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotAlias(F, 0); + return Changed; +- case LibFunc::fstat64: +- case LibFunc::fstatvfs64: ++ case LibFunc_fstat64: ++ case LibFunc_fstatvfs64: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 2); + return Changed; +- case LibFunc::open64: ++ case LibFunc_open64: + // May throw; "open" is a valid pthread cancellation point. + Changed |= setDoesNotCapture(F, 1); + Changed |= setOnlyReadsMemory(F, 1); + return Changed; +- case LibFunc::gettimeofday: ++ case LibFunc_gettimeofday: + // Currently some platforms have the restrict keyword on the arguments to + // gettimeofday. To be conservative, do not add noalias to gettimeofday's + // arguments. +@@ -674,29 +674,29 @@ bool llvm::inferLibFuncAttributes(Function &F, const TargetLibraryInfo &TLI) { + Changed |= setDoesNotCapture(F, 1); + Changed |= setDoesNotCapture(F, 2); + return Changed; +- case LibFunc::Znwj: // new(unsigned int) +- case LibFunc::Znwm: // new(unsigned long) +- case LibFunc::Znaj: // new[](unsigned int) +- case LibFunc::Znam: // new[](unsigned long) +- case LibFunc::msvc_new_int: // new(unsigned int) +- case LibFunc::msvc_new_longlong: // new(unsigned long long) +- case LibFunc::msvc_new_array_int: // new[](unsigned int) +- case LibFunc::msvc_new_array_longlong: // new[](unsigned long long) ++ case LibFunc_Znwj: // new(unsigned int) ++ case LibFunc_Znwm: // new(unsigned long) ++ case LibFunc_Znaj: // new[](unsigned int) ++ case LibFunc_Znam: // new[](unsigned long) ++ case LibFunc_msvc_new_int: // new(unsigned int) ++ case LibFunc_msvc_new_longlong: // new(unsigned long long) ++ case LibFunc_msvc_new_array_int: // new[](unsigned int) ++ case LibFunc_msvc_new_array_longlong: // new[](unsigned long long) + // Operator new always returns a nonnull noalias pointer + Changed |= setNonNull(F, AttributeSet::ReturnIndex); + Changed |= setDoesNotAlias(F, AttributeSet::ReturnIndex); + return Changed; + //TODO: add LibFunc entries for: +- //case LibFunc::memset_pattern4: +- //case LibFunc::memset_pattern8: +- case LibFunc::memset_pattern16: ++ //case LibFunc_memset_pattern4: ++ //case LibFunc_memset_pattern8: ++ case LibFunc_memset_pattern16: + Changed |= setOnlyAccessesArgMemory(F); + Changed |= setDoesNotCapture(F, 1); + Changed |= setDoesNotCapture(F, 2); + Changed |= setOnlyReadsMemory(F, 2); + return Changed; + // int __nvvm_reflect(const char *) +- case LibFunc::nvvm_reflect: ++ case LibFunc_nvvm_reflect: + Changed |= setDoesNotAccessMemory(F); + Changed |= setDoesNotThrow(F); + return Changed; +@@ -717,7 +717,7 @@ Value *llvm::castToCStr(Value *V, IRBuilder<> &B) { + + Value *llvm::emitStrLen(Value *Ptr, IRBuilder<> &B, const DataLayout &DL, + const TargetLibraryInfo *TLI) { +- if (!TLI->has(LibFunc::strlen)) ++ if (!TLI->has(LibFunc_strlen)) + return nullptr; + + Module *M = B.GetInsertBlock()->getModule(); +@@ -734,7 +734,7 @@ Value *llvm::emitStrLen(Value *Ptr, IRBuilder<> &B, const DataLayout &DL, + + Value *llvm::emitStrChr(Value *Ptr, char C, IRBuilder<> &B, + const TargetLibraryInfo *TLI) { +- if (!TLI->has(LibFunc::strchr)) ++ if (!TLI->has(LibFunc_strchr)) + return nullptr; + + Module *M = B.GetInsertBlock()->getModule(); +@@ -752,7 +752,7 @@ Value *llvm::emitStrChr(Value *Ptr, char C, IRBuilder<> &B, + + Value *llvm::emitStrNCmp(Value *Ptr1, Value *Ptr2, Value *Len, IRBuilder<> &B, + const DataLayout &DL, const TargetLibraryInfo *TLI) { +- if (!TLI->has(LibFunc::strncmp)) ++ if (!TLI->has(LibFunc_strncmp)) + return nullptr; + + Module *M = B.GetInsertBlock()->getModule(); +@@ -772,7 +772,7 @@ Value *llvm::emitStrNCmp(Value *Ptr1, Value *Ptr2, Value *Len, IRBuilder<> &B, + + Value *llvm::emitStrCpy(Value *Dst, Value *Src, IRBuilder<> &B, + const TargetLibraryInfo *TLI, StringRef Name) { +- if (!TLI->has(LibFunc::strcpy)) ++ if (!TLI->has(LibFunc_strcpy)) + return nullptr; + + Module *M = B.GetInsertBlock()->getModule(); +@@ -788,7 +788,7 @@ Value *llvm::emitStrCpy(Value *Dst, Value *Src, IRBuilder<> &B, + + Value *llvm::emitStrNCpy(Value *Dst, Value *Src, Value *Len, IRBuilder<> &B, + const TargetLibraryInfo *TLI, StringRef Name) { +- if (!TLI->has(LibFunc::strncpy)) ++ if (!TLI->has(LibFunc_strncpy)) + return nullptr; + + Module *M = B.GetInsertBlock()->getModule(); +@@ -806,7 +806,7 @@ Value *llvm::emitStrNCpy(Value *Dst, Value *Src, Value *Len, IRBuilder<> &B, + Value *llvm::emitMemCpyChk(Value *Dst, Value *Src, Value *Len, Value *ObjSize, + IRBuilder<> &B, const DataLayout &DL, + const TargetLibraryInfo *TLI) { +- if (!TLI->has(LibFunc::memcpy_chk)) ++ if (!TLI->has(LibFunc_memcpy_chk)) + return nullptr; + + Module *M = B.GetInsertBlock()->getModule(); +@@ -828,7 +828,7 @@ Value *llvm::emitMemCpyChk(Value *Dst, Value *Src, Value *Len, Value *ObjSize, + + Value *llvm::emitMemChr(Value *Ptr, Value *Val, Value *Len, IRBuilder<> &B, + const DataLayout &DL, const TargetLibraryInfo *TLI) { +- if (!TLI->has(LibFunc::memchr)) ++ if (!TLI->has(LibFunc_memchr)) + return nullptr; + + Module *M = B.GetInsertBlock()->getModule(); +@@ -847,7 +847,7 @@ Value *llvm::emitMemChr(Value *Ptr, Value *Val, Value *Len, IRBuilder<> &B, + + Value *llvm::emitMemCmp(Value *Ptr1, Value *Ptr2, Value *Len, IRBuilder<> &B, + const DataLayout &DL, const TargetLibraryInfo *TLI) { +- if (!TLI->has(LibFunc::memcmp)) ++ if (!TLI->has(LibFunc_memcmp)) + return nullptr; + + Module *M = B.GetInsertBlock()->getModule(); +@@ -914,7 +914,7 @@ Value *llvm::emitBinaryFloatFnCall(Value *Op1, Value *Op2, StringRef Name, + + Value *llvm::emitPutChar(Value *Char, IRBuilder<> &B, + const TargetLibraryInfo *TLI) { +- if (!TLI->has(LibFunc::putchar)) ++ if (!TLI->has(LibFunc_putchar)) + return nullptr; + + Module *M = B.GetInsertBlock()->getModule(); +@@ -934,7 +934,7 @@ Value *llvm::emitPutChar(Value *Char, IRBuilder<> &B, + + Value *llvm::emitPutS(Value *Str, IRBuilder<> &B, + const TargetLibraryInfo *TLI) { +- if (!TLI->has(LibFunc::puts)) ++ if (!TLI->has(LibFunc_puts)) + return nullptr; + + Module *M = B.GetInsertBlock()->getModule(); +@@ -949,7 +949,7 @@ Value *llvm::emitPutS(Value *Str, IRBuilder<> &B, + + Value *llvm::emitFPutC(Value *Char, Value *File, IRBuilder<> &B, + const TargetLibraryInfo *TLI) { +- if (!TLI->has(LibFunc::fputc)) ++ if (!TLI->has(LibFunc_fputc)) + return nullptr; + + Module *M = B.GetInsertBlock()->getModule(); +@@ -968,11 +968,11 @@ Value *llvm::emitFPutC(Value *Char, Value *File, IRBuilder<> &B, + + Value *llvm::emitFPutS(Value *Str, Value *File, IRBuilder<> &B, + const TargetLibraryInfo *TLI) { +- if (!TLI->has(LibFunc::fputs)) ++ if (!TLI->has(LibFunc_fputs)) + return nullptr; + + Module *M = B.GetInsertBlock()->getModule(); +- StringRef FPutsName = TLI->getName(LibFunc::fputs); ++ StringRef FPutsName = TLI->getName(LibFunc_fputs); + Constant *F = M->getOrInsertFunction( + FPutsName, B.getInt32Ty(), B.getInt8PtrTy(), File->getType(), nullptr); + if (File->getType()->isPointerTy()) +@@ -986,12 +986,12 @@ Value *llvm::emitFPutS(Value *Str, Value *File, IRBuilder<> &B, + + Value *llvm::emitFWrite(Value *Ptr, Value *Size, Value *File, IRBuilder<> &B, + const DataLayout &DL, const TargetLibraryInfo *TLI) { +- if (!TLI->has(LibFunc::fwrite)) ++ if (!TLI->has(LibFunc_fwrite)) + return nullptr; + + Module *M = B.GetInsertBlock()->getModule(); + LLVMContext &Context = B.GetInsertBlock()->getContext(); +- StringRef FWriteName = TLI->getName(LibFunc::fwrite); ++ StringRef FWriteName = TLI->getName(LibFunc_fwrite); + Constant *F = M->getOrInsertFunction( + FWriteName, DL.getIntPtrType(Context), B.getInt8PtrTy(), + DL.getIntPtrType(Context), DL.getIntPtrType(Context), File->getType(), +diff --git a/lib/Transforms/Utils/LibCallsShrinkWrap.cpp b/lib/Transforms/Utils/LibCallsShrinkWrap.cpp +index d97cd7582ea..fe93d6927c6 100644 +--- a/lib/Transforms/Utils/LibCallsShrinkWrap.cpp ++++ b/lib/Transforms/Utils/LibCallsShrinkWrap.cpp +@@ -100,12 +100,12 @@ private: + bool perform(CallInst *CI); + void checkCandidate(CallInst &CI); + void shrinkWrapCI(CallInst *CI, Value *Cond); +- bool performCallDomainErrorOnly(CallInst *CI, const LibFunc::Func &Func); +- bool performCallErrors(CallInst *CI, const LibFunc::Func &Func); +- bool performCallRangeErrorOnly(CallInst *CI, const LibFunc::Func &Func); +- Value *generateOneRangeCond(CallInst *CI, const LibFunc::Func &Func); +- Value *generateTwoRangeCond(CallInst *CI, const LibFunc::Func &Func); +- Value *generateCondForPow(CallInst *CI, const LibFunc::Func &Func); ++ bool performCallDomainErrorOnly(CallInst *CI, const LibFunc &Func); ++ bool performCallErrors(CallInst *CI, const LibFunc &Func); ++ bool performCallRangeErrorOnly(CallInst *CI, const LibFunc &Func); ++ Value *generateOneRangeCond(CallInst *CI, const LibFunc &Func); ++ Value *generateTwoRangeCond(CallInst *CI, const LibFunc &Func); ++ Value *generateCondForPow(CallInst *CI, const LibFunc &Func); + + // Create an OR of two conditions. + Value *createOrCond(CallInst *CI, CmpInst::Predicate Cmp, float Val, +@@ -141,44 +141,44 @@ private: + + // Perform the transformation to calls with errno set by domain error. + bool LibCallsShrinkWrap::performCallDomainErrorOnly(CallInst *CI, +- const LibFunc::Func &Func) { ++ const LibFunc &Func) { + Value *Cond = nullptr; + + switch (Func) { +- case LibFunc::acos: // DomainError: (x < -1 || x > 1) +- case LibFunc::acosf: // Same as acos +- case LibFunc::acosl: // Same as acos +- case LibFunc::asin: // DomainError: (x < -1 || x > 1) +- case LibFunc::asinf: // Same as asin +- case LibFunc::asinl: // Same as asin ++ case LibFunc_acos: // DomainError: (x < -1 || x > 1) ++ case LibFunc_acosf: // Same as acos ++ case LibFunc_acosl: // Same as acos ++ case LibFunc_asin: // DomainError: (x < -1 || x > 1) ++ case LibFunc_asinf: // Same as asin ++ case LibFunc_asinl: // Same as asin + { + ++NumWrappedTwoCond; + Cond = createOrCond(CI, CmpInst::FCMP_OLT, -1.0f, CmpInst::FCMP_OGT, 1.0f); + break; + } +- case LibFunc::cos: // DomainError: (x == +inf || x == -inf) +- case LibFunc::cosf: // Same as cos +- case LibFunc::cosl: // Same as cos +- case LibFunc::sin: // DomainError: (x == +inf || x == -inf) +- case LibFunc::sinf: // Same as sin +- case LibFunc::sinl: // Same as sin ++ case LibFunc_cos: // DomainError: (x == +inf || x == -inf) ++ case LibFunc_cosf: // Same as cos ++ case LibFunc_cosl: // Same as cos ++ case LibFunc_sin: // DomainError: (x == +inf || x == -inf) ++ case LibFunc_sinf: // Same as sin ++ case LibFunc_sinl: // Same as sin + { + ++NumWrappedTwoCond; + Cond = createOrCond(CI, CmpInst::FCMP_OEQ, INFINITY, CmpInst::FCMP_OEQ, + -INFINITY); + break; + } +- case LibFunc::acosh: // DomainError: (x < 1) +- case LibFunc::acoshf: // Same as acosh +- case LibFunc::acoshl: // Same as acosh ++ case LibFunc_acosh: // DomainError: (x < 1) ++ case LibFunc_acoshf: // Same as acosh ++ case LibFunc_acoshl: // Same as acosh + { + ++NumWrappedOneCond; + Cond = createCond(CI, CmpInst::FCMP_OLT, 1.0f); + break; + } +- case LibFunc::sqrt: // DomainError: (x < 0) +- case LibFunc::sqrtf: // Same as sqrt +- case LibFunc::sqrtl: // Same as sqrt ++ case LibFunc_sqrt: // DomainError: (x < 0) ++ case LibFunc_sqrtf: // Same as sqrt ++ case LibFunc_sqrtl: // Same as sqrt + { + ++NumWrappedOneCond; + Cond = createCond(CI, CmpInst::FCMP_OLT, 0.0f); +@@ -193,31 +193,31 @@ bool LibCallsShrinkWrap::performCallDomainErrorOnly(CallInst *CI, + + // Perform the transformation to calls with errno set by range error. + bool LibCallsShrinkWrap::performCallRangeErrorOnly(CallInst *CI, +- const LibFunc::Func &Func) { ++ const LibFunc &Func) { + Value *Cond = nullptr; + + switch (Func) { +- case LibFunc::cosh: +- case LibFunc::coshf: +- case LibFunc::coshl: +- case LibFunc::exp: +- case LibFunc::expf: +- case LibFunc::expl: +- case LibFunc::exp10: +- case LibFunc::exp10f: +- case LibFunc::exp10l: +- case LibFunc::exp2: +- case LibFunc::exp2f: +- case LibFunc::exp2l: +- case LibFunc::sinh: +- case LibFunc::sinhf: +- case LibFunc::sinhl: { ++ case LibFunc_cosh: ++ case LibFunc_coshf: ++ case LibFunc_coshl: ++ case LibFunc_exp: ++ case LibFunc_expf: ++ case LibFunc_expl: ++ case LibFunc_exp10: ++ case LibFunc_exp10f: ++ case LibFunc_exp10l: ++ case LibFunc_exp2: ++ case LibFunc_exp2f: ++ case LibFunc_exp2l: ++ case LibFunc_sinh: ++ case LibFunc_sinhf: ++ case LibFunc_sinhl: { + Cond = generateTwoRangeCond(CI, Func); + break; + } +- case LibFunc::expm1: // RangeError: (709, inf) +- case LibFunc::expm1f: // RangeError: (88, inf) +- case LibFunc::expm1l: // RangeError: (11356, inf) ++ case LibFunc_expm1: // RangeError: (709, inf) ++ case LibFunc_expm1f: // RangeError: (88, inf) ++ case LibFunc_expm1l: // RangeError: (11356, inf) + { + Cond = generateOneRangeCond(CI, Func); + break; +@@ -231,15 +231,15 @@ bool LibCallsShrinkWrap::performCallRangeErrorOnly(CallInst *CI, + + // Perform the transformation to calls with errno set by combination of errors. + bool LibCallsShrinkWrap::performCallErrors(CallInst *CI, +- const LibFunc::Func &Func) { ++ const LibFunc &Func) { + Value *Cond = nullptr; + + switch (Func) { +- case LibFunc::atanh: // DomainError: (x < -1 || x > 1) ++ case LibFunc_atanh: // DomainError: (x < -1 || x > 1) + // PoleError: (x == -1 || x == 1) + // Overall Cond: (x <= -1 || x >= 1) +- case LibFunc::atanhf: // Same as atanh +- case LibFunc::atanhl: // Same as atanh ++ case LibFunc_atanhf: // Same as atanh ++ case LibFunc_atanhl: // Same as atanh + { + if (!LibCallsShrinkWrapDoDomainError || !LibCallsShrinkWrapDoPoleError) + return false; +@@ -247,20 +247,20 @@ bool LibCallsShrinkWrap::performCallErrors(CallInst *CI, + Cond = createOrCond(CI, CmpInst::FCMP_OLE, -1.0f, CmpInst::FCMP_OGE, 1.0f); + break; + } +- case LibFunc::log: // DomainError: (x < 0) ++ case LibFunc_log: // DomainError: (x < 0) + // PoleError: (x == 0) + // Overall Cond: (x <= 0) +- case LibFunc::logf: // Same as log +- case LibFunc::logl: // Same as log +- case LibFunc::log10: // Same as log +- case LibFunc::log10f: // Same as log +- case LibFunc::log10l: // Same as log +- case LibFunc::log2: // Same as log +- case LibFunc::log2f: // Same as log +- case LibFunc::log2l: // Same as log +- case LibFunc::logb: // Same as log +- case LibFunc::logbf: // Same as log +- case LibFunc::logbl: // Same as log ++ case LibFunc_logf: // Same as log ++ case LibFunc_logl: // Same as log ++ case LibFunc_log10: // Same as log ++ case LibFunc_log10f: // Same as log ++ case LibFunc_log10l: // Same as log ++ case LibFunc_log2: // Same as log ++ case LibFunc_log2f: // Same as log ++ case LibFunc_log2l: // Same as log ++ case LibFunc_logb: // Same as log ++ case LibFunc_logbf: // Same as log ++ case LibFunc_logbl: // Same as log + { + if (!LibCallsShrinkWrapDoDomainError || !LibCallsShrinkWrapDoPoleError) + return false; +@@ -268,11 +268,11 @@ bool LibCallsShrinkWrap::performCallErrors(CallInst *CI, + Cond = createCond(CI, CmpInst::FCMP_OLE, 0.0f); + break; + } +- case LibFunc::log1p: // DomainError: (x < -1) ++ case LibFunc_log1p: // DomainError: (x < -1) + // PoleError: (x == -1) + // Overall Cond: (x <= -1) +- case LibFunc::log1pf: // Same as log1p +- case LibFunc::log1pl: // Same as log1p ++ case LibFunc_log1pf: // Same as log1p ++ case LibFunc_log1pl: // Same as log1p + { + if (!LibCallsShrinkWrapDoDomainError || !LibCallsShrinkWrapDoPoleError) + return false; +@@ -280,11 +280,11 @@ bool LibCallsShrinkWrap::performCallErrors(CallInst *CI, + Cond = createCond(CI, CmpInst::FCMP_OLE, -1.0f); + break; + } +- case LibFunc::pow: // DomainError: x < 0 and y is noninteger ++ case LibFunc_pow: // DomainError: x < 0 and y is noninteger + // PoleError: x == 0 and y < 0 + // RangeError: overflow or underflow +- case LibFunc::powf: +- case LibFunc::powl: { ++ case LibFunc_powf: ++ case LibFunc_powl: { + if (!LibCallsShrinkWrapDoDomainError || !LibCallsShrinkWrapDoPoleError || + !LibCallsShrinkWrapDoRangeError) + return false; +@@ -313,7 +313,7 @@ void LibCallsShrinkWrap::checkCandidate(CallInst &CI) { + if (!CI.use_empty()) + return; + +- LibFunc::Func Func; ++ LibFunc Func; + Function *Callee = CI.getCalledFunction(); + if (!Callee) + return; +@@ -333,16 +333,16 @@ void LibCallsShrinkWrap::checkCandidate(CallInst &CI) { + + // Generate the upper bound condition for RangeError. + Value *LibCallsShrinkWrap::generateOneRangeCond(CallInst *CI, +- const LibFunc::Func &Func) { ++ const LibFunc &Func) { + float UpperBound; + switch (Func) { +- case LibFunc::expm1: // RangeError: (709, inf) ++ case LibFunc_expm1: // RangeError: (709, inf) + UpperBound = 709.0f; + break; +- case LibFunc::expm1f: // RangeError: (88, inf) ++ case LibFunc_expm1f: // RangeError: (88, inf) + UpperBound = 88.0f; + break; +- case LibFunc::expm1l: // RangeError: (11356, inf) ++ case LibFunc_expm1l: // RangeError: (11356, inf) + UpperBound = 11356.0f; + break; + default: +@@ -355,57 +355,57 @@ Value *LibCallsShrinkWrap::generateOneRangeCond(CallInst *CI, + + // Generate the lower and upper bound condition for RangeError. + Value *LibCallsShrinkWrap::generateTwoRangeCond(CallInst *CI, +- const LibFunc::Func &Func) { ++ const LibFunc &Func) { + float UpperBound, LowerBound; + switch (Func) { +- case LibFunc::cosh: // RangeError: (x < -710 || x > 710) +- case LibFunc::sinh: // Same as cosh ++ case LibFunc_cosh: // RangeError: (x < -710 || x > 710) ++ case LibFunc_sinh: // Same as cosh + LowerBound = -710.0f; + UpperBound = 710.0f; + break; +- case LibFunc::coshf: // RangeError: (x < -89 || x > 89) +- case LibFunc::sinhf: // Same as coshf ++ case LibFunc_coshf: // RangeError: (x < -89 || x > 89) ++ case LibFunc_sinhf: // Same as coshf + LowerBound = -89.0f; + UpperBound = 89.0f; + break; +- case LibFunc::coshl: // RangeError: (x < -11357 || x > 11357) +- case LibFunc::sinhl: // Same as coshl ++ case LibFunc_coshl: // RangeError: (x < -11357 || x > 11357) ++ case LibFunc_sinhl: // Same as coshl + LowerBound = -11357.0f; + UpperBound = 11357.0f; + break; +- case LibFunc::exp: // RangeError: (x < -745 || x > 709) ++ case LibFunc_exp: // RangeError: (x < -745 || x > 709) + LowerBound = -745.0f; + UpperBound = 709.0f; + break; +- case LibFunc::expf: // RangeError: (x < -103 || x > 88) ++ case LibFunc_expf: // RangeError: (x < -103 || x > 88) + LowerBound = -103.0f; + UpperBound = 88.0f; + break; +- case LibFunc::expl: // RangeError: (x < -11399 || x > 11356) ++ case LibFunc_expl: // RangeError: (x < -11399 || x > 11356) + LowerBound = -11399.0f; + UpperBound = 11356.0f; + break; +- case LibFunc::exp10: // RangeError: (x < -323 || x > 308) ++ case LibFunc_exp10: // RangeError: (x < -323 || x > 308) + LowerBound = -323.0f; + UpperBound = 308.0f; + break; +- case LibFunc::exp10f: // RangeError: (x < -45 || x > 38) ++ case LibFunc_exp10f: // RangeError: (x < -45 || x > 38) + LowerBound = -45.0f; + UpperBound = 38.0f; + break; +- case LibFunc::exp10l: // RangeError: (x < -4950 || x > 4932) ++ case LibFunc_exp10l: // RangeError: (x < -4950 || x > 4932) + LowerBound = -4950.0f; + UpperBound = 4932.0f; + break; +- case LibFunc::exp2: // RangeError: (x < -1074 || x > 1023) ++ case LibFunc_exp2: // RangeError: (x < -1074 || x > 1023) + LowerBound = -1074.0f; + UpperBound = 1023.0f; + break; +- case LibFunc::exp2f: // RangeError: (x < -149 || x > 127) ++ case LibFunc_exp2f: // RangeError: (x < -149 || x > 127) + LowerBound = -149.0f; + UpperBound = 127.0f; + break; +- case LibFunc::exp2l: // RangeError: (x < -16445 || x > 11383) ++ case LibFunc_exp2l: // RangeError: (x < -16445 || x > 11383) + LowerBound = -16445.0f; + UpperBound = 11383.0f; + break; +@@ -434,9 +434,9 @@ Value *LibCallsShrinkWrap::generateTwoRangeCond(CallInst *CI, + // (i.e. we might invoke the calls that will not set the errno.). + // + Value *LibCallsShrinkWrap::generateCondForPow(CallInst *CI, +- const LibFunc::Func &Func) { +- // FIXME: LibFunc::powf and powl TBD. +- if (Func != LibFunc::pow) { ++ const LibFunc &Func) { ++ // FIXME: LibFunc_powf and powl TBD. ++ if (Func != LibFunc_pow) { + DEBUG(dbgs() << "Not handled powf() and powl()\n"); + return nullptr; + } +@@ -516,7 +516,7 @@ void LibCallsShrinkWrap::shrinkWrapCI(CallInst *CI, Value *Cond) { + + // Perform the transformation to a single candidate. + bool LibCallsShrinkWrap::perform(CallInst *CI) { +- LibFunc::Func Func; ++ LibFunc Func; + Function *Callee = CI->getCalledFunction(); + assert(Callee && "perform() should apply to a non-empty callee"); + TLI.getLibFunc(*Callee, Func); +diff --git a/lib/Transforms/Utils/Local.cpp b/lib/Transforms/Utils/Local.cpp +index 6e4174aa0cd..9e217fec20c 100644 +--- a/lib/Transforms/Utils/Local.cpp ++++ b/lib/Transforms/Utils/Local.cpp +@@ -2068,7 +2068,7 @@ bool llvm::recognizeBSwapOrBitReverseIdiom( + void llvm::maybeMarkSanitizerLibraryCallNoBuiltin( + CallInst *CI, const TargetLibraryInfo *TLI) { + Function *F = CI->getCalledFunction(); +- LibFunc::Func Func; ++ LibFunc Func; + if (F && !F->hasLocalLinkage() && F->hasName() && + TLI->getLibFunc(F->getName(), Func) && TLI->hasOptimizedCodeGen(Func) && + !F->doesNotAccessMemory()) +diff --git a/lib/Transforms/Utils/SimplifyLibCalls.cpp b/lib/Transforms/Utils/SimplifyLibCalls.cpp +index 8eaeb1073a7..81c8f61fd35 100644 +--- a/lib/Transforms/Utils/SimplifyLibCalls.cpp ++++ b/lib/Transforms/Utils/SimplifyLibCalls.cpp +@@ -51,9 +51,9 @@ static cl::opt + // Helper Functions + //===----------------------------------------------------------------------===// + +-static bool ignoreCallingConv(LibFunc::Func Func) { +- return Func == LibFunc::abs || Func == LibFunc::labs || +- Func == LibFunc::llabs || Func == LibFunc::strlen; ++static bool ignoreCallingConv(LibFunc Func) { ++ return Func == LibFunc_abs || Func == LibFunc_labs || ++ Func == LibFunc_llabs || Func == LibFunc_strlen; + } + + static bool isCallingConvCCompatible(CallInst *CI) { +@@ -123,8 +123,8 @@ static bool callHasFloatingPointArgument(const CallInst *CI) { + /// \brief Check whether the overloaded unary floating point function + /// corresponding to \a Ty is available. + static bool hasUnaryFloatFn(const TargetLibraryInfo *TLI, Type *Ty, +- LibFunc::Func DoubleFn, LibFunc::Func FloatFn, +- LibFunc::Func LongDoubleFn) { ++ LibFunc DoubleFn, LibFunc FloatFn, ++ LibFunc LongDoubleFn) { + switch (Ty->getTypeID()) { + case Type::FloatTyID: + return TLI->has(FloatFn); +@@ -811,7 +811,7 @@ Value *LibCallSimplifier::optimizeMemMove(CallInst *CI, IRBuilder<> &B) { + // functions be moved here? + static Value *emitCalloc(Value *Num, Value *Size, const AttributeSet &Attrs, + IRBuilder<> &B, const TargetLibraryInfo &TLI) { +- LibFunc::Func Func; ++ LibFunc Func; + if (!TLI.getLibFunc("calloc", Func) || !TLI.has(Func)) + return nullptr; + +@@ -846,9 +846,9 @@ static Value *foldMallocMemset(CallInst *Memset, IRBuilder<> &B, + + // Is the inner call really malloc()? + Function *InnerCallee = Malloc->getCalledFunction(); +- LibFunc::Func Func; ++ LibFunc Func; + if (!TLI.getLibFunc(*InnerCallee, Func) || !TLI.has(Func) || +- Func != LibFunc::malloc) ++ Func != LibFunc_malloc) + return nullptr; + + // The memset must cover the same number of bytes that are malloc'd. +@@ -1041,9 +1041,9 @@ Value *LibCallSimplifier::optimizePow(CallInst *CI, IRBuilder<> &B) { + if (ConstantFP *Op1C = dyn_cast(Op1)) { + // pow(10.0, x) -> exp10(x) + if (Op1C->isExactlyValue(10.0) && +- hasUnaryFloatFn(TLI, Op1->getType(), LibFunc::exp10, LibFunc::exp10f, +- LibFunc::exp10l)) +- return emitUnaryFloatFnCall(Op2, TLI->getName(LibFunc::exp10), B, ++ hasUnaryFloatFn(TLI, Op1->getType(), LibFunc_exp10, LibFunc_exp10f, ++ LibFunc_exp10l)) ++ return emitUnaryFloatFnCall(Op2, TLI->getName(LibFunc_exp10), B, + Callee->getAttributes()); + } + +@@ -1055,10 +1055,10 @@ Value *LibCallSimplifier::optimizePow(CallInst *CI, IRBuilder<> &B) { + // pow(exp(x), y) = pow(inf, 0.001) = inf, whereas exp(x*y) = exp(1). + auto *OpC = dyn_cast(Op1); + if (OpC && OpC->hasUnsafeAlgebra() && CI->hasUnsafeAlgebra()) { +- LibFunc::Func Func; ++ LibFunc Func; + Function *OpCCallee = OpC->getCalledFunction(); + if (OpCCallee && TLI->getLibFunc(OpCCallee->getName(), Func) && +- TLI->has(Func) && (Func == LibFunc::exp || Func == LibFunc::exp2)) { ++ TLI->has(Func) && (Func == LibFunc_exp || Func == LibFunc_exp2)) { + IRBuilder<>::FastMathFlagGuard Guard(B); + B.setFastMathFlags(CI->getFastMathFlags()); + Value *FMul = B.CreateFMul(OpC->getArgOperand(0), Op2, "mul"); +@@ -1075,8 +1075,8 @@ Value *LibCallSimplifier::optimizePow(CallInst *CI, IRBuilder<> &B) { + return ConstantFP::get(CI->getType(), 1.0); + + if (Op2C->isExactlyValue(-0.5) && +- hasUnaryFloatFn(TLI, Op2->getType(), LibFunc::sqrt, LibFunc::sqrtf, +- LibFunc::sqrtl)) { ++ hasUnaryFloatFn(TLI, Op2->getType(), LibFunc_sqrt, LibFunc_sqrtf, ++ LibFunc_sqrtl)) { + // If -ffast-math: + // pow(x, -0.5) -> 1.0 / sqrt(x) + if (CI->hasUnsafeAlgebra()) { +@@ -1085,7 +1085,7 @@ Value *LibCallSimplifier::optimizePow(CallInst *CI, IRBuilder<> &B) { + + // Here we cannot lower to an intrinsic because C99 sqrt() and llvm.sqrt + // are not guaranteed to have the same semantics. +- Value *Sqrt = emitUnaryFloatFnCall(Op1, TLI->getName(LibFunc::sqrt), B, ++ Value *Sqrt = emitUnaryFloatFnCall(Op1, TLI->getName(LibFunc_sqrt), B, + Callee->getAttributes()); + + return B.CreateFDiv(ConstantFP::get(CI->getType(), 1.0), Sqrt, "sqrtrecip"); +@@ -1093,10 +1093,10 @@ Value *LibCallSimplifier::optimizePow(CallInst *CI, IRBuilder<> &B) { + } + + if (Op2C->isExactlyValue(0.5) && +- hasUnaryFloatFn(TLI, Op2->getType(), LibFunc::sqrt, LibFunc::sqrtf, +- LibFunc::sqrtl) && +- hasUnaryFloatFn(TLI, Op2->getType(), LibFunc::fabs, LibFunc::fabsf, +- LibFunc::fabsl)) { ++ hasUnaryFloatFn(TLI, Op2->getType(), LibFunc_sqrt, LibFunc_sqrtf, ++ LibFunc_sqrtl) && ++ hasUnaryFloatFn(TLI, Op2->getType(), LibFunc_fabs, LibFunc_fabsf, ++ LibFunc_fabsl)) { + + // In -ffast-math, pow(x, 0.5) -> sqrt(x). + if (CI->hasUnsafeAlgebra()) { +@@ -1105,7 +1105,7 @@ Value *LibCallSimplifier::optimizePow(CallInst *CI, IRBuilder<> &B) { + + // Unlike other math intrinsics, sqrt has differerent semantics + // from the libc function. See LangRef for details. +- return emitUnaryFloatFnCall(Op1, TLI->getName(LibFunc::sqrt), B, ++ return emitUnaryFloatFnCall(Op1, TLI->getName(LibFunc_sqrt), B, + Callee->getAttributes()); + } + +@@ -1173,11 +1173,11 @@ Value *LibCallSimplifier::optimizeExp2(CallInst *CI, IRBuilder<> &B) { + Value *Op = CI->getArgOperand(0); + // Turn exp2(sitofp(x)) -> ldexp(1.0, sext(x)) if sizeof(x) <= 32 + // Turn exp2(uitofp(x)) -> ldexp(1.0, zext(x)) if sizeof(x) < 32 +- LibFunc::Func LdExp = LibFunc::ldexpl; ++ LibFunc LdExp = LibFunc_ldexpl; + if (Op->getType()->isFloatTy()) +- LdExp = LibFunc::ldexpf; ++ LdExp = LibFunc_ldexpf; + else if (Op->getType()->isDoubleTy()) +- LdExp = LibFunc::ldexp; ++ LdExp = LibFunc_ldexp; + + if (TLI->has(LdExp)) { + Value *LdExpArg = nullptr; +@@ -1280,17 +1280,17 @@ Value *LibCallSimplifier::optimizeLog(CallInst *CI, IRBuilder<> &B) { + FMF.setUnsafeAlgebra(); + B.setFastMathFlags(FMF); + +- LibFunc::Func Func; ++ LibFunc Func; + Function *F = OpC->getCalledFunction(); + if (F && ((TLI->getLibFunc(F->getName(), Func) && TLI->has(Func) && +- Func == LibFunc::pow) || F->getIntrinsicID() == Intrinsic::pow)) ++ Func == LibFunc_pow) || F->getIntrinsicID() == Intrinsic::pow)) + return B.CreateFMul(OpC->getArgOperand(1), + emitUnaryFloatFnCall(OpC->getOperand(0), Callee->getName(), B, + Callee->getAttributes()), "mul"); + + // log(exp2(y)) -> y*log(2) + if (F && Name == "log" && TLI->getLibFunc(F->getName(), Func) && +- TLI->has(Func) && Func == LibFunc::exp2) ++ TLI->has(Func) && Func == LibFunc_exp2) + return B.CreateFMul( + OpC->getArgOperand(0), + emitUnaryFloatFnCall(ConstantFP::get(CI->getType(), 2.0), +@@ -1302,8 +1302,8 @@ Value *LibCallSimplifier::optimizeLog(CallInst *CI, IRBuilder<> &B) { + Value *LibCallSimplifier::optimizeSqrt(CallInst *CI, IRBuilder<> &B) { + Function *Callee = CI->getCalledFunction(); + Value *Ret = nullptr; +- if (TLI->has(LibFunc::sqrtf) && (Callee->getName() == "sqrt" || +- Callee->getIntrinsicID() == Intrinsic::sqrt)) ++ if (TLI->has(LibFunc_sqrtf) && (Callee->getName() == "sqrt" || ++ Callee->getIntrinsicID() == Intrinsic::sqrt)) + Ret = optimizeUnaryDoubleFP(CI, B, true); + + if (!CI->hasUnsafeAlgebra()) +@@ -1385,12 +1385,12 @@ Value *LibCallSimplifier::optimizeTan(CallInst *CI, IRBuilder<> &B) { + // tan(atan(x)) -> x + // tanf(atanf(x)) -> x + // tanl(atanl(x)) -> x +- LibFunc::Func Func; ++ LibFunc Func; + Function *F = OpC->getCalledFunction(); + if (F && TLI->getLibFunc(F->getName(), Func) && TLI->has(Func) && +- ((Func == LibFunc::atan && Callee->getName() == "tan") || +- (Func == LibFunc::atanf && Callee->getName() == "tanf") || +- (Func == LibFunc::atanl && Callee->getName() == "tanl"))) ++ ((Func == LibFunc_atan && Callee->getName() == "tan") || ++ (Func == LibFunc_atanf && Callee->getName() == "tanf") || ++ (Func == LibFunc_atanl && Callee->getName() == "tanl"))) + Ret = OpC->getArgOperand(0); + return Ret; + } +@@ -1508,24 +1508,24 @@ void LibCallSimplifier::classifyArgUse( + return; + + Function *Callee = CI->getCalledFunction(); +- LibFunc::Func Func; ++ LibFunc Func; + if (!Callee || !TLI->getLibFunc(*Callee, Func) || !TLI->has(Func) || + !isTrigLibCall(CI)) + return; + + if (IsFloat) { +- if (Func == LibFunc::sinpif) ++ if (Func == LibFunc_sinpif) + SinCalls.push_back(CI); +- else if (Func == LibFunc::cospif) ++ else if (Func == LibFunc_cospif) + CosCalls.push_back(CI); +- else if (Func == LibFunc::sincospif_stret) ++ else if (Func == LibFunc_sincospif_stret) + SinCosCalls.push_back(CI); + } else { +- if (Func == LibFunc::sinpi) ++ if (Func == LibFunc_sinpi) + SinCalls.push_back(CI); +- else if (Func == LibFunc::cospi) ++ else if (Func == LibFunc_cospi) + CosCalls.push_back(CI); +- else if (Func == LibFunc::sincospi_stret) ++ else if (Func == LibFunc_sincospi_stret) + SinCosCalls.push_back(CI); + } + } +@@ -1699,7 +1699,7 @@ Value *LibCallSimplifier::optimizePrintF(CallInst *CI, IRBuilder<> &B) { + + // printf(format, ...) -> iprintf(format, ...) if no floating point + // arguments. +- if (TLI->has(LibFunc::iprintf) && !callHasFloatingPointArgument(CI)) { ++ if (TLI->has(LibFunc_iprintf) && !callHasFloatingPointArgument(CI)) { + Module *M = B.GetInsertBlock()->getParent()->getParent(); + Constant *IPrintFFn = + M->getOrInsertFunction("iprintf", FT, Callee->getAttributes()); +@@ -1780,7 +1780,7 @@ Value *LibCallSimplifier::optimizeSPrintF(CallInst *CI, IRBuilder<> &B) { + + // sprintf(str, format, ...) -> siprintf(str, format, ...) if no floating + // point arguments. +- if (TLI->has(LibFunc::siprintf) && !callHasFloatingPointArgument(CI)) { ++ if (TLI->has(LibFunc_siprintf) && !callHasFloatingPointArgument(CI)) { + Module *M = B.GetInsertBlock()->getParent()->getParent(); + Constant *SIPrintFFn = + M->getOrInsertFunction("siprintf", FT, Callee->getAttributes()); +@@ -1850,7 +1850,7 @@ Value *LibCallSimplifier::optimizeFPrintF(CallInst *CI, IRBuilder<> &B) { + + // fprintf(stream, format, ...) -> fiprintf(stream, format, ...) if no + // floating point arguments. +- if (TLI->has(LibFunc::fiprintf) && !callHasFloatingPointArgument(CI)) { ++ if (TLI->has(LibFunc_fiprintf) && !callHasFloatingPointArgument(CI)) { + Module *M = B.GetInsertBlock()->getParent()->getParent(); + Constant *FIPrintFFn = + M->getOrInsertFunction("fiprintf", FT, Callee->getAttributes()); +@@ -1929,7 +1929,7 @@ Value *LibCallSimplifier::optimizePuts(CallInst *CI, IRBuilder<> &B) { + } + + bool LibCallSimplifier::hasFloatVersion(StringRef FuncName) { +- LibFunc::Func Func; ++ LibFunc Func; + SmallString<20> FloatFuncName = FuncName; + FloatFuncName += 'f'; + if (TLI->getLibFunc(FloatFuncName, Func)) +@@ -1939,7 +1939,7 @@ bool LibCallSimplifier::hasFloatVersion(StringRef FuncName) { + + Value *LibCallSimplifier::optimizeStringMemoryLibCall(CallInst *CI, + IRBuilder<> &Builder) { +- LibFunc::Func Func; ++ LibFunc Func; + Function *Callee = CI->getCalledFunction(); + // Check for string/memory library functions. + if (TLI->getLibFunc(*Callee, Func) && TLI->has(Func)) { +@@ -1948,51 +1948,51 @@ Value *LibCallSimplifier::optimizeStringMemoryLibCall(CallInst *CI, + isCallingConvCCompatible(CI)) && + "Optimizing string/memory libcall would change the calling convention"); + switch (Func) { +- case LibFunc::strcat: ++ case LibFunc_strcat: + return optimizeStrCat(CI, Builder); +- case LibFunc::strncat: ++ case LibFunc_strncat: + return optimizeStrNCat(CI, Builder); +- case LibFunc::strchr: ++ case LibFunc_strchr: + return optimizeStrChr(CI, Builder); +- case LibFunc::strrchr: ++ case LibFunc_strrchr: + return optimizeStrRChr(CI, Builder); +- case LibFunc::strcmp: ++ case LibFunc_strcmp: + return optimizeStrCmp(CI, Builder); +- case LibFunc::strncmp: ++ case LibFunc_strncmp: + return optimizeStrNCmp(CI, Builder); +- case LibFunc::strcpy: ++ case LibFunc_strcpy: + return optimizeStrCpy(CI, Builder); +- case LibFunc::stpcpy: ++ case LibFunc_stpcpy: + return optimizeStpCpy(CI, Builder); +- case LibFunc::strncpy: ++ case LibFunc_strncpy: + return optimizeStrNCpy(CI, Builder); +- case LibFunc::strlen: ++ case LibFunc_strlen: + return optimizeStrLen(CI, Builder); +- case LibFunc::strpbrk: ++ case LibFunc_strpbrk: + return optimizeStrPBrk(CI, Builder); +- case LibFunc::strtol: +- case LibFunc::strtod: +- case LibFunc::strtof: +- case LibFunc::strtoul: +- case LibFunc::strtoll: +- case LibFunc::strtold: +- case LibFunc::strtoull: ++ case LibFunc_strtol: ++ case LibFunc_strtod: ++ case LibFunc_strtof: ++ case LibFunc_strtoul: ++ case LibFunc_strtoll: ++ case LibFunc_strtold: ++ case LibFunc_strtoull: + return optimizeStrTo(CI, Builder); +- case LibFunc::strspn: ++ case LibFunc_strspn: + return optimizeStrSpn(CI, Builder); +- case LibFunc::strcspn: ++ case LibFunc_strcspn: + return optimizeStrCSpn(CI, Builder); +- case LibFunc::strstr: ++ case LibFunc_strstr: + return optimizeStrStr(CI, Builder); +- case LibFunc::memchr: ++ case LibFunc_memchr: + return optimizeMemChr(CI, Builder); +- case LibFunc::memcmp: ++ case LibFunc_memcmp: + return optimizeMemCmp(CI, Builder); +- case LibFunc::memcpy: ++ case LibFunc_memcpy: + return optimizeMemCpy(CI, Builder); +- case LibFunc::memmove: ++ case LibFunc_memmove: + return optimizeMemMove(CI, Builder); +- case LibFunc::memset: ++ case LibFunc_memset: + return optimizeMemSet(CI, Builder); + default: + break; +@@ -2005,7 +2005,7 @@ Value *LibCallSimplifier::optimizeCall(CallInst *CI) { + if (CI->isNoBuiltin()) + return nullptr; + +- LibFunc::Func Func; ++ LibFunc Func; + Function *Callee = CI->getCalledFunction(); + StringRef FuncName = Callee->getName(); + +@@ -2067,114 +2067,114 @@ Value *LibCallSimplifier::optimizeCall(CallInst *CI) { + if (Value *V = optimizeStringMemoryLibCall(CI, Builder)) + return V; + switch (Func) { +- case LibFunc::cosf: +- case LibFunc::cos: +- case LibFunc::cosl: ++ case LibFunc_cosf: ++ case LibFunc_cos: ++ case LibFunc_cosl: + return optimizeCos(CI, Builder); +- case LibFunc::sinpif: +- case LibFunc::sinpi: +- case LibFunc::cospif: +- case LibFunc::cospi: ++ case LibFunc_sinpif: ++ case LibFunc_sinpi: ++ case LibFunc_cospif: ++ case LibFunc_cospi: + return optimizeSinCosPi(CI, Builder); +- case LibFunc::powf: +- case LibFunc::pow: +- case LibFunc::powl: ++ case LibFunc_powf: ++ case LibFunc_pow: ++ case LibFunc_powl: + return optimizePow(CI, Builder); +- case LibFunc::exp2l: +- case LibFunc::exp2: +- case LibFunc::exp2f: ++ case LibFunc_exp2l: ++ case LibFunc_exp2: ++ case LibFunc_exp2f: + return optimizeExp2(CI, Builder); +- case LibFunc::fabsf: +- case LibFunc::fabs: +- case LibFunc::fabsl: ++ case LibFunc_fabsf: ++ case LibFunc_fabs: ++ case LibFunc_fabsl: + return optimizeFabs(CI, Builder); +- case LibFunc::sqrtf: +- case LibFunc::sqrt: +- case LibFunc::sqrtl: ++ case LibFunc_sqrtf: ++ case LibFunc_sqrt: ++ case LibFunc_sqrtl: + return optimizeSqrt(CI, Builder); +- case LibFunc::ffs: +- case LibFunc::ffsl: +- case LibFunc::ffsll: ++ case LibFunc_ffs: ++ case LibFunc_ffsl: ++ case LibFunc_ffsll: + return optimizeFFS(CI, Builder); +- case LibFunc::fls: +- case LibFunc::flsl: +- case LibFunc::flsll: ++ case LibFunc_fls: ++ case LibFunc_flsl: ++ case LibFunc_flsll: + return optimizeFls(CI, Builder); +- case LibFunc::abs: +- case LibFunc::labs: +- case LibFunc::llabs: ++ case LibFunc_abs: ++ case LibFunc_labs: ++ case LibFunc_llabs: + return optimizeAbs(CI, Builder); +- case LibFunc::isdigit: ++ case LibFunc_isdigit: + return optimizeIsDigit(CI, Builder); +- case LibFunc::isascii: ++ case LibFunc_isascii: + return optimizeIsAscii(CI, Builder); +- case LibFunc::toascii: ++ case LibFunc_toascii: + return optimizeToAscii(CI, Builder); +- case LibFunc::printf: ++ case LibFunc_printf: + return optimizePrintF(CI, Builder); +- case LibFunc::sprintf: ++ case LibFunc_sprintf: + return optimizeSPrintF(CI, Builder); +- case LibFunc::fprintf: ++ case LibFunc_fprintf: + return optimizeFPrintF(CI, Builder); +- case LibFunc::fwrite: ++ case LibFunc_fwrite: + return optimizeFWrite(CI, Builder); +- case LibFunc::fputs: ++ case LibFunc_fputs: + return optimizeFPuts(CI, Builder); +- case LibFunc::log: +- case LibFunc::log10: +- case LibFunc::log1p: +- case LibFunc::log2: +- case LibFunc::logb: ++ case LibFunc_log: ++ case LibFunc_log10: ++ case LibFunc_log1p: ++ case LibFunc_log2: ++ case LibFunc_logb: + return optimizeLog(CI, Builder); +- case LibFunc::puts: ++ case LibFunc_puts: + return optimizePuts(CI, Builder); +- case LibFunc::tan: +- case LibFunc::tanf: +- case LibFunc::tanl: ++ case LibFunc_tan: ++ case LibFunc_tanf: ++ case LibFunc_tanl: + return optimizeTan(CI, Builder); +- case LibFunc::perror: ++ case LibFunc_perror: + return optimizeErrorReporting(CI, Builder); +- case LibFunc::vfprintf: +- case LibFunc::fiprintf: ++ case LibFunc_vfprintf: ++ case LibFunc_fiprintf: + return optimizeErrorReporting(CI, Builder, 0); +- case LibFunc::fputc: ++ case LibFunc_fputc: + return optimizeErrorReporting(CI, Builder, 1); +- case LibFunc::ceil: +- case LibFunc::floor: +- case LibFunc::rint: +- case LibFunc::round: +- case LibFunc::nearbyint: +- case LibFunc::trunc: ++ case LibFunc_ceil: ++ case LibFunc_floor: ++ case LibFunc_rint: ++ case LibFunc_round: ++ case LibFunc_nearbyint: ++ case LibFunc_trunc: + if (hasFloatVersion(FuncName)) + return optimizeUnaryDoubleFP(CI, Builder, false); + return nullptr; +- case LibFunc::acos: +- case LibFunc::acosh: +- case LibFunc::asin: +- case LibFunc::asinh: +- case LibFunc::atan: +- case LibFunc::atanh: +- case LibFunc::cbrt: +- case LibFunc::cosh: +- case LibFunc::exp: +- case LibFunc::exp10: +- case LibFunc::expm1: +- case LibFunc::sin: +- case LibFunc::sinh: +- case LibFunc::tanh: ++ case LibFunc_acos: ++ case LibFunc_acosh: ++ case LibFunc_asin: ++ case LibFunc_asinh: ++ case LibFunc_atan: ++ case LibFunc_atanh: ++ case LibFunc_cbrt: ++ case LibFunc_cosh: ++ case LibFunc_exp: ++ case LibFunc_exp10: ++ case LibFunc_expm1: ++ case LibFunc_sin: ++ case LibFunc_sinh: ++ case LibFunc_tanh: + if (UnsafeFPShrink && hasFloatVersion(FuncName)) + return optimizeUnaryDoubleFP(CI, Builder, true); + return nullptr; +- case LibFunc::copysign: ++ case LibFunc_copysign: + if (hasFloatVersion(FuncName)) + return optimizeBinaryDoubleFP(CI, Builder); + return nullptr; +- case LibFunc::fminf: +- case LibFunc::fmin: +- case LibFunc::fminl: +- case LibFunc::fmaxf: +- case LibFunc::fmax: +- case LibFunc::fmaxl: ++ case LibFunc_fminf: ++ case LibFunc_fmin: ++ case LibFunc_fminl: ++ case LibFunc_fmaxf: ++ case LibFunc_fmax: ++ case LibFunc_fmaxl: + return optimizeFMinFMax(CI, Builder); + default: + return nullptr; +@@ -2300,7 +2300,7 @@ Value *FortifiedLibCallSimplifier::optimizeMemSetChk(CallInst *CI, + + Value *FortifiedLibCallSimplifier::optimizeStrpCpyChk(CallInst *CI, + IRBuilder<> &B, +- LibFunc::Func Func) { ++ LibFunc Func) { + Function *Callee = CI->getCalledFunction(); + StringRef Name = Callee->getName(); + const DataLayout &DL = CI->getModule()->getDataLayout(); +@@ -2308,7 +2308,7 @@ Value *FortifiedLibCallSimplifier::optimizeStrpCpyChk(CallInst *CI, + *ObjSize = CI->getArgOperand(2); + + // __stpcpy_chk(x,x,...) -> x+strlen(x) +- if (Func == LibFunc::stpcpy_chk && !OnlyLowerUnknownSize && Dst == Src) { ++ if (Func == LibFunc_stpcpy_chk && !OnlyLowerUnknownSize && Dst == Src) { + Value *StrLen = emitStrLen(Src, B, DL, TLI); + return StrLen ? B.CreateInBoundsGEP(B.getInt8Ty(), Dst, StrLen) : nullptr; + } +@@ -2334,14 +2334,14 @@ Value *FortifiedLibCallSimplifier::optimizeStrpCpyChk(CallInst *CI, + Value *Ret = emitMemCpyChk(Dst, Src, LenV, ObjSize, B, DL, TLI); + // If the function was an __stpcpy_chk, and we were able to fold it into + // a __memcpy_chk, we still need to return the correct end pointer. +- if (Ret && Func == LibFunc::stpcpy_chk) ++ if (Ret && Func == LibFunc_stpcpy_chk) + return B.CreateGEP(B.getInt8Ty(), Dst, ConstantInt::get(SizeTTy, Len - 1)); + return Ret; + } + + Value *FortifiedLibCallSimplifier::optimizeStrpNCpyChk(CallInst *CI, + IRBuilder<> &B, +- LibFunc::Func Func) { ++ LibFunc Func) { + Function *Callee = CI->getCalledFunction(); + StringRef Name = Callee->getName(); + if (isFortifiedCallFoldable(CI, 3, 2, false)) { +@@ -2366,7 +2366,7 @@ Value *FortifiedLibCallSimplifier::optimizeCall(CallInst *CI) { + // + // PR23093. + +- LibFunc::Func Func; ++ LibFunc Func; + Function *Callee = CI->getCalledFunction(); + + SmallVector OpBundles; +@@ -2384,17 +2384,17 @@ Value *FortifiedLibCallSimplifier::optimizeCall(CallInst *CI) { + return nullptr; + + switch (Func) { +- case LibFunc::memcpy_chk: ++ case LibFunc_memcpy_chk: + return optimizeMemCpyChk(CI, Builder); +- case LibFunc::memmove_chk: ++ case LibFunc_memmove_chk: + return optimizeMemMoveChk(CI, Builder); +- case LibFunc::memset_chk: ++ case LibFunc_memset_chk: + return optimizeMemSetChk(CI, Builder); +- case LibFunc::stpcpy_chk: +- case LibFunc::strcpy_chk: ++ case LibFunc_stpcpy_chk: ++ case LibFunc_strcpy_chk: + return optimizeStrpCpyChk(CI, Builder, Func); +- case LibFunc::stpncpy_chk: +- case LibFunc::strncpy_chk: ++ case LibFunc_stpncpy_chk: ++ case LibFunc_strncpy_chk: + return optimizeStrpNCpyChk(CI, Builder, Func); + default: + break; diff --git a/deps/patches/llvm-D28759-loopclearance.patch b/deps/patches/llvm-D28759-loopclearance.patch new file mode 100644 index 0000000000000..036ca4d83103c --- /dev/null +++ b/deps/patches/llvm-D28759-loopclearance.patch @@ -0,0 +1,480 @@ +From e3621af0115a851d0ed02f0b436deec62ec3e99c Mon Sep 17 00:00:00 2001 +From: Keno Fischer +Date: Sun, 15 Jan 2017 23:59:07 -0500 +Subject: [PATCH] [ExecutionDepsFix] Improve clearance calculation for loops + +In revision rL278321, ExecutionDepsFix learned how to pick a better +register for undef register reads, e.g. for instructions such as +`vcvtsi2sdq`. While this revision improved performance on a good number +of our benchmarks, it unfortunately also caused significant regressions +(up to 3x) on others. This regression turned out to be caused by loops +such as: + +PH -> A -> B (xmm -> xmm) -> C -> D -> EXIT + ^ | + +----------------------------------+ + +In the previous version of the clearance calculation, we would visit +the blocks in order, remembering for each whether there were any +incoming backedges from blocks that we hadn't processed yet and if +so queuing up the block to be re-processed. However, for loop structures +such as the above, this is clearly insufficient, since the block B +does not have any unknown backedges, so we do not see the false +dependency from the previous interation's Def of xmm registers in B. + +To fix this, we need to consider all blocks that are part of the loop +and reprocess them one the correct clearance values are known. As +an optimization, we also want to avoid reprocessing any later blocks +that are not part of the loop. + +In summary, the iteration order is as follows: +Before: PH A B C D A' +Corrected (Naive): PH A B C D A' B' C' D' +Corrected (w/ optimization): PH A B C A' B' C' D + +To facilitate this optimization we introduce two new counters for each +basic block. The first counts how many of it's predecssors have +completed primary processing. The second counts how many of its +predecessors have completed all processing (we will call such a block +*done*. Now, the criteria to reprocess a block is as follows: + - All Predecessors have completed primary processing + - For x the number of predecessors that have completed primary + processing *at the time of primary processing of this block*, + the number of predecessors that are done has reached x. + +The intuition behind this criterion is as follows: +We need to perform primary processing on all predecessors in order to +find out any direct defs in those predecessors. When predecessors are +done, we also know that we have information about indirect defs (e.g. +in block B though that were inherited through B->C->A->B). However, +we can't wait for all predecessors to be done, since that would +cause cyclic dependencies. However, it is guaranteed that all those +predecessors that are prior to us in reverse postorder will be done +before us. Since we iterate of the basic blocks in reverse postorder, +the number x above, is precisely the count of the number of predecessors +prior to us in reverse postorder. +--- + lib/CodeGen/ExecutionDepsFix.cpp | 223 ++++++++++++++++++++++-------------- + test/CodeGen/X86/break-false-dep.ll | 57 +++++++++ + 2 files changed, 197 insertions(+), 83 deletions(-) + +diff --git a/lib/CodeGen/ExecutionDepsFix.cpp b/lib/CodeGen/ExecutionDepsFix.cpp +index e7c6b03..6ac1db4 100644 +--- a/lib/CodeGen/ExecutionDepsFix.cpp ++++ b/lib/CodeGen/ExecutionDepsFix.cpp +@@ -142,8 +142,26 @@ class ExeDepsFix : public MachineFunctionPass { + std::vector> AliasMap; + const unsigned NumRegs; + LiveReg *LiveRegs; +- typedef DenseMap LiveOutMap; +- LiveOutMap LiveOuts; ++ struct MBBInfo { ++ // Keeps clearance and domain information for all registers. Not that this ++ // is different from the usual definition notion of liveness. The CPU ++ // doesn't care whether or not we consider a register killed. ++ LiveReg *OutRegs; ++ ++ // Whether we have gotten to this block in primary processing yet. ++ bool PrimaryCompleted; ++ ++ // The number of predecessors for which primary processing has completed ++ unsigned IncomingProcessed; ++ ++ // The value of `IncomingProcessed` at the start of primary processing ++ unsigned PrimaryIncoming; ++ ++ // The number of predecessors for which all processing steps are done. ++ unsigned IncomingCompleted; ++ }; ++ typedef DenseMap MBBInfoMap; ++ MBBInfoMap MBBInfos; + + /// List of undefined register reads in this block in forward order. + std::vector > UndefReads; +@@ -154,11 +172,6 @@ class ExeDepsFix : public MachineFunctionPass { + /// Current instruction number. + /// The first instruction in each basic block is 0. + int CurInstr; +- +- /// True when the current block has a predecessor that hasn't been visited +- /// yet. +- bool SeenUnknownBackEdge; +- + public: + ExeDepsFix(const TargetRegisterClass *rc) + : MachineFunctionPass(ID), RC(rc), NumRegs(RC->getNumRegs()) {} +@@ -180,7 +193,6 @@ public: + private: + iterator_range::const_iterator> + regIndices(unsigned Reg) const; +- + // DomainValue allocation. + DomainValue *alloc(int domain = -1); + DomainValue *retain(DomainValue *DV) { +@@ -199,8 +211,11 @@ private: + + void enterBasicBlock(MachineBasicBlock*); + void leaveBasicBlock(MachineBasicBlock*); +- void visitInstr(MachineInstr*); +- void processDefs(MachineInstr*, bool Kill); ++ bool isBlockDone(MachineBasicBlock *); ++ void processBasicBlock(MachineBasicBlock *MBB, bool PrimaryPass, bool Done); ++ void updateSuccessors(MachineBasicBlock *MBB, bool Primary, bool Done); ++ bool visitInstr(MachineInstr *); ++ void processDefs(MachineInstr *, bool BlockDone, bool Kill); + void visitSoftInstr(MachineInstr*, unsigned mask); + void visitHardInstr(MachineInstr*, unsigned domain); + void pickBestRegisterForUndef(MachineInstr *MI, unsigned OpIdx, +@@ -360,9 +375,6 @@ bool ExeDepsFix::merge(DomainValue *A, DomainValue *B) { + + /// Set up LiveRegs by merging predecessor live-out values. + void ExeDepsFix::enterBasicBlock(MachineBasicBlock *MBB) { +- // Detect back-edges from predecessors we haven't processed yet. +- SeenUnknownBackEdge = false; +- + // Reset instruction counter in each basic block. + CurInstr = 0; + +@@ -397,18 +409,18 @@ void ExeDepsFix::enterBasicBlock(MachineBasicBlock *MBB) { + // Try to coalesce live-out registers from predecessors. + for (MachineBasicBlock::const_pred_iterator pi = MBB->pred_begin(), + pe = MBB->pred_end(); pi != pe; ++pi) { +- LiveOutMap::const_iterator fi = LiveOuts.find(*pi); +- if (fi == LiveOuts.end()) { +- SeenUnknownBackEdge = true; ++ auto fi = MBBInfos.find(*pi); ++ assert(fi != MBBInfos.end()); ++ LiveReg *Incoming = fi->second.OutRegs; ++ if (Incoming == nullptr) { + continue; + } +- assert(fi->second && "Can't have NULL entries"); + + for (unsigned rx = 0; rx != NumRegs; ++rx) { + // Use the most recent predecessor def for each register. +- LiveRegs[rx].Def = std::max(LiveRegs[rx].Def, fi->second[rx].Def); ++ LiveRegs[rx].Def = std::max(LiveRegs[rx].Def, Incoming[rx].Def); + +- DomainValue *pdv = resolve(fi->second[rx].Value); ++ DomainValue *pdv = resolve(Incoming[rx].Value); + if (!pdv) + continue; + if (!LiveRegs[rx].Value) { +@@ -432,35 +444,33 @@ void ExeDepsFix::enterBasicBlock(MachineBasicBlock *MBB) { + force(rx, pdv->getFirstDomain()); + } + } +- DEBUG(dbgs() << "BB#" << MBB->getNumber() +- << (SeenUnknownBackEdge ? ": incomplete\n" : ": all preds known\n")); ++ DEBUG( ++ dbgs() << "BB#" << MBB->getNumber() ++ << (!isBlockDone(MBB) ? ": incomplete\n" : ": all preds known\n")); + } + + void ExeDepsFix::leaveBasicBlock(MachineBasicBlock *MBB) { + assert(LiveRegs && "Must enter basic block first."); ++ LiveReg *OldOutRegs = MBBInfos[MBB].OutRegs; + // Save live registers at end of MBB - used by enterBasicBlock(). + // Also use LiveOuts as a visited set to detect back-edges. +- bool First = LiveOuts.insert(std::make_pair(MBB, LiveRegs)).second; +- +- if (First) { +- // LiveRegs was inserted in LiveOuts. Adjust all defs to be relative to +- // the end of this block instead of the beginning. +- for (unsigned i = 0, e = NumRegs; i != e; ++i) +- LiveRegs[i].Def -= CurInstr; +- } else { +- // Insertion failed, this must be the second pass. ++ MBBInfos[MBB].OutRegs = LiveRegs; ++ ++ // LiveRegs was inserted in LiveOuts. Adjust all defs to be relative to ++ // the end of this block instead of the beginning. ++ for (unsigned i = 0, e = NumRegs; i != e; ++i) ++ LiveRegs[i].Def -= CurInstr; ++ if (OldOutRegs) { ++ // This must be the second pass. + // Release all the DomainValues instead of keeping them. + for (unsigned i = 0, e = NumRegs; i != e; ++i) +- release(LiveRegs[i].Value); +- delete[] LiveRegs; ++ release(OldOutRegs[i].Value); ++ delete[] OldOutRegs; + } + LiveRegs = nullptr; + } + +-void ExeDepsFix::visitInstr(MachineInstr *MI) { +- if (MI->isDebugValue()) +- return; +- ++bool ExeDepsFix::visitInstr(MachineInstr *MI) { + // Update instructions with explicit execution domains. + std::pair DomP = TII->getExecutionDomain(*MI); + if (DomP.first) { +@@ -470,9 +480,7 @@ void ExeDepsFix::visitInstr(MachineInstr *MI) { + visitHardInstr(MI, DomP.first); + } + +- // Process defs to track register ages, and kill values clobbered by generic +- // instructions. +- processDefs(MI, !DomP.first); ++ return !DomP.first; + } + + /// \brief Helps avoid false dependencies on undef registers by updating the +@@ -542,14 +550,7 @@ bool ExeDepsFix::shouldBreakDependence(MachineInstr *MI, unsigned OpIdx, + DEBUG(dbgs() << ": Break dependency.\n"); + continue; + } +- // The current clearance seems OK, but we may be ignoring a def from a +- // back-edge. +- if (!SeenUnknownBackEdge || Pref <= unsigned(CurInstr)) { +- DEBUG(dbgs() << ": OK .\n"); +- return false; +- } +- // A def from an unprocessed back-edge may make us break this dependency. +- DEBUG(dbgs() << ": Wait for back-edge to resolve.\n"); ++ DEBUG(dbgs() << ": OK .\n"); + return false; + } + return true; +@@ -559,16 +560,21 @@ bool ExeDepsFix::shouldBreakDependence(MachineInstr *MI, unsigned OpIdx, + // If Kill is set, also kill off DomainValues clobbered by the defs. + // + // Also break dependencies on partial defs and undef uses. +-void ExeDepsFix::processDefs(MachineInstr *MI, bool Kill) { ++void ExeDepsFix::processDefs(MachineInstr *MI, bool BlockDone, bool Kill) { + assert(!MI->isDebugValue() && "Won't process debug values"); + + // Break dependence on undef uses. Do this before updating LiveRegs below. + unsigned OpNum; +- unsigned Pref = TII->getUndefRegClearance(*MI, OpNum, TRI); +- if (Pref) { +- pickBestRegisterForUndef(MI, OpNum, Pref); +- if (shouldBreakDependence(MI, OpNum, Pref)) +- UndefReads.push_back(std::make_pair(MI, OpNum)); ++ // If this block is not done, it makes little sense to make any decisions ++ // based on clearance information. We need to make a second pass anyway, ++ // and by then we'll have better information, so we can avoid this work now. ++ if (BlockDone) { ++ unsigned Pref = TII->getUndefRegClearance(*MI, OpNum, TRI); ++ if (Pref) { ++ pickBestRegisterForUndef(MI, OpNum, Pref); ++ if (shouldBreakDependence(MI, OpNum, Pref)) ++ UndefReads.push_back(std::make_pair(MI, OpNum)); ++ } + } + const MCInstrDesc &MCID = MI->getDesc(); + for (unsigned i = 0, +@@ -584,11 +590,13 @@ void ExeDepsFix::processDefs(MachineInstr *MI, bool Kill) { + DEBUG(dbgs() << TRI->getName(RC->getRegister(rx)) << ":\t" << CurInstr + << '\t' << *MI); + +- // Check clearance before partial register updates. +- // Call breakDependence before setting LiveRegs[rx].Def. +- unsigned Pref = TII->getPartialRegUpdateClearance(*MI, i, TRI); +- if (Pref && shouldBreakDependence(MI, i, Pref)) +- TII->breakPartialRegDependency(*MI, i, TRI); ++ if (BlockDone) { ++ // Check clearance before partial register updates. ++ // Call breakDependence before setting LiveRegs[rx].Def. ++ unsigned Pref = TII->getPartialRegUpdateClearance(*MI, i, TRI); ++ if (Pref && shouldBreakDependence(MI, i, Pref)) ++ TII->breakPartialRegDependency(*MI, i, TRI); ++ } + + // How many instructions since rx was last written? + LiveRegs[rx].Def = CurInstr; +@@ -780,6 +788,45 @@ void ExeDepsFix::visitSoftInstr(MachineInstr *mi, unsigned mask) { + } + } + ++void ExeDepsFix::processBasicBlock(MachineBasicBlock *MBB, bool PrimaryPass, ++ bool Done) { ++ enterBasicBlock(MBB); ++ for (MachineInstr &MI : *MBB) { ++ if (!MI.isDebugValue()) { ++ bool Kill = false; ++ if (PrimaryPass) ++ Kill = visitInstr(&MI); ++ processDefs(&MI, isBlockDone(MBB), Kill); ++ } ++ } ++ processUndefReads(MBB); ++ leaveBasicBlock(MBB); ++} ++ ++bool ExeDepsFix::isBlockDone(MachineBasicBlock *MBB) { ++ return MBBInfos[MBB].PrimaryCompleted && ++ MBBInfos[MBB].IncomingCompleted == MBBInfos[MBB].PrimaryIncoming && ++ MBBInfos[MBB].IncomingProcessed == MBB->pred_size(); ++} ++ ++void ExeDepsFix::updateSuccessors(MachineBasicBlock *MBB, bool Primary, ++ bool Done) { ++ for (auto *Succ : MBB->successors()) { ++ if (!isBlockDone(Succ)) { ++ if (Primary) { ++ MBBInfos[Succ].IncomingProcessed++; ++ } ++ if (Done) { ++ MBBInfos[Succ].IncomingCompleted++; ++ } ++ if (isBlockDone(Succ)) { ++ processBasicBlock(Succ, false, true); ++ updateSuccessors(Succ, false, true); ++ } ++ } ++ } ++} ++ + bool ExeDepsFix::runOnMachineFunction(MachineFunction &mf) { + if (skipFunction(*mf.getFunction())) + return false; +@@ -816,44 +863,54 @@ bool ExeDepsFix::runOnMachineFunction(MachineFunction &mf) { + AliasMap[*AI].push_back(i); + } + ++ // Initialize the MMBInfos ++ for (auto &MBB : mf) { ++ MBBInfo InitialInfo{nullptr, false, 0, 0, 0}; ++ MBBInfos.insert(std::make_pair(&MBB, InitialInfo)); ++ } ++ + MachineBasicBlock *Entry = &*MF->begin(); + ReversePostOrderTraversal RPOT(Entry); +- SmallVector Loops; + for (ReversePostOrderTraversal::rpo_iterator + MBBI = RPOT.begin(), MBBE = RPOT.end(); MBBI != MBBE; ++MBBI) { + MachineBasicBlock *MBB = *MBBI; +- enterBasicBlock(MBB); +- if (SeenUnknownBackEdge) +- Loops.push_back(MBB); +- for (MachineInstr &MI : *MBB) +- visitInstr(&MI); +- processUndefReads(MBB); +- leaveBasicBlock(MBB); +- } +- +- // Visit all the loop blocks again in order to merge DomainValues from +- // back-edges. +- for (MachineBasicBlock *MBB : Loops) { +- enterBasicBlock(MBB); +- for (MachineInstr &MI : *MBB) +- if (!MI.isDebugValue()) +- processDefs(&MI, false); +- processUndefReads(MBB); +- leaveBasicBlock(MBB); ++ MBBInfos[MBB].PrimaryCompleted = true; ++ MBBInfos[MBB].PrimaryIncoming = MBBInfos[MBB].IncomingProcessed; ++ bool PrimaryDone = isBlockDone(MBB); ++ processBasicBlock(MBB, true, PrimaryDone); ++ updateSuccessors(MBB, true, PrimaryDone); ++ } ++ ++ // We need to go through again and finalize any blocks that are not done yet. ++ // This is possible if blocks have dead predecessors, so we didn't visit them ++ // above. N.B.: The reason we update succesors immidately above, rather than ++ // doing everything in one go here, is to avoid having to do two passes on ++ // basic block between loops (with the scheme above, the whole loop will be ++ // completed before moving on to the blocks after it). ++ for (ReversePostOrderTraversal::rpo_iterator ++ MBBI = RPOT.begin(), ++ MBBE = RPOT.end(); ++ MBBI != MBBE; ++MBBI) { ++ MachineBasicBlock *MBB = *MBBI; ++ if (!isBlockDone(MBB)) { ++ processBasicBlock(MBB, false, true); ++ // Don't update successors here. We'll get to them anyway through this ++ // loop. ++ } + } + + // Clear the LiveOuts vectors and collapse any remaining DomainValues. + for (ReversePostOrderTraversal::rpo_iterator + MBBI = RPOT.begin(), MBBE = RPOT.end(); MBBI != MBBE; ++MBBI) { +- LiveOutMap::const_iterator FI = LiveOuts.find(*MBBI); +- if (FI == LiveOuts.end() || !FI->second) ++ auto FI = MBBInfos.find(*MBBI); ++ if (FI == MBBInfos.end() || !FI->second.OutRegs) + continue; + for (unsigned i = 0, e = NumRegs; i != e; ++i) +- if (FI->second[i].Value) +- release(FI->second[i].Value); +- delete[] FI->second; ++ if (FI->second.OutRegs[i].Value) ++ release(FI->second.OutRegs[i].Value); ++ delete[] FI->second.OutRegs; + } +- LiveOuts.clear(); ++ MBBInfos.clear(); + UndefReads.clear(); + Avail.clear(); + Allocator.DestroyAll(); +diff --git a/test/CodeGen/X86/break-false-dep.ll b/test/CodeGen/X86/break-false-dep.ll +index 4c5e747..0ba1825 100644 +--- a/test/CodeGen/X86/break-false-dep.ll ++++ b/test/CodeGen/X86/break-false-dep.ll +@@ -277,3 +277,60 @@ ret: + ;AVX: vcvtsi2sdq {{.*}}, [[XMM4_7:%xmm[4-7]]], {{%xmm[0-9]+}} + ;AVX-NOT: [[XMM4_7]] + } ++ ++; Make sure we are making a smart choice regarding undef registers even for more ++; complicated loop structures. This example is the inner loop from ++; julia> a = falses(10000); a[1:4:end] = true ++; julia> linspace(1.0,2.0,10000)[a] ++define void @loopclearance2(double* nocapture %y, i64* %x, double %c1, double %c2, double %c3, double %c4, i64 %size) { ++entry: ++ tail call void asm sideeffect "", "~{xmm7},~{dirflag},~{fpsr},~{flags}"() ++ tail call void asm sideeffect "", "~{xmm8},~{xmm9},~{xmm10},~{xmm11},~{dirflag},~{fpsr},~{flags}"() ++ tail call void asm sideeffect "", "~{xmm12},~{xmm13},~{xmm14},~{xmm15},~{dirflag},~{fpsr},~{flags}"() ++ br label %loop ++ ++loop: ++ %phi_i = phi i64 [ 1, %entry ], [ %nexti, %loop_end ] ++ %phi_j = phi i64 [ 1, %entry ], [ %nextj, %loop_end ] ++ %phi_k = phi i64 [ 0, %entry ], [ %nextk, %loop_end ] ++ br label %inner_loop ++ ++inner_loop: ++ %phi = phi i64 [ %phi_k, %loop ], [ %nextk, %inner_loop ] ++ %idx = lshr i64 %phi, 6 ++ %inputptr = getelementptr i64, i64* %x, i64 %idx ++ %input = load i64, i64* %inputptr, align 8 ++ %masked = and i64 %phi, 63 ++ %shiftedmasked = shl i64 1, %masked ++ %maskedinput = and i64 %input, %shiftedmasked ++ %cmp = icmp eq i64 %maskedinput, 0 ++ %nextk = add i64 %phi, 1 ++ br i1 %cmp, label %inner_loop, label %loop_end ++ ++loop_end: ++ %nexti = add i64 %phi_i, 1 ++ %nextj = add i64 %phi_j, 1 ++ ; Register use, plus us clobbering 7-15 above, basically forces xmm7 here as ++ ; the only reasonable choice. The primary thing we care about is that it's ++ ; not one of the registers used in the loop (e.g. not the output reg here) ++;AVX-NOT: %xmm6 ++;AVX: vcvtsi2sdq {{.*}}, %xmm6, {{%xmm[0-9]+}} ++;AVX-NOT: %xmm6 ++ %nexti_f = sitofp i64 %nexti to double ++ %sub = fsub double %c1, %nexti_f ++ %mul = fmul double %sub, %c2 ++;AVX: vcvtsi2sdq {{.*}}, %xmm6, {{%xmm[0-9]+}} ++;AVX-NOT: %xmm6 ++ %phi_f = sitofp i64 %phi to double ++ %mul2 = fmul double %phi_f, %c3 ++ %add2 = fadd double %mul, %mul2 ++ %div = fdiv double %add2, %c4 ++ %prev_j = add i64 %phi_j, -1 ++ %outptr = getelementptr double, double* %y, i64 %prev_j ++ store double %div, double* %outptr, align 8 ++ %done = icmp slt i64 %size, %nexti ++ br i1 %done, label %loopdone, label %loop ++ ++loopdone: ++ ret void ++} +-- +2.9.3 diff --git a/deps/patches/llvm-D28786-callclearance.patch b/deps/patches/llvm-D28786-callclearance.patch new file mode 100644 index 0000000000000..fa7dfd3f22d38 --- /dev/null +++ b/deps/patches/llvm-D28786-callclearance.patch @@ -0,0 +1,344 @@ +diff --git a/include/llvm/Target/TargetInstrInfo.h b/include/llvm/Target/TargetInstrInfo.h +index 83515bc..65b435a 100644 +--- a/include/llvm/Target/TargetInstrInfo.h ++++ b/include/llvm/Target/TargetInstrInfo.h +@@ -1440,6 +1440,17 @@ public: + virtual void breakPartialRegDependency(MachineInstr &MI, unsigned OpNum, + const TargetRegisterInfo *TRI) const {} + ++ /// May return true if the instruction in question is a dependency breaking ++ /// instruction. If so, the register number for which it is dependency ++ /// breaking should be returned in `OutReg`. It is prefereable to return ++ /// false if the result cannot be determined. This would at worst result ++ /// in the insertion of an unnecessary instruction, while the other ++ /// alternative could result in significant false-dependency penalties. ++ virtual bool isDependencyBreak(MachineInstr &MI, ++ unsigned *OutReg = nullptr) const { ++ return false; ++ } ++ + /// Create machine specific model for scheduling. + virtual DFAPacketizer * + CreateTargetScheduleState(const TargetSubtargetInfo &) const { +diff --git a/lib/CodeGen/ExecutionDepsFix.cpp b/lib/CodeGen/ExecutionDepsFix.cpp +index 6ac1db4..63065ea 100644 +--- a/lib/CodeGen/ExecutionDepsFix.cpp ++++ b/lib/CodeGen/ExecutionDepsFix.cpp +@@ -214,13 +214,18 @@ private: + bool isBlockDone(MachineBasicBlock *); + void processBasicBlock(MachineBasicBlock *MBB, bool PrimaryPass, bool Done); + void updateSuccessors(MachineBasicBlock *MBB, bool Primary, bool Done); +- bool visitInstr(MachineInstr *); ++ bool visitInstr(MachineInstr *, bool PrimaryPass); + void processDefs(MachineInstr *, bool BlockDone, bool Kill); + void visitSoftInstr(MachineInstr*, unsigned mask); + void visitHardInstr(MachineInstr*, unsigned domain); +- void pickBestRegisterForUndef(MachineInstr *MI, unsigned OpIdx, +- unsigned Pref); ++ void pickBestRegisterForUndef(MachineInstr *MI, unsigned OpIdx, unsigned Pref, ++ bool &TrueDependency); + bool shouldBreakDependence(MachineInstr*, unsigned OpIdx, unsigned Pref); ++ ++ // Undef Reads ++ void collapseUndefReads(unsigned from, unsigned to, unsigned Reg); ++ unsigned updateChooseableRegs(SparseSet &, ++ const TargetRegisterClass *, bool); + void processUndefReads(MachineBasicBlock*); + }; + } +@@ -394,11 +399,19 @@ void ExeDepsFix::enterBasicBlock(MachineBasicBlock *MBB) { + + // This is the entry block. + if (MBB->pred_empty()) { ++ // Treat all registers as being defined just before the first instruction. ++ // Howver, we want the logic later to prefer non live-ins over live-ins, ++ // so pretend the live-ins were defined slightly later. ++ // We used to only do this for live-ins, but that's a bit of a gamble. ++ // If our caller does arithmetic with these registers is is quite likely ++ // that it will have used registers beyond the ones that are live here. ++ // Given the immense penalty for getting this wrong, being conservative ++ // here seems worth it. ++ for (unsigned rx = 0; rx != NumRegs; ++rx) { ++ LiveRegs[rx].Def = -2; ++ } + for (const auto &LI : MBB->liveins()) { + for (int rx : regIndices(LI.PhysReg)) { +- // Treat function live-ins as if they were defined just before the first +- // instruction. Usually, function arguments are set up immediately +- // before the call. + LiveRegs[rx].Def = -1; + } + } +@@ -470,24 +483,36 @@ void ExeDepsFix::leaveBasicBlock(MachineBasicBlock *MBB) { + LiveRegs = nullptr; + } + +-bool ExeDepsFix::visitInstr(MachineInstr *MI) { +- // Update instructions with explicit execution domains. +- std::pair DomP = TII->getExecutionDomain(*MI); +- if (DomP.first) { +- if (DomP.second) +- visitSoftInstr(MI, DomP.second); +- else +- visitHardInstr(MI, DomP.first); ++bool ExeDepsFix::visitInstr(MachineInstr *MI, bool PrimaryPass) { ++ bool Kill = false; ++ ++ if (PrimaryPass) { ++ // Update instructions with explicit execution domains. ++ std::pair DomP = TII->getExecutionDomain(*MI); ++ if (DomP.first) { ++ if (DomP.second) ++ visitSoftInstr(MI, DomP.second); ++ else ++ visitHardInstr(MI, DomP.first); ++ } ++ Kill = !DomP.first; + } + +- return !DomP.first; ++ // If this is a call, pretend all registers we are considering are def'd here. ++ // We have no idea which registers the callee may use. ++ if (MI->isCall()) { ++ for (unsigned i = 0, e = NumRegs; i != e; ++i) ++ LiveRegs[i].Def = CurInstr; ++ } ++ ++ return Kill; + } + + /// \brief Helps avoid false dependencies on undef registers by updating the + /// machine instructions' undef operand to use a register that the instruction + /// is truly dependent on, or use a register with clearance higher than Pref. + void ExeDepsFix::pickBestRegisterForUndef(MachineInstr *MI, unsigned OpIdx, +- unsigned Pref) { ++ unsigned Pref, bool &TrueDependency) { + MachineOperand &MO = MI->getOperand(OpIdx); + assert(MO.isUndef() && "Expected undef machine operand"); + +@@ -510,6 +535,7 @@ void ExeDepsFix::pickBestRegisterForUndef(MachineInstr *MI, unsigned OpIdx, + // We found a true dependency - replace the undef register with the true + // dependency. + MO.setReg(CurrMO.getReg()); ++ TrueDependency = true; + return; + } + +@@ -571,9 +597,14 @@ void ExeDepsFix::processDefs(MachineInstr *MI, bool BlockDone, bool Kill) { + if (BlockDone) { + unsigned Pref = TII->getUndefRegClearance(*MI, OpNum, TRI); + if (Pref) { +- pickBestRegisterForUndef(MI, OpNum, Pref); +- if (shouldBreakDependence(MI, OpNum, Pref)) ++ bool TrueDependency = false; ++ pickBestRegisterForUndef(MI, OpNum, Pref, TrueDependency); ++ // Don't bother adding true dependencies to UndefReads. All we'd find out ++ // is that the register is live (since this very instruction depends on ++ // it), so we can't do anything. ++ if (!TrueDependency && shouldBreakDependence(MI, OpNum, Pref)) { + UndefReads.push_back(std::make_pair(MI, OpNum)); ++ } + } + } + const MCInstrDesc &MCID = MI->getDesc(); +@@ -606,9 +637,52 @@ void ExeDepsFix::processDefs(MachineInstr *MI, bool BlockDone, bool Kill) { + kill(rx); + } + } ++ unsigned DepReg = 0; ++ if (TII->isDependencyBreak(*MI, &DepReg)) { ++ for (int rx : regIndices(DepReg)) { ++ // This instruction is a dependency break, so there are no clearance ++ // issues, reset the counter. ++ LiveRegs[rx].Def = -(1 << 20); ++ } ++ } + ++CurInstr; + } + ++// Set the undef read register to `Reg` for all UndefReads in the range ++// [from,to). ++void ExeDepsFix::collapseUndefReads(unsigned from, unsigned to, unsigned Reg) { ++ if (from >= to) ++ return; ++ for (unsigned i = from; i < to; ++i) { ++ MachineInstr *MI = std::get<0>(UndefReads[i]); ++ unsigned OpIdx = std::get<1>(UndefReads[i]); ++ MachineOperand &MO = MI->getOperand(OpIdx); ++ MO.setReg(Reg); ++ } ++ TII->breakPartialRegDependency(*std::get<0>(UndefReads[from]), ++ std::get<1>(UndefReads[from]), TRI); ++} ++ ++unsigned ExeDepsFix::updateChooseableRegs(SparseSet &ChoosableRegs, ++ const TargetRegisterClass *OpRC, ++ bool add) { ++ unsigned LowestValid = (unsigned)-1; ++ ++ for (auto Reg : OpRC->getRegisters()) { ++ if (LiveRegSet.contains(Reg)) ++ ChoosableRegs.erase(Reg); ++ else if (add) { ++ ChoosableRegs.insert(Reg); ++ if (LowestValid == (unsigned)-1) ++ LowestValid = Reg; ++ } else if (ChoosableRegs.count(Reg) == 1) { ++ if (LowestValid == (unsigned)-1) ++ LowestValid = Reg; ++ } ++ } ++ return LowestValid; ++} ++ + /// \break Break false dependencies on undefined register reads. + /// + /// Walk the block backward computing precise liveness. This is expensive, so we +@@ -619,31 +693,87 @@ void ExeDepsFix::processUndefReads(MachineBasicBlock *MBB) { + if (UndefReads.empty()) + return; + ++ // We want to be slightly clever here, to avoid the following common pattern: ++ // Suppose we have some instruction `vrandom %in, %out` and the following code ++ // vrandom %xmm0, %xmm0 ++ // vrandom %xmm1, %xmm1 ++ // vrandom %xmm2, %xmm2 ++ // vrandom %xmm3, %xmm3 ++ // The earlier logic likes to produce these, because it picks the first ++ // register ++ // to break ties in clearance. However, most register allocators pick the dest ++ // register the same way. Naively, we'd have to insert a dependency break, ++ // before every instruction above. However, what we really want is ++ // vxorps %xmm3, %xmm3, %xmm3 ++ // vrandom %xmm3, %xmm0 ++ // vrandom %xmm3, %xmm1 ++ // vrandom %xmm3, %xmm2 ++ // vrandom %xmm3, %xmm3 ++ // To do so, we walk backwards and cumulatively keep track of which registers ++ // we can use to break the dependency. Then, once the set has collapsed, we ++ // reset the undef read register for all following instructions. ++ + // Collect this block's live out register units. + LiveRegSet.init(TRI); + // We do not need to care about pristine registers as they are just preserved + // but not actually used in the function. + LiveRegSet.addLiveOutsNoPristines(*MBB); + +- MachineInstr *UndefMI = UndefReads.back().first; +- unsigned OpIdx = UndefReads.back().second; ++ SparseSet ChoosableRegs; ++ ChoosableRegs.setUniverse(TRI->getNumRegs()); ++ ++ unsigned LastValid = (unsigned)-1; ++ const TargetRegisterClass *LastOpRC = nullptr; ++ size_t i, LastInit; ++ i = LastInit = UndefReads.size() - 1; ++ MachineInstr *UndefMI = std::get<0>(UndefReads[i]); + + for (MachineInstr &I : make_range(MBB->rbegin(), MBB->rend())) { + // Update liveness, including the current instruction's defs. + LiveRegSet.stepBackward(I); + ++ // This ensures that we don't accidentally pick a register whose live region ++ // lies entirely between two undef reads (since that would defeat the ++ // purpose of breaking the dependency). ++ for (auto LiveReg : LiveRegSet) ++ ChoosableRegs.erase(LiveReg); ++ + if (UndefMI == &I) { +- if (!LiveRegSet.contains(UndefMI->getOperand(OpIdx).getReg())) +- TII->breakPartialRegDependency(*UndefMI, OpIdx, TRI); ++ unsigned OpIdx = std::get<1>(UndefReads[i]); ++ // Get the undef operand's register class ++ const TargetRegisterClass *OpRC = ++ TII->getRegClass(UndefMI->getDesc(), OpIdx, TRI, *MF); ++ if (OpRC != LastOpRC || ChoosableRegs.size() == 0) { ++ if (LastInit != i) { ++ if (LastValid != (unsigned)-1) ++ collapseUndefReads(i + 1, LastInit + 1, LastValid); ++ ChoosableRegs.clear(); ++ LastInit = i; ++ } ++ } ++ ++ unsigned LowestValid = ++ updateChooseableRegs(ChoosableRegs, OpRC, LastInit == i); ++ ++ if (ChoosableRegs.size() == 0) { ++ if (LastInit != i) { ++ if (LastValid != (unsigned)-1) ++ collapseUndefReads(i + 1, LastInit + 1, LastValid); ++ LowestValid = updateChooseableRegs(ChoosableRegs, OpRC, true); ++ LastInit = i; ++ } ++ } ++ LastValid = LowestValid; ++ LastOpRC = OpRC; + +- UndefReads.pop_back(); +- if (UndefReads.empty()) +- return; ++ if (i == 0) ++ break; + +- UndefMI = UndefReads.back().first; +- OpIdx = UndefReads.back().second; ++ UndefMI = std::get<0>(UndefReads[--i]); + } + } ++ if (LastValid != (unsigned)-1) ++ collapseUndefReads(0, LastInit + 1, LastValid); + } + + // A hard instruction only works in one domain. All input registers will be +@@ -793,9 +923,7 @@ void ExeDepsFix::processBasicBlock(MachineBasicBlock *MBB, bool PrimaryPass, + enterBasicBlock(MBB); + for (MachineInstr &MI : *MBB) { + if (!MI.isDebugValue()) { +- bool Kill = false; +- if (PrimaryPass) +- Kill = visitInstr(&MI); ++ bool Kill = visitInstr(&MI, PrimaryPass); + processDefs(&MI, isBlockDone(MBB), Kill); + } + } +diff --git a/lib/Target/X86/X86InstrInfo.cpp b/lib/Target/X86/X86InstrInfo.cpp +index 5793597..f31c97e 100644 +--- a/lib/Target/X86/X86InstrInfo.cpp ++++ b/lib/Target/X86/X86InstrInfo.cpp +@@ -7496,6 +7496,23 @@ void X86InstrInfo::breakPartialRegDependency( + } + } + ++bool X86InstrInfo::isDependencyBreak(MachineInstr &MI, unsigned *OutReg) const { ++ unsigned Opc = MI.getOpcode(); ++ if (!(Opc == X86::VXORPSrr || Opc == X86::VXORPDrr || Opc == X86::XORPSrr || ++ Opc == X86::XORPDrr)) ++ return false; ++ unsigned Reg = 0; ++ for (unsigned i = 0; i < MI.getNumOperands(); ++i) { ++ const MachineOperand &MO = MI.getOperand(i); ++ if (!MO.isReg() || (Reg != 0 && MO.getReg() != Reg)) ++ return false; ++ Reg = MO.getReg(); ++ } ++ if (OutReg) ++ *OutReg = Reg; ++ return true; ++} ++ + MachineInstr * + X86InstrInfo::foldMemoryOperandImpl(MachineFunction &MF, MachineInstr &MI, + ArrayRef Ops, +diff --git a/lib/Target/X86/X86InstrInfo.h b/lib/Target/X86/X86InstrInfo.h +index 8d74617..fa86882 100644 +--- a/lib/Target/X86/X86InstrInfo.h ++++ b/lib/Target/X86/X86InstrInfo.h +@@ -484,6 +484,7 @@ public: + const TargetRegisterInfo *TRI) const override; + void breakPartialRegDependency(MachineInstr &MI, unsigned OpNum, + const TargetRegisterInfo *TRI) const override; ++ bool isDependencyBreak(MachineInstr &MI, unsigned *OutReg) const override; + + MachineInstr *foldMemoryOperandImpl(MachineFunction &MF, MachineInstr &MI, + unsigned OpNum, diff --git a/deps/patches/llvm-D28786-callclearance_4.0.patch b/deps/patches/llvm-D28786-callclearance_4.0.patch new file mode 100644 index 0000000000000..2735c7f5b3e94 --- /dev/null +++ b/deps/patches/llvm-D28786-callclearance_4.0.patch @@ -0,0 +1,344 @@ +diff --git a/include/llvm/Target/TargetInstrInfo.h b/include/llvm/Target/TargetInstrInfo.h +index 247d694f2e4..e455549cdc6 100644 +--- a/include/llvm/Target/TargetInstrInfo.h ++++ b/include/llvm/Target/TargetInstrInfo.h +@@ -1421,6 +1421,17 @@ public: + virtual void breakPartialRegDependency(MachineInstr &MI, unsigned OpNum, + const TargetRegisterInfo *TRI) const {} + ++ /// May return true if the instruction in question is a dependency breaking ++ /// instruction. If so, the register number for which it is dependency ++ /// breaking should be returned in `OutReg`. It is prefereable to return ++ /// false if the result cannot be determined. This would at worst result ++ /// in the insertion of an unnecessary instruction, while the other ++ /// alternative could result in significant false-dependency penalties. ++ virtual bool isDependencyBreak(MachineInstr &MI, ++ unsigned *OutReg = nullptr) const { ++ return false; ++ } ++ + /// Create machine specific model for scheduling. + virtual DFAPacketizer * + CreateTargetScheduleState(const TargetSubtargetInfo &) const { +diff --git a/lib/CodeGen/ExecutionDepsFix.cpp b/lib/CodeGen/ExecutionDepsFix.cpp +index 64aed533a9d..9f3bd634622 100644 +--- a/lib/CodeGen/ExecutionDepsFix.cpp ++++ b/lib/CodeGen/ExecutionDepsFix.cpp +@@ -214,13 +214,18 @@ private: + bool isBlockDone(MachineBasicBlock *); + void processBasicBlock(MachineBasicBlock *MBB, bool PrimaryPass, bool Done); + void updateSuccessors(MachineBasicBlock *MBB, bool Primary, bool Done); +- bool visitInstr(MachineInstr *); ++ bool visitInstr(MachineInstr *, bool PrimaryPass); + void processDefs(MachineInstr *, bool BlockDone, bool Kill); + void visitSoftInstr(MachineInstr*, unsigned mask); + void visitHardInstr(MachineInstr*, unsigned domain); +- void pickBestRegisterForUndef(MachineInstr *MI, unsigned OpIdx, +- unsigned Pref); ++ void pickBestRegisterForUndef(MachineInstr *MI, unsigned OpIdx, unsigned Pref, ++ bool &TrueDependency); + bool shouldBreakDependence(MachineInstr*, unsigned OpIdx, unsigned Pref); ++ ++ // Undef Reads ++ void collapseUndefReads(unsigned from, unsigned to, unsigned Reg); ++ unsigned updateChooseableRegs(SparseSet &, ++ const TargetRegisterClass *, bool); + void processUndefReads(MachineBasicBlock*); + }; + } +@@ -394,11 +399,19 @@ void ExeDepsFix::enterBasicBlock(MachineBasicBlock *MBB) { + + // This is the entry block. + if (MBB->pred_empty()) { ++ // Treat all registers as being defined just before the first instruction. ++ // Howver, we want the logic later to prefer non live-ins over live-ins, ++ // so pretend the live-ins were defined slightly later. ++ // We used to only do this for live-ins, but that's a bit of a gamble. ++ // If our caller does arithmetic with these registers is is quite likely ++ // that it will have used registers beyond the ones that are live here. ++ // Given the immense penalty for getting this wrong, being conservative ++ // here seems worth it. ++ for (unsigned rx = 0; rx != NumRegs; ++rx) { ++ LiveRegs[rx].Def = -2; ++ } + for (const auto &LI : MBB->liveins()) { + for (int rx : regIndices(LI.PhysReg)) { +- // Treat function live-ins as if they were defined just before the first +- // instruction. Usually, function arguments are set up immediately +- // before the call. + LiveRegs[rx].Def = -1; + } + } +@@ -470,24 +483,36 @@ void ExeDepsFix::leaveBasicBlock(MachineBasicBlock *MBB) { + LiveRegs = nullptr; + } + +-bool ExeDepsFix::visitInstr(MachineInstr *MI) { +- // Update instructions with explicit execution domains. +- std::pair DomP = TII->getExecutionDomain(*MI); +- if (DomP.first) { +- if (DomP.second) +- visitSoftInstr(MI, DomP.second); +- else +- visitHardInstr(MI, DomP.first); ++bool ExeDepsFix::visitInstr(MachineInstr *MI, bool PrimaryPass) { ++ bool Kill = false; ++ ++ if (PrimaryPass) { ++ // Update instructions with explicit execution domains. ++ std::pair DomP = TII->getExecutionDomain(*MI); ++ if (DomP.first) { ++ if (DomP.second) ++ visitSoftInstr(MI, DomP.second); ++ else ++ visitHardInstr(MI, DomP.first); ++ } ++ Kill = !DomP.first; ++ } ++ ++ // If this is a call, pretend all registers we are considering are def'd here. ++ // We have no idea which registers the callee may use. ++ if (MI->isCall()) { ++ for (unsigned i = 0, e = NumRegs; i != e; ++i) ++ LiveRegs[i].Def = CurInstr; + } + +- return !DomP.first; ++ return Kill; + } + + /// \brief Helps avoid false dependencies on undef registers by updating the + /// machine instructions' undef operand to use a register that the instruction + /// is truly dependent on, or use a register with clearance higher than Pref. + void ExeDepsFix::pickBestRegisterForUndef(MachineInstr *MI, unsigned OpIdx, +- unsigned Pref) { ++ unsigned Pref, bool &TrueDependency) { + MachineOperand &MO = MI->getOperand(OpIdx); + assert(MO.isUndef() && "Expected undef machine operand"); + +@@ -510,6 +535,7 @@ void ExeDepsFix::pickBestRegisterForUndef(MachineInstr *MI, unsigned OpIdx, + // We found a true dependency - replace the undef register with the true + // dependency. + MO.setReg(CurrMO.getReg()); ++ TrueDependency = true; + return; + } + +@@ -571,9 +597,14 @@ void ExeDepsFix::processDefs(MachineInstr *MI, bool BlockDone, bool Kill) { + if (BlockDone) { + unsigned Pref = TII->getUndefRegClearance(*MI, OpNum, TRI); + if (Pref) { +- pickBestRegisterForUndef(MI, OpNum, Pref); +- if (shouldBreakDependence(MI, OpNum, Pref)) ++ bool TrueDependency = false; ++ pickBestRegisterForUndef(MI, OpNum, Pref, TrueDependency); ++ // Don't bother adding true dependencies to UndefReads. All we'd find out ++ // is that the register is live (since this very instruction depends on ++ // it), so we can't do anything. ++ if (!TrueDependency && shouldBreakDependence(MI, OpNum, Pref)) { + UndefReads.push_back(std::make_pair(MI, OpNum)); ++ } + } + } + const MCInstrDesc &MCID = MI->getDesc(); +@@ -606,9 +637,52 @@ void ExeDepsFix::processDefs(MachineInstr *MI, bool BlockDone, bool Kill) { + kill(rx); + } + } ++ unsigned DepReg = 0; ++ if (TII->isDependencyBreak(*MI, &DepReg)) { ++ for (int rx : regIndices(DepReg)) { ++ // This instruction is a dependency break, so there are no clearance ++ // issues, reset the counter. ++ LiveRegs[rx].Def = -(1 << 20); ++ } ++ } + ++CurInstr; + } + ++// Set the undef read register to `Reg` for all UndefReads in the range ++// [from,to). ++void ExeDepsFix::collapseUndefReads(unsigned from, unsigned to, unsigned Reg) { ++ if (from >= to) ++ return; ++ for (unsigned i = from; i < to; ++i) { ++ MachineInstr *MI = std::get<0>(UndefReads[i]); ++ unsigned OpIdx = std::get<1>(UndefReads[i]); ++ MachineOperand &MO = MI->getOperand(OpIdx); ++ MO.setReg(Reg); ++ } ++ TII->breakPartialRegDependency(*std::get<0>(UndefReads[from]), ++ std::get<1>(UndefReads[from]), TRI); ++} ++ ++unsigned ExeDepsFix::updateChooseableRegs(SparseSet &ChoosableRegs, ++ const TargetRegisterClass *OpRC, ++ bool add) { ++ unsigned LowestValid = (unsigned)-1; ++ ++ for (auto Reg : OpRC->getRegisters()) { ++ if (LiveRegSet.contains(Reg)) ++ ChoosableRegs.erase(Reg); ++ else if (add) { ++ ChoosableRegs.insert(Reg); ++ if (LowestValid == (unsigned)-1) ++ LowestValid = Reg; ++ } else if (ChoosableRegs.count(Reg) == 1) { ++ if (LowestValid == (unsigned)-1) ++ LowestValid = Reg; ++ } ++ } ++ return LowestValid; ++} ++ + /// \break Break false dependencies on undefined register reads. + /// + /// Walk the block backward computing precise liveness. This is expensive, so we +@@ -619,31 +693,87 @@ void ExeDepsFix::processUndefReads(MachineBasicBlock *MBB) { + if (UndefReads.empty()) + return; + ++ // We want to be slightly clever here, to avoid the following common pattern: ++ // Suppose we have some instruction `vrandom %in, %out` and the following code ++ // vrandom %xmm0, %xmm0 ++ // vrandom %xmm1, %xmm1 ++ // vrandom %xmm2, %xmm2 ++ // vrandom %xmm3, %xmm3 ++ // The earlier logic likes to produce these, because it picks the first ++ // register ++ // to break ties in clearance. However, most register allocators pick the dest ++ // register the same way. Naively, we'd have to insert a dependency break, ++ // before every instruction above. However, what we really want is ++ // vxorps %xmm3, %xmm3, %xmm3 ++ // vrandom %xmm3, %xmm0 ++ // vrandom %xmm3, %xmm1 ++ // vrandom %xmm3, %xmm2 ++ // vrandom %xmm3, %xmm3 ++ // To do so, we walk backwards and cumulatively keep track of which registers ++ // we can use to break the dependency. Then, once the set has collapsed, we ++ // reset the undef read register for all following instructions. ++ + // Collect this block's live out register units. + LiveRegSet.init(*TRI); + // We do not need to care about pristine registers as they are just preserved + // but not actually used in the function. + LiveRegSet.addLiveOutsNoPristines(*MBB); + +- MachineInstr *UndefMI = UndefReads.back().first; +- unsigned OpIdx = UndefReads.back().second; ++ SparseSet ChoosableRegs; ++ ChoosableRegs.setUniverse(TRI->getNumRegs()); ++ ++ unsigned LastValid = (unsigned)-1; ++ const TargetRegisterClass *LastOpRC = nullptr; ++ size_t i, LastInit; ++ i = LastInit = UndefReads.size() - 1; ++ MachineInstr *UndefMI = std::get<0>(UndefReads[i]); + + for (MachineInstr &I : make_range(MBB->rbegin(), MBB->rend())) { + // Update liveness, including the current instruction's defs. + LiveRegSet.stepBackward(I); + ++ // This ensures that we don't accidentally pick a register whose live region ++ // lies entirely between two undef reads (since that would defeat the ++ // purpose of breaking the dependency). ++ for (auto LiveReg : LiveRegSet) ++ ChoosableRegs.erase(LiveReg); ++ + if (UndefMI == &I) { +- if (!LiveRegSet.contains(UndefMI->getOperand(OpIdx).getReg())) +- TII->breakPartialRegDependency(*UndefMI, OpIdx, TRI); ++ unsigned OpIdx = std::get<1>(UndefReads[i]); ++ // Get the undef operand's register class ++ const TargetRegisterClass *OpRC = ++ TII->getRegClass(UndefMI->getDesc(), OpIdx, TRI, *MF); ++ if (OpRC != LastOpRC || ChoosableRegs.size() == 0) { ++ if (LastInit != i) { ++ if (LastValid != (unsigned)-1) ++ collapseUndefReads(i + 1, LastInit + 1, LastValid); ++ ChoosableRegs.clear(); ++ LastInit = i; ++ } ++ } ++ ++ unsigned LowestValid = ++ updateChooseableRegs(ChoosableRegs, OpRC, LastInit == i); ++ ++ if (ChoosableRegs.size() == 0) { ++ if (LastInit != i) { ++ if (LastValid != (unsigned)-1) ++ collapseUndefReads(i + 1, LastInit + 1, LastValid); ++ LowestValid = updateChooseableRegs(ChoosableRegs, OpRC, true); ++ LastInit = i; ++ } ++ } ++ LastValid = LowestValid; ++ LastOpRC = OpRC; + +- UndefReads.pop_back(); +- if (UndefReads.empty()) +- return; ++ if (i == 0) ++ break; + +- UndefMI = UndefReads.back().first; +- OpIdx = UndefReads.back().second; ++ UndefMI = std::get<0>(UndefReads[--i]); + } + } ++ if (LastValid != (unsigned)-1) ++ collapseUndefReads(0, LastInit + 1, LastValid); + } + + // A hard instruction only works in one domain. All input registers will be +@@ -787,9 +917,7 @@ void ExeDepsFix::processBasicBlock(MachineBasicBlock *MBB, bool PrimaryPass, + enterBasicBlock(MBB); + for (MachineInstr &MI : *MBB) { + if (!MI.isDebugValue()) { +- bool Kill = false; +- if (PrimaryPass) +- Kill = visitInstr(&MI); ++ bool Kill = visitInstr(&MI, PrimaryPass); + processDefs(&MI, isBlockDone(MBB), Kill); + } + } +diff --git a/lib/Target/X86/X86InstrInfo.cpp b/lib/Target/X86/X86InstrInfo.cpp +index 627b6120b04..26665b2a15d 100644 +--- a/lib/Target/X86/X86InstrInfo.cpp ++++ b/lib/Target/X86/X86InstrInfo.cpp +@@ -7432,6 +7432,23 @@ void X86InstrInfo::breakPartialRegDependency( + } + } + ++bool X86InstrInfo::isDependencyBreak(MachineInstr &MI, unsigned *OutReg) const { ++ unsigned Opc = MI.getOpcode(); ++ if (!(Opc == X86::VXORPSrr || Opc == X86::VXORPDrr || Opc == X86::XORPSrr || ++ Opc == X86::XORPDrr)) ++ return false; ++ unsigned Reg = 0; ++ for (unsigned i = 0; i < MI.getNumOperands(); ++i) { ++ const MachineOperand &MO = MI.getOperand(i); ++ if (!MO.isReg() || (Reg != 0 && MO.getReg() != Reg)) ++ return false; ++ Reg = MO.getReg(); ++ } ++ if (OutReg) ++ *OutReg = Reg; ++ return true; ++} ++ + MachineInstr * + X86InstrInfo::foldMemoryOperandImpl(MachineFunction &MF, MachineInstr &MI, + ArrayRef Ops, +diff --git a/lib/Target/X86/X86InstrInfo.h b/lib/Target/X86/X86InstrInfo.h +index acfdef4da7a..4ea9ddfc863 100644 +--- a/lib/Target/X86/X86InstrInfo.h ++++ b/lib/Target/X86/X86InstrInfo.h +@@ -477,6 +477,7 @@ public: + const TargetRegisterInfo *TRI) const override; + void breakPartialRegDependency(MachineInstr &MI, unsigned OpNum, + const TargetRegisterInfo *TRI) const override; ++ bool isDependencyBreak(MachineInstr &MI, unsigned *OutReg) const override; + + MachineInstr *foldMemoryOperandImpl(MachineFunction &MF, MachineInstr &MI, + unsigned OpNum, diff --git a/deps/patches/llvm-D30114.patch b/deps/patches/llvm-D30114.patch new file mode 100644 index 0000000000000..6d2cde9370d32 --- /dev/null +++ b/deps/patches/llvm-D30114.patch @@ -0,0 +1,92 @@ +From 0ee8e563c9b4c77183c4a3b5fbbbb0ed71d3d5bb Mon Sep 17 00:00:00 2001 +From: Eli Friedman +Date: Fri, 24 Feb 2017 20:51:36 +0000 +Subject: [PATCH] [CodeGenPrepare] Make -addr-sink-using-gep work with address + spaces. + +When we construct addressing modes, we use isNoopAddrSpaceCast to ignore +addrspacecast instructions. Make sure we insert the correct addrspacecast +when we reconstruct the addressing mode. + +Differential Revision: https://reviews.llvm.org/D30114 + + + +git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@296167 91177308-0d34-0410-b5e6-96231b3b80d8 +--- + lib/CodeGen/CodeGenPrepare.cpp | 8 ++++---- + test/Transforms/CodeGenPrepare/X86/sink-addrspacecast.ll | 11 ++++++++--- + 2 files changed, 12 insertions(+), 7 deletions(-) + +diff --git a/lib/CodeGen/CodeGenPrepare.cpp b/lib/CodeGen/CodeGenPrepare.cpp +index 09d8b0274e5..2c9395ca4b2 100644 +--- a/lib/CodeGen/CodeGenPrepare.cpp ++++ b/lib/CodeGen/CodeGenPrepare.cpp +@@ -4167,7 +4167,7 @@ bool CodeGenPrepare::optimizeMemoryInst(Instruction *MemoryInst, Value *Addr, + DEBUG(dbgs() << "CGP: Reusing nonlocal addrmode: " << AddrMode << " for " + << *MemoryInst << "\n"); + if (SunkAddr->getType() != Addr->getType()) +- SunkAddr = Builder.CreateBitCast(SunkAddr, Addr->getType()); ++ SunkAddr = Builder.CreatePointerCast(SunkAddr, Addr->getType()); + } else if (AddrSinkUsingGEPs || + (!AddrSinkUsingGEPs.getNumOccurrences() && TM && + SubtargetInfo->useAA())) { +@@ -4273,7 +4273,7 @@ bool CodeGenPrepare::optimizeMemoryInst(Instruction *MemoryInst, Value *Addr, + // We need to add this separately from the scale above to help with + // SDAG consecutive load/store merging. + if (ResultPtr->getType() != I8PtrTy) +- ResultPtr = Builder.CreateBitCast(ResultPtr, I8PtrTy); ++ ResultPtr = Builder.CreatePointerCast(ResultPtr, I8PtrTy); + ResultPtr = Builder.CreateGEP(I8Ty, ResultPtr, ResultIndex, "sunkaddr"); + } + +@@ -4284,12 +4284,12 @@ bool CodeGenPrepare::optimizeMemoryInst(Instruction *MemoryInst, Value *Addr, + SunkAddr = ResultPtr; + } else { + if (ResultPtr->getType() != I8PtrTy) +- ResultPtr = Builder.CreateBitCast(ResultPtr, I8PtrTy); ++ ResultPtr = Builder.CreatePointerCast(ResultPtr, I8PtrTy); + SunkAddr = Builder.CreateGEP(I8Ty, ResultPtr, ResultIndex, "sunkaddr"); + } + + if (SunkAddr->getType() != Addr->getType()) +- SunkAddr = Builder.CreateBitCast(SunkAddr, Addr->getType()); ++ SunkAddr = Builder.CreatePointerCast(SunkAddr, Addr->getType()); + } + } else { + DEBUG(dbgs() << "CGP: SINKING nonlocal addrmode: " << AddrMode << " for " +diff --git a/test/Transforms/CodeGenPrepare/X86/sink-addrspacecast.ll b/test/Transforms/CodeGenPrepare/X86/sink-addrspacecast.ll +index c9f49b5d4f8..eb2c985c70e 100644 +--- a/test/Transforms/CodeGenPrepare/X86/sink-addrspacecast.ll ++++ b/test/Transforms/CodeGenPrepare/X86/sink-addrspacecast.ll +@@ -1,11 +1,14 @@ +-; RUN: opt -S -codegenprepare < %s | FileCheck %s ++; RUN: opt -S -codegenprepare < %s | FileCheck %s -check-prefix=CHECK -check-prefix=INT ++; RUN: opt -S -codegenprepare -addr-sink-using-gep=true < %s | FileCheck %s -check-prefix=CHECK -check-prefix=GEP + + target datalayout = + "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128" + target triple = "x86_64-unknown-linux-gnu" + + ; CHECK-LABEL: @load_cast_gep +-; CHECK: add i64 %sunkaddr, 40 ++; INT: add i64 %sunkaddr, 40 ++; GEP: [[CAST:%[0-9]+]] = addrspacecast i64* %base to i8 addrspace(1)* ++; GEP: getelementptr i8, i8 addrspace(1)* [[CAST]], i64 40 + define void @load_cast_gep(i1 %cond, i64* %base) { + entry: + %addr = getelementptr inbounds i64, i64* %base, i64 5 +@@ -21,7 +24,9 @@ fallthrough: + } + + ; CHECK-LABEL: @store_gep_cast +-; CHECK: add i64 %sunkaddr, 20 ++; INT: add i64 %sunkaddr, 20 ++; GEP: [[CAST:%[0-9]+]] = addrspacecast i64* %base to i8 addrspace(1)* ++; GEP: getelementptr i8, i8 addrspace(1)* [[CAST]], i64 20 + define void @store_gep_cast(i1 %cond, i64* %base) { + entry: + %casted = addrspacecast i64* %base to i32 addrspace(1)* +-- +2.16.2 + diff --git a/deps/patches/llvm-D30478-VNCoercion.patch b/deps/patches/llvm-D30478-VNCoercion.patch new file mode 100644 index 0000000000000..99ba3d9739bf4 --- /dev/null +++ b/deps/patches/llvm-D30478-VNCoercion.patch @@ -0,0 +1,1139 @@ +From 6a7ec8843d08cb2cb8d4f55353c67d879ceacb92 Mon Sep 17 00:00:00 2001 +From: Daniel Berlin +Date: Fri, 10 Mar 2017 04:54:10 +0000 +Subject: [PATCH 1/5] Move memory coercion functions from GVN.cpp to + VNCoercion.cpp so they can be shared between GVN and NewGVN. + +Summary: +These are the functions used to determine when values of loads can be +extracted from stores, etc, and to perform the necessary insertions to +do this. There are no changes to the functions themselves except +reformatting, and one case where memdep was informed of a removed load +(which was pushed into the caller). + +Reviewers: davide + +Subscribers: mgorny, llvm-commits, Prazek + +Differential Revision: https://reviews.llvm.org/D30478 + +git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@297438 91177308-0d34-0410-b5e6-96231b3b80d8 +--- + include/llvm/Transforms/Utils/VNCoercion.h | 96 ++++++ + lib/Transforms/Scalar/GVN.cpp | 466 ++--------------------------- + lib/Transforms/Utils/CMakeLists.txt | 1 + + lib/Transforms/Utils/VNCoercion.cpp | 440 +++++++++++++++++++++++++++ + 4 files changed, 556 insertions(+), 447 deletions(-) + create mode 100644 include/llvm/Transforms/Utils/VNCoercion.h + create mode 100644 lib/Transforms/Utils/VNCoercion.cpp + +diff --git a/include/llvm/Transforms/Utils/VNCoercion.h b/include/llvm/Transforms/Utils/VNCoercion.h +new file mode 100644 +index 00000000000..d3c998fa8a8 +--- /dev/null ++++ b/include/llvm/Transforms/Utils/VNCoercion.h +@@ -0,0 +1,96 @@ ++//===- VNCoercion.h - Value Numbering Coercion Utilities --------*- C++ -*-===// ++// ++// The LLVM Compiler Infrastructure ++// ++// This file is distributed under the University of Illinois Open Source ++// License. See LICENSE.TXT for details. ++// ++//===----------------------------------------------------------------------===// ++/// \file / This file provides routines used by LLVM's value numbering passes to ++/// perform various forms of value extraction from memory when the types are not ++/// identical. For example, given ++/// ++/// store i32 8, i32 *%foo ++/// %a = bitcast i32 *%foo to i16 ++/// %val = load i16, i16 *%a ++/// ++/// It possible to extract the value of the load of %a from the store to %foo. ++/// These routines know how to tell whether they can do that (the analyze* ++/// routines), and can also insert the necessary IR to do it (the get* ++/// routines). ++ ++#ifndef LLVM_TRANSFORMS_UTILS_VNCOERCION_H ++#define LLVM_TRANSFORMS_UTILS_VNCOERCION_H ++#include "llvm/IR/IRBuilder.h" ++ ++namespace llvm { ++class Function; ++class StoreInst; ++class LoadInst; ++class MemIntrinsic; ++class Instruction; ++class Value; ++class Type; ++class DataLayout; ++namespace VNCoercion { ++/// Return true if CoerceAvailableValueToLoadType would succeed if it was ++/// called. ++bool canCoerceMustAliasedValueToLoad(Value *StoredVal, Type *LoadTy, ++ const DataLayout &DL); ++ ++/// If we saw a store of a value to memory, and then a load from a must-aliased ++/// pointer of a different type, try to coerce the stored value to the loaded ++/// type. LoadedTy is the type of the load we want to replace. IRB is ++/// IRBuilder used to insert new instructions. ++/// ++/// If we can't do it, return null. ++Value *coerceAvailableValueToLoadType(Value *StoredVal, Type *LoadedTy, ++ IRBuilder<> &IRB, const DataLayout &DL); ++ ++/// This function determines whether a value for the pointer LoadPtr can be ++/// extracted from the store at DepSI. ++/// ++/// On success, it returns the offset into DepSI that extraction would start. ++/// On failure, it returns -1. ++int analyzeLoadFromClobberingStore(Type *LoadTy, Value *LoadPtr, ++ StoreInst *DepSI); ++ ++/// This function determines whether a value for the pointer LoadPtr can be ++/// extracted from the load at DepLI. ++/// ++/// On success, it returns the offset into DepLI that extraction would start. ++/// On failure, it returns -1. ++int analyzeLoadFromClobberingLoad(Type *LoadTy, Value *LoadPtr, LoadInst *DepLI, ++ const DataLayout &DL); ++ ++/// This function determines whether a value for the pointer LoadPtr can be ++/// extracted from the memory intrinsic at DepMI. ++/// ++/// On success, it returns the offset into DepMI that extraction would start. ++/// On failure, it returns -1. ++int analyzeLoadFromClobberingMemInst(Type *LoadTy, Value *LoadPtr, ++ MemIntrinsic *DepMI, const DataLayout &DL); ++ ++/// If analyzeLoadFromClobberingStore returned an offset, this function can be ++/// used to actually perform the extraction of the bits from the store. It ++/// inserts instructions to do so at InsertPt, and returns the extracted value. ++Value *getStoreValueForLoad(Value *SrcVal, unsigned Offset, Type *LoadTy, ++ Instruction *InsertPt, const DataLayout &DL); ++ ++/// If analyzeLoadFromClobberingLoad returned an offset, this function can be ++/// used to actually perform the extraction of the bits from the load, including ++/// any necessary load widening. It inserts instructions to do so at InsertPt, ++/// and returns the extracted value. ++Value *getLoadValueForLoad(LoadInst *SrcVal, unsigned Offset, Type *LoadTy, ++ Instruction *InsertPt); ++ ++/// If analyzeLoadFromClobberingMemInst returned an offset, this function can be ++/// used to actually perform the extraction of the bits from the memory ++/// intrinsic. It inserts instructions to do so at InsertPt, and returns the ++/// extracted value. ++Value *getMemInstValueForLoad(MemIntrinsic *SrcInst, unsigned Offset, ++ Type *LoadTy, Instruction *InsertPt, ++ const DataLayout &DL); ++} ++} ++#endif +diff --git a/lib/Transforms/Scalar/GVN.cpp b/lib/Transforms/Scalar/GVN.cpp +index 0137378b828..132c7297d77 100644 +--- a/lib/Transforms/Scalar/GVN.cpp ++++ b/lib/Transforms/Scalar/GVN.cpp +@@ -36,7 +36,6 @@ + #include "llvm/Analysis/OptimizationDiagnosticInfo.h" + #include "llvm/Analysis/PHITransAddr.h" + #include "llvm/Analysis/TargetLibraryInfo.h" +-#include "llvm/Analysis/ValueTracking.h" + #include "llvm/IR/DataLayout.h" + #include "llvm/IR/Dominators.h" + #include "llvm/IR/GlobalVariable.h" +@@ -51,9 +50,12 @@ + #include "llvm/Transforms/Utils/BasicBlockUtils.h" + #include "llvm/Transforms/Utils/Local.h" + #include "llvm/Transforms/Utils/SSAUpdater.h" ++#include "llvm/Transforms/Utils/VNCoercion.h" ++ + #include + using namespace llvm; + using namespace llvm::gvn; ++using namespace llvm::VNCoercion; + using namespace PatternMatch; + + #define DEBUG_TYPE "gvn" +@@ -690,442 +692,6 @@ SpeculationFailure: + } + + +-/// Return true if CoerceAvailableValueToLoadType will succeed. +-static bool CanCoerceMustAliasedValueToLoad(Value *StoredVal, +- Type *LoadTy, +- const DataLayout &DL) { +- // If the loaded or stored value is an first class array or struct, don't try +- // to transform them. We need to be able to bitcast to integer. +- if (LoadTy->isStructTy() || LoadTy->isArrayTy() || +- StoredVal->getType()->isStructTy() || +- StoredVal->getType()->isArrayTy()) +- return false; +- +- // The store has to be at least as big as the load. +- if (DL.getTypeSizeInBits(StoredVal->getType()) < +- DL.getTypeSizeInBits(LoadTy)) +- return false; +- +- return true; +-} +- +-/// If we saw a store of a value to memory, and +-/// then a load from a must-aliased pointer of a different type, try to coerce +-/// the stored value. LoadedTy is the type of the load we want to replace. +-/// IRB is IRBuilder used to insert new instructions. +-/// +-/// If we can't do it, return null. +-static Value *CoerceAvailableValueToLoadType(Value *StoredVal, Type *LoadedTy, +- IRBuilder<> &IRB, +- const DataLayout &DL) { +- assert(CanCoerceMustAliasedValueToLoad(StoredVal, LoadedTy, DL) && +- "precondition violation - materialization can't fail"); +- +- if (auto *C = dyn_cast(StoredVal)) +- if (auto *FoldedStoredVal = ConstantFoldConstant(C, DL)) +- StoredVal = FoldedStoredVal; +- +- // If this is already the right type, just return it. +- Type *StoredValTy = StoredVal->getType(); +- +- uint64_t StoredValSize = DL.getTypeSizeInBits(StoredValTy); +- uint64_t LoadedValSize = DL.getTypeSizeInBits(LoadedTy); +- +- // If the store and reload are the same size, we can always reuse it. +- if (StoredValSize == LoadedValSize) { +- // Pointer to Pointer -> use bitcast. +- if (StoredValTy->getScalarType()->isPointerTy() && +- LoadedTy->getScalarType()->isPointerTy()) { +- StoredVal = IRB.CreateBitCast(StoredVal, LoadedTy); +- } else { +- // Convert source pointers to integers, which can be bitcast. +- if (StoredValTy->getScalarType()->isPointerTy()) { +- StoredValTy = DL.getIntPtrType(StoredValTy); +- StoredVal = IRB.CreatePtrToInt(StoredVal, StoredValTy); +- } +- +- Type *TypeToCastTo = LoadedTy; +- if (TypeToCastTo->getScalarType()->isPointerTy()) +- TypeToCastTo = DL.getIntPtrType(TypeToCastTo); +- +- if (StoredValTy != TypeToCastTo) +- StoredVal = IRB.CreateBitCast(StoredVal, TypeToCastTo); +- +- // Cast to pointer if the load needs a pointer type. +- if (LoadedTy->getScalarType()->isPointerTy()) +- StoredVal = IRB.CreateIntToPtr(StoredVal, LoadedTy); +- } +- +- if (auto *C = dyn_cast(StoredVal)) +- if (auto *FoldedStoredVal = ConstantFoldConstant(C, DL)) +- StoredVal = FoldedStoredVal; +- +- return StoredVal; +- } +- +- // If the loaded value is smaller than the available value, then we can +- // extract out a piece from it. If the available value is too small, then we +- // can't do anything. +- assert(StoredValSize >= LoadedValSize && +- "CanCoerceMustAliasedValueToLoad fail"); +- +- // Convert source pointers to integers, which can be manipulated. +- if (StoredValTy->getScalarType()->isPointerTy()) { +- StoredValTy = DL.getIntPtrType(StoredValTy); +- StoredVal = IRB.CreatePtrToInt(StoredVal, StoredValTy); +- } +- +- // Convert vectors and fp to integer, which can be manipulated. +- if (!StoredValTy->isIntegerTy()) { +- StoredValTy = IntegerType::get(StoredValTy->getContext(), StoredValSize); +- StoredVal = IRB.CreateBitCast(StoredVal, StoredValTy); +- } +- +- // If this is a big-endian system, we need to shift the value down to the low +- // bits so that a truncate will work. +- if (DL.isBigEndian()) { +- uint64_t ShiftAmt = DL.getTypeStoreSizeInBits(StoredValTy) - +- DL.getTypeStoreSizeInBits(LoadedTy); +- StoredVal = IRB.CreateLShr(StoredVal, ShiftAmt, "tmp"); +- } +- +- // Truncate the integer to the right size now. +- Type *NewIntTy = IntegerType::get(StoredValTy->getContext(), LoadedValSize); +- StoredVal = IRB.CreateTrunc(StoredVal, NewIntTy, "trunc"); +- +- if (LoadedTy != NewIntTy) { +- // If the result is a pointer, inttoptr. +- if (LoadedTy->getScalarType()->isPointerTy()) +- StoredVal = IRB.CreateIntToPtr(StoredVal, LoadedTy, "inttoptr"); +- else +- // Otherwise, bitcast. +- StoredVal = IRB.CreateBitCast(StoredVal, LoadedTy, "bitcast"); +- } +- +- if (auto *C = dyn_cast(StoredVal)) +- if (auto *FoldedStoredVal = ConstantFoldConstant(C, DL)) +- StoredVal = FoldedStoredVal; +- +- return StoredVal; +-} +- +-/// This function is called when we have a +-/// memdep query of a load that ends up being a clobbering memory write (store, +-/// memset, memcpy, memmove). This means that the write *may* provide bits used +-/// by the load but we can't be sure because the pointers don't mustalias. +-/// +-/// Check this case to see if there is anything more we can do before we give +-/// up. This returns -1 if we have to give up, or a byte number in the stored +-/// value of the piece that feeds the load. +-static int AnalyzeLoadFromClobberingWrite(Type *LoadTy, Value *LoadPtr, +- Value *WritePtr, +- uint64_t WriteSizeInBits, +- const DataLayout &DL) { +- // If the loaded or stored value is a first class array or struct, don't try +- // to transform them. We need to be able to bitcast to integer. +- if (LoadTy->isStructTy() || LoadTy->isArrayTy()) +- return -1; +- +- int64_t StoreOffset = 0, LoadOffset = 0; +- Value *StoreBase = +- GetPointerBaseWithConstantOffset(WritePtr, StoreOffset, DL); +- Value *LoadBase = GetPointerBaseWithConstantOffset(LoadPtr, LoadOffset, DL); +- if (StoreBase != LoadBase) +- return -1; +- +- // If the load and store are to the exact same address, they should have been +- // a must alias. AA must have gotten confused. +- // FIXME: Study to see if/when this happens. One case is forwarding a memset +- // to a load from the base of the memset. +- +- // If the load and store don't overlap at all, the store doesn't provide +- // anything to the load. In this case, they really don't alias at all, AA +- // must have gotten confused. +- uint64_t LoadSize = DL.getTypeSizeInBits(LoadTy); +- +- if ((WriteSizeInBits & 7) | (LoadSize & 7)) +- return -1; +- uint64_t StoreSize = WriteSizeInBits / 8; // Convert to bytes. +- LoadSize /= 8; +- +- +- bool isAAFailure = false; +- if (StoreOffset < LoadOffset) +- isAAFailure = StoreOffset+int64_t(StoreSize) <= LoadOffset; +- else +- isAAFailure = LoadOffset+int64_t(LoadSize) <= StoreOffset; +- +- if (isAAFailure) +- return -1; +- +- // If the Load isn't completely contained within the stored bits, we don't +- // have all the bits to feed it. We could do something crazy in the future +- // (issue a smaller load then merge the bits in) but this seems unlikely to be +- // valuable. +- if (StoreOffset > LoadOffset || +- StoreOffset+StoreSize < LoadOffset+LoadSize) +- return -1; +- +- // Okay, we can do this transformation. Return the number of bytes into the +- // store that the load is. +- return LoadOffset-StoreOffset; +-} +- +-/// This function is called when we have a +-/// memdep query of a load that ends up being a clobbering store. +-static int AnalyzeLoadFromClobberingStore(Type *LoadTy, Value *LoadPtr, +- StoreInst *DepSI) { +- // Cannot handle reading from store of first-class aggregate yet. +- if (DepSI->getValueOperand()->getType()->isStructTy() || +- DepSI->getValueOperand()->getType()->isArrayTy()) +- return -1; +- +- const DataLayout &DL = DepSI->getModule()->getDataLayout(); +- Value *StorePtr = DepSI->getPointerOperand(); +- uint64_t StoreSize =DL.getTypeSizeInBits(DepSI->getValueOperand()->getType()); +- return AnalyzeLoadFromClobberingWrite(LoadTy, LoadPtr, +- StorePtr, StoreSize, DL); +-} +- +-/// This function is called when we have a +-/// memdep query of a load that ends up being clobbered by another load. See if +-/// the other load can feed into the second load. +-static int AnalyzeLoadFromClobberingLoad(Type *LoadTy, Value *LoadPtr, +- LoadInst *DepLI, const DataLayout &DL){ +- // Cannot handle reading from store of first-class aggregate yet. +- if (DepLI->getType()->isStructTy() || DepLI->getType()->isArrayTy()) +- return -1; +- +- Value *DepPtr = DepLI->getPointerOperand(); +- uint64_t DepSize = DL.getTypeSizeInBits(DepLI->getType()); +- int R = AnalyzeLoadFromClobberingWrite(LoadTy, LoadPtr, DepPtr, DepSize, DL); +- if (R != -1) return R; +- +- // If we have a load/load clobber an DepLI can be widened to cover this load, +- // then we should widen it! +- int64_t LoadOffs = 0; +- const Value *LoadBase = +- GetPointerBaseWithConstantOffset(LoadPtr, LoadOffs, DL); +- unsigned LoadSize = DL.getTypeStoreSize(LoadTy); +- +- unsigned Size = MemoryDependenceResults::getLoadLoadClobberFullWidthSize( +- LoadBase, LoadOffs, LoadSize, DepLI); +- if (Size == 0) return -1; +- +- // Check non-obvious conditions enforced by MDA which we rely on for being +- // able to materialize this potentially available value +- assert(DepLI->isSimple() && "Cannot widen volatile/atomic load!"); +- assert(DepLI->getType()->isIntegerTy() && "Can't widen non-integer load"); +- +- return AnalyzeLoadFromClobberingWrite(LoadTy, LoadPtr, DepPtr, Size*8, DL); +-} +- +- +- +-static int AnalyzeLoadFromClobberingMemInst(Type *LoadTy, Value *LoadPtr, +- MemIntrinsic *MI, +- const DataLayout &DL) { +- // If the mem operation is a non-constant size, we can't handle it. +- ConstantInt *SizeCst = dyn_cast(MI->getLength()); +- if (!SizeCst) return -1; +- uint64_t MemSizeInBits = SizeCst->getZExtValue()*8; +- +- // If this is memset, we just need to see if the offset is valid in the size +- // of the memset.. +- if (MI->getIntrinsicID() == Intrinsic::memset) +- return AnalyzeLoadFromClobberingWrite(LoadTy, LoadPtr, MI->getDest(), +- MemSizeInBits, DL); +- +- // If we have a memcpy/memmove, the only case we can handle is if this is a +- // copy from constant memory. In that case, we can read directly from the +- // constant memory. +- MemTransferInst *MTI = cast(MI); +- +- Constant *Src = dyn_cast(MTI->getSource()); +- if (!Src) return -1; +- +- GlobalVariable *GV = dyn_cast(GetUnderlyingObject(Src, DL)); +- if (!GV || !GV->isConstant()) return -1; +- +- // See if the access is within the bounds of the transfer. +- int Offset = AnalyzeLoadFromClobberingWrite(LoadTy, LoadPtr, +- MI->getDest(), MemSizeInBits, DL); +- if (Offset == -1) +- return Offset; +- +- unsigned AS = Src->getType()->getPointerAddressSpace(); +- // Otherwise, see if we can constant fold a load from the constant with the +- // offset applied as appropriate. +- Src = ConstantExpr::getBitCast(Src, +- Type::getInt8PtrTy(Src->getContext(), AS)); +- Constant *OffsetCst = +- ConstantInt::get(Type::getInt64Ty(Src->getContext()), (unsigned)Offset); +- Src = ConstantExpr::getGetElementPtr(Type::getInt8Ty(Src->getContext()), Src, +- OffsetCst); +- Src = ConstantExpr::getBitCast(Src, PointerType::get(LoadTy, AS)); +- if (ConstantFoldLoadFromConstPtr(Src, LoadTy, DL)) +- return Offset; +- return -1; +-} +- +- +-/// This function is called when we have a +-/// memdep query of a load that ends up being a clobbering store. This means +-/// that the store provides bits used by the load but we the pointers don't +-/// mustalias. Check this case to see if there is anything more we can do +-/// before we give up. +-static Value *GetStoreValueForLoad(Value *SrcVal, unsigned Offset, +- Type *LoadTy, +- Instruction *InsertPt, const DataLayout &DL){ +- LLVMContext &Ctx = SrcVal->getType()->getContext(); +- +- uint64_t StoreSize = (DL.getTypeSizeInBits(SrcVal->getType()) + 7) / 8; +- uint64_t LoadSize = (DL.getTypeSizeInBits(LoadTy) + 7) / 8; +- +- IRBuilder<> Builder(InsertPt); +- +- // Compute which bits of the stored value are being used by the load. Convert +- // to an integer type to start with. +- if (SrcVal->getType()->getScalarType()->isPointerTy()) +- SrcVal = Builder.CreatePtrToInt(SrcVal, +- DL.getIntPtrType(SrcVal->getType())); +- if (!SrcVal->getType()->isIntegerTy()) +- SrcVal = Builder.CreateBitCast(SrcVal, IntegerType::get(Ctx, StoreSize*8)); +- +- // Shift the bits to the least significant depending on endianness. +- unsigned ShiftAmt; +- if (DL.isLittleEndian()) +- ShiftAmt = Offset*8; +- else +- ShiftAmt = (StoreSize-LoadSize-Offset)*8; +- +- if (ShiftAmt) +- SrcVal = Builder.CreateLShr(SrcVal, ShiftAmt); +- +- if (LoadSize != StoreSize) +- SrcVal = Builder.CreateTrunc(SrcVal, IntegerType::get(Ctx, LoadSize*8)); +- +- return CoerceAvailableValueToLoadType(SrcVal, LoadTy, Builder, DL); +-} +- +-/// This function is called when we have a +-/// memdep query of a load that ends up being a clobbering load. This means +-/// that the load *may* provide bits used by the load but we can't be sure +-/// because the pointers don't mustalias. Check this case to see if there is +-/// anything more we can do before we give up. +-static Value *GetLoadValueForLoad(LoadInst *SrcVal, unsigned Offset, +- Type *LoadTy, Instruction *InsertPt, +- GVN &gvn) { +- const DataLayout &DL = SrcVal->getModule()->getDataLayout(); +- // If Offset+LoadTy exceeds the size of SrcVal, then we must be wanting to +- // widen SrcVal out to a larger load. +- unsigned SrcValStoreSize = DL.getTypeStoreSize(SrcVal->getType()); +- unsigned LoadSize = DL.getTypeStoreSize(LoadTy); +- if (Offset+LoadSize > SrcValStoreSize) { +- assert(SrcVal->isSimple() && "Cannot widen volatile/atomic load!"); +- assert(SrcVal->getType()->isIntegerTy() && "Can't widen non-integer load"); +- // If we have a load/load clobber an DepLI can be widened to cover this +- // load, then we should widen it to the next power of 2 size big enough! +- unsigned NewLoadSize = Offset+LoadSize; +- if (!isPowerOf2_32(NewLoadSize)) +- NewLoadSize = NextPowerOf2(NewLoadSize); +- +- Value *PtrVal = SrcVal->getPointerOperand(); +- +- // Insert the new load after the old load. This ensures that subsequent +- // memdep queries will find the new load. We can't easily remove the old +- // load completely because it is already in the value numbering table. +- IRBuilder<> Builder(SrcVal->getParent(), ++BasicBlock::iterator(SrcVal)); +- Type *DestPTy = +- IntegerType::get(LoadTy->getContext(), NewLoadSize*8); +- DestPTy = PointerType::get(DestPTy, +- PtrVal->getType()->getPointerAddressSpace()); +- Builder.SetCurrentDebugLocation(SrcVal->getDebugLoc()); +- PtrVal = Builder.CreateBitCast(PtrVal, DestPTy); +- LoadInst *NewLoad = Builder.CreateLoad(PtrVal); +- NewLoad->takeName(SrcVal); +- NewLoad->setAlignment(SrcVal->getAlignment()); +- +- DEBUG(dbgs() << "GVN WIDENED LOAD: " << *SrcVal << "\n"); +- DEBUG(dbgs() << "TO: " << *NewLoad << "\n"); +- +- // Replace uses of the original load with the wider load. On a big endian +- // system, we need to shift down to get the relevant bits. +- Value *RV = NewLoad; +- if (DL.isBigEndian()) +- RV = Builder.CreateLShr(RV, (NewLoadSize - SrcValStoreSize) * 8); +- RV = Builder.CreateTrunc(RV, SrcVal->getType()); +- SrcVal->replaceAllUsesWith(RV); +- +- // We would like to use gvn.markInstructionForDeletion here, but we can't +- // because the load is already memoized into the leader map table that GVN +- // tracks. It is potentially possible to remove the load from the table, +- // but then there all of the operations based on it would need to be +- // rehashed. Just leave the dead load around. +- gvn.getMemDep().removeInstruction(SrcVal); +- SrcVal = NewLoad; +- } +- +- return GetStoreValueForLoad(SrcVal, Offset, LoadTy, InsertPt, DL); +-} +- +- +-/// This function is called when we have a +-/// memdep query of a load that ends up being a clobbering mem intrinsic. +-static Value *GetMemInstValueForLoad(MemIntrinsic *SrcInst, unsigned Offset, +- Type *LoadTy, Instruction *InsertPt, +- const DataLayout &DL){ +- LLVMContext &Ctx = LoadTy->getContext(); +- uint64_t LoadSize = DL.getTypeSizeInBits(LoadTy)/8; +- +- IRBuilder<> Builder(InsertPt); +- +- // We know that this method is only called when the mem transfer fully +- // provides the bits for the load. +- if (MemSetInst *MSI = dyn_cast(SrcInst)) { +- // memset(P, 'x', 1234) -> splat('x'), even if x is a variable, and +- // independently of what the offset is. +- Value *Val = MSI->getValue(); +- if (LoadSize != 1) +- Val = Builder.CreateZExt(Val, IntegerType::get(Ctx, LoadSize*8)); +- +- Value *OneElt = Val; +- +- // Splat the value out to the right number of bits. +- for (unsigned NumBytesSet = 1; NumBytesSet != LoadSize; ) { +- // If we can double the number of bytes set, do it. +- if (NumBytesSet*2 <= LoadSize) { +- Value *ShVal = Builder.CreateShl(Val, NumBytesSet*8); +- Val = Builder.CreateOr(Val, ShVal); +- NumBytesSet <<= 1; +- continue; +- } +- +- // Otherwise insert one byte at a time. +- Value *ShVal = Builder.CreateShl(Val, 1*8); +- Val = Builder.CreateOr(OneElt, ShVal); +- ++NumBytesSet; +- } +- +- return CoerceAvailableValueToLoadType(Val, LoadTy, Builder, DL); +- } +- +- // Otherwise, this is a memcpy/memmove from a constant global. +- MemTransferInst *MTI = cast(SrcInst); +- Constant *Src = cast(MTI->getSource()); +- unsigned AS = Src->getType()->getPointerAddressSpace(); +- +- // Otherwise, see if we can constant fold a load from the constant with the +- // offset applied as appropriate. +- Src = ConstantExpr::getBitCast(Src, +- Type::getInt8PtrTy(Src->getContext(), AS)); +- Constant *OffsetCst = +- ConstantInt::get(Type::getInt64Ty(Src->getContext()), (unsigned)Offset); +- Src = ConstantExpr::getGetElementPtr(Type::getInt8Ty(Src->getContext()), Src, +- OffsetCst); +- Src = ConstantExpr::getBitCast(Src, PointerType::get(LoadTy, AS)); +- return ConstantFoldLoadFromConstPtr(Src, LoadTy, DL); +-} + + + /// Given a set of loads specified by ValuesPerBlock, +@@ -1171,7 +737,7 @@ Value *AvailableValue::MaterializeAdjustedValue(LoadInst *LI, + if (isSimpleValue()) { + Res = getSimpleValue(); + if (Res->getType() != LoadTy) { +- Res = GetStoreValueForLoad(Res, Offset, LoadTy, InsertPt, DL); ++ Res = getStoreValueForLoad(Res, Offset, LoadTy, InsertPt, DL); + + DEBUG(dbgs() << "GVN COERCED NONLOCAL VAL:\nOffset: " << Offset << " " + << *getSimpleValue() << '\n' +@@ -1182,14 +748,20 @@ Value *AvailableValue::MaterializeAdjustedValue(LoadInst *LI, + if (Load->getType() == LoadTy && Offset == 0) { + Res = Load; + } else { +- Res = GetLoadValueForLoad(Load, Offset, LoadTy, InsertPt, gvn); +- ++ Res = getLoadValueForLoad(Load, Offset, LoadTy, InsertPt); ++ // We would like to use gvn.markInstructionForDeletion here, but we can't ++ // because the load is already memoized into the leader map table that GVN ++ // tracks. It is potentially possible to remove the load from the table, ++ // but then there all of the operations based on it would need to be ++ // rehashed. Just leave the dead load around. ++ gvn.getMemDep().removeInstruction(Load); + DEBUG(dbgs() << "GVN COERCED NONLOCAL LOAD:\nOffset: " << Offset << " " + << *getCoercedLoadValue() << '\n' +- << *Res << '\n' << "\n\n\n"); ++ << *Res << '\n' ++ << "\n\n\n"); + } + } else if (isMemIntrinValue()) { +- Res = GetMemInstValueForLoad(getMemIntrinValue(), Offset, LoadTy, ++ Res = getMemInstValueForLoad(getMemIntrinValue(), Offset, LoadTy, + InsertPt, DL); + DEBUG(dbgs() << "GVN COERCED NONLOCAL MEM INTRIN:\nOffset: " << Offset + << " " << *getMemIntrinValue() << '\n' +@@ -1258,7 +830,7 @@ bool GVN::AnalyzeLoadAvailability(LoadInst *LI, MemDepResult DepInfo, + // Can't forward from non-atomic to atomic without violating memory model. + if (Address && LI->isAtomic() <= DepSI->isAtomic()) { + int Offset = +- AnalyzeLoadFromClobberingStore(LI->getType(), Address, DepSI); ++ analyzeLoadFromClobberingStore(LI->getType(), Address, DepSI); + if (Offset != -1) { + Res = AvailableValue::get(DepSI->getValueOperand(), Offset); + return true; +@@ -1276,7 +848,7 @@ bool GVN::AnalyzeLoadAvailability(LoadInst *LI, MemDepResult DepInfo, + // Can't forward from non-atomic to atomic without violating memory model. + if (DepLI != LI && Address && LI->isAtomic() <= DepLI->isAtomic()) { + int Offset = +- AnalyzeLoadFromClobberingLoad(LI->getType(), Address, DepLI, DL); ++ analyzeLoadFromClobberingLoad(LI->getType(), Address, DepLI, DL); + + if (Offset != -1) { + Res = AvailableValue::getLoad(DepLI, Offset); +@@ -1289,7 +861,7 @@ bool GVN::AnalyzeLoadAvailability(LoadInst *LI, MemDepResult DepInfo, + // forward a value on from it. + if (MemIntrinsic *DepMI = dyn_cast(DepInfo.getInst())) { + if (Address && !LI->isAtomic()) { +- int Offset = AnalyzeLoadFromClobberingMemInst(LI->getType(), Address, ++ int Offset = analyzeLoadFromClobberingMemInst(LI->getType(), Address, + DepMI, DL); + if (Offset != -1) { + Res = AvailableValue::getMI(DepMI, Offset); +@@ -1334,7 +906,7 @@ bool GVN::AnalyzeLoadAvailability(LoadInst *LI, MemDepResult DepInfo, + // different types if we have to. If the stored value is larger or equal to + // the loaded value, we can reuse it. + if (S->getValueOperand()->getType() != LI->getType() && +- !CanCoerceMustAliasedValueToLoad(S->getValueOperand(), ++ !canCoerceMustAliasedValueToLoad(S->getValueOperand(), + LI->getType(), DL)) + return false; + +@@ -1351,7 +923,7 @@ bool GVN::AnalyzeLoadAvailability(LoadInst *LI, MemDepResult DepInfo, + // If the stored value is larger or equal to the loaded value, we can reuse + // it. + if (LD->getType() != LI->getType() && +- !CanCoerceMustAliasedValueToLoad(LD, LI->getType(), DL)) ++ !canCoerceMustAliasedValueToLoad(LD, LI->getType(), DL)) + return false; + + // Can't forward from non-atomic to atomic without violating memory model. +diff --git a/lib/Transforms/Utils/CMakeLists.txt b/lib/Transforms/Utils/CMakeLists.txt +index 69889ec72f9..838761fd71d 100644 +--- a/lib/Transforms/Utils/CMakeLists.txt ++++ b/lib/Transforms/Utils/CMakeLists.txt +@@ -51,6 +51,7 @@ add_llvm_library(LLVMTransformUtils + UnifyFunctionExitNodes.cpp + Utils.cpp + ValueMapper.cpp ++ VNCoercion.cpp + + ADDITIONAL_HEADER_DIRS + ${LLVM_MAIN_INCLUDE_DIR}/llvm/Transforms +diff --git a/lib/Transforms/Utils/VNCoercion.cpp b/lib/Transforms/Utils/VNCoercion.cpp +new file mode 100644 +index 00000000000..38d26e922c3 +--- /dev/null ++++ b/lib/Transforms/Utils/VNCoercion.cpp +@@ -0,0 +1,440 @@ ++#include "llvm/Transforms/Utils/VNCoercion.h" ++#include "llvm/Analysis/AliasAnalysis.h" ++#include "llvm/Analysis/ConstantFolding.h" ++#include "llvm/Analysis/MemoryDependenceAnalysis.h" ++#include "llvm/Analysis/ValueTracking.h" ++#include "llvm/IR/IRBuilder.h" ++#include "llvm/IR/IntrinsicInst.h" ++#include "llvm/Support/Debug.h" ++ ++#define DEBUG_TYPE "vncoerce" ++namespace llvm { ++namespace VNCoercion { ++ ++/// Return true if coerceAvailableValueToLoadType will succeed. ++bool canCoerceMustAliasedValueToLoad(Value *StoredVal, Type *LoadTy, ++ const DataLayout &DL) { ++ // If the loaded or stored value is an first class array or struct, don't try ++ // to transform them. We need to be able to bitcast to integer. ++ if (LoadTy->isStructTy() || LoadTy->isArrayTy() || ++ StoredVal->getType()->isStructTy() || StoredVal->getType()->isArrayTy()) ++ return false; ++ ++ // The store has to be at least as big as the load. ++ if (DL.getTypeSizeInBits(StoredVal->getType()) < DL.getTypeSizeInBits(LoadTy)) ++ return false; ++ ++ return true; ++} ++ ++/// If we saw a store of a value to memory, and ++/// then a load from a must-aliased pointer of a different type, try to coerce ++/// the stored value. LoadedTy is the type of the load we want to replace. ++/// IRB is IRBuilder used to insert new instructions. ++/// ++/// If we can't do it, return null. ++Value *coerceAvailableValueToLoadType(Value *StoredVal, Type *LoadedTy, ++ IRBuilder<> &IRB, const DataLayout &DL) { ++ assert(canCoerceMustAliasedValueToLoad(StoredVal, LoadedTy, DL) && ++ "precondition violation - materialization can't fail"); ++ ++ if (auto *C = dyn_cast(StoredVal)) ++ if (auto *FoldedStoredVal = ConstantFoldConstant(C, DL)) ++ StoredVal = FoldedStoredVal; ++ ++ // If this is already the right type, just return it. ++ Type *StoredValTy = StoredVal->getType(); ++ ++ uint64_t StoredValSize = DL.getTypeSizeInBits(StoredValTy); ++ uint64_t LoadedValSize = DL.getTypeSizeInBits(LoadedTy); ++ ++ // If the store and reload are the same size, we can always reuse it. ++ if (StoredValSize == LoadedValSize) { ++ // Pointer to Pointer -> use bitcast. ++ if (StoredValTy->getScalarType()->isPointerTy() && ++ LoadedTy->getScalarType()->isPointerTy()) { ++ StoredVal = IRB.CreateBitCast(StoredVal, LoadedTy); ++ } else { ++ // Convert source pointers to integers, which can be bitcast. ++ if (StoredValTy->getScalarType()->isPointerTy()) { ++ StoredValTy = DL.getIntPtrType(StoredValTy); ++ StoredVal = IRB.CreatePtrToInt(StoredVal, StoredValTy); ++ } ++ ++ Type *TypeToCastTo = LoadedTy; ++ if (TypeToCastTo->getScalarType()->isPointerTy()) ++ TypeToCastTo = DL.getIntPtrType(TypeToCastTo); ++ ++ if (StoredValTy != TypeToCastTo) ++ StoredVal = IRB.CreateBitCast(StoredVal, TypeToCastTo); ++ ++ // Cast to pointer if the load needs a pointer type. ++ if (LoadedTy->getScalarType()->isPointerTy()) ++ StoredVal = IRB.CreateIntToPtr(StoredVal, LoadedTy); ++ } ++ ++ if (auto *C = dyn_cast(StoredVal)) ++ if (auto *FoldedStoredVal = ConstantFoldConstant(C, DL)) ++ StoredVal = FoldedStoredVal; ++ ++ return StoredVal; ++ } ++ ++ // If the loaded value is smaller than the available value, then we can ++ // extract out a piece from it. If the available value is too small, then we ++ // can't do anything. ++ assert(StoredValSize >= LoadedValSize && ++ "canCoerceMustAliasedValueToLoad fail"); ++ ++ // Convert source pointers to integers, which can be manipulated. ++ if (StoredValTy->getScalarType()->isPointerTy()) { ++ StoredValTy = DL.getIntPtrType(StoredValTy); ++ StoredVal = IRB.CreatePtrToInt(StoredVal, StoredValTy); ++ } ++ ++ // Convert vectors and fp to integer, which can be manipulated. ++ if (!StoredValTy->isIntegerTy()) { ++ StoredValTy = IntegerType::get(StoredValTy->getContext(), StoredValSize); ++ StoredVal = IRB.CreateBitCast(StoredVal, StoredValTy); ++ } ++ ++ // If this is a big-endian system, we need to shift the value down to the low ++ // bits so that a truncate will work. ++ if (DL.isBigEndian()) { ++ uint64_t ShiftAmt = DL.getTypeStoreSizeInBits(StoredValTy) - ++ DL.getTypeStoreSizeInBits(LoadedTy); ++ StoredVal = IRB.CreateLShr(StoredVal, ShiftAmt, "tmp"); ++ } ++ ++ // Truncate the integer to the right size now. ++ Type *NewIntTy = IntegerType::get(StoredValTy->getContext(), LoadedValSize); ++ StoredVal = IRB.CreateTrunc(StoredVal, NewIntTy, "trunc"); ++ ++ if (LoadedTy != NewIntTy) { ++ // If the result is a pointer, inttoptr. ++ if (LoadedTy->getScalarType()->isPointerTy()) ++ StoredVal = IRB.CreateIntToPtr(StoredVal, LoadedTy, "inttoptr"); ++ else ++ // Otherwise, bitcast. ++ StoredVal = IRB.CreateBitCast(StoredVal, LoadedTy, "bitcast"); ++ } ++ ++ if (auto *C = dyn_cast(StoredVal)) ++ if (auto *FoldedStoredVal = ConstantFoldConstant(C, DL)) ++ StoredVal = FoldedStoredVal; ++ ++ return StoredVal; ++} ++ ++/// This function is called when we have a ++/// memdep query of a load that ends up being a clobbering memory write (store, ++/// memset, memcpy, memmove). This means that the write *may* provide bits used ++/// by the load but we can't be sure because the pointers don't mustalias. ++/// ++/// Check this case to see if there is anything more we can do before we give ++/// up. This returns -1 if we have to give up, or a byte number in the stored ++/// value of the piece that feeds the load. ++static int analyzeLoadFromClobberingWrite(Type *LoadTy, Value *LoadPtr, ++ Value *WritePtr, ++ uint64_t WriteSizeInBits, ++ const DataLayout &DL) { ++ // If the loaded or stored value is a first class array or struct, don't try ++ // to transform them. We need to be able to bitcast to integer. ++ if (LoadTy->isStructTy() || LoadTy->isArrayTy()) ++ return -1; ++ ++ int64_t StoreOffset = 0, LoadOffset = 0; ++ Value *StoreBase = ++ GetPointerBaseWithConstantOffset(WritePtr, StoreOffset, DL); ++ Value *LoadBase = GetPointerBaseWithConstantOffset(LoadPtr, LoadOffset, DL); ++ if (StoreBase != LoadBase) ++ return -1; ++ ++ // If the load and store are to the exact same address, they should have been ++ // a must alias. AA must have gotten confused. ++ // FIXME: Study to see if/when this happens. One case is forwarding a memset ++ // to a load from the base of the memset. ++ ++ // If the load and store don't overlap at all, the store doesn't provide ++ // anything to the load. In this case, they really don't alias at all, AA ++ // must have gotten confused. ++ uint64_t LoadSize = DL.getTypeSizeInBits(LoadTy); ++ ++ if ((WriteSizeInBits & 7) | (LoadSize & 7)) ++ return -1; ++ uint64_t StoreSize = WriteSizeInBits / 8; // Convert to bytes. ++ LoadSize /= 8; ++ ++ bool isAAFailure = false; ++ if (StoreOffset < LoadOffset) ++ isAAFailure = StoreOffset + int64_t(StoreSize) <= LoadOffset; ++ else ++ isAAFailure = LoadOffset + int64_t(LoadSize) <= StoreOffset; ++ ++ if (isAAFailure) ++ return -1; ++ ++ // If the Load isn't completely contained within the stored bits, we don't ++ // have all the bits to feed it. We could do something crazy in the future ++ // (issue a smaller load then merge the bits in) but this seems unlikely to be ++ // valuable. ++ if (StoreOffset > LoadOffset || ++ StoreOffset + StoreSize < LoadOffset + LoadSize) ++ return -1; ++ ++ // Okay, we can do this transformation. Return the number of bytes into the ++ // store that the load is. ++ return LoadOffset - StoreOffset; ++} ++ ++/// This function is called when we have a ++/// memdep query of a load that ends up being a clobbering store. ++int analyzeLoadFromClobberingStore(Type *LoadTy, Value *LoadPtr, ++ StoreInst *DepSI) { ++ // Cannot handle reading from store of first-class aggregate yet. ++ if (DepSI->getValueOperand()->getType()->isStructTy() || ++ DepSI->getValueOperand()->getType()->isArrayTy()) ++ return -1; ++ ++ const DataLayout &DL = DepSI->getModule()->getDataLayout(); ++ Value *StorePtr = DepSI->getPointerOperand(); ++ uint64_t StoreSize = ++ DL.getTypeSizeInBits(DepSI->getValueOperand()->getType()); ++ return analyzeLoadFromClobberingWrite(LoadTy, LoadPtr, StorePtr, StoreSize, ++ DL); ++} ++ ++/// This function is called when we have a ++/// memdep query of a load that ends up being clobbered by another load. See if ++/// the other load can feed into the second load. ++int analyzeLoadFromClobberingLoad(Type *LoadTy, Value *LoadPtr, LoadInst *DepLI, ++ const DataLayout &DL) { ++ // Cannot handle reading from store of first-class aggregate yet. ++ if (DepLI->getType()->isStructTy() || DepLI->getType()->isArrayTy()) ++ return -1; ++ ++ Value *DepPtr = DepLI->getPointerOperand(); ++ uint64_t DepSize = DL.getTypeSizeInBits(DepLI->getType()); ++ int R = analyzeLoadFromClobberingWrite(LoadTy, LoadPtr, DepPtr, DepSize, DL); ++ if (R != -1) ++ return R; ++ ++ // If we have a load/load clobber an DepLI can be widened to cover this load, ++ // then we should widen it! ++ int64_t LoadOffs = 0; ++ const Value *LoadBase = ++ GetPointerBaseWithConstantOffset(LoadPtr, LoadOffs, DL); ++ unsigned LoadSize = DL.getTypeStoreSize(LoadTy); ++ ++ unsigned Size = MemoryDependenceResults::getLoadLoadClobberFullWidthSize( ++ LoadBase, LoadOffs, LoadSize, DepLI); ++ if (Size == 0) ++ return -1; ++ ++ // Check non-obvious conditions enforced by MDA which we rely on for being ++ // able to materialize this potentially available value ++ assert(DepLI->isSimple() && "Cannot widen volatile/atomic load!"); ++ assert(DepLI->getType()->isIntegerTy() && "Can't widen non-integer load"); ++ ++ return analyzeLoadFromClobberingWrite(LoadTy, LoadPtr, DepPtr, Size * 8, DL); ++} ++ ++int analyzeLoadFromClobberingMemInst(Type *LoadTy, Value *LoadPtr, ++ MemIntrinsic *MI, const DataLayout &DL) { ++ // If the mem operation is a non-constant size, we can't handle it. ++ ConstantInt *SizeCst = dyn_cast(MI->getLength()); ++ if (!SizeCst) ++ return -1; ++ uint64_t MemSizeInBits = SizeCst->getZExtValue() * 8; ++ ++ // If this is memset, we just need to see if the offset is valid in the size ++ // of the memset.. ++ if (MI->getIntrinsicID() == Intrinsic::memset) ++ return analyzeLoadFromClobberingWrite(LoadTy, LoadPtr, MI->getDest(), ++ MemSizeInBits, DL); ++ ++ // If we have a memcpy/memmove, the only case we can handle is if this is a ++ // copy from constant memory. In that case, we can read directly from the ++ // constant memory. ++ MemTransferInst *MTI = cast(MI); ++ ++ Constant *Src = dyn_cast(MTI->getSource()); ++ if (!Src) ++ return -1; ++ ++ GlobalVariable *GV = dyn_cast(GetUnderlyingObject(Src, DL)); ++ if (!GV || !GV->isConstant()) ++ return -1; ++ ++ // See if the access is within the bounds of the transfer. ++ int Offset = analyzeLoadFromClobberingWrite(LoadTy, LoadPtr, MI->getDest(), ++ MemSizeInBits, DL); ++ if (Offset == -1) ++ return Offset; ++ ++ unsigned AS = Src->getType()->getPointerAddressSpace(); ++ // Otherwise, see if we can constant fold a load from the constant with the ++ // offset applied as appropriate. ++ Src = ++ ConstantExpr::getBitCast(Src, Type::getInt8PtrTy(Src->getContext(), AS)); ++ Constant *OffsetCst = ++ ConstantInt::get(Type::getInt64Ty(Src->getContext()), (unsigned)Offset); ++ Src = ConstantExpr::getGetElementPtr(Type::getInt8Ty(Src->getContext()), Src, ++ OffsetCst); ++ Src = ConstantExpr::getBitCast(Src, PointerType::get(LoadTy, AS)); ++ if (ConstantFoldLoadFromConstPtr(Src, LoadTy, DL)) ++ return Offset; ++ return -1; ++} ++ ++/// This function is called when we have a ++/// memdep query of a load that ends up being a clobbering store. This means ++/// that the store provides bits used by the load but we the pointers don't ++/// mustalias. Check this case to see if there is anything more we can do ++/// before we give up. ++Value *getStoreValueForLoad(Value *SrcVal, unsigned Offset, Type *LoadTy, ++ Instruction *InsertPt, const DataLayout &DL) { ++ LLVMContext &Ctx = SrcVal->getType()->getContext(); ++ ++ uint64_t StoreSize = (DL.getTypeSizeInBits(SrcVal->getType()) + 7) / 8; ++ uint64_t LoadSize = (DL.getTypeSizeInBits(LoadTy) + 7) / 8; ++ ++ IRBuilder<> Builder(InsertPt); ++ ++ // Compute which bits of the stored value are being used by the load. Convert ++ // to an integer type to start with. ++ if (SrcVal->getType()->getScalarType()->isPointerTy()) ++ SrcVal = ++ Builder.CreatePtrToInt(SrcVal, DL.getIntPtrType(SrcVal->getType())); ++ if (!SrcVal->getType()->isIntegerTy()) ++ SrcVal = ++ Builder.CreateBitCast(SrcVal, IntegerType::get(Ctx, StoreSize * 8)); ++ ++ // Shift the bits to the least significant depending on endianness. ++ unsigned ShiftAmt; ++ if (DL.isLittleEndian()) ++ ShiftAmt = Offset * 8; ++ else ++ ShiftAmt = (StoreSize - LoadSize - Offset) * 8; ++ ++ if (ShiftAmt) ++ SrcVal = Builder.CreateLShr(SrcVal, ShiftAmt); ++ ++ if (LoadSize != StoreSize) ++ SrcVal = Builder.CreateTrunc(SrcVal, IntegerType::get(Ctx, LoadSize * 8)); ++ ++ return coerceAvailableValueToLoadType(SrcVal, LoadTy, Builder, DL); ++} ++ ++/// This function is called when we have a ++/// memdep query of a load that ends up being a clobbering load. This means ++/// that the load *may* provide bits used by the load but we can't be sure ++/// because the pointers don't mustalias. Check this case to see if there is ++/// anything more we can do before we give up. ++Value *getLoadValueForLoad(LoadInst *SrcVal, unsigned Offset, Type *LoadTy, ++ Instruction *InsertPt) { ++ ++ const DataLayout &DL = SrcVal->getModule()->getDataLayout(); ++ // If Offset+LoadTy exceeds the size of SrcVal, then we must be wanting to ++ // widen SrcVal out to a larger load. ++ unsigned SrcValStoreSize = DL.getTypeStoreSize(SrcVal->getType()); ++ unsigned LoadSize = DL.getTypeStoreSize(LoadTy); ++ if (Offset + LoadSize > SrcValStoreSize) { ++ assert(SrcVal->isSimple() && "Cannot widen volatile/atomic load!"); ++ assert(SrcVal->getType()->isIntegerTy() && "Can't widen non-integer load"); ++ // If we have a load/load clobber an DepLI can be widened to cover this ++ // load, then we should widen it to the next power of 2 size big enough! ++ unsigned NewLoadSize = Offset + LoadSize; ++ if (!isPowerOf2_32(NewLoadSize)) ++ NewLoadSize = NextPowerOf2(NewLoadSize); ++ ++ Value *PtrVal = SrcVal->getPointerOperand(); ++ ++ // Insert the new load after the old load. This ensures that subsequent ++ // memdep queries will find the new load. We can't easily remove the old ++ // load completely because it is already in the value numbering table. ++ IRBuilder<> Builder(SrcVal->getParent(), ++BasicBlock::iterator(SrcVal)); ++ Type *DestPTy = IntegerType::get(LoadTy->getContext(), NewLoadSize * 8); ++ DestPTy = ++ PointerType::get(DestPTy, PtrVal->getType()->getPointerAddressSpace()); ++ Builder.SetCurrentDebugLocation(SrcVal->getDebugLoc()); ++ PtrVal = Builder.CreateBitCast(PtrVal, DestPTy); ++ LoadInst *NewLoad = Builder.CreateLoad(PtrVal); ++ NewLoad->takeName(SrcVal); ++ NewLoad->setAlignment(SrcVal->getAlignment()); ++ ++ DEBUG(dbgs() << "GVN WIDENED LOAD: " << *SrcVal << "\n"); ++ DEBUG(dbgs() << "TO: " << *NewLoad << "\n"); ++ ++ // Replace uses of the original load with the wider load. On a big endian ++ // system, we need to shift down to get the relevant bits. ++ Value *RV = NewLoad; ++ if (DL.isBigEndian()) ++ RV = Builder.CreateLShr(RV, (NewLoadSize - SrcValStoreSize) * 8); ++ RV = Builder.CreateTrunc(RV, SrcVal->getType()); ++ SrcVal->replaceAllUsesWith(RV); ++ ++ SrcVal = NewLoad; ++ } ++ ++ return getStoreValueForLoad(SrcVal, Offset, LoadTy, InsertPt, DL); ++} ++ ++/// This function is called when we have a ++/// memdep query of a load that ends up being a clobbering mem intrinsic. ++Value *getMemInstValueForLoad(MemIntrinsic *SrcInst, unsigned Offset, ++ Type *LoadTy, Instruction *InsertPt, ++ const DataLayout &DL) { ++ LLVMContext &Ctx = LoadTy->getContext(); ++ uint64_t LoadSize = DL.getTypeSizeInBits(LoadTy) / 8; ++ ++ IRBuilder<> Builder(InsertPt); ++ ++ // We know that this method is only called when the mem transfer fully ++ // provides the bits for the load. ++ if (MemSetInst *MSI = dyn_cast(SrcInst)) { ++ // memset(P, 'x', 1234) -> splat('x'), even if x is a variable, and ++ // independently of what the offset is. ++ Value *Val = MSI->getValue(); ++ if (LoadSize != 1) ++ Val = Builder.CreateZExt(Val, IntegerType::get(Ctx, LoadSize * 8)); ++ ++ Value *OneElt = Val; ++ ++ // Splat the value out to the right number of bits. ++ for (unsigned NumBytesSet = 1; NumBytesSet != LoadSize;) { ++ // If we can double the number of bytes set, do it. ++ if (NumBytesSet * 2 <= LoadSize) { ++ Value *ShVal = Builder.CreateShl(Val, NumBytesSet * 8); ++ Val = Builder.CreateOr(Val, ShVal); ++ NumBytesSet <<= 1; ++ continue; ++ } ++ ++ // Otherwise insert one byte at a time. ++ Value *ShVal = Builder.CreateShl(Val, 1 * 8); ++ Val = Builder.CreateOr(OneElt, ShVal); ++ ++NumBytesSet; ++ } ++ ++ return coerceAvailableValueToLoadType(Val, LoadTy, Builder, DL); ++ } ++ ++ // Otherwise, this is a memcpy/memmove from a constant global. ++ MemTransferInst *MTI = cast(SrcInst); ++ Constant *Src = cast(MTI->getSource()); ++ unsigned AS = Src->getType()->getPointerAddressSpace(); ++ ++ // Otherwise, see if we can constant fold a load from the constant with the ++ // offset applied as appropriate. ++ Src = ++ ConstantExpr::getBitCast(Src, Type::getInt8PtrTy(Src->getContext(), AS)); ++ Constant *OffsetCst = ++ ConstantInt::get(Type::getInt64Ty(Src->getContext()), (unsigned)Offset); ++ Src = ConstantExpr::getGetElementPtr(Type::getInt8Ty(Src->getContext()), Src, ++ OffsetCst); ++ Src = ConstantExpr::getBitCast(Src, PointerType::get(LoadTy, AS)); ++ return ConstantFoldLoadFromConstPtr(Src, LoadTy, DL); ++} ++} // namespace VNCoercion ++} // namespace llvm +-- +2.13.1 + diff --git a/deps/patches/llvm-D31524-sovers_4.0.patch b/deps/patches/llvm-D31524-sovers_4.0.patch new file mode 100644 index 0000000000000..0e8947afc4e62 --- /dev/null +++ b/deps/patches/llvm-D31524-sovers_4.0.patch @@ -0,0 +1,82 @@ +From cd789d8cfe12aa374e66eafc748f4fc06e149ca7 Mon Sep 17 00:00:00 2001 +From: Sylvestre Ledru +Date: Mon, 17 Apr 2017 20:51:50 +0000 +Subject: [PATCH] Add a linker script to version LLVM symbols +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Summary: +This patch adds a very simple linker script to version the lib's symbols +and thus trying to avoid crashes if an application loads two different +LLVM versions (as long as they do not share data between them). + +Note that we deliberately *don't* make LLVM_5.0 depend on LLVM_4.0: +they're incompatible and the whole point of this patch is +to tell the linker that. + + +Avoid unexpected crashes when two LLVM versions are used in the same process. + +Author: Rebecca N. Palmer +Author: Lisandro Damían Nicanor Pérez Meyer +Author: Sylvestre Ledru +Bug-Debian: https://bugs.debian.org/848368 + + +Reviewers: beanz, rnk + +Reviewed By: rnk + +Subscribers: mgorny, llvm-commits + +Differential Revision: https://reviews.llvm.org/D31524 + +git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@300496 91177308-0d34-0410-b5e6-96231b3b80d8 +--- + cmake/modules/AddLLVM.cmake | 3 ++- + tools/llvm-shlib/CMakeLists.txt | 6 +++++- + tools/llvm-shlib/simple_version_script.map.in | 1 + + 3 files changed, 8 insertions(+), 2 deletions(-) + create mode 100644 tools/llvm-shlib/simple_version_script.map.in + +diff --git a/cmake/modules/AddLLVM.cmake b/cmake/modules/AddLLVM.cmake +index 7f7608cff33..e011bb40275 100644 +--- a/cmake/modules/AddLLVM.cmake ++++ b/cmake/modules/AddLLVM.cmake +@@ -81,8 +81,9 @@ function(add_llvm_symbol_exports target_name export_file) + # Gold and BFD ld require a version script rather than a plain list. + set(native_export_file "${target_name}.exports") + # FIXME: Don't write the "local:" line on OpenBSD. ++ # in the export file, also add a linker script to version LLVM symbols (form: LLVM_N.M) + add_custom_command(OUTPUT ${native_export_file} +- COMMAND echo "{" > ${native_export_file} ++ COMMAND echo "LLVM_${LLVM_VERSION_MAJOR}.${LLVM_VERSION_MINOR} {" > ${native_export_file} + COMMAND grep -q "[[:alnum:]]" ${export_file} && echo " global:" >> ${native_export_file} || : + COMMAND sed -e "s/$/;/" -e "s/^/ /" < ${export_file} >> ${native_export_file} + COMMAND echo " local: *;" >> ${native_export_file} +diff --git a/tools/llvm-shlib/CMakeLists.txt b/tools/llvm-shlib/CMakeLists.txt +index c68a2b0e60e..27815868629 100644 +--- a/tools/llvm-shlib/CMakeLists.txt ++++ b/tools/llvm-shlib/CMakeLists.txt +@@ -38,8 +38,12 @@ add_llvm_library(LLVM SHARED DISABLE_LLVM_LINK_LLVM_DYLIB SONAME ${SOURCES}) + + list(REMOVE_DUPLICATES LIB_NAMES) + if(("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux") OR (MINGW) OR ("${CMAKE_SYSTEM_NAME}" STREQUAL "FreeBSD") OR ("${CMAKE_SYSTEM_NAME}" STREQUAL "DragonFly")) # FIXME: It should be "GNU ld for elf" ++ configure_file( ++ ${CMAKE_CURRENT_SOURCE_DIR}/simple_version_script.map.in ++ ${LLVM_LIBRARY_DIR}/tools/llvm-shlib/simple_version_script.map) ++ + # GNU ld doesn't resolve symbols in the version script. +- set(LIB_NAMES -Wl,--whole-archive ${LIB_NAMES} -Wl,--no-whole-archive) ++ set(LIB_NAMES -Wl,--version-script,${LLVM_LIBRARY_DIR}/tools/llvm-shlib/simple_version_script.map -Wl,--whole-archive ${LIB_NAMES} -Wl,--no-whole-archive) + elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "Darwin") + set(LIB_NAMES -Wl,-all_load ${LIB_NAMES}) + endif() +diff --git a/tools/llvm-shlib/simple_version_script.map.in b/tools/llvm-shlib/simple_version_script.map.in +new file mode 100644 +index 00000000000..e9515fe7862 +--- /dev/null ++++ b/tools/llvm-shlib/simple_version_script.map.in +@@ -0,0 +1 @@ ++LLVM_@LLVM_VERSION_MAJOR@.@LLVM_VERSION_MINOR@ { global: *; }; diff --git a/deps/patches/llvm-D32196-LIR-non-integral.patch b/deps/patches/llvm-D32196-LIR-non-integral.patch new file mode 100644 index 0000000000000..28b4abdafa225 --- /dev/null +++ b/deps/patches/llvm-D32196-LIR-non-integral.patch @@ -0,0 +1,95 @@ +From aebd138996c29589d44d6eccea659757c6184b44 Mon Sep 17 00:00:00 2001 +From: Sanjoy Das +Date: Mon, 24 Apr 2017 20:12:10 +0000 +Subject: [PATCH 3/5] [LIR] Obey non-integral pointer semantics + +Summary: See http://llvm.org/docs/LangRef.html#non-integral-pointer-type + +Reviewers: haicheng + +Reviewed By: haicheng + +Subscribers: mcrosier, mzolotukhin, llvm-commits + +Differential Revision: https://reviews.llvm.org/D32196 + +git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@301238 91177308-0d34-0410-b5e6-96231b3b80d8 +--- + lib/Transforms/Scalar/LoopIdiomRecognize.cpp | 5 +++ + test/Transforms/LoopIdiom/non-integral-pointers.ll | 48 ++++++++++++++++++++++ + 2 files changed, 53 insertions(+) + create mode 100644 test/Transforms/LoopIdiom/non-integral-pointers.ll + +diff --git a/lib/Transforms/Scalar/LoopIdiomRecognize.cpp b/lib/Transforms/Scalar/LoopIdiomRecognize.cpp +index 5fec51c095d..570c55a3e76 100644 +--- a/lib/Transforms/Scalar/LoopIdiomRecognize.cpp ++++ b/lib/Transforms/Scalar/LoopIdiomRecognize.cpp +@@ -345,6 +345,11 @@ bool LoopIdiomRecognize::isLegalStore(StoreInst *SI, bool &ForMemset, + if (!SI->isSimple()) + return false; + ++ // Don't convert stores of non-integral pointer types to memsets (which stores ++ // integers). ++ if (DL->isNonIntegralPointerType(SI->getValueOperand()->getType())) ++ return false; ++ + // Avoid merging nontemporal stores. + if (SI->getMetadata(LLVMContext::MD_nontemporal)) + return false; +diff --git a/test/Transforms/LoopIdiom/non-integral-pointers.ll b/test/Transforms/LoopIdiom/non-integral-pointers.ll +new file mode 100644 +index 00000000000..7646d5ac72d +--- /dev/null ++++ b/test/Transforms/LoopIdiom/non-integral-pointers.ll +@@ -0,0 +1,48 @@ ++; RUN: opt -S -basicaa -loop-idiom < %s | FileCheck %s ++ ++target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128-ni:4" ++target triple = "x86_64-unknown-linux-gnu" ++ ++define void @f_0(i8 addrspace(3)** %ptr) { ++; CHECK-LABEL: @f_0( ++; CHECK: call{{.*}}memset ++ ++; LIR'ing stores of pointers with address space 3 is fine, since ++; they're integral pointers. ++ ++entry: ++ br label %for.body ++ ++for.body: ++ %indvar = phi i64 [ 0, %entry ], [ %indvar.next, %for.body ] ++ %arrayidx = getelementptr i8 addrspace(3)*, i8 addrspace(3)** %ptr, i64 %indvar ++ store i8 addrspace(3)* null, i8 addrspace(3)** %arrayidx, align 4 ++ %indvar.next = add i64 %indvar, 1 ++ %exitcond = icmp eq i64 %indvar.next, 10000 ++ br i1 %exitcond, label %for.end, label %for.body ++ ++for.end: ++ ret void ++} ++ ++define void @f_1(i8 addrspace(4)** %ptr) { ++; CHECK-LABEL: @f_1( ++; CHECK-NOT: call{{.*}}memset ++ ++; LIR'ing stores of pointers with address space 4 is not ok, since ++; they're non-integral pointers. ++ ++entry: ++ br label %for.body ++ ++for.body: ++ %indvar = phi i64 [ 0, %entry ], [ %indvar.next, %for.body ] ++ %arrayidx = getelementptr i8 addrspace(4)*, i8 addrspace(4)** %ptr, i64 %indvar ++ store i8 addrspace(4)* null, i8 addrspace(4)** %arrayidx, align 4 ++ %indvar.next = add i64 %indvar, 1 ++ %exitcond = icmp eq i64 %indvar.next, 10000 ++ br i1 %exitcond, label %for.end, label %for.body ++ ++for.end: ++ ret void ++} +-- +2.13.1 + diff --git a/deps/patches/llvm-D32203-SORA-non-integral.patch b/deps/patches/llvm-D32203-SORA-non-integral.patch new file mode 100644 index 0000000000000..6c9b75b1ca0da --- /dev/null +++ b/deps/patches/llvm-D32203-SORA-non-integral.patch @@ -0,0 +1,99 @@ +From 2fe2c1173e286203309e5bb9b034fd55dc9fc8fc Mon Sep 17 00:00:00 2001 +From: Sanjoy Das +Date: Sat, 17 Jun 2017 11:06:25 -0400 +Subject: [PATCH 1/2] [SROA] Add support for non-integral pointers + +Summary: C.f. http://llvm.org/docs/LangRef.html#non-integral-pointer-type + +Reviewers: chandlerc, loladiro + +Reviewed By: loladiro + +Subscribers: reames, loladiro, mcrosier, llvm-commits + +Differential Revision: https://reviews.llvm.org/D32203 +--- + lib/Transforms/Scalar/SROA.cpp | 13 ++++++-- + test/Transforms/SROA/non-integral-pointers.ll | 46 +++++++++++++++++++++++++++ + 2 files changed, 57 insertions(+), 2 deletions(-) + create mode 100644 test/Transforms/SROA/non-integral-pointers.ll + +diff --git a/lib/Transforms/Scalar/SROA.cpp b/lib/Transforms/Scalar/SROA.cpp +index d28490f3a50..ec8636fe25a 100644 +--- a/lib/Transforms/Scalar/SROA.cpp ++++ b/lib/Transforms/Scalar/SROA.cpp +@@ -1636,8 +1636,17 @@ static bool canConvertValue(const DataLayout &DL, Type *OldTy, Type *NewTy) { + return cast(NewTy)->getPointerAddressSpace() == + cast(OldTy)->getPointerAddressSpace(); + } +- if (NewTy->isIntegerTy() || OldTy->isIntegerTy()) +- return true; ++ ++ // We can convert integers to integral pointers, but not to non-integral ++ // pointers. ++ if (OldTy->isIntegerTy()) ++ return !DL.isNonIntegralPointerType(NewTy); ++ ++ // We can convert integral pointers to integers, but non-integral pointers ++ // need to remain pointers. ++ if (!DL.isNonIntegralPointerType(OldTy)) ++ return NewTy->isIntegerTy(); ++ + return false; + } + +diff --git a/test/Transforms/SROA/non-integral-pointers.ll b/test/Transforms/SROA/non-integral-pointers.ll +new file mode 100644 +index 00000000000..63286309f6f +--- /dev/null ++++ b/test/Transforms/SROA/non-integral-pointers.ll +@@ -0,0 +1,46 @@ ++; RUN: opt -sroa -S < %s | FileCheck %s ++ ++; This test checks that SROA does not introduce ptrtoint and inttoptr ++; casts from and to non-integral pointers. The "ni:4" bit in the ++; datalayout states that pointers of address space 4 are to be ++; considered "non-integral". ++ ++target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128-ni:4" ++target triple = "x86_64-unknown-linux-gnu" ++ ++define void @f0(i1 %alwaysFalse, i64 %val) { ++; CHECK-LABEL: @f0( ++; CHECK-NOT: inttoptr ++; CHECK-NOT: ptrtoint ++entry: ++ %loc = alloca i64 ++ store i64 %val, i64* %loc ++ br i1 %alwaysFalse, label %neverTaken, label %alwaysTaken ++ ++neverTaken: ++ %loc.bc = bitcast i64* %loc to i8 addrspace(4)** ++ %ptr = load i8 addrspace(4)*, i8 addrspace(4)** %loc.bc ++ store i8 5, i8 addrspace(4)* %ptr ++ ret void ++ ++alwaysTaken: ++ ret void ++} ++ ++define i64 @f1(i1 %alwaysFalse, i8 addrspace(4)* %val) { ++; CHECK-LABEL: @f1( ++; CHECK-NOT: inttoptr ++; CHECK-NOT: ptrtoint ++entry: ++ %loc = alloca i8 addrspace(4)* ++ store i8 addrspace(4)* %val, i8 addrspace(4)** %loc ++ br i1 %alwaysFalse, label %neverTaken, label %alwaysTaken ++ ++neverTaken: ++ %loc.bc = bitcast i8 addrspace(4)** %loc to i64* ++ %int = load i64, i64* %loc.bc ++ ret i64 %int ++ ++alwaysTaken: ++ ret i64 42 ++} +-- +2.13.1 + diff --git a/deps/patches/llvm-D32208-coerce-non-integral.patch b/deps/patches/llvm-D32208-coerce-non-integral.patch new file mode 100644 index 0000000000000..bc0ec8a594e72 --- /dev/null +++ b/deps/patches/llvm-D32208-coerce-non-integral.patch @@ -0,0 +1,137 @@ +From 2a7ef55ed78bb5f147900af862fed32103257839 Mon Sep 17 00:00:00 2001 +From: Sanjoy Das +Date: Wed, 19 Apr 2017 18:21:09 +0000 +Subject: [PATCH 2/5] [GVN] Don't coerce non-integral pointers to integers or + vice versa + +Summary: +See http://llvm.org/docs/LangRef.html#non-integral-pointer-type + +The NewGVN test does not fail without these changes (perhaps it does +try to coerce pointers <-> integers to begin with?), but I added the +test case anyway. + +Reviewers: dberlin + +Subscribers: mcrosier, llvm-commits, Prazek + +Differential Revision: https://reviews.llvm.org/D32208 + +git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@300730 91177308-0d34-0410-b5e6-96231b3b80d8 +--- + lib/Transforms/Utils/VNCoercion.cpp | 5 ++++ + test/Transforms/GVN/non-integral-pointers.ll | 39 +++++++++++++++++++++++++ + test/Transforms/NewGVN/non-integral-pointers.ll | 39 +++++++++++++++++++++++++ + 3 files changed, 83 insertions(+) + create mode 100644 test/Transforms/GVN/non-integral-pointers.ll + create mode 100644 test/Transforms/NewGVN/non-integral-pointers.ll + +diff --git a/lib/Transforms/Utils/VNCoercion.cpp b/lib/Transforms/Utils/VNCoercion.cpp +index 38d26e922c3..80762ccc0d4 100644 +--- a/lib/Transforms/Utils/VNCoercion.cpp ++++ b/lib/Transforms/Utils/VNCoercion.cpp +@@ -24,6 +24,11 @@ bool canCoerceMustAliasedValueToLoad(Value *StoredVal, Type *LoadTy, + if (DL.getTypeSizeInBits(StoredVal->getType()) < DL.getTypeSizeInBits(LoadTy)) + return false; + ++ // Don't coerce non-integral pointers to integers or vice versa. ++ if (DL.isNonIntegralPointerType(StoredVal->getType()) != ++ DL.isNonIntegralPointerType(LoadTy)) ++ return false; ++ + return true; + } + +diff --git a/test/Transforms/GVN/non-integral-pointers.ll b/test/Transforms/GVN/non-integral-pointers.ll +new file mode 100644 +index 00000000000..9ae4132231d +--- /dev/null ++++ b/test/Transforms/GVN/non-integral-pointers.ll +@@ -0,0 +1,39 @@ ++; RUN: opt -gvn -S < %s | FileCheck %s ++ ++target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128-ni:4" ++target triple = "x86_64-unknown-linux-gnu" ++ ++define void @f0(i1 %alwaysFalse, i64 %val, i64* %loc) { ++; CHECK-LABEL: @f0( ++; CHECK-NOT: inttoptr ++; CHECK-NOT: ptrtoint ++ entry: ++ store i64 %val, i64* %loc ++ br i1 %alwaysFalse, label %neverTaken, label %alwaysTaken ++ ++ neverTaken: ++ %loc.bc = bitcast i64* %loc to i8 addrspace(4)** ++ %ptr = load i8 addrspace(4)*, i8 addrspace(4)** %loc.bc ++ store i8 5, i8 addrspace(4)* %ptr ++ ret void ++ ++ alwaysTaken: ++ ret void ++} ++ ++define i64 @f1(i1 %alwaysFalse, i8 addrspace(4)* %val, i8 addrspace(4)** %loc) { ++; CHECK-LABEL: @f1( ++; CHECK-NOT: inttoptr ++; CHECK-NOT: ptrtoint ++ entry: ++ store i8 addrspace(4)* %val, i8 addrspace(4)** %loc ++ br i1 %alwaysFalse, label %neverTaken, label %alwaysTaken ++ ++ neverTaken: ++ %loc.bc = bitcast i8 addrspace(4)** %loc to i64* ++ %int = load i64, i64* %loc.bc ++ ret i64 %int ++ ++ alwaysTaken: ++ ret i64 42 ++} +diff --git a/test/Transforms/NewGVN/non-integral-pointers.ll b/test/Transforms/NewGVN/non-integral-pointers.ll +new file mode 100644 +index 00000000000..75b8285d51f +--- /dev/null ++++ b/test/Transforms/NewGVN/non-integral-pointers.ll +@@ -0,0 +1,39 @@ ++; RUN: opt -newgvn -S < %s | FileCheck %s ++ ++target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128-ni:4" ++target triple = "x86_64-unknown-linux-gnu" ++ ++define void @f0(i1 %alwaysFalse, i64 %val, i64* %loc) { ++; CHECK-LABEL: @f0( ++; CHECK-NOT: inttoptr ++; CHECK-NOT: ptrtoint ++ entry: ++ store i64 %val, i64* %loc ++ br i1 %alwaysFalse, label %neverTaken, label %alwaysTaken ++ ++ neverTaken: ++ %loc.bc = bitcast i64* %loc to i8 addrspace(4)** ++ %ptr = load i8 addrspace(4)*, i8 addrspace(4)** %loc.bc ++ store i8 5, i8 addrspace(4)* %ptr ++ ret void ++ ++ alwaysTaken: ++ ret void ++} ++ ++define i64 @f1(i1 %alwaysFalse, i8 addrspace(4)* %val, i8 addrspace(4)** %loc) { ++; CHECK-LABEL: @f1( ++; CHECK-NOT: inttoptr ++; CHECK-NOT: ptrtoint ++ entry: ++ store i8 addrspace(4)* %val, i8 addrspace(4)** %loc ++ br i1 %alwaysFalse, label %neverTaken, label %alwaysTaken ++ ++ neverTaken: ++ %loc.bc = bitcast i8 addrspace(4)** %loc to i64* ++ %int = load i64, i64* %loc.bc ++ ret i64 %int ++ ++ alwaysTaken: ++ ret i64 42 ++} +-- +2.13.1 + diff --git a/deps/patches/llvm-D32593.patch b/deps/patches/llvm-D32593.patch new file mode 100644 index 0000000000000..19c4acb960f97 --- /dev/null +++ b/deps/patches/llvm-D32593.patch @@ -0,0 +1,83 @@ +From 5eeab81d22e07b6e12821067fced590f534c251a Mon Sep 17 00:00:00 2001 +From: Keno Fischer +Date: Thu, 27 Apr 2017 14:33:33 -0400 +Subject: [PATCH] [SROA] Fix crash due to bad bitcast + +Summary: +As shown in the test case, SROA was crashing when trying to split +stores (to the alloca) of loads (from anywhere), because it assumed +the pointer operand to the loads and stores had to have the same +address space. This isn't the case. Make sure to use the correct +pointer type for both the load and the store. + +Reviewers: chandlerc, majnemer, sanjoy + +Subscribers: arsenm, llvm-commits + +Differential Revision: https://reviews.llvm.org/D32593 +--- + lib/Transforms/Scalar/SROA.cpp | 7 ++++--- + test/Transforms/SROA/address-spaces.ll | 18 ++++++++++++++++++ + 2 files changed, 22 insertions(+), 3 deletions(-) + +diff --git a/lib/Transforms/Scalar/SROA.cpp b/lib/Transforms/Scalar/SROA.cpp +index d01e91a..610d5a8 100644 +--- a/lib/Transforms/Scalar/SROA.cpp ++++ b/lib/Transforms/Scalar/SROA.cpp +@@ -3697,7 +3697,8 @@ bool SROA::presplitLoadsAndStores(AllocaInst &AI, AllocaSlices &AS) { + int Idx = 0, Size = Offsets.Splits.size(); + for (;;) { + auto *PartTy = Type::getIntNTy(Ty->getContext(), PartSize * 8); +- auto *PartPtrTy = PartTy->getPointerTo(SI->getPointerAddressSpace()); ++ auto *LoadPartPtrTy = PartTy->getPointerTo(LI->getPointerAddressSpace()); ++ auto *StorePartPtrTy = PartTy->getPointerTo(SI->getPointerAddressSpace()); + + // Either lookup a split load or create one. + LoadInst *PLoad; +@@ -3708,7 +3709,7 @@ bool SROA::presplitLoadsAndStores(AllocaInst &AI, AllocaSlices &AS) { + PLoad = IRB.CreateAlignedLoad( + getAdjustedPtr(IRB, DL, LoadBasePtr, + APInt(DL.getPointerSizeInBits(), PartOffset), +- PartPtrTy, LoadBasePtr->getName() + "."), ++ LoadPartPtrTy, LoadBasePtr->getName() + "."), + getAdjustedAlignment(LI, PartOffset, DL), /*IsVolatile*/ false, + LI->getName()); + } +@@ -3718,7 +3719,7 @@ bool SROA::presplitLoadsAndStores(AllocaInst &AI, AllocaSlices &AS) { + StoreInst *PStore = IRB.CreateAlignedStore( + PLoad, getAdjustedPtr(IRB, DL, StoreBasePtr, + APInt(DL.getPointerSizeInBits(), PartOffset), +- PartPtrTy, StoreBasePtr->getName() + "."), ++ StorePartPtrTy, StoreBasePtr->getName() + "."), + getAdjustedAlignment(SI, PartOffset, DL), /*IsVolatile*/ false); + + // Now build a new slice for the alloca. +diff --git a/test/Transforms/SROA/address-spaces.ll b/test/Transforms/SROA/address-spaces.ll +index 119f225..8fba30c 100644 +--- a/test/Transforms/SROA/address-spaces.ll ++++ b/test/Transforms/SROA/address-spaces.ll +@@ -83,3 +83,21 @@ define void @pr27557() { + store i32 addrspace(3)* @l, i32 addrspace(3)** %3, align 8 + ret void + } ++ ++; Make sure pre-splitting doesn't try to introduce an illegal bitcast ++define float @presplit(i64 addrspace(1)* %p) { ++entry: ++; CHECK-LABEL: @presplit( ++; CHECK: %[[CAST:.*]] = bitcast i64 addrspace(1)* {{.*}} to i32 addrspace(1)* ++; CHECK: load i32, i32 addrspace(1)* %[[CAST]] ++ %b = alloca i64 ++ %b.cast = bitcast i64* %b to [2 x float]* ++ %b.gep1 = getelementptr [2 x float], [2 x float]* %b.cast, i32 0, i32 0 ++ %b.gep2 = getelementptr [2 x float], [2 x float]* %b.cast, i32 0, i32 1 ++ %l = load i64, i64 addrspace(1)* %p ++ store i64 %l, i64* %b ++ %f1 = load float, float* %b.gep1 ++ %f2 = load float, float* %b.gep2 ++ %ret = fadd float %f1, %f2 ++ ret float %ret ++} +-- +2.9.3 + diff --git a/deps/patches/llvm-D32623-GVN-non-integral.patch b/deps/patches/llvm-D32623-GVN-non-integral.patch new file mode 100644 index 0000000000000..5ddc76bc046d5 --- /dev/null +++ b/deps/patches/llvm-D32623-GVN-non-integral.patch @@ -0,0 +1,94 @@ +From ad3b6cad4fcd66aab2ef2e93566d5868505c03bb Mon Sep 17 00:00:00 2001 +From: Keno Fischer +Date: Tue, 9 May 2017 21:07:20 +0000 +Subject: [PATCH 4/5] [GVN] Fix a crash on encountering non-integral pointers + +Summary: +This fixes the immediate crash caused by introducing an incorrect inttoptr +before attempting the conversion. There may still be a legality +check missing somewhere earlier for non-integral pointers, but this change +seems necessary in any case. + +Reviewers: sanjoy, dberlin + +Reviewed By: dberlin + +Subscribers: llvm-commits + +Differential Revision: https://reviews.llvm.org/D32623 + +git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@302587 91177308-0d34-0410-b5e6-96231b3b80d8 +--- + lib/Transforms/Utils/VNCoercion.cpp | 9 ++++++++ + test/Transforms/GVN/PRE/nonintegral.ll | 39 ++++++++++++++++++++++++++++++++++ + 2 files changed, 48 insertions(+) + create mode 100644 test/Transforms/GVN/PRE/nonintegral.ll + +diff --git a/lib/Transforms/Utils/VNCoercion.cpp b/lib/Transforms/Utils/VNCoercion.cpp +index 80762ccc0d4..9d2eab19ded 100644 +--- a/lib/Transforms/Utils/VNCoercion.cpp ++++ b/lib/Transforms/Utils/VNCoercion.cpp +@@ -301,6 +301,15 @@ Value *getStoreValueForLoad(Value *SrcVal, unsigned Offset, Type *LoadTy, + Instruction *InsertPt, const DataLayout &DL) { + LLVMContext &Ctx = SrcVal->getType()->getContext(); + ++ // If two pointers are in the same address space, they have the same size, ++ // so we don't need to do any truncation, etc. This avoids introducing ++ // ptrtoint instructions for pointers that may be non-integral. ++ if (SrcVal->getType()->isPointerTy() && LoadTy->isPointerTy() && ++ cast(SrcVal->getType())->getAddressSpace() == ++ cast(LoadTy)->getAddressSpace()) { ++ return SrcVal; ++ } ++ + uint64_t StoreSize = (DL.getTypeSizeInBits(SrcVal->getType()) + 7) / 8; + uint64_t LoadSize = (DL.getTypeSizeInBits(LoadTy) + 7) / 8; + +diff --git a/test/Transforms/GVN/PRE/nonintegral.ll b/test/Transforms/GVN/PRE/nonintegral.ll +new file mode 100644 +index 00000000000..75a756e8af8 +--- /dev/null ++++ b/test/Transforms/GVN/PRE/nonintegral.ll +@@ -0,0 +1,39 @@ ++; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ++; RUN: opt -gvn -S < %s | FileCheck %s ++ ++target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128-ni:4" ++target triple = "x86_64-unknown-linux-gnu" ++ ++define void @nipre(double addrspace(4)** noalias %p, i64 addrspace(4)** noalias %p2, i8 %jmp) { ++ ++; CHECK-LABEL: @nipre( ++; CHECK: [[PCAST:%.*]] = bitcast double addrspace(4)** [[P:%.*]] to i64 addrspace(4)** ++; CHECK: a: ++; CHECK: [[L1:%.*]] = load i64 addrspace(4)*, i64 addrspace(4)** [[PCAST]] ++; CHECK: [[TMP0:%.*]] = bitcast i64 addrspace(4)* [[L1]] to double addrspace(4)* ++; CHECK: b: ++; CHECK: [[L2:%.*]] = load i64 addrspace(4)*, i64 addrspace(4)** [[PCAST]] ++; CHECK: [[TMP1:%.*]] = bitcast i64 addrspace(4)* [[L2]] to double addrspace(4)* ++; CHECK: c: ++; CHECK-NEXT: [[L3_PRE:%.*]] = load double addrspace(4)*, double addrspace(4)** %p ++ ++entry: ++ %pcast = bitcast double addrspace(4)** %p to i64 addrspace(4)** ++ switch i8 %jmp, label %c [ i8 0, label %a ++ i8 1, label %b] ++a: ++ %l1 = load i64 addrspace(4)*, i64 addrspace(4)** %pcast ++ store i64 addrspace(4)* %l1, i64 addrspace(4)** %p2 ++ br label %tail ++b: ++ %l2 = load i64 addrspace(4)*, i64 addrspace(4)** %pcast ++ store i64 addrspace(4)* %l2, i64 addrspace(4)** %p2 ++ br label %tail ++c: ++ br label %tail ++tail: ++ %l3 = load double addrspace(4)*, double addrspace(4)** %p ++ %l3cast = bitcast double addrspace(4)* %l3 to i64 addrspace(4)* ++ store i64 addrspace(4)* %l3cast, i64 addrspace(4)** %p2 ++ ret void ++} +-- +2.13.1 + diff --git a/deps/patches/llvm-D33110-codegen-prepare-inttoptr.patch b/deps/patches/llvm-D33110-codegen-prepare-inttoptr.patch new file mode 100644 index 0000000000000..5f1f874c3db83 --- /dev/null +++ b/deps/patches/llvm-D33110-codegen-prepare-inttoptr.patch @@ -0,0 +1,119 @@ +From 8a2f775df3c8548bedd8437c0b96b54e9e71549d Mon Sep 17 00:00:00 2001 +From: Keno Fischer +Date: Sat, 17 Jun 2017 11:07:26 -0400 +Subject: [PATCH 2/2] [CodeGenPrepare] Don't create inttoptr for ni ptrs + +Summary: +Arguably non-integral pointers probably shouldn't show up here at all, +but since the backend doesn't complain and this takes valid (according +to the Verifier) IR and makes it invalid, make sure not to introduce +any inttoptr instructions if we're dealing with non-integral pointers. + +Reviewers: sanjoy + +Subscribers: llvm-commits + +Differential Revision: https://reviews.llvm.org/D33110 +--- + lib/CodeGen/CodeGenPrepare.cpp | 23 ++++++++----- + test/Transforms/CodeGenPrepare/nonintegral.ll | 47 +++++++++++++++++++++++++++ + 2 files changed, 62 insertions(+), 8 deletions(-) + create mode 100644 test/Transforms/CodeGenPrepare/nonintegral.ll + +diff --git a/lib/CodeGen/CodeGenPrepare.cpp b/lib/CodeGen/CodeGenPrepare.cpp +index 934b470f13b..44d6b3e264c 100644 +--- a/lib/CodeGen/CodeGenPrepare.cpp ++++ b/lib/CodeGen/CodeGenPrepare.cpp +@@ -3973,14 +3973,16 @@ bool CodeGenPrepare::optimizeMemoryInst(Instruction *MemoryInst, Value *Addr, + // If the real base value actually came from an inttoptr, then the matcher + // will look through it and provide only the integer value. In that case, + // use it here. +- if (!ResultPtr && AddrMode.BaseReg) { +- ResultPtr = +- Builder.CreateIntToPtr(AddrMode.BaseReg, Addr->getType(), "sunkaddr"); +- AddrMode.BaseReg = nullptr; +- } else if (!ResultPtr && AddrMode.Scale == 1) { +- ResultPtr = +- Builder.CreateIntToPtr(AddrMode.ScaledReg, Addr->getType(), "sunkaddr"); +- AddrMode.Scale = 0; ++ if (!DL->isNonIntegralPointerType(Addr->getType())) { ++ if (!ResultPtr && AddrMode.BaseReg) { ++ ResultPtr = Builder.CreateIntToPtr(AddrMode.BaseReg, Addr->getType(), ++ "sunkaddr"); ++ AddrMode.BaseReg = nullptr; ++ } else if (!ResultPtr && AddrMode.Scale == 1) { ++ ResultPtr = Builder.CreateIntToPtr(AddrMode.ScaledReg, Addr->getType(), ++ "sunkaddr"); ++ AddrMode.Scale = 0; ++ } + } + + if (!ResultPtr && +@@ -4061,6 +4063,11 @@ bool CodeGenPrepare::optimizeMemoryInst(Instruction *MemoryInst, Value *Addr, + SunkAddr = Builder.CreateBitCast(SunkAddr, Addr->getType()); + } + } else { ++ // We'd require an inttoptr down the line, which we can't do for ++ // non-integral pointers, so in that case bail out now. ++ if (DL->isNonIntegralPointerType(Addr->getType())) ++ return false; ++ + DEBUG(dbgs() << "CGP: SINKING nonlocal addrmode: " << AddrMode << " for " + << *MemoryInst << "\n"); + Type *IntPtrTy = DL->getIntPtrType(Addr->getType()); +diff --git a/test/Transforms/CodeGenPrepare/nonintegral.ll b/test/Transforms/CodeGenPrepare/nonintegral.ll +new file mode 100644 +index 00000000000..e49977bc940 +--- /dev/null ++++ b/test/Transforms/CodeGenPrepare/nonintegral.ll +@@ -0,0 +1,47 @@ ++; RUN: opt -S -codegenprepare < %s | FileCheck %s ++; RUN: opt -S -codegenprepare -addr-sink-using-gep=false < %s | FileCheck %s ++ ++; This target data layout is modified to have a non-integral addrspace(1), ++; in order to verify that codegenprepare does not try to introduce illegal ++; inttoptrs. ++target datalayout = ++"e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-ni:1" ++target triple = "x86_64-unknown-linux-gnu" ++ ++define void @test_simple(i1 %cond, i64 addrspace(1)* %base) { ++; CHECK-LABEL: @test_simple ++; CHECK-NOT: inttoptr {{.*}} to i64 addrspace(1)* ++entry: ++ %addr = getelementptr inbounds i64, i64 addrspace(1)* %base, i64 5 ++ %casted = bitcast i64 addrspace(1)* %addr to i32 addrspace(1)* ++ br i1 %cond, label %if.then, label %fallthrough ++ ++if.then: ++ %v = load i32, i32 addrspace(1)* %casted, align 4 ++ br label %fallthrough ++ ++fallthrough: ++ ret void ++} ++ ++ ++define void @test_inttoptr_base(i1 %cond, i64 %base) { ++; CHECK-LABEL: @test_inttoptr_base ++; CHECK-NOT: inttoptr {{.*}} to i64 addrspace(1)* ++entry: ++; Doing the inttoptr in the integral addrspace(0) followed by an explicit ++; (frontend-introduced) addrspacecast is fine. We cannot however introduce ++; a direct inttoptr to addrspace(1) ++ %baseptr = inttoptr i64 %base to i64* ++ %baseptrni = addrspacecast i64 *%baseptr to i64 addrspace(1)* ++ %addr = getelementptr inbounds i64, i64 addrspace(1)* %baseptrni, i64 5 ++ %casted = bitcast i64 addrspace(1)* %addr to i32 addrspace(1)* ++ br i1 %cond, label %if.then, label %fallthrough ++ ++if.then: ++ %v = load i32, i32 addrspace(1)* %casted, align 4 ++ br label %fallthrough ++ ++fallthrough: ++ ret void ++} +-- +2.13.1 + diff --git a/deps/patches/llvm-D33129-scevexpander-non-integral.patch b/deps/patches/llvm-D33129-scevexpander-non-integral.patch new file mode 100644 index 0000000000000..1dab29f94c041 --- /dev/null +++ b/deps/patches/llvm-D33129-scevexpander-non-integral.patch @@ -0,0 +1,153 @@ +From d551af32da5fd6654e7804848a7a409e9444aeea Mon Sep 17 00:00:00 2001 +From: Keno Fischer +Date: Sat, 27 May 2017 03:22:55 +0000 +Subject: [PATCH 5/5] [SCEVExpander] Try harder to avoid introducing inttoptr + +Summary: +This fixes introduction of an incorrect inttoptr/ptrtoint pair in +the included test case which makes use of non-integral pointers. I +suspect there are more cases like this left, but this takes care of +the one I was seeing at the moment. + +Reviewers: sanjoy + +Subscribers: mzolotukhin, llvm-commits + +Differential Revision: https://reviews.llvm.org/D33129 + +git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@304058 91177308-0d34-0410-b5e6-96231b3b80d8 +--- + lib/Analysis/ScalarEvolutionExpander.cpp | 20 ++++++++-- + test/Transforms/LoopStrengthReduce/nonintegral.ll | 45 +++++++++++++++++++++++ + unittests/Analysis/ScalarEvolutionTest.cpp | 11 +++--- + 3 files changed, 67 insertions(+), 9 deletions(-) + create mode 100644 test/Transforms/LoopStrengthReduce/nonintegral.ll + +diff --git a/lib/Analysis/ScalarEvolutionExpander.cpp b/lib/Analysis/ScalarEvolutionExpander.cpp +index d15a7dbd20e..e7d9e9a633e 100644 +--- a/lib/Analysis/ScalarEvolutionExpander.cpp ++++ b/lib/Analysis/ScalarEvolutionExpander.cpp +@@ -1306,12 +1306,17 @@ Value *SCEVExpander::expandAddRecExprLiterally(const SCEVAddRecExpr *S) { + // Expand the core addrec. If we need post-loop scaling, force it to + // expand to an integer type to avoid the need for additional casting. + Type *ExpandTy = PostLoopScale ? IntTy : STy; ++ // We can't use a pointer type for the addrec if the pointer type is ++ // non-integral. ++ Type *AddRecPHIExpandTy = ++ DL.isNonIntegralPointerType(STy) ? Normalized->getType() : ExpandTy; ++ + // In some cases, we decide to reuse an existing phi node but need to truncate + // it and/or invert the step. + Type *TruncTy = nullptr; + bool InvertStep = false; +- PHINode *PN = getAddRecExprPHILiterally(Normalized, L, ExpandTy, IntTy, +- TruncTy, InvertStep); ++ PHINode *PN = getAddRecExprPHILiterally(Normalized, L, AddRecPHIExpandTy, ++ IntTy, TruncTy, InvertStep); + + // Accommodate post-inc mode, if necessary. + Value *Result; +@@ -1384,8 +1389,15 @@ Value *SCEVExpander::expandAddRecExprLiterally(const SCEVAddRecExpr *S) { + // Re-apply any non-loop-dominating offset. + if (PostLoopOffset) { + if (PointerType *PTy = dyn_cast(ExpandTy)) { +- const SCEV *const OffsetArray[1] = { PostLoopOffset }; +- Result = expandAddToGEP(OffsetArray, OffsetArray+1, PTy, IntTy, Result); ++ if (Result->getType()->isIntegerTy()) { ++ Value *Base = expandCodeFor(PostLoopOffset, ExpandTy); ++ const SCEV *const OffsetArray[1] = {SE.getUnknown(Result)}; ++ Result = expandAddToGEP(OffsetArray, OffsetArray + 1, PTy, IntTy, Base); ++ } else { ++ const SCEV *const OffsetArray[1] = {PostLoopOffset}; ++ Result = ++ expandAddToGEP(OffsetArray, OffsetArray + 1, PTy, IntTy, Result); ++ } + } else { + Result = InsertNoopCastOfTo(Result, IntTy); + Result = Builder.CreateAdd(Result, +diff --git a/test/Transforms/LoopStrengthReduce/nonintegral.ll b/test/Transforms/LoopStrengthReduce/nonintegral.ll +new file mode 100644 +index 00000000000..5648e3aa74a +--- /dev/null ++++ b/test/Transforms/LoopStrengthReduce/nonintegral.ll +@@ -0,0 +1,45 @@ ++; RUN: opt -S -loop-reduce < %s | FileCheck %s ++ ++; Address Space 10 is non-integral. The optimizer is not allowed to use ++; ptrtoint/inttoptr instructions. Make sure that this doesn't happen ++target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128-ni:10:11:12" ++target triple = "x86_64-unknown-linux-gnu" ++ ++define void @japi1__unsafe_getindex_65028(i64 addrspace(10)* %arg) { ++; CHECK-NOT: inttoptr ++; CHECK-NOT: ptrtoint ++; How exactly SCEV chooses to materialize isn't all that important, as ++; long as it doesn't try to round-trip through integers. As of this writing, ++; it emits a byte-wise gep, which is fine. ++; CHECK: getelementptr i64, i64 addrspace(10)* {{.*}}, i64 {{.*}} ++top: ++ br label %L86 ++ ++L86: ; preds = %L86, %top ++ %i.0 = phi i64 [ 0, %top ], [ %tmp, %L86 ] ++ %tmp = add i64 %i.0, 1 ++ br i1 undef, label %L86, label %if29 ++ ++if29: ; preds = %L86 ++ %tmp1 = shl i64 %tmp, 1 ++ %tmp2 = add i64 %tmp1, -2 ++ br label %if31 ++ ++if31: ; preds = %if38, %if29 ++ %"#temp#1.sroa.0.022" = phi i64 [ 0, %if29 ], [ %tmp3, %if38 ] ++ br label %L119 ++ ++L119: ; preds = %L119, %if31 ++ %i5.0 = phi i64 [ %"#temp#1.sroa.0.022", %if31 ], [ %tmp3, %L119 ] ++ %tmp3 = add i64 %i5.0, 1 ++ br i1 undef, label %L119, label %if38 ++ ++if38: ; preds = %L119 ++ %tmp4 = add i64 %tmp2, %i5.0 ++ %tmp5 = getelementptr i64, i64 addrspace(10)* %arg, i64 %tmp4 ++ %tmp6 = load i64, i64 addrspace(10)* %tmp5 ++ br i1 undef, label %done, label %if31 ++ ++done: ; preds = %if38 ++ ret void ++} +diff --git a/unittests/Analysis/ScalarEvolutionTest.cpp b/unittests/Analysis/ScalarEvolutionTest.cpp +index f4370842edb..1af241fdfbe 100644 +--- a/unittests/Analysis/ScalarEvolutionTest.cpp ++++ b/unittests/Analysis/ScalarEvolutionTest.cpp +@@ -7,21 +7,22 @@ + // + //===----------------------------------------------------------------------===// + +-#include "llvm/Analysis/ScalarEvolutionExpander.h" +-#include "llvm/Analysis/ScalarEvolutionExpressions.h" ++#include "llvm/ADT/SmallVector.h" + #include "llvm/Analysis/AssumptionCache.h" + #include "llvm/Analysis/LoopInfo.h" +-#include "llvm/Analysis/TargetLibraryInfo.h" +-#include "llvm/ADT/SmallVector.h" + #include "llvm/Analysis/LoopInfo.h" ++#include "llvm/Analysis/ScalarEvolutionExpander.h" ++#include "llvm/Analysis/ScalarEvolutionExpressions.h" ++#include "llvm/Analysis/TargetLibraryInfo.h" + #include "llvm/AsmParser/Parser.h" + #include "llvm/IR/Constants.h" + #include "llvm/IR/Dominators.h" + #include "llvm/IR/GlobalVariable.h" ++#include "llvm/IR/IRBuilder.h" + #include "llvm/IR/InstIterator.h" + #include "llvm/IR/LLVMContext.h" +-#include "llvm/IR/Module.h" + #include "llvm/IR/LegacyPassManager.h" ++#include "llvm/IR/Module.h" + #include "llvm/IR/Verifier.h" + #include "llvm/Support/SourceMgr.h" + #include "gtest/gtest.h" +-- +2.13.1 + diff --git a/deps/patches/llvm-D33179.patch b/deps/patches/llvm-D33179.patch new file mode 100644 index 0000000000000..2be915018de24 --- /dev/null +++ b/deps/patches/llvm-D33179.patch @@ -0,0 +1,64 @@ +From b1a005ba688397ca360e89cd6c6f51f232d6c25e Mon Sep 17 00:00:00 2001 +From: Keno Fischer +Date: Fri, 19 May 2017 18:42:20 -0400 +Subject: [PATCH] [Sink] Fix predicate in legality check + +Summary: +isSafeToSpeculativelyExecute is the wrong predicate to use here. +All that checks for is whether it is safe to hoist a value due to +unaligned/un-dereferencable accesses. However, not only are we doing +sinking rather than hoisting, our concern is that the location +we're loading from may have been modified. Instead forbid sinking +any load across a critical edge. + +Reviewers: majnemer + +Subscribers: llvm-commits + +Differential Revision: https://reviews.llvm.org/D33179 +--- + lib/Transforms/Scalar/Sink.cpp | 2 +- + test/Transforms/Sink/badloadsink.ll | 18 ++++++++++++++++++ + 2 files changed, 19 insertions(+), 1 deletion(-) + create mode 100644 test/Transforms/Sink/badloadsink.ll + +diff --git a/lib/Transforms/Scalar/Sink.cpp b/lib/Transforms/Scalar/Sink.cpp +index 102e9ea..5210f16 100644 +--- a/lib/Transforms/Scalar/Sink.cpp ++++ b/lib/Transforms/Scalar/Sink.cpp +@@ -114,7 +114,7 @@ static bool IsAcceptableTarget(Instruction *Inst, BasicBlock *SuccToSinkTo, + if (SuccToSinkTo->getUniquePredecessor() != Inst->getParent()) { + // We cannot sink a load across a critical edge - there may be stores in + // other code paths. +- if (!isSafeToSpeculativelyExecute(Inst)) ++ if (isa(Inst)) + return false; + + // We don't want to sink across a critical edge if we don't dominate the +diff --git a/test/Transforms/Sink/badloadsink.ll b/test/Transforms/Sink/badloadsink.ll +new file mode 100644 +index 0000000..e3f4884 +--- /dev/null ++++ b/test/Transforms/Sink/badloadsink.ll +@@ -0,0 +1,18 @@ ++; RUN: opt < %s -basicaa -sink -S | FileCheck %s ++declare void @foo(i64 *) ++define i64 @sinkload(i1 %cmp) { ++; CHECK-LABEL: @sinkload ++top: ++ %a = alloca i64 ++; CHECK: call void @foo(i64* %a) ++; CHECK-NEXT: %x = load i64, i64* %a ++ call void @foo(i64* %a) ++ %x = load i64, i64* %a ++ br i1 %cmp, label %A, label %B ++A: ++ store i64 0, i64 *%a ++ br label %B ++B: ++; CHECK-NOT: load i64, i64 *%a ++ ret i64 %x ++} +-- +2.9.3 + diff --git a/deps/patches/llvm-D37939-Mem2Reg-Also-handle-memcpy.patch b/deps/patches/llvm-D37939-Mem2Reg-Also-handle-memcpy.patch new file mode 100644 index 0000000000000..b8753b0439ba0 --- /dev/null +++ b/deps/patches/llvm-D37939-Mem2Reg-Also-handle-memcpy.patch @@ -0,0 +1,365 @@ +From da4504b2d3c6629fbd58634bf76f1b85939d07cf Mon Sep 17 00:00:00 2001 +From: Keno Fischer +Date: Fri, 15 Sep 2017 18:30:59 -0400 +Subject: [PATCH] [Mem2Reg] Also handle memcpy + +Summary: +In julia, when we know we're moving data between two memory locations, +we always emit that as a memcpy rather than a load/store pair. However, +this can give worse optimization results in certain cases because some +optimizations that can handle load/store pairs cannot handle memcpys. +Mem2reg is one of these optimizations. This patch adds rudamentary +support for mem2reg for recognizing memcpys that cover the whole alloca +we're promoting. While several more sophisticated passes (SROA, GVN) +can get similar optimizations, it is preferable to have these kinds +of cases caught early to expose optimization opportunities before +getting to these later passes. The approach taken here is to split +the memcpy into a load/store pair early (after legality analysis) +and retain the rest of the analysis only on loads/stores. It would +be possible of course to leave the memcpy as is and generate the +left over load or store only on demand. However, that would entail +a significantly larger patch for unclear benefit. + +Reviewers: chandlerc, dberlin + +Subscribers: llvm-commits + +Differential Revision: https://reviews.llvm.org/D37939 +--- + lib/Transforms/Utils/PromoteMemoryToRegister.cpp | 166 ++++++++++++++++++++--- + test/Transforms/Mem2Reg/memcpy.ll | 101 ++++++++++++++ + 2 files changed, 251 insertions(+), 16 deletions(-) + create mode 100644 test/Transforms/Mem2Reg/memcpy.ll + +diff --git a/lib/Transforms/Utils/PromoteMemoryToRegister.cpp b/lib/Transforms/Utils/PromoteMemoryToRegister.cpp +index ac28f59..b08a0a1 100644 +--- a/lib/Transforms/Utils/PromoteMemoryToRegister.cpp ++++ b/lib/Transforms/Utils/PromoteMemoryToRegister.cpp +@@ -49,6 +49,58 @@ STATISTIC(NumSingleStore, "Number of alloca's promoted with a single store"); + STATISTIC(NumDeadAlloca, "Number of dead alloca's removed"); + STATISTIC(NumPHIInsert, "Number of PHI nodes inserted"); + ++static bool isSplittableMemCpy(const MemCpyInst *MCI, const AllocaInst *AI) { ++ // Punt if this alloca is an array allocation ++ if (AI->isArrayAllocation()) ++ return false; ++ if (MCI->isVolatile()) ++ return false; ++ Value *Length = MCI->getLength(); ++ if (!isa(Length)) ++ return false; ++ // Anything less than the full alloca, we leave for SROA ++ const DataLayout &DL = AI->getModule()->getDataLayout(); ++ size_t AIElSize = DL.getTypeAllocSize(AI->getAllocatedType()); ++ if (cast(Length)->getZExtValue() != AIElSize) ++ return false; ++ // If the other argument is also an alloca, we need to be sure that either ++ // the types are bitcastable, or the other alloca is not eligible for ++ // promotion (e.g. because the memcpy is for less than the whole size of ++ // that alloca), otherwise we risk turning an allocatable alloca into a ++ // non-allocatable one when splitting the memcpy. ++ AllocaInst *OtherAI = dyn_cast( ++ AI == MCI->getSource() ? MCI->getDest() : MCI->getSource()); ++ if (OtherAI) { ++ if (!CastInst::isBitCastable(AI->getAllocatedType(), ++ OtherAI->getAllocatedType()) && ++ DL.getTypeAllocSize(OtherAI->getAllocatedType()) == AIElSize) ++ return false; ++ } ++ return true; ++} ++ ++/// Look at the result of a bitcast and see if it's only used by lifetime ++/// intrinsics or splittable memcpys. This is needed, because IRBuilder ++/// will always insert a bitcast to i8* for these intrinsics. ++static bool onlyHasCanonicalizableUsers(const AllocaInst *AI, const Value *V) { ++ for (const User *U : V->users()) { ++ const IntrinsicInst *II = dyn_cast(U); ++ if (!II) ++ return false; ++ ++ if (isa(II)) { ++ if (!isSplittableMemCpy(cast(II), AI)) ++ return false; ++ continue; ++ } ++ ++ if (II->getIntrinsicID() != Intrinsic::lifetime_start && ++ II->getIntrinsicID() != Intrinsic::lifetime_end) ++ return false; ++ } ++ return true; ++} ++ + bool llvm::isAllocaPromotable(const AllocaInst *AI) { + // FIXME: If the memory unit is of pointer or integer type, we can permit + // assignments to subsections of the memory unit. +@@ -68,6 +120,9 @@ bool llvm::isAllocaPromotable(const AllocaInst *AI) { + // not have any meaning for a local alloca. + if (SI->isVolatile()) + return false; ++ } else if (const MemCpyInst *MCI = dyn_cast(U)) { ++ if (!isSplittableMemCpy(MCI, AI)) ++ return false; + } else if (const IntrinsicInst *II = dyn_cast(U)) { + if (II->getIntrinsicID() != Intrinsic::lifetime_start && + II->getIntrinsicID() != Intrinsic::lifetime_end) +@@ -75,7 +130,7 @@ bool llvm::isAllocaPromotable(const AllocaInst *AI) { + } else if (const BitCastInst *BCI = dyn_cast(U)) { + if (BCI->getType() != Type::getInt8PtrTy(U->getContext(), AS)) + return false; +- if (!onlyUsedByLifetimeMarkers(BCI)) ++ if (!onlyHasCanonicalizableUsers(AI, BCI)) + return false; + } else if (const GetElementPtrInst *GEPI = dyn_cast(U)) { + if (GEPI->getType() != Type::getInt8PtrTy(U->getContext(), AS)) +@@ -181,7 +235,13 @@ public: + /// This code only looks at accesses to allocas. + static bool isInterestingInstruction(const Instruction *I) { ++ if (isa(I)) { ++ const MemCpyInst *MCI = cast(I); ++ return isa(MCI->getSource()) || ++ isa(MCI->getDest()); ++ } else { + return (isa(I) && isa(I->getOperand(0))) || + (isa(I) && isa(I->getOperand(1))); + } ++ } + + /// Get or calculate the index of the specified instruction. +@@ -208,6 +264,25 @@ public: + return It->second; + } + ++ // When we split a memcpy intrinsic, we need to update the numbering in this ++ // struct. To make sure the relative ordering remains the same, we give both ++ // the LI and the SI the number that the MCI used to have (if they are both ++ // interesting). This means that they will have equal numbers, which usually ++ // can't happen. However, since they can never reference the same alloca ++ // (since memcpy operands may not overlap), this is fine, because we will ++ // never compare instruction indices for instructions that operate on distinct ++ // allocas. ++ void splitMemCpy(MemCpyInst *MCI, LoadInst *LI, StoreInst *SI) { ++ DenseMap::iterator It = ++ InstNumbers.find(MCI); ++ if (It == InstNumbers.end()) ++ return; ++ unsigned MemCpyNumber = It->second; ++ InstNumbers[LI] = MemCpyNumber; ++ InstNumbers[SI] = MemCpyNumber; ++ deleteValue(MCI); ++ } ++ + void deleteValue(const Instruction *I) { InstNumbers.erase(I); } + + void clear() { InstNumbers.clear(); } +@@ -305,9 +380,58 @@ static void addAssumeNonNull(AssumptionCache *AC, LoadInst *LI) { + AC->registerAssumption(CI); + } + +-static void removeLifetimeIntrinsicUsers(AllocaInst *AI) { +- // Knowing that this alloca is promotable, we know that it's safe to kill all +- // instructions except for load and store. ++/// Split a memcpy instruction into the corresponding load/store. It is a little ++/// more complicated than one might imagine, because we need to deal with the ++/// fact that the side of the copy we're not currently processing might also ++/// be a promotable alloca. We need to be careful to not break the promotable ++/// predicate for that other alloca (if any). ++static void doMemCpySplit(LargeBlockInfo &LBI, MemCpyInst *MCI, ++ AllocaInst *AI) { ++ AAMDNodes AA; ++ MCI->getAAMetadata(AA); ++ Value *MCISrc = MCI->getSource(); ++ Type *LoadType = AI->getAllocatedType(); ++ AllocaInst *SrcAI = dyn_cast(MCISrc); ++ if (SrcAI && SrcAI->getType() != AI->getType()) { ++ if (CastInst::isBitCastable(SrcAI->getAllocatedType(), LoadType)) ++ LoadType = SrcAI->getAllocatedType(); ++ } ++ if (cast(MCISrc->getType())->getElementType() != LoadType) ++ MCISrc = CastInst::Create( ++ Instruction::BitCast, MCISrc, ++ LoadType->getPointerTo( ++ cast(MCISrc->getType())->getAddressSpace()), ++ "", MCI); ++ // This might add to the end of the use list, but that's fine. At worst, ++ // we'd not visit the instructions we insert here, but we don't care ++ // about them in this loop anyway. ++ LoadInst *LI = new LoadInst(LoadType, MCISrc, "", MCI->isVolatile(), ++ MCI->getAlignment(), MCI); ++ Value *Val = LI; ++ Value *MCIDest = MCI->getDest(); ++ AllocaInst *DestAI = dyn_cast(MCIDest); ++ Type *DestElTy = DestAI ? DestAI->getAllocatedType() : AI->getAllocatedType(); ++ if (LI->getType() != DestElTy && ++ CastInst::isBitCastable(LI->getType(), DestElTy)) ++ Val = CastInst::Create(Instruction::BitCast, Val, DestElTy, "", MCI); ++ if (cast(MCIDest->getType())->getElementType() != Val->getType()) ++ MCIDest = CastInst::Create( ++ Instruction::BitCast, MCIDest, ++ Val->getType()->getPointerTo( ++ cast(MCIDest->getType())->getAddressSpace()), ++ "", MCI); ++ StoreInst *SI = ++ new StoreInst(Val, MCIDest, MCI->isVolatile(), MCI->getAlignment(), MCI); ++ LI->setAAMetadata(AA); ++ SI->setAAMetadata(AA); ++ LBI.splitMemCpy(MCI, LI, SI); ++ MCI->eraseFromParent(); ++} ++ ++static void canonicalizeUsers(LargeBlockInfo &LBI, AllocaInst *AI) { ++ // Knowing that this alloca is promotable, we know that it's safe to split ++ // MTIs into load/store and to kill all other instructions except for ++ // load and store. + + for (auto UI = AI->user_begin(), UE = AI->user_end(); UI != UE;) { + Instruction *I = cast(*UI); +@@ -315,14 +439,24 @@ static void removeLifetimeIntrinsicUsers(AllocaInst *AI) { + if (isa(I) || isa(I)) + continue; + ++ if (isa(I)) { ++ MemCpyInst *MCI = cast(I); ++ doMemCpySplit(LBI, MCI, AI); ++ continue; ++ } ++ + if (!I->getType()->isVoidTy()) { +- // The only users of this bitcast/GEP instruction are lifetime intrinsics. +- // Follow the use/def chain to erase them now instead of leaving it for +- // dead code elimination later. ++ // The only users of this bitcast/GEP instruction are lifetime/memcpy ++ // intrinsics. Split memcpys and delete lifetime intrinsics. + for (auto UUI = I->user_begin(), UUE = I->user_end(); UUI != UUE;) { + Instruction *Inst = cast(*UUI); + ++UUI; +- Inst->eraseFromParent(); ++ if (isa(Inst)) { ++ doMemCpySplit(LBI, cast(Inst), AI); ++ } else { ++ // Must be a lifetime intrinsic ++ Inst->eraseFromParent(); ++ } + } + } + I->eraseFromParent(); +@@ -542,7 +676,7 @@ void PromoteMem2Reg::run() { + assert(AI->getParent()->getParent() == &F && + "All allocas should be in the same function, which is same as DF!"); + +- removeLifetimeIntrinsicUsers(AI); ++ canonicalizeUsers(LBI, AI); + + if (AI->use_empty()) { + // If there are no uses of the alloca, just delete it now. +diff --git a/test/Transforms/Mem2Reg/memcpy.ll b/test/Transforms/Mem2Reg/memcpy.ll +new file mode 100644 +index 0000000..fbc4096 +--- /dev/null ++++ b/test/Transforms/Mem2Reg/memcpy.ll +@@ -0,0 +1,101 @@ ++; RUN: opt < %s -mem2reg -S | FileCheck %s ++ ++target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" ++ ++declare void @llvm.memcpy.p0i128.p0i64.i32(i128 *, i64 *, i32, i32, i1) ++declare void @llvm.memcpy.p0i8.p0i8.i32(i8 *, i8 *, i32, i32, i1) ++declare void @llvm.memcpy.p0i64.p0i64.i32(i64 *, i64 *, i32, i32, i1) ++declare void @llvm.memcpy.p0f64.p0i64.i32(double *, i64 *, i32, i32, i1) ++ ++define i128 @test_cpy_different(i64) { ++; CHECK-LABEL: @test_cpy_different ++; CHECK-NOT: alloca i64 ++; CHECK: store i64 %0 ++ %a = alloca i64 ++ %b = alloca i128 ++ store i128 0, i128 *%b ++ store i64 %0, i64 *%a ++ call void @llvm.memcpy.p0i128.p0i64.i32(i128 *%b, i64 *%a, i32 8, i32 0, i1 0) ++ %loaded = load i128, i128 *%b ++ ret i128 %loaded ++} ++ ++define i64 @test_cpy_same(i64) { ++; CHECK-LABEL: @test_cpy_same ++; CHECK-NOT: alloca ++; CHECK: ret i64 %0 ++ %a = alloca i64 ++ %b = alloca i64 ++ store i64 %0, i64 *%a ++ call void @llvm.memcpy.p0i64.p0i64.i32(i64 *%b, i64 *%a, i32 8, i32 0, i1 0) ++ %loaded = load i64, i64 *%b ++ ret i64 %loaded ++} ++ ++define double @test_cpy_different_type(i64) { ++; CHECK-LABEL: @test_cpy_different_type ++; CHECK-NOT: alloca ++; CHECK: bitcast i64 %0 to double ++ %a = alloca i64 ++ %b = alloca double ++ store i64 %0, i64 *%a ++ call void @llvm.memcpy.p0f64.p0i64.i32(double *%b, i64 *%a, i32 8, i32 0, i1 0) ++ %loaded = load double, double *%b ++ ret double %loaded ++} ++ ++define i128 @test_cpy_differenti8(i64) { ++; CHECK-LABEL: @test_cpy_differenti8 ++; CHECK-NOT: alloca i64 ++; CHECK: store i64 %0 ++ %a = alloca i64 ++ %b = alloca i128 ++ store i128 0, i128 *%b ++ store i64 %0, i64 *%a ++ %acast = bitcast i64* %a to i8* ++ %bcast = bitcast i128* %b to i8* ++ call void @llvm.memcpy.p0i8.p0i8.i32(i8 *%bcast, i8 *%acast, i32 8, i32 0, i1 0) ++ %loaded = load i128, i128 *%b ++ ret i128 %loaded ++} ++ ++define i64 @test_cpy_samei8(i64) { ++; CHECK-LABEL: @test_cpy_samei8 ++; CHECK-NOT: alloca ++; CHECK: ret i64 %0 ++ %a = alloca i64 ++ %b = alloca i64 ++ store i64 %0, i64 *%a ++ %acast = bitcast i64* %a to i8* ++ %bcast = bitcast i64* %b to i8* ++ call void @llvm.memcpy.p0i8.p0i8.i32(i8 *%bcast, i8 *%acast, i32 8, i32 0, i1 0) ++ %loaded = load i64, i64 *%b ++ ret i64 %loaded ++} ++ ++define double @test_cpy_different_typei8(i64) { ++; CHECK-LABEL: @test_cpy_different_typei8 ++; CHECK-NOT: alloca ++; CHECK: bitcast i64 %0 to double ++ %a = alloca i64 ++ %b = alloca double ++ store i64 %0, i64 *%a ++ %acast = bitcast i64* %a to i8* ++ %bcast = bitcast double* %b to i8* ++ call void @llvm.memcpy.p0i8.p0i8.i32(i8 *%bcast, i8 *%acast, i32 8, i32 0, i1 0) ++ %loaded = load double, double *%b ++ ret double %loaded ++} ++ ++define i64 @test_cpy_differenti8_reverse(i128) { ++; CHECK-LABEL: @test_cpy_differenti8_reverse ++; CHECK-NOT: alloca i64 ++ %a = alloca i64 ++ %b = alloca i128 ++ store i128 %0, i128 *%b ++ %acast = bitcast i64* %a to i8* ++ %bcast = bitcast i128* %b to i8* ++ call void @llvm.memcpy.p0i8.p0i8.i32(i8 *%acast, i8 *%bcast, i32 8, i32 0, i1 0) ++ %loaded = load i64, i64 *%a ++ ret i64 %loaded ++} +-- +2.9.3 + diff --git a/deps/patches/llvm-D38765-gvn_5.0.patch b/deps/patches/llvm-D38765-gvn_5.0.patch new file mode 100644 index 0000000000000..15c81dd8fd8d1 --- /dev/null +++ b/deps/patches/llvm-D38765-gvn_5.0.patch @@ -0,0 +1,51 @@ +From c65eb3a4b70a119da41ff2d3ebce0b037f92cba7 Mon Sep 17 00:00:00 2001 +From: Davide Italiano +Date: Wed, 11 Oct 2017 04:21:51 +0000 +Subject: [PATCH] [GVN] Don't replace constants with constants. + +This fixes PR34908. Patch by Alex Crichton! + +Differential Revision: https://reviews.llvm.org/D38765 + +git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@315429 91177308-0d34-0410-b5e6-96231b3b80d8 +--- + lib/Transforms/Scalar/GVN.cpp | 5 +++++ + test/Transforms/GVN/pr34908.ll | 13 +++++++++++++ + 2 files changed, 18 insertions(+) + create mode 100644 test/Transforms/GVN/pr34908.ll + +diff --git a/lib/Transforms/Scalar/GVN.cpp b/lib/Transforms/Scalar/GVN.cpp +index 4e24d755c26..c3cc2375e3b 100644 +--- a/lib/Transforms/Scalar/GVN.cpp ++++ b/lib/Transforms/Scalar/GVN.cpp +@@ -1362,6 +1362,11 @@ bool GVN::processAssumeIntrinsic(IntrinsicInst *IntrinsicI) { + } + markInstructionForDeletion(IntrinsicI); + return false; ++ } else if (isa(V)) { ++ // If it's not false, and constant, it must evaluate to true. This means our ++ // assume is assume(true), and thus, pointless, and we don't want to do ++ // anything more here. ++ return false; + } + + Constant *True = ConstantInt::getTrue(V->getContext()); +diff --git a/test/Transforms/GVN/pr34908.ll b/test/Transforms/GVN/pr34908.ll +new file mode 100644 +index 00000000000..c2b58ad34a6 +--- /dev/null ++++ b/test/Transforms/GVN/pr34908.ll +@@ -0,0 +1,13 @@ ++; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ++; RUN: opt < %s -gvn -S | FileCheck %s ++ ++define i1 @foo() { ++; CHECK-LABEL: @foo( ++; CHECK-NEXT: call void @llvm.assume(i1 undef) ++; CHECK-NEXT: ret i1 undef ++; ++ call void @llvm.assume(i1 undef) ++ ret i1 undef ++} ++ ++declare void @llvm.assume(i1) diff --git a/deps/patches/llvm-D39297-musl-dynamiclibrary-pre5.patch b/deps/patches/llvm-D39297-musl-dynamiclibrary-pre5.patch new file mode 100644 index 0000000000000..2ed33c9969f9f --- /dev/null +++ b/deps/patches/llvm-D39297-musl-dynamiclibrary-pre5.patch @@ -0,0 +1,40 @@ +From ae8900a8833835309aecb0a3d947c2ae46fd86c3 Mon Sep 17 00:00:00 2001 +From: Keno Fischer +Date: Thu, 26 Oct 2017 16:44:13 +0000 +Subject: [PATCH] [DynamicLibrary] Fix build on musl libc + +Summary: +On musl libc, stdin/out/err are defined as `FILE* const` globals, +and their address is not implicitly convertible to void *, +or at least gcc 6 doesn't allow it, giving errors like: + +``` +error: cannot initialize return object of type 'void *' with an rvalue of type 'FILE *const *' (aka '_IO_FILE *const *') + EXPLICIT_SYMBOL(stderr); + ^~~~~~~~~~~~~~~~~~~~~~~ +``` + +Add an explicit cast to fix that problem. + +Reviewers: marsupial, krytarowski, dim +Reviewed By: dim +Differential Revision: https://reviews.llvm.org/D39297 + +git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@316672 91177308-0d34-0410-b5e6-96231b3b80d8 +--- + lib/Support/Unix/DynamicLibrary.inc | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/lib/Support/Unix/DynamicLibrary.inc b/lib/Support/Unix/DynamicLibrary.inc +index f05103ccd1eb..029451f347e8 100644 +--- a/lib/Support/DynamicLibrary.cpp ++++ b/lib/Support/DynamicLibrary.cpp +@@ -71,7 +71,7 @@ void *DynamicLibrary::HandleSet::DLSym(void *Handle, const char *Symbol) { + + // This macro returns the address of a well-known, explicit symbol + #define EXPLICIT_SYMBOL(SYM) \ +- if (!strcmp(symbolName, #SYM)) return &SYM ++ if (!strcmp(symbolName, #SYM)) return (void*)&SYM + + // On linux we have a weird situation. The stderr/out/in symbols are both + // macros and global variables because of standards requirements. So, we diff --git a/deps/patches/llvm-D39297-musl-dynamiclibrary.patch b/deps/patches/llvm-D39297-musl-dynamiclibrary.patch new file mode 100644 index 0000000000000..f1956d841b39c --- /dev/null +++ b/deps/patches/llvm-D39297-musl-dynamiclibrary.patch @@ -0,0 +1,40 @@ +From ae8900a8833835309aecb0a3d947c2ae46fd86c3 Mon Sep 17 00:00:00 2001 +From: Keno Fischer +Date: Thu, 26 Oct 2017 16:44:13 +0000 +Subject: [PATCH] [DynamicLibrary] Fix build on musl libc + +Summary: +On musl libc, stdin/out/err are defined as `FILE* const` globals, +and their address is not implicitly convertible to void *, +or at least gcc 6 doesn't allow it, giving errors like: + +``` +error: cannot initialize return object of type 'void *' with an rvalue of type 'FILE *const *' (aka '_IO_FILE *const *') + EXPLICIT_SYMBOL(stderr); + ^~~~~~~~~~~~~~~~~~~~~~~ +``` + +Add an explicit cast to fix that problem. + +Reviewers: marsupial, krytarowski, dim +Reviewed By: dim +Differential Revision: https://reviews.llvm.org/D39297 + +git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@316672 91177308-0d34-0410-b5e6-96231b3b80d8 +--- + lib/Support/Unix/DynamicLibrary.inc | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/lib/Support/Unix/DynamicLibrary.inc b/lib/Support/Unix/DynamicLibrary.inc +index f05103ccd1eb..029451f347e8 100644 +--- a/lib/Support/Unix/DynamicLibrary.inc ++++ b/lib/Support/Unix/DynamicLibrary.inc +@@ -71,7 +71,7 @@ void *DynamicLibrary::HandleSet::DLSym(void *Handle, const char *Symbol) { + // Must declare the symbols in the global namespace. + static void *DoSearch(const char* SymbolName) { + #define EXPLICIT_SYMBOL(SYM) \ +- extern void *SYM; if (!strcmp(SymbolName, #SYM)) return &SYM ++ extern void *SYM; if (!strcmp(SymbolName, #SYM)) return (void*)&SYM + + // If this is darwin, it has some funky issues, try to solve them here. Some + // important symbols are marked 'private external' which doesn't allow diff --git a/deps/patches/llvm-D9168_argument_alignment.patch b/deps/patches/llvm-D9168_argument_alignment.patch new file mode 100644 index 0000000000000..8166cc379f419 --- /dev/null +++ b/deps/patches/llvm-D9168_argument_alignment.patch @@ -0,0 +1,98 @@ +Index: lib/Target/NVPTX/NVPTXISelLowering.h +=================================================================== +--- a/lib/Target/NVPTX/NVPTXISelLowering.h ++++ b/lib/Target/NVPTX/NVPTXISelLowering.h +@@ -539,7 +539,8 @@ + SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const override; + + unsigned getArgumentAlignment(SDValue Callee, const ImmutableCallSite *CS, +- Type *Ty, unsigned Idx) const; ++ Type *Ty, unsigned Idx, ++ const DataLayout &DL) const; + }; + } // namespace llvm + +Index: lib/Target/NVPTX/NVPTXISelLowering.cpp +=================================================================== +--- a/lib/Target/NVPTX/NVPTXISelLowering.cpp ++++ b/lib/Target/NVPTX/NVPTXISelLowering.cpp +@@ -1024,11 +1024,15 @@ + return O.str(); + } + +-unsigned +-NVPTXTargetLowering::getArgumentAlignment(SDValue Callee, +- const ImmutableCallSite *CS, +- Type *Ty, +- unsigned Idx) const { ++unsigned NVPTXTargetLowering::getArgumentAlignment(SDValue Callee, ++ const ImmutableCallSite *CS, ++ Type *Ty, unsigned Idx, ++ const DataLayout &DL) const { ++ if (!CS) { ++ // CallSite is zero, fallback to ABI type alignment ++ return DL.getABITypeAlignment(Ty); ++ } ++ + unsigned Align = 0; + const Value *DirectCallee = CS->getCalledFunction(); + +@@ -1046,7 +1050,7 @@ + + const Value *CalleeV = cast(CalleeI)->getCalledValue(); + // Ignore any bitcast instructions +- while(isa(CalleeV)) { ++ while (isa(CalleeV)) { + const ConstantExpr *CE = cast(CalleeV); + if (!CE->isCast()) + break; +@@ -1069,7 +1073,6 @@ + + // Call is indirect or alignment information is not available, fall back to + // the ABI type alignment +- auto &DL = CS->getCaller()->getParent()->getDataLayout(); + return DL.getABITypeAlignment(Ty); + } + +@@ -1126,7 +1129,8 @@ + ComputePTXValueVTs(*this, DAG.getDataLayout(), Ty, vtparts, &Offsets, + 0); + +- unsigned align = getArgumentAlignment(Callee, CS, Ty, paramCount + 1); ++ unsigned align = ++ getArgumentAlignment(Callee, CS, Ty, paramCount + 1, DL); + // declare .param .align .b8 .param[]; + unsigned sz = DL.getTypeAllocSize(Ty); + SDVTList DeclareParamVTs = DAG.getVTList(MVT::Other, MVT::Glue); +@@ -1166,7 +1170,8 @@ + } + if (Ty->isVectorTy()) { + EVT ObjectVT = getValueType(DL, Ty); +- unsigned align = getArgumentAlignment(Callee, CS, Ty, paramCount + 1); ++ unsigned align = ++ getArgumentAlignment(Callee, CS, Ty, paramCount + 1, DL); + // declare .param .align .b8 .param[]; + unsigned sz = DL.getTypeAllocSize(Ty); + SDVTList DeclareParamVTs = DAG.getVTList(MVT::Other, MVT::Glue); +@@ -1426,7 +1431,7 @@ + DeclareRetOps); + InFlag = Chain.getValue(1); + } else { +- retAlignment = getArgumentAlignment(Callee, CS, retTy, 0); ++ retAlignment = getArgumentAlignment(Callee, CS, retTy, 0, DL); + SDVTList DeclareRetVTs = DAG.getVTList(MVT::Other, MVT::Glue); + SDValue DeclareRetOps[] = { Chain, + DAG.getConstant(retAlignment, dl, MVT::i32), +@@ -1633,9 +1638,10 @@ + } else { + SmallVector VTs; + SmallVector Offsets; +- ComputePTXValueVTs(*this, DAG.getDataLayout(), retTy, VTs, &Offsets, 0); ++ auto &DL = DAG.getDataLayout(); ++ ComputePTXValueVTs(*this, DL, retTy, VTs, &Offsets, 0); + assert(VTs.size() == Ins.size() && "Bad value decomposition"); +- unsigned RetAlign = getArgumentAlignment(Callee, CS, retTy, 0); ++ unsigned RetAlign = getArgumentAlignment(Callee, CS, retTy, 0, DL); + for (unsigned i = 0, e = Ins.size(); i != e; ++i) { + unsigned sz = VTs[i].getSizeInBits(); + unsigned AlignI = GreatestCommonDivisor64(RetAlign, Offsets[i]); diff --git a/deps/patches/llvm-NVPTX-addrspaces.patch b/deps/patches/llvm-NVPTX-addrspaces.patch new file mode 100644 index 0000000000000..006868d61ace0 --- /dev/null +++ b/deps/patches/llvm-NVPTX-addrspaces.patch @@ -0,0 +1,30 @@ +diff -u llvm-3.9.1.orig/lib/Target/NVPTX/NVPTXISelLowering.cpp llvm-3.9.1/lib/Target/NVPTX/NVPTXISelLowering.cpp +--- llvm-3.9.1.orig/lib/Target/NVPTX/NVPTXISelLowering.cpp 2016-07-15 20:27:10.000000000 +0200 ++++ llvm-3.9.1/lib/Target/NVPTX/NVPTXISelLowering.cpp 2017-09-07 04:04:25.540721694 +0200 +@@ -888,6 +910,14 @@ + return TargetLoweringBase::getPreferredVectorAction(VT); + } + ++bool NVPTXTargetLowering::isNoopAddrSpaceCast(unsigned SrcAS, ++ unsigned DestAS) const { ++ assert(SrcAS != DestAS && "Expected different address spaces!"); ++ ++ return (SrcAS == ADDRESS_SPACE_GENERIC || SrcAS > ADDRESS_SPACE_LOCAL) && ++ (DestAS == ADDRESS_SPACE_GENERIC || DestAS > ADDRESS_SPACE_LOCAL); ++} ++ + SDValue + NVPTXTargetLowering::LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const { + SDLoc dl(Op); +diff -u llvm-3.9.1.orig/lib/Target/NVPTX/NVPTXISelLowering.h llvm-3.9.1/lib/Target/NVPTX/NVPTXISelLowering.h +--- llvm-3.9.1.orig/lib/Target/NVPTX/NVPTXISelLowering.h 2016-06-12 17:39:02.000000000 +0200 ++++ llvm-3.9.1/lib/Target/NVPTX/NVPTXISelLowering.h 2017-09-07 04:03:39.591373952 +0200 +@@ -442,6 +442,8 @@ + const NVPTXSubtarget &STI); + SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override; + ++ bool isNoopAddrSpaceCast(unsigned SrcAS, unsigned DestAS) const override; ++ + SDValue LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const; + + const char *getTargetNodeName(unsigned Opcode) const override; diff --git a/deps/patches/llvm-PR22923.patch b/deps/patches/llvm-PR22923.patch new file mode 100644 index 0000000000000..c48533bcc4d89 --- /dev/null +++ b/deps/patches/llvm-PR22923.patch @@ -0,0 +1,151 @@ +From e060ffb4b20e294ecb8429bd8a925f9f12b63b17 Mon Sep 17 00:00:00 2001 +From: Hal Finkel +Date: Mon, 29 Aug 2016 22:25:36 +0000 +Subject: [PATCH] [PowerPC] Fix i8/i16 atomics for little-Endian targets + without partword atomics + +For little-Endian PowerPC, we generally target only P8 and later by default. +However, generic (older) 64-bit configurations are still an option, and in that +case, partword atomics are not available (e.g. stbcx.). To lower i8/i16 atomics +without true i8/i16 atomic operations, we emulate using i32 atomics in +combination with a bunch of shifting and masking, etc. The amount by which to +shift in little-Endian mode is different from the amount in big-Endian mode (it +is inverted -- meaning we can leave off the xor when computing the amount). + +Fixes PR22923. + +git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@280022 91177308-0d34-0410-b5e6-96231b3b80d8 +--- + lib/Target/PowerPC/PPCISelLowering.cpp | 18 ++++++++++++------ + test/CodeGen/PowerPC/atomic-2.ll | 15 ++++++++++++++- + 2 files changed, 26 insertions(+), 7 deletions(-) + +diff --git a/lib/Target/PowerPC/PPCISelLowering.cpp b/lib/Target/PowerPC/PPCISelLowering.cpp +index e89b6ca..f895b06 100644 +--- a/lib/Target/PowerPC/PPCISelLowering.cpp ++++ b/lib/Target/PowerPC/PPCISelLowering.cpp +@@ -8513,6 +8513,7 @@ PPCTargetLowering::EmitPartwordAtomicBinary(MachineInstr &MI, + // registers without caring whether they're 32 or 64, but here we're + // doing actual arithmetic on the addresses. + bool is64bit = Subtarget.isPPC64(); ++ bool isLittleEndian = Subtarget.isLittleEndian(); + unsigned ZeroReg = is64bit ? PPC::ZERO8 : PPC::ZERO; + + const BasicBlock *LLVM_BB = BB->getBasicBlock(); +@@ -8542,7 +8543,8 @@ PPCTargetLowering::EmitPartwordAtomicBinary(MachineInstr &MI, + : &PPC::GPRCRegClass; + unsigned PtrReg = RegInfo.createVirtualRegister(RC); + unsigned Shift1Reg = RegInfo.createVirtualRegister(RC); +- unsigned ShiftReg = RegInfo.createVirtualRegister(RC); ++ unsigned ShiftReg = ++ isLittleEndian ? Shift1Reg : RegInfo.createVirtualRegister(RC); + unsigned Incr2Reg = RegInfo.createVirtualRegister(RC); + unsigned MaskReg = RegInfo.createVirtualRegister(RC); + unsigned Mask2Reg = RegInfo.createVirtualRegister(RC); +@@ -8587,8 +8589,9 @@ PPCTargetLowering::EmitPartwordAtomicBinary(MachineInstr &MI, + } + BuildMI(BB, dl, TII->get(PPC::RLWINM), Shift1Reg).addReg(Ptr1Reg) + .addImm(3).addImm(27).addImm(is8bit ? 28 : 27); +- BuildMI(BB, dl, TII->get(is64bit ? PPC::XORI8 : PPC::XORI), ShiftReg) +- .addReg(Shift1Reg).addImm(is8bit ? 24 : 16); ++ if (!isLittleEndian) ++ BuildMI(BB, dl, TII->get(is64bit ? PPC::XORI8 : PPC::XORI), ShiftReg) ++ .addReg(Shift1Reg).addImm(is8bit ? 24 : 16); + if (is64bit) + BuildMI(BB, dl, TII->get(PPC::RLDICR), PtrReg) + .addReg(Ptr1Reg).addImm(0).addImm(61); +@@ -9293,6 +9296,7 @@ PPCTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI, + // since we're actually doing arithmetic on them. Other registers + // can be 32-bit. + bool is64bit = Subtarget.isPPC64(); ++ bool isLittleEndian = Subtarget.isLittleEndian(); + bool is8bit = MI.getOpcode() == PPC::ATOMIC_CMP_SWAP_I8; + + unsigned dest = MI.getOperand(0).getReg(); +@@ -9319,7 +9323,8 @@ PPCTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI, + : &PPC::GPRCRegClass; + unsigned PtrReg = RegInfo.createVirtualRegister(RC); + unsigned Shift1Reg = RegInfo.createVirtualRegister(RC); +- unsigned ShiftReg = RegInfo.createVirtualRegister(RC); ++ unsigned ShiftReg = ++ isLittleEndian ? Shift1Reg : RegInfo.createVirtualRegister(RC); + unsigned NewVal2Reg = RegInfo.createVirtualRegister(RC); + unsigned NewVal3Reg = RegInfo.createVirtualRegister(RC); + unsigned OldVal2Reg = RegInfo.createVirtualRegister(RC); +@@ -9374,8 +9379,9 @@ PPCTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI, + } + BuildMI(BB, dl, TII->get(PPC::RLWINM), Shift1Reg).addReg(Ptr1Reg) + .addImm(3).addImm(27).addImm(is8bit ? 28 : 27); +- BuildMI(BB, dl, TII->get(is64bit ? PPC::XORI8 : PPC::XORI), ShiftReg) +- .addReg(Shift1Reg).addImm(is8bit ? 24 : 16); ++ if (!isLittleEndian) ++ BuildMI(BB, dl, TII->get(is64bit ? PPC::XORI8 : PPC::XORI), ShiftReg) ++ .addReg(Shift1Reg).addImm(is8bit ? 24 : 16); + if (is64bit) + BuildMI(BB, dl, TII->get(PPC::RLDICR), PtrReg) + .addReg(Ptr1Reg).addImm(0).addImm(61); +diff --git a/test/CodeGen/PowerPC/atomic-2.ll b/test/CodeGen/PowerPC/atomic-2.ll +index 1857d5d..bafabdb 100644 +--- a/test/CodeGen/PowerPC/atomic-2.ll ++++ b/test/CodeGen/PowerPC/atomic-2.ll +@@ -1,4 +1,5 @@ +-; RUN: llc < %s -march=ppc64 | FileCheck %s ++; RUN: llc < %s -march=ppc64 | FileCheck %s -check-prefix=CHECK -check-prefix=CHECK-BE ++; RUN: llc < %s -march=ppc64le | FileCheck %s -check-prefix=CHECK -check-prefix=CHECK-LE + ; RUN: llc < %s -march=ppc64 -mcpu=pwr7 | FileCheck %s + ; RUN: llc < %s -march=ppc64 -mcpu=pwr8 | FileCheck %s -check-prefix=CHECK-P8U + +@@ -12,6 +13,8 @@ define i64 @exchange_and_add(i64* %mem, i64 %val) nounwind { + + define i8 @exchange_and_add8(i8* %mem, i8 %val) nounwind { + ; CHECK-LABEL: exchange_and_add8: ++; CHECK-BE: xori ++; CHECK-LE-NOT: xori + ; CHECK-P8U: lbarx + %tmp = atomicrmw add i8* %mem, i8 %val monotonic + ; CHECK-P8U: stbcx. +@@ -20,6 +23,8 @@ define i8 @exchange_and_add8(i8* %mem, i8 %val) nounwind { + + define i16 @exchange_and_add16(i16* %mem, i16 %val) nounwind { + ; CHECK-LABEL: exchange_and_add16: ++; CHECK-BE: xori ++; CHECK-LE-NOT: xori + ; CHECK-P8U: lharx + %tmp = atomicrmw add i16* %mem, i16 %val monotonic + ; CHECK-P8U: sthcx. +@@ -38,6 +43,8 @@ define i64 @exchange_and_cmp(i64* %mem) nounwind { + + define i8 @exchange_and_cmp8(i8* %mem) nounwind { + ; CHECK-LABEL: exchange_and_cmp8: ++; CHECK-BE: xori ++; CHECK-LE-NOT: xori + ; CHECK-P8U: lbarx + %tmppair = cmpxchg i8* %mem, i8 0, i8 1 monotonic monotonic + %tmp = extractvalue { i8, i1 } %tmppair, 0 +@@ -48,6 +55,8 @@ define i8 @exchange_and_cmp8(i8* %mem) nounwind { + + define i16 @exchange_and_cmp16(i16* %mem) nounwind { + ; CHECK-LABEL: exchange_and_cmp16: ++; CHECK-BE: xori ++; CHECK-LE-NOT: xori + ; CHECK-P8U: lharx + %tmppair = cmpxchg i16* %mem, i16 0, i16 1 monotonic monotonic + %tmp = extractvalue { i16, i1 } %tmppair, 0 +@@ -66,6 +75,8 @@ define i64 @exchange(i64* %mem, i64 %val) nounwind { + + define i8 @exchange8(i8* %mem, i8 %val) nounwind { + ; CHECK-LABEL: exchange8: ++; CHECK-BE: xori ++; CHECK-LE-NOT: xori + ; CHECK-P8U: lbarx + %tmp = atomicrmw xchg i8* %mem, i8 1 monotonic + ; CHECK-P8U: stbcx. +@@ -74,6 +85,8 @@ define i8 @exchange8(i8* %mem, i8 %val) nounwind { + + define i16 @exchange16(i16* %mem, i16 %val) nounwind { + ; CHECK-LABEL: exchange16: ++; CHECK-BE: xori ++; CHECK-LE-NOT: xori + ; CHECK-P8U: lharx + %tmp = atomicrmw xchg i16* %mem, i16 1 monotonic + ; CHECK-P8U: sthcx. diff --git a/deps/patches/llvm-PR276266.patch b/deps/patches/llvm-PR276266.patch new file mode 100644 index 0000000000000..576e96e5836d3 --- /dev/null +++ b/deps/patches/llvm-PR276266.patch @@ -0,0 +1,51 @@ +From 64d1e8b748bca22ce205eab7634cc5418c827f18 Mon Sep 17 00:00:00 2001 +From: Marina Yatsina +Date: Thu, 21 Jul 2016 12:37:07 +0000 +Subject: [PATCH 3/5] ExecutionDepsFix - Fix bug in clearance calculation + +The clearance calculation did not take into account registers defined as outputs or clobbers in inline assembly machine instructions because these register defs are implicit. + +Differential Revision: http://reviews.llvm.org/D22580 + + + +git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@276266 91177308-0d34-0410-b5e6-96231b3b80d8 +--- + lib/CodeGen/ExecutionDepsFix.cpp | 2 -- + test/CodeGen/X86/break-false-dep.ll | 10 ++++++++++ + 2 files changed, 10 insertions(+), 2 deletions(-) + +diff --git a/lib/CodeGen/ExecutionDepsFix.cpp b/lib/CodeGen/ExecutionDepsFix.cpp +index 566b8d507b2..1fe5f459b69 100644 +--- a/lib/CodeGen/ExecutionDepsFix.cpp ++++ b/lib/CodeGen/ExecutionDepsFix.cpp +@@ -520,8 +520,6 @@ void ExeDepsFix::processDefs(MachineInstr *MI, bool Kill) { + MachineOperand &MO = MI->getOperand(i); + if (!MO.isReg()) + continue; +- if (MO.isImplicit()) +- break; + if (MO.isUse()) + continue; + for (int rx : regIndices(MO.getReg())) { +diff --git a/test/CodeGen/X86/break-false-dep.ll b/test/CodeGen/X86/break-false-dep.ll +index 74a0728f918..a7cda499dab 100644 +--- a/test/CodeGen/X86/break-false-dep.ll ++++ b/test/CodeGen/X86/break-false-dep.ll +@@ -199,3 +199,13 @@ for.end16: ; preds = %for.inc14 + ;AVX-NEXT: vmulsd {{.*}}, [[XMM0]], [[XMM0]] + ;AVX-NEXT: vmovsd [[XMM0]], + } ++ ++define double @inlineasmdep(i64 %arg) { ++top: ++ tail call void asm sideeffect "", "~{xmm0},~{dirflag},~{fpsr},~{flags}"() ++ %tmp1 = sitofp i64 %arg to double ++ ret double %tmp1 ++;AVX-LABEL:@inlineasmdep ++;AVX: vxorps [[XMM0:%xmm[0-9]+]], [[XMM0]], [[XMM0]] ++;AVX-NEXT: vcvtsi2sdq {{.*}}, [[XMM0]], {{%xmm[0-9]+}} ++} +-- +2.11.0 + diff --git a/deps/patches/llvm-PR277939.patch b/deps/patches/llvm-PR277939.patch new file mode 100644 index 0000000000000..65e46c32b4848 --- /dev/null +++ b/deps/patches/llvm-PR277939.patch @@ -0,0 +1,169 @@ +From 9790ab8bccdbc71dfcc166860ab6ce9c369bf686 Mon Sep 17 00:00:00 2001 +From: Simon Pilgrim +Date: Sat, 6 Aug 2016 21:21:12 +0000 +Subject: [PATCH 1/5] [X86][AVX2] Improve sign/zero extension on AVX2 targets + +Split extensions to large vectors into 256-bit chunks - the equivalent of what we do with pre-AVX2 into 128-bit chunks + +git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@277939 91177308-0d34-0410-b5e6-96231b3b80d8 +--- + lib/Target/X86/X86ISelLowering.cpp | 22 +++++++++++++++------- + test/CodeGen/X86/vec_int_to_fp.ll | 24 ++++++++---------------- + test/CodeGen/X86/vector-sext.ll | 10 ++-------- + 3 files changed, 25 insertions(+), 31 deletions(-) + +diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp +index ca205335013..2bbedd4bd97 100644 +--- a/lib/Target/X86/X86ISelLowering.cpp ++++ b/lib/Target/X86/X86ISelLowering.cpp +@@ -30164,11 +30164,9 @@ static SDValue combineToExtendVectorInReg(SDNode *N, SelectionDAG &DAG, + : DAG.getZeroExtendVectorInReg(ExOp, DL, VT); + } + +- // On pre-AVX2 targets, split into 128-bit nodes of +- // ISD::*_EXTEND_VECTOR_INREG. +- if (!Subtarget.hasInt256() && !(VT.getSizeInBits() % 128)) { +- unsigned NumVecs = VT.getSizeInBits() / 128; +- unsigned NumSubElts = 128 / SVT.getSizeInBits(); ++ auto SplitAndExtendInReg = [&](unsigned SplitSize) { ++ unsigned NumVecs = VT.getSizeInBits() / SplitSize; ++ unsigned NumSubElts = SplitSize / SVT.getSizeInBits(); + EVT SubVT = EVT::getVectorVT(*DAG.getContext(), SVT, NumSubElts); + EVT InSubVT = EVT::getVectorVT(*DAG.getContext(), InSVT, NumSubElts); + +@@ -30176,14 +30174,24 @@ static SDValue combineToExtendVectorInReg(SDNode *N, SelectionDAG &DAG, + for (unsigned i = 0, Offset = 0; i != NumVecs; ++i, Offset += NumSubElts) { + SDValue SrcVec = DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, InSubVT, N0, + DAG.getIntPtrConstant(Offset, DL)); +- SrcVec = ExtendVecSize(DL, SrcVec, 128); ++ SrcVec = ExtendVecSize(DL, SrcVec, SplitSize); + SrcVec = Opcode == ISD::SIGN_EXTEND + ? DAG.getSignExtendVectorInReg(SrcVec, DL, SubVT) + : DAG.getZeroExtendVectorInReg(SrcVec, DL, SubVT); + Opnds.push_back(SrcVec); + } + return DAG.getNode(ISD::CONCAT_VECTORS, DL, VT, Opnds); +- } ++ }; ++ ++ // On pre-AVX2 targets, split into 128-bit nodes of ++ // ISD::*_EXTEND_VECTOR_INREG. ++ if (!Subtarget.hasInt256() && !(VT.getSizeInBits() % 128)) ++ return SplitAndExtendInReg(128); ++ ++ // On pre-AVX512 targets, split into 256-bit nodes of ++ // ISD::*_EXTEND_VECTOR_INREG. ++ if (!Subtarget.hasAVX512() && !(VT.getSizeInBits() % 256)) ++ return SplitAndExtendInReg(256); + + return SDValue(); + } +diff --git a/test/CodeGen/X86/vec_int_to_fp.ll b/test/CodeGen/X86/vec_int_to_fp.ll +index 43f5318a607..5d8f91385c7 100644 +--- a/test/CodeGen/X86/vec_int_to_fp.ll ++++ b/test/CodeGen/X86/vec_int_to_fp.ll +@@ -153,8 +153,7 @@ define <2 x double> @sitofp_16i8_to_2f64(<16 x i8> %a) { + ; + ; AVX2-LABEL: sitofp_16i8_to_2f64: + ; AVX2: # BB#0: +-; AVX2-NEXT: vpmovsxbw %xmm0, %ymm0 +-; AVX2-NEXT: vpmovsxwd %xmm0, %ymm0 ++; AVX2-NEXT: vpmovsxbd %xmm0, %ymm0 + ; AVX2-NEXT: vcvtdq2pd %xmm0, %ymm0 + ; AVX2-NEXT: # kill + ; AVX2-NEXT: vzeroupper +@@ -325,8 +324,7 @@ define <4 x double> @sitofp_16i8_to_4f64(<16 x i8> %a) { + ; + ; AVX2-LABEL: sitofp_16i8_to_4f64: + ; AVX2: # BB#0: +-; AVX2-NEXT: vpmovsxbw %xmm0, %ymm0 +-; AVX2-NEXT: vpmovsxwd %xmm0, %ymm0 ++; AVX2-NEXT: vpmovsxbd %xmm0, %ymm0 + ; AVX2-NEXT: vcvtdq2pd %xmm0, %ymm0 + ; AVX2-NEXT: retq + %cvt = sitofp <16 x i8> %a to <16 x double> +@@ -543,8 +541,7 @@ define <2 x double> @uitofp_16i8_to_2f64(<16 x i8> %a) { + ; + ; AVX2-LABEL: uitofp_16i8_to_2f64: + ; AVX2: # BB#0: +-; AVX2-NEXT: vpmovzxbw {{.*#+}} ymm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero,xmm0[8],zero,xmm0[9],zero,xmm0[10],zero,xmm0[11],zero,xmm0[12],zero,xmm0[13],zero,xmm0[14],zero,xmm0[15],zero +-; AVX2-NEXT: vpmovzxwd {{.*#+}} ymm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero ++; AVX2-NEXT: vpmovzxbd {{.*#+}} ymm0 = xmm0[0],zero,zero,zero,xmm0[1],zero,zero,zero,xmm0[2],zero,zero,zero,xmm0[3],zero,zero,zero,xmm0[4],zero,zero,zero,xmm0[5],zero,zero,zero,xmm0[6],zero,zero,zero,xmm0[7],zero,zero,zero + ; AVX2-NEXT: vcvtdq2pd %xmm0, %ymm0 + ; AVX2-NEXT: # kill + ; AVX2-NEXT: vzeroupper +@@ -778,8 +775,7 @@ define <4 x double> @uitofp_16i8_to_4f64(<16 x i8> %a) { + ; + ; AVX2-LABEL: uitofp_16i8_to_4f64: + ; AVX2: # BB#0: +-; AVX2-NEXT: vpmovzxbw {{.*#+}} ymm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero,xmm0[8],zero,xmm0[9],zero,xmm0[10],zero,xmm0[11],zero,xmm0[12],zero,xmm0[13],zero,xmm0[14],zero,xmm0[15],zero +-; AVX2-NEXT: vpmovzxwd {{.*#+}} ymm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero ++; AVX2-NEXT: vpmovzxbd {{.*#+}} ymm0 = xmm0[0],zero,zero,zero,xmm0[1],zero,zero,zero,xmm0[2],zero,zero,zero,xmm0[3],zero,zero,zero,xmm0[4],zero,zero,zero,xmm0[5],zero,zero,zero,xmm0[6],zero,zero,zero,xmm0[7],zero,zero,zero + ; AVX2-NEXT: vcvtdq2pd %xmm0, %ymm0 + ; AVX2-NEXT: retq + %cvt = uitofp <16 x i8> %a to <16 x double> +@@ -958,8 +954,7 @@ define <4 x float> @sitofp_16i8_to_4f32(<16 x i8> %a) { + ; + ; AVX2-LABEL: sitofp_16i8_to_4f32: + ; AVX2: # BB#0: +-; AVX2-NEXT: vpmovsxbw %xmm0, %ymm0 +-; AVX2-NEXT: vpmovsxwd %xmm0, %ymm0 ++; AVX2-NEXT: vpmovsxbd %xmm0, %ymm0 + ; AVX2-NEXT: vcvtdq2ps %ymm0, %ymm0 + ; AVX2-NEXT: # kill + ; AVX2-NEXT: vzeroupper +@@ -1134,8 +1129,7 @@ define <8 x float> @sitofp_16i8_to_8f32(<16 x i8> %a) { + ; + ; AVX2-LABEL: sitofp_16i8_to_8f32: + ; AVX2: # BB#0: +-; AVX2-NEXT: vpmovsxbw %xmm0, %ymm0 +-; AVX2-NEXT: vpmovsxwd %xmm0, %ymm0 ++; AVX2-NEXT: vpmovsxbd %xmm0, %ymm0 + ; AVX2-NEXT: vcvtdq2ps %ymm0, %ymm0 + ; AVX2-NEXT: retq + %cvt = sitofp <16 x i8> %a to <16 x float> +@@ -1456,8 +1450,7 @@ define <4 x float> @uitofp_16i8_to_4f32(<16 x i8> %a) { + ; + ; AVX2-LABEL: uitofp_16i8_to_4f32: + ; AVX2: # BB#0: +-; AVX2-NEXT: vpmovzxbw {{.*#+}} ymm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero,xmm0[8],zero,xmm0[9],zero,xmm0[10],zero,xmm0[11],zero,xmm0[12],zero,xmm0[13],zero,xmm0[14],zero,xmm0[15],zero +-; AVX2-NEXT: vpmovzxwd {{.*#+}} ymm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero ++; AVX2-NEXT: vpmovzxbd {{.*#+}} ymm0 = xmm0[0],zero,zero,zero,xmm0[1],zero,zero,zero,xmm0[2],zero,zero,zero,xmm0[3],zero,zero,zero,xmm0[4],zero,zero,zero,xmm0[5],zero,zero,zero,xmm0[6],zero,zero,zero,xmm0[7],zero,zero,zero + ; AVX2-NEXT: vcvtdq2ps %ymm0, %ymm0 + ; AVX2-NEXT: # kill + ; AVX2-NEXT: vzeroupper +@@ -1813,8 +1806,7 @@ define <8 x float> @uitofp_16i8_to_8f32(<16 x i8> %a) { + ; + ; AVX2-LABEL: uitofp_16i8_to_8f32: + ; AVX2: # BB#0: +-; AVX2-NEXT: vpmovzxbw {{.*#+}} ymm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero,xmm0[8],zero,xmm0[9],zero,xmm0[10],zero,xmm0[11],zero,xmm0[12],zero,xmm0[13],zero,xmm0[14],zero,xmm0[15],zero +-; AVX2-NEXT: vpmovzxwd {{.*#+}} ymm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero ++; AVX2-NEXT: vpmovzxbd {{.*#+}} ymm0 = xmm0[0],zero,zero,zero,xmm0[1],zero,zero,zero,xmm0[2],zero,zero,zero,xmm0[3],zero,zero,zero,xmm0[4],zero,zero,zero,xmm0[5],zero,zero,zero,xmm0[6],zero,zero,zero,xmm0[7],zero,zero,zero + ; AVX2-NEXT: vcvtdq2ps %ymm0, %ymm0 + ; AVX2-NEXT: retq + %cvt = uitofp <16 x i8> %a to <16 x float> +diff --git a/test/CodeGen/X86/vector-sext.ll b/test/CodeGen/X86/vector-sext.ll +index 018c5922a43..e29f3e5f91f 100644 +--- a/test/CodeGen/X86/vector-sext.ll ++++ b/test/CodeGen/X86/vector-sext.ll +@@ -407,15 +407,9 @@ define <8 x i64> @sext_16i8_to_8i64(<16 x i8> %A) nounwind uwtable readnone ssp + ; + ; AVX2-LABEL: sext_16i8_to_8i64: + ; AVX2: # BB#0: # %entry +-; AVX2-NEXT: vpmovzxbd {{.*#+}} xmm1 = xmm0[0],zero,zero,zero,xmm0[1],zero,zero,zero,xmm0[2],zero,zero,zero,xmm0[3],zero,zero,zero +-; AVX2-NEXT: vpslld $24, %xmm1, %xmm1 +-; AVX2-NEXT: vpsrad $24, %xmm1, %xmm1 +-; AVX2-NEXT: vpmovsxdq %xmm1, %ymm2 ++; AVX2-NEXT: vpmovsxbq %xmm0, %ymm2 + ; AVX2-NEXT: vpshufd {{.*#+}} xmm0 = xmm0[1,1,2,3] +-; AVX2-NEXT: vpmovzxbd {{.*#+}} xmm0 = xmm0[0],zero,zero,zero,xmm0[1],zero,zero,zero,xmm0[2],zero,zero,zero,xmm0[3],zero,zero,zero +-; AVX2-NEXT: vpslld $24, %xmm0, %xmm0 +-; AVX2-NEXT: vpsrad $24, %xmm0, %xmm0 +-; AVX2-NEXT: vpmovsxdq %xmm0, %ymm1 ++; AVX2-NEXT: vpmovsxbq %xmm0, %ymm1 + ; AVX2-NEXT: vmovdqa %ymm2, %ymm0 + ; AVX2-NEXT: retq + ; +-- +2.11.0 + diff --git a/deps/patches/llvm-PR278088.patch b/deps/patches/llvm-PR278088.patch new file mode 100644 index 0000000000000..325069326b3ed --- /dev/null +++ b/deps/patches/llvm-PR278088.patch @@ -0,0 +1,224 @@ +From b01ff685400365f55c5333c29c2227842d61e984 Mon Sep 17 00:00:00 2001 +From: Craig Topper +Date: Tue, 9 Aug 2016 03:06:26 +0000 +Subject: [PATCH 2/5] [X86] Remove unnecessary bitcast from the front of + AVX1Only 256-bit logical operation patterns. + +git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@278088 91177308-0d34-0410-b5e6-96231b3b80d8 +--- + lib/Target/X86/X86InstrSSE.td | 8 +++---- + test/CodeGen/X86/WidenArith.ll | 2 +- + test/CodeGen/X86/merge-consecutive-loads-256.ll | 26 ++++++--------------- + test/CodeGen/X86/v8i1-masks.ll | 4 ++-- + test/CodeGen/X86/vec_int_to_fp.ll | 30 ++++++++++++------------- + test/CodeGen/X86/vec_uint_to_fp-fastmath.ll | 26 ++++++++++----------- + 6 files changed, 42 insertions(+), 54 deletions(-) + +diff --git a/lib/Target/X86/X86InstrSSE.td b/lib/Target/X86/X86InstrSSE.td +index f91764a67d1..77da22de4d3 100644 +--- a/lib/Target/X86/X86InstrSSE.td ++++ b/lib/Target/X86/X86InstrSSE.td +@@ -2950,13 +2950,13 @@ let isCommutable = 0 in + // AVX1 requires type coercions in order to fold loads directly into logical + // operations. + let Predicates = [HasAVX1Only] in { +- def : Pat<(bc_v8f32 (and VR256:$src1, (loadv4i64 addr:$src2))), ++ def : Pat<(and VR256:$src1, (loadv4i64 addr:$src2)), + (VANDPSYrm VR256:$src1, addr:$src2)>; +- def : Pat<(bc_v8f32 (or VR256:$src1, (loadv4i64 addr:$src2))), ++ def : Pat<(or VR256:$src1, (loadv4i64 addr:$src2)), + (VORPSYrm VR256:$src1, addr:$src2)>; +- def : Pat<(bc_v8f32 (xor VR256:$src1, (loadv4i64 addr:$src2))), ++ def : Pat<(xor VR256:$src1, (loadv4i64 addr:$src2)), + (VXORPSYrm VR256:$src1, addr:$src2)>; +- def : Pat<(bc_v8f32 (X86andnp VR256:$src1, (loadv4i64 addr:$src2))), ++ def : Pat<(X86andnp VR256:$src1, (loadv4i64 addr:$src2)), + (VANDNPSYrm VR256:$src1, addr:$src2)>; + } + +diff --git a/test/CodeGen/X86/WidenArith.ll b/test/CodeGen/X86/WidenArith.ll +index cdd1a2818b2..cc5fcba6670 100644 +--- a/test/CodeGen/X86/WidenArith.ll ++++ b/test/CodeGen/X86/WidenArith.ll +@@ -9,8 +9,8 @@ define <8 x i32> @test(<8 x float> %a, <8 x float> %b) { + ; CHECK-NEXT: vsubps %ymm2, %ymm1, %ymm3 + ; CHECK-NEXT: vcmpltps %ymm1, %ymm0, %ymm0 + ; CHECK-NEXT: vcmpltps %ymm3, %ymm2, %ymm1 +-; CHECK-NEXT: vandps {{.*}}(%rip), %ymm1, %ymm1 + ; CHECK-NEXT: vandps %ymm1, %ymm0, %ymm0 ++; CHECK-NEXT: vandps {{.*}}(%rip), %ymm0, %ymm0 + ; CHECK-NEXT: retq + %c1 = fadd <8 x float> %a, %b + %b1 = fmul <8 x float> %b, %a +diff --git a/test/CodeGen/X86/merge-consecutive-loads-256.ll b/test/CodeGen/X86/merge-consecutive-loads-256.ll +index 8c2e9372900..dc268d9bdf8 100644 +--- a/test/CodeGen/X86/merge-consecutive-loads-256.ll ++++ b/test/CodeGen/X86/merge-consecutive-loads-256.ll +@@ -547,29 +547,17 @@ define <16 x i16> @merge_16i16_i16_0uu3uuuuuuuuCuEF(i16* %ptr) nounwind uwtable + } + + define <16 x i16> @merge_16i16_i16_0uu3zzuuuuuzCuEF(i16* %ptr) nounwind uwtable noinline ssp { +-; AVX1-LABEL: merge_16i16_i16_0uu3zzuuuuuzCuEF: +-; AVX1: # BB#0: +-; AVX1-NEXT: vmovaps {{.*#+}} ymm0 = [65535,0,0,65535,0,0,0,0,0,0,0,0,65535,0,65535,65535] +-; AVX1-NEXT: vandps (%rdi), %ymm0, %ymm0 +-; AVX1-NEXT: retq +-; +-; AVX2-LABEL: merge_16i16_i16_0uu3zzuuuuuzCuEF: +-; AVX2: # BB#0: +-; AVX2-NEXT: vmovups (%rdi), %ymm0 +-; AVX2-NEXT: vandps {{.*}}(%rip), %ymm0, %ymm0 +-; AVX2-NEXT: retq +-; +-; AVX512F-LABEL: merge_16i16_i16_0uu3zzuuuuuzCuEF: +-; AVX512F: # BB#0: +-; AVX512F-NEXT: vmovups (%rdi), %ymm0 +-; AVX512F-NEXT: vandps {{.*}}(%rip), %ymm0, %ymm0 +-; AVX512F-NEXT: retq ++; AVX-LABEL: merge_16i16_i16_0uu3zzuuuuuzCuEF: ++; AVX: # BB#0: ++; AVX-NEXT: vmovups (%rdi), %ymm0 ++; AVX-NEXT: vandps {{.*}}(%rip), %ymm0, %ymm0 ++; AVX-NEXT: retq + ; + ; X32-AVX-LABEL: merge_16i16_i16_0uu3zzuuuuuzCuEF: + ; X32-AVX: # BB#0: + ; X32-AVX-NEXT: movl {{[0-9]+}}(%esp), %eax +-; X32-AVX-NEXT: vmovaps {{.*#+}} ymm0 = [65535,0,0,65535,0,0,0,0,0,0,0,0,65535,0,65535,65535] +-; X32-AVX-NEXT: vandps (%eax), %ymm0, %ymm0 ++; X32-AVX-NEXT: vmovups (%eax), %ymm0 ++; X32-AVX-NEXT: vandps {{\.LCPI.*}}, %ymm0, %ymm0 + ; X32-AVX-NEXT: retl + %ptr0 = getelementptr inbounds i16, i16* %ptr, i64 0 + %ptr3 = getelementptr inbounds i16, i16* %ptr, i64 3 +diff --git a/test/CodeGen/X86/v8i1-masks.ll b/test/CodeGen/X86/v8i1-masks.ll +index 0135832ad92..d5c31506e98 100644 +--- a/test/CodeGen/X86/v8i1-masks.ll ++++ b/test/CodeGen/X86/v8i1-masks.ll +@@ -13,8 +13,8 @@ define void @and_masks(<8 x float>* %a, <8 x float>* %b, <8 x float>* %c) nounwi + ; X32-NEXT: vcmpltps %ymm0, %ymm1, %ymm1 + ; X32-NEXT: vmovups (%eax), %ymm2 + ; X32-NEXT: vcmpltps %ymm0, %ymm2, %ymm0 +-; X32-NEXT: vandps LCPI0_0, %ymm1, %ymm1 + ; X32-NEXT: vandps %ymm1, %ymm0, %ymm0 ++; X32-NEXT: vandps LCPI0_0, %ymm0, %ymm0 + ; X32-NEXT: vmovaps %ymm0, (%eax) + ; X32-NEXT: vzeroupper + ; X32-NEXT: retl +@@ -26,8 +26,8 @@ define void @and_masks(<8 x float>* %a, <8 x float>* %b, <8 x float>* %c) nounwi + ; X64-NEXT: vcmpltps %ymm0, %ymm1, %ymm1 + ; X64-NEXT: vmovups (%rdx), %ymm2 + ; X64-NEXT: vcmpltps %ymm0, %ymm2, %ymm0 +-; X64-NEXT: vandps {{.*}}(%rip), %ymm1, %ymm1 + ; X64-NEXT: vandps %ymm1, %ymm0, %ymm0 ++; X64-NEXT: vandps {{.*}}(%rip), %ymm0, %ymm0 + ; X64-NEXT: vmovaps %ymm0, (%rax) + ; X64-NEXT: vzeroupper + ; X64-NEXT: retq +diff --git a/test/CodeGen/X86/vec_int_to_fp.ll b/test/CodeGen/X86/vec_int_to_fp.ll +index 5d8f91385c7..8ea7243664a 100644 +--- a/test/CodeGen/X86/vec_int_to_fp.ll ++++ b/test/CodeGen/X86/vec_int_to_fp.ll +@@ -1694,15 +1694,15 @@ define <8 x float> @uitofp_8i32_to_8f32(<8 x i32> %a) { + ; + ; AVX1-LABEL: uitofp_8i32_to_8f32: + ; AVX1: # BB#0: +-; AVX1-NEXT: vandps {{.*}}(%rip), %ymm0, %ymm1 ++; AVX1-NEXT: vpsrld $16, %xmm0, %xmm1 ++; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm2 ++; AVX1-NEXT: vpsrld $16, %xmm2, %xmm2 ++; AVX1-NEXT: vinsertf128 $1, %xmm2, %ymm1, %ymm1 + ; AVX1-NEXT: vcvtdq2ps %ymm1, %ymm1 +-; AVX1-NEXT: vpsrld $16, %xmm0, %xmm2 +-; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm0 +-; AVX1-NEXT: vpsrld $16, %xmm0, %xmm0 +-; AVX1-NEXT: vinsertf128 $1, %xmm0, %ymm2, %ymm0 ++; AVX1-NEXT: vmulps {{.*}}(%rip), %ymm1, %ymm1 ++; AVX1-NEXT: vandps {{.*}}(%rip), %ymm0, %ymm0 + ; AVX1-NEXT: vcvtdq2ps %ymm0, %ymm0 +-; AVX1-NEXT: vmulps {{.*}}(%rip), %ymm0, %ymm0 +-; AVX1-NEXT: vaddps %ymm1, %ymm0, %ymm0 ++; AVX1-NEXT: vaddps %ymm0, %ymm1, %ymm0 + ; AVX1-NEXT: retq + ; + ; AVX2-LABEL: uitofp_8i32_to_8f32: +@@ -3372,16 +3372,16 @@ define <8 x float> @uitofp_load_8i32_to_8f32(<8 x i32> *%a) { + ; + ; AVX1-LABEL: uitofp_load_8i32_to_8f32: + ; AVX1: # BB#0: +-; AVX1-NEXT: vmovaps (%rdi), %ymm0 +-; AVX1-NEXT: vandps {{.*}}(%rip), %ymm0, %ymm1 ++; AVX1-NEXT: vmovdqa (%rdi), %ymm0 ++; AVX1-NEXT: vpsrld $16, %xmm0, %xmm1 ++; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm2 ++; AVX1-NEXT: vpsrld $16, %xmm2, %xmm2 ++; AVX1-NEXT: vinsertf128 $1, %xmm2, %ymm1, %ymm1 + ; AVX1-NEXT: vcvtdq2ps %ymm1, %ymm1 +-; AVX1-NEXT: vpsrld $16, %xmm0, %xmm2 +-; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm0 +-; AVX1-NEXT: vpsrld $16, %xmm0, %xmm0 +-; AVX1-NEXT: vinsertf128 $1, %xmm0, %ymm2, %ymm0 ++; AVX1-NEXT: vmulps {{.*}}(%rip), %ymm1, %ymm1 ++; AVX1-NEXT: vandps {{.*}}(%rip), %ymm0, %ymm0 + ; AVX1-NEXT: vcvtdq2ps %ymm0, %ymm0 +-; AVX1-NEXT: vmulps {{.*}}(%rip), %ymm0, %ymm0 +-; AVX1-NEXT: vaddps %ymm1, %ymm0, %ymm0 ++; AVX1-NEXT: vaddps %ymm0, %ymm1, %ymm0 + ; AVX1-NEXT: retq + ; + ; AVX2-LABEL: uitofp_load_8i32_to_8f32: +diff --git a/test/CodeGen/X86/vec_uint_to_fp-fastmath.ll b/test/CodeGen/X86/vec_uint_to_fp-fastmath.ll +index c0e02bd1599..cb8e2096585 100644 +--- a/test/CodeGen/X86/vec_uint_to_fp-fastmath.ll ++++ b/test/CodeGen/X86/vec_uint_to_fp-fastmath.ll +@@ -78,18 +78,18 @@ define <4 x float> @test_uitofp_v4i32_to_v4f32(<4 x i32> %arg) { + ret <4 x float> %tmp + } + +-; AVX: [[MASKCSTADDR_v8:.LCPI[0-9_]+]]: +-; AVX-NEXT: .long 65535 # 0xffff +-; AVX-NEXT: .long 65535 # 0xffff +-; AVX-NEXT: .long 65535 # 0xffff +-; AVX-NEXT: .long 65535 # 0xffff +- + ; AVX: [[FPMASKCSTADDR_v8:.LCPI[0-9_]+]]: + ; AVX-NEXT: .long 1199570944 # float 65536 + ; AVX-NEXT: .long 1199570944 # float 65536 + ; AVX-NEXT: .long 1199570944 # float 65536 + ; AVX-NEXT: .long 1199570944 # float 65536 + ++; AVX: [[MASKCSTADDR_v8:.LCPI[0-9_]+]]: ++; AVX-NEXT: .long 65535 # 0xffff ++; AVX-NEXT: .long 65535 # 0xffff ++; AVX-NEXT: .long 65535 # 0xffff ++; AVX-NEXT: .long 65535 # 0xffff ++ + ; AVX2: [[FPMASKCSTADDR_v8:.LCPI[0-9_]+]]: + ; AVX2-NEXT: .long 1199570944 # float 65536 + +@@ -119,15 +119,15 @@ define <8 x float> @test_uitofp_v8i32_to_v8f32(<8 x i32> %arg) { + ; + ; AVX-LABEL: test_uitofp_v8i32_to_v8f32: + ; AVX: # BB#0: +-; AVX-NEXT: vandps [[MASKCSTADDR_v8]](%rip), %ymm0, %ymm1 ++; AVX-NEXT: vpsrld $16, %xmm0, %xmm1 ++; AVX-NEXT: vextractf128 $1, %ymm0, %xmm2 ++; AVX-NEXT: vpsrld $16, %xmm2, %xmm2 ++; AVX-NEXT: vinsertf128 $1, %xmm2, %ymm1, %ymm1 + ; AVX-NEXT: vcvtdq2ps %ymm1, %ymm1 +-; AVX-NEXT: vpsrld $16, %xmm0, %xmm2 +-; AVX-NEXT: vextractf128 $1, %ymm0, %xmm0 +-; AVX-NEXT: vpsrld $16, %xmm0, %xmm0 +-; AVX-NEXT: vinsertf128 $1, %xmm0, %ymm2, %ymm0 ++; AVX-NEXT: vmulps [[FPMASKCSTADDR_v8]](%rip), %ymm1, %ymm1 ++; AVX-NEXT: vandps [[MASKCSTADDR_v8]](%rip), %ymm0, %ymm0 + ; AVX-NEXT: vcvtdq2ps %ymm0, %ymm0 +-; AVX-NEXT: vmulps [[FPMASKCSTADDR_v8]](%rip), %ymm0, %ymm0 +-; AVX-NEXT: vaddps %ymm1, %ymm0, %ymm0 ++; AVX-NEXT: vaddps %ymm0, %ymm1, %ymm0 + ; AVX-NEXT: retq + ; + ; AVX2-LABEL: test_uitofp_v8i32_to_v8f32: +-- +2.11.0 + diff --git a/deps/patches/llvm-PR278321.patch b/deps/patches/llvm-PR278321.patch new file mode 100644 index 0000000000000..709436536f01a --- /dev/null +++ b/deps/patches/llvm-PR278321.patch @@ -0,0 +1,1409 @@ +From a4ec9b3d6c2c53eb463284db0aa54158fad32701 Mon Sep 17 00:00:00 2001 +From: Marina Yatsina +Date: Thu, 11 Aug 2016 07:32:08 +0000 +Subject: [PATCH 4/5] Avoid false dependencies of undef machine operands + +This patch helps avoid false dependencies on undef registers by updating the machine instructions' undef operand to use a register that the instruction is truly dependent on, or use a register with clearance higher than Pref. + +Pseudo example: + +loop: +xmm0 = ... +xmm1 = vcvtsi2sdl eax, xmm0 +... = inst xmm0 +jmp loop + +In this example, selecting xmm0 as the undef register creates false dependency between loop iterations. +This false dependency cannot be solved by inserting an xor before vcvtsi2sdl because xmm0 is alive at the point of the vcvtsi2sdl instruction. +Selecting a different register instead of xmm0, especially a register that is not used in the loop, will eliminate this problem. + +Differential Revision: https://reviews.llvm.org/D22466 + +git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@278321 91177308-0d34-0410-b5e6-96231b3b80d8 +--- + lib/CodeGen/ExecutionDepsFix.cpp | 53 ++++ + lib/Target/X86/X86InstrInfo.cpp | 2 +- + test/CodeGen/X86/break-false-dep.ll | 72 ++++- + test/CodeGen/X86/copy-propagation.ll | 3 +- + test/CodeGen/X86/half.ll | 2 +- + test/CodeGen/X86/vec_int_to_fp.ll | 579 ++++++++++++++++++++--------------- + 6 files changed, 467 insertions(+), 244 deletions(-) + +diff --git a/lib/CodeGen/ExecutionDepsFix.cpp b/lib/CodeGen/ExecutionDepsFix.cpp +index 1fe5f459b69..5f91db9251c 100644 +--- a/lib/CodeGen/ExecutionDepsFix.cpp ++++ b/lib/CodeGen/ExecutionDepsFix.cpp +@@ -203,6 +203,8 @@ private: + void processDefs(MachineInstr*, bool Kill); + void visitSoftInstr(MachineInstr*, unsigned mask); + void visitHardInstr(MachineInstr*, unsigned domain); ++ void pickBestRegisterForUndef(MachineInstr *MI, unsigned OpIdx, ++ unsigned Pref); + bool shouldBreakDependence(MachineInstr*, unsigned OpIdx, unsigned Pref); + void processUndefReads(MachineBasicBlock*); + }; +@@ -473,6 +475,56 @@ void ExeDepsFix::visitInstr(MachineInstr *MI) { + processDefs(MI, !DomP.first); + } + ++/// \brief Helps avoid false dependencies on undef registers by updating the ++/// machine instructions' undef operand to use a register that the instruction ++/// is truly dependent on, or use a register with clearance higher than Pref. ++void ExeDepsFix::pickBestRegisterForUndef(MachineInstr *MI, unsigned OpIdx, ++ unsigned Pref) { ++ MachineOperand &MO = MI->getOperand(OpIdx); ++ assert(MO.isUndef() && "Expected undef machine operand"); ++ ++ unsigned OriginalReg = MO.getReg(); ++ ++ // Update only undef operands that are mapped to one register. ++ if (AliasMap[OriginalReg].size() != 1) ++ return; ++ ++ // Get the undef operand's register class ++ const TargetRegisterClass *OpRC = ++ TII->getRegClass(MI->getDesc(), OpIdx, TRI, *MF); ++ ++ // If the instruction has a true dependency, we can hide the false depdency ++ // behind it. ++ for (MachineOperand &CurrMO : MI->operands()) { ++ if (!CurrMO.isReg() || CurrMO.isDef() || CurrMO.isUndef() || ++ !OpRC->contains(CurrMO.getReg())) ++ continue; ++ // We found a true dependency - replace the undef register with the true ++ // dependency. ++ MO.setReg(CurrMO.getReg()); ++ return; ++ } ++ ++ // Go over all registers in the register class and find the register with ++ // max clearance or clearance higher than Pref. ++ unsigned MaxClearance = 0; ++ unsigned MaxClearanceReg = OriginalReg; ++ for (unsigned rx = 0; rx < OpRC->getNumRegs(); ++rx) { ++ unsigned Clearance = CurInstr - LiveRegs[rx].Def; ++ if (Clearance <= MaxClearance) ++ continue; ++ MaxClearance = Clearance; ++ MaxClearanceReg = OpRC->getRegister(rx); ++ ++ if (MaxClearance > Pref) ++ break; ++ } ++ ++ // Update the operand if we found a register with better clearance. ++ if (MaxClearanceReg != OriginalReg) ++ MO.setReg(MaxClearanceReg); ++} ++ + /// \brief Return true to if it makes sense to break dependence on a partial def + /// or undef use. + bool ExeDepsFix::shouldBreakDependence(MachineInstr *MI, unsigned OpIdx, +@@ -510,6 +562,7 @@ void ExeDepsFix::processDefs(MachineInstr *MI, bool Kill) { + unsigned OpNum; + unsigned Pref = TII->getUndefRegClearance(*MI, OpNum, TRI); + if (Pref) { ++ pickBestRegisterForUndef(MI, OpNum, Pref); + if (shouldBreakDependence(MI, OpNum, Pref)) + UndefReads.push_back(std::make_pair(MI, OpNum)); + } +diff --git a/lib/Target/X86/X86InstrInfo.cpp b/lib/Target/X86/X86InstrInfo.cpp +index 5f0aab9ddc6..9bfe25973ae 100644 +--- a/lib/Target/X86/X86InstrInfo.cpp ++++ b/lib/Target/X86/X86InstrInfo.cpp +@@ -68,7 +68,7 @@ static cl::opt + UndefRegClearance("undef-reg-clearance", + cl::desc("How many idle instructions we would like before " + "certain undef register reads"), +- cl::init(64), cl::Hidden); ++ cl::init(128), cl::Hidden); + + enum { + // Select which memory operand is being unfolded. +diff --git a/test/CodeGen/X86/break-false-dep.ll b/test/CodeGen/X86/break-false-dep.ll +index a7cda499dab..4c5e747f9ca 100644 +--- a/test/CodeGen/X86/break-false-dep.ll ++++ b/test/CodeGen/X86/break-false-dep.ll +@@ -126,6 +126,7 @@ loop: + %i = phi i64 [ 1, %entry ], [ %inc, %loop ] + %s1 = phi i64 [ %vx, %entry ], [ %s2, %loop ] + %fi = sitofp i64 %i to double ++ tail call void asm sideeffect "", "~{xmm0},~{xmm1},~{xmm2},~{xmm3},~{xmm4},~{xmm5},~{xmm6},~{xmm7},~{xmm8},~{xmm9},~{xmm10},~{xmm11},~{xmm12},~{xmm13},~{xmm14},~{xmm15},~{dirflag},~{fpsr},~{flags}"() + %vy = load double, double* %y + %fipy = fadd double %fi, %vy + %iipy = fptosi double %fipy to i64 +@@ -174,6 +175,7 @@ for.body3: + store double %mul11, double* %arrayidx13, align 8 + %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1 + %exitcond = icmp eq i64 %indvars.iv.next, 1024 ++ tail call void asm sideeffect "", "~{xmm0},~{xmm1},~{xmm2},~{xmm3},~{xmm4},~{xmm5},~{xmm6},~{xmm7},~{xmm8},~{xmm9},~{xmm10},~{xmm11},~{xmm12},~{xmm13},~{xmm14},~{xmm15},~{dirflag},~{fpsr},~{flags}"() + br i1 %exitcond, label %for.inc14, label %for.body3 + + for.inc14: ; preds = %for.body3 +@@ -193,7 +195,7 @@ for.end16: ; preds = %for.inc14 + ;SSE-NEXT: movsd [[XMM0]], + ;AVX-LABEL:@loopdep3 + ;AVX: vxorps [[XMM0:%xmm[0-9]+]], [[XMM0]] +-;AVX-NEXT: vcvtsi2sdl {{.*}}, [[XMM0]], [[XMM0]] ++;AVX-NEXT: vcvtsi2sdl {{.*}}, [[XMM0]], {{%xmm[0-9]+}} + ;AVX-NEXT: vmulsd {{.*}}, [[XMM0]], [[XMM0]] + ;AVX-NEXT: vmulsd {{.*}}, [[XMM0]], [[XMM0]] + ;AVX-NEXT: vmulsd {{.*}}, [[XMM0]], [[XMM0]] +@@ -202,10 +204,76 @@ for.end16: ; preds = %for.inc14 + + define double @inlineasmdep(i64 %arg) { + top: +- tail call void asm sideeffect "", "~{xmm0},~{dirflag},~{fpsr},~{flags}"() ++ tail call void asm sideeffect "", "~{xmm0},~{xmm1},~{xmm2},~{xmm3},~{dirflag},~{fpsr},~{flags}"() ++ tail call void asm sideeffect "", "~{xmm4},~{xmm5},~{xmm6},~{xmm7},~{dirflag},~{fpsr},~{flags}"() ++ tail call void asm sideeffect "", "~{xmm8},~{xmm9},~{xmm10},~{xmm11},~{dirflag},~{fpsr},~{flags}"() ++ tail call void asm sideeffect "", "~{xmm12},~{xmm13},~{xmm14},~{xmm15},~{dirflag},~{fpsr},~{flags}"() + %tmp1 = sitofp i64 %arg to double + ret double %tmp1 + ;AVX-LABEL:@inlineasmdep + ;AVX: vxorps [[XMM0:%xmm[0-9]+]], [[XMM0]], [[XMM0]] + ;AVX-NEXT: vcvtsi2sdq {{.*}}, [[XMM0]], {{%xmm[0-9]+}} + } ++ ++; Make sure we are making a smart choice regarding undef registers and ++; hiding the false dependency behind a true dependency ++define double @truedeps(float %arg) { ++top: ++ tail call void asm sideeffect "", "~{xmm6},~{dirflag},~{fpsr},~{flags}"() ++ tail call void asm sideeffect "", "~{xmm0},~{xmm1},~{xmm2},~{xmm3},~{dirflag},~{fpsr},~{flags}"() ++ tail call void asm sideeffect "", "~{xmm4},~{xmm5},~{xmm7},~{dirflag},~{fpsr},~{flags}"() ++ tail call void asm sideeffect "", "~{xmm8},~{xmm9},~{xmm10},~{xmm11},~{dirflag},~{fpsr},~{flags}"() ++ tail call void asm sideeffect "", "~{xmm12},~{xmm13},~{xmm14},~{xmm15},~{dirflag},~{fpsr},~{flags}"() ++ %tmp1 = fpext float %arg to double ++ ret double %tmp1 ++;AVX-LABEL:@truedeps ++;AVX-NOT: vxorps ++;AVX: vcvtss2sd [[XMM0:%xmm[0-9]+]], [[XMM0]], {{%xmm[0-9]+}} ++} ++ ++; Make sure we are making a smart choice regarding undef registers and ++; choosing the register with the highest clearence ++define double @clearence(i64 %arg) { ++top: ++ tail call void asm sideeffect "", "~{xmm6},~{dirflag},~{fpsr},~{flags}"() ++ tail call void asm sideeffect "", "~{xmm0},~{xmm1},~{xmm2},~{xmm3},~{dirflag},~{fpsr},~{flags}"() ++ tail call void asm sideeffect "", "~{xmm4},~{xmm5},~{xmm7},~{dirflag},~{fpsr},~{flags}"() ++ tail call void asm sideeffect "", "~{xmm8},~{xmm9},~{xmm10},~{xmm11},~{dirflag},~{fpsr},~{flags}"() ++ tail call void asm sideeffect "", "~{xmm12},~{xmm13},~{xmm14},~{xmm15},~{dirflag},~{fpsr},~{flags}"() ++ %tmp1 = sitofp i64 %arg to double ++ ret double %tmp1 ++;AVX-LABEL:@clearence ++;AVX: vxorps [[XMM6:%xmm6]], [[XMM6]], [[XMM6]] ++;AVX-NEXT: vcvtsi2sdq {{.*}}, [[XMM6]], {{%xmm[0-9]+}} ++} ++ ++; Make sure we are making a smart choice regarding undef registers in order to ++; avoid a cyclic dependence on a write to the same register in a previous ++; iteration, especially when we cannot zero out the undef register because it ++; is alive. ++define i64 @loopclearence(i64* nocapture %x, double* nocapture %y) nounwind { ++entry: ++ %vx = load i64, i64* %x ++ br label %loop ++loop: ++ %i = phi i64 [ 1, %entry ], [ %inc, %loop ] ++ %s1 = phi i64 [ %vx, %entry ], [ %s2, %loop ] ++ %fi = sitofp i64 %i to double ++ tail call void asm sideeffect "", "~{xmm0},~{xmm1},~{xmm2},~{xmm3},~{dirflag},~{fpsr},~{flags}"() ++ tail call void asm sideeffect "", "~{xmm8},~{xmm9},~{xmm10},~{xmm11},~{dirflag},~{fpsr},~{flags}"() ++ tail call void asm sideeffect "", "~{xmm12},~{xmm13},~{xmm14},~{xmm15},~{dirflag},~{fpsr},~{flags}"() ++ %vy = load double, double* %y ++ %fipy = fadd double %fi, %vy ++ %iipy = fptosi double %fipy to i64 ++ %s2 = add i64 %s1, %iipy ++ %inc = add nsw i64 %i, 1 ++ %exitcond = icmp eq i64 %inc, 156250000 ++ br i1 %exitcond, label %ret, label %loop ++ret: ++ ret i64 %s2 ++;AVX-LABEL:@loopclearence ++;Registers 4-7 are not used and therefore one of them should be chosen ++;AVX-NOT: {{%xmm[4-7]}} ++;AVX: vcvtsi2sdq {{.*}}, [[XMM4_7:%xmm[4-7]]], {{%xmm[0-9]+}} ++;AVX-NOT: [[XMM4_7]] ++} +diff --git a/test/CodeGen/X86/copy-propagation.ll b/test/CodeGen/X86/copy-propagation.ll +index 19421a06fa8..dac46c17382 100644 +--- a/test/CodeGen/X86/copy-propagation.ll ++++ b/test/CodeGen/X86/copy-propagation.ll +@@ -26,7 +26,7 @@ target triple = "x86_64-pc-win32-elf" + ; Copy the result in a temporary. + ; Note: Technically the regalloc could have been smarter and this move not required, + ; which would have hidden the bug. +-; CHECK-NEXT: vmovapd %xmm0, [[TMP:%xmm[0-9]+]] ++; CHECK: vmovapd %xmm0, [[TMP:%xmm[0-9]+]] + ; Crush xmm0. + ; CHECK-NEXT: vxorps %xmm0, %xmm0, %xmm0 + ; CHECK: movl $339772768, %e[[INDIRECT_CALL2:[a-z]+]] +@@ -37,6 +37,7 @@ target triple = "x86_64-pc-win32-elf" + define double @foo(i64 %arg) { + top: + %tmp = call double inttoptr (i64 339752784 to double (double, double)*)(double 1.000000e+00, double 0.000000e+00) ++ tail call void asm sideeffect "", "x,~{xmm1},~{xmm2},~{xmm3},~{xmm4},~{xmm5},~{xmm6},~{xmm7},~{xmm8},~{xmm9},~{xmm10},~{xmm11},~{xmm12},~{xmm13},~{xmm14},~{xmm15},~{dirflag},~{fpsr},~{flags}"(double %tmp) + %tmp1 = sitofp i64 %arg to double + call void inttoptr (i64 339772768 to void (double, double)*)(double %tmp, double %tmp1) + %tmp3 = fadd double %tmp1, %tmp +diff --git a/test/CodeGen/X86/half.ll b/test/CodeGen/X86/half.ll +index 717ddbfa6fd..739bb146e3a 100644 +--- a/test/CodeGen/X86/half.ll ++++ b/test/CodeGen/X86/half.ll +@@ -299,7 +299,7 @@ define half @test_f80trunc_nodagcombine() #0 { + ; CHECK-F16C-NEXT: movswl (%rsi), %eax + ; CHECK-F16C-NEXT: vmovd %eax, %xmm0 + ; CHECK-F16C-NEXT: vcvtph2ps %xmm0, %xmm0 +-; CHECK-F16C-NEXT: vcvtsi2ssl %edi, %xmm0, %xmm1 ++; CHECK-F16C-NEXT: vcvtsi2ssl %edi, %xmm1, %xmm1 + ; CHECK-F16C-NEXT: vcvtps2ph $4, %xmm1, %xmm1 + ; CHECK-F16C-NEXT: vcvtph2ps %xmm1, %xmm1 + ; CHECK-F16C-NEXT: vaddss %xmm1, %xmm0, %xmm0 +diff --git a/test/CodeGen/X86/vec_int_to_fp.ll b/test/CodeGen/X86/vec_int_to_fp.ll +index 8ea7243664a..bb0a93dc848 100644 +--- a/test/CodeGen/X86/vec_int_to_fp.ll ++++ b/test/CodeGen/X86/vec_int_to_fp.ll +@@ -27,10 +27,9 @@ define <2 x double> @sitofp_2i64_to_2f64(<2 x i64> %a) { + ; AVX-LABEL: sitofp_2i64_to_2f64: + ; AVX: # BB#0: + ; AVX-NEXT: vpextrq $1, %xmm0, %rax +-; AVX-NEXT: vcvtsi2sdq %rax, %xmm0, %xmm1 ++; AVX-NEXT: vcvtsi2sdq %rax, %xmm1, %xmm1 + ; AVX-NEXT: vmovq %xmm0, %rax +-; AVX-NEXT: vxorps %xmm0, %xmm0, %xmm0 +-; AVX-NEXT: vcvtsi2sdq %rax, %xmm0, %xmm0 ++; AVX-NEXT: vcvtsi2sdq %rax, %xmm2, %xmm0 + ; AVX-NEXT: vunpcklpd {{.*#+}} xmm0 = xmm0[0],xmm1[0] + ; AVX-NEXT: retq + %cvt = sitofp <2 x i64> %a to <2 x double> +@@ -188,15 +187,14 @@ define <4 x double> @sitofp_4i64_to_4f64(<4 x i64> %a) { + ; AVX1: # BB#0: + ; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm1 + ; AVX1-NEXT: vpextrq $1, %xmm1, %rax +-; AVX1-NEXT: vcvtsi2sdq %rax, %xmm0, %xmm2 ++; AVX1-NEXT: vcvtsi2sdq %rax, %xmm2, %xmm2 + ; AVX1-NEXT: vmovq %xmm1, %rax +-; AVX1-NEXT: vcvtsi2sdq %rax, %xmm0, %xmm1 ++; AVX1-NEXT: vcvtsi2sdq %rax, %xmm3, %xmm1 + ; AVX1-NEXT: vunpcklpd {{.*#+}} xmm1 = xmm1[0],xmm2[0] + ; AVX1-NEXT: vpextrq $1, %xmm0, %rax +-; AVX1-NEXT: vcvtsi2sdq %rax, %xmm0, %xmm2 ++; AVX1-NEXT: vcvtsi2sdq %rax, %xmm3, %xmm2 + ; AVX1-NEXT: vmovq %xmm0, %rax +-; AVX1-NEXT: vxorps %xmm0, %xmm0, %xmm0 +-; AVX1-NEXT: vcvtsi2sdq %rax, %xmm0, %xmm0 ++; AVX1-NEXT: vcvtsi2sdq %rax, %xmm3, %xmm0 + ; AVX1-NEXT: vunpcklpd {{.*#+}} xmm0 = xmm0[0],xmm2[0] + ; AVX1-NEXT: vinsertf128 $1, %xmm1, %ymm0, %ymm0 + ; AVX1-NEXT: retq +@@ -205,18 +203,33 @@ define <4 x double> @sitofp_4i64_to_4f64(<4 x i64> %a) { + ; AVX2: # BB#0: + ; AVX2-NEXT: vextracti128 $1, %ymm0, %xmm1 + ; AVX2-NEXT: vpextrq $1, %xmm1, %rax +-; AVX2-NEXT: vcvtsi2sdq %rax, %xmm0, %xmm2 ++; AVX2-NEXT: vcvtsi2sdq %rax, %xmm2, %xmm2 + ; AVX2-NEXT: vmovq %xmm1, %rax +-; AVX2-NEXT: vcvtsi2sdq %rax, %xmm0, %xmm1 ++; AVX2-NEXT: vcvtsi2sdq %rax, %xmm3, %xmm1 + ; AVX2-NEXT: vunpcklpd {{.*#+}} xmm1 = xmm1[0],xmm2[0] + ; AVX2-NEXT: vpextrq $1, %xmm0, %rax +-; AVX2-NEXT: vcvtsi2sdq %rax, %xmm0, %xmm2 ++; AVX2-NEXT: vcvtsi2sdq %rax, %xmm3, %xmm2 + ; AVX2-NEXT: vmovq %xmm0, %rax +-; AVX2-NEXT: vxorps %xmm0, %xmm0, %xmm0 +-; AVX2-NEXT: vcvtsi2sdq %rax, %xmm0, %xmm0 ++; AVX2-NEXT: vcvtsi2sdq %rax, %xmm3, %xmm0 + ; AVX2-NEXT: vunpcklpd {{.*#+}} xmm0 = xmm0[0],xmm2[0] + ; AVX2-NEXT: vinsertf128 $1, %xmm1, %ymm0, %ymm0 + ; AVX2-NEXT: retq ++; ++; AVX512-LABEL: sitofp_4i64_to_4f64: ++; AVX512: # BB#0: ++; AVX512-NEXT: vextracti32x4 $1, %ymm0, %xmm1 ++; AVX512-NEXT: vpextrq $1, %xmm1, %rax ++; AVX512-NEXT: vcvtsi2sdq %rax, %xmm2, %xmm2 ++; AVX512-NEXT: vmovq %xmm1, %rax ++; AVX512-NEXT: vcvtsi2sdq %rax, %xmm3, %xmm1 ++; AVX512-NEXT: vunpcklpd {{.*#+}} xmm1 = xmm1[0],xmm2[0] ++; AVX512-NEXT: vpextrq $1, %xmm0, %rax ++; AVX512-NEXT: vcvtsi2sdq %rax, %xmm3, %xmm2 ++; AVX512-NEXT: vmovq %xmm0, %rax ++; AVX512-NEXT: vcvtsi2sdq %rax, %xmm3, %xmm0 ++; AVX512-NEXT: vunpcklpd {{.*#+}} xmm0 = xmm0[0],xmm2[0] ++; AVX512-NEXT: vinsertf32x4 $1, %xmm1, %ymm0, %ymm0 ++; AVX512-NEXT: retq + %cvt = sitofp <4 x i64> %a to <4 x double> + ret <4 x double> %cvt + } +@@ -803,12 +816,11 @@ define <4 x float> @sitofp_2i64_to_4f32(<2 x i64> %a) { + ; AVX-LABEL: sitofp_2i64_to_4f32: + ; AVX: # BB#0: + ; AVX-NEXT: vpextrq $1, %xmm0, %rax +-; AVX-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm1 ++; AVX-NEXT: vcvtsi2ssq %rax, %xmm1, %xmm1 + ; AVX-NEXT: vmovq %xmm0, %rax +-; AVX-NEXT: vxorps %xmm0, %xmm0, %xmm0 +-; AVX-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm0 ++; AVX-NEXT: vcvtsi2ssq %rax, %xmm2, %xmm0 + ; AVX-NEXT: vinsertps {{.*#+}} xmm0 = xmm0[0],xmm1[0],xmm0[2,3] +-; AVX-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm1 ++; AVX-NEXT: vcvtsi2ssq %rax, %xmm2, %xmm1 + ; AVX-NEXT: vinsertps {{.*#+}} xmm0 = xmm0[0,1],xmm1[0],xmm0[3] + ; AVX-NEXT: vinsertps {{.*#+}} xmm0 = xmm0[0,1,2],xmm1[0] + ; AVX-NEXT: retq +@@ -836,12 +848,11 @@ define <4 x float> @sitofp_4i64_to_4f32_undef(<2 x i64> %a) { + ; AVX-LABEL: sitofp_4i64_to_4f32_undef: + ; AVX: # BB#0: + ; AVX-NEXT: vpextrq $1, %xmm0, %rax +-; AVX-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm1 ++; AVX-NEXT: vcvtsi2ssq %rax, %xmm1, %xmm1 + ; AVX-NEXT: vmovq %xmm0, %rax +-; AVX-NEXT: vxorps %xmm0, %xmm0, %xmm0 +-; AVX-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm0 ++; AVX-NEXT: vcvtsi2ssq %rax, %xmm2, %xmm0 + ; AVX-NEXT: vinsertps {{.*#+}} xmm0 = xmm0[0],xmm1[0],xmm0[2,3] +-; AVX-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm1 ++; AVX-NEXT: vcvtsi2ssq %rax, %xmm2, %xmm1 + ; AVX-NEXT: vinsertps {{.*#+}} xmm0 = xmm0[0,1],xmm1[0],xmm0[3] + ; AVX-NEXT: vinsertps {{.*#+}} xmm0 = xmm0[0,1,2],xmm1[0] + ; AVX-NEXT: retq +@@ -988,17 +999,16 @@ define <4 x float> @sitofp_4i64_to_4f32(<4 x i64> %a) { + ; AVX1-LABEL: sitofp_4i64_to_4f32: + ; AVX1: # BB#0: + ; AVX1-NEXT: vpextrq $1, %xmm0, %rax +-; AVX1-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm1 ++; AVX1-NEXT: vcvtsi2ssq %rax, %xmm1, %xmm1 + ; AVX1-NEXT: vmovq %xmm0, %rax +-; AVX1-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm2 ++; AVX1-NEXT: vcvtsi2ssq %rax, %xmm2, %xmm2 + ; AVX1-NEXT: vinsertps {{.*#+}} xmm1 = xmm2[0],xmm1[0],xmm2[2,3] + ; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm0 + ; AVX1-NEXT: vmovq %xmm0, %rax +-; AVX1-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm2 ++; AVX1-NEXT: vcvtsi2ssq %rax, %xmm3, %xmm2 + ; AVX1-NEXT: vinsertps {{.*#+}} xmm1 = xmm1[0,1],xmm2[0],xmm1[3] + ; AVX1-NEXT: vpextrq $1, %xmm0, %rax +-; AVX1-NEXT: vxorps %xmm0, %xmm0, %xmm0 +-; AVX1-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm0 ++; AVX1-NEXT: vcvtsi2ssq %rax, %xmm3, %xmm0 + ; AVX1-NEXT: vinsertps {{.*#+}} xmm0 = xmm1[0,1,2],xmm0[0] + ; AVX1-NEXT: vzeroupper + ; AVX1-NEXT: retq +@@ -1006,20 +1016,35 @@ define <4 x float> @sitofp_4i64_to_4f32(<4 x i64> %a) { + ; AVX2-LABEL: sitofp_4i64_to_4f32: + ; AVX2: # BB#0: + ; AVX2-NEXT: vpextrq $1, %xmm0, %rax +-; AVX2-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm1 ++; AVX2-NEXT: vcvtsi2ssq %rax, %xmm1, %xmm1 + ; AVX2-NEXT: vmovq %xmm0, %rax +-; AVX2-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm2 ++; AVX2-NEXT: vcvtsi2ssq %rax, %xmm2, %xmm2 + ; AVX2-NEXT: vinsertps {{.*#+}} xmm1 = xmm2[0],xmm1[0],xmm2[2,3] + ; AVX2-NEXT: vextracti128 $1, %ymm0, %xmm0 + ; AVX2-NEXT: vmovq %xmm0, %rax +-; AVX2-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm2 ++; AVX2-NEXT: vcvtsi2ssq %rax, %xmm3, %xmm2 + ; AVX2-NEXT: vinsertps {{.*#+}} xmm1 = xmm1[0,1],xmm2[0],xmm1[3] + ; AVX2-NEXT: vpextrq $1, %xmm0, %rax +-; AVX2-NEXT: vxorps %xmm0, %xmm0, %xmm0 +-; AVX2-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm0 ++; AVX2-NEXT: vcvtsi2ssq %rax, %xmm3, %xmm0 + ; AVX2-NEXT: vinsertps {{.*#+}} xmm0 = xmm1[0,1,2],xmm0[0] + ; AVX2-NEXT: vzeroupper + ; AVX2-NEXT: retq ++; ++; AVX512-LABEL: sitofp_4i64_to_4f32: ++; AVX512: # BB#0: ++; AVX512-NEXT: vpextrq $1, %xmm0, %rax ++; AVX512-NEXT: vcvtsi2ssq %rax, %xmm1, %xmm1 ++; AVX512-NEXT: vmovq %xmm0, %rax ++; AVX512-NEXT: vcvtsi2ssq %rax, %xmm2, %xmm2 ++; AVX512-NEXT: vinsertps {{.*#+}} xmm1 = xmm2[0],xmm1[0],xmm2[2,3] ++; AVX512-NEXT: vextracti32x4 $1, %ymm0, %xmm0 ++; AVX512-NEXT: vmovq %xmm0, %rax ++; AVX512-NEXT: vcvtsi2ssq %rax, %xmm3, %xmm2 ++; AVX512-NEXT: vinsertps {{.*#+}} xmm1 = xmm1[0,1],xmm2[0],xmm1[3] ++; AVX512-NEXT: vpextrq $1, %xmm0, %rax ++; AVX512-NEXT: vcvtsi2ssq %rax, %xmm3, %xmm0 ++; AVX512-NEXT: vinsertps {{.*#+}} xmm0 = xmm1[0,1,2],xmm0[0] ++; AVX512-NEXT: retq + %cvt = sitofp <4 x i64> %a to <4 x float> + ret <4 x float> %cvt + } +@@ -1181,48 +1206,58 @@ define <4 x float> @uitofp_2i64_to_4f32(<2 x i64> %a) { + ; SSE-NEXT: unpcklps {{.*#+}} xmm0 = xmm0[0],xmm1[0],xmm0[1],xmm1[1] + ; SSE-NEXT: retq + ; +-; AVX-LABEL: uitofp_2i64_to_4f32: +-; AVX: # BB#0: +-; AVX-NEXT: vpextrq $1, %xmm0, %rax +-; AVX-NEXT: movl %eax, %ecx +-; AVX-NEXT: andl $1, %ecx +-; AVX-NEXT: testq %rax, %rax +-; AVX-NEXT: js .LBB38_1 +-; AVX-NEXT: # BB#2: +-; AVX-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm1 +-; AVX-NEXT: jmp .LBB38_3 +-; AVX-NEXT: .LBB38_1: +-; AVX-NEXT: shrq %rax +-; AVX-NEXT: orq %rax, %rcx +-; AVX-NEXT: vcvtsi2ssq %rcx, %xmm0, %xmm1 +-; AVX-NEXT: vaddss %xmm1, %xmm1, %xmm1 +-; AVX-NEXT: .LBB38_3: +-; AVX-NEXT: vmovq %xmm0, %rax +-; AVX-NEXT: movl %eax, %ecx +-; AVX-NEXT: andl $1, %ecx +-; AVX-NEXT: testq %rax, %rax +-; AVX-NEXT: js .LBB38_4 +-; AVX-NEXT: # BB#5: +-; AVX-NEXT: vxorps %xmm0, %xmm0, %xmm0 +-; AVX-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm0 +-; AVX-NEXT: jmp .LBB38_6 +-; AVX-NEXT: .LBB38_4: +-; AVX-NEXT: shrq %rax +-; AVX-NEXT: orq %rax, %rcx +-; AVX-NEXT: vxorps %xmm0, %xmm0, %xmm0 +-; AVX-NEXT: vcvtsi2ssq %rcx, %xmm0, %xmm0 +-; AVX-NEXT: vaddss %xmm0, %xmm0, %xmm0 +-; AVX-NEXT: .LBB38_6: +-; AVX-NEXT: vinsertps {{.*#+}} xmm0 = xmm0[0],xmm1[0],xmm0[2,3] +-; AVX-NEXT: vxorps %xmm1, %xmm1, %xmm1 +-; AVX-NEXT: testq %rax, %rax +-; AVX-NEXT: js .LBB38_8 +-; AVX-NEXT: # BB#7: +-; AVX-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm1 +-; AVX-NEXT: .LBB38_8: +-; AVX-NEXT: vinsertps {{.*#+}} xmm0 = xmm0[0,1],xmm1[0],xmm0[3] +-; AVX-NEXT: vinsertps {{.*#+}} xmm0 = xmm0[0,1,2],xmm1[0] +-; AVX-NEXT: retq ++; AVX1-LABEL: uitofp_2i64_to_4f32: ++; AVX1: # BB#0: ++; AVX1-NEXT: vpextrq $1, %xmm0, %rax ++; AVX1-NEXT: movl %eax, %ecx ++; AVX1-NEXT: andl $1, %ecx ++; AVX1-NEXT: testq %rax, %rax ++; AVX1-NEXT: js .LBB38_1 ++; AVX1-NEXT: # BB#2: ++; AVX1-NEXT: vcvtsi2ssq %rax, %xmm1, %xmm1 ++; AVX1-NEXT: jmp .LBB38_3 ++; AVX1-NEXT: .LBB38_1: ++; AVX1-NEXT: shrq %rax ++; AVX1-NEXT: orq %rax, %rcx ++; AVX1-NEXT: vcvtsi2ssq %rcx, %xmm1, %xmm1 ++; AVX1-NEXT: vaddss %xmm1, %xmm1, %xmm1 ++; AVX1-NEXT: .LBB38_3: ++; AVX1-NEXT: vmovq %xmm0, %rax ++; AVX1-NEXT: movl %eax, %ecx ++; AVX1-NEXT: andl $1, %ecx ++; AVX1-NEXT: testq %rax, %rax ++; AVX1-NEXT: js .LBB38_4 ++; AVX1-NEXT: # BB#5: ++; AVX1-NEXT: vcvtsi2ssq %rax, %xmm2, %xmm0 ++; AVX1-NEXT: jmp .LBB38_6 ++; AVX1-NEXT: .LBB38_4: ++; AVX1-NEXT: shrq %rax ++; AVX1-NEXT: orq %rax, %rcx ++; AVX1-NEXT: vcvtsi2ssq %rcx, %xmm2, %xmm0 ++; AVX1-NEXT: vaddss %xmm0, %xmm0, %xmm0 ++; AVX1-NEXT: .LBB38_6: ++; AVX1-NEXT: vinsertps {{.*#+}} xmm0 = xmm0[0],xmm1[0],xmm0[2,3] ++; AVX1-NEXT: vxorps %xmm1, %xmm1, %xmm1 ++; AVX1-NEXT: testq %rax, %rax ++; AVX1-NEXT: js .LBB38_8 ++; AVX1-NEXT: # BB#7: ++; AVX1-NEXT: vcvtsi2ssq %rax, %xmm2, %xmm1 ++; AVX1-NEXT: .LBB38_8: ++; AVX1-NEXT: vinsertps {{.*#+}} xmm0 = xmm0[0,1],xmm1[0],xmm0[3] ++; AVX1-NEXT: vinsertps {{.*#+}} xmm0 = xmm0[0,1,2],xmm1[0] ++; AVX1-NEXT: retq ++; ++; AVX512-LABEL: uitofp_2i64_to_4f32: ++; AVX512: # BB#0: ++; AVX512-NEXT: vpextrq $1, %xmm0, %rax ++; AVX512-NEXT: vcvtusi2ssq %rax, %xmm0, %xmm1 ++; AVX512-NEXT: vmovq %xmm0, %rax ++; AVX512-NEXT: vcvtusi2ssq %rax, %xmm0, %xmm0 ++; AVX512-NEXT: vinsertps {{.*#+}} xmm0 = xmm0[0],xmm1[0],xmm0[2,3] ++; AVX512-NEXT: vcvtusi2ssq %rax, %xmm0, %xmm1 ++; AVX512-NEXT: vinsertps {{.*#+}} xmm0 = xmm0[0,1],xmm1[0],xmm0[3] ++; AVX512-NEXT: vinsertps {{.*#+}} xmm0 = xmm0[0,1,2],xmm1[0] ++; AVX512-NEXT: retq + %cvt = uitofp <2 x i64> %a to <2 x float> + %ext = shufflevector <2 x float> %cvt, <2 x float> undef, <4 x i32> + ret <4 x float> %ext +@@ -1277,48 +1312,58 @@ define <4 x float> @uitofp_4i64_to_4f32_undef(<2 x i64> %a) { + ; SSE-NEXT: unpcklps {{.*#+}} xmm0 = xmm0[0],xmm1[0],xmm0[1],xmm1[1] + ; SSE-NEXT: retq + ; +-; AVX-LABEL: uitofp_4i64_to_4f32_undef: +-; AVX: # BB#0: +-; AVX-NEXT: vpextrq $1, %xmm0, %rax +-; AVX-NEXT: movl %eax, %ecx +-; AVX-NEXT: andl $1, %ecx +-; AVX-NEXT: testq %rax, %rax +-; AVX-NEXT: js .LBB39_1 +-; AVX-NEXT: # BB#2: +-; AVX-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm1 +-; AVX-NEXT: jmp .LBB39_3 +-; AVX-NEXT: .LBB39_1: +-; AVX-NEXT: shrq %rax +-; AVX-NEXT: orq %rax, %rcx +-; AVX-NEXT: vcvtsi2ssq %rcx, %xmm0, %xmm1 +-; AVX-NEXT: vaddss %xmm1, %xmm1, %xmm1 +-; AVX-NEXT: .LBB39_3: +-; AVX-NEXT: vmovq %xmm0, %rax +-; AVX-NEXT: movl %eax, %ecx +-; AVX-NEXT: andl $1, %ecx +-; AVX-NEXT: testq %rax, %rax +-; AVX-NEXT: js .LBB39_4 +-; AVX-NEXT: # BB#5: +-; AVX-NEXT: vxorps %xmm0, %xmm0, %xmm0 +-; AVX-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm0 +-; AVX-NEXT: jmp .LBB39_6 +-; AVX-NEXT: .LBB39_4: +-; AVX-NEXT: shrq %rax +-; AVX-NEXT: orq %rax, %rcx +-; AVX-NEXT: vxorps %xmm0, %xmm0, %xmm0 +-; AVX-NEXT: vcvtsi2ssq %rcx, %xmm0, %xmm0 +-; AVX-NEXT: vaddss %xmm0, %xmm0, %xmm0 +-; AVX-NEXT: .LBB39_6: +-; AVX-NEXT: vinsertps {{.*#+}} xmm0 = xmm0[0],xmm1[0],xmm0[2,3] +-; AVX-NEXT: vxorps %xmm1, %xmm1, %xmm1 +-; AVX-NEXT: testq %rax, %rax +-; AVX-NEXT: js .LBB39_8 +-; AVX-NEXT: # BB#7: +-; AVX-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm1 +-; AVX-NEXT: .LBB39_8: +-; AVX-NEXT: vinsertps {{.*#+}} xmm0 = xmm0[0,1],xmm1[0],xmm0[3] +-; AVX-NEXT: vinsertps {{.*#+}} xmm0 = xmm0[0,1,2],xmm1[0] +-; AVX-NEXT: retq ++; AVX1-LABEL: uitofp_4i64_to_4f32_undef: ++; AVX1: # BB#0: ++; AVX1-NEXT: vpextrq $1, %xmm0, %rax ++; AVX1-NEXT: movl %eax, %ecx ++; AVX1-NEXT: andl $1, %ecx ++; AVX1-NEXT: testq %rax, %rax ++; AVX1-NEXT: js .LBB39_1 ++; AVX1-NEXT: # BB#2: ++; AVX1-NEXT: vcvtsi2ssq %rax, %xmm1, %xmm1 ++; AVX1-NEXT: jmp .LBB39_3 ++; AVX1-NEXT: .LBB39_1: ++; AVX1-NEXT: shrq %rax ++; AVX1-NEXT: orq %rax, %rcx ++; AVX1-NEXT: vcvtsi2ssq %rcx, %xmm1, %xmm1 ++; AVX1-NEXT: vaddss %xmm1, %xmm1, %xmm1 ++; AVX1-NEXT: .LBB39_3: ++; AVX1-NEXT: vmovq %xmm0, %rax ++; AVX1-NEXT: movl %eax, %ecx ++; AVX1-NEXT: andl $1, %ecx ++; AVX1-NEXT: testq %rax, %rax ++; AVX1-NEXT: js .LBB39_4 ++; AVX1-NEXT: # BB#5: ++; AVX1-NEXT: vcvtsi2ssq %rax, %xmm2, %xmm0 ++; AVX1-NEXT: jmp .LBB39_6 ++; AVX1-NEXT: .LBB39_4: ++; AVX1-NEXT: shrq %rax ++; AVX1-NEXT: orq %rax, %rcx ++; AVX1-NEXT: vcvtsi2ssq %rcx, %xmm2, %xmm0 ++; AVX1-NEXT: vaddss %xmm0, %xmm0, %xmm0 ++; AVX1-NEXT: .LBB39_6: ++; AVX1-NEXT: vinsertps {{.*#+}} xmm0 = xmm0[0],xmm1[0],xmm0[2,3] ++; AVX1-NEXT: vxorps %xmm1, %xmm1, %xmm1 ++; AVX1-NEXT: testq %rax, %rax ++; AVX1-NEXT: js .LBB39_8 ++; AVX1-NEXT: # BB#7: ++; AVX1-NEXT: vcvtsi2ssq %rax, %xmm2, %xmm1 ++; AVX1-NEXT: .LBB39_8: ++; AVX1-NEXT: vinsertps {{.*#+}} xmm0 = xmm0[0,1],xmm1[0],xmm0[3] ++; AVX1-NEXT: vinsertps {{.*#+}} xmm0 = xmm0[0,1,2],xmm1[0] ++; AVX1-NEXT: retq ++; ++; AVX512-LABEL: uitofp_4i64_to_4f32_undef: ++; AVX512: # BB#0: ++; AVX512-NEXT: vpextrq $1, %xmm0, %rax ++; AVX512-NEXT: vcvtusi2ssq %rax, %xmm0, %xmm1 ++; AVX512-NEXT: vmovq %xmm0, %rax ++; AVX512-NEXT: vcvtusi2ssq %rax, %xmm0, %xmm0 ++; AVX512-NEXT: vinsertps {{.*#+}} xmm0 = xmm0[0],xmm1[0],xmm0[2,3] ++; AVX512-NEXT: vcvtusi2ssq %rax, %xmm0, %xmm1 ++; AVX512-NEXT: vinsertps {{.*#+}} xmm0 = xmm0[0,1],xmm1[0],xmm0[3] ++; AVX512-NEXT: vinsertps {{.*#+}} xmm0 = xmm0[0,1,2],xmm1[0] ++; AVX512-NEXT: retq + %ext = shufflevector <2 x i64> %a, <2 x i64> undef, <4 x i32> + %cvt = uitofp <4 x i64> %ext to <4 x float> + ret <4 x float> %cvt +@@ -1539,12 +1584,12 @@ define <4 x float> @uitofp_4i64_to_4f32(<4 x i64> %a) { + ; AVX1-NEXT: testq %rax, %rax + ; AVX1-NEXT: js .LBB45_1 + ; AVX1-NEXT: # BB#2: +-; AVX1-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm1 ++; AVX1-NEXT: vcvtsi2ssq %rax, %xmm1, %xmm1 + ; AVX1-NEXT: jmp .LBB45_3 + ; AVX1-NEXT: .LBB45_1: + ; AVX1-NEXT: shrq %rax + ; AVX1-NEXT: orq %rax, %rcx +-; AVX1-NEXT: vcvtsi2ssq %rcx, %xmm0, %xmm1 ++; AVX1-NEXT: vcvtsi2ssq %rcx, %xmm1, %xmm1 + ; AVX1-NEXT: vaddss %xmm1, %xmm1, %xmm1 + ; AVX1-NEXT: .LBB45_3: + ; AVX1-NEXT: vmovq %xmm0, %rax +@@ -1553,12 +1598,12 @@ define <4 x float> @uitofp_4i64_to_4f32(<4 x i64> %a) { + ; AVX1-NEXT: testq %rax, %rax + ; AVX1-NEXT: js .LBB45_4 + ; AVX1-NEXT: # BB#5: +-; AVX1-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm2 ++; AVX1-NEXT: vcvtsi2ssq %rax, %xmm2, %xmm2 + ; AVX1-NEXT: jmp .LBB45_6 + ; AVX1-NEXT: .LBB45_4: + ; AVX1-NEXT: shrq %rax + ; AVX1-NEXT: orq %rax, %rcx +-; AVX1-NEXT: vcvtsi2ssq %rcx, %xmm0, %xmm2 ++; AVX1-NEXT: vcvtsi2ssq %rcx, %xmm2, %xmm2 + ; AVX1-NEXT: vaddss %xmm2, %xmm2, %xmm2 + ; AVX1-NEXT: .LBB45_6: + ; AVX1-NEXT: vinsertps {{.*#+}} xmm1 = xmm2[0],xmm1[0],xmm2[2,3] +@@ -1569,12 +1614,12 @@ define <4 x float> @uitofp_4i64_to_4f32(<4 x i64> %a) { + ; AVX1-NEXT: testq %rax, %rax + ; AVX1-NEXT: js .LBB45_7 + ; AVX1-NEXT: # BB#8: +-; AVX1-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm2 ++; AVX1-NEXT: vcvtsi2ssq %rax, %xmm3, %xmm2 + ; AVX1-NEXT: jmp .LBB45_9 + ; AVX1-NEXT: .LBB45_7: + ; AVX1-NEXT: shrq %rax + ; AVX1-NEXT: orq %rax, %rcx +-; AVX1-NEXT: vcvtsi2ssq %rcx, %xmm0, %xmm2 ++; AVX1-NEXT: vcvtsi2ssq %rcx, %xmm3, %xmm2 + ; AVX1-NEXT: vaddss %xmm2, %xmm2, %xmm2 + ; AVX1-NEXT: .LBB45_9: + ; AVX1-NEXT: vinsertps {{.*#+}} xmm1 = xmm1[0,1],xmm2[0],xmm1[3] +@@ -1584,16 +1629,14 @@ define <4 x float> @uitofp_4i64_to_4f32(<4 x i64> %a) { + ; AVX1-NEXT: testq %rax, %rax + ; AVX1-NEXT: js .LBB45_10 + ; AVX1-NEXT: # BB#11: +-; AVX1-NEXT: vxorps %xmm0, %xmm0, %xmm0 +-; AVX1-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm0 ++; AVX1-NEXT: vcvtsi2ssq %rax, %xmm3, %xmm0 + ; AVX1-NEXT: vinsertps {{.*#+}} xmm0 = xmm1[0,1,2],xmm0[0] + ; AVX1-NEXT: vzeroupper + ; AVX1-NEXT: retq + ; AVX1-NEXT: .LBB45_10: + ; AVX1-NEXT: shrq %rax + ; AVX1-NEXT: orq %rax, %rcx +-; AVX1-NEXT: vxorps %xmm0, %xmm0, %xmm0 +-; AVX1-NEXT: vcvtsi2ssq %rcx, %xmm0, %xmm0 ++; AVX1-NEXT: vcvtsi2ssq %rcx, %xmm3, %xmm0 + ; AVX1-NEXT: vaddss %xmm0, %xmm0, %xmm0 + ; AVX1-NEXT: vinsertps {{.*#+}} xmm0 = xmm1[0,1,2],xmm0[0] + ; AVX1-NEXT: vzeroupper +@@ -1607,12 +1650,12 @@ define <4 x float> @uitofp_4i64_to_4f32(<4 x i64> %a) { + ; AVX2-NEXT: testq %rax, %rax + ; AVX2-NEXT: js .LBB45_1 + ; AVX2-NEXT: # BB#2: +-; AVX2-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm1 ++; AVX2-NEXT: vcvtsi2ssq %rax, %xmm1, %xmm1 + ; AVX2-NEXT: jmp .LBB45_3 + ; AVX2-NEXT: .LBB45_1: + ; AVX2-NEXT: shrq %rax + ; AVX2-NEXT: orq %rax, %rcx +-; AVX2-NEXT: vcvtsi2ssq %rcx, %xmm0, %xmm1 ++; AVX2-NEXT: vcvtsi2ssq %rcx, %xmm1, %xmm1 + ; AVX2-NEXT: vaddss %xmm1, %xmm1, %xmm1 + ; AVX2-NEXT: .LBB45_3: + ; AVX2-NEXT: vmovq %xmm0, %rax +@@ -1621,12 +1664,12 @@ define <4 x float> @uitofp_4i64_to_4f32(<4 x i64> %a) { + ; AVX2-NEXT: testq %rax, %rax + ; AVX2-NEXT: js .LBB45_4 + ; AVX2-NEXT: # BB#5: +-; AVX2-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm2 ++; AVX2-NEXT: vcvtsi2ssq %rax, %xmm2, %xmm2 + ; AVX2-NEXT: jmp .LBB45_6 + ; AVX2-NEXT: .LBB45_4: + ; AVX2-NEXT: shrq %rax + ; AVX2-NEXT: orq %rax, %rcx +-; AVX2-NEXT: vcvtsi2ssq %rcx, %xmm0, %xmm2 ++; AVX2-NEXT: vcvtsi2ssq %rcx, %xmm2, %xmm2 + ; AVX2-NEXT: vaddss %xmm2, %xmm2, %xmm2 + ; AVX2-NEXT: .LBB45_6: + ; AVX2-NEXT: vinsertps {{.*#+}} xmm1 = xmm2[0],xmm1[0],xmm2[2,3] +@@ -1637,12 +1680,12 @@ define <4 x float> @uitofp_4i64_to_4f32(<4 x i64> %a) { + ; AVX2-NEXT: testq %rax, %rax + ; AVX2-NEXT: js .LBB45_7 + ; AVX2-NEXT: # BB#8: +-; AVX2-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm2 ++; AVX2-NEXT: vcvtsi2ssq %rax, %xmm3, %xmm2 + ; AVX2-NEXT: jmp .LBB45_9 + ; AVX2-NEXT: .LBB45_7: + ; AVX2-NEXT: shrq %rax + ; AVX2-NEXT: orq %rax, %rcx +-; AVX2-NEXT: vcvtsi2ssq %rcx, %xmm0, %xmm2 ++; AVX2-NEXT: vcvtsi2ssq %rcx, %xmm3, %xmm2 + ; AVX2-NEXT: vaddss %xmm2, %xmm2, %xmm2 + ; AVX2-NEXT: .LBB45_9: + ; AVX2-NEXT: vinsertps {{.*#+}} xmm1 = xmm1[0,1],xmm2[0],xmm1[3] +@@ -1652,16 +1695,14 @@ define <4 x float> @uitofp_4i64_to_4f32(<4 x i64> %a) { + ; AVX2-NEXT: testq %rax, %rax + ; AVX2-NEXT: js .LBB45_10 + ; AVX2-NEXT: # BB#11: +-; AVX2-NEXT: vxorps %xmm0, %xmm0, %xmm0 +-; AVX2-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm0 ++; AVX2-NEXT: vcvtsi2ssq %rax, %xmm3, %xmm0 + ; AVX2-NEXT: vinsertps {{.*#+}} xmm0 = xmm1[0,1,2],xmm0[0] + ; AVX2-NEXT: vzeroupper + ; AVX2-NEXT: retq + ; AVX2-NEXT: .LBB45_10: + ; AVX2-NEXT: shrq %rax + ; AVX2-NEXT: orq %rax, %rcx +-; AVX2-NEXT: vxorps %xmm0, %xmm0, %xmm0 +-; AVX2-NEXT: vcvtsi2ssq %rcx, %xmm0, %xmm0 ++; AVX2-NEXT: vcvtsi2ssq %rcx, %xmm3, %xmm0 + ; AVX2-NEXT: vaddss %xmm0, %xmm0, %xmm0 + ; AVX2-NEXT: vinsertps {{.*#+}} xmm0 = xmm1[0,1,2],xmm0[0] + ; AVX2-NEXT: vzeroupper +@@ -1831,16 +1872,25 @@ define <2 x double> @sitofp_load_2i64_to_2f64(<2 x i64> *%a) { + ; SSE-NEXT: unpcklpd {{.*#+}} xmm0 = xmm0[0],xmm1[0] + ; SSE-NEXT: retq + ; +-; AVX-LABEL: sitofp_load_2i64_to_2f64: +-; AVX: # BB#0: +-; AVX-NEXT: vmovdqa (%rdi), %xmm0 +-; AVX-NEXT: vpextrq $1, %xmm0, %rax +-; AVX-NEXT: vcvtsi2sdq %rax, %xmm0, %xmm1 +-; AVX-NEXT: vmovq %xmm0, %rax +-; AVX-NEXT: vxorps %xmm0, %xmm0, %xmm0 +-; AVX-NEXT: vcvtsi2sdq %rax, %xmm0, %xmm0 +-; AVX-NEXT: vunpcklpd {{.*#+}} xmm0 = xmm0[0],xmm1[0] +-; AVX-NEXT: retq ++; AVX1-LABEL: sitofp_load_2i64_to_2f64: ++; AVX1: # BB#0: ++; AVX1-NEXT: vmovdqa (%rdi), %xmm0 ++; AVX1-NEXT: vpextrq $1, %xmm0, %rax ++; AVX1-NEXT: vcvtsi2sdq %rax, %xmm1, %xmm1 ++; AVX1-NEXT: vmovq %xmm0, %rax ++; AVX1-NEXT: vcvtsi2sdq %rax, %xmm2, %xmm0 ++; AVX1-NEXT: vunpcklpd {{.*#+}} xmm0 = xmm0[0],xmm1[0] ++; AVX1-NEXT: retq ++; ++; AVX512-LABEL: sitofp_load_2i64_to_2f64: ++; AVX512: # BB#0: ++; AVX512-NEXT: vmovdqa64 (%rdi), %xmm0 ++; AVX512-NEXT: vpextrq $1, %xmm0, %rax ++; AVX512-NEXT: vcvtsi2sdq %rax, %xmm1, %xmm1 ++; AVX512-NEXT: vmovq %xmm0, %rax ++; AVX512-NEXT: vcvtsi2sdq %rax, %xmm2, %xmm0 ++; AVX512-NEXT: vunpcklpd {{.*#+}} xmm0 = xmm0[0],xmm1[0] ++; AVX512-NEXT: retq + %ld = load <2 x i64>, <2 x i64> *%a + %cvt = sitofp <2 x i64> %ld to <2 x double> + ret <2 x double> %cvt +@@ -1930,15 +1980,14 @@ define <4 x double> @sitofp_load_4i64_to_4f64(<4 x i64> *%a) { + ; AVX1-NEXT: vmovaps (%rdi), %ymm0 + ; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm1 + ; AVX1-NEXT: vpextrq $1, %xmm1, %rax +-; AVX1-NEXT: vcvtsi2sdq %rax, %xmm0, %xmm2 ++; AVX1-NEXT: vcvtsi2sdq %rax, %xmm2, %xmm2 + ; AVX1-NEXT: vmovq %xmm1, %rax +-; AVX1-NEXT: vcvtsi2sdq %rax, %xmm0, %xmm1 ++; AVX1-NEXT: vcvtsi2sdq %rax, %xmm3, %xmm1 + ; AVX1-NEXT: vunpcklpd {{.*#+}} xmm1 = xmm1[0],xmm2[0] + ; AVX1-NEXT: vpextrq $1, %xmm0, %rax +-; AVX1-NEXT: vcvtsi2sdq %rax, %xmm0, %xmm2 ++; AVX1-NEXT: vcvtsi2sdq %rax, %xmm3, %xmm2 + ; AVX1-NEXT: vmovq %xmm0, %rax +-; AVX1-NEXT: vxorps %xmm0, %xmm0, %xmm0 +-; AVX1-NEXT: vcvtsi2sdq %rax, %xmm0, %xmm0 ++; AVX1-NEXT: vcvtsi2sdq %rax, %xmm3, %xmm0 + ; AVX1-NEXT: vunpcklpd {{.*#+}} xmm0 = xmm0[0],xmm2[0] + ; AVX1-NEXT: vinsertf128 $1, %xmm1, %ymm0, %ymm0 + ; AVX1-NEXT: retq +@@ -1948,18 +1997,34 @@ define <4 x double> @sitofp_load_4i64_to_4f64(<4 x i64> *%a) { + ; AVX2-NEXT: vmovdqa (%rdi), %ymm0 + ; AVX2-NEXT: vextracti128 $1, %ymm0, %xmm1 + ; AVX2-NEXT: vpextrq $1, %xmm1, %rax +-; AVX2-NEXT: vcvtsi2sdq %rax, %xmm0, %xmm2 ++; AVX2-NEXT: vcvtsi2sdq %rax, %xmm2, %xmm2 + ; AVX2-NEXT: vmovq %xmm1, %rax +-; AVX2-NEXT: vcvtsi2sdq %rax, %xmm0, %xmm1 ++; AVX2-NEXT: vcvtsi2sdq %rax, %xmm3, %xmm1 + ; AVX2-NEXT: vunpcklpd {{.*#+}} xmm1 = xmm1[0],xmm2[0] + ; AVX2-NEXT: vpextrq $1, %xmm0, %rax +-; AVX2-NEXT: vcvtsi2sdq %rax, %xmm0, %xmm2 ++; AVX2-NEXT: vcvtsi2sdq %rax, %xmm3, %xmm2 + ; AVX2-NEXT: vmovq %xmm0, %rax +-; AVX2-NEXT: vxorps %xmm0, %xmm0, %xmm0 +-; AVX2-NEXT: vcvtsi2sdq %rax, %xmm0, %xmm0 ++; AVX2-NEXT: vcvtsi2sdq %rax, %xmm3, %xmm0 + ; AVX2-NEXT: vunpcklpd {{.*#+}} xmm0 = xmm0[0],xmm2[0] + ; AVX2-NEXT: vinsertf128 $1, %xmm1, %ymm0, %ymm0 + ; AVX2-NEXT: retq ++; ++; AVX512-LABEL: sitofp_load_4i64_to_4f64: ++; AVX512: # BB#0: ++; AVX512-NEXT: vmovdqa64 (%rdi), %ymm0 ++; AVX512-NEXT: vextracti32x4 $1, %ymm0, %xmm1 ++; AVX512-NEXT: vpextrq $1, %xmm1, %rax ++; AVX512-NEXT: vcvtsi2sdq %rax, %xmm2, %xmm2 ++; AVX512-NEXT: vmovq %xmm1, %rax ++; AVX512-NEXT: vcvtsi2sdq %rax, %xmm3, %xmm1 ++; AVX512-NEXT: vunpcklpd {{.*#+}} xmm1 = xmm1[0],xmm2[0] ++; AVX512-NEXT: vpextrq $1, %xmm0, %rax ++; AVX512-NEXT: vcvtsi2sdq %rax, %xmm3, %xmm2 ++; AVX512-NEXT: vmovq %xmm0, %rax ++; AVX512-NEXT: vcvtsi2sdq %rax, %xmm3, %xmm0 ++; AVX512-NEXT: vunpcklpd {{.*#+}} xmm0 = xmm0[0],xmm2[0] ++; AVX512-NEXT: vinsertf32x4 $1, %xmm1, %ymm0, %ymm0 ++; AVX512-NEXT: retq + %ld = load <4 x i64>, <4 x i64> *%a + %cvt = sitofp <4 x i64> %ld to <4 x double> + ret <4 x double> %cvt +@@ -2365,17 +2430,16 @@ define <4 x float> @sitofp_load_4i64_to_4f32(<4 x i64> *%a) { + ; AVX1: # BB#0: + ; AVX1-NEXT: vmovdqa (%rdi), %ymm0 + ; AVX1-NEXT: vpextrq $1, %xmm0, %rax +-; AVX1-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm1 ++; AVX1-NEXT: vcvtsi2ssq %rax, %xmm1, %xmm1 + ; AVX1-NEXT: vmovq %xmm0, %rax +-; AVX1-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm2 ++; AVX1-NEXT: vcvtsi2ssq %rax, %xmm2, %xmm2 + ; AVX1-NEXT: vinsertps {{.*#+}} xmm1 = xmm2[0],xmm1[0],xmm2[2,3] + ; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm0 + ; AVX1-NEXT: vmovq %xmm0, %rax +-; AVX1-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm2 ++; AVX1-NEXT: vcvtsi2ssq %rax, %xmm3, %xmm2 + ; AVX1-NEXT: vinsertps {{.*#+}} xmm1 = xmm1[0,1],xmm2[0],xmm1[3] + ; AVX1-NEXT: vpextrq $1, %xmm0, %rax +-; AVX1-NEXT: vxorps %xmm0, %xmm0, %xmm0 +-; AVX1-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm0 ++; AVX1-NEXT: vcvtsi2ssq %rax, %xmm3, %xmm0 + ; AVX1-NEXT: vinsertps {{.*#+}} xmm0 = xmm1[0,1,2],xmm0[0] + ; AVX1-NEXT: vzeroupper + ; AVX1-NEXT: retq +@@ -2384,20 +2448,36 @@ define <4 x float> @sitofp_load_4i64_to_4f32(<4 x i64> *%a) { + ; AVX2: # BB#0: + ; AVX2-NEXT: vmovdqa (%rdi), %ymm0 + ; AVX2-NEXT: vpextrq $1, %xmm0, %rax +-; AVX2-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm1 ++; AVX2-NEXT: vcvtsi2ssq %rax, %xmm1, %xmm1 + ; AVX2-NEXT: vmovq %xmm0, %rax +-; AVX2-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm2 ++; AVX2-NEXT: vcvtsi2ssq %rax, %xmm2, %xmm2 + ; AVX2-NEXT: vinsertps {{.*#+}} xmm1 = xmm2[0],xmm1[0],xmm2[2,3] + ; AVX2-NEXT: vextracti128 $1, %ymm0, %xmm0 + ; AVX2-NEXT: vmovq %xmm0, %rax +-; AVX2-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm2 ++; AVX2-NEXT: vcvtsi2ssq %rax, %xmm3, %xmm2 + ; AVX2-NEXT: vinsertps {{.*#+}} xmm1 = xmm1[0,1],xmm2[0],xmm1[3] + ; AVX2-NEXT: vpextrq $1, %xmm0, %rax +-; AVX2-NEXT: vxorps %xmm0, %xmm0, %xmm0 +-; AVX2-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm0 ++; AVX2-NEXT: vcvtsi2ssq %rax, %xmm3, %xmm0 + ; AVX2-NEXT: vinsertps {{.*#+}} xmm0 = xmm1[0,1,2],xmm0[0] + ; AVX2-NEXT: vzeroupper + ; AVX2-NEXT: retq ++; ++; AVX512-LABEL: sitofp_load_4i64_to_4f32: ++; AVX512: # BB#0: ++; AVX512-NEXT: vmovdqa64 (%rdi), %ymm0 ++; AVX512-NEXT: vpextrq $1, %xmm0, %rax ++; AVX512-NEXT: vcvtsi2ssq %rax, %xmm1, %xmm1 ++; AVX512-NEXT: vmovq %xmm0, %rax ++; AVX512-NEXT: vcvtsi2ssq %rax, %xmm2, %xmm2 ++; AVX512-NEXT: vinsertps {{.*#+}} xmm1 = xmm2[0],xmm1[0],xmm2[2,3] ++; AVX512-NEXT: vextracti32x4 $1, %ymm0, %xmm0 ++; AVX512-NEXT: vmovq %xmm0, %rax ++; AVX512-NEXT: vcvtsi2ssq %rax, %xmm3, %xmm2 ++; AVX512-NEXT: vinsertps {{.*#+}} xmm1 = xmm1[0,1],xmm2[0],xmm1[3] ++; AVX512-NEXT: vpextrq $1, %xmm0, %rax ++; AVX512-NEXT: vcvtsi2ssq %rax, %xmm3, %xmm0 ++; AVX512-NEXT: vinsertps {{.*#+}} xmm0 = xmm1[0,1,2],xmm0[0] ++; AVX512-NEXT: retq + %ld = load <4 x i64>, <4 x i64> *%a + %cvt = sitofp <4 x i64> %ld to <4 x float> + ret <4 x float> %cvt +@@ -2503,29 +2583,28 @@ define <8 x float> @sitofp_load_8i64_to_8f32(<8 x i64> *%a) { + ; AVX1-NEXT: vmovdqa (%rdi), %ymm0 + ; AVX1-NEXT: vmovdqa 32(%rdi), %ymm1 + ; AVX1-NEXT: vpextrq $1, %xmm1, %rax +-; AVX1-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm2 ++; AVX1-NEXT: vcvtsi2ssq %rax, %xmm2, %xmm2 + ; AVX1-NEXT: vmovq %xmm1, %rax +-; AVX1-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm3 ++; AVX1-NEXT: vcvtsi2ssq %rax, %xmm3, %xmm3 + ; AVX1-NEXT: vinsertps {{.*#+}} xmm2 = xmm3[0],xmm2[0],xmm3[2,3] + ; AVX1-NEXT: vextractf128 $1, %ymm1, %xmm1 + ; AVX1-NEXT: vmovq %xmm1, %rax +-; AVX1-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm3 ++; AVX1-NEXT: vcvtsi2ssq %rax, %xmm4, %xmm3 + ; AVX1-NEXT: vinsertps {{.*#+}} xmm2 = xmm2[0,1],xmm3[0],xmm2[3] + ; AVX1-NEXT: vpextrq $1, %xmm1, %rax +-; AVX1-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm1 ++; AVX1-NEXT: vcvtsi2ssq %rax, %xmm4, %xmm1 + ; AVX1-NEXT: vinsertps {{.*#+}} xmm1 = xmm2[0,1,2],xmm1[0] + ; AVX1-NEXT: vpextrq $1, %xmm0, %rax +-; AVX1-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm2 ++; AVX1-NEXT: vcvtsi2ssq %rax, %xmm4, %xmm2 + ; AVX1-NEXT: vmovq %xmm0, %rax +-; AVX1-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm3 ++; AVX1-NEXT: vcvtsi2ssq %rax, %xmm4, %xmm3 + ; AVX1-NEXT: vinsertps {{.*#+}} xmm2 = xmm3[0],xmm2[0],xmm3[2,3] + ; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm0 + ; AVX1-NEXT: vmovq %xmm0, %rax +-; AVX1-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm3 ++; AVX1-NEXT: vcvtsi2ssq %rax, %xmm4, %xmm3 + ; AVX1-NEXT: vinsertps {{.*#+}} xmm2 = xmm2[0,1],xmm3[0],xmm2[3] + ; AVX1-NEXT: vpextrq $1, %xmm0, %rax +-; AVX1-NEXT: vxorps %xmm0, %xmm0, %xmm0 +-; AVX1-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm0 ++; AVX1-NEXT: vcvtsi2ssq %rax, %xmm4, %xmm0 + ; AVX1-NEXT: vinsertps {{.*#+}} xmm0 = xmm2[0,1,2],xmm0[0] + ; AVX1-NEXT: vinsertf128 $1, %xmm1, %ymm0, %ymm0 + ; AVX1-NEXT: retq +@@ -2535,32 +2614,62 @@ define <8 x float> @sitofp_load_8i64_to_8f32(<8 x i64> *%a) { + ; AVX2-NEXT: vmovdqa (%rdi), %ymm0 + ; AVX2-NEXT: vmovdqa 32(%rdi), %ymm1 + ; AVX2-NEXT: vpextrq $1, %xmm1, %rax +-; AVX2-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm2 ++; AVX2-NEXT: vcvtsi2ssq %rax, %xmm2, %xmm2 + ; AVX2-NEXT: vmovq %xmm1, %rax +-; AVX2-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm3 ++; AVX2-NEXT: vcvtsi2ssq %rax, %xmm3, %xmm3 + ; AVX2-NEXT: vinsertps {{.*#+}} xmm2 = xmm3[0],xmm2[0],xmm3[2,3] + ; AVX2-NEXT: vextracti128 $1, %ymm1, %xmm1 + ; AVX2-NEXT: vmovq %xmm1, %rax +-; AVX2-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm3 ++; AVX2-NEXT: vcvtsi2ssq %rax, %xmm4, %xmm3 + ; AVX2-NEXT: vinsertps {{.*#+}} xmm2 = xmm2[0,1],xmm3[0],xmm2[3] + ; AVX2-NEXT: vpextrq $1, %xmm1, %rax +-; AVX2-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm1 ++; AVX2-NEXT: vcvtsi2ssq %rax, %xmm4, %xmm1 + ; AVX2-NEXT: vinsertps {{.*#+}} xmm1 = xmm2[0,1,2],xmm1[0] + ; AVX2-NEXT: vpextrq $1, %xmm0, %rax +-; AVX2-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm2 ++; AVX2-NEXT: vcvtsi2ssq %rax, %xmm4, %xmm2 + ; AVX2-NEXT: vmovq %xmm0, %rax +-; AVX2-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm3 ++; AVX2-NEXT: vcvtsi2ssq %rax, %xmm4, %xmm3 + ; AVX2-NEXT: vinsertps {{.*#+}} xmm2 = xmm3[0],xmm2[0],xmm3[2,3] + ; AVX2-NEXT: vextracti128 $1, %ymm0, %xmm0 + ; AVX2-NEXT: vmovq %xmm0, %rax +-; AVX2-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm3 ++; AVX2-NEXT: vcvtsi2ssq %rax, %xmm4, %xmm3 + ; AVX2-NEXT: vinsertps {{.*#+}} xmm2 = xmm2[0,1],xmm3[0],xmm2[3] + ; AVX2-NEXT: vpextrq $1, %xmm0, %rax +-; AVX2-NEXT: vxorps %xmm0, %xmm0, %xmm0 +-; AVX2-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm0 ++; AVX2-NEXT: vcvtsi2ssq %rax, %xmm4, %xmm0 + ; AVX2-NEXT: vinsertps {{.*#+}} xmm0 = xmm2[0,1,2],xmm0[0] + ; AVX2-NEXT: vinsertf128 $1, %xmm1, %ymm0, %ymm0 + ; AVX2-NEXT: retq ++; ++; AVX512-LABEL: sitofp_load_8i64_to_8f32: ++; AVX512: # BB#0: ++; AVX512-NEXT: vmovdqa64 (%rdi), %zmm0 ++; AVX512-NEXT: vextracti32x4 $2, %zmm0, %xmm1 ++; AVX512-NEXT: vpextrq $1, %xmm1, %rax ++; AVX512-NEXT: vcvtsi2ssq %rax, %xmm2, %xmm2 ++; AVX512-NEXT: vmovq %xmm1, %rax ++; AVX512-NEXT: vcvtsi2ssq %rax, %xmm3, %xmm1 ++; AVX512-NEXT: vinsertps {{.*#+}} xmm1 = xmm1[0],xmm2[0],xmm1[2,3] ++; AVX512-NEXT: vextracti32x4 $3, %zmm0, %xmm2 ++; AVX512-NEXT: vmovq %xmm2, %rax ++; AVX512-NEXT: vcvtsi2ssq %rax, %xmm3, %xmm3 ++; AVX512-NEXT: vinsertps {{.*#+}} xmm1 = xmm1[0,1],xmm3[0],xmm1[3] ++; AVX512-NEXT: vpextrq $1, %xmm2, %rax ++; AVX512-NEXT: vcvtsi2ssq %rax, %xmm4, %xmm2 ++; AVX512-NEXT: vinsertps {{.*#+}} xmm1 = xmm1[0,1,2],xmm2[0] ++; AVX512-NEXT: vpextrq $1, %xmm0, %rax ++; AVX512-NEXT: vcvtsi2ssq %rax, %xmm4, %xmm2 ++; AVX512-NEXT: vmovq %xmm0, %rax ++; AVX512-NEXT: vcvtsi2ssq %rax, %xmm4, %xmm3 ++; AVX512-NEXT: vinsertps {{.*#+}} xmm2 = xmm3[0],xmm2[0],xmm3[2,3] ++; AVX512-NEXT: vextracti32x4 $1, %zmm0, %xmm0 ++; AVX512-NEXT: vmovq %xmm0, %rax ++; AVX512-NEXT: vcvtsi2ssq %rax, %xmm4, %xmm3 ++; AVX512-NEXT: vinsertps {{.*#+}} xmm2 = xmm2[0,1],xmm3[0],xmm2[3] ++; AVX512-NEXT: vpextrq $1, %xmm0, %rax ++; AVX512-NEXT: vcvtsi2ssq %rax, %xmm4, %xmm0 ++; AVX512-NEXT: vinsertps {{.*#+}} xmm0 = xmm2[0,1,2],xmm0[0] ++; AVX512-NEXT: vinsertf32x4 $1, %xmm1, %ymm0, %ymm0 ++; AVX512-NEXT: retq + %ld = load <8 x i64>, <8 x i64> *%a + %cvt = sitofp <8 x i64> %ld to <8 x float> + ret <8 x float> %cvt +@@ -2733,12 +2842,12 @@ define <4 x float> @uitofp_load_4i64_to_4f32(<4 x i64> *%a) { + ; AVX1-NEXT: testq %rax, %rax + ; AVX1-NEXT: js .LBB74_1 + ; AVX1-NEXT: # BB#2: +-; AVX1-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm1 ++; AVX1-NEXT: vcvtsi2ssq %rax, %xmm1, %xmm1 + ; AVX1-NEXT: jmp .LBB74_3 + ; AVX1-NEXT: .LBB74_1: + ; AVX1-NEXT: shrq %rax + ; AVX1-NEXT: orq %rax, %rcx +-; AVX1-NEXT: vcvtsi2ssq %rcx, %xmm0, %xmm1 ++; AVX1-NEXT: vcvtsi2ssq %rcx, %xmm1, %xmm1 + ; AVX1-NEXT: vaddss %xmm1, %xmm1, %xmm1 + ; AVX1-NEXT: .LBB74_3: + ; AVX1-NEXT: vmovq %xmm0, %rax +@@ -2747,12 +2856,12 @@ define <4 x float> @uitofp_load_4i64_to_4f32(<4 x i64> *%a) { + ; AVX1-NEXT: testq %rax, %rax + ; AVX1-NEXT: js .LBB74_4 + ; AVX1-NEXT: # BB#5: +-; AVX1-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm2 ++; AVX1-NEXT: vcvtsi2ssq %rax, %xmm2, %xmm2 + ; AVX1-NEXT: jmp .LBB74_6 + ; AVX1-NEXT: .LBB74_4: + ; AVX1-NEXT: shrq %rax + ; AVX1-NEXT: orq %rax, %rcx +-; AVX1-NEXT: vcvtsi2ssq %rcx, %xmm0, %xmm2 ++; AVX1-NEXT: vcvtsi2ssq %rcx, %xmm2, %xmm2 + ; AVX1-NEXT: vaddss %xmm2, %xmm2, %xmm2 + ; AVX1-NEXT: .LBB74_6: + ; AVX1-NEXT: vinsertps {{.*#+}} xmm1 = xmm2[0],xmm1[0],xmm2[2,3] +@@ -2763,12 +2872,12 @@ define <4 x float> @uitofp_load_4i64_to_4f32(<4 x i64> *%a) { + ; AVX1-NEXT: testq %rax, %rax + ; AVX1-NEXT: js .LBB74_7 + ; AVX1-NEXT: # BB#8: +-; AVX1-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm2 ++; AVX1-NEXT: vcvtsi2ssq %rax, %xmm3, %xmm2 + ; AVX1-NEXT: jmp .LBB74_9 + ; AVX1-NEXT: .LBB74_7: + ; AVX1-NEXT: shrq %rax + ; AVX1-NEXT: orq %rax, %rcx +-; AVX1-NEXT: vcvtsi2ssq %rcx, %xmm0, %xmm2 ++; AVX1-NEXT: vcvtsi2ssq %rcx, %xmm3, %xmm2 + ; AVX1-NEXT: vaddss %xmm2, %xmm2, %xmm2 + ; AVX1-NEXT: .LBB74_9: + ; AVX1-NEXT: vinsertps {{.*#+}} xmm1 = xmm1[0,1],xmm2[0],xmm1[3] +@@ -2778,16 +2887,14 @@ define <4 x float> @uitofp_load_4i64_to_4f32(<4 x i64> *%a) { + ; AVX1-NEXT: testq %rax, %rax + ; AVX1-NEXT: js .LBB74_10 + ; AVX1-NEXT: # BB#11: +-; AVX1-NEXT: vxorps %xmm0, %xmm0, %xmm0 +-; AVX1-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm0 ++; AVX1-NEXT: vcvtsi2ssq %rax, %xmm3, %xmm0 + ; AVX1-NEXT: vinsertps {{.*#+}} xmm0 = xmm1[0,1,2],xmm0[0] + ; AVX1-NEXT: vzeroupper + ; AVX1-NEXT: retq + ; AVX1-NEXT: .LBB74_10: + ; AVX1-NEXT: shrq %rax + ; AVX1-NEXT: orq %rax, %rcx +-; AVX1-NEXT: vxorps %xmm0, %xmm0, %xmm0 +-; AVX1-NEXT: vcvtsi2ssq %rcx, %xmm0, %xmm0 ++; AVX1-NEXT: vcvtsi2ssq %rcx, %xmm3, %xmm0 + ; AVX1-NEXT: vaddss %xmm0, %xmm0, %xmm0 + ; AVX1-NEXT: vinsertps {{.*#+}} xmm0 = xmm1[0,1,2],xmm0[0] + ; AVX1-NEXT: vzeroupper +@@ -2802,12 +2909,12 @@ define <4 x float> @uitofp_load_4i64_to_4f32(<4 x i64> *%a) { + ; AVX2-NEXT: testq %rax, %rax + ; AVX2-NEXT: js .LBB74_1 + ; AVX2-NEXT: # BB#2: +-; AVX2-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm1 ++; AVX2-NEXT: vcvtsi2ssq %rax, %xmm1, %xmm1 + ; AVX2-NEXT: jmp .LBB74_3 + ; AVX2-NEXT: .LBB74_1: + ; AVX2-NEXT: shrq %rax + ; AVX2-NEXT: orq %rax, %rcx +-; AVX2-NEXT: vcvtsi2ssq %rcx, %xmm0, %xmm1 ++; AVX2-NEXT: vcvtsi2ssq %rcx, %xmm1, %xmm1 + ; AVX2-NEXT: vaddss %xmm1, %xmm1, %xmm1 + ; AVX2-NEXT: .LBB74_3: + ; AVX2-NEXT: vmovq %xmm0, %rax +@@ -2816,12 +2923,12 @@ define <4 x float> @uitofp_load_4i64_to_4f32(<4 x i64> *%a) { + ; AVX2-NEXT: testq %rax, %rax + ; AVX2-NEXT: js .LBB74_4 + ; AVX2-NEXT: # BB#5: +-; AVX2-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm2 ++; AVX2-NEXT: vcvtsi2ssq %rax, %xmm2, %xmm2 + ; AVX2-NEXT: jmp .LBB74_6 + ; AVX2-NEXT: .LBB74_4: + ; AVX2-NEXT: shrq %rax + ; AVX2-NEXT: orq %rax, %rcx +-; AVX2-NEXT: vcvtsi2ssq %rcx, %xmm0, %xmm2 ++; AVX2-NEXT: vcvtsi2ssq %rcx, %xmm2, %xmm2 + ; AVX2-NEXT: vaddss %xmm2, %xmm2, %xmm2 + ; AVX2-NEXT: .LBB74_6: + ; AVX2-NEXT: vinsertps {{.*#+}} xmm1 = xmm2[0],xmm1[0],xmm2[2,3] +@@ -2832,12 +2939,12 @@ define <4 x float> @uitofp_load_4i64_to_4f32(<4 x i64> *%a) { + ; AVX2-NEXT: testq %rax, %rax + ; AVX2-NEXT: js .LBB74_7 + ; AVX2-NEXT: # BB#8: +-; AVX2-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm2 ++; AVX2-NEXT: vcvtsi2ssq %rax, %xmm3, %xmm2 + ; AVX2-NEXT: jmp .LBB74_9 + ; AVX2-NEXT: .LBB74_7: + ; AVX2-NEXT: shrq %rax + ; AVX2-NEXT: orq %rax, %rcx +-; AVX2-NEXT: vcvtsi2ssq %rcx, %xmm0, %xmm2 ++; AVX2-NEXT: vcvtsi2ssq %rcx, %xmm3, %xmm2 + ; AVX2-NEXT: vaddss %xmm2, %xmm2, %xmm2 + ; AVX2-NEXT: .LBB74_9: + ; AVX2-NEXT: vinsertps {{.*#+}} xmm1 = xmm1[0,1],xmm2[0],xmm1[3] +@@ -2847,16 +2954,14 @@ define <4 x float> @uitofp_load_4i64_to_4f32(<4 x i64> *%a) { + ; AVX2-NEXT: testq %rax, %rax + ; AVX2-NEXT: js .LBB74_10 + ; AVX2-NEXT: # BB#11: +-; AVX2-NEXT: vxorps %xmm0, %xmm0, %xmm0 +-; AVX2-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm0 ++; AVX2-NEXT: vcvtsi2ssq %rax, %xmm3, %xmm0 + ; AVX2-NEXT: vinsertps {{.*#+}} xmm0 = xmm1[0,1,2],xmm0[0] + ; AVX2-NEXT: vzeroupper + ; AVX2-NEXT: retq + ; AVX2-NEXT: .LBB74_10: + ; AVX2-NEXT: shrq %rax + ; AVX2-NEXT: orq %rax, %rcx +-; AVX2-NEXT: vxorps %xmm0, %xmm0, %xmm0 +-; AVX2-NEXT: vcvtsi2ssq %rcx, %xmm0, %xmm0 ++; AVX2-NEXT: vcvtsi2ssq %rcx, %xmm3, %xmm0 + ; AVX2-NEXT: vaddss %xmm0, %xmm0, %xmm0 + ; AVX2-NEXT: vinsertps {{.*#+}} xmm0 = xmm1[0,1,2],xmm0[0] + ; AVX2-NEXT: vzeroupper +@@ -3094,12 +3199,12 @@ define <8 x float> @uitofp_load_8i64_to_8f32(<8 x i64> *%a) { + ; AVX1-NEXT: testq %rax, %rax + ; AVX1-NEXT: js .LBB78_1 + ; AVX1-NEXT: # BB#2: +-; AVX1-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm1 ++; AVX1-NEXT: vcvtsi2ssq %rax, %xmm1, %xmm1 + ; AVX1-NEXT: jmp .LBB78_3 + ; AVX1-NEXT: .LBB78_1: + ; AVX1-NEXT: shrq %rax + ; AVX1-NEXT: orq %rax, %rcx +-; AVX1-NEXT: vcvtsi2ssq %rcx, %xmm0, %xmm1 ++; AVX1-NEXT: vcvtsi2ssq %rcx, %xmm1, %xmm1 + ; AVX1-NEXT: vaddss %xmm1, %xmm1, %xmm1 + ; AVX1-NEXT: .LBB78_3: + ; AVX1-NEXT: vmovq %xmm2, %rax +@@ -3108,12 +3213,12 @@ define <8 x float> @uitofp_load_8i64_to_8f32(<8 x i64> *%a) { + ; AVX1-NEXT: testq %rax, %rax + ; AVX1-NEXT: js .LBB78_4 + ; AVX1-NEXT: # BB#5: +-; AVX1-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm3 ++; AVX1-NEXT: vcvtsi2ssq %rax, %xmm3, %xmm3 + ; AVX1-NEXT: jmp .LBB78_6 + ; AVX1-NEXT: .LBB78_4: + ; AVX1-NEXT: shrq %rax + ; AVX1-NEXT: orq %rax, %rcx +-; AVX1-NEXT: vcvtsi2ssq %rcx, %xmm0, %xmm3 ++; AVX1-NEXT: vcvtsi2ssq %rcx, %xmm3, %xmm3 + ; AVX1-NEXT: vaddss %xmm3, %xmm3, %xmm3 + ; AVX1-NEXT: .LBB78_6: + ; AVX1-NEXT: vextractf128 $1, %ymm2, %xmm2 +@@ -3123,12 +3228,12 @@ define <8 x float> @uitofp_load_8i64_to_8f32(<8 x i64> *%a) { + ; AVX1-NEXT: testq %rax, %rax + ; AVX1-NEXT: js .LBB78_7 + ; AVX1-NEXT: # BB#8: +-; AVX1-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm4 ++; AVX1-NEXT: vcvtsi2ssq %rax, %xmm4, %xmm4 + ; AVX1-NEXT: jmp .LBB78_9 + ; AVX1-NEXT: .LBB78_7: + ; AVX1-NEXT: shrq %rax + ; AVX1-NEXT: orq %rax, %rcx +-; AVX1-NEXT: vcvtsi2ssq %rcx, %xmm0, %xmm4 ++; AVX1-NEXT: vcvtsi2ssq %rcx, %xmm4, %xmm4 + ; AVX1-NEXT: vaddss %xmm4, %xmm4, %xmm4 + ; AVX1-NEXT: .LBB78_9: + ; AVX1-NEXT: vpextrq $1, %xmm2, %rax +@@ -3137,12 +3242,12 @@ define <8 x float> @uitofp_load_8i64_to_8f32(<8 x i64> *%a) { + ; AVX1-NEXT: testq %rax, %rax + ; AVX1-NEXT: js .LBB78_10 + ; AVX1-NEXT: # BB#11: +-; AVX1-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm2 ++; AVX1-NEXT: vcvtsi2ssq %rax, %xmm5, %xmm2 + ; AVX1-NEXT: jmp .LBB78_12 + ; AVX1-NEXT: .LBB78_10: + ; AVX1-NEXT: shrq %rax + ; AVX1-NEXT: orq %rax, %rcx +-; AVX1-NEXT: vcvtsi2ssq %rcx, %xmm0, %xmm2 ++; AVX1-NEXT: vcvtsi2ssq %rcx, %xmm5, %xmm2 + ; AVX1-NEXT: vaddss %xmm2, %xmm2, %xmm2 + ; AVX1-NEXT: .LBB78_12: + ; AVX1-NEXT: vpextrq $1, %xmm0, %rax +@@ -3151,12 +3256,12 @@ define <8 x float> @uitofp_load_8i64_to_8f32(<8 x i64> *%a) { + ; AVX1-NEXT: testq %rax, %rax + ; AVX1-NEXT: js .LBB78_13 + ; AVX1-NEXT: # BB#14: +-; AVX1-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm5 ++; AVX1-NEXT: vcvtsi2ssq %rax, %xmm5, %xmm5 + ; AVX1-NEXT: jmp .LBB78_15 + ; AVX1-NEXT: .LBB78_13: + ; AVX1-NEXT: shrq %rax + ; AVX1-NEXT: orq %rax, %rcx +-; AVX1-NEXT: vcvtsi2ssq %rcx, %xmm0, %xmm5 ++; AVX1-NEXT: vcvtsi2ssq %rcx, %xmm5, %xmm5 + ; AVX1-NEXT: vaddss %xmm5, %xmm5, %xmm5 + ; AVX1-NEXT: .LBB78_15: + ; AVX1-NEXT: vinsertps {{.*#+}} xmm1 = xmm3[0],xmm1[0],xmm3[2,3] +@@ -3166,12 +3271,12 @@ define <8 x float> @uitofp_load_8i64_to_8f32(<8 x i64> *%a) { + ; AVX1-NEXT: testq %rax, %rax + ; AVX1-NEXT: js .LBB78_16 + ; AVX1-NEXT: # BB#17: +-; AVX1-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm3 ++; AVX1-NEXT: vcvtsi2ssq %rax, %xmm6, %xmm3 + ; AVX1-NEXT: jmp .LBB78_18 + ; AVX1-NEXT: .LBB78_16: + ; AVX1-NEXT: shrq %rax + ; AVX1-NEXT: orq %rax, %rcx +-; AVX1-NEXT: vcvtsi2ssq %rcx, %xmm0, %xmm3 ++; AVX1-NEXT: vcvtsi2ssq %rcx, %xmm6, %xmm3 + ; AVX1-NEXT: vaddss %xmm3, %xmm3, %xmm3 + ; AVX1-NEXT: .LBB78_18: + ; AVX1-NEXT: vinsertps {{.*#+}} xmm1 = xmm1[0,1],xmm4[0],xmm1[3] +@@ -3183,14 +3288,12 @@ define <8 x float> @uitofp_load_8i64_to_8f32(<8 x i64> *%a) { + ; AVX1-NEXT: testq %rax, %rax + ; AVX1-NEXT: js .LBB78_19 + ; AVX1-NEXT: # BB#20: +-; AVX1-NEXT: vxorps %xmm0, %xmm0, %xmm0 +-; AVX1-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm5 ++; AVX1-NEXT: vcvtsi2ssq %rax, %xmm6, %xmm5 + ; AVX1-NEXT: jmp .LBB78_21 + ; AVX1-NEXT: .LBB78_19: + ; AVX1-NEXT: shrq %rax + ; AVX1-NEXT: orq %rax, %rcx +-; AVX1-NEXT: vxorps %xmm0, %xmm0, %xmm0 +-; AVX1-NEXT: vcvtsi2ssq %rcx, %xmm0, %xmm0 ++; AVX1-NEXT: vcvtsi2ssq %rcx, %xmm6, %xmm0 + ; AVX1-NEXT: vaddss %xmm0, %xmm0, %xmm5 + ; AVX1-NEXT: .LBB78_21: + ; AVX1-NEXT: vinsertps {{.*#+}} xmm0 = xmm1[0,1,2],xmm2[0] +@@ -3201,12 +3304,12 @@ define <8 x float> @uitofp_load_8i64_to_8f32(<8 x i64> *%a) { + ; AVX1-NEXT: testq %rax, %rax + ; AVX1-NEXT: js .LBB78_22 + ; AVX1-NEXT: # BB#23: +-; AVX1-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm2 ++; AVX1-NEXT: vcvtsi2ssq %rax, %xmm6, %xmm2 + ; AVX1-NEXT: jmp .LBB78_24 + ; AVX1-NEXT: .LBB78_22: + ; AVX1-NEXT: shrq %rax + ; AVX1-NEXT: orq %rax, %rcx +-; AVX1-NEXT: vcvtsi2ssq %rcx, %xmm0, %xmm2 ++; AVX1-NEXT: vcvtsi2ssq %rcx, %xmm6, %xmm2 + ; AVX1-NEXT: vaddss %xmm2, %xmm2, %xmm2 + ; AVX1-NEXT: .LBB78_24: + ; AVX1-NEXT: vinsertps {{.*#+}} xmm1 = xmm1[0,1,2],xmm2[0] +@@ -3223,12 +3326,12 @@ define <8 x float> @uitofp_load_8i64_to_8f32(<8 x i64> *%a) { + ; AVX2-NEXT: testq %rax, %rax + ; AVX2-NEXT: js .LBB78_1 + ; AVX2-NEXT: # BB#2: +-; AVX2-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm1 ++; AVX2-NEXT: vcvtsi2ssq %rax, %xmm1, %xmm1 + ; AVX2-NEXT: jmp .LBB78_3 + ; AVX2-NEXT: .LBB78_1: + ; AVX2-NEXT: shrq %rax + ; AVX2-NEXT: orq %rax, %rcx +-; AVX2-NEXT: vcvtsi2ssq %rcx, %xmm0, %xmm1 ++; AVX2-NEXT: vcvtsi2ssq %rcx, %xmm1, %xmm1 + ; AVX2-NEXT: vaddss %xmm1, %xmm1, %xmm1 + ; AVX2-NEXT: .LBB78_3: + ; AVX2-NEXT: vmovq %xmm2, %rax +@@ -3237,12 +3340,12 @@ define <8 x float> @uitofp_load_8i64_to_8f32(<8 x i64> *%a) { + ; AVX2-NEXT: testq %rax, %rax + ; AVX2-NEXT: js .LBB78_4 + ; AVX2-NEXT: # BB#5: +-; AVX2-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm3 ++; AVX2-NEXT: vcvtsi2ssq %rax, %xmm3, %xmm3 + ; AVX2-NEXT: jmp .LBB78_6 + ; AVX2-NEXT: .LBB78_4: + ; AVX2-NEXT: shrq %rax + ; AVX2-NEXT: orq %rax, %rcx +-; AVX2-NEXT: vcvtsi2ssq %rcx, %xmm0, %xmm3 ++; AVX2-NEXT: vcvtsi2ssq %rcx, %xmm3, %xmm3 + ; AVX2-NEXT: vaddss %xmm3, %xmm3, %xmm3 + ; AVX2-NEXT: .LBB78_6: + ; AVX2-NEXT: vextracti128 $1, %ymm2, %xmm2 +@@ -3252,12 +3355,12 @@ define <8 x float> @uitofp_load_8i64_to_8f32(<8 x i64> *%a) { + ; AVX2-NEXT: testq %rax, %rax + ; AVX2-NEXT: js .LBB78_7 + ; AVX2-NEXT: # BB#8: +-; AVX2-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm4 ++; AVX2-NEXT: vcvtsi2ssq %rax, %xmm4, %xmm4 + ; AVX2-NEXT: jmp .LBB78_9 + ; AVX2-NEXT: .LBB78_7: + ; AVX2-NEXT: shrq %rax + ; AVX2-NEXT: orq %rax, %rcx +-; AVX2-NEXT: vcvtsi2ssq %rcx, %xmm0, %xmm4 ++; AVX2-NEXT: vcvtsi2ssq %rcx, %xmm4, %xmm4 + ; AVX2-NEXT: vaddss %xmm4, %xmm4, %xmm4 + ; AVX2-NEXT: .LBB78_9: + ; AVX2-NEXT: vpextrq $1, %xmm2, %rax +@@ -3266,12 +3369,12 @@ define <8 x float> @uitofp_load_8i64_to_8f32(<8 x i64> *%a) { + ; AVX2-NEXT: testq %rax, %rax + ; AVX2-NEXT: js .LBB78_10 + ; AVX2-NEXT: # BB#11: +-; AVX2-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm2 ++; AVX2-NEXT: vcvtsi2ssq %rax, %xmm5, %xmm2 + ; AVX2-NEXT: jmp .LBB78_12 + ; AVX2-NEXT: .LBB78_10: + ; AVX2-NEXT: shrq %rax + ; AVX2-NEXT: orq %rax, %rcx +-; AVX2-NEXT: vcvtsi2ssq %rcx, %xmm0, %xmm2 ++; AVX2-NEXT: vcvtsi2ssq %rcx, %xmm5, %xmm2 + ; AVX2-NEXT: vaddss %xmm2, %xmm2, %xmm2 + ; AVX2-NEXT: .LBB78_12: + ; AVX2-NEXT: vpextrq $1, %xmm0, %rax +@@ -3280,12 +3383,12 @@ define <8 x float> @uitofp_load_8i64_to_8f32(<8 x i64> *%a) { + ; AVX2-NEXT: testq %rax, %rax + ; AVX2-NEXT: js .LBB78_13 + ; AVX2-NEXT: # BB#14: +-; AVX2-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm5 ++; AVX2-NEXT: vcvtsi2ssq %rax, %xmm5, %xmm5 + ; AVX2-NEXT: jmp .LBB78_15 + ; AVX2-NEXT: .LBB78_13: + ; AVX2-NEXT: shrq %rax + ; AVX2-NEXT: orq %rax, %rcx +-; AVX2-NEXT: vcvtsi2ssq %rcx, %xmm0, %xmm5 ++; AVX2-NEXT: vcvtsi2ssq %rcx, %xmm5, %xmm5 + ; AVX2-NEXT: vaddss %xmm5, %xmm5, %xmm5 + ; AVX2-NEXT: .LBB78_15: + ; AVX2-NEXT: vinsertps {{.*#+}} xmm1 = xmm3[0],xmm1[0],xmm3[2,3] +@@ -3295,12 +3398,12 @@ define <8 x float> @uitofp_load_8i64_to_8f32(<8 x i64> *%a) { + ; AVX2-NEXT: testq %rax, %rax + ; AVX2-NEXT: js .LBB78_16 + ; AVX2-NEXT: # BB#17: +-; AVX2-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm3 ++; AVX2-NEXT: vcvtsi2ssq %rax, %xmm6, %xmm3 + ; AVX2-NEXT: jmp .LBB78_18 + ; AVX2-NEXT: .LBB78_16: + ; AVX2-NEXT: shrq %rax + ; AVX2-NEXT: orq %rax, %rcx +-; AVX2-NEXT: vcvtsi2ssq %rcx, %xmm0, %xmm3 ++; AVX2-NEXT: vcvtsi2ssq %rcx, %xmm6, %xmm3 + ; AVX2-NEXT: vaddss %xmm3, %xmm3, %xmm3 + ; AVX2-NEXT: .LBB78_18: + ; AVX2-NEXT: vinsertps {{.*#+}} xmm1 = xmm1[0,1],xmm4[0],xmm1[3] +@@ -3312,14 +3415,12 @@ define <8 x float> @uitofp_load_8i64_to_8f32(<8 x i64> *%a) { + ; AVX2-NEXT: testq %rax, %rax + ; AVX2-NEXT: js .LBB78_19 + ; AVX2-NEXT: # BB#20: +-; AVX2-NEXT: vxorps %xmm0, %xmm0, %xmm0 +-; AVX2-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm5 ++; AVX2-NEXT: vcvtsi2ssq %rax, %xmm6, %xmm5 + ; AVX2-NEXT: jmp .LBB78_21 + ; AVX2-NEXT: .LBB78_19: + ; AVX2-NEXT: shrq %rax + ; AVX2-NEXT: orq %rax, %rcx +-; AVX2-NEXT: vxorps %xmm0, %xmm0, %xmm0 +-; AVX2-NEXT: vcvtsi2ssq %rcx, %xmm0, %xmm0 ++; AVX2-NEXT: vcvtsi2ssq %rcx, %xmm6, %xmm0 + ; AVX2-NEXT: vaddss %xmm0, %xmm0, %xmm5 + ; AVX2-NEXT: .LBB78_21: + ; AVX2-NEXT: vinsertps {{.*#+}} xmm0 = xmm1[0,1,2],xmm2[0] +@@ -3330,12 +3431,12 @@ define <8 x float> @uitofp_load_8i64_to_8f32(<8 x i64> *%a) { + ; AVX2-NEXT: testq %rax, %rax + ; AVX2-NEXT: js .LBB78_22 + ; AVX2-NEXT: # BB#23: +-; AVX2-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm2 ++; AVX2-NEXT: vcvtsi2ssq %rax, %xmm6, %xmm2 + ; AVX2-NEXT: jmp .LBB78_24 + ; AVX2-NEXT: .LBB78_22: + ; AVX2-NEXT: shrq %rax + ; AVX2-NEXT: orq %rax, %rcx +-; AVX2-NEXT: vcvtsi2ssq %rcx, %xmm0, %xmm2 ++; AVX2-NEXT: vcvtsi2ssq %rcx, %xmm6, %xmm2 + ; AVX2-NEXT: vaddss %xmm2, %xmm2, %xmm2 + ; AVX2-NEXT: .LBB78_24: + ; AVX2-NEXT: vinsertps {{.*#+}} xmm1 = xmm1[0,1,2],xmm2[0] +-- +2.11.0 + diff --git a/deps/patches/llvm-PR278923.patch b/deps/patches/llvm-PR278923.patch new file mode 100644 index 0000000000000..486777711193a --- /dev/null +++ b/deps/patches/llvm-PR278923.patch @@ -0,0 +1,69 @@ +From 77eee1c0f05c587e7fb8a9a2064908d7333dcfb9 Mon Sep 17 00:00:00 2001 +From: Marina Yatsina +Date: Wed, 17 Aug 2016 11:40:21 +0000 +Subject: [PATCH 5/5] Fixing bug committed in rev. 278321 + +In theory the indices of RC (and thus the index used for LiveRegs) may differ from the indices of OpRC. +Fixed the code to extract the correct RC index. +OpRC contains the first X consecutive elements of RC, and thus their indices are currently de facto the same, therefore a test cannot be added at this point. + +Differential Revision: https://reviews.llvm.org/D23491 + + + +git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@278923 91177308-0d34-0410-b5e6-96231b3b80d8 +--- + include/llvm/Target/TargetRegisterInfo.h | 6 ++++++ + lib/CodeGen/ExecutionDepsFix.cpp | 9 ++++++--- + 2 files changed, 12 insertions(+), 3 deletions(-) + +diff --git a/include/llvm/Target/TargetRegisterInfo.h b/include/llvm/Target/TargetRegisterInfo.h +index e5a6c8ed2f2..e5642493928 100644 +--- a/include/llvm/Target/TargetRegisterInfo.h ++++ b/include/llvm/Target/TargetRegisterInfo.h +@@ -17,6 +17,7 @@ + #define LLVM_TARGET_TARGETREGISTERINFO_H + + #include "llvm/ADT/ArrayRef.h" ++#include "llvm/ADT/iterator_range.h" + #include "llvm/CodeGen/MachineBasicBlock.h" + #include "llvm/CodeGen/MachineValueType.h" + #include "llvm/IR/CallingConv.h" +@@ -86,6 +87,11 @@ public: + + /// Return the number of registers in this class. + unsigned getNumRegs() const { return MC->getNumRegs(); } ++ ++ iterator_range::const_iterator> ++ getRegisters() const { ++ return make_range(MC->begin(), MC->end()); ++ } + + /// Return the specified register in the class. + unsigned getRegister(unsigned i) const { +diff --git a/lib/CodeGen/ExecutionDepsFix.cpp b/lib/CodeGen/ExecutionDepsFix.cpp +index 5f91db9251c..213dd58a31d 100644 +--- a/lib/CodeGen/ExecutionDepsFix.cpp ++++ b/lib/CodeGen/ExecutionDepsFix.cpp +@@ -509,12 +509,15 @@ void ExeDepsFix::pickBestRegisterForUndef(MachineInstr *MI, unsigned OpIdx, + // max clearance or clearance higher than Pref. + unsigned MaxClearance = 0; + unsigned MaxClearanceReg = OriginalReg; +- for (unsigned rx = 0; rx < OpRC->getNumRegs(); ++rx) { +- unsigned Clearance = CurInstr - LiveRegs[rx].Def; ++ for (auto Reg : OpRC->getRegisters()) { ++ assert(AliasMap[Reg].size() == 1 && ++ "Reg is expected to be mapped to a single index"); ++ int RCrx = *regIndices(Reg).begin(); ++ unsigned Clearance = CurInstr - LiveRegs[RCrx].Def; + if (Clearance <= MaxClearance) + continue; + MaxClearance = Clearance; +- MaxClearanceReg = OpRC->getRegister(rx); ++ MaxClearanceReg = Reg; + + if (MaxClearance > Pref) + break; +-- +2.11.0 + diff --git a/deps/patches/llvm-PR29010-i386-xmm.patch b/deps/patches/llvm-PR29010-i386-xmm.patch new file mode 100644 index 0000000000000..b31f70d365cf0 --- /dev/null +++ b/deps/patches/llvm-PR29010-i386-xmm.patch @@ -0,0 +1,80 @@ +From 83260f239481dfb40d325cf35005c20eeb767b6c Mon Sep 17 00:00:00 2001 +From: Marina Yatsina +Date: Wed, 17 Aug 2016 19:07:40 +0000 +Subject: [PATCH] Fix for PR29010 + +This is a fix for https://llvm.org/bugs/show_bug.cgi?id=29010 +Root cause of the bug is that the register class of the machine instruction operand does not fully reflect if this registers that can be allocated. +Both for i386 and x86_64 the operand's register class is VR128RegClass and thus contains xmm0-xmm15, though in i386 we can only use xmm0-xmm8. +In order to get the actual allocable registers of the class we need to use RegisterClassInfo. + +Differential Revision: https://reviews.llvm.org/D23613 + + + +git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@278954 91177308-0d34-0410-b5e6-96231b3b80d8 +--- + lib/CodeGen/ExecutionDepsFix.cpp | 6 +++++- + test/CodeGen/X86/pr29010.ll | 12 ++++++++++++ + 2 files changed, 17 insertions(+), 1 deletion(-) + create mode 100644 test/CodeGen/X86/pr29010.ll + +diff --git a/lib/CodeGen/ExecutionDepsFix.cpp b/lib/CodeGen/ExecutionDepsFix.cpp +index 213dd58a31d..2f173f84d73 100644 +--- a/lib/CodeGen/ExecutionDepsFix.cpp ++++ b/lib/CodeGen/ExecutionDepsFix.cpp +@@ -26,6 +26,7 @@ + #include "llvm/CodeGen/LivePhysRegs.h" + #include "llvm/CodeGen/MachineFunctionPass.h" + #include "llvm/CodeGen/MachineRegisterInfo.h" ++#include "llvm/CodeGen/RegisterClassInfo.h" + #include "llvm/Support/Allocator.h" + #include "llvm/Support/Debug.h" + #include "llvm/Support/raw_ostream.h" +@@ -137,6 +138,7 @@ class ExeDepsFix : public MachineFunctionPass { + MachineFunction *MF; + const TargetInstrInfo *TII; + const TargetRegisterInfo *TRI; ++ RegisterClassInfo RegClassInfo; + std::vector> AliasMap; + const unsigned NumRegs; + LiveReg *LiveRegs; +@@ -509,7 +511,8 @@ void ExeDepsFix::pickBestRegisterForUndef(MachineInstr *MI, unsigned OpIdx, + // max clearance or clearance higher than Pref. + unsigned MaxClearance = 0; + unsigned MaxClearanceReg = OriginalReg; +- for (auto Reg : OpRC->getRegisters()) { ++ ArrayRef Order = RegClassInfo.getOrder(OpRC); ++ for (auto Reg : Order) { + assert(AliasMap[Reg].size() == 1 && + "Reg is expected to be mapped to a single index"); + int RCrx = *regIndices(Reg).begin(); +@@ -785,6 +788,7 @@ bool ExeDepsFix::runOnMachineFunction(MachineFunction &mf) { + MF = &mf; + TII = MF->getSubtarget().getInstrInfo(); + TRI = MF->getSubtarget().getRegisterInfo(); ++ RegClassInfo.runOnMachineFunction(mf); + LiveRegs = nullptr; + assert(NumRegs == RC->getNumRegs() && "Bad regclass"); + +diff --git a/test/CodeGen/X86/pr29010.ll b/test/CodeGen/X86/pr29010.ll +new file mode 100644 +index 00000000000..a2d5ff69a35 +--- /dev/null ++++ b/test/CodeGen/X86/pr29010.ll +@@ -0,0 +1,12 @@ ++; RUN: llc < %s -mtriple=i386-linux -mattr=+avx | FileCheck %s ++ ++; In i386 there are only 8 XMMs (xmm0-xmm7), make sure we we are not creating illegal XMM ++define float @only_xmm0_7(i32 %arg) { ++top: ++ tail call void asm sideeffect "", "~{xmm0},~{xmm1},~{xmm2},~{xmm3},~{dirflag},~{fpsr},~{flags}"() ++ tail call void asm sideeffect "", "~{xmm4},~{xmm5},~{xmm6},~{xmm7},~{dirflag},~{fpsr},~{flags}"() ++ %tmp1 = sitofp i32 %arg to float ++ ret float %tmp1 ++;CHECK-LABEL:@only_xmm0_7 ++;CHECK: vcvtsi2ssl {{.*}}, {{%xmm[0-7]+}}, {{%xmm[0-7]+}} ++} +-- +2.13.0 + diff --git a/deps/patches/llvm-PR36292-5.0.patch b/deps/patches/llvm-PR36292-5.0.patch new file mode 100644 index 0000000000000..7d5d8d167f533 --- /dev/null +++ b/deps/patches/llvm-PR36292-5.0.patch @@ -0,0 +1,97 @@ +From 94f96f87fa44f2fa2cf86ecb644d3cdc3fc609ad Mon Sep 17 00:00:00 2001 +From: Nemanja Ivanovic +Date: Thu, 22 Feb 2018 03:02:41 +0000 +Subject: [PATCH] [PowerPC] Do not produce invalid CTR loop with an FRem + +An FRem instruction inside a loop should prevent the loop from being converted +into a CTR loop since this is not an operation that is legal on any PPC +subtarget. This will always be a call to a library function which means the +loop will be invalid if this instruction is in the body. + +Fixes PR36292. + + +git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@325739 91177308-0d34-0410-b5e6-96231b3b80d8 +--- + lib/Target/PowerPC/PPCCTRLoops.cpp | 5 ++++- + test/CodeGen/PowerPC/pr36292.ll | 46 ++++++++++++++++++++++++++++++++++++++ + 2 files changed, 50 insertions(+), 1 deletion(-) + create mode 100644 test/CodeGen/PowerPC/pr36292.ll + +diff --git a/lib/Target/PowerPC/PPCCTRLoops.cpp b/lib/Target/PowerPC/PPCCTRLoops.cpp +index 53f33ac1fc0..97917a1d096 100644 +--- a/lib/Target/PowerPC/PPCCTRLoops.cpp ++++ b/lib/Target/PowerPC/PPCCTRLoops.cpp +@@ -437,13 +437,16 @@ bool PPCCTRLoops::mightUseCTR(BasicBlock *BB) { + return true; + } + ++ // FREM is always a call. ++ if (J->getOpcode() == Instruction::FRem) ++ return true; ++ + if (STI->useSoftFloat()) { + switch(J->getOpcode()) { + case Instruction::FAdd: + case Instruction::FSub: + case Instruction::FMul: + case Instruction::FDiv: +- case Instruction::FRem: + case Instruction::FPTrunc: + case Instruction::FPExt: + case Instruction::FPToUI: +diff --git a/test/CodeGen/PowerPC/pr36292.ll b/test/CodeGen/PowerPC/pr36292.ll +new file mode 100644 +index 00000000000..a171918b9e0 +--- /dev/null ++++ b/test/CodeGen/PowerPC/pr36292.ll +@@ -0,0 +1,46 @@ ++; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-unknown < %s | \ ++; RUN: FileCheck %s --implicit-check-not=mtctr --implicit-check-not=bdnz ++$test = comdat any ++ ++; No CTR loop due to frem (since it is always a call). ++define void @test() #0 comdat { ++; CHECK-LABEL: test: ++; CHECK: ld 29, 0(3) ++; CHECK: ld 30, 40(1) ++; CHECK: xxlxor 31, 31, 31 ++; CHECK: cmpld 30, 29 ++; CHECK-NEXT: bge- 0, .LBB0_2 ++; CHECK-NEXT: .p2align 5 ++; CHECK-NEXT: .LBB0_1: # %bounds.ok ++; CHECK: fmr 1, 31 ++; CHECK-NEXT: lfsx 2, 0, 3 ++; CHECK-NEXT: bl fmodf ++; CHECK-NEXT: nop ++; CHECK-NEXT: addi 30, 30, 1 ++; CHECK-NEXT: stfsx 1, 0, 3 ++; CHECK-NEXT: cmpld 30, 29 ++; CHECK-NEXT: blt+ 0, .LBB0_1 ++; CHECK-NEXT: .LBB0_2: # %bounds.fail ++; CHECK-NEXT: std 30, 40(1) ++ %pos = alloca i64, align 8 ++ br label %forcond ++ ++forcond: ; preds = %bounds.ok, %0 ++ %1 = load i64, i64* %pos ++ %.len1 = load i64, i64* undef ++ %bounds.cmp = icmp ult i64 %1, %.len1 ++ br i1 %bounds.cmp, label %bounds.ok, label %bounds.fail ++ ++bounds.ok: ; preds = %forcond ++ %2 = load float, float* undef ++ %3 = frem float 0.000000e+00, %2 ++ store float %3, float* undef ++ %4 = load i64, i64* %pos ++ %5 = add i64 %4, 1 ++ store i64 %5, i64* %pos ++ br label %forcond ++ ++bounds.fail: ; preds = %forcond ++ unreachable ++} ++ +-- +2.16.2 + diff --git a/deps/patches/llvm-PR36292.patch b/deps/patches/llvm-PR36292.patch new file mode 100644 index 0000000000000..8d5f72b146ac3 --- /dev/null +++ b/deps/patches/llvm-PR36292.patch @@ -0,0 +1,96 @@ +From bf6e0a9a6dacce55de9f72de06318e7b97b44e3d Mon Sep 17 00:00:00 2001 +From: Nemanja Ivanovic +Date: Thu, 22 Feb 2018 03:02:41 +0000 +Subject: [PATCH] [PowerPC] Do not produce invalid CTR loop with an FRem + +An FRem instruction inside a loop should prevent the loop from being converted +into a CTR loop since this is not an operation that is legal on any PPC +subtarget. This will always be a call to a library function which means the +loop will be invalid if this instruction is in the body. + +Fixes PR36292. + +git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@325739 91177308-0d34-0410-b5e6-96231b3b80d8 +--- + lib/Target/PowerPC/PPCCTRLoops.cpp | 5 ++++- + test/CodeGen/PowerPC/pr36292.ll | 46 ++++++++++++++++++++++++++++++++++++++ + 2 files changed, 50 insertions(+), 1 deletion(-) + create mode 100644 test/CodeGen/PowerPC/pr36292.ll + +diff --git a/lib/Target/PowerPC/PPCCTRLoops.cpp b/lib/Target/PowerPC/PPCCTRLoops.cpp +index 87522663591..6a327781ca2 100644 +--- a/lib/Target/PowerPC/PPCCTRLoops.cpp ++++ b/lib/Target/PowerPC/PPCCTRLoops.cpp +@@ -435,13 +435,16 @@ bool PPCCTRLoops::mightUseCTR(const Triple &TT, BasicBlock *BB) { + return true; + } + ++ // FREM is always a call. ++ if (J->getOpcode() == Instruction::FRem) ++ return true; ++ + if (TM->getSubtargetImpl(*BB->getParent())->getTargetLowering()->useSoftFloat()) { + switch(J->getOpcode()) { + case Instruction::FAdd: + case Instruction::FSub: + case Instruction::FMul: + case Instruction::FDiv: +- case Instruction::FRem: + case Instruction::FPTrunc: + case Instruction::FPExt: + case Instruction::FPToUI: +diff --git a/test/CodeGen/PowerPC/pr36292.ll b/test/CodeGen/PowerPC/pr36292.ll +new file mode 100644 +index 00000000000..a171918b9e0 +--- /dev/null ++++ b/test/CodeGen/PowerPC/pr36292.ll +@@ -0,0 +1,46 @@ ++; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-unknown < %s | \ ++; RUN: FileCheck %s --implicit-check-not=mtctr --implicit-check-not=bdnz ++$test = comdat any ++ ++; No CTR loop due to frem (since it is always a call). ++define void @test() #0 comdat { ++; CHECK-LABEL: test: ++; CHECK: ld 29, 0(3) ++; CHECK: ld 30, 40(1) ++; CHECK: xxlxor 31, 31, 31 ++; CHECK: cmpld 30, 29 ++; CHECK-NEXT: bge- 0, .LBB0_2 ++; CHECK-NEXT: .p2align 5 ++; CHECK-NEXT: .LBB0_1: # %bounds.ok ++; CHECK: fmr 1, 31 ++; CHECK-NEXT: lfsx 2, 0, 3 ++; CHECK-NEXT: bl fmodf ++; CHECK-NEXT: nop ++; CHECK-NEXT: addi 30, 30, 1 ++; CHECK-NEXT: stfsx 1, 0, 3 ++; CHECK-NEXT: cmpld 30, 29 ++; CHECK-NEXT: blt+ 0, .LBB0_1 ++; CHECK-NEXT: .LBB0_2: # %bounds.fail ++; CHECK-NEXT: std 30, 40(1) ++ %pos = alloca i64, align 8 ++ br label %forcond ++ ++forcond: ; preds = %bounds.ok, %0 ++ %1 = load i64, i64* %pos ++ %.len1 = load i64, i64* undef ++ %bounds.cmp = icmp ult i64 %1, %.len1 ++ br i1 %bounds.cmp, label %bounds.ok, label %bounds.fail ++ ++bounds.ok: ; preds = %forcond ++ %2 = load float, float* undef ++ %3 = frem float 0.000000e+00, %2 ++ store float %3, float* undef ++ %4 = load i64, i64* %pos ++ %5 = add i64 %4, 1 ++ store i64 %5, i64* %pos ++ br label %forcond ++ ++bounds.fail: ; preds = %forcond ++ unreachable ++} ++ +-- +2.16.2 + diff --git a/deps/patches/llvm-VNCoercion-signatures.patch b/deps/patches/llvm-VNCoercion-signatures.patch new file mode 100644 index 0000000000000..5b8923ee47678 --- /dev/null +++ b/deps/patches/llvm-VNCoercion-signatures.patch @@ -0,0 +1,60 @@ +From a0946a413f7ee14ed26c48a249b2a326ade70a42 Mon Sep 17 00:00:00 2001 +From: Daniel Berlin +Date: Sat, 11 Mar 2017 00:51:01 +0000 +Subject: [PATCH 6/7] VNCoercion: Make the function signatures all consistent + +git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@297537 91177308-0d34-0410-b5e6-96231b3b80d8 +--- + include/llvm/Transforms/Utils/VNCoercion.h | 2 +- + lib/Transforms/Scalar/GVN.cpp | 2 +- + lib/Transforms/Utils/VNCoercion.cpp | 3 +-- + 3 files changed, 3 insertions(+), 4 deletions(-) + +diff --git a/include/llvm/Transforms/Utils/VNCoercion.h b/include/llvm/Transforms/Utils/VNCoercion.h +index d3c998fa8a8..edc63ca38db 100644 +--- a/include/llvm/Transforms/Utils/VNCoercion.h ++++ b/include/llvm/Transforms/Utils/VNCoercion.h +@@ -53,7 +53,7 @@ Value *coerceAvailableValueToLoadType(Value *StoredVal, Type *LoadedTy, + /// On success, it returns the offset into DepSI that extraction would start. + /// On failure, it returns -1. + int analyzeLoadFromClobberingStore(Type *LoadTy, Value *LoadPtr, +- StoreInst *DepSI); ++ StoreInst *DepSI, const DataLayout &DL); + + /// This function determines whether a value for the pointer LoadPtr can be + /// extracted from the load at DepLI. +diff --git a/lib/Transforms/Scalar/GVN.cpp b/lib/Transforms/Scalar/GVN.cpp +index 132c7297d77..7b8948c065b 100644 +--- a/lib/Transforms/Scalar/GVN.cpp ++++ b/lib/Transforms/Scalar/GVN.cpp +@@ -830,7 +830,7 @@ bool GVN::AnalyzeLoadAvailability(LoadInst *LI, MemDepResult DepInfo, + // Can't forward from non-atomic to atomic without violating memory model. + if (Address && LI->isAtomic() <= DepSI->isAtomic()) { + int Offset = +- analyzeLoadFromClobberingStore(LI->getType(), Address, DepSI); ++ analyzeLoadFromClobberingStore(LI->getType(), Address, DepSI, DL); + if (Offset != -1) { + Res = AvailableValue::get(DepSI->getValueOperand(), Offset); + return true; +diff --git a/lib/Transforms/Utils/VNCoercion.cpp b/lib/Transforms/Utils/VNCoercion.cpp +index 9d2eab19ded..6fa9aca8436 100644 +--- a/lib/Transforms/Utils/VNCoercion.cpp ++++ b/lib/Transforms/Utils/VNCoercion.cpp +@@ -195,13 +195,12 @@ static int analyzeLoadFromClobberingWrite(Type *LoadTy, Value *LoadPtr, + /// This function is called when we have a + /// memdep query of a load that ends up being a clobbering store. + int analyzeLoadFromClobberingStore(Type *LoadTy, Value *LoadPtr, +- StoreInst *DepSI) { ++ StoreInst *DepSI, const DataLayout &DL) { + // Cannot handle reading from store of first-class aggregate yet. + if (DepSI->getValueOperand()->getType()->isStructTy() || + DepSI->getValueOperand()->getType()->isArrayTy()) + return -1; + +- const DataLayout &DL = DepSI->getModule()->getDataLayout(); + Value *StorePtr = DepSI->getPointerOperand(); + uint64_t StoreSize = + DL.getTypeSizeInBits(DepSI->getValueOperand()->getType()); +-- +2.13.1 + diff --git a/deps/patches/llvm-VNCoercion-template.patch b/deps/patches/llvm-VNCoercion-template.patch new file mode 100644 index 0000000000000..6aa87a1cf3a33 --- /dev/null +++ b/deps/patches/llvm-VNCoercion-template.patch @@ -0,0 +1,410 @@ +From 67cb3073f40c0d02334e161a1c9c749be777f411 Mon Sep 17 00:00:00 2001 +From: Daniel Berlin +Date: Mon, 20 Mar 2017 16:08:29 +0000 +Subject: [PATCH 7/7] Templatize parts of VNCoercion, and add constant-only + versions of the functions to be used in NewGVN. NFCI. + +Summary: +This is ground work for the changes to enable coercion in NewGVN. +GVN doesn't care if they end up constant because it eliminates as it goes. +NewGVN cares. + +IRBuilder and ConstantFolder deliberately present the same interface, +so we use this to our advantage to templatize our functions to make +them either constant only or not. + +Reviewers: davide + +Subscribers: llvm-commits, Prazek + +Differential Revision: https://reviews.llvm.org/D30928 + +git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@298262 91177308-0d34-0410-b5e6-96231b3b80d8 +--- + include/llvm/Transforms/Utils/VNCoercion.h | 14 ++- + lib/Transforms/Scalar/GVN.cpp | 2 +- + lib/Transforms/Utils/VNCoercion.cpp | 177 ++++++++++++++++++----------- + 3 files changed, 124 insertions(+), 69 deletions(-) + +diff --git a/include/llvm/Transforms/Utils/VNCoercion.h b/include/llvm/Transforms/Utils/VNCoercion.h +index edc63ca38db..1baa9b66e49 100644 +--- a/include/llvm/Transforms/Utils/VNCoercion.h ++++ b/include/llvm/Transforms/Utils/VNCoercion.h +@@ -76,13 +76,21 @@ int analyzeLoadFromClobberingMemInst(Type *LoadTy, Value *LoadPtr, + /// inserts instructions to do so at InsertPt, and returns the extracted value. + Value *getStoreValueForLoad(Value *SrcVal, unsigned Offset, Type *LoadTy, + Instruction *InsertPt, const DataLayout &DL); ++// This is the same as getStoreValueForLoad, except it performs no insertion ++// It only allows constant inputs. ++Constant *getConstantStoreValueForLoad(Constant *SrcVal, unsigned Offset, ++ Type *LoadTy, const DataLayout &DL); + + /// If analyzeLoadFromClobberingLoad returned an offset, this function can be + /// used to actually perform the extraction of the bits from the load, including + /// any necessary load widening. It inserts instructions to do so at InsertPt, + /// and returns the extracted value. + Value *getLoadValueForLoad(LoadInst *SrcVal, unsigned Offset, Type *LoadTy, +- Instruction *InsertPt); ++ Instruction *InsertPt, const DataLayout &DL); ++// This is the same as getLoadValueForLoad, except it is given the load value as ++// a constant. It returns nullptr if it would require widening the load. ++Constant *getConstantLoadValueForLoad(Constant *SrcVal, unsigned Offset, ++ Type *LoadTy, const DataLayout &DL); + + /// If analyzeLoadFromClobberingMemInst returned an offset, this function can be + /// used to actually perform the extraction of the bits from the memory +@@ -91,6 +99,10 @@ Value *getLoadValueForLoad(LoadInst *SrcVal, unsigned Offset, Type *LoadTy, + Value *getMemInstValueForLoad(MemIntrinsic *SrcInst, unsigned Offset, + Type *LoadTy, Instruction *InsertPt, + const DataLayout &DL); ++// This is the same as getStoreValueForLoad, except it performs no insertion. ++// It returns nullptr if it cannot produce a constant. ++Constant *getConstantMemInstValueForLoad(MemIntrinsic *SrcInst, unsigned Offset, ++ Type *LoadTy, const DataLayout &DL); + } + } + #endif +diff --git a/lib/Transforms/Scalar/GVN.cpp b/lib/Transforms/Scalar/GVN.cpp +index 7b8948c065b..91118ee7e39 100644 +--- a/lib/Transforms/Scalar/GVN.cpp ++++ b/lib/Transforms/Scalar/GVN.cpp +@@ -748,7 +748,7 @@ Value *AvailableValue::MaterializeAdjustedValue(LoadInst *LI, + if (Load->getType() == LoadTy && Offset == 0) { + Res = Load; + } else { +- Res = getLoadValueForLoad(Load, Offset, LoadTy, InsertPt); ++ Res = getLoadValueForLoad(Load, Offset, LoadTy, InsertPt, DL); + // We would like to use gvn.markInstructionForDeletion here, but we can't + // because the load is already memoized into the leader map table that GVN + // tracks. It is potentially possible to remove the load from the table, +diff --git a/lib/Transforms/Utils/VNCoercion.cpp b/lib/Transforms/Utils/VNCoercion.cpp +index 6fa9aca8436..60d9ede2c48 100644 +--- a/lib/Transforms/Utils/VNCoercion.cpp ++++ b/lib/Transforms/Utils/VNCoercion.cpp +@@ -32,17 +32,12 @@ bool canCoerceMustAliasedValueToLoad(Value *StoredVal, Type *LoadTy, + return true; + } + +-/// If we saw a store of a value to memory, and +-/// then a load from a must-aliased pointer of a different type, try to coerce +-/// the stored value. LoadedTy is the type of the load we want to replace. +-/// IRB is IRBuilder used to insert new instructions. +-/// +-/// If we can't do it, return null. +-Value *coerceAvailableValueToLoadType(Value *StoredVal, Type *LoadedTy, +- IRBuilder<> &IRB, const DataLayout &DL) { ++template ++static T *coerceAvailableValueToLoadTypeHelper(T *StoredVal, Type *LoadedTy, ++ HelperClass &Helper, ++ const DataLayout &DL) { + assert(canCoerceMustAliasedValueToLoad(StoredVal, LoadedTy, DL) && + "precondition violation - materialization can't fail"); +- + if (auto *C = dyn_cast(StoredVal)) + if (auto *FoldedStoredVal = ConstantFoldConstant(C, DL)) + StoredVal = FoldedStoredVal; +@@ -58,12 +53,12 @@ Value *coerceAvailableValueToLoadType(Value *StoredVal, Type *LoadedTy, + // Pointer to Pointer -> use bitcast. + if (StoredValTy->getScalarType()->isPointerTy() && + LoadedTy->getScalarType()->isPointerTy()) { +- StoredVal = IRB.CreateBitCast(StoredVal, LoadedTy); ++ StoredVal = Helper.CreateBitCast(StoredVal, LoadedTy); + } else { + // Convert source pointers to integers, which can be bitcast. + if (StoredValTy->getScalarType()->isPointerTy()) { + StoredValTy = DL.getIntPtrType(StoredValTy); +- StoredVal = IRB.CreatePtrToInt(StoredVal, StoredValTy); ++ StoredVal = Helper.CreatePtrToInt(StoredVal, StoredValTy); + } + + Type *TypeToCastTo = LoadedTy; +@@ -71,11 +66,11 @@ Value *coerceAvailableValueToLoadType(Value *StoredVal, Type *LoadedTy, + TypeToCastTo = DL.getIntPtrType(TypeToCastTo); + + if (StoredValTy != TypeToCastTo) +- StoredVal = IRB.CreateBitCast(StoredVal, TypeToCastTo); ++ StoredVal = Helper.CreateBitCast(StoredVal, TypeToCastTo); + + // Cast to pointer if the load needs a pointer type. + if (LoadedTy->getScalarType()->isPointerTy()) +- StoredVal = IRB.CreateIntToPtr(StoredVal, LoadedTy); ++ StoredVal = Helper.CreateIntToPtr(StoredVal, LoadedTy); + } + + if (auto *C = dyn_cast(StoredVal)) +@@ -84,7 +79,6 @@ Value *coerceAvailableValueToLoadType(Value *StoredVal, Type *LoadedTy, + + return StoredVal; + } +- + // If the loaded value is smaller than the available value, then we can + // extract out a piece from it. If the available value is too small, then we + // can't do anything. +@@ -94,13 +88,13 @@ Value *coerceAvailableValueToLoadType(Value *StoredVal, Type *LoadedTy, + // Convert source pointers to integers, which can be manipulated. + if (StoredValTy->getScalarType()->isPointerTy()) { + StoredValTy = DL.getIntPtrType(StoredValTy); +- StoredVal = IRB.CreatePtrToInt(StoredVal, StoredValTy); ++ StoredVal = Helper.CreatePtrToInt(StoredVal, StoredValTy); + } + + // Convert vectors and fp to integer, which can be manipulated. + if (!StoredValTy->isIntegerTy()) { + StoredValTy = IntegerType::get(StoredValTy->getContext(), StoredValSize); +- StoredVal = IRB.CreateBitCast(StoredVal, StoredValTy); ++ StoredVal = Helper.CreateBitCast(StoredVal, StoredValTy); + } + + // If this is a big-endian system, we need to shift the value down to the low +@@ -108,20 +102,21 @@ Value *coerceAvailableValueToLoadType(Value *StoredVal, Type *LoadedTy, + if (DL.isBigEndian()) { + uint64_t ShiftAmt = DL.getTypeStoreSizeInBits(StoredValTy) - + DL.getTypeStoreSizeInBits(LoadedTy); +- StoredVal = IRB.CreateLShr(StoredVal, ShiftAmt, "tmp"); ++ StoredVal = Helper.CreateLShr( ++ StoredVal, ConstantInt::get(StoredVal->getType(), ShiftAmt)); + } + + // Truncate the integer to the right size now. + Type *NewIntTy = IntegerType::get(StoredValTy->getContext(), LoadedValSize); +- StoredVal = IRB.CreateTrunc(StoredVal, NewIntTy, "trunc"); ++ StoredVal = Helper.CreateTruncOrBitCast(StoredVal, NewIntTy); + + if (LoadedTy != NewIntTy) { + // If the result is a pointer, inttoptr. + if (LoadedTy->getScalarType()->isPointerTy()) +- StoredVal = IRB.CreateIntToPtr(StoredVal, LoadedTy, "inttoptr"); ++ StoredVal = Helper.CreateIntToPtr(StoredVal, LoadedTy); + else + // Otherwise, bitcast. +- StoredVal = IRB.CreateBitCast(StoredVal, LoadedTy, "bitcast"); ++ StoredVal = Helper.CreateBitCast(StoredVal, LoadedTy); + } + + if (auto *C = dyn_cast(StoredVal)) +@@ -131,10 +126,21 @@ Value *coerceAvailableValueToLoadType(Value *StoredVal, Type *LoadedTy, + return StoredVal; + } + +-/// This function is called when we have a +-/// memdep query of a load that ends up being a clobbering memory write (store, +-/// memset, memcpy, memmove). This means that the write *may* provide bits used +-/// by the load but we can't be sure because the pointers don't mustalias. ++/// If we saw a store of a value to memory, and ++/// then a load from a must-aliased pointer of a different type, try to coerce ++/// the stored value. LoadedTy is the type of the load we want to replace. ++/// IRB is IRBuilder used to insert new instructions. ++/// ++/// If we can't do it, return null. ++Value *coerceAvailableValueToLoadType(Value *StoredVal, Type *LoadedTy, ++ IRBuilder<> &IRB, const DataLayout &DL) { ++ return coerceAvailableValueToLoadTypeHelper(StoredVal, LoadedTy, IRB, DL); ++} ++ ++/// This function is called when we have a memdep query of a load that ends up ++/// being a clobbering memory write (store, memset, memcpy, memmove). This ++/// means that the write *may* provide bits used by the load but we can't be ++/// sure because the pointers don't must-alias. + /// + /// Check this case to see if there is anything more we can do before we give + /// up. This returns -1 if we have to give up, or a byte number in the stored +@@ -291,13 +297,10 @@ int analyzeLoadFromClobberingMemInst(Type *LoadTy, Value *LoadPtr, + return -1; + } + +-/// This function is called when we have a +-/// memdep query of a load that ends up being a clobbering store. This means +-/// that the store provides bits used by the load but we the pointers don't +-/// mustalias. Check this case to see if there is anything more we can do +-/// before we give up. +-Value *getStoreValueForLoad(Value *SrcVal, unsigned Offset, Type *LoadTy, +- Instruction *InsertPt, const DataLayout &DL) { ++template ++static T *getStoreValueForLoadHelper(T *SrcVal, unsigned Offset, Type *LoadTy, ++ HelperClass &Helper, ++ const DataLayout &DL) { + LLVMContext &Ctx = SrcVal->getType()->getContext(); + + // If two pointers are in the same address space, they have the same size, +@@ -311,17 +314,12 @@ Value *getStoreValueForLoad(Value *SrcVal, unsigned Offset, Type *LoadTy, + + uint64_t StoreSize = (DL.getTypeSizeInBits(SrcVal->getType()) + 7) / 8; + uint64_t LoadSize = (DL.getTypeSizeInBits(LoadTy) + 7) / 8; +- +- IRBuilder<> Builder(InsertPt); +- + // Compute which bits of the stored value are being used by the load. Convert + // to an integer type to start with. + if (SrcVal->getType()->getScalarType()->isPointerTy()) +- SrcVal = +- Builder.CreatePtrToInt(SrcVal, DL.getIntPtrType(SrcVal->getType())); ++ SrcVal = Helper.CreatePtrToInt(SrcVal, DL.getIntPtrType(SrcVal->getType())); + if (!SrcVal->getType()->isIntegerTy()) +- SrcVal = +- Builder.CreateBitCast(SrcVal, IntegerType::get(Ctx, StoreSize * 8)); ++ SrcVal = Helper.CreateBitCast(SrcVal, IntegerType::get(Ctx, StoreSize * 8)); + + // Shift the bits to the least significant depending on endianness. + unsigned ShiftAmt; +@@ -329,25 +327,42 @@ Value *getStoreValueForLoad(Value *SrcVal, unsigned Offset, Type *LoadTy, + ShiftAmt = Offset * 8; + else + ShiftAmt = (StoreSize - LoadSize - Offset) * 8; +- + if (ShiftAmt) +- SrcVal = Builder.CreateLShr(SrcVal, ShiftAmt); ++ SrcVal = Helper.CreateLShr(SrcVal, ++ ConstantInt::get(SrcVal->getType(), ShiftAmt)); + + if (LoadSize != StoreSize) +- SrcVal = Builder.CreateTrunc(SrcVal, IntegerType::get(Ctx, LoadSize * 8)); ++ SrcVal = Helper.CreateTruncOrBitCast(SrcVal, ++ IntegerType::get(Ctx, LoadSize * 8)); ++ return SrcVal; ++} ++ ++/// This function is called when we have a memdep query of a load that ends up ++/// being a clobbering store. This means that the store provides bits used by ++/// the load but the pointers don't must-alias. Check this case to see if ++/// there is anything more we can do before we give up. ++Value *getStoreValueForLoad(Value *SrcVal, unsigned Offset, Type *LoadTy, ++ Instruction *InsertPt, const DataLayout &DL) { + +- return coerceAvailableValueToLoadType(SrcVal, LoadTy, Builder, DL); ++ IRBuilder<> Builder(InsertPt); ++ SrcVal = getStoreValueForLoadHelper(SrcVal, Offset, LoadTy, Builder, DL); ++ return coerceAvailableValueToLoadTypeHelper(SrcVal, LoadTy, Builder, DL); + } + +-/// This function is called when we have a +-/// memdep query of a load that ends up being a clobbering load. This means +-/// that the load *may* provide bits used by the load but we can't be sure +-/// because the pointers don't mustalias. Check this case to see if there is +-/// anything more we can do before we give up. +-Value *getLoadValueForLoad(LoadInst *SrcVal, unsigned Offset, Type *LoadTy, +- Instruction *InsertPt) { ++Constant *getConstantStoreValueForLoad(Constant *SrcVal, unsigned Offset, ++ Type *LoadTy, const DataLayout &DL) { ++ ConstantFolder F; ++ SrcVal = getStoreValueForLoadHelper(SrcVal, Offset, LoadTy, F, DL); ++ return coerceAvailableValueToLoadTypeHelper(SrcVal, LoadTy, F, DL); ++} + +- const DataLayout &DL = SrcVal->getModule()->getDataLayout(); ++/// This function is called when we have a memdep query of a load that ends up ++/// being a clobbering load. This means that the load *may* provide bits used ++/// by the load but we can't be sure because the pointers don't must-alias. ++/// Check this case to see if there is anything more we can do before we give ++/// up. ++Value *getLoadValueForLoad(LoadInst *SrcVal, unsigned Offset, Type *LoadTy, ++ Instruction *InsertPt, const DataLayout &DL) { + // If Offset+LoadTy exceeds the size of SrcVal, then we must be wanting to + // widen SrcVal out to a larger load. + unsigned SrcValStoreSize = DL.getTypeStoreSize(SrcVal->getType()); +@@ -362,7 +377,6 @@ Value *getLoadValueForLoad(LoadInst *SrcVal, unsigned Offset, Type *LoadTy, + NewLoadSize = NextPowerOf2(NewLoadSize); + + Value *PtrVal = SrcVal->getPointerOperand(); +- + // Insert the new load after the old load. This ensures that subsequent + // memdep queries will find the new load. We can't easily remove the old + // load completely because it is already in the value numbering table. +@@ -393,44 +407,51 @@ Value *getLoadValueForLoad(LoadInst *SrcVal, unsigned Offset, Type *LoadTy, + return getStoreValueForLoad(SrcVal, Offset, LoadTy, InsertPt, DL); + } + +-/// This function is called when we have a +-/// memdep query of a load that ends up being a clobbering mem intrinsic. +-Value *getMemInstValueForLoad(MemIntrinsic *SrcInst, unsigned Offset, +- Type *LoadTy, Instruction *InsertPt, +- const DataLayout &DL) { ++Constant *getConstantLoadValueForLoad(Constant *SrcVal, unsigned Offset, ++ Type *LoadTy, const DataLayout &DL) { ++ unsigned SrcValStoreSize = DL.getTypeStoreSize(SrcVal->getType()); ++ unsigned LoadSize = DL.getTypeStoreSize(LoadTy); ++ if (Offset + LoadSize > SrcValStoreSize) ++ return nullptr; ++ return getConstantStoreValueForLoad(SrcVal, Offset, LoadTy, DL); ++} ++ ++template ++T *getMemInstValueForLoadHelper(MemIntrinsic *SrcInst, unsigned Offset, ++ Type *LoadTy, HelperClass &Helper, ++ const DataLayout &DL) { + LLVMContext &Ctx = LoadTy->getContext(); + uint64_t LoadSize = DL.getTypeSizeInBits(LoadTy) / 8; + +- IRBuilder<> Builder(InsertPt); +- + // We know that this method is only called when the mem transfer fully + // provides the bits for the load. + if (MemSetInst *MSI = dyn_cast(SrcInst)) { + // memset(P, 'x', 1234) -> splat('x'), even if x is a variable, and + // independently of what the offset is. +- Value *Val = MSI->getValue(); ++ T *Val = cast(MSI->getValue()); + if (LoadSize != 1) +- Val = Builder.CreateZExt(Val, IntegerType::get(Ctx, LoadSize * 8)); +- +- Value *OneElt = Val; ++ Val = ++ Helper.CreateZExtOrBitCast(Val, IntegerType::get(Ctx, LoadSize * 8)); ++ T *OneElt = Val; + + // Splat the value out to the right number of bits. + for (unsigned NumBytesSet = 1; NumBytesSet != LoadSize;) { + // If we can double the number of bytes set, do it. + if (NumBytesSet * 2 <= LoadSize) { +- Value *ShVal = Builder.CreateShl(Val, NumBytesSet * 8); +- Val = Builder.CreateOr(Val, ShVal); ++ T *ShVal = Helper.CreateShl( ++ Val, ConstantInt::get(Val->getType(), NumBytesSet * 8)); ++ Val = Helper.CreateOr(Val, ShVal); + NumBytesSet <<= 1; + continue; + } + + // Otherwise insert one byte at a time. +- Value *ShVal = Builder.CreateShl(Val, 1 * 8); +- Val = Builder.CreateOr(OneElt, ShVal); ++ T *ShVal = Helper.CreateShl(Val, ConstantInt::get(Val->getType(), 1 * 8)); ++ Val = Helper.CreateOr(OneElt, ShVal); + ++NumBytesSet; + } + +- return coerceAvailableValueToLoadType(Val, LoadTy, Builder, DL); ++ return coerceAvailableValueToLoadTypeHelper(Val, LoadTy, Helper, DL); + } + + // Otherwise, this is a memcpy/memmove from a constant global. +@@ -449,5 +470,27 @@ Value *getMemInstValueForLoad(MemIntrinsic *SrcInst, unsigned Offset, + Src = ConstantExpr::getBitCast(Src, PointerType::get(LoadTy, AS)); + return ConstantFoldLoadFromConstPtr(Src, LoadTy, DL); + } ++ ++/// This function is called when we have a ++/// memdep query of a load that ends up being a clobbering mem intrinsic. ++Value *getMemInstValueForLoad(MemIntrinsic *SrcInst, unsigned Offset, ++ Type *LoadTy, Instruction *InsertPt, ++ const DataLayout &DL) { ++ IRBuilder<> Builder(InsertPt); ++ return getMemInstValueForLoadHelper>(SrcInst, Offset, ++ LoadTy, Builder, DL); ++} ++ ++Constant *getConstantMemInstValueForLoad(MemIntrinsic *SrcInst, unsigned Offset, ++ Type *LoadTy, const DataLayout &DL) { ++ // The only case analyzeLoadFromClobberingMemInst cannot be converted to a ++ // constant is when it's a memset of a non-constant. ++ if (auto *MSI = dyn_cast(SrcInst)) ++ if (!isa(MSI->getValue())) ++ return nullptr; ++ ConstantFolder F; ++ return getMemInstValueForLoadHelper(SrcInst, Offset, ++ LoadTy, F, DL); ++} + } // namespace VNCoercion + } // namespace llvm +-- +2.13.1 + diff --git a/deps/patches/llvm-Yet-another-fix.patch b/deps/patches/llvm-Yet-another-fix.patch new file mode 100644 index 0000000000000..39823be1cd918 --- /dev/null +++ b/deps/patches/llvm-Yet-another-fix.patch @@ -0,0 +1,40 @@ +From e92be5eb5c60dfdeb5d41d81c82f0aca0c1e4aa9 Mon Sep 17 00:00:00 2001 +From: Yichao Yu +Date: Sat, 17 Jun 2017 17:29:53 -0400 +Subject: [PATCH] 4.0 fix + +--- + lib/CodeGen/CodeGenPrepare.cpp | 17 +++++++++++++++++ + 1 file changed, 17 insertions(+) + +diff --git a/lib/CodeGen/CodeGenPrepare.cpp b/lib/CodeGen/CodeGenPrepare.cpp +index 44d6b3e264c..4177819e989 100644 +--- a/lib/CodeGen/CodeGenPrepare.cpp ++++ b/lib/CodeGen/CodeGenPrepare.cpp +@@ -4067,6 +4067,23 @@ bool CodeGenPrepare::optimizeMemoryInst(Instruction *MemoryInst, Value *Addr, + // non-integral pointers, so in that case bail out now. + if (DL->isNonIntegralPointerType(Addr->getType())) + return false; ++ if (AddrMode.BaseReg) { ++ Type *BaseTy = AddrMode.BaseReg->getType(); ++ if (BaseTy->isPointerTy() && DL->isNonIntegralPointerType(BaseTy)) { ++ return false; ++ } ++ } ++ if (AddrMode.Scale) { ++ Type *ScaleTy = AddrMode.ScaledReg->getType(); ++ if (ScaleTy->isPointerTy() && DL->isNonIntegralPointerType(ScaleTy)) { ++ return false; ++ } ++ } ++ if (AddrMode.BaseGV) { ++ if (DL->isNonIntegralPointerType(AddrMode.BaseGV->getType())) { ++ return false; ++ } ++ } + + DEBUG(dbgs() << "CGP: SINKING nonlocal addrmode: " << AddrMode << " for " + << *MemoryInst << "\n"); +-- +2.13.1 + diff --git a/deps/patches/llvm-arm-fix-prel31.patch b/deps/patches/llvm-arm-fix-prel31.patch new file mode 100644 index 0000000000000..a823ce62b0cdb --- /dev/null +++ b/deps/patches/llvm-arm-fix-prel31.patch @@ -0,0 +1,60 @@ +From 6cef9adffcf9af3c632e58e0d7d4d6e1d0525980 Mon Sep 17 00:00:00 2001 +From: Yichao Yu +Date: Thu, 29 Sep 2016 22:41:57 -0400 +Subject: [PATCH] Fix PREL31 relocation on ARM + +This is a 31bits relative relocation instead of a 32bits absolute relocation. +--- + lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp | 4 ++++ + .../RuntimeDyld/ARM/ELF_ARM_EXIDX_relocations.s | 23 ++++++++++++++++++++++ + 2 files changed, 27 insertions(+) + create mode 100644 test/ExecutionEngine/RuntimeDyld/ARM/ELF_ARM_EXIDX_relocations.s + +diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp +index 6929732..2e0d168 100644 +--- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp ++++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp +@@ -463,7 +463,11 @@ void RuntimeDyldELF::resolveARMRelocation(const SectionEntry &Section, + + case ELF::R_ARM_NONE: + break; ++ // Write a 31bit signed offset + case ELF::R_ARM_PREL31: ++ *TargetPtr &= 0x80000000; ++ *TargetPtr |= (Value - FinalAddress) & ~0x80000000; ++ break; + case ELF::R_ARM_TARGET1: + case ELF::R_ARM_ABS32: + *TargetPtr = Value; +diff --git a/test/ExecutionEngine/RuntimeDyld/ARM/ELF_ARM_EXIDX_relocations.s b/test/ExecutionEngine/RuntimeDyld/ARM/ELF_ARM_EXIDX_relocations.s +new file mode 100644 +index 0000000..eb07b00 +--- /dev/null ++++ b/test/ExecutionEngine/RuntimeDyld/ARM/ELF_ARM_EXIDX_relocations.s +@@ -0,0 +1,23 @@ ++# RUN: llvm-mc -triple=arm-linux-gnueabihf -filetype=obj -o %T/reloc.o %s ++# RUN: llvm-rtdyld -triple=arm-linux-gnueabihf -verify -map-section reloc.o,.ARM.exidx=0x6000 -map-section reloc.o,.text=0x4000 -dummy-extern __aeabi_unwind_cpp_pr0=0x1234 -check=%s %T/reloc.o ++ ++ .text ++ .syntax unified ++ .eabi_attribute 67, "2.09" @ Tag_conformance ++ .cpu cortex-a8 ++ .fpu neon ++ .file "reloc.c" ++ .globl g ++ .align 2 ++ .type g,%function ++g: ++ .fnstart ++ movw r0, #1 ++ bx lr ++ .Lfunc_end0: ++ .size g, .Lfunc_end0-g ++ .fnend ++ ++# rtdyld-check: *{4}(section_addr(reloc.o, .ARM.exidx)) = (g - (section_addr(reloc.o, .ARM.exidx))) & 0x7fffffff ++# Compat unwind info: finish(0xb0), finish(0xb0), finish(0xb0) ++# rtdyld-check: *{4}(section_addr(reloc.o, .ARM.exidx) + 0x4) = 0x80b0b0b0 +-- +2.10.0 + diff --git a/deps/patches/llvm-loadcse-addrspace_4.0.patch b/deps/patches/llvm-loadcse-addrspace_4.0.patch new file mode 100644 index 0000000000000..2728d6830aab0 --- /dev/null +++ b/deps/patches/llvm-loadcse-addrspace_4.0.patch @@ -0,0 +1,61 @@ +From 01ae2614aa184fcf88b0880f5944a23da6f215db Mon Sep 17 00:00:00 2001 +From: Yichao Yu +Date: Sun, 18 Jun 2017 16:45:38 -0400 +Subject: [PATCH] Disable LoadCSE and Store forwarding between different + address space or between non-integral pointer and integers. + +--- + lib/Analysis/Loads.cpp | 30 ++++++++++++++++++++++++++++++ + 1 file changed, 30 insertions(+) + +diff --git a/lib/Analysis/Loads.cpp b/lib/Analysis/Loads.cpp +index e46541e6538..971ce37a4a5 100644 +--- a/lib/Analysis/Loads.cpp ++++ b/lib/Analysis/Loads.cpp +@@ -362,6 +362,21 @@ Value *llvm::FindAvailableLoadedValue(LoadInst *Load, + if (LI->isAtomic() < Load->isAtomic()) + return nullptr; + ++ if (Load->getType()->isPointerTy()) { ++ PointerType *Ty1 = cast(Load->getType()); ++ if (PointerType *Ty2 = dyn_cast(LI->getType())) { ++ if (Ty1->getAddressSpace() != Ty2->getAddressSpace()) { ++ return nullptr; ++ } ++ } ++ else if (DL.isNonIntegralPointerType(Ty1)) { ++ return nullptr; ++ } ++ } ++ else if (DL.isNonIntegralPointerType(LI->getType())) { ++ return nullptr; ++ } ++ + if (IsLoadCSE) + *IsLoadCSE = true; + return LI; +@@ -381,6 +396,21 @@ Value *llvm::FindAvailableLoadedValue(LoadInst *Load, + if (SI->isAtomic() < Load->isAtomic()) + return nullptr; + ++ if (Load->getType()->isPointerTy()) { ++ PointerType *Ty1 = cast(Load->getType()); ++ if (PointerType *Ty2 = dyn_cast(SI->getValueOperand()->getType())) { ++ if (Ty1->getAddressSpace() != Ty2->getAddressSpace()) { ++ return nullptr; ++ } ++ } ++ else if (DL.isNonIntegralPointerType(Ty1)) { ++ return nullptr; ++ } ++ } ++ else if (DL.isNonIntegralPointerType(SI->getValueOperand()->getType())) { ++ return nullptr; ++ } ++ + if (IsLoadCSE) + *IsLoadCSE = false; + return SI->getOperand(0); +-- +2.13.1 + diff --git a/deps/patches/llvm-loadcse-addrspace_5.0.patch b/deps/patches/llvm-loadcse-addrspace_5.0.patch new file mode 100644 index 0000000000000..fccb8bb37281e --- /dev/null +++ b/deps/patches/llvm-loadcse-addrspace_5.0.patch @@ -0,0 +1,104 @@ +From b252987fe34a314524428d27a85a87fdd746e0b5 Mon Sep 17 00:00:00 2001 +From: Yichao Yu +Date: Sun, 18 Jun 2017 16:45:38 -0400 +Subject: [PATCH 2/4] Disable LoadCSE and Store forwarding between different + address space or between non-integral pointer and integers. + +--- + lib/Analysis/Loads.cpp | 30 +++++++++++++++++++ + .../InstCombine/non-integral-pointers.ll | 34 ++++++++++++++++++++++ + 2 files changed, 64 insertions(+) + +diff --git a/lib/Analysis/Loads.cpp b/lib/Analysis/Loads.cpp +index 591b0fc481d..e9c8be82b03 100644 +--- a/lib/Analysis/Loads.cpp ++++ b/lib/Analysis/Loads.cpp +@@ -380,6 +380,21 @@ Value *llvm::FindAvailablePtrLoadStore(Value *Ptr, Type *AccessTy, + if (LI->isAtomic() < AtLeastAtomic) + return nullptr; + ++ if (AccessTy->isPointerTy()) { ++ PointerType *Ty1 = cast(AccessTy); ++ if (PointerType *Ty2 = dyn_cast(LI->getType())) { ++ if (Ty1->getAddressSpace() != Ty2->getAddressSpace()) { ++ return nullptr; ++ } ++ } ++ else if (DL.isNonIntegralPointerType(Ty1)) { ++ return nullptr; ++ } ++ } ++ else if (DL.isNonIntegralPointerType(LI->getType())) { ++ return nullptr; ++ } ++ + if (IsLoadCSE) + *IsLoadCSE = true; + return LI; +@@ -399,6 +414,21 @@ Value *llvm::FindAvailablePtrLoadStore(Value *Ptr, Type *AccessTy, + if (SI->isAtomic() < AtLeastAtomic) + return nullptr; + ++ if (AccessTy->isPointerTy()) { ++ PointerType *Ty1 = cast(AccessTy); ++ if (PointerType *Ty2 = dyn_cast(SI->getValueOperand()->getType())) { ++ if (Ty1->getAddressSpace() != Ty2->getAddressSpace()) { ++ return nullptr; ++ } ++ } ++ else if (DL.isNonIntegralPointerType(Ty1)) { ++ return nullptr; ++ } ++ } ++ else if (DL.isNonIntegralPointerType(SI->getValueOperand()->getType())) { ++ return nullptr; ++ } ++ + if (IsLoadCSE) + *IsLoadCSE = false; + return SI->getOperand(0); +diff --git a/test/Transforms/InstCombine/non-integral-pointers.ll b/test/Transforms/InstCombine/non-integral-pointers.ll +index 4f54fe6737d..96a2b2edaf1 100644 +--- a/test/Transforms/InstCombine/non-integral-pointers.ll ++++ b/test/Transforms/InstCombine/non-integral-pointers.ll +@@ -46,3 +46,37 @@ entry: + store i8 addrspace(3)* %val, i8 addrspace(3)** %ptr1 + ret void + } ++ ++define i64 @g(i8 addrspace(4)** %gp) { ++ ; CHECK-LABEL: @g( ++ ; CHECK: load ++ %.pre = load i8 addrspace(4)*, i8 addrspace(4)** %gp, align 8 ++ %v74 = call i8 addrspace(4)* @alloc() ++ %v75 = addrspacecast i8 addrspace(4)* %v74 to i8* ++ %v76 = bitcast i8* %v75 to i8 addrspace(4)** ++ %v77 = getelementptr i8 addrspace(4)*, i8 addrspace(4)** %v76, i64 -1 ++ ; CHECK: store ++ store i8 addrspace(4)* %.pre, i8 addrspace(4)** %v77, align 8 ++ %v80 = bitcast i8 addrspace(4)** %v77 to i64* ++ ; CHECK: load ++ ; CHECK-NOT: ptrtoint ++ %v81 = load i64, i64* %v80, align 8 ++ ret i64 %v81 ++} ++ ++define i64 @g2(i8* addrspace(4)* %gp) { ++ ; CHECK-LABEL: @g2( ++ ; CHECK: load ++ %.pre = load i8*, i8* addrspace(4)* %gp, align 8 ++ %v74 = call i8 addrspace(4)* @alloc() ++ %v76 = bitcast i8 addrspace(4)* %v74 to i8* addrspace(4)* ++ %v77 = getelementptr i8*, i8* addrspace(4)* %v76, i64 -1 ++ ; CHECK: store ++ store i8* %.pre, i8* addrspace(4)* %v77, align 8 ++ %v80 = bitcast i8* addrspace(4)* %v77 to i64 addrspace(4)* ++ ; CHECK-NOT: store ++ %v81 = load i64, i64 addrspace(4)* %v80, align 8 ++ ret i64 %v81 ++} ++ ++declare i8 addrspace(4)* @alloc() +-- +2.14.1 + diff --git a/deps/patches/llvm-rL293230-icc17-cmake.patch b/deps/patches/llvm-rL293230-icc17-cmake.patch new file mode 100644 index 0000000000000..85b2a2a0b1b9d --- /dev/null +++ b/deps/patches/llvm-rL293230-icc17-cmake.patch @@ -0,0 +1,35 @@ +From eca8aa608d962e09ea9710670f1c412f608a6f12 Mon Sep 17 00:00:00 2001 +From: Yichao Yu +Date: Thu, 26 Jan 2017 23:50:18 +0000 +Subject: [PATCH] CMake is funky on detecting Intel 17 as GCC compatible. + +Summary: This adds a fallback in case that the Intel compiler is failed to be detected correctly. + +Reviewers: chapuni + +Reviewed By: chapuni + +Subscribers: llvm-commits, mgorny + +Differential Revision: https://reviews.llvm.org/D27610 + +git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@293230 91177308-0d34-0410-b5e6-96231b3b80d8 +--- + cmake/modules/DetermineGCCCompatible.cmake | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/cmake/modules/DetermineGCCCompatible.cmake b/cmake/modules/DetermineGCCCompatible.cmake +index 1bf15fcba72..1369ebe9d0e 100644 +--- a/cmake/modules/DetermineGCCCompatible.cmake ++++ b/cmake/modules/DetermineGCCCompatible.cmake +@@ -7,5 +7,7 @@ if(NOT DEFINED LLVM_COMPILER_IS_GCC_COMPATIBLE) + set(LLVM_COMPILER_IS_GCC_COMPATIBLE OFF) + elseif( "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang" ) + set(LLVM_COMPILER_IS_GCC_COMPATIBLE ON) ++ elseif( "${CMAKE_CXX_COMPILER_ID}" MATCHES "Intel" ) ++ set(LLVM_COMPILER_IS_GCC_COMPATIBLE ON) + endif() + endif() +-- +2.11.0 + diff --git a/deps/patches/llvm-rL326967-aligned-load.patch b/deps/patches/llvm-rL326967-aligned-load.patch deleted file mode 100644 index 62c112306a292..0000000000000 --- a/deps/patches/llvm-rL326967-aligned-load.patch +++ /dev/null @@ -1,301 +0,0 @@ -commit b398d8e1fa5a5a914957fa22d0a64db97f6c265e -Author: Craig Topper -Date: Thu Mar 8 00:21:17 2018 +0000 - - [X86] Fix some isel patterns that used aligned vector load instructions with unaligned predicates. - - These patterns weren't checking the alignment of the load, but were using the aligned instructions. This will cause a GP fault if the data isn't aligned. - - I believe these were introduced in r312450. - - git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@326967 91177308-0d34-0410-b5e6-96231b3b80d8 - -diff --git a/lib/Target/X86/X86InstrVecCompiler.td b/lib/Target/X86/X86InstrVecCompiler.td -index db3dfe56531..50c7763a2c3 100644 ---- a/lib/Target/X86/X86InstrVecCompiler.td -+++ b/lib/Target/X86/X86InstrVecCompiler.td -@@ -261,10 +261,10 @@ let Predicates = [HasVLX] in { - // will zero the upper bits. - // TODO: Is there a safe way to detect whether the producing instruction - // already zeroed the upper bits? --multiclass subvector_zero_lowering { -+multiclass subvector_zero_lowering { - def : Pat<(DstTy (insert_subvector (bitconvert (ZeroTy immAllZerosV)), - (SrcTy RC:$src), (iPTR 0))), - (SUBREG_TO_REG (i64 0), -@@ -274,91 +274,91 @@ multiclass subvector_zero_lowering("VMOV"#MoveStr#"rm") addr:$src), SubIdx)>; -+ (!cast("VMOV"#LoadStr#"rm") addr:$src), SubIdx)>; - } - - let Predicates = [HasAVX, NoVLX] in { -- defm : subvector_zero_lowering<"APD", VR128, v4f64, v2f64, v8i32, loadv2f64, -- sub_xmm>; -- defm : subvector_zero_lowering<"APS", VR128, v8f32, v4f32, v8i32, loadv4f32, -- sub_xmm>; -- defm : subvector_zero_lowering<"DQA", VR128, v4i64, v2i64, v8i32, loadv2i64, -- sub_xmm>; -- defm : subvector_zero_lowering<"DQA", VR128, v8i32, v4i32, v8i32, loadv2i64, -- sub_xmm>; -- defm : subvector_zero_lowering<"DQA", VR128, v16i16, v8i16, v8i32, loadv2i64, -- sub_xmm>; -- defm : subvector_zero_lowering<"DQA", VR128, v32i8, v16i8, v8i32, loadv2i64, -- sub_xmm>; --} -- --let Predicates = [HasVLX] in { -- defm : subvector_zero_lowering<"APDZ128", VR128X, v4f64, v2f64, v8i32, -+ defm : subvector_zero_lowering<"APD", "UPD", VR128, v4f64, v2f64, v8i32, - loadv2f64, sub_xmm>; -- defm : subvector_zero_lowering<"APSZ128", VR128X, v8f32, v4f32, v8i32, -+ defm : subvector_zero_lowering<"APS", "UPS", VR128, v8f32, v4f32, v8i32, - loadv4f32, sub_xmm>; -- defm : subvector_zero_lowering<"DQA64Z128", VR128X, v4i64, v2i64, v8i32, -+ defm : subvector_zero_lowering<"DQA", "DQU", VR128, v4i64, v2i64, v8i32, - loadv2i64, sub_xmm>; -- defm : subvector_zero_lowering<"DQA64Z128", VR128X, v8i32, v4i32, v8i32, -+ defm : subvector_zero_lowering<"DQA", "DQU", VR128, v8i32, v4i32, v8i32, - loadv2i64, sub_xmm>; -- defm : subvector_zero_lowering<"DQA64Z128", VR128X, v16i16, v8i16, v8i32, -+ defm : subvector_zero_lowering<"DQA", "DQU", VR128, v16i16, v8i16, v8i32, - loadv2i64, sub_xmm>; -- defm : subvector_zero_lowering<"DQA64Z128", VR128X, v32i8, v16i8, v8i32, -- loadv2i64, sub_xmm>; -- -- defm : subvector_zero_lowering<"APDZ128", VR128X, v8f64, v2f64, v16i32, -- loadv2f64, sub_xmm>; -- defm : subvector_zero_lowering<"APSZ128", VR128X, v16f32, v4f32, v16i32, -- loadv4f32, sub_xmm>; -- defm : subvector_zero_lowering<"DQA64Z128", VR128X, v8i64, v2i64, v16i32, -- loadv2i64, sub_xmm>; -- defm : subvector_zero_lowering<"DQA64Z128", VR128X, v16i32, v4i32, v16i32, -- loadv2i64, sub_xmm>; -- defm : subvector_zero_lowering<"DQA64Z128", VR128X, v32i16, v8i16, v16i32, -- loadv2i64, sub_xmm>; -- defm : subvector_zero_lowering<"DQA64Z128", VR128X, v64i8, v16i8, v16i32, -+ defm : subvector_zero_lowering<"DQA", "DQU", VR128, v32i8, v16i8, v8i32, - loadv2i64, sub_xmm>; -+} - -- defm : subvector_zero_lowering<"APDZ256", VR256X, v8f64, v4f64, v16i32, -- loadv4f64, sub_ymm>; -- defm : subvector_zero_lowering<"APSZ256", VR256X, v16f32, v8f32, v16i32, -- loadv8f32, sub_ymm>; -- defm : subvector_zero_lowering<"DQA64Z256", VR256X, v8i64, v4i64, v16i32, -- loadv4i64, sub_ymm>; -- defm : subvector_zero_lowering<"DQA64Z256", VR256X, v16i32, v8i32, v16i32, -- loadv4i64, sub_ymm>; -- defm : subvector_zero_lowering<"DQA64Z256", VR256X, v32i16, v16i16, v16i32, -- loadv4i64, sub_ymm>; -- defm : subvector_zero_lowering<"DQA64Z256", VR256X, v64i8, v32i8, v16i32, -- loadv4i64, sub_ymm>; -+let Predicates = [HasVLX] in { -+ defm : subvector_zero_lowering<"APDZ128", "UPDZ128", VR128X, v4f64, -+ v2f64, v8i32, loadv2f64, sub_xmm>; -+ defm : subvector_zero_lowering<"APSZ128", "UPSZ128", VR128X, v8f32, -+ v4f32, v8i32, loadv4f32, sub_xmm>; -+ defm : subvector_zero_lowering<"DQA64Z128", "DQU64Z128", VR128X, v4i64, -+ v2i64, v8i32, loadv2i64, sub_xmm>; -+ defm : subvector_zero_lowering<"DQA64Z128", "DQU64Z128", VR128X, v8i32, -+ v4i32, v8i32, loadv2i64, sub_xmm>; -+ defm : subvector_zero_lowering<"DQA64Z128", "DQU64Z128", VR128X, v16i16, -+ v8i16, v8i32, loadv2i64, sub_xmm>; -+ defm : subvector_zero_lowering<"DQA64Z128", "DQU64Z128", VR128X, v32i8, -+ v16i8, v8i32, loadv2i64, sub_xmm>; -+ -+ defm : subvector_zero_lowering<"APDZ128", "UPDZ128", VR128X, v8f64, -+ v2f64, v16i32, loadv2f64, sub_xmm>; -+ defm : subvector_zero_lowering<"APSZ128", "UPSZ128", VR128X, v16f32, -+ v4f32, v16i32, loadv4f32, sub_xmm>; -+ defm : subvector_zero_lowering<"DQA64Z128", "DQU64Z128", VR128X, v8i64, -+ v2i64, v16i32, loadv2i64, sub_xmm>; -+ defm : subvector_zero_lowering<"DQA64Z128", "DQU64Z128", VR128X, v16i32, -+ v4i32, v16i32, loadv2i64, sub_xmm>; -+ defm : subvector_zero_lowering<"DQA64Z128", "DQU64Z128", VR128X, v32i16, -+ v8i16, v16i32, loadv2i64, sub_xmm>; -+ defm : subvector_zero_lowering<"DQA64Z128", "DQU64Z128", VR128X, v64i8, -+ v16i8, v16i32, loadv2i64, sub_xmm>; -+ -+ defm : subvector_zero_lowering<"APDZ256", "UPDZ256", VR256X, v8f64, -+ v4f64, v16i32, loadv4f64, sub_ymm>; -+ defm : subvector_zero_lowering<"APSZ256", "UPDZ256", VR256X, v16f32, -+ v8f32, v16i32, loadv8f32, sub_ymm>; -+ defm : subvector_zero_lowering<"DQA64Z256", "DQU64Z256", VR256X, v8i64, -+ v4i64, v16i32, loadv4i64, sub_ymm>; -+ defm : subvector_zero_lowering<"DQA64Z256", "DQU64Z256", VR256X, v16i32, -+ v8i32, v16i32, loadv4i64, sub_ymm>; -+ defm : subvector_zero_lowering<"DQA64Z256", "DQU64Z256", VR256X, v32i16, -+ v16i16, v16i32, loadv4i64, sub_ymm>; -+ defm : subvector_zero_lowering<"DQA64Z256", "DQU64Z256", VR256X, v64i8, -+ v32i8, v16i32, loadv4i64, sub_ymm>; - } - - let Predicates = [HasAVX512, NoVLX] in { -- defm : subvector_zero_lowering<"APD", VR128, v8f64, v2f64, v16i32, loadv2f64, -- sub_xmm>; -- defm : subvector_zero_lowering<"APS", VR128, v16f32, v4f32, v16i32, loadv4f32, -- sub_xmm>; -- defm : subvector_zero_lowering<"DQA", VR128, v8i64, v2i64, v16i32, loadv2i64, -- sub_xmm>; -- defm : subvector_zero_lowering<"DQA", VR128, v16i32, v4i32, v16i32, loadv2i64, -- sub_xmm>; -- defm : subvector_zero_lowering<"DQA", VR128, v32i16, v8i16, v16i32, loadv2i64, -- sub_xmm>; -- defm : subvector_zero_lowering<"DQA", VR128, v64i8, v16i8, v16i32, loadv2i64, -- sub_xmm>; -- -- defm : subvector_zero_lowering<"APDY", VR256, v8f64, v4f64, v16i32, -- loadv4f64, sub_ymm>; -- defm : subvector_zero_lowering<"APSY", VR256, v16f32, v8f32, v16i32, -- loadv8f32, sub_ymm>; -- defm : subvector_zero_lowering<"DQAY", VR256, v8i64, v4i64, v16i32, -- loadv4i64, sub_ymm>; -- defm : subvector_zero_lowering<"DQAY", VR256, v16i32, v8i32, v16i32, -- loadv4i64, sub_ymm>; -- defm : subvector_zero_lowering<"DQAY", VR256, v32i16, v16i16, v16i32, -- loadv4i64, sub_ymm>; -- defm : subvector_zero_lowering<"DQAY", VR256, v64i8, v32i8, v16i32, -- loadv4i64, sub_ymm>; -+ defm : subvector_zero_lowering<"APD", "UPD", VR128, v8f64, v2f64, -+ v16i32,loadv2f64, sub_xmm>; -+ defm : subvector_zero_lowering<"APS", "UPS", VR128, v16f32, v4f32, -+ v16i32, loadv4f32, sub_xmm>; -+ defm : subvector_zero_lowering<"DQA", "DQU", VR128, v8i64, v2i64, -+ v16i32, loadv2i64, sub_xmm>; -+ defm : subvector_zero_lowering<"DQA", "DQU", VR128, v16i32, v4i32, -+ v16i32, loadv2i64, sub_xmm>; -+ defm : subvector_zero_lowering<"DQA", "DQU", VR128, v32i16, v8i16, -+ v16i32, loadv2i64, sub_xmm>; -+ defm : subvector_zero_lowering<"DQA", "DQU", VR128, v64i8, v16i8, -+ v16i32, loadv2i64, sub_xmm>; -+ -+ defm : subvector_zero_lowering<"APDY", "UPDY", VR256, v8f64, v4f64, -+ v16i32, loadv4f64, sub_ymm>; -+ defm : subvector_zero_lowering<"APSY", "UPSY", VR256, v16f32, v8f32, -+ v16i32, loadv8f32, sub_ymm>; -+ defm : subvector_zero_lowering<"DQAY", "DQUY", VR256, v8i64, v4i64, -+ v16i32, loadv4i64, sub_ymm>; -+ defm : subvector_zero_lowering<"DQAY", "DQUY", VR256, v16i32, v8i32, -+ v16i32, loadv4i64, sub_ymm>; -+ defm : subvector_zero_lowering<"DQAY", "DQUY", VR256, v32i16, v16i16, -+ v16i32, loadv4i64, sub_ymm>; -+ defm : subvector_zero_lowering<"DQAY", "DQUY", VR256, v64i8, v32i8, -+ v16i32, loadv4i64, sub_ymm>; - } - - // List of opcodes that guaranteed to zero the upper elements of vector regs. -diff --git a/test/CodeGen/X86/merge-consecutive-loads-256.ll b/test/CodeGen/X86/merge-consecutive-loads-256.ll -index 6ecd8116443..0f2cf594b1c 100644 ---- a/test/CodeGen/X86/merge-consecutive-loads-256.ll -+++ b/test/CodeGen/X86/merge-consecutive-loads-256.ll -@@ -28,13 +28,13 @@ define <4 x double> @merge_4f64_2f64_23(<2 x double>* %ptr) nounwind uwtable noi - define <4 x double> @merge_4f64_2f64_2z(<2 x double>* %ptr) nounwind uwtable noinline ssp { - ; AVX-LABEL: merge_4f64_2f64_2z: - ; AVX: # %bb.0: --; AVX-NEXT: vmovaps 32(%rdi), %xmm0 -+; AVX-NEXT: vmovups 32(%rdi), %xmm0 - ; AVX-NEXT: retq - ; - ; X32-AVX-LABEL: merge_4f64_2f64_2z: - ; X32-AVX: # %bb.0: - ; X32-AVX-NEXT: movl {{[0-9]+}}(%esp), %eax --; X32-AVX-NEXT: vmovaps 32(%eax), %xmm0 -+; X32-AVX-NEXT: vmovups 32(%eax), %xmm0 - ; X32-AVX-NEXT: retl - %ptr0 = getelementptr inbounds <2 x double>, <2 x double>* %ptr, i64 2 - %val0 = load <2 x double>, <2 x double>* %ptr0 -@@ -109,13 +109,13 @@ define <4 x double> @merge_4f64_f64_34uu(double* %ptr) nounwind uwtable noinline - define <4 x double> @merge_4f64_f64_45zz(double* %ptr) nounwind uwtable noinline ssp { - ; AVX-LABEL: merge_4f64_f64_45zz: - ; AVX: # %bb.0: --; AVX-NEXT: vmovaps 32(%rdi), %xmm0 -+; AVX-NEXT: vmovups 32(%rdi), %xmm0 - ; AVX-NEXT: retq - ; - ; X32-AVX-LABEL: merge_4f64_f64_45zz: - ; X32-AVX: # %bb.0: - ; X32-AVX-NEXT: movl {{[0-9]+}}(%esp), %eax --; X32-AVX-NEXT: vmovaps 32(%eax), %xmm0 -+; X32-AVX-NEXT: vmovups 32(%eax), %xmm0 - ; X32-AVX-NEXT: retl - %ptr0 = getelementptr inbounds double, double* %ptr, i64 4 - %ptr1 = getelementptr inbounds double, double* %ptr, i64 5 -@@ -155,13 +155,13 @@ define <4 x double> @merge_4f64_f64_34z6(double* %ptr) nounwind uwtable noinline - define <4 x i64> @merge_4i64_2i64_3z(<2 x i64>* %ptr) nounwind uwtable noinline ssp { - ; AVX-LABEL: merge_4i64_2i64_3z: - ; AVX: # %bb.0: --; AVX-NEXT: vmovaps 48(%rdi), %xmm0 -+; AVX-NEXT: vmovups 48(%rdi), %xmm0 - ; AVX-NEXT: retq - ; - ; X32-AVX-LABEL: merge_4i64_2i64_3z: - ; X32-AVX: # %bb.0: - ; X32-AVX-NEXT: movl {{[0-9]+}}(%esp), %eax --; X32-AVX-NEXT: vmovaps 48(%eax), %xmm0 -+; X32-AVX-NEXT: vmovups 48(%eax), %xmm0 - ; X32-AVX-NEXT: retl - %ptr0 = getelementptr inbounds <2 x i64>, <2 x i64>* %ptr, i64 3 - %val0 = load <2 x i64>, <2 x i64>* %ptr0 -@@ -217,13 +217,13 @@ define <4 x i64> @merge_4i64_i64_1zzu(i64* %ptr) nounwind uwtable noinline ssp { - define <4 x i64> @merge_4i64_i64_23zz(i64* %ptr) nounwind uwtable noinline ssp { - ; AVX-LABEL: merge_4i64_i64_23zz: - ; AVX: # %bb.0: --; AVX-NEXT: vmovaps 16(%rdi), %xmm0 -+; AVX-NEXT: vmovups 16(%rdi), %xmm0 - ; AVX-NEXT: retq - ; - ; X32-AVX-LABEL: merge_4i64_i64_23zz: - ; X32-AVX: # %bb.0: - ; X32-AVX-NEXT: movl {{[0-9]+}}(%esp), %eax --; X32-AVX-NEXT: vmovaps 16(%eax), %xmm0 -+; X32-AVX-NEXT: vmovups 16(%eax), %xmm0 - ; X32-AVX-NEXT: retl - %ptr0 = getelementptr inbounds i64, i64* %ptr, i64 2 - %ptr1 = getelementptr inbounds i64, i64* %ptr, i64 3 -diff --git a/test/CodeGen/X86/merge-consecutive-loads-512.ll b/test/CodeGen/X86/merge-consecutive-loads-512.ll -index 62102eb382c..3c6eaf65292 100644 ---- a/test/CodeGen/X86/merge-consecutive-loads-512.ll -+++ b/test/CodeGen/X86/merge-consecutive-loads-512.ll -@@ -106,13 +106,13 @@ define <8 x double> @merge_8f64_f64_23uuuuu9(double* %ptr) nounwind uwtable noin - define <8 x double> @merge_8f64_f64_12zzuuzz(double* %ptr) nounwind uwtable noinline ssp { - ; ALL-LABEL: merge_8f64_f64_12zzuuzz: - ; ALL: # %bb.0: --; ALL-NEXT: vmovaps 8(%rdi), %xmm0 -+; ALL-NEXT: vmovups 8(%rdi), %xmm0 - ; ALL-NEXT: retq - ; - ; X32-AVX512F-LABEL: merge_8f64_f64_12zzuuzz: - ; X32-AVX512F: # %bb.0: - ; X32-AVX512F-NEXT: movl {{[0-9]+}}(%esp), %eax --; X32-AVX512F-NEXT: vmovaps 8(%eax), %xmm0 -+; X32-AVX512F-NEXT: vmovups 8(%eax), %xmm0 - ; X32-AVX512F-NEXT: retl - %ptr0 = getelementptr inbounds double, double* %ptr, i64 1 - %ptr1 = getelementptr inbounds double, double* %ptr, i64 2 -@@ -190,7 +190,7 @@ define <8 x i64> @merge_8i64_4i64_z3(<4 x i64>* %ptr) nounwind uwtable noinline - define <8 x i64> @merge_8i64_i64_56zz9uzz(i64* %ptr) nounwind uwtable noinline ssp { - ; ALL-LABEL: merge_8i64_i64_56zz9uzz: - ; ALL: # %bb.0: --; ALL-NEXT: vmovaps 40(%rdi), %xmm0 -+; ALL-NEXT: vmovups 40(%rdi), %xmm0 - ; ALL-NEXT: vmovsd {{.*#+}} xmm1 = mem[0],zero - ; ALL-NEXT: vinsertf64x4 $1, %ymm1, %zmm0, %zmm0 - ; ALL-NEXT: retq -@@ -198,7 +198,7 @@ define <8 x i64> @merge_8i64_i64_56zz9uzz(i64* %ptr) nounwind uwtable noinline s - ; X32-AVX512F-LABEL: merge_8i64_i64_56zz9uzz: - ; X32-AVX512F: # %bb.0: - ; X32-AVX512F-NEXT: movl {{[0-9]+}}(%esp), %eax --; X32-AVX512F-NEXT: vmovaps 40(%eax), %xmm0 -+; X32-AVX512F-NEXT: vmovups 40(%eax), %xmm0 - ; X32-AVX512F-NEXT: vmovsd {{.*#+}} xmm1 = mem[0],zero - ; X32-AVX512F-NEXT: vinsertf64x4 $1, %ymm1, %zmm0, %zmm0 - ; X32-AVX512F-NEXT: retl diff --git a/doc/make.jl b/doc/make.jl index e4d849ec167bf..466d4705814af 100644 --- a/doc/make.jl +++ b/doc/make.jl @@ -162,40 +162,10 @@ makedocs( analytics = "UA-28835595-6", pages = PAGES, html_prettyurls = ("deploy" in ARGS), - html_canonical = ("deploy" in ARGS) ? "https://docs.julialang.org/en/v1/" : nothing, + html_canonical = ("deploy" in ARGS) ? "https://docs.julialang.org/en/stable/" : nothing, assets = ["assets/julia-manual.css", ] ) -# This overloads the function in Documenter that generates versions.js, to include -# v1/ in the version selector, instead of stable/. -# -# The function is identical to the version found in Documenter v0.19.6, except that -# it includes "v1" instead of "stable". -# -# Original: -# https://github.com/JuliaDocs/Documenter.jl/blob/v0.19.6/src/Writers/HTMLWriter.jl#L481-L506 -# -import Documenter.Writers.HTMLWriter: generate_version_file -function generate_version_file(dir::AbstractString) - named_folders = ["v1", "latest"] - tag_folders = [] - for each in readdir(dir) - each == "v1" && continue # skip the v1 symlink - occursin(Base.VERSION_REGEX, each) && push!(tag_folders, each) - end - # sort tags by version number - sort!(tag_folders, lt = (x, y) -> VersionNumber(x) < VersionNumber(y), rev = true) - open(joinpath(dir, "versions.js"), "w") do buf - println(buf, "var DOC_VERSIONS = [") - for group in (named_folders, tag_folders) - for folder in group - println(buf, " \"", folder, "\",") - end - end - println(buf, "];") - end -end - # Only deploy docs from 64bit Linux to avoid committing multiple versions of the same # docs from different workers. if "deploy" in ARGS && Sys.ARCH === :x86_64 && Sys.KERNEL === :Linux diff --git a/doc/src/base/arrays.md b/doc/src/base/arrays.md index 260649a3a36cf..521cbc2d3dea8 100644 --- a/doc/src/base/arrays.md +++ b/doc/src/base/arrays.md @@ -53,8 +53,6 @@ Base.axes(::AbstractArray, ::Any) Base.length(::AbstractArray) Base.eachindex Base.IndexStyle -Base.IndexLinear -Base.IndexCartesian Base.conj! Base.stride Base.strides diff --git a/doc/src/base/numbers.md b/doc/src/base/numbers.md index 50e6d2b7134da..190584bb0f8f4 100644 --- a/doc/src/base/numbers.md +++ b/doc/src/base/numbers.md @@ -89,6 +89,8 @@ Base.isinteger Base.isreal Core.Float32(::Any) Core.Float64(::Any) +Base.GMP.BigInt(::Any) +Base.MPFR.BigFloat(::Any) Base.Rounding.rounding Base.Rounding.setrounding(::Type, ::Any) Base.Rounding.setrounding(::Function, ::Type, ::RoundingMode) @@ -111,22 +113,18 @@ Base.@int128_str Base.@uint128_str ``` -## BigFloats and BigInts +## BigFloats -The [`BigFloat`](@ref) and [`BigInt`](@ref) types implements -arbitrary-precision floating point and integer arithmetic, respectively. For -[`BigFloat`](@ref) the [GNU MPFR library](http://www.mpfr.org/) is used, -and for [`BigInt`](@ref) the [GNU Multiple Precision Arithmetic Library (GMP)] -(https://gmplib.org) is used. +The [`BigFloat`](@ref) type implements arbitrary-precision floating-point arithmetic using +the [GNU MPFR library](http://www.mpfr.org/). ```@docs -Base.MPFR.BigFloat(::Any) Base.precision Base.MPFR.precision(::Type{BigFloat}) Base.MPFR.setprecision Base.MPFR.BigFloat(x, prec::Int) -Base.MPFR.BigFloat(x::Union{Integer, AbstractFloat, String}, rounding::RoundingMode) +BigFloat(x::Union{Integer, AbstractFloat, String}, rounding::RoundingMode) Base.MPFR.BigFloat(x, prec::Int, rounding::RoundingMode) -Base.GMP.BigInt(::Any) +Base.MPFR.BigFloat(x::String) Base.@big_str ``` diff --git a/doc/src/base/sort.md b/doc/src/base/sort.md index 17a9b8c5ed97d..a3c3b7c3df338 100644 --- a/doc/src/base/sort.md +++ b/doc/src/base/sort.md @@ -110,10 +110,6 @@ can be specified via the `lt` keyword. Base.sort! Base.sort Base.sortperm -Base.InsertionSort -Base.MergeSort -Base.QuickSort -Base.PartialQuickSort Base.Sort.sortperm! Base.Sort.sortslices ``` @@ -135,10 +131,10 @@ Base.Sort.partialsortperm! There are currently four sorting algorithms available in base Julia: - * [`InsertionSort`](@ref) - * [`QuickSort`](@ref) - * [`PartialQuickSort(k)`](@ref) - * [`MergeSort`](@ref) + * `InsertionSort` + * `QuickSort` + * `PartialQuickSort(k)` + * `MergeSort` `InsertionSort` is an O(n^2) stable sorting algorithm. It is efficient for very small `n`, and is used internally by `QuickSort`. diff --git a/doc/src/devdocs/backtraces.md b/doc/src/devdocs/backtraces.md index a65a494bbc3a4..ca750b79a320d 100644 --- a/doc/src/devdocs/backtraces.md +++ b/doc/src/devdocs/backtraces.md @@ -15,10 +15,10 @@ and follow the instructions to generate the debugging information requested. Ta ## [Version/Environment info](@id dev-version-info) No matter the error, we will always need to know what version of Julia you are running. When Julia -first starts up, a header is printed out with a version number and date. Please also include the output of `versioninfo()` (exported from the [`InteractiveUtils`](@ref InteractiveUtils.versioninfo) standard library) in any report you create: +first starts up, a header is printed out with a version number and date. Please also include the +output of `versioninfo()` in any report you create: ```@repl -using InteractiveUtils versioninfo() ``` diff --git a/doc/src/devdocs/gc-sa.md b/doc/src/devdocs/gc-sa.md index 4cf336bec4e31..6c5f5a8c06c5c 100644 --- a/doc/src/devdocs/gc-sa.md +++ b/doc/src/devdocs/gc-sa.md @@ -251,12 +251,10 @@ jl_ast_context_t *jl_ast_ctx(fl_context_t *fl) JL_GLOBALLY_ROOTED; This annotations is essentially equivalent to JL_GLOBALLY_ROOTED, except that is should only be used if those values are globally rooted by virtue of being -a leaftype. The rooting of leaftypes is a bit complicated. They are generally -rooted through `cache` field of the corresponding `TypeName`, which itself is -rooted by the containing module (so they're rooted as long as the containing -module is ok) and we can generally assume that leaftypes are rooted where they -are used, but we may refine this property in the future, so the separate -annotation helps split out the reason for being globally rooted. +a leaftype. The rooting of leaftypes is a bit complicated, and we can generally +assume that leaftypes are rooted where they are used, but we may refine this +property in the future, so the separate annotation helps split out the reason +for being globally rooted. The analyzer also automatically detects checks for leaftype-ness and will not complain about missing GC roots on these paths. diff --git a/doc/src/devdocs/llvm.md b/doc/src/devdocs/llvm.md index bc64345569273..9ed7da79ba699 100644 --- a/doc/src/devdocs/llvm.md +++ b/doc/src/devdocs/llvm.md @@ -42,7 +42,7 @@ The default version of LLVM is specified in `deps/Versions.make`. You can overri a file called `Make.user` in the top-level directory and adding a line to it such as: ``` -LLVM_VER = 6.0.1 +LLVM_VER = 3.5.0 ``` Besides the LLVM release numerals, you can also use `LLVM_VER = svn` to build against the latest diff --git a/doc/src/devdocs/object.md b/doc/src/devdocs/object.md index 49d1e46724301..cf9223f768d96 100644 --- a/doc/src/devdocs/object.md +++ b/doc/src/devdocs/object.md @@ -1,6 +1,6 @@ # Memory layout of Julia Objects -## Object layout (`jl_value_t`) +## Object layout (jl_value_t) The `jl_value_t` struct is the name for a block of memory owned by the Julia Garbage Collector, representing the data associated with a Julia object in memory. Absent any type information, it diff --git a/doc/src/index.md b/doc/src/index.md index a6279791f3ec2..855e45db671f1 100644 --- a/doc/src/index.md +++ b/doc/src/index.md @@ -1,23 +1,6 @@ -```@eval -io = IOBuffer() -release = isempty(VERSION.prerelease) -v = "$(VERSION.major).$(VERSION.minor)" -!release && (v = v*"-$(first(VERSION.prerelease))") -print(io, """ - # Julia $(v) Documentation +# Julia 1.0 Documentation - Welcome to the documentation for Julia $(v). - - """) -if !release - print(io,""" - !!! warning "Work in progress!" - This documentation is for an unreleased, in-development, version of Julia. - """) -end -import Markdown -Markdown.parse(String(take!(io))) -``` +Welcome to the documentation for Julia 1.0. Please read the [release blog post](https://julialang.org/blog/2018/08/one-point-zero) for a general overview of the language and many of the changes since Julia v0.6. Note that version 0.7 was released alongside diff --git a/doc/src/manual/environment-variables.md b/doc/src/manual/environment-variables.md index d38aa0f21a067..b27ff27729afc 100644 --- a/doc/src/manual/environment-variables.md +++ b/doc/src/manual/environment-variables.md @@ -65,15 +65,6 @@ and a global configuration search path of /etc/julia/startup.jl ``` -### `JULIA_PROJECT` - -A directory path that points to the current Julia project. Setting this -environment variable has the same effect as specifying the `--project` start-up -option, but `--project` has higher precedence. If the variable is set to `@.`, -Julia tries to find a project directory that contains `Project.toml` or -`JuliaProject.toml` file from the current directory and its parents. See also -the chapter on [Code Loading](@ref). - ### `JULIA_LOAD_PATH` A separated list of absolute paths that are to be appended to the variable diff --git a/doc/src/manual/functions.md b/doc/src/manual/functions.md index 5b57f6a2a435d..45c170bf9b1a6 100644 --- a/doc/src/manual/functions.md +++ b/doc/src/manual/functions.md @@ -541,10 +541,6 @@ function f(x; y=0, kwargs...) end ``` -Inside `f`, `kwargs` will be a key-value iterator over a named tuple. Named -tuples (as well as dictionaries with keys of `Symbol`) can be passed as keyword -arguments using a semicolon in a call, e.g. `f(x, z=1; kwargs...)`. - If a keyword argument is not assigned a default value in the method definition, then it is *required*: an [`UndefKeywordError`](@ref) exception will be thrown if the caller does not assign it a value: @@ -556,6 +552,9 @@ f(3, y=5) # ok, y is assigned f(3) # throws UndefKeywordError(:y) ``` +Inside `f`, `kwargs` will be a named tuple. Named tuples (as well as dictionaries) can be passed as +keyword arguments using a semicolon in a call, e.g. `f(x, z=1; kwargs...)`. + One can also pass `key => value` expressions after a semicolon. For example, `plot(x, y; :width => 2)` is equivalent to `plot(x, y, width=2)`. This is useful in situations where the keyword name is computed at runtime. diff --git a/doc/src/manual/index.md b/doc/src/manual/index.md new file mode 100644 index 0000000000000..3ae00cff847e6 --- /dev/null +++ b/doc/src/manual/index.md @@ -0,0 +1,39 @@ +# The Julia Manual + + * [Introduction](@ref man-introduction) + * [Getting Started](@ref man-getting-started) + * [Variables](@ref) + * [Integers and Floating-Point Numbers](@ref) + * [Mathematical Operations and Elementary Functions](@ref) + * [Complex and Rational Numbers](@ref) + * [Strings](@ref) + * [Functions](@ref) + * [Control Flow](@ref) + * [Scope of Variables](@ref scope-of-variables) + * [Types](@ref man-types) + * [Methods](@ref) + * [Constructors](@ref man-constructors) + * [Conversion and Promotion](@ref conversion-and-promotion) + * [Interfaces](@ref) + * [Modules](@ref) + * [Documentation](@ref) + * [Metaprogramming](@ref) + * [Multi-dimensional Arrays](@ref man-multi-dim-arrays) + * [Missing Values](@ref missing) + * [Networking and Streams](@ref) + * [Parallel Computing](@ref) + * [Dates](@ref) + * [Running External Programs](@ref) + * [Calling C and Fortran Code](@ref) + * [Handling Operating System Variation](@ref) + * [Environment Variables](@ref) + * [Embedding Julia](@ref) + * [Profiling](@ref) + * [Memory allocation analysis](@ref) + * [Stack Traces](@ref) + * [Performance Tips](@ref man-performance-tips) + * [Workflow Tips](@ref man-workflow-tips) + * [Style Guide](@ref) + * [Frequently Asked Questions](@ref) + * [Noteworthy Differences from other Languages](@ref) + * [Unicode Input](@ref) diff --git a/doc/src/manual/integers-and-floating-point-numbers.md b/doc/src/manual/integers-and-floating-point-numbers.md index 8478d497d91ad..b218ab8d582e4 100644 --- a/doc/src/manual/integers-and-floating-point-numbers.md +++ b/doc/src/manual/integers-and-floating-point-numbers.md @@ -215,7 +215,7 @@ UInt128: [0,340282366920938463463374607431768211455] ``` The values returned by [`typemin`](@ref) and [`typemax`](@ref) are always of the given argument -type. (The above expression uses several features that have yet to be introduced, including [for loops](@ref man-loops), +type. (The above expression uses several features we have yet to introduce, including [for loops](@ref man-loops), [Strings](@ref man-strings), and [Interpolation](@ref), but should be easy enough to understand for users with some existing programming experience.) @@ -678,7 +678,7 @@ where syntactic conflicts arise: * The 32-bit floating-point literal expression `1.5f22` could be interpreted as the numeric literal `1.5` multiplied by the variable `f22`. -In all cases the ambiguity is resolved in favor of interpretation as numeric literals: +In all cases, we resolve the ambiguity in favor of interpretation as numeric literals: * Expressions starting with `0x` are always hexadecimal literals. * Expressions starting with a numeric literal followed by `e` or `E` are always floating-point literals. diff --git a/doc/src/manual/modules.md b/doc/src/manual/modules.md index ef073cbe6db23..74065606cc4e4 100644 --- a/doc/src/manual/modules.md +++ b/doc/src/manual/modules.md @@ -232,10 +232,13 @@ For file dependencies, a change is determined by examining whether the modificat of each file loaded by `include` or added explicitly by `include_dependency` is unchanged, or equal to the modification time truncated to the nearest second (to accommodate systems that can't copy mtime with sub-second accuracy). It also takes into account whether the path to the file chosen -by the search logic in `require` matches the path that had created the precompile file. It also takes -into account the set of dependencies already loaded into the current process and won't recompile those -modules, even if their files change or disappear, in order to avoid creating incompatibilities between -the running system and the precompile cache. +by the search logic in `require` matches the path that had created the precompile file. + +It also takes into account the set of dependencies already loaded into the current process and +won't recompile those modules, even if their files change or disappear, in order to avoid creating +incompatibilities between the running system and the precompile cache. If you want to have changes +to the source reflected in the running system, you should call `reload("Module")` on the module +you changed, and any module that depended on it in which you want to see the change reflected. If you know that a module is *not* safe to precompile your module (for example, for one of the reasons described below), you should diff --git a/doc/src/manual/noteworthy-differences.md b/doc/src/manual/noteworthy-differences.md index c45d7b1ef8e44..9aff0df12fe68 100644 --- a/doc/src/manual/noteworthy-differences.md +++ b/doc/src/manual/noteworthy-differences.md @@ -253,7 +253,7 @@ For users coming to Julia from R, these are some noteworthy differences: Floating point literals are closer in behavior to C/C++. Octal (prefixed with `0o`) and binary (prefixed with `0b`) literals are also treated as unsigned. * String literals can be delimited with either `"` or `"""`, `"""` delimited literals can contain - `"` characters without quoting it like `"\""`. String literals can have values of other variables + `"` characters without quoting it like `"\""` String literals can have values of other variables or expressions interpolated into them, indicated by `$variablename` or `$(expression)`, which evaluates the variable name or the expression in the context of the function. * `//` indicates a [`Rational`](@ref) number, and not a single-line comment (which is `#` in Julia) diff --git a/doc/src/manual/parallel-computing.md b/doc/src/manual/parallel-computing.md index 5b5570dc5d105..5f18d97e75aa4 100644 --- a/doc/src/manual/parallel-computing.md +++ b/doc/src/manual/parallel-computing.md @@ -77,7 +77,7 @@ A channel can be visualized as a pipe, i.e., it has a write end and a read end : # we can schedule `n` instances of `foo` to be active concurrently. for _ in 1:n - @async foo() + @schedule foo() end ``` * Channels are created via the `Channel{T}(sz)` constructor. The channel will only hold objects @@ -158,7 +158,7 @@ julia> data = [i for i in c] Consider a simple example using channels for inter-task communication. We start 4 tasks to process data from a single `jobs` channel. Jobs, identified by an id (`job_id`), are written to the channel. -Each task in this simulation reads a `job_id`, waits for a random amount of time and writes back +Each task in this simulation reads a `job_id`, waits for a random amout of time and writes back a tuple of `job_id` and the simulated time to the results channel. Finally all the `results` are printed out. @@ -184,16 +184,16 @@ julia> function make_jobs(n) julia> n = 12; -julia> @async make_jobs(n); # feed the jobs channel with "n" jobs +julia> @schedule make_jobs(n); # feed the jobs channel with "n" jobs julia> for i in 1:4 # start 4 tasks to process requests in parallel - @async do_work() + @schedule do_work() end julia> @elapsed while n > 0 # print out results job_id, exec_time = take!(results) - println("$job_id finished in $(round(exec_time; digits=2)) seconds") - global n = n - 1 + println("$job_id finished in $(round(exec_time,2)) seconds") + n = n - 1 end 4 finished in 0.22 seconds 3 finished in 0.45 seconds @@ -1792,10 +1792,10 @@ mpirun -np 4 ./julia example.jl ``` [^1]: - In this context, MPI refers to the MPI-1 standard. Beginning with MPI-2, the MPI standards committee - introduced a new set of communication mechanisms, collectively referred to as Remote Memory Access - (RMA). The motivation for adding rma to the MPI standard was to facilitate one-sided communication - patterns. For additional information on the latest MPI standard, see [http://mpi-forum.org/docs](http://mpi-forum.org/docs/). + in this context, mpi refers to the mpi-1 standard. beginning with mpi-2, the mpi standards committee + introduced a new set of communication mechanisms, collectively referred to as remote memory access + (rma). the motivation for adding rma to the mpi standard was to facilitate one-sided communication + patterns. for additional information on the latest mpi standard, see [http://mpi-forum.org/docs](http://mpi-forum.org/docs/). [^2]: [Julia GPU man pages](http://juliagpu.github.io/CUDAnative.jl/stable/man/usage.html#Julia-support-1) diff --git a/doc/src/manual/performance-tips.md b/doc/src/manual/performance-tips.md index a3e08d63ad605..cd81e9eaf0c59 100644 --- a/doc/src/manual/performance-tips.md +++ b/doc/src/manual/performance-tips.md @@ -1151,7 +1151,7 @@ The common idiom of using 1:n to index into an AbstractArray is not safe if the and may cause a segmentation fault if bounds checking is turned off. Use `LinearIndices(x)` or `eachindex(x)` instead (see also [offset-arrays](https://docs.julialang.org/en/latest/devdocs/offset-arrays)). -!!! note +!!!note While `@simd` needs to be placed directly in front of an innermost `for` loop, both `@inbounds` and `@fastmath` can be applied to either single expressions or all the expressions that appear within nested blocks of code, e.g., using `@inbounds begin` or `@inbounds for ...`. diff --git a/doc/src/manual/style-guide.md b/doc/src/manual/style-guide.md index a39697d124456..624297d8a10fa 100644 --- a/doc/src/manual/style-guide.md +++ b/doc/src/manual/style-guide.md @@ -130,7 +130,7 @@ a = Vector{Union{Int,AbstractString,Tuple,Array}}(undef, n) In this case `Vector{Any}(undef, n)` is better. It is also more helpful to the compiler to annotate specific uses (e.g. `a[i]::Int`) than to try to pack many alternatives into one type. -## Use naming conventions consistent with Julia `base/` +## Use naming conventions consistent with Julia's `base/` * modules and type names use capitalization and camel case: `module SparseArrays`, `struct UnitRange`. * functions are lowercase ([`maximum`](@ref), [`convert`](@ref)) and, when readable, with multiple @@ -143,7 +143,7 @@ uses (e.g. `a[i]::Int`) than to try to pack many alternatives into one type. If a function name requires multiple words, consider whether it might represent more than one concept and might be better split into pieces. -## Write functions with argument ordering similar to Julia Base +## Write functions with argument ordering similar to Julia's Base As a general rule, the Base library uses the following order of arguments to functions, as applicable: diff --git a/doc/src/manual/types.md b/doc/src/manual/types.md index 5f307edaa989b..44eb1c76ea39b 100644 --- a/doc/src/manual/types.md +++ b/doc/src/manual/types.md @@ -1152,6 +1152,9 @@ what their types are: julia> typeof(Rational{Int}) DataType +julia> typeof(Union{Real,Float64,Rational}) +DataType + julia> typeof(Union{Real,String}) Union ``` diff --git a/doc/src/manual/variables-and-scoping.md b/doc/src/manual/variables-and-scoping.md index ab6f1962be0c6..496730a4376fa 100644 --- a/doc/src/manual/variables-and-scoping.md +++ b/doc/src/manual/variables-and-scoping.md @@ -495,7 +495,7 @@ are constant by default. Note that `const` only affects the variable binding; the variable may be bound to a mutable object (such as an array), and that object may still be modified. Additionally when one tries -to assign a value to a variable that is declared constant the following scenarios are possible: +to assign a value a variable that is declared constant the following scenarios are possible: * if a new value has a different type than the type of the constant then an error is thrown: ```jldoctest @@ -522,7 +522,7 @@ julia> const z = 100 julia> z = 100 100 ``` -The last rule applies for immutable objects even if the variable binding would change, e.g.: +The last rule applies for immutable objects even if the vairable binding would change, e.g.: ```julia-repl julia> const s1 = "1" "1" diff --git a/src/APInt-C.cpp b/src/APInt-C.cpp index 23ac9678644d8..609a086f67411 100644 --- a/src/APInt-C.cpp +++ b/src/APInt-C.cpp @@ -16,8 +16,10 @@ inline uint64_t RoundUpToAlignment(uint64_t Value, uint64_t Align, uint64_t Skew return alignTo(Value, Align, Skew); } +#if JL_LLVM_VERSION >= 50000 const unsigned int integerPartWidth = llvm::APInt::APINT_BITS_PER_WORD; const unsigned int host_char_bit = 8; +#endif /* create "APInt s" from "integerPart *ps" */ #define CREATE(s) \ @@ -349,7 +351,11 @@ void LLVMFPtoInt(unsigned numbits, integerPart *pa, unsigned onumbits, integerPa APFloat::roundingMode rounding_mode = APFloat::rmNearestTiesToEven; unsigned nbytes = RoundUpToAlignment(onumbits, integerPartWidth) / host_char_bit; integerPart *parts = (integerPart*)alloca(nbytes); +#if JL_LLVM_VERSION >= 50000 APFloat::opStatus status = a.convertToInteger(MutableArrayRef(parts, nbytes), onumbits, isSigned, rounding_mode, &isVeryExact); +#else + APFloat::opStatus status = a.convertToInteger(parts, onumbits, isSigned, rounding_mode, &isVeryExact); +#endif memcpy(pr, parts, onumbytes); if (isExact) *isExact = (status == APFloat::opOK); diff --git a/src/APInt-C.h b/src/APInt-C.h index e71d49e82e99a..6aa70380917ef 100644 --- a/src/APInt-C.h +++ b/src/APInt-C.h @@ -9,7 +9,11 @@ extern "C" { #include "dtypes.h" #ifdef LLVM_VERSION_MAJOR +# if JL_LLVM_VERSION >= 50000 using integerPart = llvm::APInt::WordType; +# else +using llvm::integerPart; +# endif #else typedef void integerPart; #endif diff --git a/src/array.c b/src/array.c index 54bee07cfc59d..746d474b97b18 100644 --- a/src/array.c +++ b/src/array.c @@ -21,19 +21,19 @@ extern "C" { #define JL_ARRAY_ALIGN(jl_value, nbytes) LLT_ALIGN(jl_value, nbytes) // array constructors --------------------------------------------------------- -char *jl_array_typetagdata(jl_array_t *a) JL_NOTSAFEPOINT +char *jl_array_typetagdata(jl_array_t *a) { assert(jl_array_isbitsunion(a)); return ((char*)jl_array_data(a)) + ((jl_array_ndims(a) == 1 ? (a->maxsize - a->offset) : jl_array_len(a)) * a->elsize) + a->offset; } -JL_DLLEXPORT int jl_array_store_unboxed(jl_value_t *eltype) JL_NOTSAFEPOINT +JL_DLLEXPORT int jl_array_store_unboxed(jl_value_t *eltype) { size_t fsz = 0, al = 0; return jl_islayout_inline(eltype, &fsz, &al); } -STATIC_INLINE jl_value_t *jl_array_owner(jl_array_t *a JL_PROPAGATES_ROOT) JL_NOTSAFEPOINT +STATIC_INLINE jl_value_t *jl_array_owner(jl_array_t *a) { if (a->flags.how == 3) { a = (jl_array_t*)jl_array_data_owner(a); @@ -61,9 +61,8 @@ static jl_array_t *_new_array_(jl_value_t *atype, uint32_t ndims, size_t *dims, jl_array_t *a; for(i=0; i < ndims; i++) { - size_t di = dims[i]; - wideint_t prod = (wideint_t)nel * (wideint_t)di; - if (prod > (wideint_t) MAXINTVAL || di > MAXINTVAL) + wideint_t prod = (wideint_t)nel * (wideint_t)dims[i]; + if (prod > (wideint_t) MAXINTVAL) jl_error("invalid Array dimensions"); nel = prod; } @@ -547,15 +546,13 @@ JL_DLLEXPORT int jl_array_isassigned(jl_array_t *a, size_t i) return 1; } -JL_DLLEXPORT void jl_arrayset(jl_array_t *a JL_ROOTING_ARGUMENT, jl_value_t *rhs JL_ROOTED_ARGUMENT JL_MAYBE_UNROOTED, size_t i) +JL_DLLEXPORT void jl_arrayset(jl_array_t *a, jl_value_t *rhs, size_t i) { assert(i < jl_array_len(a)); jl_value_t *eltype = jl_tparam0(jl_typeof(a)); if (eltype != (jl_value_t*)jl_any_type) { - JL_GC_PUSH1(&rhs); if (!jl_isa(rhs, eltype)) jl_type_error("arrayset", eltype, rhs); - JL_GC_POP(); } if (!a->flags.ptrarray) { if (jl_is_uniontype(eltype)) { diff --git a/src/ast.c b/src/ast.c index d758892961c86..59ba152bd2d39 100644 --- a/src/ast.c +++ b/src/ast.c @@ -70,7 +70,7 @@ typedef struct _jl_ast_context_list_t { } jl_ast_context_list_t; STATIC_INLINE void jl_ast_context_list_insert(jl_ast_context_list_t **head, - jl_ast_context_list_t *node) JL_NOTSAFEPOINT + jl_ast_context_list_t *node) { jl_ast_context_list_t *next = *head; if (next) @@ -80,7 +80,7 @@ STATIC_INLINE void jl_ast_context_list_insert(jl_ast_context_list_t **head, *head = node; } -STATIC_INLINE void jl_ast_context_list_delete(jl_ast_context_list_t *node) JL_NOTSAFEPOINT +STATIC_INLINE void jl_ast_context_list_delete(jl_ast_context_list_t *node) { if (node->next) node->next->prev = node->prev; @@ -105,11 +105,7 @@ typedef struct _jl_ast_context_t { static jl_ast_context_t jl_ast_main_ctx; -#ifdef __clang_analyzer__ -jl_ast_context_t *jl_ast_ctx(fl_context_t *fl) JL_GLOBALLY_ROOTED; -#else #define jl_ast_ctx(fl_ctx) container_of(fl_ctx, jl_ast_context_t, fl) -#endif #define jl_ast_context_list_item(node) \ container_of(node, jl_ast_context_t, list) @@ -251,7 +247,7 @@ static jl_mutex_t flisp_lock; static jl_ast_context_list_t *jl_ast_ctx_using = NULL; static jl_ast_context_list_t *jl_ast_ctx_freed = NULL; -static jl_ast_context_t *jl_ast_ctx_enter(void) JL_GLOBALLY_ROOTED JL_NOTSAFEPOINT +static jl_ast_context_t *jl_ast_ctx_enter(void) { jl_ptls_t ptls = jl_get_ptls_states(); JL_SIGATOMIC_BEGIN(); @@ -289,7 +285,7 @@ static jl_ast_context_t *jl_ast_ctx_enter(void) JL_GLOBALLY_ROOTED JL_NOTSAFEPOI return ctx; } -static void jl_ast_ctx_leave(jl_ast_context_t *ctx) JL_NOTSAFEPOINT +static void jl_ast_ctx_leave(jl_ast_context_t *ctx) { JL_SIGATOMIC_END(); if (--ctx->ref) @@ -650,65 +646,18 @@ static value_t julia_to_list2(fl_context_t *fl_ctx, jl_value_t *a, jl_value_t *b return l; } -static int julia_to_scm_noalloc1(fl_context_t *fl_ctx, jl_value_t *v, value_t *retval) JL_NOTSAFEPOINT +static value_t julia_to_scm_(fl_context_t *fl_ctx, jl_value_t *v) { if (v == NULL) lerror(fl_ctx, symbol(fl_ctx, "error"), "undefined reference in AST"); - else if (jl_is_symbol(v)) - *retval = symbol(fl_ctx, jl_symbol_name((jl_sym_t*)v)); - else if (v == jl_true) - *retval = jl_ast_ctx(fl_ctx)->true_sym; - else if (v == jl_false) - *retval = jl_ast_ctx(fl_ctx)->false_sym; - else if (v == jl_nothing) - *retval = fl_cons(fl_ctx, jl_ast_ctx(fl_ctx)->null_sym, fl_ctx->NIL); - else - return 0; - return 1; -} - -static value_t julia_to_scm_noalloc2(fl_context_t *fl_ctx, jl_value_t *v) JL_NOTSAFEPOINT -{ - if (jl_is_long(v) && fits_fixnum(jl_unbox_long(v))) - return fixnum(jl_unbox_long(v)); - if (jl_is_ssavalue(v)) - lerror(fl_ctx, symbol(fl_ctx, "error"), "SSAValue objects should not occur in an AST"); - if (jl_is_slot(v)) - lerror(fl_ctx, symbol(fl_ctx, "error"), "Slot objects should not occur in an AST"); - value_t opaque = cvalue(fl_ctx, jl_ast_ctx(fl_ctx)->jvtype, sizeof(void*)); - *(jl_value_t**)cv_data((cvalue_t*)ptr(opaque)) = v; - return opaque; -} - -static value_t julia_to_scm_noalloc(fl_context_t *fl_ctx, jl_value_t *v) JL_NOTSAFEPOINT -{ - value_t retval; - if (julia_to_scm_noalloc1(fl_ctx, v, &retval)) - return retval; - assert(!jl_is_expr(v) && - !jl_typeis(v, jl_linenumbernode_type) && - !jl_typeis(v, jl_gotonode_type) && - !jl_typeis(v, jl_quotenode_type) && - !jl_typeis(v, jl_newvarnode_type) && - !jl_typeis(v, jl_globalref_type)); - return julia_to_scm_noalloc2(fl_ctx, v); -} - -static value_t julia_to_list2_noalloc(fl_context_t *fl_ctx, jl_value_t *a, jl_value_t *b) JL_NOTSAFEPOINT -{ - value_t sa = julia_to_scm_noalloc(fl_ctx, a); - fl_gc_handle(fl_ctx, &sa); - value_t sb = julia_to_scm_noalloc(fl_ctx, b); - value_t l = fl_list2(fl_ctx, sa, sb); - fl_free_gc_handles(fl_ctx, 1); - return l; -} - -static value_t julia_to_scm_(fl_context_t *fl_ctx, jl_value_t *v) -{ - value_t retval; - if (julia_to_scm_noalloc1(fl_ctx, v, &retval)) - return retval; + if (jl_is_symbol(v)) + return symbol(fl_ctx, jl_symbol_name((jl_sym_t*)v)); + if (v == jl_true) + return jl_ast_ctx(fl_ctx)->true_sym; + if (v == jl_false) + return jl_ast_ctx(fl_ctx)->false_sym; + if (v == jl_nothing) + return fl_cons(fl_ctx, jl_ast_ctx(fl_ctx)->null_sym, fl_ctx->NIL); if (jl_is_expr(v)) { jl_expr_t *ex = (jl_expr_t*)v; value_t args = fl_ctx->NIL; @@ -727,12 +676,12 @@ static value_t julia_to_scm_(fl_context_t *fl_ctx, jl_value_t *v) return scmv; } // GC Note: jl_fieldref(v, 0) allocates for GotoNode - // but we don't need a GC root here because julia_to_list2_noalloc + // but we don't need a GC root here because julia_to_list2 // shouldn't allocate in this case. if (jl_typeis(v, jl_linenumbernode_type)) { - jl_value_t *file = jl_fieldref_noalloc(v,1); - jl_value_t *line = jl_fieldref(v,0); - value_t args = julia_to_list2_noalloc(fl_ctx, line, file); + jl_value_t *file = jl_fieldref_noalloc(v,1); // non-allocating + jl_value_t *line = jl_fieldref(v,0); // allocating + value_t args = julia_to_list2(fl_ctx, line, file); fl_gc_handle(fl_ctx, &args); value_t hd = julia_to_scm_(fl_ctx, (jl_value_t*)line_sym); value_t scmv = fl_cons(fl_ctx, hd, args); @@ -740,11 +689,11 @@ static value_t julia_to_scm_(fl_context_t *fl_ctx, jl_value_t *v) return scmv; } if (jl_typeis(v, jl_gotonode_type)) - return julia_to_list2_noalloc(fl_ctx, (jl_value_t*)goto_sym, jl_fieldref(v,0)); + return julia_to_list2(fl_ctx, (jl_value_t*)goto_sym, jl_fieldref(v,0)); if (jl_typeis(v, jl_quotenode_type)) - return julia_to_list2(fl_ctx, (jl_value_t*)inert_sym, jl_fieldref_noalloc(v,0)); + return julia_to_list2(fl_ctx, (jl_value_t*)inert_sym, jl_fieldref(v,0)); if (jl_typeis(v, jl_newvarnode_type)) - return julia_to_list2_noalloc(fl_ctx, (jl_value_t*)newvar_sym, jl_fieldref(v,0)); + return julia_to_list2(fl_ctx, (jl_value_t*)newvar_sym, jl_fieldref(v,0)); if (jl_typeis(v, jl_globalref_type)) { jl_module_t *m = jl_globalref_mod(v); jl_sym_t *sym = jl_globalref_name(v); @@ -758,7 +707,15 @@ static value_t julia_to_scm_(fl_context_t *fl_ctx, jl_value_t *v) fl_free_gc_handles(fl_ctx, 1); return scmv; } - return julia_to_scm_noalloc2(fl_ctx, v); + if (jl_is_long(v) && fits_fixnum(jl_unbox_long(v))) + return fixnum(jl_unbox_long(v)); + if (jl_is_ssavalue(v)) + lerror(fl_ctx, symbol(fl_ctx, "error"), "SSAValue objects should not occur in an AST"); + if (jl_is_slot(v)) + lerror(fl_ctx, symbol(fl_ctx, "error"), "Slot objects should not occur in an AST"); + value_t opaque = cvalue(fl_ctx, jl_ast_ctx(fl_ctx)->jvtype, sizeof(void*)); + *(jl_value_t**)cv_data((cvalue_t*)ptr(opaque)) = v; + return opaque; } // this is used to parse a line of repl input diff --git a/src/builtins.c b/src/builtins.c index 8428a55b6dd71..2fa6c47afc2f7 100644 --- a/src/builtins.c +++ b/src/builtins.c @@ -32,7 +32,7 @@ extern "C" { // egal and object_id --------------------------------------------------------- -static int bits_equal(void *a, void *b, int sz) JL_NOTSAFEPOINT +static int bits_equal(void *a, void *b, int sz) { switch (sz) { case 1: return *(int8_t*)a == *(int8_t*)b; @@ -63,7 +63,7 @@ static int bits_equal(void *a, void *b, int sz) JL_NOTSAFEPOINT // The solution is to keep the code in jl_egal simple and split out the // (more) complex cases into their own functions which are marked with // NOINLINE. -static int NOINLINE compare_svec(jl_svec_t *a, jl_svec_t *b) JL_NOTSAFEPOINT +static int NOINLINE compare_svec(jl_svec_t *a, jl_svec_t *b) { size_t l = jl_svec_len(a); if (l != jl_svec_len(b)) @@ -76,7 +76,7 @@ static int NOINLINE compare_svec(jl_svec_t *a, jl_svec_t *b) JL_NOTSAFEPOINT } // See comment above for an explanation of NOINLINE. -static int NOINLINE compare_fields(jl_value_t *a, jl_value_t *b, jl_datatype_t *dt) JL_NOTSAFEPOINT +static int NOINLINE compare_fields(jl_value_t *a, jl_value_t *b, jl_datatype_t *dt) { size_t f, nf = jl_datatype_nfields(dt); for (f = 0; f < nf; f++) { @@ -116,7 +116,7 @@ static int NOINLINE compare_fields(jl_value_t *a, jl_value_t *b, jl_datatype_t * return 1; } -static int egal_types(jl_value_t *a, jl_value_t *b, jl_typeenv_t *env) JL_NOTSAFEPOINT +static int egal_types(jl_value_t *a, jl_value_t *b, jl_typeenv_t *env) { if (a == b) return 1; @@ -163,7 +163,7 @@ static int egal_types(jl_value_t *a, jl_value_t *b, jl_typeenv_t *env) JL_NOTSAF return jl_egal(a, b); } -JL_DLLEXPORT int jl_egal(jl_value_t *a JL_MAYBE_UNROOTED, jl_value_t *b JL_MAYBE_UNROOTED) JL_NOTSAFEPOINT +JL_DLLEXPORT int jl_egal(jl_value_t *a, jl_value_t *b) { // warning: a,b may NOT have been gc-rooted by the caller if (a == b) @@ -199,7 +199,7 @@ JL_DLLEXPORT int jl_egal(jl_value_t *a JL_MAYBE_UNROOTED, jl_value_t *b JL_MAYBE // object_id ------------------------------------------------------------------ -static uintptr_t bits_hash(const void *b, size_t sz) JL_NOTSAFEPOINT +static uintptr_t bits_hash(const void *b, size_t sz) { switch (sz) { case 1: return int32hash(*(const int8_t*)b); @@ -219,7 +219,7 @@ static uintptr_t bits_hash(const void *b, size_t sz) JL_NOTSAFEPOINT } } -static uintptr_t NOINLINE hash_svec(jl_svec_t *v) JL_NOTSAFEPOINT +static uintptr_t NOINLINE hash_svec(jl_svec_t *v) { uintptr_t h = 0; size_t i, l = jl_svec_len(v); @@ -236,9 +236,9 @@ typedef struct _varidx { struct _varidx *prev; } jl_varidx_t; -static uintptr_t jl_object_id_(jl_value_t *tv, jl_value_t *v) JL_NOTSAFEPOINT; +static uintptr_t jl_object_id_(jl_value_t *tv, jl_value_t *v); -static uintptr_t type_object_id_(jl_value_t *v, jl_varidx_t *env) JL_NOTSAFEPOINT +static uintptr_t type_object_id_(jl_value_t *v, jl_varidx_t *env) { if (v == NULL) return 0; jl_datatype_t *tv = (jl_datatype_t*)jl_typeof(v); @@ -277,7 +277,7 @@ static uintptr_t type_object_id_(jl_value_t *v, jl_varidx_t *env) JL_NOTSAFEPOIN return jl_object_id_((jl_value_t*)tv, v); } -static uintptr_t jl_object_id_(jl_value_t *tv, jl_value_t *v) JL_NOTSAFEPOINT +static uintptr_t jl_object_id_(jl_value_t *tv, jl_value_t *v) { if (tv == (jl_value_t*)jl_sym_type) return ((jl_sym_t*)v)->hash; @@ -337,7 +337,7 @@ static uintptr_t jl_object_id_(jl_value_t *tv, jl_value_t *v) JL_NOTSAFEPOINT return h; } -JL_DLLEXPORT uintptr_t jl_object_id(jl_value_t *v) JL_NOTSAFEPOINT +JL_DLLEXPORT uintptr_t jl_object_id(jl_value_t *v) { return jl_object_id_(jl_typeof(v), v); } @@ -1132,7 +1132,7 @@ static void add_intrinsic_properties(enum intrinsic f, unsigned nargs, void (*pf runtime_fp[f] = pfunc; } -static void add_intrinsic(jl_module_t *inm, const char *name, enum intrinsic f) JL_GC_DISABLED +static void add_intrinsic(jl_module_t *inm, const char *name, enum intrinsic f) { jl_value_t *i = jl_permbox32(jl_intrinsic_type, (int32_t)f); jl_sym_t *sym = jl_symbol(name); @@ -1140,7 +1140,7 @@ static void add_intrinsic(jl_module_t *inm, const char *name, enum intrinsic f) jl_module_export(inm, sym); } -void jl_init_intrinsic_properties(void) JL_GC_DISABLED +void jl_init_intrinsic_properties(void) { #define ADD_I(name, nargs) add_intrinsic_properties(name, nargs, (void(*)(void))&jl_##name); #define ADD_HIDDEN ADD_I @@ -1151,7 +1151,7 @@ void jl_init_intrinsic_properties(void) JL_GC_DISABLED #undef ALIAS } -void jl_init_intrinsic_functions(void) JL_GC_DISABLED +void jl_init_intrinsic_functions(void) { jl_module_t *inm = jl_new_module(jl_symbol("Intrinsics")); inm->parent = jl_core_module; @@ -1175,7 +1175,7 @@ static void add_builtin(const char *name, jl_value_t *v) jl_fptr_args_t jl_get_builtin_fptr(jl_value_t *b) { assert(jl_isa(b, (jl_value_t*)jl_builtin_type)); - return ((jl_typemap_entry_t*)jl_gf_mtable(b)->cache)->func.linfo->specptr.fptr1; + return jl_gf_mtable(b)->cache.leaf->func.linfo->specptr.fptr1; } static void add_builtin_func(const char *name, jl_fptr_args_t fptr) @@ -1183,7 +1183,7 @@ static void add_builtin_func(const char *name, jl_fptr_args_t fptr) jl_mk_builtin_func(NULL, name, fptr); } -void jl_init_primitives(void) JL_GC_DISABLED +void jl_init_primitives(void) { add_builtin_func("===", jl_f_is); add_builtin_func("typeof", jl_f_typeof); diff --git a/src/ccall.cpp b/src/ccall.cpp index 0a9db2ca1d5a8..8b7457002c0a8 100644 --- a/src/ccall.cpp +++ b/src/ccall.cpp @@ -207,7 +207,11 @@ static Value *runtime_sym_lookup( // all the arguments without writing assembly directly. // This doesn't matter too much in reality since a single function is usually // not called with multiple signatures. +#if JL_LLVM_VERSION >= 50000 static DenseMap,GlobalVariable*>> allPltMap; @@ -215,7 +219,11 @@ static DenseMap= 50000 const AttributeList &attrs, +#else + const AttributeSet &attrs, +#endif CallingConv::ID cc, const char *f_lib, const char *f_name, GlobalVariable *libptrgv, GlobalVariable *llvmgv, void *symaddr, bool runtime_lib) @@ -255,7 +263,11 @@ static GlobalVariable *emit_plt_thunk( // NoReturn function can trigger LLVM verifier error when declared as // MustTail since other passes might replace the `ret` with // `unreachable` (LLVM should probably accept `unreachable`). +#if JL_LLVM_VERSION >= 50000 if (attrs.hasAttribute(AttributeList::FunctionIndex, +#else + if (attrs.hasAttribute(AttributeSet::FunctionIndex, +#endif Attribute::NoReturn)) { irbuilder.CreateUnreachable(); } @@ -288,7 +300,11 @@ static GlobalVariable *emit_plt_thunk( static Value *emit_plt( jl_codectx_t &ctx, FunctionType *functype, +#if JL_LLVM_VERSION >= 50000 const AttributeList &attrs, +#else + const AttributeSet &attrs, +#endif CallingConv::ID cc, const char *f_lib, const char *f_name) { assert(imaging_mode); @@ -438,7 +454,11 @@ static Value *llvm_type_rewrite( // sizes. Value *from; Value *to; +#if JL_LLVM_VERSION >= 40000 const DataLayout &DL = jl_data_layout; +#else + const DataLayout &DL = jl_ExecutionEngine->getDataLayout(); +#endif if (DL.getTypeAllocSize(target_type) >= DL.getTypeAllocSize(from_type)) { to = emit_static_alloca(ctx, target_type); from = emit_bitcast(ctx, to, from_type->getPointerTo()); @@ -1064,10 +1084,15 @@ static jl_cgval_t emit_llvmcall(jl_codectx_t &ctx, jl_value_t **args, size_t nar << jl_string_data(ir) << "\n}"; SMDiagnostic Err = SMDiagnostic(); std::string ir_string = ir_stream.str(); +#if JL_LLVM_VERSION >= 60000 // Do not enable update debug info since it runs the verifier on the whole module // and will error on the function we are currently emitting. bool failed = parseAssemblyInto(llvm::MemoryBufferRef(ir_string, "llvmcall"), *jl_Module, Err, nullptr, /* UpdateDebugInfo */ false); +#else + bool failed = parseAssemblyInto(llvm::MemoryBufferRef(ir_string, "llvmcall"), + *jl_Module, Err); +#endif if (failed) { std::string message = "Failed to parse LLVM Assembly: \n"; llvm::raw_string_ostream stream(message); @@ -1136,7 +1161,11 @@ static jl_cgval_t emit_llvmcall(jl_codectx_t &ctx, jl_value_t **args, size_t nar static Value *box_ccall_result(jl_codectx_t &ctx, Value *result, Value *runtime_dt, jl_value_t *rt) { // XXX: need to handle parameterized zero-byte types (singleton) +#if JL_LLVM_VERSION >= 40000 const DataLayout &DL = jl_data_layout; +#else + const DataLayout &DL = jl_ExecutionEngine->getDataLayout(); +#endif unsigned nb = DL.getTypeStoreSize(result->getType()); MDNode *tbaa = jl_is_mutable(rt) ? tbaa_mutab : tbaa_immut; Value *strct = emit_allocobj(ctx, nb, runtime_dt); @@ -1164,7 +1193,11 @@ class function_sig_t { std::vector fargt_isboxed; // vector of whether the llvm output type is a Julia-box for each argument (vararg is the last item, if applicable) Type *fargt_vasig = NULL; // ABI coercion type for vararg list std::vector byRefList; // vector of "byref" parameters (vararg is the last item, if applicable) +#if JL_LLVM_VERSION >= 50000 AttributeList attributes; // vector of function call site attributes (vararg is the last item, if applicable) +#else + AttributeSet attributes; // vector of function call site attributes (vararg is the last item, if applicable) +#endif Type *lrt; // input parameter of the llvm return type (from julia_struct_to_llvm) bool retboxed; // input parameter indicating whether lrt is jl_value_t* Type *prt; // out parameter of the llvm return type for the function signature @@ -1207,7 +1240,11 @@ std::string generate_func_sig(const char *fname) size_t nargt = jl_svec_len(at); assert(rt && !jl_is_abstract_ref_type(rt)); +#if JL_LLVM_VERSION >= 50000 std::vector paramattrs; +#else + std::vector paramattrs; +#endif std::unique_ptr abi; if (llvmcall) abi.reset(new ABI_LLVMLayout()); @@ -1230,7 +1267,11 @@ std::string generate_func_sig(const char *fname) retattrs.addAttribute(Attribute::StructRet); #endif retattrs.addAttribute(Attribute::NoAlias); +#if JL_LLVM_VERSION >= 50000 paramattrs.push_back(std::move(retattrs)); +#else + paramattrs.push_back(AttributeSet::get(jl_LLVMContext, 1, retattrs)); +#endif fargt_sig.push_back(PointerType::get(lrt, 0)); sret = 1; prt = lrt; @@ -1308,7 +1349,11 @@ std::string generate_func_sig(const char *fname) do { // for each arg for which this type applies, add the appropriate LLVM parameter attributes if (i < nargs) { // if vararg, the last declared arg type may not have a corresponding arg value +#if JL_LLVM_VERSION >= 50000 AttributeSet params = AttributeSet::get(jl_LLVMContext, ab); +#else + AttributeSet params = AttributeSet::get(jl_LLVMContext, i + sret + 1, ab); +#endif paramattrs.push_back(params); } i++; @@ -1317,13 +1362,22 @@ std::string generate_func_sig(const char *fname) for (i = 0; i < nargs + sret; ++i) { const auto &as = paramattrs.at(i); +#if JL_LLVM_VERSION >= 50000 if (!as.hasAttributes()) continue; +#else + if (as.isEmpty()) + continue; +#endif attributes = attributes.addAttributes(jl_LLVMContext, i + 1, as); } if (rt == jl_bottom_type) { attributes = attributes.addAttribute(jl_LLVMContext, +#if JL_LLVM_VERSION >= 50000 AttributeList::FunctionIndex, +#else + AttributeSet::FunctionIndex, +#endif Attribute::NoReturn); } return ""; @@ -1772,20 +1826,6 @@ static jl_cgval_t emit_ccall(jl_codectx_t &ctx, jl_value_t **args, size_t nargs) JL_GC_POP(); return mark_or_box_ccall_result(ctx, strp, retboxed, rt, unionall, static_rt); } - else if (is_libjulia_func(memcpy)) { - const jl_cgval_t &dst = argv[0]; - const jl_cgval_t &src = argv[1]; - const jl_cgval_t &n = argv[2]; - ctx.builder.CreateMemCpy( - ctx.builder.CreateIntToPtr( - emit_unbox(ctx, T_size, dst, (jl_value_t*)jl_voidpointer_type), T_pint8), - ctx.builder.CreateIntToPtr( - emit_unbox(ctx, T_size, src, (jl_value_t*)jl_voidpointer_type), T_pint8), - emit_unbox(ctx, T_size, n, (jl_value_t*)jl_ulong_type), 1, - false); - JL_GC_POP(); - return ghostValue(jl_void_type); - } jl_cgval_t retval = sig.emit_a_ccall( ctx, @@ -2057,7 +2097,11 @@ jl_cgval_t function_sig_t::emit_a_ccall( MDNode *tbaa = jl_is_mutable(rt) ? tbaa_mutab : tbaa_immut; int boxalign = jl_datatype_align(rt); // copy the data from the return value to the new struct +#if JL_LLVM_VERSION >= 40000 const DataLayout &DL = jl_data_layout; +#else + const DataLayout &DL = jl_ExecutionEngine->getDataLayout(); +#endif auto resultTy = result->getType(); if (DL.getTypeStoreSize(resultTy) > rtsz) { // ARM and AArch64 can use a LLVM type larger than the julia type. diff --git a/src/cgutils.cpp b/src/cgutils.cpp index 248cbe4c902e2..c11dc121f9a7c 100644 --- a/src/cgutils.cpp +++ b/src/cgutils.cpp @@ -183,12 +183,22 @@ static DIType *julia_type_to_di(jl_value_t *jt, DIBuilder *dbuilder, bool isboxe return (DIType*)jdt->ditype; if (jl_is_primitivetype(jt)) { uint64_t SizeInBits = jl_datatype_nbits(jdt); +#if JL_LLVM_VERSION >= 40000 llvm::DIType *t = dbuilder->createBasicType( jl_symbol_name(jdt->name->name), SizeInBits, llvm::dwarf::DW_ATE_unsigned); jdt->ditype = t; return t; +#else + llvm::DIType *t = dbuilder->createBasicType( + jl_symbol_name(jdt->name->name), + SizeInBits, + 8 * jl_datatype_align(jdt), + llvm::dwarf::DW_ATE_unsigned); + jdt->ditype = t; + return t; +#endif } if (jl_is_structtype(jt) && jdt->uid && jdt->layout && !jl_is_layout_opaque(jdt->layout)) { size_t ntypes = jl_datatype_nfields(jdt); @@ -231,7 +241,11 @@ static DIType *julia_type_to_di(jl_value_t *jt, DIBuilder *dbuilder, bool isboxe static Value *emit_pointer_from_objref_internal(jl_codectx_t &ctx, Value *V) { CallInst *Call = ctx.builder.CreateCall(prepare_call(pointer_from_objref_func), V); +#if JL_LLVM_VERSION >= 50000 Call->addAttribute(AttributeList::FunctionIndex, Attribute::ReadNone); +#else + Call->addAttribute(AttributeSet::FunctionIndex, Attribute::ReadNone); +#endif return Call; } @@ -483,7 +497,12 @@ static Type *julia_struct_to_llvm(jl_value_t *jt, jl_unionall_t *ua_env, bool *i static unsigned convert_struct_offset(Type *lty, unsigned byte_offset) { - const DataLayout &DL = jl_data_layout; + const DataLayout &DL = +#if JL_LLVM_VERSION >= 40000 + jl_data_layout; +#else + jl_ExecutionEngine->getDataLayout(); +#endif const StructLayout *SL = DL.getStructLayout(cast(lty)); return SL->getElementContainingOffset(byte_offset); } @@ -1354,7 +1373,11 @@ static void emit_memcpy_llvm(jl_codectx_t &ctx, Value *dst, MDNode *tbaa_dst, Va if (sz <= 64) { // The size limit is arbitrary but since we mainly care about floating points and // machine size vectors this should be enough. +#if JL_LLVM_VERSION >= 40000 const DataLayout &DL = jl_data_layout; +#else + const DataLayout &DL = jl_ExecutionEngine->getDataLayout(); +#endif auto srcty = cast(src->getType()); auto srcel = srcty->getElementType(); auto dstty = cast(dst->getType()); @@ -2585,8 +2608,10 @@ static void emit_signal_fence(jl_codectx_t &ctx) // https://llvm.org/bugs/show_bug.cgi?id=27545 ctx.builder.CreateCall(InlineAsm::get(FunctionType::get(T_void, false), "", "~{memory}", true)); -#else +#elif JL_LLVM_VERSION >= 50000 ctx.builder.CreateFence(AtomicOrdering::SequentiallyConsistent, SyncScope::SingleThread); +#else + ctx.builder.CreateFence(AtomicOrdering::SequentiallyConsistent, SingleThread); #endif } diff --git a/src/codegen.cpp b/src/codegen.cpp index 1b4e5938fba91..1290d3a5992f8 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -38,7 +38,11 @@ #include // target machine computation +#if JL_LLVM_VERSION >= 60000 #include +#else +#include +#endif #include #include #include @@ -66,7 +70,11 @@ #include // for llvmcall inlining #include #include // for llvmcall validation -#include +#if JL_LLVM_VERSION >= 40000 +# include +#else +# include +#endif // C API #include @@ -104,7 +112,11 @@ namespace llvm { // LLVM version compatibility macros legacy::PassManager *jl_globalPM; +#if JL_LLVM_VERSION >= 40000 #define DIFlagZero (DINode::FlagZero) +#else +#define DIFlagZero (0) +#endif extern "C" { @@ -350,7 +362,11 @@ extern "C" { template static void add_return_attr(T *f, Attribute::AttrKind Kind) { +#if JL_LLVM_VERSION >= 50000 f->addAttribute(AttributeList::ReturnIndex, Kind); +#else + f->addAttribute(AttributeSet::ReturnIndex, Kind); +#endif } static MDNode *best_tbaa(jl_value_t *jt) { @@ -575,7 +591,9 @@ static GlobalVariable *get_pointer_to_constant(Constant *val, StringRef name, Mo static AllocaInst *emit_static_alloca(jl_codectx_t &ctx, Type *lty, int arraysize=1) { return new AllocaInst(lty, +#if JL_LLVM_VERSION >= 50000 0, +#endif ConstantInt::get(T_int32, arraysize), "", /*InsertBefore=*/ctx.ptlsStates); } @@ -1256,7 +1274,11 @@ static void jl_setup_module(Module *m, const jl_cgparams_t *params = &jl_default if (!getModuleFlag(m,"Debug Info Version")) m->addModuleFlag(llvm::Module::Error, "Debug Info Version", llvm::DEBUG_METADATA_VERSION); +#if JL_LLVM_VERSION >= 40000 m->setDataLayout(jl_data_layout); +#else + m->setDataLayout(jl_ExecutionEngine->getDataLayout()); +#endif m->setTargetTriple(jl_TargetMachine->getTargetTriple().str()); } @@ -1289,9 +1311,13 @@ uint64_t jl_get_llvm_fptr(void *function) Function *F = (Function*)function; uint64_t addr = getAddressForFunction(F->getName()); if (!addr) { +#if JL_LLVM_VERSION >= 50000 if (auto exp_addr = jl_ExecutionEngine->findUnmangledSymbol(F->getName()).getAddress()) { addr = exp_addr.get(); } +#else + addr = jl_ExecutionEngine->findUnmangledSymbol(F->getName()).getAddress(); +#endif } return addr; } @@ -3361,7 +3387,11 @@ static jl_cgval_t emit_varinfo(jl_codectx_t &ctx, jl_varinfo_t &vi, jl_sym_t *va ctx.builder.CreateStore(unbox, ssaslot); } else { +#if JL_LLVM_VERSION >= 40000 const DataLayout &DL = jl_data_layout; +#else + const DataLayout &DL = jl_ExecutionEngine->getDataLayout(); +#endif uint64_t sz = DL.getTypeStoreSize(T); emit_memcpy(ctx, ssaslot, tbaa_stack, vi.value, sz, al); } @@ -4240,7 +4270,11 @@ static Function* gen_cfun_wrapper( M = new Module(name, jl_LLVMContext); jl_setup_module(M); } +#if JL_LLVM_VERSION >= 50000 AttributeList attributes = sig.attributes; +#else + AttributeSet attributes = sig.attributes; +#endif FunctionType *functype; if (nest) { // add nest parameter (pointer to jl_value_t* data array) after sret arg @@ -4861,14 +4895,15 @@ static Function *jl_cfunction_object(jl_value_t *ff, jl_value_t *declrt, jl_tupl // first split on `ft` using a simple eqtable // then use the typemap to split on argt // and finally, pick declrt from the pair-list - jl_typemap_t *cache_l2 = NULL; + union jl_typemap_t cache_l2 = { NULL }; + // cache_l2.unknown = NULL; jl_typemap_entry_t *cache_l3 = NULL; if (!jl_cfunction_list) { jl_cfunction_list = jl_alloc_vec_any(16); } else { - cache_l2 = jl_eqtable_get(jl_cfunction_list, ft, NULL); - if (cache_l2) { + cache_l2.unknown = jl_eqtable_get(jl_cfunction_list, ft, NULL); + if (cache_l2.unknown) { cache_l3 = jl_typemap_assoc_by_type(cache_l2, (jl_value_t*)argt, NULL, /*subtype*/0, /*offs*/0, /*world*/1, /*max_world_mask*/0); if (cache_l3) { @@ -4885,13 +4920,13 @@ static Function *jl_cfunction_object(jl_value_t *ff, jl_value_t *declrt, jl_tupl } if (cache_l3 == NULL) { - jl_typemap_t *insert = cache_l2; - if (!insert) - insert = jl_nothing; - cache_l3 = jl_typemap_insert(&insert, (jl_value_t*)insert, (jl_tupletype_t*)argt, + union jl_typemap_t insert = cache_l2; + if (!insert.unknown) + insert.unknown = jl_nothing; + cache_l3 = jl_typemap_insert(&insert, (jl_value_t*)insert.unknown, (jl_tupletype_t*)argt, NULL, jl_emptysvec, (jl_value_t*)jl_emptysvec, /*offs*/0, &cfunction_cache, 1, ~(size_t)0, NULL); - if (insert != cache_l2) - jl_cfunction_list = jl_eqtable_put(jl_cfunction_list, ft, insert, NULL); + if (insert.unknown != cache_l2.unknown) + jl_cfunction_list = jl_eqtable_put(jl_cfunction_list, ft, insert.unknown, NULL); } // compute / validate return type @@ -5133,7 +5168,11 @@ static jl_returninfo_t get_specsig_function(Module *M, const std::string &name, rt = T_prjlvalue; } } +#if JL_LLVM_VERSION >= 50000 AttributeList attributes; // function declaration attributes +#else + AttributeSet attributes; // function declaration attributes +#endif if (props.cc == jl_returninfo_t::SRet) { attributes = attributes.addAttribute(jl_LLVMContext, 1, Attribute::StructRet); attributes = attributes.addAttribute(jl_LLVMContext, 1, Attribute::NoAlias); @@ -5406,7 +5445,13 @@ static std::unique_ptr emit_function( // i686 Windows (which uses a 4-byte-aligned stack) AttrBuilder *attr = new AttrBuilder(); attr->addStackAlignmentAttr(16); +#if JL_LLVM_VERSION >= 50000 f->addAttributes(AttributeList::FunctionIndex, *attr); +#else + f->addAttributes(AttributeSet::FunctionIndex, + AttributeSet::get(f->getContext(), + AttributeSet::FunctionIndex, *attr)); +#endif #endif #if defined(_OS_WINDOWS_) && defined(_CPU_X86_64_) f->setHasUWTable(); // force NeedsWinEH @@ -5440,7 +5485,12 @@ static std::unique_ptr emit_function( if (ctx.debug_enabled) { // TODO: Fix when moving to new LLVM version topfile = dbuilder.createFile(filename, "."); +#if JL_LLVM_VERSION >= 40000 DICompileUnit *CU = dbuilder.createCompileUnit(0x01, topfile, "julia", true, "", 0); +#else + DICompileUnit *CU = dbuilder.createCompileUnit(0x01, filename, ".", "julia", true, "", 0); +#endif + DISubroutineType *subrty; if (jl_options.debug_level <= 1) { subrty = jl_di_func_null_sig; @@ -5616,7 +5666,11 @@ static std::unique_ptr emit_function( specsig || // for arguments, give them stack slots if they aren't in `argArray` (otherwise, will use that pointer) (va && (int)i == ctx.vaSlot) || // or it's the va arg tuple i == 0) { // or it is the first argument (which isn't in `argArray`) +#if JL_LLVM_VERSION >= 50000 AllocaInst *av = new AllocaInst(T_prjlvalue, 0, +#else + AllocaInst *av = new AllocaInst(T_prjlvalue, +#endif jl_symbol_name(s), /*InsertBefore*/ctx.ptlsStates); StoreInst *SI = new StoreInst( ConstantPointerNull::get(cast(T_prjlvalue)), av, @@ -5736,7 +5790,11 @@ static std::unique_ptr emit_function( if (ctx.debug_enabled && vi.dinfo && !vi.boxroot && !vi.value.V) { SmallVector addr; addr.push_back(llvm::dwarf::DW_OP_deref); +#if JL_LLVM_VERSION >= 50000 addr.push_back(llvm::dwarf::DW_OP_plus_uconst); +#else + addr.push_back(llvm::dwarf::DW_OP_plus); +#endif addr.push_back((i - 1) * sizeof(void*)); if ((Metadata*)vi.dinfo->getType() != jl_pvalue_dillvmt) addr.push_back(llvm::dwarf::DW_OP_deref); @@ -7358,6 +7416,8 @@ extern "C" void *jl_init_llvm(void) // Make sure we are using the large code model on 64bit // Let LLVM pick a default suitable for jitting on 32bit .setCodeModel(CodeModel::Large) +#elif JL_LLVM_VERSION < 60000 + .setCodeModel(CodeModel::JITDefault) #endif #ifdef DISABLE_OPT .setOptLevel(CodeGenOpt::None) @@ -7404,14 +7464,11 @@ extern "C" void *jl_init_llvm(void) init_julia_llvm_meta(); jl_ExecutionEngine = new JuliaOJIT(*jl_TargetMachine); - // Mark our address spaces as non-integral +// Mark our address spaces as non-integral +#if JL_LLVM_VERSION >= 40000 jl_data_layout = jl_ExecutionEngine->getDataLayout(); std::string DL = jl_data_layout.getStringRepresentation() + "-ni:10:11:12:13"; jl_data_layout.reset(DL); - -// Register GDB event listener -#ifdef JL_DEBUG_BUILD - jl_ExecutionEngine->RegisterJITEventListener(JITEventListener::createGDBRegistrationListener()); #endif #ifdef JL_USE_INTEL_JITEVENTS diff --git a/src/codegen_shared.h b/src/codegen_shared.h index b7b57a3b715a9..d93b2de8e8a9c 100644 --- a/src/codegen_shared.h +++ b/src/codegen_shared.h @@ -18,34 +18,58 @@ enum AddressSpace { static inline void llvm_dump(llvm::Value *v) { +#if JL_LLVM_VERSION >= 50000 v->print(llvm::dbgs(), true); llvm::dbgs() << "\n"; +#else + v->dump(); +#endif } static inline void llvm_dump(llvm::Type *v) { +#if JL_LLVM_VERSION >= 50000 v->print(llvm::dbgs(), true); +#else + v->dump(); +#endif llvm::dbgs() << "\n"; } static inline void llvm_dump(llvm::Function *f) { +#if JL_LLVM_VERSION >= 50000 f->print(llvm::dbgs(), nullptr, false, true); +#else + f->dump(); +#endif } static inline void llvm_dump(llvm::Module *m) { +#if JL_LLVM_VERSION >= 50000 m->print(llvm::dbgs(), nullptr); +#else + m->dump(); +#endif } static inline void llvm_dump(llvm::Metadata *m) { +#if JL_LLVM_VERSION >= 50000 m->print(llvm::dbgs()); llvm::dbgs() << "\n"; +#else + m->dump(); +#endif } static inline void llvm_dump(llvm::DebugLoc *dbg) { +#if JL_LLVM_VERSION >= 50000 dbg->print(llvm::dbgs()); +#else + dbg->dump(); +#endif llvm::dbgs() << "\n"; } diff --git a/src/datatype.c b/src/datatype.c index b26c48443b96b..63069f3675854 100644 --- a/src/datatype.c +++ b/src/datatype.c @@ -18,7 +18,7 @@ extern "C" { // allocating TypeNames ----------------------------------------------------------- -jl_sym_t *jl_demangle_typename(jl_sym_t *s) JL_NOTSAFEPOINT +jl_sym_t *jl_demangle_typename(jl_sym_t *s) { char *n = jl_symbol_name(s); if (n[0] != '#') @@ -40,8 +40,8 @@ JL_DLLEXPORT jl_methtable_t *jl_new_method_table(jl_sym_t *name, jl_module_t *mo jl_methtable_type); mt->name = jl_demangle_typename(name); mt->module = module; - mt->defs = jl_nothing; - mt->cache = jl_nothing; + mt->defs.unknown = jl_nothing; + mt->cache.unknown = jl_nothing; mt->max_args = 0; mt->kwsorter = NULL; mt->backedges = NULL; @@ -90,7 +90,7 @@ jl_datatype_t *jl_new_uninitialized_datatype(void) static jl_datatype_layout_t *jl_get_layout(uint32_t nfields, uint32_t alignment, int haspadding, - jl_fielddesc32_t desc[]) JL_NOTSAFEPOINT + jl_fielddesc32_t desc[]) { // compute the smallest fielddesc type that can hold the layout description int fielddesc_type = 0; @@ -262,7 +262,7 @@ JL_DLLEXPORT int jl_islayout_inline(jl_value_t *eltype, size_t *fsz, size_t *al) return (countbits > 0 && countbits < 127) ? countbits : 0; } -static int references_name(jl_value_t *p, jl_typename_t *name) JL_NOTSAFEPOINT +static int references_name(jl_value_t *p, jl_typename_t *name) { if (jl_is_uniontype(p)) return references_name(((jl_uniontype_t*)p)->a, name) || @@ -362,11 +362,10 @@ void jl_compute_field_offsets(jl_datatype_t *st) size_t descsz = nfields * sizeof(jl_fielddesc32_t); jl_fielddesc32_t *desc; - int should_malloc = descsz >= jl_page_size; - if (should_malloc) - desc = (jl_fielddesc32_t*)malloc(descsz); - else + if (descsz < jl_page_size) desc = (jl_fielddesc32_t*)alloca(descsz); + else + desc = (jl_fielddesc32_t*)malloc(descsz); int haspadding = 0; assert(st->name == jl_tuple_typename || st == jl_sym_type || @@ -375,7 +374,7 @@ void jl_compute_field_offsets(jl_datatype_t *st) for (size_t i = 0; i < nfields; i++) { jl_value_t *ty = jl_field_type(st, i); - size_t fsz = 0, al = 1; + size_t fsz = 0, al = 0; if (jl_islayout_inline(ty, &fsz, &al)) { if (__unlikely(fsz > max_size)) // Should never happen @@ -428,11 +427,11 @@ void jl_compute_field_offsets(jl_datatype_t *st) if (st->size > sz) haspadding = 1; st->layout = jl_get_layout(nfields, alignm, haspadding, desc); - if (should_malloc) free(desc); + if (descsz >= jl_page_size) free(desc); jl_allocate_singleton_instance(st); return; throw_ovf: - if (should_malloc) free(desc); + if (descsz >= jl_page_size) free(desc); jl_errorf("type %s has field offset %d that exceeds the page size", jl_symbol_name(st->name->name), descsz); } @@ -874,7 +873,7 @@ JL_DLLEXPORT jl_value_t *jl_get_nth_field_checked(jl_value_t *v, size_t i) return jl_new_bits(ty, (char*)v + offs); } -JL_DLLEXPORT void jl_set_nth_field(jl_value_t *v, size_t i, jl_value_t *rhs) JL_NOTSAFEPOINT +JL_DLLEXPORT void jl_set_nth_field(jl_value_t *v, size_t i, jl_value_t *rhs) { jl_datatype_t *st = (jl_datatype_t*)jl_typeof(v); size_t offs = jl_field_offset(st, i); diff --git a/src/debuginfo.cpp b/src/debuginfo.cpp index 737508301776a..15c33f86524cd 100644 --- a/src/debuginfo.cpp +++ b/src/debuginfo.cpp @@ -16,14 +16,20 @@ #include #include #include +#if JL_LLVM_VERSION >= 50000 #include +#endif #include #include #include using namespace llvm; +#if JL_LLVM_VERSION >= 50000 using llvm_file_magic = file_magic; +#else +using llvm_file_magic = sys::fs::file_magic; +#endif #include "julia.h" #include "julia_internal.h" @@ -398,7 +404,11 @@ class JuliaJITEventListener: public JITEventListener ObjectInfo tmp = {&debugObj, (size_t)SectionSize, (ptrdiff_t)(SectionAddr - SectionLoadAddr), +#if JL_LLVM_VERSION >= 60000 DWARFContext::create(debugObj, &L).release(), +#else + new DWARFContextInMemory(debugObj, &L), +#endif }; objectmap[SectionLoadAddr] = tmp; first = false; @@ -938,7 +948,11 @@ static objfileentry_t &find_object_file(uint64_t fbase, StringRef fname) slide = -(int64_t)fbase; } +#if JL_LLVM_VERSION >= 60000 auto context = DWARFContext::create(*debugobj).release(); +#else + auto context = new DWARFContextInMemory(*debugobj); +#endif auto binary = errorobj->takeBinary(); binary.first.release(); binary.second.release(); diff --git a/src/disasm.cpp b/src/disasm.cpp index e72000da83a57..c7f74765cba65 100644 --- a/src/disasm.cpp +++ b/src/disasm.cpp @@ -28,8 +28,13 @@ #include "llvm-version.h" #include +#if JL_LLVM_VERSION >= 50000 #include #include +#else +#include +#include +#endif #include #include #include @@ -645,7 +650,12 @@ static void jl_dump_asm_internal( std::unique_ptr MOFI(new MCObjectFileInfo()); MCContext Ctx(MAI.get(), MRI.get(), MOFI.get(), &SrcMgr); +#if JL_LLVM_VERSION >= 60000 MOFI->InitMCObjectFileInfo(TheTriple, /* PIC */ false, Ctx); +#else + MOFI->InitMCObjectFileInfo(TheTriple, /* PIC */ false, + CodeModel::Default, Ctx); +#endif // Set up Subtarget and Disassembler std::unique_ptr @@ -673,8 +683,15 @@ static void jl_dump_asm_internal( MCAsmBackend *MAB = 0; if (ShowEncoding) { CE = TheTarget->createMCCodeEmitter(*MCII, *MRI, Ctx); +#if JL_LLVM_VERSION >= 60000 MCTargetOptions Options; MAB = TheTarget->createMCAsmBackend(*STI, *MRI, Options); +#elif JL_LLVM_VERSION >= 40000 + MCTargetOptions Options; + MAB = TheTarget->createMCAsmBackend(*MRI, TripleName, cpu, Options); +#else + MAB = TheTarget->createMCAsmBackend(*MRI, TripleName, cpu); +#endif } // createAsmStreamer expects a unique_ptr to a formatted stream, which means diff --git a/src/dump.c b/src/dump.c index f970009de5ea8..c18865125e6c8 100644 --- a/src/dump.c +++ b/src/dump.c @@ -60,9 +60,7 @@ static arraylist_t reinit_list; // list of stuff that is being serialized // (only used by the incremental serializer in MODE_MODULE) -// This is not quite globally rooted, but we take care to only -// ever assigned rooted values here. -static jl_array_t *serializer_worklist JL_GLOBALLY_ROOTED; +static jl_array_t *serializer_worklist; // inverse of backedges tree // (only used by the incremental serializer in MODE_MODULE) @@ -162,48 +160,48 @@ static arraylist_t builtin_typenames; /* read and write in host byte order */ -static void write_int32(ios_t *s, int32_t i) JL_NOTSAFEPOINT +static void write_int32(ios_t *s, int32_t i) { ios_write(s, (char*)&i, 4); } -static int32_t read_int32(ios_t *s) JL_NOTSAFEPOINT +static int32_t read_int32(ios_t *s) { int32_t x = 0; ios_read(s, (char*)&x, 4); return x; } -static void write_uint64(ios_t *s, uint64_t i) JL_NOTSAFEPOINT +static void write_uint64(ios_t *s, uint64_t i) { ios_write(s, (char*)&i, 8); } -static uint64_t read_uint64(ios_t *s) JL_NOTSAFEPOINT +static uint64_t read_uint64(ios_t *s) { uint64_t x = 0; ios_read(s, (char*)&x, 8); return x; } -static void write_int64(ios_t *s, int64_t i) JL_NOTSAFEPOINT +static void write_int64(ios_t *s, int64_t i) { ios_write(s, (char*)&i, 8); } -static void write_uint16(ios_t *s, uint16_t i) JL_NOTSAFEPOINT +static void write_uint16(ios_t *s, uint16_t i) { ios_write(s, (char*)&i, 2); } -static uint16_t read_uint16(ios_t *s) JL_NOTSAFEPOINT +static uint16_t read_uint16(ios_t *s) { int16_t x = 0; ios_read(s, (char*)&x, 2); return x; } -static void write_float64(ios_t *s, double x) JL_NOTSAFEPOINT +static void write_float64(ios_t *s, double x) { write_uint64(s, *((uint64_t*)&x)); } @@ -211,10 +209,10 @@ static void write_float64(ios_t *s, double x) JL_NOTSAFEPOINT // --- serialize --- #define jl_serialize_value(s, v) jl_serialize_value_((s), (jl_value_t*)(v), 0) -static void jl_serialize_value_(jl_serializer_state *s, jl_value_t *v, int as_literal) JL_GC_DISABLED; -static jl_value_t *jl_deserialize_value(jl_serializer_state *s, jl_value_t **loc) JL_GC_DISABLED; +static void jl_serialize_value_(jl_serializer_state *s, jl_value_t *v, int as_literal); +static jl_value_t *jl_deserialize_value(jl_serializer_state *s, jl_value_t **loc); -static int module_in_worklist(jl_module_t *mod) JL_NOTSAFEPOINT +static int module_in_worklist(jl_module_t *mod) { int i, l = jl_array_len(serializer_worklist); for (i = 0; i < l; i++) { @@ -228,7 +226,7 @@ static int module_in_worklist(jl_module_t *mod) JL_NOTSAFEPOINT // compute whether a type references something internal to worklist // and thus could not have existed before deserialize // and thus does not need delayed unique-ing -static int type_in_worklist(jl_datatype_t *dt) JL_NOTSAFEPOINT +static int type_in_worklist(jl_datatype_t *dt) { if (module_in_worklist(dt->name->module)) return 1; @@ -243,7 +241,7 @@ static int type_in_worklist(jl_datatype_t *dt) JL_NOTSAFEPOINT static int type_recursively_external(jl_datatype_t *dt); -static int type_parameter_recursively_external(jl_value_t *p0) JL_NOTSAFEPOINT +static int type_parameter_recursively_external(jl_value_t *p0) { jl_datatype_t *p = (jl_datatype_t*)p0; while (jl_is_unionall(p)) { @@ -265,7 +263,7 @@ static int type_parameter_recursively_external(jl_value_t *p0) JL_NOTSAFEPOINT } // returns true if all of the parameters are tag 6 or 7 -static int type_recursively_external(jl_datatype_t *dt) JL_NOTSAFEPOINT +static int type_recursively_external(jl_datatype_t *dt) { if (dt->uid == 0) return 0; @@ -281,7 +279,7 @@ static int type_recursively_external(jl_datatype_t *dt) JL_NOTSAFEPOINT } -static void jl_serialize_datatype(jl_serializer_state *s, jl_datatype_t *dt) JL_GC_DISABLED +static void jl_serialize_datatype(jl_serializer_state *s, jl_datatype_t *dt) { int tag = 0; int internal = module_in_worklist(dt->name->module); @@ -462,7 +460,7 @@ static int is_ast_node(jl_value_t *v) jl_typeis(v, jl_lineinfonode_type); } -static int literal_val_id(jl_serializer_state *s, jl_value_t *v) JL_GC_DISABLED +static int literal_val_id(jl_serializer_state *s, jl_value_t *v) { jl_array_t *rs = s->method->roots; int i, l = jl_array_len(rs); @@ -482,7 +480,7 @@ static int literal_val_id(jl_serializer_state *s, jl_value_t *v) JL_GC_DISABLED return jl_array_len(rs) - 1; } -static void jl_serialize_value_(jl_serializer_state *s, jl_value_t *v, int as_literal) JL_GC_DISABLED +static void jl_serialize_value_(jl_serializer_state *s, jl_value_t *v, int as_literal) { if (v == NULL) { write_uint8(s->s, TAG_NULL); @@ -580,7 +578,7 @@ static void jl_serialize_value_(jl_serializer_state *s, jl_value_t *v, int as_li arraylist_push(&reinit_list, (void*)pos); arraylist_push(&reinit_list, (void*)3); } - if (jl_is_method(v) && jl_typeof(((jl_method_t*)v)->specializations) == (jl_value_t*)jl_typemap_level_type) { + if (jl_is_method(v) && jl_typeof(((jl_method_t*)v)->specializations.unknown) == (jl_value_t*)jl_typemap_level_type) { arraylist_push(&reinit_list, (void*)pos); arraylist_push(&reinit_list, (void*)4); } @@ -781,7 +779,8 @@ static void jl_serialize_value_(jl_serializer_state *s, jl_value_t *v, int as_li jl_datatype_t *gf = jl_first_argument_datatype((jl_value_t*)m->sig); assert(jl_is_datatype(gf) && gf->name->mt); external_mt = !module_in_worklist(gf->name->mt->module); - jl_serialize_value(s, m->specializations); + union jl_typemap_t *tf = &m->specializations; + jl_serialize_value(s, tf->unknown); jl_serialize_value(s, (jl_value_t*)m->name); jl_serialize_value(s, (jl_value_t*)m->file); write_int32(s->s, m->line); @@ -800,7 +799,7 @@ static void jl_serialize_value_(jl_serializer_state *s, jl_value_t *v, int as_li jl_serialize_value(s, (jl_value_t*)m->source); jl_serialize_value(s, (jl_value_t*)m->unspecialized); jl_serialize_value(s, (jl_value_t*)m->generator); - jl_serialize_value(s, (jl_value_t*)m->invokes); + jl_serialize_value(s, (jl_value_t*)m->invokes.unknown); } else if (jl_is_method_instance(v)) { write_uint8(s->s, TAG_METHOD_INSTANCE); @@ -998,7 +997,7 @@ static void jl_serialize_value_(jl_serializer_state *s, jl_value_t *v, int as_li jl_serialize_value(s, jl_nothing); jl_serialize_value(s, node->targ.values); jl_serialize_value(s, node->linear); - jl_serialize_value(s, node->any); + jl_serialize_value(s, node->any.unknown); jl_serialize_value(s, node->key); return; } @@ -1057,7 +1056,7 @@ static void jl_collect_missing_backedges_to_mod(jl_methtable_t *mt) // the intent of this function is to invert the backedges tree // for anything that points to a method not part of the worklist -static void collect_backedges(jl_method_instance_t *callee) JL_GC_DISABLED +static void collect_backedges(jl_method_instance_t *callee) { jl_array_t *backedges = callee->backedges; if (backedges) { @@ -1076,7 +1075,7 @@ static void collect_backedges(jl_method_instance_t *callee) JL_GC_DISABLED } -static int jl_collect_backedges_to_mod(jl_typemap_entry_t *ml, void *closure) JL_GC_DISABLED +static int jl_collect_backedges_to_mod(jl_typemap_entry_t *ml, void *closure) { (void)(jl_array_t*)closure; jl_method_instance_t *callee = ml->func.linfo; @@ -1084,7 +1083,7 @@ static int jl_collect_backedges_to_mod(jl_typemap_entry_t *ml, void *closure) JL return 1; } -static int jl_collect_methcache_from_mod(jl_typemap_entry_t *ml, void *closure) JL_GC_DISABLED +static int jl_collect_methcache_from_mod(jl_typemap_entry_t *ml, void *closure) { jl_array_t *s = (jl_array_t*)closure; jl_method_t *m = ml->func.method; @@ -1098,12 +1097,12 @@ static int jl_collect_methcache_from_mod(jl_typemap_entry_t *ml, void *closure) return 1; } -static void jl_collect_methtable_from_mod(jl_array_t *s, jl_typename_t *tn) JL_GC_DISABLED +static void jl_collect_methtable_from_mod(jl_array_t *s, jl_typename_t *tn) { jl_typemap_visitor(tn->mt->defs, jl_collect_methcache_from_mod, (void*)s); } -static void jl_collect_lambdas_from_mod(jl_array_t *s, jl_module_t *m) JL_GC_DISABLED +static void jl_collect_lambdas_from_mod(jl_array_t *s, jl_module_t *m) { if (module_in_worklist(m)) return; @@ -1139,7 +1138,7 @@ static void jl_collect_lambdas_from_mod(jl_array_t *s, jl_module_t *m) JL_GC_DIS } // flatten the backedge map reachable from caller into callees -static void jl_collect_backedges_to(jl_method_instance_t *caller, htable_t *all_callees) JL_GC_DISABLED +static void jl_collect_backedges_to(jl_method_instance_t *caller, htable_t *all_callees) { jl_array_t **pcallees = (jl_array_t**)ptrhash_bp(&edges_map, (void*)caller), *callees = *pcallees; @@ -1246,7 +1245,7 @@ static void write_work_list(ios_t *s) write_int32(s, 0); } -static void write_module_path(ios_t *s, jl_module_t *depmod) JL_NOTSAFEPOINT +static void write_module_path(ios_t *s, jl_module_t *depmod) { if (depmod->parent == jl_main_module || depmod->parent == depmod) return; @@ -1323,7 +1322,7 @@ static int64_t write_dependency_list(ios_t *s, jl_array_t **udepsp, jl_array_t * // --- deserialize --- -static jl_value_t *jl_deserialize_datatype(jl_serializer_state *s, int pos, jl_value_t **loc) JL_GC_DISABLED +static jl_value_t *jl_deserialize_datatype(jl_serializer_state *s, int pos, jl_value_t **loc) { int tag = read_uint8(s->s); if (tag == 6 || tag == 7) { @@ -1455,7 +1454,7 @@ static jl_value_t *jl_deserialize_datatype(jl_serializer_state *s, int pos, jl_v return (jl_value_t*)dt; } -static jl_value_t *jl_deserialize_value_svec(jl_serializer_state *s, uint8_t tag) JL_GC_DISABLED +static jl_value_t *jl_deserialize_value_svec(jl_serializer_state *s, uint8_t tag) { int usetable = (s->mode != MODE_IR); size_t i, len; @@ -1473,7 +1472,7 @@ static jl_value_t *jl_deserialize_value_svec(jl_serializer_state *s, uint8_t tag return (jl_value_t*)sv; } -static jl_value_t *jl_deserialize_value_symbol(jl_serializer_state *s, uint8_t tag) JL_GC_DISABLED +static jl_value_t *jl_deserialize_value_symbol(jl_serializer_state *s, uint8_t tag) { int usetable = (s->mode != MODE_IR); size_t len; @@ -1492,7 +1491,7 @@ static jl_value_t *jl_deserialize_value_symbol(jl_serializer_state *s, uint8_t t return sym; } -static jl_value_t *jl_deserialize_value_array(jl_serializer_state *s, uint8_t tag) JL_GC_DISABLED +static jl_value_t *jl_deserialize_value_array(jl_serializer_state *s, uint8_t tag) { int usetable = (s->mode != MODE_IR); int16_t i, ndims; @@ -1538,7 +1537,7 @@ static jl_value_t *jl_deserialize_value_array(jl_serializer_state *s, uint8_t ta return (jl_value_t*)a; } -static jl_value_t *jl_deserialize_value_expr(jl_serializer_state *s, uint8_t tag) JL_GC_DISABLED +static jl_value_t *jl_deserialize_value_expr(jl_serializer_state *s, uint8_t tag) { int usetable = (s->mode != MODE_IR); size_t i, len; @@ -1572,7 +1571,7 @@ static jl_value_t *jl_deserialize_value_expr(jl_serializer_state *s, uint8_t tag return (jl_value_t*)e; } -static jl_value_t *jl_deserialize_value_phi(jl_serializer_state *s, uint8_t tag) JL_GC_DISABLED +static jl_value_t *jl_deserialize_value_phi(jl_serializer_state *s, uint8_t tag) { int usetable = (s->mode != MODE_IR); size_t i, len_e, len_v; @@ -1599,7 +1598,7 @@ static jl_value_t *jl_deserialize_value_phi(jl_serializer_state *s, uint8_t tag) return phi; } -static jl_value_t *jl_deserialize_value_phic(jl_serializer_state *s, uint8_t tag) JL_GC_DISABLED +static jl_value_t *jl_deserialize_value_phic(jl_serializer_state *s, uint8_t tag) { int usetable = (s->mode != MODE_IR); size_t i, len; @@ -1618,7 +1617,7 @@ static jl_value_t *jl_deserialize_value_phic(jl_serializer_state *s, uint8_t tag return phic; } -static jl_value_t *jl_deserialize_value_method(jl_serializer_state *s, jl_value_t **loc) JL_GC_DISABLED +static jl_value_t *jl_deserialize_value_method(jl_serializer_state *s, jl_value_t **loc) { int usetable = (s->mode != MODE_IR); jl_method_t *m = @@ -1637,8 +1636,8 @@ static jl_value_t *jl_deserialize_value_method(jl_serializer_state *s, jl_value_ arraylist_push(&flagref_list, (void*)pos); return (jl_value_t*)m; } - m->specializations = jl_deserialize_value(s, (jl_value_t**)&m->specializations); - jl_gc_wb(m, m->specializations); + m->specializations.unknown = jl_deserialize_value(s, (jl_value_t**)&m->specializations); + jl_gc_wb(m, m->specializations.unknown); m->name = (jl_sym_t*)jl_deserialize_value(s, NULL); jl_gc_wb(m, m->name); m->file = (jl_sym_t*)jl_deserialize_value(s, NULL); @@ -1667,14 +1666,14 @@ static jl_value_t *jl_deserialize_value_method(jl_serializer_state *s, jl_value_ m->generator = jl_deserialize_value(s, (jl_value_t**)&m->generator); if (m->generator) jl_gc_wb(m, m->generator); - m->invokes = jl_deserialize_value(s, (jl_value_t**)&m->invokes); - jl_gc_wb(m, m->invokes); + m->invokes.unknown = jl_deserialize_value(s, (jl_value_t**)&m->invokes); + jl_gc_wb(m, m->invokes.unknown); m->traced = 0; JL_MUTEX_INIT(&m->writelock); return (jl_value_t*)m; } -static jl_value_t *jl_deserialize_value_method_instance(jl_serializer_state *s, jl_value_t **loc) JL_GC_DISABLED +static jl_value_t *jl_deserialize_value_method_instance(jl_serializer_state *s, jl_value_t **loc) { int usetable = (s->mode != MODE_IR); jl_method_instance_t *li = @@ -1742,7 +1741,7 @@ static jl_value_t *jl_deserialize_value_method_instance(jl_serializer_state *s, return (jl_value_t*)li; } -static jl_value_t *jl_deserialize_value_module(jl_serializer_state *s) JL_GC_DISABLED +static jl_value_t *jl_deserialize_value_module(jl_serializer_state *s) { int usetable = (s->mode != MODE_IR); uintptr_t pos = backref_list.len; @@ -1802,7 +1801,7 @@ static jl_value_t *jl_deserialize_value_module(jl_serializer_state *s) JL_GC_DIS return (jl_value_t*)m; } -static jl_value_t *jl_deserialize_value_globalref(jl_serializer_state *s) JL_GC_DISABLED +static jl_value_t *jl_deserialize_value_globalref(jl_serializer_state *s) { int usetable = (s->mode != MODE_IR); if (usetable) { @@ -1820,7 +1819,7 @@ static jl_value_t *jl_deserialize_value_globalref(jl_serializer_state *s) JL_GC_ } } -static jl_value_t *jl_deserialize_value_singleton(jl_serializer_state *s, jl_value_t **loc) JL_GC_DISABLED +static jl_value_t *jl_deserialize_value_singleton(jl_serializer_state *s, jl_value_t **loc) { if (s->mode == MODE_IR) { jl_datatype_t *dt = (jl_datatype_t*)jl_deserialize_value(s, NULL); @@ -1846,7 +1845,7 @@ static jl_value_t *jl_deserialize_value_singleton(jl_serializer_state *s, jl_val return v; } -static void jl_deserialize_struct(jl_serializer_state *s, jl_value_t *v, size_t startfield) JL_GC_DISABLED +static void jl_deserialize_struct(jl_serializer_state *s, jl_value_t *v, size_t startfield) { jl_datatype_t *dt = (jl_datatype_t*)jl_typeof(v); size_t i, nf = jl_datatype_nfields(dt); @@ -1888,7 +1887,7 @@ static void jl_deserialize_struct(jl_serializer_state *s, jl_value_t *v, size_t } } -static jl_value_t *jl_deserialize_typemap_entry(jl_serializer_state *s) JL_GC_DISABLED +static jl_value_t *jl_deserialize_typemap_entry(jl_serializer_state *s) { int N = read_int32(s->s); int n = N; jl_value_t *te = jl_nothing; @@ -1915,7 +1914,7 @@ static jl_value_t *jl_deserialize_typemap_entry(jl_serializer_state *s) JL_GC_DI return te; } -static jl_value_t *jl_deserialize_value_any(jl_serializer_state *s, uint8_t tag, jl_value_t **loc) JL_GC_DISABLED +static jl_value_t *jl_deserialize_value_any(jl_serializer_state *s, uint8_t tag, jl_value_t **loc) { int usetable = (s->mode != MODE_IR); int32_t sz = (tag == TAG_SHORT_GENERAL ? read_uint8(s->s) : read_int32(s->s)); @@ -1961,7 +1960,7 @@ static jl_value_t *jl_deserialize_value_any(jl_serializer_state *s, uint8_t tag, return v; } -static jl_value_t *jl_deserialize_value(jl_serializer_state *s, jl_value_t **loc) JL_GC_DISABLED +static jl_value_t *jl_deserialize_value(jl_serializer_state *s, jl_value_t **loc) { assert(!ios_eof(s->s)); jl_value_t *v; @@ -2170,7 +2169,7 @@ static void jl_insert_methods(jl_array_t *list) } } -static size_t lowerbound_dependent_world_set(size_t world, arraylist_t *dependent_worlds) JL_NOTSAFEPOINT +static size_t lowerbound_dependent_world_set(size_t world, arraylist_t *dependent_worlds) { size_t i, l = dependent_worlds->len; if (world <= (size_t)dependent_worlds->items[l - 1]) @@ -2329,7 +2328,7 @@ static void jl_finalize_serializer(jl_serializer_state *s) write_int32(s->s, -1); } -void jl_typemap_rehash(jl_typemap_t *ml, int8_t offs); +void jl_typemap_rehash(union jl_typemap_t ml, int8_t offs); static void jl_reinit_item(jl_value_t *v, int how, arraylist_t *tracee_list) { jl_ptls_t ptls = jl_get_ptls_states(); @@ -2766,7 +2765,7 @@ static int jl_invalid_types_equal(jl_datatype_t *a, jl_datatype_t *b) } #endif -static jl_datatype_t *jl_recache_type(jl_datatype_t *dt, size_t start, jl_value_t *v) JL_GC_DISABLED +static jl_datatype_t *jl_recache_type(jl_datatype_t *dt, size_t start, jl_value_t *v) { if (v == NULL) v = dt->instance; // the instance before unique'ing @@ -2835,7 +2834,6 @@ static jl_datatype_t *jl_recache_type(jl_datatype_t *dt, size_t start, jl_value_ } else if (v == o) { if (t->instance != v) { - assert(loc); *loc = t->instance; if (offs > 0) backref_list.items[offs] = t->instance; @@ -2855,7 +2853,7 @@ static jl_datatype_t *jl_recache_type(jl_datatype_t *dt, size_t start, jl_value_ return t; } -static void jl_recache_types(void) JL_GC_DISABLED +static void jl_recache_types(void) { size_t i = 0; while (i < flagref_list.len) { @@ -2893,7 +2891,6 @@ static void jl_recache_types(void) JL_GC_DISABLED if (t->instance != v) { jl_set_typeof(v, (void*)(intptr_t)0x20); // invalidate the old value to help catch errors if (v == o) { - assert(loc); *loc = t->instance; if (offs > 0) backref_list.items[offs] = t->instance; @@ -3116,10 +3113,8 @@ static jl_value_t *_jl_restore_incremental(ios_t *f, jl_array_t *mod_array) jl_gc_enable_finalizers(ptls, 1); // make sure we don't run any Julia code concurrently before this point if (tracee_list) { jl_methtable_t *mt; - while ((mt = (jl_methtable_t*)arraylist_pop(tracee_list)) != NULL) { - JL_GC_PROMISE_ROOTED(mt); + while ((mt = (jl_methtable_t*)arraylist_pop(tracee_list)) != NULL) jl_typemap_visitor(mt->defs, trace_method, NULL); - } arraylist_free(tracee_list); free(tracee_list); } diff --git a/src/gc.c b/src/gc.c index 8b9c945070b90..4a821b5b99cb4 100644 --- a/src/gc.c +++ b/src/gc.c @@ -96,7 +96,7 @@ static inline void jl_gc_wait_for_the_world(void) #define malloc_cache_align(sz) jl_malloc_aligned(sz, JL_CACHE_BYTE_ALIGNMENT) #define realloc_cache_align(p, sz, oldsz) jl_realloc_aligned(p, sz, oldsz, JL_CACHE_BYTE_ALIGNMENT) -static void schedule_finalization(void *o, void *f) JL_NOTSAFEPOINT +static void schedule_finalization(void *o, void *f) { arraylist_push(&to_finalize, o); arraylist_push(&to_finalize, f); @@ -125,7 +125,7 @@ static void run_finalizer(jl_ptls_t ptls, jl_value_t *o, jl_value_t *ff) // if `need_sync` is true, the `list` is the `finalizers` list of another // thread and we need additional synchronizations static void finalize_object(arraylist_t *list, jl_value_t *o, - arraylist_t *copied_list, int need_sync) JL_NOTSAFEPOINT + arraylist_t *copied_list, int need_sync) { // The acquire load makes sure that the first `len` objects are valid. // If `need_sync` is true, all mutations of the content should be limited @@ -258,7 +258,7 @@ JL_DLLEXPORT void jl_gc_enable_finalizers(jl_ptls_t ptls, int on) } } -static void schedule_all_finalizers(arraylist_t *flist) JL_NOTSAFEPOINT +static void schedule_all_finalizers(arraylist_t *flist) { void **items = flist->items; size_t len = flist->len; @@ -458,7 +458,7 @@ STATIC_INLINE void gc_update_heap_size(int64_t sz_ub, int64_t sz_est) last_full_live_est = sz_est; } -static void gc_sync_cache_nolock(jl_ptls_t ptls, jl_gc_mark_cache_t *gc_cache) JL_NOTSAFEPOINT +static void gc_sync_cache_nolock(jl_ptls_t ptls, jl_gc_mark_cache_t *gc_cache) { const int nbig = gc_cache->nbig_obj; for (int i = 0; i < nbig; i++) { @@ -480,7 +480,7 @@ static void gc_sync_cache_nolock(jl_ptls_t ptls, jl_gc_mark_cache_t *gc_cache) J gc_cache->scanned_bytes = 0; } -static void gc_sync_cache(jl_ptls_t ptls) JL_NOTSAFEPOINT +static void gc_sync_cache(jl_ptls_t ptls) { JL_LOCK_NOGC(&gc_cache_lock); gc_sync_cache_nolock(ptls, &ptls->gc_cache); @@ -497,7 +497,7 @@ static void gc_sync_all_caches_nolock(jl_ptls_t ptls) } STATIC_INLINE void gc_queue_big_marked(jl_ptls_t ptls, bigval_t *hdr, - int toyoung) JL_NOTSAFEPOINT + int toyoung) { const int nentry = sizeof(ptls->gc_cache.big_obj) / sizeof(void*); size_t nobj = ptls->gc_cache.nbig_obj; @@ -521,7 +521,7 @@ STATIC_INLINE void gc_queue_big_marked(jl_ptls_t ptls, bigval_t *hdr, // The return value is `1` if the object was not marked before. // Returning `0` can happen if another thread marked it in parallel. STATIC_INLINE int gc_setmark_tag(jl_taggedvalue_t *o, uint8_t mark_mode, - uintptr_t tag, uint8_t *bits) JL_NOTSAFEPOINT + uintptr_t tag, uint8_t *bits) { assert(!gc_marked(tag)); assert(gc_marked(mark_mode)); @@ -545,7 +545,7 @@ STATIC_INLINE int gc_setmark_tag(jl_taggedvalue_t *o, uint8_t mark_mode, // This function should be called exactly once during marking for each big // object being marked to update the big objects metadata. STATIC_INLINE void gc_setmark_big(jl_ptls_t ptls, jl_taggedvalue_t *o, - uint8_t mark_mode) JL_NOTSAFEPOINT + uint8_t mark_mode) { assert(!page_metadata(o)); bigval_t *hdr = bigval_header(o); @@ -572,7 +572,7 @@ STATIC_INLINE void gc_setmark_big(jl_ptls_t ptls, jl_taggedvalue_t *o, // object being marked to update the page metadata. STATIC_INLINE void gc_setmark_pool_(jl_ptls_t ptls, jl_taggedvalue_t *o, uint8_t mark_mode, - jl_gc_pagemeta_t *page) JL_NOTSAFEPOINT + jl_gc_pagemeta_t *page) { #ifdef MEMDEBUG gc_setmark_big(ptls, o, mark_mode); @@ -598,13 +598,13 @@ STATIC_INLINE void gc_setmark_pool_(jl_ptls_t ptls, jl_taggedvalue_t *o, } STATIC_INLINE void gc_setmark_pool(jl_ptls_t ptls, jl_taggedvalue_t *o, - uint8_t mark_mode) JL_NOTSAFEPOINT + uint8_t mark_mode) { gc_setmark_pool_(ptls, o, mark_mode, jl_assume(page_metadata(o))); } STATIC_INLINE void gc_setmark(jl_ptls_t ptls, jl_taggedvalue_t *o, - uint8_t mark_mode, size_t sz) JL_NOTSAFEPOINT + uint8_t mark_mode, size_t sz) { if (sz <= GC_MAX_SZCLASS) { gc_setmark_pool(ptls, o, mark_mode); @@ -614,7 +614,7 @@ STATIC_INLINE void gc_setmark(jl_ptls_t ptls, jl_taggedvalue_t *o, } } -STATIC_INLINE void gc_setmark_buf_(jl_ptls_t ptls, void *o, uint8_t mark_mode, size_t minsz) JL_NOTSAFEPOINT +STATIC_INLINE void gc_setmark_buf_(jl_ptls_t ptls, void *o, uint8_t mark_mode, size_t minsz) { jl_taggedvalue_t *buf = jl_astaggedvalue(o); uintptr_t tag = buf->header; @@ -637,12 +637,12 @@ STATIC_INLINE void gc_setmark_buf_(jl_ptls_t ptls, void *o, uint8_t mark_mode, s } } -void gc_setmark_buf(jl_ptls_t ptls, void *o, uint8_t mark_mode, size_t minsz) JL_NOTSAFEPOINT +void gc_setmark_buf(jl_ptls_t ptls, void *o, uint8_t mark_mode, size_t minsz) { gc_setmark_buf_(ptls, o, mark_mode, minsz); } -void jl_gc_force_mark_old(jl_ptls_t ptls, jl_value_t *v) JL_NOTSAFEPOINT +void jl_gc_force_mark_old(jl_ptls_t ptls, jl_value_t *v) { jl_taggedvalue_t *o = jl_astaggedvalue(v); jl_datatype_t *dt = (jl_datatype_t*)jl_typeof(v); @@ -761,7 +761,7 @@ JL_DLLEXPORT jl_value_t *jl_gc_big_alloc(jl_ptls_t ptls, size_t sz) // Sweep list rooted at *pv, removing and freeing any unmarked objects. // Return pointer to last `next` field in the culled list. -static bigval_t **sweep_big_list(int sweep_full, bigval_t **pv) JL_NOTSAFEPOINT +static bigval_t **sweep_big_list(int sweep_full, bigval_t **pv) { bigval_t *v = *pv; while (v != NULL) { @@ -821,7 +821,7 @@ static void sweep_big(jl_ptls_t ptls, int sweep_full) // tracking Arrays with malloc'd storage -void jl_gc_track_malloced_array(jl_ptls_t ptls, jl_array_t *a) JL_NOTSAFEPOINT +void jl_gc_track_malloced_array(jl_ptls_t ptls, jl_array_t *a) { // This is **NOT** a GC safe point. mallocarray_t *ma; @@ -837,19 +837,20 @@ void jl_gc_track_malloced_array(jl_ptls_t ptls, jl_array_t *a) JL_NOTSAFEPOINT ptls->heap.mallocarrays = ma; } -void jl_gc_count_allocd(size_t sz) JL_NOTSAFEPOINT +void jl_gc_count_allocd(size_t sz) { + // This is **NOT** a GC safe point. gc_num.allocd += sz; } -void jl_gc_reset_alloc_count(void) JL_NOTSAFEPOINT +void jl_gc_reset_alloc_count(void) { live_bytes += (gc_num.deferred_alloc + (gc_num.allocd + gc_num.interval)); gc_num.allocd = -(int64_t)gc_num.interval; gc_num.deferred_alloc = 0; } -static size_t array_nbytes(jl_array_t *a) JL_NOTSAFEPOINT +static size_t array_nbytes(jl_array_t *a) { size_t sz = 0; int isbitsunion = jl_array_isbitsunion(a); @@ -863,7 +864,7 @@ static size_t array_nbytes(jl_array_t *a) JL_NOTSAFEPOINT return sz; } -static void jl_gc_free_array(jl_array_t *a) JL_NOTSAFEPOINT +static void jl_gc_free_array(jl_array_t *a) { if (a->flags.how == 2) { char *d = (char*)a->data - a->offset*a->elsize; @@ -875,7 +876,7 @@ static void jl_gc_free_array(jl_array_t *a) JL_NOTSAFEPOINT } } -static void sweep_malloced_arrays(void) JL_NOTSAFEPOINT +static void sweep_malloced_arrays(void) { gc_time_mallocd_array_start(); for (int t_i = 0;t_i < jl_n_threads;t_i++) { @@ -1014,7 +1015,7 @@ int jl_gc_classify_pools(size_t sz, int *osize) int64_t lazy_freed_pages = 0; // Returns pointer to terminal pointer of list rooted at *pfl. -static jl_taggedvalue_t **sweep_page(jl_gc_pool_t *p, jl_gc_pagemeta_t *pg, jl_taggedvalue_t **pfl, int sweep_full, int osize) JL_NOTSAFEPOINT +static jl_taggedvalue_t **sweep_page(jl_gc_pool_t *p, jl_gc_pagemeta_t *pg, jl_taggedvalue_t **pfl, int sweep_full, int osize) { char *data = pg->data; uint8_t *ages = pg->ages; @@ -1130,7 +1131,7 @@ static jl_taggedvalue_t **sweep_page(jl_gc_pool_t *p, jl_gc_pagemeta_t *pg, jl_t } // the actual sweeping over all allocated pages in a memory pool -static inline void sweep_pool_page(jl_taggedvalue_t ***pfl, jl_gc_pagemeta_t *pg, int sweep_full) JL_NOTSAFEPOINT +static inline void sweep_pool_page(jl_taggedvalue_t ***pfl, jl_gc_pagemeta_t *pg, int sweep_full) { int p_n = pg->pool_n; int t_n = pg->thread_n; @@ -1141,7 +1142,7 @@ static inline void sweep_pool_page(jl_taggedvalue_t ***pfl, jl_gc_pagemeta_t *pg } // sweep over a pagetable0 for all allocated pages -static inline int sweep_pool_pagetable0(jl_taggedvalue_t ***pfl, pagetable0_t *pagetable0, int sweep_full) JL_NOTSAFEPOINT +static inline int sweep_pool_pagetable0(jl_taggedvalue_t ***pfl, pagetable0_t *pagetable0, int sweep_full) { unsigned ub = 0; unsigned alloc = 0; @@ -1165,7 +1166,7 @@ static inline int sweep_pool_pagetable0(jl_taggedvalue_t ***pfl, pagetable0_t *p } // sweep over pagetable1 for all pagetable0 that may contain allocated pages -static inline int sweep_pool_pagetable1(jl_taggedvalue_t ***pfl, pagetable1_t *pagetable1, int sweep_full) JL_NOTSAFEPOINT +static inline int sweep_pool_pagetable1(jl_taggedvalue_t ***pfl, pagetable1_t *pagetable1, int sweep_full) { unsigned ub = 0; unsigned alloc = 0; @@ -1190,7 +1191,7 @@ static inline int sweep_pool_pagetable1(jl_taggedvalue_t ***pfl, pagetable1_t *p } // sweep over all memory for all pagetable1 that may contain allocated pages -static void sweep_pool_pagetable(jl_taggedvalue_t ***pfl, int sweep_full) JL_NOTSAFEPOINT +static void sweep_pool_pagetable(jl_taggedvalue_t ***pfl, int sweep_full) { if (REGION2_PG_COUNT == 1) { // compile-time optimization pagetable1_t *pagetable1 = memory_map.meta1[0]; @@ -1217,13 +1218,13 @@ static void sweep_pool_pagetable(jl_taggedvalue_t ***pfl, int sweep_full) JL_NOT } // sweep over all memory that is being used and not in a pool -static void gc_sweep_other(jl_ptls_t ptls, int sweep_full) JL_NOTSAFEPOINT +static void gc_sweep_other(jl_ptls_t ptls, int sweep_full) { sweep_malloced_arrays(); sweep_big(ptls, sweep_full); } -static void gc_pool_sync_nfree(jl_gc_pagemeta_t *pg, jl_taggedvalue_t *last) JL_NOTSAFEPOINT +static void gc_pool_sync_nfree(jl_gc_pagemeta_t *pg, jl_taggedvalue_t *last) { assert(pg->fl_begin_offset != (uint16_t)-1); char *cur_pg = gc_page_data(last); @@ -1245,17 +1246,13 @@ static void gc_sweep_pool(int sweep_full) gc_time_pool_start(); lazy_freed_pages = 0; - // For the benfit of the analyzer, which doesn't know that jl_n_threads - // doesn't change over the course of this function - size_t n_threads = jl_n_threads; - // allocate enough space to hold the end of the free list chain // for every thread and pool size - jl_taggedvalue_t ***pfl = (jl_taggedvalue_t ***) alloca(n_threads * JL_GC_N_POOLS * sizeof(jl_taggedvalue_t**)); + jl_taggedvalue_t ***pfl = (jl_taggedvalue_t ***) alloca(jl_n_threads * JL_GC_N_POOLS * sizeof(jl_taggedvalue_t**)); // update metadata of pages that were pointed to by freelist or newpages from a pool // i.e. pages being the current allocation target - for (int t_i = 0; t_i < n_threads; t_i++) { + for (int t_i = 0; t_i < jl_n_threads; t_i++) { jl_ptls_t ptls2 = jl_all_tls_states[t_i]; for (int i = 0; i < JL_GC_N_POOLS; i++) { jl_gc_pool_t *p = &ptls2->heap.norm_pools[i]; @@ -1284,7 +1281,7 @@ static void gc_sweep_pool(int sweep_full) sweep_pool_pagetable(pfl, sweep_full); // null out terminal pointers of free lists - for (int t_i = 0; t_i < n_threads; t_i++) { + for (int t_i = 0; t_i < jl_n_threads; t_i++) { for (int i = 0; i < JL_GC_N_POOLS; i++) { *pfl[t_i * JL_GC_N_POOLS + i] = NULL; } @@ -1404,7 +1401,7 @@ static void NOINLINE gc_mark_stack_resize(jl_gc_mark_cache_t *gc_cache, gc_mark_ // in `gc_cache` or `sp` // The `sp` will be updated on return if `inc` is true. STATIC_INLINE void gc_mark_stack_push(jl_gc_mark_cache_t *gc_cache, gc_mark_sp_t *sp, - void *pc, void *data, size_t data_size, int inc) JL_NOTSAFEPOINT + void *pc, void *data, size_t data_size, int inc) { assert(data_size <= sizeof(jl_gc_mark_data_t)); if (__unlikely(sp->pc == sp->pc_end)) @@ -1422,7 +1419,7 @@ STATIC_INLINE void gc_mark_stack_push(jl_gc_mark_cache_t *gc_cache, gc_mark_sp_t // Return the tag (with GC bits cleared) and the GC bits in `*ptag` and `*pbits`. // Return whether the object needs to be scanned / have metadata updated. STATIC_INLINE int gc_try_setmark(jl_value_t *obj, uintptr_t *nptr, - uintptr_t *ptag, uint8_t *pbits) JL_NOTSAFEPOINT + uintptr_t *ptag, uint8_t *pbits) { if (!obj) return 0; @@ -1474,7 +1471,7 @@ STATIC_INLINE void gc_mark_queue_scan_obj(jl_gc_mark_cache_t *gc_cache, gc_mark_ // The object will be marked atomically which can also happen concurrently. // It will be queued if the object wasn't marked already (or concurrently by another thread) // Returns whether the object is young. -STATIC_INLINE int gc_mark_queue_obj(jl_gc_mark_cache_t *gc_cache, gc_mark_sp_t *sp, void *_obj) JL_NOTSAFEPOINT +STATIC_INLINE int gc_mark_queue_obj(jl_gc_mark_cache_t *gc_cache, gc_mark_sp_t *sp, void *_obj) { jl_value_t *obj = (jl_value_t*)jl_assume(_obj); uintptr_t nptr = 0; @@ -1490,7 +1487,7 @@ STATIC_INLINE int gc_mark_queue_obj(jl_gc_mark_cache_t *gc_cache, gc_mark_sp_t * // Check if `nptr` is tagged for `old + refyoung`, // Push the object to the remset and update the `nptr` counter if necessary. -STATIC_INLINE void gc_mark_push_remset(jl_ptls_t ptls, jl_value_t *obj, uintptr_t nptr) JL_NOTSAFEPOINT +STATIC_INLINE void gc_mark_push_remset(jl_ptls_t ptls, jl_value_t *obj, uintptr_t nptr) { if (__unlikely((nptr & 0x3) == 0x3)) { ptls->heap.remset_nptr += nptr >> 2; @@ -1576,7 +1573,7 @@ STATIC_INLINE int gc_mark_scan_obj8(jl_ptls_t ptls, gc_mark_sp_t *sp, gc_mark_ob // Scan an object with 16bits field descriptors. see `gc_mark_obj16_t` STATIC_INLINE int gc_mark_scan_obj16(jl_ptls_t ptls, gc_mark_sp_t *sp, gc_mark_obj16_t *obj16, char *parent, jl_fielddesc16_t *begin, jl_fielddesc16_t *end, - jl_value_t **pnew_obj, uintptr_t *ptag, uint8_t *pbits) JL_NOTSAFEPOINT + jl_value_t **pnew_obj, uintptr_t *ptag, uint8_t *pbits) { (void)jl_assume(obj16 == (gc_mark_obj16_t*)sp->data); (void)jl_assume(begin < end); @@ -2938,7 +2935,6 @@ static void *gc_perm_alloc_large(size_t sz, int zero, unsigned align, unsigned o if (align > 1 && (offset != 0 || align > malloc_align)) sz += align - 1; uintptr_t base = (uintptr_t)(zero ? calloc(1, sz) : malloc(sz)); - jl_may_leak(base); unsigned diff = (offset - base) % align; return (void*)(base + diff); } diff --git a/src/gc.h b/src/gc.h index c6a284d7d32ab..4cf2cd0f7fa40 100644 --- a/src/gc.h +++ b/src/gc.h @@ -348,9 +348,6 @@ typedef struct { int ub; } pagetable_t; -#ifdef __clang_analyzer__ -unsigned ffs_u32(uint32_t bitvec) JL_NOTSAFEPOINT; -#else STATIC_INLINE unsigned ffs_u32(uint32_t bitvec) { #if defined(_COMPILER_MINGW_) @@ -363,7 +360,6 @@ STATIC_INLINE unsigned ffs_u32(uint32_t bitvec) return ffs(bitvec) - 1; #endif } -#endif extern jl_gc_num_t gc_num; extern pagetable_t memory_map; @@ -372,7 +368,7 @@ extern arraylist_t finalizer_list_marked; extern arraylist_t to_finalize; extern int64_t lazy_freed_pages; -STATIC_INLINE bigval_t *bigval_header(jl_taggedvalue_t *o) JL_NOTSAFEPOINT +STATIC_INLINE bigval_t *bigval_header(jl_taggedvalue_t *o) { return container_of(o, bigval_t, header); } @@ -393,34 +389,34 @@ STATIC_INLINE jl_taggedvalue_t *page_pfl_end(jl_gc_pagemeta_t *p) return (jl_taggedvalue_t*)(p->data + p->fl_end_offset); } -STATIC_INLINE int gc_marked(uintptr_t bits) JL_NOTSAFEPOINT +STATIC_INLINE int gc_marked(uintptr_t bits) { return (bits & GC_MARKED) != 0; } -STATIC_INLINE int gc_old(uintptr_t bits) JL_NOTSAFEPOINT +STATIC_INLINE int gc_old(uintptr_t bits) { return (bits & GC_OLD) != 0; } -STATIC_INLINE uintptr_t gc_set_bits(uintptr_t tag, int bits) JL_NOTSAFEPOINT +STATIC_INLINE uintptr_t gc_set_bits(uintptr_t tag, int bits) { return (tag & ~(uintptr_t)3) | bits; } -STATIC_INLINE uintptr_t gc_ptr_tag(void *v, uintptr_t mask) JL_NOTSAFEPOINT +STATIC_INLINE uintptr_t gc_ptr_tag(void *v, uintptr_t mask) { return ((uintptr_t)v) & mask; } -STATIC_INLINE void *gc_ptr_clear_tag(void *v, uintptr_t mask) JL_NOTSAFEPOINT +STATIC_INLINE void *gc_ptr_clear_tag(void *v, uintptr_t mask) { return (void*)(((uintptr_t)v) & ~mask); } NOINLINE uintptr_t gc_get_stack_ptr(void); -STATIC_INLINE jl_gc_pagemeta_t *page_metadata(void *_data) JL_NOTSAFEPOINT +STATIC_INLINE jl_gc_pagemeta_t *page_metadata(void *_data) { uintptr_t data = ((uintptr_t)_data); unsigned i; @@ -445,7 +441,7 @@ struct jl_gc_metadata_ext { unsigned pagetable0_i32, pagetable0_i; }; -STATIC_INLINE struct jl_gc_metadata_ext page_metadata_ext(void *_data) JL_NOTSAFEPOINT +STATIC_INLINE struct jl_gc_metadata_ext page_metadata_ext(void *_data) { uintptr_t data = (uintptr_t)_data; struct jl_gc_metadata_ext info; @@ -466,7 +462,7 @@ STATIC_INLINE struct jl_gc_metadata_ext page_metadata_ext(void *_data) JL_NOTSAF return info; } -STATIC_INLINE void gc_big_object_unlink(const bigval_t *hdr) JL_NOTSAFEPOINT +STATIC_INLINE void gc_big_object_unlink(const bigval_t *hdr) { *hdr->prev = hdr->next; if (hdr->next) { @@ -474,7 +470,7 @@ STATIC_INLINE void gc_big_object_unlink(const bigval_t *hdr) JL_NOTSAFEPOINT } } -STATIC_INLINE void gc_big_object_link(bigval_t *hdr, bigval_t **list) JL_NOTSAFEPOINT +STATIC_INLINE void gc_big_object_link(bigval_t *hdr, bigval_t **list) { hdr->next = *list; hdr->prev = list; @@ -627,7 +623,7 @@ JL_DLLEXPORT extern jl_gc_debug_env_t jl_gc_debug_env; int gc_debug_check_other(void); int gc_debug_check_pool(void); void gc_debug_print(void); -void gc_scrub_record_task(jl_task_t *ta) JL_NOTSAFEPOINT; +void gc_scrub_record_task(jl_task_t *ta); void gc_scrub(void); #else #define gc_sweep_always_full 0 @@ -642,7 +638,7 @@ static inline int gc_debug_check_pool(void) static inline void gc_debug_print(void) { } -static inline void gc_scrub_record_task(jl_task_t *ta) JL_NOTSAFEPOINT +static inline void gc_scrub_record_task(jl_task_t *ta) { (void)ta; } @@ -652,11 +648,11 @@ static inline void gc_scrub(void) #endif #ifdef OBJPROFILE -void objprofile_count(void *ty, int old, int sz) JL_NOTSAFEPOINT; +void objprofile_count(void *ty, int old, int sz); void objprofile_printall(void); void objprofile_reset(void); #else -static inline void objprofile_count(void *ty, int old, int sz) JL_NOTSAFEPOINT +static inline void objprofile_count(void *ty, int old, int sz) { } diff --git a/src/gf.c b/src/gf.c index 7480524a16872..c179563422013 100644 --- a/src/gf.c +++ b/src/gf.c @@ -146,7 +146,7 @@ static int8_t jl_cachearg_offset(jl_methtable_t *mt) /// ----- Insertion logic for special entries ----- /// // get or create the MethodInstance for a specialization -JL_DLLEXPORT jl_method_instance_t *jl_specializations_get_linfo(jl_method_t *m JL_PROPAGATES_ROOT, jl_value_t *type, jl_svec_t *sparams, size_t world) +JL_DLLEXPORT jl_method_instance_t *jl_specializations_get_linfo(jl_method_t *m, jl_value_t *type, jl_svec_t *sparams, size_t world) { assert(world >= m->min_world && "typemap lookup is corrupted"); JL_LOCK(&m->writelock); @@ -204,7 +204,7 @@ JL_DLLEXPORT jl_value_t *jl_methtable_lookup(jl_methtable_t *mt, jl_value_t *typ JL_DLLEXPORT jl_method_t *jl_new_method_uninit(jl_module_t*); -void jl_mk_builtin_func(jl_datatype_t *dt, const char *name, jl_fptr_args_t fptr) JL_GC_DISABLED +void jl_mk_builtin_func(jl_datatype_t *dt, const char *name, jl_fptr_args_t fptr) { jl_sym_t *sname = jl_symbol(name); if (dt == NULL) { @@ -240,7 +240,7 @@ void jl_mk_builtin_func(jl_datatype_t *dt, const char *name, jl_fptr_args_t fptr // returns the inferred source, and may cache the result in li // if successful, also updates the li argument to describe the validity of this src // if inference doesn't occur (or can't finish), returns NULL instead -jl_code_info_t *jl_type_infer(jl_method_instance_t **pli JL_ROOTS_TEMPORARILY, size_t world, int force) +jl_code_info_t *jl_type_infer(jl_method_instance_t **pli, size_t world, int force) { JL_TIMING(INFERENCE); if (jl_typeinf_func == NULL) @@ -289,7 +289,7 @@ jl_code_info_t *jl_type_infer(jl_method_instance_t **pli JL_ROOTS_TEMPORARILY, s return src; } -int jl_is_rettype_inferred(jl_method_instance_t *li) JL_NOTSAFEPOINT +int jl_is_rettype_inferred(jl_method_instance_t *li) { if (!li->inferred) return 0; @@ -333,7 +333,7 @@ static void update_world_bound(jl_method_instance_t *replaced, jl_typemap_visito // update the world-valid in the specializations caches jl_typemap_visitor(m->specializations, fptr, (void*)&update); // update the world-valid in the invoke cache - if (m->invokes != NULL) + if (m->invokes.unknown != NULL) jl_typemap_visitor(m->invokes, fptr, (void*)&update); // update the world-valid in the gf cache jl_datatype_t *gf = jl_first_argument_datatype((jl_value_t*)m->sig); @@ -510,8 +510,8 @@ void jl_foreach_reachable_mtable(void (*visit)(jl_methtable_t *mt, void *env), v static void reset_mt_caches(jl_methtable_t *mt, void *env) { // removes all method caches - if (mt->defs != jl_nothing) // make sure not to reset builtin functions - mt->cache = jl_nothing; + if (mt->defs.unknown != jl_nothing) // make sure not to reset builtin functions + mt->cache.unknown = jl_nothing; jl_typemap_visitor(mt->defs, get_method_unspec_list, env); } @@ -576,7 +576,7 @@ jl_value_t *jl_nth_slot_type(jl_value_t *sig, size_t i) // return 1; //} -static jl_value_t *ml_matches(jl_typemap_t *ml, int offs, +static jl_value_t *ml_matches(union jl_typemap_t ml, int offs, jl_tupletype_t *type, int lim, int include_ambiguous, size_t world, size_t *min_valid, size_t *max_valid); @@ -587,7 +587,7 @@ static void jl_compilation_sig( jl_method_t *definition, intptr_t nspec, // output: - jl_svec_t **const newparams JL_REQUIRE_ROOTED_SLOT) + jl_svec_t **const newparams) { if (definition->generator) { // staged functions aren't optimized @@ -921,7 +921,7 @@ JL_DLLEXPORT int jl_isa_compileable_sig( } static jl_method_instance_t *cache_method( - jl_methtable_t *mt, jl_typemap_t **cache, jl_value_t *parent JL_PROPAGATES_ROOT, + jl_methtable_t *mt, union jl_typemap_t *cache, jl_value_t *parent, jl_tupletype_t *tt, // the original tupletype of the signature jl_method_t *definition, size_t world, @@ -1152,7 +1152,7 @@ void print_func_loc(JL_STREAM *s, jl_method_t *m) */ struct ambiguous_matches_env { struct typemap_intersection_env match; - jl_typemap_t *defs; + union jl_typemap_t defs; jl_typemap_entry_t *newentry; jl_value_t *shadowed; int after; @@ -1167,7 +1167,7 @@ static int check_ambiguous_visitor(jl_typemap_entry_t *oldentry, struct typemap_ } if (oldentry->max_world < ~(size_t)0) return 1; - jl_typemap_t *map = closure->defs; + union jl_typemap_t map = closure->defs; jl_tupletype_t *type = (jl_tupletype_t*)closure->match.type; jl_method_t *m = closure->newentry->func.method; jl_tupletype_t *sig = oldentry->sig; @@ -1248,7 +1248,7 @@ static int check_ambiguous_visitor(jl_typemap_entry_t *oldentry, struct typemap_ return 1; } -static jl_value_t *check_ambiguous_matches(jl_typemap_t *defs, jl_typemap_entry_t *newentry, jl_typemap_intersection_visitor_fptr fptr) +static jl_value_t *check_ambiguous_matches(union jl_typemap_t defs, jl_typemap_entry_t *newentry, jl_typemap_intersection_visitor_fptr fptr) { jl_tupletype_t *type = newentry->sig; jl_tupletype_t *ttypes = (jl_tupletype_t*)jl_unwrap_unionall((jl_value_t*)type); @@ -1395,35 +1395,32 @@ static int invalidate_backedges(jl_typemap_entry_t *oldentry, struct typemap_int { struct invalidate_conflicting_env *closure = container_of(closure0, struct invalidate_conflicting_env, match); if (oldentry->max_world > closure->max_world) { - jl_method_instance_t *replaced_linfo = oldentry->func.linfo; - { - struct set_world def; - def.replaced = oldentry->func.linfo; - def.world = closure->max_world; - jl_method_t *m = def.replaced->def.method; - - // truncate the max-valid in the invoke cache - if (m->invokes != NULL) - jl_typemap_visitor(m->invokes, set_max_world2, (void*)&def); - // invalidate mt cache entries - jl_datatype_t *gf = jl_first_argument_datatype((jl_value_t*)m->sig); - assert(jl_is_datatype(gf) && gf->name->mt && "method signature invalid?"); - jl_typemap_visitor(gf->name->mt->cache, set_max_world2, (void*)&def); - } + struct set_world def; + def.replaced = oldentry->func.linfo; + def.world = closure->max_world; + jl_method_t *m = def.replaced->def.method; + + // truncate the max-valid in the invoke cache + if (m->invokes.unknown != NULL) + jl_typemap_visitor(m->invokes, set_max_world2, (void*)&def); + // invalidate mt cache entries + jl_datatype_t *gf = jl_first_argument_datatype((jl_value_t*)m->sig); + assert(jl_is_datatype(gf) && gf->name->mt && "method signature invalid?"); + jl_typemap_visitor(gf->name->mt->cache, set_max_world2, (void*)&def); // invalidate backedges - JL_LOCK_NOGC(&replaced_linfo->def.method->writelock); - jl_array_t *backedges = replaced_linfo->backedges; + JL_LOCK_NOGC(&def.replaced->def.method->writelock); + jl_array_t *backedges = def.replaced->backedges; if (backedges) { size_t i, l = jl_array_len(backedges); - jl_method_instance_t **replaced = (jl_method_instance_t**)jl_array_ptr_data(backedges); + jl_method_instance_t **replaced = (jl_method_instance_t**)jl_array_data(backedges); for (i = 0; i < l; i++) { invalidate_method_instance(replaced[i], closure->max_world, 0); } } closure->invalidated = 1; - replaced_linfo->backedges = NULL; - JL_UNLOCK_NOGC(&replaced_linfo->def.method->writelock); + def.replaced->backedges = NULL; + JL_UNLOCK_NOGC(&def.replaced->def.method->writelock); } return 1; } @@ -1497,20 +1494,11 @@ static int typemap_search(jl_typemap_entry_t *entry, void *closure) return 1; } -static jl_typemap_entry_t *do_typemap_search(jl_methtable_t *mt JL_PROPAGATES_ROOT, jl_method_t *method) JL_NOTSAFEPOINT; - -#ifndef __clang_analyzer__ -static jl_typemap_entry_t *do_typemap_search(jl_methtable_t *mt JL_PROPAGATES_ROOT, jl_method_t *method) JL_NOTSAFEPOINT { - jl_value_t *closure = (jl_value_t*)(method); - if (jl_typemap_visitor(mt->defs, typemap_search, &closure)) - jl_error("method not in method table"); - return (jl_typemap_entry_t *)closure; -} -#endif - JL_DLLEXPORT void jl_method_table_disable(jl_methtable_t *mt, jl_method_t *method) { - jl_typemap_entry_t *methodentry = do_typemap_search(mt, method); + jl_typemap_entry_t *methodentry = (jl_typemap_entry_t*)(method); + if (jl_typemap_visitor(mt->defs, typemap_search, &methodentry)) + jl_error("method not in method table"); JL_LOCK(&mt->writelock); // Narrow the world age on the method to make it uncallable methodentry->max_world = jl_world_counter++; @@ -1551,7 +1539,7 @@ JL_DLLEXPORT void jl_method_table_insert(jl_methtable_t *mt, jl_method_t *method else { oldvalue = check_ambiguous_matches(mt->defs, newentry, check_ambiguous_visitor); if (mt->backedges) { - jl_value_t **backedges = jl_array_ptr_data(mt->backedges); + jl_value_t **backedges = (jl_value_t**)jl_array_data(mt->backedges); size_t i, na = jl_array_len(mt->backedges); size_t ins = 0; for (i = 1; i < na; i += 2) { @@ -1874,7 +1862,7 @@ JL_DLLEXPORT int32_t jl_invoke_api(jl_method_instance_t *mi) } // compile-time method lookup -jl_method_instance_t *jl_get_specialization1(jl_tupletype_t *types JL_PROPAGATES_ROOT, size_t world, int mt_cache) +jl_method_instance_t *jl_get_specialization1(jl_tupletype_t *types, size_t world, int mt_cache) { JL_TIMING(METHOD_LOOKUP_COMPILE); if (jl_has_free_typevars((jl_value_t*)types)) @@ -1960,7 +1948,6 @@ JL_DLLEXPORT int jl_compile_hint(jl_tupletype_t *types) // additional useful methods that should be compiled //ALT: if (jl_is_datatype(types) && ((jl_datatype_t*)types)->isdispatchtuple && !jl_egal(li->specTypes, types)) //ALT: if (jl_subtype(types, li->specTypes)) - JL_GC_PROMISE_ROOTED(li); if (!jl_subtype(li->specTypes, (jl_value_t*)types)) { jl_svec_t *tpenv2 = jl_emptysvec; jl_value_t *types2 = NULL; @@ -2051,7 +2038,7 @@ static void show_call(jl_value_t *F, jl_value_t **args, uint32_t nargs) } #endif -static jl_value_t *verify_type(jl_value_t *v) JL_NOTSAFEPOINT +static jl_value_t *verify_type(jl_value_t *v) { assert(jl_typeof(jl_typeof(v))); return v; @@ -2074,7 +2061,7 @@ STATIC_INLINE int sig_match_fast(jl_value_t **args, jl_value_t **sig, size_t i, return 1; } -jl_typemap_entry_t *call_cache[N_CALL_CACHE] JL_GLOBALLY_ROOTED; +jl_typemap_entry_t *call_cache[N_CALL_CACHE]; static uint8_t pick_which[N_CALL_CACHE]; #ifdef JL_GF_PROFILE size_t ncalls; @@ -2192,12 +2179,11 @@ JL_DLLEXPORT jl_value_t *jl_apply_generic(jl_value_t **args, uint32_t nargs) jl_method_instance_t *mfunc = jl_lookup_generic_(args, nargs, jl_int32hash_fast(jl_return_address()), jl_get_ptls_states()->world_age); - JL_GC_PROMISE_ROOTED(mfunc); jl_value_t *res = mfunc->invoke(mfunc, args, nargs); return verify_type(res); } -JL_DLLEXPORT jl_value_t *jl_gf_invoke_lookup(jl_value_t *types JL_PROPAGATES_ROOT, size_t world) +JL_DLLEXPORT jl_value_t *jl_gf_invoke_lookup(jl_value_t *types, size_t world) { jl_methtable_t *mt = jl_first_argument_datatype(types)->name->mt; jl_svec_t *env = jl_emptysvec; @@ -2244,7 +2230,7 @@ jl_value_t *jl_gf_invoke(jl_value_t *types0, jl_value_t **args, size_t nargs) jl_method_t *method = entry->func.method; jl_method_instance_t *mfunc = NULL; jl_typemap_entry_t *tm = NULL; - if (method->invokes != NULL) + if (method->invokes.unknown != NULL) tm = jl_typemap_assoc_exact(method->invokes, args, nargs, jl_cachearg_offset(mt), world); if (tm) { mfunc = tm->func.linfo; @@ -2257,14 +2243,13 @@ jl_value_t *jl_gf_invoke(jl_value_t *types0, jl_value_t **args, size_t nargs) assert(sub); (void)sub; } - if (method->invokes == NULL) - method->invokes = jl_nothing; + if (method->invokes.unknown == NULL) + method->invokes.unknown = jl_nothing; mfunc = cache_method(mt, &method->invokes, entry->func.value, tt, method, world, tpenv, 1); JL_UNLOCK(&method->writelock); } JL_GC_POP(); - JL_GC_PROMISE_ROOTED(mfunc); return mfunc->invoke(mfunc, args, nargs); } @@ -2279,7 +2264,7 @@ JL_DLLEXPORT jl_value_t *jl_get_invoke_lambda(jl_methtable_t *mt, jl_method_t *method = entry->func.method; jl_typemap_entry_t *tm = NULL; - if (method->invokes != NULL) { + if (method->invokes.unknown != NULL) { tm = jl_typemap_assoc_by_type(method->invokes, tt, NULL, /*subtype*/1, jl_cachearg_offset(mt), world, /*max_world_mask*/0); if (tm) { @@ -2288,7 +2273,7 @@ JL_DLLEXPORT jl_value_t *jl_get_invoke_lambda(jl_methtable_t *mt, } JL_LOCK(&method->writelock); - if (method->invokes != NULL) { + if (method->invokes.unknown != NULL) { tm = jl_typemap_assoc_by_type(method->invokes, tt, NULL, /*subtype*/1, jl_cachearg_offset(mt), world, /*max_world_mask*/0); if (tm) { @@ -2306,8 +2291,8 @@ JL_DLLEXPORT jl_value_t *jl_get_invoke_lambda(jl_methtable_t *mt, (void)ti; } - if (method->invokes == NULL) - method->invokes = jl_nothing; + if (method->invokes.unknown == NULL) + method->invokes.unknown = jl_nothing; jl_method_instance_t *mfunc = cache_method(mt, &method->invokes, entry->func.value, (jl_tupletype_t*)tt, method, world, tpenv, 1); @@ -2502,7 +2487,7 @@ static int ml_matches_visitor(jl_typemap_entry_t *ml, struct typemap_intersectio // // Returns a match as an array of svec(argtypes, static_params, Method). // See below for the meaning of lim. -static jl_value_t *ml_matches(jl_typemap_t *defs, int offs, +static jl_value_t *ml_matches(union jl_typemap_t defs, int offs, jl_tupletype_t *type, int lim, int include_ambiguous, size_t world, size_t *min_valid, size_t *max_valid) { diff --git a/src/init.c b/src/init.c index 5bfd0fbf3d48b..660868e4d3d00 100644 --- a/src/init.c +++ b/src/init.c @@ -278,7 +278,6 @@ JL_DLLEXPORT void jl_atexit_hook(int exitcode) } JL_CATCH { //error handling -- continue cleanup, as much as possible - assert(item); uv_unref(item->h); jl_printf(JL_STDERR, "error during exit cleanup: close: "); jl_static_show(JL_STDERR, ptls->exception_in_transit); @@ -593,8 +592,6 @@ static void jl_resolve_sysimg_location(JL_IMAGE_SEARCH rel) jl_options.outputbc = abspath(jl_options.outputbc, 0); if (jl_options.machine_file) jl_options.machine_file = abspath(jl_options.machine_file, 0); - if (jl_options.project && strncmp(jl_options.project, "@.", strlen(jl_options.project)) != 0) - jl_options.project = abspath(jl_options.project, 0); const char **cmdp = jl_options.cmds; if (cmdp) { diff --git a/src/interpreter.c b/src/interpreter.c index deb0d8986b770..030fb4a709912 100644 --- a/src/interpreter.c +++ b/src/interpreter.c @@ -124,7 +124,7 @@ SECT_INTERP void jl_set_datatype_super(jl_datatype_t *tt, jl_value_t *super) static void eval_abstracttype(jl_expr_t *ex, interpreter_state *s) { - jl_value_t **args = jl_array_ptr_data(ex->args); + jl_value_t **args = (jl_value_t**)jl_array_data(ex->args); if (inside_typedef) jl_error("cannot eval a new abstract type definition while defining another type"); jl_value_t *name = args[0]; @@ -134,7 +134,7 @@ static void eval_abstracttype(jl_expr_t *ex, interpreter_state *s) jl_datatype_t *dt = NULL; jl_value_t *w = NULL; jl_module_t *modu = s->module; - JL_GC_PUSH5(¶, &super, &temp, &w, &dt); + JL_GC_PUSH4(¶, &super, &temp, &w); assert(jl_is_svec(para)); if (jl_is_globalref(name)) { modu = jl_globalref_mod(name); @@ -168,7 +168,7 @@ static void eval_abstracttype(jl_expr_t *ex, interpreter_state *s) static void eval_primitivetype(jl_expr_t *ex, interpreter_state *s) { - jl_value_t **args = (jl_value_t**)jl_array_ptr_data(ex->args); + jl_value_t **args = (jl_value_t**)jl_array_data(ex->args); if (inside_typedef) jl_error("cannot eval a new primitive type definition while defining another type"); jl_value_t *name = args[0]; @@ -219,7 +219,7 @@ static void eval_primitivetype(jl_expr_t *ex, interpreter_state *s) static void eval_structtype(jl_expr_t *ex, interpreter_state *s) { - jl_value_t **args = jl_array_ptr_data(ex->args); + jl_value_t **args = (jl_value_t**)jl_array_data(ex->args); if (inside_typedef) jl_error("cannot eval a new struct type definition while defining another type"); jl_value_t *name = args[0]; @@ -285,7 +285,7 @@ static void eval_structtype(jl_expr_t *ex, interpreter_state *s) static jl_value_t *eval_methoddef(jl_expr_t *ex, interpreter_state *s) { - jl_value_t **args = jl_array_ptr_data(ex->args); + jl_value_t **args = (jl_value_t**)jl_array_data(ex->args); jl_sym_t *fname = (jl_sym_t*)args[0]; jl_module_t *modu = s->module; if (jl_is_globalref(fname)) { @@ -348,12 +348,12 @@ SECT_INTERP jl_value_t *jl_eval_global_var(jl_module_t *m, jl_sym_t *e) return v; } -SECT_INTERP static int jl_source_nslots(jl_code_info_t *src) JL_NOTSAFEPOINT +SECT_INTERP static int jl_source_nslots(jl_code_info_t *src) { return jl_array_len(src->slotflags); } -SECT_INTERP static int jl_source_nssavalues(jl_code_info_t *src) JL_NOTSAFEPOINT +SECT_INTERP static int jl_source_nssavalues(jl_code_info_t *src) { return jl_is_long(src->ssavaluetypes) ? jl_unbox_long(src->ssavaluetypes) : jl_array_len(src->ssavaluetypes); } @@ -397,9 +397,7 @@ SECT_INTERP static jl_value_t *eval_value(jl_value_t *e, interpreter_state *s) if (jl_is_pinode(e)) { jl_value_t *val = eval_value(jl_fieldref_noalloc(e, 0), s); #ifndef JL_NDEBUG - JL_GC_PUSH1(&val); jl_typeassert(val, jl_fieldref_noalloc(e, 1)); - JL_GC_POP(); #endif return val; } @@ -417,13 +415,13 @@ SECT_INTERP static jl_value_t *eval_value(jl_value_t *e, interpreter_state *s) // edges list doesn't contain last branch. this value should be unused. return NULL; } - jl_value_t *val = jl_array_ptr_ref((jl_array_t*)jl_fieldref_noalloc(e, 1), edge); + jl_value_t *val = jl_arrayref((jl_array_t*)jl_fieldref_noalloc(e, 1), edge); return eval_value(val, s); } if (!jl_is_expr(e)) return e; jl_expr_t *ex = (jl_expr_t*)e; - jl_value_t **args = jl_array_ptr_data(ex->args); + jl_value_t **args = (jl_value_t**)jl_array_data(ex->args); size_t nargs = jl_array_len(ex->args); jl_sym_t *head = ex->head; if (head == call_sym) { @@ -746,7 +744,6 @@ SECT_INTERP CALLBACK_ABI void *jl_interpret_call_callback(interpreter_state *s, { struct jl_interpret_call_args *args = (struct jl_interpret_call_args *)vargs; - JL_GC_PROMISE_ROOTED(args); jl_code_info_t *src = jl_code_for_interpreter(args->lam); args->lam->inferred = (jl_value_t*)src; jl_gc_wb(args->lam, src); @@ -788,7 +785,6 @@ struct jl_interpret_toplevel_thunk_args { SECT_INTERP CALLBACK_ABI void *jl_interpret_toplevel_thunk_callback(interpreter_state *s, void *vargs) { struct jl_interpret_toplevel_thunk_args *args = (struct jl_interpret_toplevel_thunk_args*)vargs; - JL_GC_PROMISE_ROOTED(args); jl_array_t *stmts = args->src->code; assert(jl_typeis(stmts, jl_array_any_type)); jl_value_t **locals; @@ -826,7 +822,6 @@ SECT_INTERP CALLBACK_ABI void *jl_interpret_toplevel_expr_in_callback(interprete { struct interpret_toplevel_expr_in_args *args = (struct interpret_toplevel_expr_in_args*)vargs; - JL_GC_PROMISE_ROOTED(args); jl_ptls_t ptls = jl_get_ptls_states(); jl_value_t *v=NULL; jl_module_t *last_m = ptls->current_module; diff --git a/src/intrinsics.cpp b/src/intrinsics.cpp index 50ace324ea313..eec4cf75f524b 100644 --- a/src/intrinsics.cpp +++ b/src/intrinsics.cpp @@ -281,7 +281,11 @@ static Value *emit_unboxed_coercion(jl_codectx_t &ctx, Type *to, Value *unboxed) Type *ty = unboxed->getType(); bool frompointer = ty->isPointerTy(); bool topointer = to->isPointerTy(); +#if JL_LLVM_VERSION >= 40000 const DataLayout &DL = jl_data_layout; +#else + const DataLayout &DL = jl_ExecutionEngine->getDataLayout(); +#endif if (ty == T_int1 && to == T_int8) { // bools may be stored internally as int8 unboxed = ctx.builder.CreateZExt(unboxed, T_int8); @@ -377,7 +381,11 @@ static Value *emit_unbox(jl_codectx_t &ctx, Type *to, const jl_cgval_t &x, jl_va // appropriate coercion manually. AllocaInst *AI = cast(p); Type *AllocType = AI->getAllocatedType(); +#if JL_LLVM_VERSION >= 40000 const DataLayout &DL = jl_data_layout; +#else + const DataLayout &DL = jl_ExecutionEngine->getDataLayout(); +#endif if (!AI->isArrayAllocation() && (AllocType->isFloatingPointTy() || AllocType->isIntegerTy() || AllocType->isPointerTy()) && (to->isFloatingPointTy() || to->isIntegerTy() || to->isPointerTy()) && @@ -747,10 +755,18 @@ struct math_builder { if (jl_options.fast_math != JL_OPTIONS_FAST_MATH_OFF && (always_fast || jl_options.fast_math == JL_OPTIONS_FAST_MATH_ON)) { +#if JL_LLVM_VERSION >= 60000 fmf.setFast(); +#else + fmf.setUnsafeAlgebra(); +#endif } +#if JL_LLVM_VERSION >= 50000 if (contract) fmf.setAllowContract(true); +#else + assert(!contract); +#endif ctxbuilder.setFastMathFlags(fmf); } IRBuilder<>& operator()() const { return ctxbuilder; } @@ -1063,11 +1079,18 @@ static Value *emit_untyped_intrinsic(jl_codectx_t &ctx, intrinsic f, Value **arg return ctx.builder.CreateCall(fmaintr, {x, y, z}); } case muladd_float: { +#if JL_LLVM_VERSION >= 50000 // LLVM 5.0 can create FMA in the backend for contractable fmul and fadd // Emitting fmul and fadd here since they are easier for other LLVM passes to // optimize. auto mathb = math_builder(ctx, false, true); return mathb().CreateFAdd(mathb().CreateFMul(x, y), z); +#else + assert(y->getType() == x->getType()); + assert(z->getType() == y->getType()); + Value *muladdintr = Intrinsic::getDeclaration(jl_Module, Intrinsic::fmuladd, makeArrayRef(t)); + return ctx.builder.CreateCall(muladdintr, {x, y, z}); +#endif } case checked_sadd_int: diff --git a/src/jitlayers.cpp b/src/jitlayers.cpp index f21994c2707a0..81de43d6f5a3c 100644 --- a/src/jitlayers.cpp +++ b/src/jitlayers.cpp @@ -28,13 +28,19 @@ #include #include #include +#if JL_LLVM_VERSION >= 40000 #include +#endif namespace llvm { extern Pass *createLowerSimdLoopPass(); } -#include +#if JL_LLVM_VERSION >= 40000 +# include +#else +# include +#endif #include #include @@ -48,6 +54,7 @@ namespace llvm { #include #include + #include #include #include @@ -111,13 +118,27 @@ void addOptimizationPasses(legacy::PassManagerBase *PM, int opt_level, bool dump PM->add(createInstructionCombiningPass()); // Cleanup for scalarrepl. PM->add(createEarlyCSEPass()); } +#if JL_LLVM_VERSION < 50000 + PM->add(createBarrierNoopPass()); + PM->add(createLowerExcHandlersPass()); + PM->add(createGCInvariantVerifierPass(false)); + PM->add(createLateLowerGCFramePass()); + PM->add(createLowerPTLSPass(dump_native)); + PM->add(createBarrierNoopPass()); +#endif PM->add(createMemCpyOptPass()); // Remove memcpy / form memset +#if JL_LLVM_VERSION >= 40000 PM->add(createAlwaysInlinerLegacyPass()); // Respect always_inline +#else + PM->add(createAlwaysInlinerPass()); // Respect always_inline +#endif +#if JL_LLVM_VERSION >= 50000 PM->add(createBarrierNoopPass()); PM->add(createLowerExcHandlersPass()); PM->add(createGCInvariantVerifierPass(false)); PM->add(createLateLowerGCFramePass()); PM->add(createLowerPTLSPass(dump_native)); +#endif PM->add(createLowerSimdLoopPass()); // Annotate loop marked with "simdloop" as LLVM parallel loop if (dump_native) PM->add(createMultiVersioningPass()); @@ -133,14 +154,32 @@ void addOptimizationPasses(legacy::PassManagerBase *PM, int opt_level, bool dump PM->add(createDeadCodeEliminationPass()); PM->add(createSROAPass()); // Kill useless allocas + // Due to bugs and missing features LLVM < 5.0, does not properly propagate + // our invariants. We need to do GC rooting here. This reduces the + // effectiveness of the optimization, but should retain correctness. +#if JL_LLVM_VERSION < 50000 + PM->add(createLowerExcHandlersPass()); + PM->add(createAllocOptPass()); + PM->add(createLateLowerGCFramePass()); + // Remove dead use of ptls + PM->add(createDeadCodeEliminationPass()); + PM->add(createLowerPTLSPass(dump_native)); +#endif + PM->add(createMemCpyOptPass()); +#if JL_LLVM_VERSION >= 40000 PM->add(createAlwaysInlinerLegacyPass()); // Respect always_inline +#else + PM->add(createAlwaysInlinerPass()); // Respect always_inline +#endif +#if JL_LLVM_VERSION >= 50000 // Running `memcpyopt` between this and `sroa` seems to give `sroa` a hard time // merging the `alloca` for the unboxed data and the `alloca` created by the `alloc_opt` // pass. PM->add(createAllocOptPass()); +#endif PM->add(createInstructionCombiningPass()); // Cleanup for scalarrepl. // Now that SROA has cleaned up for front-end mess, a lot of control flow should // be more evident - try to clean it up. @@ -160,9 +199,11 @@ void addOptimizationPasses(legacy::PassManagerBase *PM, int opt_level, bool dump PM->add(createEarlyCSEPass()); //// **** +#if JL_LLVM_VERSION >= 50000 // Load forwarding above can expose allocations that aren't actually used // remove those before optimizing loops. PM->add(createAllocOptPass()); +#endif PM->add(createLoopIdiomPass()); //// **** PM->add(createLoopRotatePass()); // Rotate loops. #ifdef USE_POLLY @@ -185,8 +226,10 @@ void addOptimizationPasses(legacy::PassManagerBase *PM, int opt_level, bool dump PM->add(createSimpleLoopUnrollPass()); // Unroll small loops //PM->add(createLoopStrengthReducePass()); // (jwb added) +#if JL_LLVM_VERSION >= 50000 // Run our own SROA on heap objects before LLVM's PM->add(createAllocOptPass()); +#endif // Re-run SROA after loop-unrolling (useful for small loops that operate, // over the structure of an aggregate) PM->add(createSROAPass()); // Break up aggregate allocas @@ -203,8 +246,10 @@ void addOptimizationPasses(legacy::PassManagerBase *PM, int opt_level, bool dump PM->add(createJumpThreadingPass()); // Thread jumps PM->add(createDeadStoreEliminationPass()); // Delete dead stores +#if JL_LLVM_VERSION >= 50000 // More dead allocation (store) deletion before loop optimization PM->add(createAllocOptPass()); +#endif // see if all of the constant folding has exposed more loops // to simplification and deletion // this helps significantly with cleaning up iteration @@ -220,6 +265,7 @@ void addOptimizationPasses(legacy::PassManagerBase *PM, int opt_level, bool dump // LowerPTLS removes an indirect call. As a result, it is likely to trigger // LLVM's devirtualization heuristics, which would result in the entire // pass pipeline being re-exectuted. Prevent this by inserting a barrier. +#if JL_LLVM_VERSION >= 50000 PM->add(createBarrierNoopPass()); PM->add(createLowerExcHandlersPass()); PM->add(createGCInvariantVerifierPass(false)); @@ -229,6 +275,7 @@ void addOptimizationPasses(legacy::PassManagerBase *PM, int opt_level, bool dump PM->add(createLowerPTLSPass(dump_native)); // Clean up write barrier and ptls lowering PM->add(createCFGSimplificationPass()); +#endif PM->add(createCombineMulAddPass()); } @@ -237,6 +284,72 @@ void jl_add_optimization_passes(LLVMPassManagerRef PM, int opt_level) { addOptimizationPasses(unwrap(PM), opt_level); } +// ------------------------ TEMPORARILY COPIED FROM LLVM ----------------- +// This must be kept in sync with gdb/gdb/jit.h . +extern "C" { + + typedef enum { + JIT_NOACTION = 0, + JIT_REGISTER_FN, + JIT_UNREGISTER_FN + } jit_actions_t; + + struct jit_code_entry { + struct jit_code_entry *next_entry; + struct jit_code_entry *prev_entry; + const char *symfile_addr; + uint64_t symfile_size; + }; + + struct jit_descriptor { + uint32_t version; + // This should be jit_actions_t, but we want to be specific about the + // bit-width. + uint32_t action_flag; + struct jit_code_entry *relevant_entry; + struct jit_code_entry *first_entry; + }; + + // We put information about the JITed function in this global, which the + // debugger reads. Make sure to specify the version statically, because the + // debugger checks the version before we can set it during runtime. + extern struct jit_descriptor __jit_debug_descriptor; + + LLVM_ATTRIBUTE_NOINLINE extern void __jit_debug_register_code(); +} + +namespace { + +// Use a local variable to hold the addresses to avoid generating a PLT +// on the function call. +// It messes up the GDB lookup logic with dynamically linked LLVM. +// (Ref https://sourceware.org/bugzilla/show_bug.cgi?id=20633) +// Use `volatile` to make sure the call always loads this slot. +void (*volatile jit_debug_register_code)() = __jit_debug_register_code; + +using namespace llvm; +using namespace llvm::object; +using namespace llvm::orc; + +/// Do the registration. +void NotifyDebugger(jit_code_entry *JITCodeEntry) +{ + __jit_debug_descriptor.action_flag = JIT_REGISTER_FN; + + // Insert this entry at the head of the list. + JITCodeEntry->prev_entry = nullptr; + jit_code_entry *NextEntry = __jit_debug_descriptor.first_entry; + JITCodeEntry->next_entry = NextEntry; + if (NextEntry) { + NextEntry->prev_entry = JITCodeEntry; + } + __jit_debug_descriptor.first_entry = JITCodeEntry; + __jit_debug_descriptor.relevant_entry = JITCodeEntry; + jit_debug_register_code(); +} +} +// ------------------------ END OF TEMPORARY COPY FROM LLVM ----------------- + #if defined(_OS_LINUX_) || defined(_OS_WINDOWS_) || defined(_OS_FREEBSD_) // Resolve non-lock free atomic functions in the libatomic1 library. // This is the library that provides support for c11/c++11 atomic operations. @@ -276,7 +389,7 @@ template void JuliaOJIT::DebugObjectRegistrar::registerObject(RTDyldObjHandleT H, const ObjT &Object, const LoadResult &LO) { - object::OwningBinary SavedObject = LO->getObjectForDebug(*Object); + OwningBinary SavedObject = LO->getObjectForDebug(*Object); // If the debug object is unavailable, save (a copy of) the original object // for our backtraces @@ -285,15 +398,16 @@ void JuliaOJIT::DebugObjectRegistrar::registerObject(RTDyldObjHandleT H, const O // ownership of the original buffer auto NewBuffer = MemoryBuffer::getMemBufferCopy(Object->getData(), Object->getFileName()); - auto NewObj = object::ObjectFile::createObjectFile(NewBuffer->getMemBufferRef()); + auto NewObj = ObjectFile::createObjectFile(NewBuffer->getMemBufferRef()); assert(NewObj); - SavedObject = object::OwningBinary(std::move(*NewObj), + SavedObject = OwningBinary(std::move(*NewObj), std::move(NewBuffer)); } else { - JIT.NotifyFinalizer(*(SavedObject.getBinary()), *LO); + NotifyGDB(SavedObject); } + JIT.NotifyFinalizer(*Object, *LO); SavedObjects.push_back(std::move(SavedObject)); ORCNotifyObjectEmitted(JuliaListener.get(), *Object, @@ -316,18 +430,52 @@ void JuliaOJIT::DebugObjectRegistrar::registerObject(RTDyldObjHandleT H, const O // note: calling getAddress here eagerly finalizes H // as an alternative, we could store the JITSymbol instead // (which would present a lazy-initializer functor interface instead) +#if JL_LLVM_VERSION >= 50000 JIT.LocalSymbolTable[Name] = (void*)(uintptr_t)cantFail(Sym.getAddress()); +#else + JIT.LocalSymbolTable[Name] = (void*)(uintptr_t)Sym.getAddress(); +#endif } } +// TODO: hook up RegisterJITEventListener, instead of hard-coding the GDB and JuliaListener targets template void JuliaOJIT::DebugObjectRegistrar::operator()(RTDyldObjHandleT H, const ObjSetT &Objects, const LoadResult &LOS) { +#if JL_LLVM_VERSION >= 50000 registerObject(H, Objects->getBinary(), static_cast(&LOS)); +#else + auto oit = Objects.begin(); + auto lit = LOS.begin(); + for (; oit != Objects.end(); ++oit, ++lit) { + const auto &Object = (*oit)->getBinary(); + auto &LO = *lit; + + registerObject(H, Object, LO); + } +#endif } +void JuliaOJIT::DebugObjectRegistrar::NotifyGDB(OwningBinary &DebugObj) +{ + const char *Buffer = DebugObj.getBinary()->getMemoryBufferRef().getBufferStart(); + size_t Size = DebugObj.getBinary()->getMemoryBufferRef().getBufferSize(); + + assert(Buffer && "Attempt to register a null object with a debugger."); + jit_code_entry *JITCodeEntry = new jit_code_entry(); + + if (!JITCodeEntry) { + jl_printf(JL_STDERR, "WARNING: Allocation failed when registering a JIT entry!\n"); + } + else { + JITCodeEntry->symfile_addr = Buffer; + JITCodeEntry->symfile_size = Size; + + NotifyDebugger(JITCodeEntry); + } +} object::OwningBinary JuliaOJIT::CompilerT::operator()(Module &M) { @@ -357,7 +505,9 @@ JuliaOJIT::JuliaOJIT(TargetMachine &TM) MemMgr(createRTDyldMemoryManager()), registrar(*this), ObjectLayer( +#if JL_LLVM_VERSION >= 50000 [&] { return MemMgr; }, +#endif std::ref(registrar) ), CompileLayer( @@ -435,9 +585,14 @@ void JuliaOJIT::addModule(std::unique_ptr M) // Step 0: ObjectLinkingLayer has checked whether it is in the current module // Step 1: See if it's something known to the ExecutionEngine if (auto Sym = findSymbol(Name, true)) { +#if JL_LLVM_VERSION >= 40000 // `findSymbol` already eagerly resolved the address // return it directly. return Sym; +#else + return RuntimeDyld::SymbolInfo(Sym.getAddress(), + Sym.getFlags()); +#endif } // Step 2: Search the program symbols if (uint64_t addr = SectionMemoryManager::getSymbolAddressInProcess(Name)) @@ -451,17 +606,32 @@ void JuliaOJIT::addModule(std::unique_ptr M) }, [](const std::string &S) { return nullptr; } ); +#if JL_LLVM_VERSION >= 50000 auto modset = cantFail(CompileLayer.addModule(std::move(M), std::move(Resolver))); +#else + SmallVector,1> Ms; + Ms.push_back(std::move(M)); + auto modset = CompileLayer.addModuleSet(std::move(Ms), MemMgr.get(), + std::move(Resolver)); +#endif // Force LLVM to emit the module so that we can register the symbols // in our lookup table. +#if JL_LLVM_VERSION >= 50000 auto Err = CompileLayer.emitAndFinalize(modset); // Check for errors to prevent LLVM from crashing the program. assert(!Err); +#else + CompileLayer.emitAndFinalize(modset); +#endif } void JuliaOJIT::removeModule(ModuleHandleT H) { +#if JL_LLVM_VERSION >= 50000 (void)CompileLayer.removeModule(H); +#else + (void)CompileLayer.removeModuleSet(H); +#endif } JL_JITSymbol JuliaOJIT::findSymbol(const std::string &Name, bool ExportedSymbolsOnly) @@ -484,14 +654,22 @@ JL_JITSymbol JuliaOJIT::findUnmangledSymbol(const std::string Name) uint64_t JuliaOJIT::getGlobalValueAddress(const std::string &Name) { +#if JL_LLVM_VERSION >= 50000 auto addr = findSymbol(getMangledName(Name), false).getAddress(); return addr ? addr.get() : 0; +#else + return findSymbol(getMangledName(Name), false).getAddress(); +#endif } uint64_t JuliaOJIT::getFunctionAddress(const std::string &Name) { +#if JL_LLVM_VERSION >= 50000 auto addr = findSymbol(getMangledName(Name), false).getAddress(); return addr ? addr.get() : 0; +#else + return findSymbol(getMangledName(Name), false).getAddress(); +#endif } Function *JuliaOJIT::FindFunctionNamed(const std::string &Name) @@ -878,15 +1056,39 @@ static void emit_result(std::vector &Archive, SmallVectorImpl< static object::Archive::Kind getDefaultForHost(Triple &triple) { if (triple.isOSDarwin()) +#if JL_LLVM_VERSION >= 50000 return object::Archive::K_DARWIN; +#else + return object::Archive::K_BSD; +#endif return object::Archive::K_GNU; } +#if JL_LLVM_VERSION >= 60000 typedef Error ArchiveWriterError; +#else +typedef std::pair ArchiveWriterError; +template +static void handleAllErrors(ArchiveWriterError E, HandlerT Handler) { + if (E.second) + Handler(E); +} +#endif +#if JL_LLVM_VERSION >= 60000 static void reportWriterError(const ErrorInfoBase &E) { std::string err = E.message(); jl_safe_printf("ERROR: failed to emit output file %s\n", err.c_str()); } +#else +static void reportWriterError(ArchiveWriterError E) { + std::string ContextStr = E.first.str(); + std::string err; + if (!ContextStr.empty()) + err += ContextStr + ": "; + err += E.second.message(); + jl_safe_printf("ERROR: failed to emit output file %s\n", err.c_str()); +} +#endif // takes the running content that has collected in the shadow module and dump it to disk // this builds the object file portion of the sysimage files for fast startup @@ -953,9 +1155,13 @@ void jl_dump_native(const char *bc_fname, const char *unopt_bc_fname, const char // Reset the target triple to make sure it matches the new target machine shadow_output->setTargetTriple(TM->getTargetTriple().str()); +#if JL_LLVM_VERSION >= 40000 DataLayout DL = TM->createDataLayout(); DL.reset(DL.getStringRepresentation() + "-ni:10:11:12:13"); shadow_output->setDataLayout(DL); +#else + shadow_output->setDataLayout(TM->createDataLayout()); +#endif // add metadata information if (imaging_mode) { diff --git a/src/jitlayers.h b/src/jitlayers.h index 6f4b8ef5c7b1c..aadda5d534cfb 100644 --- a/src/jitlayers.h +++ b/src/jitlayers.h @@ -10,7 +10,11 @@ #include "llvm/ExecutionEngine/Orc/IRCompileLayer.h" #include "llvm/ExecutionEngine/Orc/LambdaResolver.h" #include "llvm/ExecutionEngine/Orc/LazyEmittingLayer.h" -#include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h" +#if JL_LLVM_VERSION >= 50000 +# include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h" +#else +# include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h" +#endif #include "llvm/ExecutionEngine/ObjectMemoryBuffer.h" #include "llvm/ExecutionEngine/JITEventListener.h" @@ -81,15 +85,25 @@ static inline void add_named_global(GlobalObject *gv, T *addr, bool dllimport = } void jl_init_jit(Type *T_pjlvalue_); +#if JL_LLVM_VERSION >= 40000 typedef JITSymbol JL_JITSymbol; // The type that is similar to SymbolInfo on LLVM 4.0 is actually // `JITEvaluatedSymbol`. However, we only use this type when a JITSymbol // is expected. typedef JITSymbol JL_SymbolInfo; +#else +typedef orc::JITSymbol JL_JITSymbol; +typedef RuntimeDyld::SymbolInfo JL_SymbolInfo; +#endif +#if JL_LLVM_VERSION >= 50000 using RTDyldObjHandleT = orc::RTDyldObjectLinkingLayerBase::ObjHandleT; +#else +using RTDyldObjHandleT = orc::ObjectLinkingLayerBase::ObjSetHandleT; +#endif class JuliaOJIT { // Custom object emission notification handler for the JuliaOJIT + // TODO: hook up RegisterJITEventListener, instead of hard-coding the GDB and JuliaListener targets class DebugObjectRegistrar { public: DebugObjectRegistrar(JuliaOJIT &JIT); @@ -98,6 +112,7 @@ class JuliaOJIT { private: template void registerObject(RTDyldObjHandleT H, const ObjT &Object, const LoadResult &LO); + void NotifyGDB(object::OwningBinary &DebugObj); std::vector> SavedObjects; std::unique_ptr JuliaListener; JuliaOJIT &JIT; @@ -113,9 +128,15 @@ class JuliaOJIT { }; public: +#if JL_LLVM_VERSION >= 50000 typedef orc::RTDyldObjectLinkingLayer ObjLayerT; typedef orc::IRCompileLayer CompileLayerT; typedef CompileLayerT::ModuleHandleT ModuleHandleT; +#else + typedef orc::ObjectLinkingLayer> ObjLayerT; + typedef orc::IRCompileLayer CompileLayerT; + typedef CompileLayerT::ModuleSetHandleT ModuleHandleT; +#endif typedef StringMap SymbolTableT; typedef object::OwningBinary OwningObj; diff --git a/src/jlapi.c b/src/jlapi.c index f88e6fd21a28d..9f92aa25232cd 100644 --- a/src/jlapi.c +++ b/src/jlapi.c @@ -386,7 +386,6 @@ JL_DLLEXPORT jl_value_t *(jl_typeof)(jl_value_t *v) return jl_typeof(v); } -#ifndef __clang_analyzer__ JL_DLLEXPORT int8_t (jl_gc_unsafe_enter)(void) { jl_ptls_t ptls = jl_get_ptls_states(); @@ -410,7 +409,6 @@ JL_DLLEXPORT void (jl_gc_safe_leave)(int8_t state) jl_ptls_t ptls = jl_get_ptls_states(); jl_gc_safe_leave(ptls, state); } -#endif JL_DLLEXPORT void (jl_gc_safepoint)(void) { diff --git a/src/jltypes.c b/src/jltypes.c index 6258b3bfb3cdb..9a1f6a42b6449 100644 --- a/src/jltypes.c +++ b/src/jltypes.c @@ -314,7 +314,7 @@ int jl_count_union_components(jl_value_t *v) // Return the `*pi`th element of a nested type union, according to a // standard traversal order. Anything that is not itself a `Union` is // considered an "element". `*pi` is destroyed in the process. -static jl_value_t *nth_union_component(jl_value_t *v, int *pi) JL_NOTSAFEPOINT +static jl_value_t *nth_union_component(jl_value_t *v, int *pi) { if (!jl_is_uniontype(v)) { if (*pi == 0) @@ -328,13 +328,13 @@ static jl_value_t *nth_union_component(jl_value_t *v, int *pi) JL_NOTSAFEPOINT return nth_union_component(u->b, pi); } -jl_value_t *jl_nth_union_component(jl_value_t *v, int i) JL_NOTSAFEPOINT +jl_value_t *jl_nth_union_component(jl_value_t *v, int i) { return nth_union_component(v, &i); } // inverse of jl_nth_union_component -int jl_find_union_component(jl_value_t *haystack, jl_value_t *needle, unsigned *nth) JL_NOTSAFEPOINT +int jl_find_union_component(jl_value_t *haystack, jl_value_t *needle, unsigned *nth) { if (jl_is_uniontype(haystack)) { if (jl_find_union_component(((jl_uniontype_t*)haystack)->a, needle, nth)) @@ -349,7 +349,7 @@ int jl_find_union_component(jl_value_t *haystack, jl_value_t *needle, unsigned * return 0; } -static void flatten_type_union(jl_value_t **types, size_t n, jl_value_t **out, size_t *idx) JL_NOTSAFEPOINT +static void flatten_type_union(jl_value_t **types, size_t n, jl_value_t **out, size_t *idx) { size_t i; for(i=0; i < n; i++) { @@ -366,25 +366,25 @@ static void flatten_type_union(jl_value_t **types, size_t n, jl_value_t **out, s } } -STATIC_INLINE const char *datatype_module_name(jl_value_t *t) JL_NOTSAFEPOINT +STATIC_INLINE const char *datatype_module_name(jl_value_t *t) { if (((jl_datatype_t*)t)->name->module == NULL) return NULL; return jl_symbol_name(((jl_datatype_t*)t)->name->module->name); } -STATIC_INLINE const char *str_(const char *s) JL_NOTSAFEPOINT +STATIC_INLINE const char *str_(const char *s) { return s == NULL ? "" : s; } -STATIC_INLINE int cmp_(int a, int b) JL_NOTSAFEPOINT +STATIC_INLINE int cmp_(int a, int b) { return a < b ? -1 : a > b; } // a/b are jl_datatype_t* & not NULL -int datatype_name_cmp(jl_value_t *a, jl_value_t *b) JL_NOTSAFEPOINT +int datatype_name_cmp(jl_value_t *a, jl_value_t *b) { if (!jl_is_datatype(a)) return jl_is_datatype(b) ? 1 : 0; @@ -426,7 +426,7 @@ int datatype_name_cmp(jl_value_t *a, jl_value_t *b) JL_NOTSAFEPOINT // sort singletons first, then DataTypes, then UnionAlls, // ties broken alphabetically including module name & type parameters -int union_sort_cmp(const void *ap, const void *bp) JL_NOTSAFEPOINT +int union_sort_cmp(const void *ap, const void *bp) { jl_value_t *a = *(jl_value_t**)ap; jl_value_t *b = *(jl_value_t**)bp; @@ -558,7 +558,7 @@ static int contains_unions(jl_value_t *type) return 0; } -static intptr_t wrapper_id(jl_value_t *t) JL_NOTSAFEPOINT +static intptr_t wrapper_id(jl_value_t *t) { // DataType wrappers occur often, e.g. when called as constructors. // make sure any type equal to a wrapper gets a consistent, ordered ID. @@ -587,7 +587,7 @@ static int is_typekey_ordered(jl_value_t **key, size_t n) } // ordered comparison of types -static int typekey_compare(jl_datatype_t *tt, jl_value_t **key, size_t n) JL_NOTSAFEPOINT +static int typekey_compare(jl_datatype_t *tt, jl_value_t **key, size_t n) { size_t j; if (tt == NULL) return -1; // place NULLs at end to allow padding for fast growing @@ -634,7 +634,7 @@ static int typekey_compare(jl_datatype_t *tt, jl_value_t **key, size_t n) JL_NOT return 0; } -static int dt_compare(const void *ap, const void *bp) JL_NOTSAFEPOINT +static int dt_compare(const void *ap, const void *bp) { jl_datatype_t *a = *(jl_datatype_t**)ap; jl_datatype_t *b = *(jl_datatype_t**)bp; @@ -971,7 +971,6 @@ static jl_value_t *lookup_type_stack(jl_typestack_t *stack, jl_datatype_t *tt, s // stack, return it. this computes a fixed point for recursive types. jl_typename_t *tn = tt->name; while (stack != NULL) { - JL_GC_PROMISE_ROOTED(stack->tt); if (stack->tt->name == tn && ntp == jl_svec_len(stack->tt->parameters) && typekey_eq(stack->tt, iparams, ntp)) { @@ -1131,9 +1130,9 @@ static jl_value_t *inst_datatype_inner(jl_datatype_t *dt, jl_svec_t *p, jl_value } jl_datatype_t *ndt = NULL; - jl_value_t *last = iparams[ntp - 1]; - JL_GC_PUSH3(&p, &ndt, &last); + JL_GC_PUSH2(&p, &ndt); + jl_value_t *last = iparams[ntp - 1]; int isvatuple = 0; if (istuple && ntp > 0 && jl_is_vararg_type(last)) { isvatuple = 1; @@ -1149,13 +1148,17 @@ static jl_value_t *inst_datatype_inner(jl_datatype_t *dt, jl_svec_t *p, jl_value JL_GC_POP(); return (jl_value_t*)jl_anytuple_type; } - int did_normalize = 0; - jl_value_t *last2 = normalize_vararg(last); - if (last2 != last) { - last = last2; - did_normalize = 1; - va = jl_unwrap_unionall(last); - va0 = jl_tparam0(va); va1 = jl_tparam1(va); + { + JL_GC_PUSH1(&last); + jl_value_t *last2 = normalize_vararg(last); + if (last2 != last) { + last = last2; + p = jl_alloc_svec(ntp); + for (size_t i = 0; i < ntp-1; i++) + jl_svecset(p, i, iparams[i]); + jl_svecset(p, ntp-1, last); + } + JL_GC_POP(); } if (jl_is_long(va1)) { ssize_t nt = jl_unbox_long(va1); @@ -1179,12 +1182,6 @@ static jl_value_t *inst_datatype_inner(jl_datatype_t *dt, jl_svec_t *p, jl_value return ndt; } } - if (did_normalize) { - p = jl_alloc_svec(ntp); - for (size_t i = 0; i < ntp-1; i++) - jl_svecset(p, i, iparams[i]); - jl_svecset(p, ntp-1, last); - } } // move array of instantiated parameters to heap; we need to keep it @@ -1325,7 +1322,6 @@ static jl_tupletype_t *jl_apply_tuple_type_v_(jl_value_t **p, size_t np, jl_svec { int cacheable = 1; for (size_t i = 0; i < np; i++) { - assert(p[i]); if (!jl_is_concrete_type(p[i])) cacheable = 0; } @@ -1642,7 +1638,7 @@ static jl_tvar_t *tvar(const char *name) extern void jl_init_int32_int64_cache(void); -void jl_init_types(void) JL_GC_DISABLED +void jl_init_types(void) { jl_module_t *core = NULL; // will need to be assigned later diff --git a/src/julia-syntax.scm b/src/julia-syntax.scm index 4a3d43613cff1..abce5e47b6c20 100644 --- a/src/julia-syntax.scm +++ b/src/julia-syntax.scm @@ -200,17 +200,9 @@ (let ((bounds (map analyze-typevar params))) (values (map car bounds) bounds))) -(define (unmangled-name v) - (if (eq? v '||) - v - (let ((s (string v))) - (if (eqv? (string.char s 0) #\#) - (symbol (last (string-split s "#"))) - v)))) - ;; construct expression to allocate a TypeVar -(define (bounds-to-TypeVar v (unmangle #f)) - (let ((v ((if unmangle unmangled-name identity) (car v))) +(define (bounds-to-TypeVar v) + (let ((v (car v)) (lb (cadr v)) (ub (caddr v))) `(call (core TypeVar) ',v @@ -844,7 +836,7 @@ (block (global ,name) (const ,name) ,@(map (lambda (v) `(local ,v)) params) - ,@(map (lambda (n v) (make-assignment n (bounds-to-TypeVar v #t))) params bounds) + ,@(map (lambda (n v) (make-assignment n (bounds-to-TypeVar v))) params bounds) (struct_type ,name (call (core svec) ,@params) (call (core svec) ,@(map quotify field-names)) ,super (call (core svec) ,@field-types) ,mut ,min-initialized))) @@ -885,7 +877,7 @@ (scope-block (block ,@(map (lambda (v) `(local ,v)) params) - ,@(map (lambda (n v) (make-assignment n (bounds-to-TypeVar v #t))) params bounds) + ,@(map (lambda (n v) (make-assignment n (bounds-to-TypeVar v))) params bounds) (abstract_type ,name (call (core svec) ,@params) ,super)))))) (define (primitive-type-def-expr n name params super) @@ -896,7 +888,7 @@ (scope-block (block ,@(map (lambda (v) `(local ,v)) params) - ,@(map (lambda (n v) (make-assignment n (bounds-to-TypeVar v #t))) params bounds) + ,@(map (lambda (n v) (make-assignment n (bounds-to-TypeVar v))) params bounds) (primitive_type ,name (call (core svec) ,@params) ,n ,super)))))) ;; take apart a type signature, e.g. T{X} <: S{Y} diff --git a/src/julia.h b/src/julia.h index 97951e4ceba92..0c347c6ee68d0 100644 --- a/src/julia.h +++ b/src/julia.h @@ -99,12 +99,9 @@ JL_EXTENSION struct _jl_taggedvalue_t { }; #ifdef __clang_analyzer__ -JL_DLLEXPORT jl_taggedvalue_t *_jl_astaggedvalue(jl_value_t *v JL_PROPAGATES_ROOT) JL_NOTSAFEPOINT; -#define jl_astaggedvalue(v) _jl_astaggedvalue((jl_value_t*)v) -jl_value_t *_jl_valueof(jl_taggedvalue_t *tv JL_PROPAGATES_ROOT) JL_NOTSAFEPOINT; -#define jl_valueof(v) _jl_valueof((jl_taggedvalue_t*)v) -JL_DLLEXPORT jl_value_t *_jl_typeof(jl_value_t *v JL_PROPAGATES_ROOT) JL_NOTSAFEPOINT; -#define jl_typeof(v) _jl_typeof((jl_value_t*)v) +JL_DLLEXPORT jl_taggedvalue_t *jl_astaggedvalue(jl_value_t *v JL_PROPAGATES_ROOT) JL_NOTSAFEPOINT; +jl_value_t *jl_valueof(jl_taggedvalue_t *tv JL_PROPAGATES_ROOT) JL_NOTSAFEPOINT; +JL_DLLEXPORT jl_value_t *jl_typeof(jl_value_t *v JL_PROPAGATES_ROOT) JL_NOTSAFEPOINT; #else #define jl_astaggedvalue(v) \ ((jl_taggedvalue_t*)((char*)(v) - sizeof(jl_taggedvalue_t))) @@ -201,7 +198,11 @@ struct _jl_method_instance_t; // when key is a leaftype, (but only when the tree has enough entries for this to be // more efficient than storing them sorted linearly) // otherwise the leaf entries are stored sorted, linearly -typedef jl_value_t jl_typemap_t; +union jl_typemap_t { + struct _jl_typemap_level_t *node; + struct _jl_typemap_entry_t *leaf; + struct _jl_value_t *unknown; // nothing +}; typedef jl_value_t *(jl_call_t)(struct _jl_method_instance_t*, jl_value_t**, uint32_t); typedef jl_call_t *jl_callptr_t; @@ -271,7 +272,7 @@ typedef struct _jl_method_t { jl_value_t *ambig; // table of all argument types for which we've inferred or compiled this code - jl_typemap_t *specializations; + union jl_typemap_t specializations; jl_svec_t *sparam_syms; // symbols giving static parameter names jl_value_t *source; // original code template (jl_code_info_t, but may be compressed), null for builtins @@ -282,7 +283,7 @@ typedef struct _jl_method_t { // cache of specializations of this method for invoke(), i.e. // cases where this method was called even though it was not necessarily // the most specific for the argument types. - jl_typemap_t *invokes; + union jl_typemap_t invokes; int32_t nargs; int32_t called; // bit flags: whether each of the first 8 arguments is called @@ -480,14 +481,14 @@ typedef struct _jl_typemap_entry_t { // indexed by key if it is a sublevel in an array struct jl_ordereddict_t { jl_array_t *indices; // Array{Int{8,16,32}} - jl_array_t *values; // Array{jl_typemap_t*} + jl_array_t *values; // Array{union jl_typemap_t} }; typedef struct _jl_typemap_level_t { JL_DATA_TYPE struct jl_ordereddict_t arg1; struct jl_ordereddict_t targ; - jl_typemap_entry_t *linear; // jl_typemap_t * (but no more levels) - jl_typemap_t *any; // type at offs is Any + jl_typemap_entry_t *linear; // union jl_typemap_t (but no more levels) + union jl_typemap_t any; // type at offs is Any jl_value_t *key; // [nullable] } jl_typemap_level_t; @@ -495,8 +496,8 @@ typedef struct _jl_typemap_level_t { typedef struct _jl_methtable_t { JL_DATA_TYPE jl_sym_t *name; - jl_typemap_t *defs; - jl_typemap_t *cache; + union jl_typemap_t defs; + union jl_typemap_t cache; intptr_t max_args; // max # of non-vararg arguments in a signature jl_value_t *kwsorter; // keyword argument sorter function jl_module_t *module; // used for incremental serialization to locate original binding @@ -652,7 +653,6 @@ extern void JL_GC_PUSH2(void *, void *) JL_NOTSAFEPOINT; extern void JL_GC_PUSH3(void *, void *, void *) JL_NOTSAFEPOINT; extern void JL_GC_PUSH4(void *, void *, void *, void *) JL_NOTSAFEPOINT; extern void JL_GC_PUSH5(void *, void *, void *, void *, void *) JL_NOTSAFEPOINT; -extern void JL_GC_PUSH6(void *, void *, void *, void *, void *, void *) JL_NOTSAFEPOINT; extern void _JL_GC_PUSHARGS(jl_value_t **, size_t) JL_NOTSAFEPOINT; // This is necessary, because otherwise the analyzer considers this undefined // behavior and terminates the exploration @@ -749,12 +749,6 @@ JL_DLLEXPORT void *jl_gc_managed_realloc(void *d, size_t sz, size_t oldsz, #define jl_svec_set_len_unsafe(t,n) (((jl_svec_t*)(t))->length=(n)) #define jl_svec_data(t) ((jl_value_t**)((char*)(t) + sizeof(jl_svec_t))) -#ifdef __clang_analyzer__ -STATIC_INLINE jl_value_t *jl_svecref(void *t JL_PROPAGATES_ROOT, size_t i) JL_NOTSAFEPOINT; -STATIC_INLINE jl_value_t *jl_svecset( - void *t JL_ROOTING_ARGUMENT JL_PROPAGATES_ROOT, - size_t i, void *x JL_ROOTED_ARGUMENT) JL_NOTSAFEPOINT; -#else STATIC_INLINE jl_value_t *jl_svecref(void *t JL_PROPAGATES_ROOT, size_t i) JL_NOTSAFEPOINT { assert(jl_typeis(t,jl_simplevector_type)); @@ -771,7 +765,6 @@ STATIC_INLINE jl_value_t *jl_svecset( if (x) jl_gc_wb(t, x); return (jl_value_t*)x; } -#endif #ifdef STORE_ARRAY_LEN #define jl_array_len(a) (((jl_array_t*)(a))->length) @@ -789,15 +782,7 @@ JL_DLLEXPORT size_t jl_array_len_(jl_array_t *a); JL_DLLEXPORT char *jl_array_typetagdata(jl_array_t *a); -#ifdef __clang_analyzer__ -jl_value_t **jl_array_ptr_data(jl_array_t *a JL_PROPAGATES_ROOT) JL_NOTSAFEPOINT; -STATIC_INLINE jl_value_t *jl_array_ptr_ref(void *a JL_PROPAGATES_ROOT, size_t i) JL_NOTSAFEPOINT; -STATIC_INLINE jl_value_t *jl_array_ptr_set( - void *a JL_ROOTING_ARGUMENT, size_t i, - void *x JL_ROOTED_ARGUMENT) JL_NOTSAFEPOINT; -#else -#define jl_array_ptr_data(a) ((jl_value_t**)((jl_array_t*)(a))->data) -STATIC_INLINE jl_value_t *jl_array_ptr_ref(void *a JL_PROPAGATES_ROOT, size_t i) JL_NOTSAFEPOINT +STATIC_INLINE jl_value_t *jl_array_ptr_ref(void *a, size_t i) JL_NOTSAFEPOINT { assert(i < jl_array_len(a)); return ((jl_value_t**)(jl_array_data(a)))[i]; @@ -816,7 +801,6 @@ STATIC_INLINE jl_value_t *jl_array_ptr_set( } return (jl_value_t*)x; } -#endif STATIC_INLINE uint8_t jl_array_uint8_ref(void *a, size_t i) JL_NOTSAFEPOINT { @@ -831,7 +815,7 @@ STATIC_INLINE void jl_array_uint8_set(void *a, size_t i, uint8_t x) JL_NOTSAFEPO ((uint8_t*)(jl_array_data(a)))[i] = x; } -#define jl_exprarg(e,n) jl_array_ptr_ref(((jl_expr_t*)(e))->args, n) +#define jl_exprarg(e,n) (((jl_value_t**)jl_array_data(((jl_expr_t*)(e))->args))[n]) #define jl_exprargset(e, n, v) jl_array_ptr_set(((jl_expr_t*)(e))->args, n, v) #define jl_expr_nargs(e) jl_array_len(((jl_expr_t*)(e))->args) @@ -857,6 +841,7 @@ STATIC_INLINE void jl_array_uint8_set(void *a, size_t i, uint8_t x) JL_NOTSAFEPO // get a pointer to the data in a datatype #define jl_data_ptr(v) ((jl_value_t**)v) +#define jl_array_ptr_data(a) ((jl_value_t**)((jl_array_t*)a)->data) #define jl_string_data(s) ((char*)s + sizeof(void*)) #define jl_string_len(s) (*(size_t*)s) @@ -1082,7 +1067,7 @@ JL_DLLEXPORT uintptr_t jl_object_id(jl_value_t *v) JL_NOTSAFEPOINT; // type predicates and basic operations JL_DLLEXPORT int jl_has_free_typevars(jl_value_t *v) JL_NOTSAFEPOINT; -JL_DLLEXPORT int jl_has_typevar(jl_value_t *t, jl_tvar_t *v) JL_NOTSAFEPOINT; +JL_DLLEXPORT int jl_has_typevar(jl_value_t *t, jl_tvar_t *v); JL_DLLEXPORT int jl_has_typevar_from_unionall(jl_value_t *t, jl_unionall_t *ua); JL_DLLEXPORT int jl_subtype_env_size(jl_value_t *t); JL_DLLEXPORT int jl_subtype_env(jl_value_t *x, jl_value_t *y, jl_value_t **env, int envsz); @@ -1096,7 +1081,7 @@ JL_DLLEXPORT jl_value_t *jl_type_unionall(jl_tvar_t *v, jl_value_t *body); JL_DLLEXPORT const char *jl_typename_str(jl_value_t *v) JL_NOTSAFEPOINT; JL_DLLEXPORT const char *jl_typeof_str(jl_value_t *v) JL_NOTSAFEPOINT; JL_DLLEXPORT int jl_type_morespecific(jl_value_t *a, jl_value_t *b); -jl_value_t *jl_unwrap_unionall(jl_value_t *v JL_PROPAGATES_ROOT) JL_NOTSAFEPOINT; +jl_value_t *jl_unwrap_unionall(jl_value_t *v) JL_NOTSAFEPOINT; jl_value_t *jl_rewrap_unionall(jl_value_t *t, jl_value_t *u); STATIC_INLINE int jl_is_dispatch_tupletype(jl_value_t *v) JL_NOTSAFEPOINT @@ -1109,12 +1094,6 @@ STATIC_INLINE int jl_is_concrete_type(jl_value_t *v) JL_NOTSAFEPOINT return jl_is_datatype(v) && ((jl_datatype_t*)v)->isconcretetype; } -STATIC_INLINE jl_value_t *jl_typemap_entry_sig(jl_typemap_t *tmap JL_PROPAGATES_ROOT) JL_NOTSAFEPOINT -{ - assert(jl_typeof(tmap) == (jl_value_t*)jl_typemap_entry_type); - return (jl_value_t*)((jl_typemap_entry_t*)tmap)->sig; -} - // type constructors JL_DLLEXPORT jl_typename_t *jl_new_typename_in(jl_sym_t *name, jl_module_t *inmodule); JL_DLLEXPORT jl_tvar_t *jl_new_typevar(jl_sym_t *name, jl_value_t *lb, jl_value_t *ub); @@ -1260,7 +1239,7 @@ STATIC_INLINE jl_vararg_kind_t jl_vararg_kind(jl_value_t *v) JL_NOTSAFEPOINT return JL_VARARG_UNBOUND; } -STATIC_INLINE int jl_is_va_tuple(jl_datatype_t *t) JL_NOTSAFEPOINT +STATIC_INLINE int jl_is_va_tuple(jl_datatype_t *t) { assert(jl_is_tuple_type(t)); size_t l = jl_svec_len(t->parameters); @@ -1284,7 +1263,7 @@ JL_DLLEXPORT jl_value_t *jl_get_nth_field(jl_value_t *v, size_t i); JL_DLLEXPORT jl_value_t *jl_get_nth_field_noalloc(jl_value_t *v JL_PROPAGATES_ROOT, size_t i) JL_NOTSAFEPOINT; JL_DLLEXPORT jl_value_t *jl_get_nth_field_checked(jl_value_t *v, size_t i); JL_DLLEXPORT void jl_set_nth_field(jl_value_t *v, size_t i, - jl_value_t *rhs) JL_NOTSAFEPOINT; + jl_value_t *rhs); JL_DLLEXPORT int jl_field_isdefined(jl_value_t *v, size_t i); JL_DLLEXPORT jl_value_t *jl_get_field(jl_value_t *o, const char *fld); JL_DLLEXPORT jl_value_t *jl_value_ptr(jl_value_t *a); @@ -1312,7 +1291,7 @@ JL_DLLEXPORT jl_value_t *jl_array_to_string(jl_array_t *a); JL_DLLEXPORT jl_array_t *jl_alloc_vec_any(size_t n); JL_DLLEXPORT jl_value_t *jl_arrayref(jl_array_t *a, size_t i); // 0-indexed JL_DLLEXPORT jl_value_t *jl_ptrarrayref(jl_array_t *a JL_PROPAGATES_ROOT, size_t i) JL_NOTSAFEPOINT; // 0-indexed -JL_DLLEXPORT void jl_arrayset(jl_array_t *a JL_ROOTING_ARGUMENT, jl_value_t *v JL_ROOTED_ARGUMENT JL_MAYBE_UNROOTED, size_t i); // 0-indexed +JL_DLLEXPORT void jl_arrayset(jl_array_t *a, jl_value_t *v, size_t i); // 0-indexed JL_DLLEXPORT void jl_arrayunset(jl_array_t *a, size_t i); // 0-indexed JL_DLLEXPORT int jl_array_isassigned(jl_array_t *a, size_t i); // 0-indexed JL_DLLEXPORT void jl_array_grow_end(jl_array_t *a, size_t inc); @@ -1349,8 +1328,8 @@ JL_DLLEXPORT jl_binding_t *jl_get_binding_wr(jl_module_t *m JL_PROPAGATES_ROOT, JL_DLLEXPORT jl_binding_t *jl_get_binding_for_method_def(jl_module_t *m JL_PROPAGATES_ROOT, jl_sym_t *var); JL_DLLEXPORT int jl_boundp(jl_module_t *m, jl_sym_t *var); -JL_DLLEXPORT int jl_defines_or_exports_p(jl_module_t *m, jl_sym_t *var) JL_NOTSAFEPOINT; -JL_DLLEXPORT int jl_binding_resolved_p(jl_module_t *m, jl_sym_t *var) JL_NOTSAFEPOINT; +JL_DLLEXPORT int jl_defines_or_exports_p(jl_module_t *m, jl_sym_t *var); +JL_DLLEXPORT int jl_binding_resolved_p(jl_module_t *m, jl_sym_t *var); JL_DLLEXPORT int jl_is_const(jl_module_t *m, jl_sym_t *var); JL_DLLEXPORT jl_value_t *jl_get_global(jl_module_t *m JL_PROPAGATES_ROOT, jl_sym_t *var); JL_DLLEXPORT void jl_set_global(jl_module_t *m JL_ROOTING_ARGUMENT, @@ -1367,14 +1346,14 @@ JL_DLLEXPORT void jl_module_import(jl_module_t *to, jl_module_t *from, jl_sym_t *s); JL_DLLEXPORT void jl_module_export(jl_module_t *from, jl_sym_t *s); JL_DLLEXPORT int jl_is_imported(jl_module_t *m, jl_sym_t *s); -JL_DLLEXPORT int jl_module_exports_p(jl_module_t *m, jl_sym_t *var) JL_NOTSAFEPOINT; +JL_DLLEXPORT int jl_module_exports_p(jl_module_t *m, jl_sym_t *var); JL_DLLEXPORT jl_module_t *jl_new_main_module(void); JL_DLLEXPORT void jl_add_standard_imports(jl_module_t *m); STATIC_INLINE jl_function_t *jl_get_function(jl_module_t *m, const char *name) { return (jl_function_t*)jl_get_global(m, jl_symbol(name)); } -int jl_is_submodule(jl_module_t *child, jl_module_t *parent) JL_NOTSAFEPOINT; +int jl_is_submodule(jl_module_t *child, jl_module_t *parent); // eq hash tables JL_DLLEXPORT jl_array_t *jl_eqtable_put(jl_array_t *h, void *key, void *val, int *inserted); @@ -1783,11 +1762,11 @@ JL_DLLEXPORT JL_STREAM *jl_stdin_stream(void); JL_DLLEXPORT JL_STREAM *jl_stderr_stream(void); // showing and std streams -JL_DLLEXPORT void jl_flush_cstdio(void) JL_NOTSAFEPOINT; -JL_DLLEXPORT jl_value_t *jl_stdout_obj(void) JL_NOTSAFEPOINT; -JL_DLLEXPORT jl_value_t *jl_stderr_obj(void) JL_NOTSAFEPOINT; -JL_DLLEXPORT size_t jl_static_show(JL_STREAM *out, jl_value_t *v) JL_NOTSAFEPOINT; -JL_DLLEXPORT size_t jl_static_show_func_sig(JL_STREAM *s, jl_value_t *type) JL_NOTSAFEPOINT; +JL_DLLEXPORT void jl_flush_cstdio(void); +JL_DLLEXPORT jl_value_t *jl_stdout_obj(void); +JL_DLLEXPORT jl_value_t *jl_stderr_obj(void); +JL_DLLEXPORT size_t jl_static_show(JL_STREAM *out, jl_value_t *v); +JL_DLLEXPORT size_t jl_static_show_func_sig(JL_STREAM *s, jl_value_t *type); JL_DLLEXPORT void jlbacktrace(void); // Mainly for debugging, use `void*` so that no type cast is needed in C++. JL_DLLEXPORT void jl_(void *jl_value); @@ -1847,7 +1826,7 @@ JL_DLLEXPORT void jl_parse_opts(int *argcp, char ***argvp); // argc/argv JL_DLLEXPORT void jl_set_ARGS(int argc, char **argv); -JL_DLLEXPORT int jl_generating_output(void) JL_NOTSAFEPOINT; +JL_DLLEXPORT int jl_generating_output(void); // Settings for code_coverage and malloc_log // NOTE: if these numbers change, test/cmdlineargs.jl will have to be updated diff --git a/src/julia_internal.h b/src/julia_internal.h index f795442a8ee8e..186b5d7b2b985 100644 --- a/src/julia_internal.h +++ b/src/julia_internal.h @@ -137,7 +137,7 @@ STATIC_INLINE uint32_t jl_int32hash_fast(uint32_t a) #define GC_OLD_MARKED (GC_OLD | GC_MARKED) // reachable and old // useful constants -extern jl_methtable_t *jl_type_type_mt JL_GLOBALLY_ROOTED; +extern jl_methtable_t *jl_type_type_mt; JL_DLLEXPORT extern size_t jl_world_counter; typedef void (*tracer_cb)(jl_value_t *tracee); @@ -332,7 +332,7 @@ jl_llvm_functions_t jl_compile_linfo( jl_callptr_t jl_compile_method_internal(jl_method_instance_t **pmeth, size_t world); JL_DLLEXPORT int jl_compile_hint(jl_tupletype_t *types); jl_code_info_t *jl_code_for_interpreter(jl_method_instance_t *lam); -int jl_code_requires_compiler(jl_code_info_t *src) JL_NOTSAFEPOINT; +int jl_code_requires_compiler(jl_code_info_t *src); jl_code_info_t *jl_new_code_info_from_ast(jl_expr_t *ast); JL_DLLEXPORT jl_code_info_t *jl_new_code_info_uninit(void); @@ -397,10 +397,10 @@ jl_fptr_args_t jl_get_builtin_fptr(jl_value_t *b); extern uv_loop_t *jl_io_loop; void jl_uv_flush(uv_stream_t *stream); -typedef struct jl_typeenv_t { +typedef struct _typeenv { jl_tvar_t *var; jl_value_t *val; - struct jl_typeenv_t *prev; + struct _typeenv *prev; } jl_typeenv_t; int jl_tuple_isa(jl_value_t **child, size_t cl, jl_datatype_t *pdt); @@ -422,7 +422,7 @@ JL_DLLEXPORT jl_value_t *jl_instantiate_type_in_env(jl_value_t *ty, jl_unionall_ jl_value_t *jl_substitute_var(jl_value_t *t, jl_tvar_t *var, jl_value_t *val); jl_svec_t *jl_outer_unionall_vars(jl_value_t *u); int jl_count_union_components(jl_value_t *v); -jl_value_t *jl_nth_union_component(jl_value_t *v JL_PROPAGATES_ROOT, int i) JL_NOTSAFEPOINT; +jl_value_t *jl_nth_union_component(jl_value_t *v, int i) JL_NOTSAFEPOINT; int jl_find_union_component(jl_value_t *haystack, jl_value_t *needle, unsigned *nth) JL_NOTSAFEPOINT; jl_datatype_t *jl_new_uninitialized_datatype(void); void jl_precompute_memoized_dt(jl_datatype_t *dt); @@ -445,14 +445,14 @@ jl_value_t *jl_interpret_toplevel_thunk(jl_module_t *m, jl_code_info_t *src); jl_value_t *jl_interpret_toplevel_expr_in(jl_module_t *m, jl_value_t *e, jl_code_info_t *src, jl_svec_t *sparam_vals); -int jl_is_toplevel_only_expr(jl_value_t *e) JL_NOTSAFEPOINT; +int jl_is_toplevel_only_expr(jl_value_t *e); jl_value_t *jl_call_scm_on_ast(const char *funcname, jl_value_t *expr, jl_module_t *inmodule); void jl_linenumber_to_lineinfo(jl_code_info_t *ci, jl_module_t *mod, jl_sym_t *name); jl_method_instance_t *jl_method_lookup(jl_methtable_t *mt JL_PROPAGATES_ROOT, jl_value_t **args, size_t nargs, int cache, size_t world); jl_value_t *jl_gf_invoke(jl_value_t *types, jl_value_t **args, size_t nargs); -jl_method_instance_t *jl_lookup_generic(jl_value_t **args, uint32_t nargs, uint32_t callsite, size_t world) JL_ALWAYS_LEAFTYPE; +jl_method_instance_t *jl_lookup_generic(jl_value_t **args, uint32_t nargs, uint32_t callsite, size_t world); JL_DLLEXPORT jl_value_t *jl_matching_methods(jl_tupletype_t *types, int lim, int include_ambiguous, size_t world, size_t *min_valid, size_t *max_valid); @@ -465,7 +465,6 @@ void jl_compute_field_offsets(jl_datatype_t *st); jl_array_t *jl_new_array_for_deserialization(jl_value_t *atype, uint32_t ndims, size_t *dims, int isunboxed, int elsz); void jl_module_run_initializer(jl_module_t *m); -jl_binding_t *jl_get_module_binding(jl_module_t *m JL_PROPAGATES_ROOT, jl_sym_t *var) JL_NOTSAFEPOINT; extern jl_array_t *jl_module_init_order JL_GLOBALLY_ROOTED; extern jl_array_t *jl_cfunction_list JL_GLOBALLY_ROOTED; @@ -480,15 +479,15 @@ extern char jl_using_perf_jitevents; #endif extern size_t jl_arr_xtralloc_limit; -void jl_init_types(void) JL_GC_DISABLED; +void jl_init_types(void); void jl_init_box_caches(void); void jl_init_frontend(void); -void jl_init_primitives(void) JL_GC_DISABLED; +void jl_init_primitives(void); void *jl_init_llvm(void); void jl_init_codegen(void); void jl_init_intrinsic_functions(void); void jl_init_intrinsic_properties(void); -void jl_init_tasks(void) JL_GC_DISABLED; +void jl_init_tasks(void); void jl_init_stack_limits(int ismaster); void jl_init_root_task(void *stack, size_t ssize); void jl_init_serializer(void); @@ -568,7 +567,7 @@ static inline void jl_set_gc_and_wait(void) JL_DLLEXPORT jl_value_t *jl_dump_fptr_asm(uint64_t fptr, int raw_mc, const char* asm_variant); void jl_dump_native(const char *bc_fname, const char *unopt_bc_fname, const char *obj_fname, const char *sysimg_data, size_t sysimg_len); -int32_t jl_get_llvm_gv(jl_value_t *p) JL_NOTSAFEPOINT; +int32_t jl_get_llvm_gv(jl_value_t *p); int32_t jl_assign_functionID(const char *fname); // the first argument to jl_idtable_rehash is used to return a value // make sure it is rooted if it is used after the function returns @@ -635,8 +634,8 @@ typedef unw_cursor_t bt_cursor_t; typedef int bt_context_t; typedef int bt_cursor_t; #endif -size_t rec_backtrace(uintptr_t *data, size_t maxsize) JL_NOTSAFEPOINT; -size_t rec_backtrace_ctx(uintptr_t *data, size_t maxsize, bt_context_t *ctx) JL_NOTSAFEPOINT; +size_t rec_backtrace(uintptr_t *data, size_t maxsize); +size_t rec_backtrace_ctx(uintptr_t *data, size_t maxsize, bt_context_t *ctx); #ifdef LIBOSXUNWIND size_t rec_backtrace_ctx_dwarf(uintptr_t *data, size_t maxsize, bt_context_t *ctx); #endif @@ -700,8 +699,8 @@ extern JL_DLLEXPORT jl_value_t *jl_segv_exception; #endif // -- Runtime intrinsics -- // -JL_DLLEXPORT const char *jl_intrinsic_name(int f) JL_NOTSAFEPOINT; -unsigned jl_intrinsic_nargs(int f) JL_NOTSAFEPOINT; +JL_DLLEXPORT const char *jl_intrinsic_name(int f); +unsigned jl_intrinsic_nargs(int f); JL_DLLEXPORT jl_value_t *jl_bitcast(jl_value_t *ty, jl_value_t *v); JL_DLLEXPORT jl_value_t *jl_pointerref(jl_value_t *p, jl_value_t *i, jl_value_t *align); @@ -860,7 +859,7 @@ struct jl_typemap_info { jl_datatype_t **jl_contains; // the type that is being put in this }; -jl_typemap_entry_t *jl_typemap_insert(jl_typemap_t **cache, +jl_typemap_entry_t *jl_typemap_insert(union jl_typemap_t *cache, jl_value_t *parent JL_PROPAGATES_ROOT, jl_tupletype_t *type, jl_tupletype_t *simpletype, jl_svec_t *guardsigs, @@ -870,29 +869,27 @@ jl_typemap_entry_t *jl_typemap_insert(jl_typemap_t **cache, jl_value_t **overwritten); jl_typemap_entry_t *jl_typemap_assoc_by_type( - jl_typemap_t *ml_or_cache JL_PROPAGATES_ROOT, + union jl_typemap_t ml_or_cache JL_PROPAGATES_ROOT, jl_value_t *types, jl_svec_t **penv, int8_t subtype, int8_t offs, size_t world, size_t max_world_mask); jl_typemap_entry_t *jl_typemap_level_assoc_exact(jl_typemap_level_t *cache, jl_value_t **args, size_t n, int8_t offs, size_t world); jl_typemap_entry_t *jl_typemap_entry_assoc_exact(jl_typemap_entry_t *mn, jl_value_t **args, size_t n, size_t world); STATIC_INLINE jl_typemap_entry_t *jl_typemap_assoc_exact( - jl_typemap_t *ml_or_cache JL_PROPAGATES_ROOT, + union jl_typemap_t ml_or_cache JL_PROPAGATES_ROOT, jl_value_t **args, size_t n, int8_t offs, size_t world) { // NOTE: This function is a huge performance hot spot!! - if (jl_typeof(ml_or_cache) == (jl_value_t *)jl_typemap_entry_type) { - return jl_typemap_entry_assoc_exact( - (jl_typemap_entry_t *)ml_or_cache, args, n, world); + if (jl_typeof(ml_or_cache.unknown) == (jl_value_t*)jl_typemap_entry_type) { + return jl_typemap_entry_assoc_exact(ml_or_cache.leaf, args, n, world); } - else if (jl_typeof(ml_or_cache) == (jl_value_t*)jl_typemap_level_type) { - return jl_typemap_level_assoc_exact( - (jl_typemap_level_t *)ml_or_cache, args, n, offs, world); + else if (jl_typeof(ml_or_cache.unknown) == (jl_value_t*)jl_typemap_level_type) { + return jl_typemap_level_assoc_exact(ml_or_cache.node, args, n, offs, world); } return NULL; } typedef int (*jl_typemap_visitor_fptr)(jl_typemap_entry_t *l, void *closure); -int jl_typemap_visitor(jl_typemap_t *a, jl_typemap_visitor_fptr fptr, void *closure); +int jl_typemap_visitor(union jl_typemap_t a, jl_typemap_visitor_fptr fptr, void *closure); struct typemap_intersection_env; typedef int (*jl_typemap_intersection_visitor_fptr)(jl_typemap_entry_t *l, struct typemap_intersection_env *closure); @@ -906,7 +903,7 @@ struct typemap_intersection_env { jl_svec_t *env; // intersection env (initialize to null to perform intersection without an environment) int issubty; // if `a <: b` is true in `intersect(a,b)` }; -int jl_typemap_intersection_visitor(jl_typemap_t *a, int offs, struct typemap_intersection_env *closure); +int jl_typemap_intersection_visitor(union jl_typemap_t a, int offs, struct typemap_intersection_env *closure); unsigned jl_special_vector_alignment(size_t nfields, jl_value_t *field_type); diff --git a/src/julia_threads.h b/src/julia_threads.h index 204e358a39763..01d64d86877ed 100644 --- a/src/julia_threads.h +++ b/src/julia_threads.h @@ -169,18 +169,12 @@ JL_DLLEXPORT void (jl_cpu_wake)(void); jl_signal_fence(); \ (void)safepoint_load; \ } while (0) -#ifdef __clang_analyzer__ -// This is a sigint safepoint, not a GC safepoint (which -// JL_NOTSAFEPOINT refers to) -void jl_sigint_safepoint(jl_ptls_t tls) JL_NOTSAFEPOINT; -#else #define jl_sigint_safepoint(ptls) do { \ jl_signal_fence(); \ size_t safepoint_load = ptls->safepoint[-1]; \ jl_signal_fence(); \ (void)safepoint_load; \ } while (0) -#endif #ifndef JULIA_ENABLE_THREADING #define jl_gc_state(ptls) ((int8_t)0) STATIC_INLINE int8_t jl_gc_state_set(jl_ptls_t ptls, int8_t state, @@ -209,17 +203,10 @@ STATIC_INLINE int8_t jl_gc_state_save_and_set(jl_ptls_t ptls, { return jl_gc_state_set(ptls, state, jl_gc_state(ptls)); } -#ifdef __clang_analyzer__ -int8_t jl_gc_unsafe_enter(jl_ptls_t ptls); // Can be a safepoint -int8_t jl_gc_unsafe_leave(jl_ptls_t ptls, int8_t state) JL_NOTSAFEPOINT; -int8_t jl_gc_safe_enter(jl_ptls_t ptls) JL_NOTSAFEPOINT; -int8_t jl_gc_safe_leave(jl_ptls_t ptls, int8_t state); // Can be a safepoint -#else #define jl_gc_unsafe_enter(ptls) jl_gc_state_save_and_set(ptls, 0) #define jl_gc_unsafe_leave(ptls, state) ((void)jl_gc_state_set(ptls, (state), 0)) #define jl_gc_safe_enter(ptls) jl_gc_state_save_and_set(ptls, JL_GC_STATE_SAFE) #define jl_gc_safe_leave(ptls, state) ((void)jl_gc_state_set(ptls, (state), JL_GC_STATE_SAFE)) -#endif JL_DLLEXPORT void (jl_gc_safepoint)(void); JL_DLLEXPORT void jl_gc_enable_finalizers(jl_ptls_t ptls, int on); diff --git a/src/llvm-alloc-opt.cpp b/src/llvm-alloc-opt.cpp index 0b620092e94fb..f1f682afd1244 100644 --- a/src/llvm-alloc-opt.cpp +++ b/src/llvm-alloc-opt.cpp @@ -37,12 +37,27 @@ namespace { static void copyMetadata(Instruction *dest, const Instruction *src) { +#if JL_LLVM_VERSION < 40000 + if (!src->hasMetadata()) + return; + SmallVector,4> TheMDs; + src->getAllMetadataOtherThanDebugLoc(TheMDs); + for (const auto &MD : TheMDs) + dest->setMetadata(MD.first, MD.second); + dest->setDebugLoc(src->getDebugLoc()); +#else dest->copyMetadata(*src); +#endif } static bool isBundleOperand(CallInst *call, unsigned idx) { +#if JL_LLVM_VERSION < 40000 + return call->hasOperandBundles() && idx >= call->getBundleOperandsStartIndex() && + idx < call->getBundleOperandsEndIndex(); +#else return call->isBundleOperand(idx); +#endif } static void removeGCPreserve(CallInst *call, Instruction *val) @@ -893,8 +908,15 @@ void Optimizer::replaceIntrinsicUseWith(IntrinsicInst *call, Intrinsic::ID ID, auto newCall = CallInst::Create(newF, args, "", call); newCall->setTailCallKind(call->getTailCallKind()); auto old_attrs = call->getAttributes(); +#if JL_LLVM_VERSION >= 50000 newCall->setAttributes(AttributeList::get(*pass.ctx, old_attrs.getFnAttributes(), old_attrs.getRetAttributes(), {})); +#else + AttributeSet attr; + attr = attr.addAttributes(*pass.ctx, AttributeSet::ReturnIndex, old_attrs.getRetAttributes()) + .addAttributes(*pass.ctx, AttributeSet::FunctionIndex, old_attrs.getFnAttributes()); + newCall->setAttributes(attr); +#endif newCall->setDebugLoc(call->getDebugLoc()); call->replaceAllUsesWith(newCall); call->eraseFromParent(); @@ -1455,8 +1477,13 @@ bool AllocOpt::doInitialization(Module &M) T_size = sizeof(void*) == 8 ? T_int64 : T_int32; T_pint8 = PointerType::get(T_int8, 0); +#if JL_LLVM_VERSION >= 50000 lifetime_start = Intrinsic::getDeclaration(&M, Intrinsic::lifetime_start, { T_pint8 }); lifetime_end = Intrinsic::getDeclaration(&M, Intrinsic::lifetime_end, { T_pint8 }); +#else + lifetime_start = Intrinsic::getDeclaration(&M, Intrinsic::lifetime_start); + lifetime_end = Intrinsic::getDeclaration(&M, Intrinsic::lifetime_end); +#endif MDNode *tbaa_data; MDNode *tbaa_data_scalar; diff --git a/src/llvm-lower-handlers.cpp b/src/llvm-lower-handlers.cpp index b4beddb480fc1..5caee2b1998bb 100644 --- a/src/llvm-lower-handlers.cpp +++ b/src/llvm-lower-handlers.cpp @@ -115,9 +115,14 @@ bool LowerExcHandlers::doInitialization(Module &M) { jlenter_func = M.getFunction("jl_enter_handler"); setjmp_func = M.getFunction(jl_setjmp_name); +#if JL_LLVM_VERSION >= 50000 auto T_pint8 = Type::getInt8PtrTy(M.getContext(), 0); lifetime_start = Intrinsic::getDeclaration(&M, Intrinsic::lifetime_start, { T_pint8 }); lifetime_end = Intrinsic::getDeclaration(&M, Intrinsic::lifetime_end, { T_pint8 }); +#else + lifetime_start = Intrinsic::getDeclaration(&M, Intrinsic::lifetime_start); + lifetime_end = Intrinsic::getDeclaration(&M, Intrinsic::lifetime_end); +#endif return true; } @@ -179,7 +184,9 @@ bool LowerExcHandlers::runOnFunction(Function &F) { std::vector buffs; for (int i = 0; i < MaxDepth; ++i) { auto *buff = new AllocaInst(Type::getInt8Ty(F.getContext()), +#if JL_LLVM_VERSION >= 50000 0, +#endif handler_sz, "", firstInst); buff->setAlignment(16); buffs.push_back(buff); diff --git a/src/llvm-muladd.cpp b/src/llvm-muladd.cpp index b054d2ab58e03..b426035ce99ca 100644 --- a/src/llvm-muladd.cpp +++ b/src/llvm-muladd.cpp @@ -49,11 +49,37 @@ static bool checkCombine(Module *m, Instruction *addOp, Value *maybeMul, Value * return false; if (!mulOp->hasOneUse()) return false; +#if JL_LLVM_VERSION >= 50000 // On 5.0+ we only need to mark the mulOp as contract and the backend will do the work for us. auto fmf = mulOp->getFastMathFlags(); fmf.setAllowContract(true); mulOp->copyFastMathFlags(fmf); return false; +#else + IRBuilder<> builder(m->getContext()); + builder.SetInsertPoint(addOp); + auto mul1 = mulOp->getOperand(0); + auto mul2 = mulOp->getOperand(1); + Value *muladdf = Intrinsic::getDeclaration(m, Intrinsic::fmuladd, addOp->getType()); + if (negadd) { + auto newaddend = builder.CreateFNeg(addend); + // Might be a const + if (auto neginst = dyn_cast(newaddend)) + neginst->setHasUnsafeAlgebra(true); + addend = newaddend; + } + Instruction *newv = builder.CreateCall(muladdf, {mul1, mul2, addend}); + newv->setHasUnsafeAlgebra(true); + if (negres) { + // Shouldn't be a constant + newv = cast(builder.CreateFNeg(newv)); + newv->setHasUnsafeAlgebra(true); + } + addOp->replaceAllUsesWith(newv); + addOp->eraseFromParent(); + mulOp->eraseFromParent(); + return true; +#endif } bool CombineMulAdd::runOnFunction(Function &F) @@ -65,14 +91,22 @@ bool CombineMulAdd::runOnFunction(Function &F) it++; switch (I.getOpcode()) { case Instruction::FAdd: { +#if JL_LLVM_VERSION >= 60000 if (!I.isFast()) +#else + if (!I.hasUnsafeAlgebra()) +#endif continue; checkCombine(m, &I, I.getOperand(0), I.getOperand(1), false, false) || checkCombine(m, &I, I.getOperand(1), I.getOperand(0), false, false); break; } case Instruction::FSub: { +#if JL_LLVM_VERSION >= 60000 if (!I.isFast()) +#else + if (!I.hasUnsafeAlgebra()) +#endif continue; checkCombine(m, &I, I.getOperand(0), I.getOperand(1), true, false) || checkCombine(m, &I, I.getOperand(1), I.getOperand(0), true, true); diff --git a/src/llvm-ptls.cpp b/src/llvm-ptls.cpp index f09df11cd13c7..455a251d98ba6 100644 --- a/src/llvm-ptls.cpp +++ b/src/llvm-ptls.cpp @@ -70,8 +70,13 @@ struct LowerPTLS: public ModulePass { #ifdef JULIA_ENABLE_THREADING void LowerPTLS::set_ptls_attrs(CallInst *ptlsStates) const { +#if JL_LLVM_VERSION >= 50000 ptlsStates->addAttribute(AttributeList::FunctionIndex, Attribute::ReadNone); ptlsStates->addAttribute(AttributeList::FunctionIndex, Attribute::NoUnwind); +#else + ptlsStates->addAttribute(AttributeSet::FunctionIndex, Attribute::ReadNone); + ptlsStates->addAttribute(AttributeSet::FunctionIndex, Attribute::NoUnwind); +#endif } Instruction *LowerPTLS::emit_ptls_tp(Value *offset, Instruction *insertBefore) const diff --git a/src/llvm-simdloop.cpp b/src/llvm-simdloop.cpp index dbafcf265d03d..683d41d57cc68 100644 --- a/src/llvm-simdloop.cpp +++ b/src/llvm-simdloop.cpp @@ -164,7 +164,11 @@ void LowerSIMDLoop::enableUnsafeAlgebraIfReduction(PHINode *Phi, Loop *L) const } for (chainVector::const_iterator K=chain.begin(); K!=chain.end(); ++K) { DEBUG(dbgs() << "LSL: marking " << **K << "\n"); +#if JL_LLVM_VERSION >= 60000 (*K)->setFast(true); +#else + (*K)->setHasUnsafeAlgebra(true); +#endif } } diff --git a/src/llvm-version.h b/src/llvm-version.h index 1572484c09b50..fa1dbcf433e21 100644 --- a/src/llvm-version.h +++ b/src/llvm-version.h @@ -9,6 +9,6 @@ #define JL_LLVM_VERSION (LLVM_VERSION_MAJOR * 10000 + LLVM_VERSION_MINOR * 100 \ + LLVM_VERSION_PATCH) -#if JL_LLVM_VERSION < 60000 - #error Only LLVM versions >= 6.0.0 are supported by Julia +#if JL_LLVM_VERSION < 30901 + #error Only LLVM versions >= 3.9.1 are supported by Julia #endif diff --git a/src/macroexpand.scm b/src/macroexpand.scm index abad3407656fd..2c7a040e39f53 100644 --- a/src/macroexpand.scm +++ b/src/macroexpand.scm @@ -135,21 +135,16 @@ (if var (list 'varlist var) '())) ;; type definition - (pattern-lambda (struct mut spec body) - (let ((tn (typedef-expr-name spec)) - (tv (typedef-expr-tvars spec))) - (list* 'varlist (cons (unescape tn) (unescape tn)) '(new . new) - (typevar-names tv)))) - (pattern-lambda (abstract spec) - (let ((tn (typedef-expr-name spec)) - (tv (typedef-expr-tvars spec))) - (list* 'varlist (cons (unescape tn) (unescape tn)) - (typevar-names tv)))) - (pattern-lambda (primitive spec nb) - (let ((tn (typedef-expr-name spec)) - (tv (typedef-expr-tvars spec))) - (list* 'varlist (cons (unescape tn) (unescape tn)) - (typevar-names tv)))) + (pattern-lambda (struct mut (<: (curly tn . tvars) super) body) + (list* 'varlist (cons (unescape tn) (unescape tn)) '(new . new) + (typevar-names tvars))) + (pattern-lambda (struct mut (curly tn . tvars) body) + (list* 'varlist (cons (unescape tn) (unescape tn)) '(new . new) + (typevar-names tvars))) + (pattern-lambda (struct mut (<: tn super) body) + (list 'varlist (cons (unescape tn) (unescape tn)) '(new . new))) + (pattern-lambda (struct mut tn body) + (list 'varlist (cons (unescape tn) (unescape tn)) '(new . new))) )) ; vars-introduced-by-patterns @@ -183,17 +178,6 @@ (cadr e) e)) -(define (typedef-expr-name e) - (cond ((atom? e) e) - ((or (eq? (car e) 'curly) (eq? (car e) '<:)) (typedef-expr-name (cadr e))) - (else e))) - -(define (typedef-expr-tvars e) - (cond ((atom? e) '()) - ((eq? (car e) '<:) (typedef-expr-tvars (cadr e))) - ((eq? (car e) 'curly) (cddr e)) - (else '()))) - (define (typevar-expr-name e) (car (analyze-typevar e))) ;; get the list of names from a list of `where` variable expressions diff --git a/src/method.c b/src/method.c index 4365def7f3d11..981f917831fa3 100644 --- a/src/method.c +++ b/src/method.c @@ -220,7 +220,7 @@ static void jl_code_info_set_ast(jl_code_info_t *li, jl_expr_t *ast) li->code = body; jl_gc_wb(li, li->code); size_t n = jl_array_len(body); - jl_value_t **bd = (jl_value_t**)jl_array_ptr_data((jl_array_t*)li->code); + jl_value_t **bd = (jl_value_t**)jl_array_data((jl_array_t*)li->code); for (j = 0; j < n; j++) { jl_value_t *st = bd[j]; if (jl_is_expr(st) && ((jl_expr_t*)st)->head == meta_sym) { @@ -576,7 +576,7 @@ JL_DLLEXPORT jl_method_t *jl_new_method_uninit(jl_module_t *module) jl_ptls_t ptls = jl_get_ptls_states(); jl_method_t *m = (jl_method_t*)jl_gc_alloc(ptls, sizeof(jl_method_t), jl_method_type); - m->specializations = jl_nothing; + m->specializations.unknown = jl_nothing; m->sig = NULL; m->sparam_syms = NULL; m->ambig = jl_nothing; @@ -590,7 +590,7 @@ JL_DLLEXPORT jl_method_t *jl_new_method_uninit(jl_module_t *module) m->line = 0; m->called = 0xff; m->nospecialize = module->nospecialize; - m->invokes = NULL; + m->invokes.unknown = NULL; m->isva = 0; m->nargs = 0; m->traced = 0; @@ -599,7 +599,7 @@ JL_DLLEXPORT jl_method_t *jl_new_method_uninit(jl_module_t *module) return m; } -jl_array_t *jl_all_methods JL_GLOBALLY_ROOTED; +jl_array_t *jl_all_methods; static jl_method_t *jl_new_method( jl_code_info_t *definition, jl_sym_t *name, @@ -695,7 +695,7 @@ JL_DLLEXPORT jl_value_t *jl_generic_function_def(jl_sym_t *name, return gf; } -static jl_datatype_t *first_arg_datatype(jl_value_t *a JL_PROPAGATES_ROOT, int got_tuple1) JL_NOTSAFEPOINT +static jl_datatype_t *first_arg_datatype(jl_value_t *a, int got_tuple1) { if (jl_is_datatype(a)) { if (got_tuple1) @@ -726,13 +726,13 @@ static jl_datatype_t *first_arg_datatype(jl_value_t *a JL_PROPAGATES_ROOT, int g } // get DataType of first tuple element, or NULL if cannot be determined -JL_DLLEXPORT jl_datatype_t *jl_first_argument_datatype(jl_value_t *argtypes JL_PROPAGATES_ROOT) JL_NOTSAFEPOINT +JL_DLLEXPORT jl_datatype_t *jl_first_argument_datatype(jl_value_t *argtypes) { return first_arg_datatype(argtypes, 0); } // get DataType implied by a single given type, or `nothing` -JL_DLLEXPORT jl_value_t *jl_argument_datatype(jl_value_t *argt JL_PROPAGATES_ROOT) JL_NOTSAFEPOINT +JL_DLLEXPORT jl_value_t *jl_argument_datatype(jl_value_t *argt) { jl_datatype_t *dt = first_arg_datatype(argt, 1); if (dt == NULL) diff --git a/src/module.c b/src/module.c index b393543668cf3..b037b19c7a6cc 100644 --- a/src/module.c +++ b/src/module.c @@ -125,23 +125,6 @@ JL_DLLEXPORT jl_binding_t *jl_get_binding_wr(jl_module_t *m, jl_sym_t *var, int return *bp; } -// Hash tables don't generically root their contents, but they do for bindings. -// Express this to the analyzer. -#ifdef __clang_analyzer__ -jl_binding_t *_jl_get_module_binding(jl_module_t *m JL_PROPAGATES_ROOT, jl_sym_t *var) JL_NOTSAFEPOINT; -jl_binding_t **_jl_get_module_binding_bp(jl_module_t *m JL_PROPAGATES_ROOT, jl_sym_t *var) JL_NOTSAFEPOINT; -#else -static inline jl_binding_t *_jl_get_module_binding(jl_module_t *m JL_PROPAGATES_ROOT, jl_sym_t *var) JL_NOTSAFEPOINT -{ - return (jl_binding_t*)ptrhash_get(&m->bindings, var); -} -static inline jl_binding_t **_jl_get_module_binding_bp(jl_module_t *m JL_PROPAGATES_ROOT, jl_sym_t *var) JL_NOTSAFEPOINT -{ - return (jl_binding_t**)ptrhash_bp(&m->bindings, var); -} -#endif - - // return module of binding JL_DLLEXPORT jl_module_t *jl_get_module_of_binding(jl_module_t *m, jl_sym_t *var) { @@ -155,7 +138,7 @@ JL_DLLEXPORT jl_module_t *jl_get_module_of_binding(jl_module_t *m, jl_sym_t *var // like jl_get_binding_wr, but has different error paths JL_DLLEXPORT jl_binding_t *jl_get_binding_for_method_def(jl_module_t *m, jl_sym_t *var) { - jl_binding_t **bp = _jl_get_module_binding_bp(m, var); + jl_binding_t **bp = (jl_binding_t**)ptrhash_bp(&m->bindings, var); jl_binding_t *b = *bp; if (b != HT_NOTFOUND) { @@ -194,16 +177,16 @@ typedef struct _modstack_t { struct _modstack_t *prev; } modstack_t; -static jl_binding_t *jl_get_binding_(jl_module_t *m JL_PROPAGATES_ROOT, jl_sym_t *var, modstack_t *st); +static jl_binding_t *jl_get_binding_(jl_module_t *m, jl_sym_t *var, modstack_t *st); // find a binding from a module's `usings` list -static jl_binding_t *using_resolve_binding(jl_module_t *m JL_PROPAGATES_ROOT, jl_sym_t *var, modstack_t *st, int warn) +static jl_binding_t *using_resolve_binding(jl_module_t *m, jl_sym_t *var, modstack_t *st, int warn) { jl_binding_t *b = NULL; jl_module_t *owner = NULL; for(int i=(int)m->usings.len-1; i >= 0; --i) { jl_module_t *imp = (jl_module_t*)m->usings.items[i]; - jl_binding_t *tempb = _jl_get_module_binding(imp, var); + jl_binding_t *tempb = (jl_binding_t*)ptrhash_get(&imp->bindings, var); if (tempb != HT_NOTFOUND && tempb->exportp) { tempb = jl_get_binding_(imp, var, st); if (tempb == NULL || tempb->owner == NULL) @@ -244,7 +227,7 @@ static jl_binding_t *jl_get_binding_(jl_module_t *m, jl_sym_t *var, modstack_t * } tmp = tmp->prev; } - jl_binding_t *b = _jl_get_module_binding(m, var); + jl_binding_t *b = (jl_binding_t*)ptrhash_get(&m->bindings, var); if (b == HT_NOTFOUND || b->owner == NULL) { b = using_resolve_binding(m, var, &top, 1); if (b != NULL) { @@ -470,24 +453,18 @@ JL_DLLEXPORT int jl_defines_or_exports_p(jl_module_t *m, jl_sym_t *var) return b != HT_NOTFOUND && (b->exportp || b->owner==m); } -JL_DLLEXPORT int jl_module_exports_p(jl_module_t *m, jl_sym_t *var) JL_NOTSAFEPOINT +JL_DLLEXPORT int jl_module_exports_p(jl_module_t *m, jl_sym_t *var) { - jl_binding_t *b = _jl_get_module_binding(m, var); + jl_binding_t *b = (jl_binding_t*)ptrhash_get(&m->bindings, var); return b != HT_NOTFOUND && b->exportp; } -JL_DLLEXPORT int jl_binding_resolved_p(jl_module_t *m, jl_sym_t *var) JL_NOTSAFEPOINT +JL_DLLEXPORT int jl_binding_resolved_p(jl_module_t *m, jl_sym_t *var) { - jl_binding_t *b = _jl_get_module_binding(m, var); + jl_binding_t *b = (jl_binding_t*)ptrhash_get(&m->bindings, var); return b != HT_NOTFOUND && b->owner != NULL; } -JL_DLLEXPORT jl_binding_t *jl_get_module_binding(jl_module_t *m JL_PROPAGATES_ROOT, jl_sym_t *var) JL_NOTSAFEPOINT -{ - jl_binding_t *b = _jl_get_module_binding(m, var); - return b == HT_NOTFOUND ? NULL : b; -} - JL_DLLEXPORT jl_value_t *jl_get_global(jl_module_t *m, jl_sym_t *var) { jl_binding_t *b = jl_get_binding(m, var); @@ -496,7 +473,7 @@ JL_DLLEXPORT jl_value_t *jl_get_global(jl_module_t *m, jl_sym_t *var) return b->value; } -JL_DLLEXPORT void jl_set_global(jl_module_t *m JL_ROOTING_ARGUMENT, jl_sym_t *var, jl_value_t *val JL_ROOTED_ARGUMENT) +JL_DLLEXPORT void jl_set_global(jl_module_t *m, jl_sym_t *var, jl_value_t *val) { jl_binding_t *bp = jl_get_binding_wr(m, var, 1); if (!bp->constp) { @@ -505,7 +482,7 @@ JL_DLLEXPORT void jl_set_global(jl_module_t *m JL_ROOTING_ARGUMENT, jl_sym_t *va } } -JL_DLLEXPORT void jl_set_const(jl_module_t *m JL_ROOTING_ARGUMENT, jl_sym_t *var, jl_value_t *val JL_ROOTED_ARGUMENT) +JL_DLLEXPORT void jl_set_const(jl_module_t *m, jl_sym_t *var, jl_value_t *val) { jl_binding_t *bp = jl_get_binding_wr(m, var, 1); if (!bp->constp) { @@ -588,7 +565,7 @@ void jl_binding_deprecation_warning(jl_module_t *m, jl_binding_t *b) } else { jl_methtable_t *mt = jl_gf_mtable(v); - if (mt != NULL && (mt->defs != jl_nothing || + if (mt != NULL && (mt->defs.unknown != jl_nothing || jl_isa(v, (jl_value_t*)jl_builtin_type))) { jl_printf(JL_STDERR, ", use "); if (mt->module != jl_core_module) { @@ -694,7 +671,7 @@ JL_DLLEXPORT jl_uuid_t jl_module_uuid(jl_module_t* m) { return m->uuid; } // TODO: make this part of the module constructor and read-only? JL_DLLEXPORT void jl_set_module_uuid(jl_module_t *m, jl_uuid_t uuid) { m->uuid = uuid; } -int jl_is_submodule(jl_module_t *child, jl_module_t *parent) JL_NOTSAFEPOINT +int jl_is_submodule(jl_module_t *child, jl_module_t *parent) { while (1) { if (parent == child) diff --git a/src/precompile.c b/src/precompile.c index 188f58c1b2e2a..c5392af41c649 100644 --- a/src/precompile.c +++ b/src/precompile.c @@ -80,13 +80,11 @@ void jl_write_compiler_output(void) } } - if (jl_options.outputo || jl_options.outputbc || jl_options.outputunoptbc) { - assert(s); + if (jl_options.outputo || jl_options.outputbc || jl_options.outputunoptbc) jl_dump_native(jl_options.outputbc, jl_options.outputunoptbc, jl_options.outputo, (const char*)s->buf, (size_t)s->size); - } } JL_GC_POP(); } @@ -129,7 +127,6 @@ static void _compile_all_tvar_union(jl_value_t *methsig) if (!jl_has_concrete_subtype(sig)) goto getnext; // signature wouldn't be callable / is invalid -- skip it if (jl_is_concrete_type(sig)) { - JL_GC_PROMISE_ROOTED(sig); // `sig` is rooted because it's a leaftype (JL_ALWAYS_LEAFTYPE) if (jl_compile_hint((jl_tupletype_t*)sig)) goto getnext; // success } @@ -200,7 +197,6 @@ static void _compile_all_union(jl_value_t *sig) for (i = 0, idx_ctr = 0, incr = 1; i < l; i++) { jl_value_t *ty = jl_svecref(sigbody->parameters, i); if (jl_is_uniontype(ty)) { - assert(idx_ctr < count_unions); size_t l = jl_count_union_components(ty); size_t j = idx[idx_ctr]; jl_svecset(p, i, jl_nth_union_component(ty, j)); diff --git a/src/processor_arm.cpp b/src/processor_arm.cpp index 000894fb05d7d..26564f7646325 100644 --- a/src/processor_arm.cpp +++ b/src/processor_arm.cpp @@ -1361,7 +1361,7 @@ const std::pair &jl_get_llvm_disasm_target(void) // RAS is not currently detectable AFAICT auto max_feature = get_max_feature(); static const auto res = get_llvm_target_str(TargetData{host_cpu_name(), - "+dotprod,+ras", + JL_LLVM_VERSION >= 60000 ? "+dotprod,+ras" : "+ras", {max_feature, 0}, {feature_masks & ~max_feature, 0}, 0}); return res; } diff --git a/src/processor_x86.cpp b/src/processor_x86.cpp index 8023172d987f0..a4aa2b2fa4d05 100644 --- a/src/processor_x86.cpp +++ b/src/processor_x86.cpp @@ -820,6 +820,17 @@ get_llvm_target_noext(const TargetData &data) features.push_back("+sse2"); features.push_back("+mmx"); features.push_back("+fxsr"); +#if JL_LLVM_VERSION < 50000 +# ifdef _CPU_X86_ + // LLVM has bug on < 5.0 when using avx in 32bit mode. + features.push_back("-avx"); +# endif + // Scatter-gatter can't handle address space on < 5.0 + // This is a base requirement for AVX512 so we have to turn all AVX512 features off + // Gatter is available in AVX2 too but fortunately LLVM doesn't use them. + features.push_back("-avx512f"); + features.push_back("-avx512dq"); +#endif return std::make_pair(std::move(name), std::move(features)); } diff --git a/src/rtutils.c b/src/rtutils.c index 4606dcf4d0e69..de0ef70d54457 100644 --- a/src/rtutils.c +++ b/src/rtutils.c @@ -462,20 +462,20 @@ JL_DLLEXPORT int jl_substrtof(char *str, int offset, size_t len, float *out) // showing -------------------------------------------------------------------- -JL_DLLEXPORT void jl_flush_cstdio(void) JL_NOTSAFEPOINT +JL_DLLEXPORT void jl_flush_cstdio(void) { fflush(stdout); fflush(stderr); } -JL_DLLEXPORT jl_value_t *jl_stdout_obj(void) JL_NOTSAFEPOINT +JL_DLLEXPORT jl_value_t *jl_stdout_obj(void) { if (jl_base_module == NULL) return NULL; jl_value_t *stdout_obj = jl_get_global(jl_base_module, jl_symbol("stdout")); return stdout_obj; } -JL_DLLEXPORT jl_value_t *jl_stderr_obj(void) JL_NOTSAFEPOINT +JL_DLLEXPORT jl_value_t *jl_stderr_obj(void) { if (jl_base_module == NULL) return NULL; jl_value_t *stderr_obj = jl_get_global(jl_base_module, jl_symbol("stderr")); @@ -484,7 +484,7 @@ JL_DLLEXPORT jl_value_t *jl_stderr_obj(void) JL_NOTSAFEPOINT // toys for debugging --------------------------------------------------------- -static size_t jl_show_svec(JL_STREAM *out, jl_svec_t *t, const char *head, const char *opn, const char *cls) JL_NOTSAFEPOINT +static size_t jl_show_svec(JL_STREAM *out, jl_svec_t *t, const char *head, const char *opn, const char *cls) { size_t i, n=0, len = jl_svec_len(t); n += jl_printf(out, "%s", head); @@ -504,12 +504,12 @@ struct recur_list { jl_value_t *v; }; -static size_t jl_static_show_x(JL_STREAM *out, jl_value_t *v, struct recur_list *depth) JL_NOTSAFEPOINT; +static size_t jl_static_show_x(JL_STREAM *out, jl_value_t *v, struct recur_list *depth); -JL_DLLEXPORT int jl_id_start_char(uint32_t wc) JL_NOTSAFEPOINT; -JL_DLLEXPORT int jl_id_char(uint32_t wc) JL_NOTSAFEPOINT; +JL_DLLEXPORT int jl_id_start_char(uint32_t wc); +JL_DLLEXPORT int jl_id_char(uint32_t wc); -JL_DLLEXPORT int jl_is_identifier(char *str) JL_NOTSAFEPOINT +JL_DLLEXPORT int jl_is_identifier(char *str) { size_t i = 0; uint32_t wc = u8_nextchar(str, &i); @@ -528,7 +528,7 @@ JL_DLLEXPORT int jl_is_identifier(char *str) JL_NOTSAFEPOINT // This is necessary to make sure that this function doesn't allocate any // memory through the Julia GC static size_t jl_static_show_x_(JL_STREAM *out, jl_value_t *v, jl_datatype_t *vt, - struct recur_list *depth) JL_NOTSAFEPOINT + struct recur_list *depth) { size_t n = 0; if ((uintptr_t)vt < 4096U) { @@ -596,7 +596,7 @@ static size_t jl_static_show_x_(JL_STREAM *out, jl_value_t *v, jl_datatype_t *vt if (globname && !strchr(jl_symbol_name(globname), '#') && !strchr(jl_symbol_name(globname), '@') && dv->name->module && jl_binding_resolved_p(dv->name->module, globname)) { - jl_binding_t *b = jl_get_module_binding(dv->name->module, globname); + jl_binding_t *b = jl_get_binding(dv->name->module, globname); if (b && jl_typeof(b->value) == v) globfunc = 1; } @@ -953,7 +953,7 @@ static size_t jl_static_show_x_(JL_STREAM *out, jl_value_t *v, jl_datatype_t *vt return n; } -static size_t jl_static_show_x(JL_STREAM *out, jl_value_t *v, struct recur_list *depth) JL_NOTSAFEPOINT +static size_t jl_static_show_x(JL_STREAM *out, jl_value_t *v, struct recur_list *depth) { // show values without calling a julia method or allocating through the GC if (v == NULL) { @@ -973,12 +973,12 @@ static size_t jl_static_show_x(JL_STREAM *out, jl_value_t *v, struct recur_list return jl_static_show_x_(out, v, (jl_datatype_t*)jl_typeof(v), &this_item); } -JL_DLLEXPORT size_t jl_static_show(JL_STREAM *out, jl_value_t *v) JL_NOTSAFEPOINT +JL_DLLEXPORT size_t jl_static_show(JL_STREAM *out, jl_value_t *v) { return jl_static_show_x(out, v, 0); } -JL_DLLEXPORT size_t jl_static_show_func_sig(JL_STREAM *s, jl_value_t *type) JL_NOTSAFEPOINT +JL_DLLEXPORT size_t jl_static_show_func_sig(JL_STREAM *s, jl_value_t *type) { jl_value_t *ftype = (jl_value_t*)jl_first_argument_datatype(type); if (ftype == NULL) diff --git a/src/runtime_intrinsics.c b/src/runtime_intrinsics.c index f947f22b3adf3..7bf36069d2e0f 100644 --- a/src/runtime_intrinsics.c +++ b/src/runtime_intrinsics.c @@ -78,11 +78,9 @@ JL_DLLEXPORT jl_value_t *jl_pointerset(jl_value_t *p, jl_value_t *x, jl_value_t JL_DLLEXPORT jl_value_t *jl_cglobal(jl_value_t *v, jl_value_t *ty) { JL_TYPECHK(cglobal, type, ty); - JL_GC_PUSH1(&v); jl_value_t *rt = - ty == (jl_value_t*)jl_void_type ? (jl_value_t*)jl_voidpointer_type : // a common case + v == (jl_value_t*)jl_void_type ? (jl_value_t*)jl_voidpointer_type : // a common case (jl_value_t*)jl_apply_type1((jl_value_t*)jl_pointer_type, ty); - JL_GC_PROMISE_ROOTED(rt); // (JL_ALWAYS_LEAFTYPE) if (!jl_is_concrete_type(rt)) jl_error("cglobal: type argument not concrete"); @@ -90,15 +88,12 @@ JL_DLLEXPORT jl_value_t *jl_cglobal(jl_value_t *v, jl_value_t *ty) if (jl_is_tuple(v) && jl_nfields(v) == 1) v = jl_fieldref(v, 0); - if (jl_is_pointer(v)) { - v = jl_bitcast(rt, v); - JL_GC_POP(); - return v; - } + if (jl_is_pointer(v)) + return jl_bitcast(rt, v); char *f_lib = NULL; if (jl_is_tuple(v) && jl_nfields(v) > 1) { - jl_value_t *t1 = jl_fieldref_noalloc(v, 1); + jl_value_t *t1 = jl_fieldref(v, 1); v = jl_fieldref(v, 0); if (jl_is_symbol(t1)) f_lib = jl_symbol_name((jl_sym_t*)t1); @@ -126,7 +121,6 @@ JL_DLLEXPORT jl_value_t *jl_cglobal(jl_value_t *v, jl_value_t *ty) jl_value_t *jv = jl_gc_alloc_1w(); jl_set_typeof(jv, rt); *(void**)jl_data_ptr(jv) = ptr; - JL_GC_POP(); return jv; } @@ -134,19 +128,19 @@ JL_DLLEXPORT jl_value_t *jl_cglobal_auto(jl_value_t *v) { return jl_cglobal(v, (jl_value_t*)jl_void_type); } -static inline char signbitbyte(void *a, unsigned bytes) JL_NOTSAFEPOINT +static inline char signbitbyte(void *a, unsigned bytes) { // sign bit of an signed number of n bytes, as a byte return (((signed char*)a)[bytes - 1] < 0) ? ~0 : 0; } -static inline char usignbitbyte(void *a, unsigned bytes) JL_NOTSAFEPOINT +static inline char usignbitbyte(void *a, unsigned bytes) { // sign bit of an unsigned number return 0; } -static inline unsigned select_by_size(unsigned sz) JL_NOTSAFEPOINT +static inline unsigned select_by_size(unsigned sz) { /* choose the right sized function specialization */ switch (sz) { @@ -161,7 +155,7 @@ static inline unsigned select_by_size(unsigned sz) JL_NOTSAFEPOINT #define SELECTOR_FUNC(intrinsic) \ typedef intrinsic##_t select_##intrinsic##_t[6]; \ - static inline intrinsic##_t select_##intrinsic(unsigned sz, const select_##intrinsic##_t list) JL_NOTSAFEPOINT \ + static inline intrinsic##_t select_##intrinsic(unsigned sz, const select_##intrinsic##_t list) \ { \ intrinsic##_t thunk = list[select_by_size(sz)]; \ if (!thunk) thunk = list[0]; \ @@ -181,7 +175,7 @@ static inline unsigned select_by_size(unsigned sz) JL_NOTSAFEPOINT // nbits::number of bits // c_type::c_type corresponding to nbits #define un_iintrinsic_ctype(OP, name, nbits, c_type) \ -static inline void jl_##name##nbits(unsigned runtime_nbits, void *pa, void *pr) JL_NOTSAFEPOINT \ +static inline void jl_##name##nbits(unsigned runtime_nbits, void *pa, void *pr) \ { \ c_type a = *(c_type*)pa; \ *(c_type*)pr = OP(a); \ @@ -193,7 +187,7 @@ static inline void jl_##name##nbits(unsigned runtime_nbits, void *pa, void *pr) // nbits::number of bits // c_type::c_type corresponding to nbits #define uu_iintrinsic_ctype(OP, name, nbits, c_type) \ -static inline unsigned jl_##name##nbits(unsigned runtime_nbits, void *pa) JL_NOTSAFEPOINT \ +static inline unsigned jl_##name##nbits(unsigned runtime_nbits, void *pa) \ { \ c_type a = *(c_type*)pa; \ return OP(a); \ @@ -205,7 +199,7 @@ static inline unsigned jl_##name##nbits(unsigned runtime_nbits, void *pa) JL_NOT // nbits::number of bits in the *input* // c_type::c_type corresponding to nbits #define un_fintrinsic_ctype(OP, name, c_type) \ -static inline void name(unsigned osize, void *pa, void *pr) JL_NOTSAFEPOINT \ +static inline void name(unsigned osize, void *pa, void *pr) \ { \ c_type a = *(c_type*)pa; \ OP((c_type*)pr, a); \ @@ -217,7 +211,7 @@ static inline void name(unsigned osize, void *pa, void *pr) JL_NOTSAFEPOINT \ // nbits::number of bits // c_type::c_type corresponding to nbits #define bi_intrinsic_ctype(OP, name, nbits, c_type) \ -static void jl_##name##nbits(unsigned runtime_nbits, void *pa, void *pb, void *pr) JL_NOTSAFEPOINT \ +static void jl_##name##nbits(unsigned runtime_nbits, void *pa, void *pb, void *pr) \ { \ c_type a = *(c_type*)pa; \ c_type b = *(c_type*)pb; \ @@ -230,7 +224,7 @@ static void jl_##name##nbits(unsigned runtime_nbits, void *pa, void *pb, void *p // nbits::number of bits // c_type::c_type corresponding to nbits #define bool_intrinsic_ctype(OP, name, nbits, c_type) \ -static int jl_##name##nbits(unsigned runtime_nbits, void *pa, void *pb) JL_NOTSAFEPOINT \ +static int jl_##name##nbits(unsigned runtime_nbits, void *pa, void *pb) \ { \ c_type a = *(c_type*)pa; \ c_type b = *(c_type*)pb; \ @@ -243,7 +237,7 @@ static int jl_##name##nbits(unsigned runtime_nbits, void *pa, void *pb) JL_NOTSA // nbits::number of bits // c_type::c_type corresponding to nbits #define checked_intrinsic_ctype(CHECK_OP, OP, name, nbits, c_type) \ -static int jl_##name##nbits(unsigned runtime_nbits, void *pa, void *pb, void *pr) JL_NOTSAFEPOINT \ +static int jl_##name##nbits(unsigned runtime_nbits, void *pa, void *pb, void *pr) \ { \ c_type a = *(c_type*)pa; \ c_type b = *(c_type*)pb; \ @@ -259,7 +253,7 @@ static int jl_##name##nbits(unsigned runtime_nbits, void *pa, void *pb, void *pr // nbits::number of bits // c_type::c_type corresponding to nbits #define ter_intrinsic_ctype(OP, name, nbits, c_type) \ -static void jl_##name##nbits(unsigned runtime_nbits, void *pa, void *pb, void *pc, void *pr) JL_NOTSAFEPOINT \ +static void jl_##name##nbits(unsigned runtime_nbits, void *pa, void *pb, void *pc, void *pr) \ { \ c_type a = *(c_type*)pa; \ c_type b = *(c_type*)pb; \ @@ -500,7 +494,7 @@ static const select_intrinsic_cmp_t name##_list = { \ }; \ cmp_iintrinsic(name, u) -typedef int (*intrinsic_checked_t)(unsigned, void*, void*, void*) JL_NOTSAFEPOINT; +typedef int (*intrinsic_checked_t)(unsigned, void*, void*, void*); SELECTOR_FUNC(intrinsic_checked) #define checked_iintrinsic(name, u, lambda_checked) \ JL_DLLEXPORT jl_value_t *jl_##name(jl_value_t *a, jl_value_t *b) \ @@ -592,7 +586,6 @@ static inline jl_value_t *jl_intrinsiclambda_checked(jl_value_t *ty, void *pa, v params[0] = ty; params[1] = (jl_value_t*)jl_bool_type; jl_datatype_t *tuptyp = jl_apply_tuple_type_v(params, 2); - JL_GC_PROMISE_ROOTED(tuptyp); // (JL_ALAWYS_LEAFTYPE) jl_ptls_t ptls = jl_get_ptls_states(); jl_value_t *newv = jl_gc_alloc(ptls, ((jl_datatype_t*)tuptyp)->size, tuptyp); diff --git a/src/signals-unix.c b/src/signals-unix.c index 298270b52aca0..230c0cb2dada5 100644 --- a/src/signals-unix.c +++ b/src/signals-unix.c @@ -577,6 +577,7 @@ static void *signal_listener(void *arg) } #endif while (1) { + profile = 0; sig = 0; errno = 0; #ifdef HAVE_KEVENT diff --git a/src/stackwalk.c b/src/stackwalk.c index dce26784dfb1f..735dcf0e71411 100644 --- a/src/stackwalk.c +++ b/src/stackwalk.c @@ -95,7 +95,7 @@ size_t rec_backtrace(uintptr_t *data, size_t maxsize) return rec_backtrace_ctx(data, maxsize, &context); } -static jl_value_t *array_ptr_void_type JL_ALWAYS_LEAFTYPE = NULL; +static jl_value_t *array_ptr_void_type = NULL; JL_DLLEXPORT jl_value_t *jl_backtrace_from_here(int returnsp) { jl_array_t *ip = NULL; diff --git a/src/staticdata.c b/src/staticdata.c index b86ac914a7a57..a08246326dfbf 100644 --- a/src/staticdata.c +++ b/src/staticdata.c @@ -128,12 +128,12 @@ typedef enum { #define write_uint8(s, n) ios_putc((n), (s)) #define read_uint8(s) ((uint8_t)ios_getc((s))) -static void write_uint32(ios_t *s, uint32_t i) JL_NOTSAFEPOINT +static void write_uint32(ios_t *s, uint32_t i) { ios_write(s, (char*)&i, 4); } -static uint32_t read_uint32(ios_t *s) JL_NOTSAFEPOINT +static uint32_t read_uint32(ios_t *s) { uint32_t x = 0; ios_read(s, (char*)&x, 4); @@ -307,7 +307,7 @@ static void jl_serialize_value_(jl_serializer_state *s, jl_value_t *v) } } -static void ios_ensureroom(ios_t *s, size_t newsize) JL_NOTSAFEPOINT +static void ios_ensureroom(ios_t *s, size_t newsize) { size_t prevsize = s->size; if (prevsize < newsize) { @@ -317,7 +317,7 @@ static void ios_ensureroom(ios_t *s, size_t newsize) JL_NOTSAFEPOINT } } -static void record_gvar(jl_serializer_state *s, int gid, uintptr_t reloc_id) JL_NOTSAFEPOINT +static void record_gvar(jl_serializer_state *s, int gid, uintptr_t reloc_id) { if (gid == 0) return; @@ -328,7 +328,7 @@ static void record_gvar(jl_serializer_state *s, int gid, uintptr_t reloc_id) JL_ } -static void write_padding(ios_t *s, size_t nb) JL_NOTSAFEPOINT +static void write_padding(ios_t *s, size_t nb) { static const char zeros[16] = {0}; while (nb > 16) { @@ -340,7 +340,7 @@ static void write_padding(ios_t *s, size_t nb) JL_NOTSAFEPOINT } -static void write_pointer(ios_t *s) JL_NOTSAFEPOINT +static void write_pointer(ios_t *s) { assert((ios_pos(s) & (sizeof(void*) - 1)) == 0 && "stream misaligned for writing a word-sized value"); write_padding(s, sizeof(void*)); @@ -348,7 +348,7 @@ static void write_pointer(ios_t *s) JL_NOTSAFEPOINT #define backref_id(s, v) _backref_id(s, (jl_value_t*)(v)) -static uintptr_t _backref_id(jl_serializer_state *s, jl_value_t *v) JL_NOTSAFEPOINT +static uintptr_t _backref_id(jl_serializer_state *s, jl_value_t *v) { assert(v != NULL && "cannot get backref to NULL object"); void *idx = HT_NOTFOUND; @@ -376,7 +376,7 @@ static uintptr_t _backref_id(jl_serializer_state *s, jl_value_t *v) JL_NOTSAFEPO } -static void write_pointerfield(jl_serializer_state *s, jl_value_t *fld) JL_NOTSAFEPOINT +static void write_pointerfield(jl_serializer_state *s, jl_value_t *fld) { if (fld != NULL) { arraylist_push(&s->relocs_list, (void*)(uintptr_t)ios_pos(s->s)); @@ -385,7 +385,7 @@ static void write_pointerfield(jl_serializer_state *s, jl_value_t *fld) JL_NOTSA write_pointer(s->s); } -static void write_gctaggedfield(jl_serializer_state *s, uintptr_t ref) JL_NOTSAFEPOINT +static void write_gctaggedfield(jl_serializer_state *s, uintptr_t ref) { arraylist_push(&s->gctags_list, (void*)(uintptr_t)ios_pos(s->s)); arraylist_push(&s->gctags_list, (void*)ref); @@ -475,7 +475,7 @@ static void jl_write_module(jl_serializer_state *s, uintptr_t item, jl_module_t write_pointer(s->s); tot += sizeof(void*); } - // newm = (jl_module_t*)&s->s->buf[reloc_offset]; + newm = (jl_module_t*)&s->s->buf[reloc_offset]; } } } @@ -1096,7 +1096,7 @@ static void jl_finalize_serializer(jl_serializer_state *s) } -void jl_typemap_rehash(jl_typemap_t *ml, int8_t offs); +void jl_typemap_rehash(union jl_typemap_t ml, int8_t offs); static void jl_reinit_item(jl_value_t *v, int how, arraylist_t *tracee_list) { jl_ptls_t ptls = jl_get_ptls_states(); @@ -1490,7 +1490,6 @@ static void jl_restore_system_image_from_stream(ios_t *f) deser_tag.items[0] = (void*)const_data.buf; jl_read_relocations(&s, GC_OLD_MARKED); // gctags size_t sizeof_tags = ios_pos(&relocs); - (void)sizeof_tags; jl_read_relocations(&s, 0); // general relocs ios_close(&relocs); ios_close(&const_data); diff --git a/src/subtype.c b/src/subtype.c index 1fc6bf33fde5a..33baf50bac0ee 100644 --- a/src/subtype.c +++ b/src/subtype.c @@ -52,7 +52,7 @@ typedef struct { // during the computation. // Most of the complexity is due to the "diagonal rule", requiring us to // identify which type vars range over only concrete types. -typedef struct jl_varbinding_t { +typedef struct _varbinding { jl_tvar_t *var; jl_value_t *lb; jl_value_t *ub; @@ -79,16 +79,14 @@ typedef struct jl_varbinding_t { // array of typevars that our bounds depend on, whose UnionAlls need to be // moved outside ours. jl_array_t *innervars; - struct jl_varbinding_t *prev; + struct _varbinding *prev; } jl_varbinding_t; // subtype algorithm state -typedef struct jl_stenv_t { - // N.B.: varbindings are created on the stack and rooted there +typedef struct { jl_varbinding_t *vars; // type variable environment jl_unionstate_t Lunions; // union state for unions on the left of A <: B jl_unionstate_t Runions; // union state for unions on the right - // N.B.: envout is gc-rooted jl_value_t **envout; // for passing caller the computed bounds of right-side variables int envsz; // length of envout int envidx; // current index in envout @@ -101,10 +99,7 @@ typedef struct jl_stenv_t { // state manipulation utilities // look up a type variable in an environment -#ifdef __clang_analyzer__ -static jl_varbinding_t *lookup(jl_stenv_t *e, jl_tvar_t *v) JL_GLOBALLY_ROOTED JL_NOTSAFEPOINT; -#else -static jl_varbinding_t *lookup(jl_stenv_t *e, jl_tvar_t *v) JL_GLOBALLY_ROOTED JL_NOTSAFEPOINT +static jl_varbinding_t *lookup(jl_stenv_t *e, jl_tvar_t *v) { jl_varbinding_t *b = e->vars; while (b != NULL) { @@ -113,16 +108,15 @@ static jl_varbinding_t *lookup(jl_stenv_t *e, jl_tvar_t *v) JL_GLOBALLY_ROOTED J } return b; } -#endif -static int statestack_get(jl_unionstate_t *st, int i) JL_NOTSAFEPOINT +static int statestack_get(jl_unionstate_t *st, int i) { assert(i >= 0 && i < sizeof(st->stack) * 8); // get the `i`th bit in an array of 32-bit words return (st->stack[i>>5] & (1<<(i&31))) != 0; } -static void statestack_set(jl_unionstate_t *st, int i, int val) JL_NOTSAFEPOINT +static void statestack_set(jl_unionstate_t *st, int i, int val) { assert(i >= 0 && i < sizeof(st->stack) * 8); if (val) @@ -146,10 +140,6 @@ static void save_env(jl_stenv_t *e, jl_value_t **root, jl_savedenv_t *se) } *root = (jl_value_t*)jl_alloc_svec(len*3); se->buf = (int8_t*)(len ? malloc(len*2) : NULL); -#ifdef __clang_analyzer__ - if (len) - memset(se->buf, 0, len*2); -#endif int i=0, j=0; v = e->vars; while (v != NULL) { jl_svecset(*root, i++, v->lb); @@ -162,7 +152,7 @@ static void save_env(jl_stenv_t *e, jl_value_t **root, jl_savedenv_t *se) se->rdepth = e->Runions.depth; } -static void restore_env(jl_stenv_t *e, jl_value_t *root, jl_savedenv_t *se) JL_NOTSAFEPOINT +static void restore_env(jl_stenv_t *e, jl_value_t *root, jl_savedenv_t *se) { jl_varbinding_t *v = e->vars; int i = 0, j = 0; @@ -173,7 +163,6 @@ static void restore_env(jl_stenv_t *e, jl_value_t *root, jl_savedenv_t *se) JL_N i++; if (root) v->innervars = (jl_array_t*)jl_svecref(root, i); i++; - assert(se->buf); v->occurs_inv = se->buf[j++]; v->occurs_cov = se->buf[j++]; v = v->prev; @@ -427,7 +416,7 @@ static jl_unionall_t *rename_unionall(jl_unionall_t *u) static int subtype(jl_value_t *x, jl_value_t *y, jl_stenv_t *e, int param); -static jl_value_t *pick_union_element(jl_value_t *u JL_PROPAGATES_ROOT, jl_stenv_t *e, int8_t R) JL_NOTSAFEPOINT +static jl_value_t *pick_union_element(jl_value_t *u, jl_stenv_t *e, int8_t R) { jl_unionstate_t *state = R ? &e->Runions : &e->Lunions; do { @@ -478,7 +467,7 @@ static int subtype_ccheck(jl_value_t *x, jl_value_t *y, jl_stenv_t *e) // use the current context to record where a variable occurred, for the purpose // of determining whether the variable is concrete. -static void record_var_occurrence(jl_varbinding_t *vb, jl_stenv_t *e, int param) JL_NOTSAFEPOINT +static void record_var_occurrence(jl_varbinding_t *vb, jl_stenv_t *e, int param) { if (vb != NULL && param) { // saturate counters at 2; we don't need values bigger than that @@ -563,7 +552,7 @@ static int var_gt(jl_tvar_t *b, jl_value_t *a, jl_stenv_t *e, int param) // check that a type is concrete or quasi-concrete (Type{T}). // this is used to check concrete typevars: // issubtype is false if the lower bound of a concrete type var is not concrete. -static int is_leaf_bound(jl_value_t *v) JL_NOTSAFEPOINT +static int is_leaf_bound(jl_value_t *v) { if (v == jl_bottom_type) return 1; @@ -578,12 +567,12 @@ static int is_leaf_bound(jl_value_t *v) JL_NOTSAFEPOINT return !jl_is_type(v) && !jl_is_typevar(v); } -static int is_leaf_typevar(jl_tvar_t *v) JL_NOTSAFEPOINT +static int is_leaf_typevar(jl_tvar_t *v) { return is_leaf_bound(v->lb); } -static jl_value_t *widen_Type(jl_value_t *t JL_PROPAGATES_ROOT) JL_NOTSAFEPOINT +static jl_value_t *widen_Type(jl_value_t *t) { if (jl_is_type_type(t) && !jl_is_typevar(jl_tparam0(t))) return jl_typeof(jl_tparam0(t)); @@ -605,13 +594,12 @@ JL_DLLEXPORT jl_array_t *jl_find_free_typevars(jl_value_t *v); // but this causes us to infer the larger `Type{T} where T<:Vector` instead. // However this is needed because many contexts check `isa(sp, TypeVar)` to determine // when a static parameter value is not known exactly. -static jl_value_t *fix_inferred_var_bound(jl_tvar_t *var, jl_value_t *ty JL_MAYBE_UNROOTED) +static jl_value_t *fix_inferred_var_bound(jl_tvar_t *var, jl_value_t *ty) { if (!jl_is_typevar(ty) && jl_has_free_typevars(ty)) { jl_value_t *ans = ty; - jl_array_t *vs = NULL; + jl_array_t *vs = jl_find_free_typevars(ty); JL_GC_PUSH2(&ans, &vs); - vs = jl_find_free_typevars(ty); int i; for (i = 0; i < jl_array_len(vs); i++) { ans = jl_type_unionall((jl_tvar_t*)jl_array_ptr_ref(vs, i), ans); @@ -623,7 +611,7 @@ static jl_value_t *fix_inferred_var_bound(jl_tvar_t *var, jl_value_t *ty JL_MAYB return ty; } -static int var_occurs_inside(jl_value_t *v, jl_tvar_t *var, int inside, int want_inv) JL_NOTSAFEPOINT; +static int var_occurs_inside(jl_value_t *v, jl_tvar_t *var, int inside, int want_inv); // compare UnionAll type `u` to `t`. `R==1` if `u` came from the right side of A <: B. static int subtype_unionall(jl_value_t *t, jl_unionall_t *u, jl_stenv_t *e, int8_t R, int param) @@ -642,7 +630,7 @@ static int subtype_unionall(jl_value_t *t, jl_unionall_t *u, jl_stenv_t *e, int8 btemp = btemp->prev; } jl_varbinding_t vb = { u->var, u->var->lb, u->var->ub, R, NULL, 0, 0, 0, 0, e->invdepth, 0, NULL, e->vars }; - JL_GC_PUSH4(&u, &vb.lb, &vb.ub, &vb.innervars); + JL_GC_PUSH3(&u, &vb.lb, &vb.ub); e->vars = &vb; int ans; if (R) { @@ -740,9 +728,8 @@ static int subtype_unionall(jl_value_t *t, jl_unionall_t *u, jl_stenv_t *e, int8 } // unwrap <=2 layers of UnionAlls, leaving the vars in *p1 and *p2 and returning the body -static jl_value_t *unwrap_2_unionall(jl_value_t *t, jl_tvar_t **p1, jl_tvar_t **p2) JL_NOTSAFEPOINT +static jl_value_t *unwrap_2_unionall(jl_value_t *t, jl_tvar_t **p1, jl_tvar_t **p2) { - assert(t); if (jl_is_unionall(t)) { *p1 = ((jl_unionall_t*)t)->var; t = ((jl_unionall_t*)t)->body; @@ -962,7 +949,6 @@ static int subtype(jl_value_t *x, jl_value_t *y, jl_stenv_t *e, int param) jl_value_t *ux = jl_unwrap_unionall(x); jl_value_t *uy = jl_unwrap_unionall(y); if ((x != ux || y != uy) && y != (jl_value_t*)jl_any_type && jl_is_datatype(ux) && jl_is_datatype(uy)) { - assert(ux); jl_datatype_t *xd = (jl_datatype_t*)ux, *yd = (jl_datatype_t*)uy; while (xd != NULL && xd != jl_any_type && xd->name != yd->name) { xd = xd->super; @@ -1202,13 +1188,6 @@ JL_DLLEXPORT int jl_types_equal(jl_value_t *a, jl_value_t *b) { if (obviously_egal(a, b)) return 1; if (obviously_unequal(a, b)) return 0; - if (jl_is_datatype(a) && !jl_is_concrete_type(b)) { - // if one type looks more likely to be abstract, check it on the left - // first in order to reject more quickly. - jl_value_t *temp = a; - a = b; - b = temp; - } return jl_subtype(a, b) && jl_subtype(b, a); } @@ -1343,7 +1322,7 @@ static jl_value_t *intersect_ufirst(jl_value_t *x, jl_value_t *y, jl_stenv_t *e, } // set a variable to a non-type constant -static jl_value_t *set_var_to_const(jl_varbinding_t *bb, jl_value_t *v JL_MAYBE_UNROOTED, jl_varbinding_t *othervar) +static jl_value_t *set_var_to_const(jl_varbinding_t *bb, jl_value_t *v, jl_varbinding_t *othervar) { int offset = bb->offset; if (othervar && offset == 0) @@ -1487,7 +1466,7 @@ static jl_value_t *intersect_var(jl_tvar_t *b, jl_value_t *a, jl_stenv_t *e, int // test whether `var` occurs inside constructors. `want_inv` tests only inside // invariant constructors. `inside` means we are currently inside a constructor of the // requested kind. -static int var_occurs_inside(jl_value_t *v, jl_tvar_t *var, int inside, int want_inv) JL_NOTSAFEPOINT +static int var_occurs_inside(jl_value_t *v, jl_tvar_t *var, int inside, int want_inv) { if (v == (jl_value_t*)var) { return inside; @@ -1516,7 +1495,7 @@ static int var_occurs_inside(jl_value_t *v, jl_tvar_t *var, int inside, int want } // Caller might not have rooted `res` -static jl_value_t *finish_unionall(jl_value_t *res JL_MAYBE_UNROOTED, jl_varbinding_t *vb, jl_stenv_t *e) +static jl_value_t *finish_unionall(jl_value_t *res, jl_varbinding_t *vb, jl_stenv_t *e) { jl_value_t *varval = NULL; jl_tvar_t *newvar = vb->var; @@ -1618,7 +1597,7 @@ static jl_value_t *finish_unionall(jl_value_t *res JL_MAYBE_UNROOTED, jl_varbind if (res != jl_bottom_type && vb->innervars != NULL) { int i; for(i=0; i < jl_array_len(vb->innervars); i++) { - jl_tvar_t *var = (jl_tvar_t*)jl_array_ptr_ref(vb->innervars, i); + jl_tvar_t *var = (jl_tvar_t*)jl_arrayref(vb->innervars, i); if (jl_has_typevar(res, var)) res = jl_new_struct(jl_unionall_type, (jl_tvar_t*)var, res); } @@ -1745,9 +1724,7 @@ static int intersect_vararg_length(jl_value_t *v, ssize_t n, jl_stenv_t *e, int8 // only do the check if N is free in the tuple type's last parameter if (jl_is_typevar(N) && N != (jl_value_t*)va_p1 && N != (jl_value_t*)va_p2) { jl_value_t *len = jl_box_long(n); - JL_GC_PUSH1(&len); jl_value_t *il = R ? intersect(len, N, e, 2) : intersect(N, len, e, 2); - JL_GC_POP(); if (il == jl_bottom_type) return 0; } @@ -1909,15 +1886,13 @@ static jl_value_t *intersect_invariant(jl_value_t *x, jl_value_t *y, jl_stenv_t if (jl_is_typevar(x) && jl_is_typevar(y) && (jl_is_typevar(ii) || !jl_is_type(ii))) return ii; if (ii == jl_bottom_type) { - if (!subtype_in_env(x, jl_bottom_type, e)) + if (!subtype_in_env(x, ii, e)) return NULL; flip_vars(e); - if (!subtype_in_env(y, jl_bottom_type, e)) { - flip_vars(e); - return NULL; - } + if (!subtype_in_env(y, ii, e)) + ii = NULL; flip_vars(e); - return jl_bottom_type; + return ii; } /* TODO: This is a band-aid for issue #23685. A better solution would be to @@ -2497,7 +2472,7 @@ static int type_morespecific_(jl_value_t *a, jl_value_t *b, int invariant, jl_ty static int num_occurs(jl_tvar_t *v, jl_typeenv_t *env); -static jl_value_t *nth_tuple_elt(jl_datatype_t *t JL_PROPAGATES_ROOT, size_t i) JL_NOTSAFEPOINT +static jl_value_t *nth_tuple_elt(jl_datatype_t *t, size_t i) { size_t len = jl_field_count(t); if (len == 0) diff --git a/src/support/analyzer_annotations.h b/src/support/analyzer_annotations.h index 62e6f27765dff..75236435dfb69 100644 --- a/src/support/analyzer_annotations.h +++ b/src/support/analyzer_annotations.h @@ -1,13 +1,5 @@ // This file is a part of Julia. License is MIT: https://julialang.org/license -#ifndef __has_feature -#define __has_feature(x) 0 -#endif -#if !(defined(__clang__) && __has_feature(nullability)) -#define _Nonnull -#endif -#define JL_NONNULL _Nonnull - #ifdef __clang_analyzer__ #define JL_PROPAGATES_ROOT __attribute__((annotate("julia_propagates_root"))) @@ -17,14 +9,14 @@ #define JL_ROOTING_ARGUMENT __attribute__((annotate("julia_rooting_argument"))) #define JL_ROOTED_ARGUMENT __attribute__((annotate("julia_rooted_argument"))) #define JL_GC_DISABLED __attribute__((annotate("julia_gc_disabled"))) -#define JL_ALWAYS_LEAFTYPE JL_GLOBALLY_ROOTED +#define JL_ALWAYS_LEAFTYPE __attribute__((annotate("julia_always_leaftype"))) #define JL_ROOTS_TEMPORARILY __attribute__((annotate("julia_temporarily_roots"))) #define JL_REQUIRE_ROOTED_SLOT __attribute__((annotate("julia_require_rooted_slot"))) #ifdef __cplusplus extern "C" { #endif - void JL_GC_PROMISE_ROOTED(void *v) JL_NOTSAFEPOINT; - void jl_may_leak(uintptr_t) JL_NOTSAFEPOINT; + void JL_GC_PROMISE_ROOTED(void *v); + void jl_may_leak(uintptr_t); #ifdef __cplusplus } #endif diff --git a/src/support/arraylist.h b/src/support/arraylist.h index 6616cdbc40446..3c4ed8a2ef21c 100644 --- a/src/support/arraylist.h +++ b/src/support/arraylist.h @@ -9,8 +9,6 @@ extern "C" { #endif -#include "analyzer_annotations.h" - typedef struct { size_t len; size_t max; @@ -21,7 +19,7 @@ typedef struct { arraylist_t *arraylist_new(arraylist_t *a, size_t size); void arraylist_free(arraylist_t *a); -void arraylist_push(arraylist_t *a, void *elt) JL_NOTSAFEPOINT; +void arraylist_push(arraylist_t *a, void *elt); void *arraylist_pop(arraylist_t *a); void arraylist_grow(arraylist_t *a, size_t n); diff --git a/src/support/dtypes.h b/src/support/dtypes.h index bd75ea3a9913c..4dfc945dbf7dd 100644 --- a/src/support/dtypes.h +++ b/src/support/dtypes.h @@ -13,7 +13,6 @@ #endif #include "platform.h" -#include "analyzer_annotations.h" #if !defined(_OS_WINDOWS_) #include @@ -145,7 +144,7 @@ typedef uint32_t uint_t; typedef int32_t int_t; #endif -STATIC_INLINE unsigned int next_power_of_two(unsigned int val) JL_NOTSAFEPOINT +STATIC_INLINE unsigned int next_power_of_two(unsigned int val) { /* this function taken from libuv src/unix/core.c */ val -= 1; diff --git a/src/support/hashing.h b/src/support/hashing.h index 8686c746f4898..7fcbf4a323e84 100644 --- a/src/support/hashing.h +++ b/src/support/hashing.h @@ -5,33 +5,32 @@ #include "utils.h" #include "dtypes.h" -#include "analyzer_annotations.h" #ifdef __cplusplus extern "C" { #endif -uint_t nextipow2(uint_t i) JL_NOTSAFEPOINT; -JL_DLLEXPORT uint32_t int32hash(uint32_t a) JL_NOTSAFEPOINT; -JL_DLLEXPORT uint64_t int64hash(uint64_t key) JL_NOTSAFEPOINT; -JL_DLLEXPORT uint32_t int64to32hash(uint64_t key) JL_NOTSAFEPOINT; +uint_t nextipow2(uint_t i); +JL_DLLEXPORT uint32_t int32hash(uint32_t a); +JL_DLLEXPORT uint64_t int64hash(uint64_t key); +JL_DLLEXPORT uint32_t int64to32hash(uint64_t key); #ifdef _P64 #define inthash int64hash #else #define inthash int32hash #endif -JL_DLLEXPORT uint64_t memhash(const char *buf, size_t n) JL_NOTSAFEPOINT; -JL_DLLEXPORT uint64_t memhash_seed(const char *buf, size_t n, uint32_t seed) JL_NOTSAFEPOINT; -JL_DLLEXPORT uint32_t memhash32(const char *buf, size_t n) JL_NOTSAFEPOINT; -JL_DLLEXPORT uint32_t memhash32_seed(const char *buf, size_t n, uint32_t seed) JL_NOTSAFEPOINT; +JL_DLLEXPORT uint64_t memhash(const char *buf, size_t n); +JL_DLLEXPORT uint64_t memhash_seed(const char *buf, size_t n, uint32_t seed); +JL_DLLEXPORT uint32_t memhash32(const char *buf, size_t n); +JL_DLLEXPORT uint32_t memhash32_seed(const char *buf, size_t n, uint32_t seed); #ifdef _P64 -STATIC_INLINE uint64_t bitmix(uint64_t a, uint64_t b) JL_NOTSAFEPOINT +STATIC_INLINE uint64_t bitmix(uint64_t a, uint64_t b) { return int64hash(a^bswap_64(b)); } #else -STATIC_INLINE uint32_t bitmix(uint32_t a, uint32_t b) JL_NOTSAFEPOINT +STATIC_INLINE uint32_t bitmix(uint32_t a, uint32_t b) { return int64to32hash((((uint64_t)a) << 32) | (uint64_t)b); } diff --git a/src/support/htable.h b/src/support/htable.h index 317a9dae95e1d..2b79eef12dc86 100644 --- a/src/support/htable.h +++ b/src/support/htable.h @@ -5,8 +5,6 @@ #define HT_N_INLINE 32 -#include "analyzer_annotations.h" - #ifdef __cplusplus extern "C" { #endif @@ -27,13 +25,13 @@ void htable_free(htable_t *h); // clear and (possibly) change size void htable_reset(htable_t *h, size_t sz); -#define HTPROT(HTNAME) \ -void *HTNAME##_get(htable_t *h, void *key) JL_NOTSAFEPOINT; \ -void HTNAME##_put(htable_t *h, void *key, void *val) JL_NOTSAFEPOINT; \ -void HTNAME##_adjoin(htable_t *h, void *key, void *val) JL_NOTSAFEPOINT;\ -int HTNAME##_has(htable_t *h, void *key) JL_NOTSAFEPOINT; \ -int HTNAME##_remove(htable_t *h, void *key) JL_NOTSAFEPOINT; \ -void **HTNAME##_bp(htable_t *h, void *key) JL_NOTSAFEPOINT; +#define HTPROT(HTNAME) \ +void *HTNAME##_get(htable_t *h, void *key); \ +void HTNAME##_put(htable_t *h, void *key, void *val); \ +void HTNAME##_adjoin(htable_t *h, void *key, void *val); \ +int HTNAME##_has(htable_t *h, void *key); \ +int HTNAME##_remove(htable_t *h, void *key); \ +void **HTNAME##_bp(htable_t *h, void *key); #define HTPROT_R(HTNAME) \ void *HTNAME##_get_r(htable_t *h, void *key, void *ctx); \ diff --git a/src/support/ios.h b/src/support/ios.h index aafb1d6446010..9d74d3033269e 100644 --- a/src/support/ios.h +++ b/src/support/ios.h @@ -5,7 +5,6 @@ #include #include "uv.h" -#include "analyzer_annotations.h" #ifdef __cplusplus extern "C" { @@ -75,12 +74,12 @@ extern void (*ios_set_io_wait_func)(int); /* low-level interface functions */ JL_DLLEXPORT size_t ios_read(ios_t *s, char *dest, size_t n); JL_DLLEXPORT size_t ios_readall(ios_t *s, char *dest, size_t n); -JL_DLLEXPORT size_t ios_write(ios_t *s, const char *data, size_t n) JL_NOTSAFEPOINT; -JL_DLLEXPORT int64_t ios_seek(ios_t *s, int64_t pos) JL_NOTSAFEPOINT; // absolute seek +JL_DLLEXPORT size_t ios_write(ios_t *s, const char *data, size_t n); +JL_DLLEXPORT int64_t ios_seek(ios_t *s, int64_t pos); // absolute seek JL_DLLEXPORT int64_t ios_seek_end(ios_t *s); JL_DLLEXPORT int64_t ios_skip(ios_t *s, int64_t offs); // relative seek -JL_DLLEXPORT int64_t ios_pos(ios_t *s) JL_NOTSAFEPOINT; // get current position -JL_DLLEXPORT int ios_trunc(ios_t *s, size_t size) JL_NOTSAFEPOINT; +JL_DLLEXPORT int64_t ios_pos(ios_t *s); // get current position +JL_DLLEXPORT int ios_trunc(ios_t *s, size_t size); JL_DLLEXPORT int ios_eof(ios_t *s); JL_DLLEXPORT int ios_eof_blocking(ios_t *s); JL_DLLEXPORT int ios_flush(ios_t *s); @@ -88,23 +87,23 @@ JL_DLLEXPORT void ios_close(ios_t *s); JL_DLLEXPORT int ios_isopen(ios_t *s); JL_DLLEXPORT char *ios_take_buffer(ios_t *s, size_t *psize); // release buffer to caller // set buffer space to use -JL_DLLEXPORT int ios_setbuf(ios_t *s, char *buf, size_t size, int own) JL_NOTSAFEPOINT; +JL_DLLEXPORT int ios_setbuf(ios_t *s, char *buf, size_t size, int own); JL_DLLEXPORT int ios_bufmode(ios_t *s, bufmode_t mode); JL_DLLEXPORT int ios_get_readable(ios_t *s); JL_DLLEXPORT int ios_get_writable(ios_t *s); JL_DLLEXPORT void ios_set_readonly(ios_t *s); JL_DLLEXPORT size_t ios_copy(ios_t *to, ios_t *from, size_t nbytes); JL_DLLEXPORT size_t ios_copyall(ios_t *to, ios_t *from); -JL_DLLEXPORT size_t ios_copyuntil(ios_t *to, ios_t *from, char delim) JL_NOTSAFEPOINT; +JL_DLLEXPORT size_t ios_copyuntil(ios_t *to, ios_t *from, char delim); JL_DLLEXPORT size_t ios_nchomp(ios_t *from, size_t ntowrite); // ensure at least n bytes are buffered if possible. returns # available. JL_DLLEXPORT size_t ios_readprep(ios_t *from, size_t n); /* stream creation */ JL_DLLEXPORT -ios_t *ios_file(ios_t *s, const char *fname, int rd, int wr, int create, int trunc) JL_NOTSAFEPOINT; +ios_t *ios_file(ios_t *s, const char *fname, int rd, int wr, int create, int trunc); JL_DLLEXPORT ios_t *ios_mkstemp(ios_t *f, char *fname); -JL_DLLEXPORT ios_t *ios_mem(ios_t *s, size_t initsize) JL_NOTSAFEPOINT; +JL_DLLEXPORT ios_t *ios_mem(ios_t *s, size_t initsize); ios_t *ios_str(ios_t *s, char *str); ios_t *ios_static_buffer(ios_t *s, char *buf, size_t sz); JL_DLLEXPORT ios_t *ios_fd(ios_t *s, long fd, int isfile, int own); diff --git a/src/support/utf8.h b/src/support/utf8.h index 1d8e31c043838..ba5085a2b34f3 100644 --- a/src/support/utf8.h +++ b/src/support/utf8.h @@ -7,8 +7,6 @@ extern "C" { #endif -#include "analyzer_annotations.h" - /* is c the start of a utf8 sequence? */ #define isutf(c) (((c)&0xC0)!=0x80) @@ -30,7 +28,7 @@ JL_DLLEXPORT size_t u8_offset(const char *str, size_t charnum); JL_DLLEXPORT size_t u8_charnum(const char *str, size_t offset); /* return next character, updating an index variable */ -uint32_t u8_nextchar(const char *s, size_t *i) JL_NOTSAFEPOINT; +uint32_t u8_nextchar(const char *s, size_t *i); /* next character without NUL character terminator */ uint32_t u8_nextmemchar(const char *s, size_t *i); diff --git a/src/task.c b/src/task.c index f83dfcf6df561..6cd7d8c6727d8 100644 --- a/src/task.c +++ b/src/task.c @@ -41,9 +41,7 @@ volatile int jl_in_stackwalk = 0; #endif /* This probing code is derived from Douglas Jones' user thread library */ -static void _probe_arch(void); -#ifndef __clang_analyzer__ /* true if stack grows up, false if down */ static int _stack_grows_up; @@ -139,7 +137,6 @@ static void _probe_arch(void) intptr_t prior_diff = p.probe_local - p.prior_local; _frame_offset = labs(prior_diff); } -#endif /* end probing code */ @@ -199,7 +196,7 @@ static void NOINLINE restore_stack(jl_ptls_t ptls, char *p) static jl_function_t *task_done_hook_func=NULL; -static void JL_NORETURN finish_task(jl_task_t *t, jl_value_t *resultval JL_MAYBE_UNROOTED) +static void JL_NORETURN finish_task(jl_task_t *t, jl_value_t *resultval) { jl_ptls_t ptls = jl_get_ptls_states(); JL_SIGATOMIC_BEGIN(); @@ -243,7 +240,7 @@ static void JL_NORETURN finish_task(jl_task_t *t, jl_value_t *resultval JL_MAYBE abort(); } -static void record_backtrace(void) JL_NOTSAFEPOINT +static void record_backtrace(void) { jl_ptls_t ptls = jl_get_ptls_states(); ptls->bt_size = rec_backtrace(ptls->bt_data, JL_MAX_BT_SIZE); @@ -535,7 +532,7 @@ static void init_task(jl_task_t *t, char *stack) #endif /* !COPY_STACKS */ jl_timing_block_t *jl_pop_timing_block(jl_timing_block_t *cur_block); -JL_DLLEXPORT JL_NORETURN void jl_no_exc_handler(jl_value_t *e) JL_NOTSAFEPOINT +JL_DLLEXPORT JL_NORETURN void jl_no_exc_handler(jl_value_t *e) { jl_printf(JL_STDERR, "fatal: error thrown and no exception handler available.\n"); jl_static_show(JL_STDERR, e); @@ -545,15 +542,15 @@ JL_DLLEXPORT JL_NORETURN void jl_no_exc_handler(jl_value_t *e) JL_NOTSAFEPOINT } // yield to exception handler -void JL_NORETURN throw_internal(jl_value_t *e JL_MAYBE_UNROOTED) +void JL_NORETURN throw_internal(jl_value_t *e) { jl_ptls_t ptls = jl_get_ptls_states(); ptls->io_wait = 0; if (ptls->safe_restore) jl_longjmp(*ptls->safe_restore, 1); + jl_gc_unsafe_enter(ptls); assert(e != NULL); ptls->exception_in_transit = e; - jl_gc_unsafe_enter(ptls); jl_handler_t *eh = ptls->current_task->eh; if (eh != NULL) { #ifdef ENABLE_TIMINGS @@ -670,7 +667,7 @@ JL_DLLEXPORT jl_value_t *jl_get_current_task(void) jl_function_t *jl_unprotect_stack_func; // Do one-time initializations for task system -void jl_init_tasks(void) JL_GC_DISABLED +void jl_init_tasks(void) { _probe_arch(); jl_task_type = (jl_datatype_t*) diff --git a/src/threading.c b/src/threading.c index e75c0949d9ce8..1f142204b2f60 100644 --- a/src/threading.c +++ b/src/threading.c @@ -396,7 +396,6 @@ void ti_threadfun(void *arg) ti_threadgroup_fork(tg, ptls->tid, (void **)&work, init); init = 0; - JL_GC_PROMISE_ROOTED(work); #if PROFILE_JL_THREADING uint64_t tfork = uv_hrtime(); @@ -610,15 +609,12 @@ void jl_start_threads(void) mask[0] = 0; } - // The analyzer doesn't know jl_n_threads doesn't change, help it - size_t nthreads = jl_n_threads; - // create threads - targs = (ti_threadarg_t **)malloc((nthreads - 1) * sizeof (ti_threadarg_t *)); + targs = (ti_threadarg_t **)malloc((jl_n_threads - 1) * sizeof (ti_threadarg_t *)); - uv_barrier_init(&thread_init_done, nthreads); + uv_barrier_init(&thread_init_done, jl_n_threads); - for (i = 0; i < nthreads - 1; ++i) { + for (i = 0; i < jl_n_threads - 1; ++i) { targs[i] = (ti_threadarg_t *)malloc(sizeof (ti_threadarg_t)); targs[i]->state = TI_THREAD_INIT; targs[i]->tid = i + 1; @@ -632,13 +628,13 @@ void jl_start_threads(void) } // set up the world thread group - ti_threadgroup_create(1, nthreads, 1, &tgworld); - for (i = 0; i < nthreads; ++i) + ti_threadgroup_create(1, jl_n_threads, 1, &tgworld); + for (i = 0; i < jl_n_threads; ++i) ti_threadgroup_addthread(tgworld, i, NULL); ti_threadgroup_initthread(tgworld, ptls->tid); // give the threads the world thread group; they will block waiting for fork - for (i = 0; i < nthreads - 1; ++i) { + for (i = 0; i < jl_n_threads - 1; ++i) { targs[i]->tg = tgworld; jl_atomic_store_release(&targs[i]->state, TI_THREAD_WORK); } @@ -723,7 +719,6 @@ JL_DLLEXPORT jl_value_t *jl_threading_run(jl_value_t *_args) #endif // this thread must do work too (TODO: reduction?) - JL_GC_PROMISE_ROOTED(threadwork.mfunc); tw->ret = ti_run_fun(threadwork.fptr, threadwork.mfunc, args, nargs); #if PROFILE_JL_THREADING diff --git a/src/tls.h b/src/tls.h index 3bc7bf7147269..55be0a78290fd 100644 --- a/src/tls.h +++ b/src/tls.h @@ -27,10 +27,10 @@ extern "C" { JL_DLLEXPORT int16_t jl_threadid(void); JL_DLLEXPORT void jl_threading_profile(void); -JL_DLLEXPORT JL_CONST_FUNC jl_ptls_t (jl_get_ptls_states)(void) JL_GLOBALLY_ROOTED JL_NOTSAFEPOINT; +JL_DLLEXPORT JL_CONST_FUNC jl_ptls_t (jl_get_ptls_states)(void); #ifndef JULIA_ENABLE_THREADING -extern JL_DLLEXPORT jl_tls_states_t jl_tls_states JL_GLOBALLY_ROOTED; +extern JL_DLLEXPORT jl_tls_states_t jl_tls_states; #define jl_get_ptls_states() (&jl_tls_states) #else // ifndef JULIA_ENABLE_THREADING typedef jl_ptls_t (*jl_get_ptls_states_func)(void); diff --git a/src/toplevel.c b/src/toplevel.c index 0f0eff0e9ae31..6da0ab47b98f5 100644 --- a/src/toplevel.c +++ b/src/toplevel.c @@ -73,7 +73,7 @@ JL_DLLEXPORT jl_module_t *jl_new_main_module(void) return old_main; } -static jl_function_t *jl_module_get_initializer(jl_module_t *m JL_PROPAGATES_ROOT) +static jl_function_t *jl_module_get_initializer(jl_module_t *m) { return (jl_function_t*)jl_get_global(m, jl_symbol("__init__")); } @@ -273,9 +273,7 @@ jl_value_t *jl_eval_module_expr(jl_module_t *parent_module, jl_expr_t *ex) JL_TRY { size_t i, l = module_stack.len; for (i = stackidx; i < l; i++) { - jl_module_t *m = (jl_module_t*)module_stack.items[i]; - JL_GC_PROMISE_ROOTED(m); - jl_module_load_time_initialize(m); + jl_module_load_time_initialize((jl_module_t*)module_stack.items[i]); } assert(module_stack.len == l); module_stack.len = stackidx; @@ -323,7 +321,7 @@ JL_DLLEXPORT jl_module_t *jl_base_relative_to(jl_module_t *m) return jl_top_module; } -static void expr_attributes(jl_value_t *v, int *has_intrinsics, int *has_defs) JL_NOTSAFEPOINT +static void expr_attributes(jl_value_t *v, int *has_intrinsics, int *has_defs) { if (!jl_is_expr(v)) return; @@ -362,7 +360,7 @@ static void expr_attributes(jl_value_t *v, int *has_intrinsics, int *has_defs) J jl_module_t *mod = jl_globalref_mod(f); jl_sym_t *name = jl_globalref_name(f); if (jl_binding_resolved_p(mod, name)) { - jl_binding_t *b = jl_get_module_binding(mod, name); + jl_binding_t *b = jl_get_binding(mod, name); if (b && b->value && b->constp) called = b->value; } @@ -420,7 +418,7 @@ static void body_attributes(jl_array_t *body, int *has_intrinsics, int *has_defs } } -static jl_module_t *call_require(jl_module_t *mod, jl_sym_t *var) JL_GLOBALLY_ROOTED +static jl_module_t *call_require(jl_module_t *mod, jl_sym_t *var) { static jl_value_t *require_func = NULL; static size_t require_world = 0; @@ -453,7 +451,7 @@ static jl_module_t *call_require(jl_module_t *mod, jl_sym_t *var) JL_GLOBALLY_RO // either: // - sets *name and returns the module to import *name from // - sets *name to NULL and returns a module to import -static jl_module_t *eval_import_path(jl_module_t *where, jl_module_t *from JL_PROPAGATES_ROOT, jl_array_t *args, jl_sym_t **name, const char *keyword) JL_GLOBALLY_ROOTED +static jl_module_t *eval_import_path(jl_module_t *where, jl_module_t *from, jl_array_t *args, jl_sym_t **name, const char *keyword) { jl_sym_t *var = (jl_sym_t*)jl_array_ptr_ref(args, 0); size_t i = 1; @@ -490,7 +488,6 @@ static jl_module_t *eval_import_path(jl_module_t *where, jl_module_t *from JL_PR if (var != dot_sym) break; i++; - assert(m); m = m->parent; } } @@ -504,7 +501,6 @@ static jl_module_t *eval_import_path(jl_module_t *where, jl_module_t *from JL_PR if (i == jl_array_len(args)-1) break; m = (jl_module_t*)jl_eval_global_var(m, var); - JL_GC_PROMISE_ROOTED(m); if (!jl_is_module(m)) jl_errorf("invalid %s path: \"%s\" does not name a module", keyword, jl_symbol_name(var)); i++; @@ -513,7 +509,7 @@ static jl_module_t *eval_import_path(jl_module_t *where, jl_module_t *from JL_PR return m; } -int jl_is_toplevel_only_expr(jl_value_t *e) JL_NOTSAFEPOINT +int jl_is_toplevel_only_expr(jl_value_t *e) { return jl_is_expr(e) && (((jl_expr_t*)e)->head == module_sym || @@ -539,9 +535,8 @@ static jl_method_instance_t *method_instance_for_thunk(jl_code_info_t *src, jl_m return li; } -static void import_module(jl_module_t *JL_NONNULL m, jl_module_t *import) +static void import_module(jl_module_t *m, jl_module_t *import) { - assert(m); jl_sym_t *name = import->name; jl_binding_t *b; if (jl_binding_resolved_p(m, name)) { @@ -563,7 +558,7 @@ static void import_module(jl_module_t *JL_NONNULL m, jl_module_t *import) } // in `import A.B: x, y, ...`, evaluate the `A.B` part if it exists -static jl_module_t *eval_import_from(jl_module_t *m JL_PROPAGATES_ROOT, jl_expr_t *ex, const char *keyword) +static jl_module_t *eval_import_from(jl_module_t *m, jl_expr_t *ex, const char *keyword) { if (jl_expr_nargs(ex) == 1 && jl_is_expr(jl_exprarg(ex, 0))) { jl_expr_t *fr = (jl_expr_t*)jl_exprarg(ex, 0); @@ -587,7 +582,7 @@ static jl_module_t *eval_import_from(jl_module_t *m JL_PROPAGATES_ROOT, jl_expr_ return NULL; } -jl_value_t *jl_toplevel_eval_flex(jl_module_t *JL_NONNULL m, jl_value_t *e, int fast, int expanded) +jl_value_t *jl_toplevel_eval_flex(jl_module_t *m, jl_value_t *e, int fast, int expanded) { jl_ptls_t ptls = jl_get_ptls_states(); if (!jl_is_expr(e)) { diff --git a/src/typemap.c b/src/typemap.c index 42e5fb6e82b22..03f9ec7564c58 100644 --- a/src/typemap.c +++ b/src/typemap.c @@ -177,7 +177,7 @@ static inline int sig_match_simple(jl_value_t **args, size_t n, jl_value_t **sig // ----- MethodCache helper functions ----- // -static inline size_t jl_intref(const jl_array_t *arr, size_t idx) JL_NOTSAFEPOINT +static inline size_t jl_intref(const jl_array_t *arr, size_t idx) { jl_value_t *el = jl_tparam0(jl_typeof(arr)); if (el == (jl_value_t*)jl_uint8_type) @@ -190,7 +190,7 @@ static inline size_t jl_intref(const jl_array_t *arr, size_t idx) JL_NOTSAFEPOIN abort(); } -static inline void jl_intset(const jl_array_t *arr, size_t idx, size_t val) JL_NOTSAFEPOINT +static inline void jl_intset(const jl_array_t *arr, size_t idx, size_t val) { jl_value_t *el = jl_tparam0(jl_typeof(arr)); if (el == (jl_value_t*)jl_uint8_type) @@ -224,14 +224,14 @@ static jl_array_t *jl_alloc_int_1d(size_t np, size_t len) ty = jl_array_uint8_type; } else if (np < 0xFFFF) { - static jl_value_t *int16 JL_ALWAYS_LEAFTYPE = NULL; + static jl_value_t *int16 = NULL; if (int16 == NULL) int16 = jl_apply_array_type((jl_value_t*)jl_uint16_type, 1); ty = int16; } else { assert(np < 0x7FFFFFFF); - static jl_value_t *int32 JL_ALWAYS_LEAFTYPE = NULL; + static jl_value_t *int32 = NULL; if (int32 == NULL) int32 = jl_apply_array_type((jl_value_t*)jl_uint32_type, 1); ty = int32; @@ -242,28 +242,30 @@ static jl_array_t *jl_alloc_int_1d(size_t np, size_t len) } static inline -jl_typemap_t *mtcache_hash_lookup(const struct jl_ordereddict_t *a JL_PROPAGATES_ROOT, jl_value_t *ty, int8_t tparam, int8_t offs) JL_NOTSAFEPOINT +union jl_typemap_t mtcache_hash_lookup(const struct jl_ordereddict_t *a, jl_value_t *ty, int8_t tparam, int8_t offs) { uintptr_t uid = ((jl_datatype_t*)ty)->uid; - jl_typemap_t *ml = jl_nothing; + union jl_typemap_t ml; + ml.unknown = jl_nothing; if (!uid) return ml; size_t idx = jl_intref(a->indices, uid & (a->indices->nrows-1)); if (idx > 0) { - ml = jl_array_ptr_ref(a->values, idx - 1); - if (ml == jl_nothing) + ml.unknown = jl_array_ptr_ref(a->values, idx - 1); + if (ml.unknown == jl_nothing) return ml; jl_value_t *t; - if (jl_typeof(ml) == (jl_value_t*)jl_typemap_level_type) { - t = ((jl_typemap_level_t*)ml)->key; + if (jl_typeof(ml.unknown) == (jl_value_t*)jl_typemap_level_type) { + t = ml.node->key; } else { - t = jl_field_type(jl_unwrap_unionall(jl_typemap_entry_sig(ml)), offs); + assert(jl_typeof(ml.unknown) == (jl_value_t*)jl_typemap_entry_type); + t = jl_field_type(jl_unwrap_unionall((jl_value_t*)ml.leaf->sig), offs); if (tparam) t = jl_tparam0(t); } if (t != ty) - ml = jl_nothing; + ml.unknown = jl_nothing; } return ml; } @@ -273,15 +275,17 @@ static void mtcache_rehash(struct jl_ordereddict_t *pa, size_t newlen, jl_value_ size_t i, nval = jl_array_len(pa->values); jl_array_t *n = jl_alloc_int_1d(nval + 1, newlen); for (i = 1; i <= nval; i++) { - jl_typemap_t *ml = jl_array_ptr_ref(pa->values, i - 1); - if (ml == jl_nothing) + union jl_typemap_t ml; + ml.unknown = jl_array_ptr_ref(pa->values, i - 1); + if (ml.unknown == jl_nothing) continue; jl_value_t *t; - if (jl_typeof(ml) == (jl_value_t*)jl_typemap_level_type) { - t = ((jl_typemap_level_t*)ml)->key; + if (jl_typeof(ml.unknown) == (jl_value_t*)jl_typemap_level_type) { + t = ml.node->key; } else { - t = jl_field_type(jl_unwrap_unionall(jl_typemap_entry_sig(ml)), offs); + assert(jl_typeof(ml.unknown) == (jl_value_t*)jl_typemap_entry_type); + t = jl_field_type(jl_unwrap_unionall((jl_value_t*)ml.leaf->sig), offs); if (tparam) t = jl_tparam0(t); } @@ -302,31 +306,30 @@ static void mtcache_rehash(struct jl_ordereddict_t *pa, size_t newlen, jl_value_ } // Recursively rehash a TypeMap (for example, after deserialization) -void jl_typemap_rehash(jl_typemap_t *ml, int8_t offs); +void jl_typemap_rehash(union jl_typemap_t ml, int8_t offs); void jl_typemap_rehash_array(struct jl_ordereddict_t *pa, jl_value_t *parent, int8_t tparam, int8_t offs) { size_t i, len = jl_array_len(pa->values); for (i = 0; i < len; i++) { - jl_typemap_t *ml = jl_array_ptr_ref(pa->values, i); - assert(ml != NULL); + union jl_typemap_t ml; + ml.unknown = jl_array_ptr_ref(pa->values, i); + assert(ml.unknown != NULL); jl_typemap_rehash(ml, offs+1); } mtcache_rehash(pa, 4 * next_power_of_two(len), parent, tparam, offs); } -void jl_typemap_rehash(jl_typemap_t *ml, int8_t offs) -{ - if (jl_typeof(ml) == (jl_value_t*)jl_typemap_level_type) { - jl_typemap_level_t *node = (jl_typemap_level_t*)ml; - if (node->targ.values != (void *)jl_nothing) - jl_typemap_rehash_array(&node->targ, ml, 1, offs); - if (node->arg1.values != (void *)jl_nothing) - jl_typemap_rehash_array(&node->arg1, ml, 0, offs); - jl_typemap_rehash(node->any, offs + 1); +void jl_typemap_rehash(union jl_typemap_t ml, int8_t offs) { + if (jl_typeof(ml.unknown) == (jl_value_t*)jl_typemap_level_type) { + if (ml.node->targ.values != (void*)jl_nothing) + jl_typemap_rehash_array(&ml.node->targ, ml.unknown, 1, offs); + if (ml.node->arg1.values != (void*)jl_nothing) + jl_typemap_rehash_array(&ml.node->arg1, ml.unknown, 0, offs); + jl_typemap_rehash(ml.node->any, offs+1); } } -static jl_typemap_t **mtcache_hash_bp(struct jl_ordereddict_t *pa JL_PROPAGATES_ROOT, jl_value_t *ty, - int8_t tparam, int8_t offs, jl_value_t *parent) +static union jl_typemap_t *mtcache_hash_bp(struct jl_ordereddict_t *pa, jl_value_t *ty, + int8_t tparam, int8_t offs, jl_value_t *parent) { if (jl_is_datatype(ty)) { uintptr_t uid = ((jl_datatype_t*)ty)->uid; @@ -349,19 +352,18 @@ static jl_typemap_t **mtcache_hash_bp(struct jl_ordereddict_t *pa JL_PROPAGATES_ if (idx > jl_max_int(pa->indices)) mtcache_rehash(pa, jl_array_len(pa->indices), parent, tparam, offs); jl_intset(pa->indices, slot, idx); - return &((jl_typemap_t **)jl_array_ptr_data(pa->values))[idx - 1]; + return &((union jl_typemap_t*)jl_array_data(pa->values))[idx - 1]; } - jl_typemap_t **pml = &((jl_typemap_t **)jl_array_ptr_data(pa->values))[idx - 1]; - if (*pml == jl_nothing) + union jl_typemap_t *pml = &((union jl_typemap_t*)jl_array_data(pa->values))[idx - 1]; + if (pml->unknown == jl_nothing) return pml; jl_value_t *t; - if (jl_typeof(*pml) == (jl_value_t*)jl_typemap_level_type) { - t = ((jl_typemap_level_t*)*pml)->key; + if (jl_typeof(pml->unknown) == (jl_value_t*)jl_typemap_level_type) { + t = pml->node->key; } else { - t = jl_field_type(jl_unwrap_unionall( - jl_typemap_entry_sig(*pml)), - offs); + assert(jl_typeof(pml->unknown) == (jl_value_t*)jl_typemap_entry_type); + t = jl_field_type(jl_unwrap_unionall((jl_value_t*)pml->leaf->sig), offs); if (tparam) t = jl_tparam0(t); } @@ -378,7 +380,7 @@ static jl_typemap_t **mtcache_hash_bp(struct jl_ordereddict_t *pa JL_PROPAGATES_ static int jl_typemap_array_visitor(struct jl_ordereddict_t *a, jl_typemap_visitor_fptr fptr, void *closure) { size_t i, l = jl_array_len(a->values); - jl_typemap_t **data = (jl_typemap_t **)jl_array_ptr_data(a->values); + union jl_typemap_t *data = (union jl_typemap_t*)jl_array_data(a->values); for(i=0; i < l; i++) { if (!jl_typemap_visitor(data[i], fptr, closure)) return 0; @@ -397,22 +399,21 @@ static int jl_typemap_node_visitor(jl_typemap_entry_t *ml, jl_typemap_visitor_fp return 1; } -int jl_typemap_visitor(jl_typemap_t *cache, jl_typemap_visitor_fptr fptr, void *closure) +int jl_typemap_visitor(union jl_typemap_t cache, jl_typemap_visitor_fptr fptr, void *closure) { - if (jl_typeof(cache) == (jl_value_t*)jl_typemap_level_type) { - jl_typemap_level_t *node = (jl_typemap_level_t*)cache; - if (node->targ.values != (void*)jl_nothing) - if (!jl_typemap_array_visitor(&node->targ, fptr, closure)) + if (jl_typeof(cache.unknown) == (jl_value_t*)jl_typemap_level_type) { + if (cache.node->targ.values != (void*)jl_nothing) + if (!jl_typemap_array_visitor(&cache.node->targ, fptr, closure)) return 0; - if (node->arg1.values != (void*)jl_nothing) - if (!jl_typemap_array_visitor(&node->arg1, fptr, closure)) + if (cache.node->arg1.values != (void*)jl_nothing) + if (!jl_typemap_array_visitor(&cache.node->arg1, fptr, closure)) return 0; - if (!jl_typemap_node_visitor(node->linear, fptr, closure)) + if (!jl_typemap_node_visitor(cache.node->linear, fptr, closure)) return 0; - return jl_typemap_visitor(node->any, fptr, closure); + return jl_typemap_visitor(cache.node->any, fptr, closure); } else { - return jl_typemap_node_visitor((jl_typemap_entry_t*)cache, fptr, closure); + return jl_typemap_node_visitor(cache.leaf, fptr, closure); } } @@ -427,17 +428,17 @@ static int jl_typemap_intersection_array_visitor(struct jl_ordereddict_t *a, jl_ int offs, struct typemap_intersection_env *closure) { size_t i, l = jl_array_len(a->values); - jl_typemap_t **data = (jl_typemap_t **)jl_array_ptr_data(a->values); + union jl_typemap_t *data = (union jl_typemap_t*)jl_array_data(a->values); for (i = 0; i < l; i++) { - jl_typemap_t *ml = data[i]; - if (ml == jl_nothing) + union jl_typemap_t ml = data[i]; + if (ml.unknown == jl_nothing) continue; jl_value_t *t; - if (jl_typeof(ml) == (jl_value_t *)jl_typemap_level_type) { - t = ((jl_typemap_level_t*)ml)->key; + if (jl_typeof(ml.unknown) == (jl_value_t*)jl_typemap_level_type) { + t = ml.node->key; } else { - t = jl_field_type(jl_unwrap_unionall(jl_typemap_entry_sig(ml)), offs); + t = jl_field_type(jl_unwrap_unionall((jl_value_t*)ml.leaf->sig), offs); if (tparam) t = jl_tparam0(t); } @@ -492,11 +493,11 @@ static int jl_typemap_intersection_node_visitor(jl_typemap_entry_t *ml, struct t return 1; } -int jl_typemap_intersection_visitor(jl_typemap_t *map, int offs, +int jl_typemap_intersection_visitor(union jl_typemap_t map, int offs, struct typemap_intersection_env *closure) { - if (jl_typeof(map) == (jl_value_t *)jl_typemap_level_type) { - jl_typemap_level_t *cache = (jl_typemap_level_t*)map; + if (jl_typeof(map.unknown) == (jl_value_t*)jl_typemap_level_type) { + jl_typemap_level_t *cache = map.node; jl_value_t *ty = NULL; jl_value_t *ttypes = jl_unwrap_unionall(closure->type); assert(jl_is_datatype(ttypes)); @@ -523,8 +524,8 @@ int jl_typemap_intersection_visitor(jl_typemap_t *map, int offs, if (typetype) { if (is_cache_leaf(typetype)) { // direct lookup of leaf types - jl_typemap_t *ml = mtcache_hash_lookup(&cache->targ, typetype, 1, offs); - if (ml != jl_nothing) { + union jl_typemap_t ml = mtcache_hash_lookup(&cache->targ, typetype, 1, offs); + if (ml.unknown != jl_nothing) { if (!jl_typemap_intersection_visitor(ml, offs+1, closure)) return 0; } } @@ -539,8 +540,8 @@ int jl_typemap_intersection_visitor(jl_typemap_t *map, int offs, if (cache->arg1.values != (void*)jl_nothing) { if (is_cache_leaf(ty)) { // direct lookup of leaf types - jl_typemap_t *ml = mtcache_hash_lookup(&cache->arg1, ty, 0, offs); - if (ml != jl_nothing) { + union jl_typemap_t ml = mtcache_hash_lookup(&cache->arg1, ty, 0, offs); + if (ml.unknown != jl_nothing) { if (!jl_typemap_intersection_visitor(ml, offs+1, closure)) return 0; } } @@ -550,13 +551,12 @@ int jl_typemap_intersection_visitor(jl_typemap_t *map, int offs, } } } - if (!jl_typemap_intersection_node_visitor(cache->linear, closure)) + if (!jl_typemap_intersection_node_visitor(map.node->linear, closure)) return 0; - return jl_typemap_intersection_visitor(cache->any, offs+1, closure); + return jl_typemap_intersection_visitor(map.node->any, offs+1, closure); } else { - return jl_typemap_intersection_node_visitor( - (jl_typemap_entry_t*)map, closure); + return jl_typemap_intersection_node_visitor(map.leaf, closure); } } @@ -667,11 +667,11 @@ static jl_typemap_entry_t *jl_typemap_lookup_by_type_(jl_typemap_entry_t *ml, jl // this is the general entry point for looking up a type in the cache // as a subtype, or with type_equal -jl_typemap_entry_t *jl_typemap_assoc_by_type(jl_typemap_t *ml_or_cache, jl_value_t *types, jl_svec_t **penv, +jl_typemap_entry_t *jl_typemap_assoc_by_type(union jl_typemap_t ml_or_cache, jl_value_t *types, jl_svec_t **penv, int8_t subtype, int8_t offs, size_t world, size_t max_world_mask) { - if (jl_typeof(ml_or_cache) == (jl_value_t *)jl_typemap_level_type) { - jl_typemap_level_t *cache = (jl_typemap_level_t*)ml_or_cache; + if (jl_typeof(ml_or_cache.unknown) == (jl_value_t*)jl_typemap_level_type) { + jl_typemap_level_t *cache = ml_or_cache.node; // called object is the primary key for constructors, otherwise first argument jl_value_t *ty = NULL; jl_value_t *ttypes = jl_unwrap_unionall((jl_value_t*)types); @@ -703,8 +703,8 @@ jl_typemap_entry_t *jl_typemap_assoc_by_type(jl_typemap_t *ml_or_cache, jl_value if (jl_is_type_type(ty)) { jl_value_t *a0 = jl_tparam0(ty); if (cache->targ.values != (void*)jl_nothing && jl_is_datatype(a0)) { - jl_typemap_t *ml = mtcache_hash_lookup(&cache->targ, a0, 1, offs); - if (ml != jl_nothing) { + union jl_typemap_t ml = mtcache_hash_lookup(&cache->targ, a0, 1, offs); + if (ml.unknown != jl_nothing) { jl_typemap_entry_t *li = jl_typemap_assoc_by_type(ml, types, penv, subtype, offs + 1, world, max_world_mask); if (li) return li; @@ -713,8 +713,8 @@ jl_typemap_entry_t *jl_typemap_assoc_by_type(jl_typemap_t *ml_or_cache, jl_value if (!subtype && is_cache_leaf(a0)) return NULL; } if (cache->arg1.values != (void*)jl_nothing && jl_is_datatype(ty)) { - jl_typemap_t *ml = mtcache_hash_lookup(&cache->arg1, ty, 0, offs); - if (ml != jl_nothing) { + union jl_typemap_t ml = mtcache_hash_lookup(&cache->arg1, ty, 0, offs); + if (ml.unknown != jl_nothing) { jl_typemap_entry_t *li = jl_typemap_assoc_by_type(ml, types, penv, subtype, offs + 1, world, max_world_mask); if (li) return li; @@ -733,10 +733,9 @@ jl_typemap_entry_t *jl_typemap_assoc_by_type(jl_typemap_t *ml_or_cache, jl_value } } else { - jl_typemap_entry_t *leaf = (jl_typemap_entry_t*)ml_or_cache; return subtype ? - jl_typemap_assoc_by_type_(leaf, types, penv, world, max_world_mask) : - jl_typemap_lookup_by_type_(leaf, types, world, max_world_mask); + jl_typemap_assoc_by_type_(ml_or_cache.leaf, types, penv, world, max_world_mask) : + jl_typemap_lookup_by_type_(ml_or_cache.leaf, types, world, max_world_mask); } } @@ -825,12 +824,12 @@ jl_typemap_entry_t *jl_typemap_level_assoc_exact(jl_typemap_level_t *cache, jl_v jl_value_t *ty = (jl_value_t*)jl_typeof(a1); assert(jl_is_datatype(ty)); if (ty == (jl_value_t*)jl_datatype_type && cache->targ.values != (void*)jl_nothing) { - jl_typemap_t *ml_or_cache = mtcache_hash_lookup(&cache->targ, a1, 1, offs); + union jl_typemap_t ml_or_cache = mtcache_hash_lookup(&cache->targ, a1, 1, offs); jl_typemap_entry_t *ml = jl_typemap_assoc_exact(ml_or_cache, args, n, offs+1, world); if (ml) return ml; } if (cache->arg1.values != (void*)jl_nothing) { - jl_typemap_t *ml_or_cache = mtcache_hash_lookup(&cache->arg1, ty, 0, offs); + union jl_typemap_t ml_or_cache = mtcache_hash_lookup(&cache->arg1, ty, 0, offs); jl_typemap_entry_t *ml = jl_typemap_assoc_exact(ml_or_cache, args, n, offs+1, world); if (ml) return ml; } @@ -839,7 +838,7 @@ jl_typemap_entry_t *jl_typemap_level_assoc_exact(jl_typemap_level_t *cache, jl_v jl_typemap_entry_t *ml = jl_typemap_entry_assoc_exact(cache->linear, args, n, world); if (ml) return ml; } - if (cache->any != jl_nothing) + if (cache->any.unknown != jl_nothing) return jl_typemap_assoc_exact(cache->any, args, n, offs+1, world); return NULL; } @@ -847,7 +846,7 @@ jl_typemap_entry_t *jl_typemap_level_assoc_exact(jl_typemap_level_t *cache, jl_v // ----- Method List Insertion Management ----- // -static unsigned jl_typemap_list_count(jl_typemap_entry_t *ml) JL_NOTSAFEPOINT +static unsigned jl_typemap_list_count(jl_typemap_entry_t *ml) { unsigned count = 0; while (ml != (void*)jl_nothing) { @@ -869,7 +868,7 @@ static jl_typemap_level_t *jl_new_typemap_level(void) jl_typemap_level_type); cache->key = NULL; cache->linear = (jl_typemap_entry_t*)jl_nothing; - cache->any = jl_nothing; + cache->any.unknown = jl_nothing; cache->targ.indices = (jl_array_t*)jl_nothing; cache->targ.values = (jl_array_t*)jl_nothing; cache->arg1.indices = (jl_array_t*)jl_nothing; @@ -908,34 +907,31 @@ static void jl_typemap_list_insert_(jl_typemap_entry_t **pml, jl_value_t *parent } } -static void jl_typemap_insert_generic(jl_typemap_t **pml, jl_value_t *parent, +static void jl_typemap_insert_generic(union jl_typemap_t *pml, jl_value_t *parent, jl_typemap_entry_t *newrec, jl_value_t *key, int8_t offs, const struct jl_typemap_info *tparams) { - if (jl_typeof(*pml) == (jl_value_t*)jl_typemap_level_type) { - jl_typemap_level_insert_((jl_typemap_level_t*)*pml, newrec, offs, tparams); + if (jl_typeof(pml->unknown) == (jl_value_t*)jl_typemap_level_type) { + jl_typemap_level_insert_(pml->node, newrec, offs, tparams); return; } - unsigned count = jl_typemap_list_count((jl_typemap_entry_t*)*pml); + unsigned count = jl_typemap_list_count(pml->leaf); if (count > MAX_METHLIST_COUNT) { - *pml = (jl_typemap_t*)jl_method_convert_list_to_cache( - (jl_typemap_entry_t *)*pml, - key, offs, tparams); - jl_gc_wb(parent, *pml); - jl_typemap_level_insert_((jl_typemap_level_t*)*pml, newrec, offs, tparams); + pml->node = jl_method_convert_list_to_cache(pml->leaf, key, offs, tparams); + jl_gc_wb(parent, pml->node); + jl_typemap_level_insert_(pml->node, newrec, offs, tparams); return; } - jl_typemap_list_insert_((jl_typemap_entry_t **)pml, - parent, newrec, tparams); + jl_typemap_list_insert_(&pml->leaf, parent, newrec, tparams); } static int jl_typemap_array_insert_(struct jl_ordereddict_t *cache, jl_value_t *key, jl_typemap_entry_t *newrec, jl_value_t *parent, int8_t tparam, int8_t offs, const struct jl_typemap_info *tparams) { - jl_typemap_t **pml = mtcache_hash_bp(cache, key, tparam, offs, (jl_value_t*)parent); + union jl_typemap_t *pml = mtcache_hash_bp(cache, key, tparam, offs, (jl_value_t*)parent); if (pml) jl_typemap_insert_generic(pml, (jl_value_t*)cache->values, newrec, key, offs+1, tparams); return pml != NULL; @@ -983,7 +979,7 @@ static void jl_typemap_level_insert_(jl_typemap_level_t *cache, jl_typemap_entry jl_typemap_list_insert_(&cache->linear, (jl_value_t*)cache, newrec, tparams); } -jl_typemap_entry_t *jl_typemap_insert(jl_typemap_t **cache, jl_value_t *parent, +jl_typemap_entry_t *jl_typemap_insert(union jl_typemap_t *cache, jl_value_t *parent, jl_tupletype_t *type, jl_tupletype_t *simpletype, jl_svec_t *guardsigs, jl_value_t *newvalue, int8_t offs, diff --git a/stdlib/Distributed/src/cluster.jl b/stdlib/Distributed/src/cluster.jl index 49df11b6eef0d..0d1614b7e972a 100644 --- a/stdlib/Distributed/src/cluster.jl +++ b/stdlib/Distributed/src/cluster.jl @@ -644,7 +644,7 @@ end Return the cluster cookie. """ -cluster_cookie() = (init_multi(); LPROC.cookie) +cluster_cookie() = LPROC.cookie """ cluster_cookie(cookie) -> cookie @@ -652,7 +652,6 @@ cluster_cookie() = (init_multi(); LPROC.cookie) Set the passed cookie as the cluster cookie, then returns it. """ function cluster_cookie(cookie) - init_multi() # The cookie must be an ASCII string with length <= HDR_COOKIE_LEN @assert isascii(cookie) @assert length(cookie) <= HDR_COOKIE_LEN diff --git a/stdlib/Distributed/src/macros.jl b/stdlib/Distributed/src/macros.jl index 15faadb3c31fa..f04ad345f10bc 100644 --- a/stdlib/Distributed/src/macros.jl +++ b/stdlib/Distributed/src/macros.jl @@ -251,7 +251,7 @@ end function preduce(reducer, f, R) N = length(R) - chunks = splitrange(Int(N), nworkers()) + chunks = splitrange(N, nworkers()) all_w = workers()[1:length(chunks)] w_exec = Task[] diff --git a/stdlib/Distributed/test/distributed_exec.jl b/stdlib/Distributed/test/distributed_exec.jl index 383a6783a311d..04ef09d495a2d 100644 --- a/stdlib/Distributed/test/distributed_exec.jl +++ b/stdlib/Distributed/test/distributed_exec.jl @@ -3,8 +3,6 @@ using Test, Distributed, Random, Serialization, Sockets import Distributed: launch, manage -@test cluster_cookie() isa String - include(joinpath(Sys.BINDIR, "..", "share", "julia", "test", "testenv.jl")) @test Distributed.extract_imports(:(begin; import Foo, Bar; let; using Baz; end; end)) == @@ -1527,14 +1525,6 @@ end a27933 = :_not_defined_27933 @test remotecall_fetch(()->a27933, first(workers())) === a27933 -# PR #28651 -for T in (UInt8, Int8, UInt16, Int16, UInt32, Int32, UInt64) - n = @distributed (+) for i in Base.OneTo(T(10)) - i - end - @test n == 55 -end - # Run topology tests last after removing all workers, since a given # cluster at any time only supports a single topology. rmprocs(workers()) diff --git a/stdlib/LinearAlgebra/src/LinearAlgebra.jl b/stdlib/LinearAlgebra/src/LinearAlgebra.jl index f84e56883b436..48f5b34ca81f7 100644 --- a/stdlib/LinearAlgebra/src/LinearAlgebra.jl +++ b/stdlib/LinearAlgebra/src/LinearAlgebra.jl @@ -60,6 +60,7 @@ export axpby!, bunchkaufman, bunchkaufman!, + chol, cholesky, cholesky!, cond, @@ -133,6 +134,7 @@ export tr, transpose, transpose!, + transpose_type, tril, triu, tril!, diff --git a/stdlib/LinearAlgebra/src/cholesky.jl b/stdlib/LinearAlgebra/src/cholesky.jl index 5db318fabf999..3e95a92d3a0d4 100644 --- a/stdlib/LinearAlgebra/src/cholesky.jl +++ b/stdlib/LinearAlgebra/src/cholesky.jl @@ -340,11 +340,11 @@ function getproperty(C::Cholesky, d::Symbol) Cuplo = getfield(C, :uplo) info = getfield(C, :info) if d == :U - return UpperTriangular(Cuplo === char_uplo(d) ? Cfactors : copy(Cfactors')) + return UpperTriangular(Symbol(Cuplo) == d ? Cfactors : copy(Cfactors')) elseif d == :L - return LowerTriangular(Cuplo === char_uplo(d) ? Cfactors : copy(Cfactors')) + return LowerTriangular(Symbol(Cuplo) == d ? Cfactors : copy(Cfactors')) elseif d == :UL - return (Cuplo === 'U' ? UpperTriangular(Cfactors) : LowerTriangular(Cfactors)) + return (Symbol(Cuplo) == :U ? UpperTriangular(Cfactors) : LowerTriangular(Cfactors)) else return getfield(C, d) end diff --git a/stdlib/LinearAlgebra/src/diagonal.jl b/stdlib/LinearAlgebra/src/diagonal.jl index 1a5eca3c0ce05..2d2557510cca0 100644 --- a/stdlib/LinearAlgebra/src/diagonal.jl +++ b/stdlib/LinearAlgebra/src/diagonal.jl @@ -277,9 +277,9 @@ mul!(out::AbstractVector, A::Diagonal, in::AbstractVector) = out .= A.diag .* in mul!(out::AbstractVector, A::Adjoint{<:Any,<:Diagonal}, in::AbstractVector) = out .= adjoint.(A.parent.diag) .* in mul!(out::AbstractVector, A::Transpose{<:Any,<:Diagonal}, in::AbstractVector) = out .= transpose.(A.parent.diag) .* in -mul!(out::AbstractMatrix, A::Diagonal, in::StridedMatrix) = out .= A.diag .* in -mul!(out::AbstractMatrix, A::Adjoint{<:Any,<:Diagonal}, in::StridedMatrix) = out .= adjoint.(A.parent.diag) .* in -mul!(out::AbstractMatrix, A::Transpose{<:Any,<:Diagonal}, in::StridedMatrix) = out .= transpose.(A.parent.diag) .* in +mul!(out::AbstractMatrix, A::Diagonal, in::AbstractMatrix) = out .= A.diag .* in +mul!(out::AbstractMatrix, A::Adjoint{<:Any,<:Diagonal}, in::AbstractMatrix) = out .= adjoint.(A.parent.diag) .* in +mul!(out::AbstractMatrix, A::Transpose{<:Any,<:Diagonal}, in::AbstractMatrix) = out .= transpose.(A.parent.diag) .* in # ambiguities with Symmetric/Hermitian # RealHermSymComplex[Sym]/[Herm] only include Number; invariant to [c]transpose diff --git a/stdlib/LinearAlgebra/src/generic.jl b/stdlib/LinearAlgebra/src/generic.jl index ca747db604fc8..ea23e8d51cee7 100644 --- a/stdlib/LinearAlgebra/src/generic.jl +++ b/stdlib/LinearAlgebra/src/generic.jl @@ -1324,8 +1324,8 @@ julia> promote_leaf_eltypes(a) Complex{Float64} ``` """ -promote_leaf_eltypes(x::Union{AbstractArray{T},Tuple{T,Vararg{T}}}) where {T<:Number} = T -promote_leaf_eltypes(x::Union{AbstractArray{T},Tuple{T,Vararg{T}}}) where {T<:NumberArray} = eltype(T) +promote_leaf_eltypes(x::Union{AbstractArray{T},Tuple{Vararg{T}}}) where {T<:Number} = T +promote_leaf_eltypes(x::Union{AbstractArray{T},Tuple{Vararg{T}}}) where {T<:NumberArray} = eltype(T) promote_leaf_eltypes(x::T) where {T} = T promote_leaf_eltypes(x::Union{AbstractArray,Tuple}) = mapreduce(promote_leaf_eltypes, promote_type, x; init=Bool) diff --git a/stdlib/LinearAlgebra/src/uniformscaling.jl b/stdlib/LinearAlgebra/src/uniformscaling.jl index 54db4d8a6b893..57037473f4b29 100644 --- a/stdlib/LinearAlgebra/src/uniformscaling.jl +++ b/stdlib/LinearAlgebra/src/uniformscaling.jl @@ -207,9 +207,10 @@ isapprox(A::AbstractMatrix, J::UniformScaling; kwargs...) = isapprox(J, A; kwarg function copyto!(A::AbstractMatrix, J::UniformScaling) @assert !has_offset_axes(A) + size(A,1)==size(A,2) || throw(DimensionMismatch("a UniformScaling can only be copied to a square matrix")) fill!(A, 0) λ = J.λ - for i = 1:min(size(A,1),size(A,2)) + for i = 1:size(A,1) @inbounds A[i,i] = λ end return A diff --git a/stdlib/LinearAlgebra/test/ambiguous_exec.jl b/stdlib/LinearAlgebra/test/ambiguous_exec.jl deleted file mode 100644 index 6dce4926f4610..0000000000000 --- a/stdlib/LinearAlgebra/test/ambiguous_exec.jl +++ /dev/null @@ -1,4 +0,0 @@ -# This file is a part of Julia. License is MIT: https://julialang.org/license - -using Test, LinearAlgebra -@test detect_ambiguities(LinearAlgebra; imported=true, recursive=true) == [] diff --git a/stdlib/LinearAlgebra/test/matmul.jl b/stdlib/LinearAlgebra/test/matmul.jl index bd1cc3072bc79..7ac8924e63447 100644 --- a/stdlib/LinearAlgebra/test/matmul.jl +++ b/stdlib/LinearAlgebra/test/matmul.jl @@ -445,12 +445,4 @@ end @test Xv1'*Xv3' ≈ XcXc end -@testset "method ambiguity" begin - # Ambiguity test is run inside a clean process. - # https://github.com/JuliaLang/julia/issues/28804 - script = joinpath(@__DIR__, "ambiguous_exec.jl") - cmd = `$(Base.julia_cmd()) --startup-file=no $script` - @test success(pipeline(cmd; stdout=stdout, stderr=stderr)) -end - end # module TestMatmul diff --git a/stdlib/LinearAlgebra/test/uniformscaling.jl b/stdlib/LinearAlgebra/test/uniformscaling.jl index 2e2b33a08250e..52271177a1f96 100644 --- a/stdlib/LinearAlgebra/test/uniformscaling.jl +++ b/stdlib/LinearAlgebra/test/uniformscaling.jl @@ -86,13 +86,6 @@ let @test cond(J) == (λ ≠ zero(λ) ? one(real(λ)) : oftype(real(λ), Inf)) end - @testset "copyto!" begin - A = Matrix{Int}(undef, (3,3)) - @test copyto!(A, I) == one(A) - B = Matrix{ComplexF64}(undef, (1,2)) - @test copyto!(B, J) == [λ zero(λ)] - end - @testset "binary ops with matrices" begin B = bitrand(2, 2) @test B + I == B + Matrix(I, size(B)) diff --git a/stdlib/Pkg/src/Pkg.jl b/stdlib/Pkg/src/Pkg.jl index 940375c94af54..f5e34961758e0 100644 --- a/stdlib/Pkg/src/Pkg.jl +++ b/stdlib/Pkg/src/Pkg.jl @@ -368,9 +368,18 @@ const precompile_script = """ ] activate . $CTRL_C Pkg.add("Test") # adding an stdlib doesn't require internet access - ] add Te\t\t$CTRL_C ] st $CTRL_C rm(tmp; recursive=true)""" +module PrecompileArea + import ..Pkg + using ..Types + using UUIDs + import LibGit2 + import REPL + import SHA + include("precompile.jl") +end + end # module diff --git a/stdlib/Pkg/src/precompile.jl b/stdlib/Pkg/src/precompile.jl new file mode 100644 index 0000000000000..adfebb709a63f --- /dev/null +++ b/stdlib/Pkg/src/precompile.jl @@ -0,0 +1,431 @@ +# This file is a part of Julia. License is MIT: https://julialang.org/license + +precompile(Tuple{Type{Base.Dict{K, V} where V where K}, Array{Base.Pair{A, B} where B where A, 1}}) +precompile(Tuple{Type{Base.Dict{Pkg.Types.VersionRange, Base.Dict{String, Base.UUID}}}}) +precompile(Tuple{Type{Base.Dict{Pkg.Types.VersionRange, Base.Dict{String, Pkg.Types.VersionSpec}}}}) +precompile(Tuple{Type{Base.Dict{String, Any}}, Base.Pair{String, String}}) +precompile(Tuple{Type{Base.Dict{String, Base.UUID}}}) +precompile(Tuple{Type{Base.Dict{String, Pkg.Types.VersionSpec}}}) +precompile(Tuple{Type{Base.Generator{I, F} where F where I}, Type{Base.UUID}, Base.ValueIterator{Base.Dict{String, Any}}}) +precompile(Tuple{Type{Base.Generator{I, F} where F where I}, Type{Base.UUID}, Base.ValueIterator{Base.Dict{String, String}}}) +precompile(Tuple{Type{Base.Generator{I, F} where F where I}, typeof(Base.close), Array{LibGit2.GitAnnotated, 1}}) +precompile(Tuple{Type{Base.Generator{I, F} where F where I}, typeof(Pkg.TOML.is_tabular), Base.ValueIterator{Base.Dict{String, Any}}}) +precompile(Tuple{Type{Base.Generator{I, F} where F where I}, typeof(Pkg.TOML.table2dict), Array{Any, 1}}) +precompile(Tuple{Type{Base.IOContext{IO_t} where IO_t<:IO}, Base.GenericIOBuffer{Array{UInt8, 1}}, Base.TTY}) +precompile(Tuple{Type{Base.Pair{A, B} where B where A}, Base.UUID, Int64}) +precompile(Tuple{Type{Base.Pair{A, B} where B where A}, Base.UUID, Pkg.Types.VersionSpec}) +precompile(Tuple{Type{Base.Pair{A, B} where B where A}, Base.VersionNumber, Base.SHA1}) +precompile(Tuple{Type{Base.Pair{A, B} where B where A}, String, Base.UUID}) +precompile(Tuple{Type{Base.SHA1}, Base.SubString{String}}) +precompile(Tuple{Type{Base.SHA1}, String}) +precompile(Tuple{Type{Char}, Int32}) +precompile(Tuple{Type{NamedTuple{(:by,), T} where T<:Tuple}, Tuple{typeof(Base.identity)}}) +precompile(Tuple{Type{NamedTuple{(:header, :color), T} where T<:Tuple}, Tuple{String, Symbol}}) +precompile(Tuple{Type{NamedTuple{(:indent, :region_active), T} where T<:Tuple}, Tuple{Int64, Bool}}) +precompile(Tuple{Type{NamedTuple{(:indent, :sorted, :by), T} where T<:Tuple}, Tuple{Int64, Bool, typeof(Base.identity)}}) +precompile(Tuple{Type{NamedTuple{(:init,), T} where T<:Tuple}, Tuple{Int64}}) +precompile(Tuple{Type{NamedTuple{(:mode,), T} where T<:Tuple}, Tuple{Symbol}}) +precompile(Tuple{Type{NamedTuple{(:transfer_progress, :credentials), T} where T<:Tuple}, Tuple{Ptr{Nothing}, Ptr{Nothing}}}) +precompile(Tuple{Type{Pkg.Display.DiffEntry}, Base.UUID, String, Pkg.Display.VerInfo, Pkg.Display.VerInfo}) +precompile(Tuple{Type{Pkg.Display.VerInfo}, Base.SHA1, Nothing, Base.VersionNumber, Bool, Nothing}) +precompile(Tuple{Type{Pkg.Display.VerInfo}, Base.SHA1, Nothing, Base.VersionNumber, Bool, Pkg.Types.GitRepo}) +precompile(Tuple{Type{Pkg.Display.VerInfo}, Nothing, Nothing, Nothing, Bool, Nothing}) +precompile(Tuple{Type{Pkg.Display.VerInfo}, Nothing, String, Base.VersionNumber, Bool, Nothing}) +precompile(Tuple{Type{Pkg.Types.EnvCache}, Nothing, Nothing, String, String, Nothing, Base.Dict{String, Any}, Base.Dict{String, Any}, Base.Dict{String, Array{Base.UUID, 1}}, Base.Dict{Base.UUID, Array{String, 1}}, Base.Dict{Base.UUID, Array{String, 1}}}) +precompile(Tuple{Type{Pkg.Types.GitRepo}, String, String, Base.SHA1}) +precompile(Tuple{Type{Pkg.Types.GitRepo}, String, String}) +precompile(Tuple{Type{Pkg.Types.PackageSpec}, Base.SubString{String}, Pkg.Types.VersionSpec}) +precompile(Tuple{Type{Pkg.Types.PackageSpec}, Base.SubString{String}}) +precompile(Tuple{Type{Pkg.Types.PackageSpec}, String, Base.UUID, Pkg.Types.VersionSpec}) +precompile(Tuple{Type{Pkg.Types.PackageSpec}, String}) +precompile(Tuple{Type{Pkg.Types.VersionBound}, Base.SubString{String}}) +precompile(Tuple{Type{Pkg.Types.VersionBound}, Int64, Int64}) +precompile(Tuple{Type{Pkg.Types.VersionBound}, Tuple{Int64, Int64, Int64}}) +precompile(Tuple{Type{Pkg.Types.VersionBound}, Tuple{Int64, Int64}}) +precompile(Tuple{Type{Pkg.Types.VersionBound}, Tuple{UInt32, UInt32}}) +precompile(Tuple{Type{Pkg.Types.VersionBound}, UInt32, UInt32}) +precompile(Tuple{Type{Pkg.Types.VersionRange}, Base.VersionNumber}) +precompile(Tuple{Type{Pkg.Types.VersionSpec}, String}) +precompile(Tuple{Type{REPL.LineEdit.PrefixSearchState}, REPL.Terminals.TTYTerminal, REPL.LineEdit.PrefixHistoryPrompt, String, Base.GenericIOBuffer{Array{UInt8, 1}}}) +precompile(Tuple{Type{REPL.LineEdit.PromptState}, REPL.Terminals.TTYTerminal, REPL.LineEdit.Prompt, Base.GenericIOBuffer{Array{UInt8, 1}}, Symbol, Array{Base.GenericIOBuffer{Array{UInt8, 1}}, 1}, Int64, REPL.LineEdit.InputAreaState, Int64, Base.Threads.TatasLock, Float64}) +precompile(Tuple{Type{REPL.LineEdit.SearchState}, REPL.Terminals.TTYTerminal, REPL.LineEdit.HistoryPrompt, Bool, Base.GenericIOBuffer{Array{UInt8, 1}}, Base.GenericIOBuffer{Array{UInt8, 1}}}) +precompile(Tuple{Type{REPL.REPLHistoryProvider}, Array{String, 1}, Nothing, Int64, Int64, Int64, Base.GenericIOBuffer{Array{UInt8, 1}}, Nothing, Base.Dict{Symbol, Any}, Array{UInt8, 1}}) +precompile(Tuple{Type{REPL.REPLHistoryProvider}, Base.Dict{Symbol, Any}}) +precompile(Tuple{getfield(Base, Symbol("#kw##printstyled")), NamedTuple{(:bold, :color), Tuple{Bool, Symbol}}, typeof(Base.printstyled), Base.TTY, String}) +precompile(Tuple{getfield(Base, Symbol("#kw##sort!")), NamedTuple{(:by,), Tuple{typeof(Base.Unicode.lowercase)}}, typeof(Base.sort!), Array{String, 1}}) +precompile(Tuple{getfield(Base, Symbol("#kw##sort!")), NamedTuple{(:by,), Tuple{typeof(Base.identity)}}, typeof(Base.sort!), Array{String, 1}}) +precompile(Tuple{getfield(Base.Cartesian, Symbol("#@nloops")), LineNumberNode, Module, Int64, Symbol, Expr, Expr, Expr}) +precompile(Tuple{getfield(Core, Symbol("#kw#Type")), NamedTuple{(:header, :color), Tuple{String, Symbol}}, Type{Pkg.GitTools.MiniProgressBar}}) +precompile(Tuple{getfield(Core, Symbol("#kw#Type")), NamedTuple{(:payload, :transfer_progress, :credentials), Tuple{Base.Dict{Symbol, Any}, Ptr{Nothing}, Ptr{Nothing}}}, Type{LibGit2.RemoteCallbacks}}) +precompile(Tuple{getfield(Pkg.API, Symbol("#kw##add_or_develop")), NamedTuple{(:mode,), Tuple{Symbol}}, typeof(Pkg.API.add_or_develop), Pkg.Types.Context, Array{Pkg.Types.PackageSpec, 1}}) +precompile(Tuple{getfield(Pkg.TOML, Symbol("#kw##_print")), NamedTuple{(:indent, :sorted, :by), Tuple{Int64, Bool, typeof(Base.identity)}}, typeof(Pkg.TOML._print), Base.IOStream, Base.Dict{String, Any}, Array{String, 1}}) +precompile(Tuple{getfield(Pkg.TOML, Symbol("#kw##print")), NamedTuple{(:sorted,), Tuple{Bool}}, typeof(Pkg.TOML.print), Base.IOStream, Base.Dict{String, Any}}) +precompile(Tuple{getfield(Pkg.TOML, Symbol("#kw##printvalue")), NamedTuple{(:sorted,), Tuple{Bool}}, typeof(Pkg.TOML.printvalue), Base.IOStream, Array{String, 1}}) +precompile(Tuple{getfield(Pkg.TOML, Symbol("#kw##printvalue")), NamedTuple{(:sorted,), Tuple{Bool}}, typeof(Pkg.TOML.printvalue), Base.IOStream, String}) +precompile(Tuple{getfield(REPL.LineEdit, Symbol("#kw##add_nested_key!")), NamedTuple{(:override,), Tuple{Bool}}, typeof(REPL.LineEdit.add_nested_key!), Base.Dict{Char, Any}, String, Nothing}) +precompile(Tuple{getfield(REPL.LineEdit, Symbol("#kw##refresh_multi_line")), NamedTuple{(:indent, :region_active), Tuple{Int64, Bool}}, typeof(REPL.LineEdit.refresh_multi_line), REPL.Terminals.TerminalBuffer, REPL.Terminals.TTYTerminal, Base.GenericIOBuffer{Array{UInt8, 1}}, REPL.LineEdit.InputAreaState, REPL.LineEdit.PromptState}) +precompile(Tuple{typeof(Base.:(!=)), Base.SubString{String}, Nothing}) +precompile(Tuple{typeof(Base.:(!=)), Base.UUID, Base.UUID}) +precompile(Tuple{typeof(Base.:(==)), Base.Dict{String, Any}, Nothing}) +precompile(Tuple{typeof(Base.:(==)), Base.SHA1, Nothing}) +precompile(Tuple{typeof(Base.:(==)), Base.UUID, Base.UUID}) +precompile(Tuple{typeof(Base.:(==)), Expr, Int64}) +precompile(Tuple{typeof(Base.:(==)), Nothing, Base.UUID}) +precompile(Tuple{typeof(Base.:(==)), Nothing, Nothing}) +precompile(Tuple{typeof(Base.:(==)), String, Nothing}) +precompile(Tuple{typeof(Base.:(==)), Symbol, Int64}) +precompile(Tuple{typeof(Base.Cartesian._nloops), Int64, Symbol, Expr, Expr, Expr}) +precompile(Tuple{typeof(Base.Cartesian.exprresolve), LineNumberNode}) +precompile(Tuple{typeof(Base.Cartesian.lreplace!), Int64, Base.Cartesian.LReplace{String}}) +precompile(Tuple{typeof(Base.Filesystem.ispath), String}) +precompile(Tuple{typeof(Base.Filesystem.mtime), String}) +precompile(Tuple{typeof(Base.Iterators.enumerate), Array{Base.VersionNumber, 1}}) +precompile(Tuple{typeof(Base._array_for), Type{Array{Base.BitArray{2}, 1}}, Base.UnitRange{Int64}, Base.HasShape{1}}) +precompile(Tuple{typeof(Base._array_for), Type{Array{Base.VersionNumber, 1}}, Base.UnitRange{Int64}, Base.HasShape{1}}) +precompile(Tuple{typeof(Base._array_for), Type{Base.BitArray{1}}, Base.UnitRange{Int64}, Base.HasShape{1}}) +precompile(Tuple{typeof(Base._array_for), Type{Base.BitArray{2}}, Base.UnitRange{Int64}, Base.HasShape{1}}) +precompile(Tuple{typeof(Base._array_for), Type{Base.Dict{Base.VersionNumber, Int64}}, Base.UnitRange{Int64}, Base.HasShape{1}}) +precompile(Tuple{typeof(Base._array_for), Type{Base.UUID}, Base.ValueIterator{Base.Dict{String, Any}}, Base.HasLength}) +precompile(Tuple{typeof(Base._collect), Array{Pkg.REPLMode.Statement, 1}, Base.Generator{Array{Pkg.REPLMode.Statement, 1}, Type{Pkg.REPLMode.PkgCommand}}, Base.EltypeUnknown, Base.HasShape{1}}) +precompile(Tuple{typeof(Base._compute_eltype), Type{Tuple{Array{String, 1}, LibGit2.CachedCredentials}}}) +precompile(Tuple{typeof(Base._compute_eltype), Type{Tuple{Bool, LibGit2.CachedCredentials}}}) +precompile(Tuple{typeof(Base._compute_eltype), Type{Tuple{Int32, Base.Cstring, Ptr{Nothing}}}}) +precompile(Tuple{typeof(Base._deepcopy_array_t), Array{Base.Dict{String, Any}, 1}, Type{Base.Dict{String, Any}}, Base.IdDict{Any, Any}}) +precompile(Tuple{typeof(Base._getindex), Base.IndexLinear, Base.BitArray{2}, Base.LogicalIndex{Int64, Base.BitArray{1}}, Int64}) +precompile(Tuple{typeof(Base._iterate), Base.Dict{String, Any}, Int64}) +precompile(Tuple{typeof(Base._promote_typejoin), Type{Any}, Type{Ptr{Nothing}}}) +precompile(Tuple{typeof(Base._promote_typejoin), Type{Array{String, 1}}, Type{LibGit2.CachedCredentials}}) +precompile(Tuple{typeof(Base._promote_typejoin), Type{Bool}, Type{LibGit2.CachedCredentials}}) +precompile(Tuple{typeof(Base._promote_typejoin), Type{Int32}, Type{Base.Cstring}}) +precompile(Tuple{typeof(Base._promote_typejoin), Type{Union{}}, Type{Array{String, 1}}}) +precompile(Tuple{typeof(Base._promote_typejoin), Type{Union{}}, Type{Bool}}) +precompile(Tuple{typeof(Base._promote_typejoin), Type{Union{}}, Type{Int32}}) +precompile(Tuple{typeof(Base._shrink), typeof(Base.setdiff!), Array{Base.UUID, 1}, Tuple{Array{Base.UUID, 1}}}) +precompile(Tuple{typeof(Base.add_sum), Int64, Int64}) +precompile(Tuple{typeof(Base.afoldl), typeof(Base.:(+)), Int64, Int64, Int64}) +precompile(Tuple{typeof(Base.all), Base.Generator{Base.ValueIterator{Base.Dict{String, Any}}, typeof(Pkg.TOML.is_tabular)}}) +precompile(Tuple{typeof(Base.close), Base.Channel{Any}}) +precompile(Tuple{typeof(Base.close), LibGit2.GitAnnotated}) +precompile(Tuple{typeof(Base.close), LibGit2.GitConfig}) +precompile(Tuple{typeof(Base.close), LibGit2.GitDiff}) +precompile(Tuple{typeof(Base.close), LibGit2.GitReference}) +precompile(Tuple{typeof(Base.close), LibGit2.GitRemote}) +precompile(Tuple{typeof(Base.close), LibGit2.GitRepo}) +precompile(Tuple{typeof(Base.close), LibGit2.GitTree}) +precompile(Tuple{typeof(Base.cmd_gen), Tuple{Tuple{Base.Cmd}}}) +precompile(Tuple{typeof(Base.collect), Base.Generator{Array{Any, 1}, typeof(Pkg.TOML.table2dict)}}) +precompile(Tuple{typeof(Base.collect), Base.Generator{Base.ValueIterator{Base.Dict{String, Any}}, Type{Base.UUID}}}) +precompile(Tuple{typeof(Base.collect), Base.Generator{Base.ValueIterator{Base.Dict{String, String}}, Type{Base.UUID}}}) +precompile(Tuple{typeof(Base.collect), Base.KeySet{String, Base.Dict{String, Any}}}) +precompile(Tuple{typeof(Base.collect_similar), Array{LibGit2.GitAnnotated, 1}, Base.Generator{Array{LibGit2.GitAnnotated, 1}, typeof(Base.close)}}) +precompile(Tuple{typeof(Base.collect_to_with_first!), Array{Base.UUID, 1}, Base.UUID, Base.Generator{Base.ValueIterator{Base.Dict{String, Any}}, Type{Base.UUID}}, Int64}) +precompile(Tuple{typeof(Base.collect_to_with_first!), Array{String, 1}, String, Base.Generator{Array{String, 1}, typeof(Pkg.REPLMode.word2token)}, Int64}) +precompile(Tuple{typeof(Base.convert), Type{Array{Array{Base.BitArray{2}, 1}, 1}}, Array{Array{Base.BitArray{2}, 1}, 1}}) +precompile(Tuple{typeof(Base.convert), Type{Array{Array{Base.VersionNumber, 1}, 1}}, Array{Array{Base.VersionNumber, 1}, 1}}) +precompile(Tuple{typeof(Base.convert), Type{Array{Array{Int64, 1}, 1}}, Array{Array{Int64, 1}, 1}}) +precompile(Tuple{typeof(Base.convert), Type{Array{Base.BitArray{1}, 1}}, Array{Base.BitArray{1}, 1}}) +precompile(Tuple{typeof(Base.convert), Type{Array{Base.Dict{Base.VersionNumber, Int64}, 1}}, Array{Base.Dict{Base.VersionNumber, Int64}, 1}}) +precompile(Tuple{typeof(Base.convert), Type{Array{Base.UUID, 1}}, Array{Base.UUID, 1}}) +precompile(Tuple{typeof(Base.convert), Type{Array{Char, 1}}, Array{Char, 1}}) +precompile(Tuple{typeof(Base.convert), Type{Array{Int64, 1}}, Array{Int64, 1}}) +precompile(Tuple{typeof(Base.convert), Type{Array{Symbol, 1}}, Array{UInt8, 1}}) +precompile(Tuple{typeof(Base.convert), Type{Array{Union{Pkg.Types.VersionRange, String, Pkg.REPLMode.Rev}, 1}}, Array{String, 1}}) +precompile(Tuple{typeof(Base.convert), Type{Base.Dict{Base.UUID, Int64}}, Base.Dict{Base.UUID, Int64}}) +precompile(Tuple{typeof(Base.convert), Type{Base.Dict{Base.UUID, Pkg.GraphType.ResolveLogEntry}}, Base.Dict{Base.UUID, Pkg.GraphType.ResolveLogEntry}}) +precompile(Tuple{typeof(Base.convert), Type{Base.Dict{K, V} where V where K}, Base.Dict{Symbol, Any}}) +precompile(Tuple{typeof(Base.convert), Type{Base.Dict{Symbol, Any}}, Base.Dict{Any, Any}}) +precompile(Tuple{typeof(Base.convert), Type{Base.UUID}, Base.UUID}) +precompile(Tuple{typeof(Base.convert), Type{REPL.LineEdit.TextInterface}, REPL.LineEdit.Prompt}) +precompile(Tuple{typeof(Base.convert), Type{REPL.Terminals.AbstractTerminal}, REPL.Terminals.TTYTerminal}) +precompile(Tuple{typeof(Base.convert), Type{REPL.Terminals.TextTerminal}, REPL.Terminals.TTYTerminal}) +precompile(Tuple{typeof(Base.convert), Type{Union{Nothing, IO}}, Base.IOStream}) +precompile(Tuple{typeof(Base.convert), Type{Union{Nothing, IO}}, Nothing}) +precompile(Tuple{typeof(Base.convert), Type{Union{Nothing, REPL.LineEdit.Prompt}}, Nothing}) +precompile(Tuple{typeof(Base.convert), Type{Union{Pkg.Types.UpgradeLevel, Base.VersionNumber, Pkg.Types.VersionSpec}}, Base.VersionNumber}) +precompile(Tuple{typeof(Base.copy_chunks!), Array{UInt64, 1}, Int64, Array{UInt64, 1}, Int64, Int64}) +precompile(Tuple{typeof(Base.count), Base.BitArray{1}}) +precompile(Tuple{typeof(Base.deepcopy), Base.Dict{String, Any}}) +precompile(Tuple{typeof(Base.deepcopy_internal), Array{Base.Dict{String, Any}, 1}, Base.IdDict{Any, Any}}) +precompile(Tuple{typeof(Base.deepcopy_internal), Base.Dict{Any, Any}, Base.IdDict{Any, Any}}) +precompile(Tuple{typeof(Base.deepcopy_internal), Base.Dict{String, Any}, Base.IdDict{Any, Any}}) +precompile(Tuple{typeof(Base.deepcopy_internal), Base.Dict{String, String}, Base.IdDict{Any, Any}}) +precompile(Tuple{typeof(Base.deepcopy_internal), String, Base.IdDict{Any, Any}}) +precompile(Tuple{typeof(Base.delete!), Base.Dict{String, Any}, String}) +precompile(Tuple{typeof(Base.delete!), Base.IdDict{Any, Any}, Symbol}) +precompile(Tuple{typeof(Base.empty), Base.Dict{Any, Any}, Type{Base.UUID}, Type{Int64}}) +precompile(Tuple{typeof(Base.empty), Base.Dict{Any, Any}, Type{String}, Type{Base.UUID}}) +precompile(Tuple{typeof(Base.empty), Base.Dict{Any, Any}, Type{String}, Type{String}}) +precompile(Tuple{typeof(Base.eof), Base.IOStream}) +precompile(Tuple{typeof(Base.get!), Base.Dict{Base.UUID, Array{String, 1}}, Base.UUID, Array{String, 1}}) +precompile(Tuple{typeof(Base.get!), Base.Dict{Pkg.Types.VersionRange, Base.Dict{String, Base.UUID}}, Pkg.Types.VersionRange, Base.Dict{String, Base.UUID}}) +precompile(Tuple{typeof(Base.get!), Base.Dict{Pkg.Types.VersionRange, Base.Dict{String, Pkg.Types.VersionSpec}}, Pkg.Types.VersionRange, Base.Dict{String, Pkg.Types.VersionSpec}}) +precompile(Tuple{typeof(Base.get!), Base.Dict{String, Any}, String, Array{Base.Dict{String, Any}, 1}}) +precompile(Tuple{typeof(Base.get!), Base.Dict{String, Array{Base.UUID, 1}}, String, Array{Base.UUID, 1}}) +precompile(Tuple{typeof(Base.get), Base.Dict{String, Any}, String, Base.Dict{Any, Any}}) +precompile(Tuple{typeof(Base.get), Base.Dict{String, Pkg.REPLMode.CommandSpec}, String, Nothing}) +precompile(Tuple{typeof(Base.getindex), Array{Array{Base.VersionNumber, 1}, 1}, Int64}) +precompile(Tuple{typeof(Base.getindex), Array{Array{Int64, 1}, 1}, Int64}) +precompile(Tuple{typeof(Base.getindex), Array{Array{UInt64, 1}, 1}, Int64}) +precompile(Tuple{typeof(Base.getindex), Array{Base.BitArray{1}, 1}, Int64}) +precompile(Tuple{typeof(Base.getindex), Array{Base.BitArray{2}, 1}, Int64}) +precompile(Tuple{typeof(Base.getindex), Array{Base.Dict{Int64, Int64}, 1}, Int64}) +precompile(Tuple{typeof(Base.getindex), Array{Base.Dict{String, Any}, 1}, Int64}) +precompile(Tuple{typeof(Base.getindex), Array{Base.UUID, 1}, Int64}) +precompile(Tuple{typeof(Base.getindex), Array{Base.VersionNumber, 1}, Base.BitArray{1}}) +precompile(Tuple{typeof(Base.getindex), Array{Int64, 1}, Int64}) +precompile(Tuple{typeof(Base.getindex), Base.BitArray{1}, Base.UnitRange{Int64}}) +precompile(Tuple{typeof(Base.getindex), Base.BitArray{2}, Base.BitArray{1}, Base.BitArray{1}}) +precompile(Tuple{typeof(Base.getindex), Base.Dict{Int64, Int64}, Int64}) +precompile(Tuple{typeof(Base.getindex), Base.Dict{String, Base.UUID}, String}) +precompile(Tuple{typeof(Base.getindex), Base.Dict{Symbol, Function}, Symbol}) +precompile(Tuple{typeof(Base.getindex), NamedTuple{(:indent, :region_active), Tuple{Int64, Bool}}, Symbol}) +precompile(Tuple{typeof(Base.getindex), NamedTuple{(:prompt_prefix, :prompt_suffix, :complete, :sticky), Tuple{String, String, Pkg.REPLMode.PkgCompletionProvider, Bool}}, Symbol}) +precompile(Tuple{typeof(Base.getindex), NamedTuple{(:prompt_prefix, :prompt_suffix, :repl, :complete, :on_enter), Tuple{String, typeof(Base.input_color), REPL.LineEditREPL, REPL.REPLCompletionProvider, typeof(REPL.return_callback)}}, Symbol}) +precompile(Tuple{typeof(Base.getindex), Pkg.TOML.Table, String}) +precompile(Tuple{typeof(Base.getindex), Type{Pkg.Types.VersionRange}, Pkg.Pkg2.Pkg2Types.VersionInterval}) +precompile(Tuple{typeof(Base.getproperty), Pkg.TOML.Table, Symbol}) +precompile(Tuple{typeof(Base.getproperty), Pkg.Types.PackageSpec, Symbol}) +precompile(Tuple{typeof(Base.getproperty), REPL.Terminals.TerminalBuffer, Symbol}) +precompile(Tuple{typeof(Base.hash), Tuple{String, UInt64}, UInt64}) +precompile(Tuple{typeof(Base.hash), Tuple{String}, UInt64}) +precompile(Tuple{typeof(Base.haskey), Base.Dict{Base.UUID, Base.Dict{K, V} where V where K}, Base.UUID}) +precompile(Tuple{typeof(Base.haskey), Base.Dict{String, Base.UUID}, String}) +precompile(Tuple{typeof(Base.haskey), Base.Dict{String, Pkg.Types.VersionSpec}, String}) +precompile(Tuple{typeof(Base.haskey), NamedTuple{(:indent, :region_active), Tuple{Int64, Bool}}, Symbol}) +precompile(Tuple{typeof(Base.haskey), NamedTuple{(:prompt_prefix, :prompt_suffix, :complete, :sticky), Tuple{String, String, Pkg.REPLMode.PkgCompletionProvider, Bool}}, Symbol}) +precompile(Tuple{typeof(Base.haskey), NamedTuple{(:prompt_prefix, :prompt_suffix, :repl, :complete, :on_enter), Tuple{String, typeof(Base.input_color), REPL.LineEditREPL, REPL.REPLCompletionProvider, typeof(REPL.return_callback)}}, Symbol}) +precompile(Tuple{typeof(Base.haskey), Pkg.TOML.Table, String}) +precompile(Tuple{typeof(Base.ident_cmp), Tuple{String, UInt64}, Tuple{String, UInt64}}) +precompile(Tuple{typeof(Base.ident_cmp), Tuple{String}, Tuple{String}}) +precompile(Tuple{typeof(Base.ident_cmp), Tuple{}, Tuple{}}) +precompile(Tuple{typeof(Base.identity), Int64}) +precompile(Tuple{typeof(Base.in), Base.UUID, Array{Base.UUID, 1}}) +precompile(Tuple{typeof(Base.in), Base.VersionNumber, Pkg.Types.VersionSpec}) +precompile(Tuple{typeof(Base.in), String, Array{String, 1}}) +precompile(Tuple{typeof(Base.in), String, Base.KeySet{String, Base.Dict{String, Any}}}) +precompile(Tuple{typeof(Base.in), String, Base.KeySet{String, Base.Dict{String, Base.Dict{String, Pkg.REPLMode.CommandSpec}}}}) +precompile(Tuple{typeof(Base.indexed_iterate), Base.Pair{Any, Any}, Int64, Int64}) +precompile(Tuple{typeof(Base.indexed_iterate), Base.Pair{Any, Any}, Int64}) +precompile(Tuple{typeof(Base.indexed_iterate), Base.Pair{String, Any}, Int64, Int64}) +precompile(Tuple{typeof(Base.indexed_iterate), Base.Pair{String, Any}, Int64}) +precompile(Tuple{typeof(Base.indexed_iterate), Tuple{Char, Bool}, Int64, Int64}) +precompile(Tuple{typeof(Base.indexed_iterate), Tuple{Char, Bool}, Int64}) +precompile(Tuple{typeof(Base.indexed_iterate), Tuple{String, Array{String, 1}, Array{String, 1}}, Int64, Int64}) +precompile(Tuple{typeof(Base.indexed_iterate), Tuple{String, Array{String, 1}, Array{String, 1}}, Int64}) +precompile(Tuple{typeof(Base.input_color)}) +precompile(Tuple{typeof(Base.invokelatest), typeof(Pkg.REPLMode.do_status!), Base.Dict{Symbol, Any}, Array{String, 1}, Base.Dict{Symbol, Any}}) +precompile(Tuple{typeof(Base.isempty), Array{Base.Dict{String, Any}, 1}}) +precompile(Tuple{typeof(Base.isempty), Array{Base.UUID, 1}}) +precompile(Tuple{typeof(Base.isempty), Base.Dict{String, Any}}) +precompile(Tuple{typeof(Base.isempty), Base.Dict{String, String}}) +precompile(Tuple{typeof(Base.isempty), NamedTuple{(:mode,), Tuple{Symbol}}}) +precompile(Tuple{typeof(Base.isopen), Base.Channel{Any}}) +precompile(Tuple{typeof(Base.iterate), Array{Base.Dict{String, Any}, 1}, Int64}) +precompile(Tuple{typeof(Base.iterate), Array{Base.Dict{String, Any}, 1}}) +precompile(Tuple{typeof(Base.iterate), Array{Base.UUID, 1}, Int64}) +precompile(Tuple{typeof(Base.iterate), Array{Base.UUID, 1}}) +precompile(Tuple{typeof(Base.iterate), Base.Channel{Any}}) +precompile(Tuple{typeof(Base.iterate), Base.Dict{Any, Any}, Int64}) +precompile(Tuple{typeof(Base.iterate), Base.Dict{Any, Any}}) +precompile(Tuple{typeof(Base.iterate), Base.Dict{String, Any}, Int64}) +precompile(Tuple{typeof(Base.iterate), Base.Dict{String, Any}}) +precompile(Tuple{typeof(Base.iterate), Tuple{Base.BitArray{1}}, Int64}) +precompile(Tuple{typeof(Base.iterate), Tuple{Base.BitArray{1}}}) +precompile(Tuple{typeof(Base.join), Base.GenericIOBuffer{Array{UInt8, 1}}, Tuple{String}, Char}) +precompile(Tuple{typeof(Base.join), Base.GenericIOBuffer{Array{UInt8, 1}}, Tuple{Symbol, Symbol}, String}) +precompile(Tuple{typeof(Base.join), Base.GenericIOBuffer{Array{UInt8, 1}}, Tuple{UInt32, UInt32, UInt32}, Char}) +precompile(Tuple{typeof(Base.join), Base.GenericIOBuffer{Array{UInt8, 1}}, Tuple{UInt32, UInt32}, Char}) +precompile(Tuple{typeof(Base.join), Tuple{Symbol, Symbol}, String}) +precompile(Tuple{typeof(Base.keys), Base.Dict{String, Any}}) +precompile(Tuple{typeof(Base.keys), Base.Dict{String, Base.Dict{String, Pkg.REPLMode.CommandSpec}}}) +precompile(Tuple{typeof(Base.lastindex), Base.BitArray{1}}) +precompile(Tuple{typeof(Base.length), Array{Array{Base.BitArray{2}, 1}, 1}}) +precompile(Tuple{typeof(Base.length), Array{Array{Base.VersionNumber, 1}, 1}}) +precompile(Tuple{typeof(Base.length), Array{Array{Int64, 1}, 1}}) +precompile(Tuple{typeof(Base.length), Array{Base.BitArray{1}, 1}}) +precompile(Tuple{typeof(Base.length), Array{Base.Dict{Base.VersionNumber, Int64}, 1}}) +precompile(Tuple{typeof(Base.length), Array{Base.Dict{Int64, Int64}, 1}}) +precompile(Tuple{typeof(Base.length), Array{Base.Dict{String, Any}, 1}}) +precompile(Tuple{typeof(Base.length), Array{Base.UUID, 1}}) +precompile(Tuple{typeof(Base.length), Array{Int64, 1}}) +precompile(Tuple{typeof(Base.length), Base.BitArray{1}}) +precompile(Tuple{typeof(Base.length), Base.Dict{Base.UUID, Int64}}) +precompile(Tuple{typeof(Base.length), Base.Dict{Base.UUID, Pkg.GraphType.ResolveLogEntry}}) +precompile(Tuple{typeof(Base.length), Base.Dict{String, Any}}) +precompile(Tuple{typeof(Base.map), Type{Base.UUID}, Base.ValueIterator{Base.Dict{String, Any}}}) +precompile(Tuple{typeof(Base.map), Type{Base.UUID}, Base.ValueIterator{Base.Dict{String, String}}}) +precompile(Tuple{typeof(Base.map), typeof(Base.close), Array{LibGit2.GitAnnotated, 1}}) +precompile(Tuple{typeof(Base.mapreduce_first), typeof(Base.identity), typeof(Base.add_sum), Int64}) +precompile(Tuple{typeof(Base.match), Base.Regex, String}) +precompile(Tuple{typeof(Base.merge!), Base.Dict{String, Any}, Base.Dict{String, Any}}) +precompile(Tuple{typeof(Base.merge), Base.Dict{String, Any}, Base.Dict{String, String}}) +precompile(Tuple{typeof(Base.merge), NamedTuple{(), Tuple{}}, Base.Iterators.Pairs{Union{}, Union{}, Tuple{}, NamedTuple{(), Tuple{}}}}) +precompile(Tuple{typeof(Base.merge), NamedTuple{(), Tuple{}}, NamedTuple{(:mode,), Tuple{Symbol}}}) +precompile(Tuple{typeof(Base.merge), NamedTuple{(:payload,), Tuple{Base.Dict{Symbol, Any}}}, NamedTuple{(:transfer_progress, :credentials), Tuple{Ptr{Nothing}, Ptr{Nothing}}}}) +precompile(Tuple{typeof(Base.merge_names), Tuple{Symbol, Symbol, Symbol}, Tuple{Symbol}}) +precompile(Tuple{typeof(Base.merge_names), Tuple{Symbol, Symbol}, Tuple{Symbol, Symbol}}) +precompile(Tuple{typeof(Base.merge_names), Tuple{Symbol, Symbol}, Tuple{Symbol}}) +precompile(Tuple{typeof(Base.merge_names), Tuple{Symbol}, Tuple{Symbol, Symbol}}) +precompile(Tuple{typeof(Base.merge_names), Tuple{Symbol}, Tuple{Symbol}}) +precompile(Tuple{typeof(Base.merge_names), Tuple{Symbol}, Tuple{}}) +precompile(Tuple{typeof(Base.notify_error), Base.Channel{Any}, Base.InvalidStateException}) +precompile(Tuple{typeof(Base.peek), Base.IOStream}) +precompile(Tuple{typeof(Base.prepend!), Array{Base.Dict{Any, Any}, 1}, Array{Base.Dict{Any, Any}, 1}}) +precompile(Tuple{typeof(Base.print), Base.GenericIOBuffer{Array{UInt8, 1}}, Base.SubString{String}}) +precompile(Tuple{typeof(Base.print), Base.GenericIOBuffer{Array{UInt8, 1}}, Pkg.Types.VersionSpec}) +precompile(Tuple{typeof(Base.print), Base.IOStream, String, String, String, Char}) +precompile(Tuple{typeof(Base.print), Base.TTY, String, String, Char}) +precompile(Tuple{typeof(Base.promote_eltype), Base.KeySet{Base.UUID, Base.Dict{Base.UUID, Pkg.Types.VersionSpec}}}) +precompile(Tuple{typeof(Base.push!), Array{Base.UUID, 1}, Base.UUID}) +precompile(Tuple{typeof(Base.push!), Array{Int64, 1}, Int64}) +precompile(Tuple{typeof(Base.push!), Array{Pkg.Types.VersionRange, 1}, Pkg.Types.VersionRange}) +precompile(Tuple{typeof(Base.push!), Array{Tuple{Base.UUID, String}, 1}, Tuple{Base.UUID, String}}) +precompile(Tuple{typeof(Base.push!), Base.Set{Base.VersionNumber}, Base.VersionNumber}) +precompile(Tuple{typeof(Base.push!), Base.Set{Symbol}, Symbol}) +precompile(Tuple{typeof(Base.push!), Pkg.GraphType.ResolveLogEntry, Tuple{Nothing, String}}) +precompile(Tuple{typeof(Base.push!), Pkg.GraphType.ResolveLogEntry, Tuple{Pkg.GraphType.ResolveLogEntry, String}}) +precompile(Tuple{typeof(Base.put!), Base.Channel{Any}, Tuple{String, Array{String, 1}, Array{String, 1}}}) +precompile(Tuple{typeof(Base.rethrow), Base.InvalidStateException}) +precompile(Tuple{typeof(Base.rstrip), String}) +precompile(Tuple{typeof(Base.seek), Base.IOStream, Int64}) +precompile(Tuple{typeof(Base.setdiff!), Base.Set{Base.UUID}, Array{Base.UUID, 1}}) +precompile(Tuple{typeof(Base.setindex!), Array{Base.BitArray{1}, 1}, Base.BitArray{1}, Int64}) +precompile(Tuple{typeof(Base.setindex!), Base.BitArray{1}, Bool, Int64}) +precompile(Tuple{typeof(Base.setindex!), Base.Dict{Base.UUID, Base.Dict{K, V} where V where K}, Base.Dict{String, Any}, Base.UUID}) +precompile(Tuple{typeof(Base.setindex!), Base.Dict{Base.UUID, Int64}, Int64, Base.UUID}) +precompile(Tuple{typeof(Base.setindex!), Base.Dict{Base.UUID, Pkg.Types.VersionSpec}, Pkg.Types.VersionSpec, Base.UUID}) +precompile(Tuple{typeof(Base.setindex!), Base.Dict{Base.UUID, String}, String, Base.UUID}) +precompile(Tuple{typeof(Base.setindex!), Base.Dict{Base.VersionNumber, Base.SHA1}, Base.SHA1, Base.VersionNumber}) +precompile(Tuple{typeof(Base.setindex!), Base.Dict{Int64, Int64}, Int64, Int64}) +precompile(Tuple{typeof(Base.setindex!), Base.Dict{String, Any}, Array{Any, 1}, String}) +precompile(Tuple{typeof(Base.setindex!), Base.Dict{String, Any}, Array{Base.Dict{String, Any}, 1}, String}) +precompile(Tuple{typeof(Base.setindex!), Base.Dict{String, Any}, Array{String, 1}, String}) +precompile(Tuple{typeof(Base.setindex!), Base.Dict{String, Any}, Base.Dict{Any, Any}, String}) +precompile(Tuple{typeof(Base.setindex!), Base.Dict{String, Any}, Base.Dict{String, String}, String}) +precompile(Tuple{typeof(Base.setindex!), Base.Dict{String, Any}, Base.UUID, String}) +precompile(Tuple{typeof(Base.setindex!), Base.Dict{String, Base.UUID}, Base.UUID, String}) +precompile(Tuple{typeof(Base.setindex!), Base.Dict{String, Pkg.Types.VersionSpec}, Pkg.Types.VersionSpec, String}) +precompile(Tuple{typeof(Base.setindex!), Base.Dict{Symbol, Any}, LibGit2.CredentialPayload, Symbol}) +precompile(Tuple{typeof(Base.setindex!), Base.Dict{Symbol, Any}, Pkg.GitTools.MiniProgressBar, Symbol}) +precompile(Tuple{typeof(Base.setindex!), Base.EnvDict, String, String}) +precompile(Tuple{typeof(Base.setproperty!), Pkg.GraphType.Graph, Symbol, Array{Array{Base.BitArray{2}, 1}, 1}}) +precompile(Tuple{typeof(Base.setproperty!), Pkg.GraphType.Graph, Symbol, Array{Array{Int64, 1}, 1}}) +precompile(Tuple{typeof(Base.setproperty!), Pkg.GraphType.Graph, Symbol, Array{Base.BitArray{1}, 1}}) +precompile(Tuple{typeof(Base.setproperty!), Pkg.GraphType.Graph, Symbol, Array{Int64, 1}}) +precompile(Tuple{typeof(Base.setproperty!), Pkg.GraphType.GraphData, Symbol, Array{Array{Base.VersionNumber, 1}, 1}}) +precompile(Tuple{typeof(Base.setproperty!), Pkg.GraphType.GraphData, Symbol, Array{Base.Dict{Base.VersionNumber, Int64}, 1}}) +precompile(Tuple{typeof(Base.setproperty!), Pkg.GraphType.GraphData, Symbol, Array{Base.UUID, 1}}) +precompile(Tuple{typeof(Base.setproperty!), Pkg.GraphType.GraphData, Symbol, Array{Int64, 1}}) +precompile(Tuple{typeof(Base.setproperty!), Pkg.GraphType.GraphData, Symbol, Base.Dict{Base.UUID, Int64}}) +precompile(Tuple{typeof(Base.setproperty!), Pkg.GraphType.ResolveLog, Symbol, Base.Dict{Base.UUID, Pkg.GraphType.ResolveLogEntry}}) +precompile(Tuple{typeof(Base.setproperty!), Pkg.REPLMode.Statement, Symbol, Pkg.REPLMode.CommandSpec}) +precompile(Tuple{typeof(Base.setproperty!), Pkg.Types.PackageSpec, Symbol, Base.UUID}) +precompile(Tuple{typeof(Base.setproperty!), Pkg.Types.PackageSpec, Symbol, Base.VersionNumber}) +precompile(Tuple{typeof(Base.setproperty!), Pkg.Types.PackageSpec, Symbol, String}) +precompile(Tuple{typeof(Base.similar), Array{Base.Dict{String, Any}, 1}}) +precompile(Tuple{typeof(Base.skip_deleted_floor!), Base.Dict{String, Any}}) +precompile(Tuple{typeof(Base.string), String, Base.SubString{String}, String, String}) +precompile(Tuple{typeof(Base.string), Symbol, Int64}) +precompile(Tuple{typeof(Base.strip), Base.SubString{String}}) +precompile(Tuple{typeof(Base.structdiff), NamedTuple{(:indent, :region_active), Tuple{Int64, Bool}}, Type{NamedTuple{(:indent, :region_active), T} where T<:Tuple}}) +precompile(Tuple{typeof(Base.structdiff), NamedTuple{(:prompt_prefix, :prompt_suffix, :complete, :sticky), Tuple{String, String, Pkg.REPLMode.PkgCompletionProvider, Bool}}, Type{NamedTuple{(:prompt_prefix, :prompt_suffix, :keymap_dict, :repl, :complete, :on_enter, :on_done, :hist, :sticky), T} where T<:Tuple}}) +precompile(Tuple{typeof(Base.structdiff), NamedTuple{(:prompt_prefix, :prompt_suffix, :repl, :complete, :on_enter), Tuple{String, typeof(Base.input_color), REPL.LineEditREPL, REPL.REPLCompletionProvider, typeof(REPL.return_callback)}}, Type{NamedTuple{(:prompt_prefix, :prompt_suffix, :keymap_dict, :repl, :complete, :on_enter, :on_done, :hist, :sticky), T} where T<:Tuple}}) +precompile(Tuple{typeof(Base.sum), Array{Int64, 1}}) +precompile(Tuple{typeof(Base.sym_in), Symbol, Tuple{Symbol, Symbol}}) +precompile(Tuple{typeof(Base.sym_in), Symbol, Tuple{Symbol}}) +precompile(Tuple{typeof(Base.sym_in), Symbol, Tuple{}}) +precompile(Tuple{typeof(Base.to_indices), Base.BitArray{2}, Tuple{Base.OneTo{Int64}}, Tuple{Int64}}) +precompile(Tuple{typeof(Base.trues), Int64}) +precompile(Tuple{typeof(Base.union!), Base.Set{Base.UUID}, Base.KeySet{Base.UUID, Base.Dict{Base.UUID, Pkg.Types.Fixed}}}) +precompile(Tuple{typeof(Base.union!), Base.Set{Base.UUID}, Base.KeySet{Base.UUID, Base.Dict{Base.UUID, Pkg.Types.VersionSpec}}}) +precompile(Tuple{typeof(Base.unique!), Array{Base.UUID, 1}}) +precompile(Tuple{typeof(Base.unique!), Array{String, 1}}) +precompile(Tuple{typeof(Base.values), Base.Dict{String, Any}}) +precompile(Tuple{typeof(Base.values), Base.Dict{String, String}}) +precompile(Tuple{typeof(Base.vcat), Base.BitArray{1}, Base.BitArray{1}}) +precompile(Tuple{typeof(Base.vcat), Base.BitArray{1}}) +precompile(Tuple{typeof(Base.vcat), Base.BitArray{2}, Base.BitArray{2}, Base.BitArray{2}, Base.BitArray{2}}) +precompile(Tuple{typeof(Base.vcat), Base.BitArray{2}, Base.BitArray{2}}) +precompile(Tuple{typeof(Base.vect), Base.Cmd, Base.Cmd}) +precompile(Tuple{typeof(Base.vect), Base.VersionNumber}) +precompile(Tuple{typeof(Base.vect), Nothing}) +precompile(Tuple{typeof(Base.write), Base.TTY, Array{UInt8, 1}}) +precompile(Tuple{typeof(Base.write), REPL.Terminals.TTYTerminal, Array{UInt8, 1}}) +precompile(Tuple{typeof(Core.Compiler.eltype), Type{Array{Base.BitArray{2}, 1}}}) +precompile(Tuple{typeof(Core.Compiler.eltype), Type{Array{Base.KeySet{Base.UUID, Base.Dict{Base.UUID, Pkg.Types.VersionSpec}}, 1}}}) +precompile(Tuple{typeof(Core.Compiler.eltype), Type{Array{Pkg.Pkg2.Pkg2Types.VersionInterval, 1}}}) +precompile(Tuple{typeof(Core.Compiler.eltype), Type{Array{UInt32, 1}}}) +precompile(Tuple{typeof(Core.Compiler.eltype), Type{Array{UInt8, 1}}}) +precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{Base.Iterators.Pairs{Union{}, Union{}, Tuple{}, NamedTuple{(), Tuple{}}}, typeof(Base.invokelatest), Nothing}, Int64}) +precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{Base.Iterators.Pairs{Union{}, Union{}, Tuple{}, NamedTuple{(), Tuple{}}}, typeof(Base.invokelatest), typeof(Pkg.REPLMode.do_help!)}, Int64}) +precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{Base.Iterators.Pairs{Union{}, Union{}, Tuple{}, NamedTuple{(), Tuple{}}}, typeof(Base.open), typeof(Pkg.Pkg2.Reqs.read)}, Int64}) +precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{Base.Iterators.Pairs{Union{}, Union{}, Tuple{}, NamedTuple{(), Tuple{}}}, typeof(Base.open), typeof(Pkg.TOML.parse)}, Int64}) +precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{Base.IteratorsMD.CartesianIndex{0}}, Int64}) +precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{Base.Missing, Int64}, Int64}) +precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{Base.Missing}, Int64}) +precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{Base.Val{1}, typeof(Base.cat_t), Union}, Int64}) +precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{Bool, typeof(Pkg.Types.parse_toml)}, Int64}) +precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{Int64, Tuple{Int64, Tuple{Int64, Tuple{Int64, Tuple{}}}}}, Int64}) +precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{NamedTuple{(:dims,), Tuple{Base.Val{1}}}, typeof(Base.cat_t), Union}, Int64}) +precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{Nothing, Int64, typeof(Base.sprint), typeof(Base.showerror)}, Int64}) +precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{Nothing, Int64, typeof(Base.sprint), typeof(Pkg.GraphType.showlog)}, Int64}) +precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{Pkg.REPLMode.CommandKind, Int64}, Int64}) +precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{typeof(Base.:(!))}, Int64}) +precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{typeof(Base.:(&))}, Int64}) +precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{typeof(Base.:(+))}, Int64}) +precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{typeof(Base.:(-))}, Int64}) +precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{typeof(Base.:(==))}, Int64}) +precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{typeof(Base.:(>))}, Int64}) +precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{typeof(Base.:(~))}, Int64}) +precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{typeof(Base.Unicode.lowercase)}, Int64}) +precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{typeof(Base.abs)}, Int64}) +precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{typeof(Base.first)}, Int64}) +precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{typeof(Base.identity)}, Int64}) +precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{typeof(Base.maximum)}, Int64}) +precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{typeof(Pkg.BinaryProvider.parse_tar_list)}, Int64}) +precompile(Tuple{typeof(Pkg.Display.filter_manifest), Pkg.Display.InProject{Base.Dict{String, Any}}, Base.Dict{String, Any}}) +precompile(Tuple{typeof(Pkg.Display.in_project), Base.Dict{String, Any}}) +precompile(Tuple{typeof(Pkg.Display.manifest_diff), Pkg.Types.Context, Base.Dict{String, Any}, Base.Dict{String, Any}}) +precompile(Tuple{typeof(Pkg.Display.name_ver_info), Base.Dict{String, Any}}) +precompile(Tuple{typeof(Pkg.Display.not_in_project), Base.Dict{String, Any}}) +precompile(Tuple{typeof(Pkg.Display.print_diff), Base.TTY, Pkg.Types.Context, Array{Pkg.Display.DiffEntry, 1}, Bool}) +precompile(Tuple{typeof(Pkg.Operations.load_package_data_raw), Type{Base.UUID}, String}) +precompile(Tuple{typeof(Pkg.REPLMode.do_add!), Base.Dict{Symbol, Any}, Array{Pkg.Types.PackageSpec, 1}, Base.Dict{Symbol, Any}}) +precompile(Tuple{typeof(Pkg.REPLMode.do_status!), Base.Dict{Symbol, Any}, Array{String, 1}, Base.Dict{Symbol, Any}}) +precompile(Tuple{typeof(Pkg.REPLMode.promptf)}) +precompile(Tuple{typeof(Pkg.TOML.SOME), Array{String, 1}}) +precompile(Tuple{typeof(Pkg.TOML.SOME), Pkg.TOML.Table}) +precompile(Tuple{typeof(Pkg.TOML.insertpair), Pkg.TOML.Parser{Base.IOStream}, Pkg.TOML.Table, String, Array{String, 1}, Int64}) +precompile(Tuple{typeof(Pkg.TOML.insertpair), Pkg.TOML.Parser{Base.IOStream}, Pkg.TOML.Table, String, Pkg.TOML.Table, Int64}) +precompile(Tuple{typeof(Pkg.TOML.is_array_of_tables), Array{Base.Dict{String, Any}, 1}}) +precompile(Tuple{typeof(Pkg.TOML.is_array_of_tables), Array{String, 1}}) +precompile(Tuple{typeof(Pkg.TOML.is_array_of_tables), String}) +precompile(Tuple{typeof(Pkg.TOML.is_tabular), Array{Base.Dict{String, Any}, 1}}) +precompile(Tuple{typeof(Pkg.TOML.is_tabular), Array{String, 1}}) +precompile(Tuple{typeof(Pkg.TOML.is_tabular), Base.Dict{String, Any}}) +precompile(Tuple{typeof(Pkg.TOML.is_tabular), String}) +precompile(Tuple{typeof(Pkg.TOML.parsefile), String}) +precompile(Tuple{typeof(Pkg.Types.printpkgstyle), Base.TTY, Symbol, String}) +precompile(Tuple{typeof(Pkg.Types.semver_interval), Base.RegexMatch}) +precompile(Tuple{typeof(Pkg.Types.write_env_usage), String}) +precompile(Tuple{typeof(REPL.LineEdit._clear_input_area), REPL.Terminals.TerminalBuffer, REPL.LineEdit.InputAreaState}) +precompile(Tuple{typeof(REPL.LineEdit.add_history), REPL.REPLHistoryProvider, REPL.LineEdit.PromptState}) +precompile(Tuple{typeof(REPL.LineEdit.clear_input_area), REPL.Terminals.TerminalBuffer, REPL.LineEdit.PromptState}) +precompile(Tuple{typeof(REPL.LineEdit.edit_abort), REPL.LineEdit.MIState, Bool}) +precompile(Tuple{typeof(REPL.LineEdit.edit_insert), REPL.LineEdit.MIState, String}) +precompile(Tuple{typeof(REPL.LineEdit.edit_insert), REPL.LineEdit.PromptState, String}) +precompile(Tuple{typeof(REPL.LineEdit.fixup_keymaps!), Base.Dict{Char, Any}, Int64, Char, Nothing}) +precompile(Tuple{typeof(REPL.LineEdit.init_state), REPL.Terminals.TTYTerminal, REPL.LineEdit.Prompt}) +precompile(Tuple{typeof(REPL.LineEdit.move_input_end), REPL.LineEdit.MIState}) +precompile(Tuple{typeof(REPL.LineEdit.normalize_key), Int64}) +precompile(Tuple{typeof(REPL.LineEdit.normalize_key), String}) +precompile(Tuple{typeof(REPL.LineEdit.on_enter), REPL.LineEdit.MIState}) +precompile(Tuple{typeof(REPL.LineEdit.postprocess!), Base.Dict{Char, Any}}) +precompile(Tuple{typeof(REPL.LineEdit.prompt_string), String}) +precompile(Tuple{typeof(REPL.LineEdit.push_undo), REPL.LineEdit.PromptState, Bool}) +precompile(Tuple{typeof(REPL.LineEdit.refresh_line), REPL.LineEdit.PromptState, REPL.Terminals.TTYTerminal}) +precompile(Tuple{typeof(REPL.LineEdit.refresh_multi_line), REPL.Terminals.TerminalBuffer, REPL.LineEdit.PromptState}) +precompile(Tuple{typeof(REPL.LineEdit.state), REPL.LineEdit.MIState, REPL.LineEdit.Prompt}) +precompile(Tuple{typeof(REPL.LineEdit.update_key_repeats), REPL.LineEdit.MIState, Array{Char, 1}}) +precompile(Tuple{typeof(REPL.LineEdit.write_prompt), REPL.Terminals.TerminalBuffer, REPL.LineEdit.Prompt}) +precompile(Tuple{typeof(REPL.LineEdit.write_prompt), REPL.Terminals.TerminalBuffer, String}) diff --git a/stdlib/REPL/docs/src/index.md b/stdlib/REPL/docs/src/index.md index 2afa93dfb32ea..0920ab36549c3 100644 --- a/stdlib/REPL/docs/src/index.md +++ b/stdlib/REPL/docs/src/index.md @@ -15,7 +15,7 @@ Markdown.parse("```\n\$ julia\n\n$(banner)\njulia>\n```") ``` To exit the interactive session, type `^D` -- the control key together with the `d` key on a blank -line -- or type `exit()` followed by the return or enter key. The REPL greets you with a banner +line -- or type `quit()` followed by the return or enter key. The REPL greets you with a banner and a `julia>` prompt. ## The different prompt modes diff --git a/stdlib/REPL/src/REPL.jl b/stdlib/REPL/src/REPL.jl index 977c4af6edb92..2ce39a860bc51 100644 --- a/stdlib/REPL/src/REPL.jl +++ b/stdlib/REPL/src/REPL.jl @@ -346,7 +346,7 @@ function complete_line(c::REPLCompletionProvider, s) partial = beforecursor(s.input_buffer) full = LineEdit.input_string(s) ret, range, should_complete = completions(full, lastindex(partial)) - return unique!(map(completion_text, ret)), partial[range], should_complete + return map(completion_text, ret), partial[range], should_complete end function complete_line(c::ShellCompletionProvider, s) @@ -354,14 +354,14 @@ function complete_line(c::ShellCompletionProvider, s) partial = beforecursor(s.input_buffer) full = LineEdit.input_string(s) ret, range, should_complete = shell_completions(full, lastindex(partial)) - return unique!(map(completion_text, ret)), partial[range], should_complete + return map(completion_text, ret), partial[range], should_complete end function complete_line(c::LatexCompletions, s) partial = beforecursor(LineEdit.buffer(s)) full = LineEdit.input_string(s) ret, range, should_complete = bslash_completions(full, lastindex(partial))[2] - return unique!(map(completion_text, ret)), partial[range], should_complete + return map(completion_text, ret), partial[range], should_complete end mutable struct REPLHistoryProvider <: HistoryProvider diff --git a/stdlib/REPL/src/Terminals.jl b/stdlib/REPL/src/Terminals.jl index f0e03c0a23e40..bf8189c4205f4 100644 --- a/stdlib/REPL/src/Terminals.jl +++ b/stdlib/REPL/src/Terminals.jl @@ -120,10 +120,8 @@ cmove_line_up(t::UnixTerminal, n) = (cmove_up(t, n); cmove_col(t, 1)) cmove_line_down(t::UnixTerminal, n) = (cmove_down(t, n); cmove_col(t, 1)) cmove_col(t::UnixTerminal, n) = (write(t.out_stream, '\r'); n > 1 && cmove_right(t, n-1)) -const is_precompiling = Ref(false) if Sys.iswindows() function raw!(t::TTYTerminal,raw::Bool) - is_precompiling[] && return true check_open(t.in_stream) if Base.ispty(t.in_stream) run((raw ? `stty raw -echo onlcr -ocrnl opost` : `stty sane`), diff --git a/stdlib/REPL/test/replcompletions.jl b/stdlib/REPL/test/replcompletions.jl index 2e8ae033ee0d0..2d03dbf925d32 100644 --- a/stdlib/REPL/test/replcompletions.jl +++ b/stdlib/REPL/test/replcompletions.jl @@ -102,11 +102,6 @@ let s = "" @test s[r] == "" end -let s = "using REP" - c, r = test_complete(s) - @test count(isequal("REPL"), c) == 1 -end - let s = "Comp" c, r = test_complete(s) @test "CompletionFoo" in c diff --git a/stdlib/Random/src/Random.jl b/stdlib/Random/src/Random.jl index 1ac74ad5e64fd..42aebc1344d42 100644 --- a/stdlib/Random/src/Random.jl +++ b/stdlib/Random/src/Random.jl @@ -23,7 +23,9 @@ export rand!, randn!, shuffle, shuffle!, randperm, randperm!, randcycle, randcycle!, - AbstractRNG, MersenneTwister, RandomDevice + AbstractRNG, MersenneTwister, RandomDevice, + randjump + ## general definitions diff --git a/stdlib/Random/src/misc.jl b/stdlib/Random/src/misc.jl index 7b94abb062314..0e7bb9782e500 100644 --- a/stdlib/Random/src/misc.jl +++ b/stdlib/Random/src/misc.jl @@ -182,7 +182,6 @@ julia> shuffle!(rng, Vector(1:16)) function shuffle!(r::AbstractRNG, a::AbstractArray) @assert !has_offset_axes(a) n = length(a) - n <= 1 && return a # nextpow below won't work with n == 0 @assert n <= Int64(2)^52 mask = nextpow(2, n) - 1 for i = n:-1:2 diff --git a/stdlib/Random/test/runtests.jl b/stdlib/Random/test/runtests.jl index 83e4b44e83697..91d3db9eb994a 100644 --- a/stdlib/Random/test/runtests.jl +++ b/stdlib/Random/test/runtests.jl @@ -686,11 +686,3 @@ end @test Random.gentype(Random.UInt52(UInt128)) == UInt128 @test Random.gentype(Random.UInt104()) == UInt128 end - -@testset "shuffle[!]" begin - a = [] - @test shuffle(a) == a # issue #28727 - @test shuffle!(a) === a - a = rand(Int, 1) - @test shuffle(a) == a -end diff --git a/stdlib/SparseArrays/src/sparsematrix.jl b/stdlib/SparseArrays/src/sparsematrix.jl index f954d33393d61..a88f27edd90d1 100644 --- a/stdlib/SparseArrays/src/sparsematrix.jl +++ b/stdlib/SparseArrays/src/sparsematrix.jl @@ -356,7 +356,6 @@ similar(S::SparseMatrixCSC, ::Type{TvNew}, ::Type{TiNew}, m::Integer, n::Integer # converting between SparseMatrixCSC types -SparseMatrixCSC(S::SparseMatrixCSC) = copy(S) AbstractMatrix{Tv}(A::SparseMatrixCSC) where {Tv} = SparseMatrixCSC{Tv}(A) SparseMatrixCSC{Tv}(S::SparseMatrixCSC{Tv}) where {Tv} = copy(S) SparseMatrixCSC{Tv}(S::SparseMatrixCSC) where {Tv} = SparseMatrixCSC{Tv,eltype(S.colptr)}(S) diff --git a/stdlib/SparseArrays/test/sparse.jl b/stdlib/SparseArrays/test/sparse.jl index ccc715064977f..fd13fc9189233 100644 --- a/stdlib/SparseArrays/test/sparse.jl +++ b/stdlib/SparseArrays/test/sparse.jl @@ -2317,12 +2317,8 @@ end @test_throws SingularException(1) A \ ones(2) A = UpperTriangular(sparse([1.0 0;0 0])) @test_throws SingularException(2) A \ ones(2) -end -@testset "Issue #28634" begin - a = SparseMatrixCSC{Int8, Int16}([1 2; 3 4]) - na = SparseMatrixCSC(a) - @test typeof(a) === typeof(na) + end end # module diff --git a/stdlib/Statistics/src/Statistics.jl b/stdlib/Statistics/src/Statistics.jl index bc7a857079e88..28d2cae7837e3 100644 --- a/stdlib/Statistics/src/Statistics.jl +++ b/stdlib/Statistics/src/Statistics.jl @@ -248,7 +248,7 @@ end Compute the sample variance of a collection `v` with known mean(s) `m`, optionally over the given dimensions. `m` may contain means for each dimension of `v`. If `corrected` is `true`, then the sum is scaled with `n-1`, -whereas the sum is scaled with `n` if `corrected` is `false` where `n = length(v)`. +whereas the sum is scaled with `n` if `corrected` is `false` where `n = length(x)`. !!! note If array contains `NaN` or [`missing`](@ref) values, the result is also @@ -278,7 +278,7 @@ The algorithm will return an estimator of the generative distribution's variance under the assumption that each entry of `v` is an IID drawn from that generative distribution. This computation is equivalent to calculating `sum(abs2, v - mean(v)) / (length(v) - 1)`. If `corrected` is `true`, then the sum is scaled with `n-1`, -whereas the sum is scaled with `n` if `corrected` is `false` where `n = length(v)`. +whereas the sum is scaled with `n` if `corrected` is `false` where `n = length(x)`. The mean `mean` over the region may be provided. !!! note @@ -345,7 +345,7 @@ deviation under the assumption that each entry of `v` is an IID drawn from that distribution. This computation is equivalent to calculating `sqrt(sum((v - mean(v)).^2) / (length(v) - 1))`. A pre-computed `mean` may be provided. If `corrected` is `true`, then the sum is scaled with `n-1`, whereas the sum is scaled with `n` if `corrected` is -`false` where `n = length(v)`. +`false` where `n = length(x)`. !!! note If array contains `NaN` or [`missing`](@ref) values, the result is also @@ -376,7 +376,7 @@ std(iterable; corrected::Bool=true, mean=nothing) = Compute the sample standard deviation of a vector `v` with known mean `m`. If `corrected` is `true`, then the sum is scaled with `n-1`, whereas the sum is -scaled with `n` if `corrected` is `false` where `n = length(v)`. +scaled with `n` if `corrected` is `false` where `n = length(x)`. !!! note If array contains `NaN` or [`missing`](@ref) values, the result is also @@ -882,7 +882,7 @@ probabilities `p` on the interval [0,1]. The keyword argument `sorted` indicates `itr` can be assumed to be sorted. Quantiles are computed via linear interpolation between the points `((k-1)/(n-1), v[k])`, -for `k = 1:n` where `n = length(itr)`. This corresponds to Definition 7 of Hyndman and Fan +for `k = 1:n` where `n = length(v)`. This corresponds to Definition 7 of Hyndman and Fan (1996), and is the same as the R default. !!! note diff --git a/test/arrayops.jl b/test/arrayops.jl index 3edc8516838eb..7c7ae0404510b 100644 --- a/test/arrayops.jl +++ b/test/arrayops.jl @@ -2455,13 +2455,13 @@ end # Ensure we can hash strange custom structs — and they hash the same in arrays struct totally_not_five26034 end -Base.isequal(::totally_not_five26034, x::Number)=isequal(5,x); -Base.isequal(x::Number, ::totally_not_five26034)=isequal(5,x); +Base.isequal(::totally_not_five26034, x)=isequal(5,x); +Base.isequal(x, ::totally_not_five26034)=isequal(5,x); Base.isequal(::totally_not_five26034, ::totally_not_five26034)=true; Base.hash(::totally_not_five26034, h::UInt)=hash(5, h); import Base.== -==(::totally_not_five26034, x::Number)= (5==x); -==(x::Number,::totally_not_five26034)= (5==x); +==(::totally_not_five26034, x)= (5==x); +==(x,::totally_not_five26034)= (5==x); ==(::totally_not_five26034,::totally_not_five26034)=true; @testset "issue #26034" begin n5 = totally_not_five26034() diff --git a/test/bigint.jl b/test/bigint.jl index cd4c48f44873d..01acd5449b8c3 100644 --- a/test/bigint.jl +++ b/test/bigint.jl @@ -401,27 +401,3 @@ end # Issue #24298 @test mod(BigInt(6), UInt(5)) == mod(6, 5) - -@testset "cmp has values in [-1, 0, 1], issue #28780" begin - # _rand produces values whose log2 is better distributed than rand - _rand(::Type{BigInt}, n=1000) = let x = big(2)^rand(1:rand(1:n)) - rand(-x:x) - end - _rand(F::Type{<:AbstractFloat}) = F(_rand(BigInt, round(Int, log2(floatmax(F))))) + rand(F) - _rand(T) = rand(T) - for T in (Base.BitInteger_types..., BigInt, Float64, Float32, Float16) - @test cmp(big(2)^130, one(T)) === 1 - @test cmp(-big(2)^130, one(T)) === -1 - c = cmp(_rand(BigInt), _rand(T)) - @test c ∈ (-1, 0, 1) - @test c isa Int - (T <: Integer && T !== BigInt) || continue - x = rand(T) - @test cmp(big(2)^130, x) === cmp(x, -big(2)^130) === 1 - @test cmp(-big(2)^130, x) === cmp(x, big(2)^130) === -1 - @test cmp(big(x), x) === cmp(x, big(x)) === 0 - end - c = cmp(_rand(BigInt), _rand(BigInt)) - @test c ∈ (-1, 0, 1) - @test c isa Int -end diff --git a/test/compiler/compiler.jl b/test/compiler/compiler.jl index 7ddca137ed2c4..904695982e030 100644 --- a/test/compiler/compiler.jl +++ b/test/compiler/compiler.jl @@ -1977,16 +1977,3 @@ function bar28444() e[1] end @test bar28444() == 1 - -# issue #28641 -struct VoxelIndices{T <: Integer} - voxCrnrPos::NTuple{8,NTuple{3,T}} - voxEdgeCrnrs::NTuple{19, NTuple{2,T}} - voxEdgeDir::NTuple{19,T} - voxEdgeIx::NTuple{8,NTuple{8,T}} - subTets::NTuple{6,NTuple{4,T}} - tetEdgeCrnrs::NTuple{6,NTuple{2,T}} - tetTri::NTuple{16,NTuple{6,T}} -end -f28641(x::VoxelIndices, f) = getfield(x, f) -@test Base.return_types(f28641, (Any,Symbol)) == Any[Tuple] diff --git a/test/core.jl b/test/core.jl index f6f467183de83..7dd27fefe03fc 100644 --- a/test/core.jl +++ b/test/core.jl @@ -141,8 +141,6 @@ end @test typejoin(Tuple{Vararg{Int,2}}, Tuple{Int,Int,Int}) === Tuple{Int,Int,Vararg{Int}} @test typejoin(Tuple{Vararg{Int,2}}, Tuple{Vararg{Int}}) === Tuple{Vararg{Int}} -@test typejoin(NTuple{3,Tuple}, NTuple{2,T} where T) == Tuple{Any,Any,Vararg{Tuple}} - # issue #26321 struct T26321{N,S<:NTuple{N}} t::S @@ -6697,12 +6695,3 @@ function repackage28445() true end @test repackage28445() - -# issue #28597 -@test_throws ErrorException Array{Int, 2}(undef, 0, -10) -@test_throws ErrorException Array{Int, 2}(undef, -10, 0) -@test_throws ErrorException Array{Int, 2}(undef, -1, -1) - -# issue #28812 -@test Tuple{Vararg{Array{T},3} where T} === Tuple{Array,Array,Array} -@test Tuple{Vararg{Array{T} where T,3}} === Tuple{Array,Array,Array} diff --git a/test/docs.jl b/test/docs.jl index c6cbb3847ae28..3a925d65a4334 100644 --- a/test/docs.jl +++ b/test/docs.jl @@ -1121,13 +1121,6 @@ struct A_20087 end @test docstrings_equal(@doc(A_20087()), doc"a") -struct B_20087 end - -"""b""" -(::B_20087)() = a - -@test docstrings_equal(@doc(B_20087()), doc"b") - # issue #27832 _last_atdoc = Core.atdoc diff --git a/test/llvmcall.jl b/test/llvmcall.jl index ec1286ce62ce4..c92d2be67add9 100644 --- a/test/llvmcall.jl +++ b/test/llvmcall.jl @@ -179,16 +179,20 @@ module ObjLoadTest end # Test for proper parenting -local foo -function foo() - # this IR snippet triggers an optimization relying - # on the llvmcall function having a parent module - Base.llvmcall( - """%1 = getelementptr i64, i64* null, i64 1 - ret void""", - Cvoid, Tuple{}) +if Base.libllvm_version >= v"3.6" # llvm 3.6 changed the syntax for a gep, so just ignore this test on older versions + local foo + function foo() + # this IR snippet triggers an optimization relying + # on the llvmcall function having a parent module + Base.llvmcall( + """%1 = getelementptr i64, i64* null, i64 1 + ret void""", + Cvoid, Tuple{}) + end + code_llvm(devnull, foo, ()) +else + @info "Skipping gep parentage test on llvm < 3.6" end -code_llvm(devnull, foo, ()) module CcallableRetTypeTest using Base: llvmcall, @ccallable diff --git a/test/loading.jl b/test/loading.jl index 259f55a87c999..289c25e582b0a 100644 --- a/test/loading.jl +++ b/test/loading.jl @@ -547,22 +547,6 @@ finally popfirst!(LOAD_PATH) end -@testset "--project and JULIA_PROJECT paths should be absolutified" begin - mktempdir() do dir; cd(dir) do - mkdir("foo") - script = """ - using Test - old = Base.active_project() - cd("foo") - @test Base.active_project() == old - """ - @test success(`$(Base.julia_cmd()) --project=foo -e $(script)`) - withenv("JULIA_PROJECT" => "foo") do - @test success(`$(Base.julia_cmd()) -e $(script)`) - end - end; end -end - ## cleanup after tests ## for env in keys(envs) diff --git a/test/misc.jl b/test/misc.jl index c280fc79d145e..beec7c1033a31 100644 --- a/test/misc.jl +++ b/test/misc.jl @@ -678,11 +678,3 @@ end # Just checking that this doesn't stack overflow on construction @test Test27970Empty() == Test27970Empty() end - -@testset "exports of modules" begin - for (_, mod) in Base.loaded_modules - for v in names(mod) - @test isdefined(mod, v) - end - end -end diff --git a/test/sets.jl b/test/sets.jl index 35155633abb9d..ea523d43afb72 100644 --- a/test/sets.jl +++ b/test/sets.jl @@ -604,16 +604,3 @@ end end end end - -struct OpenInterval{T} - lower::T - upper::T -end -Base.in(x, i::OpenInterval) = i.lower < x < i.upper -Base.IteratorSize(::Type{<:OpenInterval}) = Base.SizeUnknown() - -@testset "Continuous sets" begin - i = OpenInterval(2, 4) - @test 3 ∈ i - @test issubset(3, i) -end diff --git a/test/strings/basic.jl b/test/strings/basic.jl index 521dfa6d52b99..034d45bee9596 100644 --- a/test/strings/basic.jl +++ b/test/strings/basic.jl @@ -34,7 +34,6 @@ using Random @test string("∀∃", "1∀∃") === "∀∃1∀∃" @test string(SubString("∀∃"), SubString("1∀∃", 2)) === "∀∃∀∃" @test string(s"123") === s"123" - @test string("123", 'α', SubString("1∀∃", 2), 'a', "foo") === "123α∀∃afoo" codegen_egal_of_strings(x, y) = (x===y, x!==y) @test codegen_egal_of_strings(string("ab", 'c'), "abc") === (true, false) let strs = ["", "a", "a b c", "до свидания"] diff --git a/test/syntax.jl b/test/syntax.jl index 9e12206ad8325..4e4417dd5a3b6 100644 --- a/test/syntax.jl +++ b/test/syntax.jl @@ -1646,30 +1646,3 @@ end # issue #28576 @test Meta.isexpr(Meta.parse("1 == 2 ?"), :incomplete) @test Meta.isexpr(Meta.parse("1 == 2 ? 3 :"), :incomplete) - -# issue #28593 -macro a28593() - quote - abstract type A28593{S<:Real, V<:AbstractVector{S}} end - end -end - -macro b28593() - quote - struct B28593{S<:Real, V<:AbstractVector{S}} end - end -end - -macro c28593() - quote - primitive type C28593{S<:Real, V<:AbstractVector{S}} 32 end - end -end - -@a28593 -@b28593 -@c28593 - -@test A28593.var.name === :S -@test B28593.var.name === :S -@test C28593.var.name === :S From 7c54648dc29d85c80bdfc00b4ab485f86fccdd58 Mon Sep 17 00:00:00 2001 From: mcognetta Date: Sat, 15 Sep 2018 16:53:28 +0900 Subject: [PATCH 16/26] Removing the speedups for sparse matrix multiplication and division. These should go in another PR so this one can be merged more quickly. Revert "added sparse multiplication and division for triangular matrices. Fix #28451" This reverts commit 11c1d1d477635042cb41fb13125acc8301ca887d. --- HISTORY.md | 1738 ----------------------- NEWS.md | 1716 +++++++++++++++++++++- README.md | 14 +- README.windows.md | 2 +- VERSION | 2 +- base/compiler/abstractinterpretation.jl | 24 +- base/compiler/typelimits.jl | 64 +- base/essentials.jl | 37 + base/exports.jl | 9 + base/io.jl | 9 +- base/iterators.jl | 2 +- base/stream.jl | 5 +- base/version.jl | 15 +- contrib/precompile_explicit.jl | 1 + doc/Manifest.toml | 26 +- doc/make.jl | 14 +- doc/src/index.md | 10 +- doc/src/manual/profile.md | 31 - doc/src/manual/types.md | 2 +- src/julia-parser.scm | 8 +- src/toplevel.c | 2 - stdlib/LibGit2/src/LibGit2.jl | 2 +- stdlib/LibGit2/src/rebase.jl | 20 +- stdlib/LibGit2/test/libgit2.jl | 2 +- stdlib/LinearAlgebra/src/adjtrans.jl | 2 +- stdlib/LinearAlgebra/src/generic.jl | 2 +- stdlib/LinearAlgebra/src/qr.jl | 5 +- stdlib/LinearAlgebra/test/adjtrans.jl | 4 +- stdlib/LinearAlgebra/test/generic.jl | 2 - stdlib/REPL/docs/src/index.md | 18 +- stdlib/SparseArrays/src/linalg.jl | 374 ++--- stdlib/SparseArrays/test/sparse.jl | 32 - test/compiler/compiler.jl | 22 +- test/iterators.jl | 3 +- test/spawn.jl | 38 +- test/syntax.jl | 4 - 36 files changed, 1973 insertions(+), 2288 deletions(-) diff --git a/HISTORY.md b/HISTORY.md index 68805667a5bd8..d461728a61b84 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,1741 +1,3 @@ -Julia v0.7.0 Release Notes -========================== - -New language features ---------------------- - - * Local variables can be tested for being defined - using the new `@isdefined variable` macro ([#22281]). - - * Destructuring in function arguments: when an expression such as `(x, y)` is used as - a function argument name, the argument is unpacked into local variables `x` and `y` - as in the assignment `(x, y) = arg` ([#6614]). - - * Named tuples, with the syntax `(a=1, b=2)`. These behave very similarly to tuples, - except components can also be accessed by name using dot syntax `t.a` ([#22194]). - - * Keyword argument containers (`kw` in `f(; kw...)`) are now based on named tuples. Dictionary - functions like `haskey` and indexing can be used on them, and name-value pairs can be - iterated using `pairs(kw)`. `kw` can no longer contain multiple entries for the same - argument name ([#4916]). - - * Custom infix operators can now be defined by appending Unicode - combining marks, primes, and sub/superscripts to other operators. - For example, `+̂ₐ″` is parsed as an infix operator with the same - precedence as `+` ([#22089]). - - * The macro call syntax `@macroname[args]` is now available and is parsed - as `@macroname([args])` ([#23519]). - - * The construct `if @generated ...; else ...; end` can be used to provide both - `@generated` and normal implementations of part of a function. Surrounding code - will be common to both versions ([#23168]). - - * Added `⟂` (`\perp`) operator with comparison precedence ([#24404]). - - * The `missing` singleton object (of type `Missing`) has been added to represent - missing values ([#24653]). It propagates through standard operators and mathematical functions, - and implements three-valued logic, similar to SQLs `NULL` and R's `NA`. - - * Field access via dot-syntax can now be overloaded by adding methods to - `Base.getproperty` and `Base.setproperty!` ([#1974]), optionally along with - a corresponding `Base.propertynames` method for reflection ([#25311]). - - * Values for `Enum`s can now be specified inside of a `begin` block when using the - `@enum` macro ([#25424]). - - * Keyword arguments can be required: if a default value is omitted, then an - exception is thrown if the caller does not assign the keyword a value ([#25830]). - - * The pair operator `=>` is now broadcastable as `.=>` which was previously a parsing error ([#27447]) - -Language changes ----------------- - - * The syntax for parametric methods, `function f{T}(x::T)`, has been - changed to `function f(x::T) where {T}` ([#11310]). - - * The fallback constructor that calls `convert` is deprecated. Instead, new types should - prefer to define constructors, and add `convert` methods that call those constructors - only as necessary ([#15120]). - - * The syntax `1.+2` is deprecated, since it is ambiguous: it could mean either - `1 .+ 2` (the current meaning) or `1. + 2` ([#19089]). - - * Mutable structs with no fields are no longer singletons; it is now possible to make - multiple instances of them that can be distinguished by `===` ([#25854]). - Zero-size immutable structs are still singletons. - - * In string and character literals, backslash `\` may no longer - precede unrecognized escape characters ([#22800]). - - * Juxtaposing binary, octal, and hexadecimal literals is deprecated, since it can lead to - confusing code such as `0xapi == 0xa * pi` ([#16356]). - - * Numeric literal juxtaposition now has slighty lower precedence than unary operators, - so for example `√2x` parses as `(√2) * x` ([#27641]). - - * Declaring arguments as `x::ANY` to avoid specialization has been replaced - by `@nospecialize x`. ([#22666]). - - This can also be used in global scope, to apply to all subsequent method definitions - in the module (until `@specialize`). ([#28065]) - - * Keyword argument default values are now evaluated in successive scopes --- - the scope for each expression includes only previous keyword arguments, in - left-to-right order ([#17240]). - - * The parsing of `1<<2*3` as `1<<(2*3)` is deprecated, and will change to - `(1<<2)*3` in a future version ([#13079]). - - * The parsing of `<|` is now right associative. `|>` remains left associative ([#24153]). - - * `:` now parses like other operators, as a call to a function named `:`, instead of - calling `colon` ([#25947]). - - * `{ }` expressions now use `braces` and `bracescat` as expression heads instead - of `cell1d` and `cell2d`, and parse similarly to `vect` and `vcat` ([#8470]). - - * Nested `if` expressions that arise from the keyword `elseif` now use `elseif` - as their expression head instead of `if` ([#21774]). - - * `let` blocks now parse the same as `for` loops; the first argument is either an - assignment or `block` of assignments, and the second argument is a block of - statements ([#21774]). - - * `do` syntax now parses to an expression with head `:do`, instead of as a function - call ([#21774]). - - * Parsed and lowered forms of type definitions have been synchronized with their - new keywords ([#23157]). Expression heads are renamed as follows: - - + `type` => `struct` - - + `bitstype` => `primitive` (order of arguments is also reversed, to match syntax) - - + `composite_type` => `struct_type` - - + `bits_type` => `primitive_type` - - * The `global` keyword now only introduces a new binding if one doesn't already exist - in the module. - This means that assignment to a global (`global sin = 3`) may now throw the error: - "cannot assign variable Base.sin from module Main", rather than emitting a warning. - Additionally, the new bindings are now created before the statement is executed. - For example, `f() = (global sin = "gluttony"; nothing)` will now resolve which module - contains `sin` eagerly, rather than delaying that decision until `f` is run. ([#22984]). - - * `global const` declarations may no longer appear inside functions ([#12010]). - - * Uninitialized `BitArray` constructors of the form `BitArray[{N}](shape...)` have been - deprecated in favor of equivalents accepting `undef` (an alias for - `UndefInitializer()`) as their first argument, as in - `BitArray[{N}](undef, shape...)`. For example, `BitVector(3)` is now - `BitVector(undef, 3)`, `BitMatrix((2, 4))` is now - `BitMatrix(undef, (2, 4))`, and `BitArray{3}(11, 13, 17)` is now - `BitArray{3}(undef, 11, 14, 17)` ([#24785]). - - * Dispatch rules have been simplified: - method matching is now determined exclusively by subtyping; - the rule that method type parameters must also be captured has been removed. - Instead, attempting to access the unconstrained parameters will throw an `UndefVarError`. - Linting in package tests is recommended to confirm that the set of methods - which might throw `UndefVarError` when accessing the static parameters - (`need_to_handle_undef_sparam = Set{Any}(m.sig for m in Test.detect_unbound_args(Base, recursive=true))`) - is equal (`==`) to some known set (`expected = Set()`). ([#23117]) - - * `const` declarations on local variables were previously ignored. They now give a - warning, so that this syntax can be disallowed or given a new meaning in a - future version ([#5148]). - - * Placing an expression after `catch`, as in `catch f(x)`, is deprecated. - Use `catch; f(x)` instead ([#19987]). - - * In `for i = ...`, if a local variable `i` already existed it would be overwritten - during the loop. This behavior is deprecated, and in the future `for` loop variables - will always be new variables local to the loop ([#22314]). - The old behavior of overwriting an existing variable is available via `for outer i = ...`. - - * In `for i in x`, `x` used to be evaluated in a new scope enclosing the `for` loop. - Now it is evaluated in the scope outside the `for` loop. - - * In `for i in x, j in y`, all variables now have fresh bindings on each iteration of the - innermost loop. For example, an assignment to `i` will not be visible on the next `j` - loop iteration ([#330]). - - * Variable bindings local to `while` loop bodies are now freshly allocated on each loop iteration, - matching the behavior of `for` loops. - - * Prefix `&` for by-reference arguments to `ccall` has been deprecated in favor of - `Ref` argument types ([#6080]). - - * The constructor `Ref(x::T)` now always returns a `Ref{T}` ([#21527]). - - * All line numbers in ASTs are represented by `LineNumberNode`s; the `:line` expression - head is no longer used. `QuoteNode`s are also consistently used for quoted symbols instead - of the `:quote` expression head (though `:quote` `Expr`s are still used for quoted - expressions) ([#23885]). - - * The `+` and `-` methods for `Number` and `UniformScaling` are not ambiguous anymore since `+` - and `-` no longer do automatic broadcasting. Hence, the methods for `UniformScaling` and `Number` are - no longer deprecated ([#23923]). - - * The keyword `importall` is deprecated. Use `using` and/or individual `import` statements - instead ([#22789]). - - * `reduce(+, [...])` and `reduce(*, [...])` no longer widen the iterated over arguments to - system word size. `sum` and `prod` still preserve this behavior. ([#22825]) - - * Like `_`, variable names consisting only of underscores can be assigned, - but accessing their values is deprecated ([#24221]). - - * Raw string literal escaping rules have been changed to make it possible to write all strings. - The rule is that backslashes escape both quotes and other backslashes, but only when a sequence - of backslashes precedes a quote character. Thus, 2n backslashes followed by a quote encodes n - backslashes and the end of the literal while 2n+1 backslashes followed by a quote encodes n - backslashes followed by a quote character ([#22926]). - - * `reprmime(mime, x)` has been renamed to `repr(mime, x)`, and along with `repr(x)` - and `sprint` it now accepts an optional `context` keyword for `IOContext` attributes. - `stringmime` has been moved to the Base64 stdlib package ([#25990]). - - * The syntax `(x...)` for constructing a tuple is deprecated; use `(x...,)` instead ([#24452]). - - * Non-parenthesized interpolated variables in strings, e.g. `"$x"`, must be followed - by a character that will never be an allowed identifier character (currently - operators, space/control characters, or common punctuation characters) ([#25231]). - - * The syntax `using A.B` can now only be used when `A.B` is a module, and the syntax - `using A: B` can only be used for adding single bindings ([#8000]). - - * `=>` now has its own precedence level, giving it strictly higher precedence than - `=` and `,` ([#25391]). - - * The conditions under which unary operators followed by `(` are parsed as prefix function - calls have changed ([#26154]). - - * `begin` is disallowed inside indexing expressions, in order to enable the syntax - `a[begin]` (for selecting the first element) in the future ([#23354]). - - * Underscores for `_italics_` and `__bold__` are now supported by the Base Markdown - parser. ([#25564]) - - * `…` (`\dots`) and `⁝` (`\tricolon`) are now parsed as binary operators ([#26262]). - - * Assignment syntax (`a=b`) inside square bracket expressions (e.g. `A[...]`, `[x, y]`) - is deprecated. It will likely be reclaimed in a later version for passing keyword - arguments. Note this does not affect updating operators like `+=` ([#25631]). - - * `try` blocks without `catch` or `finally` are no longer allowed. An explicit empty - `catch` block should be written instead ([#27554]). - - * `AbstractArray` types that use unconventional (not 1-based) indexing can now support - `size`, `length`, and `@inbounds`. To optionally enforce conventional indices, - you can `@assert !has_offset_axes(A)`. - - * Module pre-compilation is now the default for code loading. Adding a - `__precompile__()` declaration is no longer necessary, although - `__precompile__(false)` can still be used to opt-out ([#26991]). - -Breaking changes ----------------- - -This section lists changes that do not have deprecation warnings. - - * The package manager `Pkg` has been replaced with a new one. See the manual entries on - "Code Loading" and "Pkg" for documentation. - - * `replace(s::AbstractString, pat=>repl)` for function `repl` arguments formerly - passed a substring to `repl` in all cases. It now passes substrings for - string patterns `pat`, but a `Char` for character patterns (when `pat` is a - `Char`, collection of `Char`, or a character predicate) ([#25815]). - - * `readuntil` now does *not* include the delimiter in its result, matching the - behavior of `readline`. Pass `keep=true` to get the old behavior ([#25633]). - - * `lu` methods now return decomposition objects such as `LU` rather than - tuples of arrays or tuples of numbers ([#26997], [#27159], [#27212]). - - * `schur` methods now return decomposition objects such as `Schur` and - `GeneralizedSchur` rather than tuples of arrays ([#26997], [#27159], [#27212]). - - * `lq` methods now return decomposition objects such as `LQ` - rather than tuples of arrays ([#26997], [#27159], [#27212]). - - * `qr` methods now return decomposition objects such as `QR`, `QRPivoted`, - and `QRCompactWY` rather than tuples of arrays ([#26997], [#27159], [#27212]). - - * `svd` methods now return decomposition objects such as `SVD` and - `GeneralizedSVD` rather than tuples of arrays or tuples of numbers ([#26997], [#27159], [#27212]). - - * `countlines` now always counts the last non-empty line even if it does not - end with EOL, matching the behavior of `eachline` and `readlines` ([#25845]). - - * `getindex(s::String, r::UnitRange{Int})` now throws `StringIndexError` if `last(r)` - is not a valid index into `s` ([#22572]). - - * `ntuple(f, n::Integer)` throws `ArgumentError` if `n` is negative. - Previously an empty tuple was returned ([#21697]). - - * `⋮`, `⋱`, `⋰`, and `⋯` are now parsed as binary operators, not ordinary - identifiers. `≔`, `≕`, and `⩴` now parse with assignment rather than comparison - precedence ([#26262]). - - * Juxtaposing string literals (e.g. `"x"y`) is now a syntax error ([#20575]). - - * `finalizer(function, object)` now returns `object` rather than `nothing` ([#24679]). - - * The constructor of `SubString` now checks if the requested view range - is defined by valid indices in the parent `AbstractString` ([#22511]). - - * Macro calls with `for` expressions are now parsed as generators inside - function argument lists ([#18650]). Examples: - - + `sum(@inbounds a[i] for i = 1:n)` used to give a syntax error, but is now - parsed as `sum(@inbounds(a[i]) for i = 1:n)`. - - + `sum(@m x for i = 1:n end)` used to parse the argument to `sum` as a 2-argument - call to macro `@m`, but now parses it as a generator plus a syntax error - for the dangling `end`. - - * `@__DIR__` returns the current working directory rather than `nothing` when not run - from a file ([#21759]). - - * `@__FILE__` and `@__DIR__` return information relative to the file that it was parsed from, - rather than from the task-local `SOURCE_PATH` global when it was expanded. - - * All macros receive an extra argument `__source__::LineNumberNode` which describes the - parser location in the source file for the `@` of the macro call. - It can be accessed as a normal argument variable in the body of the macro. - This is implemented by inserting an extra leading argument into the - `Expr(:macrocall, :@name, LineNumberNode(...), args...)` - surface syntax. ([#21746]) - - * Passing the same keyword argument multiple times is now a syntax error ([#16937]). - - * `getsockname` on a `TCPSocket` now returns the locally bound address and port - of the socket. Previously the address of the remote endpoint was being - returned ([#21825]). - - * The `~/.juliarc.jl` file has been moved to `~/.julia/config/startup.jl` and - `/etc/julia/juliarc.jl` file has been renamed to `/etc/julia/startup.jl` ([#26161]). - - * Using `ARGS` within `startup.jl` files or within a .jl file loaded with `--load` will no - longer contain the script name as the first argument. Instead, the script name will be - assigned to `PROGRAM_FILE`. ([#22092]) - - * The format for a `ClusterManager` specifying the cookie on the command line is now - `--worker=`. `--worker ` will not work as it is now an optional argument. - - * The representation of `CartesianRange` has changed to a - tuple-of-AbstractUnitRanges; the `start` and `stop` fields are no - longer present. Use `first(R)` and `last(R)` to obtain - start/stop. ([#20974]) - - * The `Diagonal`, `Bidiagonal`, `Tridiagonal` and `SymTridiagonal` type definitions have - changed from `Diagonal{T}`, `Bidiagonal{T}`, `Tridiagonal{T}` and `SymTridiagonal{T}` - to `Diagonal{T,V<:AbstractVector{T}}`, `Bidiagonal{T,V<:AbstractVector{T}}`, - `Tridiagonal{T,V<:AbstractVector{T}}` and `SymTridiagonal{T,V<:AbstractVector{T}}` - respectively ([#22718], [#22925], [#23035], [#23154]). - - * The immediate supertype of `BitArray` is now simply `AbstractArray`. `BitArray` is no longer - considered a subtype of `DenseArray` and `StridedArray` ([#25858]). - - * When called with an argument that contains `NaN` elements, `findmin` and `findmax` now return the - first `NaN` found and its corresponding index. Previously, `NaN` elements were ignored. - The new behavior matches that of `min`, `max`, `minimum`, and `maximum`. - - * `isapprox(x,y)` now tests `norm(x-y) <= max(atol, rtol*max(norm(x), norm(y)))` - rather than `norm(x-y) <= atol + ...`, and `rtol` defaults to zero - if an `atol > 0` is specified ([#22742]). - - * Spaces are no longer allowed between `@` and the name of a macro in a macro call ([#22868]). - - * Juxtaposition of a non-literal with a macro call (`x@macro`) is no longer valid syntax ([#22868]). - - * On a cluster, all files are now loaded from the local file system rather than node 1 ([#22588]). - To load the same file everywhere from node 1, one possible alternative is to broadcast a call to `include_string`: - `@everywhere include_string(Main, $(read("filename", String)), "filename")`. - Improving upon this API is left as an opportunity for packages. - - * `randperm(n)` and `randcycle(n)` now always return a `Vector{Int}` (independent of - the type of `n`). Use the corresponding mutating functions `randperm!` and `randcycle!` - to control the array type ([#22723]). - - * Hermitian now ignores any imaginary components in the diagonal instead of checking - the diagonal. ([#17367]) - - * Worker-worker connections are setup lazily for an `:all_to_all` topology. Use keyword - arg `lazy=false` to force all connections to be setup during a `addprocs` call. ([#22814]) - - * In `joinpath(a, b)` on Windows, if the drive specifications of `a` and `b` do not match, - `joinpath` now returns `b` instead of throwing an `ArgumentError`. `joinpath(path...)` is - defined to be left associative, so if any argument has a drive path which does not match - the drive of the join of the preceding paths, the prior ones are dropped. ([#20912]) - - * `^(A::AbstractMatrix{<:Integer}, p::Integer)` now throws a `DomainError` - if `p < 0`, unless `A == one(A)` or `A == -one(A)` (same as for - `^(A::Integer, p::Integer)`) ([#23366]). - - * `^(A::AbstractMatrix{<:Integer}, p::Integer)` now promotes the element type in the same - way as `^(A::Integer, p::Integer)`. This means, for instance, that `[1 1; 0 1]^big(1)` - will return a `Matrix{BigInt}` instead of a `Matrix{Int}` ([#23366]). - - * The element type of the input is now preserved in `unique`. Previously the element type - of the output was shrunk to fit the union of the type of each element in the input. - ([#22696]) - - * The `promote` function now raises an error if its arguments are of different types - and if attempting to convert them to a common type fails to change any of their types. - This avoids stack overflows in the common case of definitions like - `f(x, y) = f(promote(x, y)...)` ([#22801]). - - * `indmin` and `indmax` have been renamed to `argmin` and `argmax`, respectively ([#25654]). - - * `findmin`, `findmax`, `argmin`, and `argmax` used to always return linear indices. - They now return `CartesianIndex`es for all but 1-d arrays, and in general return - the `keys` of indexed collections (e.g. dictionaries) ([#22907]). - - * The `openspecfun` library is no longer built and shipped with Julia, as it is no longer - used internally ([#22390]). - - * All loaded packages used to have bindings in `Main` (e.g. `Main.Package`). This is no - longer the case; now bindings will only exist for packages brought into scope by - typing `using Package` or `import Package` ([#17997]). - - * The rules for mixed-signedness integer arithmetic (e.g. `Int32(1) + UInt64(1)`) have been - simplified: if the arguments have different sizes (in bits), then the type of the larger - argument is used. If the arguments have the same size, the unsigned type is used ([#9292]). - - * All command line arguments passed via `-e`, `-E`, and `-L` will be executed in the order - given on the command line ([#23665]). - - * `I` now yields `UniformScaling{Bool}(true)` rather than `UniformScaling{Int64}(1)` - to better preserve types in operations involving `I` ([#24396]). - - * The return type of `reinterpret` has changed to `ReinterpretArray`. `reinterpret` on sparse - arrays has been discontinued. - - * `Base.find_in_path` is now `Base.find_package` or `Base.find_source_file` ([#24320]). - - * `finalizer` now takes functions or pointers as its first argument, and the object being - finalized as its second (rather than the reverse). For the majority of use cases - deprecation warnings will be triggered. However, deprecation warnings will not trigger where - (1) the callable argument is not a subtype of `Function`; or (2) both arguments are - `Function`s or `Ptr{Cvoid}`s ([#24605]). - - * The `kill` function now throws errors on user error (e.g. on permission - errors), but returns successfully if the process had previously exited. - Its return value has been removed. Use the `process_running` function - to determine if a process has already exited. - - * The logging system has been redesigned - `info` and `warn` are deprecated - and replaced with the logging macros `@info`, `@warn`, `@debug` and - `@error`. The `logging` function is also deprecated and replaced with - `AbstractLogger` and the functions from the new standard `Logging` library. - ([#24490]) - - * The `RevString` type has been removed from the language; `reverse(::String)` returns - a `String` with code points (or fragments thereof) in reverse order. In general, - `reverse(s)` should return a string of the same type and encoding as `s` with code - points in reverse order; any string type overrides `reverse` to return a different - type of string must also override `reverseind` to compute reversed indices correctly. - - * `eachindex(A, B...)` now requires that all inputs have the same number of elements. - When the chosen indexing is Cartesian, they must have the same axes. - - * `AbstractRange` objects are now considered as equal to other `AbstractArray` objects - by `==` and `isequal` if all of their elements are equal ([#16401]). - This has required changing the hashing algorithm: ranges now use an O(N) fallback - instead of a O(1) specialized method unless they define the `Base.RangeStepStyle` - trait; see its documentation for details. Types which support subtraction (operator - `-`) must now implement `widen` for hashing to work inside heterogeneous arrays. - - * `findn(x::AbstractArray)` has been deprecated in favor of `findall(!iszero, x)`, which - now returns cartesian indices for multidimensional arrays (see below, [#25532]). - - * Broadcasting operations are no longer fused into a single operation by Julia's parser. - Instead, a lazy `Broadcasted` object is created to represent the fused expression and - then realized with `copy(bc::Broadcasted)` or `copyto!(dest, bc::Broadcasted)` - to evaluate the wrapper. Consequently, package authors generally need to specialize - `copy` and `copyto!` methods rather than `broadcast` and `broadcast!`. This also allows - for more customization and control of fused broadcasts. See the - [Interfaces chapter](https://docs.julialang.org/en/latest/manual/interfaces/#man-interfaces-broadcasting-1) - for more information. - - * `find` has been renamed to `findall`. `findall`, `findfirst`, `findlast`, `findnext` - now take and/or return the same type of indices as `keys`/`pairs` for `AbstractArray`, - `AbstractDict`, `AbstractString`, `Tuple` and `NamedTuple` objects ([#24774], [#25545]). - In particular, this means that they use `CartesianIndex` objects for matrices - and higher-dimensional arrays instead of linear indices as was previously the case. - Use `LinearIndices(a)[findall(f, a)]` and similar constructs to compute linear indices. - - * The `find*` functions, i.e. `findnext`, `findprev`, `findfirst`, - and `findlast`, as well as `indexin`, now return `nothing` when no match is found rather - than `0` or `0:-1` ([#25472], [#25662], [#26149]) - - * The `Base.HasShape` iterator trait has gained a type parameter `N` indicating the - number of dimensions, which must correspond to the length of the tuple returned by - `size` ([#25655]). - - * `AbstractSet` objects are now considered equal by `==` and `isequal` if all of their - elements are equal ([#25368]). This has required changing the hashing algorithm - for `BitSet`. - - * the default behavior of `titlecase` is changed in two ways ([#23393]): - + characters not starting a word are converted to lowercase; - a new keyword argument `strict` is added which - allows to get the old behavior when it's `false`. - + any non-letter character is considered as a word separator; - to get the old behavior (only "space" characters are considered as - word separators), use the keyword `wordsep=isspace`. - - * `writedlm` in the standard library module DelimitedFiles now writes numeric values - using `print` rather than `print_shortest` ([#25745]). - - * The `tempname` function used to create a file on Windows but not on other - platforms. It now never creates a file ([#9053]). - - * The `fieldnames` and `propertynames` functions now return a tuple rather than - an array ([#25725]). - - * `indexin` now returns the first rather than the last matching index ([#25998]). - - * `parse(::Type, ::Char)` now uses a default base of 10, like other number parsing - methods, instead of 36 ([#26576]). - - * `isequal` for `Ptr`s now compares element types; `==` still compares only addresses - ([#26858]). - - * `widen` on 8- and 16-bit integer types now widens to 16- and 32-bit types, respectively. ([#28045]). - - * `mv`,`cp`, `touch`, `mkdir`, `mkpath`, `chmod` and `chown` now return the path that was created/modified - rather than `nothing` ([#27071]). - - * Regular expressions now default to UCP mode. Escape sequences such as `\w` - will now match based on unicode character properties, e.g. `r"\w+"` will - match `café` (not just `caf`). Add the `a` modifier (e.g. `r"\w+"a`) to - restore the previous behavior ([#27189]). - - * `@sync` now waits only for *lexically* enclosed (i.e. visible directly in the source - text of its argument) `@async` expressions. If you need to wait for a task created by - a called function `f`, have `f` return the task and put `@async wait(f(...))` within - the `@sync` block. - This change makes `@schedule` redundant with `@async`, so `@schedule` has been - deprecated ([#27164]). - - * `norm(A::AbstractMatrix, p=2)` computes no longer the operator/matrix norm but the `norm` of `A` - as for other iterables, i.e. as if it were a vector. Especially, `norm(A::AbstractMatrix)` is the - Frobenius norm. To compute the operator/matrix norm, use the new function `opnorm` ([#27401]). - - * `dot(u, v)` now acts recursively. Instead of `sum(u[i]' * v[i] for i in ...)`, it computes - `sum(dot(u[i], v[i]) for i in ...)`, similarly to `vecdot` before ([#27401]). - - * `Sys.CPU_CORES` has been renamed to `Sys.CPU_THREADS`; it still gives the number - of "logical cores" (including hyperthreading) rather than the number of physical - cores present on the CPU. Similarly, the environment variable `JULIA_CPU_CORES` is - deprecated in favor of `JULIA_CPU_THREADS` ([#27856]). - - * `WeakKeyDict` does not convert keys on insertion anymore (#24941). - -Library improvements --------------------- - - * The function `thisind(s::AbstractString, i::Integer)` returns the largest valid index - less or equal than `i` in the string `s` or `0` if no such index exists ([#24414]). - - * Support for Unicode 11 ([#28266]). - - * `Char` is now a subtype of `AbstractChar`, and most of the functions that - take character arguments now accept any `AbstractChar` ([#26286]). - - * `pathof(module)` returns the path a module was imported from ([#28310]). - - * `bytes2hex` now accepts an optional `io` argument to output to a hexadecimal stream - without allocating a `String` first ([#27121]). - - * `String(array)` now accepts an arbitrary `AbstractVector{UInt8}`. For `Vector` - inputs, it "steals" the memory buffer, leaving them with an empty buffer which - is guaranteed not to be shared with the `String` object. For other types of vectors - (in particular immutable vectors), a copy is made and the input is not truncated ([#26093]). - - * `Irrational` is now a subtype of `AbstractIrrational` ([#24245]). - - * Introduced the `empty` function, the functional pair to `empty!` which returns a new, - empty container ([#24390]). - - * Jump to first/last history entries in the REPL via "Alt-<" and "Alt->" ([#22829]). - - * REPL LaTeX-like tab completions have been simplified for several Unicode characters, - e.g. `𝔸` is now `\bbA` rather than `\BbbA` ([#25980]). - - * The function `chop` now accepts two arguments `head` and `tail` allowing to specify - number of characters to remove from the head and tail of the string ([#24126]). - - * `get(io, :color, false)` can now be used to query whether a stream `io` supports - [ANSI color codes](https://en.wikipedia.org/wiki/ANSI_escape_code) ([#25067]), - rather than using the undocumented `Base.have_color` global flag. - - * `print_with_color` has been deprecated in favor of - `printstyled([io], xs...; bold=false, color=:normal)` for printing styled text ([#25522]). - - * Functions `first` and `last` now accept `nchar` argument for `AbstractString`. - If this argument is used they return a string consisting of first/last `nchar` - characters from the original string ([#23960]). - - * Expressions `x^-n` where `n` is an *integer literal* now correspond to `inv(x)^n`. - For example, `x^-1` is now essentially a synonym for `inv(x)`, and works - in a type-stable way even if `typeof(x) != typeof(inv(x))` ([#24240]). - - * New `Iterators.reverse(itr)` for reverse-order iteration ([#24187]). Iterator - types `T` can implement `start` etc. for `Iterators.Reverse{T}` to support this. - - * The functions `nextind` and `prevind` now accept `nchar` argument that indicates - the number of characters to move ([#23805]). - - * The functions `strip`, `lstrip` and `rstrip` now return `SubString` ([#22496]). - - * The functions `strwidth` and `charwidth` have been merged into `textwidth`([#20816]). - - * The functions `base` and `digits` digits now accept a negative - base (like `ndigits` did) ([#21692]). - - * The function `randn` now accepts complex arguments (`Complex{T <: AbstractFloat}`) - ([#21973]). - - * `parse(Complex{T}, string)` can parse complex numbers in some common formats ([#24713]). - - * The function `rand` can now pick up random elements from strings, associatives - and sets ([#22228], [#21960], [#18155], [#22224]). - - * It's now possible to specify the characters to pick from in the `randstring` function ([#22222]). - - * Allow multidimensional arrays in `shuffle` and `shuffle!` functions ([#22226]). - - * Method lists are now printed as a numbered list. In addition, the source code of a - method can be opened in an editor by entering the corresponding number in the REPL - and pressing `^Q` ([#22007]). - - * `getpeername` on a `TCPSocket` returns the address and port of the remote - endpoint of the TCP connection ([#21825]). - - * `resize!` and `sizehint!` methods no longer over-reserve memory when the - requested array size is more than double of its current size ([#22038]). - - * The `crc32c` function for CRC-32c checksums is now exported ([#22274]). - - * `eye(::Type{Diagonal{T}}, m::Integer)` has been deprecated in favor of - `Diagonal{T}(I, m)` ([#24413]). - - * The output of `versioninfo` is now controlled with keyword arguments ([#21974]). - - * The function `LibGit2.set_remote_url` now always sets both the fetch and push URLs for a - git repo. Additionally, the argument order was changed to be consistent with the git - command line tool ([#22062]). - - * Added `unique!` which is an inplace version of `unique` ([#20549]). - - * `@test isequal(x, y)` and `@test isapprox(x, y)` now prints an evaluated expression when - the test fails ([#22296]). - - * Uses of `Val{c}` in `Base` has been replaced with `Val{c}()`, which is now easily - accessible via the efficient constructor `Val(c)`. Functions are defined as - `f(::Val{c}) = ...` and called by `f(Val(c))`. Notable affected functions include: - `ntuple`, `Base.literal_pow`, `sqrtm`, `lufact`, `lufact!`, `qrfact`, `qrfact!`, - `cholfact`, `cholfact!`, `_broadcast!`, `reshape`, `cat` and `cat_t`. - - * A new `@macroexpand1` macro for non recursive macro expansion ([#21662]). - - * `Char`s can now be concatenated with `String`s and/or other `Char`s using `*` ([#22532]). - - * `Diagonal`, `Bidiagonal`, `Tridiagonal` and `SymTridiagonal` are now parameterized on - the type of the wrapped vectors, allowing `Diagonal`, `Bidiagonal`, `Tridiagonal` and - `SymTridiagonal` matrices with arbitrary `AbstractVector`s - ([#22718], [#22925], [#23035], [#23154]). - - * Mutating versions of `randperm` and `randcycle` have been added: - `randperm!` and `randcycle!` ([#22723]). - - * `BigFloat` random numbers can now be generated ([#22720]). - - * The efficiency of random generation for MersenneTwister RNGs has been improved for - integers, `Float64` and ranges; as a result, given a seed, the produced stream of numbers - has changed ([#27560], [#25277], [#25197], [#25058], [#25047]). - - * REPL Undo via Ctrl-/ and Ctrl-_ - - * `diagm` now accepts several diagonal index/vector `Pair`s ([#24047]). - - * `isequal`, `==`, and `in` have one argument "curried" forms. For example `isequal(x)` - returns a function that compares its argument to `x` using `isequal` ([#26436]). - - * `reinterpret` now works on any AbstractArray using the new `ReinterpretArray` type. - This supersedes the old behavior of reinterpret on Arrays. As a result, reinterpreting - arrays with different alignment requirements (removed in 0.6) is once again allowed ([#23750]). - - * The `keys` of an `Associative` are now an `AbstractSet`. `Base.KeyIterator{<:Associative}` - has been changed to `KeySet{K, <:Associative{K}} <: AbstractSet{K}` ([#24580]). - - * New function `ncodeunits(s::AbstractString)` gives the number of code units in a string. - The generic definition is constant time but calls `lastindex(s)` which may be inefficient. - Therefore custom string types may want to define direct `ncodeunits` methods. - - * `reverseind(s::AbstractString, i::Integer)` now has an efficient generic fallback, so - custom string types do not need to provide their own efficient definitions. The generic - definition relies on `ncodeunits` however, so for optimal performance you may need to - define a custom method for that function. - - * The global RNG is being re-seeded with its own seed at the beginning of each `@testset`, - and have its original state restored at the end ([#24445]). This is breaking for testsets - relying implicitly on the global RNG being in a specific state. - - * `permutedims(m::AbstractMatrix)` is now short for `permutedims(m, (2,1))`, and is now a - more convenient way of making a "shallow transpose" of a 2D array. This is the - recommended approach for manipulating arrays of data, rather than the recursively - defined, linear-algebra function `transpose`. Similarly, - `permutedims(v::AbstractVector)` will create a row matrix ([#24839]). - - * A new `replace(A, old=>new)` function is introduced to replace `old` by `new` in - collection `A`. There is also another method with a different API, and - a mutating variant, `replace!` ([#22324], [#25697], [#26206], [#27944]). - - * Adding integers to `CartesianIndex` objects is now deprecated. Instead of - `i::Int + x::CartesianIndex`, use `i*one(x) + x` ([#26284]). - - * `CartesianRange` changes ([#24715]): - - Inherits from `AbstractArray`, and linear indexing can be used to provide - linear-to-cartesian conversion ([#24715]) - - It has a new constructor taking an array - - * several missing set-like operations have been added ([#23528]): - `union`, `intersect`, `symdiff`, `setdiff` are now implemented for - all collections with arbitrary many arguments, as well as the - mutating counterparts (`union!` etc.). The performance is also - much better in many cases. Note that this change is slightly - breaking: all the non-mutating functions always return a new - object even if only one argument is passed. Moreover the semantics - of `intersect` and `symdiff` is changed for vectors: - + `intersect` doesn't preserve the multiplicity anymore (use `filter` for - the old behavior) - + `symdiff` has been made consistent with the corresponding methods for - other containers, by taking the multiplicity of the arguments into account. - Use `unique` to get the old behavior. - - * The `linearindices` function has been deprecated in favor of the new - `LinearIndices` type, which additionally provides conversion from - cartesian indices to linear indices using the normal indexing operation. - ([#24715], [#26775]). - - * `IdDict{K,V}` replaces `ObjectIdDict`. It has type parameters - like other `AbstractDict` subtypes and its constructors mirror the - ones of `Dict`. ([#25210]) - - * `IOBuffer` can take the `sizehint` keyword argument to suggest a capacity of - the buffer ([#25944]). - - * `lstrip` and `rstrip` now accept a predicate function that defaults to `isspace` - ([#27309]). - - * `trunc`, `floor`, `ceil`, and `round` specify `digits`, `sigdigits` and `base` using - keyword arguments. ([#26156], [#26670]) - - * `Sys.which()` provides a cross-platform method to find executable files, similar to - the Unix `which` command. ([#26559]) - - * Added an optimized method of `vecdot` for taking the Frobenius inner product - of sparse matrices. ([#27470]) - - * Added an optimized method of `kron` for taking the tensor product of two - `Diagonal` matrices. ([27581]) - - * An official API for extending `rand` is now defined ([#23964], [#25002]). - - * The constructor `MersenneTwister()` is re-enabled, producing a randomly initialized RNG - (similar to `Random.seed!(MersenneTwister(0))`) ([#21909]). - - * `BitSet` can now store any `Int` (instead of only positive ones) ([#25029]). - - * The initial element `v0` in `reduce(op, v0, itr)` has been replaced with an `init` - optional keyword argument, as in `reduce(op, itr; init=v0)`. Similarly for `foldl`, - `foldr`, `mapreduce`, `mapfoldl`, `mapfoldr`, `accumulate` and `accumulate!`. - ([#27711], [#27859]) - -Compiler/Runtime improvements ------------------------------ - - * The inlining heuristic now models the approximate runtime cost of - a method (using some strongly-simplifying assumptions). Functions - are inlined unless their estimated runtime cost substantially - exceeds the cost of setting up and issuing a subroutine - call. ([#22210], [#22732]) - - * Inference recursion-detection heuristics are now more precise, - allowing them to be triggered less often, but being more aggressive when they - are triggered to drive the inference computation to a solution ([#23912]). - - * Inference now propagates constants inter-procedurally, and can compute - various constants expressions at compile-time ([#24362]). - - * The LLVM SLP Vectorizer optimization pass is now enabled at the default - optimization level. - -Deprecated or removed ---------------------- - - * The `JULIA_HOME` environment variable has been renamed to `JULIA_BINDIR` and - `Base.JULIA_HOME` has been moved to `Sys.BINDIR` ([#20899]). - - * The keyword `immutable` is fully deprecated to `struct`, and - `type` is fully deprecated to `mutable struct` ([#19157], [#20418]). - - * `lufact`, `schurfact`, `lqfact`, `qrfact`, `ldltfact`, `svdfact`, - `bkfact`, `hessfact`, `eigfact`, and `cholfact` have respectively been - deprecated to `lu`, `schur`, `lq`, `qr`, `ldlt`, `svd`, `bunchkaufman`, - `hessenberg`, `eigen`, and `cholesky` ([#26997], [#27159], [#27212]). - - * `lufact!`, `schurfact!`, `lqfact!`, `qrfact!`, `ldltfact!`, `svdfact!`, - `bkfact!`, `hessfact!`, and `eigfact!` have respectively been deprecated to - `lu!`, `schur!`, `lq!`, `qr!`, `ldlt!`, `svd!`, `bunchkaufman!`, - `hessenberg!`, and `eigen!` ([#26997], [#27159], [#27212]). - - * `eig(A[, args...])` has been deprecated in favor of `eigen(A[, args...])`. - Whereas the former returns a tuple of arrays, the latter returns an `Eigen` object. - So for a direct replacement, use `(eigen(A[, args...])...,)`. But going forward, - consider using the direct result of `eigen(A[, args...])` instead, either - destructured into its components (`vals, vecs = eigen(A[, args...])`) or - as an `Eigen` object (`X = eigen(A[, args...])`) ([#26997], [#27159], [#27212]). - - * `eig(A::AbstractMatrix, B::AbstractMatrix)` and `eig(A::Number, B::Number)` - have been deprecated in favor of `eigen(A, B)`. Whereas the former each return - a tuple of arrays, the latter returns a `GeneralizedEigen` object. So for a direct - replacement, use `(eigen(A, B)...,)`. But going forward, consider using the - direct result of `eigen(A, B)` instead, either destructured into its components - (`vals, vecs = eigen(A, B)`), or as a `GeneralizedEigen` object - (`X = eigen(A, B)`) ([#26997], [#27159], [#27212]). - - * `ordschur(T::StridedMatrix{Ty}, Z::StridedMatrix{Ty}, select::Union{Vector{Bool},BitVector})` - and `ordschur(S::StridedMatrix{Ty}, T::StridedMatrix{Ty}, Q::StridedMatrix{Ty}, - Z::StridedMatrix{Ty}, select::Union{Vector{Bool},BitVector})` and their respective - inplace versions have been deprecated. - Use `ordschur(schur::Schur, select::Union{Vector{Bool},BitVector})` and - `ordschur(gschur::GeneralizedSchur, select::Union{Vector{Bool},BitVector})` instead - ([#28155]). - - * Indexing into multidimensional arrays with more than one index but fewer indices than there are - dimensions is no longer permitted when those trailing dimensions have lengths greater than 1. - Instead, reshape the array or add trailing indices so the dimensionality and number of indices - match ([#14770], [#23628]). - - * The use of a positional dimension argument has largely been deprecated in favor of a - `dims` keyword argument. This includes the functions `sum`, `prod`, `maximum`, - `minimum`, `all`, `any`, `findmax`, `findmin`, `mean`, `varm`, `std`, `var`, `cov`, - `cor`, `median`, `mapreducedim`, `reducedim`, `sort`, `accumulate`, `accumulate!`, - `cumsum`, `cumsum!`, `cumprod`, `cumprod!`, `flipdim`, `dropdims`, and `cat` ([#25501], [#26660], [#27100]). - - * `indices(a)` and `indices(a,d)` have been deprecated in favor of `axes(a)` and - `axes(a, d)` ([#25057]). - - * `EnvHash` has been renamed to `EnvDict` ([#24167]). - - * Uninitialized `Array` constructors of the form - `Array[{T,N}](shape...)` have been deprecated in favor of equivalents - accepting `undef` (an alias for `UndefInitializer()`) as their first argument, - as in `Array[{T,N}](undef, shape...)`. For example, - `Vector(3)` is now `Vector(undef, 3)`, `Matrix{Int}((2, 4))` is now, - `Matrix{Int}(undef, (2, 4))`, and `Array{Float32,3}(11, 13, 17)` is now - `Array{Float32,3}(undef, 11, 13, 17)` ([#24781]). - - * Previously `setindex!(A, x, I...)` (and the syntax `A[I...] = x`) supported two - different modes of operation when supplied with a set of non-scalar indices `I` - (e.g., at least one index is an `AbstractArray`) depending upon the value of `x` - on the right hand side. If `x` is an `AbstractArray`, its _contents_ are copied - elementwise into the locations in `A` selected by `I` and it must have the same - number of elements as `I` selects locations. Otherwise, if `x` is not an - `AbstractArray`, then its _value_ is implicitly broadcast to all locations to - all locations in `A` selected by `I`. This latter behavior—implicitly broadcasting - "scalar"-like values across many locations—is now deprecated in favor of explicitly - using the broadcasted assignment syntax `A[I...] .= x` or `fill!(view(A, I...), x)` - ([#26347]). - - * `broadcast_getindex(A, I...)` and `broadcast_setindex!(A, v, I...)` are deprecated in - favor of `getindex.((A,), I...)` and `setindex!.((A,), v, I...)`, respectively ([#27075]). - - * `LinAlg.fillslots!` has been renamed `LinAlg.fillstored!` ([#25030]). - - * `fill!(A::Diagonal, x)` and `fill!(A::AbstractTriangular, x)` have been deprecated - in favor of `Base.LinAlg.fillstored!(A, x)` ([#24413]). - - * `eye` has been deprecated in favor of `I` and `Matrix` constructors. Please see the - deprecation warnings for replacement details ([#24438]). - - * `zeros(D::Diagonal[, opts...])` has been deprecated ([#24654]). - - * Using Bool values directly as indices is now deprecated and will be an error in the future. Convert - them to `Int` before indexing if you intend to access index `1` for `true` and `0` for `false`. - - * `slicedim(A, d, i)` has been deprecated in favor of `copy(selectdim(A, d, i))`. The new - `selectdim` function now always returns a view into `A`; in many cases the `copy` is - not necessary. Previously, `slicedim` on a vector `V` over dimension `d=1` and scalar - index `i` would return the just selected element (unless `V` was a `BitVector`). This - has now been made consistent: `selectdim` now always returns a view into the original - array, with a zero-dimensional view in this specific case ([#26009]). - - * `whos` has been renamed `varinfo`, and now returns a markdown table instead of printing - output ([#12131]). - - * Uninitialized `RowVector` constructors of the form `RowVector{T}(shape...)` have been - deprecated in favor of equivalents accepting `undef` (an alias for - `UndefInitializer()`) as their first argument, as in - `RowVector{T}(undef, shape...)`. For example, `RowVector{Int}(3)` is now - `RowVector{Int}(undef, 3)`, and `RowVector{Float32}((1, 4))` is now - `RowVector{Float32}(undef, (1, 4))` ([#24786]). - - * `writecsv(io, a; opts...)` has been deprecated in favor of - `writedlm(io, a, ','; opts...)` ([#23529]). - - * The method `srand(rng, filename, n=4)` has been deprecated ([#21359]). - - * `readcsv(io[, T::Type]; opts...)` has been deprecated in favor of - `readdlm(io, ','[, T]; opts...)` ([#23530]). - - * `sparse(s::UniformScaling, m::Integer)` has been deprecated in favor of the - three-argument equivalent `sparse(s::UniformScaling, m, n)` ([#24472]). - - * The `cholfact`/`cholfact!` methods that accepted an `uplo` symbol have been deprecated - in favor of using `Hermitian` (or `Symmetric`) views ([#22187], [#22188]). - - * The `thin` keyword argument for orthogonal decomposition methods has - been deprecated in favor of `full`, which has the opposite meaning: - `thin == true` if and only if `full == false` ([#24279]). - - * `isposdef(A::AbstractMatrix, UL::Symbol)` and `isposdef!(A::AbstractMatrix, UL::Symbol)` - have been deprecated in favor of `isposdef(Hermitian(A, UL))` and `isposdef!(Hermitian(A, UL))` - respectively ([#22245]). - - * The `bkfact`/`bkfact!` methods that accepted `uplo` and `issymmetric` symbols have been deprecated - in favor of using `Hermitian` (or `Symmetric`) views ([#22605]). - - * The function `current_module` is deprecated and replaced with `@__MODULE__`. - This caused the deprecation of some reflection methods (such as `macroexpand` and - `isconst`), which now require a module argument. And it caused the bugfix of other - default arguments to use the Main module (including `whos`, `which`) ([#22064]). - - * `expand(ex)` and `expand(module, ex)` have been deprecated in favor of - `Meta.lower(module, ex)` ([#22064], [#24278]). - - * `ones(A::AbstractArray[, opts...])` and `zeros(A::AbstractArray[, opts...])` methods - have been deprecated. For `zeros(A)`, consider `zero(A)`. For `ones(A)` or `zeros(A)`, - consider `ones(size(A))`, `zeros(size(A))`, `fill(v, size(A))` for `v` an appropriate - one or zero, `fill!(copy(A), {1|0})`, `fill!(similar(A), {1|0})`, or any of the preceding - with different element type and/or shape depending on `opts...`. Where strictly - necessary, consider `fill!(similar(A[, opts...]), {one(eltype(A)) | zero(eltype(A))})`. - For an algebraic multiplicative identity, consider `one(A)` ([#24656]). - - * The `similar(dims->f(..., dims...), [T], axes...)` method to add offset array support - to a function `f` that would otherwise create a non-offset array has been deprecated. - Instead, call `f(..., axes...)` directly and, if needed, the offset array implementation - should add offset axis support to the function `f` directly ([#26733]). - - * The functions `ones` and `zeros` used to accept any objects as dimensional arguments, - implicitly converting them to `Int`s. This is now deprecated; only `Integer`s or - `AbstractUnitRange`s are accepted as arguments. Instead, convert the arguments before - calling `ones` or `zeros` ([#26733]). - - * The variadic `size(A, dim1, dim2, dims...)` method to return a tuple of multiple - dimension lengths of `A` has been deprecated ([#26862]). - - * The `Operators` module is deprecated. Instead, import required operators explicitly - from `Base`, e.g. `import Base: +, -, *, /` ([#22251]). - - * Bindings to the FFTW library have been removed from Base. The DFT framework for building FFT - implementations is now in AbstractFFTs.jl, the bindings to the FFTW library are in FFTW.jl, - and the Base signal processing functions which used FFTs are now in DSP.jl ([#21956]). - - * The `corrected` positional argument to `cov` has been deprecated in favor of - a keyword argument with the same name ([#21709]). - - * Omitting spaces around the `?` and the `:` tokens in a ternary expression has been deprecated. - Ternaries must now include some amount of whitespace, e.g. `x ? a : b` rather than - `x?a:b` ([#22523] and [#22712]). - - * `?` can no longer be used as an identifier name ([#22712]) - - * The method `replace(s::AbstractString, pat, r, [count])` is deprecated - in favor of `replace(s::AbstractString, pat => r; [count])` ([#25165]). - Moreover, `count` cannot be negative anymore (use `typemax(Int)` instead ([#22325]). - - * `read(io, type, dims)` is deprecated to `read!(io, Array{type}(undef, dims))` ([#21450]). - - * `read(::IO, ::Ref)` is now a method of `read!`, since it mutates its `Ref` argument ([#21592]). - - * `nb_available` is now `bytesavailable` ([#25634]). - - * `skipchars(io::IO, predicate; linecomment=nothing)` is deprecated in favor of - `skipchars(predicate, io::IO; linecomment=nothing)` ([#25667]). - - * `Bidiagonal` constructors now use a `Symbol` (`:U` or `:L`) for the upper/lower - argument, instead of a `Bool` or a `Char` ([#22703]). - - * `Bidiagonal`, `Tridiagonal` and `SymTridiagonal` constructors that automatically - converted the input vectors to the same type are deprecated in favor of explicit - conversion ([#22925], [#23035], [#23154]. - - * Calling `nfields` on a type to find out how many fields its instances have is deprecated. - Use `fieldcount` instead. Use `nfields` only to get the number of fields in a specific object ([#22350]). - - * `fieldnames` now operates only on types. To get the names of fields in an object, use - `fieldnames(typeof(x))` ([#22350]). - - * `InexactError`, `DomainError`, and `OverflowError` now take - arguments. `InexactError(func::Symbol, type, -3)` now prints as - "ERROR: InexactError: func(type, -3)", `DomainError(val, - [msg])` prints as "ERROR: DomainError with val:\nmsg", - and `OverflowError(msg)` prints as "ERROR: OverflowError: msg". - ([#20005], [#22751], [#22761]) - - * The operating system identification functions: `is_linux`, `is_bsd`, `is_apple`, `is_unix`, - and `is_windows`, have been deprecated in favor of `Sys.islinux`, `Sys.isbsd`, `Sys.isapple`, - `Sys.isunix`, and `Sys.iswindows`, respectively ([#22182]). - - * The forms of `read`, `readstring`, and `eachline` that accepted both a `Cmd` object and an - input stream are deprecated. Use e.g. `read(pipeline(stdin, cmd))` instead ([#22762]). - - * The unexported type `AbstractIOBuffer` has been renamed to `GenericIOBuffer` ([#17360] [#22796]). - - * `IOBuffer(data::AbstractVector{UInt8}, read::Bool, write::Bool, maxsize::Integer)`, - `IOBuffer(read::Bool, write::Bool)`, and `IOBuffer(maxsize::Integer)` are - deprecated in favor of constructors taking keyword arguments ([#25872]). - - * `Display` has been renamed to `AbstractDisplay` ([#24831]). - - * Remaining vectorized methods over `SparseVector`s, particularly `floor`, `ceil`, - `trunc`, `round`, and most common transcendental functions such as `exp`, `log`, and - `sin` variants, have been deprecated in favor of dot-syntax ([#22961]). - - * The method `String(io::IOBuffer)` is deprecated to `String(take!(copy(io)))` ([#21438]). - - * The function `readstring` is deprecated in favor of `read(io, String)` ([#22793]) - - * The function `showall` is deprecated. Showing entire values is the default, unless an - `IOContext` specifying `:limit=>true` is in use ([#22847]). - - * `issubtype` has been deprecated in favor of `<:` (which used to be an alias for `issubtype`). - - * Calling `write` on non-isbits arrays is deprecated in favor of explicit loops or - `serialize` ([#6466]). - - * The default `startup.jl` file on Windows has been removed. Now must explicitly include the - full path if you need access to executables or libraries in the `Sys.BINDIR` directory, e.g. - `joinpath(Sys.BINDIR, "7z.exe")` for `7z.exe` ([#21540]). - - * `sqrtm` has been deprecated in favor of `sqrt` ([#23504]). - - * `expm` has been deprecated in favor of `exp` ([#23233]). - - * `logm` has been deprecated in favor of `log` ([#23505]). - - * `full` has been deprecated in favor of more specific, better defined alternatives. - On structured matrices `A`, consider instead `Matrix(A)`, `Array(A)`, - `SparseMatrixCSC(A)`, or `sparse(A)`. On sparse arrays `S`, consider instead - `Vector(S)`, `Matrix(S)`, or `Array(S)` as appropriate. On factorizations `F`, - consider instead `Matrix(F)`, `Array(F)`, `AbstractMatrix(F)`, or `AbstractArray(F)`. - On implicit orthogonal factors `Q`, consider instead `Matrix(Q)` or `Array(Q)`; for - implicit orthogonal factors that can be recovered in square or truncated form, - see the deprecation message for square recovery instructions. On `Symmetric`, - `Hermitian`, or `AbstractTriangular` matrices `A`, consider instead `Matrix(S)`, - `Array(S)`, `SparseMatrixCSC(S)`, or `sparse(S)`. On `Symmetric` matrices `A` - particularly, consider instead `LinAlg.copytri!(copy(parent(A)), A.uplo)`. On - `Hermitian` matrices `A` particularly, consider instead - `LinAlg.copytri!(copy(parent(A)), A.uplo, true)`. On `UpperTriangular` matrices `A` - particularly, consider instead `triu!(copy(parent(A)))`. On `LowerTriangular` matrices - `A` particularly, consider instead `tril!(copy(parent(A)))` ([#24250]). - - * `speye` has been deprecated in favor of `I`, `sparse`, and `SparseMatrixCSC` - constructor methods ([#24356]). - - * Calling `union` with no arguments is deprecated; construct an empty set with an appropriate - element type using `Set{T}()` instead ([#23144]). - - * Vectorized `DateTime`, `Date`, and `format` methods have been deprecated in favor of - dot-syntax ([#23207]). - - * `Base.cpad` has been removed; use an appropriate combination of `rpad` and `lpad` - instead ([#23187]). - - * `ctranspose` and `ctranspose!` have been deprecated in favor of `adjoint` and `adjoint!`, - respectively ([#23235]). - - * `filter` and `filter!` on dictionaries now pass a single `key=>value` pair to the - argument function, instead of two arguments ([#17886]). - - * `rol`, `rol!`, `ror`, and `ror!` have been deprecated in favor of specialized methods for - `circshift`/`circshift!` ([#23404]). - - * `Base.SparseArrays.SpDiagIterator` has been removed ([#23261]). - - * The function `cfunction`, has been deprecated in favor of a macro form `@cfunction`. - Most existing uses can be upgraded simply by adding a `@`. - The new syntax now additionally supports allocating closures at runtime, - for dealing with C APIs that don't provide a separate `void* env`-type callback - argument. ([#26486]) - - * `diagm(v::AbstractVector, k::Integer=0)` has been deprecated in favor of - `diagm(k => v)` ([#24047]). - - * `diagm(x::Number)` has been deprecated in favor of `fill(x, 1, 1)` ([#24047]). - - * `diagm(A::SparseMatrixCSC)` has been deprecated in favor of - `spdiagm(sparsevec(A))` ([#23341]). - - * `diagm(A::BitMatrix)` has been deprecated, use `diagm(0 => vec(A))` or - `BitMatrix(Diagonal(vec(A)))` instead ([#23373], [#24047]). - - * `ℯ` (written as `\mscre` or `\euler`) is now the only (by default) exported - name for Euler's number, and the type has changed from `Irrational{:e}` to - `Irrational{:ℯ}` ([#23427]). - - * The mathematical constants `π`, `pi`, `ℯ`, `e`, `γ`, `eulergamma`, `catalan`, `φ` and - `golden` have been moved from `Base` to a new module; `Base.MathConstants`. - Only `π`, `pi` and `ℯ` are now exported by default from `Base` ([#23427]). - - * `eu` (previously an alias for `ℯ`) has been deprecated in favor of `ℯ` (or `MathConstants.e`) ([#23427]). - - * `GMP.gmp_version()`, `GMP.GMP_VERSION`, `GMP.gmp_bits_per_limb()`, and `GMP.GMP_BITS_PER_LIMB` - have been renamed to `GMP.version()`, `GMP.VERSION`, `GMP.bits_per_limb()`, and `GMP.BITS_PER_LIMB`, - respectively. Similarly, `MPFR.get_version()`, has been renamed to `MPFR.version()` ([#23323]). Also, - `LinAlg.LAPACK.laver()` has been renamed to `LinAlg.LAPACK.version()` and now returns a `VersionNumber`. - - * `select`, `select!`, `selectperm` and `selectperm!` have been renamed respectively to - `partialsort`, `partialsort!`, `partialsortperm` and `partialsortperm!` ([#23051]). - - * The `Range` abstract type has been renamed to `AbstractRange` ([#23570]). - - * `map` on dictionaries previously operated on `key=>value` pairs. This behavior is deprecated, - and in the future `map` will operate only on values ([#5794]). - - * `map` on sets previously returned a `Set`, possibly changing the order or number of elements. This - behavior is deprecated and in the future `map` will preserve order and number of elements ([#26980]). - - * Previously, broadcast defaulted to treating its arguments as scalars if they were not - arrays. This behavior is deprecated, and in the future `broadcast` will default to - iterating over all its arguments. Wrap arguments you wish to be treated as scalars with - `Ref()` or a 1-tuple. Package developers can choose to allow a non-iterable type `T` to - always behave as a scalar by implementing `broadcastable(x::T) = Ref(x)` ([#26212]). - - * Automatically broadcasted `+` and `-` for `array + scalar`, `scalar - array`, and so-on have - been deprecated due to inconsistency with linear algebra. Use `.+` and `.-` for these operations - instead ([#22880], [#22932]). - - * `flipbits!(B)` is deprecated in favor of using in-place broadcast to negate each element: - `B .= .!B` ([#27067]). - - * `isleaftype` is deprecated in favor of the simpler predicates `isconcretetype` and `isdispatchtuple`. - Concrete types are those that might equal `typeof(x)` for some `x`; - `isleaftype` included some types for which this is not true. Those are now categorized more precisely - as "dispatch tuple types" and "!has_free_typevars" (not exported). ([#17086], [#25496]) - - * `contains(eq, itr, item)` is deprecated in favor of `any` with a predicate ([#23716]). - - * `spdiagm(x::AbstractVector)` has been deprecated in favor of `sparse(Diagonal(x))` - alternatively `spdiagm(0 => x)` ([#23757]). - - * `spdiagm(x::AbstractVector, d::Integer)` and `spdiagm(x::Tuple{<:AbstractVector}, d::Tuple{<:Integer})` - have been deprecated in favor of `spdiagm(d => x)` and `spdiagm(d[1] => x[1], d[2] => x[2], ...)` - respectively. The new `spdiagm` implementation now always returns a square matrix ([#23757]). - - * `spones(A::AbstractSparseArray)` has been deprecated in favor of - `LinAlg.fillstored!(copy(A), 1)` ([#25037]). - - * Constructors for `LibGit2.UserPasswordCredentials` and `LibGit2.SSHCredentials` which take a - `prompt_if_incorrect` argument are deprecated. Instead, prompting behavior is controlled using - the `allow_prompt` keyword in the `LibGit2.CredentialPayload` constructor ([#23690]). - - * `gradient` is deprecated and will be removed in the next release ([#23816]). - - * The timing functions `tic`, `toc`, and `toq` are deprecated in favor of `@time` and `@elapsed` - ([#17046]). - - * Methods of `findfirst`, `findnext`, `findlast`, and `findprev` that accept a value to - search for are deprecated in favor of passing a predicate ([#19186], [#10593]). - - * `find` functions now operate only on booleans by default. To look for non-zeros, use - `x->x!=0` or `!iszero` ([#23120]). - - * The ability of `reinterpret` to yield `Array`s of different type than the underlying storage - has been removed. The `reinterpret` function is still available, but now returns a - `ReinterpretArray`. The three argument form of `reinterpret` that implicitly reshapes - has been deprecated ([#23750]). - - * `bits` has been deprecated in favor of `bitstring` ([#24281], [#24263]). - - * `num2hex` and `hex2num` have been deprecated in favor of `reinterpret` combined with `parse`/`hex` ([#22088]). - - * `copy!` is deprecated for `AbstractSet` and `AbstractDict`, with the intention to re-enable - it with a cleaner meaning in a future version ([#24844]). - - * `copy!` (resp. `unsafe_copy!`) is deprecated for `AbstractArray` and is renamed `copyto!` - (resp. `unsafe_copyto!`); it will be re-introduced with a different meaning in a future - version ([#24808]). - - * `a:b` is deprecated for constructing a `StepRange` when `a` and `b` have physical units - (Dates and Times). Use `a:s:b`, where `s = Dates.Day(1)` or `s = Dates.Second(1)`. - - * `trues(A::AbstractArray)` and `falses(A::AbstractArray)` are deprecated in favor of - `trues(size(A))` and `falses(size(A))` respectively ([#24595]). - - * `workspace` is discontinued, check out [Revise.jl](https://github.com/timholy/Revise.jl) - for an alternative workflow ([#25046]). - - * `cumsum`, `cumprod`, `accumulate`, their mutating versions, and `diff` all now require a `dim` - argument instead of defaulting to using the first dimension unless there is only - one dimension ([#24684], [#25457]). - - * The `sum_kbn` and `cumsum_kbn` functions have been moved to the - [KahanSummation](https://github.com/JuliaMath/KahanSummation.jl) package ([#24869]). - - * `isnumber` has been renamed to `isnumeric` ([#25021]). - - * `isalpha` has been renamed to `isletter` ([#26932]). - - * `is_assigned_char` and `normalize_string` have been renamed to `isassigned` and - `normalize`, and moved to the new `Unicode` standard library module. - `graphemes` has also been moved to that module ([#25021]). - - * Sparse array functionality has moved to the `SparseArrays` standard library module ([#25249]). - - * Linear algebra functionality, and specifically the `LinAlg` module has moved to the - `LinearAlgebra` standard library module ([#25571]). - - * `@printf` and `@sprintf` have been moved to the `Printf` standard library ([#23929],[#25056]). - - * The `Libdl` module has moved to the `Libdl` standard library module ([#25459]). - - * The aliases `Complex32`, `Complex64` and `Complex128` have been deprecated in favor of `ComplexF16`, - `ComplexF32` and `ComplexF64` respectively ([#24647]). - - * `Base.parentindexes` and `SharedArrays.localindexes` have been renamed to `parentindices` - and `localindices`, respectively. Similarly, the `indexes` field in the `SubArray` type - has been renamed to `indices` without deprecation ([#25088]). - - * `Associative` has been deprecated in favor of `AbstractDict` ([#25012]). - - * `Void` has been renamed back to `Nothing` with an alias `Cvoid` for use when calling C - with a return type of `Cvoid` or a return or argument type of `Ptr{Cvoid}` ([#25162]). - - * `Nullable{T}` has been deprecated and moved to the Nullables package ([#23642]). Use - `Union{T, Nothing}` instead, or `Union{Some{T}, Nothing}` if `nothing` is a possible - value (i.e. `Nothing <: T`). `isnull(x)` can be replaced with `x === nothing` and - `unsafe_get`/`get` can be dropped or replaced with `coalesce`. - `NullException` has been removed. - - * `unshift!` and `shift!` have been renamed to `pushfirst!` and `popfirst!` ([#23902]) - - * `ipermute!` has been deprecated in favor of `invpermute!` ([#25168]). - - * `CartesianRange` has been renamed `CartesianIndices` ([#24715]). - - * `sub2ind` and `ind2sub` are deprecated in favor of using `CartesianIndices` and `LinearIndices` ([#24715]). - - * `getindex(F::Factorization, s::Symbol)` (usually seen as e.g. `F[:Q]`) is deprecated - in favor of dot overloading (`getproperty`) so factors should now be accessed as e.g. - `F.Q` instead of `F[:Q]` ([#25184]). - - * `search` and `rsearch` have been deprecated in favor of `findfirst`/`findnext` and - `findlast`/`findprev` respectively, in combination with curried `isequal` and `in` - predicates for some methods ([#24673]). - - * `search(buf::IOBuffer, delim::UInt8)` has been deprecated in favor of either `occursin(delim, buf)` - (to test containment) or `readuntil(buf, delim)` (to read data up to `delim`) ([#26600]). - - * `ismatch(regex, str)` has been deprecated in favor of `contains(str, regex)` ([#24673]). - - * `matchall` has been deprecated in favor of `collect(m.match for m in eachmatch(r, s))` ([#26071]). - - * `similar(::Associative)` has been deprecated in favor of `empty(::Associative)`, and - `similar(::Associative, ::Pair{K, V})` has been deprecated in favour of - `empty(::Associative, K, V)` ([#24390]). - - * `findin(a, b)` has been deprecated in favor of `findall(in(b), a)` ([#24673]). - - * `module_name` has been deprecated in favor of a new, general `nameof` function. Similarly, - the unexported `Base.function_name` and `Base.datatype_name` have been deprecated in favor - of `nameof` methods ([#25622]). - - * The module `Random.dSFMT` is renamed `Random.DSFMT` ([#25567]). - - * `Random.RandomDevice(unlimited::Bool)` (on non-Windows systems) is deprecated in favor of - `Random.RandomDevice(; unlimited=unlimited)` ([#25668]). - - * The generic implementations of `strides(::AbstractArray)` and `stride(::AbstractArray, ::Int)` - have been deprecated. Subtypes of `AbstractArray` that implement the newly introduced strided - array interface should define their own `strides` method ([#25321]). - - * `module_parent`, `Base.datatype_module`, and `Base.function_module` have been deprecated - in favor of `parentmodule` ([#TODO]). - - * `rand(t::Tuple{Vararg{Int}})` is deprecated in favor of `rand(Float64, t)` or `rand(t...)`; - `rand(::Tuple)` will have another meaning in the future ([#25429], [#25278]). - - * `randjump`, which produced an array, is deprecated in favor of the - scalar version `Future.randjump` used with `accumulate` ([#27746]). - - * The `assert` function (and `@assert` macro) have been documented that they are not guaranteed to run under various optimization levels and should therefore not be used to e.g. verify passwords. - - * `ObjectIdDict` has been deprecated in favor of `IdDict{Any,Any}` ([#25210]). - - * `gc` and `gc_enable` have been deprecated in favor of `GC.gc` and `GC.enable` ([#25616]). - - * `Base.@gc_preserve` has been deprecated in favor of `GC.@preserve` ([#25616]). - - * `print_shortest` has been discontinued, but is still available in the `Base.Grisu` - submodule ([#25745]). - - * `scale!` has been deprecated in favor of `mul!`, `lmul!`, and `rmul!` ([#25701], [#25812]). - - * The `remove_destination` keyword argument to `cp`, `mv`, and the unexported `cptree` - has been renamed to `force` ([#25979]). - - * `contains` has been deprecated in favor of a more general `occursin` function, which - takes its arguments in reverse order from `contains` ([#26283]). - - * `Regex` objects are no longer callable. Use `occursin` instead ([#26283]). - - * The methods of `range` based on positional arguments have been deprecated in favor of - keyword arguments ([#25896]). - - * `linspace` has been deprecated in favor of `range` with `stop` and `length` keyword - arguments ([#25896]). - - * `LinSpace` has been renamed to `LinRange` ([#25896]). - - * `logspace` has been deprecated to its definition ([#25896]). - - * `endof(a)` has been renamed to `lastindex(a)`, and the `end` keyword in indexing expressions now - lowers to either `lastindex(a)` (in the case with only one index) or `lastindex(a, d)` (in cases - where there is more than one index and `end` appears at dimension `d`) ([#23554], [#25763]). - - * `DateTime()`, `Date()`, and `Time()` have been deprecated, instead use `DateTime(1)`, `Date(1)` - and `Time(0)` respectively ([#23724]). - - * The fallback method `^(x, p::Integer)` is deprecated. If your type relied on this definition, - add a method such as `^(x::MyType, p::Integer) = Base.power_by_squaring(x, p)` ([#23332]). - - * `DevNull`, `STDIN`, `STDOUT`, and `STDERR` have been renamed to `devnull`, `stdin`, `stdout`, - and `stderr`, respectively ([#25786]). - - * `wait` and `fetch` on `Task` now resemble the interface of `Future`. - - * `showcompact(io, x...)` has been deprecated in favor of - `show(IOContext(io, :compact => true), x...)` ([#26080]). - Use `sprint(show, x..., context=:compact => true)` instead of `sprint(showcompact, x...)`. - - * `isupper`, `islower`, `ucfirst` and `lcfirst` have been deprecated in favor of `isuppercase`, - `islowercase`, `uppercasefirst` and `lowercasefirst`, respectively ([#26442]). - - * `signif` has been deprecated in favor of the `sigdigits` keyword argument to `round`. - - * `Base.IntSet` has been deprecated in favor of `Base.BitSet` ([#24282]). - - * `setrounding` has been deprecated for `Float32` and `Float64`, as the behaviour was too unreliable ([#26935]). - - * `gamma`, `lgamma`, `beta`, `lbeta` and `lfact` have been moved to - [SpecialFunctions.jl](https://github.com/JuliaMath/SpecialFunctions.jl) ([#27459], [#27473]). - - * `atan2` is now a 2-argument method of `atan` ([#27248]). - - * The functions `eigs` and `svds` have been moved to the `Arpack.jl` package ([#27616]). - - * `vecdot` and `vecnorm` are deprecated in favor of `dot` and `norm`, respectively ([#27401]). - - * `clipboard` has been moved to the `InteractiveUtils` standard library package - (along with other utilities mostly used at the interactive prompt, such as `edit` - and `less`) ([#27635]). - - * `ndigits(n, b, [pad])` is deprecated in favor of `ndigits(n, base=b, pad=pad)` ([#27908]). - - * `squeeze` is deprecated in favor of `dropdims`. - - * `srand` is deprecated in favor of the unexported `Random.seed!` ([#27726]). - - * `realmin`/`realmax` are deprecated in favor of `floatmin`/`floatmax` ([#28302]). - - * `sortrows`/`sortcols` have been deprecated in favor of the more general `sortslices`. - - * `nextpow2`/`prevpow2` have been deprecated in favor of the more general `nextpow`/`prevpow` functions. - -Command-line option changes ---------------------------- - - * New option `--warn-overwrite={yes|no}` to control the warning for overwriting method - definitions. The default is `no` ([#23002]). - - * New option `--banner={yes,no}` allows suppressing or forcing the printing of the - startup banner, overriding the default behavior (banner in REPL, no banner otherwise). - The `--quiet` option implies `--banner=no` even in REPL mode but can be overridden by - passing `--quiet` together with `--banner=yes` ([#23342]). - - * The option `--precompiled` has been renamed to `--sysimage-native-code` ([#23054]). - - * The option `--compilecache` has been renamed to `--compiled-modules` ([#23054]). - - -[#330]: https://github.com/JuliaLang/julia/issues/330 -[#1974]: https://github.com/JuliaLang/julia/issues/1974 -[#4916]: https://github.com/JuliaLang/julia/issues/4916 -[#5148]: https://github.com/JuliaLang/julia/issues/5148 -[#5794]: https://github.com/JuliaLang/julia/issues/5794 -[#6080]: https://github.com/JuliaLang/julia/issues/6080 -[#6466]: https://github.com/JuliaLang/julia/issues/6466 -[#6614]: https://github.com/JuliaLang/julia/issues/6614 -[#8000]: https://github.com/JuliaLang/julia/issues/8000 -[#8470]: https://github.com/JuliaLang/julia/issues/8470 -[#9053]: https://github.com/JuliaLang/julia/issues/9053 -[#9292]: https://github.com/JuliaLang/julia/issues/9292 -[#10593]: https://github.com/JuliaLang/julia/issues/10593 -[#11310]: https://github.com/JuliaLang/julia/issues/11310 -[#12010]: https://github.com/JuliaLang/julia/issues/12010 -[#12131]: https://github.com/JuliaLang/julia/issues/12131 -[#13079]: https://github.com/JuliaLang/julia/issues/13079 -[#14770]: https://github.com/JuliaLang/julia/issues/14770 -[#15120]: https://github.com/JuliaLang/julia/issues/15120 -[#16356]: https://github.com/JuliaLang/julia/issues/16356 -[#16401]: https://github.com/JuliaLang/julia/issues/16401 -[#16937]: https://github.com/JuliaLang/julia/issues/16937 -[#17046]: https://github.com/JuliaLang/julia/issues/17046 -[#17086]: https://github.com/JuliaLang/julia/issues/17086 -[#17240]: https://github.com/JuliaLang/julia/issues/17240 -[#17360]: https://github.com/JuliaLang/julia/issues/17360 -[#17367]: https://github.com/JuliaLang/julia/issues/17367 -[#17886]: https://github.com/JuliaLang/julia/issues/17886 -[#17997]: https://github.com/JuliaLang/julia/issues/17997 -[#18155]: https://github.com/JuliaLang/julia/issues/18155 -[#18650]: https://github.com/JuliaLang/julia/issues/18650 -[#19089]: https://github.com/JuliaLang/julia/issues/19089 -[#19157]: https://github.com/JuliaLang/julia/issues/19157 -[#19186]: https://github.com/JuliaLang/julia/issues/19186 -[#19987]: https://github.com/JuliaLang/julia/issues/19987 -[#20005]: https://github.com/JuliaLang/julia/issues/20005 -[#20418]: https://github.com/JuliaLang/julia/issues/20418 -[#20549]: https://github.com/JuliaLang/julia/issues/20549 -[#20575]: https://github.com/JuliaLang/julia/issues/20575 -[#20816]: https://github.com/JuliaLang/julia/issues/20816 -[#20899]: https://github.com/JuliaLang/julia/issues/20899 -[#20912]: https://github.com/JuliaLang/julia/issues/20912 -[#20974]: https://github.com/JuliaLang/julia/issues/20974 -[#21359]: https://github.com/JuliaLang/julia/issues/21359 -[#21438]: https://github.com/JuliaLang/julia/issues/21438 -[#21450]: https://github.com/JuliaLang/julia/issues/21450 -[#21527]: https://github.com/JuliaLang/julia/issues/21527 -[#21540]: https://github.com/JuliaLang/julia/issues/21540 -[#21592]: https://github.com/JuliaLang/julia/issues/21592 -[#21662]: https://github.com/JuliaLang/julia/issues/21662 -[#21692]: https://github.com/JuliaLang/julia/issues/21692 -[#21697]: https://github.com/JuliaLang/julia/issues/21697 -[#21709]: https://github.com/JuliaLang/julia/issues/21709 -[#21746]: https://github.com/JuliaLang/julia/issues/21746 -[#21759]: https://github.com/JuliaLang/julia/issues/21759 -[#21774]: https://github.com/JuliaLang/julia/issues/21774 -[#21825]: https://github.com/JuliaLang/julia/issues/21825 -[#21909]: https://github.com/JuliaLang/julia/issues/21909 -[#21956]: https://github.com/JuliaLang/julia/issues/21956 -[#21960]: https://github.com/JuliaLang/julia/issues/21960 -[#21973]: https://github.com/JuliaLang/julia/issues/21973 -[#21974]: https://github.com/JuliaLang/julia/issues/21974 -[#22007]: https://github.com/JuliaLang/julia/issues/22007 -[#22038]: https://github.com/JuliaLang/julia/issues/22038 -[#22062]: https://github.com/JuliaLang/julia/issues/22062 -[#22064]: https://github.com/JuliaLang/julia/issues/22064 -[#22088]: https://github.com/JuliaLang/julia/issues/22088 -[#22089]: https://github.com/JuliaLang/julia/issues/22089 -[#22092]: https://github.com/JuliaLang/julia/issues/22092 -[#22182]: https://github.com/JuliaLang/julia/issues/22182 -[#22187]: https://github.com/JuliaLang/julia/issues/22187 -[#22188]: https://github.com/JuliaLang/julia/issues/22188 -[#22194]: https://github.com/JuliaLang/julia/issues/22194 -[#22210]: https://github.com/JuliaLang/julia/issues/22210 -[#22222]: https://github.com/JuliaLang/julia/issues/22222 -[#22224]: https://github.com/JuliaLang/julia/issues/22224 -[#22226]: https://github.com/JuliaLang/julia/issues/22226 -[#22228]: https://github.com/JuliaLang/julia/issues/22228 -[#22245]: https://github.com/JuliaLang/julia/issues/22245 -[#22251]: https://github.com/JuliaLang/julia/issues/22251 -[#22274]: https://github.com/JuliaLang/julia/issues/22274 -[#22281]: https://github.com/JuliaLang/julia/issues/22281 -[#22296]: https://github.com/JuliaLang/julia/issues/22296 -[#22314]: https://github.com/JuliaLang/julia/issues/22314 -[#22324]: https://github.com/JuliaLang/julia/issues/22324 -[#22325]: https://github.com/JuliaLang/julia/issues/22325 -[#22350]: https://github.com/JuliaLang/julia/issues/22350 -[#22390]: https://github.com/JuliaLang/julia/issues/22390 -[#22496]: https://github.com/JuliaLang/julia/issues/22496 -[#22511]: https://github.com/JuliaLang/julia/issues/22511 -[#22523]: https://github.com/JuliaLang/julia/issues/22523 -[#22532]: https://github.com/JuliaLang/julia/issues/22532 -[#22572]: https://github.com/JuliaLang/julia/issues/22572 -[#22588]: https://github.com/JuliaLang/julia/issues/22588 -[#22605]: https://github.com/JuliaLang/julia/issues/22605 -[#22666]: https://github.com/JuliaLang/julia/issues/22666 -[#22696]: https://github.com/JuliaLang/julia/issues/22696 -[#22703]: https://github.com/JuliaLang/julia/issues/22703 -[#22712]: https://github.com/JuliaLang/julia/issues/22712 -[#22718]: https://github.com/JuliaLang/julia/issues/22718 -[#22720]: https://github.com/JuliaLang/julia/issues/22720 -[#22723]: https://github.com/JuliaLang/julia/issues/22723 -[#22732]: https://github.com/JuliaLang/julia/issues/22732 -[#22742]: https://github.com/JuliaLang/julia/issues/22742 -[#22751]: https://github.com/JuliaLang/julia/issues/22751 -[#22761]: https://github.com/JuliaLang/julia/issues/22761 -[#22762]: https://github.com/JuliaLang/julia/issues/22762 -[#22789]: https://github.com/JuliaLang/julia/issues/22789 -[#22793]: https://github.com/JuliaLang/julia/issues/22793 -[#22796]: https://github.com/JuliaLang/julia/issues/22796 -[#22800]: https://github.com/JuliaLang/julia/issues/22800 -[#22801]: https://github.com/JuliaLang/julia/issues/22801 -[#22814]: https://github.com/JuliaLang/julia/issues/22814 -[#22825]: https://github.com/JuliaLang/julia/issues/22825 -[#22829]: https://github.com/JuliaLang/julia/issues/22829 -[#22847]: https://github.com/JuliaLang/julia/issues/22847 -[#22868]: https://github.com/JuliaLang/julia/issues/22868 -[#22880]: https://github.com/JuliaLang/julia/issues/22880 -[#22907]: https://github.com/JuliaLang/julia/issues/22907 -[#22925]: https://github.com/JuliaLang/julia/issues/22925 -[#22926]: https://github.com/JuliaLang/julia/issues/22926 -[#22932]: https://github.com/JuliaLang/julia/issues/22932 -[#22961]: https://github.com/JuliaLang/julia/issues/22961 -[#22984]: https://github.com/JuliaLang/julia/issues/22984 -[#23002]: https://github.com/JuliaLang/julia/issues/23002 -[#23035]: https://github.com/JuliaLang/julia/issues/23035 -[#23051]: https://github.com/JuliaLang/julia/issues/23051 -[#23054]: https://github.com/JuliaLang/julia/issues/23054 -[#23117]: https://github.com/JuliaLang/julia/issues/23117 -[#23120]: https://github.com/JuliaLang/julia/issues/23120 -[#23144]: https://github.com/JuliaLang/julia/issues/23144 -[#23154]: https://github.com/JuliaLang/julia/issues/23154 -[#23157]: https://github.com/JuliaLang/julia/issues/23157 -[#23168]: https://github.com/JuliaLang/julia/issues/23168 -[#23187]: https://github.com/JuliaLang/julia/issues/23187 -[#23207]: https://github.com/JuliaLang/julia/issues/23207 -[#23233]: https://github.com/JuliaLang/julia/issues/23233 -[#23235]: https://github.com/JuliaLang/julia/issues/23235 -[#23261]: https://github.com/JuliaLang/julia/issues/23261 -[#23323]: https://github.com/JuliaLang/julia/issues/23323 -[#23332]: https://github.com/JuliaLang/julia/issues/23332 -[#23341]: https://github.com/JuliaLang/julia/issues/23341 -[#23342]: https://github.com/JuliaLang/julia/issues/23342 -[#23354]: https://github.com/JuliaLang/julia/issues/23354 -[#23366]: https://github.com/JuliaLang/julia/issues/23366 -[#23373]: https://github.com/JuliaLang/julia/issues/23373 -[#23393]: https://github.com/JuliaLang/julia/issues/23393 -[#23404]: https://github.com/JuliaLang/julia/issues/23404 -[#23427]: https://github.com/JuliaLang/julia/issues/23427 -[#23504]: https://github.com/JuliaLang/julia/issues/23504 -[#23505]: https://github.com/JuliaLang/julia/issues/23505 -[#23519]: https://github.com/JuliaLang/julia/issues/23519 -[#23528]: https://github.com/JuliaLang/julia/issues/23528 -[#23529]: https://github.com/JuliaLang/julia/issues/23529 -[#23530]: https://github.com/JuliaLang/julia/issues/23530 -[#23554]: https://github.com/JuliaLang/julia/issues/23554 -[#23570]: https://github.com/JuliaLang/julia/issues/23570 -[#23628]: https://github.com/JuliaLang/julia/issues/23628 -[#23642]: https://github.com/JuliaLang/julia/issues/23642 -[#23665]: https://github.com/JuliaLang/julia/issues/23665 -[#23690]: https://github.com/JuliaLang/julia/issues/23690 -[#23716]: https://github.com/JuliaLang/julia/issues/23716 -[#23724]: https://github.com/JuliaLang/julia/issues/23724 -[#23750]: https://github.com/JuliaLang/julia/issues/23750 -[#23757]: https://github.com/JuliaLang/julia/issues/23757 -[#23805]: https://github.com/JuliaLang/julia/issues/23805 -[#23816]: https://github.com/JuliaLang/julia/issues/23816 -[#23885]: https://github.com/JuliaLang/julia/issues/23885 -[#23902]: https://github.com/JuliaLang/julia/issues/23902 -[#23912]: https://github.com/JuliaLang/julia/issues/23912 -[#23923]: https://github.com/JuliaLang/julia/issues/23923 -[#23929]: https://github.com/JuliaLang/julia/issues/23929 -[#23960]: https://github.com/JuliaLang/julia/issues/23960 -[#23964]: https://github.com/JuliaLang/julia/issues/23964 -[#24047]: https://github.com/JuliaLang/julia/issues/24047 -[#24126]: https://github.com/JuliaLang/julia/issues/24126 -[#24153]: https://github.com/JuliaLang/julia/issues/24153 -[#24167]: https://github.com/JuliaLang/julia/issues/24167 -[#24187]: https://github.com/JuliaLang/julia/issues/24187 -[#24221]: https://github.com/JuliaLang/julia/issues/24221 -[#24240]: https://github.com/JuliaLang/julia/issues/24240 -[#24245]: https://github.com/JuliaLang/julia/issues/24245 -[#24250]: https://github.com/JuliaLang/julia/issues/24250 -[#24263]: https://github.com/JuliaLang/julia/issues/24263 -[#24278]: https://github.com/JuliaLang/julia/issues/24278 -[#24279]: https://github.com/JuliaLang/julia/issues/24279 -[#24281]: https://github.com/JuliaLang/julia/issues/24281 -[#24282]: https://github.com/JuliaLang/julia/issues/24282 -[#24320]: https://github.com/JuliaLang/julia/issues/24320 -[#24356]: https://github.com/JuliaLang/julia/issues/24356 -[#24362]: https://github.com/JuliaLang/julia/issues/24362 -[#24390]: https://github.com/JuliaLang/julia/issues/24390 -[#24396]: https://github.com/JuliaLang/julia/issues/24396 -[#24404]: https://github.com/JuliaLang/julia/issues/24404 -[#24413]: https://github.com/JuliaLang/julia/issues/24413 -[#24414]: https://github.com/JuliaLang/julia/issues/24414 -[#24438]: https://github.com/JuliaLang/julia/issues/24438 -[#24445]: https://github.com/JuliaLang/julia/issues/24445 -[#24452]: https://github.com/JuliaLang/julia/issues/24452 -[#24472]: https://github.com/JuliaLang/julia/issues/24472 -[#24490]: https://github.com/JuliaLang/julia/issues/24490 -[#24580]: https://github.com/JuliaLang/julia/issues/24580 -[#24595]: https://github.com/JuliaLang/julia/issues/24595 -[#24605]: https://github.com/JuliaLang/julia/issues/24605 -[#24647]: https://github.com/JuliaLang/julia/issues/24647 -[#24653]: https://github.com/JuliaLang/julia/issues/24653 -[#24654]: https://github.com/JuliaLang/julia/issues/24654 -[#24656]: https://github.com/JuliaLang/julia/issues/24656 -[#24673]: https://github.com/JuliaLang/julia/issues/24673 -[#24679]: https://github.com/JuliaLang/julia/issues/24679 -[#24684]: https://github.com/JuliaLang/julia/issues/24684 -[#24713]: https://github.com/JuliaLang/julia/issues/24713 -[#24715]: https://github.com/JuliaLang/julia/issues/24715 -[#24774]: https://github.com/JuliaLang/julia/issues/24774 -[#24781]: https://github.com/JuliaLang/julia/issues/24781 -[#24785]: https://github.com/JuliaLang/julia/issues/24785 -[#24786]: https://github.com/JuliaLang/julia/issues/24786 -[#24808]: https://github.com/JuliaLang/julia/issues/24808 -[#24831]: https://github.com/JuliaLang/julia/issues/24831 -[#24839]: https://github.com/JuliaLang/julia/issues/24839 -[#24844]: https://github.com/JuliaLang/julia/issues/24844 -[#24869]: https://github.com/JuliaLang/julia/issues/24869 -[#25002]: https://github.com/JuliaLang/julia/issues/25002 -[#25012]: https://github.com/JuliaLang/julia/issues/25012 -[#25021]: https://github.com/JuliaLang/julia/issues/25021 -[#25029]: https://github.com/JuliaLang/julia/issues/25029 -[#25030]: https://github.com/JuliaLang/julia/issues/25030 -[#25037]: https://github.com/JuliaLang/julia/issues/25037 -[#25046]: https://github.com/JuliaLang/julia/issues/25046 -[#25047]: https://github.com/JuliaLang/julia/issues/25047 -[#25056]: https://github.com/JuliaLang/julia/issues/25056 -[#25057]: https://github.com/JuliaLang/julia/issues/25057 -[#25058]: https://github.com/JuliaLang/julia/issues/25058 -[#25067]: https://github.com/JuliaLang/julia/issues/25067 -[#25088]: https://github.com/JuliaLang/julia/issues/25088 -[#25162]: https://github.com/JuliaLang/julia/issues/25162 -[#25165]: https://github.com/JuliaLang/julia/issues/25165 -[#25168]: https://github.com/JuliaLang/julia/issues/25168 -[#25184]: https://github.com/JuliaLang/julia/issues/25184 -[#25197]: https://github.com/JuliaLang/julia/issues/25197 -[#25210]: https://github.com/JuliaLang/julia/issues/25210 -[#25231]: https://github.com/JuliaLang/julia/issues/25231 -[#25249]: https://github.com/JuliaLang/julia/issues/25249 -[#25277]: https://github.com/JuliaLang/julia/issues/25277 -[#25278]: https://github.com/JuliaLang/julia/issues/25278 -[#25311]: https://github.com/JuliaLang/julia/issues/25311 -[#25321]: https://github.com/JuliaLang/julia/issues/25321 -[#25368]: https://github.com/JuliaLang/julia/issues/25368 -[#25391]: https://github.com/JuliaLang/julia/issues/25391 -[#25424]: https://github.com/JuliaLang/julia/issues/25424 -[#25429]: https://github.com/JuliaLang/julia/issues/25429 -[#25457]: https://github.com/JuliaLang/julia/issues/25457 -[#25459]: https://github.com/JuliaLang/julia/issues/25459 -[#25472]: https://github.com/JuliaLang/julia/issues/25472 -[#25496]: https://github.com/JuliaLang/julia/issues/25496 -[#25501]: https://github.com/JuliaLang/julia/issues/25501 -[#25522]: https://github.com/JuliaLang/julia/issues/25522 -[#25532]: https://github.com/JuliaLang/julia/issues/25532 -[#25545]: https://github.com/JuliaLang/julia/issues/25545 -[#25564]: https://github.com/JuliaLang/julia/issues/25564 -[#25567]: https://github.com/JuliaLang/julia/issues/25567 -[#25571]: https://github.com/JuliaLang/julia/issues/25571 -[#25616]: https://github.com/JuliaLang/julia/issues/25616 -[#25622]: https://github.com/JuliaLang/julia/issues/25622 -[#25631]: https://github.com/JuliaLang/julia/issues/25631 -[#25633]: https://github.com/JuliaLang/julia/issues/25633 -[#25634]: https://github.com/JuliaLang/julia/issues/25634 -[#25654]: https://github.com/JuliaLang/julia/issues/25654 -[#25655]: https://github.com/JuliaLang/julia/issues/25655 -[#25662]: https://github.com/JuliaLang/julia/issues/25662 -[#25667]: https://github.com/JuliaLang/julia/issues/25667 -[#25668]: https://github.com/JuliaLang/julia/issues/25668 -[#25697]: https://github.com/JuliaLang/julia/issues/25697 -[#25701]: https://github.com/JuliaLang/julia/issues/25701 -[#25725]: https://github.com/JuliaLang/julia/issues/25725 -[#25745]: https://github.com/JuliaLang/julia/issues/25745 -[#25763]: https://github.com/JuliaLang/julia/issues/25763 -[#25786]: https://github.com/JuliaLang/julia/issues/25786 -[#25812]: https://github.com/JuliaLang/julia/issues/25812 -[#25815]: https://github.com/JuliaLang/julia/issues/25815 -[#25830]: https://github.com/JuliaLang/julia/issues/25830 -[#25845]: https://github.com/JuliaLang/julia/issues/25845 -[#25854]: https://github.com/JuliaLang/julia/issues/25854 -[#25858]: https://github.com/JuliaLang/julia/issues/25858 -[#25872]: https://github.com/JuliaLang/julia/issues/25872 -[#25896]: https://github.com/JuliaLang/julia/issues/25896 -[#25944]: https://github.com/JuliaLang/julia/issues/25944 -[#25947]: https://github.com/JuliaLang/julia/issues/25947 -[#25979]: https://github.com/JuliaLang/julia/issues/25979 -[#25980]: https://github.com/JuliaLang/julia/issues/25980 -[#25990]: https://github.com/JuliaLang/julia/issues/25990 -[#25998]: https://github.com/JuliaLang/julia/issues/25998 -[#26009]: https://github.com/JuliaLang/julia/issues/26009 -[#26071]: https://github.com/JuliaLang/julia/issues/26071 -[#26080]: https://github.com/JuliaLang/julia/issues/26080 -[#26093]: https://github.com/JuliaLang/julia/issues/26093 -[#26149]: https://github.com/JuliaLang/julia/issues/26149 -[#26154]: https://github.com/JuliaLang/julia/issues/26154 -[#26156]: https://github.com/JuliaLang/julia/issues/26156 -[#26161]: https://github.com/JuliaLang/julia/issues/26161 -[#26206]: https://github.com/JuliaLang/julia/issues/26206 -[#26212]: https://github.com/JuliaLang/julia/issues/26212 -[#26262]: https://github.com/JuliaLang/julia/issues/26262 -[#26283]: https://github.com/JuliaLang/julia/issues/26283 -[#26284]: https://github.com/JuliaLang/julia/issues/26284 -[#26286]: https://github.com/JuliaLang/julia/issues/26286 -[#26347]: https://github.com/JuliaLang/julia/issues/26347 -[#26436]: https://github.com/JuliaLang/julia/issues/26436 -[#26442]: https://github.com/JuliaLang/julia/issues/26442 -[#26486]: https://github.com/JuliaLang/julia/issues/26486 -[#26559]: https://github.com/JuliaLang/julia/issues/26559 -[#26576]: https://github.com/JuliaLang/julia/issues/26576 -[#26600]: https://github.com/JuliaLang/julia/issues/26600 -[#26660]: https://github.com/JuliaLang/julia/issues/26660 -[#26670]: https://github.com/JuliaLang/julia/issues/26670 -[#26733]: https://github.com/JuliaLang/julia/issues/26733 -[#26775]: https://github.com/JuliaLang/julia/issues/26775 -[#26858]: https://github.com/JuliaLang/julia/issues/26858 -[#26862]: https://github.com/JuliaLang/julia/issues/26862 -[#26932]: https://github.com/JuliaLang/julia/issues/26932 -[#26935]: https://github.com/JuliaLang/julia/issues/26935 -[#26980]: https://github.com/JuliaLang/julia/issues/26980 -[#26997]: https://github.com/JuliaLang/julia/issues/26997 -[#27067]: https://github.com/JuliaLang/julia/issues/27067 -[#27071]: https://github.com/JuliaLang/julia/issues/27071 -[#27075]: https://github.com/JuliaLang/julia/issues/27075 -[#27100]: https://github.com/JuliaLang/julia/issues/27100 -[#27121]: https://github.com/JuliaLang/julia/issues/27121 -[#27159]: https://github.com/JuliaLang/julia/issues/27159 -[#27164]: https://github.com/JuliaLang/julia/issues/27164 -[#27189]: https://github.com/JuliaLang/julia/issues/27189 -[#27212]: https://github.com/JuliaLang/julia/issues/27212 -[#27248]: https://github.com/JuliaLang/julia/issues/27248 -[#27309]: https://github.com/JuliaLang/julia/issues/27309 -[#27401]: https://github.com/JuliaLang/julia/issues/27401 -[#27447]: https://github.com/JuliaLang/julia/issues/27447 -[#27459]: https://github.com/JuliaLang/julia/issues/27459 -[#27470]: https://github.com/JuliaLang/julia/issues/27470 -[#27473]: https://github.com/JuliaLang/julia/issues/27473 -[#27554]: https://github.com/JuliaLang/julia/issues/27554 -[#27560]: https://github.com/JuliaLang/julia/issues/27560 -[#27616]: https://github.com/JuliaLang/julia/issues/27616 -[#27635]: https://github.com/JuliaLang/julia/issues/27635 -[#27641]: https://github.com/JuliaLang/julia/issues/27641 -[#27711]: https://github.com/JuliaLang/julia/issues/27711 -[#27726]: https://github.com/JuliaLang/julia/issues/27726 -[#27746]: https://github.com/JuliaLang/julia/issues/27746 -[#27856]: https://github.com/JuliaLang/julia/issues/27856 -[#27859]: https://github.com/JuliaLang/julia/issues/27859 -[#27908]: https://github.com/JuliaLang/julia/issues/27908 -[#27944]: https://github.com/JuliaLang/julia/issues/27944 -[#28045]: https://github.com/JuliaLang/julia/issues/28045 -[#28065]: https://github.com/JuliaLang/julia/issues/28065 -[#28155]: https://github.com/JuliaLang/julia/issues/28155 -[#28266]: https://github.com/JuliaLang/julia/issues/28266 -[#28302]: https://github.com/JuliaLang/julia/issues/28302 - Julia v0.6.0 Release Notes ========================== diff --git a/NEWS.md b/NEWS.md index ac7b3ae5f2605..e0765654daaa7 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,29 +1,1737 @@ -Julia v1.0.0 Release Notes +Julia v0.7.0 Release Notes ========================== New language features --------------------- + * Local variables can be tested for being defined + using the new `@isdefined variable` macro ([#22281]). + + * Destructuring in function arguments: when an expression such as `(x, y)` is used as + a function argument name, the argument is unpacked into local variables `x` and `y` + as in the assignment `(x, y) = arg` ([#6614]). + + * Named tuples, with the syntax `(a=1, b=2)`. These behave very similarly to tuples, + except components can also be accessed by name using dot syntax `t.a` ([#22194]). + + * Keyword argument containers (`kw` in `f(; kw...)`) are now based on named tuples. Dictionary + functions like `haskey` and indexing can be used on them, and name-value pairs can be + iterated using `pairs(kw)`. `kw` can no longer contain multiple entries for the same + argument name ([#4916]). + + * Custom infix operators can now be defined by appending Unicode + combining marks, primes, and sub/superscripts to other operators. + For example, `+̂ₐ″` is parsed as an infix operator with the same + precedence as `+` ([#22089]). + + * The macro call syntax `@macroname[args]` is now available and is parsed + as `@macroname([args])` ([#23519]). + + * The construct `if @generated ...; else ...; end` can be used to provide both + `@generated` and normal implementations of part of a function. Surrounding code + will be common to both versions ([#23168]). + + * Added `⟂` (`\perp`) operator with comparison precedence ([#24404]). + + * The `missing` singleton object (of type `Missing`) has been added to represent + missing values ([#24653]). It propagates through standard operators and mathematical functions, + and implements three-valued logic, similar to SQLs `NULL` and R's `NA`. + + * Field access via dot-syntax can now be overloaded by adding methods to + `Base.getproperty` and `Base.setproperty!` ([#1974]), optionally along with + a corresponding `Base.propertynames` method for reflection ([#25311]). + + * Values for `Enum`s can now be specified inside of a `begin` block when using the + `@enum` macro ([#25424]). + + * Keyword arguments can be required: if a default value is omitted, then an + exception is thrown if the caller does not assign the keyword a value ([#25830]). + + * The pair operator `=>` is now broadcastable as `.=>` which was previously a parsing error ([#27447]) + Language changes ---------------- + * The syntax for parametric methods, `function f{T}(x::T)`, has been + changed to `function f(x::T) where {T}` ([#11310]). + + * The fallback constructor that calls `convert` is deprecated. Instead, new types should + prefer to define constructors, and add `convert` methods that call those constructors + only as necessary ([#15120]). + + * The syntax `1.+2` is deprecated, since it is ambiguous: it could mean either + `1 .+ 2` (the current meaning) or `1. + 2` ([#19089]). + + * Mutable structs with no fields are no longer singletons; it is now possible to make + multiple instances of them that can be distinguished by `===` ([#25854]). + Zero-size immutable structs are still singletons. + + * In string and character literals, backslash `\` may no longer + precede unrecognized escape characters ([#22800]). + + * Juxtaposing binary, octal, and hexadecimal literals is deprecated, since it can lead to + confusing code such as `0xapi == 0xa * pi` ([#16356]). + + * Numeric literal juxtaposition now has slighty lower precedence than unary operators, + so for example `√2x` parses as `(√2) * x` ([#27641]). + + * Declaring arguments as `x::ANY` to avoid specialization has been replaced + by `@nospecialize x`. ([#22666]). + + This can also be used in global scope, to apply to all subsequent method definitions + in the module (until `@specialize`). ([#28065]) + + * Keyword argument default values are now evaluated in successive scopes --- + the scope for each expression includes only previous keyword arguments, in + left-to-right order ([#17240]). + + * The parsing of `1<<2*3` as `1<<(2*3)` is deprecated, and will change to + `(1<<2)*3` in a future version ([#13079]). + + * The parsing of `<|` is now right associative. `|>` remains left associative ([#24153]). + + * `:` now parses like other operators, as a call to a function named `:`, instead of + calling `colon` ([#25947]). + + * `{ }` expressions now use `braces` and `bracescat` as expression heads instead + of `cell1d` and `cell2d`, and parse similarly to `vect` and `vcat` ([#8470]). + + * Nested `if` expressions that arise from the keyword `elseif` now use `elseif` + as their expression head instead of `if` ([#21774]). + + * `let` blocks now parse the same as `for` loops; the first argument is either an + assignment or `block` of assignments, and the second argument is a block of + statements ([#21774]). + + * `do` syntax now parses to an expression with head `:do`, instead of as a function + call ([#21774]). + + * Parsed and lowered forms of type definitions have been synchronized with their + new keywords ([#23157]). Expression heads are renamed as follows: + + + `type` => `struct` + + + `bitstype` => `primitive` (order of arguments is also reversed, to match syntax) + + + `composite_type` => `struct_type` + + + `bits_type` => `primitive_type` + + * The `global` keyword now only introduces a new binding if one doesn't already exist + in the module. + This means that assignment to a global (`global sin = 3`) may now throw the error: + "cannot assign variable Base.sin from module Main", rather than emitting a warning. + Additionally, the new bindings are now created before the statement is executed. + For example, `f() = (global sin = "gluttony"; nothing)` will now resolve which module + contains `sin` eagerly, rather than delaying that decision until `f` is run. ([#22984]). + + * `global const` declarations may no longer appear inside functions ([#12010]). + + * Uninitialized `BitArray` constructors of the form `BitArray[{N}](shape...)` have been + deprecated in favor of equivalents accepting `undef` (an alias for + `UndefInitializer()`) as their first argument, as in + `BitArray[{N}](undef, shape...)`. For example, `BitVector(3)` is now + `BitVector(undef, 3)`, `BitMatrix((2, 4))` is now + `BitMatrix(undef, (2, 4))`, and `BitArray{3}(11, 13, 17)` is now + `BitArray{3}(undef, 11, 14, 17)` ([#24785]). + + * Dispatch rules have been simplified: + method matching is now determined exclusively by subtyping; + the rule that method type parameters must also be captured has been removed. + Instead, attempting to access the unconstrained parameters will throw an `UndefVarError`. + Linting in package tests is recommended to confirm that the set of methods + which might throw `UndefVarError` when accessing the static parameters + (`need_to_handle_undef_sparam = Set{Any}(m.sig for m in Test.detect_unbound_args(Base, recursive=true))`) + is equal (`==`) to some known set (`expected = Set()`). ([#23117]) + + * `const` declarations on local variables were previously ignored. They now give a + warning, so that this syntax can be disallowed or given a new meaning in a + future version ([#5148]). + + * Placing an expression after `catch`, as in `catch f(x)`, is deprecated. + Use `catch; f(x)` instead ([#19987]). + + * In `for i = ...`, if a local variable `i` already existed it would be overwritten + during the loop. This behavior is deprecated, and in the future `for` loop variables + will always be new variables local to the loop ([#22314]). + The old behavior of overwriting an existing variable is available via `for outer i = ...`. + + * In `for i in x`, `x` used to be evaluated in a new scope enclosing the `for` loop. + Now it is evaluated in the scope outside the `for` loop. + + * In `for i in x, j in y`, all variables now have fresh bindings on each iteration of the + innermost loop. For example, an assignment to `i` will not be visible on the next `j` + loop iteration ([#330]). + + * Variable bindings local to `while` loop bodies are now freshly allocated on each loop iteration, + matching the behavior of `for` loops. + + * Prefix `&` for by-reference arguments to `ccall` has been deprecated in favor of + `Ref` argument types ([#6080]). + + * The constructor `Ref(x::T)` now always returns a `Ref{T}` ([#21527]). + + * All line numbers in ASTs are represented by `LineNumberNode`s; the `:line` expression + head is no longer used. `QuoteNode`s are also consistently used for quoted symbols instead + of the `:quote` expression head (though `:quote` `Expr`s are still used for quoted + expressions) ([#23885]). + + * The `+` and `-` methods for `Number` and `UniformScaling` are not ambiguous anymore since `+` + and `-` no longer do automatic broadcasting. Hence, the methods for `UniformScaling` and `Number` are + no longer deprecated ([#23923]). + + * The keyword `importall` is deprecated. Use `using` and/or individual `import` statements + instead ([#22789]). + + * `reduce(+, [...])` and `reduce(*, [...])` no longer widen the iterated over arguments to + system word size. `sum` and `prod` still preserve this behavior. ([#22825]) + + * Like `_`, variable names consisting only of underscores can be assigned, + but accessing their values is deprecated ([#24221]). + + * Raw string literal escaping rules have been changed to make it possible to write all strings. + The rule is that backslashes escape both quotes and other backslashes, but only when a sequence + of backslashes precedes a quote character. Thus, 2n backslashes followed by a quote encodes n + backslashes and the end of the literal while 2n+1 backslashes followed by a quote encodes n + backslashes followed by a quote character ([#22926]). + + * `reprmime(mime, x)` has been renamed to `repr(mime, x)`, and along with `repr(x)` + and `sprint` it now accepts an optional `context` keyword for `IOContext` attributes. + `stringmime` has been moved to the Base64 stdlib package ([#25990]). + + * The syntax `(x...)` for constructing a tuple is deprecated; use `(x...,)` instead ([#24452]). + + * Non-parenthesized interpolated variables in strings, e.g. `"$x"`, must be followed + by a character that will never be an allowed identifier character (currently + operators, space/control characters, or common punctuation characters) ([#25231]). + + * The syntax `using A.B` can now only be used when `A.B` is a module, and the syntax + `using A: B` can only be used for adding single bindings ([#8000]). + + * `=>` now has its own precedence level, giving it strictly higher precedence than + `=` and `,` ([#25391]). + + * The conditions under which unary operators followed by `(` are parsed as prefix function + calls have changed ([#26154]). + + * `begin` is disallowed inside indexing expressions, in order to enable the syntax + `a[begin]` (for selecting the first element) in the future ([#23354]). + + * Underscores for `_italics_` and `__bold__` are now supported by the Base Markdown + parser. ([#25564]) + + * `…` (`\dots`) and `⁝` (`\tricolon`) are now parsed as binary operators ([#26262]). + + * Assignment syntax (`a=b`) inside square bracket expressions (e.g. `A[...]`, `[x, y]`) + is deprecated. It will likely be reclaimed in a later version for passing keyword + arguments. Note this does not affect updating operators like `+=` ([#25631]). + + * `try` blocks without `catch` or `finally` are no longer allowed. An explicit empty + `catch` block should be written instead ([#27554]). + + * `AbstractArray` types that use unconventional (not 1-based) indexing can now support + `size`, `length`, and `@inbounds`. To optionally enforce conventional indices, + you can `@assert !has_offset_axes(A)`. + + * Module pre-compilation is now the default for code loading. Adding a + `__precompile__()` declaration is no longer necessary, although + `__precompile__(false)` can still be used to opt-out ([#26991]). + Breaking changes ---------------- +This section lists changes that do not have deprecation warnings. + + * The package manager `Pkg` has been replaced with a new one. See the manual entries on + "Code Loading" and "Pkg" for documentation. + + * `replace(s::AbstractString, pat=>repl)` for function `repl` arguments formerly + passed a substring to `repl` in all cases. It now passes substrings for + string patterns `pat`, but a `Char` for character patterns (when `pat` is a + `Char`, collection of `Char`, or a character predicate) ([#25815]). + + * `readuntil` now does *not* include the delimiter in its result, matching the + behavior of `readline`. Pass `keep=true` to get the old behavior ([#25633]). + + * `lu` methods now return decomposition objects such as `LU` rather than + tuples of arrays or tuples of numbers ([#26997], [#27159], [#27212]). + + * `schur` methods now return decomposition objects such as `Schur` and + `GeneralizedSchur` rather than tuples of arrays ([#26997], [#27159], [#27212]). + + * `lq` methods now return decomposition objects such as `LQ` + rather than tuples of arrays ([#26997], [#27159], [#27212]). + + * `qr` methods now return decomposition objects such as `QR`, `QRPivoted`, + and `QRCompactWY` rather than tuples of arrays ([#26997], [#27159], [#27212]). + + * `svd` methods now return decomposition objects such as `SVD` and + `GeneralizedSVD` rather than tuples of arrays or tuples of numbers ([#26997], [#27159], [#27212]). + + * `countlines` now always counts the last non-empty line even if it does not + end with EOL, matching the behavior of `eachline` and `readlines` ([#25845]). + + * `getindex(s::String, r::UnitRange{Int})` now throws `StringIndexError` if `last(r)` + is not a valid index into `s` ([#22572]). + + * `ntuple(f, n::Integer)` throws `ArgumentError` if `n` is negative. + Previously an empty tuple was returned ([#21697]). + + * `⋮`, `⋱`, `⋰`, and `⋯` are now parsed as binary operators, not ordinary + identifiers. `≔`, `≕`, and `⩴` now parse with assignment rather than comparison + precedence ([#26262]). + + * Juxtaposing string literals (e.g. `"x"y`) is now a syntax error ([#20575]). + + * `finalizer(function, object)` now returns `object` rather than `nothing` ([#24679]). + + * The constructor of `SubString` now checks if the requested view range + is defined by valid indices in the parent `AbstractString` ([#22511]). + + * Macro calls with `for` expressions are now parsed as generators inside + function argument lists ([#18650]). Examples: + + + `sum(@inbounds a[i] for i = 1:n)` used to give a syntax error, but is now + parsed as `sum(@inbounds(a[i]) for i = 1:n)`. + + + `sum(@m x for i = 1:n end)` used to parse the argument to `sum` as a 2-argument + call to macro `@m`, but now parses it as a generator plus a syntax error + for the dangling `end`. + + * `@__DIR__` returns the current working directory rather than `nothing` when not run + from a file ([#21759]). + + * `@__FILE__` and `@__DIR__` return information relative to the file that it was parsed from, + rather than from the task-local `SOURCE_PATH` global when it was expanded. + + * All macros receive an extra argument `__source__::LineNumberNode` which describes the + parser location in the source file for the `@` of the macro call. + It can be accessed as a normal argument variable in the body of the macro. + This is implemented by inserting an extra leading argument into the + `Expr(:macrocall, :@name, LineNumberNode(...), args...)` + surface syntax. ([#21746]) + + * Passing the same keyword argument multiple times is now a syntax error ([#16937]). + + * `getsockname` on a `TCPSocket` now returns the locally bound address and port + of the socket. Previously the address of the remote endpoint was being + returned ([#21825]). + + * The `~/.juliarc.jl` file has been moved to `~/.julia/config/startup.jl` and + `/etc/julia/juliarc.jl` file has been renamed to `/etc/julia/startup.jl` ([#26161]). + + * Using `ARGS` within `startup.jl` files or within a .jl file loaded with `--load` will no + longer contain the script name as the first argument. Instead, the script name will be + assigned to `PROGRAM_FILE`. ([#22092]) + + * The format for a `ClusterManager` specifying the cookie on the command line is now + `--worker=`. `--worker ` will not work as it is now an optional argument. + + * The representation of `CartesianRange` has changed to a + tuple-of-AbstractUnitRanges; the `start` and `stop` fields are no + longer present. Use `first(R)` and `last(R)` to obtain + start/stop. ([#20974]) + + * The `Diagonal`, `Bidiagonal`, `Tridiagonal` and `SymTridiagonal` type definitions have + changed from `Diagonal{T}`, `Bidiagonal{T}`, `Tridiagonal{T}` and `SymTridiagonal{T}` + to `Diagonal{T,V<:AbstractVector{T}}`, `Bidiagonal{T,V<:AbstractVector{T}}`, + `Tridiagonal{T,V<:AbstractVector{T}}` and `SymTridiagonal{T,V<:AbstractVector{T}}` + respectively ([#22718], [#22925], [#23035], [#23154]). + + * The immediate supertype of `BitArray` is now simply `AbstractArray`. `BitArray` is no longer + considered a subtype of `DenseArray` and `StridedArray` ([#25858]). + + * When called with an argument that contains `NaN` elements, `findmin` and `findmax` now return the + first `NaN` found and its corresponding index. Previously, `NaN` elements were ignored. + The new behavior matches that of `min`, `max`, `minimum`, and `maximum`. + + * `isapprox(x,y)` now tests `norm(x-y) <= max(atol, rtol*max(norm(x), norm(y)))` + rather than `norm(x-y) <= atol + ...`, and `rtol` defaults to zero + if an `atol > 0` is specified ([#22742]). + + * Spaces are no longer allowed between `@` and the name of a macro in a macro call ([#22868]). + + * Juxtaposition of a non-literal with a macro call (`x@macro`) is no longer valid syntax ([#22868]). + + * On a cluster, all files are now loaded from the local file system rather than node 1 ([#22588]). + To load the same file everywhere from node 1, one possible alternative is to broadcast a call to `include_string`: + `@everywhere include_string(Main, $(read("filename", String)), "filename")`. + Improving upon this API is left as an opportunity for packages. + + * `randperm(n)` and `randcycle(n)` now always return a `Vector{Int}` (independent of + the type of `n`). Use the corresponding mutating functions `randperm!` and `randcycle!` + to control the array type ([#22723]). + + * Hermitian now ignores any imaginary components in the diagonal instead of checking + the diagonal. ([#17367]) + + * Worker-worker connections are setup lazily for an `:all_to_all` topology. Use keyword + arg `lazy=false` to force all connections to be setup during a `addprocs` call. ([#22814]) + + * In `joinpath(a, b)` on Windows, if the drive specifications of `a` and `b` do not match, + `joinpath` now returns `b` instead of throwing an `ArgumentError`. `joinpath(path...)` is + defined to be left associative, so if any argument has a drive path which does not match + the drive of the join of the preceding paths, the prior ones are dropped. ([#20912]) + + * `^(A::AbstractMatrix{<:Integer}, p::Integer)` now throws a `DomainError` + if `p < 0`, unless `A == one(A)` or `A == -one(A)` (same as for + `^(A::Integer, p::Integer)`) ([#23366]). + + * `^(A::AbstractMatrix{<:Integer}, p::Integer)` now promotes the element type in the same + way as `^(A::Integer, p::Integer)`. This means, for instance, that `[1 1; 0 1]^big(1)` + will return a `Matrix{BigInt}` instead of a `Matrix{Int}` ([#23366]). + + * The element type of the input is now preserved in `unique`. Previously the element type + of the output was shrunk to fit the union of the type of each element in the input. + ([#22696]) + + * The `promote` function now raises an error if its arguments are of different types + and if attempting to convert them to a common type fails to change any of their types. + This avoids stack overflows in the common case of definitions like + `f(x, y) = f(promote(x, y)...)` ([#22801]). + + * `indmin` and `indmax` have been renamed to `argmin` and `argmax`, respectively ([#25654]). + + * `findmin`, `findmax`, `argmin`, and `argmax` used to always return linear indices. + They now return `CartesianIndex`es for all but 1-d arrays, and in general return + the `keys` of indexed collections (e.g. dictionaries) ([#22907]). + + * The `openspecfun` library is no longer built and shipped with Julia, as it is no longer + used internally ([#22390]). + + * All loaded packages used to have bindings in `Main` (e.g. `Main.Package`). This is no + longer the case; now bindings will only exist for packages brought into scope by + typing `using Package` or `import Package` ([#17997]). + + * The rules for mixed-signedness integer arithmetic (e.g. `Int32(1) + UInt64(1)`) have been + simplified: if the arguments have different sizes (in bits), then the type of the larger + argument is used. If the arguments have the same size, the unsigned type is used ([#9292]). + + * All command line arguments passed via `-e`, `-E`, and `-L` will be executed in the order + given on the command line ([#23665]). + + * `I` now yields `UniformScaling{Bool}(true)` rather than `UniformScaling{Int64}(1)` + to better preserve types in operations involving `I` ([#24396]). + + * The return type of `reinterpret` has changed to `ReinterpretArray`. `reinterpret` on sparse + arrays has been discontinued. + + * `Base.find_in_path` is now `Base.find_package` or `Base.find_source_file` ([#24320]). + + * `finalizer` now takes functions or pointers as its first argument, and the object being + finalized as its second (rather than the reverse). For the majority of use cases + deprecation warnings will be triggered. However, deprecation warnings will not trigger where + (1) the callable argument is not a subtype of `Function`; or (2) both arguments are + `Function`s or `Ptr{Cvoid}`s ([#24605]). + + * The `kill` function now throws errors on user error (e.g. on permission + errors), but returns successfully if the process had previously exited. + Its return value has been removed. Use the `process_running` function + to determine if a process has already exited. + + * The logging system has been redesigned - `info` and `warn` are deprecated + and replaced with the logging macros `@info`, `@warn`, `@debug` and + `@error`. The `logging` function is also deprecated and replaced with + `AbstractLogger` and the functions from the new standard `Logging` library. + ([#24490]) + + * The `RevString` type has been removed from the language; `reverse(::String)` returns + a `String` with code points (or fragments thereof) in reverse order. In general, + `reverse(s)` should return a string of the same type and encoding as `s` with code + points in reverse order; any string type overrides `reverse` to return a different + type of string must also override `reverseind` to compute reversed indices correctly. + + * `eachindex(A, B...)` now requires that all inputs have the same number of elements. + When the chosen indexing is Cartesian, they must have the same axes. + + * `AbstractRange` objects are now considered as equal to other `AbstractArray` objects + by `==` and `isequal` if all of their elements are equal ([#16401]). + This has required changing the hashing algorithm: ranges now use an O(N) fallback + instead of a O(1) specialized method unless they define the `Base.RangeStepStyle` + trait; see its documentation for details. Types which support subtraction (operator + `-`) must now implement `widen` for hashing to work inside heterogeneous arrays. + + * `findn(x::AbstractArray)` has been deprecated in favor of `findall(!iszero, x)`, which + now returns cartesian indices for multidimensional arrays (see below, [#25532]). + + * Broadcasting operations are no longer fused into a single operation by Julia's parser. + Instead, a lazy `Broadcasted` object is created to represent the fused expression and + then realized with `copy(bc::Broadcasted)` or `copyto!(dest, bc::Broadcasted)` + to evaluate the wrapper. Consequently, package authors generally need to specialize + `copy` and `copyto!` methods rather than `broadcast` and `broadcast!`. This also allows + for more customization and control of fused broadcasts. See the + [Interfaces chapter](https://docs.julialang.org/en/latest/manual/interfaces/#man-interfaces-broadcasting-1) + for more information. + + * `find` has been renamed to `findall`. `findall`, `findfirst`, `findlast`, `findnext` + now take and/or return the same type of indices as `keys`/`pairs` for `AbstractArray`, + `AbstractDict`, `AbstractString`, `Tuple` and `NamedTuple` objects ([#24774], [#25545]). + In particular, this means that they use `CartesianIndex` objects for matrices + and higher-dimensional arrays instead of linear indices as was previously the case. + Use `LinearIndices(a)[findall(f, a)]` and similar constructs to compute linear indices. + + * The `find*` functions, i.e. `findnext`, `findprev`, `findfirst`, + and `findlast`, as well as `indexin`, now return `nothing` when no match is found rather + than `0` or `0:-1` ([#25472], [#25662], [#26149]) + + * The `Base.HasShape` iterator trait has gained a type parameter `N` indicating the + number of dimensions, which must correspond to the length of the tuple returned by + `size` ([#25655]). + + * `AbstractSet` objects are now considered equal by `==` and `isequal` if all of their + elements are equal ([#25368]). This has required changing the hashing algorithm + for `BitSet`. + + * the default behavior of `titlecase` is changed in two ways ([#23393]): + + characters not starting a word are converted to lowercase; + a new keyword argument `strict` is added which + allows to get the old behavior when it's `false`. + + any non-letter character is considered as a word separator; + to get the old behavior (only "space" characters are considered as + word separators), use the keyword `wordsep=isspace`. + + * `writedlm` in the standard library module DelimitedFiles now writes numeric values + using `print` rather than `print_shortest` ([#25745]). + + * The `tempname` function used to create a file on Windows but not on other + platforms. It now never creates a file ([#9053]). + + * The `fieldnames` and `propertynames` functions now return a tuple rather than + an array ([#25725]). + + * `indexin` now returns the first rather than the last matching index ([#25998]). + + * `parse(::Type, ::Char)` now uses a default base of 10, like other number parsing + methods, instead of 36 ([#26576]). + + * `isequal` for `Ptr`s now compares element types; `==` still compares only addresses + ([#26858]). + + * `widen` on 8- and 16-bit integer types now widens to 16- and 32-bit types, respectively. ([#28045]). + + * `mv`,`cp`, `touch`, `mkdir`, `mkpath`, `chmod` and `chown` now return the path that was created/modified + rather than `nothing` ([#27071]). + + * Regular expressions now default to UCP mode. Escape sequences such as `\w` + will now match based on unicode character properties, e.g. `r"\w+"` will + match `café` (not just `caf`). Add the `a` modifier (e.g. `r"\w+"a`) to + restore the previous behavior ([#27189]). + + * `@sync` now waits only for *lexically* enclosed (i.e. visible directly in the source + text of its argument) `@async` expressions. If you need to wait for a task created by + a called function `f`, have `f` return the task and put `@async wait(f(...))` within + the `@sync` block. + This change makes `@schedule` redundant with `@async`, so `@schedule` has been + deprecated ([#27164]). + + * `norm(A::AbstractMatrix, p=2)` computes no longer the operator/matrix norm but the `norm` of `A` + as for other iterables, i.e. as if it were a vector. Especially, `norm(A::AbstractMatrix)` is the + Frobenius norm. To compute the operator/matrix norm, use the new function `opnorm` ([#27401]). + + * `dot(u, v)` now acts recursively. Instead of `sum(u[i]' * v[i] for i in ...)`, it computes + `sum(dot(u[i], v[i]) for i in ...)`, similarly to `vecdot` before ([#27401]). + + * `Sys.CPU_CORES` has been renamed to `Sys.CPU_THREADS`; it still gives the number + of "logical cores" (including hyperthreading) rather than the number of physical + cores present on the CPU. Similarly, the environment variable `JULIA_CPU_CORES` is + deprecated in favor of `JULIA_CPU_THREADS` ([#27856]). + + * `WeakKeyDict` does not convert keys on insertion anymore (#24941). + Library improvements -------------------- + * The function `thisind(s::AbstractString, i::Integer)` returns the largest valid index + less or equal than `i` in the string `s` or `0` if no such index exists ([#24414]). + + * Support for Unicode 11 ([#28266]). + + * `Char` is now a subtype of `AbstractChar`, and most of the functions that + take character arguments now accept any `AbstractChar` ([#26286]). + + * `pathof(module)` returns the path a module was imported from ([#28310]). + + * `bytes2hex` now accepts an optional `io` argument to output to a hexadecimal stream + without allocating a `String` first ([#27121]). + + * `String(array)` now accepts an arbitrary `AbstractVector{UInt8}`. For `Vector` + inputs, it "steals" the memory buffer, leaving them with an empty buffer which + is guaranteed not to be shared with the `String` object. For other types of vectors + (in particular immutable vectors), a copy is made and the input is not truncated ([#26093]). + + * `Irrational` is now a subtype of `AbstractIrrational` ([#24245]). + + * Introduced the `empty` function, the functional pair to `empty!` which returns a new, + empty container ([#24390]). + + * Jump to first/last history entries in the REPL via "Alt-<" and "Alt->" ([#22829]). + + * REPL LaTeX-like tab completions have been simplified for several Unicode characters, + e.g. `𝔸` is now `\bbA` rather than `\BbbA` ([#25980]). + + * The function `chop` now accepts two arguments `head` and `tail` allowing to specify + number of characters to remove from the head and tail of the string ([#24126]). + + * `get(io, :color, false)` can now be used to query whether a stream `io` supports + [ANSI color codes](https://en.wikipedia.org/wiki/ANSI_escape_code) ([#25067]), + rather than using the undocumented `Base.have_color` global flag. + + * `print_with_color` has been deprecated in favor of + `printstyled([io], xs...; bold=false, color=:normal)` for printing styled text ([#25522]). + + * Functions `first` and `last` now accept `nchar` argument for `AbstractString`. + If this argument is used they return a string consisting of first/last `nchar` + characters from the original string ([#23960]). + + * Expressions `x^-n` where `n` is an *integer literal* now correspond to `inv(x)^n`. + For example, `x^-1` is now essentially a synonym for `inv(x)`, and works + in a type-stable way even if `typeof(x) != typeof(inv(x))` ([#24240]). + + * New `Iterators.reverse(itr)` for reverse-order iteration ([#24187]). Iterator + types `T` can implement `start` etc. for `Iterators.Reverse{T}` to support this. + + * The functions `nextind` and `prevind` now accept `nchar` argument that indicates + the number of characters to move ([#23805]). + + * The functions `strip`, `lstrip` and `rstrip` now return `SubString` ([#22496]). + + * The functions `strwidth` and `charwidth` have been merged into `textwidth`([#20816]). + + * The functions `base` and `digits` digits now accept a negative + base (like `ndigits` did) ([#21692]). + + * The function `randn` now accepts complex arguments (`Complex{T <: AbstractFloat}`) + ([#21973]). + + * `parse(Complex{T}, string)` can parse complex numbers in some common formats ([#24713]). + + * The function `rand` can now pick up random elements from strings, associatives + and sets ([#22228], [#21960], [#18155], [#22224]). + + * It's now possible to specify the characters to pick from in the `randstring` function ([#22222]). + + * Allow multidimensional arrays in `shuffle` and `shuffle!` functions ([#22226]). + + * Method lists are now printed as a numbered list. In addition, the source code of a + method can be opened in an editor by entering the corresponding number in the REPL + and pressing `^Q` ([#22007]). + + * `getpeername` on a `TCPSocket` returns the address and port of the remote + endpoint of the TCP connection ([#21825]). + + * `resize!` and `sizehint!` methods no longer over-reserve memory when the + requested array size is more than double of its current size ([#22038]). + + * The `crc32c` function for CRC-32c checksums is now exported ([#22274]). + + * `eye(::Type{Diagonal{T}}, m::Integer)` has been deprecated in favor of + `Diagonal{T}(I, m)` ([#24413]). + + * The output of `versioninfo` is now controlled with keyword arguments ([#21974]). + + * The function `LibGit2.set_remote_url` now always sets both the fetch and push URLs for a + git repo. Additionally, the argument order was changed to be consistent with the git + command line tool ([#22062]). + + * Added `unique!` which is an inplace version of `unique` ([#20549]). + + * `@test isequal(x, y)` and `@test isapprox(x, y)` now prints an evaluated expression when + the test fails ([#22296]). + + * Uses of `Val{c}` in `Base` has been replaced with `Val{c}()`, which is now easily + accessible via the efficient constructor `Val(c)`. Functions are defined as + `f(::Val{c}) = ...` and called by `f(Val(c))`. Notable affected functions include: + `ntuple`, `Base.literal_pow`, `sqrtm`, `lufact`, `lufact!`, `qrfact`, `qrfact!`, + `cholfact`, `cholfact!`, `_broadcast!`, `reshape`, `cat` and `cat_t`. + + * A new `@macroexpand1` macro for non recursive macro expansion ([#21662]). + + * `Char`s can now be concatenated with `String`s and/or other `Char`s using `*` ([#22532]). + + * `Diagonal`, `Bidiagonal`, `Tridiagonal` and `SymTridiagonal` are now parameterized on + the type of the wrapped vectors, allowing `Diagonal`, `Bidiagonal`, `Tridiagonal` and + `SymTridiagonal` matrices with arbitrary `AbstractVector`s + ([#22718], [#22925], [#23035], [#23154]). + + * Mutating versions of `randperm` and `randcycle` have been added: + `randperm!` and `randcycle!` ([#22723]). + + * `BigFloat` random numbers can now be generated ([#22720]). + + * The efficiency of random generation for MersenneTwister RNGs has been improved for + integers, `Float64` and ranges; as a result, given a seed, the produced stream of numbers + has changed ([#27560], [#25277], [#25197], [#25058], [#25047]). + + * REPL Undo via Ctrl-/ and Ctrl-_ + + * `diagm` now accepts several diagonal index/vector `Pair`s ([#24047]). + + * `isequal`, `==`, and `in` have one argument "curried" forms. For example `isequal(x)` + returns a function that compares its argument to `x` using `isequal` ([#26436]). + + * `reinterpret` now works on any AbstractArray using the new `ReinterpretArray` type. + This supersedes the old behavior of reinterpret on Arrays. As a result, reinterpreting + arrays with different alignment requirements (removed in 0.6) is once again allowed ([#23750]). + + * The `keys` of an `Associative` are now an `AbstractSet`. `Base.KeyIterator{<:Associative}` + has been changed to `KeySet{K, <:Associative{K}} <: AbstractSet{K}` ([#24580]). + + * New function `ncodeunits(s::AbstractString)` gives the number of code units in a string. + The generic definition is constant time but calls `lastindex(s)` which may be inefficient. + Therefore custom string types may want to define direct `ncodeunits` methods. + + * `reverseind(s::AbstractString, i::Integer)` now has an efficient generic fallback, so + custom string types do not need to provide their own efficient definitions. The generic + definition relies on `ncodeunits` however, so for optimal performance you may need to + define a custom method for that function. + + * The global RNG is being re-seeded with its own seed at the beginning of each `@testset`, + and have its original state restored at the end ([#24445]). This is breaking for testsets + relying implicitly on the global RNG being in a specific state. + + * `permutedims(m::AbstractMatrix)` is now short for `permutedims(m, (2,1))`, and is now a + more convenient way of making a "shallow transpose" of a 2D array. This is the + recommended approach for manipulating arrays of data, rather than the recursively + defined, linear-algebra function `transpose`. Similarly, + `permutedims(v::AbstractVector)` will create a row matrix ([#24839]). + + * A new `replace(A, old=>new)` function is introduced to replace `old` by `new` in + collection `A`. There is also another method with a different API, and + a mutating variant, `replace!` ([#22324], [#25697], [#26206], [#27944]). + + * Adding integers to `CartesianIndex` objects is now deprecated. Instead of + `i::Int + x::CartesianIndex`, use `i*one(x) + x` ([#26284]). + + * `CartesianRange` changes ([#24715]): + - Inherits from `AbstractArray`, and linear indexing can be used to provide + linear-to-cartesian conversion ([#24715]) + - It has a new constructor taking an array + + * several missing set-like operations have been added ([#23528]): + `union`, `intersect`, `symdiff`, `setdiff` are now implemented for + all collections with arbitrary many arguments, as well as the + mutating counterparts (`union!` etc.). The performance is also + much better in many cases. Note that this change is slightly + breaking: all the non-mutating functions always return a new + object even if only one argument is passed. Moreover the semantics + of `intersect` and `symdiff` is changed for vectors: + + `intersect` doesn't preserve the multiplicity anymore (use `filter` for + the old behavior) + + `symdiff` has been made consistent with the corresponding methods for + other containers, by taking the multiplicity of the arguments into account. + Use `unique` to get the old behavior. + + * The `linearindices` function has been deprecated in favor of the new + `LinearIndices` type, which additionally provides conversion from + cartesian indices to linear indices using the normal indexing operation. + ([#24715], [#26775]). + + * `IdDict{K,V}` replaces `ObjectIdDict`. It has type parameters + like other `AbstractDict` subtypes and its constructors mirror the + ones of `Dict`. ([#25210]) + + * `IOBuffer` can take the `sizehint` keyword argument to suggest a capacity of + the buffer ([#25944]). + + * `lstrip` and `rstrip` now accept a predicate function that defaults to `isspace` + ([#27309]). + + * `trunc`, `floor`, `ceil`, and `round` specify `digits`, `sigdigits` and `base` using + keyword arguments. ([#26156], [#26670]) + + * `Sys.which()` provides a cross-platform method to find executable files, similar to + the Unix `which` command. ([#26559]) + + * Added an optimized method of `vecdot` for taking the Frobenius inner product + of sparse matrices. ([#27470]) + + * Added an optimized method of `kron` for taking the tensor product of two + `Diagonal` matrices. ([27581]) + + * An official API for extending `rand` is now defined ([#23964], [#25002]). + + * The constructor `MersenneTwister()` is re-enabled, producing a randomly initialized RNG + (similar to `Random.seed!(MersenneTwister(0))`) ([#21909]). + + * `BitSet` can now store any `Int` (instead of only positive ones) ([#25029]). + + * The initial element `v0` in `reduce(op, v0, itr)` has been replaced with an `init` + optional keyword argument, as in `reduce(op, itr; init=v0)`. Similarly for `foldl`, + `foldr`, `mapreduce`, `mapfoldl`, `mapfoldr`, `accumulate` and `accumulate!`. + ([#27711], [#27859]) + Compiler/Runtime improvements ----------------------------- + * The inlining heuristic now models the approximate runtime cost of + a method (using some strongly-simplifying assumptions). Functions + are inlined unless their estimated runtime cost substantially + exceeds the cost of setting up and issuing a subroutine + call. ([#22210], [#22732]) + + * Inference recursion-detection heuristics are now more precise, + allowing them to be triggered less often, but being more aggressive when they + are triggered to drive the inference computation to a solution ([#23912]). + + * Inference now propagates constants inter-procedurally, and can compute + various constants expressions at compile-time ([#24362]). + + * The LLVM SLP Vectorizer optimization pass is now enabled at the default + optimization level. + Deprecated or removed --------------------- -The old package manager (now called `OldPkg`) has been moved to a -separate repository at https://github.com/JuliaArchive/OldPkg.jl ([#27930]) + * The `JULIA_HOME` environment variable has been renamed to `JULIA_BINDIR` and + `Base.JULIA_HOME` has been moved to `Sys.BINDIR` ([#20899]). + + * The keyword `immutable` is fully deprecated to `struct`, and + `type` is fully deprecated to `mutable struct` ([#19157], [#20418]). + + * `lufact`, `schurfact`, `lqfact`, `qrfact`, `ldltfact`, `svdfact`, + `bkfact`, `hessfact`, `eigfact`, and `cholfact` have respectively been + deprecated to `lu`, `schur`, `lq`, `qr`, `ldlt`, `svd`, `bunchkaufman`, + `hessenberg`, `eigen`, and `cholesky` ([#26997], [#27159], [#27212]). + + * `lufact!`, `schurfact!`, `lqfact!`, `qrfact!`, `ldltfact!`, `svdfact!`, + `bkfact!`, `hessfact!`, and `eigfact!` have respectively been deprecated to + `lu!`, `schur!`, `lq!`, `qr!`, `ldlt!`, `svd!`, `bunchkaufman!`, + `hessenberg!`, and `eigen!` ([#26997], [#27159], [#27212]). + + * `eig(A[, args...])` has been deprecated in favor of `eigen(A[, args...])`. + Whereas the former returns a tuple of arrays, the latter returns an `Eigen` object. + So for a direct replacement, use `(eigen(A[, args...])...,)`. But going forward, + consider using the direct result of `eigen(A[, args...])` instead, either + destructured into its components (`vals, vecs = eigen(A[, args...])`) or + as an `Eigen` object (`X = eigen(A[, args...])`) ([#26997], [#27159], [#27212]). + + * `eig(A::AbstractMatrix, B::AbstractMatrix)` and `eig(A::Number, B::Number)` + have been deprecated in favor of `eigen(A, B)`. Whereas the former each return + a tuple of arrays, the latter returns a `GeneralizedEigen` object. So for a direct + replacement, use `(eigen(A, B)...,)`. But going forward, consider using the + direct result of `eigen(A, B)` instead, either destructured into its components + (`vals, vecs = eigen(A, B)`), or as a `GeneralizedEigen` object + (`X = eigen(A, B)`) ([#26997], [#27159], [#27212]). + + * `ordschur(T::StridedMatrix{Ty}, Z::StridedMatrix{Ty}, select::Union{Vector{Bool},BitVector})` + and `ordschur(S::StridedMatrix{Ty}, T::StridedMatrix{Ty}, Q::StridedMatrix{Ty}, + Z::StridedMatrix{Ty}, select::Union{Vector{Bool},BitVector})` and their respective + inplace versions have been deprecated. + Use `ordschur(schur::Schur, select::Union{Vector{Bool},BitVector})` and + `ordschur(gschur::GeneralizedSchur, select::Union{Vector{Bool},BitVector})` instead + ([#28155]). + + * Indexing into multidimensional arrays with more than one index but fewer indices than there are + dimensions is no longer permitted when those trailing dimensions have lengths greater than 1. + Instead, reshape the array or add trailing indices so the dimensionality and number of indices + match ([#14770], [#23628]). + + * The use of a positional dimension argument has largely been deprecated in favor of a + `dims` keyword argument. This includes the functions `sum`, `prod`, `maximum`, + `minimum`, `all`, `any`, `findmax`, `findmin`, `mean`, `varm`, `std`, `var`, `cov`, + `cor`, `median`, `mapreducedim`, `reducedim`, `sort`, `accumulate`, `accumulate!`, + `cumsum`, `cumsum!`, `cumprod`, `cumprod!`, `flipdim`, `dropdims`, and `cat` ([#25501], [#26660], [#27100]). + + * `indices(a)` and `indices(a,d)` have been deprecated in favor of `axes(a)` and + `axes(a, d)` ([#25057]). + + * `EnvHash` has been renamed to `EnvDict` ([#24167]). + + * Uninitialized `Array` constructors of the form + `Array[{T,N}](shape...)` have been deprecated in favor of equivalents + accepting `undef` (an alias for `UndefInitializer()`) as their first argument, + as in `Array[{T,N}](undef, shape...)`. For example, + `Vector(3)` is now `Vector(undef, 3)`, `Matrix{Int}((2, 4))` is now, + `Matrix{Int}(undef, (2, 4))`, and `Array{Float32,3}(11, 13, 17)` is now + `Array{Float32,3}(undef, 11, 13, 17)` ([#24781]). + + * Previously `setindex!(A, x, I...)` (and the syntax `A[I...] = x`) supported two + different modes of operation when supplied with a set of non-scalar indices `I` + (e.g., at least one index is an `AbstractArray`) depending upon the value of `x` + on the right hand side. If `x` is an `AbstractArray`, its _contents_ are copied + elementwise into the locations in `A` selected by `I` and it must have the same + number of elements as `I` selects locations. Otherwise, if `x` is not an + `AbstractArray`, then its _value_ is implicitly broadcast to all locations to + all locations in `A` selected by `I`. This latter behavior—implicitly broadcasting + "scalar"-like values across many locations—is now deprecated in favor of explicitly + using the broadcasted assignment syntax `A[I...] .= x` or `fill!(view(A, I...), x)` + ([#26347]). + + * `broadcast_getindex(A, I...)` and `broadcast_setindex!(A, v, I...)` are deprecated in + favor of `getindex.((A,), I...)` and `setindex!.((A,), v, I...)`, respectively ([#27075]). + + * `LinAlg.fillslots!` has been renamed `LinAlg.fillstored!` ([#25030]). + + * `fill!(A::Diagonal, x)` and `fill!(A::AbstractTriangular, x)` have been deprecated + in favor of `Base.LinAlg.fillstored!(A, x)` ([#24413]). + + * `eye` has been deprecated in favor of `I` and `Matrix` constructors. Please see the + deprecation warnings for replacement details ([#24438]). + + * `zeros(D::Diagonal[, opts...])` has been deprecated ([#24654]). + + * Using Bool values directly as indices is now deprecated and will be an error in the future. Convert + them to `Int` before indexing if you intend to access index `1` for `true` and `0` for `false`. + + * `slicedim(A, d, i)` has been deprecated in favor of `copy(selectdim(A, d, i))`. The new + `selectdim` function now always returns a view into `A`; in many cases the `copy` is + not necessary. Previously, `slicedim` on a vector `V` over dimension `d=1` and scalar + index `i` would return the just selected element (unless `V` was a `BitVector`). This + has now been made consistent: `selectdim` now always returns a view into the original + array, with a zero-dimensional view in this specific case ([#26009]). + + * `whos` has been renamed `varinfo`, and now returns a markdown table instead of printing + output ([#12131]). + + * Uninitialized `RowVector` constructors of the form `RowVector{T}(shape...)` have been + deprecated in favor of equivalents accepting `undef` (an alias for + `UndefInitializer()`) as their first argument, as in + `RowVector{T}(undef, shape...)`. For example, `RowVector{Int}(3)` is now + `RowVector{Int}(undef, 3)`, and `RowVector{Float32}((1, 4))` is now + `RowVector{Float32}(undef, (1, 4))` ([#24786]). + + * `writecsv(io, a; opts...)` has been deprecated in favor of + `writedlm(io, a, ','; opts...)` ([#23529]). + + * The method `srand(rng, filename, n=4)` has been deprecated ([#21359]). + + * `readcsv(io[, T::Type]; opts...)` has been deprecated in favor of + `readdlm(io, ','[, T]; opts...)` ([#23530]). + + * `sparse(s::UniformScaling, m::Integer)` has been deprecated in favor of the + three-argument equivalent `sparse(s::UniformScaling, m, n)` ([#24472]). + + * The `cholfact`/`cholfact!` methods that accepted an `uplo` symbol have been deprecated + in favor of using `Hermitian` (or `Symmetric`) views ([#22187], [#22188]). + + * The `thin` keyword argument for orthogonal decomposition methods has + been deprecated in favor of `full`, which has the opposite meaning: + `thin == true` if and only if `full == false` ([#24279]). + + * `isposdef(A::AbstractMatrix, UL::Symbol)` and `isposdef!(A::AbstractMatrix, UL::Symbol)` + have been deprecated in favor of `isposdef(Hermitian(A, UL))` and `isposdef!(Hermitian(A, UL))` + respectively ([#22245]). + + * The `bkfact`/`bkfact!` methods that accepted `uplo` and `issymmetric` symbols have been deprecated + in favor of using `Hermitian` (or `Symmetric`) views ([#22605]). + + * The function `current_module` is deprecated and replaced with `@__MODULE__`. + This caused the deprecation of some reflection methods (such as `macroexpand` and + `isconst`), which now require a module argument. And it caused the bugfix of other + default arguments to use the Main module (including `whos`, `which`) ([#22064]). + + * `expand(ex)` and `expand(module, ex)` have been deprecated in favor of + `Meta.lower(module, ex)` ([#22064], [#24278]). + + * `ones(A::AbstractArray[, opts...])` and `zeros(A::AbstractArray[, opts...])` methods + have been deprecated. For `zeros(A)`, consider `zero(A)`. For `ones(A)` or `zeros(A)`, + consider `ones(size(A))`, `zeros(size(A))`, `fill(v, size(A))` for `v` an appropriate + one or zero, `fill!(copy(A), {1|0})`, `fill!(similar(A), {1|0})`, or any of the preceding + with different element type and/or shape depending on `opts...`. Where strictly + necessary, consider `fill!(similar(A[, opts...]), {one(eltype(A)) | zero(eltype(A))})`. + For an algebraic multiplicative identity, consider `one(A)` ([#24656]). + + * The `similar(dims->f(..., dims...), [T], axes...)` method to add offset array support + to a function `f` that would otherwise create a non-offset array has been deprecated. + Instead, call `f(..., axes...)` directly and, if needed, the offset array implementation + should add offset axis support to the function `f` directly ([#26733]). + + * The functions `ones` and `zeros` used to accept any objects as dimensional arguments, + implicitly converting them to `Int`s. This is now deprecated; only `Integer`s or + `AbstractUnitRange`s are accepted as arguments. Instead, convert the arguments before + calling `ones` or `zeros` ([#26733]). + + * The variadic `size(A, dim1, dim2, dims...)` method to return a tuple of multiple + dimension lengths of `A` has been deprecated ([#26862]). + + * The `Operators` module is deprecated. Instead, import required operators explicitly + from `Base`, e.g. `import Base: +, -, *, /` ([#22251]). + + * Bindings to the FFTW library have been removed from Base. The DFT framework for building FFT + implementations is now in AbstractFFTs.jl, the bindings to the FFTW library are in FFTW.jl, + and the Base signal processing functions which used FFTs are now in DSP.jl ([#21956]). + + * The `corrected` positional argument to `cov` has been deprecated in favor of + a keyword argument with the same name ([#21709]). + + * Omitting spaces around the `?` and the `:` tokens in a ternary expression has been deprecated. + Ternaries must now include some amount of whitespace, e.g. `x ? a : b` rather than + `x?a:b` ([#22523] and [#22712]). + + * `?` can no longer be used as an identifier name ([#22712]) + + * The method `replace(s::AbstractString, pat, r, [count])` is deprecated + in favor of `replace(s::AbstractString, pat => r; [count])` ([#25165]). + Moreover, `count` cannot be negative anymore (use `typemax(Int)` instead ([#22325]). + + * `read(io, type, dims)` is deprecated to `read!(io, Array{type}(undef, dims))` ([#21450]). + + * `read(::IO, ::Ref)` is now a method of `read!`, since it mutates its `Ref` argument ([#21592]). + + * `nb_available` is now `bytesavailable` ([#25634]). + + * `skipchars(io::IO, predicate; linecomment=nothing)` is deprecated in favor of + `skipchars(predicate, io::IO; linecomment=nothing)` ([#25667]). + + * `Bidiagonal` constructors now use a `Symbol` (`:U` or `:L`) for the upper/lower + argument, instead of a `Bool` or a `Char` ([#22703]). + + * `Bidiagonal`, `Tridiagonal` and `SymTridiagonal` constructors that automatically + converted the input vectors to the same type are deprecated in favor of explicit + conversion ([#22925], [#23035], [#23154]. + + * Calling `nfields` on a type to find out how many fields its instances have is deprecated. + Use `fieldcount` instead. Use `nfields` only to get the number of fields in a specific object ([#22350]). + + * `fieldnames` now operates only on types. To get the names of fields in an object, use + `fieldnames(typeof(x))` ([#22350]). + + * `InexactError`, `DomainError`, and `OverflowError` now take + arguments. `InexactError(func::Symbol, type, -3)` now prints as + "ERROR: InexactError: func(type, -3)", `DomainError(val, + [msg])` prints as "ERROR: DomainError with val:\nmsg", + and `OverflowError(msg)` prints as "ERROR: OverflowError: msg". + ([#20005], [#22751], [#22761]) + + * The operating system identification functions: `is_linux`, `is_bsd`, `is_apple`, `is_unix`, + and `is_windows`, have been deprecated in favor of `Sys.islinux`, `Sys.isbsd`, `Sys.isapple`, + `Sys.isunix`, and `Sys.iswindows`, respectively ([#22182]). + + * The forms of `read`, `readstring`, and `eachline` that accepted both a `Cmd` object and an + input stream are deprecated. Use e.g. `read(pipeline(stdin, cmd))` instead ([#22762]). + + * The unexported type `AbstractIOBuffer` has been renamed to `GenericIOBuffer` ([#17360] [#22796]). + + * `IOBuffer(data::AbstractVector{UInt8}, read::Bool, write::Bool, maxsize::Integer)`, + `IOBuffer(read::Bool, write::Bool)`, and `IOBuffer(maxsize::Integer)` are + deprecated in favor of constructors taking keyword arguments ([#25872]). + + * `Display` has been renamed to `AbstractDisplay` ([#24831]). + + * Remaining vectorized methods over `SparseVector`s, particularly `floor`, `ceil`, + `trunc`, `round`, and most common transcendental functions such as `exp`, `log`, and + `sin` variants, have been deprecated in favor of dot-syntax ([#22961]). + + * The method `String(io::IOBuffer)` is deprecated to `String(take!(copy(io)))` ([#21438]). + + * The function `readstring` is deprecated in favor of `read(io, String)` ([#22793]) + + * The function `showall` is deprecated. Showing entire values is the default, unless an + `IOContext` specifying `:limit=>true` is in use ([#22847]). + + * `issubtype` has been deprecated in favor of `<:` (which used to be an alias for `issubtype`). + + * Calling `write` on non-isbits arrays is deprecated in favor of explicit loops or + `serialize` ([#6466]). + + * The default `startup.jl` file on Windows has been removed. Now must explicitly include the + full path if you need access to executables or libraries in the `Sys.BINDIR` directory, e.g. + `joinpath(Sys.BINDIR, "7z.exe")` for `7z.exe` ([#21540]). + + * `sqrtm` has been deprecated in favor of `sqrt` ([#23504]). + + * `expm` has been deprecated in favor of `exp` ([#23233]). + + * `logm` has been deprecated in favor of `log` ([#23505]). + + * `full` has been deprecated in favor of more specific, better defined alternatives. + On structured matrices `A`, consider instead `Matrix(A)`, `Array(A)`, + `SparseMatrixCSC(A)`, or `sparse(A)`. On sparse arrays `S`, consider instead + `Vector(S)`, `Matrix(S)`, or `Array(S)` as appropriate. On factorizations `F`, + consider instead `Matrix(F)`, `Array(F)`, `AbstractMatrix(F)`, or `AbstractArray(F)`. + On implicit orthogonal factors `Q`, consider instead `Matrix(Q)` or `Array(Q)`; for + implicit orthogonal factors that can be recovered in square or truncated form, + see the deprecation message for square recovery instructions. On `Symmetric`, + `Hermitian`, or `AbstractTriangular` matrices `A`, consider instead `Matrix(S)`, + `Array(S)`, `SparseMatrixCSC(S)`, or `sparse(S)`. On `Symmetric` matrices `A` + particularly, consider instead `LinAlg.copytri!(copy(parent(A)), A.uplo)`. On + `Hermitian` matrices `A` particularly, consider instead + `LinAlg.copytri!(copy(parent(A)), A.uplo, true)`. On `UpperTriangular` matrices `A` + particularly, consider instead `triu!(copy(parent(A)))`. On `LowerTriangular` matrices + `A` particularly, consider instead `tril!(copy(parent(A)))` ([#24250]). + + * `speye` has been deprecated in favor of `I`, `sparse`, and `SparseMatrixCSC` + constructor methods ([#24356]). + + * Calling `union` with no arguments is deprecated; construct an empty set with an appropriate + element type using `Set{T}()` instead ([#23144]). + + * Vectorized `DateTime`, `Date`, and `format` methods have been deprecated in favor of + dot-syntax ([#23207]). + + * `Base.cpad` has been removed; use an appropriate combination of `rpad` and `lpad` + instead ([#23187]). + + * `ctranspose` and `ctranspose!` have been deprecated in favor of `adjoint` and `adjoint!`, + respectively ([#23235]). + + * `filter` and `filter!` on dictionaries now pass a single `key=>value` pair to the + argument function, instead of two arguments ([#17886]). + + * `rol`, `rol!`, `ror`, and `ror!` have been deprecated in favor of specialized methods for + `circshift`/`circshift!` ([#23404]). + + * `Base.SparseArrays.SpDiagIterator` has been removed ([#23261]). + + * The function `cfunction`, has been deprecated in favor of a macro form `@cfunction`. + Most existing uses can be upgraded simply by adding a `@`. + The new syntax now additionally supports allocating closures at runtime, + for dealing with C APIs that don't provide a separate `void* env`-type callback + argument. ([#26486]) + + * `diagm(v::AbstractVector, k::Integer=0)` has been deprecated in favor of + `diagm(k => v)` ([#24047]). + + * `diagm(x::Number)` has been deprecated in favor of `fill(x, 1, 1)` ([#24047]). + + * `diagm(A::SparseMatrixCSC)` has been deprecated in favor of + `spdiagm(sparsevec(A))` ([#23341]). + + * `diagm(A::BitMatrix)` has been deprecated, use `diagm(0 => vec(A))` or + `BitMatrix(Diagonal(vec(A)))` instead ([#23373], [#24047]). + + * `ℯ` (written as `\mscre` or `\euler`) is now the only (by default) exported + name for Euler's number, and the type has changed from `Irrational{:e}` to + `Irrational{:ℯ}` ([#23427]). + + * The mathematical constants `π`, `pi`, `ℯ`, `e`, `γ`, `eulergamma`, `catalan`, `φ` and + `golden` have been moved from `Base` to a new module; `Base.MathConstants`. + Only `π`, `pi` and `ℯ` are now exported by default from `Base` ([#23427]). + + * `eu` (previously an alias for `ℯ`) has been deprecated in favor of `ℯ` (or `MathConstants.e`) ([#23427]). + + * `GMP.gmp_version()`, `GMP.GMP_VERSION`, `GMP.gmp_bits_per_limb()`, and `GMP.GMP_BITS_PER_LIMB` + have been renamed to `GMP.version()`, `GMP.VERSION`, `GMP.bits_per_limb()`, and `GMP.BITS_PER_LIMB`, + respectively. Similarly, `MPFR.get_version()`, has been renamed to `MPFR.version()` ([#23323]). Also, + `LinAlg.LAPACK.laver()` has been renamed to `LinAlg.LAPACK.version()` and now returns a `VersionNumber`. + + * `select`, `select!`, `selectperm` and `selectperm!` have been renamed respectively to + `partialsort`, `partialsort!`, `partialsortperm` and `partialsortperm!` ([#23051]). + + * The `Range` abstract type has been renamed to `AbstractRange` ([#23570]). + + * `map` on dictionaries previously operated on `key=>value` pairs. This behavior is deprecated, + and in the future `map` will operate only on values ([#5794]). + + * `map` on sets previously returned a `Set`, possibly changing the order or number of elements. This + behavior is deprecated and in the future `map` will preserve order and number of elements ([#26980]). + + * Previously, broadcast defaulted to treating its arguments as scalars if they were not + arrays. This behavior is deprecated, and in the future `broadcast` will default to + iterating over all its arguments. Wrap arguments you wish to be treated as scalars with + `Ref()` or a 1-tuple. Package developers can choose to allow a non-iterable type `T` to + always behave as a scalar by implementing `broadcastable(x::T) = Ref(x)` ([#26212]). + + * Automatically broadcasted `+` and `-` for `array + scalar`, `scalar - array`, and so-on have + been deprecated due to inconsistency with linear algebra. Use `.+` and `.-` for these operations + instead ([#22880], [#22932]). + + * `flipbits!(B)` is deprecated in favor of using in-place broadcast to negate each element: + `B .= .!B` ([#27067]). + + * `isleaftype` is deprecated in favor of the simpler predicates `isconcretetype` and `isdispatchtuple`. + Concrete types are those that might equal `typeof(x)` for some `x`; + `isleaftype` included some types for which this is not true. Those are now categorized more precisely + as "dispatch tuple types" and "!has_free_typevars" (not exported). ([#17086], [#25496]) + + * `contains(eq, itr, item)` is deprecated in favor of `any` with a predicate ([#23716]). + + * `spdiagm(x::AbstractVector)` has been deprecated in favor of `sparse(Diagonal(x))` + alternatively `spdiagm(0 => x)` ([#23757]). + + * `spdiagm(x::AbstractVector, d::Integer)` and `spdiagm(x::Tuple{<:AbstractVector}, d::Tuple{<:Integer})` + have been deprecated in favor of `spdiagm(d => x)` and `spdiagm(d[1] => x[1], d[2] => x[2], ...)` + respectively. The new `spdiagm` implementation now always returns a square matrix ([#23757]). + + * `spones(A::AbstractSparseArray)` has been deprecated in favor of + `LinAlg.fillstored!(copy(A), 1)` ([#25037]). + + * Constructors for `LibGit2.UserPasswordCredentials` and `LibGit2.SSHCredentials` which take a + `prompt_if_incorrect` argument are deprecated. Instead, prompting behavior is controlled using + the `allow_prompt` keyword in the `LibGit2.CredentialPayload` constructor ([#23690]). + + * `gradient` is deprecated and will be removed in the next release ([#23816]). + + * The timing functions `tic`, `toc`, and `toq` are deprecated in favor of `@time` and `@elapsed` + ([#17046]). + + * Methods of `findfirst`, `findnext`, `findlast`, and `findprev` that accept a value to + search for are deprecated in favor of passing a predicate ([#19186], [#10593]). + + * `find` functions now operate only on booleans by default. To look for non-zeros, use + `x->x!=0` or `!iszero` ([#23120]). + + * The ability of `reinterpret` to yield `Array`s of different type than the underlying storage + has been removed. The `reinterpret` function is still available, but now returns a + `ReinterpretArray`. The three argument form of `reinterpret` that implicitly reshapes + has been deprecated ([#23750]). + + * `bits` has been deprecated in favor of `bitstring` ([#24281], [#24263]). + + * `num2hex` and `hex2num` have been deprecated in favor of `reinterpret` combined with `parse`/`hex` ([#22088]). + + * `copy!` is deprecated for `AbstractSet` and `AbstractDict`, with the intention to re-enable + it with a cleaner meaning in a future version ([#24844]). + + * `copy!` (resp. `unsafe_copy!`) is deprecated for `AbstractArray` and is renamed `copyto!` + (resp. `unsafe_copyto!`); it will be re-introduced with a different meaning in a future + version ([#24808]). + + * `a:b` is deprecated for constructing a `StepRange` when `a` and `b` have physical units + (Dates and Times). Use `a:s:b`, where `s = Dates.Day(1)` or `s = Dates.Second(1)`. + + * `trues(A::AbstractArray)` and `falses(A::AbstractArray)` are deprecated in favor of + `trues(size(A))` and `falses(size(A))` respectively ([#24595]). + + * `workspace` is discontinued, check out [Revise.jl](https://github.com/timholy/Revise.jl) + for an alternative workflow ([#25046]). + + * `cumsum`, `cumprod`, `accumulate`, their mutating versions, and `diff` all now require a `dim` + argument instead of defaulting to using the first dimension unless there is only + one dimension ([#24684], [#25457]). + + * The `sum_kbn` and `cumsum_kbn` functions have been moved to the + [KahanSummation](https://github.com/JuliaMath/KahanSummation.jl) package ([#24869]). + + * `isnumber` has been renamed to `isnumeric` ([#25021]). + + * `isalpha` has been renamed to `isletter` ([#26932]). + + * `is_assigned_char` and `normalize_string` have been renamed to `isassigned` and + `normalize`, and moved to the new `Unicode` standard library module. + `graphemes` has also been moved to that module ([#25021]). + + * Sparse array functionality has moved to the `SparseArrays` standard library module ([#25249]). + + * Linear algebra functionality, and specifically the `LinAlg` module has moved to the + `LinearAlgebra` standard library module ([#25571]). + + * `@printf` and `@sprintf` have been moved to the `Printf` standard library ([#23929],[#25056]). + + * The `Libdl` module has moved to the `Libdl` standard library module ([#25459]). + + * The aliases `Complex32`, `Complex64` and `Complex128` have been deprecated in favor of `ComplexF16`, + `ComplexF32` and `ComplexF64` respectively ([#24647]). + + * `Base.parentindexes` and `SharedArrays.localindexes` have been renamed to `parentindices` + and `localindices`, respectively. Similarly, the `indexes` field in the `SubArray` type + has been renamed to `indices` without deprecation ([#25088]). + + * `Associative` has been deprecated in favor of `AbstractDict` ([#25012]). + + * `Void` has been renamed back to `Nothing` with an alias `Cvoid` for use when calling C + with a return type of `Cvoid` or a return or argument type of `Ptr{Cvoid}` ([#25162]). + + * `Nullable{T}` has been deprecated and moved to the Nullables package ([#23642]). Use + `Union{T, Nothing}` instead, or `Union{Some{T}, Nothing}` if `nothing` is a possible + value (i.e. `Nothing <: T`). `isnull(x)` can be replaced with `x === nothing` and + `unsafe_get`/`get` can be dropped or replaced with `coalesce`. + `NullException` has been removed. + + * `unshift!` and `shift!` have been renamed to `pushfirst!` and `popfirst!` ([#23902]) + + * `ipermute!` has been deprecated in favor of `invpermute!` ([#25168]). + + * `CartesianRange` has been renamed `CartesianIndices` ([#24715]). + + * `sub2ind` and `ind2sub` are deprecated in favor of using `CartesianIndices` and `LinearIndices` ([#24715]). + + * `getindex(F::Factorization, s::Symbol)` (usually seen as e.g. `F[:Q]`) is deprecated + in favor of dot overloading (`getproperty`) so factors should now be accessed as e.g. + `F.Q` instead of `F[:Q]` ([#25184]). + + * `search` and `rsearch` have been deprecated in favor of `findfirst`/`findnext` and + `findlast`/`findprev` respectively, in combination with curried `isequal` and `in` + predicates for some methods ([#24673]). + + * `search(buf::IOBuffer, delim::UInt8)` has been deprecated in favor of either `occursin(delim, buf)` + (to test containment) or `readuntil(buf, delim)` (to read data up to `delim`) ([#26600]). + + * `ismatch(regex, str)` has been deprecated in favor of `contains(str, regex)` ([#24673]). + + * `matchall` has been deprecated in favor of `collect(m.match for m in eachmatch(r, s))` ([#26071]). + + * `similar(::Associative)` has been deprecated in favor of `empty(::Associative)`, and + `similar(::Associative, ::Pair{K, V})` has been deprecated in favour of + `empty(::Associative, K, V)` ([#24390]). + + * `findin(a, b)` has been deprecated in favor of `findall(in(b), a)` ([#24673]). + + * `module_name` has been deprecated in favor of a new, general `nameof` function. Similarly, + the unexported `Base.function_name` and `Base.datatype_name` have been deprecated in favor + of `nameof` methods ([#25622]). + + * The module `Random.dSFMT` is renamed `Random.DSFMT` ([#25567]). + + * `Random.RandomDevice(unlimited::Bool)` (on non-Windows systems) is deprecated in favor of + `Random.RandomDevice(; unlimited=unlimited)` ([#25668]). + + * The generic implementations of `strides(::AbstractArray)` and `stride(::AbstractArray, ::Int)` + have been deprecated. Subtypes of `AbstractArray` that implement the newly introduced strided + array interface should define their own `strides` method ([#25321]). + + * `module_parent`, `Base.datatype_module`, and `Base.function_module` have been deprecated + in favor of `parentmodule` ([#TODO]). + + * `rand(t::Tuple{Vararg{Int}})` is deprecated in favor of `rand(Float64, t)` or `rand(t...)`; + `rand(::Tuple)` will have another meaning in the future ([#25429], [#25278]). + + * `randjump`, which produced an array, is deprecated in favor of the + scalar version `Future.randjump` used with `accumulate` ([#27746]). + + * The `assert` function (and `@assert` macro) have been documented that they are not guaranteed to run under various optimization levels and should therefore not be used to e.g. verify passwords. + + * `ObjectIdDict` has been deprecated in favor of `IdDict{Any,Any}` ([#25210]). + + * `gc` and `gc_enable` have been deprecated in favor of `GC.gc` and `GC.enable` ([#25616]). + + * `Base.@gc_preserve` has been deprecated in favor of `GC.@preserve` ([#25616]). + + * `print_shortest` has been discontinued, but is still available in the `Base.Grisu` + submodule ([#25745]). + + * `scale!` has been deprecated in favor of `mul!`, `lmul!`, and `rmul!` ([#25701], [#25812]). + + * The `remove_destination` keyword argument to `cp`, `mv`, and the unexported `cptree` + has been renamed to `force` ([#25979]). + + * `contains` has been deprecated in favor of a more general `occursin` function, which + takes its arguments in reverse order from `contains` ([#26283]). + + * `Regex` objects are no longer callable. Use `occursin` instead ([#26283]). + + * The methods of `range` based on positional arguments have been deprecated in favor of + keyword arguments ([#25896]). + + * `linspace` has been deprecated in favor of `range` with `stop` and `length` keyword + arguments ([#25896]). + + * `LinSpace` has been renamed to `LinRange` ([#25896]). + + * `logspace` has been deprecated to its definition ([#25896]). + + * `endof(a)` has been renamed to `lastindex(a)`, and the `end` keyword in indexing expressions now + lowers to either `lastindex(a)` (in the case with only one index) or `lastindex(a, d)` (in cases + where there is more than one index and `end` appears at dimension `d`) ([#23554], [#25763]). + + * `DateTime()`, `Date()`, and `Time()` have been deprecated, instead use `DateTime(1)`, `Date(1)` + and `Time(0)` respectively ([#23724]). + + * The fallback method `^(x, p::Integer)` is deprecated. If your type relied on this definition, + add a method such as `^(x::MyType, p::Integer) = Base.power_by_squaring(x, p)` ([#23332]). + + * `DevNull`, `STDIN`, `STDOUT`, and `STDERR` have been renamed to `devnull`, `stdin`, `stdout`, + and `stderr`, respectively ([#25786]). + + * `wait` and `fetch` on `Task` now resemble the interface of `Future`. + + * `showcompact(io, x...)` has been deprecated in favor of + `show(IOContext(io, :compact => true), x...)` ([#26080]). + Use `sprint(show, x..., context=:compact => true)` instead of `sprint(showcompact, x...)`. + + * `isupper`, `islower`, `ucfirst` and `lcfirst` have been deprecated in favor of `isuppercase`, + `islowercase`, `uppercasefirst` and `lowercasefirst`, respectively ([#26442]). + + * `signif` has been deprecated in favor of the `sigdigits` keyword argument to `round`. + + * `Base.IntSet` has been deprecated in favor of `Base.BitSet` ([#24282]). + + * `setrounding` has been deprecated for `Float32` and `Float64`, as the behaviour was too unreliable ([#26935]). + + * `gamma`, `lgamma`, `beta`, `lbeta` and `lfact` have been moved to + [SpecialFunctions.jl](https://github.com/JuliaMath/SpecialFunctions.jl) ([#27459], [#27473]). + + * `atan2` is now a 2-argument method of `atan` ([#27248]). + + * The functions `eigs` and `svds` have been moved to the `Arpack.jl` package ([#27616]). + + * `vecdot` and `vecnorm` are deprecated in favor of `dot` and `norm`, respectively ([#27401]). + + * `clipboard` has been moved to the `InteractiveUtils` standard library package + (along with other utilities mostly used at the interactive prompt, such as `edit` + and `less`) ([#27635]). + + * `ndigits(n, b, [pad])` is deprecated in favor of `ndigits(n, base=b, pad=pad)` ([#27908]). + + * `squeeze` is deprecated in favor of `dropdims`. + + * `srand` is deprecated in favor of the unexported `Random.seed!` ([#27726]). + + * `realmin`/`realmax` are deprecated in favor of `floatmin`/`floatmax` ([#28302]). + + * `sortrows`/`sortcols` have been deprecated in favor of the more general `sortslices`. + + * `nextpow2`/`prevpow2` have been deprecated in favor of the more general `nextpow`/`prevpow` functions. Command-line option changes --------------------------- + * New option `--warn-overwrite={yes|no}` to control the warning for overwriting method + definitions. The default is `no` ([#23002]). + + * New option `--banner={yes,no}` allows suppressing or forcing the printing of the + startup banner, overriding the default behavior (banner in REPL, no banner otherwise). + The `--quiet` option implies `--banner=no` even in REPL mode but can be overridden by + passing `--quiet` together with `--banner=yes` ([#23342]). + + * The option `--precompiled` has been renamed to `--sysimage-native-code` ([#23054]). + + * The option `--compilecache` has been renamed to `--compiled-modules` ([#23054]). + -[#27930]: https://github.com/JuliaLang/julia/issues/27930 +[#330]: https://github.com/JuliaLang/julia/issues/330 +[#1974]: https://github.com/JuliaLang/julia/issues/1974 +[#4916]: https://github.com/JuliaLang/julia/issues/4916 +[#5148]: https://github.com/JuliaLang/julia/issues/5148 +[#5794]: https://github.com/JuliaLang/julia/issues/5794 +[#6080]: https://github.com/JuliaLang/julia/issues/6080 +[#6466]: https://github.com/JuliaLang/julia/issues/6466 +[#6614]: https://github.com/JuliaLang/julia/issues/6614 +[#8000]: https://github.com/JuliaLang/julia/issues/8000 +[#8470]: https://github.com/JuliaLang/julia/issues/8470 +[#9053]: https://github.com/JuliaLang/julia/issues/9053 +[#9292]: https://github.com/JuliaLang/julia/issues/9292 +[#10593]: https://github.com/JuliaLang/julia/issues/10593 +[#11310]: https://github.com/JuliaLang/julia/issues/11310 +[#12010]: https://github.com/JuliaLang/julia/issues/12010 +[#12131]: https://github.com/JuliaLang/julia/issues/12131 +[#13079]: https://github.com/JuliaLang/julia/issues/13079 +[#14770]: https://github.com/JuliaLang/julia/issues/14770 +[#15120]: https://github.com/JuliaLang/julia/issues/15120 +[#16356]: https://github.com/JuliaLang/julia/issues/16356 +[#16401]: https://github.com/JuliaLang/julia/issues/16401 +[#16937]: https://github.com/JuliaLang/julia/issues/16937 +[#17046]: https://github.com/JuliaLang/julia/issues/17046 +[#17086]: https://github.com/JuliaLang/julia/issues/17086 +[#17240]: https://github.com/JuliaLang/julia/issues/17240 +[#17360]: https://github.com/JuliaLang/julia/issues/17360 +[#17367]: https://github.com/JuliaLang/julia/issues/17367 +[#17886]: https://github.com/JuliaLang/julia/issues/17886 +[#17997]: https://github.com/JuliaLang/julia/issues/17997 +[#18155]: https://github.com/JuliaLang/julia/issues/18155 +[#18650]: https://github.com/JuliaLang/julia/issues/18650 +[#19089]: https://github.com/JuliaLang/julia/issues/19089 +[#19157]: https://github.com/JuliaLang/julia/issues/19157 +[#19186]: https://github.com/JuliaLang/julia/issues/19186 +[#19987]: https://github.com/JuliaLang/julia/issues/19987 +[#20005]: https://github.com/JuliaLang/julia/issues/20005 +[#20418]: https://github.com/JuliaLang/julia/issues/20418 +[#20549]: https://github.com/JuliaLang/julia/issues/20549 +[#20575]: https://github.com/JuliaLang/julia/issues/20575 +[#20816]: https://github.com/JuliaLang/julia/issues/20816 +[#20899]: https://github.com/JuliaLang/julia/issues/20899 +[#20912]: https://github.com/JuliaLang/julia/issues/20912 +[#20974]: https://github.com/JuliaLang/julia/issues/20974 +[#21359]: https://github.com/JuliaLang/julia/issues/21359 +[#21438]: https://github.com/JuliaLang/julia/issues/21438 +[#21450]: https://github.com/JuliaLang/julia/issues/21450 +[#21527]: https://github.com/JuliaLang/julia/issues/21527 +[#21540]: https://github.com/JuliaLang/julia/issues/21540 +[#21592]: https://github.com/JuliaLang/julia/issues/21592 +[#21662]: https://github.com/JuliaLang/julia/issues/21662 +[#21692]: https://github.com/JuliaLang/julia/issues/21692 +[#21697]: https://github.com/JuliaLang/julia/issues/21697 +[#21709]: https://github.com/JuliaLang/julia/issues/21709 +[#21746]: https://github.com/JuliaLang/julia/issues/21746 +[#21759]: https://github.com/JuliaLang/julia/issues/21759 +[#21774]: https://github.com/JuliaLang/julia/issues/21774 +[#21825]: https://github.com/JuliaLang/julia/issues/21825 +[#21909]: https://github.com/JuliaLang/julia/issues/21909 +[#21956]: https://github.com/JuliaLang/julia/issues/21956 +[#21960]: https://github.com/JuliaLang/julia/issues/21960 +[#21973]: https://github.com/JuliaLang/julia/issues/21973 +[#21974]: https://github.com/JuliaLang/julia/issues/21974 +[#22007]: https://github.com/JuliaLang/julia/issues/22007 +[#22038]: https://github.com/JuliaLang/julia/issues/22038 +[#22062]: https://github.com/JuliaLang/julia/issues/22062 +[#22064]: https://github.com/JuliaLang/julia/issues/22064 +[#22088]: https://github.com/JuliaLang/julia/issues/22088 +[#22089]: https://github.com/JuliaLang/julia/issues/22089 +[#22092]: https://github.com/JuliaLang/julia/issues/22092 +[#22182]: https://github.com/JuliaLang/julia/issues/22182 +[#22187]: https://github.com/JuliaLang/julia/issues/22187 +[#22188]: https://github.com/JuliaLang/julia/issues/22188 +[#22194]: https://github.com/JuliaLang/julia/issues/22194 +[#22210]: https://github.com/JuliaLang/julia/issues/22210 +[#22222]: https://github.com/JuliaLang/julia/issues/22222 +[#22224]: https://github.com/JuliaLang/julia/issues/22224 +[#22226]: https://github.com/JuliaLang/julia/issues/22226 +[#22228]: https://github.com/JuliaLang/julia/issues/22228 +[#22245]: https://github.com/JuliaLang/julia/issues/22245 +[#22251]: https://github.com/JuliaLang/julia/issues/22251 +[#22274]: https://github.com/JuliaLang/julia/issues/22274 +[#22281]: https://github.com/JuliaLang/julia/issues/22281 +[#22296]: https://github.com/JuliaLang/julia/issues/22296 +[#22314]: https://github.com/JuliaLang/julia/issues/22314 +[#22324]: https://github.com/JuliaLang/julia/issues/22324 +[#22325]: https://github.com/JuliaLang/julia/issues/22325 +[#22350]: https://github.com/JuliaLang/julia/issues/22350 +[#22390]: https://github.com/JuliaLang/julia/issues/22390 +[#22496]: https://github.com/JuliaLang/julia/issues/22496 +[#22511]: https://github.com/JuliaLang/julia/issues/22511 +[#22523]: https://github.com/JuliaLang/julia/issues/22523 +[#22532]: https://github.com/JuliaLang/julia/issues/22532 +[#22572]: https://github.com/JuliaLang/julia/issues/22572 +[#22588]: https://github.com/JuliaLang/julia/issues/22588 +[#22605]: https://github.com/JuliaLang/julia/issues/22605 +[#22666]: https://github.com/JuliaLang/julia/issues/22666 +[#22696]: https://github.com/JuliaLang/julia/issues/22696 +[#22703]: https://github.com/JuliaLang/julia/issues/22703 +[#22712]: https://github.com/JuliaLang/julia/issues/22712 +[#22718]: https://github.com/JuliaLang/julia/issues/22718 +[#22720]: https://github.com/JuliaLang/julia/issues/22720 +[#22723]: https://github.com/JuliaLang/julia/issues/22723 +[#22732]: https://github.com/JuliaLang/julia/issues/22732 +[#22742]: https://github.com/JuliaLang/julia/issues/22742 +[#22751]: https://github.com/JuliaLang/julia/issues/22751 +[#22761]: https://github.com/JuliaLang/julia/issues/22761 +[#22762]: https://github.com/JuliaLang/julia/issues/22762 +[#22789]: https://github.com/JuliaLang/julia/issues/22789 +[#22793]: https://github.com/JuliaLang/julia/issues/22793 +[#22796]: https://github.com/JuliaLang/julia/issues/22796 +[#22800]: https://github.com/JuliaLang/julia/issues/22800 +[#22801]: https://github.com/JuliaLang/julia/issues/22801 +[#22814]: https://github.com/JuliaLang/julia/issues/22814 +[#22825]: https://github.com/JuliaLang/julia/issues/22825 +[#22829]: https://github.com/JuliaLang/julia/issues/22829 +[#22847]: https://github.com/JuliaLang/julia/issues/22847 +[#22868]: https://github.com/JuliaLang/julia/issues/22868 +[#22880]: https://github.com/JuliaLang/julia/issues/22880 +[#22907]: https://github.com/JuliaLang/julia/issues/22907 +[#22925]: https://github.com/JuliaLang/julia/issues/22925 +[#22926]: https://github.com/JuliaLang/julia/issues/22926 +[#22932]: https://github.com/JuliaLang/julia/issues/22932 +[#22961]: https://github.com/JuliaLang/julia/issues/22961 +[#22984]: https://github.com/JuliaLang/julia/issues/22984 +[#23002]: https://github.com/JuliaLang/julia/issues/23002 +[#23035]: https://github.com/JuliaLang/julia/issues/23035 +[#23051]: https://github.com/JuliaLang/julia/issues/23051 +[#23054]: https://github.com/JuliaLang/julia/issues/23054 +[#23117]: https://github.com/JuliaLang/julia/issues/23117 +[#23120]: https://github.com/JuliaLang/julia/issues/23120 +[#23144]: https://github.com/JuliaLang/julia/issues/23144 +[#23154]: https://github.com/JuliaLang/julia/issues/23154 +[#23157]: https://github.com/JuliaLang/julia/issues/23157 +[#23168]: https://github.com/JuliaLang/julia/issues/23168 +[#23187]: https://github.com/JuliaLang/julia/issues/23187 +[#23207]: https://github.com/JuliaLang/julia/issues/23207 +[#23233]: https://github.com/JuliaLang/julia/issues/23233 +[#23235]: https://github.com/JuliaLang/julia/issues/23235 +[#23261]: https://github.com/JuliaLang/julia/issues/23261 +[#23323]: https://github.com/JuliaLang/julia/issues/23323 +[#23332]: https://github.com/JuliaLang/julia/issues/23332 +[#23341]: https://github.com/JuliaLang/julia/issues/23341 +[#23342]: https://github.com/JuliaLang/julia/issues/23342 +[#23354]: https://github.com/JuliaLang/julia/issues/23354 +[#23366]: https://github.com/JuliaLang/julia/issues/23366 +[#23373]: https://github.com/JuliaLang/julia/issues/23373 +[#23393]: https://github.com/JuliaLang/julia/issues/23393 +[#23404]: https://github.com/JuliaLang/julia/issues/23404 +[#23427]: https://github.com/JuliaLang/julia/issues/23427 +[#23504]: https://github.com/JuliaLang/julia/issues/23504 +[#23505]: https://github.com/JuliaLang/julia/issues/23505 +[#23519]: https://github.com/JuliaLang/julia/issues/23519 +[#23528]: https://github.com/JuliaLang/julia/issues/23528 +[#23529]: https://github.com/JuliaLang/julia/issues/23529 +[#23530]: https://github.com/JuliaLang/julia/issues/23530 +[#23554]: https://github.com/JuliaLang/julia/issues/23554 +[#23570]: https://github.com/JuliaLang/julia/issues/23570 +[#23628]: https://github.com/JuliaLang/julia/issues/23628 +[#23642]: https://github.com/JuliaLang/julia/issues/23642 +[#23665]: https://github.com/JuliaLang/julia/issues/23665 +[#23690]: https://github.com/JuliaLang/julia/issues/23690 +[#23716]: https://github.com/JuliaLang/julia/issues/23716 +[#23724]: https://github.com/JuliaLang/julia/issues/23724 +[#23750]: https://github.com/JuliaLang/julia/issues/23750 +[#23757]: https://github.com/JuliaLang/julia/issues/23757 +[#23805]: https://github.com/JuliaLang/julia/issues/23805 +[#23816]: https://github.com/JuliaLang/julia/issues/23816 +[#23885]: https://github.com/JuliaLang/julia/issues/23885 +[#23902]: https://github.com/JuliaLang/julia/issues/23902 +[#23912]: https://github.com/JuliaLang/julia/issues/23912 +[#23923]: https://github.com/JuliaLang/julia/issues/23923 +[#23929]: https://github.com/JuliaLang/julia/issues/23929 +[#23960]: https://github.com/JuliaLang/julia/issues/23960 +[#23964]: https://github.com/JuliaLang/julia/issues/23964 +[#24047]: https://github.com/JuliaLang/julia/issues/24047 +[#24126]: https://github.com/JuliaLang/julia/issues/24126 +[#24153]: https://github.com/JuliaLang/julia/issues/24153 +[#24167]: https://github.com/JuliaLang/julia/issues/24167 +[#24187]: https://github.com/JuliaLang/julia/issues/24187 +[#24221]: https://github.com/JuliaLang/julia/issues/24221 +[#24240]: https://github.com/JuliaLang/julia/issues/24240 +[#24245]: https://github.com/JuliaLang/julia/issues/24245 +[#24250]: https://github.com/JuliaLang/julia/issues/24250 +[#24263]: https://github.com/JuliaLang/julia/issues/24263 +[#24278]: https://github.com/JuliaLang/julia/issues/24278 +[#24279]: https://github.com/JuliaLang/julia/issues/24279 +[#24281]: https://github.com/JuliaLang/julia/issues/24281 +[#24282]: https://github.com/JuliaLang/julia/issues/24282 +[#24320]: https://github.com/JuliaLang/julia/issues/24320 +[#24356]: https://github.com/JuliaLang/julia/issues/24356 +[#24362]: https://github.com/JuliaLang/julia/issues/24362 +[#24390]: https://github.com/JuliaLang/julia/issues/24390 +[#24396]: https://github.com/JuliaLang/julia/issues/24396 +[#24404]: https://github.com/JuliaLang/julia/issues/24404 +[#24413]: https://github.com/JuliaLang/julia/issues/24413 +[#24414]: https://github.com/JuliaLang/julia/issues/24414 +[#24438]: https://github.com/JuliaLang/julia/issues/24438 +[#24445]: https://github.com/JuliaLang/julia/issues/24445 +[#24452]: https://github.com/JuliaLang/julia/issues/24452 +[#24472]: https://github.com/JuliaLang/julia/issues/24472 +[#24490]: https://github.com/JuliaLang/julia/issues/24490 +[#24580]: https://github.com/JuliaLang/julia/issues/24580 +[#24595]: https://github.com/JuliaLang/julia/issues/24595 +[#24605]: https://github.com/JuliaLang/julia/issues/24605 +[#24647]: https://github.com/JuliaLang/julia/issues/24647 +[#24653]: https://github.com/JuliaLang/julia/issues/24653 +[#24654]: https://github.com/JuliaLang/julia/issues/24654 +[#24656]: https://github.com/JuliaLang/julia/issues/24656 +[#24673]: https://github.com/JuliaLang/julia/issues/24673 +[#24679]: https://github.com/JuliaLang/julia/issues/24679 +[#24684]: https://github.com/JuliaLang/julia/issues/24684 +[#24713]: https://github.com/JuliaLang/julia/issues/24713 +[#24715]: https://github.com/JuliaLang/julia/issues/24715 +[#24774]: https://github.com/JuliaLang/julia/issues/24774 +[#24781]: https://github.com/JuliaLang/julia/issues/24781 +[#24785]: https://github.com/JuliaLang/julia/issues/24785 +[#24786]: https://github.com/JuliaLang/julia/issues/24786 +[#24808]: https://github.com/JuliaLang/julia/issues/24808 +[#24831]: https://github.com/JuliaLang/julia/issues/24831 +[#24839]: https://github.com/JuliaLang/julia/issues/24839 +[#24844]: https://github.com/JuliaLang/julia/issues/24844 +[#24869]: https://github.com/JuliaLang/julia/issues/24869 +[#25002]: https://github.com/JuliaLang/julia/issues/25002 +[#25012]: https://github.com/JuliaLang/julia/issues/25012 +[#25021]: https://github.com/JuliaLang/julia/issues/25021 +[#25029]: https://github.com/JuliaLang/julia/issues/25029 +[#25030]: https://github.com/JuliaLang/julia/issues/25030 +[#25037]: https://github.com/JuliaLang/julia/issues/25037 +[#25046]: https://github.com/JuliaLang/julia/issues/25046 +[#25047]: https://github.com/JuliaLang/julia/issues/25047 +[#25056]: https://github.com/JuliaLang/julia/issues/25056 +[#25057]: https://github.com/JuliaLang/julia/issues/25057 +[#25058]: https://github.com/JuliaLang/julia/issues/25058 +[#25067]: https://github.com/JuliaLang/julia/issues/25067 +[#25088]: https://github.com/JuliaLang/julia/issues/25088 +[#25162]: https://github.com/JuliaLang/julia/issues/25162 +[#25165]: https://github.com/JuliaLang/julia/issues/25165 +[#25168]: https://github.com/JuliaLang/julia/issues/25168 +[#25184]: https://github.com/JuliaLang/julia/issues/25184 +[#25197]: https://github.com/JuliaLang/julia/issues/25197 +[#25210]: https://github.com/JuliaLang/julia/issues/25210 +[#25231]: https://github.com/JuliaLang/julia/issues/25231 +[#25249]: https://github.com/JuliaLang/julia/issues/25249 +[#25277]: https://github.com/JuliaLang/julia/issues/25277 +[#25278]: https://github.com/JuliaLang/julia/issues/25278 +[#25311]: https://github.com/JuliaLang/julia/issues/25311 +[#25321]: https://github.com/JuliaLang/julia/issues/25321 +[#25368]: https://github.com/JuliaLang/julia/issues/25368 +[#25391]: https://github.com/JuliaLang/julia/issues/25391 +[#25424]: https://github.com/JuliaLang/julia/issues/25424 +[#25429]: https://github.com/JuliaLang/julia/issues/25429 +[#25457]: https://github.com/JuliaLang/julia/issues/25457 +[#25459]: https://github.com/JuliaLang/julia/issues/25459 +[#25472]: https://github.com/JuliaLang/julia/issues/25472 +[#25496]: https://github.com/JuliaLang/julia/issues/25496 +[#25501]: https://github.com/JuliaLang/julia/issues/25501 +[#25522]: https://github.com/JuliaLang/julia/issues/25522 +[#25532]: https://github.com/JuliaLang/julia/issues/25532 +[#25545]: https://github.com/JuliaLang/julia/issues/25545 +[#25564]: https://github.com/JuliaLang/julia/issues/25564 +[#25567]: https://github.com/JuliaLang/julia/issues/25567 +[#25571]: https://github.com/JuliaLang/julia/issues/25571 +[#25616]: https://github.com/JuliaLang/julia/issues/25616 +[#25622]: https://github.com/JuliaLang/julia/issues/25622 +[#25631]: https://github.com/JuliaLang/julia/issues/25631 +[#25633]: https://github.com/JuliaLang/julia/issues/25633 +[#25634]: https://github.com/JuliaLang/julia/issues/25634 +[#25654]: https://github.com/JuliaLang/julia/issues/25654 +[#25655]: https://github.com/JuliaLang/julia/issues/25655 +[#25662]: https://github.com/JuliaLang/julia/issues/25662 +[#25667]: https://github.com/JuliaLang/julia/issues/25667 +[#25668]: https://github.com/JuliaLang/julia/issues/25668 +[#25697]: https://github.com/JuliaLang/julia/issues/25697 +[#25701]: https://github.com/JuliaLang/julia/issues/25701 +[#25725]: https://github.com/JuliaLang/julia/issues/25725 +[#25745]: https://github.com/JuliaLang/julia/issues/25745 +[#25763]: https://github.com/JuliaLang/julia/issues/25763 +[#25786]: https://github.com/JuliaLang/julia/issues/25786 +[#25812]: https://github.com/JuliaLang/julia/issues/25812 +[#25815]: https://github.com/JuliaLang/julia/issues/25815 +[#25830]: https://github.com/JuliaLang/julia/issues/25830 +[#25845]: https://github.com/JuliaLang/julia/issues/25845 +[#25854]: https://github.com/JuliaLang/julia/issues/25854 +[#25858]: https://github.com/JuliaLang/julia/issues/25858 +[#25872]: https://github.com/JuliaLang/julia/issues/25872 +[#25896]: https://github.com/JuliaLang/julia/issues/25896 +[#25944]: https://github.com/JuliaLang/julia/issues/25944 +[#25947]: https://github.com/JuliaLang/julia/issues/25947 +[#25979]: https://github.com/JuliaLang/julia/issues/25979 +[#25980]: https://github.com/JuliaLang/julia/issues/25980 +[#25990]: https://github.com/JuliaLang/julia/issues/25990 +[#25998]: https://github.com/JuliaLang/julia/issues/25998 +[#26009]: https://github.com/JuliaLang/julia/issues/26009 +[#26071]: https://github.com/JuliaLang/julia/issues/26071 +[#26080]: https://github.com/JuliaLang/julia/issues/26080 +[#26093]: https://github.com/JuliaLang/julia/issues/26093 +[#26149]: https://github.com/JuliaLang/julia/issues/26149 +[#26154]: https://github.com/JuliaLang/julia/issues/26154 +[#26156]: https://github.com/JuliaLang/julia/issues/26156 +[#26161]: https://github.com/JuliaLang/julia/issues/26161 +[#26206]: https://github.com/JuliaLang/julia/issues/26206 +[#26212]: https://github.com/JuliaLang/julia/issues/26212 +[#26262]: https://github.com/JuliaLang/julia/issues/26262 +[#26283]: https://github.com/JuliaLang/julia/issues/26283 +[#26284]: https://github.com/JuliaLang/julia/issues/26284 +[#26286]: https://github.com/JuliaLang/julia/issues/26286 +[#26347]: https://github.com/JuliaLang/julia/issues/26347 +[#26436]: https://github.com/JuliaLang/julia/issues/26436 +[#26442]: https://github.com/JuliaLang/julia/issues/26442 +[#26486]: https://github.com/JuliaLang/julia/issues/26486 +[#26559]: https://github.com/JuliaLang/julia/issues/26559 +[#26576]: https://github.com/JuliaLang/julia/issues/26576 +[#26600]: https://github.com/JuliaLang/julia/issues/26600 +[#26660]: https://github.com/JuliaLang/julia/issues/26660 +[#26670]: https://github.com/JuliaLang/julia/issues/26670 +[#26733]: https://github.com/JuliaLang/julia/issues/26733 +[#26775]: https://github.com/JuliaLang/julia/issues/26775 +[#26858]: https://github.com/JuliaLang/julia/issues/26858 +[#26862]: https://github.com/JuliaLang/julia/issues/26862 +[#26932]: https://github.com/JuliaLang/julia/issues/26932 +[#26935]: https://github.com/JuliaLang/julia/issues/26935 +[#26980]: https://github.com/JuliaLang/julia/issues/26980 +[#26997]: https://github.com/JuliaLang/julia/issues/26997 +[#27067]: https://github.com/JuliaLang/julia/issues/27067 +[#27071]: https://github.com/JuliaLang/julia/issues/27071 +[#27075]: https://github.com/JuliaLang/julia/issues/27075 +[#27100]: https://github.com/JuliaLang/julia/issues/27100 +[#27121]: https://github.com/JuliaLang/julia/issues/27121 +[#27159]: https://github.com/JuliaLang/julia/issues/27159 +[#27164]: https://github.com/JuliaLang/julia/issues/27164 +[#27189]: https://github.com/JuliaLang/julia/issues/27189 +[#27212]: https://github.com/JuliaLang/julia/issues/27212 +[#27248]: https://github.com/JuliaLang/julia/issues/27248 +[#27309]: https://github.com/JuliaLang/julia/issues/27309 +[#27401]: https://github.com/JuliaLang/julia/issues/27401 +[#27447]: https://github.com/JuliaLang/julia/issues/27447 +[#27459]: https://github.com/JuliaLang/julia/issues/27459 +[#27470]: https://github.com/JuliaLang/julia/issues/27470 +[#27473]: https://github.com/JuliaLang/julia/issues/27473 +[#27554]: https://github.com/JuliaLang/julia/issues/27554 +[#27560]: https://github.com/JuliaLang/julia/issues/27560 +[#27616]: https://github.com/JuliaLang/julia/issues/27616 +[#27635]: https://github.com/JuliaLang/julia/issues/27635 +[#27641]: https://github.com/JuliaLang/julia/issues/27641 +[#27711]: https://github.com/JuliaLang/julia/issues/27711 +[#27726]: https://github.com/JuliaLang/julia/issues/27726 +[#27746]: https://github.com/JuliaLang/julia/issues/27746 +[#27856]: https://github.com/JuliaLang/julia/issues/27856 +[#27859]: https://github.com/JuliaLang/julia/issues/27859 +[#27908]: https://github.com/JuliaLang/julia/issues/27908 +[#27944]: https://github.com/JuliaLang/julia/issues/27944 +[#28045]: https://github.com/JuliaLang/julia/issues/28045 +[#28065]: https://github.com/JuliaLang/julia/issues/28065 +[#28155]: https://github.com/JuliaLang/julia/issues/28155 +[#28266]: https://github.com/JuliaLang/julia/issues/28266 +[#28302]: https://github.com/JuliaLang/julia/issues/28302 diff --git a/README.md b/README.md index de2b75bf718bf..792a480d25913 100644 --- a/README.md +++ b/README.md @@ -84,16 +84,16 @@ Then, acquire the source code by cloning the git repository: Be sure to also configure your system to use the appropriate proxy settings, e.g. by setting the `https_proxy` and `http_proxy` variables.) -By default you will be building the latest unstable version of Julia. However, most users should use the most recent stable version of Julia, which is currently the `1.0` series of releases. You can get this version by changing to the Julia directory and running +By default you will be building the latest unstable version of Julia. However, most users should use the most recent stable version of Julia, which is currently the `0.6` series of releases. You can get this version by changing to the Julia directory and running - git checkout v1.0.0 + git checkout v0.6.4 Now run `make` to build the `julia` executable. To perform a parallel build, use `make -j N` and supply the maximum number of concurrent processes. (See [Platform Specific Build Notes](https://github.com/JuliaLang/julia#platform-specific-build-notes) for details.) When compiled the first time, it will automatically download and build its [external dependencies](#required-build-tools-and-external-libraries). This takes a while, but only has to be done once. If the defaults in the build do not work for you, and you need to set specific make parameters, you can save them in `Make.user`, and place the file in the root of your Julia source. The build will automatically check for the existence of `Make.user` and use it if it exists. Building Julia requires 5GiB of disk space and approximately 2GiB of virtual memory. -You can create out-of-tree builds of Julia by specifying `make O= configure` on the command line. This will create a directory mirror, with all of the necessary Makefiles to build Julia, in the specified directory. These builds will share the source files in Julia and `deps/srccache`. Each out-of-tree build directory can have its own `Make.user` file to override the global `Make.user` file in the top-level folder. +For builds of julia starting with 0.5.0-dev, you can create out-of-tree builds of Julia by specifying `make O= configure` on the command line. This will create a directory mirror, with all of the necessary Makefiles to build Julia, in the specified directory. These builds will share the source files in Julia and `deps/srccache`. Each out-of-tree build directory can have its own `Make.user` file to override the global `Make.user` file in the top-level folder. If you need to build Julia on a machine without internet access, use `make -C deps getall` to download all the necessary files. Then, copy the `julia` directory over to the target environment and build with `make`. @@ -300,7 +300,7 @@ sudo apt-get install build-essential libatomic1 python gfortran perl wget m4 cma Julia uses the following external libraries, which are automatically downloaded (or in a few cases, included in the Julia source repository) and then compiled from source the first time you run `make`: -- **[LLVM]** (6.0 + [patches](https://github.com/JuliaLang/julia/tree/master/deps/patches)) — compiler infrastructure (see [note below](#llvm)). +- **[LLVM]** (3.9 + patches) — compiler infrastructure (see [note below](#llvm)). - **[FemtoLisp]** — packaged with Julia source, and used to implement the compiler front-end. - **[libuv]** (custom fork) — portable, high-performance event-based I/O library. - **[OpenLibm]** — portable libm library containing elementary math functions. @@ -364,11 +364,9 @@ Please be aware that this procedure is not officially supported, as it introduce ### LLVM -The most complicated dependency is LLVM, for which we require additional patches from upstream (LLVM is not backward compatible). - -For packaging Julia with LLVM, we recommend either: +The most complicated dependency is LLVM, for which we require version 3.9 with some additional patches from upstream (LLVM is not backward compatible). For packaging Julia, we recommend either: - bundling a Julia-only LLVM library inside the Julia package, or - - adding the patches to the LLVM package of the distribution. + - adding the patches to the LLVM 3.9 package of the distribution. * A complete list of patches is available in `deps/llvm.mk`, and the patches themselves are in `deps/patches/`. * The only Julia-specific patch is the lib renaming (`llvm-symver-jlprefix.patch`), which should _not_ be applied to a system LLVM. * The remaining patches are all upstream bug fixes, and have been contributed into upstream LLVM. diff --git a/README.windows.md b/README.windows.md index a13c1ba5a86b0..76056b69959ed 100644 --- a/README.windows.md +++ b/README.windows.md @@ -23,7 +23,7 @@ Instructions for adding fonts to the terminal are available at Additionally, rather than sticking with the default command prompt, you may want to use a different terminal emulator program, such as -[Conemu](https://conemu.github.io/) or [Mintty]( +[Conemu](https://code.google.com/p/conemu-maximus5/) or [Mintty]( https://github.com/mintty/mintty) (note that running Julia on Mintty needs a copy of `stty.exe` in your `%PATH%` to work properly). Alternatively, you may prefer the features of a more full-function IDE, such as [Juno](http://junolab.org), diff --git a/VERSION b/VERSION index 87f6e89c2ee8c..5ceb1a2ccf001 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.1.0-DEV +1.0.0-DEV diff --git a/base/compiler/abstractinterpretation.jl b/base/compiler/abstractinterpretation.jl index 9ca7db1f669a6..82f4f0995108b 100644 --- a/base/compiler/abstractinterpretation.jl +++ b/base/compiler/abstractinterpretation.jl @@ -305,26 +305,10 @@ function abstract_call_method(method::Method, @nospecialize(sig), sparams::Simpl # if sig changed, may need to recompute the sparams environment if isa(method.sig, UnionAll) && isempty(sparams) recomputed = ccall(:jl_type_intersection_with_env, Any, (Any, Any), sig, method.sig)::SimpleVector - #@assert recomputed[1] !== Bottom - # We must not use `sig` here, since that may re-introduce structural complexity that - # our limiting heuristic sought to eliminate. The alternative would be to not increment depth over covariant contexts, - # but we prefer to permit inference of tuple-destructuring, so we don't do that right now - # For example, with a signature such as `Tuple{T, Ref{T}} where {T <: S}` - # we might want to limit this to `Tuple{S, Ref}`, while type-intersection can instead give us back the original type - # (which moves `S` back up to a lower comparison depth) - # Optionally, we could try to drive this to a fixed point, but I think this is getting too complex, - # and this would only cause more questions and more problems - # (the following is only an example, most of the statements are probable in the wrong order): - # newsig = sig - # seen = IdSet() - # while !(newsig in seen) - # push!(seen, newsig) - # lsig = length((unwrap_unionall(sig)::DataType).parameters) - # newsig = limit_type_size(newsig, sig, sv.linfo.specTypes, sv.params.TUPLE_COMPLEXITY_LIMIT_DEPTH, lsig) - # recomputed = ccall(:jl_type_intersection_with_env, Any, (Any, Any), newsig, method.sig)::SimpleVector - # newsig = recomputed[2] - # end - # sig = ? + sig = recomputed[1] + if !isa(unwrap_unionall(sig), DataType) # probably Union{} + return Any, false, nothing + end sparams = recomputed[2]::SimpleVector end diff --git a/base/compiler/typelimits.jl b/base/compiler/typelimits.jl index 83ca2a386b119..2ed05d0978495 100644 --- a/base/compiler/typelimits.jl +++ b/base/compiler/typelimits.jl @@ -29,20 +29,19 @@ end # try to find `type` somewhere in `comparison` type # at a minimum nesting depth of `mindepth` function is_derived_type(@nospecialize(t), @nospecialize(c), mindepth::Int) + if mindepth > 0 + mindepth -= 1 + end if t === c - return mindepth <= 1 + return mindepth == 0 end if isa(c, Union) # see if it is one of the elements of the union - return is_derived_type(t, c.a, mindepth) || is_derived_type(t, c.b, mindepth) + return is_derived_type(t, c.a, mindepth + 1) || is_derived_type(t, c.b, mindepth + 1) elseif isa(c, UnionAll) # see if it is derived from the body - # also handle the var here, since this construct bounds the mindepth to the smallest possible value - return is_derived_type(t, c.var.ub, mindepth) || is_derived_type(t, c.body, mindepth) + return is_derived_type(t, c.var.ub, mindepth) || is_derived_type(t, c.body, mindepth + 1) elseif isa(c, DataType) - if mindepth > 0 - mindepth -= 1 - end if isa(t, DataType) # see if it is one of the supertypes of a parameter super = supertype(c) @@ -93,32 +92,45 @@ function _limit_type_size(@nospecialize(t), @nospecialize(c), sources::SimpleVec elseif is_derived_type_from_any(unwrap_unionall(t), sources, depth) return t # t isn't something new end - # peel off (and ignore) wrappers - they contribute no useful information, so we don't need to consider their size - # first attempt to turn `c` into a type that contributes meaningful information - # by peeling off meaningless non-matching wrappers of comparison one at a time - # then unwrap `t` - if isa(c, TypeVar) - if isa(t, TypeVar) && t.ub === c.ub && (t.lb === Union{} || t.lb === c.lb) - return t # it's ok to change the name, or widen `lb` to Union{}, so we can handle this immediately here + if isa(t, TypeVar) + if isa(c, TypeVar) + if t.ub === c.ub && t.lb === c.lb + return t + end end - return _limit_type_size(t, c.ub, sources, depth, allowed_tuplelen) - end - if isa(c, UnionAll) - return _limit_type_size(t, c.body, sources, depth, allowed_tuplelen) - end - if isa(t, UnionAll) - tbody = _limit_type_size(t.body, c, sources, depth, allowed_tuplelen) - tbody === t.body && return t - return UnionAll(t.var, tbody) - elseif isa(t, TypeVar) - # don't have a matching TypeVar in comparison, so we keep just the upper bound - return _limit_type_size(t.ub, c, sources, depth, allowed_tuplelen) elseif isa(t, Union) if isa(c, Union) a = _limit_type_size(t.a, c.a, sources, depth, allowed_tuplelen) b = _limit_type_size(t.b, c.b, sources, depth, allowed_tuplelen) return Union{a, b} end + elseif isa(t, UnionAll) + if isa(c, UnionAll) + tv = t.var + cv = c.var + if tv.ub === cv.ub + if tv.lb === cv.lb + return UnionAll(tv, _limit_type_size(t.body, c.body, sources, depth + 1, allowed_tuplelen)) + end + ub = tv.ub + else + ub = _limit_type_size(tv.ub, cv.ub, sources, depth + 1, 0) + end + if tv.lb === cv.lb + lb = tv.lb + else + # note: lower bounds need to be widened by making them lower + lb = Bottom + end + v2 = TypeVar(tv.name, lb, ub) + return UnionAll(v2, _limit_type_size(t{v2}, c{v2}, sources, depth, allowed_tuplelen)) + end + tbody = _limit_type_size(t.body, c, sources, depth, allowed_tuplelen) + tbody === t.body && return t + return UnionAll(t.var, tbody) + elseif isa(c, UnionAll) + # peel off non-matching wrapper of comparison + return _limit_type_size(t, c.body, sources, depth, allowed_tuplelen) elseif isa(t, DataType) if isa(c, DataType) tP = t.parameters diff --git a/base/essentials.jl b/base/essentials.jl index 3bf9ecfad81d3..89818c5c287c2 100644 --- a/base/essentials.jl +++ b/base/essentials.jl @@ -690,6 +690,43 @@ function invokelatest(@nospecialize(f), @nospecialize args...; kwargs...) Core._apply_latest(inner) end +# iteration protocol + +""" + next(iter, state) -> item, state + +For a given iterable object and iteration state, return the current item and the next iteration state. + +# Examples +```jldoctest +julia> next(1:5, 3) +(3, 4) + +julia> next(1:5, 5) +(5, 6) +``` +""" +function next end + +""" + start(iter) -> state + +Get initial iteration state for an iterable object. + +# Examples +```jldoctest +julia> start(1:5) +1 + +julia> start([1;2;3]) +1 + +julia> start([4;2;3]) +1 +``` +""" +function start end + """ isempty(collection) -> Bool diff --git a/base/exports.jl b/base/exports.jl index f9e6444d6e347..d979ec2080be2 100644 --- a/base/exports.jl +++ b/base/exports.jl @@ -124,6 +124,7 @@ export InvalidStateException, KeyError, MissingException, + ParseError, SystemError, StringIndexError, @@ -410,6 +411,8 @@ export rot180, rotl90, rotr90, + shuffle, + shuffle!, size, selectdim, sort!, @@ -604,6 +607,9 @@ export summary, # logging + info, + logging, + warn, @debug, @info, @warn, @@ -618,6 +624,9 @@ export set_zero_subnormals, # iteration + done, + next, + start, iterate, enumerate, # re-exported from Iterators diff --git a/base/io.jl b/base/io.jl index 06bb38645ada4..41f4ec8258ca4 100644 --- a/base/io.jl +++ b/base/io.jl @@ -235,14 +235,9 @@ readuntil(io::AbstractPipe, arg::AbstractString; kw...) = readuntil(pipe_reader( readuntil(io::AbstractPipe, arg::AbstractVector; kw...) = readuntil(pipe_reader(io), arg; kw...) readuntil_vector!(io::AbstractPipe, target::AbstractVector, keep::Bool, out) = readuntil_vector!(pipe_reader(io), target, keep, out) -for f in ( - # peek/mark interface - :peek, :mark, :unmark, :reset, :ismarked, - # Simple reader functions - :readavailable, :isreadable) - @eval $(f)(io::AbstractPipe) = $(f)(pipe_reader(io)) -end +readavailable(io::AbstractPipe) = readavailable(pipe_reader(io)) +isreadable(io::AbstractPipe) = isreadable(pipe_reader(io)) iswritable(io::AbstractPipe) = iswritable(pipe_writer(io)) isopen(io::AbstractPipe) = isopen(pipe_writer(io)) || isopen(pipe_reader(io)) close(io::AbstractPipe) = (close(pipe_writer(io)); close(pipe_reader(io))) diff --git a/base/iterators.jl b/base/iterators.jl index 396b1744482f7..efd3300f8819e 100644 --- a/base/iterators.jl +++ b/base/iterators.jl @@ -801,7 +801,7 @@ iterate(::ProductIterator{Tuple{}}, state) = nothing @inline isdone(P::ProductIterator) = any(isdone, P.iterators) @inline function _pisdone(iters, states) iter1 = first(iters) - done1 = isdone(iter1, first(states)[2]) # check step + done1 = isdone(iter1, first(states)) # check step done1 === true || return done1 # false or missing done1 = isdone(iter1) # check restart done1 === true || return done1 # false or missing diff --git a/base/stream.jl b/base/stream.jl index 60834390a99cf..df79e77e200c5 100644 --- a/base/stream.jl +++ b/base/stream.jl @@ -911,16 +911,17 @@ for (x, writable, unix_fd, c_symbol) in (:stderr, true, 2, :jl_uv_stderr)) f = Symbol("redirect_", lowercase(string(x))) _f = Symbol("_", f) + Ux = Symbol(uppercase(string(x))) @eval begin function ($_f)(stream) - global $x + global $x, $Ux posix_fd = _fd(stream) @static if Sys.iswindows() ccall(:SetStdHandle, stdcall, Int32, (Int32, OS_HANDLE), $(-10 - unix_fd), Libc._get_osfhandle(posix_fd)) end dup(posix_fd, RawFD($unix_fd)) - $x = stream + $Ux = $x = stream nothing end function ($f)(handle::Union{LibuvStream, IOStream}) diff --git a/base/version.jl b/base/version.jl index 94baefab01542..6ff4927a54b07 100644 --- a/base/version.jl +++ b/base/version.jl @@ -278,8 +278,7 @@ function banner(io::IO = stdout) commit_string = "$(branch)/$(commit) (fork: $(distance) commits, $(days) $(unit))" end end - - commit_date = isempty(Base.GIT_VERSION_INFO.date_string) ? "" : " ($(split(Base.GIT_VERSION_INFO.date_string)[1]))" + commit_date = !isempty(GIT_VERSION_INFO.date_string) ? " ($(GIT_VERSION_INFO.date_string))" : "" if get(io, :color, false) c = text_colors @@ -291,25 +290,25 @@ function banner(io::IO = stdout) d4 = c[:bold] * c[:magenta] # fourth dot print(io,""" $(d3)_$(tx) - $(d1)_$(tx) $(jl)_$(tx) $(d2)_$(d3)(_)$(d4)_$(tx) | Documentation: https://docs.julialang.org - $(d1)(_)$(jl) | $(d2)(_)$(tx) $(d4)(_)$(tx) | + $(d1)_$(tx) $(jl)_$(tx) $(d2)_$(d3)(_)$(d4)_$(tx) | A fresh approach to technical computing + $(d1)(_)$(jl) | $(d2)(_)$(tx) $(d4)(_)$(tx) | Documentation: https://docs.julialang.org $(jl)_ _ _| |_ __ _$(tx) | Type \"?\" for help, \"]?\" for Pkg help. $(jl)| | | | | | |/ _` |$(tx) | $(jl)| | |_| | | | (_| |$(tx) | Version $(VERSION)$(commit_date) $(jl)_/ |\\__'_|_|_|\\__'_|$(tx) | $(commit_string) - $(jl)|__/$(tx) | + $(jl)|__/$(tx) | $(Sys.MACHINE) """) else print(io,""" _ - _ _ _(_)_ | Documentation: https://docs.julialang.org - (_) | (_) (_) | + _ _ _(_)_ | A fresh approach to technical computing + (_) | (_) (_) | Documentation: https://docs.julialang.org _ _ _| |_ __ _ | Type \"?\" for help, \"]?\" for Pkg help. | | | | | | |/ _` | | | | |_| | | | (_| | | Version $(VERSION)$(commit_date) _/ |\\__'_|_|_|\\__'_| | $(commit_string) - |__/ | + |__/ | $(Sys.MACHINE) """) end diff --git a/contrib/precompile_explicit.jl b/contrib/precompile_explicit.jl index a95b3cb8ddc34..38e581415cdc6 100644 --- a/contrib/precompile_explicit.jl +++ b/contrib/precompile_explicit.jl @@ -474,6 +474,7 @@ precompile(Tuple{typeof(Base.similar), Type{Array{Method, N} where N}, Tuple{Bas precompile(Tuple{typeof(Base.sizeof), String}) precompile(Tuple{typeof(Base.skip_deleted_floor!), Base.Dict{Symbol, Any}}) precompile(Tuple{typeof(Base.sort!), Array{Int64, 1}, Base.Sort.QuickSortAlg, Base.Order.Perm{Base.Order.ForwardOrdering, Array{Tuple{Float64, Int64}, 1}}}) +precompile(Tuple{typeof(Base.start), Nothing}) precompile(Tuple{typeof(Base.startswith), Base.SubString{String}, String}) precompile(Tuple{typeof(Base.startswith), String, Char}) precompile(Tuple{typeof(Base.stream_wait), Base.Timer, Base.Condition}) diff --git a/doc/Manifest.toml b/doc/Manifest.toml index d2669e5686fb4..badaf09863125 100644 --- a/doc/Manifest.toml +++ b/doc/Manifest.toml @@ -3,20 +3,17 @@ uuid = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f" [[Compat]] deps = ["Base64", "Dates", "DelimitedFiles", "Distributed", "InteractiveUtils", "LibGit2", "Libdl", "LinearAlgebra", "Markdown", "Mmap", "Pkg", "Printf", "REPL", "Random", "Serialization", "SharedArrays", "Sockets", "SparseArrays", "Statistics", "Test", "UUIDs", "Unicode"] -git-tree-sha1 = "277d3807440d9793421354b6680911fc95d91a84" +git-tree-sha1 = "c478aec93ea90bb99c307a92df17a76131bf275f" uuid = "34da2185-b29b-5c13-b0c7-acf172513d20" -version = "1.0.1" +version = "1.0.0" [[Dates]] -deps = ["Printf"] uuid = "ade2ca70-3891-5945-98fb-dc099432e06a" [[DelimitedFiles]] -deps = ["Mmap"] uuid = "8bb1440f-4735-579b-a4ab-409b98df4dab" [[Distributed]] -deps = ["LinearAlgebra", "Random", "Serialization", "Sockets"] uuid = "8ba89e20-285c-5b6f-9357-94700520ee1b" [[DocStringExtensions]] @@ -27,12 +24,11 @@ version = "0.4.5" [[Documenter]] deps = ["Compat", "DocStringExtensions", "Logging", "REPL"] -git-tree-sha1 = "ef29b036c7eb40bca1ac5471639ec01e98717d27" +git-tree-sha1 = "db9efaced47fd05e8fa5f6ec3f6925dc2f1425aa" uuid = "e30172f5-a6a5-5a46-863b-614d45cd2de4" -version = "0.19.3" +version = "0.19.1" [[InteractiveUtils]] -deps = ["LinearAlgebra", "Markdown"] uuid = "b77e0a4c-d291-57a0-90e8-8db25a27a240" [[LibGit2]] @@ -42,62 +38,48 @@ uuid = "76f85450-5226-5b5a-8eaa-529ad045b433" uuid = "8f399da3-3557-5675-b5ff-fb832c97cbdb" [[LinearAlgebra]] -deps = ["Libdl"] uuid = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" [[Logging]] uuid = "56ddb016-857b-54e1-b83d-db4d58db5568" [[Markdown]] -deps = ["Base64"] uuid = "d6f4376e-aef5-505a-96c1-9c027394607a" [[Mmap]] uuid = "a63ad114-7e13-5084-954f-fe012c677804" [[Pkg]] -deps = ["Dates", "LibGit2", "Markdown", "Printf", "REPL", "Random", "SHA", "UUIDs"] uuid = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f" [[Printf]] -deps = ["Unicode"] uuid = "de0858da-6303-5e67-8744-51eddeeeb8d7" [[REPL]] -deps = ["InteractiveUtils", "Markdown", "Sockets"] uuid = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb" [[Random]] -deps = ["Serialization"] uuid = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" -[[SHA]] -uuid = "ea8e919c-243c-51af-8825-aaa63cd721ce" - [[Serialization]] uuid = "9e88b42a-f829-5b0c-bbe9-9e923198166b" [[SharedArrays]] -deps = ["Distributed", "Mmap", "Random", "Serialization"] uuid = "1a1011a3-84de-559e-8e89-a11a2f7dc383" [[Sockets]] uuid = "6462fe0b-24de-5631-8697-dd941f90decc" [[SparseArrays]] -deps = ["LinearAlgebra", "Random"] uuid = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" [[Statistics]] -deps = ["LinearAlgebra", "SparseArrays"] uuid = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" [[Test]] -deps = ["Distributed", "InteractiveUtils", "Logging", "Random"] uuid = "8dfed614-e22c-5e08-85e1-65c5234f0b40" [[UUIDs]] -deps = ["Random"] uuid = "cf7118a7-6976-5b1a-9a39-7adc72f591a4" [[Unicode]] diff --git a/doc/make.jl b/doc/make.jl index 466d4705814af..b2b3107949103 100644 --- a/doc/make.jl +++ b/doc/make.jl @@ -40,16 +40,16 @@ cd(joinpath(@__DIR__, "src")) do end end -# # Generate a suitable markdown file from NEWS.md and put it in src -# str = read(joinpath(@__DIR__, "..", "NEWS.md"), String) -# splitted = split(str, "") -# @assert length(splitted) == 2 -# replaced_links = replace(splitted[1], r"\[\#([0-9]*?)\]" => s"[#\g<1>](https://github.com/JuliaLang/julia/issues/\g<1>)") -# write(joinpath(@__DIR__, "src", "NEWS.md"), replaced_links) +# Generate a suitable markdown file from NEWS.md and put it in src +str = read(joinpath(@__DIR__, "..", "NEWS.md"), String) +splitted = split(str, "") +@assert length(splitted) == 2 +replaced_links = replace(splitted[1], r"\[\#([0-9]*?)\]" => s"[#\g<1>](https://github.com/JuliaLang/julia/issues/\g<1>)") +write(joinpath(@__DIR__, "src", "NEWS.md"), replaced_links) const PAGES = [ "Home" => "index.md", - # hide("NEWS.md"), + hide("NEWS.md"), "Manual" => [ "manual/getting-started.md", "manual/variables.md", diff --git a/doc/src/index.md b/doc/src/index.md index 855e45db671f1..c7420bce1656a 100644 --- a/doc/src/index.md +++ b/doc/src/index.md @@ -1,12 +1,8 @@ -# Julia 1.0 Documentation +# Julia 0.7 Documentation -Welcome to the documentation for Julia 1.0. +Welcome to the documentation for Julia 0.7. -Please read the [release blog post](https://julialang.org/blog/2018/08/one-point-zero) for a general overview of the language and -many of the changes since Julia v0.6. Note that version 0.7 was released alongside -1.0 to provide an upgrade path for packages and code that predates the 1.0 release. -The only difference between 0.7 and 1.0 is the removal of deprecation warnings. -For a complete list of all the changes since 0.6, see the [release notes for version 0.7](https://docs.julialang.org/en/v0.7.0/NEWS/) +Please read the [release notes](NEWS.md) to see what has changed since the last release. ### [Introduction](@id man-introduction) diff --git a/doc/src/manual/profile.md b/doc/src/manual/profile.md index e3403cd449131..00d91cf5f0d7c 100644 --- a/doc/src/manual/profile.md +++ b/doc/src/manual/profile.md @@ -312,34 +312,3 @@ memory allocation). The recommended procedure is to force compilation by executi you want to analyze, then call [`Profile.clear_malloc_data()`](@ref) to reset all allocation counters. Finally, execute the desired commands and quit Julia to trigger the generation of the `.mem` files. - -# External Profiling - -Currently Julia supports `Intel VTune`, `OProfile` and `perf` as external profiling tools. - -Depending on the tool you choose, compile with `USE_INTEL_JITEVENTS`, `USE_OPROFILE_JITEVENTS` and -`USE_PERF_JITEVENTS` set to 1 in `Make.user`. Multiple flags are supported. - -Before running Julia set the environment variable `ENABLE_JITPROFILING` to 1. - -Now you have a multitude of ways to employ those tools! -For example with `OProfile` you can try a simple recording : - -``` ->ENABLE_JITPROFILING=1 sudo operf -Vdebug ./julia test/fastmath.jl ->opreport -l `which ./julia` -``` - -Or similary with with `perf` : - -``` -$ ENABLE_JITPROFILING=1 perf record -o /tmp/perf.data --call-graph dwarf ./julia /test/fastmath.jl -$ perf report --call-graph -G -``` - -There are many more interesting things that you can measure about your program, to get a comprehensive list -please read the [Linux perf examples page](http://www.brendangregg.com/perf.html). - -Remember that perf saves for each execution a `perf.data` file that, even for small programs, can get -quite large. Also the perf LLVM module saves temporarly debug objects in `~/.debug/jit`, remember -to clean that folder frequently. diff --git a/doc/src/manual/types.md b/doc/src/manual/types.md index 44eb1c76ea39b..7cd8c58b21542 100644 --- a/doc/src/manual/types.md +++ b/doc/src/manual/types.md @@ -1383,7 +1383,7 @@ for cases where you don't need a more elaborate hierarchy. julia> struct Val{x} end -julia> Val(x) = Val{x}() +julia> Base.@pure Val(x) = Val{x}() Val ``` diff --git a/src/julia-parser.scm b/src/julia-parser.scm index 9d832894f9bb1..13baa60e2cc69 100644 --- a/src/julia-parser.scm +++ b/src/julia-parser.scm @@ -19,12 +19,12 @@ (define prec-lazy-and '(&&)) (define prec-comparison (append! '(|<:| |>:| in isa) - (add-dots '(> < >= ≥ <= ≤ == === ≡ != ≠ !== ≢ ∈ ∉ ∋ ∌ ⊆ ⊈ ⊂ ⊄ ⊊ ∝ ∊ ∍ ∥ ∦ ∷ ∺ ∻ ∽ ∾ ≁ ≃ ≂ ≄ ≅ ≆ ≇ ≈ ≉ ≊ ≋ ≌ ≍ ≎ ≐ ≑ ≒ ≓ ≖ ≗ ≘ ≙ ≚ ≛ ≜ ≝ ≞ ≟ ≣ ≦ ≧ ≨ ≩ ≪ ≫ ≬ ≭ ≮ ≯ ≰ ≱ ≲ ≳ ≴ ≵ ≶ ≷ ≸ ≹ ≺ ≻ ≼ ≽ ≾ ≿ ⊀ ⊁ ⊃ ⊅ ⊇ ⊉ ⊋ ⊏ ⊐ ⊑ ⊒ ⊜ ⊩ ⊬ ⊮ ⊰ ⊱ ⊲ ⊳ ⊴ ⊵ ⊶ ⊷ ⋍ ⋐ ⋑ ⋕ ⋖ ⋗ ⋘ ⋙ ⋚ ⋛ ⋜ ⋝ ⋞ ⋟ ⋠ ⋡ ⋢ ⋣ ⋤ ⋥ ⋦ ⋧ ⋨ ⋩ ⋪ ⋫ ⋬ ⋭ ⋲ ⋳ ⋴ ⋵ ⋶ ⋷ ⋸ ⋹ ⋺ ⋻ ⋼ ⋽ ⋾ ⋿ ⟈ ⟉ ⟒ ⦷ ⧀ ⧁ ⧡ ⧣ ⧤ ⧥ ⩦ ⩧ ⩪ ⩫ ⩬ ⩭ ⩮ ⩯ ⩰ ⩱ ⩲ ⩳ ⩵ ⩶ ⩷ ⩸ ⩹ ⩺ ⩻ ⩼ ⩽ ⩾ ⩿ ⪀ ⪁ ⪂ ⪃ ⪄ ⪅ ⪆ ⪇ ⪈ ⪉ ⪊ ⪋ ⪌ ⪍ ⪎ ⪏ ⪐ ⪑ ⪒ ⪓ ⪔ ⪕ ⪖ ⪗ ⪘ ⪙ ⪚ ⪛ ⪜ ⪝ ⪞ ⪟ ⪠ ⪡ ⪢ ⪣ ⪤ ⪥ ⪦ ⪧ ⪨ ⪩ ⪪ ⪫ ⪬ ⪭ ⪮ ⪯ ⪰ ⪱ ⪲ ⪳ ⪴ ⪵ ⪶ ⪷ ⪸ ⪹ ⪺ ⪻ ⪼ ⪽ ⪾ ⪿ ⫀ ⫁ ⫂ ⫃ ⫄ ⫅ ⫆ ⫇ ⫈ ⫉ ⫊ ⫋ ⫌ ⫍ ⫎ ⫏ ⫐ ⫑ ⫒ ⫓ ⫔ ⫕ ⫖ ⫗ ⫘ ⫙ ⫷ ⫸ ⫹ ⫺ ⊢ ⊣ ⟂)))) + (add-dots '(> < >= ≥ <= ≤ == === ≡ != ≠ !== ≢ ∈ ∉ ∋ ∌ ⊆ ⊈ ⊂ ⊄ ⊊ ∝ ∊ ∍ ∥ ∦ ∷ ∺ ∻ ∽ ∾ ≁ ≃ ≄ ≅ ≆ ≇ ≈ ≉ ≊ ≋ ≌ ≍ ≎ ≐ ≑ ≒ ≓ ≖ ≗ ≘ ≙ ≚ ≛ ≜ ≝ ≞ ≟ ≣ ≦ ≧ ≨ ≩ ≪ ≫ ≬ ≭ ≮ ≯ ≰ ≱ ≲ ≳ ≴ ≵ ≶ ≷ ≸ ≹ ≺ ≻ ≼ ≽ ≾ ≿ ⊀ ⊁ ⊃ ⊅ ⊇ ⊉ ⊋ ⊏ ⊐ ⊑ ⊒ ⊜ ⊩ ⊬ ⊮ ⊰ ⊱ ⊲ ⊳ ⊴ ⊵ ⊶ ⊷ ⋍ ⋐ ⋑ ⋕ ⋖ ⋗ ⋘ ⋙ ⋚ ⋛ ⋜ ⋝ ⋞ ⋟ ⋠ ⋡ ⋢ ⋣ ⋤ ⋥ ⋦ ⋧ ⋨ ⋩ ⋪ ⋫ ⋬ ⋭ ⋲ ⋳ ⋴ ⋵ ⋶ ⋷ ⋸ ⋹ ⋺ ⋻ ⋼ ⋽ ⋾ ⋿ ⟈ ⟉ ⟒ ⦷ ⧀ ⧁ ⧡ ⧣ ⧤ ⧥ ⩦ ⩧ ⩪ ⩫ ⩬ ⩭ ⩮ ⩯ ⩰ ⩱ ⩲ ⩳ ⩵ ⩶ ⩷ ⩸ ⩹ ⩺ ⩻ ⩼ ⩽ ⩾ ⩿ ⪀ ⪁ ⪂ ⪃ ⪄ ⪅ ⪆ ⪇ ⪈ ⪉ ⪊ ⪋ ⪌ ⪍ ⪎ ⪏ ⪐ ⪑ ⪒ ⪓ ⪔ ⪕ ⪖ ⪗ ⪘ ⪙ ⪚ ⪛ ⪜ ⪝ ⪞ ⪟ ⪠ ⪡ ⪢ ⪣ ⪤ ⪥ ⪦ ⪧ ⪨ ⪩ ⪪ ⪫ ⪬ ⪭ ⪮ ⪯ ⪰ ⪱ ⪲ ⪳ ⪴ ⪵ ⪶ ⪷ ⪸ ⪹ ⪺ ⪻ ⪼ ⪽ ⪾ ⪿ ⫀ ⫁ ⫂ ⫃ ⫄ ⫅ ⫆ ⫇ ⫈ ⫉ ⫊ ⫋ ⫌ ⫍ ⫎ ⫏ ⫐ ⫑ ⫒ ⫓ ⫔ ⫕ ⫖ ⫗ ⫘ ⫙ ⫷ ⫸ ⫹ ⫺ ⊢ ⊣ ⟂)))) (define prec-pipe< '(|.<\|| |<\||)) (define prec-pipe> '(|.\|>| |\|>|)) (define prec-colon (append! '(: |..|) (add-dots '(… ⁝ ⋮ ⋱ ⋰ ⋯)))) (define prec-plus (append! '($) - (add-dots '(+ - |\|| ⊕ ⊖ ⊞ ⊟ |++| ∪ ∨ ⊔ ± ∓ ∔ ∸ ≏ ⊎ ⊻ ⊽ ⋎ ⋓ ⧺ ⧻ ⨈ ⨢ ⨣ ⨤ ⨥ ⨦ ⨧ ⨨ ⨩ ⨪ ⨫ ⨬ ⨭ ⨮ ⨹ ⨺ ⩁ ⩂ ⩅ ⩊ ⩌ ⩏ ⩐ ⩒ ⩔ ⩖ ⩗ ⩛ ⩝ ⩡ ⩢ ⩣)))) + (add-dots '(+ - |\|| ⊕ ⊖ ⊞ ⊟ |++| ∪ ∨ ⊔ ± ∓ ∔ ∸ ≂ ≏ ⊎ ⊻ ⊽ ⋎ ⋓ ⧺ ⧻ ⨈ ⨢ ⨣ ⨤ ⨥ ⨦ ⨧ ⨨ ⨩ ⨪ ⨫ ⨬ ⨭ ⨮ ⨹ ⨺ ⩁ ⩂ ⩅ ⩊ ⩌ ⩏ ⩐ ⩒ ⩔ ⩖ ⩗ ⩛ ⩝ ⩡ ⩢ ⩣)))) (define prec-times (add-dots '(* / ÷ % & ⋅ ∘ × |\\| ∩ ∧ ⊗ ⊘ ⊙ ⊚ ⊛ ⊠ ⊡ ⊓ ∗ ∙ ∤ ⅋ ≀ ⊼ ⋄ ⋆ ⋇ ⋉ ⋊ ⋋ ⋌ ⋏ ⋒ ⟑ ⦸ ⦼ ⦾ ⦿ ⧶ ⧷ ⨇ ⨰ ⨱ ⨲ ⨳ ⨴ ⨵ ⨶ ⨷ ⨸ ⨻ ⨼ ⨽ ⩀ ⩃ ⩄ ⩋ ⩍ ⩎ ⩑ ⩓ ⩕ ⩘ ⩚ ⩜ ⩞ ⩟ ⩠ ⫛ ⊍ ▷ ⨝ ⟕ ⟖ ⟗))) (define prec-rational (add-dots '(//))) (define prec-bitshift (add-dots '(<< >> >>>))) @@ -779,7 +779,7 @@ (begin (if (not (ts:space? s)) (error "space required before \"?\" operator")) (take-token s) ; take the ? - (let ((t (with-whitespace-newline (without-range-colon (require-token s))))) + (let ((t (with-whitespace-newline (without-range-colon (peek-token s))))) (if (not (ts:space? s)) (error "space required after \"?\" operator"))) (let ((then (without-range-colon (parse-eq* s)))) @@ -788,7 +788,7 @@ (if (not (ts:space? s)) (error "space required before colon in \"?\" expression")) (take-token s) ; take the : - (let ((t (with-whitespace-newline (require-token s)))) + (let ((t (with-whitespace-newline (peek-token s)))) (if (not (ts:space? s)) (error "space required after colon in \"?\" expression"))) (list 'if ex then (parse-eq* s))))) diff --git a/src/toplevel.c b/src/toplevel.c index 6da0ab47b98f5..724ab13c30a03 100644 --- a/src/toplevel.c +++ b/src/toplevel.c @@ -639,8 +639,6 @@ jl_value_t *jl_toplevel_eval_flex(jl_module_t *m, jl_value_t *e, int fast, int e jl_module_use(m, import, name); } else { - if (!jl_is_module(u)) - jl_errorf("invalid using path: \"%s\" does not name a module", jl_symbol_name(name)); // `using A.B` syntax jl_module_using(m, u); if (m == jl_main_module && name == NULL) { diff --git a/stdlib/LibGit2/src/LibGit2.jl b/stdlib/LibGit2/src/LibGit2.jl index 133407b9a2ac4..3a50278f2e19b 100644 --- a/stdlib/LibGit2/src/LibGit2.jl +++ b/stdlib/LibGit2/src/LibGit2.jl @@ -829,7 +829,7 @@ function rebase!(repo::GitRepo, upstream::AbstractString="", newbase::AbstractSt try rbs = GitRebase(repo, head_ann, upst_ann, onto=onto_ann) try - for rbs_op in rbs + while (rbs_op = next(rbs)) !== nothing commit(rbs, sig) end finish(rbs, sig) diff --git a/stdlib/LibGit2/src/rebase.jl b/stdlib/LibGit2/src/rebase.jl index f876ad64265dd..00193b1a9d69f 100644 --- a/stdlib/LibGit2/src/rebase.jl +++ b/stdlib/LibGit2/src/rebase.jl @@ -45,21 +45,21 @@ function Base.getindex(rb::GitRebase, i::Integer) return rb_op end -function Base.iterate(rb::GitRebase, state=nothing) +function Base.next(rb::GitRebase) ensure_initialized() rb_op_ptr_ptr = Ref{Ptr{RebaseOperation}}(C_NULL) GC.@preserve rb begin - err = ccall((:git_rebase_next, :libgit2), Cint, - (Ptr{Ptr{RebaseOperation}}, Ptr{Cvoid}), - rb_op_ptr_ptr, rb.ptr) - if err == Cint(Error.GIT_OK) - return unsafe_load(rb_op_ptr_ptr[]), nothing - elseif err == Cint(Error.ITEROVER) - return nothing - else - throw(GitError(err)) + try + @check ccall((:git_rebase_next, :libgit2), Cint, + (Ptr{Ptr{RebaseOperation}}, Ptr{Cvoid}), + rb_op_ptr_ptr, rb.ptr) + catch err + err.code == Error.ITEROVER && return nothing + rethrow(err) end + rb_op_ptr = unsafe_load(rb_op_ptr_ptr[]) end + return rb_op_ptr end function Base.show(io::IO, rb::GitRebase) diff --git a/stdlib/LibGit2/test/libgit2.jl b/stdlib/LibGit2/test/libgit2.jl index 7c95aa6e89ecc..b3a243289e0e8 100644 --- a/stdlib/LibGit2/test/libgit2.jl +++ b/stdlib/LibGit2/test/libgit2.jl @@ -1610,7 +1610,7 @@ mktempdir() do dir rb = LibGit2.GitRebase(repo, head_ann, upst_ann) @test_throws BoundsError rb[3] @test_throws BoundsError rb[0] - rbo, _ = iterate(rb) + rbo = next(rb) rbo_str = sprint(show, rbo) @test rbo_str == "RebaseOperation($(string(rbo.id)))\nOperation type: REBASE_OPERATION_PICK\n" rb_str = sprint(show, rb) diff --git a/stdlib/LinearAlgebra/src/adjtrans.jl b/stdlib/LinearAlgebra/src/adjtrans.jl index 208c2f884c563..f75c42117ec8e 100644 --- a/stdlib/LinearAlgebra/src/adjtrans.jl +++ b/stdlib/LinearAlgebra/src/adjtrans.jl @@ -150,7 +150,7 @@ similar(A::AdjOrTrans, ::Type{T}, dims::Dims{N}) where {T,N} = similar(A.parent, # sundry basic definitions parent(A::AdjOrTrans) = A.parent -vec(v::TransposeAbsVec) = parent(v) +vec(v::AdjOrTransAbsVec) = v.parent cmp(A::AdjOrTransAbsVec, B::AdjOrTransAbsVec) = cmp(parent(A), parent(B)) isless(A::AdjOrTransAbsVec, B::AdjOrTransAbsVec) = isless(parent(A), parent(B)) diff --git a/stdlib/LinearAlgebra/src/generic.jl b/stdlib/LinearAlgebra/src/generic.jl index ea23e8d51cee7..ac55b9ed696ae 100644 --- a/stdlib/LinearAlgebra/src/generic.jl +++ b/stdlib/LinearAlgebra/src/generic.jl @@ -1274,7 +1274,7 @@ julia> logabsdet(B) (0.6931471805599453, 1.0) ``` """ -logabsdet(A::AbstractMatrix) = logabsdet(lu(A, check=false)) +logabsdet(A::AbstractMatrix) = logabsdet(lu(A)) """ logdet(M) diff --git a/stdlib/LinearAlgebra/src/qr.jl b/stdlib/LinearAlgebra/src/qr.jl index dab6bd6a88912..9f32d7c8d530e 100644 --- a/stdlib/LinearAlgebra/src/qr.jl +++ b/stdlib/LinearAlgebra/src/qr.jl @@ -322,10 +322,7 @@ solution and if the solution is not unique, the one with smallest norm is return Multiplication with respect to either full/square or non-full/square `Q` is allowed, i.e. both `F.Q*F.R` and `F.Q*A` are supported. A `Q` matrix can be converted into a regular matrix with -[`Matrix`](@ref). This operation returns the "thin" Q factor, i.e., if `A` is `m`×`n` with `m>=n`, then -`Matrix(F.Q)` yields an `m`×`n` matrix with orthonormal columns. To retrieve the "full" Q factor, an -`m`×`m` orthogonal matrix, use `F.Q*Matrix(I,m,m)`. If `m<=n`, then `Matrix(F.Q)` yields an `m`×`m` -orthogonal matrix. +[`Matrix`](@ref). # Examples ```jldoctest diff --git a/stdlib/LinearAlgebra/test/adjtrans.jl b/stdlib/LinearAlgebra/test/adjtrans.jl index ba3faac50374d..5abba308fcec0 100644 --- a/stdlib/LinearAlgebra/test/adjtrans.jl +++ b/stdlib/LinearAlgebra/test/adjtrans.jl @@ -271,10 +271,8 @@ end @testset "Adjoint and Transpose vector vec methods" begin intvec = [1, 2] - @test vec(Adjoint(intvec)) == intvec + @test vec(Adjoint(intvec)) === intvec @test vec(Transpose(intvec)) === intvec - cvec = [1 + 1im] - @test vec(cvec')[1] == cvec[1]' end @testset "horizontal concatenation of Adjoint/Transpose-wrapped vectors and Numbers" begin diff --git a/stdlib/LinearAlgebra/test/generic.jl b/stdlib/LinearAlgebra/test/generic.jl index 13d18e1d29b23..1c38883356efb 100644 --- a/stdlib/LinearAlgebra/test/generic.jl +++ b/stdlib/LinearAlgebra/test/generic.jl @@ -80,8 +80,6 @@ n = 5 # should be odd @test logdet(A) ≈ log(det(A)) @test logabsdet(A)[1] ≈ log(abs(det(A))) @test logabsdet(Matrix{elty}(-I, n, n))[2] == -1 - infinity = convert(float(elty), Inf) - @test logabsdet(zeros(elty, n, n)) == (-infinity, zero(elty)) if elty <: Real @test logabsdet(A)[2] == sign(det(A)) @test_throws DomainError logdet(Matrix{elty}(-I, n, n)) diff --git a/stdlib/REPL/docs/src/index.md b/stdlib/REPL/docs/src/index.md index 0920ab36549c3..42348a1eae06a 100644 --- a/stdlib/REPL/docs/src/index.md +++ b/stdlib/REPL/docs/src/index.md @@ -6,12 +6,18 @@ it has a searchable history, tab-completion, many helpful keybindings, and dedic shell modes. The REPL can be started by simply calling `julia` with no arguments or double-clicking on the executable: -```@eval -io = IOBuffer() -Base.banner(io) -banner = String(take!(io)) -import Markdown -Markdown.parse("```\n\$ julia\n\n$(banner)\njulia>\n```") +``` +$ julia + _ + _ _ _(_)_ | A fresh approach to technical computing + (_) | (_) (_) | Documentation: https://docs.julialang.org + _ _ _| |_ __ _ | Type "?help" for help. + | | | | | | |/ _` | | + | | |_| | | | (_| | | Version 0.6.0-dev.2493 (2017-01-31 18:53 UTC) + _/ |\__'_|_|_|\__'_| | Commit c99e12c* (0 days old master) +|__/ | x86_64-linux-gnu + +julia> ``` To exit the interactive session, type `^D` -- the control key together with the `d` key on a blank diff --git a/stdlib/SparseArrays/src/linalg.jl b/stdlib/SparseArrays/src/linalg.jl index 9be76da96dc98..6e9a751dd4306 100644 --- a/stdlib/SparseArrays/src/linalg.jl +++ b/stdlib/SparseArrays/src/linalg.jl @@ -234,261 +234,46 @@ function dot(A::SparseMatrixCSC{T1,S1},B::SparseMatrixCSC{T2,S2}) where {T1,T2,S return r end -## triangular sparse handling - -possible_adjoint(adj::Bool, a::Real ) = a -possible_adjoint(adj::Bool, a ) = adj ? adjoint(a) : a - -const UnitDiagonalTriangular = Union{UnitUpperTriangular,UnitLowerTriangular} - -const LowerTriangularPlain{T} = Union{ - LowerTriangular{T,<:SparseMatrixCSCUnion{T}}, - UnitLowerTriangular{T,<:SparseMatrixCSCUnion{T}}} - -const LowerTriangularWrapped{T} = Union{ - Adjoint{T,<:UpperTriangular{T,<:SparseMatrixCSCUnion{T}}}, - Adjoint{T,<:UnitUpperTriangular{T,<:SparseMatrixCSCUnion{T}}}, - Transpose{T,<:UpperTriangular{T,<:SparseMatrixCSCUnion{T}}}, - Transpose{T,<:UnitUpperTriangular{T,<:SparseMatrixCSCUnion{T}}}} where T - -const UpperTriangularPlain{T} = Union{ - UpperTriangular{T,<:SparseMatrixCSCUnion{T}}, - UnitUpperTriangular{T,<:SparseMatrixCSCUnion{T}}} - -const UpperTriangularWrapped{T} = Union{ - Adjoint{T,<:LowerTriangular{T,<:SparseMatrixCSCUnion{T}}}, - Adjoint{T,<:UnitLowerTriangular{T,<:SparseMatrixCSCUnion{T}}}, - Transpose{T,<:LowerTriangular{T,<:SparseMatrixCSCUnion{T}}}, - Transpose{T,<:UnitLowerTriangular{T,<:SparseMatrixCSCUnion{T}}}} where T - -const UpperTriangularSparse{T} = Union{ - UpperTriangularWrapped{T}, UpperTriangularPlain{T}} where T - -const LowerTriangularSparse{T} = Union{ - LowerTriangularWrapped{T}, LowerTriangularPlain{T}} where T - -const TriangularSparse{T} = Union{ - LowerTriangularSparse{T}, UpperTriangularSparse{T}} where T - -## triangular multipliers -function lmul!(A::TriangularSparse{T}, B::StridedVecOrMat{T}) where T +## solvers +function fwdTriSolve!(A::SparseMatrixCSCUnion, B::AbstractVecOrMat) +# forward substitution for CSC matrices @assert !has_offset_axes(A, B) nrowB, ncolB = size(B, 1), size(B, 2) ncol = LinearAlgebra.checksquare(A) if nrowB != ncol throw(DimensionMismatch("A is $(ncol) columns and B has $(nrowB) rows")) end - _lmul!(A, B) -end - -# forward multiplication for UpperTriangular SparseCSC matrices -function _lmul!(U::UpperTriangularPlain, B::StridedVecOrMat) - A = U.data - unit = U isa UnitDiagonalTriangular - - nrowB, ncolB = size(B, 1), size(B, 2) - aa = getnzval(A) - ja = getrowval(A) - ia = getcolptr(A) - - joff = 0 - for k = 1:ncolB - for j = 1:nrowB - i1 = ia[j] - i2 = ia[j + 1] - 1 - done = unit - - bj = B[joff + j] - for ii = i1:i2 - jai = ja[ii] - aii = aa[ii] - if jai < j - B[joff + jai] += aii * bj - elseif jai == j - if !unit - B[joff + j] *= aii - done = true - end - else - break - end - end - if !done - B[joff + j] -= B[joff + j] - end - end - joff += nrowB - end - B -end - -# backward multiplication for LowerTriangular SparseCSC matrices -function _lmul!(L::LowerTriangularPlain, B::StridedVecOrMat) - A = L.data - unit = L isa UnitDiagonalTriangular - - nrowB, ncolB = size(B, 1), size(B, 2) - aa = getnzval(A) - ja = getrowval(A) - ia = getcolptr(A) - - joff = 0 - for k = 1:ncolB - for j = nrowB:-1:1 - i1 = ia[j] - i2 = ia[j + 1] - 1 - done = unit - - bj = B[joff + j] - for ii = i2:-1:i1 - jai = ja[ii] - aii = aa[ii] - if jai > j - B[joff + jai] += aii * bj - elseif jai == j - if !unit - B[joff + j] *= aii - done = true - end - else - break - end - end - if !done - B[joff + j] -= B[joff + j] - end - end - joff += nrowB - end - B -end - -# forward multiplication for adjoint and transpose of LowerTriangular CSC matrices -function _lmul!(U::UpperTriangularWrapped, B::StridedVecOrMat) - A = U.parent.data - unit = U.parent isa UnitDiagonalTriangular - adj = U isa Adjoint - nrowB, ncolB = size(B, 1), size(B, 2) aa = getnzval(A) ja = getrowval(A) ia = getcolptr(A) - Z = zero(eltype(A)) joff = 0 for k = 1:ncolB for j = 1:nrowB i1 = ia[j] i2 = ia[j + 1] - 1 - akku = Z - j0 = !unit ? j : j + 1 - - # loop through column j of A - only structural non-zeros - for ii = i2:-1:i1 - jai = ja[ii] - if jai >= j0 - aai = possible_adjoint(adj, aa[ii]) - akku += B[joff + jai] * aai - else - break - end - end - if unit - akku += B[joff + j] - end - B[joff + j] = akku - end - joff += nrowB - end - B -end - -# backward multiplication with adjoint and transpose of LowerTriangular CSC matrices -function _lmul!(L::LowerTriangularWrapped, B::StridedVecOrMat) - A = L.parent.data - unit = L.parent isa UnitDiagonalTriangular - adj = L isa Adjoint - - nrowB, ncolB = size(B, 1), size(B, 2) - aa = getnzval(A) - ja = getrowval(A) - ia = getcolptr(A) - Z = zero(eltype(A)) - - joff = 0 - for k = 1:ncolB - for j = nrowB:-1:1 - i1 = ia[j] - i2 = ia[j + 1] - 1 - akku = Z - j0 = !unit ? j : j - 1 - # loop through column j of A - only structural non-zeros - for ii = i1:i2 + # loop through the structural zeros + ii = i1 + jai = ja[ii] + while ii <= i2 && jai < j + ii += 1 jai = ja[ii] - if jai <= j0 - aai = possible_adjoint(adj, aa[ii]) - akku += B[joff + jai] * aai - else - break - end - end - if unit - akku += B[joff + j] end - B[joff + j] = akku - end - joff += nrowB - end - B -end -## triangular solvers -function ldiv!(A::TriangularSparse{T}, B::StridedVecOrMat{T}) where T - @assert !has_offset_axes(A, B) - nrowB, ncolB = size(B, 1), size(B, 2) - ncol = LinearAlgebra.checksquare(A) - if nrowB != ncol - throw(DimensionMismatch("A is $(ncol) columns and B has $(nrowB) rows")) - end - _ldiv!(A, B) -end - -# forward substitution for LowerTriangular CSC matrices -function _ldiv!(L::LowerTriangularPlain, B::StridedVecOrMat) - A = L.data - unit = L isa UnitDiagonalTriangular - - nrowB, ncolB = size(B, 1), size(B, 2) - aa = getnzval(A) - ja = getrowval(A) - ia = getcolptr(A) - - joff = 0 - for k = 1:ncolB - for j = 1:nrowB - i1 = ia[j] - i2 = ia[j + 1] - 1 - - # find diagonal element - ii = searchsortedfirst(ja, j, i1, i2, Base.Order.Forward) - jai = ii > i2 ? zero(eltype(ja)) : ja[ii] - - bj = B[joff + j] # check for zero pivot and divide with pivot if jai == j - if !unit - bj /= aa[ii] - B[joff + j] = bj - end + bj = B[joff + jai]/aa[ii] + B[joff + jai] = bj ii += 1 - elseif !unit + else throw(LinearAlgebra.SingularException(j)) end # update remaining part for i = ii:i2 - B[joff + ja[i]] -= bj * aa[i] + B[joff + ja[i]] -= bj*aa[i] end end joff += nrowB @@ -496,12 +281,15 @@ function _ldiv!(L::LowerTriangularPlain, B::StridedVecOrMat) B end -# backward substitution for UpperTriangular CSC matrices -function _ldiv!(U::UpperTriangularPlain, B::StridedVecOrMat) - A = U.data - unit = U isa UnitDiagonalTriangular - +function bwdTriSolve!(A::SparseMatrixCSCUnion, B::AbstractVecOrMat) +# backward substitution for CSC matrices + @assert !has_offset_axes(A, B) nrowB, ncolB = size(B, 1), size(B, 2) + ncol = LinearAlgebra.checksquare(A) + if nrowB != ncol + throw(DimensionMismatch("A is $(ncol) columns and B has $(nrowB) rows")) + end + aa = getnzval(A) ja = getrowval(A) ia = getcolptr(A) @@ -512,25 +300,26 @@ function _ldiv!(U::UpperTriangularPlain, B::StridedVecOrMat) i1 = ia[j] i2 = ia[j + 1] - 1 - # find diagonal element - ii = searchsortedlast(ja, j, i1, i2, Base.Order.Forward) - jai = ii < i1 ? zero(eltype(ja)) : ja[ii] + # loop through the structural zeros + ii = i2 + jai = ja[ii] + while ii >= i1 && jai > j + ii -= 1 + jai = ja[ii] + end - bj = B[joff + j] # check for zero pivot and divide with pivot if jai == j - if !unit - bj /= aa[ii] - B[joff + j] = bj - end + bj = B[joff + jai]/aa[ii] + B[joff + jai] = bj ii -= 1 - elseif !unit + else throw(LinearAlgebra.SingularException(j)) end # update remaining part for i = ii:-1:i1 - B[joff + ja[i]] -= bj * aa[i] + B[joff + ja[i]] -= bj*aa[i] end end joff += nrowB @@ -538,13 +327,21 @@ function _ldiv!(U::UpperTriangularPlain, B::StridedVecOrMat) B end -# forward substitution for adjoint and transpose of UpperTriangular CSC matrices -function _ldiv!(L::LowerTriangularWrapped, B::StridedVecOrMat) - A = L.parent.data - unit = L.parent isa UnitDiagonalTriangular - adj = L isa Adjoint +fwdTriSolve!(aA::Adjoint{<:Any,<:SparseMatrixCSCUnion}, B::AbstractVecOrMat) = + _fwdTriSolve!(aA.parent, B, true) + +fwdTriSolve!(aA::Transpose{<:Any,<:SparseMatrixCSCUnion}, B::AbstractVecOrMat) = + _fwdTriSolve!(aA.parent, B, false) +function _fwdTriSolve!(A::SparseMatrixCSCUnion, B::AbstractVecOrMat, adj::Bool) +# forward substitution for adjoints of CSC matrices + @assert !has_offset_axes(A, B) nrowB, ncolB = size(B, 1), size(B, 2) + ncol = LinearAlgebra.checksquare(A) + if nrowB != ncol + throw(DimensionMismatch("A is $(ncol) columns and B has $(nrowB) rows")) + end + aa = getnzval(A) ja = getrowval(A) ia = getcolptr(A) @@ -558,39 +355,41 @@ function _ldiv!(L::LowerTriangularWrapped, B::StridedVecOrMat) done = false # loop through column j of A - only structural non-zeros - for ii = i1:i2 - jai = ja[ii] - if jai < j - aai = possible_adjoint(adj, aa[ii]) - akku -= B[joff + jai] * aai - elseif jai == j - if !unit - aai = possible_adjoint(adj, aa[ii]) - akku /= aai - end + for ip = i1:i2 + i = ja[ip] + aai = adj ? aa[ip]' : aa[ip] + if i < j + akku -= B[joff + i] * aai + elseif i == j + B[joff + j] = akku / aai done = true break - else - break end end - if !done && !unit + if !done throw(LinearAlgebra.SingularException(j)) end - B[joff + j] = akku end joff += nrowB end B end -# backward substitution for adjoint and transpose of LowerTriangular CSC matrices -function _ldiv!(U::UpperTriangularWrapped, B::StridedVecOrMat) - A = U.parent.data - unit = U.parent isa UnitDiagonalTriangular - adj = U isa Adjoint +bwdTriSolve!(aA::Adjoint{<:Any,<:SparseMatrixCSCUnion}, B::AbstractVecOrMat) = + _bwdTriSolve!(aA.parent, B, true) + +bwdTriSolve!(aA::Transpose{<:Any,<:SparseMatrixCSCUnion}, B::AbstractVecOrMat) = + _bwdTriSolve!(aA.parent, B, false) + +function _bwdTriSolve!(A::SparseMatrixCSCUnion, B::AbstractVecOrMat, adj::Bool) +# forward substitution for adjoints of CSC matrices + @assert !has_offset_axes(A, B) + nrowB, ncolB = size(B, 1), size(B, 2) + ncol = LinearAlgebra.checksquare(A) + if nrowB != ncol + throw(DimensionMismatch("A is $(ncol) columns and B has $(nrowB) rows")) + end - nrowB, ncolB = size(B, 1), size(B, 2) aa = getnzval(A) ja = getrowval(A) ia = getcolptr(A) @@ -604,36 +403,43 @@ function _ldiv!(U::UpperTriangularWrapped, B::StridedVecOrMat) done = false # loop through column j of A - only structural non-zeros - for ii = i2:-1:i1 - jai = ja[ii] - if jai > j - aai = possible_adjoint(adj, aa[ii]) - akku -= B[joff + jai] * aai - elseif jai == j - if !unit - aai = possible_adjoint(adj, aa[ii]) - akku /= aai - end + for ip = i2:-1:i1 + i = ja[ip] + aai = adj ? aa[ip]' : aa[ip] + if i > j + akku -= B[joff + i] * aai + elseif i == j + B[joff + j] = akku / aai done = true break - else - break end end - if !done && !unit + if !done throw(LinearAlgebra.SingularException(j)) end - B[joff + j] = akku end joff += nrowB end B end -(\)(L::TriangularSparse, B::SparseMatrixCSC) = ldiv!(L, Array(B)) -(*)(L::TriangularSparse, B::SparseMatrixCSC) = lmul!(L, Array(B)) +ldiv!(L::LowerTriangular{T,<:SparseMatrixCSCUnion{T}}, B::StridedVecOrMat) where {T} = fwdTriSolve!(L.data, B) +ldiv!(L::Adjoint{T,<:UpperTriangular{T,<:SparseMatrixCSCUnion{T}}}, B::StridedVecOrMat) where {T} = _fwdTriSolve!(L.parent.data, B, true) +ldiv!(L::Transpose{T,<:UpperTriangular{T,<:SparseMatrixCSCUnion{T}}}, B::StridedVecOrMat) where {T} = _fwdTriSolve!(L.parent.data, B, false) + +ldiv!(U::UpperTriangular{T,<:SparseMatrixCSCUnion{T}}, B::StridedVecOrMat) where {T} = bwdTriSolve!(U.data, B) +ldiv!(L::Adjoint{T,<:LowerTriangular{T,<:SparseMatrixCSCUnion{T}}}, B::StridedVecOrMat) where {T} = _bwdTriSolve!(L.parent.data, B, true) +ldiv!(L::Transpose{T,<:LowerTriangular{T,<:SparseMatrixCSCUnion{T}}}, B::StridedVecOrMat) where {T} = _bwdTriSolve!(L.parent.data, B, false) + +(\)(L::Union{LowerTriangular{T,<:SparseMatrixCSCUnion{T}}, + Adjoint{T,<:UpperTriangular{T,<:SparseMatrixCSCUnion{T}}}, + Transpose{T,<:UpperTriangular{T,<:SparseMatrixCSCUnion{T}}}}, + B::SparseMatrixCSC) where {T} = ldiv!(L, Array(B)) -## end of triangular +(\)(U::Union{UpperTriangular{T,<:SparseMatrixCSCUnion{T}}, + Adjoint{T,<:LowerTriangular{T,<:SparseMatrixCSCUnion{T}}}, + Transpose{T,<:LowerTriangular{T,<:SparseMatrixCSCUnion{T}}}}, + B::SparseMatrixCSC) where {T} = ldiv!(U, Array(B)) \(A::Transpose{<:Real,<:Hermitian{<:Real,<:SparseMatrixCSC}}, B::Vector) = A.parent \ B \(A::Transpose{<:Complex,<:Hermitian{<:Complex,<:SparseMatrixCSC}}, B::Vector) = copy(A) \ B diff --git a/stdlib/SparseArrays/test/sparse.jl b/stdlib/SparseArrays/test/sparse.jl index fd13fc9189233..f88c6dde06493 100644 --- a/stdlib/SparseArrays/test/sparse.jl +++ b/stdlib/SparseArrays/test/sparse.jl @@ -2289,36 +2289,4 @@ end @test adjoint(MC) == copy(adjoint(SC)) end -@testset "Triangular matrices" begin - rng = Random.MersenneTwister(0) - n = 1000 - A = sprand(rng, n, n, 0.01) - B = ones(n) - MA = Matrix(A) - for tr in (identity, adjoint, transpose) - for wr in (UpperTriangular, LowerTriangular, UnitUpperTriangular, UnitLowerTriangular) - AW = tr(wr(A)) - MAW = tr(wr(MA)) - @test AW * B ≈ MAW * B - end - end - A = A - Diagonal(diag(A)) - A += 2I - MA = Matrix(A) - for tr in (identity, adjoint, transpose) - for wr in (UpperTriangular, LowerTriangular, UnitUpperTriangular, UnitLowerTriangular) - AW = tr(wr(A)) - MAW = tr(wr(MA)) - @test AW \ B ≈ MAW \ B - end - end - - A = LowerTriangular(sparse([0 2.0;0 1])) - @test_throws SingularException(1) A \ ones(2) - A = UpperTriangular(sparse([1.0 0;0 0])) - @test_throws SingularException(2) A \ ones(2) - - -end - end # module diff --git a/test/compiler/compiler.jl b/test/compiler/compiler.jl index 904695982e030..74d263e3e9061 100644 --- a/test/compiler/compiler.jl +++ b/test/compiler/compiler.jl @@ -10,28 +10,14 @@ using InteractiveUtils: code_llvm # demonstrate some of the type-size limits @test Core.Compiler.limit_type_size(Ref{Complex{T} where T}, Ref, Ref, 100, 0) == Ref @test Core.Compiler.limit_type_size(Ref{Complex{T} where T}, Ref{Complex{T} where T}, Ref, 100, 0) == Ref{Complex{T} where T} - let comparison = Tuple{X, X} where X<:Tuple sig = Tuple{X, X} where X<:comparison ref = Tuple{X, X} where X - @test Core.Compiler.limit_type_size(sig, comparison, comparison, 100, 100) == Tuple{Tuple, Tuple} - @test Core.Compiler.limit_type_size(sig, ref, comparison, 100, 100) == Tuple{Any, Any} - @test Core.Compiler.limit_type_size(Tuple{sig}, Tuple{ref}, comparison, 100, 100) == Tuple{Tuple{Any, Any}} - @test Core.Compiler.limit_type_size(sig, ref, Tuple{comparison}, 100, 100) == Tuple{Tuple{X, X} where X<:Tuple, Tuple{X, X} where X<:Tuple} - @test Core.Compiler.limit_type_size(ref, sig, Union{}, 100, 100) == ref -end - -let ref = Tuple{T, Val{T}} where T<:Val - sig = Tuple{T, Val{T}} where T<:(Val{T} where T<:Val) - @test Core.Compiler.limit_type_size(sig, ref, Union{}, 100, 100) == Tuple{Val, Val} - @test Core.Compiler.limit_type_size(ref, sig, Union{}, 100, 100) == ref + @test Core.Compiler.limit_type_size(sig, comparison, comparison, 100, 10) == comparison + @test Core.Compiler.limit_type_size(sig, ref, comparison, 100, 10) == ref + @test Core.Compiler.limit_type_size(Tuple{sig}, Tuple{ref}, comparison, 100, 10) == Tuple{ref} + @test Core.Compiler.limit_type_size(sig, ref, Tuple{comparison}, 100, 10) == sig end -let ref = Tuple{T, Val{T}} where T<:(Val{T} where T<:(Val{T} where T<:(Val{T} where T<:Val))) - sig = Tuple{T, Val{T}} where T<:(Val{T} where T<:(Val{T} where T<:(Val{T} where T<:(Val{T} where T<:Val)))) - @test Core.Compiler.limit_type_size(sig, ref, Union{}, 100, 100) == Tuple{Val, Val} - @test Core.Compiler.limit_type_size(ref, sig, Union{}, 100, 100) == ref -end - # PR 22120 function tmerge_test(a, b, r, commutative=true) diff --git a/test/iterators.jl b/test/iterators.jl index 5fca4f11b91ad..b476887f7ea05 100644 --- a/test/iterators.jl +++ b/test/iterators.jl @@ -270,8 +270,7 @@ let iters = (1:2, rand(2, 2, 2), take(1:4, 2), product(1:2, 1:3), - product(rand(2, 2), rand(1, 1, 1)), - repeated([1, -1], 2) # 28497 + product(rand(2, 2), rand(1, 1, 1)) ) for method in [size, length, ndims, eltype] for i = 1:length(iters) diff --git a/test/spawn.jl b/test/spawn.jl index aa2c4001752ce..e78e5d6933869 100644 --- a/test/spawn.jl +++ b/test/spawn.jl @@ -59,14 +59,13 @@ Sys.isunix() && run(pipeline(yescmd, `head`, devnull)) let a, p a = Base.Condition() - t = @async begin + @async begin p = run(pipeline(yescmd,devnull), wait=false) Base.notify(a,p) @test !success(p) end p = wait(a) kill(p) - wait(t) end if valgrind_off @@ -145,15 +144,11 @@ let str = "", proc, str2, file end # Here we test that if we close a stream with pending writes, we don't lose the writes. - @sync begin - proc = open(`$catcmd -`, "r+") - @async begin - write(proc, str) # TODO: use Base.uv_write_async to restore the intended functionality of this test - close(proc.in) - end - str2 = read(proc, String) - @test str2 == str - end + proc = open(`$catcmd -`, "r+") + write(proc, str) + close(proc.in) + str2 = read(proc, String) + @test str2 == str # This test hangs if the end-of-run-walk-across-uv-streams calls shutdown on a stream that is shutting down. file = tempname() @@ -420,15 +415,11 @@ end @test Base.shell_split("\"\\\\\"") == ["\\"] # issue #13616 -pcatcmd = `$catcmd _doesnt_exist__111_` -let p = eachline(pipeline(`$catcmd _doesnt_exist__111_`, stderr=devnull)) - @test_throws(ErrorException("failed process: Process($pcatcmd, ProcessExited(1)) [1]"), - collect(p)) -end +@test_throws ErrorException collect(eachline(pipeline(`$catcmd _doesnt_exist__111_`, stderr=devnull))) # make sure windows_verbatim strips quotes if Sys.iswindows() - @test read(`cmd.exe /c dir /b spawn.jl`, String) == read(Cmd(`cmd.exe /c dir /b "\"spawn.jl\""`, windows_verbatim=true), String) + read(`cmd.exe /c dir /b spawn.jl`, String) == read(Cmd(`cmd.exe /c dir /b "\"spawn.jl\""`, windows_verbatim=true), String) end # make sure Cmd is nestable @@ -489,7 +480,7 @@ let out = Pipe(), inpt = Pipe() Base.link_pipe!(out, reader_supports_async=true) Base.link_pipe!(inpt, writer_supports_async=true) p = run(pipeline(catcmd, stdin=inpt, stdout=out, stderr=devnull), wait=false) - t = @async begin # feed cat with 2 MB of data (zeros) + @async begin # feed cat with 2 MB of data (zeros) write(inpt, zeros(UInt8, 1048576 * 2)) close(inpt) end @@ -498,7 +489,6 @@ let out = Pipe(), inpt = Pipe() close(out.in) # make sure we can still close the write end @test sizeof(read(out)) == 1048576 * 2 # make sure we get all the data @test success(p) - wait(t) end # `kill` error conditions @@ -604,13 +594,3 @@ mktempdir() do dir end end end - -# Issue #27550: make sure `peek` works when slurping a Char from an AbstractPipe -open(`$catcmd`, "r+") do f - t = @async begin - write(f, "δ") - close(f.in) - end - @test read(f, Char) == 'δ' - wait(t) -end diff --git a/test/syntax.jl b/test/syntax.jl index 4e4417dd5a3b6..935c7ce58add5 100644 --- a/test/syntax.jl +++ b/test/syntax.jl @@ -1642,7 +1642,3 @@ end for ex in [:([x=1]), :(T{x=1})] @test Meta.lower(@__MODULE__, ex) == Expr(:error, string("misplaced assignment statement in \"", ex, "\"")) end - -# issue #28576 -@test Meta.isexpr(Meta.parse("1 == 2 ?"), :incomplete) -@test Meta.isexpr(Meta.parse("1 == 2 ? 3 :"), :incomplete) From 6f5e94296d618201bbcfe65f717910a5616f08db Mon Sep 17 00:00:00 2001 From: mcognetta Date: Sun, 16 Sep 2018 20:04:20 +0900 Subject: [PATCH 17/26] Revert "additional test cases and bug fix" This reverts commit 21592db0ed0dec1750db5a153a761133c0d2dd9e. --- stdlib/SparseArrays/src/linalg.jl | 6 ++++-- stdlib/SparseArrays/test/sparse.jl | 11 ----------- 2 files changed, 4 insertions(+), 13 deletions(-) diff --git a/stdlib/SparseArrays/src/linalg.jl b/stdlib/SparseArrays/src/linalg.jl index 9be76da96dc98..86ab4b78f50f0 100644 --- a/stdlib/SparseArrays/src/linalg.jl +++ b/stdlib/SparseArrays/src/linalg.jl @@ -472,7 +472,8 @@ function _ldiv!(L::LowerTriangularPlain, B::StridedVecOrMat) # find diagonal element ii = searchsortedfirst(ja, j, i1, i2, Base.Order.Forward) - jai = ii > i2 ? zero(eltype(ja)) : ja[ii] + ii > i2 && ( ii = i1) + jai = ja[ii] bj = B[joff + j] # check for zero pivot and divide with pivot @@ -514,7 +515,8 @@ function _ldiv!(U::UpperTriangularPlain, B::StridedVecOrMat) # find diagonal element ii = searchsortedlast(ja, j, i1, i2, Base.Order.Forward) - jai = ii < i1 ? zero(eltype(ja)) : ja[ii] + ii < i1 && ( ii = i2) + jai = ja[ii] bj = B[joff + j] # check for zero pivot and divide with pivot diff --git a/stdlib/SparseArrays/test/sparse.jl b/stdlib/SparseArrays/test/sparse.jl index ccc715064977f..ac91d66614fa5 100644 --- a/stdlib/SparseArrays/test/sparse.jl +++ b/stdlib/SparseArrays/test/sparse.jl @@ -2312,17 +2312,6 @@ end @test AW \ B ≈ MAW \ B end end - - A = LowerTriangular(sparse([0 2.0;0 1])) - @test_throws SingularException(1) A \ ones(2) - A = UpperTriangular(sparse([1.0 0;0 0])) - @test_throws SingularException(2) A \ ones(2) -end - -@testset "Issue #28634" begin - a = SparseMatrixCSC{Int8, Int16}([1 2; 3 4]) - na = SparseMatrixCSC(a) - @test typeof(a) === typeof(na) end end # module From 2d594962ed48a4f24bb848f6ab4b38fe6a0fcd21 Mon Sep 17 00:00:00 2001 From: mcognetta Date: Sun, 16 Sep 2018 20:05:30 +0900 Subject: [PATCH 18/26] reverting sparse changes --- stdlib/SparseArrays/src/linalg.jl | 374 +++++++---------------------- stdlib/SparseArrays/test/sparse.jl | 25 -- 2 files changed, 89 insertions(+), 310 deletions(-) diff --git a/stdlib/SparseArrays/src/linalg.jl b/stdlib/SparseArrays/src/linalg.jl index 86ab4b78f50f0..6e9a751dd4306 100644 --- a/stdlib/SparseArrays/src/linalg.jl +++ b/stdlib/SparseArrays/src/linalg.jl @@ -234,59 +234,16 @@ function dot(A::SparseMatrixCSC{T1,S1},B::SparseMatrixCSC{T2,S2}) where {T1,T2,S return r end -## triangular sparse handling - -possible_adjoint(adj::Bool, a::Real ) = a -possible_adjoint(adj::Bool, a ) = adj ? adjoint(a) : a - -const UnitDiagonalTriangular = Union{UnitUpperTriangular,UnitLowerTriangular} - -const LowerTriangularPlain{T} = Union{ - LowerTriangular{T,<:SparseMatrixCSCUnion{T}}, - UnitLowerTriangular{T,<:SparseMatrixCSCUnion{T}}} - -const LowerTriangularWrapped{T} = Union{ - Adjoint{T,<:UpperTriangular{T,<:SparseMatrixCSCUnion{T}}}, - Adjoint{T,<:UnitUpperTriangular{T,<:SparseMatrixCSCUnion{T}}}, - Transpose{T,<:UpperTriangular{T,<:SparseMatrixCSCUnion{T}}}, - Transpose{T,<:UnitUpperTriangular{T,<:SparseMatrixCSCUnion{T}}}} where T - -const UpperTriangularPlain{T} = Union{ - UpperTriangular{T,<:SparseMatrixCSCUnion{T}}, - UnitUpperTriangular{T,<:SparseMatrixCSCUnion{T}}} - -const UpperTriangularWrapped{T} = Union{ - Adjoint{T,<:LowerTriangular{T,<:SparseMatrixCSCUnion{T}}}, - Adjoint{T,<:UnitLowerTriangular{T,<:SparseMatrixCSCUnion{T}}}, - Transpose{T,<:LowerTriangular{T,<:SparseMatrixCSCUnion{T}}}, - Transpose{T,<:UnitLowerTriangular{T,<:SparseMatrixCSCUnion{T}}}} where T - -const UpperTriangularSparse{T} = Union{ - UpperTriangularWrapped{T}, UpperTriangularPlain{T}} where T - -const LowerTriangularSparse{T} = Union{ - LowerTriangularWrapped{T}, LowerTriangularPlain{T}} where T - -const TriangularSparse{T} = Union{ - LowerTriangularSparse{T}, UpperTriangularSparse{T}} where T - -## triangular multipliers -function lmul!(A::TriangularSparse{T}, B::StridedVecOrMat{T}) where T +## solvers +function fwdTriSolve!(A::SparseMatrixCSCUnion, B::AbstractVecOrMat) +# forward substitution for CSC matrices @assert !has_offset_axes(A, B) nrowB, ncolB = size(B, 1), size(B, 2) ncol = LinearAlgebra.checksquare(A) if nrowB != ncol throw(DimensionMismatch("A is $(ncol) columns and B has $(nrowB) rows")) end - _lmul!(A, B) -end -# forward multiplication for UpperTriangular SparseCSC matrices -function _lmul!(U::UpperTriangularPlain, B::StridedVecOrMat) - A = U.data - unit = U isa UnitDiagonalTriangular - - nrowB, ncolB = size(B, 1), size(B, 2) aa = getnzval(A) ja = getrowval(A) ia = getcolptr(A) @@ -296,200 +253,27 @@ function _lmul!(U::UpperTriangularPlain, B::StridedVecOrMat) for j = 1:nrowB i1 = ia[j] i2 = ia[j + 1] - 1 - done = unit - - bj = B[joff + j] - for ii = i1:i2 - jai = ja[ii] - aii = aa[ii] - if jai < j - B[joff + jai] += aii * bj - elseif jai == j - if !unit - B[joff + j] *= aii - done = true - end - else - break - end - end - if !done - B[joff + j] -= B[joff + j] - end - end - joff += nrowB - end - B -end - -# backward multiplication for LowerTriangular SparseCSC matrices -function _lmul!(L::LowerTriangularPlain, B::StridedVecOrMat) - A = L.data - unit = L isa UnitDiagonalTriangular - - nrowB, ncolB = size(B, 1), size(B, 2) - aa = getnzval(A) - ja = getrowval(A) - ia = getcolptr(A) - - joff = 0 - for k = 1:ncolB - for j = nrowB:-1:1 - i1 = ia[j] - i2 = ia[j + 1] - 1 - done = unit - - bj = B[joff + j] - for ii = i2:-1:i1 - jai = ja[ii] - aii = aa[ii] - if jai > j - B[joff + jai] += aii * bj - elseif jai == j - if !unit - B[joff + j] *= aii - done = true - end - else - break - end - end - if !done - B[joff + j] -= B[joff + j] - end - end - joff += nrowB - end - B -end - -# forward multiplication for adjoint and transpose of LowerTriangular CSC matrices -function _lmul!(U::UpperTriangularWrapped, B::StridedVecOrMat) - A = U.parent.data - unit = U.parent isa UnitDiagonalTriangular - adj = U isa Adjoint - - nrowB, ncolB = size(B, 1), size(B, 2) - aa = getnzval(A) - ja = getrowval(A) - ia = getcolptr(A) - Z = zero(eltype(A)) - - joff = 0 - for k = 1:ncolB - for j = 1:nrowB - i1 = ia[j] - i2 = ia[j + 1] - 1 - akku = Z - j0 = !unit ? j : j + 1 - - # loop through column j of A - only structural non-zeros - for ii = i2:-1:i1 - jai = ja[ii] - if jai >= j0 - aai = possible_adjoint(adj, aa[ii]) - akku += B[joff + jai] * aai - else - break - end - end - if unit - akku += B[joff + j] - end - B[joff + j] = akku - end - joff += nrowB - end - B -end - -# backward multiplication with adjoint and transpose of LowerTriangular CSC matrices -function _lmul!(L::LowerTriangularWrapped, B::StridedVecOrMat) - A = L.parent.data - unit = L.parent isa UnitDiagonalTriangular - adj = L isa Adjoint - - nrowB, ncolB = size(B, 1), size(B, 2) - aa = getnzval(A) - ja = getrowval(A) - ia = getcolptr(A) - Z = zero(eltype(A)) - - joff = 0 - for k = 1:ncolB - for j = nrowB:-1:1 - i1 = ia[j] - i2 = ia[j + 1] - 1 - akku = Z - j0 = !unit ? j : j - 1 - # loop through column j of A - only structural non-zeros - for ii = i1:i2 + # loop through the structural zeros + ii = i1 + jai = ja[ii] + while ii <= i2 && jai < j + ii += 1 jai = ja[ii] - if jai <= j0 - aai = possible_adjoint(adj, aa[ii]) - akku += B[joff + jai] * aai - else - break - end - end - if unit - akku += B[joff + j] end - B[joff + j] = akku - end - joff += nrowB - end - B -end - -## triangular solvers -function ldiv!(A::TriangularSparse{T}, B::StridedVecOrMat{T}) where T - @assert !has_offset_axes(A, B) - nrowB, ncolB = size(B, 1), size(B, 2) - ncol = LinearAlgebra.checksquare(A) - if nrowB != ncol - throw(DimensionMismatch("A is $(ncol) columns and B has $(nrowB) rows")) - end - _ldiv!(A, B) -end -# forward substitution for LowerTriangular CSC matrices -function _ldiv!(L::LowerTriangularPlain, B::StridedVecOrMat) - A = L.data - unit = L isa UnitDiagonalTriangular - - nrowB, ncolB = size(B, 1), size(B, 2) - aa = getnzval(A) - ja = getrowval(A) - ia = getcolptr(A) - - joff = 0 - for k = 1:ncolB - for j = 1:nrowB - i1 = ia[j] - i2 = ia[j + 1] - 1 - - # find diagonal element - ii = searchsortedfirst(ja, j, i1, i2, Base.Order.Forward) - ii > i2 && ( ii = i1) - jai = ja[ii] - - bj = B[joff + j] # check for zero pivot and divide with pivot if jai == j - if !unit - bj /= aa[ii] - B[joff + j] = bj - end + bj = B[joff + jai]/aa[ii] + B[joff + jai] = bj ii += 1 - elseif !unit + else throw(LinearAlgebra.SingularException(j)) end # update remaining part for i = ii:i2 - B[joff + ja[i]] -= bj * aa[i] + B[joff + ja[i]] -= bj*aa[i] end end joff += nrowB @@ -497,12 +281,15 @@ function _ldiv!(L::LowerTriangularPlain, B::StridedVecOrMat) B end -# backward substitution for UpperTriangular CSC matrices -function _ldiv!(U::UpperTriangularPlain, B::StridedVecOrMat) - A = U.data - unit = U isa UnitDiagonalTriangular - +function bwdTriSolve!(A::SparseMatrixCSCUnion, B::AbstractVecOrMat) +# backward substitution for CSC matrices + @assert !has_offset_axes(A, B) nrowB, ncolB = size(B, 1), size(B, 2) + ncol = LinearAlgebra.checksquare(A) + if nrowB != ncol + throw(DimensionMismatch("A is $(ncol) columns and B has $(nrowB) rows")) + end + aa = getnzval(A) ja = getrowval(A) ia = getcolptr(A) @@ -513,26 +300,26 @@ function _ldiv!(U::UpperTriangularPlain, B::StridedVecOrMat) i1 = ia[j] i2 = ia[j + 1] - 1 - # find diagonal element - ii = searchsortedlast(ja, j, i1, i2, Base.Order.Forward) - ii < i1 && ( ii = i2) + # loop through the structural zeros + ii = i2 jai = ja[ii] + while ii >= i1 && jai > j + ii -= 1 + jai = ja[ii] + end - bj = B[joff + j] # check for zero pivot and divide with pivot if jai == j - if !unit - bj /= aa[ii] - B[joff + j] = bj - end + bj = B[joff + jai]/aa[ii] + B[joff + jai] = bj ii -= 1 - elseif !unit + else throw(LinearAlgebra.SingularException(j)) end # update remaining part for i = ii:-1:i1 - B[joff + ja[i]] -= bj * aa[i] + B[joff + ja[i]] -= bj*aa[i] end end joff += nrowB @@ -540,13 +327,21 @@ function _ldiv!(U::UpperTriangularPlain, B::StridedVecOrMat) B end -# forward substitution for adjoint and transpose of UpperTriangular CSC matrices -function _ldiv!(L::LowerTriangularWrapped, B::StridedVecOrMat) - A = L.parent.data - unit = L.parent isa UnitDiagonalTriangular - adj = L isa Adjoint +fwdTriSolve!(aA::Adjoint{<:Any,<:SparseMatrixCSCUnion}, B::AbstractVecOrMat) = + _fwdTriSolve!(aA.parent, B, true) + +fwdTriSolve!(aA::Transpose{<:Any,<:SparseMatrixCSCUnion}, B::AbstractVecOrMat) = + _fwdTriSolve!(aA.parent, B, false) +function _fwdTriSolve!(A::SparseMatrixCSCUnion, B::AbstractVecOrMat, adj::Bool) +# forward substitution for adjoints of CSC matrices + @assert !has_offset_axes(A, B) nrowB, ncolB = size(B, 1), size(B, 2) + ncol = LinearAlgebra.checksquare(A) + if nrowB != ncol + throw(DimensionMismatch("A is $(ncol) columns and B has $(nrowB) rows")) + end + aa = getnzval(A) ja = getrowval(A) ia = getcolptr(A) @@ -560,39 +355,41 @@ function _ldiv!(L::LowerTriangularWrapped, B::StridedVecOrMat) done = false # loop through column j of A - only structural non-zeros - for ii = i1:i2 - jai = ja[ii] - if jai < j - aai = possible_adjoint(adj, aa[ii]) - akku -= B[joff + jai] * aai - elseif jai == j - if !unit - aai = possible_adjoint(adj, aa[ii]) - akku /= aai - end + for ip = i1:i2 + i = ja[ip] + aai = adj ? aa[ip]' : aa[ip] + if i < j + akku -= B[joff + i] * aai + elseif i == j + B[joff + j] = akku / aai done = true break - else - break end end - if !done && !unit + if !done throw(LinearAlgebra.SingularException(j)) end - B[joff + j] = akku end joff += nrowB end B end -# backward substitution for adjoint and transpose of LowerTriangular CSC matrices -function _ldiv!(U::UpperTriangularWrapped, B::StridedVecOrMat) - A = U.parent.data - unit = U.parent isa UnitDiagonalTriangular - adj = U isa Adjoint +bwdTriSolve!(aA::Adjoint{<:Any,<:SparseMatrixCSCUnion}, B::AbstractVecOrMat) = + _bwdTriSolve!(aA.parent, B, true) + +bwdTriSolve!(aA::Transpose{<:Any,<:SparseMatrixCSCUnion}, B::AbstractVecOrMat) = + _bwdTriSolve!(aA.parent, B, false) + +function _bwdTriSolve!(A::SparseMatrixCSCUnion, B::AbstractVecOrMat, adj::Bool) +# forward substitution for adjoints of CSC matrices + @assert !has_offset_axes(A, B) + nrowB, ncolB = size(B, 1), size(B, 2) + ncol = LinearAlgebra.checksquare(A) + if nrowB != ncol + throw(DimensionMismatch("A is $(ncol) columns and B has $(nrowB) rows")) + end - nrowB, ncolB = size(B, 1), size(B, 2) aa = getnzval(A) ja = getrowval(A) ia = getcolptr(A) @@ -606,36 +403,43 @@ function _ldiv!(U::UpperTriangularWrapped, B::StridedVecOrMat) done = false # loop through column j of A - only structural non-zeros - for ii = i2:-1:i1 - jai = ja[ii] - if jai > j - aai = possible_adjoint(adj, aa[ii]) - akku -= B[joff + jai] * aai - elseif jai == j - if !unit - aai = possible_adjoint(adj, aa[ii]) - akku /= aai - end + for ip = i2:-1:i1 + i = ja[ip] + aai = adj ? aa[ip]' : aa[ip] + if i > j + akku -= B[joff + i] * aai + elseif i == j + B[joff + j] = akku / aai done = true break - else - break end end - if !done && !unit + if !done throw(LinearAlgebra.SingularException(j)) end - B[joff + j] = akku end joff += nrowB end B end -(\)(L::TriangularSparse, B::SparseMatrixCSC) = ldiv!(L, Array(B)) -(*)(L::TriangularSparse, B::SparseMatrixCSC) = lmul!(L, Array(B)) +ldiv!(L::LowerTriangular{T,<:SparseMatrixCSCUnion{T}}, B::StridedVecOrMat) where {T} = fwdTriSolve!(L.data, B) +ldiv!(L::Adjoint{T,<:UpperTriangular{T,<:SparseMatrixCSCUnion{T}}}, B::StridedVecOrMat) where {T} = _fwdTriSolve!(L.parent.data, B, true) +ldiv!(L::Transpose{T,<:UpperTriangular{T,<:SparseMatrixCSCUnion{T}}}, B::StridedVecOrMat) where {T} = _fwdTriSolve!(L.parent.data, B, false) + +ldiv!(U::UpperTriangular{T,<:SparseMatrixCSCUnion{T}}, B::StridedVecOrMat) where {T} = bwdTriSolve!(U.data, B) +ldiv!(L::Adjoint{T,<:LowerTriangular{T,<:SparseMatrixCSCUnion{T}}}, B::StridedVecOrMat) where {T} = _bwdTriSolve!(L.parent.data, B, true) +ldiv!(L::Transpose{T,<:LowerTriangular{T,<:SparseMatrixCSCUnion{T}}}, B::StridedVecOrMat) where {T} = _bwdTriSolve!(L.parent.data, B, false) + +(\)(L::Union{LowerTriangular{T,<:SparseMatrixCSCUnion{T}}, + Adjoint{T,<:UpperTriangular{T,<:SparseMatrixCSCUnion{T}}}, + Transpose{T,<:UpperTriangular{T,<:SparseMatrixCSCUnion{T}}}}, + B::SparseMatrixCSC) where {T} = ldiv!(L, Array(B)) -## end of triangular +(\)(U::Union{UpperTriangular{T,<:SparseMatrixCSCUnion{T}}, + Adjoint{T,<:LowerTriangular{T,<:SparseMatrixCSCUnion{T}}}, + Transpose{T,<:LowerTriangular{T,<:SparseMatrixCSCUnion{T}}}}, + B::SparseMatrixCSC) where {T} = ldiv!(U, Array(B)) \(A::Transpose{<:Real,<:Hermitian{<:Real,<:SparseMatrixCSC}}, B::Vector) = A.parent \ B \(A::Transpose{<:Complex,<:Hermitian{<:Complex,<:SparseMatrixCSC}}, B::Vector) = copy(A) \ B diff --git a/stdlib/SparseArrays/test/sparse.jl b/stdlib/SparseArrays/test/sparse.jl index ac91d66614fa5..f88c6dde06493 100644 --- a/stdlib/SparseArrays/test/sparse.jl +++ b/stdlib/SparseArrays/test/sparse.jl @@ -2289,29 +2289,4 @@ end @test adjoint(MC) == copy(adjoint(SC)) end -@testset "Triangular matrices" begin - rng = Random.MersenneTwister(0) - n = 1000 - A = sprand(rng, n, n, 0.01) - B = ones(n) - MA = Matrix(A) - for tr in (identity, adjoint, transpose) - for wr in (UpperTriangular, LowerTriangular, UnitUpperTriangular, UnitLowerTriangular) - AW = tr(wr(A)) - MAW = tr(wr(MA)) - @test AW * B ≈ MAW * B - end - end - A = A - Diagonal(diag(A)) - A += 2I - MA = Matrix(A) - for tr in (identity, adjoint, transpose) - for wr in (UpperTriangular, LowerTriangular, UnitUpperTriangular, UnitLowerTriangular) - AW = tr(wr(A)) - MAW = tr(wr(MA)) - @test AW \ B ≈ MAW \ B - end - end -end - end # module From 99c40e06b726e0ecc6a6a98df708da689451ad9f Mon Sep 17 00:00:00 2001 From: Marco Cognetta Date: Mon, 24 Sep 2018 16:20:08 +0900 Subject: [PATCH 19/26] removing extra whitespace and comments --- stdlib/LinearAlgebra/src/bidiag.jl | 28 -------------------------- stdlib/LinearAlgebra/src/special.jl | 1 - stdlib/LinearAlgebra/src/triangular.jl | 1 - stdlib/SparseArrays/test/sparse.jl | 1 - 4 files changed, 31 deletions(-) diff --git a/stdlib/LinearAlgebra/src/bidiag.jl b/stdlib/LinearAlgebra/src/bidiag.jl index cb93807fefff0..040a1d164792c 100644 --- a/stdlib/LinearAlgebra/src/bidiag.jl +++ b/stdlib/LinearAlgebra/src/bidiag.jl @@ -487,34 +487,6 @@ function A_mul_B_td!(C::AbstractMatrix, A::AbstractMatrix, B::BiTriSym) end const SpecialMatrix = Union{Bidiagonal,SymTridiagonal,Tridiagonal} -# to avoid ambiguity warning, but shouldn't be necessary -#*(A::AbstractTriangular, B::SpecialMatrix) = Array(A) * Array(B) -#*(A::SpecialMatrix, B::SpecialMatrix) = Array(A) * Array(B) - -# moving several to SparseArrays since they call sparse matrix constructors - -# *(A::SymTridiagonal, B::BiTriSym) = A_mul_B_td!(zeros(eltype(A), size(A)...), A, B) - -# *(A::BiTri, B::BiTriSym) = A_mul_B_td!(zeros(size(A)...), A, B) -# *(A::BiTriSym, B::BiTriSym) = A_mul_B_td!(zero(A), A, B) - -# here we are going to specialize when the uplo values match -# *(A::AbstractTriangular, B::BiTriSym) = A_mul_B_td!(zeros(size(A)...), A, B) -# function *(A::AbstractTriangular, B::BiTri) -# if A.uplo == B.uplo -# A_mul_B_td!(zero(A), A, B) -# else -# A_mul_B_td!(zeros(size(A)...), A, B) -# end -# end - -# TS = promote_op(matprod, eltype(A), eltype(B)) -# mul!(similar(B, TS, (size(A,2), size(B,2))), adjoint(A), B) - -# function *(A::AbstractMatrix, B::Diagonal) -# TS = promote_op(matprod, eltype(A), eltype(B)) -# A_mul_B_td!(similar(A, TS), A, B) -# end function *(A::AbstractTriangular, B::Union{SymTridiagonal, Tridiagonal}) TS = promote_op(matprod, eltype(A), eltype(B)) diff --git a/stdlib/LinearAlgebra/src/special.jl b/stdlib/LinearAlgebra/src/special.jl index 7dae2c4893921..610cc14d3201c 100644 --- a/stdlib/LinearAlgebra/src/special.jl +++ b/stdlib/LinearAlgebra/src/special.jl @@ -111,7 +111,6 @@ for op in (:+, :-) end end end - # todo add the others that had regressions end # specialized +/- for structured matrices. If these are removed, it falls diff --git a/stdlib/LinearAlgebra/src/triangular.jl b/stdlib/LinearAlgebra/src/triangular.jl index 97a4bb3ece81e..d3ccf085d7488 100644 --- a/stdlib/LinearAlgebra/src/triangular.jl +++ b/stdlib/LinearAlgebra/src/triangular.jl @@ -1599,7 +1599,6 @@ rdiv!(A::LowerTriangular, transB::Transpose{<:Any,<:Union{UpperTriangular,UnitUp ## Some Triangular-Triangular cases. We might want to write tailored methods ## for these cases, but I'm not sure it is worth it. -# (*)(A::Union{Tridiagonal,SymTridiagonal}, B::AbstractTriangular) = rmul!(Matrix(A), B) for (f, f2!) in ((:*, :lmul!), (:\, :ldiv!)) @eval begin diff --git a/stdlib/SparseArrays/test/sparse.jl b/stdlib/SparseArrays/test/sparse.jl index 23c83aa660fe3..416cbffac27cf 100644 --- a/stdlib/SparseArrays/test/sparse.jl +++ b/stdlib/SparseArrays/test/sparse.jl @@ -2290,7 +2290,6 @@ end @test adjoint(MC) == copy(adjoint(SC)) end - @testset "Issue #28634" begin a = SparseMatrixCSC{Int8, Int16}([1 2; 3 4]) na = SparseMatrixCSC(a) From e1456a6ca41e274b19f207480d4df19a4aef9d79 Mon Sep 17 00:00:00 2001 From: Marco Cognetta Date: Mon, 24 Sep 2018 19:21:55 +0900 Subject: [PATCH 20/26] fixing BiTriSym*BiTriSym sparse eltype --- stdlib/SparseArrays/src/SparseArrays.jl | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/stdlib/SparseArrays/src/SparseArrays.jl b/stdlib/SparseArrays/src/SparseArrays.jl index f202d4e9e9660..81f28b150cd4b 100644 --- a/stdlib/SparseArrays/src/SparseArrays.jl +++ b/stdlib/SparseArrays/src/SparseArrays.jl @@ -51,7 +51,11 @@ similar(D::Diagonal, ::Type{T}, dims::Union{Dims{1},Dims{2}}) where {T} = spzero similar(S::SymTridiagonal, ::Type{T}, dims::Union{Dims{1},Dims{2}}) where {T} = spzeros(T, dims...) similar(M::Tridiagonal, ::Type{T}, dims::Union{Dims{1},Dims{2}}) where {T} = spzeros(T, dims...) +matprod(x, y) = x*y + x*y const BiTriSym = Union{Bidiagonal,SymTridiagonal,Tridiagonal} -*(A::BiTriSym, B::BiTriSym) = mul!(spzeros(eltype(A),size(A)...), A, B) +function *(A::BiTriSym, B::BiTriSym) + TS = promote_op(matprod, eltype(A), eltype(B)) + mul!(similar(A, TS, size(A)...), A, B) +end end From e5abe190efb3cb98e1e47e8c5dfe7fb8f18b84d8 Mon Sep 17 00:00:00 2001 From: mcognetta Date: Mon, 8 Oct 2018 20:26:26 +0900 Subject: [PATCH 21/26] fixing the cases where we have two structured matrices and the resulting diagonals are of different types. This still fails when the representation is a range and we get a step size of 0 --- stdlib/LinearAlgebra/src/bidiag.jl | 6 +- stdlib/LinearAlgebra/src/special.jl | 182 ++++++++++++++++++++++++--- stdlib/LinearAlgebra/test/special.jl | 28 +++++ 3 files changed, 194 insertions(+), 22 deletions(-) diff --git a/stdlib/LinearAlgebra/src/bidiag.jl b/stdlib/LinearAlgebra/src/bidiag.jl index 040a1d164792c..79b4244bbd9e6 100644 --- a/stdlib/LinearAlgebra/src/bidiag.jl +++ b/stdlib/LinearAlgebra/src/bidiag.jl @@ -304,7 +304,8 @@ function +(A::Bidiagonal, B::Bidiagonal) if A.uplo == B.uplo Bidiagonal(A.dv+B.dv, A.ev+B.ev, A.uplo) else - Tridiagonal((A.uplo == 'U' ? (B.ev,A.dv+B.dv,A.ev) : (A.ev,A.dv+B.dv,B.ev))...) + newdv = A.dv+B.dv + Tridiagonal((A.uplo == 'U' ? (typeof(newdv)(B.ev), newdv, typeof(newdv)(A.ev)) : (typeof(newdv)(A.ev), newdv, typeof(newdv)(B.ev)))...) end end @@ -312,7 +313,8 @@ function -(A::Bidiagonal, B::Bidiagonal) if A.uplo == B.uplo Bidiagonal(A.dv-B.dv, A.ev-B.ev, A.uplo) else - Tridiagonal((A.uplo == 'U' ? (-B.ev,A.dv-B.dv,A.ev) : (A.ev,A.dv-B.dv,-B.ev))...) + newdv = A.dv-B.dv + Tridiagonal((A.uplo == 'U' ? (typeof(newdv)(-B.ev), newdv, typeof(newdv)(A.ev)) : (typeof(newdv)(A.ev), newdv, typeof(newdv)(-B.ev)))...) end end diff --git a/stdlib/LinearAlgebra/src/special.jl b/stdlib/LinearAlgebra/src/special.jl index 610cc14d3201c..93c2fea3b968d 100644 --- a/stdlib/LinearAlgebra/src/special.jl +++ b/stdlib/LinearAlgebra/src/special.jl @@ -117,35 +117,177 @@ end # back to broadcasting which has ~2-10x speed regressions. # For the other structure matrix pairs, broadcasting works well. -+(A::Bidiagonal, B::Diagonal) = Bidiagonal(A.dv+B.diag, A.ev, A.uplo) --(A::Bidiagonal, B::Diagonal) = Bidiagonal(A.dv-B.diag, A.ev, A.uplo) -+(A::Diagonal, B::Bidiagonal) = Bidiagonal(A.diag+B.dv, B.ev, B.uplo) --(A::Diagonal, B::Bidiagonal) = Bidiagonal(A.diag-B.dv, -B.ev, B.uplo) +# For structured matrix types with different non-zero diagonals the underlying +# representations must be promoted to the same type. +# For example, in Diagonal + Bidiagonal only the main diagonal is touched so +# the off diagonal could be a different type after the operation resulting in +# an error. See issue #28994 -+(A::Diagonal, B::SymTridiagonal) = SymTridiagonal(A.diag+B.dv, B.ev) --(A::Diagonal, B::SymTridiagonal) = SymTridiagonal(A.diag-B.dv, -B.ev) -+(A::SymTridiagonal, B::Diagonal) = SymTridiagonal(A.dv+B.diag, A.ev) --(A::SymTridiagonal, B::Diagonal) = SymTridiagonal(A.dv-B.diag, A.ev) +function (+)(A::Bidiagonal, B::Diagonal) + newdv = A.dv + B.diag + Bidiagonal(newdv, typeof(newdv)(A.ev), A.uplo) +end + +function (-)(A::Bidiagonal, B::Diagonal) + newdv = A.dv - B.diag + Bidiagonal(newdv, typeof(newdv)(A.ev), A.uplo) +end + +function (+)(A::Diagonal, B::Bidiagonal) + newdv = A.diag + B.dv + Bidiagonal(newdv, typeof(newdv)(B.ev), B.uplo) +end + +function (-)(A::Diagonal, B::Bidiagonal) + newdv = A.diag-B.dv + Bidiagonal(newdv, typeof(newdv)(-B.ev), B.uplo) +end + +function (+)(A::Diagonal, B::SymTridiagonal) + newdv = A.diag+B.dv + SymTridiagonal(A.diag+B.dv, typeof(newdv)(B.ev)) +end + +function (-)(A::Diagonal, B::SymTridiagonal) + newdv = A.diag-B.dv + SymTridiagonal(newdv, typeof(newdv)(-B.ev)) +end + +function (+)(A::SymTridiagonal, B::Diagonal) + newdv = A.dv+B.diag + SymTridiagonal(newdv, typeof(newdv)(A.ev)) +end + +function (-)(A::SymTridiagonal, B::Diagonal) + newdv = A.dv-B.diag + SymTridiagonal(newdv, typeof(newdv)(A.ev)) +end + +# this set doesn't have the aforementioned problem +(A::Tridiagonal, B::SymTridiagonal) = Tridiagonal(A.dl+B.ev, A.d+B.dv, A.du+B.ev) -(A::Tridiagonal, B::SymTridiagonal) = Tridiagonal(A.dl-B.ev, A.d-B.dv, A.du-B.ev) +(A::SymTridiagonal, B::Tridiagonal) = Tridiagonal(A.ev+B.dl, A.dv+B.d, A.ev+B.du) -(A::SymTridiagonal, B::Tridiagonal) = Tridiagonal(A.ev-B.dl, A.dv-B.d, A.ev-B.du) -+(A::Diagonal, B::Tridiagonal) = Tridiagonal(B.dl, A.diag+B.d, B.du) --(A::Diagonal, B::Tridiagonal) = Tridiagonal(-B.dl, A.diag-B.d, -B.du) -+(A::Tridiagonal, B::Diagonal) = Tridiagonal(A.dl, A.d+B.diag, A.du) --(A::Tridiagonal, B::Diagonal) = Tridiagonal(A.dl, A.d-B.diag, A.du) -+(A::Bidiagonal, B::Tridiagonal) = Tridiagonal((A.uplo == 'U' ? (B.dl, A.dv+B.d, A.ev+B.du) : (A.ev+B.dl, A.dv+B.d, B.du))...) --(A::Bidiagonal, B::Tridiagonal) = Tridiagonal((A.uplo == 'U' ? (-B.dl, A.dv-B.d, A.ev-B.du) : (A.ev-B.dl, A.dv-B.d, -B.du))...) -+(A::Tridiagonal, B::Bidiagonal) = Tridiagonal((B.uplo == 'U' ? (A.dl, A.d+B.dv, A.du+B.ev) : (A.dl+B.ev, A.d+B.dv, A.du))...) --(A::Tridiagonal, B::Bidiagonal) = Tridiagonal((B.uplo == 'U' ? (A.dl, A.d-B.dv, A.du-B.ev) : (A.dl-B.ev, A.d-B.dv, A.du))...) +function (+)(A::Diagonal, B::Tridiagonal) + newdv = A.diag+B.d + Tridiagonal(typeof(newdv)(B.dl), newdv, typeof(newdv)(B.du)) +end + +function (-)(A::Diagonal, B::Tridiagonal) + newdv = A.diag-B.d + Tridiagonal(typeof(newdv)(-B.dl), newdv, typeof(newdv)(-B.du)) +end + +function (+)(A::Tridiagonal, B::Diagonal) + newdv = A.d+B.diag + Tridiagonal(typeof(newdv)(A.dl), newdv, typeof(newdv)(A.du)) +end + +function (-)(A::Tridiagonal, B::Diagonal) + newdv = A.d-B.diag + Tridiagonal(typeof(newdv)(A.dl), newdv, typeof(newdv)(A.du)) +end + +function (+)(A::Bidiagonal, B::Tridiagonal) + newdv = A.dv+B.d + Tridiagonal((A.uplo == 'U' ? (typeof(newdv)(B.dl), newdv, A.ev+B.du) : (A.ev+B.dl, newdv, typeof(newdv)(B.du)))...) +end + +function (-)(A::Bidiagonal, B::Tridiagonal) + newdv = A.dv-B.d + Tridiagonal((A.uplo == 'U' ? (typeof(newdv)(-B.dl), newdv, A.ev-B.du) : (A.ev-B.dl, newdv, typeof(newdv)(-B.du)))...) +end + +function (+)(A::Tridiagonal, B::Bidiagonal) + newdv = A.d+B.dv + Tridiagonal((B.uplo == 'U' ? (typeof(newdv)(A.dl), newdv, A.du+B.ev) : (A.dl+B.ev, newdv, typeof(newdv)(A.du)))...) +end + +function (-)(A::Tridiagonal, B::Bidiagonal) + newdv = A.d-B.dv + Tridiagonal((B.uplo == 'U' ? (typeof(newdv)(A.dl), newdv, A.du-B.ev) : (A.dl-B.ev, newdv, typeof(newdv)(A.du)))...) +end + +function (+)(A::Bidiagonal, B::SymTridiagonal) + newdv = A.dv+B.dv + Tridiagonal((A.uplo == 'U' ? (typeof(newdv)(B.ev), A.dv+B.dv, A.ev+B.ev) : (A.ev+B.ev, A.dv+B.dv, typeof(newdv)(B.ev)))...) +end + +function (-)(A::Bidiagonal, B::SymTridiagonal) + newdv = A.dv-B.dv + Tridiagonal((A.uplo == 'U' ? (typeof(newdv)(-B.ev), newdv, A.ev-B.ev) : (A.ev-B.ev, newdv, typeof(newdv)(-B.ev)))...) +end + +function (+)(A::SymTridiagonal, B::Bidiagonal) + newdv = A.dv+B.dv + Tridiagonal((B.uplo == 'U' ? (typeof(newdv)(A.ev), newdv, A.ev+B.ev) : (A.ev+B.ev, newdv, typeof(newdv)(A.ev)))...) +end + +function (-)(A::SymTridiagonal, B::Bidiagonal) + newdv = A.dv-B.dv + Tridiagonal((B.uplo == 'U' ? (typeof(newdv)(A.ev), newdv, A.ev-B.ev) : (A.ev-B.ev, newdv, typeof(newdv)(A.ev)))...) +end +# fixing uniform scaling problems from #28994 + +function (+)(A::Tridiagonal, B::UniformScaling) + newd = A.d .+ B.λ + Tridiagonal(typeof(newd)(A.dl), newd, typeof(newd)(A.du)) +end + +function (+)(A::SymTridiagonal, B::UniformScaling) + newdv = A.dv .+ B.λ + SymTridiagonal(newdv, typeof(newdv)(A.ev)) +end + +function (+)(A::Bidiagonal, B::UniformScaling) + newdv = A.dv .+ B.λ + Bidiagonal(newdv, typeof(newdv)(A.ev), A.uplo) +end + +function (+)(A::Diagonal, B::UniformScaling) + Diagonal(A.diag .+ B.λ) +end -+(A::Bidiagonal, B::SymTridiagonal) = Tridiagonal((A.uplo == 'U' ? (B.ev, A.dv+B.dv, A.ev+B.ev) : (A.ev+B.ev, A.dv+B.dv, B.ev))...) --(A::Bidiagonal, B::SymTridiagonal) = Tridiagonal((A.uplo == 'U' ? (-B.ev, A.dv-B.dv, A.ev-B.ev) : (A.ev-B.ev, A.dv-B.dv, -B.ev))...) -+(A::SymTridiagonal, B::Bidiagonal) = Tridiagonal((B.uplo == 'U' ? (A.ev, A.dv+B.dv, A.ev+B.ev) : (A.ev+B.ev, A.dv+B.dv, A.ev))...) --(A::SymTridiagonal, B::Bidiagonal) = Tridiagonal((B.uplo == 'U' ? (A.ev, A.dv-B.dv, A.ev-B.ev) : (A.ev-B.ev, A.dv-B.dv, A.ev))...) +function (+)(A::UniformScaling, B::Tridiagonal) + newd = A.λ .+ B.d + Tridiagonal(typeof(newd)(B.dl), newd, typeof(newd)(B.du)) +end + +function (+)(A::UniformScaling, B::SymTridiagonal) + newdv = A.λ .+ B.dv + SymTridiagonal(newdv, typeof(newdv)(B.ev)) +end + +function (+)(A::UniformScaling, B::Bidiagonal) + newdv = A.λ .+ B.dv + Bidiagonal(newdv, typeof(newdv)(B.ev), B.uplo) +end + +function (+)(A::UniformScaling, B::Diagonal) + Diagonal(A.λ .+ B.diag) +end + +function (-)(A::UniformScaling, B::Tridiagonal) + newd = A.λ .- B.d + Tridiagonal(typeof(newd)(-B.dl), newd, typeof(newd)(-B.du)) +end + +function (-)(A::UniformScaling, B::SymTridiagonal) + newdv = A.λ .- B.dv + SymTridiagonal(newdv, typeof(newdv)(-B.ev)) +end + +function (-)(A::UniformScaling, B::Bidiagonal) + newdv = A.λ .- B.dv + Bidiagonal(newdv, typeof(newdv)(-B.ev), B.uplo) +end + +function (-)(A::UniformScaling, B::Diagonal) + Diagonal(A.λ .- B.diag) +end rmul!(A::AbstractTriangular, adjB::Adjoint{<:Any,<:Union{QRCompactWYQ,QRPackedQ}}) = (B = adjB.parent; rmul!(full!(A), adjoint(B))) diff --git a/stdlib/LinearAlgebra/test/special.jl b/stdlib/LinearAlgebra/test/special.jl index 59ddf847e4dbd..0e6efb2d87b79 100644 --- a/stdlib/LinearAlgebra/test/special.jl +++ b/stdlib/LinearAlgebra/test/special.jl @@ -129,6 +129,34 @@ end end end +@testset "+ and - among structured matrices with different container types" begin + diag = 1:5 + offdiag = 1:4 + uniformscalingmats = [UniformScaling(3), UniformScaling(1.0), UniformScaling(3//5), UniformScaling(Complex{Float64}(1.3, 3.5))] + mats = [Diagonal(diag), Bidiagonal(diag, offdiag, 'U'), Bidiagonal(diag, offdiag, 'L'), Tridiagonal(offdiag, diag, offdiag), SymTridiagonal(diag, offdiag)] + for T in [ComplexF64, Int64, Rational{Int64}, Float64] + push!(mats, Diagonal(Vector{T}(diag))) + push!(mats, Bidiagonal(Vector{T}(diag), Vector{T}(offdiag), 'U')) + push!(mats, Bidiagonal(Vector{T}(diag), Vector{T}(offdiag), 'L')) + push!(mats, Tridiagonal(Vector{T}(offdiag), Vector{T}(diag), Vector{T}(offdiag))) + push!(mats, SymTridiagonal(Vector{T}(diag), Vector{T}(offdiag))) + end + + for op in (+,*) # to do: fix when operation is - and the matrix has a range as the underlying representation and we get a step size of 0. + for A in mats + for B in mats + @test (op)(A, B) ≈ (op)(Matrix(A), Matrix(B)) ≈ Matrix((op)(A, B)) + end + end + + for A in mats + for B in uniformscalingmats + @test (op)(A, B) ≈ (op)(Matrix(A), B) ≈ Matrix((op)(A, B)) + end + end + end +end + @testset "Triangular Types and QR" begin for typ in [UpperTriangular,LowerTriangular,LinearAlgebra.UnitUpperTriangular,LinearAlgebra.UnitLowerTriangular] a = rand(n,n) From 4a8d9b4a30131a85ddada3d307e3b1716df2cdcf Mon Sep 17 00:00:00 2001 From: mcognetta Date: Mon, 8 Oct 2018 22:57:49 +0900 Subject: [PATCH 22/26] Fixes the issue where we try to add structured matrices and one has an eltype <: AbstractArray See PR 27289 --- stdlib/LinearAlgebra/src/special.jl | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/stdlib/LinearAlgebra/src/special.jl b/stdlib/LinearAlgebra/src/special.jl index 93c2fea3b968d..a211c605a99c4 100644 --- a/stdlib/LinearAlgebra/src/special.jl +++ b/stdlib/LinearAlgebra/src/special.jl @@ -230,62 +230,64 @@ function (-)(A::SymTridiagonal, B::Bidiagonal) newdv = A.dv-B.dv Tridiagonal((B.uplo == 'U' ? (typeof(newdv)(A.ev), newdv, A.ev-B.ev) : (A.ev-B.ev, newdv, typeof(newdv)(A.ev)))...) end + # fixing uniform scaling problems from #28994 +# {<:Number} is required due to the test case from PR #27289 where eltype is a matrix. -function (+)(A::Tridiagonal, B::UniformScaling) +function (+)(A::Tridiagonal{<:Number}, B::UniformScaling) newd = A.d .+ B.λ Tridiagonal(typeof(newd)(A.dl), newd, typeof(newd)(A.du)) end -function (+)(A::SymTridiagonal, B::UniformScaling) +function (+)(A::SymTridiagonal{<:Number}, B::UniformScaling) newdv = A.dv .+ B.λ SymTridiagonal(newdv, typeof(newdv)(A.ev)) end -function (+)(A::Bidiagonal, B::UniformScaling) +function (+)(A::Bidiagonal{<:Number}, B::UniformScaling) newdv = A.dv .+ B.λ Bidiagonal(newdv, typeof(newdv)(A.ev), A.uplo) end -function (+)(A::Diagonal, B::UniformScaling) +function (+)(A::Diagonal{<:Number}, B::UniformScaling) Diagonal(A.diag .+ B.λ) end -function (+)(A::UniformScaling, B::Tridiagonal) +function (+)(A::UniformScaling, B::Tridiagonal{<:Number}) newd = A.λ .+ B.d Tridiagonal(typeof(newd)(B.dl), newd, typeof(newd)(B.du)) end -function (+)(A::UniformScaling, B::SymTridiagonal) +function (+)(A::UniformScaling, B::SymTridiagonal{<:Number}) newdv = A.λ .+ B.dv SymTridiagonal(newdv, typeof(newdv)(B.ev)) end -function (+)(A::UniformScaling, B::Bidiagonal) +function (+)(A::UniformScaling, B::Bidiagonal{<:Number}) newdv = A.λ .+ B.dv Bidiagonal(newdv, typeof(newdv)(B.ev), B.uplo) end -function (+)(A::UniformScaling, B::Diagonal) +function (+)(A::UniformScaling, B::Diagonal{<:Number}) Diagonal(A.λ .+ B.diag) end -function (-)(A::UniformScaling, B::Tridiagonal) +function (-)(A::UniformScaling, B::Tridiagonal{<:Number}) newd = A.λ .- B.d Tridiagonal(typeof(newd)(-B.dl), newd, typeof(newd)(-B.du)) end -function (-)(A::UniformScaling, B::SymTridiagonal) +function (-)(A::UniformScaling, B::SymTridiagonal{<:Number}) newdv = A.λ .- B.dv SymTridiagonal(newdv, typeof(newdv)(-B.ev)) end -function (-)(A::UniformScaling, B::Bidiagonal) +function (-)(A::UniformScaling, B::Bidiagonal{<:Number}) newdv = A.λ .- B.dv Bidiagonal(newdv, typeof(newdv)(-B.ev), B.uplo) end -function (-)(A::UniformScaling, B::Diagonal) +function (-)(A::UniformScaling, B::Diagonal{<:Number}) Diagonal(A.λ .- B.diag) end From 37c864b1592be9dbde1741a7cab91161a6109805 Mon Sep 17 00:00:00 2001 From: mcognetta Date: Tue, 9 Oct 2018 01:47:14 +0900 Subject: [PATCH 23/26] remove adjoint and transpose methods that I never changed --- stdlib/LinearAlgebra/src/bidiag.jl | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/stdlib/LinearAlgebra/src/bidiag.jl b/stdlib/LinearAlgebra/src/bidiag.jl index 79b4244bbd9e6..2161f02b59585 100644 --- a/stdlib/LinearAlgebra/src/bidiag.jl +++ b/stdlib/LinearAlgebra/src/bidiag.jl @@ -551,28 +551,6 @@ function *(A::SymTridiagonal, B::Diagonal) A_mul_B_td!(Tridiagonal(zeros(TS, size(A)...)), A, B) end -# todo update the specialized output types here. -# right now I am just fixing it so the eltype is correct -function *(A::Adjoint{<:Any,<:Diagonal}, B::BiTriSym) - TS = promote_op(matprod, eltype(A), eltype(B)) - A_mul_B_td!(zeros(TS, size(A)...), A, B) -end - -function *(A::Transpose{<:Any,<:Diagonal}, B::BiTriSym) - TS = promote_op(matprod, eltype(A), eltype(B)) - A_mul_B_td!(zeros(TS, size(A)...), A, B) -end - -function *(A::Adjoint{<:Any,<:AbstractTriangular}, B::BiTriSym) - TS = promote_op(matprod, eltype(A), eltype(B)) - A_mul_B_td!(zeros(TS, size(A)...), A, B) -end - -function *(A::Transpose{<:Any,<:AbstractTriangular}, B::BiTriSym) - TS = promote_op(matprod, eltype(A), eltype(B)) - A_mul_B_td!(zeros(TS, size(A)...), A, B) -end - #Generic multiplication *(A::Bidiagonal{T}, B::AbstractVector{T}) where {T} = *(Array(A), B) *(adjA::Adjoint{<:Any,<:Bidiagonal{T}}, B::AbstractVector{T}) where {T} = *(adjoint(Array(adjA.parent)), B) From ba1f6c08e35106859f3678d76b334093a929807e Mon Sep 17 00:00:00 2001 From: Marco Cognetta Date: Wed, 17 Oct 2018 19:36:32 +0900 Subject: [PATCH 24/26] fixing tridiagonal constructor to save time/memory --- stdlib/LinearAlgebra/src/bidiag.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stdlib/LinearAlgebra/src/bidiag.jl b/stdlib/LinearAlgebra/src/bidiag.jl index 9f3c95f523c37..59f839451080f 100644 --- a/stdlib/LinearAlgebra/src/bidiag.jl +++ b/stdlib/LinearAlgebra/src/bidiag.jl @@ -545,12 +545,12 @@ end function *(A::Diagonal, B::SymTridiagonal) TS = promote_op(matprod, eltype(A), eltype(B)) - A_mul_B_td!(Tridiagonal(zeros(TS, size(A)...)), A, B) + A_mul_B_td!(Tridiagonal(zeros(TS, size(A, 1)-1), zeros(TS, size(A, 1)), zeros(TS, size(A, 1)-1)), A, B) end function *(A::SymTridiagonal, B::Diagonal) TS = promote_op(matprod, eltype(A), eltype(B)) - A_mul_B_td!(Tridiagonal(zeros(TS, size(A)...)), A, B) + A_mul_B_td!(Tridiagonal(zeros(TS, size(A, 1)-1), zeros(TS, size(A, 1)), zeros(TS, size(A, 1)-1)), A, B) end #Generic multiplication From bbb588229f9e5653ed79ffdadbc01b4e315b0fac Mon Sep 17 00:00:00 2001 From: Marco Cognetta Date: Fri, 19 Oct 2018 15:17:53 +0900 Subject: [PATCH 25/26] fixing bidiag * diag return type --- stdlib/LinearAlgebra/src/bidiag.jl | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/stdlib/LinearAlgebra/src/bidiag.jl b/stdlib/LinearAlgebra/src/bidiag.jl index 59f839451080f..893699f5fa788 100644 --- a/stdlib/LinearAlgebra/src/bidiag.jl +++ b/stdlib/LinearAlgebra/src/bidiag.jl @@ -538,6 +538,11 @@ function *(A::Bidiagonal, B::LowerTriangular) end end +function *(A::Bidiagonal, B::Diagonal) + TS = promote_op(matprod, eltype(A), eltype(B)) + A_mul_B_td!(similar(A, TS), A, B) +end + function *(A::Diagonal, B::BiTri) TS = promote_op(matprod, eltype(A), eltype(B)) A_mul_B_td!(similar(B, TS), A, B) From aa388ceea366c95c332f986bc767ecff63c7af8e Mon Sep 17 00:00:00 2001 From: Marco Cognetta Date: Fri, 19 Oct 2018 15:38:00 +0900 Subject: [PATCH 26/26] adding multiplication to binops tests --- stdlib/LinearAlgebra/test/special.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/LinearAlgebra/test/special.jl b/stdlib/LinearAlgebra/test/special.jl index 0e6efb2d87b79..90cfe24da894a 100644 --- a/stdlib/LinearAlgebra/test/special.jl +++ b/stdlib/LinearAlgebra/test/special.jl @@ -120,7 +120,7 @@ end Dense = rand(20, 20) mats = [UpTri, LoTri, Diag, Tridiag, UpBi, LoBi, Sym, Dense] - for op in (+,-) + for op in (+,-,*) for A in mats for B in mats @test (op)(A, B) ≈ (op)(Matrix(A), Matrix(B)) ≈ Matrix((op)(A, B))