Lower procedure pointer components, except in the context of structure
constructor (left TODO).
Procedure pointer components lowering share most of the lowering logic
of procedure poionters with the following particularities:
- They are components, so an hlfir.designate must be generated to
retrieve the procedure pointer address from its derived type base.
- They may have a PASS argument. While there is no dispatching as with
type bound procedure, special care must be taken to retrieve the derived
type component base in this case since semantics placed it in the
argument list and not in the evaluate::ProcedureDesignator.
These components also bring a new level of recursive MLIR types since a
fir.type may now contain a component with an MLIR function type where
one of the argument is the fir.type itself. This required moving the
"derived type in construction" stackto the converter so that the object
and function type lowering utilities share the same state (currently the
function type utilty would end-up creating a new stack when lowering its
arguments, leading to infinite loops). The BoxedProcedurePass also
needed an update to deal with this recursive aspect.
Implement the C struct passing ABI on X86-64 for the trivial case where
the structs have one element. This is required to cover some cases of
BIND(C) derived type pass with the VALUE attribute.
In the context of C/Fortran interoperability (BIND(C)), it is possible
to give the VALUE attribute to a BIND(C) derived type dummy, which
according to Fortran 2018 18.3.6 - 2. (4) implies that it must be passed
like the equivalent C structure value. The way C structure value are
passed is ABI dependent.
LLVM does not implement the C struct ABI passing for LLVM aggregate type
arguments. It is up to the front-end, like clang is doing, to split the
struct into registers or pass the struct on the stack (llvm "byval") as
required by the target ABI.
So the logic for C struct passing sits in clang. Using it from flang
requires setting up a lot of clang context and to bridge FIR/MLIR
representation to clang AST representation for function signatures (in
both directions). It is a non trivial task.
See
https://stackoverflow.com/questions/39438033/passing-structs-by-value-in-llvm-ir/75002581#75002581.
Since BIND(C) struct are rather limited as opposed to generic C struct
(e.g. no bit fields). It is easier to provide a limited implementation
of it for the case that matter to Fortran.
This patch:
- Updates the generic target rewrite pass to keep track of both the new
argument type and attributes. The motivation for this is to be able to
tell if a previously marshalled argument is passed in memory (it is a C
pointer), or if it is being passed on the stack (has the byval llvm
attributes).
- Adds an entry point in the target specific codegen to marshal struct
arguments, and use it in the generic target rewrite pass.
- Implements limited support for the X86-64 case. So far, the support
allows telling if a struct must be passed in register or on the stack,
and to deal with the stack case. The register case is left TODO in this
patch.
The X86-64 ABI implemented is the System V ABI for AMD64 version 1.0
`nsw` is a flag for LLVM arithmetic operations meaning "no signed wrap".
If this keyword is present, the result of the operation is a poison
value if overflow occurs. Adding this keyword permits LLVM to re-order
integer arithmetic more aggressively.
In
https://discourse.llvm.org/t/rfc-changes-to-fircg-xarray-coor-codegen-to-allow-better-hoisting/75257/16
@vzakhari observed that adding nsw is useful to enable hoisting of
address calculations after some loops (or is at least a step in that
direction).
Classic flang also adds nsw to address calculations.
`llvm.fcmp` does support fast math attributes therefore so should
`arith.cmpf`.
The heavy churn in flang tests are because flang sets
`fastmath<contract>` by default on all operations that support the fast
math interface. Downstream users of MLIR should not be so effected.
This was requested in https://github.com/llvm/llvm-project/issues/74263
COMPLEX(10) passing by value and returning follows C complex
passing/returning ABI.
Cover the COMPLEX(10) case (X87 / __Complex long double on X86-64).
Implements System V ABI for AMD64 version 1.0.
The LLVM signatures match the one generated by clang for the __Complex
long double case.
Note that a FIXME is added for the COMPLEX(8) case that is incorrect in
a corner case. This will be fixed when dealing with passing derived type
by value in BIND(C) context.
…ortran_binding.h
... and into the ISO_Fortran_binding_wrapper.h header, through which the
compiler and runtime access its contents. This change ensures that user
code that #includes ISO_Fortran_binding.h within 'extern "C" {' doesn't
encounter mysterious namespace errors.
This update makes the user visible messages relating to features that
are not yet implemented be more consistent. I also cleaned up some of
the code.
For NYI messages that refer to intrinsics, I made sure the the message
begins with "not yet implemented: intrinsic:" to make them easier to
recognize.
I created some utility functions for NYI reporting that I put into
.../include/Optimizer/Support/Utils.h. These mainly convert MLIR types
to their Fortran equivalents.
I converted the NYI code to use the newly created utility functions.
This operation allows computing the address of descriptor fields. It is
needed to help attaching descriptors in OpenMP/OpenACC target region.
The pointers inside the descriptor structure must be mapped too, but the
fir.box is abstract, so these fields cannot be computed with
fir.coordinate_of.
To preserve the abstraction of the descriptor layout in FIR, introduce
an operation specifically to !fir.ref<fir.box<>> address fields based on
field names (base_addr or derived_type).
Propagate fast math flags through complex number lowering (when lowering
fir.*c directly to llvm floating point operations).
The lowering path through the MLIR complex dialect is unchanged.
This leads to a small improvement in spec2017 fotonik3d_r.
!llvm.ptr<T> typed pointers are depreciated in MLIR LLVM dialects. Flang
codegen still generated them and relied on mlir.llvm codegen to LLVM to
turn them into opaque pointers.
This patch update FIR codegen to directly emit and work with LLVM opaque
pointers.
Addresses https://github.com/llvm/llvm-project/issues/69303
- All places generating GEPs need to add an extra type argument with the
base type (the T that was previously in the llvm.ptr<T> of the base).
- llvm.alloca must also be provided the object type. In the process, I
doscovered that we were shamelessly copying all the attribute from
fir.alloca to the llvm.alloca, which makes no sense for the operand
segments. The updated code that cannot take an attribute dictionnary in
the llvm.alloca builder with opaque pointers only propagate the "pinned"
and "bindc_name" attributes to help debugging the generated IR.
- Updating all the places that rely on getting the llvm object type from
lowered llvm.ptr<T> arguments to get it from a type conversion of the
original fir types.
- Updating all the places that were generating llvm.ptr<T> types to
generate the opaque llvm.ptr type.
- Updating all the codegen tests checking generated MLIR llvm dialect.
Many tests are testing directly LLVM IR, and this change is a no-op for
those (which is expected).
The ultimate intention is to have this pass enabled by default whenever
we are optimizing for speed. But for now, just add the arguments so this
can be more easily tested.
PR: https://github.com/llvm/llvm-project/pull/68595
This is important to ensure that tags end up in the same trees that were
created in the FIR TBAA pass. If they are in different trees then
everything in one tree will be assumed to MayAlias with everything in the
other tree. This leads to poor performance.
@vzakhari requested that the old (not-per-function) trees are
maintained so I left the old test intact.
PR: https://github.com/llvm/llvm-project/pull/68437
This interface allows (HL)FIR passes to add TBAA information to fir.load
and fir.store. If present, these TBAA tags take precedence over those
added during CodeGen.
We can't reuse mlir::LLVMIR::AliasAnalysisOpInterface because that uses
the mlir::LLVMIR namespace so it tries to define methods for fir
operations in the wrong namespace. But I did re-use the tbaa tag type to
minimise boilerplate code.
The new builders are to preserve the old interface without the tbaa tag.
The goal is to progressively propagate all the derived type info that is
currently in the runtime type info globals into a FIR operation that can
be easily queried and used by FIR/HLFIR passes.
When this will be complete, the last step will be to stop generating the
runtime info global in lowering, but to do that later in or just before
codegen to keep the FIR files readable (on the added type-info.f90
tests, the lowered runtime info globals takes a whooping 2.6 millions
characters on 1600 lines of the FIR textual output. The fir.type_info that
contains all the info required to generate those globals for such
"trivial" types takes 1721 characters on 9 lines).
So far this patch simply starts by replacing the fir.dispatch_table
operation by the fir.type_info operation and to add the noinit/
nofinal/nodestroy flags to it. These flags will soon be used in HLFIR to
better rewrite hlfir.assign with derived types.
Since HLFIR bufferization can introduce shallow copies of derived
type values we have to be careful not to treat these load/store
operations as data-only-accesses. If a derived type has descriptor
members, we attach any-access tag now.
This is not standard but is vastly expected by existing code.
This was implemented by https://reviews.llvm.org/D149877 for simple
scalars, but MLIR lacked a generic way to deal with aggregate types
(arrays and derived type).
Support was recently added in
https://github.com/llvm/llvm-project/pull/65508. Leverage it to zero
initialize all types.
This revision replaces the LLVM dialect NullOp by the recently
introduced ZeroOp. The ZeroOp is more generic in the sense that it
represents zero values of any LLVM type rather than null pointers only.
This is a follow to https://github.com/llvm/llvm-project/pull/65508
This fixes a bug where functions generated by the MLIR Math dialect, for
example ipowi, would fail to link with link.exe on Windows due to having
linkonce linkage but no associated comdat. Adding the comdat on ELF also
allows linkers to perform better garbage collection in the binary.
Simply adding comdats to all functions with this linkage type should
also cover future cases where linkonce or linkonce_odr functions might
be necessary.
While creating a temporary alloca for a box in OpenMp region, the
insertion point should be the OpenMP region block instead of the
function entry block.
This vector keeps tracks of recursive types through the recursive invocations
of `convertType()`. However this is something only useful for some specific
cases, in which the dedicated conversion callbacks can handle this stack
privately.
This allows removing a mutable member of the type converter.
Reviewed By: springerm
Differential Revision: https://reviews.llvm.org/D158351
ConversionPatterns do not (and should not) modify the type converter that they are using.
* Make `ConversionPattern::typeConverter` const.
* Make member functions of the `LLVMTypeConverter` const.
* Conversion patterns take a const type converter.
* Various helper functions (that are called from patterns) now also take a const type converter.
Differential Revision: https://reviews.llvm.org/D157601
For character type with unknown length we end up generating
a GEP with the base type `llvm.ptr<i[width]>`. The GEP produces
the address of the first element of the slice, and it should be
using the offset computed in the number of characters, while we were
providing the offset in bytes.
Simple reproducer fails with and w/o HLFIR:
```
program test
integer,parameter :: ck = 4
character(:,ck),allocatable :: res(:,:)
allocate(character(3,ck) :: res(2,2))
res(1,1) = ck_'111'
res(1,2) = ck_'222'
res(2,1) = ck_'333'
res(2,2) = ck_'444'
call check(res)
contains
subroutine check(res)
character(:,ck),allocatable :: res(:,:)
print *, res(2,:)
end subroutine check
end program test
```
Reviewed By: clementval
Differential Revision: https://reviews.llvm.org/D156849
The current representation of TBAA is the very last in-tree user of the `llvm.metadata` operation.
Using ops to model metadata has a few disadvantages:
* Building a graph has to be done through some weakly typed indirection mechanism such as `SymbolRefAttr`
* Creating the metadata has to be done through a builder within a metadata op.
* It is not multithreading safe as operation insertion into the same block is not thread-safe
This patch therefore converts TBAA metadata into an attribute representation, in a similar manner as it has been done for alias groups and access groups in previous patches.
This additionally has the large benefit of giving us more "correctness by construction" as it makes things like cycles in a TBAA graph, or references to an incorrectly typed metadata node impossible.
Differential Revision: https://reviews.llvm.org/D155444
Identify multidimensional array indices in subcomponents and
convert them from column-major to row-major ordering.
This fixes codegen for fircg.ext_array_coor, fircg.ext_embox and,
possibly, fircg.ext_rebox.
Fixes https://github.com/llvm/llvm-project/issues/62038
Reviewed By: jeanPerier
Differential Revision: https://reviews.llvm.org/D154214
The code generation of the fir.embox op creating descriptors for
array substring with a non constant length base was using the
substring length to compute the first dimension result stride.
Fix it to use the input length instead.
Reviewed By: PeteSteinfeld
Differential Revision: https://reviews.llvm.org/D154086
fir.rebox is emitting an llvm.sdiv to compute the character length
given the byte size from the input descriptor.
Inside a fir.global, this is not needed given the target length must
be accessible via the type, and it caused MLIR to fail LLVM IR
code generation (and crash).
Use the input type length when available instead.
Reviewed By: PeteSteinfeld, vzakhari
Differential Revision: https://reviews.llvm.org/D154072
On platforms which support COMDAT sections we should use them when
linkonce or linkonce_odr linkage is requested. This is required on
Windows (PE/COFF) and provides better behaviour than weak symbols on
ELF-based platforms.
This patch also reverts string literals to use linkonce instead of
internal linkage now that comdats are supported.
Differential Revision: https://reviews.llvm.org/D153768
Previously only a constant reference was stored in the FirOpBuilder.
However, a lot of code was merged using
FirOpBuilder builder{rewriter, getKindMapping(mod)};
This is incorrect because the KindMapping returned will go out of scope
as soon as FirOpBuilder's constructor had run. This led to an infinite
loop running some tests using HLFIR (because the stack space containing
the kind mapping was re-used and corrupted).
One solution would have just been to fix the incorrect call sites,
however, as a large number of these had already made it past review, I
decided to instead change FirOpBuilder to store its own copy of the
KindMapping. This is not costly because nearly every time we construct a
KindMapping is exclusively to construct a FirOpBuilder. To make this
common pattern simpler, I added a new constructor to FirOpBuilder which
calls getKindMapping().
Differential Revision: https://reviews.llvm.org/D151881
The information needed for translation is now encoded in the dialect
operations and does not require a dedicated pass to be extracted.
Remove the obsolete passes that were performing operand legalization.
Reviewed By: jeanPerier
Differential Revision: https://reviews.llvm.org/D150248
Instead of filling uninitialized global variables with "undef",
initialize them with 0. Only for Integer, Float or Logical type
variables. Complex, user defined data structures, arrays, etc
are not supported at this point.
This patch fixes the main problem of
https://github.com/llvm/llvm-project/issues/62432
Reviewed By: jeanPerier
Differential Revision: https://reviews.llvm.org/D149877
This resolves issues with running out of stack on examples like
https://fortran-lang.discourse.group/t/modern-fortran-sample-code/2019/18
reported by @clementval.
When target rewrite creates alloca(s) around a call, we need to insert
stacksave/stackrestore to free the allocated stack. Better performant
code may be achieved by placing the alloca(s) outside of loops,
but the placement has to behave correctly with regards to OpenMP/OpenACC/etc.
dialect operations that have special representation for "private"
objects. This is a concervative fix for correctness issue.
Differential Revision: https://reviews.llvm.org/D149222
Fir.GlobalOp's currently do not respect attributes that
are applied to them, this change will do two things:
- Allow lowering of arbitrary attributes applied to
Fir.GlobalOp's to LLVMGlobalOp's during CodeGen
- Allow printing and parsing of arbitrarily applied attributes
This allows applying other dialects attributes (or other
fir attributes) to fir.GlobalOps on the fly and have them
exist in the resulting LLVM dialect IR or FIR IR.
Reviewer: jeanPerier
Differential Revision: https://reviews.llvm.org/D148352
The code was using the original operand of the operation, while
it should have been using the remapped operands via the adaptor.
Differential Revision: https://reviews.llvm.org/D148587
Function arguments or return values that are complex floating point values
aren't correctly lowered for Windows x86 32-bit and 64-bit targets.
See: https://github.com/llvm/llvm-project/issues/61976
Add targets that are specific for these platforms and OS.
With thanks to @mstorsjo for pointing out the fix.
Reviewed By: vzakhari
Differential Revision: https://reviews.llvm.org/D147768
When dealing with "derived_array(j)%component" where derived_array
is not a contiguous array, but for which we know the extent, lowering
generates a fir.array_coor op on a !fir.box<!fir.array<cst x T>> with
a fir.slice containing "j" in the component path.
Codegen first computes "derived_array(j)" address using the byte
strides inside the descriptor, and then computes the offset of "j"
from that address with a second GEP.
The type of the address in that second GEP matters since "j" is passed
in the GEP via an index indicating its component position in the type.
The code was using the LLVM type of "derived_array" instead of
"derived_array(j)".
In general, with fir.box, the extent ("cst" above) is unknown and those
types match. But if the extent of "derived_array" is a compile time
constant, its LLVM type will be [cst x T] instead of T*, and the produced
GEP will compute the address of the nth T instead of the nth component
inside T leading to undefined behaviors.
Fix this by computing the element type for the second GEP.
Differential Revision: https://reviews.llvm.org/D148226
After the extraction of the TypeConverter, move the header files
to the include dir so the shared library build is fine.
Reviewed By: PeteSteinfeld
Differential Revision: https://reviews.llvm.org/D147979