[RFC] Upstreaming ClangIR

Hi Chuanqi,

Then, the question may be, what if the plan when the ClangIR is proven? Just out of curiosity, not blocking questions.

At that point one idea is to put a transition plan in place. This could imply changing policy to require changes to go to both pipelines until we could flip a switch. These things take a while to converge though (the new pass manager and GlobalISel are probably good references), so we won’t introduce additional burden in the meantime.

Yeah, they are really similar. But the similar codes are the enemy of SE in my mind.

I guess it depends on what you are trying to achieve. It has been helpful to track unimplemented features, and ease up the barrier to entry (from what I’ve seen by reviewing PRs). And above all, following CodeGen’s skeleton has guided us to handling corner cases extremely well crafted over the past decade. Since there’s still a lot to be done in the project I feel like we gain more by sticking to this. Note that this doesn’t preclude some parts to be factored out, use more modern C++ features, etc – we do that to the extent that makes sense.

I feel the current framework for serializing AST may not be good to be reused for ClangIR.

Let me clarify this one. In CIR operations can hold references to AST nodes. Right now, when we dump CIR to disk (serialization or printing) we lack a way to restore AST information when we load CIR from disk (deserialization or parsing). Instead of reinventing the wheel what I’m suggesting is that the AST is serialized in a separate file, just like a .pcm or .pch. The file containing CIR will contain descriptions on how to obtain these AST nodes back. The AST nodes are finally retrieved by using those descriptions and looking inside the “pch-like” file (mechanisms already available in clang).

(Or I don’t know how can that be.) In my mind, the serialization for ClangIR should be more like the serialization of LLVM IR. Or if there is a serialization framework for MLIR, can we reuse that?

Sure, MLIR does have a bytecode format that you can read about here: MLIR Bytecode Format - MLIR.

Good insight. And maybe CIR needs some additional work to handle modules. Otherwise the analysis may be not efficient. I mean we probably don’t want the CIR to analyze the codes imported from other TUs. But this should be minor points.

Yes, some exploratory work would be necessary.

BTW, I like the idea of ClangIR due to some experience in coroutines in LLVM.
Some semantics of C++20 coroutines (like symmetric transfer, coroutine elision, exception handlings) are implemented in LLVM. This is not good. It breaks the design idea of LLVM to be a low level compiler component in some level. But with the introduction of ClangIR, maybe it is possible to move some of C++20 Coroutines specific implementations to ClangIR, and only leave the general coroutines semantics in LLVM Coroutines intrinsics.

Right on point, the way coroutines work is one of the biggest motivations. Having a CIR representation could also allow us to experiment with different LLVM lowerings (e.g. returned continuation) or apply optimizations at the CIR level (e.g. eliminate some coawait logic when init ready never suspends)

Hi Bruno,

It sounds good to me overall.

But I am still a little bit confused about the CodeGen part. I know it is somehow frustrated since you explained several times. But all your answers look like “oh, we won’t bring troubles to you”. But it sounds odd since (I believe) the clangIR is expected to be part of clang naturally if the RFC got approved. And what I am confusing or curious is, what will it be in the end of the day. I saw you said it is too far to give a roadmap here. But we still need some feelings about the future. For example, I’ll feel more natural if we can make clang ir enabled by default some day, then the pipeline of ClangIR to LLVMIR becomes the default pipeline and the existing AST to LLVMIR CodeGen part becomes a legacy part.

I know it is hard and I am not asking for a promise. I just feel weird that we have two similar components doing the same thing. In my memory, we always try to merge such things like the new PassManager and the legacy manager.

3 Likes

@ChuanqiXu

I think I know what you’re saying, and the two of you are talking past each other so please let me try to clarify!

Once work starts here, there will be 3 periods of time:

1- ClangIR under development: During this time the ClangIR developers will be doing ‘all the work’, and the rest of us are expected to just use LLVM-IR codegen as normal. They are going to use the work done in LLVM-IR codegen to help them track how far they have gone, but will be solely responsible for ClangIR. This period is expected to to take a significant amount of time. (This is similar to where the new Constexpr evaluator is!)

2- ClangIR Transition Time: This is NOT currently being proposed, but is an eventuality. Once the team has sufficient evidence to believe ClangIR is ready to replace LLVM-IR-codegen, they will publish an additional RFC and ‘figure out’ how long we’ll have to maintain parallel development. I suspect we’ll have a period where both are necessary, somewhere in timeframe between Opaque Pointers and the New Pass Manager. During this time, everyone will be responsible for ensuring changes to codegen happen in both.

