-
Notifications
You must be signed in to change notification settings - Fork 122
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][CodeGen] Adds support for inline assembler #308
Conversation
Thanks for contributing support for this in ClangIR, much welcome feature.
This one. I rather do it closer to original (to the most extend as possible) - easy for new people getting involved in the project to catch up and help.
This is fine, let's go incremental here.
You could also copy the tests from the original codegen and make sure it passes.
As long as you add an assert for other arches, x86 is fine.
My take here is to add some simple tests first and later start copy-n-paste the original ones, and make sure they pass.
Gotcha! Big patches are hard to review, I'm currently the only one doing PR reviews, so if we go even more incrementally it helps me build context and accept your patches faster. Can you break this down further? For example, the first PR could just add empty asm string, a very simple initial operation without all operands or attributes. Each following PR can then add constraints, etc. You can still keep this PR open with the complete work you have already, and slowly build the feature upstream one little piece at a time. |
Well, hard task! Let's try to do it. |
I will break the PR #308 into pieces and submit them one-by-one. The first PR introduce CIR operation and the `buildAsmStmt` function. The latter is the main place for the future changesm and the former was taken directly from MLIR LLVM IR dialect. As a result, there is nothing really interesting happen here, but now we can at least emit cir for an empty inline assembler. And as a first step
Guards cir.scope lowering against empty scopes avoiding segfaults. Also removes empty cir.scope operations on MergeCleanups pass. ghstack-source-id: c4539552568d451ae0bf220ea6bde9a44fc66b8d Pull Request resolved: llvm#144
Essentially converts a `cir.loop` op of the `while` kind to a CFG. The implementation, however, was only tested with structured loops, so if breaks, continues, or returns are found in the body, it is likely to break. ghstack-source-id: 32d262436d11d70fb6d2be23b63ba37ed01b9c1f Pull Request resolved: llvm#145
Conditionally set the loop entry point depending on whether the loop is of the `do-while` kind or not. ghstack-source-id: 711f4befd051a68a70bd099982b31d7cad3f5a71 Pull Request resolved: llvm#146
ghstack-source-id: 8e98e125c9dc41b134e3270f5c453884309d90e6 Pull Request resolved: llvm#147
globals.cir should be fixed, goto.cir is dead given that we aren't supporting ThroughMLIR
In C, whenever we logically compare two values, we may store the result in any variable type. In this case, the boolean result should be cast to whatever type the variable is. This patch adds support for this.
Casts from one integer type to another, should not be lowered to LLVM if the integers are of the same size. These may represent sign drops or inclusion in CIR but do not make sense in LLVM. This patch fixes that. ghstack-source-id: 0b028504f8f61683a85fc5fce573175ded3cc725 Pull Request resolved: llvm#154
We should not have tests that depend on target-specific executables. This patch removes the 'hello.c' executable test and converts it to both a codegen and a lowering test. ghstack-source-id: caa8f3aa01bbc89693ac8724ad7fac1a96114f1a Pull Request resolved: llvm#155
This refactor merges the lowering logic of all the different kinds of loops into a single function. It also removes unnecessary LIT tests that validate LLVM dialect to LLVM IR lowering, as this functionality is not within CIR's scope. Fixes llvm#153 ghstack-source-id: ebaab859057a6d81f1978fd88701c28402712562 Pull Request resolved: llvm#156
ghstack-source-id: 16b236e1faea9f23e09e83bf26b9167f584de0ba Pull Request resolved: llvm#157
…lineAttr (llvm#134) Setting inline attributes based on user input and command line options. This is optional as functions do not need such an attribute will not get the attribute.
… assist clangir dev
cir.binop has the constraints on operands and results types than cannot support shifts with amount types different from the value getting shift. Adding cir.shift is a closer map.
ghstack-source-id: 9d59b38339fc8c8d6ddce8b4bdb3f00f450c678b Pull Request resolved: llvm#162
LLVM's dialect does not have (at the time of writing) a way to represent zero-initializers. And, despite being possible to represent null pointers, it requires it to use a region-based initialization. To avoid this, LLVM operations that use either of these attributes are marked with a cir.zero attribute that will be identified by the LowerAttrToLLVMIR interface and patch the LLVM IR operation to be initialized with a zero-initializer or null. ghstack-source-id: 1872476a03ba9b1a75fe347b50f0552fef2e478b Pull Request resolved: llvm#163
Incremental work towards tracking exploded structs, no testcase just yet.
This change introduces `cir-translate` as a replacement of `mlir-translate` to convert CIR directly to LLVM IR. The main benefit of this is to utilize the CIR attribute interface to handle CIR-specific attributes such as `cir.extra`. Other advantages at this time, besides the cir attribute support, could be that we can go directly from CIR to LLVMIR without exposing the intermediate MLIR LLVM dialect form. Previously `cir-tool` emit the LLVM dialect form and `milr-translate` took it from there. Now `cir-translate` can directly take CIR and yield LLVMIR. I'm also renaming `cir-tool` to `cir-opt` which eventually would be just a CIR-to-CIR transformer, but for now I'm keeping the functionality of CIR to LLVM dialect. So, `cir-opt` will do all CIR-to-CIR transforms, just like LLVM `opt` or `mlir-opt`, and `cir-translate` will handle CIR to LLVMIR translation, and LLVMIR-to-LLVMIR transforms, like the LLVM `llc` or the `mlir-translate`
This is the first part of implementing vector types and vector operations in ClangIR, issue llvm#284. This is enough to compile this test program. I haven't tried to do anything beyond that yet. ``` typedef int int4 __attribute__((vector_size(16))); int main(int argc, char** argv) { int4 a = { 1, argc, argc + 1, 4 }; int4 b = { 5, argc + 2, argc + 3, 8 }; int4 c = a + b; return c[1]; } ``` This change includes: * Fixed-sized vector types which are parameterized on the element type and the number of elements. For example, `!cir.vector<s32i x 4>`. (No scalable vector types yet; those will come later.) * New operation `cir.vec` which creates an object of a vector type with the given operands. * New operation `cir.vec_elem` which extracts an element from a vector. (The array subscript operation doesn't work here because the result is an rvalue, not an lvalue.) * Basic binary arithmetic operations on vector types, though only addition has been tested. There are no unary operators, comparison operators, casts, or shuffle operations yet. Those will all come later.
…vm#356) This PR adds a support for the multi-block case statements. Previously, the code example below caused crash in cir verification Lowering to the `llvm` dialect is pretty straightforward: the same logic as before is applied to all the region's blocks with no successors, i.e. we no longer think a case/default region contains only one block. The `CodeGen` part is a little bit tricky. Previously, any sub-statement of `case` or`default`, that was not any of them (i.e. neither `case` nor `default`) was processed with an insertion guard, meaning that the next sub-statement in the same clause was inserted again in the same block as the first one. It would be fine, once sub-statement didn't generate any blocks as well. For instance, ``` void foo(int a) { switch (a) { case 3: return; break; } } ``` The `return` statement actually emit a new block after, where the unreachable code with `break` should be inserted in. That's why we also need to update `lastCaseBlock` while generating `cir.switch` This is quite frequent bug in `llvm-test-suite`
This contains just the skeleton, but the idea is that this pass is going to contain transformations done on top CIR generated by the C/C++ idiom recognizer.
4e069c6
to
79d4dc7
Compare
I will break the PR #308 into pieces and submit them one-by-one. The first PR introduce CIR operation and the `buildAsmStmt` function. The latter is the main place for the future changesm and the former was taken directly from MLIR LLVM IR dialect. As a result, there is nothing really interesting happen here, but now we can at least emit cir for an empty inline assembler. And as a first step
ed3955a
to
8b7417c
Compare
I will break the PR #308 into pieces and submit them one-by-one. The first PR introduce CIR operation and the `buildAsmStmt` function. The latter is the main place for the future changesm and the former was taken directly from MLIR LLVM IR dialect. As a result, there is nothing really interesting happen here, but now we can at least emit cir for an empty inline assembler. And as a first step
I will break the PR llvm#308 into pieces and submit them one-by-one. The first PR introduce CIR operation and the `buildAsmStmt` function. The latter is the main place for the future changesm and the former was taken directly from MLIR LLVM IR dialect. As a result, there is nothing really interesting happen here, but now we can at least emit cir for an empty inline assembler. And as a first step
I will break the PR llvm#308 into pieces and submit them one-by-one. The first PR introduce CIR operation and the `buildAsmStmt` function. The latter is the main place for the future changesm and the former was taken directly from MLIR LLVM IR dialect. As a result, there is nothing really interesting happen here, but now we can at least emit cir for an empty inline assembler. And as a first step
@gitoleg can we close this? |
I will break the PR #308 into pieces and submit them one-by-one. The first PR introduce CIR operation and the `buildAsmStmt` function. The latter is the main place for the future changesm and the former was taken directly from MLIR LLVM IR dialect. As a result, there is nothing really interesting happen here, but now we can at least emit cir for an empty inline assembler. And as a first step
I will break the PR #308 into pieces and submit them one-by-one. The first PR introduce CIR operation and the `buildAsmStmt` function. The latter is the main place for the future changesm and the former was taken directly from MLIR LLVM IR dialect. As a result, there is nothing really interesting happen here, but now we can at least emit cir for an empty inline assembler. And as a first step
I will break the PR llvm#308 into pieces and submit them one-by-one. The first PR introduce CIR operation and the `buildAsmStmt` function. The latter is the main place for the future changesm and the former was taken directly from MLIR LLVM IR dialect. As a result, there is nothing really interesting happen here, but now we can at least emit cir for an empty inline assembler. And as a first step
I will break the PR #308 into pieces and submit them one-by-one. The first PR introduce CIR operation and the `buildAsmStmt` function. The latter is the main place for the future changesm and the former was taken directly from MLIR LLVM IR dialect. As a result, there is nothing really interesting happen here, but now we can at least emit cir for an empty inline assembler. And as a first step
I will break the PR llvm#308 into pieces and submit them one-by-one. The first PR introduce CIR operation and the `buildAsmStmt` function. The latter is the main place for the future changesm and the former was taken directly from MLIR LLVM IR dialect. As a result, there is nothing really interesting happen here, but now we can at least emit cir for an empty inline assembler. And as a first step
I will break the PR llvm#308 into pieces and submit them one-by-one. The first PR introduce CIR operation and the `buildAsmStmt` function. The latter is the main place for the future changesm and the former was taken directly from MLIR LLVM IR dialect. As a result, there is nothing really interesting happen here, but now we can at least emit cir for an empty inline assembler. And as a first step
I will break the PR llvm#308 into pieces and submit them one-by-one. The first PR introduce CIR operation and the `buildAsmStmt` function. The latter is the main place for the future changesm and the former was taken directly from MLIR LLVM IR dialect. As a result, there is nothing really interesting happen here, but now we can at least emit cir for an empty inline assembler. And as a first step
I will break the PR #308 into pieces and submit them one-by-one. The first PR introduce CIR operation and the `buildAsmStmt` function. The latter is the main place for the future changesm and the former was taken directly from MLIR LLVM IR dialect. As a result, there is nothing really interesting happen here, but now we can at least emit cir for an empty inline assembler. And as a first step
This PR adds support for the inline assembly in CIR.
The PR is explicitly marked as a draft, since some discussion needed.
As usually, I started with the original codegen (
clang/lib/Codegen
), and here is a first thing we need to agree on. The original code is kind of hard to read and the first desire is to refactor the code in this PR so that it can be readable or maintainable or both. Or at least do something - actually I already did some preliminary things to clean up a little.Another approach - we may leave the code closer to the original one in order to make it simpler to reflect all the future changes in the original codegen in CIR. So it's up to you to decide which approach to apply.
Now, the PR itself.
First of all, there are several unimplemented features and limitations:
llvm.assume
or bundles.Tests
The main question is about tests. As usually we want to have such tests, that cover all use cases, every branch of the code.
But the point is - we don't need to repeat all the assembler tests from the original codegen. E.g. we don't need to check how the parse functions work. We may assume that such things are checked there.
The same is true for the different architectures support. Probably, we will need to add something arch-specific in some point of time. But it's ok for now to check everything just for x86. By "everything" I mean the code, that is CIR specific, give or take, e.g. we emit the value/operation where we need to.
Thus, for now I added just several tests and I kind of feel shame for this small number of checks I do. I'm sure we want to have more tests. And I will definitely add more. But in the same time I'm sure we don't need too much. So, I would be happy to hear your point of view.
So far, some trivial examples work and you are welcome to check (or break something :) )
UPD:
Added tests from the the
clang/test/CodeGen/asm.c
with no checks included (so far). Just to make sure we don't crush in these scenario. Only three of them skipped: module level asm, vector types and goto.