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][CIRGen] Support undefined initialization attribute #628

Closed
wants to merge 1,579 commits into from

Conversation

SchrodingerZhu
Copy link
Contributor

This PR adds the capability to initialize Globals with undefined values.

sitio-couto and others added 30 commits January 16, 2024 17:34
Same rationale as `cir.continue`, it detaches the representation of the
C/C++ `break` statement into a separate operation. This simplifies
lowering and verifications related to `break` statements, as well as the
definition and lowering of the `cir.yield` operation.

ghstack-source-id: 929cf96c3abe51d717c2fa6ca9e0073e42e770c6
Pull Request resolved: llvm#395
This changes the `cir.await` operation to expect a `cir.condition` as
the terminator for the ready region. This simplifies the `cir.await`
while also simplifying the `cir.yield`. If `cir.condition` holds a
true value, then the `cir.await` will continue the coroutine, otherwise,
it will suspend its execution.

The `cir.condition` op was also updated to allow `cir.await` as its
parent operation.

ghstack-source-id: 1ebeb2cfbdeff6f289936d16354cba534e093ea7
Pull Request resolved: llvm#396
Instead of having a `cir.yield fallthrough` operation, the default
branching behavior of the parent operation is denoted by `cir.yield`.
In other words, a `cir.yield` operation in a switch case region
represents the default branching behavior of the switch operation, which
is a fallthrough.

The `cir.yield` operation now represents the default branching behavior
of the parent operation's region. For example, in a if-else region, a
`cir.yield` operation represents a branch to the exit block.

ghstack-source-id: 713c457dfb2228fbdf63ba72dd6396665512bb9d
Pull Request resolved: llvm#397
…tcase

- Add cir.try_call parsing.
- Add block destinations and hookup exception info type.
- Properly implement interface methods.

Printer is still missing, but coming next.
After some discussions with @sitio-couto, it might be better if we use a
simplified version that doesn't take the labels into account just yet.
`cir.try_call` should have the same semantics as `cir.break`, in the sense that
it needs further expansion when getting rid of structured control flow. Early
lowering here would complicate CIR generated code and make it harder to
analyse. Further CIR to CIR passes will properly expand this at some point
prior to LLVM lowering.
We can now handle more of EHScope::Catch and lay out the skeleton for CIR's
version of that, adding tons of asserts for cases not currently handled. As
part of this we're able to build the clause list as part of CatchOp based on
the handlers, and create allocation for the exception_info type.

In the next part (where we currently hit an assert) of this work, the CatchOp
will then get its regions populated.

Incremental steps into getting basic exceptions to work, not enough for a
testcase just yet.
Doesn't do a lot of things compared to LLVM traditional codegen, one
more step towards basic exception support. No testcase possible just yet.
- Add an extra CatchOp region to hold fallback (where EH usually resumes or
  rethrows as part of try/catch).
- Emit `cir.resume` on the fallback region.

Incremental step into the next assertion, still missing pieces before adding
the first testcase.
This commit supports the codegen of wide string literals, including
`wchar_t` string literals, `char16_t` string literals, and `char32_t`
string literals.

I'm not following the proposal in llvm#374. The clang frontend doesn't
record the literal string. It only records the encoded code units for
wide string literals. So I believe that a dedicated string attribute
with an encoding tag as described in llvm#374 may not be that helpful as I
thought.
This patch introduces initial support for:
```
pragma omp parallel
```

This patch doesn't add support for any of the `parallel` clauses,
including variable privatization; thus, all variables are handled as
shared.

This PR fixes issue llvm#285.
Adds an interface to generically handle lowering and analysis of loop
operations in CIR. It can also perform verification of invariants common
to all loop operations.

ghstack-source-id: 0e413b14ea063a2b0d75aeaca0af88e547c15277
Pull Request resolved: llvm#405
Leverages the new LoopOpInterface for lowering instead of the LoopOp
operation. This is a step towards removing the LoopOp operation.

