Skip to content

Conversation

@2over12
Copy link

@2over12 2over12 commented Apr 18, 2025

The CIR linker interface currently implicitly depends on MLIRCir

ghehg and others added 30 commits January 27, 2025 14:03
Combined implementaiton with `neon_vaddlvq_u16`
OG somehow implemented them separately but they are no different except
signess and intrinsic name
[OG's
neon_vaddlvq_s16](https://github.com/llvm/clangir/blob/2b1a638ea07ca10c5727ea835bfbe17b881175cc/clang/lib/CodeGen/CGBuiltin.cpp#L13483)
[OG's
neon_vaddlvq_u16](https://github.com/llvm/clangir/blob/2b1a638ea07ca10c5727ea835bfbe17b881175cc/clang/lib/CodeGen/CGBuiltin.cpp#L13449)
The module-level uwtable attribute controls the unwind tables for any
synthesized functions, and the function-level attribute controls them
for those functions. I'll add support for this attribute to the LLVM
dialect as well, but translate it from CIR directly for now to avoid
waiting on the MLIR addition and a subsequent rebase.
llvm#1232)

Match `CodeGenModule::SetLLVMFunctionAttributesForDefinition` so that we
can see what's missing and have a good base to build upon.
I am working on a clangir based solution to improve C++'s safety
(https://discourse.llvm.org/t/rfc-a-clangir-based-safe-c/83245). This is
similar with the previous analysis only approach I proposed, where we
may not care about the lowered code. And this is what I described as
layering problems in
https://discourse.llvm.org/t/rfc-a-clangir-based-safe-c/83245

This is similar with the other issue proposed
llvm/clangir#1128. We'd better to emit the
higher level operations and lowering/optimizing it later.

This is also inspired our handling method for VAArg, where we use ABI
information to lower things during the passes. It gives me more
confidence that I am doing things right.
The PR should help us to get rid of NYI 
`NYI UNREACHABLE executed at
clang/lib/CIR/CodeGen/CIRGenExprAgg.cpp:899`
[Relevant OG code
here](https://github.com/llvm/clangir/blob/7fb608d4d1b72c25a1739a1bd66c9024208819cb/clang/lib/CodeGen/CGExpr.cpp#L4767):
I put `HasExplicitObjectParameter` support as a missing feature, which
is a new C++23 feature.
…ge (llvm#1214)

#### The Problem
Let's take a look at the following code:
```
struct A {
~A() {}
};

int foo() { return 42; }
void bar() {
  A a;
  int b = foo(); 
}
```
The call to `foo` guarded by the synthetic `tryOp` looks approximately
like the following:
```
cir.try synthetic cleanup {
   %2 = cir.call exception @_Z3foov() : () -> !s32i cleanup {
      cir.call @_ZN1AD1Ev(%0) : (!cir.ptr<!ty_A>) -> () extra(#fn_attr1)   // call to destructor of 'A'
      cir.yield
    } 
    cir.yield
} catch [#cir.unwind {
    cir.resume 
}] 
cir.store %2, %1: !s32i, !cir.ptr<!s32i>  // CIR verification error
```
The result of the `foo` call is in the `try` region - and is not
accessible from the outside, so the code generation fails with
`operand #0 does not dominate its use` .

#### Solution
So we have several options how to handle this properly. 
1. We may intpoduce a new operation here, like `TryCall` but probably
more high level one, e.g. introduce the `InvokeOp`.
2. Also, we may add the result to `TryOp`.
3. The fast fix that is implemented in this PR is a temporary `alloca`
where we store the call result right in the try region. And the result
of the whole `emitCall` is a `load` from the temp `alloca`.

So this PR is both the request for changes and an open discussion as
well - how to handle this properly. So far I choose the third approach.
If it's ok - I will need to create one more PR with a similar fix for
the aggregated results or update this one.
This PR puts for-loop body, while-loop body, and do-while-loop body in
nested scopes. Allocas in the loop body are now push down to the nested
scope.

Resolve llvm#1218 .
There are two sets of intrinsics regarding Min and Max operations for
floating points

[Maximum](https://mlir.llvm.org/docs/Dialects/LLVM/#llvmintrmaximum-llvmmaximumop)
vs
[Maxnum](https://mlir.llvm.org/docs/Dialects/LLVM/#llvmintrmaxnum-llvmmaxnumop)

[Minimum](https://mlir.llvm.org/docs/Dialects/LLVM/#llvmintrminimum-llvmminimumop)
vs
[Minnum](https://mlir.llvm.org/docs/Dialects/LLVM/#llvmintrminnum-llvmminnumop)

[The difference is whether NaN should be propagated when one of the
inputs is
NaN](https://llvm.org/docs/LangRef.html#llvm-maximumnum-intrinsic)
Maxnum and Minnum would return number if one of inputs is NaN, and the
other is a number,
But 
Maximum and Minimum would return NaN (propagation of NaN)

And they are resolved to different ASM such as
[FMAX](https://developer.arm.com/documentation/ddi0596/2021-03/SIMD-FP-Instructions/FMAX--vector---Floating-point-Maximum--vector--?lang=en)
vs
[FMAXNM](https://developer.arm.com/documentation/ddi0596/2021-03/SIMD-FP-Instructions/FMAXNM--vector---Floating-point-Maximum-Number--vector--?lang=en)

Both have user cases, we already implemented Maxnum and Minnum
But Maximum and Minimum has user cases in [neon intrinsic
](https://developer.arm.com/architectures/instruction-sets/intrinsics/vmax_f32
)
and [__builtin_elementwise_maximum
](https://github.com/llvm/clangir/blob/a989ecb2c55da1fe28e4072c31af025cba6c4f0f/clang/test/CodeGen/strictfp-elementwise-bulitins.cpp#L53)
…lvm#1235)

Use iterator to visit std::initializer_list field reduce the readability
…d neon_vaddvq_f64 (llvm#1238)

[Neon intrinsic
definition](https://developer.arm.com/architectures/instruction-sets/intrinsics/vaddv_f32).
They are vector across operation which LLVM doesn't currently have a
generic intrinsic about it. As a side note for brainstorm, it might be
worth in the future for CIR to introduce Vector Across type operations
even though LLVM dialect doesn't have it yet. This would help to expose
opt opportunities.
E.g. a very trivial constant fold can happen if we are adding across a
constant vector.
…#1239)

This implementation is different from OG in the sense we chose to use
CIR op which eventually lowers to generic LLVM intrinsics instead of
llvm.aarch64.neon intrinsics
But down to the ASM level, [they are identical
](https://godbolt.org/z/Gbbos9z6Y).
…vm#1242)

This patch follows
llvm/clangir#1220 (comment) by
augmenting `CIR_Type` with a new field, `tbaaName`. Specifically, it
enables TableGen support for the `-gen-cir-tbaa-name-lowering` option,
allowing for the generation of `getTBAAName` functions based on the
`tbaaName`. This enhancement enables us to replace the hardcoded TBAA
names in the `getTypeName` function with the newly generated
`getTBAAName`.
This PR adds a bitcast when we rewrite globals type. Previously we just
set a new type and it worked.
But recently I started to test ClangIR with CSmith in order to find some
run time bugs and faced with the next problem.

```
typedef struct {
    int x : 15;   
    uint8_t y;
} S;

S g = { -12, 254};

int main() {    
    printf("%d\n", g.y);
    return 0;
}

```
The output for this program is  ... 127 but not 254!
The reason is that first global var is created with the type of struct
`S`, then `get_member` operation is generated with index `1`
and then after, the type of the global is rewritten - I assume because
of the anon struct created on the right side in the initialization.
But the `get_member` operation still wants to access to the field at
index `1` and get a wrong byte.
If we change the `y` type to `int` we will fail on the verification
stage. But in the example above it's a run time error!

This is why I suggest to add a bitcast once we have to rewrite the
global type.
We figure it would be nice to have a common place with all our known
crashes that is tracked by git and is actively verified whether or not
we can now support the crashes by lit. It can act as our source of truth
for known failures and also being potential good first tasks for new
developers.

Add a simple test case of a known crash that involves copying a struct
in a catch.

Reviewers: smeenai, bcardosolopes

Reviewed By: bcardosolopes

Pull Request: llvm/clangir#1243
…#1247)

Basically that is - the return value for `=` operator for bitfield
assignment is wrong now. For example, the next function returns `7` for
3 bit bit field, though it should be `-1`:
```
int get_a(T *t) {
  return (t->a = 7);
}
```

This PR fix it. Actually, the bug was in the lowering - the integer cast
is applied in the wrong place (in comparison with the original codegen).
This PR changes changes the lowering of `cir.bool` to `i1` in both
DorectToLLVM and ThroughMLIR. This dramatically simplifies the lowering
logic of most operations and the lowered code itself as it naturally
uses `i1` for anything boolean.

The change involves separating between type lowering when scalars are
involved and when memory is involved. This is a pattern that was
inspired by clang's codegen which directly emits `i1` from the AST
without intermediate higher level representation like CIR has.

This also paves the way to more complex lowerings that are implemented
in clang codegen through the three primitives added here: `Convert Type
For Memory`, `Emit For Memory` and `Emit To Memory`. They are used in
clang for non-trivial types like bitints but also extensible vectors.
Close llvm/clangir#1185

The patch itself seems slightly ad-hoc. As the issue tracked by
llvm/clangir#1178, the fundamental solution
may be to introduce two type systems to solve the inconsistent semantics
for Union between LLVM IR and CIR. This will be great to handle other
inconsistent semantics between LLVM IR and CIR if any.

Back to the patch itself, although the code looks not good initially to
me too. But I feel it may be a good workaround since
clang/test/CIR/Lowering/union-array.c is an example for array of unions
directly and clang/test/CIR/Lowering/nested-union-array.c gives an
example for array of unions indirectly (array of structs which contain
unions). So I feel we've already covered all the cases.

And generally it should be good to use some simple and solid workaround
before we introduce the formal full solution.
…16` and `vdivh_f16` (llvm#1258)

Lowering:

- `vaddh_f16`
- `vsubh_f16`
- `vmulh_f16`
- `vdivh_f16`
xlauko and others added 25 commits March 31, 2025 19:04
@2over12 2over12 requested review from a team, bcardosolopes and lanza as code owners April 18, 2025 19:50
@2over12 2over12 closed this Apr 18, 2025
@github-actions
Copy link

Thank you for submitting a Pull Request (PR) to the LLVM Project!

This PR will be automatically labeled and the relevant teams will be notified.

If you wish to, you can add reviewers by using the "Reviewers" section on this page.

If this is not working for you, it is probably because you do not have write permissions for the repository. In which case you can instead tag reviewers by name in a comment by using @ followed by their GitHub username.

If you have received no comments on your PR for a week, you can request a review by "ping"ing the PR by adding a comment “Ping”. The common courtesy "ping" rate is once a week. Please remember that you are asking for valuable time from other developers.

If you have further questions, they may be answered by the LLVM GitHub User Guide.

You can also ask questions in a comment on this PR, on the LLVM Discord or on the forums.

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.