How does the compiler handle functions and subroutines?

The code can also be factored using associate. Here is an example:

module m
   implicit none
   integer, parameter :: N = 2
   real :: x(N,N)
end module
program p
   use m, only : x
   implicit none
   x = reshape( [1.0, 2.0, 3.0, 4.0], shape=shape(x) )
   associate( a=>x(:,1), b=>x(:,2) )
      print *, "X = ", x
      print *, "A = ", a
      print *, "B = ", b
   end associate
end program p

I have no idea how or if this kind of thing could be automated.

With the exercise, the expectation is a subprogram sub shall remain after refactoring. That presently the legacy sub makes use of some global.data x that is currently in a COMMON block, the data are initialized elsewhere (main program), and the data are referenced via EQUIVALENCEd objects of “a” and “b”. Such practice wasn’t uncommon with legacy codes with FORTRAN 77 and dialects and extensions. The print statements in the small example simply illustrated such use of the data in a couple of lines but the actual code may have further instructions taking place on the data. Getting rid of the subprogram altogether then is not what is called for.

I agree with all that, I was just trying to show that instead of explicitly declared pointers, one might consider using the new associate construct instead. The real issue is whether any of these things can be done automatically.