GSoC Interested student

I'm not really sure I follow your examples. Could you provide the pseudo C+OpenMP code as well?
One thing to consider:
I think we should (for now) split every memory transfer into an issue and wait call. If a memory transfer is combined with
a kernel execution we split it in its parts, e.g.,

#pragma omp target map(to:A,B) map(from:C,D)
{ code(); }

should become

issue_to(A)
issue_to(B)
wait_to(A)
wait_to(B)
kernel(...)
issue_from(C)
issue_from(D)
wait_from(C)
wait_from(D)

With regards to the moving question. It doesn't really matter where what is as we want to move both (issue and wait).
We always need to verify the instruction we move "over" is not interfering with the respective call.