This is an archive of the discontinued LLVM Phabricator instance.

Add rewrite by-reference parameter pass
ClosedPublic

Authored by grosser on Aug 16 2017, 10:26 AM.

Details

Summary

This pass detangles induction variables from functions, which take variables by
reference. Most fortran functions compiled with gfortran pass variables by
reference. Unfortunately a common pattern, printf calls of induction variables,
prevent in this situation the promotion of the induction variable to a register,
which again inhibits any kind of loop analysis. To work around this issue
we developed a specialized pass which introduces separate alloca slots for
known-read-only references, which indicate the mem2reg pass that the induction
variables can be promoted to registers and consquently enable SCEV to work.

We currently hardcode the information that a function
_gfortran_transfer_integer_write does not read its second parameter, as
dragonegg does not add the right annotations and we cannot change old dragonegg
releases. Hopefully flang will produce the right annotations.

Diff Detail

Repository
rL LLVM

Event Timeline

grosser created this revision.Aug 16 2017, 10:26 AM
bollu accepted this revision.Aug 16 2017, 3:36 PM

Nit: Consider using IRBuilder? Not sure if this is needed, but maybe it avoids the extra parameter. YMMV. Other than that LGTM.

lib/Transform/RewriteByReferenceParameters.cpp
42 ↗(On Diff #111380)

Could you please document why this is necessary?

55 ↗(On Diff #111380)

Nit: this proofs useful -> this proves useful

65 ↗(On Diff #111380)

Perhaps we can make this slightly nicer with the pattern matching utilities. If not, I believe we should at least use the Operator versions so this can work on constant versions of the operands as well.

72 ↗(On Diff #111380)

Consider appending the original alloca name?

74 ↗(On Diff #111380)

Consider appending the original alloca name?

76 ↗(On Diff #111380)

Consider appending the original Alloca name?

test/RewriteByReferenceParameters/fortran_io.ll
27 ↗(On Diff #111380)

I believe we can reduce this type to whatever we want to. Consider making this smaller?

This revision is now accepted and ready to land.Aug 16 2017, 3:36 PM
grosser marked 6 inline comments as done.Aug 16 2017, 10:25 PM

Thanks for the nice review. I addressed all but one comment, which can likely be improved in a subsequent commit. Will go ahead and commit this now.

lib/Transform/RewriteByReferenceParameters.cpp
42 ↗(On Diff #111380)

I generalized the code for this to not be necessary.

65 ↗(On Diff #111380)

Not sure what you mean. As this seems to be an extension of this functionality, I will go ahead without this and we can improve this in a subsequent commit.

This revision was automatically updated to reflect the committed changes.
grosser marked an inline comment as done.

Sorry this may be too late. Alexandre and me had discussed similar problem (but not exactly the same)

  1. maybe we could improve the ArgumentPromotion pass for this
  2. this pass seems to be generic, maybe we could move this to LLVM?

It's certainly not too late. Until now it seemed to me like a very specific optimization for gfortran. I did not see any such examples before. If we can generalize this, we can certainly try to upstream this. Could you share some of the examples you are seeing?

It's certainly not too late. Until now it seemed to me like a very specific optimization for gfortran. I did not see any such examples before. If we can generalize this, we can certainly try to upstream this. Could you share some of the examples you are seeing?

"by-reference" is one side, another side is the function return something via a pointer argument (e.g. the opencl sincos function)[1]:

int *p;
a = return_via_p(p);

We want to transform it to:

{ a, b } = return_via_p();
*p = b;

Also, a pointer can be read-modify-write:

int *p;
a = read_modify_write_p(p);

we want to transform it to:

int *p;
int pin = *p;
{a, b} = read_modify_write_p(pin);
*p = b;

[1]https://www.khronos.org/registry/OpenCL/sdk/1.0/docs/man/xhtml/sin.html

It's certainly not too late. Until now it seemed to me like a very specific optimization for gfortran. I did not see any such examples before. If we can generalize this, we can certainly try to upstream this. Could you share some of the examples you are seeing?

"by-reference" is one side, another side is the function return something via a pointer argument (e.g. the opencl sincos function)[1]:

int *p;
a = return_via_p(p);

We want to transform it to:

{ a, b } = return_via_p();
*p = b;

Also, a pointer can be read-modify-write:

int *p;
a = read_modify_write_p(p);

we want to transform it to:

int *p;
int pin = *p;
{a, b} = read_modify_write_p(pin);
*p = b;

I see. These all seem to require us to modify the function declarations. Hence, are likely out-of-scope for a function pass, but certainly a good fit for the argument promotion pass. Feel free to add me as a reviewer in case you would like to contribute patches for your two examples.

As the fortran functions are part of an external library the change I committed here likely does not benefit from argpromotion.

Best,
Tobias