Reaping unused STRUCTURE variables

Reaping unused STRUCTURE variables

ereisch's picture

Anyone know of any tricks to tease out unused STRUCTURE variables from the compiler?  I know you can use "-warn unused" to get a list of unused variables that are declared, but this doesn't seem to work with structure members.  I have a number of structures that are included via external files that are very old, and I would like to strip out all of the variables in those structures that are unused.

I'm running out of ideas; the paths that have been abandoned thus far include:

  • Downloading the gfortran source and attempting to a) modify it to even accept the STRUCTURE statement, and then use the parser in a custom program that builds an array of variable names, etc.  This was a complete failure due to the complexity of the gcc parser.
  • Doing a temporary global replace of FOO.BAR with FOO_BAR to make the compiler think they aren't structure members at all, but due to the number of variables (approximately 3000), and files (approximately 1200) involved, this became prohibitively time-consuming.

The latest path I'm wandering down is to declare all of the structures as COMMON, and then use the -fverbose-asm feature of ifort and use perl or something to search for the "$struct_name" keywords (where the code is either assigning data to or pulling data from the common block).  The line also includes an offset inside that common, which using some yet-undetermined method, can be used to reverse-engineer a list of "holes" in the COMMON that are never referenced.  Then it's just a few days of painful math to translate those offsets to variable names.

Thoughts?

11 posts / 0 new
Last post
For more complete information about compiler optimizations, see our Optimization Notice.
mecej4's picture

If this is worth investing as much time as you seem prepared to do, why not convert the STRUCTUREs and RECORDs to their equivalent Fortran 95 derived type declarations, and then have the compiler tell you which ones are not used?

ereisch's picture

Because it does not appear as though "-warn unused" operates on derived types.

mecej4's picture

Quote:

Because it does not appear as though "-warn unused" operates on derived types.

Really? Which version of the compiler? When I run IFort 12.1.7 on the program

program unusedb
type coord
   integer x; integer y; integer z
end type
type(coord) :: a,b
a%x=1; a%y=2; a%z=3;
write(*,*)a%x, a%y, a%z
end

and I compile with ifort /warn:unused on Windows 7, it says

unuse.f90(6): remark #7712: This variable has not been used.   [B]
type(coord) :: a,b
-----------------^

jimdempseyatthecove's picture

I would suggest changing FOO.BAR to FOO.xxxxxxxxxxxBAR

Reason: old code may not use IMPLICIT NONE.

Do a full build, save the log file(s), concatinate log files, strip out duplicates. If you are not handy with AWK or other scripting tool, you could write a simple FORTRAN program to strip out the duplicates and "junk" lines, leaving only the referenced field names (with xxxxxxxxxxxx prefix).

A couple of hours should have your fix.

Note, this will change the record layout. As to if this presents a different problem, well, you will have to hope it does not.

N.B. I suggest you not strip out variables that might be used later on (comment them out instead).

Jim Dempsey

www.quickthreadprogramming.com
jimdempseyatthecove's picture

mecej4,

It is not the case that B is unused, it is the case that B.x is unused.
Or more precisely coord::x is not used

Excepting in this case it is not a type but a record.

Jim Dempsey

www.quickthreadprogramming.com
mecej4's picture

Jim wrote: Quote:

It is not the case that B is unused, it is the case that B.x is unused.

Oh, so does the OP want individual components to be flagged as unused, rather than the whole structure/derived-type variable?

I wonder if that is a little too much to ask for; consider the corresponding situation with an array, say vec(3), with vec(1) and vec(3) used, but not vec(2), in a subprogram. Surely, in that case, we don't expect any "unused..." warnings?

IanH's picture

Could you just comment the definition of the component out?

jimdempseyatthecove's picture

>>Could you just comment the definition of the component out?

That is one way, but this would then require # builds == # components (~3000 components). My preference would be to comment or conditionalize them all out, run one build producing 10,000's errors (set #errors high), filter error listing to get individual component name, uncomment / unconditionialize those, run build again (to catch any straglers). If you use a conditional compilation technique, then you can quickly undo the change in the event of unanticipated problems.

Jim Dempsey

www.quickthreadprogramming.com
mecej4's picture

IanH wrote: Quote:

Could you just comment the definition of the component out?

I can think of situations where this would not be quite workable. Consider, for example, the derived type

type time_series
   integer :: ndat
   real, allocatable :: x(:)
   real :: mu,sig
end type

There are good reasons for the different components to be kept together. However, one could call an I/O routine to assign values to ndat and x(), then call another routine to compute the mean, mu, and yet another routine to compute the standard deviation. It may be that not every component of the derived type is accessed in each of these routines, and yet that would not justify removing (or commenting out) an unused component.

jimdempseyatthecove's picture

This is why you build the complete project/solution and concatinate the log files. Stripping out the duplicates would leave a list of those referenced. These would be uncommented. Out of the 3000 or so mentioned, some may remain.

The only things this would not get is UNION's and/'or records who's size is required outside the project/solution. (standardized file format).

The ereisch was using records, but this would apply to user defined types as well.

Jim Dempsey

www.quickthreadprogramming.com

Login to leave a comment.