3- ClangIR is primary, LLVM-IR CodeGen is deprecated. During this period all active development will be on ClangIR codegen, and we will keep that LLVM-IR codegen in that weird ‘not particularly maintained, but the code is still there’ state for a while.

Does this answer the question you’re asking? Or is there something more subtle to your posts that I missed?

6 Likes

Yes, this is what I am asking. Thanks : )

2 Likes

Thanks @erichkeane, perfect answer. :slight_smile:

1 Like

Thanks for the clarification @erichkeane, well done. @ChuanqiXu, you bring good questions, let us know if you have more!

2 Likes

No more from me. Everything looks good for me from the higher level. Looking forward to the code review : )

1 Like

Do we have an idea of how long it will take to get to the ClangIR Transition Time?

Do we have an idea of how long it will take to get to the ClangIR Transition Time?

It won’t be this year for sure. It’s reasonable that next year sees feasibility for some use cases, but it’s hard to predict that far ahead. I think we’ll aim for some status updates around what the plan is for 2025 during this year’s conference.

Thank you for this RFC! I’m in support of starting to upstream this into mainline Clang and I appreciate all the efforts of those involved in the project. I have some questions/concerns but none of them should block the upstreaming efforts.

A big concern I have is the eventual impact on resources required for building the project. I think LLVM and Clang have a reputation for being unfriendly for contributors due to resource requirements to build the project already today. So a 45% increase in build times may push people to avoid contributing to our project. It would be great if we could find ways to make this less of an impact before we flip the switch to enable building Clang with CIR by default.

A question I have is how well CIR handles source location fidelity as transformations happen. e.g., we issue some diagnostics from codegen already today and I want to make sure those diagnostics will still show up on the relevant lines in source even if there are transformations applied. We run into problems with this in LLVM IR already today and I don’t expect CIR to improve that situation, I’m more just making sure it doesn’t make anything worse. Note: it might be interesting to make sure that diagnostics we currently emit from CodeGen are also emitted by CIR, are we planning for 1:1 mapping for those? (e.g. llvm-project/clang/lib/CodeGen/CGStmt.cpp at fa42589fe31924b6176d7a92691c2f760b04ffd8 · llvm/llvm-project · GitHub)

Another question is with regards to ABI decisions. We currently have a rather awkward dance between Clang and LLVM where Clang is responsible for some aspects of ABI and LLVM is responsible for other aspects (think: calling convention parameter passing, structure layout, etc). Does CIR improve this situation?

Will there be a post-commit build bot which tests CIR? If so, what should the policy be regarding breaking that bot, especially in terms of reverts? e.g., if someone is working on a new feature that (correctly) changes an existing AST representation somewhat and that induces some sort of crash or misbehavior in CIR, is that grounds for a revert?

2 Likes

Thank you for this RFC! I’m in support of starting to upstream this into mainline Clang and I appreciate all the efforts of those involved in the project. I have some questions/concerns but none of them should block the upstreaming efforts.

Thanks for the feedback Aaron!

A big concern I have is the eventual impact on resources required for building the project. I think LLVM and Clang have a reputation for being unfriendly for contributors due to resource requirements to build the project already today. So a 45% increase in build times may push people to avoid contributing to our project. It would be great if we could find ways to make this less of an impact before we flip the switch to enable building Clang with CIR by default.

+1, I believe it wouldn’t be feasible to ever flip the switch without proper compile time due diligence and improvements.

A question I have is how well CIR handles source location fidelity as transformations happen. e.g., we issue some diagnostics from codegen already today and I want to make sure those diagnostics will still show up on the relevant lines in source even if there are transformations applied. We run into problems with this in LLVM IR already today and I don’t expect CIR to improve that situation, I’m more just making sure it doesn’t make anything worse. Note: it might be interesting to make sure that diagnostics we currently emit from CodeGen are also emitted by CIR, are we planning for 1:1 mapping for those? (e.g. llvm-project/clang/lib/CodeGen/CGStmt.cpp at fa42589fe31924b6176d7a92691c2f760b04ffd8 · llvm/llvm-project · GitHub 1)

