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 __builtin_isinf_sign #1142

Open
wants to merge 2,082 commits into
base: main
Choose a base branch
from

Conversation

PikachuHyA
Copy link
Collaborator

This patch adds support for __builtin_isinf_sign. The implementation has several limitations that result in discrepancies between the generated LLVM IR and the expected output.

Firstly, it uses IsFPClass to determine if a value is infinite, whereas the original CGBuiltin implementation used direct comparisons with infinity constants.
Secondly, due to #480, there are numerous unnecessary type conversions occurring, such as converting from i1 to i8 and then back to i1.
Additionally, SignBitOp cannot set the return type to CIR_BoolType, as doing so would lead to failures during the lowering to LLVM IR.

bcardosolopes and others added 30 commits November 2, 2024 23:30
…te personality functions

While here, cleanup getOrCreateLLVMFuncOp usaga a bit.
Directly erasing the op causes a use after free later on, presumably
because the lowering framework isn't aware of the op being deleted. This
fixes `clang/test/CIR/CodeGen/pointer-arith-ext.c` with ASAN.
The loop was erasing the user of a value while iterating on the value's
users, which results in a use after free. We're already assuming (and
asserting) that there's only one user, so we can just access it directly
instead. CIR/Transforms/Target/x86_64/x86_64-call-conv-lowering-pass.cpp
was failing with ASAN before this change. We're now ASAN-clean except
for llvm#829 (which is also in
progress).
Reland llvm#638

This was reverted due to llvm#655. I
tried to address the problem in the newest commit.

The changes of the PR since the last landed one includes:
- Move the definition of `cir::CIRGenConsumer` to
`clang/include/clang/CIRFrontendAction/CIRGenConsumer.h`, and leave its
`HandleTranslationUnit` interface is left empty. So that
`cir::CIRGenConsumer` won't need to depend on CodeGen any more.
- Change the old definition of `cir::CIRGenConsumer` in
`clang/lib/CIR/FrontendAction/CIRGenAction.cpp` and to
`CIRLoweringConsumer`, inherited from `cir::CIRGenConsumer`, which
implements the original `HandleTranslationUnit` interface.

I feel this may improve the readability more even without my original
patch.
This PR fixes the lowering for multi dimensional arrays.

Consider the following code snippet `test.c`: 
```
void foo() {
  char arr[4][1] = {"a", "b", "c", "d"};
}
```

When ran with `bin/clang test.c -Xclang -fclangir -Xclang -emit-llvm -S
-o -`, It produces the following error:
```
~/clangir/llvm/include/llvm/Support/Casting.h:566: decltype(auto) llvm::cast(const From&) [with To = mlir::ArrayAttr; From = mlir::Attribute]: Assertion `isa<To>(Val) && "cast<Ty>() argument of incompatible type!"' failed.
```

The bug can be traced back to `LoweringHelpers.cpp`. It considers the
values in the array as integer types, and this causes an error in this
case.

This PR updates `convertToDenseElementsAttrImpl` when the array contains
string attributes. I have also added one more similar test. Note that in
the tests I used a **literal match** to avoid matching as regex, so
`!dbg` is useful.
Support expressions at the top level such as

const unsigned int n = 1234;
const int &r = (const int&)n;

Reviewers: bcardosolopes

Pull Request: llvm#857
Fix llvm#829

Thanks @smeenai for pointing out the root cause and UBSan failure!
As title.
Also introduced buildAArch64NeonCall skeleton, which is partially the
counterpart of OG's EmitNeonCall. And this could be use for many other
neon intrinsics.

---------

Co-authored-by: Guojin He <[email protected]>
These were uninitialized, which led to intermittent test failures from
the use of uninitialized variables. Initialize them to `nullptr` as is
done with other member variables that are pointers to fix this.

I did a quick spot-check and didn't find other uninitialized variables
in the main CGF class itself. Lots of subclasses have uninitialized
member variables, but those are presumably expected to be initialized at
all points of construction, so we can leave them alone until they cause
any issues.

`ninja check-clang-cir` now passes with ASan+UBSan and MSan.

Fixes llvm#829
This PR adds aarch64 big endian support.

Basically the support for aarch64_be itself is expressed only in two
extra cases for the switch statement and changes in the `CIRDataLayout`
are needed to prove that we really support big endian. Hence the idea
for the test - I think the best way for proof is something connected
with bit-fields, so we compare the results of the original codegen and
ours.
This PR splits the old `cir-simplify` pass into two new passes, namely
`cir-canonicalize` and `cir-simplify` (the new `cir-simplify`). The
`cir-canonicalize` pass runs transformations that do not affect
CIR-to-source fidelity much, such as operation folding and redundant
operation elimination. On the other hand, the new `cir-simplify` pass
runs transformations that may significantly change the code and break
high-level code analysis passes, such as more aggresive code
optimizations.

This PR also updates the CIR-to-CIR pipeline to fit these two new
passes. The `cir-canonicalize` pass is moved to the very front of the
pipeline, while the new `cir-simplify` pass is moved to the back of the
pipeline (but still before lowering prepare of course). Additionally,
the new `cir-simplify` now only runs when the user specifies a non-zero
optimization level on the frontend.

Also fixed some typos and resolved some `clang-tidy` complaints along
the way.

Resolves llvm#827 .
Currently the C style cast is not implemented/supported for unions.

This PR adds support for union casts as done in `CGExprAgg.cpp`. I have
also added an extra test in `union-init.c`.
Mistakenly closed llvm#850

llvm#850 (review)
 
This PR fixes array initialization for expression arguments. 

Consider the following code snippet `test.c`: 
```
typedef struct {
  int a;
  int b[2];
} A;