ghstack-source-id: 28c1294833a12669d222a293de76609d2cf19148
Pull Request resolved: llvm#406
Creates a separate C/C++ operation for do-while loops, while keeping the
LoopOpInterface to generically handle loops. This simplifies the IR
generation and printing/parsing of do-while loops. It also allows us to
define it regions in the order that they are executed, which is useful
for the lifetime analysis.

ghstack-source-id: b4d9517197b8f82ae677dc2684101fe5762b21b7
Pull Request resolved: llvm#407
Creates a separate C/C++ operation for while loops, while keeping the
LoopOpInterface to generically handle loops. This simplifies the IR
generation and printing/parsing of while loops.

ghstack-source-id: 29a6d7530263a4f96dbe6ce3052875831126005d
Pull Request resolved: llvm#408
This patch completes the deprecation of the generic `cir.loop` operation
by adding a new `cir.for` operation and removing the `cir.loop` op. The
new representation removes some bloat and places the regions in order of
execution.

ghstack-source-id: 886e0dacc632e5809015e2212810d690ef3ec294
Pull Request resolved: llvm#409
…rations

More machinery for exceptions.

This time around we finally emit a cir.catch and fix the order of emitting
operations. This allows a testcase to be added. I also added `CatchParamOp`,
which fetches the arguments for the clauses from the !cir.eh_info object.

Work coming next:
- Dtors.
- Use cir.try instead of cir.scope.
- Eesume.
- Documentation.`
This is currently missing and Debug builds are failing without it.
ghstack-source-id: 855519648a4bf2dced501f96e6de1b9b164d85ad
Pull Request resolved: llvm#424
ghstack-source-id: 0706d6bb81b5b8eefb04146719b4443aedb29ab1
Pull Request resolved: llvm#427
One more step towards completing try/catch.
…rface

This is prep work for introducing cir.try_call inside cir.try scopes.
One more incremental step towards try/catch: properly use cir.try_call instead
of regular cir.call when within a cir.try region.
)

This patch adds a new `volatile` tag to the following operations to
distinguish volatile loads and stores from normal loads and stores:

- `cir.load`
- `cir.store`
- `cir.get_bitfield`
- `cir.set_bitfield`

Besides, this patch also updates the CodeGen and LLVMIR lowering code to
start emitting CIR and LLVMIR operations with volatile flag.
This is part 3 of implementing vector types and vector operations in
ClangIR, issue llvm#284.

Create new operation `cir.vec.cmp` which implements the relational
comparison operators (`== != < > <= >=`) on vector types. A new
operation was created rather than reusing `cir.cmp` because the result
is a vector of a signed intergral type, not a `bool`.

Add CodeGen and Lowering tests for vector comparisons.

Fix the floating-point comparison predicate when lowering to LLVM. To
handle NaN values correctly, the comparisons need to be ordered rather
than unordered. (Except for `!=`, which needs to be unordered.) For
example, "ueq" was changed to "oeq".
Compilation of the following test
```
void foo6(A* a1) {
  A a2 = (*a1);
}
```
fails with.
```
NYI
UNREACHABLE executed at /home/huawei/cir/repo/llvm-project/clang/lib/CIR/CodeGen/CIRGenExprAgg.cpp:175!
```
Commit adds required visitor and fixes the issue.
In the original codegen a new type is created for the base class, while
in CIR we were rewriting the type being processed (due tp misused
pointers). This PR fix this, and also makes CIR codegen even with the
original one.
This is a first PR for variable length array support. There are one (or
more :) ) ahead.

Basically, we already did lot's of preliminary job in order to land VLA
in CIR in llvm#367 llvm#346 llvm#340. So now we add initial VLA support itself.

Most of the changes are taken from the original codegen, so there is
nothing to be scary of)

I added just one test, and basically that's all we can test right now.
Later, I will add more, from the original codegen tests.
seven-mile and others added 19 commits May 17, 2024 21:11
There is [a code
path](https://github.com/llvm/clangir/blob/3da10fafac66ff125fb59c602e41ad4b4f5cb382/clang/lib/CodeGen/CGExpr.cpp#L2190)
missing the counterpart in CIRGen of vector types. When using compound
assignments like `a[0] += a[1]`, this code path is activated and end up
with NYI.
The constant initialization isn't related to the pointee. We should be
able to write #cir.ptr<-1 : i64> : !cir.ptr<whatever>
…pe (llvm#606)

This is the prelude of address space support. Linked issue: llvm#418 .

- Add the attribute and implement asm format & type conversion.
- Make ops like `cir.global` and `cir.get_global` aware of address space, and solve the latter flag.
- Relax the restriction of default alloca address space. Then we can use correct address spaces for languages like OpenCL in future.
…ance without thunk (llvm#569)

This PR adds Vtable support for C++ multiple inheritance without thunk.
This change contains the CIR codegen and lowering work:
1. `VTableAttr` should allow adding multiple `ArrayAttr` for
multi-inheritance.
3. `VTableAddrPointOpLowering` has been fixed for the multi-vtable
during the MLIR lowering phase.
    
Example:
```c++
    class Mother {
      virtual void MotherFoo() {}
      virtual void MotherFoo2() {}
    }
    
    class Father {
      virtual void FatherFoo() {}
    }
    
    class Child : public Mother, public Father {
      void MotherFoo() override {}
    }
