IntelLabs / ParallelAccelerator.jl

The ParallelAccelerator package, part of the High Performance Scripting project at Intel Labs
BSD 2-Clause "Simplified" License
294 stars 32 forks source link

CGen getfield improvement for non-constant field parameters. #72

Open DrTodd13 opened 8 years ago

DrTodd13 commented 8 years ago

I just changed CGen to check whether a getfield call has a constant or non-constant as the field parameter (args[2]). If it is a constant, then we can generate the much simpler object.fN syntax where N is the constant field number - 1. If the field is a non-constant, like a Symbol, then CGen still has a problem here. How to know the offset of a particular field of a struct at runtime when the field number itself is not known until runtime?

I suggest that when we make a Tuple struct, we generate a corresponding table where the i'th element of the table is the offset of the i'th element from the start of the struct. For example,

typedef struct { double f0; int64_t f1; } TupleFloat64Int64;

int TupleFloat64Int64Offsets[2] = { offsetof(TupleFloat64Int64, f0), offsetof(TupleFloat64Int64, f1) };

Then, getfield(obj, fieldnum) can be translated to something like: ((((char)(&obj)) + TupleFloat64Int64Offsets(fieldnum-1))).

Of course, this won't work exactly because you'd need to cast the char* to some appropriate type before dereferencing but if the types in the struct are different then you'd need a some Union type or potentially Any.

ehsantn commented 8 years ago

Could you give a Julia example code for this use case?

DrTodd13 commented 8 years ago

julia> function f1() a::Int32 = 1 b::Int32 = 2 (1.1, a, b, 2.2) end f1 (generic function with 1 method)

julia> function f2(x, y) x[y] end f2 (generic function with 1 method)

julia> code_typed(f2,(Tuple{Float64,Int32,Int32,Float64,}, Int64)) 1-element Array{Any,1}: :($(Expr(:lambda, Any[:x,:y], Any[Any[Any[:x,Tuple{Float64,Int32,Int32,Float64},0],Any[:y,Int64,0]],Any[],Any[],Any[]], :(begin # none, line 2: return (Base.getfield)(x::Tuple{Float64,Int32,Int32,Float64},y::Int64)::Union{Float64,Int32} end::Union{Float64,Int32}))))

Obviously, this is not that common which is why it doesn't seem to be an issue in any existing benchmark. I don't know what to do about the typing situation here. It doesn't seem like we handle Union types properly. Going to file another issue for this.