-
Notifications
You must be signed in to change notification settings - Fork 100
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[CIR] Introduce a flattening pass #516
Conversation
✅ With the latest revision this PR passed the C/C++ code formatter. |
8b680a2
to
4a1a234
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Awesome, mostly nitpicks comments
@@ -916,7 +917,9 @@ struct ConvertCIRToLLVMPass | |||
} | |||
void runOnOperation() final; | |||
|
|||
virtual StringRef getArgument() const override { return "cir-to-llvm"; } | |||
virtual StringRef getArgument() const override { | |||
return "cir-to-llvm-internal"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what does internal
means? I don't understand why this needs to be renamed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
internal
here is a hint that this pass can't be run with any CIR input like it was before. Now the pre requirement is our new cir-flatten-cfg
pass. I would deprecate createConvertCIRToLLVMPass
of even remove it from the interface, but it;s up to you to decide.
And the pass need to be renamed since we register a pipeline in cir-opt
with the same name - in order to guarantee any cir input is stiil valid as it was earlier - i.e. that first it will be processed by cir-flatten-cfg
pass and then will go to the lowering.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would deprecate createConvertCIRToLLVMPass of even remove it from the interface, but it;s up to you to decide.
I'm down for simplifying and unifying as much as possible, but can you address it in a follow up PR.
internal here is a hint that this pass can't be run with any CIR input like it was before. Now the pre requirement is our new cir-flatten-cfg pass
Perhaps it should be named cir-flat-to-llvm
, or something like that.
Since it would be wrong to run cir-flat-to-llvm
without running cir-flatten-cfg
, we should make cir-flat-to-llvm
pass to require cir-flatten-cfg
pass to be run before.
Seems like all the changes for this comment should be addressed together in another PR.
::mlir::registerPass([]() -> std::unique_ptr<::mlir::Pass> { | ||
return cir::direct::createConvertCIRToLLVMPass(); | ||
}); | ||
mlir::PassPipelineRegistration<mlir::EmptyPipelineOptions> pipeline( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
here we register the pipeline with the name cir-to-llvm
. So we need to rename the pass in LowerToLLVM.cpp
- otherwise we wouldn't be able to run either of them due to name conflict
@bcardosolopes done! |
7bf2c8f
to
c9c262e
Compare
c9c262e
to
5a876d9
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM.
Awesome, I have a few requests for change, but they should come in another PR (see my inline comments). I'm gonna go ahead and merge this.
@@ -916,7 +917,9 @@ struct ConvertCIRToLLVMPass | |||
} | |||
void runOnOperation() final; | |||
|
|||
virtual StringRef getArgument() const override { return "cir-to-llvm"; } | |||
virtual StringRef getArgument() const override { | |||
return "cir-to-llvm-internal"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would deprecate createConvertCIRToLLVMPass of even remove it from the interface, but it;s up to you to decide.
I'm down for simplifying and unifying as much as possible, but can you address it in a follow up PR.
internal here is a hint that this pass can't be run with any CIR input like it was before. Now the pre requirement is our new cir-flatten-cfg pass
Perhaps it should be named cir-flat-to-llvm
, or something like that.
Since it would be wrong to run cir-flat-to-llvm
without running cir-flatten-cfg
, we should make cir-flat-to-llvm
pass to require cir-flatten-cfg
pass to be run before.
Seems like all the changes for this comment should be addressed together in another PR.
This PR perform flattening for `cir::IfOp` Basically, we just move the code from `LowerToLLVM.cpp` to `FlattenCFG.cpp`. There are several important things though I would like to highlight. 1) Consider the next code from the tests: ``` cir.func @foo(%arg0: !s32i) -> !s32i { %4 = cir.cast(int_to_bool, %arg0 : !s32i), !cir.bool cir.if %4 { %5 = cir.const(#cir.int<1> : !s32i) : !s32i cir.return %5 : !s32i } else { %5 = cir.const(#cir.int<0> : !s32i) : !s32i cir.return %5 : !s32i } cir.return %arg0 : !s32i } ``` The last `cir.return` becomes unreachable after flattening and hence is not reachable in the lowering. So we got the next error: ``` error: 'cir.return' op expects parent op to be one of 'cir.func, cir.scope, cir.if, cir.switch, cir.do, cir.while, cir.for' cir.return %arg0 : !s32i ``` the parent after lowering is `llvm.func`. And this is only the beginning - the more operations will be flatten, the more similar fails will happen. Thus, I added lowering for the unreachable code as well in `LowerToLLVM.cpp`. But may be you have another solution in your mind. 2) Please, pay attention on the flattening pass - I'm not that familiar with `mlir` builders as you are, so may be I'm doing something wrong. The idea was to start flattening from the most nested operations. 3) As you requested in #516, `cir-to-llvm-internal` is renamed to `cir-flat-to-llvm`. The only thing remain undone is related to the following: > Since it would be wrong to run cir-flat-to-llvm without running cir-flatten-cfg, we should make cir-flat-to-llvm pass to require cir-flatten-cfg pass to be run before. And I'm not sure I know how to do it exactly - is there something similar to pass dependencies from LLVM IR? 4) The part of `IfOp` lowering related to elimination of the vain casts for condition branch moved directly to the lowering of `BrCondOp` with some refactoring and guarding. 5) Just note, that now `cir-opt` is able to dump the flat cir as well: `cir-opt -cir-flat-cfg`
We start our journey towards `goto` support and this is a first step on this way. There are some discussion in #508 and according to the plan we do the following here: - a new pass called `cir-flatten-cfg` that is a stub now but later will be responsible for the regions inlining. The pass works only if `-emit-flat-cir` is passed in cmd line. Thus, the clang behavior is not changed here from the user's point of view. - The pass will be accomplished with `goto` solver later, so we talk about several passes that are mandatory for the lowering into `llvm` dialect. There are at least two clients of this pass that will be affected: `clang` itself and `cir-opt`, so we need a common point for them: and `populateCIRFlatteningPasses` and `populateCIRToLLVMPasses` guarantee that `CIR` will be in the correct state for all the clients, whatever new passes we will add later.
This PR perform flattening for `cir::IfOp` Basically, we just move the code from `LowerToLLVM.cpp` to `FlattenCFG.cpp`. There are several important things though I would like to highlight. 1) Consider the next code from the tests: ``` cir.func @foo(%arg0: !s32i) -> !s32i { %4 = cir.cast(int_to_bool, %arg0 : !s32i), !cir.bool cir.if %4 { %5 = cir.const(#cir.int<1> : !s32i) : !s32i cir.return %5 : !s32i } else { %5 = cir.const(#cir.int<0> : !s32i) : !s32i cir.return %5 : !s32i } cir.return %arg0 : !s32i } ``` The last `cir.return` becomes unreachable after flattening and hence is not reachable in the lowering. So we got the next error: ``` error: 'cir.return' op expects parent op to be one of 'cir.func, cir.scope, cir.if, cir.switch, cir.do, cir.while, cir.for' cir.return %arg0 : !s32i ``` the parent after lowering is `llvm.func`. And this is only the beginning - the more operations will be flatten, the more similar fails will happen. Thus, I added lowering for the unreachable code as well in `LowerToLLVM.cpp`. But may be you have another solution in your mind. 2) Please, pay attention on the flattening pass - I'm not that familiar with `mlir` builders as you are, so may be I'm doing something wrong. The idea was to start flattening from the most nested operations. 3) As you requested in #516, `cir-to-llvm-internal` is renamed to `cir-flat-to-llvm`. The only thing remain undone is related to the following: > Since it would be wrong to run cir-flat-to-llvm without running cir-flatten-cfg, we should make cir-flat-to-llvm pass to require cir-flatten-cfg pass to be run before. And I'm not sure I know how to do it exactly - is there something similar to pass dependencies from LLVM IR? 4) The part of `IfOp` lowering related to elimination of the vain casts for condition branch moved directly to the lowering of `BrCondOp` with some refactoring and guarding. 5) Just note, that now `cir-opt` is able to dump the flat cir as well: `cir-opt -cir-flat-cfg`
We start our journey towards `goto` support and this is a first step on this way. There are some discussion in #508 and according to the plan we do the following here: - a new pass called `cir-flatten-cfg` that is a stub now but later will be responsible for the regions inlining. The pass works only if `-emit-flat-cir` is passed in cmd line. Thus, the clang behavior is not changed here from the user's point of view. - The pass will be accomplished with `goto` solver later, so we talk about several passes that are mandatory for the lowering into `llvm` dialect. There are at least two clients of this pass that will be affected: `clang` itself and `cir-opt`, so we need a common point for them: and `populateCIRFlatteningPasses` and `populateCIRToLLVMPasses` guarantee that `CIR` will be in the correct state for all the clients, whatever new passes we will add later.
This PR perform flattening for `cir::IfOp` Basically, we just move the code from `LowerToLLVM.cpp` to `FlattenCFG.cpp`. There are several important things though I would like to highlight. 1) Consider the next code from the tests: ``` cir.func @foo(%arg0: !s32i) -> !s32i { %4 = cir.cast(int_to_bool, %arg0 : !s32i), !cir.bool cir.if %4 { %5 = cir.const(#cir.int<1> : !s32i) : !s32i cir.return %5 : !s32i } else { %5 = cir.const(#cir.int<0> : !s32i) : !s32i cir.return %5 : !s32i } cir.return %arg0 : !s32i } ``` The last `cir.return` becomes unreachable after flattening and hence is not reachable in the lowering. So we got the next error: ``` error: 'cir.return' op expects parent op to be one of 'cir.func, cir.scope, cir.if, cir.switch, cir.do, cir.while, cir.for' cir.return %arg0 : !s32i ``` the parent after lowering is `llvm.func`. And this is only the beginning - the more operations will be flatten, the more similar fails will happen. Thus, I added lowering for the unreachable code as well in `LowerToLLVM.cpp`. But may be you have another solution in your mind. 2) Please, pay attention on the flattening pass - I'm not that familiar with `mlir` builders as you are, so may be I'm doing something wrong. The idea was to start flattening from the most nested operations. 3) As you requested in #516, `cir-to-llvm-internal` is renamed to `cir-flat-to-llvm`. The only thing remain undone is related to the following: > Since it would be wrong to run cir-flat-to-llvm without running cir-flatten-cfg, we should make cir-flat-to-llvm pass to require cir-flatten-cfg pass to be run before. And I'm not sure I know how to do it exactly - is there something similar to pass dependencies from LLVM IR? 4) The part of `IfOp` lowering related to elimination of the vain casts for condition branch moved directly to the lowering of `BrCondOp` with some refactoring and guarding. 5) Just note, that now `cir-opt` is able to dump the flat cir as well: `cir-opt -cir-flat-cfg`
We start our journey towards `goto` support and this is a first step on this way. There are some discussion in llvm#508 and according to the plan we do the following here: - a new pass called `cir-flatten-cfg` that is a stub now but later will be responsible for the regions inlining. The pass works only if `-emit-flat-cir` is passed in cmd line. Thus, the clang behavior is not changed here from the user's point of view. - The pass will be accomplished with `goto` solver later, so we talk about several passes that are mandatory for the lowering into `llvm` dialect. There are at least two clients of this pass that will be affected: `clang` itself and `cir-opt`, so we need a common point for them: and `populateCIRFlatteningPasses` and `populateCIRToLLVMPasses` guarantee that `CIR` will be in the correct state for all the clients, whatever new passes we will add later.
This PR perform flattening for `cir::IfOp` Basically, we just move the code from `LowerToLLVM.cpp` to `FlattenCFG.cpp`. There are several important things though I would like to highlight. 1) Consider the next code from the tests: ``` cir.func @foo(%arg0: !s32i) -> !s32i { %4 = cir.cast(int_to_bool, %arg0 : !s32i), !cir.bool cir.if %4 { %5 = cir.const(#cir.int<1> : !s32i) : !s32i cir.return %5 : !s32i } else { %5 = cir.const(#cir.int<0> : !s32i) : !s32i cir.return %5 : !s32i } cir.return %arg0 : !s32i } ``` The last `cir.return` becomes unreachable after flattening and hence is not reachable in the lowering. So we got the next error: ``` error: 'cir.return' op expects parent op to be one of 'cir.func, cir.scope, cir.if, cir.switch, cir.do, cir.while, cir.for' cir.return %arg0 : !s32i ``` the parent after lowering is `llvm.func`. And this is only the beginning - the more operations will be flatten, the more similar fails will happen. Thus, I added lowering for the unreachable code as well in `LowerToLLVM.cpp`. But may be you have another solution in your mind. 2) Please, pay attention on the flattening pass - I'm not that familiar with `mlir` builders as you are, so may be I'm doing something wrong. The idea was to start flattening from the most nested operations. 3) As you requested in llvm#516, `cir-to-llvm-internal` is renamed to `cir-flat-to-llvm`. The only thing remain undone is related to the following: > Since it would be wrong to run cir-flat-to-llvm without running cir-flatten-cfg, we should make cir-flat-to-llvm pass to require cir-flatten-cfg pass to be run before. And I'm not sure I know how to do it exactly - is there something similar to pass dependencies from LLVM IR? 4) The part of `IfOp` lowering related to elimination of the vain casts for condition branch moved directly to the lowering of `BrCondOp` with some refactoring and guarding. 5) Just note, that now `cir-opt` is able to dump the flat cir as well: `cir-opt -cir-flat-cfg`
We start our journey towards `goto` support and this is a first step on this way. There are some discussion in #508 and according to the plan we do the following here: - a new pass called `cir-flatten-cfg` that is a stub now but later will be responsible for the regions inlining. The pass works only if `-emit-flat-cir` is passed in cmd line. Thus, the clang behavior is not changed here from the user's point of view. - The pass will be accomplished with `goto` solver later, so we talk about several passes that are mandatory for the lowering into `llvm` dialect. There are at least two clients of this pass that will be affected: `clang` itself and `cir-opt`, so we need a common point for them: and `populateCIRFlatteningPasses` and `populateCIRToLLVMPasses` guarantee that `CIR` will be in the correct state for all the clients, whatever new passes we will add later.
This PR perform flattening for `cir::IfOp` Basically, we just move the code from `LowerToLLVM.cpp` to `FlattenCFG.cpp`. There are several important things though I would like to highlight. 1) Consider the next code from the tests: ``` cir.func @foo(%arg0: !s32i) -> !s32i { %4 = cir.cast(int_to_bool, %arg0 : !s32i), !cir.bool cir.if %4 { %5 = cir.const(#cir.int<1> : !s32i) : !s32i cir.return %5 : !s32i } else { %5 = cir.const(#cir.int<0> : !s32i) : !s32i cir.return %5 : !s32i } cir.return %arg0 : !s32i } ``` The last `cir.return` becomes unreachable after flattening and hence is not reachable in the lowering. So we got the next error: ``` error: 'cir.return' op expects parent op to be one of 'cir.func, cir.scope, cir.if, cir.switch, cir.do, cir.while, cir.for' cir.return %arg0 : !s32i ``` the parent after lowering is `llvm.func`. And this is only the beginning - the more operations will be flatten, the more similar fails will happen. Thus, I added lowering for the unreachable code as well in `LowerToLLVM.cpp`. But may be you have another solution in your mind. 2) Please, pay attention on the flattening pass - I'm not that familiar with `mlir` builders as you are, so may be I'm doing something wrong. The idea was to start flattening from the most nested operations. 3) As you requested in #516, `cir-to-llvm-internal` is renamed to `cir-flat-to-llvm`. The only thing remain undone is related to the following: > Since it would be wrong to run cir-flat-to-llvm without running cir-flatten-cfg, we should make cir-flat-to-llvm pass to require cir-flatten-cfg pass to be run before. And I'm not sure I know how to do it exactly - is there something similar to pass dependencies from LLVM IR? 4) The part of `IfOp` lowering related to elimination of the vain casts for condition branch moved directly to the lowering of `BrCondOp` with some refactoring and guarding. 5) Just note, that now `cir-opt` is able to dump the flat cir as well: `cir-opt -cir-flat-cfg`
We start our journey towards `goto` support and this is a first step on this way. There are some discussion in llvm#508 and according to the plan we do the following here: - a new pass called `cir-flatten-cfg` that is a stub now but later will be responsible for the regions inlining. The pass works only if `-emit-flat-cir` is passed in cmd line. Thus, the clang behavior is not changed here from the user's point of view. - The pass will be accomplished with `goto` solver later, so we talk about several passes that are mandatory for the lowering into `llvm` dialect. There are at least two clients of this pass that will be affected: `clang` itself and `cir-opt`, so we need a common point for them: and `populateCIRFlatteningPasses` and `populateCIRToLLVMPasses` guarantee that `CIR` will be in the correct state for all the clients, whatever new passes we will add later.
This PR perform flattening for `cir::IfOp` Basically, we just move the code from `LowerToLLVM.cpp` to `FlattenCFG.cpp`. There are several important things though I would like to highlight. 1) Consider the next code from the tests: ``` cir.func @foo(%arg0: !s32i) -> !s32i { %4 = cir.cast(int_to_bool, %arg0 : !s32i), !cir.bool cir.if %4 { %5 = cir.const(#cir.int<1> : !s32i) : !s32i cir.return %5 : !s32i } else { %5 = cir.const(#cir.int<0> : !s32i) : !s32i cir.return %5 : !s32i } cir.return %arg0 : !s32i } ``` The last `cir.return` becomes unreachable after flattening and hence is not reachable in the lowering. So we got the next error: ``` error: 'cir.return' op expects parent op to be one of 'cir.func, cir.scope, cir.if, cir.switch, cir.do, cir.while, cir.for' cir.return %arg0 : !s32i ``` the parent after lowering is `llvm.func`. And this is only the beginning - the more operations will be flatten, the more similar fails will happen. Thus, I added lowering for the unreachable code as well in `LowerToLLVM.cpp`. But may be you have another solution in your mind. 2) Please, pay attention on the flattening pass - I'm not that familiar with `mlir` builders as you are, so may be I'm doing something wrong. The idea was to start flattening from the most nested operations. 3) As you requested in llvm#516, `cir-to-llvm-internal` is renamed to `cir-flat-to-llvm`. The only thing remain undone is related to the following: > Since it would be wrong to run cir-flat-to-llvm without running cir-flatten-cfg, we should make cir-flat-to-llvm pass to require cir-flatten-cfg pass to be run before. And I'm not sure I know how to do it exactly - is there something similar to pass dependencies from LLVM IR? 4) The part of `IfOp` lowering related to elimination of the vain casts for condition branch moved directly to the lowering of `BrCondOp` with some refactoring and guarding. 5) Just note, that now `cir-opt` is able to dump the flat cir as well: `cir-opt -cir-flat-cfg`
We start our journey towards `goto` support and this is a first step on this way. There are some discussion in llvm#508 and according to the plan we do the following here: - a new pass called `cir-flatten-cfg` that is a stub now but later will be responsible for the regions inlining. The pass works only if `-emit-flat-cir` is passed in cmd line. Thus, the clang behavior is not changed here from the user's point of view. - The pass will be accomplished with `goto` solver later, so we talk about several passes that are mandatory for the lowering into `llvm` dialect. There are at least two clients of this pass that will be affected: `clang` itself and `cir-opt`, so we need a common point for them: and `populateCIRFlatteningPasses` and `populateCIRToLLVMPasses` guarantee that `CIR` will be in the correct state for all the clients, whatever new passes we will add later.
This PR perform flattening for `cir::IfOp` Basically, we just move the code from `LowerToLLVM.cpp` to `FlattenCFG.cpp`. There are several important things though I would like to highlight. 1) Consider the next code from the tests: ``` cir.func @foo(%arg0: !s32i) -> !s32i { %4 = cir.cast(int_to_bool, %arg0 : !s32i), !cir.bool cir.if %4 { %5 = cir.const(#cir.int<1> : !s32i) : !s32i cir.return %5 : !s32i } else { %5 = cir.const(#cir.int<0> : !s32i) : !s32i cir.return %5 : !s32i } cir.return %arg0 : !s32i } ``` The last `cir.return` becomes unreachable after flattening and hence is not reachable in the lowering. So we got the next error: ``` error: 'cir.return' op expects parent op to be one of 'cir.func, cir.scope, cir.if, cir.switch, cir.do, cir.while, cir.for' cir.return %arg0 : !s32i ``` the parent after lowering is `llvm.func`. And this is only the beginning - the more operations will be flatten, the more similar fails will happen. Thus, I added lowering for the unreachable code as well in `LowerToLLVM.cpp`. But may be you have another solution in your mind. 2) Please, pay attention on the flattening pass - I'm not that familiar with `mlir` builders as you are, so may be I'm doing something wrong. The idea was to start flattening from the most nested operations. 3) As you requested in llvm#516, `cir-to-llvm-internal` is renamed to `cir-flat-to-llvm`. The only thing remain undone is related to the following: > Since it would be wrong to run cir-flat-to-llvm without running cir-flatten-cfg, we should make cir-flat-to-llvm pass to require cir-flatten-cfg pass to be run before. And I'm not sure I know how to do it exactly - is there something similar to pass dependencies from LLVM IR? 4) The part of `IfOp` lowering related to elimination of the vain casts for condition branch moved directly to the lowering of `BrCondOp` with some refactoring and guarding. 5) Just note, that now `cir-opt` is able to dump the flat cir as well: `cir-opt -cir-flat-cfg`
We start our journey towards `goto` support and this is a first step on this way. There are some discussion in llvm#508 and according to the plan we do the following here: - a new pass called `cir-flatten-cfg` that is a stub now but later will be responsible for the regions inlining. The pass works only if `-emit-flat-cir` is passed in cmd line. Thus, the clang behavior is not changed here from the user's point of view. - The pass will be accomplished with `goto` solver later, so we talk about several passes that are mandatory for the lowering into `llvm` dialect. There are at least two clients of this pass that will be affected: `clang` itself and `cir-opt`, so we need a common point for them: and `populateCIRFlatteningPasses` and `populateCIRToLLVMPasses` guarantee that `CIR` will be in the correct state for all the clients, whatever new passes we will add later.
This PR perform flattening for `cir::IfOp` Basically, we just move the code from `LowerToLLVM.cpp` to `FlattenCFG.cpp`. There are several important things though I would like to highlight. 1) Consider the next code from the tests: ``` cir.func @foo(%arg0: !s32i) -> !s32i { %4 = cir.cast(int_to_bool, %arg0 : !s32i), !cir.bool cir.if %4 { %5 = cir.const(#cir.int<1> : !s32i) : !s32i cir.return %5 : !s32i } else { %5 = cir.const(#cir.int<0> : !s32i) : !s32i cir.return %5 : !s32i } cir.return %arg0 : !s32i } ``` The last `cir.return` becomes unreachable after flattening and hence is not reachable in the lowering. So we got the next error: ``` error: 'cir.return' op expects parent op to be one of 'cir.func, cir.scope, cir.if, cir.switch, cir.do, cir.while, cir.for' cir.return %arg0 : !s32i ``` the parent after lowering is `llvm.func`. And this is only the beginning - the more operations will be flatten, the more similar fails will happen. Thus, I added lowering for the unreachable code as well in `LowerToLLVM.cpp`. But may be you have another solution in your mind. 2) Please, pay attention on the flattening pass - I'm not that familiar with `mlir` builders as you are, so may be I'm doing something wrong. The idea was to start flattening from the most nested operations. 3) As you requested in llvm#516, `cir-to-llvm-internal` is renamed to `cir-flat-to-llvm`. The only thing remain undone is related to the following: > Since it would be wrong to run cir-flat-to-llvm without running cir-flatten-cfg, we should make cir-flat-to-llvm pass to require cir-flatten-cfg pass to be run before. And I'm not sure I know how to do it exactly - is there something similar to pass dependencies from LLVM IR? 4) The part of `IfOp` lowering related to elimination of the vain casts for condition branch moved directly to the lowering of `BrCondOp` with some refactoring and guarding. 5) Just note, that now `cir-opt` is able to dump the flat cir as well: `cir-opt -cir-flat-cfg`
We start our journey towards `goto` support and this is a first step on this way. There are some discussion in #508 and according to the plan we do the following here: - a new pass called `cir-flatten-cfg` that is a stub now but later will be responsible for the regions inlining. The pass works only if `-emit-flat-cir` is passed in cmd line. Thus, the clang behavior is not changed here from the user's point of view. - The pass will be accomplished with `goto` solver later, so we talk about several passes that are mandatory for the lowering into `llvm` dialect. There are at least two clients of this pass that will be affected: `clang` itself and `cir-opt`, so we need a common point for them: and `populateCIRFlatteningPasses` and `populateCIRToLLVMPasses` guarantee that `CIR` will be in the correct state for all the clients, whatever new passes we will add later.
This PR perform flattening for `cir::IfOp` Basically, we just move the code from `LowerToLLVM.cpp` to `FlattenCFG.cpp`. There are several important things though I would like to highlight. 1) Consider the next code from the tests: ``` cir.func @foo(%arg0: !s32i) -> !s32i { %4 = cir.cast(int_to_bool, %arg0 : !s32i), !cir.bool cir.if %4 { %5 = cir.const(#cir.int<1> : !s32i) : !s32i cir.return %5 : !s32i } else { %5 = cir.const(#cir.int<0> : !s32i) : !s32i cir.return %5 : !s32i } cir.return %arg0 : !s32i } ``` The last `cir.return` becomes unreachable after flattening and hence is not reachable in the lowering. So we got the next error: ``` error: 'cir.return' op expects parent op to be one of 'cir.func, cir.scope, cir.if, cir.switch, cir.do, cir.while, cir.for' cir.return %arg0 : !s32i ``` the parent after lowering is `llvm.func`. And this is only the beginning - the more operations will be flatten, the more similar fails will happen. Thus, I added lowering for the unreachable code as well in `LowerToLLVM.cpp`. But may be you have another solution in your mind. 2) Please, pay attention on the flattening pass - I'm not that familiar with `mlir` builders as you are, so may be I'm doing something wrong. The idea was to start flattening from the most nested operations. 3) As you requested in #516, `cir-to-llvm-internal` is renamed to `cir-flat-to-llvm`. The only thing remain undone is related to the following: > Since it would be wrong to run cir-flat-to-llvm without running cir-flatten-cfg, we should make cir-flat-to-llvm pass to require cir-flatten-cfg pass to be run before. And I'm not sure I know how to do it exactly - is there something similar to pass dependencies from LLVM IR? 4) The part of `IfOp` lowering related to elimination of the vain casts for condition branch moved directly to the lowering of `BrCondOp` with some refactoring and guarding. 5) Just note, that now `cir-opt` is able to dump the flat cir as well: `cir-opt -cir-flat-cfg`
We start our journey towards
goto
support and this is a first step on this way.There are some discussion in #508 and according to the plan we do the following here:
StructuredCFG
that is a stub now but later will be responsible for the regions inlining. The pass works only ifemit-cir
is not passed in cmd line. Thus, the clang behavior is not changed here from the user's point of view.goto
solver later, so we talk about several passes that are mandatory for the lowering intollvm
dialect. There are at least two clients of this pass that will be affected:clang
itself andcir-opt
, so we need a common point for them: andpopulateCIRFlatteningPasses
andpopulateCIRToLLVMPasses
guarantee thatCIR
will be in the correct state for all the clients, whatever new passes we will add later.-emit-flat-cir
to dump CIR after all the flattening and structuring and goto-solving.