Skip to content

Commit 0ae90bc

Browse files
Merge branch 'backports-release-1.11' into ib/regex_finalizer
2 parents e6d2725 + ec3c02a commit 0ae90bc

22 files changed

+316
-92
lines changed

THIRDPARTY.md

-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ for exceptions.
66
- [crc32c.c](https://stackoverflow.com/questions/17645167/implementing-sse-4-2s-crc32c-in-software) (CRC-32c checksum code by Mark Adler) [[ZLib](https://opensource.org/licenses/Zlib)].
77
- [LDC](https://github.com/ldc-developers/ldc/blob/master/LICENSE) (for ccall/cfunction ABI definitions) [BSD-3]. The portion of code that Julia uses from LDC is [BSD-3] licensed.
88
- [LLVM](https://releases.llvm.org/3.9.0/LICENSE.TXT) (for parts of src/disasm.cpp) [UIUC]
9-
- [MINGW](https://sourceforge.net/p/mingw/mingw-org-wsl/ci/legacy/tree/mingwrt/mingwex/dirname.c) (for dirname implementation on Windows) [MIT]
109
- [NetBSD](https://www.netbsd.org/about/redistribution.html) (for setjmp, longjmp, and strptime implementations on Windows) [BSD-3]
1110
- [Python](https://docs.python.org/3/license.html) (for strtod implementation on Windows) [PSF]
1211
- [FEMTOLISP](https://github.com/JeffBezanson/femtolisp) [BSD-3]

base/abstractarray.jl

+25-1
Original file line numberDiff line numberDiff line change
@@ -3654,7 +3654,31 @@ function _keepat!(a::AbstractVector, m::AbstractVector{Bool})
36543654
deleteat!(a, j:lastindex(a))
36553655
end
36563656

3657-
## 1-d circshift ##
3657+
"""
3658+
circshift!(a::AbstractVector, shift::Integer)
3659+
3660+
Circularly shift, or rotate, the data in vector `a` by `shift` positions.
3661+
3662+
# Examples
3663+
3664+
```jldoctest
3665+
julia> circshift!([1, 2, 3, 4, 5], 2)
3666+
5-element Vector{Int64}:
3667+
4
3668+
5
3669+
1
3670+
2
3671+
3
3672+
3673+
julia> circshift!([1, 2, 3, 4, 5], -2)
3674+
5-element Vector{Int64}:
3675+
3
3676+
4
3677+
5
3678+
1
3679+
2
3680+
```
3681+
"""
36583682
function circshift!(a::AbstractVector, shift::Integer)
36593683
n = length(a)
36603684
n == 0 && return a

base/math.jl

+41-11
Original file line numberDiff line numberDiff line change
@@ -1140,6 +1140,10 @@ function modf(x::T) where T<:IEEEFloat
11401140
return (rx, ix)
11411141
end
11421142

1143+
@inline function use_power_by_squaring(n::Integer)
1144+
-2^12 <= n <= 3 * 2^13
1145+
end
1146+
11431147
# @constprop aggressive to help the compiler see the switch between the integer and float
11441148
# variants for callers with constant `y`
11451149
@constprop :aggressive function ^(x::Float64, y::Float64)
@@ -1152,24 +1156,33 @@ end
11521156
y = sign(y)*0x1.8p62
11531157
end
11541158
yint = unsafe_trunc(Int64, y) # This is actually safe since julia freezes the result
1155-
y == yint && return @noinline x^yint
1156-
2*xu==0 && return abs(y)*Inf*(!(y>0)) # if x==0
1157-
x<0 && throw_exp_domainerror(x) # |y| is small enough that y isn't an integer
1158-
!isfinite(x) && return x*(y>0 || isnan(x)) # x is inf or NaN
1159+
yisint = y == yint
1160+
if yisint
1161+
yint == 0 && return 1.0
1162+
use_power_by_squaring(yint) && return @noinline pow_body(x, yint)
1163+
end
1164+
2*xu==0 && return abs(y)*Inf*(!(y>0)) # if x === +0.0 or -0.0 (Inf * false === 0.0)
1165+
s = 1
1166+
if x < 0
1167+
!yisint && throw_exp_domainerror(x) # y isn't an integer
1168+
s = ifelse(isodd(yint), -1, 1)
1169+
end
1170+
!isfinite(x) && return copysign(x,s)*(y>0 || isnan(x)) # x is inf or NaN
1171+
return copysign(pow_body(abs(x), y), s)
1172+
end
1173+
1174+
@assume_effects :foldable @noinline function pow_body(x::Float64, y::Float64)
1175+
xu = reinterpret(UInt64, x)
11591176
if xu < (UInt64(1)<<52) # x is subnormal
11601177
xu = reinterpret(UInt64, x * 0x1p52) # normalize x
11611178
xu &= ~sign_mask(Float64)
11621179
xu -= UInt64(52) << 52 # mess with the exponent
11631180
end
1164-
return pow_body(xu, y)
1165-
end
1166-
1167-
@inline function pow_body(xu::UInt64, y::Float64)
11681181
logxhi,logxlo = _log_ext(xu)
11691182
xyhi, xylo = two_mul(logxhi,y)
11701183
xylo = muladd(logxlo, y, xylo)
11711184
hi = xyhi+xylo
1172-
return Base.Math.exp_impl(hi, xylo-(hi-xyhi), Val(:ℯ))
1185+
return @inline Base.Math.exp_impl(hi, xylo-(hi-xyhi), Val(:ℯ))
11731186
end
11741187

11751188
@constprop :aggressive function ^(x::T, y::T) where T <: Union{Float16, Float32}
@@ -1193,12 +1206,29 @@ end
11931206
return T(exp2(log2(abs(widen(x))) * y))
11941207
end
11951208

1196-
# compensated power by squaring
11971209
@constprop :aggressive @inline function ^(x::Float64, n::Integer)
1210+
x^clamp(n, Int64)
1211+
end
1212+
@constprop :aggressive @inline function ^(x::Float64, n::Int64)
11981213
n == 0 && return one(x)
1199-
return pow_body(x, n)
1214+
if use_power_by_squaring(n)
1215+
return pow_body(x, n)
1216+
else
1217+
s = ifelse(x < 0 && isodd(n), -1.0, 1.0)
1218+
x = abs(x)
1219+
y = float(n)
1220+
if y == n
1221+
return copysign(pow_body(x, y), s)
1222+
else
1223+
n2 = n % 1024
1224+
y = float(n - n2)
1225+
return pow_body(x, y) * copysign(pow_body(x, n2), s)
1226+
end
1227+
end
12001228
end
12011229

1230+
# compensated power by squaring
1231+
# this method is only reliable for -2^20 < n < 2^20 (cf. #53881 #53886)
12021232
@assume_effects :terminates_locally @noinline function pow_body(x::Float64, n::Integer)
12031233
y = 1.0
12041234
xnlo = ynlo = 0.0

base/precompilation.jl

+3-2
Original file line numberDiff line numberDiff line change
@@ -141,15 +141,16 @@ function ExplicitEnv(envpath::String=Base.active_project())
141141

142142
# Extensions
143143
deps_pkg = get(Dict{String, Any}, pkg_info, "extensions")::Dict{String, Any}
144+
deps_pkg_concrete = Dict{String, Vector{String}}()
144145
for (ext, triggers) in deps_pkg
145146
if triggers isa String
146147
triggers = [triggers]
147148
else
148149
triggers = triggers::Vector{String}
149150
end
150-
deps_pkg[ext] = triggers
151+
deps_pkg_concrete[ext] = triggers
151152
end
152-
extensions[m_uuid] = deps_pkg
153+
extensions[m_uuid] = deps_pkg_concrete
153154

154155
# Determine strategy to find package
155156
lookup_strat = begin

base/special/exp.jl

+1-1
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,7 @@ end
252252
twopk = (k + UInt64(53)) << 52
253253
return reinterpret(T, twopk + reinterpret(UInt64, small_part))*0x1p-53
254254
end
255-
#k == 1024 && return (small_part * 2.0) * 2.0^1023
255+
k == 1024 && return (small_part * 2.0) * 2.0^1023
256256
end
257257
twopk = Int64(k) << 52
258258
return reinterpret(T, twopk + reinterpret(Int64, small_part))

base/strings/basic.jl

+6-6
Original file line numberDiff line numberDiff line change
@@ -512,11 +512,11 @@ prevind(s::AbstractString, i::Int) = prevind(s, i, 1)
512512

513513
function prevind(s::AbstractString, i::Int, n::Int)
514514
n < 0 && throw(ArgumentError("n cannot be negative: $n"))
515-
z = ncodeunits(s) + 1
515+
z = ncodeunits(s)::Int + 1
516516
@boundscheck 0 < i z || throw(BoundsError(s, i))
517-
n == 0 && return thisind(s, i) == i ? i : string_index_err(s, i)
517+
n == 0 && return thisind(s, i)::Int == i ? i : string_index_err(s, i)
518518
while n > 0 && 1 < i
519-
@inbounds n -= isvalid(s, i -= 1)
519+
@inbounds n -= isvalid(s, i -= 1)::Bool
520520
end
521521
return i - n
522522
end
@@ -571,11 +571,11 @@ nextind(s::AbstractString, i::Int) = nextind(s, i, 1)
571571

572572
function nextind(s::AbstractString, i::Int, n::Int)
573573
n < 0 && throw(ArgumentError("n cannot be negative: $n"))
574-
z = ncodeunits(s)
574+
z = ncodeunits(s)::Int
575575
@boundscheck 0 i z || throw(BoundsError(s, i))
576-
n == 0 && return thisind(s, i) == i ? i : string_index_err(s, i)
576+
n == 0 && return thisind(s, i)::Int == i ? i : string_index_err(s, i)
577577
while n > 0 && i < z
578-
@inbounds n -= isvalid(s, i += 1)
578+
@inbounds n -= isvalid(s, i += 1)::Bool
579579
end
580580
return i + n
581581
end

base/summarysize.jl

+1-6
Original file line numberDiff line numberDiff line change
@@ -149,13 +149,8 @@ function (ss::SummarySize)(obj::GenericMemory)
149149
datakey = unsafe_convert(Ptr{Cvoid}, obj)
150150
if !haskey(ss.seen, datakey)
151151
ss.seen[datakey] = true
152-
dsize = sizeof(obj)
152+
size += sizeof(obj)
153153
T = eltype(obj)
154-
if isbitsunion(T)
155-
# add 1 union selector byte for each element
156-
dsize += length(obj)
157-
end
158-
size += dsize
159154
if !isempty(obj) && T !== Symbol && (!Base.allocatedinline(T) || (T isa DataType && !Base.datatype_pointerfree(T)))
160155
push!(ss.frontier_x, obj)
161156
push!(ss.frontier_i, 1)

doc/src/manual/calling-c-and-fortran-code.md

+15-9
Original file line numberDiff line numberDiff line change
@@ -547,15 +547,14 @@ is not valid, since the type layout of `T` is not known statically.
547547

548548
### SIMD Values
549549

550-
Note: This feature is currently implemented on 64-bit x86 and AArch64 platforms only.
551-
552550
If a C/C++ routine has an argument or return value that is a native SIMD type, the corresponding
553551
Julia type is a homogeneous tuple of `VecElement` that naturally maps to the SIMD type. Specifically:
554552

555-
> * The tuple must be the same size as the SIMD type. For example, a tuple representing an `__m128`
556-
> on x86 must have a size of 16 bytes.
557-
> * The element type of the tuple must be an instance of `VecElement{T}` where `T` is a primitive type that
558-
> is 1, 2, 4 or 8 bytes.
553+
> * The tuple must be the same size and elements as the SIMD type. For example, a tuple
554+
> representing an `__m128` on x86 must have a size of 16 bytes and Float32 elements.
555+
> * The element type of the tuple must be an instance of `VecElement{T}` where `T` is a
556+
> primitive type with a power-of-two number of bytes (e.g. 1, 2, 4, 8, 16, etc) such as
557+
> Int8 or Float64.
559558
560559
For instance, consider this C routine that uses AVX intrinsics:
561560

@@ -628,6 +627,10 @@ For translating a C argument list to Julia:
628627

629628
* `T`, where `T` is a Julia leaf type
630629
* argument value will be copied (passed by value)
630+
* `vector T` (or `__attribute__ vector_size`, or a typedef such as `__m128`)
631+
632+
* `NTuple{N, VecElement{T}}`, where `T` is a primitive Julia type of the correct size
633+
and N is the number of elements in the vector (equal to `vector_size / sizeof T`).
631634
* `void*`
632635

633636
* depends on how this parameter is used, first translate this to the intended pointer type, then
@@ -674,13 +677,16 @@ For translating a C return type to Julia:
674677
* `T`, where `T` is one of the primitive types: `char`, `int`, `long`, `short`, `float`, `double`,
675678
`complex`, `enum` or any of their `typedef` equivalents
676679

677-
* `T`, where `T` is an equivalent Julia Bits Type (per the table above)
678-
* if `T` is an `enum`, the argument type should be equivalent to `Cint` or `Cuint`
680+
* same as C argument list
679681
* argument value will be copied (returned by-value)
680682
* `struct T` (including typedef to a struct)
681683

682-
* `T`, where `T` is a Julia Leaf Type
684+
* same as C argument list
683685
* argument value will be copied (returned by-value)
686+
687+
* `vector T`
688+
689+
* same as C argument list
684690
* `void*`
685691

686692
* depends on how this parameter is used, first translate this to the intended pointer type, then

src/cgutils.cpp

+4-3
Original file line numberDiff line numberDiff line change
@@ -1971,7 +1971,7 @@ static jl_cgval_t typed_load(jl_codectx_t &ctx, Value *ptr, Value *idx_0based, j
19711971
else if (!alignment)
19721972
alignment = julia_alignment(jltype);
19731973
if (intcast && Order == AtomicOrdering::NotAtomic) {
1974-
emit_memcpy(ctx, intcast, jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_stack), data, jl_aliasinfo_t::fromTBAA(ctx, tbaa), nb, Align(alignment), intcast->getAlign());
1974+
emit_memcpy(ctx, intcast, jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_stack), data, jl_aliasinfo_t::fromTBAA(ctx, tbaa), nb, intcast->getAlign(), Align(alignment));
19751975
}
19761976
else {
19771977
if (!isboxed && jl_is_genericmemoryref_type(jltype)) {
@@ -3214,7 +3214,7 @@ static void union_alloca_type(jl_uniontype_t *ut,
32143214
[&](unsigned idx, jl_datatype_t *jt) {
32153215
if (!jl_is_datatype_singleton(jt)) {
32163216
size_t nb1 = jl_datatype_size(jt);
3217-
size_t align1 = jl_datatype_align(jt);
3217+
size_t align1 = julia_alignment((jl_value_t*)jt);
32183218
if (nb1 > nbytes)
32193219
nbytes = nb1;
32203220
if (align1 > align)
@@ -3796,9 +3796,10 @@ static jl_cgval_t emit_new_struct(jl_codectx_t &ctx, jl_value_t *ty, size_t narg
37963796

37973797
// whether we should perform the initialization with the struct as a IR value
37983798
// or instead initialize the stack buffer with stores
3799+
// although we do the former if it is a vector or could be a vector element
37993800
auto tracked = CountTrackedPointers(lt);
38003801
bool init_as_value = false;
3801-
if (lt->isVectorTy() || jl_is_vecelement_type(ty)) { // maybe also check the size ?
3802+
if (lt->isVectorTy() || jl_special_vector_alignment(1, ty) != 0) {
38023803
init_as_value = true;
38033804
}
38043805
else if (tracked.count) {

src/codegen.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -8552,6 +8552,8 @@ static jl_llvm_functions_t
85528552
Type *RT = Arg->getParamStructRetType();
85538553
TypeSize sz = DL.getTypeAllocSize(RT);
85548554
Align al = DL.getPrefTypeAlign(RT);
8555+
if (al > MAX_ALIGN)
8556+
al = Align(MAX_ALIGN);
85558557
param.addAttribute(Attribute::NonNull);
85568558
// The `dereferenceable` below does not imply `nonnull` for non addrspace(0) pointers.
85578559
param.addDereferenceableAttr(sz);

src/datatype.c

+22-5
Original file line numberDiff line numberDiff line change
@@ -298,9 +298,10 @@ static jl_datatype_layout_t *jl_get_layout(uint32_t sz,
298298
}
299299

300300
// Determine if homogeneous tuple with fields of type t will have
301-
// a special alignment beyond normal Julia rules.
301+
// a special alignment and vector-ABI beyond normal rules for aggregates.
302302
// Return special alignment if one exists, 0 if normal alignment rules hold.
303303
// A non-zero result *must* match the LLVM rules for a vector type <nfields x t>.
304+
// Matching the compiler's `__attribute__ vector_size` behavior.
304305
// For sake of Ahead-Of-Time (AOT) compilation, this routine has to work
305306
// without LLVM being available.
306307
unsigned jl_special_vector_alignment(size_t nfields, jl_value_t *t)
@@ -315,8 +316,12 @@ unsigned jl_special_vector_alignment(size_t nfields, jl_value_t *t)
315316
// motivating use case comes up for Julia, we reject pointers.
316317
return 0;
317318
size_t elsz = jl_datatype_size(ty);
318-
if (elsz != 1 && elsz != 2 && elsz != 4 && elsz != 8)
319-
// Only handle power-of-two-sized elements (for now)
319+
if (next_power_of_two(elsz) != elsz)
320+
// Only handle power-of-two-sized elements (for now), since other
321+
// lengths may be packed into very complicated arrangements (llvm pads
322+
// extra bits on most platforms when computing alignment but not when
323+
// computing type size, but adds no extra bytes for each element, so
324+
// their effect on offsets are never what you may naturally expect).
320325
return 0;
321326
size_t size = nfields * elsz;
322327
// Use natural alignment for this vector: this matches LLVM and clang.
@@ -707,9 +712,9 @@ void jl_compute_field_offsets(jl_datatype_t *st)
707712
}
708713
else {
709714
fsz = sizeof(void*);
710-
if (fsz > MAX_ALIGN)
711-
fsz = MAX_ALIGN;
712715
al = fsz;
716+
if (al > MAX_ALIGN)
717+
al = MAX_ALIGN;
713718
desc[i].isptr = 1;
714719
zeroinit = 1;
715720
npointers++;
@@ -929,6 +934,18 @@ JL_DLLEXPORT jl_datatype_t *jl_new_primitivetype(jl_value_t *name, jl_module_t *
929934
jl_emptysvec, jl_emptysvec, jl_emptysvec, 0, 0, 0);
930935
uint32_t nbytes = (nbits + 7) / 8;
931936
uint32_t alignm = next_power_of_two(nbytes);
937+
# if defined(_CPU_X86_) && !defined(_OS_WINDOWS_)
938+
// datalayout strings are often weird: on 64-bit they usually follow fairly simple rules,
939+
// but on x86 32 bit platforms, sometimes 5 to 8 byte types are
940+
// 32-bit aligned even though the MAX_ALIGN (for types 9+ bytes) is 16
941+
// (except for f80 which is align 4 on Mingw, Linux, and BSDs--but align 16 on MSVC and Darwin)
942+
// https://llvm.org/doxygen/ARMTargetMachine_8cpp.html#adb29b487708f0dc2a940345b68649270
943+
// https://llvm.org/doxygen/AArch64TargetMachine_8cpp.html#a003a58caf135efbf7273c5ed84e700d7
944+
// https://llvm.org/doxygen/X86TargetMachine_8cpp.html#aefdbcd6131ef195da070cef7fdaf0532
945+
// 32-bit alignment is weird
946+
if (alignm == 8)
947+
alignm = 4;
948+
# endif
932949
if (alignm > MAX_ALIGN)
933950
alignm = MAX_ALIGN;
934951
// memoize isprimitivetype, since it is much easier than checking

src/llvm-late-gc-lowering.cpp

+4-2
Original file line numberDiff line numberDiff line change
@@ -2331,8 +2331,10 @@ bool LateLowerGCFrame::CleanupIR(Function &F, State *S, bool *CFGModified) {
23312331
// strip all constant alias information, as it might depend on the gc having
23322332
// preserved a gc root, which stops being true after this pass (#32215)
23332333
// similar to RewriteStatepointsForGC::stripNonValidData, but less aggressive
2334-
if (I->getMetadata(LLVMContext::MD_invariant_load))
2335-
I->setMetadata(LLVMContext::MD_invariant_load, NULL);
2334+
if (auto *LI = dyn_cast<LoadInst>(I)){
2335+
if (isSpecialPtr(LI->getPointerOperand()->getType()) && LI->getMetadata(LLVMContext::MD_invariant_load))
2336+
LI->setMetadata(LLVMContext::MD_invariant_load, NULL);
2337+
}
23362338
if (MDNode *TBAA = I->getMetadata(LLVMContext::MD_tbaa)) {
23372339
if (TBAA->getNumOperands() == 4 && isTBAA(TBAA, {"jtbaa_const", "jtbaa_memoryptr", "jtbaa_memorylen", "tbaa_memoryown"})) {
23382340
MDNode *MutableTBAA = createMutableTBAAAccessTag(TBAA);

0 commit comments

Comments
 (0)