This is an archive of the discontinued LLVM Phabricator instance.

[flang][hlfir] Add hlfir.forall and its OrderAssignmentTreeOpInterface
ClosedPublic

Authored by jeanPerier on May 3 2023, 2:56 AM.

Details

Summary

This patch adds the hlfir.forall operation and the
OrderAssignmentTreeOpInterface that allows representing Fortran forall.

It uses regions to keep Fortran expression evaluation independent from
each other in the IR. Forall assignments inside hlfir.forall are
represented with hlfir.region_assign which also keeps the IR generated
for each expressions independently.

The goal of this representation is to provide a representation that is
straightforward to generate from Fortran parse tree without any analysis, while
providing enough structure information so that an optimization pass can decide
how to schedule, and save if needed, the evaluations of the Forall and Where
expression and statements. It allows the data dependency analysis to be done at
the HLFIR level.

The OrderAssignmentTreeOpInterface allows ensuring that the Forall/Where
tree structure is kept in the IR. It will allow visiting this tree in
the IR without hard coding the operation structures in the pass.

Diff Detail

Event Timeline

jeanPerier created this revision.May 3 2023, 2:56 AM
Herald added a project: Restricted Project. · View Herald Transcript
jeanPerier requested review of this revision.May 3 2023, 2:56 AM
This revision is now accepted and ready to land.May 3 2023, 9:02 AM
tblah accepted this revision.May 3 2023, 9:37 AM

Looks great to me, thanks!

vzakhari accepted this revision.May 3 2023, 11:38 AM

Looks great, Jean! I have just one question.

flang/include/flang/Optimizer/HLFIR/HLFIROps.td
1069

Sounds okay, but would we have more readable IR if we support multiple indices with a single hlfir.forall? Having hlfir.yield return a vector of ints and having multiple blocks arguments in the body block does not sound too complex. Will it make the lowering more complex?

jeanPerier added inline comments.May 4 2023, 12:47 AM
flang/include/flang/Optimizer/HLFIR/HLFIROps.td
1069

Fair point, I thought a bit about having hlfir.yield returning multiple values (for the bounds remapping arguments of pointer assignments, that I have not yet covered). While it is possible and would not make lowering much more complex, it would make the data dependency a bit more complex: right now, I am planning to have a dumb approach that looks at all the operation in a region that yields a value, and if any of them has a read effect on a variable being assigned, to create a temporary for the value yielded.

If we move to yields with several values, the analysis will need to be more clever to identify which yielded value is conflicting (it would need to follow the DAG an that is a more complex), or the pass will need to save all yielded values if there is any conflict in the region, just to be safe.

So I am rather inclined to have a heavier syntax until to have a conflict analysis as simple as possible to start with. Then, if we are confident we can have a "finer grain" analysis to detect which yielded entity conflicts, I would happy to move to a lighter syntax.

vzakhari added inline comments.May 4 2023, 11:08 AM
flang/include/flang/Optimizer/HLFIR/HLFIROps.td
1069

Thank you for the explanation! I am not sure I understand the conflict detection 100%, so I am looking forward to reviewing it.