Will field extraction be recognized as a loop invariant?

In the following example

struct Foo
    colind::Int
    A::Matrix{Float64}
    v::Vector{Float64}
end

function copycol!(foo::Foo)
    for i in eachindex(foo.v)
        foo.v[i] = foo.A[i, foo.colind]
    end
    foo
end

will the compiler recognize that all of the field extractions inside the loop are loop invariants?

At present I would write copycol! as

function copycol!(foo::Foo)
    colind = foo.colind
    A = foo.A 
    v = foo.v
    for i in eachindex(v)
        v[i] = A[i, colind]
    end
    foo
end

Am I telling the compiler something it will easily recognize on its own?

In the spirit of “teach a person to fish” which of the @code_* macros should I apply to the copycol! method to work this out for myself? I hope I would be able to see it at some level before @code_native.

1 Like

I don’t know the current status but in the 0.6 era this was true for non mutable structs.

See https://github.com/JuliaLang/julia/issues/9755, SparseMatrixCSC should probably be an immutable · Issue #15668 · JuliaLang/julia · GitHub, https://github.com/JuliaLang/julia/pull/16371 and comments therein.

One wrinkle is that the data pointer for a vector can change but manually hoisting the field lookup doesn’t help, you’d need to boost the pointer lookup itself and write unsafe pointer code which will actually segfault if the data pointer changes, so that’s not recommended.