Removing bounds checking for HPC - `--check-bounds=unsafe`?

Presumably you could write a macro to do this for you. For example,

using MacroTools: @capture, postwalk

function add_inbounds_everywhere(ex)
	postwalk(ex) do x
		@capture(x, a_[b__]) || return x
		return :(@inbounds $x)
	end
end

macro add_inbounds_everywhere(ex)
    return add_inbounds_everywhere(ex)
end

Of course, it’s not quite as easy as you only want to add @inbounds on getindex, not on setindex!, e.g. you don’t want to end up with @inbounds(x[1]) = 0. So you need corrections like:

function move_assignment_inbounds(ex)
	return postwalk(ex) do x
		@capture(x, @inbounds(a_[b__]) = c__) || return x
		return :(@inbounds($a[$(b...)] = $(c...)))
	end
end

function move_broadcasted_assignment_inbounds(ex)
	return postwalk(ex) do x
		@capture(x, @inbounds(a_[b__]) .= c__) || return x
		return :(@inbounds($a[$(b...)] .= $(c...)))
	end
end

function move_view_in_front_of_inbounds(ex)
	return postwalk(ex) do x
		@capture(x, @view(@inbounds(a_))) || return x
		return :(@inbounds(@view($a)))
	end
end

carefully_add_inbounds =  move_view_in_front_of_inbounds ∘ move_broadcasted_assignment_inbounds ∘ move_assignment_inbounds ∘ add_inbounds_everywhere

Presumably there are plenty of cases still missing, but if you

include(carefully_add_inbounds, "script.jl")

for a file script.jl containing

function f(x)
	x[4] = -100
	sum(x[i] for i = 1:4)  
	# Note that @inbounds sum(x[i] for i = 1:4) would not work;
	# you need sum(@inbounds x[i] for i = 1:4).
end

println(f(rand(3)))

function g(x, y)
	x[1:5] .= @view y[1:5]
end

g(zeros(4), rand(10))

you get something like

-99.202880576623
5-element view(::Vector{Float64}, 1:5) with eltype Float64:
 0.1550523932721809
 0.16183646229915816
 0.6185234401813514
 0.6716336573001286
 0.12471934509214788

as output, without BoundsErrors.

1 Like