fir.dispatch code generation uses the binding table stored in the
type descriptor. There is no runtime call involved. The binding table
is always build from the parent type so the index of a specific binding
is the same in the parent derived-type or in the extended type.
Follow-up patches will deal cases not present here such as allocatable
polymorphic entities or pointers.
Reviewed By: jeanPerier, PeteSteinfeld
Differential Revision: https://reviews.llvm.org/D136189
Binding tables are needed to perform the fir.dispatch code generation.
The binding tables are defined as fir.global from the initial lowering.
This patch adds the ability to reconstruct the binding tables information
and store the procedure name and binding index for later use by the
fir.dispatch code generation.
Tests will come with follow up patch that makes full use of this information.
Reviewed By: jeanPerier
Differential Revision: https://reviews.llvm.org/D136141
`fir.box` and `fir.ref<fir.box>` are both lowered to LLVM as a
descriptor in memory. This is because fir.box of polymorphic and assumed
rank entities cannot be known at compile time, so fir.box cannot be
lowered to a struct value.
fir.load or fir.ref<fir.box> was previously lowered to a no-op,
propagating the operand descriptor storage as a result.
This is wrong because the operand descriptor storage may later be
modified, and these changes should not be visible in the loaded fir.box
that is an immutable SSA value.
Modify fir.load codegen for fir.box to make a copy into a new storage to
ensure the fir.box is immutable.
Differential Revision: https://reviews.llvm.org/D133779
This change makes sure that we compute the element size and the byte stride
based on the target representation of the element type.
For example, when REAL*10 is mapped to x86_fp80 each element occupies
16 bytes rather than 10 because of the padding.
Note that the size computation method used here actually returns
the distance between two adjacent element of the *same* type in memory
(which is equivalent to llvm::DataLayout::getTypeAllocSize()).
It does not return the number of bytes that may be overwritten
by storing a value of the specified type (e.g. what can be computed
via llvm::DataLayout::getTypeStoreSize(), but not available in
mlir::DataLayout).
Differential Revision: https://reviews.llvm.org/D133508
The patch introduces the required changes to update the pass declarations and definitions to use the new autogenerated files and allow dropping the old infrastructure.
Reviewed By: mehdi_amini, rriddle
Differential Review: https://reviews.llvm.org/D132838
The patch introduces the required changes to update the pass declarations and definitions to use the new autogenerated files and allow dropping the old infrastructure.
Reviewed By: mehdi_amini, rriddle
Differential Review: https://reviews.llvm.org/D132838
This patch "modernizes" the LLVM `insertvalue` and `extractvalue`
operations to use DenseI64ArrayAttr, since they only require an array of
indices and previously there was confusion about whether to use i32 or
i64 arrays, and to use assembly format.
Reviewed By: ftynse
Differential Revision: https://reviews.llvm.org/D131537
GCC and that specific build bot issued warnings turned errors, due to a narrowing conversion from `unsigned` to `int32_t`. Silence these via a static_cast.
This is the follow up on https://reviews.llvm.org/D130730 which goes through upstream code and removes creating constant values in favour of using the constant indices in GEP directly. This leads to less and more readable code and more compact IR as well.
Differential Revision: https://reviews.llvm.org/D130731
When an array is defined with "unknown" size, such as fir.array<2x?x5xi32>,
it should be converted to llvm.array<10 x i32>. The code so far has
been converting it to llvm.ptr<i32>.
Using a different function to check the if there starting are constant
dimensions, rather than if ALL dimensions are constant, it now produces
the correct array form.
Some tests has been updated, so they are now checking the new behaviour
rather than the old behaviour - so there's no need to add further tests
for this particular scenario.
This was originally found when compiling Spec 17 code, where an assert
in a GepOP was hit. That is bug #56141, which this change fixes.
Reviewed By: jeanPerier
Differential Revision: https://reviews.llvm.org/D129196
When computing the base addresses of an array slice to make a
descriptor, codegen generated two LLVM GEPs. The first to compute
the address of the base character element, and a second one to
compute the substring base inside that element.
The previous code did not care about getting the result of the first
GEP right: it used the base array LLVM type as the result type.
This used to work when opaque pointer were not enabled (the actual GEP
result type was probably applied in some later pass). But with opaque
pointers, the second GEP ends-up computing an offset of len*<LLVM array
type> instead of len*<character width>. A previous attempt to fix the
issue was done in D129079, but it does not cover the cases where the
array slice contains subcomponents before the substring
(e.g: array(:)%char_field(5:10)).
This patch fix the issue by computing the actual GEP result type in
codegen. There is also enough knowledge now so that a single GEP can be
generated instead of two.
Differential Revision: https://reviews.llvm.org/D129481
Flang C++ Style Guide tells us to avoid .has_value() in the predicate
expressions of control flow statements. I am treating ternary
expressions as control flow statements for the purpose of this patch.
Differential Revision: https://reviews.llvm.org/D128622
This patch is part of the upstreaming effort from fir-dev branch.
This is the last patch for the upstreaming effort.
Reviewed By: jeanPerier
Differential Revision: https://reviews.llvm.org/D129187
Co-authored-by: Eric Schweitz <eschweitz@nvidia.com>
When addressing a substring of a character array, codegen emits two
GEPs: one for to compute the address of the base element, and a second
one to address the first characters from that element.
The first GEP still returns the LLVM array type (if the FIR array type could be
translated to an array type. Therefore) so zero
indexes must be added to the second GEP in this case to cover for the
Fortran array dimensions before inserting the susbtring offset index.
Surprisingly, the previous code worked ok when MLIR emits none opaque
pointers. But with opaque pointers, the two GEPs are folded in an
invalid GEP where the substring offset becomes an offset for the outer
array dimension.
Note that I tried to fix the issue by modifying the first GEP to return the
element type, but this still gave bad results (here something might be
wrong with opaque pointer in MLIR or LLVM).
Differential Revision: https://reviews.llvm.org/D129079
This patch just make the code more similar
in each conversion.
This patch is part of the upstreaming effort from fir-dev branch.
Reviewed By: jeanPerier
Differential Revision: https://reviews.llvm.org/D129071
- Add verifiers that determine if an Op requires type parameters or
not and checks that the correct number of parameters is specified.
This patch is part of the upstreaming effort from fir-dev branch.
Reviewed By: PeteSteinfeld
Differential Revision: https://reviews.llvm.org/D128828
Co-authored-by: Eric Schweitz <eschweitz@nvidia.com>
Added new -lower-math-early option that defaults to 'true' that matches
the current math lowering scheme. If set to 'false', the intrinsic math
operations will be lowered to MLIR operations, which should potentially
enable more MLIR optimizations, or libm calls, if there is no corresponding
MLIR operation exists or if "precise" mode is requested.
The generated math MLIR operations are then converted to LLVM dialect
during codegen phase.
The -lower-math-early option is not exposed to users currently. I plan to
get rid of the "early" lowering completely, when "late" lowering
is robust enough to support all math intrinsics that are currently
supported via pgmath. So "late" mode will become default and -lower-math-early
option will not be needed. This will effectively eliminate the mandatory
dependency on pgmath in Fortran lowering, but this is WIP.
Differential Revision: https://reviews.llvm.org/D128385
This patch restores several calls to Optional::value() in preference
to Optional::operator*.
The Flang C++ Style Guide tells us to use x.value() where no presence
test is obviously protecting a *x reference to the contents.
Differential Revision: https://reviews.llvm.org/D128590
The upstreamed code was not incrementing the sliceOffset in multiples
of 3. This issue is fixed by using Offsets and incrementing by 3 during
every iteration.
In the conversion pattern, we were comparing the definingOp of an
operand with an FIR::UndefOp. Use LLVM::UndefOp for conversion.
Reviewed By: clementval, Leporacanthicus
Differential Revision: https://reviews.llvm.org/D128017
This patch is part of the upstreaming effort from fir-dev branch.
It also ensures all descriptors created inline complies with LBOUND
requirement that the lower bound is `1` when the related dimension
extent is zero.
This patch is part of the upstreaming effort from fir-dev branch.
Reviewed By: jeanPerier, PeteSteinfeld
Differential Revision: https://reviews.llvm.org/D128047
Co-authored-by: Eric Schweitz <eschweitz@nvidia.com>
Co-authored-by: Jean Perier <jperier@nvidia.com>
Fix some mismatch in format used in the file and reduce the diff with fir-dev
to be able to finish the upstreaming on this file.
This patch is part of the upstreaming effort from fir-dev branch.
Reviewed By: PeteSteinfeld, kiranchandramohan
Differential Revision: https://reviews.llvm.org/D127849
The previous XArrayCoorOp conversion forgot to change getting the
operands from OpAdaptor for upper bound and step of slice. This leads to
the fail of incompatible of types of codegen when slices are index type.
Reviewed By: kiranchandramohan, schweitz
Differential Revision: https://reviews.llvm.org/D125967
For arrays without a constant interior or arrays of character with
dynamic length arrays, the data types are converted to a pointer to the
element type, so the scale size of the constant extents needs to be
counted. The previous AllocaOp conversion does not consider the arrays
of character with dynamic length arrays, and the previous AllocMemOp
conversion does not consider arrays without a constant interior. This
fixes them and refactors the code so that it can be shared. Also add
the test cases.
Reviewed By: Jean Perier
Differential Revision: https://reviews.llvm.org/D124766
This patch adds lowering support for atomic read and write constructs.
Also added is pointer modelling code to allow FIR pointer like types to
be inferred and converted while lowering.
Reviewed By: kiranchandramohan
Differential Revision: https://reviews.llvm.org/D122725
Co-authored-by: Kiran Chandramohan <kiran.chandramohan@arm.com>
Fix https://github.com/flang-compiler/f18-llvm-project/issues/1416.
The `constRows` variable was being decremented too soon, causing the
last constant interior dimension extent being used to multiply the GEP
offset. This lead to wrong address computation and caused segfaults.
Note: also upstream fir.embox tests that can be upstreamed.
Differential Revision: https://reviews.llvm.org/D123130
Do not use the shift of a fir.embox to set lower bounds if there is
a fir.slice operand. This matches Fortran semantics where lower bounds
of array sections are ones.
Note that in case there is a fir.slice, the array shift may be provided
because it is used to calculate the origin/base address of an array slice.
Add a TODO for substring codegen since I noticed it was not upstreamed
yet and would cause some program to silently compile incorrectly.
Differential Revision: https://reviews.llvm.org/D123123
This commit restructures how TypeID is implemented to ideally avoid
the current problems related to shared libraries. This is done by changing
the "implicit" fallback path to use the name of the type, instead of using
a static template variable (which breaks shared libraries). The major downside to this
is that it adds some additional initialization costs for the implicit path. Given the
use of type names for uniqueness in the fallback, we also no longer allow types
defined in anonymous namespaces to have an implicit TypeID. To simplify defining
an ID for these classes, a new `MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID` macro
was added to allow for explicitly defining a TypeID directly on an internal class.
To help identify when types are using the fallback, `-debug-only=typeid` can be
used to log which types are using implicit ids.
This change generally only requires changes to the test passes, which are all defined
in anonymous namespaces, and thus can't use the fallback any longer.
Differential Revision: https://reviews.llvm.org/D122775
These are mostly small changes to make the code a bit clearer and more
consistent. Summary of changes:
* add missing namespace qualifiers (that's the preference in Flang)
* replace const member methods with static methods (to avoid passing
the *this pointer unnecessarily)
* rename `currentObjTy` (current object type) as `cpnTy` (component
type) - the latter feels more fitting
* remove redundant `return failure();` calls (` return
mlir::emitError` gives the same result)
* updated a few comments
Differential Revision: https://reviews.llvm.org/D122799
This patch addes some global initialization and global
box initialization tests.
This patch is part of the upstreaming effort from fir-dev branch.
Reviewed By: schweitz
Differential Revision: https://reviews.llvm.org/D122881
Co-authored-by: Jean Perier <jperier@nvidia.com>
Co-authored-by: Eric Schweitz <eschweitz@nvidia.com>
Follow-up of https://reviews.llvm.org/D121488 to ensure all descriptors
created inline complies with LBOUND requirement that the lower bound is
`1` when the related dimension extent is zero.
Both fir.xrebox and fir.xembox codegen is updated to enforce this
constraint.
Also upstream the "normalized lower bound" attribute that was added in fir-dev
since embox codegen was upstreamed, it is conflicting with this patch
otherwise.
Differential Revision: https://reviews.llvm.org/D122419
This patch adds the OpenMP conversion patterns to the FIR to LLVM
dialect lowering pass in Codegen. Appropriate legalization
conditions are also added. This ensures that a mix of FIR and OpenMP
dialects can be lowered to LLVM and OpenMP dialects. Also adds two
tests.
This is part of the upstreaming effort from the fir-dev branch in [1].
[1] https://github.com/flang-compiler/f18-llvm-project
Reviewed By: clementval, peixin
Differential Revision: https://reviews.llvm.org/D121793
Co-authored-by: Sourabh Singh Tomar <SourabhSingh.Tomar@amd.com>
Co-authored-by: Eric Schweitz <eschweitz@nvidia.com>
Currently, CGOps.h and FIROps.h contain `using namespace mlir;`. Every
file that includes one of these header files (directly and transitively)
will have the MLIR namespace enabled. With name-clashes within
sub-projects (LLVM and MLIR, MLIR and Flang), this is not desired. Also,
it is not possible to "un-use" a namespace once it is "used". Instead,
we should try to limit `using namespace` to implementation files (i.e.
*.cpp).
This patch removes `using namespace mlir;` from header files and adjusts
other files accordingly. In header and TableGen files, extra namespace
qualifier is added when referring to symbols defined in MLIR. Similar
approach is adopted in source files that didn't require many changes. In
files that would require a lot of changes, `using namespace mlir;` is
added instead.
Differential Revision: https://reviews.llvm.org/D120897
The front-end and the runtime are currently using the unix logical
representation, but lowering was not. These inconsistencies could
caused issues.
The only place that defines what the logical representation is in
lowering is the translation from FIR to LLVM (FIR is agnostic to the
actual representation). More precisely, the LLVM implementation of
`fir.convert` between `i1` and `fir.logcial` is what defines the
representation:
- `fir.convert` from `i1` to `fir.logical` defines the `.true.` and `.false.`
canonical representations
- `fir.convert` from `fir.logical` to `i1` decides what the test for
truth is.
Unix representation is:
- .true. canonical integer representation is 1
- .false. canonical integer representation is 0
- the test for truth is "integer representation != 0"
For the record, the previous representation that was used was in
codegen was:
- .true. canonical integer representation is -1 (all bits 1)
- .false. canonical integer representation is 0
- the test for truth is "integer representation lowest bit == 1"
Differential Revision: https://reviews.llvm.org/D121200