This is a good point, thanks for bringing it up. We’re structurally following codegen as close as possible and many of the diagnostics emitted in that process should be directly applicable. E.g. We already have 8 instances of diag:: in CIRGen that match their purpose in CodeGen. I just filed an issue to track this more diligently as well: Use IRGen diagnostics in CIRGen · Issue #435 · llvm/clangir · GitHub

Another question is with regards to ABI decisions. We currently have a rather awkward dance between Clang and LLVM where Clang is responsible for some aspects of ABI and LLVM is responsible for other aspects (think: calling convention parameter passing, structure layout, etc). Does CIR improve this situation?

Great question. We’re about to start work on this area: currently we’ve been using direct (1-1) mapping for calling conventions, but as we move to building more complex source files and linking against existing libraries, CIR must be ABI compatible. During CIRGen time, parameters will be tagged with their expected ABI behaviors using MLIR attributes, a late pass (CIR’s LoweringPrepare) will then break parameters up as encoded by the ABI requirements in the parameter attribute. I believe this is an improvement because it allows existing CIR passes (like the lifetime checker, idiom recognition and library opt) to not have to reconstruct parameter information in order to do analysis.

Here’s the plan of record for calling conventions: ABI-aware calling conventions · Issue #417 · llvm/clangir · GitHub. We have similar plans for record layout (e.g. tag padding information so that datalayout queries can give the right answer, but only change the actual type during LoweringPrepare) and other ABI related things.

Will there be a post-commit build bot which tests CIR?

Ideally yes, right now we’ve been using github’s LLVM infra to test ClangIR, but we need to figure out how that looks like post upstream, we’ll include a plan as part of our git strategy RFC.

If so, what should the policy be regarding breaking that bot, especially in terms of reverts? e.g., if someone is working on a new feature that (correctly) changes an existing AST representation somewhat and that induces some sort of crash or misbehavior in CIR, is that grounds for a revert?

The expectation should be the same as the previous questions about patching both codegen paths: the burden should be on CIR folks to catch up, no revert needed. This is more work for us, but it’s a tradeoff we’re willing to make for the time being - my feeling is that once more people start caring and more buildbots test this configuration, an RFC will likely come up proposing a revert policy.

3 Likes

Thank you for the response, this all sounds fantastic. I’d like to call out one bit specifically:

Thank you for your willingness to take this approach as it significantly reduces the burden on the wider community until things are stable enough that it makes sense to spread the cost around more widely. That’s very appreciated and is a model for how large-scale changes should be applied to the project. (The new constexpr interpreter is a similar demonstration of this model too.)

2 Likes

+1. This is a monumental task and you guys are going the extra distance to make it as smooth as possible. This proposal is a prime example of how to change large infrastructure parts in widely used upstream projects “the right way”. Kudos to all involved!

3 Likes

Fantastic development, very exciting! Kudos for driving this to this point @bcardosolopes

You’re missing MLIR :slight_smile:

From a maintenance point of view: this is causing some impact on our ability to evolve MLIR, since this will commit us to maintain ClangIR functional. This isn’t a blocker, we’ve been doing the same thing for Flang since it integrated the monorepo.
However we want to be careful about what we’re signing up for, and something we spent a large amount of time with the Flang developers before the merge has been on revisiting the layering and structure of how MLIR should be integrated and how the MLIR component are tested. We should plan on following the same principles here I think.

Something does not line up here, I’d be happy to take a look at this: MLIR is tiny compared to LLVM and Clang in my experience. I would aim to make this “negligible” in practice for clang, let’s sync offline about this!

I’m actually more concerned on the overhead of building and testing clang for MLIR changes (it’s great that you have a dedicated target check-clang-cir, but on the long term you may want to exercise clang-ir through a large number of existing clang tests).

3 Likes

Want to follow up on some of the requirements in the developer policy.

  • Must have an active community that maintains the code, including established code owners.

Is there documentation for ClangIR code owners? I’ve checked clangir/clang/CodeOwners.rst at main · llvm/clangir · GitHub but haven’t found anything for ClangIR or CIR. Also I’m not really tracking what is the situation with PR subscription groups right now, probably we’ll need to change configuration for clang/lib/CIR subdirectory.

  • Should have reasonable documentation about how it works, including a high quality README file.

