This is an archive of the discontinued LLVM Phabricator instance.

[mlir][bufferization] Support unstructured control flow
ClosedPublic

Authored by springerm on Aug 16 2023, 8:37 AM.

Details

Summary

This revision adds support for unstructured control flow to the bufferization infrastructure. In particular: regions with multiple blocks, cf.br, cf.cond_br.

Two helper templates are added to BufferizableOpInterface.h, which can be implemented by ops that supported unstructured control flow in their regions (e.g., func.func) and ops that branch to another block (e.g., cf.br).

A block signature is always bufferized together with the op that owns the block.

Depends On: D158154

Diff Detail

Event Timeline

springerm created this revision.Aug 16 2023, 8:37 AM
Herald added a project: Restricted Project. · View Herald TranscriptAug 16 2023, 8:37 AM
springerm requested review of this revision.Aug 16 2023, 8:37 AM
Matt added a subscriber: Matt.Aug 16 2023, 2:46 PM
springerm updated this revision to Diff 551142.Aug 17 2023, 8:12 AM
springerm edited the summary of this revision. (Show Details)

fix bug

Can we have an invalid-test checking for multiple return operations inside a function?
There is no looping test where the buffer type has to resort to the fully dynamic type.

Thanks for adding a lot of comments, it makes understanding the code a lot easier!

mlir/include/mlir/Dialect/Bufferization/IR/BufferizableOpInterface.h
417

Should there be some max number of revisits such that the compiler does not run into an infinite loop?

735

Those helper templates are a lot of code in this public API. Maybe we should move them to a separate header file UnstructuredControlFlowBufferizableOpImpl.h or so?

756

Shouldn't this be an emitError or assertion? Why is it safe to just skip it?

758

insert "not"

763–766

I'm curious, why does result.push_back(operands.getForwardedOperands()[bbArg.getArgNumber()]) not work?

776

Nit: Should the body of this function be outlined into a protected helper function that is called here with an assertion in front that checks for tensor results to make sure the user of this helper template uses it correctly?

794

But it calls defaultGetBufferType for OpResults below, so is it also the default implementation for those and it's not for block arguments only?

806

Where do we get the guarantee from that this will never be an unranked tensor?

813

Are we still guaranteed that it will end up in the same memory space?

mlir/include/mlir/Dialect/Bufferization/IR/BufferizableOpInterface.td
416–417

It's not clear to me what you mean by just reading this. Should the Op containing the region with unstructured control-flow bufferize the terminators as well or just the block arguments and the terminators bufferize themselves? It becomes very clear when reading the rest of the PR, but I think the phrasing here could be a bit improved.

mlir/include/mlir/Dialect/Bufferization/Transforms/Bufferize.h
83

Nit: maybe add this parenthesized part right after the 'callers' in the first line of the comment?

mlir/lib/Dialect/Bufferization/Transforms/FuncBufferizableOpInterfaceImpl.cpp
346

Should this check if the function is external/just a declaration? Should we then just use isExternal or isDeclaration instead?

mlir/lib/Dialect/ControlFlow/Transforms/BufferizableOpInterfaceImpl.cpp
19

Do we really need this include? I don't immediately see what is used from it.

48

"without"?

mlir/lib/Dialect/SCF/Transforms/BufferizableOpInterfaceImpl.cpp
103

"no"?

mlir/test/Dialect/Bufferization/Transforms/one-shot-module-bufferize.mlir
665

If there is nothing to test here, why does the test then exist? Just to check that the canonicalizer is run beforehand?

mlir/test/Dialect/ControlFlow/one-shot-bufferize.mlir
15

Wouldn't it be better to have the scf.execute_region tests in the SCF directory? And focus on tests where the CF ops are directly inside a func.func here instead?

mlir/test/Dialect/SCF/one-shot-bufferize-invalid.mlir
20–21

Does scf.execute_region verify that there exists at least one yield or should we add a test-case without any yield?

springerm marked 18 inline comments as done.Aug 22 2023, 8:17 AM

There is no looping test where the buffer type has to resort to the fully dynamic type.

This is tested by the @cond_br test case. (It is not looping, but there are two SSA values with different buffer types coming into ^bb1.)

mlir/include/mlir/Dialect/Bufferization/IR/BufferizableOpInterface.h
417

There is currently no way to keep to track of the number of visits. This would require a change to the signature of findValueInReverseUseDefChain. At the moment, this flag is always false and it is expected that (in the future) a user of findValueInReverseUseDefChain performs extra checks in the lambda function to avoid such looping.

756

Good point. We should assert. (Maybe an error in the future if there are such ops. At the moment it is not possible to emit an error here.)

763–766

There could be more block arguments than forwarded operands. E.g., the branch op could create its own values and ("produced operands") and make them available as a block argument. Such cases are not supported at the moment, but I already wanted to account for this where possible.

813

We could have different memory spaces on incoming op operands. In that case an error is produced below: incoming operands of block argument have inconsistent memory spaces

mlir/include/mlir/Dialect/Bufferization/IR/BufferizableOpInterface.td
416–417

This is actually up to the users. Either way works but bufferizing the terminator together with the block signatures ensures that the IR will stay valid at any point of time. I extended the documentation here.

mlir/test/Dialect/Bufferization/Transforms/one-shot-module-bufferize.mlir
665

I meant "nothing to check". The test is here so that unstructured control flow in a FuncOp is tested.

mlir/test/Dialect/ControlFlow/one-shot-bufferize.mlir
15

It doesn't really matter which one we use. In either case, we have to use an op from another dialect.

springerm updated this revision to Diff 552377.Aug 22 2023, 8:17 AM
springerm marked 7 inline comments as done.

address comments

dcaballe accepted this revision.Aug 30 2023, 12:51 PM
This revision is now accepted and ready to land.Aug 30 2023, 12:51 PM
This revision was automatically updated to reflect the committed changes.