--
You received this message because you are subscribed to the Google Groups "MLIR" group.
To unsubscribe from this group and stop receiving emails from it, send an email to mlir+uns...@tensorflow.org.
To view this discussion on the web visit https://groups.google.com/a/tensorflow.org/d/msgid/mlir/df062b81-2443-414a-adbd-34d9c79c7261%40tensorflow.org.
IIRC, this has been discussed several times in different contexts. The common argument against this is that, without knowing the semantics of a specific region, it's unclear where should "std.return" transfer the control flow.
func @foo() {affine.if ... {std.return // this returns from the function
}
}func @bar() {affine.greybox {std.return // this return from the region}}func @baz {affine.greybox {affine.if {std.return // 'if' says it should return from the function, but 'greybox' says return from region...}}}Adding a specific affine.yield does not cost that much...
On Thu, Dec 19, 2019 at 2:38 PM 'Uday Bondhugula' via MLIR <ml...@tensorflow.org> wrote:
Hi all,--I felt the changes in this PR may require discussion. I'm thus posting it here.This generalization is also needed to support the proposed affine.graybox in its full power:which could be the first use case exercising this additional freedom --- but there are clearly many more.Best,Uday
You received this message because you are subscribed to the Google Groups "MLIR" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ml...@tensorflow.org.
On Thursday, December 19, 2019 at 8:53:53 PM UTC+5:30, Alex Zinenko wrote:IIRC, this has been discussed several times in different contexts. The common argument against this is that, without knowing the semantics of a specific region, it's unclear where should "std.return" transfer the control flow.But that's left to the semantics of the op, and the op's implementation to deal with it.
This also happens to be consistent with the documentation on a region's control flow in LangRef (reproduced below). It was actually the implementation that was incomplete!Regions are Single-Entry-Multiple-Exit (SEME). This means that control can only flow into the first block of the region, but can flow out of the region at the end of any of the contained blocks (This behavior is similar to that of a function body in most programming languages). When exiting a Region, control is returned to the enclosing operation.
To unsubscribe from this group and stop receiving emails from it, send an email to mlir+uns...@tensorflow.org.
To view this discussion on the web visit https://groups.google.com/a/tensorflow.org/d/msgid/mlir/3820c08a-1d08-47e1-aed3-21b744c92f7a%40tensorflow.org.
On Thu, Dec 19, 2019, 16:37 'Uday Bondhugula' via MLIR <ml...@tensorflow.org> wrote:
On Thursday, December 19, 2019 at 8:53:53 PM UTC+5:30, Alex Zinenko wrote:IIRC, this has been discussed several times in different contexts. The common argument against this is that, without knowing the semantics of a specific region, it's unclear where should "std.return" transfer the control flow.But that's left to the semantics of the op, and the op's implementation to deal with it.Having the semantics of an op depend on the surrounding op, especially from a different dialect, sounds too brittle to me. And you would essentially disallow the early-return pattern in functions.Note that I'm not opposed to having a terminator that unconditionally transfers the control flow back to the surrounding op. It just shouldn't be "return", which returns from the nearest function, and being used otherwise is likely to be a perpetual source of confusion.
This also happens to be consistent with the documentation on a region's control flow in LangRef (reproduced below). It was actually the implementation that was incomplete!Regions are Single-Entry-Multiple-Exit (SEME). This means that control can only flow into the first block of the region, but can flow out of the region at the end of any of the contained blocks (This behavior is similar to that of a function body in most programming languages). When exiting a Region, control is returned to the enclosing operation.Indeed, it's a good point. I should rephrase this more carefully. And it's reasonable to think about locality of flow across nested regions, and even more
To view this discussion on the web visit https://groups.google.com/a/tensorflow.org/d/msgid/mlir/3820c08a-1d08-47e1-aed3-21b744c92f7a%40tensorflow.org.
To unsubscribe from this group and stop receiving emails from it, send an email to mlir+uns...@tensorflow.org.
To view this discussion on the web visit https://groups.google.com/a/tensorflow.org/d/msgid/mlir/a5a54a45-60cb-4d79-af96-acec24bc145f%40tensorflow.org.
On Thursday, December 19, 2019 at 9:47:11 PM UTC+5:30, Alex Zinenko wrote:On Thu, Dec 19, 2019, 16:37 'Uday Bondhugula' via MLIR <ml...@tensorflow.org> wrote:
On Thursday, December 19, 2019 at 8:53:53 PM UTC+5:30, Alex Zinenko wrote:IIRC, this has been discussed several times in different contexts. The common argument against this is that, without knowing the semantics of a specific region, it's unclear where should "std.return" transfer the control flow.But that's left to the semantics of the op, and the op's implementation to deal with it.Having the semantics of an op depend on the surrounding op, especially from a different dialect, sounds too brittle to me. And you would essentially disallow the early-return pattern in functions.Note that I'm not opposed to having a terminator that unconditionally transfers the control flow back to the surrounding op. It just shouldn't be "return", which returns from the nearest function, and being used otherwise is likely to be a perpetual source of confusion.I still don't see your point here. std.return doesn't return to the nearest function - it transfers control to its parent op just like the current doc says. In the current codebase, one can use std.return only from the top level of a func op. My patch changes that and allows one to use it from the top level of other ops that have a region (if those ops allow it). (For eg. you can use a return from the top level of an affine.graybox.) You still won't be able to use it from a point that is not the top level of that op. Could you look at the update to the 'return' op documentation I made in the PR?
This also happens to be consistent with the documentation on a region's control flow in LangRef (reproduced below). It was actually the implementation that was incomplete!Regions are Single-Entry-Multiple-Exit (SEME). This means that control can only flow into the first block of the region, but can flow out of the region at the end of any of the contained blocks (This behavior is similar to that of a function body in most programming languages). When exiting a Region, control is returned to the enclosing operation.Indeed, it's a good point. I should rephrase this more carefully. And it's reasonable to think about locality of flow across nested regions, and even moreNo, there isn't a need to update it!
To unsubscribe from this group and stop receiving emails from it, send an email to mlir+uns...@tensorflow.org.
To view this discussion on the web visit https://groups.google.com/a/tensorflow.org/d/msgid/mlir/a5a54a45-60cb-4d79-af96-acec24bc145f%40tensorflow.org.
Here's the previous discussion on this.
To view this discussion on the web visit https://groups.google.com/a/tensorflow.org/d/msgid/mlir/a5a54a45-60cb-4d79-af96-acec24bc145f%40tensorflow.org.
On Thu, Dec 19, 2019 at 6:36 PM 'Uday Bondhugula' via MLIR <ml...@tensorflow.org> wrote:
On Thursday, December 19, 2019 at 9:47:11 PM UTC+5:30, Alex Zinenko wrote:On Thu, Dec 19, 2019, 16:37 'Uday Bondhugula' via MLIR <ml...@tensorflow.org> wrote:
On Thursday, December 19, 2019 at 8:53:53 PM UTC+5:30, Alex Zinenko wrote:IIRC, this has been discussed several times in different contexts. The common argument against this is that, without knowing the semantics of a specific region, it's unclear where should "std.return" transfer the control flow.But that's left to the semantics of the op, and the op's implementation to deal with it.Having the semantics of an op depend on the surrounding op, especially from a different dialect, sounds too brittle to me. And you would essentially disallow the early-return pattern in functions.Note that I'm not opposed to having a terminator that unconditionally transfers the control flow back to the surrounding op. It just shouldn't be "return", which returns from the nearest function, and being used otherwise is likely to be a perpetual source of confusion.I still don't see your point here. std.return doesn't return to the nearest function - it transfers control to its parent op just like the current doc says. In the current codebase, one can use std.return only from the top level of a func op. My patch changes that and allows one to use it from the top level of other ops that have a region (if those ops allow it). (For eg. you can use a return from the top level of an affine.graybox.) You still won't be able to use it from a point that is not the top level of that op. Could you look at the update to the 'return' op documentation I made in the PR?We get into non-trivial interaction between the semantics of _all_ ops enclosing "return" to understand what it actually does, instead of disallowing it completely (now) or having it return from the nearest function. The current doc for "std.return" says "The return terminator operation represents the completion of a function, and produces the result values.", there's nothing about enclosing operations. The doc on region mentions "exiting a Region", but it is actually left unmodified from some earlier version of the region proposal that was having different assumptions about regions, in particular regions being able to omit terminators. We went for region _pretty printing_ being able to omit terminators instead, so it is unclear what "exiting a region" actually means now :) It used to mean "reaching the end of the operation list without seeing a terminator" (I wrote the proposal).This also happens to be consistent with the documentation on a region's control flow in LangRef (reproduced below). It was actually the implementation that was incomplete!Regions are Single-Entry-Multiple-Exit (SEME). This means that control can only flow into the first block of the region, but can flow out of the region at the end of any of the contained blocks (This behavior is similar to that of a function body in most programming languages). When exiting a Region, control is returned to the enclosing operation.Indeed, it's a good point. I should rephrase this more carefully. And it's reasonable to think about locality of flow across nested regions, and even moreNo, there isn't a need to update it!I still want support for something like if-guarded "break" in a loop. Unless we figure out some forwarding that the "if" would do to forward the fact that it was terminated by "break" to its parent, which may in turn need to forward it further up, I don't see a way around this.
To view this discussion on the web visit https://groups.google.com/a/tensorflow.org/d/msgid/mlir/a5a54a45-60cb-4d79-af96-acec24bc145f%40tensorflow.org.
---- Alex
Hi,
What happens when there is an actual function return inside the loop?
On Thu, Dec 19, 2019 at 6:36 PM 'Uday Bondhugula' via MLIR <ml...@tensorflow.org> wrote:
On Thursday, December 19, 2019 at 9:47:11 PM UTC+5:30, Alex Zinenko wrote:On Thu, Dec 19, 2019, 16:37 'Uday Bondhugula' via MLIR <ml...@tensorflow.org> wrote:
On Thursday, December 19, 2019 at 8:53:53 PM UTC+5:30, Alex Zinenko wrote:IIRC, this has been discussed several times in different contexts. The common argument against this is that, without knowing the semantics of a specific region, it's unclear where should "std.return" transfer the control flow.But that's left to the semantics of the op, and the op's implementation to deal with it.Having the semantics of an op depend on the surrounding op, especially from a different dialect, sounds too brittle to me. And you would essentially disallow the early-return pattern in functions.Note that I'm not opposed to having a terminator that unconditionally transfers the control flow back to the surrounding op. It just shouldn't be "return", which returns from the nearest function, and being used otherwise is likely to be a perpetual source of confusion.I still don't see your point here. std.return doesn't return to the nearest function - it transfers control to its parent op just like the current doc says. In the current codebase, one can use std.return only from the top level of a func op. My patch changes that and allows one to use it from the top level of other ops that have a region (if those ops allow it). (For eg. you can use a return from the top level of an affine.graybox.) You still won't be able to use it from a point that is not the top level of that op. Could you look at the update to the 'return' op documentation I made in the PR?We get into non-trivial interaction between the semantics of _all_ ops enclosing "return" to understand what it actually does, instead of disallowing it completely (now) or having it return from the nearest function. The current doc for "std.return" says "The return terminator operation represents the
~ Uday
--
You received this message because you are subscribed to the Google Groups "MLIR" group.
To unsubscribe from this group and stop receiving emails from it, send an email to mlir+uns...@tensorflow.org.
To view this discussion on the web visit https://groups.google.com/a/tensorflow.org/d/msgid/mlir/fc2476b9-5d2d-48da-a92e-ac48e54b81a4%40tensorflow.org.
~ Uday
On Thu, Dec 19, 2019 at 9:10 PM 'Uday Bondhugula' via MLIR <ml...@tensorflow.org> wrote:
On Friday, December 20, 2019 at 12:55:27 AM UTC+5:30, Alex Zinenko wrote:On Thu, Dec 19, 2019 at 6:36 PM 'Uday Bondhugula' via MLIR <ml...@tensorflow.org> wrote:
On Thursday, December 19, 2019 at 9:47:11 PM UTC+5:30, Alex Zinenko wrote:On Thu, Dec 19, 2019, 16:37 'Uday Bondhugula' via MLIR <ml...@tensorflow.org> wrote:
On Thursday, December 19, 2019 at 8:53:53 PM UTC+5:30, Alex Zinenko wrote:IIRC, this has been discussed several times in different contexts. The common argument against this is that, without knowing the semantics of a specific region, it's unclear where should "std.return" transfer the control flow.But that's left to the semantics of the op, and the op's implementation to deal with it.Having the semantics of an op depend on the surrounding op, especially from a different dialect, sounds too brittle to me. And you would essentially disallow the early-return pattern in functions.Note that I'm not opposed to having a terminator that unconditionally transfers the control flow back to the surrounding op. It just shouldn't be "return", which returns from the nearest function, and being used otherwise is likely to be a perpetual source of confusion.I still don't see your point here. std.return doesn't return to the nearest function - it transfers control to its parent op just like the current doc says. In the current codebase, one can use std.return only from the top level of a func op. My patch changes that and allows one to use it from the top level of other ops that have a region (if those ops allow it). (For eg. you can use a return from the top level of an affine.graybox.) You still won't be able to use it from a point that is not the top level of that op. Could you look at the update to the 'return' op documentation I made in the PR?We get into non-trivial interaction between the semantics of _all_ ops enclosing "return" to understand what it actually does, instead of disallowing it completely (now) or having it return from the nearest function. The current doc for "std.return" says "The return terminator operation represents theI have a feeling that you may be missing the 'top-level' part when you say 'enclose' (perhaps due to the wording of the commit message). The std.return op can only be used from the top-level of a function op (the way it is now) or the top level of another op with a region that allows it (after this PR) - affine.graybox will be an example. It isn't possible to (whether before or after this PR) to use it from within an affine.for or an affine.if; these blocks still use "affine.terminator" for their terminators. If you have a completely unknown op ("unknown"() ({...}) : () -> ()) that uses a return in its region, its semantics would be unknown and you'd anyway not convert/lower to std. FuncOp is currently the only registered op that allows a return (*only at its top level*). affine.graybox will be another op that will allow a return at its top level. In both cases, the semantics of the ensuing transfer of control are well defined. Why and where would you need to understand the semantics of an unknown op having a return in its holding region block? For the known ops, the op's implementation and lowering will define what the return means and how it should be lowered.I don't understand what you mean here. Are you implying that the lowering is based on the parent op? i.e. a ReturnOp in an affine.graybox would be lowered differently than a ReturnOp in a FuncOp? Unless you do some pre-analysis it isn't really possible to detect this during lowering, i.e. if the FuncOp/AffineGreyBox is
being lowered into something else this will happen before the ReturnOp is even visited. Unless you are suggesting that the parent operation must always lower the return, which isn't viable.-- River
--
~ Uday
You received this message because you are subscribed to the Google Groups "MLIR" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ml...@tensorflow.org.
There isn't a need for a new op - because I don't see an issue with reusing the std.return op if control is to be transferred to parent op. Reg. the return op verifier, there isn't a downside either. Can you see the update to verify(ReturnOp) on the PR? A missing return on a FuncOp will still be caught, and there isn't a win on disallowing return at the region top levels of other ops that want to. Creating a new return op wherever control is to be transferred to the parent op would be pure duplication - like for affine.graybox. If the name is confusing (I don't really see that to be an issue as well), STD.return can be renamed std.return_to_parent. But this is also unnecessary. I do understand that someone new might initially think of STD.return as a C function return.
Uday
On Friday, December 20, 2019 at 10:02:30 AM UTC+5:30, Uday Bondhugula wrote:
On Friday, December 20, 2019 at 9:34:23 AM UTC+5:30, Compiler Developer wrote:Hi,What happens when there is an actual function return inside the loop?There can't be. You'll get a verifier failure (irrespective of this PR).Yes, but isn't that what graybox needs to capture?
~ Uday
--
You received this message because you are subscribed to the Google Groups "MLIR" group.
To unsubscribe from this group and stop receiving emails from it, send an email to mlir+uns...@tensorflow.org.
To view this discussion on the web visit https://groups.google.com/a/tensorflow.org/d/msgid/mlir/fc2476b9-5d2d-48da-a92e-ac48e54b81a4%40tensorflow.org.
1.int func(..) {<outer affine loop> {for (int i = 0; i < 10; i++) {if (i < 0) {retrurn <some_val> // This is dead code.<affine operations>}}...}Above code will have two std.return operations inside the affine.graybox? One for C function and another for affine.graybox region?
2. About the affinegraybox op: I am still confused as to why not have break/continue instead of CFG? In the above case, there would be transformations to recover affine.for from the CFG based grayboxop?
On Friday, December 20, 2019 at 3:11:09 PM UTC+5:30, Compiler Developer wrote:1.int func(..) {<outer affine loop> {for (int i = 0; i < 10; i++) {if (i < 0) {retrurn <some_val> // This is dead code.<affine operations>}}...}Above code will have two std.return operations inside the affine.graybox? One for C function and another for affine.graybox region?Please either write entirely in C or MLIR - I can't really tell what your example from the mix above is!
2. About the affinegraybox op: I am still confused as to why not have break/continue instead of CFG? In the above case, there would be transformations to recover affine.for from the CFG based grayboxop?Can you please post questions on affine.graybox on a separate thread? This one isn't really about its design choices.
~ Uday
On Friday, December 20, 2019 at 2:17:59 PM UTC+5:30, Uday Bondhugula wrote:
On Friday, December 20, 2019 at 11:55:20 AM UTC+5:30, Compiler Developer wrote:On Friday, December 20, 2019 at 10:02:30 AM UTC+5:30, Uday Bondhugula wrote:
On Friday, December 20, 2019 at 9:34:23 AM UTC+5:30, Compiler Developer wrote:Hi,What happens when there is an actual function return inside the loop?There can't be. You'll get a verifier failure (irrespective of this PR).Yes, but isn't that what graybox needs to capture?The return, when it exists, will be from the top level of the graybox - you never need it inside the block of an affine.for. The terminator for an affine.for/if is still "affine.terminator". Please see for example:~ Uday" The op allows the polyhedral form to be used without the need for outlining to functions, and without the need to turn affine ops such as affine.for, affine.if into standard unrestricted for's and if's respectively." - https://github.com/bondhugula/mlir/blob/graybox/rfc/rfc-graybox.md#example-1What happens when there are loops like below (Example code 1) where we know it is going to be affine? There would also be cases where some transformations (peeling, fission, switch, unswitch, invariant code motion etc) on the unstrucutred loops which yeilds affine form. Especially for the languages like C, Fortran, no one would want to write such redundant transformations at AST level to be able to emit affine.for. It would not be good to move them to CFG based loops and then convert it to higher form.Ideal solution would be to model them in higher level loop forms with operations defined for break/ continue/ return, etc. and then lower to any of afine.for, loop.for,gpu.func(), openmp.for, CFG based loop, etc based on whichever is suitable.Example code 1:int some_func() {<outer affine loops>for (int i = 0; i < 10; i++) {if (i < 0) {retrurn <some_val> // This will be DCE'd}<inner affine loops>}}~ Uday
--
You received this message because you are subscribed to the Google Groups "MLIR" group.
To unsubscribe from this group and stop receiving emails from it, send an email to mlir+uns...@tensorflow.org.
To view this discussion on the web visit https://groups.google.com/a/tensorflow.org/d/msgid/mlir/92ef28a3-5568-42d6-b43c-d2f3911f742d%40tensorflow.org.
To unsubscribe from this group and stop receiving emails from it, send an email to ml...@tensorflow.org.
To view this discussion on the web visit https://groups.google.com/a/tensorflow.org/d/msgid/mlir/92ef28a3-5568-42d6-b43c-d2f3911f742d%40tensorflow.org.
---- Alex
--
~ Uday
You received this message because you are subscribed to the Google Groups "MLIR" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ml...@tensorflow.org.
To view this discussion on the web visit https://groups.google.com/a/tensorflow.org/d/msgid/mlir/fc2476b9-5d2d-48da-a92e-ac48e54b81a4%40tensorflow.org.
---- Alex