Appreciate the documentation available at ClangIR · A new high-level IR for clang. As it won’t be a top-level project, the requirement for a README file isn’t really applicable in this case. But I’m curious what is the plan to integrate the documentation with LLVM docs. Keeping docs separately in gh-pages branch isn’t compatible with existing LLVM practices. And I don’t think there are good reasons to change existing LLVM practices regarding the docs.

From a maintenance point of view: this is causing some impact on our ability to evolve MLIR, since this will commit us to maintain ClangIR functional. This isn’t a blocker, we’ve been doing the same thing for Flang since it integrated the monorepo.

To the best of our intentions we don’t want to impact MLIR evolution. If you think the MLIR community is interested in helping keep ClangIR functional we’re happy to welcome the effort and will provide assistance whenever needed (e.g. MLIR folks can XFAIL some CIR tests, create a gh issue, and we can follow up by fixing those, etc). Our expectation here so far is the same one for clang developers mentioned in previous replies: we’re suggesting the catch-up burden is on us.

However we want to be careful about what we’re signing up for, and something we spent a large amount of time with the Flang developers before the merge has been on revisiting the layering and structure of how MLIR should be integrated and how the MLIR component are tested. We should plan on following the same principles here I think.

Fair! Sounds like a plan. Since you mentioned this isn’t a blocker, what are the practical steps you suggest for us continuing that conversation on the side? Happy to book meetings or attend pre-existing ones.

Something does not line up here, I’d be happy to take a look at this: MLIR is tiny compared to LLVM and Clang in my experience. I would aim to make this “negligible” in practice for clang, let’s sync offline about this!

Sure, we’ll reach out over discord. The measurement is certainly an overstatement of the actual time as we explicitly built mlir-translate and mlir-opt. We erred towards the upper bound so that we didn’t come back in two years apologizing for missing our estimated build time regression.

I’m actually more concerned on the overhead of building and testing clang for MLIR changes (it’s great that you have a dedicated target check-clang-cir, but on the long term you may want to exercise clang-ir through a large number of existing clang tests).

This is a reasonable concern! If and when a MLIR based IR for Clang is accepted for tier one support, testing clang along with mlir will be required. We can’t avoid that.

Thanks for the feedback Mehdi, we only got this far because of MLIR :slight_smile:

3 Likes

Is there documentation for ClangIR code owners? I’ve checked clangir/clang/CodeOwners.rst at main · llvm/clangir · GitHub but haven’t found anything for ClangIR or CIR. Also I’m not really tracking what is the situation with PR subscription groups right now, probably we’ll need to change configuration for clang/lib/CIR subdirectory.

Nope, we have not touched the codeowners file. But the ownership is clear and unambiguous: Bruno Cardoso Lopes, Nathan Lanza and Vinicius Couto Espindola as the initial set of ClangIR owners. It’ll be added to the file if and when ClangIR is upstreamed.

Appreciate the documentation available at ClangIR · A new high-level IR for clang. As it won’t be a top-level project, the requirement for a README file isn’t really applicable in this case. But I’m curious. what is the plan to integrate the documentation with LLVM docs. Keeping docs separately in gh-pages branch isn’t compatible with existing LLVM practices. And I don’t think there are good reasons to change existing LLVM practices regarding the docs.

Right, we’ll be adding the current documentation into clang’s. The details are up in the air, but we’ve been maintaining them all along and plan to continue doing so.

3 Likes

I came across this work on SYCL-MLIR and am currently studying it. Can you briefly describe what you can do with it? what will bring improvements.

Great. You having a plan how to make the required changes is enough for me.

As for RFC is general I agree with the including ClangIR to the mono-repo given that the rest of the community isn’t responsible for any ClangIR-related maintenance.

Honestly, personally I’m skeptical about switching to ClangIR for IRGen but it’s not a subject of this proposal and I’m not blocking anything. Mention it only to help you gauge the effort required for subsequent steps. And don’t want to appear coming out of the woodwork later.

You can find more information about the project in the paper: [2312.13170] Experiences Building an MLIR-based SYCL Compiler

For that work, the project still used the polygeist frontend, but we encountered a few limitations, in particular when trying to process SYCL host code. Some of those limitations are related to polygeist not introducing a frontend dialect, but mostly lowering to LLVM dialect directly, with a few additions and raised constructs.

We believe that SYCL-MLIR and also other parallel programming models can benefit from the CIR dialect and the opportunity to preserve more of the high-level semantics of such programming models in MLIR.

6 Likes