Split the monolithic cir.unary operation (which dispatched on a
UnaryOpKind enum) into four separate operations: cir.inc, cir.dec,
cir.minus, and cir.not.
Changes:
- Add CIR_UnaryOpInterface with getInput()/getResult() methods
- Add CIR_UnaryOp and CIR_UnaryOpWithOverflowFlag base classes
- Define IncOp, DecOp, MinusOp, NotOp with per-op folds
- Add Involution trait to NotOp for not(not(x)) -> x folding
- Replace createUnaryOp() with createInc/Dec/Minus/Not builders
- Split LLVM lowering into four separate patterns
- Split LoweringPrepare complex-type handling per unary op
- Update CIRCanonicalize and CIRSimplify for new op types
- Update all codegen files to use bool params instead of UnaryOpKind
- Remove CIR_UnaryOpKind enum and old CIR_UnaryOp definition
Assembly format change:
cir.unary(inc, %x) nsw : !s32i, !s32i -> cir.inc nsw %x : !s32i
cir.unary(not, %x) : !u32i, !u32i -> cir.not %x : !u32i
Replace the single `cir.binop` operation (dispatched via a `BinOpKind`
enum) with nine distinct ops — `cir.add`, `cir.sub`, `cir.mul`,
`cir.div`, `cir.rem`, `cir.and`, `cir.or`, `cir.xor`, and `cir.max` —
each with precise type constraints and only the attributes it needs
(nsw/nuw/sat on add/sub via `BinaryOverflowOp`).
A new `BinaryOpInterface` provides uniform `getLhs`/`getRhs`/`getResult`
access for passes and analyses.
The monolithic switch-based CIRToLLVMBinOpLowering is replaced by per-op
patterns generated through the existing CIRLowering.inc TableGen
infrastructure, with shared dispatch factored into two helpers:
`lowerSaturatableArithOp` for add/sub and `lowerIntFPBinaryOp` for
div/rem.
These two are lowered as if they are the expression: LHS = (LHS < RHS )
? RHS : LHS;
and
LHS = (LHS < RHS ) ? LHS : RHS;
This patch generates these expressions and ensures they are properly
emitted into IR.
Note: this is dependent on
https://github.com/llvm/llvm-project/pull/163580
and cannot be merged until that one is (or the tests will fail).
When creating a 'yield', we have to make sure that the lexical scope we
created gets cleaned up. This isn't really testable until a followup
patch, but I got this wrong in quite a few places.
Following on the Sema changes, this does the lowering for all of the
operators that can be done as a compound operator. Lowering is very
simply looping through the objects based on array/compound/etc, and
doing a call to the operation.
These work the same as the other two (private and reduction) except that
the expression for the 'init' is a copy instead of a default/value init,
and in a separate region. This patch gets all of that correct, and
ensures we generate these as expected.
There is a little extra work to make sure that the bounds-loop
generation does 2 separate array index operations, otherwise this is
very much like the reduction implementation.
Just like with private, the lowering for these bounds are all pretty
trivial. This patch enables them for reduction, which has everything in
common except the init pattern, but that is handled/managed by Sema.
This also adds sufficient testing to spot-check the
allocation/initialization/destruction/etc.
I originally expected that we were going to need the initExpr stored
separately from the allocaDecl when doing arrays/pointers, however after
implementing it, we found that the idea of having the allocaDecl just
store its init directly still works perfectly. This patch removes the
extra field from the AST.
It was brought up by Andy in a different review that AutoVarEmission's
member variables didn't follow our naming standard. This patch corrects
that and fixes all references.
Private only does 'init' when a constructor needs to be called, so this
patch adds that. The logic of what to init is caused by Sema, but the
tests show that types that are pointers or non-class-types or class
types without a constructor aren't actually initialized.
A previous review comment pointed out that operations with only a single
result implicitly convert to `mlir::Value`. This patch removes the
explicit use of `getResult` where it is unnecessary in OpenACC lowering.
However, there ARE a few cases where it is necessary where the
`mlir::ValueRange` implicit constructor from a single value is being
used, so those are untouched.
Additionally, while the previous patch was being committed (#161382), a
second patch (#161431) changed the format of cir.casts, so this patch
fixes the additional test lines for that as well.
The previous patch ensured that we correctly got the allocas put in
place. This patch takes the address of each element of each alloca, and
copies it to the previous one. This allows us to re-form the
pointer-structure for a recipe.
This fixes macos build, where otherwise the compilation yields an error: `no viable conversion from 'bool' to 'typename iterator_traits<const QualType *>::value_type`
As a next step to generating pointer/array recipes, this patch generates
just the 'alloca' lines that are necessary. Copying pointers over to
restore the structure is held off to the next patch.
In the case of a pointer, we need to allocate the level 'below' it (if
we index into it), then copy the values into the pointers. In the case
of an array, we skip the alloca (since the array's alloca contains the
value).
After this, we'll need a patch that copies the pointers into place, and
finally one that does the initialization of these values.
It was brought up on a previous review that the CIRGenOpenACCRecipe.h
file was getting too large. I noticed that the 'dependent on template
argument' parts were actually quite small, so I extract a base class in
this patch that allows me to implement it in the .cpp file, plus
minimize the amount of code that needs instantiating.