```
```mlir
    cir.global linkonce_odr @_ZTV5Child = #cir.vtable<
    {#cir.const_array<[
      #cir.ptr<null> :  #!cir.ptr<!u8i>,
      #cir.global_view<@_ZTI5Child> : !cir.ptr<!u8i>,
      #cir.global_view<@_ZN5Child9MotherFooEv> : !cir.ptr<!u8i>,
      #cir.global_view<@_ZN6Mother10MotherFoo2Ev> : !cir.ptr<!u8i>]> : !cir.array<!cir.ptr<!u8i> x 4>,
     #cir.const_array<[
      #cir.ptr<-8> : !cir.ptr<!u8i>,
      #cir.global_view<@_ZTI5Child> : !cir.ptr<!u8i>,
      #cir.global_view<@_ZN6Father9FatherFooEv> : !cir.ptr<!u8i>]
    > : !cir.array<!cir.ptr<!u8i> x 3>}> : !ty_anon_struct3
```
Move it up for visibility, just like the other dialect headers.
Just mimic the table approach from OG codegen, there are thousands of these,
it's massive! This doesn't add any new feature yet, continues asserting as
before.

Coming next: the plan is to reuse the tablegen generated LLVM intrinsics, and
pass that down to LLVM lowering.
The alignment is still super conversative but proper support should
come next. The added test file also contains a huge pile of builtins
we need to support and should allow for incremental support here.

Next steps: fix alignement and enable testing for other vld1/vst1 variants.
In this PR I added the support for structural bindings in CIR codegen,
to reason `DecompositionDecl` and `BindDecl` properly.

Note that since `ArrayInitLoopExpr` is not implemented so binding to
arrays is not supported yet.
This commit introduces CIRForOpLowering for lowering to scf.

The initial commit only support increment loop with lt or le comparison.
This PR fixes a fail on `llvm_unreachable`  for the next case:
``` 
volatile A vol_a;
A foo7() {
  return vol_a;
}
```
Basically, it's just a copy-pasta from the original `code-gen`. 
Also, I added the `isVolatile` attribute for the `cit.copy` operation
This PR fixes the next bug showed in the example below:
```
typedef int (*fn_t)();
int get42() { return 42; }

