Skip to content

Commit

Permalink
Inline StepRange construction (#49270)
Browse files Browse the repository at this point in the history
This can improve performance when iterating over a range with a step as currently steprange_last is not inlined. About a 12ns improvement

I don't think this should slow anything down as at worst you're making a call which is what you'd have to do without inlining. Also, it should be unlikely that branch is taken.
This should allow for better automatic inlining.
  • Loading branch information
Zentrik committed May 4, 2023
1 parent 9a6af18 commit 2e80c0d
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 2 deletions.
2 changes: 1 addition & 1 deletion base/multidimensional.jl
Original file line number Diff line number Diff line change
Expand Up @@ -526,7 +526,7 @@ module IteratorsMD
dimrev = ntuple(i -> sum(==(i), dims; init = 0) == 1, Val(length(indices)))
length(dims) == sum(dimrev) || throw(ArgumentError(Base.LazyString("invalid dimensions ", dims, " in reverse")))
length(dims) == length(indices) && return Base._reverse(iter, :)
indices′ = map((i, f) -> f ? reverse(i) : i, indices, dimrev)
indices′ = map((i, f) -> f ? (@noinline reverse(i)) : i, indices, dimrev)
return CartesianIndices(indices′)
end

Expand Down
3 changes: 2 additions & 1 deletion base/range.jl
Original file line number Diff line number Diff line change
Expand Up @@ -350,7 +350,8 @@ function steprange_last(start, step, stop)::typeof(stop)
# Compute remainder as a nonnegative number:
if absdiff isa Signed && absdiff < zero(absdiff)
# unlikely, but handle the signed overflow case with unsigned rem
remain = convert(typeof(absdiff), unsigned(absdiff) % absstep)
overflow_case(absdiff, absstep) = (@noinline; convert(typeof(absdiff), unsigned(absdiff) % absstep))
remain = overflow_case(absdiff, absstep)
else
remain = convert(typeof(absdiff), absdiff % absstep)
end
Expand Down
25 changes: 25 additions & 0 deletions test/ranges.jl
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# This file is a part of Julia. License is MIT: https://julialang.org/license

using Base.Checked: checked_length
using InteractiveUtils: code_llvm

@testset "range construction" begin
@test_throws ArgumentError range(start=1, step=1, stop=2, length=10)
Expand Down Expand Up @@ -2400,3 +2401,27 @@ end
@test test_firstindex(StepRange{Union{Int64,Int128},Int}(Int64(1), 1, Int128(1)))
@test test_firstindex(StepRange{Union{Int64,Int128},Int}(Int64(1), 1, Int128(0)))
end

@testset "Inline StepRange Construction #49270" begin
x = rand(Float32, 80)
a = rand(round(Int, length(x) / 2):length(x), 10^6)

function test(x, a)
c = zero(Float32)

@inbounds for j in a
for i in 1:8:j
c += x[i]
end
end

return c
end

llvm_ir(f, args) = sprint((io, args...) -> code_llvm(io, args...; debuginfo=:none), f, Base.typesof(args...))

ir = llvm_ir(test, (x, a))
@test !occursin("steprange_last", ir)
@test !occursin("_colon", ir)
@test !occursin("StepRange", ir)
end

0 comments on commit 2e80c0d

Please sign in to comment.