This is an archive of the discontinued LLVM Phabricator instance.

[flang][hlfir] Add hlfir.region_assign and its hlfir.yield terminator
ClosedPublic

Authored by jeanPerier on Apr 28 2023, 6:14 AM.

Details

Summary

hlfir.region_assign is a Region based version of hlfir.assign: the
right-hand side and left-hand-side are evaluated in their own region,
and an optional region can be added to implement user defined
assignment.

This will be used for:

  • assignments inside where and forall
  • user defined assignments
  • assignments to vector subscripted entities.

Rational:

Forall and Where lowering requires solving an expression/assignment
evaluation scheduling problem based on data dependencies between the
variables being assigned and the one used in the expressions.
Keeping left-hand side and right-hand side in their own region will
make it really easy to analyse the dependency and move around the
expression evaluation as a whole. Operation DAGs are hard to scissor out
when the LHS and RHS evaluation are lowered in the same block. The pass
dealing with further forall/where lowering in HLFIR will need to
succeed. It is not acceptable for them to fail splitting the RHS/LHS
evaluation code. Keeping them in independent block is an approach that
cannot fail.

For user defined assignments, having a region allows implementing all
the call details in lowering, and even to allow inlining of the user
assignment, before it is decided if a temporary for the LHS or RHS is
required or not.

The operation description mention "hlfir.elemental_addr" (operation that
will be used for vector subscripted LHS) and "ordered assignment trees"
(concept/inetrface that will be used to represent forall/where structure
in HLFIR). These will be pushed in follow-up patch, but I do not want t
scissor out the descriptions.

Diff Detail

Event Timeline

jeanPerier created this revision.Apr 28 2023, 6:14 AM
jeanPerier requested review of this revision.Apr 28 2023, 6:14 AM
clementval accepted this revision.Apr 28 2023, 9:22 AM

This looks nice! Just couple of remark/questions but nothing blocking for me.

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

Maybe it's just me but I find it a bit counter intuitive to have the rhs on the left and the lhs on the right.

flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp
980

Was it too tricky to do it with the inlined assembly format?

This revision is now accepted and ready to land.Apr 28 2023, 9:22 AM
jeanPerier added inline comments.Apr 28 2023, 11:42 AM
flang/include/flang/Optimizer/HLFIR/HLFIROps.td
845

Oups, I did not update the format here... This is actually: (%rhs_elt : !fir.ref<f32>) to (%lhs_elt:!fir.ref<!fir.type<t>>), I moved to custom parser to get the to and make it clear what is the RHS vs LHS. I followed fir.store/hlfir.assign/... logic of "RHS" to "LHS".

flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp
980

The I was not sure how to get the () to () part of the user assignment block arguments with assembly format. I thought is was nicer to be heavy here to disambiguate the RHS/LHS.

Do you know if one can manipulate region arguments in inlined assembly format?

I also failed to get the terminator to be added on the the user defined region, while the other region are not implicitly terminated, but I did not try hard here.

clementval added inline comments.Apr 28 2023, 11:49 AM
flang/include/flang/Optimizer/HLFIR/HLFIROps.td
845

Ok this makes sense with the new format then.

flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp
980

I don't think you can manipulate region argument with the inlined assembly format. That's a good reason to make it custom. Thanks for the explanation.

tblah added a comment.May 1 2023, 7:02 AM

Great work on this. I like the overall idea. Other than some nits, this looks good to me.

flang/include/flang/Optimizer/HLFIR/HLFIROps.td
838–844

I think maybe something like

hlfir.region_assign {

hlfir.yield %x ...

} = {

hlfir.yield %y ...

}

Would be easier. I know there is already precedent (fir.store) for "RHS to LHS" but when I read "assign" I will be already thinking "LHS = RHS".

This is a matter of opinion so feel free to continue without changing if you prefer "RHS to LHS".

flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp
1046

I think this and printYieldOpCleanup are unused. Are they for something added in a later patch?

jeanPerier added inline comments.May 2 2023, 1:22 AM
flang/include/flang/Optimizer/HLFIR/HLFIROps.td
838–844

I do not have a strong opination either. If it was not for the fir.store / hlfir.assign / llvm store precedent, I would probably have gone LHS "something" RHS. I am not sure why LLVM store chose to put the value as its first operand.

I tried your suggestion, and unfortunately it seems "=" is a reserved keyword in MLIR parser and cannot be used here. I get the funny error:

`
region_assign.fir:15:5: error: custom op 'hlfir.region_assign' expected '='
  } = {
    ^

I find "equal" too predicate like, maybe "with" could do, also I find "assign y to x" a bit more natural than "assign x with y" (but I am not a native English speaker).

Do you see good short word I could use instead of "="?

flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp
1046

They are used in code generated by MLIR because the .td inline assembly format for YieldOp uses custom<YieldOpCleanup>($cleanup).

See the custom parsing directives https://mlir.llvm.org/docs/DefiningDialects/Operations/#custom-directives

I try to use this when possible instead of defining a complete cpp print/parse implementation.

tblah added inline comments.May 2 2023, 2:29 AM
flang/include/flang/Optimizer/HLFIR/HLFIROps.td
838–844

How about hlfir.region_assign LHS from RHS?

I don't feel strongly about this so feel free to leave it how it is. If we can't use =, I can't think of any very good options.

jeanPerier updated this revision to Diff 518711.May 2 2023, 7:10 AM

Rebase and update example to reflect the correct assembly format
for user assignment region block arguments.

tblah accepted this revision.May 2 2023, 7:56 AM