void foo() {
  fn_t f = get42;
}
```

The function type `fn_t` is generated as the variadic one due to no arg
types listed, this is the `codegen` feature. And once we store the
function pointer to a real function - a pointer to `get42` here has the
expected `i32 ()*` type - we get a verification error, so `bitcast` is
needed. The original `codegen` doesn't have it because of opaque
pointers used, and had the `bitcast` earlier, long time ago:
```
%f = alloca i32 (...)*
store i32 (...)* bitcast (i32 ()* @GET42 to i32 (...)*), i32 (...)** %f
```
This commit introduces SCFPreparePass to
1) Canonicalize IV to LHS of loop comparison
For example, transfer `cir.cmp(gt, %bound, %IV)` to `cir.cmp(lt, %IV,
%bound)`. So we could use RHS as boundary and use `lt` to determine it's
an upper bound.
2) Hoist loop invariant operations in condition block out of loop.
The condition block may be generated as following which contains the
operations produced upper bound.
SCF for loop required loop boundary as input operands. So we might need
to hoist the boundary operations out of loop.
```
      cir.for : cond {
        %4 = cir.load %2 : !cir.ptr<!s32i>, !s32i
        %5 = cir.const #cir.int<100> : !s32i       <- upper bound
        %6 = cir.cmp(lt, %4, %5) : !s32i, !s32i
        %7 = cir.cast(int_to_bool, %6 : !s32i), !cir.boo
        cir.condition(%7
       } body {
```
Don't hook this up with CIRGen just yet.

While here update parsing tests to include `atomic(seq_cst)`.
…lvm#617)

The patch resolves [issue
llvm#248](llvm#248). It can be considered
a subsequent patch to [llvm#373](llvm#373),
where the case of empty strings was processed.

The new patch adds processing for non-empty strings that may contain
trailing zeros, such as:
```
char big_string[100000] = "123";
```
That is converted to
```
@big_string = #cir.const_array<"123" : !cir.array<!s8i x 3>, trailing_zeros> : !cir.array<!s8i x 100000>
```
@bcardosolopes
Copy link
Member

Thanks for the PR, how's is this different from a global without initializers? Seems like the same functionality to me.

@@ -471,7 +471,7 @@ CIRGenModule::getOrCreateStaticVarDecl(const VarDecl &D,
mlir::Attribute Init = nullptr;
if (Ty.getAddressSpace() == LangAS::opencl_local ||
D.hasAttr<CUDASharedAttr>() || D.hasAttr<LoaderUninitializedAttr>())
llvm_unreachable("OpenCL & CUDA are NYI");
Init = builder.getUndefAttr(getTypes().ConvertType(Ty));
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bcardosolopes I see. On LLVM side, ppl used something like this to setup the __shared__ variables. For the same purpose, can we simply remove this llvm_unreachable and also remove the line that setting the initializer?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That sounds good. Please also add a C/C++ source code test that goes all the way down to LLVM, there are other examples you can look (e.g. clang/test/CIR/CodeGen/atomic.cpp)

@@ -471,7 +471,7 @@ CIRGenModule::getOrCreateStaticVarDecl(const VarDecl &D,
mlir::Attribute Init = nullptr;
if (Ty.getAddressSpace() == LangAS::opencl_local ||
D.hasAttr<CUDASharedAttr>() || D.hasAttr<LoaderUninitializedAttr>())
llvm_unreachable("OpenCL & CUDA are NYI");
Init = builder.getUndefAttr(getTypes().ConvertType(Ty));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That sounds good. Please also add a C/C++ source code test that goes all the way down to LLVM, there are other examples you can look (e.g. clang/test/CIR/CodeGen/atomic.cpp)

@bcardosolopes bcardosolopes changed the title [clang][CIR] support undefined initialization attribute [CIR][CIRGen] Support undefined initialization attribute May 24, 2024
@bcardosolopes
Copy link
Member

Btw, it's possible we might need an undef attribute someday, but up to now we should be good without one!

@bcardosolopes
Copy link
Member

@SchrodingerZhu do you plan to resume the work for this PR or should I close for the moment?

@SchrodingerZhu
Copy link
Contributor Author

I may not be able to continue on this for now due to conflict. Please close this for now. Thanks!

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.