int bar() {
  return 42;
}

void foo() {
  A a = {bar(), {}};
}
```
When ran with `bin/clang test.c -Xclang -fclangir -Xclang -emit-cir -S
-o -`, It produces the following error:
```
~/clangir/clang/lib/CIR/CodeGen/CIRGenExprAgg.cpp:483: void {anonymous}::AggExprEmitter::buildArrayInit(cir::Address, mlir::cir::ArrayType, clang::QualType, clang::Expr*, llvm::ArrayRef<clang::Expr*>, clang::Expr*): Assertion `NumInitElements != 0' failed.
```
The error can be traced back to `CIRGenExprAgg.cpp`, and the fix is
simple. It is possible to have an empty array initialization as an
expression argument!
As title, if element type of vector type is sized, then the vector type
should be deemed sized.
This would enable us generate code for neon without triggering assertion
…eon_vrndaq_v (llvm#871)

as title. 
This also added NeonType support for Float32

Co-authored-by: Guojin He <[email protected]>
It will hit another assert when calling initFullExprCleanup.
This PR fixes the case, when a temporary var is used, and `alloca`
operation is inserted in the block start before the `label` operation.
Implementation: when we search for the `alloca` place in a block, we
take label operations into account as well.

Fix llvm#870

---------

Co-authored-by: Bruno Cardoso Lopes <[email protected]>
orbiri and others added 26 commits November 12, 2024 12:15
…vm#1107)

Before the commit, when flattening if/else clauses - the else body came
before the "then" body, as opposed to clang's output order.

This commit reverses this and hopefully allows easier comparisson
between clang's output and cir's.
This patch implements transformations for VAArg in X86_64 ABI **in
shape**. `In shape` means it can't work properly due to the dependent
X86_64 ABI is not robust. e.g., when we want to use VAArg with `long
double`, we need llvm#1087.

This patch literally implement
https://github.com/llvm/llvm-project/blob/d233fedfb0de882353c348cd1ac57dab619efa6d/clang/lib/CodeGen/Targets/X86.cpp#L3015-L3240
in CIR.

There some differences due to the traditional pipeline are converting
AST to LLVM and we're transforming CIR to CIR. And also to get the ABI
Info, I moved `X86_64ABIInfo` to the header.
…ry (llvm#1111)

This PR adds a support for one more case of passing structs by value,
with `memcpy` emitted.

First of all, don't worry - despite the PR seems big, it's basically
consist of helpers + refactoring. Also, there is a minor change in the
`CIRBaseBuilder` - I made static the `getBestAllocaInsertPoint` method
in order to call it from lowering - we discussed once - and I here we
just need it (or copy-paste the code, which doesn't seem good).

I will add several comments in order to simplify review.
follow llvm#1033
handle `LongDoubleType` with `FP80Type`.
)

As title, this patch refactors raw string literals for (module)
attribute names into static methods of `CIRDialect`, following the
convention of MLIR.
This PR handles calls with unions passed by value in the calling
convention pass.

#### Implementation
As one may know, data layout for unions in CIR and in LLVM differ one
from another. In CIR we track all the union members, while in LLVM IR
only the largest one.

And here we need to take this difference into account: we need to find a
type of the largest member and treat it as the first (and only) union
member in order to preserve all the logic from the original codegen.

There is a method `StructType::getLargestMember` - but looks like it
produces different results (with the one I implemented or better to say
copy-pasted). Maybe it's done intentionally, I don't know.

The LLVM IR produced has also some difference from the original one. In
the original IR `gep` is emitted - and we can not do the same. If we
create `getMemberOp` we may fail on type checking for unions - since the
first member type may differ from the largest type. This is why we
create `bitcast` instead. Relates to the issue llvm#1061
…enBuiltinAArch64.cpp (llvm#1124)

We are still seeing crash message like `NYI UNREACHABLE executed at
clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp:3304`, which is not
convenient for triaging as our code base changes so fast, line number
doesn't help much.
So, here we replaced most of `llvm_unreachable("NYI")` with more
informative message.
…1125)

Currently, the final `target triple` in LLVM IR is set in
`CIRGenAction`, which is not executed by cir tools like `cir-translate`.
This PR delay its assignment to LLVM lowering, enabling sharing the
emitting of `target triple` between different invoking paths.
…ts (llvm#1074)

As the title says, this PR adds support for calls with struct types >
128 bits, building upon this
[PR](llvm#1068).

The idea is gotten from the original Codegen, and I have added a couple
of tests.
…bsOp to take vector input (llvm#1099)

Extend AbsOp to take vector of int input. With it, we can support
__builtin_elementwise_abs.
We should in the next PR extend FpUnaryOps to support vector type input
so we won't have blocker to implement all elementwise builtins
completely. Now just temporarily have missingFeature
`fpUnaryOPsSupportVectorType`.
Currently, int type UnaryOp support vector type. 

FYI:
[clang's documentation about elementwise
builtins](https://clang.llvm.org/docs/LanguageExtensions.html#vector-builtins)
…vm#1102)

This is a NFC patch that moves declaration from  LowerToLLVM.cpp.

The motivation of the patch is, we hope we can use the abilities from
MLIR's standard dialects without lowering **ALL** clangir operation to
MLIR's standard dialects. For example, currently we have 86 operations
in LowerToLLVM.cpp but only 45 operations under though MLIR. It won't be
easy to add proper lowering for all operation to **different** dialects.

I think the solution may be to allow **mixed** IR. So that we can
lowering CIR to MLIR's standard dialects partially and we can use some
existing analysis and optimizations in MLIR and then we can lower all of
them (the MLIR dialects and unlowered clangir) to LLVM IR. The hybrid IR
is one of the goals of MLIR as far as I know.

NOTE: I completely understand that the DirectlyLLVM pipeline is the
tier-1 pipeline that we want to support. The idea above won't change
this. I just want to offer some oppotunities for the downstream projects
and finally some chances to improve the overall ecosystem.
This is going to be raised in follow up work, which is hard to
do in one go because createBaseClassAddr goes of the OG skeleton
and ideally we want ApplyNonVirtualAndVirtualOffset to work naturally.

This also doesn't handle null checks, coming next.
Now that we fixed the dep on VBase, clean up the rest of the function.
It was always the intention for `cir.cmp` operations to return bool
result. Due
to missing constraints, a bug in codegen has slipped in which created
`cir.cmp`
operations with result type that matches the original AST expression
type. In
C, as opposed to C++, boolean expression types are "int". This resulted
with
extra operations being codegened around boolean expressions and their
usage.

This commit both enforces `cir.cmp` in the op definition and fixes the
mentioned bug.
…vm#1135)

support `llvm.intr.memset.inline` in llvm-project repo before we add
support for `__builtin_memset_inline` in clangir

cc @bcardosolopes

(cherry picked from commit 30753af)
This patch adds support for `__builtin_isinf_sign`. The implementation
has several limitations that result in discrepancies between the
generated LLVM IR and the expected output.

Firstly, it uses `IsFPClass` to determine if a value is infinite,
whereas the original CGBuiltin implementation used direct comparisons
with infinity constants.
Secondly, due to llvm#480, there are
numerous unnecessary type conversions occurring, such as converting from
i1 to i8 and then back to i1.
Additionally, `SignBitOp` cannot set the return type to `CIR_BoolType`,
as doing so would lead to failures during the lowering to LLVM IR.
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.