Skip to content
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

Merged
merged 16 commits into from
Apr 3, 2024

Conversation

gitoleg
Copy link
Collaborator

@gitoleg gitoleg commented Mar 20, 2024

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:

  1. a new pass called StructuredCFG that is a stub now but later will be responsible for the regions inlining. The pass works only if emit-cir is not passed in cmd line. Thus, the clang behavior is not changed here from the user's point of view.
  2. 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.
  3. new option -emit-flat-cir to dump CIR after all the flattening and structuring and goto-solving.

Copy link

github-actions bot commented Mar 20, 2024

✅ With the latest revision this PR passed the C/C++ code formatter.

Copy link
Member

@bcardosolopes bcardosolopes left a 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

clang/include/clang/CIR/Dialect/Passes.td Outdated Show resolved Hide resolved
clang/include/clang/Driver/Options.td Outdated Show resolved Hide resolved
clang/include/clang/CIRFrontendAction/CIRGenAction.h Outdated Show resolved Hide resolved
clang/include/clang/CIRFrontendAction/CIRGenAction.h Outdated Show resolved Hide resolved
clang/include/clang/Driver/Options.td Outdated Show resolved Hide resolved
clang/lib/CIR/Dialect/Transforms/CIRFlattening.cpp Outdated Show resolved Hide resolved
@@ -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";
Copy link
Member

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.

Copy link
Collaborator Author

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.

Copy link
Member

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.

clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp Outdated Show resolved Hide resolved
clang/lib/Driver/Driver.cpp Outdated Show resolved Hide resolved
clang/lib/CIR/Dialect/Transforms/StructuredCFG.cpp Outdated Show resolved Hide resolved
@bcardosolopes bcardosolopes changed the title [CIR] Flattening prepare [CIR] Introduce a flattening pass Mar 22, 2024
::mlir::registerPass([]() -> std::unique_ptr<::mlir::Pass> {
return cir::direct::createConvertCIRToLLVMPass();
});
mlir::PassPipelineRegistration<mlir::EmptyPipelineOptions> pipeline(
Copy link
Collaborator Author

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

@gitoleg
Copy link
Collaborator Author

gitoleg commented Mar 22, 2024

@bcardosolopes done!

Copy link
Member

@bcardosolopes bcardosolopes left a 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";
Copy link
Member

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.

@bcardosolopes bcardosolopes merged commit 9978d5e into llvm:main Apr 3, 2024
6 checks passed
bcardosolopes pushed a commit that referenced this pull request Apr 15, 2024
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`
@gitoleg gitoleg mentioned this pull request Apr 26, 2024
lanza pushed a commit that referenced this pull request Apr 29, 2024
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.
lanza pushed a commit that referenced this pull request Apr 29, 2024
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`
lanza pushed a commit that referenced this pull request Apr 29, 2024
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.
lanza pushed a commit that referenced this pull request Apr 29, 2024
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`
eZWALT pushed a commit to eZWALT/clangir that referenced this pull request Apr 29, 2024
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.
eZWALT pushed a commit to eZWALT/clangir that referenced this pull request Apr 29, 2024
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`
lanza pushed a commit that referenced this pull request Apr 29, 2024
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.
lanza pushed a commit that referenced this pull request Apr 29, 2024
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`
bruteforceboy pushed a commit to bruteforceboy/clangir that referenced this pull request Oct 2, 2024
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.
bruteforceboy pushed a commit to bruteforceboy/clangir that referenced this pull request Oct 2, 2024
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`
Hugobros3 pushed a commit to shady-gang/clangir that referenced this pull request Oct 2, 2024
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.
Hugobros3 pushed a commit to shady-gang/clangir that referenced this pull request Oct 2, 2024
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`
keryell pushed a commit to keryell/clangir that referenced this pull request Oct 19, 2024
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.
keryell pushed a commit to keryell/clangir that referenced this pull request Oct 19, 2024
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`
lanza pushed a commit that referenced this pull request Nov 5, 2024
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.
lanza pushed a commit that referenced this pull request Nov 5, 2024
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`
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants