diff options
Diffstat (limited to 'flang')
868 files changed, 20907 insertions, 9366 deletions
diff --git a/flang/docs/CMakeLists.txt b/flang/docs/CMakeLists.txt index 568f942..b183d6a 100644 --- a/flang/docs/CMakeLists.txt +++ b/flang/docs/CMakeLists.txt @@ -88,7 +88,7 @@ function (gen_rst_file_from_td output_file td_option source target) endif() get_filename_component(TABLEGEN_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/${source}" DIRECTORY) list(APPEND LLVM_TABLEGEN_FLAGS "-I${TABLEGEN_INCLUDE_DIR}") - list(APPEND LLVM_TABLEGEN_FLAGS "-I${CMAKE_CURRENT_SOURCE_DIR}/../../clang/include/clang/Driver/") + list(APPEND LLVM_TABLEGEN_FLAGS "-I${CMAKE_CURRENT_SOURCE_DIR}/../../clang/include/clang/Options/") clang_tablegen(Source/${output_file} ${td_option} SOURCE ${source} TARGET ${target}) endfunction() diff --git a/flang/docs/Directives.md b/flang/docs/Directives.md index 2f16a8d..5640e44 100644 --- a/flang/docs/Directives.md +++ b/flang/docs/Directives.md @@ -32,6 +32,22 @@ A list of non-standard directives supported by Flang end end interface ``` + Note that it's not allowed to pass array actual argument to `ignore_trk(R)` + dummy argument that is a scalar with `VALUE` attribute, for example: +``` + interface + subroutine s(b) + !dir$ ignore_tkr(r) b + integer, value :: b + end + end interface + integer :: a(5) + call s(a) +``` + The reason for this limitation is that scalars with `VALUE` attribute can + be passed in registers, so it's not clear how lowering should handle this + case. (Passing scalar actual argument to `ignore_tkr(R)` dummy argument + that is a scalar with `VALUE` attribute is allowed.) * `!dir$ assume_aligned desginator:alignment`, where designator is a variable, maybe with array indices, and alignment is what the compiler should assume the alignment to be. E.g A:64 or B(1,1,1):128. The alignment should be a power of 2, @@ -41,6 +57,15 @@ A list of non-standard directives supported by Flang * `!dir$ vector always` forces vectorization on the following loop regardless of cost model decisions. The loop must still be vectorizable. [This directive currently only works on plain do loops without labels]. +* `!dir$ vector vectorlength({fixed|scalable|<num>|<num>,fixed|<num>,scalable})` + specifies a hint to the compiler about the desired vectorization factor. If + `fixed` is used, the compiler should prefer fixed-width vectorization. + Scalable vectorization instructions may still be used with a fixed-width + predicate. If `scalable` is used the compiler should prefer scalable + vectorization, though it can choose to use fixed length vectorization or not + at all. `<num>` means that the compiler should consider using this specific + vectorization factor, which should be an integer literal. This directive + currently has the same limitations as `!dir$ vector always`. * `!dir$ unroll [n]` specifies that the compiler ought to unroll the immediately following loop `n` times. When `n` is `0` or `1`, the loop should not be unrolled at all. When `n` is `2` or greater, the loop should be unrolled exactly `n` @@ -52,6 +77,9 @@ A list of non-standard directives supported by Flang integer that specifying the unrolling factor. When `N` is `0` or `1`, the loop should not be unrolled at all. If `N` is omitted the optimizer will selects the number of times to unroll the loop. +* `!dir$ prefetch designator[, designator]...`, where the designator list can be + a variable or an array reference. This directive is used to insert a hint to + the code generator to prefetch instructions for memory references. * `!dir$ novector` disabling vectorization on the following loop. * `!dir$ nounroll` disabling unrolling on the following loop. * `!dir$ nounroll_and_jam` disabling unrolling and jamming on the following loop. diff --git a/flang/docs/Extensions.md b/flang/docs/Extensions.md index c9cc027..593cd99 100644 --- a/flang/docs/Extensions.md +++ b/flang/docs/Extensions.md @@ -946,6 +946,17 @@ print *, [(j,j=1,10)] This design allows format-driven input with `DT` editing to retain control over advancement in child input, while otherwise allowing it. +* When output takes place to a file under `ACCESS="STREAM"` after + repositioning it to an earlier position, some compilers will + truncate the file; this behavior is similar to the implicit + `ENDFILE` that takes place under sequential output after a + `BACKSPACE` or `REWIND` statement. + Truncation of streams is not specified in the standard, however, + and it does not take place with all compilers. + In this one, truncation is optional; it occurs by default, + but it can be disabled via `FORT_TRUNCATE_STREAM=0` in the + environment at execution time. + ## De Facto Standard Features * `EXTENDS_TYPE_OF()` returns `.TRUE.` if both of its arguments have the diff --git a/flang/docs/FlangDriver.md b/flang/docs/FlangDriver.md index 3286171..9953f22 100644 --- a/flang/docs/FlangDriver.md +++ b/flang/docs/FlangDriver.md @@ -76,7 +76,7 @@ will ignore it when used without `Xflang`. As hinted above, `flang` and `flang -fc1` are two separate tools. The fact that these tools are accessed through one binary, `flang`, is just an implementation detail. Each tool has a separate list of options, albeit defined -in the same file: `clang/include/clang/Driver/Options.td`. +in the same file: `clang/include/clang/Options/Options.td`. The separation helps us split various tasks and allows us to implement more specialised tools. In particular, `flang` is not aware of various @@ -112,7 +112,7 @@ in terms of Clang's driver library, `clangDriver`. This approach allows us to: as linkers and assemblers. One implication of this dependency on Clang is that all of Flang's compiler options are defined alongside Clang's options in -`clang/include/clang/Driver/Options.td`. For options that are common for both +`clang/include/clang/Options/Options.td`. For options that are common for both Flang and Clang, the corresponding definitions are shared. Internally, a `clangDriver` based compiler driver works by creating actions @@ -242,7 +242,7 @@ Adding a new compiler option in Flang consists of two steps: ### Option Definition All of Flang's compiler and frontend driver options are defined in -`clang/include/clang/Driver/Options.td` in Clang. When adding a new option to +`clang/include/clang/Options/Options.td` in Clang. When adding a new option to Flang, you will either: * extend the existing definition for an option that is already available in one of Clang's drivers (e.g. `clang`), but not yet available in Flang, or @@ -314,7 +314,7 @@ add, you will have to add a dedicated entry in that enum (e.g. `ParseSyntaxOnly` for `-fsyntax-only`) and a corresponding `case` in `ParseFrontendArgs` function in the `CompilerInvocation.cpp` file, e.g.: ```cpp - case clang::driver::options::OPT_fsyntax_only: + case clang::options::OPT_fsyntax_only: opts.programAction = ParseSyntaxOnly; break; ``` diff --git a/flang/docs/Intrinsics.md b/flang/docs/Intrinsics.md index bfda5f3..6451fc4 100644 --- a/flang/docs/Intrinsics.md +++ b/flang/docs/Intrinsics.md @@ -1288,6 +1288,40 @@ program chdir_func end program chdir_func ``` +### Non-Standard Intrinsics: FLUSH + +#### Description +`FLUSH(UNIT)` causes all pending I/O operations for the file connected to the +specified unit to be completed. If `UNIT` is omitted, all units are flushed. + +#### Arguments + +| | | +|------------|---------------------------------------------------------------------------------------------------| +| `UNIT` | (Optional) The unit number of an open file. If omitted, all open units are flushed. The type shall be `INTEGER`. | + +#### Usage and Info + +- **Standard:** GNU extension +- **Class:** Subroutine +- **Syntax:** `CALL FLUSH([UNIT])` + +#### Example +```Fortran +program demo_flush + integer :: unit + + ! Flush all units + call flush() + + ! Flush specific unit + open(unit=10, file='output.dat') + write(10, *) 'Data' + call flush(10) + close(10) +end program demo_flush +``` + ### Non-Standard Intrinsics: FSEEK and FTELL #### Description @@ -1379,3 +1413,88 @@ This is prefixed by `STRING`, a colon and a space. - **Standard:** GNU extension - **Class:** subroutine - **Syntax:** `CALL PERROR(STRING)` + +<<<<<<< HEAD +### Non-Standard Intrinsics: SRAND + +#### Description +`SRAND` reinitializes the pseudo-random number generator called by `RAND` and `IRAND`. +The new seed used by the generator is specified by the required argument `SEED`. + +#### Usage and Info + +- **Standard:** GNU extension +- **Class:** Subroutine +- **Syntax:** `CALL SRAND(SEED)` + +### Non-Standard Intrinsics: IRAND + +#### Description +`IRAND(FLAG)` returns a pseudo-random number from a uniform distribution between 0 and a system-dependent limit. +If `FLAG` is 0, the next number in the current sequence is returned; +If `FLAG` is 1, the generator is restarted by `CALL SRAND(0)`; +If `FLAG` has any other value, it is used as a new seed with `SRAND`. +The return value is of `INTEGER` type of kind 4. + +#### Usage and Info + +- **Standard:** GNU extension +- **Class:** function +- **Syntax:** `RESULT = IRAND(I)` + +### Non-Standard Intrinsics: RAND + +#### Description +`RAND(FLAG)` returns a pseudo-random number from a uniform distribution between 0 and 1. +If `FLAG` is 0, the next number in the current sequence is returned; +If `FLAG` is 1, the generator is restarted by `CALL SRAND(0)`; +If `FLAG` has any other value, it is used as a new seed with `SRAND`. +The return value is of `REAL` type with the default kind. + +#### Usage and Info + +- **Standard:** GNU extension +- **Class:** function +- **Syntax:** `RESULT = RAND(I)` + +### Non-Standard Intrinsics: SHOW_DESCRIPTOR + +#### Description +`SHOW_DESCRIPTOR(VAR)` prints (on the C stderr stream) a contents of a descriptor for the variable VAR, +which can be of any type and rank, including scalars. +Requires use of flang_debug module. + +Here is an example of its output: +``` +Descriptor @ 0x7ffe506fc368: + base_addr 0x55944caef0f0 + elem_len 4 + version 20240719 + rank 1 + type 9 "INTEGER(kind=4)" + attribute 2 (allocatable) + extra 0 + addendum 0 + alloc_idx 0 + dim[0] lower_bound 1 + extent 5 + sm 4 +``` + +#### Usage and Info +- **Standard:** flang extension +- **Class:** subroutine +- **Syntax:** `CALL show_descriptor(VAR)` + +#### Example +```Fortran +subroutine test + use flang_debug + implicit none + character(len=9) :: c = 'Hey buddy' + integer :: a(5) + call show_descriptor(c) + call show_descriptor(c(1:3)) + call show_descriptor(a) +end subroutine test +``` diff --git a/flang/docs/OpenMPSupport.md b/flang/docs/OpenMPSupport.md index 81f5f9f..6ef0f2a 100644 --- a/flang/docs/OpenMPSupport.md +++ b/flang/docs/OpenMPSupport.md @@ -40,12 +40,12 @@ Note : No distinction is made between the support in Parser/Semantics, MLIR, Low | target data construct | P | device clause not supported | | target construct | P | device clause not supported | | target update construct | P | device clause not supported | -| declare target directive | P | | +| declare target directive | Y | | | teams construct | Y | | -| distribute construct | P | dist_schedule clause not supported | -| distribute simd construct | P | dist_schedule and linear clauses are not supported | -| distribute parallel loop construct | P | dist_schedule clause not supported | -| distribute parallel loop simd construct | P | dist_schedule and linear clauses are not supported | +| distribute construct | Y | | +| distribute simd construct | P | linear clauses are not supported | +| distribute parallel loop construct | Y | | +| distribute parallel loop simd construct | P | linear clauses are not supported | | depend clause | Y | | | declare reduction construct | N | | | atomic construct extensions | Y | | @@ -53,13 +53,13 @@ Note : No distinction is made between the support in Parser/Semantics, MLIR, Low | cancellation point construct | Y | | | parallel do simd construct | P | linear clause not supported | | target teams construct | P | device clause not supported | -| teams distribute construct | P | dist_schedule clause not supported | -| teams distribute simd construct | P | dist_schedule and linear clauses are not supported | -| target teams distribute construct | P | device and dist_schedule clauses are not supported | -| teams distribute parallel loop construct | P | dist_schedule clause not supported | -| target teams distribute parallel loop construct | P | device and dist_schedule clauses are not supported | -| teams distribute parallel loop simd construct | P | dist_schedule and linear clauses are not supported | -| target teams distribute parallel loop simd construct | P | device, dist_schedule and linear clauses are not supported | +| teams distribute construct | Y | | +| teams distribute simd construct | P | linear clause is not supported | +| target teams distribute construct | P | device clause is not supported | +| teams distribute parallel loop construct | Y | | +| target teams distribute parallel loop construct | P | device clause is not supported | +| teams distribute parallel loop simd construct | P | linear clause is not supported | +| target teams distribute parallel loop simd construct | P | device and linear clauses are not supported | ## Extensions ### ATOMIC construct diff --git a/flang/docs/ReleaseNotes.md b/flang/docs/ReleaseNotes.md index 6a285f8..7993678 100644 --- a/flang/docs/ReleaseNotes.md +++ b/flang/docs/ReleaseNotes.md @@ -1,18 +1,20 @@ <!-- If you want to modify sections/contents permanently, you should modify both ReleaseNotes.md and ReleaseNotesTemplate.txt. --> -# Flang |version| (In-Progress) Release Notes +# Flang {{version}} {{in_progress}}Release Notes -> **warning** -> -> These are in-progress notes for the upcoming LLVM |version| release. -> Release notes for previous releases can be found on [the Download -> Page](https://releases.llvm.org/download.html). +````{only} PreRelease +```{warning} + These are in-progress notes for the upcoming LLVM {{version}} release. + Release notes for previous releases can be found on [the Download + Page](https://releases.llvm.org/download.html). +``` +```` ## Introduction This document contains the release notes for the Flang Fortran frontend, -part of the LLVM Compiler Infrastructure, release |version|. Here we +part of the LLVM Compiler Infrastructure, release {{version}}. Here we describe the status of Flang in some detail, including major improvements from the previous release and new feature work. For the general LLVM release notes, see [the LLVM @@ -45,7 +47,6 @@ page](https://llvm.org/releases/). ## New Issues Found - ## Additional Information Flang's documentation is located in the `flang/docs/` directory in the diff --git a/flang/docs/ReleaseNotesTemplate.txt b/flang/docs/ReleaseNotesTemplate.txt index 2ccf547..888da4d 100644 --- a/flang/docs/ReleaseNotesTemplate.txt +++ b/flang/docs/ReleaseNotesTemplate.txt @@ -1,18 +1,20 @@ <!-- If you want to modify sections/contents permanently, you should modify both ReleaseNotes.md and ReleaseNotesTemplate.txt. --> -# Flang |version| (In-Progress) Release Notes +# Flang {{version}} {{in_progress}}Release Notes -> **warning** -> -> These are in-progress notes for the upcoming LLVM |version| release. -> Release notes for previous releases can be found on [the Download -> Page](https://releases.llvm.org/download.html). +````{only} PreRelease +```{warning} +These are in-progress notes for the upcoming LLVM {{version}} release. +Release notes for previous releases can be found on [the Download +Page](https://releases.llvm.org/download.html). +``` +```` ## Introduction This document contains the release notes for the Flang Fortran frontend, -part of the LLVM Compiler Infrastructure, release |version|. Here we +part of the LLVM Compiler Infrastructure, release {{version}}. Here we describe the status of Flang in some detail, including major improvements from the previous release and new feature work. For the general LLVM release notes, see [the LLVM diff --git a/flang/docs/RuntimeEnvironment.md b/flang/docs/RuntimeEnvironment.md index c7a3dfbb..ccc401c 100644 --- a/flang/docs/RuntimeEnvironment.md +++ b/flang/docs/RuntimeEnvironment.md @@ -55,3 +55,14 @@ The default is 72. Set `NO_STOP_MESSAGE=1` to disable the extra information about IEEE floating-point exception flags that the Fortran language standard requires for `STOP` and `ERROR STOP` statements. + +## `FORT_TRUNCATE_STREAM` + +Set `FORT_TRUNCATE_STREAM=1` to make output to a formatted unit +with `ACCESS="STREAM"` truncate the file when the unit has been +repositioned via `POS=` to an earlier point in the file. +This behavior is analogous to the implicit writing of an ENDFILE record +when output takes place to a sequential unit after +executing a `BACKSPACE` or `REWIND` statement. +Truncation of a stream-access unit is common to several other +compilers, but it is not mentioned in the standard. diff --git a/flang/docs/conf.py b/flang/docs/conf.py index 0942dbf..6395834 100644 --- a/flang/docs/conf.py +++ b/flang/docs/conf.py @@ -10,6 +10,7 @@ # serve to show the default. from datetime import date + # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. @@ -46,6 +47,14 @@ source_suffix = { } myst_heading_anchors = 6 +# Enable myst's substitution extension since markdown files cannot use the +# |version| and |release| substitutions available to .rst files. +myst_enable_extensions = ["substitution"] + +# The substitutions to use in markdown files. This contains unconditional +# substitutions, but more may be added once the configuration is obtained. +myst_substitutions = {"in_progress": "(In-Progress) " if tags.has("PreRelease") else ""} + import sphinx # The encoding of source files. @@ -268,3 +277,22 @@ texinfo_documents = [ # How to display URL addresses: 'footnote', 'no', or 'inline'. # texinfo_show_urls = 'footnote' + + +# This can be treated as its own sphinx extension. setup() will be called by +# sphinx. In it, register a function to be called when the configuration has +# been initialized. The configuration will contain the values of the -D options +# passed to sphinx-build on the command line. +# +# See llvm/cmake/modules/AddSphinxTarget.cmake for details on how sphinx-build +# is invoked. +def setup(app): + app.connect("config-inited", myst_substitutions_update) + + +# Override the myst_parser substitutions map after the configuration has been +# initialized. +def myst_substitutions_update(app, config): + config.myst_substitutions.update( + {"release": config.release, "version": config.version} + ) diff --git a/flang/examples/FeatureList/FeatureList.cpp b/flang/examples/FeatureList/FeatureList.cpp index 225a655..bb55a81 100644 --- a/flang/examples/FeatureList/FeatureList.cpp +++ b/flang/examples/FeatureList/FeatureList.cpp @@ -348,6 +348,7 @@ public: READ_FEATURE(TeamValue) READ_FEATURE(ImageSelector) READ_FEATURE(ImageSelectorSpec) + READ_FEATURE(ImageSelectorSpec::Notify) READ_FEATURE(ImageSelectorSpec::Stat) READ_FEATURE(ImageSelectorSpec::Team_Number) READ_FEATURE(ImplicitPart) @@ -445,6 +446,7 @@ public: READ_FEATURE(ObjectDecl) READ_FEATURE(OldParameterStmt) READ_FEATURE(OmpAlignedClause) + READ_FEATURE(OmpAllocateDirective) READ_FEATURE(OmpBeginDirective) READ_FEATURE(OmpBeginLoopDirective) READ_FEATURE(OmpBeginSectionsDirective) @@ -541,7 +543,6 @@ public: READ_FEATURE(OpenMPCancellationPointConstruct) READ_FEATURE(OpenMPConstruct) READ_FEATURE(OpenMPCriticalConstruct) - READ_FEATURE(OpenMPDeclarativeAllocate) READ_FEATURE(OpenMPDeclarativeConstruct) READ_FEATURE(OpenMPDeclareReductionConstruct) READ_FEATURE(OpenMPDeclareSimdConstruct) @@ -550,7 +551,6 @@ public: READ_FEATURE(OmpAtomicDefaultMemOrderClause) READ_FEATURE(OpenMPFlushConstruct) READ_FEATURE(OpenMPLoopConstruct) - READ_FEATURE(OpenMPExecutableAllocate) READ_FEATURE(OpenMPAllocatorsConstruct) READ_FEATURE(OpenMPRequiresConstruct) READ_FEATURE(OpenMPSimpleStandaloneConstruct) diff --git a/flang/include/flang/Common/enum-set.h b/flang/include/flang/Common/enum-set.h index e048c66..ce11294 100644 --- a/flang/include/flang/Common/enum-set.h +++ b/flang/include/flang/Common/enum-set.h @@ -217,6 +217,16 @@ public: private: bitsetType bitset_{}; }; + +namespace detail { +template <typename...> struct IsEnumSetTest { + static constexpr bool value{false}; +}; +template <typename E, size_t B> struct IsEnumSetTest<EnumSet<E, B>> { + static constexpr bool value{true}; +}; +} // namespace detail +template <typename T> constexpr bool IsEnumSet{detail::IsEnumSetTest<T>::value}; } // namespace Fortran::common template <typename ENUM, std::size_t values> diff --git a/flang/include/flang/Evaluate/check-expression.h b/flang/include/flang/Evaluate/check-expression.h index 2ff78d7..d11fe22c 100644 --- a/flang/include/flang/Evaluate/check-expression.h +++ b/flang/include/flang/Evaluate/check-expression.h @@ -163,8 +163,8 @@ extern template bool IsErrorExpr(const Expr<SomeType> &); std::optional<parser::Message> CheckStatementFunction( const Symbol &, const Expr<SomeType> &, FoldingContext &); -bool MayNeedCopy(const ActualArgument *, const characteristics::DummyArgument *, - FoldingContext &, bool forCopyOut); +std::optional<bool> ActualArgNeedsCopy(const ActualArgument *, + const characteristics::DummyArgument *, FoldingContext &, bool forCopyOut); } // namespace Fortran::evaluate #endif diff --git a/flang/include/flang/Evaluate/intrinsics.h b/flang/include/flang/Evaluate/intrinsics.h index fc1c8b2..8bece08 100644 --- a/flang/include/flang/Evaluate/intrinsics.h +++ b/flang/include/flang/Evaluate/intrinsics.h @@ -63,7 +63,7 @@ struct SpecificIntrinsicFunctionInterface : public characteristics::Procedure { // Generic intrinsic classes from table 16.1 ENUM_CLASS(IntrinsicClass, atomicSubroutine, collectiveSubroutine, elementalFunction, elementalSubroutine, inquiryFunction, pureSubroutine, - impureSubroutine, transformationalFunction, noClass) + impureFunction, impureSubroutine, transformationalFunction, noClass) class IntrinsicProcTable { private: diff --git a/flang/include/flang/Evaluate/tools.h b/flang/include/flang/Evaluate/tools.h index 7f64d23..4248e3a 100644 --- a/flang/include/flang/Evaluate/tools.h +++ b/flang/include/flang/Evaluate/tools.h @@ -1110,6 +1110,9 @@ bool IsArraySection(const Expr<SomeType> &expr); // Predicate: does an expression contain constant? bool HasConstant(const Expr<SomeType> &); +// Predicate: Does an expression contain a component +bool HasStructureComponent(const Expr<SomeType> &expr); + // Utilities for attaching the location of the declaration of a symbol // of interest to a message. Handles the case of USE association gracefully. parser::Message *AttachDeclaration(parser::Message &, const Symbol &); diff --git a/flang/include/flang/Evaluate/traverse.h b/flang/include/flang/Evaluate/traverse.h index 48aafa8..d63c16f 100644 --- a/flang/include/flang/Evaluate/traverse.h +++ b/flang/include/flang/Evaluate/traverse.h @@ -146,7 +146,7 @@ public: return Combine(x.base(), x.subscript()); } Result operator()(const CoarrayRef &x) const { - return Combine(x.base(), x.cosubscript(), x.stat(), x.team()); + return Combine(x.base(), x.cosubscript(), x.notify(), x.stat(), x.team()); } Result operator()(const DataRef &x) const { return visitor_(x.u); } Result operator()(const Substring &x) const { diff --git a/flang/include/flang/Evaluate/variable.h b/flang/include/flang/Evaluate/variable.h index 5c14421..4f64ede 100644 --- a/flang/include/flang/Evaluate/variable.h +++ b/flang/include/flang/Evaluate/variable.h @@ -260,6 +260,9 @@ public: // it's TEAM=. std::optional<Expr<SomeType>> team() const; CoarrayRef &set_team(Expr<SomeType> &&); + // When notify() is Expr<Some>, it's NOTIFY=. + std::optional<Expr<SomeType>> notify() const; + CoarrayRef &set_notify(Expr<SomeType> &&); int Rank() const; int Corank() const { return 0; } @@ -272,6 +275,7 @@ public: private: common::CopyableIndirection<DataRef> base_; std::vector<Expr<SubscriptInteger>> cosubscript_; + std::optional<common::CopyableIndirection<Expr<SomeType>>> notify_; std::optional<common::CopyableIndirection<Expr<SomeInteger>>> stat_; std::optional<common::CopyableIndirection<Expr<SomeType>>> team_; }; diff --git a/flang/include/flang/Frontend/CodeGenOptions.def b/flang/include/flang/Frontend/CodeGenOptions.def index dc3da7b..d5415fa 100644 --- a/flang/include/flang/Frontend/CodeGenOptions.def +++ b/flang/include/flang/Frontend/CodeGenOptions.def @@ -54,7 +54,7 @@ CODEGENOPT(Underscoring, 1, 1) ENUM_CODEGENOPT(RelocationModel, llvm::Reloc::Model, 3, llvm::Reloc::PIC_) ///< Name of the relocation model to use. ENUM_CODEGENOPT(DebugInfo, llvm::codegenoptions::DebugInfoKind, 4, llvm::codegenoptions::NoDebugInfo) ///< Level of debug info to generate ENUM_CODEGENOPT(VecLib, llvm::driver::VectorLibrary, 4, llvm::driver::VectorLibrary::NoLibrary) ///< Vector functions library to use -ENUM_CODEGENOPT(FramePointer, llvm::FramePointerKind, 2, llvm::FramePointerKind::None) ///< Enable the usage of frame pointers +ENUM_CODEGENOPT(FramePointer, llvm::FramePointerKind, 3, llvm::FramePointerKind::None) ///< Enable the usage of frame pointers ENUM_CODEGENOPT(ComplexRange, ComplexRangeKind, 3, ComplexRangeKind::CX_Full) ///< Method for calculating complex number division ENUM_CODEGENOPT(DoConcurrentMapping, DoConcurrentMappingKind, 2, DoConcurrentMappingKind::DCMK_None) ///< Map `do concurrent` to OpenMP diff --git a/flang/include/flang/Lower/AbstractConverter.h b/flang/include/flang/Lower/AbstractConverter.h index f8322a5..f93f7ad 100644 --- a/flang/include/flang/Lower/AbstractConverter.h +++ b/flang/include/flang/Lower/AbstractConverter.h @@ -271,6 +271,12 @@ public: virtual bool isRegisteredDummySymbol(Fortran::semantics::SymbolRef symRef) const = 0; + /// Get the source-level argument position (1-based) for a dummy symbol. + /// Returns 0 if the symbol is not a registered dummy or position is unknown. + /// Can only be used reliably during the instantiation of variables. + virtual unsigned + getDummyArgPosition(const Fortran::semantics::Symbol &sym) const = 0; + /// Returns the FunctionLikeUnit being lowered, if any. virtual const Fortran::lower::pft::FunctionLikeUnit * getCurrentFunctionUnit() const = 0; @@ -351,6 +357,11 @@ public: virtual Fortran::lower::StatementContext &getFctCtx() = 0; + /// Generate STAT and ERRMSG from a list of StatOrErrmsg + virtual std::pair<mlir::Value, mlir::Value> + genStatAndErrmsg(mlir::Location loc, + const std::list<Fortran::parser::StatOrErrmsg> &) = 0; + AbstractConverter(const Fortran::lower::LoweringOptions &loweringOptions) : loweringOptions(loweringOptions) {} virtual ~AbstractConverter() = default; diff --git a/flang/include/flang/Lower/CUDA.h b/flang/include/flang/Lower/CUDA.h index ef7cdc42..704b035 100644 --- a/flang/include/flang/Lower/CUDA.h +++ b/flang/include/flang/Lower/CUDA.h @@ -66,6 +66,9 @@ translateSymbolCUFDataAttribute(mlir::MLIRContext *mlirContext, /// there is a conversion. Return null otherwise. hlfir::ElementalOp isTransferWithConversion(mlir::Value rhs); +/// Check if the value is an allocatable with double descriptor. +bool hasDoubleDescriptor(mlir::Value); + } // end namespace Fortran::lower #endif // FORTRAN_LOWER_CUDA_H diff --git a/flang/include/flang/Lower/DirectivesCommon.h b/flang/include/flang/Lower/DirectivesCommon.h index 2d69067..b564ee1 100644 --- a/flang/include/flang/Lower/DirectivesCommon.h +++ b/flang/include/flang/Lower/DirectivesCommon.h @@ -512,11 +512,19 @@ fir::factory::AddrAndBoundsInfo gatherDataOperandAddrAndBounds( } bool dataExvIsAssumedSize = Fortran::semantics::IsAssumedSizeArray(symRef->get().GetUltimate()); - if (genDefaultBounds && - mlir::isa<fir::SequenceType>(fir::unwrapRefType(info.addr.getType()))) + if (genDefaultBounds && mlir::isa<fir::SequenceType>( + fir::unwrapRefType(info.addr.getType()))) { bounds = fir::factory::genBaseBoundsOps<BoundsOp, BoundsType>( builder, operandLocation, dataExv, dataExvIsAssumedSize, strideIncludeLowerExtent); + } + if (genDefaultBounds && fir::characterWithDynamicLen( + fir::unwrapRefType(info.addr.getType())) || + mlir::isa<fir::BoxCharType>( + fir::unwrapRefType(info.addr.getType()))) { + bounds = {fir::factory::genBoundsOpFromBoxChar<BoundsOp, BoundsType>( + builder, operandLocation, dataExv, info)}; + } asFortran << symRef->get().name().ToString(); } else { // Unsupported llvm::report_fatal_error("Unsupported type of OpenACC operand"); diff --git a/flang/include/flang/Lower/Coarray.h b/flang/include/flang/Lower/MultiImageFortran.h index 76d6a37..d9dc9cf 100644 --- a/flang/include/flang/Lower/Coarray.h +++ b/flang/include/flang/Lower/MultiImageFortran.h @@ -1,4 +1,4 @@ -//===-- Lower/Coarray.h -- image related lowering ---------------*- C++ -*-===// +//===-- Lower/MultiImageFortran.h -- image related lowering -----*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef FORTRAN_LOWER_COARRAY_H -#define FORTRAN_LOWER_COARRAY_H +#ifndef FORTRAN_LOWER_MULTIIMAGEFORTRAN_H +#define FORTRAN_LOWER_MULTIIMAGEFORTRAN_H #include "flang/Lower/AbstractConverter.h" #include "flang/Optimizer/Builder/BoxValue.h" @@ -34,6 +34,18 @@ struct Evaluation; } // namespace pft //===----------------------------------------------------------------------===// +// Synchronization statements +//===----------------------------------------------------------------------===// + +void genSyncAllStatement(AbstractConverter &, const parser::SyncAllStmt &); + +void genSyncImagesStatement(AbstractConverter &, + const parser::SyncImagesStmt &); +void genSyncMemoryStatement(AbstractConverter &, + const parser::SyncMemoryStmt &); +void genSyncTeamStatement(AbstractConverter &, const parser::SyncTeamStmt &); + +//===----------------------------------------------------------------------===// // TEAM constructs //===----------------------------------------------------------------------===// @@ -75,4 +87,4 @@ private: } // namespace lower } // namespace Fortran -#endif // FORTRAN_LOWER_COARRAY_H +#endif // FORTRAN_LOWER_MULTIIMAGEFORTRAN_H diff --git a/flang/include/flang/Lower/OpenMP.h b/flang/include/flang/Lower/OpenMP.h index df01a7b..0080b30 100644 --- a/flang/include/flang/Lower/OpenMP.h +++ b/flang/include/flang/Lower/OpenMP.h @@ -41,6 +41,7 @@ struct OmpClauseList; namespace semantics { class Symbol; +class Scope; class SemanticsContext; } // namespace semantics @@ -97,6 +98,13 @@ bool markOpenMPDeferredDeclareTargetFunctions( AbstractConverter &); void genOpenMPRequires(mlir::Operation *, const Fortran::semantics::Symbol *); +// Materialize omp.declare_mapper ops for mapper declarations found in +// imported modules. If \p scope is null, materialize for the whole +// semantics global scope; otherwise, operate recursively starting at \p scope. +void materializeOpenMPDeclareMappers( + Fortran::lower::AbstractConverter &, Fortran::semantics::SemanticsContext &, + const Fortran::semantics::Scope *scope = nullptr); + } // namespace lower } // namespace Fortran diff --git a/flang/include/flang/Lower/OpenMP/Clauses.h b/flang/include/flang/Lower/OpenMP/Clauses.h index 688d017..737b535 100644 --- a/flang/include/flang/Lower/OpenMP/Clauses.h +++ b/flang/include/flang/Lower/OpenMP/Clauses.h @@ -204,6 +204,7 @@ using At = tomp::clause::AtT<TypeTy, IdTy, ExprTy>; using Bind = tomp::clause::BindT<TypeTy, IdTy, ExprTy>; using Capture = tomp::clause::CaptureT<TypeTy, IdTy, ExprTy>; using Collapse = tomp::clause::CollapseT<TypeTy, IdTy, ExprTy>; +using Collector = tomp::clause::CollectorT<TypeTy, IdTy, ExprTy>; using Compare = tomp::clause::CompareT<TypeTy, IdTy, ExprTy>; using Contains = tomp::clause::ContainsT<TypeTy, IdTy, ExprTy>; using Copyin = tomp::clause::CopyinT<TypeTy, IdTy, ExprTy>; @@ -239,12 +240,13 @@ using If = tomp::clause::IfT<TypeTy, IdTy, ExprTy>; using Inbranch = tomp::clause::InbranchT<TypeTy, IdTy, ExprTy>; using Inclusive = tomp::clause::InclusiveT<TypeTy, IdTy, ExprTy>; using Indirect = tomp::clause::IndirectT<TypeTy, IdTy, ExprTy>; +using Inductor = tomp::clause::InductorT<TypeTy, IdTy, ExprTy>; using Init = tomp::clause::InitT<TypeTy, IdTy, ExprTy>; using Initializer = tomp::clause::InitializerT<TypeTy, IdTy, ExprTy>; using InReduction = tomp::clause::InReductionT<TypeTy, IdTy, ExprTy>; using IsDevicePtr = tomp::clause::IsDevicePtrT<TypeTy, IdTy, ExprTy>; using Lastprivate = tomp::clause::LastprivateT<TypeTy, IdTy, ExprTy>; -using LoopRange = tomp::clause::LoopRangeT<TypeTy, IdTy, ExprTy>; +using Looprange = tomp::clause::LooprangeT<TypeTy, IdTy, ExprTy>; using Linear = tomp::clause::LinearT<TypeTy, IdTy, ExprTy>; using Link = tomp::clause::LinkT<TypeTy, IdTy, ExprTy>; using Map = tomp::clause::MapT<TypeTy, IdTy, ExprTy>; diff --git a/flang/include/flang/Lower/Runtime.h b/flang/include/flang/Lower/Runtime.h index f76f398..204093f 100644 --- a/flang/include/flang/Lower/Runtime.h +++ b/flang/include/flang/Lower/Runtime.h @@ -57,12 +57,6 @@ void genEventWaitStatement(AbstractConverter &, const parser::EventWaitStmt &); void genLockStatement(AbstractConverter &, const parser::LockStmt &); void genFailImageStatement(AbstractConverter &); void genStopStatement(AbstractConverter &, const parser::StopStmt &); -void genSyncAllStatement(AbstractConverter &, const parser::SyncAllStmt &); -void genSyncImagesStatement(AbstractConverter &, - const parser::SyncImagesStmt &); -void genSyncMemoryStatement(AbstractConverter &, - const parser::SyncMemoryStmt &); -void genSyncTeamStatement(AbstractConverter &, const parser::SyncTeamStmt &); void genUnlockStatement(AbstractConverter &, const parser::UnlockStmt &); void genPauseStatement(AbstractConverter &, const parser::PauseStmt &); diff --git a/flang/include/flang/Lower/Support/ReductionProcessor.h b/flang/include/flang/Lower/Support/ReductionProcessor.h index 66f26b3..bd04473 100644 --- a/flang/include/flang/Lower/Support/ReductionProcessor.h +++ b/flang/include/flang/Lower/Support/ReductionProcessor.h @@ -40,6 +40,13 @@ namespace omp { class ReductionProcessor { public: + using GenInitValueCBTy = + std::function<mlir::Value(fir::FirOpBuilder &builder, mlir::Location loc, + mlir::Type type, mlir::Value ompOrig)>; + using GenCombinerCBTy = std::function<void( + fir::FirOpBuilder &builder, mlir::Location loc, mlir::Type type, + mlir::Value op1, mlir::Value op2, bool isByRef)>; + // TODO: Move this enumeration to the OpenMP dialect enum ReductionIdentifier { ID, @@ -58,6 +65,9 @@ public: IEOR }; + static bool doReductionByRef(mlir::Type reductionType); + static bool doReductionByRef(mlir::Value reductionVar); + static ReductionIdentifier getReductionType(const omp::clause::ProcedureDesignator &pd); @@ -109,6 +119,14 @@ public: ReductionIdentifier redId, mlir::Type type, mlir::Value op1, mlir::Value op2); + /// Creates an OpenMP reduction declaration and inserts it into the provided + /// symbol table. The init and combiner regions are generated by the callback + /// functions genCombinerCB and genInitValueCB. + template <typename DeclareRedType> + static DeclareRedType createDeclareReductionHelper( + AbstractConverter &converter, llvm::StringRef reductionOpName, + mlir::Type type, mlir::Location loc, bool isByRef, + GenCombinerCBTy genCombinerCB, GenInitValueCBTy genInitValueCB); /// Creates an OpenMP reduction declaration and inserts it into the provided /// symbol table. The declaration has a constant initializer with the neutral diff --git a/flang/include/flang/Optimizer/Builder/CUDAIntrinsicCall.h b/flang/include/flang/Optimizer/Builder/CUDAIntrinsicCall.h new file mode 100644 index 0000000..e9b6e5c --- /dev/null +++ b/flang/include/flang/Optimizer/Builder/CUDAIntrinsicCall.h @@ -0,0 +1,99 @@ +//==-- Builder/CUDAIntrinsicCall.h - lowering of CUDA intrinsics ---*-C++-*-==// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef FORTRAN_LOWER_CUDAINTRINSICCALL_H +#define FORTRAN_LOWER_CUDAINTRINSICCALL_H + +#include "flang/Optimizer/Builder/IntrinsicCall.h" +#include "mlir/Dialect/LLVMIR/NVVMDialect.h" + +namespace fir { + +struct CUDAIntrinsicLibrary : IntrinsicLibrary { + + // Constructors. + explicit CUDAIntrinsicLibrary(fir::FirOpBuilder &builder, mlir::Location loc) + : IntrinsicLibrary(builder, loc) {} + CUDAIntrinsicLibrary() = delete; + CUDAIntrinsicLibrary(const CUDAIntrinsicLibrary &) = delete; + + // CUDA intrinsic handlers. + mlir::Value genAtomicAdd(mlir::Type, llvm::ArrayRef<mlir::Value>); + fir::ExtendedValue genAtomicAddR2(mlir::Type, + llvm::ArrayRef<fir::ExtendedValue>); + template <int extent> + fir::ExtendedValue genAtomicAddVector(mlir::Type, + llvm::ArrayRef<fir::ExtendedValue>); + fir::ExtendedValue genAtomicAddVector4x4(mlir::Type, + llvm::ArrayRef<fir::ExtendedValue>); + mlir::Value genAtomicAnd(mlir::Type, llvm::ArrayRef<mlir::Value>); + fir::ExtendedValue genAtomicCas(mlir::Type, + llvm::ArrayRef<fir::ExtendedValue>); + mlir::Value genAtomicDec(mlir::Type, llvm::ArrayRef<mlir::Value>); + fir::ExtendedValue genAtomicExch(mlir::Type, + llvm::ArrayRef<fir::ExtendedValue>); + mlir::Value genAtomicInc(mlir::Type, llvm::ArrayRef<mlir::Value>); + mlir::Value genAtomicMax(mlir::Type, llvm::ArrayRef<mlir::Value>); + mlir::Value genAtomicMin(mlir::Type, llvm::ArrayRef<mlir::Value>); + mlir::Value genAtomicOr(mlir::Type, llvm::ArrayRef<mlir::Value>); + mlir::Value genAtomicSub(mlir::Type, llvm::ArrayRef<mlir::Value>); + fir::ExtendedValue genAtomicXor(mlir::Type, + llvm::ArrayRef<fir::ExtendedValue>); + mlir::Value genBarrierArrive(mlir::Type, llvm::ArrayRef<mlir::Value>); + mlir::Value genBarrierArriveCnt(mlir::Type, llvm::ArrayRef<mlir::Value>); + void genBarrierInit(llvm::ArrayRef<fir::ExtendedValue>); + mlir::Value genBarrierTryWait(mlir::Type, llvm::ArrayRef<mlir::Value>); + mlir::Value genBarrierTryWaitSleep(mlir::Type, llvm::ArrayRef<mlir::Value>); + mlir::Value genClusterBlockIndex(mlir::Type, llvm::ArrayRef<mlir::Value>); + mlir::Value genClusterDimBlocks(mlir::Type, llvm::ArrayRef<mlir::Value>); + void genFenceProxyAsync(llvm::ArrayRef<fir::ExtendedValue>); + template <const char *fctName, int extent> + fir::ExtendedValue genLDXXFunc(mlir::Type, + llvm::ArrayRef<fir::ExtendedValue>); + mlir::Value genMatchAllSync(mlir::Type, llvm::ArrayRef<mlir::Value>); + mlir::Value genMatchAnySync(mlir::Type, llvm::ArrayRef<mlir::Value>); + template <typename OpTy> + mlir::Value genNVVMTime(mlir::Type, llvm::ArrayRef<mlir::Value>); + void genSyncThreads(llvm::ArrayRef<fir::ExtendedValue>); + mlir::Value genSyncThreadsAnd(mlir::Type, llvm::ArrayRef<mlir::Value>); + mlir::Value genSyncThreadsCount(mlir::Type, llvm::ArrayRef<mlir::Value>); + mlir::Value genSyncThreadsOr(mlir::Type, llvm::ArrayRef<mlir::Value>); + void genSyncWarp(llvm::ArrayRef<fir::ExtendedValue>); + mlir::Value genThisCluster(mlir::Type, llvm::ArrayRef<mlir::Value>); + mlir::Value genThisGrid(mlir::Type, llvm::ArrayRef<mlir::Value>); + mlir::Value genThisThreadBlock(mlir::Type, llvm::ArrayRef<mlir::Value>); + mlir::Value genThisWarp(mlir::Type, llvm::ArrayRef<mlir::Value>); + template <mlir::NVVM::MemScopeKind scope> + void genThreadFence(llvm::ArrayRef<fir::ExtendedValue>); + void genTMABulkCommitGroup(llvm::ArrayRef<fir::ExtendedValue>); + void genTMABulkG2S(llvm::ArrayRef<fir::ExtendedValue>); + void genTMABulkLoadC4(llvm::ArrayRef<fir::ExtendedValue>); + void genTMABulkLoadC8(llvm::ArrayRef<fir::ExtendedValue>); + void genTMABulkLoadI4(llvm::ArrayRef<fir::ExtendedValue>); + void genTMABulkLoadI8(llvm::ArrayRef<fir::ExtendedValue>); + void genTMABulkLoadR2(llvm::ArrayRef<fir::ExtendedValue>); + void genTMABulkLoadR4(llvm::ArrayRef<fir::ExtendedValue>); + void genTMABulkLoadR8(llvm::ArrayRef<fir::ExtendedValue>); + void genTMABulkS2G(llvm::ArrayRef<fir::ExtendedValue>); + void genTMABulkStoreC4(llvm::ArrayRef<fir::ExtendedValue>); + void genTMABulkStoreC8(llvm::ArrayRef<fir::ExtendedValue>); + void genTMABulkStoreI4(llvm::ArrayRef<fir::ExtendedValue>); + void genTMABulkStoreI8(llvm::ArrayRef<fir::ExtendedValue>); + void genTMABulkStoreR2(llvm::ArrayRef<fir::ExtendedValue>); + void genTMABulkStoreR4(llvm::ArrayRef<fir::ExtendedValue>); + void genTMABulkStoreR8(llvm::ArrayRef<fir::ExtendedValue>); + void genTMABulkWaitGroup(llvm::ArrayRef<fir::ExtendedValue>); + template <mlir::NVVM::VoteSyncKind kind> + mlir::Value genVoteSync(mlir::Type, llvm::ArrayRef<mlir::Value>); +}; + +const IntrinsicHandler *findCUDAIntrinsicHandler(llvm::StringRef name); + +} // namespace fir + +#endif // FORTRAN_LOWER_CUDAINTRINSICCALL_H diff --git a/flang/include/flang/Optimizer/Builder/CUFCommon.h b/flang/include/flang/Optimizer/Builder/CUFCommon.h index 5c56dd6b..736f901 100644 --- a/flang/include/flang/Optimizer/Builder/CUFCommon.h +++ b/flang/include/flang/Optimizer/Builder/CUFCommon.h @@ -14,10 +14,11 @@ #include "mlir/IR/BuiltinOps.h" static constexpr llvm::StringRef cudaDeviceModuleName = "cuda_device_mod"; -static constexpr llvm::StringRef cudaSharedMemSuffix = "__shared_mem"; +static constexpr llvm::StringRef cudaSharedMemSuffix = "__shared_mem__"; namespace fir { class FirOpBuilder; +class KindMapping; } // namespace fir namespace cuf { @@ -34,6 +35,14 @@ bool isRegisteredDeviceAttr(std::optional<cuf::DataAttribute> attr); void genPointerSync(const mlir::Value box, fir::FirOpBuilder &builder); +int computeElementByteSize(mlir::Location loc, mlir::Type type, + fir::KindMapping &kindMap, + bool emitErrorOnFailure = true); + +mlir::Value computeElementCount(mlir::PatternRewriter &rewriter, + mlir::Location loc, mlir::Value shapeOperand, + mlir::Type seqType, mlir::Type targetType); + } // namespace cuf #endif // FORTRAN_OPTIMIZER_TRANSFORMS_CUFCOMMON_H_ diff --git a/flang/include/flang/Optimizer/Builder/FIRBuilder.h b/flang/include/flang/Optimizer/Builder/FIRBuilder.h index 2ce0d86..48a72d7 100644 --- a/flang/include/flang/Optimizer/Builder/FIRBuilder.h +++ b/flang/include/flang/Optimizer/Builder/FIRBuilder.h @@ -208,6 +208,11 @@ public: return createRealConstant(loc, realType, 0u); } + /// Create a real constant of type \p realType with value one. + mlir::Value createRealOneConstant(mlir::Location loc, mlir::Type realType) { + return createRealConstant(loc, realType, 1u); + } + /// Create a slot for a local on the stack. Besides the variable's type and /// shape, it may be given name, pinned, or target attributes. mlir::Value allocateLocal(mlir::Location loc, mlir::Type ty, @@ -820,7 +825,8 @@ void genScalarAssignment(fir::FirOpBuilder &builder, mlir::Location loc, const fir::ExtendedValue &lhs, const fir::ExtendedValue &rhs, bool needFinalization = false, - bool isTemporaryLHS = false); + bool isTemporaryLHS = false, + mlir::ArrayAttr accessGroups = {}); /// Assign \p rhs to \p lhs. Both \p rhs and \p lhs must be scalar derived /// types. The assignment follows Fortran intrinsic assignment semantic for @@ -855,6 +861,11 @@ mlir::Value genLenOfCharacter(fir::FirOpBuilder &builder, mlir::Location loc, mlir::Value createZeroValue(fir::FirOpBuilder &builder, mlir::Location loc, mlir::Type type); +/// Create a one value of a given numerical or logical \p type (`true` +/// for logical types). +mlir::Value createOneValue(fir::FirOpBuilder &builder, mlir::Location loc, + mlir::Type type); + /// Get the integer constants of triplet and compute the extent. std::optional<std::int64_t> getExtentFromTriplet(mlir::Value lb, mlir::Value ub, mlir::Value stride); diff --git a/flang/include/flang/Optimizer/Builder/HLFIRTools.h b/flang/include/flang/Optimizer/Builder/HLFIRTools.h index 9f7c10c..9933e3e 100644 --- a/flang/include/flang/Optimizer/Builder/HLFIRTools.h +++ b/flang/include/flang/Optimizer/Builder/HLFIRTools.h @@ -233,7 +233,7 @@ genDeclare(mlir::Location loc, fir::FirOpBuilder &builder, fir::FortranVariableFlagsAttr flags, mlir::Value dummyScope = nullptr, mlir::Value storage = nullptr, std::uint64_t storageOffset = 0, - cuf::DataAttributeAttr dataAttr = {}); + cuf::DataAttributeAttr dataAttr = {}, unsigned dummyArgNo = 0); /// Generate an hlfir.associate to build a variable from an expression value. /// The type of the variable must be provided so that scalar logicals are @@ -450,6 +450,41 @@ mlir::Value inlineElementalOp( mlir::IRMapping &mapper, const std::function<bool(hlfir::ElementalOp)> &mustRecursivelyInline); +/// Generate an element-by-element assignment from \p rhs to \p lhs for arrays +/// that are known not to alias. The assignment is performed using a loop nest +/// over the optimal extents deduced from both shapes. If \p emitWorkshareLoop +/// is true, a workshare loop construct may be emitted when available. +/// Allocatable LHS must be allocated with the right shape and parameters. +void genNoAliasArrayAssignment( + mlir::Location loc, fir::FirOpBuilder &builder, hlfir::Entity rhs, + hlfir::Entity lhs, bool emitWorkshareLoop = false, + bool temporaryLHS = false, + std::function<hlfir::Entity(mlir::Location, fir::FirOpBuilder &, + hlfir::Entity, hlfir::Entity)> *combiner = + nullptr); + +/// Generate an assignment from \p rhs to \p lhs when they are known not to +/// alias. Handles both arrays and scalars: for arrays, delegates to +/// genNoAliasArrayAssignment; for scalars, performs load/store for trivial +/// scalar types and falls back to hlfir.assign otherwise. +/// Allocatable LHS must be allocated with the right shape and parameters. +void genNoAliasAssignment( + mlir::Location loc, fir::FirOpBuilder &builder, hlfir::Entity rhs, + hlfir::Entity lhs, bool emitWorkshareLoop = false, + bool temporaryLHS = false, + std::function<hlfir::Entity(mlir::Location, fir::FirOpBuilder &, + hlfir::Entity, hlfir::Entity)> *combiner = + nullptr); +inline void genNoAliasAssignment( + mlir::Location loc, fir::FirOpBuilder &builder, hlfir::Entity rhs, + hlfir::Entity lhs, bool emitWorkshareLoop, bool temporaryLHS, + std::function<hlfir::Entity(mlir::Location, fir::FirOpBuilder &, + hlfir::Entity, hlfir::Entity)> + combiner) { + genNoAliasAssignment(loc, builder, rhs, lhs, emitWorkshareLoop, temporaryLHS, + &combiner); +} + /// Create a new temporary with the shape and parameters of the provided /// hlfir.eval_in_mem operation and clone the body of the hlfir.eval_in_mem /// operating on this new temporary. returns the temporary and whether the diff --git a/flang/include/flang/Optimizer/Builder/IntrinsicCall.h b/flang/include/flang/Optimizer/Builder/IntrinsicCall.h index 3407dd0..b248106 100644 --- a/flang/include/flang/Optimizer/Builder/IntrinsicCall.h +++ b/flang/include/flang/Optimizer/Builder/IntrinsicCall.h @@ -19,7 +19,6 @@ #include "flang/Runtime/iostat-consts.h" #include "mlir/Dialect/Complex/IR/Complex.h" #include "mlir/Dialect/LLVMIR/LLVMDialect.h" -#include "mlir/Dialect/LLVMIR/NVVMDialect.h" #include "mlir/Dialect/Math/IR/Math.h" #include <optional> @@ -187,20 +186,6 @@ struct IntrinsicLibrary { mlir::Value genAnint(mlir::Type, llvm::ArrayRef<mlir::Value>); fir::ExtendedValue genAny(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>); mlir::Value genAtanpi(mlir::Type, llvm::ArrayRef<mlir::Value>); - mlir::Value genAtomicAdd(mlir::Type, llvm::ArrayRef<mlir::Value>); - mlir::Value genAtomicAnd(mlir::Type, llvm::ArrayRef<mlir::Value>); - fir::ExtendedValue genAtomicCas(mlir::Type, - llvm::ArrayRef<fir::ExtendedValue>); - mlir::Value genAtomicDec(mlir::Type, llvm::ArrayRef<mlir::Value>); - fir::ExtendedValue genAtomicExch(mlir::Type, - llvm::ArrayRef<fir::ExtendedValue>); - mlir::Value genAtomicInc(mlir::Type, llvm::ArrayRef<mlir::Value>); - mlir::Value genAtomicMax(mlir::Type, llvm::ArrayRef<mlir::Value>); - mlir::Value genAtomicMin(mlir::Type, llvm::ArrayRef<mlir::Value>); - mlir::Value genAtomicOr(mlir::Type, llvm::ArrayRef<mlir::Value>); - mlir::Value genAtomicSub(mlir::Type, llvm::ArrayRef<mlir::Value>); - fir::ExtendedValue genAtomicXor(mlir::Type, - llvm::ArrayRef<fir::ExtendedValue>); fir::ExtendedValue genCommandArgumentCount(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>); mlir::Value genAsind(mlir::Type, llvm::ArrayRef<mlir::Value>); @@ -208,11 +193,6 @@ struct IntrinsicLibrary { fir::ExtendedValue genAssociated(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>); mlir::Value genAtand(mlir::Type, llvm::ArrayRef<mlir::Value>); - mlir::Value genBarrierArrive(mlir::Type, llvm::ArrayRef<mlir::Value>); - mlir::Value genBarrierArriveCnt(mlir::Type, llvm::ArrayRef<mlir::Value>); - void genBarrierInit(llvm::ArrayRef<fir::ExtendedValue>); - mlir::Value genBarrierTryWait(mlir::Type, llvm::ArrayRef<mlir::Value>); - mlir::Value genBarrierTryWaitSleep(mlir::Type, llvm::ArrayRef<mlir::Value>); fir::ExtendedValue genBesselJn(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>); fir::ExtendedValue genBesselYn(mlir::Type, @@ -234,9 +214,6 @@ struct IntrinsicLibrary { fir::ExtendedValue genCount(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>); void genCpuTime(llvm::ArrayRef<fir::ExtendedValue>); fir::ExtendedValue genCshift(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>); - template <const char *fctName, int extent> - fir::ExtendedValue genCUDALDXXFunc(mlir::Type, - llvm::ArrayRef<fir::ExtendedValue>); fir::ExtendedValue genCAssociatedCFunPtr(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>); fir::ExtendedValue genCAssociatedCPtr(mlir::Type, @@ -276,8 +253,8 @@ struct IntrinsicLibrary { llvm::ArrayRef<fir::ExtendedValue>); template <Extremum, ExtremumBehavior> mlir::Value genExtremum(mlir::Type, llvm::ArrayRef<mlir::Value>); - void genFenceProxyAsync(llvm::ArrayRef<fir::ExtendedValue>); mlir::Value genFloor(mlir::Type, llvm::ArrayRef<mlir::Value>); + void genFlush(llvm::ArrayRef<fir::ExtendedValue>); mlir::Value genFraction(mlir::Type resultType, mlir::ArrayRef<mlir::Value> args); void genFree(mlir::ArrayRef<fir::ExtendedValue> args); @@ -294,6 +271,7 @@ struct IntrinsicLibrary { void genGetEnvironmentVariable(llvm::ArrayRef<fir::ExtendedValue>); mlir::Value genGetGID(mlir::Type resultType, llvm::ArrayRef<mlir::Value> args); + mlir::Value genGetTeam(mlir::Type, llvm::ArrayRef<mlir::Value>); mlir::Value genGetUID(mlir::Type resultType, llvm::ArrayRef<mlir::Value> args); fir::ExtendedValue genHostnm(std::optional<mlir::Type> resultType, @@ -352,6 +330,8 @@ struct IntrinsicLibrary { fir::ExtendedValue genIndex(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>); mlir::Value genIor(mlir::Type, llvm::ArrayRef<mlir::Value>); fir::ExtendedValue genIparity(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>); + fir::ExtendedValue genIrand(mlir::Type resultType, + llvm::ArrayRef<fir::ExtendedValue>); fir::ExtendedValue genIsContiguous(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>); template <Fortran::runtime::io::Iostat value> @@ -368,8 +348,6 @@ struct IntrinsicLibrary { mlir::Value genMalloc(mlir::Type, llvm::ArrayRef<mlir::Value>); template <typename Shift> mlir::Value genMask(mlir::Type, llvm::ArrayRef<mlir::Value>); - mlir::Value genMatchAllSync(mlir::Type, llvm::ArrayRef<mlir::Value>); - mlir::Value genMatchAnySync(mlir::Type, llvm::ArrayRef<mlir::Value>); fir::ExtendedValue genMatmul(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>); fir::ExtendedValue genMatmulTranspose(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>); @@ -392,8 +370,6 @@ struct IntrinsicLibrary { fir::ExtendedValue genNull(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>); fir::ExtendedValue genNumImages(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>); - template <typename OpTy> - mlir::Value genNVVMTime(mlir::Type, llvm::ArrayRef<mlir::Value>); fir::ExtendedValue genPack(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>); fir::ExtendedValue genParity(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>); void genPerror(llvm::ArrayRef<fir::ExtendedValue>); @@ -403,6 +379,8 @@ struct IntrinsicLibrary { fir::ExtendedValue genProduct(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>); fir::ExtendedValue genPutenv(std::optional<mlir::Type>, llvm::ArrayRef<fir::ExtendedValue>); + fir::ExtendedValue genRand(mlir::Type resultType, + llvm::ArrayRef<fir::ExtendedValue>); void genRandomInit(llvm::ArrayRef<fir::ExtendedValue>); void genRandomNumber(llvm::ArrayRef<fir::ExtendedValue>); void genRandomSeed(llvm::ArrayRef<fir::ExtendedValue>); @@ -435,6 +413,7 @@ struct IntrinsicLibrary { template <typename Shift> mlir::Value genShift(mlir::Type resultType, llvm::ArrayRef<mlir::Value>); mlir::Value genShiftA(mlir::Type resultType, llvm::ArrayRef<mlir::Value>); + void genShowDescriptor(llvm::ArrayRef<fir::ExtendedValue>); mlir::Value genSign(mlir::Type, llvm::ArrayRef<mlir::Value>); mlir::Value genSind(mlir::Type, llvm::ArrayRef<mlir::Value>); mlir::Value genSinpi(mlir::Type, llvm::ArrayRef<mlir::Value>); @@ -448,56 +427,27 @@ struct IntrinsicLibrary { fir::ExtendedValue genSum(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>); void genSignalSubroutine(llvm::ArrayRef<fir::ExtendedValue>); void genSleep(llvm::ArrayRef<fir::ExtendedValue>); - void genSyncThreads(llvm::ArrayRef<fir::ExtendedValue>); - mlir::Value genSyncThreadsAnd(mlir::Type, llvm::ArrayRef<mlir::Value>); - mlir::Value genSyncThreadsCount(mlir::Type, llvm::ArrayRef<mlir::Value>); - mlir::Value genSyncThreadsOr(mlir::Type, llvm::ArrayRef<mlir::Value>); - void genSyncWarp(llvm::ArrayRef<fir::ExtendedValue>); fir::ExtendedValue genSystem(std::optional<mlir::Type>, mlir::ArrayRef<fir::ExtendedValue> args); void genSystemClock(llvm::ArrayRef<fir::ExtendedValue>); mlir::Value genTand(mlir::Type, llvm::ArrayRef<mlir::Value>); mlir::Value genTanpi(mlir::Type, llvm::ArrayRef<mlir::Value>); + fir::ExtendedValue genTeamNumber(mlir::Type, + llvm::ArrayRef<fir::ExtendedValue>); mlir::Value genTime(mlir::Type, llvm::ArrayRef<mlir::Value>); - void genTMABulkCommitGroup(llvm::ArrayRef<fir::ExtendedValue>); - void genTMABulkG2S(llvm::ArrayRef<fir::ExtendedValue>); - void genTMABulkLoadC4(llvm::ArrayRef<fir::ExtendedValue>); - void genTMABulkLoadC8(llvm::ArrayRef<fir::ExtendedValue>); - void genTMABulkLoadI4(llvm::ArrayRef<fir::ExtendedValue>); - void genTMABulkLoadI8(llvm::ArrayRef<fir::ExtendedValue>); - void genTMABulkLoadR2(llvm::ArrayRef<fir::ExtendedValue>); - void genTMABulkLoadR4(llvm::ArrayRef<fir::ExtendedValue>); - void genTMABulkLoadR8(llvm::ArrayRef<fir::ExtendedValue>); - void genTMABulkS2G(llvm::ArrayRef<fir::ExtendedValue>); - void genTMABulkStoreI4(llvm::ArrayRef<fir::ExtendedValue>); - void genTMABulkStoreI8(llvm::ArrayRef<fir::ExtendedValue>); - void genTMABulkStoreR2(llvm::ArrayRef<fir::ExtendedValue>); - void genTMABulkStoreR4(llvm::ArrayRef<fir::ExtendedValue>); - void genTMABulkStoreR8(llvm::ArrayRef<fir::ExtendedValue>); - void genTMABulkStoreC4(llvm::ArrayRef<fir::ExtendedValue>); - void genTMABulkStoreC8(llvm::ArrayRef<fir::ExtendedValue>); - void genTMABulkWaitGroup(llvm::ArrayRef<fir::ExtendedValue>); mlir::Value genTrailz(mlir::Type, llvm::ArrayRef<mlir::Value>); fir::ExtendedValue genTransfer(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>); fir::ExtendedValue genTranspose(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>); - mlir::Value genThisGrid(mlir::Type, llvm::ArrayRef<mlir::Value>); fir::ExtendedValue genThisImage(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>); - mlir::Value genThisThreadBlock(mlir::Type, llvm::ArrayRef<mlir::Value>); - mlir::Value genThisWarp(mlir::Type, llvm::ArrayRef<mlir::Value>); - void genThreadFence(llvm::ArrayRef<fir::ExtendedValue>); - void genThreadFenceBlock(llvm::ArrayRef<fir::ExtendedValue>); - void genThreadFenceSystem(llvm::ArrayRef<fir::ExtendedValue>); fir::ExtendedValue genTrim(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>); fir::ExtendedValue genUbound(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>); fir::ExtendedValue genUnlink(std::optional<mlir::Type> resultType, llvm::ArrayRef<fir::ExtendedValue> args); fir::ExtendedValue genUnpack(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>); fir::ExtendedValue genVerify(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>); - template <mlir::NVVM::VoteSyncKind kind> - mlir::Value genVoteSync(mlir::Type, llvm::ArrayRef<mlir::Value>); /// Implement all conversion functions like DBLE, the first argument is /// the value to convert. There may be an additional KIND arguments that diff --git a/flang/include/flang/Optimizer/Builder/Runtime/Intrinsics.h b/flang/include/flang/Optimizer/Builder/Runtime/Intrinsics.h index 7a97172..1f75182 100644 --- a/flang/include/flang/Optimizer/Builder/Runtime/Intrinsics.h +++ b/flang/include/flang/Optimizer/Builder/Runtime/Intrinsics.h @@ -51,6 +51,8 @@ mlir::Value genDsecnds(fir::FirOpBuilder &builder, mlir::Location loc, void genEtime(fir::FirOpBuilder &builder, mlir::Location loc, mlir::Value values, mlir::Value time); +void genFlush(fir::FirOpBuilder &builder, mlir::Location loc, mlir::Value unit); + void genFree(fir::FirOpBuilder &builder, mlir::Location loc, mlir::Value ptr); mlir::Value genFseek(fir::FirOpBuilder &builder, mlir::Location loc, @@ -109,6 +111,15 @@ void genSleep(fir::FirOpBuilder &builder, mlir::Location loc, mlir::Value genChdir(fir::FirOpBuilder &builder, mlir::Location loc, mlir::Value name); +mlir::Value genIrand(fir::FirOpBuilder &builder, mlir::Location loc, + mlir::Value i); +mlir::Value genRand(fir::FirOpBuilder &builder, mlir::Location loc, + mlir::Value i); + +/// generate dump of a descriptor +void genShowDescriptor(fir::FirOpBuilder &builder, mlir::Location loc, + mlir::Value descriptor); + } // namespace runtime } // namespace fir diff --git a/flang/include/flang/Optimizer/Dialect/CUF/CUFOps.td b/flang/include/flang/Optimizer/Dialect/CUF/CUFOps.td index e3873823..636879f 100644 --- a/flang/include/flang/Optimizer/Dialect/CUF/CUFOps.td +++ b/flang/include/flang/Optimizer/Dialect/CUF/CUFOps.td @@ -26,8 +26,7 @@ include "mlir/IR/BuiltinAttributes.td" class cuf_Op<string mnemonic, list<Trait> traits> : Op<CUFDialect, mnemonic, traits>; -def cuf_AllocOp : cuf_Op<"alloc", [AttrSizedOperandSegments, - MemoryEffects<[MemAlloc]>]> { +def cuf_AllocOp : cuf_Op<"alloc", [AttrSizedOperandSegments]> { let summary = "Allocate an object on device"; let description = [{ @@ -47,7 +46,9 @@ def cuf_AllocOp : cuf_Op<"alloc", [AttrSizedOperandSegments, cuf_DataAttributeAttr:$data_attr ); - let results = (outs fir_ReferenceType:$ptr); + // Value-scoped Allocate on the returned reference + let results = + (outs Res<fir_ReferenceType, "", [MemAlloc<DefaultResource>]>:$ptr); let assemblyFormat = [{ $in_type (`(` $typeparams^ `:` type($typeparams) `)`)? @@ -99,7 +100,8 @@ def cuf_AllocateOp : cuf_Op<"allocate", [AttrSizedOperandSegments, Optional<fir_ReferenceType>:$stream, Arg<Optional<AnyRefOrBoxType>, "", [MemWrite]>:$pinned, Arg<Optional<AnyRefOrBoxType>, "", [MemRead]>:$source, - cuf_DataAttributeAttr:$data_attr, UnitAttr:$hasStat); + cuf_DataAttributeAttr:$data_attr, UnitAttr:$hasStat, + UnitAttr:$hasDoubleDescriptor, UnitAttr:$pointer); let results = (outs AnyIntegerType:$stat); @@ -125,9 +127,9 @@ def cuf_DeallocateOp : cuf_Op<"deallocate", }]; let arguments = (ins Arg<fir_ReferenceType, "", [MemRead, MemWrite]>:$box, - Arg<Optional<AnyRefOrBoxType>, "", [MemWrite]>:$errmsg, - cuf_DataAttributeAttr:$data_attr, - UnitAttr:$hasStat); + Arg<Optional<AnyRefOrBoxType>, "", [MemWrite]>:$errmsg, + cuf_DataAttributeAttr:$data_attr, UnitAttr:$hasStat, + UnitAttr:$hasDoubleDescriptor, UnitAttr:$pointer); let results = (outs AnyIntegerType:$stat); @@ -349,15 +351,15 @@ def cuf_SharedMemoryOp let arguments = (ins TypeAttr:$in_type, OptionalAttr<StrAttr>:$uniq_name, OptionalAttr<StrAttr>:$bindc_name, Variadic<AnyIntegerType>:$typeparams, Variadic<AnyIntegerType>:$shape, - Optional<AnyIntegerType>:$offset // offset in bytes from the shared memory - // base address. - ); + // offset in bytes from the shared memory base address. + Optional<AnyIntegerType>:$offset, OptionalAttr<I64Attr>:$alignment, + UnitAttr:$isStatic); let results = (outs fir_ReferenceType:$ptr); let assemblyFormat = [{ (`[` $offset^ `:` type($offset) `]`)? $in_type (`(` $typeparams^ `:` type($typeparams) `)`)? - (`,` $shape^ `:` type($shape) )? attr-dict `->` qualified(type($ptr)) + (`,` $shape^ `:` type($shape) )? (`align` $alignment^ )? attr-dict `->` qualified(type($ptr)) }]; let builders = [OpBuilder<(ins "mlir::Type":$inType, diff --git a/flang/include/flang/Optimizer/Dialect/FIRCG/CGOps.td b/flang/include/flang/Optimizer/Dialect/FIRCG/CGOps.td index 04f8393..c05b03b 100644 --- a/flang/include/flang/Optimizer/Dialect/FIRCG/CGOps.td +++ b/flang/include/flang/Optimizer/Dialect/FIRCG/CGOps.td @@ -225,16 +225,25 @@ def fircg_XDeclareOp : fircg_Op<"ext_declare", [AttrSizedOperandSegments]> { let description = [{ Prior to lowering to LLVM IR dialect, a DeclareOp will be converted to an extended DeclareOp. + + Most operands are inherited from fir.declare except for the shape and shift + operands, which are "expanded" forms of the corresponding shape/shift + operands of fir.declare. }]; let arguments = (ins AnyRefOrBox:$memref, Variadic<AnyIntegerType>:$shape, Variadic<AnyIntegerType>:$shift, Variadic<AnyIntegerType>:$typeparams, - Optional<fir_DummyScopeType>:$dummy_scope, Builtin_StringAttr:$uniq_name); + Optional<fir_DummyScopeType>:$dummy_scope, + Optional<AnyReferenceLike>:$storage, + DefaultValuedAttr<UI64Attr, "0">:$storage_offset, + Builtin_StringAttr:$uniq_name, + OptionalAttr<UI32Attr>:$dummy_arg_no); let results = (outs AnyRefOrBox); let assemblyFormat = [{ $memref (`(` $shape^ `)`)? (`origin` $shift^)? (`typeparams` $typeparams^)? - (`dummy_scope` $dummy_scope^)? + (`dummy_scope` $dummy_scope^ (`arg` $dummy_arg_no^)?)? + (`storage` `(` $storage^ `[` $storage_offset `]` `)`)? attr-dict `:` functional-type(operands, results) }]; diff --git a/flang/include/flang/Optimizer/Dialect/FIROps.td b/flang/include/flang/Optimizer/Dialect/FIROps.td index bae52d6..cfce9fc 100644 --- a/flang/include/flang/Optimizer/Dialect/FIROps.td +++ b/flang/include/flang/Optimizer/Dialect/FIROps.td @@ -80,8 +80,7 @@ def AnyRefOfConstantSizeAggregateType : TypeConstraint< // Memory SSA operations //===----------------------------------------------------------------------===// -def fir_AllocaOp : fir_Op<"alloca", [AttrSizedOperandSegments, - MemoryEffects<[MemAlloc<AutomaticAllocationScopeResource>]>]> { +def fir_AllocaOp : fir_Op<"alloca", [AttrSizedOperandSegments]> { let summary = "allocate storage for a temporary on the stack given a type"; let description = [{ This primitive operation is used to allocate an object on the stack. A @@ -162,7 +161,9 @@ def fir_AllocaOp : fir_Op<"alloca", [AttrSizedOperandSegments, Variadic<AnyIntegerType>:$shape ); - let results = (outs fir_ReferenceType); + let results = + (outs Res<fir_ReferenceType, + "", [MemAlloc<AutomaticAllocationScopeResource>]>:$res); let hasCustomAssemblyFormat = 1; let hasVerifier = 1; @@ -212,8 +213,7 @@ def fir_AllocaOp : fir_Op<"alloca", [AttrSizedOperandSegments, }]; } -def fir_AllocMemOp : fir_Op<"allocmem", - [MemoryEffects<[MemAlloc<DefaultResource>]>, AttrSizedOperandSegments]> { +def fir_AllocMemOp : fir_Op<"allocmem", [AttrSizedOperandSegments]> { let summary = "allocate storage on the heap for an object of a given type"; let description = [{ @@ -235,7 +235,7 @@ def fir_AllocMemOp : fir_Op<"allocmem", Variadic<AnyIntegerType>:$typeparams, Variadic<AnyIntegerType>:$shape ); - let results = (outs fir_HeapType); + let results = (outs Res<fir_HeapType, "", [MemAlloc<DefaultResource>]>:$res); let hasCustomAssemblyFormat = 1; let hasVerifier = 1; @@ -306,7 +306,8 @@ def fir_LoadOp : fir_OneResultOp<"load", [FirAliasTagOpInterface, }]; let arguments = (ins AnyReferenceLike:$memref, - OptionalAttr<LLVM_TBAATagArrayAttr>:$tbaa, UnitAttr:$nontemporal); + OptionalAttr<LLVM_TBAATagArrayAttr>:$tbaa, UnitAttr:$nontemporal, + OptionalAttr<LLVM_AccessGroupArrayAttr>:$accessGroups); let builders = [OpBuilder<(ins "mlir::Value":$refVal)>, OpBuilder<(ins "mlir::Type":$resTy, "mlir::Value":$refVal)>]; @@ -339,7 +340,8 @@ def fir_StoreOp : fir_Op<"store", [FirAliasTagOpInterface, }]; let arguments = (ins AnyType:$value, AnyReferenceLike:$memref, - OptionalAttr<LLVM_TBAATagArrayAttr>:$tbaa, UnitAttr:$nontemporal); + OptionalAttr<LLVM_TBAATagArrayAttr>:$tbaa, UnitAttr:$nontemporal, + OptionalAttr<LLVM_AccessGroupArrayAttr>:$accessGroups); let builders = [OpBuilder<(ins "mlir::Value":$value, "mlir::Value":$memref)>]; @@ -806,7 +808,8 @@ def fir_HasValueOp : fir_Op<"has_value", [Terminator, HasParent<"GlobalOp">]> { // Operations on !fir.box<T> type objects //===----------------------------------------------------------------------===// -def fir_EmboxOp : fir_Op<"embox", [NoMemoryEffect, AttrSizedOperandSegments]> { +def fir_EmboxOp : fir_Op<"embox", [NoMemoryEffect, AttrSizedOperandSegments, + fir_FortranObjectViewOpInterface]> { let summary = "boxes a given reference and (optional) dimension information"; let description = [{ @@ -870,10 +873,14 @@ def fir_EmboxOp : fir_Op<"embox", [NoMemoryEffect, AttrSizedOperandSegments]> { return 1 + (getShape() ? 1 : 0) + (getSlice() ? 1 : 0) + numLenParams(); } + // FortranObjectViewOpInterface methods: + mlir::Value getViewSource(mlir::OpResult) { return getMemref(); } + std::optional<std::int64_t> getViewOffset(mlir::OpResult); }]; } -def fir_ReboxOp : fir_Op<"rebox", [NoMemoryEffect, AttrSizedOperandSegments]> { +def fir_ReboxOp : fir_Op<"rebox", [NoMemoryEffect, AttrSizedOperandSegments, + fir_FortranObjectViewOpInterface]> { let summary = "create a box given another box and (optional) dimension information"; @@ -923,6 +930,12 @@ def fir_ReboxOp : fir_Op<"rebox", [NoMemoryEffect, AttrSizedOperandSegments]> { }]; let hasVerifier = 1; + + let extraClassDeclaration = [{ + // FortranObjectViewOpInterface methods: + mlir::Value getViewSource(mlir::OpResult) { return getBox(); } + std::optional<std::int64_t> getViewOffset(mlir::OpResult); + }]; } def fir_ReboxAssumedRankOp : fir_Op<"rebox_assumed_rank", @@ -1071,7 +1084,9 @@ def fir_UnboxProcOp : fir_SimpleOp<"unboxproc", [NoMemoryEffect]> { let results = (outs FunctionType, fir_ReferenceType:$refTuple); } -def fir_BoxAddrOp : fir_SimpleOneResultOp<"box_addr", [NoMemoryEffect]> { +def fir_BoxAddrOp + : fir_SimpleOneResultOp<"box_addr", [NoMemoryEffect, + fir_FortranObjectViewOpInterface]> { let summary = "return a memory reference to the boxed value"; let description = [{ @@ -1094,6 +1109,12 @@ def fir_BoxAddrOp : fir_SimpleOneResultOp<"box_addr", [NoMemoryEffect]> { let hasFolder = 1; let builders = [OpBuilder<(ins "mlir::Value":$val)>]; + + let extraClassDeclaration = [{ + // FortranObjectViewOpInterface methods: + mlir::Value getViewSource(mlir::OpResult) { return getVal(); } + std::optional<std::int64_t> getViewOffset(mlir::OpResult); + }]; } def fir_BoxCharLenOp : fir_SimpleOp<"boxchar_len", [NoMemoryEffect]> { @@ -1766,8 +1787,9 @@ def fir_ArrayMergeStoreOp : fir_Op<"array_merge_store", // Record and array type operations //===----------------------------------------------------------------------===// -def fir_ArrayCoorOp : fir_Op<"array_coor", - [NoMemoryEffect, AttrSizedOperandSegments]> { +def fir_ArrayCoorOp + : fir_Op<"array_coor", [NoMemoryEffect, AttrSizedOperandSegments, + fir_FortranObjectViewOpInterface]> { let summary = "Find the coordinate of an element of an array"; @@ -1810,9 +1832,16 @@ def fir_ArrayCoorOp : fir_Op<"array_coor", let hasVerifier = 1; let hasCanonicalizer = 1; + let extraClassDeclaration = [{ + // FortranObjectViewOpInterface methods: + mlir::Value getViewSource(mlir::OpResult) { return getMemref(); } + std::optional<std::int64_t> getViewOffset(mlir::OpResult); + }]; } -def fir_CoordinateOp : fir_Op<"coordinate_of", [NoMemoryEffect]> { +def fir_CoordinateOp + : fir_Op<"coordinate_of", [NoMemoryEffect, + fir_FortranObjectViewOpInterface]> { let summary = "Finds the coordinate (location) of a value in memory"; @@ -1864,6 +1893,10 @@ def fir_CoordinateOp : fir_Op<"coordinate_of", [NoMemoryEffect]> { let extraClassDeclaration = [{ constexpr static int32_t kDynamicIndex = std::numeric_limits<int32_t>::min(); CoordinateIndicesAdaptor getIndices(); + + // FortranObjectViewOpInterface methods: + mlir::Value getViewSource(mlir::OpResult) { return getRef(); } + std::optional<std::int64_t> getViewOffset(mlir::OpResult); }]; } @@ -2544,16 +2577,14 @@ def fir_CallOp : fir_Op<"call", ``` }]; - let arguments = (ins - OptionalAttr<SymbolRefAttr>:$callee, - Variadic<AnyType>:$args, - OptionalAttr<DictArrayAttr>:$arg_attrs, - OptionalAttr<DictArrayAttr>:$res_attrs, - OptionalAttr<fir_FortranProcedureFlagsAttr>:$procedure_attrs, - OptionalAttr<fir_FortranInlineAttr>:$inline_attr, - DefaultValuedAttr<Arith_FastMathAttr, - "::mlir::arith::FastMathFlags::none">:$fastmath - ); + let arguments = (ins OptionalAttr<SymbolRefAttr>:$callee, + Variadic<AnyType>:$args, OptionalAttr<DictArrayAttr>:$arg_attrs, + OptionalAttr<DictArrayAttr>:$res_attrs, + OptionalAttr<fir_FortranProcedureFlagsAttr>:$procedure_attrs, + OptionalAttr<fir_FortranInlineAttr>:$inline_attr, + OptionalAttr<LLVM_AccessGroupArrayAttr>:$accessGroups, + DefaultValuedAttr<Arith_FastMathAttr, + "::mlir::arith::FastMathFlags::none">:$fastmath); let results = (outs Variadic<AnyType>); let hasCustomAssemblyFormat = 1; @@ -2830,7 +2861,8 @@ def fir_VolatileCastOp : fir_SimpleOneResultOp<"volatile_cast", [Pure]> { } def fir_ConvertOp - : fir_SimpleOneResultOp<"convert", [NoMemoryEffect, ViewLikeOpInterface]> { + : fir_SimpleOneResultOp<"convert", [NoMemoryEffect, ViewLikeOpInterface, + fir_FortranObjectViewOpInterface]> { let summary = "encapsulates all Fortran entity type conversions"; let description = [{ @@ -2868,7 +2900,13 @@ def fir_ConvertOp static bool isPointerCompatible(mlir::Type ty); static bool canBeConverted(mlir::Type inType, mlir::Type outType); static bool areVectorsCompatible(mlir::Type inTy, mlir::Type outTy); + + // ViewLikeOpInterface methods: mlir::Value getViewSource() { return getValue(); } + + // FortranObjectViewOpInterface methods: + mlir::Value getViewSource(mlir::OpResult) { return getValue(); } + std::optional<std::int64_t> getViewOffset(mlir::OpResult) { return 0; } }]; let hasCanonicalizer = 1; } @@ -3069,9 +3107,12 @@ def fir_TypeInfoOp : fir_Op<"type_info", between method identifiers and corresponding `FuncOp` symbols. The ordering of associations in the map is determined by the front end. - The "no_init" flag indicates that this type has no components requiring default - initialization (including setting allocatable component to a clean deallocated - state). + The "abstract" flag indicates that this type is an ABSTRACT derived type and + that it cannot be instantiated. + + The "no_init" flag indicates that this type has no components requiring + default initialization (including setting allocatable component to a clean + deallocated state). The "no_destroy" flag indicates that there are no allocatable components that require deallocation. @@ -3080,7 +3121,8 @@ def fir_TypeInfoOp : fir_Op<"type_info", for its parents ,or for components. ``` - fir.type_info @_QMquuzTfoo noinit nofinal : !fir.type<_QMquuzTfoo{i:i32}> dispatch_table { + fir.type_info @_QMquuzTfoo abstract noinit nofinal + : !fir.type<_QMquuzTfoo{i:i32}> dispatch_table { fir.dt_entry method1, @_QFNMquuzTfooPmethod1AfooR fir.dt_entry method2, @_QFNMquuzTfooPmethod2AfooII } @@ -3091,6 +3133,7 @@ def fir_TypeInfoOp : fir_Op<"type_info", SymbolNameAttr:$sym_name, TypeAttr:$type, OptionalAttr<TypeAttr>:$parent_type, + UnitAttr:$abstract, UnitAttr:$no_init, UnitAttr:$no_destroy, UnitAttr:$no_final @@ -3109,8 +3152,9 @@ def fir_TypeInfoOp : fir_Op<"type_info", ]; let assemblyFormat = [{ - $sym_name (`noinit` $no_init^)? (`nodestroy` $no_destroy^)? - (`nofinal` $no_final^)? (`extends` $parent_type^)? attr-dict `:` $type + $sym_name (`abstract` $abstract^)? (`noinit` $no_init^)? + (`nodestroy` $no_destroy^)? (`nofinal` $no_final^)? + (`extends` $parent_type^)? attr-dict `:` $type (`dispatch_table` $dispatch_table^)? (`component_info` $component_info^)? }]; @@ -3136,23 +3180,34 @@ def fir_DTEntryOp : fir_Op<"dt_entry", [HasParent<"TypeInfoOp">]> { let summary = "map entry in a dispatch table"; let description = [{ - An entry in a dispatch table. Allows a function symbol to be bound - to a specifier method identifier. A dispatch operation uses the dynamic + An entry in a dispatch table. Allows a function symbol to be bound + to a specifier method identifier. A dispatch operation uses the dynamic type of a distinguished argument to determine an exact dispatch table and uses the method identifier to select the type-bound procedure to be called. + The optional "deferred" flag indicates that the binding is a DEFERRED + type-bound procedure (declared but without an implementation at this + type level). + ``` + // Non-deferred binding fir.dt_entry method_name, @uniquedProcedure + + // Deferred binding + fir.dt_entry method_name, @uniquedProcedure deferred ``` }]; - let arguments = (ins StrAttr:$method, SymbolRefAttr:$proc); + let arguments = (ins StrAttr:$method, SymbolRefAttr:$proc, UnitAttr:$deferred); let hasCustomAssemblyFormat = 1; let extraClassDeclaration = [{ static constexpr llvm::StringRef getProcAttrNameStr() { return "proc"; } + static constexpr llvm::StringRef getDeferredAttrNameStr() { + return "deferred"; + } }]; } @@ -3221,7 +3276,8 @@ def fir_DeclareOp : fir_Op<"declare", [AttrSizedOperandSegments, MemoryEffects<[MemAlloc<DebuggingResource>]>, DeclareOpInterfaceMethods< - fir_FortranVariableStorageOpInterface>]> { + fir_FortranVariableStorageOpInterface>, + fir_FortranObjectViewOpInterface]> { let summary = "declare a variable"; let description = [{ @@ -3274,17 +3330,24 @@ def fir_DeclareOp DefaultValuedAttr<UI64Attr, "0">:$storage_offset, Builtin_StringAttr:$uniq_name, OptionalAttr<fir_FortranVariableFlagsAttr>:$fortran_attrs, - OptionalAttr<cuf_DataAttributeAttr>:$data_attr); + OptionalAttr<cuf_DataAttributeAttr>:$data_attr, + OptionalAttr<UI32Attr>:$dummy_arg_no); let results = (outs AnyRefOrBox); let assemblyFormat = [{ $memref (`(` $shape^ `)`)? (`typeparams` $typeparams^)? - (`dummy_scope` $dummy_scope^)? + (`dummy_scope` $dummy_scope^ (`arg` $dummy_arg_no^)?)? (`storage` `(` $storage^ `[` $storage_offset `]` `)`)? attr-dict `:` functional-type(operands, results) }]; + let extraClassDeclaration = [{ + // FortranObjectViewOpInterface methods: + mlir::Value getViewSource(mlir::OpResult) { return getMemref(); } + std::optional<std::int64_t> getViewOffset(mlir::OpResult) { return 0; } + }]; + let hasVerifier = 1; } @@ -3707,7 +3770,7 @@ def fir_DeclareReductionOp : fir_Op<"declare_reduction", [IsolatedFromAbove, duplication at the moment. TODO Combine both ops into one. See: https://discourse.llvm.org/t/dialect-for-data-locality-sharing-specifiers-clauses-in-openmp-openacc-and-do-concurrent/86108. - Declares a `do concurrent` reduction. This requires two mandatory and three + Declares a `do concurrent` reduction. This requires two mandatory and four optional regions. 1. The optional alloc region specifies how to allocate the thread-local @@ -3736,6 +3799,9 @@ def fir_DeclareReductionOp : fir_Op<"declare_reduction", [IsolatedFromAbove, allocated by the initializer region. The region has an argument that contains the value of the thread-local reduction accumulator. This will be executed after the reduction has completed. + 6. The DataPtrPtr region specifies how to access the base address of a + boxed-value. This is used, in particular, for GPU reductions in order + know where partial reduction results are stored in remote lanes. Note that the MLIR type system does not allow for type-polymorphic reductions. Separate reduction declarations should be created for different @@ -3743,23 +3809,30 @@ def fir_DeclareReductionOp : fir_Op<"declare_reduction", [IsolatedFromAbove, For initializer and reduction regions, the operand to `fir.yield` must match the parent operation's results. + + * `$byref_element_type`: For by-ref reductions, we want to keep track of the + boxed/allocated type. For example, for a `real, allocatable` variable, + `real` should be stored in this attribute. }]; let arguments = (ins SymbolNameAttr:$sym_name, - TypeAttr:$type); + TypeAttr:$type, + OptionalAttr<TypeAttr>:$byref_element_type); let regions = (region MaxSizedRegion<1>:$allocRegion, AnyRegion:$initializerRegion, AnyRegion:$reductionRegion, AnyRegion:$atomicReductionRegion, - AnyRegion:$cleanupRegion); + AnyRegion:$cleanupRegion, + AnyRegion:$dataPtrPtrRegion); let assemblyFormat = "$sym_name `:` $type attr-dict-with-keyword " "( `alloc` $allocRegion^ )? " "`init` $initializerRegion " "`combiner` $reductionRegion " "( `atomic` $atomicReductionRegion^ )? " - "( `cleanup` $cleanupRegion^ )? "; + "( `cleanup` $cleanupRegion^ )? " + "( `data_ptr_ptr` $dataPtrPtrRegion^ )? "; let extraClassDeclaration = [{ mlir::BlockArgument getAllocMoldArg() { diff --git a/flang/include/flang/Optimizer/Dialect/FortranVariableInterface.td b/flang/include/flang/Optimizer/Dialect/FortranVariableInterface.td index bd65a04..f89be52 100644 --- a/flang/include/flang/Optimizer/Dialect/FortranVariableInterface.td +++ b/flang/include/flang/Optimizer/Dialect/FortranVariableInterface.td @@ -265,4 +265,59 @@ def fir_FortranVariableStorageOpInterface [{ return detail::verifyFortranVariableStorageOpInterface($_op); }]; } +def fir_FortranObjectViewOpInterface + : OpInterface<"FortranObjectViewOpInterface"> { + let description = [{ + Interface for operations that may produce results that allow accessing + objects in memory based on the operands of these operations. + For example: + ``` + %0 = fir.convert %x : (!llvm.ptr) -> !fir.llvm_ptr<i32> + ``` + When the result of `fir.convert` is used to access an object in memory, + FIR alias analysis may want to pass through `fir.convert` to be able + to find the original Fortran object that is being accessed. + This interface provides methods that allow discovering information + about the accessed object and the characteristics of the resulting + "view" of the object, e.g. whether the result and the input + access the object from the same location within the object or + whether they are offsetted (which may happen, for example, in case of + `fir.array_coor` operation). + }]; + let cppNamespace = "::fir"; + + let methods = + [InterfaceMethod< + /*desc=*/ + [{ Returns the operand which the given OpResult is based on. }], + /*retTy=*/"::mlir::Value", + /*methodName=*/"getViewSource", + /*args=*/(ins "::mlir::OpResult":$resultView), + /*methodBody=*/"", + /*defaultImplementation=*/[{ + assert($_op.getOperation() == resultView.getOwner() && + "resultView must be a result of this operation"); + return $_op.getViewSource(resultView); + }]>, + InterfaceMethod< + /*desc=*/[{ + Returns the constant offset (in bytes) applied to the corresponding + operand to produce the resulting view. + If it is not possible to identify the constant offset, + the result is nullopt. + Note that the offset may be negative, e.g. when addressing + an array section with a negative stride. + }], + /*retTy=*/"std::optional<std::int64_t>", + /*methodName=*/"getViewOffset", + /*args=*/(ins "::mlir::OpResult":$resultView), + /*methodBody=*/"", + /*defaultImplementation=*/[{ + assert($_op.getOperation() == resultView.getOwner() && + "resultView must be a result of this operation"); + return $_op.getViewOffset(resultView); + }]>, + ]; +} + #endif // FORTRANVARIABLEINTERFACE diff --git a/flang/include/flang/Optimizer/Dialect/MIF/MIFOps.td b/flang/include/flang/Optimizer/Dialect/MIF/MIFOps.td index 52471d3..a6c7d0a0 100644 --- a/flang/include/flang/Optimizer/Dialect/MIF/MIFOps.td +++ b/flang/include/flang/Optimizer/Dialect/MIF/MIFOps.td @@ -21,6 +21,10 @@ include "flang/Optimizer/Dialect/FIRAttr.td" class mif_Op<string mnemonic, list<Trait> traits> : Op<MIFDialect, mnemonic, traits>; +class region_Op<string mnemonic, list<Trait> traits = []> + : mif_Op<mnemonic, !listconcat(traits, [RecursivelySpeculatable, + RecursiveMemoryEffects])> {} + //===----------------------------------------------------------------------===// // Initialization and Finalization //===----------------------------------------------------------------------===// @@ -174,6 +178,18 @@ def mif_SyncMemoryOp : mif_Op<"sync_memory", [AttrSizedOperandSegments]> { }]; } +def mif_SyncTeamOp : mif_Op<"sync_team", [AttrSizedOperandSegments]> { + let summary = "Performs a synchronization of the team, identified by `team`"; + + let arguments = (ins AnyRefOrBoxType:$team, Optional<AnyReferenceLike>:$stat, + Optional<AnyRefOrBoxType>:$errmsg); + let assemblyFormat = [{ + $team (`stat` $stat^ )? + (`errmsg` $errmsg^ )? + attr-dict `:` functional-type(operands, results) + }]; +} + //===----------------------------------------------------------------------===// // Collective Operations //===----------------------------------------------------------------------===// @@ -265,4 +281,148 @@ def mif_CoSumOp }]; } +//===----------------------------------------------------------------------===// +// Teams +//===----------------------------------------------------------------------===// + +def mif_FormTeamOp : mif_Op<"form_team", [AttrSizedOperandSegments]> { + let summary = + "Create a set of sibling teams whose parent team is the current team."; + let description = [{ + Create a new team for each unique `team_number` value specified. + Each executing image will belong to the team whose `team_number` is equal + to the value of team-number on that image, and `team_var` becomes defined + with a value that identifies that team. + + If `new_index` is specified, the image index of the executing image will take + this index in its new team. Otherwise, the new image index is processor + dependent. + + Arguments: + - `team_number`: Shall be a positive integer. + - `team_var` : Shall be a variable of type TEAM_TYPE from the intrinsic + module ISO_FORTRAN_ENV. + - `new_index`(optional): Shall be an integer that correspond to the index that + the calling image will have in the new team. + }]; + + let arguments = (ins AnyIntegerType:$team_number, + Arg<fir_BoxType, "", [MemWrite]>:$team_var, + Optional<AnyIntegerType>:$new_index, + Arg<Optional<AnyReferenceLike>, "", [MemWrite]>:$stat, + Arg<Optional<AnyRefOrBoxType>, "", [MemWrite]>:$errmsg); + + let assemblyFormat = [{ + `team_number` $team_number `team_var` $team_var + (`new_index` $new_index^ )? + (`stat` $stat^ )? + (`errmsg` $errmsg^ )? + attr-dict `:` functional-type(operands, results) + }]; +} + +def mif_EndTeamOp : mif_Op<"end_team", [AttrSizedOperandSegments, Terminator, + ParentOneOf<["ChangeTeamOp"]>]> { + let summary = "Changes the current team to the parent team."; + let description = [{ + The END TEAM operation completes the CHANGE TEAM construct and + restores the current team to the team that was current before + the CHANGE TEAM construct. + }]; + + let arguments = (ins Arg<Optional<AnyReferenceLike>, "", [MemWrite]>:$stat, + Arg<Optional<AnyRefOrBoxType>, "", [MemWrite]>:$errmsg); + let builders = [OpBuilder<(ins), [{ /* do nothing */ }]>]; + + let assemblyFormat = [{ + (`stat` $stat^ )? (`errmsg` $errmsg^ )? + attr-dict `:` functional-type(operands, results) + }]; +} + +//===----------------------------------------------------------------------===// +// NOTE: The CHANGE TEAM region will take a coarray association list in +// argument. However, coarray management and coarray alias creation are not +// yet supported by the dialect. The argument is therefore not yet supported by +// this operation and will be added later. +//===----------------------------------------------------------------------===// +def mif_ChangeTeamOp + : region_Op<"change_team", [AttrSizedOperandSegments, + SingleBlockImplicitTerminator<"EndTeamOp">]> { + let summary = "Changes the current team."; + let description = [{ + The CHANGE TEAM construct changes the current team to the specified new + team, which must be a child team of the current team. + + ``` + mif.change_team %team { + %x = fir.convert %i : (index) -> i32 + ... + mif.end_team + } + }]; + + let arguments = (ins AnyRefOrBoxType:$team, + Arg<Optional<AnyReferenceLike>, "", [MemWrite]>:$stat, + Arg<Optional<AnyRefOrBoxType>, "", [MemWrite]>:$errmsg); + let regions = (region SizedRegion<1>:$region); + + let skipDefaultBuilders = 1; + let builders = + [OpBuilder<(ins "mlir::Value":$team, + CArg<"bool", "true">:$ensureTermination, + CArg<"llvm::ArrayRef<mlir::NamedAttribute>", "{}">:$attributes)>, + OpBuilder<(ins "mlir::Value":$team, "mlir::Value":$stat, + "mlir::Value":$errmsg, CArg<"bool", "true">:$ensureTermination, + CArg<"llvm::ArrayRef<mlir::NamedAttribute>", "{}">:$attributes)>]; + + let extraClassDeclaration = [{ + /// Get the body of the CHANGE TEAM construct + mlir::Block *getBody() { return &getRegion().front(); } + }]; + + let assemblyFormat = [{ + $team (`stat` $stat^)? + (`errmsg` $errmsg^)? + attr-dict `:` `(` type(operands) `)` + custom<ChangeTeamOpBody>($region) + }]; +} + +def mif_GetTeamOp : mif_Op<"get_team", []> { + let summary = "Get the team value for the current or ancestor team."; + let description = [{ + This operation gets the team value for the current or an ancestor team. + `level`(optional): If provided, must equal one of the following constants : + `INITIAL_TEAM`, `PARENT_TEAM` or `CURRENT_TEAM` from the module ISO_FORTRAN_ENV. + If `level` isn't present or has the value `CURRENT_TEAM` the returned + value is the current team. + }]; + + let arguments = (ins Optional<AnyIntegerType>:$level); + let results = (outs fir_BoxType:$team); + + let assemblyFormat = [{ + (`level` $level^ )? + attr-dict `:` functional-type(operands, results) + }]; +} + +def mif_TeamNumberOp : mif_Op<"team_number", []> { + let summary = "Get the team number"; + let description = [{ + Argument: `team` is optional and shall be a scalar of type TEAM_TYPE from + module ISO_FORTRAN_ENV and the value identifies the current or an ancestor team. + If `team` is absent, the team specified is the current team. + }]; + + let arguments = (ins Optional<AnyRefOrBoxType>:$team); + let results = (outs I64); + + let assemblyFormat = [{ + (`team` $team^ )? + attr-dict `:` functional-type(operands, results) + }]; +} + #endif // FORTRAN_DIALECT_MIF_MIF_OPS diff --git a/flang/include/flang/Optimizer/HLFIR/HLFIROps.td b/flang/include/flang/Optimizer/HLFIR/HLFIROps.td index b7563a2..e0d309f 100644 --- a/flang/include/flang/Optimizer/HLFIR/HLFIROps.td +++ b/flang/include/flang/Optimizer/HLFIR/HLFIROps.td @@ -39,7 +39,8 @@ def hlfir_DeclareOp : hlfir_Op<"declare", [AttrSizedOperandSegments, MemoryEffects<[MemAlloc<DebuggingResource>]>, DeclareOpInterfaceMethods< - fir_FortranVariableStorageOpInterface>]> { + fir_FortranVariableStorageOpInterface>, + fir_FortranObjectViewOpInterface]> { let summary = "declare a variable and produce an SSA value that can be used as a variable in HLFIR operations"; let description = [{ @@ -103,13 +104,13 @@ def hlfir_DeclareOp Builtin_StringAttr:$uniq_name, OptionalAttr<fir_FortranVariableFlagsAttr>:$fortran_attrs, OptionalAttr<cuf_DataAttributeAttr>:$data_attr, - OptionalAttr<UnitAttr>:$skip_rebox); + OptionalAttr<UnitAttr>:$skip_rebox, OptionalAttr<UI32Attr>:$dummy_arg_no); let results = (outs AnyFortranVariable, AnyRefOrBoxLike); let assemblyFormat = [{ $memref (`(` $shape^ `)`)? (`typeparams` $typeparams^)? - (`dummy_scope` $dummy_scope^)? + (`dummy_scope` $dummy_scope^ (`arg` $dummy_arg_no^)?)? (`storage` `(` $storage^ `[` $storage_offset `]` `)`)? (`skip_rebox` $skip_rebox^)? attr-dict `:` functional-type(operands, results) @@ -122,7 +123,8 @@ def hlfir_DeclareOp CArg<"mlir::Value", "{}">:$storage, CArg<"std::uint64_t", "0">:$storage_offset, CArg<"fir::FortranVariableFlagsAttr", "{}">:$fortran_attrs, - CArg<"cuf::DataAttributeAttr", "{}">:$data_attr)>]; + CArg<"cuf::DataAttributeAttr", "{}">:$data_attr, + CArg<"unsigned", "0">:$dummy_arg_no)>]; let extraClassDeclaration = [{ /// Get the variable original base (same as input). It lacks @@ -140,6 +142,10 @@ def hlfir_DeclareOp /// Given a FIR memory type, and information about non default lower /// bounds, get the related HLFIR variable type. static mlir::Type getHLFIRVariableType(mlir::Type type, bool hasLowerBounds); + + // FortranObjectViewOpInterface methods: + mlir::Value getViewSource(mlir::OpResult) { return getMemref(); } + std::optional<std::int64_t> getViewOffset(mlir::OpResult) { return 0; } }]; let hasVerifier = 1; @@ -213,8 +219,11 @@ def fir_AssignOp : hlfir_Op<"assign", [DeclareOpInterfaceMethods<MemoryEffectsOp let hasVerifier = 1; } -def hlfir_DesignateOp : hlfir_Op<"designate", [AttrSizedOperandSegments, - DeclareOpInterfaceMethods<fir_FortranVariableOpInterface>, NoMemoryEffect]> { +def hlfir_DesignateOp + : hlfir_Op<"designate", + [AttrSizedOperandSegments, + DeclareOpInterfaceMethods<fir_FortranVariableOpInterface>, + NoMemoryEffect, fir_FortranObjectViewOpInterface]> { let summary = "Designate a Fortran variable"; let description = [{ @@ -278,6 +287,9 @@ def hlfir_DesignateOp : hlfir_Op<"designate", [AttrSizedOperandSegments, void setFortranAttrs(fir::FortranVariableFlagsEnum flags) { this->setFortranAttrs(std::optional<fir::FortranVariableFlagsEnum>(flags)); } + // FortranObjectViewOpInterface methods: + mlir::Value getViewSource(mlir::OpResult) { return getMemref(); } + std::optional<std::int64_t> getViewOffset(mlir::OpResult); }]; let builders = [ @@ -938,8 +950,9 @@ def hlfir_EndAssociateOp : hlfir_Op<"end_associate", [MemoryEffects<[MemFree]>]> let hasVerifier = 1; } -def hlfir_AsExprOp : hlfir_Op<"as_expr", - [DeclareOpInterfaceMethods<MemoryEffectsOpInterface>]> { +def hlfir_AsExprOp + : hlfir_Op< + "as_expr", [DeclareOpInterfaceMethods<MemoryEffectsOpInterface>]> { let summary = "Take the value of an array, character or derived variable"; let description = [{ @@ -961,8 +974,8 @@ def hlfir_AsExprOp : hlfir_Op<"as_expr", let results = (outs hlfir_ExprType); let extraClassDeclaration = [{ - // Is this a "move" ? - bool isMove() { return getMustFree() != mlir::Value{}; } + // Is this a "move" ? + bool isMove() { return getMustFree() != mlir::Value{}; } }]; let assemblyFormat = [{ diff --git a/flang/include/flang/Optimizer/OpenACC/Analysis/FIROpenACCSupportAnalysis.h b/flang/include/flang/Optimizer/OpenACC/Analysis/FIROpenACCSupportAnalysis.h new file mode 100644 index 0000000..c798681 --- /dev/null +++ b/flang/include/flang/Optimizer/OpenACC/Analysis/FIROpenACCSupportAnalysis.h @@ -0,0 +1,51 @@ +//===- FIROpenACCSupportAnalysis.h - FIR OpenACCSupport Analysis ----------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines the FIR-specific implementation of OpenACCSupport analysis. +// +//===----------------------------------------------------------------------===// + +#ifndef FORTRAN_OPTIMIZER_OPENACC_ANALYSIS_FIROPENACCSUPPORTANALYSIS_H +#define FORTRAN_OPTIMIZER_OPENACC_ANALYSIS_FIROPENACCSUPPORTANALYSIS_H + +#include "mlir/Dialect/OpenACC/OpenACC.h" +#include "mlir/IR/Value.h" +#include <string> + +namespace fir { +namespace acc { + +/// FIR-specific implementation for the OpenACCSupport analysis interface. +/// +/// This class provides the custom implementations of the OpenACCSupport +/// interface methods that are tailored to FIR's requirements and +/// can handle FIR dialect operations and types. +/// Its primary intent is to be registered with the OpenACCSupport analysis +/// using setImplementation() +/// +/// Usage: +/// auto &support = getAnalysis<mlir::acc::OpenACCSupport>(); +/// support.setImplementation(fir::acc::FIROpenACCSupportAnalysis()); +/// +class FIROpenACCSupportAnalysis { +public: + FIROpenACCSupportAnalysis() = default; + + std::string getVariableName(mlir::Value v); + + std::string getRecipeName(mlir::acc::RecipeKind kind, mlir::Type type, + mlir::Value var); + + mlir::InFlightDiagnostic emitNYI(mlir::Location loc, + const mlir::Twine &message); +}; + +} // namespace acc +} // namespace fir + +#endif // FORTRAN_OPTIMIZER_OPENACC_ANALYSIS_FIROPENACCSUPPORTANALYSIS_H diff --git a/flang/include/flang/Optimizer/OpenACC/Passes.h b/flang/include/flang/Optimizer/OpenACC/Passes.h index 0627cc8..c27c7ebc 100644 --- a/flang/include/flang/Optimizer/OpenACC/Passes.h +++ b/flang/include/flang/Optimizer/OpenACC/Passes.h @@ -13,6 +13,9 @@ #ifndef FORTRAN_OPTIMIZER_OPENACC_PASSES_H #define FORTRAN_OPTIMIZER_OPENACC_PASSES_H +#include "flang/Optimizer/Dialect/FIRDialect.h" +#include "flang/Optimizer/HLFIR/HLFIRDialect.h" +#include "mlir/Dialect/OpenACC/OpenACC.h" #include "mlir/IR/BuiltinOps.h" #include "mlir/Pass/Pass.h" #include "mlir/Pass/PassRegistry.h" @@ -25,6 +28,7 @@ namespace acc { #define GEN_PASS_REGISTRATION #include "flang/Optimizer/OpenACC/Passes.h.inc" +std::unique_ptr<mlir::Pass> createACCInitializeFIRAnalysesPass(); std::unique_ptr<mlir::Pass> createACCRecipeBufferizationPass(); } // namespace acc diff --git a/flang/include/flang/Optimizer/OpenACC/Passes.td b/flang/include/flang/Optimizer/OpenACC/Passes.td index 3c127b3..d947aa4 100644 --- a/flang/include/flang/Optimizer/OpenACC/Passes.td +++ b/flang/include/flang/Optimizer/OpenACC/Passes.td @@ -11,6 +11,22 @@ include "mlir/Pass/PassBase.td" +def ACCInitializeFIRAnalyses + : Pass<"acc-initialize-fir-analyses", "mlir::ModuleOp"> { + let summary = "Initialize FIR analyses for OpenACC passes"; + let description = [{ + This pass initializes analyses that can be used by subsequent OpenACC passes + in the pipeline. It creates and caches the OpenACCSupport analysis with a + FIR-specific implementation that can handle FIR types and operations. + It also initializes FIR's AliasAnalysis for use in OpenACC passes. + This pass needs to rerun if any analyses were invalidated by MLIR's framework. + }]; + // In addition to pre-registering the needed analyses, this pass also + // pre-registers the dialects that various OpenACC passes may generate. + let dependentDialects = ["fir::FIROpsDialect", "hlfir::hlfirDialect", + "mlir::acc::OpenACCDialect"]; +} + def ACCRecipeBufferization : Pass<"fir-acc-recipe-bufferization", "mlir::ModuleOp"> { let summary = "Rewrite acc.*.recipe box values to ref<box> and update uses"; diff --git a/flang/include/flang/Optimizer/OpenACC/Support/FIROpenACCOpsInterfaces.h b/flang/include/flang/Optimizer/OpenACC/Support/FIROpenACCOpsInterfaces.h index 7afe97a..d7f8f87c 100644 --- a/flang/include/flang/Optimizer/OpenACC/Support/FIROpenACCOpsInterfaces.h +++ b/flang/include/flang/Optimizer/OpenACC/Support/FIROpenACCOpsInterfaces.h @@ -16,7 +16,9 @@ #include "mlir/Dialect/OpenACC/OpenACC.h" namespace fir { +class AddrOfOp; class DeclareOp; +class GlobalOp; } // namespace fir namespace hlfir { @@ -53,6 +55,28 @@ struct PartialEntityAccessModel<hlfir::DeclareOp> bool isCompleteView(mlir::Operation *op) const; }; +struct AddressOfGlobalModel + : public mlir::acc::AddressOfGlobalOpInterface::ExternalModel< + AddressOfGlobalModel, fir::AddrOfOp> { + mlir::SymbolRefAttr getSymbol(mlir::Operation *op) const; +}; + +struct GlobalVariableModel + : public mlir::acc::GlobalVariableOpInterface::ExternalModel< + GlobalVariableModel, fir::GlobalOp> { + bool isConstant(mlir::Operation *op) const; + mlir::Region *getInitRegion(mlir::Operation *op) const; +}; + +template <typename Op> +struct IndirectGlobalAccessModel + : public mlir::acc::IndirectGlobalAccessOpInterface::ExternalModel< + IndirectGlobalAccessModel<Op>, Op> { + void getReferencedSymbols(mlir::Operation *op, + llvm::SmallVectorImpl<mlir::SymbolRefAttr> &symbols, + mlir::SymbolTable *symbolTable) const; +}; + } // namespace fir::acc #endif // FLANG_OPTIMIZER_OPENACC_FIROPENACC_OPS_INTERFACES_H_ diff --git a/flang/include/flang/Optimizer/OpenACC/Support/FIROpenACCTypeInterfaces.h b/flang/include/flang/Optimizer/OpenACC/Support/FIROpenACCTypeInterfaces.h index 3167c55..0f13362 100644 --- a/flang/include/flang/Optimizer/OpenACC/Support/FIROpenACCTypeInterfaces.h +++ b/flang/include/flang/Optimizer/OpenACC/Support/FIROpenACCTypeInterfaces.h @@ -43,6 +43,15 @@ struct OpenACCPointerLikeModel mlir::TypedValue<mlir::acc::PointerLikeType> destination, mlir::TypedValue<mlir::acc::PointerLikeType> source, mlir::Type varType) const; + + mlir::Value genLoad(mlir::Type pointer, mlir::OpBuilder &builder, + mlir::Location loc, + mlir::TypedValue<mlir::acc::PointerLikeType> srcPtr, + mlir::Type valueType) const; + + bool genStore(mlir::Type pointer, mlir::OpBuilder &builder, + mlir::Location loc, mlir::Value valueToStore, + mlir::TypedValue<mlir::acc::PointerLikeType> destPtr) const; }; template <typename T> diff --git a/flang/include/flang/Optimizer/OpenACC/Support/FIROpenACCUtils.h b/flang/include/flang/Optimizer/OpenACC/Support/FIROpenACCUtils.h new file mode 100644 index 0000000..5ca0925 --- /dev/null +++ b/flang/include/flang/Optimizer/OpenACC/Support/FIROpenACCUtils.h @@ -0,0 +1,57 @@ +//===- FIROpenACCUtils.h - FIR OpenACC Utilities ----------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file declares utility functions for FIR OpenACC support. +// +//===----------------------------------------------------------------------===// + +#ifndef FORTRAN_OPTIMIZER_OPENACC_SUPPORT_FIROPENACCUTILS_H +#define FORTRAN_OPTIMIZER_OPENACC_SUPPORT_FIROPENACCUTILS_H + +#include "mlir/Dialect/OpenACC/OpenACC.h" +#include "mlir/IR/Value.h" +#include <string> + +namespace fir { +namespace acc { + +/// Attempts to extract the variable name from a value by walking through +/// FIR operations and looking for variable names. +/// \param v The value to extract the variable name from +/// \param preferDemangledName If true, prefers demangled/bindc names over +/// mangled/unique names. If false, prefers mangled names. +/// Returns empty string if no name is found. +std::string getVariableName(mlir::Value v, bool preferDemangledName = true); + +/// Get the recipe name for a given recipe kind, FIR type, and optional +/// variable. Uses FIR's type string representation with appropriate prefix. For +/// firstprivate and reduction recipes, handles bounds suffix when all bounds +/// are constant. For reduction recipes, embeds the operator name in the recipe. +/// \param kind The recipe kind (private, firstprivate, or reduction) +/// \param type The FIR type (must be a FIR type) +/// \param var Optional variable value +/// \param bounds Optional bounds for array sections (used for suffix +/// generation) +/// \param reductionOp Optional reduction operator (required for reduction +/// recipes) +/// \return The complete recipe name with all necessary suffixes +std::string getRecipeName(mlir::acc::RecipeKind kind, mlir::Type type, + mlir::Value var = nullptr, + llvm::ArrayRef<mlir::Value> bounds = {}, + mlir::acc::ReductionOperator reductionOp = + mlir::acc::ReductionOperator::AccNone); + +/// Check if all bounds are expressed with constant values. +/// \param bounds Array of DataBoundsOp values to check +/// \return true if all bounds have constant lowerbound/upperbound or extent +bool areAllBoundsConstant(llvm::ArrayRef<mlir::Value> bounds); + +} // namespace acc +} // namespace fir + +#endif // FORTRAN_OPTIMIZER_OPENACC_SUPPORT_FIROPENACCUTILS_H diff --git a/flang/include/flang/Optimizer/Transforms/CUDA/CUFAllocationConversion.h b/flang/include/flang/Optimizer/Transforms/CUDA/CUFAllocationConversion.h new file mode 100644 index 0000000..2a4eb1c --- /dev/null +++ b/flang/include/flang/Optimizer/Transforms/CUDA/CUFAllocationConversion.h @@ -0,0 +1,33 @@ +//===------- CUFAllocationConversion.h --------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef FORTRAN_OPTIMIZER_TRANSFORMS_CUDA_CUFALLOCATIONCONVERSION_H_ +#define FORTRAN_OPTIMIZER_TRANSFORMS_CUDA_CUFALLOCATIONCONVERSION_H_ + +#include "mlir/Pass/Pass.h" +#include "mlir/Pass/PassRegistry.h" + +namespace fir { +class LLVMTypeConverter; +} + +namespace mlir { +class DataLayout; +class SymbolTable; +} // namespace mlir + +namespace cuf { + +/// Patterns that convert CUF operations to runtime calls. +void populateCUFAllocationConversionPatterns( + const fir::LLVMTypeConverter &converter, mlir::DataLayout &dl, + const mlir::SymbolTable &symtab, mlir::RewritePatternSet &patterns); + +} // namespace cuf + +#endif // FORTRAN_OPTIMIZER_TRANSFORMS_CUDA_CUFALLOCATIONCONVERSION_H_ diff --git a/flang/include/flang/Optimizer/Transforms/Passes.h b/flang/include/flang/Optimizer/Transforms/Passes.h index 6f5dff4..4dcddda 100644 --- a/flang/include/flang/Optimizer/Transforms/Passes.h +++ b/flang/include/flang/Optimizer/Transforms/Passes.h @@ -40,7 +40,6 @@ std::unique_ptr<mlir::Pass> createArrayValueCopyPass(fir::ArrayValueCopyOptions options = {}); std::unique_ptr<mlir::Pass> createMemDataFlowOptPass(); std::unique_ptr<mlir::Pass> createPromoteToAffinePass(); -std::unique_ptr<mlir::Pass> createFIRToSCFPass(); std::unique_ptr<mlir::Pass> createAddDebugInfoPass(fir::AddDebugInfoOptions options = {}); @@ -53,6 +52,9 @@ std::unique_ptr<mlir::Pass> createVScaleAttrPass(); std::unique_ptr<mlir::Pass> createVScaleAttrPass(std::pair<unsigned, unsigned> vscaleAttr); +void populateFIRToSCFRewrites(mlir::RewritePatternSet &patterns, + bool parallelUnordered = false); + void populateCfgConversionRewrites(mlir::RewritePatternSet &patterns, bool forceLoopToExecuteOnce = false, bool setNSW = true); diff --git a/flang/include/flang/Optimizer/Transforms/Passes.td b/flang/include/flang/Optimizer/Transforms/Passes.td index bb2509b..f502027 100644 --- a/flang/include/flang/Optimizer/Transforms/Passes.td +++ b/flang/include/flang/Optimizer/Transforms/Passes.td @@ -81,10 +81,13 @@ def FIRToSCFPass : Pass<"fir-to-scf"> { let description = [{ Convert FIR structured control flow ops to SCF dialect. }]; - let constructor = "::fir::createFIRToSCFPass()"; let dependentDialects = [ "fir::FIROpsDialect", "mlir::scf::SCFDialect" ]; + let options = [Option<"parallelUnordered", "parallel-unordered", "bool", + /*default=*/"false", + "Allow converting a fir.do_loop with the `unordered` " + "attribute to scf.parallel (experimental).">]; } def AnnotateConstantOperands : Pass<"annotate-constant"> { @@ -467,11 +470,19 @@ def AssumedRankOpConversion : Pass<"fir-assumed-rank-op", "mlir::ModuleOp"> { ]; } +def CUFAllocationConversion : Pass<"cuf-allocation-convert", "mlir::ModuleOp"> { + let summary = "Convert allocation related CUF operations to runtime calls"; + let dependentDialects = ["fir::FIROpsDialect"]; +} + def CUFOpConversion : Pass<"cuf-convert", "mlir::ModuleOp"> { let summary = "Convert some CUF operations to runtime calls"; let dependentDialects = [ "fir::FIROpsDialect", "mlir::gpu::GPUDialect", "mlir::DLTIDialect" ]; + let options = [Option<"allocationConversion", "allocation-conversion", "bool", + /*default=*/"true", + "Convert allocation related operation with this pass">]; } def CUFDeviceGlobal : diff --git a/flang/include/flang/Parser/characters.h b/flang/include/flang/Parser/characters.h index dbdc058..3761700 100644 --- a/flang/include/flang/Parser/characters.h +++ b/flang/include/flang/Parser/characters.h @@ -69,10 +69,6 @@ inline constexpr char ToLowerCaseLetter(char ch) { return IsUpperCaseLetter(ch) ? ch - 'A' + 'a' : ch; } -inline constexpr char ToLowerCaseLetter(char &&ch) { - return IsUpperCaseLetter(ch) ? ch - 'A' + 'a' : ch; -} - inline std::string ToLowerCaseLetters(std::string_view str) { std::string lowered{str}; for (char &ch : lowered) { @@ -85,10 +81,6 @@ inline constexpr char ToUpperCaseLetter(char ch) { return IsLowerCaseLetter(ch) ? ch - 'a' + 'A' : ch; } -inline constexpr char ToUpperCaseLetter(char &&ch) { - return IsLowerCaseLetter(ch) ? ch - 'a' + 'A' : ch; -} - inline std::string ToUpperCaseLetters(std::string_view str) { std::string raised{str}; for (char &ch : raised) { diff --git a/flang/include/flang/Parser/dump-parse-tree.h b/flang/include/flang/Parser/dump-parse-tree.h index a7398a4..58fa48e 100644 --- a/flang/include/flang/Parser/dump-parse-tree.h +++ b/flang/include/flang/Parser/dump-parse-tree.h @@ -14,9 +14,11 @@ #include "parse-tree.h" #include "tools.h" #include "unparse.h" +#include "flang/Common/enum-set.h" #include "flang/Common/idioms.h" #include "flang/Common/indirection.h" #include "flang/Support/Fortran.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/Frontend/OpenMP/OMP.h" #include "llvm/Support/raw_ostream.h" #include <string> @@ -35,6 +37,19 @@ public: : out_(out), asFortran_{asFortran} {} static constexpr const char *GetNodeName(const char *) { return "char *"; } + + template <typename T, typename E, size_t B> + static std::string GetMemberNames(const common::EnumSet<E, B> &x) { + llvm::ListSeparator sep; + std::string s; + llvm::raw_string_ostream stream(s); + x.IterateOverMembers([&](E e) { stream << sep << T::EnumToString(e); }); + return stream.str(); + } +#define NODE_ENUMSET(T, S) \ + static std::string GetNodeName(const T::S &x) { \ + return #S " = {"s + GetMemberNames<T>(x) + "}"s; \ + } #define NODE_NAME(T, N) \ static constexpr const char *GetNodeName(const T &) { return N; } #define NODE_ENUM(T, E) \ @@ -207,17 +222,21 @@ public: NODE(CompilerDirective, AssumeAligned) NODE(CompilerDirective, IgnoreTKR) NODE(CompilerDirective, Inline) + NODE(CompilerDirective, IVDep) NODE(CompilerDirective, ForceInline) NODE(CompilerDirective, LoopCount) NODE(CompilerDirective, NameValue) NODE(CompilerDirective, NoInline) NODE(CompilerDirective, Unrecognized) NODE(CompilerDirective, VectorAlways) + NODE_ENUM(CompilerDirective::VectorLength, VectorLength::Kind) + NODE(CompilerDirective, VectorLength) NODE(CompilerDirective, Unroll) NODE(CompilerDirective, UnrollAndJam) NODE(CompilerDirective, NoVector) NODE(CompilerDirective, NoUnroll) NODE(CompilerDirective, NoUnrollAndJam) + NODE(CompilerDirective, Prefetch) NODE(parser, ComplexLiteralConstant) NODE(parser, ComplexPart) NODE(parser, ComponentArraySpec) @@ -387,6 +406,7 @@ public: NODE(parser, TeamValue) NODE(parser, ImageSelector) NODE(parser, ImageSelectorSpec) + NODE(ImageSelectorSpec, Notify) NODE(ImageSelectorSpec, Stat) NODE(ImageSelectorSpec, Team_Number) NODE(parser, ImplicitPart) @@ -512,6 +532,7 @@ public: NODE(parser, OmpAlignModifier) NODE(parser, OmpAllocateClause) NODE(OmpAllocateClause, Modifier) + NODE(parser, OmpAllocateDirective) NODE(parser, OmpAllocatorComplexModifier) NODE(parser, OmpAllocatorSimpleModifier) NODE(parser, OmpAlwaysModifier) @@ -568,7 +589,8 @@ public: NODE_ENUM(OmpDeviceTypeClause, DeviceTypeDescription) NODE(parser, OmpDirectiveName) NODE(parser, OmpDirectiveSpecification) - NODE_ENUM(OmpDirectiveSpecification, Flags) + NODE_ENUM(OmpDirectiveSpecification, Flag) + NODE_ENUMSET(OmpDirectiveSpecification, Flags) NODE(parser, OmpDoacross) NODE(OmpDoacross, Sink) NODE(OmpDoacross, Source) @@ -585,6 +607,8 @@ public: NODE(parser, OmpExpectation) NODE_ENUM(OmpExpectation, Value) NODE(parser, OmpFailClause) + NODE(parser, OmpFallbackModifier) + NODE_ENUM(OmpFallbackModifier, Value) NODE(parser, OmpFromClause) NODE(OmpFromClause, Modifier) NODE(parser, OmpGrainsizeClause) @@ -621,7 +645,7 @@ public: NODE_ENUM(OmpLinearModifier, Value) NODE(parser, OmpLocator) NODE(parser, OmpLocatorList) - NODE(parser, OmpLoopRangeClause) + NODE(parser, OmpLooprangeClause) NODE(parser, OmpMapClause) NODE(OmpMapClause, Modifier) NODE(parser, OmpMapper) @@ -739,7 +763,6 @@ public: NODE(parser, OpenMPCancellationPointConstruct) NODE(parser, OpenMPConstruct) NODE(parser, OpenMPCriticalConstruct) - NODE(parser, OpenMPDeclarativeAllocate) NODE(parser, OpenMPDeclarativeAssumes) NODE(parser, OpenMPDeclarativeConstruct) NODE(parser, OpenMPDeclareMapperConstruct) @@ -748,10 +771,11 @@ public: NODE(parser, OpenMPDeclareTargetConstruct) NODE(parser, OpenMPDepobjConstruct) NODE(parser, OpenMPDispatchConstruct) - NODE(parser, OpenMPExecutableAllocate) NODE(parser, OpenMPFlushConstruct) NODE(parser, OpenMPGroupprivate) + NODE(parser, OpenMPInvalidDirective) NODE(parser, OpenMPLoopConstruct) + NODE(parser, OpenMPMisplacedEndDirective) NODE(parser, OpenMPRequiresConstruct) NODE(parser, OpenMPSectionConstruct) NODE(parser, OpenMPSectionsConstruct) diff --git a/flang/include/flang/Parser/openmp-utils.h b/flang/include/flang/Parser/openmp-utils.h index 49db091..e164f63 100644 --- a/flang/include/flang/Parser/openmp-utils.h +++ b/flang/include/flang/Parser/openmp-utils.h @@ -14,6 +14,7 @@ #define FORTRAN_PARSER_OPENMP_UTILS_H #include "flang/Common/indirection.h" +#include "flang/Common/template.h" #include "flang/Parser/parse-tree.h" #include "llvm/Frontend/OpenMP/OMP.h" @@ -22,6 +23,7 @@ #include <type_traits> #include <utility> #include <variant> +#include <vector> namespace Fortran::parser::omp { @@ -33,23 +35,6 @@ template <typename T> constexpr auto addr_if(const std::optional<T> &x) { } namespace detail { -using D = llvm::omp::Directive; - -template <typename Construct> // -struct ConstructId { - static constexpr llvm::omp::Directive id{D::OMPD_unknown}; -}; - -#define MAKE_CONSTR_ID(Construct, Id) \ - template <> struct ConstructId<Construct> { \ - static constexpr llvm::omp::Directive id{Id}; \ - } - -MAKE_CONSTR_ID(OpenMPDeclarativeAllocate, D::OMPD_allocate); -MAKE_CONSTR_ID(OpenMPExecutableAllocate, D::OMPD_allocate); - -#undef MAKE_CONSTR_ID - struct DirectiveNameScope { static OmpDirectiveName MakeName(CharBlock source = {}, llvm::omp::Directive id = llvm::omp::Directive::OMPD_unknown) { @@ -83,23 +68,10 @@ struct DirectiveNameScope { template <typename T> static OmpDirectiveName GetOmpDirectiveName(const T &x) { if constexpr (WrapperTrait<T>) { - if constexpr (std::is_same_v<T, OpenMPCancelConstruct> || - std::is_same_v<T, OpenMPCancellationPointConstruct> || - std::is_same_v<T, OpenMPDepobjConstruct> || - std::is_same_v<T, OpenMPFlushConstruct> || - std::is_same_v<T, OpenMPInteropConstruct> || - std::is_same_v<T, OpenMPSimpleStandaloneConstruct> || - std::is_same_v<T, OpenMPGroupprivate>) { - return x.v.DirName(); - } else { - return GetOmpDirectiveName(x.v); - } + return GetOmpDirectiveName(x.v); } else if constexpr (TupleTrait<T>) { if constexpr (std::is_base_of_v<OmpBlockConstruct, T>) { return std::get<OmpBeginDirective>(x.t).DirName(); - } else if constexpr (std::is_same_v<T, OpenMPDeclarativeAllocate> || - std::is_same_v<T, OpenMPExecutableAllocate>) { - return MakeName(std::get<Verbatim>(x.t).source, ConstructId<T>::id); } else { return GetFromTuple( x.t, std::make_index_sequence<std::tuple_size_v<decltype(x.t)>>{}); @@ -139,7 +111,105 @@ template <typename T> OmpDirectiveName GetOmpDirectiveName(const T &x) { return detail::DirectiveNameScope::GetOmpDirectiveName(x); } +const OpenMPDeclarativeConstruct *GetOmp(const DeclarationConstruct &x); +const OpenMPConstruct *GetOmp(const ExecutionPartConstruct &x); + +const OpenMPLoopConstruct *GetOmpLoop(const ExecutionPartConstruct &x); +const DoConstruct *GetDoConstruct(const ExecutionPartConstruct &x); + +// Is the template argument "Statement<T>" for some T? +template <typename T> struct IsStatement { + static constexpr bool value{false}; +}; +template <typename T> struct IsStatement<Statement<T>> { + static constexpr bool value{true}; +}; + +std::optional<Label> GetStatementLabel(const ExecutionPartConstruct &x); +std::optional<Label> GetFinalLabel(const OpenMPConstruct &x); + +namespace detail { +// Clauses with flangClass = "OmpObjectList". +using MemberObjectListClauses = + std::tuple<OmpClause::Copyin, OmpClause::Copyprivate, OmpClause::Exclusive, + OmpClause::Firstprivate, OmpClause::HasDeviceAddr, OmpClause::Inclusive, + OmpClause::IsDevicePtr, OmpClause::Link, OmpClause::Private, + OmpClause::Shared, OmpClause::UseDeviceAddr, OmpClause::UseDevicePtr>; + +// Clauses with flangClass = "OmpSomeClause", and OmpObjectList a +// member of tuple OmpSomeClause::t. +using TupleObjectListClauses = std::tuple<OmpClause::AdjustArgs, + OmpClause::Affinity, OmpClause::Aligned, OmpClause::Allocate, + OmpClause::Enter, OmpClause::From, OmpClause::InReduction, + OmpClause::Lastprivate, OmpClause::Linear, OmpClause::Map, + OmpClause::Reduction, OmpClause::TaskReduction, OmpClause::To>; + +// Does U have WrapperTrait (i.e. has a member 'v'), and if so, is T the +// type of v? +template <typename T, typename U, bool IsWrapper> struct WrappedInType { + static constexpr bool value{false}; +}; + +template <typename T, typename U> struct WrappedInType<T, U, true> { + static constexpr bool value{std::is_same_v<T, decltype(U::v)>}; +}; + +// Same as WrappedInType, but with a list of types Us. Satisfied if any +// type U in Us satisfies WrappedInType<T, U>. +template <typename...> struct WrappedInTypes; + +template <typename T> struct WrappedInTypes<T> { + static constexpr bool value{false}; +}; + +template <typename T, typename U, typename... Us> +struct WrappedInTypes<T, U, Us...> { + static constexpr bool value{WrappedInType<T, U, WrapperTrait<U>>::value || + WrappedInTypes<T, Us...>::value}; +}; + +// Same as WrappedInTypes, but takes type list in a form of a tuple or +// a variant. +template <typename...> struct WrappedInTupleOrVariant { + static constexpr bool value{false}; +}; +template <typename T, typename... Us> +struct WrappedInTupleOrVariant<T, std::tuple<Us...>> { + static constexpr bool value{WrappedInTypes<T, Us...>::value}; +}; +template <typename T, typename... Us> +struct WrappedInTupleOrVariant<T, std::variant<Us...>> { + static constexpr bool value{WrappedInTypes<T, Us...>::value}; +}; +template <typename T, typename U> +constexpr bool WrappedInTupleOrVariantV{WrappedInTupleOrVariant<T, U>::value}; +} // namespace detail + +template <typename T> const OmpObjectList *GetOmpObjectList(const T &clause) { + using namespace detail; + static_assert(std::is_class_v<T>, "Unexpected argument type"); + + if constexpr (common::HasMember<T, decltype(OmpClause::u)>) { + if constexpr (common::HasMember<T, MemberObjectListClauses>) { + return &clause.v; + } else if constexpr (common::HasMember<T, TupleObjectListClauses>) { + return &std::get<OmpObjectList>(clause.v.t); + } else { + return nullptr; + } + } else if constexpr (WrappedInTupleOrVariantV<T, TupleObjectListClauses>) { + return &std::get<OmpObjectList>(clause.t); + } else if constexpr (WrappedInTupleOrVariantV<T, decltype(OmpClause::u)>) { + return nullptr; + } else { + // The condition should be type-dependent, but it should always be false. + static_assert(sizeof(T) < 0 && "Unexpected argument type"); + } +} + const OmpObjectList *GetOmpObjectList(const OmpClause &clause); +const OmpObjectList *GetOmpObjectList(const OmpClause::Depend &clause); +const OmpObjectList *GetOmpObjectList(const OmpDependClause::TaskDep &x); template <typename T> const T *GetFirstArgument(const OmpDirectiveSpecification &spec) { @@ -153,11 +223,20 @@ const T *GetFirstArgument(const OmpDirectiveSpecification &spec) { const BlockConstruct *GetFortranBlockConstruct( const ExecutionPartConstruct &epc); +const Block &GetInnermostExecPart(const Block &block); +bool IsStrictlyStructuredBlock(const Block &block); const OmpCombinerExpression *GetCombinerExpr( const OmpReductionSpecifier &rspec); const OmpInitializerExpression *GetInitializerExpr(const OmpClause &init); +struct OmpAllocateInfo { + std::vector<const OmpAllocateDirective *> dirs; + const ExecutionPartConstruct *body{nullptr}; +}; + +OmpAllocateInfo SplitOmpAllocate(const OmpAllocateDirective &x); + } // namespace Fortran::parser::omp #endif // FORTRAN_PARSER_OPENMP_UTILS_H diff --git a/flang/include/flang/Parser/parse-tree-visitor.h b/flang/include/flang/Parser/parse-tree-visitor.h index af1d34a..7ebce67 100644 --- a/flang/include/flang/Parser/parse-tree-visitor.h +++ b/flang/include/flang/Parser/parse-tree-visitor.h @@ -10,6 +10,7 @@ #define FORTRAN_PARSER_PARSE_TREE_VISITOR_H_ #include "parse-tree.h" +#include "flang/Common/enum-set.h" #include "flang/Common/visit.h" #include <cstddef> #include <optional> @@ -41,7 +42,7 @@ struct ParseTreeVisitorLookupScope { // Default case for visitation of non-class data members, strings, and // any other non-decomposable values. template <typename A, typename V> - static std::enable_if_t<!std::is_class_v<A> || + static std::enable_if_t<!std::is_class_v<A> || common::IsEnumSet<A> || std::is_same_v<std::string, A> || std::is_same_v<CharBlock, A>> Walk(const A &x, V &visitor) { if (visitor.Pre(x)) { diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h index 375790a..c4ace2d 100644 --- a/flang/include/flang/Parser/parse-tree.h +++ b/flang/include/flang/Parser/parse-tree.h @@ -22,6 +22,7 @@ #include "format-specification.h" #include "message.h" #include "provenance.h" +#include "flang/Common/enum-set.h" #include "flang/Common/idioms.h" #include "flang/Common/indirection.h" #include "flang/Common/reference.h" @@ -269,9 +270,9 @@ struct AccEndCombinedDirective; struct OpenACCDeclarativeConstruct; struct OpenACCRoutineConstruct; struct OpenMPConstruct; -struct OpenMPLoopConstruct; struct OpenMPDeclarativeConstruct; -struct OmpEndLoopDirective; +struct OpenMPInvalidDirective; +struct OpenMPMisplacedEndDirective; struct CUFKernelDoConstruct; // Cooked character stream locations @@ -407,6 +408,8 @@ struct SpecificationConstruct { common::Indirection<StructureDef>, common::Indirection<OpenACCDeclarativeConstruct>, common::Indirection<OpenMPDeclarativeConstruct>, + common::Indirection<OpenMPMisplacedEndDirective>, + common::Indirection<OpenMPInvalidDirective>, common::Indirection<CompilerDirective>> u; }; @@ -539,7 +542,8 @@ struct ExecutableConstruct { common::Indirection<OpenACCConstruct>, common::Indirection<AccEndCombinedDirective>, common::Indirection<OpenMPConstruct>, - common::Indirection<OmpEndLoopDirective>, + common::Indirection<OpenMPMisplacedEndDirective>, + common::Indirection<OpenMPInvalidDirective>, common::Indirection<CUFKernelDoConstruct>> u; }; @@ -1684,13 +1688,15 @@ using Cosubscript = ScalarIntExpr; WRAPPER_CLASS(TeamValue, Scalar<common::Indirection<Expr>>); // R926 image-selector-spec -> +// NOTIFY = notify-variable | // STAT = stat-variable | TEAM = team-value | // TEAM_NUMBER = scalar-int-expr struct ImageSelectorSpec { WRAPPER_CLASS(Stat, Scalar<Integer<common::Indirection<Variable>>>); WRAPPER_CLASS(Team_Number, ScalarIntExpr); + WRAPPER_CLASS(Notify, Scalar<common::Indirection<Variable>>); UNION_CLASS_BOILERPLATE(ImageSelectorSpec); - std::variant<Stat, TeamValue, Team_Number> u; + std::variant<Notify, Stat, TeamValue, Team_Number> u; }; // R924 image-selector -> @@ -3358,9 +3364,11 @@ struct StmtFunctionStmt { // !DIR$ NOVECTOR // !DIR$ NOUNROLL // !DIR$ NOUNROLL_AND_JAM +// !DIR$ PREFETCH designator[, designator]... // !DIR$ FORCEINLINE // !DIR$ INLINE // !DIR$ NOINLINE +// !DIR$ IVDEP // !DIR$ <anything else> struct CompilerDirective { UNION_CLASS_BOILERPLATE(CompilerDirective); @@ -3376,6 +3384,12 @@ struct CompilerDirective { std::tuple<common::Indirection<Designator>, uint64_t> t; }; EMPTY_CLASS(VectorAlways); + struct VectorLength { + TUPLE_CLASS_BOILERPLATE(VectorLength); + ENUM_CLASS(Kind, Auto, Fixed, Scalable); + + std::tuple<std::uint64_t, Kind> t; + }; struct NameValue { TUPLE_CLASS_BOILERPLATE(NameValue); std::tuple<Name, std::optional<std::uint64_t>> t; @@ -3386,17 +3400,23 @@ struct CompilerDirective { struct UnrollAndJam { WRAPPER_CLASS_BOILERPLATE(UnrollAndJam, std::optional<std::uint64_t>); }; + struct Prefetch { + WRAPPER_CLASS_BOILERPLATE( + Prefetch, std::list<common::Indirection<Designator>>); + }; EMPTY_CLASS(NoVector); EMPTY_CLASS(NoUnroll); EMPTY_CLASS(NoUnrollAndJam); EMPTY_CLASS(ForceInline); EMPTY_CLASS(Inline); EMPTY_CLASS(NoInline); + EMPTY_CLASS(IVDep); EMPTY_CLASS(Unrecognized); CharBlock source; std::variant<std::list<IgnoreTKR>, LoopCount, std::list<AssumeAligned>, - VectorAlways, std::list<NameValue>, Unroll, UnrollAndJam, Unrecognized, - NoVector, NoUnroll, NoUnrollAndJam, ForceInline, Inline, NoInline> + VectorAlways, VectorLength, std::list<NameValue>, Unroll, UnrollAndJam, + Unrecognized, NoVector, NoUnroll, NoUnrollAndJam, ForceInline, Inline, + NoInline, Prefetch, IVDep> u; }; @@ -3992,6 +4012,17 @@ struct OmpExpectation { WRAPPER_CLASS_BOILERPLATE(OmpExpectation, Value); }; +// Ref: [6.1:tbd] +// +// fallback-modifier -> +// FALLBACK(fallback-mode) // since 6.1 +// fallback-mode -> +// ABORT | DEFAULT_MEM | NULL // since 6.1 +struct OmpFallbackModifier { + ENUM_CLASS(Value, Abort, Default_Mem, Null); + WRAPPER_CLASS_BOILERPLATE(OmpFallbackModifier, Value); +}; + // REF: [5.1:217-220], [5.2:293-294] // // OmpInteropRuntimeIdentifier -> // since 5.2 @@ -4121,9 +4152,8 @@ struct OmpOrderModifier { // // prescriptiveness -> // STRICT // since 5.1 -// FALLBACK // since 6.1 struct OmpPrescriptiveness { - ENUM_CLASS(Value, Strict, Fallback) + ENUM_CLASS(Value, Strict) WRAPPER_CLASS_BOILERPLATE(OmpPrescriptiveness, Value); }; @@ -4504,7 +4534,7 @@ struct OmpDynamicAllocatorsClause { struct OmpDynGroupprivateClause { TUPLE_CLASS_BOILERPLATE(OmpDynGroupprivateClause); - MODIFIER_BOILERPLATE(OmpAccessGroup, OmpPrescriptiveness); + MODIFIER_BOILERPLATE(OmpAccessGroup, OmpFallbackModifier); std::tuple<MODIFIERS(), ScalarIntExpr> t; }; @@ -4642,10 +4672,10 @@ struct OmpLinearClause { // Ref: [6.0:207-208] // -// loop-range-clause -> +// looprange-clause -> // LOOPRANGE(first, count) // since 6.0 -struct OmpLoopRangeClause { - TUPLE_CLASS_BOILERPLATE(OmpLoopRangeClause); +struct OmpLooprangeClause { + TUPLE_CLASS_BOILERPLATE(OmpLooprangeClause); std::tuple<ScalarIntConstantExpr, ScalarIntConstantExpr> t; }; @@ -4952,7 +4982,9 @@ struct OmpClauseList { // --- Directives and constructs struct OmpDirectiveSpecification { - ENUM_CLASS(Flags, None, DeprecatedSyntax); + ENUM_CLASS(Flag, DeprecatedSyntax, CrossesLabelDo) + using Flags = common::EnumSet<Flag, Flag_enumSize>; + TUPLE_CLASS_BOILERPLATE(OmpDirectiveSpecification); const OmpDirectiveName &DirName() const { return std::get<OmpDirectiveName>(t); @@ -5151,17 +5183,42 @@ struct OpenMPThreadprivate { CharBlock source; }; -// 2.11.3 allocate -> ALLOCATE (variable-name-list) [clause] -struct OpenMPDeclarativeAllocate { - TUPLE_CLASS_BOILERPLATE(OpenMPDeclarativeAllocate); - CharBlock source; - std::tuple<Verbatim, OmpObjectList, OmpClauseList> t; +// Ref: [4.5:310-312], [5.0:156-158], [5.1:181-184], [5.2:176-177], +// [6.0:310-312] +// +// allocate-directive -> +// ALLOCATE (variable-list-item...) | // since 4.5 +// ALLOCATE (variable-list-item...) // since 5.0, until 5.1 +// ... +// allocate-stmt +// +// The first form is the "declarative-allocate", and is a declarative +// directive. The second is the "executable-allocate" and is an executable +// directive. The executable form was deprecated in 5.2. +// +// The executable-allocate consists of several ALLOCATE directives. Since +// in the parse tree every type corresponding to a directive only corresponds +// to a single directive, the executable form is represented by a sequence +// of nested OmpAlocateDirectives, e.g. +// !$OMP ALLOCATE(x) +// !$OMP ALLOCATE(y) +// ALLOCATE(x, y) +// will become +// OmpAllocateDirective +// |- ALLOCATE(x) // begin directive +// `- OmpAllocateDirective // block +// |- ALLOCATE(y) // begin directive +// `- ALLOCATE(x, y) // block +// +// The block in the declarative-allocate will be empty. +struct OmpAllocateDirective : public OmpBlockConstruct { + INHERITED_TUPLE_CLASS_BOILERPLATE(OmpAllocateDirective, OmpBlockConstruct); }; struct OpenMPDeclarativeConstruct { UNION_CLASS_BOILERPLATE(OpenMPDeclarativeConstruct); CharBlock source; - std::variant<OpenMPDeclarativeAllocate, OpenMPDeclarativeAssumes, + std::variant<OmpAllocateDirective, OpenMPDeclarativeAssumes, OpenMPDeclareMapperConstruct, OpenMPDeclareReductionConstruct, OpenMPDeclareSimdConstruct, OpenMPDeclareTargetConstruct, OmpDeclareVariantDirective, OpenMPGroupprivate, OpenMPThreadprivate, @@ -5174,19 +5231,6 @@ struct OpenMPCriticalConstruct : public OmpBlockConstruct { INHERITED_TUPLE_CLASS_BOILERPLATE(OpenMPCriticalConstruct, OmpBlockConstruct); }; -// 2.11.3 allocate -> ALLOCATE [(variable-name-list)] [clause] -// [ALLOCATE (variable-name-list) [clause] [...]] -// allocate-statement -// clause -> allocator-clause -struct OpenMPExecutableAllocate { - TUPLE_CLASS_BOILERPLATE(OpenMPExecutableAllocate); - CharBlock source; - std::tuple<Verbatim, std::optional<OmpObjectList>, OmpClauseList, - std::optional<std::list<OpenMPDeclarativeAllocate>>, - Statement<AllocateStmt>> - t; -}; - // Ref: [5.2:180-181], [6.0:315] // // allocators-construct -> @@ -5313,12 +5357,10 @@ struct OmpEndLoopDirective : public OmpEndDirective { }; // OpenMP directives enclosing do loop -using NestedConstruct = - std::variant<DoConstruct, common::Indirection<OpenMPLoopConstruct>>; struct OpenMPLoopConstruct { TUPLE_CLASS_BOILERPLATE(OpenMPLoopConstruct); OpenMPLoopConstruct(OmpBeginLoopDirective &&a) - : t({std::move(a), std::nullopt, std::nullopt}) {} + : t({std::move(a), Block{}, std::nullopt}) {} const OmpBeginLoopDirective &BeginDir() const { return std::get<OmpBeginLoopDirective>(t); @@ -5326,8 +5368,11 @@ struct OpenMPLoopConstruct { const std::optional<OmpEndLoopDirective> &EndDir() const { return std::get<std::optional<OmpEndLoopDirective>>(t); } - std::tuple<OmpBeginLoopDirective, std::optional<NestedConstruct>, - std::optional<OmpEndLoopDirective>> + const DoConstruct *GetNestedLoop() const; + const OpenMPLoopConstruct *GetNestedConstruct() const; + + CharBlock source; + std::tuple<OmpBeginLoopDirective, Block, std::optional<OmpEndLoopDirective>> t; }; @@ -5342,12 +5387,25 @@ struct OpenMPConstruct { UNION_CLASS_BOILERPLATE(OpenMPConstruct); std::variant<OpenMPStandaloneConstruct, OpenMPSectionsConstruct, OpenMPSectionConstruct, OpenMPLoopConstruct, OmpBlockConstruct, - OpenMPAtomicConstruct, OpenMPDeclarativeAllocate, OpenMPDispatchConstruct, - OpenMPUtilityConstruct, OpenMPExecutableAllocate, - OpenMPAllocatorsConstruct, OpenMPAssumeConstruct, OpenMPCriticalConstruct> + OpenMPAtomicConstruct, OmpAllocateDirective, OpenMPDispatchConstruct, + OpenMPUtilityConstruct, OpenMPAllocatorsConstruct, OpenMPAssumeConstruct, + OpenMPCriticalConstruct> u; }; +// Orphaned !$OMP END <directive>, i.e. not being a part of a valid OpenMP +// construct. +struct OpenMPMisplacedEndDirective : public OmpEndDirective { + INHERITED_TUPLE_CLASS_BOILERPLATE( + OpenMPMisplacedEndDirective, OmpEndDirective); +}; + +// Unrecognized string after the !$OMP sentinel. +struct OpenMPInvalidDirective { + using EmptyTrait = std::true_type; + CharBlock source; +}; + // Parse tree nodes for OpenACC 3.3 directives and clauses struct AccObject { diff --git a/flang/include/flang/Parser/preprocessor.h b/flang/include/flang/Parser/preprocessor.h index bb13b44..0405d42 100644 --- a/flang/include/flang/Parser/preprocessor.h +++ b/flang/include/flang/Parser/preprocessor.h @@ -38,6 +38,7 @@ public: Definition(const std::vector<std::string> &argNames, const TokenSequence &, std::size_t firstToken, std::size_t tokens, bool isVariadic = false); Definition(const std::string &predefined, AllSources &); + Definition(const TokenSequence &predefined); bool isFunctionLike() const { return isFunctionLike_; } std::size_t argumentCount() const { return argNames_.size(); } diff --git a/flang/include/flang/Runtime/CUDA/allocator.h b/flang/include/flang/Runtime/CUDA/allocator.h index 59fdb22..5617636 100644 --- a/flang/include/flang/Runtime/CUDA/allocator.h +++ b/flang/include/flang/Runtime/CUDA/allocator.h @@ -13,11 +13,14 @@ #include "flang/Runtime/descriptor-consts.h" #include "flang/Runtime/entry-names.h" +#include "cuda_runtime.h" + namespace Fortran::runtime::cuda { extern "C" { void RTDECL(CUFRegisterAllocator)(); +cudaStream_t RTDECL(CUFGetAssociatedStream)(void *); } void *CUFAllocPinned(std::size_t, std::int64_t *); diff --git a/flang/include/flang/Runtime/extensions.h b/flang/include/flang/Runtime/extensions.h index 9fd3e11..40ce771 100644 --- a/flang/include/flang/Runtime/extensions.h +++ b/flang/include/flang/Runtime/extensions.h @@ -25,6 +25,11 @@ typedef std::uint32_t gid_t; #else #include "sys/types.h" //pid_t #endif +namespace Fortran { +namespace runtime { +class Descriptor; +} +} // namespace Fortran extern "C" { @@ -34,6 +39,7 @@ double RTNAME(Dsecnds)(double *refTime, const char *sourceFile, int line); // CALL FLUSH(n) antedates the Fortran 2003 FLUSH statement. void FORTRAN_PROCEDURE_NAME(flush)(const int &unit); +void RTNAME(Flush)(int unit); // GNU extension subroutine FDATE void FORTRAN_PROCEDURE_NAME(fdate)(char *string, std::int64_t length); @@ -101,5 +107,17 @@ int FORTRAN_PROCEDURE_NAME(mclock)(); float FORTRAN_PROCEDURE_NAME(secnds)(float *refTime); float RTNAME(Secnds)(float *refTime, const char *sourceFile, int line); +// GNU extension function IRAND(I) +int RTNAME(Irand)(int *i); + +// GNU extension function RAND(I) +float RTNAME(Rand)(int *i, const char *sourceFile, int line); + +// GNU extension subroutine SRAND(SEED) +void FORTRAN_PROCEDURE_NAME(srand)(int *seed); + +// flang extension subroutine SHOW_DESCRIPTOR(D) +void RTNAME(ShowDescriptor)(const Fortran::runtime::Descriptor *descr); + } // extern "C" #endif // FORTRAN_RUNTIME_EXTENSIONS_H_ diff --git a/flang/include/flang/Runtime/iostat-consts.h b/flang/include/flang/Runtime/iostat-consts.h index 26bf75f..47093d9 100644 --- a/flang/include/flang/Runtime/iostat-consts.h +++ b/flang/include/flang/Runtime/iostat-consts.h @@ -9,7 +9,6 @@ #ifndef FORTRAN_RUNTIME_IOSTAT_CONSTS_H_ #define FORTRAN_RUNTIME_IOSTAT_CONSTS_H_ -#include "flang/Common/api-attrs.h" #include "flang/Runtime/magic-numbers.h" namespace Fortran::runtime::io { diff --git a/flang/include/flang/Runtime/iostat.h b/flang/include/flang/Runtime/iostat.h deleted file mode 100644 index d8db68a..0000000 --- a/flang/include/flang/Runtime/iostat.h +++ /dev/null @@ -1,23 +0,0 @@ -//===-- include/flang/Runtime/iostat.h --------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -// Defines the values returned by the runtime for IOSTAT= specifiers -// on I/O statements. - -#ifndef FORTRAN_RUNTIME_IOSTAT_H_ -#define FORTRAN_RUNTIME_IOSTAT_H_ - -#include "flang/Common/api-attrs.h" -#include "flang/Runtime/iostat-consts.h" - -namespace Fortran::runtime::io { - -RT_API_ATTRS const char *IostatErrorString(int); - -} // namespace Fortran::runtime::io -#endif // FORTRAN_RUNTIME_IOSTAT_H_ diff --git a/flang/include/flang/Semantics/openmp-directive-sets.h b/flang/include/flang/Semantics/openmp-directive-sets.h index 01e8481..609a7be 100644 --- a/flang/include/flang/Semantics/openmp-directive-sets.h +++ b/flang/include/flang/Semantics/openmp-directive-sets.h @@ -275,10 +275,17 @@ static const OmpDirectiveSet loopConstructSet{ Directive::OMPD_teams_distribute_parallel_do_simd, Directive::OMPD_teams_distribute_simd, Directive::OMPD_teams_loop, + Directive::OMPD_fuse, Directive::OMPD_tile, Directive::OMPD_unroll, }; +static const OmpDirectiveSet loopTransformationSet{ + Directive::OMPD_tile, + Directive::OMPD_unroll, + Directive::OMPD_fuse, +}; + static const OmpDirectiveSet nonPartialVarSet{ Directive::OMPD_allocate, Directive::OMPD_allocators, diff --git a/flang/include/flang/Semantics/openmp-modifiers.h b/flang/include/flang/Semantics/openmp-modifiers.h index bfa3aa4..283bf2a 100644 --- a/flang/include/flang/Semantics/openmp-modifiers.h +++ b/flang/include/flang/Semantics/openmp-modifiers.h @@ -67,6 +67,7 @@ template <typename SpecificTy> const OmpModifierDescriptor &OmpGetDescriptor(); #define DECLARE_DESCRIPTOR(name) \ template <> const OmpModifierDescriptor &OmpGetDescriptor<name>() +DECLARE_DESCRIPTOR(parser::OmpAccessGroup); DECLARE_DESCRIPTOR(parser::OmpAlignment); DECLARE_DESCRIPTOR(parser::OmpAlignModifier); DECLARE_DESCRIPTOR(parser::OmpAllocatorComplexModifier); @@ -82,6 +83,7 @@ DECLARE_DESCRIPTOR(parser::OmpDependenceType); DECLARE_DESCRIPTOR(parser::OmpDeviceModifier); DECLARE_DESCRIPTOR(parser::OmpDirectiveNameModifier); DECLARE_DESCRIPTOR(parser::OmpExpectation); +DECLARE_DESCRIPTOR(parser::OmpFallbackModifier); DECLARE_DESCRIPTOR(parser::OmpInteropPreference); DECLARE_DESCRIPTOR(parser::OmpInteropType); DECLARE_DESCRIPTOR(parser::OmpIterator); diff --git a/flang/include/flang/Semantics/openmp-utils.h b/flang/include/flang/Semantics/openmp-utils.h index 032944d..f5739ab 100644 --- a/flang/include/flang/Semantics/openmp-utils.h +++ b/flang/include/flang/Semantics/openmp-utils.h @@ -72,6 +72,8 @@ const parser::OmpObject *GetArgumentObject(const parser::OmpArgument &argument); bool IsCommonBlock(const Symbol &sym); bool IsExtendedListItem(const Symbol &sym); bool IsVariableListItem(const Symbol &sym); +bool IsTypeParamInquiry(const Symbol &sym); +bool IsStructureComponent(const Symbol &sym); bool IsVarOrFunctionRef(const MaybeExpr &expr); bool IsMapEnteringType(parser::OmpMapType::Value type); @@ -95,8 +97,6 @@ const SomeExpr *HasStorageOverlap( const SomeExpr &base, llvm::ArrayRef<SomeExpr> exprs); bool IsAssignment(const parser::ActionStmt *x); bool IsPointerAssignment(const evaluate::Assignment &x); -const parser::Block &GetInnermostExecPart(const parser::Block &block); -bool IsStrictlyStructuredBlock(const parser::Block &block); } // namespace omp } // namespace Fortran::semantics diff --git a/flang/include/flang/Semantics/symbol.h b/flang/include/flang/Semantics/symbol.h index cb27d544..95efe1a 100644 --- a/flang/include/flang/Semantics/symbol.h +++ b/flang/include/flang/Semantics/symbol.h @@ -777,6 +777,24 @@ private: DeclVector declList_; }; +// Used for OpenMP DECLARE MAPPER, it holds the declaration constructs +// so they can be serialized into module files and later re-parsed when +// USE-associated. +class MapperDetails { +public: + using DeclVector = std::vector<const parser::OpenMPDeclarativeConstruct *>; + + MapperDetails() = default; + + void AddDecl(const parser::OpenMPDeclarativeConstruct *decl) { + declList_.emplace_back(decl); + } + const DeclVector &GetDeclList() const { return declList_; } + +private: + DeclVector declList_; +}; + class UnknownDetails {}; using Details = std::variant<UnknownDetails, MainProgramDetails, ModuleDetails, @@ -784,7 +802,7 @@ using Details = std::variant<UnknownDetails, MainProgramDetails, ModuleDetails, ObjectEntityDetails, ProcEntityDetails, AssocEntityDetails, DerivedTypeDetails, UseDetails, UseErrorDetails, HostAssocDetails, GenericDetails, ProcBindingDetails, NamelistDetails, CommonBlockDetails, - TypeParamDetails, MiscDetails, UserReductionDetails>; + TypeParamDetails, MiscDetails, UserReductionDetails, MapperDetails>; llvm::raw_ostream &operator<<(llvm::raw_ostream &, const Details &); std::string DetailsToString(const Details &); diff --git a/flang/include/flang/Semantics/tools.h b/flang/include/flang/Semantics/tools.h index 8a7b986..1c34770 100644 --- a/flang/include/flang/Semantics/tools.h +++ b/flang/include/flang/Semantics/tools.h @@ -107,6 +107,7 @@ bool IsBindCProcedure(const Scope &); // Returns a pointer to the function's symbol when true, else null const Symbol *IsFunctionResultWithSameNameAsFunction(const Symbol &); bool IsOrContainsEventOrLockComponent(const Symbol &); +bool IsOrContainsNotifyComponent(const Symbol &); bool CanBeTypeBoundProc(const Symbol &); // Does a non-PARAMETER symbol have explicit initialization with =value or // =>target in its declaration (but not in a DATA statement)? (Being @@ -652,6 +653,8 @@ using PotentialAndPointerComponentIterator = // dereferenced. PotentialComponentIterator::const_iterator FindEventOrLockPotentialComponent( const DerivedTypeSpec &, bool ignoreCoarrays = false); +PotentialComponentIterator::const_iterator FindNotifyPotentialComponent( + const DerivedTypeSpec &, bool ignoreCoarrays = false); PotentialComponentIterator::const_iterator FindCoarrayPotentialComponent( const DerivedTypeSpec &); PotentialAndPointerComponentIterator::const_iterator diff --git a/flang/include/flang/Semantics/type.h b/flang/include/flang/Semantics/type.h index 87583a0..3a07b6e 100644 --- a/flang/include/flang/Semantics/type.h +++ b/flang/include/flang/Semantics/type.h @@ -301,6 +301,7 @@ public: void CookParameters(evaluate::FoldingContext &); // Evaluates type parameter expressions. void EvaluateParameters(SemanticsContext &); + void ReevaluateParameters(SemanticsContext &); void AddParamValue(SourceName, ParamValue &&); // Creates a Scope for the type and populates it with component // instantiations that have been specialized with actual type parameter diff --git a/flang/include/flang/Support/LangOptions.def b/flang/include/flang/Support/LangOptions.def index e7185c8..e310ecf 100644 --- a/flang/include/flang/Support/LangOptions.def +++ b/flang/include/flang/Support/LangOptions.def @@ -61,7 +61,7 @@ LANGOPT(OpenMPNoNestedParallelism, 1, 0) /// Use SIMD only OpenMP support. LANGOPT(OpenMPSimd, 1, false) /// Enable fast MOD operations for REAL -LANGOPT(NoFastRealMod, 1, false) +LANGOPT(FastRealMod, 1, false) LANGOPT(VScaleMin, 32, 0) ///< Minimum vscale range value LANGOPT(VScaleMax, 32, 0) ///< Maximum vscale range value diff --git a/flang/lib/Evaluate/check-expression.cpp b/flang/lib/Evaluate/check-expression.cpp index 839717d..e07076e 100644 --- a/flang/lib/Evaluate/check-expression.cpp +++ b/flang/lib/Evaluate/check-expression.cpp @@ -379,8 +379,11 @@ bool IsInitialProcedureTarget(const semantics::Symbol &symbol) { common::visitors{ [&](const semantics::SubprogramDetails &subp) { return !subp.isDummy() && !subp.stmtFunction() && - symbol.owner().kind() != semantics::Scope::Kind::MainProgram && - symbol.owner().kind() != semantics::Scope::Kind::Subprogram; + ((symbol.owner().kind() != + semantics::Scope::Kind::MainProgram && + symbol.owner().kind() != + semantics::Scope::Kind::Subprogram) || + ultimate.attrs().test(semantics::Attr::EXTERNAL)); }, [](const semantics::SubprogramNameDetails &x) { return x.kind() != semantics::SubprogramKind::Internal; @@ -1475,13 +1478,12 @@ public: const characteristics::DummyDataObject &dummyObj) : fc_{fc}, actual_{actual}, dummyObj_{dummyObj} {} - // Returns true, if actual and dummy have different contiguity requirements - bool HaveContiguityDifferences() const { - // Check actual contiguity, unless dummy doesn't care + // Returns true if dummy arg needs to be contiguous + bool DummyNeedsContiguity() const { + if (dummyObj_.ignoreTKR.test(common::IgnoreTKR::Contiguous)) { + return false; + } bool dummyTreatAsArray{dummyObj_.ignoreTKR.test(common::IgnoreTKR::Rank)}; - bool actualTreatAsContiguous{ - dummyObj_.ignoreTKR.test(common::IgnoreTKR::Contiguous) || - IsSimplyContiguous(actual_, fc_)}; bool dummyIsExplicitShape{dummyObj_.type.IsExplicitShape()}; bool dummyIsAssumedSize{dummyObj_.type.attrs().test( characteristics::TypeAndShape::Attr::AssumedSize)}; @@ -1498,32 +1500,17 @@ public: (dummyTreatAsArray && !dummyIsPolymorphic) || dummyIsVoidStar || dummyObj_.attrs.test( characteristics::DummyDataObject::Attr::Contiguous)}; - return !actualTreatAsContiguous && dummyNeedsContiguity; + return dummyNeedsContiguity; } - // Returns true, if actual and dummy have polymorphic differences bool HavePolymorphicDifferences() const { - bool dummyIsAssumedRank{dummyObj_.type.attrs().test( - characteristics::TypeAndShape::Attr::AssumedRank)}; - bool actualIsAssumedRank{semantics::IsAssumedRank(actual_)}; - bool dummyIsAssumedShape{dummyObj_.type.attrs().test( - characteristics::TypeAndShape::Attr::AssumedShape)}; - bool actualIsAssumedShape{semantics::IsAssumedShape(actual_)}; - if ((actualIsAssumedRank && dummyIsAssumedRank) || - (actualIsAssumedShape && dummyIsAssumedShape)) { - // Assumed-rank and assumed-shape arrays are represented by descriptors, - // so don't need to do polymorphic check. - } else if (!dummyObj_.ignoreTKR.test(common::IgnoreTKR::Type)) { - // flang supports limited cases of passing polymorphic to non-polimorphic. - // These cases require temporary of non-polymorphic type. (For example, - // the actual argument could be polymorphic array of child type, - // while the dummy argument could be non-polymorphic array of parent - // type.) + if (dummyObj_.ignoreTKR.test(common::IgnoreTKR::Type)) { + return false; + } + if (auto actualType{ + characteristics::TypeAndShape::Characterize(actual_, fc_)}) { + bool actualIsPolymorphic{actualType->type().IsPolymorphic()}; bool dummyIsPolymorphic{dummyObj_.type.type().IsPolymorphic()}; - auto actualType{ - characteristics::TypeAndShape::Characterize(actual_, fc_)}; - bool actualIsPolymorphic{ - actualType && actualType->type().IsPolymorphic()}; if (actualIsPolymorphic && !dummyIsPolymorphic) { return true; } @@ -1572,28 +1559,32 @@ private: // procedures with explicit interface, it's expected that "dummy" is not null. // For procedures with implicit interface dummy may be null. // +// Returns std::optional<bool> indicating whether the copy is known to be +// needed (true) or not needed (false); returns std::nullopt if the necessity +// of the copy is undetermined. +// // Note that these copy-in and copy-out checks are done from the caller's // perspective, meaning that for copy-in the caller need to do the copy // before calling the callee. Similarly, for copy-out the caller is expected // to do the copy after the callee returns. -bool MayNeedCopy(const ActualArgument *actual, +std::optional<bool> ActualArgNeedsCopy(const ActualArgument *actual, const characteristics::DummyArgument *dummy, FoldingContext &fc, bool forCopyOut) { if (!actual) { - return false; + return std::nullopt; } if (actual->isAlternateReturn()) { - return false; + return std::nullopt; } const auto *dummyObj{dummy ? std::get_if<characteristics::DummyDataObject>(&dummy->u) : nullptr}; - const bool forCopyIn = !forCopyOut; + const bool forCopyIn{!forCopyOut}; if (!evaluate::IsVariable(*actual)) { - // Actual argument expressions that aren’t variables are copy-in, but - // not copy-out. + // Expressions are copy-in, but not copy-out. return forCopyIn; } + auto maybeContigActual{IsContiguous(*actual, fc)}; if (dummyObj) { // Explict interface CopyInOutExplicitInterface check{fc, *actual, *dummyObj}; if (forCopyOut && check.HasIntentIn()) { @@ -1616,28 +1607,25 @@ bool MayNeedCopy(const ActualArgument *actual, if (!check.HaveArrayOrAssumedRankArgs()) { return false; } - if (check.HaveContiguityDifferences()) { - return true; - } - if (check.HavePolymorphicDifferences()) { - return true; + if (maybeContigActual.has_value()) { + // We know whether actual arg is contiguous or not + bool isContiguousActual{maybeContigActual.value()}; + bool actualArgNeedsCopy{ + (!isContiguousActual || check.HavePolymorphicDifferences()) && + check.DummyNeedsContiguity()}; + return actualArgNeedsCopy; + } else { + // We don't know whether actual arg is contiguous or not + return check.DummyNeedsContiguity(); } } else { // Implicit interface - if (ExtractCoarrayRef(*actual)) { - // Coindexed actual args may need copy-in and copy-out with implicit - // interface - return true; - } - if (!IsSimplyContiguous(*actual, fc)) { - // Copy-in: actual arguments that are variables are copy-in when - // non-contiguous. - // Copy-out: vector subscripts could refer to duplicate elements, can't - // copy out. - return !(forCopyOut && HasVectorSubscript(*actual)); + if (maybeContigActual.has_value()) { + // If known contiguous, don't copy in/out. + // If known non-contiguous, copy in/out. + return !*maybeContigActual; } } - // For everything else, no copy-in or copy-out - return false; + return std::nullopt; } } // namespace Fortran::evaluate diff --git a/flang/lib/Evaluate/common.cpp b/flang/lib/Evaluate/common.cpp index ed6a0ef..119ea3c 100644 --- a/flang/lib/Evaluate/common.cpp +++ b/flang/lib/Evaluate/common.cpp @@ -16,25 +16,26 @@ namespace Fortran::evaluate { void FoldingContext::RealFlagWarnings( const RealFlags &flags, const char *operation) { static constexpr auto warning{common::UsageWarning::FoldingException}; + if (!realFlagWarningContext_.empty()) { + // Override 'operation' with a string like + // "compilation-time evaluation of a call to '...'" + operation = realFlagWarningContext_.c_str(); + } if (flags.test(RealFlag::Overflow)) { - Warn(warning, "overflow on %s%s"_warn_en_US, operation, - realFlagWarningContext_); + Warn(warning, "overflow on %s"_warn_en_US, operation); } if (flags.test(RealFlag::DivideByZero)) { if (std::strcmp(operation, "division") == 0) { - Warn(warning, "division by zero%s"_warn_en_US, realFlagWarningContext_); + Warn(warning, "division by zero"_warn_en_US); } else { - Warn(warning, "division by zero on %s%s"_warn_en_US, operation, - realFlagWarningContext_); + Warn(warning, "division by zero on %s"_warn_en_US, operation); } } if (flags.test(RealFlag::InvalidArgument)) { - Warn(warning, "invalid argument on %s%s"_warn_en_US, operation, - realFlagWarningContext_); + Warn(warning, "invalid argument on %s"_warn_en_US, operation); } if (flags.test(RealFlag::Underflow)) { - Warn(warning, "underflow on %s%s"_warn_en_US, operation, - realFlagWarningContext_); + Warn(warning, "underflow on %s"_warn_en_US, operation); } } diff --git a/flang/lib/Evaluate/fold-real.cpp b/flang/lib/Evaluate/fold-real.cpp index 225e340..1ff9410 100644 --- a/flang/lib/Evaluate/fold-real.cpp +++ b/flang/lib/Evaluate/fold-real.cpp @@ -425,8 +425,14 @@ Expr<Type<TypeCategory::Real, KIND>> FoldIntrinsicFunction( [](const Scalar<T> &x) -> Scalar<T> { return x.SPACING(); })); } else if (name == "sqrt") { return FoldElementalIntrinsic<T, T>(context, std::move(funcRef), - ScalarFunc<T, T>( - [](const Scalar<T> &x) -> Scalar<T> { return x.SQRT().value; })); + ScalarFunc<T, T>([&context](const Scalar<T> &x) -> Scalar<T> { + ValueWithRealFlags<Scalar<T>> result{x.SQRT()}; + if (result.flags.test(RealFlag::InvalidArgument)) { + context.Warn(common::UsageWarning::FoldingValueChecks, + "Invalid argument to SQRT()"_warn_en_US); + } + return result.value; + })); } else if (name == "sum") { return FoldSum<T>(context, std::move(funcRef)); } else if (name == "tiny") { diff --git a/flang/lib/Evaluate/intrinsics-library.cpp b/flang/lib/Evaluate/intrinsics-library.cpp index d8af524..54726ac5 100644 --- a/flang/lib/Evaluate/intrinsics-library.cpp +++ b/flang/lib/Evaluate/intrinsics-library.cpp @@ -1052,7 +1052,7 @@ std::optional<HostRuntimeWrapper> GetHostRuntimeWrapper(const std::string &name, .value()); } auto restorer{context.SetRealFlagWarningContext( - " after folding a call to '"s + name + "'"s)}; + "compilation-time evaluation of a call to '"s + name + "'"s)}; return Fold(context, ConvertToType( resultType, hostFolderWithChecks(context, std::move(args))) diff --git a/flang/lib/Evaluate/intrinsics.cpp b/flang/lib/Evaluate/intrinsics.cpp index 1de5e6b..da39f19 100644 --- a/flang/lib/Evaluate/intrinsics.cpp +++ b/flang/lib/Evaluate/intrinsics.cpp @@ -654,6 +654,11 @@ static const IntrinsicInterface genericIntrinsicFunction[]{ {{"i", OperandUnsigned}, {"j", OperandUnsigned, Rank::elementalOrBOZ}}, OperandUnsigned}, {"ior", {{"i", BOZ}, {"j", SameIntOrUnsigned}}, SameIntOrUnsigned}, + {"irand", + {{"i", TypePattern{IntType, KindCode::exactKind, 4}, Rank::scalar, + Optionality::optional}}, + TypePattern{IntType, KindCode::exactKind, 4}, Rank::scalar, + IntrinsicClass::impureFunction}, {"ishft", {{"i", SameIntOrUnsigned}, {"shift", AnyInt}}, SameIntOrUnsigned}, {"ishftc", {{"i", SameIntOrUnsigned}, {"shift", AnyInt}, @@ -872,6 +877,11 @@ static const IntrinsicInterface genericIntrinsicFunction[]{ common::Intent::In, {ArgFlag::canBeMoldNull, ArgFlag::onlyConstantInquiry}}}, DefaultInt, Rank::scalar, IntrinsicClass::inquiryFunction}, + {"rand", + {{"i", TypePattern{IntType, KindCode::exactKind, 4}, Rank::scalar, + Optionality::optional}}, + TypePattern{RealType, KindCode::exactKind, 4}, Rank::scalar, + IntrinsicClass::impureFunction}, {"range", {{"x", AnyNumeric, Rank::anyOrAssumedRank, Optionality::required, common::Intent::In, @@ -1597,6 +1607,10 @@ static const IntrinsicInterface intrinsicSubroutine[]{ {"exit", {{"status", DefaultInt, Rank::scalar, Optionality::optional}}, {}, Rank::elemental, IntrinsicClass::impureSubroutine}, {"free", {{"ptr", Addressable}}, {}}, + {"flush", + {{"unit", AnyInt, Rank::scalar, Optionality::optional, + common::Intent::In}}, + {}, Rank::elemental, IntrinsicClass::impureSubroutine}, {"fseek", {{"unit", AnyInt, Rank::scalar}, {"offset", AnyInt, Rank::scalar}, {"whence", AnyInt, Rank::scalar}, @@ -1701,6 +1715,8 @@ static const IntrinsicInterface intrinsicSubroutine[]{ {}, Rank::scalar, IntrinsicClass::impureSubroutine}, {"second", {{"time", DefaultReal, Rank::scalar}}, {}, Rank::scalar, IntrinsicClass::impureSubroutine}, + {"__builtin_show_descriptor", {{"d", AnyData, Rank::anyOrAssumedRank}}, {}, + Rank::elemental, IntrinsicClass::impureSubroutine}, {"system", {{"command", DefaultChar, Rank::scalar}, {"exitstat", DefaultInt, Rank::scalar, Optionality::optional, @@ -2822,7 +2838,8 @@ std::optional<SpecificCall> IntrinsicInterface::Match( name, characteristics::Procedure{std::move(dummyArgs), attrs}}, std::move(rearranged)}; } else { - attrs.set(characteristics::Procedure::Attr::Pure); + if (intrinsicClass != IntrinsicClass::impureFunction /* RAND and IRAND */) + attrs.set(characteristics::Procedure::Attr::Pure); characteristics::TypeAndShape typeAndShape{resultType.value(), resultRank}; characteristics::FunctionResult funcResult{std::move(typeAndShape)}; characteristics::Procedure chars{ @@ -3139,28 +3156,6 @@ IntrinsicProcTable::Implementation::HandleC_F_Pointer( if (type->HasDeferredTypeParameter()) { context.messages().Say(at, "FPTR= argument to C_F_POINTER() may not have a deferred type parameter"_err_en_US); - } else if (type->category() == TypeCategory::Derived) { - if (type->IsUnlimitedPolymorphic()) { - context.Warn(common::UsageWarning::Interoperability, at, - "FPTR= argument to C_F_POINTER() should not be unlimited polymorphic"_warn_en_US); - } else if (!type->GetDerivedTypeSpec().typeSymbol().attrs().test( - semantics::Attr::BIND_C)) { - context.Warn(common::UsageWarning::Portability, at, - "FPTR= argument to C_F_POINTER() should not have a derived type that is not BIND(C)"_port_en_US); - } - } else if (!IsInteroperableIntrinsicType( - *type, &context.languageFeatures()) - .value_or(true)) { - if (type->category() == TypeCategory::Character && - type->kind() == 1) { - context.Warn(common::UsageWarning::CharacterInteroperability, at, - "FPTR= argument to C_F_POINTER() should not have the non-interoperable character length %s"_warn_en_US, - type->AsFortran()); - } else { - context.Warn(common::UsageWarning::Interoperability, at, - "FPTR= argument to C_F_POINTER() should not have the non-interoperable intrinsic type or kind %s"_warn_en_US, - type->AsFortran()); - } } if (ExtractCoarrayRef(*expr)) { context.messages().Say(at, diff --git a/flang/lib/Evaluate/tools.cpp b/flang/lib/Evaluate/tools.cpp index bd06acc..a0035ae 100644 --- a/flang/lib/Evaluate/tools.cpp +++ b/flang/lib/Evaluate/tools.cpp @@ -63,7 +63,11 @@ Expr<SomeType> Parenthesize(Expr<SomeType> &&expr) { std::optional<DataRef> ExtractDataRef( const ActualArgument &arg, bool intoSubstring, bool intoComplexPart) { - return ExtractDataRef(arg.UnwrapExpr(), intoSubstring, intoComplexPart); + if (const Symbol *assumedType{arg.GetAssumedTypeDummy()}) { + return DataRef{*assumedType}; + } else { + return ExtractDataRef(arg.UnwrapExpr(), intoSubstring, intoComplexPart); + } } std::optional<DataRef> ExtractSubstringBase(const Substring &substring) { @@ -1210,6 +1214,20 @@ bool HasConstant(const Expr<SomeType> &expr) { return HasConstantHelper{}(expr); } +// HasStructureComponent() +struct HasStructureComponentHelper + : public AnyTraverse<HasStructureComponentHelper, bool, false> { + using Base = AnyTraverse<HasStructureComponentHelper, bool, false>; + HasStructureComponentHelper() : Base(*this) {} + using Base::operator(); + + bool operator()(const Component &) const { return true; } +}; + +bool HasStructureComponent(const Expr<SomeType> &expr) { + return HasStructureComponentHelper{}(expr); +} + parser::Message *AttachDeclaration( parser::Message &message, const Symbol &symbol) { const Symbol *unhosted{&symbol}; diff --git a/flang/lib/Evaluate/variable.cpp b/flang/lib/Evaluate/variable.cpp index b9b34d4..b257dad 100644 --- a/flang/lib/Evaluate/variable.cpp +++ b/flang/lib/Evaluate/variable.cpp @@ -89,6 +89,14 @@ std::optional<Expr<SomeType>> CoarrayRef::team() const { } } +std::optional<Expr<SomeType>> CoarrayRef::notify() const { + if (notify_) { + return notify_.value().value(); + } else { + return std::nullopt; + } +} + CoarrayRef &CoarrayRef::set_stat(Expr<SomeInteger> &&v) { CHECK(IsVariable(v)); stat_.emplace(std::move(v)); @@ -100,6 +108,11 @@ CoarrayRef &CoarrayRef::set_team(Expr<SomeType> &&v) { return *this; } +CoarrayRef &CoarrayRef::set_notify(Expr<SomeType> &&v) { + notify_.emplace(std::move(v)); + return *this; +} + const Symbol &CoarrayRef::GetFirstSymbol() const { return base().GetFirstSymbol(); } diff --git a/flang/lib/Frontend/CMakeLists.txt b/flang/lib/Frontend/CMakeLists.txt index 2b3bc0e..fb74b3d 100644 --- a/flang/lib/Frontend/CMakeLists.txt +++ b/flang/lib/Frontend/CMakeLists.txt @@ -75,7 +75,7 @@ add_flang_library(flangFrontend CLANG_LIBS clangBasic - clangDriver + clangOptions ) target_precompile_headers(flangFrontend PRIVATE diff --git a/flang/lib/Frontend/CompilerInvocation.cpp b/flang/lib/Frontend/CompilerInvocation.cpp index 548ca67..b6c4e63 100644 --- a/flang/lib/Frontend/CompilerInvocation.cpp +++ b/flang/lib/Frontend/CompilerInvocation.cpp @@ -26,8 +26,8 @@ #include "clang/Basic/DiagnosticOptions.h" #include "clang/Driver/CommonArgs.h" #include "clang/Driver/Driver.h" -#include "clang/Driver/OptionUtils.h" -#include "clang/Driver/Options.h" +#include "clang/Options/OptionUtils.h" +#include "clang/Options/Options.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSwitch.h" @@ -82,11 +82,11 @@ static bool parseShowColorsArgs(const llvm::opt::ArgList &args, for (auto *a : args) { const llvm::opt::Option &opt = a->getOption(); - if (opt.matches(clang::driver::options::OPT_fcolor_diagnostics)) { + if (opt.matches(clang::options::OPT_fcolor_diagnostics)) { showColors = Colors_On; - } else if (opt.matches(clang::driver::options::OPT_fno_color_diagnostics)) { + } else if (opt.matches(clang::options::OPT_fno_color_diagnostics)) { showColors = Colors_Off; - } else if (opt.matches(clang::driver::options::OPT_fdiagnostics_color_EQ)) { + } else if (opt.matches(clang::options::OPT_fdiagnostics_color_EQ)) { llvm::StringRef value(a->getValue()); if (value == "always") showColors = Colors_On; @@ -107,15 +107,13 @@ static unsigned getOptimizationLevel(llvm::opt::ArgList &args, clang::DiagnosticsEngine &diags) { unsigned defaultOpt = 0; - if (llvm::opt::Arg *a = - args.getLastArg(clang::driver::options::OPT_O_Group)) { - if (a->getOption().matches(clang::driver::options::OPT_O0)) + if (llvm::opt::Arg *a = args.getLastArg(clang::options::OPT_O_Group)) { + if (a->getOption().matches(clang::options::OPT_O0)) return 0; - assert(a->getOption().matches(clang::driver::options::OPT_O)); + assert(a->getOption().matches(clang::options::OPT_O)); - return getLastArgIntValue(args, clang::driver::options::OPT_O, defaultOpt, - diags); + return getLastArgIntValue(args, clang::options::OPT_O, defaultOpt, diags); } return defaultOpt; @@ -133,7 +131,7 @@ static bool parseDebugArgs(Fortran::frontend::CodeGenOptions &opts, clang::DiagnosticsEngine &diags) { using DebugInfoKind = llvm::codegenoptions::DebugInfoKind; if (llvm::opt::Arg *arg = - args.getLastArg(clang::driver::options::OPT_debug_info_kind_EQ)) { + args.getLastArg(clang::options::OPT_debug_info_kind_EQ)) { std::optional<DebugInfoKind> val = llvm::StringSwitch<std::optional<DebugInfoKind>>(arg->getValue()) .Case("line-tables-only", llvm::codegenoptions::DebugLineTablesOnly) @@ -158,13 +156,13 @@ static bool parseDebugArgs(Fortran::frontend::CodeGenOptions &opts, diags.Report(debugWarning) << arg->getValue(); } opts.DwarfVersion = - getLastArgIntValue(args, clang::driver::options::OPT_dwarf_version_EQ, + getLastArgIntValue(args, clang::options::OPT_dwarf_version_EQ, /*Default=*/0, diags); if (const llvm::opt::Arg *a = - args.getLastArg(clang::driver::options::OPT_split_dwarf_file)) + args.getLastArg(clang::options::OPT_split_dwarf_file)) opts.SplitDwarfFile = a->getValue(); if (const llvm::opt::Arg *a = - args.getLastArg(clang::driver::options::OPT_split_dwarf_output)) + args.getLastArg(clang::options::OPT_split_dwarf_output)) opts.SplitDwarfOutput = a->getValue(); } return true; @@ -174,7 +172,7 @@ static void parseDoConcurrentMapping(Fortran::frontend::CodeGenOptions &opts, llvm::opt::ArgList &args, clang::DiagnosticsEngine &diags) { llvm::opt::Arg *arg = - args.getLastArg(clang::driver::options::OPT_fdo_concurrent_to_openmp_EQ); + args.getLastArg(clang::options::OPT_fdo_concurrent_to_openmp_EQ); if (!arg) return; @@ -199,7 +197,7 @@ static void parseDoConcurrentMapping(Fortran::frontend::CodeGenOptions &opts, static bool parseVectorLibArg(Fortran::frontend::CodeGenOptions &opts, llvm::opt::ArgList &args, clang::DiagnosticsEngine &diags) { - llvm::opt::Arg *arg = args.getLastArg(clang::driver::options::OPT_fveclib); + llvm::opt::Arg *arg = args.getLastArg(clang::options::OPT_fveclib); if (!arg) return true; @@ -237,7 +235,7 @@ parseOptimizationRemark(clang::DiagnosticsEngine &diags, CodeGenOptions::OptRemark result; for (llvm::opt::Arg *a : args) { - if (a->getOption().matches(clang::driver::options::OPT_R_Joined)) { + if (a->getOption().matches(clang::options::OPT_R_Joined)) { llvm::StringRef value = a->getValue(); if (value == remarkOptName) { @@ -274,43 +272,45 @@ static void parseCodeGenArgs(Fortran::frontend::CodeGenOptions &opts, clang::DiagnosticsEngine &diags) { opts.OptimizationLevel = getOptimizationLevel(args, diags); - if (args.hasFlag(clang::driver::options::OPT_fdebug_pass_manager, - clang::driver::options::OPT_fno_debug_pass_manager, false)) + if (args.hasFlag(clang::options::OPT_fdebug_pass_manager, + clang::options::OPT_fno_debug_pass_manager, false)) opts.DebugPassManager = 1; - if (args.hasFlag(clang::driver::options::OPT_fstack_arrays, - clang::driver::options::OPT_fno_stack_arrays, false)) + if (args.hasFlag(clang::options::OPT_fstack_arrays, + clang::options::OPT_fno_stack_arrays, false)) opts.StackArrays = 1; - if (args.getLastArg(clang::driver::options::OPT_floop_interchange)) + if (args.getLastArg(clang::options::OPT_floop_interchange)) opts.InterchangeLoops = 1; - if (args.getLastArg(clang::driver::options::OPT_fexperimental_loop_fusion)) + if (args.getLastArg(clang::options::OPT_fexperimental_loop_fusion)) opts.FuseLoops = 1; - if (args.getLastArg(clang::driver::options::OPT_vectorize_loops)) + if (args.getLastArg(clang::options::OPT_vectorize_loops)) opts.VectorizeLoop = 1; - if (args.getLastArg(clang::driver::options::OPT_vectorize_slp)) + if (args.getLastArg(clang::options::OPT_vectorize_slp)) opts.VectorizeSLP = 1; - if (args.hasFlag(clang::driver::options::OPT_floop_versioning, - clang::driver::options::OPT_fno_loop_versioning, false)) + if (args.hasFlag(clang::options::OPT_floop_versioning, + clang::options::OPT_fno_loop_versioning, false)) opts.LoopVersioning = 1; - opts.UnrollLoops = args.hasFlag(clang::driver::options::OPT_funroll_loops, - clang::driver::options::OPT_fno_unroll_loops, + opts.UnrollLoops = args.hasFlag(clang::options::OPT_funroll_loops, + clang::options::OPT_fno_unroll_loops, (opts.OptimizationLevel > 1)); opts.AliasAnalysis = opts.OptimizationLevel > 0; // -mframe-pointer=none/non-leaf/reserved/all option. if (const llvm::opt::Arg *a = - args.getLastArg(clang::driver::options::OPT_mframe_pointer_EQ)) { + args.getLastArg(clang::options::OPT_mframe_pointer_EQ)) { std::optional<llvm::FramePointerKind> val = llvm::StringSwitch<std::optional<llvm::FramePointerKind>>(a->getValue()) .Case("none", llvm::FramePointerKind::None) .Case("non-leaf", llvm::FramePointerKind::NonLeaf) + .Case("non-leaf-no-reserve", + llvm::FramePointerKind::NonLeafNoReserve) .Case("reserved", llvm::FramePointerKind::Reserved) .Case("all", llvm::FramePointerKind::All) .Default(std::nullopt); @@ -322,24 +322,22 @@ static void parseCodeGenArgs(Fortran::frontend::CodeGenOptions &opts, opts.setFramePointer(val.value()); } - for (auto *a : args.filtered(clang::driver::options::OPT_fpass_plugin_EQ)) + for (auto *a : args.filtered(clang::options::OPT_fpass_plugin_EQ)) opts.LLVMPassPlugins.push_back(a->getValue()); - opts.Reciprocals = clang::driver::tools::parseMRecipOption(diags, args); + opts.Reciprocals = clang::parseMRecipOption(diags, args); - opts.PreferVectorWidth = - clang::driver::tools::parseMPreferVectorWidthOption(diags, args); + opts.PreferVectorWidth = clang::parseMPreferVectorWidthOption(diags, args); // -fembed-offload-object option - for (auto *a : - args.filtered(clang::driver::options::OPT_fembed_offload_object_EQ)) + for (auto *a : args.filtered(clang::options::OPT_fembed_offload_object_EQ)) opts.OffloadObjects.push_back(a->getValue()); - if (args.hasArg(clang::driver::options::OPT_finstrument_functions)) + if (args.hasArg(clang::options::OPT_finstrument_functions)) opts.InstrumentFunctions = 1; - if (const llvm::opt::Arg *a = args.getLastArg( - clang::driver::options::OPT_mcode_object_version_EQ)) { + if (const llvm::opt::Arg *a = + args.getLastArg(clang::options::OPT_mcode_object_version_EQ)) { llvm::StringRef s = a->getValue(); if (s == "6") opts.CodeObjectVersion = llvm::CodeObjectVersionKind::COV_6; @@ -353,36 +351,36 @@ static void parseCodeGenArgs(Fortran::frontend::CodeGenOptions &opts, // -f[no-]save-optimization-record[=<format>] if (const llvm::opt::Arg *a = - args.getLastArg(clang::driver::options::OPT_opt_record_file)) + args.getLastArg(clang::options::OPT_opt_record_file)) opts.OptRecordFile = a->getValue(); // Optimization file format. Defaults to yaml if (const llvm::opt::Arg *a = - args.getLastArg(clang::driver::options::OPT_opt_record_format)) + args.getLastArg(clang::options::OPT_opt_record_format)) opts.OptRecordFormat = a->getValue(); // Specifies, using a regex, which successful optimization passes(middle and // backend), to include in the final optimization record file generated. If // not provided -fsave-optimization-record will include all passes. if (const llvm::opt::Arg *a = - args.getLastArg(clang::driver::options::OPT_opt_record_passes)) + args.getLastArg(clang::options::OPT_opt_record_passes)) opts.OptRecordPasses = a->getValue(); // Create OptRemark that allows printing of all successful optimization // passes applied. opts.OptimizationRemark = - parseOptimizationRemark(diags, args, clang::driver::options::OPT_Rpass_EQ, + parseOptimizationRemark(diags, args, clang::options::OPT_Rpass_EQ, /*remarkOptName=*/"pass"); // Create OptRemark that allows all missed optimization passes to be printed. - opts.OptimizationRemarkMissed = parseOptimizationRemark( - diags, args, clang::driver::options::OPT_Rpass_missed_EQ, - /*remarkOptName=*/"pass-missed"); + opts.OptimizationRemarkMissed = + parseOptimizationRemark(diags, args, clang::options::OPT_Rpass_missed_EQ, + /*remarkOptName=*/"pass-missed"); // Create OptRemark that allows all optimization decisions made by LLVM // to be printed. opts.OptimizationRemarkAnalysis = parseOptimizationRemark( - diags, args, clang::driver::options::OPT_Rpass_analysis_EQ, + diags, args, clang::options::OPT_Rpass_analysis_EQ, /*remarkOptName=*/"pass-analysis"); if (opts.getDebugInfo() == llvm::codegenoptions::NoDebugInfo) { @@ -400,23 +398,22 @@ static void parseCodeGenArgs(Fortran::frontend::CodeGenOptions &opts, opts.setDebugInfo(llvm::codegenoptions::LocTrackingOnly); } - if (auto *a = args.getLastArg(clang::driver::options::OPT_save_temps_EQ)) + if (auto *a = args.getLastArg(clang::options::OPT_save_temps_EQ)) opts.SaveTempsDir = a->getValue(); // -record-command-line option. if (const llvm::opt::Arg *a = - args.getLastArg(clang::driver::options::OPT_record_command_line)) { + args.getLastArg(clang::options::OPT_record_command_line)) { opts.RecordCommandLine = a->getValue(); } // -mlink-builtin-bitcode - for (auto *a : - args.filtered(clang::driver::options::OPT_mlink_builtin_bitcode)) + for (auto *a : args.filtered(clang::options::OPT_mlink_builtin_bitcode)) opts.BuiltinBCLibs.push_back(a->getValue()); // -mrelocation-model option. if (const llvm::opt::Arg *a = - args.getLastArg(clang::driver::options::OPT_mrelocation_model)) { + args.getLastArg(clang::options::OPT_mrelocation_model)) { llvm::StringRef modelName = a->getValue(); auto relocModel = llvm::StringSwitch<std::optional<llvm::Reloc::Model>>(modelName) @@ -435,31 +432,30 @@ static void parseCodeGenArgs(Fortran::frontend::CodeGenOptions &opts, } // -pic-level and -pic-is-pie option. - if (int picLevel = getLastArgIntValue( - args, clang::driver::options::OPT_pic_level, 0, diags)) { + if (int picLevel = + getLastArgIntValue(args, clang::options::OPT_pic_level, 0, diags)) { if (picLevel > 2) diags.Report(clang::diag::err_drv_invalid_value) - << args.getLastArg(clang::driver::options::OPT_pic_level) - ->getAsString(args) + << args.getLastArg(clang::options::OPT_pic_level)->getAsString(args) << picLevel; opts.PICLevel = picLevel; - if (args.hasArg(clang::driver::options::OPT_pic_is_pie)) + if (args.hasArg(clang::options::OPT_pic_is_pie)) opts.IsPIE = 1; } - if (args.hasArg(clang::driver::options::OPT_fprofile_generate)) { + if (args.hasArg(clang::options::OPT_fprofile_generate)) { opts.setProfileInstr(llvm::driver::ProfileInstrKind::ProfileIRInstr); } - if (auto A = args.getLastArg(clang::driver::options::OPT_fprofile_use_EQ)) { + if (auto A = args.getLastArg(clang::options::OPT_fprofile_use_EQ)) { opts.setProfileUse(llvm::driver::ProfileInstrKind::ProfileIRInstr); opts.ProfileInstrumentUsePath = A->getValue(); } // -mcmodel option. if (const llvm::opt::Arg *a = - args.getLastArg(clang::driver::options::OPT_mcmodel_EQ)) { + args.getLastArg(clang::options::OPT_mcmodel_EQ)) { llvm::StringRef modelName = a->getValue(); std::optional<llvm::CodeModel::Model> codeModel = getCodeModel(modelName); @@ -470,8 +466,8 @@ static void parseCodeGenArgs(Fortran::frontend::CodeGenOptions &opts, << a->getAsString(args) << modelName; } - if (const llvm::opt::Arg *arg = args.getLastArg( - clang::driver::options::OPT_mlarge_data_threshold_EQ)) { + if (const llvm::opt::Arg *arg = + args.getLastArg(clang::options::OPT_mlarge_data_threshold_EQ)) { uint64_t LDT; if (llvm::StringRef(arg->getValue()).getAsInteger(/*Radix=*/10, LDT)) { diags.Report(clang::diag::err_drv_invalid_value) @@ -481,15 +477,15 @@ static void parseCodeGenArgs(Fortran::frontend::CodeGenOptions &opts, } // This option is compatible with -f[no-]underscoring in gfortran. - if (args.hasFlag(clang::driver::options::OPT_fno_underscoring, - clang::driver::options::OPT_funderscoring, false)) { + if (args.hasFlag(clang::options::OPT_fno_underscoring, + clang::options::OPT_funderscoring, false)) { opts.Underscoring = 0; } parseDoConcurrentMapping(opts, args, diags); if (const llvm::opt::Arg *arg = - args.getLastArg(clang::driver::options::OPT_complex_range_EQ)) { + args.getLastArg(clang::options::OPT_complex_range_EQ)) { llvm::StringRef argValue = llvm::StringRef(arg->getValue()); if (argValue == "full") { opts.setComplexRange(CodeGenOptions::ComplexRangeKind::CX_Full); @@ -510,46 +506,42 @@ static void parseCodeGenArgs(Fortran::frontend::CodeGenOptions &opts, /// \param [in] opts The target options instance to update /// \param [in] args The list of input arguments (from the compiler invocation) static void parseTargetArgs(TargetOptions &opts, llvm::opt::ArgList &args) { - if (const llvm::opt::Arg *a = - args.getLastArg(clang::driver::options::OPT_triple)) + if (const llvm::opt::Arg *a = args.getLastArg(clang::options::OPT_triple)) opts.triple = a->getValue(); - opts.atomicIgnoreDenormalMode = args.hasFlag( - clang::driver::options::OPT_fatomic_ignore_denormal_mode, - clang::driver::options::OPT_fno_atomic_ignore_denormal_mode, false); - opts.atomicFineGrainedMemory = args.hasFlag( - clang::driver::options::OPT_fatomic_fine_grained_memory, - clang::driver::options::OPT_fno_atomic_fine_grained_memory, false); + opts.atomicIgnoreDenormalMode = + args.hasFlag(clang::options::OPT_fatomic_ignore_denormal_mode, + clang::options::OPT_fno_atomic_ignore_denormal_mode, false); + opts.atomicFineGrainedMemory = + args.hasFlag(clang::options::OPT_fatomic_fine_grained_memory, + clang::options::OPT_fno_atomic_fine_grained_memory, false); opts.atomicRemoteMemory = - args.hasFlag(clang::driver::options::OPT_fatomic_remote_memory, - clang::driver::options::OPT_fno_atomic_remote_memory, false); + args.hasFlag(clang::options::OPT_fatomic_remote_memory, + clang::options::OPT_fno_atomic_remote_memory, false); - if (const llvm::opt::Arg *a = - args.getLastArg(clang::driver::options::OPT_target_cpu)) + if (const llvm::opt::Arg *a = args.getLastArg(clang::options::OPT_target_cpu)) opts.cpu = a->getValue(); - if (const llvm::opt::Arg *a = - args.getLastArg(clang::driver::options::OPT_tune_cpu)) + if (const llvm::opt::Arg *a = args.getLastArg(clang::options::OPT_tune_cpu)) opts.cpuToTuneFor = a->getValue(); for (const llvm::opt::Arg *currentArg : - args.filtered(clang::driver::options::OPT_target_feature)) + args.filtered(clang::options::OPT_target_feature)) opts.featuresAsWritten.emplace_back(currentArg->getValue()); - if (args.hasArg(clang::driver::options::OPT_fdisable_real_10)) + if (args.hasArg(clang::options::OPT_fdisable_real_10)) opts.disabledRealKinds.push_back(10); - if (args.hasArg(clang::driver::options::OPT_fdisable_real_3)) + if (args.hasArg(clang::options::OPT_fdisable_real_3)) opts.disabledRealKinds.push_back(3); - if (args.hasArg(clang::driver::options::OPT_fdisable_integer_2)) + if (args.hasArg(clang::options::OPT_fdisable_integer_2)) opts.disabledIntegerKinds.push_back(2); - if (args.hasArg(clang::driver::options::OPT_fdisable_integer_16)) + if (args.hasArg(clang::options::OPT_fdisable_integer_16)) opts.disabledIntegerKinds.push_back(16); - if (const llvm::opt::Arg *a = - args.getLastArg(clang::driver::options::OPT_mabi_EQ)) { + if (const llvm::opt::Arg *a = args.getLastArg(clang::options::OPT_mabi_EQ)) { opts.abi = a->getValue(); llvm::StringRef V = a->getValue(); if (V == "vec-extabi") { @@ -559,9 +551,8 @@ static void parseTargetArgs(TargetOptions &opts, llvm::opt::ArgList &args) { } } - opts.asmVerbose = - args.hasFlag(clang::driver::options::OPT_fverbose_asm, - clang::driver::options::OPT_fno_verbose_asm, false); + opts.asmVerbose = args.hasFlag(clang::options::OPT_fverbose_asm, + clang::options::OPT_fno_verbose_asm, false); } // Tweak the frontend configuration based on the frontend action static void setUpFrontendBasedOnAction(FrontendOptions &opts) { @@ -594,108 +585,114 @@ static bool parseFrontendArgs(FrontendOptions &opts, llvm::opt::ArgList &args, // Treat multiple action options as an invocation error. Note that `clang // -cc1` does accept multiple action options, but will only consider the // rightmost one. - if (args.hasMultipleArgs(clang::driver::options::OPT_Action_Group)) { - const unsigned diagID = diags.getCustomDiagID( - clang::DiagnosticsEngine::Error, "Only one action option is allowed"); - diags.Report(diagID); + if (args.hasMultipleArgs(clang::options::OPT_Action_Group)) { + llvm::SmallString<32> buf; + llvm::raw_svector_ostream os(buf); + for (const llvm::opt::Arg *arg : + args.filtered(clang::options::OPT_Action_Group)) { + if (buf.size()) + os << ", "; + os << "'" << arg->getSpelling() << "'"; + } + diags.Report(clang::diag::err_drv_too_many_actions) << buf; return false; } // Identify the action (i.e. opts.ProgramAction) if (const llvm::opt::Arg *a = - args.getLastArg(clang::driver::options::OPT_Action_Group)) { + args.getLastArg(clang::options::OPT_Action_Group)) { switch (a->getOption().getID()) { default: { llvm_unreachable("Invalid option in group!"); } - case clang::driver::options::OPT_test_io: + case clang::options::OPT_test_io: opts.programAction = InputOutputTest; break; - case clang::driver::options::OPT_E: + case clang::options::OPT_E: opts.programAction = PrintPreprocessedInput; break; - case clang::driver::options::OPT_fsyntax_only: + case clang::options::OPT_fsyntax_only: opts.programAction = ParseSyntaxOnly; break; - case clang::driver::options::OPT_emit_fir: + case clang::options::OPT_emit_fir: opts.programAction = EmitFIR; break; - case clang::driver::options::OPT_emit_hlfir: + case clang::options::OPT_emit_hlfir: opts.programAction = EmitHLFIR; break; - case clang::driver::options::OPT_emit_llvm: + case clang::options::OPT_emit_llvm: opts.programAction = EmitLLVM; break; - case clang::driver::options::OPT_emit_llvm_bc: + case clang::options::OPT_emit_llvm_bc: opts.programAction = EmitLLVMBitcode; break; - case clang::driver::options::OPT_emit_obj: + case clang::options::OPT_emit_obj: opts.programAction = EmitObj; break; - case clang::driver::options::OPT_S: + case clang::options::OPT_S: opts.programAction = EmitAssembly; break; - case clang::driver::options::OPT_fdebug_unparse: + case clang::options::OPT_fdebug_unparse: opts.programAction = DebugUnparse; break; - case clang::driver::options::OPT_fdebug_unparse_no_sema: + case clang::options::OPT_fdebug_unparse_no_sema: opts.programAction = DebugUnparseNoSema; break; - case clang::driver::options::OPT_fdebug_unparse_with_symbols: + case clang::options::OPT_fdebug_unparse_with_symbols: opts.programAction = DebugUnparseWithSymbols; break; - case clang::driver::options::OPT_fdebug_unparse_with_modules: + case clang::options::OPT_fdebug_unparse_with_modules: opts.programAction = DebugUnparseWithModules; break; - case clang::driver::options::OPT_fdebug_dump_symbols: + case clang::options::OPT_fdebug_dump_symbols: opts.programAction = DebugDumpSymbols; break; - case clang::driver::options::OPT_fdebug_dump_parse_tree: + case clang::options::OPT_fdebug_dump_parse_tree: opts.programAction = DebugDumpParseTree; break; - case clang::driver::options::OPT_fdebug_dump_pft: + case clang::options::OPT_fdebug_dump_pft: opts.programAction = DebugDumpPFT; break; - case clang::driver::options::OPT_fdebug_dump_all: + case clang::options::OPT_fdebug_dump_all: opts.programAction = DebugDumpAll; break; - case clang::driver::options::OPT_fdebug_dump_parse_tree_no_sema: + case clang::options::OPT_fdebug_dump_parse_tree_no_sema: opts.programAction = DebugDumpParseTreeNoSema; break; - case clang::driver::options::OPT_fdebug_dump_provenance: + case clang::options::OPT_fdebug_dump_provenance: opts.programAction = DebugDumpProvenance; break; - case clang::driver::options::OPT_fdebug_dump_parsing_log: + case clang::options::OPT_fdebug_dump_parsing_log: opts.programAction = DebugDumpParsingLog; break; - case clang::driver::options::OPT_fdebug_measure_parse_tree: + case clang::options::OPT_fdebug_measure_parse_tree: opts.programAction = DebugMeasureParseTree; break; - case clang::driver::options::OPT_fdebug_pre_fir_tree: + case clang::options::OPT_fdebug_pre_fir_tree: opts.programAction = DebugPreFIRTree; break; - case clang::driver::options::OPT_fget_symbols_sources: + case clang::options::OPT_fget_symbols_sources: opts.programAction = GetSymbolsSources; break; - case clang::driver::options::OPT_fget_definition: + case clang::options::OPT_fget_definition: opts.programAction = GetDefinition; break; - case clang::driver::options::OPT_init_only: + case clang::options::OPT_init_only: opts.programAction = InitOnly; break; // TODO: - // case clang::driver::options::OPT_emit_llvm: - // case clang::driver::options::OPT_emit_llvm_only: - // case clang::driver::options::OPT_emit_codegen_only: - // case clang::driver::options::OPT_emit_module: + // case clang::options::OPT_emit_llvm: + // case clang::options::OPT_emit_llvm_only: + // case clang::options::OPT_emit_codegen_only: + // case clang::options::OPT_emit_module: // (...) } // Parse the values provided with `-fget-definition` (there should be 3 // integers) if (llvm::opt::OptSpecifier(a->getOption().getID()) == - clang::driver::options::OPT_fget_definition) { + clang::options::OPT_fget_definition) { unsigned optVals[3] = {0, 0, 0}; for (unsigned i = 0; i < 3; i++) { @@ -715,27 +712,25 @@ static bool parseFrontendArgs(FrontendOptions &opts, llvm::opt::ArgList &args, } // Parsing -load <dsopath> option and storing shared object path - if (llvm::opt::Arg *a = args.getLastArg(clang::driver::options::OPT_load)) { + if (llvm::opt::Arg *a = args.getLastArg(clang::options::OPT_load)) { opts.plugins.push_back(a->getValue()); } // Parsing -plugin <name> option and storing plugin name and setting action - if (const llvm::opt::Arg *a = - args.getLastArg(clang::driver::options::OPT_plugin)) { + if (const llvm::opt::Arg *a = args.getLastArg(clang::options::OPT_plugin)) { opts.programAction = PluginAction; opts.actionName = a->getValue(); } - opts.outputFile = args.getLastArgValue(clang::driver::options::OPT_o); - opts.showHelp = args.hasArg(clang::driver::options::OPT_help); - opts.showVersion = args.hasArg(clang::driver::options::OPT_version); + opts.outputFile = args.getLastArgValue(clang::options::OPT_o); + opts.showHelp = args.hasArg(clang::options::OPT_help); + opts.showVersion = args.hasArg(clang::options::OPT_version); opts.printSupportedCPUs = - args.hasArg(clang::driver::options::OPT_print_supported_cpus); + args.hasArg(clang::options::OPT_print_supported_cpus); // Get the input kind (from the value passed via `-x`) InputKind dashX(Language::Unknown); - if (const llvm::opt::Arg *a = - args.getLastArg(clang::driver::options::OPT_x)) { + if (const llvm::opt::Arg *a = args.getLastArg(clang::options::OPT_x)) { llvm::StringRef xValue = a->getValue(); // Principal languages. dashX = llvm::StringSwitch<InputKind>(xValue) @@ -762,7 +757,7 @@ static bool parseFrontendArgs(FrontendOptions &opts, llvm::opt::ArgList &args, // Collect the input files and save them in our instance of FrontendOptions. std::vector<std::string> inputs = - args.getAllArgValues(clang::driver::options::OPT_INPUT); + args.getAllArgValues(clang::options::OPT_INPUT); opts.inputs.clear(); if (inputs.empty()) // '-' is the default input if none is given. @@ -782,18 +777,16 @@ static bool parseFrontendArgs(FrontendOptions &opts, llvm::opt::ArgList &args, } // Set fortranForm based on options -ffree-form and -ffixed-form. - if (const auto *arg = - args.getLastArg(clang::driver::options::OPT_ffixed_form, - clang::driver::options::OPT_ffree_form)) { - opts.fortranForm = - arg->getOption().matches(clang::driver::options::OPT_ffixed_form) - ? FortranForm::FixedForm - : FortranForm::FreeForm; + if (const auto *arg = args.getLastArg(clang::options::OPT_ffixed_form, + clang::options::OPT_ffree_form)) { + opts.fortranForm = arg->getOption().matches(clang::options::OPT_ffixed_form) + ? FortranForm::FixedForm + : FortranForm::FreeForm; } // Set fixedFormColumns based on -ffixed-line-length=<value> if (const auto *arg = - args.getLastArg(clang::driver::options::OPT_ffixed_line_length_EQ)) { + args.getLastArg(clang::options::OPT_ffixed_line_length_EQ)) { llvm::StringRef argValue = llvm::StringRef(arg->getValue()); std::int64_t columns = -1; if (argValue == "none") { @@ -815,8 +808,7 @@ static bool parseFrontendArgs(FrontendOptions &opts, llvm::opt::ArgList &args, } // Set conversion based on -fconvert=<value> - if (const auto *arg = - args.getLastArg(clang::driver::options::OPT_fconvert_EQ)) { + if (const auto *arg = args.getLastArg(clang::options::OPT_fconvert_EQ)) { const char *argValue = arg->getValue(); if (auto convert = parseConvertArg(argValue)) opts.envDefaults.push_back({"FORT_CONVERT", *convert}); @@ -826,59 +818,55 @@ static bool parseFrontendArgs(FrontendOptions &opts, llvm::opt::ArgList &args, } // -f{no-}implicit-none - opts.features.Enable( - Fortran::common::LanguageFeature::ImplicitNoneTypeAlways, - args.hasFlag(clang::driver::options::OPT_fimplicit_none, - clang::driver::options::OPT_fno_implicit_none, false)); + opts.features.Enable(Fortran::common::LanguageFeature::ImplicitNoneTypeAlways, + args.hasFlag(clang::options::OPT_fimplicit_none, + clang::options::OPT_fno_implicit_none, + false)); // -f{no-}implicit-none-ext - opts.features.Enable( - Fortran::common::LanguageFeature::ImplicitNoneExternal, - args.hasFlag(clang::driver::options::OPT_fimplicit_none_ext, - clang::driver::options::OPT_fno_implicit_none_ext, false)); + opts.features.Enable(Fortran::common::LanguageFeature::ImplicitNoneExternal, + args.hasFlag(clang::options::OPT_fimplicit_none_ext, + clang::options::OPT_fno_implicit_none_ext, + false)); // -f{no-}backslash opts.features.Enable(Fortran::common::LanguageFeature::BackslashEscapes, - args.hasFlag(clang::driver::options::OPT_fbackslash, - clang::driver::options::OPT_fno_backslash, - false)); + args.hasFlag(clang::options::OPT_fbackslash, + clang::options::OPT_fno_backslash, false)); // -f{no-}logical-abbreviations opts.features.Enable( Fortran::common::LanguageFeature::LogicalAbbreviations, - args.hasFlag(clang::driver::options::OPT_flogical_abbreviations, - clang::driver::options::OPT_fno_logical_abbreviations, - false)); + args.hasFlag(clang::options::OPT_flogical_abbreviations, + clang::options::OPT_fno_logical_abbreviations, false)); // -f{no-}unsigned opts.features.Enable(Fortran::common::LanguageFeature::Unsigned, - args.hasFlag(clang::driver::options::OPT_funsigned, - clang::driver::options::OPT_fno_unsigned, - false)); + args.hasFlag(clang::options::OPT_funsigned, + clang::options::OPT_fno_unsigned, false)); // -f{no-}xor-operator - opts.features.Enable( - Fortran::common::LanguageFeature::XOROperator, - args.hasFlag(clang::driver::options::OPT_fxor_operator, - clang::driver::options::OPT_fno_xor_operator, false)); + opts.features.Enable(Fortran::common::LanguageFeature::XOROperator, + args.hasFlag(clang::options::OPT_fxor_operator, + clang::options::OPT_fno_xor_operator, + false)); // -fno-automatic - if (args.hasArg(clang::driver::options::OPT_fno_automatic)) { + if (args.hasArg(clang::options::OPT_fno_automatic)) { opts.features.Enable(Fortran::common::LanguageFeature::DefaultSave); } // -f{no}-save-main-program - opts.features.Enable( - Fortran::common::LanguageFeature::SaveMainProgram, - args.hasFlag(clang::driver::options::OPT_fsave_main_program, - clang::driver::options::OPT_fno_save_main_program, false)); + opts.features.Enable(Fortran::common::LanguageFeature::SaveMainProgram, + args.hasFlag(clang::options::OPT_fsave_main_program, + clang::options::OPT_fno_save_main_program, + false)); - if (args.hasArg( - clang::driver::options::OPT_falternative_parameter_statement)) { + if (args.hasArg(clang::options::OPT_falternative_parameter_statement)) { opts.features.Enable(Fortran::common::LanguageFeature::OldStyleParameter); } if (const llvm::opt::Arg *arg = - args.getLastArg(clang::driver::options::OPT_finput_charset_EQ)) { + args.getLastArg(clang::options::OPT_finput_charset_EQ)) { llvm::StringRef argValue = arg->getValue(); if (argValue == "utf-8") { opts.encoding = Fortran::parser::Encoding::UTF_8; @@ -923,9 +911,9 @@ static std::string getOpenMPHeadersDir(const char *argv) { static void parsePreprocessorArgs(Fortran::frontend::PreprocessorOptions &opts, llvm::opt::ArgList &args) { // Add macros from the command line. - for (const auto *currentArg : args.filtered(clang::driver::options::OPT_D, - clang::driver::options::OPT_U)) { - if (currentArg->getOption().matches(clang::driver::options::OPT_D)) { + for (const auto *currentArg : + args.filtered(clang::options::OPT_D, clang::options::OPT_U)) { + if (currentArg->getOption().matches(clang::options::OPT_D)) { opts.addMacroDef(currentArg->getValue()); } else { opts.addMacroUndef(currentArg->getValue()); @@ -933,34 +921,33 @@ static void parsePreprocessorArgs(Fortran::frontend::PreprocessorOptions &opts, } // Add the ordered list of -I's. - for (const auto *currentArg : args.filtered(clang::driver::options::OPT_I)) + for (const auto *currentArg : args.filtered(clang::options::OPT_I)) opts.searchDirectoriesFromDashI.emplace_back(currentArg->getValue()); // Prepend the ordered list of -intrinsic-modules-path // to the default location to search. for (const auto *currentArg : - args.filtered(clang::driver::options::OPT_fintrinsic_modules_path)) + args.filtered(clang::options::OPT_fintrinsic_modules_path)) opts.searchDirectoriesFromIntrModPath.emplace_back(currentArg->getValue()); // -cpp/-nocpp - if (const auto *currentArg = args.getLastArg( - clang::driver::options::OPT_cpp, clang::driver::options::OPT_nocpp)) - opts.macrosFlag = - (currentArg->getOption().matches(clang::driver::options::OPT_cpp)) - ? PPMacrosFlag::Include - : PPMacrosFlag::Exclude; + if (const auto *currentArg = + args.getLastArg(clang::options::OPT_cpp, clang::options::OPT_nocpp)) + opts.macrosFlag = (currentArg->getOption().matches(clang::options::OPT_cpp)) + ? PPMacrosFlag::Include + : PPMacrosFlag::Exclude; // Enable -cpp based on -x unless explicitly disabled with -nocpp if (opts.macrosFlag != PPMacrosFlag::Exclude) - if (const auto *dashX = args.getLastArg(clang::driver::options::OPT_x)) + if (const auto *dashX = args.getLastArg(clang::options::OPT_x)) opts.macrosFlag = llvm::StringSwitch<PPMacrosFlag>(dashX->getValue()) .Case("f95-cpp-input", PPMacrosFlag::Include) .Default(opts.macrosFlag); - opts.noReformat = args.hasArg(clang::driver::options::OPT_fno_reformat); + opts.noReformat = args.hasArg(clang::options::OPT_fno_reformat); opts.preprocessIncludeLines = - args.hasArg(clang::driver::options::OPT_fpreprocess_include_lines); - opts.noLineDirectives = args.hasArg(clang::driver::options::OPT_P); - opts.showMacros = args.hasArg(clang::driver::options::OPT_dM); + args.hasArg(clang::options::OPT_fpreprocess_include_lines); + opts.noLineDirectives = args.hasArg(clang::options::OPT_P); + opts.showMacros = args.hasArg(clang::options::OPT_dM); } /// Parses all semantic related arguments and populates the variables @@ -971,7 +958,7 @@ static bool parseSemaArgs(CompilerInvocation &res, llvm::opt::ArgList &args, // -J/module-dir option std::vector<std::string> moduleDirList = - args.getAllArgValues(clang::driver::options::OPT_module_dir); + args.getAllArgValues(clang::options::OPT_module_dir); // User can only specify one -J/-module-dir directory, but may repeat // -J/-module-dir as long as the directory is the same each time. // https://gcc.gnu.org/onlinedocs/gfortran/Directory-Options.html @@ -990,25 +977,25 @@ static bool parseSemaArgs(CompilerInvocation &res, llvm::opt::ArgList &args, res.setModuleDir(moduleDirList[0]); // -fdebug-module-writer option - if (args.hasArg(clang::driver::options::OPT_fdebug_module_writer)) { + if (args.hasArg(clang::options::OPT_fdebug_module_writer)) { res.setDebugModuleDir(true); } // -fhermetic-module-files option - if (args.hasArg(clang::driver::options::OPT_fhermetic_module_files)) { + if (args.hasArg(clang::options::OPT_fhermetic_module_files)) { res.setHermeticModuleFileOutput(true); } // -module-suffix if (const auto *moduleSuffix = - args.getLastArg(clang::driver::options::OPT_module_suffix)) { + args.getLastArg(clang::options::OPT_module_suffix)) { res.setModuleFileSuffix(moduleSuffix->getValue()); } // -f{no-}analyzed-objects-for-unparse - res.setUseAnalyzedObjectsForUnparse(args.hasFlag( - clang::driver::options::OPT_fanalyzed_objects_for_unparse, - clang::driver::options::OPT_fno_analyzed_objects_for_unparse, true)); + res.setUseAnalyzedObjectsForUnparse( + args.hasFlag(clang::options::OPT_fanalyzed_objects_for_unparse, + clang::options::OPT_fno_analyzed_objects_for_unparse, true)); return diags.getNumErrors() == numErrorsBefore; } @@ -1025,7 +1012,7 @@ static bool parseDiagArgs(CompilerInvocation &res, llvm::opt::ArgList &args, // chosen to match clang's behavior. // -pedantic - if (args.hasArg(clang::driver::options::OPT_pedantic)) { + if (args.hasArg(clang::options::OPT_pedantic)) { features.WarnOnAllNonstandard(); features.WarnOnAllUsage(); res.setEnableConformanceChecks(); @@ -1035,9 +1022,8 @@ static bool parseDiagArgs(CompilerInvocation &res, llvm::opt::ArgList &args, // -Werror option // TODO: Currently throws a Diagnostic for anything other than -W<error>, // this has to change when other -W<opt>'s are supported. - if (args.hasArg(clang::driver::options::OPT_W_Joined)) { - const auto &wArgs = - args.getAllArgValues(clang::driver::options::OPT_W_Joined); + if (args.hasArg(clang::options::OPT_W_Joined)) { + const auto &wArgs = args.getAllArgValues(clang::options::OPT_W_Joined); for (const auto &wArg : wArgs) { if (wArg == "error") { res.setWarnAsErr(true); @@ -1054,7 +1040,7 @@ static bool parseDiagArgs(CompilerInvocation &res, llvm::opt::ArgList &args, } // -w - if (args.hasArg(clang::driver::options::OPT_w)) { + if (args.hasArg(clang::options::OPT_w)) { features.DisableAllWarnings(); res.setDisableWarnings(); } @@ -1074,7 +1060,7 @@ static bool parseDialectArgs(CompilerInvocation &res, llvm::opt::ArgList &args, unsigned numErrorsBefore = diags.getNumErrors(); // -fd-lines-as-code - if (args.hasArg(clang::driver::options::OPT_fd_lines_as_code)) { + if (args.hasArg(clang::options::OPT_fd_lines_as_code)) { if (res.getFrontendOpts().fortranForm == FortranForm::FreeForm) { const unsigned fdLinesAsWarning = diags.getCustomDiagID( clang::DiagnosticsEngine::Warning, @@ -1087,7 +1073,7 @@ static bool parseDialectArgs(CompilerInvocation &res, llvm::opt::ArgList &args, } // -fd-lines-as-comments - if (args.hasArg(clang::driver::options::OPT_fd_lines_as_comments)) { + if (args.hasArg(clang::options::OPT_fd_lines_as_comments)) { if (res.getFrontendOpts().fortranForm == FortranForm::FreeForm) { const unsigned fdLinesAsWarning = diags.getCustomDiagID( clang::DiagnosticsEngine::Warning, @@ -1100,18 +1086,18 @@ static bool parseDialectArgs(CompilerInvocation &res, llvm::opt::ArgList &args, } // -fdefault* family - if (args.hasArg(clang::driver::options::OPT_fdefault_real_8)) { + if (args.hasArg(clang::options::OPT_fdefault_real_8)) { res.getDefaultKinds().set_defaultRealKind(8); res.getDefaultKinds().set_doublePrecisionKind(16); } - if (args.hasArg(clang::driver::options::OPT_fdefault_integer_8)) { + if (args.hasArg(clang::options::OPT_fdefault_integer_8)) { res.getDefaultKinds().set_defaultIntegerKind(8); res.getDefaultKinds().set_subscriptIntegerKind(8); res.getDefaultKinds().set_sizeIntegerKind(8); res.getDefaultKinds().set_defaultLogicalKind(8); } - if (args.hasArg(clang::driver::options::OPT_fdefault_double_8)) { - if (!args.hasArg(clang::driver::options::OPT_fdefault_real_8)) { + if (args.hasArg(clang::options::OPT_fdefault_double_8)) { + if (!args.hasArg(clang::options::OPT_fdefault_real_8)) { // -fdefault-double-8 has to be used with -fdefault-real-8 // to be compatible with gfortran const unsigned diagID = diags.getCustomDiagID( @@ -1122,18 +1108,18 @@ static bool parseDialectArgs(CompilerInvocation &res, llvm::opt::ArgList &args, // https://gcc.gnu.org/onlinedocs/gfortran/Fortran-Dialect-Options.html res.getDefaultKinds().set_doublePrecisionKind(8); } - if (args.hasArg(clang::driver::options::OPT_flarge_sizes)) + if (args.hasArg(clang::options::OPT_flarge_sizes)) res.getDefaultKinds().set_sizeIntegerKind(8); // -x cuda - auto language = args.getLastArgValue(clang::driver::options::OPT_x); + auto language = args.getLastArgValue(clang::options::OPT_x); if (language == "cuda") { res.getFrontendOpts().features.Enable( Fortran::common::LanguageFeature::CUDA); } // -fopenacc - if (args.hasArg(clang::driver::options::OPT_fopenacc)) { + if (args.hasArg(clang::options::OPT_fopenacc)) { res.getFrontendOpts().features.Enable( Fortran::common::LanguageFeature::OpenACC); } @@ -1141,8 +1127,8 @@ static bool parseDialectArgs(CompilerInvocation &res, llvm::opt::ArgList &args, // -std=f2018 // TODO: Set proper options when more fortran standards // are supported. - if (args.hasArg(clang::driver::options::OPT_std_EQ)) { - auto standard = args.getLastArgValue(clang::driver::options::OPT_std_EQ); + if (args.hasArg(clang::options::OPT_std_EQ)) { + auto standard = args.getLastArgValue(clang::options::OPT_std_EQ); // We only allow f2018 as the given standard if (standard == "f2018") { res.setEnableConformanceChecks(); @@ -1155,7 +1141,7 @@ static bool parseDialectArgs(CompilerInvocation &res, llvm::opt::ArgList &args, } } // -fcoarray - if (args.hasArg(clang::driver::options::OPT_fcoarray)) { + if (args.hasArg(clang::options::OPT_fcoarray)) { res.getFrontendOpts().features.Enable( Fortran::common::LanguageFeature::Coarray); const unsigned diagID = @@ -1173,13 +1159,12 @@ static bool parseDialectArgs(CompilerInvocation &res, llvm::opt::ArgList &args, /// generated. static bool parseOpenMPArgs(CompilerInvocation &res, llvm::opt::ArgList &args, clang::DiagnosticsEngine &diags) { - llvm::opt::Arg *arg = args.getLastArg(clang::driver::options::OPT_fopenmp, - clang::driver::options::OPT_fno_openmp); - if (!arg || - arg->getOption().matches(clang::driver::options::OPT_fno_openmp)) { - bool isSimdSpecified = args.hasFlag( - clang::driver::options::OPT_fopenmp_simd, - clang::driver::options::OPT_fno_openmp_simd, /*Default=*/false); + llvm::opt::Arg *arg = args.getLastArg(clang::options::OPT_fopenmp, + clang::options::OPT_fno_openmp); + if (!arg || arg->getOption().matches(clang::options::OPT_fno_openmp)) { + bool isSimdSpecified = + args.hasFlag(clang::options::OPT_fopenmp_simd, + clang::options::OPT_fno_openmp_simd, /*Default=*/false); if (!isSimdSpecified) return true; res.getLangOpts().OpenMPSimd = 1; @@ -1194,8 +1179,7 @@ static bool parseOpenMPArgs(CompilerInvocation &res, llvm::opt::ArgList &args, res.getLangOpts().OpenMPVersion = newestFullySupported; res.getFrontendOpts().features.Enable( Fortran::common::LanguageFeature::OpenMP); - if (auto *arg = - args.getLastArg(clang::driver::options::OPT_fopenmp_version_EQ)) { + if (auto *arg = args.getLastArg(clang::options::OPT_fopenmp_version_EQ)) { llvm::ArrayRef<unsigned> ompVersions = llvm::omp::getOpenMPVersions(); unsigned oldVersions[] = {11, 20, 25, 30}; unsigned version = 0; @@ -1248,16 +1232,16 @@ static bool parseOpenMPArgs(CompilerInvocation &res, llvm::opt::ArgList &args, } } - if (args.hasArg(clang::driver::options::OPT_fopenmp_force_usm)) { + if (args.hasArg(clang::options::OPT_fopenmp_force_usm)) { res.getLangOpts().OpenMPForceUSM = 1; } - if (args.hasArg(clang::driver::options::OPT_fopenmp_is_target_device)) { + if (args.hasArg(clang::options::OPT_fopenmp_is_target_device)) { res.getLangOpts().OpenMPIsTargetDevice = 1; // Get OpenMP host file path if any and report if a non existent file is // found - if (auto *arg = args.getLastArg( - clang::driver::options::OPT_fopenmp_host_ir_file_path)) { + if (auto *arg = + args.getLastArg(clang::options::OPT_fopenmp_host_ir_file_path)) { res.getLangOpts().OMPHostIRFile = arg->getValue(); if (!llvm::sys::fs::exists(res.getLangOpts().OMPHostIRFile)) diags.Report(clang::diag::err_omp_host_ir_file_not_found) @@ -1265,37 +1249,34 @@ static bool parseOpenMPArgs(CompilerInvocation &res, llvm::opt::ArgList &args, } if (args.hasFlag( - clang::driver::options::OPT_fopenmp_assume_teams_oversubscription, - clang::driver::options:: - OPT_fno_openmp_assume_teams_oversubscription, + clang::options::OPT_fopenmp_assume_teams_oversubscription, + clang::options::OPT_fno_openmp_assume_teams_oversubscription, /*Default=*/false)) res.getLangOpts().OpenMPTeamSubscription = true; - if (args.hasArg(clang::driver::options::OPT_fopenmp_assume_no_thread_state)) + if (args.hasArg(clang::options::OPT_fopenmp_assume_no_thread_state)) res.getLangOpts().OpenMPNoThreadState = 1; - if (args.hasArg( - clang::driver::options::OPT_fopenmp_assume_no_nested_parallelism)) + if (args.hasArg(clang::options::OPT_fopenmp_assume_no_nested_parallelism)) res.getLangOpts().OpenMPNoNestedParallelism = 1; if (args.hasFlag( - clang::driver::options::OPT_fopenmp_assume_threads_oversubscription, - clang::driver::options:: - OPT_fno_openmp_assume_threads_oversubscription, + clang::options::OPT_fopenmp_assume_threads_oversubscription, + clang::options::OPT_fno_openmp_assume_threads_oversubscription, /*Default=*/false)) res.getLangOpts().OpenMPThreadSubscription = true; - if ((args.hasArg(clang::driver::options::OPT_fopenmp_target_debug) || - args.hasArg(clang::driver::options::OPT_fopenmp_target_debug_EQ))) { - res.getLangOpts().OpenMPTargetDebug = getLastArgIntValue( - args, clang::driver::options::OPT_fopenmp_target_debug_EQ, - res.getLangOpts().OpenMPTargetDebug, diags); + if ((args.hasArg(clang::options::OPT_fopenmp_target_debug) || + args.hasArg(clang::options::OPT_fopenmp_target_debug_EQ))) { + res.getLangOpts().OpenMPTargetDebug = + getLastArgIntValue(args, clang::options::OPT_fopenmp_target_debug_EQ, + res.getLangOpts().OpenMPTargetDebug, diags); if (!res.getLangOpts().OpenMPTargetDebug && - args.hasArg(clang::driver::options::OPT_fopenmp_target_debug)) + args.hasArg(clang::options::OPT_fopenmp_target_debug)) res.getLangOpts().OpenMPTargetDebug = 1; } - if (args.hasArg(clang::driver::options::OPT_no_offloadlib)) + if (args.hasArg(clang::options::OPT_no_offloadlib)) res.getLangOpts().NoGPULib = 1; } if (llvm::Triple(res.getTargetOpts().triple).isGPU()) { @@ -1311,8 +1292,7 @@ static bool parseOpenMPArgs(CompilerInvocation &res, llvm::opt::ArgList &args, } // Get the OpenMP target triples if any. - if (auto *arg = - args.getLastArg(clang::driver::options::OPT_offload_targets_EQ)) { + if (auto *arg = args.getLastArg(clang::options::OPT_offload_targets_EQ)) { enum ArchPtrSize { Arch16Bit, Arch32Bit, Arch64Bit }; auto getArchPtrSize = [](const llvm::Triple &triple) { if (triple.isArch16Bit()) @@ -1355,7 +1335,7 @@ static bool parseIntegerOverflowArgs(CompilerInvocation &invoc, clang::DiagnosticsEngine &diags) { Fortran::common::LangOptions &opts = invoc.getLangOpts(); - if (args.getLastArg(clang::driver::options::OPT_fwrapv)) + if (args.getLastArg(clang::options::OPT_fwrapv)) opts.setSignedOverflowBehavior(Fortran::common::LangOptions::SOB_Defined); return true; @@ -1374,7 +1354,7 @@ static bool parseFloatingPointArgs(CompilerInvocation &invoc, Fortran::common::LangOptions &opts = invoc.getLangOpts(); if (const llvm::opt::Arg *a = - args.getLastArg(clang::driver::options::OPT_ffp_contract)) { + args.getLastArg(clang::options::OPT_ffp_contract)) { const llvm::StringRef val = a->getValue(); enum Fortran::common::LangOptions::FPModeKind fpContractMode; @@ -1391,42 +1371,49 @@ static bool parseFloatingPointArgs(CompilerInvocation &invoc, opts.setFPContractMode(fpContractMode); } - if (args.getLastArg(clang::driver::options::OPT_menable_no_infs)) { + if (args.getLastArg(clang::options::OPT_menable_no_infs)) { opts.NoHonorInfs = true; } - if (args.getLastArg(clang::driver::options::OPT_menable_no_nans)) { + if (args.getLastArg(clang::options::OPT_menable_no_nans)) { opts.NoHonorNaNs = true; } - if (args.getLastArg(clang::driver::options::OPT_fapprox_func)) { + if (args.getLastArg(clang::options::OPT_fapprox_func)) { opts.ApproxFunc = true; } - if (args.getLastArg(clang::driver::options::OPT_fno_signed_zeros)) { + if (args.getLastArg(clang::options::OPT_fno_signed_zeros)) { opts.NoSignedZeros = true; } - if (args.getLastArg(clang::driver::options::OPT_mreassociate)) { + if (args.getLastArg(clang::options::OPT_mreassociate)) { opts.AssociativeMath = true; } - if (args.getLastArg(clang::driver::options::OPT_freciprocal_math)) { + if (args.getLastArg(clang::options::OPT_freciprocal_math)) { opts.ReciprocalMath = true; } - if (args.getLastArg(clang::driver::options::OPT_ffast_math)) { + if (args.getLastArg(clang::options::OPT_ffast_math)) { opts.NoHonorInfs = true; opts.NoHonorNaNs = true; opts.AssociativeMath = true; opts.ReciprocalMath = true; opts.ApproxFunc = true; opts.NoSignedZeros = true; + opts.FastRealMod = true; opts.setFPContractMode(Fortran::common::LangOptions::FPM_Fast); } - if (args.hasArg(clang::driver::options::OPT_fno_fast_real_mod)) - opts.NoFastRealMod = true; + if (llvm::opt::Arg *arg = + args.getLastArg(clang::options::OPT_ffast_real_mod, + clang::options::OPT_fno_fast_real_mod)) { + if (arg->getOption().matches(clang::options::OPT_ffast_real_mod)) + opts.FastRealMod = true; + if (arg->getOption().matches(clang::options::OPT_fno_fast_real_mod)) + opts.FastRealMod = false; + } return true; } @@ -1440,10 +1427,8 @@ static bool parseFloatingPointArgs(CompilerInvocation &invoc, /// \param [out] diags DiagnosticsEngine to report erros with static bool parseVScaleArgs(CompilerInvocation &invoc, llvm::opt::ArgList &args, clang::DiagnosticsEngine &diags) { - const auto *vscaleMin = - args.getLastArg(clang::driver::options::OPT_mvscale_min_EQ); - const auto *vscaleMax = - args.getLastArg(clang::driver::options::OPT_mvscale_max_EQ); + const auto *vscaleMin = args.getLastArg(clang::options::OPT_mvscale_min_EQ); + const auto *vscaleMax = args.getLastArg(clang::options::OPT_mvscale_max_EQ); if (!vscaleMin && !vscaleMax) return true; @@ -1491,8 +1476,7 @@ static bool parseLinkerOptionsArgs(CompilerInvocation &invoc, // TODO: support --dependent-lib on other platforms when MLIR supports // !llvm.dependent.lib - if (args.hasArg(clang::driver::options::OPT_dependent_lib) && - !triple.isOSWindows()) { + if (args.hasArg(clang::options::OPT_dependent_lib) && !triple.isOSWindows()) { const unsigned diagID = diags.getCustomDiagID(clang::DiagnosticsEngine::Error, "--dependent-lib is only supported on Windows"); @@ -1500,12 +1484,10 @@ static bool parseLinkerOptionsArgs(CompilerInvocation &invoc, return false; } - opts.DependentLibs = - args.getAllArgValues(clang::driver::options::OPT_dependent_lib); + opts.DependentLibs = args.getAllArgValues(clang::options::OPT_dependent_lib); // -flto=full/thin option. - if (const llvm::opt::Arg *a = - args.getLastArg(clang::driver::options::OPT_flto_EQ)) { + if (const llvm::opt::Arg *a = args.getLastArg(clang::options::OPT_flto_EQ)) { llvm::StringRef s = a->getValue(); assert((s == "full" || s == "thin") && "Unknown LTO mode."); if (s == "full") @@ -1516,10 +1498,10 @@ static bool parseLinkerOptionsArgs(CompilerInvocation &invoc, // -ffat-lto-objects if (const llvm::opt::Arg *arg = - args.getLastArg(clang::driver::options::OPT_ffat_lto_objects, - clang::driver::options::OPT_fno_fat_lto_objects)) { + args.getLastArg(clang::options::OPT_ffat_lto_objects, + clang::options::OPT_fno_fat_lto_objects)) { opts.PrepareForFatLTO = - arg->getOption().matches(clang::driver::options::OPT_ffat_lto_objects); + arg->getOption().matches(clang::options::OPT_ffat_lto_objects); if (opts.PrepareForFatLTO) { assert((opts.PrepareForFullLTO || opts.PrepareForThinLTO) && "Unknown LTO mode"); @@ -1560,8 +1542,8 @@ bool CompilerInvocation::createFromArgs( llvm::Triple::normalize(llvm::sys::getDefaultTargetTriple()); // Parse the arguments - const llvm::opt::OptTable &opts = clang::driver::getDriverOptTable(); - llvm::opt::Visibility visibilityMask(clang::driver::options::FC1Option); + const llvm::opt::OptTable &opts = clang::getDriverOptTable(); + llvm::opt::Visibility visibilityMask(clang::options::FC1Option); unsigned missingArgIndex, missingArgCount; llvm::opt::InputArgList args = opts.ParseArgs( commandLineArgs, missingArgIndex, missingArgCount, visibilityMask); @@ -1574,7 +1556,7 @@ bool CompilerInvocation::createFromArgs( } // Issue errors on unknown arguments - for (const auto *a : args.filtered(clang::driver::options::OPT_UNKNOWN)) { + for (const auto *a : args.filtered(clang::options::OPT_UNKNOWN)) { auto argString = a->getAsString(args); std::string nearest; if (opts.findNearest(argString, nearest, visibilityMask) > 1) @@ -1586,15 +1568,15 @@ bool CompilerInvocation::createFromArgs( } // -flang-experimental-hlfir - if (args.hasArg(clang::driver::options::OPT_flang_experimental_hlfir) || - args.hasArg(clang::driver::options::OPT_emit_hlfir)) { + if (args.hasArg(clang::options::OPT_flang_experimental_hlfir) || + args.hasArg(clang::options::OPT_emit_hlfir)) { invoc.loweringOpts.setLowerToHighLevelFIR(true); } // -flang-deprecated-no-hlfir - if (args.hasArg(clang::driver::options::OPT_flang_deprecated_no_hlfir) && - !args.hasArg(clang::driver::options::OPT_emit_hlfir)) { - if (args.hasArg(clang::driver::options::OPT_flang_experimental_hlfir)) { + if (args.hasArg(clang::options::OPT_flang_deprecated_no_hlfir) && + !args.hasArg(clang::options::OPT_emit_hlfir)) { + if (args.hasArg(clang::options::OPT_flang_experimental_hlfir)) { const unsigned diagID = diags.getCustomDiagID( clang::DiagnosticsEngine::Error, "Options '-flang-experimental-hlfir' and " @@ -1605,13 +1587,13 @@ bool CompilerInvocation::createFromArgs( } // -fno-ppc-native-vector-element-order - if (args.hasArg(clang::driver::options::OPT_fno_ppc_native_vec_elem_order)) { + if (args.hasArg(clang::options::OPT_fno_ppc_native_vec_elem_order)) { invoc.loweringOpts.setNoPPCNativeVecElemOrder(true); } // -f[no-]init-global-zero - if (args.hasFlag(clang::driver::options::OPT_finit_global_zero, - clang::driver::options::OPT_fno_init_global_zero, + if (args.hasFlag(clang::options::OPT_finit_global_zero, + clang::options::OPT_fno_init_global_zero, /*default=*/true)) invoc.loweringOpts.setInitGlobalZero(true); else @@ -1620,8 +1602,8 @@ bool CompilerInvocation::createFromArgs( // Preserve all the remark options requested, i.e. -Rpass, -Rpass-missed or // -Rpass-analysis. This will be used later when processing and outputting the // remarks generated by LLVM in ExecuteCompilerInvocation.cpp. - for (auto *a : args.filtered(clang::driver::options::OPT_R_Group)) { - if (a->getOption().matches(clang::driver::options::OPT_R_value_Group)) + for (auto *a : args.filtered(clang::options::OPT_R_Group)) { + if (a->getOption().matches(clang::options::OPT_R_value_Group)) // This is -Rfoo=, where foo is the name of the diagnostic // group. Add only the remark option name to the diagnostics. e.g. for // -Rpass= we will add the string "pass". @@ -1634,20 +1616,19 @@ bool CompilerInvocation::createFromArgs( } // -frealloc-lhs is the default. - if (!args.hasFlag(clang::driver::options::OPT_frealloc_lhs, - clang::driver::options::OPT_fno_realloc_lhs, true)) + if (!args.hasFlag(clang::options::OPT_frealloc_lhs, + clang::options::OPT_fno_realloc_lhs, true)) invoc.loweringOpts.setReallocateLHS(false); - invoc.loweringOpts.setRepackArrays( - args.hasFlag(clang::driver::options::OPT_frepack_arrays, - clang::driver::options::OPT_fno_repack_arrays, - /*default=*/false)); + invoc.loweringOpts.setRepackArrays(args.hasFlag( + clang::options::OPT_frepack_arrays, clang::options::OPT_fno_repack_arrays, + /*default=*/false)); invoc.loweringOpts.setStackRepackArrays( - args.hasFlag(clang::driver::options::OPT_fstack_repack_arrays, - clang::driver::options::OPT_fno_stack_repack_arrays, + args.hasFlag(clang::options::OPT_fstack_repack_arrays, + clang::options::OPT_fno_stack_repack_arrays, /*default=*/false)); - if (auto *arg = args.getLastArg( - clang::driver::options::OPT_frepack_arrays_contiguity_EQ)) + if (auto *arg = + args.getLastArg(clang::options::OPT_frepack_arrays_contiguity_EQ)) invoc.loweringOpts.setRepackArraysWhole(arg->getValue() == llvm::StringRef{"whole"}); @@ -1667,10 +1648,8 @@ bool CompilerInvocation::createFromArgs( // `mlirArgs`. Instead, you can use // * `-mllvm <your-llvm-option>`, or // * `-mmlir <your-mlir-option>`. - invoc.frontendOpts.llvmArgs = - args.getAllArgValues(clang::driver::options::OPT_mllvm); - invoc.frontendOpts.mlirArgs = - args.getAllArgValues(clang::driver::options::OPT_mmlir); + invoc.frontendOpts.llvmArgs = args.getAllArgValues(clang::options::OPT_mllvm); + invoc.frontendOpts.mlirArgs = args.getAllArgValues(clang::options::OPT_mmlir); success &= parseLangOptionsArgs(invoc, args, diags); @@ -1694,7 +1673,7 @@ bool CompilerInvocation::createFromArgs( } // Process the timing-related options. - if (args.hasArg(clang::driver::options::OPT_ftime_report)) + if (args.hasArg(clang::options::OPT_ftime_report)) invoc.enableTimers = true; invoc.setArgv0(argv0); diff --git a/flang/lib/Frontend/FrontendActions.cpp b/flang/lib/Frontend/FrontendActions.cpp index 159d08a..ddf125f 100644 --- a/flang/lib/Frontend/FrontendActions.cpp +++ b/flang/lib/Frontend/FrontendActions.cpp @@ -277,11 +277,11 @@ bool CodeGenAction::beginSourceFileAction() { ci.getInvocation().getLangOpts().OpenMPVersion); } - if (ci.getInvocation().getLangOpts().NoFastRealMod) { + if (ci.getInvocation().getLangOpts().FastRealMod) { mlir::ModuleOp mod = lb.getModule(); mod.getOperation()->setAttr( mlir::StringAttr::get(mod.getContext(), - llvm::Twine{"fir.no_fast_real_mod"}), + llvm::Twine{"fir.fast_real_mod"}), mlir::BoolAttr::get(mod.getContext(), true)); } diff --git a/flang/lib/FrontendTool/CMakeLists.txt b/flang/lib/FrontendTool/CMakeLists.txt index faf56e9..b69436c 100644 --- a/flang/lib/FrontendTool/CMakeLists.txt +++ b/flang/lib/FrontendTool/CMakeLists.txt @@ -18,5 +18,6 @@ add_flang_library(flangFrontendTool CLANG_LIBS clangBasic + clangOptions clangDriver ) diff --git a/flang/lib/FrontendTool/ExecuteCompilerInvocation.cpp b/flang/lib/FrontendTool/ExecuteCompilerInvocation.cpp index 09ac129..7586be5 100644 --- a/flang/lib/FrontendTool/ExecuteCompilerInvocation.cpp +++ b/flang/lib/FrontendTool/ExecuteCompilerInvocation.cpp @@ -23,7 +23,7 @@ #include "mlir/IR/MLIRContext.h" #include "mlir/Pass/PassManager.h" #include "clang/Basic/DiagnosticFrontend.h" -#include "clang/Driver/Options.h" +#include "clang/Options/Options.h" #include "llvm/Option/OptTable.h" #include "llvm/Option/Option.h" #include "llvm/Support/BuryPointer.h" @@ -153,10 +153,10 @@ updateDiagEngineForOptRemarks(clang::DiagnosticsEngine &diagsEng, bool executeCompilerInvocation(CompilerInstance *flang) { // Honor -help. if (flang->getFrontendOpts().showHelp) { - clang::driver::getDriverOptTable().printHelp( + clang::getDriverOptTable().printHelp( llvm::outs(), "flang -fc1 [options] file...", "LLVM 'Flang' Compiler", /*ShowHidden=*/false, /*ShowAllAliases=*/false, - llvm::opt::Visibility(clang::driver::options::FC1Option)); + llvm::opt::Visibility(clang::options::FC1Option)); return true; } diff --git a/flang/lib/Lower/Allocatable.cpp b/flang/lib/Lower/Allocatable.cpp index e7a6c4d..c9a9d93 100644 --- a/flang/lib/Lower/Allocatable.cpp +++ b/flang/lib/Lower/Allocatable.cpp @@ -798,10 +798,13 @@ private: // Keep return type the same as a standard AllocatableAllocate call. mlir::Type retTy = fir::runtime::getModel<int>()(builder.getContext()); + bool doubleDescriptors = Fortran::lower::hasDoubleDescriptor(box.getAddr()); return cuf::AllocateOp::create( builder, loc, retTy, box.getAddr(), errmsg, stream, pinned, source, cudaAttr, - errorManager.hasStatSpec() ? builder.getUnitAttr() : nullptr) + errorManager.hasStatSpec() ? builder.getUnitAttr() : nullptr, + doubleDescriptors ? builder.getUnitAttr() : nullptr, + box.isPointer() ? builder.getUnitAttr() : nullptr) .getResult(); } @@ -865,11 +868,14 @@ static mlir::Value genCudaDeallocate(fir::FirOpBuilder &builder, ? nullptr : errorManager.errMsgAddr; - // Keep return type the same as a standard AllocatableAllocate call. + // Keep return type the same as a standard AllocatableDeallocate call. mlir::Type retTy = fir::runtime::getModel<int>()(builder.getContext()); + bool doubleDescriptors = Fortran::lower::hasDoubleDescriptor(box.getAddr()); return cuf::DeallocateOp::create( builder, loc, retTy, box.getAddr(), errmsg, cudaAttr, - errorManager.hasStatSpec() ? builder.getUnitAttr() : nullptr) + errorManager.hasStatSpec() ? builder.getUnitAttr() : nullptr, + doubleDescriptors ? builder.getUnitAttr() : nullptr, + box.isPointer() ? builder.getUnitAttr() : nullptr) .getResult(); } diff --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp index 0f4b39a..d175e2a 100644 --- a/flang/lib/Lower/Bridge.cpp +++ b/flang/lib/Lower/Bridge.cpp @@ -15,7 +15,6 @@ #include "flang/Lower/Allocatable.h" #include "flang/Lower/CUDA.h" #include "flang/Lower/CallInterface.h" -#include "flang/Lower/Coarray.h" #include "flang/Lower/ConvertCall.h" #include "flang/Lower/ConvertExpr.h" #include "flang/Lower/ConvertExprToHLFIR.h" @@ -26,6 +25,7 @@ #include "flang/Lower/IO.h" #include "flang/Lower/IterationSpace.h" #include "flang/Lower/Mangler.h" +#include "flang/Lower/MultiImageFortran.h" #include "flang/Lower/OpenACC.h" #include "flang/Lower/OpenMP.h" #include "flang/Lower/PFTBuilder.h" @@ -86,10 +86,6 @@ #define DEBUG_TYPE "flang-lower-bridge" -static llvm::cl::opt<bool> dumpBeforeFir( - "fdebug-dump-pre-fir", llvm::cl::init(false), - llvm::cl::desc("dump the Pre-FIR tree prior to FIR generation")); - static llvm::cl::opt<bool> forceLoopToExecuteOnce( "always-execute-loop-body", llvm::cl::init(false), llvm::cl::desc("force the body of a loop to execute at least once")); @@ -311,7 +307,11 @@ private: if (!insertPointIfCreated.isSet()) return; // fir.type_info was already built in a previous call. - // Set init, destroy, and nofinal attributes. + // Set abstract, init, destroy, and nofinal attributes. + const Fortran::semantics::Symbol &dtSymbol = info.typeSpec.typeSymbol(); + if (dtSymbol.attrs().test(Fortran::semantics::Attr::ABSTRACT)) + dt->setAttr(dt.getAbstractAttrName(), builder.getUnitAttr()); + if (!info.typeSpec.HasDefaultInitialization(/*ignoreAllocatable=*/false, /*ignorePointer=*/false)) dt->setAttr(dt.getNoInitAttrName(), builder.getUnitAttr()); @@ -335,10 +335,14 @@ private: if (details.numPrivatesNotOverridden() > 0) tbpName += "."s + std::to_string(details.numPrivatesNotOverridden()); std::string bindingName = converter.mangleName(details.symbol()); - fir::DTEntryOp::create( + auto dtEntry = fir::DTEntryOp::create( builder, info.loc, mlir::StringAttr::get(builder.getContext(), tbpName), mlir::SymbolRefAttr::get(builder.getContext(), bindingName)); + // Propagate DEFERRED attribute on the binding to fir.dt_entry. + if (binding.get().attrs().test(Fortran::semantics::Attr::DEFERRED)) + dtEntry->setAttr(fir::DTEntryOp::getDeferredAttrNameStr(), + builder.getUnitAttr()); } fir::FirEndOp::create(builder, info.loc); } @@ -448,6 +452,13 @@ public: } }); + // Ensure imported OpenMP declare mappers are materialized at module + // scope before lowering any constructs that may reference them. + createBuilderOutsideOfFuncOpAndDo([&]() { + Fortran::lower::materializeOpenMPDeclareMappers( + *this, bridge.getSemanticsContext()); + }); + // Create definitions of intrinsic module constants. createBuilderOutsideOfFuncOpAndDo( [&]() { createIntrinsicModuleDefinitions(pft); }); @@ -1111,6 +1122,34 @@ public: return bridge.fctCtx(); } + /// Initializes values for STAT and ERRMSG + std::pair<mlir::Value, mlir::Value> + genStatAndErrmsg(mlir::Location loc, + const std::list<Fortran::parser::StatOrErrmsg> + &statOrErrList) override final { + Fortran::lower::StatementContext stmtCtx; + + mlir::Value errMsgExpr, statExpr; + for (const Fortran::parser::StatOrErrmsg &statOrErr : statOrErrList) { + std::visit(Fortran::common::visitors{ + [&](const Fortran::parser::StatVariable &statVar) { + const Fortran::semantics::SomeExpr *expr = + Fortran::semantics::GetExpr(statVar); + statExpr = + fir::getBase(genExprAddr(*expr, stmtCtx, &loc)); + }, + [&](const Fortran::parser::MsgVariable &errMsgVar) { + const Fortran::semantics::SomeExpr *expr = + Fortran::semantics::GetExpr(errMsgVar); + errMsgExpr = + fir::getBase(genExprBox(loc, *expr, stmtCtx)); + }}, + statOrErr.u); + } + + return {statExpr, errMsgExpr}; + } + mlir::Value hostAssocTupleValue() override final { return hostAssocTuple; } /// Record a binding for the ssa-value of the tuple for this function. @@ -1129,6 +1168,12 @@ public: return registeredDummySymbols.contains(sym); } + unsigned getDummyArgPosition( + const Fortran::semantics::Symbol &sym) const override final { + auto it = dummyArgPositions.find(&sym); + return (it != dummyArgPositions.end()) ? it->second : 0; + } + const Fortran::lower::pft::FunctionLikeUnit * getCurrentFunctionUnit() const override final { return currentFunctionUnit; @@ -1413,11 +1458,14 @@ private: /// definitive mapping. The specification expression have not been lowered /// yet. The final mapping will be done using this pre-mapping in /// Fortran::lower::mapSymbolAttributes. + /// \param argNo The 1-based source position of this argument (0 if + /// unknown/result) bool mapBlockArgToDummyOrResult(const Fortran::semantics::SymbolRef sym, - mlir::Value val, bool isResult) { + mlir::Value val, bool isResult, + unsigned argNo = 0) { localSymbols.addSymbol(sym, val); if (!isResult) - registerDummySymbol(sym); + registerDummySymbol(sym, argNo); return true; } @@ -2264,6 +2312,35 @@ private: } } + // Add AccessGroups attribute on operations in fir::DoLoopOp if this + // operation has the parallelAccesses attribute. + void attachAccessGroupAttrToDoLoopOperations(fir::DoLoopOp &doLoop) { + if (auto loopAnnotAttr = doLoop.getLoopAnnotationAttr()) { + if (loopAnnotAttr.getParallelAccesses().size()) { + llvm::SmallVector<mlir::Attribute> accessGroupAttrs( + loopAnnotAttr.getParallelAccesses().begin(), + loopAnnotAttr.getParallelAccesses().end()); + mlir::ArrayAttr attrs = + mlir::ArrayAttr::get(builder->getContext(), accessGroupAttrs); + doLoop.walk([&](mlir::Operation *op) { + if (fir::StoreOp storeOp = mlir::dyn_cast<fir::StoreOp>(op)) { + storeOp.setAccessGroupsAttr(attrs); + } else if (fir::LoadOp loadOp = mlir::dyn_cast<fir::LoadOp>(op)) { + loadOp.setAccessGroupsAttr(attrs); + } else if (hlfir::AssignOp assignOp = + mlir::dyn_cast<hlfir::AssignOp>(op)) { + // In some loops, the HLFIR AssignOp operation can be translated + // into FIR operation(s) containing StoreOp. It is therefore + // necessary to forward the AccessGroups attribute. + assignOp.getOperation()->setAttr("access_groups", attrs); + } else if (fir::CallOp callOp = mlir::dyn_cast<fir::CallOp>(op)) { + callOp.setAccessGroupsAttr(attrs); + } + }); + } + } + } + /// Generate FIR for a DO construct. There are six variants: /// - unstructured infinite and while loops /// - structured and unstructured increment loops @@ -2412,6 +2489,11 @@ private: // This call may generate a branch in some contexts. genFIR(endDoEval, unstructuredContext); + // Add AccessGroups attribute on operations in fir::DoLoopOp if necessary + for (IncrementLoopInfo &info : incrementLoopNestInfo) + if (auto loopOp = mlir::dyn_cast_if_present<fir::DoLoopOp>(info.loopOp)) + attachAccessGroupAttrToDoLoopOperations(loopOp); + if (!incrementLoopNestInfo.empty() && incrementLoopNestInfo.back().isConcurrent) localSymbols.popScope(); @@ -2500,22 +2582,61 @@ private: {}, {}, {}, {}); } + // Enabling loop vectorization attribute. + mlir::LLVM::LoopVectorizeAttr + genLoopVectorizeAttr(mlir::BoolAttr disableAttr, + mlir::BoolAttr scalableEnable, + mlir::IntegerAttr vectorWidth) { + mlir::LLVM::LoopVectorizeAttr va; + if (disableAttr) + va = mlir::LLVM::LoopVectorizeAttr::get( + builder->getContext(), + /*disable=*/disableAttr, /*predicate=*/{}, + /*scalableEnable=*/scalableEnable, + /*vectorWidth=*/vectorWidth, {}, {}, {}); + return va; + } + void addLoopAnnotationAttr( IncrementLoopInfo &info, llvm::SmallVectorImpl<const Fortran::parser::CompilerDirective *> &dirs) { - mlir::LLVM::LoopVectorizeAttr va; + mlir::BoolAttr disableVecAttr; + mlir::BoolAttr scalableEnable; + mlir::IntegerAttr vectorWidth; mlir::LLVM::LoopUnrollAttr ua; mlir::LLVM::LoopUnrollAndJamAttr uja; + llvm::SmallVector<mlir::LLVM::AccessGroupAttr> aga; bool has_attrs = false; for (const auto *dir : dirs) { Fortran::common::visit( Fortran::common::visitors{ [&](const Fortran::parser::CompilerDirective::VectorAlways &) { - mlir::BoolAttr falseAttr = + disableVecAttr = mlir::BoolAttr::get(builder->getContext(), false); - va = mlir::LLVM::LoopVectorizeAttr::get(builder->getContext(), - /*disable=*/falseAttr, - {}, {}, {}, {}, {}, {}); + has_attrs = true; + }, + [&](const Fortran::parser::CompilerDirective::VectorLength &vl) { + using Kind = + Fortran::parser::CompilerDirective::VectorLength::Kind; + Kind kind = std::get<Kind>(vl.t); + uint64_t length = std::get<uint64_t>(vl.t); + disableVecAttr = + mlir::BoolAttr::get(builder->getContext(), false); + if (length != 0) + vectorWidth = + builder->getIntegerAttr(builder->getI64Type(), length); + switch (kind) { + case Kind::Scalable: + scalableEnable = + mlir::BoolAttr::get(builder->getContext(), true); + break; + case Kind::Fixed: + scalableEnable = + mlir::BoolAttr::get(builder->getContext(), false); + break; + case Kind::Auto: + break; + } has_attrs = true; }, [&](const Fortran::parser::CompilerDirective::Unroll &u) { @@ -2527,11 +2648,8 @@ private: has_attrs = true; }, [&](const Fortran::parser::CompilerDirective::NoVector &u) { - mlir::BoolAttr trueAttr = + disableVecAttr = mlir::BoolAttr::get(builder->getContext(), true); - va = mlir::LLVM::LoopVectorizeAttr::get(builder->getContext(), - /*disable=*/trueAttr, - {}, {}, {}, {}, {}, {}); has_attrs = true; }, [&](const Fortran::parser::CompilerDirective::NoUnroll &u) { @@ -2542,13 +2660,22 @@ private: uja = genLoopUnrollAndJamAttr(/*unrollingFactor=*/0); has_attrs = true; }, - + [&](const Fortran::parser::CompilerDirective::IVDep &iv) { + disableVecAttr = + mlir::BoolAttr::get(builder->getContext(), false); + aga.push_back( + mlir::LLVM::AccessGroupAttr::get(builder->getContext())); + has_attrs = true; + }, [&](const auto &) {}}, dir->u); } + mlir::LLVM::LoopVectorizeAttr va = + genLoopVectorizeAttr(disableVecAttr, scalableEnable, vectorWidth); mlir::LLVM::LoopAnnotationAttr la = mlir::LLVM::LoopAnnotationAttr::get( builder->getContext(), {}, /*vectorize=*/va, {}, /*unroll*/ ua, - /*unroll_and_jam*/ uja, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}); + /*unroll_and_jam*/ uja, {}, {}, {}, {}, {}, {}, {}, {}, {}, + /*parallelAccesses*/ aga); if (has_attrs) { if (auto loopOp = mlir::dyn_cast<fir::DoLoopOp>(info.loopOp)) loopOp.setLoopAnnotationAttr(la); @@ -3251,6 +3378,9 @@ private: [&](const Fortran::parser::CompilerDirective::VectorAlways &) { attachDirectiveToLoop(dir, &eval); }, + [&](const Fortran::parser::CompilerDirective::VectorLength &) { + attachDirectiveToLoop(dir, &eval); + }, [&](const Fortran::parser::CompilerDirective::Unroll &) { attachDirectiveToLoop(dir, &eval); }, @@ -3275,6 +3405,12 @@ private: [&](const Fortran::parser::CompilerDirective::NoInline &) { attachInliningDirectiveToStmt(dir, &eval); }, + [&](const Fortran::parser::CompilerDirective::Prefetch &prefetch) { + TODO(getCurrentLocation(), "!$dir prefetch"); + }, + [&](const Fortran::parser::CompilerDirective::IVDep &) { + attachDirectiveToLoop(dir, &eval); + }, [&](const auto &) {}}, dir.u); } @@ -3832,14 +3968,8 @@ private: if (!isCharSelector) return mlir::arith::CmpIOp::create(*builder, loc, pred, selector, rhs); - fir::factory::CharacterExprHelper charHelper{*builder, loc}; - std::pair<mlir::Value, mlir::Value> lhsVal = - charHelper.createUnboxChar(selector); - std::pair<mlir::Value, mlir::Value> rhsVal = - charHelper.createUnboxChar(rhs); - return fir::runtime::genCharCompare(*builder, loc, pred, lhsVal.first, - lhsVal.second, rhsVal.first, - rhsVal.second); + else + return hlfir::CmpCharOp::create(*builder, loc, pred, selector, rhs); }; mlir::Block *newBlock = insertBlock(*caseBlock); if (mlir::isa<fir::ClosedIntervalAttr>(attr)) { @@ -3950,13 +4080,30 @@ private: } void genFIR(const Fortran::parser::ChangeTeamConstruct &construct) { - TODO(toLocation(), "coarray: ChangeTeamConstruct"); + Fortran::lower::StatementContext stmtCtx; + pushActiveConstruct(getEval(), stmtCtx); + + for (Fortran::lower::pft::Evaluation &e : + getEval().getNestedEvaluations()) { + if (e.getIf<Fortran::parser::ChangeTeamStmt>()) { + maybeStartBlock(e.block); + setCurrentPosition(e.position); + genFIR(e); + } else if (e.getIf<Fortran::parser::EndChangeTeamStmt>()) { + maybeStartBlock(e.block); + setCurrentPosition(e.position); + genFIR(e); + } else { + genFIR(e); + } + } + popActiveConstruct(); } void genFIR(const Fortran::parser::ChangeTeamStmt &stmt) { - TODO(toLocation(), "coarray: ChangeTeamStmt"); + genChangeTeamStmt(*this, getEval(), stmt); } void genFIR(const Fortran::parser::EndChangeTeamStmt &stmt) { - TODO(toLocation(), "coarray: EndChangeTeamStmt"); + genEndChangeTeamStmt(*this, getEval(), stmt); } void genFIR(const Fortran::parser::CriticalConstruct &criticalConstruct) { @@ -4702,32 +4849,14 @@ private: // Generate pointer assignment with possibly empty bounds-spec. R1035: a // bounds-spec is a lower bound value. - void genPointerAssignment( + void genNoHLFIRPointerAssignment( mlir::Location loc, const Fortran::evaluate::Assignment &assign, const Fortran::evaluate::Assignment::BoundsSpec &lbExprs) { Fortran::lower::StatementContext stmtCtx; - if (!lowerToHighLevelFIR() && - Fortran::evaluate::IsProcedureDesignator(assign.rhs)) + assert(!lowerToHighLevelFIR() && "code should not be called with HFLIR"); + if (Fortran::evaluate::IsProcedureDesignator(assign.rhs)) TODO(loc, "procedure pointer assignment"); - if (Fortran::evaluate::IsProcedurePointer(assign.lhs)) { - hlfir::Entity lhs = Fortran::lower::convertExprToHLFIR( - loc, *this, assign.lhs, localSymbols, stmtCtx); - if (Fortran::evaluate::UnwrapExpr<Fortran::evaluate::NullPointer>( - assign.rhs)) { - // rhs is null(). rhs being null(pptr) is handled in genNull. - auto boxTy{ - Fortran::lower::getUntypedBoxProcType(builder->getContext())}; - hlfir::Entity rhs( - fir::factory::createNullBoxProc(*builder, loc, boxTy)); - builder->createStoreWithConvert(loc, rhs, lhs); - return; - } - hlfir::Entity rhs(getBase(Fortran::lower::convertExprToAddress( - loc, *this, assign.rhs, localSymbols, stmtCtx))); - builder->createStoreWithConvert(loc, rhs, lhs); - return; - } std::optional<Fortran::evaluate::DynamicType> lhsType = assign.lhs.GetType(); @@ -4735,7 +4864,7 @@ private: // to the runtime. element size, type code, attribute and of // course base_addr might need to be updated. if (lhsType && lhsType->IsPolymorphic()) { - if (!lowerToHighLevelFIR() && explicitIterationSpace()) + if (explicitIterationSpace()) TODO(loc, "polymorphic pointer assignment in FORALL"); llvm::SmallVector<mlir::Value> lbounds; for (const Fortran::evaluate::ExtentExpr &lbExpr : lbExprs) @@ -4762,7 +4891,7 @@ private: llvm::SmallVector<mlir::Value> lbounds; for (const Fortran::evaluate::ExtentExpr &lbExpr : lbExprs) lbounds.push_back(fir::getBase(genExprValue(toEvExpr(lbExpr), stmtCtx))); - if (!lowerToHighLevelFIR() && explicitIterationSpace()) { + if (explicitIterationSpace()) { // Pointer assignment in FORALL context. Copy the rhs box value // into the lhs box variable. genArrayAssignment(assign, stmtCtx, lbounds); @@ -4773,6 +4902,21 @@ private: stmtCtx); } + void genPointerAssignment(mlir::Location loc, + const Fortran::evaluate::Assignment &assign) { + if (isInsideHlfirForallOrWhere()) { + // Generate Pointer assignment as hlfir.region_assign. + genForallPointerAssignment(loc, assign); + return; + } + Fortran::lower::StatementContext stmtCtx; + hlfir::Entity lhs = Fortran::lower::convertExprToHLFIR( + loc, *this, assign.lhs, localSymbols, stmtCtx); + mlir::Value rhs = genPointerAssignmentRhs(loc, lhs, assign, stmtCtx); + builder->createStoreWithConvert(loc, rhs, lhs); + cuf::genPointerSync(lhs, *builder); + } + void genForallPointerAssignment(mlir::Location loc, const Fortran::evaluate::Assignment &assign) { // Lower pointer assignment inside forall with hlfir.region_assign with @@ -4793,8 +4937,7 @@ private: // Lower RHS in its own region. builder->createBlock(®ionAssignOp.getRhsRegion()); Fortran::lower::StatementContext rhsContext; - mlir::Value rhs = - genForallPointerAssignmentRhs(loc, lhs, assign, rhsContext); + mlir::Value rhs = genPointerAssignmentRhs(loc, lhs, assign, rhsContext); auto rhsYieldOp = hlfir::YieldOp::create(*builder, loc, rhs); Fortran::lower::genCleanUpInRegionIfAny( loc, *builder, rhsYieldOp.getCleanup(), rhsContext); @@ -4810,9 +4953,9 @@ private: } mlir::Value - genForallPointerAssignmentRhs(mlir::Location loc, mlir::Value lhs, - const Fortran::evaluate::Assignment &assign, - Fortran::lower::StatementContext &rhsContext) { + genPointerAssignmentRhs(mlir::Location loc, hlfir::Entity lhs, + const Fortran::evaluate::Assignment &assign, + Fortran::lower::StatementContext &rhsContext) { if (Fortran::evaluate::IsProcedureDesignator(assign.lhs)) { if (Fortran::evaluate::UnwrapExpr<Fortran::evaluate::NullPointer>( assign.rhs)) @@ -4824,11 +4967,34 @@ private: // Data target. auto lhsBoxType = llvm::cast<fir::BaseBoxType>(fir::unwrapRefType(lhs.getType())); - // For NULL, create disassociated descriptor whose dynamic type is - // the static type of the LHS. + // For NULL, create disassociated descriptor whose dynamic type is the + // static type of the LHS (fulfills 7.3.2.3 requirements that the dynamic + // type of a deallocated polymorphic pointer is its static type). if (Fortran::evaluate::UnwrapExpr<Fortran::evaluate::NullPointer>( - assign.rhs)) - return fir::factory::createUnallocatedBox(*builder, loc, lhsBoxType, {}); + assign.rhs)) { + llvm::SmallVector<mlir::Value, 1> nonDeferredLenParams; + if (auto lhsVar = + llvm::dyn_cast_if_present<fir::FortranVariableOpInterface>( + lhs.getDefiningOp())) + nonDeferredLenParams = lhsVar.getExplicitTypeParams(); + if (isInsideHlfirForallOrWhere()) { + // Inside FORALL, the non deferred type parameters may only be + // accessible in the hlfir.region_assign lhs region if they were + // computed there. + for (mlir::Value ¶m : nonDeferredLenParams) + if (!param.getParentRegion()->isAncestor( + builder->getBlock()->getParent())) { + if (llvm::isa_and_nonnull<mlir::arith::ConstantOp>( + param.getDefiningOp())) + param = builder->clone(*param.getDefiningOp())->getResult(0); + else + TODO(loc, "Pointer assignment with non deferred type parameter " + "inside FORALL"); + } + } + return fir::factory::createUnallocatedBox(*builder, loc, lhsBoxType, + nonDeferredLenParams); + } hlfir::Entity rhs = Fortran::lower::convertExprToHLFIR( loc, *this, assign.rhs, localSymbols, rhsContext); auto rhsBoxType = rhs.getBoxType(); @@ -4921,9 +5087,10 @@ private: // Pointer assignment with bounds-remapping. R1036: a bounds-remapping is a // pair, lower bound and upper bound. - void genPointerAssignment( + void genNoHLFIRPointerAssignment( mlir::Location loc, const Fortran::evaluate::Assignment &assign, const Fortran::evaluate::Assignment::BoundsRemapping &boundExprs) { + assert(!lowerToHighLevelFIR() && "code should not be called with HFLIR"); Fortran::lower::StatementContext stmtCtx; llvm::SmallVector<mlir::Value> lbounds; llvm::SmallVector<mlir::Value> ubounds; @@ -4942,7 +5109,7 @@ private: // Polymorphic lhs/rhs need more care. See F2018 10.2.2.3. if ((lhsType && lhsType->IsPolymorphic()) || (rhsType && rhsType->IsPolymorphic())) { - if (!lowerToHighLevelFIR() && explicitIterationSpace()) + if (explicitIterationSpace()) TODO(loc, "polymorphic pointer assignment in FORALL"); fir::MutableBoxValue lhsMutableBox = genExprMutableBox(loc, assign.lhs); @@ -4960,7 +5127,7 @@ private: rhsType->IsPolymorphic()); return; } - if (!lowerToHighLevelFIR() && explicitIterationSpace()) { + if (explicitIterationSpace()) { // Pointer assignment in FORALL context. Copy the rhs box value // into the lhs box variable. genArrayAssignment(assign, stmtCtx, lbounds, ubounds); @@ -4972,13 +5139,6 @@ private: fir::factory::disassociateMutableBox(*builder, loc, lhs); return; } - if (lowerToHighLevelFIR()) { - fir::ExtendedValue rhs = genExprAddr(assign.rhs, stmtCtx); - fir::factory::associateMutableBoxWithRemap(*builder, loc, lhs, rhs, - lbounds, ubounds); - return; - } - // Legacy lowering below. // Do not generate a temp in case rhs is an array section. fir::ExtendedValue rhs = Fortran::lower::isArraySectionWithoutVectorSubscript(assign.rhs) @@ -5368,18 +5528,10 @@ private: dirs); }, [&](const Fortran::evaluate::Assignment::BoundsSpec &lbExprs) { - if (isInsideHlfirForallOrWhere()) - genForallPointerAssignment(loc, assign); - else - genPointerAssignment(loc, assign, lbExprs); + genPointerAssignment(loc, assign); }, [&](const Fortran::evaluate::Assignment::BoundsRemapping - &boundExprs) { - if (isInsideHlfirForallOrWhere()) - genForallPointerAssignment(loc, assign); - else - genPointerAssignment(loc, assign, boundExprs); - }, + &boundExprs) { genPointerAssignment(loc, assign); }, }, assign.u); return; @@ -5581,11 +5733,11 @@ private: }, [&](const Fortran::evaluate::Assignment::BoundsSpec &lbExprs) { - return genPointerAssignment(loc, assign, lbExprs); + return genNoHLFIRPointerAssignment(loc, assign, lbExprs); }, [&](const Fortran::evaluate::Assignment::BoundsRemapping &boundExprs) { - return genPointerAssignment(loc, assign, boundExprs); + return genNoHLFIRPointerAssignment(loc, assign, boundExprs); }, }, assign.u); @@ -5959,7 +6111,16 @@ private: const Fortran::lower::CalleeInterface &callee) { assert(builder && "require a builder object at this point"); using PassBy = Fortran::lower::CalleeInterface::PassEntityBy; + + // Track the source-level argument position (1-based) + unsigned argPosition = 0; + auto mapPassedEntity = [&](const auto arg, bool isResult = false) { + // Count only actual source-level dummy arguments (not results or + // host assoc tuples) + if (!isResult && arg.entity.has_value()) + argPosition++; + if (arg.passBy == PassBy::AddressAndLength) { if (callee.characterize().IsBindC()) return; @@ -5970,11 +6131,12 @@ private: mlir::Value casted = builder->createVolatileCast(loc, false, arg.firArgument); mlir::Value box = charHelp.createEmboxChar(casted, arg.firLength); - mapBlockArgToDummyOrResult(arg.entity->get(), box, isResult); + mapBlockArgToDummyOrResult(arg.entity->get(), box, isResult, + isResult ? 0 : argPosition); } else { if (arg.entity.has_value()) { mapBlockArgToDummyOrResult(arg.entity->get(), arg.firArgument, - isResult); + isResult, isResult ? 0 : argPosition); } else { assert(funit.parentHasTupleHostAssoc() && "expect tuple argument"); } @@ -6832,13 +6994,22 @@ private: } /// Record the given symbol as a dummy argument of this function. - void registerDummySymbol(Fortran::semantics::SymbolRef symRef) { + /// \param symRef The symbol representing the dummy argument + /// \param argNo The 1-based position of this argument in the source (0 = + /// unknown) + void registerDummySymbol(Fortran::semantics::SymbolRef symRef, + unsigned argNo = 0) { auto *sym = &*symRef; registeredDummySymbols.insert(sym); + if (argNo > 0) + dummyArgPositions[sym] = argNo; } /// Reset all registered dummy symbols. - void resetRegisteredDummySymbols() { registeredDummySymbols.clear(); } + void resetRegisteredDummySymbols() { + registeredDummySymbols.clear(); + dummyArgPositions.clear(); + } void setCurrentFunctionUnit(Fortran::lower::pft::FunctionLikeUnit *unit) { currentFunctionUnit = unit; @@ -6880,6 +7051,11 @@ private: llvm::SmallPtrSet<const Fortran::semantics::Symbol *, 16> registeredDummySymbols; + /// Map from dummy symbols to their 1-based argument positions. + /// Used to generate debug info with correct argument numbers. + llvm::DenseMap<const Fortran::semantics::Symbol *, unsigned> + dummyArgPositions; + /// A map of unique names for constant expressions. /// The names are used for representing the constant expressions /// with global constant initialized objects. @@ -6939,8 +7115,6 @@ void Fortran::lower::LoweringBridge::lower( const Fortran::semantics::SemanticsContext &semanticsContext) { std::unique_ptr<Fortran::lower::pft::Program> pft = Fortran::lower::createPFT(prg, semanticsContext); - if (dumpBeforeFir) - Fortran::lower::dumpPFT(llvm::errs(), *pft); FirConverter converter{*this}; converter.run(*pft); } diff --git a/flang/lib/Lower/CMakeLists.txt b/flang/lib/Lower/CMakeLists.txt index 3d0b4e4..230a56a 100644 --- a/flang/lib/Lower/CMakeLists.txt +++ b/flang/lib/Lower/CMakeLists.txt @@ -5,7 +5,6 @@ add_flang_library(FortranLower Allocatable.cpp Bridge.cpp CallInterface.cpp - Coarray.cpp ComponentPath.cpp ConvertArrayConstructor.cpp ConvertCall.cpp @@ -23,6 +22,7 @@ add_flang_library(FortranLower IterationSpace.cpp LoweringOptions.cpp Mangler.cpp + MultiImageFortran.cpp OpenACC.cpp OpenMP/Atomic.cpp OpenMP/ClauseProcessor.cpp diff --git a/flang/lib/Lower/CUDA.cpp b/flang/lib/Lower/CUDA.cpp index 9501b0e..fb05528 100644 --- a/flang/lib/Lower/CUDA.cpp +++ b/flang/lib/Lower/CUDA.cpp @@ -91,3 +91,17 @@ hlfir::ElementalOp Fortran::lower::isTransferWithConversion(mlir::Value rhs) { return elOp; return {}; } + +bool Fortran::lower::hasDoubleDescriptor(mlir::Value addr) { + if (auto declareOp = + mlir::dyn_cast_or_null<hlfir::DeclareOp>(addr.getDefiningOp())) { + if (mlir::isa_and_nonnull<fir::AddrOfOp>( + declareOp.getMemref().getDefiningOp())) { + if (declareOp.getDataAttr() && + *declareOp.getDataAttr() == cuf::DataAttribute::Pinned) + return false; + return true; + } + } + return false; +} diff --git a/flang/lib/Lower/Coarray.cpp b/flang/lib/Lower/Coarray.cpp deleted file mode 100644 index a84f65a..0000000 --- a/flang/lib/Lower/Coarray.cpp +++ /dev/null @@ -1,66 +0,0 @@ -//===-- Coarray.cpp -------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -/// -/// Implementation of the lowering of image related constructs and expressions. -/// Fortran images can form teams, communicate via coarrays, etc. -/// -//===----------------------------------------------------------------------===// - -#include "flang/Lower/Coarray.h" -#include "flang/Lower/AbstractConverter.h" -#include "flang/Lower/SymbolMap.h" -#include "flang/Optimizer/Builder/FIRBuilder.h" -#include "flang/Optimizer/Builder/Todo.h" -#include "flang/Parser/parse-tree.h" -#include "flang/Semantics/expression.h" - -//===----------------------------------------------------------------------===// -// TEAM statements and constructs -//===----------------------------------------------------------------------===// - -void Fortran::lower::genChangeTeamConstruct( - Fortran::lower::AbstractConverter &converter, - Fortran::lower::pft::Evaluation &, - const Fortran::parser::ChangeTeamConstruct &) { - TODO(converter.getCurrentLocation(), "coarray: CHANGE TEAM construct"); -} - -void Fortran::lower::genChangeTeamStmt( - Fortran::lower::AbstractConverter &converter, - Fortran::lower::pft::Evaluation &, - const Fortran::parser::ChangeTeamStmt &) { - TODO(converter.getCurrentLocation(), "coarray: CHANGE TEAM statement"); -} - -void Fortran::lower::genEndChangeTeamStmt( - Fortran::lower::AbstractConverter &converter, - Fortran::lower::pft::Evaluation &, - const Fortran::parser::EndChangeTeamStmt &) { - TODO(converter.getCurrentLocation(), "coarray: END CHANGE TEAM statement"); -} - -void Fortran::lower::genFormTeamStatement( - Fortran::lower::AbstractConverter &converter, - Fortran::lower::pft::Evaluation &, const Fortran::parser::FormTeamStmt &) { - TODO(converter.getCurrentLocation(), "coarray: FORM TEAM statement"); -} - -//===----------------------------------------------------------------------===// -// COARRAY expressions -//===----------------------------------------------------------------------===// - -fir::ExtendedValue Fortran::lower::CoarrayExprHelper::genAddr( - const Fortran::evaluate::CoarrayRef &expr) { - (void)symMap; - TODO(converter.getCurrentLocation(), "co-array address"); -} - -fir::ExtendedValue Fortran::lower::CoarrayExprHelper::genValue( - const Fortran::evaluate::CoarrayRef &expr) { - TODO(converter.getCurrentLocation(), "co-array value"); -} diff --git a/flang/lib/Lower/ConvertCall.cpp b/flang/lib/Lower/ConvertCall.cpp index 9bf994e..cd5218e 100644 --- a/flang/lib/Lower/ConvertCall.cpp +++ b/flang/lib/Lower/ConvertCall.cpp @@ -713,7 +713,8 @@ Fortran::lower::genCallOpAndResult( builder.getContext(), fir::FortranInlineEnum::always_inline); auto call = fir::CallOp::create( builder, loc, funcType.getResults(), funcSymbolAttr, operands, - /*arg_attrs=*/nullptr, /*res_attrs=*/nullptr, procAttrs, inlineAttr); + /*arg_attrs=*/nullptr, /*res_attrs=*/nullptr, procAttrs, inlineAttr, + /*accessGroups=*/mlir::ArrayAttr{}); callNumResults = call.getNumResults(); if (callNumResults != 0) @@ -1296,10 +1297,14 @@ static PreparedDummyArgument preparePresentUserCallActualArgument( Fortran::evaluate::FoldingContext &foldingContext{ callContext.converter.getFoldingContext()}; - bool suggestCopyIn = Fortran::evaluate::MayNeedCopy( - arg.entity, arg.characteristics, foldingContext, /*forCopyOut=*/false); - bool suggestCopyOut = Fortran::evaluate::MayNeedCopy( - arg.entity, arg.characteristics, foldingContext, /*forCopyOut=*/true); + bool suggestCopyIn = Fortran::evaluate::ActualArgNeedsCopy( + arg.entity, arg.characteristics, foldingContext, + /*forCopyOut=*/false) + .value_or(true); + bool suggestCopyOut = Fortran::evaluate::ActualArgNeedsCopy( + arg.entity, arg.characteristics, foldingContext, + /*forCopyOut=*/true) + .value_or(true); mustDoCopyIn = actual.isArray() && suggestCopyIn; mustDoCopyOut = actual.isArray() && suggestCopyOut; } diff --git a/flang/lib/Lower/ConvertExpr.cpp b/flang/lib/Lower/ConvertExpr.cpp index a46d219..b2910a0 100644 --- a/flang/lib/Lower/ConvertExpr.cpp +++ b/flang/lib/Lower/ConvertExpr.cpp @@ -19,7 +19,6 @@ #include "flang/Lower/Bridge.h" #include "flang/Lower/BuiltinModules.h" #include "flang/Lower/CallInterface.h" -#include "flang/Lower/Coarray.h" #include "flang/Lower/ComponentPath.h" #include "flang/Lower/ConvertCall.h" #include "flang/Lower/ConvertConstant.h" @@ -28,6 +27,7 @@ #include "flang/Lower/ConvertVariable.h" #include "flang/Lower/CustomIntrinsicCall.h" #include "flang/Lower/Mangler.h" +#include "flang/Lower/MultiImageFortran.h" #include "flang/Lower/Runtime.h" #include "flang/Lower/Support/Utils.h" #include "flang/Optimizer/Builder/Character.h" diff --git a/flang/lib/Lower/ConvertVariable.cpp b/flang/lib/Lower/ConvertVariable.cpp index 2517ab3..53d4d75 100644 --- a/flang/lib/Lower/ConvertVariable.cpp +++ b/flang/lib/Lower/ConvertVariable.cpp @@ -1946,12 +1946,15 @@ static void genDeclareSymbol(Fortran::lower::AbstractConverter &converter, return; } mlir::Value dummyScope; - if (converter.isRegisteredDummySymbol(sym)) + unsigned argNo = 0; + if (converter.isRegisteredDummySymbol(sym)) { dummyScope = converter.dummyArgsScopeValue(); + argNo = converter.getDummyArgPosition(sym); + } auto [storage, storageOffset] = converter.getSymbolStorage(sym); auto newBase = hlfir::DeclareOp::create( builder, loc, base, name, shapeOrShift, lenParams, dummyScope, storage, - storageOffset, attributes, dataAttr); + storageOffset, attributes, dataAttr, argNo); symMap.addVariableDefinition(sym, newBase, force); return; } @@ -2004,15 +2007,17 @@ void Fortran::lower::genDeclareSymbol( sym.GetUltimate()); auto name = converter.mangleName(sym); mlir::Value dummyScope; + unsigned argNo = 0; fir::ExtendedValue base = exv; if (converter.isRegisteredDummySymbol(sym)) { base = genPackArray(converter, sym, exv); dummyScope = converter.dummyArgsScopeValue(); + argNo = converter.getDummyArgPosition(sym); } auto [storage, storageOffset] = converter.getSymbolStorage(sym); hlfir::EntityWithAttributes declare = hlfir::genDeclare(loc, builder, base, name, attributes, dummyScope, - storage, storageOffset, dataAttr); + storage, storageOffset, dataAttr, argNo); symMap.addVariableDefinition(sym, declare.getIfVariableInterface(), force); return; } diff --git a/flang/lib/Lower/MultiImageFortran.cpp b/flang/lib/Lower/MultiImageFortran.cpp new file mode 100644 index 0000000..745ca249 --- /dev/null +++ b/flang/lib/Lower/MultiImageFortran.cpp @@ -0,0 +1,278 @@ +//===-- MultiImageFortran.cpp ---------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +/// +/// Implementation of the lowering of image related constructs and expressions. +/// Fortran images can form teams, communicate via coarrays, etc. +/// +//===----------------------------------------------------------------------===// + +#include "flang/Lower/MultiImageFortran.h" +#include "flang/Lower/AbstractConverter.h" +#include "flang/Lower/SymbolMap.h" +#include "flang/Optimizer/Builder/FIRBuilder.h" +#include "flang/Optimizer/Builder/Todo.h" +#include "flang/Optimizer/Dialect/MIF/MIFOps.h" +#include "flang/Parser/parse-tree.h" +#include "flang/Semantics/expression.h" + +//===----------------------------------------------------------------------===// +// Synchronization statements +//===----------------------------------------------------------------------===// + +void Fortran::lower::genSyncAllStatement( + Fortran::lower::AbstractConverter &converter, + const Fortran::parser::SyncAllStmt &stmt) { + mlir::Location loc = converter.getCurrentLocation(); + converter.checkCoarrayEnabled(); + + // Handle STAT and ERRMSG values + const std::list<Fortran::parser::StatOrErrmsg> &statOrErrList = stmt.v; + auto [statAddr, errMsgAddr] = converter.genStatAndErrmsg(loc, statOrErrList); + + fir::FirOpBuilder &builder = converter.getFirOpBuilder(); + mif::SyncAllOp::create(builder, loc, statAddr, errMsgAddr); +} + +void Fortran::lower::genSyncImagesStatement( + Fortran::lower::AbstractConverter &converter, + const Fortran::parser::SyncImagesStmt &stmt) { + mlir::Location loc = converter.getCurrentLocation(); + converter.checkCoarrayEnabled(); + fir::FirOpBuilder &builder = converter.getFirOpBuilder(); + + // Handle STAT and ERRMSG values + const std::list<Fortran::parser::StatOrErrmsg> &statOrErrList = + std::get<std::list<Fortran::parser::StatOrErrmsg>>(stmt.t); + auto [statAddr, errMsgAddr] = converter.genStatAndErrmsg(loc, statOrErrList); + + // SYNC_IMAGES(*) is passed as count == -1 while SYNC IMAGES([]) has count + // == 0. Note further that SYNC IMAGES(*) is not semantically equivalent to + // SYNC ALL. + Fortran::lower::StatementContext stmtCtx; + mlir::Value imageSet; + const Fortran::parser::SyncImagesStmt::ImageSet &imgSet = + std::get<Fortran::parser::SyncImagesStmt::ImageSet>(stmt.t); + std::visit(Fortran::common::visitors{ + [&](const Fortran::parser::IntExpr &intExpr) { + const SomeExpr *expr = Fortran::semantics::GetExpr(intExpr); + imageSet = + fir::getBase(converter.genExprBox(loc, *expr, stmtCtx)); + }, + [&](const Fortran::parser::Star &) { + // Image set is not set. + imageSet = mlir::Value{}; + }}, + imgSet.u); + + mif::SyncImagesOp::create(builder, loc, imageSet, statAddr, errMsgAddr); +} + +void Fortran::lower::genSyncMemoryStatement( + Fortran::lower::AbstractConverter &converter, + const Fortran::parser::SyncMemoryStmt &stmt) { + mlir::Location loc = converter.getCurrentLocation(); + converter.checkCoarrayEnabled(); + + // Handle STAT and ERRMSG values + const std::list<Fortran::parser::StatOrErrmsg> &statOrErrList = stmt.v; + auto [statAddr, errMsgAddr] = converter.genStatAndErrmsg(loc, statOrErrList); + + fir::FirOpBuilder &builder = converter.getFirOpBuilder(); + mif::SyncMemoryOp::create(builder, loc, statAddr, errMsgAddr); +} + +void Fortran::lower::genSyncTeamStatement( + Fortran::lower::AbstractConverter &converter, + const Fortran::parser::SyncTeamStmt &stmt) { + mlir::Location loc = converter.getCurrentLocation(); + converter.checkCoarrayEnabled(); + + // Handle TEAM + Fortran::lower::StatementContext stmtCtx; + const Fortran::parser::TeamValue &teamValue = + std::get<Fortran::parser::TeamValue>(stmt.t); + const SomeExpr *teamExpr = Fortran::semantics::GetExpr(teamValue); + mlir::Value team = + fir::getBase(converter.genExprBox(loc, *teamExpr, stmtCtx)); + + // Handle STAT and ERRMSG values + const std::list<Fortran::parser::StatOrErrmsg> &statOrErrList = + std::get<std::list<Fortran::parser::StatOrErrmsg>>(stmt.t); + auto [statAddr, errMsgAddr] = converter.genStatAndErrmsg(loc, statOrErrList); + + fir::FirOpBuilder &builder = converter.getFirOpBuilder(); + mif::SyncTeamOp::create(builder, loc, team, statAddr, errMsgAddr); +} + +//===----------------------------------------------------------------------===// +// TEAM statements and constructs +//===----------------------------------------------------------------------===// + +void Fortran::lower::genChangeTeamConstruct( + Fortran::lower::AbstractConverter &converter, + Fortran::lower::pft::Evaluation &, + const Fortran::parser::ChangeTeamConstruct &) { + TODO(converter.getCurrentLocation(), "coarray: CHANGE TEAM construct"); +} + +void Fortran::lower::genChangeTeamStmt( + Fortran::lower::AbstractConverter &converter, + Fortran::lower::pft::Evaluation &, + const Fortran::parser::ChangeTeamStmt &stmt) { + mlir::Location loc = converter.getCurrentLocation(); + converter.checkCoarrayEnabled(); + fir::FirOpBuilder &builder = converter.getFirOpBuilder(); + + mlir::Value errMsgAddr, statAddr, team; + // Handle STAT and ERRMSG values + Fortran::lower::StatementContext stmtCtx; + const std::list<Fortran::parser::StatOrErrmsg> &statOrErrList = + std::get<std::list<Fortran::parser::StatOrErrmsg>>(stmt.t); + for (const Fortran::parser::StatOrErrmsg &statOrErr : statOrErrList) { + std::visit(Fortran::common::visitors{ + [&](const Fortran::parser::StatVariable &statVar) { + const auto *expr = Fortran::semantics::GetExpr(statVar); + statAddr = fir::getBase( + converter.genExprAddr(loc, *expr, stmtCtx)); + }, + [&](const Fortran::parser::MsgVariable &errMsgVar) { + const auto *expr = Fortran::semantics::GetExpr(errMsgVar); + errMsgAddr = fir::getBase( + converter.genExprBox(loc, *expr, stmtCtx)); + }, + }, + statOrErr.u); + } + + // TODO: Manage the list of coarrays associated in + // `std::list<CoarrayAssociation>`. According to the PRIF specification, it is + // necessary to call `prif_alias_{create|destroy}` for each coarray defined in + // this list. Support will be added once lowering to this procedure is + // possible. + const std::list<Fortran::parser::CoarrayAssociation> &coarrayAssocList = + std::get<std::list<Fortran::parser::CoarrayAssociation>>(stmt.t); + if (coarrayAssocList.size()) + TODO(loc, "Coarrays provided in the association list."); + + // Handle TEAM-VALUE + const auto *teamExpr = + Fortran::semantics::GetExpr(std::get<Fortran::parser::TeamValue>(stmt.t)); + team = fir::getBase(converter.genExprBox(loc, *teamExpr, stmtCtx)); + + mif::ChangeTeamOp changeOp = mif::ChangeTeamOp::create( + builder, loc, team, statAddr, errMsgAddr, /*terminator*/ false); + builder.setInsertionPointToStart(changeOp.getBody()); +} + +void Fortran::lower::genEndChangeTeamStmt( + Fortran::lower::AbstractConverter &converter, + Fortran::lower::pft::Evaluation &, + const Fortran::parser::EndChangeTeamStmt &stmt) { + converter.checkCoarrayEnabled(); + mlir::Location loc = converter.getCurrentLocation(); + fir::FirOpBuilder &builder = converter.getFirOpBuilder(); + + mlir::Value errMsgAddr, statAddr; + // Handle STAT and ERRMSG values + Fortran::lower::StatementContext stmtCtx; + const std::list<Fortran::parser::StatOrErrmsg> &statOrErrList = + std::get<std::list<Fortran::parser::StatOrErrmsg>>(stmt.t); + for (const Fortran::parser::StatOrErrmsg &statOrErr : statOrErrList) { + std::visit(Fortran::common::visitors{ + [&](const Fortran::parser::StatVariable &statVar) { + const auto *expr = Fortran::semantics::GetExpr(statVar); + statAddr = fir::getBase( + converter.genExprAddr(loc, *expr, stmtCtx)); + }, + [&](const Fortran::parser::MsgVariable &errMsgVar) { + const auto *expr = Fortran::semantics::GetExpr(errMsgVar); + errMsgAddr = fir::getBase( + converter.genExprBox(loc, *expr, stmtCtx)); + }, + }, + statOrErr.u); + } + + mif::EndTeamOp endOp = + mif::EndTeamOp::create(builder, loc, statAddr, errMsgAddr); + builder.setInsertionPointAfter(endOp.getParentOp()); +} + +void Fortran::lower::genFormTeamStatement( + Fortran::lower::AbstractConverter &converter, + Fortran::lower::pft::Evaluation &, + const Fortran::parser::FormTeamStmt &stmt) { + converter.checkCoarrayEnabled(); + mlir::Location loc = converter.getCurrentLocation(); + fir::FirOpBuilder &builder = converter.getFirOpBuilder(); + + mlir::Value errMsgAddr, statAddr, newIndex, teamNumber, team; + // Handle NEW_INDEX, STAT and ERRMSG + std::list<Fortran::parser::StatOrErrmsg> statOrErrList{}; + Fortran::lower::StatementContext stmtCtx; + const auto &formSpecList = + std::get<std::list<Fortran::parser::FormTeamStmt::FormTeamSpec>>(stmt.t); + for (const Fortran::parser::FormTeamStmt::FormTeamSpec &formSpec : + formSpecList) { + std::visit( + Fortran::common::visitors{ + [&](const Fortran::parser::StatOrErrmsg &statOrErr) { + std::visit( + Fortran::common::visitors{ + [&](const Fortran::parser::StatVariable &statVar) { + const auto *expr = Fortran::semantics::GetExpr(statVar); + statAddr = fir::getBase( + converter.genExprAddr(loc, *expr, stmtCtx)); + }, + [&](const Fortran::parser::MsgVariable &errMsgVar) { + const auto *expr = + Fortran::semantics::GetExpr(errMsgVar); + errMsgAddr = fir::getBase( + converter.genExprBox(loc, *expr, stmtCtx)); + }, + }, + statOrErr.u); + }, + [&](const Fortran::parser::ScalarIntExpr &intExpr) { + fir::ExtendedValue newIndexExpr = converter.genExprValue( + loc, Fortran::semantics::GetExpr(intExpr), stmtCtx); + newIndex = fir::getBase(newIndexExpr); + }, + }, + formSpec.u); + } + + // Handle TEAM-NUMBER + const auto *teamNumberExpr = Fortran::semantics::GetExpr( + std::get<Fortran::parser::ScalarIntExpr>(stmt.t)); + teamNumber = + fir::getBase(converter.genExprValue(loc, *teamNumberExpr, stmtCtx)); + + // Handle TEAM-VARIABLE + const auto *teamExpr = Fortran::semantics::GetExpr( + std::get<Fortran::parser::TeamVariable>(stmt.t)); + team = fir::getBase(converter.genExprBox(loc, *teamExpr, stmtCtx)); + + mif::FormTeamOp::create(builder, loc, teamNumber, team, newIndex, statAddr, + errMsgAddr); +} + +//===----------------------------------------------------------------------===// +// COARRAY expressions +//===----------------------------------------------------------------------===// + +fir::ExtendedValue Fortran::lower::CoarrayExprHelper::genAddr( + const Fortran::evaluate::CoarrayRef &expr) { + (void)symMap; + TODO(converter.getCurrentLocation(), "co-array address"); +} + +fir::ExtendedValue Fortran::lower::CoarrayExprHelper::genValue( + const Fortran::evaluate::CoarrayRef &expr) { + TODO(converter.getCurrentLocation(), "co-array value"); +} diff --git a/flang/lib/Lower/OpenACC.cpp b/flang/lib/Lower/OpenACC.cpp index d7861ac..50b08ce 100644 --- a/flang/lib/Lower/OpenACC.cpp +++ b/flang/lib/Lower/OpenACC.cpp @@ -28,6 +28,7 @@ #include "flang/Optimizer/Builder/IntrinsicCall.h" #include "flang/Optimizer/Builder/Todo.h" #include "flang/Optimizer/Dialect/FIRType.h" +#include "flang/Optimizer/OpenACC/Support/FIROpenACCUtils.h" #include "flang/Parser/parse-tree-visitor.h" #include "flang/Parser/parse-tree.h" #include "flang/Parser/tools.h" @@ -1159,18 +1160,6 @@ bool isConstantBound(mlir::acc::DataBoundsOp &op) { return false; } -/// Return true iff all the bounds are expressed with constant values. -bool areAllBoundConstant(const llvm::SmallVector<mlir::Value> &bounds) { - for (auto bound : bounds) { - auto dataBound = - mlir::dyn_cast<mlir::acc::DataBoundsOp>(bound.getDefiningOp()); - assert(dataBound && "Must be DataBoundOp operation"); - if (!isConstantBound(dataBound)) - return false; - } - return true; -} - static llvm::SmallVector<mlir::Value> genConstantBounds(fir::FirOpBuilder &builder, mlir::Location loc, mlir::acc::DataBoundsOp &dataBound) { @@ -1196,59 +1185,6 @@ genConstantBounds(fir::FirOpBuilder &builder, mlir::Location loc, return {lb, ub, step}; } -static mlir::Value genShapeFromBoundsOrArgs( - mlir::Location loc, fir::FirOpBuilder &builder, fir::SequenceType seqTy, - const llvm::SmallVector<mlir::Value> &bounds, mlir::ValueRange arguments) { - llvm::SmallVector<mlir::Value> args; - if (bounds.empty() && seqTy) { - if (seqTy.hasDynamicExtents()) { - assert(!arguments.empty() && "arguments must hold the entity"); - auto entity = hlfir::Entity{arguments[0]}; - return hlfir::genShape(loc, builder, entity); - } - return genShapeOp(builder, seqTy, loc).getResult(); - } else if (areAllBoundConstant(bounds)) { - for (auto bound : llvm::reverse(bounds)) { - auto dataBound = - mlir::cast<mlir::acc::DataBoundsOp>(bound.getDefiningOp()); - args.append(genConstantBounds(builder, loc, dataBound)); - } - } else { - assert(((arguments.size() - 2) / 3 == seqTy.getDimension()) && - "Expect 3 block arguments per dimension"); - for (auto arg : arguments.drop_front(2)) - args.push_back(arg); - } - - assert(args.size() % 3 == 0 && "Triplets must be a multiple of 3"); - llvm::SmallVector<mlir::Value> extents; - mlir::Type idxTy = builder.getIndexType(); - mlir::Value one = builder.createIntegerConstant(loc, idxTy, 1); - mlir::Value zero = builder.createIntegerConstant(loc, idxTy, 0); - for (unsigned i = 0; i < args.size(); i += 3) { - mlir::Value s1 = - mlir::arith::SubIOp::create(builder, loc, args[i + 1], args[0]); - mlir::Value s2 = mlir::arith::AddIOp::create(builder, loc, s1, one); - mlir::Value s3 = - mlir::arith::DivSIOp::create(builder, loc, s2, args[i + 2]); - mlir::Value cmp = mlir::arith::CmpIOp::create( - builder, loc, mlir::arith::CmpIPredicate::sgt, s3, zero); - mlir::Value ext = - mlir::arith::SelectOp::create(builder, loc, cmp, s3, zero); - extents.push_back(ext); - } - return fir::ShapeOp::create(builder, loc, extents); -} - -static hlfir::DesignateOp::Subscripts -getSubscriptsFromArgs(mlir::ValueRange args) { - hlfir::DesignateOp::Subscripts triplets; - for (unsigned i = 2; i < args.size(); i += 3) - triplets.emplace_back( - hlfir::DesignateOp::Triplet{args[i], args[i + 1], args[i + 2]}); - return triplets; -} - static hlfir::Entity genDesignateWithTriplets( fir::FirOpBuilder &builder, mlir::Location loc, hlfir::Entity &entity, hlfir::DesignateOp::Subscripts &triplets, mlir::Value shape) { @@ -1262,19 +1198,88 @@ static hlfir::Entity genDesignateWithTriplets( return hlfir::Entity{designate.getResult()}; } -mlir::acc::FirstprivateRecipeOp Fortran::lower::createOrGetFirstprivateRecipe( - fir::FirOpBuilder &builder, llvm::StringRef recipeName, mlir::Location loc, - mlir::Type ty, llvm::SmallVector<mlir::Value> &bounds) { - mlir::ModuleOp mod = - builder.getBlock()->getParent()->getParentOfType<mlir::ModuleOp>(); - if (auto recipe = - mod.lookupSymbol<mlir::acc::FirstprivateRecipeOp>(recipeName)) - return recipe; +// Designate uses triplets based on object lower bounds while acc.bounds are +// zero based. This helper shift the bounds to create the designate triplets. +static hlfir::DesignateOp::Subscripts +genTripletsFromAccBounds(fir::FirOpBuilder &builder, mlir::Location loc, + const llvm::SmallVector<mlir::Value> &accBounds, + hlfir::Entity entity) { + assert(entity.getRank() * 3 == static_cast<int>(accBounds.size()) && + "must get lb,ub,step for each dimension"); + hlfir::DesignateOp::Subscripts triplets; + for (unsigned i = 0; i < accBounds.size(); i += 3) { + mlir::Value lb = hlfir::genLBound(loc, builder, entity, i / 3); + lb = builder.createConvert(loc, accBounds[i].getType(), lb); + assert(accBounds[i].getType() == accBounds[i + 1].getType() && + "mix of integer types in triplets"); + mlir::Value sliceLB = + builder.createOrFold<mlir::arith::AddIOp>(loc, accBounds[i], lb); + mlir::Value sliceUB = + builder.createOrFold<mlir::arith::AddIOp>(loc, accBounds[i + 1], lb); + triplets.emplace_back( + hlfir::DesignateOp::Triplet{sliceLB, sliceUB, accBounds[i + 2]}); + } + return triplets; +} - auto ip = builder.saveInsertionPoint(); - auto recipe = genRecipeOp<mlir::acc::FirstprivateRecipeOp>( - builder, mod, recipeName, loc, ty); - bool allConstantBound = areAllBoundConstant(bounds); +static std::pair<hlfir::Entity, hlfir::Entity> +genArraySectionsInRecipe(fir::FirOpBuilder &builder, mlir::Location loc, + llvm::SmallVector<mlir::Value> &dataOperationBounds, + mlir::ValueRange recipeArguments, + bool allConstantBound, hlfir::Entity lhs, + hlfir::Entity rhs) { + lhs = hlfir::derefPointersAndAllocatables(loc, builder, lhs); + rhs = hlfir::derefPointersAndAllocatables(loc, builder, rhs); + // Get the list of lb,ub,step values for the sections that can be used inside + // the recipe region. + llvm::SmallVector<mlir::Value> bounds; + if (allConstantBound) { + // For constant bounds, the bounds are not region arguments. Materialize + // constants looking at the IR for the bounds on the data operation. + for (auto bound : dataOperationBounds) { + auto dataBound = + mlir::cast<mlir::acc::DataBoundsOp>(bound.getDefiningOp()); + bounds.append(genConstantBounds(builder, loc, dataBound)); + } + } else { + // If one bound is not constant, all of the bounds are region arguments. + for (auto arg : recipeArguments.drop_front(2)) + bounds.push_back(arg); + } + // Compute the fir.shape of the array section and the triplets to create + // hlfir.designate. + assert(lhs.getRank() * 3 == static_cast<int>(bounds.size()) && + "must get lb,ub,step for each dimension"); + llvm::SmallVector<mlir::Value> extents; + mlir::Type idxTy = builder.getIndexType(); + for (unsigned i = 0; i < bounds.size(); i += 3) + extents.push_back(builder.genExtentFromTriplet( + loc, bounds[i], bounds[i + 1], bounds[i + 2], idxTy)); + mlir::Value shape = fir::ShapeOp::create(builder, loc, extents); + hlfir::DesignateOp::Subscripts rhsTriplets = + genTripletsFromAccBounds(builder, loc, bounds, rhs); + hlfir::DesignateOp::Subscripts lhsTriplets; + // Share the bounds when both rhs/lhs are known to be 1-based to avoid noise + // in the IR for the most common cases. + if (!lhs.mayHaveNonDefaultLowerBounds() && + !rhs.mayHaveNonDefaultLowerBounds()) + lhsTriplets = rhsTriplets; + else + lhsTriplets = genTripletsFromAccBounds(builder, loc, bounds, lhs); + hlfir::Entity leftSection = + genDesignateWithTriplets(builder, loc, lhs, lhsTriplets, shape); + hlfir::Entity rightSection = + genDesignateWithTriplets(builder, loc, rhs, rhsTriplets, shape); + return {leftSection, rightSection}; +} + +// Generate the combiner or copy region block and block arguments and return the +// source and destination entities. +static std::pair<hlfir::Entity, hlfir::Entity> +genRecipeCombinerOrCopyRegion(fir::FirOpBuilder &builder, mlir::Location loc, + mlir::Type ty, mlir::Region ®ion, + llvm::SmallVector<mlir::Value> &bounds, + bool allConstantBound) { llvm::SmallVector<mlir::Type> argsTy{ty, ty}; llvm::SmallVector<mlir::Location> argsLoc{loc, loc}; if (!allConstantBound) { @@ -1289,100 +1294,57 @@ mlir::acc::FirstprivateRecipeOp Fortran::lower::createOrGetFirstprivateRecipe( argsLoc.push_back(dataBound.getStartIdx().getLoc()); } } - builder.createBlock(&recipe.getCopyRegion(), recipe.getCopyRegion().end(), - argsTy, argsLoc); + mlir::Block *block = + builder.createBlock(®ion, region.end(), argsTy, argsLoc); + builder.setInsertionPointToEnd(®ion.back()); + return {hlfir::Entity{block->getArgument(0)}, + hlfir::Entity{block->getArgument(1)}}; +} - builder.setInsertionPointToEnd(&recipe.getCopyRegion().back()); - ty = fir::unwrapRefType(ty); - if (fir::isa_trivial(ty)) { - mlir::Value initValue = fir::LoadOp::create( - builder, loc, recipe.getCopyRegion().front().getArgument(0)); - fir::StoreOp::create(builder, loc, initValue, - recipe.getCopyRegion().front().getArgument(1)); - } else if (auto seqTy = mlir::dyn_cast_or_null<fir::SequenceType>(ty)) { - fir::FirOpBuilder firBuilder{builder, recipe.getOperation()}; - auto shape = genShapeFromBoundsOrArgs( - loc, firBuilder, seqTy, bounds, recipe.getCopyRegion().getArguments()); - - auto leftDeclOp = hlfir::DeclareOp::create( - builder, loc, recipe.getCopyRegion().getArgument(0), llvm::StringRef{}, - shape); - auto rightDeclOp = hlfir::DeclareOp::create( - builder, loc, recipe.getCopyRegion().getArgument(1), llvm::StringRef{}, - shape); - - hlfir::DesignateOp::Subscripts triplets = - getSubscriptsFromArgs(recipe.getCopyRegion().getArguments()); - auto leftEntity = hlfir::Entity{leftDeclOp.getBase()}; - auto left = - genDesignateWithTriplets(firBuilder, loc, leftEntity, triplets, shape); - auto rightEntity = hlfir::Entity{rightDeclOp.getBase()}; - auto right = - genDesignateWithTriplets(firBuilder, loc, rightEntity, triplets, shape); - - hlfir::AssignOp::create(firBuilder, loc, left, right); - - } else if (auto boxTy = mlir::dyn_cast_or_null<fir::BaseBoxType>(ty)) { - fir::FirOpBuilder firBuilder{builder, recipe.getOperation()}; - llvm::SmallVector<mlir::Value> tripletArgs; - mlir::Type innerTy = fir::extractSequenceType(boxTy); - fir::SequenceType seqTy = - mlir::dyn_cast_or_null<fir::SequenceType>(innerTy); - if (!seqTy) - TODO(loc, "Unsupported boxed type in OpenACC firstprivate"); - - auto shape = genShapeFromBoundsOrArgs( - loc, firBuilder, seqTy, bounds, recipe.getCopyRegion().getArguments()); - hlfir::DesignateOp::Subscripts triplets = - getSubscriptsFromArgs(recipe.getCopyRegion().getArguments()); - auto leftEntity = hlfir::Entity{recipe.getCopyRegion().getArgument(0)}; - auto left = - genDesignateWithTriplets(firBuilder, loc, leftEntity, triplets, shape); - auto rightEntity = hlfir::Entity{recipe.getCopyRegion().getArgument(1)}; - auto right = - genDesignateWithTriplets(firBuilder, loc, rightEntity, triplets, shape); - hlfir::AssignOp::create(firBuilder, loc, left, right); - } else { - // Copy scalar derived type. - // The temporary_lhs flag allows indicating that user defined assignments - // should not be called while copying components, and that the LHS and RHS - // are known to not alias since the LHS is a created object. - hlfir::AssignOp::create( - builder, loc, recipe.getCopyRegion().getArgument(0), - recipe.getCopyRegion().getArgument(1), /*realloc=*/false, - /*keep_lhs_length_if_realloc=*/false, /*temporary_lhs=*/true); - } +mlir::acc::FirstprivateRecipeOp Fortran::lower::createOrGetFirstprivateRecipe( + fir::FirOpBuilder &builder, llvm::StringRef recipeName, mlir::Location loc, + mlir::Type ty, llvm::SmallVector<mlir::Value> &bounds) { + mlir::ModuleOp mod = + builder.getBlock()->getParent()->getParentOfType<mlir::ModuleOp>(); + if (auto recipe = + mod.lookupSymbol<mlir::acc::FirstprivateRecipeOp>(recipeName)) + return recipe; - mlir::acc::TerminatorOp::create(builder, loc); - builder.restoreInsertionPoint(ip); - return recipe; -} + mlir::OpBuilder::InsertionGuard guard(builder); + auto recipe = genRecipeOp<mlir::acc::FirstprivateRecipeOp>( + builder, mod, recipeName, loc, ty); + bool allConstantBound = fir::acc::areAllBoundsConstant(bounds); + auto [source, destination] = genRecipeCombinerOrCopyRegion( + builder, loc, ty, recipe.getCopyRegion(), bounds, allConstantBound); + + fir::FirOpBuilder firBuilder{builder, recipe.getOperation()}; + + source = hlfir::derefPointersAndAllocatables(loc, builder, source); + destination = hlfir::derefPointersAndAllocatables(loc, builder, destination); -/// Get a string representation of the bounds. -std::string getBoundsString(llvm::SmallVector<mlir::Value> &bounds) { - std::stringstream boundStr; if (!bounds.empty()) - boundStr << "_section_"; - llvm::interleave( - bounds, - [&](mlir::Value bound) { - auto boundsOp = - mlir::cast<mlir::acc::DataBoundsOp>(bound.getDefiningOp()); - if (boundsOp.getLowerbound() && - fir::getIntIfConstant(boundsOp.getLowerbound()) && - boundsOp.getUpperbound() && - fir::getIntIfConstant(boundsOp.getUpperbound())) { - boundStr << "lb" << *fir::getIntIfConstant(boundsOp.getLowerbound()) - << ".ub" << *fir::getIntIfConstant(boundsOp.getUpperbound()); - } else if (boundsOp.getExtent() && - fir::getIntIfConstant(boundsOp.getExtent())) { - boundStr << "ext" << *fir::getIntIfConstant(boundsOp.getExtent()); - } else { - boundStr << "?"; - } - }, - [&] { boundStr << "x"; }); - return boundStr.str(); + std::tie(source, destination) = genArraySectionsInRecipe( + firBuilder, loc, bounds, recipe.getCopyRegion().getArguments(), + allConstantBound, source, destination); + // The source and the destination of the firstprivate copy cannot alias, + // the destination is already properly allocated, so a simple assignment + // can be generated right away to avoid ending-up with runtime calls + // for arrays of numerical, logical and, character types. + // + // The temporary_lhs flag allows indicating that user defined assignments + // should not be called while copying components, and that the LHS and RHS + // are known to not alias since the LHS is a created object. + // + // TODO: detect cases where user defined assignment is needed and add a TODO. + // using temporary_lhs allows more aggressive optimizations of simple derived + // types. Existing compilers supporting OpenACC do not call user defined + // assignments, some use case is needed to decide what to do. + source = hlfir::loadTrivialScalar(loc, builder, source); + hlfir::AssignOp::create(builder, loc, source, destination, /*realloc=*/false, + /*keep_lhs_length_if_realloc=*/false, + /*temporary_lhs=*/true); + mlir::acc::TerminatorOp::create(builder, loc); + return recipe; } /// Rebuild the array type from the acc.bounds operation with constant @@ -1427,7 +1389,6 @@ static void genPrivatizationRecipes( Fortran::semantics::SemanticsContext &semanticsContext, Fortran::lower::StatementContext &stmtCtx, llvm::SmallVectorImpl<mlir::Value> &dataOperands, - llvm::SmallVector<mlir::Attribute> &privatizationRecipes, llvm::ArrayRef<mlir::Value> async, llvm::ArrayRef<mlir::Attribute> asyncDeviceTypes, llvm::ArrayRef<mlir::Attribute> asyncOnlyDeviceTypes, @@ -1458,15 +1419,16 @@ static void genPrivatizationRecipes( RecipeOp recipe; mlir::Type retTy = getTypeFromBounds(bounds, info.addr.getType()); if constexpr (std::is_same_v<RecipeOp, mlir::acc::PrivateRecipeOp>) { - std::string recipeName = - fir::getTypeAsString(retTy, converter.getKindMap(), - Fortran::lower::privatizationRecipePrefix); + std::string recipeName = fir::acc::getRecipeName( + mlir::acc::RecipeKind::private_recipe, retTy, info.addr, bounds); recipe = Fortran::lower::createOrGetPrivateRecipe(builder, recipeName, operandLocation, retTy); auto op = createDataEntryOp<mlir::acc::PrivateOp>( builder, operandLocation, info.addr, asFortran, bounds, true, /*implicit=*/false, mlir::acc::DataClause::acc_private, retTy, async, asyncDeviceTypes, asyncOnlyDeviceTypes, /*unwrapBoxAddr=*/true); + op.setRecipeAttr( + mlir::SymbolRefAttr::get(builder.getContext(), recipe.getSymName())); dataOperands.push_back(op.getAccVar()); // Track the symbol and its corresponding mlir::Value if requested @@ -1474,10 +1436,8 @@ static void genPrivatizationRecipes( symbolPairs->emplace_back(op.getAccVar(), Fortran::semantics::SymbolRef(symbol)); } else { - std::string suffix = - areAllBoundConstant(bounds) ? getBoundsString(bounds) : ""; - std::string recipeName = fir::getTypeAsString( - retTy, converter.getKindMap(), "firstprivatization" + suffix); + std::string recipeName = fir::acc::getRecipeName( + mlir::acc::RecipeKind::firstprivate_recipe, retTy, info.addr, bounds); recipe = Fortran::lower::createOrGetFirstprivateRecipe( builder, recipeName, operandLocation, retTy, bounds); auto op = createDataEntryOp<mlir::acc::FirstprivateOp>( @@ -1485,6 +1445,8 @@ static void genPrivatizationRecipes( /*implicit=*/false, mlir::acc::DataClause::acc_firstprivate, retTy, async, asyncDeviceTypes, asyncOnlyDeviceTypes, /*unwrapBoxAddr=*/true); + op.setRecipeAttr( + mlir::SymbolRefAttr::get(builder.getContext(), recipe.getSymName())); dataOperands.push_back(op.getAccVar()); // Track the symbol and its corresponding mlir::Value if requested @@ -1492,8 +1454,6 @@ static void genPrivatizationRecipes( symbolPairs->emplace_back(op.getAccVar(), Fortran::semantics::SymbolRef(symbol)); } - privatizationRecipes.push_back(mlir::SymbolRefAttr::get( - builder.getContext(), recipe.getSymName().str())); } } @@ -1611,205 +1571,6 @@ static mlir::Value genScalarCombiner(fir::FirOpBuilder &builder, TODO(loc, "reduction operator"); } -static hlfir::DesignateOp::Subscripts -getTripletsFromArgs(mlir::acc::ReductionRecipeOp recipe) { - hlfir::DesignateOp::Subscripts triplets; - for (unsigned i = 2; i < recipe.getCombinerRegion().getArguments().size(); - i += 3) - triplets.emplace_back(hlfir::DesignateOp::Triplet{ - recipe.getCombinerRegion().getArgument(i), - recipe.getCombinerRegion().getArgument(i + 1), - recipe.getCombinerRegion().getArgument(i + 2)}); - return triplets; -} - -static void genCombiner(fir::FirOpBuilder &builder, mlir::Location loc, - mlir::acc::ReductionOperator op, mlir::Type ty, - mlir::Value value1, mlir::Value value2, - mlir::acc::ReductionRecipeOp &recipe, - llvm::SmallVector<mlir::Value> &bounds, - bool allConstantBound) { - ty = fir::unwrapRefType(ty); - - if (auto seqTy = mlir::dyn_cast<fir::SequenceType>(ty)) { - mlir::Type refTy = fir::ReferenceType::get(seqTy.getEleTy()); - llvm::SmallVector<fir::DoLoopOp> loops; - llvm::SmallVector<mlir::Value> ivs; - if (seqTy.hasDynamicExtents()) { - auto shape = - genShapeFromBoundsOrArgs(loc, builder, seqTy, bounds, - recipe.getCombinerRegion().getArguments()); - auto v1DeclareOp = hlfir::DeclareOp::create(builder, loc, value1, - llvm::StringRef{}, shape); - auto v2DeclareOp = hlfir::DeclareOp::create(builder, loc, value2, - llvm::StringRef{}, shape); - hlfir::DesignateOp::Subscripts triplets = getTripletsFromArgs(recipe); - - llvm::SmallVector<mlir::Value> lenParamsLeft; - auto leftEntity = hlfir::Entity{v1DeclareOp.getBase()}; - hlfir::genLengthParameters(loc, builder, leftEntity, lenParamsLeft); - auto leftDesignate = hlfir::DesignateOp::create( - builder, loc, v1DeclareOp.getBase().getType(), v1DeclareOp.getBase(), - /*component=*/"", - /*componentShape=*/mlir::Value{}, triplets, - /*substring=*/mlir::ValueRange{}, /*complexPartAttr=*/std::nullopt, - shape, lenParamsLeft); - auto left = hlfir::Entity{leftDesignate.getResult()}; - - llvm::SmallVector<mlir::Value> lenParamsRight; - auto rightEntity = hlfir::Entity{v2DeclareOp.getBase()}; - hlfir::genLengthParameters(loc, builder, rightEntity, lenParamsLeft); - auto rightDesignate = hlfir::DesignateOp::create( - builder, loc, v2DeclareOp.getBase().getType(), v2DeclareOp.getBase(), - /*component=*/"", - /*componentShape=*/mlir::Value{}, triplets, - /*substring=*/mlir::ValueRange{}, /*complexPartAttr=*/std::nullopt, - shape, lenParamsRight); - auto right = hlfir::Entity{rightDesignate.getResult()}; - - llvm::SmallVector<mlir::Value, 1> typeParams; - auto genKernel = [&builder, &loc, op, seqTy, &left, &right]( - mlir::Location l, fir::FirOpBuilder &b, - mlir::ValueRange oneBasedIndices) -> hlfir::Entity { - auto leftElement = hlfir::getElementAt(l, b, left, oneBasedIndices); - auto rightElement = hlfir::getElementAt(l, b, right, oneBasedIndices); - auto leftVal = hlfir::loadTrivialScalar(l, b, leftElement); - auto rightVal = hlfir::loadTrivialScalar(l, b, rightElement); - return hlfir::Entity{genScalarCombiner( - builder, loc, op, seqTy.getEleTy(), leftVal, rightVal)}; - }; - mlir::Value elemental = hlfir::genElementalOp( - loc, builder, seqTy.getEleTy(), shape, typeParams, genKernel, - /*isUnordered=*/true); - hlfir::AssignOp::create(builder, loc, elemental, v1DeclareOp.getBase()); - return; - } - if (bounds.empty()) { - llvm::SmallVector<mlir::Value> extents; - mlir::Type idxTy = builder.getIndexType(); - for (auto extent : llvm::reverse(seqTy.getShape())) { - mlir::Value lb = mlir::arith::ConstantOp::create( - builder, loc, idxTy, builder.getIntegerAttr(idxTy, 0)); - mlir::Value ub = mlir::arith::ConstantOp::create( - builder, loc, idxTy, builder.getIntegerAttr(idxTy, extent - 1)); - mlir::Value step = mlir::arith::ConstantOp::create( - builder, loc, idxTy, builder.getIntegerAttr(idxTy, 1)); - auto loop = fir::DoLoopOp::create(builder, loc, lb, ub, step, - /*unordered=*/false); - builder.setInsertionPointToStart(loop.getBody()); - loops.push_back(loop); - ivs.push_back(loop.getInductionVar()); - } - } else if (allConstantBound) { - // Use the constant bound directly in the combiner region so they do not - // need to be passed as block argument. - assert(!bounds.empty() && - "seq type with constant bounds cannot have empty bounds"); - for (auto bound : llvm::reverse(bounds)) { - auto dataBound = - mlir::dyn_cast<mlir::acc::DataBoundsOp>(bound.getDefiningOp()); - llvm::SmallVector<mlir::Value> values = - genConstantBounds(builder, loc, dataBound); - auto loop = - fir::DoLoopOp::create(builder, loc, values[0], values[1], values[2], - /*unordered=*/false); - builder.setInsertionPointToStart(loop.getBody()); - loops.push_back(loop); - ivs.push_back(loop.getInductionVar()); - } - } else { - // Lowerbound, upperbound and step are passed as block arguments. - unsigned nbRangeArgs = - recipe.getCombinerRegion().getArguments().size() - 2; - assert((nbRangeArgs / 3 == seqTy.getDimension()) && - "Expect 3 block arguments per dimension"); - for (int i = nbRangeArgs - 1; i >= 2; i -= 3) { - mlir::Value lb = recipe.getCombinerRegion().getArgument(i); - mlir::Value ub = recipe.getCombinerRegion().getArgument(i + 1); - mlir::Value step = recipe.getCombinerRegion().getArgument(i + 2); - auto loop = fir::DoLoopOp::create(builder, loc, lb, ub, step, - /*unordered=*/false); - builder.setInsertionPointToStart(loop.getBody()); - loops.push_back(loop); - ivs.push_back(loop.getInductionVar()); - } - } - llvm::SmallVector<mlir::Value> reversedIvs(ivs.rbegin(), ivs.rend()); - auto addr1 = - fir::CoordinateOp::create(builder, loc, refTy, value1, reversedIvs); - auto addr2 = - fir::CoordinateOp::create(builder, loc, refTy, value2, reversedIvs); - auto load1 = fir::LoadOp::create(builder, loc, addr1); - auto load2 = fir::LoadOp::create(builder, loc, addr2); - mlir::Value res = - genScalarCombiner(builder, loc, op, seqTy.getEleTy(), load1, load2); - fir::StoreOp::create(builder, loc, res, addr1); - builder.setInsertionPointAfter(loops[0]); - } else if (auto boxTy = mlir::dyn_cast<fir::BaseBoxType>(ty)) { - mlir::Type innerTy = fir::unwrapRefType(boxTy.getEleTy()); - if (fir::isa_trivial(innerTy)) { - mlir::Value boxAddr1 = value1, boxAddr2 = value2; - if (fir::isBoxAddress(boxAddr1.getType())) - boxAddr1 = fir::LoadOp::create(builder, loc, boxAddr1); - if (fir::isBoxAddress(boxAddr2.getType())) - boxAddr2 = fir::LoadOp::create(builder, loc, boxAddr2); - boxAddr1 = fir::BoxAddrOp::create(builder, loc, boxAddr1); - boxAddr2 = fir::BoxAddrOp::create(builder, loc, boxAddr2); - auto leftEntity = hlfir::Entity{boxAddr1}; - auto rightEntity = hlfir::Entity{boxAddr2}; - - auto leftVal = hlfir::loadTrivialScalar(loc, builder, leftEntity); - auto rightVal = hlfir::loadTrivialScalar(loc, builder, rightEntity); - mlir::Value res = - genScalarCombiner(builder, loc, op, innerTy, leftVal, rightVal); - hlfir::AssignOp::create(builder, loc, res, boxAddr1); - } else { - mlir::Type innerTy = fir::extractSequenceType(boxTy); - fir::SequenceType seqTy = - mlir::dyn_cast_or_null<fir::SequenceType>(innerTy); - if (!seqTy) - TODO(loc, "Unsupported boxed type in OpenACC reduction combiner"); - - auto shape = - genShapeFromBoundsOrArgs(loc, builder, seqTy, bounds, - recipe.getCombinerRegion().getArguments()); - hlfir::DesignateOp::Subscripts triplets = - getSubscriptsFromArgs(recipe.getCombinerRegion().getArguments()); - auto leftEntity = hlfir::Entity{value1}; - if (fir::isBoxAddress(value1.getType())) - leftEntity = hlfir::Entity{ - fir::LoadOp::create(builder, loc, value1).getResult()}; - auto left = - genDesignateWithTriplets(builder, loc, leftEntity, triplets, shape); - auto rightEntity = hlfir::Entity{value2}; - if (fir::isBoxAddress(value2.getType())) - rightEntity = hlfir::Entity{ - fir::LoadOp::create(builder, loc, value2).getResult()}; - auto right = - genDesignateWithTriplets(builder, loc, rightEntity, triplets, shape); - - llvm::SmallVector<mlir::Value, 1> typeParams; - auto genKernel = [&builder, &loc, op, seqTy, &left, &right]( - mlir::Location l, fir::FirOpBuilder &b, - mlir::ValueRange oneBasedIndices) -> hlfir::Entity { - auto leftElement = hlfir::getElementAt(l, b, left, oneBasedIndices); - auto rightElement = hlfir::getElementAt(l, b, right, oneBasedIndices); - auto leftVal = hlfir::loadTrivialScalar(l, b, leftElement); - auto rightVal = hlfir::loadTrivialScalar(l, b, rightElement); - return hlfir::Entity{genScalarCombiner( - builder, loc, op, seqTy.getEleTy(), leftVal, rightVal)}; - }; - mlir::Value elemental = hlfir::genElementalOp( - loc, builder, seqTy.getEleTy(), shape, typeParams, genKernel, - /*isUnordered=*/true); - hlfir::AssignOp::create(builder, loc, elemental, value1); - } - } else { - mlir::Value res = genScalarCombiner(builder, loc, op, ty, value1, value2); - fir::StoreOp::create(builder, loc, res, value1); - } -} - mlir::acc::ReductionRecipeOp Fortran::lower::createOrGetReductionRecipe( fir::FirOpBuilder &builder, llvm::StringRef recipeName, mlir::Location loc, mlir::Type ty, mlir::acc::ReductionOperator op, @@ -1819,37 +1580,33 @@ mlir::acc::ReductionRecipeOp Fortran::lower::createOrGetReductionRecipe( if (auto recipe = mod.lookupSymbol<mlir::acc::ReductionRecipeOp>(recipeName)) return recipe; - auto ip = builder.saveInsertionPoint(); - + mlir::OpBuilder::InsertionGuard guard(builder); auto recipe = genRecipeOp<mlir::acc::ReductionRecipeOp>( builder, mod, recipeName, loc, ty, op); - - // The two first block arguments are the two values to be combined. - // The next arguments are the iteration ranges (lb, ub, step) to be used - // for the combiner if needed. - llvm::SmallVector<mlir::Type> argsTy{ty, ty}; - llvm::SmallVector<mlir::Location> argsLoc{loc, loc}; - bool allConstantBound = areAllBoundConstant(bounds); - if (!allConstantBound) { - for (mlir::Value bound : llvm::reverse(bounds)) { - auto dataBound = - mlir::dyn_cast<mlir::acc::DataBoundsOp>(bound.getDefiningOp()); - argsTy.push_back(dataBound.getLowerbound().getType()); - argsLoc.push_back(dataBound.getLowerbound().getLoc()); - argsTy.push_back(dataBound.getUpperbound().getType()); - argsLoc.push_back(dataBound.getUpperbound().getLoc()); - argsTy.push_back(dataBound.getStartIdx().getType()); - argsLoc.push_back(dataBound.getStartIdx().getLoc()); - } - } - builder.createBlock(&recipe.getCombinerRegion(), - recipe.getCombinerRegion().end(), argsTy, argsLoc); - builder.setInsertionPointToEnd(&recipe.getCombinerRegion().back()); - mlir::Value v1 = recipe.getCombinerRegion().front().getArgument(0); - mlir::Value v2 = recipe.getCombinerRegion().front().getArgument(1); - genCombiner(builder, loc, op, ty, v1, v2, recipe, bounds, allConstantBound); - mlir::acc::YieldOp::create(builder, loc, v1); - builder.restoreInsertionPoint(ip); + bool allConstantBound = fir::acc::areAllBoundsConstant(bounds); + + auto [dest, src] = genRecipeCombinerOrCopyRegion( + builder, loc, ty, recipe.getCombinerRegion(), bounds, allConstantBound); + // Generate loops that combine and assign the inputs into dest (or array + // section of the inputs when there are bounds). + hlfir::Entity srcSection = src; + hlfir::Entity destSection = dest; + if (!bounds.empty()) + std::tie(srcSection, destSection) = genArraySectionsInRecipe( + builder, loc, bounds, recipe.getCombinerRegion().getArguments(), + allConstantBound, srcSection, destSection); + + mlir::Type elementType = fir::getFortranElementType(ty); + auto genKernel = [&](mlir::Location l, fir::FirOpBuilder &b, + hlfir::Entity srcElementValue, + hlfir::Entity destElementValue) -> hlfir::Entity { + return hlfir::Entity{genScalarCombiner(builder, loc, op, elementType, + srcElementValue, destElementValue)}; + }; + hlfir::genNoAliasAssignment(loc, builder, srcSection, destSection, + /*emitWorkshareLoop=*/false, + /*temporaryLHS=*/false, genKernel); + mlir::acc::YieldOp::create(builder, loc, dest); return recipe; } @@ -1866,16 +1623,17 @@ static bool isSupportedReductionType(mlir::Type ty) { return fir::isa_trivial(ty); } -static void -genReductions(const Fortran::parser::AccObjectListWithReduction &objectList, - Fortran::lower::AbstractConverter &converter, - Fortran::semantics::SemanticsContext &semanticsContext, - Fortran::lower::StatementContext &stmtCtx, - llvm::SmallVectorImpl<mlir::Value> &reductionOperands, - llvm::SmallVector<mlir::Attribute> &reductionRecipes, - llvm::ArrayRef<mlir::Value> async, - llvm::ArrayRef<mlir::Attribute> asyncDeviceTypes, - llvm::ArrayRef<mlir::Attribute> asyncOnlyDeviceTypes) { +static void genReductions( + const Fortran::parser::AccObjectListWithReduction &objectList, + Fortran::lower::AbstractConverter &converter, + Fortran::semantics::SemanticsContext &semanticsContext, + Fortran::lower::StatementContext &stmtCtx, + llvm::SmallVectorImpl<mlir::Value> &reductionOperands, + llvm::ArrayRef<mlir::Value> async, + llvm::ArrayRef<mlir::Attribute> asyncDeviceTypes, + llvm::ArrayRef<mlir::Attribute> asyncOnlyDeviceTypes, + llvm::SmallVectorImpl<std::pair<mlir::Value, Fortran::semantics::SymbolRef>> + *symbolPairs = nullptr) { fir::FirOpBuilder &builder = converter.getFirOpBuilder(); const auto &objects = std::get<Fortran::parser::AccObjectList>(objectList.t); const auto &op = std::get<Fortran::parser::ReductionOperator>(objectList.t); @@ -1888,6 +1646,8 @@ genReductions(const Fortran::parser::AccObjectListWithReduction &objectList, Fortran::semantics::Symbol &symbol = getSymbolFromAccObject(accObject); Fortran::semantics::MaybeExpr designator = Fortran::common::visit( [&](auto &&s) { return ea.Analyze(s); }, accObject.u); + bool isWholeSymbol = + !designator || Fortran::evaluate::UnwrapWholeSymbolDataRef(*designator); fir::factory::AddrAndBoundsInfo info = Fortran::lower::gatherDataOperandAddrAndBounds< mlir::acc::DataBoundsOp, mlir::acc::DataBoundsType>( @@ -1911,22 +1671,24 @@ genReductions(const Fortran::parser::AccObjectListWithReduction &objectList, mlir::acc::DataClause::acc_reduction, info.addr.getType(), async, asyncDeviceTypes, asyncOnlyDeviceTypes, /*unwrapBoxAddr=*/true); mlir::Type ty = op.getAccVar().getType(); - if (!areAllBoundConstant(bounds) || + if (!fir::acc::areAllBoundsConstant(bounds) || fir::isAssumedShape(info.addr.getType()) || fir::isAllocatableOrPointerArray(info.addr.getType())) ty = info.addr.getType(); - std::string suffix = - areAllBoundConstant(bounds) ? getBoundsString(bounds) : ""; - std::string recipeName = fir::getTypeAsString( - ty, converter.getKindMap(), - ("reduction_" + stringifyReductionOperator(mlirOp)).str() + suffix); + std::string recipeName = fir::acc::getRecipeName( + mlir::acc::RecipeKind::reduction_recipe, ty, info.addr, bounds, mlirOp); mlir::acc::ReductionRecipeOp recipe = Fortran::lower::createOrGetReductionRecipe( builder, recipeName, operandLocation, ty, mlirOp, bounds); - reductionRecipes.push_back(mlir::SymbolRefAttr::get( - builder.getContext(), recipe.getSymName().str())); + op.setRecipeAttr( + mlir::SymbolRefAttr::get(builder.getContext(), recipe.getSymName())); reductionOperands.push_back(op.getAccVar()); + // Track the symbol and its corresponding mlir::Value if requested so that + // accesses inside the compute/loop regions use the acc.reduction variable. + if (symbolPairs && isWholeSymbol) + symbolPairs->emplace_back(op.getAccVar(), + Fortran::semantics::SymbolRef(symbol)); } } @@ -2138,7 +1900,6 @@ static void privatizeIv( llvm::SmallVector<mlir::Value> &privateOperands, llvm::SmallVector<std::pair<mlir::Value, Fortran::semantics::SymbolRef>> &ivPrivate, - llvm::SmallVector<mlir::Attribute> &privatizationRecipes, bool isDoConcurrent = false) { fir::FirOpBuilder &builder = converter.getFirOpBuilder(); @@ -2164,9 +1925,8 @@ static void privatizeIv( } if (privateOp == nullptr) { - std::string recipeName = - fir::getTypeAsString(ivValue.getType(), converter.getKindMap(), - Fortran::lower::privatizationRecipePrefix); + std::string recipeName = fir::acc::getRecipeName( + mlir::acc::RecipeKind::private_recipe, ivValue.getType(), ivValue, {}); auto recipe = Fortran::lower::createOrGetPrivateRecipe( builder, recipeName, loc, ivValue.getType()); @@ -2176,11 +1936,11 @@ static void privatizeIv( builder, loc, ivValue, asFortran, {}, true, /*implicit=*/true, mlir::acc::DataClause::acc_private, ivValue.getType(), /*async=*/{}, /*asyncDeviceTypes=*/{}, /*asyncOnlyDeviceTypes=*/{}); + op.setRecipeAttr( + mlir::SymbolRefAttr::get(builder.getContext(), recipe.getSymName())); privateOp = op.getOperation(); privateOperands.push_back(op.getAccVar()); - privatizationRecipes.push_back(mlir::SymbolRefAttr::get( - builder.getContext(), recipe.getSymName().str())); } ivPrivate.emplace_back(mlir::acc::getAccVar(privateOp), @@ -2251,6 +2011,49 @@ static void determineDefaultLoopParMode( } } +// Helper to visit Bounds of DO LOOP nest. +static void visitLoopControl( + Fortran::lower::AbstractConverter &converter, + const Fortran::parser::DoConstruct &outerDoConstruct, + uint64_t loopsToProcess, Fortran::lower::pft::Evaluation &eval, + std::function<void(const Fortran::parser::LoopControl::Bounds &, + mlir::Location)> + callback) { + Fortran::lower::pft::Evaluation *crtEval = &eval.getFirstNestedEvaluation(); + for (uint64_t i = 0; i < loopsToProcess; ++i) { + const Fortran::parser::LoopControl *loopControl; + if (i == 0) { + loopControl = &*outerDoConstruct.GetLoopControl(); + mlir::Location loc = converter.genLocation( + Fortran::parser::FindSourceLocation(outerDoConstruct)); + callback(std::get<Fortran::parser::LoopControl::Bounds>(loopControl->u), + loc); + } else { + // Safely locate the next inner DoConstruct within this eval. + const Fortran::parser::DoConstruct *innerDo = nullptr; + if (crtEval && crtEval->hasNestedEvaluations()) { + for (Fortran::lower::pft::Evaluation &child : + crtEval->getNestedEvaluations()) { + if (auto *stmt = child.getIf<Fortran::parser::DoConstruct>()) { + innerDo = stmt; + // Prepare to descend for the next iteration + crtEval = &child; + break; + } + } + } + if (!innerDo) + break; // No deeper loop; stop collecting collapsed bounds. + + loopControl = &*innerDo->GetLoopControl(); + mlir::Location loc = + converter.genLocation(Fortran::parser::FindSourceLocation(*innerDo)); + callback(std::get<Fortran::parser::LoopControl::Bounds>(loopControl->u), + loc); + } + } +} + // Extract loop bounds, steps, induction variables, and privatization info // for both DO CONCURRENT and regular do loops static void processDoLoopBounds( @@ -2265,14 +2068,12 @@ static void processDoLoopBounds( llvm::SmallVector<mlir::Value> &privateOperands, llvm::SmallVector<std::pair<mlir::Value, Fortran::semantics::SymbolRef>> &ivPrivate, - llvm::SmallVector<mlir::Attribute> &privatizationRecipes, llvm::SmallVector<mlir::Type> &ivTypes, llvm::SmallVector<mlir::Location> &ivLocs, llvm::SmallVector<bool> &inclusiveBounds, llvm::SmallVector<mlir::Location> &locs, uint64_t loopsToProcess) { assert(loopsToProcess > 0 && "expect at least one loop"); locs.push_back(currentLocation); // Location of the directive - Fortran::lower::pft::Evaluation *crtEval = &eval.getFirstNestedEvaluation(); bool isDoConcurrent = outerDoConstruct.IsDoConcurrent(); if (isDoConcurrent) { @@ -2307,63 +2108,34 @@ static void processDoLoopBounds( const auto &name = std::get<Fortran::parser::Name>(control.t); privatizeIv(converter, *name.symbol, currentLocation, ivTypes, ivLocs, - privateOperands, ivPrivate, privatizationRecipes, - isDoConcurrent); + privateOperands, ivPrivate, isDoConcurrent); inclusiveBounds.push_back(true); } } else { - for (uint64_t i = 0; i < loopsToProcess; ++i) { - const Fortran::parser::LoopControl *loopControl; - if (i == 0) { - loopControl = &*outerDoConstruct.GetLoopControl(); - locs.push_back(converter.genLocation( - Fortran::parser::FindSourceLocation(outerDoConstruct))); - } else { - // Safely locate the next inner DoConstruct within this eval. - const Fortran::parser::DoConstruct *innerDo = nullptr; - if (crtEval && crtEval->hasNestedEvaluations()) { - for (Fortran::lower::pft::Evaluation &child : - crtEval->getNestedEvaluations()) { - if (auto *stmt = child.getIf<Fortran::parser::DoConstruct>()) { - innerDo = stmt; - // Prepare to descend for the next iteration - crtEval = &child; - break; - } - } - } - if (!innerDo) - break; // No deeper loop; stop collecting collapsed bounds. - - loopControl = &*innerDo->GetLoopControl(); - locs.push_back(converter.genLocation( - Fortran::parser::FindSourceLocation(*innerDo))); - } - - const Fortran::parser::LoopControl::Bounds *bounds = - std::get_if<Fortran::parser::LoopControl::Bounds>(&loopControl->u); - assert(bounds && "Expected bounds on the loop construct"); - lowerbounds.push_back(fir::getBase(converter.genExprValue( - *Fortran::semantics::GetExpr(bounds->lower), stmtCtx))); - upperbounds.push_back(fir::getBase(converter.genExprValue( - *Fortran::semantics::GetExpr(bounds->upper), stmtCtx))); - if (bounds->step) - steps.push_back(fir::getBase(converter.genExprValue( - *Fortran::semantics::GetExpr(bounds->step), stmtCtx))); - else // If `step` is not present, assume it is `1`. - steps.push_back(builder.createIntegerConstant( - currentLocation, upperbounds[upperbounds.size() - 1].getType(), 1)); - - Fortran::semantics::Symbol &ivSym = - bounds->name.thing.symbol->GetUltimate(); - privatizeIv(converter, ivSym, currentLocation, ivTypes, ivLocs, - privateOperands, ivPrivate, privatizationRecipes); - - inclusiveBounds.push_back(true); - - // crtEval already updated when descending; no blind increment here. - } + visitLoopControl( + converter, outerDoConstruct, loopsToProcess, eval, + [&](const Fortran::parser::LoopControl::Bounds &bounds, + mlir::Location loc) { + locs.push_back(loc); + lowerbounds.push_back(fir::getBase(converter.genExprValue( + *Fortran::semantics::GetExpr(bounds.lower), stmtCtx))); + upperbounds.push_back(fir::getBase(converter.genExprValue( + *Fortran::semantics::GetExpr(bounds.upper), stmtCtx))); + if (bounds.step) + steps.push_back(fir::getBase(converter.genExprValue( + *Fortran::semantics::GetExpr(bounds.step), stmtCtx))); + else // If `step` is not present, assume it is `1`. + steps.push_back(builder.createIntegerConstant( + currentLocation, upperbounds[upperbounds.size() - 1].getType(), + 1)); + Fortran::semantics::Symbol &ivSym = + bounds.name.thing.symbol->GetUltimate(); + privatizeIv(converter, ivSym, currentLocation, ivTypes, ivLocs, + privateOperands, ivPrivate); + + inclusiveBounds.push_back(true); + }); } } @@ -2499,6 +2271,32 @@ static void remapDataOperandSymbols( } } +static void privatizeInductionVariables( + Fortran::lower::AbstractConverter &converter, + mlir::Location currentLocation, + const Fortran::parser::DoConstruct &outerDoConstruct, + Fortran::lower::pft::Evaluation &eval, + llvm::SmallVector<mlir::Value> &privateOperands, + llvm::SmallVector<std::pair<mlir::Value, Fortran::semantics::SymbolRef>> + &ivPrivate, + llvm::SmallVector<mlir::Location> &locs, uint64_t loopsToProcess) { + // ivTypes and locs will be ignored since no acc.loop control arguments will + // be created. + llvm::SmallVector<mlir::Type> ivTypes; + llvm::SmallVector<mlir::Location> ivLocs; + assert(!outerDoConstruct.IsDoConcurrent() && + "do concurrent loops are not expected to contained earlty exits"); + visitLoopControl(converter, outerDoConstruct, loopsToProcess, eval, + [&](const Fortran::parser::LoopControl::Bounds &bounds, + mlir::Location loc) { + locs.push_back(loc); + Fortran::semantics::Symbol &ivSym = + bounds.name.thing.symbol->GetUltimate(); + privatizeIv(converter, ivSym, currentLocation, ivTypes, + ivLocs, privateOperands, ivPrivate); + }); +} + static mlir::acc::LoopOp buildACCLoopOp( Fortran::lower::AbstractConverter &converter, mlir::Location currentLocation, @@ -2507,7 +2305,6 @@ static mlir::acc::LoopOp buildACCLoopOp( const Fortran::parser::DoConstruct &outerDoConstruct, Fortran::lower::pft::Evaluation &eval, llvm::SmallVector<mlir::Value> &privateOperands, - llvm::SmallVector<mlir::Attribute> &privatizationRecipes, llvm::SmallVector<std::pair<mlir::Value, Fortran::semantics::SymbolRef>> &dataOperandSymbolPairs, llvm::SmallVector<mlir::Value> &gangOperands, @@ -2528,13 +2325,22 @@ static mlir::acc::LoopOp buildACCLoopOp( llvm::SmallVector<mlir::Location> locs; llvm::SmallVector<mlir::Value> lowerbounds, upperbounds, steps; - // Look at the do/do concurrent loops to extract bounds information. - processDoLoopBounds(converter, currentLocation, stmtCtx, builder, - outerDoConstruct, eval, lowerbounds, upperbounds, steps, - privateOperands, ivPrivate, privatizationRecipes, ivTypes, - ivLocs, inclusiveBounds, locs, loopsToProcess); - - // Prepare the operand segment size attribute and the operands value range. + // Look at the do/do concurrent loops to extract bounds information unless + // this loop is lowered in an unstructured fashion, in which case bounds are + // not represented on acc.loop and explicit control flow is used inside body. + if (!eval.lowerAsUnstructured()) { + processDoLoopBounds(converter, currentLocation, stmtCtx, builder, + outerDoConstruct, eval, lowerbounds, upperbounds, steps, + privateOperands, ivPrivate, ivTypes, ivLocs, + inclusiveBounds, locs, loopsToProcess); + } else { + // When the loop contains early exits, privatize induction variables, but do + // not create acc.loop bounds. The control flow of the loop will be + // generated explicitly in the acc.loop body that is just a container. + privatizeInductionVariables(converter, currentLocation, outerDoConstruct, + eval, privateOperands, ivPrivate, locs, + loopsToProcess); + } llvm::SmallVector<mlir::Value> operands; llvm::SmallVector<int32_t> operandSegments; addOperands(operands, operandSegments, lowerbounds); @@ -2563,20 +2369,36 @@ static mlir::acc::LoopOp buildACCLoopOp( // Remap symbols from data clauses to use data operation results remapDataOperandSymbols(converter, builder, loopOp, dataOperandSymbolPairs); - for (auto [arg, iv] : - llvm::zip(loopOp.getLoopRegions().front()->front().getArguments(), - ivPrivate)) { - // Store block argument to the related iv private variable. - mlir::Value privateValue = - converter.getSymbolAddress(std::get<Fortran::semantics::SymbolRef>(iv)); - fir::StoreOp::create(builder, currentLocation, arg, privateValue); + if (!eval.lowerAsUnstructured()) { + for (auto [arg, iv] : + llvm::zip(loopOp.getLoopRegions().front()->front().getArguments(), + ivPrivate)) { + // Store block argument to the related iv private variable. + mlir::Value privateValue = converter.getSymbolAddress( + std::get<Fortran::semantics::SymbolRef>(iv)); + fir::StoreOp::create(builder, currentLocation, arg, privateValue); + } + loopOp.setInclusiveUpperbound(inclusiveBounds); + } else { + loopOp.setUnstructuredAttr(builder.getUnitAttr()); } - loopOp.setInclusiveUpperbound(inclusiveBounds); - return loopOp; } +static bool hasEarlyReturn(Fortran::lower::pft::Evaluation &eval) { + bool hasReturnStmt = false; + for (auto &e : eval.getNestedEvaluations()) { + e.visit(Fortran::common::visitors{ + [&](const Fortran::parser::ReturnStmt &) { hasReturnStmt = true; }, + [&](const auto &s) {}, + }); + if (e.hasNestedEvaluations()) + hasReturnStmt = hasEarlyReturn(e); + } + return hasReturnStmt; +} + static mlir::acc::LoopOp createLoopOp( Fortran::lower::AbstractConverter &converter, mlir::Location currentLocation, @@ -2586,13 +2408,11 @@ static mlir::acc::LoopOp createLoopOp( Fortran::lower::pft::Evaluation &eval, const Fortran::parser::AccClauseList &accClauseList, std::optional<mlir::acc::CombinedConstructsType> combinedConstructs = - std::nullopt, - bool needEarlyReturnHandling = false) { + std::nullopt) { fir::FirOpBuilder &builder = converter.getFirOpBuilder(); llvm::SmallVector<mlir::Value> tileOperands, privateOperands, reductionOperands, cacheOperands, vectorOperands, workerNumOperands, gangOperands; - llvm::SmallVector<mlir::Attribute> privatizationRecipes, reductionRecipes; llvm::SmallVector<int32_t> tileOperandsSegments, gangOperandsSegments; llvm::SmallVector<int64_t> collapseValues; @@ -2719,15 +2539,16 @@ static mlir::acc::LoopOp createLoopOp( &clause.u)) { genPrivatizationRecipes<mlir::acc::PrivateRecipeOp>( privateClause->v, converter, semanticsContext, stmtCtx, - privateOperands, privatizationRecipes, /*async=*/{}, + privateOperands, /*async=*/{}, /*asyncDeviceTypes=*/{}, /*asyncOnlyDeviceTypes=*/{}, &dataOperandSymbolPairs); } else if (const auto *reductionClause = std::get_if<Fortran::parser::AccClause::Reduction>( &clause.u)) { genReductions(reductionClause->v, converter, semanticsContext, stmtCtx, - reductionOperands, reductionRecipes, /*async=*/{}, - /*asyncDeviceTypes=*/{}, /*asyncOnlyDeviceTypes=*/{}); + reductionOperands, /*async=*/{}, + /*asyncDeviceTypes=*/{}, /*asyncOnlyDeviceTypes=*/{}, + &dataOperandSymbolPairs); } else if (std::get_if<Fortran::parser::AccClause::Seq>(&clause.u)) { for (auto crtDeviceTypeAttr : crtDeviceTypes) seqDeviceTypes.push_back(crtDeviceTypeAttr); @@ -2763,7 +2584,10 @@ static mlir::acc::LoopOp createLoopOp( llvm::SmallVector<mlir::Type> retTy; mlir::Value yieldValue; - if (needEarlyReturnHandling) { + if (eval.lowerAsUnstructured() && hasEarlyReturn(eval)) { + // When there is a return statement inside the loop, add a result to the + // acc.loop that will be used in a conditional branch after the loop to + // return. mlir::Type i1Ty = builder.getI1Type(); yieldValue = builder.createIntegerConstant(currentLocation, i1Ty, 0); retTy.push_back(i1Ty); @@ -2773,9 +2597,9 @@ static mlir::acc::LoopOp createLoopOp( Fortran::lower::getLoopCountForCollapseAndTile(accClauseList); auto loopOp = buildACCLoopOp( converter, currentLocation, semanticsContext, stmtCtx, outerDoConstruct, - eval, privateOperands, privatizationRecipes, dataOperandSymbolPairs, - gangOperands, workerNumOperands, vectorOperands, tileOperands, - cacheOperands, reductionOperands, retTy, yieldValue, loopsToProcess); + eval, privateOperands, dataOperandSymbolPairs, gangOperands, + workerNumOperands, vectorOperands, tileOperands, cacheOperands, + reductionOperands, retTy, yieldValue, loopsToProcess); if (!gangDeviceTypes.empty()) loopOp.setGangAttr(builder.getArrayAttr(gangDeviceTypes)); @@ -2817,14 +2641,6 @@ static mlir::acc::LoopOp createLoopOp( if (!autoDeviceTypes.empty()) loopOp.setAuto_Attr(builder.getArrayAttr(autoDeviceTypes)); - if (!privatizationRecipes.empty()) - loopOp.setPrivatizationRecipesAttr( - mlir::ArrayAttr::get(builder.getContext(), privatizationRecipes)); - - if (!reductionRecipes.empty()) - loopOp.setReductionRecipesAttr( - mlir::ArrayAttr::get(builder.getContext(), reductionRecipes)); - if (!collapseValues.empty()) loopOp.setCollapseAttr(builder.getI64ArrayAttr(collapseValues)); if (!collapseDeviceTypes.empty()) @@ -2844,19 +2660,6 @@ static mlir::acc::LoopOp createLoopOp( return loopOp; } -static bool hasEarlyReturn(Fortran::lower::pft::Evaluation &eval) { - bool hasReturnStmt = false; - for (auto &e : eval.getNestedEvaluations()) { - e.visit(Fortran::common::visitors{ - [&](const Fortran::parser::ReturnStmt &) { hasReturnStmt = true; }, - [&](const auto &s) {}, - }); - if (e.hasNestedEvaluations()) - hasReturnStmt = hasEarlyReturn(e); - } - return hasReturnStmt; -} - static mlir::Value genACC(Fortran::lower::AbstractConverter &converter, Fortran::semantics::SemanticsContext &semanticsContext, @@ -2870,17 +2673,6 @@ genACC(Fortran::lower::AbstractConverter &converter, mlir::Location currentLocation = converter.genLocation(beginLoopDirective.source); - bool needEarlyExitHandling = false; - if (eval.lowerAsUnstructured()) { - needEarlyExitHandling = hasEarlyReturn(eval); - // If the loop is lowered in an unstructured fashion, lowering generates - // explicit control flow that duplicates the looping semantics of the - // loops. - if (!needEarlyExitHandling) - TODO(currentLocation, - "loop with early exit inside OpenACC loop construct"); - } - Fortran::lower::StatementContext stmtCtx; assert(loopDirective.v == llvm::acc::ACCD_loop && @@ -2893,8 +2685,8 @@ genACC(Fortran::lower::AbstractConverter &converter, std::get<std::optional<Fortran::parser::DoConstruct>>(loopConstruct.t); auto loopOp = createLoopOp(converter, currentLocation, semanticsContext, stmtCtx, *outerDoConstruct, eval, accClauseList, - /*combinedConstructs=*/{}, needEarlyExitHandling); - if (needEarlyExitHandling) + /*combinedConstructs=*/{}); + if (loopOp.getNumResults() == 1) return loopOp.getResult(0); return mlir::Value{}; @@ -2955,8 +2747,6 @@ static Op createComputeOp( llvm::SmallVector<mlir::Value> reductionOperands, privateOperands, firstprivateOperands; - llvm::SmallVector<mlir::Attribute> privatizationRecipes, - firstPrivatizationRecipes, reductionRecipes; // Vector to track mlir::Value results and their corresponding Fortran symbols llvm::SmallVector<std::pair<mlir::Value, Fortran::semantics::SymbolRef>> @@ -3106,8 +2896,8 @@ static Op createComputeOp( genDataOperandOperationsWithModifier<mlir::acc::CreateOp, Fortran::parser::AccClause::Copyout>( copyoutClause, converter, semanticsContext, stmtCtx, - Fortran::parser::AccDataModifier::Modifier::ReadOnly, - dataClauseOperands, mlir::acc::DataClause::acc_copyout, + Fortran::parser::AccDataModifier::Modifier::Zero, dataClauseOperands, + mlir::acc::DataClause::acc_copyout, mlir::acc::DataClause::acc_copyout_zero, async, asyncDeviceTypes, asyncOnlyDeviceTypes, /*setDeclareAttr=*/false, &dataOperandSymbolPairs); @@ -3178,15 +2968,15 @@ static Op createComputeOp( if (!combinedConstructs) genPrivatizationRecipes<mlir::acc::PrivateRecipeOp>( privateClause->v, converter, semanticsContext, stmtCtx, - privateOperands, privatizationRecipes, async, asyncDeviceTypes, - asyncOnlyDeviceTypes, &dataOperandSymbolPairs); + privateOperands, async, asyncDeviceTypes, asyncOnlyDeviceTypes, + &dataOperandSymbolPairs); } else if (const auto *firstprivateClause = std::get_if<Fortran::parser::AccClause::Firstprivate>( &clause.u)) { genPrivatizationRecipes<mlir::acc::FirstprivateRecipeOp>( firstprivateClause->v, converter, semanticsContext, stmtCtx, - firstprivateOperands, firstPrivatizationRecipes, async, - asyncDeviceTypes, asyncOnlyDeviceTypes, &dataOperandSymbolPairs); + firstprivateOperands, async, asyncDeviceTypes, asyncOnlyDeviceTypes, + &dataOperandSymbolPairs); } else if (const auto *reductionClause = std::get_if<Fortran::parser::AccClause::Reduction>( &clause.u)) { @@ -3197,8 +2987,8 @@ static Op createComputeOp( // instead. if (!combinedConstructs) { genReductions(reductionClause->v, converter, semanticsContext, stmtCtx, - reductionOperands, reductionRecipes, async, - asyncDeviceTypes, asyncOnlyDeviceTypes); + reductionOperands, async, asyncDeviceTypes, + asyncOnlyDeviceTypes, &dataOperandSymbolPairs); } else { auto crtDataStart = dataClauseOperands.size(); genDataOperandOperations<mlir::acc::CopyinOp>( @@ -3234,11 +3024,9 @@ static Op createComputeOp( } addOperand(operands, operandSegments, ifCond); addOperand(operands, operandSegments, selfCond); - if constexpr (!std::is_same_v<Op, mlir::acc::KernelsOp>) { - addOperands(operands, operandSegments, reductionOperands); - addOperands(operands, operandSegments, privateOperands); - addOperands(operands, operandSegments, firstprivateOperands); - } + addOperands(operands, operandSegments, reductionOperands); + addOperands(operands, operandSegments, privateOperands); + addOperands(operands, operandSegments, firstprivateOperands); addOperands(operands, operandSegments, dataClauseOperands); Op computeOp; @@ -3290,18 +3078,6 @@ static Op createComputeOp( if (!waitOnlyDeviceTypes.empty()) computeOp.setWaitOnlyAttr(builder.getArrayAttr(waitOnlyDeviceTypes)); - if constexpr (!std::is_same_v<Op, mlir::acc::KernelsOp>) { - if (!privatizationRecipes.empty()) - computeOp.setPrivatizationRecipesAttr( - mlir::ArrayAttr::get(builder.getContext(), privatizationRecipes)); - if (!reductionRecipes.empty()) - computeOp.setReductionRecipesAttr( - mlir::ArrayAttr::get(builder.getContext(), reductionRecipes)); - if (!firstPrivatizationRecipes.empty()) - computeOp.setFirstprivatizationRecipesAttr(mlir::ArrayAttr::get( - builder.getContext(), firstPrivatizationRecipes)); - } - if (combinedConstructs) computeOp.setCombinedAttr(builder.getUnitAttr()); @@ -3679,10 +3455,6 @@ genACC(Fortran::lower::AbstractConverter &converter, converter.genLocation(beginCombinedDirective.source); Fortran::lower::StatementContext stmtCtx; - if (eval.lowerAsUnstructured()) - TODO(currentLocation, - "loop with early exit inside OpenACC combined construct"); - if (combinedDirective.v == llvm::acc::ACCD_kernels_loop) { createComputeOp<mlir::acc::KernelsOp>( converter, currentLocation, eval, semanticsContext, stmtCtx, @@ -5014,37 +4786,8 @@ static void genACC(Fortran::lower::AbstractConverter &converter, Fortran::semantics::SemanticsContext &semanticsContext, const Fortran::parser::OpenACCCacheConstruct &cacheConstruct) { - fir::FirOpBuilder &builder = converter.getFirOpBuilder(); - auto loopOp = builder.getRegion().getParentOfType<mlir::acc::LoopOp>(); - auto crtPos = builder.saveInsertionPoint(); - if (loopOp) { - builder.setInsertionPoint(loopOp); - Fortran::lower::StatementContext stmtCtx; - llvm::SmallVector<mlir::Value> cacheOperands; - const Fortran::parser::AccObjectListWithModifier &listWithModifier = - std::get<Fortran::parser::AccObjectListWithModifier>(cacheConstruct.t); - const auto &accObjectList = - std::get<Fortran::parser::AccObjectList>(listWithModifier.t); - const auto &modifier = - std::get<std::optional<Fortran::parser::AccDataModifier>>( - listWithModifier.t); - - mlir::acc::DataClause dataClause = mlir::acc::DataClause::acc_cache; - if (modifier && - (*modifier).v == Fortran::parser::AccDataModifier::Modifier::ReadOnly) - dataClause = mlir::acc::DataClause::acc_cache_readonly; - genDataOperandOperations<mlir::acc::CacheOp>( - accObjectList, converter, semanticsContext, stmtCtx, cacheOperands, - dataClause, - /*structured=*/true, /*implicit=*/false, - /*async=*/{}, /*asyncDeviceTypes=*/{}, /*asyncOnlyDeviceTypes=*/{}, - /*setDeclareAttr*/ false); - loopOp.getCacheOperandsMutable().append(cacheOperands); - } else { - llvm::report_fatal_error( - "could not find loop to attach OpenACC cache information."); - } - builder.restoreInsertionPoint(crtPos); + mlir::Location loc = converter.genLocation(cacheConstruct.source); + TODO(loc, "OpenACC cache directive"); } mlir::Value Fortran::lower::genOpenACCConstruct( @@ -5315,7 +5058,6 @@ mlir::Operation *Fortran::lower::genOpenACCLoopFromDoConstruct( llvm::SmallVector<mlir::Value> privateOperands, gangOperands, workerNumOperands, vectorOperands, tileOperands, cacheOperands, reductionOperands; - llvm::SmallVector<mlir::Attribute> privatizationRecipes; llvm::SmallVector<mlir::Type> retTy; llvm::SmallVector<std::pair<mlir::Value, Fortran::semantics::SymbolRef>> dataOperandSymbolPairs; @@ -5327,15 +5069,9 @@ mlir::Operation *Fortran::lower::genOpenACCLoopFromDoConstruct( Fortran::lower::StatementContext stmtCtx; auto loopOp = buildACCLoopOp( converter, converter.getCurrentLocation(), semanticsContext, stmtCtx, - doConstruct, eval, privateOperands, privatizationRecipes, - dataOperandSymbolPairs, gangOperands, workerNumOperands, vectorOperands, - tileOperands, cacheOperands, reductionOperands, retTy, yieldValue, - loopsToProcess); - - fir::FirOpBuilder &builder = converter.getFirOpBuilder(); - if (!privatizationRecipes.empty()) - loopOp.setPrivatizationRecipesAttr(mlir::ArrayAttr::get( - converter.getFirOpBuilder().getContext(), privatizationRecipes)); + doConstruct, eval, privateOperands, dataOperandSymbolPairs, gangOperands, + workerNumOperands, vectorOperands, tileOperands, cacheOperands, + reductionOperands, retTy, yieldValue, loopsToProcess); // Normal do loops which are not annotated with `acc loop` should be // left for analysis by marking with `auto`. This is the case even in the case @@ -5349,8 +5085,9 @@ mlir::Operation *Fortran::lower::genOpenACCLoopFromDoConstruct( // So this means that in all cases we mark with `auto` unless it is a // `do concurrent` in an `acc parallel` construct or it must be `seq` because // it is in an `acc serial` construct. + fir::FirOpBuilder &builder = converter.getFirOpBuilder(); mlir::Operation *accRegionOp = - mlir::acc::getEnclosingComputeOp(converter.getFirOpBuilder().getRegion()); + mlir::acc::getEnclosingComputeOp(builder.getRegion()); mlir::acc::LoopParMode parMode = mlir::isa_and_present<mlir::acc::ParallelOp>(accRegionOp) && doConstruct.IsDoConcurrent() diff --git a/flang/lib/Lower/OpenMP/ClauseProcessor.cpp b/flang/lib/Lower/OpenMP/ClauseProcessor.cpp index 1c163e6..a81ba37 100644 --- a/flang/lib/Lower/OpenMP/ClauseProcessor.cpp +++ b/flang/lib/Lower/OpenMP/ClauseProcessor.cpp @@ -13,10 +13,12 @@ #include "ClauseProcessor.h" #include "Utils.h" +#include "flang/Lower/ConvertCall.h" #include "flang/Lower/ConvertExprToHLFIR.h" #include "flang/Lower/OpenMP/Clauses.h" #include "flang/Lower/PFTBuilder.h" #include "flang/Lower/Support/ReductionProcessor.h" +#include "flang/Optimizer/Dialect/FIRType.h" #include "flang/Parser/tools.h" #include "flang/Semantics/tools.h" #include "flang/Utils/OpenMP.h" @@ -42,15 +44,6 @@ mlir::omp::ReductionModifier translateReductionModifier(ReductionModifier mod) { return mlir::omp::ReductionModifier::defaultmod; } -/// Check for unsupported map operand types. -static void checkMapType(mlir::Location location, mlir::Type type) { - if (auto refType = mlir::dyn_cast<fir::ReferenceType>(type)) - type = refType.getElementType(); - if (auto boxType = mlir::dyn_cast_or_null<fir::BoxType>(type)) - if (!mlir::isa<fir::PointerType>(boxType.getElementType())) - TODO(location, "OMPD_target_data MapOperand BoxType"); -} - static mlir::omp::ScheduleModifier translateScheduleModifier(const omp::clause::Schedule::OrderingModifier &m) { switch (m) { @@ -209,18 +202,6 @@ getIfClauseOperand(lower::AbstractConverter &converter, ifVal); } -static void addUseDeviceClause( - lower::AbstractConverter &converter, const omp::ObjectList &objects, - llvm::SmallVectorImpl<mlir::Value> &operands, - llvm::SmallVectorImpl<const semantics::Symbol *> &useDeviceSyms) { - genObjectList(objects, converter, operands); - for (mlir::Value &operand : operands) - checkMapType(operand.getLoc(), operand.getType()); - - for (const omp::Object &object : objects) - useDeviceSyms.push_back(object.sym()); -} - //===----------------------------------------------------------------------===// // ClauseProcessor unique clauses //===----------------------------------------------------------------------===// @@ -401,11 +382,75 @@ bool ClauseProcessor::processInclusive( return false; } +bool ClauseProcessor::processInitializer( + lower::SymMap &symMap, const parser::OmpClause::Initializer &inp, + ReductionProcessor::GenInitValueCBTy &genInitValueCB) const { + if (auto *clause = findUniqueClause<omp::clause::Initializer>()) { + genInitValueCB = [&, clause](fir::FirOpBuilder &builder, mlir::Location loc, + mlir::Type type, mlir::Value ompOrig) { + lower::SymMapScope scope(symMap); + const parser::OmpInitializerExpression &iexpr = inp.v.v; + const parser::OmpStylizedInstance &styleInstance = iexpr.v.front(); + const std::list<parser::OmpStylizedDeclaration> &declList = + std::get<std::list<parser::OmpStylizedDeclaration>>(styleInstance.t); + mlir::Value ompPrivVar; + for (const parser::OmpStylizedDeclaration &decl : declList) { + auto &name = std::get<parser::ObjectName>(decl.var.t); + assert(name.symbol && "Name does not have a symbol"); + mlir::Value addr = builder.createTemporary(loc, ompOrig.getType()); + fir::StoreOp::create(builder, loc, ompOrig, addr); + fir::FortranVariableFlagsEnum extraFlags = {}; + fir::FortranVariableFlagsAttr attributes = + Fortran::lower::translateSymbolAttributes(builder.getContext(), + *name.symbol, extraFlags); + auto declareOp = hlfir::DeclareOp::create( + builder, loc, addr, name.ToString(), nullptr, {}, nullptr, nullptr, + 0, attributes); + if (name.ToString() == "omp_priv") + ompPrivVar = declareOp.getResult(0); + symMap.addVariableDefinition(*name.symbol, declareOp); + } + // Lower the expression/function call + lower::StatementContext stmtCtx; + mlir::Value result = common::visit( + common::visitors{ + [&](const evaluate::ProcedureRef &procRef) -> mlir::Value { + convertCallToHLFIR(loc, converter, procRef, std::nullopt, + symMap, stmtCtx); + auto privVal = fir::LoadOp::create(builder, loc, ompPrivVar); + return privVal; + }, + [&](const auto &expr) -> mlir::Value { + mlir::Value exprResult = fir::getBase(convertExprToValue( + loc, converter, clause->v, symMap, stmtCtx)); + // Conversion can either give a value or a refrence to a value, + // we need to return the reduction type, so an optional load may + // be generated. + if (auto refType = llvm::dyn_cast<fir::ReferenceType>( + exprResult.getType())) + if (ompPrivVar.getType() == refType) + exprResult = fir::LoadOp::create(builder, loc, exprResult); + return exprResult; + }}, + clause->v.u); + stmtCtx.finalizeAndPop(); + return result; + }; + return true; + } + return false; +} + bool ClauseProcessor::processMergeable( mlir::omp::MergeableClauseOps &result) const { return markClauseOccurrence<omp::clause::Mergeable>(result.mergeable); } +bool ClauseProcessor::processNogroup( + mlir::omp::NogroupClauseOps &result) const { + return markClauseOccurrence<omp::clause::Nogroup>(result.nogroup); +} + bool ClauseProcessor::processNowait(mlir::omp::NowaitClauseOps &result) const { return markClauseOccurrence<omp::clause::Nowait>(result.nowait); } @@ -1159,14 +1204,26 @@ bool ClauseProcessor::processInReduction( } bool ClauseProcessor::processIsDevicePtr( - mlir::omp::IsDevicePtrClauseOps &result, + lower::StatementContext &stmtCtx, mlir::omp::IsDevicePtrClauseOps &result, llvm::SmallVectorImpl<const semantics::Symbol *> &isDeviceSyms) const { - return findRepeatableClause<omp::clause::IsDevicePtr>( - [&](const omp::clause::IsDevicePtr &devPtrClause, - const parser::CharBlock &) { - addUseDeviceClause(converter, devPtrClause.v, result.isDevicePtrVars, - isDeviceSyms); + std::map<Object, OmpMapParentAndMemberData> parentMemberIndices; + bool clauseFound = findRepeatableClause<omp::clause::IsDevicePtr>( + [&](const omp::clause::IsDevicePtr &clause, + const parser::CharBlock &source) { + mlir::Location location = converter.genLocation(source); + // Force a map so the descriptor is materialized on the device with the + // device address inside. + mlir::omp::ClauseMapFlags mapTypeBits = + mlir::omp::ClauseMapFlags::is_device_ptr | + mlir::omp::ClauseMapFlags::to; + processMapObjects(stmtCtx, location, clause.v, mapTypeBits, + parentMemberIndices, result.isDevicePtrVars, + isDeviceSyms); }); + + insertChildMapInfoIntoParent(converter, semaCtx, stmtCtx, parentMemberIndices, + result.isDevicePtrVars, isDeviceSyms); + return clauseFound; } bool ClauseProcessor::processLinear(mlir::omp::LinearClauseOps &result) const { @@ -1175,11 +1232,20 @@ bool ClauseProcessor::processLinear(mlir::omp::LinearClauseOps &result) const { omp::clause::Linear>([&](const omp::clause::Linear &clause, const parser::CharBlock &) { auto &objects = std::get<omp::ObjectList>(clause.t); + static std::vector<mlir::Attribute> typeAttrs; + + if (!result.linearVars.size()) + typeAttrs.clear(); + for (const omp::Object &object : objects) { semantics::Symbol *sym = object.sym(); const mlir::Value variable = converter.getSymbolAddress(*sym); result.linearVars.push_back(variable); + mlir::Type ty = converter.genType(*sym); + typeAttrs.push_back(mlir::TypeAttr::get(ty)); } + result.linearVarTypes = + mlir::ArrayAttr::get(&converter.getMLIRContext(), typeAttrs); if (objects.size()) { if (auto &mod = std::get<std::optional<omp::clause::Linear::StepComplexModifier>>( @@ -1223,26 +1289,67 @@ void ClauseProcessor::processMapObjects( llvm::StringRef mapperIdNameRef) const { fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); - auto getDefaultMapperID = [&](const omp::Object &object, - std::string &mapperIdName) { - if (!mlir::isa<mlir::omp::DeclareMapperOp>( - firOpBuilder.getRegion().getParentOp())) { - const semantics::DerivedTypeSpec *typeSpec = nullptr; + auto getSymbolDerivedType = [](const semantics::Symbol &symbol) + -> const semantics::DerivedTypeSpec * { + const semantics::Symbol &ultimate = symbol.GetUltimate(); + if (const semantics::DeclTypeSpec *declType = ultimate.GetType()) + if (const auto *derived = declType->AsDerived()) + return derived; + return nullptr; + }; + + auto addImplicitMapper = [&](const omp::Object &object, + std::string &mapperIdName, + bool allowGenerate) -> mlir::FlatSymbolRefAttr { + if (mapperIdName.empty()) + return mlir::FlatSymbolRefAttr(); - if (object.sym()->owner().IsDerivedType()) - typeSpec = object.sym()->owner().derivedTypeSpec(); - else if (object.sym()->GetType() && - object.sym()->GetType()->category() == - semantics::DeclTypeSpec::TypeDerived) - typeSpec = &object.sym()->GetType()->derivedTypeSpec(); - - if (typeSpec) { - mapperIdName = - typeSpec->name().ToString() + llvm::omp::OmpDefaultMapperName; - if (auto *sym = converter.getCurrentScope().FindSymbol(mapperIdName)) - mapperIdName = converter.mangleName(mapperIdName, sym->owner()); - } + if (converter.getModuleOp().lookupSymbol(mapperIdName)) + return mlir::FlatSymbolRefAttr::get(&converter.getMLIRContext(), + mapperIdName); + + if (!allowGenerate) + return mlir::FlatSymbolRefAttr(); + + const semantics::DerivedTypeSpec *typeSpec = + getSymbolDerivedType(*object.sym()); + if (!typeSpec && object.sym()->owner().IsDerivedType()) + typeSpec = object.sym()->owner().derivedTypeSpec(); + + if (!typeSpec) + return mlir::FlatSymbolRefAttr(); + + mlir::Type type = converter.genType(*typeSpec); + auto recordType = mlir::dyn_cast<fir::RecordType>(type); + if (!recordType) + return mlir::FlatSymbolRefAttr(); + + return getOrGenImplicitDefaultDeclareMapper(converter, clauseLocation, + recordType, mapperIdName); + }; + + auto getDefaultMapperID = + [&](const semantics::DerivedTypeSpec *typeSpec) -> std::string { + if (mlir::isa<mlir::omp::DeclareMapperOp>( + firOpBuilder.getRegion().getParentOp()) || + !typeSpec) + return {}; + + std::string mapperIdName = + typeSpec->name().ToString() + llvm::omp::OmpDefaultMapperName; + if (auto *sym = converter.getCurrentScope().FindSymbol(mapperIdName)) { + mapperIdName = + converter.mangleName(mapperIdName, sym->GetUltimate().owner()); + } else { + mapperIdName = converter.mangleName(mapperIdName, *typeSpec->GetScope()); } + + // Make sure we don't return a mapper to self. + if (auto declMapOp = mlir::dyn_cast<mlir::omp::DeclareMapperOp>( + firOpBuilder.getRegion().getParentOp())) + if (mapperIdName == declMapOp.getSymName()) + return {}; + return mapperIdName; }; // Create the mapper symbol from its name, if specified. @@ -1251,8 +1358,13 @@ void ClauseProcessor::processMapObjects( mapperIdNameRef != "__implicit_mapper") { std::string mapperIdName = mapperIdNameRef.str(); const omp::Object &object = objects.front(); - if (mapperIdNameRef == "default") - getDefaultMapperID(object, mapperIdName); + if (mapperIdNameRef == "default") { + const semantics::DerivedTypeSpec *typeSpec = + getSymbolDerivedType(*object.sym()); + if (!typeSpec && object.sym()->owner().IsDerivedType()) + typeSpec = object.sym()->owner().derivedTypeSpec(); + mapperIdName = getDefaultMapperID(typeSpec); + } assert(converter.getModuleOp().lookupSymbol(mapperIdName) && "mapper not found"); mapperId = @@ -1290,13 +1402,25 @@ void ClauseProcessor::processMapObjects( } } + const semantics::DerivedTypeSpec *objectTypeSpec = + getSymbolDerivedType(*object.sym()); + if (mapperIdNameRef == "__implicit_mapper") { - std::string mapperIdName; - getDefaultMapperID(object, mapperIdName); - mapperId = converter.getModuleOp().lookupSymbol(mapperIdName) - ? mlir::FlatSymbolRefAttr::get(&converter.getMLIRContext(), - mapperIdName) - : mlir::FlatSymbolRefAttr(); + if (parentObj.has_value()) { + mapperId = mlir::FlatSymbolRefAttr(); + } else if (objectTypeSpec) { + std::string mapperIdName = getDefaultMapperID(objectTypeSpec); + bool needsDefaultMapper = + semantics::IsAllocatableOrObjectPointer(object.sym()) || + requiresImplicitDefaultDeclareMapper(*objectTypeSpec); + if (!mapperIdName.empty()) + mapperId = addImplicitMapper(object, mapperIdName, + /*allowGenerate=*/needsDefaultMapper); + else + mapperId = mlir::FlatSymbolRefAttr(); + } else { + mapperId = mlir::FlatSymbolRefAttr(); + } } // Explicit map captures are captured ByRef by default, @@ -1392,10 +1516,14 @@ bool ClauseProcessor::processMap( } if (mappers) { assert(mappers->size() == 1 && "more than one mapper"); - mapperIdName = mappers->front().v.id().symbol->name().ToString(); - if (mapperIdName != "default") - mapperIdName = converter.mangleName( - mapperIdName, mappers->front().v.id().symbol->owner()); + const semantics::Symbol *mapperSym = mappers->front().v.id().symbol; + mapperIdName = mapperSym->name().ToString(); + if (mapperIdName != "default") { + // Mangle with the ultimate owner so that use-associated mapper + // identifiers resolve to the same symbol as their defining scope. + const semantics::Symbol &ultimate = mapperSym->GetUltimate(); + mapperIdName = converter.mangleName(mapperIdName, ultimate.owner()); + } } processMapObjects(stmtCtx, clauseLocation, diff --git a/flang/lib/Lower/OpenMP/ClauseProcessor.h b/flang/lib/Lower/OpenMP/ClauseProcessor.h index 6452e39..3485a4e 100644 --- a/flang/lib/Lower/OpenMP/ClauseProcessor.h +++ b/flang/lib/Lower/OpenMP/ClauseProcessor.h @@ -18,8 +18,8 @@ #include "flang/Lower/Bridge.h" #include "flang/Lower/DirectivesCommon.h" #include "flang/Lower/OpenMP/Clauses.h" +#include "flang/Lower/Support/ReductionProcessor.h" #include "flang/Optimizer/Builder/Todo.h" -#include "flang/Parser/dump-parse-tree.h" #include "flang/Parser/parse-tree.h" #include "mlir/Dialect/OpenMP/OpenMPDialect.h" @@ -88,7 +88,11 @@ public: bool processHint(mlir::omp::HintClauseOps &result) const; bool processInclusive(mlir::Location currentLocation, mlir::omp::InclusiveClauseOps &result) const; + bool processInitializer( + lower::SymMap &symMap, const parser::OmpClause::Initializer &inp, + ReductionProcessor::GenInitValueCBTy &genInitValueCB) const; bool processMergeable(mlir::omp::MergeableClauseOps &result) const; + bool processNogroup(mlir::omp::NogroupClauseOps &result) const; bool processNowait(mlir::omp::NowaitClauseOps &result) const; bool processNumTasks(lower::StatementContext &stmtCtx, mlir::omp::NumTasksClauseOps &result) const; @@ -130,7 +134,7 @@ public: mlir::Location currentLocation, mlir::omp::InReductionClauseOps &result, llvm::SmallVectorImpl<const semantics::Symbol *> &outReductionSyms) const; bool processIsDevicePtr( - mlir::omp::IsDevicePtrClauseOps &result, + lower::StatementContext &stmtCtx, mlir::omp::IsDevicePtrClauseOps &result, llvm::SmallVectorImpl<const semantics::Symbol *> &isDeviceSyms) const; bool processLinear(mlir::omp::LinearClauseOps &result) const; bool diff --git a/flang/lib/Lower/OpenMP/Clauses.cpp b/flang/lib/Lower/OpenMP/Clauses.cpp index 0f60b47..61430fc 100644 --- a/flang/lib/Lower/OpenMP/Clauses.cpp +++ b/flang/lib/Lower/OpenMP/Clauses.cpp @@ -10,7 +10,6 @@ #include "flang/Common/idioms.h" #include "flang/Evaluate/expression.h" -#include "flang/Optimizer/Builder/Todo.h" #include "flang/Parser/parse-tree.h" #include "flang/Semantics/expression.h" #include "flang/Semantics/openmp-modifiers.h" @@ -249,8 +248,10 @@ MAKE_EMPTY_CLASS(Groupprivate, Groupprivate); MAKE_INCOMPLETE_CLASS(AdjustArgs, AdjustArgs); MAKE_INCOMPLETE_CLASS(AppendArgs, AppendArgs); +MAKE_INCOMPLETE_CLASS(Collector, Collector); MAKE_INCOMPLETE_CLASS(GraphId, GraphId); MAKE_INCOMPLETE_CLASS(GraphReset, GraphReset); +MAKE_INCOMPLETE_CLASS(Inductor, Inductor); MAKE_INCOMPLETE_CLASS(Replayable, Replayable); MAKE_INCOMPLETE_CLASS(Transparent, Transparent); @@ -394,8 +395,6 @@ makePrescriptiveness(parser::OmpPrescriptiveness::Value v) { switch (v) { case parser::OmpPrescriptiveness::Value::Strict: return clause::Prescriptiveness::Strict; - case parser::OmpPrescriptiveness::Value::Fallback: - return clause::Prescriptiveness::Fallback; } llvm_unreachable("Unexpected prescriptiveness"); } @@ -797,21 +796,31 @@ DynGroupprivate make(const parser::OmpClause::DynGroupprivate &inp, semantics::SemanticsContext &semaCtx) { // imp.v -> OmpDyngroupprivateClause CLAUSET_ENUM_CONVERT( // - convert, parser::OmpAccessGroup::Value, DynGroupprivate::AccessGroup, + makeAccessGroup, parser::OmpAccessGroup::Value, + DynGroupprivate::AccessGroup, // clang-format off MS(Cgroup, Cgroup) // clang-format on ); + CLAUSET_ENUM_CONVERT( // + makeFallback, parser::OmpFallbackModifier::Value, + DynGroupprivate::Fallback, + // clang-format off + MS(Abort, Abort) + MS(Default_Mem, Default_Mem) + MS(Null, Null) + // clang-format on + ); + auto &mods = semantics::OmpGetModifiers(inp.v); auto *m0 = semantics::OmpGetUniqueModifier<parser::OmpAccessGroup>(mods); - auto *m1 = semantics::OmpGetUniqueModifier<parser::OmpPrescriptiveness>(mods); + auto *m1 = semantics::OmpGetUniqueModifier<parser::OmpFallbackModifier>(mods); auto &size = std::get<parser::ScalarIntExpr>(inp.v.t); - return DynGroupprivate{ - {/*AccessGroup=*/maybeApplyToV(convert, m0), - /*Prescriptiveness=*/maybeApplyToV(makePrescriptiveness, m1), - /*Size=*/makeExpr(size, semaCtx)}}; + return DynGroupprivate{{/*AccessGroup=*/maybeApplyToV(makeAccessGroup, m0), + /*Fallback=*/maybeApplyToV(makeFallback, m1), + /*Size=*/makeExpr(size, semaCtx)}}; } Enter make(const parser::OmpClause::Enter &inp, @@ -972,7 +981,22 @@ Init make(const parser::OmpClause::Init &inp, Initializer make(const parser::OmpClause::Initializer &inp, semantics::SemanticsContext &semaCtx) { - llvm_unreachable("Empty: initializer"); + const parser::OmpInitializerExpression &iexpr = inp.v.v; + const parser::OmpStylizedInstance &styleInstance = iexpr.v.front(); + const parser::OmpStylizedInstance::Instance &instance = + std::get<parser::OmpStylizedInstance::Instance>(styleInstance.t); + if (const auto *as = std::get_if<parser::AssignmentStmt>(&instance.u)) { + auto &expr = std::get<parser::Expr>(as->t); + return Initializer{makeExpr(expr, semaCtx)}; + } else if (const auto *call = std::get_if<parser::CallStmt>(&instance.u)) { + if (call->typedCall) { + const auto &procRef = *call->typedCall; + semantics::SomeExpr evalProcRef{procRef}; + return Initializer{evalProcRef}; + } + } + + llvm_unreachable("Unexpected initializer"); } InReduction make(const parser::OmpClause::InReduction &inp, @@ -1052,7 +1076,7 @@ Link make(const parser::OmpClause::Link &inp, return Link{/*List=*/makeObjects(inp.v, semaCtx)}; } -LoopRange make(const parser::OmpClause::Looprange &inp, +Looprange make(const parser::OmpClause::Looprange &inp, semantics::SemanticsContext &semaCtx) { llvm_unreachable("Unimplemented: looprange"); } diff --git a/flang/lib/Lower/OpenMP/DataSharingProcessor.cpp b/flang/lib/Lower/OpenMP/DataSharingProcessor.cpp index 146a252..83c2eda 100644 --- a/flang/lib/Lower/OpenMP/DataSharingProcessor.cpp +++ b/flang/lib/Lower/OpenMP/DataSharingProcessor.cpp @@ -342,7 +342,8 @@ void DataSharingProcessor::insertLastPrivateCompare(mlir::Operation *op) { if (!hasLastPrivate) return; - if (mlir::isa<mlir::omp::WsloopOp>(op) || mlir::isa<mlir::omp::SimdOp>(op)) { + if (mlir::isa<mlir::omp::WsloopOp>(op) || mlir::isa<mlir::omp::SimdOp>(op) || + mlir::isa<mlir::omp::TaskloopOp>(op)) { mlir::omp::LoopRelatedClauseOps result; llvm::SmallVector<const semantics::Symbol *> iv; collectLoopRelatedInfo(converter, converter.getCurrentLocation(), eval, @@ -408,7 +409,7 @@ void DataSharingProcessor::insertLastPrivateCompare(mlir::Operation *op) { } else { TODO(converter.getCurrentLocation(), "lastprivate clause in constructs other than " - "simd/worksharing-loop"); + "simd/worksharing-loop/taskloop"); } } diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp index 7106728..9c25c19 100644 --- a/flang/lib/Lower/OpenMP/OpenMP.cpp +++ b/flang/lib/Lower/OpenMP/OpenMP.cpp @@ -18,12 +18,17 @@ #include "Decomposer.h" #include "Utils.h" #include "flang/Common/idioms.h" +#include "flang/Evaluate/type.h" #include "flang/Lower/Bridge.h" +#include "flang/Lower/ConvertCall.h" #include "flang/Lower/ConvertExpr.h" +#include "flang/Lower/ConvertExprToHLFIR.h" #include "flang/Lower/ConvertVariable.h" #include "flang/Lower/DirectivesCommon.h" #include "flang/Lower/OpenMP/Clauses.h" +#include "flang/Lower/PFTBuilder.h" #include "flang/Lower/StatementContext.h" +#include "flang/Lower/Support/ReductionProcessor.h" #include "flang/Lower/SymbolMap.h" #include "flang/Optimizer/Builder/BoxValue.h" #include "flang/Optimizer/Builder/FIRBuilder.h" @@ -565,14 +570,9 @@ getCollapsedLoopEval(lower::pft::Evaluation &eval, int collapseValue) { if (collapseValue == 0) return &eval; - lower::pft::Evaluation *curEval = &eval.getFirstNestedEvaluation(); - for (int i = 1; i < collapseValue; i++) { - // The nested evaluations should be DoConstructs (i.e. they should form - // a loop nest). Each DoConstruct is a tuple <NonLabelDoStmt, Block, - // EndDoStmt>. - assert(curEval->isA<parser::DoConstruct>()); - curEval = &*std::next(curEval->getNestedEvaluations().begin()); - } + lower::pft::Evaluation *curEval = &eval; + for (int i = 0; i < collapseValue; i++) + curEval = getNestedDoConstruct(*curEval); return curEval; } @@ -1008,9 +1008,7 @@ getImplicitMapTypeAndKind(fir::FirOpBuilder &firOpBuilder, mlir::omp::VariableCaptureKind::ByRef); break; case DefMap::ImplicitBehavior::Firstprivate: - case DefMap::ImplicitBehavior::None: - TODO(loc, "Firstprivate and None are currently unsupported defaultmap " - "behaviour"); + TODO(loc, "Firstprivate is currently unsupported defaultmap behaviour"); break; case DefMap::ImplicitBehavior::From: return std::make_pair(mapFlag |= mlir::omp::ClauseMapFlags::from, @@ -1032,8 +1030,9 @@ getImplicitMapTypeAndKind(fir::FirOpBuilder &firOpBuilder, mlir::omp::VariableCaptureKind::ByRef); break; case DefMap::ImplicitBehavior::Default: + case DefMap::ImplicitBehavior::None: llvm_unreachable( - "Implicit None Behaviour Should Have Been Handled Earlier"); + "Implicit None and Default behaviour should have been handled earlier"); break; } @@ -1203,7 +1202,7 @@ static void createBodyOfOp(mlir::Operation &op, const OpWithBodyGenInfo &info, // Start with privatization, so that the lowering of the nested // code will use the right symbols. bool isLoop = llvm::omp::getDirectiveAssociation(info.dir) == - llvm::omp::Association::Loop; + llvm::omp::Association::LoopNest; bool privatize = info.clauses && info.privatize; firOpBuilder.setInsertionPoint(marker); @@ -1637,8 +1636,7 @@ static void genSimdClauses( cp.processReduction(loc, clauseOps, reductionSyms); cp.processSafelen(clauseOps); cp.processSimdlen(clauseOps); - - cp.processTODO<clause::Linear>(loc, llvm::omp::Directive::OMPD_simd); + cp.processLinear(clauseOps); } static void genSingleClauses(lower::AbstractConverter &converter, @@ -1673,7 +1671,7 @@ static void genTargetClauses( hostEvalInfo->collectValues(clauseOps.hostEvalVars); } cp.processIf(llvm::omp::Directive::OMPD_target, clauseOps); - cp.processIsDevicePtr(clauseOps, isDevicePtrSyms); + cp.processIsDevicePtr(stmtCtx, clauseOps, isDevicePtrSyms); cp.processMap(loc, stmtCtx, clauseOps, llvm::omp::Directive::OMPD_unknown, &mapSyms); cp.processNowait(clauseOps); @@ -1763,21 +1761,25 @@ static void genTaskgroupClauses( cp.processTaskReduction(loc, clauseOps, taskReductionSyms); } -static void genTaskloopClauses(lower::AbstractConverter &converter, - semantics::SemanticsContext &semaCtx, - lower::StatementContext &stmtCtx, - const List<Clause> &clauses, mlir::Location loc, - mlir::omp::TaskloopOperands &clauseOps) { +static void genTaskloopClauses( + lower::AbstractConverter &converter, semantics::SemanticsContext &semaCtx, + lower::StatementContext &stmtCtx, const List<Clause> &clauses, + mlir::Location loc, mlir::omp::TaskloopOperands &clauseOps, + llvm::SmallVectorImpl<const semantics::Symbol *> &reductionSyms, + llvm::SmallVectorImpl<const semantics::Symbol *> &inReductionSyms) { ClauseProcessor cp(converter, semaCtx, clauses); + cp.processAllocate(clauseOps); + cp.processFinal(stmtCtx, clauseOps); cp.processGrainsize(stmtCtx, clauseOps); + cp.processIf(llvm::omp::Directive::OMPD_taskloop, clauseOps); + cp.processInReduction(loc, clauseOps, inReductionSyms); + cp.processMergeable(clauseOps); + cp.processNogroup(clauseOps); cp.processNumTasks(stmtCtx, clauseOps); - - cp.processTODO<clause::Allocate, clause::Collapse, clause::Default, - clause::Final, clause::If, clause::InReduction, - clause::Lastprivate, clause::Mergeable, clause::Nogroup, - clause::Priority, clause::Reduction, clause::Shared, - clause::Untied>(loc, llvm::omp::Directive::OMPD_taskloop); + cp.processPriority(stmtCtx, clauseOps); + cp.processReduction(loc, clauseOps, reductionSyms); + cp.processUntied(clauseOps); } static void genTaskwaitClauses(lower::AbstractConverter &converter, @@ -1828,9 +1830,9 @@ static void genWsloopClauses( cp.processOrdered(clauseOps); cp.processReduction(loc, clauseOps, reductionSyms); cp.processSchedule(stmtCtx, clauseOps); + cp.processLinear(clauseOps); - cp.processTODO<clause::Allocate, clause::Linear>( - loc, llvm::omp::Directive::OMPD_do); + cp.processTODO<clause::Allocate>(loc, llvm::omp::Directive::OMPD_do); } //===----------------------------------------------------------------------===// @@ -2485,13 +2487,15 @@ static bool isDuplicateMappedSymbol( const semantics::Symbol &sym, const llvm::SetVector<const semantics::Symbol *> &privatizedSyms, const llvm::SmallVectorImpl<const semantics::Symbol *> &hasDevSyms, - const llvm::SmallVectorImpl<const semantics::Symbol *> &mappedSyms) { + const llvm::SmallVectorImpl<const semantics::Symbol *> &mappedSyms, + const llvm::SmallVectorImpl<const semantics::Symbol *> &isDevicePtrSyms) { llvm::SmallVector<const semantics::Symbol *> concatSyms; concatSyms.reserve(privatizedSyms.size() + hasDevSyms.size() + - mappedSyms.size()); + mappedSyms.size() + isDevicePtrSyms.size()); concatSyms.append(privatizedSyms.begin(), privatizedSyms.end()); concatSyms.append(hasDevSyms.begin(), hasDevSyms.end()); concatSyms.append(mappedSyms.begin(), mappedSyms.end()); + concatSyms.append(isDevicePtrSyms.begin(), isDevicePtrSyms.end()); auto checkSymbol = [&](const semantics::Symbol &checkSym) { return std::any_of(concatSyms.begin(), concatSyms.end(), @@ -2531,6 +2535,38 @@ genTargetOp(lower::AbstractConverter &converter, lower::SymMap &symTable, loc, clauseOps, defaultMaps, hasDeviceAddrSyms, isDevicePtrSyms, mapSyms); + if (!isDevicePtrSyms.empty()) { + // is_device_ptr maps get duplicated so the clause and synthesized + // has_device_addr entry each own a unique MapInfoOp user, keeping + // MapInfoFinalization happy while still wiring the symbol into + // has_device_addr when the user didn’t spell it explicitly. + auto insertionPt = firOpBuilder.saveInsertionPoint(); + auto alreadyPresent = [&](const semantics::Symbol *sym) { + return llvm::any_of(hasDeviceAddrSyms, [&](const semantics::Symbol *s) { + return s && sym && s->GetUltimate() == sym->GetUltimate(); + }); + }; + + for (auto [idx, sym] : llvm::enumerate(isDevicePtrSyms)) { + mlir::Value mapVal = clauseOps.isDevicePtrVars[idx]; + assert(sym && "expected symbol for is_device_ptr"); + assert(mapVal && "expected map value for is_device_ptr"); + auto mapInfo = mapVal.getDefiningOp<mlir::omp::MapInfoOp>(); + assert(mapInfo && "expected map info op"); + + if (!alreadyPresent(sym)) { + clauseOps.hasDeviceAddrVars.push_back(mapVal); + hasDeviceAddrSyms.push_back(sym); + } + + firOpBuilder.setInsertionPointAfter(mapInfo); + mlir::Operation *clonedOp = firOpBuilder.clone(*mapInfo.getOperation()); + auto clonedMapInfo = mlir::cast<mlir::omp::MapInfoOp>(clonedOp); + clauseOps.isDevicePtrVars[idx] = clonedMapInfo.getResult(); + } + firOpBuilder.restoreInsertionPoint(insertionPt); + } + DataSharingProcessor dsp(converter, semaCtx, item->clauses, eval, /*shouldCollectPreDeterminedSymbols=*/ lower::omp::isLastItemInQueue(item, queue), @@ -2570,7 +2606,7 @@ genTargetOp(lower::AbstractConverter &converter, lower::SymMap &symTable, return; if (!isDuplicateMappedSymbol(sym, dsp.getAllSymbolsToPrivatize(), - hasDeviceAddrSyms, mapSyms)) { + hasDeviceAddrSyms, mapSyms, isDevicePtrSyms)) { if (const auto *details = sym.template detailsIf<semantics::HostAssocDetails>()) converter.copySymbolBinding(details->symbol(), sym); @@ -2578,18 +2614,6 @@ genTargetOp(lower::AbstractConverter &converter, lower::SymMap &symTable, fir::ExtendedValue dataExv = converter.getSymbolExtendedValue(sym); name << sym.name().ToString(); - mlir::FlatSymbolRefAttr mapperId; - if (sym.GetType()->category() == semantics::DeclTypeSpec::TypeDerived) { - auto &typeSpec = sym.GetType()->derivedTypeSpec(); - std::string mapperIdName = - typeSpec.name().ToString() + llvm::omp::OmpDefaultMapperName; - if (auto *sym = converter.getCurrentScope().FindSymbol(mapperIdName)) - mapperIdName = converter.mangleName(mapperIdName, sym->owner()); - if (converter.getModuleOp().lookupSymbol(mapperIdName)) - mapperId = mlir::FlatSymbolRefAttr::get(&converter.getMLIRContext(), - mapperIdName); - } - fir::factory::AddrAndBoundsInfo info = Fortran::lower::getDataOperandBaseAddr( converter, firOpBuilder, sym.GetUltimate(), @@ -2609,6 +2633,44 @@ genTargetOp(lower::AbstractConverter &converter, lower::SymMap &symTable, mapFlagAndKind = getImplicitMapTypeAndKind( firOpBuilder, converter, defaultMaps, eleType, loc, sym); + mlir::FlatSymbolRefAttr mapperId; + if (defaultMaps.empty()) { + // TODO: Honor user-provided defaultmap clauses (aggregates/pointers) + // instead of blanket-disabling implicit mapper generation whenever any + // explicit default map is present. + const semantics::DerivedTypeSpec *typeSpec = + sym.GetType() ? sym.GetType()->AsDerived() : nullptr; + if (typeSpec) { + std::string mapperIdName = + typeSpec->name().ToString() + llvm::omp::OmpDefaultMapperName; + if (auto *mapperSym = + converter.getCurrentScope().FindSymbol(mapperIdName)) + mapperIdName = converter.mangleName( + mapperIdName, mapperSym->GetUltimate().owner()); + else + mapperIdName = + converter.mangleName(mapperIdName, *typeSpec->GetScope()); + + if (!mapperIdName.empty()) { + bool allowImplicitMapper = + semantics::IsAllocatableOrObjectPointer(&sym); + bool hasDefaultMapper = + converter.getModuleOp().lookupSymbol(mapperIdName); + if (hasDefaultMapper || allowImplicitMapper) { + if (!hasDefaultMapper) { + if (auto recordType = mlir::dyn_cast_or_null<fir::RecordType>( + converter.genType(*typeSpec))) + mapperId = getOrGenImplicitDefaultDeclareMapper( + converter, loc, recordType, mapperIdName); + } else { + mapperId = mlir::FlatSymbolRefAttr::get( + &converter.getMLIRContext(), mapperIdName); + } + } + } + } + } + mlir::Value mapOp = createMapInfoOp( firOpBuilder, converter.getCurrentLocation(), baseOp, /*varPtrPtr=*/mlir::Value{}, name.str(), bounds, /*members=*/{}, @@ -2818,7 +2880,6 @@ genTeamsOp(lower::AbstractConverter &converter, lower::SymMap &symTable, // TODO: Add private syms and vars. args.reduction.syms = reductionSyms; args.reduction.vars = clauseOps.reductionVars; - return genOpWithBody<mlir::omp::TeamsOp>( OpWithBodyGenInfo(converter, symTable, semaCtx, loc, eval, llvm::omp::Directive::OMPD_teams) @@ -2979,8 +3040,11 @@ static mlir::omp::TaskloopOp genStandaloneTaskloop( lower::pft::Evaluation &eval, mlir::Location loc, const ConstructQueue &queue, ConstructQueue::const_iterator item) { mlir::omp::TaskloopOperands taskloopClauseOps; + llvm::SmallVector<const semantics::Symbol *> reductionSyms; + llvm::SmallVector<const semantics::Symbol *> inReductionSyms; + genTaskloopClauses(converter, semaCtx, stmtCtx, item->clauses, loc, - taskloopClauseOps); + taskloopClauseOps, reductionSyms, inReductionSyms); DataSharingProcessor dsp(converter, semaCtx, item->clauses, eval, /*shouldCollectPreDeterminedSymbols=*/true, enableDelayedPrivatization, symTable); @@ -2994,6 +3058,10 @@ static mlir::omp::TaskloopOp genStandaloneTaskloop( EntryBlockArgs taskloopArgs; taskloopArgs.priv.syms = dsp.getDelayedPrivSymbols(); taskloopArgs.priv.vars = taskloopClauseOps.privateVars; + taskloopArgs.reduction.syms = reductionSyms; + taskloopArgs.reduction.vars = taskloopClauseOps.reductionVars; + taskloopArgs.inReduction.syms = inReductionSyms; + taskloopArgs.inReduction.vars = taskloopClauseOps.inReductionVars; auto taskLoopOp = genWrapperOp<mlir::omp::TaskloopOp>( converter, loc, taskloopClauseOps, taskloopArgs); @@ -3246,17 +3314,12 @@ static mlir::omp::WsloopOp genCompositeDoSimd( genSimdClauses(converter, semaCtx, simdItem->clauses, loc, simdClauseOps, simdReductionSyms); - DataSharingProcessor wsloopItemDSP( - converter, semaCtx, doItem->clauses, eval, - /*shouldCollectPreDeterminedSymbols=*/false, - /*useDelayedPrivatization=*/true, symTable); + DataSharingProcessor wsloopItemDSP(converter, semaCtx, doItem->clauses, eval, + /*shouldCollectPreDeterminedSymbols=*/true, + /*useDelayedPrivatization=*/true, + symTable); wsloopItemDSP.processStep1(&wsloopClauseOps); - DataSharingProcessor simdItemDSP(converter, semaCtx, simdItem->clauses, eval, - /*shouldCollectPreDeterminedSymbols=*/true, - /*useDelayedPrivatization=*/true, symTable); - simdItemDSP.processStep1(&simdClauseOps, simdItem->id); - // Pass the innermost leaf construct's clauses because that's where COLLAPSE // is placed by construct decomposition. mlir::omp::LoopNestOperands loopNestClauseOps; @@ -3275,8 +3338,9 @@ static mlir::omp::WsloopOp genCompositeDoSimd( wsloopOp.setComposite(/*val=*/true); EntryBlockArgs simdArgs; - simdArgs.priv.syms = simdItemDSP.getDelayedPrivSymbols(); - simdArgs.priv.vars = simdClauseOps.privateVars; + // For composite 'do simd', privatization is handled by the wsloop. + // The simd does not create separate private storage for variables already + // privatized by the worksharing construct. simdArgs.reduction.syms = simdReductionSyms; simdArgs.reduction.vars = simdClauseOps.reductionVars; auto simdOp = @@ -3286,7 +3350,7 @@ static mlir::omp::WsloopOp genCompositeDoSimd( genLoopNestOp(converter, symTable, semaCtx, eval, loc, queue, simdItem, loopNestClauseOps, iv, {{wsloopOp, wsloopArgs}, {simdOp, simdArgs}}, - llvm::omp::Directive::OMPD_do_simd, simdItemDSP); + llvm::omp::Directive::OMPD_do_simd, wsloopItemDSP); return wsloopOp; } @@ -3362,7 +3426,7 @@ static void genOMPDispatch(lower::AbstractConverter &converter, }; bool loopLeaf = llvm::omp::getDirectiveAssociation(item->id) == - llvm::omp::Association::Loop; + llvm::omp::Association::LoopNest; if (loopLeaf) { symTable.pushScope(); if (genOMPCompositeDispatch(converter, symTable, stmtCtx, semaCtx, eval, @@ -3471,6 +3535,13 @@ static void genOMPDispatch(lower::AbstractConverter &converter, case llvm::omp::Directive::OMPD_tile: genTileOp(converter, symTable, stmtCtx, semaCtx, eval, loc, queue, item); break; + case llvm::omp::Directive::OMPD_fuse: { + unsigned version = semaCtx.langOptions().OpenMPVersion; + if (!semaCtx.langOptions().OpenMPSimd) + TODO(loc, "Unhandled loop directive (" + + llvm::omp::getOpenMPDirectiveName(dir, version) + ")"); + break; + } case llvm::omp::Directive::OMPD_unroll: genUnrollOp(converter, symTable, stmtCtx, semaCtx, eval, loc, queue, item); break; @@ -3503,12 +3574,12 @@ static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable, lower::pft::Evaluation &eval, const parser::OpenMPUtilityConstruct &); -static void -genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable, - semantics::SemanticsContext &semaCtx, lower::pft::Evaluation &eval, - const parser::OpenMPDeclarativeAllocate &declarativeAllocate) { +static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable, + semantics::SemanticsContext &semaCtx, + lower::pft::Evaluation &eval, + const parser::OmpAllocateDirective &allocate) { if (!semaCtx.langOptions().OpenMPSimd) - TODO(converter.getCurrentLocation(), "OpenMPDeclarativeAllocate"); + TODO(converter.getCurrentLocation(), "OmpAllocateDirective"); } static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable, @@ -3527,12 +3598,186 @@ genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable, TODO(converter.getCurrentLocation(), "OmpDeclareVariantDirective"); } +static ReductionProcessor::GenCombinerCBTy +processReductionCombiner(lower::AbstractConverter &converter, + lower::SymMap &symTable, + semantics::SemanticsContext &semaCtx, + const parser::OmpReductionSpecifier &specifier) { + ReductionProcessor::GenCombinerCBTy genCombinerCB; + const auto &combinerExpression = + std::get<std::optional<parser::OmpCombinerExpression>>(specifier.t) + .value(); + const parser::OmpStylizedInstance &combinerInstance = + combinerExpression.v.front(); + const parser::OmpStylizedInstance::Instance &instance = + std::get<parser::OmpStylizedInstance::Instance>(combinerInstance.t); + + std::optional<semantics::SomeExpr> evalExprOpt; + if (const auto *as = std::get_if<parser::AssignmentStmt>(&instance.u)) { + auto &expr = std::get<parser::Expr>(as->t); + evalExprOpt = makeExpr(expr, semaCtx); + } else if (const auto *call = std::get_if<parser::CallStmt>(&instance.u)) { + if (call->typedCall) { + const auto &procRef = *call->typedCall; + evalExprOpt = semantics::SomeExpr{procRef}; + } else { + TODO(converter.getCurrentLocation(), + "CallStmt without typedCall is not yet supported"); + } + } else { + TODO(converter.getCurrentLocation(), "Unsupported combiner instance type"); + } + + assert(evalExprOpt.has_value() && "evalExpr must be initialized"); + semantics::SomeExpr evalExpr = *evalExprOpt; + + genCombinerCB = [&, evalExpr](fir::FirOpBuilder &builder, mlir::Location loc, + mlir::Type type, mlir::Value lhs, + mlir::Value rhs, bool isByRef) { + lower::SymMapScope scope(symTable); + const std::list<parser::OmpStylizedDeclaration> &declList = + std::get<std::list<parser::OmpStylizedDeclaration>>(combinerInstance.t); + mlir::Value ompOutVar; + for (const parser::OmpStylizedDeclaration &decl : declList) { + auto &name = std::get<parser::ObjectName>(decl.var.t); + mlir::Value addr = lhs; + mlir::Type type = lhs.getType(); + bool isRhs = name.ToString() == std::string("omp_in"); + if (isRhs) { + addr = rhs; + type = rhs.getType(); + } + + assert(name.symbol && "Reduction object name does not have a symbol"); + if (!fir::conformsWithPassByRef(type)) { + addr = builder.createTemporary(loc, type); + fir::StoreOp::create(builder, loc, isRhs ? rhs : lhs, addr); + } + fir::FortranVariableFlagsEnum extraFlags = {}; + fir::FortranVariableFlagsAttr attributes = + Fortran::lower::translateSymbolAttributes(builder.getContext(), + *name.symbol, extraFlags); + auto declareOp = + hlfir::DeclareOp::create(builder, loc, addr, name.ToString(), nullptr, + {}, nullptr, nullptr, 0, attributes); + if (name.ToString() == "omp_out") + ompOutVar = declareOp.getResult(0); + symTable.addVariableDefinition(*name.symbol, declareOp); + } + + lower::StatementContext stmtCtx; + mlir::Value result = common::visit( + common::visitors{ + [&](const evaluate::ProcedureRef &procRef) -> mlir::Value { + convertCallToHLFIR(loc, converter, procRef, std::nullopt, + symTable, stmtCtx); + auto outVal = fir::LoadOp::create(builder, loc, ompOutVar); + return outVal; + }, + [&](const auto &expr) -> mlir::Value { + mlir::Value exprResult = fir::getBase(convertExprToValue( + loc, converter, evalExpr, symTable, stmtCtx)); + // Optional load may be generated if we get a reference to the + // reduction type. + if (auto refType = + llvm::dyn_cast<fir::ReferenceType>(exprResult.getType())) + if (lhs.getType() == refType.getElementType()) + exprResult = fir::LoadOp::create(builder, loc, exprResult); + return exprResult; + }}, + evalExpr.u); + stmtCtx.finalizeAndPop(); + if (isByRef) { + fir::StoreOp::create(builder, loc, result, lhs); + mlir::omp::YieldOp::create(builder, loc, lhs); + } else { + mlir::omp::YieldOp::create(builder, loc, result); + } + }; + return genCombinerCB; +} + +// Checks that the reduction type is either a trivial type or a derived type of +// trivial types. +static bool isSimpleReductionType(mlir::Type reductionType) { + if (fir::isa_trivial(reductionType)) + return true; + if (auto recordTy = mlir::dyn_cast<fir::RecordType>(reductionType)) { + for (auto [_, fieldType] : recordTy.getTypeList()) { + if (!fir::isa_trivial(fieldType)) + return false; + } + } + return true; +} + +// Getting the type from a symbol compared to a DeclSpec is simpler since we do +// not need to consider derived vs intrinsic types. Semantics is guaranteed to +// generate these symbols. +static mlir::Type +getReductionType(lower::AbstractConverter &converter, + const parser::OmpReductionSpecifier &specifier) { + const auto &combinerExpression = + std::get<std::optional<parser::OmpCombinerExpression>>(specifier.t) + .value(); + const parser::OmpStylizedInstance &combinerInstance = + combinerExpression.v.front(); + const std::list<parser::OmpStylizedDeclaration> &declList = + std::get<std::list<parser::OmpStylizedDeclaration>>(combinerInstance.t); + const parser::OmpStylizedDeclaration &decl = declList.front(); + const auto &name = std::get<parser::ObjectName>(decl.var.t); + const auto &symbol = semantics::SymbolRef(*name.symbol); + mlir::Type reductionType = converter.genType(symbol); + + if (!isSimpleReductionType(reductionType)) + TODO(converter.getCurrentLocation(), + "declare reduction currently only supports trival types or derived " + "types containing trivial types"); + return reductionType; +} + static void genOMP( lower::AbstractConverter &converter, lower::SymMap &symTable, semantics::SemanticsContext &semaCtx, lower::pft::Evaluation &eval, const parser::OpenMPDeclareReductionConstruct &declareReductionConstruct) { - if (!semaCtx.langOptions().OpenMPSimd) - TODO(converter.getCurrentLocation(), "OpenMPDeclareReductionConstruct"); + if (semaCtx.langOptions().OpenMPSimd) + return; + + const parser::OmpArgumentList &args{declareReductionConstruct.v.Arguments()}; + const parser::OmpArgument &arg{args.v.front()}; + const auto &specifier = std::get<parser::OmpReductionSpecifier>(arg.u); + + if (std::get<parser::OmpTypeNameList>(specifier.t).v.size() > 1) + TODO(converter.getCurrentLocation(), + "multiple types in declare reduction is not yet supported"); + + mlir::Type reductionType = getReductionType(converter, specifier); + ReductionProcessor::GenCombinerCBTy genCombinerCB = + processReductionCombiner(converter, symTable, semaCtx, specifier); + const parser::OmpClauseList &initializer = + declareReductionConstruct.v.Clauses(); + if (initializer.v.size() > 0) { + List<Clause> clauses = makeClauses(initializer, semaCtx); + ReductionProcessor::GenInitValueCBTy genInitValueCB; + ClauseProcessor cp(converter, semaCtx, clauses); + const parser::OmpClause::Initializer &iclause{ + std::get<parser::OmpClause::Initializer>(initializer.v.front().u)}; + cp.processInitializer(symTable, iclause, genInitValueCB); + const auto &identifier = + std::get<parser::OmpReductionIdentifier>(specifier.t); + const auto &designator = + std::get<parser::ProcedureDesignator>(identifier.u); + const auto &reductionName = std::get<parser::Name>(designator.u); + bool isByRef = ReductionProcessor::doReductionByRef(reductionType); + ReductionProcessor::createDeclareReductionHelper< + mlir::omp::DeclareReductionOp>( + converter, reductionName.ToString(), reductionType, + converter.getCurrentLocation(), isByRef, genCombinerCB, genInitValueCB); + } else { + TODO(converter.getCurrentLocation(), + "declare reduction without an initializer clause is not yet " + "supported"); + } } static void @@ -3543,10 +3788,10 @@ genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable, TODO(converter.getCurrentLocation(), "OpenMPDeclareSimdConstruct"); } -static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable, - semantics::SemanticsContext &semaCtx, - lower::pft::Evaluation &eval, - const parser::OpenMPDeclareMapperConstruct &construct) { +static void genOpenMPDeclareMapperImpl( + lower::AbstractConverter &converter, semantics::SemanticsContext &semaCtx, + const parser::OpenMPDeclareMapperConstruct &construct, + const semantics::Symbol *mapperSymOpt = nullptr) { mlir::Location loc = converter.genLocation(construct.source); fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); const parser::OmpArgumentList &args = construct.v.Arguments(); @@ -3562,8 +3807,17 @@ static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable, "Expected derived type"); std::string mapperNameStr = mapperName; - if (auto *sym = converter.getCurrentScope().FindSymbol(mapperNameStr)) + if (mapperSymOpt && mapperNameStr != "default") { + mapperNameStr = converter.mangleName(mapperNameStr, mapperSymOpt->owner()); + } else if (auto *sym = + converter.getCurrentScope().FindSymbol(mapperNameStr)) { mapperNameStr = converter.mangleName(mapperNameStr, sym->owner()); + } + + // If the mapper op already exists (e.g., created by regular lowering or by + // materialization of imported mappers), do not recreate it. + if (converter.getModuleOp().lookupSymbol(mapperNameStr)) + return; // Save current insertion point before moving to the module scope to create // the DeclareMapperOp @@ -3586,6 +3840,13 @@ static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable, mlir::omp::DeclareMapperInfoOp::create(firOpBuilder, loc, clauseOps.mapVars); } +static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable, + semantics::SemanticsContext &semaCtx, + lower::pft::Evaluation &eval, + const parser::OpenMPDeclareMapperConstruct &construct) { + genOpenMPDeclareMapperImpl(converter, semaCtx, construct); +} + static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable, semantics::SemanticsContext &semaCtx, lower::pft::Evaluation &eval, @@ -3902,14 +4163,6 @@ static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable, static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable, semantics::SemanticsContext &semaCtx, lower::pft::Evaluation &eval, - const parser::OpenMPExecutableAllocate &execAllocConstruct) { - if (!semaCtx.langOptions().OpenMPSimd) - TODO(converter.getCurrentLocation(), "OpenMPExecutableAllocate"); -} - -static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable, - semantics::SemanticsContext &semaCtx, - lower::pft::Evaluation &eval, const parser::OpenMPLoopConstruct &loopConstruct) { const parser::OmpDirectiveSpecification &beginSpec = loopConstruct.BeginDir(); List<Clause> clauses = makeClauses(beginSpec.Clauses(), semaCtx); @@ -3918,12 +4171,9 @@ static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable, mlir::Location currentLocation = converter.genLocation(beginSpec.source); - auto &optLoopCons = - std::get<std::optional<parser::NestedConstruct>>(loopConstruct.t); - if (optLoopCons.has_value()) { - if (auto *ompNestedLoopCons{ - std::get_if<common::Indirection<parser::OpenMPLoopConstruct>>( - &*optLoopCons)}) { + for (auto &construct : std::get<parser::Block>(loopConstruct.t)) { + if (const parser::OpenMPLoopConstruct *ompNestedLoopCons = + parser::omp::GetOmpLoop(construct)) { llvm::omp::Directive nestedDirective = parser::omp::GetOmpDirectiveName(*ompNestedLoopCons).v; switch (nestedDirective) { @@ -4229,3 +4479,36 @@ void Fortran::lower::genOpenMPRequires(mlir::Operation *mod, offloadMod.setRequires(mlirFlags); } } + +// Walk scopes and materialize omp.declare_mapper ops for mapper declarations +// found in imported modules. If \p scope is null, start from the global scope. +void Fortran::lower::materializeOpenMPDeclareMappers( + Fortran::lower::AbstractConverter &converter, + semantics::SemanticsContext &semaCtx, const semantics::Scope *scope) { + const semantics::Scope &root = scope ? *scope : semaCtx.globalScope(); + + // Recurse into child scopes first (modules, submodules, etc.). + for (const semantics::Scope &child : root.children()) + materializeOpenMPDeclareMappers(converter, semaCtx, &child); + + // Only consider module scopes to avoid duplicating local constructs. + if (!root.IsModule()) + return; + + // Only materialize for modules coming from mod files to avoid duplicates. + if (!root.symbol() || !root.symbol()->test(semantics::Symbol::Flag::ModFile)) + return; + + // Scan symbols in this module scope for MapperDetails. + for (auto &it : root) { + const semantics::Symbol &sym = *it.second; + if (auto *md = sym.detailsIf<semantics::MapperDetails>()) { + for (const auto *decl : md->GetDeclList()) { + if (const auto *mapperDecl = + std::get_if<parser::OpenMPDeclareMapperConstruct>(&decl->u)) { + genOpenMPDeclareMapperImpl(converter, semaCtx, *mapperDecl, &sym); + } + } + } + } +} diff --git a/flang/lib/Lower/OpenMP/Utils.cpp b/flang/lib/Lower/OpenMP/Utils.cpp index 6487f59..a818d63 100644 --- a/flang/lib/Lower/OpenMP/Utils.cpp +++ b/flang/lib/Lower/OpenMP/Utils.cpp @@ -14,22 +14,28 @@ #include "ClauseFinder.h" #include "flang/Evaluate/fold.h" +#include "flang/Evaluate/tools.h" #include <flang/Lower/AbstractConverter.h> #include <flang/Lower/ConvertType.h> #include <flang/Lower/DirectivesCommon.h> #include <flang/Lower/OpenMP/Clauses.h> #include <flang/Lower/PFTBuilder.h> #include <flang/Lower/Support/PrivateReductionUtils.h> +#include <flang/Optimizer/Builder/BoxValue.h> #include <flang/Optimizer/Builder/FIRBuilder.h> #include <flang/Optimizer/Builder/Todo.h> +#include <flang/Optimizer/HLFIR/HLFIROps.h> #include <flang/Parser/openmp-utils.h> #include <flang/Parser/parse-tree.h> #include <flang/Parser/tools.h> #include <flang/Semantics/tools.h> #include <flang/Semantics/type.h> #include <flang/Utils/OpenMP.h> +#include <llvm/ADT/SmallPtrSet.h> +#include <llvm/ADT/StringRef.h> #include <llvm/Support/CommandLine.h> +#include <functional> #include <iterator> template <typename T> @@ -61,6 +67,142 @@ namespace Fortran { namespace lower { namespace omp { +mlir::FlatSymbolRefAttr getOrGenImplicitDefaultDeclareMapper( + lower::AbstractConverter &converter, mlir::Location loc, + fir::RecordType recordType, llvm::StringRef mapperNameStr) { + if (mapperNameStr.empty()) + return {}; + + if (converter.getModuleOp().lookupSymbol(mapperNameStr)) + return mlir::FlatSymbolRefAttr::get(&converter.getMLIRContext(), + mapperNameStr); + + fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); + mlir::OpBuilder::InsertionGuard guard(firOpBuilder); + + firOpBuilder.setInsertionPointToStart(converter.getModuleOp().getBody()); + auto declMapperOp = mlir::omp::DeclareMapperOp::create( + firOpBuilder, loc, mapperNameStr, recordType); + auto ®ion = declMapperOp.getRegion(); + firOpBuilder.createBlock(®ion); + auto mapperArg = region.addArgument(firOpBuilder.getRefType(recordType), loc); + + auto declareOp = hlfir::DeclareOp::create(firOpBuilder, loc, mapperArg, + /*uniq_name=*/""); + + const auto genBoundsOps = [&](mlir::Value mapVal, + llvm::SmallVectorImpl<mlir::Value> &bounds) { + fir::ExtendedValue extVal = + hlfir::translateToExtendedValue(mapVal.getLoc(), firOpBuilder, + hlfir::Entity{mapVal}, + /*contiguousHint=*/true) + .first; + fir::factory::AddrAndBoundsInfo info = fir::factory::getDataOperandBaseAddr( + firOpBuilder, mapVal, /*isOptional=*/false, mapVal.getLoc()); + bounds = fir::factory::genImplicitBoundsOps<mlir::omp::MapBoundsOp, + mlir::omp::MapBoundsType>( + firOpBuilder, info, extVal, + /*dataExvIsAssumedSize=*/false, mapVal.getLoc()); + }; + + const auto getFieldRef = [&](mlir::Value rec, llvm::StringRef fieldName, + mlir::Type fieldTy, mlir::Type recType) { + mlir::Value field = fir::FieldIndexOp::create( + firOpBuilder, loc, fir::FieldType::get(recType.getContext()), fieldName, + recType, fir::getTypeParams(rec)); + return fir::CoordinateOp::create( + firOpBuilder, loc, firOpBuilder.getRefType(fieldTy), rec, field); + }; + + llvm::SmallVector<mlir::Value> clauseMapVars; + llvm::SmallVector<llvm::SmallVector<int64_t>> memberPlacementIndices; + llvm::SmallVector<mlir::Value> memberMapOps; + + mlir::omp::ClauseMapFlags mapFlag = mlir::omp::ClauseMapFlags::to | + mlir::omp::ClauseMapFlags::from | + mlir::omp::ClauseMapFlags::implicit; + mlir::omp::VariableCaptureKind captureKind = + mlir::omp::VariableCaptureKind::ByRef; + + for (const auto &entry : llvm::enumerate(recordType.getTypeList())) { + const auto &memberName = entry.value().first; + const auto &memberType = entry.value().second; + mlir::FlatSymbolRefAttr mapperId; + if (auto recType = mlir::dyn_cast<fir::RecordType>( + fir::getFortranElementType(memberType))) { + std::string mapperIdName = + recType.getName().str() + llvm::omp::OmpDefaultMapperName; + if (auto *sym = converter.getCurrentScope().FindSymbol(mapperIdName)) + mapperIdName = converter.mangleName(mapperIdName, sym->owner()); + else if (auto *memberSym = + converter.getCurrentScope().FindSymbol(memberName)) + mapperIdName = converter.mangleName(mapperIdName, memberSym->owner()); + + mapperId = getOrGenImplicitDefaultDeclareMapper(converter, loc, recType, + mapperIdName); + } + + auto ref = + getFieldRef(declareOp.getBase(), memberName, memberType, recordType); + llvm::SmallVector<mlir::Value> bounds; + genBoundsOps(ref, bounds); + mlir::Value mapOp = Fortran::utils::openmp::createMapInfoOp( + firOpBuilder, loc, ref, /*varPtrPtr=*/mlir::Value{}, /*name=*/"", + bounds, + /*members=*/{}, + /*membersIndex=*/mlir::ArrayAttr{}, mapFlag, captureKind, ref.getType(), + /*partialMap=*/false, mapperId); + memberMapOps.emplace_back(mapOp); + memberPlacementIndices.emplace_back( + llvm::SmallVector<int64_t>{(int64_t)entry.index()}); + } + + llvm::SmallVector<mlir::Value> bounds; + genBoundsOps(declareOp.getOriginalBase(), bounds); + mlir::omp::ClauseMapFlags parentMapFlag = mlir::omp::ClauseMapFlags::implicit; + mlir::omp::MapInfoOp mapOp = Fortran::utils::openmp::createMapInfoOp( + firOpBuilder, loc, declareOp.getOriginalBase(), + /*varPtrPtr=*/mlir::Value(), /*name=*/"", bounds, memberMapOps, + firOpBuilder.create2DI64ArrayAttr(memberPlacementIndices), parentMapFlag, + captureKind, declareOp.getType(0), + /*partialMap=*/true); + + clauseMapVars.emplace_back(mapOp); + mlir::omp::DeclareMapperInfoOp::create(firOpBuilder, loc, clauseMapVars); + return mlir::FlatSymbolRefAttr::get(&converter.getMLIRContext(), + mapperNameStr); +} + +bool requiresImplicitDefaultDeclareMapper( + const semantics::DerivedTypeSpec &typeSpec) { + // ISO C interoperable types (e.g., c_ptr, c_funptr) must always have implicit + // default mappers available so that OpenMP offloading can correctly map them. + if (semantics::IsIsoCType(&typeSpec)) + return true; + + llvm::SmallPtrSet<const semantics::DerivedTypeSpec *, 8> visited; + + std::function<bool(const semantics::DerivedTypeSpec &)> requiresMapper = + [&](const semantics::DerivedTypeSpec &spec) -> bool { + if (!visited.insert(&spec).second) + return false; + + semantics::DirectComponentIterator directComponents{spec}; + for (const semantics::Symbol &component : directComponents) { + if (component.attrs().test(semantics::Attr::ALLOCATABLE)) + return true; + + if (const semantics::DeclTypeSpec *declType = component.GetType()) + if (const auto *nested = declType->AsDerived()) + if (requiresMapper(*nested)) + return true; + } + return false; + }; + + return requiresMapper(typeSpec); +} + int64_t getCollapseValue(const List<Clause> &clauses) { auto iter = llvm::find_if(clauses, [](const Clause &clause) { return clause.id == llvm::omp::Clause::OMPC_collapse; @@ -537,6 +679,12 @@ void insertChildMapInfoIntoParent( mapOperands[std::distance(mapSyms.begin(), parentIter)] .getDefiningOp()); + // Once explicit members are attached to a parent map, do not also invoke + // a declare mapper on it, otherwise the mapper would remap the same + // components leading to duplicate mappings at runtime. + if (!indices.second.memberMap.empty() && mapOp.getMapperIdAttr()) + mapOp.setMapperIdAttr(nullptr); + // NOTE: To maintain appropriate SSA ordering, we move the parent map // which will now have references to its children after the last // of its members to be generated. This is necessary when a user @@ -631,17 +779,9 @@ static void processTileSizesFromOpenMPConstruct( if (!ompCons) return; if (auto *ompLoop{std::get_if<parser::OpenMPLoopConstruct>(&ompCons->u)}) { - const auto &nestedOptional = - std::get<std::optional<parser::NestedConstruct>>(ompLoop->t); - assert(nestedOptional.has_value() && - "Expected a DoConstruct or OpenMPLoopConstruct"); - const auto *innerConstruct = - std::get_if<common::Indirection<parser::OpenMPLoopConstruct>>( - &(nestedOptional.value())); - if (innerConstruct) { - const auto &innerLoopDirective = innerConstruct->value(); + if (auto *innerConstruct = ompLoop->GetNestedConstruct()) { const parser::OmpDirectiveSpecification &innerBeginSpec = - innerLoopDirective.BeginDir(); + innerConstruct->BeginDir(); if (innerBeginSpec.DirId() == llvm::omp::Directive::OMPD_tile) { // Get the size values from parse tree and convert to a vector. for (const auto &clause : innerBeginSpec.Clauses().v) { @@ -656,6 +796,28 @@ static void processTileSizesFromOpenMPConstruct( } } +pft::Evaluation *getNestedDoConstruct(pft::Evaluation &eval) { + for (pft::Evaluation &nested : eval.getNestedEvaluations()) { + // In an OpenMPConstruct there can be compiler directives: + // 1 <<OpenMPConstruct>> + // 2 CompilerDirective: !unroll + // <<DoConstruct>> -> 8 + if (nested.getIf<parser::CompilerDirective>()) + continue; + // Within a DoConstruct, there can be compiler directives, plus + // there is a DoStmt before the body: + // <<DoConstruct>> -> 8 + // 3 NonLabelDoStmt -> 7: do i = 1, n + // <<DoConstruct>> -> 7 + if (nested.getIf<parser::NonLabelDoStmt>()) + continue; + assert(nested.getIf<parser::DoConstruct>() && + "Unexpected construct in the nested evaluations"); + return &nested; + } + llvm_unreachable("Expected do loop to be in the nested evaluations"); +} + /// Populates the sizes vector with values if the given OpenMPConstruct /// contains a loop construct with an inner tiling construct. void collectTileSizesFromOpenMPConstruct( @@ -678,7 +840,7 @@ int64_t collectLoopRelatedInfo( int64_t numCollapse = 1; // Collect the loops to collapse. - lower::pft::Evaluation *doConstructEval = &eval.getFirstNestedEvaluation(); + lower::pft::Evaluation *doConstructEval = getNestedDoConstruct(eval); if (doConstructEval->getIf<parser::DoConstruct>()->IsDoConcurrent()) { TODO(currentLocation, "Do Concurrent in Worksharing loop construct"); } @@ -704,7 +866,7 @@ void collectLoopRelatedInfo( fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); // Collect the loops to collapse. - lower::pft::Evaluation *doConstructEval = &eval.getFirstNestedEvaluation(); + lower::pft::Evaluation *doConstructEval = getNestedDoConstruct(eval); if (doConstructEval->getIf<parser::DoConstruct>()->IsDoConcurrent()) { TODO(currentLocation, "Do Concurrent in Worksharing loop construct"); } @@ -745,9 +907,8 @@ void collectLoopRelatedInfo( iv.push_back(bounds->name.thing.symbol); loopVarTypeSize = std::max(loopVarTypeSize, bounds->name.thing.symbol->GetUltimate().size()); - collapseValue--; - doConstructEval = - &*std::next(doConstructEval->getNestedEvaluations().begin()); + if (--collapseValue) + doConstructEval = getNestedDoConstruct(*doConstructEval); } while (collapseValue > 0); convertLoopBounds(converter, currentLocation, result, loopVarTypeSize); diff --git a/flang/lib/Lower/OpenMP/Utils.h b/flang/lib/Lower/OpenMP/Utils.h index ef1f37a..8a68ff8 100644 --- a/flang/lib/Lower/OpenMP/Utils.h +++ b/flang/lib/Lower/OpenMP/Utils.h @@ -20,6 +20,7 @@ extern llvm::cl::opt<bool> treatIndexAsSection; namespace fir { class FirOpBuilder; +class RecordType; } // namespace fir namespace Fortran { @@ -136,6 +137,13 @@ mlir::Value createParentSymAndGenIntermediateMaps( OmpMapParentAndMemberData &parentMemberIndices, llvm::StringRef asFortran, mlir::omp::ClauseMapFlags mapTypeBits); +mlir::FlatSymbolRefAttr getOrGenImplicitDefaultDeclareMapper( + Fortran::lower::AbstractConverter &converter, mlir::Location loc, + fir::RecordType recordType, llvm::StringRef mapperNameStr); + +bool requiresImplicitDefaultDeclareMapper( + const semantics::DerivedTypeSpec &typeSpec); + omp::ObjectList gatherObjectsOf(omp::Object derivedTypeMember, semantics::SemanticsContext &semaCtx); @@ -159,6 +167,8 @@ void genObjectList(const ObjectList &objects, void lastprivateModifierNotSupported(const omp::clause::Lastprivate &lastp, mlir::Location loc); +pft::Evaluation *getNestedDoConstruct(pft::Evaluation &eval); + int64_t collectLoopRelatedInfo( lower::AbstractConverter &converter, mlir::Location currentLocation, lower::pft::Evaluation &eval, const omp::List<omp::Clause> &clauses, diff --git a/flang/lib/Lower/Runtime.cpp b/flang/lib/Lower/Runtime.cpp index cb55524..5f8586b 100644 --- a/flang/lib/Lower/Runtime.cpp +++ b/flang/lib/Lower/Runtime.cpp @@ -48,31 +48,6 @@ static void genUnreachable(fir::FirOpBuilder &builder, mlir::Location loc) { builder.setInsertionPointToStart(newBlock); } -/// Initializes values for STAT and ERRMSG -static std::pair<mlir::Value, mlir::Value> getStatAndErrmsg( - Fortran::lower::AbstractConverter &converter, mlir::Location loc, - const std::list<Fortran::parser::StatOrErrmsg> &statOrErrList) { - Fortran::lower::StatementContext stmtCtx; - - mlir::Value errMsgExpr, statExpr; - for (const Fortran::parser::StatOrErrmsg &statOrErr : statOrErrList) { - std::visit(Fortran::common::visitors{ - [&](const Fortran::parser::StatVariable &statVar) { - statExpr = fir::getBase(converter.genExprAddr( - loc, Fortran::semantics::GetExpr(statVar), stmtCtx)); - }, - [&](const Fortran::parser::MsgVariable &errMsgVar) { - const Fortran::semantics::SomeExpr *expr = - Fortran::semantics::GetExpr(errMsgVar); - errMsgExpr = fir::getBase( - converter.genExprBox(loc, *expr, stmtCtx)); - }}, - statOrErr.u); - } - - return {statExpr, errMsgExpr}; -} - //===----------------------------------------------------------------------===// // Misc. Fortran statements that lower to runtime calls //===----------------------------------------------------------------------===// @@ -115,8 +90,7 @@ void Fortran::lower::genStopStatement( operands.push_back(cast); }, [&](auto) { - mlir::emitError(loc, "unhandled expression in STOP"); - std::exit(1); + fir::emitFatalError(loc, "unhandled expression in STOP"); }); } else { callee = fir::runtime::getRuntimeFunc<mkRTKey(StopStatement)>(loc, builder); @@ -193,82 +167,57 @@ void Fortran::lower::genUnlockStatement( TODO(converter.getCurrentLocation(), "coarray: UNLOCK runtime"); } -void Fortran::lower::genSyncAllStatement( +void Fortran::lower::genPauseStatement( Fortran::lower::AbstractConverter &converter, - const Fortran::parser::SyncAllStmt &stmt) { - mlir::Location loc = converter.getCurrentLocation(); - converter.checkCoarrayEnabled(); - - // Handle STAT and ERRMSG values - const std::list<Fortran::parser::StatOrErrmsg> &statOrErrList = stmt.v; - auto [statAddr, errMsgAddr] = getStatAndErrmsg(converter, loc, statOrErrList); + const Fortran::parser::PauseStmt &stmt) { fir::FirOpBuilder &builder = converter.getFirOpBuilder(); - mif::SyncAllOp::create(builder, loc, statAddr, errMsgAddr); -} - -void Fortran::lower::genSyncImagesStatement( - Fortran::lower::AbstractConverter &converter, - const Fortran::parser::SyncImagesStmt &stmt) { mlir::Location loc = converter.getCurrentLocation(); - converter.checkCoarrayEnabled(); - fir::FirOpBuilder &builder = converter.getFirOpBuilder(); - - // Handle STAT and ERRMSG values - const std::list<Fortran::parser::StatOrErrmsg> &statOrErrList = - std::get<std::list<Fortran::parser::StatOrErrmsg>>(stmt.t); - auto [statAddr, errMsgAddr] = getStatAndErrmsg(converter, loc, statOrErrList); - - // SYNC_IMAGES(*) is passed as count == -1 while SYNC IMAGES([]) has count - // == 0. Note further that SYNC IMAGES(*) is not semantically equivalent to - // SYNC ALL. Fortran::lower::StatementContext stmtCtx; - mlir::Value imageSet; - const Fortran::parser::SyncImagesStmt::ImageSet &imgSet = - std::get<Fortran::parser::SyncImagesStmt::ImageSet>(stmt.t); - std::visit(Fortran::common::visitors{ - [&](const Fortran::parser::IntExpr &intExpr) { - const SomeExpr *expr = Fortran::semantics::GetExpr(intExpr); - imageSet = - fir::getBase(converter.genExprBox(loc, *expr, stmtCtx)); - }, - [&](const Fortran::parser::Star &) { - // Image set is not set. - imageSet = mlir::Value{}; - }}, - imgSet.u); - - mif::SyncImagesOp::create(builder, loc, imageSet, statAddr, errMsgAddr); -} -void Fortran::lower::genSyncMemoryStatement( - Fortran::lower::AbstractConverter &converter, - const Fortran::parser::SyncMemoryStmt &stmt) { - mlir::Location loc = converter.getCurrentLocation(); - converter.checkCoarrayEnabled(); + llvm::SmallVector<mlir::Value> operands; + mlir::func::FuncOp callee; + mlir::FunctionType calleeType; - // Handle STAT and ERRMSG values - const std::list<Fortran::parser::StatOrErrmsg> &statOrErrList = stmt.v; - auto [statAddr, errMsgAddr] = getStatAndErrmsg(converter, loc, statOrErrList); + if (stmt.v.has_value()) { + const auto &code = stmt.v.value(); + auto expr = + converter.genExprValue(*Fortran::semantics::GetExpr(code), stmtCtx); + expr.match( + // Character-valued expression -> call PauseStatementText (CHAR, LEN) + [&](const fir::CharBoxValue &x) { + callee = fir::runtime::getRuntimeFunc<mkRTKey(PauseStatementText)>( + loc, builder); + calleeType = callee.getFunctionType(); - fir::FirOpBuilder &builder = converter.getFirOpBuilder(); - mif::SyncMemoryOp::create(builder, loc, statAddr, errMsgAddr); -} + operands.push_back( + builder.createConvert(loc, calleeType.getInput(0), x.getAddr())); + operands.push_back( + builder.createConvert(loc, calleeType.getInput(1), x.getLen())); + }, + // Unboxed value -> call PauseStatementInt which accepts an integer. + [&](fir::UnboxedValue x) { + callee = fir::runtime::getRuntimeFunc<mkRTKey(PauseStatementInt)>( + loc, builder); + calleeType = callee.getFunctionType(); + assert(calleeType.getNumInputs() >= 1); + mlir::Value cast = + builder.createConvert(loc, calleeType.getInput(0), x); + operands.push_back(cast); + }, + [&](auto) { + fir::emitFatalError(loc, "unhandled expression in PAUSE"); + }); + } else { + callee = + fir::runtime::getRuntimeFunc<mkRTKey(PauseStatement)>(loc, builder); + calleeType = callee.getFunctionType(); + } -void Fortran::lower::genSyncTeamStatement( - Fortran::lower::AbstractConverter &converter, - const Fortran::parser::SyncTeamStmt &) { - TODO(converter.getCurrentLocation(), "coarray: SYNC TEAM runtime"); -} + fir::CallOp::create(builder, loc, callee, operands); -void Fortran::lower::genPauseStatement( - Fortran::lower::AbstractConverter &converter, - const Fortran::parser::PauseStmt &) { - fir::FirOpBuilder &builder = converter.getFirOpBuilder(); - mlir::Location loc = converter.getCurrentLocation(); - mlir::func::FuncOp callee = - fir::runtime::getRuntimeFunc<mkRTKey(PauseStatement)>(loc, builder); - fir::CallOp::create(builder, loc, callee, mlir::ValueRange{}); + // NOTE: PAUSE does not terminate the current block. The program may resume + // and continue normal execution, so we do not emit control-flow terminators. } void Fortran::lower::genPointerAssociate(fir::FirOpBuilder &builder, diff --git a/flang/lib/Lower/Support/ReductionProcessor.cpp b/flang/lib/Lower/Support/ReductionProcessor.cpp index 605a5b6b..db8ad90 100644 --- a/flang/lib/Lower/Support/ReductionProcessor.cpp +++ b/flang/lib/Lower/Support/ReductionProcessor.cpp @@ -501,7 +501,7 @@ static mlir::Type unwrapSeqOrBoxedType(mlir::Type ty) { template <typename OpType> static void createReductionAllocAndInitRegions( AbstractConverter &converter, mlir::Location loc, OpType &reductionDecl, - const ReductionProcessor::ReductionIdentifier redId, mlir::Type type, + ReductionProcessor::GenInitValueCBTy genInitValueCB, mlir::Type type, bool isByRef) { fir::FirOpBuilder &builder = converter.getFirOpBuilder(); auto yield = [&](mlir::Value ret) { genYield<OpType>(builder, loc, ret); }; @@ -523,9 +523,8 @@ static void createReductionAllocAndInitRegions( mlir::Type ty = fir::unwrapRefType(type); builder.setInsertionPointToEnd(initBlock); - mlir::Value initValue = ReductionProcessor::getReductionInitValue( - loc, unwrapSeqOrBoxedType(ty), redId, builder); - + mlir::Value initValue = + genInitValueCB(builder, loc, ty, initBlock->getArgument(0)); if (isByRef) { populateByRefInitAndCleanupRegions( converter, loc, type, initValue, initBlock, @@ -536,7 +535,7 @@ static void createReductionAllocAndInitRegions( /*isDoConcurrent*/ std::is_same_v<OpType, fir::DeclareReductionOp>); } - if (fir::isa_trivial(ty)) { + if (fir::isa_trivial(ty) || fir::isa_derived(ty)) { if (isByRef) { // alloc region builder.setInsertionPointToEnd(allocBlock); @@ -556,43 +555,117 @@ static void createReductionAllocAndInitRegions( yield(boxAlloca); } -template <typename OpType> -OpType ReductionProcessor::createDeclareReduction( +template <typename DeclareRedType> +DeclareRedType ReductionProcessor::createDeclareReductionHelper( AbstractConverter &converter, llvm::StringRef reductionOpName, - const ReductionIdentifier redId, mlir::Type type, mlir::Location loc, - bool isByRef) { + mlir::Type type, mlir::Location loc, bool isByRef, + GenCombinerCBTy genCombinerCB, GenInitValueCBTy genInitValueCB) { fir::FirOpBuilder &builder = converter.getFirOpBuilder(); mlir::OpBuilder::InsertionGuard guard(builder); mlir::ModuleOp module = builder.getModule(); assert(!reductionOpName.empty()); - auto decl = module.lookupSymbol<OpType>(reductionOpName); + auto decl = module.lookupSymbol<DeclareRedType>(reductionOpName); if (decl) return decl; mlir::OpBuilder modBuilder(module.getBodyRegion()); mlir::Type valTy = fir::unwrapRefType(type); - if (!isByRef) + + // For by-ref reductions, we want to keep track of the + // boxed/referenced/allocated type. For example, for a `real, allocatable` + // variable, `real` should be stored. + mlir::TypeAttr boxedTyAttr{}; + mlir::Type boxedTy; + + if (isByRef) { + boxedTy = fir::unwrapPassByRefType(valTy); + boxedTyAttr = mlir::TypeAttr::get(boxedTy); + } else type = valTy; - decl = OpType::create(modBuilder, loc, reductionOpName, type); - createReductionAllocAndInitRegions(converter, loc, decl, redId, type, + decl = DeclareRedType::create(modBuilder, loc, reductionOpName, type, + boxedTyAttr); + createReductionAllocAndInitRegions(converter, loc, decl, genInitValueCB, type, isByRef); - builder.createBlock(&decl.getReductionRegion(), decl.getReductionRegion().end(), {type, type}, {loc, loc}); - builder.setInsertionPointToEnd(&decl.getReductionRegion().back()); mlir::Value op1 = decl.getReductionRegion().front().getArgument(0); mlir::Value op2 = decl.getReductionRegion().front().getArgument(1); - genCombiner<OpType>(builder, loc, redId, type, op1, op2, isByRef); + genCombinerCB(builder, loc, type, op1, op2, isByRef); + + if (isByRef && fir::isa_box_type(valTy)) { + bool isBoxReductionSupported = [&]() { + auto offloadMod = llvm::dyn_cast<mlir::omp::OffloadModuleInterface>( + *builder.getModule()); + + // This check tests the implementation status on the GPU. Box reductions + // are fully supported on the CPU. + if (!offloadMod.getIsGPU()) + return true; + + auto seqTy = mlir::dyn_cast<fir::SequenceType>(boxedTy); + + // Dynamically-shaped arrays are not supported yet on the GPU. + return !seqTy || !fir::sequenceWithNonConstantShape(seqTy); + }(); + + if (!isBoxReductionSupported) { + TODO(loc, "Reduction of dynamically-shaped arrays are not supported yet " + "on the GPU."); + } + + mlir::Region &dataPtrPtrRegion = decl.getDataPtrPtrRegion(); + mlir::Block &dataAddrBlock = *builder.createBlock( + &dataPtrPtrRegion, dataPtrPtrRegion.end(), {type}, {loc}); + builder.setInsertionPointToEnd(&dataAddrBlock); + mlir::Value boxRefOperand = dataAddrBlock.getArgument(0); + mlir::Value baseAddrOffset = fir::BoxOffsetOp::create( + builder, loc, boxRefOperand, fir::BoxFieldAttr::base_addr); + genYield<DeclareRedType>(builder, loc, baseAddrOffset); + } return decl; } -static bool doReductionByRef(mlir::Value reductionVar) { +template <typename OpType> +OpType ReductionProcessor::createDeclareReduction( + AbstractConverter &converter, llvm::StringRef reductionOpName, + const ReductionIdentifier redId, mlir::Type type, mlir::Location loc, + bool isByRef) { + auto genInitValueCB = [&](fir::FirOpBuilder &builder, mlir::Location loc, + mlir::Type type, mlir::Value val) { + mlir::Type ty = fir::unwrapRefType(type); + mlir::Value initValue = ReductionProcessor::getReductionInitValue( + loc, unwrapSeqOrBoxedType(ty), redId, builder); + return initValue; + }; + auto genCombinerCB = [&](fir::FirOpBuilder &builder, mlir::Location loc, + mlir::Type type, mlir::Value op1, mlir::Value op2, + bool isByRef) { + genCombiner<OpType>(builder, loc, redId, type, op1, op2, isByRef); + }; + + return createDeclareReductionHelper<OpType>(converter, reductionOpName, type, + loc, isByRef, genCombinerCB, + genInitValueCB); +} + +bool ReductionProcessor::doReductionByRef(mlir::Type reductionType) { + if (forceByrefReduction) + return true; + + if (!fir::isa_trivial(fir::unwrapRefType(reductionType)) && + !fir::isa_derived(fir::unwrapRefType(reductionType))) + return true; + + return false; +} + +bool ReductionProcessor::doReductionByRef(mlir::Value reductionVar) { if (forceByrefReduction) return true; @@ -600,10 +673,7 @@ static bool doReductionByRef(mlir::Value reductionVar) { mlir::dyn_cast<hlfir::DeclareOp>(reductionVar.getDefiningOp())) reductionVar = declare.getMemref(); - if (!fir::isa_trivial(fir::unwrapRefType(reductionVar.getType()))) - return true; - - return false; + return doReductionByRef(reductionVar.getType()); } template <typename OpType, typename RedOperatorListTy> @@ -614,6 +684,8 @@ bool ReductionProcessor::processReductionArguments( llvm::SmallVectorImpl<bool> &reduceVarByRef, llvm::SmallVectorImpl<mlir::Attribute> &reductionDeclSymbols, const llvm::SmallVectorImpl<const semantics::Symbol *> &reductionSymbols) { + fir::FirOpBuilder &builder = converter.getFirOpBuilder(); + if constexpr (std::is_same_v<RedOperatorListTy, omp::clause::ReductionOperatorList>) { // For OpenMP reduction clauses, check if the reduction operator is @@ -627,7 +699,13 @@ bool ReductionProcessor::processReductionArguments( std::get_if<omp::clause::ProcedureDesignator>(&redOperator.u)) { if (!ReductionProcessor::supportedIntrinsicProcReduction( *reductionIntrinsic)) { - return false; + // If not an intrinsic is has to be a custom reduction op, and should + // be available in the module. + semantics::Symbol *sym = reductionIntrinsic->v.sym(); + mlir::ModuleOp module = builder.getModule(); + auto decl = module.lookupSymbol<OpType>(getRealName(sym).ToString()); + if (!decl) + return false; } } else { return false; @@ -637,7 +715,6 @@ bool ReductionProcessor::processReductionArguments( // Reduction variable processing common to both intrinsic operators and // procedure designators - fir::FirOpBuilder &builder = converter.getFirOpBuilder(); mlir::OpBuilder::InsertPoint dcIP; constexpr bool isDoConcurrent = std::is_same_v<OpType, fir::DeclareReductionOp>; @@ -741,7 +818,13 @@ bool ReductionProcessor::processReductionArguments( &redOperator.u)) { if (!ReductionProcessor::supportedIntrinsicProcReduction( *reductionIntrinsic)) { - TODO(currentLocation, "Unsupported intrinsic proc reduction"); + // Custom reductions we can just add to the symbols without + // generating the declare reduction op. + semantics::Symbol *sym = reductionIntrinsic->v.sym(); + reductionDeclSymbols.push_back(mlir::SymbolRefAttr::get( + builder.getContext(), sym->name().ToString())); + ++idx; + continue; } redId = getReductionType(*reductionIntrinsic); reductionName = diff --git a/flang/lib/Lower/Support/Utils.cpp b/flang/lib/Lower/Support/Utils.cpp index 1b4d37e..4b95a3a 100644 --- a/flang/lib/Lower/Support/Utils.cpp +++ b/flang/lib/Lower/Support/Utils.cpp @@ -82,7 +82,7 @@ public: x.cosubscript()) cosubs -= getHashValue(v); return getHashValue(x.base()) * 97u - cosubs + getHashValue(x.stat()) + - 257u + getHashValue(x.team()); + 257u + getHashValue(x.team()) + getHashValue(x.notify()); } static unsigned getHashValue(const Fortran::evaluate::NamedEntity &x) { if (x.IsSymbol()) @@ -341,7 +341,8 @@ public: const Fortran::evaluate::CoarrayRef &y) { return isEqual(x.base(), y.base()) && isEqual(x.cosubscript(), y.cosubscript()) && - isEqual(x.stat(), y.stat()) && isEqual(x.team(), y.team()); + isEqual(x.stat(), y.stat()) && isEqual(x.team(), y.team()) && + isEqual(x.notify(), y.notify()); } static bool isEqual(const Fortran::evaluate::NamedEntity &x, const Fortran::evaluate::NamedEntity &y) { diff --git a/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp b/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp index 73ddd1f..0e956d8 100644 --- a/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp +++ b/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp @@ -27,6 +27,26 @@ using namespace mlir; #define DEBUG_TYPE "fir-alias-analysis" +// Inspect for value-scoped Allocate effects and determine whether +// 'candidate' is a new allocation. Returns SourceKind::Allocate if a +// MemAlloc effect is attached +static fir::AliasAnalysis::SourceKind +classifyAllocateFromEffects(mlir::Operation *op, mlir::Value candidate) { + if (!op) + return fir::AliasAnalysis::SourceKind::Unknown; + auto interface = llvm::dyn_cast<mlir::MemoryEffectOpInterface>(op); + if (!interface) + return fir::AliasAnalysis::SourceKind::Unknown; + llvm::SmallVector<mlir::MemoryEffects::EffectInstance, 4> effects; + interface.getEffects(effects); + for (mlir::MemoryEffects::EffectInstance &e : effects) { + if (mlir::isa<mlir::MemoryEffects::Allocate>(e.getEffect()) && + e.getValue() && e.getValue() == candidate) + return fir::AliasAnalysis::SourceKind::Allocate; + } + return fir::AliasAnalysis::SourceKind::Unknown; +} + //===----------------------------------------------------------------------===// // AliasAnalysis: alias //===----------------------------------------------------------------------===// @@ -214,6 +234,17 @@ AliasResult AliasAnalysis::alias(Source lhsSrc, Source rhsSrc, mlir::Value lhs, << " aliasing because same source kind and origin\n"); if (approximateSource) return AliasResult::MayAlias; + // One should be careful about relying on MustAlias. + // The LLVM definition implies that the two MustAlias + // memory objects start at exactly the same location. + // With Fortran array slices two objects may have + // the same starting location, but otherwise represent + // partially overlapping memory locations, e.g.: + // integer :: a(10) + // ... a(5:1:-1) ! starts at a(5) and addresses a(5), ..., a(1) + // ... a(5:10:1) ! starts at a(5) and addresses a(5), ..., a(10) + // The current implementation of FIR alias analysis will always + // return MayAlias for such cases. return AliasResult::MustAlias; } // If one value is the address of a composite, and if the other value is the @@ -534,13 +565,28 @@ AliasAnalysis::Source AliasAnalysis::getSource(mlir::Value v, Source::Attributes attributes; mlir::Operation *instantiationPoint{nullptr}; while (defOp && !breakFromLoop) { - ty = defOp->getResultTypes()[0]; + // Value-scoped allocation detection via effects. + if (classifyAllocateFromEffects(defOp, v) == SourceKind::Allocate) { + type = SourceKind::Allocate; + break; + } + // Operations may have multiple results, so we need to analyze + // the result for which the source is queried. + auto opResult = mlir::cast<OpResult>(v); + assert(opResult.getOwner() == defOp && "v must be a result of defOp"); + ty = opResult.getType(); llvm::TypeSwitch<Operation *>(defOp) .Case<hlfir::AsExprOp>([&](auto op) { + // TODO: we should probably always report hlfir.as_expr + // as a unique source, and let the codegen decide whether + // to use the original buffer or create a copy. v = op.getVar(); defOp = v.getDefiningOp(); }) .Case<hlfir::AssociateOp>([&](auto op) { + assert(opResult != op.getMustFreeStrorageFlag() && + "MustFreeStorageFlag result is not an aliasing candidate"); + mlir::Value source = op.getSource(); if (fir::isa_trivial(source.getType())) { // Trivial values will always use distinct temp memory, @@ -554,16 +600,6 @@ AliasAnalysis::Source AliasAnalysis::getSource(mlir::Value v, defOp = v.getDefiningOp(); } }) - .Case<fir::AllocaOp, fir::AllocMemOp>([&](auto op) { - // Unique memory allocation. - type = SourceKind::Allocate; - breakFromLoop = true; - }) - .Case<fir::ConvertOp>([&](auto op) { - // Skip ConvertOp's and track further through the operand. - v = op->getOperand(0); - defOp = v.getDefiningOp(); - }) .Case<fir::PackArrayOp>([&](auto op) { // The packed array is not distinguishable from the original // array, so skip PackArrayOp and track further through @@ -572,28 +608,6 @@ AliasAnalysis::Source AliasAnalysis::getSource(mlir::Value v, defOp = v.getDefiningOp(); approximateSource = true; }) - .Case<fir::BoxAddrOp>([&](auto op) { - v = op->getOperand(0); - defOp = v.getDefiningOp(); - if (mlir::isa<fir::BaseBoxType>(v.getType())) - followBoxData = true; - }) - .Case<fir::ArrayCoorOp, fir::CoordinateOp>([&](auto op) { - if (isPointerReference(ty)) - attributes.set(Attribute::Pointer); - v = op->getOperand(0); - defOp = v.getDefiningOp(); - if (mlir::isa<fir::BaseBoxType>(v.getType())) - followBoxData = true; - approximateSource = true; - }) - .Case<fir::EmboxOp, fir::ReboxOp>([&](auto op) { - if (followBoxData) { - v = op->getOperand(0); - defOp = v.getDefiningOp(); - } else - breakFromLoop = true; - }) .Case<fir::LoadOp>([&](auto op) { // If load is inside target and it points to mapped item, // continue tracking. @@ -628,16 +642,23 @@ AliasAnalysis::Source AliasAnalysis::getSource(mlir::Value v, type = SourceKind::Global; } else { auto def = llvm::cast<mlir::Value>(boxSrc.origin.u); - // TODO: Add support to fir.allocmem - if (auto allocOp = def.template getDefiningOp<fir::AllocaOp>()) { - v = def; - defOp = v.getDefiningOp(); - type = SourceKind::Allocate; - } else if (isDummyArgument(def)) { - defOp = nullptr; - v = def; - } else { - type = SourceKind::Indirect; + bool classified = false; + if (auto defDefOp = def.getDefiningOp()) { + if (classifyAllocateFromEffects(defDefOp, def) == + SourceKind::Allocate) { + v = def; + defOp = defDefOp; + type = SourceKind::Allocate; + classified = true; + } + } + if (!classified) { + if (isDummyArgument(def)) { + defOp = nullptr; + v = def; + } else { + type = SourceKind::Indirect; + } } } breakFromLoop = true; @@ -663,6 +684,9 @@ AliasAnalysis::Source AliasAnalysis::getSource(mlir::Value v, breakFromLoop = true; }) .Case<hlfir::DeclareOp, fir::DeclareOp>([&](auto op) { + // The declare operations support FortranObjectViewOpInterface, + // but their handling is more complex. Maybe we can find better + // abstractions to handle them in a general fashion. bool isPrivateItem = false; if (omp::BlockArgOpenMPOpInterface argIface = dyn_cast<omp::BlockArgOpenMPOpInterface>(op->getParentOp())) { @@ -713,7 +737,7 @@ AliasAnalysis::Source AliasAnalysis::getSource(mlir::Value v, // currently provide any useful information. The host associated // access will end up dereferencing the host association tuple, // so we may as well stop right now. - v = defOp->getResult(0); + v = opResult; // TODO: if the host associated variable is a dummy argument // of the host, I think, we can treat it as SourceKind::Argument // for the purpose of alias analysis inside the internal procedure. @@ -748,21 +772,45 @@ AliasAnalysis::Source AliasAnalysis::getSource(mlir::Value v, v = op.getMemref(); defOp = v.getDefiningOp(); }) - .Case<hlfir::DesignateOp>([&](auto op) { - auto varIf = llvm::cast<fir::FortranVariableOpInterface>(defOp); - attributes |= getAttrsFromVariable(varIf); - // Track further through the memory indexed into - // => if the source arrays/structures don't alias then nor do the - // results of hlfir.designate - v = op.getMemref(); + .Case<fir::FortranObjectViewOpInterface>([&](auto op) { + // This case must be located after the cases for concrete + // operations that support FortraObjectViewOpInterface, + // so that their special handling kicks in. + + // fir.embox/rebox case: this is the only case where we check + // for followBoxData. + // TODO: it looks like we do not have LIT tests that fail + // upon removal of the followBoxData code. We should come up + // with a test or remove this code. + if (!followBoxData && + (mlir::isa<fir::EmboxOp>(op) || mlir::isa<fir::ReboxOp>(op))) { + breakFromLoop = true; + return; + } + + // Collect attributes from FortranVariableOpInterface operations. + if (auto varIf = + mlir::dyn_cast<fir::FortranVariableOpInterface>(defOp)) + attributes |= getAttrsFromVariable(varIf); + // Set Pointer attribute based on the reference type. + if (isPointerReference(ty)) + attributes.set(Attribute::Pointer); + + // Update v to point to the operand that represents the object + // referenced by the operation's result. + v = op.getViewSource(opResult); defOp = v.getDefiningOp(); - // TODO: there will be some cases which provably don't alias if one - // takes into account the component or indices, which are currently - // ignored here - leading to false positives - // because of this limitation, we need to make sure we never return - // MustAlias after going through a designate operation - approximateSource = true; - if (mlir::isa<fir::BaseBoxType>(v.getType())) + // If the input the resulting object references are offsetted, + // then set approximateSource. + auto offset = op.getViewOffset(opResult); + if (!offset || *offset != 0) + approximateSource = true; + + // If the source is a box, and the result is not a box, + // then this is one of the box "unpacking" operations, + // so we should set followBoxData. + if (mlir::isa<fir::BaseBoxType>(v.getType()) && + !mlir::isa<fir::BaseBoxType>(ty)) followBoxData = true; }) .Default([&](auto op) { diff --git a/flang/lib/Optimizer/Builder/CMakeLists.txt b/flang/lib/Optimizer/Builder/CMakeLists.txt index 1f95259..37c9c2d 100644 --- a/flang/lib/Optimizer/Builder/CMakeLists.txt +++ b/flang/lib/Optimizer/Builder/CMakeLists.txt @@ -5,6 +5,7 @@ add_flang_library(FIRBuilder BoxValue.cpp Character.cpp Complex.cpp + CUDAIntrinsicCall.cpp CUFCommon.cpp DoLoopHelper.cpp FIRBuilder.cpp diff --git a/flang/lib/Optimizer/Builder/CUDAIntrinsicCall.cpp b/flang/lib/Optimizer/Builder/CUDAIntrinsicCall.cpp new file mode 100644 index 0000000..3c86a9d --- /dev/null +++ b/flang/lib/Optimizer/Builder/CUDAIntrinsicCall.cpp @@ -0,0 +1,1722 @@ +//===-- CUDAIntrinsicCall.cpp ---------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Helper routines for constructing the FIR dialect of MLIR for PowerPC +// intrinsics. Extensive use of MLIR interfaces and MLIR's coding style +// (https://mlir.llvm.org/getting_started/DeveloperGuide/) is used in this +// module. +// +//===----------------------------------------------------------------------===// + +#include "flang/Optimizer/Builder/CUDAIntrinsicCall.h" +#include "flang/Evaluate/common.h" +#include "flang/Optimizer/Builder/FIRBuilder.h" +#include "flang/Optimizer/Builder/MutableBox.h" +#include "flang/Optimizer/Dialect/CUF/CUFOps.h" +#include "flang/Optimizer/HLFIR/HLFIROps.h" +#include "mlir/Dialect/Index/IR/IndexOps.h" +#include "mlir/Dialect/SCF/IR/SCF.h" +#include "mlir/Dialect/Vector/IR/VectorOps.h" + +namespace fir { + +using CI = CUDAIntrinsicLibrary; + +static const char __ldca_i4x4[] = "__ldca_i4x4_"; +static const char __ldca_i8x2[] = "__ldca_i8x2_"; +static const char __ldca_r2x2[] = "__ldca_r2x2_"; +static const char __ldca_r4x4[] = "__ldca_r4x4_"; +static const char __ldca_r8x2[] = "__ldca_r8x2_"; +static const char __ldcg_i4x4[] = "__ldcg_i4x4_"; +static const char __ldcg_i8x2[] = "__ldcg_i8x2_"; +static const char __ldcg_r2x2[] = "__ldcg_r2x2_"; +static const char __ldcg_r4x4[] = "__ldcg_r4x4_"; +static const char __ldcg_r8x2[] = "__ldcg_r8x2_"; +static const char __ldcs_i4x4[] = "__ldcs_i4x4_"; +static const char __ldcs_i8x2[] = "__ldcs_i8x2_"; +static const char __ldcs_r2x2[] = "__ldcs_r2x2_"; +static const char __ldcs_r4x4[] = "__ldcs_r4x4_"; +static const char __ldcs_r8x2[] = "__ldcs_r8x2_"; +static const char __ldcv_i4x4[] = "__ldcv_i4x4_"; +static const char __ldcv_i8x2[] = "__ldcv_i8x2_"; +static const char __ldcv_r2x2[] = "__ldcv_r2x2_"; +static const char __ldcv_r4x4[] = "__ldcv_r4x4_"; +static const char __ldcv_r8x2[] = "__ldcv_r8x2_"; +static const char __ldlu_i4x4[] = "__ldlu_i4x4_"; +static const char __ldlu_i8x2[] = "__ldlu_i8x2_"; +static const char __ldlu_r2x2[] = "__ldlu_r2x2_"; +static const char __ldlu_r4x4[] = "__ldlu_r4x4_"; +static const char __ldlu_r8x2[] = "__ldlu_r8x2_"; + +static constexpr unsigned kTMAAlignment = 16; + +// CUDA specific intrinsic handlers. +static constexpr IntrinsicHandler cudaHandlers[]{ + {"__ldca_i4x4", + static_cast<CUDAIntrinsicLibrary::ExtendedGenerator>( + &CI::genLDXXFunc<__ldca_i4x4, 4>), + {{{"a", asAddr}}}, + /*isElemental=*/false}, + {"__ldca_i8x2", + static_cast<CUDAIntrinsicLibrary::ExtendedGenerator>( + &CI::genLDXXFunc<__ldca_i8x2, 2>), + {{{"a", asAddr}}}, + /*isElemental=*/false}, + {"__ldca_r2x2", + static_cast<CUDAIntrinsicLibrary::ExtendedGenerator>( + &CI::genLDXXFunc<__ldca_r2x2, 2>), + {{{"a", asAddr}}}, + /*isElemental=*/false}, + {"__ldca_r4x4", + static_cast<CUDAIntrinsicLibrary::ExtendedGenerator>( + &CI::genLDXXFunc<__ldca_r4x4, 4>), + {{{"a", asAddr}}}, + /*isElemental=*/false}, + {"__ldca_r8x2", + static_cast<CUDAIntrinsicLibrary::ExtendedGenerator>( + &CI::genLDXXFunc<__ldca_r8x2, 2>), + {{{"a", asAddr}}}, + /*isElemental=*/false}, + {"__ldcg_i4x4", + static_cast<CUDAIntrinsicLibrary::ExtendedGenerator>( + &CI::genLDXXFunc<__ldcg_i4x4, 4>), + {{{"a", asAddr}}}, + /*isElemental=*/false}, + {"__ldcg_i8x2", + static_cast<CUDAIntrinsicLibrary::ExtendedGenerator>( + &CI::genLDXXFunc<__ldcg_i8x2, 2>), + {{{"a", asAddr}}}, + /*isElemental=*/false}, + {"__ldcg_r2x2", + static_cast<CUDAIntrinsicLibrary::ExtendedGenerator>( + &CI::genLDXXFunc<__ldcg_r2x2, 2>), + {{{"a", asAddr}}}, + /*isElemental=*/false}, + {"__ldcg_r4x4", + static_cast<CUDAIntrinsicLibrary::ExtendedGenerator>( + &CI::genLDXXFunc<__ldcg_r4x4, 4>), + {{{"a", asAddr}}}, + /*isElemental=*/false}, + {"__ldcg_r8x2", + static_cast<CUDAIntrinsicLibrary::ExtendedGenerator>( + &CI::genLDXXFunc<__ldcg_r8x2, 2>), + {{{"a", asAddr}}}, + /*isElemental=*/false}, + {"__ldcs_i4x4", + static_cast<CUDAIntrinsicLibrary::ExtendedGenerator>( + &CI::genLDXXFunc<__ldcs_i4x4, 4>), + {{{"a", asAddr}}}, + /*isElemental=*/false}, + {"__ldcs_i8x2", + static_cast<CUDAIntrinsicLibrary::ExtendedGenerator>( + &CI::genLDXXFunc<__ldcs_i8x2, 2>), + {{{"a", asAddr}}}, + /*isElemental=*/false}, + {"__ldcs_r2x2", + static_cast<CUDAIntrinsicLibrary::ExtendedGenerator>( + &CI::genLDXXFunc<__ldcs_r2x2, 2>), + {{{"a", asAddr}}}, + /*isElemental=*/false}, + {"__ldcs_r4x4", + static_cast<CUDAIntrinsicLibrary::ExtendedGenerator>( + &CI::genLDXXFunc<__ldcs_r4x4, 4>), + {{{"a", asAddr}}}, + /*isElemental=*/false}, + {"__ldcs_r8x2", + static_cast<CUDAIntrinsicLibrary::ExtendedGenerator>( + &CI::genLDXXFunc<__ldcs_r8x2, 2>), + {{{"a", asAddr}}}, + /*isElemental=*/false}, + {"__ldcv_i4x4", + static_cast<CUDAIntrinsicLibrary::ExtendedGenerator>( + &CI::genLDXXFunc<__ldcv_i4x4, 4>), + {{{"a", asAddr}}}, + /*isElemental=*/false}, + {"__ldcv_i8x2", + static_cast<CUDAIntrinsicLibrary::ExtendedGenerator>( + &CI::genLDXXFunc<__ldcv_i8x2, 2>), + {{{"a", asAddr}}}, + /*isElemental=*/false}, + {"__ldcv_r2x2", + static_cast<CUDAIntrinsicLibrary::ExtendedGenerator>( + &CI::genLDXXFunc<__ldcv_r2x2, 2>), + {{{"a", asAddr}}}, + /*isElemental=*/false}, + {"__ldcv_r4x4", + static_cast<CUDAIntrinsicLibrary::ExtendedGenerator>( + &CI::genLDXXFunc<__ldcv_r4x4, 4>), + {{{"a", asAddr}}}, + /*isElemental=*/false}, + {"__ldcv_r8x2", + static_cast<CUDAIntrinsicLibrary::ExtendedGenerator>( + &CI::genLDXXFunc<__ldcv_r8x2, 2>), + {{{"a", asAddr}}}, + /*isElemental=*/false}, + {"__ldlu_i4x4", + static_cast<CUDAIntrinsicLibrary::ExtendedGenerator>( + &CI::genLDXXFunc<__ldlu_i4x4, 4>), + {{{"a", asAddr}}}, + /*isElemental=*/false}, + {"__ldlu_i8x2", + static_cast<CUDAIntrinsicLibrary::ExtendedGenerator>( + &CI::genLDXXFunc<__ldlu_i8x2, 2>), + {{{"a", asAddr}}}, + /*isElemental=*/false}, + {"__ldlu_r2x2", + static_cast<CUDAIntrinsicLibrary::ExtendedGenerator>( + &CI::genLDXXFunc<__ldlu_r2x2, 2>), + {{{"a", asAddr}}}, + /*isElemental=*/false}, + {"__ldlu_r4x4", + static_cast<CUDAIntrinsicLibrary::ExtendedGenerator>( + &CI::genLDXXFunc<__ldlu_r4x4, 4>), + {{{"a", asAddr}}}, + /*isElemental=*/false}, + {"__ldlu_r8x2", + static_cast<CUDAIntrinsicLibrary::ExtendedGenerator>( + &CI::genLDXXFunc<__ldlu_r8x2, 2>), + {{{"a", asAddr}}}, + /*isElemental=*/false}, + {"all_sync", + static_cast<CUDAIntrinsicLibrary::ElementalGenerator>( + &CI::genVoteSync<mlir::NVVM::VoteSyncKind::all>), + {{{"mask", asValue}, {"pred", asValue}}}, + /*isElemental=*/false}, + {"any_sync", + static_cast<CUDAIntrinsicLibrary::ElementalGenerator>( + &CI::genVoteSync<mlir::NVVM::VoteSyncKind::any>), + {{{"mask", asValue}, {"pred", asValue}}}, + /*isElemental=*/false}, + {"atomicadd_r4x2", + static_cast<CUDAIntrinsicLibrary::ExtendedGenerator>( + &CI::genAtomicAddVector<2>), + {{{"a", asAddr}, {"v", asAddr}}}, + false}, + {"atomicadd_r4x4", + static_cast<CUDAIntrinsicLibrary::ExtendedGenerator>( + &CI::genAtomicAddVector4x4), + {{{"a", asAddr}, {"v", asAddr}}}, + false}, + {"atomicaddd", + static_cast<CUDAIntrinsicLibrary::ElementalGenerator>(&CI::genAtomicAdd), + {{{"a", asAddr}, {"v", asValue}}}, + false}, + {"atomicaddf", + static_cast<CUDAIntrinsicLibrary::ElementalGenerator>(&CI::genAtomicAdd), + {{{"a", asAddr}, {"v", asValue}}}, + false}, + {"atomicaddi", + static_cast<CUDAIntrinsicLibrary::ElementalGenerator>(&CI::genAtomicAdd), + {{{"a", asAddr}, {"v", asValue}}}, + false}, + {"atomicaddl", + static_cast<CUDAIntrinsicLibrary::ElementalGenerator>(&CI::genAtomicAdd), + {{{"a", asAddr}, {"v", asValue}}}, + false}, + {"atomicaddr2", + static_cast<CUDAIntrinsicLibrary::ExtendedGenerator>(&CI::genAtomicAddR2), + {{{"a", asAddr}, {"v", asAddr}}}, + false}, + {"atomicaddvector_r2x2", + static_cast<CUDAIntrinsicLibrary::ExtendedGenerator>( + &CI::genAtomicAddVector<2>), + {{{"a", asAddr}, {"v", asAddr}}}, + false}, + {"atomicaddvector_r4x2", + static_cast<CUDAIntrinsicLibrary::ExtendedGenerator>( + &CI::genAtomicAddVector<2>), + {{{"a", asAddr}, {"v", asAddr}}}, + false}, + {"atomicandi", + static_cast<CUDAIntrinsicLibrary::ElementalGenerator>(&CI::genAtomicAnd), + {{{"a", asAddr}, {"v", asValue}}}, + false}, + {"atomiccasd", + static_cast<CUDAIntrinsicLibrary::ExtendedGenerator>(&CI::genAtomicCas), + {{{"a", asAddr}, {"v1", asValue}, {"v2", asValue}}}, + false}, + {"atomiccasf", + static_cast<CUDAIntrinsicLibrary::ExtendedGenerator>(&CI::genAtomicCas), + {{{"a", asAddr}, {"v1", asValue}, {"v2", asValue}}}, + false}, + {"atomiccasi", + static_cast<CUDAIntrinsicLibrary::ExtendedGenerator>(&CI::genAtomicCas), + {{{"a", asAddr}, {"v1", asValue}, {"v2", asValue}}}, + false}, + {"atomiccasul", + static_cast<CUDAIntrinsicLibrary::ExtendedGenerator>(&CI::genAtomicCas), + {{{"a", asAddr}, {"v1", asValue}, {"v2", asValue}}}, + false}, + {"atomicdeci", + static_cast<CUDAIntrinsicLibrary::ElementalGenerator>(&CI::genAtomicDec), + {{{"a", asAddr}, {"v", asValue}}}, + false}, + {"atomicexchd", + static_cast<CUDAIntrinsicLibrary::ExtendedGenerator>(&CI::genAtomicExch), + {{{"a", asAddr}, {"v", asValue}}}, + false}, + {"atomicexchf", + static_cast<CUDAIntrinsicLibrary::ExtendedGenerator>(&CI::genAtomicExch), + {{{"a", asAddr}, {"v", asValue}}}, + false}, + {"atomicexchi", + static_cast<CUDAIntrinsicLibrary::ExtendedGenerator>(&CI::genAtomicExch), + {{{"a", asAddr}, {"v", asValue}}}, + false}, + {"atomicexchul", + static_cast<CUDAIntrinsicLibrary::ExtendedGenerator>(&CI::genAtomicExch), + {{{"a", asAddr}, {"v", asValue}}}, + false}, + {"atomicinci", + static_cast<CUDAIntrinsicLibrary::ElementalGenerator>(&CI::genAtomicInc), + {{{"a", asAddr}, {"v", asValue}}}, + false}, + {"atomicmaxd", + static_cast<CUDAIntrinsicLibrary::ElementalGenerator>(&CI::genAtomicMax), + {{{"a", asAddr}, {"v", asValue}}}, + false}, + {"atomicmaxf", + static_cast<CUDAIntrinsicLibrary::ElementalGenerator>(&CI::genAtomicMax), + {{{"a", asAddr}, {"v", asValue}}}, + false}, + {"atomicmaxi", + static_cast<CUDAIntrinsicLibrary::ElementalGenerator>(&CI::genAtomicMax), + {{{"a", asAddr}, {"v", asValue}}}, + false}, + {"atomicmaxl", + static_cast<CUDAIntrinsicLibrary::ElementalGenerator>(&CI::genAtomicMax), + {{{"a", asAddr}, {"v", asValue}}}, + false}, + {"atomicmind", + static_cast<CUDAIntrinsicLibrary::ElementalGenerator>(&CI::genAtomicMin), + {{{"a", asAddr}, {"v", asValue}}}, + false}, + {"atomicminf", + static_cast<CUDAIntrinsicLibrary::ElementalGenerator>(&CI::genAtomicMin), + {{{"a", asAddr}, {"v", asValue}}}, + false}, + {"atomicmini", + static_cast<CUDAIntrinsicLibrary::ElementalGenerator>(&CI::genAtomicMin), + {{{"a", asAddr}, {"v", asValue}}}, + false}, + {"atomicminl", + static_cast<CUDAIntrinsicLibrary::ElementalGenerator>(&CI::genAtomicMin), + {{{"a", asAddr}, {"v", asValue}}}, + false}, + {"atomicori", + static_cast<CUDAIntrinsicLibrary::ElementalGenerator>(&CI::genAtomicOr), + {{{"a", asAddr}, {"v", asValue}}}, + false}, + {"atomicsubd", + static_cast<CUDAIntrinsicLibrary::ElementalGenerator>(&CI::genAtomicSub), + {{{"a", asAddr}, {"v", asValue}}}, + false}, + {"atomicsubf", + static_cast<CUDAIntrinsicLibrary::ElementalGenerator>(&CI::genAtomicSub), + {{{"a", asAddr}, {"v", asValue}}}, + false}, + {"atomicsubi", + static_cast<CUDAIntrinsicLibrary::ElementalGenerator>(&CI::genAtomicSub), + {{{"a", asAddr}, {"v", asValue}}}, + false}, + {"atomicsubl", + static_cast<CUDAIntrinsicLibrary::ElementalGenerator>(&CI::genAtomicSub), + {{{"a", asAddr}, {"v", asValue}}}, + false}, + {"atomicxori", + static_cast<CUDAIntrinsicLibrary::ExtendedGenerator>(&CI::genAtomicXor), + {{{"a", asAddr}, {"v", asValue}}}, + false}, + {"ballot_sync", + static_cast<CUDAIntrinsicLibrary::ElementalGenerator>( + &CI::genVoteSync<mlir::NVVM::VoteSyncKind::ballot>), + {{{"mask", asValue}, {"pred", asValue}}}, + /*isElemental=*/false}, + {"barrier_arrive", + static_cast<CUDAIntrinsicLibrary::ElementalGenerator>( + &CI::genBarrierArrive), + {{{"barrier", asAddr}}}, + /*isElemental=*/false}, + {"barrier_arrive_cnt", + static_cast<CUDAIntrinsicLibrary::ElementalGenerator>( + &CI::genBarrierArriveCnt), + {{{"barrier", asAddr}, {"count", asValue}}}, + /*isElemental=*/false}, + {"barrier_init", + static_cast<CUDAIntrinsicLibrary::SubroutineGenerator>( + &CI::genBarrierInit), + {{{"barrier", asAddr}, {"count", asValue}}}, + /*isElemental=*/false}, + {"barrier_try_wait", + static_cast<CUDAIntrinsicLibrary::ElementalGenerator>( + &CI::genBarrierTryWait), + {{{"barrier", asAddr}, {"token", asValue}}}, + /*isElemental=*/false}, + {"barrier_try_wait_sleep", + static_cast<CUDAIntrinsicLibrary::ElementalGenerator>( + &CI::genBarrierTryWaitSleep), + {{{"barrier", asAddr}, {"token", asValue}, {"ns", asValue}}}, + /*isElemental=*/false}, + {"clock", + static_cast<CUDAIntrinsicLibrary::ElementalGenerator>( + &CI::genNVVMTime<mlir::NVVM::ClockOp>), + {}, + /*isElemental=*/false}, + {"clock64", + static_cast<CUDAIntrinsicLibrary::ElementalGenerator>( + &CI::genNVVMTime<mlir::NVVM::Clock64Op>), + {}, + /*isElemental=*/false}, + {"cluster_block_index", + static_cast<CUDAIntrinsicLibrary::ElementalGenerator>( + &CI::genClusterBlockIndex), + {}, + /*isElemental=*/false}, + {"cluster_dim_blocks", + static_cast<CUDAIntrinsicLibrary::ElementalGenerator>( + &CI::genClusterDimBlocks), + {}, + /*isElemental=*/false}, + {"fence_proxy_async", + static_cast<CUDAIntrinsicLibrary::SubroutineGenerator>( + &CI::genFenceProxyAsync), + {}, + /*isElemental=*/false}, + {"globaltimer", + static_cast<CUDAIntrinsicLibrary::ElementalGenerator>( + &CI::genNVVMTime<mlir::NVVM::GlobalTimerOp>), + {}, + /*isElemental=*/false}, + {"match_all_syncjd", + static_cast<CUDAIntrinsicLibrary::ElementalGenerator>( + &CI::genMatchAllSync), + {{{"mask", asValue}, {"value", asValue}, {"pred", asAddr}}}, + /*isElemental=*/false}, + {"match_all_syncjf", + static_cast<CUDAIntrinsicLibrary::ElementalGenerator>( + &CI::genMatchAllSync), + {{{"mask", asValue}, {"value", asValue}, {"pred", asAddr}}}, + /*isElemental=*/false}, + {"match_all_syncjj", + static_cast<CUDAIntrinsicLibrary::ElementalGenerator>( + &CI::genMatchAllSync), + {{{"mask", asValue}, {"value", asValue}, {"pred", asAddr}}}, + /*isElemental=*/false}, + {"match_all_syncjx", + static_cast<CUDAIntrinsicLibrary::ElementalGenerator>( + &CI::genMatchAllSync), + {{{"mask", asValue}, {"value", asValue}, {"pred", asAddr}}}, + /*isElemental=*/false}, + {"match_any_syncjd", + static_cast<CUDAIntrinsicLibrary::ElementalGenerator>( + &CI::genMatchAnySync), + {{{"mask", asValue}, {"value", asValue}}}, + /*isElemental=*/false}, + {"match_any_syncjf", + static_cast<CUDAIntrinsicLibrary::ElementalGenerator>( + &CI::genMatchAnySync), + {{{"mask", asValue}, {"value", asValue}}}, + /*isElemental=*/false}, + {"match_any_syncjj", + static_cast<CUDAIntrinsicLibrary::ElementalGenerator>( + &CI::genMatchAnySync), + {{{"mask", asValue}, {"value", asValue}}}, + /*isElemental=*/false}, + {"match_any_syncjx", + static_cast<CUDAIntrinsicLibrary::ElementalGenerator>( + &CI::genMatchAnySync), + {{{"mask", asValue}, {"value", asValue}}}, + /*isElemental=*/false}, + {"syncthreads", + static_cast<CUDAIntrinsicLibrary::SubroutineGenerator>( + &CI::genSyncThreads), + {}, + /*isElemental=*/false}, + {"syncthreads_and_i4", + static_cast<CUDAIntrinsicLibrary::ElementalGenerator>( + &CI::genSyncThreadsAnd), + {}, + /*isElemental=*/false}, + {"syncthreads_and_l4", + static_cast<CUDAIntrinsicLibrary::ElementalGenerator>( + &CI::genSyncThreadsAnd), + {}, + /*isElemental=*/false}, + {"syncthreads_count_i4", + static_cast<CUDAIntrinsicLibrary::ElementalGenerator>( + &CI::genSyncThreadsCount), + {}, + /*isElemental=*/false}, + {"syncthreads_count_l4", + static_cast<CUDAIntrinsicLibrary::ElementalGenerator>( + &CI::genSyncThreadsCount), + {}, + /*isElemental=*/false}, + {"syncthreads_or_i4", + static_cast<CUDAIntrinsicLibrary::ElementalGenerator>( + &CI::genSyncThreadsOr), + {}, + /*isElemental=*/false}, + {"syncthreads_or_l4", + static_cast<CUDAIntrinsicLibrary::ElementalGenerator>( + &CI::genSyncThreadsOr), + {}, + /*isElemental=*/false}, + {"syncwarp", + static_cast<CUDAIntrinsicLibrary::SubroutineGenerator>(&CI::genSyncWarp), + {}, + /*isElemental=*/false}, + {"this_cluster", + static_cast<CUDAIntrinsicLibrary::ElementalGenerator>(&CI::genThisCluster), + {}, + /*isElemental=*/false}, + {"this_grid", + static_cast<CUDAIntrinsicLibrary::ElementalGenerator>(&CI::genThisGrid), + {}, + /*isElemental=*/false}, + {"this_thread_block", + static_cast<CUDAIntrinsicLibrary::ElementalGenerator>( + &CI::genThisThreadBlock), + {}, + /*isElemental=*/false}, + {"this_warp", + static_cast<CUDAIntrinsicLibrary::ElementalGenerator>(&CI::genThisWarp), + {}, + /*isElemental=*/false}, + {"threadfence", + static_cast<CUDAIntrinsicLibrary::SubroutineGenerator>( + &CI::genThreadFence<mlir::NVVM::MemScopeKind::GPU>), + {}, + /*isElemental=*/false}, + {"threadfence_block", + static_cast<CUDAIntrinsicLibrary::SubroutineGenerator>( + &CI::genThreadFence<mlir::NVVM::MemScopeKind::CTA>), + {}, + /*isElemental=*/false}, + {"threadfence_system", + static_cast<CUDAIntrinsicLibrary::SubroutineGenerator>( + &CI::genThreadFence<mlir::NVVM::MemScopeKind::SYS>), + {}, + /*isElemental=*/false}, + {"tma_bulk_commit_group", + static_cast<CUDAIntrinsicLibrary::SubroutineGenerator>( + &CI::genTMABulkCommitGroup), + {{}}, + /*isElemental=*/false}, + {"tma_bulk_g2s", + static_cast<CUDAIntrinsicLibrary::SubroutineGenerator>(&CI::genTMABulkG2S), + {{{"barrier", asAddr}, + {"src", asAddr}, + {"dst", asAddr}, + {"nbytes", asValue}}}, + /*isElemental=*/false}, + {"tma_bulk_ldc4", + static_cast<CUDAIntrinsicLibrary::SubroutineGenerator>( + &CI::genTMABulkLoadC4), + {{{"barrier", asAddr}, + {"src", asAddr}, + {"dst", asAddr}, + {"nelems", asValue}}}, + /*isElemental=*/false}, + {"tma_bulk_ldc8", + static_cast<CUDAIntrinsicLibrary::SubroutineGenerator>( + &CI::genTMABulkLoadC8), + {{{"barrier", asAddr}, + {"src", asAddr}, + {"dst", asAddr}, + {"nelems", asValue}}}, + /*isElemental=*/false}, + {"tma_bulk_ldi4", + static_cast<CUDAIntrinsicLibrary::SubroutineGenerator>( + &CI::genTMABulkLoadI4), + {{{"barrier", asAddr}, + {"src", asAddr}, + {"dst", asAddr}, + {"nelems", asValue}}}, + /*isElemental=*/false}, + {"tma_bulk_ldi8", + static_cast<CUDAIntrinsicLibrary::SubroutineGenerator>( + &CI::genTMABulkLoadI8), + {{{"barrier", asAddr}, + {"src", asAddr}, + {"dst", asAddr}, + {"nelems", asValue}}}, + /*isElemental=*/false}, + {"tma_bulk_ldr2", + static_cast<CUDAIntrinsicLibrary::SubroutineGenerator>( + &CI::genTMABulkLoadR2), + {{{"barrier", asAddr}, + {"src", asAddr}, + {"dst", asAddr}, + {"nelems", asValue}}}, + /*isElemental=*/false}, + {"tma_bulk_ldr4", + static_cast<CUDAIntrinsicLibrary::SubroutineGenerator>( + &CI::genTMABulkLoadR4), + {{{"barrier", asAddr}, + {"src", asAddr}, + {"dst", asAddr}, + {"nelems", asValue}}}, + /*isElemental=*/false}, + {"tma_bulk_ldr8", + static_cast<CUDAIntrinsicLibrary::SubroutineGenerator>( + &CI::genTMABulkLoadR8), + {{{"barrier", asAddr}, + {"src", asAddr}, + {"dst", asAddr}, + {"nelems", asValue}}}, + /*isElemental=*/false}, + {"tma_bulk_s2g", + static_cast<CUDAIntrinsicLibrary::SubroutineGenerator>(&CI::genTMABulkS2G), + {{{"src", asAddr}, {"dst", asAddr}, {"nbytes", asValue}}}, + /*isElemental=*/false}, + {"tma_bulk_store_c4", + static_cast<CUDAIntrinsicLibrary::SubroutineGenerator>( + &CI::genTMABulkStoreC4), + {{{"src", asAddr}, {"dst", asAddr}, {"count", asValue}}}, + /*isElemental=*/false}, + {"tma_bulk_store_c8", + static_cast<CUDAIntrinsicLibrary::SubroutineGenerator>( + &CI::genTMABulkStoreC8), + {{{"src", asAddr}, {"dst", asAddr}, {"count", asValue}}}, + /*isElemental=*/false}, + {"tma_bulk_store_i4", + static_cast<CUDAIntrinsicLibrary::SubroutineGenerator>( + &CI::genTMABulkStoreI4), + {{{"src", asAddr}, {"dst", asAddr}, {"count", asValue}}}, + /*isElemental=*/false}, + {"tma_bulk_store_i8", + static_cast<CUDAIntrinsicLibrary::SubroutineGenerator>( + &CI::genTMABulkStoreI8), + {{{"src", asAddr}, {"dst", asAddr}, {"count", asValue}}}, + /*isElemental=*/false}, + {"tma_bulk_store_r2", + static_cast<CUDAIntrinsicLibrary::SubroutineGenerator>( + &CI::genTMABulkStoreR2), + {{{"src", asAddr}, {"dst", asAddr}, {"count", asValue}}}, + /*isElemental=*/false}, + {"tma_bulk_store_r4", + static_cast<CUDAIntrinsicLibrary::SubroutineGenerator>( + &CI::genTMABulkStoreR4), + {{{"src", asAddr}, {"dst", asAddr}, {"count", asValue}}}, + /*isElemental=*/false}, + {"tma_bulk_store_r8", + static_cast<CUDAIntrinsicLibrary::SubroutineGenerator>( + &CI::genTMABulkStoreR8), + {{{"src", asAddr}, {"dst", asAddr}, {"count", asValue}}}, + /*isElemental=*/false}, + {"tma_bulk_wait_group", + static_cast<CUDAIntrinsicLibrary::SubroutineGenerator>( + &CI::genTMABulkWaitGroup), + {{}}, + /*isElemental=*/false}, +}; + +template <std::size_t N> +static constexpr bool isSorted(const IntrinsicHandler (&array)[N]) { + // Replace by std::sorted when C++20 is default (will be constexpr). + const IntrinsicHandler *lastSeen{nullptr}; + bool isSorted{true}; + for (const auto &x : array) { + if (lastSeen) + isSorted &= std::string_view{lastSeen->name} < std::string_view{x.name}; + lastSeen = &x; + } + return isSorted; +} +static_assert(isSorted(cudaHandlers) && "map must be sorted"); + +const IntrinsicHandler *findCUDAIntrinsicHandler(llvm::StringRef name) { + auto compare = [](const IntrinsicHandler &cudaHandler, llvm::StringRef name) { + return name.compare(cudaHandler.name) > 0; + }; + auto result = llvm::lower_bound(cudaHandlers, name, compare); + return result != std::end(cudaHandlers) && result->name == name ? result + : nullptr; +} + +static mlir::Value convertPtrToNVVMSpace(fir::FirOpBuilder &builder, + mlir::Location loc, + mlir::Value barrier, + mlir::NVVM::NVVMMemorySpace space) { + mlir::Value llvmPtr = fir::ConvertOp::create( + builder, loc, mlir::LLVM::LLVMPointerType::get(builder.getContext()), + barrier); + mlir::Value addrCast = mlir::LLVM::AddrSpaceCastOp::create( + builder, loc, + mlir::LLVM::LLVMPointerType::get(builder.getContext(), + static_cast<unsigned>(space)), + llvmPtr); + return addrCast; +} + +static mlir::Value genAtomBinOp(fir::FirOpBuilder &builder, mlir::Location &loc, + mlir::LLVM::AtomicBinOp binOp, mlir::Value arg0, + mlir::Value arg1) { + auto llvmPointerType = mlir::LLVM::LLVMPointerType::get(builder.getContext()); + arg0 = builder.createConvert(loc, llvmPointerType, arg0); + return mlir::LLVM::AtomicRMWOp::create(builder, loc, binOp, arg0, arg1, + mlir::LLVM::AtomicOrdering::seq_cst); +} + +// ATOMICADD +mlir::Value +CUDAIntrinsicLibrary::genAtomicAdd(mlir::Type resultType, + llvm::ArrayRef<mlir::Value> args) { + assert(args.size() == 2); + mlir::LLVM::AtomicBinOp binOp = + mlir::isa<mlir::IntegerType>(args[1].getType()) + ? mlir::LLVM::AtomicBinOp::add + : mlir::LLVM::AtomicBinOp::fadd; + return genAtomBinOp(builder, loc, binOp, args[0], args[1]); +} + +fir::ExtendedValue +CUDAIntrinsicLibrary::genAtomicAddR2(mlir::Type resultType, + llvm::ArrayRef<fir::ExtendedValue> args) { + assert(args.size() == 2); + + mlir::Value a = fir::getBase(args[0]); + + if (mlir::isa<fir::BaseBoxType>(a.getType())) { + a = fir::BoxAddrOp::create(builder, loc, a); + } + + auto loc = builder.getUnknownLoc(); + auto f16Ty = builder.getF16Type(); + auto i32Ty = builder.getI32Type(); + auto vecF16Ty = mlir::VectorType::get({2}, f16Ty); + mlir::Type idxTy = builder.getIndexType(); + auto f16RefTy = fir::ReferenceType::get(f16Ty); + auto zero = builder.createIntegerConstant(loc, idxTy, 0); + auto one = builder.createIntegerConstant(loc, idxTy, 1); + auto v1Coord = fir::CoordinateOp::create(builder, loc, f16RefTy, + fir::getBase(args[1]), zero); + auto v2Coord = fir::CoordinateOp::create(builder, loc, f16RefTy, + fir::getBase(args[1]), one); + auto v1 = fir::LoadOp::create(builder, loc, v1Coord); + auto v2 = fir::LoadOp::create(builder, loc, v2Coord); + mlir::Value undef = mlir::LLVM::UndefOp::create(builder, loc, vecF16Ty); + mlir::Value vec1 = mlir::LLVM::InsertElementOp::create( + builder, loc, undef, v1, builder.createIntegerConstant(loc, i32Ty, 0)); + mlir::Value vec2 = mlir::LLVM::InsertElementOp::create( + builder, loc, vec1, v2, builder.createIntegerConstant(loc, i32Ty, 1)); + auto res = genAtomBinOp(builder, loc, mlir::LLVM::AtomicBinOp::fadd, a, vec2); + auto i32VecTy = mlir::VectorType::get({1}, i32Ty); + mlir::Value vecI32 = + mlir::vector::BitCastOp::create(builder, loc, i32VecTy, res); + return mlir::vector::ExtractOp::create(builder, loc, vecI32, + mlir::ArrayRef<int64_t>{0}); +} + +// ATOMICADDVECTOR +template <int extent> +fir::ExtendedValue CUDAIntrinsicLibrary::genAtomicAddVector( + mlir::Type resultType, llvm::ArrayRef<fir::ExtendedValue> args) { + assert(args.size() == 2); + mlir::Value res = fir::AllocaOp::create( + builder, loc, fir::SequenceType::get({extent}, resultType)); + mlir::Value a = fir::getBase(args[0]); + if (mlir::isa<fir::BaseBoxType>(a.getType())) { + a = fir::BoxAddrOp::create(builder, loc, a); + } + auto vecTy = mlir::VectorType::get({extent}, resultType); + auto refTy = fir::ReferenceType::get(resultType); + mlir::Type i32Ty = builder.getI32Type(); + mlir::Type idxTy = builder.getIndexType(); + + // Extract the values from the array. + llvm::SmallVector<mlir::Value> values; + for (unsigned i = 0; i < extent; ++i) { + mlir::Value pos = builder.createIntegerConstant(loc, idxTy, i); + mlir::Value coord = fir::CoordinateOp::create(builder, loc, refTy, + fir::getBase(args[1]), pos); + mlir::Value value = fir::LoadOp::create(builder, loc, coord); + values.push_back(value); + } + // Pack extracted values into a vector to call the atomic add. + mlir::Value undef = mlir::LLVM::UndefOp::create(builder, loc, vecTy); + for (unsigned i = 0; i < extent; ++i) { + mlir::Value insert = mlir::LLVM::InsertElementOp::create( + builder, loc, undef, values[i], + builder.createIntegerConstant(loc, i32Ty, i)); + undef = insert; + } + // Atomic operation with a vector of values. + mlir::Value add = + genAtomBinOp(builder, loc, mlir::LLVM::AtomicBinOp::fadd, a, undef); + // Store results in the result array. + for (unsigned i = 0; i < extent; ++i) { + mlir::Value r = mlir::LLVM::ExtractElementOp::create( + builder, loc, add, builder.createIntegerConstant(loc, i32Ty, i)); + mlir::Value c = fir::CoordinateOp::create( + builder, loc, refTy, res, builder.createIntegerConstant(loc, idxTy, i)); + fir::StoreOp::create(builder, loc, r, c); + } + mlir::Value ext = builder.createIntegerConstant(loc, idxTy, extent); + return fir::ArrayBoxValue(res, {ext}); +} + +// ATOMICADDVECTOR4x4 +fir::ExtendedValue CUDAIntrinsicLibrary::genAtomicAddVector4x4( + mlir::Type resultType, llvm::ArrayRef<fir::ExtendedValue> args) { + assert(args.size() == 2); + mlir::Value a = fir::getBase(args[0]); + if (mlir::isa<fir::BaseBoxType>(a.getType())) + a = fir::BoxAddrOp::create(builder, loc, a); + + const unsigned extent = 4; + auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(builder.getContext()); + mlir::Value ptr = builder.createConvert(loc, llvmPtrTy, a); + mlir::Type f32Ty = builder.getF32Type(); + mlir::Type idxTy = builder.getIndexType(); + mlir::Type refTy = fir::ReferenceType::get(f32Ty); + llvm::SmallVector<mlir::Value> values; + for (unsigned i = 0; i < extent; ++i) { + mlir::Value pos = builder.createIntegerConstant(loc, idxTy, i); + mlir::Value coord = fir::CoordinateOp::create(builder, loc, refTy, + fir::getBase(args[1]), pos); + mlir::Value value = fir::LoadOp::create(builder, loc, coord); + values.push_back(value); + } + + auto inlinePtx = mlir::NVVM::InlinePtxOp::create( + builder, loc, {f32Ty, f32Ty, f32Ty, f32Ty}, + {ptr, values[0], values[1], values[2], values[3]}, {}, + "atom.add.v4.f32 {%0, %1, %2, %3}, [%4], {%5, %6, %7, %8};", {}); + + llvm::SmallVector<mlir::Value> results; + results.push_back(inlinePtx.getResult(0)); + results.push_back(inlinePtx.getResult(1)); + results.push_back(inlinePtx.getResult(2)); + results.push_back(inlinePtx.getResult(3)); + + mlir::Type vecF32Ty = mlir::VectorType::get({extent}, f32Ty); + mlir::Value undef = mlir::LLVM::UndefOp::create(builder, loc, vecF32Ty); + mlir::Type i32Ty = builder.getI32Type(); + for (unsigned i = 0; i < extent; ++i) + undef = mlir::LLVM::InsertElementOp::create( + builder, loc, undef, results[i], + builder.createIntegerConstant(loc, i32Ty, i)); + + auto i128Ty = builder.getIntegerType(128); + auto i128VecTy = mlir::VectorType::get({1}, i128Ty); + mlir::Value vec128 = + mlir::vector::BitCastOp::create(builder, loc, i128VecTy, undef); + return mlir::vector::ExtractOp::create(builder, loc, vec128, + mlir::ArrayRef<int64_t>{0}); +} + +mlir::Value +CUDAIntrinsicLibrary::genAtomicAnd(mlir::Type resultType, + llvm::ArrayRef<mlir::Value> args) { + assert(args.size() == 2); + assert(mlir::isa<mlir::IntegerType>(args[1].getType())); + + mlir::LLVM::AtomicBinOp binOp = mlir::LLVM::AtomicBinOp::_and; + return genAtomBinOp(builder, loc, binOp, args[0], args[1]); +} + +mlir::Value +CUDAIntrinsicLibrary::genAtomicOr(mlir::Type resultType, + llvm::ArrayRef<mlir::Value> args) { + assert(args.size() == 2); + assert(mlir::isa<mlir::IntegerType>(args[1].getType())); + + mlir::LLVM::AtomicBinOp binOp = mlir::LLVM::AtomicBinOp::_or; + return genAtomBinOp(builder, loc, binOp, args[0], args[1]); +} + +// ATOMICCAS +fir::ExtendedValue +CUDAIntrinsicLibrary::genAtomicCas(mlir::Type resultType, + llvm::ArrayRef<fir::ExtendedValue> args) { + assert(args.size() == 3); + auto successOrdering = mlir::LLVM::AtomicOrdering::acq_rel; + auto failureOrdering = mlir::LLVM::AtomicOrdering::monotonic; + auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(resultType.getContext()); + + mlir::Value arg0 = fir::getBase(args[0]); + mlir::Value arg1 = fir::getBase(args[1]); + mlir::Value arg2 = fir::getBase(args[2]); + + auto bitCastFloat = [&](mlir::Value arg) -> mlir::Value { + if (mlir::isa<mlir::Float32Type>(arg.getType())) + return mlir::LLVM::BitcastOp::create(builder, loc, builder.getI32Type(), + arg); + if (mlir::isa<mlir::Float64Type>(arg.getType())) + return mlir::LLVM::BitcastOp::create(builder, loc, builder.getI64Type(), + arg); + return arg; + }; + + arg1 = bitCastFloat(arg1); + arg2 = bitCastFloat(arg2); + + if (arg1.getType() != arg2.getType()) { + // arg1 and arg2 need to have the same type in AtomicCmpXchgOp. + arg2 = builder.createConvert(loc, arg1.getType(), arg2); + } + + auto address = + mlir::UnrealizedConversionCastOp::create(builder, loc, llvmPtrTy, arg0) + .getResult(0); + auto cmpxchg = mlir::LLVM::AtomicCmpXchgOp::create( + builder, loc, address, arg1, arg2, successOrdering, failureOrdering); + mlir::Value boolResult = + mlir::LLVM::ExtractValueOp::create(builder, loc, cmpxchg, 1); + return builder.createConvert(loc, resultType, boolResult); +} + +mlir::Value +CUDAIntrinsicLibrary::genAtomicDec(mlir::Type resultType, + llvm::ArrayRef<mlir::Value> args) { + assert(args.size() == 2); + assert(mlir::isa<mlir::IntegerType>(args[1].getType())); + + mlir::LLVM::AtomicBinOp binOp = mlir::LLVM::AtomicBinOp::udec_wrap; + return genAtomBinOp(builder, loc, binOp, args[0], args[1]); +} + +// ATOMICEXCH +fir::ExtendedValue +CUDAIntrinsicLibrary::genAtomicExch(mlir::Type resultType, + llvm::ArrayRef<fir::ExtendedValue> args) { + assert(args.size() == 2); + mlir::Value arg0 = fir::getBase(args[0]); + mlir::Value arg1 = fir::getBase(args[1]); + assert(arg1.getType().isIntOrFloat()); + + mlir::LLVM::AtomicBinOp binOp = mlir::LLVM::AtomicBinOp::xchg; + return genAtomBinOp(builder, loc, binOp, arg0, arg1); +} + +mlir::Value +CUDAIntrinsicLibrary::genAtomicInc(mlir::Type resultType, + llvm::ArrayRef<mlir::Value> args) { + assert(args.size() == 2); + assert(mlir::isa<mlir::IntegerType>(args[1].getType())); + + mlir::LLVM::AtomicBinOp binOp = mlir::LLVM::AtomicBinOp::uinc_wrap; + return genAtomBinOp(builder, loc, binOp, args[0], args[1]); +} + +mlir::Value +CUDAIntrinsicLibrary::genAtomicMax(mlir::Type resultType, + llvm::ArrayRef<mlir::Value> args) { + assert(args.size() == 2); + + mlir::LLVM::AtomicBinOp binOp = + mlir::isa<mlir::IntegerType>(args[1].getType()) + ? mlir::LLVM::AtomicBinOp::max + : mlir::LLVM::AtomicBinOp::fmax; + return genAtomBinOp(builder, loc, binOp, args[0], args[1]); +} + +mlir::Value +CUDAIntrinsicLibrary::genAtomicMin(mlir::Type resultType, + llvm::ArrayRef<mlir::Value> args) { + assert(args.size() == 2); + + mlir::LLVM::AtomicBinOp binOp = + mlir::isa<mlir::IntegerType>(args[1].getType()) + ? mlir::LLVM::AtomicBinOp::min + : mlir::LLVM::AtomicBinOp::fmin; + return genAtomBinOp(builder, loc, binOp, args[0], args[1]); +} + +// ATOMICSUB +mlir::Value +CUDAIntrinsicLibrary::genAtomicSub(mlir::Type resultType, + llvm::ArrayRef<mlir::Value> args) { + assert(args.size() == 2); + mlir::LLVM::AtomicBinOp binOp = + mlir::isa<mlir::IntegerType>(args[1].getType()) + ? mlir::LLVM::AtomicBinOp::sub + : mlir::LLVM::AtomicBinOp::fsub; + return genAtomBinOp(builder, loc, binOp, args[0], args[1]); +} + +// ATOMICXOR +fir::ExtendedValue +CUDAIntrinsicLibrary::genAtomicXor(mlir::Type resultType, + llvm::ArrayRef<fir::ExtendedValue> args) { + assert(args.size() == 2); + mlir::Value arg0 = fir::getBase(args[0]); + mlir::Value arg1 = fir::getBase(args[1]); + return genAtomBinOp(builder, loc, mlir::LLVM::AtomicBinOp::_xor, arg0, arg1); +} + +// BARRIER_ARRIVE +mlir::Value +CUDAIntrinsicLibrary::genBarrierArrive(mlir::Type resultType, + llvm::ArrayRef<mlir::Value> args) { + assert(args.size() == 1); + mlir::Value barrier = convertPtrToNVVMSpace( + builder, loc, args[0], mlir::NVVM::NVVMMemorySpace::Shared); + return mlir::NVVM::MBarrierArriveOp::create(builder, loc, resultType, barrier) + .getResult(0); +} + +// BARRIER_ARRIBVE_CNT +mlir::Value +CUDAIntrinsicLibrary::genBarrierArriveCnt(mlir::Type resultType, + llvm::ArrayRef<mlir::Value> args) { + assert(args.size() == 2); + mlir::Value barrier = convertPtrToNVVMSpace( + builder, loc, args[0], mlir::NVVM::NVVMMemorySpace::Shared); + return mlir::NVVM::InlinePtxOp::create(builder, loc, {resultType}, + {barrier, args[1]}, {}, + "mbarrier.arrive.expect_tx.release." + "cta.shared::cta.b64 %0, [%1], %2;", + {}) + .getResult(0); +} + +// BARRIER_INIT +void CUDAIntrinsicLibrary::genBarrierInit( + llvm::ArrayRef<fir::ExtendedValue> args) { + assert(args.size() == 2); + mlir::Value barrier = convertPtrToNVVMSpace( + builder, loc, fir::getBase(args[0]), mlir::NVVM::NVVMMemorySpace::Shared); + mlir::NVVM::MBarrierInitOp::create(builder, loc, barrier, + fir::getBase(args[1]), {}); + auto kind = mlir::NVVM::ProxyKindAttr::get( + builder.getContext(), mlir::NVVM::ProxyKind::async_shared); + auto space = mlir::NVVM::SharedSpaceAttr::get( + builder.getContext(), mlir::NVVM::SharedSpace::shared_cta); + mlir::NVVM::FenceProxyOp::create(builder, loc, kind, space); +} + +// BARRIER_TRY_WAIT +mlir::Value +CUDAIntrinsicLibrary::genBarrierTryWait(mlir::Type resultType, + llvm::ArrayRef<mlir::Value> args) { + assert(args.size() == 2); + mlir::Value res = fir::AllocaOp::create(builder, loc, resultType); + mlir::Value zero = builder.createIntegerConstant(loc, resultType, 0); + fir::StoreOp::create(builder, loc, zero, res); + mlir::Value ns = + builder.createIntegerConstant(loc, builder.getI32Type(), 1000000); + mlir::Value load = fir::LoadOp::create(builder, loc, res); + auto whileOp = mlir::scf::WhileOp::create( + builder, loc, mlir::TypeRange{resultType}, mlir::ValueRange{load}); + mlir::Block *beforeBlock = builder.createBlock(&whileOp.getBefore()); + mlir::Value beforeArg = beforeBlock->addArgument(resultType, loc); + builder.setInsertionPointToStart(beforeBlock); + mlir::Value condition = mlir::arith::CmpIOp::create( + builder, loc, mlir::arith::CmpIPredicate::ne, beforeArg, zero); + mlir::scf::ConditionOp::create(builder, loc, condition, beforeArg); + mlir::Block *afterBlock = builder.createBlock(&whileOp.getAfter()); + afterBlock->addArgument(resultType, loc); + builder.setInsertionPointToStart(afterBlock); + auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(builder.getContext()); + auto barrier = builder.createConvert(loc, llvmPtrTy, args[0]); + mlir::Value ret = mlir::NVVM::InlinePtxOp::create( + builder, loc, {resultType}, {barrier, args[1], ns}, {}, + "{\n" + " .reg .pred p;\n" + " mbarrier.try_wait.shared.b64 p, [%1], %2, %3;\n" + " selp.b32 %0, 1, 0, p;\n" + "}", + {}) + .getResult(0); + mlir::scf::YieldOp::create(builder, loc, ret); + builder.setInsertionPointAfter(whileOp); + return whileOp.getResult(0); +} + +// BARRIER_TRY_WAIT_SLEEP +mlir::Value +CUDAIntrinsicLibrary::genBarrierTryWaitSleep(mlir::Type resultType, + llvm::ArrayRef<mlir::Value> args) { + assert(args.size() == 3); + auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(builder.getContext()); + auto barrier = builder.createConvert(loc, llvmPtrTy, args[0]); + return mlir::NVVM::InlinePtxOp::create( + builder, loc, {resultType}, {barrier, args[1], args[2]}, {}, + "{\n" + " .reg .pred p;\n" + " mbarrier.try_wait.shared.b64 p, [%1], %2, %3;\n" + " selp.b32 %0, 1, 0, p;\n" + "}", + {}) + .getResult(0); +} + +static void insertValueAtPos(fir::FirOpBuilder &builder, mlir::Location loc, + fir::RecordType recTy, mlir::Value base, + mlir::Value dim, unsigned fieldPos) { + auto fieldName = recTy.getTypeList()[fieldPos].first; + mlir::Type fieldTy = recTy.getTypeList()[fieldPos].second; + mlir::Type fieldIndexType = fir::FieldType::get(base.getContext()); + mlir::Value fieldIndex = + fir::FieldIndexOp::create(builder, loc, fieldIndexType, fieldName, recTy, + /*typeParams=*/mlir::ValueRange{}); + mlir::Value coord = fir::CoordinateOp::create( + builder, loc, builder.getRefType(fieldTy), base, fieldIndex); + fir::StoreOp::create(builder, loc, dim, coord); +} + +// CLUSTER_BLOCK_INDEX +mlir::Value +CUDAIntrinsicLibrary::genClusterBlockIndex(mlir::Type resultType, + llvm::ArrayRef<mlir::Value> args) { + assert(args.size() == 0); + auto recTy = mlir::cast<fir::RecordType>(resultType); + assert(recTy && "RecordType expepected"); + mlir::Value res = fir::AllocaOp::create(builder, loc, resultType); + mlir::Type i32Ty = builder.getI32Type(); + mlir::Value x = mlir::NVVM::BlockInClusterIdXOp::create(builder, loc, i32Ty); + mlir::Value one = builder.createIntegerConstant(loc, i32Ty, 1); + x = mlir::arith::AddIOp::create(builder, loc, x, one); + insertValueAtPos(builder, loc, recTy, res, x, 0); + mlir::Value y = mlir::NVVM::BlockInClusterIdYOp::create(builder, loc, i32Ty); + y = mlir::arith::AddIOp::create(builder, loc, y, one); + insertValueAtPos(builder, loc, recTy, res, y, 1); + mlir::Value z = mlir::NVVM::BlockInClusterIdZOp::create(builder, loc, i32Ty); + z = mlir::arith::AddIOp::create(builder, loc, z, one); + insertValueAtPos(builder, loc, recTy, res, z, 2); + return res; +} + +// CLUSTER_DIM_BLOCKS +mlir::Value +CUDAIntrinsicLibrary::genClusterDimBlocks(mlir::Type resultType, + llvm::ArrayRef<mlir::Value> args) { + assert(args.size() == 0); + auto recTy = mlir::cast<fir::RecordType>(resultType); + assert(recTy && "RecordType expepected"); + mlir::Value res = fir::AllocaOp::create(builder, loc, resultType); + mlir::Type i32Ty = builder.getI32Type(); + mlir::Value x = mlir::NVVM::ClusterDimBlocksXOp::create(builder, loc, i32Ty); + insertValueAtPos(builder, loc, recTy, res, x, 0); + mlir::Value y = mlir::NVVM::ClusterDimBlocksYOp::create(builder, loc, i32Ty); + insertValueAtPos(builder, loc, recTy, res, y, 1); + mlir::Value z = mlir::NVVM::ClusterDimBlocksZOp::create(builder, loc, i32Ty); + insertValueAtPos(builder, loc, recTy, res, z, 2); + return res; +} + +// FENCE_PROXY_ASYNC +void CUDAIntrinsicLibrary::genFenceProxyAsync( + llvm::ArrayRef<fir::ExtendedValue> args) { + assert(args.size() == 0); + auto kind = mlir::NVVM::ProxyKindAttr::get( + builder.getContext(), mlir::NVVM::ProxyKind::async_shared); + auto space = mlir::NVVM::SharedSpaceAttr::get( + builder.getContext(), mlir::NVVM::SharedSpace::shared_cta); + mlir::NVVM::FenceProxyOp::create(builder, loc, kind, space); +} + +// __LDCA, __LDCS, __LDLU, __LDCV +template <const char *fctName, int extent> +fir::ExtendedValue +CUDAIntrinsicLibrary::genLDXXFunc(mlir::Type resultType, + llvm::ArrayRef<fir::ExtendedValue> args) { + assert(args.size() == 1); + mlir::Type resTy = fir::SequenceType::get(extent, resultType); + mlir::Value arg = fir::getBase(args[0]); + mlir::Value res = fir::AllocaOp::create(builder, loc, resTy); + if (mlir::isa<fir::BaseBoxType>(arg.getType())) + arg = fir::BoxAddrOp::create(builder, loc, arg); + mlir::Type refResTy = fir::ReferenceType::get(resTy); + mlir::FunctionType ftype = + mlir::FunctionType::get(arg.getContext(), {refResTy, refResTy}, {}); + auto funcOp = builder.createFunction(loc, fctName, ftype); + llvm::SmallVector<mlir::Value> funcArgs; + funcArgs.push_back(res); + funcArgs.push_back(arg); + fir::CallOp::create(builder, loc, funcOp, funcArgs); + mlir::Value ext = + builder.createIntegerConstant(loc, builder.getIndexType(), extent); + return fir::ArrayBoxValue(res, {ext}); +} + +// CLOCK, CLOCK64, GLOBALTIMER +template <typename OpTy> +mlir::Value +CUDAIntrinsicLibrary::genNVVMTime(mlir::Type resultType, + llvm::ArrayRef<mlir::Value> args) { + assert(args.size() == 0 && "expect no arguments"); + return OpTy::create(builder, loc, resultType).getResult(); +} + +// MATCH_ALL_SYNC +mlir::Value +CUDAIntrinsicLibrary::genMatchAllSync(mlir::Type resultType, + llvm::ArrayRef<mlir::Value> args) { + assert(args.size() == 3); + bool is32 = args[1].getType().isInteger(32) || args[1].getType().isF32(); + + mlir::Type i1Ty = builder.getI1Type(); + mlir::MLIRContext *context = builder.getContext(); + + mlir::Value arg1 = args[1]; + if (arg1.getType().isF32() || arg1.getType().isF64()) + arg1 = fir::ConvertOp::create( + builder, loc, is32 ? builder.getI32Type() : builder.getI64Type(), arg1); + + mlir::Type retTy = + mlir::LLVM::LLVMStructType::getLiteral(context, {resultType, i1Ty}); + auto match = + mlir::NVVM::MatchSyncOp::create(builder, loc, retTy, args[0], arg1, + mlir::NVVM::MatchSyncKind::all) + .getResult(); + auto value = mlir::LLVM::ExtractValueOp::create(builder, loc, match, 0); + auto pred = mlir::LLVM::ExtractValueOp::create(builder, loc, match, 1); + auto conv = mlir::LLVM::ZExtOp::create(builder, loc, resultType, pred); + fir::StoreOp::create(builder, loc, conv, args[2]); + return value; +} + +// MATCH_ANY_SYNC +mlir::Value +CUDAIntrinsicLibrary::genMatchAnySync(mlir::Type resultType, + llvm::ArrayRef<mlir::Value> args) { + assert(args.size() == 2); + bool is32 = args[1].getType().isInteger(32) || args[1].getType().isF32(); + + mlir::Value arg1 = args[1]; + if (arg1.getType().isF32() || arg1.getType().isF64()) + arg1 = fir::ConvertOp::create( + builder, loc, is32 ? builder.getI32Type() : builder.getI64Type(), arg1); + + return mlir::NVVM::MatchSyncOp::create(builder, loc, resultType, args[0], + arg1, mlir::NVVM::MatchSyncKind::any) + .getResult(); +} + +// SYNCTHREADS +void CUDAIntrinsicLibrary::genSyncThreads( + llvm::ArrayRef<fir::ExtendedValue> args) { + mlir::NVVM::Barrier0Op::create(builder, loc); +} + +// SYNCTHREADS_AND +mlir::Value +CUDAIntrinsicLibrary::genSyncThreadsAnd(mlir::Type resultType, + llvm::ArrayRef<mlir::Value> args) { + mlir::Value arg = builder.createConvert(loc, builder.getI32Type(), args[0]); + return mlir::NVVM::BarrierOp::create( + builder, loc, resultType, {}, {}, + mlir::NVVM::BarrierReductionAttr::get( + builder.getContext(), mlir::NVVM::BarrierReduction::AND), + arg) + .getResult(0); +} + +// SYNCTHREADS_COUNT +mlir::Value +CUDAIntrinsicLibrary::genSyncThreadsCount(mlir::Type resultType, + llvm::ArrayRef<mlir::Value> args) { + mlir::Value arg = builder.createConvert(loc, builder.getI32Type(), args[0]); + return mlir::NVVM::BarrierOp::create( + builder, loc, resultType, {}, {}, + mlir::NVVM::BarrierReductionAttr::get( + builder.getContext(), mlir::NVVM::BarrierReduction::POPC), + arg) + .getResult(0); +} + +// SYNCTHREADS_OR +mlir::Value +CUDAIntrinsicLibrary::genSyncThreadsOr(mlir::Type resultType, + llvm::ArrayRef<mlir::Value> args) { + mlir::Value arg = builder.createConvert(loc, builder.getI32Type(), args[0]); + return mlir::NVVM::BarrierOp::create( + builder, loc, resultType, {}, {}, + mlir::NVVM::BarrierReductionAttr::get( + builder.getContext(), mlir::NVVM::BarrierReduction::OR), + arg) + .getResult(0); +} + +// SYNCWARP +void CUDAIntrinsicLibrary::genSyncWarp( + llvm::ArrayRef<fir::ExtendedValue> args) { + assert(args.size() == 1); + mlir::NVVM::SyncWarpOp::create(builder, loc, fir::getBase(args[0])); +} + +// THIS_CLUSTER +mlir::Value +CUDAIntrinsicLibrary::genThisCluster(mlir::Type resultType, + llvm::ArrayRef<mlir::Value> args) { + assert(args.size() == 0); + auto recTy = mlir::cast<fir::RecordType>(resultType); + assert(recTy && "RecordType expepected"); + mlir::Value res = fir::AllocaOp::create(builder, loc, resultType); + mlir::Type i32Ty = builder.getI32Type(); + + // SIZE + mlir::Value size = mlir::NVVM::ClusterDim::create(builder, loc, i32Ty); + auto sizeFieldName = recTy.getTypeList()[1].first; + mlir::Type sizeFieldTy = recTy.getTypeList()[1].second; + mlir::Type fieldIndexType = fir::FieldType::get(resultType.getContext()); + mlir::Value sizeFieldIndex = fir::FieldIndexOp::create( + builder, loc, fieldIndexType, sizeFieldName, recTy, + /*typeParams=*/mlir::ValueRange{}); + mlir::Value sizeCoord = fir::CoordinateOp::create( + builder, loc, builder.getRefType(sizeFieldTy), res, sizeFieldIndex); + fir::StoreOp::create(builder, loc, size, sizeCoord); + + // RANK + mlir::Value rank = mlir::NVVM::ClusterId::create(builder, loc, i32Ty); + mlir::Value one = builder.createIntegerConstant(loc, i32Ty, 1); + rank = mlir::arith::AddIOp::create(builder, loc, rank, one); + auto rankFieldName = recTy.getTypeList()[2].first; + mlir::Type rankFieldTy = recTy.getTypeList()[2].second; + mlir::Value rankFieldIndex = fir::FieldIndexOp::create( + builder, loc, fieldIndexType, rankFieldName, recTy, + /*typeParams=*/mlir::ValueRange{}); + mlir::Value rankCoord = fir::CoordinateOp::create( + builder, loc, builder.getRefType(rankFieldTy), res, rankFieldIndex); + fir::StoreOp::create(builder, loc, rank, rankCoord); + + return res; +} + +// THIS_GRID +mlir::Value +CUDAIntrinsicLibrary::genThisGrid(mlir::Type resultType, + llvm::ArrayRef<mlir::Value> args) { + assert(args.size() == 0); + auto recTy = mlir::cast<fir::RecordType>(resultType); + assert(recTy && "RecordType expepected"); + mlir::Value res = fir::AllocaOp::create(builder, loc, resultType); + mlir::Type i32Ty = builder.getI32Type(); + + mlir::Value threadIdX = mlir::NVVM::ThreadIdXOp::create(builder, loc, i32Ty); + mlir::Value threadIdY = mlir::NVVM::ThreadIdYOp::create(builder, loc, i32Ty); + mlir::Value threadIdZ = mlir::NVVM::ThreadIdZOp::create(builder, loc, i32Ty); + + mlir::Value blockIdX = mlir::NVVM::BlockIdXOp::create(builder, loc, i32Ty); + mlir::Value blockIdY = mlir::NVVM::BlockIdYOp::create(builder, loc, i32Ty); + mlir::Value blockIdZ = mlir::NVVM::BlockIdZOp::create(builder, loc, i32Ty); + + mlir::Value blockDimX = mlir::NVVM::BlockDimXOp::create(builder, loc, i32Ty); + mlir::Value blockDimY = mlir::NVVM::BlockDimYOp::create(builder, loc, i32Ty); + mlir::Value blockDimZ = mlir::NVVM::BlockDimZOp::create(builder, loc, i32Ty); + mlir::Value gridDimX = mlir::NVVM::GridDimXOp::create(builder, loc, i32Ty); + mlir::Value gridDimY = mlir::NVVM::GridDimYOp::create(builder, loc, i32Ty); + mlir::Value gridDimZ = mlir::NVVM::GridDimZOp::create(builder, loc, i32Ty); + + // this_grid.size = ((blockDim.z * gridDim.z) * (blockDim.y * gridDim.y)) * + // (blockDim.x * gridDim.x); + mlir::Value resZ = + mlir::arith::MulIOp::create(builder, loc, blockDimZ, gridDimZ); + mlir::Value resY = + mlir::arith::MulIOp::create(builder, loc, blockDimY, gridDimY); + mlir::Value resX = + mlir::arith::MulIOp::create(builder, loc, blockDimX, gridDimX); + mlir::Value resZY = mlir::arith::MulIOp::create(builder, loc, resZ, resY); + mlir::Value size = mlir::arith::MulIOp::create(builder, loc, resZY, resX); + + // tmp = ((blockIdx.z * gridDim.y * gridDim.x) + (blockIdx.y * gridDim.x)) + + // blockIdx.x; + // this_group.rank = tmp * ((blockDim.x * blockDim.y) * blockDim.z) + + // ((threadIdx.z * blockDim.y) * blockDim.x) + + // (threadIdx.y * blockDim.x) + threadIdx.x + 1; + mlir::Value r1 = + mlir::arith::MulIOp::create(builder, loc, blockIdZ, gridDimY); + mlir::Value r2 = mlir::arith::MulIOp::create(builder, loc, r1, gridDimX); + mlir::Value r3 = + mlir::arith::MulIOp::create(builder, loc, blockIdY, gridDimX); + mlir::Value r2r3 = mlir::arith::AddIOp::create(builder, loc, r2, r3); + mlir::Value tmp = mlir::arith::AddIOp::create(builder, loc, r2r3, blockIdX); + + mlir::Value bXbY = + mlir::arith::MulIOp::create(builder, loc, blockDimX, blockDimY); + mlir::Value bXbYbZ = + mlir::arith::MulIOp::create(builder, loc, bXbY, blockDimZ); + mlir::Value tZbY = + mlir::arith::MulIOp::create(builder, loc, threadIdZ, blockDimY); + mlir::Value tZbYbX = + mlir::arith::MulIOp::create(builder, loc, tZbY, blockDimX); + mlir::Value tYbX = + mlir::arith::MulIOp::create(builder, loc, threadIdY, blockDimX); + mlir::Value rank = mlir::arith::MulIOp::create(builder, loc, tmp, bXbYbZ); + rank = mlir::arith::AddIOp::create(builder, loc, rank, tZbYbX); + rank = mlir::arith::AddIOp::create(builder, loc, rank, tYbX); + rank = mlir::arith::AddIOp::create(builder, loc, rank, threadIdX); + mlir::Value one = builder.createIntegerConstant(loc, i32Ty, 1); + rank = mlir::arith::AddIOp::create(builder, loc, rank, one); + + auto sizeFieldName = recTy.getTypeList()[1].first; + mlir::Type sizeFieldTy = recTy.getTypeList()[1].second; + mlir::Type fieldIndexType = fir::FieldType::get(resultType.getContext()); + mlir::Value sizeFieldIndex = fir::FieldIndexOp::create( + builder, loc, fieldIndexType, sizeFieldName, recTy, + /*typeParams=*/mlir::ValueRange{}); + mlir::Value sizeCoord = fir::CoordinateOp::create( + builder, loc, builder.getRefType(sizeFieldTy), res, sizeFieldIndex); + fir::StoreOp::create(builder, loc, size, sizeCoord); + + auto rankFieldName = recTy.getTypeList()[2].first; + mlir::Type rankFieldTy = recTy.getTypeList()[2].second; + mlir::Value rankFieldIndex = fir::FieldIndexOp::create( + builder, loc, fieldIndexType, rankFieldName, recTy, + /*typeParams=*/mlir::ValueRange{}); + mlir::Value rankCoord = fir::CoordinateOp::create( + builder, loc, builder.getRefType(rankFieldTy), res, rankFieldIndex); + fir::StoreOp::create(builder, loc, rank, rankCoord); + return res; +} + +// THIS_THREAD_BLOCK +mlir::Value +CUDAIntrinsicLibrary::genThisThreadBlock(mlir::Type resultType, + llvm::ArrayRef<mlir::Value> args) { + assert(args.size() == 0); + auto recTy = mlir::cast<fir::RecordType>(resultType); + assert(recTy && "RecordType expepected"); + mlir::Value res = fir::AllocaOp::create(builder, loc, resultType); + mlir::Type i32Ty = builder.getI32Type(); + + // this_thread_block%size = blockDim.z * blockDim.y * blockDim.x; + mlir::Value blockDimX = mlir::NVVM::BlockDimXOp::create(builder, loc, i32Ty); + mlir::Value blockDimY = mlir::NVVM::BlockDimYOp::create(builder, loc, i32Ty); + mlir::Value blockDimZ = mlir::NVVM::BlockDimZOp::create(builder, loc, i32Ty); + mlir::Value size = + mlir::arith::MulIOp::create(builder, loc, blockDimZ, blockDimY); + size = mlir::arith::MulIOp::create(builder, loc, size, blockDimX); + + // this_thread_block%rank = ((threadIdx.z * blockDim.y) * blockDim.x) + + // (threadIdx.y * blockDim.x) + threadIdx.x + 1; + mlir::Value threadIdX = mlir::NVVM::ThreadIdXOp::create(builder, loc, i32Ty); + mlir::Value threadIdY = mlir::NVVM::ThreadIdYOp::create(builder, loc, i32Ty); + mlir::Value threadIdZ = mlir::NVVM::ThreadIdZOp::create(builder, loc, i32Ty); + mlir::Value r1 = + mlir::arith::MulIOp::create(builder, loc, threadIdZ, blockDimY); + mlir::Value r2 = mlir::arith::MulIOp::create(builder, loc, r1, blockDimX); + mlir::Value r3 = + mlir::arith::MulIOp::create(builder, loc, threadIdY, blockDimX); + mlir::Value r2r3 = mlir::arith::AddIOp::create(builder, loc, r2, r3); + mlir::Value rank = mlir::arith::AddIOp::create(builder, loc, r2r3, threadIdX); + mlir::Value one = builder.createIntegerConstant(loc, i32Ty, 1); + rank = mlir::arith::AddIOp::create(builder, loc, rank, one); + + auto sizeFieldName = recTy.getTypeList()[1].first; + mlir::Type sizeFieldTy = recTy.getTypeList()[1].second; + mlir::Type fieldIndexType = fir::FieldType::get(resultType.getContext()); + mlir::Value sizeFieldIndex = fir::FieldIndexOp::create( + builder, loc, fieldIndexType, sizeFieldName, recTy, + /*typeParams=*/mlir::ValueRange{}); + mlir::Value sizeCoord = fir::CoordinateOp::create( + builder, loc, builder.getRefType(sizeFieldTy), res, sizeFieldIndex); + fir::StoreOp::create(builder, loc, size, sizeCoord); + + auto rankFieldName = recTy.getTypeList()[2].first; + mlir::Type rankFieldTy = recTy.getTypeList()[2].second; + mlir::Value rankFieldIndex = fir::FieldIndexOp::create( + builder, loc, fieldIndexType, rankFieldName, recTy, + /*typeParams=*/mlir::ValueRange{}); + mlir::Value rankCoord = fir::CoordinateOp::create( + builder, loc, builder.getRefType(rankFieldTy), res, rankFieldIndex); + fir::StoreOp::create(builder, loc, rank, rankCoord); + return res; +} + +// THIS_WARP +mlir::Value +CUDAIntrinsicLibrary::genThisWarp(mlir::Type resultType, + llvm::ArrayRef<mlir::Value> args) { + assert(args.size() == 0); + auto recTy = mlir::cast<fir::RecordType>(resultType); + assert(recTy && "RecordType expepected"); + mlir::Value res = fir::AllocaOp::create(builder, loc, resultType); + mlir::Type i32Ty = builder.getI32Type(); + + // coalesced_group%size = 32 + mlir::Value size = builder.createIntegerConstant(loc, i32Ty, 32); + auto sizeFieldName = recTy.getTypeList()[1].first; + mlir::Type sizeFieldTy = recTy.getTypeList()[1].second; + mlir::Type fieldIndexType = fir::FieldType::get(resultType.getContext()); + mlir::Value sizeFieldIndex = fir::FieldIndexOp::create( + builder, loc, fieldIndexType, sizeFieldName, recTy, + /*typeParams=*/mlir::ValueRange{}); + mlir::Value sizeCoord = fir::CoordinateOp::create( + builder, loc, builder.getRefType(sizeFieldTy), res, sizeFieldIndex); + fir::StoreOp::create(builder, loc, size, sizeCoord); + + // coalesced_group%rank = threadIdx.x & 31 + 1 + mlir::Value threadIdX = mlir::NVVM::ThreadIdXOp::create(builder, loc, i32Ty); + mlir::Value mask = builder.createIntegerConstant(loc, i32Ty, 31); + mlir::Value one = builder.createIntegerConstant(loc, i32Ty, 1); + mlir::Value masked = + mlir::arith::AndIOp::create(builder, loc, threadIdX, mask); + mlir::Value rank = mlir::arith::AddIOp::create(builder, loc, masked, one); + auto rankFieldName = recTy.getTypeList()[2].first; + mlir::Type rankFieldTy = recTy.getTypeList()[2].second; + mlir::Value rankFieldIndex = fir::FieldIndexOp::create( + builder, loc, fieldIndexType, rankFieldName, recTy, + /*typeParams=*/mlir::ValueRange{}); + mlir::Value rankCoord = fir::CoordinateOp::create( + builder, loc, builder.getRefType(rankFieldTy), res, rankFieldIndex); + fir::StoreOp::create(builder, loc, rank, rankCoord); + return res; +} + +// THREADFENCE, THREADFENCE_BLOCK, THREADFENCE_SYSTEM +template <mlir::NVVM::MemScopeKind scope> +void CUDAIntrinsicLibrary::genThreadFence( + llvm::ArrayRef<fir::ExtendedValue> args) { + assert(args.size() == 0); + mlir::NVVM::MembarOp::create(builder, loc, scope); +} + +// TMA_BULK_COMMIT_GROUP +void CUDAIntrinsicLibrary::genTMABulkCommitGroup( + llvm::ArrayRef<fir::ExtendedValue> args) { + assert(args.size() == 0); + mlir::NVVM::CpAsyncBulkCommitGroupOp::create(builder, loc); +} + +// TMA_BULK_G2S +void CUDAIntrinsicLibrary::genTMABulkG2S( + llvm::ArrayRef<fir::ExtendedValue> args) { + assert(args.size() == 4); + mlir::Value barrier = convertPtrToNVVMSpace( + builder, loc, fir::getBase(args[0]), mlir::NVVM::NVVMMemorySpace::Shared); + mlir::Value dst = + convertPtrToNVVMSpace(builder, loc, fir::getBase(args[2]), + mlir::NVVM::NVVMMemorySpace::SharedCluster); + mlir::Value src = convertPtrToNVVMSpace(builder, loc, fir::getBase(args[1]), + mlir::NVVM::NVVMMemorySpace::Global); + mlir::NVVM::CpAsyncBulkGlobalToSharedClusterOp::create( + builder, loc, dst, src, barrier, fir::getBase(args[3]), {}, {}); +} + +static void setAlignment(mlir::Value ptr, unsigned alignment) { + if (auto declareOp = mlir::dyn_cast<hlfir::DeclareOp>(ptr.getDefiningOp())) + if (auto sharedOp = mlir::dyn_cast<cuf::SharedMemoryOp>( + declareOp.getMemref().getDefiningOp())) + sharedOp.setAlignment(alignment); +} + +static void genTMABulkLoad(fir::FirOpBuilder &builder, mlir::Location loc, + mlir::Value barrier, mlir::Value src, + mlir::Value dst, mlir::Value nelem, + mlir::Value eleSize) { + mlir::Value size = mlir::arith::MulIOp::create(builder, loc, nelem, eleSize); + auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(builder.getContext()); + barrier = builder.createConvert(loc, llvmPtrTy, barrier); + setAlignment(dst, kTMAAlignment); + dst = builder.createConvert(loc, llvmPtrTy, dst); + src = builder.createConvert(loc, llvmPtrTy, src); + mlir::NVVM::InlinePtxOp::create( + builder, loc, mlir::TypeRange{}, {dst, src, size, barrier}, {}, + "cp.async.bulk.shared::cluster.global.mbarrier::complete_tx::bytes [%0], " + "[%1], %2, [%3];", + {}); + mlir::NVVM::InlinePtxOp::create( + builder, loc, mlir::TypeRange{}, {barrier, size}, {}, + "mbarrier.expect_tx.relaxed.cta.shared::cta.b64 [%0], %1;", {}); +} + +// TMA_BULK_LOADC4 +void CUDAIntrinsicLibrary::genTMABulkLoadC4( + llvm::ArrayRef<fir::ExtendedValue> args) { + assert(args.size() == 4); + mlir::Value eleSize = + builder.createIntegerConstant(loc, builder.getI32Type(), 8); + genTMABulkLoad(builder, loc, fir::getBase(args[0]), fir::getBase(args[1]), + fir::getBase(args[2]), fir::getBase(args[3]), eleSize); +} + +// TMA_BULK_LOADC8 +void CUDAIntrinsicLibrary::genTMABulkLoadC8( + llvm::ArrayRef<fir::ExtendedValue> args) { + assert(args.size() == 4); + mlir::Value eleSize = + builder.createIntegerConstant(loc, builder.getI32Type(), 16); + genTMABulkLoad(builder, loc, fir::getBase(args[0]), fir::getBase(args[1]), + fir::getBase(args[2]), fir::getBase(args[3]), eleSize); +} + +// TMA_BULK_LOADI4 +void CUDAIntrinsicLibrary::genTMABulkLoadI4( + llvm::ArrayRef<fir::ExtendedValue> args) { + assert(args.size() == 4); + mlir::Value eleSize = + builder.createIntegerConstant(loc, builder.getI32Type(), 4); + genTMABulkLoad(builder, loc, fir::getBase(args[0]), fir::getBase(args[1]), + fir::getBase(args[2]), fir::getBase(args[3]), eleSize); +} + +// TMA_BULK_LOADI8 +void CUDAIntrinsicLibrary::genTMABulkLoadI8( + llvm::ArrayRef<fir::ExtendedValue> args) { + assert(args.size() == 4); + mlir::Value eleSize = + builder.createIntegerConstant(loc, builder.getI32Type(), 8); + genTMABulkLoad(builder, loc, fir::getBase(args[0]), fir::getBase(args[1]), + fir::getBase(args[2]), fir::getBase(args[3]), eleSize); +} + +// TMA_BULK_LOADR2 +void CUDAIntrinsicLibrary::genTMABulkLoadR2( + llvm::ArrayRef<fir::ExtendedValue> args) { + assert(args.size() == 4); + mlir::Value eleSize = + builder.createIntegerConstant(loc, builder.getI32Type(), 2); + genTMABulkLoad(builder, loc, fir::getBase(args[0]), fir::getBase(args[1]), + fir::getBase(args[2]), fir::getBase(args[3]), eleSize); +} + +// TMA_BULK_LOADR4 +void CUDAIntrinsicLibrary::genTMABulkLoadR4( + llvm::ArrayRef<fir::ExtendedValue> args) { + assert(args.size() == 4); + mlir::Value eleSize = + builder.createIntegerConstant(loc, builder.getI32Type(), 4); + genTMABulkLoad(builder, loc, fir::getBase(args[0]), fir::getBase(args[1]), + fir::getBase(args[2]), fir::getBase(args[3]), eleSize); +} + +// TMA_BULK_LOADR8 +void CUDAIntrinsicLibrary::genTMABulkLoadR8( + llvm::ArrayRef<fir::ExtendedValue> args) { + assert(args.size() == 4); + mlir::Value eleSize = + builder.createIntegerConstant(loc, builder.getI32Type(), 8); + genTMABulkLoad(builder, loc, fir::getBase(args[0]), fir::getBase(args[1]), + fir::getBase(args[2]), fir::getBase(args[3]), eleSize); +} + +// TMA_BULK_S2G +void CUDAIntrinsicLibrary::genTMABulkS2G( + llvm::ArrayRef<fir::ExtendedValue> args) { + assert(args.size() == 3); + mlir::Value src = convertPtrToNVVMSpace(builder, loc, fir::getBase(args[0]), + mlir::NVVM::NVVMMemorySpace::Shared); + mlir::Value dst = convertPtrToNVVMSpace(builder, loc, fir::getBase(args[1]), + mlir::NVVM::NVVMMemorySpace::Global); + mlir::NVVM::CpAsyncBulkSharedCTAToGlobalOp::create( + builder, loc, dst, src, fir::getBase(args[2]), {}, {}); + + mlir::NVVM::InlinePtxOp::create(builder, loc, mlir::TypeRange{}, {}, {}, + "cp.async.bulk.commit_group;", {}); + mlir::NVVM::CpAsyncBulkWaitGroupOp::create(builder, loc, + builder.getI32IntegerAttr(0), {}); +} + +static void genTMABulkStore(fir::FirOpBuilder &builder, mlir::Location loc, + mlir::Value src, mlir::Value dst, mlir::Value count, + mlir::Value eleSize) { + mlir::Value size = mlir::arith::MulIOp::create(builder, loc, eleSize, count); + setAlignment(src, kTMAAlignment); + src = convertPtrToNVVMSpace(builder, loc, src, + mlir::NVVM::NVVMMemorySpace::Shared); + dst = convertPtrToNVVMSpace(builder, loc, dst, + mlir::NVVM::NVVMMemorySpace::Global); + mlir::NVVM::CpAsyncBulkSharedCTAToGlobalOp::create(builder, loc, dst, src, + size, {}, {}); + mlir::NVVM::InlinePtxOp::create(builder, loc, mlir::TypeRange{}, {}, {}, + "cp.async.bulk.commit_group;", {}); + mlir::NVVM::CpAsyncBulkWaitGroupOp::create(builder, loc, + builder.getI32IntegerAttr(0), {}); +} + +// TMA_BULK_STORE_C4 +void CUDAIntrinsicLibrary::genTMABulkStoreC4( + llvm::ArrayRef<fir::ExtendedValue> args) { + assert(args.size() == 3); + mlir::Value eleSize = + builder.createIntegerConstant(loc, builder.getI32Type(), 8); + genTMABulkStore(builder, loc, fir::getBase(args[0]), fir::getBase(args[1]), + fir::getBase(args[2]), eleSize); +} + +// TMA_BULK_STORE_C8 +void CUDAIntrinsicLibrary::genTMABulkStoreC8( + llvm::ArrayRef<fir::ExtendedValue> args) { + assert(args.size() == 3); + mlir::Value eleSize = + builder.createIntegerConstant(loc, builder.getI32Type(), 16); + genTMABulkStore(builder, loc, fir::getBase(args[0]), fir::getBase(args[1]), + fir::getBase(args[2]), eleSize); +} + +// TMA_BULK_STORE_I4 +void CUDAIntrinsicLibrary::genTMABulkStoreI4( + llvm::ArrayRef<fir::ExtendedValue> args) { + assert(args.size() == 3); + mlir::Value eleSize = + builder.createIntegerConstant(loc, builder.getI32Type(), 4); + genTMABulkStore(builder, loc, fir::getBase(args[0]), fir::getBase(args[1]), + fir::getBase(args[2]), eleSize); +} + +// TMA_BULK_STORE_I8 +void CUDAIntrinsicLibrary::genTMABulkStoreI8( + llvm::ArrayRef<fir::ExtendedValue> args) { + assert(args.size() == 3); + mlir::Value eleSize = + builder.createIntegerConstant(loc, builder.getI32Type(), 8); + genTMABulkStore(builder, loc, fir::getBase(args[0]), fir::getBase(args[1]), + fir::getBase(args[2]), eleSize); +} + +// TMA_BULK_STORE_R2 +void CUDAIntrinsicLibrary::genTMABulkStoreR2( + llvm::ArrayRef<fir::ExtendedValue> args) { + assert(args.size() == 3); + mlir::Value eleSize = + builder.createIntegerConstant(loc, builder.getI32Type(), 2); + genTMABulkStore(builder, loc, fir::getBase(args[0]), fir::getBase(args[1]), + fir::getBase(args[2]), eleSize); +} + +// TMA_BULK_STORE_R4 +void CUDAIntrinsicLibrary::genTMABulkStoreR4( + llvm::ArrayRef<fir::ExtendedValue> args) { + assert(args.size() == 3); + mlir::Value eleSize = + builder.createIntegerConstant(loc, builder.getI32Type(), 4); + genTMABulkStore(builder, loc, fir::getBase(args[0]), fir::getBase(args[1]), + fir::getBase(args[2]), eleSize); +} + +// TMA_BULK_STORE_R8 +void CUDAIntrinsicLibrary::genTMABulkStoreR8( + llvm::ArrayRef<fir::ExtendedValue> args) { + assert(args.size() == 3); + mlir::Value eleSize = + builder.createIntegerConstant(loc, builder.getI32Type(), 8); + genTMABulkStore(builder, loc, fir::getBase(args[0]), fir::getBase(args[1]), + fir::getBase(args[2]), eleSize); +} + +// TMA_BULK_WAIT_GROUP +void CUDAIntrinsicLibrary::genTMABulkWaitGroup( + llvm::ArrayRef<fir::ExtendedValue> args) { + assert(args.size() == 0); + auto group = builder.getIntegerAttr(builder.getI32Type(), 0); + mlir::NVVM::CpAsyncBulkWaitGroupOp::create(builder, loc, group, {}); +} + +// ALL_SYNC, ANY_SYNC, BALLOT_SYNC +template <mlir::NVVM::VoteSyncKind kind> +mlir::Value +CUDAIntrinsicLibrary::genVoteSync(mlir::Type resultType, + llvm::ArrayRef<mlir::Value> args) { + assert(args.size() == 2); + mlir::Value arg1 = + fir::ConvertOp::create(builder, loc, builder.getI1Type(), args[1]); + mlir::Type resTy = kind == mlir::NVVM::VoteSyncKind::ballot + ? builder.getI32Type() + : builder.getI1Type(); + auto voteRes = + mlir::NVVM::VoteSyncOp::create(builder, loc, resTy, args[0], arg1, kind) + .getResult(); + return fir::ConvertOp::create(builder, loc, resultType, voteRes); +} + +} // namespace fir diff --git a/flang/lib/Optimizer/Builder/CUFCommon.cpp b/flang/lib/Optimizer/Builder/CUFCommon.cpp index cf7588f..2266f4d 100644 --- a/flang/lib/Optimizer/Builder/CUFCommon.cpp +++ b/flang/lib/Optimizer/Builder/CUFCommon.cpp @@ -9,6 +9,7 @@ #include "flang/Optimizer/Builder/CUFCommon.h" #include "flang/Optimizer/Builder/FIRBuilder.h" #include "flang/Optimizer/Dialect/CUF/CUFOps.h" +#include "flang/Optimizer/Dialect/Support/KindMapping.h" #include "flang/Optimizer/HLFIR/HLFIROps.h" #include "mlir/Dialect/Func/IR/FuncOps.h" #include "mlir/Dialect/LLVMIR/NVVMDialect.h" @@ -91,3 +92,66 @@ void cuf::genPointerSync(const mlir::Value box, fir::FirOpBuilder &builder) { } } } + +int cuf::computeElementByteSize(mlir::Location loc, mlir::Type type, + fir::KindMapping &kindMap, + bool emitErrorOnFailure) { + auto eleTy = fir::unwrapSequenceType(type); + if (auto t{mlir::dyn_cast<mlir::IntegerType>(eleTy)}) + return t.getWidth() / 8; + if (auto t{mlir::dyn_cast<mlir::FloatType>(eleTy)}) + return t.getWidth() / 8; + if (auto t{mlir::dyn_cast<fir::LogicalType>(eleTy)}) + return kindMap.getLogicalBitsize(t.getFKind()) / 8; + if (auto t{mlir::dyn_cast<mlir::ComplexType>(eleTy)}) { + int elemSize = + mlir::cast<mlir::FloatType>(t.getElementType()).getWidth() / 8; + return 2 * elemSize; + } + if (auto t{mlir::dyn_cast<fir::CharacterType>(eleTy)}) + return kindMap.getCharacterBitsize(t.getFKind()) / 8; + if (emitErrorOnFailure) + mlir::emitError(loc, "unsupported type"); + return 0; +} + +mlir::Value cuf::computeElementCount(mlir::PatternRewriter &rewriter, + mlir::Location loc, + mlir::Value shapeOperand, + mlir::Type seqType, + mlir::Type targetType) { + if (shapeOperand) { + // Dynamic extent - extract from shape operand + llvm::SmallVector<mlir::Value> extents; + if (auto shapeOp = + mlir::dyn_cast<fir::ShapeOp>(shapeOperand.getDefiningOp())) { + extents = shapeOp.getExtents(); + } else if (auto shapeShiftOp = mlir::dyn_cast<fir::ShapeShiftOp>( + shapeOperand.getDefiningOp())) { + for (auto i : llvm::enumerate(shapeShiftOp.getPairs())) + if (i.index() & 1) + extents.push_back(i.value()); + } + + if (extents.empty()) + return mlir::Value(); + + // Compute total element count by multiplying all dimensions + mlir::Value count = + fir::ConvertOp::create(rewriter, loc, targetType, extents[0]); + for (unsigned i = 1; i < extents.size(); ++i) { + auto operand = + fir::ConvertOp::create(rewriter, loc, targetType, extents[i]); + count = mlir::arith::MulIOp::create(rewriter, loc, count, operand); + } + return count; + } else { + // Static extent - use constant array size + if (auto seqTy = mlir::dyn_cast_or_null<fir::SequenceType>(seqType)) { + mlir::IntegerAttr attr = + rewriter.getIntegerAttr(targetType, seqTy.getConstantArraySize()); + return mlir::arith::ConstantOp::create(rewriter, loc, targetType, attr); + } + } + return mlir::Value(); +} diff --git a/flang/lib/Optimizer/Builder/FIRBuilder.cpp b/flang/lib/Optimizer/Builder/FIRBuilder.cpp index 5da27d1..c704ac7 100644 --- a/flang/lib/Optimizer/Builder/FIRBuilder.cpp +++ b/flang/lib/Optimizer/Builder/FIRBuilder.cpp @@ -427,7 +427,8 @@ mlir::Value fir::FirOpBuilder::genTempDeclareOp( builder, loc, memref.getType(), memref, shape, typeParams, /*dummy_scope=*/nullptr, /*storage=*/nullptr, - /*storage_offset=*/0, nameAttr, fortranAttrs, cuf::DataAttributeAttr{}); + /*storage_offset=*/0, nameAttr, fortranAttrs, cuf::DataAttributeAttr{}, + /*dummy_arg_no=*/mlir::IntegerAttr{}); } mlir::Value fir::FirOpBuilder::genStackSave(mlir::Location loc) { @@ -1392,12 +1393,10 @@ fir::ExtendedValue fir::factory::arraySectionElementToExtendedValue( return fir::factory::componentToExtendedValue(builder, loc, element); } -void fir::factory::genScalarAssignment(fir::FirOpBuilder &builder, - mlir::Location loc, - const fir::ExtendedValue &lhs, - const fir::ExtendedValue &rhs, - bool needFinalization, - bool isTemporaryLHS) { +void fir::factory::genScalarAssignment( + fir::FirOpBuilder &builder, mlir::Location loc, + const fir::ExtendedValue &lhs, const fir::ExtendedValue &rhs, + bool needFinalization, bool isTemporaryLHS, mlir::ArrayAttr accessGroups) { assert(lhs.rank() == 0 && rhs.rank() == 0 && "must be scalars"); auto type = fir::unwrapSequenceType( fir::unwrapPassByRefType(fir::getBase(lhs).getType())); @@ -1419,7 +1418,9 @@ void fir::factory::genScalarAssignment(fir::FirOpBuilder &builder, mlir::Value lhsAddr = fir::getBase(lhs); rhsVal = builder.createConvert(loc, fir::unwrapRefType(lhsAddr.getType()), rhsVal); - fir::StoreOp::create(builder, loc, rhsVal, lhsAddr); + fir::StoreOp store = fir::StoreOp::create(builder, loc, rhsVal, lhsAddr); + if (accessGroups) + store.setAccessGroupsAttr(accessGroups); } } @@ -1670,6 +1671,26 @@ mlir::Value fir::factory::createZeroValue(fir::FirOpBuilder &builder, "numeric or logical type"); } +mlir::Value fir::factory::createOneValue(fir::FirOpBuilder &builder, + mlir::Location loc, mlir::Type type) { + mlir::Type i1 = builder.getIntegerType(1); + if (mlir::isa<fir::LogicalType>(type) || type == i1) + return builder.createConvert(loc, type, builder.createBool(loc, true)); + if (fir::isa_integer(type)) + return builder.createIntegerConstant(loc, type, 1); + if (fir::isa_real(type)) + return builder.createRealOneConstant(loc, type); + if (fir::isa_complex(type)) { + fir::factory::Complex complexHelper(builder, loc); + mlir::Type partType = complexHelper.getComplexPartType(type); + mlir::Value realPart = builder.createRealOneConstant(loc, partType); + mlir::Value imagPart = builder.createRealZeroConstant(loc, partType); + return complexHelper.createComplex(type, realPart, imagPart); + } + fir::emitFatalError(loc, "internal: trying to generate one value of non " + "numeric or logical type"); +} + std::optional<std::int64_t> fir::factory::getExtentFromTriplet(mlir::Value lb, mlir::Value ub, mlir::Value stride) { diff --git a/flang/lib/Optimizer/Builder/HLFIRTools.cpp b/flang/lib/Optimizer/Builder/HLFIRTools.cpp index 93dfc57..a345dcb 100644 --- a/flang/lib/Optimizer/Builder/HLFIRTools.cpp +++ b/flang/lib/Optimizer/Builder/HLFIRTools.cpp @@ -250,7 +250,7 @@ hlfir::genDeclare(mlir::Location loc, fir::FirOpBuilder &builder, const fir::ExtendedValue &exv, llvm::StringRef name, fir::FortranVariableFlagsAttr flags, mlir::Value dummyScope, mlir::Value storage, std::uint64_t storageOffset, - cuf::DataAttributeAttr dataAttr) { + cuf::DataAttributeAttr dataAttr, unsigned dummyArgNo) { mlir::Value base = fir::getBase(exv); assert(fir::conformsWithPassByRef(base.getType()) && @@ -281,7 +281,7 @@ hlfir::genDeclare(mlir::Location loc, fir::FirOpBuilder &builder, [](const auto &) {}); auto declareOp = hlfir::DeclareOp::create( builder, loc, base, name, shapeOrShift, lenParams, dummyScope, storage, - storageOffset, flags, dataAttr); + storageOffset, flags, dataAttr, dummyArgNo); return mlir::cast<fir::FortranVariableOpInterface>(declareOp.getOperation()); } @@ -402,9 +402,9 @@ hlfir::Entity hlfir::genVariableBox(mlir::Location loc, fir::BoxType::get(var.getElementOrSequenceType(), isVolatile); if (forceBoxType) { boxType = forceBoxType; - mlir::Type baseType = - fir::ReferenceType::get(fir::unwrapRefType(forceBoxType.getEleTy())); - addr = builder.createConvert(loc, baseType, addr); + mlir::Type baseType = fir::ReferenceType::get( + fir::unwrapRefType(forceBoxType.getEleTy()), forceBoxType.isVolatile()); + addr = builder.createConvertWithVolatileCast(loc, baseType, addr); } auto embox = fir::EmboxOp::create(builder, loc, boxType, addr, shape, /*slice=*/mlir::Value{}, typeParams); @@ -1392,6 +1392,66 @@ bool hlfir::elementalOpMustProduceTemp(hlfir::ElementalOp elemental) { return false; } +static void combineAndStoreElement( + mlir::Location loc, fir::FirOpBuilder &builder, hlfir::Entity lhs, + hlfir::Entity rhs, bool temporaryLHS, + std::function<hlfir::Entity(mlir::Location, fir::FirOpBuilder &, + hlfir::Entity, hlfir::Entity)> *combiner) { + hlfir::Entity valueToAssign = hlfir::loadTrivialScalar(loc, builder, rhs); + if (combiner) { + hlfir::Entity lhsValue = hlfir::loadTrivialScalar(loc, builder, lhs); + valueToAssign = (*combiner)(loc, builder, lhsValue, valueToAssign); + } + hlfir::AssignOp::create(builder, loc, valueToAssign, lhs, + /*realloc=*/false, + /*keep_lhs_length_if_realloc=*/false, + /*temporary_lhs=*/temporaryLHS); +} + +void hlfir::genNoAliasArrayAssignment( + mlir::Location loc, fir::FirOpBuilder &builder, hlfir::Entity rhs, + hlfir::Entity lhs, bool emitWorkshareLoop, bool temporaryLHS, + std::function<hlfir::Entity(mlir::Location, fir::FirOpBuilder &, + hlfir::Entity, hlfir::Entity)> *combiner) { + mlir::OpBuilder::InsertionGuard guard(builder); + rhs = hlfir::derefPointersAndAllocatables(loc, builder, rhs); + lhs = hlfir::derefPointersAndAllocatables(loc, builder, lhs); + mlir::Value lhsShape = hlfir::genShape(loc, builder, lhs); + llvm::SmallVector<mlir::Value> lhsExtents = + hlfir::getIndexExtents(loc, builder, lhsShape); + mlir::Value rhsShape = hlfir::genShape(loc, builder, rhs); + llvm::SmallVector<mlir::Value> rhsExtents = + hlfir::getIndexExtents(loc, builder, rhsShape); + llvm::SmallVector<mlir::Value> extents = + fir::factory::deduceOptimalExtents(lhsExtents, rhsExtents); + hlfir::LoopNest loopNest = + hlfir::genLoopNest(loc, builder, extents, + /*isUnordered=*/true, emitWorkshareLoop); + builder.setInsertionPointToStart(loopNest.body); + auto rhsArrayElement = + hlfir::getElementAt(loc, builder, rhs, loopNest.oneBasedIndices); + rhsArrayElement = hlfir::loadTrivialScalar(loc, builder, rhsArrayElement); + auto lhsArrayElement = + hlfir::getElementAt(loc, builder, lhs, loopNest.oneBasedIndices); + combineAndStoreElement(loc, builder, lhsArrayElement, rhsArrayElement, + temporaryLHS, combiner); +} + +void hlfir::genNoAliasAssignment( + mlir::Location loc, fir::FirOpBuilder &builder, hlfir::Entity rhs, + hlfir::Entity lhs, bool emitWorkshareLoop, bool temporaryLHS, + std::function<hlfir::Entity(mlir::Location, fir::FirOpBuilder &, + hlfir::Entity, hlfir::Entity)> *combiner) { + if (lhs.isArray()) { + genNoAliasArrayAssignment(loc, builder, rhs, lhs, emitWorkshareLoop, + temporaryLHS, combiner); + return; + } + rhs = hlfir::derefPointersAndAllocatables(loc, builder, rhs); + lhs = hlfir::derefPointersAndAllocatables(loc, builder, lhs); + combineAndStoreElement(loc, builder, lhs, rhs, temporaryLHS, combiner); +} + std::pair<hlfir::Entity, bool> hlfir::createTempFromMold(mlir::Location loc, fir::FirOpBuilder &builder, hlfir::Entity mold) { diff --git a/flang/lib/Optimizer/Builder/IntrinsicCall.cpp b/flang/lib/Optimizer/Builder/IntrinsicCall.cpp index 15ea845..75a74ee 100644 --- a/flang/lib/Optimizer/Builder/IntrinsicCall.cpp +++ b/flang/lib/Optimizer/Builder/IntrinsicCall.cpp @@ -16,6 +16,7 @@ #include "flang/Optimizer/Builder/IntrinsicCall.h" #include "flang/Common/static-multimap-view.h" #include "flang/Optimizer/Builder/BoxValue.h" +#include "flang/Optimizer/Builder/CUDAIntrinsicCall.h" #include "flang/Optimizer/Builder/CUFCommon.h" #include "flang/Optimizer/Builder/Character.h" #include "flang/Optimizer/Builder/Complex.h" @@ -50,7 +51,6 @@ #include "mlir/Dialect/LLVMIR/LLVMDialect.h" #include "mlir/Dialect/LLVMIR/LLVMTypes.h" #include "mlir/Dialect/Math/IR/Math.h" -#include "mlir/Dialect/SCF/IR/SCF.h" #include "mlir/Dialect/Vector/IR/VectorOps.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" @@ -91,6 +91,11 @@ static bool isStaticallyAbsent(llvm::ArrayRef<mlir::Value> args, size_t argIndex) { return args.size() <= argIndex || !args[argIndex]; } +static bool isOptional(mlir::Value value) { + auto varIface = mlir::dyn_cast_or_null<fir::FortranVariableOpInterface>( + value.getDefiningOp()); + return varIface && varIface.isOptional(); +} /// Test if an ExtendedValue is present. This is used to test if an intrinsic /// argument is present at compile time. This does not imply that the related @@ -108,34 +113,6 @@ using I = IntrinsicLibrary; /// argument is an optional variable in the current scope). static constexpr bool handleDynamicOptional = true; -/// TODO: Move all CUDA Fortran intrinsic handlers into its own file similar to -/// PPC. -static const char __ldca_i4x4[] = "__ldca_i4x4_"; -static const char __ldca_i8x2[] = "__ldca_i8x2_"; -static const char __ldca_r2x2[] = "__ldca_r2x2_"; -static const char __ldca_r4x4[] = "__ldca_r4x4_"; -static const char __ldca_r8x2[] = "__ldca_r8x2_"; -static const char __ldcg_i4x4[] = "__ldcg_i4x4_"; -static const char __ldcg_i8x2[] = "__ldcg_i8x2_"; -static const char __ldcg_r2x2[] = "__ldcg_r2x2_"; -static const char __ldcg_r4x4[] = "__ldcg_r4x4_"; -static const char __ldcg_r8x2[] = "__ldcg_r8x2_"; -static const char __ldcs_i4x4[] = "__ldcs_i4x4_"; -static const char __ldcs_i8x2[] = "__ldcs_i8x2_"; -static const char __ldcs_r2x2[] = "__ldcs_r2x2_"; -static const char __ldcs_r4x4[] = "__ldcs_r4x4_"; -static const char __ldcs_r8x2[] = "__ldcs_r8x2_"; -static const char __ldcv_i4x4[] = "__ldcv_i4x4_"; -static const char __ldcv_i8x2[] = "__ldcv_i8x2_"; -static const char __ldcv_r2x2[] = "__ldcv_r2x2_"; -static const char __ldcv_r4x4[] = "__ldcv_r4x4_"; -static const char __ldcv_r8x2[] = "__ldcv_r8x2_"; -static const char __ldlu_i4x4[] = "__ldlu_i4x4_"; -static const char __ldlu_i8x2[] = "__ldlu_i8x2_"; -static const char __ldlu_r2x2[] = "__ldlu_r2x2_"; -static const char __ldlu_r4x4[] = "__ldlu_r4x4_"; -static const char __ldlu_r8x2[] = "__ldlu_r8x2_"; - /// Table that drives the fir generation depending on the intrinsic or intrinsic /// module procedure one to one mapping with Fortran arguments. If no mapping is /// defined here for a generic intrinsic, genRuntimeCall will be called @@ -144,106 +121,6 @@ static const char __ldlu_r8x2[] = "__ldlu_r8x2_"; /// argument must not be lowered by value. In which case, the lowering rules /// should be provided for all the intrinsic arguments for completeness. static constexpr IntrinsicHandler handlers[]{ - {"__ldca_i4x4", - &I::genCUDALDXXFunc<__ldca_i4x4, 4>, - {{{"a", asAddr}}}, - /*isElemental=*/false}, - {"__ldca_i8x2", - &I::genCUDALDXXFunc<__ldca_i8x2, 2>, - {{{"a", asAddr}}}, - /*isElemental=*/false}, - {"__ldca_r2x2", - &I::genCUDALDXXFunc<__ldca_r2x2, 2>, - {{{"a", asAddr}}}, - /*isElemental=*/false}, - {"__ldca_r4x4", - &I::genCUDALDXXFunc<__ldca_r4x4, 4>, - {{{"a", asAddr}}}, - /*isElemental=*/false}, - {"__ldca_r8x2", - &I::genCUDALDXXFunc<__ldca_r8x2, 2>, - {{{"a", asAddr}}}, - /*isElemental=*/false}, - {"__ldcg_i4x4", - &I::genCUDALDXXFunc<__ldcg_i4x4, 4>, - {{{"a", asAddr}}}, - /*isElemental=*/false}, - {"__ldcg_i8x2", - &I::genCUDALDXXFunc<__ldcg_i8x2, 2>, - {{{"a", asAddr}}}, - /*isElemental=*/false}, - {"__ldcg_r2x2", - &I::genCUDALDXXFunc<__ldcg_r2x2, 2>, - {{{"a", asAddr}}}, - /*isElemental=*/false}, - {"__ldcg_r4x4", - &I::genCUDALDXXFunc<__ldcg_r4x4, 4>, - {{{"a", asAddr}}}, - /*isElemental=*/false}, - {"__ldcg_r8x2", - &I::genCUDALDXXFunc<__ldcg_r8x2, 2>, - {{{"a", asAddr}}}, - /*isElemental=*/false}, - {"__ldcs_i4x4", - &I::genCUDALDXXFunc<__ldcs_i4x4, 4>, - {{{"a", asAddr}}}, - /*isElemental=*/false}, - {"__ldcs_i8x2", - &I::genCUDALDXXFunc<__ldcs_i8x2, 2>, - {{{"a", asAddr}}}, - /*isElemental=*/false}, - {"__ldcs_r2x2", - &I::genCUDALDXXFunc<__ldcs_r2x2, 2>, - {{{"a", asAddr}}}, - /*isElemental=*/false}, - {"__ldcs_r4x4", - &I::genCUDALDXXFunc<__ldcs_r4x4, 4>, - {{{"a", asAddr}}}, - /*isElemental=*/false}, - {"__ldcs_r8x2", - &I::genCUDALDXXFunc<__ldcs_r8x2, 2>, - {{{"a", asAddr}}}, - /*isElemental=*/false}, - {"__ldcv_i4x4", - &I::genCUDALDXXFunc<__ldcv_i4x4, 4>, - {{{"a", asAddr}}}, - /*isElemental=*/false}, - {"__ldcv_i8x2", - &I::genCUDALDXXFunc<__ldcv_i8x2, 2>, - {{{"a", asAddr}}}, - /*isElemental=*/false}, - {"__ldcv_r2x2", - &I::genCUDALDXXFunc<__ldcv_r2x2, 2>, - {{{"a", asAddr}}}, - /*isElemental=*/false}, - {"__ldcv_r4x4", - &I::genCUDALDXXFunc<__ldcv_r4x4, 4>, - {{{"a", asAddr}}}, - /*isElemental=*/false}, - {"__ldcv_r8x2", - &I::genCUDALDXXFunc<__ldcv_r8x2, 2>, - {{{"a", asAddr}}}, - /*isElemental=*/false}, - {"__ldlu_i4x4", - &I::genCUDALDXXFunc<__ldlu_i4x4, 4>, - {{{"a", asAddr}}}, - /*isElemental=*/false}, - {"__ldlu_i8x2", - &I::genCUDALDXXFunc<__ldlu_i8x2, 2>, - {{{"a", asAddr}}}, - /*isElemental=*/false}, - {"__ldlu_r2x2", - &I::genCUDALDXXFunc<__ldlu_r2x2, 2>, - {{{"a", asAddr}}}, - /*isElemental=*/false}, - {"__ldlu_r4x4", - &I::genCUDALDXXFunc<__ldlu_r4x4, 4>, - {{{"a", asAddr}}}, - /*isElemental=*/false}, - {"__ldlu_r8x2", - &I::genCUDALDXXFunc<__ldlu_r8x2, 2>, - {{{"a", asAddr}}}, - /*isElemental=*/false}, {"abort", &I::genAbort}, {"abs", &I::genAbs}, {"achar", &I::genChar}, @@ -263,10 +140,6 @@ static constexpr IntrinsicHandler handlers[]{ &I::genAll, {{{"mask", asAddr}, {"dim", asValue}}}, /*isElemental=*/false}, - {"all_sync", - &I::genVoteSync<mlir::NVVM::VoteSyncKind::all>, - {{{"mask", asValue}, {"pred", asValue}}}, - /*isElemental=*/false}, {"allocated", &I::genAllocated, {{{"array", asInquired}, {"scalar", asInquired}}}, @@ -276,10 +149,6 @@ static constexpr IntrinsicHandler handlers[]{ &I::genAny, {{{"mask", asAddr}, {"dim", asValue}}}, /*isElemental=*/false}, - {"any_sync", - &I::genVoteSync<mlir::NVVM::VoteSyncKind::any>, - {{{"mask", asValue}, {"pred", asValue}}}, - /*isElemental=*/false}, {"asind", &I::genAsind}, {"asinpi", &I::genAsinpi}, {"associated", @@ -290,83 +159,6 @@ static constexpr IntrinsicHandler handlers[]{ {"atan2pi", &I::genAtanpi}, {"atand", &I::genAtand}, {"atanpi", &I::genAtanpi}, - {"atomicaddd", &I::genAtomicAdd, {{{"a", asAddr}, {"v", asValue}}}, false}, - {"atomicaddf", &I::genAtomicAdd, {{{"a", asAddr}, {"v", asValue}}}, false}, - {"atomicaddi", &I::genAtomicAdd, {{{"a", asAddr}, {"v", asValue}}}, false}, - {"atomicaddl", &I::genAtomicAdd, {{{"a", asAddr}, {"v", asValue}}}, false}, - {"atomicandi", &I::genAtomicAnd, {{{"a", asAddr}, {"v", asValue}}}, false}, - {"atomiccasd", - &I::genAtomicCas, - {{{"a", asAddr}, {"v1", asValue}, {"v2", asValue}}}, - false}, - {"atomiccasf", - &I::genAtomicCas, - {{{"a", asAddr}, {"v1", asValue}, {"v2", asValue}}}, - false}, - {"atomiccasi", - &I::genAtomicCas, - {{{"a", asAddr}, {"v1", asValue}, {"v2", asValue}}}, - false}, - {"atomiccasul", - &I::genAtomicCas, - {{{"a", asAddr}, {"v1", asValue}, {"v2", asValue}}}, - false}, - {"atomicdeci", &I::genAtomicDec, {{{"a", asAddr}, {"v", asValue}}}, false}, - {"atomicexchd", - &I::genAtomicExch, - {{{"a", asAddr}, {"v", asValue}}}, - false}, - {"atomicexchf", - &I::genAtomicExch, - {{{"a", asAddr}, {"v", asValue}}}, - false}, - {"atomicexchi", - &I::genAtomicExch, - {{{"a", asAddr}, {"v", asValue}}}, - false}, - {"atomicexchul", - &I::genAtomicExch, - {{{"a", asAddr}, {"v", asValue}}}, - false}, - {"atomicinci", &I::genAtomicInc, {{{"a", asAddr}, {"v", asValue}}}, false}, - {"atomicmaxd", &I::genAtomicMax, {{{"a", asAddr}, {"v", asValue}}}, false}, - {"atomicmaxf", &I::genAtomicMax, {{{"a", asAddr}, {"v", asValue}}}, false}, - {"atomicmaxi", &I::genAtomicMax, {{{"a", asAddr}, {"v", asValue}}}, false}, - {"atomicmaxl", &I::genAtomicMax, {{{"a", asAddr}, {"v", asValue}}}, false}, - {"atomicmind", &I::genAtomicMin, {{{"a", asAddr}, {"v", asValue}}}, false}, - {"atomicminf", &I::genAtomicMin, {{{"a", asAddr}, {"v", asValue}}}, false}, - {"atomicmini", &I::genAtomicMin, {{{"a", asAddr}, {"v", asValue}}}, false}, - {"atomicminl", &I::genAtomicMin, {{{"a", asAddr}, {"v", asValue}}}, false}, - {"atomicori", &I::genAtomicOr, {{{"a", asAddr}, {"v", asValue}}}, false}, - {"atomicsubd", &I::genAtomicSub, {{{"a", asAddr}, {"v", asValue}}}, false}, - {"atomicsubf", &I::genAtomicSub, {{{"a", asAddr}, {"v", asValue}}}, false}, - {"atomicsubi", &I::genAtomicSub, {{{"a", asAddr}, {"v", asValue}}}, false}, - {"atomicsubl", &I::genAtomicSub, {{{"a", asAddr}, {"v", asValue}}}, false}, - {"atomicxori", &I::genAtomicXor, {{{"a", asAddr}, {"v", asValue}}}, false}, - {"ballot_sync", - &I::genVoteSync<mlir::NVVM::VoteSyncKind::ballot>, - {{{"mask", asValue}, {"pred", asValue}}}, - /*isElemental=*/false}, - {"barrier_arrive", - &I::genBarrierArrive, - {{{"barrier", asAddr}}}, - /*isElemental=*/false}, - {"barrier_arrive_cnt", - &I::genBarrierArriveCnt, - {{{"barrier", asAddr}, {"count", asValue}}}, - /*isElemental=*/false}, - {"barrier_init", - &I::genBarrierInit, - {{{"barrier", asAddr}, {"count", asValue}}}, - /*isElemental=*/false}, - {"barrier_try_wait", - &I::genBarrierTryWait, - {{{"barrier", asAddr}, {"token", asValue}}}, - /*isElemental=*/false}, - {"barrier_try_wait_sleep", - &I::genBarrierTryWaitSleep, - {{{"barrier", asAddr}, {"token", asValue}, {"ns", asValue}}}, - /*isElemental=*/false}, {"bessel_jn", &I::genBesselJn, {{{"n1", asValue}, {"n2", asValue}, {"x", asValue}}}, @@ -410,11 +202,6 @@ static constexpr IntrinsicHandler handlers[]{ &I::genChdir, {{{"name", asAddr}, {"status", asAddr, handleDynamicOptional}}}, /*isElemental=*/false}, - {"clock", &I::genNVVMTime<mlir::NVVM::ClockOp>, {}, /*isElemental=*/false}, - {"clock64", - &I::genNVVMTime<mlir::NVVM::Clock64Op>, - {}, - /*isElemental=*/false}, {"cmplx", &I::genCmplx, {{{"x", asValue}, {"y", asValue, handleDynamicOptional}}}}, @@ -511,10 +298,6 @@ static constexpr IntrinsicHandler handlers[]{ &I::genExtendsTypeOf, {{{"a", asBox}, {"mold", asBox}}}, /*isElemental=*/false}, - {"fence_proxy_async", - &I::genFenceProxyAsync, - {}, - /*isElemental=*/false}, {"findloc", &I::genFindloc, {{{"array", asBox}, @@ -525,6 +308,10 @@ static constexpr IntrinsicHandler handlers[]{ {"back", asValue, handleDynamicOptional}}}, /*isElemental=*/false}, {"floor", &I::genFloor}, + {"flush", + &I::genFlush, + {{{"unit", asAddr}}}, + /*isElemental=*/false}, {"fraction", &I::genFraction}, {"free", &I::genFree}, {"fseek", @@ -562,6 +349,10 @@ static constexpr IntrinsicHandler handlers[]{ {"trim_name", asAddr, handleDynamicOptional}, {"errmsg", asBox, handleDynamicOptional}}}, /*isElemental=*/false}, + {"get_team", + &I::genGetTeam, + {{{"level", asValue, handleDynamicOptional}}}, + /*isElemental=*/false}, {"getcwd", &I::genGetCwd, {{{"c", asBox}, {"status", asAddr, handleDynamicOptional}}}, @@ -569,10 +360,6 @@ static constexpr IntrinsicHandler handlers[]{ {"getgid", &I::genGetGID}, {"getpid", &I::genGetPID}, {"getuid", &I::genGetUID}, - {"globaltimer", - &I::genNVVMTime<mlir::NVVM::GlobalTimerOp>, - {}, - /*isElemental=*/false}, {"hostnm", &I::genHostnm, {{{"c", asBox}, {"status", asAddr, handleDynamicOptional}}}, @@ -712,6 +499,10 @@ static constexpr IntrinsicHandler handlers[]{ {"dim", asValue}, {"mask", asBox, handleDynamicOptional}}}, /*isElemental=*/false}, + {"irand", + &I::genIrand, + {{{"i", asAddr, handleDynamicOptional}}}, + /*isElemental=*/false}, {"is_contiguous", &I::genIsContiguous, {{{"array", asBox}}}, @@ -740,38 +531,6 @@ static constexpr IntrinsicHandler handlers[]{ {"malloc", &I::genMalloc}, {"maskl", &I::genMask<mlir::arith::ShLIOp>}, {"maskr", &I::genMask<mlir::arith::ShRUIOp>}, - {"match_all_syncjd", - &I::genMatchAllSync, - {{{"mask", asValue}, {"value", asValue}, {"pred", asAddr}}}, - /*isElemental=*/false}, - {"match_all_syncjf", - &I::genMatchAllSync, - {{{"mask", asValue}, {"value", asValue}, {"pred", asAddr}}}, - /*isElemental=*/false}, - {"match_all_syncjj", - &I::genMatchAllSync, - {{{"mask", asValue}, {"value", asValue}, {"pred", asAddr}}}, - /*isElemental=*/false}, - {"match_all_syncjx", - &I::genMatchAllSync, - {{{"mask", asValue}, {"value", asValue}, {"pred", asAddr}}}, - /*isElemental=*/false}, - {"match_any_syncjd", - &I::genMatchAnySync, - {{{"mask", asValue}, {"value", asValue}}}, - /*isElemental=*/false}, - {"match_any_syncjf", - &I::genMatchAnySync, - {{{"mask", asValue}, {"value", asValue}}}, - /*isElemental=*/false}, - {"match_any_syncjj", - &I::genMatchAnySync, - {{{"mask", asValue}, {"value", asValue}}}, - /*isElemental=*/false}, - {"match_any_syncjx", - &I::genMatchAnySync, - {{{"mask", asValue}, {"value", asValue}}}, - /*isElemental=*/false}, {"matmul", &I::genMatmul, {{{"matrix_a", asAddr}, {"matrix_b", asAddr}}}, @@ -870,6 +629,10 @@ static constexpr IntrinsicHandler handlers[]{ &I::genPutenv, {{{"str", asAddr}, {"status", asAddr, handleDynamicOptional}}}, /*isElemental=*/false}, + {"rand", + &I::genRand, + {{{"i", asAddr, handleDynamicOptional}}}, + /*isElemental=*/false}, {"random_init", &I::genRandomInit, {{{"repeatable", asValue}, {"image_distinct", asValue}}}, @@ -964,6 +727,10 @@ static constexpr IntrinsicHandler handlers[]{ {"shifta", &I::genShiftA}, {"shiftl", &I::genShift<mlir::arith::ShLIOp>}, {"shiftr", &I::genShift<mlir::arith::ShRUIOp>}, + {"show_descriptor", + &I::genShowDescriptor, + {{{"d", asBox}}}, + /*isElemental=*/false}, {"sign", &I::genSign}, {"signal", &I::genSignalSubroutine, @@ -997,20 +764,6 @@ static constexpr IntrinsicHandler handlers[]{ {"dim", asValue}, {"mask", asBox, handleDynamicOptional}}}, /*isElemental=*/false}, - {"syncthreads", &I::genSyncThreads, {}, /*isElemental=*/false}, - {"syncthreads_and_i4", &I::genSyncThreadsAnd, {}, /*isElemental=*/false}, - {"syncthreads_and_l4", &I::genSyncThreadsAnd, {}, /*isElemental=*/false}, - {"syncthreads_count_i4", - &I::genSyncThreadsCount, - {}, - /*isElemental=*/false}, - {"syncthreads_count_l4", - &I::genSyncThreadsCount, - {}, - /*isElemental=*/false}, - {"syncthreads_or_i4", &I::genSyncThreadsOr, {}, /*isElemental=*/false}, - {"syncthreads_or_l4", &I::genSyncThreadsOr, {}, /*isElemental=*/false}, - {"syncwarp", &I::genSyncWarp, {}, /*isElemental=*/false}, {"system", &I::genSystem, {{{"command", asBox}, {"exitstat", asBox, handleDynamicOptional}}}, @@ -1021,115 +774,17 @@ static constexpr IntrinsicHandler handlers[]{ /*isElemental=*/false}, {"tand", &I::genTand}, {"tanpi", &I::genTanpi}, - {"this_grid", &I::genThisGrid, {}, /*isElemental=*/false}, + {"team_number", + &I::genTeamNumber, + {{{"team", asBox, handleDynamicOptional}}}, + /*isElemental=*/false}, {"this_image", &I::genThisImage, {{{"coarray", asBox}, {"dim", asAddr}, {"team", asBox, handleDynamicOptional}}}, /*isElemental=*/false}, - {"this_thread_block", &I::genThisThreadBlock, {}, /*isElemental=*/false}, - {"this_warp", &I::genThisWarp, {}, /*isElemental=*/false}, - {"threadfence", &I::genThreadFence, {}, /*isElemental=*/false}, - {"threadfence_block", &I::genThreadFenceBlock, {}, /*isElemental=*/false}, - {"threadfence_system", &I::genThreadFenceSystem, {}, /*isElemental=*/false}, {"time", &I::genTime, {}, /*isElemental=*/false}, - {"tma_bulk_commit_group", - &I::genTMABulkCommitGroup, - {{}}, - /*isElemental=*/false}, - {"tma_bulk_g2s", - &I::genTMABulkG2S, - {{{"barrier", asAddr}, - {"src", asAddr}, - {"dst", asAddr}, - {"nbytes", asValue}}}, - /*isElemental=*/false}, - {"tma_bulk_ldc4", - &I::genTMABulkLoadC4, - {{{"barrier", asAddr}, - {"src", asAddr}, - {"dst", asAddr}, - {"nelems", asValue}}}, - /*isElemental=*/false}, - {"tma_bulk_ldc8", - &I::genTMABulkLoadC8, - {{{"barrier", asAddr}, - {"src", asAddr}, - {"dst", asAddr}, - {"nelems", asValue}}}, - /*isElemental=*/false}, - {"tma_bulk_ldi4", - &I::genTMABulkLoadI4, - {{{"barrier", asAddr}, - {"src", asAddr}, - {"dst", asAddr}, - {"nelems", asValue}}}, - /*isElemental=*/false}, - {"tma_bulk_ldi8", - &I::genTMABulkLoadI8, - {{{"barrier", asAddr}, - {"src", asAddr}, - {"dst", asAddr}, - {"nelems", asValue}}}, - /*isElemental=*/false}, - {"tma_bulk_ldr2", - &I::genTMABulkLoadR2, - {{{"barrier", asAddr}, - {"src", asAddr}, - {"dst", asAddr}, - {"nelems", asValue}}}, - /*isElemental=*/false}, - {"tma_bulk_ldr4", - &I::genTMABulkLoadR4, - {{{"barrier", asAddr}, - {"src", asAddr}, - {"dst", asAddr}, - {"nelems", asValue}}}, - /*isElemental=*/false}, - {"tma_bulk_ldr8", - &I::genTMABulkLoadR8, - {{{"barrier", asAddr}, - {"src", asAddr}, - {"dst", asAddr}, - {"nelems", asValue}}}, - /*isElemental=*/false}, - {"tma_bulk_s2g", - &I::genTMABulkS2G, - {{{"src", asAddr}, {"dst", asAddr}, {"nbytes", asValue}}}, - /*isElemental=*/false}, - {"tma_bulk_store_c4", - &I::genTMABulkStoreC4, - {{{"src", asAddr}, {"dst", asAddr}, {"count", asValue}}}, - /*isElemental=*/false}, - {"tma_bulk_store_c8", - &I::genTMABulkStoreC8, - {{{"src", asAddr}, {"dst", asAddr}, {"count", asValue}}}, - /*isElemental=*/false}, - {"tma_bulk_store_i4", - &I::genTMABulkStoreI4, - {{{"src", asAddr}, {"dst", asAddr}, {"count", asValue}}}, - /*isElemental=*/false}, - {"tma_bulk_store_i8", - &I::genTMABulkStoreI8, - {{{"src", asAddr}, {"dst", asAddr}, {"count", asValue}}}, - /*isElemental=*/false}, - {"tma_bulk_store_r2", - &I::genTMABulkStoreR2, - {{{"src", asAddr}, {"dst", asAddr}, {"count", asValue}}}, - /*isElemental=*/false}, - {"tma_bulk_store_r4", - &I::genTMABulkStoreR4, - {{{"src", asAddr}, {"dst", asAddr}, {"count", asValue}}}, - /*isElemental=*/false}, - {"tma_bulk_store_r8", - &I::genTMABulkStoreR8, - {{{"src", asAddr}, {"dst", asAddr}, {"count", asValue}}}, - /*isElemental=*/false}, - {"tma_bulk_wait_group", - &I::genTMABulkWaitGroup, - {{}}, - /*isElemental=*/false}, {"trailz", &I::genTrailz}, {"transfer", &I::genTransfer, @@ -2221,6 +1876,9 @@ lookupIntrinsicHandler(fir::FirOpBuilder &builder, if (isPPCTarget) if (const IntrinsicHandler *ppcHandler = findPPCIntrinsicHandler(name)) return std::make_optional<IntrinsicHandlerEntry>(ppcHandler); + // TODO: Look for CUDA intrinsic handlers only if CUDA is enabled. + if (const IntrinsicHandler *cudaHandler = findCUDAIntrinsicHandler(name)) + return std::make_optional<IntrinsicHandlerEntry>(cudaHandler); // Subroutines should have a handler. if (!resultType) return std::nullopt; @@ -3107,159 +2765,6 @@ mlir::Value IntrinsicLibrary::genAtanpi(mlir::Type resultType, return mlir::arith::MulFOp::create(builder, loc, atan, factor); } -static mlir::Value genAtomBinOp(fir::FirOpBuilder &builder, mlir::Location &loc, - mlir::LLVM::AtomicBinOp binOp, mlir::Value arg0, - mlir::Value arg1) { - auto llvmPointerType = mlir::LLVM::LLVMPointerType::get(builder.getContext()); - arg0 = builder.createConvert(loc, llvmPointerType, arg0); - return mlir::LLVM::AtomicRMWOp::create(builder, loc, binOp, arg0, arg1, - mlir::LLVM::AtomicOrdering::seq_cst); -} - -mlir::Value IntrinsicLibrary::genAtomicAdd(mlir::Type resultType, - llvm::ArrayRef<mlir::Value> args) { - assert(args.size() == 2); - - mlir::LLVM::AtomicBinOp binOp = - mlir::isa<mlir::IntegerType>(args[1].getType()) - ? mlir::LLVM::AtomicBinOp::add - : mlir::LLVM::AtomicBinOp::fadd; - return genAtomBinOp(builder, loc, binOp, args[0], args[1]); -} - -mlir::Value IntrinsicLibrary::genAtomicSub(mlir::Type resultType, - llvm::ArrayRef<mlir::Value> args) { - assert(args.size() == 2); - - mlir::LLVM::AtomicBinOp binOp = - mlir::isa<mlir::IntegerType>(args[1].getType()) - ? mlir::LLVM::AtomicBinOp::sub - : mlir::LLVM::AtomicBinOp::fsub; - return genAtomBinOp(builder, loc, binOp, args[0], args[1]); -} - -mlir::Value IntrinsicLibrary::genAtomicAnd(mlir::Type resultType, - llvm::ArrayRef<mlir::Value> args) { - assert(args.size() == 2); - assert(mlir::isa<mlir::IntegerType>(args[1].getType())); - - mlir::LLVM::AtomicBinOp binOp = mlir::LLVM::AtomicBinOp::_and; - return genAtomBinOp(builder, loc, binOp, args[0], args[1]); -} - -mlir::Value IntrinsicLibrary::genAtomicOr(mlir::Type resultType, - llvm::ArrayRef<mlir::Value> args) { - assert(args.size() == 2); - assert(mlir::isa<mlir::IntegerType>(args[1].getType())); - - mlir::LLVM::AtomicBinOp binOp = mlir::LLVM::AtomicBinOp::_or; - return genAtomBinOp(builder, loc, binOp, args[0], args[1]); -} - -// ATOMICCAS -fir::ExtendedValue -IntrinsicLibrary::genAtomicCas(mlir::Type resultType, - llvm::ArrayRef<fir::ExtendedValue> args) { - assert(args.size() == 3); - auto successOrdering = mlir::LLVM::AtomicOrdering::acq_rel; - auto failureOrdering = mlir::LLVM::AtomicOrdering::monotonic; - auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(resultType.getContext()); - - mlir::Value arg0 = fir::getBase(args[0]); - mlir::Value arg1 = fir::getBase(args[1]); - mlir::Value arg2 = fir::getBase(args[2]); - - auto bitCastFloat = [&](mlir::Value arg) -> mlir::Value { - if (mlir::isa<mlir::Float32Type>(arg.getType())) - return mlir::LLVM::BitcastOp::create(builder, loc, builder.getI32Type(), - arg); - if (mlir::isa<mlir::Float64Type>(arg.getType())) - return mlir::LLVM::BitcastOp::create(builder, loc, builder.getI64Type(), - arg); - return arg; - }; - - arg1 = bitCastFloat(arg1); - arg2 = bitCastFloat(arg2); - - if (arg1.getType() != arg2.getType()) { - // arg1 and arg2 need to have the same type in AtomicCmpXchgOp. - arg2 = builder.createConvert(loc, arg1.getType(), arg2); - } - - auto address = - mlir::UnrealizedConversionCastOp::create(builder, loc, llvmPtrTy, arg0) - .getResult(0); - auto cmpxchg = mlir::LLVM::AtomicCmpXchgOp::create( - builder, loc, address, arg1, arg2, successOrdering, failureOrdering); - mlir::Value boolResult = - mlir::LLVM::ExtractValueOp::create(builder, loc, cmpxchg, 1); - return builder.createConvert(loc, resultType, boolResult); -} - -mlir::Value IntrinsicLibrary::genAtomicDec(mlir::Type resultType, - llvm::ArrayRef<mlir::Value> args) { - assert(args.size() == 2); - assert(mlir::isa<mlir::IntegerType>(args[1].getType())); - - mlir::LLVM::AtomicBinOp binOp = mlir::LLVM::AtomicBinOp::udec_wrap; - return genAtomBinOp(builder, loc, binOp, args[0], args[1]); -} - -// ATOMICEXCH -fir::ExtendedValue -IntrinsicLibrary::genAtomicExch(mlir::Type resultType, - llvm::ArrayRef<fir::ExtendedValue> args) { - assert(args.size() == 2); - mlir::Value arg0 = fir::getBase(args[0]); - mlir::Value arg1 = fir::getBase(args[1]); - assert(arg1.getType().isIntOrFloat()); - - mlir::LLVM::AtomicBinOp binOp = mlir::LLVM::AtomicBinOp::xchg; - return genAtomBinOp(builder, loc, binOp, arg0, arg1); -} - -mlir::Value IntrinsicLibrary::genAtomicInc(mlir::Type resultType, - llvm::ArrayRef<mlir::Value> args) { - assert(args.size() == 2); - assert(mlir::isa<mlir::IntegerType>(args[1].getType())); - - mlir::LLVM::AtomicBinOp binOp = mlir::LLVM::AtomicBinOp::uinc_wrap; - return genAtomBinOp(builder, loc, binOp, args[0], args[1]); -} - -mlir::Value IntrinsicLibrary::genAtomicMax(mlir::Type resultType, - llvm::ArrayRef<mlir::Value> args) { - assert(args.size() == 2); - - mlir::LLVM::AtomicBinOp binOp = - mlir::isa<mlir::IntegerType>(args[1].getType()) - ? mlir::LLVM::AtomicBinOp::max - : mlir::LLVM::AtomicBinOp::fmax; - return genAtomBinOp(builder, loc, binOp, args[0], args[1]); -} - -mlir::Value IntrinsicLibrary::genAtomicMin(mlir::Type resultType, - llvm::ArrayRef<mlir::Value> args) { - assert(args.size() == 2); - - mlir::LLVM::AtomicBinOp binOp = - mlir::isa<mlir::IntegerType>(args[1].getType()) - ? mlir::LLVM::AtomicBinOp::min - : mlir::LLVM::AtomicBinOp::fmin; - return genAtomBinOp(builder, loc, binOp, args[0], args[1]); -} - -// ATOMICXOR -fir::ExtendedValue -IntrinsicLibrary::genAtomicXor(mlir::Type resultType, - llvm::ArrayRef<fir::ExtendedValue> args) { - assert(args.size() == 2); - mlir::Value arg0 = fir::getBase(args[0]); - mlir::Value arg1 = fir::getBase(args[1]); - return genAtomBinOp(builder, loc, mlir::LLVM::AtomicBinOp::_xor, arg0, arg1); -} - // ASSOCIATED fir::ExtendedValue IntrinsicLibrary::genAssociated(mlir::Type resultType, @@ -3311,114 +2816,6 @@ IntrinsicLibrary::genAssociated(mlir::Type resultType, return fir::runtime::genAssociated(builder, loc, pointerBox, targetBox); } -static mlir::Value convertPtrToNVVMSpace(fir::FirOpBuilder &builder, - mlir::Location loc, - mlir::Value barrier, - mlir::NVVM::NVVMMemorySpace space) { - mlir::Value llvmPtr = fir::ConvertOp::create( - builder, loc, mlir::LLVM::LLVMPointerType::get(builder.getContext()), - barrier); - mlir::Value addrCast = mlir::LLVM::AddrSpaceCastOp::create( - builder, loc, - mlir::LLVM::LLVMPointerType::get(builder.getContext(), - static_cast<unsigned>(space)), - llvmPtr); - return addrCast; -} - -// BARRIER_ARRIVE (CUDA) -mlir::Value -IntrinsicLibrary::genBarrierArrive(mlir::Type resultType, - llvm::ArrayRef<mlir::Value> args) { - assert(args.size() == 1); - mlir::Value barrier = convertPtrToNVVMSpace( - builder, loc, args[0], mlir::NVVM::NVVMMemorySpace::Shared); - return mlir::NVVM::MBarrierArriveSharedOp::create(builder, loc, resultType, - barrier) - .getResult(); -} - -// BARRIER_ARRIBVE_CNT (CUDA) -mlir::Value -IntrinsicLibrary::genBarrierArriveCnt(mlir::Type resultType, - llvm::ArrayRef<mlir::Value> args) { - assert(args.size() == 2); - mlir::Value barrier = convertPtrToNVVMSpace( - builder, loc, args[0], mlir::NVVM::NVVMMemorySpace::Shared); - mlir::Value token = fir::AllocaOp::create(builder, loc, resultType); - // TODO: the MBarrierArriveExpectTxOp is not taking the state argument and - // currently just the sink symbol `_`. - // https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#parallel-synchronization-and-communication-instructions-mbarrier-arrive - mlir::NVVM::MBarrierArriveExpectTxOp::create(builder, loc, barrier, args[1], - {}); - return fir::LoadOp::create(builder, loc, token); -} - -// BARRIER_INIT (CUDA) -void IntrinsicLibrary::genBarrierInit(llvm::ArrayRef<fir::ExtendedValue> args) { - assert(args.size() == 2); - mlir::Value barrier = convertPtrToNVVMSpace( - builder, loc, fir::getBase(args[0]), mlir::NVVM::NVVMMemorySpace::Shared); - mlir::NVVM::MBarrierInitOp::create(builder, loc, barrier, - fir::getBase(args[1]), {}); - auto kind = mlir::NVVM::ProxyKindAttr::get( - builder.getContext(), mlir::NVVM::ProxyKind::async_shared); - auto space = mlir::NVVM::SharedSpaceAttr::get( - builder.getContext(), mlir::NVVM::SharedSpace::shared_cta); - mlir::NVVM::FenceProxyOp::create(builder, loc, kind, space); -} - -// BARRIER_TRY_WAIT (CUDA) -mlir::Value -IntrinsicLibrary::genBarrierTryWait(mlir::Type resultType, - llvm::ArrayRef<mlir::Value> args) { - assert(args.size() == 2); - mlir::Value res = fir::AllocaOp::create(builder, loc, resultType); - mlir::Value zero = builder.createIntegerConstant(loc, resultType, 0); - fir::StoreOp::create(builder, loc, zero, res); - mlir::Value ns = - builder.createIntegerConstant(loc, builder.getI32Type(), 1000000); - mlir::Value load = fir::LoadOp::create(builder, loc, res); - auto whileOp = mlir::scf::WhileOp::create( - builder, loc, mlir::TypeRange{resultType}, mlir::ValueRange{load}); - mlir::Block *beforeBlock = builder.createBlock(&whileOp.getBefore()); - mlir::Value beforeArg = beforeBlock->addArgument(resultType, loc); - builder.setInsertionPointToStart(beforeBlock); - mlir::Value condition = mlir::arith::CmpIOp::create( - builder, loc, mlir::arith::CmpIPredicate::ne, beforeArg, zero); - mlir::scf::ConditionOp::create(builder, loc, condition, beforeArg); - mlir::Block *afterBlock = builder.createBlock(&whileOp.getAfter()); - afterBlock->addArgument(resultType, loc); - builder.setInsertionPointToStart(afterBlock); - auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(builder.getContext()); - auto barrier = builder.createConvert(loc, llvmPtrTy, args[0]); - mlir::Value ret = - mlir::NVVM::InlinePtxOp::create( - builder, loc, {resultType}, {barrier, args[1], ns}, {}, - ".reg .pred p; mbarrier.try_wait.shared.b64 p, [%1], %2, %3; " - "selp.b32 %0, 1, 0, p;", - {}) - .getResult(0); - mlir::scf::YieldOp::create(builder, loc, ret); - builder.setInsertionPointAfter(whileOp); - return whileOp.getResult(0); -} - -// BARRIER_TRY_WAIT_SLEEP (CUDA) -mlir::Value -IntrinsicLibrary::genBarrierTryWaitSleep(mlir::Type resultType, - llvm::ArrayRef<mlir::Value> args) { - assert(args.size() == 3); - auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(builder.getContext()); - auto barrier = builder.createConvert(loc, llvmPtrTy, args[0]); - return mlir::NVVM::InlinePtxOp::create( - builder, loc, {resultType}, {barrier, args[1], args[2]}, {}, - ".reg .pred p; mbarrier.try_wait.shared.b64 p, [%1], %2, %3; " - "selp.b32 %0, 1, 0, p;", - {}) - .getResult(0); -} - // BESSEL_JN fir::ExtendedValue IntrinsicLibrary::genBesselJn(mlir::Type resultType, @@ -4152,30 +3549,6 @@ IntrinsicLibrary::genCshift(mlir::Type resultType, return readAndAddCleanUp(resultMutableBox, resultType, "CSHIFT"); } -// __LDCA, __LDCS, __LDLU, __LDCV -template <const char *fctName, int extent> -fir::ExtendedValue -IntrinsicLibrary::genCUDALDXXFunc(mlir::Type resultType, - llvm::ArrayRef<fir::ExtendedValue> args) { - assert(args.size() == 1); - mlir::Type resTy = fir::SequenceType::get(extent, resultType); - mlir::Value arg = fir::getBase(args[0]); - mlir::Value res = fir::AllocaOp::create(builder, loc, resTy); - if (mlir::isa<fir::BaseBoxType>(arg.getType())) - arg = fir::BoxAddrOp::create(builder, loc, arg); - mlir::Type refResTy = fir::ReferenceType::get(resTy); - mlir::FunctionType ftype = - mlir::FunctionType::get(arg.getContext(), {refResTy, refResTy}, {}); - auto funcOp = builder.createFunction(loc, fctName, ftype); - llvm::SmallVector<mlir::Value> funcArgs; - funcArgs.push_back(res); - funcArgs.push_back(arg); - fir::CallOp::create(builder, loc, funcOp, funcArgs); - mlir::Value ext = - builder.createIntegerConstant(loc, builder.getIndexType(), extent); - return fir::ArrayBoxValue(res, {ext}); -} - // DATE_AND_TIME void IntrinsicLibrary::genDateAndTime(llvm::ArrayRef<fir::ExtendedValue> args) { assert(args.size() == 4 && "date_and_time has 4 args"); @@ -4508,17 +3881,6 @@ IntrinsicLibrary::genExtendsTypeOf(mlir::Type resultType, fir::getBase(args[1]))); } -// FENCE_PROXY_ASYNC (CUDA) -void IntrinsicLibrary::genFenceProxyAsync( - llvm::ArrayRef<fir::ExtendedValue> args) { - assert(args.size() == 0); - auto kind = mlir::NVVM::ProxyKindAttr::get( - builder.getContext(), mlir::NVVM::ProxyKind::async_shared); - auto space = mlir::NVVM::SharedSpaceAttr::get( - builder.getContext(), mlir::NVVM::SharedSpace::shared_cta); - mlir::NVVM::FenceProxyOp::create(builder, loc, kind, space); -} - // FINDLOC fir::ExtendedValue IntrinsicLibrary::genFindloc(mlir::Type resultType, @@ -4601,6 +3963,40 @@ mlir::Value IntrinsicLibrary::genFloor(mlir::Type resultType, return builder.createConvert(loc, resultType, floor); } +// FLUSH +void IntrinsicLibrary::genFlush(llvm::ArrayRef<fir::ExtendedValue> args) { + assert(args.size() == 1); + + mlir::Value unit; + if (isStaticallyAbsent(args[0])) + // Give a sentinal value of `-1` on the `()` case. + unit = builder.createIntegerConstant(loc, builder.getI32Type(), -1); + else { + unit = fir::getBase(args[0]); + if (isOptional(unit)) { + mlir::Value isPresent = + fir::IsPresentOp::create(builder, loc, builder.getI1Type(), unit); + unit = builder + .genIfOp(loc, builder.getI32Type(), isPresent, + /*withElseRegion=*/true) + .genThen([&]() { + mlir::Value loaded = fir::LoadOp::create(builder, loc, unit); + fir::ResultOp::create(builder, loc, loaded); + }) + .genElse([&]() { + mlir::Value negOne = builder.createIntegerConstant( + loc, builder.getI32Type(), -1); + fir::ResultOp::create(builder, loc, negOne); + }) + .getResults()[0]; + } else { + unit = fir::LoadOp::create(builder, loc, unit); + } + } + + fir::runtime::genFlush(builder, loc, unit); +} + // FRACTION mlir::Value IntrinsicLibrary::genFraction(mlir::Type resultType, llvm::ArrayRef<mlir::Value> args) { @@ -4680,6 +4076,15 @@ IntrinsicLibrary::genFtell(std::optional<mlir::Type> resultType, } } +// GET_TEAM +mlir::Value IntrinsicLibrary::genGetTeam(mlir::Type resultType, + llvm::ArrayRef<mlir::Value> args) { + converter->checkCoarrayEnabled(); + assert(args.size() == 1); + return mif::GetTeamOp::create(builder, loc, fir::BoxType::get(resultType), + /*level*/ args[0]); +} + // GETCWD fir::ExtendedValue IntrinsicLibrary::genGetCwd(std::optional<mlir::Type> resultType, @@ -6765,6 +6170,20 @@ IntrinsicLibrary::genIparity(mlir::Type resultType, "IPARITY", resultType, args); } +// IRAND +fir::ExtendedValue +IntrinsicLibrary::genIrand(mlir::Type resultType, + llvm::ArrayRef<fir::ExtendedValue> args) { + assert(args.size() == 1); + mlir::Value i = + isStaticallyPresent(args[0]) + ? fir::getBase(args[0]) + : fir::AbsentOp::create(builder, loc, + builder.getRefType(builder.getI32Type())) + .getResult(); + return fir::runtime::genIrand(builder, loc, i); +} + // IS_CONTIGUOUS fir::ExtendedValue IntrinsicLibrary::genIsContiguous(mlir::Type resultType, @@ -6948,12 +6367,6 @@ IntrinsicLibrary::genCharacterCompare(mlir::Type resultType, fir::getBase(args[1]), fir::getLen(args[1])); } -static bool isOptional(mlir::Value value) { - auto varIface = mlir::dyn_cast_or_null<fir::FortranVariableOpInterface>( - value.getDefiningOp()); - return varIface && varIface.isOptional(); -} - // LOC fir::ExtendedValue IntrinsicLibrary::genLoc(mlir::Type resultType, @@ -7029,67 +6442,6 @@ mlir::Value IntrinsicLibrary::genMask(mlir::Type resultType, return result; } -// MATCH_ALL_SYNC -mlir::Value -IntrinsicLibrary::genMatchAllSync(mlir::Type resultType, - llvm::ArrayRef<mlir::Value> args) { - assert(args.size() == 3); - bool is32 = args[1].getType().isInteger(32) || args[1].getType().isF32(); - - mlir::Type i1Ty = builder.getI1Type(); - mlir::MLIRContext *context = builder.getContext(); - - mlir::Value arg1 = args[1]; - if (arg1.getType().isF32() || arg1.getType().isF64()) - arg1 = fir::ConvertOp::create( - builder, loc, is32 ? builder.getI32Type() : builder.getI64Type(), arg1); - - mlir::Type retTy = - mlir::LLVM::LLVMStructType::getLiteral(context, {resultType, i1Ty}); - auto match = - mlir::NVVM::MatchSyncOp::create(builder, loc, retTy, args[0], arg1, - mlir::NVVM::MatchSyncKind::all) - .getResult(); - auto value = mlir::LLVM::ExtractValueOp::create(builder, loc, match, 0); - auto pred = mlir::LLVM::ExtractValueOp::create(builder, loc, match, 1); - auto conv = mlir::LLVM::ZExtOp::create(builder, loc, resultType, pred); - fir::StoreOp::create(builder, loc, conv, args[2]); - return value; -} - -// ALL_SYNC, ANY_SYNC, BALLOT_SYNC -template <mlir::NVVM::VoteSyncKind kind> -mlir::Value IntrinsicLibrary::genVoteSync(mlir::Type resultType, - llvm::ArrayRef<mlir::Value> args) { - assert(args.size() == 2); - mlir::Value arg1 = - fir::ConvertOp::create(builder, loc, builder.getI1Type(), args[1]); - mlir::Type resTy = kind == mlir::NVVM::VoteSyncKind::ballot - ? builder.getI32Type() - : builder.getI1Type(); - auto voteRes = - mlir::NVVM::VoteSyncOp::create(builder, loc, resTy, args[0], arg1, kind) - .getResult(); - return fir::ConvertOp::create(builder, loc, resultType, voteRes); -} - -// MATCH_ANY_SYNC -mlir::Value -IntrinsicLibrary::genMatchAnySync(mlir::Type resultType, - llvm::ArrayRef<mlir::Value> args) { - assert(args.size() == 2); - bool is32 = args[1].getType().isInteger(32) || args[1].getType().isF32(); - - mlir::Value arg1 = args[1]; - if (arg1.getType().isF32() || arg1.getType().isF64()) - arg1 = fir::ConvertOp::create( - builder, loc, is32 ? builder.getI32Type() : builder.getI64Type(), arg1); - - return mlir::NVVM::MatchSyncOp::create(builder, loc, resultType, args[0], - arg1, mlir::NVVM::MatchSyncKind::any) - .getResult(); -} - // MATMUL fir::ExtendedValue IntrinsicLibrary::genMatmul(mlir::Type resultType, @@ -7237,11 +6589,9 @@ static mlir::Value genFastMod(fir::FirOpBuilder &builder, mlir::Location loc, mlir::Value IntrinsicLibrary::genMod(mlir::Type resultType, llvm::ArrayRef<mlir::Value> args) { auto mod = builder.getModule(); - bool dontUseFastRealMod = false; - bool canUseApprox = mlir::arith::bitEnumContainsAny( - builder.getFastMathFlags(), mlir::arith::FastMathFlags::afn); - if (auto attr = mod->getAttrOfType<mlir::BoolAttr>("fir.no_fast_real_mod")) - dontUseFastRealMod = attr.getValue(); + bool useFastRealMod = false; + if (auto attr = mod->getAttrOfType<mlir::BoolAttr>("fir.fast_real_mod")) + useFastRealMod = attr.getValue(); assert(args.size() == 2); if (resultType.isUnsignedInteger()) { @@ -7254,7 +6604,7 @@ mlir::Value IntrinsicLibrary::genMod(mlir::Type resultType, if (mlir::isa<mlir::IntegerType>(resultType)) return mlir::arith::RemSIOp::create(builder, loc, args[0], args[1]); - if (resultType.isFloat() && canUseApprox && !dontUseFastRealMod) { + if (resultType.isFloat() && useFastRealMod) { // Treat MOD as an approximate function and code-gen inline code // instead of calling into the Fortran runtime library. return builder.createConvert(loc, resultType, @@ -7707,14 +7057,6 @@ IntrinsicLibrary::genNumImages(mlir::Type resultType, return mif::NumImagesOp::create(builder, loc).getResult(); } -// CLOCK, CLOCK64, GLOBALTIMER -template <typename OpTy> -mlir::Value IntrinsicLibrary::genNVVMTime(mlir::Type resultType, - llvm::ArrayRef<mlir::Value> args) { - assert(args.size() == 0 && "expect no arguments"); - return OpTy::create(builder, loc, resultType).getResult(); -} - // PACK fir::ExtendedValue IntrinsicLibrary::genPack(mlir::Type resultType, @@ -7868,6 +7210,19 @@ IntrinsicLibrary::genPutenv(std::optional<mlir::Type> resultType, return {}; } +// RAND +fir::ExtendedValue +IntrinsicLibrary::genRand(mlir::Type, llvm::ArrayRef<fir::ExtendedValue> args) { + assert(args.size() == 1); + mlir::Value i = + isStaticallyPresent(args[0]) + ? fir::getBase(args[0]) + : fir::AbsentOp::create(builder, loc, + builder.getRefType(builder.getI32Type())) + .getResult(); + return fir::runtime::genRand(builder, loc, i); +} + // RANDOM_INIT void IntrinsicLibrary::genRandomInit(llvm::ArrayRef<fir::ExtendedValue> args) { assert(args.size() == 2); @@ -8533,6 +7888,16 @@ mlir::Value IntrinsicLibrary::genShiftA(mlir::Type resultType, return result; } +void IntrinsicLibrary::genShowDescriptor( + llvm::ArrayRef<fir::ExtendedValue> args) { + assert(args.size() == 1 && "expected single argument for show_descriptor"); + const mlir::Value descriptor = fir::getBase(args[0]); + + assert(fir::isa_box_type(descriptor.getType()) && + "argument must have been lowered to box type"); + fir::runtime::genShowDescriptor(builder, loc, descriptor); +} + // SIGNAL void IntrinsicLibrary::genSignalSubroutine( llvm::ArrayRef<fir::ExtendedValue> args) { @@ -8689,90 +8054,14 @@ mlir::Value IntrinsicLibrary::genTanpi(mlir::Type resultType, return getRuntimeCallGenerator("tan", ftype)(builder, loc, {arg}); } -// THIS_GRID -mlir::Value IntrinsicLibrary::genThisGrid(mlir::Type resultType, - llvm::ArrayRef<mlir::Value> args) { - assert(args.size() == 0); - auto recTy = mlir::cast<fir::RecordType>(resultType); - assert(recTy && "RecordType expepected"); - mlir::Value res = fir::AllocaOp::create(builder, loc, resultType); - mlir::Type i32Ty = builder.getI32Type(); - - mlir::Value threadIdX = mlir::NVVM::ThreadIdXOp::create(builder, loc, i32Ty); - mlir::Value threadIdY = mlir::NVVM::ThreadIdYOp::create(builder, loc, i32Ty); - mlir::Value threadIdZ = mlir::NVVM::ThreadIdZOp::create(builder, loc, i32Ty); - - mlir::Value blockIdX = mlir::NVVM::BlockIdXOp::create(builder, loc, i32Ty); - mlir::Value blockIdY = mlir::NVVM::BlockIdYOp::create(builder, loc, i32Ty); - mlir::Value blockIdZ = mlir::NVVM::BlockIdZOp::create(builder, loc, i32Ty); - - mlir::Value blockDimX = mlir::NVVM::BlockDimXOp::create(builder, loc, i32Ty); - mlir::Value blockDimY = mlir::NVVM::BlockDimYOp::create(builder, loc, i32Ty); - mlir::Value blockDimZ = mlir::NVVM::BlockDimZOp::create(builder, loc, i32Ty); - mlir::Value gridDimX = mlir::NVVM::GridDimXOp::create(builder, loc, i32Ty); - mlir::Value gridDimY = mlir::NVVM::GridDimYOp::create(builder, loc, i32Ty); - mlir::Value gridDimZ = mlir::NVVM::GridDimZOp::create(builder, loc, i32Ty); - - // this_grid.size = ((blockDim.z * gridDim.z) * (blockDim.y * gridDim.y)) * - // (blockDim.x * gridDim.x); - mlir::Value resZ = - mlir::arith::MulIOp::create(builder, loc, blockDimZ, gridDimZ); - mlir::Value resY = - mlir::arith::MulIOp::create(builder, loc, blockDimY, gridDimY); - mlir::Value resX = - mlir::arith::MulIOp::create(builder, loc, blockDimX, gridDimX); - mlir::Value resZY = mlir::arith::MulIOp::create(builder, loc, resZ, resY); - mlir::Value size = mlir::arith::MulIOp::create(builder, loc, resZY, resX); - - // tmp = ((blockIdx.z * gridDim.y * gridDim.x) + (blockIdx.y * gridDim.x)) + - // blockIdx.x; - // this_group.rank = tmp * ((blockDim.x * blockDim.y) * blockDim.z) + - // ((threadIdx.z * blockDim.y) * blockDim.x) + - // (threadIdx.y * blockDim.x) + threadIdx.x + 1; - mlir::Value r1 = - mlir::arith::MulIOp::create(builder, loc, blockIdZ, gridDimY); - mlir::Value r2 = mlir::arith::MulIOp::create(builder, loc, r1, gridDimX); - mlir::Value r3 = - mlir::arith::MulIOp::create(builder, loc, blockIdY, gridDimX); - mlir::Value r2r3 = mlir::arith::AddIOp::create(builder, loc, r2, r3); - mlir::Value tmp = mlir::arith::AddIOp::create(builder, loc, r2r3, blockIdX); - - mlir::Value bXbY = - mlir::arith::MulIOp::create(builder, loc, blockDimX, blockDimY); - mlir::Value bXbYbZ = - mlir::arith::MulIOp::create(builder, loc, bXbY, blockDimZ); - mlir::Value tZbY = - mlir::arith::MulIOp::create(builder, loc, threadIdZ, blockDimY); - mlir::Value tZbYbX = - mlir::arith::MulIOp::create(builder, loc, tZbY, blockDimX); - mlir::Value tYbX = - mlir::arith::MulIOp::create(builder, loc, threadIdY, blockDimX); - mlir::Value rank = mlir::arith::MulIOp::create(builder, loc, tmp, bXbYbZ); - rank = mlir::arith::AddIOp::create(builder, loc, rank, tZbYbX); - rank = mlir::arith::AddIOp::create(builder, loc, rank, tYbX); - rank = mlir::arith::AddIOp::create(builder, loc, rank, threadIdX); - mlir::Value one = builder.createIntegerConstant(loc, i32Ty, 1); - rank = mlir::arith::AddIOp::create(builder, loc, rank, one); - - auto sizeFieldName = recTy.getTypeList()[1].first; - mlir::Type sizeFieldTy = recTy.getTypeList()[1].second; - mlir::Type fieldIndexType = fir::FieldType::get(resultType.getContext()); - mlir::Value sizeFieldIndex = fir::FieldIndexOp::create( - builder, loc, fieldIndexType, sizeFieldName, recTy, - /*typeParams=*/mlir::ValueRange{}); - mlir::Value sizeCoord = fir::CoordinateOp::create( - builder, loc, builder.getRefType(sizeFieldTy), res, sizeFieldIndex); - fir::StoreOp::create(builder, loc, size, sizeCoord); - - auto rankFieldName = recTy.getTypeList()[2].first; - mlir::Type rankFieldTy = recTy.getTypeList()[2].second; - mlir::Value rankFieldIndex = fir::FieldIndexOp::create( - builder, loc, fieldIndexType, rankFieldName, recTy, - /*typeParams=*/mlir::ValueRange{}); - mlir::Value rankCoord = fir::CoordinateOp::create( - builder, loc, builder.getRefType(rankFieldTy), res, rankFieldIndex); - fir::StoreOp::create(builder, loc, rank, rankCoord); - return res; +// TEAM_NUMBER +fir::ExtendedValue +IntrinsicLibrary::genTeamNumber(mlir::Type, + llvm::ArrayRef<fir::ExtendedValue> args) { + converter->checkCoarrayEnabled(); + assert(args.size() == 1); + return mif::TeamNumberOp::create(builder, loc, + /*team*/ fir::getBase(args[0])); } // THIS_IMAGE @@ -8790,99 +8079,6 @@ IntrinsicLibrary::genThisImage(mlir::Type resultType, return builder.createConvert(loc, resultType, res); } -// THIS_THREAD_BLOCK -mlir::Value -IntrinsicLibrary::genThisThreadBlock(mlir::Type resultType, - llvm::ArrayRef<mlir::Value> args) { - assert(args.size() == 0); - auto recTy = mlir::cast<fir::RecordType>(resultType); - assert(recTy && "RecordType expepected"); - mlir::Value res = fir::AllocaOp::create(builder, loc, resultType); - mlir::Type i32Ty = builder.getI32Type(); - - // this_thread_block%size = blockDim.z * blockDim.y * blockDim.x; - mlir::Value blockDimX = mlir::NVVM::BlockDimXOp::create(builder, loc, i32Ty); - mlir::Value blockDimY = mlir::NVVM::BlockDimYOp::create(builder, loc, i32Ty); - mlir::Value blockDimZ = mlir::NVVM::BlockDimZOp::create(builder, loc, i32Ty); - mlir::Value size = - mlir::arith::MulIOp::create(builder, loc, blockDimZ, blockDimY); - size = mlir::arith::MulIOp::create(builder, loc, size, blockDimX); - - // this_thread_block%rank = ((threadIdx.z * blockDim.y) * blockDim.x) + - // (threadIdx.y * blockDim.x) + threadIdx.x + 1; - mlir::Value threadIdX = mlir::NVVM::ThreadIdXOp::create(builder, loc, i32Ty); - mlir::Value threadIdY = mlir::NVVM::ThreadIdYOp::create(builder, loc, i32Ty); - mlir::Value threadIdZ = mlir::NVVM::ThreadIdZOp::create(builder, loc, i32Ty); - mlir::Value r1 = - mlir::arith::MulIOp::create(builder, loc, threadIdZ, blockDimY); - mlir::Value r2 = mlir::arith::MulIOp::create(builder, loc, r1, blockDimX); - mlir::Value r3 = - mlir::arith::MulIOp::create(builder, loc, threadIdY, blockDimX); - mlir::Value r2r3 = mlir::arith::AddIOp::create(builder, loc, r2, r3); - mlir::Value rank = mlir::arith::AddIOp::create(builder, loc, r2r3, threadIdX); - mlir::Value one = builder.createIntegerConstant(loc, i32Ty, 1); - rank = mlir::arith::AddIOp::create(builder, loc, rank, one); - - auto sizeFieldName = recTy.getTypeList()[1].first; - mlir::Type sizeFieldTy = recTy.getTypeList()[1].second; - mlir::Type fieldIndexType = fir::FieldType::get(resultType.getContext()); - mlir::Value sizeFieldIndex = fir::FieldIndexOp::create( - builder, loc, fieldIndexType, sizeFieldName, recTy, - /*typeParams=*/mlir::ValueRange{}); - mlir::Value sizeCoord = fir::CoordinateOp::create( - builder, loc, builder.getRefType(sizeFieldTy), res, sizeFieldIndex); - fir::StoreOp::create(builder, loc, size, sizeCoord); - - auto rankFieldName = recTy.getTypeList()[2].first; - mlir::Type rankFieldTy = recTy.getTypeList()[2].second; - mlir::Value rankFieldIndex = fir::FieldIndexOp::create( - builder, loc, fieldIndexType, rankFieldName, recTy, - /*typeParams=*/mlir::ValueRange{}); - mlir::Value rankCoord = fir::CoordinateOp::create( - builder, loc, builder.getRefType(rankFieldTy), res, rankFieldIndex); - fir::StoreOp::create(builder, loc, rank, rankCoord); - return res; -} - -// THIS_WARP -mlir::Value IntrinsicLibrary::genThisWarp(mlir::Type resultType, - llvm::ArrayRef<mlir::Value> args) { - assert(args.size() == 0); - auto recTy = mlir::cast<fir::RecordType>(resultType); - assert(recTy && "RecordType expepected"); - mlir::Value res = fir::AllocaOp::create(builder, loc, resultType); - mlir::Type i32Ty = builder.getI32Type(); - - // coalesced_group%size = 32 - mlir::Value size = builder.createIntegerConstant(loc, i32Ty, 32); - auto sizeFieldName = recTy.getTypeList()[1].first; - mlir::Type sizeFieldTy = recTy.getTypeList()[1].second; - mlir::Type fieldIndexType = fir::FieldType::get(resultType.getContext()); - mlir::Value sizeFieldIndex = fir::FieldIndexOp::create( - builder, loc, fieldIndexType, sizeFieldName, recTy, - /*typeParams=*/mlir::ValueRange{}); - mlir::Value sizeCoord = fir::CoordinateOp::create( - builder, loc, builder.getRefType(sizeFieldTy), res, sizeFieldIndex); - fir::StoreOp::create(builder, loc, size, sizeCoord); - - // coalesced_group%rank = threadIdx.x & 31 + 1 - mlir::Value threadIdX = mlir::NVVM::ThreadIdXOp::create(builder, loc, i32Ty); - mlir::Value mask = builder.createIntegerConstant(loc, i32Ty, 31); - mlir::Value one = builder.createIntegerConstant(loc, i32Ty, 1); - mlir::Value masked = - mlir::arith::AndIOp::create(builder, loc, threadIdX, mask); - mlir::Value rank = mlir::arith::AddIOp::create(builder, loc, masked, one); - auto rankFieldName = recTy.getTypeList()[2].first; - mlir::Type rankFieldTy = recTy.getTypeList()[2].second; - mlir::Value rankFieldIndex = fir::FieldIndexOp::create( - builder, loc, fieldIndexType, rankFieldName, recTy, - /*typeParams=*/mlir::ValueRange{}); - mlir::Value rankCoord = fir::CoordinateOp::create( - builder, loc, builder.getRefType(rankFieldTy), res, rankFieldIndex); - fir::StoreOp::create(builder, loc, rank, rankCoord); - return res; -} - // TRAILZ mlir::Value IntrinsicLibrary::genTrailz(mlir::Type resultType, llvm::ArrayRef<mlir::Value> args) { @@ -9104,65 +8300,6 @@ IntrinsicLibrary::genSum(mlir::Type resultType, resultType, args); } -// SYNCTHREADS -void IntrinsicLibrary::genSyncThreads(llvm::ArrayRef<fir::ExtendedValue> args) { - mlir::NVVM::Barrier0Op::create(builder, loc); -} - -// SYNCTHREADS_AND -mlir::Value -IntrinsicLibrary::genSyncThreadsAnd(mlir::Type resultType, - llvm::ArrayRef<mlir::Value> args) { - constexpr llvm::StringLiteral funcName = "llvm.nvvm.barrier0.and"; - mlir::MLIRContext *context = builder.getContext(); - mlir::Type i32 = builder.getI32Type(); - mlir::FunctionType ftype = - mlir::FunctionType::get(context, {resultType}, {i32}); - auto funcOp = builder.createFunction(loc, funcName, ftype); - mlir::Value arg = builder.createConvert(loc, i32, args[0]); - return fir::CallOp::create(builder, loc, funcOp, {arg}).getResult(0); -} - -// SYNCTHREADS_COUNT -mlir::Value -IntrinsicLibrary::genSyncThreadsCount(mlir::Type resultType, - llvm::ArrayRef<mlir::Value> args) { - constexpr llvm::StringLiteral funcName = "llvm.nvvm.barrier0.popc"; - mlir::MLIRContext *context = builder.getContext(); - mlir::Type i32 = builder.getI32Type(); - mlir::FunctionType ftype = - mlir::FunctionType::get(context, {resultType}, {i32}); - auto funcOp = builder.createFunction(loc, funcName, ftype); - mlir::Value arg = builder.createConvert(loc, i32, args[0]); - return fir::CallOp::create(builder, loc, funcOp, {arg}).getResult(0); -} - -// SYNCTHREADS_OR -mlir::Value -IntrinsicLibrary::genSyncThreadsOr(mlir::Type resultType, - llvm::ArrayRef<mlir::Value> args) { - constexpr llvm::StringLiteral funcName = "llvm.nvvm.barrier0.or"; - mlir::MLIRContext *context = builder.getContext(); - mlir::Type i32 = builder.getI32Type(); - mlir::FunctionType ftype = - mlir::FunctionType::get(context, {resultType}, {i32}); - auto funcOp = builder.createFunction(loc, funcName, ftype); - mlir::Value arg = builder.createConvert(loc, i32, args[0]); - return fir::CallOp::create(builder, loc, funcOp, {arg}).getResult(0); -} - -// SYNCWARP -void IntrinsicLibrary::genSyncWarp(llvm::ArrayRef<fir::ExtendedValue> args) { - assert(args.size() == 1); - constexpr llvm::StringLiteral funcName = "llvm.nvvm.bar.warp.sync"; - mlir::Value mask = fir::getBase(args[0]); - mlir::FunctionType funcType = - mlir::FunctionType::get(builder.getContext(), {mask.getType()}, {}); - auto funcOp = builder.createFunction(loc, funcName, funcType); - llvm::SmallVector<mlir::Value> argsList{mask}; - fir::CallOp::create(builder, loc, funcOp, argsList); -} - // SYSTEM fir::ExtendedValue IntrinsicLibrary::genSystem(std::optional<mlir::Type> resultType, @@ -9294,38 +8431,6 @@ IntrinsicLibrary::genTranspose(mlir::Type resultType, return readAndAddCleanUp(resultMutableBox, resultType, "TRANSPOSE"); } -// THREADFENCE -void IntrinsicLibrary::genThreadFence(llvm::ArrayRef<fir::ExtendedValue> args) { - constexpr llvm::StringLiteral funcName = "llvm.nvvm.membar.gl"; - mlir::FunctionType funcType = - mlir::FunctionType::get(builder.getContext(), {}, {}); - auto funcOp = builder.createFunction(loc, funcName, funcType); - llvm::SmallVector<mlir::Value> noArgs; - fir::CallOp::create(builder, loc, funcOp, noArgs); -} - -// THREADFENCE_BLOCK -void IntrinsicLibrary::genThreadFenceBlock( - llvm::ArrayRef<fir::ExtendedValue> args) { - constexpr llvm::StringLiteral funcName = "llvm.nvvm.membar.cta"; - mlir::FunctionType funcType = - mlir::FunctionType::get(builder.getContext(), {}, {}); - auto funcOp = builder.createFunction(loc, funcName, funcType); - llvm::SmallVector<mlir::Value> noArgs; - fir::CallOp::create(builder, loc, funcOp, noArgs); -} - -// THREADFENCE_SYSTEM -void IntrinsicLibrary::genThreadFenceSystem( - llvm::ArrayRef<fir::ExtendedValue> args) { - constexpr llvm::StringLiteral funcName = "llvm.nvvm.membar.sys"; - mlir::FunctionType funcType = - mlir::FunctionType::get(builder.getContext(), {}, {}); - auto funcOp = builder.createFunction(loc, funcName, funcType); - llvm::SmallVector<mlir::Value> noArgs; - fir::CallOp::create(builder, loc, funcOp, noArgs); -} - // TIME mlir::Value IntrinsicLibrary::genTime(mlir::Type resultType, llvm::ArrayRef<mlir::Value> args) { @@ -9334,226 +8439,6 @@ mlir::Value IntrinsicLibrary::genTime(mlir::Type resultType, fir::runtime::genTime(builder, loc)); } -// TMA_BULK_COMMIT_GROUP (CUDA) -void IntrinsicLibrary::genTMABulkCommitGroup( - llvm::ArrayRef<fir::ExtendedValue> args) { - assert(args.size() == 0); - mlir::NVVM::CpAsyncBulkCommitGroupOp::create(builder, loc); -} - -// TMA_BULK_G2S (CUDA) -void IntrinsicLibrary::genTMABulkG2S(llvm::ArrayRef<fir::ExtendedValue> args) { - assert(args.size() == 4); - mlir::Value barrier = convertPtrToNVVMSpace( - builder, loc, fir::getBase(args[0]), mlir::NVVM::NVVMMemorySpace::Shared); - mlir::Value dst = - convertPtrToNVVMSpace(builder, loc, fir::getBase(args[2]), - mlir::NVVM::NVVMMemorySpace::SharedCluster); - mlir::Value src = convertPtrToNVVMSpace(builder, loc, fir::getBase(args[1]), - mlir::NVVM::NVVMMemorySpace::Global); - mlir::NVVM::CpAsyncBulkGlobalToSharedClusterOp::create( - builder, loc, dst, src, barrier, fir::getBase(args[3]), {}, {}); -} - -static void genTMABulkLoad(fir::FirOpBuilder &builder, mlir::Location loc, - mlir::Value barrier, mlir::Value src, - mlir::Value dst, mlir::Value nelem, - mlir::Value eleSize) { - mlir::Value size = mlir::arith::MulIOp::create(builder, loc, nelem, eleSize); - auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(builder.getContext()); - barrier = builder.createConvert(loc, llvmPtrTy, barrier); - dst = builder.createConvert(loc, llvmPtrTy, dst); - src = builder.createConvert(loc, llvmPtrTy, src); - mlir::NVVM::InlinePtxOp::create( - builder, loc, mlir::TypeRange{}, {dst, src, size, barrier}, {}, - "cp.async.bulk.shared::cluster.global.mbarrier::complete_tx::bytes [%0], " - "[%1], %2, [%3];", - {}); - mlir::NVVM::InlinePtxOp::create( - builder, loc, mlir::TypeRange{}, {barrier, size}, {}, - "mbarrier.expect_tx.relaxed.cta.shared::cta.b64 [%0], %1;", {}); -} - -// TMA_BULK_LOADC4 -void IntrinsicLibrary::genTMABulkLoadC4( - llvm::ArrayRef<fir::ExtendedValue> args) { - assert(args.size() == 4); - mlir::Value eleSize = - builder.createIntegerConstant(loc, builder.getI32Type(), 8); - genTMABulkLoad(builder, loc, fir::getBase(args[0]), fir::getBase(args[1]), - fir::getBase(args[2]), fir::getBase(args[3]), eleSize); -} - -// TMA_BULK_LOADC8 -void IntrinsicLibrary::genTMABulkLoadC8( - llvm::ArrayRef<fir::ExtendedValue> args) { - assert(args.size() == 4); - mlir::Value eleSize = - builder.createIntegerConstant(loc, builder.getI32Type(), 16); - genTMABulkLoad(builder, loc, fir::getBase(args[0]), fir::getBase(args[1]), - fir::getBase(args[2]), fir::getBase(args[3]), eleSize); -} - -// TMA_BULK_LOADI4 -void IntrinsicLibrary::genTMABulkLoadI4( - llvm::ArrayRef<fir::ExtendedValue> args) { - assert(args.size() == 4); - mlir::Value eleSize = - builder.createIntegerConstant(loc, builder.getI32Type(), 4); - genTMABulkLoad(builder, loc, fir::getBase(args[0]), fir::getBase(args[1]), - fir::getBase(args[2]), fir::getBase(args[3]), eleSize); -} - -// TMA_BULK_LOADI8 -void IntrinsicLibrary::genTMABulkLoadI8( - llvm::ArrayRef<fir::ExtendedValue> args) { - assert(args.size() == 4); - mlir::Value eleSize = - builder.createIntegerConstant(loc, builder.getI32Type(), 8); - genTMABulkLoad(builder, loc, fir::getBase(args[0]), fir::getBase(args[1]), - fir::getBase(args[2]), fir::getBase(args[3]), eleSize); -} - -// TMA_BULK_LOADR2 -void IntrinsicLibrary::genTMABulkLoadR2( - llvm::ArrayRef<fir::ExtendedValue> args) { - assert(args.size() == 4); - mlir::Value eleSize = - builder.createIntegerConstant(loc, builder.getI32Type(), 2); - genTMABulkLoad(builder, loc, fir::getBase(args[0]), fir::getBase(args[1]), - fir::getBase(args[2]), fir::getBase(args[3]), eleSize); -} - -// TMA_BULK_LOADR4 -void IntrinsicLibrary::genTMABulkLoadR4( - llvm::ArrayRef<fir::ExtendedValue> args) { - assert(args.size() == 4); - mlir::Value eleSize = - builder.createIntegerConstant(loc, builder.getI32Type(), 4); - genTMABulkLoad(builder, loc, fir::getBase(args[0]), fir::getBase(args[1]), - fir::getBase(args[2]), fir::getBase(args[3]), eleSize); -} - -// TMA_BULK_LOADR8 -void IntrinsicLibrary::genTMABulkLoadR8( - llvm::ArrayRef<fir::ExtendedValue> args) { - assert(args.size() == 4); - mlir::Value eleSize = - builder.createIntegerConstant(loc, builder.getI32Type(), 8); - genTMABulkLoad(builder, loc, fir::getBase(args[0]), fir::getBase(args[1]), - fir::getBase(args[2]), fir::getBase(args[3]), eleSize); -} - -// TMA_BULK_S2G (CUDA) -void IntrinsicLibrary::genTMABulkS2G(llvm::ArrayRef<fir::ExtendedValue> args) { - assert(args.size() == 3); - mlir::Value src = convertPtrToNVVMSpace(builder, loc, fir::getBase(args[0]), - mlir::NVVM::NVVMMemorySpace::Shared); - mlir::Value dst = convertPtrToNVVMSpace(builder, loc, fir::getBase(args[1]), - mlir::NVVM::NVVMMemorySpace::Global); - mlir::NVVM::CpAsyncBulkSharedCTAToGlobalOp::create( - builder, loc, dst, src, fir::getBase(args[2]), {}, {}); - - mlir::NVVM::InlinePtxOp::create(builder, loc, mlir::TypeRange{}, {}, {}, - "cp.async.bulk.commit_group", {}); - mlir::NVVM::CpAsyncBulkWaitGroupOp::create(builder, loc, - builder.getI32IntegerAttr(0), {}); -} - -static void genTMABulkStore(fir::FirOpBuilder &builder, mlir::Location loc, - mlir::Value src, mlir::Value dst, mlir::Value count, - mlir::Value eleSize) { - mlir::Value size = mlir::arith::MulIOp::create(builder, loc, eleSize, count); - src = convertPtrToNVVMSpace(builder, loc, src, - mlir::NVVM::NVVMMemorySpace::Shared); - dst = convertPtrToNVVMSpace(builder, loc, dst, - mlir::NVVM::NVVMMemorySpace::Global); - mlir::NVVM::CpAsyncBulkSharedCTAToGlobalOp::create(builder, loc, dst, src, - size, {}, {}); - mlir::NVVM::InlinePtxOp::create(builder, loc, mlir::TypeRange{}, {}, {}, - "cp.async.bulk.commit_group", {}); - mlir::NVVM::CpAsyncBulkWaitGroupOp::create(builder, loc, - builder.getI32IntegerAttr(0), {}); -} - -// TMA_BULK_STORE_C4 (CUDA) -void IntrinsicLibrary::genTMABulkStoreC4( - llvm::ArrayRef<fir::ExtendedValue> args) { - assert(args.size() == 3); - mlir::Value eleSize = - builder.createIntegerConstant(loc, builder.getI32Type(), 8); - genTMABulkStore(builder, loc, fir::getBase(args[0]), fir::getBase(args[1]), - fir::getBase(args[2]), eleSize); -} - -// TMA_BULK_STORE_C8 (CUDA) -void IntrinsicLibrary::genTMABulkStoreC8( - llvm::ArrayRef<fir::ExtendedValue> args) { - assert(args.size() == 3); - mlir::Value eleSize = - builder.createIntegerConstant(loc, builder.getI32Type(), 16); - genTMABulkStore(builder, loc, fir::getBase(args[0]), fir::getBase(args[1]), - fir::getBase(args[2]), eleSize); -} - -// TMA_BULK_STORE_I4 (CUDA) -void IntrinsicLibrary::genTMABulkStoreI4( - llvm::ArrayRef<fir::ExtendedValue> args) { - assert(args.size() == 3); - mlir::Value eleSize = - builder.createIntegerConstant(loc, builder.getI32Type(), 4); - genTMABulkStore(builder, loc, fir::getBase(args[0]), fir::getBase(args[1]), - fir::getBase(args[2]), eleSize); -} - -// TMA_BULK_STORE_I8 (CUDA) -void IntrinsicLibrary::genTMABulkStoreI8( - llvm::ArrayRef<fir::ExtendedValue> args) { - assert(args.size() == 3); - mlir::Value eleSize = - builder.createIntegerConstant(loc, builder.getI32Type(), 8); - genTMABulkStore(builder, loc, fir::getBase(args[0]), fir::getBase(args[1]), - fir::getBase(args[2]), eleSize); -} - -// TMA_BULK_STORE_R2 (CUDA) -void IntrinsicLibrary::genTMABulkStoreR2( - llvm::ArrayRef<fir::ExtendedValue> args) { - assert(args.size() == 3); - mlir::Value eleSize = - builder.createIntegerConstant(loc, builder.getI32Type(), 2); - genTMABulkStore(builder, loc, fir::getBase(args[0]), fir::getBase(args[1]), - fir::getBase(args[2]), eleSize); -} - -// TMA_BULK_STORE_R4 (CUDA) -void IntrinsicLibrary::genTMABulkStoreR4( - llvm::ArrayRef<fir::ExtendedValue> args) { - assert(args.size() == 3); - mlir::Value eleSize = - builder.createIntegerConstant(loc, builder.getI32Type(), 4); - genTMABulkStore(builder, loc, fir::getBase(args[0]), fir::getBase(args[1]), - fir::getBase(args[2]), eleSize); -} - -// TMA_BULK_STORE_R8 (CUDA) -void IntrinsicLibrary::genTMABulkStoreR8( - llvm::ArrayRef<fir::ExtendedValue> args) { - assert(args.size() == 3); - mlir::Value eleSize = - builder.createIntegerConstant(loc, builder.getI32Type(), 8); - genTMABulkStore(builder, loc, fir::getBase(args[0]), fir::getBase(args[1]), - fir::getBase(args[2]), eleSize); -} - -// TMA_BULK_WAIT_GROUP (CUDA) -void IntrinsicLibrary::genTMABulkWaitGroup( - llvm::ArrayRef<fir::ExtendedValue> args) { - assert(args.size() == 0); - auto group = builder.getIntegerAttr(builder.getI32Type(), 0); - mlir::NVVM::CpAsyncBulkWaitGroupOp::create(builder, loc, group, {}); -} - // TRIM fir::ExtendedValue IntrinsicLibrary::genTrim(mlir::Type resultType, @@ -9968,6 +8853,9 @@ getIntrinsicArgumentLowering(llvm::StringRef specificName) { if (const IntrinsicHandler *ppcHandler = findPPCIntrinsicHandler(name)) if (!ppcHandler->argLoweringRules.hasDefaultRules()) return &ppcHandler->argLoweringRules; + if (const IntrinsicHandler *cudaHandler = findCUDAIntrinsicHandler(name)) + if (!cudaHandler->argLoweringRules.hasDefaultRules()) + return &cudaHandler->argLoweringRules; return nullptr; } diff --git a/flang/lib/Optimizer/Builder/Runtime/Character.cpp b/flang/lib/Optimizer/Builder/Runtime/Character.cpp index 540ecba..2f1772f 100644 --- a/flang/lib/Optimizer/Builder/Runtime/Character.cpp +++ b/flang/lib/Optimizer/Builder/Runtime/Character.cpp @@ -94,27 +94,34 @@ fir::runtime::genCharCompare(fir::FirOpBuilder &builder, mlir::Location loc, mlir::arith::CmpIPredicate cmp, mlir::Value lhsBuff, mlir::Value lhsLen, mlir::Value rhsBuff, mlir::Value rhsLen) { - mlir::func::FuncOp beginFunc; - switch (discoverKind(lhsBuff.getType())) { + int lhsKind = discoverKind(lhsBuff.getType()); + int rhsKind = discoverKind(rhsBuff.getType()); + if (lhsKind != rhsKind) { + fir::emitFatalError(loc, "runtime does not support comparison of different " + "CHARACTER kind values"); + } + mlir::func::FuncOp func; + switch (lhsKind) { case 1: - beginFunc = fir::runtime::getRuntimeFunc<mkRTKey(CharacterCompareScalar1)>( + func = fir::runtime::getRuntimeFunc<mkRTKey(CharacterCompareScalar1)>( loc, builder); break; case 2: - beginFunc = fir::runtime::getRuntimeFunc<mkRTKey(CharacterCompareScalar2)>( + func = fir::runtime::getRuntimeFunc<mkRTKey(CharacterCompareScalar2)>( loc, builder); break; case 4: - beginFunc = fir::runtime::getRuntimeFunc<mkRTKey(CharacterCompareScalar4)>( + func = fir::runtime::getRuntimeFunc<mkRTKey(CharacterCompareScalar4)>( loc, builder); break; default: - llvm_unreachable("runtime does not support CHARACTER KIND"); + fir::emitFatalError( + loc, "unsupported CHARACTER kind value. Runtime expects 1, 2, or 4."); } - auto fTy = beginFunc.getFunctionType(); + auto fTy = func.getFunctionType(); auto args = fir::runtime::createArguments(builder, loc, fTy, lhsBuff, rhsBuff, lhsLen, rhsLen); - auto tri = fir::CallOp::create(builder, loc, beginFunc, args).getResult(0); + auto tri = fir::CallOp::create(builder, loc, func, args).getResult(0); auto zero = builder.createIntegerConstant(loc, tri.getType(), 0); return mlir::arith::CmpIOp::create(builder, loc, cmp, tri, zero); } diff --git a/flang/lib/Optimizer/Builder/Runtime/Intrinsics.cpp b/flang/lib/Optimizer/Builder/Runtime/Intrinsics.cpp index 110b1b2..a5f16f8 100644 --- a/flang/lib/Optimizer/Builder/Runtime/Intrinsics.cpp +++ b/flang/lib/Optimizer/Builder/Runtime/Intrinsics.cpp @@ -137,6 +137,15 @@ void fir::runtime::genEtime(fir::FirOpBuilder &builder, mlir::Location loc, fir::CallOp::create(builder, loc, runtimeFunc, args); } +void fir::runtime::genFlush(fir::FirOpBuilder &builder, mlir::Location loc, + mlir::Value unit) { + auto runtimeFunc = fir::runtime::getRuntimeFunc<mkRTKey(Flush)>(loc, builder); + llvm::SmallVector<mlir::Value> args = fir::runtime::createArguments( + builder, loc, runtimeFunc.getFunctionType(), unit); + + fir::CallOp::create(builder, loc, runtimeFunc, args); +} + void fir::runtime::genFree(fir::FirOpBuilder &builder, mlir::Location loc, mlir::Value ptr) { auto runtimeFunc = fir::runtime::getRuntimeFunc<mkRTKey(Free)>(loc, builder); @@ -461,3 +470,34 @@ mlir::Value fir::runtime::genChdir(fir::FirOpBuilder &builder, fir::runtime::createArguments(builder, loc, func.getFunctionType(), name); return fir::CallOp::create(builder, loc, func, args).getResult(0); } + +mlir::Value fir::runtime::genIrand(fir::FirOpBuilder &builder, + mlir::Location loc, mlir::Value i) { + auto runtimeFunc = fir::runtime::getRuntimeFunc<mkRTKey(Irand)>(loc, builder); + mlir::FunctionType runtimeFuncTy = runtimeFunc.getFunctionType(); + + llvm::SmallVector<mlir::Value> args = + fir::runtime::createArguments(builder, loc, runtimeFuncTy, i); + return fir::CallOp::create(builder, loc, runtimeFunc, args).getResult(0); +} + +mlir::Value fir::runtime::genRand(fir::FirOpBuilder &builder, + mlir::Location loc, mlir::Value i) { + auto runtimeFunc = fir::runtime::getRuntimeFunc<mkRTKey(Rand)>(loc, builder); + mlir::FunctionType runtimeFuncTy = runtimeFunc.getFunctionType(); + + mlir::Value sourceFile = fir::factory::locationToFilename(builder, loc); + mlir::Value sourceLine = + fir::factory::locationToLineNo(builder, loc, runtimeFuncTy.getInput(2)); + + llvm::SmallVector<mlir::Value> args = fir::runtime::createArguments( + builder, loc, runtimeFuncTy, i, sourceFile, sourceLine); + return fir::CallOp::create(builder, loc, runtimeFunc, args).getResult(0); +} + +void fir::runtime::genShowDescriptor(fir::FirOpBuilder &builder, + mlir::Location loc, mlir::Value descAddr) { + mlir::func::FuncOp func{ + fir::runtime::getRuntimeFunc<mkRTKey(ShowDescriptor)>(loc, builder)}; + fir::CallOp::create(builder, loc, func, descAddr); +} diff --git a/flang/lib/Optimizer/Builder/Runtime/Reduction.cpp b/flang/lib/Optimizer/Builder/Runtime/Reduction.cpp index 157d435..343d848 100644 --- a/flang/lib/Optimizer/Builder/Runtime/Reduction.cpp +++ b/flang/lib/Optimizer/Builder/Runtime/Reduction.cpp @@ -1841,7 +1841,7 @@ mlir::Value fir::runtime::genReduce(fir::FirOpBuilder &builder, assert((fir::isa_real(eleTy) || fir::isa_integer(eleTy) || mlir::isa<fir::LogicalType>(eleTy)) && - "expect real, interger or logical"); + "expect real, integer or logical"); auto [cat, kind] = fir::mlirTypeToCategoryKind(loc, eleTy); mlir::func::FuncOp func; diff --git a/flang/lib/Optimizer/CodeGen/CodeGen.cpp b/flang/lib/Optimizer/CodeGen/CodeGen.cpp index ca4aefb..f96d45d 100644 --- a/flang/lib/Optimizer/CodeGen/CodeGen.cpp +++ b/flang/lib/Optimizer/CodeGen/CodeGen.cpp @@ -692,6 +692,10 @@ struct CallOpConversion : public fir::FIROpConversion<fir::CallOp> { } } + if (std::optional<mlir::ArrayAttr> optionalAccessGroups = + call.getAccessGroups()) + llvmCall.setAccessGroups(*optionalAccessGroups); + if (memAttr) llvmCall.setMemoryEffectsAttr( mlir::cast<mlir::LLVM::MemoryEffectsAttr>(memAttr)); @@ -3402,6 +3406,9 @@ struct LoadOpConversion : public fir::FIROpConversion<fir::LoadOp> { loadOp.setTBAATags(*optionalTag); else attachTBAATag(loadOp, load.getType(), load.getType(), nullptr); + if (std::optional<mlir::ArrayAttr> optionalAccessGroups = + load.getAccessGroups()) + loadOp.setAccessGroups(*optionalAccessGroups); rewriter.replaceOp(load, loadOp.getResult()); } return mlir::success(); @@ -3733,6 +3740,10 @@ struct StoreOpConversion : public fir::FIROpConversion<fir::StoreOp> { if (store.getNontemporal()) storeOp.setNontemporal(true); + if (std::optional<mlir::ArrayAttr> optionalAccessGroups = + store.getAccessGroups()) + storeOp.setAccessGroups(*optionalAccessGroups); + newOp = storeOp; } if (std::optional<mlir::ArrayAttr> optionalTag = store.getTbaa()) diff --git a/flang/lib/Optimizer/CodeGen/LowerRepackArrays.cpp b/flang/lib/Optimizer/CodeGen/LowerRepackArrays.cpp index ac432c7..81488d7 100644 --- a/flang/lib/Optimizer/CodeGen/LowerRepackArrays.cpp +++ b/flang/lib/Optimizer/CodeGen/LowerRepackArrays.cpp @@ -289,7 +289,6 @@ PackArrayConversion::genRepackedBox(fir::FirOpBuilder &builder, fir::factory::genDimInfoFromBox(builder, loc, box, &lbounds, &extents, /*strides=*/nullptr); // Get the type parameters from the box, if needed. - llvm::SmallVector<mlir::Value> assumedTypeParams; if (numTypeParams != 0) { if (auto charType = mlir::dyn_cast<fir::CharacterType>(boxType.unwrapInnerType())) diff --git a/flang/lib/Optimizer/CodeGen/PassDetail.h b/flang/lib/Optimizer/CodeGen/PassDetail.h index f703013..252da02 100644 --- a/flang/lib/Optimizer/CodeGen/PassDetail.h +++ b/flang/lib/Optimizer/CodeGen/PassDetail.h @@ -18,7 +18,7 @@ namespace fir { -#define GEN_PASS_CLASSES +#define GEN_PASS_DECL #include "flang/Optimizer/CodeGen/CGPasses.h.inc" } // namespace fir diff --git a/flang/lib/Optimizer/CodeGen/PreCGRewrite.cpp b/flang/lib/Optimizer/CodeGen/PreCGRewrite.cpp index 1b1d43c..3b137d1 100644 --- a/flang/lib/Optimizer/CodeGen/PreCGRewrite.cpp +++ b/flang/lib/Optimizer/CodeGen/PreCGRewrite.cpp @@ -302,11 +302,16 @@ public: else return mlir::failure(); } + // Extract dummy_arg_no attribute if present + mlir::IntegerAttr dummyArgNoAttr; + if (auto attr = declareOp->getAttrOfType<mlir::IntegerAttr>("dummy_arg_no")) + dummyArgNoAttr = attr; // FIXME: Add FortranAttrs and CudaAttrs auto xDeclOp = fir::cg::XDeclareOp::create( rewriter, loc, declareOp.getType(), declareOp.getMemref(), shapeOpers, shiftOpers, declareOp.getTypeparams(), declareOp.getDummyScope(), - declareOp.getUniqName()); + declareOp.getStorage(), declareOp.getStorageOffset(), + declareOp.getUniqName(), dummyArgNoAttr); LLVM_DEBUG(llvm::dbgs() << "rewriting " << declareOp << " to " << xDeclOp << '\n'); rewriter.replaceOp(declareOp, xDeclOp.getOperation()->getResults()); diff --git a/flang/lib/Optimizer/Dialect/CUF/CUFOps.cpp b/flang/lib/Optimizer/Dialect/CUF/CUFOps.cpp index 687007d..97f7f76a 100644 --- a/flang/lib/Optimizer/Dialect/CUF/CUFOps.cpp +++ b/flang/lib/Optimizer/Dialect/CUF/CUFOps.cpp @@ -333,7 +333,8 @@ void cuf::SharedMemoryOp::build( bindcName.empty() ? mlir::StringAttr{} : builder.getStringAttr(bindcName); build(builder, result, wrapAllocaResultType(inType), mlir::TypeAttr::get(inType), nameAttr, bindcAttr, typeparams, shape, - /*offset=*/mlir::Value{}); + /*offset=*/mlir::Value{}, /*alignment=*/mlir::IntegerAttr{}, + /*isStatic=*/nullptr); result.addAttributes(attributes); } diff --git a/flang/lib/Optimizer/Dialect/FIROps.cpp b/flang/lib/Optimizer/Dialect/FIROps.cpp index 4f97aca..4e797d6 100644 --- a/flang/lib/Optimizer/Dialect/FIROps.cpp +++ b/flang/lib/Optimizer/Dialect/FIROps.cpp @@ -834,6 +834,11 @@ void fir::ArrayCoorOp::getCanonicalizationPatterns( patterns.add<SimplifyArrayCoorOp>(context); } +std::optional<std::int64_t> fir::ArrayCoorOp::getViewOffset(mlir::OpResult) { + // TODO: we can try to compute the constant offset. + return std::nullopt; +} + //===----------------------------------------------------------------------===// // ArrayLoadOp //===----------------------------------------------------------------------===// @@ -1086,6 +1091,13 @@ mlir::OpFoldResult fir::BoxAddrOp::fold(FoldAdaptor adaptor) { return {}; } +std::optional<std::int64_t> fir::BoxAddrOp::getViewOffset(mlir::OpResult) { + // fir.box_addr just returns the base address stored inside a box, + // so the direct accesses through the base address and through the box + // are not offsetted. + return 0; +} + //===----------------------------------------------------------------------===// // BoxCharLenOp //===----------------------------------------------------------------------===// @@ -1820,6 +1832,11 @@ fir::CoordinateIndicesAdaptor fir::CoordinateOp::getIndices() { return CoordinateIndicesAdaptor(getFieldIndicesAttr(), getCoor()); } +std::optional<std::int64_t> fir::CoordinateOp::getViewOffset(mlir::OpResult) { + // TODO: we can try to compute the constant offset. + return std::nullopt; +} + //===----------------------------------------------------------------------===// // DispatchOp //===----------------------------------------------------------------------===// @@ -2066,6 +2083,14 @@ bool fir::isContiguousEmbox(fir::EmboxOp embox, bool checkWhole) { return false; } +std::optional<std::int64_t> fir::EmboxOp::getViewOffset(mlir::OpResult) { + // The address offset is zero, unless there is a slice. + // TODO: we can handle slices that leave the base address untouched. + if (!getSlice()) + return 0; + return std::nullopt; +} + //===----------------------------------------------------------------------===// // EmboxCharOp //===----------------------------------------------------------------------===// @@ -3205,11 +3230,19 @@ mlir::ParseResult fir::DTEntryOp::parse(mlir::OpAsmParser &parser, parser.parseAttribute(calleeAttr, fir::DTEntryOp::getProcAttrNameStr(), result.attributes)) return mlir::failure(); + + // Optional "deferred" keyword. + if (succeeded(parser.parseOptionalKeyword("deferred"))) { + result.addAttribute(fir::DTEntryOp::getDeferredAttrNameStr(), + parser.getBuilder().getUnitAttr()); + } return mlir::success(); } void fir::DTEntryOp::print(mlir::OpAsmPrinter &p) { p << ' ' << getMethodAttr() << ", " << getProcAttr(); + if ((*this)->getAttr(fir::DTEntryOp::getDeferredAttrNameStr())) + p << " deferred"; } //===----------------------------------------------------------------------===// @@ -3313,6 +3346,14 @@ llvm::LogicalResult fir::ReboxOp::verify() { return mlir::success(); } +std::optional<std::int64_t> fir::ReboxOp::getViewOffset(mlir::OpResult) { + // The address offset is zero, unless there is a slice. + // TODO: we can handle slices that leave the base address untouched. + if (!getSlice()) + return 0; + return std::nullopt; +} + //===----------------------------------------------------------------------===// // ReboxAssumedRankOp //===----------------------------------------------------------------------===// @@ -4252,7 +4293,7 @@ llvm::LogicalResult fir::StoreOp::verify() { void fir::StoreOp::build(mlir::OpBuilder &builder, mlir::OperationState &result, mlir::Value value, mlir::Value memref) { - build(builder, result, value, memref, {}); + build(builder, result, value, memref, {}, {}, {}); } void fir::StoreOp::getEffects( diff --git a/flang/lib/Optimizer/Dialect/MIF/MIFOps.cpp b/flang/lib/Optimizer/Dialect/MIF/MIFOps.cpp index c6cc2e8..5f68f3d 100644 --- a/flang/lib/Optimizer/Dialect/MIF/MIFOps.cpp +++ b/flang/lib/Optimizer/Dialect/MIF/MIFOps.cpp @@ -15,9 +15,6 @@ #include "mlir/IR/PatternMatch.h" #include "llvm/ADT/SmallVector.h" -#define GET_OP_CLASSES -#include "flang/Optimizer/Dialect/MIF/MIFOps.cpp.inc" - //===----------------------------------------------------------------------===// // NumImagesOp //===----------------------------------------------------------------------===// @@ -151,3 +148,60 @@ llvm::LogicalResult mif::CoSumOp::verify() { return emitOpError("`A` shall be of numeric type."); return mlir::success(); } + +//===----------------------------------------------------------------------===// +// ChangeTeamOp +//===----------------------------------------------------------------------===// + +void mif::ChangeTeamOp::build(mlir::OpBuilder &builder, + mlir::OperationState &result, mlir::Value team, + bool ensureTerminator, + llvm::ArrayRef<mlir::NamedAttribute> attributes) { + build(builder, result, team, /*stat*/ mlir::Value{}, /*errmsg*/ mlir::Value{}, + ensureTerminator, attributes); +} + +void mif::ChangeTeamOp::build(mlir::OpBuilder &builder, + mlir::OperationState &result, mlir::Value team, + mlir::Value stat, mlir::Value errmsg, + bool ensureTerminator, + llvm::ArrayRef<mlir::NamedAttribute> attributes) { + std::int32_t argStat = 0, argErrmsg = 0; + result.addOperands(team); + if (stat) { + result.addOperands(stat); + argStat++; + } + if (errmsg) { + result.addOperands(errmsg); + argErrmsg++; + } + + mlir::Region *bodyRegion = result.addRegion(); + bodyRegion->push_back(new mlir::Block{}); + if (ensureTerminator) + ChangeTeamOp::ensureTerminator(*bodyRegion, builder, result.location); + + result.addAttribute(getOperandSegmentSizeAttr(), + builder.getDenseI32ArrayAttr({1, argStat, argErrmsg})); + result.addAttributes(attributes); +} + +static mlir::ParseResult parseChangeTeamOpBody(mlir::OpAsmParser &parser, + mlir::Region &body) { + if (parser.parseRegion(body)) + return mlir::failure(); + + auto &builder = parser.getBuilder(); + mif::ChangeTeamOp::ensureTerminator(body, builder, builder.getUnknownLoc()); + return mlir::success(); +} + +static void printChangeTeamOpBody(mlir::OpAsmPrinter &p, mif::ChangeTeamOp op, + mlir::Region &body) { + p.printRegion(op.getRegion(), /*printEntryBlockArgs=*/true, + /*printBlockTerminators=*/true); +} + +#define GET_OP_CLASSES +#include "flang/Optimizer/Dialect/MIF/MIFOps.cpp.inc" diff --git a/flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp b/flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp index 1332dc5..e42c064 100644 --- a/flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp +++ b/flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp @@ -261,14 +261,12 @@ updateDeclaredInputTypeWithVolatility(mlir::Type inputType, mlir::Value memref, return std::make_pair(inputType, memref); } -void hlfir::DeclareOp::build(mlir::OpBuilder &builder, - mlir::OperationState &result, mlir::Value memref, - llvm::StringRef uniq_name, mlir::Value shape, - mlir::ValueRange typeparams, - mlir::Value dummy_scope, mlir::Value storage, - std::uint64_t storage_offset, - fir::FortranVariableFlagsAttr fortran_attrs, - cuf::DataAttributeAttr data_attr) { +void hlfir::DeclareOp::build( + mlir::OpBuilder &builder, mlir::OperationState &result, mlir::Value memref, + llvm::StringRef uniq_name, mlir::Value shape, mlir::ValueRange typeparams, + mlir::Value dummy_scope, mlir::Value storage, std::uint64_t storage_offset, + fir::FortranVariableFlagsAttr fortran_attrs, + cuf::DataAttributeAttr data_attr, unsigned dummy_arg_no) { auto nameAttr = builder.getStringAttr(uniq_name); mlir::Type inputType = memref.getType(); bool hasExplicitLbs = hasExplicitLowerBounds(shape); @@ -279,9 +277,12 @@ void hlfir::DeclareOp::build(mlir::OpBuilder &builder, } auto [hlfirVariableType, firVarType] = getDeclareOutputTypes(inputType, hasExplicitLbs); + mlir::IntegerAttr argNoAttr; + if (dummy_arg_no > 0) + argNoAttr = builder.getUI32IntegerAttr(dummy_arg_no); build(builder, result, {hlfirVariableType, firVarType}, memref, shape, typeparams, dummy_scope, storage, storage_offset, nameAttr, - fortran_attrs, data_attr, /*skip_rebox=*/mlir::UnitAttr{}); + fortran_attrs, data_attr, /*skip_rebox=*/mlir::UnitAttr{}, argNoAttr); } llvm::LogicalResult hlfir::DeclareOp::verify() { @@ -591,6 +592,12 @@ llvm::LogicalResult hlfir::DesignateOp::verify() { return mlir::success(); } +std::optional<std::int64_t> hlfir::DesignateOp::getViewOffset(mlir::OpResult) { + // TODO: we can compute the constant offset + // based on the component/indices/etc. + return std::nullopt; +} + //===----------------------------------------------------------------------===// // ParentComponentOp //===----------------------------------------------------------------------===// diff --git a/flang/lib/Optimizer/HLFIR/Transforms/ConvertToFIR.cpp b/flang/lib/Optimizer/HLFIR/Transforms/ConvertToFIR.cpp index 6a57bf2..8bdf13e 100644 --- a/flang/lib/Optimizer/HLFIR/Transforms/ConvertToFIR.cpp +++ b/flang/lib/Optimizer/HLFIR/Transforms/ConvertToFIR.cpp @@ -149,13 +149,18 @@ public: !assignOp.isTemporaryLHS() && mlir::isa<fir::RecordType>(fir::getElementTypeOf(lhsExv)); + mlir::ArrayAttr accessGroups; + if (auto attrs = assignOp.getOperation()->getAttrOfType<mlir::ArrayAttr>( + "access_groups")) + accessGroups = attrs; + // genScalarAssignment() must take care of potential overlap // between LHS and RHS. Note that the overlap is possible // also for components of LHS/RHS, and the Assign() runtime // must take care of it. - fir::factory::genScalarAssignment(builder, loc, lhsExv, rhsExv, - needFinalization, - assignOp.isTemporaryLHS()); + fir::factory::genScalarAssignment( + builder, loc, lhsExv, rhsExv, needFinalization, + assignOp.isTemporaryLHS(), accessGroups); } rewriter.eraseOp(assignOp); return mlir::success(); @@ -308,7 +313,8 @@ public: declareOp.getTypeparams(), declareOp.getDummyScope(), /*storage=*/declareOp.getStorage(), /*storage_offset=*/declareOp.getStorageOffset(), - declareOp.getUniqName(), fortranAttrs, dataAttr); + declareOp.getUniqName(), fortranAttrs, dataAttr, + declareOp.getDummyArgNoAttr()); // Propagate other attributes from hlfir.declare to fir.declare. // OpenACC's acc.declare is one example. Right now, the propagation diff --git a/flang/lib/Optimizer/HLFIR/Transforms/InlineHLFIRAssign.cpp b/flang/lib/Optimizer/HLFIR/Transforms/InlineHLFIRAssign.cpp index 86d3974..1fc592c 100644 --- a/flang/lib/Optimizer/HLFIR/Transforms/InlineHLFIRAssign.cpp +++ b/flang/lib/Optimizer/HLFIR/Transforms/InlineHLFIRAssign.cpp @@ -107,26 +107,8 @@ public: mlir::Location loc = assign->getLoc(); fir::FirOpBuilder builder(rewriter, assign.getOperation()); builder.setInsertionPoint(assign); - rhs = hlfir::derefPointersAndAllocatables(loc, builder, rhs); - lhs = hlfir::derefPointersAndAllocatables(loc, builder, lhs); - mlir::Value lhsShape = hlfir::genShape(loc, builder, lhs); - llvm::SmallVector<mlir::Value> lhsExtents = - hlfir::getIndexExtents(loc, builder, lhsShape); - mlir::Value rhsShape = hlfir::genShape(loc, builder, rhs); - llvm::SmallVector<mlir::Value> rhsExtents = - hlfir::getIndexExtents(loc, builder, rhsShape); - llvm::SmallVector<mlir::Value> extents = - fir::factory::deduceOptimalExtents(lhsExtents, rhsExtents); - hlfir::LoopNest loopNest = - hlfir::genLoopNest(loc, builder, extents, /*isUnordered=*/true, - flangomp::shouldUseWorkshareLowering(assign)); - builder.setInsertionPointToStart(loopNest.body); - auto rhsArrayElement = - hlfir::getElementAt(loc, builder, rhs, loopNest.oneBasedIndices); - rhsArrayElement = hlfir::loadTrivialScalar(loc, builder, rhsArrayElement); - auto lhsArrayElement = - hlfir::getElementAt(loc, builder, lhs, loopNest.oneBasedIndices); - hlfir::AssignOp::create(builder, loc, rhsArrayElement, lhsArrayElement); + hlfir::genNoAliasArrayAssignment( + loc, builder, rhs, lhs, flangomp::shouldUseWorkshareLowering(assign)); rewriter.eraseOp(assign); return mlir::success(); } diff --git a/flang/lib/Optimizer/HLFIR/Transforms/SimplifyHLFIRIntrinsics.cpp b/flang/lib/Optimizer/HLFIR/Transforms/SimplifyHLFIRIntrinsics.cpp index ce8ebaa..4fa8103 100644 --- a/flang/lib/Optimizer/HLFIR/Transforms/SimplifyHLFIRIntrinsics.cpp +++ b/flang/lib/Optimizer/HLFIR/Transforms/SimplifyHLFIRIntrinsics.cpp @@ -931,6 +931,37 @@ private: mlir::Value genScalarAdd(mlir::Value value1, mlir::Value value2); }; +/// Reduction converter for Product. +class ProductAsElementalConverter + : public NumericReductionAsElementalConverterBase<hlfir::ProductOp> { + using Base = NumericReductionAsElementalConverterBase; + +public: + ProductAsElementalConverter(hlfir::ProductOp op, + mlir::PatternRewriter &rewriter) + : Base{op, rewriter} {} + +private: + virtual llvm::SmallVector<mlir::Value> genReductionInitValues( + [[maybe_unused]] mlir::ValueRange oneBasedIndices, + [[maybe_unused]] const llvm::SmallVectorImpl<mlir::Value> &extents) + final { + return {fir::factory::createOneValue(builder, loc, getResultElementType())}; + } + virtual llvm::SmallVector<mlir::Value> + reduceOneElement(const llvm::SmallVectorImpl<mlir::Value> ¤tValue, + hlfir::Entity array, + mlir::ValueRange oneBasedIndices) final { + checkReductions(currentValue); + hlfir::Entity elementValue = + hlfir::loadElementAt(loc, builder, array, oneBasedIndices); + return {genScalarMult(currentValue[0], elementValue)}; + } + + // Generate scalar multiplication of the two values (of the same data type). + mlir::Value genScalarMult(mlir::Value value1, mlir::Value value2); +}; + /// Base class for logical reductions like ALL, ANY, COUNT. /// They do not have MASK and FastMathFlags. template <typename OpT> @@ -1194,6 +1225,20 @@ mlir::Value SumAsElementalConverter::genScalarAdd(mlir::Value value1, llvm_unreachable("unsupported SUM reduction type"); } +mlir::Value ProductAsElementalConverter::genScalarMult(mlir::Value value1, + mlir::Value value2) { + mlir::Type ty = value1.getType(); + assert(ty == value2.getType() && "reduction values' types do not match"); + if (mlir::isa<mlir::FloatType>(ty)) + return mlir::arith::MulFOp::create(builder, loc, value1, value2); + else if (mlir::isa<mlir::ComplexType>(ty)) + return fir::MulcOp::create(builder, loc, value1, value2); + else if (mlir::isa<mlir::IntegerType>(ty)) + return mlir::arith::MulIOp::create(builder, loc, value1, value2); + + llvm_unreachable("unsupported MUL reduction type"); +} + mlir::Value ReductionAsElementalConverter::genMaskValue( mlir::Value mask, mlir::Value isPresentPred, mlir::ValueRange indices) { mlir::OpBuilder::InsertionGuard guard(builder); @@ -1265,6 +1310,9 @@ public: } else if constexpr (std::is_same_v<Op, hlfir::SumOp>) { SumAsElementalConverter converter{op, rewriter}; return converter.convert(); + } else if constexpr (std::is_same_v<Op, hlfir::ProductOp>) { + ProductAsElementalConverter converter{op, rewriter}; + return converter.convert(); } return rewriter.notifyMatchFailure(op, "unexpected reduction operation"); } @@ -3158,6 +3206,7 @@ public: mlir::RewritePatternSet patterns(context); patterns.insert<TransposeAsElementalConversion>(context); patterns.insert<ReductionConversion<hlfir::SumOp>>(context); + patterns.insert<ReductionConversion<hlfir::ProductOp>>(context); patterns.insert<ArrayShiftConversion<hlfir::CShiftOp>>(context); patterns.insert<ArrayShiftConversion<hlfir::EOShiftOp>>(context); patterns.insert<CmpCharOpConversion>(context); diff --git a/flang/lib/Optimizer/OpenACC/Analysis/CMakeLists.txt b/flang/lib/Optimizer/OpenACC/Analysis/CMakeLists.txt new file mode 100644 index 0000000..e05d145 --- /dev/null +++ b/flang/lib/Optimizer/OpenACC/Analysis/CMakeLists.txt @@ -0,0 +1,22 @@ +add_flang_library(FIROpenACCAnalysis + FIROpenACCSupportAnalysis.cpp + + DEPENDS + FIRAnalysis + FIRDialect + FIROpenACCSupport + HLFIRDialect + + LINK_LIBS + FIRAnalysis + FIRDialect + FIROpenACCSupport + HLFIRDialect + + MLIR_DEPS + MLIROpenACCDialect + + MLIR_LIBS + MLIROpenACCDialect +) + diff --git a/flang/lib/Optimizer/OpenACC/Analysis/FIROpenACCSupportAnalysis.cpp b/flang/lib/Optimizer/OpenACC/Analysis/FIROpenACCSupportAnalysis.cpp new file mode 100644 index 0000000..8cdbe1d --- /dev/null +++ b/flang/lib/Optimizer/OpenACC/Analysis/FIROpenACCSupportAnalysis.cpp @@ -0,0 +1,40 @@ +//===- FIROpenACCSupportAnalysis.cpp - FIR OpenACCSupport Analysis -------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file implements the FIR-specific OpenACCSupport analysis. +// +//===----------------------------------------------------------------------===// + +#include "flang/Optimizer/OpenACC/Analysis/FIROpenACCSupportAnalysis.h" +#include "flang/Optimizer/Builder/Todo.h" +#include "flang/Optimizer/OpenACC/Support/FIROpenACCUtils.h" + +using namespace mlir; + +namespace fir { +namespace acc { + +std::string FIROpenACCSupportAnalysis::getVariableName(Value v) { + return fir::acc::getVariableName(v, /*preferDemangledName=*/true); +} + +std::string FIROpenACCSupportAnalysis::getRecipeName(mlir::acc::RecipeKind kind, + Type type, Value var) { + return fir::acc::getRecipeName(kind, type, var); +} + +mlir::InFlightDiagnostic +FIROpenACCSupportAnalysis::emitNYI(Location loc, const Twine &message) { + TODO(loc, message); + // Should be unreachable, but we return an actual diagnostic + // to satisfy the interface. + return mlir::emitError(loc, "not yet implemented: " + message.str()); +} + +} // namespace acc +} // namespace fir diff --git a/flang/lib/Optimizer/OpenACC/CMakeLists.txt b/flang/lib/Optimizer/OpenACC/CMakeLists.txt index 790b9fd..16a4025 100644 --- a/flang/lib/Optimizer/OpenACC/CMakeLists.txt +++ b/flang/lib/Optimizer/OpenACC/CMakeLists.txt @@ -1,2 +1,3 @@ +add_subdirectory(Analysis) add_subdirectory(Support) add_subdirectory(Transforms) diff --git a/flang/lib/Optimizer/OpenACC/Support/CMakeLists.txt b/flang/lib/Optimizer/OpenACC/Support/CMakeLists.txt index 898fb00..9c6f0ee 100644 --- a/flang/lib/Optimizer/OpenACC/Support/CMakeLists.txt +++ b/flang/lib/Optimizer/OpenACC/Support/CMakeLists.txt @@ -4,6 +4,7 @@ add_flang_library(FIROpenACCSupport FIROpenACCAttributes.cpp FIROpenACCOpsInterfaces.cpp FIROpenACCTypeInterfaces.cpp + FIROpenACCUtils.cpp RegisterOpenACCExtensions.cpp DEPENDS diff --git a/flang/lib/Optimizer/OpenACC/Support/FIROpenACCOpsInterfaces.cpp b/flang/lib/Optimizer/OpenACC/Support/FIROpenACCOpsInterfaces.cpp index c1734be..e4d02e9 100644 --- a/flang/lib/Optimizer/OpenACC/Support/FIROpenACCOpsInterfaces.cpp +++ b/flang/lib/Optimizer/OpenACC/Support/FIROpenACCOpsInterfaces.cpp @@ -14,6 +14,9 @@ #include "flang/Optimizer/Dialect/FIROps.h" #include "flang/Optimizer/HLFIR/HLFIROps.h" +#include "flang/Optimizer/Support/InternalNames.h" +#include "mlir/IR/SymbolTable.h" +#include "llvm/ADT/SmallSet.h" namespace fir::acc { @@ -59,4 +62,111 @@ bool PartialEntityAccessModel<hlfir::DeclareOp>::isCompleteView( return !getBaseEntity(op); } +mlir::SymbolRefAttr AddressOfGlobalModel::getSymbol(mlir::Operation *op) const { + return mlir::cast<fir::AddrOfOp>(op).getSymbolAttr(); +} + +bool GlobalVariableModel::isConstant(mlir::Operation *op) const { + auto globalOp = mlir::cast<fir::GlobalOp>(op); + return globalOp.getConstant().has_value(); +} + +mlir::Region *GlobalVariableModel::getInitRegion(mlir::Operation *op) const { + auto globalOp = mlir::cast<fir::GlobalOp>(op); + return globalOp.hasInitializationBody() ? &globalOp.getRegion() : nullptr; +} + +// Helper to recursively process address-of operations in derived type +// descriptors and collect all needed fir.globals. +static void processAddrOfOpInDerivedTypeDescriptor( + fir::AddrOfOp addrOfOp, mlir::SymbolTable &symTab, + llvm::SmallSet<mlir::Operation *, 16> &globalsSet, + llvm::SmallVectorImpl<mlir::SymbolRefAttr> &symbols) { + if (auto globalOp = symTab.lookup<fir::GlobalOp>( + addrOfOp.getSymbol().getLeafReference().getValue())) { + if (globalsSet.contains(globalOp)) + return; + globalsSet.insert(globalOp); + symbols.push_back(addrOfOp.getSymbolAttr()); + globalOp.walk([&](fir::AddrOfOp op) { + processAddrOfOpInDerivedTypeDescriptor(op, symTab, globalsSet, symbols); + }); + } +} + +// Utility to collect referenced symbols for type descriptors of derived types. +// This is the common logic for operations that may require type descriptor +// globals. +static void collectReferencedSymbolsForType( + mlir::Type ty, mlir::Operation *op, + llvm::SmallVectorImpl<mlir::SymbolRefAttr> &symbols, + mlir::SymbolTable *symbolTable) { + ty = fir::getDerivedType(fir::unwrapRefType(ty)); + + // Look for type descriptor globals only if it's a derived (record) type + if (auto recTy = mlir::dyn_cast_if_present<fir::RecordType>(ty)) { + // If no symbol table provided, simply add the type descriptor name + if (!symbolTable) { + symbols.push_back(mlir::SymbolRefAttr::get( + op->getContext(), + fir::NameUniquer::getTypeDescriptorName(recTy.getName()))); + return; + } + + // Otherwise, do full lookup and recursive processing + llvm::SmallSet<mlir::Operation *, 16> globalsSet; + + fir::GlobalOp globalOp = symbolTable->lookup<fir::GlobalOp>( + fir::NameUniquer::getTypeDescriptorName(recTy.getName())); + if (!globalOp) + globalOp = symbolTable->lookup<fir::GlobalOp>( + fir::NameUniquer::getTypeDescriptorAssemblyName(recTy.getName())); + + if (globalOp) { + globalsSet.insert(globalOp); + symbols.push_back( + mlir::SymbolRefAttr::get(op->getContext(), globalOp.getSymName())); + globalOp.walk([&](fir::AddrOfOp addrOp) { + processAddrOfOpInDerivedTypeDescriptor(addrOp, *symbolTable, globalsSet, + symbols); + }); + } + } +} + +template <> +void IndirectGlobalAccessModel<fir::AllocaOp>::getReferencedSymbols( + mlir::Operation *op, llvm::SmallVectorImpl<mlir::SymbolRefAttr> &symbols, + mlir::SymbolTable *symbolTable) const { + auto allocaOp = mlir::cast<fir::AllocaOp>(op); + collectReferencedSymbolsForType(allocaOp.getType(), op, symbols, symbolTable); +} + +template <> +void IndirectGlobalAccessModel<fir::EmboxOp>::getReferencedSymbols( + mlir::Operation *op, llvm::SmallVectorImpl<mlir::SymbolRefAttr> &symbols, + mlir::SymbolTable *symbolTable) const { + auto emboxOp = mlir::cast<fir::EmboxOp>(op); + collectReferencedSymbolsForType(emboxOp.getMemref().getType(), op, symbols, + symbolTable); +} + +template <> +void IndirectGlobalAccessModel<fir::ReboxOp>::getReferencedSymbols( + mlir::Operation *op, llvm::SmallVectorImpl<mlir::SymbolRefAttr> &symbols, + mlir::SymbolTable *symbolTable) const { + auto reboxOp = mlir::cast<fir::ReboxOp>(op); + collectReferencedSymbolsForType(reboxOp.getBox().getType(), op, symbols, + symbolTable); +} + +template <> +void IndirectGlobalAccessModel<fir::TypeDescOp>::getReferencedSymbols( + mlir::Operation *op, llvm::SmallVectorImpl<mlir::SymbolRefAttr> &symbols, + mlir::SymbolTable *symbolTable) const { + auto typeDescOp = mlir::cast<fir::TypeDescOp>(op); + collectReferencedSymbolsForType(typeDescOp.getInType(), op, symbols, + symbolTable); +} + } // namespace fir::acc diff --git a/flang/lib/Optimizer/OpenACC/Support/FIROpenACCTypeInterfaces.cpp b/flang/lib/Optimizer/OpenACC/Support/FIROpenACCTypeInterfaces.cpp index ae0f5fb8..9fcc7d3 100644 --- a/flang/lib/Optimizer/OpenACC/Support/FIROpenACCTypeInterfaces.cpp +++ b/flang/lib/Optimizer/OpenACC/Support/FIROpenACCTypeInterfaces.cpp @@ -1014,4 +1014,114 @@ template bool OpenACCPointerLikeModel<fir::LLVMPointerType>::genCopy( mlir::TypedValue<mlir::acc::PointerLikeType> source, mlir::Type varType) const; +template <typename Ty> +mlir::Value OpenACCPointerLikeModel<Ty>::genLoad( + mlir::Type pointer, mlir::OpBuilder &builder, mlir::Location loc, + mlir::TypedValue<mlir::acc::PointerLikeType> srcPtr, + mlir::Type valueType) const { + + // Unwrap to get the pointee type. + mlir::Type pointeeTy = fir::dyn_cast_ptrEleTy(pointer); + assert(pointeeTy && "expected pointee type to be extractable"); + + // Box types contain both a descriptor and referenced data. The genLoad API + // handles simple loads and cannot properly manage both parts. + if (fir::isa_box_type(pointeeTy)) + return {}; + + // Unlimited polymorphic (class(*)) cannot be handled because type is unknown. + if (fir::isUnlimitedPolymorphicType(pointeeTy)) + return {}; + + // Return empty for dynamic size types because the load logic + // cannot be determined simply from the type. + if (fir::hasDynamicSize(pointeeTy)) + return {}; + + mlir::Value loadedValue = fir::LoadOp::create(builder, loc, srcPtr); + + // If valueType is provided and differs from the loaded type, insert a convert + if (valueType && loadedValue.getType() != valueType) + return fir::ConvertOp::create(builder, loc, valueType, loadedValue); + + return loadedValue; +} + +template mlir::Value OpenACCPointerLikeModel<fir::ReferenceType>::genLoad( + mlir::Type pointer, mlir::OpBuilder &builder, mlir::Location loc, + mlir::TypedValue<mlir::acc::PointerLikeType> srcPtr, + mlir::Type valueType) const; + +template mlir::Value OpenACCPointerLikeModel<fir::PointerType>::genLoad( + mlir::Type pointer, mlir::OpBuilder &builder, mlir::Location loc, + mlir::TypedValue<mlir::acc::PointerLikeType> srcPtr, + mlir::Type valueType) const; + +template mlir::Value OpenACCPointerLikeModel<fir::HeapType>::genLoad( + mlir::Type pointer, mlir::OpBuilder &builder, mlir::Location loc, + mlir::TypedValue<mlir::acc::PointerLikeType> srcPtr, + mlir::Type valueType) const; + +template mlir::Value OpenACCPointerLikeModel<fir::LLVMPointerType>::genLoad( + mlir::Type pointer, mlir::OpBuilder &builder, mlir::Location loc, + mlir::TypedValue<mlir::acc::PointerLikeType> srcPtr, + mlir::Type valueType) const; + +template <typename Ty> +bool OpenACCPointerLikeModel<Ty>::genStore( + mlir::Type pointer, mlir::OpBuilder &builder, mlir::Location loc, + mlir::Value valueToStore, + mlir::TypedValue<mlir::acc::PointerLikeType> destPtr) const { + + // Unwrap to get the pointee type. + mlir::Type pointeeTy = fir::dyn_cast_ptrEleTy(pointer); + assert(pointeeTy && "expected pointee type to be extractable"); + + // Box types contain both a descriptor and referenced data. The genStore API + // handles simple stores and cannot properly manage both parts. + if (fir::isa_box_type(pointeeTy)) + return false; + + // Unlimited polymorphic (class(*)) cannot be handled because type is unknown. + if (fir::isUnlimitedPolymorphicType(pointeeTy)) + return false; + + // Return false for dynamic size types because the store logic + // cannot be determined simply from the type. + if (fir::hasDynamicSize(pointeeTy)) + return false; + + // Get the type from the value being stored + mlir::Type valueType = valueToStore.getType(); + mlir::Value convertedValue = valueToStore; + + // If the value type differs from the pointee type, insert a convert + if (valueType != pointeeTy) + convertedValue = + fir::ConvertOp::create(builder, loc, pointeeTy, valueToStore); + + fir::StoreOp::create(builder, loc, convertedValue, destPtr); + return true; +} + +template bool OpenACCPointerLikeModel<fir::ReferenceType>::genStore( + mlir::Type pointer, mlir::OpBuilder &builder, mlir::Location loc, + mlir::Value valueToStore, + mlir::TypedValue<mlir::acc::PointerLikeType> destPtr) const; + +template bool OpenACCPointerLikeModel<fir::PointerType>::genStore( + mlir::Type pointer, mlir::OpBuilder &builder, mlir::Location loc, + mlir::Value valueToStore, + mlir::TypedValue<mlir::acc::PointerLikeType> destPtr) const; + +template bool OpenACCPointerLikeModel<fir::HeapType>::genStore( + mlir::Type pointer, mlir::OpBuilder &builder, mlir::Location loc, + mlir::Value valueToStore, + mlir::TypedValue<mlir::acc::PointerLikeType> destPtr) const; + +template bool OpenACCPointerLikeModel<fir::LLVMPointerType>::genStore( + mlir::Type pointer, mlir::OpBuilder &builder, mlir::Location loc, + mlir::Value valueToStore, + mlir::TypedValue<mlir::acc::PointerLikeType> destPtr) const; + } // namespace fir::acc diff --git a/flang/lib/Optimizer/OpenACC/Support/FIROpenACCUtils.cpp b/flang/lib/Optimizer/OpenACC/Support/FIROpenACCUtils.cpp new file mode 100644 index 0000000..e5b8123 --- /dev/null +++ b/flang/lib/Optimizer/OpenACC/Support/FIROpenACCUtils.cpp @@ -0,0 +1,269 @@ +//===- FIROpenACCUtils.cpp - FIR OpenACC Utilities ------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file implements utility functions for FIR OpenACC support. +// +//===----------------------------------------------------------------------===// + +#include "flang/Optimizer/OpenACC/Support/FIROpenACCUtils.h" +#include "flang/Optimizer/Dialect/FIROps.h" +#include "flang/Optimizer/Dialect/FIROpsSupport.h" +#include "flang/Optimizer/Dialect/FIRType.h" +#include "flang/Optimizer/Dialect/Support/FIRContext.h" +#include "flang/Optimizer/Dialect/Support/KindMapping.h" +#include "flang/Optimizer/HLFIR/HLFIROps.h" +#include "flang/Optimizer/Support/InternalNames.h" +#include "mlir/Dialect/OpenACC/OpenACC.h" +#include "mlir/IR/Matchers.h" +#include "mlir/Interfaces/ViewLikeInterface.h" +#include "llvm/ADT/TypeSwitch.h" +#include "llvm/Support/raw_ostream.h" + +using namespace mlir; + +namespace fir { +namespace acc { + +std::string getVariableName(Value v, bool preferDemangledName) { + std::string srcName; + std::string prefix; + llvm::SmallVector<std::string, 4> arrayIndices; + bool iterate = true; + mlir::Operation *defOp; + + // For integer constants, no need to further iterate - print their value + // immediately. + if (v.getDefiningOp()) { + IntegerAttr::ValueType val; + if (matchPattern(v.getDefiningOp(), m_ConstantInt(&val))) { + llvm::raw_string_ostream os(prefix); + val.print(os, /*isSigned=*/true); + return prefix; + } + } + + while (v && (defOp = v.getDefiningOp()) && iterate) { + iterate = + llvm::TypeSwitch<mlir::Operation *, bool>(defOp) + .Case<mlir::ViewLikeOpInterface>( + [&v](mlir::ViewLikeOpInterface op) { + v = op.getViewSource(); + return true; + }) + .Case<fir::ReboxOp>([&v](fir::ReboxOp op) { + v = op.getBox(); + return true; + }) + .Case<fir::EmboxOp>([&v](fir::EmboxOp op) { + v = op.getMemref(); + return true; + }) + .Case<fir::ConvertOp>([&v](fir::ConvertOp op) { + v = op.getValue(); + return true; + }) + .Case<fir::LoadOp>([&v](fir::LoadOp op) { + v = op.getMemref(); + return true; + }) + .Case<fir::BoxAddrOp>([&v](fir::BoxAddrOp op) { + // The box holds the name of the variable. + v = op.getVal(); + return true; + }) + .Case<fir::AddrOfOp>([&](fir::AddrOfOp op) { + // Only use address_of symbol if mangled name is preferred + if (!preferDemangledName) { + auto symRef = op.getSymbol(); + srcName = symRef.getLeafReference().getValue().str(); + } + return false; + }) + .Case<fir::ArrayCoorOp>([&](fir::ArrayCoorOp op) { + v = op.getMemref(); + for (auto coor : op.getIndices()) { + auto idxName = getVariableName(coor, preferDemangledName); + arrayIndices.push_back(idxName.empty() ? "?" : idxName); + } + return true; + }) + .Case<fir::CoordinateOp>([&](fir::CoordinateOp op) { + std::optional<llvm::ArrayRef<int32_t>> fieldIndices = + op.getFieldIndices(); + if (fieldIndices && fieldIndices->size() > 0 && + (*fieldIndices)[0] != fir::CoordinateOp::kDynamicIndex) { + int fieldId = (*fieldIndices)[0]; + mlir::Type baseType = + fir::getFortranElementType(op.getRef().getType()); + if (auto recType = llvm::dyn_cast<fir::RecordType>(baseType)) { + srcName = recType.getTypeList()[fieldId].first; + } + } + if (!srcName.empty()) { + // If the field name is known - attempt to continue building + // name by looking at its parents. + prefix = + getVariableName(op.getRef(), preferDemangledName) + "%"; + } + return false; + }) + .Case<hlfir::DesignateOp>([&](hlfir::DesignateOp op) { + if (op.getComponent()) { + srcName = op.getComponent().value().str(); + prefix = + getVariableName(op.getMemref(), preferDemangledName) + "%"; + return false; + } + for (auto coor : op.getIndices()) { + auto idxName = getVariableName(coor, preferDemangledName); + arrayIndices.push_back(idxName.empty() ? "?" : idxName); + } + v = op.getMemref(); + return true; + }) + .Case<fir::DeclareOp, hlfir::DeclareOp>([&](auto op) { + srcName = op.getUniqName().str(); + return false; + }) + .Case<fir::AllocaOp>([&](fir::AllocaOp op) { + if (preferDemangledName) { + // Prefer demangled name (bindc_name over uniq_name) + srcName = op.getBindcName() ? *op.getBindcName() + : op.getUniqName() ? *op.getUniqName() + : ""; + } else { + // Prefer mangled name (uniq_name over bindc_name) + srcName = op.getUniqName() ? *op.getUniqName() + : op.getBindcName() ? *op.getBindcName() + : ""; + } + return false; + }) + .Default([](mlir::Operation *) { return false; }); + } + + // Fallback to the default implementation. + if (srcName.empty()) + return acc::getVariableName(v); + + // Build array index suffix if present + std::string suffix; + if (!arrayIndices.empty()) { + llvm::raw_string_ostream os(suffix); + os << "("; + llvm::interleaveComma(arrayIndices, os); + os << ")"; + } + + // Names from FIR operations may be mangled. + // When the demangled name is requested - demangle it. + if (preferDemangledName) { + auto [kind, deconstructed] = fir::NameUniquer::deconstruct(srcName); + if (kind != fir::NameUniquer::NameKind::NOT_UNIQUED) + return prefix + deconstructed.name + suffix; + } + + return prefix + srcName + suffix; +} + +bool areAllBoundsConstant(llvm::ArrayRef<Value> bounds) { + for (auto bound : bounds) { + auto dataBound = + mlir::dyn_cast<mlir::acc::DataBoundsOp>(bound.getDefiningOp()); + if (!dataBound) + return false; + + // Check if this bound has constant values + bool hasConstant = false; + if (dataBound.getLowerbound() && dataBound.getUpperbound()) + hasConstant = + fir::getIntIfConstant(dataBound.getLowerbound()).has_value() && + fir::getIntIfConstant(dataBound.getUpperbound()).has_value(); + else if (dataBound.getExtent()) + hasConstant = fir::getIntIfConstant(dataBound.getExtent()).has_value(); + + if (!hasConstant) + return false; + } + return true; +} + +static std::string getBoundsString(llvm::ArrayRef<Value> bounds) { + if (bounds.empty()) + return ""; + + std::string boundStr; + llvm::raw_string_ostream os(boundStr); + os << "_section_"; + + llvm::interleave( + bounds, + [&](Value bound) { + auto boundsOp = + mlir::cast<mlir::acc::DataBoundsOp>(bound.getDefiningOp()); + if (boundsOp.getLowerbound() && + fir::getIntIfConstant(boundsOp.getLowerbound()) && + boundsOp.getUpperbound() && + fir::getIntIfConstant(boundsOp.getUpperbound())) { + os << "lb" << *fir::getIntIfConstant(boundsOp.getLowerbound()) + << ".ub" << *fir::getIntIfConstant(boundsOp.getUpperbound()); + } else if (boundsOp.getExtent() && + fir::getIntIfConstant(boundsOp.getExtent())) { + os << "ext" << *fir::getIntIfConstant(boundsOp.getExtent()); + } else { + os << "?"; + } + }, + [&] { os << "x"; }); + + return os.str(); +} + +std::string getRecipeName(mlir::acc::RecipeKind kind, Type type, Value var, + llvm::ArrayRef<Value> bounds, + mlir::acc::ReductionOperator reductionOp) { + assert(fir::isa_fir_type(type) && "getRecipeName expects a FIR type"); + + // Build the complete prefix with all components before calling + // getTypeAsString + std::string prefixStr; + llvm::raw_string_ostream prefixOS(prefixStr); + + switch (kind) { + case mlir::acc::RecipeKind::private_recipe: + prefixOS << "privatization"; + // Private recipes do not currently include bounds in the name + // TODO: They should include them - but lowering tests would need to + // be updated. + break; + case mlir::acc::RecipeKind::firstprivate_recipe: + prefixOS << "firstprivatization"; + // Add bounds to the prefix if applicable (only for firstprivate) + if (!bounds.empty() && areAllBoundsConstant(bounds)) + prefixOS << getBoundsString(bounds); + break; + case mlir::acc::RecipeKind::reduction_recipe: + prefixOS << "reduction"; + // Embed the reduction operator in the prefix + if (reductionOp != mlir::acc::ReductionOperator::AccNone) + prefixOS << "_" + << mlir::acc::stringifyReductionOperator(reductionOp).str(); + // Add bounds to the prefix if applicable (only for reduction) + if (!bounds.empty() && areAllBoundsConstant(bounds)) + prefixOS << getBoundsString(bounds); + break; + } + + auto kindMap = var && var.getDefiningOp() + ? fir::getKindMapping(var.getDefiningOp()) + : fir::KindMapping(type.getContext()); + return fir::getTypeAsString(type, kindMap, prefixOS.str()); +} + +} // namespace acc +} // namespace fir diff --git a/flang/lib/Optimizer/OpenACC/Support/RegisterOpenACCExtensions.cpp b/flang/lib/Optimizer/OpenACC/Support/RegisterOpenACCExtensions.cpp index d71c40d..acd1d01 100644 --- a/flang/lib/Optimizer/OpenACC/Support/RegisterOpenACCExtensions.cpp +++ b/flang/lib/Optimizer/OpenACC/Support/RegisterOpenACCExtensions.cpp @@ -49,6 +49,18 @@ void registerOpenACCExtensions(mlir::DialectRegistry ®istry) { PartialEntityAccessModel<fir::CoordinateOp>>(*ctx); fir::DeclareOp::attachInterface<PartialEntityAccessModel<fir::DeclareOp>>( *ctx); + + fir::AddrOfOp::attachInterface<AddressOfGlobalModel>(*ctx); + fir::GlobalOp::attachInterface<GlobalVariableModel>(*ctx); + + fir::AllocaOp::attachInterface<IndirectGlobalAccessModel<fir::AllocaOp>>( + *ctx); + fir::EmboxOp::attachInterface<IndirectGlobalAccessModel<fir::EmboxOp>>( + *ctx); + fir::ReboxOp::attachInterface<IndirectGlobalAccessModel<fir::ReboxOp>>( + *ctx); + fir::TypeDescOp::attachInterface< + IndirectGlobalAccessModel<fir::TypeDescOp>>(*ctx); }); // Register HLFIR operation interfaces diff --git a/flang/lib/Optimizer/OpenACC/Transforms/ACCInitializeFIRAnalyses.cpp b/flang/lib/Optimizer/OpenACC/Transforms/ACCInitializeFIRAnalyses.cpp new file mode 100644 index 0000000..679b29b --- /dev/null +++ b/flang/lib/Optimizer/OpenACC/Transforms/ACCInitializeFIRAnalyses.cpp @@ -0,0 +1,56 @@ +//===- ACCInitializeFIRAnalyses.cpp - Initialize FIR analyses ------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This pass initializes analyses that can be reused by subsequent OpenACC +// passes in the pipeline. +// +//===----------------------------------------------------------------------===// + +#include "flang/Optimizer/Analysis/AliasAnalysis.h" +#include "flang/Optimizer/OpenACC/Analysis/FIROpenACCSupportAnalysis.h" +#include "flang/Optimizer/OpenACC/Passes.h" +#include "mlir/Analysis/AliasAnalysis.h" +#include "mlir/Dialect/OpenACC/Analysis/OpenACCSupport.h" + +namespace fir { +namespace acc { +#define GEN_PASS_DEF_ACCINITIALIZEFIRANALYSES +#include "flang/Optimizer/OpenACC/Passes.h.inc" +} // namespace acc +} // namespace fir + +#define DEBUG_TYPE "acc-initialize-fir-analyses" + +namespace { + +/// This pass initializes analyses for reuse by subsequent OpenACC passes in the +/// pipeline. It creates and caches analyses like OpenACCSupport so they can be +/// retrieved by later passes using getAnalysis() or getCachedAnalysis(). +class ACCInitializeFIRAnalysesPass + : public fir::acc::impl::ACCInitializeFIRAnalysesBase< + ACCInitializeFIRAnalysesPass> { +public: + void runOnOperation() override { + // Initialize OpenACCSupport with FIR-specific implementation. + auto &openACCSupport = getAnalysis<mlir::acc::OpenACCSupport>(); + openACCSupport.setImplementation(fir::acc::FIROpenACCSupportAnalysis()); + + // Initialize AliasAnalysis with FIR-specific implementation. + auto &aliasAnalysis = getAnalysis<mlir::AliasAnalysis>(); + aliasAnalysis.addAnalysisImplementation(fir::AliasAnalysis()); + + // Mark all analyses as preserved since this pass only initializes them + markAllAnalysesPreserved(); + } +}; + +} // namespace + +std::unique_ptr<mlir::Pass> fir::acc::createACCInitializeFIRAnalysesPass() { + return std::make_unique<ACCInitializeFIRAnalysesPass>(); +} diff --git a/flang/lib/Optimizer/OpenACC/Transforms/ACCRecipeBufferization.cpp b/flang/lib/Optimizer/OpenACC/Transforms/ACCRecipeBufferization.cpp index 0d135a9..ad0cfa3 100644 --- a/flang/lib/Optimizer/OpenACC/Transforms/ACCRecipeBufferization.cpp +++ b/flang/lib/Optimizer/OpenACC/Transforms/ACCRecipeBufferization.cpp @@ -87,30 +87,26 @@ static void bufferizeRegionArgsAndYields(mlir::Region ®ion, } } -static void updateRecipeUse(mlir::ArrayAttr recipes, mlir::ValueRange operands, +template <typename OpTy> +static void updateRecipeUse(mlir::ValueRange operands, llvm::StringRef recipeSymName, mlir::Operation *computeOp) { - if (!recipes) - return; - for (auto [recipeSym, oldRes] : llvm::zip(recipes, operands)) { - if (llvm::cast<mlir::SymbolRefAttr>(recipeSym).getLeafReference() != - recipeSymName) + for (auto operand : operands) { + auto op = operand.getDefiningOp<OpTy>(); + if (!op || !op.getRecipe().has_value() || + op.getRecipeAttr().getLeafReference() != recipeSymName) continue; - mlir::Operation *dataOp = oldRes.getDefiningOp(); - assert(dataOp && "dataOp must be paired with computeOp"); - mlir::Location loc = dataOp->getLoc(); - mlir::OpBuilder builder(dataOp); - llvm::TypeSwitch<mlir::Operation *, void>(dataOp) - .Case<mlir::acc::PrivateOp, mlir::acc::FirstprivateOp, - mlir::acc::ReductionOp>([&](auto privateOp) { - builder.setInsertionPointAfterValue(privateOp.getVar()); - mlir::Value alloca = BufferizeInterface::placeInMemory( - builder, loc, privateOp.getVar()); - privateOp.getVarMutable().assign(alloca); - privateOp.getAccVar().setType(alloca.getType()); - }); + mlir::Location loc = op->getLoc(); + + mlir::OpBuilder builder(op); + builder.setInsertionPointAfterValue(op.getVar()); + mlir::Value alloca = + BufferizeInterface::placeInMemory(builder, loc, op.getVar()); + op.getVarMutable().assign(alloca); + op.getAccVar().setType(alloca.getType()); + mlir::Value oldRes = op.getAccVar(); llvm::SmallVector<mlir::Operation *> users(oldRes.getUsers().begin(), oldRes.getUsers().end()); for (mlir::Operation *useOp : users) { @@ -166,18 +162,15 @@ public: .Case<mlir::acc::LoopOp, mlir::acc::ParallelOp, mlir::acc::SerialOp>( [&](auto computeOp) { for (llvm::StringRef recipeName : recipeNames) { - if (computeOp.getPrivatizationRecipes()) - updateRecipeUse(computeOp.getPrivatizationRecipesAttr(), - computeOp.getPrivateOperands(), recipeName, - op); - if (computeOp.getFirstprivatizationRecipes()) - updateRecipeUse( - computeOp.getFirstprivatizationRecipesAttr(), + if (!computeOp.getPrivateOperands().empty()) + updateRecipeUse<mlir::acc::PrivateOp>( + computeOp.getPrivateOperands(), recipeName, op); + if (!computeOp.getFirstprivateOperands().empty()) + updateRecipeUse<mlir::acc::FirstprivateOp>( computeOp.getFirstprivateOperands(), recipeName, op); - if (computeOp.getReductionRecipes()) - updateRecipeUse(computeOp.getReductionRecipesAttr(), - computeOp.getReductionOperands(), - recipeName, op); + if (!computeOp.getReductionOperands().empty()) + updateRecipeUse<mlir::acc::ReductionOp>( + computeOp.getReductionOperands(), recipeName, op); } }); }); diff --git a/flang/lib/Optimizer/OpenACC/Transforms/CMakeLists.txt b/flang/lib/Optimizer/OpenACC/Transforms/CMakeLists.txt index ed177ba..d41e99a 100644 --- a/flang/lib/Optimizer/OpenACC/Transforms/CMakeLists.txt +++ b/flang/lib/Optimizer/OpenACC/Transforms/CMakeLists.txt @@ -1,14 +1,19 @@ add_flang_library(FIROpenACCTransforms + ACCInitializeFIRAnalyses.cpp ACCRecipeBufferization.cpp DEPENDS FIROpenACCPassesIncGen LINK_LIBS + FIRAnalysis FIRDialect + FIROpenACCAnalysis + HLFIRDialect MLIR_LIBS MLIRIR MLIRPass MLIROpenACCDialect + MLIROpenACCUtils ) diff --git a/flang/lib/Optimizer/OpenMP/DoConcurrentConversion.cpp b/flang/lib/Optimizer/OpenMP/DoConcurrentConversion.cpp index 1229018..1012a96 100644 --- a/flang/lib/Optimizer/OpenMP/DoConcurrentConversion.cpp +++ b/flang/lib/Optimizer/OpenMP/DoConcurrentConversion.cpp @@ -692,9 +692,6 @@ private: if (!targetShapeCreationInfo.isShapedValue()) return {}; - llvm::SmallVector<mlir::Value> extentOperands; - llvm::SmallVector<mlir::Value> startIndexOperands; - if (targetShapeCreationInfo.isShapeShiftedValue()) { llvm::SmallVector<mlir::Value> shapeShiftOperands; @@ -851,7 +848,8 @@ private: if (!ompReducer) { ompReducer = mlir::omp::DeclareReductionOp::create( rewriter, firReducer.getLoc(), ompReducerName, - firReducer.getTypeAttr().getValue()); + firReducer.getTypeAttr().getValue(), + firReducer.getByrefElementTypeAttr()); cloneFIRRegionToOMP(rewriter, firReducer.getAllocRegion(), ompReducer.getAllocRegion()); diff --git a/flang/lib/Optimizer/OpenMP/MapInfoFinalization.cpp b/flang/lib/Optimizer/OpenMP/MapInfoFinalization.cpp index bd07d7f..3fe133d 100644 --- a/flang/lib/Optimizer/OpenMP/MapInfoFinalization.cpp +++ b/flang/lib/Optimizer/OpenMP/MapInfoFinalization.cpp @@ -347,10 +347,10 @@ class MapInfoFinalizationPass /// base address (BoxOffsetOp) and a MapInfoOp for it. The most /// important thing to note is that we normally move the bounds from /// the descriptor map onto the base address map. - mlir::omp::MapInfoOp genBaseAddrMap(mlir::Value descriptor, - mlir::OperandRange bounds, - mlir::omp::ClauseMapFlags mapType, - fir::FirOpBuilder &builder) { + mlir::omp::MapInfoOp + genBaseAddrMap(mlir::Value descriptor, mlir::OperandRange bounds, + mlir::omp::ClauseMapFlags mapType, fir::FirOpBuilder &builder, + mlir::FlatSymbolRefAttr mapperId = mlir::FlatSymbolRefAttr()) { mlir::Location loc = descriptor.getLoc(); mlir::Value baseAddrAddr = fir::BoxOffsetOp::create( builder, loc, descriptor, fir::BoxFieldAttr::base_addr); @@ -372,7 +372,7 @@ class MapInfoFinalizationPass mlir::omp::VariableCaptureKind::ByRef), baseAddrAddr, /*members=*/mlir::SmallVector<mlir::Value>{}, /*membersIndex=*/mlir::ArrayAttr{}, bounds, - /*mapperId*/ mlir::FlatSymbolRefAttr(), + /*mapperId=*/mapperId, /*name=*/builder.getStringAttr(""), /*partial_map=*/builder.getBoolAttr(false)); } @@ -437,6 +437,20 @@ class MapInfoFinalizationPass mapFlags flags = mapFlags::to | (mapTypeFlag & (mapFlags::implicit | mapFlags::always)); + + // Descriptors for objects will always be copied. This is because the + // descriptor can be rematerialized by the compiler, and so the address + // of the descriptor for a given object at one place in the code may + // differ from that address in another place. The contents of the + // descriptor (the base address in particular) will remain unchanged + // though. + // TODO/FIXME: We currently cannot have MAP_CLOSE and MAP_ALWAYS on + // the descriptor at once, these are mutually exclusive and when + // both are applied the runtime will fail to map. + flags |= ((mapFlags(mapTypeFlag) & mapFlags::close) == mapFlags::close) + ? mapFlags::close + : mapFlags::always; + // For unified_shared_memory, we additionally add `CLOSE` on the descriptor // to ensure device-local placement where required by tests relying on USM + // close semantics. @@ -477,58 +491,6 @@ class MapInfoFinalizationPass return false; } - mlir::omp::MapInfoOp genBoxcharMemberMap(mlir::omp::MapInfoOp op, - fir::FirOpBuilder &builder) { - if (!op.getMembers().empty()) - return op; - mlir::Location loc = op.getVarPtr().getLoc(); - mlir::Value boxChar = op.getVarPtr(); - - if (mlir::isa<fir::ReferenceType>(op.getVarPtr().getType())) - boxChar = fir::LoadOp::create(builder, loc, op.getVarPtr()); - - fir::BoxCharType boxCharType = - mlir::dyn_cast<fir::BoxCharType>(boxChar.getType()); - mlir::Value boxAddr = fir::BoxOffsetOp::create( - builder, loc, op.getVarPtr(), fir::BoxFieldAttr::base_addr); - - mlir::ArrayAttr newMembersAttr; - llvm::SmallVector<llvm::SmallVector<int64_t>> memberIdx = {{0}}; - newMembersAttr = builder.create2DI64ArrayAttr(memberIdx); - - mlir::Value varPtr = op.getVarPtr(); - mlir::omp::MapInfoOp memberMapInfoOp = mlir::omp::MapInfoOp::create( - builder, op.getLoc(), varPtr.getType(), varPtr, - mlir::TypeAttr::get(boxCharType.getEleTy()), - builder.getAttr<mlir::omp::ClauseMapFlagsAttr>( - mlir::omp::ClauseMapFlags::to | - mlir::omp::ClauseMapFlags::implicit), - builder.getAttr<mlir::omp::VariableCaptureKindAttr>( - mlir::omp::VariableCaptureKind::ByRef), - /*varPtrPtr=*/boxAddr, - /*members=*/llvm::SmallVector<mlir::Value>{}, - /*member_index=*/mlir::ArrayAttr{}, - /*bounds=*/op.getBounds(), - /*mapperId=*/mlir::FlatSymbolRefAttr(), /*name=*/op.getNameAttr(), - builder.getBoolAttr(false)); - - mlir::omp::MapInfoOp newMapInfoOp = mlir::omp::MapInfoOp::create( - builder, op.getLoc(), op.getResult().getType(), varPtr, - mlir::TypeAttr::get( - llvm::cast<mlir::omp::PointerLikeType>(varPtr.getType()) - .getElementType()), - op.getMapTypeAttr(), op.getMapCaptureTypeAttr(), - /*varPtrPtr=*/mlir::Value{}, - /*members=*/llvm::SmallVector<mlir::Value>{memberMapInfoOp}, - /*member_index=*/newMembersAttr, - /*bounds=*/llvm::SmallVector<mlir::Value>{}, - /*mapperId=*/mlir::FlatSymbolRefAttr(), op.getNameAttr(), - /*partial_map=*/builder.getBoolAttr(false)); - op.replaceAllUsesWith(newMapInfoOp.getResult()); - op->erase(); - return newMapInfoOp; - } - // Expand mappings of type(C_PTR) to map their `__address` field explicitly // as a single pointer-sized member (USM-gated at callsite). This helps in // USM scenarios to ensure the pointer-sized mapping is used. @@ -630,6 +592,7 @@ class MapInfoFinalizationPass // from the descriptor to be used verbatim, i.e. without additional // remapping. To avoid this remapping, simply don't generate any map // information for the descriptor members. + mlir::FlatSymbolRefAttr mapperId = op.getMapperIdAttr(); if (!mapMemberUsers.empty()) { // Currently, there should only be one user per map when this pass // is executed. Either a parent map, holding the current map in its @@ -640,8 +603,8 @@ class MapInfoFinalizationPass assert(mapMemberUsers.size() == 1 && "OMPMapInfoFinalization currently only supports single users of a " "MapInfoOp"); - auto baseAddr = - genBaseAddrMap(descriptor, op.getBounds(), op.getMapType(), builder); + auto baseAddr = genBaseAddrMap(descriptor, op.getBounds(), + op.getMapType(), builder, mapperId); ParentAndPlacement mapUser = mapMemberUsers[0]; adjustMemberIndices(memberIndices, mapUser.index); llvm::SmallVector<mlir::Value> newMemberOps; @@ -654,8 +617,8 @@ class MapInfoFinalizationPass mapUser.parent.setMembersIndexAttr( builder.create2DI64ArrayAttr(memberIndices)); } else if (!isHasDeviceAddrFlag) { - auto baseAddr = - genBaseAddrMap(descriptor, op.getBounds(), op.getMapType(), builder); + auto baseAddr = genBaseAddrMap(descriptor, op.getBounds(), + op.getMapType(), builder, mapperId); newMembers.push_back(baseAddr); if (!op.getMembers().empty()) { for (auto &indices : memberIndices) @@ -687,7 +650,7 @@ class MapInfoFinalizationPass getDescriptorMapType(mapType, target)), op.getMapCaptureTypeAttr(), /*varPtrPtr=*/mlir::Value{}, newMembers, newMembersAttr, /*bounds=*/mlir::SmallVector<mlir::Value>{}, - /*mapperId*/ mlir::FlatSymbolRefAttr(), op.getNameAttr(), + /*mapperId=*/mlir::FlatSymbolRefAttr(), op.getNameAttr(), /*partial_map=*/builder.getBoolAttr(false)); op.replaceAllUsesWith(newDescParentMapOp.getResult()); op->erase(); @@ -956,6 +919,14 @@ class MapInfoFinalizationPass baseAddr.erase(); } + static bool hasADescriptor(mlir::Operation *varOp, mlir::Type varType) { + if (fir::isTypeWithDescriptor(varType) || + mlir::isa<fir::BoxCharType>(varType) || + mlir::isa_and_present<fir::BoxAddrOp>(varOp)) + return true; + return false; + } + // This pass executes on omp::MapInfoOp's containing descriptor based types // (allocatables, pointers, assumed shape etc.) and expanding them into // multiple omp::MapInfoOp's for each pointer member contained within the @@ -987,38 +958,6 @@ class MapInfoFinalizationPass localBoxAllocas.clear(); deferrableDesc.clear(); - // First, walk `omp.map.info` ops to see if any of them have varPtrs - // with an underlying type of fir.char<k, ?>, i.e a character - // with dynamic length. If so, check if they need bounds added. - func->walk([&](mlir::omp::MapInfoOp op) { - if (!op.getBounds().empty()) - return; - - mlir::Value varPtr = op.getVarPtr(); - mlir::Type underlyingVarType = fir::unwrapRefType(varPtr.getType()); - - if (!fir::characterWithDynamicLen(underlyingVarType)) - return; - - fir::factory::AddrAndBoundsInfo info = - fir::factory::getDataOperandBaseAddr( - builder, varPtr, /*isOptional=*/false, varPtr.getLoc()); - - fir::ExtendedValue extendedValue = - hlfir::translateToExtendedValue(varPtr.getLoc(), builder, - hlfir::Entity{info.addr}, - /*continguousHint=*/true) - .first; - builder.setInsertionPoint(op); - llvm::SmallVector<mlir::Value> boundsOps = - fir::factory::genImplicitBoundsOps<mlir::omp::MapBoundsOp, - mlir::omp::MapBoundsType>( - builder, info, extendedValue, - /*dataExvIsAssumedSize=*/false, varPtr.getLoc()); - - op.getBoundsMutable().append(boundsOps); - }); - // Next, walk `omp.map.info` ops to see if any record members should be // implicitly mapped. func->walk([&](mlir::omp::MapInfoOp op) { @@ -1209,36 +1148,6 @@ class MapInfoFinalizationPass return mlir::WalkResult::advance(); }); - func->walk([&](mlir::omp::MapInfoOp op) { - if (!op.getMembers().empty()) - return; - - if (!mlir::isa<fir::BoxCharType>(fir::unwrapRefType(op.getVarType()))) - return; - - // POSSIBLE_HACK_ALERT: If the boxchar has been implicitly mapped then - // it is likely that the underlying pointer to the data - // (!fir.ref<fir.char<k,?>>) has already been mapped. So, skip such - // boxchars. We are primarily interested in boxchars that were mapped - // by passes such as MapsForPrivatizedSymbols that map boxchars that - // are privatized. At present, such boxchar maps are not marked - // implicit. Should they be? I don't know. If they should be then - // we need to change this check for early return OR live with - // over-mapping. - bool hasImplicitMap = - (op.getMapType() & mlir::omp::ClauseMapFlags::implicit) == - mlir::omp::ClauseMapFlags::implicit; - if (hasImplicitMap) - return; - - assert(llvm::hasSingleElement(op->getUsers()) && - "OMPMapInfoFinalization currently only supports single users " - "of a MapInfoOp"); - - builder.setInsertionPoint(op); - genBoxcharMemberMap(op, builder); - }); - // Expand type(C_PTR) only when unified_shared_memory is required, // to ensure device-visible pointer size/behavior in USM scenarios // without changing default expectations elsewhere. @@ -1266,9 +1175,8 @@ class MapInfoFinalizationPass "OMPMapInfoFinalization currently only supports single users " "of a MapInfoOp"); - if (fir::isTypeWithDescriptor(op.getVarType()) || - mlir::isa_and_present<fir::BoxAddrOp>( - op.getVarPtr().getDefiningOp())) { + if (hasADescriptor(op.getVarPtr().getDefiningOp(), + fir::unwrapRefType(op.getVarType()))) { builder.setInsertionPoint(op); mlir::Operation *targetUser = getFirstTargetUser(op); assert(targetUser && "expected user of map operation was not found"); diff --git a/flang/lib/Optimizer/OpenMP/MapsForPrivatizedSymbols.cpp b/flang/lib/Optimizer/OpenMP/MapsForPrivatizedSymbols.cpp index 0972861..6404e18 100644 --- a/flang/lib/Optimizer/OpenMP/MapsForPrivatizedSymbols.cpp +++ b/flang/lib/Optimizer/OpenMP/MapsForPrivatizedSymbols.cpp @@ -104,21 +104,31 @@ class MapsForPrivatizedSymbolsPass llvm::SmallVector<mlir::Value> boundsOps; if (needsBoundsOps(varPtr)) genBoundsOps(builder, varPtr, boundsOps); + mlir::Type varType = varPtr.getType(); mlir::omp::VariableCaptureKind captureKind = mlir::omp::VariableCaptureKind::ByRef; - if (fir::isa_trivial(fir::unwrapRefType(varPtr.getType())) || - fir::isa_char(fir::unwrapRefType(varPtr.getType()))) { - if (canPassByValue(fir::unwrapRefType(varPtr.getType()))) { + if (fir::isa_trivial(fir::unwrapRefType(varType)) || + fir::isa_char(fir::unwrapRefType(varType))) { + if (canPassByValue(fir::unwrapRefType(varType))) { captureKind = mlir::omp::VariableCaptureKind::ByCopy; } } + // Use tofrom if what we are mapping is not a trivial type. In all + // likelihood, it is a descriptor + mlir::omp::ClauseMapFlags mapFlag; + if (fir::isa_trivial(fir::unwrapRefType(varType)) || + fir::isa_char(fir::unwrapRefType(varType))) + mapFlag = mlir::omp::ClauseMapFlags::to; + else + mapFlag = mlir::omp::ClauseMapFlags::to | mlir::omp::ClauseMapFlags::from; + return omp::MapInfoOp::create( - builder, loc, varPtr.getType(), varPtr, - TypeAttr::get(llvm::cast<omp::PointerLikeType>(varPtr.getType()) - .getElementType()), - builder.getAttr<omp::ClauseMapFlagsAttr>(omp::ClauseMapFlags::to), + builder, loc, varType, varPtr, + TypeAttr::get( + llvm::cast<omp::PointerLikeType>(varType).getElementType()), + builder.getAttr<omp::ClauseMapFlagsAttr>(mapFlag), builder.getAttr<omp::VariableCaptureKindAttr>(captureKind), /*varPtrPtr=*/Value{}, /*members=*/SmallVector<Value>{}, diff --git a/flang/lib/Optimizer/OpenMP/MarkDeclareTarget.cpp b/flang/lib/Optimizer/OpenMP/MarkDeclareTarget.cpp index 0b0e6bd..5fa77fb 100644 --- a/flang/lib/Optimizer/OpenMP/MarkDeclareTarget.cpp +++ b/flang/lib/Optimizer/OpenMP/MarkDeclareTarget.cpp @@ -21,6 +21,7 @@ #include "mlir/Pass/Pass.h" #include "mlir/Support/LLVM.h" #include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/TypeSwitch.h" namespace flangomp { #define GEN_PASS_DEF_MARKDECLARETARGETPASS @@ -31,9 +32,93 @@ namespace { class MarkDeclareTargetPass : public flangomp::impl::MarkDeclareTargetPassBase<MarkDeclareTargetPass> { - void markNestedFuncs(mlir::omp::DeclareTargetDeviceType parentDevTy, - mlir::omp::DeclareTargetCaptureClause parentCapClause, - bool parentAutomap, mlir::Operation *currOp, + struct ParentInfo { + mlir::omp::DeclareTargetDeviceType devTy; + mlir::omp::DeclareTargetCaptureClause capClause; + bool automap; + }; + + void processSymbolRef(mlir::SymbolRefAttr symRef, ParentInfo parentInfo, + llvm::SmallPtrSet<mlir::Operation *, 16> visited) { + if (auto currFOp = + getOperation().lookupSymbol<mlir::func::FuncOp>(symRef)) { + auto current = llvm::dyn_cast<mlir::omp::DeclareTargetInterface>( + currFOp.getOperation()); + + if (current.isDeclareTarget()) { + auto currentDt = current.getDeclareTargetDeviceType(); + + // Found the same function twice, with different device_types, + // mark as Any as it belongs to both + if (currentDt != parentInfo.devTy && + currentDt != mlir::omp::DeclareTargetDeviceType::any) { + current.setDeclareTarget(mlir::omp::DeclareTargetDeviceType::any, + current.getDeclareTargetCaptureClause(), + current.getDeclareTargetAutomap()); + } + } else { + current.setDeclareTarget(parentInfo.devTy, parentInfo.capClause, + parentInfo.automap); + } + + markNestedFuncs(parentInfo, currFOp, visited); + } + } + + void processReductionRefs(std::optional<mlir::ArrayAttr> symRefs, + ParentInfo parentInfo, + llvm::SmallPtrSet<mlir::Operation *, 16> visited) { + if (!symRefs) + return; + + for (auto symRef : symRefs->getAsRange<mlir::SymbolRefAttr>()) { + if (auto declareReductionOp = + getOperation().lookupSymbol<mlir::omp::DeclareReductionOp>( + symRef)) { + markNestedFuncs(parentInfo, declareReductionOp, visited); + } + } + } + + void + processReductionClauses(mlir::Operation *op, ParentInfo parentInfo, + llvm::SmallPtrSet<mlir::Operation *, 16> visited) { + llvm::TypeSwitch<mlir::Operation &>(*op) + .Case([&](mlir::omp::LoopOp op) { + processReductionRefs(op.getReductionSyms(), parentInfo, visited); + }) + .Case([&](mlir::omp::ParallelOp op) { + processReductionRefs(op.getReductionSyms(), parentInfo, visited); + }) + .Case([&](mlir::omp::SectionsOp op) { + processReductionRefs(op.getReductionSyms(), parentInfo, visited); + }) + .Case([&](mlir::omp::SimdOp op) { + processReductionRefs(op.getReductionSyms(), parentInfo, visited); + }) + .Case([&](mlir::omp::TargetOp op) { + processReductionRefs(op.getInReductionSyms(), parentInfo, visited); + }) + .Case([&](mlir::omp::TaskgroupOp op) { + processReductionRefs(op.getTaskReductionSyms(), parentInfo, visited); + }) + .Case([&](mlir::omp::TaskloopOp op) { + processReductionRefs(op.getReductionSyms(), parentInfo, visited); + processReductionRefs(op.getInReductionSyms(), parentInfo, visited); + }) + .Case([&](mlir::omp::TaskOp op) { + processReductionRefs(op.getInReductionSyms(), parentInfo, visited); + }) + .Case([&](mlir::omp::TeamsOp op) { + processReductionRefs(op.getReductionSyms(), parentInfo, visited); + }) + .Case([&](mlir::omp::WsloopOp op) { + processReductionRefs(op.getReductionSyms(), parentInfo, visited); + }) + .Default([](mlir::Operation &) {}); + } + + void markNestedFuncs(ParentInfo parentInfo, mlir::Operation *currOp, llvm::SmallPtrSet<mlir::Operation *, 16> visited) { if (visited.contains(currOp)) return; @@ -43,33 +128,10 @@ class MarkDeclareTargetPass if (auto callOp = llvm::dyn_cast<mlir::CallOpInterface>(op)) { if (auto symRef = llvm::dyn_cast_if_present<mlir::SymbolRefAttr>( callOp.getCallableForCallee())) { - if (auto currFOp = - getOperation().lookupSymbol<mlir::func::FuncOp>(symRef)) { - auto current = llvm::dyn_cast<mlir::omp::DeclareTargetInterface>( - currFOp.getOperation()); - - if (current.isDeclareTarget()) { - auto currentDt = current.getDeclareTargetDeviceType(); - - // Found the same function twice, with different device_types, - // mark as Any as it belongs to both - if (currentDt != parentDevTy && - currentDt != mlir::omp::DeclareTargetDeviceType::any) { - current.setDeclareTarget( - mlir::omp::DeclareTargetDeviceType::any, - current.getDeclareTargetCaptureClause(), - current.getDeclareTargetAutomap()); - } - } else { - current.setDeclareTarget(parentDevTy, parentCapClause, - parentAutomap); - } - - markNestedFuncs(parentDevTy, parentCapClause, parentAutomap, - currFOp, visited); - } + processSymbolRef(symRef, parentInfo, visited); } } + processReductionClauses(op, parentInfo, visited); }); } @@ -82,10 +144,10 @@ class MarkDeclareTargetPass functionOp.getOperation()); if (declareTargetOp.isDeclareTarget()) { llvm::SmallPtrSet<mlir::Operation *, 16> visited; - markNestedFuncs(declareTargetOp.getDeclareTargetDeviceType(), - declareTargetOp.getDeclareTargetCaptureClause(), - declareTargetOp.getDeclareTargetAutomap(), functionOp, - visited); + ParentInfo parentInfo{declareTargetOp.getDeclareTargetDeviceType(), + declareTargetOp.getDeclareTargetCaptureClause(), + declareTargetOp.getDeclareTargetAutomap()}; + markNestedFuncs(parentInfo, functionOp, visited); } } @@ -96,12 +158,13 @@ class MarkDeclareTargetPass // the contents of the device clause getOperation()->walk([&](mlir::omp::TargetOp tarOp) { llvm::SmallPtrSet<mlir::Operation *, 16> visited; - markNestedFuncs( - /*parentDevTy=*/mlir::omp::DeclareTargetDeviceType::nohost, - /*parentCapClause=*/mlir::omp::DeclareTargetCaptureClause::to, - /*parentAutomap=*/false, tarOp, visited); + ParentInfo parentInfo = { + /*devTy=*/mlir::omp::DeclareTargetDeviceType::nohost, + /*capClause=*/mlir::omp::DeclareTargetCaptureClause::to, + /*automap=*/false, + }; + markNestedFuncs(parentInfo, tarOp, visited); }); } }; - } // namespace diff --git a/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp b/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp index e006d2e..7491b7b 100644 --- a/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp +++ b/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp @@ -53,7 +53,7 @@ class AddDebugInfoPass : public fir::impl::AddDebugInfoBase<AddDebugInfoPass> { mlir::LLVM::DIFileAttr fileAttr, mlir::LLVM::DIScopeAttr scopeAttr, fir::DebugTypeGenerator &typeGen, - mlir::SymbolTable *symbolTable); + mlir::SymbolTable *symbolTable, mlir::Value dummyScope); public: AddDebugInfoPass(fir::AddDebugInfoOptions options) : Base(options) {} @@ -144,69 +144,88 @@ bool AddDebugInfoPass::createCommonBlockGlobal( fir::DebugTypeGenerator &typeGen, mlir::SymbolTable *symbolTable) { mlir::MLIRContext *context = &getContext(); mlir::OpBuilder builder(context); - std::optional<std::int64_t> optint; - mlir::Operation *op = declOp.getMemref().getDefiningOp(); - if (auto conOp = mlir::dyn_cast_if_present<fir::ConvertOp>(op)) - op = conOp.getValue().getDefiningOp(); + std::optional<std::int64_t> offset; + mlir::Value storage = declOp.getStorage(); + if (!storage) + return false; + + // Extract offset from storage_offset attribute + uint64_t storageOffset = declOp.getStorageOffset(); + if (storageOffset != 0) + offset = static_cast<std::int64_t>(storageOffset); + + // Get the GlobalOp from the storage value. + // The storage may be wrapped in ConvertOp, so unwrap it first. + mlir::Operation *storageOp = storage.getDefiningOp(); + if (auto convertOp = mlir::dyn_cast_if_present<fir::ConvertOp>(storageOp)) + storageOp = convertOp.getValue().getDefiningOp(); + + auto addrOfOp = mlir::dyn_cast_if_present<fir::AddrOfOp>(storageOp); + if (!addrOfOp) + return false; + + mlir::SymbolRefAttr sym = addrOfOp.getSymbol(); + fir::GlobalOp global = + symbolTable->lookup<fir::GlobalOp>(sym.getRootReference()); + if (!global) + return false; + + // Check if the global is actually a common block by demangling its name. + // Module EQUIVALENCE variables also use storage operands but are mangled + // as VARIABLE type, so we reject them to avoid treating them as common + // blocks. + llvm::StringRef globalSymbol = sym.getRootReference(); + auto globalResult = fir::NameUniquer::deconstruct(globalSymbol); + if (globalResult.first == fir::NameUniquer::NameKind::VARIABLE) + return false; + + // FIXME: We are trying to extract the name of the common block from the + // name of the global. As part of mangling, GetCommonBlockObjectName can + // add a trailing _ in the name of that global. The demangle function + // does not seem to handle such cases. So the following hack is used to + // remove the trailing '_'. + llvm::StringRef commonName = globalSymbol; + if (commonName != Fortran::common::blankCommonObjectName && + !commonName.empty() && commonName.back() == '_') + commonName = commonName.drop_back(); + + // Create the debug attributes. + unsigned line = getLineFromLoc(global.getLoc()); + mlir::LLVM::DICommonBlockAttr commonBlock = + getOrCreateCommonBlockAttr(commonName, fileAttr, scopeAttr, line); + + mlir::LLVM::DITypeAttr diType = typeGen.convertType( + fir::unwrapRefType(declOp.getType()), fileAttr, scopeAttr, declOp); + + line = getLineFromLoc(declOp.getLoc()); + auto gvAttr = mlir::LLVM::DIGlobalVariableAttr::get( + context, commonBlock, mlir::StringAttr::get(context, name), + declOp.getUniqName(), fileAttr, line, diType, + /*isLocalToUnit*/ false, /*isDefinition*/ true, /* alignInBits*/ 0); + + // Create DIExpression for offset if needed + mlir::LLVM::DIExpressionAttr expr; + if (offset && *offset != 0) { + llvm::SmallVector<mlir::LLVM::DIExpressionElemAttr> ops; + ops.push_back(mlir::LLVM::DIExpressionElemAttr::get( + context, llvm::dwarf::DW_OP_plus_uconst, *offset)); + expr = mlir::LLVM::DIExpressionAttr::get(context, ops); + } - if (auto cordOp = mlir::dyn_cast_if_present<fir::CoordinateOp>(op)) { - auto coors = cordOp.getCoor(); - if (coors.size() != 1) - return false; - optint = fir::getIntIfConstant(coors[0]); - if (!optint) - return false; - op = cordOp.getRef().getDefiningOp(); - if (auto conOp2 = mlir::dyn_cast_if_present<fir::ConvertOp>(op)) - op = conOp2.getValue().getDefiningOp(); + auto dbgExpr = mlir::LLVM::DIGlobalVariableExpressionAttr::get( + global.getContext(), gvAttr, expr); + globalToGlobalExprsMap[global].push_back(dbgExpr); - if (auto addrOfOp = mlir::dyn_cast_if_present<fir::AddrOfOp>(op)) { - mlir::SymbolRefAttr sym = addrOfOp.getSymbol(); - if (auto global = - symbolTable->lookup<fir::GlobalOp>(sym.getRootReference())) { - - unsigned line = getLineFromLoc(global.getLoc()); - llvm::StringRef commonName(sym.getRootReference()); - // FIXME: We are trying to extract the name of the common block from the - // name of the global. As part of mangling, GetCommonBlockObjectName can - // add a trailing _ in the name of that global. The demangle function - // does not seem to handle such cases. So the following hack is used to - // remove the trailing '_'. - if (commonName != Fortran::common::blankCommonObjectName && - commonName.back() == '_') - commonName = commonName.drop_back(); - mlir::LLVM::DICommonBlockAttr commonBlock = - getOrCreateCommonBlockAttr(commonName, fileAttr, scopeAttr, line); - mlir::LLVM::DITypeAttr diType = typeGen.convertType( - fir::unwrapRefType(declOp.getType()), fileAttr, scopeAttr, declOp); - line = getLineFromLoc(declOp.getLoc()); - auto gvAttr = mlir::LLVM::DIGlobalVariableAttr::get( - context, commonBlock, mlir::StringAttr::get(context, name), - declOp.getUniqName(), fileAttr, line, diType, - /*isLocalToUnit*/ false, /*isDefinition*/ true, /* alignInBits*/ 0); - mlir::LLVM::DIExpressionAttr expr; - if (*optint != 0) { - llvm::SmallVector<mlir::LLVM::DIExpressionElemAttr> ops; - ops.push_back(mlir::LLVM::DIExpressionElemAttr::get( - context, llvm::dwarf::DW_OP_plus_uconst, *optint)); - expr = mlir::LLVM::DIExpressionAttr::get(context, ops); - } - auto dbgExpr = mlir::LLVM::DIGlobalVariableExpressionAttr::get( - global.getContext(), gvAttr, expr); - globalToGlobalExprsMap[global].push_back(dbgExpr); - return true; - } - } - } - return false; + return true; } void AddDebugInfoPass::handleDeclareOp(fir::cg::XDeclareOp declOp, mlir::LLVM::DIFileAttr fileAttr, mlir::LLVM::DIScopeAttr scopeAttr, fir::DebugTypeGenerator &typeGen, - mlir::SymbolTable *symbolTable) { + mlir::SymbolTable *symbolTable, + mlir::Value dummyScope) { mlir::MLIRContext *context = &getContext(); mlir::OpBuilder builder(context); auto result = fir::NameUniquer::deconstruct(declOp.getUniqName()); @@ -228,24 +247,11 @@ void AddDebugInfoPass::handleDeclareOp(fir::cg::XDeclareOp declOp, } } - // FIXME: There may be cases where an argument is processed a bit before - // DeclareOp is generated. In that case, DeclareOp may point to an - // intermediate op and not to BlockArgument. - // Moreover, with MLIR inlining we cannot use the BlockArgument - // position to identify the original number of the dummy argument. - // If we want to keep running AddDebugInfoPass late, the dummy argument - // position in the argument list has to be expressed in FIR (e.g. as a - // constant attribute of [hl]fir.declare/fircg.ext_declare operation that has - // a dummy_scope operand). + // Get the dummy argument position from the explicit attribute. unsigned argNo = 0; - if (declOp.getDummyScope()) { - if (auto arg = llvm::dyn_cast<mlir::BlockArgument>(declOp.getMemref())) { - // Check if it is the BlockArgument of the function's entry block. - if (auto funcLikeOp = - declOp->getParentOfType<mlir::FunctionOpInterface>()) - if (arg.getOwner() == &funcLikeOp.front()) - argNo = arg.getArgNumber() + 1; - } + if (dummyScope && declOp.getDummyScope() == dummyScope) { + if (auto argNoOpt = declOp.getDummyArgNo()) + argNo = *argNoOpt; } auto tyAttr = typeGen.convertType(fir::unwrapRefType(declOp.getType()), @@ -623,6 +629,21 @@ void AddDebugInfoPass::handleFuncOp(mlir::func::FuncOp funcOp, funcOp->setLoc(builder.getFusedLoc({l}, spAttr)); addTargetOpDISP(/*lineTableOnly=*/false, entities); + // Find the first dummy_scope definition. This is the one of the current + // function. The other ones may come from inlined calls. The variables inside + // those inlined calls should not be identified as arguments of the current + // function. + mlir::Value dummyScope; + funcOp.walk([&](fir::UndefOp undef) -> mlir::WalkResult { + // TODO: delay fir.dummy_scope translation to undefined until + // codegeneration. This is nicer and safer to match. + if (llvm::isa<fir::DummyScopeType>(undef.getType())) { + dummyScope = undef; + return mlir::WalkResult::interrupt(); + } + return mlir::WalkResult::advance(); + }); + funcOp.walk([&](fir::cg::XDeclareOp declOp) { mlir::LLVM::DISubprogramAttr spTy = spAttr; if (auto tOp = declOp->getParentOfType<mlir::omp::TargetOp>()) { @@ -632,7 +653,7 @@ void AddDebugInfoPass::handleFuncOp(mlir::func::FuncOp funcOp, spTy = sp; } } - handleDeclareOp(declOp, fileAttr, spTy, typeGen, symbolTable); + handleDeclareOp(declOp, fileAttr, spTy, typeGen, symbolTable, dummyScope); }); // commonBlockMap ensures that we don't create multiple DICommonBlockAttr of // the same name in one function. But it is ok (rather required) to create diff --git a/flang/lib/Optimizer/Transforms/CMakeLists.txt b/flang/lib/Optimizer/Transforms/CMakeLists.txt index 0388439..619f3adc 100644 --- a/flang/lib/Optimizer/Transforms/CMakeLists.txt +++ b/flang/lib/Optimizer/Transforms/CMakeLists.txt @@ -9,6 +9,7 @@ add_flang_library(FIRTransforms CompilerGeneratedNames.cpp ConstantArgumentGlobalisation.cpp ControlFlowConverter.cpp + CUDA/CUFAllocationConversion.cpp CUFAddConstructor.cpp CUFDeviceGlobal.cpp CUFOpConversion.cpp diff --git a/flang/lib/Optimizer/Transforms/CUDA/CUFAllocationConversion.cpp b/flang/lib/Optimizer/Transforms/CUDA/CUFAllocationConversion.cpp new file mode 100644 index 0000000..6579c23 --- /dev/null +++ b/flang/lib/Optimizer/Transforms/CUDA/CUFAllocationConversion.cpp @@ -0,0 +1,438 @@ +//===-- CUFAllocationConversion.cpp ---------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "flang/Optimizer/Transforms/CUDA/CUFAllocationConversion.h" +#include "flang/Optimizer/Builder/CUFCommon.h" +#include "flang/Optimizer/Builder/FIRBuilder.h" +#include "flang/Optimizer/Builder/Runtime/CUDA/Descriptor.h" +#include "flang/Optimizer/Builder/Runtime/RTBuilder.h" +#include "flang/Optimizer/CodeGen/TypeConverter.h" +#include "flang/Optimizer/Dialect/CUF/CUFOps.h" +#include "flang/Optimizer/Dialect/FIRDialect.h" +#include "flang/Optimizer/Dialect/FIROps.h" +#include "flang/Optimizer/HLFIR/HLFIROps.h" +#include "flang/Optimizer/Support/DataLayout.h" +#include "flang/Runtime/CUDA/allocatable.h" +#include "flang/Runtime/CUDA/common.h" +#include "flang/Runtime/CUDA/descriptor.h" +#include "flang/Runtime/CUDA/memory.h" +#include "flang/Runtime/CUDA/pointer.h" +#include "flang/Runtime/allocatable.h" +#include "flang/Runtime/allocator-registry-consts.h" +#include "flang/Support/Fortran.h" +#include "mlir/Dialect/Func/IR/FuncOps.h" +#include "mlir/IR/Matchers.h" +#include "mlir/Pass/Pass.h" +#include "mlir/Transforms/DialectConversion.h" +#include "mlir/Transforms/GreedyPatternRewriteDriver.h" + +namespace fir { +#define GEN_PASS_DEF_CUFALLOCATIONCONVERSION +#include "flang/Optimizer/Transforms/Passes.h.inc" +} // namespace fir + +using namespace fir; +using namespace mlir; +using namespace Fortran::runtime; +using namespace Fortran::runtime::cuda; + +namespace { + +template <typename OpTy> +static bool isPinned(OpTy op) { + if (op.getDataAttr() && *op.getDataAttr() == cuf::DataAttribute::Pinned) + return true; + return false; +} + +static inline unsigned getMemType(cuf::DataAttribute attr) { + if (attr == cuf::DataAttribute::Device) + return kMemTypeDevice; + if (attr == cuf::DataAttribute::Managed) + return kMemTypeManaged; + if (attr == cuf::DataAttribute::Pinned) + return kMemTypePinned; + if (attr == cuf::DataAttribute::Unified) + return kMemTypeUnified; + llvm_unreachable("unsupported memory type"); +} + +static bool inDeviceContext(mlir::Operation *op) { + if (op->getParentOfType<cuf::KernelOp>()) + return true; + if (auto funcOp = op->getParentOfType<mlir::gpu::GPUFuncOp>()) + return true; + if (auto funcOp = op->getParentOfType<mlir::gpu::LaunchOp>()) + return true; + if (auto funcOp = op->getParentOfType<mlir::func::FuncOp>()) { + if (auto cudaProcAttr = + funcOp.getOperation()->getAttrOfType<cuf::ProcAttributeAttr>( + cuf::getProcAttrName())) { + return cudaProcAttr.getValue() != cuf::ProcAttribute::Host && + cudaProcAttr.getValue() != cuf::ProcAttribute::HostDevice; + } + } + return false; +} + +template <typename OpTy> +static mlir::LogicalResult convertOpToCall(OpTy op, + mlir::PatternRewriter &rewriter, + mlir::func::FuncOp func) { + auto mod = op->template getParentOfType<mlir::ModuleOp>(); + fir::FirOpBuilder builder(rewriter, mod); + mlir::Location loc = op.getLoc(); + auto fTy = func.getFunctionType(); + + mlir::Value sourceFile = fir::factory::locationToFilename(builder, loc); + mlir::Value sourceLine; + if constexpr (std::is_same_v<OpTy, cuf::AllocateOp>) + sourceLine = fir::factory::locationToLineNo( + builder, loc, op.getSource() ? fTy.getInput(7) : fTy.getInput(6)); + else + sourceLine = fir::factory::locationToLineNo(builder, loc, fTy.getInput(4)); + + mlir::Value hasStat = op.getHasStat() ? builder.createBool(loc, true) + : builder.createBool(loc, false); + + mlir::Value errmsg; + if (op.getErrmsg()) { + errmsg = op.getErrmsg(); + } else { + mlir::Type boxNoneTy = fir::BoxType::get(builder.getNoneType()); + errmsg = fir::AbsentOp::create(builder, loc, boxNoneTy).getResult(); + } + llvm::SmallVector<mlir::Value> args; + if constexpr (std::is_same_v<OpTy, cuf::AllocateOp>) { + mlir::Value pinned = + op.getPinned() + ? op.getPinned() + : builder.createNullConstant( + loc, fir::ReferenceType::get( + mlir::IntegerType::get(op.getContext(), 1))); + if (op.getSource()) { + mlir::Value stream = + op.getStream() ? op.getStream() + : builder.createNullConstant(loc, fTy.getInput(2)); + args = fir::runtime::createArguments( + builder, loc, fTy, op.getBox(), op.getSource(), stream, pinned, + hasStat, errmsg, sourceFile, sourceLine); + } else { + mlir::Value stream = + op.getStream() ? op.getStream() + : builder.createNullConstant(loc, fTy.getInput(1)); + args = fir::runtime::createArguments(builder, loc, fTy, op.getBox(), + stream, pinned, hasStat, errmsg, + sourceFile, sourceLine); + } + } else { + args = + fir::runtime::createArguments(builder, loc, fTy, op.getBox(), hasStat, + errmsg, sourceFile, sourceLine); + } + auto callOp = fir::CallOp::create(builder, loc, func, args); + rewriter.replaceOp(op, callOp); + return mlir::success(); +} + +struct CUFAllocOpConversion : public mlir::OpRewritePattern<cuf::AllocOp> { + using OpRewritePattern::OpRewritePattern; + + CUFAllocOpConversion(mlir::MLIRContext *context, mlir::DataLayout *dl, + const fir::LLVMTypeConverter *typeConverter) + : OpRewritePattern(context), dl{dl}, typeConverter{typeConverter} {} + + mlir::LogicalResult + matchAndRewrite(cuf::AllocOp op, + mlir::PatternRewriter &rewriter) const override { + + mlir::Location loc = op.getLoc(); + + if (inDeviceContext(op.getOperation())) { + // In device context just replace the cuf.alloc operation with a fir.alloc + // the cuf.free will be removed. + auto allocaOp = + fir::AllocaOp::create(rewriter, loc, op.getInType(), + op.getUniqName() ? *op.getUniqName() : "", + op.getBindcName() ? *op.getBindcName() : "", + op.getTypeparams(), op.getShape()); + allocaOp->setAttr(cuf::getDataAttrName(), op.getDataAttrAttr()); + rewriter.replaceOp(op, allocaOp); + return mlir::success(); + } + + auto mod = op->getParentOfType<mlir::ModuleOp>(); + fir::FirOpBuilder builder(rewriter, mod); + mlir::Value sourceFile = fir::factory::locationToFilename(builder, loc); + + if (!mlir::dyn_cast_or_null<fir::BaseBoxType>(op.getInType())) { + // Convert scalar and known size array allocations. + mlir::Value bytes; + fir::KindMapping kindMap{fir::getKindMapping(mod)}; + if (fir::isa_trivial(op.getInType())) { + int width = cuf::computeElementByteSize(loc, op.getInType(), kindMap); + bytes = + builder.createIntegerConstant(loc, builder.getIndexType(), width); + } else if (auto seqTy = mlir::dyn_cast_or_null<fir::SequenceType>( + op.getInType())) { + std::size_t size = 0; + if (fir::isa_derived(seqTy.getEleTy())) { + mlir::Type structTy = typeConverter->convertType(seqTy.getEleTy()); + size = dl->getTypeSizeInBits(structTy) / 8; + } else { + size = cuf::computeElementByteSize(loc, seqTy.getEleTy(), kindMap); + } + mlir::Value width = + builder.createIntegerConstant(loc, builder.getIndexType(), size); + mlir::Value nbElem; + if (fir::sequenceWithNonConstantShape(seqTy)) { + assert(!op.getShape().empty() && "expect shape with dynamic arrays"); + nbElem = builder.loadIfRef(loc, op.getShape()[0]); + for (unsigned i = 1; i < op.getShape().size(); ++i) { + nbElem = mlir::arith::MulIOp::create( + rewriter, loc, nbElem, + builder.loadIfRef(loc, op.getShape()[i])); + } + } else { + nbElem = builder.createIntegerConstant(loc, builder.getIndexType(), + seqTy.getConstantArraySize()); + } + bytes = mlir::arith::MulIOp::create(rewriter, loc, nbElem, width); + } else if (fir::isa_derived(op.getInType())) { + mlir::Type structTy = typeConverter->convertType(op.getInType()); + std::size_t structSize = dl->getTypeSizeInBits(structTy) / 8; + bytes = builder.createIntegerConstant(loc, builder.getIndexType(), + structSize); + } else if (fir::isa_char(op.getInType())) { + mlir::Type charTy = typeConverter->convertType(op.getInType()); + std::size_t charSize = dl->getTypeSizeInBits(charTy) / 8; + bytes = builder.createIntegerConstant(loc, builder.getIndexType(), + charSize); + } else { + mlir::emitError(loc, "unsupported type in cuf.alloc\n"); + } + mlir::func::FuncOp func = + fir::runtime::getRuntimeFunc<mkRTKey(CUFMemAlloc)>(loc, builder); + auto fTy = func.getFunctionType(); + mlir::Value sourceLine = + fir::factory::locationToLineNo(builder, loc, fTy.getInput(3)); + mlir::Value memTy = builder.createIntegerConstant( + loc, builder.getI32Type(), getMemType(op.getDataAttr())); + llvm::SmallVector<mlir::Value> args{fir::runtime::createArguments( + builder, loc, fTy, bytes, memTy, sourceFile, sourceLine)}; + auto callOp = fir::CallOp::create(builder, loc, func, args); + callOp->setAttr(cuf::getDataAttrName(), op.getDataAttrAttr()); + auto convOp = builder.createConvert(loc, op.getResult().getType(), + callOp.getResult(0)); + rewriter.replaceOp(op, convOp); + return mlir::success(); + } + + // Convert descriptor allocations to function call. + auto boxTy = mlir::dyn_cast_or_null<fir::BaseBoxType>(op.getInType()); + mlir::func::FuncOp func = + fir::runtime::getRuntimeFunc<mkRTKey(CUFAllocDescriptor)>(loc, builder); + auto fTy = func.getFunctionType(); + mlir::Value sourceLine = + fir::factory::locationToLineNo(builder, loc, fTy.getInput(2)); + + mlir::Type structTy = typeConverter->convertBoxTypeAsStruct(boxTy); + std::size_t boxSize = dl->getTypeSizeInBits(structTy) / 8; + mlir::Value sizeInBytes = + builder.createIntegerConstant(loc, builder.getIndexType(), boxSize); + + llvm::SmallVector<mlir::Value> args{fir::runtime::createArguments( + builder, loc, fTy, sizeInBytes, sourceFile, sourceLine)}; + auto callOp = fir::CallOp::create(builder, loc, func, args); + callOp->setAttr(cuf::getDataAttrName(), op.getDataAttrAttr()); + auto convOp = builder.createConvert(loc, op.getResult().getType(), + callOp.getResult(0)); + rewriter.replaceOp(op, convOp); + return mlir::success(); + } + +private: + mlir::DataLayout *dl; + const fir::LLVMTypeConverter *typeConverter; +}; + +struct CUFFreeOpConversion : public mlir::OpRewritePattern<cuf::FreeOp> { + using OpRewritePattern::OpRewritePattern; + + mlir::LogicalResult + matchAndRewrite(cuf::FreeOp op, + mlir::PatternRewriter &rewriter) const override { + if (inDeviceContext(op.getOperation())) { + rewriter.eraseOp(op); + return mlir::success(); + } + + if (!mlir::isa<fir::ReferenceType>(op.getDevptr().getType())) + return failure(); + + auto mod = op->getParentOfType<mlir::ModuleOp>(); + fir::FirOpBuilder builder(rewriter, mod); + mlir::Location loc = op.getLoc(); + mlir::Value sourceFile = fir::factory::locationToFilename(builder, loc); + + auto refTy = mlir::dyn_cast<fir::ReferenceType>(op.getDevptr().getType()); + if (!mlir::isa<fir::BaseBoxType>(refTy.getEleTy())) { + mlir::func::FuncOp func = + fir::runtime::getRuntimeFunc<mkRTKey(CUFMemFree)>(loc, builder); + auto fTy = func.getFunctionType(); + mlir::Value sourceLine = + fir::factory::locationToLineNo(builder, loc, fTy.getInput(3)); + mlir::Value memTy = builder.createIntegerConstant( + loc, builder.getI32Type(), getMemType(op.getDataAttr())); + llvm::SmallVector<mlir::Value> args{fir::runtime::createArguments( + builder, loc, fTy, op.getDevptr(), memTy, sourceFile, sourceLine)}; + fir::CallOp::create(builder, loc, func, args); + rewriter.eraseOp(op); + return mlir::success(); + } + + // Convert cuf.free on descriptors. + mlir::func::FuncOp func = + fir::runtime::getRuntimeFunc<mkRTKey(CUFFreeDescriptor)>(loc, builder); + auto fTy = func.getFunctionType(); + mlir::Value sourceLine = + fir::factory::locationToLineNo(builder, loc, fTy.getInput(2)); + llvm::SmallVector<mlir::Value> args{fir::runtime::createArguments( + builder, loc, fTy, op.getDevptr(), sourceFile, sourceLine)}; + auto callOp = fir::CallOp::create(builder, loc, func, args); + callOp->setAttr(cuf::getDataAttrName(), op.getDataAttrAttr()); + rewriter.eraseOp(op); + return mlir::success(); + } +}; + +struct CUFAllocateOpConversion + : public mlir::OpRewritePattern<cuf::AllocateOp> { + using OpRewritePattern::OpRewritePattern; + + mlir::LogicalResult + matchAndRewrite(cuf::AllocateOp op, + mlir::PatternRewriter &rewriter) const override { + auto mod = op->getParentOfType<mlir::ModuleOp>(); + fir::FirOpBuilder builder(rewriter, mod); + mlir::Location loc = op.getLoc(); + + bool isPointer = op.getPointer(); + if (op.getHasDoubleDescriptor()) { + // Allocation for module variable are done with custom runtime entry point + // so the descriptors can be synchronized. + mlir::func::FuncOp func; + if (op.getSource()) { + func = isPointer ? fir::runtime::getRuntimeFunc<mkRTKey( + CUFPointerAllocateSourceSync)>(loc, builder) + : fir::runtime::getRuntimeFunc<mkRTKey( + CUFAllocatableAllocateSourceSync)>(loc, builder); + } else { + func = + isPointer + ? fir::runtime::getRuntimeFunc<mkRTKey(CUFPointerAllocateSync)>( + loc, builder) + : fir::runtime::getRuntimeFunc<mkRTKey( + CUFAllocatableAllocateSync)>(loc, builder); + } + return convertOpToCall<cuf::AllocateOp>(op, rewriter, func); + } + + mlir::func::FuncOp func; + if (op.getSource()) { + func = + isPointer + ? fir::runtime::getRuntimeFunc<mkRTKey(CUFPointerAllocateSource)>( + loc, builder) + : fir::runtime::getRuntimeFunc<mkRTKey( + CUFAllocatableAllocateSource)>(loc, builder); + } else { + func = + isPointer + ? fir::runtime::getRuntimeFunc<mkRTKey(CUFPointerAllocate)>( + loc, builder) + : fir::runtime::getRuntimeFunc<mkRTKey(CUFAllocatableAllocate)>( + loc, builder); + } + + return convertOpToCall<cuf::AllocateOp>(op, rewriter, func); + } +}; + +struct CUFDeallocateOpConversion + : public mlir::OpRewritePattern<cuf::DeallocateOp> { + using OpRewritePattern::OpRewritePattern; + + mlir::LogicalResult + matchAndRewrite(cuf::DeallocateOp op, + mlir::PatternRewriter &rewriter) const override { + + auto mod = op->getParentOfType<mlir::ModuleOp>(); + fir::FirOpBuilder builder(rewriter, mod); + mlir::Location loc = op.getLoc(); + + if (op.getHasDoubleDescriptor()) { + // Deallocation for module variable are done with custom runtime entry + // point so the descriptors can be synchronized. + mlir::func::FuncOp func = + fir::runtime::getRuntimeFunc<mkRTKey(CUFAllocatableDeallocate)>( + loc, builder); + return convertOpToCall<cuf::DeallocateOp>(op, rewriter, func); + } + + // Deallocation for local descriptor falls back on the standard runtime + // AllocatableDeallocate as the dedicated deallocator is set in the + // descriptor before the call. + mlir::func::FuncOp func = + fir::runtime::getRuntimeFunc<mkRTKey(AllocatableDeallocate)>(loc, + builder); + return convertOpToCall<cuf::DeallocateOp>(op, rewriter, func); + } +}; + +class CUFAllocationConversion + : public fir::impl::CUFAllocationConversionBase<CUFAllocationConversion> { +public: + void runOnOperation() override { + auto *ctx = &getContext(); + mlir::RewritePatternSet patterns(ctx); + mlir::ConversionTarget target(*ctx); + + mlir::Operation *op = getOperation(); + mlir::ModuleOp module = mlir::dyn_cast<mlir::ModuleOp>(op); + if (!module) + return signalPassFailure(); + mlir::SymbolTable symtab(module); + + std::optional<mlir::DataLayout> dl = fir::support::getOrSetMLIRDataLayout( + module, /*allowDefaultLayout=*/false); + fir::LLVMTypeConverter typeConverter(module, /*applyTBAA=*/false, + /*forceUnifiedTBAATree=*/false, *dl); + target.addLegalDialect<fir::FIROpsDialect, mlir::arith::ArithDialect, + mlir::gpu::GPUDialect>(); + target.addLegalOp<cuf::StreamCastOp>(); + cuf::populateCUFAllocationConversionPatterns(typeConverter, *dl, symtab, + patterns); + if (mlir::failed(mlir::applyPartialConversion(getOperation(), target, + std::move(patterns)))) { + mlir::emitError(mlir::UnknownLoc::get(ctx), + "error in CUF allocation conversion\n"); + signalPassFailure(); + } + } +}; + +} // namespace + +void cuf::populateCUFAllocationConversionPatterns( + const fir::LLVMTypeConverter &converter, mlir::DataLayout &dl, + const mlir::SymbolTable &symtab, mlir::RewritePatternSet &patterns) { + patterns.insert<CUFAllocOpConversion>(patterns.getContext(), &dl, &converter); + patterns.insert<CUFFreeOpConversion, CUFAllocateOpConversion, + CUFDeallocateOpConversion>(patterns.getContext()); +} diff --git a/flang/lib/Optimizer/Transforms/CUFComputeSharedMemoryOffsetsAndSize.cpp b/flang/lib/Optimizer/Transforms/CUFComputeSharedMemoryOffsetsAndSize.cpp index 09126e0..7bae060 100644 --- a/flang/lib/Optimizer/Transforms/CUFComputeSharedMemoryOffsetsAndSize.cpp +++ b/flang/lib/Optimizer/Transforms/CUFComputeSharedMemoryOffsetsAndSize.cpp @@ -41,12 +41,48 @@ namespace { static bool isAssumedSize(mlir::ValueRange shape) { if (shape.size() != 1) return false; - std::optional<std::int64_t> val = fir::getIntIfConstant(shape[0]); - if (val && *val == -1) + if (llvm::isa_and_nonnull<fir::AssumedSizeExtentOp>(shape[0].getDefiningOp())) return true; return false; } +static void createSharedMemoryGlobal(fir::FirOpBuilder &builder, + mlir::Location loc, llvm::StringRef prefix, + llvm::StringRef suffix, + mlir::gpu::GPUModuleOp gpuMod, + mlir::Type sharedMemType, unsigned size, + unsigned align, bool isDynamic) { + std::string sharedMemGlobalName = + isDynamic ? (prefix + llvm::Twine(cudaSharedMemSuffix)).str() + : (prefix + llvm::Twine(cudaSharedMemSuffix) + suffix).str(); + + mlir::OpBuilder::InsertionGuard guard(builder); + builder.setInsertionPointToEnd(gpuMod.getBody()); + + mlir::StringAttr linkage = isDynamic ? builder.createExternalLinkage() + : builder.createInternalLinkage(); + llvm::SmallVector<mlir::NamedAttribute> attrs; + auto globalOpName = mlir::OperationName(fir::GlobalOp::getOperationName(), + gpuMod.getContext()); + attrs.push_back(mlir::NamedAttribute( + fir::GlobalOp::getDataAttrAttrName(globalOpName), + cuf::DataAttributeAttr::get(gpuMod.getContext(), + cuf::DataAttribute::Shared))); + + mlir::DenseElementsAttr init = {}; + mlir::Type i8Ty = builder.getI8Type(); + if (size > 0) { + auto vecTy = mlir::VectorType::get( + static_cast<fir::SequenceType::Extent>(size), i8Ty); + mlir::Attribute zero = mlir::IntegerAttr::get(i8Ty, 0); + init = mlir::DenseElementsAttr::get(vecTy, llvm::ArrayRef(zero)); + } + auto sharedMem = + fir::GlobalOp::create(builder, loc, sharedMemGlobalName, false, false, + sharedMemType, init, linkage, attrs); + sharedMem.setAlignment(align); +} + struct CUFComputeSharedMemoryOffsetsAndSize : public fir::impl::CUFComputeSharedMemoryOffsetsAndSizeBase< CUFComputeSharedMemoryOffsetsAndSize> { @@ -109,18 +145,23 @@ struct CUFComputeSharedMemoryOffsetsAndSize crtDynOffset, dynSize); else crtDynOffset = dynSize; - - continue; + } else { + // Static shared memory. + auto [size, align] = fir::getTypeSizeAndAlignmentOrCrash( + loc, sharedOp.getInType(), *dl, kindMap); + createSharedMemoryGlobal( + builder, sharedOp.getLoc(), funcOp.getName(), + *sharedOp.getBindcName(), gpuMod, + fir::SequenceType::get(size, i8Ty), size, + sharedOp.getAlignment() ? *sharedOp.getAlignment() : align, + /*isDynamic=*/false); + mlir::Value zero = builder.createIntegerConstant(loc, i32Ty, 0); + sharedOp.getOffsetMutable().assign(zero); + if (!sharedOp.getAlignment()) + sharedOp.setAlignment(align); + sharedOp.setIsStatic(true); + ++nbStaticSharedVariables; } - auto [size, align] = fir::getTypeSizeAndAlignmentOrCrash( - sharedOp.getLoc(), sharedOp.getInType(), *dl, kindMap); - ++nbStaticSharedVariables; - mlir::Value offset = builder.createIntegerConstant( - loc, i32Ty, llvm::alignTo(sharedMemSize, align)); - sharedOp.getOffsetMutable().assign(offset); - sharedMemSize = - llvm::alignTo(sharedMemSize, align) + llvm::alignTo(size, align); - alignment = std::max(alignment, align); } if (nbDynamicSharedVariables == 0 && nbStaticSharedVariables == 0) @@ -131,35 +172,13 @@ struct CUFComputeSharedMemoryOffsetsAndSize funcOp.getLoc(), "static and dynamic shared variables in a single kernel"); - mlir::DenseElementsAttr init = {}; - if (sharedMemSize > 0) { - auto vecTy = mlir::VectorType::get(sharedMemSize, i8Ty); - mlir::Attribute zero = mlir::IntegerAttr::get(i8Ty, 0); - init = mlir::DenseElementsAttr::get(vecTy, llvm::ArrayRef(zero)); - } + if (nbStaticSharedVariables > 0) + continue; - // Create the shared memory global where each shared variable will point - // to. auto sharedMemType = fir::SequenceType::get(sharedMemSize, i8Ty); - std::string sharedMemGlobalName = - (funcOp.getName() + llvm::Twine(cudaSharedMemSuffix)).str(); - // Dynamic shared memory needs an external linkage while static shared - // memory needs an internal linkage. - mlir::StringAttr linkage = nbDynamicSharedVariables > 0 - ? builder.createExternalLinkage() - : builder.createInternalLinkage(); - builder.setInsertionPointToEnd(gpuMod.getBody()); - llvm::SmallVector<mlir::NamedAttribute> attrs; - auto globalOpName = mlir::OperationName(fir::GlobalOp::getOperationName(), - gpuMod.getContext()); - attrs.push_back(mlir::NamedAttribute( - fir::GlobalOp::getDataAttrAttrName(globalOpName), - cuf::DataAttributeAttr::get(gpuMod.getContext(), - cuf::DataAttribute::Shared))); - auto sharedMem = fir::GlobalOp::create( - builder, funcOp.getLoc(), sharedMemGlobalName, false, false, - sharedMemType, init, linkage, attrs); - sharedMem.setAlignment(alignment); + createSharedMemoryGlobal(builder, funcOp.getLoc(), funcOp.getName(), "", + gpuMod, sharedMemType, sharedMemSize, alignment, + /*isDynamic=*/true); } } }; diff --git a/flang/lib/Optimizer/Transforms/CUFGPUToLLVMConversion.cpp b/flang/lib/Optimizer/Transforms/CUFGPUToLLVMConversion.cpp index 40f180a..d5a8212 100644 --- a/flang/lib/Optimizer/Transforms/CUFGPUToLLVMConversion.cpp +++ b/flang/lib/Optimizer/Transforms/CUFGPUToLLVMConversion.cpp @@ -249,8 +249,13 @@ struct CUFSharedMemoryOpConversion "cuf.shared_memory must have an offset for code gen"); auto gpuMod = op->getParentOfType<gpu::GPUModuleOp>(); + std::string sharedGlobalName = - (getFuncName(op) + llvm::Twine(cudaSharedMemSuffix)).str(); + op.getIsStatic() + ? (getFuncName(op) + llvm::Twine(cudaSharedMemSuffix) + + *op.getBindcName()) + .str() + : (getFuncName(op) + llvm::Twine(cudaSharedMemSuffix)).str(); mlir::Value sharedGlobalAddr = createAddressOfOp(rewriter, loc, gpuMod, sharedGlobalName); diff --git a/flang/lib/Optimizer/Transforms/CUFOpConversion.cpp b/flang/lib/Optimizer/Transforms/CUFOpConversion.cpp index 8d00272..424a8fd 100644 --- a/flang/lib/Optimizer/Transforms/CUFOpConversion.cpp +++ b/flang/lib/Optimizer/Transforms/CUFOpConversion.cpp @@ -16,6 +16,8 @@ #include "flang/Optimizer/Dialect/FIROps.h" #include "flang/Optimizer/HLFIR/HLFIROps.h" #include "flang/Optimizer/Support/DataLayout.h" +#include "flang/Optimizer/Transforms/CUDA/CUFAllocationConversion.h" +#include "flang/Optimizer/Transforms/Passes.h" #include "flang/Runtime/CUDA/allocatable.h" #include "flang/Runtime/CUDA/common.h" #include "flang/Runtime/CUDA/descriptor.h" @@ -44,207 +46,6 @@ using namespace Fortran::runtime::cuda; namespace { -static inline unsigned getMemType(cuf::DataAttribute attr) { - if (attr == cuf::DataAttribute::Device) - return kMemTypeDevice; - if (attr == cuf::DataAttribute::Managed) - return kMemTypeManaged; - if (attr == cuf::DataAttribute::Unified) - return kMemTypeUnified; - if (attr == cuf::DataAttribute::Pinned) - return kMemTypePinned; - llvm::report_fatal_error("unsupported memory type"); -} - -template <typename OpTy> -static bool isPinned(OpTy op) { - if (op.getDataAttr() && *op.getDataAttr() == cuf::DataAttribute::Pinned) - return true; - return false; -} - -template <typename OpTy> -static bool hasDoubleDescriptors(OpTy op) { - if (auto declareOp = - mlir::dyn_cast_or_null<fir::DeclareOp>(op.getBox().getDefiningOp())) { - if (mlir::isa_and_nonnull<fir::AddrOfOp>( - declareOp.getMemref().getDefiningOp())) { - if (isPinned(declareOp)) - return false; - return true; - } - } else if (auto declareOp = mlir::dyn_cast_or_null<hlfir::DeclareOp>( - op.getBox().getDefiningOp())) { - if (mlir::isa_and_nonnull<fir::AddrOfOp>( - declareOp.getMemref().getDefiningOp())) { - if (isPinned(declareOp)) - return false; - return true; - } - } - return false; -} - -static mlir::Value createConvertOp(mlir::PatternRewriter &rewriter, - mlir::Location loc, mlir::Type toTy, - mlir::Value val) { - if (val.getType() != toTy) - return fir::ConvertOp::create(rewriter, loc, toTy, val); - return val; -} - -template <typename OpTy> -static mlir::LogicalResult convertOpToCall(OpTy op, - mlir::PatternRewriter &rewriter, - mlir::func::FuncOp func) { - auto mod = op->template getParentOfType<mlir::ModuleOp>(); - fir::FirOpBuilder builder(rewriter, mod); - mlir::Location loc = op.getLoc(); - auto fTy = func.getFunctionType(); - - mlir::Value sourceFile = fir::factory::locationToFilename(builder, loc); - mlir::Value sourceLine; - if constexpr (std::is_same_v<OpTy, cuf::AllocateOp>) - sourceLine = fir::factory::locationToLineNo( - builder, loc, op.getSource() ? fTy.getInput(7) : fTy.getInput(6)); - else - sourceLine = fir::factory::locationToLineNo(builder, loc, fTy.getInput(4)); - - mlir::Value hasStat = op.getHasStat() ? builder.createBool(loc, true) - : builder.createBool(loc, false); - - mlir::Value errmsg; - if (op.getErrmsg()) { - errmsg = op.getErrmsg(); - } else { - mlir::Type boxNoneTy = fir::BoxType::get(builder.getNoneType()); - errmsg = fir::AbsentOp::create(builder, loc, boxNoneTy).getResult(); - } - llvm::SmallVector<mlir::Value> args; - if constexpr (std::is_same_v<OpTy, cuf::AllocateOp>) { - mlir::Value pinned = - op.getPinned() - ? op.getPinned() - : builder.createNullConstant( - loc, fir::ReferenceType::get( - mlir::IntegerType::get(op.getContext(), 1))); - if (op.getSource()) { - mlir::Value stream = - op.getStream() ? op.getStream() - : builder.createNullConstant(loc, fTy.getInput(2)); - args = fir::runtime::createArguments( - builder, loc, fTy, op.getBox(), op.getSource(), stream, pinned, - hasStat, errmsg, sourceFile, sourceLine); - } else { - mlir::Value stream = - op.getStream() ? op.getStream() - : builder.createNullConstant(loc, fTy.getInput(1)); - args = fir::runtime::createArguments(builder, loc, fTy, op.getBox(), - stream, pinned, hasStat, errmsg, - sourceFile, sourceLine); - } - } else { - args = - fir::runtime::createArguments(builder, loc, fTy, op.getBox(), hasStat, - errmsg, sourceFile, sourceLine); - } - auto callOp = fir::CallOp::create(builder, loc, func, args); - rewriter.replaceOp(op, callOp); - return mlir::success(); -} - -struct CUFAllocateOpConversion - : public mlir::OpRewritePattern<cuf::AllocateOp> { - using OpRewritePattern::OpRewritePattern; - - mlir::LogicalResult - matchAndRewrite(cuf::AllocateOp op, - mlir::PatternRewriter &rewriter) const override { - auto mod = op->getParentOfType<mlir::ModuleOp>(); - fir::FirOpBuilder builder(rewriter, mod); - mlir::Location loc = op.getLoc(); - - bool isPointer = false; - - if (auto declareOp = - mlir::dyn_cast_or_null<fir::DeclareOp>(op.getBox().getDefiningOp())) - if (declareOp.getFortranAttrs() && - bitEnumContainsAny(*declareOp.getFortranAttrs(), - fir::FortranVariableFlagsEnum::pointer)) - isPointer = true; - - if (hasDoubleDescriptors(op)) { - // Allocation for module variable are done with custom runtime entry point - // so the descriptors can be synchronized. - mlir::func::FuncOp func; - if (op.getSource()) { - func = isPointer ? fir::runtime::getRuntimeFunc<mkRTKey( - CUFPointerAllocateSourceSync)>(loc, builder) - : fir::runtime::getRuntimeFunc<mkRTKey( - CUFAllocatableAllocateSourceSync)>(loc, builder); - } else { - func = - isPointer - ? fir::runtime::getRuntimeFunc<mkRTKey(CUFPointerAllocateSync)>( - loc, builder) - : fir::runtime::getRuntimeFunc<mkRTKey( - CUFAllocatableAllocateSync)>(loc, builder); - } - return convertOpToCall<cuf::AllocateOp>(op, rewriter, func); - } - - mlir::func::FuncOp func; - if (op.getSource()) { - func = - isPointer - ? fir::runtime::getRuntimeFunc<mkRTKey(CUFPointerAllocateSource)>( - loc, builder) - : fir::runtime::getRuntimeFunc<mkRTKey( - CUFAllocatableAllocateSource)>(loc, builder); - } else { - func = - isPointer - ? fir::runtime::getRuntimeFunc<mkRTKey(CUFPointerAllocate)>( - loc, builder) - : fir::runtime::getRuntimeFunc<mkRTKey(CUFAllocatableAllocate)>( - loc, builder); - } - - return convertOpToCall<cuf::AllocateOp>(op, rewriter, func); - } -}; - -struct CUFDeallocateOpConversion - : public mlir::OpRewritePattern<cuf::DeallocateOp> { - using OpRewritePattern::OpRewritePattern; - - mlir::LogicalResult - matchAndRewrite(cuf::DeallocateOp op, - mlir::PatternRewriter &rewriter) const override { - - auto mod = op->getParentOfType<mlir::ModuleOp>(); - fir::FirOpBuilder builder(rewriter, mod); - mlir::Location loc = op.getLoc(); - - if (hasDoubleDescriptors(op)) { - // Deallocation for module variable are done with custom runtime entry - // point so the descriptors can be synchronized. - mlir::func::FuncOp func = - fir::runtime::getRuntimeFunc<mkRTKey(CUFAllocatableDeallocate)>( - loc, builder); - return convertOpToCall<cuf::DeallocateOp>(op, rewriter, func); - } - - // Deallocation for local descriptor falls back on the standard runtime - // AllocatableDeallocate as the dedicated deallocator is set in the - // descriptor before the call. - mlir::func::FuncOp func = - fir::runtime::getRuntimeFunc<mkRTKey(AllocatableDeallocate)>(loc, - builder); - return convertOpToCall<cuf::DeallocateOp>(op, rewriter, func); - } -}; - static bool inDeviceContext(mlir::Operation *op) { if (op->getParentOfType<cuf::KernelOp>()) return true; @@ -263,144 +64,14 @@ static bool inDeviceContext(mlir::Operation *op) { return false; } -static int computeWidth(mlir::Location loc, mlir::Type type, - fir::KindMapping &kindMap) { - auto eleTy = fir::unwrapSequenceType(type); - if (auto t{mlir::dyn_cast<mlir::IntegerType>(eleTy)}) - return t.getWidth() / 8; - if (auto t{mlir::dyn_cast<mlir::FloatType>(eleTy)}) - return t.getWidth() / 8; - if (eleTy.isInteger(1)) - return 1; - if (auto t{mlir::dyn_cast<fir::LogicalType>(eleTy)}) - return kindMap.getLogicalBitsize(t.getFKind()) / 8; - if (auto t{mlir::dyn_cast<mlir::ComplexType>(eleTy)}) { - int elemSize = - mlir::cast<mlir::FloatType>(t.getElementType()).getWidth() / 8; - return 2 * elemSize; - } - if (auto t{mlir::dyn_cast_or_null<fir::CharacterType>(eleTy)}) - return kindMap.getCharacterBitsize(t.getFKind()) / 8; - mlir::emitError(loc, "unsupported type"); - return 0; +static mlir::Value createConvertOp(mlir::PatternRewriter &rewriter, + mlir::Location loc, mlir::Type toTy, + mlir::Value val) { + if (val.getType() != toTy) + return fir::ConvertOp::create(rewriter, loc, toTy, val); + return val; } -struct CUFAllocOpConversion : public mlir::OpRewritePattern<cuf::AllocOp> { - using OpRewritePattern::OpRewritePattern; - - CUFAllocOpConversion(mlir::MLIRContext *context, mlir::DataLayout *dl, - const fir::LLVMTypeConverter *typeConverter) - : OpRewritePattern(context), dl{dl}, typeConverter{typeConverter} {} - - mlir::LogicalResult - matchAndRewrite(cuf::AllocOp op, - mlir::PatternRewriter &rewriter) const override { - - mlir::Location loc = op.getLoc(); - - if (inDeviceContext(op.getOperation())) { - // In device context just replace the cuf.alloc operation with a fir.alloc - // the cuf.free will be removed. - auto allocaOp = - fir::AllocaOp::create(rewriter, loc, op.getInType(), - op.getUniqName() ? *op.getUniqName() : "", - op.getBindcName() ? *op.getBindcName() : "", - op.getTypeparams(), op.getShape()); - allocaOp->setAttr(cuf::getDataAttrName(), op.getDataAttrAttr()); - rewriter.replaceOp(op, allocaOp); - return mlir::success(); - } - - auto mod = op->getParentOfType<mlir::ModuleOp>(); - fir::FirOpBuilder builder(rewriter, mod); - mlir::Value sourceFile = fir::factory::locationToFilename(builder, loc); - - if (!mlir::dyn_cast_or_null<fir::BaseBoxType>(op.getInType())) { - // Convert scalar and known size array allocations. - mlir::Value bytes; - fir::KindMapping kindMap{fir::getKindMapping(mod)}; - if (fir::isa_trivial(op.getInType())) { - int width = computeWidth(loc, op.getInType(), kindMap); - bytes = - builder.createIntegerConstant(loc, builder.getIndexType(), width); - } else if (auto seqTy = mlir::dyn_cast_or_null<fir::SequenceType>( - op.getInType())) { - std::size_t size = 0; - if (fir::isa_derived(seqTy.getEleTy())) { - mlir::Type structTy = typeConverter->convertType(seqTy.getEleTy()); - size = dl->getTypeSizeInBits(structTy) / 8; - } else { - size = computeWidth(loc, seqTy.getEleTy(), kindMap); - } - mlir::Value width = - builder.createIntegerConstant(loc, builder.getIndexType(), size); - mlir::Value nbElem; - if (fir::sequenceWithNonConstantShape(seqTy)) { - assert(!op.getShape().empty() && "expect shape with dynamic arrays"); - nbElem = builder.loadIfRef(loc, op.getShape()[0]); - for (unsigned i = 1; i < op.getShape().size(); ++i) { - nbElem = mlir::arith::MulIOp::create( - rewriter, loc, nbElem, - builder.loadIfRef(loc, op.getShape()[i])); - } - } else { - nbElem = builder.createIntegerConstant(loc, builder.getIndexType(), - seqTy.getConstantArraySize()); - } - bytes = mlir::arith::MulIOp::create(rewriter, loc, nbElem, width); - } else if (fir::isa_derived(op.getInType())) { - mlir::Type structTy = typeConverter->convertType(op.getInType()); - std::size_t structSize = dl->getTypeSizeInBits(structTy) / 8; - bytes = builder.createIntegerConstant(loc, builder.getIndexType(), - structSize); - } else { - mlir::emitError(loc, "unsupported type in cuf.alloc\n"); - } - mlir::func::FuncOp func = - fir::runtime::getRuntimeFunc<mkRTKey(CUFMemAlloc)>(loc, builder); - auto fTy = func.getFunctionType(); - mlir::Value sourceLine = - fir::factory::locationToLineNo(builder, loc, fTy.getInput(3)); - mlir::Value memTy = builder.createIntegerConstant( - loc, builder.getI32Type(), getMemType(op.getDataAttr())); - llvm::SmallVector<mlir::Value> args{fir::runtime::createArguments( - builder, loc, fTy, bytes, memTy, sourceFile, sourceLine)}; - auto callOp = fir::CallOp::create(builder, loc, func, args); - callOp->setAttr(cuf::getDataAttrName(), op.getDataAttrAttr()); - auto convOp = builder.createConvert(loc, op.getResult().getType(), - callOp.getResult(0)); - rewriter.replaceOp(op, convOp); - return mlir::success(); - } - - // Convert descriptor allocations to function call. - auto boxTy = mlir::dyn_cast_or_null<fir::BaseBoxType>(op.getInType()); - mlir::func::FuncOp func = - fir::runtime::getRuntimeFunc<mkRTKey(CUFAllocDescriptor)>(loc, builder); - auto fTy = func.getFunctionType(); - mlir::Value sourceLine = - fir::factory::locationToLineNo(builder, loc, fTy.getInput(2)); - - mlir::Type structTy = typeConverter->convertBoxTypeAsStruct(boxTy); - std::size_t boxSize = dl->getTypeSizeInBits(structTy) / 8; - mlir::Value sizeInBytes = - builder.createIntegerConstant(loc, builder.getIndexType(), boxSize); - - llvm::SmallVector<mlir::Value> args{fir::runtime::createArguments( - builder, loc, fTy, sizeInBytes, sourceFile, sourceLine)}; - auto callOp = fir::CallOp::create(builder, loc, func, args); - callOp->setAttr(cuf::getDataAttrName(), op.getDataAttrAttr()); - auto convOp = builder.createConvert(loc, op.getResult().getType(), - callOp.getResult(0)); - rewriter.replaceOp(op, convOp); - return mlir::success(); - } - -private: - mlir::DataLayout *dl; - const fir::LLVMTypeConverter *typeConverter; -}; - struct CUFDeviceAddressOpConversion : public mlir::OpRewritePattern<cuf::DeviceAddressOp> { using OpRewritePattern::OpRewritePattern; @@ -477,56 +148,6 @@ private: const mlir::SymbolTable &symTab; }; -struct CUFFreeOpConversion : public mlir::OpRewritePattern<cuf::FreeOp> { - using OpRewritePattern::OpRewritePattern; - - mlir::LogicalResult - matchAndRewrite(cuf::FreeOp op, - mlir::PatternRewriter &rewriter) const override { - if (inDeviceContext(op.getOperation())) { - rewriter.eraseOp(op); - return mlir::success(); - } - - if (!mlir::isa<fir::ReferenceType>(op.getDevptr().getType())) - return failure(); - - auto mod = op->getParentOfType<mlir::ModuleOp>(); - fir::FirOpBuilder builder(rewriter, mod); - mlir::Location loc = op.getLoc(); - mlir::Value sourceFile = fir::factory::locationToFilename(builder, loc); - - auto refTy = mlir::dyn_cast<fir::ReferenceType>(op.getDevptr().getType()); - if (!mlir::isa<fir::BaseBoxType>(refTy.getEleTy())) { - mlir::func::FuncOp func = - fir::runtime::getRuntimeFunc<mkRTKey(CUFMemFree)>(loc, builder); - auto fTy = func.getFunctionType(); - mlir::Value sourceLine = - fir::factory::locationToLineNo(builder, loc, fTy.getInput(3)); - mlir::Value memTy = builder.createIntegerConstant( - loc, builder.getI32Type(), getMemType(op.getDataAttr())); - llvm::SmallVector<mlir::Value> args{fir::runtime::createArguments( - builder, loc, fTy, op.getDevptr(), memTy, sourceFile, sourceLine)}; - fir::CallOp::create(builder, loc, func, args); - rewriter.eraseOp(op); - return mlir::success(); - } - - // Convert cuf.free on descriptors. - mlir::func::FuncOp func = - fir::runtime::getRuntimeFunc<mkRTKey(CUFFreeDescriptor)>(loc, builder); - auto fTy = func.getFunctionType(); - mlir::Value sourceLine = - fir::factory::locationToLineNo(builder, loc, fTy.getInput(2)); - llvm::SmallVector<mlir::Value> args{fir::runtime::createArguments( - builder, loc, fTy, op.getDevptr(), sourceFile, sourceLine)}; - auto callOp = fir::CallOp::create(builder, loc, func, args); - callOp->setAttr(cuf::getDataAttrName(), op.getDataAttrAttr()); - rewriter.eraseOp(op); - return mlir::success(); - } -}; - static bool isDstGlobal(cuf::DataTransferOp op) { if (auto declareOp = op.getDst().getDefiningOp<fir::DeclareOp>()) if (declareOp.getMemref().getDefiningOp<fir::AddrOfOp>()) @@ -673,38 +294,15 @@ struct CUFDataTransferOpConversion } mlir::Type i64Ty = builder.getI64Type(); - mlir::Value nbElement; - if (op.getShape()) { - llvm::SmallVector<mlir::Value> extents; - if (auto shapeOp = - mlir::dyn_cast<fir::ShapeOp>(op.getShape().getDefiningOp())) { - extents = shapeOp.getExtents(); - } else if (auto shapeShiftOp = mlir::dyn_cast<fir::ShapeShiftOp>( - op.getShape().getDefiningOp())) { - for (auto i : llvm::enumerate(shapeShiftOp.getPairs())) - if (i.index() & 1) - extents.push_back(i.value()); - } - - nbElement = fir::ConvertOp::create(rewriter, loc, i64Ty, extents[0]); - for (unsigned i = 1; i < extents.size(); ++i) { - auto operand = - fir::ConvertOp::create(rewriter, loc, i64Ty, extents[i]); - nbElement = - mlir::arith::MulIOp::create(rewriter, loc, nbElement, operand); - } - } else { - if (auto seqTy = mlir::dyn_cast_or_null<fir::SequenceType>(dstTy)) - nbElement = builder.createIntegerConstant( - loc, i64Ty, seqTy.getConstantArraySize()); - } + mlir::Value nbElement = + cuf::computeElementCount(rewriter, loc, op.getShape(), dstTy, i64Ty); unsigned width = 0; if (fir::isa_derived(fir::unwrapSequenceType(dstTy))) { mlir::Type structTy = typeConverter->convertType(fir::unwrapSequenceType(dstTy)); width = dl->getTypeSizeInBits(structTy) / 8; } else { - width = computeWidth(loc, dstTy, kindMap); + width = cuf::computeElementByteSize(loc, dstTy, kindMap); } mlir::Value widthValue = mlir::arith::ConstantOp::create( rewriter, loc, i64Ty, rewriter.getIntegerAttr(i64Ty, width)); @@ -936,6 +534,8 @@ struct CUFSyncDescriptorOpConversion }; class CUFOpConversion : public fir::impl::CUFOpConversionBase<CUFOpConversion> { + using CUFOpConversionBase::CUFOpConversionBase; + public: void runOnOperation() override { auto *ctx = &getContext(); @@ -957,6 +557,9 @@ public: target.addLegalOp<cuf::StreamCastOp>(); cuf::populateCUFToFIRConversionPatterns(typeConverter, *dl, symtab, patterns); + if (allocationConversion) + cuf::populateCUFAllocationConversionPatterns(typeConverter, *dl, symtab, + patterns); if (mlir::failed(mlir::applyPartialConversion(getOperation(), target, std::move(patterns)))) { mlir::emitError(mlir::UnknownLoc::get(ctx), @@ -996,10 +599,7 @@ public: void cuf::populateCUFToFIRConversionPatterns( const fir::LLVMTypeConverter &converter, mlir::DataLayout &dl, const mlir::SymbolTable &symtab, mlir::RewritePatternSet &patterns) { - patterns.insert<CUFAllocOpConversion>(patterns.getContext(), &dl, &converter); - patterns.insert<CUFAllocateOpConversion, CUFDeallocateOpConversion, - CUFFreeOpConversion, CUFSyncDescriptorOpConversion>( - patterns.getContext()); + patterns.insert<CUFSyncDescriptorOpConversion>(patterns.getContext()); patterns.insert<CUFDataTransferOpConversion>(patterns.getContext(), symtab, &dl, &converter); patterns.insert<CUFLaunchOpConversion, CUFDeviceAddressOpConversion>( diff --git a/flang/lib/Optimizer/Transforms/DebugTypeGenerator.cpp b/flang/lib/Optimizer/Transforms/DebugTypeGenerator.cpp index e1e6125..8019c39 100644 --- a/flang/lib/Optimizer/Transforms/DebugTypeGenerator.cpp +++ b/flang/lib/Optimizer/Transforms/DebugTypeGenerator.cpp @@ -718,6 +718,31 @@ DebugTypeGenerator::convertType(mlir::Type Ty, mlir::LLVM::DIFileAttr fileAttr, return convertRecordType(recTy, fileAttr, scope, declOp); } else if (auto tupleTy = mlir::dyn_cast_if_present<mlir::TupleType>(Ty)) { return convertTupleType(tupleTy, fileAttr, scope, declOp); + } else if (mlir::isa<mlir::FunctionType>(Ty)) { + // Handle function types - these represent procedure pointers after the + // BoxedProcedure pass has run and unwrapped the fir.boxproc type, as well + // as dummy procedures (which are represented as function types in FIR) + llvm::SmallVector<mlir::LLVM::DITypeAttr> types; + + auto funcTy = mlir::cast<mlir::FunctionType>(Ty); + // Add return type (or void if no return type) + if (funcTy.getNumResults() == 0) + types.push_back(mlir::LLVM::DINullTypeAttr::get(context)); + else + types.push_back( + convertType(funcTy.getResult(0), fileAttr, scope, declOp)); + + for (mlir::Type paramTy : funcTy.getInputs()) + types.push_back(convertType(paramTy, fileAttr, scope, declOp)); + + auto subroutineTy = mlir::LLVM::DISubroutineTypeAttr::get( + context, /*callingConvention=*/0, types); + + return mlir::LLVM::DIDerivedTypeAttr::get( + context, llvm::dwarf::DW_TAG_pointer_type, + mlir::StringAttr::get(context, ""), subroutineTy, + /*sizeInBits=*/ptrSize * 8, /*alignInBits=*/0, /*offset=*/0, + /*optional<address space>=*/std::nullopt, /*extra data=*/nullptr); } else if (auto refTy = mlir::dyn_cast_if_present<fir::ReferenceType>(Ty)) { auto elTy = refTy.getEleTy(); return convertPointerLikeType(elTy, fileAttr, scope, declOp, diff --git a/flang/lib/Optimizer/Transforms/FIRToSCF.cpp b/flang/lib/Optimizer/Transforms/FIRToSCF.cpp index 70d6ebb..d38bedc 100644 --- a/flang/lib/Optimizer/Transforms/FIRToSCF.cpp +++ b/flang/lib/Optimizer/Transforms/FIRToSCF.cpp @@ -18,6 +18,8 @@ namespace fir { namespace { class FIRToSCFPass : public fir::impl::FIRToSCFPassBase<FIRToSCFPass> { + using FIRToSCFPassBase::FIRToSCFPassBase; + public: void runOnOperation() override; }; @@ -25,11 +27,18 @@ public: struct DoLoopConversion : public mlir::OpRewritePattern<fir::DoLoopOp> { using OpRewritePattern<fir::DoLoopOp>::OpRewritePattern; + DoLoopConversion(mlir::MLIRContext *context, + bool parallelUnorderedLoop = false, + mlir::PatternBenefit benefit = 1) + : OpRewritePattern<fir::DoLoopOp>(context, benefit), + parallelUnorderedLoop(parallelUnorderedLoop) {} + mlir::LogicalResult matchAndRewrite(fir::DoLoopOp doLoopOp, mlir::PatternRewriter &rewriter) const override { mlir::Location loc = doLoopOp.getLoc(); bool hasFinalValue = doLoopOp.getFinalValue().has_value(); + bool isUnordered = doLoopOp.getUnordered().has_value(); // Get loop values from the DoLoopOp mlir::Value low = doLoopOp.getLowerBound(); @@ -53,39 +62,54 @@ struct DoLoopConversion : public mlir::OpRewritePattern<fir::DoLoopOp> { mlir::arith::DivSIOp::create(rewriter, loc, distance, step); auto zero = mlir::arith::ConstantIndexOp::create(rewriter, loc, 0); auto one = mlir::arith::ConstantIndexOp::create(rewriter, loc, 1); - auto scfForOp = - mlir::scf::ForOp::create(rewriter, loc, zero, tripCount, one, iterArgs); + // Create the scf.for or scf.parallel operation + mlir::Operation *scfLoopOp = nullptr; + if (isUnordered && parallelUnorderedLoop) { + scfLoopOp = mlir::scf::ParallelOp::create(rewriter, loc, {zero}, + {tripCount}, {one}, iterArgs); + } else { + scfLoopOp = mlir::scf::ForOp::create(rewriter, loc, zero, tripCount, one, + iterArgs); + } + + // Move the body of the fir.do_loop to the scf.for or scf.parallel auto &loopOps = doLoopOp.getBody()->getOperations(); auto resultOp = mlir::cast<fir::ResultOp>(doLoopOp.getBody()->getTerminator()); auto results = resultOp.getOperands(); - mlir::Block *loweredBody = scfForOp.getBody(); + auto scfLoopLikeOp = mlir::cast<mlir::LoopLikeOpInterface>(scfLoopOp); + mlir::Block &scfLoopBody = scfLoopLikeOp.getLoopRegions().front()->front(); - loweredBody->getOperations().splice(loweredBody->begin(), loopOps, - loopOps.begin(), - std::prev(loopOps.end())); + scfLoopBody.getOperations().splice(scfLoopBody.begin(), loopOps, + loopOps.begin(), + std::prev(loopOps.end())); - rewriter.setInsertionPointToStart(loweredBody); + rewriter.setInsertionPointToStart(&scfLoopBody); mlir::Value iv = mlir::arith::MulIOp::create( - rewriter, loc, scfForOp.getInductionVar(), step); + rewriter, loc, scfLoopLikeOp.getSingleInductionVar().value(), step); iv = mlir::arith::AddIOp::create(rewriter, loc, low, iv); if (!results.empty()) { - rewriter.setInsertionPointToEnd(loweredBody); + rewriter.setInsertionPointToEnd(&scfLoopBody); mlir::scf::YieldOp::create(rewriter, resultOp->getLoc(), results); } doLoopOp.getInductionVar().replaceAllUsesWith(iv); - rewriter.replaceAllUsesWith(doLoopOp.getRegionIterArgs(), - hasFinalValue - ? scfForOp.getRegionIterArgs().drop_front() - : scfForOp.getRegionIterArgs()); - - // Copy all the attributes from the old to new op. - scfForOp->setAttrs(doLoopOp->getAttrs()); - rewriter.replaceOp(doLoopOp, scfForOp); + rewriter.replaceAllUsesWith( + doLoopOp.getRegionIterArgs(), + hasFinalValue ? scfLoopLikeOp.getRegionIterArgs().drop_front() + : scfLoopLikeOp.getRegionIterArgs()); + + // Copy loop annotations from the fir.do_loop to scf loop op. + if (auto ann = doLoopOp.getLoopAnnotation()) + scfLoopOp->setAttr("loop_annotation", *ann); + + rewriter.replaceOp(doLoopOp, scfLoopOp); return mlir::success(); } + +private: + bool parallelUnorderedLoop; }; struct IterWhileConversion : public mlir::OpRewritePattern<fir::IterWhileOp> { @@ -102,6 +126,7 @@ struct IterWhileConversion : public mlir::OpRewritePattern<fir::IterWhileOp> { mlir::Value okInit = iterWhileOp.getIterateIn(); mlir::ValueRange iterArgs = iterWhileOp.getInitArgs(); + bool hasFinalValue = iterWhileOp.getFinalValue().has_value(); mlir::SmallVector<mlir::Value> initVals; initVals.push_back(lowerBound); @@ -128,10 +153,23 @@ struct IterWhileConversion : public mlir::OpRewritePattern<fir::IterWhileOp> { rewriter.setInsertionPointToStart(&beforeBlock); - mlir::Value inductionCmp = mlir::arith::CmpIOp::create( + // The comparison depends on the sign of the step value. We fully expect + // this expression to be folded by the optimizer or LLVM. This expression + // is written this way so that `step == 0` always returns `false`. + auto zero = mlir::arith::ConstantIndexOp::create(rewriter, loc, 0); + auto compl0 = mlir::arith::CmpIOp::create( + rewriter, loc, mlir::arith::CmpIPredicate::slt, zero, step); + auto compl1 = mlir::arith::CmpIOp::create( rewriter, loc, mlir::arith::CmpIPredicate::sle, ivInBefore, upperBound); - mlir::Value cond = mlir::arith::AndIOp::create(rewriter, loc, inductionCmp, - earlyExitInBefore); + auto compl2 = mlir::arith::CmpIOp::create( + rewriter, loc, mlir::arith::CmpIPredicate::slt, step, zero); + auto compl3 = mlir::arith::CmpIOp::create( + rewriter, loc, mlir::arith::CmpIPredicate::sge, ivInBefore, upperBound); + auto cmp0 = mlir::arith::AndIOp::create(rewriter, loc, compl0, compl1); + auto cmp1 = mlir::arith::AndIOp::create(rewriter, loc, compl2, compl3); + auto cmp2 = mlir::arith::OrIOp::create(rewriter, loc, cmp0, cmp1); + mlir::Value cond = + mlir::arith::AndIOp::create(rewriter, loc, earlyExitInBefore, cmp2); mlir::scf::ConditionOp::create(rewriter, loc, cond, argsInBefore); @@ -140,17 +178,22 @@ struct IterWhileConversion : public mlir::OpRewritePattern<fir::IterWhileOp> { auto *afterBody = scfWhileOp.getAfterBody(); auto resultOp = mlir::cast<fir::ResultOp>(afterBody->getTerminator()); - mlir::SmallVector<mlir::Value> results(resultOp->getOperands()); - mlir::Value ivInAfter = scfWhileOp.getAfterArguments()[0]; + mlir::SmallVector<mlir::Value> results; + mlir::Value iv = scfWhileOp.getAfterArguments()[0]; rewriter.setInsertionPointToStart(afterBody); - results[0] = mlir::arith::AddIOp::create(rewriter, loc, ivInAfter, step); + results.push_back(mlir::arith::AddIOp::create(rewriter, loc, iv, step)); + llvm::append_range(results, hasFinalValue + ? resultOp->getOperands().drop_front() + : resultOp->getOperands()); rewriter.setInsertionPointToEnd(afterBody); rewriter.replaceOpWithNewOp<mlir::scf::YieldOp>(resultOp, results); scfWhileOp->setAttrs(iterWhileOp->getAttrs()); - rewriter.replaceOp(iterWhileOp, scfWhileOp); + rewriter.replaceOp(iterWhileOp, + hasFinalValue ? scfWhileOp->getResults() + : scfWhileOp->getResults().drop_front()); return mlir::success(); } }; @@ -197,13 +240,14 @@ struct IfConversion : public mlir::OpRewritePattern<fir::IfOp> { }; } // namespace +void fir::populateFIRToSCFRewrites(mlir::RewritePatternSet &patterns, + bool parallelUnordered) { + patterns.add<IterWhileConversion, IfConversion>(patterns.getContext()); + patterns.add<DoLoopConversion>(patterns.getContext(), parallelUnordered); +} + void FIRToSCFPass::runOnOperation() { mlir::RewritePatternSet patterns(&getContext()); - patterns.add<DoLoopConversion, IterWhileConversion, IfConversion>( - patterns.getContext()); + fir::populateFIRToSCFRewrites(patterns, parallelUnordered); walkAndApplyPatterns(getOperation(), std::move(patterns)); } - -std::unique_ptr<mlir::Pass> fir::createFIRToSCFPass() { - return std::make_unique<FIRToSCFPass>(); -} diff --git a/flang/lib/Optimizer/Transforms/MIFOpConversion.cpp b/flang/lib/Optimizer/Transforms/MIFOpConversion.cpp index 206cb9b..0d3d2f6c 100644 --- a/flang/lib/Optimizer/Transforms/MIFOpConversion.cpp +++ b/flang/lib/Optimizer/Transforms/MIFOpConversion.cpp @@ -67,6 +67,13 @@ genErrmsgPRIF(fir::FirOpBuilder &builder, mlir::Location loc, return {errMsg, errMsgAlloc}; } +static mlir::Value genStatPRIF(fir::FirOpBuilder &builder, mlir::Location loc, + mlir::Value stat) { + if (!stat) + return fir::AbsentOp::create(builder, loc, getPRIFStatType(builder)); + return stat; +} + /// Convert mif.init operation to runtime call of 'prif_init' struct MIFInitOpConversion : public mlir::OpRewritePattern<mif::InitOp> { using OpRewritePattern::OpRewritePattern; @@ -210,9 +217,7 @@ struct MIFSyncAllOpConversion : public mlir::OpRewritePattern<mif::SyncAllOp> { auto [errmsgArg, errmsgAllocArg] = genErrmsgPRIF(builder, loc, op.getErrmsg()); - mlir::Value stat = op.getStat(); - if (!stat) - stat = fir::AbsentOp::create(builder, loc, getPRIFStatType(builder)); + mlir::Value stat = genStatPRIF(builder, loc, op.getStat()); llvm::SmallVector<mlir::Value> args = fir::runtime::createArguments( builder, loc, ftype, stat, errmsgArg, errmsgAllocArg); rewriter.replaceOpWithNewOp<fir::CallOp>(op, funcOp, args); @@ -261,9 +266,7 @@ struct MIFSyncImagesOpConversion } auto [errmsgArg, errmsgAllocArg] = genErrmsgPRIF(builder, loc, op.getErrmsg()); - mlir::Value stat = op.getStat(); - if (!stat) - stat = fir::AbsentOp::create(builder, loc, getPRIFStatType(builder)); + mlir::Value stat = genStatPRIF(builder, loc, op.getStat()); llvm::SmallVector<mlir::Value> args = fir::runtime::createArguments( builder, loc, ftype, imageSet, stat, errmsgArg, errmsgAllocArg); rewriter.replaceOpWithNewOp<fir::CallOp>(op, funcOp, args); @@ -293,9 +296,7 @@ struct MIFSyncMemoryOpConversion auto [errmsgArg, errmsgAllocArg] = genErrmsgPRIF(builder, loc, op.getErrmsg()); - mlir::Value stat = op.getStat(); - if (!stat) - stat = fir::AbsentOp::create(builder, loc, getPRIFStatType(builder)); + mlir::Value stat = genStatPRIF(builder, loc, op.getStat()); llvm::SmallVector<mlir::Value> args = fir::runtime::createArguments( builder, loc, ftype, stat, errmsgArg, errmsgAllocArg); rewriter.replaceOpWithNewOp<fir::CallOp>(op, funcOp, args); @@ -303,6 +304,37 @@ struct MIFSyncMemoryOpConversion } }; +/// Convert mif.sync_team operation to runtime call of 'prif_sync_team' +struct MIFSyncTeamOpConversion + : public mlir::OpRewritePattern<mif::SyncTeamOp> { + using OpRewritePattern::OpRewritePattern; + + mlir::LogicalResult + matchAndRewrite(mif::SyncTeamOp op, + mlir::PatternRewriter &rewriter) const override { + auto mod = op->template getParentOfType<mlir::ModuleOp>(); + fir::FirOpBuilder builder(rewriter, mod); + mlir::Location loc = op.getLoc(); + + mlir::Type boxTy = fir::BoxType::get(builder.getNoneType()); + mlir::Type errmsgTy = getPRIFErrmsgType(builder); + mlir::FunctionType ftype = mlir::FunctionType::get( + builder.getContext(), + /*inputs*/ {boxTy, getPRIFStatType(builder), errmsgTy, errmsgTy}, + /*results*/ {}); + mlir::func::FuncOp funcOp = + builder.createFunction(loc, getPRIFProcName("sync_team"), ftype); + + auto [errmsgArg, errmsgAllocArg] = + genErrmsgPRIF(builder, loc, op.getErrmsg()); + mlir::Value stat = genStatPRIF(builder, loc, op.getStat()); + llvm::SmallVector<mlir::Value> args = fir::runtime::createArguments( + builder, loc, ftype, op.getTeam(), stat, errmsgArg, errmsgAllocArg); + rewriter.replaceOpWithNewOp<fir::CallOp>(op, funcOp, args); + return mlir::success(); + } +}; + /// Generate call to collective subroutines except co_reduce /// A must be lowered as a box static fir::CallOp genCollectiveSubroutine(fir::FirOpBuilder &builder, @@ -432,6 +464,208 @@ struct MIFCoSumOpConversion : public mlir::OpRewritePattern<mif::CoSumOp> { } }; +/// Convert mif.form_team operation to runtime call of 'prif_form_team' +struct MIFFormTeamOpConversion + : public mlir::OpRewritePattern<mif::FormTeamOp> { + using OpRewritePattern::OpRewritePattern; + + mlir::LogicalResult + matchAndRewrite(mif::FormTeamOp op, + mlir::PatternRewriter &rewriter) const override { + auto mod = op->template getParentOfType<mlir::ModuleOp>(); + fir::FirOpBuilder builder(rewriter, mod); + mlir::Location loc = op.getLoc(); + mlir::Type errmsgTy = getPRIFErrmsgType(builder); + mlir::Type boxTy = fir::BoxType::get(builder.getNoneType()); + mlir::FunctionType ftype = mlir::FunctionType::get( + builder.getContext(), + /*inputs*/ + {builder.getRefType(builder.getI64Type()), boxTy, + builder.getRefType(builder.getI32Type()), getPRIFStatType(builder), + errmsgTy, errmsgTy}, + /*results*/ {}); + mlir::func::FuncOp funcOp = + builder.createFunction(loc, getPRIFProcName("form_team"), ftype); + + mlir::Type i64Ty = builder.getI64Type(); + mlir::Value teamNumber = builder.createTemporary(loc, i64Ty); + mlir::Value t = + (op.getTeamNumber().getType() == i64Ty) + ? op.getTeamNumber() + : fir::ConvertOp::create(builder, loc, i64Ty, op.getTeamNumber()); + fir::StoreOp::create(builder, loc, t, teamNumber); + + mlir::Type i32Ty = builder.getI32Type(); + mlir::Value newIndex; + if (op.getNewIndex()) { + newIndex = builder.createTemporary(loc, i32Ty); + mlir::Value ni = + (op.getNewIndex().getType() == i32Ty) + ? op.getNewIndex() + : fir::ConvertOp::create(builder, loc, i32Ty, op.getNewIndex()); + fir::StoreOp::create(builder, loc, ni, newIndex); + } else + newIndex = fir::AbsentOp::create(builder, loc, builder.getRefType(i32Ty)); + + mlir::Value stat = genStatPRIF(builder, loc, op.getStat()); + auto [errmsgArg, errmsgAllocArg] = + genErrmsgPRIF(builder, loc, op.getErrmsg()); + llvm::SmallVector<mlir::Value> args = fir::runtime::createArguments( + builder, loc, ftype, teamNumber, op.getTeamVar(), newIndex, stat, + errmsgArg, errmsgAllocArg); + fir::CallOp callOp = fir::CallOp::create(builder, loc, funcOp, args); + rewriter.replaceOp(op, callOp); + return mlir::success(); + } +}; + +/// Convert mif.change_team operation to runtime call of 'prif_change_team' +struct MIFChangeTeamOpConversion + : public mlir::OpRewritePattern<mif::ChangeTeamOp> { + using OpRewritePattern::OpRewritePattern; + + mlir::LogicalResult + matchAndRewrite(mif::ChangeTeamOp op, + mlir::PatternRewriter &rewriter) const override { + auto mod = op->template getParentOfType<mlir::ModuleOp>(); + fir::FirOpBuilder builder(rewriter, mod); + builder.setInsertionPoint(op); + + mlir::Location loc = op.getLoc(); + mlir::Type errmsgTy = getPRIFErrmsgType(builder); + mlir::Type boxTy = fir::BoxType::get(builder.getNoneType()); + mlir::FunctionType ftype = mlir::FunctionType::get( + builder.getContext(), + /*inputs*/ {boxTy, getPRIFStatType(builder), errmsgTy, errmsgTy}, + /*results*/ {}); + mlir::func::FuncOp funcOp = + builder.createFunction(loc, getPRIFProcName("change_team"), ftype); + + mlir::Value stat = genStatPRIF(builder, loc, op.getStat()); + auto [errmsgArg, errmsgAllocArg] = + genErrmsgPRIF(builder, loc, op.getErrmsg()); + llvm::SmallVector<mlir::Value> args = fir::runtime::createArguments( + builder, loc, ftype, op.getTeam(), stat, errmsgArg, errmsgAllocArg); + fir::CallOp::create(builder, loc, funcOp, args); + + mlir::Operation *changeOp = op.getOperation(); + auto &bodyRegion = op.getRegion(); + mlir::Block &bodyBlock = bodyRegion.front(); + + rewriter.inlineBlockBefore(&bodyBlock, changeOp); + rewriter.eraseOp(op); + return mlir::success(); + } +}; + +/// Convert mif.end_team operation to runtime call of 'prif_end_team' +struct MIFEndTeamOpConversion : public mlir::OpRewritePattern<mif::EndTeamOp> { + using OpRewritePattern::OpRewritePattern; + + mlir::LogicalResult + matchAndRewrite(mif::EndTeamOp op, + mlir::PatternRewriter &rewriter) const override { + auto mod = op->template getParentOfType<mlir::ModuleOp>(); + fir::FirOpBuilder builder(rewriter, mod); + mlir::Location loc = op.getLoc(); + mlir::Type errmsgTy = getPRIFErrmsgType(builder); + mlir::FunctionType ftype = mlir::FunctionType::get( + builder.getContext(), + /*inputs*/ {getPRIFStatType(builder), errmsgTy, errmsgTy}, + /*results*/ {}); + mlir::func::FuncOp funcOp = + builder.createFunction(loc, getPRIFProcName("end_team"), ftype); + + mlir::Value stat = genStatPRIF(builder, loc, op.getStat()); + auto [errmsgArg, errmsgAllocArg] = + genErrmsgPRIF(builder, loc, op.getErrmsg()); + llvm::SmallVector<mlir::Value> args = fir::runtime::createArguments( + builder, loc, ftype, stat, errmsgArg, errmsgAllocArg); + fir::CallOp callOp = fir::CallOp::create(builder, loc, funcOp, args); + rewriter.replaceOp(op, callOp); + return mlir::success(); + } +}; + +/// Convert mif.get_team operation to runtime call of 'prif_get_team' +struct MIFGetTeamOpConversion : public mlir::OpRewritePattern<mif::GetTeamOp> { + using OpRewritePattern::OpRewritePattern; + + mlir::LogicalResult + matchAndRewrite(mif::GetTeamOp op, + mlir::PatternRewriter &rewriter) const override { + auto mod = op->template getParentOfType<mlir::ModuleOp>(); + fir::FirOpBuilder builder(rewriter, mod); + mlir::Location loc = op.getLoc(); + + mlir::Type boxTy = fir::BoxType::get(builder.getNoneType()); + mlir::Type lvlTy = builder.getRefType(builder.getI32Type()); + mlir::FunctionType ftype = + mlir::FunctionType::get(builder.getContext(), + /*inputs*/ {lvlTy, boxTy}, + /*results*/ {}); + mlir::func::FuncOp funcOp = + builder.createFunction(loc, getPRIFProcName("get_team"), ftype); + + mlir::Value level = op.getLevel(); + if (!level) + level = fir::AbsentOp::create(builder, loc, lvlTy); + else { + mlir::Value cst = op.getLevel(); + mlir::Type i32Ty = builder.getI32Type(); + level = builder.createTemporary(loc, i32Ty); + if (cst.getType() != i32Ty) + cst = builder.createConvert(loc, i32Ty, cst); + fir::StoreOp::create(builder, loc, cst, level); + } + mlir::Type resultType = op.getResult().getType(); + mlir::Type baseTy = fir::unwrapRefType(resultType); + mlir::Value team = builder.createTemporary(loc, baseTy); + fir::EmboxOp box = fir::EmboxOp::create(builder, loc, resultType, team); + + llvm::SmallVector<mlir::Value> args = + fir::runtime::createArguments(builder, loc, ftype, level, box); + fir::CallOp::create(builder, loc, funcOp, args); + + rewriter.replaceOp(op, box); + return mlir::success(); + } +}; + +/// Convert mif.team_number operation to runtime call of 'prif_team_number' +struct MIFTeamNumberOpConversion + : public mlir::OpRewritePattern<mif::TeamNumberOp> { + using OpRewritePattern::OpRewritePattern; + + mlir::LogicalResult + matchAndRewrite(mif::TeamNumberOp op, + mlir::PatternRewriter &rewriter) const override { + auto mod = op->template getParentOfType<mlir::ModuleOp>(); + fir::FirOpBuilder builder(rewriter, mod); + mlir::Location loc = op.getLoc(); + mlir::Type i64Ty = builder.getI64Type(); + mlir::Type boxTy = fir::BoxType::get(builder.getNoneType()); + mlir::FunctionType ftype = + mlir::FunctionType::get(builder.getContext(), + /*inputs*/ {boxTy, builder.getRefType(i64Ty)}, + /*results*/ {}); + mlir::func::FuncOp funcOp = + builder.createFunction(loc, getPRIFProcName("team_number"), ftype); + + mlir::Value team = op.getTeam(); + if (!team) + team = fir::AbsentOp::create(builder, loc, boxTy); + + mlir::Value result = builder.createTemporary(loc, i64Ty); + llvm::SmallVector<mlir::Value> args = + fir::runtime::createArguments(builder, loc, ftype, team, result); + fir::CallOp::create(builder, loc, funcOp, args); + fir::LoadOp load = fir::LoadOp::create(builder, loc, result); + rewriter.replaceOp(op, load); + return mlir::success(); + } +}; + class MIFOpConversion : public fir::impl::MIFOpConversionBase<MIFOpConversion> { public: void runOnOperation() override { @@ -458,7 +692,10 @@ void mif::populateMIFOpConversionPatterns(mlir::RewritePatternSet &patterns) { patterns.insert<MIFInitOpConversion, MIFThisImageOpConversion, MIFNumImagesOpConversion, MIFSyncAllOpConversion, MIFSyncImagesOpConversion, MIFSyncMemoryOpConversion, - MIFCoBroadcastOpConversion, MIFCoMaxOpConversion, - MIFCoMinOpConversion, MIFCoSumOpConversion>( + MIFSyncTeamOpConversion, MIFCoBroadcastOpConversion, + MIFCoMaxOpConversion, MIFCoMinOpConversion, + MIFCoSumOpConversion, MIFFormTeamOpConversion, + MIFChangeTeamOpConversion, MIFEndTeamOpConversion, + MIFGetTeamOpConversion, MIFTeamNumberOpConversion>( patterns.getContext()); } diff --git a/flang/lib/Optimizer/Transforms/PolymorphicOpConversion.cpp b/flang/lib/Optimizer/Transforms/PolymorphicOpConversion.cpp index 8c0acc5..c9d52c4 100644 --- a/flang/lib/Optimizer/Transforms/PolymorphicOpConversion.cpp +++ b/flang/lib/Optimizer/Transforms/PolymorphicOpConversion.cpp @@ -247,7 +247,8 @@ struct DispatchOpConv : public OpConversionPattern<fir::DispatchOp> { rewriter.replaceOpWithNewOp<fir::CallOp>( dispatch, resTypes, nullptr, args, dispatch.getArgAttrsAttr(), dispatch.getResAttrsAttr(), dispatch.getProcedureAttrsAttr(), - /*inline_attr*/ fir::FortranInlineEnumAttr{}); + /*inline_attr*/ fir::FortranInlineEnumAttr{}, + /*accessGroups*/ mlir::ArrayAttr{}); return mlir::success(); } diff --git a/flang/lib/Optimizer/Transforms/SetRuntimeCallAttributes.cpp b/flang/lib/Optimizer/Transforms/SetRuntimeCallAttributes.cpp index 378037e..4ba2ea5 100644 --- a/flang/lib/Optimizer/Transforms/SetRuntimeCallAttributes.cpp +++ b/flang/lib/Optimizer/Transforms/SetRuntimeCallAttributes.cpp @@ -85,7 +85,10 @@ static mlir::LLVM::MemoryEffectsAttr getGenericMemoryAttr(fir::CallOp callOp) { callOp->getContext(), {/*other=*/mlir::LLVM::ModRefInfo::NoModRef, /*argMem=*/mlir::LLVM::ModRefInfo::ModRef, - /*inaccessibleMem=*/mlir::LLVM::ModRefInfo::ModRef}); + /*inaccessibleMem=*/mlir::LLVM::ModRefInfo::ModRef, + /*errnoMem=*/mlir::LLVM::ModRefInfo::NoModRef, + /*targetMem0=*/mlir::LLVM::ModRefInfo::NoModRef, + /*targetMem1=*/mlir::LLVM::ModRefInfo::NoModRef}); } return {}; diff --git a/flang/lib/Optimizer/Transforms/SimplifyIntrinsics.cpp b/flang/lib/Optimizer/Transforms/SimplifyIntrinsics.cpp index 49a085e..49ae189 100644 --- a/flang/lib/Optimizer/Transforms/SimplifyIntrinsics.cpp +++ b/flang/lib/Optimizer/Transforms/SimplifyIntrinsics.cpp @@ -730,7 +730,6 @@ static void genRuntimeMinMaxlocBody(fir::FirOpBuilder &builder, mlir::Value ifCompatElem = fir::ConvertOp::create(builder, loc, ifCompatType, maskElem); - llvm::SmallVector<mlir::Type> resultsTy = {elementType, elementType}; fir::IfOp ifOp = fir::IfOp::create(builder, loc, elementType, ifCompatElem, /*withElseRegion=*/true); diff --git a/flang/lib/Parser/Fortran-parsers.cpp b/flang/lib/Parser/Fortran-parsers.cpp index 59fe7d8..988db54 100644 --- a/flang/lib/Parser/Fortran-parsers.cpp +++ b/flang/lib/Parser/Fortran-parsers.cpp @@ -1212,12 +1212,15 @@ TYPE_CONTEXT_PARSER("image selector"_en_US, // R926 image-selector-spec -> // STAT = stat-variable | TEAM = team-value | -// TEAM_NUMBER = scalar-int-expr +// TEAM_NUMBER = scalar-int-expr | +// NOTIFY = notify-variable TYPE_PARSER(construct<ImageSelectorSpec>(construct<ImageSelectorSpec::Stat>( "STAT =" >> scalar(integer(indirect(variable))))) || construct<ImageSelectorSpec>(construct<TeamValue>("TEAM =" >> teamValue)) || construct<ImageSelectorSpec>(construct<ImageSelectorSpec::Team_Number>( - "TEAM_NUMBER =" >> scalarIntExpr))) + "TEAM_NUMBER =" >> scalarIntExpr)) || + construct<ImageSelectorSpec>(construct<ImageSelectorSpec::Notify>( + "NOTIFY =" >> scalar(indirect(variable))))) // R927 allocate-stmt -> // ALLOCATE ( [type-spec ::] allocation-list [, alloc-opt-list] ) @@ -1292,8 +1295,11 @@ TYPE_PARSER(construct<StatOrErrmsg>("STAT =" >> statVariable) || // Directives, extensions, and deprecated statements // !DIR$ IGNORE_TKR [ [(tkrdmac...)] name ]... // !DIR$ LOOP COUNT (n1[, n2]...) +// !DIR$ VECTOR VECTORLENGTH ({FIXED|SCALABLE|<num>|<num>,FIXED|<num>,SCALABLE}) // !DIR$ name[=value] [, name[=value]]... // !DIR$ UNROLL [n] +// !DIR$ PREFETCH designator[, designator]... +// !DIR$ IVDEP // !DIR$ <anything else> constexpr auto ignore_tkr{ "IGNORE_TKR" >> optionalList(construct<CompilerDirective::IgnoreTKR>( @@ -1306,8 +1312,19 @@ constexpr auto assumeAligned{"ASSUME_ALIGNED" >> indirect(designator), ":"_tok >> digitString64))}; constexpr auto vectorAlways{ "VECTOR ALWAYS" >> construct<CompilerDirective::VectorAlways>()}; +constexpr auto vectorLengthKind{ + "FIXED" >> pure(CompilerDirective::VectorLength::Kind::Fixed) || + "SCALABLE" >> pure(CompilerDirective::VectorLength::Kind::Scalable)}; +constexpr auto vectorLength{"VECTOR VECTORLENGTH" >> + parenthesized(construct<CompilerDirective::VectorLength>( + digitString64, ","_tok >> vectorLengthKind) || + construct<CompilerDirective::VectorLength>(pure(0), vectorLengthKind) || + construct<CompilerDirective::VectorLength>( + digitString64, pure(CompilerDirective::VectorLength::Kind::Auto)))}; constexpr auto unroll{ "UNROLL" >> construct<CompilerDirective::Unroll>(maybe(digitString64))}; +constexpr auto prefetch{"PREFETCH" >> + construct<CompilerDirective::Prefetch>(nonemptyList(indirect(designator)))}; constexpr auto unrollAndJam{"UNROLL_AND_JAM" >> construct<CompilerDirective::UnrollAndJam>(maybe(digitString64))}; constexpr auto novector{"NOVECTOR" >> construct<CompilerDirective::NoVector>()}; @@ -1319,19 +1336,23 @@ constexpr auto forceinlineDir{ constexpr auto noinlineDir{ "NOINLINE" >> construct<CompilerDirective::NoInline>()}; constexpr auto inlineDir{"INLINE" >> construct<CompilerDirective::Inline>()}; +constexpr auto ivdep{"IVDEP" >> construct<CompilerDirective::IVDep>()}; TYPE_PARSER(beginDirective >> "DIR$ "_tok >> sourced((construct<CompilerDirective>(ignore_tkr) || construct<CompilerDirective>(loopCount) || construct<CompilerDirective>(assumeAligned) || construct<CompilerDirective>(vectorAlways) || + construct<CompilerDirective>(vectorLength) || construct<CompilerDirective>(unrollAndJam) || construct<CompilerDirective>(unroll) || + construct<CompilerDirective>(prefetch) || construct<CompilerDirective>(novector) || construct<CompilerDirective>(nounrollAndJam) || construct<CompilerDirective>(nounroll) || construct<CompilerDirective>(noinlineDir) || construct<CompilerDirective>(forceinlineDir) || construct<CompilerDirective>(inlineDir) || + construct<CompilerDirective>(ivdep) || construct<CompilerDirective>( many(construct<CompilerDirective::NameValue>( name, maybe(("="_tok || ":"_tok) >> digitString64))))) / diff --git a/flang/lib/Parser/executable-parsers.cpp b/flang/lib/Parser/executable-parsers.cpp index fadec1f..2241c04 100644 --- a/flang/lib/Parser/executable-parsers.cpp +++ b/flang/lib/Parser/executable-parsers.cpp @@ -49,8 +49,9 @@ constexpr auto executableConstruct{first( construct<ExecutableConstruct>(indirect(Parser<SelectTypeConstruct>{})), construct<ExecutableConstruct>(indirect(whereConstruct)), construct<ExecutableConstruct>(indirect(forallConstruct)), - construct<ExecutableConstruct>(indirect(ompEndLoopDirective)), construct<ExecutableConstruct>(indirect(openmpConstruct)), + construct<ExecutableConstruct>(indirect(openmpMisplacedEndDirective)), + construct<ExecutableConstruct>(indirect(openmpInvalidDirective)), construct<ExecutableConstruct>(indirect(Parser<OpenACCConstruct>{})), construct<ExecutableConstruct>(indirect(compilerDirective)), construct<ExecutableConstruct>(indirect(Parser<CUFKernelDoConstruct>{})))}; diff --git a/flang/lib/Parser/openmp-parsers.cpp b/flang/lib/Parser/openmp-parsers.cpp index 4159d2e..a0e106d7 100644 --- a/flang/lib/Parser/openmp-parsers.cpp +++ b/flang/lib/Parser/openmp-parsers.cpp @@ -17,6 +17,7 @@ #include "type-parser-implementation.h" #include "flang/Parser/openmp-utils.h" #include "flang/Parser/parse-tree.h" +#include "flang/Parser/tools.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/Bitset.h" #include "llvm/ADT/STLExtras.h" @@ -30,6 +31,7 @@ #include <iterator> #include <list> #include <optional> +#include <set> #include <string> #include <tuple> #include <type_traits> @@ -56,6 +58,35 @@ constexpr auto endOmpLine = space >> endOfLine; constexpr auto logicalConstantExpr{logical(constantExpr)}; constexpr auto scalarLogicalConstantExpr{scalar(logicalConstantExpr)}; +// Parser that wraps the result of another parser into a Block. If the given +// parser succeeds, the result is a block containing the ExecutionPartConstruct +// result of the argument parser. Otherwise the parser fails. +template <typename ExecParser> struct AsBlockParser { + using resultType = Block; + static_assert( + std::is_same_v<typename ExecParser::resultType, ExecutionPartConstruct>); + + constexpr AsBlockParser(ExecParser epc) : epc_(epc) {} + std::optional<resultType> Parse(ParseState &state) const { + if (auto &&exec{attempt(epc_).Parse(state)}) { + Block body; + body.push_back(std::move(*exec)); + return std::move(body); // std::move for GCC 7.5.0 + } + return std::nullopt; + } + +private: + const ExecParser epc_; +}; + +template <typename ExecParser, + typename = std::enable_if<std::is_same_v<typename ExecParser::resultType, + ExecutionPartConstruct>>> +constexpr auto asBlock(ExecParser epc) { + return AsBlockParser<ExecParser>(epc); +} + // Given a parser for a single element, and a parser for a list of elements // of the same type, create a parser that constructs the entire list by having // the single element be the head of the list, and the rest be the tail. @@ -791,6 +822,12 @@ TYPE_PARSER(construct<OmpDirectiveNameModifier>(OmpDirectiveNameParser{})) TYPE_PARSER(construct<OmpExpectation>( // "PRESENT" >> pure(OmpExpectation::Value::Present))) +TYPE_PARSER(construct<OmpFallbackModifier>("FALLBACK"_tok >> + parenthesized( // + "ABORT" >> pure(OmpFallbackModifier::Value::Abort) || + "DEFAULT_MEM" >> pure(OmpFallbackModifier::Value::Default_Mem) || + "NULL" >> pure(OmpFallbackModifier::Value::Null)))) + TYPE_PARSER(construct<OmpInteropRuntimeIdentifier>( construct<OmpInteropRuntimeIdentifier>(charLiteralConstant) || construct<OmpInteropRuntimeIdentifier>(scalarIntConstantExpr))) @@ -857,8 +894,7 @@ TYPE_PARSER(construct<OmpOrderingModifier>( "SIMD" >> pure(OmpOrderingModifier::Value::Simd))) TYPE_PARSER(construct<OmpPrescriptiveness>( - "STRICT" >> pure(OmpPrescriptiveness::Value::Strict) || - "FALLBACK" >> pure(OmpPrescriptiveness::Value::Fallback))) + "STRICT" >> pure(OmpPrescriptiveness::Value::Strict))) TYPE_PARSER(construct<OmpPresentModifier>( // "PRESENT" >> pure(OmpPresentModifier::Value::Present))) @@ -925,7 +961,7 @@ TYPE_PARSER( // sourced(construct<OmpDynGroupprivateClause::Modifier>( Parser<OmpAccessGroup>{})) || sourced(construct<OmpDynGroupprivateClause::Modifier>( - Parser<OmpPrescriptiveness>{}))) + Parser<OmpFallbackModifier>{}))) TYPE_PARSER( sourced(construct<OmpDeviceClause::Modifier>(Parser<OmpDeviceModifier>{}))) @@ -1163,6 +1199,10 @@ TYPE_PARSER(construct<OmpTaskReductionClause>( TYPE_PARSER(construct<OmpTransparentClause>(scalarIntExpr)) +TYPE_PARSER(construct<OmpThreadsetClause>( + "OMP_POOL" >> pure(OmpThreadsetClause::ThreadsetPolicy::Omp_Pool) || + "OMP_TEAM" >> pure(OmpThreadsetClause::ThreadsetPolicy::Omp_Team))) + // OMP 5.0 2.11.4 allocate-clause -> ALLOCATE ([allocator:] variable-name-list) // OMP 5.2 2.13.4 allocate-clause -> ALLOCATE ([allocate-modifier // [, allocate-modifier] :] @@ -1242,7 +1282,7 @@ TYPE_PARSER( maybe(":"_tok >> nonemptyList(Parser<OmpLinearClause::Modifier>{})), /*PostModified=*/pure(true))) -TYPE_PARSER(construct<OmpLoopRangeClause>( +TYPE_PARSER(construct<OmpLooprangeClause>( scalarIntConstantExpr, "," >> scalarIntConstantExpr)) // OpenMPv5.2 12.5.2 detach-clause -> DETACH (event-handle) @@ -1435,7 +1475,7 @@ TYPE_PARSER( // "LINK" >> construct<OmpClause>(construct<OmpClause::Link>( parenthesized(Parser<OmpObjectList>{}))) || "LOOPRANGE" >> construct<OmpClause>(construct<OmpClause::Looprange>( - parenthesized(Parser<OmpLoopRangeClause>{}))) || + parenthesized(Parser<OmpLooprangeClause>{}))) || "MAP" >> construct<OmpClause>(construct<OmpClause::Map>( parenthesized(Parser<OmpMapClause>{}))) || "MATCH" >> construct<OmpClause>(construct<OmpClause::Match>( @@ -1514,7 +1554,9 @@ TYPE_PARSER( // parenthesized(nonemptyList(scalarIntExpr)))) || "PERMUTATION" >> construct<OmpClause>(construct<OmpClause::Permutation>( parenthesized(nonemptyList(scalarIntExpr)))) || - "THREADS" >> construct<OmpClause>(construct<OmpClause::Threads>()) || + "THREADS"_id >> construct<OmpClause>(construct<OmpClause::Threads>()) || + "THREADSET" >> construct<OmpClause>(construct<OmpClause::Threadset>( + parenthesized(Parser<OmpThreadsetClause>{}))) || "THREAD_LIMIT" >> construct<OmpClause>(construct<OmpClause::ThreadLimit>( parenthesized(scalarIntExpr))) || "TO" >> construct<OmpClause>(construct<OmpClause::To>( @@ -1566,6 +1608,14 @@ static inline constexpr auto IsMemberOf(const DirectiveSet &dirs) { }; } +constexpr auto validEPC{// + predicated(executionPartConstruct, [](auto &epc) { + return !Unwrap<OpenMPMisplacedEndDirective>(epc) && + !Unwrap<OpenMPMisplacedEndDirective>(epc); + })}; + +constexpr auto validBlock{many(validEPC)}; + TYPE_PARSER(sourced(construct<OmpDirectiveName>(OmpDirectiveNameParser{}))) OmpDirectiveSpecification static makeFlushFromOldSyntax(Verbatim &&text, @@ -1589,7 +1639,8 @@ TYPE_PARSER( maybe(Parser<OmpClauseList>{}), maybe(parenthesized( OmpArgumentListParser<llvm::omp::Directive::OMPD_flush>{})), - pure(OmpDirectiveSpecification::Flags::DeprecatedSyntax)))) || + pure(OmpDirectiveSpecification::Flags( + {OmpDirectiveSpecification::Flag::DeprecatedSyntax}))))) || // Parse DECLARE_VARIANT individually, because the "[base:]variant" // argument will conflict with DECLARE_REDUCTION's "ident:types...". predicated(Parser<OmpDirectiveName>{}, @@ -1599,13 +1650,13 @@ TYPE_PARSER( maybe(parenthesized(OmpArgumentListParser< llvm::omp::Directive::OMPD_declare_variant>{})), maybe(Parser<OmpClauseList>{}), - pure(OmpDirectiveSpecification::Flags::None))) || + pure(OmpDirectiveSpecification::Flags()))) || // Parse the standard syntax: directive [(arguments)] [clauses] sourced(construct<OmpDirectiveSpecification>( // sourced(OmpDirectiveNameParser{}), maybe(parenthesized(OmpArgumentListParser<>{})), maybe(Parser<OmpClauseList>{}), - pure(OmpDirectiveSpecification::Flags::None)))) + pure(OmpDirectiveSpecification::Flags())))) static bool IsStandaloneOrdered(const OmpDirectiveSpecification &dirSpec) { // An ORDERED construct is standalone if it has DOACROSS or DEPEND clause. @@ -1623,7 +1674,7 @@ struct StrictlyStructuredBlockParser { std::optional<resultType> Parse(ParseState &state) const { // Detect BLOCK construct without parsing the entire thing. if (lookAhead(skipStuffBeforeStatement >> "BLOCK"_tok).Parse(state)) { - if (auto epc{Parser<ExecutionPartConstruct>{}.Parse(state)}) { + if (auto &&epc{executionPartConstruct.Parse(state)}) { if (GetFortranBlockConstruct(*epc) != nullptr) { Block body; body.emplace_back(std::move(*epc)); @@ -1643,7 +1694,7 @@ struct LooselyStructuredBlockParser { if (lookAhead(skipStuffBeforeStatement >> "BLOCK"_tok).Parse(state)) { return std::nullopt; } - if (auto &&body{block.Parse(state)}) { + if (auto &&body{validBlock.Parse(state)}) { // Empty body is ok. return std::move(body); } @@ -1651,6 +1702,86 @@ struct LooselyStructuredBlockParser { } }; +struct NonBlockDoConstructParser { + using resultType = Block; + + std::optional<resultType> Parse(ParseState &state) const { + std::set<Label> labels; + Block body; + + // Parse nests like + // do 20 i = 1, n LabelDoStmt.t<Label> = 20 + // do 10 j = 1, m + // ... + // 10 continue Statement<...>.label = 10 + // 20 continue + + // Keep parsing ExecutionPartConstructs until the set of open label-do + // statements becomes empty, or until the EPC parser fails. + auto processEpc{[&](ExecutionPartConstruct &&epc) { + if (auto &&label{GetStatementLabel(epc)}) { + labels.erase(*label); + } + if (auto *labelDo{Unwrap<LabelDoStmt>(epc)}) { + labels.insert(std::get<Label>(labelDo->t)); + } + body.push_back(std::move(epc)); + }}; + + auto nonBlockDo{predicated(executionPartConstruct, + [](auto &epc) { return Unwrap<LabelDoStmt>(epc); })}; + + if (auto &&nbd{nonBlockDo.Parse(state)}) { + processEpc(std::move(*nbd)); + while (auto &&epc{attempt(validEPC).Parse(state)}) { + processEpc(std::move(*epc)); + if (labels.empty()) { + break; + } + } + } + + if (!body.empty()) { + return std::move(body); + } + return std::nullopt; + } +}; + +struct LoopNestParser { + using resultType = Block; + + std::optional<resultType> Parse(ParseState &state) const { + // Parse !$DIR as an ExecutionPartConstruct + auto fortranDirective{predicated(executionPartConstruct, + [](auto &epc) { return Unwrap<CompilerDirective>(epc); })}; + // Parse DO loop as an ExecutionPartConstruct + auto fortranDoConstruct{predicated(executionPartConstruct, + [&](auto &epc) { return Unwrap<DoConstruct>(epc); })}; + ParseState backtrack{state}; + + Block body; + llvm::move(*many(fortranDirective).Parse(state), std::back_inserter(body)); + + if (auto &&doLoop{attempt(fortranDoConstruct).Parse(state)}) { + body.push_back(std::move(*doLoop)); + return std::move(body); + } + if (auto &&labelDo{attempt(NonBlockDoConstructParser{}).Parse(state)}) { + llvm::move(*labelDo, std::back_inserter(body)); + return std::move(body); + } + if (auto &&sblock{attempt(StrictlyStructuredBlockParser{}).Parse(state)}) { + llvm::move(*sblock, std::back_inserter(body)); + return std::move(body); + } + // If it's neither a DO-loop, nor a BLOCK, undo the parsing of the + // directives and fail. + state = backtrack; + return std::nullopt; + } +}; + TYPE_PARSER(construct<OmpErrorDirective>( predicated(Parser<OmpDirectiveName>{}, IsDirective(llvm::omp::Directive::OMPD_error)) >= @@ -1724,7 +1855,7 @@ struct OmpStatementConstructParser { std::optional<resultType> Parse(ParseState &state) const { if (auto begin{OmpBeginDirectiveParser(dir_).Parse(state)}) { Block body; - if (auto stmt{attempt(Parser<ExecutionPartConstruct>{}).Parse(state)}) { + if (auto stmt{attempt(validEPC).Parse(state)}) { body.emplace_back(std::move(*stmt)); } // Allow empty block. Check for this in semantics. @@ -1778,6 +1909,79 @@ private: llvm::omp::Directive dir_; }; +struct OmpLoopConstructParser { + using resultType = OpenMPLoopConstruct; + + constexpr OmpLoopConstructParser(DirectiveSet dirs) : dirs_(dirs) {} + + std::optional<resultType> Parse(ParseState &state) const { + auto ompLoopConstruct{asBlock(predicated(executionPartConstruct, + [](auto &epc) { return Unwrap<OpenMPLoopConstruct>(epc); }))}; + auto loopItem{LoopNestParser{} || ompLoopConstruct}; + + if (auto &&begin{OmpBeginDirectiveParser(dirs_).Parse(state)}) { + auto loopDir{begin->DirId()}; + auto assoc{llvm::omp::getDirectiveAssociation(loopDir)}; + if (assoc == llvm::omp::Association::LoopNest) { + if (auto &&item{attempt(loopItem).Parse(state)}) { + auto end{maybe(OmpEndDirectiveParser{loopDir}).Parse(state)}; + return OpenMPLoopConstruct{OmpBeginLoopDirective(std::move(*begin)), + std::move(*item), + llvm::transformOptional(std::move(*end), + [](auto &&s) { return OmpEndLoopDirective(std::move(s)); })}; + } else if (auto &&empty{pure<Block>().Parse(state)}) { + // Allow empty body. + auto end{maybe(OmpEndDirectiveParser{loopDir}).Parse(state)}; + return OpenMPLoopConstruct{OmpBeginLoopDirective(std::move(*begin)), + std::move(*empty), + llvm::transformOptional(std::move(*end), + [](auto &&s) { return OmpEndLoopDirective(std::move(s)); })}; + } + } else if (assoc == llvm::omp::Association::LoopSeq) { + // Parse loop sequence as a block. + if (auto &&body{validBlock.Parse(state)}) { + auto end{maybe(OmpEndDirectiveParser{loopDir}).Parse(state)}; + return OpenMPLoopConstruct{OmpBeginLoopDirective(std::move(*begin)), + std::move(*body), + llvm::transformOptional(std::move(*end), + [](auto &&s) { return OmpEndLoopDirective(std::move(s)); })}; + } + } else { + llvm_unreachable("Unexpected association"); + } + } + return std::nullopt; + } + +private: + DirectiveSet dirs_; +}; + +struct OmpDeclarativeAllocateParser { + using resultType = OmpAllocateDirective; + + std::optional<resultType> Parse(ParseState &state) const { + constexpr llvm::omp::Directive dir{llvm::omp::Directive::OMPD_allocate}; + if (auto &&begin{attempt(OmpBeginDirectiveParser(dir)).Parse(state)}) { + Block empty; + auto end{maybe(OmpEndDirectiveParser{dir}).Parse(state)}; + return OmpAllocateDirective{std::move(*begin), std::move(empty), + llvm::transformOptional(std::move(*end), + [](auto &&s) { return OmpEndDirective(std::move(s)); })}; + } + return std::nullopt; + } +}; + +struct OmpExecutableAllocateParser { + using resultType = OmpAllocateDirective; + + std::optional<resultType> Parse(ParseState &state) const { + OmpStatementConstructParser p{llvm::omp::Directive::OMPD_allocate}; + return construct<OmpAllocateDirective>(p).Parse(state); + } +}; + TYPE_PARSER(sourced(construct<OpenMPAllocatorsConstruct>( OmpStatementConstructParser{llvm::omp::Directive::OMPD_allocators}))) @@ -1832,11 +2036,9 @@ struct OmpAtomicConstructParser { return std::nullopt; } - auto exec{Parser<ExecutionPartConstruct>{}}; - auto end{OmpEndDirectiveParser{llvm::omp::Directive::OMPD_atomic}}; TailType tail; - if (ParseOne(exec, end, tail, state)) { + if (ParseOne(tail, state)) { if (!tail.first.empty()) { if (auto &&rest{attempt(LimitedTailParser(BodyLimit)).Parse(state)}) { for (auto &&s : rest->first) { @@ -1863,13 +2065,12 @@ private: // Parse either an ExecutionPartConstruct, or atomic end-directive. When // successful, record the result in the "tail" provided, otherwise fail. - static std::optional<Success> ParseOne( // - Parser<ExecutionPartConstruct> &exec, OmpEndDirectiveParser &end, - TailType &tail, ParseState &state) { - auto isRecovery{[](const ExecutionPartConstruct &e) { - return std::holds_alternative<ErrorRecovery>(e.u); + static std::optional<Success> ParseOne(TailType &tail, ParseState &state) { + auto isUsable{[](const std::optional<ExecutionPartConstruct> &e) { + return e && !std::holds_alternative<ErrorRecovery>(e->u); }}; - if (auto &&stmt{attempt(exec).Parse(state)}; stmt && !isRecovery(*stmt)) { + auto end{OmpEndDirectiveParser{llvm::omp::Directive::OMPD_atomic}}; + if (auto &&stmt{attempt(validEPC).Parse(state)}; isUsable(stmt)) { tail.first.emplace_back(std::move(*stmt)); } else if (auto &&dir{attempt(end).Parse(state)}) { tail.second = std::move(*dir); @@ -1885,12 +2086,10 @@ private: constexpr LimitedTailParser(size_t count) : count_(count) {} std::optional<resultType> Parse(ParseState &state) const { - auto exec{Parser<ExecutionPartConstruct>{}}; - auto end{OmpEndDirectiveParser{llvm::omp::Directive::OMPD_atomic}}; TailType tail; for (size_t i{0}; i != count_; ++i) { - if (ParseOne(exec, end, tail, state)) { + if (ParseOne(tail, state)) { if (tail.second) { // Return when the end-directive was parsed. return std::move(tail); @@ -2044,13 +2243,6 @@ TYPE_PARSER(construct<OmpInitializerExpression>(OmpStylizedExpressionParser{})) TYPE_PARSER(sourced(construct<OpenMPCriticalConstruct>( OmpBlockConstructParser{llvm::omp::Directive::OMPD_critical}))) -// 2.11.3 Executable Allocate directive -TYPE_PARSER( - sourced(construct<OpenMPExecutableAllocate>(verbatim("ALLOCATE"_tok), - maybe(parenthesized(Parser<OmpObjectList>{})), Parser<OmpClauseList>{}, - maybe(nonemptyList(Parser<OpenMPDeclarativeAllocate>{})) / endOmpLine, - statement(allocateStmt)))) - // 2.8.2 Declare Simd construct TYPE_PARSER(sourced(construct<OpenMPDeclareSimdConstruct>( predicated(Parser<OmpDirectiveName>{}, @@ -2076,12 +2268,6 @@ TYPE_PARSER(sourced( // IsDirective(llvm::omp::Directive::OMPD_threadprivate)) >= Parser<OmpDirectiveSpecification>{}))) -// 2.11.3 Declarative Allocate directive -TYPE_PARSER( - sourced(construct<OpenMPDeclarativeAllocate>(verbatim("ALLOCATE"_tok), - parenthesized(Parser<OmpObjectList>{}), Parser<OmpClauseList>{})) / - lookAhead(endOmpLine / !statement(allocateStmt))) - // Assumes Construct TYPE_PARSER(sourced(construct<OpenMPDeclarativeAssumes>( predicated(OmpDirectiveNameParser{}, @@ -2104,7 +2290,7 @@ TYPE_PARSER( construct<OpenMPDeclarativeConstruct>( Parser<OmpDeclareVariantDirective>{}) || construct<OpenMPDeclarativeConstruct>( - Parser<OpenMPDeclarativeAllocate>{}) || + sourced(OmpDeclarativeAllocateParser{})) || construct<OpenMPDeclarativeConstruct>( Parser<OpenMPGroupprivate>{}) || construct<OpenMPDeclarativeConstruct>( @@ -2175,9 +2361,9 @@ TYPE_PARSER(sourced(construct<OpenMPSectionsConstruct>( Parser<OmpBeginSectionsDirective>{} / endOmpLine, cons( // construct<OpenMPConstruct>(sourced( - construct<OpenMPSectionConstruct>(maybe(sectionDir), block))), - many(construct<OpenMPConstruct>( - sourced(construct<OpenMPSectionConstruct>(sectionDir, block))))), + construct<OpenMPSectionConstruct>(maybe(sectionDir), validBlock))), + many(construct<OpenMPConstruct>(sourced( + construct<OpenMPSectionConstruct>(sectionDir, validBlock))))), maybe(Parser<OmpEndSectionsDirective>{} / endOmpLine)))) static bool IsExecutionPart(const OmpDirectiveName &name) { @@ -2192,6 +2378,8 @@ TYPE_CONTEXT_PARSER("OpenMP construct"_en_US, withMessage("expected OpenMP construct"_err_en_US, first(construct<OpenMPConstruct>(Parser<OpenMPSectionsConstruct>{}), construct<OpenMPConstruct>(Parser<OpenMPLoopConstruct>{}), + construct<OpenMPConstruct>( + sourced(OmpExecutableAllocateParser{})), construct<OpenMPConstruct>(Parser<OmpBlockConstruct>{}), // OmpBlockConstruct is attempted before // OpenMPStandaloneConstruct to resolve !$OMP ORDERED @@ -2199,9 +2387,7 @@ TYPE_CONTEXT_PARSER("OpenMP construct"_en_US, construct<OpenMPConstruct>(Parser<OpenMPAtomicConstruct>{}), construct<OpenMPConstruct>(Parser<OpenMPUtilityConstruct>{}), construct<OpenMPConstruct>(Parser<OpenMPDispatchConstruct>{}), - construct<OpenMPConstruct>(Parser<OpenMPExecutableAllocate>{}), construct<OpenMPConstruct>(Parser<OpenMPAllocatorsConstruct>{}), - construct<OpenMPConstruct>(Parser<OpenMPDeclarativeAllocate>{}), construct<OpenMPConstruct>(Parser<OpenMPAssumeConstruct>{}), construct<OpenMPConstruct>(Parser<OpenMPCriticalConstruct>{})))) @@ -2243,19 +2429,24 @@ static constexpr DirectiveSet GetLoopDirectives() { unsigned(Directive::OMPD_teams_distribute_parallel_do_simd), unsigned(Directive::OMPD_teams_distribute_simd), unsigned(Directive::OMPD_teams_loop), + unsigned(Directive::OMPD_fuse), unsigned(Directive::OMPD_tile), unsigned(Directive::OMPD_unroll), }; return loopDirectives; } -TYPE_PARSER(sourced(construct<OmpBeginLoopDirective>( - sourced(OmpBeginDirectiveParser(GetLoopDirectives()))))) +TYPE_PARSER(sourced(construct<OpenMPLoopConstruct>( + OmpLoopConstructParser(GetLoopDirectives())))) -// END OMP Loop directives -TYPE_PARSER(sourced(construct<OmpEndLoopDirective>( - sourced(OmpEndDirectiveParser(GetLoopDirectives()))))) +static constexpr DirectiveSet GetAllDirectives() { // + return ~DirectiveSet{}; +} -TYPE_PARSER(construct<OpenMPLoopConstruct>( - Parser<OmpBeginLoopDirective>{} / endOmpLine)) +TYPE_PARSER(construct<OpenMPMisplacedEndDirective>( + OmpEndDirectiveParser{GetAllDirectives()})) + +TYPE_PARSER( // + startOmpLine >> sourced(construct<OpenMPInvalidDirective>( + !OmpDirectiveNameParser{} >> SkipTo<'\n'>{}))) } // namespace Fortran::parser diff --git a/flang/lib/Parser/openmp-utils.cpp b/flang/lib/Parser/openmp-utils.cpp index 95ad3f6..4c38917e 100644 --- a/flang/lib/Parser/openmp-utils.cpp +++ b/flang/lib/Parser/openmp-utils.cpp @@ -15,6 +15,7 @@ #include "flang/Common/indirection.h" #include "flang/Common/template.h" #include "flang/Common/visit.h" +#include "flang/Parser/tools.h" #include <tuple> #include <type_traits> @@ -22,44 +23,114 @@ namespace Fortran::parser::omp { +const OpenMPDeclarativeConstruct *GetOmp(const DeclarationConstruct &x) { + if (auto *y = std::get_if<SpecificationConstruct>(&x.u)) { + if (auto *z{std::get_if<common::Indirection<OpenMPDeclarativeConstruct>>( + &y->u)}) { + return &z->value(); + } + } + return nullptr; +} + +const OpenMPConstruct *GetOmp(const ExecutionPartConstruct &x) { + if (auto *y{std::get_if<ExecutableConstruct>(&x.u)}) { + if (auto *z{std::get_if<common::Indirection<OpenMPConstruct>>(&y->u)}) { + return &z->value(); + } + } + return nullptr; +} + +const OpenMPLoopConstruct *GetOmpLoop(const ExecutionPartConstruct &x) { + if (auto *construct{GetOmp(x)}) { + if (auto *omp{std::get_if<OpenMPLoopConstruct>(&construct->u)}) { + return omp; + } + } + return nullptr; +} +const DoConstruct *GetDoConstruct(const ExecutionPartConstruct &x) { + if (auto *y{std::get_if<ExecutableConstruct>(&x.u)}) { + if (auto *z{std::get_if<common::Indirection<DoConstruct>>(&y->u)}) { + return &z->value(); + } + } + return nullptr; +} + +// Get the Label from a Statement<...> contained in an ExecutionPartConstruct, +// or std::nullopt, if there is no Statement<...> contained in there. +template <typename T> +static std::optional<Label> GetStatementLabelHelper(const T &stmt) { + if constexpr (IsStatement<T>::value) { + return stmt.label; + } else if constexpr (WrapperTrait<T>) { + return GetStatementLabelHelper(stmt.v); + } else if constexpr (UnionTrait<T>) { + return common::visit( + [&](auto &&s) { return GetStatementLabelHelper(s); }, stmt.u); + } + return std::nullopt; +} + +std::optional<Label> GetStatementLabel(const ExecutionPartConstruct &x) { + return GetStatementLabelHelper(x); +} + +static std::optional<Label> GetFinalLabel(const Block &x) { + if (!x.empty()) { + const ExecutionPartConstruct &last{x.back()}; + if (auto *omp{Unwrap<OpenMPConstruct>(last)}) { + return GetFinalLabel(*omp); + } else if (auto *doLoop{Unwrap<DoConstruct>(last)}) { + return GetFinalLabel(std::get<Block>(doLoop->t)); + } else { + return GetStatementLabel(x.back()); + } + } else { + return std::nullopt; + } +} + +std::optional<Label> GetFinalLabel(const OpenMPConstruct &x) { + return common::visit( + [](auto &&s) -> std::optional<Label> { + using TypeS = llvm::remove_cvref_t<decltype(s)>; + if constexpr (std::is_same_v<TypeS, OpenMPSectionsConstruct>) { + auto &list{std::get<std::list<OpenMPConstruct>>(s.t)}; + if (!list.empty()) { + return GetFinalLabel(list.back()); + } else { + return std::nullopt; + } + } else if constexpr ( // + std::is_same_v<TypeS, OpenMPLoopConstruct> || + std::is_same_v<TypeS, OpenMPSectionConstruct> || + std::is_base_of_v<OmpBlockConstruct, TypeS>) { + return GetFinalLabel(std::get<Block>(s.t)); + } else { + return std::nullopt; + } + }, + x.u); +} + const OmpObjectList *GetOmpObjectList(const OmpClause &clause) { - // Clauses with OmpObjectList as its data member - using MemberObjectListClauses = std::tuple<OmpClause::Copyin, - OmpClause::Copyprivate, OmpClause::Exclusive, OmpClause::Firstprivate, - OmpClause::HasDeviceAddr, OmpClause::Inclusive, OmpClause::IsDevicePtr, - OmpClause::Link, OmpClause::Private, OmpClause::Shared, - OmpClause::UseDeviceAddr, OmpClause::UseDevicePtr>; - - // Clauses with OmpObjectList in the tuple - using TupleObjectListClauses = std::tuple<OmpClause::AdjustArgs, - OmpClause::Affinity, OmpClause::Aligned, OmpClause::Allocate, - OmpClause::Enter, OmpClause::From, OmpClause::InReduction, - OmpClause::Lastprivate, OmpClause::Linear, OmpClause::Map, - OmpClause::Reduction, OmpClause::TaskReduction, OmpClause::To>; - - // TODO:: Generate the tuples using TableGen. + return common::visit([](auto &&s) { return GetOmpObjectList(s); }, clause.u); +} + +const OmpObjectList *GetOmpObjectList(const OmpClause::Depend &clause) { return common::visit( common::visitors{ - [&](const OmpClause::Depend &x) -> const OmpObjectList * { - if (auto *taskDep{std::get_if<OmpDependClause::TaskDep>(&x.v.u)}) { - return &std::get<OmpObjectList>(taskDep->t); - } else { - return nullptr; - } - }, - [&](const auto &x) -> const OmpObjectList * { - using Ty = std::decay_t<decltype(x)>; - if constexpr (common::HasMember<Ty, MemberObjectListClauses>) { - return &x.v; - } else if constexpr (common::HasMember<Ty, - TupleObjectListClauses>) { - return &std::get<OmpObjectList>(x.v.t); - } else { - return nullptr; - } - }, + [](const OmpDoacross &) -> const OmpObjectList * { return nullptr; }, + [](const OmpDependClause::TaskDep &x) { return GetOmpObjectList(x); }, }, - clause.u); + clause.v.u); +} + +const OmpObjectList *GetOmpObjectList(const OmpDependClause::TaskDep &x) { + return &std::get<OmpObjectList>(x.t); } const BlockConstruct *GetFortranBlockConstruct( @@ -74,6 +145,34 @@ const BlockConstruct *GetFortranBlockConstruct( return nullptr; } +/// parser::Block is a list of executable constructs, parser::BlockConstruct +/// is Fortran's BLOCK/ENDBLOCK construct. +/// Strip the outermost BlockConstructs, return the reference to the Block +/// in the executable part of the innermost of the stripped constructs. +/// Specifically, if the given `block` has a single entry (it's a list), and +/// the entry is a BlockConstruct, get the Block contained within. Repeat +/// this step as many times as possible. +const Block &GetInnermostExecPart(const Block &block) { + const Block *iter{&block}; + while (iter->size() == 1) { + const ExecutionPartConstruct &ep{iter->front()}; + if (auto *bc{GetFortranBlockConstruct(ep)}) { + iter = &std::get<Block>(bc->t); + } else { + break; + } + } + return *iter; +} + +bool IsStrictlyStructuredBlock(const Block &block) { + if (block.size() == 1) { + return GetFortranBlockConstruct(block.front()) != nullptr; + } else { + return false; + } +} + const OmpCombinerExpression *GetCombinerExpr( const OmpReductionSpecifier &rspec) { return addr_if(std::get<std::optional<OmpCombinerExpression>>(rspec.t)); @@ -86,4 +185,24 @@ const OmpInitializerExpression *GetInitializerExpr(const OmpClause &init) { return nullptr; } +static void SplitOmpAllocateHelper( + OmpAllocateInfo &n, const OmpAllocateDirective &x) { + n.dirs.push_back(&x); + const Block &body{std::get<Block>(x.t)}; + if (!body.empty()) { + if (auto *omp{GetOmp(body.front())}) { + if (auto *ad{std::get_if<OmpAllocateDirective>(&omp->u)}) { + return SplitOmpAllocateHelper(n, *ad); + } + } + n.body = &body.front(); + } +} + +OmpAllocateInfo SplitOmpAllocate(const OmpAllocateDirective &x) { + OmpAllocateInfo info; + SplitOmpAllocateHelper(info, x); + return info; +} + } // namespace Fortran::parser::omp diff --git a/flang/lib/Parser/parse-tree.cpp b/flang/lib/Parser/parse-tree.cpp index ad0016e..53d4e4e 100644 --- a/flang/lib/Parser/parse-tree.cpp +++ b/flang/lib/Parser/parse-tree.cpp @@ -7,8 +7,10 @@ //===----------------------------------------------------------------------===// #include "flang/Parser/parse-tree.h" + #include "flang/Common/idioms.h" #include "flang/Common/indirection.h" +#include "flang/Parser/openmp-utils.h" #include "flang/Parser/tools.h" #include "flang/Parser/user-state.h" #include "llvm/ADT/ArrayRef.h" @@ -432,6 +434,39 @@ const OmpClauseList &OmpDirectiveSpecification::Clauses() const { return empty; } +const DoConstruct *OpenMPLoopConstruct::GetNestedLoop() const { + auto getFromBlock{[](const Block &body, auto self) -> const DoConstruct * { + for (auto &stmt : body) { + if (auto *block{Unwrap<BlockConstruct>(&stmt)}) { + return self(std::get<Block>(block->t), self); + } + if (auto *loop{Unwrap<DoConstruct>(&stmt)}) { + return loop; + } + } + return nullptr; + }}; + + return getFromBlock(std::get<Block>(t), getFromBlock); +} + +const OpenMPLoopConstruct *OpenMPLoopConstruct::GetNestedConstruct() const { + auto getFromBlock{ + [](const Block &body, auto self) -> const OpenMPLoopConstruct * { + for (auto &stmt : body) { + if (auto *block{Unwrap<BlockConstruct>(&stmt)}) { + return self(std::get<Block>(block->t), self); + } + if (auto *omp{Unwrap<OpenMPLoopConstruct>(&stmt)}) { + return omp; + } + } + return nullptr; + }}; + + return getFromBlock(std::get<Block>(t), getFromBlock); +} + static bool InitCharBlocksFromStrings(llvm::MutableArrayRef<CharBlock> blocks, llvm::ArrayRef<std::string> strings) { for (auto [i, n] : llvm::enumerate(strings)) { diff --git a/flang/lib/Parser/preprocessor.cpp b/flang/lib/Parser/preprocessor.cpp index 9176b4d..529d2c3 100644 --- a/flang/lib/Parser/preprocessor.cpp +++ b/flang/lib/Parser/preprocessor.cpp @@ -43,6 +43,9 @@ Definition::Definition(const std::string &predefined, AllSources &sources) replacement_{ predefined, sources.AddCompilerInsertion(predefined).start()} {} +Definition::Definition(const TokenSequence &repl) + : isPredefined_{true}, replacement_{repl} {} + bool Definition::set_isDisabled(bool disable) { bool was{isDisabled_}; isDisabled_ = disable; @@ -371,40 +374,66 @@ TokenSequence Preprocessor::TokenizeMacroBody(const std::string &str) { Provenance provenance{allSources_.AddCompilerInsertion(str).start()}; auto end{str.size()}; for (std::string::size_type at{0}; at < end;) { - // Alternate between tokens that are identifiers (and therefore subject - // to argument replacement) and those that are not. - auto start{str.find_first_of(idChars, at)}; - if (start == str.npos) { - tokens.Put(str.substr(at), provenance + at); - break; - } else if (start > at) { - tokens.Put(str.substr(at, start - at), provenance + at); + char ch{str.at(at)}; + if (IsWhiteSpace(ch)) { + ++at; + continue; } - at = str.find_first_not_of(idChars, start + 1); - if (at == str.npos) { + std::string::size_type start{at}; + if (IsLegalIdentifierStart(ch)) { + for (++at; at < end && IsLegalInIdentifier(str.at(at)); ++at) { + } + } else if (IsDecimalDigit(ch) || ch == '.') { + for (++at; at < end; ++at) { + ch = str.at(at); + if (!IsDecimalDigit(ch) && ch != '.') { + break; + } + } + if (at < end) { + ch = ToUpperCaseLetter(str.at(at)); + if (ch == 'E' || ch == 'D' || ch == 'Q') { + if (++at < end) { + ch = str.at(at); + if (ch == '+' || ch == '-') { + ++at; + } + for (; at < end && IsDecimalDigit(str.at(at)); ++at) { + } + } + } + } + } else if (ch == '\'' || ch == '"') { + for (++at; at < end && str.at(at) != ch; ++at) { + } + if (at < end) { + ++at; + } + } else { + ++at; // single-character token + } + if (at >= end || at == str.npos) { tokens.Put(str.substr(start), provenance + start); break; - } else { - tokens.Put(str.substr(start, at - start), provenance + start); } + tokens.Put(str.substr(start, at - start), provenance + start); } return tokens; } void Preprocessor::Define(const std::string ¯o, const std::string &value) { + TokenSequence rhs{TokenizeMacroBody(value)}; if (auto lhs{TokenizeMacroNameAndArgs(macro)}) { // function-like macro CharBlock macroName{SaveTokenAsName(lhs->front())}; auto iter{lhs->begin()}; ++iter; std::vector<std::string> argNames{iter, lhs->end()}; - auto rhs{TokenizeMacroBody(value)}; definitions_.emplace(std::make_pair(macroName, Definition{ argNames, rhs, 0, rhs.SizeInTokens(), /*isVariadic=*/false})); } else { // keyword macro - definitions_.emplace( - SaveTokenAsName(macro), Definition{value, allSources_}); + definitions_.emplace(SaveTokenAsName(macro), Definition{rhs}); } } diff --git a/flang/lib/Parser/prescan.cpp b/flang/lib/Parser/prescan.cpp index efce8fc..5e8d50b 100644 --- a/flang/lib/Parser/prescan.cpp +++ b/flang/lib/Parser/prescan.cpp @@ -557,7 +557,7 @@ bool Prescanner::MustSkipToEndOfLine() const { return true; // skip over ignored columns in right margin (73:80) } else if (*at_ == '!' && !inCharLiteral_ && (!inFixedForm_ || tabInCurrentLine_ || column_ != 6)) { - return !IsCompilerDirectiveSentinel(at_ + 1); + return InCompilerDirective() || !IsCompilerDirectiveSentinel(at_ + 1); } else { return false; } @@ -845,6 +845,9 @@ bool Prescanner::NextToken(TokenSequence &tokens) { if (InFixedFormSource()) { SkipSpaces(); } + if (inFixedForm_ && (IsOpenMPDirective() && parenthesisNesting_ > 0)) { + SkipSpaces(); + } if ((*at_ == '\'' || *at_ == '"') && tokens.CharAt(tokens.SizeInChars() - 1) == '_') { // kind_"..." QuotedCharacterLiteral(tokens, start); diff --git a/flang/lib/Parser/prescan.h b/flang/lib/Parser/prescan.h index 5e74817..4f691d5 100644 --- a/flang/lib/Parser/prescan.h +++ b/flang/lib/Parser/prescan.h @@ -183,6 +183,9 @@ private: bool InConditionalLine() const { return InOpenMPConditionalLine() || InOpenACCOrCUDAConditionalLine(); } + bool IsOpenMPDirective() const { + return directiveSentinel_ && std::strcmp(directiveSentinel_, "$omp") == 0; + } bool InFixedFormSource() const { return inFixedForm_ && !inPreprocessorDirective_ && !InCompilerDirective(); } diff --git a/flang/lib/Parser/program-parsers.cpp b/flang/lib/Parser/program-parsers.cpp index 740dbbf..3033359 100644 --- a/flang/lib/Parser/program-parsers.cpp +++ b/flang/lib/Parser/program-parsers.cpp @@ -201,6 +201,9 @@ TYPE_CONTEXT_PARSER("specification construct"_en_US, construct<SpecificationConstruct>( indirect(openaccDeclarativeConstruct)), construct<SpecificationConstruct>(indirect(openmpDeclarativeConstruct)), + construct<SpecificationConstruct>( + indirect(openmpMisplacedEndDirective)), + construct<SpecificationConstruct>(indirect(openmpInvalidDirective)), construct<SpecificationConstruct>(indirect(compilerDirective)))) // R513 other-specification-stmt -> diff --git a/flang/lib/Parser/type-parsers.h b/flang/lib/Parser/type-parsers.h index 3900c5a..142aa22 100644 --- a/flang/lib/Parser/type-parsers.h +++ b/flang/lib/Parser/type-parsers.h @@ -139,7 +139,8 @@ constexpr Parser<OpenACCDeclarativeConstruct> openaccDeclarativeConstruct; constexpr Parser<OpenMPConstruct> openmpConstruct; constexpr Parser<OpenMPExecDirective> openmpExecDirective; constexpr Parser<OpenMPDeclarativeConstruct> openmpDeclarativeConstruct; -constexpr Parser<OmpEndLoopDirective> ompEndLoopDirective; +constexpr Parser<OpenMPMisplacedEndDirective> openmpMisplacedEndDirective; +constexpr Parser<OpenMPInvalidDirective> openmpInvalidDirective; constexpr Parser<IntrinsicVectorTypeSpec> intrinsicVectorTypeSpec; // Extension constexpr Parser<VectorTypeSpec> vectorTypeSpec; // Extension constexpr Parser<UnsignedTypeSpec> unsignedTypeSpec; // Extension diff --git a/flang/lib/Parser/unparse.cpp b/flang/lib/Parser/unparse.cpp index 9b38cfc..f90e329 100644 --- a/flang/lib/Parser/unparse.cpp +++ b/flang/lib/Parser/unparse.cpp @@ -819,6 +819,7 @@ public: Word("TEAM="); } } + void Before(const ImageSelectorSpec::Notify &) { Word("NOTIFY="); } void Unparse(const AllocateStmt &x) { // R927 Word("ALLOCATE("); Walk(std::get<std::optional<TypeSpec>>(x.t), "::"); @@ -1847,6 +1848,25 @@ public: [&](const CompilerDirective::VectorAlways &valways) { Word("!DIR$ VECTOR ALWAYS"); }, + [&](const CompilerDirective::VectorLength &vlength) { + using Kind = CompilerDirective::VectorLength::Kind; + std::uint64_t length = std::get<std::uint64_t>(vlength.t); + Kind kind = std::get<Kind>(vlength.t); + + Word("!DIR$ VECTOR VECTORLENGTH ("); + // || kind == Kind::Auto handles the case of VECTORLENGTH(0) so we + // don't print nothing + if (length != 0 || kind == Kind::Auto) { + Walk(length); + } + if (length != 0 && kind != Kind::Auto) { + Word(", "); + } + if (kind != Kind::Auto) { + Word(CompilerDirective::VectorLength::EnumToString(kind)); + } + Word(")"); + }, [&](const std::list<CompilerDirective::NameValue> &names) { Walk("!DIR$ ", names, " "); }, @@ -1854,6 +1874,10 @@ public: Word("!DIR$ UNROLL"); Walk(" ", unroll.v); }, + [&](const CompilerDirective::Prefetch &prefetch) { + Word("!DIR$ PREFETCH"); + Walk(" ", prefetch.v); + }, [&](const CompilerDirective::UnrollAndJam &unrollAndJam) { Word("!DIR$ UNROLL_AND_JAM"); Walk(" ", unrollAndJam.v); @@ -1874,6 +1898,7 @@ public: [&](const CompilerDirective::NoInline &) { Word("!DIR$ NOINLINE"); }, + [&](const CompilerDirective::IVDep &) { Word("!DIR$ IVDEP"); }, [&](const CompilerDirective::Unrecognized &) { Word("!DIR$ "); Word(x.source.ToString()); @@ -2136,7 +2161,7 @@ public: Walk(std::get<OmpDirectiveName>(x.t)); auto flags{std::get<OmpDirectiveSpecification::Flags>(x.t)}; - if (flags == OmpDirectiveSpecification::Flags::DeprecatedSyntax) { + if (flags.test(OmpDirectiveSpecification::Flag::DeprecatedSyntax)) { if (x.DirId() == llvm::omp::Directive::OMPD_flush) { // FLUSH clause arglist unparseClauses(); @@ -2281,6 +2306,11 @@ public: Walk(std::get<OmpObjectList>(x.t)); Walk(": ", std::get<std::optional<std::list<Modifier>>>(x.t)); } + void Unparse(const OmpFallbackModifier &x) { + Word("FALLBACK("); + Walk(x.v); + Put(")"); + } void Unparse(const OmpDynGroupprivateClause &x) { using Modifier = OmpDynGroupprivateClause::Modifier; Walk(std::get<std::optional<std::list<Modifier>>>(x.t), ": "); @@ -2359,7 +2389,7 @@ public: } } } - void Unparse(const OmpLoopRangeClause &x) { + void Unparse(const OmpLooprangeClause &x) { Word("LOOPRANGE("); Walk(std::get<0>(x.t)); Put(", "); @@ -2482,32 +2512,8 @@ public: Unparse(static_cast<const OmpBlockConstruct &>(x)); } - void Unparse(const OpenMPExecutableAllocate &x) { - const auto &fields = - std::get<std::optional<std::list<parser::OpenMPDeclarativeAllocate>>>( - x.t); - if (fields) { - for (const auto &decl : *fields) { - Walk(decl); - } - } - BeginOpenMP(); - Word("!$OMP ALLOCATE"); - Walk(" (", std::get<std::optional<OmpObjectList>>(x.t), ")"); - Walk(std::get<OmpClauseList>(x.t)); - Put("\n"); - EndOpenMP(); - Walk(std::get<Statement<AllocateStmt>>(x.t)); - } - void Unparse(const OpenMPDeclarativeAllocate &x) { - BeginOpenMP(); - Word("!$OMP ALLOCATE"); - Put(" ("); - Walk(std::get<OmpObjectList>(x.t)); - Put(")"); - Walk(std::get<OmpClauseList>(x.t)); - Put("\n"); - EndOpenMP(); + void Unparse(const OmpAllocateDirective &x) { + Unparse(static_cast<const OmpBlockConstruct &>(x)); } void Unparse(const OpenMPAllocatorsConstruct &x) { Unparse(static_cast<const OmpBlockConstruct &>(x)); @@ -2552,8 +2558,8 @@ public: void Unparse(const OpenMPInteropConstruct &x) { BeginOpenMP(); Word("!$OMP INTEROP"); - using Flags = OmpDirectiveSpecification::Flags; - if (std::get<Flags>(x.v.t) == Flags::DeprecatedSyntax) { + auto flags{std::get<OmpDirectiveSpecification::Flags>(x.v.t)}; + if (flags.test(OmpDirectiveSpecification::Flag::DeprecatedSyntax)) { Walk("(", std::get<std::optional<OmpArgumentList>>(x.v.t), ")"); Walk(" ", std::get<std::optional<OmpClauseList>>(x.v.t)); } else { @@ -2692,8 +2698,8 @@ public: void Unparse(const OpenMPFlushConstruct &x) { BeginOpenMP(); Word("!$OMP FLUSH"); - using Flags = OmpDirectiveSpecification::Flags; - if (std::get<Flags>(x.v.t) == Flags::DeprecatedSyntax) { + auto flags{std::get<OmpDirectiveSpecification::Flags>(x.v.t)}; + if (flags.test(OmpDirectiveSpecification::Flag::DeprecatedSyntax)) { Walk("(", std::get<std::optional<OmpArgumentList>>(x.v.t), ")"); Walk(" ", std::get<std::optional<OmpClauseList>>(x.v.t)); } else { @@ -2719,11 +2725,15 @@ public: Put("\n"); EndOpenMP(); } - void Unparse(const OpenMPLoopConstruct &x) { - Walk(std::get<OmpBeginLoopDirective>(x.t)); - Walk(std::get<std::optional<std::variant<DoConstruct, - common::Indirection<parser::OpenMPLoopConstruct>>>>(x.t)); - Walk(std::get<std::optional<OmpEndLoopDirective>>(x.t)); + void Unparse(const OpenMPMisplacedEndDirective &x) { + Unparse(static_cast<const OmpEndDirective &>(x)); + } + void Unparse(const OpenMPInvalidDirective &x) { + BeginOpenMP(); + Word("!$OMP "); + Put(parser::ToUpperCaseLetters(x.source.ToString())); + Put("\n"); + EndOpenMP(); } void Unparse(const BasedPointer &x) { Put('('), Walk(std::get<0>(x.t)), Put(","), Walk(std::get<1>(x.t)); @@ -2808,12 +2818,14 @@ public: WALK_NESTED_ENUM(OmpTaskDependenceType, Value) // OMP task-dependence-type WALK_NESTED_ENUM(OmpScheduleClause, Kind) // OMP schedule-kind WALK_NESTED_ENUM(OmpSeverityClause, Severity) // OMP severity + WALK_NESTED_ENUM(OmpThreadsetClause, ThreadsetPolicy) // OMP threadset WALK_NESTED_ENUM(OmpAccessGroup, Value) WALK_NESTED_ENUM(OmpDeviceModifier, Value) // OMP device modifier WALK_NESTED_ENUM( OmpDeviceTypeClause, DeviceTypeDescription) // OMP device_type WALK_NESTED_ENUM(OmpReductionModifier, Value) // OMP reduction-modifier WALK_NESTED_ENUM(OmpExpectation, Value) // OMP motion-expectation + WALK_NESTED_ENUM(OmpFallbackModifier, Value) // OMP fallback-modifier WALK_NESTED_ENUM(OmpInteropType, Value) // OMP InteropType WALK_NESTED_ENUM(OmpOrderClause, Ordering) // OMP ordering WALK_NESTED_ENUM(OmpOrderModifier, Value) // OMP order-modifier diff --git a/flang/lib/Semantics/canonicalize-directives.cpp b/flang/lib/Semantics/canonicalize-directives.cpp index a651a87..f32a3d3 100644 --- a/flang/lib/Semantics/canonicalize-directives.cpp +++ b/flang/lib/Semantics/canonicalize-directives.cpp @@ -56,6 +56,7 @@ bool CanonicalizeDirectives( static bool IsExecutionDirective(const parser::CompilerDirective &dir) { return std::holds_alternative<parser::CompilerDirective::VectorAlways>( dir.u) || + std::holds_alternative<parser::CompilerDirective::VectorLength>(dir.u) || std::holds_alternative<parser::CompilerDirective::Unroll>(dir.u) || std::holds_alternative<parser::CompilerDirective::UnrollAndJam>(dir.u) || std::holds_alternative<parser::CompilerDirective::NoVector>(dir.u) || @@ -64,7 +65,8 @@ static bool IsExecutionDirective(const parser::CompilerDirective &dir) { dir.u) || std::holds_alternative<parser::CompilerDirective::ForceInline>(dir.u) || std::holds_alternative<parser::CompilerDirective::Inline>(dir.u) || - std::holds_alternative<parser::CompilerDirective::NoInline>(dir.u); + std::holds_alternative<parser::CompilerDirective::NoInline>(dir.u) || + std::holds_alternative<parser::CompilerDirective::IVDep>(dir.u); } void CanonicalizationOfDirectives::Post(parser::SpecificationPart &spec) { @@ -120,6 +122,9 @@ void CanonicalizationOfDirectives::Post(parser::Block &block) { common::visitors{[&](parser::CompilerDirective::VectorAlways &) { CheckLoopDirective(*dir, block, it); }, + [&](parser::CompilerDirective::VectorLength &) { + CheckLoopDirective(*dir, block, it); + }, [&](parser::CompilerDirective::Unroll &) { CheckLoopDirective(*dir, block, it); }, @@ -135,6 +140,9 @@ void CanonicalizationOfDirectives::Post(parser::Block &block) { [&](parser::CompilerDirective::NoUnrollAndJam &) { CheckLoopDirective(*dir, block, it); }, + [&](parser::CompilerDirective::IVDep &) { + CheckLoopDirective(*dir, block, it); + }, [&](auto &) {}}, dir->u); } diff --git a/flang/lib/Semantics/canonicalize-do.cpp b/flang/lib/Semantics/canonicalize-do.cpp index ef20cff..8b23f88 100644 --- a/flang/lib/Semantics/canonicalize-do.cpp +++ b/flang/lib/Semantics/canonicalize-do.cpp @@ -7,7 +7,9 @@ //===----------------------------------------------------------------------===// #include "canonicalize-do.h" +#include "flang/Parser/openmp-utils.h" #include "flang/Parser/parse-tree-visitor.h" +#include "flang/Parser/tools.h" namespace Fortran::parser { @@ -87,6 +89,16 @@ public: [&](Statement<ActionStmt> &actionStmt) { CanonicalizeIfMatch(block, stack, i, actionStmt); }, + [&](common::Indirection<OpenMPConstruct> &construct) { + // If the body of the OpenMP construct ends with a label, + // treat the label as ending the construct itself. + OpenMPConstruct &omp{construct.value()}; + if (CanonicalizeIfMatch( + block, stack, i, omp::GetFinalLabel(omp))) { + MarkOpenMPConstruct( + omp, OmpDirectiveSpecification::Flag::CrossesLabelDo); + } + }, }, executableConstruct->u); } @@ -95,12 +107,16 @@ public: private: template <typename T> - void CanonicalizeIfMatch(Block &originalBlock, std::vector<LabelInfo> &stack, + bool CanonicalizeIfMatch(Block &originalBlock, std::vector<LabelInfo> &stack, Block::iterator &i, Statement<T> &statement) { - if (!stack.empty() && statement.label && - stack.back().label == *statement.label) { + return CanonicalizeIfMatch(originalBlock, stack, i, statement.label); + } + + bool CanonicalizeIfMatch(Block &originalBlock, std::vector<LabelInfo> &stack, + Block::iterator &i, std::optional<Label> label) { + if (!stack.empty() && label && stack.back().label == *label) { auto currentLabel{stack.back().label}; - if constexpr (std::is_same_v<T, common::Indirection<EndDoStmt>>) { + if (Unwrap<EndDoStmt>(*i)) { std::get<ExecutableConstruct>(i->u).u = Statement<ActionStmt>{ std::optional<Label>{currentLabel}, ContinueStmt{}}; } @@ -129,8 +145,27 @@ private: stack.pop_back(); } while (!stack.empty() && stack.back().label == currentLabel); i = --next; + return true; + } else { + return false; } } + + void MarkOpenMPConstruct( + OpenMPConstruct &omp, OmpDirectiveSpecification::Flag flag) { + common::visit( + [&](const auto &s) { + using S = std::decay_t<decltype(s)>; + if constexpr (std::is_base_of_v<OmpBlockConstruct, S> || + std::is_same_v<OpenMPLoopConstruct, S>) { + const OmpDirectiveSpecification &beginSpec{s.BeginDir()}; + auto &flags{ + std::get<OmpDirectiveSpecification::Flags>(beginSpec.t)}; + const_cast<OmpDirectiveSpecification::Flags &>(flags).set(flag); + } + }, + omp.u); + } }; bool CanonicalizeDo(Program &program) { diff --git a/flang/lib/Semantics/canonicalize-omp.cpp b/flang/lib/Semantics/canonicalize-omp.cpp index c884658..802b2ac 100644 --- a/flang/lib/Semantics/canonicalize-omp.cpp +++ b/flang/lib/Semantics/canonicalize-omp.cpp @@ -9,6 +9,7 @@ #include "canonicalize-omp.h" #include "flang/Parser/parse-tree-visitor.h" #include "flang/Parser/parse-tree.h" +#include "flang/Semantics/openmp-directive-sets.h" #include "flang/Semantics/semantics.h" // After Loop Canonicalization, rewrite OpenMP parse tree to make OpenMP @@ -31,28 +32,6 @@ public: CanonicalizationOfOmp(SemanticsContext &context) : context_{context}, messages_{context.messages()} {} - void Post(parser::Block &block) { - for (auto it{block.begin()}; it != block.end(); ++it) { - if (auto *ompCons{GetConstructIf<parser::OpenMPConstruct>(*it)}) { - // OpenMPLoopConstruct - if (auto *ompLoop{ - std::get_if<parser::OpenMPLoopConstruct>(&ompCons->u)}) { - RewriteOpenMPLoopConstruct(*ompLoop, block, it); - } - } else if (auto *endDir{ - GetConstructIf<parser::OmpEndLoopDirective>(*it)}) { - // Unmatched OmpEndLoopDirective - const parser::OmpDirectiveName &endName{endDir->DirName()}; - messages_.Say(endName.source, - "The %s directive must follow the DO loop associated with the " - "loop construct"_err_en_US, - parser::ToUpperCaseLetters(endName.source.ToString())); - } - } // Block list - } - - void Post(parser::ExecutionPart &body) { RewriteOmpAllocations(body); } - // Pre-visit all constructs that have both a specification part and // an execution part, and store the connection between the two. bool Pre(parser::BlockConstruct &x) { @@ -88,184 +67,144 @@ public: void Post(parser::SpecificationPart &spec) { CanonicalizeUtilityConstructs(spec); + CanonicalizeAllocateDirectives(spec); } void Post(parser::OmpMapClause &map) { CanonicalizeMapModifiers(map); } private: - template <typename T> T *GetConstructIf(parser::ExecutionPartConstruct &x) { - if (auto *y{std::get_if<parser::ExecutableConstruct>(&x.u)}) { - if (auto *z{std::get_if<common::Indirection<T>>(&y->u)}) { - return &z->value(); - } + // Canonicalization of allocate directives + // + // In OpenMP 5.0 and 5.1 the allocate directive could either be a declarative + // one or an executable one. As usual in such cases, this poses a problem + // when the directive appears at the boundary between the specification part + // and the execution part. + // The executable form can actually consist of several adjacent directives, + // whereas the declarative form is always standalone. Additionally, the + // executable form must be associated with an allocate statement. + // + // The parser tries to parse declarative statements first, so in the + // following case, the two directives will be declarative, even though + // they should be treated as a single executable form: + // integer, allocatable :: x, y ! Specification + // !$omp allocate(x) + // !$omp allocate(y) + // allocate(x, y) ! Execution + // + void CanonicalizeAllocateDirectives(parser::SpecificationPart &spec) { + auto found = blockForSpec_.find(&spec); + if (found == blockForSpec_.end()) { + // There is no corresponding execution part, so there is nothing to do. + return; } - return nullptr; - } + parser::Block &block = *found->second; - template <typename T> T *GetOmpIf(parser::ExecutionPartConstruct &x) { - if (auto *construct{GetConstructIf<parser::OpenMPConstruct>(x)}) { - if (auto *omp{std::get_if<T>(&construct->u)}) { - return omp; + auto isAllocateStmt = [](const parser::ExecutionPartConstruct &epc) { + if (auto *ec = std::get_if<parser::ExecutableConstruct>(&epc.u)) { + if (auto *as = + std::get_if<parser::Statement<parser::ActionStmt>>(&ec->u)) { + return std::holds_alternative< + common::Indirection<parser::AllocateStmt>>(as->statement.u); + } + } + return false; + }; + + if (!block.empty() && isAllocateStmt(block.front())) { + // There are two places where an OpenMP declarative construct can + // show up in the tuple in specification part: + // (1) in std::list<OpenMPDeclarativeConstruct>, or + // (2) in std::list<DeclarationConstruct>. + // The case (1) is only possible if the list (2) is empty. + + auto &omps = + std::get<std::list<parser::OpenMPDeclarativeConstruct>>(spec.t); + auto &decls = std::get<std::list<parser::DeclarationConstruct>>(spec.t); + + if (!decls.empty()) { + MakeExecutableAllocateFromDecls(decls, block); + } else { + MakeExecutableAllocateFromOmps(omps, block); } } - return nullptr; } - void RewriteOpenMPLoopConstruct(parser::OpenMPLoopConstruct &x, - parser::Block &block, parser::Block::iterator it) { - // Check the sequence of DoConstruct and OmpEndLoopDirective - // in the same iteration - // - // Original: - // ExecutableConstruct -> OpenMPConstruct -> OpenMPLoopConstruct - // OmpBeginLoopDirective - // ExecutableConstruct -> DoConstruct - // ExecutableConstruct -> OmpEndLoopDirective (if available) - // - // After rewriting: - // ExecutableConstruct -> OpenMPConstruct -> OpenMPLoopConstruct - // OmpBeginLoopDirective - // DoConstruct - // OmpEndLoopDirective (if available) - parser::Block::iterator nextIt; - const parser::OmpDirectiveSpecification &beginDir{x.BeginDir()}; - const parser::OmpDirectiveName &beginName{beginDir.DirName()}; - - auto missingDoConstruct = [](const parser::OmpDirectiveName &dirName, - parser::Messages &messages) { - messages.Say(dirName.source, - "A DO loop must follow the %s directive"_err_en_US, - parser::ToUpperCaseLetters(dirName.source.ToString())); - }; - auto tileUnrollError = [](const parser::OmpDirectiveName &dirName, - parser::Messages &messages) { - messages.Say(dirName.source, - "If a loop construct has been fully unrolled, it cannot then be tiled"_err_en_US, - parser::ToUpperCaseLetters(dirName.source.ToString())); - }; + parser::ExecutionPartConstruct EmbedInExec( + parser::OmpAllocateDirective *alo, parser::ExecutionPartConstruct &&epc) { + // Nest current epc inside the allocate directive. + std::get<parser::Block>(alo->t).push_front(std::move(epc)); + // Set the new epc to be the ExecutionPartConstruct made from + // the allocate directive. + parser::OpenMPConstruct opc(std::move(*alo)); + common::Indirection<parser::OpenMPConstruct> ind(std::move(opc)); + parser::ExecutableConstruct ec(std::move(ind)); + return parser::ExecutionPartConstruct(std::move(ec)); + } - nextIt = it; - while (++nextIt != block.end()) { - // Ignore compiler directives. - if (GetConstructIf<parser::CompilerDirective>(*nextIt)) - continue; - - if (auto *doCons{GetConstructIf<parser::DoConstruct>(*nextIt)}) { - if (doCons->GetLoopControl()) { - // move DoConstruct - std::get<std::optional<std::variant<parser::DoConstruct, - common::Indirection<parser::OpenMPLoopConstruct>>>>(x.t) = - std::move(*doCons); - nextIt = block.erase(nextIt); - // try to match OmpEndLoopDirective - if (nextIt != block.end()) { - if (auto *endDir{ - GetConstructIf<parser::OmpEndLoopDirective>(*nextIt)}) { - std::get<std::optional<parser::OmpEndLoopDirective>>(x.t) = - std::move(*endDir); - nextIt = block.erase(nextIt); - } + void MakeExecutableAllocateFromDecls( + std::list<parser::DeclarationConstruct> &decls, parser::Block &body) { + using OpenMPDeclarativeConstruct = + common::Indirection<parser::OpenMPDeclarativeConstruct>; + + auto getAllocate = [](parser::DeclarationConstruct *dc) { + if (auto *sc = std::get_if<parser::SpecificationConstruct>(&dc->u)) { + if (auto *odc = std::get_if<OpenMPDeclarativeConstruct>(&sc->u)) { + if (auto *alo = + std::get_if<parser::OmpAllocateDirective>(&odc->value().u)) { + return alo; } - } else { - messages_.Say(beginName.source, - "DO loop after the %s directive must have loop control"_err_en_US, - parser::ToUpperCaseLetters(beginName.source.ToString())); } - } else if (auto *ompLoopCons{ - GetOmpIf<parser::OpenMPLoopConstruct>(*nextIt)}) { - // We should allow UNROLL and TILE constructs to be inserted between an - // OpenMP Loop Construct and the DO loop itself - auto &nestedBeginDirective = ompLoopCons->BeginDir(); - auto &nestedBeginName = nestedBeginDirective.DirName(); - if ((nestedBeginName.v == llvm::omp::Directive::OMPD_unroll || - nestedBeginName.v == llvm::omp::Directive::OMPD_tile) && - !(nestedBeginName.v == llvm::omp::Directive::OMPD_unroll && - beginName.v == llvm::omp::Directive::OMPD_tile)) { - // iterate through the remaining block items to find the end directive - // for the unroll/tile directive. - parser::Block::iterator endIt; - endIt = nextIt; - while (endIt != block.end()) { - if (auto *endDir{ - GetConstructIf<parser::OmpEndLoopDirective>(*endIt)}) { - auto &endDirName = endDir->DirName(); - if (endDirName.v == beginName.v) { - std::get<std::optional<parser::OmpEndLoopDirective>>(x.t) = - std::move(*endDir); - endIt = block.erase(endIt); - continue; - } - } - ++endIt; - } - RewriteOpenMPLoopConstruct(*ompLoopCons, block, nextIt); - auto &ompLoop = std::get<std::optional<parser::NestedConstruct>>(x.t); - ompLoop = - std::optional<parser::NestedConstruct>{parser::NestedConstruct{ - common::Indirection{std::move(*ompLoopCons)}}}; - nextIt = block.erase(nextIt); - } else if (nestedBeginName.v == llvm::omp::Directive::OMPD_unroll && - beginName.v == llvm::omp::Directive::OMPD_tile) { - // if a loop has been unrolled, the user can not then tile that loop - // as it has been unrolled - const parser::OmpClauseList &unrollClauseList{ - nestedBeginDirective.Clauses()}; - if (unrollClauseList.v.empty()) { - // if the clause list is empty for an unroll construct, we assume - // the loop is being fully unrolled - tileUnrollError(beginName, messages_); - } else { - // parse the clauses for the unroll directive to find the full - // clause - for (auto &clause : unrollClauseList.v) { - if (clause.Id() == llvm::omp::OMPC_full) { - tileUnrollError(beginName, messages_); - } - } - } - } else { - messages_.Say(nestedBeginName.source, - "Only Loop Transformation Constructs or Loop Nests can be nested within Loop Constructs"_err_en_US, - parser::ToUpperCaseLetters(nestedBeginName.source.ToString())); + } + return static_cast<parser::OmpAllocateDirective *>(nullptr); + }; + + std::list<parser::DeclarationConstruct>::reverse_iterator rlast = [&]() { + for (auto rit = decls.rbegin(), rend = decls.rend(); rit != rend; ++rit) { + if (getAllocate(&*rit) == nullptr) { + return rit; } - } else { - missingDoConstruct(beginName, messages_); } - // If we get here, we either found a loop, or issued an error message. - return; - } - if (nextIt == block.end()) { - missingDoConstruct(beginName, messages_); + return decls.rend(); + }(); + + if (rlast != decls.rbegin()) { + // We have already checked that the first statement in body is + // ALLOCATE. + parser::ExecutionPartConstruct epc(std::move(body.front())); + for (auto rit = decls.rbegin(); rit != rlast; ++rit) { + epc = EmbedInExec(getAllocate(&*rit), std::move(epc)); + } + + body.pop_front(); + body.push_front(std::move(epc)); + decls.erase(rlast.base(), decls.end()); } } - void RewriteOmpAllocations(parser::ExecutionPart &body) { - // Rewrite leading declarative allocations so they are nested - // within their respective executable allocate directive - // - // Original: - // ExecutionPartConstruct -> OpenMPDeclarativeAllocate - // ExecutionPartConstruct -> OpenMPDeclarativeAllocate - // ExecutionPartConstruct -> OpenMPExecutableAllocate - // - // After rewriting: - // ExecutionPartConstruct -> OpenMPExecutableAllocate - // ExecutionPartConstruct -> OpenMPDeclarativeAllocate - // ExecutionPartConstruct -> OpenMPDeclarativeAllocate - for (auto it = body.v.rbegin(); it != body.v.rend();) { - if (auto *exec = GetOmpIf<parser::OpenMPExecutableAllocate>(*(it++))) { - parser::OpenMPDeclarativeAllocate *decl; - std::list<parser::OpenMPDeclarativeAllocate> subAllocates; - while (it != body.v.rend() && - (decl = GetOmpIf<parser::OpenMPDeclarativeAllocate>(*it))) { - subAllocates.push_front(std::move(*decl)); - it = decltype(it)(body.v.erase(std::next(it).base())); - } - if (!subAllocates.empty()) { - std::get<std::optional<std::list<parser::OpenMPDeclarativeAllocate>>>( - exec->t) = {std::move(subAllocates)}; + void MakeExecutableAllocateFromOmps( + std::list<parser::OpenMPDeclarativeConstruct> &omps, + parser::Block &body) { + using OpenMPDeclarativeConstruct = parser::OpenMPDeclarativeConstruct; + + std::list<OpenMPDeclarativeConstruct>::reverse_iterator rlast = [&]() { + for (auto rit = omps.rbegin(), rend = omps.rend(); rit != rend; ++rit) { + if (!std::holds_alternative<parser::OmpAllocateDirective>(rit->u)) { + return rit; } } + return omps.rend(); + }(); + + if (rlast != omps.rbegin()) { + parser::ExecutionPartConstruct epc(std::move(body.front())); + for (auto rit = omps.rbegin(); rit != rlast; ++rit) { + epc = EmbedInExec( + &std::get<parser::OmpAllocateDirective>(rit->u), std::move(epc)); + } + + body.pop_front(); + body.push_front(std::move(epc)); + omps.erase(rlast.base(), omps.end()); } } diff --git a/flang/lib/Semantics/check-call.cpp b/flang/lib/Semantics/check-call.cpp index 995deaa..022b428 100644 --- a/flang/lib/Semantics/check-call.cpp +++ b/flang/lib/Semantics/check-call.cpp @@ -548,8 +548,13 @@ static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy, actualLastSymbol = &ResolveAssociations(*actualLastSymbol); } int actualRank{actualType.Rank()}; - if (dummy.type.attrs().test( - characteristics::TypeAndShape::Attr::AssumedShape)) { + if (dummyIsValue && dummyRank == 0 && + dummy.ignoreTKR.test(common::IgnoreTKR::Rank) && actualRank > 0) { + messages.Say( + "Array actual argument may not be associated with IGNORE_TKR(R) scalar %s with VALUE attribute"_err_en_US, + dummyName); + } else if (dummy.type.attrs().test( + characteristics::TypeAndShape::Attr::AssumedShape)) { // 15.5.2.4(16) if (actualIsAssumedRank) { messages.Say( @@ -795,7 +800,9 @@ static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy, bool dummyIsAssumedShape{dummy.type.attrs().test( characteristics::TypeAndShape::Attr::AssumedShape)}; bool copyOutNeeded{ - evaluate::MayNeedCopy(&arg, &dummyArg, foldingContext, true)}; + evaluate::ActualArgNeedsCopy(&arg, &dummyArg, foldingContext, + /*forCopyOut=*/true) + .value_or(false)}; if (copyOutNeeded && !dummyIsValue && (dummyIsAsynchronous || dummyIsVolatile)) { if (actualIsAsynchronous || actualIsVolatile) { @@ -832,8 +839,8 @@ static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy, // a unread value in the actual argument. // Occurences of `volatileOrAsyncNeedsTempDiagnosticIssued = true` indicate a // more specific error message has already been issued. We might be able to - // clean this up by switching the coding style of MayNeedCopy to be more like - // WhyNotDefinable. + // clean this up by switching the coding style of ActualArgNeedsCopy to be + // more like WhyNotDefinable. if (copyOutNeeded && !volatileOrAsyncNeedsTempDiagnosticIssued) { if ((actualIsVolatile || actualIsAsynchronous) && (dummyIsVolatile || dummyIsAsynchronous)) { diff --git a/flang/lib/Semantics/check-declarations.cpp b/flang/lib/Semantics/check-declarations.cpp index de407d3..9a6b3ff 100644 --- a/flang/lib/Semantics/check-declarations.cpp +++ b/flang/lib/Semantics/check-declarations.cpp @@ -855,6 +855,15 @@ void CheckHelper::CheckObjectEntity( messages_.Say( "Variable '%s' with EVENT_TYPE or LOCK_TYPE potential component '%s' must be a coarray"_err_en_US, symbol.name(), component.BuildResultDesignatorName()); + } else if (IsNotifyType(derived)) { // C1612 + messages_.Say( + "Variable '%s' with NOTIFY_TYPE must be a coarray"_err_en_US, + symbol.name()); + } else if (auto component{FindNotifyPotentialComponent( // C1611 + *derived, /*ignoreCoarrays=*/true)}) { + messages_.Say( + "Variable '%s' with NOTIFY_TYPE potential component '%s' must be a coarray"_err_en_US, + symbol.name(), component.BuildResultDesignatorName()); } } } @@ -873,6 +882,10 @@ void CheckHelper::CheckObjectEntity( messages_.Say( "An INTENT(OUT) dummy argument may not be, or contain, EVENT_TYPE or LOCK_TYPE"_err_en_US); } + if (IsOrContainsNotifyComponent(symbol)) { // C1613 + messages_.Say( + "An INTENT(OUT) dummy argument may not be, or contain, NOTIFY_TYPE"_err_en_US); + } if (IsAssumedSizeArray(symbol)) { // C834 if (type && type->IsPolymorphic()) { messages_.Say( diff --git a/flang/lib/Semantics/check-omp-atomic.cpp b/flang/lib/Semantics/check-omp-atomic.cpp index 2707921..b9e34ca 100644 --- a/flang/lib/Semantics/check-omp-atomic.cpp +++ b/flang/lib/Semantics/check-omp-atomic.cpp @@ -19,6 +19,7 @@ #include "flang/Evaluate/rewrite.h" #include "flang/Evaluate/tools.h" #include "flang/Parser/char-block.h" +#include "flang/Parser/openmp-utils.h" #include "flang/Parser/parse-tree.h" #include "flang/Semantics/openmp-utils.h" #include "flang/Semantics/symbol.h" @@ -41,6 +42,7 @@ namespace Fortran::semantics { +using namespace Fortran::parser::omp; using namespace Fortran::semantics::omp; namespace operation = Fortran::evaluate::operation; @@ -590,9 +592,11 @@ void OmpStructureChecker::CheckAtomicVariable( CheckAtomicType(syms.back(), source, atom.AsFortran(), checkTypeOnPointer); - if (IsAllocatable(syms.back()) && !IsArrayElement(atom)) { - context_.Say(source, "Atomic variable %s cannot be ALLOCATABLE"_err_en_US, - atom.AsFortran()); + if (!IsArrayElement(atom) && !ExtractComplexPart(atom)) { + if (IsAllocatable(syms.back())) { + context_.Say(source, "Atomic variable %s cannot be ALLOCATABLE"_err_en_US, + atom.AsFortran()); + } } } diff --git a/flang/lib/Semantics/check-omp-loop.cpp b/flang/lib/Semantics/check-omp-loop.cpp index aaaa2d6..726dbe8 100644 --- a/flang/lib/Semantics/check-omp-loop.cpp +++ b/flang/lib/Semantics/check-omp-loop.cpp @@ -245,6 +245,98 @@ void OmpStructureChecker::CheckSIMDNest(const parser::OpenMPConstruct &c) { } } +static bool IsLoopTransforming(llvm::omp::Directive dir) { + switch (dir) { + // TODO case llvm::omp::Directive::OMPD_flatten: + case llvm::omp::Directive::OMPD_fuse: + case llvm::omp::Directive::OMPD_interchange: + case llvm::omp::Directive::OMPD_nothing: + case llvm::omp::Directive::OMPD_reverse: + // TODO case llvm::omp::Directive::OMPD_split: + case llvm::omp::Directive::OMPD_stripe: + case llvm::omp::Directive::OMPD_tile: + case llvm::omp::Directive::OMPD_unroll: + return true; + default: + return false; + } +} + +void OmpStructureChecker::CheckNestedBlock(const parser::OpenMPLoopConstruct &x, + const parser::Block &body, size_t &nestedCount) { + for (auto &stmt : body) { + if (auto *dir{parser::Unwrap<parser::CompilerDirective>(stmt)}) { + context_.Say(dir->source, + "Compiler directives are not allowed inside OpenMP loop constructs"_warn_en_US); + } else if (parser::Unwrap<parser::DoConstruct>(stmt)) { + ++nestedCount; + } else if (auto *omp{parser::Unwrap<parser::OpenMPLoopConstruct>(stmt)}) { + if (!IsLoopTransforming(omp->BeginDir().DirId())) { + context_.Say(omp->source, + "Only loop-transforming OpenMP constructs are allowed inside OpenMP loop constructs"_err_en_US); + } + ++nestedCount; + } else if (auto *block{parser::Unwrap<parser::BlockConstruct>(stmt)}) { + CheckNestedBlock(x, std::get<parser::Block>(block->t), nestedCount); + } else { + parser::CharBlock source{parser::GetSource(stmt).value_or(x.source)}; + context_.Say(source, + "OpenMP loop construct can only contain DO loops or loop-nest-generating OpenMP constructs"_err_en_US); + } + } +} + +void OmpStructureChecker::CheckNestedConstruct( + const parser::OpenMPLoopConstruct &x) { + size_t nestedCount{0}; + + // End-directive is not allowed in such cases: + // do 100 i = ... + // !$omp do + // do 100 j = ... + // 100 continue + // !$omp end do ! error + const parser::OmpDirectiveSpecification &beginSpec{x.BeginDir()}; + auto &flags{std::get<parser::OmpDirectiveSpecification::Flags>(beginSpec.t)}; + if (flags.test(parser::OmpDirectiveSpecification::Flag::CrossesLabelDo)) { + if (auto &endSpec{x.EndDir()}) { + parser::CharBlock beginSource{beginSpec.DirName().source}; + context_ + .Say(endSpec->DirName().source, + "END %s directive is not allowed when the construct does not contain all loops that share a loop-terminating statement"_err_en_US, + parser::ToUpperCaseLetters(beginSource.ToString())) + .Attach(beginSource, "The construct starts here"_en_US); + } + } + + auto &body{std::get<parser::Block>(x.t)}; + if (body.empty()) { + context_.Say(x.source, + "OpenMP loop construct should contain a DO-loop or a loop-nest-generating OpenMP construct"_err_en_US); + } else { + CheckNestedBlock(x, body, nestedCount); + } +} + +void OmpStructureChecker::CheckFullUnroll( + const parser::OpenMPLoopConstruct &x) { + // If the nested construct is a full unroll, then this construct is invalid + // since it won't contain a loop. + if (const parser::OpenMPLoopConstruct *nested{x.GetNestedConstruct()}) { + auto &nestedSpec{nested->BeginDir()}; + if (nestedSpec.DirId() == llvm::omp::Directive::OMPD_unroll) { + bool isPartial{ + llvm::any_of(nestedSpec.Clauses().v, [](const parser::OmpClause &c) { + return c.Id() == llvm::omp::Clause::OMPC_partial; + })}; + if (!isPartial) { + context_.Say(x.source, + "OpenMP loop construct cannot apply to a fully unrolled loop"_err_en_US); + } + } + } +} + void OmpStructureChecker::Enter(const parser::OpenMPLoopConstruct &x) { loopStack_.push_back(&x); @@ -262,6 +354,15 @@ void OmpStructureChecker::Enter(const parser::OpenMPLoopConstruct &x) { EnterDirectiveNest(SIMDNest); } + if (CurrentDirectiveIsNested() && + llvm::omp::topTeamsSet.test(GetContext().directive) && + GetContextParent().directive == llvm::omp::Directive::OMPD_target && + !GetDirectiveNest(TargetBlockOnlyTeams)) { + context_.Say(GetContextParent().directiveSource, + "TARGET construct with nested TEAMS region contains statements or " + "directives outside of the TEAMS construct"_err_en_US); + } + // Combined target loop constructs are target device constructs. Keep track of // whether any such construct has been visited to later check that REQUIRES // directives for target-related options don't appear after them. @@ -285,15 +386,15 @@ void OmpStructureChecker::Enter(const parser::OpenMPLoopConstruct &x) { } SetLoopInfo(x); - auto &optLoopCons = std::get<std::optional<parser::NestedConstruct>>(x.t); - if (optLoopCons.has_value()) { - if (const auto &doConstruct{ - std::get_if<parser::DoConstruct>(&*optLoopCons)}) { + for (auto &construct : std::get<parser::Block>(x.t)) { + if (const auto *doConstruct{parser::omp::GetDoConstruct(construct)}) { const auto &doBlock{std::get<parser::Block>(doConstruct->t)}; CheckNoBranching(doBlock, beginName.v, beginName.source); } } CheckLoopItrVariableIsInt(x); + CheckNestedConstruct(x); + CheckFullUnroll(x); CheckAssociatedLoopConstraints(x); HasInvalidDistributeNesting(x); HasInvalidLoopBinding(x); @@ -305,6 +406,11 @@ void OmpStructureChecker::Enter(const parser::OpenMPLoopConstruct &x) { beginName.v == llvm::omp::Directive::OMPD_distribute_simd) { CheckDistLinear(x); } + if (beginName.v == llvm::omp::Directive::OMPD_fuse) { + CheckLooprangeBounds(x); + } else { + CheckNestedFuse(x); + } } const parser::Name OmpStructureChecker::GetLoopIndex( @@ -314,45 +420,37 @@ const parser::Name OmpStructureChecker::GetLoopIndex( } void OmpStructureChecker::SetLoopInfo(const parser::OpenMPLoopConstruct &x) { - auto &optLoopCons = std::get<std::optional<parser::NestedConstruct>>(x.t); - if (optLoopCons.has_value()) { - if (const auto &loopConstruct{ - std::get_if<parser::DoConstruct>(&*optLoopCons)}) { - const parser::DoConstruct *loop{&*loopConstruct}; - if (loop && loop->IsDoNormal()) { - const parser::Name &itrVal{GetLoopIndex(loop)}; - SetLoopIv(itrVal.symbol); - } + if (const auto *loop{x.GetNestedLoop()}) { + if (loop->IsDoNormal()) { + const parser::Name &itrVal{GetLoopIndex(loop)}; + SetLoopIv(itrVal.symbol); } } } void OmpStructureChecker::CheckLoopItrVariableIsInt( const parser::OpenMPLoopConstruct &x) { - auto &optLoopCons = std::get<std::optional<parser::NestedConstruct>>(x.t); - if (optLoopCons.has_value()) { - if (const auto &loopConstruct{ - std::get_if<parser::DoConstruct>(&*optLoopCons)}) { - - for (const parser::DoConstruct *loop{&*loopConstruct}; loop;) { - if (loop->IsDoNormal()) { - const parser::Name &itrVal{GetLoopIndex(loop)}; - if (itrVal.symbol) { - const auto *type{itrVal.symbol->GetType()}; - if (!type->IsNumeric(TypeCategory::Integer)) { - context_.Say(itrVal.source, - "The DO loop iteration" - " variable must be of the type integer."_err_en_US, - itrVal.ToString()); - } + for (auto &construct : std::get<parser::Block>(x.t)) { + for (const parser::DoConstruct *loop{ + parser::omp::GetDoConstruct(construct)}; + loop;) { + if (loop->IsDoNormal()) { + const parser::Name &itrVal{GetLoopIndex(loop)}; + if (itrVal.symbol) { + const auto *type{itrVal.symbol->GetType()}; + if (!type->IsNumeric(TypeCategory::Integer)) { + context_.Say(itrVal.source, + "The DO loop iteration" + " variable must be of the type integer."_err_en_US, + itrVal.ToString()); } } - // Get the next DoConstruct if block is not empty. - const auto &block{std::get<parser::Block>(loop->t)}; - const auto it{block.begin()}; - loop = it != block.end() ? parser::Unwrap<parser::DoConstruct>(*it) - : nullptr; } + // Get the next DoConstruct if block is not empty. + const auto &block{std::get<parser::Block>(loop->t)}; + const auto it{block.begin()}; + loop = it != block.end() ? parser::Unwrap<parser::DoConstruct>(*it) + : nullptr; } } } @@ -401,9 +499,8 @@ void OmpStructureChecker::CheckDistLinear( // Collect symbols of all the variables from linear clauses for (auto &clause : clauses.v) { - if (auto *linearClause{std::get_if<parser::OmpClause::Linear>(&clause.u)}) { - auto &objects{std::get<parser::OmpObjectList>(linearClause->v.t)}; - GetSymbolsInObjectList(objects, indexVars); + if (std::get_if<parser::OmpClause::Linear>(&clause.u)) { + GetSymbolsInObjectList(*parser::omp::GetOmpObjectList(clause), indexVars); } } @@ -417,28 +514,27 @@ void OmpStructureChecker::CheckDistLinear( // Match the loop index variables with the collected symbols from linear // clauses. - auto &optLoopCons = std::get<std::optional<parser::NestedConstruct>>(x.t); - if (optLoopCons.has_value()) { - if (const auto &loopConstruct{ - std::get_if<parser::DoConstruct>(&*optLoopCons)}) { - for (const parser::DoConstruct *loop{&*loopConstruct}; loop;) { - if (loop->IsDoNormal()) { - const parser::Name &itrVal{GetLoopIndex(loop)}; - if (itrVal.symbol) { - // Remove the symbol from the collected set - indexVars.erase(&itrVal.symbol->GetUltimate()); - } - collapseVal--; - if (collapseVal == 0) { - break; - } + for (auto &construct : std::get<parser::Block>(x.t)) { + std::int64_t curCollapseVal{collapseVal}; + for (const parser::DoConstruct *loop{ + parser::omp::GetDoConstruct(construct)}; + loop;) { + if (loop->IsDoNormal()) { + const parser::Name &itrVal{GetLoopIndex(loop)}; + if (itrVal.symbol) { + // Remove the symbol from the collected set + indexVars.erase(&itrVal.symbol->GetUltimate()); + } + curCollapseVal--; + if (curCollapseVal == 0) { + break; } - // Get the next DoConstruct if block is not empty. - const auto &block{std::get<parser::Block>(loop->t)}; - const auto it{block.begin()}; - loop = it != block.end() ? parser::Unwrap<parser::DoConstruct>(*it) - : nullptr; } + // Get the next DoConstruct if block is not empty. + const auto &block{std::get<parser::Block>(loop->t)}; + const auto it{block.begin()}; + loop = it != block.end() ? parser::Unwrap<parser::DoConstruct>(*it) + : nullptr; } } @@ -452,6 +548,101 @@ void OmpStructureChecker::CheckDistLinear( } } +void OmpStructureChecker::CheckLooprangeBounds( + const parser::OpenMPLoopConstruct &x) { + const parser::OmpClauseList &clauseList{x.BeginDir().Clauses()}; + if (clauseList.v.empty()) { + return; + } + for (auto &clause : clauseList.v) { + if (const auto *lrClause{ + std::get_if<parser::OmpClause::Looprange>(&clause.u)}) { + auto first{GetIntValue(std::get<0>((lrClause->v).t))}; + auto count{GetIntValue(std::get<1>((lrClause->v).t))}; + if (!first || !count) { + return; + } + auto &loopConsList{std::get<parser::Block>(x.t)}; + if (*first > 0 && *count > 0 && + loopConsList.size() < (unsigned)(*first + *count - 1)) { + context_.Say(clause.source, + "The loop range indicated in the %s clause must not be out of the bounds of the Loop Sequence following the construct."_err_en_US, + parser::ToUpperCaseLetters(clause.source.ToString())); + } + return; + } + } +} + +void OmpStructureChecker::CheckNestedFuse( + const parser::OpenMPLoopConstruct &x) { + auto &loopConsList{std::get<parser::Block>(x.t)}; + if (loopConsList.empty()) { + return; + } + const auto *ompConstruct{parser::omp::GetOmpLoop(loopConsList.front())}; + if (!ompConstruct) { + return; + } + const parser::OmpClauseList &clauseList{ompConstruct->BeginDir().Clauses()}; + if (clauseList.v.empty()) { + return; + } + for (auto &clause : clauseList.v) { + if (const auto *lrClause{ + std::get_if<parser::OmpClause::Looprange>(&clause.u)}) { + auto count{GetIntValue(std::get<1>((lrClause->v).t))}; + if (!count) { + return; + } + auto &nestedLoopConsList{std::get<parser::Block>(ompConstruct->t)}; + if (nestedLoopConsList.size() > (unsigned)(*count)) { + context_.Say(x.BeginDir().DirName().source, + "The loop sequence following the %s construct must be fully fused first."_err_en_US, + parser::ToUpperCaseLetters( + x.BeginDir().DirName().source.ToString())); + } + return; + } + } +} + +void OmpStructureChecker::CheckScanModifier( + const parser::OmpClause::Reduction &x) { + using ReductionModifier = parser::OmpReductionModifier; + + auto checkReductionSymbolInScan{[&](const parser::Name &name) { + if (auto *symbol{name.symbol}) { + if (!symbol->test(Symbol::Flag::OmpInclusiveScan) && + !symbol->test(Symbol::Flag::OmpExclusiveScan)) { + context_.Say(name.source, + "List item %s must appear in EXCLUSIVE or INCLUSIVE clause of an enclosed SCAN directive"_err_en_US, + name.ToString()); + } + } + }}; + + auto &modifiers{OmpGetModifiers(x.v)}; + auto *maybeModifier{OmpGetUniqueModifier<ReductionModifier>(modifiers)}; + if (maybeModifier && maybeModifier->v == ReductionModifier::Value::Inscan) { + for (const auto &ompObj : parser::omp::GetOmpObjectList(x)->v) { + common::visit( + common::visitors{ + [&](const parser::Designator &desg) { + if (auto *name{parser::GetDesignatorNameIfDataRef(desg)}) { + checkReductionSymbolInScan(*name); + } + }, + [&](const parser::Name &name) { + checkReductionSymbolInScan(name); + }, + [&](const parser::OmpObject::Invalid &invalid) {}, + }, + ompObj.u); + } + } +} + void OmpStructureChecker::Leave(const parser::OpenMPLoopConstruct &x) { const parser::OmpClauseList &clauseList{x.BeginDir().Clauses()}; @@ -459,45 +650,9 @@ void OmpStructureChecker::Leave(const parser::OpenMPLoopConstruct &x) { // constructs inside LOOP may add the relevant information. Scan reduction is // supported only in loop constructs, so same checks are not applicable to // other directives. - using ReductionModifier = parser::OmpReductionModifier; for (const auto &clause : clauseList.v) { - if (const auto *reductionClause{ - std::get_if<parser::OmpClause::Reduction>(&clause.u)}) { - auto &modifiers{OmpGetModifiers(reductionClause->v)}; - auto *maybeModifier{OmpGetUniqueModifier<ReductionModifier>(modifiers)}; - if (maybeModifier && - maybeModifier->v == ReductionModifier::Value::Inscan) { - const auto &objectList{ - std::get<parser::OmpObjectList>(reductionClause->v.t)}; - auto checkReductionSymbolInScan = [&](const parser::Name *name) { - if (auto &symbol = name->symbol) { - if (!symbol->test(Symbol::Flag::OmpInclusiveScan) && - !symbol->test(Symbol::Flag::OmpExclusiveScan)) { - context_.Say(name->source, - "List item %s must appear in EXCLUSIVE or " - "INCLUSIVE clause of an " - "enclosed SCAN directive"_err_en_US, - name->ToString()); - } - } - }; - for (const auto &ompObj : objectList.v) { - common::visit( - common::visitors{ - [&](const parser::Designator &designator) { - if (const auto *name{ - parser::GetDesignatorNameIfDataRef(designator)}) { - checkReductionSymbolInScan(name); - } - }, - [&](const parser::Name &name) { - checkReductionSymbolInScan(&name); - }, - [&](const parser::OmpObject::Invalid &invalid) {}, - }, - ompObj.u); - } - } + if (auto *reduction{std::get_if<parser::OmpClause::Reduction>(&clause.u)}) { + CheckScanModifier(*reduction); } } if (llvm::omp::allSimdSet.test(GetContext().directive)) { @@ -636,6 +791,20 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Linear &x) { } } +void OmpStructureChecker::Enter(const parser::OmpClause::Sizes &c) { + CheckAllowedClause(llvm::omp::Clause::OMPC_sizes); + for (const parser::Cosubscript &v : c.v) + RequiresPositiveParameter(llvm::omp::Clause::OMPC_sizes, v, + /*paramName=*/"parameter", /*allowZero=*/false); +} + +void OmpStructureChecker::Enter(const parser::OmpClause::Looprange &x) { + CheckAllowedClause(llvm::omp::Clause::OMPC_looprange); + auto &[first, count]{x.v.t}; + RequiresConstantPositiveParameter(llvm::omp::Clause::OMPC_looprange, count); + RequiresConstantPositiveParameter(llvm::omp::Clause::OMPC_looprange, first); +} + void OmpStructureChecker::Enter(const parser::DoConstruct &x) { Base::Enter(x); loopStack_.push_back(&x); diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp index aaaf1ec..7776f0d 100644 --- a/flang/lib/Semantics/check-omp-structure.cpp +++ b/flang/lib/Semantics/check-omp-structure.cpp @@ -179,29 +179,21 @@ void OmpStructureChecker::Leave(const parser::BlockConstruct &x) { } } -// Use when clause falls under 'struct OmpClause' in 'parse-tree.h'. -#define CHECK_SIMPLE_CLAUSE(X, Y) \ - void OmpStructureChecker::Enter(const parser::OmpClause::X &) { \ - CheckAllowedClause(llvm::omp::Clause::Y); \ - } +void OmpStructureChecker::Enter(const parser::SpecificationPart &) { + partStack_.push_back(PartKind::SpecificationPart); +} -#define CHECK_REQ_CONSTANT_SCALAR_INT_CLAUSE(X, Y) \ - void OmpStructureChecker::Enter(const parser::OmpClause::X &c) { \ - CheckAllowedClause(llvm::omp::Clause::Y); \ - RequiresConstantPositiveParameter(llvm::omp::Clause::Y, c.v); \ - } +void OmpStructureChecker::Leave(const parser::SpecificationPart &) { + partStack_.pop_back(); +} -#define CHECK_REQ_SCALAR_INT_CLAUSE(X, Y) \ - void OmpStructureChecker::Enter(const parser::OmpClause::X &c) { \ - CheckAllowedClause(llvm::omp::Clause::Y); \ - RequiresPositiveParameter(llvm::omp::Clause::Y, c.v); \ - } +void OmpStructureChecker::Enter(const parser::ExecutionPart &) { + partStack_.push_back(PartKind::ExecutionPart); +} -// Use when clause don't falls under 'struct OmpClause' in 'parse-tree.h'. -#define CHECK_SIMPLE_PARSER_CLAUSE(X, Y) \ - void OmpStructureChecker::Enter(const parser::X &) { \ - CheckAllowedClause(llvm::omp::Y); \ - } +void OmpStructureChecker::Leave(const parser::ExecutionPart &) { + partStack_.pop_back(); +} // 'OmpWorkshareBlockChecker' is used to check the validity of the assignment // statements and the expressions enclosed in an OpenMP Workshare construct @@ -632,11 +624,9 @@ void OmpStructureChecker::CheckMultListItems() { // Linear clause for (auto [_, clause] : FindClauses(llvm::omp::Clause::OMPC_linear)) { - auto &linearClause{std::get<parser::OmpClause::Linear>(clause->u)}; std::list<parser::Name> nameList; SymbolSourceMap symbols; - GetSymbolsInObjectList( - std::get<parser::OmpObjectList>(linearClause.v.t), symbols); + GetSymbolsInObjectList(*GetOmpObjectList(*clause), symbols); llvm::transform(symbols, std::back_inserter(nameList), [&](auto &&pair) { return parser::Name{pair.second, const_cast<Symbol *>(pair.first)}; }); @@ -667,49 +657,6 @@ void OmpStructureChecker::HasInvalidTeamsNesting( } } -void OmpStructureChecker::CheckPredefinedAllocatorRestriction( - const parser::CharBlock &source, const parser::Name &name) { - if (const auto *symbol{name.symbol}) { - const auto *commonBlock{FindCommonBlockContaining(*symbol)}; - const auto &scope{context_.FindScope(symbol->name())}; - const Scope &containingScope{GetProgramUnitContaining(scope)}; - if (!isPredefinedAllocator && - (IsSaved(*symbol) || commonBlock || - containingScope.kind() == Scope::Kind::Module)) { - context_.Say(source, - "If list items within the %s directive have the " - "SAVE attribute, are a common block name, or are " - "declared in the scope of a module, then only " - "predefined memory allocator parameters can be used " - "in the allocator clause"_err_en_US, - ContextDirectiveAsFortran()); - } - } -} - -void OmpStructureChecker::CheckPredefinedAllocatorRestriction( - const parser::CharBlock &source, - const parser::OmpObjectList &ompObjectList) { - for (const auto &ompObject : ompObjectList.v) { - common::visit( - common::visitors{ - [&](const parser::Designator &designator) { - if (const auto *dataRef{ - std::get_if<parser::DataRef>(&designator.u)}) { - if (const auto *name{std::get_if<parser::Name>(&dataRef->u)}) { - CheckPredefinedAllocatorRestriction(source, *name); - } - } - }, - [&](const parser::Name &name) { - CheckPredefinedAllocatorRestriction(source, name); - }, - [&](const parser::OmpObject::Invalid &invalid) {}, - }, - ompObject.u); - } -} - void OmpStructureChecker::Enter(const parser::OmpClause::Hint &x) { CheckAllowedClause(llvm::omp::Clause::OMPC_hint); auto &dirCtx{GetContext()}; @@ -733,6 +680,13 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Hint &x) { } } +void OmpStructureChecker::Enter(const parser::OmpClause::DynGroupprivate &x) { + CheckAllowedClause(llvm::omp::Clause::OMPC_dyn_groupprivate); + parser::CharBlock source{GetContext().clauseSource}; + + OmpVerifyModifiers(x.v, llvm::omp::OMPC_dyn_groupprivate, source, context_); +} + void OmpStructureChecker::Enter(const parser::OmpDirectiveSpecification &x) { // OmpDirectiveSpecification exists on its own only in METADIRECTIVE. // In other cases it's a part of other constructs that handle directive @@ -763,18 +717,10 @@ template <typename Checker> struct DirectiveSpellingVisitor { return std::get<parser::OmpBeginDirective>(t).DirName(); } - bool Pre(const parser::OpenMPDeclarativeAllocate &x) { - checker_(std::get<parser::Verbatim>(x.t).source, Directive::OMPD_allocate); - return false; - } bool Pre(const parser::OpenMPDispatchConstruct &x) { checker_(GetDirName(x.t).source, Directive::OMPD_dispatch); return false; } - bool Pre(const parser::OpenMPExecutableAllocate &x) { - checker_(std::get<parser::Verbatim>(x.t).source, Directive::OMPD_allocate); - return false; - } bool Pre(const parser::OpenMPAllocatorsConstruct &x) { checker_(GetDirName(x.t).source, Directive::OMPD_allocators); return false; @@ -1710,12 +1656,39 @@ void OmpStructureChecker::Leave(const parser::OpenMPRequiresConstruct &) { dirContext_.pop_back(); } -void OmpStructureChecker::CheckAllocateDirective(parser::CharBlock source, - const parser::OmpObjectList &objects, - const parser::OmpClauseList &clauses) { - const Scope &thisScope{context_.FindScope(source)}; - SymbolSourceMap symbols; - GetSymbolsInObjectList(objects, symbols); +static std::pair<const parser::AllocateStmt *, parser::CharBlock> +getAllocateStmtAndSource(const parser::ExecutionPartConstruct *epc) { + if (SourcedActionStmt as{GetActionStmt(epc)}) { + using IndirectionAllocateStmt = common::Indirection<parser::AllocateStmt>; + if (auto *indirect{std::get_if<IndirectionAllocateStmt>(&as.stmt->u)}) { + return {&indirect->value(), as.source}; + } + } + return {nullptr, ""}; +} + +// Collect symbols that correspond to non-component objects on the +// ALLOCATE statement. +static UnorderedSymbolSet GetNonComponentSymbols( + const parser::AllocateStmt &stmt) { + UnorderedSymbolSet symbols; + for (auto &alloc : std::get<std::list<parser::Allocation>>(stmt.t)) { + auto &object{std::get<parser::AllocateObject>(alloc.t)}; + if (auto *name{std::get_if<parser::Name>(&object.u)}) { + if (name->symbol) { + symbols.insert(name->symbol->GetUltimate()); + } + } + } + return symbols; +} + +void OmpStructureChecker::CheckIndividualAllocateDirective( + const parser::OmpAllocateDirective &x, bool isExecutable) { + const parser::OmpDirectiveSpecification &beginSpec{x.BeginDir()}; + const parser::OmpDirectiveName &dirName{beginSpec.DirName()}; + + const Scope &thisScope{context_.FindScope(dirName.source)}; auto maybeHasPredefinedAllocator{[&](const parser::OmpClause *calloc) { // Return "true" if the ALLOCATOR clause was provided with an argument @@ -1741,73 +1714,200 @@ void OmpStructureChecker::CheckAllocateDirective(parser::CharBlock source, return true; }}; - const auto *allocator{FindClause(llvm::omp::Clause::OMPC_allocator)}; + const auto *allocator{[&]() { + // Can't use FindClause in Enter (because clauses haven't been visited + // yet). + for (const parser::OmpClause &c : beginSpec.Clauses().v) { + if (c.Id() == llvm::omp::Clause::OMPC_allocator) { + return &c; + } + } + return static_cast<const parser::OmpClause *>(nullptr); + }()}; + if (InTargetRegion()) { bool hasDynAllocators{ HasRequires(llvm::omp::Clause::OMPC_dynamic_allocators)}; if (!allocator && !hasDynAllocators) { - context_.Say(source, + context_.Say(dirName.source, "An ALLOCATE directive in a TARGET region must specify an ALLOCATOR clause or REQUIRES(DYNAMIC_ALLOCATORS) must be specified"_err_en_US); } } auto maybePredefined{maybeHasPredefinedAllocator(allocator)}; - for (auto &[symbol, source] : symbols) { - if (!inExecutableAllocate_) { - if (symbol->owner() != thisScope) { + unsigned version{context_.langOptions().OpenMPVersion}; + std::string condStr{version == 50 + ? "a named common block, has SAVE attribute or is declared in the " + "scope of a module" + : "a named common block or has SAVE attribute"}; + + auto checkSymbol{[&](const Symbol &symbol, parser::CharBlock source) { + if (!isExecutable) { + // For structure members, the scope is the derived type, which is + // never "this" scope. Ignore this check for members, they will be + // flagged anyway. + if (symbol.owner() != thisScope && !IsStructureComponent(symbol)) { context_.Say(source, "A list item on a declarative ALLOCATE must be declared in the same scope in which the directive appears"_err_en_US); } - if (IsPointer(*symbol) || IsAllocatable(*symbol)) { + if (IsPointer(symbol) || IsAllocatable(symbol)) { context_.Say(source, "A list item in a declarative ALLOCATE cannot have the ALLOCATABLE or POINTER attribute"_err_en_US); } } - if (symbol->GetUltimate().has<AssocEntityDetails>()) { + if (symbol.GetUltimate().has<AssocEntityDetails>()) { context_.Say(source, "A list item in a declarative ALLOCATE cannot be an associate name"_err_en_US); } - if (symbol->attrs().test(Attr::SAVE) || IsCommonBlock(*symbol)) { + bool inModule{ + version == 50 && symbol.owner().kind() == Scope::Kind::Module}; + if (symbol.attrs().test(Attr::SAVE) || IsCommonBlock(symbol) || inModule) { if (!allocator) { context_.Say(source, - "If a list item is a named common block or has SAVE attribute, an ALLOCATOR clause must be present with a predefined allocator"_err_en_US); + "If a list item is %s, an ALLOCATOR clause must be present with a predefined allocator"_err_en_US, + condStr); } else if (!maybePredefined) { context_.Say(source, - "If a list item is a named common block or has SAVE attribute, only a predefined allocator may be used on the ALLOCATOR clause"_err_en_US); + "If a list item is %s, only a predefined allocator may be used on the ALLOCATOR clause"_err_en_US, + condStr); } } - if (FindCommonBlockContaining(*symbol)) { + if (FindCommonBlockContaining(symbol)) { context_.Say(source, "A variable that is part of a common block may not be specified as a list item in an ALLOCATE directive, except implicitly via the named common block"_err_en_US); } + }}; + + for (const parser::OmpArgument &arg : beginSpec.Arguments().v) { + const parser::OmpObject *object{GetArgumentObject(arg)}; + if (!object) { + context_.Say(arg.source, + "An argument to ALLOCATE directive must be a variable list item"_err_en_US); + continue; + } + + if (const Symbol *symbol{GetObjectSymbol(*object)}) { + if (!IsTypeParamInquiry(*symbol)) { + checkSymbol(*symbol, arg.source); + } + CheckVarIsNotPartOfAnotherVar(dirName.source, *object); + } } - CheckVarIsNotPartOfAnotherVar(source, objects); } -void OmpStructureChecker::Enter(const parser::OpenMPDeclarativeAllocate &x) { - const auto &dir{std::get<parser::Verbatim>(x.t)}; - PushContextAndClauseSets(dir.source, llvm::omp::Directive::OMPD_allocate); +void OmpStructureChecker::CheckExecutableAllocateDirective( + const parser::OmpAllocateDirective &x) { + parser::omp::OmpAllocateInfo info{SplitOmpAllocate(x)}; + + auto [allocStmt, allocSource]{getAllocateStmtAndSource(info.body)}; + if (!allocStmt) { + // This has been diagnosed already. + return; + } + + UnorderedSymbolSet allocateSyms{GetNonComponentSymbols(*allocStmt)}; + SymbolSourceMap directiveSyms; + bool hasEmptyList{false}; + + for (const parser::OmpAllocateDirective *ompAlloc : info.dirs) { + const parser::OmpDirectiveSpecification &spec{DEREF(ompAlloc).BeginDir()}; + if (spec.Arguments().v.empty()) { + if (hasEmptyList && info.dirs.size() > 1) { + context_.Say(spec.DirName().source, + "If multiple directives are present in an executable ALLOCATE directive, at most one of them may specify no list items"_err_en_US); + } + hasEmptyList = true; + } + for (const parser::OmpArgument &arg : spec.Arguments().v) { + if (auto *sym{GetArgumentSymbol(arg)}) { + // Ignore these checks for structure members. They are not allowed + // in the first place, so don't tell the users that they need to + // be specified somewhere, + if (IsStructureComponent(*sym)) { + continue; + } + if (auto f{directiveSyms.find(sym)}; f != directiveSyms.end()) { + parser::MessageFormattedText txt( + "A list item on an executable ALLOCATE may only be specified once"_err_en_US); + parser::Message message(arg.source, txt); + message.Attach(f->second, "The list item was specified here"_en_US); + context_.Say(std::move(message)); + } else { + directiveSyms.insert(std::make_pair(sym, arg.source)); + } + + if (auto f{allocateSyms.find(*sym)}; f == allocateSyms.end()) { + context_ + .Say(arg.source, + "A list item on an executable ALLOCATE must be specified on the associated ALLOCATE statement"_err_en_US) + .Attach(allocSource, "The ALLOCATE statement"_en_US); + } + } + } + } } -void OmpStructureChecker::Leave(const parser::OpenMPDeclarativeAllocate &x) { - if (!inExecutableAllocate_) { - const auto &dir{std::get<parser::Verbatim>(x.t)}; - const auto &clauseList{std::get<parser::OmpClauseList>(x.t)}; - const auto &objectList{std::get<parser::OmpObjectList>(x.t)}; +void OmpStructureChecker::Enter(const parser::OmpAllocateDirective &x) { + const parser::OmpDirectiveSpecification &beginSpec{x.BeginDir()}; + const parser::OmpDirectiveName &dirName{beginSpec.DirName()}; + PushContextAndClauseSets(dirName.source, dirName.v); + ++allocateDirectiveLevel; + + bool isExecutable{partStack_.back() == PartKind::ExecutionPart}; + + unsigned version{context_.langOptions().OpenMPVersion}; + if (isExecutable && allocateDirectiveLevel == 1 && version >= 52) { + context_.Warn(common::UsageWarning::OpenMPUsage, dirName.source, + "The executable form of the OpenMP ALLOCATE directive has been deprecated, please use ALLOCATORS instead"_warn_en_US); + } + + CheckIndividualAllocateDirective(x, isExecutable); - isPredefinedAllocator = true; - CheckAllocateDirective(dir.source, objectList, clauseList); + if (isExecutable) { + auto isOmpAllocate{[](const parser::ExecutionPartConstruct &epc) { + if (auto *omp{GetOmp(epc)}) { + auto odn{GetOmpDirectiveName(*omp)}; + return odn.v == llvm::omp::Directive::OMPD_allocate; + } + return false; + }}; + + auto &body{std::get<parser::Block>(x.t)}; + // The parser should put at most one statement in the body. + assert(body.size() <= 1 && "Multiple statements in allocate"); + if (body.empty()) { + context_.Say(dirName.source, + "An executable ALLOCATE directive must be associated with an ALLOCATE statement"_err_en_US); + } else { + const parser::ExecutionPartConstruct &first{body.front()}; + auto [allocStmt, _]{getAllocateStmtAndSource(&body.front())}; + if (!isOmpAllocate(first) && !allocStmt) { + parser::CharBlock source{[&]() { + if (auto &&maybeSource{parser::GetSource(first)}) { + return *maybeSource; + } + return dirName.source; + }()}; + context_.Say(source, + "The statement associated with executable ALLOCATE directive must be an ALLOCATE statement"_err_en_US); + } + } } +} + +void OmpStructureChecker::Leave(const parser::OmpAllocateDirective &x) { + bool isExecutable{partStack_.back() == PartKind::ExecutionPart}; + if (isExecutable && allocateDirectiveLevel == 1) { + CheckExecutableAllocateDirective(x); + } + + --allocateDirectiveLevel; dirContext_.pop_back(); } void OmpStructureChecker::Enter(const parser::OmpClause::Allocator &x) { CheckAllowedClause(llvm::omp::Clause::OMPC_allocator); - // Note: Predefined allocators are stored in ScalarExpr as numbers - // whereas custom allocators are stored as strings, so if the ScalarExpr - // actually has an int value, then it must be a predefined allocator - isPredefinedAllocator = GetIntValue(x.v).has_value(); RequiresPositiveParameter(llvm::omp::Clause::OMPC_allocator, x.v); } @@ -1823,16 +1923,6 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Allocate &x) { "The alignment value should be a constant positive integer"_err_en_US); } } - // The simple and complex modifiers have the same structure. They only - // differ in their syntax. - if (auto *alloc{OmpGetUniqueModifier<parser::OmpAllocatorComplexModifier>( - modifiers)}) { - isPredefinedAllocator = GetIntValue(alloc->v).has_value(); - } - if (auto *alloc{OmpGetUniqueModifier<parser::OmpAllocatorSimpleModifier>( - modifiers)}) { - isPredefinedAllocator = GetIntValue(alloc->v).has_value(); - } } } @@ -2009,29 +2099,29 @@ void OmpStructureChecker::Leave(const parser::OpenMPDeclareTargetConstruct &x) { } } - bool toClauseFound{false}, deviceTypeClauseFound{false}, - enterClauseFound{false}; + bool toClauseFound{false}; + bool deviceTypeClauseFound{false}; + bool enterClauseFound{false}; for (const parser::OmpClause &clause : x.v.Clauses().v) { common::visit( common::visitors{ - [&](const parser::OmpClause::To &toClause) { - toClauseFound = true; - auto &objList{std::get<parser::OmpObjectList>(toClause.v.t)}; - CheckSymbolNames(dirName.source, objList); - CheckVarIsNotPartOfAnotherVar(dirName.source, objList); - CheckThreadprivateOrDeclareTargetVar(objList); - }, - [&](const parser::OmpClause::Link &linkClause) { - CheckSymbolNames(dirName.source, linkClause.v); - CheckVarIsNotPartOfAnotherVar(dirName.source, linkClause.v); - CheckThreadprivateOrDeclareTargetVar(linkClause.v); - }, - [&](const parser::OmpClause::Enter &enterClause) { - enterClauseFound = true; - auto &objList{std::get<parser::OmpObjectList>(enterClause.v.t)}; - CheckSymbolNames(dirName.source, objList); - CheckVarIsNotPartOfAnotherVar(dirName.source, objList); - CheckThreadprivateOrDeclareTargetVar(objList); + [&](const auto &c) { + using TypeC = llvm::remove_cvref_t<decltype(c)>; + if constexpr ( // + std::is_same_v<TypeC, parser::OmpClause::Enter> || + std::is_same_v<TypeC, parser::OmpClause::Link> || + std::is_same_v<TypeC, parser::OmpClause::To>) { + auto &objList{*GetOmpObjectList(c)}; + CheckSymbolNames(dirName.source, objList); + CheckVarIsNotPartOfAnotherVar(dirName.source, objList); + CheckThreadprivateOrDeclareTargetVar(objList); + } + if constexpr (std::is_same_v<TypeC, parser::OmpClause::Enter>) { + enterClauseFound = true; + } + if constexpr (std::is_same_v<TypeC, parser::OmpClause::To>) { + toClauseFound = true; + } }, [&](const parser::OmpClause::DeviceType &deviceTypeClause) { deviceTypeClauseFound = true; @@ -2042,7 +2132,6 @@ void OmpStructureChecker::Leave(const parser::OpenMPDeclareTargetConstruct &x) { deviceConstructFound_ = true; } }, - [&](const auto &) {}, }, clause.u); @@ -2115,168 +2204,88 @@ void OmpStructureChecker::Enter(const parser::OmpClause::At &x) { } } -// Goes through the names in an OmpObjectList and checks if each name appears -// in the given allocate statement -void OmpStructureChecker::CheckAllNamesInAllocateStmt( - const parser::CharBlock &source, const parser::OmpObjectList &ompObjectList, - const parser::AllocateStmt &allocate) { - for (const auto &obj : ompObjectList.v) { - if (const auto *d{std::get_if<parser::Designator>(&obj.u)}) { - if (const auto *ref{std::get_if<parser::DataRef>(&d->u)}) { - if (const auto *n{std::get_if<parser::Name>(&ref->u)}) { - CheckNameInAllocateStmt(source, *n, allocate); - } - } - } - } -} - -void OmpStructureChecker::CheckNameInAllocateStmt( - const parser::CharBlock &source, const parser::Name &name, - const parser::AllocateStmt &allocate) { - for (const auto &allocation : - std::get<std::list<parser::Allocation>>(allocate.t)) { - const auto &allocObj = std::get<parser::AllocateObject>(allocation.t); - if (const auto *n{std::get_if<parser::Name>(&allocObj.u)}) { - if (n->source == name.source) { - return; - } - } - } - unsigned version{context_.langOptions().OpenMPVersion}; - context_.Say(source, - "Object '%s' in %s directive not " - "found in corresponding ALLOCATE statement"_err_en_US, - name.ToString(), - parser::ToUpperCaseLetters( - llvm::omp::getOpenMPDirectiveName(GetContext().directive, version) - .str())); -} - -void OmpStructureChecker::Enter(const parser::OpenMPExecutableAllocate &x) { - inExecutableAllocate_ = true; - const auto &dir{std::get<parser::Verbatim>(x.t)}; - PushContextAndClauseSets(dir.source, llvm::omp::Directive::OMPD_allocate); - - unsigned version{context_.langOptions().OpenMPVersion}; - if (version >= 52) { - context_.Warn(common::UsageWarning::OpenMPUsage, x.source, - "The executable form of the OpenMP ALLOCATE directive has been deprecated, please use ALLOCATORS instead"_warn_en_US); - } - - const auto &allocateStmt = - std::get<parser::Statement<parser::AllocateStmt>>(x.t).statement; - if (const auto &list{std::get<std::optional<parser::OmpObjectList>>(x.t)}) { - CheckAllNamesInAllocateStmt( - std::get<parser::Verbatim>(x.t).source, *list, allocateStmt); - } - if (const auto &subDirs{ - std::get<std::optional<std::list<parser::OpenMPDeclarativeAllocate>>>( - x.t)}) { - for (const auto &dalloc : *subDirs) { - CheckAllNamesInAllocateStmt(std::get<parser::Verbatim>(dalloc.t).source, - std::get<parser::OmpObjectList>(dalloc.t), allocateStmt); - } - } - - isPredefinedAllocator = true; -} +void OmpStructureChecker::Enter(const parser::OpenMPAllocatorsConstruct &x) { + const parser::OmpDirectiveSpecification &beginSpec{x.BeginDir()}; + const parser::OmpDirectiveName &dirName{beginSpec.DirName()}; + PushContextAndClauseSets( + dirName.source, llvm::omp::Directive::OMPD_allocators); -void OmpStructureChecker::Leave(const parser::OpenMPExecutableAllocate &x) { - parser::OmpObjectList empty{std::list<parser::OmpObject>{}}; - auto &objects{[&]() -> const parser::OmpObjectList & { - if (auto &objects{std::get<std::optional<parser::OmpObjectList>>(x.t)}) { - return *objects; - } else { - return empty; + for (const auto &clause : beginSpec.Clauses().v) { + auto *alloc{std::get_if<parser::OmpClause::Allocate>(&clause.u)}; + if (!alloc) { + continue; } - }()}; - auto &clauses{std::get<parser::OmpClauseList>(x.t)}; - CheckAllocateDirective( - std::get<parser::Verbatim>(x.t).source, objects, clauses); - - if (const auto &subDirs{ - std::get<std::optional<std::list<parser::OpenMPDeclarativeAllocate>>>( - x.t)}) { - for (const auto &dalloc : *subDirs) { - const auto &dir{std::get<parser::Verbatim>(x.t)}; - const auto &clauses{std::get<parser::OmpClauseList>(dalloc.t)}; - const auto &objects{std::get<parser::OmpObjectList>(dalloc.t)}; - CheckAllocateDirective(dir.source, objects, clauses); + using OmpAllocatorSimpleModifier = parser::OmpAllocatorSimpleModifier; + using OmpAllocatorComplexModifier = parser::OmpAllocatorComplexModifier; + + if (InTargetRegion()) { + auto &modifiers{OmpGetModifiers(alloc->v)}; + bool hasAllocator{ + OmpGetUniqueModifier<OmpAllocatorSimpleModifier>(modifiers) || + OmpGetUniqueModifier<OmpAllocatorComplexModifier>(modifiers)}; + bool hasDynAllocators{ + HasRequires(llvm::omp::Clause::OMPC_dynamic_allocators)}; + if (!hasAllocator && !hasDynAllocators) { + context_.Say(clause.source, + "An ALLOCATE clause in a TARGET region must specify an allocator or REQUIRES(DYNAMIC_ALLOCATORS) must be specified"_err_en_US); + } } } - dirContext_.pop_back(); - inExecutableAllocate_ = false; -} - -void OmpStructureChecker::Enter(const parser::OpenMPAllocatorsConstruct &x) { - isPredefinedAllocator = true; - - const parser::OmpDirectiveSpecification &dirSpec{x.BeginDir()}; - auto &block{std::get<parser::Block>(x.t)}; - PushContextAndClauseSets( - dirSpec.DirName().source, llvm::omp::Directive::OMPD_allocators); - - if (block.empty()) { - context_.Say(dirSpec.source, - "The ALLOCATORS construct should contain a single ALLOCATE statement"_err_en_US); + auto &body{std::get<parser::Block>(x.t)}; + // The parser should put at most one statement in the body. + assert(body.size() <= 1 && "Malformed body in allocators"); + if (body.empty()) { + context_.Say(dirName.source, + "The body of an ALLOCATORS construct should be an ALLOCATE statement"_err_en_US); return; } - omp::SourcedActionStmt action{omp::GetActionStmt(block)}; - const auto *allocate{ - action ? parser::Unwrap<parser::AllocateStmt>(action.stmt) : nullptr}; - - if (allocate) { - for (const auto &clause : dirSpec.Clauses().v) { - if (auto *alloc{std::get_if<parser::OmpClause::Allocate>(&clause.u)}) { - CheckAllNamesInAllocateStmt( - x.source, std::get<parser::OmpObjectList>(alloc->v.t), *allocate); - - using OmpAllocatorSimpleModifier = parser::OmpAllocatorSimpleModifier; - using OmpAllocatorComplexModifier = parser::OmpAllocatorComplexModifier; - - auto &modifiers{OmpGetModifiers(alloc->v)}; - bool hasAllocator{ - OmpGetUniqueModifier<OmpAllocatorSimpleModifier>(modifiers) || - OmpGetUniqueModifier<OmpAllocatorComplexModifier>(modifiers)}; - - // TODO: As with allocate directive, exclude the case when a requires - // directive with the dynamic_allocators clause is present in - // the same compilation unit (OMP5.0 2.11.3). - if (IsNestedInDirective(llvm::omp::Directive::OMPD_target) && - !hasAllocator) { - context_.Say(x.source, - "ALLOCATORS directives that appear in a TARGET region must specify an allocator"_err_en_US); - } + auto [allocStmt, allocSource]{getAllocateStmtAndSource(&body.front())}; + if (!allocStmt) { + parser::CharBlock source{[&]() { + if (auto &&maybeSource{parser::GetSource(body.front())}) { + return *maybeSource; } - } - } else { - const parser::CharBlock &source = action ? action.source : x.source; + return dirName.source; + }()}; context_.Say(source, - "The body of the ALLOCATORS construct should be an ALLOCATE statement"_err_en_US); + "The body of an ALLOCATORS construct should be an ALLOCATE statement"_err_en_US); + return; } - for (const auto &clause : dirSpec.Clauses().v) { - if (const auto *allocClause{ - parser::Unwrap<parser::OmpClause::Allocate>(clause)}) { - CheckVarIsNotPartOfAnotherVar( - dirSpec.source, std::get<parser::OmpObjectList>(allocClause->v.t)); + UnorderedSymbolSet allocateSyms{GetNonComponentSymbols(*allocStmt)}; + for (const auto &clause : beginSpec.Clauses().v) { + auto *alloc{std::get_if<parser::OmpClause::Allocate>(&clause.u)}; + if (!alloc) { + continue; + } + for (auto &object : DEREF(GetOmpObjectList(clause)).v) { + CheckVarIsNotPartOfAnotherVar(dirName.source, object); + if (auto *symbol{GetObjectSymbol(object)}) { + if (IsStructureComponent(*symbol)) { + continue; + } + parser::CharBlock source{[&]() { + if (auto &&objectSource{GetObjectSource(object)}) { + return *objectSource; + } + return clause.source; + }()}; + if (!IsTypeParamInquiry(*symbol)) { + if (auto f{allocateSyms.find(*symbol)}; f == allocateSyms.end()) { + context_ + .Say(source, + "A list item in an ALLOCATORS construct must be specified on the associated ALLOCATE statement"_err_en_US) + .Attach(allocSource, "The ALLOCATE statement"_en_US); + } + } + } } } } void OmpStructureChecker::Leave(const parser::OpenMPAllocatorsConstruct &x) { - const parser::OmpDirectiveSpecification &dirSpec{x.BeginDir()}; - - for (const auto &clause : dirSpec.Clauses().v) { - if (const auto *allocClause{ - std::get_if<parser::OmpClause::Allocate>(&clause.u)}) { - CheckPredefinedAllocatorRestriction( - dirSpec.source, std::get<parser::OmpObjectList>(allocClause->v.t)); - } - } dirContext_.pop_back(); } @@ -2412,12 +2421,8 @@ void OmpStructureChecker::CheckTargetUpdate() { } if (toWrapper && fromWrapper) { SymbolSourceMap toSymbols, fromSymbols; - auto &fromClause{std::get<parser::OmpClause::From>(fromWrapper->u).v}; - auto &toClause{std::get<parser::OmpClause::To>(toWrapper->u).v}; - GetSymbolsInObjectList( - std::get<parser::OmpObjectList>(fromClause.t), fromSymbols); - GetSymbolsInObjectList( - std::get<parser::OmpObjectList>(toClause.t), toSymbols); + GetSymbolsInObjectList(*GetOmpObjectList(*fromWrapper), fromSymbols); + GetSymbolsInObjectList(*GetOmpObjectList(*toWrapper), toSymbols); for (auto &[symbol, source] : toSymbols) { auto fromSymbol{fromSymbols.find(symbol)}; @@ -2736,8 +2741,8 @@ void OmpStructureChecker::Leave(const parser::OpenMPFlushConstruct &x) { unsigned version{context_.langOptions().OpenMPVersion}; if (version >= 52) { - using Flags = parser::OmpDirectiveSpecification::Flags; - if (std::get<Flags>(x.v.t) == Flags::DeprecatedSyntax) { + auto &flags{std::get<parser::OmpDirectiveSpecification::Flags>(x.v.t)}; + if (flags.test(parser::OmpDirectiveSpecification::Flag::DeprecatedSyntax)) { context_.Say(x.source, "The syntax \"FLUSH clause (object, ...)\" has been deprecated, use \"FLUSH(object, ...) clause\" instead"_warn_en_US); } @@ -2795,7 +2800,7 @@ void OmpStructureChecker::Leave(const parser::OpenMPCancelConstruct &) { void OmpStructureChecker::Enter(const parser::OpenMPCriticalConstruct &x) { const parser::OmpBeginDirective &beginSpec{x.BeginDir()}; const std::optional<parser::OmpEndDirective> &endSpec{x.EndDir()}; - PushContextAndClauseSets(beginSpec.DirName().source, beginSpec.DirName().v); + PushContextAndClauseSets(beginSpec.DirName().source, beginSpec.DirId()); const auto &block{std::get<parser::Block>(x.t)}; CheckNoBranching( @@ -3257,7 +3262,7 @@ void OmpStructureChecker::Leave(const parser::OmpClauseList &) { const auto &irClause{ std::get<parser::OmpClause::InReduction>(dataEnvClause->u)}; checkVarAppearsInDataEnvClause( - std::get<parser::OmpObjectList>(irClause.v.t), "IN_REDUCTION"); + *GetOmpObjectList(irClause), "IN_REDUCTION"); } } } @@ -3311,6 +3316,32 @@ void OmpStructureChecker::Leave(const parser::OmpClauseList &) { } } + // Default access-group for DYN_GROUPPRIVATE is "cgroup". On a given + // construct there can be at most one DYN_GROUPPRIVATE with a given + // access-group. + const parser::OmpClause + *accGrpClause[parser::OmpAccessGroup::Value_enumSize] = {nullptr}; + for (auto [_, clause] : + FindClauses(llvm::omp::Clause::OMPC_dyn_groupprivate)) { + auto &wrapper{std::get<parser::OmpClause::DynGroupprivate>(clause->u)}; + auto &modifiers{OmpGetModifiers(wrapper.v)}; + auto accGrp{parser::OmpAccessGroup::Value::Cgroup}; + if (auto *ag{OmpGetUniqueModifier<parser::OmpAccessGroup>(modifiers)}) { + accGrp = ag->v; + } + auto &firstClause{accGrpClause[llvm::to_underlying(accGrp)]}; + if (firstClause) { + context_ + .Say(clause->source, + "The access-group modifier can only occur on a single clause in a construct"_err_en_US) + .Attach(firstClause->source, + "Previous clause with access-group modifier"_en_US); + break; + } else { + firstClause = clause; + } + } + CheckRequireAtLeastOneOf(); } @@ -3355,101 +3386,6 @@ void OmpStructureChecker::Enter(const parser::OmpClause &x) { } } -void OmpStructureChecker::Enter(const parser::OmpClause::Sizes &c) { - CheckAllowedClause(llvm::omp::Clause::OMPC_sizes); - for (const parser::Cosubscript &v : c.v) - RequiresPositiveParameter(llvm::omp::Clause::OMPC_sizes, v, - /*paramName=*/"parameter", /*allowZero=*/false); -} - -// Following clauses do not have a separate node in parse-tree.h. -CHECK_SIMPLE_CLAUSE(Absent, OMPC_absent) -CHECK_SIMPLE_CLAUSE(Affinity, OMPC_affinity) -CHECK_SIMPLE_CLAUSE(Capture, OMPC_capture) -CHECK_SIMPLE_CLAUSE(Contains, OMPC_contains) -CHECK_SIMPLE_CLAUSE(Default, OMPC_default) -CHECK_SIMPLE_CLAUSE(Depobj, OMPC_depobj) -CHECK_SIMPLE_CLAUSE(DeviceType, OMPC_device_type) -CHECK_SIMPLE_CLAUSE(DistSchedule, OMPC_dist_schedule) -CHECK_SIMPLE_CLAUSE(DynGroupprivate, OMPC_dyn_groupprivate) -CHECK_SIMPLE_CLAUSE(Exclusive, OMPC_exclusive) -CHECK_SIMPLE_CLAUSE(Final, OMPC_final) -CHECK_SIMPLE_CLAUSE(Flush, OMPC_flush) -CHECK_SIMPLE_CLAUSE(Full, OMPC_full) -CHECK_SIMPLE_CLAUSE(Grainsize, OMPC_grainsize) -CHECK_SIMPLE_CLAUSE(GraphId, OMPC_graph_id) -CHECK_SIMPLE_CLAUSE(GraphReset, OMPC_graph_reset) -CHECK_SIMPLE_CLAUSE(Holds, OMPC_holds) -CHECK_SIMPLE_CLAUSE(Inclusive, OMPC_inclusive) -CHECK_SIMPLE_CLAUSE(Initializer, OMPC_initializer) -CHECK_SIMPLE_CLAUSE(Match, OMPC_match) -CHECK_SIMPLE_CLAUSE(Nontemporal, OMPC_nontemporal) -CHECK_SIMPLE_CLAUSE(NumTasks, OMPC_num_tasks) -CHECK_SIMPLE_CLAUSE(Order, OMPC_order) -CHECK_SIMPLE_CLAUSE(Read, OMPC_read) -CHECK_SIMPLE_CLAUSE(Threadprivate, OMPC_threadprivate) -CHECK_SIMPLE_CLAUSE(Groupprivate, OMPC_groupprivate) -CHECK_SIMPLE_CLAUSE(Threads, OMPC_threads) -CHECK_SIMPLE_CLAUSE(Threadset, OMPC_threadset) -CHECK_SIMPLE_CLAUSE(Inbranch, OMPC_inbranch) -CHECK_SIMPLE_CLAUSE(Link, OMPC_link) -CHECK_SIMPLE_CLAUSE(Indirect, OMPC_indirect) -CHECK_SIMPLE_CLAUSE(Mergeable, OMPC_mergeable) -CHECK_SIMPLE_CLAUSE(NoOpenmp, OMPC_no_openmp) -CHECK_SIMPLE_CLAUSE(NoOpenmpRoutines, OMPC_no_openmp_routines) -CHECK_SIMPLE_CLAUSE(NoOpenmpConstructs, OMPC_no_openmp_constructs) -CHECK_SIMPLE_CLAUSE(NoParallelism, OMPC_no_parallelism) -CHECK_SIMPLE_CLAUSE(Nogroup, OMPC_nogroup) -CHECK_SIMPLE_CLAUSE(Notinbranch, OMPC_notinbranch) -CHECK_SIMPLE_CLAUSE(Partial, OMPC_partial) -CHECK_SIMPLE_CLAUSE(ProcBind, OMPC_proc_bind) -CHECK_SIMPLE_CLAUSE(Simd, OMPC_simd) -CHECK_SIMPLE_CLAUSE(Permutation, OMPC_permutation) -CHECK_SIMPLE_CLAUSE(Uniform, OMPC_uniform) -CHECK_SIMPLE_CLAUSE(Unknown, OMPC_unknown) -CHECK_SIMPLE_CLAUSE(Untied, OMPC_untied) -CHECK_SIMPLE_CLAUSE(UsesAllocators, OMPC_uses_allocators) -CHECK_SIMPLE_CLAUSE(Write, OMPC_write) -CHECK_SIMPLE_CLAUSE(Init, OMPC_init) -CHECK_SIMPLE_CLAUSE(Use, OMPC_use) -CHECK_SIMPLE_CLAUSE(Novariants, OMPC_novariants) -CHECK_SIMPLE_CLAUSE(Nocontext, OMPC_nocontext) -CHECK_SIMPLE_CLAUSE(Severity, OMPC_severity) -CHECK_SIMPLE_CLAUSE(Message, OMPC_message) -CHECK_SIMPLE_CLAUSE(Filter, OMPC_filter) -CHECK_SIMPLE_CLAUSE(Otherwise, OMPC_otherwise) -CHECK_SIMPLE_CLAUSE(AdjustArgs, OMPC_adjust_args) -CHECK_SIMPLE_CLAUSE(AppendArgs, OMPC_append_args) -CHECK_SIMPLE_CLAUSE(MemoryOrder, OMPC_memory_order) -CHECK_SIMPLE_CLAUSE(Bind, OMPC_bind) -CHECK_SIMPLE_CLAUSE(Compare, OMPC_compare) -CHECK_SIMPLE_CLAUSE(OmpxAttribute, OMPC_ompx_attribute) -CHECK_SIMPLE_CLAUSE(Weak, OMPC_weak) -CHECK_SIMPLE_CLAUSE(AcqRel, OMPC_acq_rel) -CHECK_SIMPLE_CLAUSE(Acquire, OMPC_acquire) -CHECK_SIMPLE_CLAUSE(Relaxed, OMPC_relaxed) -CHECK_SIMPLE_CLAUSE(Release, OMPC_release) -CHECK_SIMPLE_CLAUSE(Replayable, OMPC_replayable) -CHECK_SIMPLE_CLAUSE(Transparent, OMPC_transparent) -CHECK_SIMPLE_CLAUSE(SeqCst, OMPC_seq_cst) -CHECK_SIMPLE_CLAUSE(Fail, OMPC_fail) - -CHECK_REQ_SCALAR_INT_CLAUSE(NumTeams, OMPC_num_teams) -CHECK_REQ_SCALAR_INT_CLAUSE(NumThreads, OMPC_num_threads) -CHECK_REQ_SCALAR_INT_CLAUSE(OmpxDynCgroupMem, OMPC_ompx_dyn_cgroup_mem) -CHECK_REQ_SCALAR_INT_CLAUSE(Priority, OMPC_priority) -CHECK_REQ_SCALAR_INT_CLAUSE(ThreadLimit, OMPC_thread_limit) - -CHECK_REQ_CONSTANT_SCALAR_INT_CLAUSE(Collapse, OMPC_collapse) -CHECK_REQ_CONSTANT_SCALAR_INT_CLAUSE(Safelen, OMPC_safelen) -CHECK_REQ_CONSTANT_SCALAR_INT_CLAUSE(Simdlen, OMPC_simdlen) - -void OmpStructureChecker::Enter(const parser::OmpClause::Looprange &x) { - context_.Say(GetContext().clauseSource, - "LOOPRANGE clause is not implemented yet"_err_en_US, - ContextDirectiveAsFortran()); -} - // Restrictions specific to each clause are implemented apart from the // generalized restrictions. @@ -3478,7 +3414,7 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Destroy &x) { void OmpStructureChecker::Enter(const parser::OmpClause::Reduction &x) { CheckAllowedClause(llvm::omp::Clause::OMPC_reduction); - auto &objects{std::get<parser::OmpObjectList>(x.v.t)}; + auto &objects{*GetOmpObjectList(x)}; if (OmpVerifyModifiers(x.v, llvm::omp::OMPC_reduction, GetContext().clauseSource, context_)) { @@ -3518,7 +3454,7 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Reduction &x) { void OmpStructureChecker::Enter(const parser::OmpClause::InReduction &x) { CheckAllowedClause(llvm::omp::Clause::OMPC_in_reduction); - auto &objects{std::get<parser::OmpObjectList>(x.v.t)}; + auto &objects{*GetOmpObjectList(x)}; if (OmpVerifyModifiers(x.v, llvm::omp::OMPC_in_reduction, GetContext().clauseSource, context_)) { @@ -3536,7 +3472,7 @@ void OmpStructureChecker::Enter(const parser::OmpClause::InReduction &x) { void OmpStructureChecker::Enter(const parser::OmpClause::TaskReduction &x) { CheckAllowedClause(llvm::omp::Clause::OMPC_task_reduction); - auto &objects{std::get<parser::OmpObjectList>(x.v.t)}; + auto &objects{*GetOmpObjectList(x)}; if (OmpVerifyModifiers(x.v, llvm::omp::OMPC_task_reduction, GetContext().clauseSource, context_)) { @@ -4389,8 +4325,7 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Map &x) { }}; evaluate::ExpressionAnalyzer ea{context_}; - const auto &objects{std::get<parser::OmpObjectList>(x.v.t)}; - for (auto &object : objects.v) { + for (auto &object : GetOmpObjectList(x)->v) { if (const parser::Designator *d{GetDesignatorFromObj(object)}) { if (auto &&expr{ea.Analyze(*d)}) { if (hasBasePointer(*expr)) { @@ -4543,7 +4478,7 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Depend &x) { } } if (taskDep) { - auto &objList{std::get<parser::OmpObjectList>(taskDep->t)}; + auto &objList{*GetOmpObjectList(*taskDep)}; if (dir == llvm::omp::OMPD_depobj) { // [5.0:255:13], [5.1:288:6], [5.2:322:26] // A depend clause on a depobj construct must only specify one locator. @@ -4689,7 +4624,7 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Copyprivate &x) { void OmpStructureChecker::Enter(const parser::OmpClause::Lastprivate &x) { CheckAllowedClause(llvm::omp::Clause::OMPC_lastprivate); - const auto &objectList{std::get<parser::OmpObjectList>(x.v.t)}; + const auto &objectList{*GetOmpObjectList(x)}; CheckVarIsNotPartOfAnotherVar( GetContext().clauseSource, objectList, "LASTPRIVATE"); CheckCrayPointee(objectList, "LASTPRIVATE"); @@ -4750,10 +4685,12 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Copyin &x) { void OmpStructureChecker::CheckStructureComponent( const parser::OmpObjectList &objects, llvm::omp::Clause clauseId) { auto CheckComponent{[&](const parser::Designator &designator) { - if (auto *dataRef{std::get_if<parser::DataRef>(&designator.u)}) { + if (const parser::DataRef *dataRef{ + std::get_if<parser::DataRef>(&designator.u)}) { if (!IsDataRefTypeParamInquiry(dataRef)) { - if (auto *comp{parser::Unwrap<parser::StructureComponent>(*dataRef)}) { - context_.Say(comp->component.source, + const auto expr{AnalyzeExpr(context_, designator)}; + if (expr.has_value() && evaluate::HasStructureComponent(expr.value())) { + context_.Say(designator.source, "A variable that is part of another variable cannot appear on the %s clause"_err_en_US, parser::ToUpperCaseLetters(getClauseName(clauseId).str())); } @@ -4929,9 +4866,8 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Enter &x) { x.v, llvm::omp::OMPC_enter, GetContext().clauseSource, context_)) { return; } - const parser::OmpObjectList &objList{std::get<parser::OmpObjectList>(x.v.t)}; SymbolSourceMap symbols; - GetSymbolsInObjectList(objList, symbols); + GetSymbolsInObjectList(*GetOmpObjectList(x), symbols); for (const auto &[symbol, source] : symbols) { if (!IsExtendedListItem(*symbol)) { context_.SayWithDecl(*symbol, source, @@ -4954,7 +4890,7 @@ void OmpStructureChecker::Enter(const parser::OmpClause::From &x) { CheckIteratorModifier(*iter); } - const auto &objList{std::get<parser::OmpObjectList>(x.v.t)}; + const auto &objList{*GetOmpObjectList(x)}; SymbolSourceMap symbols; GetSymbolsInObjectList(objList, symbols); CheckVariableListItem(symbols); @@ -4994,7 +4930,7 @@ void OmpStructureChecker::Enter(const parser::OmpClause::To &x) { CheckIteratorModifier(*iter); } - const auto &objList{std::get<parser::OmpObjectList>(x.v.t)}; + const auto &objList{*GetOmpObjectList(x)}; SymbolSourceMap symbols; GetSymbolsInObjectList(objList, symbols); CheckVariableListItem(symbols); @@ -5257,6 +5193,13 @@ bool OmpStructureChecker::CheckTargetBlockOnlyTeams( if (dirId == llvm::omp::Directive::OMPD_teams) { nestedTeams = true; } + } else if (const auto *ompLoopConstruct{ + std::get_if<parser::OpenMPLoopConstruct>( + &ompConstruct->u)}) { + llvm::omp::Directive dirId{ompLoopConstruct->BeginDir().DirId()}; + if (llvm::omp::topTeamsSet.test(dirId)) { + nestedTeams = true; + } } } @@ -5516,4 +5459,124 @@ void OmpStructureChecker::CheckAllowedRequiresClause(llvmOmpClause clause) { } } +void OmpStructureChecker::Enter(const parser::OpenMPMisplacedEndDirective &x) { + context_.Say(x.DirName().source, "Misplaced OpenMP end-directive"_err_en_US); + PushContextAndClauseSets( + x.DirName().source, llvm::omp::Directive::OMPD_unknown); +} + +void OmpStructureChecker::Leave(const parser::OpenMPMisplacedEndDirective &x) { + dirContext_.pop_back(); +} + +void OmpStructureChecker::Enter(const parser::OpenMPInvalidDirective &x) { + context_.Say(x.source, "Invalid OpenMP directive"_err_en_US); + PushContextAndClauseSets(x.source, llvm::omp::Directive::OMPD_unknown); +} + +void OmpStructureChecker::Leave(const parser::OpenMPInvalidDirective &x) { + dirContext_.pop_back(); +} + +// Use when clause falls under 'struct OmpClause' in 'parse-tree.h'. +#define CHECK_SIMPLE_CLAUSE(X, Y) \ + void OmpStructureChecker::Enter(const parser::OmpClause::X &) { \ + CheckAllowedClause(llvm::omp::Clause::Y); \ + } + +#define CHECK_REQ_CONSTANT_SCALAR_INT_CLAUSE(X, Y) \ + void OmpStructureChecker::Enter(const parser::OmpClause::X &c) { \ + CheckAllowedClause(llvm::omp::Clause::Y); \ + RequiresConstantPositiveParameter(llvm::omp::Clause::Y, c.v); \ + } + +#define CHECK_REQ_SCALAR_INT_CLAUSE(X, Y) \ + void OmpStructureChecker::Enter(const parser::OmpClause::X &c) { \ + CheckAllowedClause(llvm::omp::Clause::Y); \ + RequiresPositiveParameter(llvm::omp::Clause::Y, c.v); \ + } + +// Following clauses do not have a separate node in parse-tree.h. +CHECK_SIMPLE_CLAUSE(Absent, OMPC_absent) +CHECK_SIMPLE_CLAUSE(AcqRel, OMPC_acq_rel) +CHECK_SIMPLE_CLAUSE(Acquire, OMPC_acquire) +CHECK_SIMPLE_CLAUSE(AdjustArgs, OMPC_adjust_args) +CHECK_SIMPLE_CLAUSE(Affinity, OMPC_affinity) +CHECK_SIMPLE_CLAUSE(AppendArgs, OMPC_append_args) +CHECK_SIMPLE_CLAUSE(Bind, OMPC_bind) +CHECK_SIMPLE_CLAUSE(Capture, OMPC_capture) +CHECK_SIMPLE_CLAUSE(Collector, OMPC_collector) +CHECK_SIMPLE_CLAUSE(Compare, OMPC_compare) +CHECK_SIMPLE_CLAUSE(Contains, OMPC_contains) +CHECK_SIMPLE_CLAUSE(Default, OMPC_default) +CHECK_SIMPLE_CLAUSE(Depobj, OMPC_depobj) +CHECK_SIMPLE_CLAUSE(DeviceType, OMPC_device_type) +CHECK_SIMPLE_CLAUSE(DistSchedule, OMPC_dist_schedule) +CHECK_SIMPLE_CLAUSE(Exclusive, OMPC_exclusive) +CHECK_SIMPLE_CLAUSE(Fail, OMPC_fail) +CHECK_SIMPLE_CLAUSE(Filter, OMPC_filter) +CHECK_SIMPLE_CLAUSE(Final, OMPC_final) +CHECK_SIMPLE_CLAUSE(Flush, OMPC_flush) +CHECK_SIMPLE_CLAUSE(Full, OMPC_full) +CHECK_SIMPLE_CLAUSE(Grainsize, OMPC_grainsize) +CHECK_SIMPLE_CLAUSE(GraphId, OMPC_graph_id) +CHECK_SIMPLE_CLAUSE(GraphReset, OMPC_graph_reset) +CHECK_SIMPLE_CLAUSE(Groupprivate, OMPC_groupprivate) +CHECK_SIMPLE_CLAUSE(Holds, OMPC_holds) +CHECK_SIMPLE_CLAUSE(Inbranch, OMPC_inbranch) +CHECK_SIMPLE_CLAUSE(Inclusive, OMPC_inclusive) +CHECK_SIMPLE_CLAUSE(Indirect, OMPC_indirect) +CHECK_SIMPLE_CLAUSE(Inductor, OMPC_inductor) +CHECK_SIMPLE_CLAUSE(Initializer, OMPC_initializer) +CHECK_SIMPLE_CLAUSE(Init, OMPC_init) +CHECK_SIMPLE_CLAUSE(Link, OMPC_link) +CHECK_SIMPLE_CLAUSE(Match, OMPC_match) +CHECK_SIMPLE_CLAUSE(MemoryOrder, OMPC_memory_order) +CHECK_SIMPLE_CLAUSE(Mergeable, OMPC_mergeable) +CHECK_SIMPLE_CLAUSE(Message, OMPC_message) +CHECK_SIMPLE_CLAUSE(Nocontext, OMPC_nocontext) +CHECK_SIMPLE_CLAUSE(Nogroup, OMPC_nogroup) +CHECK_SIMPLE_CLAUSE(Nontemporal, OMPC_nontemporal) +CHECK_SIMPLE_CLAUSE(NoOpenmpConstructs, OMPC_no_openmp_constructs) +CHECK_SIMPLE_CLAUSE(NoOpenmp, OMPC_no_openmp) +CHECK_SIMPLE_CLAUSE(NoOpenmpRoutines, OMPC_no_openmp_routines) +CHECK_SIMPLE_CLAUSE(NoParallelism, OMPC_no_parallelism) +CHECK_SIMPLE_CLAUSE(Notinbranch, OMPC_notinbranch) +CHECK_SIMPLE_CLAUSE(Novariants, OMPC_novariants) +CHECK_SIMPLE_CLAUSE(NumTasks, OMPC_num_tasks) +CHECK_SIMPLE_CLAUSE(OmpxAttribute, OMPC_ompx_attribute) +CHECK_SIMPLE_CLAUSE(Order, OMPC_order) +CHECK_SIMPLE_CLAUSE(Otherwise, OMPC_otherwise) +CHECK_SIMPLE_CLAUSE(Partial, OMPC_partial) +CHECK_SIMPLE_CLAUSE(Permutation, OMPC_permutation) +CHECK_SIMPLE_CLAUSE(ProcBind, OMPC_proc_bind) +CHECK_SIMPLE_CLAUSE(Read, OMPC_read) +CHECK_SIMPLE_CLAUSE(Relaxed, OMPC_relaxed) +CHECK_SIMPLE_CLAUSE(Release, OMPC_release) +CHECK_SIMPLE_CLAUSE(Replayable, OMPC_replayable) +CHECK_SIMPLE_CLAUSE(SeqCst, OMPC_seq_cst) +CHECK_SIMPLE_CLAUSE(Severity, OMPC_severity) +CHECK_SIMPLE_CLAUSE(Simd, OMPC_simd) +CHECK_SIMPLE_CLAUSE(Threadprivate, OMPC_threadprivate) +CHECK_SIMPLE_CLAUSE(Threadset, OMPC_threadset) +CHECK_SIMPLE_CLAUSE(Threads, OMPC_threads) +CHECK_SIMPLE_CLAUSE(Transparent, OMPC_transparent) +CHECK_SIMPLE_CLAUSE(Uniform, OMPC_uniform) +CHECK_SIMPLE_CLAUSE(Unknown, OMPC_unknown) +CHECK_SIMPLE_CLAUSE(Untied, OMPC_untied) +CHECK_SIMPLE_CLAUSE(Use, OMPC_use) +CHECK_SIMPLE_CLAUSE(UsesAllocators, OMPC_uses_allocators) +CHECK_SIMPLE_CLAUSE(Weak, OMPC_weak) +CHECK_SIMPLE_CLAUSE(Write, OMPC_write) + +CHECK_REQ_SCALAR_INT_CLAUSE(NumTeams, OMPC_num_teams) +CHECK_REQ_SCALAR_INT_CLAUSE(NumThreads, OMPC_num_threads) +CHECK_REQ_SCALAR_INT_CLAUSE(OmpxDynCgroupMem, OMPC_ompx_dyn_cgroup_mem) +CHECK_REQ_SCALAR_INT_CLAUSE(Priority, OMPC_priority) +CHECK_REQ_SCALAR_INT_CLAUSE(ThreadLimit, OMPC_thread_limit) + +CHECK_REQ_CONSTANT_SCALAR_INT_CLAUSE(Collapse, OMPC_collapse) +CHECK_REQ_CONSTANT_SCALAR_INT_CLAUSE(Safelen, OMPC_safelen) +CHECK_REQ_CONSTANT_SCALAR_INT_CLAUSE(Simdlen, OMPC_simdlen) + } // namespace Fortran::semantics diff --git a/flang/lib/Semantics/check-omp-structure.h b/flang/lib/Semantics/check-omp-structure.h index 7426559..5bd5ae0 100644 --- a/flang/lib/Semantics/check-omp-structure.h +++ b/flang/lib/Semantics/check-omp-structure.h @@ -82,6 +82,11 @@ public: bool Enter(const parser::BlockConstruct &); void Leave(const parser::BlockConstruct &); + void Enter(const parser::SpecificationPart &); + void Leave(const parser::SpecificationPart &); + void Enter(const parser::ExecutionPart &); + void Leave(const parser::ExecutionPart &); + void Enter(const parser::OpenMPConstruct &); void Leave(const parser::OpenMPConstruct &); void Enter(const parser::OpenMPInteropConstruct &); @@ -89,6 +94,11 @@ public: void Enter(const parser::OpenMPDeclarativeConstruct &); void Leave(const parser::OpenMPDeclarativeConstruct &); + void Enter(const parser::OpenMPMisplacedEndDirective &); + void Leave(const parser::OpenMPMisplacedEndDirective &); + void Enter(const parser::OpenMPInvalidDirective &); + void Leave(const parser::OpenMPInvalidDirective &); + void Enter(const parser::OpenMPLoopConstruct &); void Leave(const parser::OpenMPLoopConstruct &); void Enter(const parser::OmpEndLoopDirective &); @@ -113,8 +123,8 @@ public: void Leave(const parser::OmpDeclareVariantDirective &); void Enter(const parser::OpenMPDeclareSimdConstruct &); void Leave(const parser::OpenMPDeclareSimdConstruct &); - void Enter(const parser::OpenMPDeclarativeAllocate &); - void Leave(const parser::OpenMPDeclarativeAllocate &); + void Enter(const parser::OmpAllocateDirective &); + void Leave(const parser::OmpAllocateDirective &); void Enter(const parser::OpenMPDeclareMapperConstruct &); void Leave(const parser::OpenMPDeclareMapperConstruct &); void Enter(const parser::OpenMPDeclareReductionConstruct &); @@ -129,8 +139,6 @@ public: void Leave(const parser::OmpErrorDirective &); void Enter(const parser::OmpNothingDirective &); void Leave(const parser::OmpNothingDirective &); - void Enter(const parser::OpenMPExecutableAllocate &); - void Leave(const parser::OpenMPExecutableAllocate &); void Enter(const parser::OpenMPAllocatorsConstruct &); void Leave(const parser::OpenMPAllocatorsConstruct &); void Enter(const parser::OpenMPRequiresConstruct &); @@ -263,9 +271,9 @@ private: bool CheckTargetBlockOnlyTeams(const parser::Block &); void CheckWorkshareBlockStmts(const parser::Block &, parser::CharBlock); void CheckWorkdistributeBlockStmts(const parser::Block &, parser::CharBlock); - void CheckAllocateDirective(parser::CharBlock source, - const parser::OmpObjectList &objects, - const parser::OmpClauseList &clauses); + void CheckIndividualAllocateDirective( + const parser::OmpAllocateDirective &x, bool isExecutable); + void CheckExecutableAllocateDirective(const parser::OmpAllocateDirective &x); void CheckIteratorRange(const parser::OmpIteratorSpecifier &x); void CheckIteratorModifier(const parser::OmpIterator &x); @@ -313,8 +321,15 @@ private: void CheckAtomicWrite(const parser::OpenMPAtomicConstruct &x); void CheckAtomicUpdate(const parser::OpenMPAtomicConstruct &x); + void CheckScanModifier(const parser::OmpClause::Reduction &x); + void CheckLooprangeBounds(const parser::OpenMPLoopConstruct &x); + void CheckNestedFuse(const parser::OpenMPLoopConstruct &x); void CheckDistLinear(const parser::OpenMPLoopConstruct &x); void CheckSIMDNest(const parser::OpenMPConstruct &x); + void CheckNestedBlock(const parser::OpenMPLoopConstruct &x, + const parser::Block &body, size_t &nestedCount); + void CheckNestedConstruct(const parser::OpenMPLoopConstruct &x); + void CheckFullUnroll(const parser::OpenMPLoopConstruct &x); void CheckTargetNest(const parser::OpenMPConstruct &x); void CheckTargetUpdate(); void CheckTaskgraph(const parser::OmpBlockConstruct &x); @@ -325,11 +340,6 @@ private: const std::optional<parser::OmpClauseList> &maybeClauses); void CheckCancellationNest( const parser::CharBlock &source, llvm::omp::Directive type); - void CheckAllNamesInAllocateStmt(const parser::CharBlock &source, - const parser::OmpObjectList &ompObjectList, - const parser::AllocateStmt &allocate); - void CheckNameInAllocateStmt(const parser::CharBlock &source, - const parser::Name &ompObject, const parser::AllocateStmt &allocate); std::int64_t GetOrdCollapseLevel(const parser::OpenMPLoopConstruct &x); void CheckReductionObjects( const parser::OmpObjectList &objects, llvm::omp::Clause clauseId); @@ -353,11 +363,6 @@ private: const parser::OmpObjectList &ompObjectList); void CheckIfContiguous(const parser::OmpObject &object); const parser::Name *GetObjectName(const parser::OmpObject &object); - void CheckPredefinedAllocatorRestriction(const parser::CharBlock &source, - const parser::OmpObjectList &ompObjectList); - void CheckPredefinedAllocatorRestriction( - const parser::CharBlock &source, const parser::Name &name); - bool isPredefinedAllocator{false}; void CheckAllowedRequiresClause(llvmOmpClause clause); bool deviceConstructFound_{false}; @@ -383,7 +388,7 @@ private: }; int directiveNest_[LastType + 1] = {0}; - bool inExecutableAllocate_{false}; + int allocateDirectiveLevel{0}; parser::CharBlock visitedAtomicSource_; SymbolSourceMap deferredNonVariables_; @@ -392,6 +397,14 @@ private: std::vector<LoopConstruct> loopStack_; // Scopes for scoping units. std::vector<const Scope *> scopeStack_; + + enum class PartKind : int { + // There are also other "parts", such as internal-subprogram-part, etc, + // but we're keeping track of these two for now. + SpecificationPart, + ExecutionPart, + }; + std::vector<PartKind> partStack_; }; /// Find a duplicate entry in the range, and return an iterator to it. diff --git a/flang/lib/Semantics/dump-expr.cpp b/flang/lib/Semantics/dump-expr.cpp index 66cedab..8d354cf 100644 --- a/flang/lib/Semantics/dump-expr.cpp +++ b/flang/lib/Semantics/dump-expr.cpp @@ -23,6 +23,7 @@ void DumpEvaluateExpr::Show(const evaluate::CoarrayRef &x) { Indent("coarray ref"); Show(x.base()); Show(x.cosubscript()); + Show(x.notify()); Show(x.stat()); Show(x.team()); Outdent(); diff --git a/flang/lib/Semantics/expression.cpp b/flang/lib/Semantics/expression.cpp index c8167fd..6f5d0bf 100644 --- a/flang/lib/Semantics/expression.cpp +++ b/flang/lib/Semantics/expression.cpp @@ -1579,6 +1579,19 @@ MaybeExpr ExpressionAnalyzer::Analyze(const parser::CoindexedNamedObject &x) { std::get<std::list<parser::ImageSelectorSpec>>(x.imageSelector.t)) { common::visit( common::visitors{ + [&](const parser::ImageSelectorSpec::Notify &x) { + Analyze(x.v); + if (const auto *expr{GetExpr(context_, x.v)}) { + if (coarrayRef.notify()) { + Say("coindexed reference has multiple NOTIFY= specifiers"_err_en_US); + } else if (auto dyType{expr->GetType()}; + dyType && IsNotifyType(GetDerivedTypeSpec(*dyType))) { + coarrayRef.set_notify(Expr<SomeType>{*expr}); + } else { + Say("NOTIFY= specifier must have type NOTIFY_TYPE from ISO_FORTRAN_ENV"_err_en_US); + } + } + }, [&](const parser::ImageSelectorSpec::Stat &x) { Analyze(x.v); if (const auto *expr{GetExpr(context_, x.v)}) { @@ -2090,17 +2103,32 @@ static MaybeExpr ImplicitConvertTo(const Symbol &sym, Expr<SomeType> &&expr, } MaybeExpr ExpressionAnalyzer::CheckStructureConstructor( - parser::CharBlock typeName, const semantics::DerivedTypeSpec &spec, + parser::CharBlock typeName, const semantics::DerivedTypeSpec &spec0, std::list<ComponentSpec> &&componentSpecs) { + semantics::Scope &scope{context_.FindScope(typeName)}; + FoldingContext &foldingContext{GetFoldingContext()}; + const semantics::DerivedTypeSpec *effectiveSpec{&spec0}; + if (foldingContext.pdtInstance() && spec0.MightBeParameterized()) { + // We're processing a structure constructor in the context of a derived + // type instantiation, and the derived type of the structure constructor + // is parameterized. Evaluate its parameters in the context of the + // instantiation in progress so that the components in constructor's scope + // have the correct types. + semantics::DerivedTypeSpec newSpec{spec0}; + newSpec.ReevaluateParameters(context()); + const semantics::DeclTypeSpec &instantiatedType{ + semantics::FindOrInstantiateDerivedType( + scope, std::move(newSpec), semantics::DeclTypeSpec::TypeDerived)}; + effectiveSpec = &instantiatedType.derivedTypeSpec(); + } + const semantics::DerivedTypeSpec &spec{*effectiveSpec}; const Symbol &typeSymbol{spec.typeSymbol()}; if (!spec.scope() || !typeSymbol.has<semantics::DerivedTypeDetails>()) { return std::nullopt; // error recovery } - const semantics::Scope &scope{context_.FindScope(typeName)}; const semantics::Scope *pureContext{FindPureProcedureContaining(scope)}; const auto &typeDetails{typeSymbol.get<semantics::DerivedTypeDetails>()}; const Symbol *parentComponent{typeDetails.GetParentComponent(*spec.scope())}; - if (typeSymbol.attrs().test(semantics::Attr::ABSTRACT)) { // C796 AttachDeclaration( Say(typeName, @@ -2140,6 +2168,9 @@ MaybeExpr ExpressionAnalyzer::CheckStructureConstructor( parser::CharBlock exprSource{componentSpec.exprSource}; auto restorer{messages.SetLocation(source)}; const Symbol *symbol{componentSpec.keywordSymbol}; + if (symbol) { + symbol = spec.scope()->FindComponent(symbol->name()); + } MaybeExpr &maybeValue{componentSpec.expr}; if (!maybeValue.has_value()) { return std::nullopt; @@ -2315,7 +2346,6 @@ MaybeExpr ExpressionAnalyzer::CheckStructureConstructor( // convert would cause a segfault. Lowering will deal with // conditionally converting and preserving the lower bounds in this // case. - FoldingContext &foldingContext{GetFoldingContext()}; if (MaybeExpr converted{ImplicitConvertTo(*symbol, std::move(value), /*keepConvertImplicit=*/IsAllocatable(*symbol), foldingContext)}) { diff --git a/flang/lib/Semantics/mod-file.cpp b/flang/lib/Semantics/mod-file.cpp index b419864..840b98d 100644 --- a/flang/lib/Semantics/mod-file.cpp +++ b/flang/lib/Semantics/mod-file.cpp @@ -59,6 +59,7 @@ static void PutBound(llvm::raw_ostream &, const Bound &); static void PutShapeSpec(llvm::raw_ostream &, const ShapeSpec &); static void PutShape( llvm::raw_ostream &, const ArraySpec &, char open, char close); +static void PutMapper(llvm::raw_ostream &, const Symbol &, SemanticsContext &); static llvm::raw_ostream &PutAttr(llvm::raw_ostream &, Attr); static llvm::raw_ostream &PutType(llvm::raw_ostream &, const DeclTypeSpec &); @@ -938,6 +939,7 @@ void ModFileWriter::PutEntity(llvm::raw_ostream &os, const Symbol &symbol) { [&](const ProcEntityDetails &) { PutProcEntity(os, symbol); }, [&](const TypeParamDetails &) { PutTypeParam(os, symbol); }, [&](const UserReductionDetails &) { PutUserReduction(os, symbol); }, + [&](const MapperDetails &) { PutMapper(decls_, symbol, context_); }, [&](const auto &) { common::die("PutEntity: unexpected details: %s", DetailsToString(symbol.details()).c_str()); @@ -1101,6 +1103,16 @@ void ModFileWriter::PutUserReduction( } } +static void PutMapper( + llvm::raw_ostream &os, const Symbol &symbol, SemanticsContext &context) { + const auto &details{symbol.get<MapperDetails>()}; + // Emit each saved DECLARE MAPPER construct as-is, so that consumers of the + // module can reparse it and recreate the mapper symbol and semantics state. + for (const auto *decl : details.GetDeclList()) { + Unparse(os, *decl, context.langOptions()); + } +} + void PutInit(llvm::raw_ostream &os, const Symbol &symbol, const MaybeExpr &init, const parser::Expr *unanalyzed, SemanticsContext &context) { if (IsNamedConstant(symbol) || symbol.owner().IsDerivedType()) { diff --git a/flang/lib/Semantics/openmp-modifiers.cpp b/flang/lib/Semantics/openmp-modifiers.cpp index 717fb03..f191b4d 100644 --- a/flang/lib/Semantics/openmp-modifiers.cpp +++ b/flang/lib/Semantics/openmp-modifiers.cpp @@ -75,6 +75,22 @@ unsigned OmpModifierDescriptor::since(llvm::omp::Clause id) const { // generated in the future. template <> +const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpAccessGroup>() { + static const OmpModifierDescriptor desc{ + /*name=*/"access-group", + /*props=*/ + { + {61, {OmpProperty::Unique}}, + }, + /*clauses=*/ + { + {61, {Clause::OMPC_dyn_groupprivate}}, + }, + }; + return desc; +} + +template <> const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpAlignment>() { static const OmpModifierDescriptor desc{ /*name=*/"alignment", @@ -322,6 +338,22 @@ const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpExpectation>() { } template <> +const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpFallbackModifier>() { + static const OmpModifierDescriptor desc{ + /*name=*/"fallback-modifier", + /*props=*/ + { + {61, {OmpProperty::Unique}}, + }, + /*clauses=*/ + { + {61, {Clause::OMPC_dyn_groupprivate}}, + }, + }; + return desc; +} + +template <> const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpInteropPreference>() { static const OmpModifierDescriptor desc{ /*name=*/"interop-preference", diff --git a/flang/lib/Semantics/openmp-utils.cpp b/flang/lib/Semantics/openmp-utils.cpp index 6b304b6..18a37d6 100644 --- a/flang/lib/Semantics/openmp-utils.cpp +++ b/flang/lib/Semantics/openmp-utils.cpp @@ -186,6 +186,23 @@ bool IsExtendedListItem(const Symbol &sym) { return IsVariableListItem(sym) || sym.IsSubprogram(); } +bool IsTypeParamInquiry(const Symbol &sym) { + return common::visit( // + common::visitors{ + [&](const MiscDetails &d) { + return d.kind() == MiscDetails::Kind::KindParamInquiry || + d.kind() == MiscDetails::Kind::LenParamInquiry; + }, + [&](const TypeParamDetails &s) { return true; }, + [&](auto &&) { return false; }, + }, + sym.details()); +} + +bool IsStructureComponent(const Symbol &sym) { + return sym.owner().kind() == Scope::Kind::DerivedType; +} + bool IsVarOrFunctionRef(const MaybeExpr &expr) { if (expr) { return evaluate::UnwrapProcedureRef(*expr) != nullptr || @@ -479,32 +496,4 @@ bool IsPointerAssignment(const evaluate::Assignment &x) { return std::holds_alternative<evaluate::Assignment::BoundsSpec>(x.u) || std::holds_alternative<evaluate::Assignment::BoundsRemapping>(x.u); } - -/// parser::Block is a list of executable constructs, parser::BlockConstruct -/// is Fortran's BLOCK/ENDBLOCK construct. -/// Strip the outermost BlockConstructs, return the reference to the Block -/// in the executable part of the innermost of the stripped constructs. -/// Specifically, if the given `block` has a single entry (it's a list), and -/// the entry is a BlockConstruct, get the Block contained within. Repeat -/// this step as many times as possible. -const parser::Block &GetInnermostExecPart(const parser::Block &block) { - const parser::Block *iter{&block}; - while (iter->size() == 1) { - const parser::ExecutionPartConstruct &ep{iter->front()}; - if (auto *bc{GetFortranBlockConstruct(ep)}) { - iter = &std::get<parser::Block>(bc->t); - } else { - break; - } - } - return *iter; -} - -bool IsStrictlyStructuredBlock(const parser::Block &block) { - if (block.size() == 1) { - return GetFortranBlockConstruct(block.front()) != nullptr; - } else { - return false; - } -} } // namespace Fortran::semantics::omp diff --git a/flang/lib/Semantics/resolve-directives.cpp b/flang/lib/Semantics/resolve-directives.cpp index 628068f..6211643 100644 --- a/flang/lib/Semantics/resolve-directives.cpp +++ b/flang/lib/Semantics/resolve-directives.cpp @@ -415,6 +415,18 @@ public: return true; } + bool Pre(const parser::SpecificationPart &) { + partStack_.push_back(PartKind::SpecificationPart); + return true; + } + void Post(const parser::SpecificationPart &) { partStack_.pop_back(); } + + bool Pre(const parser::ExecutionPart &) { + partStack_.push_back(PartKind::ExecutionPart); + return true; + } + void Post(const parser::ExecutionPart &) { partStack_.pop_back(); } + bool Pre(const parser::InternalSubprogram &) { // Clear the labels being tracked in the previous scope ClearLabels(); @@ -513,10 +525,16 @@ public: void Post(const parser::OpenMPSimpleStandaloneConstruct &) { PopContext(); } bool Pre(const parser::OpenMPLoopConstruct &); - void Post(const parser::OpenMPLoopConstruct &) { PopContext(); } + void Post(const parser::OpenMPLoopConstruct &) { + ordCollapseLevel++; + PopContext(); + } void Post(const parser::OmpBeginLoopDirective &) { GetContext().withinConstruct = true; } + bool Pre(const parser::OpenMPMisplacedEndDirective &x) { return false; } + bool Pre(const parser::OpenMPInvalidDirective &x) { return false; } + bool Pre(const parser::DoConstruct &); bool Pre(const parser::OpenMPSectionsConstruct &); @@ -639,8 +657,7 @@ public: bool Pre(const parser::OpenMPThreadprivate &); void Post(const parser::OpenMPThreadprivate &) { PopContext(); } - bool Pre(const parser::OpenMPDeclarativeAllocate &); - void Post(const parser::OpenMPDeclarativeAllocate &) { PopContext(); } + bool Pre(const parser::OmpAllocateDirective &); bool Pre(const parser::OpenMPAssumeConstruct &); void Post(const parser::OpenMPAssumeConstruct &) { PopContext(); } @@ -651,9 +668,6 @@ public: bool Pre(const parser::OpenMPDispatchConstruct &); void Post(const parser::OpenMPDispatchConstruct &) { PopContext(); } - bool Pre(const parser::OpenMPExecutableAllocate &); - void Post(const parser::OpenMPExecutableAllocate &); - bool Pre(const parser::OpenMPAllocatorsConstruct &); void Post(const parser::OpenMPAllocatorsConstruct &); @@ -703,8 +717,8 @@ public: return false; } bool Pre(const parser::OmpAllocateClause &x) { - const auto &objectList{std::get<parser::OmpObjectList>(x.t)}; - ResolveOmpObjectList(objectList, Symbol::Flag::OmpAllocate); + ResolveOmpObjectList( + *parser::omp::GetOmpObjectList(x), Symbol::Flag::OmpAllocate); return false; } bool Pre(const parser::OmpClause::Firstprivate &x) { @@ -712,8 +726,8 @@ public: return false; } bool Pre(const parser::OmpClause::Lastprivate &x) { - const auto &objList{std::get<parser::OmpObjectList>(x.v.t)}; - ResolveOmpObjectList(objList, Symbol::Flag::OmpLastPrivate); + ResolveOmpObjectList( + *parser::omp::GetOmpObjectList(x), Symbol::Flag::OmpLastPrivate); return false; } bool Pre(const parser::OmpClause::Copyin &x) { @@ -725,8 +739,8 @@ public: return false; } bool Pre(const parser::OmpLinearClause &x) { - auto &objects{std::get<parser::OmpObjectList>(x.t)}; - ResolveOmpObjectList(objects, Symbol::Flag::OmpLinear); + ResolveOmpObjectList( + *parser::omp::GetOmpObjectList(x), Symbol::Flag::OmpLinear); return false; } @@ -736,13 +750,13 @@ public: } bool Pre(const parser::OmpInReductionClause &x) { - auto &objects{std::get<parser::OmpObjectList>(x.t)}; - ResolveOmpObjectList(objects, Symbol::Flag::OmpInReduction); + ResolveOmpObjectList( + *parser::omp::GetOmpObjectList(x), Symbol::Flag::OmpInReduction); return false; } bool Pre(const parser::OmpClause::Reduction &x) { - const auto &objList{std::get<parser::OmpObjectList>(x.v.t)}; + const auto &objList{*parser::omp::GetOmpObjectList(x)}; ResolveOmpObjectList(objList, Symbol::Flag::OmpReduction); if (auto &modifiers{OmpGetModifiers(x.v)}) { @@ -792,8 +806,8 @@ public: } bool Pre(const parser::OmpAlignedClause &x) { - const auto &alignedNameList{std::get<parser::OmpObjectList>(x.t)}; - ResolveOmpObjectList(alignedNameList, Symbol::Flag::OmpAligned); + ResolveOmpObjectList( + *parser::omp::GetOmpObjectList(x), Symbol::Flag::OmpAligned); return false; } @@ -906,7 +920,7 @@ public: } } - const auto &ompObjList{std::get<parser::OmpObjectList>(x.t)}; + const auto &ompObjList{*parser::omp::GetOmpObjectList(x)}; for (const auto &ompObj : ompObjList.v) { common::visit( common::visitors{ @@ -998,6 +1012,14 @@ private: targetLabels_; parser::CharBlock currentStatementSource_; + enum class PartKind : int { + // There are also other "parts", such as internal-subprogram-part, etc, + // but we're keeping track of these two for now. + SpecificationPart, + ExecutionPart, + }; + std::vector<PartKind> partStack_; + void AddAllocateName(const parser::Name *&object) { allocateNames_.push_back(object); } @@ -2012,6 +2034,7 @@ bool OmpAttributeVisitor::Pre(const parser::OpenMPLoopConstruct &x) { case llvm::omp::Directive::OMPD_teams_distribute_parallel_do_simd: case llvm::omp::Directive::OMPD_teams_distribute_simd: case llvm::omp::Directive::OMPD_teams_loop: + case llvm::omp::Directive::OMPD_fuse: case llvm::omp::Directive::OMPD_tile: case llvm::omp::Directive::OMPD_unroll: PushContext(beginName.source, beginName.v); @@ -2022,8 +2045,7 @@ bool OmpAttributeVisitor::Pre(const parser::OpenMPLoopConstruct &x) { if (beginName.v == llvm::omp::OMPD_master_taskloop || beginName.v == llvm::omp::OMPD_master_taskloop_simd || beginName.v == llvm::omp::OMPD_parallel_master_taskloop || - beginName.v == llvm::omp::OMPD_parallel_master_taskloop_simd || - beginName.v == llvm::omp::Directive::OMPD_target_loop) { + beginName.v == llvm::omp::OMPD_parallel_master_taskloop_simd) { unsigned version{context_.langOptions().OpenMPVersion}; IssueNonConformanceWarning(beginName.v, beginName.source, version); } @@ -2031,13 +2053,9 @@ bool OmpAttributeVisitor::Pre(const parser::OpenMPLoopConstruct &x) { SetContextAssociatedLoopLevel(GetNumAffectedLoopsFromLoopConstruct(x)); if (beginName.v == llvm::omp::Directive::OMPD_do) { - auto &optLoopCons = std::get<std::optional<parser::NestedConstruct>>(x.t); - if (optLoopCons.has_value()) { - if (const auto &doConstruct{ - std::get_if<parser::DoConstruct>(&*optLoopCons)}) { - if (doConstruct->IsDoWhile()) { - return true; - } + if (const parser::DoConstruct *doConstruct{x.GetNestedLoop()}) { + if (doConstruct->IsDoWhile()) { + return true; } } } @@ -2194,18 +2212,11 @@ void OmpAttributeVisitor::CollectNumAffectedLoopsFromInnerLoopContruct( const parser::OpenMPLoopConstruct &x, llvm::SmallVector<std::int64_t> &levels, llvm::SmallVector<const parser::OmpClause *> &clauses) { - - const auto &nestedOptional = - std::get<std::optional<parser::NestedConstruct>>(x.t); - assert(nestedOptional.has_value() && - "Expected a DoConstruct or OpenMPLoopConstruct"); - const auto *innerConstruct = - std::get_if<common::Indirection<parser::OpenMPLoopConstruct>>( - &(nestedOptional.value())); - - if (innerConstruct) { - CollectNumAffectedLoopsFromLoopConstruct( - innerConstruct->value(), levels, clauses); + for (auto &construct : std::get<parser::Block>(x.t)) { + if (auto *innerConstruct{parser::omp::GetOmpLoop(construct)}) { + CollectNumAffectedLoopsFromLoopConstruct( + *innerConstruct, levels, clauses); + } } } @@ -2270,86 +2281,74 @@ void OmpAttributeVisitor::CheckPerfectNestAndRectangularLoop( // Find the associated region by skipping nested loop-associated constructs // such as loop transformations - const parser::NestedConstruct *innermostAssocRegion{nullptr}; - const parser::OpenMPLoopConstruct *innermostConstruct{&x}; - while (const auto &innerAssocStmt{ - std::get<std::optional<parser::NestedConstruct>>( - innermostConstruct->t)}) { - innermostAssocRegion = &(innerAssocStmt.value()); - if (const auto *innerConstruct{ - std::get_if<common::Indirection<parser::OpenMPLoopConstruct>>( - innermostAssocRegion)}) { - innermostConstruct = &innerConstruct->value(); - } else { - break; - } - } - - if (!innermostAssocRegion) - return; - const auto &outer{std::get_if<parser::DoConstruct>(innermostAssocRegion)}; - if (!outer) - return; - - llvm::SmallVector<Symbol *> ivs; - int curLevel{0}; - const parser::DoConstruct *loop{outer}; - while (true) { - auto [iv, lb, ub, step] = GetLoopBounds(*loop); - - if (lb) - checkExprHasSymbols(ivs, lb); - if (ub) - checkExprHasSymbols(ivs, ub); - if (step) - checkExprHasSymbols(ivs, step); - if (iv) { - if (auto *symbol{currScope().FindSymbol(iv->source)}) - ivs.push_back(symbol); - } + for (auto &construct : std::get<parser::Block>(x.t)) { + if (const auto *innermostConstruct{parser::omp::GetOmpLoop(construct)}) { + CheckPerfectNestAndRectangularLoop(*innermostConstruct); + } else if (const auto *doConstruct{ + parser::omp::GetDoConstruct(construct)}) { + + llvm::SmallVector<Symbol *> ivs; + int curLevel{0}; + const auto *loop{doConstruct}; + while (true) { + auto [iv, lb, ub, step] = GetLoopBounds(*loop); + + if (lb) + checkExprHasSymbols(ivs, lb); + if (ub) + checkExprHasSymbols(ivs, ub); + if (step) + checkExprHasSymbols(ivs, step); + if (iv) { + if (auto *symbol{currScope().FindSymbol(iv->source)}) + ivs.push_back(symbol); + } - // Stop after processing all affected loops - if (curLevel + 1 >= dirDepth) - break; + // Stop after processing all affected loops + if (curLevel + 1 >= dirDepth) + break; - // Recurse into nested loop - const auto &block{std::get<parser::Block>(loop->t)}; - if (block.empty()) { - // Insufficient number of nested loops already reported by - // CheckAssocLoopLevel() - break; - } + // Recurse into nested loop + const auto &block{std::get<parser::Block>(loop->t)}; + if (block.empty()) { + // Insufficient number of nested loops already reported by + // CheckAssocLoopLevel() + break; + } - loop = GetDoConstructIf(block.front()); - if (!loop) { - // Insufficient number of nested loops already reported by - // CheckAssocLoopLevel() - break; - } + loop = GetDoConstructIf(block.front()); + if (!loop) { + // Insufficient number of nested loops already reported by + // CheckAssocLoopLevel() + break; + } - auto checkPerfectNest = [&, this]() { - if (block.empty()) - return; - auto last = block.end(); - --last; + auto checkPerfectNest = [&, this]() { + if (block.empty()) + return; + auto last = block.end(); + --last; - // A trailing CONTINUE is not considered part of the loop body - if (parser::Unwrap<parser::ContinueStmt>(*last)) - --last; + // A trailing CONTINUE is not considered part of the loop body + if (parser::Unwrap<parser::ContinueStmt>(*last)) + --last; - // In a perfectly nested loop, the nested loop must be the only statement - if (last == block.begin()) - return; + // In a perfectly nested loop, the nested loop must be the only + // statement + if (last == block.begin()) + return; - // Non-perfectly nested loop - // TODO: Point to non-DO statement, directiveSource as a note - context_.Say(dirContext.directiveSource, - "Canonical loop nest must be perfectly nested."_err_en_US); - }; + // Non-perfectly nested loop + // TODO: Point to non-DO statement, directiveSource as a note + context_.Say(dirContext.directiveSource, + "Canonical loop nest must be perfectly nested."_err_en_US); + }; - checkPerfectNest(); + checkPerfectNest(); - ++curLevel; + ++curLevel; + } + } } } @@ -2363,7 +2362,6 @@ void OmpAttributeVisitor::CheckPerfectNestAndRectangularLoop( // construct with multiple associated do-loops are lastprivate. void OmpAttributeVisitor::PrivatizeAssociatedLoopIndexAndCheckLoopLevel( const parser::OpenMPLoopConstruct &x) { - unsigned version{context_.langOptions().OpenMPVersion}; std::int64_t level{GetContext().associatedLoopLevel}; if (level <= 0) { return; @@ -2382,22 +2380,13 @@ void OmpAttributeVisitor::PrivatizeAssociatedLoopIndexAndCheckLoopLevel( const parser::OmpClause *clause{GetAssociatedClause()}; bool hasCollapseClause{ clause ? (clause->Id() == llvm::omp::OMPC_collapse) : false}; - const parser::OpenMPLoopConstruct *innerMostLoop = &x; - const parser::NestedConstruct *innerMostNest = nullptr; - while (auto &optLoopCons{ - std::get<std::optional<parser::NestedConstruct>>(innerMostLoop->t)}) { - innerMostNest = &(optLoopCons.value()); - if (const auto *innerLoop{ - std::get_if<common::Indirection<parser::OpenMPLoopConstruct>>( - innerMostNest)}) { - innerMostLoop = &(innerLoop->value()); - } else - break; - } - if (innerMostNest) { - if (const auto &outer{std::get_if<parser::DoConstruct>(innerMostNest)}) { - for (const parser::DoConstruct *loop{&*outer}; loop && level > 0; + for (auto &construct : std::get<parser::Block>(x.t)) { + if (const auto *innermostConstruct{parser::omp::GetOmpLoop(construct)}) { + PrivatizeAssociatedLoopIndexAndCheckLoopLevel(*innermostConstruct); + } else if (const auto *doConstruct{ + parser::omp::GetDoConstruct(construct)}) { + for (const parser::DoConstruct *loop{&*doConstruct}; loop && level > 0; --level) { if (loop->IsDoConcurrent()) { // DO CONCURRENT is explicitly allowed for the LOOP construct so long @@ -2430,28 +2419,6 @@ void OmpAttributeVisitor::PrivatizeAssociatedLoopIndexAndCheckLoopLevel( } } CheckAssocLoopLevel(level, GetAssociatedClause()); - } else if (const auto *loop{std::get_if< - common::Indirection<parser::OpenMPLoopConstruct>>( - innerMostNest)}) { - const parser::OmpDirectiveSpecification &beginSpec{ - loop->value().BeginDir()}; - const parser::OmpDirectiveName &beginName{beginSpec.DirName()}; - if (beginName.v != llvm::omp::Directive::OMPD_unroll && - beginName.v != llvm::omp::Directive::OMPD_tile) { - context_.Say(GetContext().directiveSource, - "Only UNROLL or TILE constructs are allowed between an OpenMP Loop Construct and a DO construct"_err_en_US, - parser::ToUpperCaseLetters(llvm::omp::getOpenMPDirectiveName( - GetContext().directive, version) - .str())); - } else { - PrivatizeAssociatedLoopIndexAndCheckLoopLevel(loop->value()); - } - } else { - context_.Say(GetContext().directiveSource, - "A DO loop must follow the %s directive"_err_en_US, - parser::ToUpperCaseLetters( - llvm::omp::getOpenMPDirectiveName(GetContext().directive, version) - .str())); } } } @@ -2510,7 +2477,7 @@ bool OmpAttributeVisitor::Pre(const parser::OpenMPSectionConstruct &x) { bool OmpAttributeVisitor::Pre(const parser::OpenMPCriticalConstruct &x) { const parser::OmpBeginDirective &beginSpec{x.BeginDir()}; - PushContext(beginSpec.DirName().source, beginSpec.DirName().v); + PushContext(beginSpec.DirName().source, beginSpec.DirId()); GetContext().withinConstruct = true; return true; } @@ -2558,10 +2525,24 @@ bool OmpAttributeVisitor::Pre(const parser::OpenMPThreadprivate &x) { return true; } -bool OmpAttributeVisitor::Pre(const parser::OpenMPDeclarativeAllocate &x) { +bool OmpAttributeVisitor::Pre(const parser::OmpAllocateDirective &x) { PushContext(x.source, llvm::omp::Directive::OMPD_allocate); - const auto &list{std::get<parser::OmpObjectList>(x.t)}; - ResolveOmpObjectList(list, Symbol::Flag::OmpDeclarativeAllocateDirective); + assert(!partStack_.empty() && "Misplaced directive"); + + auto ompFlag{partStack_.back() == PartKind::SpecificationPart + ? Symbol::Flag::OmpDeclarativeAllocateDirective + : Symbol::Flag::OmpExecutableAllocateDirective}; + + parser::omp::OmpAllocateInfo info{parser::omp::SplitOmpAllocate(x)}; + for (const parser::OmpAllocateDirective *ad : info.dirs) { + for (const parser::OmpArgument &arg : ad->BeginDir().Arguments().v) { + if (auto *object{omp::GetArgumentObject(arg)}) { + ResolveOmpObject(*object, ompFlag); + } + } + } + + PopContext(); return false; } @@ -2580,23 +2561,13 @@ bool OmpAttributeVisitor::Pre(const parser::OpenMPDispatchConstruct &x) { return true; } -bool OmpAttributeVisitor::Pre(const parser::OpenMPExecutableAllocate &x) { - PushContext(x.source, llvm::omp::Directive::OMPD_allocate); - const auto &list{std::get<std::optional<parser::OmpObjectList>>(x.t)}; - if (list) { - ResolveOmpObjectList(*list, Symbol::Flag::OmpExecutableAllocateDirective); - } - return true; -} - bool OmpAttributeVisitor::Pre(const parser::OpenMPAllocatorsConstruct &x) { const parser::OmpDirectiveSpecification &dirSpec{x.BeginDir()}; PushContext(x.source, dirSpec.DirId()); for (const auto &clause : dirSpec.Clauses().v) { - if (const auto *allocClause{ - std::get_if<parser::OmpClause::Allocate>(&clause.u)}) { - ResolveOmpObjectList(std::get<parser::OmpObjectList>(allocClause->v.t), + if (std::get_if<parser::OmpClause::Allocate>(&clause.u)) { + ResolveOmpObjectList(*parser::omp::GetOmpObjectList(clause), Symbol::Flag::OmpExecutableAllocateDirective); } } @@ -2660,10 +2631,6 @@ bool OmpAttributeVisitor::IsNestedInDirective(llvm::omp::Directive directive) { return false; } -void OmpAttributeVisitor::Post(const parser::OpenMPExecutableAllocate &x) { - PopContext(); -} - void OmpAttributeVisitor::Post(const parser::OpenMPAllocatorsConstruct &x) { PopContext(); } @@ -2948,6 +2915,67 @@ void OmpAttributeVisitor::CreateImplicitSymbols(const Symbol *symbol) { } } +static bool IsOpenMPPointer(const Symbol &symbol) { + if (IsPointer(symbol) || IsBuiltinCPtr(symbol)) + return true; + return false; +} + +static bool IsOpenMPAggregate(const Symbol &symbol) { + if (IsAllocatable(symbol) || IsOpenMPPointer(symbol)) + return false; + + const auto *type{symbol.GetType()}; + // OpenMP categorizes Fortran characters as aggregates. + if (type->category() == Fortran::semantics::DeclTypeSpec::Category::Character) + return true; + + if (const auto *det{symbol.GetUltimate() + .detailsIf<Fortran::semantics::ObjectEntityDetails>()}) + if (det->IsArray()) + return true; + + if (type->AsDerived()) + return true; + + if (IsDeferredShape(symbol) || IsAssumedRank(symbol) || + IsAssumedShape(symbol)) + return true; + return false; +} + +static bool IsOpenMPScalar(const Symbol &symbol) { + if (IsOpenMPAggregate(symbol) || IsOpenMPPointer(symbol) || + IsAllocatable(symbol)) + return false; + const auto *type{symbol.GetType()}; + if ((!symbol.GetShape() || symbol.GetShape()->empty()) && + (type->category() == + Fortran::semantics::DeclTypeSpec::Category::Numeric || + type->category() == + Fortran::semantics::DeclTypeSpec::Category::Logical)) + return true; + return false; +} + +static bool DefaultMapCategoryMatchesSymbol( + parser::OmpVariableCategory::Value category, const Symbol &symbol) { + using VarCat = parser::OmpVariableCategory::Value; + switch (category) { + case VarCat::Scalar: + return IsOpenMPScalar(symbol); + case VarCat::Allocatable: + return IsAllocatable(symbol); + case VarCat::Aggregate: + return IsOpenMPAggregate(symbol); + case VarCat::Pointer: + return IsOpenMPPointer(symbol); + case VarCat::All: + return true; + } + return false; +} + // For OpenMP constructs, check all the data-refs within the constructs // and adjust the symbol for each Name if necessary void OmpAttributeVisitor::Post(const parser::Name &name) { @@ -2983,6 +3011,41 @@ void OmpAttributeVisitor::Post(const parser::Name &name) { } } + // TODO: handle case where default and defaultmap are present on the same + // construct and conflict, defaultmap should supersede default if they + // conflict. + if (!GetContext().defaultMap.empty()) { + // Checked before implicit data sharing attributes as this rule ignores + // them and expects explicit predetermined/specified attributes to be in + // place for the types specified. + if (Symbol * found{currScope().FindSymbol(name.source)}) { + // If the variable has declare target applied to it (enter or link) it + // is exempt from defaultmap(none) restrictions. + // We also exempt procedures and named constants from defaultmap(none) + // checking. + if (!symbol->GetUltimate().test(Symbol::Flag::OmpDeclareTarget) && + !(IsProcedure(*symbol) && + !semantics::IsProcedurePointer(*symbol)) && + !IsNamedConstant(*symbol)) { + auto &dMap = GetContext().defaultMap; + for (auto defaults : dMap) { + if (defaults.second == + parser::OmpDefaultmapClause::ImplicitBehavior::None) { + if (DefaultMapCategoryMatchesSymbol(defaults.first, *found)) { + if (!IsObjectWithDSA(*symbol)) { + context_.Say(name.source, + "The DEFAULTMAP(NONE) clause requires that '%s' must be " + "listed in a " + "data-sharing attribute, data-mapping attribute, or is_device_ptr clause"_err_en_US, + symbol->name()); + } + } + } + } + } + } + } + if (Symbol * found{currScope().FindSymbol(name.source)}) { if (found->GetUltimate().test(semantics::Symbol::Flag::OmpThreadprivate)) return; @@ -3561,8 +3624,8 @@ void OmpAttributeVisitor::IssueNonConformanceWarning(llvm::omp::Directive D, case llvm::omp::OMPD_allocate: setAlternativeStr("ALLOCATORS"); break; - case llvm::omp::OMPD_target_loop: - default:; + default: + break; } context_.Warn(common::UsageWarning::OpenMPUsage, source, "%s"_warn_en_US, warnStrOS.str()); diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp index 220f1c9..345a0e4 100644 --- a/flang/lib/Semantics/resolve-names.cpp +++ b/flang/lib/Semantics/resolve-names.cpp @@ -1700,12 +1700,12 @@ public: void Post(const parser::OpenMPDeclareTargetConstruct &) { SkipImplicitTyping(false); } - bool Pre(const parser::OpenMPDeclarativeAllocate &x) { + bool Pre(const parser::OmpAllocateDirective &x) { AddOmpSourceRange(x.source); SkipImplicitTyping(true); return true; } - void Post(const parser::OpenMPDeclarativeAllocate &) { + void Post(const parser::OmpAllocateDirective &) { SkipImplicitTyping(false); messageHandler().set_currStmtSource(std::nullopt); } @@ -1852,21 +1852,25 @@ bool OmpVisitor::Pre(const parser::OmpMapClause &x) { // TODO: Do we need a specific flag or type here, to distinghuish against // other ConstructName things? Leaving this for the full implementation // of mapper lowering. - auto *misc{symbol->detailsIf<MiscDetails>()}; - if (!misc || misc->kind() != MiscDetails::Kind::ConstructName) + auto &ultimate{symbol->GetUltimate()}; + auto *misc{ultimate.detailsIf<MiscDetails>()}; + auto *md{ultimate.detailsIf<MapperDetails>()}; + if (!md && (!misc || misc->kind() != MiscDetails::Kind::ConstructName)) context().Say(mapper->v.source, "Name '%s' should be a mapper name"_err_en_US, mapper->v.source); else mapper->v.symbol = symbol; } else { - mapper->v.symbol = - &MakeSymbol(mapper->v, MiscDetails{MiscDetails::Kind::ConstructName}); - // TODO: When completing the implementation, we probably want to error if - // the symbol is not declared, but right now, testing that the TODO for - // OmpMapClause happens is obscured by the TODO for declare mapper, so - // leaving this out. Remove the above line once the declare mapper is - // implemented. context().Say(mapper->v.source, "'%s' not - // declared"_err_en_US, mapper->v.source); + // Allow the special 'default' mapper identifier without prior + // declaration so lowering can recognize and handle it. Emit an + // error for any other missing mapper identifier. + if (mapper->v.source.ToString() == "default") { + mapper->v.symbol = &MakeSymbol( + mapper->v, MiscDetails{MiscDetails::Kind::ConstructName}); + } else { + context().Say( + mapper->v.source, "'%s' not declared"_err_en_US, mapper->v.source); + } } } return true; @@ -1880,8 +1884,16 @@ void OmpVisitor::ProcessMapperSpecifier(const parser::OmpMapperSpecifier &spec, // the type has been fully processed. BeginDeclTypeSpec(); auto &mapperName{std::get<std::string>(spec.t)}; - MakeSymbol(parser::CharBlock(mapperName), Attrs{}, - MiscDetails{MiscDetails::Kind::ConstructName}); + // Create or update the mapper symbol with MapperDetails and + // keep track of the declarative construct for module emission. + SourceName mapperSource{context().SaveTempName(std::string{mapperName})}; + Symbol &mapperSym{MakeSymbol(mapperSource, Attrs{})}; + if (!mapperSym.detailsIf<MapperDetails>()) { + mapperSym.set_details(MapperDetails{}); + } + if (!context().langOptions().OpenMPSimd) { + mapperSym.get<MapperDetails>().AddDecl(declaratives_.back()); + } PushScope(Scope::Kind::OtherConstruct, nullptr); Walk(std::get<parser::TypeSpec>(spec.t)); auto &varName{std::get<parser::Name>(spec.t)}; @@ -2141,6 +2153,8 @@ public: void Post(const parser::AssignedGotoStmt &); void Post(const parser::CompilerDirective &); + bool Pre(const parser::SectionSubscript &); + // These nodes should never be reached: they are handled in ProgramUnit bool Pre(const parser::MainProgram &) { llvm_unreachable("This node is handled in ProgramUnit"); @@ -3611,10 +3625,20 @@ void ModuleVisitor::Post(const parser::UseStmt &x) { rename.u); } for (const auto &[name, symbol] : *useModuleScope_) { + // Default USE imports public names, excluding intrinsic-only and most + // miscellaneous details. Allow OpenMP mapper identifiers represented + // as MapperDetails, and also legacy MiscDetails::ConstructName. + bool isMapper{symbol->has<MapperDetails>()}; + if (!isMapper) { + if (const auto *misc{symbol->detailsIf<MiscDetails>()}) { + isMapper = misc->kind() == MiscDetails::Kind::ConstructName; + } + } if (symbol->attrs().test(Attr::PUBLIC) && !IsUseRenamed(symbol->name()) && (!symbol->implicitAttrs().test(Attr::INTRINSIC) || symbol->has<UseDetails>()) && - !symbol->has<MiscDetails>() && useNames.count(name) == 0) { + (!symbol->has<MiscDetails>() || isMapper) && + useNames.count(name) == 0) { SourceName location{x.moduleName.source}; if (auto *localSymbol{FindInScope(name)}) { DoAddUse(location, localSymbol->name(), *localSymbol, *symbol); @@ -3945,22 +3969,6 @@ void ModuleVisitor::DoAddUse(SourceName location, SourceName localName, useProcedure = &useUltimate; } - // Creates a UseErrorDetails symbol in the current scope for a - // current UseDetails symbol, but leaves the UseDetails in the - // scope's name map. - auto CreateLocalUseError{[&]() { - EraseSymbol(*localSymbol); - CHECK(localSymbol->has<UseDetails>()); - UseErrorDetails details{localSymbol->get<UseDetails>()}; - details.add_occurrence(location, useSymbol); - Symbol *newSymbol{&MakeSymbol(localName, Attrs{}, std::move(details))}; - // Restore *localSymbol in currScope - auto iter{currScope().find(localName)}; - CHECK(iter != currScope().end() && &*iter->second == newSymbol); - iter->second = MutableSymbolRef{*localSymbol}; - return newSymbol; - }}; - // When two derived types arrived, try to combine them. const Symbol *combinedDerivedType{nullptr}; if (!useDerivedType) { @@ -3986,8 +3994,19 @@ void ModuleVisitor::DoAddUse(SourceName location, SourceName localName, combinedDerivedType = localDerivedType; } else { // Create a local UseErrorDetails for the ambiguous derived type - if (localGeneric) { - combinedDerivedType = CreateLocalUseError(); + if (localSymbol->has<UseDetails>() && localGeneric) { + // Creates a UseErrorDetails symbol in the current scope for a + // current UseDetails symbol, but leaves the UseDetails in the + // scope's name map. + UseErrorDetails details{localSymbol->get<UseDetails>()}; + EraseSymbol(*localSymbol); + details.add_occurrence(location, useSymbol); + Symbol *newSymbol{&MakeSymbol(localName, Attrs{}, std::move(details))}; + // Restore *localSymbol in currScope + auto iter{currScope().find(localName)}; + CHECK(iter != currScope().end() && &*iter->second == newSymbol); + iter->second = MutableSymbolRef{*localSymbol}; + combinedDerivedType = newSymbol; } else { ConvertToUseError(*localSymbol, location, useSymbol); localDerivedType = nullptr; @@ -10058,6 +10077,7 @@ void ResolveNamesVisitor::Post(const parser::AssignedGotoStmt &x) { void ResolveNamesVisitor::Post(const parser::CompilerDirective &x) { if (std::holds_alternative<parser::CompilerDirective::VectorAlways>(x.u) || + std::holds_alternative<parser::CompilerDirective::VectorLength>(x.u) || std::holds_alternative<parser::CompilerDirective::Unroll>(x.u) || std::holds_alternative<parser::CompilerDirective::UnrollAndJam>(x.u) || std::holds_alternative<parser::CompilerDirective::NoVector>(x.u) || @@ -10065,7 +10085,9 @@ void ResolveNamesVisitor::Post(const parser::CompilerDirective &x) { std::holds_alternative<parser::CompilerDirective::NoUnrollAndJam>(x.u) || std::holds_alternative<parser::CompilerDirective::ForceInline>(x.u) || std::holds_alternative<parser::CompilerDirective::Inline>(x.u) || - std::holds_alternative<parser::CompilerDirective::NoInline>(x.u)) { + std::holds_alternative<parser::CompilerDirective::Prefetch>(x.u) || + std::holds_alternative<parser::CompilerDirective::NoInline>(x.u) || + std::holds_alternative<parser::CompilerDirective::IVDep>(x.u)) { return; } if (const auto *tkr{ @@ -10198,6 +10220,14 @@ template <typename A> std::set<SourceName> GetUses(const A &x) { return uses; } +bool ResolveNamesVisitor::Pre(const parser::SectionSubscript &x) { + // Turn off "in EQUIVALENCE" check for array indexing, because + // the indices themselves are not part of the EQUIVALENCE. + auto restorer{common::ScopedSet(inEquivalenceStmt_, false)}; + Walk(x.u); + return false; +} + bool ResolveNamesVisitor::Pre(const parser::Program &x) { if (Scope * hermetic{context().currentHermeticModuleFileScope()}) { // Processing either the dependent modules or first module of a diff --git a/flang/lib/Semantics/rewrite-parse-tree.cpp b/flang/lib/Semantics/rewrite-parse-tree.cpp index 5b7dab3..60e3e6a 100644 --- a/flang/lib/Semantics/rewrite-parse-tree.cpp +++ b/flang/lib/Semantics/rewrite-parse-tree.cpp @@ -9,6 +9,7 @@ #include "rewrite-parse-tree.h" #include "flang/Common/indirection.h" +#include "flang/Parser/openmp-utils.h" #include "flang/Parser/parse-tree-visitor.h" #include "flang/Parser/parse-tree.h" #include "flang/Parser/tools.h" @@ -117,7 +118,7 @@ static bool ReturnsDataPointer(const Symbol &symbol) { } static bool LoopConstructIsSIMD(parser::OpenMPLoopConstruct *ompLoop) { - return llvm::omp::allSimdSet.test(ompLoop->BeginDir().DirName().v); + return llvm::omp::allSimdSet.test(ompLoop->BeginDir().DirId()); } // Remove non-SIMD OpenMPConstructs once they are parsed. @@ -195,20 +196,24 @@ void RewriteMutator::OpenMPSimdOnly( ++it; continue; } - auto &nest = - std::get<std::optional<parser::NestedConstruct>>(ompLoop->t); - - if (auto *doConstruct = - std::get_if<parser::DoConstruct>(&nest.value())) { - auto &loopBody = std::get<parser::Block>(doConstruct->t); - // We can only remove some constructs from a loop when it's _not_ a - // OpenMP simd loop - OpenMPSimdOnly(loopBody, /*isNonSimdLoopBody=*/true); - auto newDoConstruct = std::move(*doConstruct); - auto newLoop = parser::ExecutionPartConstruct{ - parser::ExecutableConstruct{std::move(newDoConstruct)}}; + std::list<parser::ExecutionPartConstruct> doList; + for (auto &construct : std::get<parser::Block>(ompLoop->t)) { + if (auto *doConstruct = const_cast<parser::DoConstruct *>( + parser::omp::GetDoConstruct(construct))) { + auto &loopBody = std::get<parser::Block>(doConstruct->t); + // We can only remove some constructs from a loop when it's _not_ + // a OpenMP simd loop + OpenMPSimdOnly(const_cast<parser::Block &>(loopBody), + /*isNonSimdLoopBody=*/true); + auto newLoop = parser::ExecutionPartConstruct{ + parser::ExecutableConstruct{std::move(*doConstruct)}}; + doList.insert(doList.end(), std::move(newLoop)); + } + } + if (!doList.empty()) { it = block.erase(it); - block.insert(it, std::move(newLoop)); + for (auto &newLoop : doList) + block.insert(it, std::move(newLoop)); continue; } } else if (auto *ompCon{std::get_if<parser::OpenMPSectionsConstruct>( @@ -386,13 +391,12 @@ bool RewriteMutator::Pre(parser::OpenMPLoopConstruct &ompLoop) { // If we're looking at a non-simd OpenMP loop, we need to explicitly // call OpenMPSimdOnly on the nested loop block while indicating where // the block comes from. - auto &nest = std::get<std::optional<parser::NestedConstruct>>(ompLoop.t); - if (!nest.has_value()) { - return true; - } - if (auto *doConstruct = std::get_if<parser::DoConstruct>(&*nest)) { - auto &innerBlock = std::get<parser::Block>(doConstruct->t); - OpenMPSimdOnly(innerBlock, /*isNonSimdLoopBody=*/true); + for (auto &construct : std::get<parser::Block>(ompLoop.t)) { + if (auto *doConstruct = parser::omp::GetDoConstruct(construct)) { + auto &innerBlock = std::get<parser::Block>(doConstruct->t); + OpenMPSimdOnly(const_cast<parser::Block &>(innerBlock), + /*isNonSimdLoopBody=*/true); + } } } return true; diff --git a/flang/lib/Semantics/symbol.cpp b/flang/lib/Semantics/symbol.cpp index 0ec44b7..ed0715a 100644 --- a/flang/lib/Semantics/symbol.cpp +++ b/flang/lib/Semantics/symbol.cpp @@ -338,7 +338,8 @@ std::string DetailsToString(const Details &details) { [](const TypeParamDetails &) { return "TypeParam"; }, [](const MiscDetails &) { return "Misc"; }, [](const AssocEntityDetails &) { return "AssocEntity"; }, - [](const UserReductionDetails &) { return "UserReductionDetails"; }}, + [](const UserReductionDetails &) { return "UserReductionDetails"; }, + [](const MapperDetails &) { return "MapperDetails"; }}, details); } @@ -379,6 +380,7 @@ bool Symbol::CanReplaceDetails(const Details &details) const { [&](const UserReductionDetails &) { return has<UserReductionDetails>(); }, + [&](const MapperDetails &) { return has<MapperDetails>(); }, [](const auto &) { return false; }, }, details); @@ -685,6 +687,8 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &os, const Details &details) { DumpType(os, type); } }, + // Avoid recursive streaming for MapperDetails; nothing more to dump + [&](const MapperDetails &) {}, [&](const auto &x) { os << x; }, }, details); diff --git a/flang/lib/Semantics/tools.cpp b/flang/lib/Semantics/tools.cpp index 8eddd03..cf1e5e7 100644 --- a/flang/lib/Semantics/tools.cpp +++ b/flang/lib/Semantics/tools.cpp @@ -582,6 +582,18 @@ bool IsOrContainsEventOrLockComponent(const Symbol &original) { return false; } +bool IsOrContainsNotifyComponent(const Symbol &original) { + const Symbol &symbol{ResolveAssociations(original, /*stopAtTypeGuard=*/true)}; + if (evaluate::IsVariable(symbol)) { + if (const DeclTypeSpec *type{symbol.GetType()}) { + if (const DerivedTypeSpec *derived{type->AsDerived()}) { + return IsNotifyType(derived) || FindNotifyPotentialComponent(*derived); + } + } + } + return false; +} + // Check this symbol suitable as a type-bound procedure - C769 bool CanBeTypeBoundProc(const Symbol &symbol) { if (IsDummy(symbol) || IsProcedurePointer(symbol)) { @@ -1489,6 +1501,32 @@ PotentialComponentIterator::const_iterator FindEventOrLockPotentialComponent( return iter; } +PotentialComponentIterator::const_iterator FindNotifyPotentialComponent( + const DerivedTypeSpec &derived, bool ignoreCoarrays) { + PotentialComponentIterator potentials{derived}; + auto iter{potentials.begin()}; + for (auto end{potentials.end()}; iter != end; ++iter) { + const Symbol &component{*iter}; + if (const auto *object{component.detailsIf<ObjectEntityDetails>()}) { + if (const DeclTypeSpec *type{object->type()}) { + if (IsNotifyType(type->AsDerived())) { + if (!ignoreCoarrays) { + break; // found one + } + auto path{iter.GetComponentPath()}; + path.pop_back(); + if (std::find_if(path.begin(), path.end(), [](const Symbol &sym) { + return evaluate::IsCoarray(sym); + }) == path.end()) { + break; // found one not in a coarray + } + } + } + } + } + return iter; +} + UltimateComponentIterator::const_iterator FindAllocatableUltimateComponent( const DerivedTypeSpec &derived) { UltimateComponentIterator ultimates{derived}; diff --git a/flang/lib/Semantics/type.cpp b/flang/lib/Semantics/type.cpp index dba15e6..038a402 100644 --- a/flang/lib/Semantics/type.cpp +++ b/flang/lib/Semantics/type.cpp @@ -192,6 +192,13 @@ void DerivedTypeSpec::EvaluateParameters(SemanticsContext &context) { } } +void DerivedTypeSpec::ReevaluateParameters(SemanticsContext &context) { + evaluated_ = false; + instantiated_ = false; + scope_ = nullptr; + EvaluateParameters(context); +} + void DerivedTypeSpec::AddParamValue(SourceName name, ParamValue &&value) { CHECK(cooked_); auto pair{parameters_.insert(std::make_pair(name, std::move(value)))}; diff --git a/flang/module/__fortran_builtins.f90 b/flang/module/__fortran_builtins.f90 index 4d134fa..a9b6050 100644 --- a/flang/module/__fortran_builtins.f90 +++ b/flang/module/__fortran_builtins.f90 @@ -28,6 +28,9 @@ module __fortran_builtins intrinsic :: __builtin_c_f_pointer public :: __builtin_c_f_pointer + intrinsic :: __builtin_show_descriptor + public :: __builtin_show_descriptor + intrinsic :: sizeof ! extension public :: sizeof diff --git a/flang/module/cooperative_groups.f90 b/flang/module/cooperative_groups.f90 index b8875f7..8bb4af3 100644 --- a/flang/module/cooperative_groups.f90 +++ b/flang/module/cooperative_groups.f90 @@ -14,6 +14,12 @@ use, intrinsic :: __fortran_builtins, only: c_devptr => __builtin_c_devptr implicit none +type :: cluster_group + type(c_devptr), private :: handle + integer(4) :: size + integer(4) :: rank +end type cluster_group + type :: grid_group type(c_devptr), private :: handle integer(4) :: size @@ -33,6 +39,27 @@ type :: thread_group end type thread_group interface + attributes(device) function cluster_block_index() + import + type(dim3) :: cluster_block_index + end function +end interface + +interface + attributes(device) function cluster_dim_blocks() + import + type(dim3) :: cluster_dim_blocks + end function +end interface + +interface + attributes(device) function this_cluster() + import + type(cluster_group) :: this_cluster + end function +end interface + +interface attributes(device) function this_grid() import type(grid_group) :: this_grid diff --git a/flang/module/cudadevice.f90 b/flang/module/cudadevice.f90 index 59af58d..2709719 100644 --- a/flang/module/cudadevice.f90 +++ b/flang/module/cudadevice.f90 @@ -1171,6 +1171,45 @@ implicit none integer(8), intent(inout) :: address integer(8), value :: val end function + attributes(device) pure integer(4) function atomicaddr2(address, val) + !dir$ ignore_tkr (rd) address, (d) val + real(2), dimension(2), intent(inout) :: address + real(2), dimension(2), intent(in) :: val + end function + end interface + + interface atomicaddvector + attributes(device) pure function atomicaddvector_r2x2(address, val) result(z) + !dir$ ignore_tkr (rd) address, (d) val + real(2), dimension(2), intent(inout) :: address + real(2), dimension(2), intent(in) :: val + real(2), dimension(2) :: z + end function + + attributes(device) pure function atomicaddvector_r4x2(address, val) result(z) + !dir$ ignore_tkr (rd) address, (d) val + real(4), dimension(2), intent(inout) :: address + real(4), dimension(2), intent(in) :: val + real(4), dimension(2) :: z + end function + end interface + + interface atomicaddreal4x2 + attributes(device) pure function atomicadd_r4x2(address, val) result(z) + !dir$ ignore_tkr (rd) address, (d) val + real(4), dimension(2), intent(inout) :: address + real(4), dimension(2), intent(in) :: val + real(4), dimension(2) :: z + end function + end interface + + interface atomicaddreal4x4 + attributes(device) pure function atomicadd_r4x4(address, val) result(z) + !dir$ ignore_tkr (rd) address, (d) val + real(4), dimension(4), intent(inout) :: address + real(4), dimension(4), intent(in) :: val + real(4), dimension(4) :: z + end function end interface interface atomicsub diff --git a/flang/module/flang_debug.f90 b/flang/module/flang_debug.f90 new file mode 100644 index 0000000..baab3b2 --- /dev/null +++ b/flang/module/flang_debug.f90 @@ -0,0 +1,14 @@ +!===-- module/flang_debug.f90 ----------------------------------------------===! +! +! Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +! See https://llvm.org/LICENSE.txt for license information. +! SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +! +!===------------------------------------------------------------------------===! + +module flang_debug + + use __fortran_builtins, only: & + show_descriptor => __builtin_show_descriptor + +end module flang_debug diff --git a/flang/test/Analysis/AliasAnalysis/cuf-alloc-source-kind.mlir b/flang/test/Analysis/AliasAnalysis/cuf-alloc-source-kind.mlir new file mode 100644 index 0000000..f062dcb --- /dev/null +++ b/flang/test/Analysis/AliasAnalysis/cuf-alloc-source-kind.mlir @@ -0,0 +1,22 @@ +// REQUIRES: asserts +// RUN: fir-opt %s -pass-pipeline='builtin.module(func.func(test-fir-alias-analysis))' -debug-only=fir-alias-analysis --mlir-disable-threading 2>&1 | FileCheck %s + +// Verify that a CUF allocation is recognized as SourceKind::Allocate by +// fir::AliasAnalysis::getSource. + +module { + func.func @_QQmain() attributes {fir.bindc_name = "TEST"} { + // Allocate two independent device arrays and tag the results; with + // value-scoped MemAlloc handling in AA, these should be classified as + // Allocate and not alias. + %a = cuf.alloc !fir.box<!fir.heap<!fir.array<?xf32>>> {bindc_name = "a1", data_attr = #cuf.cuda<device>, uniq_name = "_QFEa1", test.ptr = "cuf_alloc_a"} -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>> + %b = cuf.alloc !fir.box<!fir.heap<!fir.array<?xf32>>> {bindc_name = "a2", data_attr = #cuf.cuda<device>, uniq_name = "_QFEa2", test.ptr = "cuf_alloc_b"} -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>> + return + } +} + +// CHECK-LABEL: Testing : "_QQmain" +// Distinct allocations should not alias. +// CHECK: cuf_alloc_a#0 <-> cuf_alloc_b#0: NoAlias + + diff --git a/flang/test/Analysis/AliasAnalysis/modref-call-globals.f90 b/flang/test/Analysis/AliasAnalysis/modref-call-globals.f90 index 695b38e..fd1d37d 100644 --- a/flang/test/Analysis/AliasAnalysis/modref-call-globals.f90 +++ b/flang/test/Analysis/AliasAnalysis/modref-call-globals.f90 @@ -75,7 +75,7 @@ end subroutine subroutine test_common implicit none real :: test_var_x_common - common /comm/ test_var_x_common + common /comm/ test_var_x_common call test_effect_external() end subroutine ! CHECK-LABEL: Testing : "_QPtest_common" diff --git a/flang/test/Driver/Inputs/fedora_39_tree/usr/lib/gcc/x86_64-linux-gnu/13/crtbegin.o b/flang/test/Driver/Inputs/fedora_39_tree/usr/lib/gcc/x86_64-linux-gnu/13/crtbegin.o new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/flang/test/Driver/Inputs/fedora_39_tree/usr/lib/gcc/x86_64-linux-gnu/13/crtbegin.o diff --git a/flang/test/Driver/Inputs/fedora_39_tree/usr/lib/gcc/x86_64-linux-gnu/13/crtend.o b/flang/test/Driver/Inputs/fedora_39_tree/usr/lib/gcc/x86_64-linux-gnu/13/crtend.o new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/flang/test/Driver/Inputs/fedora_39_tree/usr/lib/gcc/x86_64-linux-gnu/13/crtend.o diff --git a/flang/test/Driver/Inputs/fedora_39_tree/usr/lib/gcc/x86_64-linux-gnu/13/crti.o b/flang/test/Driver/Inputs/fedora_39_tree/usr/lib/gcc/x86_64-linux-gnu/13/crti.o new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/flang/test/Driver/Inputs/fedora_39_tree/usr/lib/gcc/x86_64-linux-gnu/13/crti.o diff --git a/flang/test/Driver/Inputs/fedora_39_tree/usr/lib/gcc/x86_64-linux-gnu/13/crtn.o b/flang/test/Driver/Inputs/fedora_39_tree/usr/lib/gcc/x86_64-linux-gnu/13/crtn.o new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/flang/test/Driver/Inputs/fedora_39_tree/usr/lib/gcc/x86_64-linux-gnu/13/crtn.o diff --git a/flang/test/Driver/Inputs/fedora_39_tree/usr/lib/gcc/x86_64-redhat-linux/13/crtbegin.o b/flang/test/Driver/Inputs/fedora_39_tree/usr/lib/gcc/x86_64-redhat-linux/13/crtbegin.o new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/flang/test/Driver/Inputs/fedora_39_tree/usr/lib/gcc/x86_64-redhat-linux/13/crtbegin.o diff --git a/flang/test/Driver/Inputs/fedora_39_tree/usr/lib/gcc/x86_64-redhat-linux/13/crtend.o b/flang/test/Driver/Inputs/fedora_39_tree/usr/lib/gcc/x86_64-redhat-linux/13/crtend.o new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/flang/test/Driver/Inputs/fedora_39_tree/usr/lib/gcc/x86_64-redhat-linux/13/crtend.o diff --git a/flang/test/Driver/Inputs/fedora_39_tree/usr/lib/gcc/x86_64-redhat-linux/13/crti.o b/flang/test/Driver/Inputs/fedora_39_tree/usr/lib/gcc/x86_64-redhat-linux/13/crti.o new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/flang/test/Driver/Inputs/fedora_39_tree/usr/lib/gcc/x86_64-redhat-linux/13/crti.o diff --git a/flang/test/Driver/Inputs/fedora_39_tree/usr/lib/gcc/x86_64-redhat-linux/13/crtn.o b/flang/test/Driver/Inputs/fedora_39_tree/usr/lib/gcc/x86_64-redhat-linux/13/crtn.o new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/flang/test/Driver/Inputs/fedora_39_tree/usr/lib/gcc/x86_64-redhat-linux/13/crtn.o diff --git a/flang/test/Driver/convert.f90 b/flang/test/Driver/convert.f90 index 0ba31d2..0b4da02 100755 --- a/flang/test/Driver/convert.f90 +++ b/flang/test/Driver/convert.f90 @@ -1,5 +1,5 @@ ! Ensure argument -fconvert=<value> accepts all relevant options and produces an -! error if an invalid value is specified. +! error if an invalid value is specified. !-------------------------- ! FLANG DRIVER (flang) diff --git a/flang/test/Driver/do_concurrent_to_omp_cli.f90 b/flang/test/Driver/do_concurrent_to_omp_cli.f90 index bdb603f..e44db04 100644 --- a/flang/test/Driver/do_concurrent_to_omp_cli.f90 +++ b/flang/test/Driver/do_concurrent_to_omp_cli.f90 @@ -3,12 +3,12 @@ ! RUN: %flang --help | FileCheck %s --check-prefix=FLANG ! FLANG: -fdo-concurrent-to-openmp=<value> -! FLANG-NEXT: Try to map `do concurrent` loops to OpenMP [none|host|device] +! FLANG-NEXT: Try to map `do concurrent` loops to OpenMP [none|host|device] ! RUN: bbc --help | FileCheck %s --check-prefix=BBC ! BBC: -fdo-concurrent-to-openmp=<string> -! BBC-SAME: Try to map `do concurrent` loops to OpenMP [none|host|device] +! BBC-SAME: Try to map `do concurrent` loops to OpenMP [none|host|device] ! RUN: %flang -c -fdo-concurrent-to-openmp=host %s 2>&1 \ ! RUN: | FileCheck %s --check-prefix=OPT diff --git a/flang/test/Driver/emit-mlir.f90 b/flang/test/Driver/emit-mlir.f90 index de5a62d..f2a4b6c 100644 --- a/flang/test/Driver/emit-mlir.f90 +++ b/flang/test/Driver/emit-mlir.f90 @@ -21,7 +21,7 @@ ! CHECK-NEXT: func.func @main(%arg0: i32, %arg1: !llvm.ptr, %arg2: !llvm.ptr) -> i32 { ! CHECK-NEXT: %c0_i32 = arith.constant 0 : i32 ! CHECK-NEXT: %0 = fir.zero_bits !fir.ref<tuple<i32, !fir.ref<!fir.array<0xtuple<!fir.ref<i8>, !fir.ref<i8>>>>>> -! CHECK-NEXT: fir.call @_FortranAProgramStart(%arg0, %arg1, %arg2, %0) {{.*}} : (i32, !llvm.ptr, !llvm.ptr, !fir.ref<tuple<i32, !fir.ref<!fir.array<0xtuple<!fir.ref<i8>, !fir.ref<i8>>>>>>) +! CHECK-NEXT: fir.call @_FortranAProgramStart(%arg0, %arg1, %arg2, %0) {{.*}} : (i32, !llvm.ptr, !llvm.ptr, !fir.ref<tuple<i32, !fir.ref<!fir.array<0xtuple<!fir.ref<i8>, !fir.ref<i8>>>>>>) ! CHECK-NEXT: fir.call @_QQmain() fastmath<contract> : () -> () ! CHECK-NEXT: fir.call @_FortranAProgramEndStatement() {{.*}} : () -> () ! CHECK-NEXT: return %c0_i32 : i32 diff --git a/flang/test/Driver/fast-real-mod.f90 b/flang/test/Driver/fast-real-mod.f90 index 4ea9b26..1ab28ae 100644 --- a/flang/test/Driver/fast-real-mod.f90 +++ b/flang/test/Driver/fast-real-mod.f90 @@ -1,6 +1,12 @@ +! RUN: %flang -ffast-real-mod -### -c %s 2>&1 | FileCheck %s -check-prefix CHECK-FAST-REAL-MOD ! RUN: %flang -fno-fast-real-mod -### -c %s 2>&1 | FileCheck %s -check-prefix CHECK-NO-FAST-REAL-MOD +! RUN: %flang -fno-fast-real-mod -ffast-real-mod -### -c %s 2>&1 | FileCheck %s -check-prefix CHECK-FAST-REAL-MOD +! RUN: %flang -ffast-real-mod -fno-fast-real-mod -### -c %s 2>&1 | FileCheck %s -check-prefix CHECK-NO-FAST-REAL-MOD +! CHECK-FAST-REAL-MOD: "-ffast-real-mod" +! CHECK-FAST-REAL-MOD-NOT: "-fno-fast-real-mod" ! CHECK-NO-FAST-REAL-MOD: "-fno-fast-real-mod" +! CHECK-NO-FAST-REAL-MOD-NOT: "-fast-real-mod" program test ! nothing to be done in here diff --git a/flang/test/Driver/fatal-errors-parsing.f90 b/flang/test/Driver/fatal-errors-parsing.f90 index 185a6e0..fd8e167 100644 --- a/flang/test/Driver/fatal-errors-parsing.f90 +++ b/flang/test/Driver/fatal-errors-parsing.f90 @@ -7,7 +7,7 @@ program p ! CHECK2: fatal-errors-parsing.f90:{{.*}} error: continue end - + subroutine s contains ! CHECK1-NOT: error: diff --git a/flang/test/Driver/fatal-errors-semantics.f90 b/flang/test/Driver/fatal-errors-semantics.f90 index 54740dd..3d3f642 100644 --- a/flang/test/Driver/fatal-errors-semantics.f90 +++ b/flang/test/Driver/fatal-errors-semantics.f90 @@ -37,4 +37,3 @@ module m call soa(null()) end end -
\ No newline at end of file diff --git a/flang/test/Driver/flang-f-opts.f90 b/flang/test/Driver/flang-f-opts.f90 index 9ef0aba..3f53ada 100644 --- a/flang/test/Driver/flang-f-opts.f90 +++ b/flang/test/Driver/flang-f-opts.f90 @@ -13,20 +13,22 @@ ! CHECK-PROFILE-GENERATE-LLVM: "-fprofile-generate" ! RUN: %flang -### -S -fprofile-use=%S %s 2>&1 | FileCheck -check-prefix=CHECK-PROFILE-USE-DIR %s ! CHECK-PROFILE-USE-DIR: "-fprofile-use={{.*}}" - +! +! ------------------------------------------------------------------------------ ! RUN: %flang -### -fbuiltin %s 2>&1 \ ! RUN: | FileCheck %s -check-prefix=WARN-BUILTIN ! WARN-BUILTIN: warning: '-fbuiltin' is not valid for Fortran - +! ! RUN: %flang -### -fno-builtin %s 2>&1 \ ! RUN: | FileCheck %s -check-prefix=WARN-NO-BUILTIN ! WARN-NO-BUILTIN: warning: '-fno-builtin' is not valid for Fortran - +! ! RUN: %flang -### -fbuiltin -fno-builtin %s 2>&1 \ ! RUN: | FileCheck %s -check-prefix=WARN-BUILTIN-MULTIPLE ! WARN-BUILTIN-MULTIPLE: warning: '-fbuiltin' is not valid for Fortran ! WARN-BUILTIN-MULTIPLE: warning: '-fno-builtin' is not valid for Fortran - +! +! ------------------------------------------------------------------------------ ! When emitting an error with a suggestion, ensure that the diagnostic message ! uses '-Xflang' instead of '-Xclang'. This is typically emitted when an option ! that is available for `flang -fc1` is passed to `flang`. We use -complex-range @@ -43,3 +45,115 @@ ! RUN: | FileCheck %s -check-prefix UNKNOWN-NO-SUGGEST ! ! UNKNOWN-NO-SUGGEST: error: unknown argument: '-not-an-option'{{$}} +! +! ------------------------------------------------------------------------------ +! The options in the command below are gfortran-specific optimization flags that +! are accepted by flang's driver but ignored. Check that the correct warning +! message is displayed when these are used. +! RUN: %flang -### %s \ +! RUN: -finline-limit=1000 \ +! RUN: -finline-limit \ +! RUN: -fexpensive-optimizations \ +! RUN: -fno-expensive-optimizations \ +! RUN: -fno-defer-pop \ +! RUN: -fkeep-inline-functions \ +! RUN: -fno-keep-inline-functions \ +! RUN: -freorder-blocks \ +! RUN: -ffloat-store \ +! RUN: -fgcse \ +! RUN: -fivopts \ +! RUN: -fprefetch-loop-arrays \ +! RUN: -fprofile-correction \ +! RUN: -fprofile-values \ +! RUN: -fschedule-insns \ +! RUN: -fsignaling-nans \ +! RUN: -fstrength-reduce \ +! RUN: -ftracer \ +! RUN: -funroll-all-loops \ +! RUN: -funswitch-loops \ +! RUN: -falign-labels \ +! RUN: -falign-labels=100 \ +! RUN: -falign-jumps \ +! RUN: -falign-jumps=100 \ +! RUN: -fbranch-count-reg \ +! RUN: -fcaller-saves \ +! RUN: -fno-default-inline \ +! RUN: -fgcse-after-reload \ +! RUN: -fgcse-las \ +! RUN: -fgcse-sm \ +! RUN: -fipa-cp \ +! RUN: -finline-functions-called-once \ +! RUN: -fmodulo-sched \ +! RUN: -fmodulo-sched-allow-regmoves \ +! RUN: -fpeel-loops \ +! RUN: -frename-registers \ +! RUN: -fschedule-insns2 \ +! RUN: -fsingle-precision-constant \ +! RUN: -funsafe-loop-optimizations \ +! RUN: -fuse-linker-plugin \ +! RUN: -fvect-cost-model \ +! RUN: -fvariable-expansion-in-unroller \ +! RUN: -fweb \ +! RUN: -fwhole-program \ +! RUN: -fcaller-saves \ +! RUN: -freorder-blocks \ +! RUN: -ffat-lto-objects \ +! RUN: -fmerge-constants \ +! RUN: -finline-small-functions \ +! RUN: -ftree-dce \ +! RUN: -ftree-ter \ +! RUN: -ftree-vrp \ +! RUN: -fno-devirtualize 2>&1 \ +! RUN: | FileCheck --check-prefix=CHECK-WARNING %s +! CHECK-WARNING-DAG: optimization flag '-finline-limit=1000' is not supported +! CHECK-WARNING-DAG: optimization flag '-finline-limit' is not supported +! CHECK-WARNING-DAG: optimization flag '-fexpensive-optimizations' is not supported +! CHECK-WARNING-DAG: optimization flag '-fno-expensive-optimizations' is not supported +! CHECK-WARNING-DAG: optimization flag '-fno-defer-pop' is not supported +! CHECK-WARNING-DAG: optimization flag '-fkeep-inline-functions' is not supported +! CHECK-WARNING-DAG: optimization flag '-fno-keep-inline-functions' is not supported +! CHECK-WARNING-DAG: optimization flag '-freorder-blocks' is not supported +! CHECK-WARNING-DAG: optimization flag '-ffloat-store' is not supported +! CHECK-WARNING-DAG: optimization flag '-fgcse' is not supported +! CHECK-WARNING-DAG: optimization flag '-fivopts' is not supported +! CHECK-WARNING-DAG: optimization flag '-fprefetch-loop-arrays' is not supported +! CHECK-WARNING-DAG: optimization flag '-fprofile-correction' is not supported +! CHECK-WARNING-DAG: optimization flag '-fprofile-values' is not supported +! CHECK-WARNING-DAG: optimization flag '-fschedule-insns' is not supported +! CHECK-WARNING-DAG: optimization flag '-fsignaling-nans' is not supported +! CHECK-WARNING-DAG: optimization flag '-fstrength-reduce' is not supported +! CHECK-WARNING-DAG: optimization flag '-ftracer' is not supported +! CHECK-WARNING-DAG: optimization flag '-funroll-all-loops' is not supported +! CHECK-WARNING-DAG: optimization flag '-funswitch-loops' is not supported +! CHECK-WARNING-DAG: optimization flag '-falign-labels' is not supported +! CHECK-WARNING-DAG: optimization flag '-falign-labels=100' is not supported +! CHECK-WARNING-DAG: optimization flag '-falign-jumps' is not supported +! CHECK-WARNING-DAG: optimization flag '-falign-jumps=100' is not supported +! CHECK-WARNING-DAG: optimization flag '-fbranch-count-reg' is not supported +! CHECK-WARNING-DAG: optimization flag '-fcaller-saves' is not supported +! CHECK-WARNING-DAG: optimization flag '-fno-default-inline' is not supported +! CHECK-WARNING-DAG: optimization flag '-fgcse-after-reload' is not supported +! CHECK-WARNING-DAG: optimization flag '-fgcse-las' is not supported +! CHECK-WARNING-DAG: optimization flag '-fgcse-sm' is not supported +! CHECK-WARNING-DAG: optimization flag '-fipa-cp' is not supported +! CHECK-WARNING-DAG: optimization flag '-finline-functions-called-once' is not supported +! CHECK-WARNING-DAG: optimization flag '-fmodulo-sched' is not supported +! CHECK-WARNING-DAG: optimization flag '-fmodulo-sched-allow-regmoves' is not supported +! CHECK-WARNING-DAG: optimization flag '-fpeel-loops' is not supported +! CHECK-WARNING-DAG: optimization flag '-frename-registers' is not supported +! CHECK-WARNING-DAG: optimization flag '-fschedule-insns2' is not supported +! CHECK-WARNING-DAG: optimization flag '-fsingle-precision-constant' is not supported +! CHECK-WARNING-DAG: optimization flag '-funsafe-loop-optimizations' is not supported +! CHECK-WARNING-DAG: optimization flag '-fuse-linker-plugin' is not supported +! CHECK-WARNING-DAG: optimization flag '-fvect-cost-model' is not supported +! CHECK-WARNING-DAG: optimization flag '-fvariable-expansion-in-unroller' is not supported +! CHECK-WARNING-DAG: optimization flag '-fweb' is not supported +! CHECK-WARNING-DAG: optimization flag '-fwhole-program' is not supported +! CHECK-WARNING-DAG: optimization flag '-fcaller-saves' is not supported +! CHECK-WARNING-DAG: optimization flag '-freorder-blocks' is not supported +! CHECK-WARNING-DAG: optimization flag '-fmerge-constants' is not supported +! CHECK-WARNING-DAG: optimization flag '-finline-small-functions' is not supported +! CHECK-WARNING-DAG: optimization flag '-ftree-dce' is not supported +! CHECK-WARNING-DAG: optimization flag '-ftree-ter' is not supported +! CHECK-WARNING-DAG: optimization flag '-ftree-vrp' is not supported +! CHECK-WARNING-DAG: optimization flag '-fno-devirtualize' is not supported diff --git a/flang/test/Driver/flang-ld-aarch64.f90 b/flang/test/Driver/flang-ld-aarch64.f90 index 61cd46c..4039859 100644 --- a/flang/test/Driver/flang-ld-aarch64.f90 +++ b/flang/test/Driver/flang-ld-aarch64.f90 @@ -1,4 +1,4 @@ -! Check linker flags for AArch64 linux, since it needs both libgcc and +! Check linker flags for AArch64 linux, since it needs both libgcc and ! compiler-rt, with compiler-rt second when -rtlib=libgcc. ! RUN: %flang -### -rtlib=libgcc --target=aarch64-linux-gnu %S/Inputs/hello.f90 2>&1 | FileCheck %s diff --git a/flang/test/Driver/flang-ld-powerpc.f90 b/flang/test/Driver/flang-ld-powerpc.f90 index 5328077ac..9058679 100644 --- a/flang/test/Driver/flang-ld-powerpc.f90 +++ b/flang/test/Driver/flang-ld-powerpc.f90 @@ -4,7 +4,7 @@ !! -static-libflang_rt in the future. Need to add that option here. !! Because flang-rt currently only supports -!! LLVM_ENABLE_PER_TARGET_RUNTIME_DIR=ON, use +!! LLVM_ENABLE_PER_TARGET_RUNTIME_DIR=ON, use !! resource_dir_with_per_target_subdir as inputs. ! Check powerpc64-ibm-aix 64-bit linking to static flang-rt by default @@ -26,7 +26,7 @@ ! AIX64-LD-PER-TARGET-DEFAULT-NOT: "-L/[[RESOURCE_DIR]]{{/|\\\\}}lib{{/|\\\\}}powerpc64-ibm-aix" -! Check powerpc64-ibm-aix 64-bit linking to static flang-rt by option +! Check powerpc64-ibm-aix 64-bit linking to static flang-rt by option ! RUN: %flang -static-libflangrt -Werror %s -### 2>&1 \ ! RUN: --target=powerpc64-ibm-aix \ ! RUN: -resource-dir=%S/../../../clang/test/Driver/Inputs/resource_dir_with_per_target_subdir \ @@ -44,7 +44,7 @@ ! AIX64-LD-PER-TARGET-STATIC-SAME: "-lpthread" -! Check powerpc64-ibm-aix 64-bit linking to shared flang-rt by option +! Check powerpc64-ibm-aix 64-bit linking to shared flang-rt by option ! RUN: %flang -shared-libflangrt -Werror %s -### 2>&1 \ ! RUN: --target=powerpc64-ibm-aix \ ! RUN: -resource-dir=%S/../../../clang/test/Driver/Inputs/resource_dir_with_per_target_subdir \ diff --git a/flang/test/Driver/frame-pointer-forwarding.f90 b/flang/test/Driver/frame-pointer-forwarding.f90 index 9fcbd6e..7e97c98 100644 --- a/flang/test/Driver/frame-pointer-forwarding.f90 +++ b/flang/test/Driver/frame-pointer-forwarding.f90 @@ -1,12 +1,12 @@ ! Test that flang forwards -fno-omit-frame-pointer and -fomit-frame-pointer Flang frontend ! RUN: %flang --target=aarch64-none-none -fsyntax-only -### %s -o %t 2>&1 | FileCheck %s --check-prefix=CHECK-NOVALUE -! CHECK-NOVALUE: "-fc1"{{.*}}"-mframe-pointer=non-leaf" +! CHECK-NOVALUE: "-fc1"{{.*}}"-mframe-pointer=non-leaf-no-reserve" ! RUN: %flang -fomit-frame-pointer --target=aarch64-none-none -fsyntax-only -### %s -o %t 2>&1 | FileCheck %s --check-prefix=CHECK-NONEFP ! CHECK-NONEFP: "-fc1"{{.*}}"-mframe-pointer=none" ! RUN: %flang -fno-omit-frame-pointer --target=aarch64-none-none -fsyntax-only -### %s -o %t 2>&1 | FileCheck %s --check-prefix=CHECK-NONLEAFFP -! CHECK-NONLEAFFP: "-fc1"{{.*}}"-mframe-pointer=non-leaf" +! CHECK-NONLEAFFP: "-fc1"{{.*}}"-mframe-pointer=non-leaf-no-reserve" ! RUN: %flang -fno-omit-frame-pointer --target=x86-none-none -fsyntax-only -### %s -o %t 2>&1 | FileCheck %s --check-prefix=CHECK-ALLFP ! CHECK-ALLFP: "-fc1"{{.*}}"-mframe-pointer=all" diff --git a/flang/test/Driver/gcc-toolchain-install-dir.f90 b/flang/test/Driver/gcc-toolchain-install-dir.f90 index e195bdd..05b73bc 100644 --- a/flang/test/Driver/gcc-toolchain-install-dir.f90 +++ b/flang/test/Driver/gcc-toolchain-install-dir.f90 @@ -5,10 +5,10 @@ ! RUN: %flang 2>&1 -### -v -o %t %s -no-integrated-as -fuse-ld=ld --target=i386-unknown-linux-gnu --gcc-install-dir=%S/Inputs/basic_cross_linux_tree/usr/lib/gcc/i386-unknown-linux-gnu/10.2.0 | FileCheck %s --check-prefix=CHECK-I386 ! RUN: %flang 2>&1 -### -v -o %t %s -no-integrated-as -fuse-ld=ld --target=i386-unknown-linux-gnu --gcc-toolchain=%S/Inputs/basic_cross_linux_tree/usr | FileCheck %s --check-prefix=CHECK-I386 ! CHECK-I386: Selected GCC installation: [[PREFIX:[^"]+]]/Inputs/basic_cross_linux_tree/usr/lib/gcc/i386-unknown-linux-gnu/10.2.0 -! CHECK-I386: "-fc1" "-triple" "i386-unknown-linux-gnu" +! CHECK-I386: "-fc1" "-triple" "i386-unknown-linux-gnu" ! CHECK-I386: "[[PREFIX:[^"]+]]/Inputs/basic_cross_linux_tree/usr/lib/gcc/i386-unknown-linux-gnu/10.2.0/../../../../i386-unknown-linux-gnu/bin{{/|\\\\}}as" ! CHECK-I386: "[[PREFIX]]/Inputs/basic_cross_linux_tree/usr/lib/gcc/i386-unknown-linux-gnu/10.2.0/../../../../i386-unknown-linux-gnu/bin{{/|\\\\}}ld" {{.*}} "-m" "elf_i386" -! CHECK-I386-SAME: "-L[[PREFIX]]/Inputs/basic_cross_linux_tree/usr/lib/gcc/i386-unknown-linux-gnu/10.2.0" +! CHECK-I386-SAME: "-L[[PREFIX]]/Inputs/basic_cross_linux_tree/usr/lib/gcc/i386-unknown-linux-gnu/10.2.0" ! CHECK-I386-SAME: "-L[[PREFIX]]/Inputs/basic_cross_linux_tree/usr/lib/gcc/i386-unknown-linux-gnu/10.2.0/../../../../i386-unknown-linux-gnu/lib" ! RUN: %flang 2>&1 -### -v -o %t %s -no-integrated-as -fuse-ld=ld --target=x86_64-unknown-linux-gnu --gcc-install-dir=%S/Inputs/basic_cross_linux_tree/usr/lib/gcc/x86_64-unknown-linux-gnu/10.2.0 | FileCheck %s --check-prefix=CHECK-X86-64 @@ -17,5 +17,5 @@ ! CHECK-X86-64: "-fc1" "-triple" "x86_64-unknown-linux-gnu" ! CHECK-X86-64: "[[PREFIX:[^"]+]]/Inputs/basic_cross_linux_tree/usr/lib/gcc/x86_64-unknown-linux-gnu/10.2.0/../../../../x86_64-unknown-linux-gnu/bin{{/|\\\\}}as" "--64" ! CHECK-X86-64: "[[PREFIX]]/Inputs/basic_cross_linux_tree/usr/lib/gcc/x86_64-unknown-linux-gnu/10.2.0/../../../../x86_64-unknown-linux-gnu/bin{{/|\\\\}}ld" {{.*}} "-m" "elf_x86_64" -! CHECK-X86-64-SAME: "-L[[PREFIX]]/Inputs/basic_cross_linux_tree/usr/lib/gcc/x86_64-unknown-linux-gnu/10.2.0" +! CHECK-X86-64-SAME: "-L[[PREFIX]]/Inputs/basic_cross_linux_tree/usr/lib/gcc/x86_64-unknown-linux-gnu/10.2.0" ! CHECK-X86-64-SAME: "-L[[PREFIX]]/Inputs/basic_cross_linux_tree/usr/lib/gcc/x86_64-unknown-linux-gnu/10.2.0/../../../../x86_64-unknown-linux-gnu/lib" diff --git a/flang/test/Driver/gcc-triple.f90 b/flang/test/Driver/gcc-triple.f90 new file mode 100644 index 0000000..3aacb84 --- /dev/null +++ b/flang/test/Driver/gcc-triple.f90 @@ -0,0 +1,18 @@ +!! UNSUPPORTED: system-windows, system-aix + +!! Test that --gcc-triple option is working as expected. + +! RUN: %flang --target=x86_64-linux-gnu -v --sysroot=%S/Inputs/fedora_39_tree 2>&1 | FileCheck %s --dump-input=always --check-prefix=DEFAULT_TRIPLE +! DEFAULT_TRIPLE: {{^}}Found candidate GCC installation: +! DEFAULT_TRIPLE: fedora_39_tree/usr/lib/gcc/x86_64-linux-gnu/13 +! DEFAULT_TRIPLE: {{^}}Found candidate GCC installation: +! DEFAULT_TRIPLE: fedora_39_tree/usr/lib/gcc/x86_64-redhat-linux/13 +! DEFAULT_TRIPLE: {{^}}Selected GCC installation: +! DEFAULT_TRIPLE: fedora_39_tree/usr/lib/gcc/x86_64-linux-gnu/13 + +! RUN: %flang -v --sysroot=%S/Inputs/fedora_39_tree --gcc-triple=x86_64-redhat-linux 2>&1 | FileCheck %s --check-prefix=TRIPLE_EXISTS +! TRIPLE_EXISTS: {{^}}Selected GCC installation: +! TRIPLE_EXISTS: fedora_39_tree/usr/lib/gcc/x86_64-redhat-linux/13 + +! RUN: %flang -v --sysroot=%S/Inputs/fedora_39_tree --gcc-triple=x86_64-foo-linux 2>&1 | FileCheck %s --check-prefix=TRIPLE_DOES_NOT_EXISTS +! TRIPLE_DOES_NOT_EXISTS-NOT: x86_64-foo-linux
\ No newline at end of file diff --git a/flang/test/Driver/large-data-threshold.f90 b/flang/test/Driver/large-data-threshold.f90 index 6a7eef7..fa2d4ae 100644 --- a/flang/test/Driver/large-data-threshold.f90 +++ b/flang/test/Driver/large-data-threshold.f90 @@ -5,8 +5,8 @@ ! RUN: %flang -### -c --target=x86_64 -mlarge-data-threshold=32768 %s 2>&1 | FileCheck %s --check-prefix=NO-MCMODEL ! RUN: %flang -### -c --target=x86_64 -mcmodel=small -mlarge-data-threshold=32768 %s 2>&1 | FileCheck %s --check-prefix=NO-MCMODEL ! RUN: not %flang -### -c --target=aarch64 -mcmodel=small -mlarge-data-threshold=32768 %s 2>&1 | FileCheck %s --check-prefix=NOT-SUPPORTED - - + + ! CHECK: "{{.*}}flang" "-fc1" ! CHECK-SAME: "-mlarge-data-threshold=32768" ! CHECK-59000: "{{.*}}flang" "-fc1" diff --git a/flang/test/Driver/lto-fatlto.f90 b/flang/test/Driver/lto-fatlto.f90 index c52d6e3..2ea251e 100644 --- a/flang/test/Driver/lto-fatlto.f90 +++ b/flang/test/Driver/lto-fatlto.f90 @@ -1,5 +1,5 @@ ! REQUIRES: x86-registered-target -! checks fatlto objects: that valid bitcode is included in the object file generated. +! checks fatlto objects: that valid bitcode is included in the object file generated. ! RUN: %flang -fc1 -triple x86_64-unknown-linux-gnu -flto -ffat-lto-objects -emit-obj %s -o %t.o ! RUN: llvm-readelf -S %t.o | FileCheck %s --check-prefixes=ELF diff --git a/flang/test/Driver/mlir-debug-pass-pipeline.f90 b/flang/test/Driver/mlir-debug-pass-pipeline.f90 index eb5165e..0138d9b 100644 --- a/flang/test/Driver/mlir-debug-pass-pipeline.f90 +++ b/flang/test/Driver/mlir-debug-pass-pipeline.f90 @@ -100,7 +100,7 @@ end program ! ALL-NEXT: CSE ! ALL-NEXT: (S) 0 num-cse'd - Number of operations CSE'd ! ALL-NEXT: (S) 0 num-dce'd - Number of operations DCE'd -! ALL-NEXT: MIFOpConversion +! ALL-NEXT: MIFOpConversion ! ALL-NEXT: BoxedProcedurePass ! ALL-NEXT: Pipeline Collection : ['fir.global', 'func.func', 'gpu.module', 'omp.declare_reduction', 'omp.private'] @@ -109,10 +109,10 @@ end program ! ALL-NEXT: 'func.func' Pipeline ! ALL-NEXT: AbstractResultOpt ! ALL-NEXT: 'gpu.module' Pipeline -! ALL-NEXT: Pipeline Collection : ['func.func', 'gpu.func'] -! ALL-NEXT: 'func.func' Pipeline +! ALL-NEXT: Pipeline Collection : ['func.func', 'gpu.func'] +! ALL-NEXT: 'func.func' Pipeline ! ALL-NEXT: AbstractResultOpt -! ALL-NEXT: 'gpu.func' Pipeline +! ALL-NEXT: 'gpu.func' Pipeline ! ALL-NEXT: AbstractResultOpt ! ALL-NEXT: 'omp.declare_reduction' Pipeline ! ALL-NEXT: AbstractResultOpt diff --git a/flang/test/Driver/mlir-pass-pipeline.f90 b/flang/test/Driver/mlir-pass-pipeline.f90 index 3b6a9d7..0d68191 100644 --- a/flang/test/Driver/mlir-pass-pipeline.f90 +++ b/flang/test/Driver/mlir-pass-pipeline.f90 @@ -142,7 +142,7 @@ end program ! ALL-NEXT: (S) 0 num-dce'd - Number of operations DCE'd ! O2-NEXT: 'func.func' Pipeline ! O2-NEXT: SetRuntimeCallAttributes -! ALL-NEXT: MIFOpConversion +! ALL-NEXT: MIFOpConversion ! ALL-NEXT: BoxedProcedurePass ! O2-NEXT: AddAliasTags @@ -152,10 +152,10 @@ end program ! ALL-NEXT: 'func.func' Pipeline ! ALL-NEXT: AbstractResultOpt ! ALL-NEXT: 'gpu.module' Pipeline -! ALL-NEXT: Pipeline Collection : ['func.func', 'gpu.func'] -! ALL-NEXT: 'func.func' Pipeline +! ALL-NEXT: Pipeline Collection : ['func.func', 'gpu.func'] +! ALL-NEXT: 'func.func' Pipeline ! ALL-NEXT: AbstractResultOpt -! ALL-NEXT: 'gpu.func' Pipeline +! ALL-NEXT: 'gpu.func' Pipeline ! ALL-NEXT: AbstractResultOpt ! ALL-NEXT: 'omp.declare_reduction' Pipeline ! ALL-NEXT: AbstractResultOpt diff --git a/flang/test/Driver/multiple-actions-error.f95 b/flang/test/Driver/multiple-actions-error.f95 index 5ec4e91..3b2b7dc 100644 --- a/flang/test/Driver/multiple-actions-error.f95 +++ b/flang/test/Driver/multiple-actions-error.f95 @@ -1,8 +1,30 @@ -! Verify that the frontend driver error-out if multiple actions are specified - -! RUN: not %flang_fc1 -E -fsyntax-only %s 2>&1 | FileCheck %s --check-prefix=ERROR -! RUN: not %flang_fc1 -fsyntax-only -fsyntax-only %s 2>&1 | FileCheck %s --check-prefix=ERROR - -! ERROR: error: Only one action option is allowed - -end progream +! Verify that the frontend driver raises the expected error when multiple +! actions are specified. +! +! RUN: not %flang_fc1 -fsyntax-only -fsyntax-only %s 2>&1 \ +! RUN: | FileCheck %s --check-prefixes=ERROR,ACTIONS-1 +! +! RUN: not %flang_fc1 -E -fsyntax-only %s 2>&1 \ +! RUN: | FileCheck %s --check-prefixes=ERROR,ACTIONS-2 +! +! RUN: not %flang_fc1 -fsyntax-only -E -emit-llvm %s 2>&1 \ +! RUN: | FileCheck %s --check-prefixes=ERROR,ACTIONS-3 +! +! If one or more options are specified with -Xflang, they will appear last in +! the error message. +! +! RUN: not %flang -S -Xflang -emit-llvm %s 2>&1 \ +! RUN: | FileCheck %s --check-prefixes=ERROR,ACTIONS-4 +! +! RUN: not %flang -Xflang -emit-llvm -S %s 2>&1 \ +! RUN: | FileCheck %s --check-prefixes=ERROR,ACTIONS-4 +! +! RUN: not %flang -Xflang -emit-obj -S -Xflang -emit-llvm %s 2>&1 \ +! RUN: | FileCheck %s --check-prefixes=ERROR,ACTIONS-5 +! +! ERROR: error: only one action option is allowed. +! ACTIONS-1: Got '-fsyntax-only', '-fsyntax-only' +! ACTIONS-2: Got '-E', '-fsyntax-only' +! ACTIONS-3: Got '-fsyntax-only', '-E', '-emit-llvm' +! ACTIONS-4: Got '-S', '-emit-llvm' +! ACTIONS-5: Got '-S', '-emit-obj', '-emit-llvm' diff --git a/flang/test/Driver/multiple-fc1-input.f90 b/flang/test/Driver/multiple-fc1-input.f90 index 57f7c5e..e142f35 100644 --- a/flang/test/Driver/multiple-fc1-input.f90 +++ b/flang/test/Driver/multiple-fc1-input.f90 @@ -5,5 +5,5 @@ ! RUN: %flang_fc1 -emit-fir %s %s -o - | FileCheck %s subroutine foo() end subroutine -! CHECK: func @_QPfoo() -! CHECK: func @_QPfoo() +! CHECK: func @_QPfoo() +! CHECK: func @_QPfoo() diff --git a/flang/test/Driver/omp-driver-offload.f90 b/flang/test/Driver/omp-driver-offload.f90 index 0924857..8660bec 100644 --- a/flang/test/Driver/omp-driver-offload.f90 +++ b/flang/test/Driver/omp-driver-offload.f90 @@ -1,9 +1,9 @@ -! Test that flang OpenMP and OpenMP offload related -! commands forward or expand to the appropriate commands +! Test that flang OpenMP and OpenMP offload related +! commands forward or expand to the appropriate commands ! for flang -fc1 as expected. Assumes a gfx90a, aarch64, -! and sm_70 architecture, but doesn't require one to be -! installed or compiled for, just testing the appropriate -! generation of jobs are created with the correct +! and sm_70 architecture, but doesn't require one to be +! installed or compiled for, just testing the appropriate +! generation of jobs are created with the correct ! corresponding arguments. ! Test regular -fopenmp with no offload @@ -47,7 +47,7 @@ ! OFFLOAD-DEVICE-NEXT: "{{[^"]*}}flang" "-fc1" "-triple" "nvptx64-nvidia-cuda" ! OFFLOAD-DEVICE-NOT: "{{[^"]*}}flang" "-fc1" "-triple" "aarch64-unknown-linux-gnu" -! Test regular -fopenmp with offload for basic fopenmp-is-target-device flag addition and correct fopenmp +! Test regular -fopenmp with offload for basic fopenmp-is-target-device flag addition and correct fopenmp ! RUN: %flang -### -fopenmp --offload-arch=gfx90a -fopenmp-targets=amdgcn-amd-amdhsa -nogpulib %s 2>&1 | FileCheck --check-prefixes=CHECK-OPENMP-IS-TARGET-DEVICE %s ! CHECK-OPENMP-IS-TARGET-DEVICE: "{{[^"]*}}flang" "-fc1" {{.*}} "-fopenmp" {{.*}} "-fopenmp-is-target-device" {{.*}}.f90" @@ -169,7 +169,7 @@ ! RUN: | FileCheck %s --check-prefixes=CHECK-OPENMP-VERSION ! CHECK-OPENMP-VERSION: "{{[^"]*}}flang" "-fc1" {{.*}} "-fopenmp" "-fopenmp-version=45" {{.*}}.f90" -! Test diagnostic error when host IR file is non-existent +! Test diagnostic error when host IR file is non-existent ! RUN: not %flang_fc1 %s -o %t 2>&1 -fopenmp -fopenmp-is-target-device \ ! RUN: -fopenmp-host-ir-file-path non-existant-file.bc \ ! RUN: | FileCheck %s --check-prefix=HOST-IR-MISSING diff --git a/flang/test/Driver/tco-emit-final-mlir.fir b/flang/test/Driver/tco-emit-final-mlir.fir index 75f8f15..7e934c9 100644 --- a/flang/test/Driver/tco-emit-final-mlir.fir +++ b/flang/test/Driver/tco-emit-final-mlir.fir @@ -15,5 +15,7 @@ func.func @_QPfoo() { %1 = fir.alloca i32 + %0 = arith.constant 0 : i32 + fir.store %0 to %1 : !fir.ref<i32> return } diff --git a/flang/test/Driver/tune-cpu-fir.f90 b/flang/test/Driver/tune-cpu-fir.f90 index 43c13b4..843feeb 100644 --- a/flang/test/Driver/tune-cpu-fir.f90 +++ b/flang/test/Driver/tune-cpu-fir.f90 @@ -14,7 +14,7 @@ ! ARMTUNE-SAME: fir.tune_cpu = "neoverse-n1" ! ARMBOTH-SAME: fir.target_cpu = "aarch64" -! ARMBOTH-SAME: fir.tune_cpu = "neoverse-n1" +! ARMBOTH-SAME: fir.tune_cpu = "neoverse-n1" ! X86CPU-SAME: fir.target_cpu = "x86-64" ! X86CPU-NOT: fir.tune_cpu = "pentium4" diff --git a/flang/test/Driver/version-loops.f90 b/flang/test/Driver/version-loops.f90 index d206393..c4caf46 100644 --- a/flang/test/Driver/version-loops.f90 +++ b/flang/test/Driver/version-loops.f90 @@ -1,22 +1,22 @@ -! Test that flang forwards the -f{no-,}version-loops-for-stride +! Test that flang forwards the -f{no-,}version-loops-for-stride ! options correctly to flang -fc1 for different variants of optimisation ! and explicit flags. ! RUN: %flang -### %s -o %t 2>&1 -O3 \ ! RUN: | FileCheck %s - + ! RUN: %flang -### %s -o %t 2>&1 -O2 \ ! RUN: | FileCheck %s --check-prefix=CHECK-O2 ! RUN: %flang -### %s -o %t 2>&1 -O2 -fversion-loops-for-stride \ ! RUN: | FileCheck %s --check-prefix=CHECK-O2-with - + ! RUN: %flang -### %s -o %t 2>&1 -O4 \ ! RUN: | FileCheck %s --check-prefix=CHECK-O4 - + ! RUN: %flang -### %s -o %t 2>&1 -Ofast \ ! RUN: | FileCheck %s --check-prefix=CHECK-Ofast - + ! RUN: %flang -### %s -o %t 2>&1 -Ofast -fno-version-loops-for-stride \ ! RUN: | FileCheck %s --check-prefix=CHECK-Ofast-no @@ -29,12 +29,12 @@ ! CHECK-O2: "{{.*}}flang" "-fc1" ! CHECK-O2-NOT: "-fversion-loops-for-stride" -! CHECK-O2-SAME: "-O2" +! CHECK-O2-SAME: "-O2" ! CHECK-O2-with: "{{.*}}flang" "-fc1" ! CHECK-O2-with-SAME: "-fversion-loops-for-stride" -! CHECK-O2-with-SAME: "-O2" - +! CHECK-O2-with-SAME: "-O2" + ! CHECK-O4: "{{.*}}flang" "-fc1" ! CHECK-O4-SAME: "-fversion-loops-for-stride" ! CHECK-O4-SAME: "-O3" diff --git a/flang/test/Evaluate/bug168978.f90 b/flang/test/Evaluate/bug168978.f90 new file mode 100644 index 0000000..ffe7750 --- /dev/null +++ b/flang/test/Evaluate/bug168978.f90 @@ -0,0 +1,6 @@ +!RUN: %flang_fc1 -fdebug-unparse %s 2>&1 | FileCheck %s +subroutine sub(dd) + type(*)::dd(..) + !CHECK: PRINT *, size(lbound(dd)) + print *, size(lbound(dd)) ! do not fold +end diff --git a/flang/test/Evaluate/folding03.f90 b/flang/test/Evaluate/folding03.f90 index 5b7ddd3..1d79098 100644 --- a/flang/test/Evaluate/folding03.f90 +++ b/flang/test/Evaluate/folding03.f90 @@ -83,6 +83,8 @@ module real_tests real(4), parameter :: r4_pinf = 1._4/0._4 !WARN: warning: division by zero [-Wfolding-exception] real(4), parameter :: r4_ninf = -1._4/0._4 + !WARN: warning: Invalid argument to SQRT() [-Wfolding-value-checks] + real(4), parameter :: r4_sqrtneg = sqrt(-1._4) logical, parameter :: test_r4_nan_parentheses1 = .NOT.(((r4_nan)).EQ.r4_nan) logical, parameter :: test_r4_nan_parentheses2 = .NOT.(((r4_nan)).LT.r4_nan) @@ -155,6 +157,8 @@ module real_tests TEST_ISNAN(r4_nan_add5) real(4), parameter :: r4_nan_add6 = r4_nan + r4_nan TEST_ISNAN(r4_nan_add6) + real(4), parameter :: r4_nan_sqrt = sqrt(r4_nan) + TEST_ISNAN(r4_nan_sqrt) !WARN: warning: overflow on multiplication [-Wfolding-exception] logical, parameter :: test_inf_r4_mult1 = (1.5_4*r4_pmax).eq.(r4_pinf) diff --git a/flang/test/Evaluate/folding12.f90 b/flang/test/Evaluate/folding12.f90 index 016e692..1a0a8cb 100644 --- a/flang/test/Evaluate/folding12.f90 +++ b/flang/test/Evaluate/folding12.f90 @@ -5,7 +5,7 @@ module m1 integer :: parent_field end type parent_type type, extends(parent_type) :: child_type - integer :: child_field + integer :: child_field end type child_type type parent_array_type integer, dimension(2) :: parent_field @@ -21,7 +21,7 @@ module m1 type(child_type), parameter :: child_const2 = child_type(12, 13) type(child_type), parameter :: array_var(2) = & [child_type(14, 15), child_type(16, 17)] - logical, parameter :: test_array_child = array_var(2)%child_field == 17 + logical, parameter :: test_array_child = array_var(2)%child_field == 17 logical, parameter :: test_array_parent = array_var(2)%parent_field == 16 type array_type @@ -40,7 +40,7 @@ module m1 type(child_array_type), parameter, dimension(2) :: child_const5 = & [child_array_type([22, 23], 24), child_array_type([25, 26], 27)] integer, dimension(2), parameter :: int_const6 = child_const5(:)%parent_field(2) - logical, parameter :: test_child3 = int_const6(1) == 23 + logical, parameter :: test_child3 = int_const6(1) == 23 type(child_type), parameter :: child_const7 = child_type(28, 29) type(parent_type), parameter :: parent_const8 = child_const7%parent_type @@ -114,7 +114,7 @@ module m3 logical, parameter :: test_parent1 = child_const1%parent_field1 == 12 logical, parameter :: test_parent2 = child_const1%parent_field2 == 10.0 logical, parameter :: test_parent3 = child_const1%parent_field3 .eqv. .false. - logical, parameter :: test_parent4 = & + logical, parameter :: test_parent4 = & child_const1%parent_type%parent_field1 == 12 logical, parameter :: test_parent5 = & child_const1%parent_type%parent_field2 == 10.0 diff --git a/flang/test/Evaluate/folding33.f90 b/flang/test/Evaluate/folding33.f90 index fb5a23cf..299cb7e 100644 --- a/flang/test/Evaluate/folding33.f90 +++ b/flang/test/Evaluate/folding33.f90 @@ -1,4 +1,4 @@ !RUN: %flang_fc1 -fsyntax-only %s 2>&1 | FileCheck %s -!CHECK: warning: overflow on REAL(4) to REAL(2) conversion after folding a call to 'exp' [-Wfolding-exception] +!CHECK: warning: overflow on compilation-time evaluation of a call to 'exp' [-Wfolding-exception] print *, exp((11.265625_2,1._2)) end diff --git a/flang/test/Examples/omp-in-reduction-clause.f90 b/flang/test/Examples/omp-in-reduction-clause.f90 index ced6722..73ba197 100644 --- a/flang/test/Examples/omp-in-reduction-clause.f90 +++ b/flang/test/Examples/omp-in-reduction-clause.f90 @@ -15,7 +15,7 @@ subroutine omp_in_reduction_taskgroup() do i=1,10 z = z * 5 end do - !$omp end taskloop + !$omp end taskloop !$omp end taskgroup end subroutine omp_in_reduction_taskgroup diff --git a/flang/test/Fir/CUDA/cuda-alloc-free.fir b/flang/test/Fir/CUDA/cuda-alloc-free.fir index 31f2ed0..85313d7 100644 --- a/flang/test/Fir/CUDA/cuda-alloc-free.fir +++ b/flang/test/Fir/CUDA/cuda-alloc-free.fir @@ -94,4 +94,24 @@ func.func @_QQalloc_char() attributes {fir.bindc_name = "alloc_char"} { // CHECK: %[[BYTES_CONV:.*]] = fir.convert %[[BYTES]] : (index) -> i64 // CHECK: fir.call @_FortranACUFMemAlloc(%[[BYTES_CONV]], %c0{{.*}}, %{{.*}}, %{{.*}}) {cuf.data_attr = #cuf.cuda<device>} : (i64, i32, !fir.ref<i8>, i32) -> !fir.llvm_ptr<i8> + +func.func @_QQalloc_char2() { + %c4 = arith.constant 4 : index + %1 = cuf.alloc !fir.char<1,4>(%c4 : index) {bindc_name = "b", data_attr = #cuf.cuda<device>, uniq_name = "_QFsub1Eb"} -> !fir.ref<!fir.char<1,4>> + %2 = cuf.alloc !fir.char<2,4>(%c4 : index) {bindc_name = "c", data_attr = #cuf.cuda<device>, uniq_name = "_QFsub1Ec"} -> !fir.ref<!fir.char<2,4>> + %c10 = arith.constant 4 : index + %3 = cuf.alloc !fir.char<4,10>(%c10 : index) {bindc_name = "d", data_attr = #cuf.cuda<device>, uniq_name = "_QFsub1Ed"} -> !fir.ref<!fir.char<4,10>> + return +} + +// CHECK-LABEL: func.func @_QQalloc_char2() +// CHECK: %[[BYTES_4:.*]] = fir.convert %c4{{.*}} : (index) -> i64 +// CHECK: %{{.*}} = fir.call @_FortranACUFMemAlloc(%[[BYTES_4]], %{{.*}}, %{{.*}}, %{{.*}}) {cuf.data_attr = #cuf.cuda<device>} : (i64, i32, !fir.ref<i8>, i32) -> !fir.llvm_ptr<i8> + +// CHECK: %[[BYTES_8:.*]] = fir.convert %c8{{.*}} : (index) -> i64 +// CHECK: %{{.*}} = fir.call @_FortranACUFMemAlloc(%[[BYTES_8]], %{{.*}}, %{{.*}}, %{{.*}}) {cuf.data_attr = #cuf.cuda<device>} : (i64, i32, !fir.ref<i8>, i32) -> !fir.llvm_ptr<i8> + +// CHECK: %[[BYTES_40:.*]] = fir.convert %c40{{.*}} : (index) -> i64 +// CHECK: %{{.*}} = fir.call @_FortranACUFMemAlloc(%[[BYTES_40]], %{{.*}}, %{{.*}}, %{{.*}}) {cuf.data_attr = #cuf.cuda<device>} : (i64, i32, !fir.ref<i8>, i32) -> !fir.llvm_ptr<i8> + } // end module diff --git a/flang/test/Fir/CUDA/cuda-allocate.fir b/flang/test/Fir/CUDA/cuda-allocate.fir index ea7890c..9d0d181 100644 --- a/flang/test/Fir/CUDA/cuda-allocate.fir +++ b/flang/test/Fir/CUDA/cuda-allocate.fir @@ -37,8 +37,8 @@ fir.global @_QMmod1Ea {data_attr = #cuf.cuda<device>} : !fir.box<!fir.heap<!fir. func.func @_QPsub3() { %0 = fir.address_of(@_QMmod1Ea) : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>> %1:2 = hlfir.declare %0 {data_attr = #cuf.cuda<device>, fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QMmod1Ea"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>) - %2 = cuf.allocate %1#1 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>> {data_attr = #cuf.cuda<device>} -> i32 - %3 = cuf.deallocate %1#1 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>> {data_attr = #cuf.cuda<device>} -> i32 + %2 = cuf.allocate %1#1 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>> {data_attr = #cuf.cuda<device>, hasDoubleDescriptor} -> i32 + %3 = cuf.deallocate %1#1 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>> {data_attr = #cuf.cuda<device>, hasDoubleDescriptor} -> i32 return } @@ -109,7 +109,7 @@ func.func @_QQsub6() attributes {fir.bindc_name = "test"} { %3 = fir.convert %c1 : (index) -> i64 %4 = fir.convert %c10_i32 : (i32) -> i64 fir.call @_FortranAAllocatableSetBounds(%2, %c0_i32, %3, %4) fastmath<contract> : (!fir.ref<!fir.box<none>>, i32, i64, i64) -> () - %6 = cuf.allocate %1#1 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> {data_attr = #cuf.cuda<device>} -> i32 + %6 = cuf.allocate %1#1 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> {data_attr = #cuf.cuda<device>, hasDoubleDescriptor} -> i32 return } @@ -158,7 +158,7 @@ func.func @_QMmod1Pallocate_source_global() { %2 = fir.alloca !fir.box<!fir.heap<!fir.array<?x?xf32>>> {bindc_name = "a", uniq_name = "_QMmod1Fallocate_source_globalEa"} %6 = fir.declare %2 {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QMmod1Fallocate_source_globalEa"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?x?xf32>>>>) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?x?xf32>>>> %7 = fir.load %6 : !fir.ref<!fir.box<!fir.heap<!fir.array<?x?xf32>>>> - %21 = cuf.allocate %1 : !fir.ref<!fir.box<!fir.heap<!fir.array<?x?xf32>>>> source(%7 : !fir.box<!fir.heap<!fir.array<?x?xf32>>>) {data_attr = #cuf.cuda<device>} -> i32 + %21 = cuf.allocate %1 : !fir.ref<!fir.box<!fir.heap<!fir.array<?x?xf32>>>> source(%7 : !fir.box<!fir.heap<!fir.array<?x?xf32>>>) {data_attr = #cuf.cuda<device>, hasDoubleDescriptor} -> i32 return } @@ -183,7 +183,7 @@ func.func @_QQallocate_stream() { func.func @_QPp_alloc() { %0 = cuf.alloc !fir.box<!fir.ptr<!fir.array<?xcomplex<f32>>>> {bindc_name = "complex_array", data_attr = #cuf.cuda<device>, uniq_name = "_QFp_allocEcomplex_array"} -> !fir.ref<!fir.box<!fir.ptr<!fir.array<?xcomplex<f32>>>>> %4 = fir.declare %0 {data_attr = #cuf.cuda<device>, fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFp_allocEcomplex_array"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xcomplex<f32>>>>>) -> !fir.ref<!fir.box<!fir.ptr<!fir.array<?xcomplex<f32>>>>> - %9 = cuf.allocate %4 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xcomplex<f32>>>>> {data_attr = #cuf.cuda<device>} -> i32 + %9 = cuf.allocate %4 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xcomplex<f32>>>>> {data_attr = #cuf.cuda<device>, pointer} -> i32 return } @@ -201,7 +201,7 @@ func.func @_QPpointer_source() { %5 = cuf.alloc !fir.box<!fir.ptr<!fir.array<?x?xf32>>> {bindc_name = "a_d", data_attr = #cuf.cuda<device>, uniq_name = "_QFpointer_sourceEa_d"} -> !fir.ref<!fir.box<!fir.ptr<!fir.array<?x?xf32>>>> %7 = fir.declare %5 {data_attr = #cuf.cuda<device>, fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFpointer_sourceEa_d"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?x?xf32>>>>) -> !fir.ref<!fir.box<!fir.ptr<!fir.array<?x?xf32>>>> %8 = fir.load %4 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?x?xf32>>>> - %22 = cuf.allocate %7 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?x?xf32>>>> source(%8 : !fir.box<!fir.ptr<!fir.array<?x?xf32>>>) {data_attr = #cuf.cuda<device>} -> i32 + %22 = cuf.allocate %7 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?x?xf32>>>> source(%8 : !fir.box<!fir.ptr<!fir.array<?x?xf32>>>) {data_attr = #cuf.cuda<device>, pointer} -> i32 return } @@ -226,7 +226,7 @@ func.func @_QQpointer_sync() attributes {fir.bindc_name = "test"} { %3 = fir.convert %c1 : (index) -> i64 %4 = fir.convert %c10_i32 : (i32) -> i64 fir.call @_FortranAAllocatableSetBounds(%2, %c0_i32, %3, %4) fastmath<contract> : (!fir.ref<!fir.box<none>>, i32, i64, i64) -> () - %6 = cuf.allocate %1 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>> {data_attr = #cuf.cuda<device>} -> i32 + %6 = cuf.allocate %1 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>> {data_attr = #cuf.cuda<device>, hasDoubleDescriptor, pointer} -> i32 return } @@ -246,7 +246,7 @@ func.func @_QMmod1Ppointer_source_global() { %2 = fir.alloca !fir.box<!fir.ptr<!fir.array<?x?xf32>>> {bindc_name = "a", uniq_name = "_QMmod1Fallocate_source_globalEa"} %6 = fir.declare %2 {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QMmod1Fallocate_source_globalEa"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?x?xf32>>>>) -> !fir.ref<!fir.box<!fir.ptr<!fir.array<?x?xf32>>>> %7 = fir.load %6 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?x?xf32>>>> - %21 = cuf.allocate %1 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?x?xf32>>>> source(%7 : !fir.box<!fir.ptr<!fir.array<?x?xf32>>>) {data_attr = #cuf.cuda<device>} -> i32 + %21 = cuf.allocate %1 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?x?xf32>>>> source(%7 : !fir.box<!fir.ptr<!fir.array<?x?xf32>>>) {data_attr = #cuf.cuda<device>, hasDoubleDescriptor, pointer} -> i32 return } diff --git a/flang/test/Fir/CUDA/cuda-code-gen.mlir b/flang/test/Fir/CUDA/cuda-code-gen.mlir index 60cda9e..e83648f 100644 --- a/flang/test/Fir/CUDA/cuda-code-gen.mlir +++ b/flang/test/Fir/CUDA/cuda-code-gen.mlir @@ -201,9 +201,9 @@ func.func @_QMm1Psub1(%arg0: !fir.box<!fir.array<?xi32>> {cuf.data_attr = #cuf.c // ----- -fir.global common @_QPshared_static__shared_mem(dense<0> : vector<28xi8>) {alignment = 8 : i64, data_attr = #cuf.cuda<shared>} : !fir.array<28xi8> +fir.global common @_QPshared_static__shared_mem__(dense<0> : vector<28xi8>) {alignment = 8 : i64, data_attr = #cuf.cuda<shared>} : !fir.array<28xi8> -// CHECK: llvm.mlir.global common @_QPshared_static__shared_mem(dense<0> : vector<28xi8>) {addr_space = 3 : i32, alignment = 8 : i64} : !llvm.array<28 x i8> +// CHECK: llvm.mlir.global common @_QPshared_static__shared_mem__(dense<0> : vector<28xi8>) {addr_space = 3 : i32, alignment = 8 : i64} : !llvm.array<28 x i8> // ----- diff --git a/flang/test/Fir/CUDA/cuda-constructor-2.f90 b/flang/test/Fir/CUDA/cuda-constructor-2.f90 index 62118bb..f21d8f9 100644 --- a/flang/test/Fir/CUDA/cuda-constructor-2.f90 +++ b/flang/test/Fir/CUDA/cuda-constructor-2.f90 @@ -28,10 +28,10 @@ module attributes {dlti.dl_spec = #dlti.dl_spec<#dlti.dl_entry<!llvm.ptr, dense< // CHECK-DAG: fir.call @_FortranACUFRegisterVariable(%[[MODULE2]], %[[VAR_ADDR2]], %[[VAR_NAME2]], %[[CST2]]) : (!fir.ref<!fir.llvm_ptr<i8>>, !fir.ref<i8>, !fir.ref<i8>, i64) -> () // CHECK-DAG: %[[BOX:.*]] = fir.address_of(@_QMmtestsEndev) : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> // CHECK-DAG: %[[BOXREF:.*]] = fir.convert %[[BOX]] : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) -> !fir.ref<i8> -// CHECK-DAG: fir.call @_FortranACUFRegisterVariable(%[[MODULE:.*]], %[[BOXREF]], %{{.*}}, %{{.*}}) +// CHECK-DAG: fir.call @_FortranACUFRegisterVariable(%[[MODULE:.*]], %[[BOXREF]], %{{.*}}, %{{.*}}) // -// ----- +// ----- // Checking that constant global variables are not registered @@ -40,7 +40,7 @@ module attributes {dlti.dl_spec = #dlti.dl_spec<#dlti.dl_entry<!llvm.ptr, dense< module attributes {dlti.dl_spec = #dlti.dl_spec<i8 = dense<8> : vector<2xi64>, i16 = dense<16> : vector<2xi64>, i1 = dense<8> : vector<2xi64>, !llvm.ptr = dense<64> : vector<4xi64>, f80 = dense<128> : vector<2xi64>, i128 = dense<128> : vector<2xi64>, i64 = dense<64> : vector<2xi64>, !llvm.ptr<271> = dense<32> : vector<4xi64>, !llvm.ptr<272> = dense<64> : vector<4xi64>, f128 = dense<128> : vector<2xi64>, !llvm.ptr<270> = dense<32> : vector<4xi64>, f16 = dense<16> : vector<2xi64>, f64 = dense<64> : vector<2xi64>, i32 = dense<32> : vector<2xi64>, "dlti.stack_alignment" = 128 : i64, "dlti.endianness" = "little">, fir.defaultkind = "a1c4d8i4l4r4", fir.kindmap = "", gpu.container_module, llvm.data_layout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128", llvm.ident = "flang version 20.0.0 (https://github.com/llvm/llvm-project.git 3372303188df0f7f8ac26e7ab610cf8b0f716d42)", llvm.target_triple = "x86_64-unknown-linux-gnu"} { fir.global @_QMiso_c_bindingECc_int constant : i32 - + fir.type_info @_QM__fortran_builtinsT__builtin_c_ptr noinit nodestroy nofinal : !fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}> gpu.module @cuda_device_mod { @@ -63,7 +63,7 @@ module attributes {dlti.dl_spec = #dlti.dl_spec<i8 = dense<8> : vector<2xi64>, i // ----- -module attributes {dlti.dl_spec = #dlti.dl_spec<i8 = dense<8> : vector<2xi64>, i16 = dense<16> : vector<2xi64>, i1 = dense<8> : vector<2xi64>, !llvm.ptr = dense<64> : vector<4xi64>, f80 = dense<128> : vector<2xi64>, i128 = dense<128> : vector<2xi64>, i64 = dense<64> : vector<2xi64>, !llvm.ptr<271> = dense<32> : vector<4xi64>, !llvm.ptr<272> = dense<64> : vector<4xi64>, f128 = dense<128> : vector<2xi64>, !llvm.ptr<270> = dense<32> : vector<4xi64>, f16 = dense<16> : vector<2xi64>, f64 = dense<64> : vector<2xi64>, i32 = dense<32> : vector<2xi64>, "dlti.stack_alignment" = 128 : i64, "dlti.endianness" = "little">, fir.defaultkind = "a1c4d8i4l4r4", fir.kindmap = "", gpu.container_module, llvm.data_layout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128", llvm.ident = "flang version 20.0.0 (https://github.com/llvm/llvm-project.git 3372303188df0f7f8ac26e7ab610cf8b0f716d42)", llvm.target_triple = "x86_64-unknown-linux-gnu"} { +module attributes {dlti.dl_spec = #dlti.dl_spec<i8 = dense<8> : vector<2xi64>, i16 = dense<16> : vector<2xi64>, i1 = dense<8> : vector<2xi64>, !llvm.ptr = dense<64> : vector<4xi64>, f80 = dense<128> : vector<2xi64>, i128 = dense<128> : vector<2xi64>, i64 = dense<64> : vector<2xi64>, !llvm.ptr<271> = dense<32> : vector<4xi64>, !llvm.ptr<272> = dense<64> : vector<4xi64>, f128 = dense<128> : vector<2xi64>, !llvm.ptr<270> = dense<32> : vector<4xi64>, f16 = dense<16> : vector<2xi64>, f64 = dense<64> : vector<2xi64>, i32 = dense<32> : vector<2xi64>, "dlti.stack_alignment" = 128 : i64, "dlti.endianness" = "little">, fir.defaultkind = "a1c4d8i4l4r4", fir.kindmap = "", gpu.container_module, llvm.data_layout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128", llvm.ident = "flang version 20.0.0 (https://github.com/llvm/llvm-project.git 3372303188df0f7f8ac26e7ab610cf8b0f716d42)", llvm.target_triple = "x86_64-unknown-linux-gnu"} { fir.global @_QMmEa00 {data_attr = #cuf.cuda<managed>} : !fir.box<!fir.heap<!fir.array<?x?x?x?x?xf64>>> { %c0 = arith.constant 0 : index %0 = fir.zero_bits !fir.heap<!fir.array<?x?x?x?x?xf64>> diff --git a/flang/test/Fir/CUDA/cuda-implicit-device-global.f90 b/flang/test/Fir/CUDA/cuda-implicit-device-global.f90 index 758c2e2..f399767 100644 --- a/flang/test/Fir/CUDA/cuda-implicit-device-global.f90 +++ b/flang/test/Fir/CUDA/cuda-implicit-device-global.f90 @@ -144,7 +144,7 @@ func.func private @_FortranAioEndIoStatement(!fir.ref<i8>) -> i32 attributes {fi // Checking that a constant fir.global that is used in device code is copied over to the device // CHECK: fir.global linkonce @_QQclX5465737420504153534544 constant : !fir.char<1,11> -// CHECK-LABEL: gpu.module @cuda_device_mod +// CHECK-LABEL: gpu.module @cuda_device_mod // CHECK: fir.global linkonce @_QQclX5465737420504153534544 constant // ----- @@ -312,10 +312,10 @@ fir.global linkonce_odr @_QM__mod1E.n.cptr constant : !fir.char<1,4> { // ----- // Variables with initialization are promoted to non constant global. -// +// // attributes(global) subroutine kernel4() // integer :: a = 4 -// end subroutine +// end subroutine func.func @_QPkernel4() attributes {cuf.proc_attr = #cuf.cuda_proc<global>} { %0 = fir.address_of(@_QFkernel4Ea) : !fir.ref<i32> diff --git a/flang/test/Fir/CUDA/cuda-shared-offset.mlir b/flang/test/Fir/CUDA/cuda-shared-offset.mlir index 9c057d0..1a39fef 100644 --- a/flang/test/Fir/CUDA/cuda-shared-offset.mlir +++ b/flang/test/Fir/CUDA/cuda-shared-offset.mlir @@ -3,9 +3,9 @@ module attributes {dlti.dl_spec = #dlti.dl_spec<#dlti.dl_entry<!llvm.ptr, dense<64> : vector<4xi64>>, #dlti.dl_entry<!llvm.ptr<271>, dense<32> : vector<4xi64>>, #dlti.dl_entry<!llvm.ptr<270>, dense<32> : vector<4xi64>>, #dlti.dl_entry<f128, dense<128> : vector<2xi64>>, #dlti.dl_entry<f64, dense<64> : vector<2xi64>>, #dlti.dl_entry<f80, dense<128> : vector<2xi64>>, #dlti.dl_entry<f16, dense<16> : vector<2xi64>>, #dlti.dl_entry<i32, dense<32> : vector<2xi64>>, #dlti.dl_entry<i16, dense<16> : vector<2xi64>>, #dlti.dl_entry<i128, dense<128> : vector<2xi64>>, #dlti.dl_entry<i8, dense<8> : vector<2xi64>>, #dlti.dl_entry<!llvm.ptr<272>, dense<64> : vector<4xi64>>, #dlti.dl_entry<i64, dense<64> : vector<2xi64>>, #dlti.dl_entry<i1, dense<8> : vector<2xi64>>, #dlti.dl_entry<"dlti.endianness", "little">, #dlti.dl_entry<"dlti.stack_alignment", 128 : i64>>, fir.defaultkind = "a1c4d8i4l4r4", fir.kindmap = "", gpu.container_module, llvm.data_layout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128", llvm.ident = "flang version 20.0.0 (https://github.com/llvm/llvm-project.git cae351f3453a0a26ec8eb2ddaf773c24a29d929e)", llvm.target_triple = "x86_64-unknown-linux-gnu"} { gpu.module @cuda_device_mod { gpu.func @_QPdynshared() kernel { - %c-1 = arith.constant -1 : index - %6 = cuf.shared_memory !fir.array<?xf32>, %c-1 : index {bindc_name = "r", uniq_name = "_QFdynsharedEr"} -> !fir.ref<!fir.array<?xf32>> - %7 = fir.shape %c-1 : (index) -> !fir.shape<1> + %0 = fir.assumed_size_extent : index + %6 = cuf.shared_memory !fir.array<?xf32>, %0 : index {bindc_name = "r", uniq_name = "_QFdynsharedEr"} -> !fir.ref<!fir.array<?xf32>> + %7 = fir.shape %0 : (index) -> !fir.shape<1> %8 = fir.declare %6(%7) {data_attr = #cuf.cuda<shared>, uniq_name = "_QFdynsharedEr"} : (!fir.ref<!fir.array<?xf32>>, !fir.shape<1>) -> !fir.ref<!fir.array<?xf32>> gpu.return } @@ -14,10 +14,10 @@ module attributes {dlti.dl_spec = #dlti.dl_spec<#dlti.dl_entry<!llvm.ptr, dense< // CHECK-LABEL: gpu.module @cuda_device_mod // CHECK: gpu.func @_QPdynshared() -// CHECK: %{{.*}} = cuf.shared_memory[%c0{{.*}} : i32] !fir.array<?xf32>, %c-1 : index {bindc_name = "r", uniq_name = "_QFdynsharedEr"} -> !fir.ref<!fir.array<?xf32>> +// CHECK: %{{.*}} = cuf.shared_memory[%c0{{.*}} : i32] !fir.array<?xf32>, %{{.*}} : index {bindc_name = "r", uniq_name = "_QFdynsharedEr"} -> !fir.ref<!fir.array<?xf32>> // CHECK: gpu.return // CHECK: } -// CHECK: fir.global external @_QPdynshared__shared_mem {alignment = 4 : i64, data_attr = #cuf.cuda<shared>} : !fir.array<0xi8> +// CHECK: fir.global external @_QPdynshared__shared_mem__ {alignment = 4 : i64, data_attr = #cuf.cuda<shared>} : !fir.array<0xi8> // ----- @@ -43,15 +43,20 @@ module attributes {dlti.dl_spec = #dlti.dl_spec<#dlti.dl_entry<!llvm.ptr, dense< // CHECK-LABEL: gpu.module @cuda_device_mod // CHECK: gpu.func @_QPshared_static() -// CHECK: cuf.shared_memory[%c0{{.*}} : i32] i32 {bindc_name = "a", uniq_name = "_QFshared_staticEa"} -> !fir.ref<i32> -// CHECK: cuf.shared_memory[%c4{{.*}} : i32] i32 {bindc_name = "b", uniq_name = "_QFshared_staticEb"} -> !fir.ref<i32> -// CHECK: cuf.shared_memory[%c8{{.*}} : i32] i32 {bindc_name = "c", uniq_name = "_QFshared_staticEc"} -> !fir.ref<i32> -// CHECK: cuf.shared_memory[%c12{{.*}} : i32] i32 {bindc_name = "d", uniq_name = "_QFshared_staticEd"} -> !fir.ref<i32> -// CHECK: cuf.shared_memory[%c16{{.*}} : i32] i64 {bindc_name = "e", uniq_name = "_QFshared_staticEe"} -> !fir.ref<i64> -// CHECK: cuf.shared_memory[%c24{{.*}} : i32] f32 {bindc_name = "r", uniq_name = "_QFshared_staticEr"} -> !fir.ref<f32> +// CHECK: cuf.shared_memory[%c0{{.*}} : i32] i32 align 4 {bindc_name = "a", isStatic, uniq_name = "_QFshared_staticEa"} -> !fir.ref<i32> +// CHECK: cuf.shared_memory[%c0{{.*}} : i32] i32 align 4 {bindc_name = "b", isStatic, uniq_name = "_QFshared_staticEb"} -> !fir.ref<i32> +// CHECK: cuf.shared_memory[%c0{{.*}} : i32] i32 align 4 {bindc_name = "c", isStatic, uniq_name = "_QFshared_staticEc"} -> !fir.ref<i32> +// CHECK: cuf.shared_memory[%c0{{.*}} : i32] i32 align 4 {bindc_name = "d", isStatic, uniq_name = "_QFshared_staticEd"} -> !fir.ref<i32> +// CHECK: cuf.shared_memory[%c0{{.*}} : i32] i64 align 8 {bindc_name = "e", isStatic, uniq_name = "_QFshared_staticEe"} -> !fir.ref<i64> +// CHECK: cuf.shared_memory[%c0{{.*}} : i32] f32 align 4 {bindc_name = "r", isStatic, uniq_name = "_QFshared_staticEr"} -> !fir.ref<f32> // CHECK: gpu.return // CHECK: } -// CHECK: fir.global internal @_QPshared_static__shared_mem(dense<0> : vector<28xi8>) {alignment = 8 : i64, data_attr = #cuf.cuda<shared>} : !fir.array<28xi8> +// CHECK: fir.global internal @_QPshared_static__shared_mem__a(dense<0> : vector<4xi8>) {alignment = 4 : i64, data_attr = #cuf.cuda<shared>} : !fir.array<4xi8> +// CHECK: fir.global internal @_QPshared_static__shared_mem__b(dense<0> : vector<4xi8>) {alignment = 4 : i64, data_attr = #cuf.cuda<shared>} : !fir.array<4xi8> +// CHECK: fir.global internal @_QPshared_static__shared_mem__c(dense<0> : vector<4xi8>) {alignment = 4 : i64, data_attr = #cuf.cuda<shared>} : !fir.array<4xi8> +// CHECK: fir.global internal @_QPshared_static__shared_mem__d(dense<0> : vector<4xi8>) {alignment = 4 : i64, data_attr = #cuf.cuda<shared>} : !fir.array<4xi8> +// CHECK: fir.global internal @_QPshared_static__shared_mem__e(dense<0> : vector<8xi8>) {alignment = 8 : i64, data_attr = #cuf.cuda<shared>} : !fir.array<8xi8> +// CHECK: fir.global internal @_QPshared_static__shared_mem__r(dense<0> : vector<4xi8>) {alignment = 4 : i64, data_attr = #cuf.cuda<shared>} : !fir.array<4xi8> // CHECK: } // CHECK: } @@ -127,16 +132,16 @@ module attributes {dlti.dl_spec = #dlti.dl_spec<#dlti.dl_entry<!llvm.ptr, dense< gpu.module @cuda_device_mod { gpu.func @_QMmtestsPtestany(%arg0: !fir.ref<!fir.array<?xf32>> {cuf.data_attr = #cuf.cuda<device>, fir.bindc_name = "a"}) attributes {cuf.proc_attr = #cuf.cuda_proc<global>} { %0 = fir.dummy_scope : !fir.dscope - %c-1 = arith.constant -1 : index - %1 = fir.shape %c-1 : (index) -> !fir.shape<1> + %a0 = fir.assumed_size_extent : index + %1 = fir.shape %a0 : (index) -> !fir.shape<1> %2:2 = hlfir.declare %arg0(%1) dummy_scope %0 {data_attr = #cuf.cuda<device>, uniq_name = "_QMmtestsFtestanyEa"} : (!fir.ref<!fir.array<?xf32>>, !fir.shape<1>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.ref<!fir.array<?xf32>>) %3 = fir.address_of(@_QM__fortran_builtinsE__builtin_blockdim) : !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_dim3{x:i32,y:i32,z:i32}>> %4:2 = hlfir.declare %3 {uniq_name = "_QM__fortran_builtinsE__builtin_blockdim"} : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_dim3{x:i32,y:i32,z:i32}>>) -> (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_dim3{x:i32,y:i32,z:i32}>>, !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_dim3{x:i32,y:i32,z:i32}>>) %5 = fir.address_of(@_QM__fortran_builtinsE__builtin_blockidx) : !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_dim3{x:i32,y:i32,z:i32}>> %6:2 = hlfir.declare %5 {uniq_name = "_QM__fortran_builtinsE__builtin_blockidx"} : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_dim3{x:i32,y:i32,z:i32}>>) -> (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_dim3{x:i32,y:i32,z:i32}>>, !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_dim3{x:i32,y:i32,z:i32}>>) - %c-1_0 = arith.constant -1 : index - %7 = cuf.shared_memory !fir.array<?xf64>, %c-1_0 : index {bindc_name = "dmasks", uniq_name = "_QMmtestsFtestanyEdmasks"} -> !fir.ref<!fir.array<?xf64>> - %8 = fir.shape %c-1_0 : (index) -> !fir.shape<1> + %a2 = fir.assumed_size_extent : index + %7 = cuf.shared_memory !fir.array<?xf64>, %a2 : index {bindc_name = "dmasks", uniq_name = "_QMmtestsFtestanyEdmasks"} -> !fir.ref<!fir.array<?xf64>> + %8 = fir.shape %a2 : (index) -> !fir.shape<1> %9:2 = hlfir.declare %7(%8) {data_attr = #cuf.cuda<shared>, uniq_name = "_QMmtestsFtestanyEdmasks"} : (!fir.ref<!fir.array<?xf64>>, !fir.shape<1>) -> (!fir.box<!fir.array<?xf64>>, !fir.ref<!fir.array<?xf64>>) %10 = fir.address_of(@_QM__fortran_builtinsE__builtin_griddim) : !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_dim3{x:i32,y:i32,z:i32}>> %11:2 = hlfir.declare %10 {uniq_name = "_QM__fortran_builtinsE__builtin_griddim"} : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_dim3{x:i32,y:i32,z:i32}>>) -> (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_dim3{x:i32,y:i32,z:i32}>>, !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_dim3{x:i32,y:i32,z:i32}>>) @@ -146,9 +151,9 @@ module attributes {dlti.dl_spec = #dlti.dl_spec<#dlti.dl_entry<!llvm.ptr, dense< %15:2 = hlfir.declare %14 {uniq_name = "_QMmtestsFtestanyEiam"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) %16 = fir.alloca i32 {bindc_name = "j", uniq_name = "_QMmtestsFtestanyEj"} %17:2 = hlfir.declare %16 {uniq_name = "_QMmtestsFtestanyEj"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) - %c-1_1 = arith.constant -1 : index - %18 = cuf.shared_memory !fir.array<?xf32>, %c-1_1 : index {bindc_name = "smasks", uniq_name = "_QMmtestsFtestanyEsmasks"} -> !fir.ref<!fir.array<?xf32>> - %19 = fir.shape %c-1_1 : (index) -> !fir.shape<1> + %a3 = fir.assumed_size_extent : index + %18 = cuf.shared_memory !fir.array<?xf32>, %a3 : index {bindc_name = "smasks", uniq_name = "_QMmtestsFtestanyEsmasks"} -> !fir.ref<!fir.array<?xf32>> + %19 = fir.shape %a3 : (index) -> !fir.shape<1> %20:2 = hlfir.declare %18(%19) {data_attr = #cuf.cuda<shared>, uniq_name = "_QMmtestsFtestanyEsmasks"} : (!fir.ref<!fir.array<?xf32>>, !fir.shape<1>) -> (!fir.box<!fir.array<?xf32>>, !fir.ref<!fir.array<?xf32>>) gpu.return } @@ -156,7 +161,7 @@ module attributes {dlti.dl_spec = #dlti.dl_spec<#dlti.dl_entry<!llvm.ptr, dense< } // CHECK-LABEL: gpu.func @_QMmtestsPtestany -// CHECK: %{{.*}} = cuf.shared_memory[%c0{{.*}} : i32] !fir.array<?xf64>, %c-1{{.*}} : index {bindc_name = "dmasks", uniq_name = "_QMmtestsFtestanyEdmasks"} -> !fir.ref<!fir.array<?xf64>> -// CHECK: %{{.*}} = cuf.shared_memory[%c0{{.*}} : i32] !fir.array<?xf32>, %c-1{{.*}} : index {bindc_name = "smasks", uniq_name = "_QMmtestsFtestanyEsmasks"} -> !fir.ref<!fir.array<?xf32>> +// CHECK: %{{.*}} = cuf.shared_memory[%c0{{.*}} : i32] !fir.array<?xf64>, %{{.*}} : index {bindc_name = "dmasks", uniq_name = "_QMmtestsFtestanyEdmasks"} -> !fir.ref<!fir.array<?xf64>> +// CHECK: %{{.*}} = cuf.shared_memory[%c0{{.*}} : i32] !fir.array<?xf32>, %{{.*}} : index {bindc_name = "smasks", uniq_name = "_QMmtestsFtestanyEsmasks"} -> !fir.ref<!fir.array<?xf32>> -// CHECK: fir.global external @_QMmtestsPtestany__shared_mem {alignment = 8 : i64, data_attr = #cuf.cuda<shared>} : !fir.array<0xi8> +// CHECK: fir.global external @_QMmtestsPtestany__shared_mem__ {alignment = 8 : i64, data_attr = #cuf.cuda<shared>} : !fir.array<0xi8> diff --git a/flang/test/Fir/CUDA/cuda-shared-to-llvm.mlir b/flang/test/Fir/CUDA/cuda-shared-to-llvm.mlir index 26479d1..6937061 100644 --- a/flang/test/Fir/CUDA/cuda-shared-to-llvm.mlir +++ b/flang/test/Fir/CUDA/cuda-shared-to-llvm.mlir @@ -9,14 +9,14 @@ module attributes {dlti.dl_spec = #dlti.dl_spec<#dlti.dl_entry<!llvm.ptr, dense< %1 = cuf.shared_memory [%c4 : i32] i32 {bindc_name = "b", uniq_name = "_QFshared_staticEb"} -> !fir.ref<i32> llvm.return } - llvm.mlir.global common @_QPshared_static__shared_mem(dense<0> : vector<28xi8>) {addr_space = 3 : i32, alignment = 8 : i64} : !llvm.array<28 x i8> + llvm.mlir.global common @_QPshared_static__shared_mem__(dense<0> : vector<28xi8>) {addr_space = 3 : i32, alignment = 8 : i64} : !llvm.array<28 x i8> } } // CHECK-LABEL: llvm.func @_QPshared_static() -// CHECK: %[[ADDR0:.*]] = llvm.mlir.addressof @_QPshared_static__shared_mem : !llvm.ptr<3> +// CHECK: %[[ADDR0:.*]] = llvm.mlir.addressof @_QPshared_static__shared_mem__ : !llvm.ptr<3> // CHECK: %[[ADDRCAST0:.*]] = llvm.addrspacecast %[[ADDR0]] : !llvm.ptr<3> to !llvm.ptr // CHECK: %[[A:.*]] = llvm.getelementptr %[[ADDRCAST0]][%c0{{.*}}] : (!llvm.ptr, i32) -> !llvm.ptr, i8 -// CHECK: %[[ADDR1:.*]] = llvm.mlir.addressof @_QPshared_static__shared_mem : !llvm.ptr<3> +// CHECK: %[[ADDR1:.*]] = llvm.mlir.addressof @_QPshared_static__shared_mem__ : !llvm.ptr<3> // CHECK: %[[ADDRCAST1:.*]] = llvm.addrspacecast %[[ADDR1]] : !llvm.ptr<3> to !llvm.ptr // CHECK: %[[B:.*]] = llvm.getelementptr %[[ADDRCAST1]][%c4{{.*}}] : (!llvm.ptr, i32) -> !llvm.ptr, i8 diff --git a/flang/test/Fir/FirToSCF/do-loop.fir b/flang/test/Fir/FirToSCF/do-loop.fir index 812497c..8862a4c 100644 --- a/flang/test/Fir/FirToSCF/do-loop.fir +++ b/flang/test/Fir/FirToSCF/do-loop.fir @@ -1,4 +1,5 @@ -// RUN: fir-opt %s --fir-to-scf | FileCheck %s +// RUN: fir-opt %s --fir-to-scf --split-input-file | FileCheck %s --check-prefixes=CHECK,NO-PARALLEL +// RUN: fir-opt %s --fir-to-scf='parallel-unordered' --split-input-file | FileCheck %s --check-prefixes=CHECK,PARALLEL // CHECK-LABEL: func.func @simple_loop( // CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.array<100xi32>>) { @@ -31,6 +32,8 @@ func.func @simple_loop(%arg0: !fir.ref<!fir.array<100xi32>>) { return } +// ----- + // CHECK-LABEL: func.func @loop_with_negtive_step( // CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.array<100xi32>>) { // CHECK: %[[VAL_0:.*]] = arith.constant 100 : index @@ -64,6 +67,8 @@ func.func @loop_with_negtive_step(%arg0: !fir.ref<!fir.array<100xi32>>) { return } +// ----- + // CHECK-LABEL: func.func @loop_with_results( // CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.array<100xi32>>, // CHECK-SAME: %[[ARG1:.*]]: !fir.ref<i32>) { @@ -102,6 +107,8 @@ func.func @loop_with_results(%arg0: !fir.ref<!fir.array<100xi32>>, %arg1: !fir.r return } +// ----- + // CHECK-LABEL: func.func @loop_with_final_value( // CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.array<100xi32>>, // CHECK-SAME: %[[ARG1:.*]]: !fir.ref<i32>) { @@ -146,6 +153,45 @@ func.func @loop_with_final_value(%arg0: !fir.ref<!fir.array<100xi32>>, %arg1: !f return } +// ----- + +// CHECK-LABEL: func.func @loop_with_unordered_attr( +// CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.array<100xi32>>) { +// CHECK: %[[CONSTANT_0:.*]] = arith.constant 1 : index +// CHECK: %[[CONSTANT_1:.*]] = arith.constant 100 : index +// CHECK: %[[SHAPE_0:.*]] = fir.shape %[[CONSTANT_1]] : (index) -> !fir.shape<1> +// CHECK: %[[CONSTANT_2:.*]] = arith.constant 1 : i32 +// CHECK: %[[SUBI_0:.*]] = arith.subi %[[CONSTANT_1]], %[[CONSTANT_0]] : index +// CHECK: %[[ADDI_0:.*]] = arith.addi %[[SUBI_0]], %[[CONSTANT_0]] : index +// CHECK: %[[DIVSI_0:.*]] = arith.divsi %[[ADDI_0]], %[[CONSTANT_0]] : index +// CHECK: %[[CONSTANT_3:.*]] = arith.constant 0 : index +// CHECK: %[[CONSTANT_4:.*]] = arith.constant 1 : index +// PARALLEL: scf.parallel (%[[VAL_0:.*]]) = (%[[CONSTANT_3]]) to (%[[DIVSI_0]]) step (%[[CONSTANT_4]]) { +// NO-PARALLEL: scf.for %[[VAL_0:.*]] = %[[CONSTANT_3]] to %[[DIVSI_0]] step %[[CONSTANT_4]] { +// CHECK: %[[MULI_0:.*]] = arith.muli %[[VAL_0]], %[[CONSTANT_0]] : index +// CHECK: %[[ADDI_1:.*]] = arith.addi %[[CONSTANT_0]], %[[MULI_0]] : index +// CHECK: %[[ARRAY_COOR_0:.*]] = fir.array_coor %[[ARG0]](%[[SHAPE_0]]) %[[ADDI_1]] : (!fir.ref<!fir.array<100xi32>>, !fir.shape<1>, index) -> !fir.ref<i32> +// CHECK: fir.store %[[CONSTANT_2]] to %[[ARRAY_COOR_0]] : !fir.ref<i32> +// PARALLEL: scf.reduce +// CHECK: } +// CHECK: return +// CHECK: } +func.func @loop_with_unordered_attr(%arg0: !fir.ref<!fir.array<100xi32>>) { + %c1 = arith.constant 1 : index + %c100 = arith.constant 100 : index + %0 = fir.shape %c100 : (index) -> !fir.shape<1> + %c1_i32 = arith.constant 1 : i32 + fir.do_loop %arg1 = %c1 to %c100 step %c1 unordered { + %1 = fir.array_coor %arg0(%0) %arg1 : (!fir.ref<!fir.array<100xi32>>, !fir.shape<1>, index) -> !fir.ref<i32> + fir.store %c1_i32 to %1 : !fir.ref<i32> + } + return +} + +// ----- + +// CHECK: #[[$ATTR_0:.+]] = #llvm.loop_vectorize<disable = false> +// CHECK: #[[$ATTR_1:.+]] = #llvm.loop_annotation<vectorize = #[[$ATTR_0]]> // CHECK-LABEL: func.func @loop_with_attribute( // CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.array<100xi32>>, // CHECK-SAME: %[[ARG1:.*]]: !fir.ref<i32>) { @@ -167,16 +213,19 @@ func.func @loop_with_final_value(%arg0: !fir.ref<!fir.array<100xi32>>, %arg1: !f // CHECK: %[[VAL_15:.*]] = fir.load %[[VAL_3]] : !fir.ref<i32> // CHECK: %[[VAL_16:.*]] = arith.addi %[[VAL_15]], %[[VAL_14]] : i32 // CHECK: fir.store %[[VAL_16]] to %[[VAL_3]] : !fir.ref<i32> -// CHECK: } {operandSegmentSizes = array<i32: 1, 1, 1, 1, 0>, reduceAttrs = [#fir.reduce_attr<add>]} +// CHECK: } {loop_annotation = #[[$ATTR_1]]} // CHECK: return // CHECK: } + +#loop_vectorize = #llvm.loop_vectorize<disable = false> +#loop_annotation = #llvm.loop_annotation<vectorize = #loop_vectorize> func.func @loop_with_attribute(%arg0: !fir.ref<!fir.array<100xi32>>, %arg1: !fir.ref<i32>) { %c1 = arith.constant 1 : index %c0_i32 = arith.constant 0 : i32 %c100 = arith.constant 100 : index %0 = fir.alloca i32 %1 = fir.shape %c100 : (index) -> !fir.shape<1> - fir.do_loop %arg2 = %c1 to %c100 step %c1 reduce(#fir.reduce_attr<add> -> %0 : !fir.ref<i32>) { + fir.do_loop %arg2 = %c1 to %c100 step %c1 attributes {loopAnnotation = #loop_annotation} { %2 = fir.array_coor %arg0(%1) %arg2 : (!fir.ref<!fir.array<100xi32>>, !fir.shape<1>, index) -> !fir.ref<i32> %3 = fir.load %2 : !fir.ref<i32> %4 = fir.load %0 : !fir.ref<i32> @@ -187,6 +236,8 @@ func.func @loop_with_attribute(%arg0: !fir.ref<!fir.array<100xi32>>, %arg1: !fir return } +// ----- + // CHECK-LABEL: func.func @nested_loop( // CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.array<100x100xi32>>) { // CHECK: %[[VAL_0:.*]] = arith.constant 1 : index diff --git a/flang/test/Fir/FirToSCF/iter-while.fir b/flang/test/Fir/FirToSCF/iter-while.fir index 0de7aab..d980fa6 100644 --- a/flang/test/Fir/FirToSCF/iter-while.fir +++ b/flang/test/Fir/FirToSCF/iter-while.fir @@ -1,25 +1,32 @@ -// RUN: fir-opt %s --fir-to-scf | FileCheck %s +// RUN: fir-opt %s --fir-to-scf --allow-unregistered-dialect | FileCheck %s // CHECK-LABEL: func.func @test_simple_iterate_while_1() -> (index, i1, i16, i32) { -// CHECK: %[[VAL_0:.*]] = arith.constant 11 : index -// CHECK: %[[VAL_1:.*]] = arith.constant 22 : index -// CHECK: %[[VAL_2:.*]] = arith.constant 2 : index -// CHECK: %[[VAL_3:.*]] = arith.constant true -// CHECK: %[[VAL_4:.*]] = arith.constant 123 : i16 -// CHECK: %[[VAL_5:.*]] = arith.constant 456 : i32 -// CHECK: %[[VAL_6:.*]]:4 = scf.while (%[[VAL_7:.*]] = %[[VAL_0]], %[[VAL_8:.*]] = %[[VAL_3]], %[[VAL_9:.*]] = %[[VAL_4]], %[[VAL_10:.*]] = %[[VAL_5]]) : (index, i1, i16, i32) -> (index, i1, i16, i32) { -// CHECK: %[[VAL_11:.*]] = arith.cmpi sle, %[[VAL_7]], %[[VAL_1]] : index -// CHECK: %[[VAL_12:.*]] = arith.andi %[[VAL_11]], %[[VAL_8]] : i1 -// CHECK: scf.condition(%[[VAL_12]]) %[[VAL_7]], %[[VAL_8]], %[[VAL_9]], %[[VAL_10]] : index, i1, i16, i32 +// CHECK: %[[CONSTANT_0:.*]] = arith.constant 11 : index +// CHECK: %[[CONSTANT_1:.*]] = arith.constant 22 : index +// CHECK: %[[CONSTANT_2:.*]] = arith.constant 2 : index +// CHECK: %[[CONSTANT_3:.*]] = arith.constant true +// CHECK: %[[CONSTANT_4:.*]] = arith.constant 123 : i16 +// CHECK: %[[CONSTANT_5:.*]] = arith.constant 456 : i32 +// CHECK: %[[WHILE_0:.*]]:4 = scf.while (%[[VAL_0:.*]] = %[[CONSTANT_0]], %[[VAL_1:.*]] = %[[CONSTANT_3]], %[[VAL_2:.*]] = %[[CONSTANT_4]], %[[VAL_3:.*]] = %[[CONSTANT_5]]) : (index, i1, i16, i32) -> (index, i1, i16, i32) { +// CHECK: %[[CONSTANT_6:.*]] = arith.constant 0 : index +// CHECK: %[[CMPI_0:.*]] = arith.cmpi slt, %[[CONSTANT_6]], %[[CONSTANT_2]] : index +// CHECK: %[[CMPI_1:.*]] = arith.cmpi sle, %[[VAL_0]], %[[CONSTANT_1]] : index +// CHECK: %[[CMPI_2:.*]] = arith.cmpi slt, %[[CONSTANT_2]], %[[CONSTANT_6]] : index +// CHECK: %[[CMPI_3:.*]] = arith.cmpi sge, %[[VAL_0]], %[[CONSTANT_1]] : index +// CHECK: %[[ANDI_0:.*]] = arith.andi %[[CMPI_0]], %[[CMPI_1]] : i1 +// CHECK: %[[ANDI_1:.*]] = arith.andi %[[CMPI_2]], %[[CMPI_3]] : i1 +// CHECK: %[[ORI_0:.*]] = arith.ori %[[ANDI_0]], %[[ANDI_1]] : i1 +// CHECK: %[[ANDI_2:.*]] = arith.andi %[[VAL_1]], %[[ORI_0]] : i1 +// CHECK: scf.condition(%[[ANDI_2]]) %[[VAL_0]], %[[VAL_1]], %[[VAL_2]], %[[VAL_3]] : index, i1, i16, i32 // CHECK: } do { -// CHECK: ^bb0(%[[VAL_13:.*]]: index, %[[VAL_14:.*]]: i1, %[[VAL_15:.*]]: i16, %[[VAL_16:.*]]: i32): -// CHECK: %[[VAL_17:.*]] = arith.addi %[[VAL_13]], %[[VAL_2]] : index -// CHECK: %[[VAL_18:.*]] = arith.constant true -// CHECK: %[[VAL_19:.*]] = arith.constant 22 : i16 -// CHECK: %[[VAL_20:.*]] = arith.constant 33 : i32 -// CHECK: scf.yield %[[VAL_17]], %[[VAL_18]], %[[VAL_19]], %[[VAL_20]] : index, i1, i16, i32 -// CHECK: } -// CHECK: return %[[VAL_21:.*]]#0, %[[VAL_21]]#1, %[[VAL_21]]#2, %[[VAL_21]]#3 : index, i1, i16, i32 +// CHECK: ^bb0(%[[VAL_4:.*]]: index, %[[VAL_5:.*]]: i1, %[[VAL_6:.*]]: i16, %[[VAL_7:.*]]: i32): +// CHECK: %[[ADDI_0:.*]] = arith.addi %[[VAL_4]], %[[CONSTANT_2]] : index +// CHECK: %[[CONSTANT_7:.*]] = arith.constant true +// CHECK: %[[CONSTANT_8:.*]] = arith.constant 22 : i16 +// CHECK: %[[CONSTANT_9:.*]] = arith.constant 33 : i32 +// CHECK: scf.yield %[[ADDI_0]], %[[CONSTANT_7]], %[[CONSTANT_8]], %[[CONSTANT_9]] : index, i1, i16, i32 +// CHECK: } attributes {finalValue} +// CHECK: return %[[VAL_8:.*]]#0, %[[VAL_8]]#1, %[[VAL_8]]#2, %[[VAL_8]]#3 : index, i1, i16, i32 // CHECK: } func.func @test_simple_iterate_while_1() -> (index, i1, i16, i32) { %lo = arith.constant 11 : index @@ -41,19 +48,26 @@ func.func @test_simple_iterate_while_1() -> (index, i1, i16, i32) { // CHECK-LABEL: func.func @test_simple_iterate_while_2( // CHECK-SAME: %[[ARG0:.*]]: index, %[[ARG1:.*]]: index, %[[ARG2:.*]]: i1, %[[ARG3:.*]]: i32) -> (index, i1, i32) { -// CHECK: %[[VAL_0:.*]] = arith.constant 1 : index -// CHECK: %[[VAL_1:.*]]:3 = scf.while (%[[VAL_2:.*]] = %[[ARG0]], %[[VAL_3:.*]] = %[[ARG2]], %[[VAL_4:.*]] = %[[ARG3]]) : (index, i1, i32) -> (index, i1, i32) { -// CHECK: %[[VAL_5:.*]] = arith.cmpi sle, %[[VAL_2]], %[[ARG1]] : index -// CHECK: %[[VAL_6:.*]] = arith.andi %[[VAL_5]], %[[VAL_3]] : i1 -// CHECK: scf.condition(%[[VAL_6]]) %[[VAL_2]], %[[VAL_3]], %[[VAL_4]] : index, i1, i32 +// CHECK: %[[CONSTANT_0:.*]] = arith.constant 1 : index +// CHECK: %[[WHILE_0:.*]]:3 = scf.while (%[[VAL_0:.*]] = %[[ARG0]], %[[VAL_1:.*]] = %[[ARG2]], %[[VAL_2:.*]] = %[[ARG3]]) : (index, i1, i32) -> (index, i1, i32) { +// CHECK: %[[CONSTANT_1:.*]] = arith.constant 0 : index +// CHECK: %[[CMPI_0:.*]] = arith.cmpi slt, %[[CONSTANT_1]], %[[CONSTANT_0]] : index +// CHECK: %[[CMPI_1:.*]] = arith.cmpi sle, %[[VAL_0]], %[[ARG1]] : index +// CHECK: %[[CMPI_2:.*]] = arith.cmpi slt, %[[CONSTANT_0]], %[[CONSTANT_1]] : index +// CHECK: %[[CMPI_3:.*]] = arith.cmpi sge, %[[VAL_0]], %[[ARG1]] : index +// CHECK: %[[ANDI_0:.*]] = arith.andi %[[CMPI_0]], %[[CMPI_1]] : i1 +// CHECK: %[[ANDI_1:.*]] = arith.andi %[[CMPI_2]], %[[CMPI_3]] : i1 +// CHECK: %[[ORI_0:.*]] = arith.ori %[[ANDI_0]], %[[ANDI_1]] : i1 +// CHECK: %[[ANDI_2:.*]] = arith.andi %[[VAL_1]], %[[ORI_0]] : i1 +// CHECK: scf.condition(%[[ANDI_2]]) %[[VAL_0]], %[[VAL_1]], %[[VAL_2]] : index, i1, i32 // CHECK: } do { -// CHECK: ^bb0(%[[VAL_7:.*]]: index, %[[VAL_8:.*]]: i1, %[[VAL_9:.*]]: i32): -// CHECK: %[[VAL_10:.*]] = arith.addi %[[VAL_7]], %[[VAL_0]] : index -// CHECK: %[[VAL_11:.*]] = arith.constant 123 : i32 -// CHECK: %[[VAL_12:.*]] = arith.constant true -// CHECK: scf.yield %[[VAL_10]], %[[VAL_12]], %[[VAL_11]] : index, i1, i32 -// CHECK: } -// CHECK: return %[[VAL_13:.*]]#0, %[[VAL_13]]#1, %[[VAL_13]]#2 : index, i1, i32 +// CHECK: ^bb0(%[[VAL_3:.*]]: index, %[[VAL_4:.*]]: i1, %[[VAL_5:.*]]: i32): +// CHECK: %[[ADDI_0:.*]] = arith.addi %[[VAL_3]], %[[CONSTANT_0]] : index +// CHECK: %[[CONSTANT_2:.*]] = arith.constant 123 : i32 +// CHECK: %[[CONSTANT_3:.*]] = arith.constant true +// CHECK: scf.yield %[[ADDI_0]], %[[CONSTANT_3]], %[[CONSTANT_2]] : index, i1, i32 +// CHECK: } attributes {finalValue} +// CHECK: return %[[VAL_6:.*]]#0, %[[VAL_6]]#1, %[[VAL_6]]#2 : index, i1, i32 // CHECK: } func.func @test_simple_iterate_while_2(%start: index, %stop: index, %cond: i1, %val: i32) -> (index, i1, i32) { %step = arith.constant 1 : index @@ -67,22 +81,97 @@ func.func @test_simple_iterate_while_2(%start: index, %stop: index, %cond: i1, % return %res#0, %res#1, %res#2 : index, i1, i32 } +// CHECK-LABEL: func.func @loop_with_negtive_step( +// CHECK-SAME: %[[ARG0:.*]]: index, +// CHECK-SAME: %[[ARG1:.*]]: index) -> i1 { +// CHECK: %[[CONSTANT_0:.*]] = arith.constant -1 : index +// CHECK: %[[CONSTANT_1:.*]] = arith.constant true +// CHECK: %[[WHILE_0:.*]]:2 = scf.while (%[[VAL_0:.*]] = %[[ARG0]], %[[VAL_1:.*]] = %[[CONSTANT_1]]) : (index, i1) -> (index, i1) { +// CHECK: %[[CONSTANT_2:.*]] = arith.constant 0 : index +// CHECK: %[[CMPI_0:.*]] = arith.cmpi slt, %[[CONSTANT_2]], %[[CONSTANT_0]] : index +// CHECK: %[[CMPI_1:.*]] = arith.cmpi sle, %[[VAL_0]], %[[ARG1]] : index +// CHECK: %[[CMPI_2:.*]] = arith.cmpi slt, %[[CONSTANT_0]], %[[CONSTANT_2]] : index +// CHECK: %[[CMPI_3:.*]] = arith.cmpi sge, %[[VAL_0]], %[[ARG1]] : index +// CHECK: %[[ANDI_0:.*]] = arith.andi %[[CMPI_0]], %[[CMPI_1]] : i1 +// CHECK: %[[ANDI_1:.*]] = arith.andi %[[CMPI_2]], %[[CMPI_3]] : i1 +// CHECK: %[[ORI_0:.*]] = arith.ori %[[ANDI_0]], %[[ANDI_1]] : i1 +// CHECK: %[[ANDI_2:.*]] = arith.andi %[[VAL_1]], %[[ORI_0]] : i1 +// CHECK: scf.condition(%[[ANDI_2]]) %[[VAL_0]], %[[VAL_1]] : index, i1 +// CHECK: } do { +// CHECK: ^bb0(%[[VAL_2:.*]]: index, %[[VAL_3:.*]]: i1): +// CHECK: %[[ADDI_0:.*]] = arith.addi %[[VAL_2]], %[[CONSTANT_0]] : index +// CHECK: %[[VAL_4:.*]] = "test.get_some_value"() : () -> i1 +// CHECK: scf.yield %[[ADDI_0]], %[[VAL_4]] : index, i1 +// CHECK: } attributes {finalValue} +// CHECK: return %[[VAL_5:.*]]#1 : i1 +// CHECK: } +func.func @loop_with_negtive_step(%lo : index, %up : index) -> i1 { + %c-1 = arith.constant -1 : index + %ok1 = arith.constant true + %res:2 = fir.iterate_while (%i = %lo to %up step %c-1) and (%j = %ok1) -> (index, i1) { + %ok = "test.get_some_value"() : () -> i1 + fir.result %i, %ok : index, i1 + } + return %res#1 : i1 +} + +// CHECK-LABEL: func.func @loop_with_zero_step( +// CHECK-SAME: %[[ARG0:.*]]: index, +// CHECK-SAME: %[[ARG1:.*]]: index) -> i1 { +// CHECK: %[[CONSTANT_0:.*]] = arith.constant 0 : index +// CHECK: %[[CONSTANT_1:.*]] = arith.constant true +// CHECK: %[[WHILE_0:.*]]:2 = scf.while (%[[VAL_0:.*]] = %[[ARG0]], %[[VAL_1:.*]] = %[[CONSTANT_1]]) : (index, i1) -> (index, i1) { +// CHECK: %[[CONSTANT_2:.*]] = arith.constant 0 : index +// CHECK: %[[CMPI_0:.*]] = arith.cmpi slt, %[[CONSTANT_2]], %[[CONSTANT_0]] : index +// CHECK: %[[CMPI_1:.*]] = arith.cmpi sle, %[[VAL_0]], %[[ARG1]] : index +// CHECK: %[[CMPI_2:.*]] = arith.cmpi slt, %[[CONSTANT_0]], %[[CONSTANT_2]] : index +// CHECK: %[[CMPI_3:.*]] = arith.cmpi sge, %[[VAL_0]], %[[ARG1]] : index +// CHECK: %[[ANDI_0:.*]] = arith.andi %[[CMPI_0]], %[[CMPI_1]] : i1 +// CHECK: %[[ANDI_1:.*]] = arith.andi %[[CMPI_2]], %[[CMPI_3]] : i1 +// CHECK: %[[ORI_0:.*]] = arith.ori %[[ANDI_0]], %[[ANDI_1]] : i1 +// CHECK: %[[ANDI_2:.*]] = arith.andi %[[VAL_1]], %[[ORI_0]] : i1 +// CHECK: scf.condition(%[[ANDI_2]]) %[[VAL_0]], %[[VAL_1]] : index, i1 +// CHECK: } do { +// CHECK: ^bb0(%[[VAL_2:.*]]: index, %[[VAL_3:.*]]: i1): +// CHECK: %[[ADDI_0:.*]] = arith.addi %[[VAL_2]], %[[CONSTANT_0]] : index +// CHECK: %[[VAL_4:.*]] = "test.get_some_value"() : () -> i1 +// CHECK: scf.yield %[[ADDI_0]], %[[VAL_4]] : index, i1 +// CHECK: } attributes {finalValue} +// CHECK: return %[[VAL_5:.*]]#1 : i1 +// CHECK: } +func.func @loop_with_zero_step(%lo : index, %up : index) -> i1 { + %c0 = arith.constant 0 : index + %ok1 = arith.constant true + %res:2 = fir.iterate_while (%i = %lo to %up step %c0) and (%j = %ok1) -> (index, i1) { + %ok = "test.get_some_value"() : () -> i1 + fir.result %i, %ok : index, i1 + } + return %res#1 : i1 +} + // CHECK-LABEL: func.func @test_zero_iterations() -> (index, i1, i8) { -// CHECK: %[[VAL_0:.*]] = arith.constant 10 : index -// CHECK: %[[VAL_1:.*]] = arith.constant 5 : index -// CHECK: %[[VAL_2:.*]] = arith.constant 1 : index -// CHECK: %[[VAL_3:.*]] = arith.constant true -// CHECK: %[[VAL_4:.*]] = arith.constant 42 : i8 -// CHECK: %[[VAL_5:.*]]:3 = scf.while (%[[VAL_6:.*]] = %[[VAL_0]], %[[VAL_7:.*]] = %[[VAL_3]], %[[VAL_8:.*]] = %[[VAL_4]]) : (index, i1, i8) -> (index, i1, i8) { -// CHECK: %[[VAL_9:.*]] = arith.cmpi sle, %[[VAL_6]], %[[VAL_1]] : index -// CHECK: %[[VAL_10:.*]] = arith.andi %[[VAL_9]], %[[VAL_7]] : i1 -// CHECK: scf.condition(%[[VAL_10]]) %[[VAL_6]], %[[VAL_7]], %[[VAL_8]] : index, i1, i8 +// CHECK: %[[CONSTANT_0:.*]] = arith.constant 10 : index +// CHECK: %[[CONSTANT_1:.*]] = arith.constant 5 : index +// CHECK: %[[CONSTANT_2:.*]] = arith.constant 1 : index +// CHECK: %[[CONSTANT_3:.*]] = arith.constant true +// CHECK: %[[CONSTANT_4:.*]] = arith.constant 42 : i8 +// CHECK: %[[WHILE_0:.*]]:3 = scf.while (%[[VAL_0:.*]] = %[[CONSTANT_0]], %[[VAL_1:.*]] = %[[CONSTANT_3]], %[[VAL_2:.*]] = %[[CONSTANT_4]]) : (index, i1, i8) -> (index, i1, i8) { +// CHECK: %[[CONSTANT_5:.*]] = arith.constant 0 : index +// CHECK: %[[CMPI_0:.*]] = arith.cmpi slt, %[[CONSTANT_5]], %[[CONSTANT_2]] : index +// CHECK: %[[CMPI_1:.*]] = arith.cmpi sle, %[[VAL_0]], %[[CONSTANT_1]] : index +// CHECK: %[[CMPI_2:.*]] = arith.cmpi slt, %[[CONSTANT_2]], %[[CONSTANT_5]] : index +// CHECK: %[[CMPI_3:.*]] = arith.cmpi sge, %[[VAL_0]], %[[CONSTANT_1]] : index +// CHECK: %[[ANDI_0:.*]] = arith.andi %[[CMPI_0]], %[[CMPI_1]] : i1 +// CHECK: %[[ANDI_1:.*]] = arith.andi %[[CMPI_2]], %[[CMPI_3]] : i1 +// CHECK: %[[ORI_0:.*]] = arith.ori %[[ANDI_0]], %[[ANDI_1]] : i1 +// CHECK: %[[ANDI_2:.*]] = arith.andi %[[VAL_1]], %[[ORI_0]] : i1 +// CHECK: scf.condition(%[[ANDI_2]]) %[[VAL_0]], %[[VAL_1]], %[[VAL_2]] : index, i1, i8 // CHECK: } do { -// CHECK: ^bb0(%[[VAL_11:.*]]: index, %[[VAL_12:.*]]: i1, %[[VAL_13:.*]]: i8): -// CHECK: %[[VAL_14:.*]] = arith.addi %[[VAL_11]], %[[VAL_2]] : index -// CHECK: scf.yield %[[VAL_14]], %[[VAL_12]], %[[VAL_13]] : index, i1, i8 -// CHECK: } -// CHECK: return %[[VAL_15:.*]]#0, %[[VAL_15]]#1, %[[VAL_15]]#2 : index, i1, i8 +// CHECK: ^bb0(%[[VAL_3:.*]]: index, %[[VAL_4:.*]]: i1, %[[VAL_5:.*]]: i8): +// CHECK: %[[ADDI_0:.*]] = arith.addi %[[VAL_3]], %[[CONSTANT_2]] : index +// CHECK: scf.yield %[[ADDI_0]], %[[VAL_4]], %[[VAL_5]] : index, i1, i8 +// CHECK: } attributes {finalValue} +// CHECK: return %[[VAL_6:.*]]#0, %[[VAL_6]]#1, %[[VAL_6]]#2 : index, i1, i8 // CHECK: } func.func @test_zero_iterations() -> (index, i1, i8) { %lo = arith.constant 10 : index @@ -97,3 +186,37 @@ func.func @test_zero_iterations() -> (index, i1, i8) { return %res#0, %res#1, %res#2 : index, i1, i8 } + +// CHECK-LABEL: func.func @test_without_final_value( +// CHECK-SAME: %[[ARG0:.*]]: index, +// CHECK-SAME: %[[ARG1:.*]]: index) -> i1 { +// CHECK: %[[CONSTANT_0:.*]] = arith.constant 1 : index +// CHECK: %[[CONSTANT_1:.*]] = arith.constant true +// CHECK: %[[WHILE_0:.*]]:2 = scf.while (%[[VAL_0:.*]] = %[[ARG0]], %[[VAL_1:.*]] = %[[CONSTANT_1]]) : (index, i1) -> (index, i1) { +// CHECK: %[[CONSTANT_2:.*]] = arith.constant 0 : index +// CHECK: %[[CMPI_0:.*]] = arith.cmpi slt, %[[CONSTANT_2]], %[[CONSTANT_0]] : index +// CHECK: %[[CMPI_1:.*]] = arith.cmpi sle, %[[VAL_0]], %[[ARG1]] : index +// CHECK: %[[CMPI_2:.*]] = arith.cmpi slt, %[[CONSTANT_0]], %[[CONSTANT_2]] : index +// CHECK: %[[CMPI_3:.*]] = arith.cmpi sge, %[[VAL_0]], %[[ARG1]] : index +// CHECK: %[[ANDI_0:.*]] = arith.andi %[[CMPI_0]], %[[CMPI_1]] : i1 +// CHECK: %[[ANDI_1:.*]] = arith.andi %[[CMPI_2]], %[[CMPI_3]] : i1 +// CHECK: %[[ORI_0:.*]] = arith.ori %[[ANDI_0]], %[[ANDI_1]] : i1 +// CHECK: %[[ANDI_2:.*]] = arith.andi %[[VAL_1]], %[[ORI_0]] : i1 +// CHECK: scf.condition(%[[ANDI_2]]) %[[VAL_0]], %[[VAL_1]] : index, i1 +// CHECK: } do { +// CHECK: ^bb0(%[[VAL_2:.*]]: index, %[[VAL_3:.*]]: i1): +// CHECK: %[[ADDI_0:.*]] = arith.addi %[[VAL_2]], %[[CONSTANT_0]] : index +// CHECK: %[[VAL_4:.*]] = "test.get_some_value"() : () -> i1 +// CHECK: scf.yield %[[ADDI_0]], %[[VAL_4]] : index, i1 +// CHECK: } +// CHECK: return %[[VAL_5:.*]]#1 : i1 +// CHECK: } +func.func @test_without_final_value(%lo : index, %up : index) -> i1 { + %c1 = arith.constant 1 : index + %ok1 = arith.constant true + %ok2 = fir.iterate_while (%i = %lo to %up step %c1) and (%j = %ok1) { + %ok = "test.get_some_value"() : () -> i1 + fir.result %ok : i1 + } + return %ok2 : i1 +} diff --git a/flang/test/Fir/MIF/change_team.mlir b/flang/test/Fir/MIF/change_team.mlir new file mode 100644 index 0000000..1dbfee5 --- /dev/null +++ b/flang/test/Fir/MIF/change_team.mlir @@ -0,0 +1,51 @@ +// RUN: fir-opt --mif-convert %s | FileCheck %s + +func.func @_QQmain() attributes {fir.bindc_name = "TEST_CHANGE_TEAM"} { + %0 = fir.dummy_scope : !fir.dscope + %c10 = arith.constant 10 : index + %1 = fir.alloca !fir.char<1,10> {bindc_name = "err", uniq_name = "_QFEerr"} + %2:2 = hlfir.declare %1 typeparams %c10 {uniq_name = "_QFEerr"} : (!fir.ref<!fir.char<1,10>>, index) -> (!fir.ref<!fir.char<1,10>>, !fir.ref<!fir.char<1,10>>) + %3 = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFEi"} + %4:2 = hlfir.declare %3 {uniq_name = "_QFEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) + %5 = fir.alloca i32 {bindc_name = "stat", uniq_name = "_QFEstat"} + %6:2 = hlfir.declare %5 {uniq_name = "_QFEstat"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) + %7 = fir.alloca !fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}> {bindc_name = "team", uniq_name = "_QFEteam"} + %8:2 = hlfir.declare %7 {uniq_name = "_QFEteam"} : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>>) -> (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>>, !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>>) + %9 = fir.address_of(@_QQ_QM__fortran_builtinsT__builtin_team_type.DerivedInit) : !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>> + fir.copy %9 to %8#0 no_overlap : !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>>, !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>> + %10 = fir.embox %8#0 : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>>) -> !fir.box<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>> + mif.change_team %10 : (!fir.box<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>>) { + %13 = fir.load %4#0 : !fir.ref<i32> + %c1_i32 = arith.constant 1 : i32 + %14 = arith.addi %13, %c1_i32 : i32 + hlfir.assign %14 to %4#0 : i32, !fir.ref<i32> + mif.end_team : () -> () + } + %11 = fir.embox %2#0 : (!fir.ref<!fir.char<1,10>>) -> !fir.box<!fir.char<1,10>> + %12 = fir.embox %8#0 : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>>) -> !fir.box<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>> + mif.change_team %12 stat %6#0 errmsg %11 : (!fir.box<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>>, !fir.ref<i32>, !fir.box<!fir.char<1,10>>) { + mif.end_team : () -> () + } + return +} + +// CHECK: %[[VAL_1:.*]] = fir.absent !fir.ref<i32> +// CHECK: %[[VAL_2:.*]] = fir.absent !fir.box<!fir.char<1,?>> +// CHECK: %[[VAL_3:.*]] = fir.convert %[[TEAM:.*]] : ({{.*}}) -> !fir.box<none> +// CHECK: fir.call @_QMprifPprif_change_team(%[[VAL_3]], %[[VAL_1]], %[[VAL_2]], %[[VAL_2]]) : (!fir.box<none>, !fir.ref<i32>, !fir.box<!fir.char<1,?>>, !fir.box<!fir.char<1,?>>) -> () +// CHECK: %[[VAL_4:.*]] = fir.load %[[VAR_1:.*]]#0 : !fir.ref<i32> +// CHECK: %[[C1:.*]] = arith.constant 1 : i32 +// CHECK: %[[VAL_5:.*]] = arith.addi %[[VAL_4]], %[[C1]] : i32 +// CHECK: hlfir.assign %[[VAL_5]] to %[[VAR_1]]#0 : i32, !fir.ref<i32> +// CHECK: %[[VAL_6:.*]] = fir.absent !fir.ref<i32> +// CHECK: %[[VAL_7:.*]] = fir.absent !fir.box<!fir.char<1,?>> +// CHECK: fir.call @_QMprifPprif_end_team(%[[VAL_6]], %[[VAL_7]], %[[VAL_7]]) : (!fir.ref<i32>, !fir.box<!fir.char<1,?>>, !fir.box<!fir.char<1,?>>) -> () + +// CHECK: %[[VAL_8:.*]] = fir.embox %[[ERRMSG:.*]]#0 : (!fir.ref<!fir.char<1,10>>) -> !fir.box<!fir.char<1,10> +// CHECK: %[[VAL_9:.*]] = fir.absent !fir.box<!fir.char<1,?>> +// CHECK: %[[TEAM_2:.*]] = fir.convert %[[TEAM:.*]] : ({{.*}}) -> !fir.box<none> +// CHECK: %[[VAL_10:.*]] = fir.convert %[[VAL_8]] : (!fir.box<!fir.char<1,10>>) -> !fir.box<!fir.char<1,?>> +// CHECK: fir.call @_QMprifPprif_change_team(%[[TEAM_2]], %[[STAT:.*]]#0, %[[VAL_10]], %[[VAL_9]]) : (!fir.box<none>, !fir.ref<i32>, !fir.box<!fir.char<1,?>>, !fir.box<!fir.char<1,?>>) -> () +// CHECK: %[[VAL_11:.*]] = fir.absent !fir.ref<i32> +// CHECK: %[[VAL_12:.*]] = fir.absent !fir.box<!fir.char<1,?>> +// CHECK: fir.call @_QMprifPprif_end_team(%[[VAL_11]], %[[VAL_12]], %[[VAL_12]]) : (!fir.ref<i32>, !fir.box<!fir.char<1,?>>, !fir.box<!fir.char<1,?>>) -> () diff --git a/flang/test/Fir/MIF/form_team.mlir b/flang/test/Fir/MIF/form_team.mlir new file mode 100644 index 0000000..f7f957a --- /dev/null +++ b/flang/test/Fir/MIF/form_team.mlir @@ -0,0 +1,56 @@ +// RUN: fir-opt --mif-convert %s | FileCheck %s + +func.func @_QQmain() attributes {fir.bindc_name = "TEST_FORM_TEAM"} { + %0 = fir.dummy_scope : !fir.dscope + %c10 = arith.constant 10 : index + %1 = fir.alloca !fir.char<1,10> {bindc_name = "err", uniq_name = "_QFEerr"} + %2:2 = hlfir.declare %1 typeparams %c10 {uniq_name = "_QFEerr"} : (!fir.ref<!fir.char<1,10>>, index) -> (!fir.ref<!fir.char<1,10>>, !fir.ref<!fir.char<1,10>>) + %3 = fir.alloca i32 {bindc_name = "stat", uniq_name = "_QFEstat"} + %4:2 = hlfir.declare %3 {uniq_name = "_QFEstat"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) + %5 = fir.alloca !fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}> {bindc_name = "team", uniq_name = "_QFEteam"} + %6:2 = hlfir.declare %5 {uniq_name = "_QFEteam"} : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>>) -> (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>>, !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>>) + %7 = fir.address_of(@_QQ_QM__fortran_builtinsT__builtin_team_type.DerivedInit) : !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>> + fir.copy %7 to %6#0 no_overlap : !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>>, !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>> + %8 = fir.alloca i32 {bindc_name = "team_index", uniq_name = "_QFEteam_index"} + %9:2 = hlfir.declare %8 {uniq_name = "_QFEteam_index"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) + %10 = fir.alloca i32 {bindc_name = "team_number", uniq_name = "_QFEteam_number"} + %11:2 = hlfir.declare %10 {uniq_name = "_QFEteam_number"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) + %12 = fir.load %11#0 : !fir.ref<i32> + %13 = fir.embox %6#0 : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>>) -> !fir.box<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>> + mif.form_team team_number %12 team_var %13 : (i32, !fir.box<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>>) -> () + %14 = fir.load %9#0 : !fir.ref<i32> + %15 = fir.load %11#0 : !fir.ref<i32> + %16 = fir.embox %6#0 : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>>) -> !fir.box<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>> + mif.form_team team_number %15 team_var %16 new_index %14 : (i32, !fir.box<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>>, i32) -> () + %17 = fir.load %11#0 : !fir.ref<i32> + %18 = fir.embox %6#0 : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>>) -> !fir.box<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>> + mif.form_team team_number %17 team_var %18 stat %4#0 : (i32, !fir.box<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>>, !fir.ref<i32>) -> () + %19 = fir.embox %2#0 : (!fir.ref<!fir.char<1,10>>) -> !fir.box<!fir.char<1,10>> + %20 = fir.load %11#0 : !fir.ref<i32> + %21 = fir.embox %6#0 : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>>) -> !fir.box<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>> + mif.form_team team_number %20 team_var %21 errmsg %19 : (i32, !fir.box<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>>, !fir.box<!fir.char<1,10>>) -> () + return +} +// CHECK: %[[VAL_1:.*]] = fir.absent !fir.ref<i32> +// CHECK: %[[VAL_2:.*]] = fir.absent !fir.ref<i32> +// CHECK: %[[VAL_3:.*]] = fir.absent !fir.box<!fir.char<1,?>> +// CHECK: %[[VAL_4:.*]] = fir.convert %[[TEAM:.*]] : ({{.*}}) -> !fir.box<none> +// CHECK: fir.call @_QMprifPprif_form_team(%[[TEAM_NUMBER:.*]], %[[VAL_4]], %[[VAL_1]], %[[VAL_2]], %[[VAL_3]], %[[VAL_3]]) : (!fir.ref<i64>, !fir.box<none>, !fir.ref<i32>, !fir.ref<i32>, !fir.box<!fir.char<1,?>>, !fir.box<!fir.char<1,?>>) -> () + +// CHECK: %[[VAL_5:.*]] = fir.absent !fir.ref<i32> +// CHECK: %[[VAL_6:.*]] = fir.absent !fir.box<!fir.char<1,?>> +// CHECK: %[[VAL_7:.*]] = fir.convert %[[TEAM:.*]] : ({{.*}}) -> !fir.box<none> +// CHECK: fir.call @_QMprifPprif_form_team(%[[TEAM_NUMBER:.*]], %[[VAL_7]], %[[NEW_INDEX:.*]], %[[VAL_5]], %[[VAL_6]], %[[VAL_6]]) : (!fir.ref<i64>, !fir.box<none>, !fir.ref<i32>, !fir.ref<i32>, !fir.box<!fir.char<1,?>>, !fir.box<!fir.char<1,?>>) -> () + +// CHECK: %[[VAL_8:.*]] = fir.absent !fir.ref<i32> +// CHECK: %[[VAL_9:.*]] = fir.absent !fir.box<!fir.char<1,?>> +// CHECK: %[[VAL_10:.*]] = fir.convert %[[TEAM:.*]] : ({{.*}}) -> !fir.box<none> +// CHECK: fir.call @_QMprifPprif_form_team(%[[TEAM_NUMBER:.*]], %[[VAL_10]], %[[VAL_8]], %[[START:.*]]#0, %[[VAL_9]], %[[VAL_9]]) : (!fir.ref<i64>, !fir.box<none>, !fir.ref<i32>, !fir.ref<i32>, !fir.box<!fir.char<1,?>>, !fir.box<!fir.char<1,?>>) -> () + +// CHECK: %[[VAL_11:.*]] = fir.embox %[[ERRMSG:.*]]#0 : (!fir.ref<!fir.char<1,10>>) -> !fir.box<!fir.char<1,10>> +// CHECK: %[[VAL_12:.*]] = fir.absent !fir.ref<i32> +// CHECK: %[[VAL_13:.*]] = fir.absent !fir.ref<i32> +// CHECK: %[[VAL_14:.*]] = fir.absent !fir.box<!fir.char<1,?>> +// CHECK: %[[VAL_15:.*]] = fir.convert %[[TEAM:.*]] : ({{.*}}) -> !fir.box<none> +// CHECK: %[[VAL_16:.*]] = fir.convert %[[VAL_11]] : (!fir.box<!fir.char<1,10>>) -> !fir.box<!fir.char<1,?>> +// CHECK: fir.call @_QMprifPprif_form_team(%[[TEAM_NUMBER:.*]], %[[VAL_15]], %[[VAL_12]], %[[VAL_13]], %[[VAL_16]], %[[VAL_14]]) : (!fir.ref<i64>, !fir.box<none>, !fir.ref<i32>, !fir.ref<i32>, !fir.box<!fir.char<1,?>>, !fir.box<!fir.char<1,?>>) -> () diff --git a/flang/test/Fir/MIF/get_team.mlir b/flang/test/Fir/MIF/get_team.mlir new file mode 100644 index 0000000..10799fa --- /dev/null +++ b/flang/test/Fir/MIF/get_team.mlir @@ -0,0 +1,68 @@ +// RUN: fir-opt --mif-convert %s | FileCheck %s + +func.func @_QQmain() attributes {fir.bindc_name = "TEST_FORM_TEAM"} { + %0 = fir.dummy_scope : !fir.dscope + %1 = fir.address_of(@_QMiso_fortran_envECcurrent_team) : !fir.ref<i32> + %2:2 = hlfir.declare %1 {fortran_attrs = #fir.var_attrs<parameter>, uniq_name = "_QMiso_fortran_envECcurrent_team"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) + %3 = fir.address_of(@_QMiso_fortran_envECinitial_team) : !fir.ref<i32> + %4:2 = hlfir.declare %3 {fortran_attrs = #fir.var_attrs<parameter>, uniq_name = "_QMiso_fortran_envECinitial_team"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) + %5 = fir.alloca i32 {bindc_name = "n", uniq_name = "_QFEn"} + %6:2 = hlfir.declare %5 {uniq_name = "_QFEn"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) + %7 = fir.address_of(@_QMiso_fortran_envECparent_team) : !fir.ref<i32> + %8:2 = hlfir.declare %7 {fortran_attrs = #fir.var_attrs<parameter>, uniq_name = "_QMiso_fortran_envECparent_team"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) + %9 = fir.alloca !fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}> {bindc_name = "result_team", uniq_name = "_QFEresult_team"} + %10:2 = hlfir.declare %9 {uniq_name = "_QFEresult_team"} : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>>) -> (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>>, !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>>) + %11 = fir.address_of(@_QQ_QM__fortran_builtinsT__builtin_team_type.DerivedInit) : !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>> + fir.copy %11 to %10#0 no_overlap : !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>>, !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>> + %12 = mif.get_team : () -> !fir.box<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>> + %13:2 = hlfir.declare %12 {uniq_name = ".tmp.intrinsic_result"} : (!fir.box<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>>) -> (!fir.box<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>>, !fir.box<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>>) + %false = arith.constant false + %14 = hlfir.as_expr %13#0 move %false : (!fir.box<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>>, i1) -> !hlfir.expr<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>> + hlfir.assign %14 to %10#0 : !hlfir.expr<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>>, !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>> + hlfir.destroy %14 : !hlfir.expr<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>> + %c-2_i32 = arith.constant -2 : i32 + %15 = mif.get_team level %c-2_i32 : (i32) -> !fir.box<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>> + %16:2 = hlfir.declare %15 {uniq_name = ".tmp.intrinsic_result"} : (!fir.box<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>>) -> (!fir.box<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>>, !fir.box<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>>) + %false_0 = arith.constant false + %17 = hlfir.as_expr %16#0 move %false_0 : (!fir.box<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>>, i1) -> !hlfir.expr<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>> + hlfir.assign %17 to %10#0 : !hlfir.expr<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>>, !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>> + hlfir.destroy %17 : !hlfir.expr<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>> + %c-1_i32 = arith.constant -1 : i32 + %18 = mif.get_team level %c-1_i32 : (i32) -> !fir.box<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>> + %19:2 = hlfir.declare %18 {uniq_name = ".tmp.intrinsic_result"} : (!fir.box<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>>) -> (!fir.box<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>>, !fir.box<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>>) + %false_1 = arith.constant false + %20 = hlfir.as_expr %19#0 move %false_1 : (!fir.box<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>>, i1) -> !hlfir.expr<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>> + hlfir.assign %20 to %10#0 : !hlfir.expr<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>>, !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>> + hlfir.destroy %20 : !hlfir.expr<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>> + %c-3_i32 = arith.constant -3 : i32 + %21 = mif.get_team level %c-3_i32 : (i32) -> !fir.box<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>> + %22:2 = hlfir.declare %21 {uniq_name = ".tmp.intrinsic_result"} : (!fir.box<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>>) -> (!fir.box<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>>, !fir.box<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>>) + %false_2 = arith.constant false + %23 = hlfir.as_expr %22#0 move %false_2 : (!fir.box<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>>, i1) -> !hlfir.expr<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>> + hlfir.assign %23 to %10#0 : !hlfir.expr<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>>, !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>> + hlfir.destroy %23 : !hlfir.expr<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>> + %24 = fir.load %6#0 : !fir.ref<i32> + %25 = mif.get_team level %24 : (i32) -> !fir.box<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>> + %26:2 = hlfir.declare %25 {uniq_name = ".tmp.intrinsic_result"} : (!fir.box<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>>) -> (!fir.box<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>>, !fir.box<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>>) + %false_3 = arith.constant false + %27 = hlfir.as_expr %26#0 move %false_3 : (!fir.box<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>>, i1) -> !hlfir.expr<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>> + hlfir.assign %27 to %10#0 : !hlfir.expr<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>>, !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>> + hlfir.destroy %27 : !hlfir.expr<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>> + return +} + +// CHECK: %[[VAL_1:.*]] = fir.absent !fir.ref<i32> +// CHECK: %[[RESULT:.*]] = fir.convert %[[TEAM:.*]] : ({{.*}}) -> !fir.box<none> +// CHECK: fir.call @_QMprifPprif_get_team(%[[VAL_1]], %[[RESULT]]) : (!fir.ref<i32>, !fir.box<none>) -> () + +// CHECK: %[[RESULT:.*]] = fir.convert %[[TEAM:.*]] : ({{.*}}) -> !fir.box<none> +// CHECK: fir.call @_QMprifPprif_get_team(%[[INIT:.*]], %[[RESULT]]) : (!fir.ref<i32>, !fir.box<none>) -> () + +// CHECK: %[[RESULT:.*]] = fir.convert %[[TEAM:.*]] : ({{.*}}) -> !fir.box<none> +// CHECK: fir.call @_QMprifPprif_get_team(%[[CURRENT:.*]], %[[RESULT]]) : (!fir.ref<i32>, !fir.box<none>) -> () + +// CHECK: %[[RESULT:.*]] = fir.convert %[[TEAM:.*]] : ({{.*}}) -> !fir.box<none> +// CHECK: fir.call @_QMprifPprif_get_team(%[[PARENT:.*]], %[[RESULT]]) : (!fir.ref<i32>, !fir.box<none>) -> () + +// CHECK: %[[RESULT:.*]] = fir.convert %[[TEAM:.*]] : ({{.*}}) -> !fir.box<none> +// CHECK: fir.call @_QMprifPprif_get_team(%[[VAL_N:.*]], %[[RESULT]]) : (!fir.ref<i32>, !fir.box<none>) -> () diff --git a/flang/test/Fir/MIF/sync_team.mlir b/flang/test/Fir/MIF/sync_team.mlir new file mode 100644 index 0000000..d7db171 --- /dev/null +++ b/flang/test/Fir/MIF/sync_team.mlir @@ -0,0 +1,54 @@ +// RUN: fir-opt --mif-convert %s | FileCheck %s + +func.func @_QQmain() attributes {fir.bindc_name = "TEST_SYNC_TEAM"} { + %0 = fir.dummy_scope : !fir.dscope + %1 = fir.address_of(@_QFEerror_message) : !fir.ref<!fir.char<1,128>> + %c128 = arith.constant 128 : index + %2:2 = hlfir.declare %1 typeparams %c128 {uniq_name = "_QFEerror_message"} : (!fir.ref<!fir.char<1,128>>, index) -> (!fir.ref<!fir.char<1,128>>, !fir.ref<!fir.char<1,128>>) + %3 = fir.alloca i32 {bindc_name = "sync_status", uniq_name = "_QFEsync_status"} + %4:2 = hlfir.declare %3 {uniq_name = "_QFEsync_status"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) + %5 = fir.alloca !fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}> {bindc_name = "team", uniq_name = "_QFEteam"} + %6:2 = hlfir.declare %5 {uniq_name = "_QFEteam"} : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>>) -> (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>>, !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>>) + %7 = fir.address_of(@_QQ_QM__fortran_builtinsT__builtin_team_type.DerivedInit) : !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>> + fir.copy %7 to %6#0 no_overlap : !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>>, !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>> + %8 = fir.embox %6#0 : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>>) -> !fir.box<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>> + mif.sync_team %8 : (!fir.box<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>>) -> () + %9 = fir.embox %6#0 : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>>) -> !fir.box<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>> + mif.sync_team %9 stat %4#0 : (!fir.box<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>>, !fir.ref<i32>) -> () + %10 = fir.embox %6#0 : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>>) -> !fir.box<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>> + %11 = fir.embox %2#0 : (!fir.ref<!fir.char<1,128>>) -> !fir.box<!fir.char<1,128>> + mif.sync_team %10 errmsg %11 : (!fir.box<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>>, !fir.box<!fir.char<1,128>>) -> () + %12 = fir.embox %6#0 : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>>) -> !fir.box<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>> + %13 = fir.embox %2#0 : (!fir.ref<!fir.char<1,128>>) -> !fir.box<!fir.char<1,128>> + mif.sync_team %12 stat %4#0 errmsg %13 : (!fir.box<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>>, !fir.ref<i32>, !fir.box<!fir.char<1,128>>) -> () + return +} +fir.global internal @_QFEerror_message : !fir.char<1,128> { + %0 = fir.zero_bits !fir.char<1,128> + fir.has_value %0 : !fir.char<1,128> +} + +// CHECK: %[[ERRMSG:.*]]:2 = hlfir.declare %[[E:.*]] typeparams %[[C_128:.*]] {uniq_name = "_QFEerror_message"} : (!fir.ref<!fir.char<1,128>>, index) -> (!fir.ref<!fir.char<1,128>>, !fir.ref<!fir.char<1,128>>) +// CHECK: %[[STAT:.*]]:2 = hlfir.declare %[[S:.*]] {uniq_name = "_QFEsync_status"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) + +// CHECK: %[[VAL_1:.*]] = fir.absent !fir.box<!fir.char<1,?>> +// CHECK: %[[VAL_2:.*]] = fir.absent !fir.ref<i32> +// CHECK: %[[TEAM_2:.*]] = fir.convert %[[TEAM:.*]] : ({{.*}}) -> !fir.box<none> +// CHECK: fir.call @_QMprifPprif_sync_team(%[[TEAM_2]], %[[VAL_2]], %[[VAL_1]], %[[VAL_1]]) : (!fir.box<none>, !fir.ref<i32>, !fir.box<!fir.char<1,?>>, !fir.box<!fir.char<1,?>>) -> () + +// CHECK: %[[VAL_3:.*]] = fir.absent !fir.box<!fir.char<1,?>> +// CHECK: %[[TEAM_2:.*]] = fir.convert %[[TEAM:.*]] : ({{.*}}) -> !fir.box<none> +// CHECK: fir.call @_QMprifPprif_sync_team(%[[TEAM_2]], %[[STAT]]#0, %[[VAL_3]], %[[VAL_3]]) : (!fir.box<none>, !fir.ref<i32>, !fir.box<!fir.char<1,?>>, !fir.box<!fir.char<1,?>>) -> () + +// CHECK: %[[VAL_4:.*]] = fir.embox %[[ERRMSG]]#0 : (!fir.ref<!fir.char<1,128>>) -> !fir.box<!fir.char<1,128>> +// CHECK: %[[VAL_5:.*]] = fir.absent !fir.box<!fir.char<1,?>> +// CHECK: %[[VAL_6:.*]] = fir.absent !fir.ref<i32> +// CHECK: %[[TEAM_2:.*]] = fir.convert %[[TEAM:.*]] : ({{.*}}) -> !fir.box<none> +// CHECK: %[[VAL_7:.*]] = fir.convert %[[VAL_4]] : (!fir.box<!fir.char<1,128>>) -> !fir.box<!fir.char<1,?>> +// CHECK: fir.call @_QMprifPprif_sync_team(%[[TEAM_2]], %[[VAL_6]], %[[VAL_7]], %[[VAL_5]]) : (!fir.box<none>, !fir.ref<i32>, !fir.box<!fir.char<1,?>>, !fir.box<!fir.char<1,?>>) -> () + +// CHECK: %[[VAL_8:.*]] = fir.embox %[[ERRMSG]]#0 : (!fir.ref<!fir.char<1,128>>) -> !fir.box<!fir.char<1,128>> +// CHECK: %[[VAL_9:.*]] = fir.absent !fir.box<!fir.char<1,?>> +// CHECK: %[[TEAM_2:.*]] = fir.convert %[[TEAM:.*]] : ({{.*}}) -> !fir.box<none> +// CHECK: %[[VAL_10:.*]] = fir.convert %[[VAL_8]] : (!fir.box<!fir.char<1,128>>) -> !fir.box<!fir.char<1,?>> +// CHECK: fir.call @_QMprifPprif_sync_team(%[[TEAM_2]], %[[STAT]]#0, %[[VAL_10]], %[[VAL_9]]) : (!fir.box<none>, !fir.ref<i32>, !fir.box<!fir.char<1,?>>, !fir.box<!fir.char<1,?>>) -> () diff --git a/flang/test/Fir/MIF/team_number.mlir b/flang/test/Fir/MIF/team_number.mlir new file mode 100644 index 0000000..4dc766d --- /dev/null +++ b/flang/test/Fir/MIF/team_number.mlir @@ -0,0 +1,27 @@ +// RUN: fir-opt --mif-convert %s | FileCheck %s + +func.func @_QQmain() attributes {fir.bindc_name = "TEST_TEAM_NUMBER"} { + %0 = fir.dummy_scope : !fir.dscope + %1 = fir.alloca i32 {bindc_name = "t", uniq_name = "_QFEt"} + %2:2 = hlfir.declare %1 {uniq_name = "_QFEt"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) + %3 = fir.alloca !fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}> {bindc_name = "team", uniq_name = "_QFEteam"} + %4:2 = hlfir.declare %3 {uniq_name = "_QFEteam"} : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>>) -> (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>>, !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>>) + %5 = fir.address_of(@_QQ_QM__fortran_builtinsT__builtin_team_type.DerivedInit) : !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>> + fir.copy %5 to %4#0 no_overlap : !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>>, !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>> + %6 = fir.embox %4#0 : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>>) -> !fir.box<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>> + %7 = mif.team_number team %6 : (!fir.box<!fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}>>) -> i64 + %8 = fir.convert %7 : (i64) -> i32 + hlfir.assign %8 to %2#0 : i32, !fir.ref<i32> + %9 = mif.team_number : () -> i64 + %10 = fir.convert %9 : (i64) -> i32 + hlfir.assign %10 to %2#0 : i32, !fir.ref<i32> + return +} + +// CHECK: %[[VAL_1:.*]] = fir.convert %[[TEAM:.*]] : ({{.*}}) -> !fir.box<none> +// CHECK: fir.call @_QMprifPprif_team_number(%[[VAL_1]], %[[RESULT:.*]]) : (!fir.box<none>, !fir.ref<i64>) -> () +// CHECK: %[[VAL_2:.*]] = fir.load %[[RESULT]] : !fir.ref<i64> + +// CHECK: %[[VAL_3:.*]] = fir.absent !fir.box<none> +// CHECK: fir.call @_QMprifPprif_team_number(%[[VAL_3]], %[[RESULT:.*]]) : (!fir.box<none>, !fir.ref<i64>) -> () +// CHECK: %[[VAL_4:.*]] = fir.load %[[RESULT]] : !fir.ref<i64> diff --git a/flang/test/Fir/OpenACC/pointer-like-interface-load.mlir b/flang/test/Fir/OpenACC/pointer-like-interface-load.mlir new file mode 100644 index 0000000..170ea56 --- /dev/null +++ b/flang/test/Fir/OpenACC/pointer-like-interface-load.mlir @@ -0,0 +1,95 @@ +// RUN: fir-opt %s --split-input-file --pass-pipeline="builtin.module(func.func(test-acc-pointer-like-interface{test-mode=load}))" 2>&1 | FileCheck %s + +func.func @test_load_scalar_f32() { + %ptr = fir.alloca f32 {test.ptr} + // CHECK: Successfully generated load for operation: %{{.*}} = fir.alloca f32 {test.ptr} + // CHECK: Loaded value type: f32 + // CHECK: Generated: %{{.*}} = fir.load %{{.*}} : !fir.ref<f32> + return +} + +// ----- + +func.func @test_load_scalar_i32() { + %ptr = fir.alloca i32 {test.ptr} + // CHECK: Successfully generated load for operation: %{{.*}} = fir.alloca i32 {test.ptr} + // CHECK: Loaded value type: i32 + // CHECK: Generated: %{{.*}} = fir.load %{{.*}} : !fir.ref<i32> + return +} + +// ----- + +func.func @test_load_scalar_i64() { + %ptr = fir.alloca i64 {test.ptr} + // CHECK: Successfully generated load for operation: %{{.*}} = fir.alloca i64 {test.ptr} + // CHECK: Loaded value type: i64 + // CHECK: Generated: %{{.*}} = fir.load %{{.*}} : !fir.ref<i64> + return +} + +// ----- + +func.func @test_load_heap_scalar() { + %ptr = fir.allocmem f64 {test.ptr} + // CHECK: Successfully generated load for operation: %{{.*}} = fir.allocmem f64 {test.ptr} + // CHECK: Loaded value type: f64 + // CHECK: Generated: %{{.*}} = fir.load %{{.*}} : !fir.heap<f64> + return +} + +// ----- + +func.func @test_load_logical() { + %ptr = fir.alloca !fir.logical<4> {test.ptr} + // CHECK: Successfully generated load for operation: %{{.*}} = fir.alloca !fir.logical<4> {test.ptr} + // CHECK: Loaded value type: !fir.logical<4> + // CHECK: Generated: %{{.*}} = fir.load %{{.*}} : !fir.ref<!fir.logical<4>> + return +} + +// ----- + +func.func @test_load_derived_type() { + %ptr = fir.alloca !fir.type<_QTt{i:i32}> {test.ptr} + // CHECK: Successfully generated load for operation: %{{.*}} = fir.alloca !fir.type<_QTt{i:i32}> {test.ptr} + // CHECK: Loaded value type: !fir.type<_QTt{i:i32}> + // CHECK: Generated: %{{.*}} = fir.load %{{.*}} : !fir.ref<!fir.type<_QTt{i:i32}>> + return +} + +// ----- + +func.func @test_load_constant_array() { + %ptr = fir.alloca !fir.array<10xf32> {test.ptr} + // CHECK: Successfully generated load for operation: %{{.*}} = fir.alloca !fir.array<10xf32> {test.ptr} + // CHECK: Loaded value type: !fir.array<10xf32> + // CHECK: Generated: %{{.*}} = fir.load %{{.*}} : !fir.ref<!fir.array<10xf32>> + return +} + +// ----- + +func.func @test_load_dynamic_array_fails() { + %c10 = arith.constant 10 : index + %ptr = fir.alloca !fir.array<?xf32>, %c10 {test.ptr} + // CHECK: Failed to generate load for operation: %{{.*}} = fir.alloca !fir.array<?xf32> + return +} + +// ----- + +func.func @test_load_box_fails() { + %ptr = fir.alloca !fir.box<!fir.ptr<f32>> {test.ptr} + // CHECK: Failed to generate load for operation: %{{.*}} = fir.alloca !fir.box<!fir.ptr<f32>> + return +} + +// ----- + +func.func @test_load_unlimited_polymorphic_fails() { + %ptr = fir.alloca !fir.class<none> {test.ptr} + // CHECK: Failed to generate load for operation: %{{.*}} = fir.alloca !fir.class<none> + return +} + diff --git a/flang/test/Fir/OpenACC/pointer-like-interface-store.mlir b/flang/test/Fir/OpenACC/pointer-like-interface-store.mlir new file mode 100644 index 0000000..5ea4f0e --- /dev/null +++ b/flang/test/Fir/OpenACC/pointer-like-interface-store.mlir @@ -0,0 +1,85 @@ +// RUN: fir-opt %s --split-input-file --pass-pipeline="builtin.module(func.func(test-acc-pointer-like-interface{test-mode=store}))" 2>&1 | FileCheck %s + +func.func @test_store_scalar_f32() { + %ptr = fir.alloca f32 {test.ptr} + // CHECK: Successfully generated store for operation: %{{.*}} = fir.alloca f32 {test.ptr} + // CHECK: Generated: %[[VAL:.*]] = arith.constant 4.200000e+01 : f32 + // CHECK: Generated: fir.store %[[VAL]] to %{{.*}} : !fir.ref<f32> + return +} + +// ----- + +func.func @test_store_scalar_i32() { + %ptr = fir.alloca i32 {test.ptr} + // CHECK: Successfully generated store for operation: %{{.*}} = fir.alloca i32 {test.ptr} + // CHECK: Generated: %[[VAL:.*]] = arith.constant 42 : i32 + // CHECK: Generated: fir.store %[[VAL]] to %{{.*}} : !fir.ref<i32> + return +} + +// ----- + +func.func @test_store_scalar_i64() { + %ptr = fir.alloca i64 {test.ptr} + // CHECK: Successfully generated store for operation: %{{.*}} = fir.alloca i64 {test.ptr} + // CHECK: Generated: %[[VAL:.*]] = arith.constant 42 : i64 + // CHECK: Generated: fir.store %[[VAL]] to %{{.*}} : !fir.ref<i64> + return +} + +// ----- + +func.func @test_store_heap_scalar() { + %ptr = fir.allocmem f64 {test.ptr} + // CHECK: Successfully generated store for operation: %{{.*}} = fir.allocmem f64 {test.ptr} + // CHECK: Generated: %[[VAL:.*]] = arith.constant 4.200000e+01 : f64 + // CHECK: Generated: fir.store %[[VAL]] to %{{.*}} : !fir.heap<f64> + return +} + +// ----- + +func.func @test_store_with_type_conversion() { + %ptr = fir.alloca i32 {test.ptr} + // CHECK: Successfully generated store for operation: %{{.*}} = fir.alloca i32 {test.ptr} + // CHECK: Generated: %[[VAL:.*]] = arith.constant 42 : i32 + // CHECK: Generated: fir.store %[[VAL]] to %{{.*}} : !fir.ref<i32> + return +} + +// ----- + +func.func @test_store_constant_array() { + %val = fir.undefined !fir.array<10xf32> {test.value} + %ptr = fir.alloca !fir.array<10xf32> {test.ptr} + // CHECK: Successfully generated store for operation: %{{.*}} = fir.alloca !fir.array<10xf32> {test.ptr} + // CHECK: Generated: fir.store %{{.*}} to %{{.*}} : !fir.ref<!fir.array<10xf32>> + return +} + +// ----- + +func.func @test_store_dynamic_array_fails() { + %c10 = arith.constant 10 : index + %ptr = fir.alloca !fir.array<?xf32>, %c10 {test.ptr} + // CHECK: Failed to generate store for operation: %{{.*}} = fir.alloca !fir.array<?xf32> + return +} + +// ----- + +func.func @test_store_box_fails() { + %ptr = fir.alloca !fir.box<!fir.ptr<f32>> {test.ptr} + // CHECK: Failed to generate store for operation: %{{.*}} = fir.alloca !fir.box<!fir.ptr<f32>> + return +} + +// ----- + +func.func @test_store_unlimited_polymorphic_fails() { + %ptr = fir.alloca !fir.class<none> {test.ptr} + // CHECK: Failed to generate store for operation: %{{.*}} = fir.alloca !fir.class<none> + return +} + diff --git a/flang/test/Fir/OpenACC/recipe-bufferization.mlir b/flang/test/Fir/OpenACC/recipe-bufferization.mlir index c4f96f6..247f617 100644 --- a/flang/test/Fir/OpenACC/recipe-bufferization.mlir +++ b/flang/test/Fir/OpenACC/recipe-bufferization.mlir @@ -240,9 +240,9 @@ func.func @_QPfoo(%arg0: !fir.box<!fir.array<?xf32>> {fir.bindc_name = "x"}) { %2 = fir.declare %1 {uniq_name = "_QFfooEi"} : (!fir.ref<i32>) -> !fir.ref<i32> %3 = fir.declare %arg0 dummy_scope %0 {uniq_name = "_QFfooEx"} : (!fir.box<!fir.array<?xf32>>, !fir.dscope) -> !fir.box<!fir.array<?xf32>> acc.parallel combined(loop) { - %4 = acc.private var(%3 : !fir.box<!fir.array<?xf32>>) -> !fir.box<!fir.array<?xf32>> {name = "x"} - %5 = acc.private varPtr(%2 : !fir.ref<i32>) -> !fir.ref<i32> {implicit = true, name = "i"} - acc.loop combined(parallel) private(@privatization_box_Uxf32 -> %4 : !fir.box<!fir.array<?xf32>>, @privatization_ref_i32 -> %5 : !fir.ref<i32>) control(%arg1 : i32) = (%c1_i32 : i32) to (%c200_i32 : i32) step (%c1_i32 : i32) { + %4 = acc.private var(%3 : !fir.box<!fir.array<?xf32>>) recipe(@privatization_box_Uxf32) -> !fir.box<!fir.array<?xf32>> {name = "x"} + %5 = acc.private varPtr(%2 : !fir.ref<i32>) recipe(@privatization_ref_i32) -> !fir.ref<i32> {implicit = true, name = "i"} + acc.loop combined(parallel) private(%4, %5 : !fir.box<!fir.array<?xf32>>, !fir.ref<i32>) control(%arg1 : i32) = (%c1_i32 : i32) to (%c200_i32 : i32) step (%c1_i32 : i32) { %6 = fir.dummy_scope : !fir.dscope %7 = fir.declare %4 dummy_scope %6 {uniq_name = "_QFfooEx"} : (!fir.box<!fir.array<?xf32>>, !fir.dscope) -> !fir.box<!fir.array<?xf32>> %8 = fir.declare %5 {uniq_name = "_QFfooEi"} : (!fir.ref<i32>) -> !fir.ref<i32> @@ -297,9 +297,9 @@ func.func @_QPfoo(%arg0: !fir.box<!fir.array<?xf32>> {fir.bindc_name = "x"}) { // CHECK: %[[VAL_6:.*]] = fir.alloca !fir.box<!fir.array<?xf32>> // CHECK: fir.store %[[VAL_5]] to %[[VAL_6]] : !fir.ref<!fir.box<!fir.array<?xf32>>> // CHECK: acc.parallel combined(loop) { -// CHECK: %[[VAL_7:.*]] = acc.private varPtr(%[[VAL_6]] : !fir.ref<!fir.box<!fir.array<?xf32>>>) -> !fir.ref<!fir.box<!fir.array<?xf32>>> {name = "x"} -// CHECK: %[[VAL_8:.*]] = acc.private varPtr(%[[VAL_4]] : !fir.ref<i32>) -> !fir.ref<i32> {implicit = true, name = "i"} -// CHECK: acc.loop combined(parallel) private(@privatization_box_Uxf32 -> %[[VAL_7]] : !fir.ref<!fir.box<!fir.array<?xf32>>>, @privatization_ref_i32 -> %[[VAL_8]] : !fir.ref<i32>) control(%[[VAL_9:.*]] : i32) = (%[[VAL_1]] : i32) to (%[[VAL_0]] : i32) step (%[[VAL_1]] : i32) { +// CHECK: %[[VAL_7:.*]] = acc.private varPtr(%[[VAL_6]] : !fir.ref<!fir.box<!fir.array<?xf32>>>) recipe(@privatization_box_Uxf32) -> !fir.ref<!fir.box<!fir.array<?xf32>>> {name = "x"} +// CHECK: %[[VAL_8:.*]] = acc.private varPtr(%[[VAL_4]] : !fir.ref<i32>) recipe(@privatization_ref_i32) -> !fir.ref<i32> {implicit = true, name = "i"} +// CHECK: acc.loop combined(parallel) private(%[[VAL_7]], %[[VAL_8]] : !fir.ref<!fir.box<!fir.array<?xf32>>>, !fir.ref<i32>) control(%[[VAL_9:.*]] : i32) = (%[[VAL_1]] : i32) to (%[[VAL_0]] : i32) step (%[[VAL_1]] : i32) { // CHECK: %[[VAL_10:.*]] = fir.dummy_scope : !fir.dscope // CHECK: %[[VAL_11:.*]] = fir.load %[[VAL_7]] : !fir.ref<!fir.box<!fir.array<?xf32>>> // CHECK: %[[VAL_12:.*]] = fir.declare %[[VAL_11]] dummy_scope %[[VAL_10]] {uniq_name = "_QFfooEx"} : (!fir.box<!fir.array<?xf32>>, !fir.dscope) -> !fir.box<!fir.array<?xf32>> diff --git a/flang/test/Fir/alloc.fir b/flang/test/Fir/alloc.fir index 8da8b82..613c8e2 100644 --- a/flang/test/Fir/alloc.fir +++ b/flang/test/Fir/alloc.fir @@ -372,8 +372,17 @@ func.func @alloca_unlimited_polymorphic_box() { %1 = fir.alloca !fir.class<!fir.array<?xnone>> %2 = fir.alloca !fir.box<none> %3 = fir.alloca !fir.box<!fir.array<?xnone>> + // Add real uses so allocas are not trivially dead. + fir.call @__use_class_none(%0) : (!fir.ref<!fir.class<none>>) -> () + fir.call @__use_class_array(%1) : (!fir.ref<!fir.class<!fir.array<?xnone>>>) -> () + fir.call @__use_box_none(%2) : (!fir.ref<!fir.box<none>>) -> () + fir.call @__use_box_array(%3) : (!fir.ref<!fir.box<!fir.array<?xnone>>>) -> () return } +func.func private @__use_class_none(!fir.ref<!fir.class<none>>) -> () +func.func private @__use_class_array(!fir.ref<!fir.class<!fir.array<?xnone>>>) -> () +func.func private @__use_box_none(!fir.ref<!fir.box<none>>) -> () +func.func private @__use_box_array(!fir.ref<!fir.box<!fir.array<?xnone>>>) -> () // Note: allocmem of fir.box are not possible (fir::HeapType::verify does not // accept box types), so there is no equivalent of // alloca_unlimited_polymorphic_box for allocmem. diff --git a/flang/test/Fir/declare-codegen.fir b/flang/test/Fir/declare-codegen.fir index fe8d84e..9413525 100644 --- a/flang/test/Fir/declare-codegen.fir +++ b/flang/test/Fir/declare-codegen.fir @@ -52,3 +52,23 @@ func.func @unreachable_code(%arg0: !fir.ref<!fir.char<1,10>>) { // NODECL-NOT: uniq_name = "live_code" // DECL-LABEL: func.func @unreachable_code( // DECL: uniq_name = "live_code" + +// Test that storage and storage_offset operands are preserved during conversion +func.func @test_storage_operands() { + %c0 = arith.constant 0 : index + %c4 = arith.constant 4 : index + %0 = fir.address_of(@common_block) : !fir.ref<!fir.array<8xi8>> + %1 = fir.coordinate_of %0, %c0 : (!fir.ref<!fir.array<8xi8>>, index) -> !fir.ref<i8> + %2 = fir.convert %1 : (!fir.ref<i8>) -> !fir.ref<f32> + %3 = fir.declare %2 storage(%0[0]) {uniq_name = "_QFEx"} : (!fir.ref<f32>, !fir.ref<!fir.array<8xi8>>) -> !fir.ref<f32> + %4 = fir.coordinate_of %0, %c4 : (!fir.ref<!fir.array<8xi8>>, index) -> !fir.ref<i8> + %5 = fir.convert %4 : (!fir.ref<i8>) -> !fir.ref<i32> + %6 = fir.declare %5 storage(%0[4]) {uniq_name = "_QFEy"} : (!fir.ref<i32>, !fir.ref<!fir.array<8xi8>>) -> !fir.ref<i32> + return +} +fir.global @common_block : !fir.array<8xi8> + +// DECL-LABEL: func.func @test_storage_operands() +// DECL: %[[STORAGE:.*]] = fir.address_of(@common_block) : !fir.ref<!fir.array<8xi8>> +// DECL: fircg.ext_declare {{.*}} storage(%[[STORAGE]][0]) {uniq_name = "_QFEx"} +// DECL: fircg.ext_declare {{.*}} storage(%[[STORAGE]][4]) {uniq_name = "_QFEy"} diff --git a/flang/test/Fir/dispatch.f90 b/flang/test/Fir/dispatch.f90 index 2b1ae22..74109970 100644 --- a/flang/test/Fir/dispatch.f90 +++ b/flang/test/Fir/dispatch.f90 @@ -195,7 +195,7 @@ end ! CHECK-LABEL: func.func @_QMdispatch1Pdisplay_class( ! CHECK-SAME: %[[ARG:.*]]: [[CLASS:!fir.class<.*>>]] -! CHECK: %[[ARG_DECL:.*]]:2 = hlfir.declare %[[ARG]] dummy_scope %{{[0-9]+}} {uniq_name = "_QMdispatch1Fdisplay_classEp"} : (!fir.class<!fir.type<_QMdispatch1Tp1{a:i32,b:i32}>>, !fir.dscope) -> (!fir.class<!fir.type<_QMdispatch1Tp1{a:i32,b:i32}>>, !fir.class<!fir.type<_QMdispatch1Tp1{a:i32,b:i32}>>) +! CHECK: %[[ARG_DECL:.*]]:2 = hlfir.declare %[[ARG]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QMdispatch1Fdisplay_classEp"} : (!fir.class<!fir.type<_QMdispatch1Tp1{a:i32,b:i32}>>, !fir.dscope) -> (!fir.class<!fir.type<_QMdispatch1Tp1{a:i32,b:i32}>>, !fir.class<!fir.type<_QMdispatch1Tp1{a:i32,b:i32}>>) ! Check dynamic dispatch equal to `call p%display2()` with binding index = 2. ! CHECK: %[[BOXDESC:.*]] = fir.box_tdesc %[[ARG_DECL]]#0 : ([[CLASS]]) -> !fir.tdesc<none> @@ -296,7 +296,7 @@ end ! CHECK-LABEL: _QMdispatch1Pno_pass_array_pointer ! CHECK-LABEL: _QMdispatch1Pcall_a1_proc -! Check the layout of the binding table. This is easier to do in FIR than in +! Check the layout of the binding table. This is easier to do in FIR than in ! LLVM IR. ! BT-LABEL: fir.type_info @_QMdispatch1Tty_kindK10K20 diff --git a/flang/test/Fir/fir-ops.fir b/flang/test/Fir/fir-ops.fir index 0892eb9..8336b6d 100644 --- a/flang/test/Fir/fir-ops.fir +++ b/flang/test/Fir/fir-ops.fir @@ -467,6 +467,13 @@ fir.type_info @cpinfo : !fir.type<cpinfo{comp_i:!fir.array<10x20xi32>}> componen fir.dt_component "component_info" lbs [2, 3] } +// CHECK-LABEL: fir.type_info @abstract_dispatch_tbl abstract : !fir.type<abstract_dispatch_tbl{i:i32}> dispatch_table { +// CHECK: fir.dt_entry "deferred_method", @deferred_impl deferred +// CHECK: } +fir.type_info @abstract_dispatch_tbl abstract : !fir.type<abstract_dispatch_tbl{i:i32}> dispatch_table { + fir.dt_entry "deferred_method", @deferred_impl deferred +} + // CHECK-LABEL: func @compare_complex( // CHECK-SAME: [[VAL_151:%.*]]: complex<f128>, [[VAL_152:%.*]]: complex<f128>) { func.func @compare_complex(%a : complex<f128>, %b : complex<f128>) { diff --git a/flang/test/Fir/global.fir b/flang/test/Fir/global.fir index 598fcb3..b57d3ed 100644 --- a/flang/test/Fir/global.fir +++ b/flang/test/Fir/global.fir @@ -50,7 +50,7 @@ fir.global internal @_QEmultiarray : !fir.array<32x32xi32> { fir.has_value %2 : !fir.array<32x32xi32> } -// CHECK: @_QEmasklogical = internal global [32768 x i32] [i32 -1, i32 -1, +// CHECK: @_QEmasklogical = internal global [32768 x i32] [i32 1, i32 1, fir.global internal @_QEmasklogical : !fir.array<32768x!fir.logical<4>> { %true = arith.constant true %0 = fir.undefined !fir.array<32768x!fir.logical<4>> diff --git a/flang/test/Fir/non-trivial-procedure-binding-description.f90 b/flang/test/Fir/non-trivial-procedure-binding-description.f90 index 6689286..13fcfee 100644 --- a/flang/test/Fir/non-trivial-procedure-binding-description.f90 +++ b/flang/test/Fir/non-trivial-procedure-binding-description.f90 @@ -25,6 +25,6 @@ end module a program main use a - type(f) :: obj + type(f) :: obj print *, obj%foo(obj) end program diff --git a/flang/test/Fir/omp-reduction-embox-codegen.fir b/flang/test/Fir/omp-reduction-embox-codegen.fir index 1645e1a..47fffb3 100644 --- a/flang/test/Fir/omp-reduction-embox-codegen.fir +++ b/flang/test/Fir/omp-reduction-embox-codegen.fir @@ -28,9 +28,11 @@ func.func @_QQmain() attributes {fir.bindc_name = "reduce"} { omp.parallel reduction(byref @test_reduction %4 -> %arg0 : !fir.ref<!fir.box<i32>>) { omp.terminator } + func.call @__use_box_i32(%4) : (!fir.ref<!fir.box<i32>>) -> () return } +func.func private @__use_box_i32(!fir.ref<!fir.box<i32>>) -> () // basically we are testing that there isn't a crash // CHECK-LABEL: define void @_QQmain // CHECK-NEXT: alloca { ptr, i64, i32, i8, i8, i8, i8 }, i64 1, align 8 diff --git a/flang/test/Fir/pdt.fir b/flang/test/Fir/pdt.fir index a200cd7..04f48e7 100644 --- a/flang/test/Fir/pdt.fir +++ b/flang/test/Fir/pdt.fir @@ -95,14 +95,14 @@ func.func @_QTt1P.f2.offset(%0 : i32, %1 : i32) -> i32 { // end program p func.func private @bar(!fir.ref<!fir.char<1,?>>) +func.func private @__use_t1(!fir.ref<!fir.type<_QTt1(p1:i32,p2:i32){f1:!fir.char<1,?>,f2:!fir.char<1,?>}>>) -> () // CHECK-LABEL: define void @_QPfoo(i32 %0, i32 %1) func.func @_QPfoo(%arg0 : i32, %arg1 : i32) { // CHECK: %[[size:.*]] = call i64 @_QTt1P.mem.size(i32 %0, i32 %1) // CHECK: %[[alloc:.*]] = alloca i8, i64 %[[size]] %0 = fir.alloca !fir.type<_QTt1(p1:i32,p2:i32){f1:!fir.char<1,?>,f2:!fir.char<1,?>}>(%arg0, %arg1 : i32, i32) - //%2 = fir.coordinate_of %0, f2 : (!fir.ref<!fir.type<_QTt1>>) -> !fir.ref<!fir.char<1,?>> - %2 = fir.zero_bits !fir.ref<!fir.char<1,?>> - fir.call @bar(%2) : (!fir.ref<!fir.char<1,?>>) -> () + // Keep alloca live without creating an unsupported coordinate_of on dynamic-sized field. + func.call @__use_t1(%0) : (!fir.ref<!fir.type<_QTt1(p1:i32,p2:i32){f1:!fir.char<1,?>,f2:!fir.char<1,?>}>>) -> () return } diff --git a/flang/test/HLFIR/assumed-type-actual-args.f90 b/flang/test/HLFIR/assumed-type-actual-args.f90 index aaac98b..fde7965 100644 --- a/flang/test/HLFIR/assumed-type-actual-args.f90 +++ b/flang/test/HLFIR/assumed-type-actual-args.f90 @@ -105,7 +105,7 @@ end subroutine ! CHECK-LABEL: func.func @_QPtest1( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<none> {fir.bindc_name = "x"}) { ! CHECK: %[[DSCOPE:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[DSCOPE]] {uniq_name = "_QFtest1Ex"} : (!fir.ref<none>, !fir.dscope) -> (!fir.ref<none>, !fir.ref<none>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[DSCOPE]] arg {{[0-9]+}} {uniq_name = "_QFtest1Ex"} : (!fir.ref<none>, !fir.dscope) -> (!fir.ref<none>, !fir.ref<none>) ! CHECK: fir.call @_QPs1(%[[VAL_1]]#0) fastmath<contract> : (!fir.ref<none>) -> () ! CHECK: return ! CHECK: } @@ -115,7 +115,7 @@ end subroutine ! CHECK: %[[DSCOPE:.*]] = fir.dummy_scope : !fir.dscope ! CHECK: %[[VAL_1:.*]] = fir.assumed_size_extent : index ! CHECK: %[[VAL_2:.*]] = fir.shape %[[VAL_1]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_2]]) dummy_scope %[[DSCOPE]] {uniq_name = "_QFtest2Ex"} : (!fir.ref<!fir.array<?xnone>>, !fir.shape<1>, !fir.dscope) -> (!fir.box<!fir.array<?xnone>>, !fir.ref<!fir.array<?xnone>>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_2]]) dummy_scope %[[DSCOPE]] arg {{[0-9]+}} {uniq_name = "_QFtest2Ex"} : (!fir.ref<!fir.array<?xnone>>, !fir.shape<1>, !fir.dscope) -> (!fir.box<!fir.array<?xnone>>, !fir.ref<!fir.array<?xnone>>) ! CHECK: fir.call @_QPs2(%[[VAL_3]]#1) fastmath<contract> : (!fir.ref<!fir.array<?xnone>>) -> () ! CHECK: return ! CHECK: } @@ -123,7 +123,7 @@ end subroutine ! CHECK-LABEL: func.func @_QPtest3( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.box<!fir.array<?xnone>> {fir.bindc_name = "x"}) { ! CHECK: %[[DSCOPE:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[DSCOPE]] {uniq_name = "_QFtest3Ex"} : (!fir.box<!fir.array<?xnone>>, !fir.dscope) -> (!fir.box<!fir.array<?xnone>>, !fir.box<!fir.array<?xnone>>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[DSCOPE]] arg {{[0-9]+}} {uniq_name = "_QFtest3Ex"} : (!fir.box<!fir.array<?xnone>>, !fir.dscope) -> (!fir.box<!fir.array<?xnone>>, !fir.box<!fir.array<?xnone>>) ! CHECK: fir.call @_QPs3(%[[VAL_1]]#0) fastmath<contract> : (!fir.box<!fir.array<?xnone>>) -> () ! CHECK: return ! CHECK: } @@ -131,7 +131,7 @@ end subroutine ! CHECK-LABEL: func.func @_QPtest4( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.box<!fir.array<?xnone>> {fir.bindc_name = "x"}) { ! CHECK: %[[DSCOPE:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[DSCOPE]] {uniq_name = "_QFtest4Ex"} : (!fir.box<!fir.array<?xnone>>, !fir.dscope) -> (!fir.box<!fir.array<?xnone>>, !fir.box<!fir.array<?xnone>>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[DSCOPE]] arg {{[0-9]+}} {uniq_name = "_QFtest4Ex"} : (!fir.box<!fir.array<?xnone>>, !fir.dscope) -> (!fir.box<!fir.array<?xnone>>, !fir.box<!fir.array<?xnone>>) ! CHECK: %[[VAL_2:.*]]:2 = hlfir.copy_in %[[VAL_1]]#0 to %[[TMP_BOX:.*]] : (!fir.box<!fir.array<?xnone>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xnone>>>>) -> (!fir.box<!fir.array<?xnone>>, i1) ! CHECK: %[[VAL_3:.*]] = fir.box_addr %[[VAL_2]]#0 : (!fir.box<!fir.array<?xnone>>) -> !fir.ref<!fir.array<?xnone>> ! CHECK: fir.call @_QPs4(%[[VAL_3]]) fastmath<contract> : (!fir.ref<!fir.array<?xnone>>) -> () @@ -142,7 +142,7 @@ end subroutine ! CHECK-LABEL: func.func @_QPtest3b( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.box<!fir.array<?xnone>> {fir.bindc_name = "x", fir.optional}) { ! CHECK: %[[DSCOPE:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[DSCOPE]] {fortran_attrs = #fir.var_attrs<optional>, uniq_name = "_QFtest3bEx"} : (!fir.box<!fir.array<?xnone>>, !fir.dscope) -> (!fir.box<!fir.array<?xnone>>, !fir.box<!fir.array<?xnone>>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[DSCOPE]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<optional>, uniq_name = "_QFtest3bEx"} : (!fir.box<!fir.array<?xnone>>, !fir.dscope) -> (!fir.box<!fir.array<?xnone>>, !fir.box<!fir.array<?xnone>>) ! CHECK: %[[VAL_2:.*]] = fir.is_present %[[VAL_1]]#0 : (!fir.box<!fir.array<?xnone>>) -> i1 ! CHECK: %[[VAL_3:.*]]:3 = fir.if %[[VAL_2]] -> (!fir.box<!fir.array<?xnone>>, i1, !fir.box<!fir.array<?xnone>>) { ! CHECK: %[[VAL_4:.*]]:2 = hlfir.copy_in %[[VAL_1]]#0 to %[[TMP_BOX:.*]] : (!fir.box<!fir.array<?xnone>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xnone>>>>) -> (!fir.box<!fir.array<?xnone>>, i1) @@ -161,7 +161,7 @@ end subroutine ! CHECK-LABEL: func.func @_QPtest4b( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.box<!fir.array<?xnone>> {fir.bindc_name = "x", fir.optional}) { ! CHECK: %[[DSCOPE:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[DSCOPE]] {fortran_attrs = #fir.var_attrs<optional>, uniq_name = "_QFtest4bEx"} : (!fir.box<!fir.array<?xnone>>, !fir.dscope) -> (!fir.box<!fir.array<?xnone>>, !fir.box<!fir.array<?xnone>>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[DSCOPE]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<optional>, uniq_name = "_QFtest4bEx"} : (!fir.box<!fir.array<?xnone>>, !fir.dscope) -> (!fir.box<!fir.array<?xnone>>, !fir.box<!fir.array<?xnone>>) ! CHECK: %[[VAL_2:.*]] = fir.is_present %[[VAL_1]]#0 : (!fir.box<!fir.array<?xnone>>) -> i1 ! CHECK: %[[VAL_3:.*]]:3 = fir.if %[[VAL_2]] -> (!fir.ref<!fir.array<?xnone>>, i1, !fir.box<!fir.array<?xnone>>) { ! CHECK: %[[VAL_4:.*]]:2 = hlfir.copy_in %[[VAL_1]]#0 to %[[TMP_BOX:.*]] : (!fir.box<!fir.array<?xnone>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xnone>>>>) -> (!fir.box<!fir.array<?xnone>>, i1) @@ -181,7 +181,7 @@ end subroutine ! CHECK-LABEL: func.func @_QPtest4c( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.box<!fir.array<?xnone>> {fir.bindc_name = "x", fir.contiguous, fir.optional}) { ! CHECK: %[[DSCOPE:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[DSCOPE]] {fortran_attrs = #fir.var_attrs<contiguous, optional>, uniq_name = "_QFtest4cEx"} : (!fir.box<!fir.array<?xnone>>, !fir.dscope) -> (!fir.box<!fir.array<?xnone>>, !fir.box<!fir.array<?xnone>>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[DSCOPE]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<contiguous, optional>, uniq_name = "_QFtest4cEx"} : (!fir.box<!fir.array<?xnone>>, !fir.dscope) -> (!fir.box<!fir.array<?xnone>>, !fir.box<!fir.array<?xnone>>) ! CHECK: %[[VAL_2:.*]] = fir.is_present %[[VAL_1]]#0 : (!fir.box<!fir.array<?xnone>>) -> i1 ! CHECK: %[[VAL_3:.*]] = fir.if %[[VAL_2]] -> (!fir.ref<!fir.array<?xnone>>) { ! CHECK: %[[VAL_4:.*]] = fir.box_addr %[[VAL_1]]#1 : (!fir.box<!fir.array<?xnone>>) -> !fir.ref<!fir.array<?xnone>> @@ -197,7 +197,7 @@ end subroutine ! CHECK-LABEL: func.func @_QPtest4d( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.box<!fir.array<?xnone>> {fir.bindc_name = "x", fir.contiguous}) { ! CHECK: %[[DSCOPE:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[DSCOPE]] {fortran_attrs = #fir.var_attrs<contiguous>, uniq_name = "_QFtest4dEx"} : (!fir.box<!fir.array<?xnone>>, !fir.dscope) -> (!fir.box<!fir.array<?xnone>>, !fir.box<!fir.array<?xnone>>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[DSCOPE]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<contiguous>, uniq_name = "_QFtest4dEx"} : (!fir.box<!fir.array<?xnone>>, !fir.dscope) -> (!fir.box<!fir.array<?xnone>>, !fir.box<!fir.array<?xnone>>) ! CHECK: %[[VAL_2:.*]] = fir.box_addr %[[VAL_1]]#1 : (!fir.box<!fir.array<?xnone>>) -> !fir.ref<!fir.array<?xnone>> ! CHECK: fir.call @_QPs4d(%[[VAL_2]]) fastmath<contract> : (!fir.ref<!fir.array<?xnone>>) -> () ! CHECK: return @@ -206,7 +206,7 @@ end subroutine ! CHECK-LABEL: func.func @_QPtest5( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.box<!fir.array<?xnone>> {fir.bindc_name = "x"}) { ! CHECK: %[[DSCOPE:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[DSCOPE]] {uniq_name = "_QFtest5Ex"} : (!fir.box<!fir.array<?xnone>>, !fir.dscope) -> (!fir.box<!fir.array<?xnone>>, !fir.box<!fir.array<?xnone>>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[DSCOPE]] arg {{[0-9]+}} {uniq_name = "_QFtest5Ex"} : (!fir.box<!fir.array<?xnone>>, !fir.dscope) -> (!fir.box<!fir.array<?xnone>>, !fir.box<!fir.array<?xnone>>) ! CHECK: %[[VAL_2:.*]] = fir.convert %[[VAL_1]]#0 : (!fir.box<!fir.array<?xnone>>) -> !fir.box<!fir.array<*:none>> ! CHECK: fir.call @_QPs5(%[[VAL_2]]) fastmath<contract> : (!fir.box<!fir.array<*:none>>) -> () ! CHECK: return @@ -215,7 +215,7 @@ end subroutine ! CHECK-LABEL: func.func @_QPtest5b( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.box<!fir.array<?xnone>> {fir.bindc_name = "x", fir.optional}) { ! CHECK: %[[DSCOPE:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[DSCOPE]] {fortran_attrs = #fir.var_attrs<optional>, uniq_name = "_QFtest5bEx"} : (!fir.box<!fir.array<?xnone>>, !fir.dscope) -> (!fir.box<!fir.array<?xnone>>, !fir.box<!fir.array<?xnone>>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[DSCOPE]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<optional>, uniq_name = "_QFtest5bEx"} : (!fir.box<!fir.array<?xnone>>, !fir.dscope) -> (!fir.box<!fir.array<?xnone>>, !fir.box<!fir.array<?xnone>>) ! CHECK: %[[VAL_2:.*]] = fir.is_present %[[VAL_1]]#0 : (!fir.box<!fir.array<?xnone>>) -> i1 ! CHECK: %[[VAL_3:.*]]:3 = fir.if %[[VAL_2]] -> (!fir.box<!fir.array<?xnone>>, i1, !fir.box<!fir.array<?xnone>>) { ! CHECK: %[[VAL_4:.*]]:2 = hlfir.copy_in %[[VAL_1]]#0 to %[[TMP_BOX:.*]] : (!fir.box<!fir.array<?xnone>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xnone>>>>) -> (!fir.box<!fir.array<?xnone>>, i1) diff --git a/flang/test/HLFIR/assumed_shape_with_value_keyword.f90 b/flang/test/HLFIR/assumed_shape_with_value_keyword.f90 index 0f90404..89f8386 100644 --- a/flang/test/HLFIR/assumed_shape_with_value_keyword.f90 +++ b/flang/test/HLFIR/assumed_shape_with_value_keyword.f90 @@ -9,7 +9,7 @@ end ! CHECK-LABEL: func.func @_QPtest_integer_value1( ! CHECK-SAME: %[[ARG0:.*]]: !fir.box<!fir.array<?xi32>> {fir.bindc_name = "x"}) { -! CHECK: %[[VAL_0:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<value>, uniq_name = "_QFtest_integer_value1Ex"} : (!fir.box<!fir.array<?xi32>>, !fir.dscope) -> (!fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>>) +! CHECK: %[[VAL_0:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<value>, uniq_name = "_QFtest_integer_value1Ex"} : (!fir.box<!fir.array<?xi32>>, !fir.dscope) -> (!fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>>) ! CHECK: %[[VAL_1:.*]]:2 = hlfir.copy_in %[[VAL_0]]#0 to %[[TMP_BOX:.*]] : (!fir.box<!fir.array<?xi32>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) -> (!fir.box<!fir.array<?xi32>>, i1) ! CHECK: %[[VAL_2:.*]] = fir.box_addr %[[VAL_1]]#0 : (!fir.box<!fir.array<?xi32>>) -> !fir.ref<!fir.array<?xi32>> ! CHECK: fir.call @_QPinternal_call1(%[[VAL_2]]) fastmath<contract> : (!fir.ref<!fir.array<?xi32>>) -> () @@ -23,7 +23,7 @@ subroutine test_integer_value2(x) end ! CHECK-LABEL: func.func @_QPtest_integer_value2( ! CHECK-SAME: %[[ARG0:.*]]: !fir.box<!fir.array<?x?xi32>> {fir.bindc_name = "x"}) { -! CHECK: %[[VAL_0:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<value>, uniq_name = "_QFtest_integer_value2Ex"} : (!fir.box<!fir.array<?x?xi32>>, !fir.dscope) -> (!fir.box<!fir.array<?x?xi32>>, !fir.box<!fir.array<?x?xi32>>) +! CHECK: %[[VAL_0:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<value>, uniq_name = "_QFtest_integer_value2Ex"} : (!fir.box<!fir.array<?x?xi32>>, !fir.dscope) -> (!fir.box<!fir.array<?x?xi32>>, !fir.box<!fir.array<?x?xi32>>) ! CHECK: %[[VAL_1:.*]]:2 = hlfir.copy_in %[[VAL_0]]#0 to %[[TMP_BOX:.*]] : (!fir.box<!fir.array<?x?xi32>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?x?xi32>>>>) -> (!fir.box<!fir.array<?x?xi32>>, i1) ! CHECK: %[[VAL_2:.*]] = fir.box_addr %[[VAL_1]]#0 : (!fir.box<!fir.array<?x?xi32>>) -> !fir.ref<!fir.array<?x?xi32>> ! CHECK: fir.call @_QPinternal_call2(%[[VAL_2]]) fastmath<contract> : (!fir.ref<!fir.array<?x?xi32>>) -> () @@ -31,13 +31,13 @@ end ! CHECK: return ! CHECK: } -subroutine test_real_value1(x) +subroutine test_real_value1(x) real, value :: x(:) call internal_call3(x) end ! CHECK-LABEL: func.func @_QPtest_real_value1( ! CHECK-SAME: %[[ARG0:.*]]: !fir.box<!fir.array<?xf32>> {fir.bindc_name = "x"}) { -! CHECK: %[[VAL_0:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<value>, uniq_name = "_QFtest_real_value1Ex"} : (!fir.box<!fir.array<?xf32>>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.box<!fir.array<?xf32>>) +! CHECK: %[[VAL_0:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<value>, uniq_name = "_QFtest_real_value1Ex"} : (!fir.box<!fir.array<?xf32>>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.box<!fir.array<?xf32>>) ! CHECK: %[[VAL_1:.*]]:2 = hlfir.copy_in %[[VAL_0]]#0 to %[[TMP_BOX:.*]] : (!fir.box<!fir.array<?xf32>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>) -> (!fir.box<!fir.array<?xf32>>, i1) ! CHECK: %[[VAL_2:.*]] = fir.box_addr %[[VAL_1]]#0 : (!fir.box<!fir.array<?xf32>>) -> !fir.ref<!fir.array<?xf32>> ! CHECK: fir.call @_QPinternal_call3(%[[VAL_2]]) fastmath<contract> : (!fir.ref<!fir.array<?xf32>>) -> () @@ -45,13 +45,13 @@ end ! CHECK: return ! CHECK: } -subroutine test_real_value2(x) +subroutine test_real_value2(x) real, value :: x(:,:) call internal_call4(x) end ! CHECK-LABEL: func.func @_QPtest_real_value2( ! CHECK-SAME: %[[ARG0:.*]]: !fir.box<!fir.array<?x?xf32>> {fir.bindc_name = "x"}) { -! CHECK: %[[VAL_0:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<value>, uniq_name = "_QFtest_real_value2Ex"} : (!fir.box<!fir.array<?x?xf32>>, !fir.dscope) -> (!fir.box<!fir.array<?x?xf32>>, !fir.box<!fir.array<?x?xf32>>) +! CHECK: %[[VAL_0:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<value>, uniq_name = "_QFtest_real_value2Ex"} : (!fir.box<!fir.array<?x?xf32>>, !fir.dscope) -> (!fir.box<!fir.array<?x?xf32>>, !fir.box<!fir.array<?x?xf32>>) ! CHECK: %[[VAL_1:.*]]:2 = hlfir.copy_in %[[VAL_0]]#0 to %[[TMP_BOX:.*]] : (!fir.box<!fir.array<?x?xf32>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?x?xf32>>>>) -> (!fir.box<!fir.array<?x?xf32>>, i1) ! CHECK: %[[VAL_2:.*]] = fir.box_addr %[[VAL_1]]#0 : (!fir.box<!fir.array<?x?xf32>>) -> !fir.ref<!fir.array<?x?xf32>> ! CHECK: fir.call @_QPinternal_call4(%[[VAL_2]]) fastmath<contract> : (!fir.ref<!fir.array<?x?xf32>>) -> () @@ -65,7 +65,7 @@ subroutine test_complex_value1(x) end ! CHECK-LABEL: func.func @_QPtest_complex_value1( ! CHECK-SAME: %[[ARG0:.*]]: !fir.box<!fir.array<?xcomplex<f32>>> {fir.bindc_name = "x"}) { -! CHECK: %[[VAL_0:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<value>, uniq_name = "_QFtest_complex_value1Ex"} : (!fir.box<!fir.array<?xcomplex<f32>>>, !fir.dscope) -> (!fir.box<!fir.array<?xcomplex<f32>>>, !fir.box<!fir.array<?xcomplex<f32>>>) +! CHECK: %[[VAL_0:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<value>, uniq_name = "_QFtest_complex_value1Ex"} : (!fir.box<!fir.array<?xcomplex<f32>>>, !fir.dscope) -> (!fir.box<!fir.array<?xcomplex<f32>>>, !fir.box<!fir.array<?xcomplex<f32>>>) ! CHECK: %[[VAL_1:.*]]:2 = hlfir.copy_in %[[VAL_0]]#0 to %[[TMP_BOX:.*]] : (!fir.box<!fir.array<?xcomplex<f32>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xcomplex<f32>>>>>) -> (!fir.box<!fir.array<?xcomplex<f32>>>, i1) ! CHECK: %[[VAL_2:.*]] = fir.box_addr %[[VAL_1]]#0 : (!fir.box<!fir.array<?xcomplex<f32>>>) -> !fir.ref<!fir.array<?xcomplex<f32>>> ! CHECK: fir.call @_QPinternal_call5(%[[VAL_2]]) fastmath<contract> : (!fir.ref<!fir.array<?xcomplex<f32>>>) -> () @@ -79,7 +79,7 @@ subroutine test_complex_value2(x) end ! CHECK-LABEL: func.func @_QPtest_complex_value2( ! CHECK-SAME: %[[ARG0:.*]]: !fir.box<!fir.array<?x?xcomplex<f32>>> {fir.bindc_name = "x"}) { -! CHECK: %[[VAL_0:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<value>, uniq_name = "_QFtest_complex_value2Ex"} : (!fir.box<!fir.array<?x?xcomplex<f32>>>, !fir.dscope) -> (!fir.box<!fir.array<?x?xcomplex<f32>>>, !fir.box<!fir.array<?x?xcomplex<f32>>>) +! CHECK: %[[VAL_0:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<value>, uniq_name = "_QFtest_complex_value2Ex"} : (!fir.box<!fir.array<?x?xcomplex<f32>>>, !fir.dscope) -> (!fir.box<!fir.array<?x?xcomplex<f32>>>, !fir.box<!fir.array<?x?xcomplex<f32>>>) ! CHECK: %[[VAL_1:.*]]:2 = hlfir.copy_in %[[VAL_0]]#0 to %[[TMP_BOX:.*]] : (!fir.box<!fir.array<?x?xcomplex<f32>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?x?xcomplex<f32>>>>>) -> (!fir.box<!fir.array<?x?xcomplex<f32>>>, i1) ! CHECK: %[[VAL_2:.*]] = fir.box_addr %[[VAL_1]]#0 : (!fir.box<!fir.array<?x?xcomplex<f32>>>) -> !fir.ref<!fir.array<?x?xcomplex<f32>>> ! CHECK: fir.call @_QPinternal_call6(%[[VAL_2]]) fastmath<contract> : (!fir.ref<!fir.array<?x?xcomplex<f32>>>) -> () @@ -95,7 +95,7 @@ subroutine test_optional1(x) end ! CHECK-LABEL: func.func @_QPtest_optional1( ! CHECK-SAME: %[[ARG0:.*]]: !fir.box<!fir.array<?xf32>> {fir.bindc_name = "x", fir.optional}) { -! CHECK: %[[VAL_0:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<optional, value>, uniq_name = "_QFtest_optional1Ex"} : (!fir.box<!fir.array<?xf32>>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.box<!fir.array<?xf32>>) +! CHECK: %[[VAL_0:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<optional, value>, uniq_name = "_QFtest_optional1Ex"} : (!fir.box<!fir.array<?xf32>>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.box<!fir.array<?xf32>>) ! CHECK: %[[VAL_1:.*]] = fir.is_present %[[VAL_0]]#1 : (!fir.box<!fir.array<?xf32>>) -> i1 ! CHECK: fir.if %[[VAL_1:.*]] { ! CHECK: %[[VAL_2:.*]]:2 = hlfir.copy_in %[[VAL_0]]#0 to %[[TMP_BOX:.*]] : (!fir.box<!fir.array<?xf32>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>) -> (!fir.box<!fir.array<?xf32>>, i1) @@ -114,7 +114,7 @@ subroutine test_optional2(x) end ! CHECK-LABEL: func.func @_QPtest_optional2( ! CHECK-SAME: %[[ARG0:.*]]: !fir.box<!fir.array<?x?xf32>> {fir.bindc_name = "x", fir.optional}) { -! CHECK: %[[VAL_0:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<optional, value>, uniq_name = "_QFtest_optional2Ex"} : (!fir.box<!fir.array<?x?xf32>>, !fir.dscope) -> (!fir.box<!fir.array<?x?xf32>>, !fir.box<!fir.array<?x?xf32>>) +! CHECK: %[[VAL_0:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<optional, value>, uniq_name = "_QFtest_optional2Ex"} : (!fir.box<!fir.array<?x?xf32>>, !fir.dscope) -> (!fir.box<!fir.array<?x?xf32>>, !fir.box<!fir.array<?x?xf32>>) ! CHECK: %[[VAL_1:.*]] = fir.is_present %[[VAL_0]]#1 : (!fir.box<!fir.array<?x?xf32>>) -> i1 ! CHECK: fir.if %[[VAL_1:.*]] { ! CHECK: %[[VAL_2:.*]]:2 = hlfir.copy_in %[[VAL_0]]#0 to %[[TMP_BOX:.*]] : (!fir.box<!fir.array<?x?xf32>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?x?xf32>>>>) -> (!fir.box<!fir.array<?x?xf32>>, i1) @@ -133,7 +133,7 @@ subroutine test_optional3(x) end ! CHECK-LABEL: func.func @_QPtest_optional3( ! CHECK-SAME: %[[ARG0:.*]]: !fir.box<!fir.array<?xf32>> {fir.bindc_name = "x", fir.optional}) { -! CHECK: %[[VAL_0:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<optional, value>, uniq_name = "_QFtest_optional3Ex"} : (!fir.box<!fir.array<?xf32>>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.box<!fir.array<?xf32>>) +! CHECK: %[[VAL_0:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<optional, value>, uniq_name = "_QFtest_optional3Ex"} : (!fir.box<!fir.array<?xf32>>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.box<!fir.array<?xf32>>) ! CHECK: %[[VAL_1:.*]] = fir.is_present %[[VAL_0]]#1 : (!fir.box<!fir.array<?xf32>>) -> i1 ! CHECK: cf.cond_br %[[VAL_1]], ^bb1, ^bb2 ! CHECK: b1: // pred: ^bb0 diff --git a/flang/test/HLFIR/boxchar_emboxing.f90 b/flang/test/HLFIR/boxchar_emboxing.f90 index b80ff98..da61e36 100644 --- a/flang/test/HLFIR/boxchar_emboxing.f90 +++ b/flang/test/HLFIR/boxchar_emboxing.f90 @@ -2,7 +2,7 @@ ! CHECK-LABEL: func.func @_QPtest1( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.class<none> {fir.bindc_name = "x"}) { -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFtest1Ex"} : (!fir.class<none>, !fir.dscope) -> (!fir.class<none>, !fir.class<none>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFtest1Ex"} : (!fir.class<none>, !fir.dscope) -> (!fir.class<none>, !fir.class<none>) ! CHECK: fir.select_type %[[VAL_1]]#1 : !fir.class<none> [#fir.type_is<!fir.char<1,?>>, ^bb1, unit, ^bb2] ! CHECK: ^bb1: ! CHECK: %[[VAL_2:.*]] = fir.box_addr %[[VAL_1]]#1 : (!fir.class<none>) -> !fir.ref<!fir.char<1,?>> @@ -44,7 +44,7 @@ end subroutine test1 ! CHECK-LABEL: func.func @_QPtest2( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.class<!fir.array<10xnone>> {fir.bindc_name = "x"}) { -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFtest2Ex"} : (!fir.class<!fir.array<10xnone>>, !fir.dscope) -> (!fir.class<!fir.array<10xnone>>, !fir.class<!fir.array<10xnone>>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFtest2Ex"} : (!fir.class<!fir.array<10xnone>>, !fir.dscope) -> (!fir.class<!fir.array<10xnone>>, !fir.class<!fir.array<10xnone>>) ! CHECK: fir.select_type %[[VAL_1]]#1 : !fir.class<!fir.array<10xnone>> [#fir.type_is<!fir.char<1,?>>, ^bb1, unit, ^bb2] ! CHECK: ^bb1: ! CHECK: %[[VAL_2:.*]] = fir.convert %[[VAL_1]]#1 : (!fir.class<!fir.array<10xnone>>) -> !fir.box<!fir.array<10x!fir.char<1,?>>> diff --git a/flang/test/HLFIR/c_ptr_byvalue.f90 b/flang/test/HLFIR/c_ptr_byvalue.f90 index f39059a8..651c37b 100644 --- a/flang/test/HLFIR/c_ptr_byvalue.f90 +++ b/flang/test/HLFIR/c_ptr_byvalue.f90 @@ -22,7 +22,7 @@ end ! CHECK-LABEL: func.func @_QPtest2( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>> {fir.bindc_name = "cptr"}) { ! CHECK: %[[DSCOPE:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_97:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[DSCOPE]] {uniq_name = "_QFtest2Ecptr"} : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>, !fir.dscope) -> (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>, !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>) +! CHECK: %[[VAL_97:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[DSCOPE]] arg {{[0-9]+}} {uniq_name = "_QFtest2Ecptr"} : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>, !fir.dscope) -> (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>, !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>) ! CHECK: %[[VAL_99:.*]] = fir.coordinate_of %[[VAL_97]]#0, __address : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>) -> !fir.ref<i64> ! CHECK: %[[VAL_100:.*]] = fir.load %[[VAL_99]] : !fir.ref<i64> ! CHECK: %[[VAL_101:.*]] = fir.convert %[[VAL_100]] : (i64) -> !fir.ref<i64> diff --git a/flang/test/HLFIR/call_with_poly_dummy.f90 b/flang/test/HLFIR/call_with_poly_dummy.f90 index 93cd410..9b74bfb 100644 --- a/flang/test/HLFIR/call_with_poly_dummy.f90 +++ b/flang/test/HLFIR/call_with_poly_dummy.f90 @@ -23,7 +23,7 @@ end subroutine test1 ! CHECK-LABEL: func.func @_QPtest2( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<f32> {fir.bindc_name = "x"}) { ! CHECK: %[[DSCOPE:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[DSCOPE]] {uniq_name = "_QFtest2Ex"} : (!fir.ref<f32>, !fir.dscope) -> (!fir.ref<f32>, !fir.ref<f32>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[DSCOPE]] arg {{[0-9]+}} {uniq_name = "_QFtest2Ex"} : (!fir.ref<f32>, !fir.dscope) -> (!fir.ref<f32>, !fir.ref<f32>) ! CHECK: %[[VAL_2:.*]] = fir.load %[[VAL_1]]#0 : !fir.ref<f32> ! CHECK: %[[VAL_3:.*]] = arith.constant 0.000000e+00 : f32 ! CHECK: %[[VAL_4:.*]] = arith.cmpf oeq, %[[VAL_2]], %[[VAL_3]] {{.*}} : f32 diff --git a/flang/test/HLFIR/inline-hlfir-copy-in.fir b/flang/test/HLFIR/inline-hlfir-copy-in.fir index f3c4b38..f1da1da 100644 --- a/flang/test/HLFIR/inline-hlfir-copy-in.fir +++ b/flang/test/HLFIR/inline-hlfir-copy-in.fir @@ -75,7 +75,7 @@ func.func private @_test_inline_copy_in(%arg0: !fir.box<!fir.array<?x?x?xf64>> { // CHECK: %[[VAL_22:.*]] = fir.box_addr %[[VAL_21:.*]]#0 : (!fir.box<!fir.array<?xf64>>) -> !fir.ref<!fir.array<?xf64>> // CHECK: %[[VAL_23:.*]]:3 = hlfir.associate %[[VAL_5:.*]] {adapt.valuebyref} : (i32) -> (!fir.ref<i32>, !fir.ref<i32>, i1) // CHECK: fir.call @_QFPsb(%[[VAL_22:.*]], %[[VAL_23:.*]]#0) fastmath<contract> : (!fir.ref<!fir.array<?xf64>>, !fir.ref<i32>) -> () -// CHECK: hlfir.copy_out %16, %15#1 : (!fir.ref<!fir.box<!fir.array<?xf64>>>, i1) -> () +// CHECK: hlfir.copy_out %{{.*}}, %[[VAL_21:.*]]#1 : (!fir.ref<!fir.box<!fir.array<?xf64>>>, i1) -> () // CHECK: hlfir.end_associate %[[VAL_23:.*]]#1, %[[VAL_23:.*]]#2 : !fir.ref<i32>, i1 // CHECK: return // CHECK: } diff --git a/flang/test/HLFIR/optional_dummy.f90 b/flang/test/HLFIR/optional_dummy.f90 index ecb14f6..86ddeb9 100644 --- a/flang/test/HLFIR/optional_dummy.f90 +++ b/flang/test/HLFIR/optional_dummy.f90 @@ -5,7 +5,7 @@ ! CHECK-LABEL: func.func @_QPtest( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.box<!fir.array<?xi32>> {fir.bindc_name = "ext_buf", fir.contiguous, fir.optional}) { -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<contiguous, optional>, uniq_name = "_QFtestEext_buf"} : (!fir.box<!fir.array<?xi32>>, !fir.dscope) -> (!fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<contiguous, optional>, uniq_name = "_QFtestEext_buf"} : (!fir.box<!fir.array<?xi32>>, !fir.dscope) -> (!fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>>) ! CHECK: %[[VAL_2:.*]] = fir.is_present %[[VAL_1]]#1 : (!fir.box<!fir.array<?xi32>>) -> i1 ! CHECK: cf.cond_br %[[VAL_2]], ^bb1, ^bb2 ! CHECK: ^bb1: diff --git a/flang/test/HLFIR/order_assignments/forall-proc-pointer-assignment-scheduling-character.f90 b/flang/test/HLFIR/order_assignments/forall-proc-pointer-assignment-scheduling-character.f90 index d2d1939..ff7f70b 100644 --- a/flang/test/HLFIR/order_assignments/forall-proc-pointer-assignment-scheduling-character.f90 +++ b/flang/test/HLFIR/order_assignments/forall-proc-pointer-assignment-scheduling-character.f90 @@ -44,7 +44,7 @@ contains integer pure function decode(c) character(2), intent(in) :: c - decode = modulo(iachar(c(2:2))-49,10)+1 + decode = modulo(iachar(c(2:2))-49,10)+1 end function subroutine test_no_conflict(x) diff --git a/flang/test/HLFIR/simplify-hlfir-intrinsics-product.fir b/flang/test/HLFIR/simplify-hlfir-intrinsics-product.fir new file mode 100644 index 0000000..6d6b15f --- /dev/null +++ b/flang/test/HLFIR/simplify-hlfir-intrinsics-product.fir @@ -0,0 +1,457 @@ +// RUN: fir-opt --simplify-hlfir-intrinsics %s | FileCheck %s + +// box with known extents +func.func @product_box_known_extents(%arg0: !fir.box<!fir.array<2x3xi32>>) -> !hlfir.expr<2xi32> { + %cst = arith.constant 2 : i32 + %res = hlfir.product %arg0 dim %cst : (!fir.box<!fir.array<2x3xi32>>, i32) -> !hlfir.expr<2xi32> + return %res : !hlfir.expr<2xi32> +} +// CHECK-LABEL: func.func @product_box_known_extents( +// CHECK-SAME: %[[ARG0:.*]]: !fir.box<!fir.array<2x3xi32>>) -> !hlfir.expr<2xi32> { +// CHECK: %[[CONSTANT_0:.*]] = arith.constant 0 : index +// CHECK: %[[CONSTANT_1:.*]] = arith.constant 1 : index +// CHECK: %[[CONSTANT_2:.*]] = arith.constant 1 : i32 +// CHECK: %[[CONSTANT_3:.*]] = arith.constant 2 : index +// CHECK: %[[CONSTANT_4:.*]] = arith.constant 3 : index +// CHECK: %[[SHAPE_0:.*]] = fir.shape %[[CONSTANT_3]] : (index) -> !fir.shape<1> +// CHECK: %[[ELEMENTAL_0:.*]] = hlfir.elemental %[[SHAPE_0]] unordered : (!fir.shape<1>) -> !hlfir.expr<2xi32> { +// CHECK: ^bb0(%[[VAL_0:.*]]: index): +// CHECK: %[[DO_LOOP_0:.*]] = fir.do_loop %[[VAL_1:.*]] = %[[CONSTANT_1]] to %[[CONSTANT_4]] step %[[CONSTANT_1]] unordered iter_args(%[[VAL_2:.*]] = %[[CONSTANT_2]]) -> (i32) { +// CHECK: %[[BOX_DIMS_0:.*]]:3 = fir.box_dims %[[ARG0]], %[[CONSTANT_0]] : (!fir.box<!fir.array<2x3xi32>>, index) -> (index, index, index) +// CHECK: %[[BOX_DIMS_1:.*]]:3 = fir.box_dims %[[ARG0]], %[[CONSTANT_1]] : (!fir.box<!fir.array<2x3xi32>>, index) -> (index, index, index) +// CHECK: %[[SUBI_0:.*]] = arith.subi %[[BOX_DIMS_0]]#0, %[[CONSTANT_1]] : index +// CHECK: %[[ADDI_0:.*]] = arith.addi %[[VAL_0]], %[[SUBI_0]] : index +// CHECK: %[[SUBI_1:.*]] = arith.subi %[[BOX_DIMS_1]]#0, %[[CONSTANT_1]] : index +// CHECK: %[[ADDI_1:.*]] = arith.addi %[[VAL_1]], %[[SUBI_1]] : index +// CHECK: %[[DESIGNATE_0:.*]] = hlfir.designate %[[ARG0]] (%[[ADDI_0]], %[[ADDI_1]]) : (!fir.box<!fir.array<2x3xi32>>, index, index) -> !fir.ref<i32> +// CHECK: %[[LOAD_0:.*]] = fir.load %[[DESIGNATE_0]] : !fir.ref<i32> +// CHECK: %[[MULI_0:.*]] = arith.muli %[[VAL_2]], %[[LOAD_0]] : i32 +// CHECK: fir.result %[[MULI_0]] : i32 +// CHECK: } +// CHECK: hlfir.yield_element %[[DO_LOOP_0]] : i32 +// CHECK: } +// CHECK: return %[[ELEMENTAL_0]] : !hlfir.expr<2xi32> +// CHECK: } + +// expr with known extents +func.func @product_expr_known_extents(%arg0: !hlfir.expr<2x3xi32>) -> !hlfir.expr<3xi32> { + %cst = arith.constant 1 : i32 + %res = hlfir.product %arg0 dim %cst : (!hlfir.expr<2x3xi32>, i32) -> !hlfir.expr<3xi32> + return %res : !hlfir.expr<3xi32> +} +// CHECK-LABEL: func.func @product_expr_known_extents( +// CHECK-SAME: %[[ARG0:.*]]: !hlfir.expr<2x3xi32>) -> !hlfir.expr<3xi32> { +// CHECK: %[[CONSTANT_0:.*]] = arith.constant 1 : index +// CHECK: %[[CONSTANT_1:.*]] = arith.constant 1 : i32 +// CHECK: %[[CONSTANT_2:.*]] = arith.constant 2 : index +// CHECK: %[[CONSTANT_3:.*]] = arith.constant 3 : index +// CHECK: %[[SHAPE_0:.*]] = fir.shape %[[CONSTANT_3]] : (index) -> !fir.shape<1> +// CHECK: %[[ELEMENTAL_0:.*]] = hlfir.elemental %[[SHAPE_0]] unordered : (!fir.shape<1>) -> !hlfir.expr<3xi32> { +// CHECK: ^bb0(%[[VAL_0:.*]]: index): +// CHECK: %[[DO_LOOP_0:.*]] = fir.do_loop %[[VAL_1:.*]] = %[[CONSTANT_0]] to %[[CONSTANT_2]] step %[[CONSTANT_0]] unordered iter_args(%[[VAL_2:.*]] = %[[CONSTANT_1]]) -> (i32) { +// CHECK: %[[APPLY_0:.*]] = hlfir.apply %[[ARG0]], %[[VAL_1]], %[[VAL_0]] : (!hlfir.expr<2x3xi32>, index, index) -> i32 +// CHECK: %[[MULI_0:.*]] = arith.muli %[[VAL_2]], %[[APPLY_0]] : i32 +// CHECK: fir.result %[[MULI_0]] : i32 +// CHECK: } +// CHECK: hlfir.yield_element %[[DO_LOOP_0]] : i32 +// CHECK: } +// CHECK: return %[[ELEMENTAL_0]] : !hlfir.expr<3xi32> +// CHECK: } + + +// box with unknown extent +func.func @product_box_unknown_extent1(%arg0: !fir.box<!fir.array<?x3xcomplex<f64>>>) -> !hlfir.expr<3xcomplex<f64>> { + %cst = arith.constant 1 : i32 + %res = hlfir.product %arg0 dim %cst : (!fir.box<!fir.array<?x3xcomplex<f64>>>, i32) -> !hlfir.expr<3xcomplex<f64>> + return %res : !hlfir.expr<3xcomplex<f64>> +} +// CHECK-LABEL: func.func @product_box_unknown_extent1( +// CHECK-SAME: %[[ARG0:.*]]: !fir.box<!fir.array<?x3xcomplex<f64>>>) -> !hlfir.expr<3xcomplex<f64>> { +// CHECK: %[[CONSTANT_0:.*]] = arith.constant 1 : index +// CHECK: %[[CONSTANT_1:.*]] = arith.constant 0.000000e+00 : f64 +// CHECK: %[[CONSTANT_2:.*]] = arith.constant 1.000000e+00 : f64 +// CHECK: %[[CONSTANT_3:.*]] = arith.constant 3 : index +// CHECK: %[[CONSTANT_4:.*]] = arith.constant 0 : index +// CHECK: %[[BOX_DIMS_0:.*]]:3 = fir.box_dims %[[ARG0]], %[[CONSTANT_4]] : (!fir.box<!fir.array<?x3xcomplex<f64>>>, index) -> (index, index, index) +// CHECK: %[[SHAPE_0:.*]] = fir.shape %[[CONSTANT_3]] : (index) -> !fir.shape<1> +// CHECK: %[[ELEMENTAL_0:.*]] = hlfir.elemental %[[SHAPE_0]] unordered : (!fir.shape<1>) -> !hlfir.expr<3xcomplex<f64>> { +// CHECK: ^bb0(%[[VAL_0:.*]]: index): +// CHECK: %[[UNDEFINED_0:.*]] = fir.undefined complex<f64> +// CHECK: %[[INSERT_VALUE_0:.*]] = fir.insert_value %[[UNDEFINED_0]], %[[CONSTANT_2]], [0 : index] : (complex<f64>, f64) -> complex<f64> +// CHECK: %[[INSERT_VALUE_1:.*]] = fir.insert_value %[[INSERT_VALUE_0]], %[[CONSTANT_1]], [1 : index] : (complex<f64>, f64) -> complex<f64> +// CHECK: %[[DO_LOOP_0:.*]] = fir.do_loop %[[VAL_1:.*]] = %[[CONSTANT_0]] to %[[BOX_DIMS_0]]#1 step %[[CONSTANT_0]] iter_args(%[[VAL_2:.*]] = %[[INSERT_VALUE_1]]) -> (complex<f64>) { +// CHECK: %[[BOX_DIMS_1:.*]]:3 = fir.box_dims %[[ARG0]], %[[CONSTANT_4]] : (!fir.box<!fir.array<?x3xcomplex<f64>>>, index) -> (index, index, index) +// CHECK: %[[BOX_DIMS_2:.*]]:3 = fir.box_dims %[[ARG0]], %[[CONSTANT_0]] : (!fir.box<!fir.array<?x3xcomplex<f64>>>, index) -> (index, index, index) +// CHECK: %[[SUBI_0:.*]] = arith.subi %[[BOX_DIMS_1]]#0, %[[CONSTANT_0]] : index +// CHECK: %[[ADDI_0:.*]] = arith.addi %[[VAL_1]], %[[SUBI_0]] : index +// CHECK: %[[SUBI_1:.*]] = arith.subi %[[BOX_DIMS_2]]#0, %[[CONSTANT_0]] : index +// CHECK: %[[ADDI_1:.*]] = arith.addi %[[VAL_0]], %[[SUBI_1]] : index +// CHECK: %[[DESIGNATE_0:.*]] = hlfir.designate %[[ARG0]] (%[[ADDI_0]], %[[ADDI_1]]) : (!fir.box<!fir.array<?x3xcomplex<f64>>>, index, index) -> !fir.ref<complex<f64>> +// CHECK: %[[LOAD_0:.*]] = fir.load %[[DESIGNATE_0]] : !fir.ref<complex<f64>> +// CHECK: %[[MULC_0:.*]] = fir.mulc %[[VAL_2]], %[[LOAD_0]] : complex<f64> +// CHECK: fir.result %[[MULC_0]] : complex<f64> +// CHECK: } +// CHECK: hlfir.yield_element %[[DO_LOOP_0]] : complex<f64> +// CHECK: } +// CHECK: return %[[ELEMENTAL_0]] : !hlfir.expr<3xcomplex<f64>> +// CHECK: } + + +func.func @product_box_unknown_extent2(%arg0: !fir.box<!fir.array<?x3xcomplex<f64>>>) -> !hlfir.expr<?xcomplex<f64>> { + %cst = arith.constant 2 : i32 + %res = hlfir.product %arg0 dim %cst : (!fir.box<!fir.array<?x3xcomplex<f64>>>, i32) -> !hlfir.expr<?xcomplex<f64>> + return %res : !hlfir.expr<?xcomplex<f64>> +} +// CHECK-LABEL: func.func @product_box_unknown_extent2( +// CHECK-SAME: %[[ARG0:.*]]: !fir.box<!fir.array<?x3xcomplex<f64>>>) -> !hlfir.expr<?xcomplex<f64>> { +// CHECK: %[[CONSTANT_0:.*]] = arith.constant 1 : index +// CHECK: %[[CONSTANT_1:.*]] = arith.constant 0.000000e+00 : f64 +// CHECK: %[[CONSTANT_2:.*]] = arith.constant 1.000000e+00 : f64 +// CHECK: %[[CONSTANT_3:.*]] = arith.constant 3 : index +// CHECK: %[[CONSTANT_4:.*]] = arith.constant 0 : index +// CHECK: %[[BOX_DIMS_0:.*]]:3 = fir.box_dims %[[ARG0]], %[[CONSTANT_4]] : (!fir.box<!fir.array<?x3xcomplex<f64>>>, index) -> (index, index, index) +// CHECK: %[[SHAPE_0:.*]] = fir.shape %[[BOX_DIMS_0]]#1 : (index) -> !fir.shape<1> +// CHECK: %[[ELEMENTAL_0:.*]] = hlfir.elemental %[[SHAPE_0]] unordered : (!fir.shape<1>) -> !hlfir.expr<?xcomplex<f64>> { +// CHECK: ^bb0(%[[VAL_0:.*]]: index): +// CHECK: %[[UNDEFINED_0:.*]] = fir.undefined complex<f64> +// CHECK: %[[INSERT_VALUE_0:.*]] = fir.insert_value %[[UNDEFINED_0]], %[[CONSTANT_2]], [0 : index] : (complex<f64>, f64) -> complex<f64> +// CHECK: %[[INSERT_VALUE_1:.*]] = fir.insert_value %[[INSERT_VALUE_0]], %[[CONSTANT_1]], [1 : index] : (complex<f64>, f64) -> complex<f64> +// CHECK: %[[DO_LOOP_0:.*]] = fir.do_loop %[[VAL_1:.*]] = %[[CONSTANT_0]] to %[[CONSTANT_3]] step %[[CONSTANT_0]] iter_args(%[[VAL_2:.*]] = %[[INSERT_VALUE_1]]) -> (complex<f64>) { +// CHECK: %[[BOX_DIMS_1:.*]]:3 = fir.box_dims %[[ARG0]], %[[CONSTANT_4]] : (!fir.box<!fir.array<?x3xcomplex<f64>>>, index) -> (index, index, index) +// CHECK: %[[BOX_DIMS_2:.*]]:3 = fir.box_dims %[[ARG0]], %[[CONSTANT_0]] : (!fir.box<!fir.array<?x3xcomplex<f64>>>, index) -> (index, index, index) +// CHECK: %[[SUBI_0:.*]] = arith.subi %[[BOX_DIMS_1]]#0, %[[CONSTANT_0]] : index +// CHECK: %[[ADDI_0:.*]] = arith.addi %[[VAL_0]], %[[SUBI_0]] : index +// CHECK: %[[SUBI_1:.*]] = arith.subi %[[BOX_DIMS_2]]#0, %[[CONSTANT_0]] : index +// CHECK: %[[ADDI_1:.*]] = arith.addi %[[VAL_1]], %[[SUBI_1]] : index +// CHECK: %[[DESIGNATE_0:.*]] = hlfir.designate %[[ARG0]] (%[[ADDI_0]], %[[ADDI_1]]) : (!fir.box<!fir.array<?x3xcomplex<f64>>>, index, index) -> !fir.ref<complex<f64>> +// CHECK: %[[LOAD_0:.*]] = fir.load %[[DESIGNATE_0]] : !fir.ref<complex<f64>> +// CHECK: %[[MULC_0:.*]] = fir.mulc %[[VAL_2]], %[[LOAD_0]] : complex<f64> +// CHECK: fir.result %[[MULC_0]] : complex<f64> +// CHECK: } +// CHECK: hlfir.yield_element %[[DO_LOOP_0]] : complex<f64> +// CHECK: } +// CHECK: return %[[ELEMENTAL_0]] : !hlfir.expr<?xcomplex<f64>> +// CHECK: } + + +// expr with unknown extent +func.func @product_expr_unknown_extent1(%arg0: !hlfir.expr<?x3xf32>) -> !hlfir.expr<3xf32> { + %cst = arith.constant 1 : i32 + %res = hlfir.product %arg0 dim %cst : (!hlfir.expr<?x3xf32>, i32) -> !hlfir.expr<3xf32> + return %res : !hlfir.expr<3xf32> +} +// CHECK-LABEL: func.func @product_expr_unknown_extent1( +// CHECK-SAME: %[[ARG0:.*]]: !hlfir.expr<?x3xf32>) -> !hlfir.expr<3xf32> { +// CHECK: %[[CONSTANT_0:.*]] = arith.constant 1 : index +// CHECK: %[[CONSTANT_1:.*]] = arith.constant 1.000000e+00 : f32 +// CHECK: %[[CONSTANT_2:.*]] = arith.constant 3 : index +// CHECK: %[[SHAPE_OF_0:.*]] = hlfir.shape_of %[[ARG0]] : (!hlfir.expr<?x3xf32>) -> !fir.shape<2> +// CHECK: %[[GET_EXTENT_0:.*]] = hlfir.get_extent %[[SHAPE_OF_0]] {dim = 0 : index} : (!fir.shape<2>) -> index +// CHECK: %[[SHAPE_0:.*]] = fir.shape %[[CONSTANT_2]] : (index) -> !fir.shape<1> +// CHECK: %[[ELEMENTAL_0:.*]] = hlfir.elemental %[[SHAPE_0]] unordered : (!fir.shape<1>) -> !hlfir.expr<3xf32> { +// CHECK: ^bb0(%[[VAL_0:.*]]: index): +// CHECK: %[[DO_LOOP_0:.*]] = fir.do_loop %[[VAL_1:.*]] = %[[CONSTANT_0]] to %[[GET_EXTENT_0]] step %[[CONSTANT_0]] iter_args(%[[VAL_2:.*]] = %[[CONSTANT_1]]) -> (f32) { +// CHECK: %[[APPLY_0:.*]] = hlfir.apply %[[ARG0]], %[[VAL_1]], %[[VAL_0]] : (!hlfir.expr<?x3xf32>, index, index) -> f32 +// CHECK: %[[MULF_0:.*]] = arith.mulf %[[VAL_2]], %[[APPLY_0]] : f32 +// CHECK: fir.result %[[MULF_0]] : f32 +// CHECK: } +// CHECK: hlfir.yield_element %[[DO_LOOP_0]] : f32 +// CHECK: } +// CHECK: return %[[ELEMENTAL_0]] : !hlfir.expr<3xf32> +// CHECK: } + + +func.func @product_expr_unknown_extent2(%arg0: !hlfir.expr<?x3xf32>) -> !hlfir.expr<?xf32> { + %cst = arith.constant 2 : i32 + %res = hlfir.product %arg0 dim %cst : (!hlfir.expr<?x3xf32>, i32) -> !hlfir.expr<?xf32> + return %res : !hlfir.expr<?xf32> +} +// CHECK-LABEL: func.func @product_expr_unknown_extent2( +// CHECK-SAME: %[[ARG0:.*]]: !hlfir.expr<?x3xf32>) -> !hlfir.expr<?xf32> { +// CHECK: %[[CONSTANT_0:.*]] = arith.constant 1 : index +// CHECK: %[[CONSTANT_1:.*]] = arith.constant 1.000000e+00 : f32 +// CHECK: %[[CONSTANT_2:.*]] = arith.constant 3 : index +// CHECK: %[[SHAPE_OF_0:.*]] = hlfir.shape_of %[[ARG0]] : (!hlfir.expr<?x3xf32>) -> !fir.shape<2> +// CHECK: %[[GET_EXTENT_0:.*]] = hlfir.get_extent %[[SHAPE_OF_0]] {dim = 0 : index} : (!fir.shape<2>) -> index +// CHECK: %[[SHAPE_0:.*]] = fir.shape %[[GET_EXTENT_0]] : (index) -> !fir.shape<1> +// CHECK: %[[ELEMENTAL_0:.*]] = hlfir.elemental %[[SHAPE_0]] unordered : (!fir.shape<1>) -> !hlfir.expr<?xf32> { +// CHECK: ^bb0(%[[VAL_0:.*]]: index): +// CHECK: %[[DO_LOOP_0:.*]] = fir.do_loop %[[VAL_1:.*]] = %[[CONSTANT_0]] to %[[CONSTANT_2]] step %[[CONSTANT_0]] iter_args(%[[VAL_2:.*]] = %[[CONSTANT_1]]) -> (f32) { +// CHECK: %[[APPLY_0:.*]] = hlfir.apply %[[ARG0]], %[[VAL_0]], %[[VAL_1]] : (!hlfir.expr<?x3xf32>, index, index) -> f32 +// CHECK: %[[MULF_0:.*]] = arith.mulf %[[VAL_2]], %[[APPLY_0]] : f32 +// CHECK: fir.result %[[MULF_0]] : f32 +// CHECK: } +// CHECK: hlfir.yield_element %[[DO_LOOP_0]] : f32 +// CHECK: } +// CHECK: return %[[ELEMENTAL_0]] : !hlfir.expr<?xf32> +// CHECK: } + +// scalar mask +func.func @product_scalar_mask(%arg0: !hlfir.expr<?x3xf32>, %mask: !fir.ref<!fir.logical<1>>) -> !hlfir.expr<3xf32> { + %cst = arith.constant 1 : i32 + %res = hlfir.product %arg0 dim %cst mask %mask : (!hlfir.expr<?x3xf32>, i32, !fir.ref<!fir.logical<1>>) -> !hlfir.expr<3xf32> + return %res : !hlfir.expr<3xf32> +} +// CHECK-LABEL: func.func @product_scalar_mask( +// CHECK-SAME: %[[ARG0:.*]]: !hlfir.expr<?x3xf32>, +// CHECK-SAME: %[[ARG1:.*]]: !fir.ref<!fir.logical<1>>) -> !hlfir.expr<3xf32> { +// CHECK: %[[CONSTANT_0:.*]] = arith.constant 1 : index +// CHECK: %[[CONSTANT_1:.*]] = arith.constant 1.000000e+00 : f32 +// CHECK: %[[CONSTANT_2:.*]] = arith.constant 3 : index +// CHECK: %[[SHAPE_OF_0:.*]] = hlfir.shape_of %[[ARG0]] : (!hlfir.expr<?x3xf32>) -> !fir.shape<2> +// CHECK: %[[GET_EXTENT_0:.*]] = hlfir.get_extent %[[SHAPE_OF_0]] {dim = 0 : index} : (!fir.shape<2>) -> index +// CHECK: %[[SHAPE_0:.*]] = fir.shape %[[CONSTANT_2]] : (index) -> !fir.shape<1> +// CHECK: %[[LOAD_0:.*]] = fir.load %[[ARG1]] : !fir.ref<!fir.logical<1>> +// CHECK: %[[ELEMENTAL_0:.*]] = hlfir.elemental %[[SHAPE_0]] unordered : (!fir.shape<1>) -> !hlfir.expr<3xf32> { +// CHECK: ^bb0(%[[VAL_0:.*]]: index): +// CHECK: %[[DO_LOOP_0:.*]] = fir.do_loop %[[VAL_1:.*]] = %[[CONSTANT_0]] to %[[GET_EXTENT_0]] step %[[CONSTANT_0]] iter_args(%[[VAL_2:.*]] = %[[CONSTANT_1]]) -> (f32) { +// CHECK: %[[CONVERT_0:.*]] = fir.convert %[[LOAD_0]] : (!fir.logical<1>) -> i1 +// CHECK: %[[IF_0:.*]] = fir.if %[[CONVERT_0]] -> (f32) { +// CHECK: %[[APPLY_0:.*]] = hlfir.apply %[[ARG0]], %[[VAL_1]], %[[VAL_0]] : (!hlfir.expr<?x3xf32>, index, index) -> f32 +// CHECK: %[[MULF_0:.*]] = arith.mulf %[[VAL_2]], %[[APPLY_0]] : f32 +// CHECK: fir.result %[[MULF_0]] : f32 +// CHECK: } else { +// CHECK: fir.result %[[VAL_2]] : f32 +// CHECK: } +// CHECK: fir.result %[[IF_0]] : f32 +// CHECK: } +// CHECK: hlfir.yield_element %[[DO_LOOP_0]] : f32 +// CHECK: } +// CHECK: return %[[ELEMENTAL_0]] : !hlfir.expr<3xf32> +// CHECK: } + +// scalar boxed mask +func.func @product_scalar_boxed_mask(%arg0: !hlfir.expr<?x3xf32>, %mask: !fir.box<!fir.logical<1>>) -> !hlfir.expr<3xf32> { + %cst = arith.constant 1 : i32 + %res = hlfir.product %arg0 dim %cst mask %mask : (!hlfir.expr<?x3xf32>, i32, !fir.box<!fir.logical<1>>) -> !hlfir.expr<3xf32> + return %res : !hlfir.expr<3xf32> +} +// CHECK-LABEL: func.func @product_scalar_boxed_mask( +// CHECK-SAME: %[[ARG0:.*]]: !hlfir.expr<?x3xf32>, +// CHECK-SAME: %[[ARG1:.*]]: !fir.box<!fir.logical<1>>) -> !hlfir.expr<3xf32> { +// CHECK: %[[CONSTANT_0:.*]] = arith.constant 1 : index +// CHECK: %[[CONSTANT_1:.*]] = arith.constant 1.000000e+00 : f32 +// CHECK: %[[CONSTANT_2:.*]] = arith.constant true +// CHECK: %[[CONSTANT_3:.*]] = arith.constant 3 : index +// CHECK: %[[SHAPE_OF_0:.*]] = hlfir.shape_of %[[ARG0]] : (!hlfir.expr<?x3xf32>) -> !fir.shape<2> +// CHECK: %[[GET_EXTENT_0:.*]] = hlfir.get_extent %[[SHAPE_OF_0]] {dim = 0 : index} : (!fir.shape<2>) -> index +// CHECK: %[[SHAPE_0:.*]] = fir.shape %[[CONSTANT_3]] : (index) -> !fir.shape<1> +// CHECK: %[[IS_PRESENT_0:.*]] = fir.is_present %[[ARG1]] : (!fir.box<!fir.logical<1>>) -> i1 +// CHECK: %[[IF_0:.*]] = fir.if %[[IS_PRESENT_0]] -> (!fir.logical<1>) { +// CHECK: %[[BOX_ADDR_0:.*]] = fir.box_addr %[[ARG1]] : (!fir.box<!fir.logical<1>>) -> !fir.ref<!fir.logical<1>> +// CHECK: %[[LOAD_0:.*]] = fir.load %[[BOX_ADDR_0]] : !fir.ref<!fir.logical<1>> +// CHECK: fir.result %[[LOAD_0]] : !fir.logical<1> +// CHECK: } else { +// CHECK: %[[CONVERT_0:.*]] = fir.convert %[[CONSTANT_2]] : (i1) -> !fir.logical<1> +// CHECK: fir.result %[[CONVERT_0]] : !fir.logical<1> +// CHECK: } +// CHECK: %[[ELEMENTAL_0:.*]] = hlfir.elemental %[[SHAPE_0]] unordered : (!fir.shape<1>) -> !hlfir.expr<3xf32> { +// CHECK: ^bb0(%[[VAL_0:.*]]: index): +// CHECK: %[[DO_LOOP_0:.*]] = fir.do_loop %[[VAL_1:.*]] = %[[CONSTANT_0]] to %[[GET_EXTENT_0]] step %[[CONSTANT_0]] iter_args(%[[VAL_2:.*]] = %[[CONSTANT_1]]) -> (f32) { +// CHECK: %[[CONVERT_1:.*]] = fir.convert %[[IF_0]] : (!fir.logical<1>) -> i1 +// CHECK: %[[IF_1:.*]] = fir.if %[[CONVERT_1]] -> (f32) { +// CHECK: %[[APPLY_0:.*]] = hlfir.apply %[[ARG0]], %[[VAL_1]], %[[VAL_0]] : (!hlfir.expr<?x3xf32>, index, index) -> f32 +// CHECK: %[[MULF_0:.*]] = arith.mulf %[[VAL_2]], %[[APPLY_0]] : f32 +// CHECK: fir.result %[[MULF_0]] : f32 +// CHECK: } else { +// CHECK: fir.result %[[VAL_2]] : f32 +// CHECK: } +// CHECK: fir.result %[[IF_1]] : f32 +// CHECK: } +// CHECK: hlfir.yield_element %[[DO_LOOP_0]] : f32 +// CHECK: } +// CHECK: return %[[ELEMENTAL_0]] : !hlfir.expr<3xf32> +// CHECK: } + + +// array mask +func.func @product_array_mask(%arg0: !hlfir.expr<?x3xf32>, %mask: !fir.box<!fir.array<?x3x!fir.logical<1>>>) -> !hlfir.expr<?xf32> { + %cst = arith.constant 2 : i32 + %res = hlfir.product %arg0 dim %cst mask %mask : (!hlfir.expr<?x3xf32>, i32, !fir.box<!fir.array<?x3x!fir.logical<1>>>) -> !hlfir.expr<?xf32> + return %res : !hlfir.expr<?xf32> +} +// CHECK-LABEL: func.func @product_array_mask( +// CHECK-SAME: %[[ARG0:.*]]: !hlfir.expr<?x3xf32>, +// CHECK-SAME: %[[ARG1:.*]]: !fir.box<!fir.array<?x3x!fir.logical<1>>>) -> !hlfir.expr<?xf32> { +// CHECK: %[[CONSTANT_0:.*]] = arith.constant true +// CHECK: %[[CONSTANT_1:.*]] = arith.constant 0 : index +// CHECK: %[[CONSTANT_2:.*]] = arith.constant 1 : index +// CHECK: %[[CONSTANT_3:.*]] = arith.constant 1.000000e+00 : f32 +// CHECK: %[[CONSTANT_4:.*]] = arith.constant 3 : index +// CHECK: %[[SHAPE_OF_0:.*]] = hlfir.shape_of %[[ARG0]] : (!hlfir.expr<?x3xf32>) -> !fir.shape<2> +// CHECK: %[[GET_EXTENT_0:.*]] = hlfir.get_extent %[[SHAPE_OF_0]] {dim = 0 : index} : (!fir.shape<2>) -> index +// CHECK: %[[SHAPE_0:.*]] = fir.shape %[[GET_EXTENT_0]] : (index) -> !fir.shape<1> +// CHECK: %[[IS_PRESENT_0:.*]] = fir.is_present %[[ARG1]] : (!fir.box<!fir.array<?x3x!fir.logical<1>>>) -> i1 +// CHECK: %[[ELEMENTAL_0:.*]] = hlfir.elemental %[[SHAPE_0]] unordered : (!fir.shape<1>) -> !hlfir.expr<?xf32> { +// CHECK: ^bb0(%[[VAL_0:.*]]: index): +// CHECK: %[[DO_LOOP_0:.*]] = fir.do_loop %[[VAL_1:.*]] = %[[CONSTANT_2]] to %[[CONSTANT_4]] step %[[CONSTANT_2]] iter_args(%[[VAL_2:.*]] = %[[CONSTANT_3]]) -> (f32) { +// CHECK: %[[IF_0:.*]] = fir.if %[[IS_PRESENT_0]] -> (!fir.logical<1>) { +// CHECK: %[[BOX_DIMS_0:.*]]:3 = fir.box_dims %[[ARG1]], %[[CONSTANT_1]] : (!fir.box<!fir.array<?x3x!fir.logical<1>>>, index) -> (index, index, index) +// CHECK: %[[BOX_DIMS_1:.*]]:3 = fir.box_dims %[[ARG1]], %[[CONSTANT_2]] : (!fir.box<!fir.array<?x3x!fir.logical<1>>>, index) -> (index, index, index) +// CHECK: %[[SUBI_0:.*]] = arith.subi %[[BOX_DIMS_0]]#0, %[[CONSTANT_2]] : index +// CHECK: %[[ADDI_0:.*]] = arith.addi %[[VAL_0]], %[[SUBI_0]] : index +// CHECK: %[[SUBI_1:.*]] = arith.subi %[[BOX_DIMS_1]]#0, %[[CONSTANT_2]] : index +// CHECK: %[[ADDI_1:.*]] = arith.addi %[[VAL_1]], %[[SUBI_1]] : index +// CHECK: %[[DESIGNATE_0:.*]] = hlfir.designate %[[ARG1]] (%[[ADDI_0]], %[[ADDI_1]]) : (!fir.box<!fir.array<?x3x!fir.logical<1>>>, index, index) -> !fir.ref<!fir.logical<1>> +// CHECK: %[[LOAD_0:.*]] = fir.load %[[DESIGNATE_0]] : !fir.ref<!fir.logical<1>> +// CHECK: fir.result %[[LOAD_0]] : !fir.logical<1> +// CHECK: } else { +// CHECK: %[[CONVERT_0:.*]] = fir.convert %[[CONSTANT_0]] : (i1) -> !fir.logical<1> +// CHECK: fir.result %[[CONVERT_0]] : !fir.logical<1> +// CHECK: } +// CHECK: %[[CONVERT_1:.*]] = fir.convert %[[IF_0]] : (!fir.logical<1>) -> i1 +// CHECK: %[[IF_1:.*]] = fir.if %[[CONVERT_1]] -> (f32) { +// CHECK: %[[APPLY_0:.*]] = hlfir.apply %[[ARG0]], %[[VAL_0]], %[[VAL_1]] : (!hlfir.expr<?x3xf32>, index, index) -> f32 +// CHECK: %[[MULF_0:.*]] = arith.mulf %[[VAL_2]], %[[APPLY_0]] : f32 +// CHECK: fir.result %[[MULF_0]] : f32 +// CHECK: } else { +// CHECK: fir.result %[[VAL_2]] : f32 +// CHECK: } +// CHECK: fir.result %[[IF_1]] : f32 +// CHECK: } +// CHECK: hlfir.yield_element %[[DO_LOOP_0]] : f32 +// CHECK: } +// CHECK: return %[[ELEMENTAL_0]] : !hlfir.expr<?xf32> +// CHECK: } + + +// array expr mask +func.func @product_array_expr_mask(%arg0: !hlfir.expr<?x3xf32>, %mask: !hlfir.expr<?x3x!fir.logical<1>>) -> !hlfir.expr<?xf32> { + %cst = arith.constant 2 : i32 + %res = hlfir.product %arg0 dim %cst mask %mask : (!hlfir.expr<?x3xf32>, i32, !hlfir.expr<?x3x!fir.logical<1>>) -> !hlfir.expr<?xf32> + return %res : !hlfir.expr<?xf32> +} +// CHECK-LABEL: func.func @product_array_expr_mask( +// CHECK-SAME: %[[ARG0:.*]]: !hlfir.expr<?x3xf32>, +// CHECK-SAME: %[[ARG1:.*]]: !hlfir.expr<?x3x!fir.logical<1>>) -> !hlfir.expr<?xf32> { +// CHECK: %[[CONSTANT_0:.*]] = arith.constant 1 : index +// CHECK: %[[CONSTANT_1:.*]] = arith.constant 1.000000e+00 : f32 +// CHECK: %[[CONSTANT_2:.*]] = arith.constant 3 : index +// CHECK: %[[SHAPE_OF_0:.*]] = hlfir.shape_of %[[ARG0]] : (!hlfir.expr<?x3xf32>) -> !fir.shape<2> +// CHECK: %[[GET_EXTENT_0:.*]] = hlfir.get_extent %[[SHAPE_OF_0]] {dim = 0 : index} : (!fir.shape<2>) -> index +// CHECK: %[[SHAPE_0:.*]] = fir.shape %[[GET_EXTENT_0]] : (index) -> !fir.shape<1> +// CHECK: %[[ELEMENTAL_0:.*]] = hlfir.elemental %[[SHAPE_0]] unordered : (!fir.shape<1>) -> !hlfir.expr<?xf32> { +// CHECK: ^bb0(%[[VAL_0:.*]]: index): +// CHECK: %[[DO_LOOP_0:.*]] = fir.do_loop %[[VAL_1:.*]] = %[[CONSTANT_0]] to %[[CONSTANT_2]] step %[[CONSTANT_0]] iter_args(%[[VAL_2:.*]] = %[[CONSTANT_1]]) -> (f32) { +// CHECK: %[[APPLY_0:.*]] = hlfir.apply %[[ARG1]], %[[VAL_0]], %[[VAL_1]] : (!hlfir.expr<?x3x!fir.logical<1>>, index, index) -> !fir.logical<1> +// CHECK: %[[CONVERT_0:.*]] = fir.convert %[[APPLY_0]] : (!fir.logical<1>) -> i1 +// CHECK: %[[IF_0:.*]] = fir.if %[[CONVERT_0]] -> (f32) { +// CHECK: %[[APPLY_1:.*]] = hlfir.apply %[[ARG0]], %[[VAL_0]], %[[VAL_1]] : (!hlfir.expr<?x3xf32>, index, index) -> f32 +// CHECK: %[[MULF_0:.*]] = arith.mulf %[[VAL_2]], %[[APPLY_1]] : f32 +// CHECK: fir.result %[[MULF_0]] : f32 +// CHECK: } else { +// CHECK: fir.result %[[VAL_2]] : f32 +// CHECK: } +// CHECK: fir.result %[[IF_0]] : f32 +// CHECK: } +// CHECK: hlfir.yield_element %[[DO_LOOP_0]] : f32 +// CHECK: } +// CHECK: return %[[ELEMENTAL_0]] : !hlfir.expr<?xf32> +// CHECK: } + +// unordered floating point reduction +func.func @product_unordered_reduction(%arg0: !hlfir.expr<2x3xf32>) -> !hlfir.expr<3xf32> { + %cst = arith.constant 1 : i32 + %res = hlfir.product %arg0 dim %cst {fastmath = #arith.fastmath<reassoc>} : (!hlfir.expr<2x3xf32>, i32) -> !hlfir.expr<3xf32> + return %res : !hlfir.expr<3xf32> +} +// CHECK-LABEL: func.func @product_unordered_reduction( +// CHECK-SAME: %[[ARG0:.*]]: !hlfir.expr<2x3xf32>) -> !hlfir.expr<3xf32> { +// CHECK: %[[CONSTANT_0:.*]] = arith.constant 1 : index +// CHECK: %[[CONSTANT_1:.*]] = arith.constant 1.000000e+00 : f32 +// CHECK: %[[CONSTANT_2:.*]] = arith.constant 2 : index +// CHECK: %[[CONSTANT_3:.*]] = arith.constant 3 : index +// CHECK: %[[SHAPE_0:.*]] = fir.shape %[[CONSTANT_3]] : (index) -> !fir.shape<1> +// CHECK: %[[ELEMENTAL_0:.*]] = hlfir.elemental %[[SHAPE_0]] unordered : (!fir.shape<1>) -> !hlfir.expr<3xf32> { +// CHECK: ^bb0(%[[VAL_0:.*]]: index): +// CHECK: %[[DO_LOOP_0:.*]] = fir.do_loop %[[VAL_1:.*]] = %[[CONSTANT_0]] to %[[CONSTANT_2]] step %[[CONSTANT_0]] unordered iter_args(%[[VAL_2:.*]] = %[[CONSTANT_1]]) -> (f32) { +// CHECK: %[[APPLY_0:.*]] = hlfir.apply %[[ARG0]], %[[VAL_1]], %[[VAL_0]] : (!hlfir.expr<2x3xf32>, index, index) -> f32 +// CHECK: %[[MULF_0:.*]] = arith.mulf %[[VAL_2]], %[[APPLY_0]] fastmath<reassoc> : f32 +// CHECK: fir.result %[[MULF_0]] : f32 +// CHECK: } +// CHECK: hlfir.yield_element %[[DO_LOOP_0]] : f32 +// CHECK: } +// CHECK: return %[[ELEMENTAL_0]] : !hlfir.expr<3xf32> +// CHECK: } + + +// total 1d reduction +func.func @product_total_1d_reduction(%arg0: !fir.box<!fir.array<3xi32>>) -> i32 { + %cst = arith.constant 1 : i32 + %res = hlfir.product %arg0 dim %cst : (!fir.box<!fir.array<3xi32>>, i32) -> i32 + return %res : i32 +} +// CHECK-LABEL: func.func @product_total_1d_reduction( +// CHECK-SAME: %[[ARG0:.*]]: !fir.box<!fir.array<3xi32>>) -> i32 { +// CHECK: %[[CONSTANT_0:.*]] = arith.constant 0 : index +// CHECK: %[[CONSTANT_1:.*]] = arith.constant 3 : index +// CHECK: %[[CONSTANT_2:.*]] = arith.constant 1 : i32 +// CHECK: %[[CONSTANT_3:.*]] = arith.constant 1 : index +// CHECK: %[[DO_LOOP_0:.*]] = fir.do_loop %[[VAL_0:.*]] = %[[CONSTANT_3]] to %[[CONSTANT_1]] step %[[CONSTANT_3]] unordered iter_args(%[[VAL_1:.*]] = %[[CONSTANT_2]]) -> (i32) { +// CHECK: %[[BOX_DIMS_0:.*]]:3 = fir.box_dims %[[ARG0]], %[[CONSTANT_0]] : (!fir.box<!fir.array<3xi32>>, index) -> (index, index, index) +// CHECK: %[[SUBI_0:.*]] = arith.subi %[[BOX_DIMS_0]]#0, %[[CONSTANT_3]] : index +// CHECK: %[[ADDI_0:.*]] = arith.addi %[[VAL_0]], %[[SUBI_0]] : index +// CHECK: %[[DESIGNATE_0:.*]] = hlfir.designate %[[ARG0]] (%[[ADDI_0]]) : (!fir.box<!fir.array<3xi32>>, index) -> !fir.ref<i32> +// CHECK: %[[LOAD_0:.*]] = fir.load %[[DESIGNATE_0]] : !fir.ref<i32> +// CHECK: %[[MULI_0:.*]] = arith.muli %[[VAL_1]], %[[LOAD_0]] : i32 +// CHECK: fir.result %[[MULI_0]] : i32 +// CHECK: } +// CHECK: return %[[DO_LOOP_0]] : i32 +// CHECK: } + +// total 2d reduction +func.func @product_total_2d_reduction(%arg0: !fir.box<!fir.array<?x3xi32>>) -> i32 { + %res = hlfir.product %arg0 : (!fir.box<!fir.array<?x3xi32>>) -> i32 + return %res : i32 +} +// CHECK-LABEL: func.func @product_total_2d_reduction( +// CHECK-SAME: %[[ARG0:.*]]: !fir.box<!fir.array<?x3xi32>>) -> i32 { +// CHECK: %[[CONSTANT_0:.*]] = arith.constant 1 : index +// CHECK: %[[CONSTANT_1:.*]] = arith.constant 1 : i32 +// CHECK: %[[CONSTANT_2:.*]] = arith.constant 3 : index +// CHECK: %[[CONSTANT_3:.*]] = arith.constant 0 : index +// CHECK: %[[BOX_DIMS_0:.*]]:3 = fir.box_dims %[[ARG0]], %[[CONSTANT_3]] : (!fir.box<!fir.array<?x3xi32>>, index) -> (index, index, index) +// CHECK: %[[DO_LOOP_0:.*]] = fir.do_loop %[[VAL_0:.*]] = %[[CONSTANT_0]] to %[[CONSTANT_2]] step %[[CONSTANT_0]] unordered iter_args(%[[VAL_1:.*]] = %[[CONSTANT_1]]) -> (i32) { +// CHECK: %[[DO_LOOP_1:.*]] = fir.do_loop %[[VAL_2:.*]] = %[[CONSTANT_0]] to %[[BOX_DIMS_0]]#1 step %[[CONSTANT_0]] unordered iter_args(%[[VAL_3:.*]] = %[[VAL_1]]) -> (i32) { +// CHECK: %[[BOX_DIMS_1:.*]]:3 = fir.box_dims %[[ARG0]], %[[CONSTANT_3]] : (!fir.box<!fir.array<?x3xi32>>, index) -> (index, index, index) +// CHECK: %[[BOX_DIMS_2:.*]]:3 = fir.box_dims %[[ARG0]], %[[CONSTANT_0]] : (!fir.box<!fir.array<?x3xi32>>, index) -> (index, index, index) +// CHECK: %[[SUBI_0:.*]] = arith.subi %[[BOX_DIMS_1]]#0, %[[CONSTANT_0]] : index +// CHECK: %[[ADDI_0:.*]] = arith.addi %[[VAL_2]], %[[SUBI_0]] : index +// CHECK: %[[SUBI_1:.*]] = arith.subi %[[BOX_DIMS_2]]#0, %[[CONSTANT_0]] : index +// CHECK: %[[ADDI_1:.*]] = arith.addi %[[VAL_0]], %[[SUBI_1]] : index +// CHECK: %[[DESIGNATE_0:.*]] = hlfir.designate %[[ARG0]] (%[[ADDI_0]], %[[ADDI_1]]) : (!fir.box<!fir.array<?x3xi32>>, index, index) -> !fir.ref<i32> +// CHECK: %[[LOAD_0:.*]] = fir.load %[[DESIGNATE_0]] : !fir.ref<i32> +// CHECK: %[[MULI_0:.*]] = arith.muli %[[VAL_3]], %[[LOAD_0]] : i32 +// CHECK: fir.result %[[MULI_0]] : i32 +// CHECK: } +// CHECK: fir.result %[[DO_LOOP_1]] : i32 +// CHECK: } +// CHECK: return %[[DO_LOOP_0]] : i32 +// CHECK: } + + +// negative: invalid dim==0 +func.func @product_invalid_dim0(%arg0: !hlfir.expr<2x3xi32>) -> !hlfir.expr<3xi32> { + %cst = arith.constant 0 : i32 + %res = hlfir.product %arg0 dim %cst : (!hlfir.expr<2x3xi32>, i32) -> !hlfir.expr<3xi32> + return %res : !hlfir.expr<3xi32> +} +// CHECK-LABEL: func.func @product_invalid_dim0( +// CHECK-SAME: %[[ARG0:.*]]: !hlfir.expr<2x3xi32>) -> !hlfir.expr<3xi32> { +// CHECK: %[[CONSTANT_0:.*]] = arith.constant 0 : i32 +// CHECK: %[[PRODUCT_0:.*]] = hlfir.product %[[ARG0]] dim %[[CONSTANT_0]] : (!hlfir.expr<2x3xi32>, i32) -> !hlfir.expr<3xi32> +// CHECK: return %[[PRODUCT_0]] : !hlfir.expr<3xi32> +// CHECK: } + +// negative: invalid dim>rank +func.func @product_invalid_dim_big(%arg0: !hlfir.expr<2x3xi32>) -> !hlfir.expr<3xi32> { + %cst = arith.constant 3 : i32 + %res = hlfir.product %arg0 dim %cst : (!hlfir.expr<2x3xi32>, i32) -> !hlfir.expr<3xi32> + return %res : !hlfir.expr<3xi32> +} +// CHECK-LABEL: func.func @product_invalid_dim_big( +// CHECK-SAME: %[[ARG0:.*]]: !hlfir.expr<2x3xi32>) -> !hlfir.expr<3xi32> { +// CHECK: %[[CONSTANT_0:.*]] = arith.constant 3 : i32 +// CHECK: %[[PRODUCT_0:.*]] = hlfir.product %[[ARG0]] dim %[[CONSTANT_0]] : (!hlfir.expr<2x3xi32>, i32) -> !hlfir.expr<3xi32> +// CHECK: return %[[PRODUCT_0]] : !hlfir.expr<3xi32> +// CHECK: }
\ No newline at end of file diff --git a/flang/test/Integration/OpenMP/do-simd-firstprivate-lastprivate-runtime.f90 b/flang/test/Integration/OpenMP/do-simd-firstprivate-lastprivate-runtime.f90 new file mode 100644 index 0000000..4fef691 --- /dev/null +++ b/flang/test/Integration/OpenMP/do-simd-firstprivate-lastprivate-runtime.f90 @@ -0,0 +1,48 @@ +! Test runtime behavior of DO SIMD with firstprivate and lastprivate on same variable +! This is the reproducer from issue #168306 + +! REQUIRES: openmp-runtime + +! RUN: %flang_fc1 -fopenmp -emit-llvm %s -o - | FileCheck %s --check-prefix=LLVM +! RUN: %flang -fopenmp %s -o %t && %t | FileCheck %s + +! LLVM-LABEL: define {{.*}} @_QQmain +program main + integer :: a + integer :: i + + a = 10 + !$omp do simd lastprivate(a) firstprivate(a) + do i = 1, 1 + ! Inside loop: a should be 10 (from firstprivate initialization) + ! CHECK: main1 : a = 10 + print *, "main1 : a = ", a + a = 20 + end do + !$omp end do simd + ! After loop: a should be 20 (from lastprivate copy-out) + ! CHECK: main2 : a = 20 + print *, "main2 : a = ", a + + call sub + ! CHECK: pass + print *, 'pass' +end program main + +subroutine sub + integer :: a + integer :: i + + a = 10 + !$omp do simd lastprivate(a) firstprivate(a) + do i = 1, 1 + ! Inside loop: a should be 10 (from firstprivate initialization) + ! CHECK: sub1 : a = 10 + print *, "sub1 : a = ", a + a = 20 + end do + !$omp end do simd + ! After loop: a should be 20 (from lastprivate copy-out) + ! CHECK: sub2 : a = 20 + print *, "sub2 : a = ", a +end subroutine sub diff --git a/flang/test/Integration/OpenMP/map-types-and-sizes.f90 b/flang/test/Integration/OpenMP/map-types-and-sizes.f90 index 44a049f..d6d93985 100644 --- a/flang/test/Integration/OpenMP/map-types-and-sizes.f90 +++ b/flang/test/Integration/OpenMP/map-types-and-sizes.f90 @@ -33,8 +33,17 @@ subroutine mapType_array !$omp end target end subroutine mapType_array -!CHECK: @.offload_sizes{{.*}} = private unnamed_addr constant [4 x i64] [i64 0, i64 24, i64 8, i64 0] -!CHECK: @.offload_maptypes{{.*}} = private unnamed_addr constant [4 x i64] [i64 32, i64 281474976711169, i64 281474976711171, i64 281474976711187] +!CHECK: @.offload_sizes{{.*}} = private unnamed_addr constant [1 x i64] [i64 8] +!CHECK: @.offload_maptypes{{.*}} = private unnamed_addr constant [1 x i64] [i64 33] +subroutine mapType_is_device_ptr + use iso_c_binding, only : c_ptr + type(c_ptr) :: p + !$omp target is_device_ptr(p) + !$omp end target +end subroutine mapType_is_device_ptr + +!CHECK: @.offload_sizes{{.*}} = private unnamed_addr constant [5 x i64] [i64 0, i64 0, i64 0, i64 8, i64 0] +!CHECK: @.offload_maptypes{{.*}} = private unnamed_addr constant [5 x i64] [i64 32, i64 281474976711173, i64 281474976711173, i64 281474976711171, i64 281474976711187] subroutine mapType_ptr integer, pointer :: a !$omp target @@ -73,8 +82,8 @@ subroutine map_ompx_hold !$omp end target data end subroutine -!CHECK: @.offload_sizes{{.*}} = private unnamed_addr constant [4 x i64] [i64 0, i64 24, i64 8, i64 0] -!CHECK: @.offload_maptypes{{.*}} = private unnamed_addr constant [4 x i64] [i64 32, i64 281474976711169, i64 281474976711171, i64 281474976711187] +!CHECK: @.offload_sizes{{.*}} = private unnamed_addr constant [5 x i64] [i64 0, i64 0, i64 0, i64 8, i64 0] +!CHECK: @.offload_maptypes{{.*}} = private unnamed_addr constant [5 x i64] [i64 32, i64 281474976711173, i64 281474976711173, i64 281474976711171, i64 281474976711187] subroutine mapType_allocatable integer, allocatable :: a allocate(a) @@ -84,8 +93,8 @@ subroutine mapType_allocatable deallocate(a) end subroutine mapType_allocatable -!CHECK: @.offload_sizes{{.*}} = private unnamed_addr constant [4 x i64] [i64 0, i64 24, i64 8, i64 0] -!CHECK: @.offload_maptypes{{.*}} = private unnamed_addr constant [4 x i64] [i64 32, i64 281474976710657, i64 281474976710659, i64 281474976710675] +!CHECK: @.offload_sizes{{.*}} = private unnamed_addr constant [5 x i64] [i64 0, i64 0, i64 0, i64 8, i64 0] +!CHECK: @.offload_maptypes{{.*}} = private unnamed_addr constant [5 x i64] [i64 32, i64 281474976710661, i64 281474976710661, i64 281474976710659, i64 281474976710675] subroutine mapType_ptr_explicit integer, pointer :: a !$omp target map(tofrom: a) @@ -93,8 +102,8 @@ subroutine mapType_ptr_explicit !$omp end target end subroutine mapType_ptr_explicit -!CHECK: @.offload_sizes{{.*}} = private unnamed_addr constant [4 x i64] [i64 0, i64 24, i64 8, i64 0] -!CHECK: @.offload_maptypes{{.*}} = private unnamed_addr constant [4 x i64] [i64 32, i64 281474976710657, i64 281474976710659, i64 281474976710675] +!CHECK: @.offload_sizes{{.*}} = private unnamed_addr constant [5 x i64] [i64 0, i64 0, i64 0, i64 8, i64 0] +!CHECK: @.offload_maptypes{{.*}} = private unnamed_addr constant [5 x i64] [i64 32, i64 281474976710661, i64 281474976710661, i64 281474976710659, i64 281474976710675] subroutine mapType_allocatable_explicit integer, allocatable :: a allocate(a) @@ -246,7 +255,7 @@ subroutine mapType_derived_explicit_nested_member_with_bounds end subroutine mapType_derived_explicit_nested_member_with_bounds !CHECK: @.offload_sizes{{.*}} = private unnamed_addr constant [4 x i64] [i64 0, i64 48, i64 8, i64 0] -!CHECK: @.offload_maptypes{{.*}} = private unnamed_addr constant [4 x i64] [i64 32, i64 281474976710657, i64 281474976710659, i64 281474976710675] +!CHECK: @.offload_maptypes{{.*}} = private unnamed_addr constant [4 x i64] [i64 32, i64 281474976710661, i64 281474976710659, i64 281474976710675] subroutine mapType_derived_type_alloca() type :: one_layer real(4) :: i @@ -266,8 +275,8 @@ subroutine mapType_derived_type_alloca() !$omp end target end subroutine -!CHECK: @.offload_sizes{{.*}} = private unnamed_addr constant [8 x i64] [i64 0, i64 40, i64 8, i64 0, i64 48, i64 8, i64 0, i64 4] -!CHECK: @.offload_maptypes{{.*}} = private unnamed_addr constant [8 x i64] [i64 32, i64 281474976710657, i64 281474976710659, i64 281474976710675, i64 281474976710657, i64 281474976710659, i64 281474976710675, i64 281474976710659] +!CHECK: @.offload_sizes{{.*}} = private unnamed_addr constant [9 x i64] [i64 0, i64 0, i64 0, i64 8, i64 0, i64 48, i64 8, i64 0, i64 4] +!CHECK: @.offload_maptypes{{.*}} = private unnamed_addr constant [9 x i64] [i64 32, i64 281474976710661, i64 281474976710661, i64 281474976710659, i64 281474976710675, i64 281474976710661, i64 281474976710659, i64 281474976710675, i64 281474976710659] subroutine mapType_alloca_derived_type() type :: one_layer real(4) :: i @@ -289,8 +298,8 @@ subroutine mapType_alloca_derived_type() !$omp end target end subroutine -!CHECK: @.offload_sizes{{.*}} = private unnamed_addr constant [8 x i64] [i64 0, i64 40, i64 8, i64 0, i64 48, i64 8, i64 0, i64 4] -!CHECK: @.offload_maptypes{{.*}} = private unnamed_addr constant [8 x i64] [i64 32, i64 281474976710657, i64 281474976710659, i64 281474976710675, i64 281474976710657, i64 281474976710659, i64 281474976710675, i64 281474976710659] +!CHECK: @.offload_sizes{{.*}} = private unnamed_addr constant [9 x i64] [i64 0, i64 0, i64 0, i64 8, i64 0, i64 48, i64 8, i64 0, i64 4] +!CHECK: @.offload_maptypes{{.*}} = private unnamed_addr constant [9 x i64] [i64 32, i64 281474976710661, i64 281474976710661, i64 281474976710659, i64 281474976710675, i64 281474976710661, i64 281474976710659, i64 281474976710675, i64 281474976710659] subroutine mapType_alloca_nested_derived_type() type :: middle_layer real(4) :: i @@ -321,7 +330,7 @@ subroutine mapType_alloca_nested_derived_type() end subroutine !CHECK: @.offload_sizes{{.*}} = private unnamed_addr constant [4 x i64] [i64 0, i64 48, i64 8, i64 0] -!CHECK: @.offload_maptypes{{.*}} = private unnamed_addr constant [4 x i64] [i64 32, i64 281474976710657, i64 281474976710659, i64 281474976710675] +!CHECK: @.offload_maptypes{{.*}} = private unnamed_addr constant [4 x i64] [i64 32, i64 281474976710661, i64 281474976710659, i64 281474976710675] subroutine mapType_nested_derived_type_alloca() type :: middle_layer real(4) :: i @@ -350,7 +359,7 @@ subroutine mapType_nested_derived_type_alloca() end subroutine !CHECK: @.offload_sizes{{.*}} = private unnamed_addr constant [7 x i64] [i64 0, i64 64, i64 8, i64 0, i64 48, i64 8, i64 0] -!CHECK: @.offload_maptypes{{.*}} = private unnamed_addr constant [7 x i64] [i64 32, i64 281474976710657, i64 281474976710656, i64 281474976710672, i64 281474976710657, i64 281474976710659, i64 281474976710675] +!CHECK: @.offload_maptypes{{.*}} = private unnamed_addr constant [7 x i64] [i64 32, i64 281474976710661, i64 281474976710656, i64 281474976710672, i64 281474976710661, i64 281474976710659, i64 281474976710675] subroutine mapType_nested_derived_type_member_idx() type :: vertexes integer :: test @@ -428,7 +437,7 @@ end subroutine mapType_common_block_members !CHECK: %[[ALLOCA_INT:.*]] = ptrtoint ptr %[[ALLOCA]] to i64 !CHECK: %[[SIZE_DIFF:.*]] = sub i64 %[[ALLOCA_GEP_INT]], %[[ALLOCA_INT]] !CHECK: %[[DIV:.*]] = sdiv exact i64 %[[SIZE_DIFF]], ptrtoint (ptr getelementptr (i8, ptr null, i32 1) to i64) -!CHECK: %[[OFFLOAD_SIZE_ARR:.*]] = getelementptr inbounds [4 x i64], ptr %.offload_sizes, i32 0, i32 0 +!CHECK: %[[OFFLOAD_SIZE_ARR:.*]] = getelementptr inbounds [5 x i64], ptr %.offload_sizes, i32 0, i32 0 !CHECK: store i64 %[[DIV]], ptr %[[OFFLOAD_SIZE_ARR]], align 8 !CHECK-LABEL: define {{.*}} @{{.*}}maptype_allocatable_explicit_{{.*}} @@ -438,7 +447,7 @@ end subroutine mapType_common_block_members !CHECK: %[[ALLOCA_INT:.*]] = ptrtoint ptr %[[ALLOCA]] to i64 !CHECK: %[[SIZE_DIFF:.*]] = sub i64 %[[ALLOCA_GEP_INT]], %[[ALLOCA_INT]] !CHECK: %[[DIV:.*]] = sdiv exact i64 %[[SIZE_DIFF]], ptrtoint (ptr getelementptr (i8, ptr null, i32 1) to i64) -!CHECK: %[[OFFLOAD_SIZE_ARR:.*]] = getelementptr inbounds [4 x i64], ptr %.offload_sizes, i32 0, i32 0 +!CHECK: %[[OFFLOAD_SIZE_ARR:.*]] = getelementptr inbounds [5 x i64], ptr %.offload_sizes, i32 0, i32 0 !CHECK: store i64 %[[DIV]], ptr %[[OFFLOAD_SIZE_ARR]], align 8 !CHECK-LABEL: define {{.*}} @{{.*}}maptype_derived_implicit_{{.*}} @@ -620,43 +629,56 @@ end subroutine mapType_common_block_members !CHECK: %[[DTYPE_BEGIN:.*]] = ptrtoint ptr %[[DTYPE_DESC_ALLOCA_3]] to i64 !CHECK: %[[DTYPE_DESC_SZ_CALC:.*]] = sub i64 %[[DTYPE_END]], %[[DTYPE_BEGIN]] !CHECK: %[[DTYPE_DESC_SZ:.*]] = sdiv exact i64 %[[DTYPE_DESC_SZ_CALC]], ptrtoint (ptr getelementptr (i8, ptr null, i32 1) to i64) -!CHECK: %[[SIZE_CMP:.*]] = icmp eq ptr %[[MEMBER_ARRAY_OFFSET]], null -!CHECK: %[[SIZE_SEL:.*]] = select i1 %[[SIZE_CMP]], i64 0, i64 %[[MEMBER_SIZE_CALC_4]] -!CHECK: %[[BASE_PTR_ARR:.*]] = getelementptr inbounds [8 x ptr], ptr %.offload_baseptrs, i32 0, i32 0 +!CHECK: %[[DTYPE_BASE_ADDR_ACCESS_4:.*]] = getelementptr { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] }, ptr %[[DTYPE_DESC_ALLOCA_3]], i32 1 +!CHECK: %[[DTYPE_BASE_ADDR_ACCESS_3_OFF:.*]] = getelementptr ptr, ptr %[[DTYPE_BASE_ADDR_ACCESS_3]], i32 1 +!CHECK: %[[SIZE_2_CALC_1:.*]] = ptrtoint ptr %[[DTYPE_BASE_ADDR_ACCESS_4]] to i64 +!CHECK: %[[SIZE_2_CALC_2:.*]] = ptrtoint ptr %[[DTYPE_BASE_ADDR_ACCESS_3_OFF]] to i64 +!CHECK: %[[SIZE_2_CALC_3:.*]] = sub i64 %[[SIZE_2_CALC_1]], %[[SIZE_2_CALC_2]] +!CHECK: %[[SIZE_2_CALC_4:.*]] = sdiv exact i64 %[[SIZE_2_CALC_3]], ptrtoint (ptr getelementptr (i8, ptr null, i32 1) to i64) +!CHECK: %[[CMP_NULL:.*]] = icmp eq ptr %[[MEMBER_ARRAY_OFFSET]], null +!CHECK: %[[NULL_SEL:.*]] = select i1 %[[CMP_NULL]], i64 0, i64 %[[MEMBER_SIZE_CALC_4]] + +!CHECK: %[[BASE_PTR_ARR:.*]] = getelementptr inbounds [9 x ptr], ptr %.offload_baseptrs, i32 0, i32 0 !CHECK: store ptr %[[DTYPE_DESC_ALLOCA_3]], ptr %[[BASE_PTR_ARR]], align 8 -!CHECK: %[[OFFLOAD_PTR_ARR:.*]] = getelementptr inbounds [8 x ptr], ptr %.offload_ptrs, i32 0, i32 0 +!CHECK: %[[OFFLOAD_PTR_ARR:.*]] = getelementptr inbounds [9 x ptr], ptr %.offload_ptrs, i32 0, i32 0 !CHECK: store ptr %[[DTYPE_DESC_ALLOCA_3]], ptr %[[OFFLOAD_PTR_ARR]], align 8 -!CHECK: %[[OFFLOAD_SIZE_ARR:.*]] = getelementptr inbounds [8 x i64], ptr %.offload_sizes, i32 0, i32 0 +!CHECK: %[[OFFLOAD_SIZE_ARR:.*]] = getelementptr inbounds [9 x i64], ptr %.offload_sizes, i32 0, i32 0 !CHECK: store i64 %[[DTYPE_DESC_SZ]], ptr %[[OFFLOAD_SIZE_ARR]], align 8 -!CHECK: %[[BASE_PTR_ARR:.*]] = getelementptr inbounds [8 x ptr], ptr %.offload_baseptrs, i32 0, i32 1 +!CHECK: %[[BASE_PTR_ARR:.*]] = getelementptr inbounds [9 x ptr], ptr %.offload_baseptrs, i32 0, i32 1 !CHECK: store ptr %[[DTYPE_DESC_ALLOCA_3]], ptr %[[BASE_PTR_ARR]], align 8 -!CHECK: %[[OFFLOAD_PTR_ARR:.*]] = getelementptr inbounds [8 x ptr], ptr %.offload_ptrs, i32 0, i32 1 +!CHECK: %[[OFFLOAD_PTR_ARR:.*]] = getelementptr inbounds [9 x ptr], ptr %.offload_ptrs, i32 0, i32 1 !CHECK: store ptr %[[DTYPE_DESC_ALLOCA_3]], ptr %[[OFFLOAD_PTR_ARR]], align 8 -!CHECK: %[[BASE_PTR_ARR:.*]] = getelementptr inbounds [8 x ptr], ptr %.offload_baseptrs, i32 0, i32 2 +!CHECK: %[[BASE_PTR_ARR:.*]] = getelementptr inbounds [9 x ptr], ptr %.offload_baseptrs, i32 0, i32 2 !CHECK: store ptr %[[DTYPE_DESC_ALLOCA_3]], ptr %[[BASE_PTR_ARR]], align 8 -!CHECK: %[[OFFLOAD_PTR_ARR:.*]] = getelementptr inbounds [8 x ptr], ptr %.offload_ptrs, i32 0, i32 2 +!CHECK: %[[OFFLOAD_PTR_ARR:.*]] = getelementptr inbounds [9 x ptr], ptr %.offload_ptrs, i32 0, i32 2 +!CHECK: store ptr %[[DTYPE_BASE_ADDR_ACCESS_3_OFF]], ptr %[[OFFLOAD_PTR_ARR]], align 8 +!CHECK: %[[OFFLOAD_SIZE_ARR:.*]] = getelementptr inbounds [9 x i64], ptr %.offload_sizes, i32 0, i32 2 +!CHECK: store i64 %[[SIZE_2_CALC_4]], ptr %[[OFFLOAD_SIZE_ARR]], align 8 +!CHECK: %[[BASE_PTR_ARR:.*]] = getelementptr inbounds [9 x ptr], ptr %.offload_baseptrs, i32 0, i32 3 +!CHECK: store ptr %[[DTYPE_DESC_ALLOCA_3]], ptr %[[BASE_PTR_ARR]], align 8 +!CHECK: %[[OFFLOAD_PTR_ARR:.*]] = getelementptr inbounds [9 x ptr], ptr %.offload_ptrs, i32 0, i32 3 !CHECK: store ptr %[[DTYPE_BASE_ADDR_ACCESS_3]], ptr %[[OFFLOAD_PTR_ARR]], align 8 -!CHECK: %[[BASE_PTR_ARR:.*]] = getelementptr inbounds [8 x ptr], ptr %.offload_baseptrs, i32 0, i32 3 +!CHECK: %[[BASE_PTR_ARR:.*]] = getelementptr inbounds [9 x ptr], ptr %.offload_baseptrs, i32 0, i32 4 !CHECK: store ptr %[[DTYPE_BASE_ADDR_ACCESS_3]], ptr %[[BASE_PTR_ARR]], align 8 -!CHECK: %[[OFFLOAD_PTR_ARR:.*]] = getelementptr inbounds [8 x ptr], ptr %.offload_ptrs, i32 0, i32 3 +!CHECK: %[[OFFLOAD_PTR_ARR:.*]] = getelementptr inbounds [9 x ptr], ptr %.offload_ptrs, i32 0, i32 4 !CHECK: store ptr %[[DTYPE_BASE_ADDR_LOAD_3]], ptr %[[OFFLOAD_PTR_ARR]], align 8 -!CHECK: %[[BASE_PTR_ARR:.*]] = getelementptr inbounds [8 x ptr], ptr %.offload_baseptrs, i32 0, i32 4 +!CHECK: %[[BASE_PTR_ARR:.*]] = getelementptr inbounds [9 x ptr], ptr %.offload_baseptrs, i32 0, i32 5 !CHECK: store ptr %[[DTYPE_DESC_ALLOCA_3]], ptr %[[BASE_PTR_ARR]], align 8 -!CHECK: %[[OFFLOAD_PTR_ARR:.*]] = getelementptr inbounds [8 x ptr], ptr %.offload_ptrs, i32 0, i32 4 +!CHECK: %[[OFFLOAD_PTR_ARR:.*]] = getelementptr inbounds [9 x ptr], ptr %.offload_ptrs, i32 0, i32 5 !CHECK: store ptr %[[DTYPE_ALLOCA_MEMBER_ACCESS]], ptr %[[OFFLOAD_PTR_ARR]], align 8 -!CHECK: %[[BASE_PTR_ARR:.*]] = getelementptr inbounds [8 x ptr], ptr %.offload_baseptrs, i32 0, i32 5 +!CHECK: %[[BASE_PTR_ARR:.*]] = getelementptr inbounds [9 x ptr], ptr %.offload_baseptrs, i32 0, i32 6 !CHECK: store ptr %[[DTYPE_DESC_ALLOCA_3]], ptr %[[BASE_PTR_ARR]], align 8 -!CHECK: %[[OFFLOAD_PTR_ARR:.*]] = getelementptr inbounds [8 x ptr], ptr %.offload_ptrs, i32 0, i32 5 +!CHECK: %[[OFFLOAD_PTR_ARR:.*]] = getelementptr inbounds [9 x ptr], ptr %.offload_ptrs, i32 0, i32 6 !CHECK: store ptr %[[DTYPE_ALLOCA_MEMBER_BASE_ADDR_ACCESS]], ptr %[[OFFLOAD_PTR_ARR]], align 8 -!CHECK: %[[BASE_PTR_ARR:.*]] = getelementptr inbounds [8 x ptr], ptr %.offload_baseptrs, i32 0, i32 6 +!CHECK: %[[BASE_PTR_ARR:.*]] = getelementptr inbounds [9 x ptr], ptr %.offload_baseptrs, i32 0, i32 7 !CHECK: store ptr %[[DTYPE_ALLOCA_MEMBER_BASE_ADDR_ACCESS]], ptr %[[BASE_PTR_ARR]], align 8 -!CHECK: %[[OFFLOAD_PTR_ARR:.*]] = getelementptr inbounds [8 x ptr], ptr %.offload_ptrs, i32 0, i32 6 +!CHECK: %[[OFFLOAD_PTR_ARR:.*]] = getelementptr inbounds [9 x ptr], ptr %.offload_ptrs, i32 0, i32 7 !CHECK: store ptr %[[MEMBER_ARRAY_OFFSET]], ptr %[[OFFLOAD_PTR_ARR]], align 8 -!CHECK: %[[OFFLOAD_SIZE_ARR:.*]] = getelementptr inbounds [8 x i64], ptr %.offload_sizes, i32 0, i32 6 -!CHECK: store i64 %[[SIZE_SEL]], ptr %[[OFFLOAD_SIZE_ARR]], align 8 -!CHECK: %[[BASE_PTR_ARR:.*]] = getelementptr inbounds [8 x ptr], ptr %.offload_baseptrs, i32 0, i32 7 +!CHECK: %[[OFFLOAD_SIZE_ARR:.*]] = getelementptr inbounds [9 x i64], ptr %.offload_sizes, i32 0, i32 7 +!CHECK: store i64 %[[NULL_SEL]], ptr %[[OFFLOAD_SIZE_ARR]], align 8 +!CHECK: %[[BASE_PTR_ARR:.*]] = getelementptr inbounds [9 x ptr], ptr %.offload_baseptrs, i32 0, i32 8 !CHECK: store ptr %[[DTYPE_DESC_ALLOCA_3]], ptr %[[BASE_PTR_ARR]], align 8 -!CHECK: %[[OFFLOAD_PTR_ARR:.*]] = getelementptr inbounds [8 x ptr], ptr %.offload_ptrs, i32 0, i32 7 +!CHECK: %[[OFFLOAD_PTR_ARR:.*]] = getelementptr inbounds [9 x ptr], ptr %.offload_ptrs, i32 0, i32 8 !CHECK: store ptr %[[DTYPE_NONALLOCA_MEMBER_ACCESS]], ptr %[[OFFLOAD_PTR_ARR]], align 8 !CHECK-LABEL: define {{.*}} @{{.*}}maptype_alloca_nested_derived_type{{.*}} @@ -690,43 +712,55 @@ end subroutine mapType_common_block_members !CHECK: %[[DTYPE_DESC_SIZE_CALC_3:.*]] = ptrtoint ptr %[[DTYPE_DESC_ALLOCA_3]] to i64 !CHECK: %[[DTYPE_DESC_SIZE_CALC_4:.*]] = sub i64 %[[DTYPE_DESC_SIZE_CALC_2]], %[[DTYPE_DESC_SIZE_CALC_3]] !CHECK: %[[DTYPE_DESC_SIZE_CALC_5:.*]] = sdiv exact i64 %[[DTYPE_DESC_SIZE_CALC_4]], ptrtoint (ptr getelementptr (i8, ptr null, i32 1) to i64) -!CHECK: %[[DATA_CMP:.*]] = icmp eq ptr %[[ARRAY_OFFSET]], null -!CHECK: %[[DATA_SEL:.*]] = select i1 %[[DATA_CMP]], i64 0, i64 %[[ALLOCATABLE_MEMBER_SIZE_CALC_5]] -!CHECK: %[[BASE_PTR_ARR:.*]] = getelementptr inbounds [8 x ptr], ptr %.offload_baseptrs, i32 0, i32 0 +!CHECK: %[[DTYPE_BASE_ADDR_ACCESS_3:.*]] = getelementptr { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] }, ptr %[[DTYPE_DESC_ALLOCA_3]], i32 1 +!CHECK: %[[DTYPE_BASE_ADDR_ACCESS_3_OFF:.*]] = getelementptr ptr, ptr %[[DTYPE_DESC_BASE_ADDR]], i32 1 +!CHECK: %[[SIZE_2_CALC_1:.*]] = ptrtoint ptr %[[DTYPE_BASE_ADDR_ACCESS_3]] to i64 +!CHECK: %[[SIZE_2_CALC_2:.*]] = ptrtoint ptr %[[DTYPE_BASE_ADDR_ACCESS_3_OFF]] to i64 +!CHECK: %[[SIZE_2_CALC_3:.*]] = sub i64 %[[SIZE_2_CALC_1]], %[[SIZE_2_CALC_2]] +!CHECK: %[[SIZE_2_CALC_4:.*]] = sdiv exact i64 %[[SIZE_2_CALC_3]], ptrtoint (ptr getelementptr (i8, ptr null, i32 1) to i64) +!CHECK: %[[NULL_CMP:.*]] = icmp eq ptr %[[ARRAY_OFFSET]], null +!CHECK: %[[NULL_SEL:.*]] = select i1 %[[NULL_CMP]], i64 0, i64 %[[ALLOCATABLE_MEMBER_SIZE_CALC_5]] +!CHECK: %[[BASE_PTR_ARR:.*]] = getelementptr inbounds [9 x ptr], ptr %.offload_baseptrs, i32 0, i32 0 !CHECK: store ptr %[[DTYPE_DESC_ALLOCA_3]], ptr %[[BASE_PTR_ARR]], align 8 -!CHECK: %[[OFFLOAD_PTR_ARR:.*]] = getelementptr inbounds [8 x ptr], ptr %.offload_ptrs, i32 0, i32 0 +!CHECK: %[[OFFLOAD_PTR_ARR:.*]] = getelementptr inbounds [9 x ptr], ptr %.offload_ptrs, i32 0, i32 0 !CHECK: store ptr %[[DTYPE_DESC_ALLOCA_3]], ptr %[[OFFLOAD_PTR_ARR]], align 8 -!CHECK: %[[OFFLOAD_SIZE_ARR:.*]] = getelementptr inbounds [8 x i64], ptr %.offload_sizes, i32 0, i32 0 +!CHECK: %[[OFFLOAD_SIZE_ARR:.*]] = getelementptr inbounds [9 x i64], ptr %.offload_sizes, i32 0, i32 0 !CHECK: store i64 %[[DTYPE_DESC_SIZE_CALC_5]], ptr %[[OFFLOAD_SIZE_ARR]], align 8 -!CHECK: %[[BASE_PTR_ARR:.*]] = getelementptr inbounds [8 x ptr], ptr %.offload_baseptrs, i32 0, i32 1 +!CHECK: %[[BASE_PTR_ARR:.*]] = getelementptr inbounds [9 x ptr], ptr %.offload_baseptrs, i32 0, i32 1 !CHECK: store ptr %[[DTYPE_DESC_ALLOCA_3]], ptr %[[BASE_PTR_ARR]], align 8 -!CHECK: %[[OFFLOAD_PTR_ARR:.*]] = getelementptr inbounds [8 x ptr], ptr %.offload_ptrs, i32 0, i32 1 +!CHECK: %[[OFFLOAD_PTR_ARR:.*]] = getelementptr inbounds [9 x ptr], ptr %.offload_ptrs, i32 0, i32 1 !CHECK: store ptr %[[DTYPE_DESC_ALLOCA_3]], ptr %[[OFFLOAD_PTR_ARR]], align 8 -!CHECK: %[[BASE_PTR_ARR:.*]] = getelementptr inbounds [8 x ptr], ptr %.offload_baseptrs, i32 0, i32 2 +!CHECK: %[[BASE_PTR_ARR:.*]] = getelementptr inbounds [9 x ptr], ptr %.offload_baseptrs, i32 0, i32 2 !CHECK: store ptr %[[DTYPE_DESC_ALLOCA_3]], ptr %[[BASE_PTR_ARR]], align 8 -!CHECK: %[[OFFLOAD_PTR_ARR:.*]] = getelementptr inbounds [8 x ptr], ptr %.offload_ptrs, i32 0, i32 2 +!CHECK: %[[OFFLOAD_PTR_ARR:.*]] = getelementptr inbounds [9 x ptr], ptr %.offload_ptrs, i32 0, i32 2 +!CHECK: store ptr %[[DTYPE_BASE_ADDR_ACCESS_3_OFF]], ptr %[[OFFLOAD_PTR_ARR]], align 8 +!CHECK: %[[OFFLOAD_SIZE_ARR:.*]] = getelementptr inbounds [9 x i64], ptr %.offload_sizes, i32 0, i32 2 +!CHECK: store i64 %[[SIZE_2_CALC_4]], ptr %[[OFFLOAD_SIZE_ARR]], align 8 +!CHECK: %[[BASE_PTR_ARR:.*]] = getelementptr inbounds [9 x ptr], ptr %.offload_baseptrs, i32 0, i32 3 +!CHECK: store ptr %[[DTYPE_DESC_ALLOCA_3]], ptr %[[BASE_PTR_ARR]], align 8 +!CHECK: %[[OFFLOAD_PTR_ARR:.*]] = getelementptr inbounds [9 x ptr], ptr %.offload_ptrs, i32 0, i32 3 !CHECK: store ptr %[[DTYPE_DESC_BASE_ADDR]], ptr %[[OFFLOAD_PTR_ARR]], align 8 -!CHECK: %[[BASE_PTR_ARR:.*]] = getelementptr inbounds [8 x ptr], ptr %.offload_baseptrs, i32 0, i32 3 +!CHECK: %[[BASE_PTR_ARR:.*]] = getelementptr inbounds [9 x ptr], ptr %.offload_baseptrs, i32 0, i32 4 !CHECK: store ptr %[[DTYPE_DESC_BASE_ADDR]], ptr %[[BASE_PTR_ARR]], align 8 -!CHECK: %[[OFFLOAD_PTR_ARR:.*]] = getelementptr inbounds [8 x ptr], ptr %.offload_ptrs, i32 0, i32 3 +!CHECK: %[[OFFLOAD_PTR_ARR:.*]] = getelementptr inbounds [9 x ptr], ptr %.offload_ptrs, i32 0, i32 4 !CHECK: store ptr %[[LOAD_BASE_ADDR]], ptr %[[OFFLOAD_PTR_ARR]], align 8 -!CHECK: %[[BASE_PTR_ARR:.*]] = getelementptr inbounds [8 x ptr], ptr %.offload_baseptrs, i32 0, i32 4 +!CHECK: %[[BASE_PTR_ARR:.*]] = getelementptr inbounds [9 x ptr], ptr %.offload_baseptrs, i32 0, i32 5 !CHECK: store ptr %[[DTYPE_DESC_ALLOCA_3]], ptr %[[BASE_PTR_ARR]], align 8 -!CHECK: %[[OFFLOAD_PTR_ARR:.*]] = getelementptr inbounds [8 x ptr], ptr %.offload_ptrs, i32 0, i32 4 +!CHECK: %[[OFFLOAD_PTR_ARR:.*]] = getelementptr inbounds [9 x ptr], ptr %.offload_ptrs, i32 0, i32 5 !CHECK: store ptr %[[MAPPED_MEMBER_ACCESS]], ptr %[[OFFLOAD_PTR_ARR]], align 8 -!CHECK: %[[BASE_PTR_ARR:.*]] = getelementptr inbounds [8 x ptr], ptr %.offload_baseptrs, i32 0, i32 5 +!CHECK: %[[BASE_PTR_ARR:.*]] = getelementptr inbounds [9 x ptr], ptr %.offload_baseptrs, i32 0, i32 6 !CHECK: store ptr %[[DTYPE_DESC_ALLOCA_3]], ptr %[[BASE_PTR_ARR]], align 8 -!CHECK: %[[OFFLOAD_PTR_ARR:.*]] = getelementptr inbounds [8 x ptr], ptr %.offload_ptrs, i32 0, i32 5 +!CHECK: %[[OFFLOAD_PTR_ARR:.*]] = getelementptr inbounds [9 x ptr], ptr %.offload_ptrs, i32 0, i32 6 !CHECK: store ptr %[[MAPPED_MEMBER_BASE_ADDR_ACCESS]], ptr %[[OFFLOAD_PTR_ARR]], align 8 -!CHECK: %[[BASE_PTR_ARR:.*]] = getelementptr inbounds [8 x ptr], ptr %.offload_baseptrs, i32 0, i32 6 +!CHECK: %[[BASE_PTR_ARR:.*]] = getelementptr inbounds [9 x ptr], ptr %.offload_baseptrs, i32 0, i32 7 !CHECK: store ptr %[[MAPPED_MEMBER_BASE_ADDR_ACCESS]], ptr %[[BASE_PTR_ARR]], align 8 -!CHECK: %[[OFFLOAD_PTR_ARR:.*]] = getelementptr inbounds [8 x ptr], ptr %.offload_ptrs, i32 0, i32 6 +!CHECK: %[[OFFLOAD_PTR_ARR:.*]] = getelementptr inbounds [9 x ptr], ptr %.offload_ptrs, i32 0, i32 7 !CHECK: store ptr %[[ARRAY_OFFSET]], ptr %[[OFFLOAD_PTR_ARR]], align 8 -!CHECK: %[[OFFLOAD_SIZE_ARR:.*]] = getelementptr inbounds [8 x i64], ptr %.offload_sizes, i32 0, i32 6 -!CHECK: store i64 %[[DATA_SEL]], ptr %[[OFFLOAD_SIZE_ARR]], align 8 -!CHECK: %[[BASE_PTR_ARR:.*]] = getelementptr inbounds [8 x ptr], ptr %.offload_baseptrs, i32 0, i32 7 +!CHECK: %[[OFFLOAD_SIZE_ARR:.*]] = getelementptr inbounds [9 x i64], ptr %.offload_sizes, i32 0, i32 7 +!CHECK: store i64 %[[NULL_SEL]], ptr %[[OFFLOAD_SIZE_ARR]], align 8 +!CHECK: %[[BASE_PTR_ARR:.*]] = getelementptr inbounds [9 x ptr], ptr %.offload_baseptrs, i32 0, i32 8 !CHECK: store ptr %[[DTYPE_DESC_ALLOCA_3]], ptr %[[BASE_PTR_ARR]], align 8 -!CHECK: %[[OFFLOAD_PTR_ARR:.*]] = getelementptr inbounds [8 x ptr], ptr %.offload_ptrs, i32 0, i32 7 +!CHECK: %[[OFFLOAD_PTR_ARR:.*]] = getelementptr inbounds [9 x ptr], ptr %.offload_ptrs, i32 0, i32 8 !CHECK: store ptr %[[NESTED_NONALLOCA_MEMBER_ACCESS]], ptr %[[OFFLOAD_PTR_ARR]], align 8 !CHECK-LABEL: define {{.*}} @{{.*}}maptype_nested_derived_type_alloca{{.*}} diff --git a/flang/test/Integration/OpenMP/parallel-private-reduction-worstcase.f90 b/flang/test/Integration/OpenMP/parallel-private-reduction-worstcase.f90 index cf77c46..fd59d39 100644 --- a/flang/test/Integration/OpenMP/parallel-private-reduction-worstcase.f90 +++ b/flang/test/Integration/OpenMP/parallel-private-reduction-worstcase.f90 @@ -174,10 +174,13 @@ end subroutine ! CHECK-NEXT: br label %omp.par.pre_finalize ! CHECK: omp.par.pre_finalize: ; preds = %reduce.finalize +! CHECK-NEXT: br label %.fini + +! CHECK: .fini: ! CHECK-NEXT: %{{.*}} = load ptr, ptr ! CHECK-NEXT: br label %omp.reduction.cleanup -! CHECK: omp.reduction.cleanup: ; preds = %omp.par.pre_finalize +! CHECK: omp.reduction.cleanup: ; preds = %.fini ! [null check] ! CHECK: br i1 %{{.*}}, label %omp.reduction.cleanup43, label %omp.reduction.cleanup44 diff --git a/flang/test/Integration/debug-char-arg-issue-112886.f90 b/flang/test/Integration/debug-char-arg-issue-112886.f90 new file mode 100644 index 0000000..e2ebb38 --- /dev/null +++ b/flang/test/Integration/debug-char-arg-issue-112886.f90 @@ -0,0 +1,46 @@ +! RUN: %flang_fc1 -emit-llvm -debug-info-kind=standalone %s -o - | \ +! RUN: FileCheck %s --check-prefix=LLVM + +! Test CHARACTER argument +subroutine char_arg(str1) + character(len=5) :: str1 + print *, str1 +end subroutine + +! Test CHARACTER argument with different length +subroutine char_arg_len10(str2) + character(len=10) :: str2 + print *, str2 +end subroutine + +! Test multiple CHARACTER arguments +subroutine multi_char_args(s1, s2, s3) + character(len=5) :: s1 + character(len=8) :: s2 + character(len=3) :: s3 + print *, s1, s2, s3 +end subroutine + +! Test mixed argument types (CHARACTER and INTEGER) +subroutine mixed_args(n, str, m) + integer :: n + character(len=7) :: str + integer :: m + print *, n, str, m +end subroutine + +program test + call char_arg('hello') + call char_arg_len10('hello test') + call multi_char_args('abc', 'test123', 'xyz') + call mixed_args(1, 'fortran', 2) +end program test + +! LLVM-DAG: !DILocalVariable(name: "str1", arg: 1 +! LLVM-DAG: !DILocalVariable(name: "str2", arg: 1 +! LLVM-DAG: !DILocalVariable(name: "s1", arg: 1 +! LLVM-DAG: !DILocalVariable(name: "s2", arg: 2 +! LLVM-DAG: !DILocalVariable(name: "s3", arg: 3 +! LLVM-DAG: !DILocalVariable(name: "n", arg: 1 +! LLVM-DAG: !DILocalVariable(name: "str", arg: 2 +! LLVM-DAG: !DILocalVariable(name: "m", arg: 3 diff --git a/flang/test/Integration/debug-module-equivalence.f90 b/flang/test/Integration/debug-module-equivalence.f90 new file mode 100644 index 0000000..ed709f1 --- /dev/null +++ b/flang/test/Integration/debug-module-equivalence.f90 @@ -0,0 +1,20 @@ +! RUN: %flang_fc1 -emit-llvm -debug-info-kind=standalone %s -o - | FileCheck %s + +! Test that module EQUIVALENCE does not generate DICommonBlock. + +module data_module + real :: var1, var2 + equivalence (var1, var2) +end module data_module + +subroutine test_module_equiv + use data_module + var1 = 1.5 + var2 = 2.5 +end subroutine + +program main + call test_module_equiv() +end program + +! CHECK-NOT: DICommonBlock diff --git a/flang/test/Integration/debug-proc-ptr-e2e.f90 b/flang/test/Integration/debug-proc-ptr-e2e.f90 new file mode 100644 index 0000000..aa89160 --- /dev/null +++ b/flang/test/Integration/debug-proc-ptr-e2e.f90 @@ -0,0 +1,26 @@ +! RUN: %flang_fc1 -emit-llvm -debug-info-kind=standalone %s -o - | FileCheck %s + +program test_proc_ptr + implicit none + procedure(fun1), pointer :: fun_ptr + + fun_ptr => fun1 + print *, fun_ptr(3) + +contains + integer function fun1(x) + integer :: x + fun1 = x + 1 + end function fun1 +end program test_proc_ptr + +! Check that fun_ptr is declared with correct type +! CHECK-DAG: ![[INT:.*]] = !DIBasicType(name: "integer", size: 32, encoding: DW_ATE_signed) +! CHECK-DAG: ![[PTR_INT:.*]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[INT]], size: 64) + +! Check that fun_ptr variable is a pointer to a subroutine type +! The order is: DILocalVariable -> pointer type -> subroutine type -> {return, params} +! CHECK-DAG: ![[FUN_PTR_VAR:.*]] = !DILocalVariable(name: "fun_ptr", {{.*}}type: ![[PROC_PTR:[0-9]+]] +! CHECK-DAG: ![[PROC_PTR]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[SUBR_TYPE:[0-9]+]], size: 64) +! CHECK-DAG: ![[SUBR_TYPE]] = !DISubroutineType(types: ![[SUBR_TYPES:[0-9]+]]) +! CHECK-DAG: ![[SUBR_TYPES]] = !{![[INT]], ![[PTR_INT]]} diff --git a/flang/test/Integration/ivdep.f90 b/flang/test/Integration/ivdep.f90 new file mode 100644 index 0000000..b122f58 --- /dev/null +++ b/flang/test/Integration/ivdep.f90 @@ -0,0 +1,116 @@ +! RUN: %flang_fc1 -emit-llvm -o - %s | FileCheck %s + +! CHECK-LABEL: ivdep_test1 +subroutine ivdep_test1 + integer :: a(10) + !dir$ ivdep + ! CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}} + do i=1,10 + a(i)=i + !CHECK: store i32 {{.*}}, ptr {{.*}}, align 4, !llvm.access.group [[DISTRINCT:.*]] + !CHECK: %[[VAL_8:.*]] = load i32, ptr {{.*}}, align 4, !llvm.access.group [[DISTRINCT]] + !CHECK: %[[VAL_9:.*]] = sext i32 %[[VAL_8]] to i64 + !CHECK: %[[VAL_10:.*]] = sub nsw i64 %[[VAL_9]], 1 + !CHECK: %[[VAL_11:.*]] = mul nsw i64 %[[VAL_10]], 1 + !CHECK: %[[VAL_12:.*]] = mul nsw i64 %[[VAL_11]], 1 + !CHECK: %[[VAL_13:.*]] = add nsw i64 %[[VAL_12]], 0 + !CHECK: %[[VAL_14:.*]] = getelementptr i32, ptr {{.*}}, i64 %[[VAL_13]] + !CHECK: store i32 %[[VAL_8]], ptr %[[VAL_14]], align 4, !llvm.access.group [[DISTRINCT]] + !CHECK: %[[VAL_15:.*]] = load i32, ptr {{.*}}, align 4, !llvm.access.group [[DISTRINCT]] + !CHECK: %[[VAL_16:.*]] = add nsw i32 %[[VAL_15]], 1 + !CHECK: %[[VAL_17:.*]] = sub i64 {{.*}}, 1 + !CHECK: br label {{.*}}, !llvm.loop ![[ANNOTATION:.*]] + end do +end subroutine ivdep_test1 + + +! CHECK-LABEL: ivdep_test2 +subroutine ivdep_test2 + integer :: a(10), b(10), c(10) + !dir$ ivdep + !dir$ unknown + ! CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}} + do i=1,10 + a(i)=b(i)+c(i) + !CHECK: store i32 {{.*}}, ptr {{.*}}, align 4, !llvm.access.group [[DISTRINCT1:.*]] + !CHECK: %[[VAL_10:.*]] = load i32, ptr {{.*}}, align 4, !llvm.access.group [[DISTRINCT1]] + !CHECK: %[[VAL_11:.*]] = sext i32 %[[VAL_10]] to i64 + !CHECK: %[[VAL_12:.*]] = sub nsw i64 %[[VAL_11]], 1 + !CHECK: %[[VAL_13:.*]] = mul nsw i64 %[[VAL_12]], 1 + !CHECK: %[[VAL_14:.*]] = mul nsw i64 %[[VAL_13]], 1 + !CHECK: %[[VAL_15:.*]] = add nsw i64 %[[VAL_14]], 0 + !CHECK: %[[VAL_16:.*]] = getelementptr i32, ptr {{.*}}, i64 %[[VAL_15]] + !CHECK: %[[VAL_17:.*]] = load i32, ptr {{.*}}, align 4, !llvm.access.group [[DISTRINCT1]] + !CHECK: %[[VAL_18:.*]] = sub nsw i64 %[[VAL_11]], 1 + !CHECK: %[[VAL_19:.*]] = mul nsw i64 %[[VAL_18]], 1 + !CHECK: %[[VAL_20:.*]] = mul nsw i64 %[[VAL_19]], 1 + !CHECK: %[[VAL_21:.*]] = add nsw i64 %[[VAL_20]], 0 + !CHECK: %[[VAL_22:.*]] = getelementptr i32, ptr {{.*}}, i64 %[[VAL_21]] + !CHECK: %[[VAL_23:.*]] = load i32, ptr {{.*}}, align 4, !llvm.access.group [[DISTRINCT1]] + !CHECK: %[[VAL_24:.*]] = add i32 %[[VAL_17]], %[[VAL_23]] + !CHECK: %[[VAL_25:.*]] = sub nsw i64 %[[VAL_11]], 1 + !CHECK: %[[VAL_26:.*]] = mul nsw i64 %[[VAL_25]], 1 + !CHECK: %[[VAL_27:.*]] = mul nsw i64 %[[VAL_26]], 1 + !CHECK: %[[VAL_28:.*]] = add nsw i64 %[[VAL_27]], 0 + !CHECK: %[[VAL_29:.*]] = getelementptr i32, ptr {{.*}}, i64 %[[VAL_28]] + !CHECK: store i32 %[[VAL_24]], ptr %[[VAL_29]], align 4, !llvm.access.group [[DISTRINCT1]] + !CHECK: %[[VAL_30:.*]] = load i32, ptr {{.*}}, align 4, !llvm.access.group [[DISTRINCT1]] + !CHECK: %[[VAL_31:.*]] = add nsw i32 %[[VAL_30]], 1 + !CHECK: %[[VAL_32:.*]] = sub i64 {{.*}}, 1 + !CHECK: br label {{.*}}, !llvm.loop ![[ANNOTATION1:.*]] + end do +end subroutine ivdep_test2 + + +! CHECK-LABEL: ivdep_test3 +subroutine ivdep_test3 + integer :: a(10), b(10), c(10) + !dir$ ivdep + ! CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}} + do i=1,10 + a(i)=b(i)+c(i) + call foo() + !CHECK: store i32 {{.*}}, ptr {{.*}}, align 4, !llvm.access.group [[DISTRINCT2:.*]] + !CHECK: %[[VAL_10:.*]] = load i32, ptr {{.*}}, align 4, !llvm.access.group [[DISTRINCT2]] + !CHECK: %[[VAL_11:.*]] = sext i32 %[[VAL_10]] to i64 + !CHECK: %[[VAL_12:.*]] = sub nsw i64 %[[VAL_11]], 1 + !CHECK: %[[VAL_13:.*]] = mul nsw i64 %[[VAL_12]], 1 + !CHECK: %[[VAL_14:.*]] = mul nsw i64 %[[VAL_13]], 1 + !CHECK: %[[VAL_15:.*]] = add nsw i64 %[[VAL_14]], 0 + !CHECK: %[[VAL_16:.*]] = getelementptr i32, ptr {{.*}}, i64 %[[VAL_15]] + !CHECK: %[[VAL_17:.*]] = load i32, ptr {{.*}}, align 4, !llvm.access.group [[DISTRINCT2]] + !CHECK: %[[VAL_18:.*]] = sub nsw i64 %[[VAL_11]], 1 + !CHECK: %[[VAL_19:.*]] = mul nsw i64 %[[VAL_18]], 1 + !CHECK: %[[VAL_20:.*]] = mul nsw i64 %[[VAL_19]], 1 + !CHECK: %[[VAL_21:.*]] = add nsw i64 %[[VAL_20]], 0 + !CHECK: %[[VAL_22:.*]] = getelementptr i32, ptr {{.*}}, i64 %[[VAL_21]] + !CHECK: %[[VAL_23:.*]] = load i32, ptr {{.*}}, align 4, !llvm.access.group [[DISTRINCT2]] + !CHECK: %[[VAL_24:.*]] = add i32 %[[VAL_17]], %[[VAL_23]] + !CHECK: %[[VAL_25:.*]] = sub nsw i64 %[[VAL_11]], 1 + !CHECK: %[[VAL_26:.*]] = mul nsw i64 %[[VAL_25]], 1 + !CHECK: %[[VAL_27:.*]] = mul nsw i64 %[[VAL_26]], 1 + !CHECK: %[[VAL_28:.*]] = add nsw i64 %[[VAL_27]], 0 + !CHECK: %[[VAL_29:.*]] = getelementptr i32, ptr {{.*}}, i64 %[[VAL_28]] + !CHECK: store i32 %[[VAL_24]], ptr %[[VAL_29]], align 4, !llvm.access.group [[DISTRINCT2]] + !CHECK: call void @_QFivdep_test3Pfoo(), !llvm.access.group [[DISTRINCT2]] + !CHECK: %[[VAL_30:.*]] = load i32, ptr {{.*}}, align 4, !llvm.access.group [[DISTRINCT2]] + !CHECK: %[[VAL_31:.*]] = add nsw i32 %[[VAL_30]], 1 + !CHECK: %[[VAL_32:.*]] = sub i64 {{.*}}, 1 + !CHECK: br label {{.*}}, !llvm.loop ![[ANNOTATION2:.*]] + end do + contains + subroutine foo() + end subroutine +end subroutine ivdep_test3 + +! CHECK: [[DISTRINCT]] = distinct !{} +! CHECK: ![[ANNOTATION]] = distinct !{![[ANNOTATION]], ![[VECTORIZE:.*]], ![[PARALLEL_ACCESSES:.*]]} +! CHECK: ![[VECTORIZE]] = !{!"llvm.loop.vectorize.enable", i1 true} +! CHECK: ![[PARALLEL_ACCESSES]] = !{!"llvm.loop.parallel_accesses", [[DISTRINCT]]} +! CHECK: [[DISTRINCT1]] = distinct !{} +! CHECK: ![[ANNOTATION1]] = distinct !{![[ANNOTATION1]], ![[VECTORIZE:.*]], ![[PARALLEL_ACCESSES1:.*]]} +! CHECK: ![[PARALLEL_ACCESSES1]] = !{!"llvm.loop.parallel_accesses", [[DISTRINCT1]]} +! CHECK: [[DISTRINCT2]] = distinct !{} +! CHECK: ![[ANNOTATION2]] = distinct !{![[ANNOTATION2]], ![[VECTORIZE:.*]], ![[PARALLEL_ACCESSES2:.*]]} +! CHECK: ![[PARALLEL_ACCESSES2]] = !{!"llvm.loop.parallel_accesses", [[DISTRINCT2]]} + diff --git a/flang/test/Integration/unroll-loops.f90 b/flang/test/Integration/unroll-loops.f90 index 87ab9ef..2c4a349 100644 --- a/flang/test/Integration/unroll-loops.f90 +++ b/flang/test/Integration/unroll-loops.f90 @@ -25,7 +25,7 @@ subroutine unroll(a) ! NO-UNROLL-NEXT: %[[GEP:.*]] = getelementptr i64, ptr %[[ARG0]], i64 %[[IND]] ! NO-UNROLL-NEXT: store <2 x i64> %[[VIND]], ptr %[[GEP]] ! NO-UNROLL-NEXT: %[[NIV:.*]] = add nuw i64 %{{.*}}, 2 - ! NO-UNROLL-NEXT: %[[NVIND]] = add <2 x i64> %[[VIND]], splat (i64 2) + ! NO-UNROLL-NEXT: %[[NVIND]] = add nuw nsw <2 x i64> %[[VIND]], splat (i64 2) ! ! UNROLL-NEXT: %[[VIND1:.*]] = add <2 x i64> %[[VIND]], splat (i64 2) ! UNROLL-NEXT: %[[GEP0:.*]] = getelementptr i64, ptr %[[ARG0]], i64 %[[IND]] diff --git a/flang/test/Integration/unroll.f90 b/flang/test/Integration/unroll.f90 index f2c2ecb..63c71e1 100644 --- a/flang/test/Integration/unroll.f90 +++ b/flang/test/Integration/unroll.f90 @@ -3,7 +3,7 @@ ! CHECK-LABEL: unroll_dir subroutine unroll_dir integer :: a(10) - !dir$ unroll + !dir$ unroll ! CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}} ! CHECK-NOT: !llvm.loop ! CHECK: br label {{.*}}, !llvm.loop ![[UNROLL_ENABLE_FULL_ANNO:.*]] diff --git a/flang/test/Integration/unroll_and_jam.f90 b/flang/test/Integration/unroll_and_jam.f90 index 05b3aaa0..e5e509cc 100644 --- a/flang/test/Integration/unroll_and_jam.f90 +++ b/flang/test/Integration/unroll_and_jam.f90 @@ -27,7 +27,7 @@ end subroutine unroll_and_jam_dir_0 ! CHECK-LABEL: unroll_and_jam_dir_1 subroutine unroll_and_jam_dir_1 integer :: a(10) - !dir$ unroll_and_jam 1 + !dir$ unroll_and_jam 1 ! CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}} ! CHECK-NOT: !llvm.loop ! CHECK: br label {{.*}}, !llvm.loop ![[ANNOTATION_DISABLE]] diff --git a/flang/test/Lower/CUDA/cuda-allocatable.cuf b/flang/test/Lower/CUDA/cuda-allocatable.cuf index 2cf8c7d..43e7165 100644 --- a/flang/test/Lower/CUDA/cuda-allocatable.cuf +++ b/flang/test/Lower/CUDA/cuda-allocatable.cuf @@ -227,6 +227,14 @@ end ! CHECK: %[[FLASE_CONV:.*]] = fir.convert %[[FALSE]] : (i1) -> !fir.logical<4> ! CHECK: fir.store %[[FLASE_CONV]] to %[[PLOG_DECL]]#0 : !fir.ref<!fir.logical<4>> +subroutine devicepointer() + integer, device, pointer :: i(:) + allocate(i(10)) +end + +! CHECK-LABEL: func.func @_QPdevicepointer() +! CHECK: cuf.allocate{{.*}}pointer + subroutine cuda_component() use globals type(t1), pointer, dimension(:) :: d @@ -235,3 +243,21 @@ end subroutine ! CHECK-LABEL: func.func @_QPcuda_component() ! CHECK: cuf.allocate + +subroutine module_allocate() + use globals + allocate(a_device(10)) + allocate(a_managed(10)) + allocate(a_pinned(10)) + deallocate(a_device) + deallocate(a_managed) + deallocate(a_pinned) +end subroutine + +! CHECK-LABEL: func.func @_QPmodule_allocate() +! CHECK: cuf.allocate %{{.*}} : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>> {data_attr = #cuf.cuda<device>, hasDoubleDescriptor} -> i32 +! CHECK: cuf.allocate %{{.*}} : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>> {data_attr = #cuf.cuda<managed>, hasDoubleDescriptor} -> i32 +! CHECK: cuf.allocate %{{.*}} : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>> {data_attr = #cuf.cuda<pinned>} -> i32 +! CHECK: cuf.deallocate %{{.*}} : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>> {data_attr = #cuf.cuda<device>, hasDoubleDescriptor} -> i32 +! CHECK: cuf.deallocate %{{.*}} : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>> {data_attr = #cuf.cuda<managed>, hasDoubleDescriptor} -> i32 +! CHECK: cuf.deallocate %{{.*}} : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>> {data_attr = #cuf.cuda<pinned>} -> i32 diff --git a/flang/test/Lower/CUDA/cuda-atomicadd.cuf b/flang/test/Lower/CUDA/cuda-atomicadd.cuf new file mode 100644 index 0000000..573e012 --- /dev/null +++ b/flang/test/Lower/CUDA/cuda-atomicadd.cuf @@ -0,0 +1,35 @@ +! RUN: bbc -emit-hlfir -fcuda %s -o - | FileCheck %s + +! Test CUDA Fortran atmoicadd functions available cudadevice module + +attributes(global) subroutine test_atomicaddvector_r2() + real(2), device :: a(2), tmp1(2), tmp2(2) + tmp1 = atomicAddVector(a, tmp2) +end subroutine + +! CHECK-LABEL: func.func @_QPtest_atomicaddvector_r2() attributes {cuf.proc_attr = #cuf.cuda_proc<global>} +! CHECK: llvm.atomicrmw fadd %{{.*}}, %{{.*}} seq_cst : !llvm.ptr, vector<2xf16> + +attributes(global) subroutine test_atomicaddvector_r4() + real(4), device :: a(2), tmp1(2), tmp2(2) + tmp1 = atomicAddVector(a, tmp2) +end subroutine + +! CHECK-LABEL: func.func @_QPtest_atomicaddvector_r4() attributes {cuf.proc_attr = #cuf.cuda_proc<global>} +! CHECK: llvm.atomicrmw fadd %{{.*}}, %{{.*}} seq_cst : !llvm.ptr, vector<2xf32> + +attributes(global) subroutine test_atomicadd_r2x4() + real(4), device :: a(2), tmp1(2), tmp2(2) + tmp1 = atomicaddreal4x2(a, tmp2) +end subroutine + +! CHECK-LABEL: func.func @_QPtest_atomicadd_r2x4() attributes {cuf.proc_attr = #cuf.cuda_proc<global>} +! CHECK: llvm.atomicrmw fadd %{{.*}}, %{{.*}} seq_cst : !llvm.ptr, vector<2xf32> + +attributes(global) subroutine test_atomicadd_r4x4() + real(4), device :: a(4), tmp1(4), tmp2(4) + tmp1 = atomicaddreal4x4(a, tmp2) +end subroutine + +! CHECK-LABEL: func.func @_QPtest_atomicadd_r4x4() attributes {cuf.proc_attr = #cuf.cuda_proc<global>} +! CHECK: atom.add.v4.f32 diff --git a/flang/test/Lower/CUDA/cuda-cluster.cuf b/flang/test/Lower/CUDA/cuda-cluster.cuf new file mode 100644 index 0000000..78cca15 --- /dev/null +++ b/flang/test/Lower/CUDA/cuda-cluster.cuf @@ -0,0 +1,55 @@ +! RUN: bbc -emit-hlfir -fcuda %s -o - | FileCheck %s + +attributes(global) subroutine test_this_cluster() + use cooperative_groups + type(cluster_group) :: cluster + + cluster = this_cluster() +end subroutine + +! CHECK-LABEL: func.func @_QPtest_this_cluster() attributes {cuf.proc_attr = #cuf.cuda_proc<global>} +! CHECK: %{{.*}} = fir.alloca !fir.type<_QMcooperative_groupsTcluster_group +! CHECK: %[[RES:.*]] = fir.alloca !fir.type<_QMcooperative_groupsTcluster_group{_QMcooperative_groupsTcluster_group.handle:!fir.type<_QM__fortran_builtinsT__builtin_c_devptr{cptr:!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>}>,size:i32,rank:i32}> +! CHECK: %[[RANK:.*]] = nvvm.read.ptx.sreg.cluster.ctarank : i32 +! CHECK: %[[RANK_1:.*]] = arith.addi %[[RANK]], %c1{{.*}} : i32 +! CHECK: %[[RANK_COORD:.*]] = fir.coordinate_of %[[RES]], rank : (!fir.ref<!fir.type<_QMcooperative_groupsTcluster_group{_QMcooperative_groupsTcluster_group.handle:!fir.type<_QM__fortran_builtinsT__builtin_c_devptr{cptr:!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>}>,size:i32,rank:i32}>>) -> !fir.ref<i32> +! CHECK: fir.store %[[RANK_1]] to %[[RANK_COORD]] : !fir.ref<i32> + +attributes(global) subroutine test_cluster_dim_blocks() + use cooperative_groups + type(dim3) :: clusterDim + + clusterDim = cluster_dim_blocks() +end subroutine + +! CHECK-LABEL: func.func @_QPtest_cluster_dim_blocks() attributes {cuf.proc_attr = #cuf.cuda_proc<global>} +! CHECK: %[[X:.*]] = nvvm.read.ptx.sreg.cluster.nctaid.x : i32 +! CHECK: %[[COORD_X:.*]] = fir.coordinate_of %{{.*}}, x : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_dim3{x:i32,y:i32,z:i32}>>) -> !fir.ref<i32> +! CHECK: fir.store %[[X]] to %[[COORD_X]] : !fir.ref<i32> +! CHECK: %[[Y:.*]] = nvvm.read.ptx.sreg.cluster.nctaid.y : i32 +! CHECK: %[[COORD_Y:.*]] = fir.coordinate_of %{{.*}}, y : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_dim3{x:i32,y:i32,z:i32}>>) -> !fir.ref<i32> +! CHECK: fir.store %[[Y]] to %[[COORD_Y]] : !fir.ref<i32> +! CHECK: %[[Z:.*]] = nvvm.read.ptx.sreg.cluster.nctaid.z : i32 +! CHECK: %[[COORD_Z:.*]] = fir.coordinate_of %{{.*}}, z : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_dim3{x:i32,y:i32,z:i32}>>) -> !fir.ref<i32> +! CHECK: fir.store %[[Z]] to %[[COORD_Z]] : !fir.ref<i32> + +attributes(global) subroutine test_cluster_block_index() + use cooperative_groups + type(dim3) :: blockIndex + + blockIndex = cluster_block_index() +end subroutine + +! CHECK-LABEL: func.func @_QPtest_cluster_block_index() attributes {cuf.proc_attr = #cuf.cuda_proc<global>} +! CHECK: %[[X:.*]] = nvvm.read.ptx.sreg.cluster.ctaid.x : i32 +! CHECK: %[[X1:.*]] = arith.addi %[[X]], %c1{{.*}} : i32 +! CHECK: %[[COORD_X:.*]] = fir.coordinate_of %{{.*}}, x : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_dim3{x:i32,y:i32,z:i32}>>) -> !fir.ref<i32> +! CHECK: fir.store %[[X1]] to %[[COORD_X]] : !fir.ref<i32> +! CHECK: %[[Y:.*]] = nvvm.read.ptx.sreg.cluster.ctaid.y : i32 +! CHECK: %[[Y1:.*]] = arith.addi %[[Y]], %c1{{.*}} : i32 +! CHECK: %[[COORD_Y:.*]] = fir.coordinate_of %{{.*}}, y : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_dim3{x:i32,y:i32,z:i32}>>) -> !fir.ref<i32> +! CHECK: fir.store %[[Y1]] to %[[COORD_Y]] : !fir.ref<i32> +! CHECK: %[[Z:.*]] = nvvm.read.ptx.sreg.cluster.ctaid.z : i32 +! CHECK: %[[Z1:.*]] = arith.addi %[[Z]], %c1{{.*}} : i32 +! CHECK: %[[COORD_Z:.*]] = fir.coordinate_of %{{.*}}, z : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_dim3{x:i32,y:i32,z:i32}>>) -> !fir.ref<i32> +! CHECK: fir.store %[[Z1]] to %[[COORD_Z]] : !fir.ref<i32> diff --git a/flang/test/Lower/CUDA/cuda-data-attribute.cuf b/flang/test/Lower/CUDA/cuda-data-attribute.cuf index 9023bc7..17bdce9 100644 --- a/flang/test/Lower/CUDA/cuda-data-attribute.cuf +++ b/flang/test/Lower/CUDA/cuda-data-attribute.cuf @@ -54,28 +54,28 @@ subroutine dummy_arg_device(dd) end subroutine ! CHECK-LABEL: func.func @_QMcuda_varPdummy_arg_device( ! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<f32> {cuf.data_attr = #cuf.cuda<device>, fir.bindc_name = "dd"}) { -! CHECK: %{{.*}}:2 = hlfir.declare %[[ARG0]] dummy_scope %{{[0-9]+}} {data_attr = #cuf.cuda<device>, uniq_name = "_QMcuda_varFdummy_arg_deviceEdd"} : (!fir.ref<f32>, !fir.dscope) -> (!fir.ref<f32>, !fir.ref<f32>) +! CHECK: %{{.*}}:2 = hlfir.declare %[[ARG0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {data_attr = #cuf.cuda<device>, uniq_name = "_QMcuda_varFdummy_arg_deviceEdd"} : (!fir.ref<f32>, !fir.dscope) -> (!fir.ref<f32>, !fir.ref<f32>) subroutine dummy_arg_managed(dm) real, allocatable, managed :: dm end subroutine ! CHECK-LABEL: func.func @_QMcuda_varPdummy_arg_managed( ! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.box<!fir.heap<f32>>> {cuf.data_attr = #cuf.cuda<managed>, fir.bindc_name = "dm"}) { -! CHECK: %{{.*}}:2 = hlfir.declare %[[ARG0]] dummy_scope %{{[0-9]+}} {data_attr = #cuf.cuda<managed>, fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QMcuda_varFdummy_arg_managedEdm"} : (!fir.ref<!fir.box<!fir.heap<f32>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<f32>>>, !fir.ref<!fir.box<!fir.heap<f32>>>) +! CHECK: %{{.*}}:2 = hlfir.declare %[[ARG0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {data_attr = #cuf.cuda<managed>, fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QMcuda_varFdummy_arg_managedEdm"} : (!fir.ref<!fir.box<!fir.heap<f32>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<f32>>>, !fir.ref<!fir.box<!fir.heap<f32>>>) subroutine dummy_arg_pinned(dp) real, allocatable, pinned :: dp end subroutine ! CHECK-LABEL: func.func @_QMcuda_varPdummy_arg_pinned( ! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.box<!fir.heap<f32>>> {cuf.data_attr = #cuf.cuda<pinned>, fir.bindc_name = "dp"}) { -! CHECK: %{{.*}}:2 = hlfir.declare %[[ARG0]] dummy_scope %{{[0-9]+}} {data_attr = #cuf.cuda<pinned>, fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QMcuda_varFdummy_arg_pinnedEdp"} : (!fir.ref<!fir.box<!fir.heap<f32>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<f32>>>, !fir.ref<!fir.box<!fir.heap<f32>>>) +! CHECK: %{{.*}}:2 = hlfir.declare %[[ARG0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {data_attr = #cuf.cuda<pinned>, fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QMcuda_varFdummy_arg_pinnedEdp"} : (!fir.ref<!fir.box<!fir.heap<f32>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<f32>>>, !fir.ref<!fir.box<!fir.heap<f32>>>) subroutine dummy_arg_unified(du) real, unified :: du end subroutine ! CHECK-LABEL: func.func @_QMcuda_varPdummy_arg_unified( ! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<f32> {cuf.data_attr = #cuf.cuda<unified>, fir.bindc_name = "du"}) -! CHECK: %{{.*}}:2 = hlfir.declare %[[ARG0]] dummy_scope %{{[0-9]+}} {data_attr = #cuf.cuda<unified>, uniq_name = "_QMcuda_varFdummy_arg_unifiedEdu"} : (!fir.ref<f32>, !fir.dscope) -> (!fir.ref<f32>, !fir.ref<f32>) +! CHECK: %{{.*}}:2 = hlfir.declare %[[ARG0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {data_attr = #cuf.cuda<unified>, uniq_name = "_QMcuda_varFdummy_arg_unifiedEdu"} : (!fir.ref<f32>, !fir.dscope) -> (!fir.ref<f32>, !fir.ref<f32>) subroutine cuda_alloc_free(n) integer :: n diff --git a/flang/test/Lower/CUDA/cuda-data-transfer.cuf b/flang/test/Lower/CUDA/cuda-data-transfer.cuf index b0b8d09..0159474 100644 --- a/flang/test/Lower/CUDA/cuda-data-transfer.cuf +++ b/flang/test/Lower/CUDA/cuda-data-transfer.cuf @@ -199,9 +199,9 @@ end subroutine ! CHECK-LABEL: func.func @_QPsub7( ! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> {cuf.data_attr = #cuf.cuda<device>, fir.bindc_name = "a"}, %[[ARG1:.*]]: !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> {fir.bindc_name = "b"}, %[[ARG2:.*]]: !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> {cuf.data_attr = #cuf.cuda<device>, fir.bindc_name = "c"}) { -! CHECK: %[[A:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{.*}} {data_attr = #cuf.cuda<device>, fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFsub7Ea"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) -! CHECK: %[[B:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %{{.*}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFsub7Eb"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) -! CHECK: %[[C:.*]]:2 = hlfir.declare %[[ARG2]] dummy_scope %0 {data_attr = #cuf.cuda<device>, fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFsub7Ec"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) +! CHECK: %[[A:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{.*}} arg {{[0-9]+}} {data_attr = #cuf.cuda<device>, fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFsub7Ea"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) +! CHECK: %[[B:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %{{.*}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFsub7Eb"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) +! CHECK: %[[C:.*]]:2 = hlfir.declare %[[ARG2]] dummy_scope %0 arg {{[0-9]+}} {data_attr = #cuf.cuda<device>, fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFsub7Ec"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) ! CHECK: cuf.data_transfer %[[A]]#0 to %[[B]]#0 {transfer_kind = #cuf.cuda_transfer<device_host>} : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> ! CHECK: cuf.data_transfer %[[B]]#0 to %[[A]]#0 {transfer_kind = #cuf.cuda_transfer<host_device>} : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> ! CHECK: cuf.data_transfer %[[A]]#0 to %[[C]]#0 {transfer_kind = #cuf.cuda_transfer<device_device>} : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> @@ -216,8 +216,8 @@ end subroutine ! CHECK-LABEL: func.func @_QPsub8( ! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.array<?xi32>> {cuf.data_attr = #cuf.cuda<device>, fir.bindc_name = "a"}, %[[ARG1:.*]]: !fir.ref<!fir.array<10xi32>> {fir.bindc_name = "b"}, %[[ARG2:.*]]: !fir.ref<i32> {fir.bindc_name = "n"}) -! CHECK: %[[B:.*]]:2 = hlfir.declare %[[ARG1]](%{{.*}}) dummy_scope %{{.*}} {uniq_name = "_QFsub8Eb"} : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>) -! CHECK: %[[A:.*]]:2 = hlfir.declare %[[ARG0]](%{{.*}}) dummy_scope %{{.*}} {data_attr = #cuf.cuda<device>, uniq_name = "_QFsub8Ea"} : (!fir.ref<!fir.array<?xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.box<!fir.array<?xi32>>, !fir.ref<!fir.array<?xi32>>) +! CHECK: %[[B:.*]]:2 = hlfir.declare %[[ARG1]](%{{.*}}) dummy_scope %{{.*}} {{.*}} {uniq_name = "_QFsub8Eb"} : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>) +! CHECK: %[[A:.*]]:2 = hlfir.declare %[[ARG0]](%{{.*}}) dummy_scope %{{.*}} {{.*}} {data_attr = #cuf.cuda<device>, uniq_name = "_QFsub8Ea"} : (!fir.ref<!fir.array<?xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.box<!fir.array<?xi32>>, !fir.ref<!fir.array<?xi32>>) ! CHECK: cuf.data_transfer %[[A]]#1 to %[[B]]#0, %{{.*}} : !fir.shape<1> {transfer_kind = #cuf.cuda_transfer<device_host>} : !fir.ref<!fir.array<?xi32>>, !fir.ref<!fir.array<10xi32>> ! CHECK: cuf.data_transfer %[[B]]#0 to %[[A]]#1, %{{.*}} : !fir.shape<1> {transfer_kind = #cuf.cuda_transfer<host_device>} : !fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<?xi32>> @@ -242,7 +242,7 @@ end subroutine ! CHECK-LABEL: func.func @_QPsub10( ! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<i32> {cuf.data_attr = #cuf.cuda<device>, fir.bindc_name = "a"} -! CHECK: %[[A:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %1 {data_attr = #cuf.cuda<device>, uniq_name = "_QFsub10Ea"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[A:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %1 {{.*}} {data_attr = #cuf.cuda<device>, uniq_name = "_QFsub10Ea"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: cuf.data_transfer %[[A]]#0 to %{{.*}}#0 {transfer_kind = #cuf.cuda_transfer<device_host>} : !fir.ref<i32>, !fir.ref<i32> ! CHECK-NOT: cuf.data_transfer @@ -305,9 +305,9 @@ end subroutine ! CHECK-LABEL: func.func @_QPsub15( ! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.array<?xf32>> {cuf.data_attr = #cuf.cuda<device>, fir.bindc_name = "a_dev"}, %[[ARG1:.*]]: !fir.ref<!fir.array<?xf32>> {fir.bindc_name = "a_host"} -! CHECK: %[[ADEV:.*]]:2 = hlfir.declare %[[ARG0]](%{{.*}}) dummy_scope %{{.*}} {data_attr = #cuf.cuda<device>, uniq_name = "_QFsub15Ea_dev"} : (!fir.ref<!fir.array<?xf32>>, !fir.shape<1>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.ref<!fir.array<?xf32>>) +! CHECK: %[[ADEV:.*]]:2 = hlfir.declare %[[ARG0]](%{{.*}}) dummy_scope %{{.*}} {{.*}} {data_attr = #cuf.cuda<device>, uniq_name = "_QFsub15Ea_dev"} : (!fir.ref<!fir.array<?xf32>>, !fir.shape<1>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.ref<!fir.array<?xf32>>) ! CHECK: %[[SHAPE:.*]] = fir.shape %{{.*}} : (index) -> !fir.shape<1> -! CHECK: %[[AHOST:.*]]:2 = hlfir.declare %[[ARG1]](%{{.*}}) dummy_scope %{{.*}} {uniq_name = "_QFsub15Ea_host"} : (!fir.ref<!fir.array<?xf32>>, !fir.shape<1>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.ref<!fir.array<?xf32>>) +! CHECK: %[[AHOST:.*]]:2 = hlfir.declare %[[ARG1]](%{{.*}}) dummy_scope %{{.*}} {{.*}} {uniq_name = "_QFsub15Ea_host"} : (!fir.ref<!fir.array<?xf32>>, !fir.shape<1>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.ref<!fir.array<?xf32>>) ! CHECK: cuf.data_transfer %[[AHOST]]#1 to %[[ADEV]]#1, %[[SHAPE]] : !fir.shape<1> {transfer_kind = #cuf.cuda_transfer<host_device>} : !fir.ref<!fir.array<?xf32>>, !fir.ref<!fir.array<?xf32>> ! Check that cuf.data_transfer are not generated within OpenACC region diff --git a/flang/test/Lower/CUDA/cuda-device-proc.cuf b/flang/test/Lower/CUDA/cuda-device-proc.cuf index 09b4302..27ef8e0 100644 --- a/flang/test/Lower/CUDA/cuda-device-proc.cuf +++ b/flang/test/Lower/CUDA/cuda-device-proc.cuf @@ -14,15 +14,14 @@ attributes(global) subroutine devsub() integer :: smalltime integer(4) :: res, offset integer(8) :: resl + real(2) :: r2a(2) + real(2) :: tmp2(2) integer :: tid tid = threadIdx%x call syncthreads() call syncwarp(1) - call threadfence() - call threadfence_block() - call threadfence_system() ret = syncthreads_and(1) res = syncthreads_and(tid > offset) ret = syncthreads_count(1) @@ -34,6 +33,7 @@ attributes(global) subroutine devsub() al = atomicadd(al, 1_8) af = atomicadd(af, 1.0_4) ad = atomicadd(ad, 1.0_8) + ai = atomicadd(r2a, tmp2) ai = atomicsub(ai, 1_4) al = atomicsub(al, 1_8) @@ -102,32 +102,30 @@ end ! CHECK-LABEL: func.func @_QPdevsub() attributes {cuf.proc_attr = #cuf.cuda_proc<global>} ! CHECK: nvvm.barrier0 -! CHECK: fir.call @llvm.nvvm.bar.warp.sync(%c1{{.*}}) fastmath<contract> : (i32) -> () -! CHECK: fir.call @llvm.nvvm.membar.gl() fastmath<contract> : () -> () -! CHECK: fir.call @llvm.nvvm.membar.cta() fastmath<contract> : () -> () -! CHECK: fir.call @llvm.nvvm.membar.sys() fastmath<contract> : () -> () -! CHECK: %{{.*}} = fir.call @llvm.nvvm.barrier0.and(%c1{{.*}}) fastmath<contract> : (i32) -> i32 +! CHECK: nvvm.bar.warp.sync %c1{{.*}} : i32 +! CHECK: %{{.*}} = nvvm.barrier #nvvm.reduction<and> %c1{{.*}} -> i32 ! CHECK: %[[A:.*]] = fir.load %{{.*}} : !fir.ref<i32> ! CHECK: %[[B:.*]] = fir.load %{{.*}} : !fir.ref<i32> ! CHECK: %[[CMP:.*]] = arith.cmpi sgt, %[[A]], %[[B]] : i32 ! CHECK: %[[CONV:.*]] = fir.convert %[[CMP]] : (i1) -> i32 -! CHECK: %{{.*}} = fir.call @llvm.nvvm.barrier0.and(%[[CONV]]) -! CHECK: %{{.*}} = fir.call @llvm.nvvm.barrier0.popc(%c1{{.*}}) fastmath<contract> : (i32) -> i32 +! CHECK: %{{.*}} = nvvm.barrier #nvvm.reduction<and> %[[CONV]] -> i32 +! CHECK: %{{.*}} = nvvm.barrier #nvvm.reduction<popc> %c1{{.*}} -> i32 ! CHECK: %[[A:.*]] = fir.load %{{.*}} : !fir.ref<i32> ! CHECK: %[[B:.*]] = fir.load %{{.*}} : !fir.ref<i32> ! CHECK: %[[CMP:.*]] = arith.cmpi sgt, %[[A]], %[[B]] : i32 ! CHECK: %[[CONV:.*]] = fir.convert %[[CMP]] : (i1) -> i32 -! CHECK: %{{.*}} = fir.call @llvm.nvvm.barrier0.popc(%[[CONV]]) fastmath<contract> : (i32) -> i32 -! CHECK: %{{.*}} = fir.call @llvm.nvvm.barrier0.or(%c1{{.*}}) fastmath<contract> : (i32) -> i32 +! CHECK: %{{.*}} = nvvm.barrier #nvvm.reduction<popc> %[[CONV]] -> i32 +! CHECK: %{{.*}} = nvvm.barrier #nvvm.reduction<or> %c1{{.*}} -> i32 ! CHECK: %[[A:.*]] = fir.load %{{.*}} : !fir.ref<i32> ! CHECK: %[[B:.*]] = fir.load %{{.*}} : !fir.ref<i32> ! CHECK: %[[CMP:.*]] = arith.cmpi sgt, %[[A]], %[[B]] : i32 ! CHECK: %[[CONV:.*]] = fir.convert %[[CMP]] : (i1) -> i32 -! CHECK: %{{.*}} = fir.call @llvm.nvvm.barrier0.or(%[[CONV]]) fastmath<contract> : (i32) -> i32 +! CHECK: %{{.*}} = nvvm.barrier #nvvm.reduction<or> %[[CONV]] -> i32 ! CHECK: %{{.*}} = llvm.atomicrmw add %{{.*}}, %{{.*}} seq_cst : !llvm.ptr, i32 ! CHECK: %{{.*}} = llvm.atomicrmw add %{{.*}}, %{{.*}} seq_cst : !llvm.ptr, i64 ! CHECK: %{{.*}} = llvm.atomicrmw fadd %{{.*}}, %{{.*}} seq_cst : !llvm.ptr, f32 ! CHECK: %{{.*}} = llvm.atomicrmw fadd %{{.*}}, %{{.*}} seq_cst : !llvm.ptr, f64 +! CHECK: %{{.*}} = llvm.atomicrmw fadd %{{.*}}, %{{.*}} seq_cst : !llvm.ptr, vector<2xf16> ! CHECK: %{{.*}} = llvm.atomicrmw sub %{{.*}}, %{{.*}} seq_cst : !llvm.ptr, i32 ! CHECK: %{{.*}} = llvm.atomicrmw sub %{{.*}}, %{{.*}} seq_cst : !llvm.ptr, i64 @@ -215,10 +213,10 @@ end ! CHECK-LABEL: func.func @_QPhost1() ! CHECK: cuf.kernel ! CHECK: nvvm.barrier0 -! CHECK: fir.call @llvm.nvvm.bar.warp.sync(%c1{{.*}}) fastmath<contract> : (i32) -> () -! CHECK: fir.call @llvm.nvvm.barrier0.and(%c1{{.*}}) fastmath<contract> : (i32) -> i32 -! CHECK: fir.call @llvm.nvvm.barrier0.popc(%c1{{.*}}) fastmath<contract> : (i32) -> i32 -! CHECK: fir.call @llvm.nvvm.barrier0.or(%c1{{.*}}) fastmath<contract> : (i32) -> i32 +! CHECK: nvvm.bar.warp.sync %c1{{.*}} : i32 +! CHECK: nvvm.barrier #nvvm.reduction<and> %c1{{.*}} -> i32 +! CHECK: nvvm.barrier #nvvm.reduction<popc> %c1{{.*}} -> i32 +! CHECK: nvvm.barrier #nvvm.reduction<or> %c1{{.*}} -> i32 attributes(device) subroutine testMatch() integer :: a, ipred, mask, v32 @@ -436,11 +434,11 @@ end subroutine ! CHECK: %[[LLVM_PTR:.*]] = fir.convert %[[DECL_SHARED]]#0 : (!fir.ref<i64>) -> !llvm.ptr ! CHECK: %[[SHARED_PTR:.*]] = llvm.addrspacecast %[[LLVM_PTR]] : !llvm.ptr to !llvm.ptr<3> -! CHECK: %{{.*}} = nvvm.mbarrier.arrive.shared %[[SHARED_PTR]] : !llvm.ptr<3> -> i64 +! CHECK: %{{.*}} = nvvm.mbarrier.arrive %[[SHARED_PTR]] : !llvm.ptr<3> -> i64 ! CHECK: %[[LLVM_PTR:.*]] = fir.convert %[[DECL_SHARED]]#0 : (!fir.ref<i64>) -> !llvm.ptr ! CHECK: %[[SHARED_PTR:.*]] = llvm.addrspacecast %[[LLVM_PTR]] : !llvm.ptr to !llvm.ptr<3> -! CHECK: nvvm.mbarrier.arrive.expect_tx %[[SHARED_PTR]], %{{.*}} : !llvm.ptr<3>, i32 +! CHECK: %{{.*}} = nvvm.inline_ptx "mbarrier.arrive.expect_tx.release.cta.shared::cta.b64 %{{.*}}, [%{{.*}}], %{{.*}};" ro(%{{.*}}, %{{.*}} : !llvm.ptr<3>, i32) -> i64 attributes(global) subroutine test_fence() @@ -479,7 +477,7 @@ end subroutine ! CHECK: %[[DST_7:.*]] = llvm.addrspacecast %[[DST_PTR]] : !llvm.ptr to !llvm.ptr<7> ! CHECK: %[[SRC_PTR:.*]] = fir.convert %[[SRC]] : (!fir.ref<f64>) -> !llvm.ptr ! CHECK: %[[SRC_3:.*]] = llvm.addrspacecast %[[SRC_PTR]] : !llvm.ptr to !llvm.ptr<1> -! CHECK: nvvm.cp.async.bulk.shared.cluster.global %[[DST_7]], %[[SRC_3]], %[[BARRIER_3]], %[[COUNT_LOAD]] : <7>, <1> +! CHECK: nvvm.cp.async.bulk.shared.cluster.global %[[DST_7]], %[[SRC_3]], %[[BARRIER_3]], %[[COUNT_LOAD]] : !llvm.ptr<7>, <1> attributes(global) subroutine test_bulk_s2g(a) real(8), device :: a(*) @@ -490,7 +488,7 @@ end subroutine ! CHECK-LABEL: func.func @_QPtest_bulk_s2g ! CHECL: nvvm.cp.async.bulk.global.shared.cta %{{.*}}, %{{.*}}, %{{.*}} : <1>, <3> -! CHECK: nvvm.inline_ptx "cp.async.bulk.commit_group" +! CHECK: nvvm.inline_ptx "cp.async.bulk.commit_group;" ! CHECK: nvvm.cp.async.bulk.wait_group 0 attributes(device) subroutine testAtomicCasLoop(aa, n) @@ -515,7 +513,7 @@ end subroutine ! CHECK-LABEL: func.func @_QPtest_barrier_try_wait() ! CHECK: scf.while -! CHECK: %{{.*}} = nvvm.inline_ptx ".reg .pred p; mbarrier.try_wait.shared.b64 p, [%{{.*}}], %{{.*}}, %{{.*}}; selp.b32 %{{.*}}, 1, 0, p;" ro(%{{.*}}, %{{.*}}, %c1000000{{.*}} : !llvm.ptr, i64, i32) -> i32 +! CHECK: %{{.*}} = nvvm.inline_ptx "{\0A .reg .pred p;\0A mbarrier.try_wait.shared.b64 p, [%{{.*}}], %{{.*}}, %{{.*}};\0A selp.b32 %{{.*}}, 1, 0, p;\0A}" ro(%{{.*}}, %{{.*}}, %{{.*}} : !llvm.ptr, i64, i32) -> i32 attributes(global) subroutine test_barrier_try_wait_sleep() integer :: istat @@ -526,7 +524,7 @@ attributes(global) subroutine test_barrier_try_wait_sleep() end subroutine ! CHECK-LABEL: func.func @_QPtest_barrier_try_wait_sleep() -! CHECK: %{{.*}} = nvvm.inline_ptx ".reg .pred p; mbarrier.try_wait.shared.b64 p, [%{{.*}}], %{{.*}}, %{{.*}}; selp.b32 %0, 1, 0, p;" ro(%{{.*}}, %{{.*}}, %{{.*}} : !llvm.ptr, i64, i32) -> i32 +! CHECK: %{{.*}} = nvvm.inline_ptx "{\0A .reg .pred p;\0A mbarrier.try_wait.shared.b64 p, [%{{.*}}], %{{.*}}, %{{.*}};\0A selp.b32 %{{.*}}, 1, 0, p;\0A}" ro(%{{.*}}, %{{.*}}, %{{.*}} : !llvm.ptr, i64, i32) -> i32 attributes(global) subroutine test_tma_bulk_load_c4(a, n) integer(8), shared :: barrier1 @@ -540,6 +538,7 @@ end subroutine ! CHECK-LABEL: func.func @_QPtest_tma_bulk_load_c4 ! CHECK: %[[BARRIER:.*]]:2 = hlfir.declare %{{.*}} {data_attr = #cuf.cuda<shared>, uniq_name = "_QFtest_tma_bulk_load_c4Ebarrier1"} : (!fir.ref<i64>) -> (!fir.ref<i64>, !fir.ref<i64>) ! CHECK: %[[ELEM_COUNT:.*]]:2 = hlfir.declare %{{.*}} {data_attr = #cuf.cuda<device>, uniq_name = "_QFtest_tma_bulk_load_c4Eelem_count"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: cuf.shared_memory !fir.array<1024xcomplex<f32>> align 16 {bindc_name = "tmp", uniq_name = "_QFtest_tma_bulk_load_c4Etmp"} -> !fir.ref<!fir.array<1024xcomplex<f32>>> ! CHECK: %[[COUNT:.*]] = fir.load %[[ELEM_COUNT]]#0 : !fir.ref<i32> ! CHECK: %[[ELEM_SIZE:.*]] = arith.constant 8 : i32 ! CHECK: %[[SIZE:.*]] = arith.muli %[[COUNT]], %[[ELEM_SIZE]] : i32 @@ -559,6 +558,7 @@ end subroutine ! CHECK-LABEL: func.func @_QPtest_tma_bulk_load_c8 ! CHECK: %[[BARRIER:.*]]:2 = hlfir.declare %{{.*}} {data_attr = #cuf.cuda<shared>, uniq_name = "_QFtest_tma_bulk_load_c8Ebarrier1"} : (!fir.ref<i64>) -> (!fir.ref<i64>, !fir.ref<i64>) ! CHECK: %[[ELEM_COUNT:.*]]:2 = hlfir.declare %{{.*}} {data_attr = #cuf.cuda<device>, uniq_name = "_QFtest_tma_bulk_load_c8Eelem_count"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: cuf.shared_memory !fir.array<1024xcomplex<f64>> align 16 {bindc_name = "tmp", uniq_name = "_QFtest_tma_bulk_load_c8Etmp"} -> !fir.ref<!fir.array<1024xcomplex<f64>>> ! CHECK: %[[COUNT:.*]] = fir.load %[[ELEM_COUNT]]#0 : !fir.ref<i32> ! CHECK: %[[ELEM_SIZE:.*]] = arith.constant 16 : i32 ! CHECK: %[[SIZE:.*]] = arith.muli %[[COUNT]], %[[ELEM_SIZE]] : i32 @@ -578,6 +578,7 @@ end subroutine ! CHECK-LABEL: func.func @_QPtest_tma_bulk_load_i4 ! CHECK: %[[BARRIER:.*]]:2 = hlfir.declare %{{.*}} {data_attr = #cuf.cuda<shared>, uniq_name = "_QFtest_tma_bulk_load_i4Ebarrier1"} : (!fir.ref<i64>) -> (!fir.ref<i64>, !fir.ref<i64>) ! CHECK: %[[ELEM_COUNT:.*]]:2 = hlfir.declare %{{.*}} {data_attr = #cuf.cuda<device>, uniq_name = "_QFtest_tma_bulk_load_i4Eelem_count"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: cuf.shared_memory !fir.array<1024xi32> align 16 {bindc_name = "tmp", uniq_name = "_QFtest_tma_bulk_load_i4Etmp"} -> !fir.ref<!fir.array<1024xi32>> ! CHECK: %[[COUNT:.*]] = fir.load %[[ELEM_COUNT]]#0 : !fir.ref<i32> ! CHECK: %[[ELEM_SIZE:.*]] = arith.constant 4 : i32 ! CHECK: %[[SIZE:.*]] = arith.muli %[[COUNT]], %[[ELEM_SIZE]] : i32 @@ -597,6 +598,7 @@ end subroutine ! CHECK-LABEL: func.func @_QPtest_tma_bulk_load_i8 ! CHECK: %[[BARRIER:.*]]:2 = hlfir.declare %{{.*}} {data_attr = #cuf.cuda<shared>, uniq_name = "_QFtest_tma_bulk_load_i8Ebarrier1"} : (!fir.ref<i64>) -> (!fir.ref<i64>, !fir.ref<i64>) ! CHECK: %[[ELEM_COUNT:.*]]:2 = hlfir.declare %{{.*}} {data_attr = #cuf.cuda<device>, uniq_name = "_QFtest_tma_bulk_load_i8Eelem_count"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: cuf.shared_memory !fir.array<1024xi64> align 16 {bindc_name = "tmp", uniq_name = "_QFtest_tma_bulk_load_i8Etmp"} -> !fir.ref<!fir.array<1024xi64>> ! CHECK: %[[COUNT:.*]] = fir.load %[[ELEM_COUNT]]#0 : !fir.ref<i32> ! CHECK: %[[ELEM_SIZE:.*]] = arith.constant 8 : i32 ! CHECK: %[[SIZE:.*]] = arith.muli %[[COUNT]], %[[ELEM_SIZE]] : i32 @@ -616,6 +618,7 @@ end subroutine ! CHECK-LABEL: func.func @_QPtest_tma_bulk_load_r2 ! CHECK: %[[BARRIER:.*]]:2 = hlfir.declare %{{.*}} {data_attr = #cuf.cuda<shared>, uniq_name = "_QFtest_tma_bulk_load_r2Ebarrier1"} : (!fir.ref<i64>) -> (!fir.ref<i64>, !fir.ref<i64>) ! CHECK: %[[ELEM_COUNT:.*]]:2 = hlfir.declare %{{.*}} {data_attr = #cuf.cuda<device>, uniq_name = "_QFtest_tma_bulk_load_r2Eelem_count"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: cuf.shared_memory !fir.array<1024xf16> align 16 {bindc_name = "tmp", uniq_name = "_QFtest_tma_bulk_load_r2Etmp"} -> !fir.ref<!fir.array<1024xf16>> ! CHECK: %[[COUNT:.*]] = fir.load %[[ELEM_COUNT]]#0 : !fir.ref<i32> ! CHECK: %[[ELEM_SIZE:.*]] = arith.constant 2 : i32 ! CHECK: %[[SIZE:.*]] = arith.muli %[[COUNT]], %[[ELEM_SIZE]] : i32 @@ -635,6 +638,7 @@ end subroutine ! CHECK-LABEL: func.func @_QPtest_tma_bulk_load_r4 ! CHECK: %[[BARRIER:.*]]:2 = hlfir.declare %{{.*}} {data_attr = #cuf.cuda<shared>, uniq_name = "_QFtest_tma_bulk_load_r4Ebarrier1"} : (!fir.ref<i64>) -> (!fir.ref<i64>, !fir.ref<i64>) ! CHECK: %[[ELEM_COUNT:.*]]:2 = hlfir.declare %{{.*}} {data_attr = #cuf.cuda<device>, uniq_name = "_QFtest_tma_bulk_load_r4Eelem_count"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: cuf.shared_memory !fir.array<1024xf32> align 16 {bindc_name = "tmp", uniq_name = "_QFtest_tma_bulk_load_r4Etmp"} -> !fir.ref<!fir.array<1024xf32>> ! CHECK: %[[COUNT:.*]] = fir.load %[[ELEM_COUNT]]#0 : !fir.ref<i32> ! CHECK: %[[ELEM_SIZE:.*]] = arith.constant 4 : i32 ! CHECK: %[[SIZE:.*]] = arith.muli %[[COUNT]], %[[ELEM_SIZE]] : i32 @@ -654,6 +658,7 @@ end subroutine ! CHECK-LABEL: func.func @_QPtest_tma_bulk_load_r8 ! CHECK: %[[BARRIER:.*]]:2 = hlfir.declare %{{.*}} {data_attr = #cuf.cuda<shared>, uniq_name = "_QFtest_tma_bulk_load_r8Ebarrier1"} : (!fir.ref<i64>) -> (!fir.ref<i64>, !fir.ref<i64>) ! CHECK: %[[ELEM_COUNT:.*]]:2 = hlfir.declare %{{.*}} {data_attr = #cuf.cuda<device>, uniq_name = "_QFtest_tma_bulk_load_r8Eelem_count"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: cuf.shared_memory !fir.array<1024xf64> align 16 {bindc_name = "tmp", uniq_name = "_QFtest_tma_bulk_load_r8Etmp"} -> !fir.ref<!fir.array<1024xf64>> ! CHECK: %[[COUNT:.*]] = fir.load %[[ELEM_COUNT]]#0 : !fir.ref<i32> ! CHECK: %[[ELEM_SIZE:.*]] = arith.constant 8 : i32 ! CHECK: %[[SIZE:.*]] = arith.muli %[[COUNT]], %[[ELEM_SIZE]] : i32 @@ -670,8 +675,9 @@ attributes(global) subroutine test_tma_bulk_store_c4(c, n) end subroutine ! CHECK-LABEL: func.func @_QPtest_tma_bulk_store_c4 +! CHECK: cuf.shared_memory !fir.array<1024xcomplex<f32>> align 16 {bindc_name = "tmpa", uniq_name = "_QFtest_tma_bulk_store_c4Etmpa"} -> !fir.ref<!fir.array<1024xcomplex<f32>>> ! CHECK: nvvm.cp.async.bulk.global.shared.cta %{{.*}}, %{{.*}}, %{{.*}} : <1>, <3> -! CHECK: nvvm.inline_ptx "cp.async.bulk.commit_group" +! CHECK: nvvm.inline_ptx "cp.async.bulk.commit_group;" ! CHECK: nvvm.cp.async.bulk.wait_group 0 attributes(global) subroutine test_tma_bulk_store_c8(c, n) @@ -683,8 +689,9 @@ attributes(global) subroutine test_tma_bulk_store_c8(c, n) end subroutine ! CHECK-LABEL: func.func @_QPtest_tma_bulk_store_c8 +! CHECK: cuf.shared_memory !fir.array<1024xcomplex<f64>> align 16 {bindc_name = "tmpa", uniq_name = "_QFtest_tma_bulk_store_c8Etmpa"} -> !fir.ref<!fir.array<1024xcomplex<f64>>> ! CHECK: nvvm.cp.async.bulk.global.shared.cta %{{.*}}, %{{.*}}, %{{.*}} : <1>, <3> -! CHECK: nvvm.inline_ptx "cp.async.bulk.commit_group" +! CHECK: nvvm.inline_ptx "cp.async.bulk.commit_group;" ! CHECK: nvvm.cp.async.bulk.wait_group 0 attributes(global) subroutine test_tma_bulk_store_i4(c, n) @@ -696,8 +703,9 @@ attributes(global) subroutine test_tma_bulk_store_i4(c, n) end subroutine ! CHECK-LABEL: func.func @_QPtest_tma_bulk_store_i4 +! CHECK: cuf.shared_memory !fir.array<1024xi32> align 16 {bindc_name = "tmpa", uniq_name = "_QFtest_tma_bulk_store_i4Etmpa"} -> !fir.ref<!fir.array<1024xi32>> ! CHECK: nvvm.cp.async.bulk.global.shared.cta %{{.*}}, %{{.*}}, %{{.*}} : <1>, <3> -! CHECK: nvvm.inline_ptx "cp.async.bulk.commit_group" +! CHECK: nvvm.inline_ptx "cp.async.bulk.commit_group;" ! CHECK: nvvm.cp.async.bulk.wait_group 0 attributes(global) subroutine test_tma_bulk_store_i8(c, n) @@ -709,8 +717,9 @@ attributes(global) subroutine test_tma_bulk_store_i8(c, n) end subroutine ! CHECK-LABEL: func.func @_QPtest_tma_bulk_store_i8 +! CHECK: cuf.shared_memory !fir.array<1024xi64> align 16 {bindc_name = "tmpa", uniq_name = "_QFtest_tma_bulk_store_i8Etmpa"} -> !fir.ref<!fir.array<1024xi64>> ! CHECK: nvvm.cp.async.bulk.global.shared.cta %{{.*}}, %{{.*}}, %{{.*}} : <1>, <3> -! CHECK: nvvm.inline_ptx "cp.async.bulk.commit_group" +! CHECK: nvvm.inline_ptx "cp.async.bulk.commit_group;" ! CHECK: nvvm.cp.async.bulk.wait_group 0 @@ -723,8 +732,9 @@ attributes(global) subroutine test_tma_bulk_store_r2(c, n) end subroutine ! CHECK-LABEL: func.func @_QPtest_tma_bulk_store_r2 +! CHECK: cuf.shared_memory !fir.array<1024xf16> align 16 {bindc_name = "tmpa", uniq_name = "_QFtest_tma_bulk_store_r2Etmpa"} -> !fir.ref<!fir.array<1024xf16>> ! CHECK: nvvm.cp.async.bulk.global.shared.cta %{{.*}}, %{{.*}}, %{{.*}} : <1>, <3> -! CHECK: nvvm.inline_ptx "cp.async.bulk.commit_group" +! CHECK: nvvm.inline_ptx "cp.async.bulk.commit_group;" ! CHECK: nvvm.cp.async.bulk.wait_group 0 attributes(global) subroutine test_tma_bulk_store_r4(c, n) @@ -736,8 +746,9 @@ attributes(global) subroutine test_tma_bulk_store_r4(c, n) end subroutine ! CHECK-LABEL: func.func @_QPtest_tma_bulk_store_r4 +! CHECK: cuf.shared_memory !fir.array<1024xf32> align 16 {bindc_name = "tmpa", uniq_name = "_QFtest_tma_bulk_store_r4Etmpa"} -> !fir.ref<!fir.array<1024xf32>> ! CHECK: nvvm.cp.async.bulk.global.shared.cta %{{.*}}, %{{.*}}, %{{.*}} : <1>, <3> -! CHECK: nvvm.inline_ptx "cp.async.bulk.commit_group" +! CHECK: nvvm.inline_ptx "cp.async.bulk.commit_group;" ! CHECK: nvvm.cp.async.bulk.wait_group 0 attributes(global) subroutine test_tma_bulk_store_r8(c, n) @@ -749,6 +760,7 @@ attributes(global) subroutine test_tma_bulk_store_r8(c, n) end subroutine ! CHECK-LABEL: func.func @_QPtest_tma_bulk_store_r8 +! CHECK: cuf.shared_memory !fir.array<1024xf64> align 16 {bindc_name = "tmpa", uniq_name = "_QFtest_tma_bulk_store_r8Etmpa"} -> !fir.ref<!fir.array<1024xf64>> ! CHECK: nvvm.cp.async.bulk.global.shared.cta %{{.*}}, %{{.*}}, %{{.*}} : <1>, <3> -! CHECK: nvvm.inline_ptx "cp.async.bulk.commit_group" +! CHECK: nvvm.inline_ptx "cp.async.bulk.commit_group;" ! CHECK: nvvm.cp.async.bulk.wait_group 0 diff --git a/flang/test/Lower/CUDA/cuda-synchronization.cuf b/flang/test/Lower/CUDA/cuda-synchronization.cuf new file mode 100644 index 0000000..6e2e234 --- /dev/null +++ b/flang/test/Lower/CUDA/cuda-synchronization.cuf @@ -0,0 +1,14 @@ +! RUN: bbc -emit-hlfir -fcuda %s -o - | FileCheck %s + +! Test CUDA Fortran instrinsics lowerings for synchronization. + +attributes(global) subroutine sync() + call threadfence() + call threadfence_block() + call threadfence_system() +end subroutine + +! CHECK-LABEL: func.func @_QPsync() attributes {cuf.proc_attr = #cuf.cuda_proc<global>} +! CHECK: nvvm.memory.barrier <gpu> +! CHECK: nvvm.memory.barrier <cta> +! CHECK: nvvm.memory.barrier <sys> diff --git a/flang/test/Lower/HLFIR/actual_target_for_dummy_pointer.f90 b/flang/test/Lower/HLFIR/actual_target_for_dummy_pointer.f90 index efe9e6d..2222259 100644 --- a/flang/test/Lower/HLFIR/actual_target_for_dummy_pointer.f90 +++ b/flang/test/Lower/HLFIR/actual_target_for_dummy_pointer.f90 @@ -50,7 +50,7 @@ end subroutine integer_assumed_shape_array ! CHECK-SAME: %[[VAL_0:.*]]: !fir.box<!fir.array<?xi32>> {fir.bindc_name = "i", fir.target}) { ! CHECK: %[[VAL_1:.*]] = fir.alloca !fir.class<!fir.ptr<!fir.array<?xnone>>> ! CHECK: %[[VAL_2:.*]] = fir.alloca !fir.box<!fir.ptr<!fir.array<?xi32>>> -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<target>, uniq_name = "_QFinteger_assumed_shape_arrayEi"} : (!fir.box<!fir.array<?xi32>>, !fir.dscope) -> (!fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<target>, uniq_name = "_QFinteger_assumed_shape_arrayEi"} : (!fir.box<!fir.array<?xi32>>, !fir.dscope) -> (!fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>>) ! CHECK: %[[VAL_4:.*]] = fir.rebox %[[VAL_3]]#1 : (!fir.box<!fir.array<?xi32>>) -> !fir.box<!fir.ptr<!fir.array<?xi32>>> ! CHECK: fir.store %[[VAL_4]] to %[[VAL_2]] : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>> ! CHECK: fir.call @_QPinteger_assumed_shape_array_callee(%[[VAL_2]]) fastmath<contract> : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>) -> () @@ -159,8 +159,8 @@ end subroutine char_assumed_shape_array ! CHECK: %[[VAL_6:.*]] = fir.alloca !fir.box<!fir.ptr<!fir.array<?x!fir.char<1,?>>>> ! CHECK: %[[VAL_7:.*]] = fir.alloca !fir.box<!fir.ptr<!fir.array<?x!fir.char<1,2>>>> ! CHECK: %[[VAL_8:.*]] = arith.constant 2 : index -! CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[VAL_0]] typeparams %[[VAL_8]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<target>, uniq_name = "_QFchar_assumed_shape_arrayEa1"} : (!fir.box<!fir.array<?x!fir.char<1,2>>>, index, !fir.dscope) -> (!fir.box<!fir.array<?x!fir.char<1,2>>>, !fir.box<!fir.array<?x!fir.char<1,2>>>) -! CHECK: %[[VAL_10:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<target>, uniq_name = "_QFchar_assumed_shape_arrayEa2"} : (!fir.box<!fir.array<?x!fir.char<1,?>>>, !fir.dscope) -> (!fir.box<!fir.array<?x!fir.char<1,?>>>, !fir.box<!fir.array<?x!fir.char<1,?>>>) +! CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[VAL_0]] typeparams %[[VAL_8]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<target>, uniq_name = "_QFchar_assumed_shape_arrayEa1"} : (!fir.box<!fir.array<?x!fir.char<1,2>>>, index, !fir.dscope) -> (!fir.box<!fir.array<?x!fir.char<1,2>>>, !fir.box<!fir.array<?x!fir.char<1,2>>>) +! CHECK: %[[VAL_10:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<target>, uniq_name = "_QFchar_assumed_shape_arrayEa2"} : (!fir.box<!fir.array<?x!fir.char<1,?>>>, !fir.dscope) -> (!fir.box<!fir.array<?x!fir.char<1,?>>>, !fir.box<!fir.array<?x!fir.char<1,?>>>) ! CHECK: %[[VAL_11:.*]] = fir.rebox %[[VAL_9]]#1 : (!fir.box<!fir.array<?x!fir.char<1,2>>>) -> !fir.box<!fir.ptr<!fir.array<?x!fir.char<1,2>>>> ! CHECK: fir.store %[[VAL_11]] to %[[VAL_7]] : !fir.ref<!fir.box<!fir.ptr<!fir.array<?x!fir.char<1,2>>>>> ! CHECK: fir.call @_QPchar_assumed_shape_array_explicit_len_callee(%[[VAL_7]]) fastmath<contract> : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?x!fir.char<1,2>>>>>) -> () @@ -220,7 +220,7 @@ end subroutine char_explicit_shape_array ! CHECK: %[[VAL_13:.*]] = fir.convert %[[VAL_12]]#0 : (!fir.ref<!fir.char<1,?>>) -> !fir.ref<!fir.array<100x!fir.char<1,?>>> ! CHECK: %[[VAL_14:.*]] = arith.constant 100 : index ! CHECK: %[[VAL_15:.*]] = fir.shape %[[VAL_14]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_16:.*]]:2 = hlfir.declare %[[VAL_13]](%[[VAL_15]]) typeparams %[[VAL_12]]#1 dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<target>, uniq_name = "_QFchar_explicit_shape_arrayEa2"} : (!fir.ref<!fir.array<100x!fir.char<1,?>>>, !fir.shape<1>, index, !fir.dscope) -> (!fir.box<!fir.array<100x!fir.char<1,?>>>, !fir.ref<!fir.array<100x!fir.char<1,?>>>) +! CHECK: %[[VAL_16:.*]]:2 = hlfir.declare %[[VAL_13]](%[[VAL_15]]) typeparams %[[VAL_12]]#1 dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<target>, uniq_name = "_QFchar_explicit_shape_arrayEa2"} : (!fir.ref<!fir.array<100x!fir.char<1,?>>>, !fir.shape<1>, index, !fir.dscope) -> (!fir.box<!fir.array<100x!fir.char<1,?>>>, !fir.ref<!fir.array<100x!fir.char<1,?>>>) ! CHECK: %[[VAL_17:.*]] = fir.shape %[[VAL_8]] : (index) -> !fir.shape<1> ! CHECK: %[[VAL_18:.*]] = fir.convert %[[VAL_11]]#0 : (!fir.ref<!fir.array<100x!fir.char<1,2>>>) -> !fir.ref<!fir.array<?x!fir.char<1,2>>> ! CHECK: %[[VAL_19:.*]] = fir.embox %[[VAL_18]](%[[VAL_17]]) : (!fir.ref<!fir.array<?x!fir.char<1,2>>>, !fir.shape<1>) -> !fir.box<!fir.ptr<!fir.array<?x!fir.char<1,2>>>> @@ -317,7 +317,7 @@ end subroutine type_assumed_shape_array ! CHECK: %[[VAL_1:.*]] = fir.alloca !fir.class<!fir.ptr<!fir.array<?xnone>>> ! CHECK: %[[VAL_2:.*]] = fir.alloca !fir.class<!fir.ptr<!fir.array<?x!fir.type<_QMtarget_to_pointer_typesTt1>>>> ! CHECK: %[[VAL_3:.*]] = fir.alloca !fir.box<!fir.ptr<!fir.array<?x!fir.type<_QMtarget_to_pointer_typesTt1>>>> -! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<target>, uniq_name = "_QFtype_assumed_shape_arrayEt"} : (!fir.box<!fir.array<?x!fir.type<_QMtarget_to_pointer_typesTt1>>>, !fir.dscope) -> (!fir.box<!fir.array<?x!fir.type<_QMtarget_to_pointer_typesTt1>>>, !fir.box<!fir.array<?x!fir.type<_QMtarget_to_pointer_typesTt1>>>) +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<target>, uniq_name = "_QFtype_assumed_shape_arrayEt"} : (!fir.box<!fir.array<?x!fir.type<_QMtarget_to_pointer_typesTt1>>>, !fir.dscope) -> (!fir.box<!fir.array<?x!fir.type<_QMtarget_to_pointer_typesTt1>>>, !fir.box<!fir.array<?x!fir.type<_QMtarget_to_pointer_typesTt1>>>) ! CHECK: %[[VAL_5:.*]] = fir.rebox %[[VAL_4]]#1 : (!fir.box<!fir.array<?x!fir.type<_QMtarget_to_pointer_typesTt1>>>) -> !fir.box<!fir.ptr<!fir.array<?x!fir.type<_QMtarget_to_pointer_typesTt1>>>> ! CHECK: fir.store %[[VAL_5]] to %[[VAL_3]] : !fir.ref<!fir.box<!fir.ptr<!fir.array<?x!fir.type<_QMtarget_to_pointer_typesTt1>>>>> ! CHECK: fir.call @_QPtype_assumed_shape_array_callee(%[[VAL_3]]) fastmath<contract> : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?x!fir.type<_QMtarget_to_pointer_typesTt1>>>>>) -> () @@ -400,7 +400,7 @@ end subroutine class_scalar ! CHECK: %[[VAL_1:.*]] = fir.alloca !fir.class<!fir.ptr<none>> ! CHECK: %[[VAL_2:.*]] = fir.alloca !fir.class<!fir.ptr<!fir.type<_QMtarget_to_pointer_typesTt1>>> ! CHECK: %[[VAL_3:.*]] = fir.alloca !fir.box<!fir.ptr<!fir.type<_QMtarget_to_pointer_typesTt1>>> -! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<target>, uniq_name = "_QFclass_scalarEt"} : (!fir.class<!fir.type<_QMtarget_to_pointer_typesTt1>>, !fir.dscope) -> (!fir.class<!fir.type<_QMtarget_to_pointer_typesTt1>>, !fir.class<!fir.type<_QMtarget_to_pointer_typesTt1>>) +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<target>, uniq_name = "_QFclass_scalarEt"} : (!fir.class<!fir.type<_QMtarget_to_pointer_typesTt1>>, !fir.dscope) -> (!fir.class<!fir.type<_QMtarget_to_pointer_typesTt1>>, !fir.class<!fir.type<_QMtarget_to_pointer_typesTt1>>) ! CHECK: %[[VAL_5:.*]] = fir.rebox %[[VAL_4]]#1 : (!fir.class<!fir.type<_QMtarget_to_pointer_typesTt1>>) -> !fir.box<!fir.ptr<!fir.type<_QMtarget_to_pointer_typesTt1>>> ! CHECK: fir.store %[[VAL_5]] to %[[VAL_3]] : !fir.ref<!fir.box<!fir.ptr<!fir.type<_QMtarget_to_pointer_typesTt1>>>> ! CHECK: fir.call @_QPclass_scalar_callee(%[[VAL_3]]) fastmath<contract> : (!fir.ref<!fir.box<!fir.ptr<!fir.type<_QMtarget_to_pointer_typesTt1>>>>) -> () @@ -439,7 +439,7 @@ end subroutine class_assumed_shape_array ! CHECK: %[[VAL_1:.*]] = fir.alloca !fir.class<!fir.ptr<!fir.array<?xnone>>> ! CHECK: %[[VAL_2:.*]] = fir.alloca !fir.class<!fir.ptr<!fir.array<?x!fir.type<_QMtarget_to_pointer_typesTt1>>>> ! CHECK: %[[VAL_3:.*]] = fir.alloca !fir.box<!fir.ptr<!fir.array<?x!fir.type<_QMtarget_to_pointer_typesTt1>>>> -! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<target>, uniq_name = "_QFclass_assumed_shape_arrayEt"} : (!fir.class<!fir.array<?x!fir.type<_QMtarget_to_pointer_typesTt1>>>, !fir.dscope) -> (!fir.class<!fir.array<?x!fir.type<_QMtarget_to_pointer_typesTt1>>>, !fir.class<!fir.array<?x!fir.type<_QMtarget_to_pointer_typesTt1>>>) +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<target>, uniq_name = "_QFclass_assumed_shape_arrayEt"} : (!fir.class<!fir.array<?x!fir.type<_QMtarget_to_pointer_typesTt1>>>, !fir.dscope) -> (!fir.class<!fir.array<?x!fir.type<_QMtarget_to_pointer_typesTt1>>>, !fir.class<!fir.array<?x!fir.type<_QMtarget_to_pointer_typesTt1>>>) ! CHECK: %[[VAL_5:.*]] = fir.rebox %[[VAL_4]]#1 : (!fir.class<!fir.array<?x!fir.type<_QMtarget_to_pointer_typesTt1>>>) -> !fir.box<!fir.ptr<!fir.array<?x!fir.type<_QMtarget_to_pointer_typesTt1>>>> ! CHECK: fir.store %[[VAL_5]] to %[[VAL_3]] : !fir.ref<!fir.box<!fir.ptr<!fir.array<?x!fir.type<_QMtarget_to_pointer_typesTt1>>>>> ! CHECK: fir.call @_QPclass_assumed_shape_array_callee(%[[VAL_3]]) fastmath<contract> : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?x!fir.type<_QMtarget_to_pointer_typesTt1>>>>>) -> () @@ -478,7 +478,7 @@ end subroutine class_explicit_shape_array ! CHECK: %[[VAL_1:.*]] = fir.alloca !fir.class<!fir.ptr<!fir.array<?xnone>>> ! CHECK: %[[VAL_2:.*]] = fir.alloca !fir.class<!fir.ptr<!fir.array<?x!fir.type<_QMtarget_to_pointer_typesTt1>>>> ! CHECK: %[[VAL_3:.*]] = fir.alloca !fir.box<!fir.ptr<!fir.array<?x!fir.type<_QMtarget_to_pointer_typesTt1>>>> -! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<target>, uniq_name = "_QFclass_explicit_shape_arrayEt"} : (!fir.class<!fir.array<100x!fir.type<_QMtarget_to_pointer_typesTt1>>>, !fir.dscope) -> (!fir.class<!fir.array<100x!fir.type<_QMtarget_to_pointer_typesTt1>>>, !fir.class<!fir.array<100x!fir.type<_QMtarget_to_pointer_typesTt1>>>) +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<target>, uniq_name = "_QFclass_explicit_shape_arrayEt"} : (!fir.class<!fir.array<100x!fir.type<_QMtarget_to_pointer_typesTt1>>>, !fir.dscope) -> (!fir.class<!fir.array<100x!fir.type<_QMtarget_to_pointer_typesTt1>>>, !fir.class<!fir.array<100x!fir.type<_QMtarget_to_pointer_typesTt1>>>) ! CHECK: %[[VAL_5:.*]] = fir.rebox %[[VAL_4]]#1 : (!fir.class<!fir.array<100x!fir.type<_QMtarget_to_pointer_typesTt1>>>) -> !fir.box<!fir.ptr<!fir.array<?x!fir.type<_QMtarget_to_pointer_typesTt1>>>> ! CHECK: fir.store %[[VAL_5]] to %[[VAL_3]] : !fir.ref<!fir.box<!fir.ptr<!fir.array<?x!fir.type<_QMtarget_to_pointer_typesTt1>>>>> ! CHECK: fir.call @_QPclass_explicit_shape_array_callee(%[[VAL_3]]) fastmath<contract> : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?x!fir.type<_QMtarget_to_pointer_typesTt1>>>>>) -> () @@ -505,7 +505,7 @@ end subroutine uclass_scalar ! CHECK-LABEL: func.func @_QPuclass_scalar( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.class<none> {fir.bindc_name = "t", fir.target}) { ! CHECK: %[[VAL_1:.*]] = fir.alloca !fir.class<!fir.ptr<none>> -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<target>, uniq_name = "_QFuclass_scalarEt"} : (!fir.class<none>, !fir.dscope) -> (!fir.class<none>, !fir.class<none>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<target>, uniq_name = "_QFuclass_scalarEt"} : (!fir.class<none>, !fir.dscope) -> (!fir.class<none>, !fir.class<none>) ! CHECK: %[[VAL_3:.*]] = fir.rebox %[[VAL_2]]#1 : (!fir.class<none>) -> !fir.class<!fir.ptr<none>> ! CHECK: fir.store %[[VAL_3]] to %[[VAL_1]] : !fir.ref<!fir.class<!fir.ptr<none>>> ! CHECK: fir.call @_QPuclass_scalar_uclass_callee(%[[VAL_1]]) fastmath<contract> : (!fir.ref<!fir.class<!fir.ptr<none>>>) -> () @@ -526,7 +526,7 @@ end subroutine uclass_assumed_shape_array ! CHECK-LABEL: func.func @_QPuclass_assumed_shape_array( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.class<!fir.array<?xnone>> {fir.bindc_name = "t", fir.target}) { ! CHECK: %[[VAL_1:.*]] = fir.alloca !fir.class<!fir.ptr<!fir.array<?xnone>>> -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<target>, uniq_name = "_QFuclass_assumed_shape_arrayEt"} : (!fir.class<!fir.array<?xnone>>, !fir.dscope) -> (!fir.class<!fir.array<?xnone>>, !fir.class<!fir.array<?xnone>>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<target>, uniq_name = "_QFuclass_assumed_shape_arrayEt"} : (!fir.class<!fir.array<?xnone>>, !fir.dscope) -> (!fir.class<!fir.array<?xnone>>, !fir.class<!fir.array<?xnone>>) ! CHECK: %[[VAL_3:.*]] = fir.rebox %[[VAL_2]]#1 : (!fir.class<!fir.array<?xnone>>) -> !fir.class<!fir.ptr<!fir.array<?xnone>>> ! CHECK: fir.store %[[VAL_3]] to %[[VAL_1]] : !fir.ref<!fir.class<!fir.ptr<!fir.array<?xnone>>>> ! CHECK: fir.call @_QPuclass_assumed_shape_array_uclass_callee(%[[VAL_1]]) fastmath<contract> : (!fir.ref<!fir.class<!fir.ptr<!fir.array<?xnone>>>>) -> () @@ -547,7 +547,7 @@ end subroutine uclass_explicit_shape_array ! CHECK-LABEL: func.func @_QPuclass_explicit_shape_array( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.class<!fir.array<100xnone>> {fir.bindc_name = "t", fir.target}) { ! CHECK: %[[VAL_1:.*]] = fir.alloca !fir.class<!fir.ptr<!fir.array<?xnone>>> -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<target>, uniq_name = "_QFuclass_explicit_shape_arrayEt"} : (!fir.class<!fir.array<100xnone>>, !fir.dscope) -> (!fir.class<!fir.array<100xnone>>, !fir.class<!fir.array<100xnone>>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<target>, uniq_name = "_QFuclass_explicit_shape_arrayEt"} : (!fir.class<!fir.array<100xnone>>, !fir.dscope) -> (!fir.class<!fir.array<100xnone>>, !fir.class<!fir.array<100xnone>>) ! CHECK: %[[VAL_3:.*]] = fir.rebox %[[VAL_2]]#1 : (!fir.class<!fir.array<100xnone>>) -> !fir.class<!fir.ptr<!fir.array<?xnone>>> ! CHECK: fir.store %[[VAL_3]] to %[[VAL_1]] : !fir.ref<!fir.class<!fir.ptr<!fir.array<?xnone>>>> ! CHECK: fir.call @_QPuclass_explicit_shape_array_uclass_callee(%[[VAL_1]]) fastmath<contract> : (!fir.ref<!fir.class<!fir.ptr<!fir.array<?xnone>>>>) -> () diff --git a/flang/test/Lower/HLFIR/allocatable-and-pointer-status-change.f90 b/flang/test/Lower/HLFIR/allocatable-and-pointer-status-change.f90 index 08492e9..0c57b20 100644 --- a/flang/test/Lower/HLFIR/allocatable-and-pointer-status-change.f90 +++ b/flang/test/Lower/HLFIR/allocatable-and-pointer-status-change.f90 @@ -5,7 +5,7 @@ subroutine allocation(x) character(*), allocatable :: x(:) ! CHECK-LABEL: func.func @_QPallocation( -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0:[a-z0-9]*]] typeparams %[[VAL_2:[a-z0-9]*]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, {{.*}}Ex +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0:[a-z0-9]*]] typeparams %[[VAL_2:[a-z0-9]*]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, {{.*}}Ex deallocate(x) ! CHECK: %[[VAL_4:.*]] = fir.load %[[VAL_3]]#0 : !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.char<1,?>>>>> ! CHECK: %[[VAL_5:.*]] = fir.box_addr %[[VAL_4]] : (!fir.box<!fir.heap<!fir.array<?x!fir.char<1,?>>>>) -> !fir.heap<!fir.array<?x!fir.char<1,?>>> @@ -30,11 +30,11 @@ subroutine pointer_assignment(p, ziel) real, pointer :: p(:) real, target :: ziel(42:) ! CHECK-LABEL: func.func @_QPpointer_assignment( -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0:[a-z0-9]*]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, {{.*}}Ep -! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_1:[a-z0-9]*]](%[[VAL_5:[a-z0-9]*]]) dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<target>, {{.*}}Eziel +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0:[a-z0-9]*]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, {{.*}}Ep +! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_1:[a-z0-9]*]](%[[VAL_5:[a-z0-9]*]]) dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<target>, {{.*}}Eziel p => ziel ! CHECK: %[[VAL_7:.*]] = fir.shift %[[VAL_4:.*]] : (index) -> !fir.shift<1> -! CHECK: %[[VAL_8:.*]] = fir.rebox %[[VAL_6]]#1(%[[VAL_7]]) : (!fir.box<!fir.array<?xf32>>, !fir.shift<1>) -> !fir.box<!fir.ptr<!fir.array<?xf32>>> +! CHECK: %[[VAL_8:.*]] = fir.rebox %[[VAL_6]]#0(%[[VAL_7]]) : (!fir.box<!fir.array<?xf32>>, !fir.shift<1>) -> !fir.box<!fir.ptr<!fir.array<?xf32>>> ! CHECK: fir.store %[[VAL_8]] to %[[VAL_2]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>> p => ziel(42:77:3) ! CHECK: %[[VAL_14:.*]] = hlfir.designate %{{.*}}#0 (%{{.*}}:%{{.*}}:%{{.*}}) shape %{{.*}} : (!fir.box<!fir.array<?xf32>>, index, index, index, !fir.shape<1>) -> !fir.box<!fir.array<12xf32>> @@ -46,30 +46,32 @@ subroutine pointer_remapping(p, ziel) real, pointer :: p(:, :) real, target :: ziel(10, 20, 30) ! CHECK-LABEL: func.func @_QPpointer_remapping( -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0:[a-z0-9]*]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, {{.*}}Ep -! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_1:[a-z0-9]*]](%[[VAL_6:[a-z0-9]*]]) dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<target>, {{.*}}Eziel +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0:[a-z0-9]*]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, {{.*}}Ep +! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_1:[a-z0-9]*]](%[[VAL_6:[a-z0-9]*]]) dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<target>, {{.*}}Eziel p(2:7, 3:102) => ziel -! CHECK: %[[VAL_8:.*]] = arith.constant 2 : i64 -! CHECK: %[[VAL_9:.*]] = arith.constant 7 : i64 -! CHECK: %[[VAL_10:.*]] = arith.constant 3 : i64 -! CHECK: %[[VAL_11:.*]] = arith.constant 102 : i64 -! CHECK: %[[VAL_12:.*]] = arith.constant 1 : index -! CHECK: %[[VAL_13:.*]] = fir.convert %[[VAL_8]] : (i64) -> index -! CHECK: %[[VAL_14:.*]] = fir.convert %[[VAL_9]] : (i64) -> index -! CHECK: %[[VAL_15:.*]] = arith.subi %[[VAL_14]], %[[VAL_13]] : index -! CHECK: %[[VAL_16:.*]] = arith.addi %[[VAL_15]], %[[VAL_12]] : index -! CHECK: %[[cmp0:.*]] = arith.cmpi sgt, %[[VAL_16]], %c0{{.*}} : index -! CHECK: %[[ext0:.*]] = arith.select %[[cmp0]], %[[VAL_16]], %c0{{.*}} : index -! CHECK: %[[VAL_17:.*]] = fir.convert %[[VAL_10]] : (i64) -> index -! CHECK: %[[VAL_18:.*]] = fir.convert %[[VAL_11]] : (i64) -> index -! CHECK: %[[VAL_19:.*]] = arith.subi %[[VAL_18]], %[[VAL_17]] : index -! CHECK: %[[VAL_20:.*]] = arith.addi %[[VAL_19]], %[[VAL_12]] : index -! CHECK: %[[cmp1:.*]] = arith.cmpi sgt, %[[VAL_20]], %c0{{.*}} : index -! CHECK: %[[ext1:.*]] = arith.select %[[cmp1]], %[[VAL_20]], %c0{{.*}} : index -! CHECK: %[[VAL_21:.*]] = fir.convert %[[VAL_7]]#0 : (!fir.ref<!fir.array<10x20x30xf32>>) -> !fir.ref<!fir.array<?x?xf32>> -! CHECK: %[[VAL_22:.*]] = fir.shape_shift %[[VAL_8]], %[[ext0]], %[[VAL_10]], %[[ext1]] : (i64, index, i64, index) -> !fir.shapeshift<2> -! CHECK: %[[VAL_23:.*]] = fir.embox %[[VAL_21]](%[[VAL_22]]) : (!fir.ref<!fir.array<?x?xf32>>, !fir.shapeshift<2>) -> !fir.box<!fir.ptr<!fir.array<?x?xf32>>> -! CHECK: fir.store %[[VAL_23]] to %[[VAL_2]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?x?xf32>>>> +! CHECK: %[[CONVERT_0:.*]] = fir.convert %[[VAL_7]]#0 : (!fir.ref<!fir.array<10x20x30xf32>>) -> !fir.ref<!fir.array<?x?x?xf32>> +! CHECK: %[[EMBOX_0:.*]] = fir.embox %[[CONVERT_0]](%[[VAL_6]]) : (!fir.ref<!fir.array<?x?x?xf32>>, !fir.shape<3>) -> !fir.box<!fir.ptr<!fir.array<?x?x?xf32>>> +! CHECK: %[[CONSTANT_3:.*]] = arith.constant 0 : index +! CHECK: %[[CONSTANT_4:.*]] = arith.constant 1 : index +! CHECK: %[[CONSTANT_5:.*]] = arith.constant 2 : i64 +! CHECK: %[[CONVERT_1:.*]] = fir.convert %[[CONSTANT_5]] : (i64) -> index +! CHECK: %[[CONSTANT_6:.*]] = arith.constant 7 : i64 +! CHECK: %[[CONVERT_2:.*]] = fir.convert %[[CONSTANT_6]] : (i64) -> index +! CHECK: %[[SUBI_0:.*]] = arith.subi %[[CONVERT_2]], %[[CONVERT_1]] : index +! CHECK: %[[ADDI_0:.*]] = arith.addi %[[SUBI_0]], %[[CONSTANT_4]] : index +! CHECK: %[[CMPI_0:.*]] = arith.cmpi sgt, %[[ADDI_0]], %[[CONSTANT_3]] : index +! CHECK: %[[SELECT_0:.*]] = arith.select %[[CMPI_0]], %[[ADDI_0]], %[[CONSTANT_3]] : index +! CHECK: %[[CONSTANT_7:.*]] = arith.constant 3 : i64 +! CHECK: %[[CONVERT_3:.*]] = fir.convert %[[CONSTANT_7]] : (i64) -> index +! CHECK: %[[CONSTANT_8:.*]] = arith.constant 102 : i64 +! CHECK: %[[CONVERT_4:.*]] = fir.convert %[[CONSTANT_8]] : (i64) -> index +! CHECK: %[[SUBI_1:.*]] = arith.subi %[[CONVERT_4]], %[[CONVERT_3]] : index +! CHECK: %[[ADDI_1:.*]] = arith.addi %[[SUBI_1]], %[[CONSTANT_4]] : index +! CHECK: %[[CMPI_1:.*]] = arith.cmpi sgt, %[[ADDI_1]], %[[CONSTANT_3]] : index +! CHECK: %[[SELECT_1:.*]] = arith.select %[[CMPI_1]], %[[ADDI_1]], %[[CONSTANT_3]] : index +! CHECK: %[[SHAPE_SHIFT_0:.*]] = fir.shape_shift %[[CONVERT_1]], %[[SELECT_0]], %[[CONVERT_3]], %[[SELECT_1]] : (index, index, index, index) -> !fir.shapeshift<2> +! CHECK: %[[REBOX_0:.*]] = fir.rebox %[[EMBOX_0]](%[[SHAPE_SHIFT_0]]) : (!fir.box<!fir.ptr<!fir.array<?x?x?xf32>>>, !fir.shapeshift<2>) -> !fir.box<!fir.ptr<!fir.array<?x?xf32>>> +! CHECK: fir.store %[[REBOX_0]] to %[[VAL_2]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?x?xf32>>>> end subroutine subroutine alloc_comp(x) @@ -105,11 +107,11 @@ subroutine ptr_comp_assign(x, ziel) x(9_8)%p => ziel ! CHECK: %[[VAL_5:.*]] = arith.constant 100 : index ! CHECK: %[[VAL_6:.*]] = fir.shape %[[VAL_5]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_1:[a-z0-9]*]](%[[VAL_6:[a-z0-9]*]]) dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<target>, {{.*}}Eziel +! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_1:[a-z0-9]*]](%[[VAL_6:[a-z0-9]*]]) dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<target>, {{.*}}Eziel ! CHECK: %[[VAL_8:.*]] = arith.constant 9 : index ! CHECK: %[[VAL_9:.*]] = hlfir.designate %[[VAL_4]]#0 (%[[VAL_8]]) : (!fir.ref<!fir.array<10x!fir.type<_QFptr_comp_assignTt{p:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>>>, index) -> !fir.ref<!fir.type<_QFptr_comp_assignTt{p:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>> ! CHECK: %[[VAL_10:.*]] = hlfir.designate %[[VAL_9]]{"p"} {fortran_attrs = #fir.var_attrs<pointer>} : (!fir.ref<!fir.type<_QFptr_comp_assignTt{p:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>>) -> !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>> -! CHECK: %[[VAL_11:.*]] = fir.shape %[[VAL_5]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_12:.*]] = fir.embox %[[VAL_7]]#0(%[[VAL_11]]) : (!fir.ref<!fir.array<100xf32>>, !fir.shape<1>) -> !fir.box<!fir.ptr<!fir.array<?xf32>>> +! CHECK: %[[CAST:.*]] = fir.convert %[[VAL_7]]#0 : (!fir.ref<!fir.array<100xf32>>) -> !fir.ref<!fir.array<?xf32>> +! CHECK: %[[VAL_12:.*]] = fir.embox %[[CAST]](%[[VAL_6]]) : (!fir.ref<!fir.array<?xf32>>, !fir.shape<1>) -> !fir.box<!fir.ptr<!fir.array<?xf32>>> ! CHECK: fir.store %[[VAL_12]] to %[[VAL_10]] : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>> end subroutine diff --git a/flang/test/Lower/HLFIR/allocatables-and-pointers.f90 b/flang/test/Lower/HLFIR/allocatables-and-pointers.f90 index d6cbea8..ed20d2e 100644 --- a/flang/test/Lower/HLFIR/allocatables-and-pointers.f90 +++ b/flang/test/Lower/HLFIR/allocatables-and-pointers.f90 @@ -15,7 +15,7 @@ subroutine passing_allocatable(x) call takes_array(x) end subroutine ! CHECK-LABEL: func.func @_QPpassing_allocatable( -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0:[a-z0-9]*]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = {{.*}}Ex"} +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0:[a-z0-9]*]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = {{.*}}Ex"} ! CHECK: fir.call @_QPtakes_allocatable(%[[VAL_1]]#0) {{.*}} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>) -> () ! CHECK: %[[VAL_2:.*]] = fir.load %[[VAL_1]]#0 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>> ! CHECK: %[[VAL_3:.*]] = fir.box_addr %[[VAL_2]] : (!fir.box<!fir.heap<!fir.array<?xf32>>>) -> !fir.heap<!fir.array<?xf32>> @@ -34,7 +34,7 @@ subroutine passing_pointer(x) end subroutine ! CHECK-LABEL: func.func @_QPpassing_pointer( ! CHECK: %[[VAL_1:.*]] = fir.alloca !fir.box<!fir.ptr<!fir.array<?xf32>>> -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0:[a-z0-9]*]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = {{.*}}Ex"} +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0:[a-z0-9]*]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = {{.*}}Ex"} ! CHECK: fir.call @_QPtakes_pointer(%[[VAL_2]]#0) {{.*}} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>) -> () ! CHECK: %[[VAL_3:.*]] = fir.zero_bits !fir.ptr<!fir.array<?xf32>> ! CHECK: %[[VAL_4:.*]] = arith.constant 0 : index @@ -53,7 +53,7 @@ subroutine passing_contiguous_pointer(x) call takes_array(x) end subroutine ! CHECK-LABEL: func.func @_QPpassing_contiguous_pointer( -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0:[a-z0-9]*]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<contiguous, pointer>, uniq_name = {{.*}}Ex"} +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0:[a-z0-9]*]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<contiguous, pointer>, uniq_name = {{.*}}Ex"} ! CHECK: %[[VAL_2:.*]] = fir.load %[[VAL_1]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>> ! CHECK: %[[VAL_3:.*]] = fir.box_addr %[[VAL_2]] : (!fir.box<!fir.ptr<!fir.array<?xf32>>>) -> !fir.ptr<!fir.array<?xf32>> ! CHECK: %[[VAL_4:.*]] = fir.convert %[[VAL_3]] : (!fir.ptr<!fir.array<?xf32>>) -> !fir.ref<!fir.array<?xf32>> @@ -66,7 +66,7 @@ subroutine character_allocatable_cst_len(x) end subroutine ! CHECK-LABEL: func.func @_QPcharacter_allocatable_cst_len( ! CHECK: %[[VAL_1:.*]] = arith.constant 10 : index -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0:[a-z0-9]*]] typeparams %[[VAL_1:[a-z0-9]*]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = {{.*}}Ex"} +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0:[a-z0-9]*]] typeparams %[[VAL_1:[a-z0-9]*]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = {{.*}}Ex"} ! CHECK: %[[VAL_3:.*]] = fir.load %[[VAL_2]]#0 : !fir.ref<!fir.box<!fir.heap<!fir.char<1,10>>>> ! CHECK: %[[VAL_4:.*]] = fir.box_addr %[[VAL_3]] : (!fir.box<!fir.heap<!fir.char<1,10>>>) -> !fir.heap<!fir.char<1,10>> ! CHECK: %[[VAL_5:.*]] = arith.constant 10 : index @@ -87,12 +87,12 @@ subroutine character_allocatable_dyn_len(x, l) call takes_char(x//"hello") end subroutine ! CHECK-LABEL: func.func @_QPcharacter_allocatable_dyn_len( -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1:[a-z0-9]*]] dummy_scope %{{[0-9]+}} {uniq_name = {{.*}}El"} +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1:[a-z0-9]*]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = {{.*}}El"} ! CHECK: %[[VAL_3:.*]] = fir.load %[[VAL_2]]#0 : !fir.ref<i64> ! CHECK: %[[VAL_4:.*]] = arith.constant 0 : i64 ! CHECK: %[[VAL_5:.*]] = arith.cmpi sgt, %[[VAL_3]], %[[VAL_4]] : i64 ! CHECK: %[[VAL_6:.*]] = arith.select %[[VAL_5]], %[[VAL_3]], %[[VAL_4]] : i64 -! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_0:[a-z0-9]*]] typeparams %[[VAL_6:[a-z0-9]*]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = {{.*}}Ex"} +! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_0:[a-z0-9]*]] typeparams %[[VAL_6:[a-z0-9]*]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = {{.*}}Ex"} ! CHECK: %[[VAL_8:.*]] = fir.load %[[VAL_7]]#0 : !fir.ref<!fir.box<!fir.heap<!fir.char<1,?>>>> ! CHECK: %[[VAL_9:.*]] = fir.box_addr %[[VAL_8]] : (!fir.box<!fir.heap<!fir.char<1,?>>>) -> !fir.heap<!fir.char<1,?>> ! CHECK: %[[VAL_10:.*]] = fir.emboxchar %[[VAL_9]], %[[VAL_6]] : (!fir.heap<!fir.char<1,?>>, i64) -> !fir.boxchar<1> @@ -110,7 +110,7 @@ subroutine print_allocatable(x) print *, x end subroutine ! CHECK-LABEL: func.func @_QPprint_allocatable( -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0:[a-z0-9]*]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = {{.*}}Ex"} +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0:[a-z0-9]*]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = {{.*}}Ex"} ! CHECK: %[[VAL_7:.*]] = fir.load %[[VAL_1]]#0 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>> ! CHECK: %[[VAL_8:.*]] = fir.convert %[[VAL_7]] : (!fir.box<!fir.heap<!fir.array<?xf32>>>) -> !fir.box<none> ! CHECK: %[[VAL_9:.*]] = fir.call @_FortranAioOutputDescriptor(%{{.*}}, %[[VAL_8]]) @@ -120,7 +120,7 @@ subroutine print_pointer(x) print *, x end subroutine ! CHECK-LABEL: func.func @_QPprint_pointer( -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0:[a-z0-9]*]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = {{.*}}Ex"} +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0:[a-z0-9]*]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = {{.*}}Ex"} ! CHECK: %[[VAL_7:.*]] = fir.load %[[VAL_1]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>> ! CHECK: %[[VAL_8:.*]] = fir.convert %[[VAL_7]] : (!fir.box<!fir.ptr<!fir.array<?xf32>>>) -> !fir.box<none> ! CHECK: %[[VAL_9:.*]] = fir.call @_FortranAioOutputDescriptor(%{{.*}}, %[[VAL_8]]) @@ -130,7 +130,7 @@ subroutine elemental_expr(x) call takes_array_2(x+42) end subroutine ! CHECK-LABEL: func.func @_QPelemental_expr( -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0:[a-z0-9]*]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = {{.*}}Ex"} +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0:[a-z0-9]*]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = {{.*}}Ex"} ! CHECK: %[[VAL_2:.*]] = fir.load %[[VAL_1]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?x?xi32>>>> ! CHECK: %[[VAL_3:.*]] = arith.constant 42 : i32 ! CHECK: %[[VAL_4:.*]] = arith.constant 0 : index diff --git a/flang/test/Lower/HLFIR/array-ctor-as-elemental-nested.f90 b/flang/test/Lower/HLFIR/array-ctor-as-elemental-nested.f90 index 1dc033d..bad3c62 100644 --- a/flang/test/Lower/HLFIR/array-ctor-as-elemental-nested.f90 +++ b/flang/test/Lower/HLFIR/array-ctor-as-elemental-nested.f90 @@ -9,14 +9,14 @@ ! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref<!fir.array<2xf32>> {fir.bindc_name = "h1"}) { ! CHECK: %[[VAL_2:.*]] = arith.constant 2 : index ! CHECK: %[[VAL_3:.*]] = fir.shape %[[VAL_2]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_1]](%[[VAL_3]]) dummy_scope %{{[0-9]+}} {uniq_name = "_QFtestEh1"} : (!fir.ref<!fir.array<2xf32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<2xf32>>, !fir.ref<!fir.array<2xf32>>) +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_1]](%[[VAL_3]]) dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFtestEh1"} : (!fir.ref<!fir.array<2xf32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<2xf32>>, !fir.ref<!fir.array<2xf32>>) ! CHECK: %[[VAL_5:.*]] = fir.alloca i32 {bindc_name = "k", uniq_name = "_QFtestEk"} ! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_5]] {uniq_name = "_QFtestEk"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_7:.*]] = fir.alloca i32 {bindc_name = "l", uniq_name = "_QFtestEl"} ! CHECK: %[[VAL_8:.*]]:2 = hlfir.declare %[[VAL_7]] {uniq_name = "_QFtestEl"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_9:.*]] = fir.address_of(@_QFtestECn) : !fir.ref<i32> ! CHECK: %[[VAL_10:.*]]:2 = hlfir.declare %[[VAL_9]] {fortran_attrs = #fir.var_attrs<parameter>, uniq_name = "_QFtestECn"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) -! CHECK: %[[VAL_11:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFtestEpi"} : (!fir.ref<f32>, !fir.dscope) -> (!fir.ref<f32>, !fir.ref<f32>) +! CHECK: %[[VAL_11:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFtestEpi"} : (!fir.ref<f32>, !fir.dscope) -> (!fir.ref<f32>, !fir.ref<f32>) ! CHECK: %[[VAL_12:.*]] = arith.constant 2 : index ! CHECK: %[[VAL_13:.*]] = fir.shape %[[VAL_12]] : (index) -> !fir.shape<1> ! CHECK: %[[VAL_14:.*]] = hlfir.elemental %[[VAL_13]] unordered : (!fir.shape<1>) -> !hlfir.expr<2xf32> { diff --git a/flang/test/Lower/HLFIR/array-ctor-as-elemental.f90 b/flang/test/Lower/HLFIR/array-ctor-as-elemental.f90 index 10fb500..5c4f079 100644 --- a/flang/test/Lower/HLFIR/array-ctor-as-elemental.f90 +++ b/flang/test/Lower/HLFIR/array-ctor-as-elemental.f90 @@ -7,7 +7,7 @@ subroutine test_as_simple_elemental(n) end subroutine ! CHECK-LABEL: func.func @_QPtest_as_simple_elemental( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<i32> {fir.bindc_name = "n"}) { -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFtest_as_simple_elementalEn"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFtest_as_simple_elementalEn"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_2:.*]] = arith.constant 4 : index ! CHECK: %[[VAL_3:.*]] = fir.shape %[[VAL_2]] : (index) -> !fir.shape<1> ! CHECK: %[[VAL_4:.*]] = arith.constant 1 : i64 @@ -42,9 +42,9 @@ end subroutine ! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref<i64> {fir.bindc_name = "ub"}, ! CHECK-SAME: %[[VAL_2:.*]]: !fir.ref<i64> {fir.bindc_name = "stride"}) { ! CHECK: %[[DSCOPE:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[DSCOPE]] {uniq_name = "_QFtest_as_strided_elementalElb"} : (!fir.ref<i64>, !fir.dscope) -> (!fir.ref<i64>, !fir.ref<i64>) -! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_2]] dummy_scope %[[DSCOPE]] {uniq_name = "_QFtest_as_strided_elementalEstride"} : (!fir.ref<i64>, !fir.dscope) -> (!fir.ref<i64>, !fir.ref<i64>) -! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %[[DSCOPE]] {uniq_name = "_QFtest_as_strided_elementalEub"} : (!fir.ref<i64>, !fir.dscope) -> (!fir.ref<i64>, !fir.ref<i64>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[DSCOPE]] arg {{[0-9]+}} {uniq_name = "_QFtest_as_strided_elementalElb"} : (!fir.ref<i64>, !fir.dscope) -> (!fir.ref<i64>, !fir.ref<i64>) +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_2]] dummy_scope %[[DSCOPE]] arg {{[0-9]+}} {uniq_name = "_QFtest_as_strided_elementalEstride"} : (!fir.ref<i64>, !fir.dscope) -> (!fir.ref<i64>, !fir.ref<i64>) +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %[[DSCOPE]] arg {{[0-9]+}} {uniq_name = "_QFtest_as_strided_elementalEub"} : (!fir.ref<i64>, !fir.dscope) -> (!fir.ref<i64>, !fir.ref<i64>) ! CHECK: %[[VAL_6:.*]] = arith.constant 0 : i64 ! CHECK: %[[VAL_7:.*]] = fir.load %[[VAL_5]]#0 : !fir.ref<i64> ! CHECK: %[[VAL_8:.*]] = fir.load %[[VAL_3]]#0 : !fir.ref<i64> @@ -92,7 +92,7 @@ subroutine test_as_elemental_with_pure_call(n) end subroutine ! CHECK-LABEL: func.func @_QPtest_as_elemental_with_pure_call( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<i32> {fir.bindc_name = "n"}) { -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFtest_as_elemental_with_pure_callEn"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFtest_as_elemental_with_pure_callEn"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_2:.*]] = arith.constant 4 : index ! CHECK: %[[VAL_3:.*]] = fir.shape %[[VAL_2]] : (index) -> !fir.shape<1> ! CHECK: %[[VAL_4:.*]] = arith.constant 1 : i64 diff --git a/flang/test/Lower/HLFIR/array-ctor-as-inlined-temp.f90 b/flang/test/Lower/HLFIR/array-ctor-as-inlined-temp.f90 index 6bbfffc..415a9df 100644 --- a/flang/test/Lower/HLFIR/array-ctor-as-inlined-temp.f90 +++ b/flang/test/Lower/HLFIR/array-ctor-as-inlined-temp.f90 @@ -116,7 +116,7 @@ end subroutine ! CHECK-LABEL: func.func @_QPtest_implied_do( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<i64> {fir.bindc_name = "n"}) { ! CHECK: %[[VAL_1:.*]] = fir.alloca index -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFtest_implied_doEn"} : (!fir.ref<i64>, !fir.dscope) -> (!fir.ref<i64>, !fir.ref<i64>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFtest_implied_doEn"} : (!fir.ref<i64>, !fir.dscope) -> (!fir.ref<i64>, !fir.ref<i64>) ! CHECK: %[[VAL_3:.*]] = arith.constant 0 : i64 ! CHECK: %[[VAL_4:.*]] = arith.constant 2 : i64 ! CHECK: %[[VAL_5:.*]] = fir.load %[[VAL_2]]#0 : !fir.ref<i64> @@ -178,9 +178,9 @@ end subroutine ! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref<i64> {fir.bindc_name = "ub"}, ! CHECK-SAME: %[[VAL_2:.*]]: !fir.ref<i64> {fir.bindc_name = "stride"}) { ! CHECK: %[[VAL_3:.*]] = fir.alloca index -! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFtest_strided_implied_doElb"} : (!fir.ref<i64>, !fir.dscope) -> (!fir.ref<i64>, !fir.ref<i64>) -! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_2]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFtest_strided_implied_doEstride"} : (!fir.ref<i64>, !fir.dscope) -> (!fir.ref<i64>, !fir.ref<i64>) -! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFtest_strided_implied_doEub"} : (!fir.ref<i64>, !fir.dscope) -> (!fir.ref<i64>, !fir.ref<i64>) +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFtest_strided_implied_doElb"} : (!fir.ref<i64>, !fir.dscope) -> (!fir.ref<i64>, !fir.ref<i64>) +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_2]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFtest_strided_implied_doEstride"} : (!fir.ref<i64>, !fir.dscope) -> (!fir.ref<i64>, !fir.ref<i64>) +! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFtest_strided_implied_doEub"} : (!fir.ref<i64>, !fir.dscope) -> (!fir.ref<i64>, !fir.ref<i64>) ! CHECK: %[[VAL_7:.*]] = arith.constant 0 : i64 ! CHECK: %[[VAL_8:.*]] = arith.constant 2 : i64 ! CHECK: %[[VAL_9:.*]] = fir.load %[[VAL_6]]#0 : !fir.ref<i64> @@ -241,8 +241,8 @@ end subroutine ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<i64> {fir.bindc_name = "n"}, ! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref<i64> {fir.bindc_name = "m"}) { ! CHECK: %[[VAL_2:.*]] = fir.alloca index -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFtest_nested_implied_doEm"} : (!fir.ref<i64>, !fir.dscope) -> (!fir.ref<i64>, !fir.ref<i64>) -! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFtest_nested_implied_doEn"} : (!fir.ref<i64>, !fir.dscope) -> (!fir.ref<i64>, !fir.ref<i64>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFtest_nested_implied_doEm"} : (!fir.ref<i64>, !fir.dscope) -> (!fir.ref<i64>, !fir.ref<i64>) +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFtest_nested_implied_doEn"} : (!fir.ref<i64>, !fir.dscope) -> (!fir.ref<i64>, !fir.ref<i64>) ! CHECK: %[[VAL_5:.*]] = arith.constant 0 : i64 ! CHECK: %[[VAL_6:.*]] = arith.constant 0 : i64 ! CHECK: %[[VAL_7:.*]] = fir.load %[[VAL_3]]#0 : !fir.ref<i64> diff --git a/flang/test/Lower/HLFIR/array-ctor-index.f90 b/flang/test/Lower/HLFIR/array-ctor-index.f90 index d94f45b..98b3aee 100644 --- a/flang/test/Lower/HLFIR/array-ctor-index.f90 +++ b/flang/test/Lower/HLFIR/array-ctor-index.f90 @@ -8,7 +8,7 @@ function test1(k) end function test1 ! CHECK-LABEL: func.func @_QPtest1( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<i8> {fir.bindc_name = "k"}) -> !fir.array<4xi8> { -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFtest1Ek"} : (!fir.ref<i8>, !fir.dscope) -> (!fir.ref<i8>, !fir.ref<i8>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFtest1Ek"} : (!fir.ref<i8>, !fir.dscope) -> (!fir.ref<i8>, !fir.ref<i8>) ! CHECK: %[[VAL_2:.*]] = arith.constant 4 : index ! CHECK: %[[VAL_3:.*]] = fir.alloca !fir.array<4xi8> {bindc_name = "test1", uniq_name = "_QFtest1Etest1"} ! CHECK: %[[VAL_4:.*]] = fir.shape %[[VAL_2]] : (index) -> !fir.shape<1> @@ -58,7 +58,7 @@ function test2(k) end function test2 ! CHECK-LABEL: func.func @_QPtest2( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<i16> {fir.bindc_name = "k"}) -> !fir.array<4xi16> { -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFtest2Ek"} : (!fir.ref<i16>, !fir.dscope) -> (!fir.ref<i16>, !fir.ref<i16>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFtest2Ek"} : (!fir.ref<i16>, !fir.dscope) -> (!fir.ref<i16>, !fir.ref<i16>) ! CHECK: %[[VAL_2:.*]] = arith.constant 4 : index ! CHECK: %[[VAL_3:.*]] = fir.alloca !fir.array<4xi16> {bindc_name = "test2", uniq_name = "_QFtest2Etest2"} ! CHECK: %[[VAL_4:.*]] = fir.shape %[[VAL_2]] : (index) -> !fir.shape<1> @@ -108,7 +108,7 @@ function test3(k) end function test3 ! CHECK-LABEL: func.func @_QPtest3( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<i32> {fir.bindc_name = "k"}) -> !fir.array<4xi32> { -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFtest3Ek"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFtest3Ek"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_2:.*]] = arith.constant 4 : index ! CHECK: %[[VAL_3:.*]] = fir.alloca !fir.array<4xi32> {bindc_name = "test3", uniq_name = "_QFtest3Etest3"} ! CHECK: %[[VAL_4:.*]] = fir.shape %[[VAL_2]] : (index) -> !fir.shape<1> @@ -158,7 +158,7 @@ function test4(k) end function test4 ! CHECK-LABEL: func.func @_QPtest4( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<i64> {fir.bindc_name = "k"}) -> !fir.array<4xi64> { -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFtest4Ek"} : (!fir.ref<i64>, !fir.dscope) -> (!fir.ref<i64>, !fir.ref<i64>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFtest4Ek"} : (!fir.ref<i64>, !fir.dscope) -> (!fir.ref<i64>, !fir.ref<i64>) ! CHECK: %[[VAL_2:.*]] = arith.constant 4 : index ! CHECK: %[[VAL_3:.*]] = fir.alloca !fir.array<4xi64> {bindc_name = "test4", uniq_name = "_QFtest4Etest4"} ! CHECK: %[[VAL_4:.*]] = fir.shape %[[VAL_2]] : (index) -> !fir.shape<1> diff --git a/flang/test/Lower/HLFIR/assumed-rank-calls.f90 b/flang/test/Lower/HLFIR/assumed-rank-calls.f90 index 63b8d9f..7458310 100644 --- a/flang/test/Lower/HLFIR/assumed-rank-calls.f90 +++ b/flang/test/Lower/HLFIR/assumed-rank-calls.f90 @@ -15,7 +15,7 @@ end subroutine ! CHECK-LABEL: func.func @_QPtest_alloc_to_nonalloc( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.heap<!fir.array<*:f32>>>> {fir.bindc_name = "x"}) { ! CHECK: %[[VAL_1:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFtest_alloc_to_nonallocEx"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<*:f32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<*:f32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<*:f32>>>>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFtest_alloc_to_nonallocEx"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<*:f32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<*:f32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<*:f32>>>>) ! CHECK: %[[VAL_3:.*]] = fir.load %[[VAL_2]]#0 : !fir.ref<!fir.box<!fir.heap<!fir.array<*:f32>>>> ! CHECK: %[[VAL_4:.*]] = fir.rebox_assumed_rank %[[VAL_3]] lbs ones : (!fir.box<!fir.heap<!fir.array<*:f32>>>) -> !fir.box<!fir.array<*:f32>> ! CHECK: fir.call @_QPtakes_assumed_rank(%[[VAL_4]]) fastmath<contract> : (!fir.box<!fir.array<*:f32>>) -> () @@ -34,7 +34,7 @@ end subroutine ! CHECK-LABEL: func.func @_QPtest_to_bindc( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.box<!fir.array<*:f32>> {fir.bindc_name = "x"}) { ! CHECK: %[[VAL_1:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] {uniq_name = "_QFtest_to_bindcEx"} : (!fir.box<!fir.array<*:f32>>, !fir.dscope) -> (!fir.box<!fir.array<*:f32>>, !fir.box<!fir.array<*:f32>>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] arg {{[0-9]+}} {uniq_name = "_QFtest_to_bindcEx"} : (!fir.box<!fir.array<*:f32>>, !fir.dscope) -> (!fir.box<!fir.array<*:f32>>, !fir.box<!fir.array<*:f32>>) ! CHECK: %[[VAL_3:.*]] = fir.rebox_assumed_rank %[[VAL_2]]#0 lbs zeroes : (!fir.box<!fir.array<*:f32>>) -> !fir.box<!fir.array<*:f32>> ! CHECK: fir.call @bindc_func(%[[VAL_3]]) proc_attrs<bind_c> fastmath<contract> : (!fir.box<!fir.array<*:f32>>) -> () ! CHECK: return @@ -53,7 +53,7 @@ end subroutine ! CHECK-SAME: %[[VAL_0:.*]]: !fir.box<!fir.array<*:f32>> {fir.bindc_name = "x", fir.target}) { ! CHECK: %[[VAL_1:.*]] = fir.alloca !fir.box<!fir.ptr<!fir.array<*:f32>>> ! CHECK: %[[VAL_2:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_2]] {fortran_attrs = #fir.var_attrs<target>, uniq_name = "_QFtest_target_to_pointerEx"} : (!fir.box<!fir.array<*:f32>>, !fir.dscope) -> (!fir.box<!fir.array<*:f32>>, !fir.box<!fir.array<*:f32>>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_2]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<target>, uniq_name = "_QFtest_target_to_pointerEx"} : (!fir.box<!fir.array<*:f32>>, !fir.dscope) -> (!fir.box<!fir.array<*:f32>>, !fir.box<!fir.array<*:f32>>) ! CHECK: %[[VAL_4:.*]] = fir.rebox_assumed_rank %[[VAL_3]]#0 lbs preserve : (!fir.box<!fir.array<*:f32>>) -> !fir.box<!fir.ptr<!fir.array<*:f32>>> ! CHECK: fir.store %[[VAL_4]] to %[[VAL_1]] : !fir.ref<!fir.box<!fir.ptr<!fir.array<*:f32>>>> ! CHECK: fir.call @_QPtakes_target_as_pointer(%[[VAL_1]]) fastmath<contract> : (!fir.ref<!fir.box<!fir.ptr<!fir.array<*:f32>>>>) -> () @@ -74,7 +74,7 @@ end subroutine ! CHECK-LABEL: func.func @_QPtest_poly_to_nonepoly( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.class<!fir.array<*:!fir.type<_QFtest_poly_to_nonepolyTt{i:i32}>>> {fir.bindc_name = "x"}) { ! CHECK: %[[VAL_1:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] {uniq_name = "_QFtest_poly_to_nonepolyEx"} : (!fir.class<!fir.array<*:!fir.type<_QFtest_poly_to_nonepolyTt{i:i32}>>>, !fir.dscope) -> (!fir.class<!fir.array<*:!fir.type<_QFtest_poly_to_nonepolyTt{i:i32}>>>, !fir.class<!fir.array<*:!fir.type<_QFtest_poly_to_nonepolyTt{i:i32}>>>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] arg {{[0-9]+}} {uniq_name = "_QFtest_poly_to_nonepolyEx"} : (!fir.class<!fir.array<*:!fir.type<_QFtest_poly_to_nonepolyTt{i:i32}>>>, !fir.dscope) -> (!fir.class<!fir.array<*:!fir.type<_QFtest_poly_to_nonepolyTt{i:i32}>>>, !fir.class<!fir.array<*:!fir.type<_QFtest_poly_to_nonepolyTt{i:i32}>>>) ! CHECK: %[[VAL_3:.*]] = fir.rebox_assumed_rank %[[VAL_2]]#0 lbs ones : (!fir.class<!fir.array<*:!fir.type<_QFtest_poly_to_nonepolyTt{i:i32}>>>) -> !fir.box<!fir.array<*:!fir.type<_QFtest_poly_to_nonepolyTt{i:i32}>>> ! CHECK: fir.call @_QPtakes_assumed_rank_t(%[[VAL_3]]) fastmath<contract> : (!fir.box<!fir.array<*:!fir.type<_QFtest_poly_to_nonepolyTt{i:i32}>>>) -> () ! CHECK: return @@ -94,7 +94,7 @@ end subroutine ! CHECK-SAME: %[[VAL_0:.*]]: !fir.box<!fir.array<*:f32>> {fir.bindc_name = "x"}) { ! CHECK: %[[VAL_1:.*]] = fir.alloca !fir.box<!fir.heap<!fir.array<*:f32>>> ! CHECK: %[[VAL_2:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_2]] {uniq_name = "_QFtest_copy_in_outEx"} : (!fir.box<!fir.array<*:f32>>, !fir.dscope) -> (!fir.box<!fir.array<*:f32>>, !fir.box<!fir.array<*:f32>>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_2]] arg {{[0-9]+}} {uniq_name = "_QFtest_copy_in_outEx"} : (!fir.box<!fir.array<*:f32>>, !fir.dscope) -> (!fir.box<!fir.array<*:f32>>, !fir.box<!fir.array<*:f32>>) ! CHECK: %[[VAL_4:.*]]:2 = hlfir.copy_in %[[VAL_3]]#0 to %[[VAL_1]] : (!fir.box<!fir.array<*:f32>>, !fir.ref<!fir.box<!fir.heap<!fir.array<*:f32>>>>) -> (!fir.box<!fir.array<*:f32>>, i1) ! CHECK: fir.call @_QPtakes_contiguous(%[[VAL_4]]#0) fastmath<contract> : (!fir.box<!fir.array<*:f32>>) -> () ! CHECK: hlfir.copy_out %[[VAL_1]], %[[VAL_4]]#1 to %[[VAL_3]]#0 : (!fir.ref<!fir.box<!fir.heap<!fir.array<*:f32>>>>, i1, !fir.box<!fir.array<*:f32>>) -> () @@ -112,7 +112,7 @@ end subroutine ! CHECK-SAME: %[[VAL_0:.*]]: !fir.box<!fir.array<*:f32>> {fir.bindc_name = "x"}) { ! CHECK: %[[VAL_1:.*]] = fir.alloca !fir.box<!fir.heap<!fir.array<*:f32>>> ! CHECK: %[[VAL_2:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_2]] {uniq_name = "_QFtest_copy_in_out_2Ex"} : (!fir.box<!fir.array<*:f32>>, !fir.dscope) -> (!fir.box<!fir.array<*:f32>>, !fir.box<!fir.array<*:f32>>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_2]] arg {{[0-9]+}} {uniq_name = "_QFtest_copy_in_out_2Ex"} : (!fir.box<!fir.array<*:f32>>, !fir.dscope) -> (!fir.box<!fir.array<*:f32>>, !fir.box<!fir.array<*:f32>>) ! CHECK: %[[VAL_4:.*]]:2 = hlfir.copy_in %[[VAL_3]]#0 to %[[VAL_1]] : (!fir.box<!fir.array<*:f32>>, !fir.ref<!fir.box<!fir.heap<!fir.array<*:f32>>>>) -> (!fir.box<!fir.array<*:f32>>, i1) ! CHECK: fir.call @_QPtakes_contiguous_intentin(%[[VAL_4]]#0) fastmath<contract> : (!fir.box<!fir.array<*:f32>>) -> () ! CHECK: hlfir.copy_out %[[VAL_1]], %[[VAL_4]]#1 : (!fir.ref<!fir.box<!fir.heap<!fir.array<*:f32>>>>, i1) -> () diff --git a/flang/test/Lower/HLFIR/assumed-rank-entry.f90 b/flang/test/Lower/HLFIR/assumed-rank-entry.f90 index d2e470a..3135a63 100644 --- a/flang/test/Lower/HLFIR/assumed-rank-entry.f90 +++ b/flang/test/Lower/HLFIR/assumed-rank-entry.f90 @@ -16,7 +16,7 @@ end subroutine ! CHECK-LABEL: func.func @_QPtest_main_entry( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.box<!fir.array<*:f32>> {fir.bindc_name = "x"}) { ! CHECK: %[[VAL_1:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] {uniq_name = "_QFtest_main_entryEx"} : (!fir.box<!fir.array<*:f32>>, !fir.dscope) -> (!fir.box<!fir.array<*:f32>>, !fir.box<!fir.array<*:f32>>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] arg {{[0-9]+}} {uniq_name = "_QFtest_main_entryEx"} : (!fir.box<!fir.array<*:f32>>, !fir.dscope) -> (!fir.box<!fir.array<*:f32>>, !fir.box<!fir.array<*:f32>>) ! CHECK-LABEL: func.func @_QPtest_alternate_entry() { ! CHECK: %[[VAL_0:.*]] = fir.alloca !fir.box<!fir.heap<!fir.array<*:f32>>> diff --git a/flang/test/Lower/HLFIR/assumed-rank-iface-alloc-ptr.f90 b/flang/test/Lower/HLFIR/assumed-rank-iface-alloc-ptr.f90 index fb1385f..bcb0031 100644 --- a/flang/test/Lower/HLFIR/assumed-rank-iface-alloc-ptr.f90 +++ b/flang/test/Lower/HLFIR/assumed-rank-iface-alloc-ptr.f90 @@ -23,7 +23,7 @@ subroutine scalar_alloc_to_assumed_rank(x) end subroutine ! CHECK-LABEL: func.func @_QPscalar_alloc_to_assumed_rank( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.heap<f32>>> {fir.bindc_name = "x"}) { -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFscalar_alloc_to_assumed_rankEx"} : (!fir.ref<!fir.box<!fir.heap<f32>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<f32>>>, !fir.ref<!fir.box<!fir.heap<f32>>>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFscalar_alloc_to_assumed_rankEx"} : (!fir.ref<!fir.box<!fir.heap<f32>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<f32>>>, !fir.ref<!fir.box<!fir.heap<f32>>>) ! CHECK: %[[VAL_2:.*]] = fir.convert %[[VAL_1]]#0 : (!fir.ref<!fir.box<!fir.heap<f32>>>) -> !fir.ref<!fir.box<!fir.heap<!fir.array<*:f32>>>> ! CHECK: fir.call @_QPalloc_assumed_rank(%[[VAL_2]]) fastmath<contract> : (!fir.ref<!fir.box<!fir.heap<!fir.array<*:f32>>>>) -> () @@ -34,7 +34,7 @@ subroutine r2_alloc_to_assumed_rank(x) end subroutine ! CHECK-LABEL: func.func @_QPr2_alloc_to_assumed_rank( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.heap<!fir.array<?x?xf32>>>> {fir.bindc_name = "x"}) { -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFr2_alloc_to_assumed_rankEx"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?x?xf32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?x?xf32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?x?xf32>>>>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFr2_alloc_to_assumed_rankEx"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?x?xf32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?x?xf32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?x?xf32>>>>) ! CHECK: %[[VAL_2:.*]] = fir.convert %[[VAL_1]]#0 : (!fir.ref<!fir.box<!fir.heap<!fir.array<?x?xf32>>>>) -> !fir.ref<!fir.box<!fir.heap<!fir.array<*:f32>>>> ! CHECK: fir.call @_QPalloc_assumed_rank(%[[VAL_2]]) fastmath<contract> : (!fir.ref<!fir.box<!fir.heap<!fir.array<*:f32>>>>) -> () @@ -45,7 +45,7 @@ subroutine scalar_pointer_to_assumed_rank(x) end subroutine ! CHECK-LABEL: func.func @_QPscalar_pointer_to_assumed_rank( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.ptr<f32>>> {fir.bindc_name = "x"}) { -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFscalar_pointer_to_assumed_rankEx"} : (!fir.ref<!fir.box<!fir.ptr<f32>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<f32>>>, !fir.ref<!fir.box<!fir.ptr<f32>>>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFscalar_pointer_to_assumed_rankEx"} : (!fir.ref<!fir.box<!fir.ptr<f32>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<f32>>>, !fir.ref<!fir.box<!fir.ptr<f32>>>) ! CHECK: %[[VAL_2:.*]] = fir.convert %[[VAL_1]]#0 : (!fir.ref<!fir.box<!fir.ptr<f32>>>) -> !fir.ref<!fir.box<!fir.ptr<!fir.array<*:f32>>>> ! CHECK: fir.call @_QPpointer_assumed_rank(%[[VAL_2]]) fastmath<contract> : (!fir.ref<!fir.box<!fir.ptr<!fir.array<*:f32>>>>) -> () @@ -56,7 +56,7 @@ subroutine r2_pointer_to_assumed_rank(x) end subroutine ! CHECK-LABEL: func.func @_QPr2_pointer_to_assumed_rank( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.ptr<!fir.array<?x?xf32>>>> {fir.bindc_name = "x"}) { -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFr2_pointer_to_assumed_rankEx"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?x?xf32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?x?xf32>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?x?xf32>>>>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFr2_pointer_to_assumed_rankEx"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?x?xf32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?x?xf32>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?x?xf32>>>>) ! CHECK: %[[VAL_2:.*]] = fir.convert %[[VAL_1]]#0 : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?x?xf32>>>>) -> !fir.ref<!fir.box<!fir.ptr<!fir.array<*:f32>>>> ! CHECK: fir.call @_QPpointer_assumed_rank(%[[VAL_2]]) fastmath<contract> : (!fir.ref<!fir.box<!fir.ptr<!fir.array<*:f32>>>>) -> () @@ -68,7 +68,7 @@ end subroutine ! CHECK-LABEL: func.func @_QPr2_target_to_pointer_assumed_rank( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.box<!fir.array<?x?xf32>> {fir.bindc_name = "x", fir.target}) { ! CHECK: %[[VAL_1:.*]] = fir.alloca !fir.box<!fir.ptr<!fir.array<?x?xf32>>> -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<target>, uniq_name = "_QFr2_target_to_pointer_assumed_rankEx"} : (!fir.box<!fir.array<?x?xf32>>, !fir.dscope) -> (!fir.box<!fir.array<?x?xf32>>, !fir.box<!fir.array<?x?xf32>>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<target>, uniq_name = "_QFr2_target_to_pointer_assumed_rankEx"} : (!fir.box<!fir.array<?x?xf32>>, !fir.dscope) -> (!fir.box<!fir.array<?x?xf32>>, !fir.box<!fir.array<?x?xf32>>) ! CHECK: %[[VAL_3:.*]] = fir.rebox %[[VAL_2]]#1 : (!fir.box<!fir.array<?x?xf32>>) -> !fir.box<!fir.ptr<!fir.array<?x?xf32>>> ! CHECK: fir.store %[[VAL_3]] to %[[VAL_1]] : !fir.ref<!fir.box<!fir.ptr<!fir.array<?x?xf32>>>> ! CHECK: %[[VAL_4:.*]] = fir.convert %[[VAL_1]] : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?x?xf32>>>>) -> !fir.ref<!fir.box<!fir.ptr<!fir.array<*:f32>>>> diff --git a/flang/test/Lower/HLFIR/assumed-rank-iface.f90 b/flang/test/Lower/HLFIR/assumed-rank-iface.f90 index ffb36fa..7837b4f 100644 --- a/flang/test/Lower/HLFIR/assumed-rank-iface.f90 +++ b/flang/test/Lower/HLFIR/assumed-rank-iface.f90 @@ -23,7 +23,7 @@ subroutine int_scalar_to_assumed_rank(x) end subroutine ! CHECK-LABEL: func.func @_QPint_scalar_to_assumed_rank( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<i32> {fir.bindc_name = "x"}) { -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFint_scalar_to_assumed_rankEx"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFint_scalar_to_assumed_rankEx"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_2:.*]] = fir.embox %[[VAL_1]]#0 : (!fir.ref<i32>) -> !fir.box<i32> ! CHECK: %[[VAL_3:.*]] = fir.convert %[[VAL_2]] : (!fir.box<i32>) -> !fir.box<!fir.array<*:i32>> ! CHECK: fir.call @_QPint_assumed_rank(%[[VAL_3]]) fastmath<contract> : (!fir.box<!fir.array<*:i32>>) -> () @@ -35,7 +35,7 @@ subroutine int_scalar_to_assumed_rank_bindc(x) end subroutine ! CHECK-LABEL: func.func @_QPint_scalar_to_assumed_rank_bindc( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<i32> {fir.bindc_name = "x"}) { -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFint_scalar_to_assumed_rank_bindcEx"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFint_scalar_to_assumed_rank_bindcEx"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_2:.*]] = fir.embox %[[VAL_1]]#0 : (!fir.ref<i32>) -> !fir.box<i32> ! CHECK: %[[VAL_3:.*]] = fir.convert %[[VAL_2]] : (!fir.box<i32>) -> !fir.box<!fir.array<*:i32>> ! CHECK: fir.call @int_assumed_rank_bindc(%[[VAL_3]]) proc_attrs<bind_c> fastmath<contract> : (!fir.box<!fir.array<*:i32>>) -> () @@ -49,7 +49,7 @@ end subroutine ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.array<10xi32>> {fir.bindc_name = "x"}) { ! CHECK: %[[VAL_1:.*]] = arith.constant 10 : index ! CHECK: %[[VAL_2:.*]] = fir.shape %[[VAL_1]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_2]]) dummy_scope %{{[0-9]+}} {uniq_name = "_QFint_r1_to_assumed_rankEx"} : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_2]]) dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFint_r1_to_assumed_rankEx"} : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>) ! CHECK: %[[VAL_4:.*]] = fir.embox %[[VAL_3]]#0(%[[VAL_2]]) : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>) -> !fir.box<!fir.array<10xi32>> ! CHECK: %[[VAL_5:.*]] = fir.convert %[[VAL_4]] : (!fir.box<!fir.array<10xi32>>) -> !fir.box<!fir.array<*:i32>> ! CHECK: fir.call @_QPint_assumed_rank(%[[VAL_5]]) fastmath<contract> : (!fir.box<!fir.array<*:i32>>) -> () @@ -66,7 +66,7 @@ end subroutine ! CHECK: %[[VAL_3:.*]] = arith.constant 4 : index ! CHECK: %[[VAL_4:.*]] = arith.constant 5 : index ! CHECK: %[[VAL_5:.*]] = fir.shape %[[VAL_1]], %[[VAL_2]], %[[VAL_3]], %[[VAL_4]] : (index, index, index, index) -> !fir.shape<4> -! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_5]]) dummy_scope %{{[0-9]+}} {uniq_name = "_QFint_r4_to_assumed_rankEx"} : (!fir.ref<!fir.array<2x3x4x5xi32>>, !fir.shape<4>, !fir.dscope) -> (!fir.ref<!fir.array<2x3x4x5xi32>>, !fir.ref<!fir.array<2x3x4x5xi32>>) +! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_5]]) dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFint_r4_to_assumed_rankEx"} : (!fir.ref<!fir.array<2x3x4x5xi32>>, !fir.shape<4>, !fir.dscope) -> (!fir.ref<!fir.array<2x3x4x5xi32>>, !fir.ref<!fir.array<2x3x4x5xi32>>) ! CHECK: %[[VAL_7:.*]] = fir.embox %[[VAL_6]]#0(%[[VAL_5]]) : (!fir.ref<!fir.array<2x3x4x5xi32>>, !fir.shape<4>) -> !fir.box<!fir.array<2x3x4x5xi32>> ! CHECK: %[[VAL_8:.*]] = fir.convert %[[VAL_7]] : (!fir.box<!fir.array<2x3x4x5xi32>>) -> !fir.box<!fir.array<*:i32>> ! CHECK: fir.call @_QPint_assumed_rank(%[[VAL_8]]) fastmath<contract> : (!fir.box<!fir.array<*:i32>>) -> () @@ -78,7 +78,7 @@ subroutine int_assumed_shape_to_assumed_rank(x) end subroutine ! CHECK-LABEL: func.func @_QPint_assumed_shape_to_assumed_rank( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.box<!fir.array<?x?xi32>> {fir.bindc_name = "x"}) { -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFint_assumed_shape_to_assumed_rankEx"} : (!fir.box<!fir.array<?x?xi32>>, !fir.dscope) -> (!fir.box<!fir.array<?x?xi32>>, !fir.box<!fir.array<?x?xi32>>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFint_assumed_shape_to_assumed_rankEx"} : (!fir.box<!fir.array<?x?xi32>>, !fir.dscope) -> (!fir.box<!fir.array<?x?xi32>>, !fir.box<!fir.array<?x?xi32>>) ! CHECK: %[[VAL_2:.*]] = fir.convert %[[VAL_1]]#0 : (!fir.box<!fir.array<?x?xi32>>) -> !fir.box<!fir.array<*:i32>> ! CHECK: fir.call @_QPint_assumed_rank(%[[VAL_2]]) fastmath<contract> : (!fir.box<!fir.array<*:i32>>) -> () @@ -89,7 +89,7 @@ subroutine int_assumed_shape_to_assumed_rank_bindc(x) end subroutine ! CHECK-LABEL: func.func @_QPint_assumed_shape_to_assumed_rank_bindc( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.box<!fir.array<?x?xi32>> {fir.bindc_name = "x"}) { -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFint_assumed_shape_to_assumed_rank_bindcEx"} : (!fir.box<!fir.array<?x?xi32>>, !fir.dscope) -> (!fir.box<!fir.array<?x?xi32>>, !fir.box<!fir.array<?x?xi32>>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFint_assumed_shape_to_assumed_rank_bindcEx"} : (!fir.box<!fir.array<?x?xi32>>, !fir.dscope) -> (!fir.box<!fir.array<?x?xi32>>, !fir.box<!fir.array<?x?xi32>>) ! CHECK: %[[VAL_2:.*]] = arith.constant 0 : index ! CHECK: %[[VAL_3:.*]] = fir.shift %[[VAL_2]], %[[VAL_2]] : (index, index) -> !fir.shift<2> ! CHECK: %[[VAL_4:.*]] = fir.rebox %[[VAL_1]]#0(%[[VAL_3]]) : (!fir.box<!fir.array<?x?xi32>>, !fir.shift<2>) -> !fir.box<!fir.array<?x?xi32>> @@ -103,7 +103,7 @@ subroutine int_allocatable_to_assumed_rank(x) end subroutine ! CHECK-LABEL: func.func @_QPint_allocatable_to_assumed_rank( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.heap<!fir.array<?x?xi32>>>> {fir.bindc_name = "x"}) { -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFint_allocatable_to_assumed_rankEx"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?x?xi32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?x?xi32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?x?xi32>>>>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFint_allocatable_to_assumed_rankEx"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?x?xi32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?x?xi32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?x?xi32>>>>) ! CHECK: %[[VAL_2:.*]] = fir.load %[[VAL_1]]#0 : !fir.ref<!fir.box<!fir.heap<!fir.array<?x?xi32>>>> ! CHECK: %[[VAL_3:.*]] = fir.rebox %[[VAL_2]] : (!fir.box<!fir.heap<!fir.array<?x?xi32>>>) -> !fir.box<!fir.array<?x?xi32>> ! CHECK: %[[VAL_4:.*]] = fir.convert %[[VAL_3]] : (!fir.box<!fir.array<?x?xi32>>) -> !fir.box<!fir.array<*:i32>> @@ -116,7 +116,7 @@ subroutine int_allocatable_to_assumed_rank_opt(x) end subroutine ! CHECK-LABEL: func.func @_QPint_allocatable_to_assumed_rank_opt( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.heap<!fir.array<?x?xi32>>>> {fir.bindc_name = "x"}) { -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFint_allocatable_to_assumed_rank_optEx"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?x?xi32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?x?xi32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?x?xi32>>>>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFint_allocatable_to_assumed_rank_optEx"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?x?xi32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?x?xi32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?x?xi32>>>>) ! CHECK: %[[VAL_2:.*]] = fir.load %[[VAL_1]]#0 : !fir.ref<!fir.box<!fir.heap<!fir.array<?x?xi32>>>> ! CHECK: %[[VAL_3:.*]] = fir.box_addr %[[VAL_2]] : (!fir.box<!fir.heap<!fir.array<?x?xi32>>>) -> !fir.heap<!fir.array<?x?xi32>> ! CHECK: %[[VAL_4:.*]] = fir.convert %[[VAL_3]] : (!fir.heap<!fir.array<?x?xi32>>) -> i64 @@ -147,6 +147,6 @@ end subroutine ! CHECK: %[[VAL_5:.*]] = arith.select %[[VAL_4]], %[[VAL_2]], %[[VAL_3]] : index ! CHECK: %[[VAL_6:.*]] = fir.assumed_size_extent : index ! CHECK: %[[VAL_7:.*]] = fir.shape %[[VAL_5]], %[[VAL_6]] : (index, index) -> !fir.shape<2> -! CHECK: %[[VAL_8:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_7]]) dummy_scope %{{[0-9]+}} {uniq_name = "_QFint_r2_assumed_size_to_assumed_rankEx"} : (!fir.ref<!fir.array<10x?xi32>>, !fir.shape<2>, !fir.dscope) -> (!fir.box<!fir.array<10x?xi32>>, !fir.ref<!fir.array<10x?xi32>>) +! CHECK: %[[VAL_8:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_7]]) dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFint_r2_assumed_size_to_assumed_rankEx"} : (!fir.ref<!fir.array<10x?xi32>>, !fir.shape<2>, !fir.dscope) -> (!fir.box<!fir.array<10x?xi32>>, !fir.ref<!fir.array<10x?xi32>>) ! CHECK: %[[VAL_9:.*]] = fir.convert %[[VAL_8]]#0 : (!fir.box<!fir.array<10x?xi32>>) -> !fir.box<!fir.array<*:i32>> ! CHECK: fir.call @_QPint_assumed_rank(%[[VAL_9]]) fastmath<contract> : (!fir.box<!fir.array<*:i32>>) -> () diff --git a/flang/test/Lower/HLFIR/assumed-rank-inquiries-2.f90 b/flang/test/Lower/HLFIR/assumed-rank-inquiries-2.f90 index f54399e..1e82b29 100644 --- a/flang/test/Lower/HLFIR/assumed-rank-inquiries-2.f90 +++ b/flang/test/Lower/HLFIR/assumed-rank-inquiries-2.f90 @@ -28,7 +28,7 @@ end subroutine ! CHECK-LABEL: func.func @_QPtest_size_1( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.box<!fir.array<*:f32>> {fir.bindc_name = "x"}) { ! CHECK: %[[VAL_1:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] {uniq_name = "_QFtest_size_1Ex"} : (!fir.box<!fir.array<*:f32>>, !fir.dscope) -> (!fir.box<!fir.array<*:f32>>, !fir.box<!fir.array<*:f32>>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] arg {{[0-9]+}} {uniq_name = "_QFtest_size_1Ex"} : (!fir.box<!fir.array<*:f32>>, !fir.dscope) -> (!fir.box<!fir.array<*:f32>>, !fir.box<!fir.array<*:f32>>) ! CHECK: %[[VAL_5:.*]] = fir.convert %[[VAL_2]]#0 : (!fir.box<!fir.array<*:f32>>) -> !fir.box<none> ! CHECK: %[[VAL_7:.*]] = fir.call @_FortranASize(%[[VAL_5]] ! CHECK: %[[VAL_8:.*]] = fir.convert %[[VAL_7]] : (i64) -> i32 @@ -42,7 +42,7 @@ end subroutine ! CHECK-SAME: %[[VAL_0:.*]]: !fir.box<!fir.array<*:f32>> {fir.bindc_name = "x"}) { ! CHECK: %[[VAL_1:.*]] = fir.alloca i32 ! CHECK: %[[VAL_2:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_2]] {uniq_name = "_QFtest_size_2Ex"} : (!fir.box<!fir.array<*:f32>>, !fir.dscope) -> (!fir.box<!fir.array<*:f32>>, !fir.box<!fir.array<*:f32>>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_2]] arg {{[0-9]+}} {uniq_name = "_QFtest_size_2Ex"} : (!fir.box<!fir.array<*:f32>>, !fir.dscope) -> (!fir.box<!fir.array<*:f32>>, !fir.box<!fir.array<*:f32>>) ! CHECK: %[[VAL_4:.*]] = arith.constant 2 : i32 ! CHECK: fir.store %[[VAL_4]] to %[[VAL_1]] : !fir.ref<i32> ! CHECK: %[[VAL_5:.*]] = fir.convert %[[VAL_1]] : (!fir.ref<i32>) -> i64 @@ -70,8 +70,8 @@ end subroutine ! CHECK-SAME: %[[VAL_0:.*]]: !fir.box<!fir.array<*:f32>> {fir.bindc_name = "x"}, ! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref<i32> {fir.bindc_name = "d", fir.optional}) { ! CHECK: %[[VAL_2:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %[[VAL_2]] {fortran_attrs = #fir.var_attrs<optional>, uniq_name = "_QFtest_size_3Ed"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) -! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_2]] {uniq_name = "_QFtest_size_3Ex"} : (!fir.box<!fir.array<*:f32>>, !fir.dscope) -> (!fir.box<!fir.array<*:f32>>, !fir.box<!fir.array<*:f32>>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %[[VAL_2]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<optional>, uniq_name = "_QFtest_size_3Ed"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_2]] arg {{[0-9]+}} {uniq_name = "_QFtest_size_3Ex"} : (!fir.box<!fir.array<*:f32>>, !fir.dscope) -> (!fir.box<!fir.array<*:f32>>, !fir.box<!fir.array<*:f32>>) ! CHECK: %[[VAL_5:.*]] = fir.convert %[[VAL_3]]#0 : (!fir.ref<i32>) -> i64 ! CHECK: %[[VAL_6:.*]] = arith.constant 0 : i64 ! CHECK: %[[VAL_7:.*]] = arith.cmpi eq, %[[VAL_5]], %[[VAL_6]] : i64 @@ -96,7 +96,7 @@ end subroutine ! CHECK-LABEL: func.func @_QPtest_size_4( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.heap<!fir.array<*:f32>>>> {fir.bindc_name = "x"}) { ! CHECK: %[[VAL_1:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFtest_size_4Ex"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<*:f32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<*:f32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<*:f32>>>>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFtest_size_4Ex"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<*:f32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<*:f32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<*:f32>>>>) ! CHECK: %[[VAL_3:.*]] = fir.load %[[VAL_2]]#0 : !fir.ref<!fir.box<!fir.heap<!fir.array<*:f32>>>> ! CHECK: %[[VAL_6:.*]] = fir.convert %[[VAL_3]] : (!fir.box<!fir.heap<!fir.array<*:f32>>>) -> !fir.box<none> ! CHECK: %[[VAL_8:.*]] = fir.call @_FortranASize(%[[VAL_6]] diff --git a/flang/test/Lower/HLFIR/assumed-rank-inquiries.f90 b/flang/test/Lower/HLFIR/assumed-rank-inquiries.f90 index f19596e..fcca173 100644 --- a/flang/test/Lower/HLFIR/assumed-rank-inquiries.f90 +++ b/flang/test/Lower/HLFIR/assumed-rank-inquiries.f90 @@ -98,7 +98,7 @@ end subroutine ! CHECK-LABEL: func.func @_QPtest_allocated( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.heap<!fir.array<*:f32>>>> {fir.bindc_name = "x"}) { ! CHECK: %[[VAL_1:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFtest_allocatedEx"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<*:f32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<*:f32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<*:f32>>>>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFtest_allocatedEx"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<*:f32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<*:f32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<*:f32>>>>) ! CHECK: %[[VAL_3:.*]] = fir.load %[[VAL_2]]#0 : !fir.ref<!fir.box<!fir.heap<!fir.array<*:f32>>>> ! CHECK: %[[VAL_4:.*]] = fir.box_addr %[[VAL_3]] : (!fir.box<!fir.heap<!fir.array<*:f32>>>) -> !fir.heap<!fir.array<*:f32>> ! CHECK: %[[VAL_5:.*]] = fir.convert %[[VAL_4]] : (!fir.heap<!fir.array<*:f32>>) -> i64 @@ -114,7 +114,7 @@ end subroutine ! CHECK-LABEL: func.func @_QPtest_associated_1( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.ptr<!fir.array<*:f32>>>> {fir.bindc_name = "x"}) { ! CHECK: %[[VAL_1:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFtest_associated_1Ex"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<*:f32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<*:f32>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<*:f32>>>>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFtest_associated_1Ex"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<*:f32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<*:f32>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<*:f32>>>>) ! CHECK: %[[VAL_3:.*]] = fir.load %[[VAL_2]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<*:f32>>>> ! CHECK: %[[VAL_4:.*]] = fir.box_addr %[[VAL_3]] : (!fir.box<!fir.ptr<!fir.array<*:f32>>>) -> !fir.ptr<!fir.array<*:f32>> ! CHECK: %[[VAL_5:.*]] = fir.convert %[[VAL_4]] : (!fir.ptr<!fir.array<*:f32>>) -> i64 @@ -131,8 +131,8 @@ end subroutine ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.ptr<!fir.array<*:f32>>>> {fir.bindc_name = "x"}, ! CHECK-SAME: %[[VAL_1:.*]]: !fir.box<!fir.array<?xf32>> {fir.bindc_name = "y", fir.target}) { ! CHECK: %[[VAL_2:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_2]] {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFtest_associated_2Ex"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<*:f32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<*:f32>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<*:f32>>>>) -! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %[[VAL_2]] {fortran_attrs = #fir.var_attrs<target>, uniq_name = "_QFtest_associated_2Ey"} : (!fir.box<!fir.array<?xf32>>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.box<!fir.array<?xf32>>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_2]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFtest_associated_2Ex"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<*:f32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<*:f32>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<*:f32>>>>) +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %[[VAL_2]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<target>, uniq_name = "_QFtest_associated_2Ey"} : (!fir.box<!fir.array<?xf32>>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.box<!fir.array<?xf32>>) ! CHECK: %[[VAL_5:.*]] = fir.load %[[VAL_3]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<*:f32>>>> ! CHECK: %[[VAL_6:.*]] = fir.convert %[[VAL_5]] : (!fir.box<!fir.ptr<!fir.array<*:f32>>>) -> !fir.box<none> ! CHECK: %[[VAL_7:.*]] = fir.convert %[[VAL_4]]#1 : (!fir.box<!fir.array<?xf32>>) -> !fir.box<none> @@ -148,8 +148,8 @@ end subroutine ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.ptr<!fir.array<*:f32>>>> {fir.bindc_name = "x"}, ! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref<!fir.box<!fir.ptr<!fir.array<*:f32>>>> {fir.bindc_name = "y"}) { ! CHECK: %[[VAL_2:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_2]] {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFtest_associated_3Ex"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<*:f32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<*:f32>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<*:f32>>>>) -! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %[[VAL_2]] {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFtest_associated_3Ey"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<*:f32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<*:f32>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<*:f32>>>>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_2]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFtest_associated_3Ex"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<*:f32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<*:f32>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<*:f32>>>>) +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %[[VAL_2]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFtest_associated_3Ey"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<*:f32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<*:f32>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<*:f32>>>>) ! CHECK: %[[VAL_5:.*]] = fir.load %[[VAL_4]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<*:f32>>>> ! CHECK: %[[VAL_6:.*]] = fir.load %[[VAL_3]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<*:f32>>>> ! CHECK: %[[VAL_7:.*]] = fir.convert %[[VAL_6]] : (!fir.box<!fir.ptr<!fir.array<*:f32>>>) -> !fir.box<none> @@ -165,7 +165,7 @@ end subroutine ! CHECK-LABEL: func.func @_QPtest_len_1( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.box<!fir.array<*:!fir.char<1,?>>> {fir.bindc_name = "x"}) { ! CHECK: %[[VAL_1:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] {uniq_name = "_QFtest_len_1Ex"} : (!fir.box<!fir.array<*:!fir.char<1,?>>>, !fir.dscope) -> (!fir.box<!fir.array<*:!fir.char<1,?>>>, !fir.box<!fir.array<*:!fir.char<1,?>>>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] arg {{[0-9]+}} {uniq_name = "_QFtest_len_1Ex"} : (!fir.box<!fir.array<*:!fir.char<1,?>>>, !fir.dscope) -> (!fir.box<!fir.array<*:!fir.char<1,?>>>, !fir.box<!fir.array<*:!fir.char<1,?>>>) ! CHECK: %[[VAL_3:.*]] = fir.box_elesize %[[VAL_2]]#0 : (!fir.box<!fir.array<*:!fir.char<1,?>>>) -> index ! CHECK: %[[VAL_4:.*]] = fir.convert %[[VAL_3]] : (index) -> i32 ! CHECK: %[[VAL_5:.*]]:3 = hlfir.associate %[[VAL_4]] {adapt.valuebyref} : (i32) -> (!fir.ref<i32>, !fir.ref<i32>, i1) @@ -179,7 +179,7 @@ end subroutine ! CHECK: %[[VAL_1:.*]] = fir.dummy_scope : !fir.dscope ! CHECK: %[[VAL_2:.*]] = fir.load %[[VAL_0]] : !fir.ref<!fir.box<!fir.ptr<!fir.array<*:!fir.char<1,?>>>>> ! CHECK: %[[VAL_3:.*]] = fir.box_elesize %[[VAL_2]] : (!fir.box<!fir.ptr<!fir.array<*:!fir.char<1,?>>>>) -> index -! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_0]] typeparams %[[VAL_3]] dummy_scope %[[VAL_1]] {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFtest_len_2Ex"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<*:!fir.char<1,?>>>>>, index, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<*:!fir.char<1,?>>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<*:!fir.char<1,?>>>>>) +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_0]] typeparams %[[VAL_3]] dummy_scope %[[VAL_1]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFtest_len_2Ex"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<*:!fir.char<1,?>>>>>, index, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<*:!fir.char<1,?>>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<*:!fir.char<1,?>>>>>) ! CHECK: %[[VAL_5:.*]] = fir.convert %[[VAL_3]] : (index) -> i32 ! CHECK: %[[VAL_6:.*]]:3 = hlfir.associate %[[VAL_5]] {adapt.valuebyref} : (i32) -> (!fir.ref<i32>, !fir.ref<i32>, i1) ! CHECK: fir.call @_QPtakes_integer(%[[VAL_6]]#0) fastmath<contract> : (!fir.ref<i32>) -> () @@ -190,7 +190,7 @@ end subroutine ! CHECK-LABEL: func.func @_QPtest_storage_size_1( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.class<!fir.array<*:none>> {fir.bindc_name = "x"}) { ! CHECK: %[[VAL_1:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] {uniq_name = "_QFtest_storage_size_1Ex"} : (!fir.class<!fir.array<*:none>>, !fir.dscope) -> (!fir.class<!fir.array<*:none>>, !fir.class<!fir.array<*:none>>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] arg {{[0-9]+}} {uniq_name = "_QFtest_storage_size_1Ex"} : (!fir.class<!fir.array<*:none>>, !fir.dscope) -> (!fir.class<!fir.array<*:none>>, !fir.class<!fir.array<*:none>>) ! CHECK: %[[VAL_3:.*]] = fir.box_elesize %[[VAL_2]]#0 : (!fir.class<!fir.array<*:none>>) -> i32 ! CHECK: %[[VAL_4:.*]] = arith.constant 8 : i32 ! CHECK: %[[VAL_5:.*]] = arith.muli %[[VAL_3]], %[[VAL_4]] : i32 @@ -203,7 +203,7 @@ end subroutine ! CHECK-LABEL: func.func @_QPtest_storage_size_2( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.class<!fir.ptr<!fir.array<*:none>>>> {fir.bindc_name = "x"}) { ! CHECK: %[[VAL_1:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFtest_storage_size_2Ex"} : (!fir.ref<!fir.class<!fir.ptr<!fir.array<*:none>>>>, !fir.dscope) -> (!fir.ref<!fir.class<!fir.ptr<!fir.array<*:none>>>>, !fir.ref<!fir.class<!fir.ptr<!fir.array<*:none>>>>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFtest_storage_size_2Ex"} : (!fir.ref<!fir.class<!fir.ptr<!fir.array<*:none>>>>, !fir.dscope) -> (!fir.ref<!fir.class<!fir.ptr<!fir.array<*:none>>>>, !fir.ref<!fir.class<!fir.ptr<!fir.array<*:none>>>>) ! CHECK: %[[VAL_3:.*]] = fir.load %[[VAL_2]]#0 : !fir.ref<!fir.class<!fir.ptr<!fir.array<*:none>>>> ! CHECK: %[[VAL_4:.*]] = fir.box_addr %[[VAL_3]] : (!fir.class<!fir.ptr<!fir.array<*:none>>>) -> !fir.ptr<!fir.array<*:none>> ! CHECK: %[[VAL_5:.*]] = fir.convert %[[VAL_4]] : (!fir.ptr<!fir.array<*:none>>) -> i64 @@ -225,7 +225,7 @@ end subroutine ! CHECK-LABEL: func.func @_QPtest_present_1( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.class<!fir.array<*:none>> {fir.bindc_name = "x", fir.optional}) { ! CHECK: %[[VAL_1:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] {fortran_attrs = #fir.var_attrs<optional>, uniq_name = "_QFtest_present_1Ex"} : (!fir.class<!fir.array<*:none>>, !fir.dscope) -> (!fir.class<!fir.array<*:none>>, !fir.class<!fir.array<*:none>>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<optional>, uniq_name = "_QFtest_present_1Ex"} : (!fir.class<!fir.array<*:none>>, !fir.dscope) -> (!fir.class<!fir.array<*:none>>, !fir.class<!fir.array<*:none>>) ! CHECK: %[[VAL_3:.*]] = fir.is_present %[[VAL_2]]#0 : (!fir.class<!fir.array<*:none>>) -> i1 ! CHECK: %[[VAL_4:.*]] = fir.convert %[[VAL_3]] : (i1) -> !fir.logical<4> ! CHECK: %[[VAL_5:.*]]:3 = hlfir.associate %[[VAL_4]] {adapt.valuebyref} : (!fir.logical<4>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>, i1) @@ -237,7 +237,7 @@ end subroutine ! CHECK-LABEL: func.func @_QPtest_present_2( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.class<!fir.ptr<!fir.array<*:none>>>> {fir.bindc_name = "x", fir.optional}) { ! CHECK: %[[VAL_1:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] {fortran_attrs = #fir.var_attrs<optional, pointer>, uniq_name = "_QFtest_present_2Ex"} : (!fir.ref<!fir.class<!fir.ptr<!fir.array<*:none>>>>, !fir.dscope) -> (!fir.ref<!fir.class<!fir.ptr<!fir.array<*:none>>>>, !fir.ref<!fir.class<!fir.ptr<!fir.array<*:none>>>>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<optional, pointer>, uniq_name = "_QFtest_present_2Ex"} : (!fir.ref<!fir.class<!fir.ptr<!fir.array<*:none>>>>, !fir.dscope) -> (!fir.ref<!fir.class<!fir.ptr<!fir.array<*:none>>>>, !fir.ref<!fir.class<!fir.ptr<!fir.array<*:none>>>>) ! CHECK: %[[VAL_3:.*]] = fir.is_present %[[VAL_2]]#0 : (!fir.ref<!fir.class<!fir.ptr<!fir.array<*:none>>>>) -> i1 ! CHECK: %[[VAL_4:.*]] = fir.convert %[[VAL_3]] : (i1) -> !fir.logical<4> ! CHECK: %[[VAL_5:.*]]:3 = hlfir.associate %[[VAL_4]] {adapt.valuebyref} : (!fir.logical<4>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>, i1) @@ -249,7 +249,7 @@ end subroutine ! CHECK-LABEL: func.func @_QPtest_is_contiguous_1( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.class<!fir.array<*:none>> {fir.bindc_name = "x"}) { ! CHECK: %[[VAL_1:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] {uniq_name = "_QFtest_is_contiguous_1Ex"} : (!fir.class<!fir.array<*:none>>, !fir.dscope) -> (!fir.class<!fir.array<*:none>>, !fir.class<!fir.array<*:none>>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] arg {{[0-9]+}} {uniq_name = "_QFtest_is_contiguous_1Ex"} : (!fir.class<!fir.array<*:none>>, !fir.dscope) -> (!fir.class<!fir.array<*:none>>, !fir.class<!fir.array<*:none>>) ! CHECK: %[[VAL_3:.*]] = fir.convert %[[VAL_2]]#0 : (!fir.class<!fir.array<*:none>>) -> !fir.box<none> ! CHECK: %[[VAL_4:.*]] = fir.call @_FortranAIsContiguous(%[[VAL_3]]) fastmath<contract> : (!fir.box<none>) -> i1 ! CHECK: %[[VAL_5:.*]] = fir.convert %[[VAL_4]] : (i1) -> !fir.logical<4> @@ -262,7 +262,7 @@ end subroutine ! CHECK-LABEL: func.func @_QPtest_is_contiguous_2( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.class<!fir.ptr<!fir.array<*:none>>>> {fir.bindc_name = "x"}) { ! CHECK: %[[VAL_1:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFtest_is_contiguous_2Ex"} : (!fir.ref<!fir.class<!fir.ptr<!fir.array<*:none>>>>, !fir.dscope) -> (!fir.ref<!fir.class<!fir.ptr<!fir.array<*:none>>>>, !fir.ref<!fir.class<!fir.ptr<!fir.array<*:none>>>>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFtest_is_contiguous_2Ex"} : (!fir.ref<!fir.class<!fir.ptr<!fir.array<*:none>>>>, !fir.dscope) -> (!fir.ref<!fir.class<!fir.ptr<!fir.array<*:none>>>>, !fir.ref<!fir.class<!fir.ptr<!fir.array<*:none>>>>) ! CHECK: %[[VAL_3:.*]] = fir.load %[[VAL_2]]#0 : !fir.ref<!fir.class<!fir.ptr<!fir.array<*:none>>>> ! CHECK: %[[VAL_4:.*]] = fir.convert %[[VAL_3]] : (!fir.class<!fir.ptr<!fir.array<*:none>>>) -> !fir.box<none> ! CHECK: %[[VAL_5:.*]] = fir.call @_FortranAIsContiguous(%[[VAL_4]]) fastmath<contract> : (!fir.box<none>) -> i1 @@ -277,8 +277,8 @@ end subroutine ! CHECK-SAME: %[[VAL_0:.*]]: !fir.class<!fir.array<*:none>> {fir.bindc_name = "x"}, ! CHECK-SAME: %[[VAL_1:.*]]: !fir.class<!fir.array<*:none>> {fir.bindc_name = "y"}) { ! CHECK: %[[VAL_2:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_2]] {uniq_name = "_QFtest_same_type_as_1Ex"} : (!fir.class<!fir.array<*:none>>, !fir.dscope) -> (!fir.class<!fir.array<*:none>>, !fir.class<!fir.array<*:none>>) -! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %[[VAL_2]] {uniq_name = "_QFtest_same_type_as_1Ey"} : (!fir.class<!fir.array<*:none>>, !fir.dscope) -> (!fir.class<!fir.array<*:none>>, !fir.class<!fir.array<*:none>>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_2]] arg {{[0-9]+}} {uniq_name = "_QFtest_same_type_as_1Ex"} : (!fir.class<!fir.array<*:none>>, !fir.dscope) -> (!fir.class<!fir.array<*:none>>, !fir.class<!fir.array<*:none>>) +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %[[VAL_2]] arg {{[0-9]+}} {uniq_name = "_QFtest_same_type_as_1Ey"} : (!fir.class<!fir.array<*:none>>, !fir.dscope) -> (!fir.class<!fir.array<*:none>>, !fir.class<!fir.array<*:none>>) ! CHECK: %[[VAL_5:.*]] = fir.convert %[[VAL_3]]#0 : (!fir.class<!fir.array<*:none>>) -> !fir.box<none> ! CHECK: %[[VAL_6:.*]] = fir.convert %[[VAL_4]]#0 : (!fir.class<!fir.array<*:none>>) -> !fir.box<none> ! CHECK: %[[VAL_7:.*]] = fir.call @_FortranASameTypeAs(%[[VAL_5]], %[[VAL_6]]) fastmath<contract> : (!fir.box<none>, !fir.box<none>) -> i1 @@ -293,8 +293,8 @@ end subroutine ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.class<!fir.ptr<!fir.array<*:none>>>> {fir.bindc_name = "x"}, ! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref<!fir.class<!fir.ptr<!fir.array<*:none>>>> {fir.bindc_name = "y"}) { ! CHECK: %[[VAL_2:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_2]] {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFtest_same_type_as_2Ex"} : (!fir.ref<!fir.class<!fir.ptr<!fir.array<*:none>>>>, !fir.dscope) -> (!fir.ref<!fir.class<!fir.ptr<!fir.array<*:none>>>>, !fir.ref<!fir.class<!fir.ptr<!fir.array<*:none>>>>) -! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %[[VAL_2]] {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFtest_same_type_as_2Ey"} : (!fir.ref<!fir.class<!fir.ptr<!fir.array<*:none>>>>, !fir.dscope) -> (!fir.ref<!fir.class<!fir.ptr<!fir.array<*:none>>>>, !fir.ref<!fir.class<!fir.ptr<!fir.array<*:none>>>>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_2]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFtest_same_type_as_2Ex"} : (!fir.ref<!fir.class<!fir.ptr<!fir.array<*:none>>>>, !fir.dscope) -> (!fir.ref<!fir.class<!fir.ptr<!fir.array<*:none>>>>, !fir.ref<!fir.class<!fir.ptr<!fir.array<*:none>>>>) +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %[[VAL_2]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFtest_same_type_as_2Ey"} : (!fir.ref<!fir.class<!fir.ptr<!fir.array<*:none>>>>, !fir.dscope) -> (!fir.ref<!fir.class<!fir.ptr<!fir.array<*:none>>>>, !fir.ref<!fir.class<!fir.ptr<!fir.array<*:none>>>>) ! CHECK: %[[VAL_5:.*]] = fir.load %[[VAL_3]]#0 : !fir.ref<!fir.class<!fir.ptr<!fir.array<*:none>>>> ! CHECK: %[[VAL_6:.*]] = fir.load %[[VAL_4]]#0 : !fir.ref<!fir.class<!fir.ptr<!fir.array<*:none>>>> ! CHECK: %[[VAL_7:.*]] = fir.convert %[[VAL_5]] : (!fir.class<!fir.ptr<!fir.array<*:none>>>) -> !fir.box<none> @@ -311,8 +311,8 @@ end subroutine ! CHECK-SAME: %[[VAL_0:.*]]: !fir.class<!fir.array<*:none>> {fir.bindc_name = "x"}, ! CHECK-SAME: %[[VAL_1:.*]]: !fir.class<!fir.array<*:none>> {fir.bindc_name = "y"}) { ! CHECK: %[[VAL_2:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_2]] {uniq_name = "_QFtest_extends_type_of_1Ex"} : (!fir.class<!fir.array<*:none>>, !fir.dscope) -> (!fir.class<!fir.array<*:none>>, !fir.class<!fir.array<*:none>>) -! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %[[VAL_2]] {uniq_name = "_QFtest_extends_type_of_1Ey"} : (!fir.class<!fir.array<*:none>>, !fir.dscope) -> (!fir.class<!fir.array<*:none>>, !fir.class<!fir.array<*:none>>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_2]] arg {{[0-9]+}} {uniq_name = "_QFtest_extends_type_of_1Ex"} : (!fir.class<!fir.array<*:none>>, !fir.dscope) -> (!fir.class<!fir.array<*:none>>, !fir.class<!fir.array<*:none>>) +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %[[VAL_2]] arg {{[0-9]+}} {uniq_name = "_QFtest_extends_type_of_1Ey"} : (!fir.class<!fir.array<*:none>>, !fir.dscope) -> (!fir.class<!fir.array<*:none>>, !fir.class<!fir.array<*:none>>) ! CHECK: %[[VAL_5:.*]] = fir.convert %[[VAL_3]]#0 : (!fir.class<!fir.array<*:none>>) -> !fir.box<none> ! CHECK: %[[VAL_6:.*]] = fir.convert %[[VAL_4]]#0 : (!fir.class<!fir.array<*:none>>) -> !fir.box<none> ! CHECK: %[[VAL_7:.*]] = fir.call @_FortranAExtendsTypeOf(%[[VAL_5]], %[[VAL_6]]) fastmath<contract> : (!fir.box<none>, !fir.box<none>) -> i1 @@ -327,8 +327,8 @@ end subroutine ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.class<!fir.ptr<!fir.array<*:none>>>> {fir.bindc_name = "x"}, ! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref<!fir.class<!fir.ptr<!fir.array<*:none>>>> {fir.bindc_name = "y"}) { ! CHECK: %[[VAL_2:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_2]] {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFtest_extends_type_of_2Ex"} : (!fir.ref<!fir.class<!fir.ptr<!fir.array<*:none>>>>, !fir.dscope) -> (!fir.ref<!fir.class<!fir.ptr<!fir.array<*:none>>>>, !fir.ref<!fir.class<!fir.ptr<!fir.array<*:none>>>>) -! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %[[VAL_2]] {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFtest_extends_type_of_2Ey"} : (!fir.ref<!fir.class<!fir.ptr<!fir.array<*:none>>>>, !fir.dscope) -> (!fir.ref<!fir.class<!fir.ptr<!fir.array<*:none>>>>, !fir.ref<!fir.class<!fir.ptr<!fir.array<*:none>>>>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_2]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFtest_extends_type_of_2Ex"} : (!fir.ref<!fir.class<!fir.ptr<!fir.array<*:none>>>>, !fir.dscope) -> (!fir.ref<!fir.class<!fir.ptr<!fir.array<*:none>>>>, !fir.ref<!fir.class<!fir.ptr<!fir.array<*:none>>>>) +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %[[VAL_2]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFtest_extends_type_of_2Ey"} : (!fir.ref<!fir.class<!fir.ptr<!fir.array<*:none>>>>, !fir.dscope) -> (!fir.ref<!fir.class<!fir.ptr<!fir.array<*:none>>>>, !fir.ref<!fir.class<!fir.ptr<!fir.array<*:none>>>>) ! CHECK: %[[VAL_5:.*]] = fir.load %[[VAL_3]]#0 : !fir.ref<!fir.class<!fir.ptr<!fir.array<*:none>>>> ! CHECK: %[[VAL_6:.*]] = fir.load %[[VAL_4]]#0 : !fir.ref<!fir.class<!fir.ptr<!fir.array<*:none>>>> ! CHECK: %[[VAL_7:.*]] = fir.convert %[[VAL_5]] : (!fir.class<!fir.ptr<!fir.array<*:none>>>) -> !fir.box<none> @@ -344,7 +344,7 @@ end subroutine ! CHECK-LABEL: func.func @_QPc_loc_1( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.box<!fir.array<*:f32>> {fir.bindc_name = "x", fir.target}) { ! CHECK: %[[VAL_1:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] {fortran_attrs = #fir.var_attrs<target>, uniq_name = "_QFc_loc_1Ex"} : (!fir.box<!fir.array<*:f32>>, !fir.dscope) -> (!fir.box<!fir.array<*:f32>>, !fir.box<!fir.array<*:f32>>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<target>, uniq_name = "_QFc_loc_1Ex"} : (!fir.box<!fir.array<*:f32>>, !fir.dscope) -> (!fir.box<!fir.array<*:f32>>, !fir.box<!fir.array<*:f32>>) ! CHECK: %[[VAL_3:.*]] = fir.alloca !fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}> ! CHECK: %[[VAL_5:.*]] = fir.coordinate_of %[[VAL_3]], __address : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>) -> !fir.ref<i64> ! CHECK: %[[VAL_6:.*]] = fir.box_addr %[[VAL_2]]#0 : (!fir.box<!fir.array<*:f32>>) -> !fir.ref<!fir.array<*:f32>> @@ -363,7 +363,7 @@ end subroutine ! CHECK-LABEL: func.func @_QPc_loc_2( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.ptr<!fir.array<*:f32>>>> {fir.bindc_name = "x"}) { ! CHECK: %[[VAL_1:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFc_loc_2Ex"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<*:f32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<*:f32>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<*:f32>>>>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFc_loc_2Ex"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<*:f32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<*:f32>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<*:f32>>>>) ! CHECK: %[[VAL_3:.*]] = fir.load %[[VAL_2]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<*:f32>>>> ! CHECK: %[[VAL_4:.*]] = fir.alloca !fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}> ! CHECK: %[[VAL_6:.*]] = fir.coordinate_of %[[VAL_4]], __address : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>) -> !fir.ref<i64> diff --git a/flang/test/Lower/HLFIR/assumed-rank-internal-proc.f90 b/flang/test/Lower/HLFIR/assumed-rank-internal-proc.f90 index e46d21d..cd01ea5 100644 --- a/flang/test/Lower/HLFIR/assumed-rank-internal-proc.f90 +++ b/flang/test/Lower/HLFIR/assumed-rank-internal-proc.f90 @@ -17,7 +17,7 @@ end subroutine ! CHECK-LABEL: func.func @_QPtest_assumed_rank( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.box<!fir.array<*:f32>> {fir.bindc_name = "x"}) { ! CHECK: %[[VAL_1:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] {fortran_attrs = #fir.var_attrs<internal_assoc>, uniq_name = "_QFtest_assumed_rankEx"} : (!fir.box<!fir.array<*:f32>>, !fir.dscope) -> (!fir.box<!fir.array<*:f32>>, !fir.box<!fir.array<*:f32>>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<internal_assoc>, uniq_name = "_QFtest_assumed_rankEx"} : (!fir.box<!fir.array<*:f32>>, !fir.dscope) -> (!fir.box<!fir.array<*:f32>>, !fir.box<!fir.array<*:f32>>) ! CHECK: %[[VAL_3:.*]] = fir.alloca tuple<!fir.box<!fir.array<*:f32>>> ! CHECK: %[[VAL_4:.*]] = arith.constant 0 : i32 ! CHECK: %[[VAL_5:.*]] = fir.coordinate_of %[[VAL_3]], %[[VAL_4]] : (!fir.ref<tuple<!fir.box<!fir.array<*:f32>>>>, i32) -> !fir.ref<!fir.box<!fir.array<*:f32>>> @@ -55,7 +55,7 @@ end subroutine ! CHECK-LABEL: func.func @_QPtest_assumed_rank_optional( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.class<!fir.array<*:none>> {fir.bindc_name = "x", fir.optional}) { ! CHECK: %[[VAL_1:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] {fortran_attrs = #fir.var_attrs<optional, internal_assoc>, uniq_name = "_QFtest_assumed_rank_optionalEx"} : (!fir.class<!fir.array<*:none>>, !fir.dscope) -> (!fir.class<!fir.array<*:none>>, !fir.class<!fir.array<*:none>>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<optional, internal_assoc>, uniq_name = "_QFtest_assumed_rank_optionalEx"} : (!fir.class<!fir.array<*:none>>, !fir.dscope) -> (!fir.class<!fir.array<*:none>>, !fir.class<!fir.array<*:none>>) ! CHECK: %[[VAL_3:.*]] = fir.alloca tuple<!fir.class<!fir.array<*:none>>> ! CHECK: %[[VAL_4:.*]] = arith.constant 0 : i32 ! CHECK: %[[VAL_5:.*]] = fir.coordinate_of %[[VAL_3]], %[[VAL_4]] : (!fir.ref<tuple<!fir.class<!fir.array<*:none>>>>, i32) -> !fir.ref<!fir.class<!fir.array<*:none>>> @@ -107,7 +107,7 @@ end subroutine ! CHECK-LABEL: func.func @_QPtest_assumed_rank_ptr( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.ptr<!fir.array<*:f32>>>> {fir.bindc_name = "x"}) { ! CHECK: %[[VAL_1:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] {fortran_attrs = #fir.var_attrs<pointer, internal_assoc>, uniq_name = "_QFtest_assumed_rank_ptrEx"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<*:f32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<*:f32>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<*:f32>>>>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer, internal_assoc>, uniq_name = "_QFtest_assumed_rank_ptrEx"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<*:f32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<*:f32>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<*:f32>>>>) ! CHECK: %[[VAL_3:.*]] = fir.alloca tuple<!fir.ref<!fir.box<!fir.ptr<!fir.array<*:f32>>>>> ! CHECK: %[[VAL_4:.*]] = arith.constant 0 : i32 ! CHECK: %[[VAL_5:.*]] = fir.coordinate_of %[[VAL_3]], %[[VAL_4]] : (!fir.ref<tuple<!fir.ref<!fir.box<!fir.ptr<!fir.array<*:f32>>>>>>, i32) -> !fir.llvm_ptr<!fir.ref<!fir.box<!fir.ptr<!fir.array<*:f32>>>>> diff --git a/flang/test/Lower/HLFIR/binary-ops.f90 b/flang/test/Lower/HLFIR/binary-ops.f90 index b7695a7..f4e1643 100644 --- a/flang/test/Lower/HLFIR/binary-ops.f90 +++ b/flang/test/Lower/HLFIR/binary-ops.f90 @@ -281,8 +281,8 @@ subroutine cmp_char(l, x, y) l = x .eq. y end subroutine ! CHECK-LABEL: func.func @_QPcmp_char( -! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %{{.*}} typeparams %[[VAL_4:.*]]#1 dummy_scope %{{[0-9]+}} {uniq_name = "_QFcmp_charEx"} : (!fir.ref<!fir.char<1,?>>, index, !fir.dscope) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>) -! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %{{.*}} typeparams %[[VAL_6:.*]]#1 dummy_scope %{{[0-9]+}} {uniq_name = "_QFcmp_charEy"} : (!fir.ref<!fir.char<1,?>>, index, !fir.dscope) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>) +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %{{.*}} typeparams %[[VAL_4:.*]]#1 dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFcmp_charEx"} : (!fir.ref<!fir.char<1,?>>, index, !fir.dscope) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>) +! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %{{.*}} typeparams %[[VAL_6:.*]]#1 dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFcmp_charEy"} : (!fir.ref<!fir.char<1,?>>, index, !fir.dscope) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>) ! CHECK: %[[VAL_8:.*]] = hlfir.cmpchar eq %[[VAL_5]]#0 %[[VAL_7]]#0 : (!fir.boxchar<1>, !fir.boxchar<1>) -> i1 ! CHECK: %[[VAL_9:.*]] = fir.convert %[[VAL_8]] : (i1) -> !fir.logical<4> diff --git a/flang/test/Lower/HLFIR/bindc-value-derived.f90 b/flang/test/Lower/HLFIR/bindc-value-derived.f90 index e161884..3a9fb78 100644 --- a/flang/test/Lower/HLFIR/bindc-value-derived.f90 +++ b/flang/test/Lower/HLFIR/bindc-value-derived.f90 @@ -17,7 +17,7 @@ contains ! CHECK-SAME: %[[VAL_0:.*]]: !fir.type<_QMbindc_byvalTt{{[<]?}}{i:i32}{{[>]?}}> ! CHECK: %[[VAL_1:.*]] = fir.alloca !fir.type<_QMbindc_byvalTt{{[<]?}}{i:i32}{{[>]?}}> ! CHECK: fir.store %[[VAL_0]] to %[[VAL_1]] : !fir.ref<!fir.type<_QMbindc_byvalTt{{[<]?}}{i:i32}{{[>]?}}>> -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %{{[0-9]}} {fortran_attrs = #fir.var_attrs<value>, uniq_name = "_QMbindc_byvalFtestEx"} : (!fir.ref<!fir.type<_QMbindc_byvalTt{{[<]?}}{i:i32}{{[>]?}}>>, !fir.dscope) -> (!fir.ref<!fir.type<_QMbindc_byvalTt{{[<]?}}{i:i32}{{[>]?}}>>, !fir.ref<!fir.type<_QMbindc_byvalTt{{[<]?}}{i:i32}{{[>]?}}>>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %{{[0-9]}} {{.*}} {fortran_attrs = #fir.var_attrs<value>, uniq_name = "_QMbindc_byvalFtestEx"} : (!fir.ref<!fir.type<_QMbindc_byvalTt{{[<]?}}{i:i32}{{[>]?}}>>, !fir.dscope) -> (!fir.ref<!fir.type<_QMbindc_byvalTt{{[<]?}}{i:i32}{{[>]?}}>>, !fir.ref<!fir.type<_QMbindc_byvalTt{{[<]?}}{i:i32}{{[>]?}}>>) ! CHECK: %[[VAL_3:.*]] = hlfir.designate %[[VAL_2]]#0{"i"} : (!fir.ref<!fir.type<_QMbindc_byvalTt{{[<]?}}{i:i32}{{[>]?}}>>) -> !fir.ref<i32> ! CHECK: fir.call @_QPuse_it(%[[VAL_3]]) fastmath<contract> : (!fir.ref<i32>) -> () ! CHECK: return @@ -29,7 +29,7 @@ contains end subroutine ! CHECK-LABEL: func.func @_QMbindc_byvalPcall_it( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.type<_QMbindc_byvalTt{{[<]?}}{i:i32}{{[>]?}}>> -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]}} {uniq_name = "_QMbindc_byvalFcall_itEx"} : (!fir.ref<!fir.type<_QMbindc_byvalTt{{[<]?}}{i:i32}{{[>]?}}>>, !fir.dscope) -> (!fir.ref<!fir.type<_QMbindc_byvalTt{{[<]?}}{i:i32}{{[>]?}}>>, !fir.ref<!fir.type<_QMbindc_byvalTt{{[<]?}}{i:i32}{{[>]?}}>>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]}} {{.*}} {uniq_name = "_QMbindc_byvalFcall_itEx"} : (!fir.ref<!fir.type<_QMbindc_byvalTt{{[<]?}}{i:i32}{{[>]?}}>>, !fir.dscope) -> (!fir.ref<!fir.type<_QMbindc_byvalTt{{[<]?}}{i:i32}{{[>]?}}>>, !fir.ref<!fir.type<_QMbindc_byvalTt{{[<]?}}{i:i32}{{[>]?}}>>) ! CHECK: %[[VAL_2:.*]] = fir.load %[[VAL_1]]#0 : !fir.ref<!fir.type<_QMbindc_byvalTt{{[<]?}}{i:i32}{{[>]?}}>> ! CHECK: fir.call @test(%[[VAL_2]]) proc_attrs<bind_c> fastmath<contract> : (!fir.type<_QMbindc_byvalTt{{[<]?}}{i:i32}{{[>]?}}>) -> () ! CHECK: return diff --git a/flang/test/Lower/HLFIR/call-sequence-associated-descriptors.f90 b/flang/test/Lower/HLFIR/call-sequence-associated-descriptors.f90 index 2cb9d7c..aa3c842 100644 --- a/flang/test/Lower/HLFIR/call-sequence-associated-descriptors.f90 +++ b/flang/test/Lower/HLFIR/call-sequence-associated-descriptors.f90 @@ -23,7 +23,7 @@ contains call takes_char(x, 100) end subroutine ! CHECK-LABEL: func.func @_QMbindc_seq_assocPtest_char_1( -! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_2:.*]](%[[VAL_5:.*]]) typeparams %[[VAL_1:.*]]#1 dummy_scope %{{[0-9]+}} {uniq_name = "_QMbindc_seq_assocFtest_char_1Ex"} : (!fir.ref<!fir.array<10x20x!fir.char<1,?>>>, !fir.shape<2>, index, !fir.dscope) -> (!fir.box<!fir.array<10x20x!fir.char<1,?>>>, !fir.ref<!fir.array<10x20x!fir.char<1,?>>>) +! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_2:.*]](%[[VAL_5:.*]]) typeparams %[[VAL_1:.*]]#1 dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QMbindc_seq_assocFtest_char_1Ex"} : (!fir.ref<!fir.array<10x20x!fir.char<1,?>>>, !fir.shape<2>, index, !fir.dscope) -> (!fir.box<!fir.array<10x20x!fir.char<1,?>>>, !fir.ref<!fir.array<10x20x!fir.char<1,?>>>) ! CHECK: %[[VAL_7:.*]] = arith.constant 100 : i32 ! CHECK: %[[VAL_8:.*]] = arith.constant 0 : index ! CHECK: %[[VAL_9:.*]] = fir.shift %[[VAL_8]], %[[VAL_8]] : (index, index) -> !fir.shift<2> @@ -56,7 +56,7 @@ contains call takes_char(x, 100) end subroutine ! CHECK-LABEL: func.func @_QMbindc_seq_assocPtest_char_copy_in_copy_out( -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0:.*]] dummy_scope %{{[0-9]+}} {uniq_name = "_QMbindc_seq_assocFtest_char_copy_in_copy_outEx"} : (!fir.box<!fir.array<?x?x!fir.char<1,?>>>, !fir.dscope) -> (!fir.box<!fir.array<?x?x!fir.char<1,?>>>, !fir.box<!fir.array<?x?x!fir.char<1,?>>>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0:.*]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QMbindc_seq_assocFtest_char_copy_in_copy_outEx"} : (!fir.box<!fir.array<?x?x!fir.char<1,?>>>, !fir.dscope) -> (!fir.box<!fir.array<?x?x!fir.char<1,?>>>, !fir.box<!fir.array<?x?x!fir.char<1,?>>>) ! CHECK: %[[VAL_2:.*]] = arith.constant 100 : i32 ! CHECK: %[[VAL_3:.*]]:2 = hlfir.copy_in %[[VAL_1]]#0 to %[[TMP_BOX:.*]] : (!fir.box<!fir.array<?x?x!fir.char<1,?>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?x?x!fir.char<1,?>>>>>) -> (!fir.box<!fir.array<?x?x!fir.char<1,?>>>, i1) ! CHECK: %[[VAL_4:.*]] = arith.constant 0 : index @@ -91,7 +91,7 @@ contains call takes_char_assumed_size(x) end subroutine ! CHECK-LABEL: func.func @_QMbindc_seq_assocPtest_char_assumed_size( -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0:.*]] dummy_scope %{{[0-9]+}} {uniq_name = "_QMbindc_seq_assocFtest_char_assumed_sizeEx"} : (!fir.box<!fir.array<?x?x!fir.char<1,?>>>, !fir.dscope) -> (!fir.box<!fir.array<?x?x!fir.char<1,?>>>, !fir.box<!fir.array<?x?x!fir.char<1,?>>>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0:.*]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QMbindc_seq_assocFtest_char_assumed_sizeEx"} : (!fir.box<!fir.array<?x?x!fir.char<1,?>>>, !fir.dscope) -> (!fir.box<!fir.array<?x?x!fir.char<1,?>>>, !fir.box<!fir.array<?x?x!fir.char<1,?>>>) ! CHECK: %[[VAL_2:.*]]:2 = hlfir.copy_in %[[VAL_1]]#0 to %[[TMP_BOX:.*]] : (!fir.box<!fir.array<?x?x!fir.char<1,?>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?x?x!fir.char<1,?>>>>>) -> (!fir.box<!fir.array<?x?x!fir.char<1,?>>>, i1) ! CHECK: %[[VAL_3:.*]] = arith.constant 0 : index ! CHECK: %[[VAL_4:.*]] = fir.shift %[[VAL_3]], %[[VAL_3]] : (index, index) -> !fir.shift<2> @@ -123,7 +123,7 @@ contains call takes_optional_char(x, 100) end subroutine ! CHECK-LABEL: func.func @_QMbindc_seq_assocPtest_optional_char( -! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_2:.*]](%[[VAL_5:.*]]) typeparams %[[VAL_1:.*]]#1 dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<optional>, uniq_name = "_QMbindc_seq_assocFtest_optional_charEx"} : (!fir.ref<!fir.array<10x20x!fir.char<1,?>>>, !fir.shape<2>, index, !fir.dscope) -> (!fir.box<!fir.array<10x20x!fir.char<1,?>>>, !fir.ref<!fir.array<10x20x!fir.char<1,?>>>) +! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_2:.*]](%[[VAL_5:.*]]) typeparams %[[VAL_1:.*]]#1 dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<optional>, uniq_name = "_QMbindc_seq_assocFtest_optional_charEx"} : (!fir.ref<!fir.array<10x20x!fir.char<1,?>>>, !fir.shape<2>, index, !fir.dscope) -> (!fir.box<!fir.array<10x20x!fir.char<1,?>>>, !fir.ref<!fir.array<10x20x!fir.char<1,?>>>) ! CHECK: %[[VAL_7:.*]] = fir.is_present %[[VAL_6]]#0 : (!fir.box<!fir.array<10x20x!fir.char<1,?>>>) -> i1 ! CHECK: %[[VAL_8:.*]] = arith.constant 100 : i32 ! CHECK: %[[VAL_9:.*]] = fir.if %[[VAL_7]] -> (!fir.box<!fir.array<10x20x!fir.char<1,?>>>) { @@ -186,7 +186,7 @@ contains end subroutine ! CHECK-LABEL: func.func @_QMpoly_seq_assocPtest_poly_1( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.class<!fir.array<10x20xnone>> {fir.bindc_name = "x"}) { -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0:.*]] dummy_scope %{{[0-9]+}} {uniq_name = "_QMpoly_seq_assocFtest_poly_1Ex"} : (!fir.class<!fir.array<10x20xnone>>, !fir.dscope) -> (!fir.class<!fir.array<10x20xnone>>, !fir.class<!fir.array<10x20xnone>>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0:.*]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QMpoly_seq_assocFtest_poly_1Ex"} : (!fir.class<!fir.array<10x20xnone>>, !fir.dscope) -> (!fir.class<!fir.array<10x20xnone>>, !fir.class<!fir.array<10x20xnone>>) ! CHECK: %[[VAL_2:.*]] = arith.constant 100 : i32 ! CHECK: %[[VAL_3:.*]]:3 = hlfir.associate %[[VAL_2]] {adapt.valuebyref} : (i32) -> (!fir.ref<i32>, !fir.ref<i32>, i1) ! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_3]]#0 {uniq_name = "_QMpoly_seq_assocFtakes_polyEn"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) @@ -214,7 +214,7 @@ contains call takes_poly(x, 100) end subroutine ! CHECK-LABEL: func.func @_QMpoly_seq_assocPtest_poly_copy_in_copy_out( -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0:.*]] dummy_scope %{{[0-9]+}} {uniq_name = "_QMpoly_seq_assocFtest_poly_copy_in_copy_outEx"} : (!fir.class<!fir.array<?x?xnone>>, !fir.dscope) -> (!fir.class<!fir.array<?x?xnone>>, !fir.class<!fir.array<?x?xnone>>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0:.*]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QMpoly_seq_assocFtest_poly_copy_in_copy_outEx"} : (!fir.class<!fir.array<?x?xnone>>, !fir.dscope) -> (!fir.class<!fir.array<?x?xnone>>, !fir.class<!fir.array<?x?xnone>>) ! CHECK: %[[VAL_2:.*]] = arith.constant 100 : i32 ! CHECK: %[[VAL_3:.*]]:2 = hlfir.copy_in %[[VAL_1]]#0 to %[[TMP_BOX:.*]] : (!fir.class<!fir.array<?x?xnone>>, !fir.ref<!fir.class<!fir.heap<!fir.array<?x?xnone>>>>) -> (!fir.class<!fir.array<?x?xnone>>, i1) ! CHECK: %[[VAL_4:.*]]:3 = hlfir.associate %[[VAL_2]] {adapt.valuebyref} : (i32) -> (!fir.ref<i32>, !fir.ref<i32>, i1) @@ -244,7 +244,7 @@ contains call takes_poly_assumed_size(x) end subroutine ! CHECK-LABEL: func.func @_QMpoly_seq_assocPtest_poly_assumed_size( -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0:.*]] dummy_scope %{{[0-9]+}} {uniq_name = "_QMpoly_seq_assocFtest_poly_assumed_sizeEx"} : (!fir.class<!fir.array<?x?xnone>>, !fir.dscope) -> (!fir.class<!fir.array<?x?xnone>>, !fir.class<!fir.array<?x?xnone>>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0:.*]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QMpoly_seq_assocFtest_poly_assumed_sizeEx"} : (!fir.class<!fir.array<?x?xnone>>, !fir.dscope) -> (!fir.class<!fir.array<?x?xnone>>, !fir.class<!fir.array<?x?xnone>>) ! CHECK: %[[VAL_2:.*]]:2 = hlfir.copy_in %[[VAL_1]]#0 to %[[TMP_BOX:.*]] : (!fir.class<!fir.array<?x?xnone>>, !fir.ref<!fir.class<!fir.heap<!fir.array<?x?xnone>>>>) -> (!fir.class<!fir.array<?x?xnone>>, i1) ! CHECK: %[[VAL_3:.*]] = arith.constant 10 : i64 ! CHECK: %[[VAL_4:.*]] = arith.constant 1 : i64 @@ -271,7 +271,7 @@ contains call takes_optional_poly(x, 100) end subroutine ! CHECK-LABEL: func.func @_QMpoly_seq_assocPtest_optional_poly( -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0:.*]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<optional>, uniq_name = "_QMpoly_seq_assocFtest_optional_polyEx"} : (!fir.class<!fir.array<10x20xnone>>, !fir.dscope) -> (!fir.class<!fir.array<10x20xnone>>, !fir.class<!fir.array<10x20xnone>>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0:.*]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<optional>, uniq_name = "_QMpoly_seq_assocFtest_optional_polyEx"} : (!fir.class<!fir.array<10x20xnone>>, !fir.dscope) -> (!fir.class<!fir.array<10x20xnone>>, !fir.class<!fir.array<10x20xnone>>) ! CHECK: %[[VAL_2:.*]] = fir.is_present %[[VAL_1]]#0 : (!fir.class<!fir.array<10x20xnone>>) -> i1 ! CHECK: %[[VAL_3:.*]] = arith.constant 100 : i32 ! CHECK: %[[VAL_4:.*]] = fir.if %[[VAL_2]] -> (!fir.class<!fir.array<10x20xnone>>) { diff --git a/flang/test/Lower/HLFIR/calls-array-results.f90 b/flang/test/Lower/HLFIR/calls-array-results.f90 index 425969e..6bc8090 100644 --- a/flang/test/Lower/HLFIR/calls-array-results.f90 +++ b/flang/test/Lower/HLFIR/calls-array-results.f90 @@ -72,7 +72,7 @@ end subroutine ! CHECK-LABEL: func.func @_QParg_test( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<i64> {fir.bindc_name = "n"}) { ! CHECK: %[[VAL_1:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] {uniq_name = "_QFarg_testEn"} : (!fir.ref<i64>, !fir.dscope) -> (!fir.ref<i64>, !fir.ref<i64>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] arg {{[0-9]+}} {uniq_name = "_QFarg_testEn"} : (!fir.ref<i64>, !fir.dscope) -> (!fir.ref<i64>, !fir.ref<i64>) ! CHECK: %[[VAL_3:.*]] = fir.load %[[VAL_2]]#0 : !fir.ref<i64> ! CHECK: %[[VAL_4:.*]] = fir.convert %[[VAL_3]] : (i64) -> index ! CHECK: %[[VAL_5:.*]] = arith.constant 0 : index @@ -106,10 +106,10 @@ end subroutine ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.array<10xf32>> {fir.bindc_name = "x"}, ! CHECK-SAME: %[[VAL_1:.*]]: !fir.class<!fir.type<_QMtype_defsTt>> {fir.bindc_name = "a"}) { ! CHECK: %[[VAL_2:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %[[VAL_2]] {uniq_name = "_QFdispatch_testEa"} : (!fir.class<!fir.type<_QMtype_defsTt>>, !fir.dscope) -> (!fir.class<!fir.type<_QMtype_defsTt>>, !fir.class<!fir.type<_QMtype_defsTt>>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %[[VAL_2]] arg {{[0-9]+}} {uniq_name = "_QFdispatch_testEa"} : (!fir.class<!fir.type<_QMtype_defsTt>>, !fir.dscope) -> (!fir.class<!fir.type<_QMtype_defsTt>>, !fir.class<!fir.type<_QMtype_defsTt>>) ! CHECK: %[[VAL_4:.*]] = arith.constant 10 : index ! CHECK: %[[VAL_5:.*]] = fir.shape %[[VAL_4]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_5]]) dummy_scope %[[VAL_2]] {uniq_name = "_QFdispatch_testEx"} : (!fir.ref<!fir.array<10xf32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<10xf32>>, !fir.ref<!fir.array<10xf32>>) +! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_5]]) dummy_scope %[[VAL_2]] arg {{[0-9]+}} {uniq_name = "_QFdispatch_testEx"} : (!fir.ref<!fir.array<10xf32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<10xf32>>, !fir.ref<!fir.array<10xf32>>) ! CHECK: %[[VAL_7:.*]] = arith.constant 10 : i64 ! CHECK: %[[VAL_8:.*]] = arith.constant 1 : i64 ! CHECK: %[[VAL_9:.*]] = arith.subi %[[VAL_7]], %[[VAL_8]] : i64 diff --git a/flang/test/Lower/HLFIR/calls-assumed-shape.f90 b/flang/test/Lower/HLFIR/calls-assumed-shape.f90 index 102f315..9bf150d 100644 --- a/flang/test/Lower/HLFIR/calls-assumed-shape.f90 +++ b/flang/test/Lower/HLFIR/calls-assumed-shape.f90 @@ -12,7 +12,7 @@ subroutine test_assumed_to_assumed(x) call takes_assumed(x) end subroutine ! CHECK-LABEL: func.func @_QPtest_assumed_to_assumed( -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0:[a-z0-9]*]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFtest_assumed_to_assumedEx"} : (!fir.box<!fir.array<?xf32>>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.box<!fir.array<?xf32>>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0:[a-z0-9]*]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFtest_assumed_to_assumedEx"} : (!fir.box<!fir.array<?xf32>>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.box<!fir.array<?xf32>>) ! CHECK: fir.call @_QPtakes_assumed(%[[VAL_1]]#0) {{.*}} : (!fir.box<!fir.array<?xf32>>) -> () subroutine test_ptr_to_assumed(p) @@ -25,7 +25,7 @@ subroutine test_ptr_to_assumed(p) call takes_assumed(p) end subroutine ! CHECK-LABEL: func.func @_QPtest_ptr_to_assumed( -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0:[a-z0-9]*]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFtest_ptr_to_assumedEp"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0:[a-z0-9]*]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFtest_ptr_to_assumedEp"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>) ! CHECK: %[[VAL_2:.*]] = fir.load %[[VAL_1]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>> ! CHECK: %[[VAL_3:.*]] = fir.rebox %[[VAL_2]] : (!fir.box<!fir.ptr<!fir.array<?xf32>>>) -> !fir.box<!fir.array<?xf32>> ! CHECK: fir.call @_QPtakes_assumed(%[[VAL_3]]) {{.*}} : (!fir.box<!fir.array<?xf32>>) -> () @@ -40,7 +40,7 @@ subroutine test_ptr_to_contiguous_assumed(p) call takes_contiguous_assumed(p) end subroutine ! CHECK-LABEL: func.func @_QPtest_ptr_to_contiguous_assumed( -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0:[a-z0-9]*]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFtest_ptr_to_contiguous_assumedEp"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0:[a-z0-9]*]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFtest_ptr_to_contiguous_assumedEp"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>) ! CHECK: %[[VAL_2:.*]] = fir.load %[[VAL_1]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>> ! CHECK: %[[VAL_3:.*]]:2 = hlfir.copy_in %[[VAL_2]] to %[[TMP_BOX:.*]] : (!fir.box<!fir.ptr<!fir.array<?xf32>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>) -> (!fir.box<!fir.ptr<!fir.array<?xf32>>>, i1) ! CHECK: %[[VAL_4:.*]] = fir.rebox %[[VAL_3]]#0 : (!fir.box<!fir.ptr<!fir.array<?xf32>>>) -> !fir.box<!fir.array<?xf32>> @@ -57,7 +57,7 @@ subroutine test_ptr_to_contiguous_assumed_classstar(p) call takes_contiguous_assumed_classstar(p) end subroutine ! CHECK-LABEL: func.func @_QPtest_ptr_to_contiguous_assumed_classstar( -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0:[a-z0-9]*]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFtest_ptr_to_contiguous_assumed_classstarEp"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0:[a-z0-9]*]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFtest_ptr_to_contiguous_assumed_classstarEp"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>) ! CHECK: %[[VAL_2:.*]] = fir.load %[[VAL_1]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>> ! CHECK: %[[VAL_3:.*]]:2 = hlfir.copy_in %[[VAL_2]] to %[[TMP_BOX:.*]] : (!fir.box<!fir.ptr<!fir.array<?xf32>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>) -> (!fir.box<!fir.ptr<!fir.array<?xf32>>>, i1) ! CHECK: %[[VAL_4:.*]] = fir.rebox %[[VAL_3]]#0 : (!fir.box<!fir.ptr<!fir.array<?xf32>>>) -> !fir.class<!fir.array<?xnone>> @@ -74,7 +74,7 @@ subroutine test_ptr_to_assumed_typestar(p) call takes_assumed_typestar(p) end subroutine ! CHECK-LABEL: func.func @_QPtest_ptr_to_assumed_typestar( -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0:[a-z0-9]*]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFtest_ptr_to_assumed_typestarEp"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0:[a-z0-9]*]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFtest_ptr_to_assumed_typestarEp"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>) ! CHECK: %[[VAL_2:.*]] = fir.load %[[VAL_1]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>> ! CHECK: %[[VAL_3:.*]] = fir.rebox %[[VAL_2]] : (!fir.box<!fir.ptr<!fir.array<?xf32>>>) -> !fir.box<!fir.array<?xnone>> ! CHECK: fir.call @_QPtakes_assumed_typestar(%[[VAL_3]]) {{.*}} : (!fir.box<!fir.array<?xnone>>) -> () @@ -94,7 +94,7 @@ end subroutine ! CHECK: %[[VAL_2:.*]] = arith.constant 10 : index ! CHECK: %[[VAL_4:.*]] = arith.constant 20 : index ! CHECK: %[[VAL_5:.*]] = fir.shape %[[VAL_4]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_3]](%[[VAL_5:[a-z0-9]*]]) typeparams %[[VAL_2:[a-z0-9]*]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFtest_explicit_char_to_boxEe"} : (!fir.ref<!fir.array<20x!fir.char<1,10>>>, !fir.shape<1>, index, !fir.dscope) -> (!fir.ref<!fir.array<20x!fir.char<1,10>>>, !fir.ref<!fir.array<20x!fir.char<1,10>>>) +! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_3]](%[[VAL_5:[a-z0-9]*]]) typeparams %[[VAL_2:[a-z0-9]*]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFtest_explicit_char_to_boxEe"} : (!fir.ref<!fir.array<20x!fir.char<1,10>>>, !fir.shape<1>, index, !fir.dscope) -> (!fir.ref<!fir.array<20x!fir.char<1,10>>>, !fir.ref<!fir.array<20x!fir.char<1,10>>>) ! CHECK: %[[VAL_7:.*]] = fir.embox %[[VAL_6]]#0(%[[VAL_5]]) : (!fir.ref<!fir.array<20x!fir.char<1,10>>>, !fir.shape<1>) -> !fir.box<!fir.array<20x!fir.char<1,10>>> ! CHECK: %[[VAL_8:.*]] = fir.convert %[[VAL_7]] : (!fir.box<!fir.array<20x!fir.char<1,10>>>) -> !fir.box<!fir.array<?x!fir.char<1,?>>> ! CHECK: fir.call @_QPtakes_assumed_character(%[[VAL_8]]) {{.*}} : (!fir.box<!fir.array<?x!fir.char<1,?>>>) -> () @@ -109,7 +109,7 @@ subroutine test_explicit_by_val(x) call takes_explicit_by_value(x) end subroutine ! CHECK-LABEL: func.func @_QPtest_explicit_by_val( -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0:[a-z0-9]*]](%[[VAL_2:[a-z0-9]*]]) dummy_scope %{{[0-9]+}} {uniq_name = "_QFtest_explicit_by_valEx"} : (!fir.ref<!fir.array<10xf32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<10xf32>>, !fir.ref<!fir.array<10xf32>>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0:[a-z0-9]*]](%[[VAL_2:[a-z0-9]*]]) dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFtest_explicit_by_valEx"} : (!fir.ref<!fir.array<10xf32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<10xf32>>, !fir.ref<!fir.array<10xf32>>) ! CHECK: %[[VAL_4:.*]] = hlfir.as_expr %[[VAL_3]]#0 : (!fir.ref<!fir.array<10xf32>>) -> !hlfir.expr<10xf32> ! CHECK: %[[VAL_5:.*]]:3 = hlfir.associate %[[VAL_4]](%[[VAL_2]]) {adapt.valuebyref} : (!hlfir.expr<10xf32>, !fir.shape<1>) -> (!fir.ref<!fir.array<10xf32>>, !fir.ref<!fir.array<10xf32>>, i1) ! CHECK: fir.call @_QPtakes_explicit_by_value(%[[VAL_5]]#0) {{.*}} : (!fir.ref<!fir.array<10xf32>>) -> () diff --git a/flang/test/Lower/HLFIR/calls-constant-expr-arg.f90 b/flang/test/Lower/HLFIR/calls-constant-expr-arg.f90 index f41b9cd..2186bda 100644 --- a/flang/test/Lower/HLFIR/calls-constant-expr-arg.f90 +++ b/flang/test/Lower/HLFIR/calls-constant-expr-arg.f90 @@ -18,7 +18,7 @@ end subroutine sub ! CHECK-LABEL: func.func @_QPsub( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.array<?xi32>> {fir.bindc_name = "i"}, ! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref<i32> {fir.bindc_name = "n"}) { -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFsubEn"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFsubEn"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_3:.*]] = fir.load %[[VAL_2]]#0 : !fir.ref<i32> ! CHECK: %[[VAL_4:.*]] = fir.convert %[[VAL_3]] : (i32) -> i64 ! CHECK: %[[VAL_5:.*]] = fir.convert %[[VAL_4]] : (i64) -> index @@ -26,7 +26,7 @@ end subroutine sub ! CHECK: %[[VAL_7:.*]] = arith.cmpi sgt, %[[VAL_5]], %[[VAL_6]] : index ! CHECK: %[[VAL_8:.*]] = arith.select %[[VAL_7]], %[[VAL_5]], %[[VAL_6]] : index ! CHECK: %[[VAL_9:.*]] = fir.shape %[[VAL_8]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_10:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_9]]) dummy_scope %{{[0-9]+}} {uniq_name = "_QFsubEi"} : (!fir.ref<!fir.array<?xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.box<!fir.array<?xi32>>, !fir.ref<!fir.array<?xi32>>) +! CHECK: %[[VAL_10:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_9]]) dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFsubEi"} : (!fir.ref<!fir.array<?xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.box<!fir.array<?xi32>>, !fir.ref<!fir.array<?xi32>>) ! CHECK: %[[VAL_11:.*]] = arith.constant 3 : index ! CHECK: %[[VAL_12:.*]] = arith.constant 2 : index ! CHECK: %[[VAL_13:.*]] = arith.constant 0 : index diff --git a/flang/test/Lower/HLFIR/calls-f77.f90 b/flang/test/Lower/HLFIR/calls-f77.f90 index 450f881..97d2307 100644 --- a/flang/test/Lower/HLFIR/calls-f77.f90 +++ b/flang/test/Lower/HLFIR/calls-f77.f90 @@ -19,7 +19,7 @@ subroutine call_int_arg_var(n) end subroutine ! CHECK-LABEL: func.func @_QPcall_int_arg_var( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<i32> -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFcall_int_arg_varEn"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFcall_int_arg_varEn"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: fir.call @_QPtake_i4(%[[VAL_1]]#0) fastmath<contract> : (!fir.ref<i32>) -> () subroutine call_int_arg_expr() @@ -46,7 +46,7 @@ subroutine call_real_arg_var(x) end subroutine ! CHECK-LABEL: func.func @_QPcall_real_arg_var( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<f32> -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFcall_real_arg_varEx"} : (!fir.ref<f32>, !fir.dscope) -> (!fir.ref<f32>, !fir.ref<f32>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFcall_real_arg_varEx"} : (!fir.ref<f32>, !fir.dscope) -> (!fir.ref<f32>, !fir.ref<f32>) ! CHECK: fir.call @_QPtake_r4(%[[VAL_1]]#0) fastmath<contract> : (!fir.ref<f32>) -> () subroutine call_logical_arg_var(x) @@ -55,7 +55,7 @@ subroutine call_logical_arg_var(x) end subroutine ! CHECK-LABEL: func.func @_QPcall_logical_arg_var( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.logical<4>> -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFcall_logical_arg_varEx"} : (!fir.ref<!fir.logical<4>>, !fir.dscope) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFcall_logical_arg_varEx"} : (!fir.ref<!fir.logical<4>>, !fir.dscope) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) ! CHECK: fir.call @_QPtake_l4(%[[VAL_1]]#0) fastmath<contract> : (!fir.ref<!fir.logical<4>>) -> () subroutine call_logical_arg_expr() @@ -85,7 +85,7 @@ end subroutine ! CHECK-LABEL: func.func @_QPcall_char_arg_var( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.boxchar<1> ! CHECK: %[[VAL_1:.*]]:2 = fir.unboxchar %[[VAL_0]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index) -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]]#0 typeparams %[[VAL_1]]#1 dummy_scope %{{[0-9]+}} {uniq_name = "_QFcall_char_arg_varEx"} : (!fir.ref<!fir.char<1,?>>, index, !fir.dscope) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]]#0 typeparams %[[VAL_1]]#1 dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFcall_char_arg_varEx"} : (!fir.ref<!fir.char<1,?>>, index, !fir.dscope) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>) ! CHECK: fir.call @_QPtake_c(%[[VAL_2]]#0) fastmath<contract> : (!fir.boxchar<1>) -> () subroutine call_char_arg_var_expr(x) @@ -95,7 +95,7 @@ end subroutine ! CHECK-LABEL: func.func @_QPcall_char_arg_var_expr( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.boxchar<1> ! CHECK: %[[VAL_1:.*]]:2 = fir.unboxchar %[[VAL_0]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index) -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]]#0 typeparams %[[VAL_1]]#1 dummy_scope %{{[0-9]+}} {uniq_name = "_QFcall_char_arg_var_exprEx"} : (!fir.ref<!fir.char<1,?>>, index, !fir.dscope) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]]#0 typeparams %[[VAL_1]]#1 dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFcall_char_arg_var_exprEx"} : (!fir.ref<!fir.char<1,?>>, index, !fir.dscope) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>) ! CHECK: %[[VAL_3:.*]] = arith.addi %[[VAL_1]]#1, %[[VAL_1]]#1 : index ! CHECK: %[[VAL_4:.*]] = hlfir.concat %[[VAL_2]]#0, %[[VAL_2]]#0 len %[[VAL_3]] : (!fir.boxchar<1>, !fir.boxchar<1>, index) -> !hlfir.expr<!fir.char<1,?>> ! CHECK: %[[VAL_5:.*]]:3 = hlfir.associate %[[VAL_4]] typeparams %[[VAL_3]] {adapt.valuebyref} : (!hlfir.expr<!fir.char<1,?>>, index) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>, i1) @@ -111,7 +111,7 @@ end subroutine ! CHECK: %[[VAL_1:.*]] = arith.constant 10 : index ! CHECK: %[[VAL_2:.*]] = arith.constant 20 : index ! CHECK: %[[VAL_3:.*]] = fir.shape %[[VAL_1]], %[[VAL_2]] : (index, index) -> !fir.shape<2> -! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_3]]) dummy_scope %{{[0-9]+}} {uniq_name = "_QFcall_arg_array_varEn"} : (!fir.ref<!fir.array<10x20xi32>>, !fir.shape<2>, !fir.dscope) -> (!fir.ref<!fir.array<10x20xi32>>, !fir.ref<!fir.array<10x20xi32>>) +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_3]]) dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFcall_arg_array_varEn"} : (!fir.ref<!fir.array<10x20xi32>>, !fir.shape<2>, !fir.dscope) -> (!fir.ref<!fir.array<10x20xi32>>, !fir.ref<!fir.array<10x20xi32>>) ! CHECK: fir.call @_QPtake_arr(%[[VAL_4]]#0) fastmath<contract> : (!fir.ref<!fir.array<10x20xi32>>) -> () subroutine call_arg_array_2(n) @@ -120,7 +120,7 @@ subroutine call_arg_array_2(n) end subroutine ! CHECK-LABEL: func.func @_QPcall_arg_array_2( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.box<!fir.array<?x?xi32>> -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<contiguous, optional>, uniq_name = "_QFcall_arg_array_2En"} : (!fir.box<!fir.array<?x?xi32>>, !fir.dscope) -> (!fir.box<!fir.array<?x?xi32>>, !fir.box<!fir.array<?x?xi32>>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<contiguous, optional>, uniq_name = "_QFcall_arg_array_2En"} : (!fir.box<!fir.array<?x?xi32>>, !fir.dscope) -> (!fir.box<!fir.array<?x?xi32>>, !fir.box<!fir.array<?x?xi32>>) ! CHECK: %[[VAL_2:.*]] = fir.box_addr %[[VAL_1]]#1 : (!fir.box<!fir.array<?x?xi32>>) -> !fir.ref<!fir.array<?x?xi32>> ! CHECK: fir.call @_QPtake_arr_2(%[[VAL_2]]) fastmath<contract> : (!fir.ref<!fir.array<?x?xi32>>) -> () diff --git a/flang/test/Lower/HLFIR/calls-optional.f90 b/flang/test/Lower/HLFIR/calls-optional.f90 index 76e1d136..d8d3bfe 100644 --- a/flang/test/Lower/HLFIR/calls-optional.f90 +++ b/flang/test/Lower/HLFIR/calls-optional.f90 @@ -14,7 +14,7 @@ subroutine optional_copy_in_out(x) call takes_optional_explicit(x) end subroutine ! CHECK-LABEL: func.func @_QPoptional_copy_in_out( -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0:[a-z0-9]*]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<optional>, uniq_name = "_QFoptional_copy_in_outEx"} : (!fir.box<!fir.array<?xf32>>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.box<!fir.array<?xf32>>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0:[a-z0-9]*]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<optional>, uniq_name = "_QFoptional_copy_in_outEx"} : (!fir.box<!fir.array<?xf32>>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.box<!fir.array<?xf32>>) ! CHECK: %[[VAL_2:.*]] = fir.is_present %[[VAL_1]]#0 : (!fir.box<!fir.array<?xf32>>) -> i1 ! CHECK: %[[VAL_3:.*]]:3 = fir.if %[[VAL_2]] -> (!fir.ref<!fir.array<?xf32>>, i1, !fir.box<!fir.array<?xf32>>) { ! CHECK: %[[VAL_4:.*]]:2 = hlfir.copy_in %[[VAL_1]]#0 to %[[TMP_BOX:.*]] : (!fir.box<!fir.array<?xf32>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>) -> (!fir.box<!fir.array<?xf32>>, i1) @@ -39,7 +39,7 @@ subroutine optional_value_copy(x) call takes_optional_explicit_value(x) end subroutine ! CHECK-LABEL: func.func @_QPoptional_value_copy( -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0:[a-z0-9]*]](%[[VAL_2:[a-z0-9]*]]) dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<optional>, uniq_name = "_QFoptional_value_copyEx"} : (!fir.ref<!fir.array<100xf32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100xf32>>, !fir.ref<!fir.array<100xf32>>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0:[a-z0-9]*]](%[[VAL_2:[a-z0-9]*]]) dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<optional>, uniq_name = "_QFoptional_value_copyEx"} : (!fir.ref<!fir.array<100xf32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100xf32>>, !fir.ref<!fir.array<100xf32>>) ! CHECK: %[[VAL_4:.*]] = fir.is_present %[[VAL_3]]#0 : (!fir.ref<!fir.array<100xf32>>) -> i1 ! CHECK: %[[VAL_5:.*]]:3 = fir.if %[[VAL_4]] -> (!fir.ref<!fir.array<100xf32>>, !fir.ref<!fir.array<100xf32>>, i1) { ! CHECK: %[[VAL_6:.*]] = hlfir.as_expr %[[VAL_3]]#0 : (!fir.ref<!fir.array<100xf32>>) -> !hlfir.expr<100xf32> @@ -65,8 +65,8 @@ subroutine elem_pointer_to_optional(x, y) call elem_takes_two_optional(x, y) end subroutine ! CHECK-LABEL: func.func @_QPelem_pointer_to_optional( -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0:[a-z0-9]*]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFelem_pointer_to_optionalEx"} : (!fir.box<!fir.array<?xf32>>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.box<!fir.array<?xf32>>) -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_1:[a-z0-9]*]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFelem_pointer_to_optionalEy"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0:[a-z0-9]*]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFelem_pointer_to_optionalEx"} : (!fir.box<!fir.array<?xf32>>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.box<!fir.array<?xf32>>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_1:[a-z0-9]*]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFelem_pointer_to_optionalEy"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>) ! CHECK: %[[VAL_4:.*]] = fir.load %[[VAL_3]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>> ! CHECK: %[[VAL_5:.*]] = fir.box_addr %[[VAL_4]] : (!fir.box<!fir.ptr<!fir.array<?xf32>>>) -> !fir.ptr<!fir.array<?xf32>> ! CHECK: %[[VAL_6:.*]] = fir.convert %[[VAL_5]] : (!fir.ptr<!fir.array<?xf32>>) -> i64 @@ -104,7 +104,7 @@ subroutine optional_cannot_be_absent_optional(x) call elem_takes_one_optional(x) end subroutine ! CHECK-LABEL: func.func @_QPoptional_cannot_be_absent_optional( -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0:[a-z0-9]*]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<optional>, uniq_name = "_QFoptional_cannot_be_absent_optionalEx"} : (!fir.box<!fir.array<?xf32>>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.box<!fir.array<?xf32>>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0:[a-z0-9]*]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<optional>, uniq_name = "_QFoptional_cannot_be_absent_optionalEx"} : (!fir.box<!fir.array<?xf32>>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.box<!fir.array<?xf32>>) ! CHECK: %[[VAL_2:.*]] = arith.constant 0 : index ! CHECK: %[[VAL_3:.*]]:3 = fir.box_dims %[[VAL_1]]#0, %[[VAL_2]] : (!fir.box<!fir.array<?xf32>>, index) -> (index, index, index) ! CHECK: %[[VAL_4:.*]] = arith.constant 1 : index @@ -124,8 +124,8 @@ subroutine optional_elem_poly(x, y) call elem_optional_poly(x, y) end subroutine ! CHECK-LABEL: func.func @_QPoptional_elem_poly( -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0:[a-z0-9]*]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFoptional_elem_polyEx"} : (!fir.box<!fir.array<?xf32>>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.box<!fir.array<?xf32>>) -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_1:[a-z0-9]*]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<optional>, uniq_name = "_QFoptional_elem_polyEy"} : (!fir.box<!fir.array<?xf32>>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.box<!fir.array<?xf32>>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0:[a-z0-9]*]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFoptional_elem_polyEx"} : (!fir.box<!fir.array<?xf32>>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.box<!fir.array<?xf32>>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_1:[a-z0-9]*]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<optional>, uniq_name = "_QFoptional_elem_polyEy"} : (!fir.box<!fir.array<?xf32>>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.box<!fir.array<?xf32>>) ! CHECK: %[[VAL_4:.*]] = fir.is_present %[[VAL_3]]#0 : (!fir.box<!fir.array<?xf32>>) -> i1 ! CHECK: %[[VAL_5:.*]] = arith.constant 0 : index ! CHECK: %[[VAL_6:.*]]:3 = fir.box_dims %[[VAL_2]]#0, %[[VAL_5]] : (!fir.box<!fir.array<?xf32>>, index) -> (index, index, index) diff --git a/flang/test/Lower/HLFIR/calls-percent-val-ref.f90 b/flang/test/Lower/HLFIR/calls-percent-val-ref.f90 index d150295..bb5591e 100644 --- a/flang/test/Lower/HLFIR/calls-percent-val-ref.f90 +++ b/flang/test/Lower/HLFIR/calls-percent-val-ref.f90 @@ -7,7 +7,7 @@ subroutine test_val_1(x) end subroutine ! CHECK-LABEL: func.func @_QPtest_val_1( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<i32> {fir.bindc_name = "x"}) { -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFtest_val_1Ex"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFtest_val_1Ex"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_2:.*]] = fir.load %[[VAL_1]]#0 : !fir.ref<i32> ! CHECK: fir.call @_QPval1(%[[VAL_2]]) fastmath<contract> : (i32) -> () @@ -17,7 +17,7 @@ subroutine test_val_2(x) end subroutine ! CHECK-LABEL: func.func @_QPtest_val_2( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.heap<complex<f32>>>> {fir.bindc_name = "x"}) { -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFtest_val_2Ex"} : (!fir.ref<!fir.box<!fir.heap<complex<f32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<complex<f32>>>>, !fir.ref<!fir.box<!fir.heap<complex<f32>>>>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFtest_val_2Ex"} : (!fir.ref<!fir.box<!fir.heap<complex<f32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<complex<f32>>>>, !fir.ref<!fir.box<!fir.heap<complex<f32>>>>) ! CHECK: %[[VAL_2:.*]] = fir.load %[[VAL_1]]#0 : !fir.ref<!fir.box<!fir.heap<complex<f32>>>> ! CHECK: %[[VAL_3:.*]] = fir.box_addr %[[VAL_2]] : (!fir.box<!fir.heap<complex<f32>>>) -> !fir.heap<complex<f32>> ! CHECK: %[[VAL_4:.*]] = fir.load %[[VAL_3]] : !fir.heap<complex<f32>> @@ -32,7 +32,7 @@ end subroutine ! CHECK-LABEL: func.func @_QPtest_ref_char( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.boxchar<1> {fir.bindc_name = "x"}) { ! CHECK: %[[VAL_1:.*]]:2 = fir.unboxchar %[[VAL_0]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index) -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]]#0 typeparams %[[VAL_1]]#1 dummy_scope %{{[0-9]+}} {uniq_name = "_QFtest_ref_charEx"} : (!fir.ref<!fir.char<1,?>>, index, !fir.dscope) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]]#0 typeparams %[[VAL_1]]#1 dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFtest_ref_charEx"} : (!fir.ref<!fir.char<1,?>>, index, !fir.dscope) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>) ! CHECK: %[[VAL_3:.*]]:2 = fir.unboxchar %[[VAL_2]]#0 : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index) ! CHECK: fir.call @_QPref_char(%[[VAL_3]]#0) fastmath<contract> : (!fir.ref<!fir.char<1,?>>) -> () @@ -42,7 +42,7 @@ subroutine test_ref_1(x) end subroutine ! CHECK-LABEL: func.func @_QPtest_ref_1( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<i32> {fir.bindc_name = "x"}) { -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFtest_ref_1Ex"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFtest_ref_1Ex"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: fir.call @_QPref1(%[[VAL_1]]#0) fastmath<contract> : (!fir.ref<i32>) -> () subroutine test_ref_2(x) @@ -51,7 +51,7 @@ subroutine test_ref_2(x) end subroutine ! CHECK-LABEL: func.func @_QPtest_ref_2( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.ptr<complex<f32>>>> {fir.bindc_name = "x"}) { -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFtest_ref_2Ex"} : (!fir.ref<!fir.box<!fir.ptr<complex<f32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<complex<f32>>>>, !fir.ref<!fir.box<!fir.ptr<complex<f32>>>>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFtest_ref_2Ex"} : (!fir.ref<!fir.box<!fir.ptr<complex<f32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<complex<f32>>>>, !fir.ref<!fir.box<!fir.ptr<complex<f32>>>>) ! CHECK: %[[VAL_2:.*]] = fir.load %[[VAL_1]]#0 : !fir.ref<!fir.box<!fir.ptr<complex<f32>>>> ! CHECK: %[[VAL_3:.*]] = fir.box_addr %[[VAL_2]] : (!fir.box<!fir.ptr<complex<f32>>>) -> !fir.ptr<complex<f32>> ! CHECK: %[[VAL_4:.*]] = fir.convert %[[VAL_3]] : (!fir.ptr<complex<f32>>) -> !fir.ref<complex<f32>> @@ -63,7 +63,7 @@ subroutine test_skip_copy_in_out(x) end subroutine ! CHECK-LABEL: func.func @_QPtest_skip_copy_in_out( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.box<!fir.array<?xf32>> {fir.bindc_name = "x"}) { -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFtest_skip_copy_in_outEx"} : (!fir.box<!fir.array<?xf32>>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.box<!fir.array<?xf32>>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFtest_skip_copy_in_outEx"} : (!fir.box<!fir.array<?xf32>>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.box<!fir.array<?xf32>>) ! CHECK: %[[VAL_2:.*]] = fir.box_addr %[[VAL_1]]#1 : (!fir.box<!fir.array<?xf32>>) -> !fir.ref<!fir.array<?xf32>> ! CHECK: %[[VAL_3:.*]] = fir.convert %[[VAL_2]] : (!fir.ref<!fir.array<?xf32>>) -> i64 ! CHECK: fir.call @_QPval3(%[[VAL_3]]) fastmath<contract> : (i64) -> () diff --git a/flang/test/Lower/HLFIR/calls-poly-to-assumed-type.f90 b/flang/test/Lower/HLFIR/calls-poly-to-assumed-type.f90 index d607e74..24d7ca9 100644 --- a/flang/test/Lower/HLFIR/calls-poly-to-assumed-type.f90 +++ b/flang/test/Lower/HLFIR/calls-poly-to-assumed-type.f90 @@ -12,7 +12,7 @@ subroutine pass_poly_to_assumed_type_assumed_size(x) call assumed_type_assumed_size(x) end subroutine ! CHECK-LABEL: func.func @_QPpass_poly_to_assumed_type_assumed_size( -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0:[a-z0-9]*]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<target>, uniq_name = "_QFpass_poly_to_assumed_type_assumed_sizeEx"} : (!fir.class<!fir.array<?x?xnone>>, !fir.dscope) -> (!fir.class<!fir.array<?x?xnone>>, !fir.class<!fir.array<?x?xnone>>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0:[a-z0-9]*]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<target>, uniq_name = "_QFpass_poly_to_assumed_type_assumed_sizeEx"} : (!fir.class<!fir.array<?x?xnone>>, !fir.dscope) -> (!fir.class<!fir.array<?x?xnone>>, !fir.class<!fir.array<?x?xnone>>) ! CHECK: %[[VAL_2:.*]]:2 = hlfir.copy_in %[[VAL_1]]#0 to %[[TMP_BOX:.*]] : (!fir.class<!fir.array<?x?xnone>>, !fir.ref<!fir.class<!fir.heap<!fir.array<?x?xnone>>>>) -> (!fir.class<!fir.array<?x?xnone>>, i1) ! CHECK: %[[VAL_3:.*]] = fir.box_addr %[[VAL_2]]#0 : (!fir.class<!fir.array<?x?xnone>>) -> !fir.ref<!fir.array<?x?xnone>> ! CHECK: %[[VAL_4:.*]] = fir.convert %[[VAL_3]] : (!fir.ref<!fir.array<?x?xnone>>) -> !fir.ref<!fir.array<?xnone>> diff --git a/flang/test/Lower/HLFIR/charconvert.f90 b/flang/test/Lower/HLFIR/charconvert.f90 index 45b0f35..f4cd3b1 100644 --- a/flang/test/Lower/HLFIR/charconvert.f90 +++ b/flang/test/Lower/HLFIR/charconvert.f90 @@ -13,7 +13,7 @@ subroutine charconvert1(c,n) end subroutine charconvert1 ! CHECK-LABEL: func.func @_QPcharconvert1 -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<intent_in>, uniq_name = "_QFcharconvert1Ec"} : (!fir.box<!fir.array<?x!fir.char<4,?>>>, !fir.dscope) -> (!fir.box<!fir.array<?x!fir.char<4,?>>>, !fir.box<!fir.array<?x!fir.char<4,?>>>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<intent_in>, uniq_name = "_QFcharconvert1Ec"} : (!fir.box<!fir.array<?x!fir.char<4,?>>>, !fir.dscope) -> (!fir.box<!fir.array<?x!fir.char<4,?>>>, !fir.box<!fir.array<?x!fir.char<4,?>>>) ! CHECK: ^bb0(%[[ARG2:.*]]: index): ! CHECK: %[[VAL_37:.*]] = fir.box_elesize %[[VAL_2]]#1 : (!fir.box<!fir.array<?x!fir.char<4,?>>>) -> index ! CHECK: %[[C4_4:.*]] = arith.constant 4 : index @@ -36,7 +36,7 @@ end subroutine charconvert2 ! CHECK: %[[C1:.*]] = arith.constant 1 : index ! CHECK: %[[VAL_1:.*]] = fir.alloca !fir.char<4> {bindc_name = "cx", uniq_name = "_QFcharconvert2Ecx"} ! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] typeparams %[[C1]] {uniq_name = "_QFcharconvert2Ecx"} : (!fir.ref<!fir.char<4>>, index) -> (!fir.ref<!fir.char<4>>, !fir.ref<!fir.char<4>>) -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<intent_in>, uniq_name = "_QFcharconvert2Ex"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<intent_in>, uniq_name = "_QFcharconvert2Ex"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_4:.*]] = fir.load %[[VAL_3]]#0 : !fir.ref<i32> ! CHECK: %[[VAL_5:.*]] = fir.convert %[[VAL_4]] : (i32) -> i64 ! CHECK: %[[VAL_6:.*]] = fir.convert %[[VAL_5]] : (i64) -> i8 @@ -56,11 +56,11 @@ subroutine charconvert3(c, c4) end subroutine ! CHECK-LABEL: func.func @_QPcharconvert3 -! CHECK-SAME: %[[ARG0:.*]]: !fir.boxchar<1> {{.*}}, %[[ARG1:.*]]: !fir.boxchar<4> +! CHECK-SAME: %[[ARG0:.*]]: !fir.boxchar<1> {{.*}}, %[[ARG1:.*]]: !fir.boxchar<4> ! CHECK: %[[VAL_0:.*]]:2 = fir.unboxchar %[[ARG0]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index) -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]]#0 typeparams %[[VAL_0]]#1 dummy_scope %{{[0-9]+}} {uniq_name = "_QFcharconvert3Ec"} : (!fir.ref<!fir.char<1,?>>, index, !fir.dscope) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]]#0 typeparams %[[VAL_0]]#1 dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFcharconvert3Ec"} : (!fir.ref<!fir.char<1,?>>, index, !fir.dscope) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>) ! CHECK: %[[VAL_2:.*]]:2 = fir.unboxchar %[[ARG1]] : (!fir.boxchar<4>) -> (!fir.ref<!fir.char<4,?>>, index) -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]]#0 typeparams %[[VAL_2]]#1 dummy_scope %{{[0-9]+}} {uniq_name = "_QFcharconvert3Ec4"} : (!fir.ref<!fir.char<4,?>>, index, !fir.dscope) -> (!fir.boxchar<4>, !fir.ref<!fir.char<4,?>>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]]#0 typeparams %[[VAL_2]]#1 dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFcharconvert3Ec4"} : (!fir.ref<!fir.char<4,?>>, index, !fir.dscope) -> (!fir.boxchar<4>, !fir.ref<!fir.char<4,?>>) ! CHECK: %[[VAL_4:.*]] = arith.addi %[[VAL_0]]#1, %[[VAL_0]]#1 : index ! CHECK: %[[VAL_5:.*]] = hlfir.concat %[[VAL_1]]#0, %[[VAL_1]]#0 len %[[VAL_4]] : (!fir.boxchar<1>, !fir.boxchar<1>, index) -> !hlfir.expr<!fir.char<1,?>> ! CHECK: %[[VAL_7:.*]]:3 = hlfir.associate %[[VAL_5]] typeparams %[[VAL_4]] {adapt.valuebyref} : (!hlfir.expr<!fir.char<1,?>>, index) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>, i1) diff --git a/flang/test/Lower/HLFIR/complex-div-to-hlfir-kind10.f90 b/flang/test/Lower/HLFIR/complex-div-to-hlfir-kind10.f90 index 0e219e3..7af4418 100644 --- a/flang/test/Lower/HLFIR/complex-div-to-hlfir-kind10.f90 +++ b/flang/test/Lower/HLFIR/complex-div-to-hlfir-kind10.f90 @@ -11,9 +11,9 @@ ! CHECK-LABEL: @_QPdiv_test_extended ! CHECK-SAME: %[[REF_0:.*]]: !fir.ref<complex<f80>> {{.*}}, %[[REF_1:.*]]: !fir.ref<complex<f80>> {{.*}}, %[[REF_2:.*]]: !fir.ref<complex<f80>> {{.*}}) ! CHECK: %[[VAL_3:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[REF_0]] dummy_scope %[[VAL_3]] {uniq_name = "_QFdiv_test_extendedEa"} : (!fir.ref<complex<f80>>, !fir.dscope) -> (!fir.ref<complex<f80>>, !fir.ref<complex<f80>>) -! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[REF_1]] dummy_scope %[[VAL_3]] {uniq_name = "_QFdiv_test_extendedEb"} : (!fir.ref<complex<f80>>, !fir.dscope) -> (!fir.ref<complex<f80>>, !fir.ref<complex<f80>>) -! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[REF_2]] dummy_scope %[[VAL_3]] {uniq_name = "_QFdiv_test_extendedEc"} : (!fir.ref<complex<f80>>, !fir.dscope) -> (!fir.ref<complex<f80>>, !fir.ref<complex<f80>>) +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[REF_0]] dummy_scope %[[VAL_3]] arg {{[0-9]+}} {uniq_name = "_QFdiv_test_extendedEa"} : (!fir.ref<complex<f80>>, !fir.dscope) -> (!fir.ref<complex<f80>>, !fir.ref<complex<f80>>) +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[REF_1]] dummy_scope %[[VAL_3]] arg {{[0-9]+}} {uniq_name = "_QFdiv_test_extendedEb"} : (!fir.ref<complex<f80>>, !fir.dscope) -> (!fir.ref<complex<f80>>, !fir.ref<complex<f80>>) +! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[REF_2]] dummy_scope %[[VAL_3]] arg {{[0-9]+}} {uniq_name = "_QFdiv_test_extendedEc"} : (!fir.ref<complex<f80>>, !fir.dscope) -> (!fir.ref<complex<f80>>, !fir.ref<complex<f80>>) ! CHECK: %[[VAL_7:.*]] = fir.load %[[VAL_5]]#0 : !fir.ref<complex<f80>> ! CHECK: %[[VAL_8:.*]] = fir.load %[[VAL_6]]#0 : !fir.ref<complex<f80>> diff --git a/flang/test/Lower/HLFIR/complex-div-to-hlfir-kind16.f90 b/flang/test/Lower/HLFIR/complex-div-to-hlfir-kind16.f90 index fe4a725..e732221 100644 --- a/flang/test/Lower/HLFIR/complex-div-to-hlfir-kind16.f90 +++ b/flang/test/Lower/HLFIR/complex-div-to-hlfir-kind16.f90 @@ -12,9 +12,9 @@ ! CHECK-LABEL: @_QPdiv_test_quad ! CHECK-SAME: %[[REF_0:.*]]: !fir.ref<complex<f128>> {{.*}}, %[[REF_1:.*]]: !fir.ref<complex<f128>> {{.*}}, %[[REF_2:.*]]: !fir.ref<complex<f128>> {{.*}}) ! CHECK: %[[VAL_3:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[REF_0]] dummy_scope %[[VAL_3]] {uniq_name = "_QFdiv_test_quadEa"} : (!fir.ref<complex<f128>>, !fir.dscope) -> (!fir.ref<complex<f128>>, !fir.ref<complex<f128>>) -! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[REF_1]] dummy_scope %[[VAL_3]] {uniq_name = "_QFdiv_test_quadEb"} : (!fir.ref<complex<f128>>, !fir.dscope) -> (!fir.ref<complex<f128>>, !fir.ref<complex<f128>>) -! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[REF_2]] dummy_scope %[[VAL_3]] {uniq_name = "_QFdiv_test_quadEc"} : (!fir.ref<complex<f128>>, !fir.dscope) -> (!fir.ref<complex<f128>>, !fir.ref<complex<f128>>) +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[REF_0]] dummy_scope %[[VAL_3]] arg {{[0-9]+}} {uniq_name = "_QFdiv_test_quadEa"} : (!fir.ref<complex<f128>>, !fir.dscope) -> (!fir.ref<complex<f128>>, !fir.ref<complex<f128>>) +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[REF_1]] dummy_scope %[[VAL_3]] arg {{[0-9]+}} {uniq_name = "_QFdiv_test_quadEb"} : (!fir.ref<complex<f128>>, !fir.dscope) -> (!fir.ref<complex<f128>>, !fir.ref<complex<f128>>) +! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[REF_2]] dummy_scope %[[VAL_3]] arg {{[0-9]+}} {uniq_name = "_QFdiv_test_quadEc"} : (!fir.ref<complex<f128>>, !fir.dscope) -> (!fir.ref<complex<f128>>, !fir.ref<complex<f128>>) ! CHECK: %[[VAL_7:.*]] = fir.load %[[VAL_5]]#0 : !fir.ref<complex<f128>> ! CHECK: %[[VAL_8:.*]] = fir.load %[[VAL_6]]#0 : !fir.ref<complex<f128>> diff --git a/flang/test/Lower/HLFIR/complex-div-to-hlfir.f90 b/flang/test/Lower/HLFIR/complex-div-to-hlfir.f90 index b488bfd..f9d7f8f 100644 --- a/flang/test/Lower/HLFIR/complex-div-to-hlfir.f90 +++ b/flang/test/Lower/HLFIR/complex-div-to-hlfir.f90 @@ -11,9 +11,9 @@ ! CHECK-LABEL: @_QPdiv_test_half ! CHECK-SAME: %[[REF_0:.*]]: !fir.ref<complex<f16>> {{.*}}, %[[REF_1:.*]]: !fir.ref<complex<f16>> {{.*}}, %[[REF_2:.*]]: !fir.ref<complex<f16>> {{.*}}) ! CHECK: %[[VAL_3:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[REF_0]] dummy_scope %[[VAL_3]] {uniq_name = "_QFdiv_test_halfEa"} : (!fir.ref<complex<f16>>, !fir.dscope) -> (!fir.ref<complex<f16>>, !fir.ref<complex<f16>>) -! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[REF_1]] dummy_scope %[[VAL_3]] {uniq_name = "_QFdiv_test_halfEb"} : (!fir.ref<complex<f16>>, !fir.dscope) -> (!fir.ref<complex<f16>>, !fir.ref<complex<f16>>) -! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[REF_2]] dummy_scope %[[VAL_3]] {uniq_name = "_QFdiv_test_halfEc"} : (!fir.ref<complex<f16>>, !fir.dscope) -> (!fir.ref<complex<f16>>, !fir.ref<complex<f16>>) +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[REF_0]] dummy_scope %[[VAL_3]] arg {{[0-9]+}} {uniq_name = "_QFdiv_test_halfEa"} : (!fir.ref<complex<f16>>, !fir.dscope) -> (!fir.ref<complex<f16>>, !fir.ref<complex<f16>>) +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[REF_1]] dummy_scope %[[VAL_3]] arg {{[0-9]+}} {uniq_name = "_QFdiv_test_halfEb"} : (!fir.ref<complex<f16>>, !fir.dscope) -> (!fir.ref<complex<f16>>, !fir.ref<complex<f16>>) +! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[REF_2]] dummy_scope %[[VAL_3]] arg {{[0-9]+}} {uniq_name = "_QFdiv_test_halfEc"} : (!fir.ref<complex<f16>>, !fir.dscope) -> (!fir.ref<complex<f16>>, !fir.ref<complex<f16>>) ! CHECK: %[[VAL_7:.*]] = fir.load %[[VAL_5]]#0 : !fir.ref<complex<f16>> ! CHECK: %[[VAL_8:.*]] = fir.load %[[VAL_6]]#0 : !fir.ref<complex<f16>> ! CHECK: %[[VAL_9:.*]] = complex.div %[[VAL_7]], %[[VAL_8]] fastmath<contract> : complex<f16> @@ -28,9 +28,9 @@ end subroutine div_test_half ! CHECK-LABEL: @_QPdiv_test_bfloat ! CHECK-SAME: %[[REF_0:.*]]: !fir.ref<complex<bf16>> {{.*}}, %[[REF_1:.*]]: !fir.ref<complex<bf16>> {{.*}}, %[[REF_2:.*]]: !fir.ref<complex<bf16>> {{.*}}) ! CHECK: %[[VAL_3:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[REF_0]] dummy_scope %[[VAL_3]] {uniq_name = "_QFdiv_test_bfloatEa"} : (!fir.ref<complex<bf16>>, !fir.dscope) -> (!fir.ref<complex<bf16>>, !fir.ref<complex<bf16>>) -! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[REF_1]] dummy_scope %[[VAL_3]] {uniq_name = "_QFdiv_test_bfloatEb"} : (!fir.ref<complex<bf16>>, !fir.dscope) -> (!fir.ref<complex<bf16>>, !fir.ref<complex<bf16>>) -! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[REF_2]] dummy_scope %[[VAL_3]] {uniq_name = "_QFdiv_test_bfloatEc"} : (!fir.ref<complex<bf16>>, !fir.dscope) -> (!fir.ref<complex<bf16>>, !fir.ref<complex<bf16>>) +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[REF_0]] dummy_scope %[[VAL_3]] arg {{[0-9]+}} {uniq_name = "_QFdiv_test_bfloatEa"} : (!fir.ref<complex<bf16>>, !fir.dscope) -> (!fir.ref<complex<bf16>>, !fir.ref<complex<bf16>>) +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[REF_1]] dummy_scope %[[VAL_3]] arg {{[0-9]+}} {uniq_name = "_QFdiv_test_bfloatEb"} : (!fir.ref<complex<bf16>>, !fir.dscope) -> (!fir.ref<complex<bf16>>, !fir.ref<complex<bf16>>) +! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[REF_2]] dummy_scope %[[VAL_3]] arg {{[0-9]+}} {uniq_name = "_QFdiv_test_bfloatEc"} : (!fir.ref<complex<bf16>>, !fir.dscope) -> (!fir.ref<complex<bf16>>, !fir.ref<complex<bf16>>) ! CHECK: %[[VAL_7:.*]] = fir.load %[[VAL_5]]#0 : !fir.ref<complex<bf16>> ! CHECK: %[[VAL_8:.*]] = fir.load %[[VAL_6]]#0 : !fir.ref<complex<bf16>> ! CHECK: %[[VAL_9:.*]] = complex.div %[[VAL_7]], %[[VAL_8]] fastmath<contract> : complex<bf16> @@ -45,9 +45,9 @@ end subroutine div_test_bfloat ! CHECK-LABEL: @_QPdiv_test_single ! CHECK-SAME: %[[REF_0:.*]]: !fir.ref<complex<f32>> {{.*}}, %[[REF_1:.*]]: !fir.ref<complex<f32>> {{.*}}, %[[REF_2:.*]]: !fir.ref<complex<f32>> {{.*}}) ! CHECK: %[[VAL_3:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[REF_0]] dummy_scope %[[VAL_3]] {uniq_name = "_QFdiv_test_singleEa"} : (!fir.ref<complex<f32>>, !fir.dscope) -> (!fir.ref<complex<f32>>, !fir.ref<complex<f32>>) -! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[REF_1]] dummy_scope %[[VAL_3]] {uniq_name = "_QFdiv_test_singleEb"} : (!fir.ref<complex<f32>>, !fir.dscope) -> (!fir.ref<complex<f32>>, !fir.ref<complex<f32>>) -! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[REF_2]] dummy_scope %[[VAL_3]] {uniq_name = "_QFdiv_test_singleEc"} : (!fir.ref<complex<f32>>, !fir.dscope) -> (!fir.ref<complex<f32>>, !fir.ref<complex<f32>>) +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[REF_0]] dummy_scope %[[VAL_3]] arg {{[0-9]+}} {uniq_name = "_QFdiv_test_singleEa"} : (!fir.ref<complex<f32>>, !fir.dscope) -> (!fir.ref<complex<f32>>, !fir.ref<complex<f32>>) +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[REF_1]] dummy_scope %[[VAL_3]] arg {{[0-9]+}} {uniq_name = "_QFdiv_test_singleEb"} : (!fir.ref<complex<f32>>, !fir.dscope) -> (!fir.ref<complex<f32>>, !fir.ref<complex<f32>>) +! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[REF_2]] dummy_scope %[[VAL_3]] arg {{[0-9]+}} {uniq_name = "_QFdiv_test_singleEc"} : (!fir.ref<complex<f32>>, !fir.dscope) -> (!fir.ref<complex<f32>>, !fir.ref<complex<f32>>) ! CHECK: %[[VAL_7:.*]] = fir.load %[[VAL_5]]#0 : !fir.ref<complex<f32>> ! CHECK: %[[VAL_8:.*]] = fir.load %[[VAL_6]]#0 : !fir.ref<complex<f32>> @@ -71,9 +71,9 @@ end subroutine div_test_single ! CHECK-LABEL: @_QPdiv_test_double ! CHECK-SAME: %[[REF_0:.*]]: !fir.ref<complex<f64>> {{.*}}, %[[REF_1:.*]]: !fir.ref<complex<f64>> {{.*}}, %[[REF_2:.*]]: !fir.ref<complex<f64>> {{.*}}) ! CHECK: %[[VAL_3:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[REF_0]] dummy_scope %[[VAL_3]] {uniq_name = "_QFdiv_test_doubleEa"} : (!fir.ref<complex<f64>>, !fir.dscope) -> (!fir.ref<complex<f64>>, !fir.ref<complex<f64>>) -! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[REF_1]] dummy_scope %[[VAL_3]] {uniq_name = "_QFdiv_test_doubleEb"} : (!fir.ref<complex<f64>>, !fir.dscope) -> (!fir.ref<complex<f64>>, !fir.ref<complex<f64>>) -! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[REF_2]] dummy_scope %[[VAL_3]] {uniq_name = "_QFdiv_test_doubleEc"} : (!fir.ref<complex<f64>>, !fir.dscope) -> (!fir.ref<complex<f64>>, !fir.ref<complex<f64>>) +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[REF_0]] dummy_scope %[[VAL_3]] arg {{[0-9]+}} {uniq_name = "_QFdiv_test_doubleEa"} : (!fir.ref<complex<f64>>, !fir.dscope) -> (!fir.ref<complex<f64>>, !fir.ref<complex<f64>>) +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[REF_1]] dummy_scope %[[VAL_3]] arg {{[0-9]+}} {uniq_name = "_QFdiv_test_doubleEb"} : (!fir.ref<complex<f64>>, !fir.dscope) -> (!fir.ref<complex<f64>>, !fir.ref<complex<f64>>) +! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[REF_2]] dummy_scope %[[VAL_3]] arg {{[0-9]+}} {uniq_name = "_QFdiv_test_doubleEc"} : (!fir.ref<complex<f64>>, !fir.dscope) -> (!fir.ref<complex<f64>>, !fir.ref<complex<f64>>) ! CHECK: %[[VAL_7:.*]] = fir.load %[[VAL_5]]#0 : !fir.ref<complex<f64>> ! CHECK: %[[VAL_8:.*]] = fir.load %[[VAL_6]]#0 : !fir.ref<complex<f64>> diff --git a/flang/test/Lower/HLFIR/convert-mbox-to-value.f90 b/flang/test/Lower/HLFIR/convert-mbox-to-value.f90 index ef9c121..b34dc8d 100644 --- a/flang/test/Lower/HLFIR/convert-mbox-to-value.f90 +++ b/flang/test/Lower/HLFIR/convert-mbox-to-value.f90 @@ -7,7 +7,7 @@ subroutine test_int_allocatable(a) end subroutine test_int_allocatable ! CHECK-LABEL: func.func @_QPtest_int_allocatable( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.heap<i32>>> {fir.bindc_name = "a"}) { -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFtest_int_allocatableEa"} : (!fir.ref<!fir.box<!fir.heap<i32>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<i32>>>, !fir.ref<!fir.box<!fir.heap<i32>>>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFtest_int_allocatableEa"} : (!fir.ref<!fir.box<!fir.heap<i32>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<i32>>>, !fir.ref<!fir.box<!fir.heap<i32>>>) ! CHECK: %[[VAL_2:.*]] = arith.constant 6 : i32 ! CHECK: %[[VAL_3:.*]] = fir.address_of(@_QQclX{{.*}}) : !fir.ref<!fir.char<1,{{[0-9]*}}>> ! CHECK: %[[VAL_4:.*]] = fir.convert %[[VAL_3]] : (!fir.ref<!fir.char<1,{{[0-9]*}}>>) -> !fir.ref<i8> @@ -27,7 +27,7 @@ subroutine test_int_pointer(p) end subroutine test_int_pointer ! CHECK-LABEL: func.func @_QPtest_int_pointer( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.ptr<i32>>> {fir.bindc_name = "p"}) { -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFtest_int_pointerEp"} : (!fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.ref<!fir.box<!fir.ptr<i32>>>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFtest_int_pointerEp"} : (!fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.ref<!fir.box<!fir.ptr<i32>>>) ! CHECK: %[[VAL_2:.*]] = arith.constant 6 : i32 ! CHECK: %[[VAL_3:.*]] = fir.address_of(@_QQclX{{.*}}) : !fir.ref<!fir.char<1,{{[0-9]*}}>> ! CHECK: %[[VAL_4:.*]] = fir.convert %[[VAL_3]] : (!fir.ref<!fir.char<1,{{[0-9]*}}>>) -> !fir.ref<i8> @@ -49,7 +49,7 @@ end subroutine test_char_allocatable ! CHECK-LABEL: func.func @_QPtest_char_allocatable( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.heap<!fir.char<1,11>>>> {fir.bindc_name = "a"}) { ! CHECK: %[[VAL_1:.*]] = arith.constant 11 : index -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] typeparams %[[VAL_1]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFtest_char_allocatableEa"} : (!fir.ref<!fir.box<!fir.heap<!fir.char<1,11>>>>, index, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.char<1,11>>>>, !fir.ref<!fir.box<!fir.heap<!fir.char<1,11>>>>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] typeparams %[[VAL_1]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFtest_char_allocatableEa"} : (!fir.ref<!fir.box<!fir.heap<!fir.char<1,11>>>>, index, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.char<1,11>>>>, !fir.ref<!fir.box<!fir.heap<!fir.char<1,11>>>>) ! CHECK: %[[VAL_3:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFtest_char_allocatableEi"} ! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_3]] {uniq_name = "_QFtest_char_allocatableEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_5:.*]] = fir.load %[[VAL_2]]#0 : !fir.ref<!fir.box<!fir.heap<!fir.char<1,11>>>> @@ -86,7 +86,7 @@ end subroutine test_char_pointer ! CHECK: %[[VAL_1:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFtest_char_pointerEi"} ! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "_QFtest_char_pointerEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_3:.*]] = arith.constant 11 : index -! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_0]] typeparams %[[VAL_3]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFtest_char_pointerEp"} : (!fir.ref<!fir.box<!fir.ptr<!fir.char<1,11>>>>, index, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.char<1,11>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.char<1,11>>>>) +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_0]] typeparams %[[VAL_3]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFtest_char_pointerEp"} : (!fir.ref<!fir.box<!fir.ptr<!fir.char<1,11>>>>, index, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.char<1,11>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.char<1,11>>>>) ! CHECK: %[[VAL_5:.*]] = fir.load %[[VAL_4]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.char<1,11>>>> ! CHECK: %[[VAL_6:.*]] = fir.box_addr %[[VAL_5]] : (!fir.box<!fir.ptr<!fir.char<1,11>>>) -> !fir.ptr<!fir.char<1,11>> ! CHECK: %[[VAL_3B:.*]] = arith.constant 11 : index @@ -120,7 +120,7 @@ end subroutine test_dyn_char_allocatable ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.heap<!fir.char<1,?>>>> {fir.bindc_name = "a"}) { ! CHECK: %[[VAL_1:.*]] = fir.load %[[VAL_0]] : !fir.ref<!fir.box<!fir.heap<!fir.char<1,?>>>> ! CHECK: %[[VAL_2:.*]] = fir.box_elesize %[[VAL_1]] : (!fir.box<!fir.heap<!fir.char<1,?>>>) -> index -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] typeparams %[[VAL_2]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFtest_dyn_char_allocatableEa"} : (!fir.ref<!fir.box<!fir.heap<!fir.char<1,?>>>>, index, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.char<1,?>>>>, !fir.ref<!fir.box<!fir.heap<!fir.char<1,?>>>>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] typeparams %[[VAL_2]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFtest_dyn_char_allocatableEa"} : (!fir.ref<!fir.box<!fir.heap<!fir.char<1,?>>>>, index, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.char<1,?>>>>, !fir.ref<!fir.box<!fir.heap<!fir.char<1,?>>>>) ! CHECK: %[[VAL_4:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFtest_dyn_char_allocatableEi"} ! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_4]] {uniq_name = "_QFtest_dyn_char_allocatableEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_6:.*]] = fir.load %[[VAL_3]]#0 : !fir.ref<!fir.box<!fir.heap<!fir.char<1,?>>>> @@ -157,7 +157,7 @@ end subroutine test_dyn_char_pointer ! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "_QFtest_dyn_char_pointerEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_3:.*]] = fir.load %[[VAL_0]] : !fir.ref<!fir.box<!fir.ptr<!fir.char<1,?>>>> ! CHECK: %[[VAL_4:.*]] = fir.box_elesize %[[VAL_3]] : (!fir.box<!fir.ptr<!fir.char<1,?>>>) -> index -! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_0]] typeparams %[[VAL_4]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFtest_dyn_char_pointerEp"} : (!fir.ref<!fir.box<!fir.ptr<!fir.char<1,?>>>>, index, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.char<1,?>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.char<1,?>>>>) +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_0]] typeparams %[[VAL_4]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFtest_dyn_char_pointerEp"} : (!fir.ref<!fir.box<!fir.ptr<!fir.char<1,?>>>>, index, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.char<1,?>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.char<1,?>>>>) ! CHECK: %[[VAL_6:.*]] = fir.load %[[VAL_5]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.char<1,?>>>> ! CHECK: %[[VAL_7:.*]] = fir.box_addr %[[VAL_6]] : (!fir.box<!fir.ptr<!fir.char<1,?>>>) -> !fir.ptr<!fir.char<1,?>> ! CHECK: %[[VAL_8:.*]] = arith.constant 1 : index @@ -201,7 +201,7 @@ end subroutine test_derived_allocatable ! CHECK: %[[VAL_7:.*]] = fir.embox %[[VAL_6]] : (!fir.heap<!fir.type<_QFtest_derived_allocatableTt>>) -> !fir.class<!fir.heap<!fir.type<_QFtest_derived_allocatableTt>>> ! CHECK: fir.store %[[VAL_7]] to %[[VAL_5]] : !fir.ref<!fir.class<!fir.heap<!fir.type<_QFtest_derived_allocatableTt>>>> ! CHECK: %[[VAL_8:.*]]:2 = hlfir.declare %[[VAL_5]] {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFtest_derived_allocatableEa2"} : (!fir.ref<!fir.class<!fir.heap<!fir.type<_QFtest_derived_allocatableTt>>>>) -> (!fir.ref<!fir.class<!fir.heap<!fir.type<_QFtest_derived_allocatableTt>>>>, !fir.ref<!fir.class<!fir.heap<!fir.type<_QFtest_derived_allocatableTt>>>>) -! CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFtest_derived_allocatableEl"} : (!fir.ref<!fir.logical<4>>, !fir.dscope) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) +! CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFtest_derived_allocatableEl"} : (!fir.ref<!fir.logical<4>>, !fir.dscope) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) ! CHECK: %[[VAL_10:.*]] = fir.alloca !fir.class<!fir.heap<!fir.type<_QFtest_derived_allocatableTt>>> {bindc_name = "r", uniq_name = "_QFtest_derived_allocatableEr"} ! CHECK: %[[VAL_11:.*]] = fir.zero_bits !fir.heap<!fir.type<_QFtest_derived_allocatableTt>> ! CHECK: %[[VAL_12:.*]] = fir.embox %[[VAL_11]] : (!fir.heap<!fir.type<_QFtest_derived_allocatableTt>>) -> !fir.class<!fir.heap<!fir.type<_QFtest_derived_allocatableTt>>> @@ -241,7 +241,7 @@ end subroutine test_derived_pointer ! CHECK: %[[VAL_7:.*]] = fir.embox %[[VAL_6]] : (!fir.heap<!fir.type<_QFtest_derived_pointerTt>>) -> !fir.class<!fir.heap<!fir.type<_QFtest_derived_pointerTt>>> ! CHECK: fir.store %[[VAL_7]] to %[[VAL_5]] : !fir.ref<!fir.class<!fir.heap<!fir.type<_QFtest_derived_pointerTt>>>> ! CHECK: %[[VAL_8:.*]]:2 = hlfir.declare %[[VAL_5]] {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFtest_derived_pointerEa2"} : (!fir.ref<!fir.class<!fir.heap<!fir.type<_QFtest_derived_pointerTt>>>>) -> (!fir.ref<!fir.class<!fir.heap<!fir.type<_QFtest_derived_pointerTt>>>>, !fir.ref<!fir.class<!fir.heap<!fir.type<_QFtest_derived_pointerTt>>>>) -! CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFtest_derived_pointerEl"} : (!fir.ref<!fir.logical<4>>, !fir.dscope) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) +! CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFtest_derived_pointerEl"} : (!fir.ref<!fir.logical<4>>, !fir.dscope) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) ! CHECK: %[[VAL_10:.*]] = fir.alloca !fir.class<!fir.heap<!fir.type<_QFtest_derived_pointerTt>>> {bindc_name = "r", uniq_name = "_QFtest_derived_pointerEr"} ! CHECK: %[[VAL_11:.*]] = fir.zero_bits !fir.heap<!fir.type<_QFtest_derived_pointerTt>> ! CHECK: %[[VAL_12:.*]] = fir.embox %[[VAL_11]] : (!fir.heap<!fir.type<_QFtest_derived_pointerTt>>) -> !fir.class<!fir.heap<!fir.type<_QFtest_derived_pointerTt>>> diff --git a/flang/test/Lower/HLFIR/convert-variable-assumed-rank.f90 b/flang/test/Lower/HLFIR/convert-variable-assumed-rank.f90 index d2931ea..8c7a8c4 100644 --- a/flang/test/Lower/HLFIR/convert-variable-assumed-rank.f90 +++ b/flang/test/Lower/HLFIR/convert-variable-assumed-rank.f90 @@ -52,7 +52,7 @@ end subroutine ! CHECK-LABEL: func.func @_QMassumed_rank_testsPtest_intrinsic( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.box<!fir.array<*:f32>> {fir.bindc_name = "x"}) { ! CHECK: %[[VAL_1:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] {uniq_name = "_QMassumed_rank_testsFtest_intrinsicEx"} : (!fir.box<!fir.array<*:f32>>, !fir.dscope) -> (!fir.box<!fir.array<*:f32>>, !fir.box<!fir.array<*:f32>>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] arg {{[0-9]+}} {uniq_name = "_QMassumed_rank_testsFtest_intrinsicEx"} : (!fir.box<!fir.array<*:f32>>, !fir.dscope) -> (!fir.box<!fir.array<*:f32>>, !fir.box<!fir.array<*:f32>>) ! CHECK: fir.call @_QPtakes_real(%[[VAL_2]]#0) fastmath<contract> : (!fir.box<!fir.array<*:f32>>) -> () ! CHECK: return ! CHECK: } @@ -61,12 +61,12 @@ end subroutine ! CHECK-SAME: %[[VAL_0:.*]]: !fir.box<!fir.array<*:!fir.char<1,?>>> {fir.bindc_name = "x"}, ! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref<i64> {fir.bindc_name = "n"}) { ! CHECK: %[[VAL_2:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %[[VAL_2]] {uniq_name = "_QMassumed_rank_testsFtest_character_explicit_lenEn"} : (!fir.ref<i64>, !fir.dscope) -> (!fir.ref<i64>, !fir.ref<i64>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %[[VAL_2]] arg {{[0-9]+}} {uniq_name = "_QMassumed_rank_testsFtest_character_explicit_lenEn"} : (!fir.ref<i64>, !fir.dscope) -> (!fir.ref<i64>, !fir.ref<i64>) ! CHECK: %[[VAL_4:.*]] = fir.load %[[VAL_3]]#0 : !fir.ref<i64> ! CHECK: %[[VAL_5:.*]] = arith.constant 0 : i64 ! CHECK: %[[VAL_6:.*]] = arith.cmpi sgt, %[[VAL_4]], %[[VAL_5]] : i64 ! CHECK: %[[VAL_7:.*]] = arith.select %[[VAL_6]], %[[VAL_4]], %[[VAL_5]] : i64 -! CHECK: %[[VAL_8:.*]]:2 = hlfir.declare %[[VAL_0]] typeparams %[[VAL_7]] dummy_scope %[[VAL_2]] {uniq_name = "_QMassumed_rank_testsFtest_character_explicit_lenEx"} : (!fir.box<!fir.array<*:!fir.char<1,?>>>, i64, !fir.dscope) -> (!fir.box<!fir.array<*:!fir.char<1,?>>>, !fir.box<!fir.array<*:!fir.char<1,?>>>) +! CHECK: %[[VAL_8:.*]]:2 = hlfir.declare %[[VAL_0]] typeparams %[[VAL_7]] dummy_scope %[[VAL_2]] arg {{[0-9]+}} {uniq_name = "_QMassumed_rank_testsFtest_character_explicit_lenEx"} : (!fir.box<!fir.array<*:!fir.char<1,?>>>, i64, !fir.dscope) -> (!fir.box<!fir.array<*:!fir.char<1,?>>>, !fir.box<!fir.array<*:!fir.char<1,?>>>) ! CHECK: fir.call @_QPtakes_char(%[[VAL_8]]#0) fastmath<contract> : (!fir.box<!fir.array<*:!fir.char<1,?>>>) -> () ! CHECK: return ! CHECK: } @@ -74,7 +74,7 @@ end subroutine ! CHECK-LABEL: func.func @_QMassumed_rank_testsPtest_character_assumed_len( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.box<!fir.array<*:!fir.char<1,?>>> {fir.bindc_name = "x"}) { ! CHECK: %[[VAL_1:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] {uniq_name = "_QMassumed_rank_testsFtest_character_assumed_lenEx"} : (!fir.box<!fir.array<*:!fir.char<1,?>>>, !fir.dscope) -> (!fir.box<!fir.array<*:!fir.char<1,?>>>, !fir.box<!fir.array<*:!fir.char<1,?>>>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] arg {{[0-9]+}} {uniq_name = "_QMassumed_rank_testsFtest_character_assumed_lenEx"} : (!fir.box<!fir.array<*:!fir.char<1,?>>>, !fir.dscope) -> (!fir.box<!fir.array<*:!fir.char<1,?>>>, !fir.box<!fir.array<*:!fir.char<1,?>>>) ! CHECK: fir.call @_QPtakes_char(%[[VAL_2]]#0) fastmath<contract> : (!fir.box<!fir.array<*:!fir.char<1,?>>>) -> () ! CHECK: return ! CHECK: } @@ -82,27 +82,27 @@ end subroutine ! CHECK-LABEL: func.func @_QMassumed_rank_testsPtest_with_attrs( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.box<!fir.array<*:f32>> {fir.bindc_name = "x", fir.optional, fir.target}) { ! CHECK: %[[VAL_1:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] {fortran_attrs = #fir.var_attrs<optional, target>, uniq_name = "_QMassumed_rank_testsFtest_with_attrsEx"} : (!fir.box<!fir.array<*:f32>>, !fir.dscope) -> (!fir.box<!fir.array<*:f32>>, !fir.box<!fir.array<*:f32>>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<optional, target>, uniq_name = "_QMassumed_rank_testsFtest_with_attrsEx"} : (!fir.box<!fir.array<*:f32>>, !fir.dscope) -> (!fir.box<!fir.array<*:f32>>, !fir.box<!fir.array<*:f32>>) ! CHECK: fir.call @_QPtakes_real(%[[VAL_2]]#0) fastmath<contract> : (!fir.box<!fir.array<*:f32>>) -> () ! CHECK-LABEL: func.func @_QMassumed_rank_testsPtest_simple_allocatable( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.heap<!fir.array<*:f32>>>> {fir.bindc_name = "x"}) { ! CHECK: %[[VAL_1:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QMassumed_rank_testsFtest_simple_allocatableEx"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<*:f32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<*:f32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<*:f32>>>>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QMassumed_rank_testsFtest_simple_allocatableEx"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<*:f32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<*:f32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<*:f32>>>>) ! CHECK: return ! CHECK: } ! CHECK-LABEL: func.func @_QMassumed_rank_testsPtest_simple_pointer( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.ptr<!fir.array<*:f32>>>> {fir.bindc_name = "x"}) { ! CHECK: %[[VAL_1:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QMassumed_rank_testsFtest_simple_pointerEx"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<*:f32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<*:f32>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<*:f32>>>>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QMassumed_rank_testsFtest_simple_pointerEx"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<*:f32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<*:f32>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<*:f32>>>>) ! CHECK: return ! CHECK: } ! CHECK-LABEL: func.func @_QMassumed_rank_testsPtest_intentout( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.heap<!fir.array<*:f32>>>> {fir.bindc_name = "x"}) { ! CHECK: %[[VAL_1:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] {fortran_attrs = #fir.var_attrs<allocatable, intent_out>, uniq_name = "_QMassumed_rank_testsFtest_intentoutEx"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<*:f32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<*:f32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<*:f32>>>>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable, intent_out>, uniq_name = "_QMassumed_rank_testsFtest_intentoutEx"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<*:f32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<*:f32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<*:f32>>>>) ! CHECK: %[[VAL_3:.*]] = fir.load %[[VAL_2]]#0 : !fir.ref<!fir.box<!fir.heap<!fir.array<*:f32>>>> ! CHECK: %[[VAL_4:.*]] = fir.box_addr %[[VAL_3]] : (!fir.box<!fir.heap<!fir.array<*:f32>>>) -> !fir.heap<!fir.array<*:f32>> ! CHECK: %[[VAL_5:.*]] = fir.convert %[[VAL_4]] : (!fir.heap<!fir.array<*:f32>>) -> i64 @@ -122,7 +122,7 @@ end subroutine ! CHECK: %[[VAL_1:.*]] = fir.dummy_scope : !fir.dscope ! CHECK: %[[VAL_2:.*]] = fir.load %[[VAL_0]] : !fir.ref<!fir.box<!fir.heap<!fir.array<*:!fir.char<1,?>>>>> ! CHECK: %[[VAL_3:.*]] = fir.box_elesize %[[VAL_2]] : (!fir.box<!fir.heap<!fir.array<*:!fir.char<1,?>>>>) -> index -! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_0]] typeparams %[[VAL_3]] dummy_scope %[[VAL_1]] {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QMassumed_rank_testsFtest_assumed_length_allocEx"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<*:!fir.char<1,?>>>>>, index, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<*:!fir.char<1,?>>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<*:!fir.char<1,?>>>>>) +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_0]] typeparams %[[VAL_3]] dummy_scope %[[VAL_1]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QMassumed_rank_testsFtest_assumed_length_allocEx"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<*:!fir.char<1,?>>>>>, index, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<*:!fir.char<1,?>>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<*:!fir.char<1,?>>>>>) ! CHECK: return ! CHECK: } end module diff --git a/flang/test/Lower/HLFIR/convert-variable-block.f90 b/flang/test/Lower/HLFIR/convert-variable-block.f90 index dad6bc1..ba988bc 100644 --- a/flang/test/Lower/HLFIR/convert-variable-block.f90 +++ b/flang/test/Lower/HLFIR/convert-variable-block.f90 @@ -12,7 +12,7 @@ subroutine test(n) end subroutine ! CHECK-LABEL: func.func @_QPtest( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<i64> {fir.bindc_name = "n"}) { -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFtestEn"} : (!fir.ref<i64>, !fir.dscope) -> (!fir.ref<i64>, !fir.ref<i64>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFtestEn"} : (!fir.ref<i64>, !fir.dscope) -> (!fir.ref<i64>, !fir.ref<i64>) ! CHECK: fir.call @_QPbefore_block() {{.*}}: () -> () ! CHECK: %[[VAL_3:.*]] = fir.load %[[VAL_1]]#0 : !fir.ref<i64> ! CHECK: %[[VAL_4:.*]] = fir.convert %[[VAL_3]] : (i64) -> index diff --git a/flang/test/Lower/HLFIR/convert-variable.f90 b/flang/test/Lower/HLFIR/convert-variable.f90 index 07b91d0..b9fda640 100644 --- a/flang/test/Lower/HLFIR/convert-variable.f90 +++ b/flang/test/Lower/HLFIR/convert-variable.f90 @@ -6,7 +6,7 @@ subroutine scalar_numeric(x) end subroutine ! CHECK-LABEL: func.func @_QPscalar_numeric( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<i32> -! CHECK: %[[VAL_1:.*]] = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFscalar_numericEx"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_1:.*]] = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFscalar_numericEx"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) subroutine scalar_character(c) character(*) :: c @@ -14,7 +14,7 @@ end subroutine ! CHECK-LABEL: func.func @_QPscalar_character( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.boxchar<1> ! CHECK: %[[VAL_1:.*]]:2 = fir.unboxchar %[[VAL_0]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index) -! CHECK: %[[VAL_2:.*]] = hlfir.declare %[[VAL_1]]#0 typeparams %[[VAL_1]]#1 dummy_scope %{{[0-9]+}} {uniq_name = "_QFscalar_characterEc"} : (!fir.ref<!fir.char<1,?>>, index, !fir.dscope) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>) +! CHECK: %[[VAL_2:.*]] = hlfir.declare %[[VAL_1]]#0 typeparams %[[VAL_1]]#1 dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFscalar_characterEc"} : (!fir.ref<!fir.char<1,?>>, index, !fir.dscope) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>) subroutine scalar_character_cst_len(c) character(10) :: c @@ -24,7 +24,7 @@ end subroutine ! CHECK: %[[VAL_1:.*]]:2 = fir.unboxchar %[[VAL_0]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index) ! CHECK: %[[VAL_3:.*]] = fir.convert %[[VAL_1]]#0 : (!fir.ref<!fir.char<1,?>>) -> !fir.ref<!fir.char<1,10>> ! CHECK: %[[VAL_2:.*]] = arith.constant 10 : index -! CHECK: %[[VAL_4:.*]] = hlfir.declare %[[VAL_3]] typeparams %[[VAL_2]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFscalar_character_cst_lenEc"} : (!fir.ref<!fir.char<1,10>>, index, !fir.dscope) -> (!fir.ref<!fir.char<1,10>>, !fir.ref<!fir.char<1,10>>) +! CHECK: %[[VAL_4:.*]] = hlfir.declare %[[VAL_3]] typeparams %[[VAL_2]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFscalar_character_cst_lenEc"} : (!fir.ref<!fir.char<1,10>>, index, !fir.dscope) -> (!fir.ref<!fir.char<1,10>>, !fir.ref<!fir.char<1,10>>) subroutine array_numeric(x) integer :: x(10, 20) @@ -34,7 +34,7 @@ end subroutine ! CHECK: %[[VAL_1:.*]] = arith.constant 10 : index ! CHECK: %[[VAL_2:.*]] = arith.constant 20 : index ! CHECK: %[[VAL_3:.*]] = fir.shape %[[VAL_1]], %[[VAL_2]] : (index, index) -> !fir.shape<2> -! CHECK: %[[VAL_4:.*]] = hlfir.declare %[[VAL_0]](%[[VAL_3]]) dummy_scope %{{[0-9]+}} {uniq_name = "_QFarray_numericEx"} : (!fir.ref<!fir.array<10x20xi32>>, !fir.shape<2>, !fir.dscope) -> (!fir.ref<!fir.array<10x20xi32>>, !fir.ref<!fir.array<10x20xi32>>) +! CHECK: %[[VAL_4:.*]] = hlfir.declare %[[VAL_0]](%[[VAL_3]]) dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFarray_numericEx"} : (!fir.ref<!fir.array<10x20xi32>>, !fir.shape<2>, !fir.dscope) -> (!fir.ref<!fir.array<10x20xi32>>, !fir.ref<!fir.array<10x20xi32>>) subroutine array_numeric_lbounds(x) @@ -47,7 +47,7 @@ end subroutine ! CHECK: %[[VAL_3:.*]] = arith.constant -2 : index ! CHECK: %[[VAL_4:.*]] = arith.constant 23 : index ! CHECK: %[[VAL_5:.*]] = fir.shape_shift %[[VAL_1]], %[[VAL_2]], %[[VAL_3]], %[[VAL_4]] : (index, index, index, index) -> !fir.shapeshift<2> -! CHECK: %[[VAL_6:.*]] = hlfir.declare %[[VAL_0]](%[[VAL_5]]) dummy_scope %{{[0-9]+}} {uniq_name = "_QFarray_numeric_lboundsEx"} : (!fir.ref<!fir.array<12x23xi32>>, !fir.shapeshift<2>, !fir.dscope) -> (!fir.box<!fir.array<12x23xi32>>, !fir.ref<!fir.array<12x23xi32>>) +! CHECK: %[[VAL_6:.*]] = hlfir.declare %[[VAL_0]](%[[VAL_5]]) dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFarray_numeric_lboundsEx"} : (!fir.ref<!fir.array<12x23xi32>>, !fir.shapeshift<2>, !fir.dscope) -> (!fir.box<!fir.array<12x23xi32>>, !fir.ref<!fir.array<12x23xi32>>) subroutine array_character(c) character(*) :: c(50) @@ -58,14 +58,14 @@ end subroutine ! CHECK: %[[VAL_2:.*]] = fir.convert %[[VAL_1]]#0 : (!fir.ref<!fir.char<1,?>>) -> !fir.ref<!fir.array<50x!fir.char<1,?>>> ! CHECK: %[[VAL_3:.*]] = arith.constant 50 : index ! CHECK: %[[VAL_4:.*]] = fir.shape %[[VAL_3]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_5:.*]] = hlfir.declare %[[VAL_2]](%[[VAL_4]]) typeparams %[[VAL_1]]#1 dummy_scope %{{[0-9]+}} {uniq_name = "_QFarray_characterEc"} : (!fir.ref<!fir.array<50x!fir.char<1,?>>>, !fir.shape<1>, index, !fir.dscope) -> (!fir.box<!fir.array<50x!fir.char<1,?>>>, !fir.ref<!fir.array<50x!fir.char<1,?>>>) +! CHECK: %[[VAL_5:.*]] = hlfir.declare %[[VAL_2]](%[[VAL_4]]) typeparams %[[VAL_1]]#1 dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFarray_characterEc"} : (!fir.ref<!fir.array<50x!fir.char<1,?>>>, !fir.shape<1>, index, !fir.dscope) -> (!fir.box<!fir.array<50x!fir.char<1,?>>>, !fir.ref<!fir.array<50x!fir.char<1,?>>>) subroutine scalar_numeric_attributes(x) integer, optional, target, intent(in) :: x end subroutine ! CHECK-LABEL: func.func @_QPscalar_numeric_attributes( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<i32> -! CHECK: %[[VAL_1:.*]] = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<intent_in, optional, target>, uniq_name = "_QFscalar_numeric_attributesEx"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_1:.*]] = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<intent_in, optional, target>, uniq_name = "_QFscalar_numeric_attributesEx"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) subroutine scalar_numeric_attributes_2(x) integer, parameter :: rk = merge(16, 8, selected_real_kind(33, 4931)==16) @@ -76,22 +76,22 @@ end subroutine ! F64-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.array<100xf64>> ! CHECK: %[[VAL_1:.*]] = arith.constant 100 : index ! CHECK: %[[VAL_2:.*]] = fir.shape %[[VAL_1]] : (index) -> !fir.shape<1> -! F128: %[[VAL_3:.*]] = hlfir.declare %[[VAL_0]](%[[VAL_2]]) dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<value>, uniq_name = "_QFscalar_numeric_attributes_2Ex"} : (!fir.ref<!fir.array<100xf128>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100xf128>>, !fir.ref<!fir.array<100xf128>>) -! F64: %[[VAL_3:.*]] = hlfir.declare %[[VAL_0]](%[[VAL_2]]) dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<value>, uniq_name = "_QFscalar_numeric_attributes_2Ex"} : (!fir.ref<!fir.array<100xf64>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100xf64>>, !fir.ref<!fir.array<100xf64>>) +! F128: %[[VAL_3:.*]] = hlfir.declare %[[VAL_0]](%[[VAL_2]]) dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<value>, uniq_name = "_QFscalar_numeric_attributes_2Ex"} : (!fir.ref<!fir.array<100xf128>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100xf128>>, !fir.ref<!fir.array<100xf128>>) +! F64: %[[VAL_3:.*]] = hlfir.declare %[[VAL_0]](%[[VAL_2]]) dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<value>, uniq_name = "_QFscalar_numeric_attributes_2Ex"} : (!fir.ref<!fir.array<100xf64>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100xf64>>, !fir.ref<!fir.array<100xf64>>) subroutine scalar_numeric_attributes_3(x) real, intent(in) :: x end subroutine ! CHECK-LABEL: func.func @_QPscalar_numeric_attributes_3( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<f32> -! CHECK: %[[VAL_1:.*]] = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<intent_in>, uniq_name = "_QFscalar_numeric_attributes_3Ex"} : (!fir.ref<f32>, !fir.dscope) -> (!fir.ref<f32>, !fir.ref<f32>) +! CHECK: %[[VAL_1:.*]] = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {{.*}} {fortran_attrs = #fir.var_attrs<intent_in>, uniq_name = "_QFscalar_numeric_attributes_3Ex"} : (!fir.ref<f32>, !fir.dscope) -> (!fir.ref<f32>, !fir.ref<f32>) subroutine scalar_numeric_attributes_4(x) logical(8), intent(out) :: x end subroutine ! CHECK-LABEL: func.func @_QPscalar_numeric_attributes_4( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.logical<8>> -! CHECK: %[[VAL_1:.*]] = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<intent_out>, uniq_name = "_QFscalar_numeric_attributes_4Ex"} : (!fir.ref<!fir.logical<8>>, !fir.dscope) -> (!fir.ref<!fir.logical<8>>, !fir.ref<!fir.logical<8>>) +! CHECK: %[[VAL_1:.*]] = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {{.*}} {fortran_attrs = #fir.var_attrs<intent_out>, uniq_name = "_QFscalar_numeric_attributes_4Ex"} : (!fir.ref<!fir.logical<8>>, !fir.dscope) -> (!fir.ref<!fir.logical<8>>, !fir.ref<!fir.logical<8>>) subroutine scalar_numeric_parameter() integer, parameter :: p = 42 diff --git a/flang/test/Lower/HLFIR/cray-pointers.f90 b/flang/test/Lower/HLFIR/cray-pointers.f90 index 6a5a3d1..082aa1e 100644 --- a/flang/test/Lower/HLFIR/cray-pointers.f90 +++ b/flang/test/Lower/HLFIR/cray-pointers.f90 @@ -62,8 +62,8 @@ end subroutine test3 ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<i64> {fir.bindc_name = "cp"}, ! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref<i32> {fir.bindc_name = "n"}) { ! CHECK: %[[VAL_2:.*]] = fir.alloca !fir.box<!fir.ptr<!fir.array<?x!fir.char<1,11>>>> -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFtest3En"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) -! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFtest3Ecp"} : (!fir.ref<i64>, !fir.dscope) -> (!fir.ref<i64>, !fir.ref<i64>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFtest3En"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFtest3Ecp"} : (!fir.ref<i64>, !fir.dscope) -> (!fir.ref<i64>, !fir.ref<i64>) ! CHECK: %[[VAL_5:.*]] = arith.constant 11 : index ! CHECK: %[[VAL_8:.*]] = arith.constant 11 : index ! CHECK: %[[VAL_24:.*]] = fir.shape_shift %{{.*}}, %{{.*}} : (index, index) -> !fir.shapeshift<1> @@ -88,7 +88,7 @@ end subroutine test4 ! CHECK-LABEL: func.func @_QPtest4( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<i32> {fir.bindc_name = "n"}) { ! CHECK: %[[VAL_1:.*]] = fir.alloca !fir.box<!fir.ptr<!fir.char<1,?>>> -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFtest4En"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFtest4En"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_3:.*]] = fir.alloca i64 {bindc_name = "cp", uniq_name = "_QFtest4Ecp"} ! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_3]] {uniq_name = "_QFtest4Ecp"} : (!fir.ref<i64>) -> (!fir.ref<i64>, !fir.ref<i64>) ! CHECK: %[[VAL_5:.*]] = fir.load %[[VAL_2]]#0 : !fir.ref<i32> @@ -153,7 +153,7 @@ end subroutine test6 ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<i32> {fir.bindc_name = "n"}) { ! CHECK: %[[VAL_1:.*]] = fir.alloca !fir.box<!fir.ptr<!fir.array<?xf32>>> ! CHECK: %[[VAL_2:.*]] = fir.alloca !fir.box<!fir.ptr<!fir.array<?x!fir.char<1,?>>>> -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFtest6En"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFtest6En"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_4:.*]] = fir.alloca i64 {bindc_name = "cp", uniq_name = "_QFtest6Ecp"} ! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_4]] {uniq_name = "_QFtest6Ecp"} : (!fir.ref<i64>) -> (!fir.ref<i64>, !fir.ref<i64>) ! CHECK: %[[VAL_8:.*]] = fir.load %[[VAL_3]]#0 : !fir.ref<i32> @@ -379,7 +379,7 @@ end subroutine ! CHECK-LABEL: func.func @_QPtest_craypointer_capture( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<i32> {fir.bindc_name = "n"}) { ! CHECK: %[[VAL_1:.*]] = fir.alloca !fir.box<!fir.ptr<!fir.char<1,?>>> -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFtest_craypointer_captureEn"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFtest_craypointer_captureEn"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_3:.*]] = fir.alloca i64 {bindc_name = "cray_pointer", uniq_name = "_QFtest_craypointer_captureEcray_pointer"} ! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_3]] {fortran_attrs = #fir.var_attrs<internal_assoc>, uniq_name = "_QFtest_craypointer_captureEcray_pointer"} : (!fir.ref<i64>) -> (!fir.ref<i64>, !fir.ref<i64>) ! CHECK: %[[VAL_5:.*]] = fir.load %[[VAL_2]]#0 : !fir.ref<i32> diff --git a/flang/test/Lower/HLFIR/cshift.f90 b/flang/test/Lower/HLFIR/cshift.f90 index c374306..64fd376 100644 --- a/flang/test/Lower/HLFIR/cshift.f90 +++ b/flang/test/Lower/HLFIR/cshift.f90 @@ -206,9 +206,9 @@ end subroutine ! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref<i32> {fir.bindc_name = "s"}, ! CHECK-SAME: %[[VAL_2:.*]]: !fir.ref<i32> {fir.bindc_name = "d"}) { ! CHECK: %[[VAL_3:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_3]] {uniq_name = "_QFcshift11Ea"} : (!fir.box<!fir.array<?xi32>>, !fir.dscope) -> (!fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>>) -! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_2]] dummy_scope %[[VAL_3]] {uniq_name = "_QFcshift11Ed"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) -! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %[[VAL_3]] {uniq_name = "_QFcshift11Es"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_3]] arg {{[0-9]+}} {uniq_name = "_QFcshift11Ea"} : (!fir.box<!fir.array<?xi32>>, !fir.dscope) -> (!fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>>) +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_2]] dummy_scope %[[VAL_3]] arg {{[0-9]+}} {uniq_name = "_QFcshift11Ed"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %[[VAL_3]] arg {{[0-9]+}} {uniq_name = "_QFcshift11Es"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_7:.*]] = arith.constant 2 : i32 ! CHECK: %[[VAL_8:.*]] = fir.load %[[VAL_5]]#0 : !fir.ref<i32> ! CHECK: %[[VAL_9:.*]] = hlfir.cshift %[[VAL_4]]#0 %[[VAL_7]] dim %[[VAL_8]] : (!fir.box<!fir.array<?xi32>>, i32, i32) -> !hlfir.expr<?xi32> diff --git a/flang/test/Lower/HLFIR/custom-intrinsic.f90 b/flang/test/Lower/HLFIR/custom-intrinsic.f90 index 5ec6e0a..4999eeb 100644 --- a/flang/test/Lower/HLFIR/custom-intrinsic.f90 +++ b/flang/test/Lower/HLFIR/custom-intrinsic.f90 @@ -8,8 +8,8 @@ end function ! CHECK-SAME: %[[A_ARG:.*]]: !fir.ref<i32> {fir.bindc_name = "a"} ! CHECK-SAME: %[[B_ARG:.*]]: !fir.ref<i32> {fir.bindc_name = "b"} ! CHECK-NEXT: %[[DSCOPE:.*]] = fir.dummy_scope : !fir.dscope -! CHECK-NEXT: %[[A_DECL:.*]]:2 = hlfir.declare %[[A_ARG]] dummy_scope %[[DSCOPE]] {uniq_name = "_QFmax_simpleEa"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) -! CHECK-NEXT: %[[B_DECL:.*]]:2 = hlfir.declare %[[B_ARG]] dummy_scope %[[DSCOPE]] {uniq_name = "_QFmax_simpleEb"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK-NEXT: %[[A_DECL:.*]]:2 = hlfir.declare %[[A_ARG]] dummy_scope %[[DSCOPE]] arg {{[0-9]+}} {uniq_name = "_QFmax_simpleEa"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK-NEXT: %[[B_DECL:.*]]:2 = hlfir.declare %[[B_ARG]] dummy_scope %[[DSCOPE]] arg {{[0-9]+}} {uniq_name = "_QFmax_simpleEb"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK-NEXT: %[[RES_ALLOC:.*]] = fir.alloca i32 {bindc_name = "max_simple", uniq_name = "_QFmax_simpleEmax_simple"} ! CHECK-NEXT: %[[RES_DECL:.*]]:2 = hlfir.declare %[[RES_ALLOC]] {uniq_name = "_QFmax_simpleEmax_simple"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK-NEXT: %[[A_LD:.*]] = fir.load %[[A_DECL]]#0 : !fir.ref<i32> @@ -30,9 +30,9 @@ end function ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<i32> {fir.bindc_name = "a"}, ! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref<i32> {fir.bindc_name = "b"}, ! CHECK-SAME: %[[VAL_2:.*]]: !fir.ref<i32> {fir.bindc_name = "c", fir.optional}) -> i32 { -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFmax_dynamic_optional_scalarEa"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) -! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFmax_dynamic_optional_scalarEb"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) -! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_2]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<optional>, uniq_name = "_QFmax_dynamic_optional_scalarEc"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFmax_dynamic_optional_scalarEa"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFmax_dynamic_optional_scalarEb"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_2]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<optional>, uniq_name = "_QFmax_dynamic_optional_scalarEc"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_6:.*]] = fir.alloca i32 {bindc_name = "max_dynamic_optional_scalar", uniq_name = "_QFmax_dynamic_optional_scalarEmax_dynamic_optional_scalar"} ! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_6]] {uniq_name = "_QFmax_dynamic_optional_scalarEmax_dynamic_optional_scalar"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_8:.*]] = fir.load %[[VAL_3]]#0 : !fir.ref<i32> @@ -63,10 +63,10 @@ end function ! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref<i32> {fir.bindc_name = "b"}, ! CHECK-SAME: %[[VAL_2:.*]]: !fir.ref<i32> {fir.bindc_name = "c", fir.optional}, ! CHECK-SAME: %[[VAL_3:.*]]: !fir.ref<i32> {fir.bindc_name = "d", fir.optional}) -> i32 { -! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFmax_dynamic_optional_scalar2Ea"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) -! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFmax_dynamic_optional_scalar2Eb"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) -! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_2]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<optional>, uniq_name = "_QFmax_dynamic_optional_scalar2Ec"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) -! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_3]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<optional>, uniq_name = "_QFmax_dynamic_optional_scalar2Ed"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFmax_dynamic_optional_scalar2Ea"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFmax_dynamic_optional_scalar2Eb"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_2]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<optional>, uniq_name = "_QFmax_dynamic_optional_scalar2Ec"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_3]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<optional>, uniq_name = "_QFmax_dynamic_optional_scalar2Ed"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_8:.*]] = fir.alloca i32 {bindc_name = "max_dynamic_optional_scalar2", uniq_name = "_QFmax_dynamic_optional_scalar2Emax_dynamic_optional_scalar2"} ! CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[VAL_8]] {uniq_name = "_QFmax_dynamic_optional_scalar2Emax_dynamic_optional_scalar2"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_10:.*]] = fir.load %[[VAL_4]]#0 : !fir.ref<i32> @@ -105,10 +105,10 @@ end function ! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref<!fir.array<42xi32>> {fir.bindc_name = "b"}) -> !fir.array<42xi32> { ! CHECK: %[[VAL_2:.*]] = arith.constant 42 : index ! CHECK: %[[VAL_3:.*]] = fir.shape %[[VAL_2]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_3]]) dummy_scope %{{[0-9]+}} {uniq_name = "_QFmax_arrayEa"} : (!fir.ref<!fir.array<42xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<42xi32>>, !fir.ref<!fir.array<42xi32>>) +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_3]]) dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFmax_arrayEa"} : (!fir.ref<!fir.array<42xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<42xi32>>, !fir.ref<!fir.array<42xi32>>) ! CHECK: %[[VAL_5:.*]] = arith.constant 42 : index ! CHECK: %[[VAL_6:.*]] = fir.shape %[[VAL_5]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_1]](%[[VAL_6]]) dummy_scope %{{[0-9]+}} {uniq_name = "_QFmax_arrayEb"} : (!fir.ref<!fir.array<42xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<42xi32>>, !fir.ref<!fir.array<42xi32>>) +! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_1]](%[[VAL_6]]) dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFmax_arrayEb"} : (!fir.ref<!fir.array<42xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<42xi32>>, !fir.ref<!fir.array<42xi32>>) ! CHECK: %[[VAL_8:.*]] = arith.constant 42 : index ! CHECK: %[[VAL_9:.*]] = fir.alloca !fir.array<42xi32> {bindc_name = "max_array", uniq_name = "_QFmax_arrayEmax_array"} ! CHECK: %[[VAL_10:.*]] = fir.shape %[[VAL_8]] : (index) -> !fir.shape<1> @@ -138,13 +138,13 @@ end function ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<i32> {fir.bindc_name = "a"}, ! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref<!fir.array<10xi32>> {fir.bindc_name = "b"}, ! CHECK-SAME: %[[VAL_2:.*]]: !fir.ref<!fir.array<10xi32>> {fir.bindc_name = "c", fir.optional}) -> !fir.array<10xi32> { -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFmax_dynamic_optional_arrayEa"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFmax_dynamic_optional_arrayEa"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_4:.*]] = arith.constant 10 : index ! CHECK: %[[VAL_5:.*]] = fir.shape %[[VAL_4]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_1]](%[[VAL_5]]) dummy_scope %{{[0-9]+}} {uniq_name = "_QFmax_dynamic_optional_arrayEb"} : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>) +! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_1]](%[[VAL_5]]) dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFmax_dynamic_optional_arrayEb"} : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>) ! CHECK: %[[VAL_7:.*]] = arith.constant 10 : index ! CHECK: %[[VAL_8:.*]] = fir.shape %[[VAL_7]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[VAL_2]](%[[VAL_8]]) dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<optional>, uniq_name = "_QFmax_dynamic_optional_arrayEc"} : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>) +! CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[VAL_2]](%[[VAL_8]]) dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<optional>, uniq_name = "_QFmax_dynamic_optional_arrayEc"} : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>) ! CHECK: %[[VAL_10:.*]] = arith.constant 10 : index ! CHECK: %[[VAL_11:.*]] = fir.alloca !fir.array<10xi32> {bindc_name = "max_dynamic_optional_array", uniq_name = "_QFmax_dynamic_optional_arrayEmax_dynamic_optional_array"} ! CHECK: %[[VAL_12:.*]] = fir.shape %[[VAL_10]] : (index) -> !fir.shape<1> @@ -181,8 +181,8 @@ end function ! CHECK-LABEL: func.func @_QPmin_simple( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<i32> {fir.bindc_name = "a"}, ! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref<i32> {fir.bindc_name = "b"}) -> i32 { -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFmin_simpleEa"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFmin_simpleEb"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFmin_simpleEa"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFmin_simpleEb"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_4:.*]] = fir.alloca i32 {bindc_name = "min_simple", uniq_name = "_QFmin_simpleEmin_simple"} ! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_4]] {uniq_name = "_QFmin_simpleEmin_simple"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_6:.*]] = fir.load %[[VAL_2]]#0 : !fir.ref<i32> @@ -203,9 +203,9 @@ end function ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<i32> {fir.bindc_name = "a"}, ! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref<i32> {fir.bindc_name = "b"}, ! CHECK-SAME: %[[VAL_2:.*]]: !fir.ref<i32> {fir.bindc_name = "c", fir.optional}) -> i32 { -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFmin_dynamic_optional_scalarEa"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) -! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFmin_dynamic_optional_scalarEb"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) -! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_2]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<optional>, uniq_name = "_QFmin_dynamic_optional_scalarEc"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFmin_dynamic_optional_scalarEa"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFmin_dynamic_optional_scalarEb"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_2]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<optional>, uniq_name = "_QFmin_dynamic_optional_scalarEc"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_6:.*]] = fir.alloca i32 {bindc_name = "min_dynamic_optional_scalar", uniq_name = "_QFmin_dynamic_optional_scalarEmin_dynamic_optional_scalar"} ! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_6]] {uniq_name = "_QFmin_dynamic_optional_scalarEmin_dynamic_optional_scalar"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_8:.*]] = fir.load %[[VAL_3]]#0 : !fir.ref<i32> @@ -236,10 +236,10 @@ end function ! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref<i32> {fir.bindc_name = "b"}, ! CHECK-SAME: %[[VAL_2:.*]]: !fir.ref<i32> {fir.bindc_name = "c", fir.optional}, ! CHECK-SAME: %[[VAL_3:.*]]: !fir.ref<i32> {fir.bindc_name = "d", fir.optional}) -> i32 { -! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFmin_dynamic_optional_scalar2Ea"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) -! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFmin_dynamic_optional_scalar2Eb"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) -! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_2]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<optional>, uniq_name = "_QFmin_dynamic_optional_scalar2Ec"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) -! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_3]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<optional>, uniq_name = "_QFmin_dynamic_optional_scalar2Ed"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFmin_dynamic_optional_scalar2Ea"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFmin_dynamic_optional_scalar2Eb"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_2]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<optional>, uniq_name = "_QFmin_dynamic_optional_scalar2Ec"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_3]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<optional>, uniq_name = "_QFmin_dynamic_optional_scalar2Ed"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_8:.*]] = fir.alloca i32 {bindc_name = "min_dynamic_optional_scalar2", uniq_name = "_QFmin_dynamic_optional_scalar2Emin_dynamic_optional_scalar2"} ! CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[VAL_8]] {uniq_name = "_QFmin_dynamic_optional_scalar2Emin_dynamic_optional_scalar2"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_10:.*]] = fir.load %[[VAL_4]]#0 : !fir.ref<i32> @@ -278,10 +278,10 @@ end function ! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref<!fir.array<42xi32>> {fir.bindc_name = "b"}) -> !fir.array<42xi32> { ! CHECK: %[[VAL_2:.*]] = arith.constant 42 : index ! CHECK: %[[VAL_3:.*]] = fir.shape %[[VAL_2]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_3]]) dummy_scope %{{[0-9]+}} {uniq_name = "_QFmin_arrayEa"} : (!fir.ref<!fir.array<42xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<42xi32>>, !fir.ref<!fir.array<42xi32>>) +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_3]]) dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFmin_arrayEa"} : (!fir.ref<!fir.array<42xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<42xi32>>, !fir.ref<!fir.array<42xi32>>) ! CHECK: %[[VAL_5:.*]] = arith.constant 42 : index ! CHECK: %[[VAL_6:.*]] = fir.shape %[[VAL_5]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_1]](%[[VAL_6]]) dummy_scope %{{[0-9]+}} {uniq_name = "_QFmin_arrayEb"} : (!fir.ref<!fir.array<42xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<42xi32>>, !fir.ref<!fir.array<42xi32>>) +! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_1]](%[[VAL_6]]) dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFmin_arrayEb"} : (!fir.ref<!fir.array<42xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<42xi32>>, !fir.ref<!fir.array<42xi32>>) ! CHECK: %[[VAL_8:.*]] = arith.constant 42 : index ! CHECK: %[[VAL_9:.*]] = fir.alloca !fir.array<42xi32> {bindc_name = "min_array", uniq_name = "_QFmin_arrayEmin_array"} ! CHECK: %[[VAL_10:.*]] = fir.shape %[[VAL_8]] : (index) -> !fir.shape<1> @@ -311,13 +311,13 @@ end function ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<i32> {fir.bindc_name = "a"}, ! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref<!fir.array<10xi32>> {fir.bindc_name = "b"}, ! CHECK-SAME: %[[VAL_2:.*]]: !fir.ref<!fir.array<10xi32>> {fir.bindc_name = "c", fir.optional}) -> !fir.array<10xi32> { -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFmin_dynamic_optional_arrayEa"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFmin_dynamic_optional_arrayEa"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_4:.*]] = arith.constant 10 : index ! CHECK: %[[VAL_5:.*]] = fir.shape %[[VAL_4]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_1]](%[[VAL_5]]) dummy_scope %{{[0-9]+}} {uniq_name = "_QFmin_dynamic_optional_arrayEb"} : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>) +! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_1]](%[[VAL_5]]) dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFmin_dynamic_optional_arrayEb"} : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>) ! CHECK: %[[VAL_7:.*]] = arith.constant 10 : index ! CHECK: %[[VAL_8:.*]] = fir.shape %[[VAL_7]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[VAL_2]](%[[VAL_8]]) dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<optional>, uniq_name = "_QFmin_dynamic_optional_arrayEc"} : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>) +! CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[VAL_2]](%[[VAL_8]]) dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<optional>, uniq_name = "_QFmin_dynamic_optional_arrayEc"} : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>) ! CHECK: %[[VAL_10:.*]] = arith.constant 10 : index ! CHECK: %[[VAL_11:.*]] = fir.alloca !fir.array<10xi32> {bindc_name = "min_dynamic_optional_array", uniq_name = "_QFmin_dynamic_optional_arrayEmin_dynamic_optional_array"} ! CHECK: %[[VAL_12:.*]] = fir.shape %[[VAL_10]] : (index) -> !fir.shape<1> @@ -356,7 +356,7 @@ end function ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.ptr<i32>>> {fir.bindc_name = "pointer"}) -> !fir.logical<4> { ! CHECK: %[[VAL_1:.*]] = fir.alloca !fir.logical<4> {bindc_name = "associated_simple", uniq_name = "_QFassociated_simpleEassociated_simple"} ! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "_QFassociated_simpleEassociated_simple"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFassociated_simpleEpointer"} : (!fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.ref<!fir.box<!fir.ptr<i32>>>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFassociated_simpleEpointer"} : (!fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.ref<!fir.box<!fir.ptr<i32>>>) ! CHECK: %[[VAL_4:.*]] = fir.load %[[VAL_3]]#0 : !fir.ref<!fir.box<!fir.ptr<i32>>> ! CHECK: %[[VAL_5:.*]] = fir.box_addr %[[VAL_4]] : (!fir.box<!fir.ptr<i32>>) -> !fir.ptr<i32> ! CHECK: %[[VAL_6:.*]] = fir.convert %[[VAL_5]] : (!fir.ptr<i32>) -> i64 @@ -379,8 +379,8 @@ end function ! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref<i32> {fir.bindc_name = "target", fir.target}) -> !fir.logical<4> { ! CHECK: %[[VAL_2:.*]] = fir.alloca !fir.logical<4> {bindc_name = "associated_target", uniq_name = "_QFassociated_targetEassociated_target"} ! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]] {uniq_name = "_QFassociated_targetEassociated_target"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) -! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFassociated_targetEpointer"} : (!fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.ref<!fir.box<!fir.ptr<i32>>>) -! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<target>, uniq_name = "_QFassociated_targetEtarget"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFassociated_targetEpointer"} : (!fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.ref<!fir.box<!fir.ptr<i32>>>) +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<target>, uniq_name = "_QFassociated_targetEtarget"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_6:.*]] = fir.embox %[[VAL_5]]#0 : (!fir.ref<i32>) -> !fir.box<i32> ! CHECK: %[[VAL_7:.*]] = fir.load %[[VAL_4]]#0 : !fir.ref<!fir.box<!fir.ptr<i32>>> ! CHECK: %[[VAL_8:.*]] = fir.convert %[[VAL_7]] : (!fir.box<!fir.ptr<i32>>) -> !fir.box<none> @@ -403,8 +403,8 @@ end function ! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref<!fir.box<!fir.ptr<i32>>> {fir.bindc_name = "target"}) -> !fir.logical<4> { ! CHECK: %[[VAL_2:.*]] = fir.alloca !fir.logical<4> {bindc_name = "associated_pointer", uniq_name = "_QFassociated_pointerEassociated_pointer"} ! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]] {uniq_name = "_QFassociated_pointerEassociated_pointer"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) -! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFassociated_pointerEpointer"} : (!fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.ref<!fir.box<!fir.ptr<i32>>>) -! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFassociated_pointerEtarget"} : (!fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.ref<!fir.box<!fir.ptr<i32>>>) +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFassociated_pointerEpointer"} : (!fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.ref<!fir.box<!fir.ptr<i32>>>) +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFassociated_pointerEtarget"} : (!fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.ref<!fir.box<!fir.ptr<i32>>>) ! CHECK: %[[VAL_6:.*]] = fir.load %[[VAL_5]]#0 : !fir.ref<!fir.box<!fir.ptr<i32>>> ! CHECK: %[[VAL_7:.*]] = fir.load %[[VAL_4]]#0 : !fir.ref<!fir.box<!fir.ptr<i32>>> ! CHECK: %[[VAL_8:.*]] = fir.convert %[[VAL_7]] : (!fir.box<!fir.ptr<i32>>) -> !fir.box<none> @@ -427,8 +427,8 @@ end function ! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>> {fir.bindc_name = "target"}) -> !fir.logical<4> { ! CHECK: %[[VAL_2:.*]] = fir.alloca !fir.logical<4> {bindc_name = "associated_array", uniq_name = "_QFassociated_arrayEassociated_array"} ! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]] {uniq_name = "_QFassociated_arrayEassociated_array"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) -! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFassociated_arrayEpointer"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>) -! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFassociated_arrayEtarget"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>) +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFassociated_arrayEpointer"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>) +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFassociated_arrayEtarget"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>) ! CHECK: %[[VAL_6:.*]] = fir.load %[[VAL_5]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>> ! CHECK: %[[VAL_7:.*]] = fir.load %[[VAL_4]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>> ! CHECK: %[[VAL_8:.*]] = fir.convert %[[VAL_7]] : (!fir.box<!fir.ptr<!fir.array<?xi32>>>) -> !fir.box<none> @@ -448,11 +448,11 @@ end function ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<i32> {fir.bindc_name = "i"}, ! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref<i32> {fir.bindc_name = "shift"}, ! CHECK-SAME: %[[VAL_2:.*]]: !fir.ref<i32> {fir.bindc_name = "size"}) -> i32 { -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFishftc_simpleEi"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFishftc_simpleEi"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_4:.*]] = fir.alloca i32 {bindc_name = "ishftc_simple", uniq_name = "_QFishftc_simpleEishftc_simple"} ! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_4]] {uniq_name = "_QFishftc_simpleEishftc_simple"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) -! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFishftc_simpleEshift"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) -! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_2]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFishftc_simpleEsize"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFishftc_simpleEshift"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_2]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFishftc_simpleEsize"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_8:.*]] = fir.load %[[VAL_3]]#0 : !fir.ref<i32> ! CHECK: %[[VAL_9:.*]] = fir.load %[[VAL_6]]#0 : !fir.ref<i32> ! CHECK: %[[VAL_10:.*]] = fir.load %[[VAL_7]]#0 : !fir.ref<i32> @@ -499,11 +499,11 @@ end function ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<i32> {fir.bindc_name = "i"}, ! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref<i32> {fir.bindc_name = "shift"}, ! CHECK-SAME: %[[VAL_2:.*]]: !fir.ref<i32> {fir.bindc_name = "size", fir.optional}) -> i32 { -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFishftc_dynamically_optional_scalarEi"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFishftc_dynamically_optional_scalarEi"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_4:.*]] = fir.alloca i32 {bindc_name = "ishftc_dynamically_optional_scalar", uniq_name = "_QFishftc_dynamically_optional_scalarEishftc_dynamically_optional_scalar"} ! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_4]] {uniq_name = "_QFishftc_dynamically_optional_scalarEishftc_dynamically_optional_scalar"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) -! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFishftc_dynamically_optional_scalarEshift"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) -! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_2]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<optional>, uniq_name = "_QFishftc_dynamically_optional_scalarEsize"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFishftc_dynamically_optional_scalarEshift"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_2]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<optional>, uniq_name = "_QFishftc_dynamically_optional_scalarEsize"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_8:.*]] = fir.load %[[VAL_3]]#0 : !fir.ref<i32> ! CHECK: %[[VAL_9:.*]] = fir.load %[[VAL_6]]#0 : !fir.ref<i32> ! CHECK: %[[VAL_10:.*]] = fir.is_present %[[VAL_7]]#0 : (!fir.ref<i32>) -> i1 @@ -558,17 +558,17 @@ end function ! CHECK-SAME: %[[VAL_2:.*]]: !fir.ref<!fir.array<42xi32>> {fir.bindc_name = "size"}) -> !fir.array<42xi32> { ! CHECK: %[[VAL_3:.*]] = arith.constant 42 : index ! CHECK: %[[VAL_4:.*]] = fir.shape %[[VAL_3]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_4]]) dummy_scope %{{[0-9]+}} {uniq_name = "_QFishftc_arrayEi"} : (!fir.ref<!fir.array<42xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<42xi32>>, !fir.ref<!fir.array<42xi32>>) +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_4]]) dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFishftc_arrayEi"} : (!fir.ref<!fir.array<42xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<42xi32>>, !fir.ref<!fir.array<42xi32>>) ! CHECK: %[[VAL_6:.*]] = arith.constant 42 : index ! CHECK: %[[VAL_7:.*]] = fir.alloca !fir.array<42xi32> {bindc_name = "ishftc_array", uniq_name = "_QFishftc_arrayEishftc_array"} ! CHECK: %[[VAL_8:.*]] = fir.shape %[[VAL_6]] : (index) -> !fir.shape<1> ! CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[VAL_7]](%[[VAL_8]]) {uniq_name = "_QFishftc_arrayEishftc_array"} : (!fir.ref<!fir.array<42xi32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<42xi32>>, !fir.ref<!fir.array<42xi32>>) ! CHECK: %[[VAL_10:.*]] = arith.constant 42 : index ! CHECK: %[[VAL_11:.*]] = fir.shape %[[VAL_10]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_12:.*]]:2 = hlfir.declare %[[VAL_1]](%[[VAL_11]]) dummy_scope %{{[0-9]+}} {uniq_name = "_QFishftc_arrayEshift"} : (!fir.ref<!fir.array<42xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<42xi32>>, !fir.ref<!fir.array<42xi32>>) +! CHECK: %[[VAL_12:.*]]:2 = hlfir.declare %[[VAL_1]](%[[VAL_11]]) dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFishftc_arrayEshift"} : (!fir.ref<!fir.array<42xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<42xi32>>, !fir.ref<!fir.array<42xi32>>) ! CHECK: %[[VAL_13:.*]] = arith.constant 42 : index ! CHECK: %[[VAL_14:.*]] = fir.shape %[[VAL_13]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_15:.*]]:2 = hlfir.declare %[[VAL_2]](%[[VAL_14]]) dummy_scope %{{[0-9]+}} {uniq_name = "_QFishftc_arrayEsize"} : (!fir.ref<!fir.array<42xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<42xi32>>, !fir.ref<!fir.array<42xi32>>) +! CHECK: %[[VAL_15:.*]]:2 = hlfir.declare %[[VAL_2]](%[[VAL_14]]) dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFishftc_arrayEsize"} : (!fir.ref<!fir.array<42xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<42xi32>>, !fir.ref<!fir.array<42xi32>>) ! CHECK: %[[VAL_16:.*]] = hlfir.elemental %[[VAL_4]] unordered : (!fir.shape<1>) -> !hlfir.expr<42xi32> { ! CHECK: ^bb0(%[[VAL_17:.*]]: index): ! CHECK: %[[VAL_18:.*]] = hlfir.designate %[[VAL_5]]#0 (%[[VAL_17]]) : (!fir.ref<!fir.array<42xi32>>, index) -> !fir.ref<i32> @@ -625,13 +625,13 @@ end function ! CHECK-SAME: %[[VAL_2:.*]]: !fir.ref<i32> {fir.bindc_name = "size", fir.optional}) -> !fir.array<42xi32> { ! CHECK: %[[VAL_3:.*]] = arith.constant 42 : index ! CHECK: %[[VAL_4:.*]] = fir.shape %[[VAL_3]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_4]]) dummy_scope %{{[0-9]+}} {uniq_name = "_QFishftc_dynamically_optional_arrayEi"} : (!fir.ref<!fir.array<42xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<42xi32>>, !fir.ref<!fir.array<42xi32>>) +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_4]]) dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFishftc_dynamically_optional_arrayEi"} : (!fir.ref<!fir.array<42xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<42xi32>>, !fir.ref<!fir.array<42xi32>>) ! CHECK: %[[VAL_6:.*]] = arith.constant 42 : index ! CHECK: %[[VAL_7:.*]] = fir.alloca !fir.array<42xi32> {bindc_name = "ishftc_dynamically_optional_array", uniq_name = "_QFishftc_dynamically_optional_arrayEishftc_dynamically_optional_array"} ! CHECK: %[[VAL_8:.*]] = fir.shape %[[VAL_6]] : (index) -> !fir.shape<1> ! CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[VAL_7]](%[[VAL_8]]) {uniq_name = "_QFishftc_dynamically_optional_arrayEishftc_dynamically_optional_array"} : (!fir.ref<!fir.array<42xi32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<42xi32>>, !fir.ref<!fir.array<42xi32>>) -! CHECK: %[[VAL_10:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFishftc_dynamically_optional_arrayEshift"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) -! CHECK: %[[VAL_11:.*]]:2 = hlfir.declare %[[VAL_2]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<optional>, uniq_name = "_QFishftc_dynamically_optional_arrayEsize"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_10:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFishftc_dynamically_optional_arrayEshift"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_11:.*]]:2 = hlfir.declare %[[VAL_2]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<optional>, uniq_name = "_QFishftc_dynamically_optional_arrayEsize"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_12:.*]] = fir.is_present %[[VAL_11]]#0 : (!fir.ref<i32>) -> i1 ! CHECK: %[[VAL_13:.*]] = fir.load %[[VAL_10]]#0 : !fir.ref<i32> ! CHECK: %[[VAL_14:.*]] = hlfir.elemental %[[VAL_4]] unordered : (!fir.shape<1>) -> !hlfir.expr<42xi32> { @@ -699,9 +699,9 @@ end subroutine ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.heap<!fir.array<?x?x?xi32>>>> {fir.bindc_name = "a"}, ! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref<!fir.box<!fir.heap<!fir.array<?x?x?xi32>>>> {fir.bindc_name = "b"}, ! CHECK-SAME: %[[VAL_2:.*]]: !fir.ref<!fir.box<!fir.heap<!fir.array<?x?x?xi32>>>> {fir.bindc_name = "c"}) { -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFallocatables_testEa"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?x?x?xi32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?x?x?xi32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?x?x?xi32>>>>) -! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFallocatables_testEb"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?x?x?xi32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?x?x?xi32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?x?x?xi32>>>>) -! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_2]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFallocatables_testEc"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?x?x?xi32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?x?x?xi32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?x?x?xi32>>>>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFallocatables_testEa"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?x?x?xi32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?x?x?xi32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?x?x?xi32>>>>) +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFallocatables_testEb"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?x?x?xi32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?x?x?xi32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?x?x?xi32>>>>) +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_2]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFallocatables_testEc"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?x?x?xi32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?x?x?xi32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?x?x?xi32>>>>) ! CHECK: %[[VAL_6:.*]] = fir.address_of(@_QFallocatables_testECnx) : !fir.ref<i32> ! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_6]] {fortran_attrs = #fir.var_attrs<parameter>, uniq_name = "_QFallocatables_testECnx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_8:.*]] = fir.address_of(@_QFallocatables_testECny) : !fir.ref<i32> diff --git a/flang/test/Lower/HLFIR/designators-component-ref.f90 b/flang/test/Lower/HLFIR/designators-component-ref.f90 index 935176b..e6bb9c3 100644 --- a/flang/test/Lower/HLFIR/designators-component-ref.f90 +++ b/flang/test/Lower/HLFIR/designators-component-ref.f90 @@ -350,7 +350,7 @@ subroutine test_scalar_array_complex_chain(a) type(t_complex) :: a print *, a%array_comp%im ! CHECK-LABEL: func.func @_QPtest_scalar_array_complex_chain( -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFtest_scalar_array_complex_chainEa"} : (!fir.ref<!fir.type<_QMcomp_refTt_complex{array_comp:!fir.array<10x20xcomplex<f32>>}>>, !fir.dscope) -> (!fir.ref<!fir.type<_QMcomp_refTt_complex{array_comp:!fir.array<10x20xcomplex<f32>>}>>, !fir.ref<!fir.type<_QMcomp_refTt_complex{array_comp:!fir.array<10x20xcomplex<f32>>}>>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFtest_scalar_array_complex_chainEa"} : (!fir.ref<!fir.type<_QMcomp_refTt_complex{array_comp:!fir.array<10x20xcomplex<f32>>}>>, !fir.dscope) -> (!fir.ref<!fir.type<_QMcomp_refTt_complex{array_comp:!fir.array<10x20xcomplex<f32>>}>>, !fir.ref<!fir.type<_QMcomp_refTt_complex{array_comp:!fir.array<10x20xcomplex<f32>>}>>) ! CHECK: %[[VAL_7:.*]] = arith.constant 10 : index ! CHECK: %[[VAL_8:.*]] = arith.constant 20 : index ! CHECK: %[[VAL_9:.*]] = arith.constant 2 : index @@ -389,13 +389,13 @@ end subroutine test_poly_array_vector_subscript ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.class<!fir.ptr<!fir.array<?x!fir.type<_QMcomp_refTt1{scalar_i:i32,scalar_x:f32}>>>>> {fir.bindc_name = "p"}, ! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref<!fir.array<3xi32>> {fir.bindc_name = "v"}, ! CHECK-SAME: %[[VAL_2:.*]]: !fir.ref<!fir.array<3xi32>> {fir.bindc_name = "r"}) { -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFtest_poly_array_vector_subscriptEp"} : (!fir.ref<!fir.class<!fir.ptr<!fir.array<?x!fir.type<_QMcomp_refTt1{scalar_i:i32,scalar_x:f32}>>>>>, !fir.dscope) -> (!fir.ref<!fir.class<!fir.ptr<!fir.array<?x!fir.type<_QMcomp_refTt1{scalar_i:i32,scalar_x:f32}>>>>>, !fir.ref<!fir.class<!fir.ptr<!fir.array<?x!fir.type<_QMcomp_refTt1{scalar_i:i32,scalar_x:f32}>>>>>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFtest_poly_array_vector_subscriptEp"} : (!fir.ref<!fir.class<!fir.ptr<!fir.array<?x!fir.type<_QMcomp_refTt1{scalar_i:i32,scalar_x:f32}>>>>>, !fir.dscope) -> (!fir.ref<!fir.class<!fir.ptr<!fir.array<?x!fir.type<_QMcomp_refTt1{scalar_i:i32,scalar_x:f32}>>>>>, !fir.ref<!fir.class<!fir.ptr<!fir.array<?x!fir.type<_QMcomp_refTt1{scalar_i:i32,scalar_x:f32}>>>>>) ! CHECK: %[[VAL_4:.*]] = arith.constant 3 : index ! CHECK: %[[VAL_5:.*]] = fir.shape %[[VAL_4]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_2]](%[[VAL_5]]) dummy_scope %{{[0-9]+}} {uniq_name = "_QFtest_poly_array_vector_subscriptEr"} : (!fir.ref<!fir.array<3xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<3xi32>>, !fir.ref<!fir.array<3xi32>>) +! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_2]](%[[VAL_5]]) dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFtest_poly_array_vector_subscriptEr"} : (!fir.ref<!fir.array<3xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<3xi32>>, !fir.ref<!fir.array<3xi32>>) ! CHECK: %[[VAL_7:.*]] = arith.constant 3 : index ! CHECK: %[[VAL_8:.*]] = fir.shape %[[VAL_7]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[VAL_1]](%[[VAL_8]]) dummy_scope %{{[0-9]+}} {uniq_name = "_QFtest_poly_array_vector_subscriptEv"} : (!fir.ref<!fir.array<3xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<3xi32>>, !fir.ref<!fir.array<3xi32>>) +! CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[VAL_1]](%[[VAL_8]]) dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFtest_poly_array_vector_subscriptEv"} : (!fir.ref<!fir.array<3xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<3xi32>>, !fir.ref<!fir.array<3xi32>>) ! CHECK: %[[VAL_10:.*]] = fir.load %[[VAL_3]]#0 : !fir.ref<!fir.class<!fir.ptr<!fir.array<?x!fir.type<_QMcomp_refTt1{scalar_i:i32,scalar_x:f32}>>>>> ! CHECK: %[[VAL_11:.*]] = hlfir.elemental %[[VAL_8]] unordered : (!fir.shape<1>) -> !hlfir.expr<3xi64> { ! CHECK: ^bb0(%[[VAL_12:.*]]: index): diff --git a/flang/test/Lower/HLFIR/designators.f90 b/flang/test/Lower/HLFIR/designators.f90 index cb1cab3..6e7ee6d 100644 --- a/flang/test/Lower/HLFIR/designators.f90 +++ b/flang/test/Lower/HLFIR/designators.f90 @@ -7,8 +7,8 @@ subroutine array_ref(x, n) print *, x(n) end subroutine ! CHECK-LABEL: func.func @_QParray_ref( -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %{{[0-9]+}} {uniq_name = "_QFarray_refEn"} : (!fir.ref<i64>, !fir.dscope) -> (!fir.ref<i64>, !fir.ref<i64>) -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %{{[0-9]+}} {uniq_name = "_QFarray_refEx"} : (!fir.box<!fir.array<?xf32>>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.box<!fir.array<?xf32>>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFarray_refEn"} : (!fir.ref<i64>, !fir.dscope) -> (!fir.ref<i64>, !fir.ref<i64>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFarray_refEx"} : (!fir.box<!fir.array<?xf32>>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.box<!fir.array<?xf32>>) ! CHECK: %[[VAL_9:.*]] = fir.load %[[VAL_2]]#0 : !fir.ref<i64> ! CHECK: %[[VAL_10:.*]] = hlfir.designate %[[VAL_3]]#0 (%[[VAL_9]]) : (!fir.box<!fir.array<?xf32>>, i64) -> !fir.ref<f32> @@ -17,8 +17,8 @@ subroutine char_array_ref(x, n) print *, x(10) end subroutine ! CHECK-LABEL: func.func @_QPchar_array_ref( -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %{{[0-9]+}} {uniq_name = "_QFchar_array_refEn"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %{{[0-9]+}} {uniq_name = "_QFchar_array_refEx"} : (!fir.box<!fir.array<?x!fir.char<1,?>>>, !fir.dscope) -> (!fir.box<!fir.array<?x!fir.char<1,?>>>, !fir.box<!fir.array<?x!fir.char<1,?>>>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFchar_array_refEn"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFchar_array_refEx"} : (!fir.box<!fir.array<?x!fir.char<1,?>>>, !fir.dscope) -> (!fir.box<!fir.array<?x!fir.char<1,?>>>, !fir.box<!fir.array<?x!fir.char<1,?>>>) ! CHECK: %[[VAL_9:.*]] = fir.box_elesize %[[VAL_3]]#1 : (!fir.box<!fir.array<?x!fir.char<1,?>>>) -> index ! CHECK: %[[VAL_10:.*]] = arith.constant 10 : index ! CHECK: %[[VAL_11:.*]] = hlfir.designate %[[VAL_3]]#0 (%[[VAL_10]]) typeparams %[[VAL_9]] : (!fir.box<!fir.array<?x!fir.char<1,?>>>, index, index) -> !fir.boxchar<1> @@ -28,9 +28,9 @@ subroutine char_array_ref_cst_len(x, n) print *, x(10) end subroutine ! CHECK-LABEL: func.func @_QPchar_array_ref_cst_len( -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %{{[0-9]+}} {uniq_name = "_QFchar_array_ref_cst_lenEn"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFchar_array_ref_cst_lenEn"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_3:.*]] = arith.constant 5 : index -! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %{{.*}} typeparams %[[VAL_3]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFchar_array_ref_cst_lenEx"} : (!fir.box<!fir.array<?x!fir.char<1,5>>>, index, !fir.dscope) -> (!fir.box<!fir.array<?x!fir.char<1,5>>>, !fir.box<!fir.array<?x!fir.char<1,5>>>) +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %{{.*}} typeparams %[[VAL_3]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFchar_array_ref_cst_lenEx"} : (!fir.box<!fir.array<?x!fir.char<1,5>>>, index, !fir.dscope) -> (!fir.box<!fir.array<?x!fir.char<1,5>>>, !fir.box<!fir.array<?x!fir.char<1,5>>>) ! CHECK: %[[VAL_10:.*]] = arith.constant 10 : index ! CHECK: %[[VAL_11:.*]] = hlfir.designate %[[VAL_4]]#0 (%[[VAL_10]]) typeparams %[[VAL_3]] : (!fir.box<!fir.array<?x!fir.char<1,5>>>, index, index) -> !fir.ref<!fir.char<1,5>> @@ -41,7 +41,7 @@ end subroutine ! CHECK-LABEL: func.func @_QParray_section( ! CHECK: %[[VAL_1:.*]] = arith.constant 10 : index ! CHECK: %[[VAL_2:.*]] = fir.shape %[[VAL_1]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %{{.*}}(%[[VAL_2]]) dummy_scope %{{[0-9]+}} {uniq_name = "_QFarray_sectionEx"} : (!fir.ref<!fir.array<10xf32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<10xf32>>, !fir.ref<!fir.array<10xf32>>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %{{.*}}(%[[VAL_2]]) dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFarray_sectionEx"} : (!fir.ref<!fir.array<10xf32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<10xf32>>, !fir.ref<!fir.array<10xf32>>) ! CHECK: %[[VAL_9:.*]] = arith.constant 2 : index ! CHECK: %[[VAL_10:.*]] = arith.constant 8 : index ! CHECK: %[[VAL_11:.*]] = arith.constant 3 : index @@ -55,8 +55,8 @@ subroutine array_section_2(x, n) print *, x(n::3) end subroutine ! CHECK-LABEL: func.func @_QParray_section_2( -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %{{[0-9]+}} {uniq_name = "_QFarray_section_2En"} : (!fir.ref<i64>, !fir.dscope) -> (!fir.ref<i64>, !fir.ref<i64>) -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %{{[0-9]+}} {uniq_name = "_QFarray_section_2Ex"} : (!fir.box<!fir.array<?xf32>>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.box<!fir.array<?xf32>>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFarray_section_2En"} : (!fir.ref<i64>, !fir.dscope) -> (!fir.ref<i64>, !fir.ref<i64>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFarray_section_2Ex"} : (!fir.box<!fir.array<?xf32>>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.box<!fir.array<?xf32>>) ! CHECK: %[[VAL_9:.*]] = fir.load %[[VAL_2]]#0 : !fir.ref<i64> ! CHECK: %[[VAL_10:.*]] = arith.constant 0 : index ! CHECK: %[[VAL_11:.*]]:3 = fir.box_dims %[[VAL_3]]#1, %[[VAL_10]] : (!fir.box<!fir.array<?xf32>>, index) -> (index, index, index) @@ -76,8 +76,8 @@ subroutine char_array_section(x, n) print *, x(::3) end subroutine ! CHECK-LABEL: func.func @_QPchar_array_section( -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %{{[0-9]+}} {uniq_name = "_QFchar_array_sectionEn"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %{{[0-9]+}} {uniq_name = "_QFchar_array_sectionEx"} : (!fir.box<!fir.array<?x!fir.char<1,?>>>, !fir.dscope) -> (!fir.box<!fir.array<?x!fir.char<1,?>>>, !fir.box<!fir.array<?x!fir.char<1,?>>>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFchar_array_sectionEn"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFchar_array_sectionEx"} : (!fir.box<!fir.array<?x!fir.char<1,?>>>, !fir.dscope) -> (!fir.box<!fir.array<?x!fir.char<1,?>>>, !fir.box<!fir.array<?x!fir.char<1,?>>>) ! CHECK: %[[VAL_9:.*]] = fir.box_elesize %[[VAL_3]]#1 : (!fir.box<!fir.array<?x!fir.char<1,?>>>) -> index ! CHECK: %[[VAL_10:.*]] = arith.constant 1 : index ! CHECK: %[[VAL_11:.*]] = arith.constant 0 : index @@ -97,9 +97,9 @@ subroutine char_array_section_cst_len(x, n) print *, x(::3) end subroutine ! CHECK-LABEL: func.func @_QPchar_array_section_cst_len( -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %{{[0-9]+}} {uniq_name = "_QFchar_array_section_cst_lenEn"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFchar_array_section_cst_lenEn"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_3:.*]] = arith.constant 5 : index -! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %{{.*}} typeparams %[[VAL_3]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFchar_array_section_cst_lenEx"} : (!fir.box<!fir.array<?x!fir.char<1,5>>>, index, !fir.dscope) -> (!fir.box<!fir.array<?x!fir.char<1,5>>>, !fir.box<!fir.array<?x!fir.char<1,5>>>) +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %{{.*}} typeparams %[[VAL_3]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFchar_array_section_cst_lenEx"} : (!fir.box<!fir.array<?x!fir.char<1,5>>>, index, !fir.dscope) -> (!fir.box<!fir.array<?x!fir.char<1,5>>>, !fir.box<!fir.array<?x!fir.char<1,5>>>) ! CHECK: %[[VAL_10:.*]] = arith.constant 1 : index ! CHECK: %[[VAL_11:.*]] = arith.constant 0 : index ! CHECK: %[[VAL_12:.*]]:3 = fir.box_dims %[[VAL_4]]#1, %[[VAL_11]] : (!fir.box<!fir.array<?x!fir.char<1,5>>>, index) -> (index, index, index) @@ -120,7 +120,7 @@ subroutine complex_imag_ref(x) print *, x%im end subroutine ! CHECK-LABEL: func.func @_QPcomplex_imag_ref( -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %{{[0-9]+}} {uniq_name = "_QFcomplex_imag_refEx"} : (!fir.box<!fir.array<?xcomplex<f32>>>, !fir.dscope) -> (!fir.box<!fir.array<?xcomplex<f32>>>, !fir.box<!fir.array<?xcomplex<f32>>>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFcomplex_imag_refEx"} : (!fir.box<!fir.array<?xcomplex<f32>>>, !fir.dscope) -> (!fir.box<!fir.array<?xcomplex<f32>>>, !fir.box<!fir.array<?xcomplex<f32>>>) ! CHECK: %[[VAL_3:.*]] = fir.shape %[[VAL_4:.*]]#1 : (index) -> !fir.shape<1> ! CHECK: %[[VAL_5:.*]] = hlfir.designate %[[VAL_2]]#0 imag shape %[[VAL_3]] : (!fir.box<!fir.array<?xcomplex<f32>>>, !fir.shape<1>) -> !fir.box<!fir.array<?xf32>> @@ -129,7 +129,7 @@ subroutine complex_real_ref(x) print *, x%re end subroutine ! CHECK-LABEL: func.func @_QPcomplex_real_ref( -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %{{[0-9]+}} {uniq_name = "_QFcomplex_real_refEx"} : (!fir.box<!fir.array<?xcomplex<f32>>>, !fir.dscope) -> (!fir.box<!fir.array<?xcomplex<f32>>>, !fir.box<!fir.array<?xcomplex<f32>>>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFcomplex_real_refEx"} : (!fir.box<!fir.array<?xcomplex<f32>>>, !fir.dscope) -> (!fir.box<!fir.array<?xcomplex<f32>>>, !fir.box<!fir.array<?xcomplex<f32>>>) ! CHECK: %[[VAL_3:.*]] = fir.shape %[[VAL_4:.*]]#1 : (index) -> !fir.shape<1> ! CHECK: %[[VAL_5:.*]] = hlfir.designate %[[VAL_2]]#0 real shape %[[VAL_3]] : (!fir.box<!fir.array<?xcomplex<f32>>>, !fir.shape<1>) -> !fir.box<!fir.array<?xf32>> @@ -139,8 +139,8 @@ subroutine complex_individual_ref(x, n) print *, x(n)%im end subroutine ! CHECK-LABEL: func.func @_QPcomplex_individual_ref( -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %{{[0-9]+}} {uniq_name = "_QFcomplex_individual_refEn"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %{{[0-9]+}} {uniq_name = "_QFcomplex_individual_refEx"} : (!fir.box<!fir.array<?xcomplex<f32>>>, !fir.dscope) -> (!fir.box<!fir.array<?xcomplex<f32>>>, !fir.box<!fir.array<?xcomplex<f32>>>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFcomplex_individual_refEn"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFcomplex_individual_refEx"} : (!fir.box<!fir.array<?xcomplex<f32>>>, !fir.dscope) -> (!fir.box<!fir.array<?xcomplex<f32>>>, !fir.box<!fir.array<?xcomplex<f32>>>) ! CHECK: %[[VAL_4:.*]] = fir.load %[[VAL_2]]#0 : !fir.ref<i32> ! CHECK: %[[VAL_5:.*]] = fir.convert %[[VAL_4]] : (i32) -> i64 ! CHECK: %[[VAL_6:.*]] = hlfir.designate %{{[0-9]+}}#0 (%[[VAL_5]]) imag : (!fir.box<!fir.array<?xcomplex<f32>>>, i64) -> !fir.ref<f32> @@ -151,9 +151,9 @@ subroutine complex_slice_ref(x, start, end) print *, x(start:end)%re end subroutine ! CHECK-LABEL: func.func @_QPcomplex_slice_ref( -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %{{[0-9]+}} {uniq_name = "_QFcomplex_slice_refEend"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %{{[0-9]+}} {uniq_name = "_QFcomplex_slice_refEstart"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) -! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %arg0 dummy_scope %{{[0-9]+}} {uniq_name = "_QFcomplex_slice_refEx"} : (!fir.box<!fir.array<?xcomplex<f32>>>, !fir.dscope) -> (!fir.box<!fir.array<?xcomplex<f32>>>, !fir.box<!fir.array<?xcomplex<f32>>>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFcomplex_slice_refEend"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFcomplex_slice_refEstart"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %arg0 dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFcomplex_slice_refEx"} : (!fir.box<!fir.array<?xcomplex<f32>>>, !fir.dscope) -> (!fir.box<!fir.array<?xcomplex<f32>>>, !fir.box<!fir.array<?xcomplex<f32>>>) ! CHECK: %[[VAL_5:.*]] = fir.load %[[VAL_3]]#0 : !fir.ref<i32> ! CHECK: %[[VAL_6:.*]] = fir.convert %[[VAL_5]] : (i32) -> i64 ! CHECK: %[[VAL_7:.*]] = fir.load %[[VAL_2]]#0 : !fir.ref<i32> diff --git a/flang/test/Lower/HLFIR/dot_product.f90 b/flang/test/Lower/HLFIR/dot_product.f90 index 2d3ee97..f36c314 100644 --- a/flang/test/Lower/HLFIR/dot_product.f90 +++ b/flang/test/Lower/HLFIR/dot_product.f90 @@ -72,10 +72,10 @@ endsubroutine ! CHECK-NEXT: } ! CHECK-LABEL: func.func @_QPdot_product5 -! CHECK: %[[LHS:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %{{[0-9]+}} {uniq_name = "_QFdot_product5Elhs"} : (!fir.box<!fir.array<?xi32>>, !fir.dscope) -> (!fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>>) +! CHECK: %[[LHS:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFdot_product5Elhs"} : (!fir.box<!fir.array<?xi32>>, !fir.dscope) -> (!fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>>) ! CHECK: %[[C3:.*]] = arith.constant 3 : index ! CHECK: %[[RHS_SHAPE:.*]] = fir.shape %[[C3]] : (index) -> !fir.shape<1> -! CHECK: %[[RHS:.*]]:2 = hlfir.declare %{{.*}}(%[[RHS_SHAPE]]) dummy_scope %{{[0-9]+}} {uniq_name = "_QFdot_product5Erhs"} : (!fir.ref<!fir.array<3xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<3xi32>>, !fir.ref<!fir.array<3xi32>>) +! CHECK: %[[RHS:.*]]:2 = hlfir.declare %{{.*}}(%[[RHS_SHAPE]]) dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFdot_product5Erhs"} : (!fir.ref<!fir.array<3xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<3xi32>>, !fir.ref<!fir.array<3xi32>>) ! CHECK: {{.*}} = hlfir.dot_product %[[LHS]]#0 %[[RHS]]#0 {fastmath = #arith.fastmath<contract>} : (!fir.box<!fir.array<?xi32>>, !fir.ref<!fir.array<3xi32>>) -> i32 subroutine dot_product5(lhs, rhs, res) integer :: lhs(:), rhs(3) diff --git a/flang/test/Lower/HLFIR/dummy-arg-number.f90 b/flang/test/Lower/HLFIR/dummy-arg-number.f90 new file mode 100644 index 0000000..938cdcc --- /dev/null +++ b/flang/test/Lower/HLFIR/dummy-arg-number.f90 @@ -0,0 +1,53 @@ +! Test that dummy argument positions are tracked in hlfir.declare +! RUN: bbc -emit-hlfir -o - %s | FileCheck %s + +! CHECK-LABEL: func.func @_QPsingle_arg( +subroutine single_arg(n) + integer :: n + ! CHECK: hlfir.declare %{{.*}} dummy_scope %{{.*}} arg 1 {uniq_name = "_QFsingle_argEn"} + print *, n +end subroutine + +! CHECK-LABEL: func.func @_QPmultiple_args( +subroutine multiple_args(a, b, c) + integer :: a, b, c + ! CHECK-DAG: hlfir.declare %{{.*}} dummy_scope %{{.*}} arg 1 {uniq_name = "_QFmultiple_argsEa"} + ! CHECK-DAG: hlfir.declare %{{.*}} dummy_scope %{{.*}} arg 2 {uniq_name = "_QFmultiple_argsEb"} + ! CHECK-DAG: hlfir.declare %{{.*}} dummy_scope %{{.*}} arg 3 {uniq_name = "_QFmultiple_argsEc"} + print *, a, b, c +end subroutine + +! CHECK-LABEL: func.func @_QPchar_arg( +subroutine char_arg(str) + character(len=5) :: str + ! CHECK: hlfir.declare %{{.*}} typeparams %{{.*}} dummy_scope %{{.*}} arg 1 {uniq_name = "_QFchar_argEstr"} + print *, str +end subroutine + +! CHECK-LABEL: func.func @_QParray_arg( +subroutine array_arg(arr) + integer :: arr(:) + ! CHECK: hlfir.declare %{{.*}} dummy_scope %{{.*}} arg 1 {uniq_name = "_QFarray_argEarr"} + print *, arr(1) +end subroutine + +! Test that local variables do NOT get arg numbers +! CHECK-LABEL: func.func @_QPlocal_var() +subroutine local_var() + integer :: x + ! CHECK: hlfir.declare %{{[0-9]+}} {uniq_name = "_QFlocal_varEx"} + x = 10 + print *, x +end subroutine + +! Test mixed arguments and locals +! CHECK-LABEL: func.func @_QPmixed( +subroutine mixed(n) + integer :: n + integer :: local_x + ! CHECK-DAG: hlfir.declare %{{[0-9]+}} {uniq_name = "_QFmixedElocal_x"} + ! CHECK-DAG: hlfir.declare {{.*}} dummy_scope {{.*}} arg 1 {uniq_name = "_QFmixedEn"} + local_x = n + 1 + print *, local_x +end subroutine + diff --git a/flang/test/Lower/HLFIR/dummy-scope.f90 b/flang/test/Lower/HLFIR/dummy-scope.f90 index 4b1a332..da22318 100644 --- a/flang/test/Lower/HLFIR/dummy-scope.f90 +++ b/flang/test/Lower/HLFIR/dummy-scope.f90 @@ -7,7 +7,7 @@ end subroutine sub_arg ! CHECK-LABEL: func.func @_QPsub_arg( ! CHECK-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<i32> {fir.bindc_name = "x"}) { ! CHECK: %[[VAL_1:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] {uniq_name = "_QFsub_argEx"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] arg {{[0-9]+}} {uniq_name = "_QFsub_argEx"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: return ! CHECK: } @@ -29,7 +29,7 @@ end function func_arg ! CHECK: %[[VAL_1:.*]] = fir.dummy_scope : !fir.dscope ! CHECK: %[[VAL_2:.*]] = fir.alloca i32 {bindc_name = "func_arg", uniq_name = "_QFfunc_argEfunc_arg"} ! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]] {uniq_name = "_QFfunc_argEfunc_arg"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) -! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] {uniq_name = "_QFfunc_argEx"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] arg {{[0-9]+}} {uniq_name = "_QFfunc_argEx"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_5:.*]] = fir.load %[[VAL_4]]#0 : !fir.ref<i32> ! CHECK: hlfir.assign %[[VAL_5]] to %[[VAL_3]]#0 : i32, !fir.ref<i32> ! CHECK: %[[VAL_6:.*]] = fir.load %[[VAL_3]]#0 : !fir.ref<i32> diff --git a/flang/test/Lower/HLFIR/elemental-array-ops.f90 b/flang/test/Lower/HLFIR/elemental-array-ops.f90 index 10450f6..3a923b3 100644 --- a/flang/test/Lower/HLFIR/elemental-array-ops.f90 +++ b/flang/test/Lower/HLFIR/elemental-array-ops.f90 @@ -166,9 +166,9 @@ end subroutine char_return ! CHECK: fir.store %[[VAL_7]] to %[[VAL_3]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.logical<4>>>>> ! CHECK: %[[VAL_8:.*]]:2 = hlfir.declare %[[VAL_3]] {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFchar_returnEl"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.logical<4>>>>>) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.logical<4>>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.logical<4>>>>>) ! CHECK: %[[VAL_9:.*]] = arith.constant 3 : index -! CHECK: %[[VAL_10:.*]]:2 = hlfir.declare %[[VAL_0]] typeparams %[[VAL_9]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<intent_in>, uniq_name = "_QFchar_returnEx"} : (!fir.box<!fir.array<?x!fir.char<1,3>>>, index, !fir.dscope) -> (!fir.box<!fir.array<?x!fir.char<1,3>>>, !fir.box<!fir.array<?x!fir.char<1,3>>>) +! CHECK: %[[VAL_10:.*]]:2 = hlfir.declare %[[VAL_0]] typeparams %[[VAL_9]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<intent_in>, uniq_name = "_QFchar_returnEx"} : (!fir.box<!fir.array<?x!fir.char<1,3>>>, index, !fir.dscope) -> (!fir.box<!fir.array<?x!fir.char<1,3>>>, !fir.box<!fir.array<?x!fir.char<1,3>>>) ! CHECK: %[[VAL_11:.*]] = arith.constant 3 : index -! CHECK: %[[VAL_12:.*]]:2 = hlfir.declare %[[VAL_1]] typeparams %[[VAL_11]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<intent_in>, uniq_name = "_QFchar_returnEy"} : (!fir.box<!fir.array<?x!fir.char<1,3>>>, index, !fir.dscope) -> (!fir.box<!fir.array<?x!fir.char<1,3>>>, !fir.box<!fir.array<?x!fir.char<1,3>>>) +! CHECK: %[[VAL_12:.*]]:2 = hlfir.declare %[[VAL_1]] typeparams %[[VAL_11]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<intent_in>, uniq_name = "_QFchar_returnEy"} : (!fir.box<!fir.array<?x!fir.char<1,3>>>, index, !fir.dscope) -> (!fir.box<!fir.array<?x!fir.char<1,3>>>, !fir.box<!fir.array<?x!fir.char<1,3>>>) ! CHECK: %[[VAL_13:.*]] = arith.constant 0 : index ! CHECK: %[[VAL_14:.*]]:3 = fir.box_dims %[[VAL_12]]#0, %[[VAL_13]] : (!fir.box<!fir.array<?x!fir.char<1,3>>>, index) -> (index, index, index) ! CHECK: %[[VAL_15:.*]] = fir.shape %[[VAL_14]]#1 : (index) -> !fir.shape<1> @@ -210,8 +210,8 @@ end subroutine polymorphic_parenthesis ! CHECK-LABEL: func.func @_QPpolymorphic_parenthesis( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.class<!fir.heap<!fir.array<?x!fir.type<_QFpolymorphic_parenthesisTt>>>>> {fir.bindc_name = "x"}, ! CHECK-SAME: %[[VAL_1:.*]]: !fir.class<!fir.array<?x!fir.type<_QFpolymorphic_parenthesisTt>>> {fir.bindc_name = "y"}) { -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFpolymorphic_parenthesisEx"} : (!fir.ref<!fir.class<!fir.heap<!fir.array<?x!fir.type<_QFpolymorphic_parenthesisTt>>>>>, !fir.dscope) -> (!fir.ref<!fir.class<!fir.heap<!fir.array<?x!fir.type<_QFpolymorphic_parenthesisTt>>>>>, !fir.ref<!fir.class<!fir.heap<!fir.array<?x!fir.type<_QFpolymorphic_parenthesisTt>>>>>) -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<intent_in>, uniq_name = "_QFpolymorphic_parenthesisEy"} : (!fir.class<!fir.array<?x!fir.type<_QFpolymorphic_parenthesisTt>>>, !fir.dscope) -> (!fir.class<!fir.array<?x!fir.type<_QFpolymorphic_parenthesisTt>>>, !fir.class<!fir.array<?x!fir.type<_QFpolymorphic_parenthesisTt>>>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFpolymorphic_parenthesisEx"} : (!fir.ref<!fir.class<!fir.heap<!fir.array<?x!fir.type<_QFpolymorphic_parenthesisTt>>>>>, !fir.dscope) -> (!fir.ref<!fir.class<!fir.heap<!fir.array<?x!fir.type<_QFpolymorphic_parenthesisTt>>>>>, !fir.ref<!fir.class<!fir.heap<!fir.array<?x!fir.type<_QFpolymorphic_parenthesisTt>>>>>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<intent_in>, uniq_name = "_QFpolymorphic_parenthesisEy"} : (!fir.class<!fir.array<?x!fir.type<_QFpolymorphic_parenthesisTt>>>, !fir.dscope) -> (!fir.class<!fir.array<?x!fir.type<_QFpolymorphic_parenthesisTt>>>, !fir.class<!fir.array<?x!fir.type<_QFpolymorphic_parenthesisTt>>>) ! CHECK: %[[VAL_4:.*]] = arith.constant 0 : index ! CHECK: %[[VAL_5:.*]]:3 = fir.box_dims %[[VAL_3]]#0, %[[VAL_4]] : (!fir.class<!fir.array<?x!fir.type<_QFpolymorphic_parenthesisTt>>>, index) -> (index, index, index) ! CHECK: %[[VAL_6:.*]] = fir.shape %[[VAL_5]]#1 : (index) -> !fir.shape<1> @@ -234,8 +234,8 @@ end subroutine unlimited_polymorphic_parenthesis ! CHECK-LABEL: func.func @_QPunlimited_polymorphic_parenthesis( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.class<!fir.heap<!fir.array<?xnone>>>> {fir.bindc_name = "x"}, ! CHECK-SAME: %[[VAL_1:.*]]: !fir.class<!fir.array<?xnone>> {fir.bindc_name = "y"}) { -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFunlimited_polymorphic_parenthesisEx"} : (!fir.ref<!fir.class<!fir.heap<!fir.array<?xnone>>>>, !fir.dscope) -> (!fir.ref<!fir.class<!fir.heap<!fir.array<?xnone>>>>, !fir.ref<!fir.class<!fir.heap<!fir.array<?xnone>>>>) -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<intent_in>, uniq_name = "_QFunlimited_polymorphic_parenthesisEy"} : (!fir.class<!fir.array<?xnone>>, !fir.dscope) -> (!fir.class<!fir.array<?xnone>>, !fir.class<!fir.array<?xnone>>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFunlimited_polymorphic_parenthesisEx"} : (!fir.ref<!fir.class<!fir.heap<!fir.array<?xnone>>>>, !fir.dscope) -> (!fir.ref<!fir.class<!fir.heap<!fir.array<?xnone>>>>, !fir.ref<!fir.class<!fir.heap<!fir.array<?xnone>>>>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<intent_in>, uniq_name = "_QFunlimited_polymorphic_parenthesisEy"} : (!fir.class<!fir.array<?xnone>>, !fir.dscope) -> (!fir.class<!fir.array<?xnone>>, !fir.class<!fir.array<?xnone>>) ! CHECK: %[[VAL_4:.*]] = arith.constant 0 : index ! CHECK: %[[VAL_5:.*]]:3 = fir.box_dims %[[VAL_3]]#0, %[[VAL_4]] : (!fir.class<!fir.array<?xnone>>, index) -> (index, index, index) ! CHECK: %[[VAL_6:.*]] = fir.shape %[[VAL_5]]#1 : (index) -> !fir.shape<1> diff --git a/flang/test/Lower/HLFIR/elemental-polymorphic-merge.f90 b/flang/test/Lower/HLFIR/elemental-polymorphic-merge.f90 index 36762d4..7453eca 100644 --- a/flang/test/Lower/HLFIR/elemental-polymorphic-merge.f90 +++ b/flang/test/Lower/HLFIR/elemental-polymorphic-merge.f90 @@ -14,10 +14,10 @@ end subroutine test_polymorphic_merge ! CHECK-SAME: %[[VAL_1:.*]]: !fir.class<!fir.array<?x!fir.type<_QFtest_polymorphic_mergeTt>>> {fir.bindc_name = "y"}, ! CHECK-SAME: %[[VAL_2:.*]]: !fir.ref<!fir.class<!fir.heap<!fir.array<?x!fir.type<_QFtest_polymorphic_mergeTt>>>>> {fir.bindc_name = "r"}, ! CHECK-SAME: %[[VAL_3:.*]]: !fir.box<!fir.array<?x!fir.logical<4>>> {fir.bindc_name = "m"}) { -! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_3]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFtest_polymorphic_mergeEm"} : (!fir.box<!fir.array<?x!fir.logical<4>>>, !fir.dscope) -> (!fir.box<!fir.array<?x!fir.logical<4>>>, !fir.box<!fir.array<?x!fir.logical<4>>>) -! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_2]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFtest_polymorphic_mergeEr"} : (!fir.ref<!fir.class<!fir.heap<!fir.array<?x!fir.type<_QFtest_polymorphic_mergeTt>>>>>, !fir.dscope) -> (!fir.ref<!fir.class<!fir.heap<!fir.array<?x!fir.type<_QFtest_polymorphic_mergeTt>>>>>, !fir.ref<!fir.class<!fir.heap<!fir.array<?x!fir.type<_QFtest_polymorphic_mergeTt>>>>>) -! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<intent_in>, uniq_name = "_QFtest_polymorphic_mergeEx"} : (!fir.class<!fir.type<_QFtest_polymorphic_mergeTt>>, !fir.dscope) -> (!fir.class<!fir.type<_QFtest_polymorphic_mergeTt>>, !fir.class<!fir.type<_QFtest_polymorphic_mergeTt>>) -! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<intent_in>, uniq_name = "_QFtest_polymorphic_mergeEy"} : (!fir.class<!fir.array<?x!fir.type<_QFtest_polymorphic_mergeTt>>>, !fir.dscope) -> (!fir.class<!fir.array<?x!fir.type<_QFtest_polymorphic_mergeTt>>>, !fir.class<!fir.array<?x!fir.type<_QFtest_polymorphic_mergeTt>>>) +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_3]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFtest_polymorphic_mergeEm"} : (!fir.box<!fir.array<?x!fir.logical<4>>>, !fir.dscope) -> (!fir.box<!fir.array<?x!fir.logical<4>>>, !fir.box<!fir.array<?x!fir.logical<4>>>) +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_2]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFtest_polymorphic_mergeEr"} : (!fir.ref<!fir.class<!fir.heap<!fir.array<?x!fir.type<_QFtest_polymorphic_mergeTt>>>>>, !fir.dscope) -> (!fir.ref<!fir.class<!fir.heap<!fir.array<?x!fir.type<_QFtest_polymorphic_mergeTt>>>>>, !fir.ref<!fir.class<!fir.heap<!fir.array<?x!fir.type<_QFtest_polymorphic_mergeTt>>>>>) +! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<intent_in>, uniq_name = "_QFtest_polymorphic_mergeEx"} : (!fir.class<!fir.type<_QFtest_polymorphic_mergeTt>>, !fir.dscope) -> (!fir.class<!fir.type<_QFtest_polymorphic_mergeTt>>, !fir.class<!fir.type<_QFtest_polymorphic_mergeTt>>) +! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<intent_in>, uniq_name = "_QFtest_polymorphic_mergeEy"} : (!fir.class<!fir.array<?x!fir.type<_QFtest_polymorphic_mergeTt>>>, !fir.dscope) -> (!fir.class<!fir.array<?x!fir.type<_QFtest_polymorphic_mergeTt>>>, !fir.class<!fir.array<?x!fir.type<_QFtest_polymorphic_mergeTt>>>) ! CHECK: %[[VAL_8:.*]] = arith.constant 0 : index ! CHECK: %[[VAL_9:.*]]:3 = fir.box_dims %[[VAL_7]]#0, %[[VAL_8]] : (!fir.class<!fir.array<?x!fir.type<_QFtest_polymorphic_mergeTt>>>, index) -> (index, index, index) ! CHECK: %[[VAL_10:.*]] = fir.shape %[[VAL_9]]#1 : (index) -> !fir.shape<1> diff --git a/flang/test/Lower/HLFIR/elemental-result-length.f90 b/flang/test/Lower/HLFIR/elemental-result-length.f90 index 9418a40..4cce2ce 100644 --- a/flang/test/Lower/HLFIR/elemental-result-length.f90 +++ b/flang/test/Lower/HLFIR/elemental-result-length.f90 @@ -18,11 +18,11 @@ end subroutine ! CHECK-LABEL: func.func @_QMm1Psub2( ! CHECK-SAME: %[[ARG0:.*]]: !fir.boxchar<1> {fir.bindc_name = "a"}, %[[ARG1:.*]]: !fir.boxchar<1> {fir.bindc_name = "b"}, %[[ARG2:.*]]: !fir.boxchar<1> {fir.bindc_name = "c"}) { ! CHECK: %[[UNBOX_ARG0:.*]]:2 = fir.unboxchar %[[ARG0]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index) -! CHECK: %[[A:.*]]:2 = hlfir.declare %[[UNBOX_ARG0]]#0 typeparams %[[UNBOX_ARG0]]#1 dummy_scope %0 {fortran_attrs = #fir.var_attrs<intent_in>, uniq_name = "_QMm1Fsub2Ea"} : (!fir.ref<!fir.char<1,?>>, index, !fir.dscope) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>) +! CHECK: %[[A:.*]]:2 = hlfir.declare %[[UNBOX_ARG0]]#0 typeparams %[[UNBOX_ARG0]]#1 dummy_scope %0 {{.*}} {fortran_attrs = #fir.var_attrs<intent_in>, uniq_name = "_QMm1Fsub2Ea"} : (!fir.ref<!fir.char<1,?>>, index, !fir.dscope) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>) ! CHECK: %[[UNBOX_ARG1:.*]]:2 = fir.unboxchar %[[ARG1]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index) -! CHECK: %[[B:.*]]:2 = hlfir.declare %[[UNBOX_ARG1]]#0 typeparams %[[UNBOX_ARG1]]#1 dummy_scope %{{.*}} {fortran_attrs = #fir.var_attrs<intent_in>, uniq_name = "_QMm1Fsub2Eb"} : (!fir.ref<!fir.char<1,?>>, index, !fir.dscope) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>) +! CHECK: %[[B:.*]]:2 = hlfir.declare %[[UNBOX_ARG1]]#0 typeparams %[[UNBOX_ARG1]]#1 dummy_scope %{{.*}} {{.*}} {fortran_attrs = #fir.var_attrs<intent_in>, uniq_name = "_QMm1Fsub2Eb"} : (!fir.ref<!fir.char<1,?>>, index, !fir.dscope) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>) ! CHECK: %[[UNBOX_ARG2:.*]]:2 = fir.unboxchar %[[ARG2]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index) -! CHECK: %[[C:.*]]:2 = hlfir.declare %[[UNBOX_ARG2]]#0 typeparams %[[UNBOX_ARG2]]#1 dummy_scope %{{.*}} {fortran_attrs = #fir.var_attrs<intent_inout>, uniq_name = "_QMm1Fsub2Ec"} : (!fir.ref<!fir.char<1,?>>, index, !fir.dscope) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>) +! CHECK: %[[C:.*]]:2 = hlfir.declare %[[UNBOX_ARG2]]#0 typeparams %[[UNBOX_ARG2]]#1 dummy_scope %{{.*}} {{.*}} {fortran_attrs = #fir.var_attrs<intent_inout>, uniq_name = "_QMm1Fsub2Ec"} : (!fir.ref<!fir.char<1,?>>, index, !fir.dscope) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>) ! CHECK: %[[UNBOX_A:.*]]:2 = fir.unboxchar %[[A]]#0 : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index) ! CHECK: %[[DUMMYA:.*]]:2 = hlfir.declare %[[UNBOX_A]]#0 typeparams %[[UNBOX_A]]#1 {fortran_attrs = #fir.var_attrs<intent_in>, uniq_name = "_QMm1Ffct1Ea"} : (!fir.ref<!fir.char<1,?>>, index) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>) ! CHECK: %[[UNBOX_B:.*]]:2 = fir.unboxchar %[[B]]#0 : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index) @@ -45,9 +45,9 @@ end subroutine ! CHECK-LABEL: func.func @_QMm1Psub4( ! CHECK-SAME: %[[ARG0:.*]]: !fir.box<!fir.array<?x!fir.char<1,?>>> {fir.bindc_name = "a"}, %[[ARG1:.*]]: !fir.box<!fir.array<?x!fir.char<1,?>>> {fir.bindc_name = "b"}, %[[ARG2:.*]]: !fir.box<!fir.array<?x!fir.char<1,?>>> {fir.bindc_name = "c"}) { -! CHECK: %[[A:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{.*}} {fortran_attrs = #fir.var_attrs<intent_in>, uniq_name = "_QMm1Fsub4Ea"} : (!fir.box<!fir.array<?x!fir.char<1,?>>>, !fir.dscope) -> (!fir.box<!fir.array<?x!fir.char<1,?>>>, !fir.box<!fir.array<?x!fir.char<1,?>>>) -! CHECK: %[[B:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %{{.*}} {fortran_attrs = #fir.var_attrs<intent_in>, uniq_name = "_QMm1Fsub4Eb"} : (!fir.box<!fir.array<?x!fir.char<1,?>>>, !fir.dscope) -> (!fir.box<!fir.array<?x!fir.char<1,?>>>, !fir.box<!fir.array<?x!fir.char<1,?>>>) -! CHECK: %[[C:.*]]:2 = hlfir.declare %[[ARG2]] dummy_scope %{{.*}} {fortran_attrs = #fir.var_attrs<intent_inout>, uniq_name = "_QMm1Fsub4Ec"} : (!fir.box<!fir.array<?x!fir.char<1,?>>>, !fir.dscope) -> (!fir.box<!fir.array<?x!fir.char<1,?>>>, !fir.box<!fir.array<?x!fir.char<1,?>>>) +! CHECK: %[[A:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{.*}} {{.*}} {fortran_attrs = #fir.var_attrs<intent_in>, uniq_name = "_QMm1Fsub4Ea"} : (!fir.box<!fir.array<?x!fir.char<1,?>>>, !fir.dscope) -> (!fir.box<!fir.array<?x!fir.char<1,?>>>, !fir.box<!fir.array<?x!fir.char<1,?>>>) +! CHECK: %[[B:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %{{.*}} {{.*}} {fortran_attrs = #fir.var_attrs<intent_in>, uniq_name = "_QMm1Fsub4Eb"} : (!fir.box<!fir.array<?x!fir.char<1,?>>>, !fir.dscope) -> (!fir.box<!fir.array<?x!fir.char<1,?>>>, !fir.box<!fir.array<?x!fir.char<1,?>>>) +! CHECK: %[[C:.*]]:2 = hlfir.declare %[[ARG2]] dummy_scope %{{.*}} {{.*}} {fortran_attrs = #fir.var_attrs<intent_inout>, uniq_name = "_QMm1Fsub4Ec"} : (!fir.box<!fir.array<?x!fir.char<1,?>>>, !fir.dscope) -> (!fir.box<!fir.array<?x!fir.char<1,?>>>, !fir.box<!fir.array<?x!fir.char<1,?>>>) ! CHECK: %[[LEN_A:.*]] = fir.box_elesize %[[A]]#1 : (!fir.box<!fir.array<?x!fir.char<1,?>>>) -> index ! CHECK: %[[LEN_B:.*]] = fir.box_elesize %[[B]]#1 : (!fir.box<!fir.array<?x!fir.char<1,?>>>) -> index ! CHECK: %[[LEN_A_I32:.*]] = fir.convert %[[LEN_A]] : (index) -> i64 diff --git a/flang/test/Lower/HLFIR/elemental-user-procedure-ref.f90 b/flang/test/Lower/HLFIR/elemental-user-procedure-ref.f90 index 1080c9d..95e74cd 100644 --- a/flang/test/Lower/HLFIR/elemental-user-procedure-ref.f90 +++ b/flang/test/Lower/HLFIR/elemental-user-procedure-ref.f90 @@ -111,7 +111,7 @@ end subroutine ! CHECK: %[[VAL_1:.*]] = arith.constant 10 : index ! CHECK: %[[VAL_2:.*]] = arith.constant 20 : index ! CHECK: %[[VAL_3:.*]] = fir.shape %[[VAL_1]], %[[VAL_2]] : (index, index) -> !fir.shape<2> -! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_3]]) dummy_scope %{{[0-9]+}} {uniq_name = "_QFimpure_elementalEx"} : (!fir.ref<!fir.array<10x20xf32>>, !fir.shape<2>, !fir.dscope) -> (!fir.ref<!fir.array<10x20xf32>>, !fir.ref<!fir.array<10x20xf32>>) +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_3]]) dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFimpure_elementalEx"} : (!fir.ref<!fir.array<10x20xf32>>, !fir.shape<2>, !fir.dscope) -> (!fir.ref<!fir.array<10x20xf32>>, !fir.ref<!fir.array<10x20xf32>>) ! CHECK: %[[VAL_5:.*]] = arith.constant 1 : index ! CHECK: fir.do_loop %[[VAL_6:.*]] = %[[VAL_5]] to %[[VAL_2]] step %[[VAL_5]] { ! CHECK: fir.do_loop %[[VAL_7:.*]] = %[[VAL_5]] to %[[VAL_1]] step %[[VAL_5]] { @@ -136,7 +136,7 @@ end subroutine ! CHECK: %[[VAL_1:.*]] = arith.constant 10 : index ! CHECK: %[[VAL_2:.*]] = arith.constant 20 : index ! CHECK: %[[VAL_3:.*]] = fir.shape %[[VAL_1]], %[[VAL_2]] : (index, index) -> !fir.shape<2> -! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_3]]) dummy_scope %{{[0-9]+}} {uniq_name = "_QFordered_elementalEx"} : (!fir.ref<!fir.array<10x20xf32>>, !fir.shape<2>, !fir.dscope) -> (!fir.ref<!fir.array<10x20xf32>>, !fir.ref<!fir.array<10x20xf32>>) +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_3]]) dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFordered_elementalEx"} : (!fir.ref<!fir.array<10x20xf32>>, !fir.shape<2>, !fir.dscope) -> (!fir.ref<!fir.array<10x20xf32>>, !fir.ref<!fir.array<10x20xf32>>) ! CHECK: %[[VAL_5:.*]] = arith.constant 1 : index ! CHECK: fir.do_loop %[[VAL_6:.*]] = %[[VAL_5]] to %[[VAL_2]] step %[[VAL_5]] { ! CHECK: fir.do_loop %[[VAL_7:.*]] = %[[VAL_5]] to %[[VAL_1]] step %[[VAL_5]] { @@ -161,7 +161,7 @@ end subroutine ! CHECK: %[[VAL_1:.*]] = arith.constant 10 : index ! CHECK: %[[VAL_2:.*]] = arith.constant 20 : index ! CHECK: %[[VAL_3:.*]] = fir.shape %[[VAL_1]], %[[VAL_2]] : (index, index) -> !fir.shape<2> -! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_3]]) dummy_scope %{{[0-9]+}} {uniq_name = "_QFimpure_elemental_arg_evalEx"} : (!fir.ref<!fir.array<10x20xf32>>, !fir.shape<2>, !fir.dscope) -> (!fir.ref<!fir.array<10x20xf32>>, !fir.ref<!fir.array<10x20xf32>>) +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_3]]) dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFimpure_elemental_arg_evalEx"} : (!fir.ref<!fir.array<10x20xf32>>, !fir.shape<2>, !fir.dscope) -> (!fir.ref<!fir.array<10x20xf32>>, !fir.ref<!fir.array<10x20xf32>>) ! CHECK: %[[VAL_5:.*]] = hlfir.elemental %[[VAL_3]] unordered : (!fir.shape<2>) -> !hlfir.expr<10x20xf32> { ! CHECK: ^bb0(%[[VAL_6:.*]]: index, %[[VAL_7:.*]]: index): ! CHECK: %[[VAL_8:.*]] = hlfir.designate %[[VAL_4]]#0 (%[[VAL_6]], %[[VAL_7]]) : (!fir.ref<!fir.array<10x20xf32>>, index, index) -> !fir.ref<f32> diff --git a/flang/test/Lower/HLFIR/eoshift.f90 b/flang/test/Lower/HLFIR/eoshift.f90 index 8d54177..25442ae 100644 --- a/flang/test/Lower/HLFIR/eoshift.f90 +++ b/flang/test/Lower/HLFIR/eoshift.f90 @@ -169,8 +169,8 @@ end subroutine ! CHECK-SAME: %[[ARG0:.*]]: !fir.box<!fir.array<?x!fir.type<_QMeoshift_typesTt>>> {fir.bindc_name = "a"}, ! CHECK-SAME: %[[ARG1:.*]]: !fir.ref<f32> {fir.bindc_name = "s"}) { ! CHECK: %[[VAL_0:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %[[VAL_0]] {uniq_name = "_QFeoshift9Ea"} : (!fir.box<!fir.array<?x!fir.type<_QMeoshift_typesTt>>>, !fir.dscope) -> (!fir.box<!fir.array<?x!fir.type<_QMeoshift_typesTt>>>, !fir.box<!fir.array<?x!fir.type<_QMeoshift_typesTt>>>) -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %[[VAL_0]] {uniq_name = "_QFeoshift9Es"} : (!fir.ref<f32>, !fir.dscope) -> (!fir.ref<f32>, !fir.ref<f32>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %[[VAL_0]] arg {{[0-9]+}} {uniq_name = "_QFeoshift9Ea"} : (!fir.box<!fir.array<?x!fir.type<_QMeoshift_typesTt>>>, !fir.dscope) -> (!fir.box<!fir.array<?x!fir.type<_QMeoshift_typesTt>>>, !fir.box<!fir.array<?x!fir.type<_QMeoshift_typesTt>>>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %[[VAL_0]] arg {{[0-9]+}} {uniq_name = "_QFeoshift9Es"} : (!fir.ref<f32>, !fir.dscope) -> (!fir.ref<f32>, !fir.ref<f32>) ! CHECK: %[[VAL_3:.*]] = arith.constant 2 : i32 ! CHECK: %[[VAL_4:.*]] = fir.address_of(@_QQro._QMeoshift_typesTt.0) : !fir.ref<!fir.type<_QMeoshift_typesTt>> ! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_4]] {fortran_attrs = #fir.var_attrs<parameter>, uniq_name = "_QQro._QMeoshift_typesTt.0"} : (!fir.ref<!fir.type<_QMeoshift_typesTt>>) -> (!fir.ref<!fir.type<_QMeoshift_typesTt>>, !fir.ref<!fir.type<_QMeoshift_typesTt>>) @@ -190,8 +190,8 @@ end subroutine ! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.class<!fir.heap<!fir.array<?x!fir.type<_QMeoshift_typesTt>>>>> {fir.bindc_name = "a"}, ! CHECK-SAME: %[[ARG1:.*]]: !fir.ref<f32> {fir.bindc_name = "s"}) { ! CHECK: %[[VAL_0:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %[[VAL_0]] {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFeoshift10Ea"} : (!fir.ref<!fir.class<!fir.heap<!fir.array<?x!fir.type<_QMeoshift_typesTt>>>>>, !fir.dscope) -> (!fir.ref<!fir.class<!fir.heap<!fir.array<?x!fir.type<_QMeoshift_typesTt>>>>>, !fir.ref<!fir.class<!fir.heap<!fir.array<?x!fir.type<_QMeoshift_typesTt>>>>>) -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %[[VAL_0]] {uniq_name = "_QFeoshift10Es"} : (!fir.ref<f32>, !fir.dscope) -> (!fir.ref<f32>, !fir.ref<f32>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %[[VAL_0]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFeoshift10Ea"} : (!fir.ref<!fir.class<!fir.heap<!fir.array<?x!fir.type<_QMeoshift_typesTt>>>>>, !fir.dscope) -> (!fir.ref<!fir.class<!fir.heap<!fir.array<?x!fir.type<_QMeoshift_typesTt>>>>>, !fir.ref<!fir.class<!fir.heap<!fir.array<?x!fir.type<_QMeoshift_typesTt>>>>>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %[[VAL_0]] arg {{[0-9]+}} {uniq_name = "_QFeoshift10Es"} : (!fir.ref<f32>, !fir.dscope) -> (!fir.ref<f32>, !fir.ref<f32>) ! CHECK: %[[VAL_3:.*]] = arith.constant 2 : i32 ! CHECK: %[[VAL_4:.*]] = fir.address_of(@_QQro._QMeoshift_typesTt.1) : !fir.ref<!fir.type<_QMeoshift_typesTt>> ! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_4]] {fortran_attrs = #fir.var_attrs<parameter>, uniq_name = "_QQro._QMeoshift_typesTt.1"} : (!fir.ref<!fir.type<_QMeoshift_typesTt>>) -> (!fir.ref<!fir.type<_QMeoshift_typesTt>>, !fir.ref<!fir.type<_QMeoshift_typesTt>>) @@ -212,9 +212,9 @@ end subroutine ! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref<i32> {fir.bindc_name = "s"}, ! CHECK-SAME: %[[VAL_2:.*]]: !fir.ref<i32> {fir.bindc_name = "d"}) { ! CHECK: %[[VAL_3:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_3]] {uniq_name = "_QFeoshift11Ea"} : (!fir.box<!fir.array<?xi32>>, !fir.dscope) -> (!fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>>) -! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_2]] dummy_scope %[[VAL_3]] {uniq_name = "_QFeoshift11Ed"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) -! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %[[VAL_3]] {uniq_name = "_QFeoshift11Es"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_3]] arg {{[0-9]+}} {uniq_name = "_QFeoshift11Ea"} : (!fir.box<!fir.array<?xi32>>, !fir.dscope) -> (!fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>>) +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_2]] dummy_scope %[[VAL_3]] arg {{[0-9]+}} {uniq_name = "_QFeoshift11Ed"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %[[VAL_3]] arg {{[0-9]+}} {uniq_name = "_QFeoshift11Es"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_7:.*]] = arith.constant 2 : i32 ! CHECK: %[[VAL_8:.*]] = fir.load %[[VAL_5]]#0 : !fir.ref<i32> ! CHECK: %[[VAL_9:.*]] = hlfir.eoshift %[[VAL_4]]#0 %[[VAL_7]] dim %[[VAL_8]] : (!fir.box<!fir.array<?xi32>>, i32, i32) -> !hlfir.expr<?xi32> @@ -235,10 +235,10 @@ end subroutine eoshift12 ! CHECK-SAME: %[[ARG2:.*]]: !fir.ref<f32> {fir.bindc_name = "boundary", fir.optional}, ! CHECK-SAME: %[[ARG3:.*]]: !fir.ref<i32> {fir.bindc_name = "dim"}) { ! CHECK: %[[VAL_0:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %[[VAL_0]] {uniq_name = "_QFeoshift12Earray"} : (!fir.box<!fir.array<?x?xf32>>, !fir.dscope) -> (!fir.box<!fir.array<?x?xf32>>, !fir.box<!fir.array<?x?xf32>>) -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[ARG2]] dummy_scope %[[VAL_0]] {fortran_attrs = #fir.var_attrs<optional>, uniq_name = "_QFeoshift12Eboundary"} : (!fir.ref<f32>, !fir.dscope) -> (!fir.ref<f32>, !fir.ref<f32>) -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[ARG3]] dummy_scope %[[VAL_0]] {uniq_name = "_QFeoshift12Edim"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) -! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %[[VAL_0]] {uniq_name = "_QFeoshift12Eshift"} : (!fir.box<!fir.array<?xi32>>, !fir.dscope) -> (!fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %[[VAL_0]] arg {{[0-9]+}} {uniq_name = "_QFeoshift12Earray"} : (!fir.box<!fir.array<?x?xf32>>, !fir.dscope) -> (!fir.box<!fir.array<?x?xf32>>, !fir.box<!fir.array<?x?xf32>>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[ARG2]] dummy_scope %[[VAL_0]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<optional>, uniq_name = "_QFeoshift12Eboundary"} : (!fir.ref<f32>, !fir.dscope) -> (!fir.ref<f32>, !fir.ref<f32>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[ARG3]] dummy_scope %[[VAL_0]] arg {{[0-9]+}} {uniq_name = "_QFeoshift12Edim"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %[[VAL_0]] arg {{[0-9]+}} {uniq_name = "_QFeoshift12Eshift"} : (!fir.box<!fir.array<?xi32>>, !fir.dscope) -> (!fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>>) ! CHECK: %[[VAL_5:.*]] = fir.is_present %[[VAL_2]]#0 : (!fir.ref<f32>) -> i1 ! CHECK: %[[VAL_6:.*]] = fir.embox %[[VAL_2]]#0 : (!fir.ref<f32>) -> !fir.box<f32> ! CHECK: %[[VAL_7:.*]] = fir.absent !fir.box<f32> diff --git a/flang/test/Lower/HLFIR/expr-addr.f90 b/flang/test/Lower/HLFIR/expr-addr.f90 index 1f67617..fae54ec 100644 --- a/flang/test/Lower/HLFIR/expr-addr.f90 +++ b/flang/test/Lower/HLFIR/expr-addr.f90 @@ -6,7 +6,7 @@ subroutine foo(x) integer :: x read (*,*) x - ! CHECK: %[[x:.]]:2 = hlfir.declare %[[arg0]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFfooEx"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) + ! CHECK: %[[x:.]]:2 = hlfir.declare %[[arg0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFfooEx"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[x_cast:.*]] = fir.convert %[[x]]#0 : (!fir.ref<i32>) -> !fir.ref<i64> ! CHECK: fir.call @_FortranAioInputInteger(%{{.*}}, %[[x_cast]], %{{.*}}) {{.*}}: (!fir.ref<i8>, !fir.ref<i64>, i32) -> i1 end subroutine diff --git a/flang/test/Lower/HLFIR/expr-box.f90 b/flang/test/Lower/HLFIR/expr-box.f90 index f0de381..4631d18 100644 --- a/flang/test/Lower/HLFIR/expr-box.f90 +++ b/flang/test/Lower/HLFIR/expr-box.f90 @@ -9,7 +9,7 @@ subroutine foo(x) ! CHECK-DAG: %[[VAL_3:.*]] = arith.constant 21 : index ! CHECK-DAG: %[[VAL_4:.*]] = arith.constant 10 : index ! CHECK: %[[VAL_5:.*]] = fir.shape_shift %[[VAL_3]], %[[VAL_4]] : (index, index) -> !fir.shapeshift<1> -! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_5]]) dummy_scope %{{[0-9]+}} {uniq_name = "_QFfooEx"} : (!fir.ref<!fir.array<10xi32>>, !fir.shapeshift<1>, !fir.dscope) -> (!fir.box<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>) +! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_5]]) dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFfooEx"} : (!fir.ref<!fir.array<10xi32>>, !fir.shapeshift<1>, !fir.dscope) -> (!fir.box<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>) ! CHECK: fir.embox %[[VAL_6]]#1(%[[VAL_5]]) : (!fir.ref<!fir.array<10xi32>>, !fir.shapeshift<1>) -> !fir.box<!fir.array<10xi32>> end subroutine diff --git a/flang/test/Lower/HLFIR/expr-value.f90 b/flang/test/Lower/HLFIR/expr-value.f90 index c692ec7..e8e7f756 100644 --- a/flang/test/Lower/HLFIR/expr-value.f90 +++ b/flang/test/Lower/HLFIR/expr-value.f90 @@ -11,7 +11,7 @@ end subroutine ! CHECK-LABEL: func.func @_QPfoo_designator( ! CHECK-SAME: %[[arg0:.*]]: !fir.ref<i32> subroutine foo_designator(n) - !CHECK: %[[n:.*]]:2 = hlfir.declare %[[arg0]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFfoo_designatorEn"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) + !CHECK: %[[n:.*]]:2 = hlfir.declare %[[arg0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFfoo_designatorEn"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) print *, n ! CHECK: %[[nval:.*]] = fir.load %[[n]]#0 : !fir.ref<i32> ! CHECK: fir.call @_FortranAioOutputInteger32(%{{.*}}, %[[nval]]) {{.*}}: (!fir.ref<i8>, i32) -> i1 diff --git a/flang/test/Lower/HLFIR/ignore-rank-unlimited-polymorphic.f90 b/flang/test/Lower/HLFIR/ignore-rank-unlimited-polymorphic.f90 index aeb5c2a..84cceee 100644 --- a/flang/test/Lower/HLFIR/ignore-rank-unlimited-polymorphic.f90 +++ b/flang/test/Lower/HLFIR/ignore-rank-unlimited-polymorphic.f90 @@ -49,7 +49,7 @@ subroutine test_logical_assumed_shape_array(x) end subroutine test_logical_assumed_shape_array ! CHECK-LABEL: func.func @_QPtest_logical_assumed_shape_array( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.box<!fir.array<?x!fir.logical<4>>> {fir.bindc_name = "x"}) { -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFtest_logical_assumed_shape_arrayEx"} : (!fir.box<!fir.array<?x!fir.logical<4>>>, !fir.dscope) -> (!fir.box<!fir.array<?x!fir.logical<4>>>, !fir.box<!fir.array<?x!fir.logical<4>>>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFtest_logical_assumed_shape_arrayEx"} : (!fir.box<!fir.array<?x!fir.logical<4>>>, !fir.dscope) -> (!fir.box<!fir.array<?x!fir.logical<4>>>, !fir.box<!fir.array<?x!fir.logical<4>>>) ! CHECK: %[[VAL_2:.*]] = fir.rebox %[[VAL_1]]#0 : (!fir.box<!fir.array<?x!fir.logical<4>>>) -> !fir.class<!fir.array<?xnone>> ! CHECK: %[[VAL_3:.*]] = fir.convert %[[VAL_2]] : (!fir.class<!fir.array<?xnone>>) -> !fir.class<none> ! CHECK: fir.call @_QPcallee(%[[VAL_3]]) fastmath<contract> : (!fir.class<none>) -> () @@ -63,7 +63,7 @@ subroutine test_real_2d_pointer(x) end subroutine test_real_2d_pointer ! CHECK-LABEL: func.func @_QPtest_real_2d_pointer( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.ptr<!fir.array<?x?xf32>>>> {fir.bindc_name = "x"}) { -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFtest_real_2d_pointerEx"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?x?xf32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?x?xf32>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?x?xf32>>>>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFtest_real_2d_pointerEx"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?x?xf32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?x?xf32>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?x?xf32>>>>) ! CHECK: %[[VAL_2:.*]] = fir.load %[[VAL_1]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?x?xf32>>>> ! CHECK: %[[VAL_3:.*]] = fir.rebox %[[VAL_2]] : (!fir.box<!fir.ptr<!fir.array<?x?xf32>>>) -> !fir.class<!fir.array<?x?xnone>> ! CHECK: %[[VAL_4:.*]] = fir.convert %[[VAL_3]] : (!fir.class<!fir.array<?x?xnone>>) -> !fir.class<none> @@ -78,7 +78,7 @@ subroutine test_up_assumed_shape_1d_array(x) end subroutine test_up_assumed_shape_1d_array ! CHECK-LABEL: func.func @_QPtest_up_assumed_shape_1d_array( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.class<!fir.array<?xnone>> {fir.bindc_name = "x"}) { -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFtest_up_assumed_shape_1d_arrayEx"} : (!fir.class<!fir.array<?xnone>>, !fir.dscope) -> (!fir.class<!fir.array<?xnone>>, !fir.class<!fir.array<?xnone>>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFtest_up_assumed_shape_1d_arrayEx"} : (!fir.class<!fir.array<?xnone>>, !fir.dscope) -> (!fir.class<!fir.array<?xnone>>, !fir.class<!fir.array<?xnone>>) ! CHECK: %[[VAL_2:.*]] = fir.convert %[[VAL_1]]#0 : (!fir.class<!fir.array<?xnone>>) -> !fir.class<none> ! CHECK: fir.call @_QPcallee(%[[VAL_2]]) fastmath<contract> : (!fir.class<none>) -> () ! CHECK: return @@ -115,7 +115,7 @@ subroutine test_up_allocatable_2d_array(x) end subroutine test_up_allocatable_2d_array ! CHECK-LABEL: func.func @_QPtest_up_allocatable_2d_array( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.class<!fir.heap<!fir.array<?x?xnone>>>> {fir.bindc_name = "x"}) { -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFtest_up_allocatable_2d_arrayEx"} : (!fir.ref<!fir.class<!fir.heap<!fir.array<?x?xnone>>>>, !fir.dscope) -> (!fir.ref<!fir.class<!fir.heap<!fir.array<?x?xnone>>>>, !fir.ref<!fir.class<!fir.heap<!fir.array<?x?xnone>>>>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFtest_up_allocatable_2d_arrayEx"} : (!fir.ref<!fir.class<!fir.heap<!fir.array<?x?xnone>>>>, !fir.dscope) -> (!fir.ref<!fir.class<!fir.heap<!fir.array<?x?xnone>>>>, !fir.ref<!fir.class<!fir.heap<!fir.array<?x?xnone>>>>) ! CHECK: %[[VAL_2:.*]] = fir.load %[[VAL_1]]#0 : !fir.ref<!fir.class<!fir.heap<!fir.array<?x?xnone>>>> ! CHECK: %[[VAL_3:.*]] = fir.rebox %[[VAL_2]] : (!fir.class<!fir.heap<!fir.array<?x?xnone>>>) -> !fir.class<!fir.array<?x?xnone>> ! CHECK: %[[VAL_4:.*]] = fir.convert %[[VAL_3]] : (!fir.class<!fir.array<?x?xnone>>) -> !fir.class<none> @@ -130,7 +130,7 @@ subroutine test_up_pointer_1d_array(x) end subroutine test_up_pointer_1d_array ! CHECK-LABEL: func.func @_QPtest_up_pointer_1d_array( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.class<!fir.ptr<!fir.array<?xnone>>>> {fir.bindc_name = "x"}) { -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFtest_up_pointer_1d_arrayEx"} : (!fir.ref<!fir.class<!fir.ptr<!fir.array<?xnone>>>>, !fir.dscope) -> (!fir.ref<!fir.class<!fir.ptr<!fir.array<?xnone>>>>, !fir.ref<!fir.class<!fir.ptr<!fir.array<?xnone>>>>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFtest_up_pointer_1d_arrayEx"} : (!fir.ref<!fir.class<!fir.ptr<!fir.array<?xnone>>>>, !fir.dscope) -> (!fir.ref<!fir.class<!fir.ptr<!fir.array<?xnone>>>>, !fir.ref<!fir.class<!fir.ptr<!fir.array<?xnone>>>>) ! CHECK: %[[VAL_2:.*]] = fir.load %[[VAL_1]]#0 : !fir.ref<!fir.class<!fir.ptr<!fir.array<?xnone>>>> ! CHECK: %[[VAL_3:.*]] = fir.rebox %[[VAL_2]] : (!fir.class<!fir.ptr<!fir.array<?xnone>>>) -> !fir.class<!fir.array<?xnone>> ! CHECK: %[[VAL_4:.*]] = fir.convert %[[VAL_3]] : (!fir.class<!fir.array<?xnone>>) -> !fir.class<none> diff --git a/flang/test/Lower/HLFIR/implicit-type-conversion.f90 b/flang/test/Lower/HLFIR/implicit-type-conversion.f90 index dc2d111..f55784e 100644 --- a/flang/test/Lower/HLFIR/implicit-type-conversion.f90 +++ b/flang/test/Lower/HLFIR/implicit-type-conversion.f90 @@ -3,8 +3,8 @@ ! CHECK-LABEL: func.func @_QPtest1( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<i32> {fir.bindc_name = "x"}, ! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref<!fir.logical<4>> {fir.bindc_name = "y"}) { -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFtest1Ex"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFtest1Ey"} : (!fir.ref<!fir.logical<4>>, !fir.dscope) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFtest1Ex"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFtest1Ey"} : (!fir.ref<!fir.logical<4>>, !fir.dscope) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) ! CHECK: %[[VAL_4:.*]] = fir.load %[[VAL_3]]#0 : !fir.ref<!fir.logical<4>> ! CHECK: %[[VAL_5:.*]] = fir.convert %[[VAL_4]] : (!fir.logical<4>) -> i32 ! CHECK: hlfir.assign %[[VAL_5]] to %[[VAL_2]]#0 : i32, !fir.ref<i32> @@ -19,8 +19,8 @@ end subroutine test1 ! CHECK-LABEL: func.func @_QPtest2( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<i32> {fir.bindc_name = "x"}, ! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref<!fir.logical<4>> {fir.bindc_name = "y"}) { -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFtest2Ex"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFtest2Ey"} : (!fir.ref<!fir.logical<4>>, !fir.dscope) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFtest2Ex"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFtest2Ey"} : (!fir.ref<!fir.logical<4>>, !fir.dscope) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) ! CHECK: %[[VAL_4:.*]] = fir.load %[[VAL_2]]#0 : !fir.ref<i32> ! CHECK: %[[VAL_5:.*]] = fir.convert %[[VAL_4]] : (i32) -> !fir.logical<4> ! CHECK: hlfir.assign %[[VAL_5]] to %[[VAL_3]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>> @@ -35,8 +35,8 @@ end subroutine test2 ! CHECK-LABEL: func.func @_QPtest3( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.logical<4>> {fir.bindc_name = "x"}, ! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref<i32> {fir.bindc_name = "y"}) { -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFtest3Ex"} : (!fir.ref<!fir.logical<4>>, !fir.dscope) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFtest3Ey"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFtest3Ex"} : (!fir.ref<!fir.logical<4>>, !fir.dscope) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFtest3Ey"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_4:.*]] = fir.load %[[VAL_3]]#0 : !fir.ref<i32> ! CHECK: %[[VAL_5:.*]] = arith.constant 1 : i32 ! CHECK: %[[VAL_6:.*]] = arith.cmpi eq, %[[VAL_4]], %[[VAL_5]] : i32 @@ -54,8 +54,8 @@ end subroutine test3 ! CHECK-LABEL: func.func @_QPtest4( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<i32> {fir.bindc_name = "x"}, ! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref<i32> {fir.bindc_name = "y"}) { -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFtest4Ex"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFtest4Ey"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFtest4Ex"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFtest4Ey"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_4:.*]] = fir.load %[[VAL_3]]#0 : !fir.ref<i32> ! CHECK: %[[VAL_5:.*]] = arith.constant 1 : i32 ! CHECK: %[[VAL_6:.*]] = arith.cmpi eq, %[[VAL_4]], %[[VAL_5]] : i32 @@ -73,8 +73,8 @@ end subroutine test4 ! CHECK-LABEL: func.func @_QPtest5( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.box<!fir.array<?xi32>> {fir.bindc_name = "x"}, ! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref<!fir.logical<4>> {fir.bindc_name = "y"}) { -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFtest5Ex"} : (!fir.box<!fir.array<?xi32>>, !fir.dscope) -> (!fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>>) -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFtest5Ey"} : (!fir.ref<!fir.logical<4>>, !fir.dscope) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFtest5Ex"} : (!fir.box<!fir.array<?xi32>>, !fir.dscope) -> (!fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFtest5Ey"} : (!fir.ref<!fir.logical<4>>, !fir.dscope) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) ! CHECK: %[[VAL_4:.*]] = fir.load %[[VAL_3]]#0 : !fir.ref<!fir.logical<4>> ! CHECK: %[[VAL_5:.*]] = fir.convert %[[VAL_4]] : (!fir.logical<4>) -> i32 ! CHECK: hlfir.assign %[[VAL_5]] to %[[VAL_2]]#0 : i32, !fir.box<!fir.array<?xi32>> @@ -89,8 +89,8 @@ end subroutine test5 ! CHECK-LABEL: func.func @_QPtest6( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.box<!fir.array<?xi32>> {fir.bindc_name = "x"}, ! CHECK-SAME: %[[VAL_1:.*]]: !fir.box<!fir.array<?x!fir.logical<4>>> {fir.bindc_name = "y"}) { -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFtest6Ex"} : (!fir.box<!fir.array<?xi32>>, !fir.dscope) -> (!fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>>) -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFtest6Ey"} : (!fir.box<!fir.array<?x!fir.logical<4>>>, !fir.dscope) -> (!fir.box<!fir.array<?x!fir.logical<4>>>, !fir.box<!fir.array<?x!fir.logical<4>>>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFtest6Ex"} : (!fir.box<!fir.array<?xi32>>, !fir.dscope) -> (!fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFtest6Ey"} : (!fir.box<!fir.array<?x!fir.logical<4>>>, !fir.dscope) -> (!fir.box<!fir.array<?x!fir.logical<4>>>, !fir.box<!fir.array<?x!fir.logical<4>>>) ! CHECK: %[[VAL_4:.*]] = arith.constant 0 : index ! CHECK: %[[VAL_5:.*]]:3 = fir.box_dims %[[VAL_3]]#0, %[[VAL_4]] : (!fir.box<!fir.array<?x!fir.logical<4>>>, index) -> (index, index, index) ! CHECK: %[[VAL_6:.*]] = fir.shape %[[VAL_5]]#1 : (index) -> !fir.shape<1> @@ -114,8 +114,8 @@ end subroutine test6 ! CHECK-LABEL: func.func @_QPtest7( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.box<!fir.array<?x!fir.logical<4>>> {fir.bindc_name = "x"}, ! CHECK-SAME: %[[VAL_1:.*]]: !fir.box<!fir.array<?xi32>> {fir.bindc_name = "y"}) { -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFtest7Ex"} : (!fir.box<!fir.array<?x!fir.logical<4>>>, !fir.dscope) -> (!fir.box<!fir.array<?x!fir.logical<4>>>, !fir.box<!fir.array<?x!fir.logical<4>>>) -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFtest7Ey"} : (!fir.box<!fir.array<?xi32>>, !fir.dscope) -> (!fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFtest7Ex"} : (!fir.box<!fir.array<?x!fir.logical<4>>>, !fir.dscope) -> (!fir.box<!fir.array<?x!fir.logical<4>>>, !fir.box<!fir.array<?x!fir.logical<4>>>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFtest7Ey"} : (!fir.box<!fir.array<?xi32>>, !fir.dscope) -> (!fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>>) ! CHECK: %[[VAL_4:.*]] = arith.constant 0 : index ! CHECK: %[[VAL_5:.*]]:3 = fir.box_dims %[[VAL_3]]#0, %[[VAL_4]] : (!fir.box<!fir.array<?xi32>>, index) -> (index, index, index) ! CHECK: %[[VAL_6:.*]] = fir.shape %[[VAL_5]]#1 : (index) -> !fir.shape<1> diff --git a/flang/test/Lower/HLFIR/index.f90 b/flang/test/Lower/HLFIR/index.f90 index a36027f..84cdd58 100644 --- a/flang/test/Lower/HLFIR/index.f90 +++ b/flang/test/Lower/HLFIR/index.f90 @@ -13,7 +13,7 @@ end subroutine t ! CHECK: %[[VAL_1:.*]] = fir.alloca i32 {bindc_name = "n", uniq_name = "_QFtEn"} ! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "_QFtEn"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_3:.*]]:2 = fir.unboxchar %[[ARG0]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index) -! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_3]]#0 typeparams %[[VAL_3]]#1 dummy_scope %[[VAL_0]] {uniq_name = "_QFtEs"} : (!fir.ref<!fir.char<1,?>>, index, !fir.dscope) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>) +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_3]]#0 typeparams %[[VAL_3]]#1 dummy_scope %[[VAL_0]] arg {{[0-9]+}} {uniq_name = "_QFtEs"} : (!fir.ref<!fir.char<1,?>>, index, !fir.dscope) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>) ! CHECK: %[[VAL_5:.*]] = fir.address_of(@_QQclX74686973) : !fir.ref<!fir.char<1,4>> ! CHECK: %[[VAL_6:.*]] = arith.constant 4 : index ! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_5]] typeparams %[[VAL_6]] {fortran_attrs = #fir.var_attrs<parameter>, uniq_name = "_QQclX74686973"} : (!fir.ref<!fir.char<1,4>>, index) -> (!fir.ref<!fir.char<1,4>>, !fir.ref<!fir.char<1,4>>) @@ -31,11 +31,11 @@ end subroutine t1 ! CHECK-SAME: %[[ARG0:.*]]: !fir.boxchar<1> {fir.bindc_name = "s"}, ! CHECK-SAME: %[[ARG1:.*]]: !fir.ref<!fir.logical<4>> {fir.bindc_name = "b"}) { ! CHECK: %[[VAL_0:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %[[VAL_0]] {uniq_name = "_QFt1Eb"} : (!fir.ref<!fir.logical<4>>, !fir.dscope) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %[[VAL_0]] arg {{[0-9]+}} {uniq_name = "_QFt1Eb"} : (!fir.ref<!fir.logical<4>>, !fir.dscope) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) ! CHECK: %[[VAL_2:.*]] = fir.alloca i32 {bindc_name = "n", uniq_name = "_QFt1En"} ! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]] {uniq_name = "_QFt1En"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_4:.*]]:2 = fir.unboxchar %[[ARG0]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index) -! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_4]]#0 typeparams %[[VAL_4]]#1 dummy_scope %[[VAL_0]] {uniq_name = "_QFt1Es"} : (!fir.ref<!fir.char<1,?>>, index, !fir.dscope) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>) +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_4]]#0 typeparams %[[VAL_4]]#1 dummy_scope %[[VAL_0]] arg {{[0-9]+}} {uniq_name = "_QFt1Es"} : (!fir.ref<!fir.char<1,?>>, index, !fir.dscope) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>) ! CHECK: %[[VAL_6:.*]] = fir.address_of(@_QQclX74686973) : !fir.ref<!fir.char<1,4>> ! CHECK: %[[VAL_7:.*]] = arith.constant 4 : index ! CHECK: %[[VAL_8:.*]]:2 = hlfir.declare %[[VAL_6]] typeparams %[[VAL_7]] {fortran_attrs = #fir.var_attrs<parameter>, uniq_name = "_QQclX74686973"} : (!fir.ref<!fir.char<1,4>>, index) -> (!fir.ref<!fir.char<1,4>>, !fir.ref<!fir.char<1,4>>) @@ -55,11 +55,11 @@ end subroutine t2 ! CHECK-SAME: %[[ARG1:.*]]: !fir.boxchar<2> {fir.bindc_name = "c"}) { ! CHECK: %[[VAL_0:.*]] = fir.dummy_scope : !fir.dscope ! CHECK: %[[VAL_1:.*]]:2 = fir.unboxchar %[[ARG1]] : (!fir.boxchar<2>) -> (!fir.ref<!fir.char<2,?>>, index) -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]]#0 typeparams %[[VAL_1]]#1 dummy_scope %[[VAL_0]] {uniq_name = "_QFt2Ec"} : (!fir.ref<!fir.char<2,?>>, index, !fir.dscope) -> (!fir.boxchar<2>, !fir.ref<!fir.char<2,?>>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]]#0 typeparams %[[VAL_1]]#1 dummy_scope %[[VAL_0]] arg {{[0-9]+}} {uniq_name = "_QFt2Ec"} : (!fir.ref<!fir.char<2,?>>, index, !fir.dscope) -> (!fir.boxchar<2>, !fir.ref<!fir.char<2,?>>) ! CHECK: %[[VAL_3:.*]] = fir.alloca i32 {bindc_name = "n", uniq_name = "_QFt2En"} ! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_3]] {uniq_name = "_QFt2En"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_5:.*]]:2 = fir.unboxchar %[[ARG0]] : (!fir.boxchar<2>) -> (!fir.ref<!fir.char<2,?>>, index) -! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_5]]#0 typeparams %[[VAL_5]]#1 dummy_scope %[[VAL_0]] {uniq_name = "_QFt2Es"} : (!fir.ref<!fir.char<2,?>>, index, !fir.dscope) -> (!fir.boxchar<2>, !fir.ref<!fir.char<2,?>>) +! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_5]]#0 typeparams %[[VAL_5]]#1 dummy_scope %[[VAL_0]] arg {{[0-9]+}} {uniq_name = "_QFt2Es"} : (!fir.ref<!fir.char<2,?>>, index, !fir.dscope) -> (!fir.boxchar<2>, !fir.ref<!fir.char<2,?>>) ! CHECK: %[[VAL_7:.*]] = arith.constant false ! CHECK: %[[VAL_8:.*]] = hlfir.index %[[VAL_2]]#0 in %[[VAL_6]]#0 back %[[VAL_7]] : (!fir.boxchar<2>, !fir.boxchar<2>, i1) -> i32 ! CHECK: hlfir.assign %[[VAL_8]] to %[[VAL_4]]#0 : i32, !fir.ref<i32> @@ -75,11 +75,11 @@ end subroutine t3 ! CHECK-SAME: %[[ARG1:.*]]: !fir.boxchar<4> {fir.bindc_name = "c"}) { ! CHECK: %[[VAL_0:.*]] = fir.dummy_scope : !fir.dscope ! CHECK: %[[VAL_1:.*]]:2 = fir.unboxchar %[[ARG1]] : (!fir.boxchar<4>) -> (!fir.ref<!fir.char<4,?>>, index) -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]]#0 typeparams %[[VAL_1]]#1 dummy_scope %[[VAL_0]] {uniq_name = "_QFt3Ec"} : (!fir.ref<!fir.char<4,?>>, index, !fir.dscope) -> (!fir.boxchar<4>, !fir.ref<!fir.char<4,?>>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]]#0 typeparams %[[VAL_1]]#1 dummy_scope %[[VAL_0]] arg {{[0-9]+}} {uniq_name = "_QFt3Ec"} : (!fir.ref<!fir.char<4,?>>, index, !fir.dscope) -> (!fir.boxchar<4>, !fir.ref<!fir.char<4,?>>) ! CHECK: %[[VAL_3:.*]] = fir.alloca i32 {bindc_name = "n", uniq_name = "_QFt3En"} ! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_3]] {uniq_name = "_QFt3En"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_5:.*]]:2 = fir.unboxchar %[[ARG0]] : (!fir.boxchar<4>) -> (!fir.ref<!fir.char<4,?>>, index) -! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_5]]#0 typeparams %[[VAL_5]]#1 dummy_scope %[[VAL_0]] {uniq_name = "_QFt3Es"} : (!fir.ref<!fir.char<4,?>>, index, !fir.dscope) -> (!fir.boxchar<4>, !fir.ref<!fir.char<4,?>>) +! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_5]]#0 typeparams %[[VAL_5]]#1 dummy_scope %[[VAL_0]] arg {{[0-9]+}} {uniq_name = "_QFt3Es"} : (!fir.ref<!fir.char<4,?>>, index, !fir.dscope) -> (!fir.boxchar<4>, !fir.ref<!fir.char<4,?>>) ! CHECK: %[[VAL_7:.*]] = arith.constant true ! CHECK: %[[VAL_8:.*]] = hlfir.index %[[VAL_2]]#0 in %[[VAL_6]]#0 back %[[VAL_7]] : (!fir.boxchar<4>, !fir.boxchar<4>, i1) -> i8 ! CHECK: %[[VAL_9:.*]] = fir.convert %[[VAL_8]] : (i8) -> i32 @@ -100,12 +100,12 @@ end subroutine t4 ! CHECK: %[[VAL_2:.*]] = fir.convert %[[VAL_1]]#0 : (!fir.ref<!fir.char<1,?>>) -> !fir.ref<!fir.array<3x!fir.char<1,?>>> ! CHECK: %[[VAL_3:.*]] = arith.constant 3 : index ! CHECK: %[[VAL_4:.*]] = fir.shape %[[VAL_3]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_2]](%[[VAL_4]]) typeparams %[[VAL_1]]#1 dummy_scope %[[VAL_0]] {uniq_name = "_QFt4Ec1"} : (!fir.ref<!fir.array<3x!fir.char<1,?>>>, !fir.shape<1>, index, !fir.dscope) -> (!fir.box<!fir.array<3x!fir.char<1,?>>>, !fir.ref<!fir.array<3x!fir.char<1,?>>>) +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_2]](%[[VAL_4]]) typeparams %[[VAL_1]]#1 dummy_scope %[[VAL_0]] arg {{[0-9]+}} {uniq_name = "_QFt4Ec1"} : (!fir.ref<!fir.array<3x!fir.char<1,?>>>, !fir.shape<1>, index, !fir.dscope) -> (!fir.box<!fir.array<3x!fir.char<1,?>>>, !fir.ref<!fir.array<3x!fir.char<1,?>>>) ! CHECK: %[[VAL_6:.*]]:2 = fir.unboxchar %[[ARG1]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index) ! CHECK: %[[VAL_7:.*]] = fir.convert %[[VAL_6]]#0 : (!fir.ref<!fir.char<1,?>>) -> !fir.ref<!fir.array<3x!fir.char<1,?>>> ! CHECK: %[[VAL_8:.*]] = arith.constant 3 : index ! CHECK: %[[VAL_9:.*]] = fir.shape %[[VAL_8]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_10:.*]]:2 = hlfir.declare %[[VAL_7]](%[[VAL_9]]) typeparams %[[VAL_6]]#1 dummy_scope %[[VAL_0]] {uniq_name = "_QFt4Ec2"} : (!fir.ref<!fir.array<3x!fir.char<1,?>>>, !fir.shape<1>, index, !fir.dscope) -> (!fir.box<!fir.array<3x!fir.char<1,?>>>, !fir.ref<!fir.array<3x!fir.char<1,?>>>) +! CHECK: %[[VAL_10:.*]]:2 = hlfir.declare %[[VAL_7]](%[[VAL_9]]) typeparams %[[VAL_6]]#1 dummy_scope %[[VAL_0]] arg {{[0-9]+}} {uniq_name = "_QFt4Ec2"} : (!fir.ref<!fir.array<3x!fir.char<1,?>>>, !fir.shape<1>, index, !fir.dscope) -> (!fir.box<!fir.array<3x!fir.char<1,?>>>, !fir.ref<!fir.array<3x!fir.char<1,?>>>) ! CHECK: %[[VAL_11:.*]] = arith.constant 3 : index ! CHECK: %[[VAL_12:.*]] = fir.alloca !fir.array<3xi8> {bindc_name = "n", uniq_name = "_QFt4En"} ! CHECK: %[[VAL_13:.*]] = fir.shape %[[VAL_11]] : (index) -> !fir.shape<1> @@ -137,9 +137,9 @@ end program test ! CHECK-SAME: %[[ARG2:.*]]: !fir.box<!fir.array<?x!fir.logical<4>>> {fir.bindc_name = "c", fir.optional}) attributes {fir.host_symbol = @_QQmain, llvm.linkage = #llvm.linkage<internal>} { ! CHECK: %[[VAL_0:.*]] = fir.dummy_scope : !fir.dscope ! CHECK: %[[VAL_1:.*]]:2 = fir.unboxchar %[[ARG0]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index) -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]]#0 typeparams %[[VAL_1]]#1 dummy_scope %[[VAL_0]] {uniq_name = "_QFFsubEa"} : (!fir.ref<!fir.char<1,?>>, index, !fir.dscope) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>) -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %[[VAL_0]] {uniq_name = "_QFFsubEb"} : (!fir.box<!fir.array<?x!fir.char<1,?>>>, !fir.dscope) -> (!fir.box<!fir.array<?x!fir.char<1,?>>>, !fir.box<!fir.array<?x!fir.char<1,?>>>) -! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[ARG2]] dummy_scope %[[VAL_0]] {fortran_attrs = #fir.var_attrs<optional>, uniq_name = "_QFFsubEc"} : (!fir.box<!fir.array<?x!fir.logical<4>>>, !fir.dscope) -> (!fir.box<!fir.array<?x!fir.logical<4>>>, !fir.box<!fir.array<?x!fir.logical<4>>>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]]#0 typeparams %[[VAL_1]]#1 dummy_scope %[[VAL_0]] arg {{[0-9]+}} {uniq_name = "_QFFsubEa"} : (!fir.ref<!fir.char<1,?>>, index, !fir.dscope) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %[[VAL_0]] arg {{[0-9]+}} {uniq_name = "_QFFsubEb"} : (!fir.box<!fir.array<?x!fir.char<1,?>>>, !fir.dscope) -> (!fir.box<!fir.array<?x!fir.char<1,?>>>, !fir.box<!fir.array<?x!fir.char<1,?>>>) +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[ARG2]] dummy_scope %[[VAL_0]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<optional>, uniq_name = "_QFFsubEc"} : (!fir.box<!fir.array<?x!fir.logical<4>>>, !fir.dscope) -> (!fir.box<!fir.array<?x!fir.logical<4>>>, !fir.box<!fir.array<?x!fir.logical<4>>>) ! CHECK: %[[VAL_10:.*]] = fir.is_present %[[VAL_4]]#0 : (!fir.box<!fir.array<?x!fir.logical<4>>>) -> i1 ! CHECK: %[[VAL_11:.*]] = arith.constant 0 : index ! CHECK: %[[VAL_12:.*]]:3 = fir.box_dims %[[VAL_3]]#0, %[[VAL_11]] : (!fir.box<!fir.array<?x!fir.char<1,?>>>, index) -> (index, index, index) diff --git a/flang/test/Lower/HLFIR/intentout-allocatable-components.f90 b/flang/test/Lower/HLFIR/intentout-allocatable-components.f90 index 8cb733a..4093452 100644 --- a/flang/test/Lower/HLFIR/intentout-allocatable-components.f90 +++ b/flang/test/Lower/HLFIR/intentout-allocatable-components.f90 @@ -10,7 +10,7 @@ subroutine test_intentout_component_deallocate(a) end subroutine ! CHECK-LABEL: func.func @_QPtest_intentout_component_deallocate( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.type<_QFtest_intentout_component_deallocateTt{x:!fir.box<!fir.heap<i32>>}>> -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<intent_out>, uniq_name = "_QFtest_intentout_component_deallocateEa"} +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<intent_out>, uniq_name = "_QFtest_intentout_component_deallocateEa"} ! CHECK: %[[VAL_2:.*]] = fir.embox %[[VAL_1]]#0 : (!fir.ref<!fir.type<_QFtest_intentout_component_deallocateTt{x:!fir.box<!fir.heap<i32>>}>>) -> !fir.box<!fir.type<_QFtest_intentout_component_deallocateTt{x:!fir.box<!fir.heap<i32>>}>> ! CHECK: %[[VAL_3:.*]] = fir.convert %[[VAL_2]] : (!fir.box<!fir.type<_QFtest_intentout_component_deallocateTt{x:!fir.box<!fir.heap<i32>>}>>) -> !fir.box<none> ! CHECK: fir.call @_FortranADestroy(%[[VAL_3]]) fastmath<contract> : (!fir.box<none>) -> () @@ -23,7 +23,7 @@ subroutine test_intentout_optional_component_deallocate(a) end subroutine ! CHECK-LABEL: func.func @_QPtest_intentout_optional_component_deallocate( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.type<_QFtest_intentout_optional_component_deallocateTt{x:!fir.box<!fir.heap<i32>>}>> -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<intent_out, optional>, uniq_name = "_QFtest_intentout_optional_component_deallocateEa"} +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<intent_out, optional>, uniq_name = "_QFtest_intentout_optional_component_deallocateEa"} ! CHECK: %[[VAL_2:.*]] = fir.is_present %[[VAL_1]]#0 : (!fir.ref<!fir.type<_QFtest_intentout_optional_component_deallocateTt{x:!fir.box<!fir.heap<i32>>}>>) -> i1 ! CHECK: fir.if %[[VAL_2]] { ! CHECK: %[[VAL_3:.*]] = fir.embox %[[VAL_1]]#0 : (!fir.ref<!fir.type<_QFtest_intentout_optional_component_deallocateTt{x:!fir.box<!fir.heap<i32>>}>>) -> !fir.box<!fir.type<_QFtest_intentout_optional_component_deallocateTt{x:!fir.box<!fir.heap<i32>>}>> diff --git a/flang/test/Lower/HLFIR/internal-procedures.f90 b/flang/test/Lower/HLFIR/internal-procedures.f90 index f0e168a..07e4ebc 100644 --- a/flang/test/Lower/HLFIR/internal-procedures.f90 +++ b/flang/test/Lower/HLFIR/internal-procedures.f90 @@ -70,7 +70,7 @@ contains end subroutine ! CHECK-LABEL: func.func @_QPtest_proc_pointer( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.boxproc<() -> ()>>) { -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer, internal_assoc>, uniq_name = "_QFtest_proc_pointerEp"} : (!fir.ref<!fir.boxproc<() -> ()>>, !fir.dscope) -> (!fir.ref<!fir.boxproc<() -> ()>>, !fir.ref<!fir.boxproc<() -> ()>>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer, internal_assoc>, uniq_name = "_QFtest_proc_pointerEp"} : (!fir.ref<!fir.boxproc<() -> ()>>, !fir.dscope) -> (!fir.ref<!fir.boxproc<() -> ()>>, !fir.ref<!fir.boxproc<() -> ()>>) ! CHECK: %[[VAL_2:.*]] = fir.alloca tuple<!fir.ref<!fir.boxproc<() -> ()>>> ! CHECK: %[[VAL_3:.*]] = arith.constant 0 : i32 ! CHECK: %[[VAL_4:.*]] = fir.coordinate_of %[[VAL_2]], %[[VAL_3]] : (!fir.ref<tuple<!fir.ref<!fir.boxproc<() -> ()>>>>, i32) -> !fir.llvm_ptr<!fir.ref<!fir.boxproc<() -> ()>>> diff --git a/flang/test/Lower/HLFIR/intrinsic-dynamically-optional.f90 b/flang/test/Lower/HLFIR/intrinsic-dynamically-optional.f90 index 6830175..79cc58d 100644 --- a/flang/test/Lower/HLFIR/intrinsic-dynamically-optional.f90 +++ b/flang/test/Lower/HLFIR/intrinsic-dynamically-optional.f90 @@ -166,10 +166,10 @@ end function ! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref<!fir.array<3xf32>> {fir.bindc_name = "imaginary", fir.optional}) -> !fir.array<3xcomplex<f32>> { ! CHECK: %[[VAL_2:.*]] = arith.constant 3 : index ! CHECK: %[[VAL_3:.*]] = fir.shape %[[VAL_2]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_1]](%[[VAL_3]]) dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<optional>, uniq_name = "_QFtest_elemental_optional_as_valueEimaginary"} : (!fir.ref<!fir.array<3xf32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<3xf32>>, !fir.ref<!fir.array<3xf32>>) +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_1]](%[[VAL_3]]) dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<optional>, uniq_name = "_QFtest_elemental_optional_as_valueEimaginary"} : (!fir.ref<!fir.array<3xf32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<3xf32>>, !fir.ref<!fir.array<3xf32>>) ! CHECK: %[[VAL_5:.*]] = arith.constant 3 : index ! CHECK: %[[VAL_6:.*]] = fir.shape %[[VAL_5]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_6]]) dummy_scope %{{[0-9]+}} {uniq_name = "_QFtest_elemental_optional_as_valueEreal"} : (!fir.ref<!fir.array<3xf32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<3xf32>>, !fir.ref<!fir.array<3xf32>>) +! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_6]]) dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFtest_elemental_optional_as_valueEreal"} : (!fir.ref<!fir.array<3xf32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<3xf32>>, !fir.ref<!fir.array<3xf32>>) ! CHECK: %[[VAL_8:.*]] = arith.constant 3 : index ! CHECK: %[[VAL_9:.*]] = fir.alloca !fir.array<3xcomplex<f32>> {bindc_name = "test_elemental_optional_as_value", uniq_name = "_QFtest_elemental_optional_as_valueEtest_elemental_optional_as_value"} ! CHECK: %[[VAL_10:.*]] = fir.shape %[[VAL_8]] : (index) -> !fir.shape<1> diff --git a/flang/test/Lower/HLFIR/issue80884.f90 b/flang/test/Lower/HLFIR/issue80884.f90 index a5a5178..063f371 100644 --- a/flang/test/Lower/HLFIR/issue80884.f90 +++ b/flang/test/Lower/HLFIR/issue80884.f90 @@ -14,21 +14,22 @@ end subroutine ! CHECK-LABEL: func.func @_QPissue80884( ! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %{{.*}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFissue80884Ep"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>) ! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %{{.*}} {fortran_attrs = #fir.var_attrs<target>, uniq_name = "_QFissue80884Etarg"} : (!fir.ref<!fir.type<_QFissue80884Tt{t0:!fir.type<_QFissue80884Tt0{array:!fir.array<10x10xf32>}>}>>, !fir.dscope) -> (!fir.ref<!fir.type<_QFissue80884Tt{t0:!fir.type<_QFissue80884Tt0{array:!fir.array<10x10xf32>}>}>>, !fir.ref<!fir.type<_QFissue80884Tt{t0:!fir.type<_QFissue80884Tt0{array:!fir.array<10x10xf32>}>}>>) -! CHECK: %[[VAL_4:.*]] = arith.constant 1 : i64 -! CHECK: %[[VAL_5:.*]] = arith.constant 100 : i64 ! CHECK: %[[VAL_6:.*]] = hlfir.designate %[[VAL_3]]#0{"t0"} : (!fir.ref<!fir.type<_QFissue80884Tt{t0:!fir.type<_QFissue80884Tt0{array:!fir.array<10x10xf32>}>}>>) -> !fir.ref<!fir.type<_QFissue80884Tt0{array:!fir.array<10x10xf32>}>> ! CHECK: %[[VAL_7:.*]] = arith.constant 10 : index ! CHECK: %[[VAL_8:.*]] = arith.constant 10 : index ! CHECK: %[[VAL_9:.*]] = fir.shape %[[VAL_7]], %[[VAL_8]] : (index, index) -> !fir.shape<2> ! CHECK: %[[VAL_10:.*]] = hlfir.designate %[[VAL_6]]{"array"} shape %[[VAL_9]] : (!fir.ref<!fir.type<_QFissue80884Tt0{array:!fir.array<10x10xf32>}>>, !fir.shape<2>) -> !fir.ref<!fir.array<10x10xf32>> +! CHECK: %[[CAST:.*]] = fir.convert %[[VAL_10]] : (!fir.ref<!fir.array<10x10xf32>>) -> !fir.ref<!fir.array<?x?xf32>> +! CHECK: %[[BOX:.*]] = fir.embox %[[CAST]](%[[VAL_9]]) : (!fir.ref<!fir.array<?x?xf32>>, !fir.shape<2>) -> !fir.box<!fir.ptr<!fir.array<?x?xf32>>> ! CHECK: %[[VAL_11:.*]] = arith.constant 1 : index +! CHECK: %[[VAL_4:.*]] = arith.constant 1 : i64 ! CHECK: %[[VAL_12:.*]] = fir.convert %[[VAL_4]] : (i64) -> index +! CHECK: %[[VAL_5:.*]] = arith.constant 100 : i64 ! CHECK: %[[VAL_13:.*]] = fir.convert %[[VAL_5]] : (i64) -> index ! CHECK: %[[VAL_14:.*]] = arith.subi %[[VAL_13]], %[[VAL_12]] : index ! CHECK: %[[VAL_15:.*]] = arith.addi %[[VAL_14]], %[[VAL_11]] : index ! CHECK: %[[cmp0:.*]] = arith.cmpi sgt, %[[VAL_15]], %c0{{.*}} : index ! CHECK: %[[ext0:.*]] = arith.select %[[cmp0]], %[[VAL_15]], %c0{{.*}} : index -! CHECK: %[[VAL_16:.*]] = fir.convert %[[VAL_10]] : (!fir.ref<!fir.array<10x10xf32>>) -> !fir.ref<!fir.array<?xf32>> -! CHECK: %[[VAL_17:.*]] = fir.shape_shift %[[VAL_4]], %[[ext0]] : (i64, index) -> !fir.shapeshift<1> -! CHECK: %[[VAL_18:.*]] = fir.embox %[[VAL_16]](%[[VAL_17]]) : (!fir.ref<!fir.array<?xf32>>, !fir.shapeshift<1>) -> !fir.box<!fir.ptr<!fir.array<?xf32>>> +! CHECK: %[[VAL_17:.*]] = fir.shape_shift %[[VAL_12]], %[[ext0]] : (index, index) -> !fir.shapeshift<1> +! CHECK: %[[VAL_18:.*]] = fir.rebox %[[BOX]](%[[VAL_17]]) : (!fir.box<!fir.ptr<!fir.array<?x?xf32>>>, !fir.shapeshift<1>) -> !fir.box<!fir.ptr<!fir.array<?xf32>>> ! CHECK: fir.store %[[VAL_18]] to %[[VAL_2]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>> diff --git a/flang/test/Lower/HLFIR/proc-pointer-comp-nopass.f90 b/flang/test/Lower/HLFIR/proc-pointer-comp-nopass.f90 index 206b6e4..594b6e9 100644 --- a/flang/test/Lower/HLFIR/proc-pointer-comp-nopass.f90 +++ b/flang/test/Lower/HLFIR/proc-pointer-comp-nopass.f90 @@ -57,10 +57,9 @@ end subroutine ! CHECK-LABEL: func.func @_QPtest3( ! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0:[a-z0-9]*]] {{.*}}Ex ! CHECK: %[[VAL_2:.*]] = hlfir.designate %[[VAL_1]]#0{"p"} {fortran_attrs = #fir.var_attrs<pointer>} : (!fir.ref<!fir.type<_QMproc_comp_defsTt{j:i32,p:!fir.boxproc<(!fir.ref<f32>) -> f32>}>>) -> !fir.ref<!fir.boxproc<(!fir.ref<f32>) -> f32>> -! CHECK: %[[VAL_3:.*]] = fir.zero_bits () -> () -! CHECK: %[[VAL_4:.*]] = fir.emboxproc %[[VAL_3]] : (() -> ()) -> !fir.boxproc<() -> ()> -! CHECK: %[[VAL_5:.*]] = fir.convert %[[VAL_4]] : (!fir.boxproc<() -> ()>) -> !fir.boxproc<(!fir.ref<f32>) -> f32> -! CHECK: fir.store %[[VAL_5]] to %[[VAL_2]] : !fir.ref<!fir.boxproc<(!fir.ref<f32>) -> f32>> +! CHECK: %[[VAL_3:.*]] = fir.zero_bits (!fir.ref<f32>) -> f32 +! CHECK: %[[VAL_4:.*]] = fir.emboxproc %[[VAL_3]] : ((!fir.ref<f32>) -> f32) -> !fir.boxproc<(!fir.ref<f32>) -> f32> +! CHECK: fir.store %[[VAL_4]] to %[[VAL_2]] : !fir.ref<!fir.boxproc<(!fir.ref<f32>) -> f32>> subroutine test4(x) use proc_comp_defs, only : t diff --git a/flang/test/Lower/HLFIR/procedure-pointer-component-default-init.f90 b/flang/test/Lower/HLFIR/procedure-pointer-component-default-init.f90 index 8593126..61cc743 100644 --- a/flang/test/Lower/HLFIR/procedure-pointer-component-default-init.f90 +++ b/flang/test/Lower/HLFIR/procedure-pointer-component-default-init.f90 @@ -1,5 +1,5 @@ ! Test procedure pointer component default initialization when the size -! of the derived type is 32 bytes and larger. +! of the derived type is 32 bytes and larger. ! RUN: bbc -emit-hlfir -o - %s | FileCheck %s interface diff --git a/flang/test/Lower/HLFIR/procedure-pointer.f90 b/flang/test/Lower/HLFIR/procedure-pointer.f90 index 053c44f..23e4e842 100644 --- a/flang/test/Lower/HLFIR/procedure-pointer.f90 +++ b/flang/test/Lower/HLFIR/procedure-pointer.f90 @@ -11,7 +11,7 @@ module m real :: x end function character(:) function char_func(x) - pointer :: char_func + pointer :: char_func integer :: x end function subroutine sub(x) @@ -26,6 +26,7 @@ module m end module m !!! Testing declaration and initialization +! CHECK-LABEL: sub1 subroutine sub1() use m procedure(real_func), pointer :: p1 @@ -71,6 +72,7 @@ end subroutine sub1 !!! Testing pointer assignment and invocation +! CHECK-LABEL: sub2 subroutine sub2() use m procedure(real_func), pointer :: p1 @@ -81,12 +83,12 @@ use m ! CHECK: %[[VAL_2:.*]] = fir.emboxproc %[[VAL_1]] : ((!fir.ref<f32>) -> f32) -> !fir.boxproc<(!fir.ref<f32>) -> f32> ! CHECK: fir.store %[[VAL_2]] to %[[VAL_0]] : !fir.ref<!fir.boxproc<(!fir.ref<f32>) -> f32>> ! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFsub2Ep1"} : (!fir.ref<!fir.boxproc<(!fir.ref<f32>) -> f32>>) -> (!fir.ref<!fir.boxproc<(!fir.ref<f32>) -> f32>>, !fir.ref<!fir.boxproc<(!fir.ref<f32>) -> f32>>) -! CHECK: %[[VAL_4:.*]] = fir.zero_bits () -> () -! CHECK: %[[VAL_5:.*]] = fir.emboxproc %[[VAL_4]] : (() -> ()) -> !fir.boxproc<() -> ()> -! CHECK: %[[VAL_6:.*]] = fir.convert %[[VAL_5]] : (!fir.boxproc<() -> ()>) -> !fir.boxproc<(!fir.ref<f32>) -> f32> -! CHECK: fir.store %[[VAL_6]] to %[[VAL_3]]#0 : !fir.ref<!fir.boxproc<(!fir.ref<f32>) -> f32>> +! CHECK: %[[VAL_4:.*]] = fir.zero_bits (!fir.ref<f32>) -> f32 +! CHECK: %[[VAL_5:.*]] = fir.emboxproc %[[VAL_4]] : ((!fir.ref<f32>) -> f32) -> !fir.boxproc<(!fir.ref<f32>) -> f32> +! CHECK: fir.store %[[VAL_5]] to %[[VAL_3]]#0 : !fir.ref<!fir.boxproc<(!fir.ref<f32>) -> f32>> end subroutine +! CHECK-LABEL: sub3 subroutine sub3() use m procedure(real_func), pointer :: p1 @@ -148,7 +150,7 @@ subroutine sub5() use m procedure(real), pointer :: p3 - p3 => real_func + p3 => real_func ! CHECK: %[[VAL_0:.*]] = fir.alloca !fir.boxproc<() -> f32> {bindc_name = "p3", uniq_name = "_QFsub5Ep3"} ! CHECK: %[[VAL_1:.*]] = fir.zero_bits () -> f32 ! CHECK: %[[VAL_2:.*]] = fir.emboxproc %[[VAL_1]] : (() -> f32) -> !fir.boxproc<() -> f32> @@ -165,7 +167,7 @@ use m procedure(), pointer :: p4 real :: r - p4 => sub + p4 => sub ! CHECK: %[[VAL_0:.*]] = fir.alloca !fir.boxproc<() -> ()> {bindc_name = "p4", uniq_name = "_QFsub6Ep4"} ! CHECK: %[[VAL_1:.*]] = fir.zero_bits () -> () ! CHECK: %[[VAL_2:.*]] = fir.emboxproc %[[VAL_1]] : (() -> ()) -> !fir.boxproc<() -> ()> @@ -186,10 +188,10 @@ end subroutine subroutine sub7(p1, p2) use m procedure(real_func), pointer :: p1 -! CHECK: %[[VAL_0:.*]]:2 = hlfir.declare %arg0 dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFsub7Ep1"} : (!fir.ref<!fir.boxproc<() -> ()>>, !fir.dscope) -> (!fir.ref<!fir.boxproc<() -> ()>>, !fir.ref<!fir.boxproc<() -> ()>>) +! CHECK: %[[VAL_0:.*]]:2 = hlfir.declare %arg0 dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFsub7Ep1"} : (!fir.ref<!fir.boxproc<() -> ()>>, !fir.dscope) -> (!fir.ref<!fir.boxproc<() -> ()>>, !fir.ref<!fir.boxproc<() -> ()>>) procedure(char_func), pointer :: p2 -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %arg1 dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFsub7Ep2"} : (!fir.ref<!fir.boxproc<() -> ()>>, !fir.dscope) -> (!fir.ref<!fir.boxproc<() -> ()>>, !fir.ref<!fir.boxproc<() -> ()>>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %arg1 dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFsub7Ep2"} : (!fir.ref<!fir.boxproc<() -> ()>>, !fir.dscope) -> (!fir.ref<!fir.boxproc<() -> ()>>, !fir.ref<!fir.boxproc<() -> ()>>) call foo1(p1) ! CHECK: %[[VAL_2:.*]] = fir.load %[[VAL_0]]#0 : !fir.ref<!fir.boxproc<() -> ()>> @@ -197,7 +199,7 @@ use m call foo2(p2) ! CHECK: fir.call @_QPfoo2(%[[VAL_1]]#0) fastmath<contract> : (!fir.ref<!fir.boxproc<() -> ()>>) -> () -end +end subroutine sub8() use m @@ -265,7 +267,7 @@ contains function reffunc(arg) result(pp) integer :: arg procedure(real_func), pointer :: pp -! CHECK: %[[VAL_0:.*]]:2 = hlfir.declare %arg0 dummy_scope %{{[0-9]+}} {uniq_name = "_QFsub10FreffuncEarg"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_0:.*]]:2 = hlfir.declare %arg0 dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFsub10FreffuncEarg"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_1:.*]] = fir.alloca !fir.boxproc<(!fir.ref<f32>) -> f32> {bindc_name = "pp", uniq_name = "_QFsub10FreffuncEpp"} ! CHECK: %[[VAL_2:.*]] = fir.zero_bits (!fir.ref<f32>) -> f32 ! CHECK: %[[VAL_3:.*]] = fir.emboxproc %[[VAL_2]] : ((!fir.ref<f32>) -> f32) -> !fir.boxproc<(!fir.ref<f32>) -> f32> @@ -338,7 +340,7 @@ use m ! CHECK: %[[VAL_16:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = ".tmp.intrinsic_result"} : (!fir.ref<!fir.boxproc<(!fir.ref<i32>) -> !fir.box<!fir.ptr<!fir.char<1,?>>>>>) -> (!fir.ref<!fir.boxproc<(!fir.ref<i32>) -> !fir.box<!fir.ptr<!fir.char<1,?>>>>>, !fir.ref<!fir.boxproc<(!fir.ref<i32>) -> !fir.box<!fir.ptr<!fir.char<1,?>>>>>) ! CHECK: %[[VAL_17:.*]] = fir.convert %[[VAL_16]]#0 : (!fir.ref<!fir.boxproc<(!fir.ref<i32>) -> !fir.box<!fir.ptr<!fir.char<1,?>>>>>) -> !fir.ref<!fir.boxproc<() -> ()>> ! CHECK: fir.call @_QPfoo2(%[[VAL_17]]) fastmath<contract> : (!fir.ref<!fir.boxproc<() -> ()>>) -> () -end +end subroutine test_opt_pointer() interface diff --git a/flang/test/Lower/HLFIR/reshape.f90 b/flang/test/Lower/HLFIR/reshape.f90 index 8bf3cfd..83072d3 100644 --- a/flang/test/Lower/HLFIR/reshape.f90 +++ b/flang/test/Lower/HLFIR/reshape.f90 @@ -49,7 +49,7 @@ end subroutine reshape_test_nopad ! CHECK: %[[VAL_10:.*]]:2 = hlfir.declare {{.*}}{uniq_name = "_QFreshape_test_nopadEsh"} : (!fir.ref<!fir.array<2xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<2xi32>>, !fir.ref<!fir.array<2xi32>>) ! CHECK: %[[VAL_11:.*]]:2 = hlfir.declare {{.*}}{uniq_name = "_QFreshape_test_nopadEsource"} : (!fir.box<!fir.array<?x?x?xi32>>, !fir.dscope) -> (!fir.box<!fir.array<?x?x?xi32>>, !fir.box<!fir.array<?x?x?xi32>>) ! CHECK: %[[VAL_13:.*]] = hlfir.reshape %[[VAL_11]]#0 %[[VAL_10]]#0 order %[[VAL_7]]#0 : (!fir.box<!fir.array<?x?x?xi32>>, !fir.ref<!fir.array<2xi32>>, !fir.ref<!fir.array<2xi32>>) -> !hlfir.expr<?x?xi32> - + subroutine test_reshape_optional1(pad, order, source, shape) real, pointer :: pad(:, :) integer, pointer :: order(:) diff --git a/flang/test/Lower/HLFIR/select-rank.f90 b/flang/test/Lower/HLFIR/select-rank.f90 index f1f968de..4e05926 100644 --- a/flang/test/Lower/HLFIR/select-rank.f90 +++ b/flang/test/Lower/HLFIR/select-rank.f90 @@ -293,7 +293,7 @@ end subroutine ! CHECK-LABEL: func.func @_QPtest_single_case( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.box<!fir.array<*:f32>> {fir.bindc_name = "x"}) { ! CHECK: %[[VAL_1:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] {uniq_name = "_QFtest_single_caseEx"} : (!fir.box<!fir.array<*:f32>>, !fir.dscope) -> (!fir.box<!fir.array<*:f32>>, !fir.box<!fir.array<*:f32>>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] arg {{[0-9]+}} {uniq_name = "_QFtest_single_caseEx"} : (!fir.box<!fir.array<*:f32>>, !fir.dscope) -> (!fir.box<!fir.array<*:f32>>, !fir.box<!fir.array<*:f32>>) ! CHECK: %[[VAL_3:.*]] = arith.constant 1 : i8 ! CHECK: %[[VAL_4:.*]] = fir.is_assumed_size %[[VAL_2]]#0 : (!fir.box<!fir.array<*:f32>>) -> i1 ! CHECK: cf.cond_br %[[VAL_4]], ^bb3, ^bb1 @@ -312,7 +312,7 @@ end subroutine ! CHECK-LABEL: func.func @_QPtest_simple_case( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.box<!fir.array<*:f32>> {fir.bindc_name = "x"}) { ! CHECK: %[[VAL_1:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] {uniq_name = "_QFtest_simple_caseEx"} : (!fir.box<!fir.array<*:f32>>, !fir.dscope) -> (!fir.box<!fir.array<*:f32>>, !fir.box<!fir.array<*:f32>>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] arg {{[0-9]+}} {uniq_name = "_QFtest_simple_caseEx"} : (!fir.box<!fir.array<*:f32>>, !fir.dscope) -> (!fir.box<!fir.array<*:f32>>, !fir.box<!fir.array<*:f32>>) ! CHECK: %[[VAL_3:.*]] = arith.constant 1 : i8 ! CHECK: %[[VAL_4:.*]] = arith.constant 15 : i8 ! CHECK: %[[VAL_5:.*]] = arith.constant 0 : i8 @@ -348,7 +348,7 @@ end subroutine ! CHECK-LABEL: func.func @_QPtest_rank_star( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.box<!fir.array<*:f32>> {fir.bindc_name = "x"}) { ! CHECK: %[[VAL_1:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] {uniq_name = "_QFtest_rank_starEx"} : (!fir.box<!fir.array<*:f32>>, !fir.dscope) -> (!fir.box<!fir.array<*:f32>>, !fir.box<!fir.array<*:f32>>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] arg {{[0-9]+}} {uniq_name = "_QFtest_rank_starEx"} : (!fir.box<!fir.array<*:f32>>, !fir.dscope) -> (!fir.box<!fir.array<*:f32>>, !fir.box<!fir.array<*:f32>>) ! CHECK: %[[VAL_3:.*]] = arith.constant 2 : i8 ! CHECK: %[[VAL_4:.*]] = arith.constant 1 : i8 ! CHECK: %[[VAL_5:.*]] = fir.is_assumed_size %[[VAL_2]]#0 : (!fir.box<!fir.array<*:f32>>) -> i1 @@ -385,7 +385,7 @@ end subroutine ! CHECK-LABEL: func.func @_QPtest_renaming( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.box<!fir.array<*:f32>> {fir.bindc_name = "x"}) { ! CHECK: %[[VAL_1:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] {uniq_name = "_QFtest_renamingEx"} : (!fir.box<!fir.array<*:f32>>, !fir.dscope) -> (!fir.box<!fir.array<*:f32>>, !fir.box<!fir.array<*:f32>>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] arg {{[0-9]+}} {uniq_name = "_QFtest_renamingEx"} : (!fir.box<!fir.array<*:f32>>, !fir.dscope) -> (!fir.box<!fir.array<*:f32>>, !fir.box<!fir.array<*:f32>>) ! CHECK: %[[VAL_3:.*]] = arith.constant 1 : i8 ! CHECK: %[[VAL_4:.*]] = fir.is_assumed_size %[[VAL_2]]#0 : (!fir.box<!fir.array<*:f32>>) -> i1 ! CHECK: cf.cond_br %[[VAL_4]], ^bb3, ^bb1 @@ -405,7 +405,7 @@ end subroutine ! CHECK-LABEL: func.func @_QPtest_no_case( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.box<!fir.array<*:f32>> {fir.bindc_name = "x"}) { ! CHECK: %[[VAL_1:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] {uniq_name = "_QFtest_no_caseEx"} : (!fir.box<!fir.array<*:f32>>, !fir.dscope) -> (!fir.box<!fir.array<*:f32>>, !fir.box<!fir.array<*:f32>>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] arg {{[0-9]+}} {uniq_name = "_QFtest_no_caseEx"} : (!fir.box<!fir.array<*:f32>>, !fir.dscope) -> (!fir.box<!fir.array<*:f32>>, !fir.box<!fir.array<*:f32>>) ! CHECK: %[[VAL_3:.*]] = fir.is_assumed_size %[[VAL_2]]#0 : (!fir.box<!fir.array<*:f32>>) -> i1 ! CHECK: cf.cond_br %[[VAL_3]], ^bb2, ^bb1 ! CHECK: ^bb1: @@ -418,7 +418,7 @@ end subroutine ! CHECK-LABEL: func.func @_QPtest_rank_star_attributes( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.box<!fir.array<*:f32>> {fir.asynchronous, fir.bindc_name = "x", fir.optional, fir.target}) { ! CHECK: %[[VAL_1:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] {fortran_attrs = #fir.var_attrs<asynchronous, optional, target>, uniq_name = "_QFtest_rank_star_attributesEx"} : (!fir.box<!fir.array<*:f32>>, !fir.dscope) -> (!fir.box<!fir.array<*:f32>>, !fir.box<!fir.array<*:f32>>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<asynchronous, optional, target>, uniq_name = "_QFtest_rank_star_attributesEx"} : (!fir.box<!fir.array<*:f32>>, !fir.dscope) -> (!fir.box<!fir.array<*:f32>>, !fir.box<!fir.array<*:f32>>) ! CHECK: %[[VAL_3:.*]] = arith.constant 2 : i8 ! CHECK: %[[VAL_4:.*]] = fir.is_assumed_size %[[VAL_2]]#0 : (!fir.box<!fir.array<*:f32>>) -> i1 ! CHECK: cf.cond_br %[[VAL_4]], ^bb4, ^bb1 @@ -449,7 +449,7 @@ end subroutine ! CHECK-LABEL: func.func @_QPtest_rank_star_contiguous( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.box<!fir.array<*:f32>> {fir.bindc_name = "x", fir.contiguous, fir.target}) { ! CHECK: %[[VAL_1:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] {fortran_attrs = #fir.var_attrs<contiguous, target>, uniq_name = "_QFtest_rank_star_contiguousEx"} : (!fir.box<!fir.array<*:f32>>, !fir.dscope) -> (!fir.box<!fir.array<*:f32>>, !fir.box<!fir.array<*:f32>>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<contiguous, target>, uniq_name = "_QFtest_rank_star_contiguousEx"} : (!fir.box<!fir.array<*:f32>>, !fir.dscope) -> (!fir.box<!fir.array<*:f32>>, !fir.box<!fir.array<*:f32>>) ! CHECK: %[[VAL_3:.*]] = arith.constant 2 : i8 ! CHECK: %[[VAL_4:.*]] = arith.constant 1 : i8 ! CHECK: %[[VAL_5:.*]] = fir.is_assumed_size %[[VAL_2]]#0 : (!fir.box<!fir.array<*:f32>>) -> i1 @@ -497,12 +497,12 @@ end subroutine ! CHECK-SAME: %[[VAL_0:.*]]: !fir.box<!fir.array<*:!fir.char<1,?>>> {fir.bindc_name = "x", fir.contiguous}, ! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref<i64> {fir.bindc_name = "n"}) { ! CHECK: %[[VAL_2:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %[[VAL_2]] {uniq_name = "_QFtest_rank_star_contiguous_characterEn"} : (!fir.ref<i64>, !fir.dscope) -> (!fir.ref<i64>, !fir.ref<i64>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %[[VAL_2]] arg {{[0-9]+}} {uniq_name = "_QFtest_rank_star_contiguous_characterEn"} : (!fir.ref<i64>, !fir.dscope) -> (!fir.ref<i64>, !fir.ref<i64>) ! CHECK: %[[VAL_4:.*]] = fir.load %[[VAL_3]]#0 : !fir.ref<i64> ! CHECK: %[[VAL_5:.*]] = arith.constant 0 : i64 ! CHECK: %[[VAL_6:.*]] = arith.cmpi sgt, %[[VAL_4]], %[[VAL_5]] : i64 ! CHECK: %[[VAL_7:.*]] = arith.select %[[VAL_6]], %[[VAL_4]], %[[VAL_5]] : i64 -! CHECK: %[[VAL_8:.*]]:2 = hlfir.declare %[[VAL_0]] typeparams %[[VAL_7]] dummy_scope %[[VAL_2]] {fortran_attrs = #fir.var_attrs<contiguous>, uniq_name = "_QFtest_rank_star_contiguous_characterEx"} : (!fir.box<!fir.array<*:!fir.char<1,?>>>, i64, !fir.dscope) -> (!fir.box<!fir.array<*:!fir.char<1,?>>>, !fir.box<!fir.array<*:!fir.char<1,?>>>) +! CHECK: %[[VAL_8:.*]]:2 = hlfir.declare %[[VAL_0]] typeparams %[[VAL_7]] dummy_scope %[[VAL_2]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<contiguous>, uniq_name = "_QFtest_rank_star_contiguous_characterEx"} : (!fir.box<!fir.array<*:!fir.char<1,?>>>, i64, !fir.dscope) -> (!fir.box<!fir.array<*:!fir.char<1,?>>>, !fir.box<!fir.array<*:!fir.char<1,?>>>) ! CHECK: %[[VAL_9:.*]] = arith.constant 0 : i8 ! CHECK: %[[VAL_10:.*]] = arith.constant 1 : i8 ! CHECK: %[[VAL_11:.*]] = fir.is_assumed_size %[[VAL_8]]#0 : (!fir.box<!fir.array<*:!fir.char<1,?>>>) -> i1 @@ -550,7 +550,7 @@ end subroutine ! CHECK-LABEL: func.func @_QPtest_simple_alloc( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.heap<!fir.array<*:f32>>>> {fir.bindc_name = "x"}) { ! CHECK: %[[VAL_1:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFtest_simple_allocEx"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<*:f32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<*:f32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<*:f32>>>>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFtest_simple_allocEx"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<*:f32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<*:f32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<*:f32>>>>) ! CHECK: %[[VAL_3:.*]] = arith.constant 2 : i8 ! CHECK: %[[VAL_4:.*]] = arith.constant 0 : i8 ! CHECK: %[[VAL_5:.*]] = arith.constant 1 : i8 @@ -583,7 +583,7 @@ end subroutine ! CHECK-LABEL: func.func @_QPtest_character_alloc( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.heap<!fir.array<*:!fir.char<1,?>>>>> {fir.bindc_name = "x"}) { ! CHECK: %[[VAL_1:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFtest_character_allocEx"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<*:!fir.char<1,?>>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<*:!fir.char<1,?>>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<*:!fir.char<1,?>>>>>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFtest_character_allocEx"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<*:!fir.char<1,?>>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<*:!fir.char<1,?>>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<*:!fir.char<1,?>>>>>) ! CHECK: %[[VAL_3:.*]] = arith.constant 1 : i8 ! CHECK: %[[VAL_4:.*]] = fir.box_rank %[[VAL_2]]#0 : (!fir.ref<!fir.box<!fir.heap<!fir.array<*:!fir.char<1,?>>>>>) -> i8 ! CHECK: fir.select_case %[[VAL_4]] : i8 [#fir.point, %[[VAL_3]], ^bb2, unit, ^bb1] @@ -604,12 +604,12 @@ end subroutine ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.heap<!fir.array<*:!fir.char<1,?>>>>> {fir.bindc_name = "x"}, ! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref<i64> {fir.bindc_name = "n"}) { ! CHECK: %[[VAL_2:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %[[VAL_2]] {uniq_name = "_QFtest_explicit_character_ptrEn"} : (!fir.ref<i64>, !fir.dscope) -> (!fir.ref<i64>, !fir.ref<i64>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %[[VAL_2]] arg {{[0-9]+}} {uniq_name = "_QFtest_explicit_character_ptrEn"} : (!fir.ref<i64>, !fir.dscope) -> (!fir.ref<i64>, !fir.ref<i64>) ! CHECK: %[[VAL_4:.*]] = fir.load %[[VAL_3]]#0 : !fir.ref<i64> ! CHECK: %[[VAL_5:.*]] = arith.constant 0 : i64 ! CHECK: %[[VAL_6:.*]] = arith.cmpi sgt, %[[VAL_4]], %[[VAL_5]] : i64 ! CHECK: %[[VAL_7:.*]] = arith.select %[[VAL_6]], %[[VAL_4]], %[[VAL_5]] : i64 -! CHECK: %[[VAL_8:.*]]:2 = hlfir.declare %[[VAL_0]] typeparams %[[VAL_7]] dummy_scope %[[VAL_2]] {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFtest_explicit_character_ptrEx"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<*:!fir.char<1,?>>>>>, i64, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<*:!fir.char<1,?>>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<*:!fir.char<1,?>>>>>) +! CHECK: %[[VAL_8:.*]]:2 = hlfir.declare %[[VAL_0]] typeparams %[[VAL_7]] dummy_scope %[[VAL_2]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFtest_explicit_character_ptrEx"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<*:!fir.char<1,?>>>>>, i64, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<*:!fir.char<1,?>>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<*:!fir.char<1,?>>>>>) ! CHECK: %[[VAL_9:.*]] = arith.constant 0 : i8 ! CHECK: %[[VAL_10:.*]] = fir.box_rank %[[VAL_8]]#0 : (!fir.ref<!fir.box<!fir.heap<!fir.array<*:!fir.char<1,?>>>>>) -> i8 ! CHECK: fir.select_case %[[VAL_10]] : i8 [#fir.point, %[[VAL_9]], ^bb2, unit, ^bb1] @@ -629,7 +629,7 @@ end subroutine ! CHECK: %[[VAL_1:.*]] = fir.dummy_scope : !fir.dscope ! CHECK: %[[VAL_2:.*]] = fir.load %[[VAL_0]] : !fir.ref<!fir.box<!fir.heap<!fir.array<*:!fir.char<1,?>>>>> ! CHECK: %[[VAL_3:.*]] = fir.box_elesize %[[VAL_2]] : (!fir.box<!fir.heap<!fir.array<*:!fir.char<1,?>>>>) -> index -! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_0]] typeparams %[[VAL_3]] dummy_scope %[[VAL_1]] {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFtest_assumed_character_ptrEx"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<*:!fir.char<1,?>>>>>, index, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<*:!fir.char<1,?>>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<*:!fir.char<1,?>>>>>) +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_0]] typeparams %[[VAL_3]] dummy_scope %[[VAL_1]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFtest_assumed_character_ptrEx"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<*:!fir.char<1,?>>>>>, index, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<*:!fir.char<1,?>>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<*:!fir.char<1,?>>>>>) ! CHECK: %[[VAL_5:.*]] = arith.constant 0 : i8 ! CHECK: %[[VAL_6:.*]] = fir.box_rank %[[VAL_4]]#0 : (!fir.ref<!fir.box<!fir.heap<!fir.array<*:!fir.char<1,?>>>>>) -> i8 ! CHECK: fir.select_case %[[VAL_6]] : i8 [#fir.point, %[[VAL_5]], ^bb2, unit, ^bb1] @@ -647,7 +647,7 @@ end subroutine ! CHECK-LABEL: func.func @_QPtest_polymorphic( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.class<!fir.array<*:none>> {fir.bindc_name = "x"}) { ! CHECK: %[[VAL_1:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] {uniq_name = "_QFtest_polymorphicEx"} : (!fir.class<!fir.array<*:none>>, !fir.dscope) -> (!fir.class<!fir.array<*:none>>, !fir.class<!fir.array<*:none>>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] arg {{[0-9]+}} {uniq_name = "_QFtest_polymorphicEx"} : (!fir.class<!fir.array<*:none>>, !fir.dscope) -> (!fir.class<!fir.array<*:none>>, !fir.class<!fir.array<*:none>>) ! CHECK: %[[VAL_3:.*]] = arith.constant 1 : i8 ! CHECK: %[[VAL_4:.*]] = arith.constant 0 : i8 ! CHECK: %[[VAL_5:.*]] = fir.is_assumed_size %[[VAL_2]]#0 : (!fir.class<!fir.array<*:none>>) -> i1 @@ -677,8 +677,8 @@ end subroutine ! CHECK-SAME: %[[VAL_0:.*]]: !fir.box<!fir.array<*:f32>> {fir.bindc_name = "x1"}, ! CHECK-SAME: %[[VAL_1:.*]]: !fir.box<!fir.array<*:f32>> {fir.bindc_name = "x2"}) { ! CHECK: %[[VAL_2:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_2]] {uniq_name = "_QFtest_nested_select_rankEx1"} : (!fir.box<!fir.array<*:f32>>, !fir.dscope) -> (!fir.box<!fir.array<*:f32>>, !fir.box<!fir.array<*:f32>>) -! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %[[VAL_2]] {uniq_name = "_QFtest_nested_select_rankEx2"} : (!fir.box<!fir.array<*:f32>>, !fir.dscope) -> (!fir.box<!fir.array<*:f32>>, !fir.box<!fir.array<*:f32>>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_2]] arg {{[0-9]+}} {uniq_name = "_QFtest_nested_select_rankEx1"} : (!fir.box<!fir.array<*:f32>>, !fir.dscope) -> (!fir.box<!fir.array<*:f32>>, !fir.box<!fir.array<*:f32>>) +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %[[VAL_2]] arg {{[0-9]+}} {uniq_name = "_QFtest_nested_select_rankEx2"} : (!fir.box<!fir.array<*:f32>>, !fir.dscope) -> (!fir.box<!fir.array<*:f32>>, !fir.box<!fir.array<*:f32>>) ! CHECK: %[[VAL_5:.*]] = arith.constant 0 : i8 ! CHECK: %[[VAL_6:.*]] = arith.constant 1 : i8 ! CHECK: %[[VAL_7:.*]] = fir.is_assumed_size %[[VAL_3]]#0 : (!fir.box<!fir.array<*:f32>>) -> i1 @@ -783,7 +783,7 @@ end subroutine ! CHECK-LABEL: func.func @_QPtest_branching( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.box<!fir.array<*:f32>> {fir.bindc_name = "x"}) { ! CHECK: %[[VAL_1:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] {uniq_name = "_QFtest_branchingEx"} : (!fir.box<!fir.array<*:f32>>, !fir.dscope) -> (!fir.box<!fir.array<*:f32>>, !fir.box<!fir.array<*:f32>>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] arg {{[0-9]+}} {uniq_name = "_QFtest_branchingEx"} : (!fir.box<!fir.array<*:f32>>, !fir.dscope) -> (!fir.box<!fir.array<*:f32>>, !fir.box<!fir.array<*:f32>>) ! CHECK: %[[VAL_3:.*]] = arith.constant 1 : i8 ! CHECK: %[[VAL_4:.*]] = arith.constant 2 : i8 ! CHECK: %[[VAL_5:.*]] = fir.is_assumed_size %[[VAL_2]]#0 : (!fir.box<!fir.array<*:f32>>) -> i1 diff --git a/flang/test/Lower/HLFIR/statement-functions.f90 b/flang/test/Lower/HLFIR/statement-functions.f90 index 4f91c94..86e3074 100644 --- a/flang/test/Lower/HLFIR/statement-functions.f90 +++ b/flang/test/Lower/HLFIR/statement-functions.f90 @@ -43,7 +43,7 @@ subroutine char_test2(c) call test(stmt_func(c)) end subroutine ! CHECK-LABEL: func.func @_QPchar_test2( -! CHECK: %[[C:.*]]:2 = hlfir.declare %{{.*}} typeparams %c10 dummy_scope %{{[0-9]+}} {uniq_name = "_QFchar_test2Ec"} : (!fir.ref<!fir.char<1,10>>, index, !fir.dscope) -> (!fir.ref<!fir.char<1,10>>, !fir.ref<!fir.char<1,10>>) +! CHECK: %[[C:.*]]:2 = hlfir.declare %{{.*}} typeparams %c10 dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFchar_test2Ec"} : (!fir.ref<!fir.char<1,10>>, index, !fir.dscope) -> (!fir.ref<!fir.char<1,10>>, !fir.ref<!fir.char<1,10>>) ! CHECK: %[[CAST:.*]] = fir.convert %[[C]]#0 : (!fir.ref<!fir.char<1,10>>) -> !fir.ref<!fir.char<1,5>> ! CHECK: %[[C_STMT_FUNC:.*]]:2 = hlfir.declare %[[CAST]] typeparams %c5{{.*}} {uniq_name = "_QFchar_test2Fstmt_funcEc_stmt_func"} : (!fir.ref<!fir.char<1,5>>, index) -> (!fir.ref<!fir.char<1,5>>, !fir.ref<!fir.char<1,5>>) ! CHECK: hlfir.concat %[[C_STMT_FUNC]]#0, %{{.*}} len %{{.*}} : (!fir.ref<!fir.char<1,5>>, !fir.ref<!fir.char<1,7>>, index) -> !hlfir.expr<!fir.char<1,12>> diff --git a/flang/test/Lower/HLFIR/structure-constructor.f90 b/flang/test/Lower/HLFIR/structure-constructor.f90 index 5d5fe33..094aeaa 100644 --- a/flang/test/Lower/HLFIR/structure-constructor.f90 +++ b/flang/test/Lower/HLFIR/structure-constructor.f90 @@ -43,7 +43,7 @@ end subroutine test1 ! CHECK: %[[VAL_4:.*]]:2 = fir.unboxchar %[[VAL_0]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index) ! CHECK: %[[VAL_5:.*]] = fir.convert %[[VAL_4]]#0 : (!fir.ref<!fir.char<1,?>>) -> !fir.ref<!fir.char<1,4>> ! CHECK: %[[VAL_6:.*]] = arith.constant 4 : index -! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_5]] typeparams %[[VAL_6]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFtest1Ex"} : (!fir.ref<!fir.char<1,4>>, index, !fir.dscope) -> (!fir.ref<!fir.char<1,4>>, !fir.ref<!fir.char<1,4>>) +! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_5]] typeparams %[[VAL_6]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFtest1Ex"} : (!fir.ref<!fir.char<1,4>>, index, !fir.dscope) -> (!fir.ref<!fir.char<1,4>>, !fir.ref<!fir.char<1,4>>) ! CHECK: %[[VAL_8:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "ctor.temp"} : (!fir.ref<!fir.type<_QMtypesTt1{c:!fir.char<1,4>}>>) -> (!fir.ref<!fir.type<_QMtypesTt1{c:!fir.char<1,4>}>>, !fir.ref<!fir.type<_QMtypesTt1{c:!fir.char<1,4>}>>) ! CHECK: %[[VAL_9:.*]] = fir.embox %[[VAL_8]]#0 : (!fir.ref<!fir.type<_QMtypesTt1{c:!fir.char<1,4>}>>) -> !fir.box<!fir.type<_QMtypesTt1{c:!fir.char<1,4>}>> ! CHECK: %[[VAL_10:.*]] = fir.address_of(@_QQclX{{.*}}) : !fir.ref<!fir.char<1,{{[0-9]*}}>> @@ -71,7 +71,7 @@ end subroutine test2 ! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]] {uniq_name = "_QFtest2Eres"} : (!fir.ref<!fir.type<_QMtypesTt2{i:!fir.array<10xi32>}>>) -> (!fir.ref<!fir.type<_QMtypesTt2{i:!fir.array<10xi32>}>>, !fir.ref<!fir.type<_QMtypesTt2{i:!fir.array<10xi32>}>>) ! CHECK: %[[VAL_4:.*]] = arith.constant 10 : index ! CHECK: %[[VAL_5:.*]] = fir.shape %[[VAL_4]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_5]]) dummy_scope %{{[0-9]+}} {uniq_name = "_QFtest2Ex"} : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>) +! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_5]]) dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFtest2Ex"} : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>) ! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "ctor.temp"} : (!fir.ref<!fir.type<_QMtypesTt2{i:!fir.array<10xi32>}>>) -> (!fir.ref<!fir.type<_QMtypesTt2{i:!fir.array<10xi32>}>>, !fir.ref<!fir.type<_QMtypesTt2{i:!fir.array<10xi32>}>>) ! CHECK: %[[VAL_8:.*]] = fir.embox %[[VAL_7]]#0 : (!fir.ref<!fir.type<_QMtypesTt2{i:!fir.array<10xi32>}>>) -> !fir.box<!fir.type<_QMtypesTt2{i:!fir.array<10xi32>}>> ! CHECK: %[[VAL_9:.*]] = fir.address_of(@_QQclX{{.*}}) : !fir.ref<!fir.char<1,{{[0-9]*}}>> @@ -100,7 +100,7 @@ end subroutine test3 ! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]] {uniq_name = "_QFtest3Eres"} : (!fir.ref<!fir.type<_QMtypesTt3{r:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>>) -> (!fir.ref<!fir.type<_QMtypesTt3{r:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>>, !fir.ref<!fir.type<_QMtypesTt3{r:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>>) ! CHECK: %[[ADDR:.*]] = fir.address_of(@_QQ_QMtypesTt3.DerivedInit) : !fir.ref<!fir.type<_QMtypesTt3{r:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>> ! CHECK: fir.copy %[[ADDR]] to %[[VAL_3]]#0 no_overlap : !fir.ref<!fir.type<_QMtypesTt3{r:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>>, !fir.ref<!fir.type<_QMtypesTt3{r:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>> -! CHECK: %[[VAL_10:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFtest3Ex"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>) +! CHECK: %[[VAL_10:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFtest3Ex"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>) ! CHECK: %[[VAL_11:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "ctor.temp"} : (!fir.ref<!fir.type<_QMtypesTt3{r:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>>) -> (!fir.ref<!fir.type<_QMtypesTt3{r:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>>, !fir.ref<!fir.type<_QMtypesTt3{r:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>>) ! CHECK: %[[VAL_12:.*]] = fir.embox %[[VAL_11]]#0 : (!fir.ref<!fir.type<_QMtypesTt3{r:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>>) -> !fir.box<!fir.type<_QMtypesTt3{r:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>> ! CHECK: %[[VAL_13:.*]] = fir.address_of(@_QQclX{{.*}}) : !fir.ref<!fir.char<1,{{[0-9]*}}>> @@ -133,7 +133,7 @@ end subroutine test4 ! CHECK: %[[ADDR:.*]] = fir.address_of(@_QQ_QMtypesTt4.DerivedInit) : !fir.ref<!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>> ! CHECK: fir.copy %[[ADDR]] to %[[VAL_3]]#0 no_overlap : !fir.ref<!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>, !fir.ref<!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>> ! CHECK: %[[VAL_10:.*]] = arith.constant 2 : index -! CHECK: %[[VAL_11:.*]]:2 = hlfir.declare %[[VAL_0]] typeparams %[[VAL_10]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFtest4Ex"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>>, index, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>>) +! CHECK: %[[VAL_11:.*]]:2 = hlfir.declare %[[VAL_0]] typeparams %[[VAL_10]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFtest4Ex"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>>, index, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>>) ! CHECK: %[[VAL_12:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "ctor.temp"} : (!fir.ref<!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>) -> (!fir.ref<!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>, !fir.ref<!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>) ! CHECK: %[[VAL_13:.*]] = fir.embox %[[VAL_12]]#0 : (!fir.ref<!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>) -> !fir.box<!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>> ! CHECK: %[[VAL_14:.*]] = fir.address_of(@_QQclX{{.*}}) : !fir.ref<!fir.char<1,{{[0-9]*}}>> @@ -172,7 +172,7 @@ end subroutine test5 ! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]] {uniq_name = "_QFtest5Eres"} : (!fir.ref<!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>>) -> (!fir.ref<!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>>, !fir.ref<!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>>) ! CHECK: %[[ADDR:.*]] = fir.address_of(@_QQ_QMtypesTt5.DerivedInit) : !fir.ref<!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>> ! CHECK: fir.copy %[[ADDR]] to %[[VAL_3]]#0 no_overlap : !fir.ref<!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>>, !fir.ref<!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>> -! CHECK: %[[VAL_10:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFtest5Ex"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>>) +! CHECK: %[[VAL_10:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFtest5Ex"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>>) ! CHECK: %[[VAL_11:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "ctor.temp"} : (!fir.ref<!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>>) -> (!fir.ref<!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>>, !fir.ref<!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>>) ! CHECK: %[[VAL_12:.*]] = fir.embox %[[VAL_11]]#0 : (!fir.ref<!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>>) -> !fir.box<!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>> ! CHECK: %[[VAL_13:.*]] = fir.address_of(@_QQclX{{.*}}) : !fir.ref<!fir.char<1,{{[0-9]*}}>> @@ -214,12 +214,12 @@ end subroutine test6 ! CHECK: %[[VAL_7:.*]]:2 = fir.unboxchar %[[VAL_1]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index) ! CHECK: %[[VAL_8:.*]] = fir.convert %[[VAL_7]]#0 : (!fir.ref<!fir.char<1,?>>) -> !fir.ref<!fir.char<1,4>> ! CHECK: %[[VAL_9:.*]] = arith.constant 4 : index -! CHECK: %[[VAL_10:.*]]:2 = hlfir.declare %[[VAL_8]] typeparams %[[VAL_9]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFtest6Ec"} : (!fir.ref<!fir.char<1,4>>, index, !fir.dscope) -> (!fir.ref<!fir.char<1,4>>, !fir.ref<!fir.char<1,4>>) +! CHECK: %[[VAL_10:.*]]:2 = hlfir.declare %[[VAL_8]] typeparams %[[VAL_9]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFtest6Ec"} : (!fir.ref<!fir.char<1,4>>, index, !fir.dscope) -> (!fir.ref<!fir.char<1,4>>, !fir.ref<!fir.char<1,4>>) ! CHECK: %[[VAL_11:.*]] = fir.alloca !fir.type<_QMtypesTt6{t5:!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>,t6m:!fir.array<1x!fir.type<_QMtypesTt1{c:!fir.char<1,4>}>>}> {bindc_name = "res", uniq_name = "_QFtest6Eres"} ! CHECK: %[[VAL_12:.*]]:2 = hlfir.declare %[[VAL_11]] {uniq_name = "_QFtest6Eres"} : (!fir.ref<!fir.type<_QMtypesTt6{t5:!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>,t6m:!fir.array<1x!fir.type<_QMtypesTt1{c:!fir.char<1,4>}>>}>>) -> (!fir.ref<!fir.type<_QMtypesTt6{t5:!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>,t6m:!fir.array<1x!fir.type<_QMtypesTt1{c:!fir.char<1,4>}>>}>>, !fir.ref<!fir.type<_QMtypesTt6{t5:!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>,t6m:!fir.array<1x!fir.type<_QMtypesTt1{c:!fir.char<1,4>}>>}>>) ! CHECK: %[[ADDR:.*]] = fir.address_of(@_QQ_QMtypesTt6.DerivedInit) : !fir.ref<!fir.type<_QMtypesTt6{t5:!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>,t6m:!fir.array<1x!fir.type<_QMtypesTt1{c:!fir.char<1,4>}>>}>> ! CHECK: fir.copy %[[ADDR]] to %[[VAL_12]]#0 no_overlap : !fir.ref<!fir.type<_QMtypesTt6{t5:!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>,t6m:!fir.array<1x!fir.type<_QMtypesTt1{c:!fir.char<1,4>}>>}>>, !fir.ref<!fir.type<_QMtypesTt6{t5:!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>,t6m:!fir.array<1x!fir.type<_QMtypesTt1{c:!fir.char<1,4>}>>}>> -! CHECK: %[[VAL_19:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFtest6Ex"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>>) +! CHECK: %[[VAL_19:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFtest6Ex"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>>) ! CHECK: %[[VAL_20:.*]]:2 = hlfir.declare %[[VAL_6]] {uniq_name = "ctor.temp"} : (!fir.ref<!fir.type<_QMtypesTt6{t5:!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>,t6m:!fir.array<1x!fir.type<_QMtypesTt1{c:!fir.char<1,4>}>>}>>) -> (!fir.ref<!fir.type<_QMtypesTt6{t5:!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>,t6m:!fir.array<1x!fir.type<_QMtypesTt1{c:!fir.char<1,4>}>>}>>, !fir.ref<!fir.type<_QMtypesTt6{t5:!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>,t6m:!fir.array<1x!fir.type<_QMtypesTt1{c:!fir.char<1,4>}>>}>>) ! CHECK: %[[VAL_21:.*]] = fir.embox %[[VAL_20]]#0 : (!fir.ref<!fir.type<_QMtypesTt6{t5:!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>,t6m:!fir.array<1x!fir.type<_QMtypesTt1{c:!fir.char<1,4>}>>}>>) -> !fir.box<!fir.type<_QMtypesTt6{t5:!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>,t6m:!fir.array<1x!fir.type<_QMtypesTt1{c:!fir.char<1,4>}>>}>> ! CHECK: %[[VAL_22:.*]] = fir.address_of(@_QQclX{{.*}}) : !fir.ref<!fir.char<1,{{[0-9]*}}>> @@ -299,7 +299,7 @@ end subroutine test7 ! CHECK-LABEL: func.func @_QPtest7( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<i32> {fir.bindc_name = "n"}) { ! CHECK: %[[VAL_1:.*]] = fir.alloca !fir.type<_QMtypesTt7{c1:i32,c2:!fir.box<!fir.heap<!fir.array<?xf32>>>}> -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<intent_in>, uniq_name = "_QFtest7En"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<intent_in>, uniq_name = "_QFtest7En"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_3:.*]] = fir.alloca !fir.type<_QMtypesTt7{c1:i32,c2:!fir.box<!fir.heap<!fir.array<?xf32>>>}> {bindc_name = "x", uniq_name = "_QFtest7Ex"} ! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_3]] {uniq_name = "_QFtest7Ex"} : (!fir.ref<!fir.type<_QMtypesTt7{c1:i32,c2:!fir.box<!fir.heap<!fir.array<?xf32>>>}>>) -> (!fir.ref<!fir.type<_QMtypesTt7{c1:i32,c2:!fir.box<!fir.heap<!fir.array<?xf32>>>}>>, !fir.ref<!fir.type<_QMtypesTt7{c1:i32,c2:!fir.box<!fir.heap<!fir.array<?xf32>>>}>>) ! CHECK: %[[ADDR:.*]] = fir.address_of(@_QQ_QMtypesTt7.DerivedInit) : !fir.ref<!fir.type<_QMtypesTt7{c1:i32,c2:!fir.box<!fir.heap<!fir.array<?xf32>>>}>> diff --git a/flang/test/Lower/HLFIR/transformational.f90 b/flang/test/Lower/HLFIR/transformational.f90 index 6be0184..7af56354 100644 --- a/flang/test/Lower/HLFIR/transformational.f90 +++ b/flang/test/Lower/HLFIR/transformational.f90 @@ -16,7 +16,7 @@ subroutine test_transformational_implemented_with_runtime_allocation(x) end subroutine ! CHECK-LABEL: func.func @_QPtest_transformational_implemented_with_runtime_allocation( ! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.array<10x10xf32>> {fir.bindc_name = "x"}) { -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[ARG0]](%{{.*}}) dummy_scope %{{[0-9]+}} {uniq_name = "_QFtest_transformational_implemented_with_runtime_allocationEx"} +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[ARG0]](%{{.*}}) dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFtest_transformational_implemented_with_runtime_allocationEx"} ! CHECK: %[[VAL_2:.*]] = hlfir.minloc %[[VAL_1]]#0 ! CHECK: %[[VAL_3:.*]] = hlfir.shape_of %[[VAL_2]] ! CHECK: %[[VAL_4:.*]]:3 = hlfir.associate %[[VAL_2]](%[[VAL_3]]) {adapt.valuebyref} diff --git a/flang/test/Lower/HLFIR/transpose.f90 b/flang/test/Lower/HLFIR/transpose.f90 index 6d8e337..823ecf4 100644 --- a/flang/test/Lower/HLFIR/transpose.f90 +++ b/flang/test/Lower/HLFIR/transpose.f90 @@ -8,8 +8,8 @@ endsubroutine ! CHECK-LABEL: func.func @_QPtranspose1 ! CHECK: %[[M_ARG:.*]]: !fir.ref<!fir.array<1x2xi32>> ! CHECK: %[[RES_ARG:.*]]: !fir.ref<!fir.array<2x1xi32>> -! CHECK-DAG: %[[ARG:.*]]:2 = hlfir.declare %[[M_ARG]](%[[M_SHAPE:.*]]) dummy_scope %{{[0-9]+}} {[[NAME:.*]]} : (!fir.ref<!fir.array<1x2xi32>>, !fir.shape<2>, !fir.dscope) -> (!fir.ref<!fir.array<1x2xi32>>, !fir.ref<!fir.array<1x2xi32>>) -! CHECK-DAG: %[[RES:.*]]:2 = hlfir.declare %[[RES_ARG]](%[[RES_SHAPE:.*]]) dummy_scope %{{[0-9]+}} {[[NAME2:.*]]} : (!fir.ref<!fir.array<2x1xi32>>, !fir.shape<2>, !fir.dscope) -> (!fir.ref<!fir.array<2x1xi32>>, !fir.ref<!fir.array<2x1xi32>>) +! CHECK-DAG: %[[ARG:.*]]:2 = hlfir.declare %[[M_ARG]](%[[M_SHAPE:.*]]) dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {[[NAME:.*]]} : (!fir.ref<!fir.array<1x2xi32>>, !fir.shape<2>, !fir.dscope) -> (!fir.ref<!fir.array<1x2xi32>>, !fir.ref<!fir.array<1x2xi32>>) +! CHECK-DAG: %[[RES:.*]]:2 = hlfir.declare %[[RES_ARG]](%[[RES_SHAPE:.*]]) dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {[[NAME2:.*]]} : (!fir.ref<!fir.array<2x1xi32>>, !fir.shape<2>, !fir.dscope) -> (!fir.ref<!fir.array<2x1xi32>>, !fir.ref<!fir.array<2x1xi32>>) ! CHECK: %[[EXPR:.*]] = hlfir.transpose %[[ARG]]#0 : (!fir.ref<!fir.array<1x2xi32>>) -> !hlfir.expr<2x1xi32> ! CHECK-NEXT: hlfir.assign %[[EXPR]] to %[[RES]]#0 ! CHECK-NEXT: hlfir.destroy %[[EXPR]] @@ -38,7 +38,7 @@ endsubroutine ! CHECK: %[[M_ARG:.*]]: !fir.ref<!fir.box<!fir.heap<!fir.array<?x?xi32>>>> ! CHECK: %[[RES_ARG:.*]]: !fir.ref<!fir.array<2x1xi32>> ! CHECK-DAG: %[[ARG:.*]]:2 = hlfir.declare %[[M_ARG]] -! CHECK-DAG: %[[RES:.*]]:2 = hlfir.declare %[[RES_ARG]](%[[RES_SHAPE:.*]]) dummy_scope %{{[0-9]+}} {[[NAME2:.*]]} : (!fir.ref<!fir.array<2x1xi32>>, !fir.shape<2>, !fir.dscope) -> (!fir.ref<!fir.array<2x1xi32>>, !fir.ref<!fir.array<2x1xi32>>) +! CHECK-DAG: %[[RES:.*]]:2 = hlfir.declare %[[RES_ARG]](%[[RES_SHAPE:.*]]) dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {[[NAME2:.*]]} : (!fir.ref<!fir.array<2x1xi32>>, !fir.shape<2>, !fir.dscope) -> (!fir.ref<!fir.array<2x1xi32>>, !fir.ref<!fir.array<2x1xi32>>) ! CHECK: %[[ARG_LOADED:.*]] = fir.load %[[ARG]]#0 ! CHECK: %[[EXPR:.*]] = hlfir.transpose %[[ARG_LOADED]] : (!fir.box<!fir.heap<!fir.array<?x?xi32>>>) -> !hlfir.expr<?x?xi32> ! CHECK-NEXT: hlfir.assign %[[EXPR]] to %[[RES]]#0 @@ -54,8 +54,8 @@ end subroutine test_polymorphic_result ! CHECK-LABEL: func.func @_QPtest_polymorphic_result( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.class<!fir.heap<!fir.array<?x?xnone>>>> {fir.bindc_name = "m"}, ! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref<!fir.class<!fir.heap<!fir.array<?x?xnone>>>> {fir.bindc_name = "res"}) { -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFtest_polymorphic_resultEm"} : (!fir.ref<!fir.class<!fir.heap<!fir.array<?x?xnone>>>>, !fir.dscope) -> (!fir.ref<!fir.class<!fir.heap<!fir.array<?x?xnone>>>>, !fir.ref<!fir.class<!fir.heap<!fir.array<?x?xnone>>>>) -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFtest_polymorphic_resultEres"} : (!fir.ref<!fir.class<!fir.heap<!fir.array<?x?xnone>>>>, !fir.dscope) -> (!fir.ref<!fir.class<!fir.heap<!fir.array<?x?xnone>>>>, !fir.ref<!fir.class<!fir.heap<!fir.array<?x?xnone>>>>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFtest_polymorphic_resultEm"} : (!fir.ref<!fir.class<!fir.heap<!fir.array<?x?xnone>>>>, !fir.dscope) -> (!fir.ref<!fir.class<!fir.heap<!fir.array<?x?xnone>>>>, !fir.ref<!fir.class<!fir.heap<!fir.array<?x?xnone>>>>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFtest_polymorphic_resultEres"} : (!fir.ref<!fir.class<!fir.heap<!fir.array<?x?xnone>>>>, !fir.dscope) -> (!fir.ref<!fir.class<!fir.heap<!fir.array<?x?xnone>>>>, !fir.ref<!fir.class<!fir.heap<!fir.array<?x?xnone>>>>) ! CHECK: %[[VAL_4:.*]] = fir.load %[[VAL_2]]#0 : !fir.ref<!fir.class<!fir.heap<!fir.array<?x?xnone>>>> ! CHECK: %[[VAL_5:.*]] = hlfir.transpose %[[VAL_4]] : (!fir.class<!fir.heap<!fir.array<?x?xnone>>>) -> !hlfir.expr<?x?xnone?> ! CHECK: hlfir.assign %[[VAL_5]] to %[[VAL_3]]#0 realloc : !hlfir.expr<?x?xnone?>, !fir.ref<!fir.class<!fir.heap<!fir.array<?x?xnone>>>> diff --git a/flang/test/Lower/HLFIR/trim.f90 b/flang/test/Lower/HLFIR/trim.f90 index d09e6c5..9b63029 100644 --- a/flang/test/Lower/HLFIR/trim.f90 +++ b/flang/test/Lower/HLFIR/trim.f90 @@ -4,7 +4,7 @@ ! CHECK-SAME: %[[VAL_0:.*]]: !fir.boxchar<1> {fir.bindc_name = "c"}) { ! CHECK: %[[VAL_1:.*]] = fir.dummy_scope : !fir.dscope ! CHECK-NEXT: %[[VAL_2:.*]]:2 = fir.unboxchar %[[VAL_0]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index) -! CHECK-NEXT: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]]#0 typeparams %[[VAL_2]]#1 dummy_scope %[[VAL_1]] {uniq_name = "_QFtrim_testEc"} : (!fir.ref<!fir.char<1,?>>, index, !fir.dscope) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>) +! CHECK-NEXT: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]]#0 typeparams %[[VAL_2]]#1 dummy_scope %[[VAL_1]] arg {{[0-9]+}} {uniq_name = "_QFtrim_testEc"} : (!fir.ref<!fir.char<1,?>>, index, !fir.dscope) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>) ! CHECK-NEXT: %[[VAL_4:.*]] = arith.constant 8 : index ! CHECK-NEXT: %[[VAL_5:.*]] = fir.alloca !fir.char<1,8> {bindc_name = "tc", uniq_name = "_QFtrim_testEtc"} ! CHECK-NEXT: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_5]] typeparams %[[VAL_4]] {uniq_name = "_QFtrim_testEtc"} : (!fir.ref<!fir.char<1,8>>, index) -> (!fir.ref<!fir.char<1,8>>, !fir.ref<!fir.char<1,8>>) diff --git a/flang/test/Lower/HLFIR/unroll-loops.fir b/flang/test/Lower/HLFIR/unroll-loops.fir index 89e8ce8..1ccb6b1 100644 --- a/flang/test/Lower/HLFIR/unroll-loops.fir +++ b/flang/test/Lower/HLFIR/unroll-loops.fir @@ -27,7 +27,7 @@ func.func @unroll(%arg0: !fir.ref<!fir.array<1000 x index>> {fir.bindc_name = "a // NO-UNROLL-NEXT: %[[GEP:.*]] = getelementptr i64, ptr %[[ARG0]], i64 %[[IND]] // NO-UNROLL-NEXT: store <2 x i64> %[[VIND]], ptr %[[GEP]] // NO-UNROLL-NEXT: %[[NIV:.*]] = add nuw i64 %{{.*}}, 2 - // NO-UNROLL-NEXT: %[[NVIND]] = add <2 x i64> %[[VIND]], splat (i64 2) + // NO-UNROLL-NEXT: %[[NVIND]] = add nuw nsw <2 x i64> %[[VIND]], splat (i64 2) // UNROLL-NEXT: %[[VIND1:.*]] = add <2 x i64> %[[VIND]], splat (i64 2) // UNROLL-NEXT: %[[GEP0:.*]] = getelementptr i64, ptr %[[ARG0]], i64 %[[IND]] diff --git a/flang/test/Lower/HLFIR/user-defined-assignment.f90 b/flang/test/Lower/HLFIR/user-defined-assignment.f90 index 5d58dca..2dffd92 100644 --- a/flang/test/Lower/HLFIR/user-defined-assignment.f90 +++ b/flang/test/Lower/HLFIR/user-defined-assignment.f90 @@ -35,8 +35,8 @@ end subroutine ! CHECK-LABEL: func.func @_QMuser_defPtest_user_defined_elemental_array( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.box<!fir.array<?xi32>> {fir.bindc_name = "i"}, ! CHECK-SAME: %[[VAL_1:.*]]: !fir.box<!fir.array<?x!fir.logical<4>>> {fir.bindc_name = "l"}) { -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {uniq_name = "_QMuser_defFtest_user_defined_elemental_arrayEi"} : (!fir.box<!fir.array<?xi32>>, !fir.dscope) -> (!fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>>) -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %{{[0-9]+}} {uniq_name = "_QMuser_defFtest_user_defined_elemental_arrayEl"} : (!fir.box<!fir.array<?x!fir.logical<4>>>, !fir.dscope) -> (!fir.box<!fir.array<?x!fir.logical<4>>>, !fir.box<!fir.array<?x!fir.logical<4>>>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QMuser_defFtest_user_defined_elemental_arrayEi"} : (!fir.box<!fir.array<?xi32>>, !fir.dscope) -> (!fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QMuser_defFtest_user_defined_elemental_arrayEl"} : (!fir.box<!fir.array<?x!fir.logical<4>>>, !fir.dscope) -> (!fir.box<!fir.array<?x!fir.logical<4>>>, !fir.box<!fir.array<?x!fir.logical<4>>>) ! CHECK: hlfir.region_assign { ! CHECK: hlfir.yield %[[VAL_3]]#0 : !fir.box<!fir.array<?x!fir.logical<4>>> ! CHECK: } to { @@ -53,8 +53,8 @@ end subroutine ! CHECK-LABEL: func.func @_QMuser_defPtest_user_defined_elemental_array_value( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.box<!fir.array<?xcomplex<f32>>> {fir.bindc_name = "z"}, ! CHECK-SAME: %[[VAL_1:.*]]: !fir.box<!fir.array<?x!fir.logical<4>>> {fir.bindc_name = "l"}) { -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %{{[0-9]+}} {uniq_name = "_QMuser_defFtest_user_defined_elemental_array_valueEl"} : (!fir.box<!fir.array<?x!fir.logical<4>>>, !fir.dscope) -> (!fir.box<!fir.array<?x!fir.logical<4>>>, !fir.box<!fir.array<?x!fir.logical<4>>>) -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {uniq_name = "_QMuser_defFtest_user_defined_elemental_array_valueEz"} : (!fir.box<!fir.array<?xcomplex<f32>>>, !fir.dscope) -> (!fir.box<!fir.array<?xcomplex<f32>>>, !fir.box<!fir.array<?xcomplex<f32>>>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QMuser_defFtest_user_defined_elemental_array_valueEl"} : (!fir.box<!fir.array<?x!fir.logical<4>>>, !fir.dscope) -> (!fir.box<!fir.array<?x!fir.logical<4>>>, !fir.box<!fir.array<?x!fir.logical<4>>>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QMuser_defFtest_user_defined_elemental_array_valueEz"} : (!fir.box<!fir.array<?xcomplex<f32>>>, !fir.dscope) -> (!fir.box<!fir.array<?xcomplex<f32>>>, !fir.box<!fir.array<?xcomplex<f32>>>) ! CHECK: hlfir.region_assign { ! CHECK: hlfir.yield %[[VAL_2]]#0 : !fir.box<!fir.array<?x!fir.logical<4>>> ! CHECK: } to { @@ -72,8 +72,8 @@ end subroutine ! CHECK-LABEL: func.func @_QMuser_defPtest_user_defined_scalar( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<i32> {fir.bindc_name = "i"}, ! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref<!fir.logical<4>> {fir.bindc_name = "l"}) { -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {uniq_name = "_QMuser_defFtest_user_defined_scalarEi"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %{{[0-9]+}} {uniq_name = "_QMuser_defFtest_user_defined_scalarEl"} : (!fir.ref<!fir.logical<4>>, !fir.dscope) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QMuser_defFtest_user_defined_scalarEi"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QMuser_defFtest_user_defined_scalarEl"} : (!fir.ref<!fir.logical<4>>, !fir.dscope) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) ! CHECK: hlfir.region_assign { ! CHECK: %[[VAL_4:.*]] = fir.load %[[VAL_3]]#0 : !fir.ref<!fir.logical<4>> ! CHECK: hlfir.yield %[[VAL_4]] : !fir.logical<4> @@ -91,7 +91,7 @@ subroutine test_non_elemental_array(x) end subroutine ! CHECK-LABEL: func.func @_QMuser_defPtest_non_elemental_array( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.box<!fir.array<?xf32>> {fir.bindc_name = "x"}) { -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {uniq_name = "_QMuser_defFtest_non_elemental_arrayEx"} : (!fir.box<!fir.array<?xf32>>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.box<!fir.array<?xf32>>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QMuser_defFtest_non_elemental_arrayEx"} : (!fir.box<!fir.array<?xf32>>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.box<!fir.array<?xf32>>) ! CHECK: hlfir.region_assign { ! CHECK: %[[VAL_2:.*]] = arith.constant 4.200000e+01 : f32 ! CHECK: %[[VAL_3:.*]] = arith.constant 0 : index @@ -126,9 +126,9 @@ end subroutine ! CHECK-SAME: %[[VAL_0:.*]]: !fir.box<!fir.array<?xi32>> {fir.bindc_name = "i"}, ! CHECK-SAME: %[[VAL_1:.*]]: !fir.box<!fir.array<?x!fir.logical<4>>> {fir.bindc_name = "l"}, ! CHECK-SAME: %[[VAL_2:.*]]: !fir.box<!fir.array<?x!fir.logical<4>>> {fir.bindc_name = "l2"}) { -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {uniq_name = "_QMuser_defFtest_where_user_def_assignmentEi"} : (!fir.box<!fir.array<?xi32>>, !fir.dscope) -> (!fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>>) -! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %{{[0-9]+}} {uniq_name = "_QMuser_defFtest_where_user_def_assignmentEl"} : (!fir.box<!fir.array<?x!fir.logical<4>>>, !fir.dscope) -> (!fir.box<!fir.array<?x!fir.logical<4>>>, !fir.box<!fir.array<?x!fir.logical<4>>>) -! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_2]] dummy_scope %{{[0-9]+}} {uniq_name = "_QMuser_defFtest_where_user_def_assignmentEl2"} : (!fir.box<!fir.array<?x!fir.logical<4>>>, !fir.dscope) -> (!fir.box<!fir.array<?x!fir.logical<4>>>, !fir.box<!fir.array<?x!fir.logical<4>>>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QMuser_defFtest_where_user_def_assignmentEi"} : (!fir.box<!fir.array<?xi32>>, !fir.dscope) -> (!fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>>) +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QMuser_defFtest_where_user_def_assignmentEl"} : (!fir.box<!fir.array<?x!fir.logical<4>>>, !fir.dscope) -> (!fir.box<!fir.array<?x!fir.logical<4>>>, !fir.box<!fir.array<?x!fir.logical<4>>>) +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_2]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QMuser_defFtest_where_user_def_assignmentEl2"} : (!fir.box<!fir.array<?x!fir.logical<4>>>, !fir.dscope) -> (!fir.box<!fir.array<?x!fir.logical<4>>>, !fir.box<!fir.array<?x!fir.logical<4>>>) ! CHECK: hlfir.where { ! CHECK: hlfir.yield %[[VAL_4]]#0 : !fir.box<!fir.array<?x!fir.logical<4>>> ! CHECK: } do { @@ -171,11 +171,11 @@ end subroutine ! CHECK: %[[VAL_2:.*]] = arith.constant 20 : index ! CHECK: %[[VAL_3:.*]] = arith.constant 10 : index ! CHECK: %[[VAL_4:.*]] = fir.shape %[[VAL_2]], %[[VAL_3]] : (index, index) -> !fir.shape<2> -! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_4]]) dummy_scope %{{[0-9]+}} {uniq_name = "_QMuser_defFtest_forall_user_def_assignmentEi"} : (!fir.ref<!fir.array<20x10xi32>>, !fir.shape<2>, !fir.dscope) -> (!fir.ref<!fir.array<20x10xi32>>, !fir.ref<!fir.array<20x10xi32>>) +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_4]]) dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QMuser_defFtest_forall_user_def_assignmentEi"} : (!fir.ref<!fir.array<20x10xi32>>, !fir.shape<2>, !fir.dscope) -> (!fir.ref<!fir.array<20x10xi32>>, !fir.ref<!fir.array<20x10xi32>>) ! CHECK: %[[VAL_6:.*]] = arith.constant 20 : index ! CHECK: %[[VAL_7:.*]] = arith.constant 10 : index ! CHECK: %[[VAL_8:.*]] = fir.shape %[[VAL_6]], %[[VAL_7]] : (index, index) -> !fir.shape<2> -! CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[VAL_1]](%[[VAL_8]]) dummy_scope %{{[0-9]+}} {uniq_name = "_QMuser_defFtest_forall_user_def_assignmentEl"} : (!fir.ref<!fir.array<20x10x!fir.logical<4>>>, !fir.shape<2>, !fir.dscope) -> (!fir.ref<!fir.array<20x10x!fir.logical<4>>>, !fir.ref<!fir.array<20x10x!fir.logical<4>>>) +! CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[VAL_1]](%[[VAL_8]]) dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QMuser_defFtest_forall_user_def_assignmentEl"} : (!fir.ref<!fir.array<20x10x!fir.logical<4>>>, !fir.shape<2>, !fir.dscope) -> (!fir.ref<!fir.array<20x10x!fir.logical<4>>>, !fir.ref<!fir.array<20x10x!fir.logical<4>>>) ! CHECK: %[[VAL_10:.*]] = arith.constant 1 : i32 ! CHECK: %[[VAL_11:.*]] = arith.constant 10 : i32 ! CHECK: hlfir.forall lb { @@ -218,11 +218,11 @@ end subroutine ! CHECK: %[[VAL_2:.*]] = arith.constant 20 : index ! CHECK: %[[VAL_3:.*]] = arith.constant 10 : index ! CHECK: %[[VAL_4:.*]] = fir.shape %[[VAL_2]], %[[VAL_3]] : (index, index) -> !fir.shape<2> -! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_1]](%[[VAL_4]]) dummy_scope %{{[0-9]+}} {uniq_name = "_QMuser_defFtest_forall_user_def_assignment_non_elemental_arrayEl"} : (!fir.ref<!fir.array<20x10x!fir.logical<4>>>, !fir.shape<2>, !fir.dscope) -> (!fir.ref<!fir.array<20x10x!fir.logical<4>>>, !fir.ref<!fir.array<20x10x!fir.logical<4>>>) +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_1]](%[[VAL_4]]) dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QMuser_defFtest_forall_user_def_assignment_non_elemental_arrayEl"} : (!fir.ref<!fir.array<20x10x!fir.logical<4>>>, !fir.shape<2>, !fir.dscope) -> (!fir.ref<!fir.array<20x10x!fir.logical<4>>>, !fir.ref<!fir.array<20x10x!fir.logical<4>>>) ! CHECK: %[[VAL_6:.*]] = arith.constant 20 : index ! CHECK: %[[VAL_7:.*]] = arith.constant 10 : index ! CHECK: %[[VAL_8:.*]] = fir.shape %[[VAL_6]], %[[VAL_7]] : (index, index) -> !fir.shape<2> -! CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_8]]) dummy_scope %{{[0-9]+}} {uniq_name = "_QMuser_defFtest_forall_user_def_assignment_non_elemental_arrayEx"} : (!fir.ref<!fir.array<20x10xf32>>, !fir.shape<2>, !fir.dscope) -> (!fir.ref<!fir.array<20x10xf32>>, !fir.ref<!fir.array<20x10xf32>>) +! CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_8]]) dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QMuser_defFtest_forall_user_def_assignment_non_elemental_arrayEx"} : (!fir.ref<!fir.array<20x10xf32>>, !fir.shape<2>, !fir.dscope) -> (!fir.ref<!fir.array<20x10xf32>>, !fir.ref<!fir.array<20x10xf32>>) ! CHECK: %[[VAL_10:.*]] = arith.constant 1 : i32 ! CHECK: %[[VAL_11:.*]] = arith.constant 10 : i32 ! CHECK: hlfir.forall lb { @@ -269,8 +269,8 @@ end subroutine ! CHECK-LABEL: func.func @_QMuser_defPtest_pointer( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>> {fir.bindc_name = "p"}, ! CHECK-SAME: %[[VAL_1:.*]]: !fir.box<!fir.array<?x?xf32>> {fir.bindc_name = "x"}) { -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QMuser_defFtest_pointerEp"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>) -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %{{[0-9]+}} {uniq_name = "_QMuser_defFtest_pointerEx"} : (!fir.box<!fir.array<?x?xf32>>, !fir.dscope) -> (!fir.box<!fir.array<?x?xf32>>, !fir.box<!fir.array<?x?xf32>>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QMuser_defFtest_pointerEp"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QMuser_defFtest_pointerEx"} : (!fir.box<!fir.array<?x?xf32>>, !fir.dscope) -> (!fir.box<!fir.array<?x?xf32>>, !fir.box<!fir.array<?x?xf32>>) ! CHECK: hlfir.region_assign { ! CHECK: hlfir.yield %[[VAL_3]]#0 : !fir.box<!fir.array<?x?xf32>> ! CHECK: } to { @@ -287,8 +287,8 @@ end subroutine ! CHECK-LABEL: func.func @_QMuser_defPtest_allocatable( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.heap<!fir.array<?x?xi32>>>> {fir.bindc_name = "a"}, ! CHECK-SAME: %[[VAL_1:.*]]: !fir.box<!fir.array<?xf32>> {fir.bindc_name = "x"}) { -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QMuser_defFtest_allocatableEa"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?x?xi32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?x?xi32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?x?xi32>>>>) -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %{{[0-9]+}} {uniq_name = "_QMuser_defFtest_allocatableEx"} : (!fir.box<!fir.array<?xf32>>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.box<!fir.array<?xf32>>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QMuser_defFtest_allocatableEa"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?x?xi32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?x?xi32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?x?xi32>>>>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QMuser_defFtest_allocatableEx"} : (!fir.box<!fir.array<?xf32>>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.box<!fir.array<?xf32>>) ! CHECK: hlfir.region_assign { ! CHECK: hlfir.yield %[[VAL_3]]#0 : !fir.box<!fir.array<?xf32>> ! CHECK: } to { @@ -313,7 +313,7 @@ end subroutine test_char_get_length ! CHECK-LABEL: func.func @_QPtest_char_get_length( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.boxchar<1> {fir.bindc_name = "ch"}) { ! CHECK: %[[VAL_1:.*]]:2 = fir.unboxchar %[[VAL_0]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index) -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]]#0 typeparams %[[VAL_1]]#1 dummy_scope %{{[0-9]+}} {uniq_name = "_QFtest_char_get_lengthEch"} : (!fir.ref<!fir.char<1,?>>, index, !fir.dscope) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]]#0 typeparams %[[VAL_1]]#1 dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFtest_char_get_lengthEch"} : (!fir.ref<!fir.char<1,?>>, index, !fir.dscope) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>) ! CHECK: %[[VAL_3:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFtest_char_get_lengthEx"} ! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_3]] {uniq_name = "_QFtest_char_get_lengthEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: hlfir.region_assign { diff --git a/flang/test/Lower/HLFIR/vector-subscript-as-value.f90 b/flang/test/Lower/HLFIR/vector-subscript-as-value.f90 index 6b69369..4ec57c7 100644 --- a/flang/test/Lower/HLFIR/vector-subscript-as-value.f90 +++ b/flang/test/Lower/HLFIR/vector-subscript-as-value.f90 @@ -68,7 +68,7 @@ subroutine foo3(x, y) call bar2(x(1:8:2, 5, y)) end subroutine ! CHECK-LABEL: func.func @_QPfoo3( -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0:[a-z0-9]*]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFfoo3Ex"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?x?x?xi32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?x?x?xi32>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?x?x?xi32>>>>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0:[a-z0-9]*]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFfoo3Ex"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?x?x?xi32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?x?x?xi32>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?x?x?xi32>>>>) ! CHECK: %[[VAL_3:.*]] = arith.constant 20 : index ! CHECK: %[[VAL_4:.*]] = fir.shape %[[VAL_3]] : (index) -> !fir.shape<1> ! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_1:[a-z0-9]*]](%[[VAL_4:[a-z0-9]*]]) {{.*}}Ey @@ -196,8 +196,8 @@ end subroutine ! CHECK-LABEL: func.func @_QPtest_passing_subscripted_poly( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.class<!fir.array<?x?xnone>> ! CHECK-SAME: %[[VAL_1:.*]]: !fir.box<!fir.array<?xi64>> -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFtest_passing_subscripted_polyEvector"} : (!fir.box<!fir.array<?xi64>>, !fir.dscope) -> (!fir.box<!fir.array<?xi64>>, !fir.box<!fir.array<?xi64>>) -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFtest_passing_subscripted_polyEx"} : (!fir.class<!fir.array<?x?xnone>>, !fir.dscope) -> (!fir.class<!fir.array<?x?xnone>>, !fir.class<!fir.array<?x?xnone>>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFtest_passing_subscripted_polyEvector"} : (!fir.box<!fir.array<?xi64>>, !fir.dscope) -> (!fir.box<!fir.array<?xi64>>, !fir.box<!fir.array<?xi64>>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFtest_passing_subscripted_polyEx"} : (!fir.class<!fir.array<?x?xnone>>, !fir.dscope) -> (!fir.class<!fir.array<?x?xnone>>, !fir.class<!fir.array<?x?xnone>>) ! CHECK: %[[VAL_4:.*]] = arith.constant 314 : index ! CHECK: %[[VAL_5:.*]] = arith.constant 0 : index ! CHECK: %[[VAL_6:.*]]:3 = fir.box_dims %[[VAL_2]]#0, %[[VAL_5]] : (!fir.box<!fir.array<?xi64>>, index) -> (index, index, index) diff --git a/flang/test/Lower/Intrinsics/adjustl.f90 b/flang/test/Lower/Intrinsics/adjustl.f90 index a742f58..b66a840 100644 --- a/flang/test/Lower/Intrinsics/adjustl.f90 +++ b/flang/test/Lower/Intrinsics/adjustl.f90 @@ -16,4 +16,3 @@ subroutine adjustl_test ! CHECK: fir.call @_FortranAAdjustl(%[[r3]], %[[r4]], %[[r5]], %{{.*}}) {{.*}}: (!fir.ref<!fir.box<none>>, !fir.box<none>, !fir.ref<i8>, i32) -> () adjust_str = adjustl(adjust_str) end subroutine - diff --git a/flang/test/Lower/Intrinsics/adjustr.f90 b/flang/test/Lower/Intrinsics/adjustr.f90 index a929ab1..8e82371 100644 --- a/flang/test/Lower/Intrinsics/adjustr.f90 +++ b/flang/test/Lower/Intrinsics/adjustr.f90 @@ -16,4 +16,3 @@ subroutine adjustr_test ! CHECK: fir.call @_FortranAAdjustr(%[[r3]], %[[r4]], %[[r5]], %{{.*}}) {{.*}}: (!fir.ref<!fir.box<none>>, !fir.box<none>, !fir.ref<i8>, i32) -> () adjust_str = adjustr(adjust_str) end subroutine - diff --git a/flang/test/Lower/Intrinsics/associated-proc-pointers.f90 b/flang/test/Lower/Intrinsics/associated-proc-pointers.f90 index f5dd86f..d1db8a5 100644 --- a/flang/test/Lower/Intrinsics/associated-proc-pointers.f90 +++ b/flang/test/Lower/Intrinsics/associated-proc-pointers.f90 @@ -9,7 +9,7 @@ end subroutine ! CHECK-LABEL: func.func @_QPtest_proc_pointer_1( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.boxproc<() -> ()>>, ! CHECK-SAME: %[[VAL_1:.*]]: !fir.boxproc<() -> ()>) { -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFtest_proc_pointer_1Ep"} : (!fir.ref<!fir.boxproc<() -> ()>>, !fir.dscope) -> (!fir.ref<!fir.boxproc<() -> ()>>, !fir.ref<!fir.boxproc<() -> ()>>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFtest_proc_pointer_1Ep"} : (!fir.ref<!fir.boxproc<() -> ()>>, !fir.dscope) -> (!fir.ref<!fir.boxproc<() -> ()>>, !fir.ref<!fir.boxproc<() -> ()>>) ! CHECK: %[[VAL_3:.*]] = fir.load %[[VAL_2]]#0 : !fir.ref<!fir.boxproc<() -> ()>> ! CHECK: %[[VAL_4:.*]] = fir.box_addr %[[VAL_3]] : (!fir.boxproc<() -> ()>) -> (() -> ()) ! CHECK: %[[VAL_5:.*]] = fir.box_addr %[[VAL_1]] : (!fir.boxproc<() -> ()>) -> (() -> ()) @@ -28,8 +28,8 @@ end subroutine ! CHECK-LABEL: func.func @_QPtest_proc_pointer_2( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.boxproc<() -> ()>>, ! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref<!fir.boxproc<() -> ()>>) { -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFtest_proc_pointer_2Ep"} : (!fir.ref<!fir.boxproc<() -> ()>>, !fir.dscope) -> (!fir.ref<!fir.boxproc<() -> ()>>, !fir.ref<!fir.boxproc<() -> ()>>) -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFtest_proc_pointer_2Ep_target"} : (!fir.ref<!fir.boxproc<() -> ()>>, !fir.dscope) -> (!fir.ref<!fir.boxproc<() -> ()>>, !fir.ref<!fir.boxproc<() -> ()>>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFtest_proc_pointer_2Ep"} : (!fir.ref<!fir.boxproc<() -> ()>>, !fir.dscope) -> (!fir.ref<!fir.boxproc<() -> ()>>, !fir.ref<!fir.boxproc<() -> ()>>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFtest_proc_pointer_2Ep_target"} : (!fir.ref<!fir.boxproc<() -> ()>>, !fir.dscope) -> (!fir.ref<!fir.boxproc<() -> ()>>, !fir.ref<!fir.boxproc<() -> ()>>) ! CHECK: %[[VAL_4:.*]] = fir.load %[[VAL_2]]#0 : !fir.ref<!fir.boxproc<() -> ()>> ! CHECK: %[[VAL_5:.*]] = fir.box_addr %[[VAL_4]] : (!fir.boxproc<() -> ()>) -> (() -> ()) ! CHECK: %[[VAL_6:.*]] = fir.load %[[VAL_3]]#0 : !fir.ref<!fir.boxproc<() -> ()>> @@ -50,7 +50,7 @@ end subroutine ! CHECK-LABEL: func.func @_QPtest_proc_pointer_3( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.boxproc<() -> ()>>, ! CHECK-SAME: %[[VAL_1:.*]]: !fir.boxproc<() -> ()>) { -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFtest_proc_pointer_3Ep"} : (!fir.ref<!fir.boxproc<() -> ()>>, !fir.dscope) -> (!fir.ref<!fir.boxproc<() -> ()>>, !fir.ref<!fir.boxproc<() -> ()>>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFtest_proc_pointer_3Ep"} : (!fir.ref<!fir.boxproc<() -> ()>>, !fir.dscope) -> (!fir.ref<!fir.boxproc<() -> ()>>, !fir.ref<!fir.boxproc<() -> ()>>) ! CHECK: %[[VAL_3:.*]] = fir.load %[[VAL_2]]#0 : !fir.ref<!fir.boxproc<() -> ()>> ! CHECK: %[[VAL_4:.*]] = fir.box_addr %[[VAL_3]] : (!fir.boxproc<() -> ()>) -> (() -> ()) ! CHECK: %[[VAL_5:.*]] = fir.box_addr %[[VAL_1]] : (!fir.boxproc<() -> ()>) -> (() -> ()) @@ -69,7 +69,7 @@ subroutine test_proc_pointer_4(p) end subroutine ! CHECK-LABEL: func.func @_QPtest_proc_pointer_4( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.boxproc<() -> ()>>) { -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFtest_proc_pointer_4Ep"} : (!fir.ref<!fir.boxproc<() -> ()>>, !fir.dscope) -> (!fir.ref<!fir.boxproc<() -> ()>>, !fir.ref<!fir.boxproc<() -> ()>>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFtest_proc_pointer_4Ep"} : (!fir.ref<!fir.boxproc<() -> ()>>, !fir.dscope) -> (!fir.ref<!fir.boxproc<() -> ()>>, !fir.ref<!fir.boxproc<() -> ()>>) ! CHECK: %[[VAL_2:.*]] = fir.address_of(@_QPsome_external) : () -> () ! CHECK: %[[VAL_3:.*]] = fir.emboxproc %[[VAL_2]] : (() -> ()) -> !fir.boxproc<() -> ()> ! CHECK: %[[VAL_4:.*]] = fir.load %[[VAL_1]]#0 : !fir.ref<!fir.boxproc<() -> ()>> @@ -95,7 +95,7 @@ end subroutine ! CHECK-LABEL: func.func @_QPtest_proc_pointer_5( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.boxproc<() -> ()>>, ! CHECK-SAME: %[[VAL_1:.*]]: tuple<!fir.boxproc<() -> ()>, i64> {fir.char_proc}) { -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFtest_proc_pointer_5Ep"} : (!fir.ref<!fir.boxproc<() -> ()>>, !fir.dscope) -> (!fir.ref<!fir.boxproc<() -> ()>>, !fir.ref<!fir.boxproc<() -> ()>>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFtest_proc_pointer_5Ep"} : (!fir.ref<!fir.boxproc<() -> ()>>, !fir.dscope) -> (!fir.ref<!fir.boxproc<() -> ()>>, !fir.ref<!fir.boxproc<() -> ()>>) ! CHECK: %[[VAL_3:.*]] = fir.extract_value %[[VAL_1]], [0 : index] : (tuple<!fir.boxproc<() -> ()>, i64>) -> !fir.boxproc<() -> ()> ! CHECK: %[[VAL_4:.*]] = fir.box_addr %[[VAL_3]] : (!fir.boxproc<() -> ()>) -> (() -> ()) ! CHECK: %[[VAL_5:.*]] = arith.constant 10 : i64 diff --git a/flang/test/Lower/Intrinsics/associated.f90 b/flang/test/Lower/Intrinsics/associated.f90 index 9308ec7..b32e0ab 100644 --- a/flang/test/Lower/Intrinsics/associated.f90 +++ b/flang/test/Lower/Intrinsics/associated.f90 @@ -23,11 +23,11 @@ subroutine associated_test(scalar, array) ! CHECK: fir.call @_FortranAPointerIsAssociatedWith(%[[sbox]], %[[zbox]]) {{.*}}: (!fir.box<none>, !fir.box<none>) -> i1 print *, associated(scalar, ziel) end subroutine - + subroutine test_func_results() interface function get_pointer() - real, pointer :: get_pointer(:) + real, pointer :: get_pointer(:) end function end interface ! CHECK: %[[result:.*]] = fir.call @_QPget_pointer() {{.*}}: () -> !fir.box<!fir.ptr<!fir.array<?xf32>>> @@ -38,7 +38,7 @@ subroutine associated_test(scalar, array) ! CHECK: arith.cmpi ne, %[[addr_cast]], %c0{{.*}} : i64 print *, associated(get_pointer()) end subroutine - + ! CHECK-LABEL: func @_QPtest_optional_target_1( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>> {fir.bindc_name = "p"}, ! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref<!fir.array<10xf32>> {fir.bindc_name = "optionales_ziel", fir.optional, fir.target}) { @@ -61,7 +61,7 @@ subroutine associated_test(scalar, array) ! CHECK: %[[VAL_15:.*]] = fir.convert %[[VAL_4]] : (!fir.box<!fir.array<10xf32>>) -> !fir.box<none> ! CHECK: fir.call @_FortranAPointerIsAssociatedWith(%[[VAL_14]], %[[VAL_15]]) {{.*}}: (!fir.box<none>, !fir.box<none>) -> i1 end subroutine - + ! CHECK-LABEL: func @_QPtest_optional_target_2( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>> {fir.bindc_name = "p"}, ! CHECK-SAME: %[[VAL_1:.*]]: !fir.box<!fir.array<?xf32>> {fir.bindc_name = "optionales_ziel", fir.optional, fir.target}) { @@ -81,7 +81,7 @@ subroutine associated_test(scalar, array) ! CHECK: %[[VAL_12:.*]] = fir.convert %[[VAL_8]] : (!fir.box<!fir.array<?xf32>>) -> !fir.box<none> ! CHECK: fir.call @_FortranAPointerIsAssociatedWith(%[[VAL_11]], %[[VAL_12]]) {{.*}}: (!fir.box<none>, !fir.box<none>) -> i1 end subroutine - + ! CHECK-LABEL: func @_QPtest_optional_target_3( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>> {fir.bindc_name = "p"}, ! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>> {fir.bindc_name = "optionales_ziel", fir.optional}) { @@ -102,7 +102,7 @@ subroutine associated_test(scalar, array) ! CHECK: %[[VAL_13:.*]] = fir.convert %[[VAL_9]] : (!fir.box<!fir.ptr<!fir.array<?xf32>>>) -> !fir.box<none> ! CHECK: fir.call @_FortranAPointerIsAssociatedWith(%[[VAL_12]], %[[VAL_13]]) {{.*}}: (!fir.box<none>, !fir.box<none>) -> i1 end subroutine - + ! CHECK-LABEL: func @_QPtest_optional_target_4( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>> {fir.bindc_name = "p"}, ! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>> {fir.bindc_name = "optionales_ziel", fir.optional, fir.target}) { @@ -123,7 +123,7 @@ subroutine associated_test(scalar, array) ! CHECK: %[[VAL_13:.*]] = fir.convert %[[VAL_9]] : (!fir.box<!fir.heap<!fir.array<?xf32>>>) -> !fir.box<none> ! CHECK: fir.call @_FortranAPointerIsAssociatedWith(%[[VAL_12]], %[[VAL_13]]) {{.*}}: (!fir.box<none>, !fir.box<none>) -> i1 end subroutine - + ! CHECK-LABEL: func @_QPtest_pointer_target( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>> {fir.bindc_name = "p"}, ! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>> {fir.bindc_name = "pointer_ziel"}) { @@ -137,7 +137,7 @@ subroutine associated_test(scalar, array) ! CHECK: %[[VAL_10:.*]] = fir.convert %[[VAL_7]] : (!fir.box<!fir.ptr<!fir.array<?xf32>>>) -> !fir.box<none> ! CHECK: fir.call @_FortranAPointerIsAssociatedWith(%[[VAL_9]], %[[VAL_10]]) {{.*}}: (!fir.box<none>, !fir.box<none>) -> i1 end subroutine - + ! CHECK-LABEL: func @_QPtest_allocatable_target( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>> {fir.bindc_name = "p"}, ! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>> {fir.bindc_name = "allocatable_ziel", fir.target}) { diff --git a/flang/test/Lower/Intrinsics/btest.f90 b/flang/test/Lower/Intrinsics/btest.f90 index 6c0fccd..b10850e 100644 --- a/flang/test/Lower/Intrinsics/btest.f90 +++ b/flang/test/Lower/Intrinsics/btest.f90 @@ -15,4 +15,3 @@ function btest_test(i, j) ! CHECK: return %[[VAL_9]] : !fir.logical<4> btest_test = btest(i, j) end -
\ No newline at end of file diff --git a/flang/test/Lower/Intrinsics/c_f_pointer.f90 b/flang/test/Lower/Intrinsics/c_f_pointer.f90 index c1f1d79..f54fda4 100644 --- a/flang/test/Lower/Intrinsics/c_f_pointer.f90 +++ b/flang/test/Lower/Intrinsics/c_f_pointer.f90 @@ -153,7 +153,6 @@ subroutine dynamic_shape_lower(cptr, fpr, shape, lower) ! CHECK: %[[VAL_2:.*]] = fir.shape %[[C_0]], %[[C_0]] : (index, index) -> !fir.shape<2> ! CHECK: %[[VAL_3:.*]] = fir.embox %[[VAL_1:.*]](%[[VAL_2]]) : (!fir.ptr<!fir.array<?x?xf32>>, !fir.shape<2>) -> !fir.box<!fir.ptr<!fir.array<?x?xf32>>> ! CHECK: fir.store %[[VAL_3]] to %[[VAL_0:.*]] : !fir.ref<!fir.box<!fir.ptr<!fir.array<?x?xf32>>>> -! CHECK: %[[VAL_4:.*]] = fir.alloca i32 {bindc_name = "n", uniq_name = "_QFdynamic_shape_lowerEn"} ! CHECK: %[[VAL_5:.*]] = fir.coordinate_of %[[ARG_0:.*]], __address : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>) -> !fir.ref<i64> ! CHECK: %[[VAL_6:.*]] = fir.load %[[VAL_5]] : !fir.ref<i64> ! CHECK: %[[VAL_7:.*]] = fir.convert %[[VAL_6]] : (i64) -> !fir.ptr<!fir.array<?x?xf32>> diff --git a/flang/test/Lower/Intrinsics/c_f_procpointer.f90 b/flang/test/Lower/Intrinsics/c_f_procpointer.f90 index b5e9783..e4cfacb 100644 --- a/flang/test/Lower/Intrinsics/c_f_procpointer.f90 +++ b/flang/test/Lower/Intrinsics/c_f_procpointer.f90 @@ -10,8 +10,8 @@ end subroutine ! CHECK-LABEL: func.func @_QPtest_c_funloc( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.boxproc<() -> ()>>, ! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_funptr{__address:i64}>> {fir.bindc_name = "cptr"}) { -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFtest_c_funlocEcptr"} : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_funptr{__address:i64}>>, !fir.dscope) -> (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_funptr{__address:i64}>>, !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_funptr{__address:i64}>>) -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFtest_c_funlocEfptr"} : (!fir.ref<!fir.boxproc<() -> ()>>, !fir.dscope) -> (!fir.ref<!fir.boxproc<() -> ()>>, !fir.ref<!fir.boxproc<() -> ()>>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFtest_c_funlocEcptr"} : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_funptr{__address:i64}>>, !fir.dscope) -> (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_funptr{__address:i64}>>, !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_funptr{__address:i64}>>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFtest_c_funlocEfptr"} : (!fir.ref<!fir.boxproc<() -> ()>>, !fir.dscope) -> (!fir.ref<!fir.boxproc<() -> ()>>, !fir.ref<!fir.boxproc<() -> ()>>) ! CHECK: %[[VAL_5:.*]] = fir.coordinate_of %[[VAL_2]]#0, __address : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_funptr{__address:i64}>>) -> !fir.ref<i64> ! CHECK: %[[VAL_6:.*]] = fir.load %[[VAL_5]] : !fir.ref<i64> ! CHECK: %[[VAL_7:.*]] = fir.convert %[[VAL_6]] : (i64) -> (() -> ()) @@ -31,8 +31,8 @@ end subroutine ! CHECK-LABEL: func.func @_QPtest_c_funloc_char( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.boxproc<() -> ()>>, ! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_funptr{__address:i64}>> {fir.bindc_name = "cptr"}) { -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFtest_c_funloc_charEcptr"} : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_funptr{__address:i64}>>, !fir.dscope) -> (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_funptr{__address:i64}>>, !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_funptr{__address:i64}>>) -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFtest_c_funloc_charEfptr"} : (!fir.ref<!fir.boxproc<() -> ()>>, !fir.dscope) -> (!fir.ref<!fir.boxproc<() -> ()>>, !fir.ref<!fir.boxproc<() -> ()>>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFtest_c_funloc_charEcptr"} : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_funptr{__address:i64}>>, !fir.dscope) -> (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_funptr{__address:i64}>>, !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_funptr{__address:i64}>>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFtest_c_funloc_charEfptr"} : (!fir.ref<!fir.boxproc<() -> ()>>, !fir.dscope) -> (!fir.ref<!fir.boxproc<() -> ()>>, !fir.ref<!fir.boxproc<() -> ()>>) ! CHECK: %[[VAL_5:.*]] = fir.coordinate_of %[[VAL_2]]#0, __address : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_funptr{__address:i64}>>) -> !fir.ref<i64> ! CHECK: %[[VAL_6:.*]] = fir.load %[[VAL_5]] : !fir.ref<i64> ! CHECK: %[[VAL_7:.*]] = fir.convert %[[VAL_6]] : (i64) -> (() -> ()) diff --git a/flang/test/Lower/Intrinsics/c_funloc-proc-pointers.f90 b/flang/test/Lower/Intrinsics/c_funloc-proc-pointers.f90 index fbd1968..e991958 100644 --- a/flang/test/Lower/Intrinsics/c_funloc-proc-pointers.f90 +++ b/flang/test/Lower/Intrinsics/c_funloc-proc-pointers.f90 @@ -8,7 +8,7 @@ subroutine test_c_funloc(p) end subroutine ! CHECK-LABEL: func.func @_QPtest_c_funloc( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.boxproc<() -> ()>>) { -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFtest_c_funlocEp"} : (!fir.ref<!fir.boxproc<() -> ()>>, !fir.dscope) -> (!fir.ref<!fir.boxproc<() -> ()>>, !fir.ref<!fir.boxproc<() -> ()>>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFtest_c_funlocEp"} : (!fir.ref<!fir.boxproc<() -> ()>>, !fir.dscope) -> (!fir.ref<!fir.boxproc<() -> ()>>, !fir.ref<!fir.boxproc<() -> ()>>) ! CHECK: %[[VAL_2:.*]] = fir.load %[[VAL_1]]#0 : !fir.ref<!fir.boxproc<() -> ()>> ! CHECK: %[[VAL_3:.*]] = fir.alloca !fir.type<_QM__fortran_builtinsT__builtin_c_funptr{__address:i64}> ! CHECK: %[[VAL_5:.*]] = fir.coordinate_of %[[VAL_3]], __address : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_funptr{__address:i64}>>) -> !fir.ref<i64> @@ -27,7 +27,7 @@ subroutine test_c_funloc_char(p) end subroutine ! CHECK-LABEL: func.func @_QPtest_c_funloc_char( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.boxproc<() -> ()>>) { -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFtest_c_funloc_charEp"} : (!fir.ref<!fir.boxproc<() -> ()>>, !fir.dscope) -> (!fir.ref<!fir.boxproc<() -> ()>>, !fir.ref<!fir.boxproc<() -> ()>>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFtest_c_funloc_charEp"} : (!fir.ref<!fir.boxproc<() -> ()>>, !fir.dscope) -> (!fir.ref<!fir.boxproc<() -> ()>>, !fir.ref<!fir.boxproc<() -> ()>>) ! CHECK: %[[VAL_2:.*]] = fir.load %[[VAL_1]]#0 : !fir.ref<!fir.boxproc<() -> ()>> ! CHECK: %[[VAL_3:.*]] = fir.alloca !fir.type<_QM__fortran_builtinsT__builtin_c_funptr{__address:i64}> ! CHECK: %[[VAL_5:.*]] = fir.coordinate_of %[[VAL_3]], __address : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_funptr{__address:i64}>>) -> !fir.ref<i64> diff --git a/flang/test/Lower/Intrinsics/c_ptr_eq_ne.f90 b/flang/test/Lower/Intrinsics/c_ptr_eq_ne.f90 index 80feb08..16c2452 100644 --- a/flang/test/Lower/Intrinsics/c_ptr_eq_ne.f90 +++ b/flang/test/Lower/Intrinsics/c_ptr_eq_ne.f90 @@ -10,8 +10,8 @@ end ! CHECK-LABEL: func.func @_QPtest_c_ptr_eq( ! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>> {fir.bindc_name = "ptr1"}, %[[ARG1:.*]]: !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>> {fir.bindc_name = "ptr2"}) -> !fir.logical<4> { -! CHECK: %[[DECL_ARG0:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<intent_in>, uniq_name = "_QFtest_c_ptr_eqEptr1"} : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>, !fir.dscope) -> (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>, !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>) -! CHECK: %[[DECL_ARG1:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<intent_in>, uniq_name = "_QFtest_c_ptr_eqEptr2"} : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>, !fir.dscope) -> (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>, !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>) +! CHECK: %[[DECL_ARG0:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<intent_in>, uniq_name = "_QFtest_c_ptr_eqEptr1"} : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>, !fir.dscope) -> (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>, !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>) +! CHECK: %[[DECL_ARG1:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<intent_in>, uniq_name = "_QFtest_c_ptr_eqEptr2"} : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>, !fir.dscope) -> (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>, !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>) ! CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.logical<4> {bindc_name = "test_c_ptr_eq", uniq_name = "_QFtest_c_ptr_eqEtest_c_ptr_eq"} ! CHECK: %[[DECL_RET:.*]]:2 = hlfir.declare %[[ALLOCA]] {uniq_name = "_QFtest_c_ptr_eqEtest_c_ptr_eq"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) ! CHECK: %[[COORD_ADDRESS0:.*]] = fir.coordinate_of %[[DECL_ARG0]]#0, __address : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>) -> !fir.ref<i64> @@ -35,8 +35,8 @@ end ! CHECK-LABEL: func.func @_QPtest_c_ptr_ne( ! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>> {fir.bindc_name = "ptr1"}, %[[ARG1:.*]]: !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>> {fir.bindc_name = "ptr2"}) -> !fir.logical<4> { -! CHECK: %[[DECL_ARG0:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<intent_in>, uniq_name = "_QFtest_c_ptr_neEptr1"} : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>, !fir.dscope) -> (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>, !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>) -! CHECK: %[[DECL_ARG1:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<intent_in>, uniq_name = "_QFtest_c_ptr_neEptr2"} : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>, !fir.dscope) -> (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>, !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>) +! CHECK: %[[DECL_ARG0:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<intent_in>, uniq_name = "_QFtest_c_ptr_neEptr1"} : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>, !fir.dscope) -> (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>, !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>) +! CHECK: %[[DECL_ARG1:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<intent_in>, uniq_name = "_QFtest_c_ptr_neEptr2"} : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>, !fir.dscope) -> (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>, !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>) ! CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.logical<4> {bindc_name = "test_c_ptr_ne", uniq_name = "_QFtest_c_ptr_neEtest_c_ptr_ne"} ! CHECK: %[[DECL_RET:.*]]:2 = hlfir.declare %[[ALLOCA]] {uniq_name = "_QFtest_c_ptr_neEtest_c_ptr_ne"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) ! CHECK: %[[COORD_ADDRESS0:.*]] = fir.coordinate_of %[[DECL_ARG0]]#0, __address : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>) -> !fir.ref<i64> diff --git a/flang/test/Lower/Intrinsics/ceiling.f90 b/flang/test/Lower/Intrinsics/ceiling.f90 index 8c283de..3c87bec 100644 --- a/flang/test/Lower/Intrinsics/ceiling.f90 +++ b/flang/test/Lower/Intrinsics/ceiling.f90 @@ -16,5 +16,3 @@ subroutine ceiling_test1(i, a) ! CHECK: %[[f:.*]] = math.ceil %{{.*}} : f32 ! CHECK: fir.convert %[[f]] : (f32) -> i64 end subroutine - - diff --git a/flang/test/Lower/Intrinsics/command_argument_count.f90 b/flang/test/Lower/Intrinsics/command_argument_count.f90 index a30b27d6..35737e8 100644 --- a/flang/test/Lower/Intrinsics/command_argument_count.f90 +++ b/flang/test/Lower/Intrinsics/command_argument_count.f90 @@ -1,6 +1,6 @@ ! RUN: bbc -emit-fir %s -o - | FileCheck %s ! bbc doesn't have a way to set the default kinds so we use flang driver -! RUN: flang -fc1 -fdefault-integer-8 -emit-fir %s -o - | FileCheck --check-prefixes=CHECK,CHECK-64 %s +! RUN: %flang_fc1 -fdefault-integer-8 -emit-fir %s -o - | FileCheck --check-prefixes=CHECK,CHECK-64 %s ! CHECK-LABEL: argument_count_test subroutine argument_count_test() diff --git a/flang/test/Lower/Intrinsics/count.f90 b/flang/test/Lower/Intrinsics/count.f90 index c3efe6b..064d011 100644 --- a/flang/test/Lower/Intrinsics/count.f90 +++ b/flang/test/Lower/Intrinsics/count.f90 @@ -11,7 +11,7 @@ subroutine count_test1(rslt, mask) rslt = count(mask) ! CHECK: %[[a5:.*]] = fir.call @_FortranACount(%[[a2]], %{{.*}}, %{{.*}}, %[[a4]]) {{.*}}: (!fir.box<none>, !fir.ref<i8>, i32, i32) -> i64 end subroutine - + ! CHECK-LABEL: test_count2 ! CHECK-SAME: %[[arg0:.*]]: !fir.box<!fir.array<?xi32>>{{.*}}, %[[arg1:.*]]: !fir.box<!fir.array<?x?x!fir.logical<4>>>{{.*}}) subroutine test_count2(rslt, mask) @@ -29,7 +29,7 @@ subroutine count_test1(rslt, mask) ! CHECK: %[[a12:.*]] = fir.box_addr %[[a10]] : (!fir.box<!fir.heap<!fir.array<?xi32>>>) -> !fir.heap<!fir.array<?xi32>> ! CHECK: fir.freemem %[[a12]] end subroutine - + ! CHECK-LABEL: test_count3 ! CHECK-SAME: %[[arg0:.*]]: !fir.ref<i32>{{.*}}, %[[arg1:.*]]: !fir.box<!fir.array<?x!fir.logical<4>>>{{.*}}) subroutine test_count3(rslt, mask) diff --git a/flang/test/Lower/Intrinsics/cpu_time.f90 b/flang/test/Lower/Intrinsics/cpu_time.f90 index 25ff4f8..73eead3 100644 --- a/flang/test/Lower/Intrinsics/cpu_time.f90 +++ b/flang/test/Lower/Intrinsics/cpu_time.f90 @@ -8,4 +8,3 @@ subroutine cpu_time_test(t) ! CHECK: fir.store %[[result32]] to %arg0 : !fir.ref<f32> call cpu_time(t) end subroutine - diff --git a/flang/test/Lower/Intrinsics/date_and_time.f90 b/flang/test/Lower/Intrinsics/date_and_time.f90 index 55b1383..d9ca46e 100644 --- a/flang/test/Lower/Intrinsics/date_and_time.f90 +++ b/flang/test/Lower/Intrinsics/date_and_time.f90 @@ -18,13 +18,13 @@ subroutine date_and_time_test(date, time, zone, values) ! CHECK: fir.call @_FortranADateAndTime(%[[dateBuffer]], %[[dateLen]], %[[timeBuffer]], %[[timeLen]], %[[zoneBuffer]], %[[zoneLen]], %{{.*}}, %{{.*}}, %[[valuesCast]]) {{.*}}: (!fir.ref<i8>, i64, !fir.ref<i8>, i64, !fir.ref<i8>, i64, !fir.ref<i8>, i32, !fir.box<none>) -> () call date_and_time(date, time, zone, values) end subroutine - + ! CHECK-LABEL: func @_QPdate_and_time_test2( ! CHECK-SAME: %[[date:.*]]: !fir.boxchar<1>{{.*}}) subroutine date_and_time_test2(date) character(*) :: date ! CHECK: %[[dateUnbox:.*]]:2 = fir.unboxchar %[[date]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index) - ! CHECK: %[[values:.*]] = fir.absent !fir.box<none> + ! CHECK: %[[values:.*]] = fir.absent !fir.box<none> ! CHECK: %[[dateBuffer:.*]] = fir.convert %[[dateUnbox]]#0 : (!fir.ref<!fir.char<1,?>>) -> !fir.ref<i8> ! CHECK: %[[dateLen:.*]] = fir.convert %[[dateUnbox]]#1 : (index) -> i64 ! CHECK: %[[timeBuffer:.*]] = fir.convert %c0{{.*}} : (index) -> !fir.ref<i8> @@ -34,7 +34,7 @@ subroutine date_and_time_test(date, time, zone, values) ! CHECK: fir.call @_FortranADateAndTime(%[[dateBuffer]], %[[dateLen]], %[[timeBuffer]], %[[timeLen]], %[[zoneBuffer]], %[[zoneLen]], %{{.*}}, %{{.*}}, %[[values]]) {{.*}}: (!fir.ref<i8>, i64, !fir.ref<i8>, i64, !fir.ref<i8>, i64, !fir.ref<i8>, i32, !fir.box<none>) -> () call date_and_time(date) end subroutine - + ! CHECK-LABEL: func @_QPdate_and_time_dynamic_optional( ! CHECK-SAME: %[[VAL_0:[^:]*]]: !fir.boxchar<1> ! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref<!fir.box<!fir.ptr<!fir.char<1,?>>>> diff --git a/flang/test/Lower/Intrinsics/eoshift.f90 b/flang/test/Lower/Intrinsics/eoshift.f90 index 9cd0b86..4f01ce9 100644 --- a/flang/test/Lower/Intrinsics/eoshift.f90 +++ b/flang/test/Lower/Intrinsics/eoshift.f90 @@ -13,16 +13,16 @@ subroutine eoshift_test1(arr, shift) ! CHECK: fir.store %[[init]] to %[[resBox]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.logical<4>>>>> ! CHECK: %[[boundBox:.*]] = fir.absent !fir.box<none> ! CHECK: %[[shift:.*]] = fir.load %arg1 : !fir.ref<i32> - + res = eoshift(arr, shift) - + ! CHECK: %[[resIRBox:.*]] = fir.convert %[[resBox]] : (!fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.logical<4>>>>>) -> !fir.ref<!fir.box<none>> ! CHECK: %[[arrBox:.*]] = fir.convert %[[arr]] : (!fir.box<!fir.array<3x!fir.logical<4>>>) -> !fir.box<none> ! CHECK: %[[shiftBox:.*]] = fir.convert %[[shift]] : (i32) -> i64 ! CHECK: fir.call @_FortranAEoshiftVector(%[[resIRBox]], %[[arrBox]], %[[shiftBox]], %[[boundBox]], {{.*}}, {{.*}}) {{.*}}: (!fir.ref<!fir.box<none>>, !fir.box<none>, i64, !fir.box<none>, !fir.ref<i8>, i32) -> () ! CHECK: fir.array_merge_store %[[resLoad]], {{.*}} to %[[res]] : !fir.array<3x!fir.logical<4>>, !fir.array<3x!fir.logical<4>>, !fir.ref<!fir.array<3x!fir.logical<4>>> end subroutine eoshift_test1 - + ! CHECK-LABEL: eoshift_test2 subroutine eoshift_test2(arr, shift, bound, dim) integer, dimension(3,3) :: arr, res @@ -31,9 +31,9 @@ subroutine eoshift_test1(arr, shift) ! CHECK: %[[resBox:.*]] = fir.alloca !fir.box<!fir.heap<!fir.array<?x?xi32>>> ! CHECK: %[[res:.*]] = fir.alloca !fir.array<3x3xi32> {bindc_name = "res", uniq_name = "_QFeoshift_test2Eres"} !CHECK: %[[resLoad:.*]] = fir.array_load %[[res]]({{.*}}) : (!fir.ref<!fir.array<3x3xi32>>, !fir.shape<2>) -> !fir.array<3x3xi32> - + res = eoshift(arr, shift, bound, dim) - + ! CHECK: %[[arr:.*]] = fir.embox %arg0({{.*}}) : (!fir.ref<!fir.array<3x3xi32>>, !fir.shape<2>) -> !fir.box<!fir.array<3x3xi32>> ! CHECK: %[[boundBox:.*]] = fir.embox %arg2 : (!fir.ref<i32>) -> !fir.box<i32> ! CHECK: %[[dim:.*]] = fir.load %arg3 : !fir.ref<i32> @@ -42,16 +42,16 @@ subroutine eoshift_test1(arr, shift) ! CHECK: %[[arrBox:.*]] = fir.convert %[[arr]] : (!fir.box<!fir.array<3x3xi32>>) -> !fir.box<none> ! CHECK: %[[shiftBoxNone:.*]] = fir.convert %[[shiftBox]] : (!fir.box<!fir.array<3xi32>>) -> !fir.box<none> ! CHECK: %[[boundBoxNone:.*]] = fir.convert %[[boundBox]] : (!fir.box<i32>) -> !fir.box<none> - + ! CHECK: fir.call @_FortranAEoshift(%[[resIRBox]], %[[arrBox]], %[[shiftBoxNone]], %[[boundBoxNone]], %[[dim]], {{.*}}, {{.*}}) {{.*}}: (!fir.ref<!fir.box<none>>, !fir.box<none>, !fir.box<none>, !fir.box<none>, i32, !fir.ref<i8>, i32) -> () ! CHECK: fir.array_merge_store %[[resLoad]], {{.*}} to %[[res]] : !fir.array<3x3xi32>, !fir.array<3x3xi32>, !fir.ref<!fir.array<3x3xi32>> end subroutine eoshift_test2 - + ! CHECK-LABEL: eoshift_test3 subroutine eoshift_test3(arr, shift, dim) character(4), dimension(3,3) :: arr, res integer :: shift, dim - + ! CHECK: %[[resBox:.*]] = fir.alloca !fir.box<!fir.heap<!fir.array<?x?x!fir.char<1,4>>>> ! CHECK: %[[arr:.*]]:2 = fir.unboxchar %arg0 : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index) ! CHECK: %[[array:.*]] = fir.convert %[[arr]]#0 : (!fir.ref<!fir.char<1,?>>) -> !fir.ref<!fir.array<3x3x!fir.char<1,4>>> @@ -59,9 +59,9 @@ subroutine eoshift_test1(arr, shift) ! CHECK: %[[resLoad:.*]] = fir.array_load %[[res]]({{.*}}) : (!fir.ref<!fir.array<3x3x!fir.char<1,4>>>, !fir.shape<2>) -> !fir.array<3x3x!fir.char<1,4>> ! CHECK: %[[arrayBox:.*]] = fir.embox %[[array]]({{.*}}) : (!fir.ref<!fir.array<3x3x!fir.char<1,4>>>, !fir.shape<2>) -> !fir.box<!fir.array<3x3x!fir.char<1,4>>> ! CHECK: %[[dim:.*]] = fir.load %arg2 : !fir.ref<i32> - + res = eoshift(arr, SHIFT=shift, DIM=dim) - + ! CHECK: %[[boundBox:.*]] = fir.absent !fir.box<none> ! CHECK: %[[shiftBox:.*]] = fir.embox %arg1 : (!fir.ref<i32>) -> !fir.box<i32> ! CHECK: %[[resIRBox:.*]] = fir.convert %[[resBox]] : (!fir.ref<!fir.box<!fir.heap<!fir.array<?x?x!fir.char<1,4>>>>>) -> !fir.ref<!fir.box<none>> @@ -70,7 +70,7 @@ subroutine eoshift_test1(arr, shift) ! CHECK: fir.call @_FortranAEoshift(%[[resIRBox]], %[[arrayBoxNone]], %[[shiftBoxNone]], %[[boundBox]], %[[dim]], {{.*}}, {{.*}}) {{.*}}: (!fir.ref<!fir.box<none>>, !fir.box<none>, !fir.box<none>, !fir.box<none>, i32, !fir.ref<i8>, i32) -> () ! CHECK: fir.array_merge_store %[[resLoad]], {{.*}} to %[[res]] : !fir.array<3x3x!fir.char<1,4>>, !fir.array<3x3x!fir.char<1,4>>, !fir.ref<!fir.array<3x3x!fir.char<1,4>>> end subroutine eoshift_test3 - + ! CHECK-LABEL: func @_QPeoshift_test_dynamic_optional( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.box<!fir.array<?x?xi32>> ! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref<i32> diff --git a/flang/test/Lower/Intrinsics/etime-function.f90 b/flang/test/Lower/Intrinsics/etime-function.f90 index f4594ce..a2017f1 100644 --- a/flang/test/Lower/Intrinsics/etime-function.f90 +++ b/flang/test/Lower/Intrinsics/etime-function.f90 @@ -11,9 +11,9 @@ subroutine etime_test(values, time) ! CHECK-NEXT: %[[c2:.*]] = arith.constant 2 : index ! CHECK-NEXT: %[[timeTmpAddr:.*]] = fir.alloca f32 ! CHECK-NEXT: %[[DSCOPE:.*]] = fir.dummy_scope : !fir.dscope - ! CHECK-NEXT: %[[timeDeclare:.*]] = fir.declare %[[timeArg]] dummy_scope %[[DSCOPE]] {uniq_name = "_QFetime_testEtime"} : (!fir.ref<f32>, !fir.dscope) -> !fir.ref<f32> + ! CHECK-NEXT: %[[timeDeclare:.*]] = fir.declare %[[timeArg]] dummy_scope %[[DSCOPE]] arg {{[0-9]+}} {uniq_name = "_QFetime_testEtime"} : (!fir.ref<f32>, !fir.dscope) -> !fir.ref<f32> ! CHECK-NEXT: %[[shape:.*]] = fir.shape %[[c2]] : (index) -> !fir.shape<1> - ! CHECK-NEXT: %[[valuesDeclare:.*]] = fir.declare %[[valuesArg]](%[[shape]]) dummy_scope %[[DSCOPE]] {uniq_name = "_QFetime_testEvalues"} : (!fir.ref<!fir.array<2xf32>>, !fir.shape<1>, !fir.dscope) -> !fir.ref<!fir.array<2xf32>> + ! CHECK-NEXT: %[[valuesDeclare:.*]] = fir.declare %[[valuesArg]](%[[shape]]) dummy_scope %[[DSCOPE]] arg {{[0-9]+}} {uniq_name = "_QFetime_testEvalues"} : (!fir.ref<!fir.array<2xf32>>, !fir.shape<1>, !fir.dscope) -> !fir.ref<!fir.array<2xf32>> ! CHECK-NEXT: %[[valuesBox:.*]] = fir.embox %[[valuesDeclare]](%[[shape]]) : (!fir.ref<!fir.array<2xf32>>, !fir.shape<1>) -> !fir.box<!fir.array<2xf32>> ! CHECK-NEXT: %[[timeTmpBox:.*]] = fir.embox %[[timeTmpAddr]] : (!fir.ref<f32>) -> !fir.box<f32> ! CHECK: %[[values:.*]] = fir.convert %[[valuesBox]] : (!fir.box<!fir.array<2xf32>>) -> !fir.box<none> diff --git a/flang/test/Lower/Intrinsics/etime.f90 b/flang/test/Lower/Intrinsics/etime.f90 index fe5d16b..a8fabb1 100644 --- a/flang/test/Lower/Intrinsics/etime.f90 +++ b/flang/test/Lower/Intrinsics/etime.f90 @@ -10,9 +10,9 @@ subroutine etime_test(values, time) ! CHECK-NEXT: %[[c9:.*]] = arith.constant 9 : i32 ! CHECK-NEXT: %[[c2:.*]] = arith.constant 2 : index ! CHECK-NEXT: %[[DSCOPE:.*]] = fir.dummy_scope : !fir.dscope - ! CHECK-NEXT: %[[timeDeclare:.*]] = fir.declare %[[timeArg]] dummy_scope %[[DSCOPE]] {uniq_name = "_QFetime_testEtime"} : (!fir.ref<f32>, !fir.dscope) -> !fir.ref<f32> + ! CHECK-NEXT: %[[timeDeclare:.*]] = fir.declare %[[timeArg]] dummy_scope %[[DSCOPE]] arg {{[0-9]+}} {uniq_name = "_QFetime_testEtime"} : (!fir.ref<f32>, !fir.dscope) -> !fir.ref<f32> ! CHECK-NEXT: %[[shape:.*]] = fir.shape %[[c2]] : (index) -> !fir.shape<1> - ! CHECK-NEXT: %[[valuesDeclare:.*]] = fir.declare %[[valuesArg]](%[[shape]]) dummy_scope %[[DSCOPE]] {uniq_name = "_QFetime_testEvalues"} : (!fir.ref<!fir.array<2xf32>>, !fir.shape<1>, !fir.dscope) -> !fir.ref<!fir.array<2xf32>> + ! CHECK-NEXT: %[[valuesDeclare:.*]] = fir.declare %[[valuesArg]](%[[shape]]) dummy_scope %[[DSCOPE]] arg {{[0-9]+}} {uniq_name = "_QFetime_testEvalues"} : (!fir.ref<!fir.array<2xf32>>, !fir.shape<1>, !fir.dscope) -> !fir.ref<!fir.array<2xf32>> ! CHECK-NEXT: %[[valuesBox:.*]] = fir.embox %[[valuesDeclare]](%[[shape]]) : (!fir.ref<!fir.array<2xf32>>, !fir.shape<1>) -> !fir.box<!fir.array<2xf32>> ! CHECK-NEXT: %[[timeBox:.*]] = fir.embox %[[timeDeclare]] : (!fir.ref<f32>) -> !fir.box<f32> ! CHECK: %[[values:.*]] = fir.convert %[[valuesBox]] : (!fir.box<!fir.array<2xf32>>) -> !fir.box<none> diff --git a/flang/test/Lower/Intrinsics/execute_command_line-optional.f90 b/flang/test/Lower/Intrinsics/execute_command_line-optional.f90 index 00a3258..a4137df 100644 --- a/flang/test/Lower/Intrinsics/execute_command_line-optional.f90 +++ b/flang/test/Lower/Intrinsics/execute_command_line-optional.f90 @@ -12,18 +12,18 @@ subroutine all_args_optional(command, isWait, exitVal, cmdVal, msg) LOGICAL, OPTIONAL :: isWait ! Note: command is not optional in execute_command_line and must be present call execute_command_line(command, isWait, exitVal, cmdVal, msg) -! CHECK-NEXT: %[[c14:.*]] = arith.constant 14 : i32 -! CHECK-NEXT: %true = arith.constant true -! CHECK-NEXT: %[[c0:.*]] = arith.constant 0 : i64 +! CHECK-NEXT: %[[c14:.*]] = arith.constant 14 : i32 +! CHECK-NEXT: %true = arith.constant true +! CHECK-NEXT: %[[c0:.*]] = arith.constant 0 : i64 ! CHECK-NEXT: %[[DSCOPE:.*]] = fir.dummy_scope : !fir.dscope -! CHECK-NEXT: %[[cmdstatDeclare:.*]] = fir.declare %[[cmdstatArg]] dummy_scope %[[DSCOPE]] {fortran_attrs = #fir.var_attrs<optional>, uniq_name = "_QFall_args_optionalEcmdval"} : (!fir.ref<i32>, !fir.dscope) -> !fir.ref<i32> +! CHECK-NEXT: %[[cmdstatDeclare:.*]] = fir.declare %[[cmdstatArg]] dummy_scope %[[DSCOPE]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<optional>, uniq_name = "_QFall_args_optionalEcmdval"} : (!fir.ref<i32>, !fir.dscope) -> !fir.ref<i32> ! CHECK-NEXT: %[[commandUnbox:.*]]:2 = fir.unboxchar %[[commandArg]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index) -! CHECK-NEXT: %[[commandDeclare:.*]] = fir.declare %[[commandUnbox]]#0 typeparams %[[commandUnbox]]#1 dummy_scope %[[DSCOPE]] {fortran_attrs = #fir.var_attrs<optional>, uniq_name = "_QFall_args_optionalEcommand"} : (!fir.ref<!fir.char<1,?>>, index, !fir.dscope) -> !fir.ref<!fir.char<1,?>> +! CHECK-NEXT: %[[commandDeclare:.*]] = fir.declare %[[commandUnbox]]#0 typeparams %[[commandUnbox]]#1 dummy_scope %[[DSCOPE]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<optional>, uniq_name = "_QFall_args_optionalEcommand"} : (!fir.ref<!fir.char<1,?>>, index, !fir.dscope) -> !fir.ref<!fir.char<1,?>> ! CHECK-NEXT: %[[commandBoxTemp:.*]] = fir.emboxchar %[[commandDeclare]], %[[commandUnbox]]#1 : (!fir.ref<!fir.char<1,?>>, index) -> !fir.boxchar<1> -! CHECK-NEXT: %[[exitstatDeclare:.*]] = fir.declare %[[exitstatArg]] dummy_scope %[[DSCOPE]] {fortran_attrs = #fir.var_attrs<optional>, uniq_name = "_QFall_args_optionalEexitval"} : (!fir.ref<i32>, !fir.dscope) -> !fir.ref<i32> -! CHECK-NEXT: %[[waitDeclare:.*]] = fir.declare %[[waitArg]] dummy_scope %[[DSCOPE]] {fortran_attrs = #fir.var_attrs<optional>, uniq_name = "_QFall_args_optionalEiswait"} : (!fir.ref<!fir.logical<4>>, !fir.dscope) -> !fir.ref<!fir.logical<4>> +! CHECK-NEXT: %[[exitstatDeclare:.*]] = fir.declare %[[exitstatArg]] dummy_scope %[[DSCOPE]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<optional>, uniq_name = "_QFall_args_optionalEexitval"} : (!fir.ref<i32>, !fir.dscope) -> !fir.ref<i32> +! CHECK-NEXT: %[[waitDeclare:.*]] = fir.declare %[[waitArg]] dummy_scope %[[DSCOPE]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<optional>, uniq_name = "_QFall_args_optionalEiswait"} : (!fir.ref<!fir.logical<4>>, !fir.dscope) -> !fir.ref<!fir.logical<4>> ! CHECK-NEXT: %[[cmdmsgUnbox:.*]]:2 = fir.unboxchar %[[cmdmsgArg]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index) -! CHECK-NEXT: %[[cmdmsgDeclare:.*]] = fir.declare %[[cmdmsgUnbox]]#0 typeparams %[[cmdmsgUnbox]]#1 dummy_scope %[[DSCOPE]] {fortran_attrs = #fir.var_attrs<optional>, uniq_name = "_QFall_args_optionalEmsg"} : (!fir.ref<!fir.char<1,?>>, index, !fir.dscope) -> !fir.ref<!fir.char<1,?>> +! CHECK-NEXT: %[[cmdmsgDeclare:.*]] = fir.declare %[[cmdmsgUnbox]]#0 typeparams %[[cmdmsgUnbox]]#1 dummy_scope %[[DSCOPE]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<optional>, uniq_name = "_QFall_args_optionalEmsg"} : (!fir.ref<!fir.char<1,?>>, index, !fir.dscope) -> !fir.ref<!fir.char<1,?>> ! CHECK-NEXT: %[[cmdmsgBoxTemp:.*]] = fir.emboxchar %[[cmdmsgDeclare]], %[[cmdmsgUnbox]]#1 : (!fir.ref<!fir.char<1,?>>, index) -> !fir.boxchar<1> ! CHECK-NEXT: %[[exitstatIsPresent:.*]] = fir.is_present %[[exitstatDeclare]] : (!fir.ref<i32>) -> i1 ! CHECK-NEXT: %[[cmdstatIsPresent:.*]] = fir.is_present %[[cmdstatDeclare]] : (!fir.ref<i32>) -> i1 @@ -35,7 +35,7 @@ subroutine all_args_optional(command, isWait, exitVal, cmdVal, msg) ! CHECK-NEXT: %[[cmdstatArgBox:.*]] = fir.embox %[[cmdstatDeclare]] : (!fir.ref<i32>) -> !fir.box<i32> ! CHECK-NEXT: %[[cmdstatBox:.*]] = arith.select %[[cmdstatIsPresent]], %[[cmdstatArgBox]], %[[absentBoxi32]] : !fir.box<i32> ! CHECK-NEXT: %[[cmdmsgArgBox:.*]] = fir.embox %[[cmdmsgDeclare]] typeparams %[[cmdmsgUnbox]]#1 : (!fir.ref<!fir.char<1,?>>, index) -> !fir.box<!fir.char<1,?>> -! CHECK-NEXT: %[[absentBox:.*]] = fir.absent !fir.box<!fir.char<1,?>> +! CHECK-NEXT: %[[absentBox:.*]] = fir.absent !fir.box<!fir.char<1,?>> ! CHECK-NEXT: %[[cmdmsgBox:.*]] = arith.select %[[cmdmsgIsPresent]], %[[cmdmsgArgBox]], %[[absentBox]] : !fir.box<!fir.char<1,?>> ! CHECK-NEXT: %[[waitCast:.*]] = fir.convert %[[waitDeclare]] : (!fir.ref<!fir.logical<4>>) -> i64 ! CHECK-NEXT: %[[waitPresent:.*]] = arith.cmpi ne, %[[waitCast]], %[[c0]] : i64 diff --git a/flang/test/Lower/Intrinsics/execute_command_line.f90 b/flang/test/Lower/Intrinsics/execute_command_line.f90 index 77f1750..e29c096 100644 --- a/flang/test/Lower/Intrinsics/execute_command_line.f90 +++ b/flang/test/Lower/Intrinsics/execute_command_line.f90 @@ -11,20 +11,20 @@ CHARACTER(30) :: command, msg INTEGER :: exitVal, cmdVal LOGICAL :: isWait call execute_command_line(command, isWait, exitVal, cmdVal, msg) -! CHECK-NEXT: %[[c13:.*]] = arith.constant 13 : i32 -! CHECK-NEXT: %true = arith.constant true -! CHECK-NEXT: %[[c0:.*]] = arith.constant 0 : i64 +! CHECK-NEXT: %[[c13:.*]] = arith.constant 13 : i32 +! CHECK-NEXT: %true = arith.constant true +! CHECK-NEXT: %[[c0:.*]] = arith.constant 0 : i64 ! CHECK-NEXT: %[[c30:.*]] = arith.constant 30 : index ! CHECK-NEXT: %[[DSCOPE:.*]] = fir.dummy_scope : !fir.dscope -! CHECK-NEXT: %[[cmdstatsDeclare:.*]] = fir.declare %[[cmdstatArg]] dummy_scope %[[DSCOPE]] {uniq_name = "_QFall_argsEcmdval"} : (!fir.ref<i32>, !fir.dscope) -> !fir.ref<i32> +! CHECK-NEXT: %[[cmdstatsDeclare:.*]] = fir.declare %[[cmdstatArg]] dummy_scope %[[DSCOPE]] arg {{[0-9]+}} {uniq_name = "_QFall_argsEcmdval"} : (!fir.ref<i32>, !fir.dscope) -> !fir.ref<i32> ! CHECK-NEXT: %[[commandUnbox:.*]]:2 = fir.unboxchar %[[commandArg]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index) ! CHECK-NEXT: %[[commandCast:.*]] = fir.convert %[[commandUnbox]]#0 : (!fir.ref<!fir.char<1,?>>) -> !fir.ref<!fir.char<1,30>> -! CHECK-NEXT: %[[commandDeclare:.*]] = fir.declare %[[commandCast]] typeparams %[[c30]] dummy_scope %[[DSCOPE]] {uniq_name = "_QFall_argsEcommand"} : (!fir.ref<!fir.char<1,30>>, index, !fir.dscope) -> !fir.ref<!fir.char<1,30>> -! CHECK-NEXT: %[[exitstatDeclare:.*]] = fir.declare %[[exitstatArg]] dummy_scope %[[DSCOPE]] {uniq_name = "_QFall_argsEexitval"} : (!fir.ref<i32>, !fir.dscope) -> !fir.ref<i32> -! CHECK-NEXT: %[[waitDeclare:.*]] = fir.declare %[[waitArg]] dummy_scope %[[DSCOPE]] {uniq_name = "_QFall_argsEiswait"} : (!fir.ref<!fir.logical<4>>, !fir.dscope) -> !fir.ref<!fir.logical<4>> +! CHECK-NEXT: %[[commandDeclare:.*]] = fir.declare %[[commandCast]] typeparams %[[c30]] dummy_scope %[[DSCOPE]] arg {{[0-9]+}} {uniq_name = "_QFall_argsEcommand"} : (!fir.ref<!fir.char<1,30>>, index, !fir.dscope) -> !fir.ref<!fir.char<1,30>> +! CHECK-NEXT: %[[exitstatDeclare:.*]] = fir.declare %[[exitstatArg]] dummy_scope %[[DSCOPE]] arg {{[0-9]+}} {uniq_name = "_QFall_argsEexitval"} : (!fir.ref<i32>, !fir.dscope) -> !fir.ref<i32> +! CHECK-NEXT: %[[waitDeclare:.*]] = fir.declare %[[waitArg]] dummy_scope %[[DSCOPE]] arg {{[0-9]+}} {uniq_name = "_QFall_argsEiswait"} : (!fir.ref<!fir.logical<4>>, !fir.dscope) -> !fir.ref<!fir.logical<4>> ! CHECK-NEXT: %[[cmdmsgUnbox:.*]]:2 = fir.unboxchar %[[cmdmsgArg]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index) ! CHECK-NEXT: %[[cmdmsgCast:.*]] = fir.convert %[[cmdmsgUnbox]]#0 : (!fir.ref<!fir.char<1,?>>) -> !fir.ref<!fir.char<1,30>> -! CHECK-NEXT: %[[cmdmsgDeclare:.*]] = fir.declare %[[cmdmsgCast]] typeparams %[[c30]] dummy_scope %[[DSCOPE]] {uniq_name = "_QFall_argsEmsg"} : (!fir.ref<!fir.char<1,30>>, index, !fir.dscope) -> !fir.ref<!fir.char<1,30>> +! CHECK-NEXT: %[[cmdmsgDeclare:.*]] = fir.declare %[[cmdmsgCast]] typeparams %[[c30]] dummy_scope %[[DSCOPE]] arg {{[0-9]+}} {uniq_name = "_QFall_argsEmsg"} : (!fir.ref<!fir.char<1,30>>, index, !fir.dscope) -> !fir.ref<!fir.char<1,30>> ! CHECK-NEXT: %[[commandBox:.*]] = fir.embox %[[commandDeclare]] : (!fir.ref<!fir.char<1,30>>) -> !fir.box<!fir.char<1,30>> ! CHECK-NEXT: %[[exitstatBox:.*]] = fir.embox %[[exitstatDeclare]] : (!fir.ref<i32>) -> !fir.box<i32> ! CHECK-NEXT: %[[cmdstatBox:.*]] = fir.embox %[[cmdstatsDeclare]] : (!fir.ref<i32>) -> !fir.box<i32> @@ -51,16 +51,16 @@ end subroutine all_args subroutine only_command_default_wait_true(command) CHARACTER(30) :: command call execute_command_line(command) -! CHECK-NEXT: %[[c52:.*]] = arith.constant 53 : i32 -! CHECK-NEXT: %true = arith.constant true +! CHECK-NEXT: %[[c52:.*]] = arith.constant 53 : i32 +! CHECK-NEXT: %true = arith.constant true ! CHECK-NEXT: %[[c30:.*]] = arith.constant 30 : index ! CHECK-NEXT: %[[DSCOPE:.*]] = fir.dummy_scope : !fir.dscope ! CHECK-NEXT: %[[commandUnbox:.*]]:2 = fir.unboxchar %[[cmdArg]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index) ! CHECK-NEXT: %[[commandCast:.*]] = fir.convert %[[commandUnbox]]#0 : (!fir.ref<!fir.char<1,?>>) -> !fir.ref<!fir.char<1,30>> -! CHECK-NEXT: %[[commandDeclare:.*]] = fir.declare %[[commandCast]] typeparams %[[c30]] dummy_scope %[[DSCOPE]] {uniq_name = "_QFonly_command_default_wait_trueEcommand"} : (!fir.ref<!fir.char<1,30>>, index, !fir.dscope) -> !fir.ref<!fir.char<1,30>> +! CHECK-NEXT: %[[commandDeclare:.*]] = fir.declare %[[commandCast]] typeparams %[[c30]] dummy_scope %[[DSCOPE]] arg {{[0-9]+}} {uniq_name = "_QFonly_command_default_wait_trueEcommand"} : (!fir.ref<!fir.char<1,30>>, index, !fir.dscope) -> !fir.ref<!fir.char<1,30>> ! CHECK-NEXT: %[[commandBox:.*]] = fir.embox %[[commandDeclare]] : (!fir.ref<!fir.char<1,30>>) -> !fir.box<!fir.char<1,30>> ! CHECK-NEXT: %[[absent:.*]] = fir.absent !fir.box<none> -! CHECK: %[[command:.*]] = fir.convert %[[commandBox]] : (!fir.box<!fir.char<1,30>>) -> !fir.box<none> +! CHECK: %[[command:.*]] = fir.convert %[[commandBox]] : (!fir.box<!fir.char<1,30>>) -> !fir.box<none> ! CHECK: fir.call @_FortranAExecuteCommandLine(%[[command]], %true, %[[absent]], %[[absent]], %[[absent]], %[[VAL_7:.*]], %[[c52]]) fastmath<contract> : (!fir.box<none>, i1, !fir.box<none>, !fir.box<none>, !fir.box<none>, !fir.ref<i8>, i32) -> () ! CHECK-NEXT: return end subroutine only_command_default_wait_true diff --git a/flang/test/Lower/Intrinsics/exit.f90 b/flang/test/Lower/Intrinsics/exit.f90 index d80efc5..49b4134 100644 --- a/flang/test/Lower/Intrinsics/exit.f90 +++ b/flang/test/Lower/Intrinsics/exit.f90 @@ -10,7 +10,7 @@ subroutine exit_test1 ! CHECK-32: fir.call @_FortranAExit(%[[status]]) {{.*}}: (i32) -> () ! CHECK-64: fir.call @_FortranAExit(%[[statusConvert]]) {{.*}}: (i32) -> () end subroutine exit_test1 - + ! CHECK-LABEL: func @_QPexit_test2( ! CHECK-SAME: %[[statusArg:.*]]: !fir.ref<i[[DEFAULT_INTEGER_SIZE]]>{{.*}}) { subroutine exit_test2(status) diff --git a/flang/test/Lower/Intrinsics/extends_type_of.f90 b/flang/test/Lower/Intrinsics/extends_type_of.f90 index f99a63e..d69e35f 100644 --- a/flang/test/Lower/Intrinsics/extends_type_of.f90 +++ b/flang/test/Lower/Intrinsics/extends_type_of.f90 @@ -9,7 +9,7 @@ module extends_type_of_mod type, extends(p1) :: p2 integer :: b end type - + type k1(a) integer, kind :: a end type diff --git a/flang/test/Lower/Intrinsics/fast-real-mod.f90 b/flang/test/Lower/Intrinsics/fast-real-mod.f90 index f80f720..6ecbb9b 100644 --- a/flang/test/Lower/Intrinsics/fast-real-mod.f90 +++ b/flang/test/Lower/Intrinsics/fast-real-mod.f90 @@ -1,24 +1,38 @@ -! RUN: %flang_fc1 -ffast-math -emit-mlir -o - %s | FileCheck %s --check-prefixes=CHECK%if target=x86_64{{.*}} %{,CHECK-KIND10%}%if flang-supports-f128-math %{,CHECK-KIND16%} +! RUN: %flang_fc1 -ffast-real-mod -emit-mlir -o - %s | FileCheck %s --check-prefixes=CHECK-FRM%if target=x86_64{{.*}} %{,CHECK-FRM-KIND10%}%if flang-supports-f128-math %{,CHECK-FRM-KIND16%} +! RUN: %flang_fc1 -ffast-real-mod -fno-fast-real-mod -emit-mlir -o - %s | FileCheck %s --check-prefixes=CHECK-NFRM%if target=x86_64{{.*}} %{,CHECK-NFRM-KIND10%}%if flang-supports-f128-math %{,CHECK-NFRM-KIND16%} +! RUN: %flang_fc1 -fno-fast-real-mod -ffast-real-mod -emit-mlir -o - %s | FileCheck %s --check-prefixes=CHECK-FRM%if target=x86_64{{.*}} %{,CHECK-FRM-KIND10%}%if flang-supports-f128-math %{,CHECK-FRM-KIND16%} +! RUN: %flang_fc1 -ffast-math -emit-mlir -o - %s | FileCheck %s --check-prefixes=CHECK-FM%if target=x86_64{{.*}} %{,CHECK-FM-KIND10%}%if flang-supports-f128-math %{,CHECK-FM-KIND16%} ! RUN: %flang_fc1 -ffast-math -fno-fast-real-mod -emit-mlir -o - %s | FileCheck %s --check-prefixes=CHECK-NFRM%if target=x86_64{{.*}} %{,CHECK-NFRM-KIND10%}%if flang-supports-f128-math %{,CHECK-NFRM-KIND16%} -! TODO: check line that fir.fast_real_mod is not there -! CHECK-NFRM: module attributes {{{.*}}fir.no_fast_real_mod = true{{.*}}} +! CHECK-FM: module attributes {{{.*}}fir.fast_real_mod = true{{.*}}} +! CHECK-FRM: module attributes {{{.*}}fir.fast_real_mod = true{{.*}}} ! CHECK-LABEL: @_QPmod_real4 subroutine mod_real4(r, a, p) implicit none real(kind=4) :: r, a, p -! CHECK: %[[A:.*]] = fir.declare{{.*}}a" -! CHECK: %[[P:.*]] = fir.declare{{.*}}p" -! CHECK: %[[R:.*]] = fir.declare{{.*}}r" -! CHECK: %[[A_LOAD:.*]] = fir.load %[[A]] -! CHECK: %[[P_LOAD:.*]] = fir.load %[[P]] -! CHECK: %[[DIV:.*]] = arith.divf %[[A_LOAD]], %[[P_LOAD]] fastmath<fast> : f32 -! CHECK: %[[CV1:.*]] = fir.convert %[[DIV]] : (f32) -> si32 -! CHECK: %[[CV2:.*]] = fir.convert %[[CV1]] : (si32) -> f32 -! CHECK: %[[MUL:.*]] = arith.mulf %[[CV2]], %[[P_LOAD]] fastmath<fast> : f32 -! CHECK: %[[SUB:.*]] = arith.subf %[[A_LOAD]], %[[MUL]] fastmath<fast> : f32 -! CHECK: fir.store %[[SUB]] to %[[R]] : !fir.ref<f32> +! CHECK-FRM: %[[A:.*]] = fir.declare{{.*}}a" +! CHECK-FRM: %[[P:.*]] = fir.declare{{.*}}p" +! CHECK-FRM: %[[R:.*]] = fir.declare{{.*}}r" +! CHECK-FRM: %[[A_LOAD:.*]] = fir.load %[[A]] +! CHECK-FRM: %[[P_LOAD:.*]] = fir.load %[[P]] +! CHECK-FRM: %[[DIV:.*]] = arith.divf %[[A_LOAD]], %[[P_LOAD]] fastmath<contract> : f32 +! CHECK-FRM: %[[CV1:.*]] = fir.convert %[[DIV]] : (f32) -> si32 +! CHECK-FRM: %[[CV2:.*]] = fir.convert %[[CV1]] : (si32) -> f32 +! CHECK-FRM: %[[MUL:.*]] = arith.mulf %[[CV2]], %[[P_LOAD]] fastmath<contract> : f32 +! CHECK-FRM: %[[SUB:.*]] = arith.subf %[[A_LOAD]], %[[MUL]] fastmath<contract> : f32 +! CHECK-FRM: fir.store %[[SUB]] to %[[R]] : !fir.ref<f32> +! CHECK-FM: %[[A:.*]] = fir.declare{{.*}}a" +! CHECK-FM: %[[P:.*]] = fir.declare{{.*}}p" +! CHECK-FM: %[[R:.*]] = fir.declare{{.*}}r" +! CHECK-FM: %[[A_LOAD:.*]] = fir.load %[[A]] +! CHECK-FM: %[[P_LOAD:.*]] = fir.load %[[P]] +! CHECK-FM: %[[DIV:.*]] = arith.divf %[[A_LOAD]], %[[P_LOAD]] fastmath<fast> : f32 +! CHECK-FM: %[[CV1:.*]] = fir.convert %[[DIV]] : (f32) -> si32 +! CHECK-FM: %[[CV2:.*]] = fir.convert %[[CV1]] : (si32) -> f32 +! CHECK-FM: %[[MUL:.*]] = arith.mulf %[[CV2]], %[[P_LOAD]] fastmath<fast> : f32 +! CHECK-FM: %[[SUB:.*]] = arith.subf %[[A_LOAD]], %[[MUL]] fastmath<fast> : f32 +! CHECK-FM: fir.store %[[SUB]] to %[[R]] : !fir.ref<f32> ! CHECK-NFRM: fir.call @_FortranAModReal4(%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}) {{.*}}: (f32, f32, !fir.ref<i8>, i32) -> f32 r = mod(a, p) end subroutine mod_real4 @@ -27,17 +41,28 @@ end subroutine mod_real4 subroutine mod_real8(r, a, p) implicit none real(kind=8) :: r, a, p -! CHECK: %[[A:.*]] = fir.declare{{.*}}a" -! CHECK: %[[P:.*]] = fir.declare{{.*}}p" -! CHECK: %[[R:.*]] = fir.declare{{.*}}r" -! CHECK: %[[A_LOAD:.*]] = fir.load %[[A]] -! CHECK: %[[P_LOAD:.*]] = fir.load %[[P]] -! CHECK: %[[DIV:.*]] = arith.divf %[[A_LOAD]], %[[P_LOAD]] fastmath<fast> : f64 -! CHECK: %[[CV1:.*]] = fir.convert %[[DIV]] : (f64) -> si64 -! CHECK: %[[CV2:.*]] = fir.convert %[[CV1]] : (si64) -> f64 -! CHECK: %[[MUL:.*]] = arith.mulf %[[CV2]], %[[P_LOAD]] fastmath<fast> : f64 -! CHECK: %[[SUB:.*]] = arith.subf %[[A_LOAD]], %[[MUL]] fastmath<fast> : f64 -! CHECK: fir.store %[[SUB]] to %[[R]] : !fir.ref<f64> +! CHECK-FRM: %[[A:.*]] = fir.declare{{.*}}a" +! CHECK-FRM: %[[P:.*]] = fir.declare{{.*}}p" +! CHECK-FRM: %[[R:.*]] = fir.declare{{.*}}r" +! CHECK-FRM: %[[A_LOAD:.*]] = fir.load %[[A]] +! CHECK-FRM: %[[P_LOAD:.*]] = fir.load %[[P]] +! CHECK-FRM: %[[DIV:.*]] = arith.divf %[[A_LOAD]], %[[P_LOAD]] fastmath<contract> : f64 +! CHECK-FRM: %[[CV1:.*]] = fir.convert %[[DIV]] : (f64) -> si64 +! CHECK-FRM: %[[CV2:.*]] = fir.convert %[[CV1]] : (si64) -> f64 +! CHECK-FRM: %[[MUL:.*]] = arith.mulf %[[CV2]], %[[P_LOAD]] fastmath<contract> : f64 +! CHECK-FRM: %[[SUB:.*]] = arith.subf %[[A_LOAD]], %[[MUL]] fastmath<contract> : f64 +! CHECK-FRM: fir.store %[[SUB]] to %[[R]] : !fir.ref<f64> +! CHECK-FM: %[[A:.*]] = fir.declare{{.*}}a" +! CHECK-FM: %[[P:.*]] = fir.declare{{.*}}p" +! CHECK-FM: %[[R:.*]] = fir.declare{{.*}}r" +! CHECK-FM: %[[A_LOAD:.*]] = fir.load %[[A]] +! CHECK-FM: %[[P_LOAD:.*]] = fir.load %[[P]] +! CHECK-FM: %[[DIV:.*]] = arith.divf %[[A_LOAD]], %[[P_LOAD]] fastmath<fast> : f64 +! CHECK-FM: %[[CV1:.*]] = fir.convert %[[DIV]] : (f64) -> si64 +! CHECK-FM: %[[CV2:.*]] = fir.convert %[[CV1]] : (si64) -> f64 +! CHECK-FM: %[[MUL:.*]] = arith.mulf %[[CV2]], %[[P_LOAD]] fastmath<fast> : f64 +! CHECK-FM: %[[SUB:.*]] = arith.subf %[[A_LOAD]], %[[MUL]] fastmath<fast> : f64 +! CHECK-FM: fir.store %[[SUB]] to %[[R]] : !fir.ref<f64> ! CHECK-NFRM: fir.call @_FortranAModReal8(%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}) {{.*}}: (f64, f64, !fir.ref<i8>, i32) -> f64 r = mod(a, p) end subroutine mod_real8 @@ -47,17 +72,28 @@ subroutine mod_real10(r, a, p) implicit none integer, parameter :: kind10 = merge(10, 4, selected_real_kind(p=18).eq.10) real(kind=kind10) :: r, a, p -! CHECK-KIND10: %[[A:.*]] = fir.declare{{.*}}a" -! CHECK-KIND10: %[[P:.*]] = fir.declare{{.*}}p" -! CHECK-KIND10: %[[R:.*]] = fir.declare{{.*}}r" -! CHECK-KIND10: %[[A_LOAD:.*]] = fir.load %[[A]] -! CHECK-KIND10: %[[P_LOAD:.*]] = fir.load %[[P]] -! CHECK-KIND10: %[[DIV:.*]] = arith.divf %[[A_LOAD]], %[[P_LOAD]] fastmath<fast> : f80 -! CHECK-KIND10: %[[CV1:.*]] = fir.convert %[[DIV]] : (f80) -> si80 -! CHECK-KIND10: %[[CV2:.*]] = fir.convert %[[CV1]] : (si80) -> f80 -! CHECK-KIND10: %[[MUL:.*]] = arith.mulf %[[CV2]], %[[P_LOAD]] fastmath<fast> : f80 -! CHECK-KIND10: %[[SUB:.*]] = arith.subf %[[A_LOAD]], %[[MUL]] fastmath<fast> : f80 -! CHECK-KIND10: fir.store %[[SUB]] to %[[R]] : !fir.ref<f80> +! CHECK-FRM-KIND10: %[[A:.*]] = fir.declare{{.*}}a" +! CHECK-FRM-KIND10: %[[P:.*]] = fir.declare{{.*}}p" +! CHECK-FRM-KIND10: %[[R:.*]] = fir.declare{{.*}}r" +! CHECK-FRM-KIND10: %[[A_LOAD:.*]] = fir.load %[[A]] +! CHECK-FRM-KIND10: %[[P_LOAD:.*]] = fir.load %[[P]] +! CHECK-FRM-KIND10: %[[DIV:.*]] = arith.divf %[[A_LOAD]], %[[P_LOAD]] fastmath<contract> : f80 +! CHECK-FRM-KIND10: %[[CV1:.*]] = fir.convert %[[DIV]] : (f80) -> si80 +! CHECK-FRM-KIND10: %[[CV2:.*]] = fir.convert %[[CV1]] : (si80) -> f80 +! CHECK-FRM-KIND10: %[[MUL:.*]] = arith.mulf %[[CV2]], %[[P_LOAD]] fastmath<contract> : f80 +! CHECK-FRM-KIND10: %[[SUB:.*]] = arith.subf %[[A_LOAD]], %[[MUL]] fastmath<contract> : f80 +! CHECK-FRM-KIND10: fir.store %[[SUB]] to %[[R]] : !fir.ref<f80> +! CHECK-FM-KIND10: %[[A:.*]] = fir.declare{{.*}}a" +! CHECK-FM-KIND10: %[[P:.*]] = fir.declare{{.*}}p" +! CHECK-FM-KIND10: %[[R:.*]] = fir.declare{{.*}}r" +! CHECK-FM-KIND10: %[[A_LOAD:.*]] = fir.load %[[A]] +! CHECK-FM-KIND10: %[[P_LOAD:.*]] = fir.load %[[P]] +! CHECK-FM-KIND10: %[[DIV:.*]] = arith.divf %[[A_LOAD]], %[[P_LOAD]] fastmath<fast> : f80 +! CHECK-FM-KIND10: %[[CV1:.*]] = fir.convert %[[DIV]] : (f80) -> si80 +! CHECK-FM-KIND10: %[[CV2:.*]] = fir.convert %[[CV1]] : (si80) -> f80 +! CHECK-FM-KIND10: %[[MUL:.*]] = arith.mulf %[[CV2]], %[[P_LOAD]] fastmath<fast> : f80 +! CHECK-FM-KIND10: %[[SUB:.*]] = arith.subf %[[A_LOAD]], %[[MUL]] fastmath<fast> : f80 +! CHECK-FM-KIND10: fir.store %[[SUB]] to %[[R]] : !fir.ref<f80> ! CHECK-NFRM-KIND10: fir.call @_FortranAModReal10(%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}) {{.*}}: (f80, f80, !fir.ref<i8>, i32) -> f80 r = mod(a, p) end subroutine mod_real10 @@ -67,17 +103,28 @@ subroutine mod_real16(r, a, p) implicit none integer, parameter :: kind16 = merge(16, 4, selected_real_kind(p=33).eq.16) real(kind=kind16) :: r, a, p -! CHECK-KIND16: %[[A:.*]] = fir.declare{{.*}}a" -! CHECK-KIND16: %[[P:.*]] = fir.declare{{.*}}p" -! CHECK-KIND16: %[[R:.*]] = fir.declare{{.*}}r" -! CHECK-KIND16: %[[A_LOAD:.*]] = fir.load %[[A]] -! CHECK-KIND16: %[[P_LOAD:.*]] = fir.load %[[P]] -! CHECK-KIND16: %[[DIV:.*]] = arith.divf %[[A_LOAD]], %[[P_LOAD]] fastmath<fast> : f128 -! CHECK-KIND16: %[[CV1:.*]] = fir.convert %[[DIV]] : (f128) -> si128 -! CHECK-KIND16: %[[CV2:.*]] = fir.convert %[[CV1]] : (si128) -> f128 -! CHECK-KIND16: %[[MUL:.*]] = arith.mulf %[[CV2]], %[[P_LOAD]] fastmath<fast> : f128 -! CHECK-KIND16: %[[SUB:.*]] = arith.subf %[[A_LOAD]], %[[MUL]] fastmath<fast> : f128 -! CHECK-KIND16: fir.store %[[SUB]] to %[[R]] : !fir.ref<f128> +! CHECK-FRM-KIND16: %[[A:.*]] = fir.declare{{.*}}a" +! CHECK-FRM-KIND16: %[[P:.*]] = fir.declare{{.*}}p" +! CHECK-FRM-KIND16: %[[R:.*]] = fir.declare{{.*}}r" +! CHECK-FRM-KIND16: %[[A_LOAD:.*]] = fir.load %[[A]] +! CHECK-FRM-KIND16: %[[P_LOAD:.*]] = fir.load %[[P]] +! CHECK-FRM-KIND16: %[[DIV:.*]] = arith.divf %[[A_LOAD]], %[[P_LOAD]] fastmath<contract> : f128 +! CHECK-FRM-KIND16: %[[CV1:.*]] = fir.convert %[[DIV]] : (f128) -> si128 +! CHECK-FRM-KIND16: %[[CV2:.*]] = fir.convert %[[CV1]] : (si128) -> f128 +! CHECK-FRM-KIND16: %[[MUL:.*]] = arith.mulf %[[CV2]], %[[P_LOAD]] fastmath<contract> : f128 +! CHECK-FRM-KIND16: %[[SUB:.*]] = arith.subf %[[A_LOAD]], %[[MUL]] fastmath<contract> : f128 +! CHECK-FRM-KIND16: fir.store %[[SUB]] to %[[R]] : !fir.ref<f128> +! CHECK-FM-KIND16: %[[A:.*]] = fir.declare{{.*}}a" +! CHECK-FM-KIND16: %[[P:.*]] = fir.declare{{.*}}p" +! CHECK-FM-KIND16: %[[R:.*]] = fir.declare{{.*}}r" +! CHECK-FM-KIND16: %[[A_LOAD:.*]] = fir.load %[[A]] +! CHECK-FM-KIND16: %[[P_LOAD:.*]] = fir.load %[[P]] +! CHECK-FM-KIND16: %[[DIV:.*]] = arith.divf %[[A_LOAD]], %[[P_LOAD]] fastmath<fast> : f128 +! CHECK-FM-KIND16: %[[CV1:.*]] = fir.convert %[[DIV]] : (f128) -> si128 +! CHECK-FM-KIND16: %[[CV2:.*]] = fir.convert %[[CV1]] : (si128) -> f128 +! CHECK-FM-KIND16: %[[MUL:.*]] = arith.mulf %[[CV2]], %[[P_LOAD]] fastmath<fast> : f128 +! CHECK-FM-KIND16: %[[SUB:.*]] = arith.subf %[[A_LOAD]], %[[MUL]] fastmath<fast> : f128 +! CHECK-FM-KIND16: fir.store %[[SUB]] to %[[R]] : !fir.ref<f128> ! CHECK-NFRM-KIND16: fir.call @_FortranAModReal16(%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}) {{.*}}: (f128, f128, !fir.ref<i8>, i32) -> f128 r = mod(a, p) end subroutine mod_real16 diff --git a/flang/test/Lower/Intrinsics/floor.f90 b/flang/test/Lower/Intrinsics/floor.f90 index 63d6d2f..b478b67 100644 --- a/flang/test/Lower/Intrinsics/floor.f90 +++ b/flang/test/Lower/Intrinsics/floor.f90 @@ -16,4 +16,3 @@ subroutine floor_test1(i, a) ! CHECK: %[[f:.*]] = math.floor %{{.*}} : f32 ! CHECK: fir.convert %[[f]] : (f32) -> i64 end subroutine - diff --git a/flang/test/Lower/Intrinsics/flush.f90 b/flang/test/Lower/Intrinsics/flush.f90 new file mode 100644 index 0000000..2b02179 --- /dev/null +++ b/flang/test/Lower/Intrinsics/flush.f90 @@ -0,0 +1,41 @@ +! RUN: bbc -emit-hlfir %s -o - | FileCheck %s +! RUN: %flang_fc1 -emit-hlfir %s -o - | FileCheck %s +! +! Test lowering of intrinsic subroutine FLUSH with and without optional UNIT argument. +! +! CHECK-LABEL: func.func @_QPflush_all() +! CHECK: %[[UNIT:.*]] = arith.constant -1 : i32 +! CHECK: fir.call @_FortranAFlush(%[[UNIT]]) fastmath<contract> : (i32) -> () +! CHECK: return +subroutine flush_all() + call flush() ! flush all units +end subroutine + +! CHECK-LABEL: func.func @_QPflush_unit() +! CHECK: %[[ALLOCA:.*]] = fir.alloca i32 +! CHECK: %[[UNITC:.*]] = arith.constant 10 : i32 +! CHECK: fir.store %[[UNITC]] to %[[ALLOCA]] : !fir.ref<i32> +! CHECK: %[[LOADED:.*]] = fir.load %[[ALLOCA]] : !fir.ref<i32> +! CHECK: fir.call @_FortranAFlush(%[[LOADED]]) fastmath<contract> : (i32) -> () +! CHECK: return +subroutine flush_unit() + call flush(10) ! flush specific unit +end subroutine + +! CHECK-LABEL: func.func @_QPflush_optional( +! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<i32> {fir.bindc_name = "unit", fir.optional}) { +! CHECK: %[[DECL:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{.*}} {fortran_attrs = #fir.var_attrs<optional>, uniq_name = "_QFflush_optionalEunit"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[IS_PRESENT:.*]] = fir.is_present %[[DECL]]#0 : (!fir.ref<i32>) -> i1 +! CHECK: %[[UNIT:.*]] = fir.if %[[IS_PRESENT]] -> (i32) { +! CHECK: %[[LOADED:.*]] = fir.load %[[DECL]]#0 : !fir.ref<i32> +! CHECK: fir.result %[[LOADED]] : i32 +! CHECK: } else { +! CHECK: %[[DEFAULT:.*]] = arith.constant -1 : i32 +! CHECK: fir.result %[[DEFAULT]] : i32 +! CHECK: } +! CHECK: fir.call @_FortranAFlush(%[[UNIT]]) fastmath<contract> : (i32) -> () +! CHECK: return +subroutine flush_optional(unit) + integer, optional :: unit + call flush(unit) ! flush with dynamically optional argument +end subroutine diff --git a/flang/test/Lower/Intrinsics/get_command_argument-optional.f90 b/flang/test/Lower/Intrinsics/get_command_argument-optional.f90 index c1b081b..545ca66 100644 --- a/flang/test/Lower/Intrinsics/get_command_argument-optional.f90 +++ b/flang/test/Lower/Intrinsics/get_command_argument-optional.f90 @@ -7,11 +7,11 @@ ! CHECK-SAME: %[[lengthParam:.*]]: !fir.ref<i32> {fir.bindc_name = "length", fir.optional}, ! CHECK-SAME: %[[statusParam:.*]]: !fir.ref<i32> {fir.bindc_name = "status", fir.optional}, ! CHECK-SAME: %[[errmsgParam:.*]]: !fir.boxchar<1> {fir.bindc_name = "errmsg", fir.optional}) { -subroutine test(number, value, length, status, errmsg) +subroutine test(number, value, length, status, errmsg) integer, optional :: number, status, length character(*), optional :: value, errmsg ! Note: number cannot be absent - call get_command_argument(number, value, length, status, errmsg) + call get_command_argument(number, value, length, status, errmsg) ! CHECK: %[[errmsgUnboxed:.*]]:2 = fir.unboxchar %[[errmsgParam]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index) ! CHECK: %[[valueUnboxed:.*]]:2 = fir.unboxchar %[[valueParam]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index) ! CHECK: %[[number:.*]] = fir.load %[[numberParam]] : !fir.ref<i32> diff --git a/flang/test/Lower/Intrinsics/getcwd-function.f90 b/flang/test/Lower/Intrinsics/getcwd-function.f90 index 50b6472..4442941 100644 --- a/flang/test/Lower/Intrinsics/getcwd-function.f90 +++ b/flang/test/Lower/Intrinsics/getcwd-function.f90 @@ -11,7 +11,7 @@ integer function test(cwd) ! CHECK-NEXT: %[[DSCOPE:.*]] = fir.dummy_scope : !fir.dscope ! CHECK-NEXT: %[[cwdUnbox:.*]]:2 = fir.unboxchar %[[cwdArg]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index) ! CHECK-NEXT: %[[cwdCast:.*]] = fir.convert %[[cwdUnbox]]#0 : (!fir.ref<!fir.char<1,?>>) -> !fir.ref<!fir.char<1,255>> - ! CHECK-NEXT: %[[cwdDeclare:.*]] = fir.declare %[[cwdCast]] typeparams %[[c255]] dummy_scope %[[DSCOPE]] {uniq_name = "_QFtestEcwd"} : (!fir.ref<!fir.char<1,255>>, index, !fir.dscope) -> !fir.ref<!fir.char<1,255>> + ! CHECK-NEXT: %[[cwdDeclare:.*]] = fir.declare %[[cwdCast]] typeparams %[[c255]] dummy_scope %[[DSCOPE]] arg {{[0-9]+}} {uniq_name = "_QFtestEcwd"} : (!fir.ref<!fir.char<1,255>>, index, !fir.dscope) -> !fir.ref<!fir.char<1,255>> ! CHECK-NEXT: %[[test:.*]] = fir.alloca i32 {bindc_name = "test", uniq_name = "_QFtestEtest"} ! CHECK-NEXT: %[[testAddr:.*]] = fir.declare %[[test]] {uniq_name = "_QFtestEtest"} : (!fir.ref<i32>) -> !fir.ref<i32> ! CHECK-NEXT: %[[cwdBox:.*]] = fir.embox %[[cwdDeclare]] : (!fir.ref<!fir.char<1,255>>) -> !fir.box<!fir.char<1,255>> diff --git a/flang/test/Lower/Intrinsics/getcwd-optional.f90 b/flang/test/Lower/Intrinsics/getcwd-optional.f90 index 3e2a221..ee1612f 100644 --- a/flang/test/Lower/Intrinsics/getcwd-optional.f90 +++ b/flang/test/Lower/Intrinsics/getcwd-optional.f90 @@ -15,8 +15,8 @@ subroutine test(cwd, status) ! CHECK-NEXT: %[[DSCOPE:.*]] = fir.dummy_scope : !fir.dscope ! CHECK-NEXT: %[[cwdUnbox:.*]]:2 = fir.unboxchar %[[cwdArg]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index) ! CHECK-NEXT: %[[cwdCast:.*]] = fir.convert %[[cwdUnbox]]#0 : (!fir.ref<!fir.char<1,?>>) -> !fir.ref<!fir.char<1,255>> - ! CHECK-NEXT: %[[cwdDeclare:.*]] = fir.declare %[[cwdCast]] typeparams %[[c255]] dummy_scope %[[DSCOPE]] {uniq_name = "_QFtestEcwd"} : (!fir.ref<!fir.char<1,255>>, index, !fir.dscope) -> !fir.ref<!fir.char<1,255>> - ! CHECK-NEXT: %[[statusAddr:.*]] = fir.declare %[[statusArg]] dummy_scope %[[DSCOPE]] {fortran_attrs = #fir.var_attrs<optional>, uniq_name = "_QFtestEstatus"} : (!fir.ref<i32>, !fir.dscope) -> !fir.ref<i32> + ! CHECK-NEXT: %[[cwdDeclare:.*]] = fir.declare %[[cwdCast]] typeparams %[[c255]] dummy_scope %[[DSCOPE]] arg {{[0-9]+}} {uniq_name = "_QFtestEcwd"} : (!fir.ref<!fir.char<1,255>>, index, !fir.dscope) -> !fir.ref<!fir.char<1,255>> + ! CHECK-NEXT: %[[statusAddr:.*]] = fir.declare %[[statusArg]] dummy_scope %[[DSCOPE]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<optional>, uniq_name = "_QFtestEstatus"} : (!fir.ref<i32>, !fir.dscope) -> !fir.ref<i32> ! CHECK-NEXT: %[[cwdBox:.*]] = fir.embox %[[cwdDeclare]] : (!fir.ref<!fir.char<1,255>>) -> !fir.box<!fir.char<1,255>> ! CHECK: %[[cwd:.*]] = fir.convert %[[cwdBox]] : (!fir.box<!fir.char<1,255>>) -> !fir.box<none> ! CHECK: %[[statusValue:.*]] = fir.call @_FortranAGetCwd(%[[cwd]], %[[VAL_8:.*]], %[[c11]]) fastmath<contract> : (!fir.box<none>, !fir.ref<i8>, i32) -> i32 diff --git a/flang/test/Lower/Intrinsics/getcwd.f90 b/flang/test/Lower/Intrinsics/getcwd.f90 index fe20785..900075f 100644 --- a/flang/test/Lower/Intrinsics/getcwd.f90 +++ b/flang/test/Lower/Intrinsics/getcwd.f90 @@ -10,7 +10,7 @@ subroutine cwd_only(cwd) ! CHECK-NEXT: %[[DSCOPE:.*]] = fir.dummy_scope : !fir.dscope ! CHECK-NEXT: %[[cwdUnbox:.*]]:2 = fir.unboxchar %[[cwdArg]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index) ! CHECK-NEXT: %[[cwdCast:.*]] = fir.convert %[[cwdUnbox]]#0 : (!fir.ref<!fir.char<1,?>>) -> !fir.ref<!fir.char<1,255>> - ! CHECK-NEXT: %[[cwdDeclare:.*]] = fir.declare %[[cwdCast]] typeparams %[[c255]] dummy_scope %[[DSCOPE]] {uniq_name = "_QFcwd_onlyEcwd"} : (!fir.ref<!fir.char<1,255>>, index, !fir.dscope) -> !fir.ref<!fir.char<1,255>> + ! CHECK-NEXT: %[[cwdDeclare:.*]] = fir.declare %[[cwdCast]] typeparams %[[c255]] dummy_scope %[[DSCOPE]] arg {{[0-9]+}} {uniq_name = "_QFcwd_onlyEcwd"} : (!fir.ref<!fir.char<1,255>>, index, !fir.dscope) -> !fir.ref<!fir.char<1,255>> ! CHECK-NEXT: %[[cwdBox:.*]] = fir.embox %[[cwdDeclare]] : (!fir.ref<!fir.char<1,255>>) -> !fir.box<!fir.char<1,255>> ! CHECK: %[[cwd:.*]] = fir.convert %[[cwdBox]] : (!fir.box<!fir.char<1,255>>) -> !fir.box<none> ! CHECK: %[[statusValue:.*]] = fir.call @_FortranAGetCwd(%[[cwd]], %[[VAL_7:.*]], %[[c7]]) fastmath<contract> : (!fir.box<none>, !fir.ref<i8>, i32) -> i32 @@ -30,8 +30,8 @@ subroutine all_arguments(cwd, status) ! CHECK-NEXT: %[[DSCOPE:.*]] = fir.dummy_scope : !fir.dscope ! CHECK-NEXT: %[[cwdUnbox:.*]]:2 = fir.unboxchar %[[cwdArg]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index) ! CHECK-NEXT: %[[cwdCast:.*]] = fir.convert %[[cwdUnbox]]#0 : (!fir.ref<!fir.char<1,?>>) -> !fir.ref<!fir.char<1,255>> - ! CHECK-NEXT: %[[cwdDeclare:.*]] = fir.declare %[[cwdCast]] typeparams %[[c255]] dummy_scope %[[DSCOPE]] {uniq_name = "_QFall_argumentsEcwd"} : (!fir.ref<!fir.char<1,255>>, index, !fir.dscope) -> !fir.ref<!fir.char<1,255>> - ! CHECK-NEXT: %[[statusAddr:.*]] = fir.declare %[[statusArg]] dummy_scope %0 {uniq_name = "_QFall_argumentsEstatus"} : (!fir.ref<i32>, !fir.dscope) -> !fir.ref<i32> + ! CHECK-NEXT: %[[cwdDeclare:.*]] = fir.declare %[[cwdCast]] typeparams %[[c255]] dummy_scope %[[DSCOPE]] arg {{[0-9]+}} {uniq_name = "_QFall_argumentsEcwd"} : (!fir.ref<!fir.char<1,255>>, index, !fir.dscope) -> !fir.ref<!fir.char<1,255>> + ! CHECK-NEXT: %[[statusAddr:.*]] = fir.declare %[[statusArg]] dummy_scope %0 {{.*}} {uniq_name = "_QFall_argumentsEstatus"} : (!fir.ref<i32>, !fir.dscope) -> !fir.ref<i32> ! CHECK-NEXT: %[[cwdBox:.*]] = fir.embox %[[cwdDeclare]] : (!fir.ref<!fir.char<1,255>>) -> !fir.box<!fir.char<1,255>> ! CHECK: %[[cwd:.*]] = fir.convert %[[cwdBox]] : (!fir.box<!fir.char<1,255>>) -> !fir.box<none> ! CHECK: %[[statusValue:.*]] = fir.call @_FortranAGetCwd(%[[cwd]], %[[VAL_8:.*]], %[[c26]]) fastmath<contract> : (!fir.box<none>, !fir.ref<i8>, i32) -> i32 diff --git a/flang/test/Lower/Intrinsics/ichar.f90 b/flang/test/Lower/Intrinsics/ichar.f90 index 9928445..eb7e038 100644 --- a/flang/test/Lower/Intrinsics/ichar.f90 +++ b/flang/test/Lower/Intrinsics/ichar.f90 @@ -37,7 +37,7 @@ end subroutine subroutine no_extui(ch) integer, parameter :: kind = selected_char_kind('ISO_10646') character(*, kind), intent(in) :: ch(:) - integer :: i, j + integer :: i, j ! CHECK-NOT: arith.extui j = ichar(ch(i)(i:i)) end subroutine diff --git a/flang/test/Lower/Intrinsics/ieee_logb.f90 b/flang/test/Lower/Intrinsics/ieee_logb.f90 index 4d32d95..fd4144e 100644 --- a/flang/test/Lower/Intrinsics/ieee_logb.f90 +++ b/flang/test/Lower/Intrinsics/ieee_logb.f90 @@ -9,7 +9,7 @@ subroutine out(x) ! CHECK: %[[V_61:[0-9]+]] = fir.declare %[[V_60]] {uniq_name = "_QFoutEl"} : (!fir.ref<!fir.logical<4>>) -> !fir.ref<!fir.logical<4>> ! CHECK: %[[V_62:[0-9]+]] = fir.alloca f64 {bindc_name = "r", uniq_name = "_QFoutEr"} ! CHECK: %[[V_63:[0-9]+]] = fir.declare %[[V_62]] {uniq_name = "_QFoutEr"} : (!fir.ref<f64>) -> !fir.ref<f64> - ! CHECK: %[[V_64:[0-9]+]] = fir.declare %arg0 dummy_scope %{{[0-9]+}} {uniq_name = "_QFoutEx"} : (!fir.ref<f64>, !fir.dscope) -> !fir.ref<f64> + ! CHECK: %[[V_64:[0-9]+]] = fir.declare %arg0 dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFoutEx"} : (!fir.ref<f64>, !fir.dscope) -> !fir.ref<f64> real(k) :: x, r logical :: L diff --git a/flang/test/Lower/Intrinsics/ishftc.f90 b/flang/test/Lower/Intrinsics/ishftc.f90 index 70d7112..f13d9c0 100644 --- a/flang/test/Lower/Intrinsics/ishftc.f90 +++ b/flang/test/Lower/Intrinsics/ishftc.f90 @@ -40,7 +40,7 @@ function ishftc_test(i, j, k) ! CHECK: return %[[VAL_36]] : i32 ishftc_test = ishftc(i, j, k) end - + ! Test cases where the size argument presence can only be know at runtime module test_ishftc contains @@ -67,9 +67,9 @@ function ishftc_test(i, j, k) ! CHECK: %[[VAL_19:.*]] = arith.xori %[[VAL_9]], %[[VAL_18]] : i32 ! CHECK: %[[VAL_20:.*]] = arith.subi %[[VAL_19]], %[[VAL_18]] : i32 ! CHECK: %[[VAL_21:.*]] = arith.subi %[[VAL_11]], %[[VAL_20]] : i32 - ! ... as in non optional case + ! ... as in non optional case end subroutine - + ! CHECK-LABEL: func @_QMtest_ishftcPdyn_optional_array_scalar( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.box<!fir.array<?xi32>> {fir.bindc_name = "i"}, ! CHECK-SAME: %[[VAL_1:.*]]: !fir.box<!fir.array<?xi32>> {fir.bindc_name = "shift"}, @@ -90,11 +90,11 @@ function ishftc_test(i, j, k) ! CHECK: %[[VAL_26:.*]] = arith.constant 32 : i32 ! CHECK: fir.result %[[VAL_26]] : i32 ! CHECK: } - ! ... as in non optional case + ! ... as in non optional case ! CHECK: } print *, ishftc(i, shift, size) end subroutine - + ! CHECK-LABEL: func @_QMtest_ishftcPdyn_optional_array( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.box<!fir.array<?xi32>> {fir.bindc_name = "i"}, ! CHECK-SAME: %[[VAL_1:.*]]: !fir.box<!fir.array<?xi32>> {fir.bindc_name = "shift"}, @@ -117,22 +117,22 @@ function ishftc_test(i, j, k) ! CHECK: %[[VAL_32:.*]] = arith.constant 32 : i32 ! CHECK: fir.result %[[VAL_32]] : i32 ! CHECK: } - ! ... as in non optional case + ! ... as in non optional case ! CHECK: } print *, ishftc(i, shift, size) end subroutine end module - + use test_ishftc integer :: i(4) = [333, 334, 335, 336] integer :: shift(4) = [2, 1, -1, -2] integer :: size(4) = [2, 4, 8, 16] call dyn_optional_scalar(i(1), shift(1)) call dyn_optional_scalar(i(1), shift(1), size(1)) - + call dyn_optional_array_scalar(i, shift) call dyn_optional_array_scalar(i, shift, size(1)) - + call dyn_optional_array(i, shift) call dyn_optional_array(i, shift, size) end diff --git a/flang/test/Lower/Intrinsics/max.f90 b/flang/test/Lower/Intrinsics/max.f90 index 1909a4e..c3d2457 100644 --- a/flang/test/Lower/Intrinsics/max.f90 +++ b/flang/test/Lower/Intrinsics/max.f90 @@ -31,8 +31,8 @@ module max_test ! CHECK: fir.result %[[VAL_36]] : !fir.array<?xi32> ! CHECK: } print *, max(a, b, c) - end subroutine - + end subroutine + ! CHECK-LABEL: func @_QMmax_testPdynamic_optional_array_expr_scalar_optional( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.box<!fir.array<?xi32>> {fir.bindc_name = "a"}, ! CHECK-SAME: %[[VAL_1:.*]]: !fir.box<!fir.array<?xi32>> {fir.bindc_name = "b"}, @@ -60,8 +60,8 @@ module max_test ! CHECK: %[[VAL_30:.*]] = fir.array_update %[[VAL_21]], %[[VAL_26]], %[[VAL_20]] : (!fir.array<?xi32>, i32, index) -> !fir.array<?xi32> ! CHECK: fir.result %[[VAL_30]] : !fir.array<?xi32> ! CHECK: } - end subroutine - + end subroutine + ! CHECK-LABEL: func @_QMmax_testPdynamic_optional_scalar( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<i32> {fir.bindc_name = "a"}, ! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref<i32> {fir.bindc_name = "b"}, @@ -84,8 +84,8 @@ module max_test ! CHECK: fir.result %[[VAL_12]] : i32 ! CHECK: } ! CHECK: fir.call @_FortranAioOutputInteger32(%{{.*}}, %[[VAL_13]]) {{.*}}: (!fir.ref<i8>, i32) -> i1 - end subroutine - + end subroutine + ! CHECK-LABEL: func @_QMmax_testPdynamic_optional_weird( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<i32> {fir.bindc_name = "a"}, ! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref<i32> {fir.bindc_name = "b"}, @@ -123,9 +123,9 @@ module max_test ! CHECK: fir.result %[[VAL_23]] : i32 ! CHECK: } ! CHECK: fir.call @_FortranAioOutputInteger32(%{{.*}}, %[[VAL_24]]) {{.*}}: (!fir.ref<i8>, i32) -> i1 - end subroutine + end subroutine end module - + use :: max_test integer :: a(4) = [1,12,23, 34] integer :: b(4) = [31,22,13, 4] diff --git a/flang/test/Lower/Intrinsics/maxloc.f90 b/flang/test/Lower/Intrinsics/maxloc.f90 index 87f17881..13dbe98 100644 --- a/flang/test/Lower/Intrinsics/maxloc.f90 +++ b/flang/test/Lower/Intrinsics/maxloc.f90 @@ -18,7 +18,7 @@ subroutine maxloc_test(arr,res) ! CHECK-DAG: %[[a14:.*]] = fir.box_addr %[[a12]] : (!fir.box<!fir.heap<!fir.array<?xi32>>>) -> !fir.heap<!fir.array<?xi32>> ! CHECK-DAG: fir.freemem %[[a14]] end subroutine - + ! CHECK-LABEL: func @_QPmaxloc_test2( ! CHECK-SAME: %[[arg0:.*]]: !fir.box<!fir.array<?xi32>>{{.*}}, %[[arg1:.*]]: !fir.box<!fir.array<?xi32>>{{.*}}, %[[arg2:.*]]: !fir.ref<i32>{{.*}}) { subroutine maxloc_test2(arr,res,d) @@ -39,7 +39,7 @@ subroutine maxloc_test(arr,res) ! CHECK: %[[a13:.*]] = fir.box_addr %[[a12]] : (!fir.box<!fir.heap<i32>>) -> !fir.heap<i32> ! CHECK: fir.freemem %[[a13]] end subroutine - + ! CHECK-LABEL: func @_QPtest_maxloc_optional_scalar_mask( ! CHECK-SAME: %[[VAL_0:[^:]+]]: !fir.ref<!fir.logical<4>> ! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref<!fir.logical<4>> @@ -65,7 +65,7 @@ subroutine maxloc_test(arr,res) ! CHECK: %[[VAL_30:.*]] = fir.convert %[[VAL_14]] : (!fir.logical<4>) -> i1 ! CHECK: fir.call @_FortranAMaxlocInteger4(%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %[[VAL_29]], %[[VAL_30]]) {{.*}}: (!fir.ref<!fir.box<none>>, !fir.box<none>, i32, !fir.ref<i8>, i32, !fir.box<none>, i1) -> () end subroutine - + ! CHECK-LABEL: func @_QPtest_maxloc_optional_array_mask( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.box<!fir.array<?x!fir.logical<4>>> ! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref<!fir.logical<4>> diff --git a/flang/test/Lower/Intrinsics/merge.f90 b/flang/test/Lower/Intrinsics/merge.f90 index 2e17efc..52417f8 100644 --- a/flang/test/Lower/Intrinsics/merge.f90 +++ b/flang/test/Lower/Intrinsics/merge.f90 @@ -9,7 +9,7 @@ logical :: mask merge_test = merge(o1, o2, mask) ! CHECK: %[[a0:.*]]:2 = fir.unboxchar %[[arg2]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index) ! CHECK: %[[a0_cast:.*]] = fir.convert %[[a0]]#0 : (!fir.ref<!fir.char<1,?>>) -> !fir.ref<!fir.char<1>> -! CHECK: %[[a1:.*]]:2 = fir.unboxchar %[[arg3]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index) +! CHECK: %[[a1:.*]]:2 = fir.unboxchar %[[arg3]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index) ! CHECK: %[[a1_cast:.*]] = fir.convert %[[a1]]#0 : (!fir.ref<!fir.char<1,?>>) -> !fir.ref<!fir.char<1>> ! CHECK: %[[a2:.*]] = fir.load %[[arg4]] : !fir.ref<!fir.logical<4>> ! CHECK: %[[a3:.*]] = fir.convert %[[a2]] : (!fir.logical<4>) -> i1 diff --git a/flang/test/Lower/Intrinsics/minloc.f90 b/flang/test/Lower/Intrinsics/minloc.f90 index caab36d..fa3bc9b 100644 --- a/flang/test/Lower/Intrinsics/minloc.f90 +++ b/flang/test/Lower/Intrinsics/minloc.f90 @@ -18,7 +18,7 @@ subroutine minloc_test(arr,res) ! CHECK-DAG: %[[a14:.*]] = fir.box_addr %[[a12]] : (!fir.box<!fir.heap<!fir.array<?xi32>>>) -> !fir.heap<!fir.array<?xi32>> ! CHECK-DAG: fir.freemem %[[a14]] end subroutine - + ! CHECK-LABEL: func @_QPminloc_test2( ! CHECK-SAME: %[[arg0:.*]]: !fir.box<!fir.array<?xi32>>{{.*}}, %[[arg1:.*]]: !fir.box<!fir.array<?xi32>>{{.*}}, %[[arg2:.*]]: !fir.ref<i32> subroutine minloc_test2(arr,res,d) @@ -39,7 +39,7 @@ subroutine minloc_test(arr,res) ! CHECK: %[[a13:.*]] = fir.box_addr %[[a12]] : (!fir.box<!fir.heap<i32>>) -> !fir.heap<i32> ! CHECK: fir.freemem %[[a13]] end subroutine - + ! CHECK-LABEL: func @_QPtest_minloc_optional_scalar_mask( ! CHECK-SAME: %[[VAL_0:[^:]+]]: !fir.ref<!fir.logical<4>> ! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref<!fir.logical<4>> @@ -65,7 +65,7 @@ subroutine minloc_test(arr,res) ! CHECK: %[[VAL_30:.*]] = fir.convert %[[VAL_14]] : (!fir.logical<4>) -> i1 ! CHECK: fir.call @_FortranAMinlocInteger4(%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %[[VAL_29]], %[[VAL_30]]) {{.*}}: (!fir.ref<!fir.box<none>>, !fir.box<none>, i32, !fir.ref<i8>, i32, !fir.box<none>, i1) -> () end subroutine - + ! CHECK-LABEL: func @_QPtest_minloc_optional_array_mask( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.box<!fir.array<?x!fir.logical<4>>> ! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref<!fir.logical<4>> diff --git a/flang/test/Lower/Intrinsics/modulo.f90 b/flang/test/Lower/Intrinsics/modulo.f90 index 37c4cd1a..f31a809 100644 --- a/flang/test/Lower/Intrinsics/modulo.f90 +++ b/flang/test/Lower/Intrinsics/modulo.f90 @@ -1,5 +1,5 @@ ! RUN: bbc -emit-fir -hlfir=false %s -o - | FileCheck %s -check-prefixes=HONORINF,ALL -! RUN: flang -fc1 -menable-no-infs -emit-fir -flang-deprecated-no-hlfir %s -o - | FileCheck %s -check-prefixes=CHECK,ALL,%if flang-supports-f128-math %{F128%} %else %{F64%} +! RUN: %flang_fc1 -menable-no-infs -emit-fir -flang-deprecated-no-hlfir %s -o - | FileCheck %s -check-prefixes=CHECK,ALL,%if flang-supports-f128-math %{F128%} %else %{F64%} ! ALL-LABEL: func @_QPmodulo_testr( ! ALL-SAME: %[[arg0:.*]]: !fir.ref<f64>{{.*}}, %[[arg1:.*]]: !fir.ref<f64>{{.*}}, %[[arg2:.*]]: !fir.ref<f64>{{.*}}) { @@ -20,7 +20,7 @@ subroutine modulo_testr(r, a, p) ! ALL: fir.store %[[res]] to %[[arg0]] : !fir.ref<f64> r = modulo(a, p) end subroutine - + ! ALL-LABEL: func @_QPmodulo_testi( ! ALL-SAME: %[[arg0:.*]]: !fir.ref<i64>{{.*}}, %[[arg1:.*]]: !fir.ref<i64>{{.*}}, %[[arg2:.*]]: !fir.ref<i64>{{.*}}) { subroutine modulo_testi(r, a, p) diff --git a/flang/test/Lower/Intrinsics/nearest.f90 b/flang/test/Lower/Intrinsics/nearest.f90 index 6dbdc8b..95e3ea5 100644 --- a/flang/test/Lower/Intrinsics/nearest.f90 +++ b/flang/test/Lower/Intrinsics/nearest.f90 @@ -4,8 +4,8 @@ ! CHECK: %[[V_0:[0-9]+]] = fir.dummy_scope : !fir.dscope ! CHECK: %[[V_1:[0-9]+]] = fir.alloca f16 {bindc_name = "res", uniq_name = "_QFnearest_test1Eres"} ! CHECK: %[[V_2:[0-9]+]] = fir.declare %[[V_1]] {uniq_name = "_QFnearest_test1Eres"} : (!fir.ref<f16>) -> !fir.ref<f16> - ! CHECK: %[[V_3:[0-9]+]] = fir.declare %arg1 dummy_scope %[[V_0]] {uniq_name = "_QFnearest_test1Es"} : (!fir.ref<f16>, !fir.dscope) -> !fir.ref<f16> - ! CHECK: %[[V_4:[0-9]+]] = fir.declare %arg0 dummy_scope %[[V_0]] {uniq_name = "_QFnearest_test1Ex"} : (!fir.ref<f16>, !fir.dscope) -> !fir.ref<f16> + ! CHECK: %[[V_3:[0-9]+]] = fir.declare %arg1 dummy_scope %[[V_0]] arg {{[0-9]+}} {uniq_name = "_QFnearest_test1Es"} : (!fir.ref<f16>, !fir.dscope) -> !fir.ref<f16> + ! CHECK: %[[V_4:[0-9]+]] = fir.declare %arg0 dummy_scope %[[V_0]] arg {{[0-9]+}} {uniq_name = "_QFnearest_test1Ex"} : (!fir.ref<f16>, !fir.dscope) -> !fir.ref<f16> ! CHECK: %[[V_5:[0-9]+]] = fir.load %[[V_4]] : !fir.ref<f16> ! CHECK: %[[V_6:[0-9]+]] = fir.load %[[V_3]] : !fir.ref<f16> ! CHECK: %[[V_7:[0-9]+]] = "llvm.intr.is.fpclass"(%[[V_5]]) <{bit = 3 : i32}> : (f16) -> i1 @@ -63,8 +63,8 @@ end ! CHECK: %[[V_0:[0-9]+]] = fir.dummy_scope : !fir.dscope ! CHECK: %[[V_1:[0-9]+]] = fir.alloca bf16 {bindc_name = "res", uniq_name = "_QFnearest_test2Eres"} ! CHECK: %[[V_2:[0-9]+]] = fir.declare %[[V_1]] {uniq_name = "_QFnearest_test2Eres"} : (!fir.ref<bf16>) -> !fir.ref<bf16> - ! CHECK: %[[V_3:[0-9]+]] = fir.declare %arg1 dummy_scope %[[V_0]] {uniq_name = "_QFnearest_test2Es"} : (!fir.ref<bf16>, !fir.dscope) -> !fir.ref<bf16> - ! CHECK: %[[V_4:[0-9]+]] = fir.declare %arg0 dummy_scope %[[V_0]] {uniq_name = "_QFnearest_test2Ex"} : (!fir.ref<bf16>, !fir.dscope) -> !fir.ref<bf16> + ! CHECK: %[[V_3:[0-9]+]] = fir.declare %arg1 dummy_scope %[[V_0]] arg {{[0-9]+}} {uniq_name = "_QFnearest_test2Es"} : (!fir.ref<bf16>, !fir.dscope) -> !fir.ref<bf16> + ! CHECK: %[[V_4:[0-9]+]] = fir.declare %arg0 dummy_scope %[[V_0]] arg {{[0-9]+}} {uniq_name = "_QFnearest_test2Ex"} : (!fir.ref<bf16>, !fir.dscope) -> !fir.ref<bf16> ! CHECK: %[[V_5:[0-9]+]] = fir.load %[[V_4]] : !fir.ref<bf16> ! CHECK: %[[V_6:[0-9]+]] = fir.load %[[V_3]] : !fir.ref<bf16> ! CHECK: %[[V_7:[0-9]+]] = "llvm.intr.is.fpclass"(%[[V_5]]) <{bit = 3 : i32}> : (bf16) -> i1 @@ -126,8 +126,8 @@ end ! CHECK: %[[V_0:[0-9]+]] = fir.dummy_scope : !fir.dscope ! CHECK: %[[V_1:[0-9]+]] = fir.alloca f32 {bindc_name = "res", uniq_name = "_QFnearest_test3Eres"} ! CHECK: %[[V_2:[0-9]+]] = fir.declare %[[V_1]] {uniq_name = "_QFnearest_test3Eres"} : (!fir.ref<f32>) -> !fir.ref<f32> - ! CHECK: %[[V_3:[0-9]+]] = fir.declare %arg1 dummy_scope %[[V_0]] {uniq_name = "_QFnearest_test3Es"} : (!fir.ref<f32>, !fir.dscope) -> !fir.ref<f32> - ! CHECK: %[[V_4:[0-9]+]] = fir.declare %arg0 dummy_scope %[[V_0]] {uniq_name = "_QFnearest_test3Ex"} : (!fir.ref<f32>, !fir.dscope) -> !fir.ref<f32> + ! CHECK: %[[V_3:[0-9]+]] = fir.declare %arg1 dummy_scope %[[V_0]] arg {{[0-9]+}} {uniq_name = "_QFnearest_test3Es"} : (!fir.ref<f32>, !fir.dscope) -> !fir.ref<f32> + ! CHECK: %[[V_4:[0-9]+]] = fir.declare %arg0 dummy_scope %[[V_0]] arg {{[0-9]+}} {uniq_name = "_QFnearest_test3Ex"} : (!fir.ref<f32>, !fir.dscope) -> !fir.ref<f32> ! CHECK: %[[V_5:[0-9]+]] = fir.load %[[V_4]] : !fir.ref<f32> ! CHECK: %[[V_6:[0-9]+]] = fir.load %[[V_3]] : !fir.ref<f32> ! CHECK: %[[V_7:[0-9]+]] = "llvm.intr.is.fpclass"(%[[V_5]]) <{bit = 3 : i32}> : (f32) -> i1 @@ -185,8 +185,8 @@ end ! CHECK: %[[V_0:[0-9]+]] = fir.dummy_scope : !fir.dscope ! CHECK: %[[V_1:[0-9]+]] = fir.alloca f64 {bindc_name = "res", uniq_name = "_QFnearest_test4Eres"} ! CHECK: %[[V_2:[0-9]+]] = fir.declare %[[V_1]] {uniq_name = "_QFnearest_test4Eres"} : (!fir.ref<f64>) -> !fir.ref<f64> - ! CHECK: %[[V_3:[0-9]+]] = fir.declare %arg1 dummy_scope %[[V_0]] {uniq_name = "_QFnearest_test4Es"} : (!fir.ref<f64>, !fir.dscope) -> !fir.ref<f64> - ! CHECK: %[[V_4:[0-9]+]] = fir.declare %arg0 dummy_scope %[[V_0]] {uniq_name = "_QFnearest_test4Ex"} : (!fir.ref<f64>, !fir.dscope) -> !fir.ref<f64> + ! CHECK: %[[V_3:[0-9]+]] = fir.declare %arg1 dummy_scope %[[V_0]] arg {{[0-9]+}} {uniq_name = "_QFnearest_test4Es"} : (!fir.ref<f64>, !fir.dscope) -> !fir.ref<f64> + ! CHECK: %[[V_4:[0-9]+]] = fir.declare %arg0 dummy_scope %[[V_0]] arg {{[0-9]+}} {uniq_name = "_QFnearest_test4Ex"} : (!fir.ref<f64>, !fir.dscope) -> !fir.ref<f64> ! CHECK: %[[V_5:[0-9]+]] = fir.load %[[V_4]] : !fir.ref<f64> ! CHECK: %[[V_6:[0-9]+]] = fir.load %[[V_3]] : !fir.ref<f64> ! CHECK: %[[V_7:[0-9]+]] = "llvm.intr.is.fpclass"(%[[V_5]]) <{bit = 3 : i32}> : (f64) -> i1 @@ -244,8 +244,8 @@ end ! CHECK-KIND10: %[[V_0:[0-9]+]] = fir.dummy_scope : !fir.dscope ! CHECK-KIND10: %[[V_1:[0-9]+]] = fir.alloca f80 {bindc_name = "res", uniq_name = "_QFnearest_test5Eres"} ! CHECK-KIND10: %[[V_2:[0-9]+]] = fir.declare %[[V_1]] {uniq_name = "_QFnearest_test5Eres"} : (!fir.ref<f80>) -> !fir.ref<f80> - ! CHECK-KIND10: %[[V_3:[0-9]+]] = fir.declare %arg1 dummy_scope %[[V_0]] {uniq_name = "_QFnearest_test5Es"} : (!fir.ref<f80>, !fir.dscope) -> !fir.ref<f80> - ! CHECK-KIND10: %[[V_4:[0-9]+]] = fir.declare %arg0 dummy_scope %[[V_0]] {uniq_name = "_QFnearest_test5Ex"} : (!fir.ref<f80>, !fir.dscope) -> !fir.ref<f80> + ! CHECK-KIND10: %[[V_3:[0-9]+]] = fir.declare %arg1 dummy_scope %[[V_0]] arg {{[0-9]+}} {uniq_name = "_QFnearest_test5Es"} : (!fir.ref<f80>, !fir.dscope) -> !fir.ref<f80> + ! CHECK-KIND10: %[[V_4:[0-9]+]] = fir.declare %arg0 dummy_scope %[[V_0]] arg {{[0-9]+}} {uniq_name = "_QFnearest_test5Ex"} : (!fir.ref<f80>, !fir.dscope) -> !fir.ref<f80> ! CHECK-KIND10: %[[V_5:[0-9]+]] = fir.load %[[V_4]] : !fir.ref<f80> ! CHECK-KIND10: %[[V_6:[0-9]+]] = fir.load %[[V_3]] : !fir.ref<f80> ! CHECK-KIND10: %[[V_7:[0-9]+]] = "llvm.intr.is.fpclass"(%[[V_5]]) <{bit = 3 : i32}> : (f80) -> i1 @@ -291,8 +291,8 @@ end ! CHECK-KIND16: %[[V_0:[0-9]+]] = fir.dummy_scope : !fir.dscope ! CHECK-KIND16: %[[V_1:[0-9]+]] = fir.alloca f128 {bindc_name = "res", uniq_name = "_QFnearest_test6Eres"} ! CHECK-KIND16: %[[V_2:[0-9]+]] = fir.declare %[[V_1]] {uniq_name = "_QFnearest_test6Eres"} : (!fir.ref<f128>) -> !fir.ref<f128> - ! CHECK-KIND16: %[[V_3:[0-9]+]] = fir.declare %arg1 dummy_scope %[[V_0]] {uniq_name = "_QFnearest_test6Es"} : (!fir.ref<f128>, !fir.dscope) -> !fir.ref<f128> - ! CHECK-KIND16: %[[V_4:[0-9]+]] = fir.declare %arg0 dummy_scope %[[V_0]] {uniq_name = "_QFnearest_test6Ex"} : (!fir.ref<f128>, !fir.dscope) -> !fir.ref<f128> + ! CHECK-KIND16: %[[V_3:[0-9]+]] = fir.declare %arg1 dummy_scope %[[V_0]] arg {{[0-9]+}} {uniq_name = "_QFnearest_test6Es"} : (!fir.ref<f128>, !fir.dscope) -> !fir.ref<f128> + ! CHECK-KIND16: %[[V_4:[0-9]+]] = fir.declare %arg0 dummy_scope %[[V_0]] arg {{[0-9]+}} {uniq_name = "_QFnearest_test6Ex"} : (!fir.ref<f128>, !fir.dscope) -> !fir.ref<f128> ! CHECK-KIND16: %[[V_5:[0-9]+]] = fir.load %[[V_4]] : !fir.ref<f128> ! CHECK-KIND16: %[[V_6:[0-9]+]] = fir.load %[[V_3]] : !fir.ref<f128> ! CHECK-KIND16: %[[V_7:[0-9]+]] = "llvm.intr.is.fpclass"(%[[V_5]]) <{bit = 3 : i32}> : (f128) -> i1 @@ -351,8 +351,8 @@ end ! CHECK-KIND16: %[[V_0:[0-9]+]] = fir.dummy_scope : !fir.dscope ! CHECK-KIND16: %[[V_1:[0-9]+]] = fir.alloca f128 {bindc_name = "res", uniq_name = "_QFnearest_test7Eres"} ! CHECK-KIND16: %[[V_2:[0-9]+]] = fir.declare %[[V_1]] {uniq_name = "_QFnearest_test7Eres"} : (!fir.ref<f128>) -> !fir.ref<f128> - ! CHECK-KIND16: %[[V_3:[0-9]+]] = fir.declare %arg1 dummy_scope %[[V_0]] {uniq_name = "_QFnearest_test7Es"} : (!fir.ref<f32>, !fir.dscope) -> !fir.ref<f32> - ! CHECK-KIND16: %[[V_4:[0-9]+]] = fir.declare %arg0 dummy_scope %[[V_0]] {uniq_name = "_QFnearest_test7Ex"} : (!fir.ref<f128>, !fir.dscope) -> !fir.ref<f128> + ! CHECK-KIND16: %[[V_3:[0-9]+]] = fir.declare %arg1 dummy_scope %[[V_0]] arg {{[0-9]+}} {uniq_name = "_QFnearest_test7Es"} : (!fir.ref<f32>, !fir.dscope) -> !fir.ref<f32> + ! CHECK-KIND16: %[[V_4:[0-9]+]] = fir.declare %arg0 dummy_scope %[[V_0]] arg {{[0-9]+}} {uniq_name = "_QFnearest_test7Ex"} : (!fir.ref<f128>, !fir.dscope) -> !fir.ref<f128> ! CHECK-KIND16: %[[V_5:[0-9]+]] = fir.load %[[V_4]] : !fir.ref<f128> ! CHECK-KIND16: %[[V_6:[0-9]+]] = fir.load %[[V_3]] : !fir.ref<f32> ! CHECK-KIND16: %[[V_7:[0-9]+]] = "llvm.intr.is.fpclass"(%[[V_5]]) <{bit = 3 : i32}> : (f128) -> i1 diff --git a/flang/test/Lower/Intrinsics/nint.f90 b/flang/test/Lower/Intrinsics/nint.f90 index 2f25eda..166fdac 100644 --- a/flang/test/Lower/Intrinsics/nint.f90 +++ b/flang/test/Lower/Intrinsics/nint.f90 @@ -14,4 +14,3 @@ subroutine nint_test1(i, a) i = nint(a, 8) ! CHECK: fir.call @llvm.lround.i64.f64 end subroutine -
\ No newline at end of file diff --git a/flang/test/Lower/Intrinsics/not.f90 b/flang/test/Lower/Intrinsics/not.f90 index 140800c..b772e8b 100644 --- a/flang/test/Lower/Intrinsics/not.f90 +++ b/flang/test/Lower/Intrinsics/not.f90 @@ -13,4 +13,3 @@ subroutine not_test ! CHECK: return destination = not(source) end subroutine -
\ No newline at end of file diff --git a/flang/test/Lower/Intrinsics/pack.f90 b/flang/test/Lower/Intrinsics/pack.f90 index a00c10d..f4eeef7 100644 --- a/flang/test/Lower/Intrinsics/pack.f90 +++ b/flang/test/Lower/Intrinsics/pack.f90 @@ -21,7 +21,7 @@ subroutine pack_test(a,m,v,r) ! CHECK: %[[a13:.*]] = fir.box_addr %[[a11]] : (!fir.box<!fir.heap<!fir.array<?xi32>>>) -> !fir.heap<!fir.array<?xi32>> ! CHECK: fir.freemem %[[a13]] end subroutine - + ! CHECK-LABEL: func @_QPtest_pack_optional( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>> subroutine test_pack_optional(vector, array, mask) diff --git a/flang/test/Lower/Intrinsics/perror.f90 b/flang/test/Lower/Intrinsics/perror.f90 index acecf0b..a595ab5 100644 --- a/flang/test/Lower/Intrinsics/perror.f90 +++ b/flang/test/Lower/Intrinsics/perror.f90 @@ -11,13 +11,13 @@ subroutine test_perror() ! CHECK: %[[C10:.*]] = arith.constant 10 : index ! CHECK: %[[VAL_2:.*]] = fir.alloca !fir.char<1,10> {bindc_name = "string", uniq_name = "_QFtest_perrorEstring"} ! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]] typeparams %[[C10]] {uniq_name = "_QFtest_perrorEstring"} : (!fir.ref<!fir.char<1,10>>, index) -> (!fir.ref<!fir.char<1,10>>, !fir.ref<!fir.char<1,10>>) - + call perror(string) ! CHECK: %[[VAL_4:.*]] = fir.embox %[[VAL_3]]#0 : (!fir.ref<!fir.char<1,10>>) -> !fir.box<!fir.char<1,10>> ! CHECK: %[[VAL_5:.*]] = fir.box_addr %[[VAL_4]] : (!fir.box<!fir.char<1,10>>) -> !fir.ref<!fir.char<1,10>> ! CHECK: %[[VAL_6:.*]] = fir.convert %[[VAL_5]] : (!fir.ref<!fir.char<1,10>>) -> !fir.ref<i8> - ! CHECK: fir.call @_FortranAPerror(%[[VAL_6]]) fastmath<contract> : (!fir.ref<i8>) -> () - + ! CHECK: fir.call @_FortranAPerror(%[[VAL_6]]) fastmath<contract> : (!fir.ref<i8>) -> () + call perror("prefix") ! CHECK: %[[VAL_7:.*]] = fir.address_of(@{{.*}}) : !fir.ref<!fir.char<1,6>> ! CHECK: %[[C6:.*]] = arith.constant 6 : index @@ -25,13 +25,13 @@ subroutine test_perror() ! CHECK: %[[VAL_9:.*]] = fir.embox %[[VAL_8]]#0 : (!fir.ref<!fir.char<1,6>>) -> !fir.box<!fir.char<1,6>> ! CHECK: %[[VAL_10:.*]] = fir.box_addr %[[VAL_9]] : (!fir.box<!fir.char<1,6>>) -> !fir.ref<!fir.char<1,6>> ! CHECK: %[[VAL_11:.*]] = fir.convert %[[VAL_10]] : (!fir.ref<!fir.char<1,6>>) -> !fir.ref<i8> - ! CHECK: fir.call @_FortranAPerror(%[[VAL_11]]) fastmath<contract> : (!fir.ref<i8>) -> () - + ! CHECK: fir.call @_FortranAPerror(%[[VAL_11]]) fastmath<contract> : (!fir.ref<i8>) -> () + call perror(one) ! CHECK: %[[VAL_12:.*]] = fir.embox %[[VAL_1]]#0 : (!fir.ref<!fir.char<1>>) -> !fir.box<!fir.char<1>> ! CHECK: %[[VAL_13:.*]] = fir.box_addr %[[VAL_12]] : (!fir.box<!fir.char<1>>) -> !fir.ref<!fir.char<1>> ! CHECK: %[[VAL_14:.*]] = fir.convert %[[VAL_13]] : (!fir.ref<!fir.char<1>>) -> !fir.ref<i8> - ! CHECK: fir.call @_FortranAPerror(%[[VAL_14]]) fastmath<contract> : (!fir.ref<i8>) -> () + ! CHECK: fir.call @_FortranAPerror(%[[VAL_14]]) fastmath<contract> : (!fir.ref<i8>) -> () end subroutine test_perror ! CHECK-LABEL: func @_QPtest_perror_unknown_length( @@ -43,7 +43,7 @@ subroutine test_perror_unknown_length(str) call perror(str) ! CHECK: %[[VAL_0:.*]] = fir.dummy_scope : !fir.dscope ! CHECK: %[[VAL_1:.*]]:2 = fir.unboxchar %[[ARG0]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index) - ! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]]#0 typeparams %[[VAL_1]]#1 dummy_scope %[[VAL_0]] {fortran_attrs = #fir.var_attrs<intent_in>, uniq_name = "_QFtest_perror_unknown_lengthEstr"} : (!fir.ref<!fir.char<1,?>>, index, !fir.dscope) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>) + ! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]]#0 typeparams %[[VAL_1]]#1 dummy_scope %[[VAL_0]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<intent_in>, uniq_name = "_QFtest_perror_unknown_lengthEstr"} : (!fir.ref<!fir.char<1,?>>, index, !fir.dscope) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>) ! CHECK: %[[VAL_3:.*]] = fir.embox %[[VAL_2]]#1 typeparams %[[VAL_1]]#1 : (!fir.ref<!fir.char<1,?>>, index) -> !fir.box<!fir.char<1,?>> ! CHECK: %[[VAL_4:.*]] = fir.box_addr %[[VAL_3]] : (!fir.box<!fir.char<1,?>>) -> !fir.ref<!fir.char<1,?>> ! CHECK: %[[VAL_5:.*]] = fir.convert %[[VAL_4]] : (!fir.ref<!fir.char<1,?>>) -> !fir.ref<i8> diff --git a/flang/test/Lower/Intrinsics/product.f90 b/flang/test/Lower/Intrinsics/product.f90 index df7c1e4..c64982e 100644 --- a/flang/test/Lower/Intrinsics/product.f90 +++ b/flang/test/Lower/Intrinsics/product.f90 @@ -111,7 +111,7 @@ real function product_test_optional_4(x, use_mask) real :: x(:) logical :: use_mask logical, allocatable :: mask(:) -if (use_mask) then +if (use_mask) then allocate(mask(size(x, 1))) call set_mask(mask) ! CHECK: fir.call @_QPset_mask diff --git a/flang/test/Lower/Intrinsics/putenv-sub.f90 b/flang/test/Lower/Intrinsics/putenv-sub.f90 index 285dbc6..f7c347f 100644 --- a/flang/test/Lower/Intrinsics/putenv-sub.f90 +++ b/flang/test/Lower/Intrinsics/putenv-sub.f90 @@ -6,7 +6,7 @@ subroutine str_only(str) CHARACTER(len=*) :: str !CHECK-DAG: %[[scope:.*]] = fir.dummy_scope : !fir.dscope !CHECK-DAG: %[[unbox_str:.*]]:2 = fir.unboxchar %[[dummyStr]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index) - !CHECK-DAG: %[[str_decl:.*]]:2 = hlfir.declare %[[unbox_str]]#0 typeparams %[[unbox_str]]#1 dummy_scope %[[scope]] {uniq_name = "_QFstr_onlyEstr"} : (!fir.ref<!fir.char<1,?>>, index, !fir.dscope) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>) + !CHECK-DAG: %[[str_decl:.*]]:2 = hlfir.declare %[[unbox_str]]#0 typeparams %[[unbox_str]]#1 dummy_scope %[[scope]] arg {{[0-9]+}} {uniq_name = "_QFstr_onlyEstr"} : (!fir.ref<!fir.char<1,?>>, index, !fir.dscope) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>) !CHECK-DAG: %[[src_str_addr:.*]] = fir.address_of(@_{{.*}}) : !fir.ref<!fir.char<1,{{.*}}>> !CHECK-DAG: %[[line_value:.*]] = arith.constant {{.*}} : i64 !CHECK-DAG: %[[str:.*]] = fir.convert %[[str_decl]]#1 : (!fir.ref<!fir.char<1,?>>) -> !fir.ref<i8> @@ -30,8 +30,8 @@ subroutine all_arguments(str, status) INTEGER :: status !CHECK-DAG: %[[scope:.*]] = fir.dummy_scope : !fir.dscope !CHECK-DAG: %[[unbox_str:.*]]:2 = fir.unboxchar %[[dummyStr]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index) - !CHECK-DAG: %[[str_decl:.*]]:2 = hlfir.declare %[[unbox_str]]#0 typeparams %[[unbox_str]]#1 dummy_scope %[[scope]] {uniq_name = "_QFall_argumentsEstr"} : (!fir.ref<!fir.char<1,?>>, index, !fir.dscope) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>) - !CHECK-DAG: %[[status_decl:.*]]:2 = hlfir.declare %[[dummyStat]] dummy_scope %[[scope]] {uniq_name = "_QFall_argumentsEstatus"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) + !CHECK-DAG: %[[str_decl:.*]]:2 = hlfir.declare %[[unbox_str]]#0 typeparams %[[unbox_str]]#1 dummy_scope %[[scope]] arg {{[0-9]+}} {uniq_name = "_QFall_argumentsEstr"} : (!fir.ref<!fir.char<1,?>>, index, !fir.dscope) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>) + !CHECK-DAG: %[[status_decl:.*]]:2 = hlfir.declare %[[dummyStat]] dummy_scope %[[scope]] arg {{[0-9]+}} {uniq_name = "_QFall_argumentsEstatus"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) !CHECK-DAG: %[[src_str_addr:.*]] = fir.address_of(@_{{.*}}) : !fir.ref<!fir.char<1,{{.*}}>> !CHECK-DAG: %[[line_value:.*]] = arith.constant {{.*}} : i64 !CHECK-DAG: %[[str:.*]] = fir.convert %[[str_decl]]#1 : (!fir.ref<!fir.char<1,?>>) -> !fir.ref<i8> diff --git a/flang/test/Lower/Intrinsics/rand.f90 b/flang/test/Lower/Intrinsics/rand.f90 new file mode 100644 index 0000000..1ff5bb6 --- /dev/null +++ b/flang/test/Lower/Intrinsics/rand.f90 @@ -0,0 +1,41 @@ +! RUN: bbc -emit-hlfir %s -o - | FileCheck --check-prefixes=CHECK %s +! RUN: %flang_fc1 -emit-hlfir %s -o - | FileCheck --check-prefixes=CHECK %s + +! CHECK-LABEL: func @_QPtest_srand( +subroutine test_srand() + integer :: seed = 0 + call srand(seed) + ! CHECK: %[[VAL_0:.*]] = fir.address_of(@_QFtest_srandEseed) : !fir.ref<i32> + ! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = "_QFtest_srandEseed"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) + ! CHECK: fir.call @_QPsrand(%[[VAL_1]]#0) fastmath<contract> : (!fir.ref<i32>) -> () + ! CHECK: return +end subroutine test_srand + +! CHECK-LABEL: func @_QPtest_irand( +subroutine test_irand() + integer :: seed = 0 + integer :: result + result = irand(seed) + ! CHECK: %[[VAL_0:.*]] = fir.alloca i32 {bindc_name = "result", uniq_name = "_QFtest_irandEresult"} + ! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = "_QFtest_irandEresult"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) + ! CHECK: %[[VAL_2:.*]] = fir.address_of(@_QFtest_irandEseed) : !fir.ref<i32> + ! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]] {uniq_name = "_QFtest_irandEseed"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) + ! CHECK: %[[VAL_4:.*]] = fir.call @_FortranAIrand(%[[VAL_3]]#0) fastmath<contract> : (!fir.ref<i32>) -> i32 + ! CHECK: hlfir.assign %[[VAL_4]] to %[[VAL_1]]#0 : i32, !fir.ref<i32> + ! CHECK: return +end subroutine test_irand + +! CHECK-LABEL: func @_QPtest_rand( +subroutine test_rand() + integer :: seed = 0 + real :: result + result = rand(seed) + ! CHECK: %[[VAL_0:.*]] = fir.alloca f32 {bindc_name = "result", uniq_name = "_QFtest_randEresult"} + ! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = "_QFtest_randEresult"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>) + ! CHECK: %[[VAL_2:.*]] = fir.address_of(@_QFtest_randEseed) : !fir.ref<i32> + ! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]] {uniq_name = "_QFtest_randEseed"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) + ! CHECK: %[[VAL_4:.*]] = fir.call @_FortranARand(%[[VAL_3]]#0, %[[SOURCE:.*]], %[[LINE:.*]]) fastmath<contract> : (!fir.ref<i32>, !fir.ref<i8>, i32) -> f32 + ! CHECK: hlfir.assign %[[VAL_4]] to %[[VAL_1]]#0 : f32, !fir.ref<f32> + ! CHECK: return +end subroutine test_rand + diff --git a/flang/test/Lower/Intrinsics/reduce.f90 b/flang/test/Lower/Intrinsics/reduce.f90 index 083dca5..27c4277 100644 --- a/flang/test/Lower/Intrinsics/reduce.f90 +++ b/flang/test/Lower/Intrinsics/reduce.f90 @@ -19,7 +19,7 @@ end type integer, parameter :: kind10 = merge(10, 4, selected_real_kind(p=18).eq.10) integer, parameter :: kind16 = merge(16, 4, selected_real_kind(p=33).eq.16) - + contains @@ -46,11 +46,11 @@ subroutine integer1(a, id, d1, d2) res = reduce(a, red_int1) res = reduce(a, red_int1, identity=id) - + res = reduce(a, red_int1, identity=id, ordered = .true.) res = reduce(a, red_int1, [.true., .true., .false.]) - + res = reduce(a, red_int1_value) fptr => red_int1 diff --git a/flang/test/Lower/Intrinsics/rename.f90 b/flang/test/Lower/Intrinsics/rename.f90 index 41d1203..6fdb514 100644 --- a/flang/test/Lower/Intrinsics/rename.f90 +++ b/flang/test/Lower/Intrinsics/rename.f90 @@ -9,9 +9,9 @@ subroutine test_rename(src, dst) call rename(src, dst) !CHECK: %[[dstUnbox:.*]]:2 = fir.unboxchar %[[dummyDst]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index) - !CHECK-NEXT: %[[dstDecl:.*]]:2 = hlfir.declare %[[dstUnbox]]#0 typeparams %[[dstUnbox]]#1 dummy_scope %0 {uniq_name = "_QFtest_renameEdst"} : (!fir.ref<!fir.char<1,?>>, index, !fir.dscope) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>) + !CHECK-NEXT: %[[dstDecl:.*]]:2 = hlfir.declare %[[dstUnbox]]#0 typeparams %[[dstUnbox]]#1 dummy_scope %0 {{.*}} {uniq_name = "_QFtest_renameEdst"} : (!fir.ref<!fir.char<1,?>>, index, !fir.dscope) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>) !CHECK-NEXT: %[[srcUnbox:.*]]:2 = fir.unboxchar %[[dummySrc]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index) - !CHECK-NEXT: %[[srcDecl:.*]]:2 = hlfir.declare %3#0 typeparams %[[srcUnbox]]#1 dummy_scope %0 {uniq_name = "_QFtest_renameEsrc"} : (!fir.ref<!fir.char<1,?>>, index, !fir.dscope) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>) + !CHECK-NEXT: %[[srcDecl:.*]]:2 = hlfir.declare %3#0 typeparams %[[srcUnbox]]#1 dummy_scope %0 {{.*}} {uniq_name = "_QFtest_renameEsrc"} : (!fir.ref<!fir.char<1,?>>, index, !fir.dscope) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>) !CHECK-NEXT: %[[srcBox:.*]] = fir.embox %[[srcDecl]]#1 typeparams %[[srcUnbox]]#1 : (!fir.ref<!fir.char<1,?>>, index) -> !fir.box<!fir.char<1,?>> !CHECK-NEXT: %[[dstBox:.*]] = fir.embox %[[dstDecl]]#1 typeparams %[[dstUnbox]]#1 : (!fir.ref<!fir.char<1,?>>, index) -> !fir.box<!fir.char<1,?>> !CHECK-NEXT: %[[statusBox:.*]] = fir.absent !fir.box<none> @@ -33,9 +33,9 @@ subroutine test_rename_status(src, dst) call rename(src, dst, status) !CHECK: %[[dstUnbox:.*]]:2 = fir.unboxchar %[[dummyDst]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index) - !CHECK-NEXT: %[[dstDecl:.*]]:2 = hlfir.declare %[[dstUnbox]]#0 typeparams %[[dstUnbox]]#1 dummy_scope %0 {uniq_name = "_QFtest_rename_statusEdst"} : (!fir.ref<!fir.char<1,?>>, index, !fir.dscope) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>) + !CHECK-NEXT: %[[dstDecl:.*]]:2 = hlfir.declare %[[dstUnbox]]#0 typeparams %[[dstUnbox]]#1 dummy_scope %0 {{.*}} {uniq_name = "_QFtest_rename_statusEdst"} : (!fir.ref<!fir.char<1,?>>, index, !fir.dscope) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>) !CHECK-NEXT: %[[srcUnbox:.*]]:2 = fir.unboxchar %[[dummySrc]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index) - !CHECK-NEXT: %[[srcDecl:.*]]:2 = hlfir.declare %3#0 typeparams %[[srcUnbox]]#1 dummy_scope %0 {uniq_name = "_QFtest_rename_statusEsrc"} : (!fir.ref<!fir.char<1,?>>, index, !fir.dscope) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>) + !CHECK-NEXT: %[[srcDecl:.*]]:2 = hlfir.declare %3#0 typeparams %[[srcUnbox]]#1 dummy_scope %0 {{.*}} {uniq_name = "_QFtest_rename_statusEsrc"} : (!fir.ref<!fir.char<1,?>>, index, !fir.dscope) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>) !CHECK-NEXT: %[[statusAlloc:.*]] = fir.alloca i32 {bindc_name = "status", uniq_name = "_QFtest_rename_statusEstatus"} !CHECK-NEXT: %[[statusDecl:.*]]:2 = hlfir.declare %[[statusAlloc]] {uniq_name = "_QFtest_rename_statusEstatus"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) !CHECK-NEXT: %[[srcBox:.*]] = fir.embox %[[srcDecl]]#1 typeparams %[[srcUnbox]]#1 : (!fir.ref<!fir.char<1,?>>, index) -> !fir.box<!fir.char<1,?>> diff --git a/flang/test/Lower/Intrinsics/reshape.f90 b/flang/test/Lower/Intrinsics/reshape.f90 index 4f4f509..b960a3e 100644 --- a/flang/test/Lower/Intrinsics/reshape.f90 +++ b/flang/test/Lower/Intrinsics/reshape.f90 @@ -24,16 +24,16 @@ subroutine reshape_test(x, source, pd, sh, ord) ! CHECK-DAG: %[[a18:.*]] = fir.box_addr %[[a15]] : (!fir.box<!fir.heap<!fir.array<?x?xi32>>>) -> !fir.heap<!fir.array<?x?xi32>> ! CHECK-DAG: fir.freemem %[[a18]] end subroutine - + ! CHECK-LABEL: func @_QPtest_reshape_optional( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.ptr<!fir.array<?x?xf32>>>> ! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>> subroutine test_reshape_optional(pad, order, source, shape) - real, pointer :: pad(:, :) - integer, pointer :: order(:) + real, pointer :: pad(:, :) + integer, pointer :: order(:) real :: source(:, :, :) - integer :: shape(4) - print *, reshape(source=source, shape=shape, pad=pad, order=order) + integer :: shape(4) + print *, reshape(source=source, shape=shape, pad=pad, order=order) ! CHECK: %[[VAL_13:.*]] = fir.load %[[VAL_0]] : !fir.ref<!fir.box<!fir.ptr<!fir.array<?x?xf32>>>> ! CHECK: %[[VAL_14:.*]] = fir.box_addr %[[VAL_13]] : (!fir.box<!fir.ptr<!fir.array<?x?xf32>>>) -> !fir.ptr<!fir.array<?x?xf32>> ! CHECK: %[[VAL_15:.*]] = fir.convert %[[VAL_14]] : (!fir.ptr<!fir.array<?x?xf32>>) -> i64 diff --git a/flang/test/Lower/Intrinsics/scale.f90 b/flang/test/Lower/Intrinsics/scale.f90 index 9c97349..9034c48 100644 --- a/flang/test/Lower/Intrinsics/scale.f90 +++ b/flang/test/Lower/Intrinsics/scale.f90 @@ -14,7 +14,7 @@ subroutine scale_test1(x, i) ! CHECK: %[[tmp:.*]] = fir.call @_FortranAScale4(%[[x_val]], %[[i_cast]]) {{.*}}: (f32, i64) -> f32 ! CHECK: hlfir.assign %[[tmp]] to %[[res]]#0 : f32, !fir.ref<f32> end subroutine scale_test1 - + ! CHECK-LABEL: scale_test2 subroutine scale_test2(x, i) real(kind=8) :: x, res diff --git a/flang/test/Lower/Intrinsics/second.f90 b/flang/test/Lower/Intrinsics/second.f90 index 55af10b..0da6463 100644 --- a/flang/test/Lower/Intrinsics/second.f90 +++ b/flang/test/Lower/Intrinsics/second.f90 @@ -8,7 +8,7 @@ end subroutine ! CHECK-LABEL: func.func @_QPtest_subroutine( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<f32> {fir.bindc_name = "time"}) { ! CHECK: %[[VAL_1:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] {uniq_name = "_QFtest_subroutineEtime"} : (!fir.ref<f32>, !fir.dscope) -> (!fir.ref<f32>, !fir.ref<f32>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] arg {{[0-9]+}} {uniq_name = "_QFtest_subroutineEtime"} : (!fir.ref<f32>, !fir.dscope) -> (!fir.ref<f32>, !fir.ref<f32>) ! CHECK: %[[VAL_3:.*]] = fir.call @_FortranACpuTime() fastmath<contract> : () -> f64 ! CHECK: %[[VAL_4:.*]] = fir.convert %[[VAL_3]] : (f64) -> f32 ! CHECK: fir.store %[[VAL_4]] to %[[VAL_2]]#0 : !fir.ref<f32> @@ -24,7 +24,7 @@ end subroutine ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<f32> {fir.bindc_name = "time"}) { ! CHECK: %[[VAL_1:.*]] = fir.alloca f32 ! CHECK: %[[VAL_2:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_2]] {uniq_name = "_QFtest_functionEtime"} : (!fir.ref<f32>, !fir.dscope) -> (!fir.ref<f32>, !fir.ref<f32>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_2]] arg {{[0-9]+}} {uniq_name = "_QFtest_functionEtime"} : (!fir.ref<f32>, !fir.dscope) -> (!fir.ref<f32>, !fir.ref<f32>) ! CHECK: %[[VAL_4:.*]] = fir.call @_FortranACpuTime() fastmath<contract> : () -> f64 ! CHECK: %[[VAL_5:.*]] = fir.convert %[[VAL_4]] : (f64) -> f32 ! CHECK: fir.store %[[VAL_5]] to %[[VAL_1]] : !fir.ref<f32> @@ -42,8 +42,8 @@ end subroutine ! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref<f32> {fir.bindc_name = "t2"}) { ! CHECK: %[[VAL_2:.*]] = fir.alloca f32 ! CHECK: %[[VAL_3:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_3]] {uniq_name = "_QFtest_function_subexprEt1"} : (!fir.ref<f32>, !fir.dscope) -> (!fir.ref<f32>, !fir.ref<f32>) -! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %[[VAL_3]] {uniq_name = "_QFtest_function_subexprEt2"} : (!fir.ref<f32>, !fir.dscope) -> (!fir.ref<f32>, !fir.ref<f32>) +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_3]] arg {{[0-9]+}} {uniq_name = "_QFtest_function_subexprEt1"} : (!fir.ref<f32>, !fir.dscope) -> (!fir.ref<f32>, !fir.ref<f32>) +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %[[VAL_3]] arg {{[0-9]+}} {uniq_name = "_QFtest_function_subexprEt2"} : (!fir.ref<f32>, !fir.dscope) -> (!fir.ref<f32>, !fir.ref<f32>) ! CHECK: %[[VAL_6:.*]] = fir.call @_FortranACpuTime() fastmath<contract> : () -> f64 ! CHECK: %[[VAL_7:.*]] = fir.convert %[[VAL_6]] : (f64) -> f32 ! CHECK: fir.store %[[VAL_7]] to %[[VAL_2]] : !fir.ref<f32> diff --git a/flang/test/Lower/Intrinsics/selected_char_kind.f90 b/flang/test/Lower/Intrinsics/selected_char_kind.f90 index 4012591..d2040a4 100644 --- a/flang/test/Lower/Intrinsics/selected_char_kind.f90 +++ b/flang/test/Lower/Intrinsics/selected_char_kind.f90 @@ -9,7 +9,7 @@ end ! CHECK-LABEL: func.func @_QPselected_char_kind_test( ! CHECK-SAME: %[[ARG0:.*]]: !fir.boxchar<1> {fir.bindc_name = "c"}) ! CHECK: %[[UNBOXCHAR:.*]]:2 = fir.unboxchar %[[ARG0]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index) -! CHECK: %[[C:.*]]:2 = hlfir.declare %[[UNBOXCHAR]]#0 typeparams %[[UNBOXCHAR]]#1 dummy_scope %0 {uniq_name = "_QFselected_char_kind_testEc"} : (!fir.ref<!fir.char<1,?>>, index, !fir.dscope) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>) +! CHECK: %[[C:.*]]:2 = hlfir.declare %[[UNBOXCHAR]]#0 typeparams %[[UNBOXCHAR]]#1 dummy_scope %0 {{.*}} {uniq_name = "_QFselected_char_kind_testEc"} : (!fir.ref<!fir.char<1,?>>, index, !fir.dscope) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>) ! CHECK: %[[RES_ALLOCA:.*]] = fir.alloca i32 {bindc_name = "res", uniq_name = "_QFselected_char_kind_testEres"} ! CHECK: %[[RES:.*]]:2 = hlfir.declare %[[RES_ALLOCA]] {uniq_name = "_QFselected_char_kind_testEres"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[CHAR_PTR:.*]] = fir.convert %[[C]]#1 : (!fir.ref<!fir.char<1,?>>) -> !fir.ref<i8> diff --git a/flang/test/Lower/Intrinsics/selected_logical_kind.f90 b/flang/test/Lower/Intrinsics/selected_logical_kind.f90 index 5d2d995..c818a1f 100644 --- a/flang/test/Lower/Intrinsics/selected_logical_kind.f90 +++ b/flang/test/Lower/Intrinsics/selected_logical_kind.f90 @@ -7,7 +7,7 @@ end ! CHECK-LABEL: func.func @_QPselected_logical_kind_test1( ! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<i8> {fir.bindc_name = "input"}) -! CHECK: %[[INPUT:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{.*}} {uniq_name = "_QFselected_logical_kind_test1Einput"} : (!fir.ref<i8>, !fir.dscope) -> (!fir.ref<i8>, !fir.ref<i8>) +! CHECK: %[[INPUT:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{.*}} {{.*}} {uniq_name = "_QFselected_logical_kind_test1Einput"} : (!fir.ref<i8>, !fir.dscope) -> (!fir.ref<i8>, !fir.ref<i8>) ! CHECK: %[[RES_ALLOCA:.*]] = fir.alloca i8 {bindc_name = "res", uniq_name = "_QFselected_logical_kind_test1Eres"} ! CHECK: %[[RES:.*]]:2 = hlfir.declare %[[RES_ALLOCA]] {uniq_name = "_QFselected_logical_kind_test1Eres"} : (!fir.ref<i8>) -> (!fir.ref<i8>, !fir.ref<i8>) ! CHECK: %[[KIND:.*]] = arith.constant 1 : i32 @@ -21,7 +21,7 @@ end ! CHECK-LABEL: func.func @_QPselected_logical_kind_test2( ! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<i16> {fir.bindc_name = "input"}) -! CHECK: %[[INPUT:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{.*}} {uniq_name = "_QFselected_logical_kind_test2Einput"} : (!fir.ref<i16>, !fir.dscope) -> (!fir.ref<i16>, !fir.ref<i16>) +! CHECK: %[[INPUT:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{.*}} {{.*}} {uniq_name = "_QFselected_logical_kind_test2Einput"} : (!fir.ref<i16>, !fir.dscope) -> (!fir.ref<i16>, !fir.ref<i16>) ! CHECK: %[[RES_ALLOCA:.*]] = fir.alloca i16 {bindc_name = "res", uniq_name = "_QFselected_logical_kind_test2Eres"} ! CHECK: %[[RES:.*]]:2 = hlfir.declare %[[RES_ALLOCA]] {uniq_name = "_QFselected_logical_kind_test2Eres"} : (!fir.ref<i16>) -> (!fir.ref<i16>, !fir.ref<i16>) ! CHECK: %[[KIND:.*]] = arith.constant 2 : i32 @@ -35,7 +35,7 @@ end ! CHECK-LABEL: func.func @_QPselected_logical_kind_test4( ! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<i32> {fir.bindc_name = "input"}) -! CHECK: %[[INPUT:.*]]:2 = hlfir.declare %arg0 dummy_scope %0 {uniq_name = "_QFselected_logical_kind_test4Einput"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[INPUT:.*]]:2 = hlfir.declare %arg0 dummy_scope %0 {{.*}} {uniq_name = "_QFselected_logical_kind_test4Einput"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[RES_ALLOCA:.*]] = fir.alloca i32 {bindc_name = "res", uniq_name = "_QFselected_logical_kind_test4Eres"} ! CHECK: %[[RES:.*]]:2 = hlfir.declare %[[RES_ALLOCA]] {uniq_name = "_QFselected_logical_kind_test4Eres"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[KIND:.*]] = arith.constant 4 : i32 @@ -49,7 +49,7 @@ end ! CHECK-LABEL: func.func @_QPselected_logical_kind_test8( ! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<i64> {fir.bindc_name = "input"}) -! CHECK: %[[INPUT:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{.*}} {uniq_name = "_QFselected_logical_kind_test8Einput"} : (!fir.ref<i64>, !fir.dscope) -> (!fir.ref<i64>, !fir.ref<i64>) +! CHECK: %[[INPUT:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{.*}} {{.*}} {uniq_name = "_QFselected_logical_kind_test8Einput"} : (!fir.ref<i64>, !fir.dscope) -> (!fir.ref<i64>, !fir.ref<i64>) ! CHECK: %[[RES_ALLOCA]] = fir.alloca i64 {bindc_name = "res", uniq_name = "_QFselected_logical_kind_test8Eres"} ! CHECK: %[[RES:.*]]:2 = hlfir.declare %[[RES_ALLOCA]] {uniq_name = "_QFselected_logical_kind_test8Eres"} : (!fir.ref<i64>) -> (!fir.ref<i64>, !fir.ref<i64>) ! CHECK: %[[KIND:.*]] = arith.constant 8 : i32 @@ -63,7 +63,7 @@ end ! CHECK-LABEL: func.func @_QPselected_logical_kind_test16( ! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<i128> {fir.bindc_name = "input"}) -! CHECK: %[[INPUT:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{.*}} {uniq_name = "_QFselected_logical_kind_test16Einput"} : (!fir.ref<i128>, !fir.dscope) -> (!fir.ref<i128>, !fir.ref<i128>) +! CHECK: %[[INPUT:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{.*}} {{.*}} {uniq_name = "_QFselected_logical_kind_test16Einput"} : (!fir.ref<i128>, !fir.dscope) -> (!fir.ref<i128>, !fir.ref<i128>) ! CHECK: %[[RES_ALLOCA:.*]] = fir.alloca i128 {bindc_name = "res", uniq_name = "_QFselected_logical_kind_test16Eres"} ! CHECK: %[[RES:.*]]:2 = hlfir.declare %[[RES_ALLOCA]] {uniq_name = "_QFselected_logical_kind_test16Eres"} : (!fir.ref<i128>) -> (!fir.ref<i128>, !fir.ref<i128>) ! CHECK: %[[KIND:.*]] = arith.constant 16 : i32 diff --git a/flang/test/Lower/Intrinsics/show_descriptor.f90 b/flang/test/Lower/Intrinsics/show_descriptor.f90 new file mode 100644 index 0000000..a0b8d3e --- /dev/null +++ b/flang/test/Lower/Intrinsics/show_descriptor.f90 @@ -0,0 +1,241 @@ +! RUN: bbc -emit-fir %s -o - | FileCheck %s + +module test_show_descriptor +use flang_debug +contains +subroutine test_int +! CHECK-LABEL: func.func @_QMtest_show_descriptorPtest_int() { + implicit none + integer :: n + integer,allocatable :: a(:) + n = 5 + allocate(a(n)) +! CHECK: %[[C3:.*]] = arith.constant 3 : index +! CHECK: %[[C1:.*]] = arith.constant 1 : index +! CHECK: %[[C5:.*]] = arith.constant 5 : i32 +! CHECK: %[[C0:.*]] = arith.constant 0 : index +! CHECK: %[[DUMMY_SCOPE_0:.*]] = fir.dummy_scope : !fir.dscope +! CHECK: %[[ALLOCA_0:.*]] = fir.alloca !fir.box<!fir.heap<!fir.array<?xi32>>> {bindc_name = "a", uniq_name = "_QMtest_show_descriptorFtest_intEa"} +! CHECK: %[[ZERO_BITS_0:.*]] = fir.zero_bits !fir.heap<!fir.array<?xi32>> +! CHECK: %[[SHAPE_0:.*]] = fir.shape %[[C0]] : (index) -> !fir.shape<1> +! CHECK: %[[EMBOX_0:.*]] = fir.embox %[[ZERO_BITS_0]](%[[SHAPE_0]]) : (!fir.heap<!fir.array<?xi32>>, !fir.shape<1>) -> !fir.box<!fir.heap<!fir.array<?xi32>>> +! CHECK: fir.store %[[EMBOX_0]] to %[[ALLOCA_0]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> +! CHECK: %[[DECLARE_0:.*]] = fir.declare %[[ALLOCA_0]] {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QMtest_show_descriptorFtest_intEa"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> +! CHECK: %[[ALLOCA_1:.*]] = fir.alloca i32 {bindc_name = "n", uniq_name = "_QMtest_show_descriptorFtest_intEn"} +! CHECK: %[[DECLARE_1:.*]] = fir.declare %[[ALLOCA_1]] {uniq_name = "_QMtest_show_descriptorFtest_intEn"} : (!fir.ref<i32>) -> !fir.ref<i32> +! CHECK: fir.store %[[C5]] to %[[DECLARE_1]] : !fir.ref<i32> +! CHECK: %[[LOAD_0:.*]] = fir.load %[[DECLARE_1]] : !fir.ref<i32> +! CHECK: %[[CONVERT_0:.*]] = fir.convert %[[LOAD_0]] : (i32) -> index +! CHECK: %[[CMPI_0:.*]] = arith.cmpi sgt, %[[CONVERT_0]], %[[C0]] : index +! CHECK: %[[SELECT_0:.*]] = arith.select %[[CMPI_0]], %[[CONVERT_0]], %[[C0]] : index +! CHECK: %[[ALLOCMEM_0:.*]] = fir.allocmem !fir.array<?xi32>, %[[SELECT_0]] {fir.must_be_heap = true, uniq_name = "_QMtest_show_descriptorFtest_intEa.alloc"} + + call show_descriptor(a) +! CHECK: %[[SHAPE_1:.*]] = fir.shape %[[SELECT_0]] : (index) -> !fir.shape<1> +! CHECK: %[[EMBOX_1:.*]] = fir.embox %[[ALLOCMEM_0]](%[[SHAPE_1]]) : (!fir.heap<!fir.array<?xi32>>, !fir.shape<1>) -> !fir.box<!fir.heap<!fir.array<?xi32>>> +! CHECK: fir.store %[[EMBOX_1]] to %[[DECLARE_0]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> +! CHECK: %[[LOAD_1:.*]] = fir.load %[[DECLARE_0]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> +! CHECK: fir.call @_FortranAShowDescriptor(%[[LOAD_1]]) fastmath<contract> : (!fir.box<!fir.heap<!fir.array<?xi32>>>) -> () + + call show_descriptor(a(1:3)) +! CHECK: %[[LOAD_2:.*]] = fir.load %[[DECLARE_0]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> +! CHECK: %[[SHAPE_2:.*]] = fir.shape %[[C3]] : (index) -> !fir.shape<1> +! CHECK: %[[BOX_ADDR_0:.*]] = fir.box_addr %[[LOAD_2]] : (!fir.box<!fir.heap<!fir.array<?xi32>>>) -> !fir.heap<!fir.array<?xi32>> +! CHECK: %[[CONSTANT_4:.*]] = arith.constant 0 : index +! CHECK: %[[BOX_DIMS_0:.*]]:3 = fir.box_dims %[[LOAD_2]], %[[CONSTANT_4]] : (!fir.box<!fir.heap<!fir.array<?xi32>>>, index) -> (index, index, index) +! CHECK: %[[SHAPE_SHIFT_0:.*]] = fir.shape_shift %[[BOX_DIMS_0]]#0, %[[BOX_DIMS_0]]#1 : (index, index) -> !fir.shapeshift<1> +! CHECK: %[[ARRAY_COOR_0:.*]] = fir.array_coor %[[BOX_ADDR_0]](%[[SHAPE_SHIFT_0]]) %[[C1]] : (!fir.heap<!fir.array<?xi32>>, !fir.shapeshift<1>, index) -> !fir.ref<i32> +! CHECK: %[[CONVERT_1:.*]] = fir.convert %[[ARRAY_COOR_0]] : (!fir.ref<i32>) -> !fir.ref<!fir.array<3xi32>> +! CHECK: %[[EMBOX_2:.*]] = fir.embox %[[CONVERT_1]](%[[SHAPE_2]]) : (!fir.ref<!fir.array<3xi32>>, !fir.shape<1>) -> !fir.box<!fir.array<3xi32>> +! CHECK: fir.call @_FortranAShowDescriptor(%[[EMBOX_2]]) fastmath<contract> : (!fir.box<!fir.array<3xi32>>) -> () + deallocate(a) +end subroutine test_int + +subroutine test_char +! CHECK-LABEL: func.func @_QMtest_show_descriptorPtest_char() { + implicit none + character(len=9) :: c = 'Hey buddy' + call show_descriptor(c) +! CHECK: %[[C3:.*]] = arith.constant 3 : index +! CHECK: %[[C1:.*]] = arith.constant 1 : index +! CHECK: %[[C9:.*]] = arith.constant 9 : index +! CHECK: %[[DUMMY_SCOPE_0:.*]] = fir.dummy_scope : !fir.dscope +! CHECK: %[[ADDRESS_OF_0:.*]] = fir.address_of(@_QMtest_show_descriptorFtest_charEc) : !fir.ref<!fir.char<1,9>> +! CHECK: %[[DECLARE_0:.*]] = fir.declare %[[ADDRESS_OF_0]] typeparams %[[C9]] {uniq_name = "_QMtest_show_descriptorFtest_charEc"} : (!fir.ref<!fir.char<1,9>>, index) -> !fir.ref<!fir.char<1,9>> +! CHECK: %[[EMBOX_0:.*]] = fir.embox %[[DECLARE_0]] : (!fir.ref<!fir.char<1,9>>) -> !fir.box<!fir.char<1,9>> +! CHECK: fir.call @_FortranAShowDescriptor(%[[EMBOX_0]]) fastmath<contract> : (!fir.box<!fir.char<1,9>>) -> () + + call show_descriptor(c(1:3)) +! CHECK: %[[C1_0:.*]] = arith.constant 1 : index +! CHECK: %[[SUBI_0:.*]] = arith.subi %[[C1]], %[[C1_0]] : index +! CHECK: %[[CONVERT_0:.*]] = fir.convert %[[DECLARE_0]] : (!fir.ref<!fir.char<1,9>>) -> !fir.ref<!fir.array<9x!fir.char<1>>> +! CHECK: %[[COORDINATE_OF_0:.*]] = fir.coordinate_of %[[CONVERT_0]], %[[SUBI_0]] : (!fir.ref<!fir.array<9x!fir.char<1>>>, index) -> !fir.ref<!fir.char<1>> +! CHECK: %[[CONVERT_1:.*]] = fir.convert %[[COORDINATE_OF_0]] : (!fir.ref<!fir.char<1>>) -> !fir.ref<!fir.char<1,3>> +! CHECK: %[[EMBOX_1:.*]] = fir.embox %[[CONVERT_1]] : (!fir.ref<!fir.char<1,3>>) -> !fir.box<!fir.char<1,3>> +! CHECK: fir.call @_FortranAShowDescriptor(%[[EMBOX_1]]) fastmath<contract> : (!fir.box<!fir.char<1,3>>) -> () +! CHECK: return +end subroutine test_char + +subroutine test_logical +! CHECK-LABEL: func.func @_QMtest_show_descriptorPtest_logical() { + implicit none + logical(kind=1) :: l1 = .false. + logical(kind=2) :: l2 = .true. + logical(kind=2), dimension(2), target :: la2 = (/ .true., .false. /) + logical(kind=2), dimension(:), pointer :: pla2 +! CHECK: %[[C0:.*]] = arith.constant 0 : index +! CHECK: %[[C2:.*]] = arith.constant 2 : index +! CHECK: %[[DUMMY_SCOPE_0:.*]] = fir.dummy_scope : !fir.dscope +! CHECK: %[[ADDRESS_OF_0:.*]] = fir.address_of(@_QMtest_show_descriptorFtest_logicalEl1) : !fir.ref<!fir.logical<1>> +! CHECK: %[[DECLARE_0:.*]] = fir.declare %[[ADDRESS_OF_0]] {uniq_name = "_QMtest_show_descriptorFtest_logicalEl1"} : (!fir.ref<!fir.logical<1>>) -> !fir.ref<!fir.logical<1>> +! CHECK: %[[ADDRESS_OF_1:.*]] = fir.address_of(@_QMtest_show_descriptorFtest_logicalEl2) : !fir.ref<!fir.logical<2>> +! CHECK: %[[DECLARE_1:.*]] = fir.declare %[[ADDRESS_OF_1]] {uniq_name = "_QMtest_show_descriptorFtest_logicalEl2"} : (!fir.ref<!fir.logical<2>>) -> !fir.ref<!fir.logical<2>> +! CHECK: %[[ADDRESS_OF_2:.*]] = fir.address_of(@_QMtest_show_descriptorFtest_logicalEla2) : !fir.ref<!fir.array<2x!fir.logical<2>>> +! CHECK: %[[SHAPE_0:.*]] = fir.shape %[[C2]] : (index) -> !fir.shape<1> +! CHECK: %[[DECLARE_2:.*]] = fir.declare %[[ADDRESS_OF_2]](%[[SHAPE_0]]) {fortran_attrs = #fir.var_attrs<target>, uniq_name = "_QMtest_show_descriptorFtest_logicalEla2"} : (!fir.ref<!fir.array<2x!fir.logical<2>>>, !fir.shape<1>) -> !fir.ref<!fir.array<2x!fir.logical<2>>> +! CHECK: %[[ALLOCA_0:.*]] = fir.alloca !fir.box<!fir.ptr<!fir.array<?x!fir.logical<2>>>> {bindc_name = "pla2", uniq_name = "_QMtest_show_descriptorFtest_logicalEpla2"} +! CHECK: %[[ZERO_BITS_0:.*]] = fir.zero_bits !fir.ptr<!fir.array<?x!fir.logical<2>>> +! CHECK: %[[SHAPE_1:.*]] = fir.shape %[[C0]] : (index) -> !fir.shape<1> +! CHECK: %[[EMBOX_0:.*]] = fir.embox %[[ZERO_BITS_0]](%[[SHAPE_1]]) : (!fir.ptr<!fir.array<?x!fir.logical<2>>>, !fir.shape<1>) -> !fir.box<!fir.ptr<!fir.array<?x!fir.logical<2>>>> +! CHECK: fir.store %[[EMBOX_0]] to %[[ALLOCA_0]] : !fir.ref<!fir.box<!fir.ptr<!fir.array<?x!fir.logical<2>>>>> + + call show_descriptor(l1) + call show_descriptor(l2) + pla2 => la2 +! CHECK: %[[DECLARE_3:.*]] = fir.declare %[[ALLOCA_0]] {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QMtest_show_descriptorFtest_logicalEpla2"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?x!fir.logical<2>>>>>) -> !fir.ref<!fir.box<!fir.ptr<!fir.array<?x!fir.logical<2>>>>> +! CHECK: %[[EMBOX_1:.*]] = fir.embox %[[DECLARE_0]] : (!fir.ref<!fir.logical<1>>) -> !fir.box<!fir.logical<1>> +! CHECK: fir.call @_FortranAShowDescriptor(%[[EMBOX_1]]) fastmath<contract> : (!fir.box<!fir.logical<1>>) -> () +! CHECK: %[[EMBOX_2:.*]] = fir.embox %[[DECLARE_1]] : (!fir.ref<!fir.logical<2>>) -> !fir.box<!fir.logical<2>> +! CHECK: fir.call @_FortranAShowDescriptor(%[[EMBOX_2]]) fastmath<contract> : (!fir.box<!fir.logical<2>>) -> () + + call show_descriptor(la2) + call show_descriptor(pla2) +! CHECK: %[[CONVERT_0:.*]] = fir.convert %[[DECLARE_2]] : (!fir.ref<!fir.array<2x!fir.logical<2>>>) -> !fir.ref<!fir.array<?x!fir.logical<2>>> +! CHECK: %[[EMBOX_3:.*]] = fir.embox %[[CONVERT_0]](%[[SHAPE_0]]) : (!fir.ref<!fir.array<?x!fir.logical<2>>>, !fir.shape<1>) -> !fir.box<!fir.ptr<!fir.array<?x!fir.logical<2>>>> +! CHECK: fir.store %[[EMBOX_3]] to %[[DECLARE_3]] : !fir.ref<!fir.box<!fir.ptr<!fir.array<?x!fir.logical<2>>>>> +! CHECK: %[[EMBOX_4:.*]] = fir.embox %[[DECLARE_2]](%[[SHAPE_0]]) : (!fir.ref<!fir.array<2x!fir.logical<2>>>, !fir.shape<1>) -> !fir.box<!fir.array<2x!fir.logical<2>>> +! CHECK: fir.call @_FortranAShowDescriptor(%[[EMBOX_4]]) fastmath<contract> : (!fir.box<!fir.array<2x!fir.logical<2>>>) -> () +! CHECK: %[[LOAD_0:.*]] = fir.load %[[DECLARE_3]] : !fir.ref<!fir.box<!fir.ptr<!fir.array<?x!fir.logical<2>>>>> +! CHECK: fir.call @_FortranAShowDescriptor(%[[LOAD_0]]) fastmath<contract> : (!fir.box<!fir.ptr<!fir.array<?x!fir.logical<2>>>>) -> () +! CHECK: return +end subroutine test_logical + +subroutine test_real +! CHECK-LABEL: func.func @_QMtest_show_descriptorPtest_real() { + implicit none + real :: half = 0.5 + real :: row(3) = (/ 1 , 2, 3 /) + real(kind=8) :: w(4) = (/ .00011_8 , .00012_8, .00013_8, .00014_8 /) +! CHECK: %[[C2:.*]] = arith.constant 2 : index +! CHECK: %[[C1:.*]] = arith.constant 1 : index +! CHECK: %[[C4:.*]] = arith.constant 4 : index +! CHECK: %[[C3:.*]] = arith.constant 3 : index +! CHECK: %[[DUMMY_SCOPE_2:.*]] = fir.dummy_scope : !fir.dscope +! CHECK: %[[ADDRESS_OF_4:.*]] = fir.address_of(@_QMtest_show_descriptorFtest_realEhalf) : !fir.ref<f32> +! CHECK: %[[DECLARE_5:.*]] = fir.declare %[[ADDRESS_OF_4]] {uniq_name = "_QMtest_show_descriptorFtest_realEhalf"} : (!fir.ref<f32>) -> !fir.ref<f32> +! CHECK: %[[ADDRESS_OF_5:.*]] = fir.address_of(@_QMtest_show_descriptorFtest_realErow) : !fir.ref<!fir.array<3xf32>> +! CHECK: %[[SHAPE_2:.*]] = fir.shape %[[C3]] : (index) -> !fir.shape<1> +! CHECK: %[[DECLARE_6:.*]] = fir.declare %[[ADDRESS_OF_5]](%[[SHAPE_2]]) {uniq_name = "_QMtest_show_descriptorFtest_realErow"} : (!fir.ref<!fir.array<3xf32>>, !fir.shape<1>) -> !fir.ref<!fir.array<3xf32>> +! CHECK: %[[ADDRESS_OF_6:.*]] = fir.address_of(@_QMtest_show_descriptorFtest_realEw) : !fir.ref<!fir.array<4xf64>> +! CHECK: %[[SHAPE_3:.*]] = fir.shape %[[C4]] : (index) -> !fir.shape<1> +! CHECK: %[[DECLARE_7:.*]] = fir.declare %[[ADDRESS_OF_6]](%[[SHAPE_3]]) {uniq_name = "_QMtest_show_descriptorFtest_realEw"} : (!fir.ref<!fir.array<4xf64>>, !fir.shape<1>) -> !fir.ref<!fir.array<4xf64>> + + call show_descriptor(half) + call show_descriptor(row) + call show_descriptor(w) + call show_descriptor(w(1:4:2)) +! CHECK: %[[EMBOX_7:.*]] = fir.embox %[[DECLARE_5]] : (!fir.ref<f32>) -> !fir.box<f32> +! CHECK: fir.call @_FortranAShowDescriptor(%[[EMBOX_7]]) fastmath<contract> : (!fir.box<f32>) -> () +! CHECK: %[[EMBOX_8:.*]] = fir.embox %[[DECLARE_6]](%[[SHAPE_2]]) : (!fir.ref<!fir.array<3xf32>>, !fir.shape<1>) -> !fir.box<!fir.array<3xf32>> +! CHECK: fir.call @_FortranAShowDescriptor(%[[EMBOX_8]]) fastmath<contract> : (!fir.box<!fir.array<3xf32>>) -> () +! CHECK: %[[EMBOX_9:.*]] = fir.embox %[[DECLARE_7]](%[[SHAPE_3]]) : (!fir.ref<!fir.array<4xf64>>, !fir.shape<1>) -> !fir.box<!fir.array<4xf64>> +! CHECK: fir.call @_FortranAShowDescriptor(%[[EMBOX_9]]) fastmath<contract> : (!fir.box<!fir.array<4xf64>>) -> () +! CHECK: %[[SHAPE_4:.*]] = fir.shape %[[C2]] : (index) -> !fir.shape<1> +! CHECK: %[[UNDEFINED_0:.*]] = fir.undefined index +! CHECK: %[[SLICE_0:.*]] = fir.slice %[[C1]], %[[C4]], %[[C2]] : (index, index, index) -> !fir.slice<1> +! CHECK: %[[EMBOX_10:.*]] = fir.embox %[[DECLARE_7]](%[[SHAPE_3]]) {{\[}}%[[SLICE_0]]] : (!fir.ref<!fir.array<4xf64>>, !fir.shape<1>, !fir.slice<1>) -> !fir.box<!fir.array<2xf64>> +! CHECK: fir.call @_FortranAShowDescriptor(%[[EMBOX_10]]) fastmath<contract> : (!fir.box<!fir.array<2xf64>>) -> () +! CHECK: return +end subroutine test_real + +subroutine test_complex +! CHECK-LABEL: func.func @_QMtest_show_descriptorPtest_complex() { + implicit none + complex, parameter :: hr = 0.5 + complex, parameter :: hi = (0, 0.5) + complex :: c1 = hr + complex :: c2 = hi + complex :: a2(2) = (/ hr, hi /) +! CHECK: %[[CST_0:.*]] = arith.constant 0.000000e+00 : f32 +! CHECK: %[[CST_1:.*]] = arith.constant 5.000000e-01 : f32 +! CHECK: %[[C2:.*]] = arith.constant 2 : index +! CHECK: %[[ALLOCA_1:.*]] = fir.alloca complex<f32> +! CHECK: %[[ALLOCA_2:.*]] = fir.alloca complex<f32> +! CHECK: %[[DUMMY_SCOPE_3:.*]] = fir.dummy_scope : !fir.dscope +! CHECK: %[[ADDRESS_OF_7:.*]] = fir.address_of(@_QMtest_show_descriptorFtest_complexEa2) : !fir.ref<!fir.array<2xcomplex<f32>>> +! CHECK: %[[SHAPE_5:.*]] = fir.shape %[[C2]] : (index) -> !fir.shape<1> +! CHECK: %[[DECLARE_8:.*]] = fir.declare %[[ADDRESS_OF_7]](%[[SHAPE_5]]) {uniq_name = "_QMtest_show_descriptorFtest_complexEa2"} : (!fir.ref<!fir.array<2xcomplex<f32>>>, !fir.shape<1>) -> !fir.ref<!fir.array<2xcomplex<f32>>> +! CHECK: %[[ADDRESS_OF_8:.*]] = fir.address_of(@_QMtest_show_descriptorFtest_complexEc1) : !fir.ref<complex<f32>> +! CHECK: %[[DECLARE_9:.*]] = fir.declare %[[ADDRESS_OF_8]] {uniq_name = "_QMtest_show_descriptorFtest_complexEc1"} : (!fir.ref<complex<f32>>) -> !fir.ref<complex<f32>> +! CHECK: %[[ADDRESS_OF_9:.*]] = fir.address_of(@_QMtest_show_descriptorFtest_complexEc2) : !fir.ref<complex<f32>> +! CHECK: %[[DECLARE_10:.*]] = fir.declare %[[ADDRESS_OF_9]] {uniq_name = "_QMtest_show_descriptorFtest_complexEc2"} : (!fir.ref<complex<f32>>) -> !fir.ref<complex<f32>> +! CHECK: %[[ADDRESS_OF_10:.*]] = fir.address_of(@_QMtest_show_descriptorFtest_complexEChi) : !fir.ref<complex<f32>> +! CHECK: %[[DECLARE_11:.*]] = fir.declare %[[ADDRESS_OF_10]] {fortran_attrs = #fir.var_attrs<parameter>, uniq_name = "_QMtest_show_descriptorFtest_complexEChi"} : (!fir.ref<complex<f32>>) -> !fir.ref<complex<f32>> +! CHECK: %[[ADDRESS_OF_11:.*]] = fir.address_of(@_QMtest_show_descriptorFtest_complexEChr) : !fir.ref<complex<f32>> +! CHECK: %[[DECLARE_12:.*]] = fir.declare %[[ADDRESS_OF_11]] {fortran_attrs = #fir.var_attrs<parameter>, uniq_name = "_QMtest_show_descriptorFtest_complexEChr"} : (!fir.ref<complex<f32>>) -> !fir.ref<complex<f32>> +! CHECK: %[[UNDEFINED_1:.*]] = fir.undefined complex<f32> +! CHECK: %[[INSERT_VALUE_0:.*]] = fir.insert_value %[[UNDEFINED_1]], %[[CST_1]], [0 : index] : (complex<f32>, f32) -> complex<f32> +! CHECK: %[[INSERT_VALUE_1:.*]] = fir.insert_value %[[INSERT_VALUE_0]], %[[CST_0]], [1 : index] : (complex<f32>, f32) -> complex<f32> +! CHECK: fir.store %[[INSERT_VALUE_1]] to %[[ALLOCA_2]] : !fir.ref<complex<f32>> + + call show_descriptor(hr) +! CHECK: %[[EMBOX_11:.*]] = fir.embox %[[ALLOCA_2]] : (!fir.ref<complex<f32>>) -> !fir.box<complex<f32>> +! CHECK: fir.call @_FortranAShowDescriptor(%[[EMBOX_11]]) fastmath<contract> : (!fir.box<complex<f32>>) -> () + + call show_descriptor(hi) +! CHECK: %[[INSERT_VALUE_2:.*]] = fir.insert_value %[[UNDEFINED_1]], %[[CST_0]], [0 : index] : (complex<f32>, f32) -> complex<f32> +! CHECK: %[[INSERT_VALUE_3:.*]] = fir.insert_value %[[INSERT_VALUE_2]], %[[CST_1]], [1 : index] : (complex<f32>, f32) -> complex<f32> +! CHECK: fir.store %[[INSERT_VALUE_3]] to %[[ALLOCA_1]] : !fir.ref<complex<f32>> +! CHECK: %[[EMBOX_12:.*]] = fir.embox %[[ALLOCA_1]] : (!fir.ref<complex<f32>>) -> !fir.box<complex<f32>> +! CHECK: fir.call @_FortranAShowDescriptor(%[[EMBOX_12]]) fastmath<contract> : (!fir.box<complex<f32>>) -> () + + call show_descriptor(a2) +! CHECK: %[[EMBOX_13:.*]] = fir.embox %[[DECLARE_8]](%[[SHAPE_5]]) : (!fir.ref<!fir.array<2xcomplex<f32>>>, !fir.shape<1>) -> !fir.box<!fir.array<2xcomplex<f32>>> +! CHECK: fir.call @_FortranAShowDescriptor(%[[EMBOX_13]]) fastmath<contract> : (!fir.box<!fir.array<2xcomplex<f32>>>) -> () +! CHECK: return +end subroutine test_complex + +subroutine test_derived +! CHECK-LABEL: func.func @_QMtest_show_descriptorPtest_derived() { + implicit none + type :: t1 + integer :: a + integer :: b + end type t1 + type, extends (t1) :: t2 + integer :: c + end type t2 + type(t2) :: vt2 = t2(7,5,3) +! CHECK: %[[C0:.*]] = arith.constant 0 : index +! CHECK: %[[C2:.*]] = arith.constant 2 : index +! CHECK: %[[C1:.*]] = arith.constant 1 : index +! CHECK: %[[DUMMY_SCOPE_4:.*]] = fir.dummy_scope : !fir.dscope +! CHECK: %[[ADDRESS_OF_12:.*]] = fir.address_of(@_QMtest_show_descriptorFtest_derivedE.n.a) : !fir.ref<!fir.char<1>> +! CHECK: %[[DECLARE_13:.*]] = fir.declare %[[ADDRESS_OF_12]] typeparams %[[C1]] {fortran_attrs = #fir.var_attrs<target>, uniq_name = "_QMtest_show_descriptorFtest_derivedE.n.a"} : (!fir.ref<!fir.char<1>>, index) -> !fir.ref<!fir.char<1>> +! CHECK: %[[ADDRESS_OF_13:.*]] = fir.address_of(@_QMtest_show_descriptorFtest_derivedE.n.b) : !fir.ref<!fir.char<1>> +! CHECK: %[[DECLARE_14:.*]] = fir.declare %[[ADDRESS_OF_13]] typeparams %[[C1]] {fortran_attrs = #fir.var_attrs<target>, uniq_name = "_QMtest_show_descriptorFtest_derivedE.n.b"} : (!fir.ref<!fir.char<1>>, index) -> !fir.ref<!fir.char<1>> +! CHECK: %[[ADDRESS_OF_14:.*]] = fir.address_of(@_QMtest_show_descriptorFtest_derivedE.n.t1) : !fir.ref<!fir.char<1,2>> +! CHECK: %[[DECLARE_15:.*]] = fir.declare %[[ADDRESS_OF_14]] typeparams %[[C2]] {fortran_attrs = #fir.var_attrs<target>, uniq_name = "_QMtest_show_descriptorFtest_derivedE.n.t1"} : (!fir.ref<!fir.char<1,2>>, index) -> !fir.ref<!fir.char<1,2>> +! CHECK: %[[ADDRESS_OF_15:.*]] = fir.address_of(@_QMtest_show_descriptorFtest_derivedE.n.c) : !fir.ref<!fir.char<1>> +! CHECK: %[[DECLARE_16:.*]] = fir.declare %[[ADDRESS_OF_15]] typeparams %[[C1]] {fortran_attrs = #fir.var_attrs<target>, uniq_name = "_QMtest_show_descriptorFtest_derivedE.n.c"} : (!fir.ref<!fir.char<1>>, index) -> !fir.ref<!fir.char<1>> +! CHECK: %[[ADDRESS_OF_16:.*]] = fir.address_of(@_QMtest_show_descriptorFtest_derivedE.n.t2) : !fir.ref<!fir.char<1,2>> +! CHECK: %[[DECLARE_17:.*]] = fir.declare %[[ADDRESS_OF_16]] typeparams %[[C2]] {fortran_attrs = #fir.var_attrs<target>, uniq_name = "_QMtest_show_descriptorFtest_derivedE.n.t2"} : (!fir.ref<!fir.char<1,2>>, index) -> !fir.ref<!fir.char<1,2>> +! CHECK: %[[ADDRESS_OF_17:.*]] = fir.address_of(@_QMtest_show_descriptorFtest_derivedEvt2) : !fir.ref<!fir.type<_QMtest_show_descriptorFtest_derivedTt2{t1:!fir.type<_QMtest_show_descriptorFtest_derivedTt1{a:i32,b:i32}>,c:i32}>> +! CHECK: %[[DECLARE_18:.*]] = fir.declare %[[ADDRESS_OF_17]] {uniq_name = "_QMtest_show_descriptorFtest_derivedEvt2"} : (!fir.ref<!fir.type<_QMtest_show_descriptorFtest_derivedTt2{t1:!fir.type<_QMtest_show_descriptorFtest_derivedTt1{a:i32,b:i32}>,c:i32}>>) -> !fir.ref<!fir.type<_QMtest_show_descriptorFtest_derivedTt2{t1:!fir.type<_QMtest_show_descriptorFtest_derivedTt1{a:i32,b:i32}>,c:i32}>> + + call show_descriptor(vt2) +! CHECK: %[[EMBOX_16:.*]] = fir.embox %[[DECLARE_18]] : (!fir.ref<!fir.type<_QMtest_show_descriptorFtest_derivedTt2{t1:!fir.type<_QMtest_show_descriptorFtest_derivedTt1{a:i32,b:i32}>,c:i32}>>) -> !fir.box<!fir.type<_QMtest_show_descriptorFtest_derivedTt2{t1:!fir.type<_QMtest_show_descriptorFtest_derivedTt1{a:i32,b:i32}>,c:i32}>> +! CHECK: fir.call @_FortranAShowDescriptor(%[[EMBOX_16]]) fastmath<contract> : (!fir.box<!fir.type<_QMtest_show_descriptorFtest_derivedTt2{t1:!fir.type<_QMtest_show_descriptorFtest_derivedTt1{a:i32,b:i32}>,c:i32}>>) -> () +! CHECK: return +end subroutine test_derived +end module test_show_descriptor diff --git a/flang/test/Lower/Intrinsics/signal.f90 b/flang/test/Lower/Intrinsics/signal.f90 index 18a6470..5c227ae 100644 --- a/flang/test/Lower/Intrinsics/signal.f90 +++ b/flang/test/Lower/Intrinsics/signal.f90 @@ -23,7 +23,7 @@ contains integer, optional, intent(out) :: optional_status ! CHECK: %[[VAL_1:.*]] = fir.alloca i32 -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<intent_out, optional>, uniq_name = "_QMmFsetup_signalsEoptional_status"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<intent_out, optional>, uniq_name = "_QMmFsetup_signalsEoptional_status"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_14:.*]]:2 = hlfir.declare %{{.*}} {uniq_name = "_QMmFsetup_signalsEstat"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) call signal(SIGFPE, handler) diff --git a/flang/test/Lower/Intrinsics/sizeof.f90 b/flang/test/Lower/Intrinsics/sizeof.f90 index 7e749f0..a8bc8b3 100644 --- a/flang/test/Lower/Intrinsics/sizeof.f90 +++ b/flang/test/Lower/Intrinsics/sizeof.f90 @@ -6,7 +6,7 @@ integer(8) function test1(x) test1 = sizeof(x) end function ! CHECK-LABEL: func.func @_QPtest1( -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %{{[0-9]+}} {uniq_name = "_QFtest1Ex"} : (!fir.class<none>, !fir.dscope) -> (!fir.class<none>, !fir.class<none>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFtest1Ex"} : (!fir.class<none>, !fir.dscope) -> (!fir.class<none>, !fir.class<none>) ! CHECK: %[[VAL_4:.*]] = fir.box_elesize %[[VAL_3]]#1 : (!fir.class<none>) -> i64 ! CHECK: hlfir.assign %[[VAL_4]] to %{{.*}} : i64, !fir.ref<i64> @@ -15,7 +15,7 @@ integer(8) function test2(x) test2 = sizeof(x) end function ! CHECK-LABEL: func.func @_QPtest2( -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %{{[0-9]+}} {uniq_name = "_QFtest2Ex"} : (!fir.class<!fir.array<?x?xnone>>, !fir.dscope) -> (!fir.class<!fir.array<?x?xnone>>, !fir.class<!fir.array<?x?xnone>>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFtest2Ex"} : (!fir.class<!fir.array<?x?xnone>>, !fir.dscope) -> (!fir.class<!fir.array<?x?xnone>>, !fir.class<!fir.array<?x?xnone>>) ! CHECK: %[[VAL_4:.*]] = fir.box_elesize %[[VAL_3]]#1 : (!fir.class<!fir.array<?x?xnone>>) -> i64 ! CHECK: %[[VAL_7:.*]] = fir.convert %[[VAL_3]]#1 : (!fir.class<!fir.array<?x?xnone>>) -> !fir.box<none> ! CHECK: %[[VAL_9:.*]] = fir.call @_FortranASize(%[[VAL_7]], %{{.*}}, %{{.*}}) fastmath<contract> : (!fir.box<none>, !fir.ref<i8>, i32) -> i64 diff --git a/flang/test/Lower/Intrinsics/spread.f90 b/flang/test/Lower/Intrinsics/spread.f90 index 3c20ec2..d4d16a6 100644 --- a/flang/test/Lower/Intrinsics/spread.f90 +++ b/flang/test/Lower/Intrinsics/spread.f90 @@ -30,7 +30,7 @@ subroutine spread_test(s,d,n,r) ! CHECK-DAG: %[[a15:.*]] = fir.box_addr %[[a13]] : (!fir.box<!fir.heap<!fir.array<?xi32>>>) -> !fir.heap<!fir.array<?xi32>> ! CHECK: fir.freemem %[[a15]] end subroutine - + ! CHECK-LABEL: func @_QMspread_modPspread_test2( ! CHECK-SAME: %[[arg0:.*]]: !fir.box<!fir.array<?xi32>>{{.*}}, %[[arg1:[^:]+]]: !fir.ref<i32>{{.*}}, %[[arg2:[^:]+]]: !fir.ref<i32>{{.*}}, %[[arg3:.*]]: !fir.box<!fir.array<?x?xi32>>{{.*}}) { subroutine spread_test2(s,d,n,r) diff --git a/flang/test/Lower/Intrinsics/sum.f90 b/flang/test/Lower/Intrinsics/sum.f90 index 3167617..454d564 100644 --- a/flang/test/Lower/Intrinsics/sum.f90 +++ b/flang/test/Lower/Intrinsics/sum.f90 @@ -111,7 +111,7 @@ integer function sum_test_optional_4(x, use_mask) integer :: x(:) logical :: use_mask logical, allocatable :: mask(:) -if (use_mask) then +if (use_mask) then allocate(mask(size(x, 1))) call set_mask(mask) ! CHECK: fir.call @_QPset_mask diff --git a/flang/test/Lower/Intrinsics/system-optional.f90 b/flang/test/Lower/Intrinsics/system-optional.f90 index 8695d18..672c398 100644 --- a/flang/test/Lower/Intrinsics/system-optional.f90 +++ b/flang/test/Lower/Intrinsics/system-optional.f90 @@ -11,8 +11,8 @@ call system(command, exitstat) ! CHECK-NEXT: %[[cmdstatVal:.*]] = fir.alloca i16 ! CHECK-NEXT: %[[DSCOPE:.*]] = fir.dummy_scope : !fir.dscope ! CHECK-NEXT: %[[commandUnbox:.*]]:2 = fir.unboxchar %[[commandArg]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index) -! CHECK-NEXT: %[[commandDeclare:.*]]:2 = hlfir.declare %[[commandUnbox]]#0 typeparams %[[commandUnbox]]#1 dummy_scope %[[DSCOPE]] {fortran_attrs = #fir.var_attrs<optional>, uniq_name = "_QFall_argsEcommand"} : (!fir.ref<!fir.char<1,?>>, index, !fir.dscope) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>) -! CHECK-NEXT: %[[exitstatDeclare:.*]]:2 = hlfir.declare %[[exitstatArg]] dummy_scope %[[DSCOPE]] {fortran_attrs = #fir.var_attrs<optional>, uniq_name = "_QFall_argsEexitstat"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK-NEXT: %[[commandDeclare:.*]]:2 = hlfir.declare %[[commandUnbox]]#0 typeparams %[[commandUnbox]]#1 dummy_scope %[[DSCOPE]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<optional>, uniq_name = "_QFall_argsEcommand"} : (!fir.ref<!fir.char<1,?>>, index, !fir.dscope) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>) +! CHECK-NEXT: %[[exitstatDeclare:.*]]:2 = hlfir.declare %[[exitstatArg]] dummy_scope %[[DSCOPE]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<optional>, uniq_name = "_QFall_argsEexitstat"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK-NEXT: %[[exitstatIsPresent:.*]] = fir.is_present %[[exitstatDeclare]]#0 : (!fir.ref<i32>) -> i1 ! CHECK-NEXT: %[[commandBox:.*]] = fir.embox %[[commandDeclare]]#1 typeparams %[[commandUnbox]]#1 : (!fir.ref<!fir.char<1,?>>, index) -> !fir.box<!fir.char<1,?>> ! CHECK-NEXT: %[[exitstatBox:.*]] = fir.embox %[[exitstatDeclare]]#0 : (!fir.ref<i32>) -> !fir.box<i32> diff --git a/flang/test/Lower/Intrinsics/system.f90 b/flang/test/Lower/Intrinsics/system.f90 index 5e9f8f2..183725cf 100644 --- a/flang/test/Lower/Intrinsics/system.f90 +++ b/flang/test/Lower/Intrinsics/system.f90 @@ -1,8 +1,8 @@ ! RUN: bbc -emit-hlfir %s -o - | FileCheck %s ! CHECK-LABEL: func.func @_QPall_args( -! CHECK-SAME: %[[commandArg:.*]]: !fir.boxchar<1> {fir.bindc_name = "command"}, -! CHECK-SAME: %[[exitstatArg:.*]]: !fir.ref<i32> {fir.bindc_name = "exitstat"}) { +! CHECK-SAME: %[[commandArg:.*]]: !fir.boxchar<1> {fir.bindc_name = "command"}, +! CHECK-SAME: %[[exitstatArg:.*]]: !fir.ref<i32> {fir.bindc_name = "exitstat"}) { subroutine all_args(command, exitstat) CHARACTER(*) :: command INTEGER :: exitstat @@ -10,8 +10,8 @@ call system(command, exitstat) ! CHECK-NEXT: %[[cmdstatVal:.*]] = fir.alloca i16 ! CHECK-NEXT: %[[DSCOPE:.*]] = fir.dummy_scope : !fir.dscope ! CHECK-NEXT: %[[commandUnbox:.*]]:2 = fir.unboxchar %[[commandArg]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index) -! CHECK-NEXT: %[[commandDeclare:.*]]:2 = hlfir.declare %[[commandUnbox]]#0 typeparams %[[commandUnbox]]#1 dummy_scope %[[DSCOPE]] {uniq_name = "_QFall_argsEcommand"} : (!fir.ref<!fir.char<1,?>>, index, !fir.dscope) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>) -! CHECK-NEXT: %[[exitstatDeclare:.*]]:2 = hlfir.declare %[[exitstatArg]] dummy_scope %[[DSCOPE]] {uniq_name = "_QFall_argsEexitstat"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK-NEXT: %[[commandDeclare:.*]]:2 = hlfir.declare %[[commandUnbox]]#0 typeparams %[[commandUnbox]]#1 dummy_scope %[[DSCOPE]] arg {{[0-9]+}} {uniq_name = "_QFall_argsEcommand"} : (!fir.ref<!fir.char<1,?>>, index, !fir.dscope) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>) +! CHECK-NEXT: %[[exitstatDeclare:.*]]:2 = hlfir.declare %[[exitstatArg]] dummy_scope %[[DSCOPE]] arg {{[0-9]+}} {uniq_name = "_QFall_argsEexitstat"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK-NEXT: %[[commandBox:.*]] = fir.embox %[[commandDeclare]]#1 typeparams %[[commandUnbox]]#1 : (!fir.ref<!fir.char<1,?>>, index) -> !fir.box<!fir.char<1,?>> ! CHECK-NEXT: %[[exitstatBox:.*]] = fir.embox %[[exitstatDeclare]]#0 : (!fir.ref<i32>) -> !fir.box<i32> ! CHECK-NEXT: %[[true:.*]] = arith.constant true @@ -36,7 +36,7 @@ call system(command) ! CHECK-NEXT: %[[cmdstatVal:.*]] = fir.alloca i16 ! CHECK-NEXT: %[[DSCOPE:.*]] = fir.dummy_scope : !fir.dscope ! CHECK-NEXT: %[[commandUnbox:.*]]:2 = fir.unboxchar %arg0 : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index) -! CHECK-NEXT: %[[commandDeclare:.*]]:2 = hlfir.declare %[[commandUnbox]]#0 typeparams %[[commandUnbox]]#1 dummy_scope %[[DSCOPE]] {uniq_name = "_QFonly_commandEcommand"} : (!fir.ref<!fir.char<1,?>>, index, !fir.dscope) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>) +! CHECK-NEXT: %[[commandDeclare:.*]]:2 = hlfir.declare %[[commandUnbox]]#0 typeparams %[[commandUnbox]]#1 dummy_scope %[[DSCOPE]] arg {{[0-9]+}} {uniq_name = "_QFonly_commandEcommand"} : (!fir.ref<!fir.char<1,?>>, index, !fir.dscope) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>) ! CHECK-NEXT: %[[commandBox:.*]] = fir.embox %[[commandDeclare]]#1 typeparams %[[commandUnbox]]#1 : (!fir.ref<!fir.char<1,?>>, index) -> !fir.box<!fir.char<1,?>> ! CHECK-NEXT: %[[true:.*]] = arith.constant true ! CHECK-NEXT: %[[absentBox:.*]] = fir.absent !fir.box<none> @@ -63,7 +63,7 @@ end subroutine ! CHECK-NEXT: %[[RETVAL:.*]] = fir.alloca i32 ! CHECK-NEXT: %[[DSCOPE:.*]] = fir.dummy_scope : !fir.dscope ! CHECK-NEXT: %[[commandUnbox:.*]]:2 = fir.unboxchar %[[commandArg]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index) -! CHECK-NEXT: %[[commandDeclare:.*]]:2 = hlfir.declare %[[commandUnbox]]#0 typeparams %[[commandUnbox]]#1 dummy_scope %[[DSCOPE]] {uniq_name = "_QFas_functionEcommand"} : (!fir.ref<!fir.char<1,?>>, index, !fir.dscope) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>) +! CHECK-NEXT: %[[commandDeclare:.*]]:2 = hlfir.declare %[[commandUnbox]]#0 typeparams %[[commandUnbox]]#1 dummy_scope %[[DSCOPE]] arg {{[0-9]+}} {uniq_name = "_QFas_functionEcommand"} : (!fir.ref<!fir.char<1,?>>, index, !fir.dscope) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>) ! CHECK-NEXT: %[[EXITSTAT_ALLOC:.*]] = fir.alloca i32 ! CHECK-NEXT: %[[exitstatDeclare:.*]]:2 = hlfir.declare %[[EXITSTAT_ALLOC]] {uniq_name = "_QFas_functionEexitstat"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK-NEXT: %[[commandBox:.*]] = fir.embox %[[commandDeclare]]#1 typeparams %[[commandUnbox]]#1 : (!fir.ref<!fir.char<1,?>>, index) -> !fir.box<!fir.char<1,?>> diff --git a/flang/test/Lower/Intrinsics/system_clock.f90 b/flang/test/Lower/Intrinsics/system_clock.f90 index 9eae3a5..f6fae11 100644 --- a/flang/test/Lower/Intrinsics/system_clock.f90 +++ b/flang/test/Lower/Intrinsics/system_clock.f90 @@ -32,11 +32,9 @@ end subroutine ! CHECK-LABEL: @_QPss subroutine ss(count) - ! CHECK: %[[V_0:[0-9]+]] = fir.alloca !fir.box<!fir.heap<i64>> {bindc_name = "count_max", uniq_name = "_QFssEcount_max"} ! CHECK: %[[V_1:[0-9]+]] = fir.alloca !fir.heap<i64> {uniq_name = "_QFssEcount_max.addr"} ! CHECK: %[[V_2:[0-9]+]] = fir.zero_bits !fir.heap<i64> ! CHECK: fir.store %[[V_2]] to %[[V_1]] : !fir.ref<!fir.heap<i64>> - ! CHECK: %[[V_3:[0-9]+]] = fir.alloca !fir.box<!fir.ptr<i64>> {bindc_name = "count_rate", uniq_name = "_QFssEcount_rate"} ! CHECK: %[[V_4:[0-9]+]] = fir.alloca !fir.ptr<i64> {uniq_name = "_QFssEcount_rate.addr"} ! CHECK: %[[V_5:[0-9]+]] = fir.zero_bits !fir.ptr<i64> ! CHECK: fir.store %[[V_5]] to %[[V_4]] : !fir.ref<!fir.ptr<i64>> diff --git a/flang/test/Lower/Intrinsics/transfer.f90 b/flang/test/Lower/Intrinsics/transfer.f90 index 2cc7e93..a792c8e 100644 --- a/flang/test/Lower/Intrinsics/transfer.f90 +++ b/flang/test/Lower/Intrinsics/transfer.f90 @@ -27,7 +27,7 @@ subroutine trans_test(store, word) real :: word store = transfer(word, store) end subroutine - + ! CHECK-LABEL: func @_QPtrans_test2( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.array<3xi32>>{{.*}}, %[[VAL_1:.*]]: !fir.ref<f32>{{.*}}) { ! CHECK: %[[VAL_2:.*]] = fir.alloca !fir.box<!fir.heap<!fir.array<?xi32>>> @@ -69,13 +69,13 @@ subroutine trans_test(store, word) ! CHECK: fir.freemem %[[VAL_25]] ! CHECK: return ! CHECK: } - + subroutine trans_test2(store, word) integer :: store(3) real :: word store = transfer(word, store, 3) end subroutine - + integer function trans_test3(p) ! CHECK-LABEL: func @_QPtrans_test3( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<i32>{{.*}}) -> i32 { diff --git a/flang/test/Lower/Intrinsics/unlink-sub.f90 b/flang/test/Lower/Intrinsics/unlink-sub.f90 index 78d2b10..3b5c22a 100644 --- a/flang/test/Lower/Intrinsics/unlink-sub.f90 +++ b/flang/test/Lower/Intrinsics/unlink-sub.f90 @@ -6,7 +6,7 @@ subroutine path_only(path) CHARACTER(len=*) :: path !CHECK-DAG: %[[scope:.*]] = fir.dummy_scope : !fir.dscope !CHECK-DAG: %[[unbox_path:.*]]:2 = fir.unboxchar %[[dummyPath]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index) - !CHECK-DAG: %[[path_decl:.*]]:2 = hlfir.declare %[[unbox_path]]#0 typeparams %[[unbox_path]]#1 dummy_scope %[[scope]] {uniq_name = "_QFpath_onlyEpath"} : (!fir.ref<!fir.char<1,?>>, index, !fir.dscope) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>) + !CHECK-DAG: %[[path_decl:.*]]:2 = hlfir.declare %[[unbox_path]]#0 typeparams %[[unbox_path]]#1 dummy_scope %[[scope]] arg {{[0-9]+}} {uniq_name = "_QFpath_onlyEpath"} : (!fir.ref<!fir.char<1,?>>, index, !fir.dscope) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>) !CHECK-DAG: %[[src_path_addr:.*]] = fir.address_of(@_{{.*}}) : !fir.ref<!fir.char<1,{{.*}}>> !CHECK-DAG: %[[line_value:.*]] = arith.constant {{.*}} : i64 !CHECK-DAG: %[[path:.*]] = fir.convert %[[path_decl]]#1 : (!fir.ref<!fir.char<1,?>>) -> !fir.ref<i8> @@ -30,8 +30,8 @@ subroutine all_arguments(path, status) INTEGER :: status !CHECK-DAG: %[[scope:.*]] = fir.dummy_scope : !fir.dscope !CHECK-DAG: %[[unbox_path:.*]]:2 = fir.unboxchar %[[dummyPath]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index) - !CHECK-DAG: %[[path_decl:.*]]:2 = hlfir.declare %[[unbox_path]]#0 typeparams %[[unbox_path]]#1 dummy_scope %[[scope]] {uniq_name = "_QFall_argumentsEpath"} : (!fir.ref<!fir.char<1,?>>, index, !fir.dscope) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>) - !CHECK-DAG: %[[status_decl:.*]]:2 = hlfir.declare %[[dummyStat]] dummy_scope %[[scope]] {uniq_name = "_QFall_argumentsEstatus"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) + !CHECK-DAG: %[[path_decl:.*]]:2 = hlfir.declare %[[unbox_path]]#0 typeparams %[[unbox_path]]#1 dummy_scope %[[scope]] arg {{[0-9]+}} {uniq_name = "_QFall_argumentsEpath"} : (!fir.ref<!fir.char<1,?>>, index, !fir.dscope) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>) + !CHECK-DAG: %[[status_decl:.*]]:2 = hlfir.declare %[[dummyStat]] dummy_scope %[[scope]] arg {{[0-9]+}} {uniq_name = "_QFall_argumentsEstatus"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) !CHECK-DAG: %[[src_path_addr:.*]] = fir.address_of(@_{{.*}}) : !fir.ref<!fir.char<1,{{.*}}>> !CHECK-DAG: %[[line_value:.*]] = arith.constant {{.*}} : i64 !CHECK-DAG: %[[path:.*]] = fir.convert %[[path_decl]]#1 : (!fir.ref<!fir.char<1,?>>) -> !fir.ref<i8> @@ -41,7 +41,7 @@ subroutine all_arguments(path, status) !CHECK: %[[unlink_result:.*]] = fir.call @_FortranAUnlink(%[[path]], %[[path_len]], %[[src_path]], %[[line]]) !CHECK-SAME: : (!fir.ref<i8>, i64, !fir.ref<i8>, i32) !CHECK-SAME: -> i32 - + !CHECK-DAG: %[[status_i64:.*]] = fir.convert %[[status_decl]]#0 : (!fir.ref<i32>) -> i64 !CHECK-DAG: %[[c_null:.*]] = arith.constant 0 : i64 !CHECK-DAG: %[[cmp_result:.*]] = arith.cmpi ne, %[[status_i64]], %[[c_null]] : i64 diff --git a/flang/test/Lower/MIF/change_team.f90 b/flang/test/Lower/MIF/change_team.f90 new file mode 100644 index 0000000..7fb31aa --- /dev/null +++ b/flang/test/Lower/MIF/change_team.f90 @@ -0,0 +1,27 @@ +! RUN: %flang_fc1 -emit-hlfir -fcoarray %s -o - | FileCheck %s --check-prefixes=COARRAY +! RUN: not %flang_fc1 -emit-hlfir %s 2>&1 | FileCheck %s --check-prefixes=NOCOARRAY + +program test_change_team + use, intrinsic :: iso_fortran_env, only: team_type + implicit none + ! NOCOARRAY: Not yet implemented: Multi-image features are experimental and are disabled by default, use '-fcoarray' to enable. + + type(team_type) :: team + integer :: stat, i + character(len=10) :: err + + ! COARRAY: mif.change_team %[[TEAM:.*]] : ({{.*}}) { + change team (team) + i = i +1 + end team + ! COARRAY: mif.end_team + ! COARRAY: } + + ! COARRAY: mif.change_team %[[TEAM:.*]] stat %[[STAT:.*]]#0 errmsg %[[ERR:.*]] : ({{.*}}, !fir.ref<i32>, !fir.box<!fir.char<1,10>>) { + change team (team, STAT=stat, ERRMSG=err) + end team + ! COARRAY: mif.end_team + ! COARRAY: } + +end program test_change_team + diff --git a/flang/test/Lower/MIF/co_broadcast.f90 b/flang/test/Lower/MIF/co_broadcast.f90 index 25e4330..fadee5f 100644 --- a/flang/test/Lower/MIF/co_broadcast.f90 +++ b/flang/test/Lower/MIF/co_broadcast.f90 @@ -34,13 +34,13 @@ program test_co_broadcast ! CHECK: %[[V1:.*]] = fir.embox %[[ARRAY_I:.*]]#0(%[[SHAPE_2]]) : (!fir.ref<!fir.array<2xi32>>, !fir.shape<1>) -> !fir.box<!fir.array<2xi32>> ! CHECK: mif.co_broadcast %[[V1]] source %[[C1_i32:.*]] : (!fir.box<!fir.array<2xi32>>, i32) call co_broadcast(array_i, source_image=1) - + ! CHECK: %[[C1_i32:.*]] = arith.constant 1 : i32 ! CHECK: %[[SHAPE_2:.*]] = fir.shape %[[C2_2:.*]] : (index) -> !fir.shape<1> ! CHECK: %[[V1:.*]] = fir.embox %[[ARRAY_C:.*]]#0(%[[SHAPE_2]]) : (!fir.ref<!fir.array<2xcomplex<f32>>>, !fir.shape<1>) -> !fir.box<!fir.array<2xcomplex<f32>>> ! CHECK: mif.co_broadcast %[[V1]] source %[[C1_i32:.*]] : (!fir.box<!fir.array<2xcomplex<f32>>>, i32) call co_broadcast(array_c, source_image=1) - + ! CHECK: %[[C1_i32:.*]] = arith.constant 1 : i32 ! CHECK: %[[SHAPE_2:.*]] = fir.shape %[[C2_2:.*]] : (index) -> !fir.shape<1> ! CHECK: %[[V1:.*]] = fir.embox %[[ARRAY_D:.*]]#0(%[[SHAPE_2]]) : (!fir.ref<!fir.array<2xf64>>, !fir.shape<1>) -> !fir.box<!fir.array<2xf64>> diff --git a/flang/test/Lower/MIF/co_max.f90 b/flang/test/Lower/MIF/co_max.f90 index 19e6562..0a179c8 100644 --- a/flang/test/Lower/MIF/co_max.f90 +++ b/flang/test/Lower/MIF/co_max.f90 @@ -40,12 +40,12 @@ program test_co_max ! CHECK: %[[V1:.*]] = fir.embox %[[ARRAY_I:.*]]#0(%[[SHAPE_2]]) : (!fir.ref<!fir.array<2xi32>>, !fir.shape<1>) -> !fir.box<!fir.array<2xi32>> ! CHECK: mif.co_max %[[V1]] : (!fir.box<!fir.array<2xi32>>) call co_max(array_i) - + ! CHECK: %[[SHAPE_2:.*]] = fir.shape %[[C2_2:.*]] : (index) -> !fir.shape<1> ! CHECK: %[[V1:.*]] = fir.embox %[[ARRAY_C:.*]]#0(%[[SHAPE_2]]) : (!fir.ref<!fir.array<2x!fir.char<1>>>, !fir.shape<1>) -> !fir.box<!fir.array<2x!fir.char<1>>> ! CHECK: mif.co_max %[[V1]] result %[[C1_i32:.*]] : (!fir.box<!fir.array<2x!fir.char<1>>>, i32) - call co_max(array_c, result_image=1) - + call co_max(array_c, result_image=1) + ! CHECK: %[[SHAPE_2:.*]] = fir.shape %[[C2_2:.*]] : (index) -> !fir.shape<1> ! CHECK: %[[V1:.*]] = fir.embox %[[ARRAY_D:.*]]#0(%[[SHAPE_2]]) : (!fir.ref<!fir.array<2xf64>>, !fir.shape<1>) -> !fir.box<!fir.array<2xf64>> ! CHECK: mif.co_max %[[V1]] result %[[C1_i32:.*]] stat %[[STATUS:.*]]#0 : (!fir.box<!fir.array<2xf64>>, i32, !fir.ref<i32>) diff --git a/flang/test/Lower/MIF/co_min.f90 b/flang/test/Lower/MIF/co_min.f90 index a7adc6b..bedee0e 100644 --- a/flang/test/Lower/MIF/co_min.f90 +++ b/flang/test/Lower/MIF/co_min.f90 @@ -40,12 +40,12 @@ program test_co_min ! CHECK: %[[V1:.*]] = fir.embox %[[ARRAY_I:.*]]#0(%[[SHAPE_2]]) : (!fir.ref<!fir.array<2xi32>>, !fir.shape<1>) -> !fir.box<!fir.array<2xi32>> ! CHECK: mif.co_min %[[V1]] : (!fir.box<!fir.array<2xi32>>) call co_min(array_i) - + ! CHECK: %[[SHAPE_2:.*]] = fir.shape %[[C2_2:.*]] : (index) -> !fir.shape<1> ! CHECK: %[[V1:.*]] = fir.embox %[[ARRAY_C:.*]]#0(%[[SHAPE_2]]) : (!fir.ref<!fir.array<2x!fir.char<1>>>, !fir.shape<1>) -> !fir.box<!fir.array<2x!fir.char<1>>> ! CHECK: mif.co_min %[[V1]] result %[[C1_i32:.*]] : (!fir.box<!fir.array<2x!fir.char<1>>>, i32) - call co_min(array_c, result_image=1) - + call co_min(array_c, result_image=1) + ! CHECK: %[[SHAPE_2:.*]] = fir.shape %[[C2_2:.*]] : (index) -> !fir.shape<1> ! CHECK: %[[V1:.*]] = fir.embox %[[ARRAY_D:.*]]#0(%[[SHAPE_2]]) : (!fir.ref<!fir.array<2xf64>>, !fir.shape<1>) -> !fir.box<!fir.array<2xf64>> ! CHECK: mif.co_min %[[V1]] result %[[C1_i32:.*]] stat %[[STATUS:.*]]#0 : (!fir.box<!fir.array<2xf64>>, i32, !fir.ref<i32>) diff --git a/flang/test/Lower/MIF/co_sum.f90 b/flang/test/Lower/MIF/co_sum.f90 index 0d8a2585..9710fd6 100644 --- a/flang/test/Lower/MIF/co_sum.f90 +++ b/flang/test/Lower/MIF/co_sum.f90 @@ -36,7 +36,7 @@ program test_co_sum ! CHECK: %[[V1:.*]] = fir.embox %[[ARRAY_I:.*]]#0(%[[SHAPE_2]]) : (!fir.ref<!fir.array<2xi32>>, !fir.shape<1>) -> !fir.box<!fir.array<2xi32>> ! CHECK: mif.co_sum %[[V1]] : (!fir.box<!fir.array<2xi32>>) call co_sum(array_i) - + ! CHECK: %[[SHAPE_2:.*]] = fir.shape %[[C2_2:.*]] : (index) -> !fir.shape<1> ! CHECK: %[[V1:.*]] = fir.embox %[[ARRAY_D:.*]]#0(%[[SHAPE_2]]) : (!fir.ref<!fir.array<2xf64>>, !fir.shape<1>) -> !fir.box<!fir.array<2xf64>> ! CHECK: mif.co_sum %[[V1]] result %[[C1_i32:.*]] stat %[[STATUS:.*]]#0 : (!fir.box<!fir.array<2xf64>>, i32, !fir.ref<i32>) diff --git a/flang/test/Lower/MIF/coarray-init.f90 b/flang/test/Lower/MIF/coarray-init.f90 index e354473..e3526f6 100644 --- a/flang/test/Lower/MIF/coarray-init.f90 +++ b/flang/test/Lower/MIF/coarray-init.f90 @@ -3,7 +3,7 @@ program test_init -end +end ! ALL-LABEL: func.func @main ! ALL: fir.call @_FortranAProgramStart diff --git a/flang/test/Lower/MIF/form_team.f90 b/flang/test/Lower/MIF/form_team.f90 new file mode 100644 index 0000000..4f44b23 --- /dev/null +++ b/flang/test/Lower/MIF/form_team.f90 @@ -0,0 +1,29 @@ +! RUN: %flang_fc1 -emit-hlfir -fcoarray %s -o - | FileCheck %s --check-prefixes=COARRAY +! RUN: not %flang_fc1 -emit-hlfir %s 2>&1 | FileCheck %s --check-prefixes=NOCOARRAY + +program test_form_team + use, intrinsic :: iso_fortran_env, only: team_type + implicit none + ! NOCOARRAY: Not yet implemented: Multi-image features are experimental and are disabled by default, use '-fcoarray' to enable. + + type(team_type) :: team + integer :: team_number + integer :: team_index + integer :: stat + character(len=10) :: err + + form team (team_number, team) + ! COARRAY: mif.form_team team_number %[[ARG1:.*]] team_var %[[ARG2:.*]] : (i32, {{.*}}) -> () + + form team (team_number, team, NEW_INDEX=team_index) + ! COARRAY: mif.form_team team_number %[[ARG1:.*]] team_var %[[ARG2:.*]] new_index %[[NI:.*]] : (i32, {{.*}}, i32) -> () + + form team (team_number, team, STAT=stat) + ! COARRAY: mif.form_team team_number %[[ARG1:.*]] team_var %[[ARG2:.*]] stat %[[STAT:.*]] : (i32, {{.*}}, !fir.ref<i32>) -> () + + form team (team_number, team, ERRMSG=err) + ! COARRAY: mif.form_team team_number %[[ARG1:.*]] team_var %[[ARG2:.*]] errmsg %[[ERR:.*]] : (i32, {{.*}}, !fir.box<!fir.char<1,10>>) -> () + +end program test_form_team + + diff --git a/flang/test/Lower/MIF/get_team.f90 b/flang/test/Lower/MIF/get_team.f90 new file mode 100644 index 0000000..f27b70e --- /dev/null +++ b/flang/test/Lower/MIF/get_team.f90 @@ -0,0 +1,28 @@ +! RUN: %flang_fc1 -emit-hlfir -fcoarray %s -o - | FileCheck %s --check-prefixes=COARRAY +! RUN: not %flang_fc1 -emit-hlfir %s 2>&1 | FileCheck %s --check-prefixes=NOCOARRAY + +program test_get_team + use, intrinsic :: iso_fortran_env, only: team_type, initial_team, current_team, parent_team + implicit none + ! NOCOARRAY: Not yet implemented: Multi-image features are experimental and are disabled by default, use '-fcoarray' to enable. + + type(team_type) :: result_team + integer :: n + + ! COARRAY: %[[RES:.*]] = mif.get_team : () -> {{.*}} + result_team = get_team() + + ! COARRAY: %[[RES:.*]] = mif.get_team level %[[INIT:.*]] : (i32) -> {{.*}} + result_team = get_team(initial_team) + + ! COARRAY: %[[RES:.*]] = mif.get_team level %[[CURRENT:.*]] : (i32) -> {{.*}} + result_team = get_team(current_team) + + ! COARRAY: %[[RES:.*]] = mif.get_team level %[[PARENT:.*]] : (i32) -> {{.*}} + result_team = get_team(parent_team) + + ! COARRAY: %[[RES:.*]] = mif.get_team level %[[VAL_N:.*]] : (i32) -> {{.*}} + result_team = get_team(n) + +end program test_get_team + diff --git a/flang/test/Lower/MIF/num_images.f90 b/flang/test/Lower/MIF/num_images.f90 index a673b6e..8f31ab4 100644 --- a/flang/test/Lower/MIF/num_images.f90 +++ b/flang/test/Lower/MIF/num_images.f90 @@ -3,7 +3,7 @@ program test use iso_fortran_env integer :: i - integer :: team_number + integer :: team_number type(team_type) :: team ! CHECK: mif.num_images : () -> i32 diff --git a/flang/test/Lower/MIF/sync_all.f90 b/flang/test/Lower/MIF/sync_all.f90 index 2b1997c..4d685df 100644 --- a/flang/test/Lower/MIF/sync_all.f90 +++ b/flang/test/Lower/MIF/sync_all.f90 @@ -4,7 +4,7 @@ program test_sync_all implicit none ! NOCOARRAY: Not yet implemented: Multi-image features are experimental and are disabled by default, use '-fcoarray' to enable. - + ! COARRAY: %[[ERRMSG:.*]]:2 = hlfir.declare %[[VAL_1:.*]] typeparams %[[C_128:.*]] {uniq_name = "_QFEerror_message"} : (!fir.ref<!fir.char<1,128>>, index) -> (!fir.ref<!fir.char<1,128>>, !fir.ref<!fir.char<1,128>>) ! COARRAY: %[[STAT:.*]]:2 = hlfir.declare %[[VAL_2:.*]] {uniq_name = "_QFEsync_status"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) integer sync_status @@ -15,11 +15,11 @@ program test_sync_all ! COARRAY: mif.sync_all stat %[[STAT]]#0 : (!fir.ref<i32>) sync all(stat=sync_status) - + ! COARRAY: %[[VAL_1:.*]] = fir.embox %[[ERRMSG]]#0 : (!fir.ref<!fir.char<1,128>>) -> !fir.box<!fir.char<1,128>> ! COARRAY: mif.sync_all errmsg %[[VAL_1]] : (!fir.box<!fir.char<1,128>>) sync all( errmsg=error_message) - + ! COARRAY: %[[VAL_2:.*]] = fir.embox %[[ERRMSG]]#0 : (!fir.ref<!fir.char<1,128>>) -> !fir.box<!fir.char<1,128>> ! COARRAY: mif.sync_all stat %[[STAT]]#0 errmsg %[[VAL_2]] : (!fir.ref<i32>, !fir.box<!fir.char<1,128>>) sync all(stat=sync_status, errmsg=error_message) diff --git a/flang/test/Lower/MIF/sync_images.f90 b/flang/test/Lower/MIF/sync_images.f90 index 7ee5936..1ef577e 100644 --- a/flang/test/Lower/MIF/sync_images.f90 +++ b/flang/test/Lower/MIF/sync_images.f90 @@ -4,7 +4,7 @@ program test_sync_images implicit none ! NOCOARRAY: Not yet implemented: Multi-image features are experimental and are disabled by default, use '-fcoarray' to enable. - + ! COARRAY: %[[ERRMSG:.*]]:2 = hlfir.declare %[[VAL_1:.*]] typeparams %[[C_128:.*]] {uniq_name = "_QFEerror_message"} : (!fir.ref<!fir.char<1,128>>, index) -> (!fir.ref<!fir.char<1,128>>, !fir.ref<!fir.char<1,128>>) ! COARRAY: %[[ME:.*]]:2 = hlfir.declare %[[VAL_3:.*]] {uniq_name = "_QFEme"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) ! COARRAY: %[[STAT:.*]]:2 = hlfir.declare %[[VAL_2:.*]] {uniq_name = "_QFEsync_status"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) @@ -24,14 +24,14 @@ program test_sync_images ! COARRAY: %[[VAL_5:.*]] = fir.embox %[[IMG_SET:.*]]#0(%[[SHAPE_1:.*]]) : (!fir.ref<!fir.array<1xi32>>, !fir.shape<1>) -> !fir.box<!fir.array<1xi32>> ! COARRAY: mif.sync_images image_set %[[VAL_5]] stat %[[STAT]]#0 errmsg %[[VAL_4]] : (!fir.box<!fir.array<1xi32>>, !fir.ref<i32>, !fir.box<!fir.char<1,128>>) sync images([1], stat=sync_status, errmsg=error_message) - + ! COARRAY: mif.sync_images : () sync images(*) - + ! COARRAY: %[[VAL_6:.*]] = fir.embox %[[ME]]#0 : (!fir.ref<i32>) -> !fir.box<i32> ! COARRAY: mif.sync_images image_set %[[VAL_6]] : (!fir.box<i32>) sync images(me) - + ! COARRAY: %[[VAL_7:.*]] = fir.embox %[[IMG_SET:.*]]#0(%[[SHAPE_3:.*]]) : (!fir.ref<!fir.array<1xi32>>, !fir.shape<1>) -> !fir.box<!fir.array<1xi32>> ! COARRAY: mif.sync_images image_set %[[VAL_7]] : (!fir.box<!fir.array<1xi32>>) sync images([1]) diff --git a/flang/test/Lower/MIF/sync_memory.f90 b/flang/test/Lower/MIF/sync_memory.f90 index e6e0fa1..a36fc2d 100644 --- a/flang/test/Lower/MIF/sync_memory.f90 +++ b/flang/test/Lower/MIF/sync_memory.f90 @@ -4,22 +4,22 @@ program test_sync_memory implicit none ! NOCOARRAY: Not yet implemented: Multi-image features are experimental and are disabled by default, use '-fcoarray' to enable. - + ! COARRAY: %[[ERRMSG:.*]]:2 = hlfir.declare %[[VAL_1:.*]] typeparams %[[C_128:.*]] {uniq_name = "_QFEerror_message"} : (!fir.ref<!fir.char<1,128>>, index) -> (!fir.ref<!fir.char<1,128>>, !fir.ref<!fir.char<1,128>>) ! COARRAY: %[[STAT:.*]]:2 = hlfir.declare %[[VAL_2:.*]] {uniq_name = "_QFEsync_status"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) integer sync_status character(len=128) :: error_message - ! COARRAY: mif.sync_memory : () + ! COARRAY: mif.sync_memory : () sync memory ! COARRAY: mif.sync_memory stat %[[STAT]]#0 : (!fir.ref<i32>) sync memory(stat=sync_status) - + ! COARRAY: %[[VAL_1:.*]] = fir.embox %[[ERRMSG]]#0 : (!fir.ref<!fir.char<1,128>>) -> !fir.box<!fir.char<1,128>> ! COARRAY: mif.sync_memory errmsg %[[VAL_1]] : (!fir.box<!fir.char<1,128>>) sync memory( errmsg=error_message) - + ! COARRAY: %[[VAL_2:.*]] = fir.embox %[[ERRMSG]]#0 : (!fir.ref<!fir.char<1,128>>) -> !fir.box<!fir.char<1,128>> ! COARRAY: mif.sync_memory stat %[[STAT]]#0 errmsg %[[VAL_2]] : (!fir.ref<i32>, !fir.box<!fir.char<1,128>>) sync memory(stat=sync_status, errmsg=error_message) diff --git a/flang/test/Lower/MIF/sync_team.f90 b/flang/test/Lower/MIF/sync_team.f90 new file mode 100644 index 0000000..923bfbc --- /dev/null +++ b/flang/test/Lower/MIF/sync_team.f90 @@ -0,0 +1,25 @@ +! RUN: %flang_fc1 -emit-hlfir -fcoarray %s -o - | FileCheck %s --check-prefixes=COARRAY +! RUN2: not %flang_fc1 -emit-hlfir %s -o - | FileCheck %s --check-prefixes=NOCOARRAY + +program test_sync_team + use, intrinsic :: iso_fortran_env, only: team_type + implicit none + ! NOCOARRAY: Not yet implemented: Multi-image features are experimental and are disabled by default, use '-fcoarray' to enable. + + integer sync_status + character(len=128) :: error_message + type(team_type) :: team + + ! COARRAY: mif.sync_team %[[TEAM:.*]] : ({{.*}}) -> () + sync team(team) + + ! COARRAY: mif.sync_team %[[TEAM:.*]] stat %[[STAT:.*]]#0 : ({{.*}}, !fir.ref<i32>) -> () + sync team(team, stat=sync_status) + + ! COARRAY: mif.sync_team %[[TEAM:.*]] errmsg %[[ERR:.*]] : ({{.*}}, !fir.box<!fir.char<1,128>>) -> () + sync team(team, errmsg=error_message) + + ! COARRAY: mif.sync_team %[[TEAM:.*]] stat %[[STAT:.*]]#0 errmsg %[[ERR:.*]] : ({{.*}}, !fir.ref<i32>, !fir.box<!fir.char<1,128>>) -> () + sync team(team, stat=sync_status, errmsg=error_message) + +end program test_sync_team diff --git a/flang/test/Lower/MIF/team_number.f90 b/flang/test/Lower/MIF/team_number.f90 new file mode 100644 index 0000000..48a5f5b --- /dev/null +++ b/flang/test/Lower/MIF/team_number.f90 @@ -0,0 +1,19 @@ +! RUN: %flang_fc1 -emit-hlfir -fcoarray %s -o - | FileCheck %s --check-prefixes=COARRAY +! RUN: not %flang_fc1 -emit-hlfir %s 2>&1 | FileCheck %s --check-prefixes=NOCOARRAY + +program test_team_number + use, intrinsic :: iso_fortran_env, only: team_type + implicit none + ! NOCOARRAY: Not yet implemented: Multi-image features are experimental and are disabled by default, use '-fcoarray' to enable. + + type(team_type) :: team + integer :: t + + ! COARRAY: %[[RES:.*]] = mif.team_number team %[[TEAM:.*]] : ({{.*}}) -> i64 + t = team_number(team) + + ! COARRAY: %[[RES:.*]] = mif.team_number : () -> i64 + t = team_number() + +end program test_team_number + diff --git a/flang/test/Lower/MIF/this_image.f90 b/flang/test/Lower/MIF/this_image.f90 index ce729b3..c6674c3 100644 --- a/flang/test/Lower/MIF/this_image.f90 +++ b/flang/test/Lower/MIF/this_image.f90 @@ -5,7 +5,7 @@ program test integer :: i type(team_type) :: team - ! CHECK: mif.this_image : () -> i32 + ! CHECK: mif.this_image : () -> i32 i = this_image() ! CHECK: mif.this_image team %[[TEAM:.*]] : ({{.*}}) -> i32 diff --git a/flang/test/Lower/OpenACC/Todo/acc-cache.f90 b/flang/test/Lower/OpenACC/Todo/acc-cache.f90 new file mode 100644 index 0000000..8b81e87 --- /dev/null +++ b/flang/test/Lower/OpenACC/Todo/acc-cache.f90 @@ -0,0 +1,15 @@ +! RUN: %not_todo_cmd bbc -fopenacc -emit-hlfir %s -o - 2>&1 | FileCheck %s + +! CHECK: not yet implemented: OpenACC cache directive + +subroutine test_cache() + integer, parameter :: n = 10 + real, dimension(n) :: a, b + integer :: i + + !$acc loop + do i = 1, n + !$acc cache(b) + a(i) = b(i) + end do +end subroutine diff --git a/flang/test/Lower/OpenACC/Todo/do-loops-to-acc-loops-todo.f90 b/flang/test/Lower/OpenACC/Todo/do-loops-to-acc-loops-todo.f90 index aa1d443..3f2b77a 100644 --- a/flang/test/Lower/OpenACC/Todo/do-loops-to-acc-loops-todo.f90 +++ b/flang/test/Lower/OpenACC/Todo/do-loops-to-acc-loops-todo.f90 @@ -72,9 +72,9 @@ subroutine nested_loop_with_inner_goto() integer :: ii = 0, jj = 0 integer, parameter :: nn = 3 real, dimension(nn, nn) :: aa - + aa = -1 - + ! Nested loop with goto from inner loop - unstructured control flow is not converted. !$acc kernels do ii = 1, nn @@ -88,4 +88,4 @@ subroutine nested_loop_with_inner_goto() ! CHECK4: not yet implemented: unstructured do loop in acc kernels -end subroutine
\ No newline at end of file +end subroutine diff --git a/flang/test/Lower/OpenACC/acc-atomic-capture.f90 b/flang/test/Lower/OpenACC/acc-atomic-capture.f90 index 30e60e3..ccdd4d3 100644 --- a/flang/test/Lower/OpenACC/acc-atomic-capture.f90 +++ b/flang/test/Lower/OpenACC/acc-atomic-capture.f90 @@ -36,7 +36,7 @@ program acc_atomic_capture_test !CHECK: } !$acc atomic capture - y = x * y + y = x * y x = y !$acc end atomic @@ -53,8 +53,8 @@ program acc_atomic_capture_test !$acc atomic capture x = y - y = 2 * 10 + (8 - x) - !$acc end atomic + y = 2 * 10 + (8 - x) + !$acc end atomic end program @@ -123,8 +123,8 @@ end subroutine ! CHECK: } subroutine capture_with_convert_i32_to_f64() - real(8) :: x - integer :: v, u + real(8) :: x + integer :: v, u x = 1.0 v = 0 u = 1 diff --git a/flang/test/Lower/OpenACC/acc-atomic-update-array.f90 b/flang/test/Lower/OpenACC/acc-atomic-update-array.f90 index d281fe4..b04b0c9 100644 --- a/flang/test/Lower/OpenACC/acc-atomic-update-array.f90 +++ b/flang/test/Lower/OpenACC/acc-atomic-update-array.f90 @@ -5,7 +5,7 @@ subroutine atomic_update_array1(r, n, x) integer :: n real :: r(n), x integer :: i - + !$acc data copy(r) !$acc parallel loop @@ -20,8 +20,8 @@ end subroutine ! CHECK-LABEL: func.func @_QPatomic_update_array1( ! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.array<?xf32>> {fir.bindc_name = "r"}, %[[ARG1:.*]]: !fir.ref<i32> {fir.bindc_name = "n"}, %[[ARG2:.*]]: !fir.ref<f32> {fir.bindc_name = "x"}) { -! CHECK: %[[DECL_ARG2:.*]]:2 = hlfir.declare %[[ARG2]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFatomic_update_array1Ex"} : (!fir.ref<f32>, !fir.dscope) -> (!fir.ref<f32>, !fir.ref<f32>) -! CHECK: %[[DECL_ARG0:.*]]:2 = hlfir.declare %[[ARG0]](%{{.*}}) dummy_scope %{{[0-9]+}} {uniq_name = "_QFatomic_update_array1Er"} : (!fir.ref<!fir.array<?xf32>>, !fir.shape<1>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.ref<!fir.array<?xf32>>) +! CHECK: %[[DECL_ARG2:.*]]:2 = hlfir.declare %[[ARG2]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFatomic_update_array1Ex"} : (!fir.ref<f32>, !fir.dscope) -> (!fir.ref<f32>, !fir.ref<f32>) +! CHECK: %[[DECL_ARG0:.*]]:2 = hlfir.declare %[[ARG0]](%{{.*}}) dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFatomic_update_array1Er"} : (!fir.ref<!fir.array<?xf32>>, !fir.shape<1>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.ref<!fir.array<?xf32>>) ! CHECK: %[[ARRAY_REF:.*]] = hlfir.designate %[[DECL_ARG0]]#0 (%{{.*}}) : (!fir.box<!fir.array<?xf32>>, i64) -> !fir.ref<f32> ! CHECK: %[[LOAD_X:.*]] = fir.load %[[DECL_ARG2]]#0 : !fir.ref<f32> ! CHECK: acc.atomic.update %[[ARRAY_REF]] : !fir.ref<f32> { @@ -42,8 +42,8 @@ end subroutine ! CHECK-LABEL: func.func @_QPatomic_read_array1( ! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.array<?xf32>> {fir.bindc_name = "r"}, %[[ARG1:.*]]: !fir.ref<i32> {fir.bindc_name = "n"}, %[[ARG2:.*]]: !fir.ref<f32> {fir.bindc_name = "x"}) { -! CHECK: %[[DECL_X:.*]]:2 = hlfir.declare %[[ARG2]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFatomic_read_array1Ex"} : (!fir.ref<f32>, !fir.dscope) -> (!fir.ref<f32>, !fir.ref<f32>) -! CHECK: %[[DECL_R:.*]]:2 = hlfir.declare %[[ARG0]](%{{.*}}) dummy_scope %{{[0-9]+}} {uniq_name = "_QFatomic_read_array1Er"} : (!fir.ref<!fir.array<?xf32>>, !fir.shape<1>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.ref<!fir.array<?xf32>>) +! CHECK: %[[DECL_X:.*]]:2 = hlfir.declare %[[ARG2]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFatomic_read_array1Ex"} : (!fir.ref<f32>, !fir.dscope) -> (!fir.ref<f32>, !fir.ref<f32>) +! CHECK: %[[DECL_R:.*]]:2 = hlfir.declare %[[ARG0]](%{{.*}}) dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFatomic_read_array1Er"} : (!fir.ref<!fir.array<?xf32>>, !fir.shape<1>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.ref<!fir.array<?xf32>>) ! CHECK: %[[DES:.*]] = hlfir.designate %[[DECL_R]]#0 (%{{.*}}) : (!fir.box<!fir.array<?xf32>>, i64) -> !fir.ref<f32> ! CHECK: acc.atomic.read %[[DECL_X]]#0 = %[[DES]] : !fir.ref<f32>, !fir.ref<f32>, f32 @@ -51,17 +51,17 @@ subroutine atomic_write_array1(r, n, x) implicit none integer :: n real :: r(n), x - + !$acc atomic write x = r(n) end subroutine ! CHECK-LABEL: func.func @_QPatomic_write_array1( ! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.array<?xf32>> {fir.bindc_name = "r"}, %[[ARG1:.*]]: !fir.ref<i32> {fir.bindc_name = "n"}, %[[ARG2:.*]]: !fir.ref<f32> {fir.bindc_name = "x"}) { -! CHECK: %[[DECL_X:.*]]:2 = hlfir.declare %[[ARG2]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFatomic_write_array1Ex"} : (!fir.ref<f32>, !fir.dscope) -> (!fir.ref<f32>, !fir.ref<f32>) -! CHECK: %[[DECL_R:.*]]:2 = hlfir.declare %[[ARG0]](%{{.*}}) dummy_scope %{{[0-9]+}} {uniq_name = "_QFatomic_write_array1Er"} : (!fir.ref<!fir.array<?xf32>>, !fir.shape<1>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.ref<!fir.array<?xf32>>) +! CHECK: %[[DECL_X:.*]]:2 = hlfir.declare %[[ARG2]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFatomic_write_array1Ex"} : (!fir.ref<f32>, !fir.dscope) -> (!fir.ref<f32>, !fir.ref<f32>) +! CHECK: %[[DECL_R:.*]]:2 = hlfir.declare %[[ARG0]](%{{.*}}) dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFatomic_write_array1Er"} : (!fir.ref<!fir.array<?xf32>>, !fir.shape<1>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.ref<!fir.array<?xf32>>) ! CHECK: %[[DES:.*]] = hlfir.designate %[[DECL_R]]#0 (%{{.*}}) : (!fir.box<!fir.array<?xf32>>, i64) -> !fir.ref<f32> -! CHECK: %[[LOAD:.*]] = fir.load %[[DES]] : !fir.ref<f32> +! CHECK: %[[LOAD:.*]] = fir.load %[[DES]] : !fir.ref<f32> ! CHECK: acc.atomic.write %[[DECL_X]]#0 = %[[LOAD]] : !fir.ref<f32>, f32 subroutine atomic_capture_array1(r, n, x, y) @@ -77,9 +77,9 @@ end subroutine ! CHECK-LABEL: func.func @_QPatomic_capture_array1( ! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.array<?xf32>> {fir.bindc_name = "r"}, %[[ARG1:.*]]: !fir.ref<i32> {fir.bindc_name = "n"}, %[[ARG2:.*]]: !fir.ref<f32> {fir.bindc_name = "x"}, %[[ARG3:.*]]: !fir.ref<f32> {fir.bindc_name = "y"}) { -! CHECK: %[[DECL_X:.*]]:2 = hlfir.declare %[[ARG2]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFatomic_capture_array1Ex"} : (!fir.ref<f32>, !fir.dscope) -> (!fir.ref<f32>, !fir.ref<f32>) -! CHECK: %[[DECL_Y:.*]]:2 = hlfir.declare %[[ARG3]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFatomic_capture_array1Ey"} : (!fir.ref<f32>, !fir.dscope) -> (!fir.ref<f32>, !fir.ref<f32>) -! CHECK: %[[DECL_R:.*]]:2 = hlfir.declare %[[ARG0]](%{{.*}}) dummy_scope %{{[0-9]+}} {uniq_name = "_QFatomic_capture_array1Er"} : (!fir.ref<!fir.array<?xf32>>, !fir.shape<1>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.ref<!fir.array<?xf32>>) +! CHECK: %[[DECL_X:.*]]:2 = hlfir.declare %[[ARG2]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFatomic_capture_array1Ex"} : (!fir.ref<f32>, !fir.dscope) -> (!fir.ref<f32>, !fir.ref<f32>) +! CHECK: %[[DECL_Y:.*]]:2 = hlfir.declare %[[ARG3]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFatomic_capture_array1Ey"} : (!fir.ref<f32>, !fir.dscope) -> (!fir.ref<f32>, !fir.ref<f32>) +! CHECK: %[[DECL_R:.*]]:2 = hlfir.declare %[[ARG0]](%{{.*}}) dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFatomic_capture_array1Er"} : (!fir.ref<!fir.array<?xf32>>, !fir.shape<1>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.ref<!fir.array<?xf32>>) ! CHECK: %[[R_I:.*]] = hlfir.designate %[[DECL_R]]#0 (%{{.*}}) : (!fir.box<!fir.array<?xf32>>, i64) -> !fir.ref<f32> ! CHECK: %[[LOAD:.*]] = fir.load %[[DECL_X]]#0 : !fir.ref<f32> ! CHECK: acc.atomic.capture { diff --git a/flang/test/Lower/OpenACC/acc-atomic-update.f90 b/flang/test/Lower/OpenACC/acc-atomic-update.f90 index 71aa69f..f4c305a 100644 --- a/flang/test/Lower/OpenACC/acc-atomic-update.f90 +++ b/flang/test/Lower/OpenACC/acc-atomic-update.f90 @@ -42,7 +42,7 @@ program acc_atomic_update_test !CHECK: } !$acc atomic update - a = a + b + a = a + b !CHECK: {{.*}} = arith.constant 1 : i32 !CHECK: acc.atomic.update %[[Y_DECL]]#0 : !fir.ref<i32> { @@ -56,10 +56,10 @@ program acc_atomic_update_test !CHECK: %[[RESULT:.*]] = arith.muli %[[LOADED_X]], %[[ARG]] : i32 !CHECK: acc.yield %[[RESULT]] : i32 !CHECK: } - !$acc atomic + !$acc atomic y = y + 1 !$acc atomic update - z = x * z + z = x * z !CHECK: %[[C1_VAL:.*]] = arith.constant 1 : i32 !CHECK: acc.atomic.update %[[I1_DECL]]#0 : !fir.ref<i8> { diff --git a/flang/test/Lower/OpenACC/acc-bounds.f90 b/flang/test/Lower/OpenACC/acc-bounds.f90 index f6996df..03779ac 100644 --- a/flang/test/Lower/OpenACC/acc-bounds.f90 +++ b/flang/test/Lower/OpenACC/acc-bounds.f90 @@ -81,7 +81,7 @@ contains ! CHECK-LABEL: func.func @_QMopenacc_boundsPacc_undefined_extent( ! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.array<?xf32>> {fir.bindc_name = "a"}) { -! CHECK: %[[DECL_ARG0:.*]]:2 = hlfir.declare %[[ARG0]](%{{.*}}) dummy_scope %{{[0-9]+}} {uniq_name = "_QMopenacc_boundsFacc_undefined_extentEa"} : (!fir.ref<!fir.array<?xf32>>, !fir.shape<1>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.ref<!fir.array<?xf32>>) +! CHECK: %[[DECL_ARG0:.*]]:2 = hlfir.declare %[[ARG0]](%{{.*}}) dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QMopenacc_boundsFacc_undefined_extentEa"} : (!fir.ref<!fir.array<?xf32>>, !fir.shape<1>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.ref<!fir.array<?xf32>>) ! CHECK: %[[DIMS0:.*]]:3 = fir.box_dims %[[DECL_ARG0]]#0, %c0{{.*}} : (!fir.box<!fir.array<?xf32>>, index) -> (index, index, index) ! CHECK: %[[UB:.*]] = arith.subi %[[DIMS0]]#1, %c1{{.*}} : index ! CHECK: %[[BOUND:.*]] = acc.bounds lowerbound(%c0{{.*}} : index) upperbound(%[[UB]] : index) extent(%[[DIMS0]]#1 : index) stride(%[[DIMS0]]#2 : index) startIdx(%c1{{.*}} : index) {strideInBytes = true} @@ -97,7 +97,7 @@ contains ! CHECK-LABEL: func.func @_QMopenacc_boundsPacc_multi_strides( ! CHECK-SAME: %[[ARG0:.*]]: !fir.box<!fir.array<?x?x?xf32>> {fir.bindc_name = "a"}) -! CHECK: %[[DECL_ARG0:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{[0-9]+}} {uniq_name = "_QMopenacc_boundsFacc_multi_stridesEa"} : (!fir.box<!fir.array<?x?x?xf32>>, !fir.dscope) -> (!fir.box<!fir.array<?x?x?xf32>>, !fir.box<!fir.array<?x?x?xf32>>) +! CHECK: %[[DECL_ARG0:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QMopenacc_boundsFacc_multi_stridesEa"} : (!fir.box<!fir.array<?x?x?xf32>>, !fir.dscope) -> (!fir.box<!fir.array<?x?x?xf32>>, !fir.box<!fir.array<?x?x?xf32>>) ! CHECK: %[[BOX_DIMS0:.*]]:3 = fir.box_dims %[[DECL_ARG0]]#0, %c0{{.*}} : (!fir.box<!fir.array<?x?x?xf32>>, index) -> (index, index, index) ! CHECK: %[[BOUNDS0:.*]] = acc.bounds lowerbound(%{{.*}} : index) upperbound(%{{.*}} : index) extent(%[[BOX_DIMS0]]#1 : index) stride(%[[BOX_DIMS0]]#2 : index) startIdx(%{{.*}} : index) {strideInBytes = true} ! CHECK: %[[STRIDE1:.*]] = arith.muli %[[BOX_DIMS0]]#2, %[[BOX_DIMS0]]#1 : index @@ -114,10 +114,10 @@ contains !$acc data attach(a) !$acc end data end subroutine - + ! CHECK-LABEL: func.func @_QMopenacc_boundsPacc_optional_data( ! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>> {fir.bindc_name = "a", fir.optional}) { -! CHECK: %[[ARG0_DECL:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<optional, pointer>, uniq_name = "_QMopenacc_boundsFacc_optional_dataEa"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>) +! CHECK: %[[ARG0_DECL:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<optional, pointer>, uniq_name = "_QMopenacc_boundsFacc_optional_dataEa"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>) ! CHECK: %[[IS_PRESENT:.*]] = fir.is_present %[[ARG0_DECL]]#1 : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>) -> i1 ! CHECK: %[[RES:.*]]:5 = fir.if %[[IS_PRESENT]] -> (index, index, index, index, index) { ! CHECK: %[[LOAD:.*]] = fir.load %[[ARG0_DECL]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>> @@ -140,7 +140,7 @@ contains ! CHECK-LABEL: func.func @_QMopenacc_boundsPacc_optional_data2( ! CHECK-SAME: %[[A:.*]]: !fir.ref<!fir.array<?xf32>> {fir.bindc_name = "a", fir.optional}, %[[N:.*]]: !fir.ref<i32> {fir.bindc_name = "n"}) { -! CHECK: %[[DECL_A:.*]]:2 = hlfir.declare %[[A]](%{{.*}}) dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<optional>, uniq_name = "_QMopenacc_boundsFacc_optional_data2Ea"} : (!fir.ref<!fir.array<?xf32>>, !fir.shape<1>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.ref<!fir.array<?xf32>>) +! CHECK: %[[DECL_A:.*]]:2 = hlfir.declare %[[A]](%{{.*}}) dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<optional>, uniq_name = "_QMopenacc_boundsFacc_optional_data2Ea"} : (!fir.ref<!fir.array<?xf32>>, !fir.shape<1>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.ref<!fir.array<?xf32>>) ! CHECK: %[[NO_CREATE:.*]] = acc.nocreate varPtr(%[[DECL_A]]#1 : !fir.ref<!fir.array<?xf32>>) bounds(%{{[0-9]+}}) -> !fir.ref<!fir.array<?xf32>> {name = "a"} ! CHECK: acc.data dataOperands(%[[NO_CREATE]] : !fir.ref<!fir.array<?xf32>>) { @@ -153,7 +153,7 @@ contains ! CHECK-LABEL: func.func @_QMopenacc_boundsPacc_optional_data3( ! CHECK-SAME: %[[A:.*]]: !fir.ref<!fir.array<?xf32>> {fir.bindc_name = "a", fir.optional}, %[[N:.*]]: !fir.ref<i32> {fir.bindc_name = "n"}) { -! CHECK: %[[DECL_A:.*]]:2 = hlfir.declare %[[A]](%{{.*}}) dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<optional>, uniq_name = "_QMopenacc_boundsFacc_optional_data3Ea"} : (!fir.ref<!fir.array<?xf32>>, !fir.shape<1>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.ref<!fir.array<?xf32>>) +! CHECK: %[[DECL_A:.*]]:2 = hlfir.declare %[[A]](%{{.*}}) dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<optional>, uniq_name = "_QMopenacc_boundsFacc_optional_data3Ea"} : (!fir.ref<!fir.array<?xf32>>, !fir.shape<1>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.ref<!fir.array<?xf32>>) ! CHECK: %[[PRES:.*]] = fir.is_present %[[DECL_A]]#1 : (!fir.ref<!fir.array<?xf32>>) -> i1 ! CHECK: %[[STRIDE:.*]] = fir.if %[[PRES]] -> (index) { ! CHECK: %[[DIMS:.*]]:3 = fir.box_dims %[[DECL_A]]#0, %c0{{.*}} : (!fir.box<!fir.array<?xf32>>, index) -> (index, index, index) diff --git a/flang/test/Lower/OpenACC/acc-data-operands-remapping.f90 b/flang/test/Lower/OpenACC/acc-data-operands-remapping.f90 index 9d36f6a..b657881 100644 --- a/flang/test/Lower/OpenACC/acc-data-operands-remapping.f90 +++ b/flang/test/Lower/OpenACC/acc-data-operands-remapping.f90 @@ -187,11 +187,11 @@ end module ! CHECK-LABEL: func.func @_QMmPtest_scalar( ! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<f32> {fir.bindc_name = "x"}) { ! CHECK: %[[VAL_0:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %[[VAL_0]] {uniq_name = "_QMmFtest_scalarEx"} : (!fir.ref<f32>, !fir.dscope) -> (!fir.ref<f32>, !fir.ref<f32>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %[[VAL_0]] arg {{[0-9]+}} {uniq_name = "_QMmFtest_scalarEx"} : (!fir.ref<f32>, !fir.dscope) -> (!fir.ref<f32>, !fir.ref<f32>) ! CHECK: %[[VAL_2:.*]] = acc.copyin varPtr(%[[VAL_1]]#0 : !fir.ref<f32>) -> !fir.ref<f32> {dataClause = #acc<data_clause acc_copy>, name = "x"} ! CHECK: acc.parallel dataOperands(%[[VAL_2]] : !fir.ref<f32>) { ! CHECK: %[[VAL_3:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_2]] dummy_scope %[[VAL_3]] {uniq_name = "_QMmFtest_scalarEx"} : (!fir.ref<f32>, !fir.dscope) -> (!fir.ref<f32>, !fir.ref<f32>) +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_2]] dummy_scope %[[VAL_3]] arg {{[0-9]+}} {uniq_name = "_QMmFtest_scalarEx"} : (!fir.ref<f32>, !fir.dscope) -> (!fir.ref<f32>, !fir.ref<f32>) ! CHECK: fir.call @_QPtakes_scalar(%[[VAL_4]]#0) fastmath<contract> : (!fir.ref<f32>) -> () ! CHECK: acc.yield ! CHECK: } @@ -203,7 +203,7 @@ end module ! CHECK-SAME: %[[ARG0:.*]]: !fir.boxchar<1> {fir.bindc_name = "c"}, ! CHECK-SAME: %[[ARG1:.*]]: !fir.ref<i32> {fir.bindc_name = "l"}) { ! CHECK: %[[VAL_0:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %[[VAL_0]] {uniq_name = "_QMmFtest_scalar_characterEl"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %[[VAL_0]] arg {{[0-9]+}} {uniq_name = "_QMmFtest_scalar_characterEl"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_2:.*]] = fir.alloca f32 {bindc_name = "x", uniq_name = "_QMmFtest_scalar_characterEx"} ! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]] {uniq_name = "_QMmFtest_scalar_characterEx"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>) ! CHECK: %[[VAL_4:.*]]:2 = fir.unboxchar %[[ARG0]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index) @@ -211,7 +211,7 @@ end module ! CHECK: %[[VAL_6:.*]] = arith.constant 0 : i32 ! CHECK: %[[VAL_7:.*]] = arith.cmpi sgt, %[[VAL_5]], %[[VAL_6]] : i32 ! CHECK: %[[VAL_8:.*]] = arith.select %[[VAL_7]], %[[VAL_5]], %[[VAL_6]] : i32 -! CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[VAL_4]]#0 typeparams %[[VAL_8]] dummy_scope %[[VAL_0]] {uniq_name = "_QMmFtest_scalar_characterEc"} : (!fir.ref<!fir.char<1,?>>, i32, !fir.dscope) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>) +! CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[VAL_4]]#0 typeparams %[[VAL_8]] dummy_scope %[[VAL_0]] arg {{[0-9]+}} {uniq_name = "_QMmFtest_scalar_characterEc"} : (!fir.ref<!fir.char<1,?>>, i32, !fir.dscope) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>) ! CHECK: %[[VAL_10:.*]] = acc.copyin varPtr(%[[VAL_3]]#0 : !fir.ref<f32>) -> !fir.ref<f32> {dataClause = #acc<data_clause acc_copy>, name = "x"} ! CHECK: acc.parallel dataOperands(%[[VAL_10]] : !fir.ref<f32>) { ! CHECK: %[[VAL_11:.*]]:2 = hlfir.declare %[[VAL_10]] {uniq_name = "_QMmFtest_scalar_characterEx"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>) @@ -229,11 +229,11 @@ end module ! CHECK: %[[VAL_0:.*]] = fir.dummy_scope : !fir.dscope ! CHECK: %[[VAL_1:.*]] = arith.constant 100 : index ! CHECK: %[[VAL_2:.*]] = fir.shape %[[VAL_1]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[ARG0]](%[[VAL_2]]) dummy_scope %[[VAL_0]] {uniq_name = "_QMmFtest_cst_shapeEx"} : (!fir.ref<!fir.array<100xf32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100xf32>>, !fir.ref<!fir.array<100xf32>>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[ARG0]](%[[VAL_2]]) dummy_scope %[[VAL_0]] arg {{[0-9]+}} {uniq_name = "_QMmFtest_cst_shapeEx"} : (!fir.ref<!fir.array<100xf32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100xf32>>, !fir.ref<!fir.array<100xf32>>) ! CHECK: %[[VAL_4:.*]] = acc.copyin varPtr(%[[VAL_3]]#0 : !fir.ref<!fir.array<100xf32>>) -> !fir.ref<!fir.array<100xf32>> {dataClause = #acc<data_clause acc_copy>, name = "x"} ! CHECK: acc.parallel dataOperands(%[[VAL_4]] : !fir.ref<!fir.array<100xf32>>) { ! CHECK: %[[VAL_5:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_4]](%[[VAL_2]]) dummy_scope %[[VAL_5]] {uniq_name = "_QMmFtest_cst_shapeEx"} : (!fir.ref<!fir.array<100xf32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100xf32>>, !fir.ref<!fir.array<100xf32>>) +! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_4]](%[[VAL_2]]) dummy_scope %[[VAL_5]] arg {{[0-9]+}} {uniq_name = "_QMmFtest_cst_shapeEx"} : (!fir.ref<!fir.array<100xf32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100xf32>>, !fir.ref<!fir.array<100xf32>>) ! CHECK: fir.call @_QPtakes_explicit_cst_shape(%[[VAL_6]]#0) fastmath<contract> : (!fir.ref<!fir.array<100xf32>>) -> () ! CHECK: acc.yield ! CHECK: } @@ -245,7 +245,7 @@ end module ! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.array<?xf32>> {fir.bindc_name = "x"}, ! CHECK-SAME: %[[ARG1:.*]]: !fir.ref<i32> {fir.bindc_name = "n"}) { ! CHECK: %[[VAL_0:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %[[VAL_0]] {uniq_name = "_QMmFtest_explicit_shapeEn"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %[[VAL_0]] arg {{[0-9]+}} {uniq_name = "_QMmFtest_explicit_shapeEn"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_2:.*]] = fir.load %[[VAL_1]]#0 : !fir.ref<i32> ! CHECK: %[[VAL_3:.*]] = fir.convert %[[VAL_2]] : (i32) -> i64 ! CHECK: %[[VAL_4:.*]] = fir.convert %[[VAL_3]] : (i64) -> index @@ -253,12 +253,12 @@ end module ! CHECK: %[[VAL_6:.*]] = arith.cmpi sgt, %[[VAL_4]], %[[VAL_5]] : index ! CHECK: %[[VAL_7:.*]] = arith.select %[[VAL_6]], %[[VAL_4]], %[[VAL_5]] : index ! CHECK: %[[VAL_8:.*]] = fir.shape %[[VAL_7]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[ARG0]](%[[VAL_8]]) dummy_scope %[[VAL_0]] {uniq_name = "_QMmFtest_explicit_shapeEx"} : (!fir.ref<!fir.array<?xf32>>, !fir.shape<1>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.ref<!fir.array<?xf32>>) +! CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[ARG0]](%[[VAL_8]]) dummy_scope %[[VAL_0]] arg {{[0-9]+}} {uniq_name = "_QMmFtest_explicit_shapeEx"} : (!fir.ref<!fir.array<?xf32>>, !fir.shape<1>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.ref<!fir.array<?xf32>>) ! CHECK: %[[VAL_10:.*]] = acc.copyin var(%[[VAL_9]]#0 : !fir.box<!fir.array<?xf32>>) -> !fir.box<!fir.array<?xf32>> {dataClause = #acc<data_clause acc_copy>, name = "x"} ! CHECK: acc.parallel dataOperands(%[[VAL_10]] : !fir.box<!fir.array<?xf32>>) { ! CHECK: %[[VAL_11:.*]] = fir.box_addr %[[VAL_10]] : (!fir.box<!fir.array<?xf32>>) -> !fir.ref<!fir.array<?xf32>> ! CHECK: %[[VAL_12:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_13:.*]]:2 = hlfir.declare %[[VAL_11]](%[[VAL_8]]) dummy_scope %[[VAL_12]] {uniq_name = "_QMmFtest_explicit_shapeEx"} : (!fir.ref<!fir.array<?xf32>>, !fir.shape<1>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.ref<!fir.array<?xf32>>) +! CHECK: %[[VAL_13:.*]]:2 = hlfir.declare %[[VAL_11]](%[[VAL_8]]) dummy_scope %[[VAL_12]] {{.*}} {uniq_name = "_QMmFtest_explicit_shapeEx"} : (!fir.ref<!fir.array<?xf32>>, !fir.shape<1>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.ref<!fir.array<?xf32>>) ! CHECK: %[[VAL_14:.*]] = fir.convert %[[VAL_7]] : (index) -> i64 ! CHECK: %[[VAL_15:.*]] = fir.convert %[[VAL_14]] : (i64) -> i32 ! CHECK: %[[VAL_16:.*]]:3 = hlfir.associate %[[VAL_15]] {adapt.valuebyref} : (i32) -> (!fir.ref<i32>, !fir.ref<i32>, i1) @@ -274,12 +274,12 @@ end module ! CHECK-SAME: %[[ARG0:.*]]: !fir.box<!fir.array<?xf32>> {fir.bindc_name = "x"}, ! CHECK-SAME: %[[ARG1:.*]]: !fir.ref<i32> {fir.bindc_name = "n"}) { ! CHECK: %[[VAL_0:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %[[VAL_0]] {uniq_name = "_QMmFtest_assumed_shapeEn"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %[[VAL_0]] {uniq_name = "_QMmFtest_assumed_shapeEx"} : (!fir.box<!fir.array<?xf32>>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.box<!fir.array<?xf32>>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %[[VAL_0]] arg {{[0-9]+}} {uniq_name = "_QMmFtest_assumed_shapeEn"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %[[VAL_0]] arg {{[0-9]+}} {uniq_name = "_QMmFtest_assumed_shapeEx"} : (!fir.box<!fir.array<?xf32>>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.box<!fir.array<?xf32>>) ! CHECK: %[[VAL_3:.*]] = acc.copyin var(%[[VAL_2]]#0 : !fir.box<!fir.array<?xf32>>) -> !fir.box<!fir.array<?xf32>> {dataClause = #acc<data_clause acc_copy>, name = "x"} ! CHECK: acc.parallel dataOperands(%[[VAL_3]] : !fir.box<!fir.array<?xf32>>) { ! CHECK: %[[VAL_4:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_3]] dummy_scope %[[VAL_4]] skip_rebox {uniq_name = "_QMmFtest_assumed_shapeEx"} : (!fir.box<!fir.array<?xf32>>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.box<!fir.array<?xf32>>) +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_3]] dummy_scope %[[VAL_4]] arg {{[0-9]+}} skip_rebox {uniq_name = "_QMmFtest_assumed_shapeEx"} : (!fir.box<!fir.array<?xf32>>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.box<!fir.array<?xf32>>) ! CHECK: fir.call @_QPtakes_assumed_shape(%[[VAL_5]]#0) fastmath<contract> : (!fir.box<!fir.array<?xf32>>) -> () ! CHECK: acc.yield ! CHECK: } @@ -291,18 +291,18 @@ end module ! CHECK-SAME: %[[ARG0:.*]]: !fir.box<!fir.array<?xf32>> {fir.bindc_name = "x", fir.contiguous}, ! CHECK-SAME: %[[ARG1:.*]]: !fir.ref<i32> {fir.bindc_name = "n"}) { ! CHECK: %[[VAL_0:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %[[VAL_0]] {uniq_name = "_QMmFtest_contiguous_assumed_shapeEn"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %[[VAL_0]] arg {{[0-9]+}} {uniq_name = "_QMmFtest_contiguous_assumed_shapeEn"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_2:.*]] = fir.box_addr %[[ARG0]] : (!fir.box<!fir.array<?xf32>>) -> !fir.ref<!fir.array<?xf32>> ! CHECK: %[[VAL_3:.*]] = arith.constant 0 : index ! CHECK: %[[VAL_4:.*]]:3 = fir.box_dims %[[ARG0]], %[[VAL_3]] : (!fir.box<!fir.array<?xf32>>, index) -> (index, index, index) ! CHECK: %[[VAL_5:.*]] = arith.constant 1 : index ! CHECK: %[[VAL_6:.*]] = fir.shape_shift %[[VAL_5]], %[[VAL_4]]#1 : (index, index) -> !fir.shapeshift<1> -! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_2]](%[[VAL_6]]) dummy_scope %[[VAL_0]] {fortran_attrs = #fir.var_attrs<contiguous>, uniq_name = "_QMmFtest_contiguous_assumed_shapeEx"} : (!fir.ref<!fir.array<?xf32>>, !fir.shapeshift<1>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.ref<!fir.array<?xf32>>) +! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_2]](%[[VAL_6]]) dummy_scope %[[VAL_0]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<contiguous>, uniq_name = "_QMmFtest_contiguous_assumed_shapeEx"} : (!fir.ref<!fir.array<?xf32>>, !fir.shapeshift<1>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.ref<!fir.array<?xf32>>) ! CHECK: %[[VAL_8:.*]] = acc.copyin var(%[[VAL_7]]#0 : !fir.box<!fir.array<?xf32>>) -> !fir.box<!fir.array<?xf32>> {dataClause = #acc<data_clause acc_copy>, name = "x"} ! CHECK: acc.parallel dataOperands(%[[VAL_8]] : !fir.box<!fir.array<?xf32>>) { ! CHECK: %[[VAL_9:.*]] = fir.box_addr %[[VAL_8]] : (!fir.box<!fir.array<?xf32>>) -> !fir.ref<!fir.array<?xf32>> ! CHECK: %[[VAL_10:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_11:.*]]:2 = hlfir.declare %[[VAL_9]](%[[VAL_6]]) dummy_scope %[[VAL_10]] {fortran_attrs = #fir.var_attrs<contiguous>, uniq_name = "_QMmFtest_contiguous_assumed_shapeEx"} : (!fir.ref<!fir.array<?xf32>>, !fir.shapeshift<1>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.ref<!fir.array<?xf32>>) +! CHECK: %[[VAL_11:.*]]:2 = hlfir.declare %[[VAL_9]](%[[VAL_6]]) dummy_scope %[[VAL_10]] {{.*}} {fortran_attrs = #fir.var_attrs<contiguous>, uniq_name = "_QMmFtest_contiguous_assumed_shapeEx"} : (!fir.ref<!fir.array<?xf32>>, !fir.shapeshift<1>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.ref<!fir.array<?xf32>>) ! CHECK: %[[VAL_12:.*]] = fir.convert %[[VAL_4]]#1 : (index) -> i64 ! CHECK: %[[VAL_13:.*]] = fir.convert %[[VAL_12]] : (i64) -> i32 ! CHECK: %[[VAL_14:.*]]:3 = hlfir.associate %[[VAL_13]] {adapt.valuebyref} : (i32) -> (!fir.ref<i32>, !fir.ref<i32>, i1) @@ -318,12 +318,12 @@ end module ! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>> {fir.bindc_name = "x"}, ! CHECK-SAME: %[[ARG1:.*]]: !fir.ref<i32> {fir.bindc_name = "n"}) { ! CHECK: %[[VAL_0:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %[[VAL_0]] {uniq_name = "_QMmFtest_pointerEn"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %[[VAL_0]] {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QMmFtest_pointerEx"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %[[VAL_0]] arg {{[0-9]+}} {uniq_name = "_QMmFtest_pointerEn"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %[[VAL_0]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QMmFtest_pointerEx"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>) ! CHECK: %[[VAL_3:.*]] = acc.copyin varPtr(%[[VAL_2]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>) -> !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>> {dataClause = #acc<data_clause acc_copy>, name = "x"} ! CHECK: acc.parallel dataOperands(%[[VAL_3]] : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>) { ! CHECK: %[[VAL_4:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_3]] dummy_scope %[[VAL_4]] {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QMmFtest_pointerEx"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>) +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_3]] dummy_scope %[[VAL_4]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QMmFtest_pointerEx"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>) ! CHECK: fir.call @_QPtakes_pointer(%[[VAL_5]]#0) fastmath<contract> : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>) -> () ! CHECK: acc.yield ! CHECK: } @@ -335,7 +335,7 @@ end module ! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.array<?xf32>> {fir.bindc_name = "x"}, ! CHECK-SAME: %[[ARG1:.*]]: !fir.ref<i32> {fir.bindc_name = "n"}) { ! CHECK: %[[VAL_0:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %[[VAL_0]] {uniq_name = "_QMmFtest_using_both_resultsEn"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %[[VAL_0]] arg {{[0-9]+}} {uniq_name = "_QMmFtest_using_both_resultsEn"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_2:.*]] = fir.load %[[VAL_1]]#0 : !fir.ref<i32> ! CHECK: %[[VAL_3:.*]] = fir.convert %[[VAL_2]] : (i32) -> i64 ! CHECK: %[[VAL_4:.*]] = fir.convert %[[VAL_3]] : (i64) -> index @@ -343,12 +343,12 @@ end module ! CHECK: %[[VAL_6:.*]] = arith.cmpi sgt, %[[VAL_4]], %[[VAL_5]] : index ! CHECK: %[[VAL_7:.*]] = arith.select %[[VAL_6]], %[[VAL_4]], %[[VAL_5]] : index ! CHECK: %[[VAL_8:.*]] = fir.shape %[[VAL_7]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[ARG0]](%[[VAL_8]]) dummy_scope %[[VAL_0]] {uniq_name = "_QMmFtest_using_both_resultsEx"} : (!fir.ref<!fir.array<?xf32>>, !fir.shape<1>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.ref<!fir.array<?xf32>>) +! CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[ARG0]](%[[VAL_8]]) dummy_scope %[[VAL_0]] arg {{[0-9]+}} {uniq_name = "_QMmFtest_using_both_resultsEx"} : (!fir.ref<!fir.array<?xf32>>, !fir.shape<1>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.ref<!fir.array<?xf32>>) ! CHECK: %[[VAL_10:.*]] = acc.copyin var(%[[VAL_9]]#0 : !fir.box<!fir.array<?xf32>>) -> !fir.box<!fir.array<?xf32>> {dataClause = #acc<data_clause acc_copy>, name = "x"} ! CHECK: acc.parallel dataOperands(%[[VAL_10]] : !fir.box<!fir.array<?xf32>>) { ! CHECK: %[[VAL_11:.*]] = fir.box_addr %[[VAL_10]] : (!fir.box<!fir.array<?xf32>>) -> !fir.ref<!fir.array<?xf32>> ! CHECK: %[[VAL_12:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_13:.*]]:2 = hlfir.declare %[[VAL_11]](%[[VAL_8]]) dummy_scope %[[VAL_12]] {uniq_name = "_QMmFtest_using_both_resultsEx"} : (!fir.ref<!fir.array<?xf32>>, !fir.shape<1>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.ref<!fir.array<?xf32>>) +! CHECK: %[[VAL_13:.*]]:2 = hlfir.declare %[[VAL_11]](%[[VAL_8]]) dummy_scope %[[VAL_12]] {{.*}} {uniq_name = "_QMmFtest_using_both_resultsEx"} : (!fir.ref<!fir.array<?xf32>>, !fir.shape<1>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.ref<!fir.array<?xf32>>) ! CHECK: fir.call @_QPtakes_assumed_shape(%[[VAL_13]]#0) fastmath<contract> : (!fir.box<!fir.array<?xf32>>) -> () ! CHECK: %[[VAL_14:.*]] = fir.convert %[[VAL_7]] : (index) -> i64 ! CHECK: %[[VAL_15:.*]] = fir.convert %[[VAL_14]] : (i64) -> i32 @@ -367,11 +367,11 @@ end module ! CHECK: %[[VAL_1:.*]] = arith.constant 10 : index ! CHECK: %[[VAL_2:.*]] = arith.constant 20 : index ! CHECK: %[[VAL_3:.*]] = fir.shape %[[VAL_1]], %[[VAL_2]] : (index, index) -> !fir.shape<2> -! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[ARG0]](%[[VAL_3]]) dummy_scope %[[VAL_0]] {uniq_name = "_QMmFaddressing_cst_shapeEx"} : (!fir.ref<!fir.array<10x20xf32>>, !fir.shape<2>, !fir.dscope) -> (!fir.ref<!fir.array<10x20xf32>>, !fir.ref<!fir.array<10x20xf32>>) +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[ARG0]](%[[VAL_3]]) dummy_scope %[[VAL_0]] arg {{[0-9]+}} {uniq_name = "_QMmFaddressing_cst_shapeEx"} : (!fir.ref<!fir.array<10x20xf32>>, !fir.shape<2>, !fir.dscope) -> (!fir.ref<!fir.array<10x20xf32>>, !fir.ref<!fir.array<10x20xf32>>) ! CHECK: %[[VAL_5:.*]] = acc.copyin varPtr(%[[VAL_4]]#0 : !fir.ref<!fir.array<10x20xf32>>) -> !fir.ref<!fir.array<10x20xf32>> {dataClause = #acc<data_clause acc_copy>, name = "x"} ! CHECK: acc.parallel dataOperands(%[[VAL_5]] : !fir.ref<!fir.array<10x20xf32>>) { ! CHECK: %[[VAL_6:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_5]](%[[VAL_3]]) dummy_scope %[[VAL_6]] {uniq_name = "_QMmFaddressing_cst_shapeEx"} : (!fir.ref<!fir.array<10x20xf32>>, !fir.shape<2>, !fir.dscope) -> (!fir.ref<!fir.array<10x20xf32>>, !fir.ref<!fir.array<10x20xf32>>) +! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_5]](%[[VAL_3]]) dummy_scope %[[VAL_6]] {{.*}} {uniq_name = "_QMmFaddressing_cst_shapeEx"} : (!fir.ref<!fir.array<10x20xf32>>, !fir.shape<2>, !fir.dscope) -> (!fir.ref<!fir.array<10x20xf32>>, !fir.ref<!fir.array<10x20xf32>>) ! CHECK: %[[VAL_8:.*]] = arith.constant 2 : index ! CHECK: %[[VAL_9:.*]] = arith.constant 3 : index ! CHECK: %[[VAL_10:.*]] = hlfir.designate %[[VAL_7]]#0 (%[[VAL_8]], %[[VAL_9]]) : (!fir.ref<!fir.array<10x20xf32>>, index, index) -> !fir.ref<f32> @@ -387,8 +387,8 @@ end module ! CHECK-SAME: %[[ARG1:.*]]: !fir.ref<i32> {fir.bindc_name = "n"}, ! CHECK-SAME: %[[ARG2:.*]]: !fir.ref<i32> {fir.bindc_name = "m"}) { ! CHECK: %[[VAL_0:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[ARG2]] dummy_scope %[[VAL_0]] {uniq_name = "_QMmFaddressing_explicit_shapeEm"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %[[VAL_0]] {uniq_name = "_QMmFaddressing_explicit_shapeEn"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[ARG2]] dummy_scope %[[VAL_0]] arg {{[0-9]+}} {uniq_name = "_QMmFaddressing_explicit_shapeEm"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %[[VAL_0]] arg {{[0-9]+}} {uniq_name = "_QMmFaddressing_explicit_shapeEn"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_3:.*]] = fir.load %[[VAL_2]]#0 : !fir.ref<i32> ! CHECK: %[[VAL_4:.*]] = fir.convert %[[VAL_3]] : (i32) -> i64 ! CHECK: %[[VAL_5:.*]] = fir.convert %[[VAL_4]] : (i64) -> index @@ -402,12 +402,12 @@ end module ! CHECK: %[[VAL_13:.*]] = arith.cmpi sgt, %[[VAL_11]], %[[VAL_12]] : index ! CHECK: %[[VAL_14:.*]] = arith.select %[[VAL_13]], %[[VAL_11]], %[[VAL_12]] : index ! CHECK: %[[VAL_15:.*]] = fir.shape %[[VAL_8]], %[[VAL_14]] : (index, index) -> !fir.shape<2> -! CHECK: %[[VAL_16:.*]]:2 = hlfir.declare %[[ARG0]](%[[VAL_15]]) dummy_scope %[[VAL_0]] {uniq_name = "_QMmFaddressing_explicit_shapeEx"} : (!fir.ref<!fir.array<?x?xf32>>, !fir.shape<2>, !fir.dscope) -> (!fir.box<!fir.array<?x?xf32>>, !fir.ref<!fir.array<?x?xf32>>) +! CHECK: %[[VAL_16:.*]]:2 = hlfir.declare %[[ARG0]](%[[VAL_15]]) dummy_scope %[[VAL_0]] arg {{[0-9]+}} {uniq_name = "_QMmFaddressing_explicit_shapeEx"} : (!fir.ref<!fir.array<?x?xf32>>, !fir.shape<2>, !fir.dscope) -> (!fir.box<!fir.array<?x?xf32>>, !fir.ref<!fir.array<?x?xf32>>) ! CHECK: %[[VAL_17:.*]] = acc.copyin var(%[[VAL_16]]#0 : !fir.box<!fir.array<?x?xf32>>) -> !fir.box<!fir.array<?x?xf32>> {dataClause = #acc<data_clause acc_copy>, name = "x"} ! CHECK: acc.parallel dataOperands(%[[VAL_17]] : !fir.box<!fir.array<?x?xf32>>) { ! CHECK: %[[VAL_18:.*]] = fir.box_addr %[[VAL_17]] : (!fir.box<!fir.array<?x?xf32>>) -> !fir.ref<!fir.array<?x?xf32>> ! CHECK: %[[VAL_19:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_20:.*]]:2 = hlfir.declare %[[VAL_18]](%[[VAL_15]]) dummy_scope %[[VAL_19]] {uniq_name = "_QMmFaddressing_explicit_shapeEx"} : (!fir.ref<!fir.array<?x?xf32>>, !fir.shape<2>, !fir.dscope) -> (!fir.box<!fir.array<?x?xf32>>, !fir.ref<!fir.array<?x?xf32>>) +! CHECK: %[[VAL_20:.*]]:2 = hlfir.declare %[[VAL_18]](%[[VAL_15]]) dummy_scope %[[VAL_19]] {{.*}} {uniq_name = "_QMmFaddressing_explicit_shapeEx"} : (!fir.ref<!fir.array<?x?xf32>>, !fir.shape<2>, !fir.dscope) -> (!fir.box<!fir.array<?x?xf32>>, !fir.ref<!fir.array<?x?xf32>>) ! CHECK: %[[VAL_21:.*]] = arith.constant 2 : index ! CHECK: %[[VAL_22:.*]] = arith.constant 3 : index ! CHECK: %[[VAL_23:.*]] = hlfir.designate %[[VAL_20]]#0 (%[[VAL_21]], %[[VAL_22]]) : (!fir.box<!fir.array<?x?xf32>>, index, index) -> !fir.ref<f32> @@ -422,12 +422,12 @@ end module ! CHECK-SAME: %[[ARG0:.*]]: !fir.box<!fir.array<?x?xf32>> {fir.bindc_name = "x"}, ! CHECK-SAME: %[[ARG1:.*]]: !fir.ref<i32> {fir.bindc_name = "n"}) { ! CHECK: %[[VAL_0:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %[[VAL_0]] {uniq_name = "_QMmFaddressing_assumed_shapeEn"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %[[VAL_0]] {uniq_name = "_QMmFaddressing_assumed_shapeEx"} : (!fir.box<!fir.array<?x?xf32>>, !fir.dscope) -> (!fir.box<!fir.array<?x?xf32>>, !fir.box<!fir.array<?x?xf32>>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %[[VAL_0]] arg {{[0-9]+}} {uniq_name = "_QMmFaddressing_assumed_shapeEn"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %[[VAL_0]] arg {{[0-9]+}} {uniq_name = "_QMmFaddressing_assumed_shapeEx"} : (!fir.box<!fir.array<?x?xf32>>, !fir.dscope) -> (!fir.box<!fir.array<?x?xf32>>, !fir.box<!fir.array<?x?xf32>>) ! CHECK: %[[VAL_3:.*]] = acc.copyin var(%[[VAL_2]]#0 : !fir.box<!fir.array<?x?xf32>>) -> !fir.box<!fir.array<?x?xf32>> {dataClause = #acc<data_clause acc_copy>, name = "x"} ! CHECK: acc.parallel dataOperands(%[[VAL_3]] : !fir.box<!fir.array<?x?xf32>>) { ! CHECK: %[[VAL_4:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_3]] dummy_scope %[[VAL_4]] skip_rebox {uniq_name = "_QMmFaddressing_assumed_shapeEx"} : (!fir.box<!fir.array<?x?xf32>>, !fir.dscope) -> (!fir.box<!fir.array<?x?xf32>>, !fir.box<!fir.array<?x?xf32>>) +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_3]] dummy_scope %[[VAL_4]] arg {{[0-9]+}} skip_rebox {uniq_name = "_QMmFaddressing_assumed_shapeEx"} : (!fir.box<!fir.array<?x?xf32>>, !fir.dscope) -> (!fir.box<!fir.array<?x?xf32>>, !fir.box<!fir.array<?x?xf32>>) ! CHECK: %[[VAL_6:.*]] = arith.constant 2 : index ! CHECK: %[[VAL_7:.*]] = arith.constant 3 : index ! CHECK: %[[VAL_8:.*]] = hlfir.designate %[[VAL_5]]#0 (%[[VAL_6]], %[[VAL_7]]) : (!fir.box<!fir.array<?x?xf32>>, index, index) -> !fir.ref<f32> @@ -442,7 +442,7 @@ end module ! CHECK-SAME: %[[ARG0:.*]]: !fir.box<!fir.array<?x?xf32>> {fir.bindc_name = "x", fir.contiguous}, ! CHECK-SAME: %[[ARG1:.*]]: !fir.ref<i32> {fir.bindc_name = "n"}) { ! CHECK: %[[VAL_0:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %[[VAL_0]] {uniq_name = "_QMmFaddressing_contiguous_assumed_shapeEn"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %[[VAL_0]] arg {{[0-9]+}} {uniq_name = "_QMmFaddressing_contiguous_assumed_shapeEn"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_2:.*]] = fir.box_addr %[[ARG0]] : (!fir.box<!fir.array<?x?xf32>>) -> !fir.ref<!fir.array<?x?xf32>> ! CHECK: %[[VAL_3:.*]] = arith.constant 0 : index ! CHECK: %[[VAL_4:.*]]:3 = fir.box_dims %[[ARG0]], %[[VAL_3]] : (!fir.box<!fir.array<?x?xf32>>, index) -> (index, index, index) @@ -451,12 +451,12 @@ end module ! CHECK: %[[VAL_7:.*]]:3 = fir.box_dims %[[ARG0]], %[[VAL_6]] : (!fir.box<!fir.array<?x?xf32>>, index) -> (index, index, index) ! CHECK: %[[VAL_8:.*]] = arith.constant 1 : index ! CHECK: %[[VAL_9:.*]] = fir.shape_shift %[[VAL_5]], %[[VAL_4]]#1, %[[VAL_8]], %[[VAL_7]]#1 : (index, index, index, index) -> !fir.shapeshift<2> -! CHECK: %[[VAL_10:.*]]:2 = hlfir.declare %[[VAL_2]](%[[VAL_9]]) dummy_scope %[[VAL_0]] {fortran_attrs = #fir.var_attrs<contiguous>, uniq_name = "_QMmFaddressing_contiguous_assumed_shapeEx"} : (!fir.ref<!fir.array<?x?xf32>>, !fir.shapeshift<2>, !fir.dscope) -> (!fir.box<!fir.array<?x?xf32>>, !fir.ref<!fir.array<?x?xf32>>) +! CHECK: %[[VAL_10:.*]]:2 = hlfir.declare %[[VAL_2]](%[[VAL_9]]) dummy_scope %[[VAL_0]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<contiguous>, uniq_name = "_QMmFaddressing_contiguous_assumed_shapeEx"} : (!fir.ref<!fir.array<?x?xf32>>, !fir.shapeshift<2>, !fir.dscope) -> (!fir.box<!fir.array<?x?xf32>>, !fir.ref<!fir.array<?x?xf32>>) ! CHECK: %[[VAL_11:.*]] = acc.copyin var(%[[VAL_10]]#0 : !fir.box<!fir.array<?x?xf32>>) -> !fir.box<!fir.array<?x?xf32>> {dataClause = #acc<data_clause acc_copy>, name = "x"} ! CHECK: acc.parallel dataOperands(%[[VAL_11]] : !fir.box<!fir.array<?x?xf32>>) { ! CHECK: %[[VAL_12:.*]] = fir.box_addr %[[VAL_11]] : (!fir.box<!fir.array<?x?xf32>>) -> !fir.ref<!fir.array<?x?xf32>> ! CHECK: %[[VAL_13:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_14:.*]]:2 = hlfir.declare %[[VAL_12]](%[[VAL_9]]) dummy_scope %[[VAL_13]] {fortran_attrs = #fir.var_attrs<contiguous>, uniq_name = "_QMmFaddressing_contiguous_assumed_shapeEx"} : (!fir.ref<!fir.array<?x?xf32>>, !fir.shapeshift<2>, !fir.dscope) -> (!fir.box<!fir.array<?x?xf32>>, !fir.ref<!fir.array<?x?xf32>>) +! CHECK: %[[VAL_14:.*]]:2 = hlfir.declare %[[VAL_12]](%[[VAL_9]]) dummy_scope %[[VAL_13]] {{.*}} {fortran_attrs = #fir.var_attrs<contiguous>, uniq_name = "_QMmFaddressing_contiguous_assumed_shapeEx"} : (!fir.ref<!fir.array<?x?xf32>>, !fir.shapeshift<2>, !fir.dscope) -> (!fir.box<!fir.array<?x?xf32>>, !fir.ref<!fir.array<?x?xf32>>) ! CHECK: %[[VAL_15:.*]] = arith.constant 2 : index ! CHECK: %[[VAL_16:.*]] = arith.constant 3 : index ! CHECK: %[[VAL_17:.*]] = hlfir.designate %[[VAL_14]]#0 (%[[VAL_15]], %[[VAL_16]]) : (!fir.box<!fir.array<?x?xf32>>, index, index) -> !fir.ref<f32> @@ -470,11 +470,11 @@ end module ! CHECK-LABEL: func.func @_QMmPaddressing_pointer( ! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.box<!fir.ptr<!fir.array<?x?xf32>>>> {fir.bindc_name = "x"}) { ! CHECK: %[[VAL_0:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %[[VAL_0]] {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QMmFaddressing_pointerEx"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?x?xf32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?x?xf32>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?x?xf32>>>>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %[[VAL_0]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QMmFaddressing_pointerEx"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?x?xf32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?x?xf32>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?x?xf32>>>>) ! CHECK: %[[VAL_2:.*]] = acc.copyin varPtr(%[[VAL_1]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?x?xf32>>>>) -> !fir.ref<!fir.box<!fir.ptr<!fir.array<?x?xf32>>>> {dataClause = #acc<data_clause acc_copy>, name = "x"} ! CHECK: acc.parallel dataOperands(%[[VAL_2]] : !fir.ref<!fir.box<!fir.ptr<!fir.array<?x?xf32>>>>) { ! CHECK: %[[VAL_3:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_2]] dummy_scope %[[VAL_3]] {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QMmFaddressing_pointerEx"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?x?xf32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?x?xf32>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?x?xf32>>>>) +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_2]] dummy_scope %[[VAL_3]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QMmFaddressing_pointerEx"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?x?xf32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?x?xf32>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?x?xf32>>>>) ! CHECK: %[[VAL_5:.*]] = fir.load %[[VAL_4]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?x?xf32>>>> ! CHECK: %[[VAL_6:.*]] = arith.constant 2 : index ! CHECK: %[[VAL_7:.*]] = arith.constant 3 : index @@ -489,11 +489,11 @@ end module ! CHECK-LABEL: func.func @_QMmPtest_optional_scalar( ! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<f32> {fir.bindc_name = "x", fir.optional}) { ! CHECK: %[[VAL_0:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %[[VAL_0]] {fortran_attrs = #fir.var_attrs<optional>, uniq_name = "_QMmFtest_optional_scalarEx"} : (!fir.ref<f32>, !fir.dscope) -> (!fir.ref<f32>, !fir.ref<f32>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %[[VAL_0]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<optional>, uniq_name = "_QMmFtest_optional_scalarEx"} : (!fir.ref<f32>, !fir.dscope) -> (!fir.ref<f32>, !fir.ref<f32>) ! CHECK: %[[VAL_2:.*]] = acc.copyin varPtr(%[[VAL_1]]#0 : !fir.ref<f32>) -> !fir.ref<f32> {dataClause = #acc<data_clause acc_copy>, name = "x"} ! CHECK: acc.parallel dataOperands(%[[VAL_2]] : !fir.ref<f32>) { ! CHECK: %[[VAL_3:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_2]] dummy_scope %[[VAL_3]] {fortran_attrs = #fir.var_attrs<optional>, uniq_name = "_QMmFtest_optional_scalarEx"} : (!fir.ref<f32>, !fir.dscope) -> (!fir.ref<f32>, !fir.ref<f32>) +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_2]] dummy_scope %[[VAL_3]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<optional>, uniq_name = "_QMmFtest_optional_scalarEx"} : (!fir.ref<f32>, !fir.dscope) -> (!fir.ref<f32>, !fir.ref<f32>) ! CHECK: %[[VAL_5:.*]] = fir.is_present %[[VAL_4]]#0 : (!fir.ref<f32>) -> i1 ! CHECK: %[[VAL_6:.*]] = fir.if %[[VAL_5]] -> (!fir.ref<f32>) { ! CHECK: fir.result %[[VAL_4]]#0 : !fir.ref<f32> @@ -513,11 +513,11 @@ end module ! CHECK: %[[VAL_0:.*]] = fir.dummy_scope : !fir.dscope ! CHECK: %[[VAL_1:.*]] = arith.constant 100 : index ! CHECK: %[[VAL_2:.*]] = fir.shape %[[VAL_1]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[ARG0]](%[[VAL_2]]) dummy_scope %[[VAL_0]] {fortran_attrs = #fir.var_attrs<optional>, uniq_name = "_QMmFtest_optional_explicit_cst_shapeEx"} : (!fir.ref<!fir.array<100xf32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100xf32>>, !fir.ref<!fir.array<100xf32>>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[ARG0]](%[[VAL_2]]) dummy_scope %[[VAL_0]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<optional>, uniq_name = "_QMmFtest_optional_explicit_cst_shapeEx"} : (!fir.ref<!fir.array<100xf32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100xf32>>, !fir.ref<!fir.array<100xf32>>) ! CHECK: %[[VAL_4:.*]] = acc.copyin varPtr(%[[VAL_3]]#0 : !fir.ref<!fir.array<100xf32>>) -> !fir.ref<!fir.array<100xf32>> {dataClause = #acc<data_clause acc_copy>, name = "x"} ! CHECK: acc.parallel dataOperands(%[[VAL_4]] : !fir.ref<!fir.array<100xf32>>) { ! CHECK: %[[VAL_5:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_4]](%[[VAL_2]]) dummy_scope %[[VAL_5]] {fortran_attrs = #fir.var_attrs<optional>, uniq_name = "_QMmFtest_optional_explicit_cst_shapeEx"} : (!fir.ref<!fir.array<100xf32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100xf32>>, !fir.ref<!fir.array<100xf32>>) +! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_4]](%[[VAL_2]]) dummy_scope %[[VAL_5]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<optional>, uniq_name = "_QMmFtest_optional_explicit_cst_shapeEx"} : (!fir.ref<!fir.array<100xf32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100xf32>>, !fir.ref<!fir.array<100xf32>>) ! CHECK: %[[VAL_7:.*]] = fir.is_present %[[VAL_6]]#0 : (!fir.ref<!fir.array<100xf32>>) -> i1 ! CHECK: %[[VAL_8:.*]] = fir.if %[[VAL_7]] -> (!fir.ref<!fir.array<100xf32>>) { ! CHECK: fir.result %[[VAL_6]]#0 : !fir.ref<!fir.array<100xf32>> @@ -536,7 +536,7 @@ end module ! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.array<?xf32>> {fir.bindc_name = "x", fir.optional}, ! CHECK-SAME: %[[ARG1:.*]]: !fir.ref<i32> {fir.bindc_name = "n"}) { ! CHECK: %[[VAL_0:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %[[VAL_0]] {uniq_name = "_QMmFtest_optional_explicit_shapeEn"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %[[VAL_0]] arg {{[0-9]+}} {uniq_name = "_QMmFtest_optional_explicit_shapeEn"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_2:.*]] = fir.load %[[VAL_1]]#0 : !fir.ref<i32> ! CHECK: %[[VAL_3:.*]] = fir.convert %[[VAL_2]] : (i32) -> i64 ! CHECK: %[[VAL_4:.*]] = fir.convert %[[VAL_3]] : (i64) -> index @@ -544,11 +544,11 @@ end module ! CHECK: %[[VAL_6:.*]] = arith.cmpi sgt, %[[VAL_4]], %[[VAL_5]] : index ! CHECK: %[[VAL_7:.*]] = arith.select %[[VAL_6]], %[[VAL_4]], %[[VAL_5]] : index ! CHECK: %[[VAL_8:.*]] = fir.shape %[[VAL_7]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[ARG0]](%[[VAL_8]]) dummy_scope %[[VAL_0]] {fortran_attrs = #fir.var_attrs<optional>, uniq_name = "_QMmFtest_optional_explicit_shapeEx"} : (!fir.ref<!fir.array<?xf32>>, !fir.shape<1>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.ref<!fir.array<?xf32>>) +! CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[ARG0]](%[[VAL_8]]) dummy_scope %[[VAL_0]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<optional>, uniq_name = "_QMmFtest_optional_explicit_shapeEx"} : (!fir.ref<!fir.array<?xf32>>, !fir.shape<1>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.ref<!fir.array<?xf32>>) ! CHECK: %[[VAL_10:.*]] = acc.copyin varPtr(%[[VAL_9]]#1 : !fir.ref<!fir.array<?xf32>>) -> !fir.ref<!fir.array<?xf32>> {dataClause = #acc<data_clause acc_copy>, name = "x"} ! CHECK: acc.parallel dataOperands(%[[VAL_10]] : !fir.ref<!fir.array<?xf32>>) { ! CHECK: %[[VAL_11:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_12:.*]]:2 = hlfir.declare %[[VAL_10]](%[[VAL_8]]) dummy_scope %[[VAL_11]] {fortran_attrs = #fir.var_attrs<optional>, uniq_name = "_QMmFtest_optional_explicit_shapeEx"} : (!fir.ref<!fir.array<?xf32>>, !fir.shape<1>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.ref<!fir.array<?xf32>>) +! CHECK: %[[VAL_12:.*]]:2 = hlfir.declare %[[VAL_10]](%[[VAL_8]]) dummy_scope %[[VAL_11]] {{.*}} {fortran_attrs = #fir.var_attrs<optional>, uniq_name = "_QMmFtest_optional_explicit_shapeEx"} : (!fir.ref<!fir.array<?xf32>>, !fir.shape<1>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.ref<!fir.array<?xf32>>) ! CHECK: %[[VAL_13:.*]] = fir.is_present %[[VAL_12]]#0 : (!fir.box<!fir.array<?xf32>>) -> i1 ! CHECK: %[[VAL_14:.*]] = fir.if %[[VAL_13]] -> (!fir.ref<!fir.array<?xf32>>) { ! CHECK: fir.result %[[VAL_12]]#1 : !fir.ref<!fir.array<?xf32>> @@ -566,11 +566,11 @@ end module ! CHECK-LABEL: func.func @_QMmPtest_optional_assumed_shape( ! CHECK-SAME: %[[ARG0:.*]]: !fir.box<!fir.array<?xf32>> {fir.bindc_name = "x", fir.optional}) { ! CHECK: %[[VAL_0:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %[[VAL_0]] {fortran_attrs = #fir.var_attrs<optional>, uniq_name = "_QMmFtest_optional_assumed_shapeEx"} : (!fir.box<!fir.array<?xf32>>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.box<!fir.array<?xf32>>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %[[VAL_0]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<optional>, uniq_name = "_QMmFtest_optional_assumed_shapeEx"} : (!fir.box<!fir.array<?xf32>>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.box<!fir.array<?xf32>>) ! CHECK: %[[VAL_2:.*]] = acc.copyin var(%[[VAL_1]]#0 : !fir.box<!fir.array<?xf32>>) -> !fir.box<!fir.array<?xf32>> {dataClause = #acc<data_clause acc_copy>, name = "x"} ! CHECK: acc.parallel dataOperands(%[[VAL_2]] : !fir.box<!fir.array<?xf32>>) { ! CHECK: %[[VAL_3:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_2]] dummy_scope %[[VAL_3]] skip_rebox {fortran_attrs = #fir.var_attrs<optional>, uniq_name = "_QMmFtest_optional_assumed_shapeEx"} : (!fir.box<!fir.array<?xf32>>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.box<!fir.array<?xf32>>) +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_2]] dummy_scope %[[VAL_3]] arg {{[0-9]+}} skip_rebox {fortran_attrs = #fir.var_attrs<optional>, uniq_name = "_QMmFtest_optional_assumed_shapeEx"} : (!fir.box<!fir.array<?xf32>>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.box<!fir.array<?xf32>>) ! CHECK: %[[VAL_5:.*]] = fir.is_present %[[VAL_4]]#0 : (!fir.box<!fir.array<?xf32>>) -> i1 ! CHECK: %[[VAL_6:.*]] = fir.if %[[VAL_5]] -> (!fir.box<!fir.array<?xf32>>) { ! CHECK: fir.result %[[VAL_4]]#0 : !fir.box<!fir.array<?xf32>> @@ -588,11 +588,11 @@ end module ! CHECK-LABEL: func.func @_QMmPtest_optional_pointer( ! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>> {fir.bindc_name = "x", fir.optional}) { ! CHECK: %[[VAL_0:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %[[VAL_0]] {fortran_attrs = #fir.var_attrs<optional, pointer>, uniq_name = "_QMmFtest_optional_pointerEx"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %[[VAL_0]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<optional, pointer>, uniq_name = "_QMmFtest_optional_pointerEx"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>) ! CHECK: %[[VAL_2:.*]] = acc.copyin varPtr(%[[VAL_1]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>) -> !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>> {dataClause = #acc<data_clause acc_copy>, name = "x"} ! CHECK: acc.parallel dataOperands(%[[VAL_2]] : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>) { ! CHECK: %[[VAL_3:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_2]] dummy_scope %[[VAL_3]] {fortran_attrs = #fir.var_attrs<optional, pointer>, uniq_name = "_QMmFtest_optional_pointerEx"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>) +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_2]] dummy_scope %[[VAL_3]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<optional, pointer>, uniq_name = "_QMmFtest_optional_pointerEx"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>) ! CHECK: fir.call @_QPtakes_optional_pointer(%[[VAL_4]]#0) fastmath<contract> : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>) -> () ! CHECK: acc.yield ! CHECK: } diff --git a/flang/test/Lower/OpenACC/acc-declare.f90 b/flang/test/Lower/OpenACC/acc-declare.f90 index 46c4365..98f7ed3 100644 --- a/flang/test/Lower/OpenACC/acc-declare.f90 +++ b/flang/test/Lower/OpenACC/acc-declare.f90 @@ -57,7 +57,7 @@ module acc_declare ! CHECK-LABEL: func.func @_QMacc_declarePacc_declare_present( ! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.array<100xi32>> {fir.bindc_name = "a"}) -! CHECK: %[[DECL:.*]]:2 = hlfir.declare %[[ARG0]](%{{.*}}) dummy_scope %{{[0-9]+}} {acc.declare = #acc.declare<dataClause = acc_present>, uniq_name = "_QMacc_declareFacc_declare_presentEa"} : (!fir.ref<!fir.array<100xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100xi32>>, !fir.ref<!fir.array<100xi32>>) +! CHECK: %[[DECL:.*]]:2 = hlfir.declare %[[ARG0]](%{{.*}}) dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {acc.declare = #acc.declare<dataClause = acc_present>, uniq_name = "_QMacc_declareFacc_declare_presentEa"} : (!fir.ref<!fir.array<100xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100xi32>>, !fir.ref<!fir.array<100xi32>>) ! CHECK: %[[PRESENT:.*]] = acc.present varPtr(%[[DECL]]#0 : !fir.ref<!fir.array<100xi32>>) -> !fir.ref<!fir.array<100xi32>> {name = "a"} ! CHECK: %[[TOKEN:.*]] = acc.declare_enter dataOperands(%[[PRESENT]] : !fir.ref<!fir.array<100xi32>>) ! CHECK: %{{.*}} = fir.do_loop %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} iter_args(%arg{{.*}} = %{{.*}}) -> (i32) @@ -115,7 +115,7 @@ module acc_declare ! CHECK-LABEL: func.func @_QMacc_declarePacc_declare_deviceptr( ! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.array<100xi32>> {fir.bindc_name = "a"}) { -! CHECK: %[[DECL:.*]]:2 = hlfir.declare %[[ARG0]](%{{.*}}) dummy_scope %{{[0-9]+}} {acc.declare = #acc.declare<dataClause = acc_deviceptr>, uniq_name = "_QMacc_declareFacc_declare_deviceptrEa"} : (!fir.ref<!fir.array<100xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100xi32>>, !fir.ref<!fir.array<100xi32>>) +! CHECK: %[[DECL:.*]]:2 = hlfir.declare %[[ARG0]](%{{.*}}) dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {acc.declare = #acc.declare<dataClause = acc_deviceptr>, uniq_name = "_QMacc_declareFacc_declare_deviceptrEa"} : (!fir.ref<!fir.array<100xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100xi32>>, !fir.ref<!fir.array<100xi32>>) ! CHECK: %[[DEVICEPTR:.*]] = acc.deviceptr varPtr(%[[DECL]]#0 : !fir.ref<!fir.array<100xi32>>) -> !fir.ref<!fir.array<100xi32>> {name = "a"} ! CHECK: acc.declare_enter dataOperands(%[[DEVICEPTR]] : !fir.ref<!fir.array<100xi32>>) ! CHECK: %{{.*}} = fir.do_loop %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} iter_args(%arg{{.*}} = %{{.*}}) -> (i32) @@ -131,7 +131,7 @@ module acc_declare ! CHECK-LABEL: func.func @_QMacc_declarePacc_declare_link( ! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.array<100xi32>> {fir.bindc_name = "a"}) -! CHECK: %[[DECL:.*]]:2 = hlfir.declare %[[ARG0]](%{{.*}}) dummy_scope %{{[0-9]+}} {acc.declare = #acc.declare<dataClause = acc_declare_link>, uniq_name = "_QMacc_declareFacc_declare_linkEa"} : (!fir.ref<!fir.array<100xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100xi32>>, !fir.ref<!fir.array<100xi32>>) +! CHECK: %[[DECL:.*]]:2 = hlfir.declare %[[ARG0]](%{{.*}}) dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {acc.declare = #acc.declare<dataClause = acc_declare_link>, uniq_name = "_QMacc_declareFacc_declare_linkEa"} : (!fir.ref<!fir.array<100xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100xi32>>, !fir.ref<!fir.array<100xi32>>) ! CHECK: %[[LINK:.*]] = acc.declare_link varPtr(%[[DECL]]#0 : !fir.ref<!fir.array<100xi32>>) -> !fir.ref<!fir.array<100xi32>> {name = "a"} ! CHECK: acc.declare_enter dataOperands(%[[LINK]] : !fir.ref<!fir.array<100xi32>>) ! CHECK: %{{.*}} = fir.do_loop %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} iter_args(%arg{{.*}} = %{{.*}}) -> (i32) @@ -147,7 +147,7 @@ module acc_declare ! CHECK-LABEL: func.func @_QMacc_declarePacc_declare_device_resident( ! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.array<100xi32>> {fir.bindc_name = "a"}) -! CHECK: %[[DECL:.*]]:2 = hlfir.declare %[[ARG0]](%{{.*}}) dummy_scope %{{[0-9]+}} {acc.declare = #acc.declare<dataClause = acc_declare_device_resident>, uniq_name = "_QMacc_declareFacc_declare_device_residentEa"} : (!fir.ref<!fir.array<100xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100xi32>>, !fir.ref<!fir.array<100xi32>>) +! CHECK: %[[DECL:.*]]:2 = hlfir.declare %[[ARG0]](%{{.*}}) dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {acc.declare = #acc.declare<dataClause = acc_declare_device_resident>, uniq_name = "_QMacc_declareFacc_declare_device_residentEa"} : (!fir.ref<!fir.array<100xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100xi32>>, !fir.ref<!fir.array<100xi32>>) ! CHECK: %[[DEVICERES:.*]] = acc.declare_device_resident varPtr(%[[DECL]]#0 : !fir.ref<!fir.array<100xi32>>) -> !fir.ref<!fir.array<100xi32>> {name = "a"} ! CHECK: %[[TOKEN:.*]] = acc.declare_enter dataOperands(%[[DEVICERES]] : !fir.ref<!fir.array<100xi32>>) ! CHECK: %{{.*}} = fir.do_loop %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} iter_args(%arg{{.*}} = %{{.*}}) -> (i32) @@ -274,8 +274,8 @@ module acc_declare ! CHECK-LABEL: func.func @_QMacc_declarePacc_declare_multiple_directive( ! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.array<100xi32>> {fir.bindc_name = "a"}, %[[ARG1:.*]]: !fir.ref<!fir.array<100xi32>> {fir.bindc_name = "b"}) { -! CHECK: %[[DECL_A:.*]]:2 = hlfir.declare %[[ARG0]](%{{.*}}) dummy_scope %{{[0-9]+}} {acc.declare = #acc.declare<dataClause = acc_copy>, uniq_name = "_QMacc_declareFacc_declare_multiple_directiveEa"} : (!fir.ref<!fir.array<100xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100xi32>>, !fir.ref<!fir.array<100xi32>>) -! CHECK: %[[DECL_B:.*]]:2 = hlfir.declare %[[ARG1]](%{{.*}}) dummy_scope %{{[0-9]+}} {acc.declare = #acc.declare<dataClause = acc_copyout>, uniq_name = "_QMacc_declareFacc_declare_multiple_directiveEb"} : (!fir.ref<!fir.array<100xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100xi32>>, !fir.ref<!fir.array<100xi32>>) +! CHECK: %[[DECL_A:.*]]:2 = hlfir.declare %[[ARG0]](%{{.*}}) dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {acc.declare = #acc.declare<dataClause = acc_copy>, uniq_name = "_QMacc_declareFacc_declare_multiple_directiveEa"} : (!fir.ref<!fir.array<100xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100xi32>>, !fir.ref<!fir.array<100xi32>>) +! CHECK: %[[DECL_B:.*]]:2 = hlfir.declare %[[ARG1]](%{{.*}}) dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {acc.declare = #acc.declare<dataClause = acc_copyout>, uniq_name = "_QMacc_declareFacc_declare_multiple_directiveEb"} : (!fir.ref<!fir.array<100xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100xi32>>, !fir.ref<!fir.array<100xi32>>) ! CHECK: %[[COPYIN:.*]] = acc.copyin varPtr(%[[DECL_A]]#0 : !fir.ref<!fir.array<100xi32>>) -> !fir.ref<!fir.array<100xi32>> {dataClause = #acc<data_clause acc_copy>, name = "a"} ! CHECK: %[[CREATE:.*]] = acc.create varPtr(%[[DECL_B]]#0 : !fir.ref<!fir.array<100xi32>>) -> !fir.ref<!fir.array<100xi32>> {dataClause = #acc<data_clause acc_copyout>, name = "b"} ! CHECK: acc.declare_enter dataOperands(%[[COPYIN]], %[[CREATE]] : !fir.ref<!fir.array<100xi32>>, !fir.ref<!fir.array<100xi32>>) @@ -296,7 +296,7 @@ module acc_declare ! CHECK-LABEL: func.func @_QMacc_declarePacc_declare_array_section( ! CHECK-SAME: %[[ARG0:.*]]: !fir.box<!fir.array<?xi32>> {fir.bindc_name = "a"}) { -! CHECK: %[[DECL_A:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{[0-9]+}} {acc.declare = #acc.declare<dataClause = acc_copy>, uniq_name = "_QMacc_declareFacc_declare_array_sectionEa"} : (!fir.box<!fir.array<?xi32>>, !fir.dscope) -> (!fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>>) +! CHECK: %[[DECL_A:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {acc.declare = #acc.declare<dataClause = acc_copy>, uniq_name = "_QMacc_declareFacc_declare_array_sectionEa"} : (!fir.box<!fir.array<?xi32>>, !fir.dscope) -> (!fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>>) ! CHECK: %[[COPYIN:.*]] = acc.copyin var(%[[DECL_A]]#0 : !fir.box<!fir.array<?xi32>>) bounds(%{{.*}}) -> !fir.box<!fir.array<?xi32>> {dataClause = #acc<data_clause acc_copy>, name = "a(1:10)"} ! CHECK: acc.declare_enter dataOperands(%[[COPYIN]] : !fir.box<!fir.array<?xi32>>) diff --git a/flang/test/Lower/OpenACC/acc-enter-data.f90 b/flang/test/Lower/OpenACC/acc-enter-data.f90 index 2718c96..1e20bdc 100644 --- a/flang/test/Lower/OpenACC/acc-enter-data.f90 +++ b/flang/test/Lower/OpenACC/acc-enter-data.f90 @@ -668,6 +668,6 @@ end subroutine ! CHECK-LABEL: func.func @_QPtest_class( ! CHECK-SAME: %[[ARG0:.*]]: !fir.class<!fir.type<_QMmod1Tderived{m:f32}>> {fir.bindc_name = "a"}) { -! CHECK: %[[DECL_ARG0:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %0 {uniq_name = "_QFtest_classEa"} : (!fir.class<!fir.type<_QMmod1Tderived{m:f32}>>, !fir.dscope) -> (!fir.class<!fir.type<_QMmod1Tderived{m:f32}>>, !fir.class<!fir.type<_QMmod1Tderived{m:f32}>>) +! CHECK: %[[DECL_ARG0:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %0 {{.*}} {uniq_name = "_QFtest_classEa"} : (!fir.class<!fir.type<_QMmod1Tderived{m:f32}>>, !fir.dscope) -> (!fir.class<!fir.type<_QMmod1Tderived{m:f32}>>, !fir.class<!fir.type<_QMmod1Tderived{m:f32}>>) ! CHECK: %[[COPYIN:.*]] = acc.copyin var(%[[DECL_ARG0]]#0 : !fir.class<!fir.type<_QMmod1Tderived{m:f32}>>) -> !fir.class<!fir.type<_QMmod1Tderived{m:f32}>> {name = "a", structured = false} ! CHECK: acc.enter_data dataOperands(%[[COPYIN]] : !fir.class<!fir.type<_QMmod1Tderived{m:f32}>>) diff --git a/flang/test/Lower/OpenACC/acc-firstprivate-derived-allocatable-component.f90 b/flang/test/Lower/OpenACC/acc-firstprivate-derived-allocatable-component.f90 index 3987f9f..066e80e 100644 --- a/flang/test/Lower/OpenACC/acc-firstprivate-derived-allocatable-component.f90 +++ b/flang/test/Lower/OpenACC/acc-firstprivate-derived-allocatable-component.f90 @@ -44,15 +44,15 @@ module m_firstprivate_derived_alloc_comp ! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]] {uniq_name = "_QMm_firstprivate_derived_alloc_compFtestEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_4:.*]] = fir.alloca i32 {bindc_name = "n", uniq_name = "_QMm_firstprivate_derived_alloc_compFtestEn"} ! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_4]] {uniq_name = "_QMm_firstprivate_derived_alloc_compFtestEn"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) -! CHECK: %[[VAL_6:.*]] = acc.firstprivate varPtr(%[[VAL_1]]#0 : !fir.ref<!fir.type<_QMm_firstprivate_derived_alloc_compTpoint{x:!fir.box<!fir.heap<!fir.array<?xf32>>>}>>) -> !fir.ref<!fir.type<_QMm_firstprivate_derived_alloc_compTpoint{x:!fir.box<!fir.heap<!fir.array<?xf32>>>}>> {name = "a"} -! CHECK: acc.parallel combined(loop) firstprivate(@firstprivatization_ref_rec__QMm_firstprivate_derived_alloc_compTpoint -> %[[VAL_6]] : !fir.ref<!fir.type<_QMm_firstprivate_derived_alloc_compTpoint{x:!fir.box<!fir.heap<!fir.array<?xf32>>>}>>) { +! CHECK: %[[VAL_6:.*]] = acc.firstprivate varPtr(%[[VAL_1]]#0 : !fir.ref<!fir.type<_QMm_firstprivate_derived_alloc_compTpoint{x:!fir.box<!fir.heap<!fir.array<?xf32>>>}>>) recipe(@firstprivatization_ref_rec__QMm_firstprivate_derived_alloc_compTpoint) -> !fir.ref<!fir.type<_QMm_firstprivate_derived_alloc_compTpoint{x:!fir.box<!fir.heap<!fir.array<?xf32>>>}>> {name = "a"} +! CHECK: acc.parallel combined(loop) firstprivate(%[[VAL_6]] : !fir.ref<!fir.type<_QMm_firstprivate_derived_alloc_compTpoint{x:!fir.box<!fir.heap<!fir.array<?xf32>>>}>>) { ! CHECK: %[[VAL_7:.*]] = fir.dummy_scope : !fir.dscope ! CHECK: %[[VAL_8:.*]]:2 = hlfir.declare %[[VAL_6]] dummy_scope %[[VAL_7]] {uniq_name = "_QMm_firstprivate_derived_alloc_compFtestEa"} : (!fir.ref<!fir.type<_QMm_firstprivate_derived_alloc_compTpoint{x:!fir.box<!fir.heap<!fir.array<?xf32>>>}>>, !fir.dscope) -> (!fir.ref<!fir.type<_QMm_firstprivate_derived_alloc_compTpoint{x:!fir.box<!fir.heap<!fir.array<?xf32>>>}>>, !fir.ref<!fir.type<_QMm_firstprivate_derived_alloc_compTpoint{x:!fir.box<!fir.heap<!fir.array<?xf32>>>}>>) ! CHECK: %[[VAL_9:.*]] = arith.constant 1 : i32 ! CHECK: %[[VAL_10:.*]] = fir.load %[[VAL_5]]#0 : !fir.ref<i32> ! CHECK: %[[VAL_11:.*]] = arith.constant 1 : i32 -! CHECK: %[[VAL_12:.*]] = acc.private varPtr(%[[VAL_3]]#0 : !fir.ref<i32>) -> !fir.ref<i32> {implicit = true, name = "i"} -! CHECK: acc.loop combined(parallel) private(@privatization_ref_i32 -> %[[VAL_12]] : !fir.ref<i32>) control(%[[VAL_14:.*]] : i32) = (%[[VAL_9]] : i32) to (%[[VAL_10]] : i32) step (%[[VAL_11]] : i32) { +! CHECK: %[[VAL_12:.*]] = acc.private varPtr(%[[VAL_3]]#0 : !fir.ref<i32>) recipe(@privatization_ref_i32) -> !fir.ref<i32> {implicit = true, name = "i"} +! CHECK: acc.loop combined(parallel) private(%[[VAL_12]] : !fir.ref<i32>) control(%[[VAL_14:.*]] : i32) = (%[[VAL_9]] : i32) to (%[[VAL_10]] : i32) step (%[[VAL_11]] : i32) { ! CHECK: %[[VAL_13:.*]]:2 = hlfir.declare %[[VAL_12]] {uniq_name = "_QMm_firstprivate_derived_alloc_compFtestEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: fir.store %[[VAL_14]] to %[[VAL_13]]#0 : !fir.ref<i32> ! CHECK: %[[VAL_15:.*]] = arith.constant 1.000000e+00 : f32 diff --git a/flang/test/Lower/OpenACC/acc-firstprivate-derived-pointer-component.f90 b/flang/test/Lower/OpenACC/acc-firstprivate-derived-pointer-component.f90 index 9ef4fe6..61f3d02 100644 --- a/flang/test/Lower/OpenACC/acc-firstprivate-derived-pointer-component.f90 +++ b/flang/test/Lower/OpenACC/acc-firstprivate-derived-pointer-component.f90 @@ -34,20 +34,20 @@ module m_firstprivate_derived_ptr_comp ! CHECK-LABEL: func.func @_QMm_firstprivate_derived_ptr_compPtest( ! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.type<_QMm_firstprivate_derived_ptr_compTpoint{x:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>> {fir.bindc_name = "a"}) { ! CHECK: %[[VAL_0:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %[[VAL_0]] {uniq_name = "_QMm_firstprivate_derived_ptr_compFtestEa"} : (!fir.ref<!fir.type<_QMm_firstprivate_derived_ptr_compTpoint{x:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>>, !fir.dscope) -> (!fir.ref<!fir.type<_QMm_firstprivate_derived_ptr_compTpoint{x:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>>, !fir.ref<!fir.type<_QMm_firstprivate_derived_ptr_compTpoint{x:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %[[VAL_0]] arg {{[0-9]+}} {uniq_name = "_QMm_firstprivate_derived_ptr_compFtestEa"} : (!fir.ref<!fir.type<_QMm_firstprivate_derived_ptr_compTpoint{x:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>>, !fir.dscope) -> (!fir.ref<!fir.type<_QMm_firstprivate_derived_ptr_compTpoint{x:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>>, !fir.ref<!fir.type<_QMm_firstprivate_derived_ptr_compTpoint{x:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>>) ! CHECK: %[[VAL_2:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QMm_firstprivate_derived_ptr_compFtestEi"} ! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]] {uniq_name = "_QMm_firstprivate_derived_ptr_compFtestEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_4:.*]] = fir.alloca i32 {bindc_name = "n", uniq_name = "_QMm_firstprivate_derived_ptr_compFtestEn"} ! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_4]] {uniq_name = "_QMm_firstprivate_derived_ptr_compFtestEn"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) -! CHECK: %[[VAL_6:.*]] = acc.firstprivate varPtr(%[[VAL_1]]#0 : !fir.ref<!fir.type<_QMm_firstprivate_derived_ptr_compTpoint{x:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>>) -> !fir.ref<!fir.type<_QMm_firstprivate_derived_ptr_compTpoint{x:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>> {name = "a"} -! CHECK: acc.parallel combined(loop) firstprivate(@firstprivatization_ref_rec__QMm_firstprivate_derived_ptr_compTpoint -> %[[VAL_6]] : !fir.ref<!fir.type<_QMm_firstprivate_derived_ptr_compTpoint{x:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>>) { +! CHECK: %[[VAL_6:.*]] = acc.firstprivate varPtr(%[[VAL_1]]#0 : !fir.ref<!fir.type<_QMm_firstprivate_derived_ptr_compTpoint{x:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>>) recipe(@firstprivatization_ref_rec__QMm_firstprivate_derived_ptr_compTpoint) -> !fir.ref<!fir.type<_QMm_firstprivate_derived_ptr_compTpoint{x:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>> {name = "a"} +! CHECK: acc.parallel combined(loop) firstprivate(%[[VAL_6]] : !fir.ref<!fir.type<_QMm_firstprivate_derived_ptr_compTpoint{x:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>>) { ! CHECK: %[[VAL_7:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_8:.*]]:2 = hlfir.declare %[[VAL_6]] dummy_scope %[[VAL_7]] {uniq_name = "_QMm_firstprivate_derived_ptr_compFtestEa"} : (!fir.ref<!fir.type<_QMm_firstprivate_derived_ptr_compTpoint{x:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>>, !fir.dscope) -> (!fir.ref<!fir.type<_QMm_firstprivate_derived_ptr_compTpoint{x:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>>, !fir.ref<!fir.type<_QMm_firstprivate_derived_ptr_compTpoint{x:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>>) +! CHECK: %[[VAL_8:.*]]:2 = hlfir.declare %[[VAL_6]] dummy_scope %[[VAL_7]] {{.*}} {uniq_name = "_QMm_firstprivate_derived_ptr_compFtestEa"} : (!fir.ref<!fir.type<_QMm_firstprivate_derived_ptr_compTpoint{x:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>>, !fir.dscope) -> (!fir.ref<!fir.type<_QMm_firstprivate_derived_ptr_compTpoint{x:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>>, !fir.ref<!fir.type<_QMm_firstprivate_derived_ptr_compTpoint{x:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>>) ! CHECK: %[[VAL_9:.*]] = arith.constant 1 : i32 ! CHECK: %[[VAL_10:.*]] = fir.load %[[VAL_5]]#0 : !fir.ref<i32> ! CHECK: %[[VAL_11:.*]] = arith.constant 1 : i32 -! CHECK: %[[VAL_12:.*]] = acc.private varPtr(%[[VAL_3]]#0 : !fir.ref<i32>) -> !fir.ref<i32> {implicit = true, name = "i"} -! CHECK: acc.loop combined(parallel) private(@privatization_ref_i32 -> %[[VAL_12]] : !fir.ref<i32>) control(%[[VAL_14:.*]] : i32) = (%[[VAL_9]] : i32) to (%[[VAL_10]] : i32) step (%[[VAL_11]] : i32) { +! CHECK: %[[VAL_12:.*]] = acc.private varPtr(%[[VAL_3]]#0 : !fir.ref<i32>) recipe(@privatization_ref_i32) -> !fir.ref<i32> {implicit = true, name = "i"} +! CHECK: acc.loop combined(parallel) private(%[[VAL_12]] : !fir.ref<i32>) control(%[[VAL_14:.*]] : i32) = (%[[VAL_9]] : i32) to (%[[VAL_10]] : i32) step (%[[VAL_11]] : i32) { ! CHECK: %[[VAL_13:.*]]:2 = hlfir.declare %[[VAL_12]] {uniq_name = "_QMm_firstprivate_derived_ptr_compFtestEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: fir.store %[[VAL_14]] to %[[VAL_13]]#0 : !fir.ref<i32> ! CHECK: %[[VAL_15:.*]] = arith.constant 1.000000e+00 : f32 diff --git a/flang/test/Lower/OpenACC/acc-firstprivate-derived-user-assign.f90 b/flang/test/Lower/OpenACC/acc-firstprivate-derived-user-assign.f90 index e90ec32..9ada6d3 100644 --- a/flang/test/Lower/OpenACC/acc-firstprivate-derived-user-assign.f90 +++ b/flang/test/Lower/OpenACC/acc-firstprivate-derived-user-assign.f90 @@ -53,14 +53,14 @@ module m_firstprivate_derived_user_def ! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_3]] {uniq_name = "_QMm_firstprivate_derived_user_defFtestEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_5:.*]] = fir.alloca i32 {bindc_name = "n", uniq_name = "_QMm_firstprivate_derived_user_defFtestEn"} ! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_5]] {uniq_name = "_QMm_firstprivate_derived_user_defFtestEn"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) -! CHECK: %[[VAL_7:.*]] = acc.firstprivate varPtr(%[[VAL_2]]#0 : !fir.ref<!fir.type<_QMm_firstprivate_derived_user_defTpoint{x:f32,y:f32,z:f32}>>) -> !fir.ref<!fir.type<_QMm_firstprivate_derived_user_defTpoint{x:f32,y:f32,z:f32}>> {name = "a"} -! CHECK: acc.parallel combined(loop) firstprivate(@firstprivatization_ref_rec__QMm_firstprivate_derived_user_defTpoint -> %[[VAL_7]] : !fir.ref<!fir.type<_QMm_firstprivate_derived_user_defTpoint{x:f32,y:f32,z:f32}>>) { +! CHECK: %[[VAL_7:.*]] = acc.firstprivate varPtr(%[[VAL_2]]#0 : !fir.ref<!fir.type<_QMm_firstprivate_derived_user_defTpoint{x:f32,y:f32,z:f32}>>) recipe(@firstprivatization_ref_rec__QMm_firstprivate_derived_user_defTpoint) -> !fir.ref<!fir.type<_QMm_firstprivate_derived_user_defTpoint{x:f32,y:f32,z:f32}>> {name = "a"} +! CHECK: acc.parallel combined(loop) firstprivate(%[[VAL_7]] : !fir.ref<!fir.type<_QMm_firstprivate_derived_user_defTpoint{x:f32,y:f32,z:f32}>>) { ! CHECK: %[[VAL_8:.*]]:2 = hlfir.declare %[[VAL_7]] {uniq_name = "_QMm_firstprivate_derived_user_defFtestEa"} : (!fir.ref<!fir.type<_QMm_firstprivate_derived_user_defTpoint{x:f32,y:f32,z:f32}>>) -> (!fir.ref<!fir.type<_QMm_firstprivate_derived_user_defTpoint{x:f32,y:f32,z:f32}>>, !fir.ref<!fir.type<_QMm_firstprivate_derived_user_defTpoint{x:f32,y:f32,z:f32}>>) ! CHECK: %[[VAL_9:.*]] = arith.constant 1 : i32 ! CHECK: %[[VAL_10:.*]] = fir.load %[[VAL_6]]#0 : !fir.ref<i32> ! CHECK: %[[VAL_11:.*]] = arith.constant 1 : i32 -! CHECK: %[[VAL_12:.*]] = acc.private varPtr(%[[VAL_4]]#0 : !fir.ref<i32>) -> !fir.ref<i32> {implicit = true, name = "i"} -! CHECK: acc.loop combined(parallel) private(@privatization_ref_i32 -> %[[VAL_12]] : !fir.ref<i32>) control(%[[VAL_14:.*]] : i32) = (%[[VAL_9]] : i32) to (%[[VAL_10]] : i32) step (%[[VAL_11]] : i32) { +! CHECK: %[[VAL_12:.*]] = acc.private varPtr(%[[VAL_4]]#0 : !fir.ref<i32>) recipe(@privatization_ref_i32) -> !fir.ref<i32> {implicit = true, name = "i"} +! CHECK: acc.loop combined(parallel) private(%[[VAL_12]] : !fir.ref<i32>) control(%[[VAL_14:.*]] : i32) = (%[[VAL_9]] : i32) to (%[[VAL_10]] : i32) step (%[[VAL_11]] : i32) { ! CHECK: %[[VAL_13:.*]]:2 = hlfir.declare %[[VAL_12]] {uniq_name = "_QMm_firstprivate_derived_user_defFtestEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: fir.store %[[VAL_14]] to %[[VAL_13]]#0 : !fir.ref<i32> ! CHECK: %[[VAL_15:.*]] = arith.constant 1.000000e+00 : f32 diff --git a/flang/test/Lower/OpenACC/acc-firstprivate-derived.f90 b/flang/test/Lower/OpenACC/acc-firstprivate-derived.f90 index e91fc9b..6260f75 100644 --- a/flang/test/Lower/OpenACC/acc-firstprivate-derived.f90 +++ b/flang/test/Lower/OpenACC/acc-firstprivate-derived.f90 @@ -39,14 +39,14 @@ module m_firstprivate_derived ! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_3]] {uniq_name = "_QMm_firstprivate_derivedFtestEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_5:.*]] = fir.alloca i32 {bindc_name = "n", uniq_name = "_QMm_firstprivate_derivedFtestEn"} ! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_5]] {uniq_name = "_QMm_firstprivate_derivedFtestEn"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) -! CHECK: %[[VAL_7:.*]] = acc.firstprivate varPtr(%[[VAL_2]]#0 : !fir.ref<!fir.type<_QMm_firstprivate_derivedTpoint{x:f32,y:f32,z:f32}>>) -> !fir.ref<!fir.type<_QMm_firstprivate_derivedTpoint{x:f32,y:f32,z:f32}>> {name = "a"} -! CHECK: acc.parallel combined(loop) firstprivate(@firstprivatization_ref_rec__QMm_firstprivate_derivedTpoint -> %[[VAL_7]] : !fir.ref<!fir.type<_QMm_firstprivate_derivedTpoint{x:f32,y:f32,z:f32}>>) { +! CHECK: %[[VAL_7:.*]] = acc.firstprivate varPtr(%[[VAL_2]]#0 : !fir.ref<!fir.type<_QMm_firstprivate_derivedTpoint{x:f32,y:f32,z:f32}>>) recipe(@firstprivatization_ref_rec__QMm_firstprivate_derivedTpoint) -> !fir.ref<!fir.type<_QMm_firstprivate_derivedTpoint{x:f32,y:f32,z:f32}>> {name = "a"} +! CHECK: acc.parallel combined(loop) firstprivate(%[[VAL_7]] : !fir.ref<!fir.type<_QMm_firstprivate_derivedTpoint{x:f32,y:f32,z:f32}>>) { ! CHECK: %[[VAL_8:.*]]:2 = hlfir.declare %[[VAL_7]] {uniq_name = "_QMm_firstprivate_derivedFtestEa"} : (!fir.ref<!fir.type<_QMm_firstprivate_derivedTpoint{x:f32,y:f32,z:f32}>>) -> (!fir.ref<!fir.type<_QMm_firstprivate_derivedTpoint{x:f32,y:f32,z:f32}>>, !fir.ref<!fir.type<_QMm_firstprivate_derivedTpoint{x:f32,y:f32,z:f32}>>) ! CHECK: %[[VAL_9:.*]] = arith.constant 1 : i32 ! CHECK: %[[VAL_10:.*]] = fir.load %[[VAL_6]]#0 : !fir.ref<i32> ! CHECK: %[[VAL_11:.*]] = arith.constant 1 : i32 -! CHECK: %[[VAL_12:.*]] = acc.private varPtr(%[[VAL_4]]#0 : !fir.ref<i32>) -> !fir.ref<i32> {implicit = true, name = "i"} -! CHECK: acc.loop combined(parallel) private(@privatization_ref_i32 -> %[[VAL_12]] : !fir.ref<i32>) control(%[[VAL_14:.*]] : i32) = (%[[VAL_9]] : i32) to (%[[VAL_10]] : i32) step (%[[VAL_11]] : i32) { +! CHECK: %[[VAL_12:.*]] = acc.private varPtr(%[[VAL_4]]#0 : !fir.ref<i32>) recipe(@privatization_ref_i32) -> !fir.ref<i32> {implicit = true, name = "i"} +! CHECK: acc.loop combined(parallel) private(%[[VAL_12]] : !fir.ref<i32>) control(%[[VAL_14:.*]] : i32) = (%[[VAL_9]] : i32) to (%[[VAL_10]] : i32) step (%[[VAL_11]] : i32) { ! CHECK: %[[VAL_13:.*]]:2 = hlfir.declare %[[VAL_12]] {uniq_name = "_QMm_firstprivate_derivedFtestEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: fir.store %[[VAL_14]] to %[[VAL_13]]#0 : !fir.ref<i32> ! CHECK: %[[VAL_15:.*]] = arith.constant 1.000000e+00 : f32 diff --git a/flang/test/Lower/OpenACC/acc-host-data.f90 b/flang/test/Lower/OpenACC/acc-host-data.f90 index 4d09b25..2cf8060 100644 --- a/flang/test/Lower/OpenACC/acc-host-data.f90 +++ b/flang/test/Lower/OpenACC/acc-host-data.f90 @@ -26,7 +26,7 @@ subroutine acc_host_data() ! CHECK: acc.host_data dataOperands(%[[DA0]], %[[DA1]] : !fir.ref<!fir.array<10xf32>>, !fir.ref<!fir.array<10xf32>>) ! CHECK: } attributes {ifPresent} - !$acc host_data use_device(a) if_present + !$acc host_data use_device(a) if_present !$acc end host_data ! CHECK: acc.host_data dataOperands(%{{.*}}{{.*}} : !fir.ref<!fir.array<10xf32>>{{.*}}) { ! CHECK: } attributes {ifPresent} diff --git a/flang/test/Lower/OpenACC/acc-kernels-loop.f90 b/flang/test/Lower/OpenACC/acc-kernels-loop.f90 index 8d95f35..70f5b7d 100644 --- a/flang/test/Lower/OpenACC/acc-kernels-loop.f90 +++ b/flang/test/Lower/OpenACC/acc-kernels-loop.f90 @@ -360,7 +360,7 @@ subroutine acc_kernels_loop END DO ! CHECK: %[[CREATE_A:.*]] = acc.create varPtr(%[[DECLA]]#0 : !fir.ref<!fir.array<10xf32>>) -> !fir.ref<!fir.array<10xf32>> {dataClause = #acc<data_clause acc_copyout>, name = "a"} -! CHECK: %[[CREATE_B:.*]] = acc.create varPtr(%[[DECLB]]#0 : !fir.ref<!fir.array<10xf32>>) -> !fir.ref<!fir.array<10xf32>> {dataClause = #acc<data_clause acc_copyout>, name = "b"} +! CHECK: %[[CREATE_B:.*]] = acc.create varPtr(%[[DECLB]]#0 : !fir.ref<!fir.array<10xf32>>) -> !fir.ref<!fir.array<10xf32>> {dataClause = #acc<data_clause acc_copyout_zero>, name = "b"} ! CHECK: acc.kernels {{.*}} dataOperands(%[[CREATE_A]], %[[CREATE_B]] : !fir.ref<!fir.array<10xf32>>, !fir.ref<!fir.array<10xf32>>) { ! CHECK: acc.loop {{.*}} { ! CHECK: acc.yield @@ -368,7 +368,7 @@ subroutine acc_kernels_loop ! CHECK: acc.terminator ! CHECK-NEXT: }{{$}} ! CHECK: acc.copyout accPtr(%[[CREATE_A]] : !fir.ref<!fir.array<10xf32>>) to varPtr(%[[DECLA]]#0 : !fir.ref<!fir.array<10xf32>>) {name = "a"} -! CHECK: acc.copyout accPtr(%[[CREATE_B]] : !fir.ref<!fir.array<10xf32>>) to varPtr(%[[DECLB]]#0 : !fir.ref<!fir.array<10xf32>>) {name = "b"} +! CHECK: acc.copyout accPtr(%[[CREATE_B]] : !fir.ref<!fir.array<10xf32>>) to varPtr(%[[DECLB]]#0 : !fir.ref<!fir.array<10xf32>>) {dataClause = #acc<data_clause acc_copyout_zero>, name = "b"} !$acc kernels loop create(b) create(zero: a) DO i = 1, n @@ -704,7 +704,9 @@ subroutine acc_kernels_loop ! CHECK: %[[COPYINREDR:.*]] = acc.copyin varPtr(%{{.*}} : !fir.ref<f32>) -> !fir.ref<f32> {dataClause = #acc<data_clause acc_reduction>, implicit = true, name = "reduction_r"} ! CHECK: %[[COPYINREDI:.*]] = acc.copyin varPtr(%{{.*}} : !fir.ref<i32>) -> !fir.ref<i32> {dataClause = #acc<data_clause acc_reduction>, implicit = true, name = "reduction_i"} ! CHECK: acc.kernels {{.*}} dataOperands(%[[COPYINREDR]], %[[COPYINREDI]] : !fir.ref<f32>, !fir.ref<i32>) { -! CHECK: acc.loop {{.*}} reduction(@reduction_add_ref_f32 -> %{{.*}} : !fir.ref<f32>, @reduction_mul_ref_i32 -> %{{.*}} : !fir.ref<i32>) {{.*}} { +! CHECK: %[[REDUCTION_R:.*]] = acc.reduction varPtr(%{{.*}} : !fir.ref<f32>) recipe(@reduction_add_ref_f32) -> !fir.ref<f32> {name = "reduction_r"} +! CHECK: %[[REDUCTION_I:.*]] = acc.reduction varPtr(%{{.*}} : !fir.ref<i32>) recipe(@reduction_mul_ref_i32) -> !fir.ref<i32> {name = "reduction_i"} +! CHECK: acc.loop {{.*}} reduction(%[[REDUCTION_R]], %[[REDUCTION_I]] : !fir.ref<f32>, !fir.ref<i32>) {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} ! CHECK: acc.terminator diff --git a/flang/test/Lower/OpenACC/acc-kernels.f90 b/flang/test/Lower/OpenACC/acc-kernels.f90 index b90870d..65079e6 100644 --- a/flang/test/Lower/OpenACC/acc-kernels.f90 +++ b/flang/test/Lower/OpenACC/acc-kernels.f90 @@ -222,13 +222,13 @@ subroutine acc_kernels !$acc end kernels ! CHECK: %[[CREATE_A:.*]] = acc.create varPtr(%[[DECLA]]#0 : !fir.ref<!fir.array<10x10xf32>>) -> !fir.ref<!fir.array<10x10xf32>> {dataClause = #acc<data_clause acc_copyout>, name = "a"} -! CHECK: %[[CREATE_B:.*]] = acc.create varPtr(%[[DECLB]]#0 : !fir.ref<!fir.array<10x10xf32>>) -> !fir.ref<!fir.array<10x10xf32>> {dataClause = #acc<data_clause acc_copyout>, name = "b"} +! CHECK: %[[CREATE_B:.*]] = acc.create varPtr(%[[DECLB]]#0 : !fir.ref<!fir.array<10x10xf32>>) -> !fir.ref<!fir.array<10x10xf32>> {dataClause = #acc<data_clause acc_copyout_zero>, name = "b"} ! CHECK: %[[CREATE_C:.*]] = acc.create varPtr(%[[DECLC]]#0 : !fir.ref<!fir.array<10x10xf32>>) -> !fir.ref<!fir.array<10x10xf32>> {dataClause = #acc<data_clause acc_copyout>, name = "c"} ! CHECK: acc.kernels dataOperands(%[[CREATE_A]], %[[CREATE_B]], %[[CREATE_C]] : !fir.ref<!fir.array<10x10xf32>>, !fir.ref<!fir.array<10x10xf32>>, !fir.ref<!fir.array<10x10xf32>>) { ! CHECK: acc.terminator ! CHECK-NEXT: }{{$}} ! CHECK: acc.copyout accPtr(%[[CREATE_A]] : !fir.ref<!fir.array<10x10xf32>>) to varPtr(%[[DECLA]]#0 : !fir.ref<!fir.array<10x10xf32>>) {name = "a"} -! CHECK: acc.copyout accPtr(%[[CREATE_B]] : !fir.ref<!fir.array<10x10xf32>>) to varPtr(%[[DECLB]]#0 : !fir.ref<!fir.array<10x10xf32>>) {name = "b"} +! CHECK: acc.copyout accPtr(%[[CREATE_B]] : !fir.ref<!fir.array<10x10xf32>>) to varPtr(%[[DECLB]]#0 : !fir.ref<!fir.array<10x10xf32>>) {dataClause = #acc<data_clause acc_copyout_zero>, name = "b"} ! CHECK: acc.copyout accPtr(%[[CREATE_C]] : !fir.ref<!fir.array<10x10xf32>>) to varPtr(%[[DECLC]]#0 : !fir.ref<!fir.array<10x10xf32>>) {name = "c"} !$acc kernels create(a, b) create(zero: c) diff --git a/flang/test/Lower/OpenACC/acc-loop-exit.f90 b/flang/test/Lower/OpenACC/acc-loop-exit.f90 index af11b34..6ab215f 100644 --- a/flang/test/Lower/OpenACC/acc-loop-exit.f90 +++ b/flang/test/Lower/OpenACC/acc-loop-exit.f90 @@ -11,18 +11,18 @@ subroutine sub1(x, a) end do i = 2 -end +end ! CHECK-LABEL: func.func @_QPsub1 -! CHECK: %[[A:.*]]:2 = hlfir.declare %arg1 dummy_scope %{{[0-9]+}} {uniq_name = "_QFsub1Ea"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[A:.*]]:2 = hlfir.declare %arg1 dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFsub1Ea"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[I:.*]]:2 = hlfir.declare %{{[0-9]+}} {uniq_name = "_QFsub1Ei"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[EXIT_COND:.*]] = acc.loop ! CHECK: %[[I:.*]]:2 = hlfir.declare %{{[0-9]+}} {uniq_name = "_QFsub1Ei"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: ^bb{{.*}}: ! CHECK: ^bb{{.*}}: -! CHECK: %[[LOAD_I:.*]] = fir.load %[[I]]#0 : !fir.ref<i32> -! CHECK: %[[LOAD_I:.*]] = fir.load %[[I]]#0 : !fir.ref<i32> -! CHECK: %[[LOAD_A:.*]] = fir.load %[[A]]#0 : !fir.ref<i32> +! CHECK: %[[LOAD_I:.*]] = fir.load %[[I]]#0 : !fir.ref<i32> +! CHECK: %[[LOAD_I:.*]] = fir.load %[[I]]#0 : !fir.ref<i32> +! CHECK: %[[LOAD_A:.*]] = fir.load %[[A]]#0 : !fir.ref<i32> ! CHECK: %[[CMP:.*]] = arith.cmpi eq, %[[LOAD_I]], %[[LOAD_A]] : i32 ! CHECK: cf.cond_br %[[CMP]], ^[[EARLY_RET:.*]], ^[[NO_RET:.*]] ! CHECK: ^[[EARLY_RET]]: diff --git a/flang/test/Lower/OpenACC/acc-loop.f90 b/flang/test/Lower/OpenACC/acc-loop.f90 index f9f5e8c..ed87cf7 100644 --- a/flang/test/Lower/OpenACC/acc-loop.f90 +++ b/flang/test/Lower/OpenACC/acc-loop.f90 @@ -27,7 +27,8 @@ program acc_loop a(i) = b(i) END DO -! CHECK: acc.loop private(@privatization_ref_i32 -> %{{.*}} : !fir.ref<i32>) control(%arg0 : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) { +! CHECK: %[[PRIVATE_I:.*]] = acc.private varPtr(%{{.*}} : !fir.ref<i32>) recipe(@privatization_ref_i32) -> !fir.ref<i32> {implicit = true, name = "i"} +! CHECK: acc.loop private(%[[PRIVATE_I]] : !fir.ref<i32>) control(%arg0 : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) { ! CHECK: acc.yield ! CHECK-NEXT: } attributes {inclusiveUpperbound = array<i1: true>, independent = [#acc.device_type<none>]}{{$}} @@ -36,7 +37,8 @@ program acc_loop a(i) = b(i) END DO -! CHECK: acc.loop private(@privatization_ref_i32 -> %{{.*}} : !fir.ref<i32>) control(%arg0 : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) { +! CHECK: %[[PRIVATE_I:.*]] = acc.private varPtr(%{{.*}} : !fir.ref<i32>) recipe(@privatization_ref_i32) -> !fir.ref<i32> {implicit = true, name = "i"} +! CHECK: acc.loop private(%[[PRIVATE_I]] : !fir.ref<i32>) control(%arg0 : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) { ! CHECK: acc.yield ! CHECK-NEXT: } attributes {inclusiveUpperbound = array<i1: true>, seq = [#acc.device_type<none>]} @@ -45,7 +47,8 @@ program acc_loop a(i) = b(i) END DO -! CHECK: acc.loop private(@privatization_ref_i32 -> %{{.*}} : !fir.ref<i32>) control(%arg0 : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) { +! CHECK: %[[PRIVATE_I:.*]] = acc.private varPtr(%{{.*}} : !fir.ref<i32>) recipe(@privatization_ref_i32) -> !fir.ref<i32> {implicit = true, name = "i"} +! CHECK: acc.loop private(%[[PRIVATE_I]] : !fir.ref<i32>) control(%arg0 : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) { ! CHECK: acc.yield ! CHECK-NEXT: } attributes {auto_ = [#acc.device_type<none>], inclusiveUpperbound = array<i1: true>} @@ -54,7 +57,8 @@ program acc_loop a(i) = b(i) END DO -! CHECK: acc.loop private(@privatization_ref_i32 -> %{{.*}} : !fir.ref<i32>) control(%arg0 : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) { +! CHECK: %[[PRIVATE_I:.*]] = acc.private varPtr(%{{.*}} : !fir.ref<i32>) recipe(@privatization_ref_i32) -> !fir.ref<i32> {implicit = true, name = "i"} +! CHECK: acc.loop private(%[[PRIVATE_I]] : !fir.ref<i32>) control(%arg0 : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) { ! CHECK: acc.yield ! CHECK-NEXT: } attributes {inclusiveUpperbound = array<i1: true>, independent = [#acc.device_type<none>]} @@ -63,7 +67,8 @@ program acc_loop a(i) = b(i) END DO -! CHECK: acc.loop gang private(@privatization_ref_i32 -> %{{.*}} : !fir.ref<i32>) control(%arg0 : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) { +! CHECK: %[[PRIVATE_I:.*]] = acc.private varPtr(%{{.*}} : !fir.ref<i32>) recipe(@privatization_ref_i32) -> !fir.ref<i32> {implicit = true, name = "i"} +! CHECK: acc.loop gang private(%[[PRIVATE_I]] : !fir.ref<i32>) control(%arg0 : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) { ! CHECK: acc.yield ! CHECK-NEXT: } attributes {inclusiveUpperbound = array<i1: true>, independent = [#acc.device_type<none>]} @@ -73,7 +78,8 @@ program acc_loop END DO ! CHECK: [[GANGNUM1:%.*]] = arith.constant 8 : i32 -! CHECK: acc.loop gang({num=[[GANGNUM1]] : i32}) private(@privatization_ref_i32 -> %{{.*}} : !fir.ref<i32>) control(%arg0 : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) { +! CHECK: %[[PRIVATE_I:.*]] = acc.private varPtr(%{{.*}} : !fir.ref<i32>) recipe(@privatization_ref_i32) -> !fir.ref<i32> {implicit = true, name = "i"} +! CHECK: acc.loop gang({num=[[GANGNUM1]] : i32}) private(%[[PRIVATE_I]] : !fir.ref<i32>) control(%arg0 : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) { ! CHECK: acc.yield ! CHECK-NEXT: } attributes {inclusiveUpperbound = array<i1: true>, independent = [#acc.device_type<none>]} @@ -83,7 +89,8 @@ program acc_loop END DO ! CHECK: [[GANGNUM2:%.*]] = fir.load %{{.*}} : !fir.ref<i32> -! CHECK: acc.loop gang({num=[[GANGNUM2]] : i32}) private(@privatization_ref_i32 -> %{{.*}} : !fir.ref<i32>) control(%arg0 : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) { +! CHECK: %[[PRIVATE_I:.*]] = acc.private varPtr(%{{.*}} : !fir.ref<i32>) recipe(@privatization_ref_i32) -> !fir.ref<i32> {implicit = true, name = "i"} +! CHECK: acc.loop gang({num=[[GANGNUM2]] : i32}) private(%[[PRIVATE_I]] : !fir.ref<i32>) control(%arg0 : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) { ! CHECK: acc.yield ! CHECK-NEXT: } attributes {inclusiveUpperbound = array<i1: true>, independent = [#acc.device_type<none>]} @@ -92,7 +99,8 @@ program acc_loop a(i) = b(i) END DO -! CHECK: acc.loop gang({num=%{{.*}} : i32, static=%{{.*}} : i32}) private(@privatization_ref_i32 -> %{{.*}} : !fir.ref<i32>) control(%arg0 : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) { +! CHECK: %[[PRIVATE_I:.*]] = acc.private varPtr(%{{.*}} : !fir.ref<i32>) recipe(@privatization_ref_i32) -> !fir.ref<i32> {implicit = true, name = "i"} +! CHECK: acc.loop gang({num=%{{.*}} : i32, static=%{{.*}} : i32}) private(%[[PRIVATE_I]] : !fir.ref<i32>) control(%arg0 : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) { ! CHECK: acc.yield ! CHECK-NEXT: } attributes {inclusiveUpperbound = array<i1: true>, independent = [#acc.device_type<none>]} @@ -101,7 +109,8 @@ program acc_loop a(i) = b(i) END DO -! CHECK: acc.loop vector private(@privatization_ref_i32 -> %{{.*}} : !fir.ref<i32>) control(%arg0 : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) { +! CHECK: %[[PRIVATE_I:.*]] = acc.private varPtr(%{{.*}} : !fir.ref<i32>) recipe(@privatization_ref_i32) -> !fir.ref<i32> {implicit = true, name = "i"} +! CHECK: acc.loop vector private(%[[PRIVATE_I]] : !fir.ref<i32>) control(%arg0 : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) { ! CHECK: acc.yield ! CHECK-NEXT: } attributes {inclusiveUpperbound = array<i1: true>, independent = [#acc.device_type<none>]} @@ -110,8 +119,9 @@ program acc_loop a(i) = b(i) END DO -! CHECK: [[CONSTANT128:%.*]] = arith.constant 128 : i32 -! CHECK: acc.loop vector([[CONSTANT128]] : i32) private(@privatization_ref_i32 -> %{{.*}} : !fir.ref<i32>) control(%arg0 : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) { +! CHECK: [[CONSTANT128:%.*]] = arith.constant 128 : i32 +! CHECK: %[[PRIVATE_I:.*]] = acc.private varPtr(%{{.*}} : !fir.ref<i32>) recipe(@privatization_ref_i32) -> !fir.ref<i32> {implicit = true, name = "i"} +! CHECK: acc.loop vector([[CONSTANT128]] : i32) private(%[[PRIVATE_I]] : !fir.ref<i32>) control(%arg0 : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) { ! CHECK: acc.yield ! CHECK-NEXT: } attributes {inclusiveUpperbound = array<i1: true>, independent = [#acc.device_type<none>]} @@ -121,7 +131,8 @@ program acc_loop END DO ! CHECK: [[VECTORLENGTH:%.*]] = fir.load %{{.*}} : !fir.ref<i32> -! CHECK: acc.loop vector([[VECTORLENGTH]] : i32) private(@privatization_ref_i32 -> %{{.*}} : !fir.ref<i32>) control(%arg0 : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) { +! CHECK: %[[PRIVATE_I:.*]] = acc.private varPtr(%{{.*}} : !fir.ref<i32>) recipe(@privatization_ref_i32) -> !fir.ref<i32> {implicit = true, name = "i"} +! CHECK: acc.loop vector([[VECTORLENGTH]] : i32) private(%[[PRIVATE_I]] : !fir.ref<i32>) control(%arg0 : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) { ! CHECK: acc.yield ! CHECK-NEXT: } attributes {inclusiveUpperbound = array<i1: true>, independent = [#acc.device_type<none>]} @@ -130,7 +141,8 @@ program acc_loop a(i) = b(i) END DO -! CHECK: acc.loop worker private(@privatization_ref_i32 -> %{{.*}} : !fir.ref<i32>) control(%arg0 : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) { +! CHECK: %[[PRIVATE_I:.*]] = acc.private varPtr(%{{.*}} : !fir.ref<i32>) recipe(@privatization_ref_i32) -> !fir.ref<i32> {implicit = true, name = "i"} +! CHECK: acc.loop worker private(%[[PRIVATE_I]] : !fir.ref<i32>) control(%arg0 : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) { ! CHECK: acc.yield ! CHECK-NEXT: } attributes {inclusiveUpperbound = array<i1: true>, independent = [#acc.device_type<none>]} @@ -139,8 +151,9 @@ program acc_loop a(i) = b(i) END DO -! CHECK: [[WORKER128:%.*]] = arith.constant 128 : i32 -! CHECK: acc.loop worker([[WORKER128]] : i32) private(@privatization_ref_i32 -> %{{.*}} : !fir.ref<i32>) control(%arg0 : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) { +! CHECK: [[WORKER128:%.*]] = arith.constant 128 : i32 +! CHECK: %[[PRIVATE_I:.*]] = acc.private varPtr(%{{.*}} : !fir.ref<i32>) recipe(@privatization_ref_i32) -> !fir.ref<i32> {implicit = true, name = "i"} +! CHECK: acc.loop worker([[WORKER128]] : i32) private(%[[PRIVATE_I]] : !fir.ref<i32>) control(%arg0 : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) { ! CHECK: acc.yield ! CHECK-NEXT: } attributes {inclusiveUpperbound = array<i1: true>, independent = [#acc.device_type<none>]} @@ -149,7 +162,9 @@ program acc_loop c(:,i) = d(:,i) END DO -! CHECK: acc.loop private(@privatization_ref_10x10xf32 -> %{{.*}} : !fir.ref<!fir.array<10x10xf32>>, @privatization_ref_i32 -> %{{.*}} : !fir.ref<i32>) control(%arg0 : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) { +! CHECK: %[[PRIVATE_C:.*]] = acc.private varPtr(%{{.*}} : !fir.ref<!fir.array<10x10xf32>>) recipe(@privatization_ref_10x10xf32) -> !fir.ref<!fir.array<10x10xf32>> {name = "c"} +! CHECK: %[[PRIVATE_I:.*]] = acc.private varPtr(%{{.*}} : !fir.ref<i32>) recipe(@privatization_ref_i32) -> !fir.ref<i32> {implicit = true, name = "i"} +! CHECK: acc.loop private(%[[PRIVATE_C]], %[[PRIVATE_I]] : !fir.ref<!fir.array<10x10xf32>>, !fir.ref<i32>) control(%arg0 : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) { ! CHECK: acc.yield ! CHECK-NEXT: } attributes {inclusiveUpperbound = array<i1: true>, independent = [#acc.device_type<none>]} @@ -159,7 +174,8 @@ program acc_loop a(i) = b(i) END DO -! CHECK: acc.loop private(@privatization_ref_i32 -> %{{.*}} : !fir.ref<i32>) control(%arg0 : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) { +! CHECK: %[[PRIVATE_I:.*]] = acc.private varPtr(%{{.*}} : !fir.ref<i32>) recipe(@privatization_ref_i32) -> !fir.ref<i32> {name = "i"} +! CHECK: acc.loop private(%[[PRIVATE_I]] : !fir.ref<i32>) control(%arg0 : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) { ! CHECK: acc.yield ! CHECK-NEXT: } attributes {inclusiveUpperbound = array<i1: true>, independent = [#acc.device_type<none>]} @@ -168,7 +184,10 @@ program acc_loop c(:,i) = d(:,i) END DO -! CHECK: acc.loop private(@privatization_ref_10x10xf32 -> %{{.*}} : !fir.ref<!fir.array<10x10xf32>>, @privatization_ref_10x10xf32 -> %{{.*}} : !fir.ref<!fir.array<10x10xf32>>, @privatization_ref_i32 -> %{{.*}} : !fir.ref<i32>) control(%arg0 : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) { +! CHECK: %[[PRIVATE_C:.*]] = acc.private varPtr(%{{.*}} : !fir.ref<!fir.array<10x10xf32>>) recipe(@privatization_ref_10x10xf32) -> !fir.ref<!fir.array<10x10xf32>> {name = "c"} +! CHECK: %[[PRIVATE_D:.*]] = acc.private varPtr(%{{.*}} : !fir.ref<!fir.array<10x10xf32>>) recipe(@privatization_ref_10x10xf32) -> !fir.ref<!fir.array<10x10xf32>> {name = "d"} +! CHECK: %[[PRIVATE_I:.*]] = acc.private varPtr(%{{.*}} : !fir.ref<i32>) recipe(@privatization_ref_i32) -> !fir.ref<i32> {implicit = true, name = "i"} +! CHECK: acc.loop private(%[[PRIVATE_C]], %[[PRIVATE_D]], %[[PRIVATE_I]] : !fir.ref<!fir.array<10x10xf32>>, !fir.ref<!fir.array<10x10xf32>>, !fir.ref<i32>) control(%arg0 : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) { ! CHECK: acc.yield ! CHECK-NEXT: } attributes {inclusiveUpperbound = array<i1: true>, independent = [#acc.device_type<none>]} @@ -177,7 +196,10 @@ program acc_loop c(:,i) = d(:,i) END DO -! CHECK: acc.loop private(@privatization_ref_10x10xf32 -> %{{.*}} : !fir.ref<!fir.array<10x10xf32>>, @privatization_ref_10x10xf32 -> %{{.*}} : !fir.ref<!fir.array<10x10xf32>>, @privatization_ref_i32 -> %{{.*}} : !fir.ref<i32>) control(%arg0 : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) { +! CHECK: %[[PRIVATE_C:.*]] = acc.private varPtr(%{{.*}} : !fir.ref<!fir.array<10x10xf32>>) recipe(@privatization_ref_10x10xf32) -> !fir.ref<!fir.array<10x10xf32>> {name = "c"} +! CHECK: %[[PRIVATE_D:.*]] = acc.private varPtr(%{{.*}} : !fir.ref<!fir.array<10x10xf32>>) recipe(@privatization_ref_10x10xf32) -> !fir.ref<!fir.array<10x10xf32>> {name = "d"} +! CHECK: %[[PRIVATE_I:.*]] = acc.private varPtr(%{{.*}} : !fir.ref<i32>) recipe(@privatization_ref_i32) -> !fir.ref<i32> {implicit = true, name = "i"} +! CHECK: acc.loop private(%[[PRIVATE_C]], %[[PRIVATE_D]], %[[PRIVATE_I]] : !fir.ref<!fir.array<10x10xf32>>, !fir.ref<!fir.array<10x10xf32>>, !fir.ref<i32>) control(%arg0 : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) { ! CHECK: acc.yield ! CHECK-NEXT: } attributes {inclusiveUpperbound = array<i1: true>, independent = [#acc.device_type<none>]} @@ -312,7 +334,10 @@ program acc_loop reduction_i = 1 end do -! CHECK: acc.loop private(@privatization_ref_i32 -> %{{.*}} : !fir.ref<i32>) reduction(@reduction_add_ref_f32 -> %{{.*}} : !fir.ref<f32>, @reduction_mul_ref_i32 -> %{{.*}} : !fir.ref<i32>) control(%arg0 : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) { +! CHECK: %[[REDUCTION_R:.*]] = acc.reduction varPtr(%{{.*}} : !fir.ref<f32>) recipe(@reduction_add_ref_f32) -> !fir.ref<f32> {name = "reduction_r"} +! CHECK: %[[REDUCTION_I:.*]] = acc.reduction varPtr(%{{.*}} : !fir.ref<i32>) recipe(@reduction_mul_ref_i32) -> !fir.ref<i32> {name = "reduction_i"} +! CHECK: %[[PRIVATE_I:.*]] = acc.private varPtr(%{{.*}} : !fir.ref<i32>) recipe(@privatization_ref_i32) -> !fir.ref<i32> {implicit = true, name = "i"} +! CHECK: acc.loop private(%[[PRIVATE_I]] : !fir.ref<i32>) reduction(%[[REDUCTION_R]], %[[REDUCTION_I]] : !fir.ref<f32>, !fir.ref<i32>) control(%arg0 : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) { ! CHECK: acc.yield ! CHECK-NEXT: } attributes {inclusiveUpperbound = array<i1: true>, independent = [#acc.device_type<none>]} @@ -335,15 +360,6 @@ program acc_loop ! CHECK-NEXT: } attributes {inclusiveUpperbound = array<i1: true>, independent = [#acc.device_type<none>]} !$acc loop - DO i = 1, n - !$acc cache(b) - a(i) = b(i) - END DO - -! CHECK: %[[CACHE:.*]] = acc.cache varPtr(%{{.*}} : !fir.ref<!fir.array<10xf32>>) -> !fir.ref<!fir.array<10xf32>> {name = "b"} -! CHECK: acc.loop {{.*}} cache(%[[CACHE]] : !fir.ref<!fir.array<10xf32>>) - - !$acc loop do 100 i=0, n 100 continue ! CHECK: acc.loop @@ -376,11 +392,11 @@ end subroutine ! CHECK-SAME: %[[ARG_J:.*]]: !fir.ref<i32> {fir.bindc_name = "j"} ! CHECK-SAME: %[[ARG_K:.*]]: !fir.ref<i32> {fir.bindc_name = "k"} ! CHECK: %[[DC_I:.*]]:2 = hlfir.declare %[[ARG_I]] dummy_scope %0 -! CHECK: %[[DC_J:.*]]:2 = hlfir.declare %[[ARG_J]] dummy_scope %0 -! CHECK: %[[DC_K:.*]]:2 = hlfir.declare %[[ARG_K]] dummy_scope %0 +! CHECK: %[[DC_J:.*]]:2 = hlfir.declare %[[ARG_J]] dummy_scope %0 +! CHECK: %[[DC_K:.*]]:2 = hlfir.declare %[[ARG_K]] dummy_scope %0 ! CHECK: acc.parallel combined(loop) -! CHECK: %[[P_I:.*]] = acc.private varPtr(%[[DC_I]]#0 : !fir.ref<i32>) -> !fir.ref<i32> {implicit = true, name = "i"} -! CHECK: %[[P_J:.*]] = acc.private varPtr(%[[DC_J]]#0 : !fir.ref<i32>) -> !fir.ref<i32> {implicit = true, name = "j"} -! CHECK: %[[P_K:.*]] = acc.private varPtr(%[[DC_K]]#0 : !fir.ref<i32>) -> !fir.ref<i32> {implicit = true, name = "k"} -! CHECK: acc.loop combined(parallel) private(@privatization_ref_i32 -> %[[P_I]] : !fir.ref<i32>, @privatization_ref_i32 -> %[[P_J]] : !fir.ref<i32>, @privatization_ref_i32 -> %[[P_K]] : !fir.ref<i32>) control(%{{.*}} : i32, %{{.*}} : i32, %{{.*}} : i32) = (%c1{{.*}}, %c1{{.*}}, %c1{{.*}} : i32, i32, i32) to (%c10{{.*}}, %c100{{.*}}, %c200{{.*}} : i32, i32, i32) step (%c1{{.*}}, %c1{{.*}}, %c1{{.*}} : i32, i32, i32) +! CHECK: %[[P_I:.*]] = acc.private varPtr(%[[DC_I]]#0 : !fir.ref<i32>) recipe(@privatization_ref_i32) -> !fir.ref<i32> {implicit = true, name = "i"} +! CHECK: %[[P_J:.*]] = acc.private varPtr(%[[DC_J]]#0 : !fir.ref<i32>) recipe(@privatization_ref_i32) -> !fir.ref<i32> {implicit = true, name = "j"} +! CHECK: %[[P_K:.*]] = acc.private varPtr(%[[DC_K]]#0 : !fir.ref<i32>) recipe(@privatization_ref_i32) -> !fir.ref<i32> {implicit = true, name = "k"} +! CHECK: acc.loop combined(parallel) private(%[[P_I]], %[[P_J]], %[[P_K]] : !fir.ref<i32>, !fir.ref<i32>, !fir.ref<i32>) control(%{{.*}} : i32, %{{.*}} : i32, %{{.*}} : i32) = (%c1{{.*}}, %c1{{.*}}, %c1{{.*}} : i32, i32, i32) to (%c10{{.*}}, %c100{{.*}}, %c200{{.*}} : i32, i32, i32) step (%c1{{.*}}, %c1{{.*}}, %c1{{.*}} : i32, i32, i32) ! CHECK: } attributes {inclusiveUpperbound = array<i1: true, true, true>, independent = [#acc.device_type<none>]} diff --git a/flang/test/Lower/OpenACC/acc-parallel-loop.f90 b/flang/test/Lower/OpenACC/acc-parallel-loop.f90 index 8086080..b5ad46a 100644 --- a/flang/test/Lower/OpenACC/acc-parallel-loop.f90 +++ b/flang/test/Lower/OpenACC/acc-parallel-loop.f90 @@ -360,7 +360,7 @@ subroutine acc_parallel_loop END DO ! CHECK: %[[CREATE_A:.*]] = acc.create varPtr(%[[DECLA]]#0 : !fir.ref<!fir.array<10xf32>>) -> !fir.ref<!fir.array<10xf32>> {dataClause = #acc<data_clause acc_copyout>, name = "a"} -! CHECK: %[[CREATE_B:.*]] = acc.create varPtr(%[[DECLB]]#0 : !fir.ref<!fir.array<10xf32>>) -> !fir.ref<!fir.array<10xf32>> {dataClause = #acc<data_clause acc_copyout>, name = "b"} +! CHECK: %[[CREATE_B:.*]] = acc.create varPtr(%[[DECLB]]#0 : !fir.ref<!fir.array<10xf32>>) -> !fir.ref<!fir.array<10xf32>> {dataClause = #acc<data_clause acc_copyout_zero>, name = "b"} ! CHECK: acc.parallel {{.*}} dataOperands(%[[CREATE_A]], %[[CREATE_B]] : !fir.ref<!fir.array<10xf32>>, !fir.ref<!fir.array<10xf32>>) { ! CHECK: acc.loop {{.*}} { ! CHECK: acc.yield @@ -368,7 +368,7 @@ subroutine acc_parallel_loop ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} ! CHECK: acc.copyout accPtr(%[[CREATE_A]] : !fir.ref<!fir.array<10xf32>>) to varPtr(%[[DECLA]]#0 : !fir.ref<!fir.array<10xf32>>) {name = "a"} -! CHECK: acc.copyout accPtr(%[[CREATE_B]] : !fir.ref<!fir.array<10xf32>>) to varPtr(%[[DECLB]]#0 : !fir.ref<!fir.array<10xf32>>) {name = "b"} +! CHECK: acc.copyout accPtr(%[[CREATE_B]] : !fir.ref<!fir.array<10xf32>>) to varPtr(%[[DECLB]]#0 : !fir.ref<!fir.array<10xf32>>) {dataClause = #acc<data_clause acc_copyout_zero>, name = "b"} !$acc parallel loop create(b) create(zero: a) DO i = 1, n @@ -451,10 +451,10 @@ subroutine acc_parallel_loop a(i) = b(i) END DO -! CHECK: %[[ACC_PRIVATE_B:.*]] = acc.firstprivate varPtr(%[[DECLB]]#0 : !fir.ref<!fir.array<10xf32>>) -> !fir.ref<!fir.array<10xf32>> {name = "b"} -! CHECK: acc.parallel {{.*}} firstprivate(@firstprivatization_ref_10xf32 -> %[[ACC_PRIVATE_B]] : !fir.ref<!fir.array<10xf32>>) { -! CHECK: %[[ACC_PRIVATE_A:.*]] = acc.private varPtr(%[[DECLA]]#0 : !fir.ref<!fir.array<10xf32>>) -> !fir.ref<!fir.array<10xf32>> {name = "a"} -! CHECK: acc.loop {{.*}} private({{.*}}@privatization_ref_10xf32 -> %[[ACC_PRIVATE_A]] : !fir.ref<!fir.array<10xf32>>{{.*}}) +! CHECK: %[[ACC_PRIVATE_B:.*]] = acc.firstprivate varPtr(%[[DECLB]]#0 : !fir.ref<!fir.array<10xf32>>) recipe(@firstprivatization_ref_10xf32) -> !fir.ref<!fir.array<10xf32>> {name = "b"} +! CHECK: acc.parallel {{.*}} firstprivate(%[[ACC_PRIVATE_B]] : !fir.ref<!fir.array<10xf32>>) { +! CHECK: %[[ACC_PRIVATE_A:.*]] = acc.private varPtr(%[[DECLA]]#0 : !fir.ref<!fir.array<10xf32>>) recipe(@privatization_ref_10xf32) -> !fir.ref<!fir.array<10xf32>> {name = "a"} +! CHECK: acc.loop {{.*}} private(%[[ACC_PRIVATE_A]]{{.*}} : !fir.ref<!fir.array<10xf32>>{{.*}}) ! CHECK-NOT: fir.do_loop ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -722,7 +722,9 @@ subroutine acc_parallel_loop ! CHECK: %[[COPYINREDR:.*]] = acc.copyin varPtr(%{{.*}} : !fir.ref<f32>) -> !fir.ref<f32> {dataClause = #acc<data_clause acc_reduction>, implicit = true, name = "reduction_r"} ! CHECK: %[[COPYINREDI:.*]] = acc.copyin varPtr(%{{.*}} : !fir.ref<i32>) -> !fir.ref<i32> {dataClause = #acc<data_clause acc_reduction>, implicit = true, name = "reduction_i"} ! CHECK: acc.parallel {{.*}} dataOperands(%[[COPYINREDR]], %[[COPYINREDI]] : !fir.ref<f32>, !fir.ref<i32>) { -! CHECK: acc.loop {{.*}} reduction(@reduction_add_ref_f32 -> %{{.*}} : !fir.ref<f32>, @reduction_mul_ref_i32 -> %{{.*}} : !fir.ref<i32>) {{.*}} +! CHECK: %[[REDUCTION_R:.*]] = acc.reduction varPtr(%{{.*}} : !fir.ref<f32>) recipe(@reduction_add_ref_f32) -> !fir.ref<f32> {name = "reduction_r"} +! CHECK: %[[REDUCTION_I:.*]] = acc.reduction varPtr(%{{.*}} : !fir.ref<i32>) recipe(@reduction_mul_ref_i32) -> !fir.ref<i32> {name = "reduction_i"} +! CHECK: acc.loop {{.*}} reduction(%[[REDUCTION_R]], %[[REDUCTION_I]] : !fir.ref<f32>, !fir.ref<i32>) {{.*}} ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} ! CHECK: acc.yield diff --git a/flang/test/Lower/OpenACC/acc-parallel.f90 b/flang/test/Lower/OpenACC/acc-parallel.f90 index 1eae106..103dec2 100644 --- a/flang/test/Lower/OpenACC/acc-parallel.f90 +++ b/flang/test/Lower/OpenACC/acc-parallel.f90 @@ -252,13 +252,13 @@ subroutine acc_parallel !$acc end parallel ! CHECK: %[[CREATE_A:.*]] = acc.create varPtr(%[[DECLA]]#0 : !fir.ref<!fir.array<10x10xf32>>) -> !fir.ref<!fir.array<10x10xf32>> {dataClause = #acc<data_clause acc_copyout>, name = "a"} -! CHECK: %[[CREATE_B:.*]] = acc.create varPtr(%[[DECLB]]#0 : !fir.ref<!fir.array<10x10xf32>>) -> !fir.ref<!fir.array<10x10xf32>> {dataClause = #acc<data_clause acc_copyout>, name = "b"} +! CHECK: %[[CREATE_B:.*]] = acc.create varPtr(%[[DECLB]]#0 : !fir.ref<!fir.array<10x10xf32>>) -> !fir.ref<!fir.array<10x10xf32>> {dataClause = #acc<data_clause acc_copyout_zero>, name = "b"} ! CHECK: %[[CREATE_C:.*]] = acc.create varPtr(%[[DECLC]]#0 : !fir.ref<!fir.array<10x10xf32>>) -> !fir.ref<!fir.array<10x10xf32>> {dataClause = #acc<data_clause acc_copyout>, name = "c"} ! CHECK: acc.parallel dataOperands(%[[CREATE_A]], %[[CREATE_B]], %[[CREATE_C]] : !fir.ref<!fir.array<10x10xf32>>, !fir.ref<!fir.array<10x10xf32>>, !fir.ref<!fir.array<10x10xf32>>) { ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} ! CHECK: acc.copyout accPtr(%[[CREATE_A]] : !fir.ref<!fir.array<10x10xf32>>) to varPtr(%[[DECLA]]#0 : !fir.ref<!fir.array<10x10xf32>>) {name = "a"} -! CHECK: acc.copyout accPtr(%[[CREATE_B]] : !fir.ref<!fir.array<10x10xf32>>) to varPtr(%[[DECLB]]#0 : !fir.ref<!fir.array<10x10xf32>>) {name = "b"} +! CHECK: acc.copyout accPtr(%[[CREATE_B]] : !fir.ref<!fir.array<10x10xf32>>) to varPtr(%[[DECLB]]#0 : !fir.ref<!fir.array<10x10xf32>>) {dataClause = #acc<data_clause acc_copyout_zero>, name = "b"} ! CHECK: acc.copyout accPtr(%[[CREATE_C]] : !fir.ref<!fir.array<10x10xf32>>) to varPtr(%[[DECLC]]#0 : !fir.ref<!fir.array<10x10xf32>>) {name = "c"} !$acc parallel create(a, b) create(zero: c) @@ -330,17 +330,19 @@ subroutine acc_parallel !$acc parallel private(a) firstprivate(b) private(c) async(1) !$acc end parallel -! CHECK: %[[ACC_PRIVATE_A:.*]] = acc.private varPtr(%[[DECLA]]#0 : !fir.ref<!fir.array<10x10xf32>>) async([[ASYNC3:%.*]]) -> !fir.ref<!fir.array<10x10xf32>> {name = "a"} -! CHECK: %[[ACC_FPRIVATE_B:.*]] = acc.firstprivate varPtr(%[[DECLB]]#0 : !fir.ref<!fir.array<10x10xf32>>) async([[ASYNC3]]) -> !fir.ref<!fir.array<10x10xf32>> {name = "b"} -! CHECK: %[[ACC_PRIVATE_C:.*]] = acc.private varPtr(%[[DECLC]]#0 : !fir.ref<!fir.array<10x10xf32>>) async([[ASYNC3]]) -> !fir.ref<!fir.array<10x10xf32>> {name = "c"} -! CHECK: acc.parallel async([[ASYNC3]]) firstprivate(@firstprivatization_ref_10x10xf32 -> %[[ACC_FPRIVATE_B]] : !fir.ref<!fir.array<10x10xf32>>) private(@privatization_ref_10x10xf32 -> %[[ACC_PRIVATE_A]] : !fir.ref<!fir.array<10x10xf32>>, @privatization_ref_10x10xf32 -> %[[ACC_PRIVATE_C]] : !fir.ref<!fir.array<10x10xf32>>) { +! CHECK: %[[ACC_PRIVATE_A:.*]] = acc.private varPtr(%[[DECLA]]#0 : !fir.ref<!fir.array<10x10xf32>>) async([[ASYNC3:%.*]]) recipe(@privatization_ref_10x10xf32) -> !fir.ref<!fir.array<10x10xf32>> {name = "a"} +! CHECK: %[[ACC_FPRIVATE_B:.*]] = acc.firstprivate varPtr(%[[DECLB]]#0 : !fir.ref<!fir.array<10x10xf32>>) async([[ASYNC3]]) recipe(@firstprivatization_ref_10x10xf32) -> !fir.ref<!fir.array<10x10xf32>> {name = "b"} +! CHECK: %[[ACC_PRIVATE_C:.*]] = acc.private varPtr(%[[DECLC]]#0 : !fir.ref<!fir.array<10x10xf32>>) async([[ASYNC3]]) recipe(@privatization_ref_10x10xf32) -> !fir.ref<!fir.array<10x10xf32>> {name = "c"} +! CHECK: acc.parallel async([[ASYNC3]]) firstprivate(%[[ACC_FPRIVATE_B]] : !fir.ref<!fir.array<10x10xf32>>) private(%[[ACC_PRIVATE_A]], %[[ACC_PRIVATE_C]] : !fir.ref<!fir.array<10x10xf32>>, !fir.ref<!fir.array<10x10xf32>>) { ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} !$acc parallel reduction(+:reduction_r) reduction(*:reduction_i) !$acc end parallel -! CHECK: acc.parallel reduction(@reduction_add_ref_f32 -> %{{.*}} : !fir.ref<f32>, @reduction_mul_ref_i32 -> %{{.*}} : !fir.ref<i32>) { +! CHECK: %[[REDUCTION_R:.*]] = acc.reduction varPtr(%{{.*}} : !fir.ref<f32>) recipe(@reduction_add_ref_f32) -> !fir.ref<f32> +! CHECK: %[[REDUCTION_I:.*]] = acc.reduction varPtr(%{{.*}} : !fir.ref<i32>) recipe(@reduction_mul_ref_i32) -> !fir.ref<i32> +! CHECK: acc.parallel reduction(%[[REDUCTION_R]], %[[REDUCTION_I]] : !fir.ref<f32>, !fir.ref<i32>) { ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} diff --git a/flang/test/Lower/OpenACC/acc-private.f90 b/flang/test/Lower/OpenACC/acc-private.f90 index 485825d..c62e918 100644 --- a/flang/test/Lower/OpenACC/acc-private.f90 +++ b/flang/test/Lower/OpenACC/acc-private.f90 @@ -21,10 +21,7 @@ ! CHECK: acc.yield %[[DECL]]#0 : !fir.box<!fir.array<?x?x2xi32>> ! CHECK: } copy { ! CHECK: ^bb0(%[[ARG0:.*]]: !fir.box<!fir.array<?x?x2xi32>>, %[[ARG1:.*]]: !fir.box<!fir.array<?x?x2xi32>>): -! CHECK: %[[SHAPE:.*]] = fir.shape %{{.*}}, %{{.*}}, %{{.*}} : (index, index, index) -> !fir.shape<3> -! CHECK: %[[DES_SRC:.*]] = hlfir.designate %[[ARG0]] shape %[[SHAPE]] : (!fir.box<!fir.array<?x?x2xi32>>, !fir.shape<3>) -> !fir.box<!fir.array<?x?x2xi32>> -! CHECK: %[[DES_DST:.*]] = hlfir.designate %[[ARG1]] shape %[[SHAPE]] : (!fir.box<!fir.array<?x?x2xi32>>, !fir.shape<3>) -> !fir.box<!fir.array<?x?x2xi32>> -! CHECK: hlfir.assign %[[DES_SRC]] to %[[DES_DST]] : !fir.box<!fir.array<?x?x2xi32>>, !fir.box<!fir.array<?x?x2xi32>> +! CHECK: hlfir.assign %[[ARG0]] to %[[ARG1]] temporary_lhs : !fir.box<!fir.array<?x?x2xi32>>, !fir.box<!fir.array<?x?x2xi32>> ! CHECK: acc.terminator ! CHECK: } destroy { ! CHECK: ^bb0(%[[ARG0:.*]]: !fir.box<!fir.array<?x?x2xi32>>, %[[ARG1:.*]]: !fir.box<!fir.array<?x?x2xi32>>): @@ -38,20 +35,7 @@ ! CHECK: ^bb0(%{{.*}}: !fir.box<!fir.array<?xi32>>): ! CHECK: } copy { ! CHECK: ^bb0(%[[ARG0:.*]]: !fir.box<!fir.array<?xi32>>, %[[ARG1:.*]]: !fir.box<!fir.array<?xi32>>): -! CHECK: %[[LB:.*]] = arith.constant 4 : index -! CHECK: %[[UB:.*]] = arith.constant 9 : index -! CHECK: %[[STEP:.*]] = arith.constant 1 : index -! CHECK: %[[C1:.*]] = arith.constant 1 : index -! CHECK: %[[C0:.*]] = arith.constant 0 : index -! CHECK: %[[EXT0:.*]] = arith.subi %[[UB]], %[[LB]] : index -! CHECK: %[[EXT1:.*]] = arith.addi %[[EXT0]], %[[C1]] : index -! CHECK: %[[EXT2:.*]] = arith.divsi %[[EXT1]], %[[STEP]] : index -! CHECK: %[[CMP:.*]] = arith.cmpi sgt, %[[EXT2]], %[[C0]] : index -! CHECK: %[[SELECT:.*]] = arith.select %[[CMP]], %[[EXT2]], %[[C0]] : index -! CHECK: %[[SHAPE:.*]] = fir.shape %[[SELECT]] : (index) -> !fir.shape<1> -! CHECK: %[[LEFT:.*]] = hlfir.designate %[[ARG0]] shape %[[SHAPE]] : (!fir.box<!fir.array<?xi32>>, !fir.shape<1>) -> !fir.box<!fir.array<?xi32>> -! CHECK: %[[RIGHT:.*]] = hlfir.designate %[[ARG1]] shape %[[SHAPE]] : (!fir.box<!fir.array<?xi32>>, !fir.shape<1>) -> !fir.box<!fir.array<?xi32>> -! CHECK: hlfir.assign %[[LEFT]] to %[[RIGHT]] : !fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>> +! CHECK: hlfir.assign {{.*}} to {{.*}} temporary_lhs : !fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>> ! CHECK: acc.terminator ! CHECK: } destroy { ! CHECK: ^bb0(%[[ARG0:.*]]: !fir.box<!fir.array<?xi32>>, %[[ARG1:.*]]: !fir.box<!fir.array<?xi32>>): @@ -71,10 +55,7 @@ ! CHECK: acc.yield %[[DECL]]#0 : !fir.box<!fir.array<?xi32>> ! CHECK: } copy { ! CHECK: ^bb0(%[[ARG0:.*]]: !fir.box<!fir.array<?xi32>>, %[[ARG1:.*]]: !fir.box<!fir.array<?xi32>>): -! CHECK: %[[SHAPE:.*]] = fir.shape %{{.*}} : (index) -> !fir.shape<1> -! CHECK: %[[DES_V1:.*]] = hlfir.designate %[[ARG0]] shape %[[SHAPE]] : (!fir.box<!fir.array<?xi32>>, !fir.shape<1>) -> !fir.box<!fir.array<?xi32>> -! CHECK: %[[DES_V2:.*]] = hlfir.designate %[[ARG1]] shape %[[SHAPE]] : (!fir.box<!fir.array<?xi32>>, !fir.shape<1>) -> !fir.box<!fir.array<?xi32>> -! CHECK: hlfir.assign %[[DES_V1]] to %[[DES_V2]] : !fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>> +! CHECK: hlfir.assign %[[ARG0]] to %[[ARG1]] temporary_lhs : !fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>> ! CHECK: acc.terminator ! CHECK: } destroy { ! CHECK: ^bb0(%[[ARG0:.*]]: !fir.box<!fir.array<?xi32>>, %[[ARG1:.*]]: !fir.box<!fir.array<?xi32>>): @@ -183,12 +164,19 @@ ! CHECK: acc.yield %[[DECLARE]]#0 : !fir.ref<!fir.array<50xf32>> ! CHECK: } copy { ! CHECK: ^bb0(%[[SRC:.*]]: !fir.ref<!fir.array<50xf32>>, %[[DST:.*]]: !fir.ref<!fir.array<50xf32>>): -! CHECK: %[[SHAPE:.*]] = fir.shape %{{.*}} : (index) -> !fir.shape<1> -! CHECK: %[[DECL_SRC:.*]]:2 = hlfir.declare %[[SRC]](%[[SHAPE]]) {uniq_name = ""} : (!fir.ref<!fir.array<50xf32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<50xf32>>, !fir.ref<!fir.array<50xf32>>) -! CHECK: %[[DECL_DST:.*]]:2 = hlfir.declare %[[DST]](%[[SHAPE]]) {uniq_name = ""} : (!fir.ref<!fir.array<50xf32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<50xf32>>, !fir.ref<!fir.array<50xf32>>) -! CHECK: %[[DES_SRC:.*]] = hlfir.designate %[[DECL_SRC]]#0 shape %[[SHAPE:.*]] : (!fir.ref<!fir.array<50xf32>>, !fir.shape<1>) -> !fir.ref<!fir.array<50xf32>> -! CHECK: %[[DES_DST:.*]] = hlfir.designate %[[DECL_DST]]#0 shape %[[SHAPE:.*]] : (!fir.ref<!fir.array<50xf32>>, !fir.shape<1>) -> !fir.ref<!fir.array<50xf32>> -! CHECK: hlfir.assign %[[DES_SRC]] to %[[DES_DST]] : !fir.ref<!fir.array<50xf32>>, !fir.ref<!fir.array<50xf32>> +! CHECK: %[[C50:.*]] = arith.constant 50 : index +! CHECK: %[[C99:.*]] = arith.constant 99 : index +! CHECK: %[[C1:.*]] = arith.constant 1 : index +! CHECK: %[[C0:.*]] = arith.constant 0 : index +! CHECK: %[[D0:.*]] = arith.subi %[[C99]], %[[C50]] : index +! CHECK: %[[D1:.*]] = arith.addi %[[D0]], %[[C1]] : index +! CHECK: %[[D2:.*]] = arith.divsi %[[D1]], %[[C1]] : index +! CHECK: %[[CMP:.*]] = arith.cmpi sgt, %[[D2]], %[[C0]] : index +! CHECK: %[[SEL:.*]] = arith.select %[[CMP]], %[[D2]], %[[C0]] : index +! CHECK: %[[SH:.*]] = fir.shape %[[SEL]] : (index) -> !fir.shape<1> +! CHECK: %[[SEC_SRC:.*]] = hlfir.designate %[[SRC]] (%c51{{.*}}:%c100{{.*}}:%c1{{.*}}) shape %[[SH]] : (!fir.ref<!fir.array<50xf32>>, index, index, index, !fir.shape<1>) -> !fir.ref<!fir.array<50xf32>> +! CHECK: %[[SEC_DST:.*]] = hlfir.designate %[[DST]] (%c51{{.*}}:%c100{{.*}}:%c1{{.*}}) shape %[[SH]] : (!fir.ref<!fir.array<50xf32>>, index, index, index, !fir.shape<1>) -> !fir.ref<!fir.array<50xf32>> +! CHECK: hlfir.assign %[[SEC_SRC]] to %[[SEC_DST]] temporary_lhs : !fir.ref<!fir.array<50xf32>>, !fir.ref<!fir.array<50xf32>> ! CHECK: acc.terminator ! CHECK: } @@ -200,24 +188,19 @@ ! CHECK: acc.yield %[[DECLARE]]#0 : !fir.ref<!fir.array<100xf32>> ! CHECK: } copy { ! CHECK: ^bb0(%[[SRC:.*]]: !fir.ref<!fir.array<100xf32>>, %[[DST:.*]]: !fir.ref<!fir.array<100xf32>>): -! CHECK: %[[SHAPE:.*]] = fir.shape %{{.*}} : (index) -> !fir.shape<1> -! CHECK: %[[DECL_SRC:.*]]:2 = hlfir.declare %[[SRC]](%[[SHAPE]]) {uniq_name = ""} : (!fir.ref<!fir.array<100xf32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<100xf32>>, !fir.ref<!fir.array<100xf32>>) -! CHECK: %[[DECL_DST:.*]]:2 = hlfir.declare %[[DST]](%[[SHAPE]]) {uniq_name = ""} : (!fir.ref<!fir.array<100xf32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<100xf32>>, !fir.ref<!fir.array<100xf32>>) -! CHECK: %[[DES_SRC:.*]] = hlfir.designate %[[DECL_SRC]]#0 shape %[[SHAPE]] : (!fir.ref<!fir.array<100xf32>>, !fir.shape<1>) -> !fir.ref<!fir.array<100xf32>> -! CHECK: %[[DES_DST:.*]] = hlfir.designate %[[DECL_DST]]#0 shape %[[SHAPE]] : (!fir.ref<!fir.array<100xf32>>, !fir.shape<1>) -> !fir.ref<!fir.array<100xf32>> -! CHECK: hlfir.assign %[[DES_SRC]] to %[[DES_DST]] : !fir.ref<!fir.array<100xf32>>, !fir.ref<!fir.array<100xf32>> +! CHECK: hlfir.assign %[[SRC]] to %[[DST]] temporary_lhs : !fir.ref<!fir.array<100xf32>>, !fir.ref<!fir.array<100xf32>> ! CHECK: acc.terminator ! CHECK: } ! CHECK-LABEL: acc.firstprivate.recipe @firstprivatization_ref_i32 : !fir.ref<i32> init { ! CHECK: ^bb0(%{{.*}}: !fir.ref<i32>): ! CHECK: %[[ALLOCA:.*]] = fir.alloca i32 -! CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %[[ALLOCA]] {uniq_name = "acc.private.init"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) -! CHECK: acc.yield %[[DECLARE]]#0 : !fir.ref<i32> +! CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %[[ALLOCA]] {uniq_name = "acc.private.init"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: acc.yield %[[DECLARE]]#0 : !fir.ref<i32> ! CHECK: } copy { ! CHECK: ^bb0(%[[SRC:.*]]: !fir.ref<i32>, %[[DST:.*]]: !fir.ref<i32>): ! CHECK: %[[VALUE:.*]] = fir.load %[[SRC]] : !fir.ref<i32> -! CHECK: fir.store %[[VALUE]] to %[[DST]] : !fir.ref<i32> +! CHECK: fir.assign %[[VALUE]] to %[[DST]] temporary_lhs : i32, !fir.ref<i32> ! CHECK: acc.terminator ! CHECK: } @@ -240,8 +223,8 @@ ! CHECK-LABEL: acc.private.recipe @privatization_ref_i32 : !fir.ref<i32> init { ! CHECK: ^bb0(%{{.*}}: !fir.ref<i32>): ! CHECK: %[[ALLOCA:.*]] = fir.alloca i32 -! CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %[[ALLOCA]] {uniq_name = "acc.private.init"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) -! CHECK: acc.yield %[[DECLARE]]#0 : !fir.ref<i32> +! CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %[[ALLOCA]] {uniq_name = "acc.private.init"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: acc.yield %[[DECLARE]]#0 : !fir.ref<i32> ! CHECK: } program acc_private @@ -260,8 +243,8 @@ program acc_private a(i) = b(i) + c END DO -! CHECK: %[[C_PRIVATE:.*]] = acc.private varPtr(%[[DECLC]]#0 : !fir.ref<i32>) -> !fir.ref<i32> {name = "c"} -! CHECK: acc.loop private({{.*}}@privatization_ref_i32 -> %[[C_PRIVATE]] : !fir.ref<i32>{{.*}}) +! CHECK: %[[C_PRIVATE:.*]] = acc.private varPtr(%[[DECLC]]#0 : !fir.ref<i32>) recipe(@privatization_ref_i32) -> !fir.ref<i32> {name = "c"} +! CHECK: acc.loop private(%[[C_PRIVATE]]{{.*}} : !fir.ref<i32>{{.*}}) ! CHECK: acc.yield !$acc loop private(b) @@ -270,8 +253,8 @@ program acc_private a(i) = b(i) + c END DO -! CHECK: %[[B_PRIVATE:.*]] = acc.private varPtr(%[[DECLB]]#0 : !fir.ref<!fir.array<100xf32>>) -> !fir.ref<!fir.array<100xf32>> {name = "b"} -! CHECK: acc.loop private({{.*}}@privatization_ref_100xf32 -> %[[B_PRIVATE]] : !fir.ref<!fir.array<100xf32>>{{.*}}) +! CHECK: %[[B_PRIVATE:.*]] = acc.private varPtr(%[[DECLB]]#0 : !fir.ref<!fir.array<100xf32>>) recipe(@privatization_ref_100xf32) -> !fir.ref<!fir.array<100xf32>> {name = "b"} +! CHECK: acc.loop private(%[[B_PRIVATE]]{{.*}} : !fir.ref<!fir.array<100xf32>>{{.*}}) ! CHECK: acc.yield !$acc loop private(b(1:50)) @@ -284,8 +267,8 @@ program acc_private ! CHECK: %[[LB:.*]] = arith.constant 0 : index ! CHECK: %[[UB:.*]] = arith.constant 49 : index ! CHECK: %[[BOUND:.*]] = acc.bounds lowerbound(%[[LB]] : index) upperbound(%[[UB]] : index) extent(%{{.*}} : index) stride(%[[C1]] : index) startIdx(%[[C1]] : index) -! CHECK: %[[B_PRIVATE:.*]] = acc.private varPtr(%[[DECLB]]#0 : !fir.ref<!fir.array<100xf32>>) bounds(%[[BOUND]]) -> !fir.ref<!fir.array<50xf32>> {name = "b(1:50)"} -! CHECK: acc.loop private({{.*}}@privatization_ref_50xf32 -> %[[B_PRIVATE]] : !fir.ref<!fir.array<50xf32>>{{.*}}) +! CHECK: %[[B_PRIVATE:.*]] = acc.private varPtr(%[[DECLB]]#0 : !fir.ref<!fir.array<100xf32>>) bounds(%[[BOUND]]) recipe(@privatization_ref_50xf32) -> !fir.ref<!fir.array<50xf32>> {name = "b(1:50)"} +! CHECK: acc.loop private(%[[B_PRIVATE]]{{.*}} : !fir.ref<!fir.array<50xf32>>{{.*}}) !$acc parallel loop firstprivate(c) DO i = 1, n @@ -293,8 +276,8 @@ program acc_private a(i) = b(i) + c END DO -! CHECK: %[[FP_C:.*]] = acc.firstprivate varPtr(%[[DECLC]]#0 : !fir.ref<i32>) -> !fir.ref<i32> {name = "c"} -! CHECK: acc.parallel {{.*}} firstprivate(@firstprivatization_ref_i32 -> %[[FP_C]] : !fir.ref<i32>) +! CHECK: %[[FP_C:.*]] = acc.firstprivate varPtr(%[[DECLC]]#0 : !fir.ref<i32>) recipe(@firstprivatization_ref_i32) -> !fir.ref<i32> {name = "c"} +! CHECK: acc.parallel {{.*}} firstprivate(%[[FP_C]] : !fir.ref<i32>) ! CHECK: acc.yield !$acc parallel loop firstprivate(b) @@ -303,8 +286,8 @@ program acc_private a(i) = b(i) + c END DO -! CHECK: %[[FP_B:.*]] = acc.firstprivate varPtr(%[[DECLB]]#0 : !fir.ref<!fir.array<100xf32>>) -> !fir.ref<!fir.array<100xf32>> {name = "b"} -! CHECK: acc.parallel {{.*}} firstprivate(@firstprivatization_ref_100xf32 -> %[[FP_B]] : !fir.ref<!fir.array<100xf32>>) +! CHECK: %[[FP_B:.*]] = acc.firstprivate varPtr(%[[DECLB]]#0 : !fir.ref<!fir.array<100xf32>>) recipe(@firstprivatization_ref_100xf32) -> !fir.ref<!fir.array<100xf32>> {name = "b"} +! CHECK: acc.parallel {{.*}} firstprivate(%[[FP_B]] : !fir.ref<!fir.array<100xf32>>) ! CHECK: acc.yield !$acc parallel loop firstprivate(b(51:100)) @@ -317,8 +300,8 @@ program acc_private ! CHECK: %[[LB:.*]] = arith.constant 50 : index ! CHECK: %[[UB:.*]] = arith.constant 99 : index ! CHECK: %[[BOUND:.*]] = acc.bounds lowerbound(%[[LB]] : index) upperbound(%[[UB]] : index) extent(%{{.*}} : index) stride(%[[C1]] : index) startIdx(%[[C1]] : index) -! CHECK: %[[FP_B:.*]] = acc.firstprivate varPtr(%[[DECLB]]#0 : !fir.ref<!fir.array<100xf32>>) bounds(%[[BOUND]]) -> !fir.ref<!fir.array<50xf32>> {name = "b(51:100)"} -! CHECK: acc.parallel {{.*}} firstprivate(@firstprivatization_section_lb50.ub99_ref_50xf32 -> %[[FP_B]] : !fir.ref<!fir.array<50xf32>>) +! CHECK: %[[FP_B:.*]] = acc.firstprivate varPtr(%[[DECLB]]#0 : !fir.ref<!fir.array<100xf32>>) bounds(%[[BOUND]]) recipe(@firstprivatization_section_lb50.ub99_ref_50xf32) -> !fir.ref<!fir.array<50xf32>> {name = "b(51:100)"} +! CHECK: acc.parallel {{.*}} firstprivate(%[[FP_B]] : !fir.ref<!fir.array<50xf32>>) end program @@ -333,10 +316,10 @@ end subroutine ! CHECK-LABEL: func.func @_QPacc_private_assumed_shape( ! CHECK-SAME: %[[ARG0:.*]]: !fir.box<!fir.array<?xi32>> {fir.bindc_name = "a"} -! CHECK: %[[DECL_A:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFacc_private_assumed_shapeEa"} : (!fir.box<!fir.array<?xi32>>, !fir.dscope) -> (!fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>>) +! CHECK: %[[DECL_A:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFacc_private_assumed_shapeEa"} : (!fir.box<!fir.array<?xi32>>, !fir.dscope) -> (!fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>>) ! CHECK: acc.parallel {{.*}} { -! CHECK: %[[PRIVATE:.*]] = acc.private var(%[[DECL_A]]#0 : !fir.box<!fir.array<?xi32>>) -> !fir.box<!fir.array<?xi32>> {name = "a"} -! CHECK: acc.loop {{.*}} private({{.*}}@privatization_box_Uxi32 -> %[[PRIVATE]] : !fir.box<!fir.array<?xi32>>{{.*}}) +! CHECK: %[[PRIVATE:.*]] = acc.private var(%[[DECL_A]]#0 : !fir.box<!fir.array<?xi32>>) recipe(@privatization_box_Uxi32) -> !fir.box<!fir.array<?xi32>> {name = "a"} +! CHECK: acc.loop {{.*}} private(%[[PRIVATE]]{{.*}} : !fir.box<!fir.array<?xi32>>{{.*}}) subroutine acc_private_allocatable_array(a, n) integer, allocatable :: a(:) @@ -354,11 +337,12 @@ end subroutine ! CHECK-LABEL: func.func @_QPacc_private_allocatable_array( ! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> {fir.bindc_name = "a"} -! CHECK: %[[DECLA_A:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFacc_private_allocatable_arrayEa"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) +! CHECK: %[[DECLA_A:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFacc_private_allocatable_arrayEa"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) ! CHECK: acc.parallel {{.*}} { -! CHECK: %[[PRIVATE:.*]] = acc.private varPtr(%[[DECLA_A]]#0 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> {name = "a"} -! CHECK: acc.loop {{.*}} private({{.*}}@privatization_ref_box_heap_Uxi32 -> %[[PRIVATE]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>{{.*}}) -! CHECK: acc.serial private(@privatization_ref_box_heap_Uxi32 -> %{{.*}} : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) +! CHECK: %[[PRIVATE:.*]] = acc.private varPtr(%[[DECLA_A]]#0 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) recipe(@privatization_ref_box_heap_Uxi32) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> {name = "a"} +! CHECK: acc.loop {{.*}} private(%[[PRIVATE]]{{.*}} : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>{{.*}}) +! CHECK: %[[PRIVATE_SERIAL:.*]] = acc.private varPtr(%{{.*}} : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) recipe(@privatization_ref_box_heap_Uxi32) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> +! CHECK: acc.serial private(%[[PRIVATE_SERIAL]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) subroutine acc_private_allocatable_scalar(b, a, n) integer :: a(n) @@ -377,11 +361,12 @@ end subroutine ! CHECK-LABEL: func.func @_QPacc_private_allocatable_scalar( ! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.box<!fir.heap<i32>>> {fir.bindc_name = "b"} -! CHECK: %[[DECLA_B:.*]]:2 = hlfir.declare %arg0 dummy_scope %0 {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFacc_private_allocatable_scalarEb"} : (!fir.ref<!fir.box<!fir.heap<i32>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<i32>>>, !fir.ref<!fir.box<!fir.heap<i32>>>) +! CHECK: %[[DECLA_B:.*]]:2 = hlfir.declare %arg0 dummy_scope %0 {{.*}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFacc_private_allocatable_scalarEb"} : (!fir.ref<!fir.box<!fir.heap<i32>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<i32>>>, !fir.ref<!fir.box<!fir.heap<i32>>>) ! CHECK: acc.parallel {{.*}} { -! CHECK: %[[PRIVATE:.*]] = acc.private varPtr(%[[DECLA_B]]#0 : !fir.ref<!fir.box<!fir.heap<i32>>>) -> !fir.ref<!fir.box<!fir.heap<i32>>> {name = "b"} -! CHECK: acc.loop {{.*}} private({{.*}}@privatization_ref_box_heap_i32 -> %[[PRIVATE]] : !fir.ref<!fir.box<!fir.heap<i32>>>{{.*}}) -! CHECK: acc.serial private(@privatization_ref_box_heap_i32 -> %{{.*}} : !fir.ref<!fir.box<!fir.heap<i32>>>) { +! CHECK: %[[PRIVATE:.*]] = acc.private varPtr(%[[DECLA_B]]#0 : !fir.ref<!fir.box<!fir.heap<i32>>>) recipe(@privatization_ref_box_heap_i32) -> !fir.ref<!fir.box<!fir.heap<i32>>> {name = "b"} +! CHECK: acc.loop {{.*}} private(%[[PRIVATE]]{{.*}} : !fir.ref<!fir.box<!fir.heap<i32>>>{{.*}}) +! CHECK: %[[PRIVATE_SERIAL:.*]] = acc.private varPtr(%{{.*}} : !fir.ref<!fir.box<!fir.heap<i32>>>) recipe(@privatization_ref_box_heap_i32) -> !fir.ref<!fir.box<!fir.heap<i32>>> +! CHECK: acc.serial private(%[[PRIVATE_SERIAL]] : !fir.ref<!fir.box<!fir.heap<i32>>>) { subroutine acc_private_pointer_array(a, n) integer, pointer :: a(:) @@ -395,10 +380,10 @@ end subroutine ! CHECK-LABEL: func.func @_QPacc_private_pointer_array( ! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>> {fir.bindc_name = "a"}, %arg1: !fir.ref<i32> {fir.bindc_name = "n"}) { -! CHECK: %[[DECL_A:.*]]:2 = hlfir.declare %arg0 dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFacc_private_pointer_arrayEa"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>) +! CHECK: %[[DECL_A:.*]]:2 = hlfir.declare %arg0 dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFacc_private_pointer_arrayEa"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>) ! CHECK: acc.parallel {{.*}} { -! CHECK: %[[PRIVATE:.*]] = acc.private varPtr(%[[DECLA_A]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>) -> !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>> {name = "a"} -! CHECK: acc.loop {{.*}} private({{.*}}@privatization_ref_box_ptr_Uxi32 -> %[[PRIVATE]] : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>{{.*}}) +! CHECK: %[[PRIVATE:.*]] = acc.private varPtr(%[[DECLA_A]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>) recipe(@privatization_ref_box_ptr_Uxi32) -> !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>> {name = "a"} +! CHECK: acc.loop {{.*}} private(%[[PRIVATE]]{{.*}} : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>{{.*}}) subroutine acc_private_dynamic_extent(a, n) integer :: n, i @@ -412,11 +397,11 @@ end subroutine ! CHECK-LABEL: func.func @_QPacc_private_dynamic_extent( ! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.array<?x?x2xi32>> {fir.bindc_name = "a"}, %[[ARG1:.*]]: !fir.ref<i32> {fir.bindc_name = "n"}) { -! CHECK: %[[DECL_N:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFacc_private_dynamic_extentEn"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) -! CHECK: %[[DECL_A:.*]]:2 = hlfir.declare %[[ARG0]](%{{.*}}) dummy_scope %{{[0-9]+}} {uniq_name = "_QFacc_private_dynamic_extentEa"} : (!fir.ref<!fir.array<?x?x2xi32>>, !fir.shape<3>, !fir.dscope) -> (!fir.box<!fir.array<?x?x2xi32>>, !fir.ref<!fir.array<?x?x2xi32>>) +! CHECK: %[[DECL_N:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFacc_private_dynamic_extentEn"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[DECL_A:.*]]:2 = hlfir.declare %[[ARG0]](%{{.*}}) dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFacc_private_dynamic_extentEa"} : (!fir.ref<!fir.array<?x?x2xi32>>, !fir.shape<3>, !fir.dscope) -> (!fir.box<!fir.array<?x?x2xi32>>, !fir.ref<!fir.array<?x?x2xi32>>) ! CHECK: acc.parallel {{.*}} { -! CHECK: %[[PRIV:.*]] = acc.private var(%[[DECL_A]]#0 : !fir.box<!fir.array<?x?x2xi32>>) -> !fir.box<!fir.array<?x?x2xi32>> {name = "a"} -! CHECK: acc.loop {{.*}} private({{.*}}@privatization_box_UxUx2xi32 -> %[[PRIV]] : !fir.box<!fir.array<?x?x2xi32>>{{.*}}) +! CHECK: %[[PRIV:.*]] = acc.private var(%[[DECL_A]]#0 : !fir.box<!fir.array<?x?x2xi32>>) recipe(@privatization_box_UxUx2xi32) -> !fir.box<!fir.array<?x?x2xi32>> {name = "a"} +! CHECK: acc.loop {{.*}} private(%[[PRIV]]{{.*}} : !fir.box<!fir.array<?x?x2xi32>>{{.*}}) subroutine acc_firstprivate_assumed_shape(a, n) integer :: a(:), i, n @@ -427,6 +412,10 @@ subroutine acc_firstprivate_assumed_shape(a, n) end do end subroutine +! CHECK-LABEL: func.func @_QPacc_firstprivate_assumed_shape +! CHECK: %[[FIRSTPRIVATE_A:.*]] = acc.firstprivate var(%{{.*}} : !fir.box<!fir.array<?xi32>>) recipe(@firstprivatization_box_Uxi32) -> !fir.box<!fir.array<?xi32>> {name = "a"} +! CHECK: acc.parallel {{.*}}firstprivate(%[[FIRSTPRIVATE_A]] : !fir.box<!fir.array<?xi32>>) { + subroutine acc_firstprivate_assumed_shape_with_section(a, n) integer :: a(:), i, n @@ -436,6 +425,10 @@ subroutine acc_firstprivate_assumed_shape_with_section(a, n) end do end subroutine +! CHECK-LABEL: func.func @_QPacc_firstprivate_assumed_shape_with_section +! CHECK: %[[FIRSTPRIVATE_A:.*]] = acc.firstprivate var(%{{.*}} : !fir.box<!fir.array<?xi32>>) bounds(%{{.*}}) recipe(@firstprivatization_section_lb4.ub9_box_Uxi32) -> !fir.box<!fir.array<?xi32>> {name = "a(5:10)"} +! CHECK: acc.parallel {{.*}}firstprivate(%[[FIRSTPRIVATE_A]] : !fir.box<!fir.array<?xi32>>) + subroutine acc_firstprivate_dynamic_extent(a, n) integer :: n, i integer :: a(n, n, 2) @@ -446,7 +439,9 @@ subroutine acc_firstprivate_dynamic_extent(a, n) end do end subroutine -! CHECK: acc.parallel {{.*}} firstprivate(@firstprivatization_box_UxUx2xi32 -> %{{.*}} : !fir.box<!fir.array<?x?x2xi32>>) +! CHECK-LABEL: func.func @_QPacc_firstprivate_dynamic_extent +! CHECK: %[[FIRSTPRIVATE_A:.*]] = acc.firstprivate var(%{{.*}} : !fir.box<!fir.array<?x?x2xi32>>) recipe(@firstprivatization_box_UxUx2xi32) -> !fir.box<!fir.array<?x?x2xi32>> {name = "a"} +! CHECK: acc.parallel {{.*}}firstprivate(%[[FIRSTPRIVATE_A]] : !fir.box<!fir.array<?x?x2xi32>>) module acc_declare_equivalent integer, parameter :: n = 10 @@ -460,7 +455,8 @@ contains end subroutine end module -! CHECK: acc.parallel private(@privatization_ptr_10xf32 -> %{{.*}} : !fir.ptr<!fir.array<10xf32>>) +! CHECK: %[[PRIVATE_V2:.*]] = acc.private varPtr(%{{.*}} : !fir.ptr<!fir.array<10xf32>>) recipe(@privatization_ptr_10xf32) -> !fir.ptr<!fir.array<10xf32>> +! CHECK: acc.parallel private(%[[PRIVATE_V2]] : !fir.ptr<!fir.array<10xf32>>) subroutine acc_private_use() integer :: i, j @@ -475,8 +471,8 @@ end ! CHECK: %[[I:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFacc_private_useEi"} ! CHECK: %[[DECL_I:.*]]:2 = hlfir.declare %[[I]] {uniq_name = "_QFacc_private_useEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: acc.parallel -! CHECK: %[[PRIV_I:.*]] = acc.private varPtr(%[[DECL_I]]#0 : !fir.ref<i32>) -> !fir.ref<i32> {implicit = true, name = "i"} -! CHECK: acc.loop {{.*}} private(@privatization_ref_i32 -> %[[PRIV_I]] : !fir.ref<i32>) control(%[[IV0:.*]] : i32) = (%c1{{.*}} : i32) to (%c10{{.*}} : i32) step (%c1{{.*}} : i32) +! CHECK: %[[PRIV_I:.*]] = acc.private varPtr(%[[DECL_I]]#0 : !fir.ref<i32>) recipe(@privatization_ref_i32) -> !fir.ref<i32> {implicit = true, name = "i"} +! CHECK: acc.loop {{.*}} private(%[[PRIV_I]] : !fir.ref<i32>) control(%[[IV0:.*]] : i32) = (%c1{{.*}} : i32) to (%c10{{.*}} : i32) step (%c1{{.*}} : i32) ! CHECK: %[[DECL_PRIV_I:.*]]:2 = hlfir.declare %[[PRIV_I]] {uniq_name = "_QFacc_private_useEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: fir.store %[[IV0]] to %[[DECL_PRIV_I]]#0 : !fir.ref<i32> ! CHECK: %{{.*}} = fir.load %[[DECL_PRIV_I]]#0 : !fir.ref<i32> diff --git a/flang/test/Lower/OpenACC/acc-reduction-remapping.f90 b/flang/test/Lower/OpenACC/acc-reduction-remapping.f90 new file mode 100644 index 0000000..8c69efe --- /dev/null +++ b/flang/test/Lower/OpenACC/acc-reduction-remapping.f90 @@ -0,0 +1,160 @@ +! Test remapping of variables appearing in OpenACC reduction clause +! to the related acc dialect data operation result. + +! This tests checks how the hlfir.declare is recreated and used inside +! the acc compute region. + +! RUN: bbc -fopenacc -emit-hlfir %s -o - | FileCheck %s + +subroutine scalar_combined(x, y) + real :: y, x(100) + !$acc parallel copyin(x) reduction(+:y) + do i=1,100 + y = y + x(i) + end do + !$acc end parallel +end subroutine + +subroutine scalar_split(x, y) + real :: y, x(100) + !$acc parallel copyin(x) copyout(y) + !$acc loop reduction(+:y) + do i=1,100 + y = y + x(i) + end do + !$acc end parallel +end subroutine + +subroutine array_combined(x, y, n) + integer(8) :: n + real :: y(n), x(100, n) + !$acc parallel copyin(x) reduction(+:y) + do j=1,n + do i=1,100 + y(j) = y(j) + x(i, j) + end do + end do + !$acc end parallel +end subroutine + +subroutine array_split(x, y, n) + integer(8) :: n + real :: y(n), x(100, n) + !$acc parallel copyin(x) copyout(y) + !$acc loop reduction(+:y) + do j=1,n + do i=1,100 + y(j) = y(j) + x(i, j) + end do + end do + !$acc end parallel +end subroutine + +! CHECK-LABEL: func.func @_QPscalar_combined( +! CHECK: %[[DUMMY_SCOPE_0:.*]] = fir.dummy_scope : !fir.dscope +! CHECK: %[[DECLARE_Y:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %[[DUMMY_SCOPE_0]] arg 2 {uniq_name = "_QFscalar_combinedEy"} : (!fir.ref<f32>, !fir.dscope) -> (!fir.ref<f32>, !fir.ref<f32>) +! CHECK: %[[REDUCTION_Y:.*]] = acc.reduction varPtr(%[[DECLARE_Y]]#0 : !fir.ref<f32>) recipe(@reduction_add_ref_f32) -> !fir.ref<f32> {name = "y"} +! CHECK: acc.parallel {{.*}} reduction(%[[REDUCTION_Y]] : !fir.ref<f32>) { +! CHECK: %[[DUMMY_SCOPE_1:.*]] = fir.dummy_scope : !fir.dscope +! CHECK: %[[DECLARE_RED_PAR:.*]]:2 = hlfir.declare %[[REDUCTION_Y]] dummy_scope %[[DUMMY_SCOPE_1]] arg 2 {uniq_name = "_QFscalar_combinedEy"} : (!fir.ref<f32>, !fir.dscope) -> (!fir.ref<f32>, !fir.ref<f32>) +! CHECK: %[[PRIVATE_I:.*]] = acc.private varPtr({{.*}}) recipe(@privatization_ref_i32) -> !fir.ref<i32> {implicit = true, name = "i"} +! CHECK: acc.loop private(%[[PRIVATE_I]] : !fir.ref<i32>) {{.*}} { +! CHECK: %[[DECLARE_I:.*]]:2 = hlfir.declare %[[PRIVATE_I]] {uniq_name = "_QFscalar_combinedEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: fir.store %[[VAL_0:.*]] to %[[DECLARE_I]]#0 : !fir.ref<i32> +! CHECK: %[[LOAD_RED:.*]] = fir.load %[[DECLARE_RED_PAR]]#0 : !fir.ref<f32> +! CHECK: {{.*}} = hlfir.designate {{.*}} : (!fir.ref<!fir.array<100xf32>>, i64) -> !fir.ref<f32> +! CHECK: {{.*}} = fir.load {{.*}} : !fir.ref<f32> +! CHECK: %[[ADDF:.*]] = arith.addf %[[LOAD_RED]], {{.*}} {{.*}}: f32 +! CHECK: hlfir.assign %[[ADDF]] to %[[DECLARE_RED_PAR]]#0 : f32, !fir.ref<f32> +! CHECK: acc.yield +! CHECK: } +! CHECK: acc.yield +! CHECK: } +! CHECK: return +! CHECK: } +! +! +! CHECK-LABEL: func.func @_QPscalar_split( +! CHECK: %[[DUMMY_SCOPE_0:.*]] = fir.dummy_scope : !fir.dscope +! CHECK: %[[DECLARE_Y:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %[[DUMMY_SCOPE_0]] arg 2 {uniq_name = "_QFscalar_splitEy"} : (!fir.ref<f32>, !fir.dscope) -> (!fir.ref<f32>, !fir.ref<f32>) +! CHECK: %[[CREATE_Y:.*]] = acc.create varPtr(%[[DECLARE_Y]]#0 : !fir.ref<f32>) -> !fir.ref<f32> {dataClause = #acc<data_clause acc_copyout>, name = "y"} +! CHECK: acc.parallel dataOperands({{.*}}%[[CREATE_Y]] : {{.*}}) { +! CHECK: %[[DUMMY_SCOPE_1:.*]] = fir.dummy_scope : !fir.dscope +! CHECK: %[[DECLARE_Y_PAR:.*]]:2 = hlfir.declare %[[CREATE_Y]] dummy_scope %[[DUMMY_SCOPE_1]] arg 2 {uniq_name = "_QFscalar_splitEy"} : (!fir.ref<f32>, !fir.dscope) -> (!fir.ref<f32>, !fir.ref<f32>) +! CHECK: %[[REDUCTION_Y:.*]] = acc.reduction varPtr(%[[DECLARE_Y_PAR]]#0 : !fir.ref<f32>) recipe(@reduction_add_ref_f32) -> !fir.ref<f32> {name = "y"} +! CHECK: %[[PRIVATE_I:.*]] = acc.private varPtr({{.*}}) recipe(@privatization_ref_i32) -> !fir.ref<i32> {implicit = true, name = "i"} +! CHECK: acc.loop private(%[[PRIVATE_I]] : !fir.ref<i32>) reduction(%[[REDUCTION_Y]] : !fir.ref<f32>) {{.*}} { +! CHECK: %[[DUMMY_SCOPE_2:.*]] = fir.dummy_scope : !fir.dscope +! CHECK: %[[DECLARE_RED:.*]]:2 = hlfir.declare %[[REDUCTION_Y]] dummy_scope %[[DUMMY_SCOPE_2]] arg 2 {uniq_name = "_QFscalar_splitEy"} : (!fir.ref<f32>, !fir.dscope) -> (!fir.ref<f32>, !fir.ref<f32>) +! CHECK: %[[LOAD_RED:.*]] = fir.load %[[DECLARE_RED]]#0 : !fir.ref<f32> +! CHECK: %[[ADDF:.*]] = arith.addf %[[LOAD_RED]], {{.*}} {{.*}}: f32 +! CHECK: hlfir.assign %[[ADDF]] to %[[DECLARE_RED]]#0 : f32, !fir.ref<f32> +! CHECK: acc.yield +! CHECK: } +! CHECK: acc.yield +! CHECK: } +! CHECK: return +! CHECK: } + + +! CHECK-LABEL: func.func @_QParray_combined( +! CHECK: %[[DUMMY_SCOPE_0:.*]] = fir.dummy_scope : !fir.dscope +! CHECK: %[[DECLARE_N:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %[[DUMMY_SCOPE_0]] arg 3 {uniq_name = "_QFarray_combinedEn"} : (!fir.ref<i64>, !fir.dscope) -> (!fir.ref<i64>, !fir.ref<i64>) +! CHECK: %[[DECLARE_Y:.*]]:2 = hlfir.declare %{{.*}}({{.*}}) dummy_scope %[[DUMMY_SCOPE_0]] arg 2 {uniq_name = "_QFarray_combinedEy"} : (!fir.ref<!fir.array<?xf32>>, {{.*}}, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.ref<!fir.array<?xf32>>) +! CHECK: %[[REDUCTION_Y:.*]] = acc.reduction var(%[[DECLARE_Y]]#0 : !fir.box<!fir.array<?xf32>>) recipe(@reduction_add_box_Uxf32) -> !fir.box<!fir.array<?xf32>> {name = "y"} +! CHECK: acc.parallel dataOperands({{.*}}) reduction(%[[REDUCTION_Y]] : !fir.box<!fir.array<?xf32>>) { +! CHECK: %[[DUMMY_SCOPE_1:.*]] = fir.dummy_scope : !fir.dscope +! CHECK: %[[BOX_ADDR_RED:.*]] = fir.box_addr %[[REDUCTION_Y]] : (!fir.box<!fir.array<?xf32>>) -> !fir.ref<!fir.array<?xf32>> +! CHECK: %[[DECLARE_Y_PAR:.*]]:2 = hlfir.declare %[[BOX_ADDR_RED]]({{.*}}) dummy_scope %[[DUMMY_SCOPE_1]] arg 2 {uniq_name = "_QFarray_combinedEy"} : (!fir.ref<!fir.array<?xf32>>, {{.*}}, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.ref<!fir.array<?xf32>>) +! CHECK: %[[PRIVATE_J:.*]] = acc.private varPtr({{.*}}) recipe(@privatization_ref_i32) -> !fir.ref<i32> {implicit = true, name = "j"} +! CHECK: acc.loop private(%[[PRIVATE_J]] : !fir.ref<i32>) {{.*}} { +! CHECK: %[[PRIVATE_I:.*]] = acc.private varPtr({{.*}}) recipe(@privatization_ref_i32) -> !fir.ref<i32> {implicit = true, name = "i"} +! CHECK: acc.loop private(%[[PRIVATE_I]] : !fir.ref<i32>) {{.*}} { +! CHECK: %[[DESIGNATE_RED:.*]] = hlfir.designate %[[DECLARE_Y_PAR]]#0 ({{.*}}) : (!fir.box<!fir.array<?xf32>>, i64) -> !fir.ref<f32> +! CHECK: %[[LOAD_OLD:.*]] = fir.load %[[DESIGNATE_RED]] : !fir.ref<f32> +! CHECK: {{.*}} = hlfir.designate {{.*}} : (!fir.box<!fir.array<100x?xf32>>, i64, i64) -> !fir.ref<f32> +! CHECK: {{.*}} = fir.load {{.*}} : !fir.ref<f32> +! CHECK: %[[ADDF:.*]] = arith.addf %[[LOAD_OLD]], {{.*}} {{.*}}: f32 +! CHECK: %[[DESIGNATE_RED2:.*]] = hlfir.designate %[[DECLARE_Y_PAR]]#0 ({{.*}}) : (!fir.box<!fir.array<?xf32>>, i64) -> !fir.ref<f32> +! CHECK: hlfir.assign %[[ADDF]] to %[[DESIGNATE_RED2]] : f32, !fir.ref<f32> +! CHECK: acc.yield +! CHECK: } +! CHECK: acc.yield +! CHECK: } +! CHECK: acc.yield +! CHECK: } +! CHECK: return +! CHECK: } + + +! CHECK-LABEL: func.func @_QParray_split( +! CHECK: %[[DUMMY_SCOPE_0:.*]] = fir.dummy_scope : !fir.dscope +! CHECK: %[[DECLARE_Y:.*]]:2 = hlfir.declare %{{.*}}({{.*}}) dummy_scope %[[DUMMY_SCOPE_0]] arg 2 {uniq_name = "_QFarray_splitEy"} : (!fir.ref<!fir.array<?xf32>>, {{.*}}, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.ref<!fir.array<?xf32>>) +! CHECK: %[[CREATE_Y:.*]] = acc.create var(%[[DECLARE_Y]]#0 : !fir.box<!fir.array<?xf32>>) -> !fir.box<!fir.array<?xf32>> {dataClause = #acc<data_clause acc_copyout>, name = "y"} +! CHECK: acc.parallel dataOperands({{.*}}%[[CREATE_Y]] : {{.*}}) { +! CHECK: %[[DUMMY_SCOPE_1:.*]] = fir.dummy_scope : !fir.dscope +! CHECK: %[[BOX_ADDR_Y:.*]] = fir.box_addr %[[CREATE_Y]] : (!fir.box<!fir.array<?xf32>>) -> !fir.ref<!fir.array<?xf32>> +! CHECK: %[[DECLARE_Y_PAR:.*]]:2 = hlfir.declare %[[BOX_ADDR_Y]]({{.*}}) dummy_scope %[[DUMMY_SCOPE_1]] arg 2 {uniq_name = "_QFarray_splitEy"} : (!fir.ref<!fir.array<?xf32>>, {{.*}}, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.ref<!fir.array<?xf32>>) +! CHECK: %[[REDUCTION_Y:.*]] = acc.reduction var(%[[DECLARE_Y_PAR]]#0 : !fir.box<!fir.array<?xf32>>) recipe(@reduction_add_box_Uxf32) -> !fir.box<!fir.array<?xf32>> {name = "y"} +! CHECK: %[[PRIVATE_J:.*]] = acc.private varPtr({{.*}}) recipe(@privatization_ref_i32) -> !fir.ref<i32> {implicit = true, name = "j"} +! CHECK: acc.loop private(%[[PRIVATE_J]] : !fir.ref<i32>) reduction(%[[REDUCTION_Y]] : !fir.box<!fir.array<?xf32>>) {{.*}} { +! CHECK: %[[BOX_ADDR_RED:.*]] = fir.box_addr %[[REDUCTION_Y]] : (!fir.box<!fir.array<?xf32>>) -> !fir.ref<!fir.array<?xf32>> +! CHECK: %[[DUMMY_SCOPE_2:.*]] = fir.dummy_scope : !fir.dscope +! CHECK: %[[DECLARE_Y_LOOP_PAR:.*]]:2 = hlfir.declare %[[BOX_ADDR_RED]]({{.*}}) dummy_scope %[[DUMMY_SCOPE_2]] arg 2 {uniq_name = "_QFarray_splitEy"} : (!fir.ref<!fir.array<?xf32>>, {{.*}}, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.ref<!fir.array<?xf32>>) +! CHECK: %[[PRIVATE_I:.*]] = acc.private varPtr({{.*}}) recipe(@privatization_ref_i32) -> !fir.ref<i32> {implicit = true, name = "i"} +! CHECK: acc.loop private(%[[PRIVATE_I]] : !fir.ref<i32>) {{.*}} { +! CHECK: %[[DESIGNATE_RED:.*]] = hlfir.designate %[[DECLARE_Y_LOOP_PAR]]#0 ({{.*}}) : (!fir.box<!fir.array<?xf32>>, i64) -> !fir.ref<f32> +! CHECK: %[[LOAD_OLD:.*]] = fir.load %[[DESIGNATE_RED]] : !fir.ref<f32> +! CHECK: {{.*}} = hlfir.designate {{.*}} : (!fir.box<!fir.array<100x?xf32>>, i64, i64) -> !fir.ref<f32> +! CHECK: {{.*}} = fir.load {{.*}} : !fir.ref<f32> +! CHECK: %[[ADDF:.*]] = arith.addf %[[LOAD_OLD]], {{.*}} {{.*}}: f32 +! CHECK: %[[DESIGNATE_RED2:.*]] = hlfir.designate %[[DECLARE_Y_LOOP_PAR]]#0 ({{.*}}) : (!fir.box<!fir.array<?xf32>>, i64) -> !fir.ref<f32> +! CHECK: hlfir.assign %[[ADDF]] to %[[DESIGNATE_RED2]] : f32, !fir.ref<f32> +! CHECK: acc.yield +! CHECK: } +! CHECK: acc.yield +! CHECK: } +! CHECK: acc.yield +! CHECK: } +! CHECK: return +! CHECK: } diff --git a/flang/test/Lower/OpenACC/acc-reduction.f90 b/flang/test/Lower/OpenACC/acc-reduction.f90 index 6cb8bdf..940332b 100644 --- a/flang/test/Lower/OpenACC/acc-reduction.f90 +++ b/flang/test/Lower/OpenACC/acc-reduction.f90 @@ -2,757 +2,1212 @@ ! RUN: bbc -fopenacc -emit-hlfir %s -o - | FileCheck %s -! CHECK-LABEL: acc.reduction.recipe @reduction_max_box_UxUxf32 : !fir.box<!fir.array<?x?xf32>> reduction_operator <max> init { -! CHECK: ^bb0(%[[ARG0:.*]]: !fir.box<!fir.array<?x?xf32>>): -! CHECK: %[[CST:.*]] = arith.constant -1.401300e-45 : f32 -! CHECK: %[[DIMS0:.*]]:3 = fir.box_dims %[[ARG0]], %c0{{.*}} : (!fir.box<!fir.array<?x?xf32>>, index) -> (index, index, index) -! CHECK: %[[DIMS1:.*]]:3 = fir.box_dims %[[ARG0]], %c1 : (!fir.box<!fir.array<?x?xf32>>, index) -> (index, index, index) -! CHECK: %[[SHAPE:.*]] = fir.shape %[[DIMS0]]#1, %[[DIMS1]]#1 : (index, index) -> !fir.shape<2> -! CHECK: %[[TEMP:.*]] = fir.allocmem !fir.array<?x?xf32>, %[[DIMS0]]#1, %[[DIMS1]]#1 {bindc_name = ".tmp", uniq_name = ""} -! CHECK: %[[DECL:.*]]:2 = hlfir.declare %[[TEMP]](%[[SHAPE]]) {uniq_name = ".tmp"} : (!fir.heap<!fir.array<?x?xf32>>, !fir.shape<2>) -> (!fir.box<!fir.array<?x?xf32>>, !fir.heap<!fir.array<?x?xf32>>) -! CHECK: hlfir.assign %[[CST]] to %[[DECL]]#0 : f32, !fir.box<!fir.array<?x?xf32>> -! CHECK: acc.yield %[[DECL]]#0 : !fir.box<!fir.array<?x?xf32>> -! CHECK: } combiner { -! CHECK: ^bb0(%[[V1:.*]]: !fir.box<!fir.array<?x?xf32>>, %[[V2:.*]]: !fir.box<!fir.array<?x?xf32>>): -! CHECK: %[[SHAPE:.*]] = fir.shape %{{.*}}, %{{.*}} : (index, index) -> !fir.shape<2> -! CHECK: %[[DES_V1:.*]] = hlfir.designate %[[V1]] shape %[[SHAPE]] : (!fir.box<!fir.array<?x?xf32>>, !fir.shape<2>) -> !fir.box<!fir.array<?x?xf32>> -! CHECK: %[[DES_V2:.*]] = hlfir.designate %[[V2]] shape %[[SHAPE]] : (!fir.box<!fir.array<?x?xf32>>, !fir.shape<2>) -> !fir.box<!fir.array<?x?xf32>> -! CHECK: %[[ELEMENTAL:.*]] = hlfir.elemental %[[SHAPE]] unordered : (!fir.shape<2>) -> !hlfir.expr<?x?xf32> { -! CHECK: ^bb0(%[[ARG0:.*]]: index, %[[ARG1:.*]]: index): -! CHECK: %[[D1:.*]] = hlfir.designate %[[DES_V1]] (%[[ARG0]], %[[ARG1]]) : (!fir.box<!fir.array<?x?xf32>>, index, index) -> !fir.ref<f32> -! CHECK: %[[D2:.*]] = hlfir.designate %[[DES_V2]] (%[[ARG0]], %[[ARG1]]) : (!fir.box<!fir.array<?x?xf32>>, index, index) -> !fir.ref<f32> -! CHECK: %[[LOAD1:.*]] = fir.load %[[D1]] : !fir.ref<f32> -! CHECK: %[[LOAD2:.*]] = fir.load %[[D2]] : !fir.ref<f32> -! CHECK: %[[CMP:.*]] = arith.cmpf ogt, %[[LOAD1]], %[[LOAD2]] {{.*}} : f32 -! CHECK: %[[SELECT:.*]] = arith.select %[[CMP]], %[[LOAD1]], %[[LOAD2]] : f32 -! CHECK: hlfir.yield_element %[[SELECT]] : f32 -! CHECK: } -! CHECK: hlfir.assign %[[ELEMENTAL]] to %[[V1]] : !hlfir.expr<?x?xf32>, !fir.box<!fir.array<?x?xf32>> -! CHECK: acc.yield %[[V1]] : !fir.box<!fir.array<?x?xf32>> -! CHECK: } - -! CHECK-LABEL: acc.reduction.recipe @reduction_max_ref_box_ptr_Uxf32 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>> reduction_operator <max> init { -! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>): -! CHECK: %[[CST:.*]] = arith.constant -1.401300e-45 : f32 -! CHECK: %[[BOX:.*]] = fir.load %[[ARG0]] : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>> -! CHECK: %[[C0:.*]] = arith.constant 0 : index -! CHECK: %[[BOX_DIMS:.*]]:3 = fir.box_dims %[[BOX]], %[[C0]] : (!fir.box<!fir.ptr<!fir.array<?xf32>>>, index) -> (index, index, index) -! CHECK: %[[SHAPE:.*]] = fir.shape %[[BOX_DIMS]]#1 : (index) -> !fir.shape<1> -! CHECK: %[[TEMP:.*]] = fir.allocmem !fir.array<?xf32>, %[[BOX_DIMS]]#1 {bindc_name = ".tmp", uniq_name = ""} -! CHECK: %[[STORAGE:.*]]:2 = hlfir.declare %[[TEMP]](%[[SHAPE]]) {uniq_name = ".tmp"} : (!fir.heap<!fir.array<?xf32>>, !fir.shape<1>) -> (!fir.box<!fir.array<?xf32>>, !fir.heap<!fir.array<?xf32>>) -! CHECK: %[[BOXTEMP:.*]] = fir.alloca !fir.box<!fir.ptr<!fir.array<?xf32>>> -! CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %[[BOXTEMP]] {uniq_name = "acc.reduction.init"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>) -! CHECK: hlfir.assign %[[CST]] to %[[DECLARE]]#0 : f32, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>> -! CHECK: acc.yield %[[DECLARE]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>> -! CHECK: } combiner { -! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>, %[[ARG1:.*]]: !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>): -! CHECK: %[[BOX0:.*]] = fir.load %[[ARG0]] : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>> -! CHECK: %[[C0:.*]] = arith.constant 0 : index -! CHECK: %[[BOX_DIMS:.*]]:3 = fir.box_dims %[[BOX0]], %[[C0]] : (!fir.box<!fir.ptr<!fir.array<?xf32>>>, index) -> (index, index, index) -! CHECK: %[[SHAPE:.*]] = fir.shape %[[BOX_DIMS]]#1 : (index) -> !fir.shape<1> -! CHECK: %[[BOX0:.*]] = fir.load %[[ARG0]] : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>> -! CHECK: %[[DES_V1:.*]] = hlfir.designate %[[BOX0]] shape %[[SHAPE]] : (!fir.box<!fir.ptr<!fir.array<?xf32>>>, !fir.shape<1>) -> !fir.box<!fir.ptr<!fir.array<?xf32>>> -! CHECK: %[[BOX1:.*]] = fir.load %[[ARG1]] : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>> -! CHECK: %[[DES_V2:.*]] = hlfir.designate %[[BOX1]] shape %[[SHAPE]] : (!fir.box<!fir.ptr<!fir.array<?xf32>>>, !fir.shape<1>) -> !fir.box<!fir.ptr<!fir.array<?xf32>>> -! CHECK: %[[ELEMENTAL:.*]] = hlfir.elemental %[[SHAPE]] unordered : (!fir.shape<1>) -> !hlfir.expr<?xf32> { -! CHECK: ^bb0(%[[IV:.*]]: index): -! CHECK: %[[V1:.*]] = hlfir.designate %[[DES_V1]] (%[[IV]]) : (!fir.box<!fir.ptr<!fir.array<?xf32>>>, index) -> !fir.ref<f32> -! CHECK: %[[V2:.*]] = hlfir.designate %[[DES_V2]] (%[[IV]]) : (!fir.box<!fir.ptr<!fir.array<?xf32>>>, index) -> !fir.ref<f32> -! CHECK: %[[LOAD_V1:.*]] = fir.load %[[V1]] : !fir.ref<f32> -! CHECK: %[[LOAD_V2:.*]] = fir.load %[[V2]] : !fir.ref<f32> -! CHECK: %[[CMP:.*]] = arith.cmpf ogt, %[[LOAD_V1]], %[[LOAD_V2]] {{.*}} : f32 -! CHECK: %[[SELECT:.*]] = arith.select %[[CMP]], %[[LOAD_V1]], %[[LOAD_V2]] : f32 -! CHECK: hlfir.yield_element %[[SELECT]] : f32 -! CHECK: } -! CHECK: hlfir.assign %[[ELEMENTAL]] to %[[ARG0]] : !hlfir.expr<?xf32>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>> -! CHECK: acc.yield %[[ARG0]] : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>> -! CHECK: } - -! CHECK-LABEL: acc.reduction.recipe @reduction_max_ref_box_heap_Uxf32 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>> reduction_operator <max> init { -! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>): -! CHECK: %[[CST:.*]] = arith.constant -1.401300e-45 : f32 -! CHECK: %[[BOX:.*]] = fir.load %[[ARG0]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>> -! CHECK: %[[C0:.*]] = arith.constant 0 : index -! CHECK: %[[BOX_DIMS:.*]]:3 = fir.box_dims %[[BOX]], %[[C0]] : (!fir.box<!fir.heap<!fir.array<?xf32>>>, index) -> (index, index, index) -! CHECK: %[[SHAPE:.*]] = fir.shape %[[BOX_DIMS]]#1 : (index) -> !fir.shape<1> -! CHECK: %[[TEMP:.*]] = fir.allocmem !fir.array<?xf32>, %[[BOX_DIMS]]#1 {bindc_name = ".tmp", uniq_name = ""} -! CHECK: %[[STORAGE:.*]]:2 = hlfir.declare %[[TEMP]](%[[SHAPE]]) {uniq_name = ".tmp"} : (!fir.heap<!fir.array<?xf32>>, !fir.shape<1>) -> (!fir.box<!fir.array<?xf32>>, !fir.heap<!fir.array<?xf32>>) -! CHECK: %[[BOXTEMP:.*]] = fir.alloca !fir.box<!fir.heap<!fir.array<?xf32>>> -! CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %[[BOXTEMP]] {uniq_name = "acc.reduction.init"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>) -! CHECK: hlfir.assign %[[CST]] to %[[DECLARE]]#0 : f32, !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>> -! CHECK: acc.yield %[[DECLARE]]#0 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>> -! CHECK: } combiner { -! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>, %[[ARG1:.*]]: !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>): -! CHECK: %[[BOX0:.*]] = fir.load %[[ARG0]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>> -! CHECK: %[[C0:.*]] = arith.constant 0 : index -! CHECK: %[[BOX_DIMS:.*]]:3 = fir.box_dims %[[BOX0]], %[[C0]] : (!fir.box<!fir.heap<!fir.array<?xf32>>>, index) -> (index, index, index) -! CHECK: %[[SHAPE:.*]] = fir.shape %[[BOX_DIMS]]#1 : (index) -> !fir.shape<1> -! CHECK: %[[BOX0:.*]] = fir.load %[[ARG0]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>> -! CHECK: %[[DES_V1:.*]] = hlfir.designate %[[BOX0]] shape %[[SHAPE]] : (!fir.box<!fir.heap<!fir.array<?xf32>>>, !fir.shape<1>) -> !fir.box<!fir.heap<!fir.array<?xf32>>> -! CHECK: %[[BOX1:.*]] = fir.load %[[ARG1]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>> -! CHECK: %[[DES_V2:.*]] = hlfir.designate %[[BOX1]] shape %[[SHAPE]] : (!fir.box<!fir.heap<!fir.array<?xf32>>>, !fir.shape<1>) -> !fir.box<!fir.heap<!fir.array<?xf32>>> -! CHECK: %[[ELEMENTAL:.*]] = hlfir.elemental %[[SHAPE]] unordered : (!fir.shape<1>) -> !hlfir.expr<?xf32> { -! CHECK: ^bb0(%[[IV:.*]]: index): -! CHECK: %[[V1:.*]] = hlfir.designate %[[DES_V1]] (%[[IV]]) : (!fir.box<!fir.heap<!fir.array<?xf32>>>, index) -> !fir.ref<f32> -! CHECK: %[[V2:.*]] = hlfir.designate %[[DES_V2]] (%[[IV]]) : (!fir.box<!fir.heap<!fir.array<?xf32>>>, index) -> !fir.ref<f32> -! CHECK: %[[LOAD_V1:.*]] = fir.load %[[V1]] : !fir.ref<f32> -! CHECK: %[[LOAD_V2:.*]] = fir.load %[[V2]] : !fir.ref<f32> -! CHECK: %[[CMP:.*]] = arith.cmpf ogt, %[[LOAD_V1]], %[[LOAD_V2]] {{.*}} : f32 -! CHECK: %[[SELECT:.*]] = arith.select %[[CMP]], %[[LOAD_V1]], %[[LOAD_V2]] : f32 -! CHECK: hlfir.yield_element %[[SELECT]] : f32 -! CHECK: } -! CHECK: hlfir.assign %[[ELEMENTAL]] to %[[ARG0]] : !hlfir.expr<?xf32>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>> -! CHECK: acc.yield %[[ARG0]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>> -! CHECK: } - -! CHECK-LABEL: acc.reduction.recipe @reduction_add_section_lb1.ub3_box_Uxi32 : !fir.box<!fir.array<?xi32>> reduction_operator <add> init { -! CHECK: ^bb0(%[[ARG0:.*]]: !fir.box<!fir.array<?xi32>>): -! CHECK: %[[BOX_DIMS:.*]]:3 = fir.box_dims %[[ARG0]], %c0{{.*}} : (!fir.box<!fir.array<?xi32>>, index) -> (index, index, index) -! CHECK: %[[SHAPE:.*]] = fir.shape %[[BOX_DIMS]]#1 : (index) -> !fir.shape<1> -! CHECK: %[[TEMP:.*]] = fir.allocmem !fir.array<?xi32>, %0#1 {bindc_name = ".tmp", uniq_name = ""} -! CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %[[TEMP]](%[[SHAPE]]) {uniq_name = ".tmp"} : (!fir.heap<!fir.array<?xi32>>, !fir.shape<1>) -> (!fir.box<!fir.array<?xi32>>, !fir.heap<!fir.array<?xi32>>) -! CHECK: hlfir.assign %c0{{.*}} to %[[DECLARE]]#0 : i32, !fir.box<!fir.array<?xi32>> -! CHECK: acc.yield %[[DECLARE]]#0 : !fir.box<!fir.array<?xi32>> -! CHECK: } combiner { -! CHECK: ^bb0(%[[ARG0:.*]]: !fir.box<!fir.array<?xi32>>, %[[ARG1:.*]]: !fir.box<!fir.array<?xi32>>): -! CHECK: %[[SHAPE:.*]] = fir.shape %{{.*}} : (index) -> !fir.shape<1> -! CHECK: %[[DES1:.*]] = hlfir.designate %[[ARG0]] shape %[[SHAPE]] : (!fir.box<!fir.array<?xi32>>, !fir.shape<1>) -> !fir.box<!fir.array<?xi32>> -! CHECK: %[[DES2:.*]] = hlfir.designate %[[ARG1]] shape %[[SHAPE]] : (!fir.box<!fir.array<?xi32>>, !fir.shape<1>) -> !fir.box<!fir.array<?xi32>> -! CHECK: %[[ELEMENTAL:.*]] = hlfir.elemental %[[SHAPE]] unordered : (!fir.shape<1>) -> !hlfir.expr<?xi32> { -! CHECK: ^bb0(%[[IV:.*]]: index): -! CHECK: %[[DES_V1:.*]] = hlfir.designate %[[DES1]] (%[[IV]]) : (!fir.box<!fir.array<?xi32>>, index) -> !fir.ref<i32> -! CHECK: %[[DES_V2:.*]] = hlfir.designate %[[DES2]] (%[[IV]]) : (!fir.box<!fir.array<?xi32>>, index) -> !fir.ref<i32> -! CHECK: %[[LOAD_V1:.*]] = fir.load %[[DES_V1]] : !fir.ref<i32> -! CHECK: %[[LOAD_V2:.*]] = fir.load %[[DES_V2]] : !fir.ref<i32> -! CHECK: %[[COMBINED:.*]] = arith.addi %[[LOAD_V1]], %[[LOAD_V2]] : i32 -! CHECK: hlfir.yield_element %[[COMBINED]] : i32 -! CHECK: } -! CHECK: hlfir.assign %[[ELEMENTAL]] to %[[ARG0]] : !hlfir.expr<?xi32>, !fir.box<!fir.array<?xi32>> -! CHECK: acc.yield %[[ARG0]] : !fir.box<!fir.array<?xi32>> -! CHECK: } - -! CHECK-LABEL: acc.reduction.recipe @reduction_max_box_Uxf32 : !fir.box<!fir.array<?xf32>> reduction_operator <max> init { -! CHECK: ^bb0(%[[ARG0:.*]]: !fir.box<!fir.array<?xf32>>): -! CHECK: %[[INIT_VALUE:.*]] = arith.constant -1.401300e-45 : f32 -! CHECK: %[[C0:.*]] = arith.constant 0 : index -! CHECK: %[[BOX_DIMS:.*]]:3 = fir.box_dims %[[ARG0]], %[[C0]] : (!fir.box<!fir.array<?xf32>>, index) -> (index, index, index) -! CHECK: %[[SHAPE:.*]] = fir.shape %[[BOX_DIMS]]#1 : (index) -> !fir.shape<1> -! CHECK: %[[TEMP:.*]] = fir.allocmem !fir.array<?xf32>, %0#1 {bindc_name = ".tmp", uniq_name = ""} -! CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %[[TEMP]](%[[SHAPE]]) {uniq_name = ".tmp"} : (!fir.heap<!fir.array<?xf32>>, !fir.shape<1>) -> (!fir.box<!fir.array<?xf32>>, !fir.heap<!fir.array<?xf32>>) -! CHECK: hlfir.assign %[[INIT_VALUE]] to %[[DECLARE]]#0 : f32, !fir.box<!fir.array<?xf32>> -! CHECK: acc.yield %[[DECLARE]]#0 : !fir.box<!fir.array<?xf32>> -! CHECK: } combiner { -! CHECK: ^bb0(%[[ARG0:.*]]: !fir.box<!fir.array<?xf32>>, %[[ARG1:.*]]: !fir.box<!fir.array<?xf32>> -! CHECK: %[[LEFT:.*]] = hlfir.designate %[[ARG0]] shape %{{.*}} : (!fir.box<!fir.array<?xf32>>, !fir.shape<1>) -> !fir.box<!fir.array<?xf32>> -! CHECK: %[[RIGHT:.*]] = hlfir.designate %[[ARG1]] shape %{{.*}} : (!fir.box<!fir.array<?xf32>>, !fir.shape<1>) -> !fir.box<!fir.array<?xf32>> -! CHECK: %[[ELEMENTAL:.*]] = hlfir.elemental %{{.*}} unordered : (!fir.shape<1>) -> !hlfir.expr<?xf32> { -! CHECK: ^bb0(%{{.*}}: index): -! CHECK: %[[DES_V1:.*]] = hlfir.designate %[[LEFT]] (%{{.*}}) : (!fir.box<!fir.array<?xf32>>, index) -> !fir.ref<f32> -! CHECK: %[[DES_V2:.*]] = hlfir.designate %[[RIGHT]] (%{{.*}}) : (!fir.box<!fir.array<?xf32>>, index) -> !fir.ref<f32> -! CHECK: %[[LOAD_V1:.*]] = fir.load %[[DES_V1]] : !fir.ref<f32> -! CHECK: %[[LOAD_V2:.*]] = fir.load %[[DES_V2]] : !fir.ref<f32> -! CHECK: %[[CMPF:.*]] = arith.cmpf ogt, %[[LOAD_V1]], %[[LOAD_V2]] {{.*}} : f32 -! CHECK: %[[SELECT:.*]] = arith.select %[[CMPF]], %[[LOAD_V1]], %[[LOAD_V2]] : f32 -! CHECK: hlfir.yield_element %[[SELECT]] : f32 -! CHECK: } -! CHECK: hlfir.assign %[[ELEMENTAL]] to %[[ARG0]] : !hlfir.expr<?xf32>, !fir.box<!fir.array<?xf32>> -! CHECK: acc.yield %[[ARG0]] : !fir.box<!fir.array<?xf32>> -! CHECK: } - -! CHECK-LABEL: acc.reduction.recipe @reduction_add_box_Uxi32 : !fir.box<!fir.array<?xi32>> reduction_operator <add> init { -! CHECK: ^bb0(%[[ARG0:.*]]: !fir.box<!fir.array<?xi32>>): -! CHECK: %[[INIT_VALUE:.*]] = arith.constant 0 : i32 -! CHECK: %[[C0:.*]] = arith.constant 0 : index -! CHECK: %[[BOX_DIMS:.*]]:3 = fir.box_dims %[[ARG0]], %[[C0]] : (!fir.box<!fir.array<?xi32>>, index) -> (index, index, index) -! CHECK: %[[SHAPE:.*]] = fir.shape %[[BOX_DIMS]]#1 : (index) -> !fir.shape<1> -! CHECK: %[[TEMP:.*]] = fir.allocmem !fir.array<?xi32>, %[[BOX_DIMS]]#1 {bindc_name = ".tmp", uniq_name = ""} -! CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %[[TEMP]](%[[SHAPE]]) {uniq_name = ".tmp"} : (!fir.heap<!fir.array<?xi32>>, !fir.shape<1>) -> (!fir.box<!fir.array<?xi32>>, !fir.heap<!fir.array<?xi32>>) -! CHECK: hlfir.assign %[[INIT_VALUE]] to %[[DECLARE]]#0 : i32, !fir.box<!fir.array<?xi32>> -! CHECK: acc.yield %[[DECLARE]]#0 : !fir.box<!fir.array<?xi32>> -! CHECK: } combiner { -! CHECK: ^bb0(%[[ARG0:.*]]: !fir.box<!fir.array<?xi32>>, %[[ARG1:.*]]: !fir.box<!fir.array<?xi32>> -! CHECK: %[[C0:.*]] = arith.constant 0 : index -! CHECK: %[[BOX_DIMS:.*]]:3 = fir.box_dims %[[ARG0]], %[[C0]] : (!fir.box<!fir.array<?xi32>>, index) -> (index, index, index) -! CHECK: %[[SHAPE:.*]] = fir.shape %[[BOX_DIMS]]#1 : (index) -> !fir.shape<1> -! CHECK: %[[LEFT:.*]] = hlfir.designate %[[ARG0]] shape %[[SHAPE]] : (!fir.box<!fir.array<?xi32>>, !fir.shape<1>) -> !fir.box<!fir.array<?xi32>> -! CHECK: %[[RIGHT:.*]] = hlfir.designate %[[ARG1]] shape %[[SHAPE]] : (!fir.box<!fir.array<?xi32>>, !fir.shape<1>) -> !fir.box<!fir.array<?xi32>> -! CHECK: %[[ELEMENTAL:.*]] = hlfir.elemental %{{.*}} unordered : (!fir.shape<1>) -> !hlfir.expr<?xi32> { -! CHECK: ^bb0(%{{.*}}: index): -! CHECK: %[[DES_V1:.*]] = hlfir.designate %[[LEFT]] (%{{.*}}) : (!fir.box<!fir.array<?xi32>>, index) -> !fir.ref<i32> -! CHECK: %[[DES_V2:.*]] = hlfir.designate %[[RIGHT]] (%{{.*}}) : (!fir.box<!fir.array<?xi32>>, index) -> !fir.ref<i32> -! CHECK: %[[LOAD_V1:.*]] = fir.load %[[DES_V1]] : !fir.ref<i32> -! CHECK: %[[LOAD_V2:.*]] = fir.load %[[DES_V2]] : !fir.ref<i32> -! CHECK: %[[COMBINED:.*]] = arith.addi %[[LOAD_V1]], %[[LOAD_V2]] : i32 -! CHECK: hlfir.yield_element %[[COMBINED]] : i32 -! CHECK: } -! CHECK: hlfir.assign %[[ELEMENTAL]] to %[[ARG0]] : !hlfir.expr<?xi32>, !fir.box<!fir.array<?xi32>> -! CHECK: acc.yield %arg0 : !fir.box<!fir.array<?xi32>> -! CHECK: } - -! CHECK-LABEL: acc.reduction.recipe @reduction_add_section_lb0.ub9xlb0.ub19_ref_10x20xi32 : !fir.ref<!fir.array<10x20xi32>> reduction_operator <add> init { -! CHECK: fir.do_loop %arg1 = %c0 to %c19 step %c1 { -! CHECK: fir.do_loop %arg2 = %c0_0 to %c9 step %c1_1 { -! CHECK: } combiner { -! CHECK: fir.do_loop %arg2 = %c0 to %c19 step %c1 { -! CHECK: fir.do_loop %arg3 = %c0_0 to %c9 step %c1_1 { -! CHECK: } - -! CHECK-LABEL: acc.reduction.recipe @reduction_mul_ref_z32 : !fir.ref<complex<f32>> reduction_operator <mul> init { -! CHECK: ^bb0(%{{.*}}: !fir.ref<complex<f32>>): -! CHECK: %[[REAL:.*]] = arith.constant 1.000000e+00 : f32 -! CHECK: %[[IMAG:.*]] = arith.constant 0.000000e+00 : f32 -! CHECK: %[[UNDEF:.*]] = fir.undefined complex<f32> -! CHECK: %[[UNDEF1:.*]] = fir.insert_value %[[UNDEF]], %[[REAL]], [0 : index] : (complex<f32>, f32) -> complex<f32> -! CHECK: %[[UNDEF2:.*]] = fir.insert_value %[[UNDEF1]], %[[IMAG]], [1 : index] : (complex<f32>, f32) -> complex<f32> -! CHECK: %[[ALLOCA:.*]] = fir.alloca complex<f32> -! CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %[[ALLOCA]] {uniq_name = "acc.reduction.init"} : (!fir.ref<complex<f32>>) -> (!fir.ref<complex<f32>>, !fir.ref<complex<f32>>) -! CHECK: fir.store %[[UNDEF2]] to %[[DECLARE]]#0 : !fir.ref<complex<f32>> -! CHECK: acc.yield %[[DECLARE]]#0 : !fir.ref<complex<f32>> -! CHECK: } combiner { -! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref<complex<f32>>, %[[ARG1:.*]]: !fir.ref<complex<f32>>): -! CHECK: %[[LOAD0:.*]] = fir.load %[[ARG0]] : !fir.ref<complex<f32>> -! CHECK: %[[LOAD1:.*]] = fir.load %[[ARG1]] : !fir.ref<complex<f32>> -! CHECK: %[[COMBINED:.*]] = fir.mulc %[[LOAD0]], %[[LOAD1]] {fastmath = #arith.fastmath<contract>} : complex<f32> -! CHECK: fir.store %[[COMBINED]] to %[[ARG0]] : !fir.ref<complex<f32>> -! CHECK: acc.yield %[[ARG0]] : !fir.ref<complex<f32>> -! CHECK: } - -! CHECK-LABEL: acc.reduction.recipe @reduction_add_ref_z32 : !fir.ref<complex<f32>> reduction_operator <add> init { -! CHECK: ^bb0(%{{.*}}: !fir.ref<complex<f32>>): -! CHECK: %[[REAL:.*]] = arith.constant 0.000000e+00 : f32 -! CHECK: %[[IMAG:.*]] = arith.constant 0.000000e+00 : f32 -! CHECK: %[[UNDEF:.*]] = fir.undefined complex<f32> -! CHECK: %[[UNDEF1:.*]] = fir.insert_value %[[UNDEF]], %[[REAL]], [0 : index] : (complex<f32>, f32) -> complex<f32> -! CHECK: %[[UNDEF2:.*]] = fir.insert_value %[[UNDEF1]], %[[IMAG]], [1 : index] : (complex<f32>, f32) -> complex<f32> -! CHECK: %[[ALLOCA:.*]] = fir.alloca complex<f32> -! CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %[[ALLOCA]] {uniq_name = "acc.reduction.init"} : (!fir.ref<complex<f32>>) -> (!fir.ref<complex<f32>>, !fir.ref<complex<f32>>) -! CHECK: fir.store %[[UNDEF2]] to %[[DECLARE]]#0 : !fir.ref<complex<f32>> -! CHECK: acc.yield %[[DECLARE]]#0 : !fir.ref<complex<f32>> -! CHECK: } combiner { -! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref<complex<f32>>, %[[ARG1:.*]]: !fir.ref<complex<f32>>): -! CHECK: %[[LOAD0:.*]] = fir.load %[[ARG0]] : !fir.ref<complex<f32>> -! CHECK: %[[LOAD1:.*]] = fir.load %[[ARG1]] : !fir.ref<complex<f32>> -! CHECK: %[[COMBINED:.*]] = fir.addc %[[LOAD0]], %[[LOAD1]] {fastmath = #arith.fastmath<contract>} : complex<f32> -! CHECK: fir.store %[[COMBINED]] to %[[ARG0]] : !fir.ref<complex<f32>> -! CHECK: acc.yield %[[ARG0]] : !fir.ref<complex<f32>> -! CHECK: } - -! CHECK-LABEL: acc.reduction.recipe @reduction_neqv_ref_l32 : !fir.ref<!fir.logical<4>> reduction_operator <neqv> init { -! CHECK: ^bb0(%{{.*}}: !fir.ref<!fir.logical<4>>): -! CHECK: %[[CST:.*]] = arith.constant false -! CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.logical<4> -! CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %[[ALLOCA]] {uniq_name = "acc.reduction.init"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) -! CHECK: %[[CONVERT:.*]] = fir.convert %[[CST]] : (i1) -> !fir.logical<4> -! CHECK: fir.store %[[CONVERT]] to %[[DECLARE]]#0 : !fir.ref<!fir.logical<4>> -! CHECK: acc.yield %[[DECLARE]]#0 : !fir.ref<!fir.logical<4>> -! CHECK: } combiner { -! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref<!fir.logical<4>>, %[[ARG1:.*]]: !fir.ref<!fir.logical<4>>): -! CHECK: %[[LOAD0:.*]] = fir.load %[[ARG0]] : !fir.ref<!fir.logical<4>> -! CHECK: %[[LOAD1:.*]] = fir.load %[[ARG1]] : !fir.ref<!fir.logical<4>> -! CHECK: %[[CONV0:.*]] = fir.convert %[[LOAD0]] : (!fir.logical<4>) -> i1 -! CHECK: %[[CONV1:.*]] = fir.convert %[[LOAD1]] : (!fir.logical<4>) -> i1 -! CHECK: %[[CMP:.*]] = arith.cmpi ne, %[[CONV0]], %[[CONV1]] : i1 -! CHECK: %[[CMP_CONV:.*]] = fir.convert %[[CMP]] : (i1) -> !fir.logical<4> -! CHECK: fir.store %[[CMP_CONV]] to %[[ARG0]] : !fir.ref<!fir.logical<4>> -! CHECK: acc.yield %[[ARG0]] : !fir.ref<!fir.logical<4>> -! CHECK: } - -! CHECK-LABEL: acc.reduction.recipe @reduction_eqv_ref_l32 : !fir.ref<!fir.logical<4>> reduction_operator <eqv> init { -! CHECK: ^bb0(%{{.*}}: !fir.ref<!fir.logical<4>>): -! CHECK: %[[CST:.*]] = arith.constant true -! CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.logical<4> -! CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %[[ALLOCA]] {uniq_name = "acc.reduction.init"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) -! CHECK: %[[CONVERT:.*]] = fir.convert %[[CST]] : (i1) -> !fir.logical<4> -! CHECK: fir.store %[[CONVERT]] to %[[DECLARE]]#0 : !fir.ref<!fir.logical<4>> -! CHECK: acc.yield %[[DECLARE]]#0 : !fir.ref<!fir.logical<4>> -! CHECK: } combiner { -! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref<!fir.logical<4>>, %[[ARG1:.*]]: !fir.ref<!fir.logical<4>>): -! CHECK: %[[LOAD0:.*]] = fir.load %[[ARG0]] : !fir.ref<!fir.logical<4>> -! CHECK: %[[LOAD1:.*]] = fir.load %[[ARG1]] : !fir.ref<!fir.logical<4>> -! CHECK: %[[CONV0:.*]] = fir.convert %[[LOAD0]] : (!fir.logical<4>) -> i1 -! CHECK: %[[CONV1:.*]] = fir.convert %[[LOAD1]] : (!fir.logical<4>) -> i1 -! CHECK: %[[CMP:.*]] = arith.cmpi eq, %[[CONV0]], %[[CONV1]] : i1 -! CHECK: %[[CMP_CONV:.*]] = fir.convert %[[CMP]] : (i1) -> !fir.logical<4> -! CHECK: fir.store %[[CMP_CONV]] to %[[ARG0]] : !fir.ref<!fir.logical<4>> -! CHECK: acc.yield %[[ARG0]] : !fir.ref<!fir.logical<4>> -! CHECK: } - -! CHECK-LABEL: acc.reduction.recipe @reduction_lor_ref_l32 : !fir.ref<!fir.logical<4>> reduction_operator <lor> init { -! CHECK: ^bb0(%{{.*}}: !fir.ref<!fir.logical<4>>): -! CHECK: %[[CST:.*]] = arith.constant false -! CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.logical<4> -! CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %[[ALLOCA]] {uniq_name = "acc.reduction.init"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) -! CHECK: %[[CONVERT:.*]] = fir.convert %[[CST]] : (i1) -> !fir.logical<4> -! CHECK: fir.store %[[CONVERT]] to %[[DECLARE]]#0 : !fir.ref<!fir.logical<4>> -! CHECK: acc.yield %[[DECLARE]]#0 : !fir.ref<!fir.logical<4>> -! CHECK: } combiner { -! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref<!fir.logical<4>>, %[[ARG1:.*]]: !fir.ref<!fir.logical<4>>): -! CHECK: %[[LOAD0:.*]] = fir.load %[[ARG0]] : !fir.ref<!fir.logical<4>> -! CHECK: %[[LOAD1:.*]] = fir.load %[[ARG1]] : !fir.ref<!fir.logical<4>> -! CHECK: %[[CONV0:.*]] = fir.convert %[[LOAD0]] : (!fir.logical<4>) -> i1 -! CHECK: %[[CONV1:.*]] = fir.convert %[[LOAD1]] : (!fir.logical<4>) -> i1 -! CHECK: %[[CMP:.*]] = arith.ori %[[CONV0]], %[[CONV1]] : i1 -! CHECK: %[[CMP_CONV:.*]] = fir.convert %[[CMP]] : (i1) -> !fir.logical<4> -! CHECK: fir.store %[[CMP_CONV]] to %[[ARG0]] : !fir.ref<!fir.logical<4>> -! CHECK: acc.yield %[[ARG0]] : !fir.ref<!fir.logical<4>> -! CHECK: } - -! CHECK-LABEL: acc.reduction.recipe @reduction_land_ref_l32 : !fir.ref<!fir.logical<4>> reduction_operator <land> init { -! CHECK: ^bb0(%{{.*}}: !fir.ref<!fir.logical<4>>): -! CHECK: %[[CST:.*]] = arith.constant true -! CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.logical<4> -! CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %[[ALLOCA]] {uniq_name = "acc.reduction.init"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) -! CHECK: %[[CONVERT:.*]] = fir.convert %[[CST]] : (i1) -> !fir.logical<4> -! CHECK: fir.store %[[CONVERT]] to %[[DECLARE]]#0 : !fir.ref<!fir.logical<4>> -! CHECK: acc.yield %[[DECLARE]]#0 : !fir.ref<!fir.logical<4>> -! CHECK: } combiner { -! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref<!fir.logical<4>>, %[[ARG1:.*]]: !fir.ref<!fir.logical<4>>): -! CHECK: %[[LOAD0:.*]] = fir.load %[[ARG0]] : !fir.ref<!fir.logical<4>> -! CHECK: %[[LOAD1:.*]] = fir.load %[[ARG1]] : !fir.ref<!fir.logical<4>> -! CHECK: %[[CONV0:.*]] = fir.convert %[[LOAD0]] : (!fir.logical<4>) -> i1 -! CHECK: %[[CONV1:.*]] = fir.convert %[[LOAD1]] : (!fir.logical<4>) -> i1 -! CHECK: %[[CMP:.*]] = arith.andi %[[CONV0]], %[[CONV1]] : i1 -! CHECK: %[[CMP_CONV:.*]] = fir.convert %[[CMP]] : (i1) -> !fir.logical<4> -! CHECK: fir.store %[[CMP_CONV]] to %[[ARG0]] : !fir.ref<!fir.logical<4>> -! CHECK: acc.yield %[[ARG0]] : !fir.ref<!fir.logical<4>> -! CHECK: } - -! CHECK-LABEL: acc.reduction.recipe @reduction_xor_ref_i32 : !fir.ref<i32> reduction_operator <xor> init { -! CHECK: ^bb0(%{{.*}}: !fir.ref<i32>): -! CHECK: %[[CST:.*]] = arith.constant 0 : i32 -! CHECK: %[[ALLOCA:.*]] = fir.alloca i32 -! CHECK: %[[DECLARE]]:2 = hlfir.declare %[[ALLOCA]] {uniq_name = "acc.reduction.init"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) -! CHECK: fir.store %[[CST]] to %[[DECLARE]]#0 : !fir.ref<i32> -! CHECK: acc.yield %[[DECLARE]]#0 : !fir.ref<i32> -! CHECK: } combiner { -! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref<i32>, %[[ARG1:.*]]: !fir.ref<i32>): -! CHECK: %[[LOAD0:.*]] = fir.load %[[ARG0]] : !fir.ref<i32> -! CHECK: %[[LOAD1:.*]] = fir.load %[[ARG1]] : !fir.ref<i32> -! CHECK: %[[COMBINED:.*]] = arith.xori %[[LOAD0]], %[[LOAD1]] : i32 -! CHECK: fir.store %[[COMBINED]] to %[[ARG0]] : !fir.ref<i32> -! CHECK: acc.yield %[[ARG0]] : !fir.ref<i32> -! CHECK: } - -! CHECK-LABEL: acc.reduction.recipe @reduction_ior_ref_i32 : !fir.ref<i32> reduction_operator <ior> init { -! CHECK: ^bb0(%{{.*}}: !fir.ref<i32>): -! CHECK: %[[CST:.*]] = arith.constant 0 : i32 -! CHECK: %[[ALLOCA:.*]] = fir.alloca i32 -! CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %[[ALLOCA]] {uniq_name = "acc.reduction.init"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) -! CHECK: fir.store %[[CST]] to %[[DECLARE:.*]]#0 : !fir.ref<i32> -! CHECK: acc.yield %[[DECLARE:.*]]#0 : !fir.ref<i32> -! CHECK: } combiner { -! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref<i32>, %[[ARG1:.*]]: !fir.ref<i32>): -! CHECK: %[[LOAD0:.*]] = fir.load %[[ARG0]] : !fir.ref<i32> -! CHECK: %[[LOAD1:.*]] = fir.load %[[ARG1]] : !fir.ref<i32> -! CHECK: %[[COMBINED:.*]] = arith.ori %[[LOAD0]], %[[LOAD1]] : i32 -! CHECK: fir.store %[[COMBINED]] to %[[ARG0]] : !fir.ref<i32> -! CHECK: acc.yield %[[ARG0]] : !fir.ref<i32> -! CHECK: } - -! CHECK-LABEL: acc.reduction.recipe @reduction_iand_ref_i32 : !fir.ref<i32> reduction_operator <iand> init { -! CHECK: ^bb0(%{{.*}}: !fir.ref<i32>): -! CHECK: %[[CST:.*]] = arith.constant -1 : i32 -! CHECK: %[[ALLOCA:.*]] = fir.alloca i32 -! CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %[[ALLOCA]] {uniq_name = "acc.reduction.init"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) -! CHECK: fir.store %[[CST]] to %[[DECLARE]]#0 : !fir.ref<i32> -! CHECK: acc.yield %[[DECLARE]]#0 : !fir.ref<i32> -! CHECK: } combiner { -! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref<i32>, %[[ARG1:.*]]: !fir.ref<i32>): -! CHECK: %[[LOAD0:.*]] = fir.load %[[ARG0]] : !fir.ref<i32> -! CHECK: %[[LOAD1:.*]] = fir.load %[[ARG1]] : !fir.ref<i32> -! CHECK: %[[COMBINED:.*]] = arith.andi %[[LOAD0]], %[[LOAD1]] : i32 -! CHECK: fir.store %[[COMBINED]] to %[[ARG0]] : !fir.ref<i32> -! CHECK: acc.yield %[[ARG0]] : !fir.ref<i32> -! CHECK: } - -! CHECK-LABEL: acc.reduction.recipe @reduction_max_ref_100xf32 : !fir.ref<!fir.array<100xf32>> reduction_operator <max> init { -! CHECK: ^bb0(%{{.*}}: !fir.ref<!fir.array<100xf32>>): -! CHECK: %[[INIT:.*]] = arith.constant -1.401300e-45 : f32 -! CHECK: %[[SHAPE:.*]] = fir.shape %{{.*}} : (index) -> !fir.shape<1> -! CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.array<100xf32> -! CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %[[ALLOCA]](%[[SHAPE]]) {uniq_name = "acc.reduction.init"} : (!fir.ref<!fir.array<100xf32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<100xf32>>, !fir.ref<!fir.array<100xf32>>) -! CHECK: %[[LB:.*]] = arith.constant 0 : index -! CHECK: %[[UB:.*]] = arith.constant 99 : index -! CHECK: %[[STEP:.*]] = arith.constant 1 : index -! CHECK: fir.do_loop %[[IV:.*]] = %[[LB]] to %[[UB]] step %[[STEP]] { -! CHECK: %[[COORD:.*]] = fir.coordinate_of %[[DECLARE]]#0, %[[IV]] : (!fir.ref<!fir.array<100xf32>>, index) -> !fir.ref<f32> -! CHECK: fir.store %[[INIT]] to %[[COORD]] : !fir.ref<f32> -! CHECK: } -! CHECK: acc.yield %[[DECLARE]]#0 : !fir.ref<!fir.array<100xf32>> -! CHECK: } combiner { -! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref<!fir.array<100xf32>>, %[[ARG1:.*]]: !fir.ref<!fir.array<100xf32>>): -! CHECK: %[[LB0:.*]] = arith.constant 0 : index -! CHECK: %[[UB0:.*]] = arith.constant 99 : index -! CHECK: %[[STEP0:.*]] = arith.constant 1 : index -! CHECK: fir.do_loop %[[IV0:.*]] = %[[LB0]] to %[[UB0]] step %[[STEP0]] { -! CHECK: %[[COORD1:.*]] = fir.coordinate_of %[[ARG0]], %[[IV0]] : (!fir.ref<!fir.array<100xf32>>, index) -> !fir.ref<f32> -! CHECK: %[[COORD2:.*]] = fir.coordinate_of %[[ARG1]], %[[IV0]] : (!fir.ref<!fir.array<100xf32>>, index) -> !fir.ref<f32> -! CHECK: %[[LOAD1:.*]] = fir.load %[[COORD1]] : !fir.ref<f32> -! CHECK: %[[LOAD2:.*]] = fir.load %[[COORD2]] : !fir.ref<f32> -! CHECK: %[[CMP:.*]] = arith.cmpf ogt, %[[LOAD1]], %[[LOAD2]] {{.*}} : f32 -! CHECK: %[[SELECT:.*]] = arith.select %[[CMP]], %[[LOAD1]], %[[LOAD2]] : f32 -! CHECK: fir.store %[[SELECT]] to %[[COORD1]] : !fir.ref<f32> -! CHECK: } -! CHECK: acc.yield %[[ARG0]] : !fir.ref<!fir.array<100xf32>> -! CHECK: } - -! CHECK-LABEL: acc.reduction.recipe @reduction_max_ref_f32 : !fir.ref<f32> reduction_operator <max> init { -! CHECK: ^bb0(%{{.*}}: !fir.ref<f32>): -! CHECK: %[[INIT:.*]] = arith.constant -1.401300e-45 : f32 -! CHECK: %[[ALLOCA:.*]] = fir.alloca f32 -! CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %0 {uniq_name = "acc.reduction.init"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>) -! CHECK: fir.store %[[INIT]] to %[[DECLARE]]#0 : !fir.ref<f32> -! CHECK: acc.yield %[[DECLARE]]#0 : !fir.ref<f32> -! CHECK: } combiner { -! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref<f32>, %[[ARG1:.*]]: !fir.ref<f32>): -! CHECK: %[[LOAD0:.*]] = fir.load %[[ARG0]] : !fir.ref<f32> -! CHECK: %[[LOAD1:.*]] = fir.load %[[ARG1]] : !fir.ref<f32> -! CHECK: %[[CMP:.*]] = arith.cmpf ogt, %[[LOAD0]], %[[LOAD1]] {{.*}} : f32 -! CHECK: %[[SELECT:.*]] = arith.select %[[CMP]], %[[LOAD0]], %[[LOAD1]] : f32 -! CHECK: fir.store %[[SELECT]] to %[[ARG0]] : !fir.ref<f32> -! CHECK: acc.yield %[[ARG0]] : !fir.ref<f32> -! CHECK: } - -! CHECK-LABEL: acc.reduction.recipe @reduction_max_ref_100x10xi32 : !fir.ref<!fir.array<100x10xi32>> reduction_operator <max> init { -! CHECK: ^bb0(%arg0: !fir.ref<!fir.array<100x10xi32>>): -! CHECK: %[[INIT:.*]] = arith.constant -2147483648 : i32 -! CHECK: %[[SHAPE:.*]] = fir.shape %{{.*}}, %{{.*}} : (index, index) -> !fir.shape<2> -! CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.array<100x10xi32> -! CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %[[ALLOCA]](%[[SHAPE]]) {uniq_name = "acc.reduction.init"} : (!fir.ref<!fir.array<100x10xi32>>, !fir.shape<2>) -> (!fir.ref<!fir.array<100x10xi32>>, !fir.ref<!fir.array<100x10xi32>>) -! CHECK: acc.yield %[[DECLARE]]#0 : !fir.ref<!fir.array<100x10xi32>> -! CHECK: } combiner { -! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref<!fir.array<100x10xi32>>, %[[ARG1:.*]]: !fir.ref<!fir.array<100x10xi32>>): -! CHECK: %[[LB0:.*]] = arith.constant 0 : index -! CHECK: %[[UB0:.*]] = arith.constant 9 : index -! CHECK: %[[STEP0:.*]] = arith.constant 1 : index -! CHECK: fir.do_loop %[[IV0:.*]] = %[[LB0]] to %[[UB0]] step %[[STEP0]] { -! CHECK: %[[LB1:.*]] = arith.constant 0 : index -! CHECK: %[[UB1:.*]] = arith.constant 99 : index -! CHECK: %[[STEP1:.*]] = arith.constant 1 : index -! CHECK: fir.do_loop %[[IV1:.*]] = %[[LB1]] to %[[UB1]] step %[[STEP1]] { -! CHECK: %[[COORD1:.*]] = fir.coordinate_of %[[ARG0:.*]], %[[IV1]], %[[IV0]] : (!fir.ref<!fir.array<100x10xi32>>, index, index) -> !fir.ref<i32> -! CHECK: %[[COORD2:.*]] = fir.coordinate_of %[[ARG1:.*]], %[[IV1]], %[[IV0]] : (!fir.ref<!fir.array<100x10xi32>>, index, index) -> !fir.ref<i32> -! CHECK: %[[LOAD1:.*]] = fir.load %[[COORD1]] : !fir.ref<i32> -! CHECK: %[[LOAD2:.*]] = fir.load %[[COORD2]] : !fir.ref<i32> -! CHECK: %[[CMP:.*]] = arith.cmpi sgt, %[[LOAD1]], %[[LOAD2]] : i32 -! CHECK: %[[SELECT:.*]] = arith.select %[[CMP]], %[[LOAD1]], %[[LOAD2]] : i32 -! CHECK: fir.store %[[SELECT]] to %[[COORD1]] : !fir.ref<i32> -! CHECK: } -! CHECK: } -! CHECK: acc.yield %[[ARG0]] : !fir.ref<!fir.array<100x10xi32>> -! CHECK: } - -! CHECK-LABEL: acc.reduction.recipe @reduction_max_ref_i32 : !fir.ref<i32> reduction_operator <max> init { -! CHECK: ^bb0(%arg0: !fir.ref<i32>): -! CHECK: %[[INIT:.*]] = arith.constant -2147483648 : i32 -! CHECK: %[[ALLOCA:.*]] = fir.alloca i32 -! CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %[[ALLOCA]] {uniq_name = "acc.reduction.init"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) -! CHECK: fir.store %[[INIT]] to %[[DECLARE]]#0 : !fir.ref<i32> -! CHECK: acc.yield %[[DECLARE]]#0 : !fir.ref<i32> -! CHECK: } combiner { -! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref<i32>, %[[ARG1:.*]]: !fir.ref<i32>): -! CHECK: %[[LOAD0:.*]] = fir.load %[[ARG0]] : !fir.ref<i32> -! CHECK: %[[LOAD1:.*]] = fir.load %[[ARG1]] : !fir.ref<i32> -! CHECK: %[[CMP:.*]] = arith.cmpi sgt, %[[LOAD0]], %[[LOAD1]] : i32 -! CHECK: %[[SELECT:.*]] = arith.select %[[CMP]], %[[LOAD0]], %[[LOAD1]] : i32 -! CHECK: fir.store %[[SELECT]] to %[[ARG0]] : !fir.ref<i32> -! CHECK: acc.yield %[[ARG0]] : !fir.ref<i32> -! CHECK: } - -! CHECK-LABEL: acc.reduction.recipe @reduction_min_ref_100x10xf32 : !fir.ref<!fir.array<100x10xf32>> reduction_operator <min> init { -! CHECK: ^bb0(%{{.*}}: !fir.ref<!fir.array<100x10xf32>>): -! CHECK: %[[INIT:.*]] = arith.constant 3.40282347E+38 : f32 -! CHECK: %[[SHAPE:.*]] = fir.shape %{{.*}}, %{{.*}} : (index, index) -> !fir.shape<2> -! CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.array<100x10xf32> -! CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %[[ALLOCA]](%[[SHAPE]]) {uniq_name = "acc.reduction.init"} : (!fir.ref<!fir.array<100x10xf32>>, !fir.shape<2>) -> (!fir.ref<!fir.array<100x10xf32>>, !fir.ref<!fir.array<100x10xf32>>) -! CHECK: acc.yield %[[DECLARE]]#0 : !fir.ref<!fir.array<100x10xf32>> -! CHECK: } combiner { -! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref<!fir.array<100x10xf32>>, %[[ARG1:.*]]: !fir.ref<!fir.array<100x10xf32>>): -! CHECK: %[[LB0:.*]] = arith.constant 0 : index -! CHECK: %[[UB0:.*]] = arith.constant 9 : index -! CHECK: %[[STEP0:.*]] = arith.constant 1 : index -! CHECK: fir.do_loop %[[IV0:.*]] = %[[LB0]] to %[[UB0]] step %[[STEP0]] { -! CHECK: %[[LB1:.*]] = arith.constant 0 : index -! CHECK: %[[UB1:.*]] = arith.constant 99 : index -! CHECK: %[[STEP1:.*]] = arith.constant 1 : index -! CHECK: fir.do_loop %[[IV1:.*]] = %[[LB1]] to %[[UB1]] step %[[STEP1]] { -! CHECK: %[[COORD1:.*]] = fir.coordinate_of %[[ARG0]], %[[IV1]], %[[IV0]] : (!fir.ref<!fir.array<100x10xf32>>, index, index) -> !fir.ref<f32> -! CHECK: %[[COORD2:.*]] = fir.coordinate_of %[[ARG1]], %[[IV1]], %[[IV0]] : (!fir.ref<!fir.array<100x10xf32>>, index, index) -> !fir.ref<f32> -! CHECK: %[[LOAD1:.*]] = fir.load %[[COORD1]] : !fir.ref<f32> -! CHECK: %[[LOAD2:.*]] = fir.load %[[COORD2]] : !fir.ref<f32> -! CHECK: %[[CMP:.*]] = arith.cmpf olt, %[[LOAD1]], %[[LOAD2]] {{.*}} : f32 -! CHECK: %[[SELECT:.*]] = arith.select %[[CMP]], %[[LOAD1]], %[[LOAD2]] : f32 -! CHECK: fir.store %[[SELECT]] to %[[COORD1]] : !fir.ref<f32> -! CHECK: } -! CHECK: } -! CHECK: acc.yield %[[ARG0]] : !fir.ref<!fir.array<100x10xf32>> -! CHECK: } - -! CHECK-LABEL: acc.reduction.recipe @reduction_min_ref_f32 : !fir.ref<f32> reduction_operator <min> init { -! CHECK: ^bb0(%{{.*}}: !fir.ref<f32>): -! CHECK: %[[INIT:.*]] = arith.constant 3.40282347E+38 : f32 -! CHECK: %[[ALLOCA:.*]] = fir.alloca f32 -! CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %[[ALLOCA]] {uniq_name = "acc.reduction.init"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>) -! CHECK: fir.store %[[INIT]] to %[[DECLARE]]#0 : !fir.ref<f32> -! CHECK: acc.yield %[[DECLARE]]#0 : !fir.ref<f32> -! CHECK: } combiner { -! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref<f32>, %[[ARG1:.*]]: !fir.ref<f32>): -! CHECK: %[[LOAD0:.*]] = fir.load %[[ARG0]] : !fir.ref<f32> -! CHECK: %[[LOAD1:.*]] = fir.load %[[ARG1]] : !fir.ref<f32> -! CHECK: %[[CMP:.*]] = arith.cmpf olt, %[[LOAD0]], %[[LOAD1]] {{.*}} : f32 -! CHECK: %[[SELECT:.*]] = arith.select %[[CMP]], %[[LOAD0]], %[[LOAD1]] : f32 -! CHECK: fir.store %[[SELECT]] to %[[ARG0]] : !fir.ref<f32> -! CHECK: acc.yield %[[ARG0]] : !fir.ref<f32> -! CHECK: } - -! CHECK-LABEL: acc.reduction.recipe @reduction_min_ref_100xi32 : !fir.ref<!fir.array<100xi32>> reduction_operator <min> init { -! CHECK: ^bb0(%{{.*}}: !fir.ref<!fir.array<100xi32>>): -! CHECK: %[[INIT:.*]] = arith.constant 2147483647 : i32 -! CHECK: %[[SHAPE:.*]] = fir.shape %{{.*}} : (index) -> !fir.shape<1> -! CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.array<100xi32> -! CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %[[ALLOCA]](%[[SHAPE]]) {uniq_name = "acc.reduction.init"} : (!fir.ref<!fir.array<100xi32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<100xi32>>, !fir.ref<!fir.array<100xi32>>) -! CHECK: acc.yield %[[DECLARE]]#0 : !fir.ref<!fir.array<100xi32>> -! CHECK: } combiner { -! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref<!fir.array<100xi32>>, %[[ARG1:.*]]: !fir.ref<!fir.array<100xi32>>): -! CHECK: %[[LB0:.*]] = arith.constant 0 : index -! CHECK: %[[UB0:.*]] = arith.constant 99 : index -! CHECK: %[[STEP0:.*]] = arith.constant 1 : index -! CHECK: fir.do_loop %[[IV0:.*]] = %[[LB0]] to %[[UB0]] step %[[STEP0]] { -! CHECK: %[[COORD1:.*]] = fir.coordinate_of %[[ARG0]], %[[IV0]] : (!fir.ref<!fir.array<100xi32>>, index) -> !fir.ref<i32> -! CHECK: %[[COORD2:.*]] = fir.coordinate_of %[[ARG1]], %[[IV0]] : (!fir.ref<!fir.array<100xi32>>, index) -> !fir.ref<i32> -! CHECK: %[[LOAD1:.*]] = fir.load %[[COORD1]] : !fir.ref<i32> -! CHECK: %[[LOAD2:.*]] = fir.load %[[COORD2]] : !fir.ref<i32> -! CHECK: %[[CMP:.*]] = arith.cmpi slt, %[[LOAD1]], %[[LOAD2]] : i32 -! CHECK: %[[SELECT:.*]] = arith.select %[[CMP]], %[[LOAD1]], %[[LOAD2]] : i32 -! CHECK: fir.store %[[SELECT]] to %[[COORD1]] : !fir.ref<i32> -! CHECK: } -! CHECK: acc.yield %[[ARG0]] : !fir.ref<!fir.array<100xi32>> -! CHECK: } - -! CHECK-LABEL: acc.reduction.recipe @reduction_min_ref_i32 : !fir.ref<i32> reduction_operator <min> init { -! CHECK: ^bb0(%{{.*}}: !fir.ref<i32>): -! CHECK: %[[INIT:.*]] = arith.constant 2147483647 : i32 -! CHECK: %[[ALLOCA:.*]] = fir.alloca i32 -! CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %[[ALLOCA]] {uniq_name = "acc.reduction.init"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) -! CHECK: fir.store %[[INIT]] to %[[DECLARE]]#0 : !fir.ref<i32> -! CHECK: acc.yield %[[DECLARE]]#0 : !fir.ref<i32> -! CHECK: } combiner { -! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref<i32>, %[[ARG1:.*]]: !fir.ref<i32>): -! CHECK: %[[LOAD0:.*]] = fir.load %[[ARG0]] : !fir.ref<i32> -! CHECK: %[[LOAD1:.*]] = fir.load %[[ARG1]] : !fir.ref<i32> -! CHECK: %[[CMP:.*]] = arith.cmpi slt, %[[LOAD0]], %[[LOAD1]] : i32 -! CHECK: %[[SELECT:.*]] = arith.select %[[CMP]], %[[LOAD0]], %[[LOAD1]] : i32 -! CHECK: fir.store %[[SELECT]] to %[[ARG0]] : !fir.ref<i32> -! CHECK: acc.yield %[[ARG0]] : !fir.ref<i32> -! CHECK: } - -! CHECK-LABEL: acc.reduction.recipe @reduction_mul_ref_f32 : !fir.ref<f32> reduction_operator <mul> init { -! CHECK: ^bb0(%{{.*}}: !fir.ref<f32>): -! CHECK: %[[INIT:.*]] = arith.constant 1.000000e+00 : f32 -! CHECK: %[[ALLOCA:.*]] = fir.alloca f32 -! CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %[[ALLOCA]] {uniq_name = "acc.reduction.init"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>) -! CHECK: fir.store %[[INIT]] to %[[DECLARE]]#0 : !fir.ref<f32> -! CHECK: acc.yield %[[DECLARE]]#0 : !fir.ref<f32> -! CHECK: } combiner { -! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref<f32>, %[[ARG1:.*]]: !fir.ref<f32>): -! CHECK: %[[LOAD0:.*]] = fir.load %[[ARG0]] : !fir.ref<f32> -! CHECK: %[[LOAD1:.*]] = fir.load %[[ARG1]] : !fir.ref<f32> -! CHECK: %[[COMBINED:.*]] = arith.mulf %[[LOAD0]], %[[LOAD1]] fastmath<contract> : f32 -! CHECK: fir.store %[[COMBINED]] to %[[ARG0]] : !fir.ref<f32> -! CHECK: acc.yield %[[ARG0]] : !fir.ref<f32> -! CHECK: } - -! CHECK-LABEL: acc.reduction.recipe @reduction_mul_ref_100xi32 : !fir.ref<!fir.array<100xi32>> reduction_operator <mul> init { -! CHECK: ^bb0(%{{.*}}: !fir.ref<!fir.array<100xi32>>): -! CHECK: %[[INIT:.*]] = arith.constant 1 : i32 -! CHECK: %[[SHAPE:.*]] = fir.shape %{{.*}} : (index) -> !fir.shape<1> -! CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.array<100xi32> -! CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %[[ALLOCA]](%[[SHAPE]]) {uniq_name = "acc.reduction.init"} : (!fir.ref<!fir.array<100xi32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<100xi32>>, !fir.ref<!fir.array<100xi32>>) -! CHECK: acc.yield %[[DECLARE]]#0 : !fir.ref<!fir.array<100xi32>> -! CHECK: } combiner { -! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref<!fir.array<100xi32>>, %[[ARG1:.*]]: !fir.ref<!fir.array<100xi32>>): -! CHECK: %[[LB:.*]] = arith.constant 0 : index -! CHECK: %[[UB:.*]] = arith.constant 99 : index -! CHECK: %[[STEP:.*]] = arith.constant 1 : index -! CHECK: fir.do_loop %[[IV:.*]] = %[[LB]] to %[[UB]] step %[[STEP]] { -! CHECK: %[[COORD1:.*]] = fir.coordinate_of %[[ARG0]], %[[IV]] : (!fir.ref<!fir.array<100xi32>>, index) -> !fir.ref<i32> -! CHECK: %[[COORD2:.*]] = fir.coordinate_of %[[ARG1]], %[[IV]] : (!fir.ref<!fir.array<100xi32>>, index) -> !fir.ref<i32> -! CHECK: %[[LOAD1:.*]] = fir.load %[[COORD1]] : !fir.ref<i32> -! CHECK: %[[LOAD2:.*]] = fir.load %[[COORD2]] : !fir.ref<i32> -! CHECK: %[[COMBINED:.*]] = arith.muli %[[LOAD1]], %[[LOAD2]] : i32 -! CHECK: fir.store %[[COMBINED]] to %[[COORD1]] : !fir.ref<i32> -! CHECK: } -! CHECK: acc.yield %[[ARG0]] : !fir.ref<!fir.array<100xi32>> -! CHECK: } - -! CHECK-LABEL: acc.reduction.recipe @reduction_mul_ref_i32 : !fir.ref<i32> reduction_operator <mul> init { -! CHECK: ^bb0(%{{.*}}: !fir.ref<i32>): -! CHECK: %[[INIT:.*]] = arith.constant 1 : i32 -! CHECK: %[[ALLOCA:.*]] = fir.alloca i32 -! CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %[[ALLOCA]] {uniq_name = "acc.reduction.init"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) -! CHECK: fir.store %[[INIT]] to %[[DECLARE]]#0 : !fir.ref<i32> -! CHECK: acc.yield %[[DECLARE]]#0 : !fir.ref<i32> -! CHECK: } combiner { -! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref<i32>, %[[ARG1:.*]]: !fir.ref<i32>): -! CHECK: %[[LOAD0:.*]] = fir.load %[[ARG0]] : !fir.ref<i32> -! CHECK: %[[LOAD1:.*]] = fir.load %[[ARG1]] : !fir.ref<i32> -! CHECK: %[[COMBINED:.*]] = arith.muli %[[LOAD0]], %[[LOAD1]] : i32 -! CHECK: fir.store %[[COMBINED]] to %[[ARG0]] : !fir.ref<i32> -! CHECK: acc.yield %[[ARG0]] : !fir.ref<i32> -! CHECK: } - -! CHECK-LABEL: acc.reduction.recipe @reduction_add_ref_100xf32 : !fir.ref<!fir.array<100xf32>> reduction_operator <add> init { -! CHECK: ^bb0(%{{.*}}: !fir.ref<!fir.array<100xf32>>): -! CHECK: %[[INIT:.*]] = arith.constant 0.000000e+00 : f32 -! CHECK: %[[SHAPE:.*]] = fir.shape %{{.*}} : (index) -> !fir.shape<1> -! CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.array<100xf32> -! CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %[[ALLOCA]](%[[SHAPE]]) {uniq_name = "acc.reduction.init"} : (!fir.ref<!fir.array<100xf32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<100xf32>>, !fir.ref<!fir.array<100xf32>>) -! CHECK: acc.yield %[[DECLARE]]#0 : !fir.ref<!fir.array<100xf32>> -! CHECK: } combiner { -! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref<!fir.array<100xf32>>, %[[ARG1:.*]]: !fir.ref<!fir.array<100xf32>>): -! CHECK: %[[LB:.*]] = arith.constant 0 : index -! CHECK: %[[UB:.*]] = arith.constant 99 : index -! CHECK: %[[STEP:.*]] = arith.constant 1 : index -! CHECK: fir.do_loop %[[IV:.*]] = %[[LB]] to %[[UB]] step %[[STEP]] { -! CHECK: %[[COORD1:.*]] = fir.coordinate_of %[[ARG0]], %[[IV]] : (!fir.ref<!fir.array<100xf32>>, index) -> !fir.ref<f32> -! CHECK: %[[COORD2:.*]] = fir.coordinate_of %[[ARG1]], %[[IV]] : (!fir.ref<!fir.array<100xf32>>, index) -> !fir.ref<f32> -! CHECK: %[[LOAD1:.*]] = fir.load %[[COORD1]] : !fir.ref<f32> -! CHECK: %[[LOAD2:.*]] = fir.load %[[COORD2]] : !fir.ref<f32> -! CHECK: %[[COMBINED:.*]] = arith.addf %[[LOAD1]], %[[LOAD2]] fastmath<contract> : f32 -! CHECK: fir.store %[[COMBINED]] to %[[COORD1]] : !fir.ref<f32> -! CHECK: } -! CHECK: acc.yield %[[ARG0]] : !fir.ref<!fir.array<100xf32>> -! CHECK: } - -! CHECK-LABEL: acc.reduction.recipe @reduction_add_ref_f32 : !fir.ref<f32> reduction_operator <add> init { -! CHECK: ^bb0(%{{.*}}: !fir.ref<f32>): -! CHECK: %[[INIT:.*]] = arith.constant 0.000000e+00 : f32 -! CHECK: %[[ALLOCA:.*]] = fir.alloca f32 -! CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %[[ALLOCA]] {uniq_name = "acc.reduction.init"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>) -! CHECK: fir.store %[[INIT]] to %[[DECLARE]]#0 : !fir.ref<f32> -! CHECK: acc.yield %[[DECLARE]]#0 : !fir.ref<f32> -! CHECK: } combiner { -! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref<f32>, %[[ARG1:.*]]: !fir.ref<f32>): -! CHECK: %[[LOAD0:.*]] = fir.load %[[ARG0]] : !fir.ref<f32> -! CHECK: %[[LOAD1:.*]] = fir.load %[[ARG1]] : !fir.ref<f32> -! CHECK: %[[COMBINED:.*]] = arith.addf %[[LOAD0]], %[[LOAD1]] fastmath<contract> : f32 -! CHECK: fir.store %[[COMBINED]] to %[[ARG0]] : !fir.ref<f32> -! CHECK: acc.yield %[[ARG0]] : !fir.ref<f32> -! CHECK: } - -! CHECK-LABEL: acc.reduction.recipe @reduction_add_ref_100x10x2xi32 : !fir.ref<!fir.array<100x10x2xi32>> reduction_operator <add> init { -! CHECK: ^bb0(%{{.*}}: !fir.ref<!fir.array<100x10x2xi32>>): -! CHECK: %[[INIT:.*]] = arith.constant 0 : i32 -! CHECK: %[[SHAPE:.*]] = fir.shape %{{.*}}, %{{.*}}, %{{.*}} : (index, index, index) -> !fir.shape<3> -! CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.array<100x10x2xi32> -! CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %[[ALLOCA]](%[[SHAPE]]) {uniq_name = "acc.reduction.init"} : (!fir.ref<!fir.array<100x10x2xi32>>, !fir.shape<3>) -> (!fir.ref<!fir.array<100x10x2xi32>>, !fir.ref<!fir.array<100x10x2xi32>>) -! CHECK: %[[LB0:.*]] = arith.constant 0 : index -! CHECK: %[[UB0:.*]] = arith.constant 1 : index -! CHECK: %[[STEP0:.*]] = arith.constant 1 : index -! CHECK: fir.do_loop %[[IV0:.*]] = %[[LB0]] to %[[UB0]] step %[[STEP0]] { -! CHECK: %[[LB1:.*]] = arith.constant 0 : index -! CHECK: %[[UB1:.*]] = arith.constant 9 : index -! CHECK: %[[STEP1:.*]] = arith.constant 1 : index -! CHECK: fir.do_loop %[[IV1:.*]] = %[[LB1]] to %[[UB1]] step %[[STEP1]] { -! CHECK: %[[LB2:.*]] = arith.constant 0 : index -! CHECK: %[[UB2:.*]] = arith.constant 99 : index -! CHECK: %[[STEP2:.*]] = arith.constant 1 : index -! CHECK: fir.do_loop %[[IV2:.*]] = %[[LB2]] to %[[UB2]] step %[[STEP2]] { -! CHECK: %[[COORD]] = fir.coordinate_of %[[DECLARE]]#0, %[[IV2]], %[[IV1]], %[[IV0]] : (!fir.ref<!fir.array<100x10x2xi32>>, index, index, index) -> !fir.ref<i32> -! CHECK: fir.store %[[INIT]] to %[[COORD]] : !fir.ref<i32> -! CHECK: acc.yield %[[DECLARE]]#0 : !fir.ref<!fir.array<100x10x2xi32>> -! CHECK: } combiner { -! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref<!fir.array<100x10x2xi32>>, %[[ARG1:.*]]: !fir.ref<!fir.array<100x10x2xi32>>): -! CHECK: %[[LB0:.*]] = arith.constant 0 : index -! CHECK: %[[UB0:.*]] = arith.constant 1 : index -! CHECK: %[[STEP0:.*]] = arith.constant 1 : index -! CHECK: fir.do_loop %[[IV0:.*]] = %[[LB0]] to %[[UB0]] step %[[STEP0]] { -! CHECK: %[[LB1:.*]] = arith.constant 0 : index -! CHECK: %[[UB1:.*]] = arith.constant 9 : index -! CHECK: %[[STEP1:.*]] = arith.constant 1 : index -! CHECK: fir.do_loop %[[IV1:.*]] = %[[LB1]] to %[[UB1]] step %[[STEP1]] { -! CHECK: %[[LB2:.*]] = arith.constant 0 : index -! CHECK: %[[UB2:.*]] = arith.constant 99 : index -! CHECK: %[[STEP2:.*]] = arith.constant 1 : index -! CHECK: fir.do_loop %[[IV2:.*]] = %[[LB2]] to %[[UB2]] step %[[STEP2]] { -! CHECK: %[[COORD1:.*]] = fir.coordinate_of %[[ARG0]], %[[IV2]], %[[IV1]], %[[IV0]] : (!fir.ref<!fir.array<100x10x2xi32>>, index, index, index) -> !fir.ref<i32> -! CHECK: %[[COORD2:.*]] = fir.coordinate_of %[[ARG1]], %[[IV2]], %[[IV1]], %[[IV0]] : (!fir.ref<!fir.array<100x10x2xi32>>, index, index, index) -> !fir.ref<i32> -! CHECK: %[[LOAD1:.*]] = fir.load %[[COORD1]] : !fir.ref<i32> -! CHECK: %[[LOAD2:.*]] = fir.load %[[COORD2]] : !fir.ref<i32> -! CHECK: %[[COMBINED:.*]] = arith.addi %[[LOAD1]], %[[LOAD2]] : i32 -! CHECK: fir.store %[[COMBINED]] to %[[COORD1]] : !fir.ref<i32> -! CHECK: } -! CHECK: } -! CHECK: } -! CHECK: acc.yield %[[ARG0]] : !fir.ref<!fir.array<100x10x2xi32>> -! CHECK: } - -! CHECK-LABEL: acc.reduction.recipe @reduction_add_ref_100x10xi32 : !fir.ref<!fir.array<100x10xi32>> reduction_operator <add> init { -! CHECK: ^bb0(%{{.*}}: !fir.ref<!fir.array<100x10xi32>>): -! CHECK: %[[INIT:.*]] = arith.constant 0 : i32 -! CHECK: %[[SHAPE:.*]] = fir.shape %{{.*}}, %{{.*}} : (index, index) -> !fir.shape<2> -! CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.array<100x10xi32> -! CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %[[ALLOCA]](%[[SHAPE]]) {uniq_name = "acc.reduction.init"} : (!fir.ref<!fir.array<100x10xi32>>, !fir.shape<2>) -> (!fir.ref<!fir.array<100x10xi32>>, !fir.ref<!fir.array<100x10xi32>>) -! CHECK: acc.yield %[[DECLARE]]#0 : !fir.ref<!fir.array<100x10xi32>> -! CHECK: } combiner { -! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref<!fir.array<100x10xi32>>, %[[ARG1:.*]]: !fir.ref<!fir.array<100x10xi32>>): -! CHECK: %[[LB0:.*]] = arith.constant 0 : index -! CHECK: %[[UB0:.*]] = arith.constant 9 : index -! CHECK: %[[STEP0:.*]] = arith.constant 1 : index -! CHECK: fir.do_loop %[[IV0:.*]] = %[[LB0]] to %[[UB0]] step %[[STEP0]] { -! CHECK: %[[LB1:.*]] = arith.constant 0 : index -! CHECK: %[[UB1:.*]] = arith.constant 99 : index -! CHECK: %[[STEP1:.*]] = arith.constant 1 : index -! CHECK: fir.do_loop %[[IV1:.*]] = %[[LB1]] to %[[UB1]] step %[[STEP1]] { -! CHECK: %[[COORD1:.*]] = fir.coordinate_of %[[ARG0]], %[[IV1]], %[[IV0]] : (!fir.ref<!fir.array<100x10xi32>>, index, index) -> !fir.ref<i32> -! CHECK: %[[COORD2:.*]] = fir.coordinate_of %[[ARG1]], %[[IV1]], %[[IV0]] : (!fir.ref<!fir.array<100x10xi32>>, index, index) -> !fir.ref<i32> -! CHECK: %[[LOAD1]] = fir.load %[[COORD1]] : !fir.ref<i32> -! CHECK: %[[LOAD2]] = fir.load %[[COORD2]] : !fir.ref<i32> -! CHECK: %[[COMBINED:.*]] = arith.addi %[[LOAD1]], %[[LOAD2]] : i32 -! CHECK: fir.store %[[COMBINED]] to %[[COORD1]] : !fir.ref<i32> -! CHECK: } -! CHECK: } -! CHECK: acc.yield %[[ARG0]] : !fir.ref<!fir.array<100x10xi32>> -! CHECK: } - -! CHECK-LABEL: acc.reduction.recipe @reduction_add_ref_100xi32 : !fir.ref<!fir.array<100xi32>> reduction_operator <add> init { -! CHECK: ^bb0(%{{.*}}: !fir.ref<!fir.array<100xi32>>): -! CHECK: %[[INIT:.*]] = arith.constant 0 : i32 -! CHECK: %[[SHAPE:.*]] = fir.shape %{{.*}} : (index) -> !fir.shape<1> -! CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.array<100xi32> -! CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %[[ALLOCA]](%[[SHAPE]]) {uniq_name = "acc.reduction.init"} : (!fir.ref<!fir.array<100xi32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<100xi32>>, !fir.ref<!fir.array<100xi32>>) -! HFLIR: acc.yield %[[DECLARE]]#0 : !fir.ref<!fir.array<100xi32>> -! CHECK: } combiner { -! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref<!fir.array<100xi32>>, %[[ARG1:.*]]: !fir.ref<!fir.array<100xi32>>): -! CHECK: %[[LB:.*]] = arith.constant 0 : index -! CHECK: %[[UB:.*]] = arith.constant 99 : index -! CHECK: %[[STEP:.*]] = arith.constant 1 : index -! CHECK: fir.do_loop %[[IV:.*]] = %[[LB]] to %[[UB]] step %[[STEP]] { -! CHECK: %[[COORD1:.*]] = fir.coordinate_of %[[ARG0]], %[[IV]] : (!fir.ref<!fir.array<100xi32>>, index) -> !fir.ref<i32> -! CHECK: %[[COORD2:.*]] = fir.coordinate_of %[[ARG1]], %[[IV]] : (!fir.ref<!fir.array<100xi32>>, index) -> !fir.ref<i32> -! CHECK: %[[LOAD1:.*]] = fir.load %[[COORD1]] : !fir.ref<i32> -! CHECK: %[[LOAD2:.*]] = fir.load %[[COORD2]] : !fir.ref<i32> -! CHECK: %[[COMBINED:.*]] = arith.addi %[[LOAD1]], %[[LOAD2]] : i32 -! CHECK: fir.store %[[COMBINED]] to %[[COORD1]] : !fir.ref<i32> -! CHECK: } -! CHECK: acc.yield %[[ARG0]] : !fir.ref<!fir.array<100xi32>> -! CHECK: } - -! CHECK-LABEL: acc.reduction.recipe @reduction_add_ref_i32 : !fir.ref<i32> reduction_operator <add> init { -! CHECK: ^bb0(%{{.*}}: !fir.ref<i32>): -! CHECK: %[[INIT:.*]] = arith.constant 0 : i32 -! CHECK: %[[ALLOCA:.*]] = fir.alloca i32 -! CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %[[ALLOCA]] {uniq_name = "acc.reduction.init"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) -! CHECK: fir.store %[[INIT]] to %[[DECLARE]]#0 : !fir.ref<i32> -! CHECK: acc.yield %[[DECLARE]]#0 : !fir.ref<i32> -! CHECK: } combiner { -! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref<i32>, %[[ARG1:.*]]: !fir.ref<i32>): -! CHECK: %[[LOAD0:.*]] = fir.load %[[ARG0]] : !fir.ref<i32> -! CHECK: %[[LOAD1:.*]] = fir.load %[[ARG1]] : !fir.ref<i32> -! CHECK: %[[COMBINED:.*]] = arith.addi %[[LOAD0]], %[[LOAD1]] : i32 -! CHECK: fir.store %[[COMBINED]] to %[[ARG0]] : !fir.ref<i32> -! CHECK: acc.yield %[[ARG0]] : !fir.ref<i32> -! CHECK: } +! CHECK-LABEL: acc.reduction.recipe @reduction_max_box_UxUxf32 : !fir.box<!fir.array<?x?xf32>> reduction_operator <max> init { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.box<!fir.array<?x?xf32>>): +! CHECK: %[[CONSTANT_0:.*]] = arith.constant -1.401300e-45 : f32 +! CHECK: %[[CONSTANT_1:.*]] = arith.constant 0 : index +! CHECK: %[[BOX_DIMS_0:.*]]:3 = fir.box_dims %[[VAL_0]], %[[CONSTANT_1]] : (!fir.box<!fir.array<?x?xf32>>, index) -> (index, index, index) +! CHECK: %[[CONSTANT_2:.*]] = arith.constant 1 : index +! CHECK: %[[BOX_DIMS_1:.*]]:3 = fir.box_dims %[[VAL_0]], %[[CONSTANT_2]] : (!fir.box<!fir.array<?x?xf32>>, index) -> (index, index, index) +! CHECK: %[[SHAPE_0:.*]] = fir.shape %[[BOX_DIMS_0]]#1, %[[BOX_DIMS_1]]#1 : (index, index) -> !fir.shape<2> +! CHECK: %[[ALLOCMEM_0:.*]] = fir.allocmem !fir.array<?x?xf32>, %[[BOX_DIMS_0]]#1, %[[BOX_DIMS_1]]#1 {bindc_name = ".tmp", uniq_name = ""} +! CHECK: %[[DECLARE_0:.*]]:2 = hlfir.declare %[[ALLOCMEM_0]](%[[SHAPE_0]]) {uniq_name = ".tmp"} : (!fir.heap<!fir.array<?x?xf32>>, !fir.shape<2>) -> (!fir.box<!fir.array<?x?xf32>>, !fir.heap<!fir.array<?x?xf32>>) +! CHECK: hlfir.assign %[[CONSTANT_0]] to %[[DECLARE_0]]#0 : f32, !fir.box<!fir.array<?x?xf32>> +! CHECK: acc.yield %[[DECLARE_0]]#0 : !fir.box<!fir.array<?x?xf32>> + +! CHECK-LABEL: } combiner { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.box<!fir.array<?x?xf32>>, %[[VAL_1:.*]]: !fir.box<!fir.array<?x?xf32>>): +! CHECK: %[[CONSTANT_0:.*]] = arith.constant 0 : index +! CHECK: %[[BOX_DIMS_0:.*]]:3 = fir.box_dims %[[VAL_0]], %[[CONSTANT_0]] : (!fir.box<!fir.array<?x?xf32>>, index) -> (index, index, index) +! CHECK: %[[CONSTANT_1:.*]] = arith.constant 1 : index +! CHECK: %[[BOX_DIMS_1:.*]]:3 = fir.box_dims %[[VAL_0]], %[[CONSTANT_1]] : (!fir.box<!fir.array<?x?xf32>>, index) -> (index, index, index) +! CHECK: %[[SHAPE_0:.*]] = fir.shape %[[BOX_DIMS_0]]#1, %[[BOX_DIMS_1]]#1 : (index, index) -> !fir.shape<2> +! CHECK: %[[CONSTANT_2:.*]] = arith.constant 0 : index +! CHECK: %[[BOX_DIMS_2:.*]]:3 = fir.box_dims %[[VAL_1]], %[[CONSTANT_2]] : (!fir.box<!fir.array<?x?xf32>>, index) -> (index, index, index) +! CHECK: %[[CONSTANT_3:.*]] = arith.constant 1 : index +! CHECK: %[[BOX_DIMS_3:.*]]:3 = fir.box_dims %[[VAL_1]], %[[CONSTANT_3]] : (!fir.box<!fir.array<?x?xf32>>, index) -> (index, index, index) +! CHECK: %[[SHAPE_1:.*]] = fir.shape %[[BOX_DIMS_2]]#1, %[[BOX_DIMS_3]]#1 : (index, index) -> !fir.shape<2> +! CHECK: %[[CONSTANT_4:.*]] = arith.constant 1 : index +! CHECK: fir.do_loop %[[VAL_2:.*]] = %[[CONSTANT_4]] to %[[BOX_DIMS_1]]#1 step %[[CONSTANT_4]] unordered { +! CHECK: fir.do_loop %[[VAL_3:.*]] = %[[CONSTANT_4]] to %[[BOX_DIMS_0]]#1 step %[[CONSTANT_4]] unordered { +! CHECK: %[[CONSTANT_5:.*]] = arith.constant 0 : index +! CHECK: %[[BOX_DIMS_4:.*]]:3 = fir.box_dims %[[VAL_1]], %[[CONSTANT_5]] : (!fir.box<!fir.array<?x?xf32>>, index) -> (index, index, index) +! CHECK: %[[CONSTANT_6:.*]] = arith.constant 1 : index +! CHECK: %[[BOX_DIMS_5:.*]]:3 = fir.box_dims %[[VAL_1]], %[[CONSTANT_6]] : (!fir.box<!fir.array<?x?xf32>>, index) -> (index, index, index) +! CHECK: %[[CONSTANT_7:.*]] = arith.constant 1 : index +! CHECK: %[[SUBI_0:.*]] = arith.subi %[[BOX_DIMS_4]]#0, %[[CONSTANT_7]] : index +! CHECK: %[[ADDI_0:.*]] = arith.addi %[[VAL_3]], %[[SUBI_0]] : index +! CHECK: %[[SUBI_1:.*]] = arith.subi %[[BOX_DIMS_5]]#0, %[[CONSTANT_7]] : index +! CHECK: %[[ADDI_1:.*]] = arith.addi %[[VAL_2]], %[[SUBI_1]] : index +! CHECK: %[[DESIGNATE_0:.*]] = hlfir.designate %[[VAL_1]] (%[[ADDI_0]], %[[ADDI_1]]) : (!fir.box<!fir.array<?x?xf32>>, index, index) -> !fir.ref<f32> +! CHECK: %[[LOAD_0:.*]] = fir.load %[[DESIGNATE_0]] : !fir.ref<f32> +! CHECK: %[[CONSTANT_8:.*]] = arith.constant 0 : index +! CHECK: %[[BOX_DIMS_6:.*]]:3 = fir.box_dims %[[VAL_0]], %[[CONSTANT_8]] : (!fir.box<!fir.array<?x?xf32>>, index) -> (index, index, index) +! CHECK: %[[CONSTANT_9:.*]] = arith.constant 1 : index +! CHECK: %[[BOX_DIMS_7:.*]]:3 = fir.box_dims %[[VAL_0]], %[[CONSTANT_9]] : (!fir.box<!fir.array<?x?xf32>>, index) -> (index, index, index) +! CHECK: %[[CONSTANT_10:.*]] = arith.constant 1 : index +! CHECK: %[[SUBI_2:.*]] = arith.subi %[[BOX_DIMS_6]]#0, %[[CONSTANT_10]] : index +! CHECK: %[[ADDI_2:.*]] = arith.addi %[[VAL_3]], %[[SUBI_2]] : index +! CHECK: %[[SUBI_3:.*]] = arith.subi %[[BOX_DIMS_7]]#0, %[[CONSTANT_10]] : index +! CHECK: %[[ADDI_3:.*]] = arith.addi %[[VAL_2]], %[[SUBI_3]] : index +! CHECK: %[[DESIGNATE_1:.*]] = hlfir.designate %[[VAL_0]] (%[[ADDI_2]], %[[ADDI_3]]) : (!fir.box<!fir.array<?x?xf32>>, index, index) -> !fir.ref<f32> +! CHECK: %[[LOAD_1:.*]] = fir.load %[[DESIGNATE_1]] : !fir.ref<f32> +! CHECK: %[[CMPF_0:.*]] = arith.cmpf ogt, %[[LOAD_1]], %[[LOAD_0]] fastmath<contract> : f32 +! CHECK: %[[SELECT_0:.*]] = arith.select %[[CMPF_0]], %[[LOAD_1]], %[[LOAD_0]] : f32 +! CHECK: hlfir.assign %[[SELECT_0]] to %[[DESIGNATE_1]] : f32, !fir.ref<f32> +! CHECK: } +! CHECK: } +! CHECK: acc.yield %[[VAL_0]] : !fir.box<!fir.array<?x?xf32>> + +! CHECK-LABEL: } destroy { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.box<!fir.array<?x?xf32>>, %[[VAL_1:.*]]: !fir.box<!fir.array<?x?xf32>>): +! CHECK: %[[BOX_ADDR_0:.*]] = fir.box_addr %[[VAL_1]] : (!fir.box<!fir.array<?x?xf32>>) -> !fir.ref<!fir.array<?x?xf32>> +! CHECK: %[[CONVERT_0:.*]] = fir.convert %[[BOX_ADDR_0]] : (!fir.ref<!fir.array<?x?xf32>>) -> !fir.heap<!fir.array<?x?xf32>> +! CHECK: fir.freemem %[[CONVERT_0]] : !fir.heap<!fir.array<?x?xf32>> +! CHECK: acc.terminator +! CHECK: } + +! CHECK-LABEL: acc.reduction.recipe @reduction_max_ref_box_ptr_Uxf32 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>> reduction_operator <max> init { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>): +! CHECK: %[[CONSTANT_0:.*]] = arith.constant -1.401300e-45 : f32 +! CHECK: %[[LOAD_0:.*]] = fir.load %[[VAL_0]] : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>> +! CHECK: %[[CONSTANT_1:.*]] = arith.constant 0 : index +! CHECK: %[[BOX_DIMS_0:.*]]:3 = fir.box_dims %[[LOAD_0]], %[[CONSTANT_1]] : (!fir.box<!fir.ptr<!fir.array<?xf32>>>, index) -> (index, index, index) +! CHECK: %[[SHAPE_0:.*]] = fir.shape %[[BOX_DIMS_0]]#1 : (index) -> !fir.shape<1> +! CHECK: %[[ALLOCMEM_0:.*]] = fir.allocmem !fir.array<?xf32>, %[[BOX_DIMS_0]]#1 {bindc_name = ".tmp", uniq_name = ""} +! CHECK: %[[DECLARE_0:.*]]:2 = hlfir.declare %[[ALLOCMEM_0]](%[[SHAPE_0]]) {uniq_name = ".tmp"} : (!fir.heap<!fir.array<?xf32>>, !fir.shape<1>) -> (!fir.box<!fir.array<?xf32>>, !fir.heap<!fir.array<?xf32>>) +! CHECK: %[[ALLOCA_0:.*]] = fir.alloca !fir.box<!fir.ptr<!fir.array<?xf32>>> +! CHECK: %[[DECLARE_1:.*]]:2 = hlfir.declare %[[ALLOCA_0]] {uniq_name = "acc.reduction.init"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>) +! CHECK: %[[CONVERT_0:.*]] = fir.convert %[[DECLARE_1]]#0 : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>) -> !fir.ref<!fir.box<!fir.array<?xf32>>> +! CHECK: fir.store %[[DECLARE_0]]#0 to %[[CONVERT_0]] : !fir.ref<!fir.box<!fir.array<?xf32>>> +! CHECK: hlfir.assign %[[CONSTANT_0]] to %[[DECLARE_1]]#0 : f32, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>> +! CHECK: acc.yield %[[DECLARE_1]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>> + +! CHECK-LABEL: } combiner { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>, %[[VAL_1:.*]]: !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>): +! CHECK: %[[LOAD_0:.*]] = fir.load %[[VAL_1]] : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>> +! CHECK: %[[LOAD_1:.*]] = fir.load %[[VAL_0]] : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>> +! CHECK: %[[CONSTANT_0:.*]] = arith.constant 0 : index +! CHECK: %[[BOX_DIMS_0:.*]]:3 = fir.box_dims %[[LOAD_1]], %[[CONSTANT_0]] : (!fir.box<!fir.ptr<!fir.array<?xf32>>>, index) -> (index, index, index) +! CHECK: %[[SHAPE_0:.*]] = fir.shape %[[BOX_DIMS_0]]#1 : (index) -> !fir.shape<1> +! CHECK: %[[CONSTANT_1:.*]] = arith.constant 0 : index +! CHECK: %[[BOX_DIMS_1:.*]]:3 = fir.box_dims %[[LOAD_0]], %[[CONSTANT_1]] : (!fir.box<!fir.ptr<!fir.array<?xf32>>>, index) -> (index, index, index) +! CHECK: %[[SHAPE_1:.*]] = fir.shape %[[BOX_DIMS_1]]#1 : (index) -> !fir.shape<1> +! CHECK: %[[CONSTANT_2:.*]] = arith.constant 1 : index +! CHECK: fir.do_loop %[[VAL_2:.*]] = %[[CONSTANT_2]] to %[[BOX_DIMS_0]]#1 step %[[CONSTANT_2]] unordered { +! CHECK: %[[CONSTANT_3:.*]] = arith.constant 0 : index +! CHECK: %[[BOX_DIMS_2:.*]]:3 = fir.box_dims %[[LOAD_0]], %[[CONSTANT_3]] : (!fir.box<!fir.ptr<!fir.array<?xf32>>>, index) -> (index, index, index) +! CHECK: %[[CONSTANT_4:.*]] = arith.constant 1 : index +! CHECK: %[[SUBI_0:.*]] = arith.subi %[[BOX_DIMS_2]]#0, %[[CONSTANT_4]] : index +! CHECK: %[[ADDI_0:.*]] = arith.addi %[[VAL_2]], %[[SUBI_0]] : index +! CHECK: %[[DESIGNATE_0:.*]] = hlfir.designate %[[LOAD_0]] (%[[ADDI_0]]) : (!fir.box<!fir.ptr<!fir.array<?xf32>>>, index) -> !fir.ref<f32> +! CHECK: %[[LOAD_2:.*]] = fir.load %[[DESIGNATE_0]] : !fir.ref<f32> +! CHECK: %[[CONSTANT_5:.*]] = arith.constant 0 : index +! CHECK: %[[BOX_DIMS_3:.*]]:3 = fir.box_dims %[[LOAD_1]], %[[CONSTANT_5]] : (!fir.box<!fir.ptr<!fir.array<?xf32>>>, index) -> (index, index, index) +! CHECK: %[[CONSTANT_6:.*]] = arith.constant 1 : index +! CHECK: %[[SUBI_1:.*]] = arith.subi %[[BOX_DIMS_3]]#0, %[[CONSTANT_6]] : index +! CHECK: %[[ADDI_1:.*]] = arith.addi %[[VAL_2]], %[[SUBI_1]] : index +! CHECK: %[[DESIGNATE_1:.*]] = hlfir.designate %[[LOAD_1]] (%[[ADDI_1]]) : (!fir.box<!fir.ptr<!fir.array<?xf32>>>, index) -> !fir.ref<f32> +! CHECK: %[[LOAD_3:.*]] = fir.load %[[DESIGNATE_1]] : !fir.ref<f32> +! CHECK: %[[CMPF_0:.*]] = arith.cmpf ogt, %[[LOAD_3]], %[[LOAD_2]] fastmath<contract> : f32 +! CHECK: %[[SELECT_0:.*]] = arith.select %[[CMPF_0]], %[[LOAD_3]], %[[LOAD_2]] : f32 +! CHECK: hlfir.assign %[[SELECT_0]] to %[[DESIGNATE_1]] : f32, !fir.ref<f32> +! CHECK: } +! CHECK: acc.yield %[[VAL_0]] : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>> + +! CHECK-LABEL: } destroy { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>, %[[VAL_1:.*]]: !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>): +! CHECK: %[[LOAD_0:.*]] = fir.load %[[VAL_1]] : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>> +! CHECK: %[[BOX_ADDR_0:.*]] = fir.box_addr %[[LOAD_0]] : (!fir.box<!fir.ptr<!fir.array<?xf32>>>) -> !fir.ptr<!fir.array<?xf32>> +! CHECK: %[[CONVERT_0:.*]] = fir.convert %[[BOX_ADDR_0]] : (!fir.ptr<!fir.array<?xf32>>) -> !fir.heap<!fir.array<?xf32>> +! CHECK: fir.freemem %[[CONVERT_0]] : !fir.heap<!fir.array<?xf32>> +! CHECK: acc.terminator +! CHECK: } + +! CHECK-LABEL: acc.reduction.recipe @reduction_max_ref_box_heap_Uxf32 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>> reduction_operator <max> init { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>): +! CHECK: %[[CONSTANT_0:.*]] = arith.constant -1.401300e-45 : f32 +! CHECK: %[[LOAD_0:.*]] = fir.load %[[VAL_0]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>> +! CHECK: %[[CONSTANT_1:.*]] = arith.constant 0 : index +! CHECK: %[[BOX_DIMS_0:.*]]:3 = fir.box_dims %[[LOAD_0]], %[[CONSTANT_1]] : (!fir.box<!fir.heap<!fir.array<?xf32>>>, index) -> (index, index, index) +! CHECK: %[[SHAPE_0:.*]] = fir.shape %[[BOX_DIMS_0]]#1 : (index) -> !fir.shape<1> +! CHECK: %[[ALLOCMEM_0:.*]] = fir.allocmem !fir.array<?xf32>, %[[BOX_DIMS_0]]#1 {bindc_name = ".tmp", uniq_name = ""} +! CHECK: %[[DECLARE_0:.*]]:2 = hlfir.declare %[[ALLOCMEM_0]](%[[SHAPE_0]]) {uniq_name = ".tmp"} : (!fir.heap<!fir.array<?xf32>>, !fir.shape<1>) -> (!fir.box<!fir.array<?xf32>>, !fir.heap<!fir.array<?xf32>>) +! CHECK: %[[ALLOCA_0:.*]] = fir.alloca !fir.box<!fir.heap<!fir.array<?xf32>>> +! CHECK: %[[DECLARE_1:.*]]:2 = hlfir.declare %[[ALLOCA_0]] {uniq_name = "acc.reduction.init"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>) +! CHECK: %[[CONVERT_0:.*]] = fir.convert %[[DECLARE_1]]#0 : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>) -> !fir.ref<!fir.box<!fir.array<?xf32>>> +! CHECK: fir.store %[[DECLARE_0]]#0 to %[[CONVERT_0]] : !fir.ref<!fir.box<!fir.array<?xf32>>> +! CHECK: hlfir.assign %[[CONSTANT_0]] to %[[DECLARE_1]]#0 : f32, !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>> +! CHECK: acc.yield %[[DECLARE_1]]#0 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>> + +! CHECK-LABEL: } combiner { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>, %[[VAL_1:.*]]: !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>): +! CHECK: %[[LOAD_0:.*]] = fir.load %[[VAL_1]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>> +! CHECK: %[[LOAD_1:.*]] = fir.load %[[VAL_0]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>> +! CHECK: %[[CONSTANT_0:.*]] = arith.constant 0 : index +! CHECK: %[[BOX_DIMS_0:.*]]:3 = fir.box_dims %[[LOAD_1]], %[[CONSTANT_0]] : (!fir.box<!fir.heap<!fir.array<?xf32>>>, index) -> (index, index, index) +! CHECK: %[[SHAPE_0:.*]] = fir.shape %[[BOX_DIMS_0]]#1 : (index) -> !fir.shape<1> +! CHECK: %[[CONSTANT_1:.*]] = arith.constant 0 : index +! CHECK: %[[BOX_DIMS_1:.*]]:3 = fir.box_dims %[[LOAD_0]], %[[CONSTANT_1]] : (!fir.box<!fir.heap<!fir.array<?xf32>>>, index) -> (index, index, index) +! CHECK: %[[SHAPE_1:.*]] = fir.shape %[[BOX_DIMS_1]]#1 : (index) -> !fir.shape<1> +! CHECK: %[[CONSTANT_2:.*]] = arith.constant 1 : index +! CHECK: fir.do_loop %[[VAL_2:.*]] = %[[CONSTANT_2]] to %[[BOX_DIMS_0]]#1 step %[[CONSTANT_2]] unordered { +! CHECK: %[[CONSTANT_3:.*]] = arith.constant 0 : index +! CHECK: %[[BOX_DIMS_2:.*]]:3 = fir.box_dims %[[LOAD_0]], %[[CONSTANT_3]] : (!fir.box<!fir.heap<!fir.array<?xf32>>>, index) -> (index, index, index) +! CHECK: %[[CONSTANT_4:.*]] = arith.constant 1 : index +! CHECK: %[[SUBI_0:.*]] = arith.subi %[[BOX_DIMS_2]]#0, %[[CONSTANT_4]] : index +! CHECK: %[[ADDI_0:.*]] = arith.addi %[[VAL_2]], %[[SUBI_0]] : index +! CHECK: %[[DESIGNATE_0:.*]] = hlfir.designate %[[LOAD_0]] (%[[ADDI_0]]) : (!fir.box<!fir.heap<!fir.array<?xf32>>>, index) -> !fir.ref<f32> +! CHECK: %[[LOAD_2:.*]] = fir.load %[[DESIGNATE_0]] : !fir.ref<f32> +! CHECK: %[[CONSTANT_5:.*]] = arith.constant 0 : index +! CHECK: %[[BOX_DIMS_3:.*]]:3 = fir.box_dims %[[LOAD_1]], %[[CONSTANT_5]] : (!fir.box<!fir.heap<!fir.array<?xf32>>>, index) -> (index, index, index) +! CHECK: %[[CONSTANT_6:.*]] = arith.constant 1 : index +! CHECK: %[[SUBI_1:.*]] = arith.subi %[[BOX_DIMS_3]]#0, %[[CONSTANT_6]] : index +! CHECK: %[[ADDI_1:.*]] = arith.addi %[[VAL_2]], %[[SUBI_1]] : index +! CHECK: %[[DESIGNATE_1:.*]] = hlfir.designate %[[LOAD_1]] (%[[ADDI_1]]) : (!fir.box<!fir.heap<!fir.array<?xf32>>>, index) -> !fir.ref<f32> +! CHECK: %[[LOAD_3:.*]] = fir.load %[[DESIGNATE_1]] : !fir.ref<f32> +! CHECK: %[[CMPF_0:.*]] = arith.cmpf ogt, %[[LOAD_3]], %[[LOAD_2]] fastmath<contract> : f32 +! CHECK: %[[SELECT_0:.*]] = arith.select %[[CMPF_0]], %[[LOAD_3]], %[[LOAD_2]] : f32 +! CHECK: hlfir.assign %[[SELECT_0]] to %[[DESIGNATE_1]] : f32, !fir.ref<f32> +! CHECK: } +! CHECK: acc.yield %[[VAL_0]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>> + +! CHECK-LABEL: } destroy { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>, %[[VAL_1:.*]]: !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>): +! CHECK: %[[LOAD_0:.*]] = fir.load %[[VAL_1]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>> +! CHECK: %[[BOX_ADDR_0:.*]] = fir.box_addr %[[LOAD_0]] : (!fir.box<!fir.heap<!fir.array<?xf32>>>) -> !fir.heap<!fir.array<?xf32>> +! CHECK: fir.freemem %[[BOX_ADDR_0]] : !fir.heap<!fir.array<?xf32>> +! CHECK: acc.terminator +! CHECK: } + +! CHECK-LABEL: acc.reduction.recipe @reduction_add_section_lb1.ub3_box_Uxi32 : !fir.box<!fir.array<?xi32>> reduction_operator <add> init { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.box<!fir.array<?xi32>>): +! CHECK: %[[CONSTANT_0:.*]] = arith.constant 0 : i32 +! CHECK: %[[CONSTANT_1:.*]] = arith.constant 0 : index +! CHECK: %[[BOX_DIMS_0:.*]]:3 = fir.box_dims %[[VAL_0]], %[[CONSTANT_1]] : (!fir.box<!fir.array<?xi32>>, index) -> (index, index, index) +! CHECK: %[[SHAPE_0:.*]] = fir.shape %[[BOX_DIMS_0]]#1 : (index) -> !fir.shape<1> +! CHECK: %[[ALLOCMEM_0:.*]] = fir.allocmem !fir.array<?xi32>, %[[BOX_DIMS_0]]#1 {bindc_name = ".tmp", uniq_name = ""} +! CHECK: %[[DECLARE_0:.*]]:2 = hlfir.declare %[[ALLOCMEM_0]](%[[SHAPE_0]]) {uniq_name = ".tmp"} : (!fir.heap<!fir.array<?xi32>>, !fir.shape<1>) -> (!fir.box<!fir.array<?xi32>>, !fir.heap<!fir.array<?xi32>>) +! CHECK: hlfir.assign %[[CONSTANT_0]] to %[[DECLARE_0]]#0 : i32, !fir.box<!fir.array<?xi32>> +! CHECK: acc.yield %[[DECLARE_0]]#0 : !fir.box<!fir.array<?xi32>> + +! CHECK-LABEL: } combiner { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.box<!fir.array<?xi32>>, %[[VAL_1:.*]]: !fir.box<!fir.array<?xi32>>): +! CHECK: %[[CONSTANT_0:.*]] = arith.constant 1 : index +! CHECK: %[[CONSTANT_1:.*]] = arith.constant 3 : index +! CHECK: %[[CONSTANT_2:.*]] = arith.constant 1 : index +! CHECK: %[[CONSTANT_3:.*]] = arith.constant 0 : index +! CHECK: %[[SUBI_0:.*]] = arith.subi %[[CONSTANT_1]], %[[CONSTANT_0]] : index +! CHECK: %[[ADDI_0:.*]] = arith.addi %[[SUBI_0]], %[[CONSTANT_2]] : index +! CHECK: %[[DIVSI_0:.*]] = arith.divsi %[[ADDI_0]], %[[CONSTANT_2]] : index +! CHECK: %[[CMPI_0:.*]] = arith.cmpi sgt, %[[DIVSI_0]], %[[CONSTANT_3]] : index +! CHECK: %[[SELECT_0:.*]] = arith.select %[[CMPI_0]], %[[DIVSI_0]], %[[CONSTANT_3]] : index +! CHECK: %[[SHAPE_0:.*]] = fir.shape %[[SELECT_0]] : (index) -> !fir.shape<1> +! CHECK: %[[BD_LHS:.*]]:3 = fir.box_dims %[[VAL_0]], %c0{{.*}} : (!fir.box<!fir.array<?xi32>>, index) -> (index, index, index) +! CHECK: %[[LB_LHS:.*]] = arith.addi %[[BD_LHS]]#0, %c1{{.*}} : index +! CHECK: %[[UB_LHS:.*]] = arith.addi %[[BD_LHS]]#0, %c3{{.*}} : index +! CHECK: %[[BD_RHS:.*]]:3 = fir.box_dims %[[VAL_1]], %c0{{.*}} : (!fir.box<!fir.array<?xi32>>, index) -> (index, index, index) +! CHECK: %[[LB_RHS:.*]] = arith.addi %[[BD_RHS]]#0, %c1{{.*}} : index +! CHECK: %[[UB_RHS:.*]] = arith.addi %[[BD_RHS]]#0, %c3{{.*}} : index +! CHECK: %[[DESIGNATE_0:.*]] = hlfir.designate %[[VAL_1]] (%[[LB_RHS]]:%[[UB_RHS]]:%c1{{.*}}) shape %[[SHAPE_0]] : (!fir.box<!fir.array<?xi32>>, index, index, index, !fir.shape<1>) -> !fir.box<!fir.array<?xi32>> +! CHECK: %[[DESIGNATE_1:.*]] = hlfir.designate %[[VAL_0]] (%[[LB_LHS]]:%[[UB_LHS]]:%c1{{.*}}) shape %[[SHAPE_0]] : (!fir.box<!fir.array<?xi32>>, index, index, index, !fir.shape<1>) -> !fir.box<!fir.array<?xi32>> +! CHECK: %[[CONSTANT_4:.*]] = arith.constant 1 : index +! CHECK: fir.do_loop %[[VAL_2:.*]] = %[[CONSTANT_4]] to %[[SELECT_0]] step %[[CONSTANT_4]] unordered { +! CHECK: %[[DESIGNATE_2:.*]] = hlfir.designate %[[DESIGNATE_0]] (%[[VAL_2]]) : (!fir.box<!fir.array<?xi32>>, index) -> !fir.ref<i32> +! CHECK: %[[LOAD_0:.*]] = fir.load %[[DESIGNATE_2]] : !fir.ref<i32> +! CHECK: %[[DESIGNATE_3:.*]] = hlfir.designate %[[DESIGNATE_1]] (%[[VAL_2]]) : (!fir.box<!fir.array<?xi32>>, index) -> !fir.ref<i32> +! CHECK: %[[LOAD_1:.*]] = fir.load %[[DESIGNATE_3]] : !fir.ref<i32> +! CHECK: %[[ADDI_1:.*]] = arith.addi %[[LOAD_1]], %[[LOAD_0]] : i32 +! CHECK: hlfir.assign %[[ADDI_1]] to %[[DESIGNATE_3]] : i32, !fir.ref<i32> +! CHECK: } +! CHECK: acc.yield %[[VAL_0]] : !fir.box<!fir.array<?xi32>> + +! CHECK-LABEL: } destroy { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.box<!fir.array<?xi32>>, %[[VAL_1:.*]]: !fir.box<!fir.array<?xi32>>): +! CHECK: %[[BOX_ADDR_0:.*]] = fir.box_addr %[[VAL_1]] : (!fir.box<!fir.array<?xi32>>) -> !fir.ref<!fir.array<?xi32>> +! CHECK: %[[CONVERT_0:.*]] = fir.convert %[[BOX_ADDR_0]] : (!fir.ref<!fir.array<?xi32>>) -> !fir.heap<!fir.array<?xi32>> +! CHECK: fir.freemem %[[CONVERT_0]] : !fir.heap<!fir.array<?xi32>> +! CHECK: acc.terminator +! CHECK: } + +! CHECK-LABEL: acc.reduction.recipe @reduction_max_box_Uxf32 : !fir.box<!fir.array<?xf32>> reduction_operator <max> init { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.box<!fir.array<?xf32>>): +! CHECK: %[[CONSTANT_0:.*]] = arith.constant -1.401300e-45 : f32 +! CHECK: %[[CONSTANT_1:.*]] = arith.constant 0 : index +! CHECK: %[[BOX_DIMS_0:.*]]:3 = fir.box_dims %[[VAL_0]], %[[CONSTANT_1]] : (!fir.box<!fir.array<?xf32>>, index) -> (index, index, index) +! CHECK: %[[SHAPE_0:.*]] = fir.shape %[[BOX_DIMS_0]]#1 : (index) -> !fir.shape<1> +! CHECK: %[[ALLOCMEM_0:.*]] = fir.allocmem !fir.array<?xf32>, %[[BOX_DIMS_0]]#1 {bindc_name = ".tmp", uniq_name = ""} +! CHECK: %[[DECLARE_0:.*]]:2 = hlfir.declare %[[ALLOCMEM_0]](%[[SHAPE_0]]) {uniq_name = ".tmp"} : (!fir.heap<!fir.array<?xf32>>, !fir.shape<1>) -> (!fir.box<!fir.array<?xf32>>, !fir.heap<!fir.array<?xf32>>) +! CHECK: hlfir.assign %[[CONSTANT_0]] to %[[DECLARE_0]]#0 : f32, !fir.box<!fir.array<?xf32>> +! CHECK: acc.yield %[[DECLARE_0]]#0 : !fir.box<!fir.array<?xf32>> + +! CHECK-LABEL: } combiner { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.box<!fir.array<?xf32>>, %[[VAL_1:.*]]: !fir.box<!fir.array<?xf32>>): +! CHECK: %[[CONSTANT_0:.*]] = arith.constant 0 : index +! CHECK: %[[BOX_DIMS_0:.*]]:3 = fir.box_dims %[[VAL_0]], %[[CONSTANT_0]] : (!fir.box<!fir.array<?xf32>>, index) -> (index, index, index) +! CHECK: %[[SHAPE_0:.*]] = fir.shape %[[BOX_DIMS_0]]#1 : (index) -> !fir.shape<1> +! CHECK: %[[CONSTANT_1:.*]] = arith.constant 0 : index +! CHECK: %[[BOX_DIMS_1:.*]]:3 = fir.box_dims %[[VAL_1]], %[[CONSTANT_1]] : (!fir.box<!fir.array<?xf32>>, index) -> (index, index, index) +! CHECK: %[[SHAPE_1:.*]] = fir.shape %[[BOX_DIMS_1]]#1 : (index) -> !fir.shape<1> +! CHECK: %[[CONSTANT_2:.*]] = arith.constant 1 : index +! CHECK: fir.do_loop %[[VAL_2:.*]] = %[[CONSTANT_2]] to %[[BOX_DIMS_0]]#1 step %[[CONSTANT_2]] unordered { +! CHECK: %[[CONSTANT_3:.*]] = arith.constant 0 : index +! CHECK: %[[BOX_DIMS_2:.*]]:3 = fir.box_dims %[[VAL_1]], %[[CONSTANT_3]] : (!fir.box<!fir.array<?xf32>>, index) -> (index, index, index) +! CHECK: %[[CONSTANT_4:.*]] = arith.constant 1 : index +! CHECK: %[[SUBI_0:.*]] = arith.subi %[[BOX_DIMS_2]]#0, %[[CONSTANT_4]] : index +! CHECK: %[[ADDI_0:.*]] = arith.addi %[[VAL_2]], %[[SUBI_0]] : index +! CHECK: %[[DESIGNATE_0:.*]] = hlfir.designate %[[VAL_1]] (%[[ADDI_0]]) : (!fir.box<!fir.array<?xf32>>, index) -> !fir.ref<f32> +! CHECK: %[[LOAD_0:.*]] = fir.load %[[DESIGNATE_0]] : !fir.ref<f32> +! CHECK: %[[CONSTANT_5:.*]] = arith.constant 0 : index +! CHECK: %[[BOX_DIMS_3:.*]]:3 = fir.box_dims %[[VAL_0]], %[[CONSTANT_5]] : (!fir.box<!fir.array<?xf32>>, index) -> (index, index, index) +! CHECK: %[[CONSTANT_6:.*]] = arith.constant 1 : index +! CHECK: %[[SUBI_1:.*]] = arith.subi %[[BOX_DIMS_3]]#0, %[[CONSTANT_6]] : index +! CHECK: %[[ADDI_1:.*]] = arith.addi %[[VAL_2]], %[[SUBI_1]] : index +! CHECK: %[[DESIGNATE_1:.*]] = hlfir.designate %[[VAL_0]] (%[[ADDI_1]]) : (!fir.box<!fir.array<?xf32>>, index) -> !fir.ref<f32> +! CHECK: %[[LOAD_1:.*]] = fir.load %[[DESIGNATE_1]] : !fir.ref<f32> +! CHECK: %[[CMPF_0:.*]] = arith.cmpf ogt, %[[LOAD_1]], %[[LOAD_0]] fastmath<contract> : f32 +! CHECK: %[[SELECT_0:.*]] = arith.select %[[CMPF_0]], %[[LOAD_1]], %[[LOAD_0]] : f32 +! CHECK: hlfir.assign %[[SELECT_0]] to %[[DESIGNATE_1]] : f32, !fir.ref<f32> +! CHECK: } +! CHECK: acc.yield %[[VAL_0]] : !fir.box<!fir.array<?xf32>> + +! CHECK-LABEL: } destroy { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.box<!fir.array<?xf32>>, %[[VAL_1:.*]]: !fir.box<!fir.array<?xf32>>): +! CHECK: %[[BOX_ADDR_0:.*]] = fir.box_addr %[[VAL_1]] : (!fir.box<!fir.array<?xf32>>) -> !fir.ref<!fir.array<?xf32>> +! CHECK: %[[CONVERT_0:.*]] = fir.convert %[[BOX_ADDR_0]] : (!fir.ref<!fir.array<?xf32>>) -> !fir.heap<!fir.array<?xf32>> +! CHECK: fir.freemem %[[CONVERT_0]] : !fir.heap<!fir.array<?xf32>> +! CHECK: acc.terminator +! CHECK: } + +! CHECK-LABEL: acc.reduction.recipe @reduction_add_box_Uxi32 : !fir.box<!fir.array<?xi32>> reduction_operator <add> init { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.box<!fir.array<?xi32>>): +! CHECK: %[[CONSTANT_0:.*]] = arith.constant 0 : i32 +! CHECK: %[[CONSTANT_1:.*]] = arith.constant 0 : index +! CHECK: %[[BOX_DIMS_0:.*]]:3 = fir.box_dims %[[VAL_0]], %[[CONSTANT_1]] : (!fir.box<!fir.array<?xi32>>, index) -> (index, index, index) +! CHECK: %[[SHAPE_0:.*]] = fir.shape %[[BOX_DIMS_0]]#1 : (index) -> !fir.shape<1> +! CHECK: %[[ALLOCMEM_0:.*]] = fir.allocmem !fir.array<?xi32>, %[[BOX_DIMS_0]]#1 {bindc_name = ".tmp", uniq_name = ""} +! CHECK: %[[DECLARE_0:.*]]:2 = hlfir.declare %[[ALLOCMEM_0]](%[[SHAPE_0]]) {uniq_name = ".tmp"} : (!fir.heap<!fir.array<?xi32>>, !fir.shape<1>) -> (!fir.box<!fir.array<?xi32>>, !fir.heap<!fir.array<?xi32>>) +! CHECK: hlfir.assign %[[CONSTANT_0]] to %[[DECLARE_0]]#0 : i32, !fir.box<!fir.array<?xi32>> +! CHECK: acc.yield %[[DECLARE_0]]#0 : !fir.box<!fir.array<?xi32>> + +! CHECK-LABEL: } combiner { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.box<!fir.array<?xi32>>, %[[VAL_1:.*]]: !fir.box<!fir.array<?xi32>>): +! CHECK: %[[CONSTANT_0:.*]] = arith.constant 0 : index +! CHECK: %[[BOX_DIMS_0:.*]]:3 = fir.box_dims %[[VAL_0]], %[[CONSTANT_0]] : (!fir.box<!fir.array<?xi32>>, index) -> (index, index, index) +! CHECK: %[[SHAPE_0:.*]] = fir.shape %[[BOX_DIMS_0]]#1 : (index) -> !fir.shape<1> +! CHECK: %[[CONSTANT_1:.*]] = arith.constant 0 : index +! CHECK: %[[BOX_DIMS_1:.*]]:3 = fir.box_dims %[[VAL_1]], %[[CONSTANT_1]] : (!fir.box<!fir.array<?xi32>>, index) -> (index, index, index) +! CHECK: %[[SHAPE_1:.*]] = fir.shape %[[BOX_DIMS_1]]#1 : (index) -> !fir.shape<1> +! CHECK: %[[CONSTANT_2:.*]] = arith.constant 1 : index +! CHECK: fir.do_loop %[[VAL_2:.*]] = %[[CONSTANT_2]] to %[[BOX_DIMS_0]]#1 step %[[CONSTANT_2]] unordered { +! CHECK: %[[CONSTANT_3:.*]] = arith.constant 0 : index +! CHECK: %[[BOX_DIMS_2:.*]]:3 = fir.box_dims %[[VAL_1]], %[[CONSTANT_3]] : (!fir.box<!fir.array<?xi32>>, index) -> (index, index, index) +! CHECK: %[[CONSTANT_4:.*]] = arith.constant 1 : index +! CHECK: %[[SUBI_0:.*]] = arith.subi %[[BOX_DIMS_2]]#0, %[[CONSTANT_4]] : index +! CHECK: %[[ADDI_0:.*]] = arith.addi %[[VAL_2]], %[[SUBI_0]] : index +! CHECK: %[[DESIGNATE_0:.*]] = hlfir.designate %[[VAL_1]] (%[[ADDI_0]]) : (!fir.box<!fir.array<?xi32>>, index) -> !fir.ref<i32> +! CHECK: %[[LOAD_0:.*]] = fir.load %[[DESIGNATE_0]] : !fir.ref<i32> +! CHECK: %[[CONSTANT_5:.*]] = arith.constant 0 : index +! CHECK: %[[BOX_DIMS_3:.*]]:3 = fir.box_dims %[[VAL_0]], %[[CONSTANT_5]] : (!fir.box<!fir.array<?xi32>>, index) -> (index, index, index) +! CHECK: %[[CONSTANT_6:.*]] = arith.constant 1 : index +! CHECK: %[[SUBI_1:.*]] = arith.subi %[[BOX_DIMS_3]]#0, %[[CONSTANT_6]] : index +! CHECK: %[[ADDI_1:.*]] = arith.addi %[[VAL_2]], %[[SUBI_1]] : index +! CHECK: %[[DESIGNATE_1:.*]] = hlfir.designate %[[VAL_0]] (%[[ADDI_1]]) : (!fir.box<!fir.array<?xi32>>, index) -> !fir.ref<i32> +! CHECK: %[[LOAD_1:.*]] = fir.load %[[DESIGNATE_1]] : !fir.ref<i32> +! CHECK: %[[ADDI_2:.*]] = arith.addi %[[LOAD_1]], %[[LOAD_0]] : i32 +! CHECK: hlfir.assign %[[ADDI_2]] to %[[DESIGNATE_1]] : i32, !fir.ref<i32> +! CHECK: } +! CHECK: acc.yield %[[VAL_0]] : !fir.box<!fir.array<?xi32>> + +! CHECK-LABEL: } destroy { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.box<!fir.array<?xi32>>, %[[VAL_1:.*]]: !fir.box<!fir.array<?xi32>>): +! CHECK: %[[BOX_ADDR_0:.*]] = fir.box_addr %[[VAL_1]] : (!fir.box<!fir.array<?xi32>>) -> !fir.ref<!fir.array<?xi32>> +! CHECK: %[[CONVERT_0:.*]] = fir.convert %[[BOX_ADDR_0]] : (!fir.ref<!fir.array<?xi32>>) -> !fir.heap<!fir.array<?xi32>> +! CHECK: fir.freemem %[[CONVERT_0]] : !fir.heap<!fir.array<?xi32>> +! CHECK: acc.terminator +! CHECK: } + +! CHECK-LABEL: acc.reduction.recipe @reduction_add_section_lb0.ub9xlb0.ub19_ref_10x20xi32 : !fir.ref<!fir.array<10x20xi32>> reduction_operator <add> init { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<!fir.array<10x20xi32>>): +! CHECK: %[[CONSTANT_0:.*]] = arith.constant 0 : i32 +! CHECK: %[[CONSTANT_1:.*]] = arith.constant 10 : index +! CHECK: %[[CONSTANT_2:.*]] = arith.constant 20 : index +! CHECK: %[[SHAPE_0:.*]] = fir.shape %[[CONSTANT_1]], %[[CONSTANT_2]] : (index, index) -> !fir.shape<2> +! CHECK: %[[ALLOCA_0:.*]] = fir.alloca !fir.array<10x20xi32> +! CHECK: %[[DECLARE_0:.*]]:2 = hlfir.declare %[[ALLOCA_0]](%[[SHAPE_0]]) {uniq_name = "acc.reduction.init"} : (!fir.ref<!fir.array<10x20xi32>>, !fir.shape<2>) -> (!fir.ref<!fir.array<10x20xi32>>, !fir.ref<!fir.array<10x20xi32>>) +! CHECK: %[[CONSTANT_3:.*]] = arith.constant 0 : index +! CHECK: %[[CONSTANT_4:.*]] = arith.constant 19 : index +! CHECK: %[[CONSTANT_5:.*]] = arith.constant 1 : index +! CHECK: fir.do_loop %[[VAL_1:.*]] = %[[CONSTANT_3]] to %[[CONSTANT_4]] step %[[CONSTANT_5]] { +! CHECK: %[[CONSTANT_6:.*]] = arith.constant 0 : index +! CHECK: %[[CONSTANT_7:.*]] = arith.constant 9 : index +! CHECK: %[[CONSTANT_8:.*]] = arith.constant 1 : index +! CHECK: fir.do_loop %[[VAL_2:.*]] = %[[CONSTANT_6]] to %[[CONSTANT_7]] step %[[CONSTANT_8]] { +! CHECK: %[[COORDINATE_OF_0:.*]] = fir.coordinate_of %[[DECLARE_0]]#0, %[[VAL_2]], %[[VAL_1]] : (!fir.ref<!fir.array<10x20xi32>>, index, index) -> !fir.ref<i32> +! CHECK: fir.store %[[CONSTANT_0]] to %[[COORDINATE_OF_0]] : !fir.ref<i32> +! CHECK: } +! CHECK: } +! CHECK: acc.yield %[[DECLARE_0]]#0 : !fir.ref<!fir.array<10x20xi32>> + +! CHECK-LABEL: } combiner { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<!fir.array<10x20xi32>>, %[[VAL_1:.*]]: !fir.ref<!fir.array<10x20xi32>>): +! CHECK: %[[CONSTANT_0:.*]] = arith.constant 0 : index +! CHECK: %[[CONSTANT_1:.*]] = arith.constant 9 : index +! CHECK: %[[CONSTANT_2:.*]] = arith.constant 1 : index +! CHECK: %[[CONSTANT_3:.*]] = arith.constant 0 : index +! CHECK: %[[CONSTANT_4:.*]] = arith.constant 19 : index +! CHECK: %[[CONSTANT_5:.*]] = arith.constant 1 : index +! CHECK: %[[CONSTANT_6:.*]] = arith.constant 0 : index +! CHECK: %[[SUBI_0:.*]] = arith.subi %[[CONSTANT_1]], %[[CONSTANT_0]] : index +! CHECK: %[[ADDI_0:.*]] = arith.addi %[[SUBI_0]], %[[CONSTANT_2]] : index +! CHECK: %[[DIVSI_0:.*]] = arith.divsi %[[ADDI_0]], %[[CONSTANT_2]] : index +! CHECK: %[[CMPI_0:.*]] = arith.cmpi sgt, %[[DIVSI_0]], %[[CONSTANT_6]] : index +! CHECK: %[[SELECT_0:.*]] = arith.select %[[CMPI_0]], %[[DIVSI_0]], %[[CONSTANT_6]] : index +! CHECK: %[[CONSTANT_7:.*]] = arith.constant 0 : index +! CHECK: %[[SUBI_1:.*]] = arith.subi %[[CONSTANT_4]], %[[CONSTANT_3]] : index +! CHECK: %[[ADDI_1:.*]] = arith.addi %[[SUBI_1]], %[[CONSTANT_5]] : index +! CHECK: %[[DIVSI_1:.*]] = arith.divsi %[[ADDI_1]], %[[CONSTANT_5]] : index +! CHECK: %[[CMPI_1:.*]] = arith.cmpi sgt, %[[DIVSI_1]], %[[CONSTANT_7]] : index +! CHECK: %[[SELECT_1:.*]] = arith.select %[[CMPI_1]], %[[DIVSI_1]], %[[CONSTANT_7]] : index +! CHECK: %[[SHAPE_0:.*]] = fir.shape %[[SELECT_0]], %[[SELECT_1]] : (index, index) -> !fir.shape<2> +! CHECK: %[[DESIGNATE_0:.*]] = hlfir.designate %[[VAL_1]] (%c1{{.*}}:%c10{{.*}}:%c1{{.*}}, %c1{{.*}}:%c20{{.*}}:%c1{{.*}}) shape %[[SHAPE_0]] : (!fir.ref<!fir.array<10x20xi32>>, index, index, index, index, index, index, !fir.shape<2>) -> !fir.ref<!fir.array<10x20xi32>> +! CHECK: %[[DESIGNATE_1:.*]] = hlfir.designate %[[VAL_0]] (%c1{{.*}}:%c10{{.*}}:%c1{{.*}}, %c1{{.*}}:%c20{{.*}}:%c1{{.*}}) shape %[[SHAPE_0]] : (!fir.ref<!fir.array<10x20xi32>>, index, index, index, index, index, index, !fir.shape<2>) -> !fir.ref<!fir.array<10x20xi32>> +! CHECK: %[[CONSTANT_8:.*]] = arith.constant 1 : index +! CHECK: fir.do_loop %[[VAL_2:.*]] = %[[CONSTANT_8]] to %[[SELECT_1]] step %[[CONSTANT_8]] unordered { +! CHECK: fir.do_loop %[[VAL_3:.*]] = %[[CONSTANT_8]] to %[[SELECT_0]] step %[[CONSTANT_8]] unordered { +! CHECK: %[[DESIGNATE_2:.*]] = hlfir.designate %[[DESIGNATE_0]] (%[[VAL_3]], %[[VAL_2]]) : (!fir.ref<!fir.array<10x20xi32>>, index, index) -> !fir.ref<i32> +! CHECK: %[[LOAD_0:.*]] = fir.load %[[DESIGNATE_2]] : !fir.ref<i32> +! CHECK: %[[DESIGNATE_3:.*]] = hlfir.designate %[[DESIGNATE_1]] (%[[VAL_3]], %[[VAL_2]]) : (!fir.ref<!fir.array<10x20xi32>>, index, index) -> !fir.ref<i32> +! CHECK: %[[LOAD_1:.*]] = fir.load %[[DESIGNATE_3]] : !fir.ref<i32> +! CHECK: %[[ADDI_2:.*]] = arith.addi %[[LOAD_1]], %[[LOAD_0]] : i32 +! CHECK: hlfir.assign %[[ADDI_2]] to %[[DESIGNATE_3]] : i32, !fir.ref<i32> +! CHECK: } +! CHECK: } +! CHECK: acc.yield %[[VAL_0]] : !fir.ref<!fir.array<10x20xi32>> +! CHECK: } + +! CHECK-LABEL: acc.reduction.recipe @reduction_add_section_lb10.ub19_ref_100xi32 : !fir.ref<!fir.array<100xi32>> reduction_operator <add> init { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<!fir.array<100xi32>>): +! CHECK: %[[CONSTANT_0:.*]] = arith.constant 0 : i32 +! CHECK: %[[CONSTANT_1:.*]] = arith.constant 100 : index +! CHECK: %[[SHAPE_0:.*]] = fir.shape %[[CONSTANT_1]] : (index) -> !fir.shape<1> +! CHECK: %[[ALLOCA_0:.*]] = fir.alloca !fir.array<100xi32> +! CHECK: %[[DECLARE_0:.*]]:2 = hlfir.declare %[[ALLOCA_0]](%[[SHAPE_0]]) {uniq_name = "acc.reduction.init"} : (!fir.ref<!fir.array<100xi32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<100xi32>>, !fir.ref<!fir.array<100xi32>>) +! CHECK: %[[CONSTANT_2:.*]] = arith.constant 0 : index +! CHECK: %[[CONSTANT_3:.*]] = arith.constant 99 : index +! CHECK: %[[CONSTANT_4:.*]] = arith.constant 1 : index +! CHECK: fir.do_loop %[[VAL_1:.*]] = %[[CONSTANT_2]] to %[[CONSTANT_3]] step %[[CONSTANT_4]] { +! CHECK: %[[COORDINATE_OF_0:.*]] = fir.coordinate_of %[[DECLARE_0]]#0, %[[VAL_1]] : (!fir.ref<!fir.array<100xi32>>, index) -> !fir.ref<i32> +! CHECK: fir.store %[[CONSTANT_0]] to %[[COORDINATE_OF_0]] : !fir.ref<i32> +! CHECK: } +! CHECK: acc.yield %[[DECLARE_0]]#0 : !fir.ref<!fir.array<100xi32>> + +! CHECK-LABEL: } combiner { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<!fir.array<100xi32>>, %[[VAL_1:.*]]: !fir.ref<!fir.array<100xi32>>): +! CHECK: %[[CONSTANT_0:.*]] = arith.constant 10 : index +! CHECK: %[[CONSTANT_1:.*]] = arith.constant 19 : index +! CHECK: %[[CONSTANT_2:.*]] = arith.constant 1 : index +! CHECK: %[[CONSTANT_3:.*]] = arith.constant 0 : index +! CHECK: %[[SUBI_0:.*]] = arith.subi %[[CONSTANT_1]], %[[CONSTANT_0]] : index +! CHECK: %[[ADDI_0:.*]] = arith.addi %[[SUBI_0]], %[[CONSTANT_2]] : index +! CHECK: %[[DIVSI_0:.*]] = arith.divsi %[[ADDI_0]], %[[CONSTANT_2]] : index +! CHECK: %[[CMPI_0:.*]] = arith.cmpi sgt, %[[DIVSI_0]], %[[CONSTANT_3]] : index +! CHECK: %[[SELECT_0:.*]] = arith.select %[[CMPI_0]], %[[DIVSI_0]], %[[CONSTANT_3]] : index +! CHECK: %[[SHAPE_0:.*]] = fir.shape %[[SELECT_0]] : (index) -> !fir.shape<1> +! CHECK: %[[DESIGNATE_0:.*]] = hlfir.designate %[[VAL_1]] (%c11{{.*}}:%c20{{.*}}:%c1{{.*}}) shape %[[SHAPE_0]] : (!fir.ref<!fir.array<100xi32>>, index, index, index, !fir.shape<1>) -> !fir.ref<!fir.array<100xi32>> +! CHECK: %[[DESIGNATE_1:.*]] = hlfir.designate %[[VAL_0]] (%c11{{.*}}:%c20{{.*}}:%c1{{.*}}) shape %[[SHAPE_0]] : (!fir.ref<!fir.array<100xi32>>, index, index, index, !fir.shape<1>) -> !fir.ref<!fir.array<100xi32>> +! CHECK: %[[CONSTANT_4:.*]] = arith.constant 1 : index +! CHECK: fir.do_loop %[[VAL_2:.*]] = %[[CONSTANT_4]] to %[[SELECT_0]] step %[[CONSTANT_4]] unordered { +! CHECK: %[[DESIGNATE_2:.*]] = hlfir.designate %[[DESIGNATE_0]] (%[[VAL_2]]) : (!fir.ref<!fir.array<100xi32>>, index) -> !fir.ref<i32> +! CHECK: %[[LOAD_0:.*]] = fir.load %[[DESIGNATE_2]] : !fir.ref<i32> +! CHECK: %[[DESIGNATE_3:.*]] = hlfir.designate %[[DESIGNATE_1]] (%[[VAL_2]]) : (!fir.ref<!fir.array<100xi32>>, index) -> !fir.ref<i32> +! CHECK: %[[LOAD_1:.*]] = fir.load %[[DESIGNATE_3]] : !fir.ref<i32> +! CHECK: %[[ADDI_1:.*]] = arith.addi %[[LOAD_1]], %[[LOAD_0]] : i32 +! CHECK: hlfir.assign %[[ADDI_1]] to %[[DESIGNATE_3]] : i32, !fir.ref<i32> +! CHECK: } +! CHECK: acc.yield %[[VAL_0]] : !fir.ref<!fir.array<100xi32>> +! CHECK: } + +! CHECK-LABEL: acc.reduction.recipe @reduction_add_ref_box_ptr_i32 : !fir.ref<!fir.box<!fir.ptr<i32>>> reduction_operator <add> init { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.ptr<i32>>>): +! CHECK: %[[CONSTANT_0:.*]] = arith.constant 0 : i32 +! CHECK: %[[ALLOCA_0:.*]] = fir.alloca !fir.box<!fir.ptr<i32>> +! CHECK: %[[DECLARE_0:.*]]:2 = hlfir.declare %[[ALLOCA_0]] {uniq_name = "acc.reduction.init"} : (!fir.ref<!fir.box<!fir.ptr<i32>>>) -> (!fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.ref<!fir.box<!fir.ptr<i32>>>) +! CHECK: %[[ALLOCMEM_0:.*]] = fir.allocmem i32 +! CHECK: %[[EMBOX_0:.*]] = fir.embox %[[ALLOCMEM_0]] : (!fir.heap<i32>) -> !fir.box<!fir.ptr<i32>> +! CHECK: fir.store %[[EMBOX_0]] to %[[DECLARE_0]]#0 : !fir.ref<!fir.box<!fir.ptr<i32>>> +! CHECK: hlfir.assign %[[CONSTANT_0]] to %[[DECLARE_0]]#0 : i32, !fir.ref<!fir.box<!fir.ptr<i32>>> +! CHECK: acc.yield %[[DECLARE_0]]#0 : !fir.ref<!fir.box<!fir.ptr<i32>>> + +! CHECK-LABEL: } combiner { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.ptr<i32>>>, %[[VAL_1:.*]]: !fir.ref<!fir.box<!fir.ptr<i32>>>): +! CHECK: %[[LOAD_0:.*]] = fir.load %[[VAL_1]] : !fir.ref<!fir.box<!fir.ptr<i32>>> +! CHECK: %[[BOX_ADDR_0:.*]] = fir.box_addr %[[LOAD_0]] : (!fir.box<!fir.ptr<i32>>) -> !fir.ptr<i32> +! CHECK: %[[LOAD_1:.*]] = fir.load %[[VAL_0]] : !fir.ref<!fir.box<!fir.ptr<i32>>> +! CHECK: %[[BOX_ADDR_1:.*]] = fir.box_addr %[[LOAD_1]] : (!fir.box<!fir.ptr<i32>>) -> !fir.ptr<i32> +! CHECK: %[[LOAD_2:.*]] = fir.load %[[BOX_ADDR_0]] : !fir.ptr<i32> +! CHECK: %[[LOAD_3:.*]] = fir.load %[[BOX_ADDR_1]] : !fir.ptr<i32> +! CHECK: %[[ADDI_0:.*]] = arith.addi %[[LOAD_3]], %[[LOAD_2]] : i32 +! CHECK: hlfir.assign %[[ADDI_0]] to %[[BOX_ADDR_1]] : i32, !fir.ptr<i32> +! CHECK: acc.yield %[[VAL_0]] : !fir.ref<!fir.box<!fir.ptr<i32>>> + +! CHECK-LABEL: } destroy { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.ptr<i32>>>, %[[VAL_1:.*]]: !fir.ref<!fir.box<!fir.ptr<i32>>>): +! CHECK: %[[LOAD_0:.*]] = fir.load %[[VAL_1]] : !fir.ref<!fir.box<!fir.ptr<i32>>> +! CHECK: %[[BOX_ADDR_0:.*]] = fir.box_addr %[[LOAD_0]] : (!fir.box<!fir.ptr<i32>>) -> !fir.ptr<i32> +! CHECK: %[[CONVERT_0:.*]] = fir.convert %[[BOX_ADDR_0]] : (!fir.ptr<i32>) -> !fir.heap<i32> +! CHECK: fir.freemem %[[CONVERT_0]] : !fir.heap<i32> +! CHECK: acc.terminator +! CHECK: } + +! CHECK-LABEL: acc.reduction.recipe @reduction_add_ref_box_heap_i32 : !fir.ref<!fir.box<!fir.heap<i32>>> reduction_operator <add> init { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.heap<i32>>>): +! CHECK: %[[CONSTANT_0:.*]] = arith.constant 0 : i32 +! CHECK: %[[ALLOCA_0:.*]] = fir.alloca !fir.box<!fir.heap<i32>> +! CHECK: %[[DECLARE_0:.*]]:2 = hlfir.declare %[[ALLOCA_0]] {uniq_name = "acc.reduction.init"} : (!fir.ref<!fir.box<!fir.heap<i32>>>) -> (!fir.ref<!fir.box<!fir.heap<i32>>>, !fir.ref<!fir.box<!fir.heap<i32>>>) +! CHECK: %[[ALLOCMEM_0:.*]] = fir.allocmem i32 +! CHECK: %[[EMBOX_0:.*]] = fir.embox %[[ALLOCMEM_0]] : (!fir.heap<i32>) -> !fir.box<!fir.heap<i32>> +! CHECK: fir.store %[[EMBOX_0]] to %[[DECLARE_0]]#0 : !fir.ref<!fir.box<!fir.heap<i32>>> +! CHECK: hlfir.assign %[[CONSTANT_0]] to %[[DECLARE_0]]#0 : i32, !fir.ref<!fir.box<!fir.heap<i32>>> +! CHECK: acc.yield %[[DECLARE_0]]#0 : !fir.ref<!fir.box<!fir.heap<i32>>> + +! CHECK-LABEL: } combiner { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.heap<i32>>>, %[[VAL_1:.*]]: !fir.ref<!fir.box<!fir.heap<i32>>>): +! CHECK: %[[LOAD_0:.*]] = fir.load %[[VAL_1]] : !fir.ref<!fir.box<!fir.heap<i32>>> +! CHECK: %[[BOX_ADDR_0:.*]] = fir.box_addr %[[LOAD_0]] : (!fir.box<!fir.heap<i32>>) -> !fir.heap<i32> +! CHECK: %[[LOAD_1:.*]] = fir.load %[[VAL_0]] : !fir.ref<!fir.box<!fir.heap<i32>>> +! CHECK: %[[BOX_ADDR_1:.*]] = fir.box_addr %[[LOAD_1]] : (!fir.box<!fir.heap<i32>>) -> !fir.heap<i32> +! CHECK: %[[LOAD_2:.*]] = fir.load %[[BOX_ADDR_0]] : !fir.heap<i32> +! CHECK: %[[LOAD_3:.*]] = fir.load %[[BOX_ADDR_1]] : !fir.heap<i32> +! CHECK: %[[ADDI_0:.*]] = arith.addi %[[LOAD_3]], %[[LOAD_2]] : i32 +! CHECK: hlfir.assign %[[ADDI_0]] to %[[BOX_ADDR_1]] : i32, !fir.heap<i32> +! CHECK: acc.yield %[[VAL_0]] : !fir.ref<!fir.box<!fir.heap<i32>>> + +! CHECK-LABEL: } destroy { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.heap<i32>>>, %[[VAL_1:.*]]: !fir.ref<!fir.box<!fir.heap<i32>>>): +! CHECK: %[[LOAD_0:.*]] = fir.load %[[VAL_1]] : !fir.ref<!fir.box<!fir.heap<i32>>> +! CHECK: %[[BOX_ADDR_0:.*]] = fir.box_addr %[[LOAD_0]] : (!fir.box<!fir.heap<i32>>) -> !fir.heap<i32> +! CHECK: fir.freemem %[[BOX_ADDR_0]] : !fir.heap<i32> +! CHECK: acc.terminator +! CHECK: } + +! CHECK-LABEL: acc.reduction.recipe @reduction_mul_ref_z32 : !fir.ref<complex<f32>> reduction_operator <mul> init { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<complex<f32>>): +! CHECK: %[[CONSTANT_0:.*]] = arith.constant 1.000000e+00 : f32 +! CHECK: %[[CONSTANT_1:.*]] = arith.constant 0.000000e+00 : f32 +! CHECK: %[[UNDEFINED_0:.*]] = fir.undefined complex<f32> +! CHECK: %[[INSERT_VALUE_0:.*]] = fir.insert_value %[[UNDEFINED_0]], %[[CONSTANT_0]], [0 : index] : (complex<f32>, f32) -> complex<f32> +! CHECK: %[[INSERT_VALUE_1:.*]] = fir.insert_value %[[INSERT_VALUE_0]], %[[CONSTANT_1]], [1 : index] : (complex<f32>, f32) -> complex<f32> +! CHECK: %[[ALLOCA_0:.*]] = fir.alloca complex<f32> +! CHECK: %[[DECLARE_0:.*]]:2 = hlfir.declare %[[ALLOCA_0]] {uniq_name = "acc.reduction.init"} : (!fir.ref<complex<f32>>) -> (!fir.ref<complex<f32>>, !fir.ref<complex<f32>>) +! CHECK: fir.store %[[INSERT_VALUE_1]] to %[[DECLARE_0]]#0 : !fir.ref<complex<f32>> +! CHECK: acc.yield %[[DECLARE_0]]#0 : !fir.ref<complex<f32>> + +! CHECK-LABEL: } combiner { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<complex<f32>>, %[[VAL_1:.*]]: !fir.ref<complex<f32>>): +! CHECK: %[[LOAD_0:.*]] = fir.load %[[VAL_1]] : !fir.ref<complex<f32>> +! CHECK: %[[LOAD_1:.*]] = fir.load %[[VAL_0]] : !fir.ref<complex<f32>> +! CHECK: %[[MULC_0:.*]] = fir.mulc %[[LOAD_1]], %[[LOAD_0]] {fastmath = #arith.fastmath<contract>} : complex<f32> +! CHECK: hlfir.assign %[[MULC_0]] to %[[VAL_0]] : complex<f32>, !fir.ref<complex<f32>> +! CHECK: acc.yield %[[VAL_0]] : !fir.ref<complex<f32>> +! CHECK: } + +! CHECK-LABEL: acc.reduction.recipe @reduction_add_ref_z32 : !fir.ref<complex<f32>> reduction_operator <add> init { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<complex<f32>>): +! CHECK: %[[CONSTANT_0:.*]] = arith.constant 0.000000e+00 : f32 +! CHECK: %[[CONSTANT_1:.*]] = arith.constant 0.000000e+00 : f32 +! CHECK: %[[UNDEFINED_0:.*]] = fir.undefined complex<f32> +! CHECK: %[[INSERT_VALUE_0:.*]] = fir.insert_value %[[UNDEFINED_0]], %[[CONSTANT_0]], [0 : index] : (complex<f32>, f32) -> complex<f32> +! CHECK: %[[INSERT_VALUE_1:.*]] = fir.insert_value %[[INSERT_VALUE_0]], %[[CONSTANT_1]], [1 : index] : (complex<f32>, f32) -> complex<f32> +! CHECK: %[[ALLOCA_0:.*]] = fir.alloca complex<f32> +! CHECK: %[[DECLARE_0:.*]]:2 = hlfir.declare %[[ALLOCA_0]] {uniq_name = "acc.reduction.init"} : (!fir.ref<complex<f32>>) -> (!fir.ref<complex<f32>>, !fir.ref<complex<f32>>) +! CHECK: fir.store %[[INSERT_VALUE_1]] to %[[DECLARE_0]]#0 : !fir.ref<complex<f32>> +! CHECK: acc.yield %[[DECLARE_0]]#0 : !fir.ref<complex<f32>> + +! CHECK-LABEL: } combiner { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<complex<f32>>, %[[VAL_1:.*]]: !fir.ref<complex<f32>>): +! CHECK: %[[LOAD_0:.*]] = fir.load %[[VAL_1]] : !fir.ref<complex<f32>> +! CHECK: %[[LOAD_1:.*]] = fir.load %[[VAL_0]] : !fir.ref<complex<f32>> +! CHECK: %[[ADDC_0:.*]] = fir.addc %[[LOAD_1]], %[[LOAD_0]] {fastmath = #arith.fastmath<contract>} : complex<f32> +! CHECK: hlfir.assign %[[ADDC_0]] to %[[VAL_0]] : complex<f32>, !fir.ref<complex<f32>> +! CHECK: acc.yield %[[VAL_0]] : !fir.ref<complex<f32>> +! CHECK: } + +! CHECK-LABEL: acc.reduction.recipe @reduction_neqv_ref_l32 : !fir.ref<!fir.logical<4>> reduction_operator <neqv> init { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<!fir.logical<4>>): +! CHECK: %[[CONSTANT_0:.*]] = arith.constant false +! CHECK: %[[ALLOCA_0:.*]] = fir.alloca !fir.logical<4> +! CHECK: %[[DECLARE_0:.*]]:2 = hlfir.declare %[[ALLOCA_0]] {uniq_name = "acc.reduction.init"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) +! CHECK: %[[CONVERT_0:.*]] = fir.convert %[[CONSTANT_0]] : (i1) -> !fir.logical<4> +! CHECK: fir.store %[[CONVERT_0]] to %[[DECLARE_0]]#0 : !fir.ref<!fir.logical<4>> +! CHECK: acc.yield %[[DECLARE_0]]#0 : !fir.ref<!fir.logical<4>> + +! CHECK-LABEL: } combiner { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<!fir.logical<4>>, %[[VAL_1:.*]]: !fir.ref<!fir.logical<4>>): +! CHECK: %[[LOAD_0:.*]] = fir.load %[[VAL_1]] : !fir.ref<!fir.logical<4>> +! CHECK: %[[LOAD_1:.*]] = fir.load %[[VAL_0]] : !fir.ref<!fir.logical<4>> +! CHECK: %[[CONVERT_0:.*]] = fir.convert %[[LOAD_1]] : (!fir.logical<4>) -> i1 +! CHECK: %[[CONVERT_1:.*]] = fir.convert %[[LOAD_0]] : (!fir.logical<4>) -> i1 +! CHECK: %[[CMPI_0:.*]] = arith.cmpi ne, %[[CONVERT_0]], %[[CONVERT_1]] : i1 +! CHECK: %[[CONVERT_2:.*]] = fir.convert %[[CMPI_0]] : (i1) -> !fir.logical<4> +! CHECK: hlfir.assign %[[CONVERT_2]] to %[[VAL_0]] : !fir.logical<4>, !fir.ref<!fir.logical<4>> +! CHECK: acc.yield %[[VAL_0]] : !fir.ref<!fir.logical<4>> +! CHECK: } + +! CHECK-LABEL: acc.reduction.recipe @reduction_eqv_ref_l32 : !fir.ref<!fir.logical<4>> reduction_operator <eqv> init { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<!fir.logical<4>>): +! CHECK: %[[CONSTANT_0:.*]] = arith.constant true +! CHECK: %[[ALLOCA_0:.*]] = fir.alloca !fir.logical<4> +! CHECK: %[[DECLARE_0:.*]]:2 = hlfir.declare %[[ALLOCA_0]] {uniq_name = "acc.reduction.init"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) +! CHECK: %[[CONVERT_0:.*]] = fir.convert %[[CONSTANT_0]] : (i1) -> !fir.logical<4> +! CHECK: fir.store %[[CONVERT_0]] to %[[DECLARE_0]]#0 : !fir.ref<!fir.logical<4>> +! CHECK: acc.yield %[[DECLARE_0]]#0 : !fir.ref<!fir.logical<4>> + +! CHECK-LABEL: } combiner { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<!fir.logical<4>>, %[[VAL_1:.*]]: !fir.ref<!fir.logical<4>>): +! CHECK: %[[LOAD_0:.*]] = fir.load %[[VAL_1]] : !fir.ref<!fir.logical<4>> +! CHECK: %[[LOAD_1:.*]] = fir.load %[[VAL_0]] : !fir.ref<!fir.logical<4>> +! CHECK: %[[CONVERT_0:.*]] = fir.convert %[[LOAD_1]] : (!fir.logical<4>) -> i1 +! CHECK: %[[CONVERT_1:.*]] = fir.convert %[[LOAD_0]] : (!fir.logical<4>) -> i1 +! CHECK: %[[CMPI_0:.*]] = arith.cmpi eq, %[[CONVERT_0]], %[[CONVERT_1]] : i1 +! CHECK: %[[CONVERT_2:.*]] = fir.convert %[[CMPI_0]] : (i1) -> !fir.logical<4> +! CHECK: hlfir.assign %[[CONVERT_2]] to %[[VAL_0]] : !fir.logical<4>, !fir.ref<!fir.logical<4>> +! CHECK: acc.yield %[[VAL_0]] : !fir.ref<!fir.logical<4>> +! CHECK: } + +! CHECK-LABEL: acc.reduction.recipe @reduction_lor_ref_l32 : !fir.ref<!fir.logical<4>> reduction_operator <lor> init { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<!fir.logical<4>>): +! CHECK: %[[CONSTANT_0:.*]] = arith.constant false +! CHECK: %[[ALLOCA_0:.*]] = fir.alloca !fir.logical<4> +! CHECK: %[[DECLARE_0:.*]]:2 = hlfir.declare %[[ALLOCA_0]] {uniq_name = "acc.reduction.init"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) +! CHECK: %[[CONVERT_0:.*]] = fir.convert %[[CONSTANT_0]] : (i1) -> !fir.logical<4> +! CHECK: fir.store %[[CONVERT_0]] to %[[DECLARE_0]]#0 : !fir.ref<!fir.logical<4>> +! CHECK: acc.yield %[[DECLARE_0]]#0 : !fir.ref<!fir.logical<4>> + +! CHECK-LABEL: } combiner { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<!fir.logical<4>>, %[[VAL_1:.*]]: !fir.ref<!fir.logical<4>>): +! CHECK: %[[LOAD_0:.*]] = fir.load %[[VAL_1]] : !fir.ref<!fir.logical<4>> +! CHECK: %[[LOAD_1:.*]] = fir.load %[[VAL_0]] : !fir.ref<!fir.logical<4>> +! CHECK: %[[CONVERT_0:.*]] = fir.convert %[[LOAD_1]] : (!fir.logical<4>) -> i1 +! CHECK: %[[CONVERT_1:.*]] = fir.convert %[[LOAD_0]] : (!fir.logical<4>) -> i1 +! CHECK: %[[ORI_0:.*]] = arith.ori %[[CONVERT_0]], %[[CONVERT_1]] : i1 +! CHECK: %[[CONVERT_2:.*]] = fir.convert %[[ORI_0]] : (i1) -> !fir.logical<4> +! CHECK: hlfir.assign %[[CONVERT_2]] to %[[VAL_0]] : !fir.logical<4>, !fir.ref<!fir.logical<4>> +! CHECK: acc.yield %[[VAL_0]] : !fir.ref<!fir.logical<4>> +! CHECK: } + +! CHECK-LABEL: acc.reduction.recipe @reduction_land_ref_l32 : !fir.ref<!fir.logical<4>> reduction_operator <land> init { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<!fir.logical<4>>): +! CHECK: %[[CONSTANT_0:.*]] = arith.constant true +! CHECK: %[[ALLOCA_0:.*]] = fir.alloca !fir.logical<4> +! CHECK: %[[DECLARE_0:.*]]:2 = hlfir.declare %[[ALLOCA_0]] {uniq_name = "acc.reduction.init"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) +! CHECK: %[[CONVERT_0:.*]] = fir.convert %[[CONSTANT_0]] : (i1) -> !fir.logical<4> +! CHECK: fir.store %[[CONVERT_0]] to %[[DECLARE_0]]#0 : !fir.ref<!fir.logical<4>> +! CHECK: acc.yield %[[DECLARE_0]]#0 : !fir.ref<!fir.logical<4>> + +! CHECK-LABEL: } combiner { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<!fir.logical<4>>, %[[VAL_1:.*]]: !fir.ref<!fir.logical<4>>): +! CHECK: %[[LOAD_0:.*]] = fir.load %[[VAL_1]] : !fir.ref<!fir.logical<4>> +! CHECK: %[[LOAD_1:.*]] = fir.load %[[VAL_0]] : !fir.ref<!fir.logical<4>> +! CHECK: %[[CONVERT_0:.*]] = fir.convert %[[LOAD_1]] : (!fir.logical<4>) -> i1 +! CHECK: %[[CONVERT_1:.*]] = fir.convert %[[LOAD_0]] : (!fir.logical<4>) -> i1 +! CHECK: %[[ANDI_0:.*]] = arith.andi %[[CONVERT_0]], %[[CONVERT_1]] : i1 +! CHECK: %[[CONVERT_2:.*]] = fir.convert %[[ANDI_0]] : (i1) -> !fir.logical<4> +! CHECK: hlfir.assign %[[CONVERT_2]] to %[[VAL_0]] : !fir.logical<4>, !fir.ref<!fir.logical<4>> +! CHECK: acc.yield %[[VAL_0]] : !fir.ref<!fir.logical<4>> +! CHECK: } + +! CHECK-LABEL: acc.reduction.recipe @reduction_xor_ref_i32 : !fir.ref<i32> reduction_operator <xor> init { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<i32>): +! CHECK: %[[CONSTANT_0:.*]] = arith.constant 0 : i32 +! CHECK: %[[ALLOCA_0:.*]] = fir.alloca i32 +! CHECK: %[[DECLARE_0:.*]]:2 = hlfir.declare %[[ALLOCA_0]] {uniq_name = "acc.reduction.init"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: fir.store %[[CONSTANT_0]] to %[[DECLARE_0]]#0 : !fir.ref<i32> +! CHECK: acc.yield %[[DECLARE_0]]#0 : !fir.ref<i32> + +! CHECK-LABEL: } combiner { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<i32>, %[[VAL_1:.*]]: !fir.ref<i32>): +! CHECK: %[[LOAD_0:.*]] = fir.load %[[VAL_1]] : !fir.ref<i32> +! CHECK: %[[LOAD_1:.*]] = fir.load %[[VAL_0]] : !fir.ref<i32> +! CHECK: %[[XORI_0:.*]] = arith.xori %[[LOAD_1]], %[[LOAD_0]] : i32 +! CHECK: hlfir.assign %[[XORI_0]] to %[[VAL_0]] : i32, !fir.ref<i32> +! CHECK: acc.yield %[[VAL_0]] : !fir.ref<i32> +! CHECK: } + +! CHECK-LABEL: acc.reduction.recipe @reduction_ior_ref_i32 : !fir.ref<i32> reduction_operator <ior> init { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<i32>): +! CHECK: %[[CONSTANT_0:.*]] = arith.constant 0 : i32 +! CHECK: %[[ALLOCA_0:.*]] = fir.alloca i32 +! CHECK: %[[DECLARE_0:.*]]:2 = hlfir.declare %[[ALLOCA_0]] {uniq_name = "acc.reduction.init"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: fir.store %[[CONSTANT_0]] to %[[DECLARE_0]]#0 : !fir.ref<i32> +! CHECK: acc.yield %[[DECLARE_0]]#0 : !fir.ref<i32> + +! CHECK-LABEL: } combiner { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<i32>, %[[VAL_1:.*]]: !fir.ref<i32>): +! CHECK: %[[LOAD_0:.*]] = fir.load %[[VAL_1]] : !fir.ref<i32> +! CHECK: %[[LOAD_1:.*]] = fir.load %[[VAL_0]] : !fir.ref<i32> +! CHECK: %[[ORI_0:.*]] = arith.ori %[[LOAD_1]], %[[LOAD_0]] : i32 +! CHECK: hlfir.assign %[[ORI_0]] to %[[VAL_0]] : i32, !fir.ref<i32> +! CHECK: acc.yield %[[VAL_0]] : !fir.ref<i32> +! CHECK: } + +! CHECK-LABEL: acc.reduction.recipe @reduction_iand_ref_i32 : !fir.ref<i32> reduction_operator <iand> init { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<i32>): +! CHECK: %[[CONSTANT_0:.*]] = arith.constant -1 : i32 +! CHECK: %[[ALLOCA_0:.*]] = fir.alloca i32 +! CHECK: %[[DECLARE_0:.*]]:2 = hlfir.declare %[[ALLOCA_0]] {uniq_name = "acc.reduction.init"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: fir.store %[[CONSTANT_0]] to %[[DECLARE_0]]#0 : !fir.ref<i32> +! CHECK: acc.yield %[[DECLARE_0]]#0 : !fir.ref<i32> + +! CHECK-LABEL: } combiner { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<i32>, %[[VAL_1:.*]]: !fir.ref<i32>): +! CHECK: %[[LOAD_0:.*]] = fir.load %[[VAL_1]] : !fir.ref<i32> +! CHECK: %[[LOAD_1:.*]] = fir.load %[[VAL_0]] : !fir.ref<i32> +! CHECK: %[[ANDI_0:.*]] = arith.andi %[[LOAD_1]], %[[LOAD_0]] : i32 +! CHECK: hlfir.assign %[[ANDI_0]] to %[[VAL_0]] : i32, !fir.ref<i32> +! CHECK: acc.yield %[[VAL_0]] : !fir.ref<i32> +! CHECK: } + +! CHECK-LABEL: acc.reduction.recipe @reduction_max_ref_100xf32 : !fir.ref<!fir.array<100xf32>> reduction_operator <max> init { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<!fir.array<100xf32>>): +! CHECK: %[[CONSTANT_0:.*]] = arith.constant -1.401300e-45 : f32 +! CHECK: %[[CONSTANT_1:.*]] = arith.constant 100 : index +! CHECK: %[[SHAPE_0:.*]] = fir.shape %[[CONSTANT_1]] : (index) -> !fir.shape<1> +! CHECK: %[[ALLOCA_0:.*]] = fir.alloca !fir.array<100xf32> +! CHECK: %[[DECLARE_0:.*]]:2 = hlfir.declare %[[ALLOCA_0]](%[[SHAPE_0]]) {uniq_name = "acc.reduction.init"} : (!fir.ref<!fir.array<100xf32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<100xf32>>, !fir.ref<!fir.array<100xf32>>) +! CHECK: %[[CONSTANT_2:.*]] = arith.constant 0 : index +! CHECK: %[[CONSTANT_3:.*]] = arith.constant 99 : index +! CHECK: %[[CONSTANT_4:.*]] = arith.constant 1 : index +! CHECK: fir.do_loop %[[VAL_1:.*]] = %[[CONSTANT_2]] to %[[CONSTANT_3]] step %[[CONSTANT_4]] { +! CHECK: %[[COORDINATE_OF_0:.*]] = fir.coordinate_of %[[DECLARE_0]]#0, %[[VAL_1]] : (!fir.ref<!fir.array<100xf32>>, index) -> !fir.ref<f32> +! CHECK: fir.store %[[CONSTANT_0]] to %[[COORDINATE_OF_0]] : !fir.ref<f32> +! CHECK: } +! CHECK: acc.yield %[[DECLARE_0]]#0 : !fir.ref<!fir.array<100xf32>> + +! CHECK-LABEL: } combiner { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<!fir.array<100xf32>>, %[[VAL_1:.*]]: !fir.ref<!fir.array<100xf32>>): +! CHECK: %[[CONSTANT_0:.*]] = arith.constant 100 : index +! CHECK: %[[SHAPE_0:.*]] = fir.shape %[[CONSTANT_0]] : (index) -> !fir.shape<1> +! CHECK: %[[CONSTANT_1:.*]] = arith.constant 100 : index +! CHECK: %[[SHAPE_1:.*]] = fir.shape %[[CONSTANT_1]] : (index) -> !fir.shape<1> +! CHECK: %[[CONSTANT_2:.*]] = arith.constant 1 : index +! CHECK: fir.do_loop %[[VAL_2:.*]] = %[[CONSTANT_2]] to %[[CONSTANT_0]] step %[[CONSTANT_2]] unordered { +! CHECK: %[[DESIGNATE_0:.*]] = hlfir.designate %[[VAL_1]] (%[[VAL_2]]) : (!fir.ref<!fir.array<100xf32>>, index) -> !fir.ref<f32> +! CHECK: %[[LOAD_0:.*]] = fir.load %[[DESIGNATE_0]] : !fir.ref<f32> +! CHECK: %[[DESIGNATE_1:.*]] = hlfir.designate %[[VAL_0]] (%[[VAL_2]]) : (!fir.ref<!fir.array<100xf32>>, index) -> !fir.ref<f32> +! CHECK: %[[LOAD_1:.*]] = fir.load %[[DESIGNATE_1]] : !fir.ref<f32> +! CHECK: %[[CMPF_0:.*]] = arith.cmpf ogt, %[[LOAD_1]], %[[LOAD_0]] fastmath<contract> : f32 +! CHECK: %[[SELECT_0:.*]] = arith.select %[[CMPF_0]], %[[LOAD_1]], %[[LOAD_0]] : f32 +! CHECK: hlfir.assign %[[SELECT_0]] to %[[DESIGNATE_1]] : f32, !fir.ref<f32> +! CHECK: } +! CHECK: acc.yield %[[VAL_0]] : !fir.ref<!fir.array<100xf32>> +! CHECK: } + +! CHECK-LABEL: acc.reduction.recipe @reduction_max_ref_f32 : !fir.ref<f32> reduction_operator <max> init { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<f32>): +! CHECK: %[[CONSTANT_0:.*]] = arith.constant -1.401300e-45 : f32 +! CHECK: %[[ALLOCA_0:.*]] = fir.alloca f32 +! CHECK: %[[DECLARE_0:.*]]:2 = hlfir.declare %[[ALLOCA_0]] {uniq_name = "acc.reduction.init"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>) +! CHECK: fir.store %[[CONSTANT_0]] to %[[DECLARE_0]]#0 : !fir.ref<f32> +! CHECK: acc.yield %[[DECLARE_0]]#0 : !fir.ref<f32> + +! CHECK-LABEL: } combiner { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<f32>, %[[VAL_1:.*]]: !fir.ref<f32>): +! CHECK: %[[LOAD_0:.*]] = fir.load %[[VAL_1]] : !fir.ref<f32> +! CHECK: %[[LOAD_1:.*]] = fir.load %[[VAL_0]] : !fir.ref<f32> +! CHECK: %[[CMPF_0:.*]] = arith.cmpf ogt, %[[LOAD_1]], %[[LOAD_0]] fastmath<contract> : f32 +! CHECK: %[[SELECT_0:.*]] = arith.select %[[CMPF_0]], %[[LOAD_1]], %[[LOAD_0]] : f32 +! CHECK: hlfir.assign %[[SELECT_0]] to %[[VAL_0]] : f32, !fir.ref<f32> +! CHECK: acc.yield %[[VAL_0]] : !fir.ref<f32> +! CHECK: } + +! CHECK-LABEL: acc.reduction.recipe @reduction_max_ref_100x10xi32 : !fir.ref<!fir.array<100x10xi32>> reduction_operator <max> init { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<!fir.array<100x10xi32>>): +! CHECK: %[[CONSTANT_0:.*]] = arith.constant -2147483648 : i32 +! CHECK: %[[CONSTANT_1:.*]] = arith.constant 100 : index +! CHECK: %[[CONSTANT_2:.*]] = arith.constant 10 : index +! CHECK: %[[SHAPE_0:.*]] = fir.shape %[[CONSTANT_1]], %[[CONSTANT_2]] : (index, index) -> !fir.shape<2> +! CHECK: %[[ALLOCA_0:.*]] = fir.alloca !fir.array<100x10xi32> +! CHECK: %[[DECLARE_0:.*]]:2 = hlfir.declare %[[ALLOCA_0]](%[[SHAPE_0]]) {uniq_name = "acc.reduction.init"} : (!fir.ref<!fir.array<100x10xi32>>, !fir.shape<2>) -> (!fir.ref<!fir.array<100x10xi32>>, !fir.ref<!fir.array<100x10xi32>>) +! CHECK: %[[CONSTANT_3:.*]] = arith.constant 0 : index +! CHECK: %[[CONSTANT_4:.*]] = arith.constant 9 : index +! CHECK: %[[CONSTANT_5:.*]] = arith.constant 1 : index +! CHECK: fir.do_loop %[[VAL_1:.*]] = %[[CONSTANT_3]] to %[[CONSTANT_4]] step %[[CONSTANT_5]] { +! CHECK: %[[CONSTANT_6:.*]] = arith.constant 0 : index +! CHECK: %[[CONSTANT_7:.*]] = arith.constant 99 : index +! CHECK: %[[CONSTANT_8:.*]] = arith.constant 1 : index +! CHECK: fir.do_loop %[[VAL_2:.*]] = %[[CONSTANT_6]] to %[[CONSTANT_7]] step %[[CONSTANT_8]] { +! CHECK: %[[COORDINATE_OF_0:.*]] = fir.coordinate_of %[[DECLARE_0]]#0, %[[VAL_2]], %[[VAL_1]] : (!fir.ref<!fir.array<100x10xi32>>, index, index) -> !fir.ref<i32> +! CHECK: fir.store %[[CONSTANT_0]] to %[[COORDINATE_OF_0]] : !fir.ref<i32> +! CHECK: } +! CHECK: } +! CHECK: acc.yield %[[DECLARE_0]]#0 : !fir.ref<!fir.array<100x10xi32>> + +! CHECK-LABEL: } combiner { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<!fir.array<100x10xi32>>, %[[VAL_1:.*]]: !fir.ref<!fir.array<100x10xi32>>): +! CHECK: %[[CONSTANT_0:.*]] = arith.constant 100 : index +! CHECK: %[[CONSTANT_1:.*]] = arith.constant 10 : index +! CHECK: %[[SHAPE_0:.*]] = fir.shape %[[CONSTANT_0]], %[[CONSTANT_1]] : (index, index) -> !fir.shape<2> +! CHECK: %[[CONSTANT_2:.*]] = arith.constant 100 : index +! CHECK: %[[CONSTANT_3:.*]] = arith.constant 10 : index +! CHECK: %[[SHAPE_1:.*]] = fir.shape %[[CONSTANT_2]], %[[CONSTANT_3]] : (index, index) -> !fir.shape<2> +! CHECK: %[[CONSTANT_4:.*]] = arith.constant 1 : index +! CHECK: fir.do_loop %[[VAL_2:.*]] = %[[CONSTANT_4]] to %[[CONSTANT_1]] step %[[CONSTANT_4]] unordered { +! CHECK: fir.do_loop %[[VAL_3:.*]] = %[[CONSTANT_4]] to %[[CONSTANT_0]] step %[[CONSTANT_4]] unordered { +! CHECK: %[[DESIGNATE_0:.*]] = hlfir.designate %[[VAL_1]] (%[[VAL_3]], %[[VAL_2]]) : (!fir.ref<!fir.array<100x10xi32>>, index, index) -> !fir.ref<i32> +! CHECK: %[[LOAD_0:.*]] = fir.load %[[DESIGNATE_0]] : !fir.ref<i32> +! CHECK: %[[DESIGNATE_1:.*]] = hlfir.designate %[[VAL_0]] (%[[VAL_3]], %[[VAL_2]]) : (!fir.ref<!fir.array<100x10xi32>>, index, index) -> !fir.ref<i32> +! CHECK: %[[LOAD_1:.*]] = fir.load %[[DESIGNATE_1]] : !fir.ref<i32> +! CHECK: %[[CMPI_0:.*]] = arith.cmpi sgt, %[[LOAD_1]], %[[LOAD_0]] : i32 +! CHECK: %[[SELECT_0:.*]] = arith.select %[[CMPI_0]], %[[LOAD_1]], %[[LOAD_0]] : i32 +! CHECK: hlfir.assign %[[SELECT_0]] to %[[DESIGNATE_1]] : i32, !fir.ref<i32> +! CHECK: } +! CHECK: } +! CHECK: acc.yield %[[VAL_0]] : !fir.ref<!fir.array<100x10xi32>> +! CHECK: } + +! CHECK-LABEL: acc.reduction.recipe @reduction_max_ref_i32 : !fir.ref<i32> reduction_operator <max> init { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<i32>): +! CHECK: %[[CONSTANT_0:.*]] = arith.constant -2147483648 : i32 +! CHECK: %[[ALLOCA_0:.*]] = fir.alloca i32 +! CHECK: %[[DECLARE_0:.*]]:2 = hlfir.declare %[[ALLOCA_0]] {uniq_name = "acc.reduction.init"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: fir.store %[[CONSTANT_0]] to %[[DECLARE_0]]#0 : !fir.ref<i32> +! CHECK: acc.yield %[[DECLARE_0]]#0 : !fir.ref<i32> + +! CHECK-LABEL: } combiner { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<i32>, %[[VAL_1:.*]]: !fir.ref<i32>): +! CHECK: %[[LOAD_0:.*]] = fir.load %[[VAL_1]] : !fir.ref<i32> +! CHECK: %[[LOAD_1:.*]] = fir.load %[[VAL_0]] : !fir.ref<i32> +! CHECK: %[[CMPI_0:.*]] = arith.cmpi sgt, %[[LOAD_1]], %[[LOAD_0]] : i32 +! CHECK: %[[SELECT_0:.*]] = arith.select %[[CMPI_0]], %[[LOAD_1]], %[[LOAD_0]] : i32 +! CHECK: hlfir.assign %[[SELECT_0]] to %[[VAL_0]] : i32, !fir.ref<i32> +! CHECK: acc.yield %[[VAL_0]] : !fir.ref<i32> +! CHECK: } + +! CHECK-LABEL: acc.reduction.recipe @reduction_min_ref_100x10xf32 : !fir.ref<!fir.array<100x10xf32>> reduction_operator <min> init { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<!fir.array<100x10xf32>>): +! CHECK: %[[CONSTANT_0:.*]] = arith.constant 3.40282347E+38 : f32 +! CHECK: %[[CONSTANT_1:.*]] = arith.constant 100 : index +! CHECK: %[[CONSTANT_2:.*]] = arith.constant 10 : index +! CHECK: %[[SHAPE_0:.*]] = fir.shape %[[CONSTANT_1]], %[[CONSTANT_2]] : (index, index) -> !fir.shape<2> +! CHECK: %[[ALLOCA_0:.*]] = fir.alloca !fir.array<100x10xf32> +! CHECK: %[[DECLARE_0:.*]]:2 = hlfir.declare %[[ALLOCA_0]](%[[SHAPE_0]]) {uniq_name = "acc.reduction.init"} : (!fir.ref<!fir.array<100x10xf32>>, !fir.shape<2>) -> (!fir.ref<!fir.array<100x10xf32>>, !fir.ref<!fir.array<100x10xf32>>) +! CHECK: %[[CONSTANT_3:.*]] = arith.constant 0 : index +! CHECK: %[[CONSTANT_4:.*]] = arith.constant 9 : index +! CHECK: %[[CONSTANT_5:.*]] = arith.constant 1 : index +! CHECK: fir.do_loop %[[VAL_1:.*]] = %[[CONSTANT_3]] to %[[CONSTANT_4]] step %[[CONSTANT_5]] { +! CHECK: %[[CONSTANT_6:.*]] = arith.constant 0 : index +! CHECK: %[[CONSTANT_7:.*]] = arith.constant 99 : index +! CHECK: %[[CONSTANT_8:.*]] = arith.constant 1 : index +! CHECK: fir.do_loop %[[VAL_2:.*]] = %[[CONSTANT_6]] to %[[CONSTANT_7]] step %[[CONSTANT_8]] { +! CHECK: %[[COORDINATE_OF_0:.*]] = fir.coordinate_of %[[DECLARE_0]]#0, %[[VAL_2]], %[[VAL_1]] : (!fir.ref<!fir.array<100x10xf32>>, index, index) -> !fir.ref<f32> +! CHECK: fir.store %[[CONSTANT_0]] to %[[COORDINATE_OF_0]] : !fir.ref<f32> +! CHECK: } +! CHECK: } +! CHECK: acc.yield %[[DECLARE_0]]#0 : !fir.ref<!fir.array<100x10xf32>> + +! CHECK-LABEL: } combiner { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<!fir.array<100x10xf32>>, %[[VAL_1:.*]]: !fir.ref<!fir.array<100x10xf32>>): +! CHECK: %[[CONSTANT_0:.*]] = arith.constant 100 : index +! CHECK: %[[CONSTANT_1:.*]] = arith.constant 10 : index +! CHECK: %[[SHAPE_0:.*]] = fir.shape %[[CONSTANT_0]], %[[CONSTANT_1]] : (index, index) -> !fir.shape<2> +! CHECK: %[[CONSTANT_2:.*]] = arith.constant 100 : index +! CHECK: %[[CONSTANT_3:.*]] = arith.constant 10 : index +! CHECK: %[[SHAPE_1:.*]] = fir.shape %[[CONSTANT_2]], %[[CONSTANT_3]] : (index, index) -> !fir.shape<2> +! CHECK: %[[CONSTANT_4:.*]] = arith.constant 1 : index +! CHECK: fir.do_loop %[[VAL_2:.*]] = %[[CONSTANT_4]] to %[[CONSTANT_1]] step %[[CONSTANT_4]] unordered { +! CHECK: fir.do_loop %[[VAL_3:.*]] = %[[CONSTANT_4]] to %[[CONSTANT_0]] step %[[CONSTANT_4]] unordered { +! CHECK: %[[DESIGNATE_0:.*]] = hlfir.designate %[[VAL_1]] (%[[VAL_3]], %[[VAL_2]]) : (!fir.ref<!fir.array<100x10xf32>>, index, index) -> !fir.ref<f32> +! CHECK: %[[LOAD_0:.*]] = fir.load %[[DESIGNATE_0]] : !fir.ref<f32> +! CHECK: %[[DESIGNATE_1:.*]] = hlfir.designate %[[VAL_0]] (%[[VAL_3]], %[[VAL_2]]) : (!fir.ref<!fir.array<100x10xf32>>, index, index) -> !fir.ref<f32> +! CHECK: %[[LOAD_1:.*]] = fir.load %[[DESIGNATE_1]] : !fir.ref<f32> +! CHECK: %[[CMPF_0:.*]] = arith.cmpf olt, %[[LOAD_1]], %[[LOAD_0]] fastmath<contract> : f32 +! CHECK: %[[SELECT_0:.*]] = arith.select %[[CMPF_0]], %[[LOAD_1]], %[[LOAD_0]] : f32 +! CHECK: hlfir.assign %[[SELECT_0]] to %[[DESIGNATE_1]] : f32, !fir.ref<f32> +! CHECK: } +! CHECK: } +! CHECK: acc.yield %[[VAL_0]] : !fir.ref<!fir.array<100x10xf32>> +! CHECK: } + +! CHECK-LABEL: acc.reduction.recipe @reduction_min_ref_f32 : !fir.ref<f32> reduction_operator <min> init { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<f32>): +! CHECK: %[[CONSTANT_0:.*]] = arith.constant 3.40282347E+38 : f32 +! CHECK: %[[ALLOCA_0:.*]] = fir.alloca f32 +! CHECK: %[[DECLARE_0:.*]]:2 = hlfir.declare %[[ALLOCA_0]] {uniq_name = "acc.reduction.init"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>) +! CHECK: fir.store %[[CONSTANT_0]] to %[[DECLARE_0]]#0 : !fir.ref<f32> +! CHECK: acc.yield %[[DECLARE_0]]#0 : !fir.ref<f32> + +! CHECK-LABEL: } combiner { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<f32>, %[[VAL_1:.*]]: !fir.ref<f32>): +! CHECK: %[[LOAD_0:.*]] = fir.load %[[VAL_1]] : !fir.ref<f32> +! CHECK: %[[LOAD_1:.*]] = fir.load %[[VAL_0]] : !fir.ref<f32> +! CHECK: %[[CMPF_0:.*]] = arith.cmpf olt, %[[LOAD_1]], %[[LOAD_0]] fastmath<contract> : f32 +! CHECK: %[[SELECT_0:.*]] = arith.select %[[CMPF_0]], %[[LOAD_1]], %[[LOAD_0]] : f32 +! CHECK: hlfir.assign %[[SELECT_0]] to %[[VAL_0]] : f32, !fir.ref<f32> +! CHECK: acc.yield %[[VAL_0]] : !fir.ref<f32> +! CHECK: } + +! CHECK-LABEL: acc.reduction.recipe @reduction_min_ref_100xi32 : !fir.ref<!fir.array<100xi32>> reduction_operator <min> init { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<!fir.array<100xi32>>): +! CHECK: %[[CONSTANT_0:.*]] = arith.constant 2147483647 : i32 +! CHECK: %[[CONSTANT_1:.*]] = arith.constant 100 : index +! CHECK: %[[SHAPE_0:.*]] = fir.shape %[[CONSTANT_1]] : (index) -> !fir.shape<1> +! CHECK: %[[ALLOCA_0:.*]] = fir.alloca !fir.array<100xi32> +! CHECK: %[[DECLARE_0:.*]]:2 = hlfir.declare %[[ALLOCA_0]](%[[SHAPE_0]]) {uniq_name = "acc.reduction.init"} : (!fir.ref<!fir.array<100xi32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<100xi32>>, !fir.ref<!fir.array<100xi32>>) +! CHECK: %[[CONSTANT_2:.*]] = arith.constant 0 : index +! CHECK: %[[CONSTANT_3:.*]] = arith.constant 99 : index +! CHECK: %[[CONSTANT_4:.*]] = arith.constant 1 : index +! CHECK: fir.do_loop %[[VAL_1:.*]] = %[[CONSTANT_2]] to %[[CONSTANT_3]] step %[[CONSTANT_4]] { +! CHECK: %[[COORDINATE_OF_0:.*]] = fir.coordinate_of %[[DECLARE_0]]#0, %[[VAL_1]] : (!fir.ref<!fir.array<100xi32>>, index) -> !fir.ref<i32> +! CHECK: fir.store %[[CONSTANT_0]] to %[[COORDINATE_OF_0]] : !fir.ref<i32> +! CHECK: } +! CHECK: acc.yield %[[DECLARE_0]]#0 : !fir.ref<!fir.array<100xi32>> + +! CHECK-LABEL: } combiner { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<!fir.array<100xi32>>, %[[VAL_1:.*]]: !fir.ref<!fir.array<100xi32>>): +! CHECK: %[[CONSTANT_0:.*]] = arith.constant 100 : index +! CHECK: %[[SHAPE_0:.*]] = fir.shape %[[CONSTANT_0]] : (index) -> !fir.shape<1> +! CHECK: %[[CONSTANT_1:.*]] = arith.constant 100 : index +! CHECK: %[[SHAPE_1:.*]] = fir.shape %[[CONSTANT_1]] : (index) -> !fir.shape<1> +! CHECK: %[[CONSTANT_2:.*]] = arith.constant 1 : index +! CHECK: fir.do_loop %[[VAL_2:.*]] = %[[CONSTANT_2]] to %[[CONSTANT_0]] step %[[CONSTANT_2]] unordered { +! CHECK: %[[DESIGNATE_0:.*]] = hlfir.designate %[[VAL_1]] (%[[VAL_2]]) : (!fir.ref<!fir.array<100xi32>>, index) -> !fir.ref<i32> +! CHECK: %[[LOAD_0:.*]] = fir.load %[[DESIGNATE_0]] : !fir.ref<i32> +! CHECK: %[[DESIGNATE_1:.*]] = hlfir.designate %[[VAL_0]] (%[[VAL_2]]) : (!fir.ref<!fir.array<100xi32>>, index) -> !fir.ref<i32> +! CHECK: %[[LOAD_1:.*]] = fir.load %[[DESIGNATE_1]] : !fir.ref<i32> +! CHECK: %[[CMPI_0:.*]] = arith.cmpi slt, %[[LOAD_1]], %[[LOAD_0]] : i32 +! CHECK: %[[SELECT_0:.*]] = arith.select %[[CMPI_0]], %[[LOAD_1]], %[[LOAD_0]] : i32 +! CHECK: hlfir.assign %[[SELECT_0]] to %[[DESIGNATE_1]] : i32, !fir.ref<i32> +! CHECK: } +! CHECK: acc.yield %[[VAL_0]] : !fir.ref<!fir.array<100xi32>> +! CHECK: } + +! CHECK-LABEL: acc.reduction.recipe @reduction_min_ref_i32 : !fir.ref<i32> reduction_operator <min> init { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<i32>): +! CHECK: %[[CONSTANT_0:.*]] = arith.constant 2147483647 : i32 +! CHECK: %[[ALLOCA_0:.*]] = fir.alloca i32 +! CHECK: %[[DECLARE_0:.*]]:2 = hlfir.declare %[[ALLOCA_0]] {uniq_name = "acc.reduction.init"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: fir.store %[[CONSTANT_0]] to %[[DECLARE_0]]#0 : !fir.ref<i32> +! CHECK: acc.yield %[[DECLARE_0]]#0 : !fir.ref<i32> + +! CHECK-LABEL: } combiner { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<i32>, %[[VAL_1:.*]]: !fir.ref<i32>): +! CHECK: %[[LOAD_0:.*]] = fir.load %[[VAL_1]] : !fir.ref<i32> +! CHECK: %[[LOAD_1:.*]] = fir.load %[[VAL_0]] : !fir.ref<i32> +! CHECK: %[[CMPI_0:.*]] = arith.cmpi slt, %[[LOAD_1]], %[[LOAD_0]] : i32 +! CHECK: %[[SELECT_0:.*]] = arith.select %[[CMPI_0]], %[[LOAD_1]], %[[LOAD_0]] : i32 +! CHECK: hlfir.assign %[[SELECT_0]] to %[[VAL_0]] : i32, !fir.ref<i32> +! CHECK: acc.yield %[[VAL_0]] : !fir.ref<i32> +! CHECK: } + +! CHECK-LABEL: acc.reduction.recipe @reduction_mul_ref_100xf32 : !fir.ref<!fir.array<100xf32>> reduction_operator <mul> init { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<!fir.array<100xf32>>): +! CHECK: %[[CONSTANT_0:.*]] = arith.constant 1.000000e+00 : f32 +! CHECK: %[[CONSTANT_1:.*]] = arith.constant 100 : index +! CHECK: %[[SHAPE_0:.*]] = fir.shape %[[CONSTANT_1]] : (index) -> !fir.shape<1> +! CHECK: %[[ALLOCA_0:.*]] = fir.alloca !fir.array<100xf32> +! CHECK: %[[DECLARE_0:.*]]:2 = hlfir.declare %[[ALLOCA_0]](%[[SHAPE_0]]) {uniq_name = "acc.reduction.init"} : (!fir.ref<!fir.array<100xf32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<100xf32>>, !fir.ref<!fir.array<100xf32>>) +! CHECK: %[[CONSTANT_2:.*]] = arith.constant 0 : index +! CHECK: %[[CONSTANT_3:.*]] = arith.constant 99 : index +! CHECK: %[[CONSTANT_4:.*]] = arith.constant 1 : index +! CHECK: fir.do_loop %[[VAL_1:.*]] = %[[CONSTANT_2]] to %[[CONSTANT_3]] step %[[CONSTANT_4]] { +! CHECK: %[[COORDINATE_OF_0:.*]] = fir.coordinate_of %[[DECLARE_0]]#0, %[[VAL_1]] : (!fir.ref<!fir.array<100xf32>>, index) -> !fir.ref<f32> +! CHECK: fir.store %[[CONSTANT_0]] to %[[COORDINATE_OF_0]] : !fir.ref<f32> +! CHECK: } +! CHECK: acc.yield %[[DECLARE_0]]#0 : !fir.ref<!fir.array<100xf32>> + +! CHECK-LABEL: } combiner { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<!fir.array<100xf32>>, %[[VAL_1:.*]]: !fir.ref<!fir.array<100xf32>>): +! CHECK: %[[CONSTANT_0:.*]] = arith.constant 100 : index +! CHECK: %[[SHAPE_0:.*]] = fir.shape %[[CONSTANT_0]] : (index) -> !fir.shape<1> +! CHECK: %[[CONSTANT_1:.*]] = arith.constant 100 : index +! CHECK: %[[SHAPE_1:.*]] = fir.shape %[[CONSTANT_1]] : (index) -> !fir.shape<1> +! CHECK: %[[CONSTANT_2:.*]] = arith.constant 1 : index +! CHECK: fir.do_loop %[[VAL_2:.*]] = %[[CONSTANT_2]] to %[[CONSTANT_0]] step %[[CONSTANT_2]] unordered { +! CHECK: %[[DESIGNATE_0:.*]] = hlfir.designate %[[VAL_1]] (%[[VAL_2]]) : (!fir.ref<!fir.array<100xf32>>, index) -> !fir.ref<f32> +! CHECK: %[[LOAD_0:.*]] = fir.load %[[DESIGNATE_0]] : !fir.ref<f32> +! CHECK: %[[DESIGNATE_1:.*]] = hlfir.designate %[[VAL_0]] (%[[VAL_2]]) : (!fir.ref<!fir.array<100xf32>>, index) -> !fir.ref<f32> +! CHECK: %[[LOAD_1:.*]] = fir.load %[[DESIGNATE_1]] : !fir.ref<f32> +! CHECK: %[[MULF_0:.*]] = arith.mulf %[[LOAD_1]], %[[LOAD_0]] fastmath<contract> : f32 +! CHECK: hlfir.assign %[[MULF_0]] to %[[DESIGNATE_1]] : f32, !fir.ref<f32> +! CHECK: } +! CHECK: acc.yield %[[VAL_0]] : !fir.ref<!fir.array<100xf32>> +! CHECK: } + +! CHECK-LABEL: acc.reduction.recipe @reduction_mul_ref_f32 : !fir.ref<f32> reduction_operator <mul> init { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<f32>): +! CHECK: %[[CONSTANT_0:.*]] = arith.constant 1.000000e+00 : f32 +! CHECK: %[[ALLOCA_0:.*]] = fir.alloca f32 +! CHECK: %[[DECLARE_0:.*]]:2 = hlfir.declare %[[ALLOCA_0]] {uniq_name = "acc.reduction.init"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>) +! CHECK: fir.store %[[CONSTANT_0]] to %[[DECLARE_0]]#0 : !fir.ref<f32> +! CHECK: acc.yield %[[DECLARE_0]]#0 : !fir.ref<f32> + +! CHECK-LABEL: } combiner { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<f32>, %[[VAL_1:.*]]: !fir.ref<f32>): +! CHECK: %[[LOAD_0:.*]] = fir.load %[[VAL_1]] : !fir.ref<f32> +! CHECK: %[[LOAD_1:.*]] = fir.load %[[VAL_0]] : !fir.ref<f32> +! CHECK: %[[MULF_0:.*]] = arith.mulf %[[LOAD_1]], %[[LOAD_0]] fastmath<contract> : f32 +! CHECK: hlfir.assign %[[MULF_0]] to %[[VAL_0]] : f32, !fir.ref<f32> +! CHECK: acc.yield %[[VAL_0]] : !fir.ref<f32> +! CHECK: } + +! CHECK-LABEL: acc.reduction.recipe @reduction_mul_ref_100xi32 : !fir.ref<!fir.array<100xi32>> reduction_operator <mul> init { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<!fir.array<100xi32>>): +! CHECK: %[[CONSTANT_0:.*]] = arith.constant 1 : i32 +! CHECK: %[[CONSTANT_1:.*]] = arith.constant 100 : index +! CHECK: %[[SHAPE_0:.*]] = fir.shape %[[CONSTANT_1]] : (index) -> !fir.shape<1> +! CHECK: %[[ALLOCA_0:.*]] = fir.alloca !fir.array<100xi32> +! CHECK: %[[DECLARE_0:.*]]:2 = hlfir.declare %[[ALLOCA_0]](%[[SHAPE_0]]) {uniq_name = "acc.reduction.init"} : (!fir.ref<!fir.array<100xi32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<100xi32>>, !fir.ref<!fir.array<100xi32>>) +! CHECK: %[[CONSTANT_2:.*]] = arith.constant 0 : index +! CHECK: %[[CONSTANT_3:.*]] = arith.constant 99 : index +! CHECK: %[[CONSTANT_4:.*]] = arith.constant 1 : index +! CHECK: fir.do_loop %[[VAL_1:.*]] = %[[CONSTANT_2]] to %[[CONSTANT_3]] step %[[CONSTANT_4]] { +! CHECK: %[[COORDINATE_OF_0:.*]] = fir.coordinate_of %[[DECLARE_0]]#0, %[[VAL_1]] : (!fir.ref<!fir.array<100xi32>>, index) -> !fir.ref<i32> +! CHECK: fir.store %[[CONSTANT_0]] to %[[COORDINATE_OF_0]] : !fir.ref<i32> +! CHECK: } +! CHECK: acc.yield %[[DECLARE_0]]#0 : !fir.ref<!fir.array<100xi32>> + +! CHECK-LABEL: } combiner { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<!fir.array<100xi32>>, %[[VAL_1:.*]]: !fir.ref<!fir.array<100xi32>>): +! CHECK: %[[CONSTANT_0:.*]] = arith.constant 100 : index +! CHECK: %[[SHAPE_0:.*]] = fir.shape %[[CONSTANT_0]] : (index) -> !fir.shape<1> +! CHECK: %[[CONSTANT_1:.*]] = arith.constant 100 : index +! CHECK: %[[SHAPE_1:.*]] = fir.shape %[[CONSTANT_1]] : (index) -> !fir.shape<1> +! CHECK: %[[CONSTANT_2:.*]] = arith.constant 1 : index +! CHECK: fir.do_loop %[[VAL_2:.*]] = %[[CONSTANT_2]] to %[[CONSTANT_0]] step %[[CONSTANT_2]] unordered { +! CHECK: %[[DESIGNATE_0:.*]] = hlfir.designate %[[VAL_1]] (%[[VAL_2]]) : (!fir.ref<!fir.array<100xi32>>, index) -> !fir.ref<i32> +! CHECK: %[[LOAD_0:.*]] = fir.load %[[DESIGNATE_0]] : !fir.ref<i32> +! CHECK: %[[DESIGNATE_1:.*]] = hlfir.designate %[[VAL_0]] (%[[VAL_2]]) : (!fir.ref<!fir.array<100xi32>>, index) -> !fir.ref<i32> +! CHECK: %[[LOAD_1:.*]] = fir.load %[[DESIGNATE_1]] : !fir.ref<i32> +! CHECK: %[[MULI_0:.*]] = arith.muli %[[LOAD_1]], %[[LOAD_0]] : i32 +! CHECK: hlfir.assign %[[MULI_0]] to %[[DESIGNATE_1]] : i32, !fir.ref<i32> +! CHECK: } +! CHECK: acc.yield %[[VAL_0]] : !fir.ref<!fir.array<100xi32>> +! CHECK: } + +! CHECK-LABEL: acc.reduction.recipe @reduction_mul_ref_i32 : !fir.ref<i32> reduction_operator <mul> init { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<i32>): +! CHECK: %[[CONSTANT_0:.*]] = arith.constant 1 : i32 +! CHECK: %[[ALLOCA_0:.*]] = fir.alloca i32 +! CHECK: %[[DECLARE_0:.*]]:2 = hlfir.declare %[[ALLOCA_0]] {uniq_name = "acc.reduction.init"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: fir.store %[[CONSTANT_0]] to %[[DECLARE_0]]#0 : !fir.ref<i32> +! CHECK: acc.yield %[[DECLARE_0]]#0 : !fir.ref<i32> + +! CHECK-LABEL: } combiner { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<i32>, %[[VAL_1:.*]]: !fir.ref<i32>): +! CHECK: %[[LOAD_0:.*]] = fir.load %[[VAL_1]] : !fir.ref<i32> +! CHECK: %[[LOAD_1:.*]] = fir.load %[[VAL_0]] : !fir.ref<i32> +! CHECK: %[[MULI_0:.*]] = arith.muli %[[LOAD_1]], %[[LOAD_0]] : i32 +! CHECK: hlfir.assign %[[MULI_0]] to %[[VAL_0]] : i32, !fir.ref<i32> +! CHECK: acc.yield %[[VAL_0]] : !fir.ref<i32> +! CHECK: } + +! CHECK-LABEL: acc.reduction.recipe @reduction_add_ref_100xf32 : !fir.ref<!fir.array<100xf32>> reduction_operator <add> init { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<!fir.array<100xf32>>): +! CHECK: %[[CONSTANT_0:.*]] = arith.constant 0.000000e+00 : f32 +! CHECK: %[[CONSTANT_1:.*]] = arith.constant 100 : index +! CHECK: %[[SHAPE_0:.*]] = fir.shape %[[CONSTANT_1]] : (index) -> !fir.shape<1> +! CHECK: %[[ALLOCA_0:.*]] = fir.alloca !fir.array<100xf32> +! CHECK: %[[DECLARE_0:.*]]:2 = hlfir.declare %[[ALLOCA_0]](%[[SHAPE_0]]) {uniq_name = "acc.reduction.init"} : (!fir.ref<!fir.array<100xf32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<100xf32>>, !fir.ref<!fir.array<100xf32>>) +! CHECK: %[[CONSTANT_2:.*]] = arith.constant 0 : index +! CHECK: %[[CONSTANT_3:.*]] = arith.constant 99 : index +! CHECK: %[[CONSTANT_4:.*]] = arith.constant 1 : index +! CHECK: fir.do_loop %[[VAL_1:.*]] = %[[CONSTANT_2]] to %[[CONSTANT_3]] step %[[CONSTANT_4]] { +! CHECK: %[[COORDINATE_OF_0:.*]] = fir.coordinate_of %[[DECLARE_0]]#0, %[[VAL_1]] : (!fir.ref<!fir.array<100xf32>>, index) -> !fir.ref<f32> +! CHECK: fir.store %[[CONSTANT_0]] to %[[COORDINATE_OF_0]] : !fir.ref<f32> +! CHECK: } +! CHECK: acc.yield %[[DECLARE_0]]#0 : !fir.ref<!fir.array<100xf32>> + +! CHECK-LABEL: } combiner { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<!fir.array<100xf32>>, %[[VAL_1:.*]]: !fir.ref<!fir.array<100xf32>>): +! CHECK: %[[CONSTANT_0:.*]] = arith.constant 100 : index +! CHECK: %[[SHAPE_0:.*]] = fir.shape %[[CONSTANT_0]] : (index) -> !fir.shape<1> +! CHECK: %[[CONSTANT_1:.*]] = arith.constant 100 : index +! CHECK: %[[SHAPE_1:.*]] = fir.shape %[[CONSTANT_1]] : (index) -> !fir.shape<1> +! CHECK: %[[CONSTANT_2:.*]] = arith.constant 1 : index +! CHECK: fir.do_loop %[[VAL_2:.*]] = %[[CONSTANT_2]] to %[[CONSTANT_0]] step %[[CONSTANT_2]] unordered { +! CHECK: %[[DESIGNATE_0:.*]] = hlfir.designate %[[VAL_1]] (%[[VAL_2]]) : (!fir.ref<!fir.array<100xf32>>, index) -> !fir.ref<f32> +! CHECK: %[[LOAD_0:.*]] = fir.load %[[DESIGNATE_0]] : !fir.ref<f32> +! CHECK: %[[DESIGNATE_1:.*]] = hlfir.designate %[[VAL_0]] (%[[VAL_2]]) : (!fir.ref<!fir.array<100xf32>>, index) -> !fir.ref<f32> +! CHECK: %[[LOAD_1:.*]] = fir.load %[[DESIGNATE_1]] : !fir.ref<f32> +! CHECK: %[[ADDF_0:.*]] = arith.addf %[[LOAD_1]], %[[LOAD_0]] fastmath<contract> : f32 +! CHECK: hlfir.assign %[[ADDF_0]] to %[[DESIGNATE_1]] : f32, !fir.ref<f32> +! CHECK: } +! CHECK: acc.yield %[[VAL_0]] : !fir.ref<!fir.array<100xf32>> +! CHECK: } + +! CHECK-LABEL: acc.reduction.recipe @reduction_add_ref_f32 : !fir.ref<f32> reduction_operator <add> init { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<f32>): +! CHECK: %[[CONSTANT_0:.*]] = arith.constant 0.000000e+00 : f32 +! CHECK: %[[ALLOCA_0:.*]] = fir.alloca f32 +! CHECK: %[[DECLARE_0:.*]]:2 = hlfir.declare %[[ALLOCA_0]] {uniq_name = "acc.reduction.init"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>) +! CHECK: fir.store %[[CONSTANT_0]] to %[[DECLARE_0]]#0 : !fir.ref<f32> +! CHECK: acc.yield %[[DECLARE_0]]#0 : !fir.ref<f32> + +! CHECK-LABEL: } combiner { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<f32>, %[[VAL_1:.*]]: !fir.ref<f32>): +! CHECK: %[[LOAD_0:.*]] = fir.load %[[VAL_1]] : !fir.ref<f32> +! CHECK: %[[LOAD_1:.*]] = fir.load %[[VAL_0]] : !fir.ref<f32> +! CHECK: %[[ADDF_0:.*]] = arith.addf %[[LOAD_1]], %[[LOAD_0]] fastmath<contract> : f32 +! CHECK: hlfir.assign %[[ADDF_0]] to %[[VAL_0]] : f32, !fir.ref<f32> +! CHECK: acc.yield %[[VAL_0]] : !fir.ref<f32> +! CHECK: } + +! CHECK-LABEL: acc.reduction.recipe @reduction_add_ref_100x10x2xi32 : !fir.ref<!fir.array<100x10x2xi32>> reduction_operator <add> init { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<!fir.array<100x10x2xi32>>): +! CHECK: %[[CONSTANT_0:.*]] = arith.constant 0 : i32 +! CHECK: %[[CONSTANT_1:.*]] = arith.constant 100 : index +! CHECK: %[[CONSTANT_2:.*]] = arith.constant 10 : index +! CHECK: %[[CONSTANT_3:.*]] = arith.constant 2 : index +! CHECK: %[[SHAPE_0:.*]] = fir.shape %[[CONSTANT_1]], %[[CONSTANT_2]], %[[CONSTANT_3]] : (index, index, index) -> !fir.shape<3> +! CHECK: %[[ALLOCA_0:.*]] = fir.alloca !fir.array<100x10x2xi32> +! CHECK: %[[DECLARE_0:.*]]:2 = hlfir.declare %[[ALLOCA_0]](%[[SHAPE_0]]) {uniq_name = "acc.reduction.init"} : (!fir.ref<!fir.array<100x10x2xi32>>, !fir.shape<3>) -> (!fir.ref<!fir.array<100x10x2xi32>>, !fir.ref<!fir.array<100x10x2xi32>>) +! CHECK: %[[CONSTANT_4:.*]] = arith.constant 0 : index +! CHECK: %[[CONSTANT_5:.*]] = arith.constant 1 : index +! CHECK: %[[CONSTANT_6:.*]] = arith.constant 1 : index +! CHECK: fir.do_loop %[[VAL_1:.*]] = %[[CONSTANT_4]] to %[[CONSTANT_5]] step %[[CONSTANT_6]] { +! CHECK: %[[CONSTANT_7:.*]] = arith.constant 0 : index +! CHECK: %[[CONSTANT_8:.*]] = arith.constant 9 : index +! CHECK: %[[CONSTANT_9:.*]] = arith.constant 1 : index +! CHECK: fir.do_loop %[[VAL_2:.*]] = %[[CONSTANT_7]] to %[[CONSTANT_8]] step %[[CONSTANT_9]] { +! CHECK: %[[CONSTANT_10:.*]] = arith.constant 0 : index +! CHECK: %[[CONSTANT_11:.*]] = arith.constant 99 : index +! CHECK: %[[CONSTANT_12:.*]] = arith.constant 1 : index +! CHECK: fir.do_loop %[[VAL_3:.*]] = %[[CONSTANT_10]] to %[[CONSTANT_11]] step %[[CONSTANT_12]] { +! CHECK: %[[COORDINATE_OF_0:.*]] = fir.coordinate_of %[[DECLARE_0]]#0, %[[VAL_3]], %[[VAL_2]], %[[VAL_1]] : (!fir.ref<!fir.array<100x10x2xi32>>, index, index, index) -> !fir.ref<i32> +! CHECK: fir.store %[[CONSTANT_0]] to %[[COORDINATE_OF_0]] : !fir.ref<i32> +! CHECK: } +! CHECK: } +! CHECK: } +! CHECK: acc.yield %[[DECLARE_0]]#0 : !fir.ref<!fir.array<100x10x2xi32>> + +! CHECK-LABEL: } combiner { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<!fir.array<100x10x2xi32>>, %[[VAL_1:.*]]: !fir.ref<!fir.array<100x10x2xi32>>): +! CHECK: %[[CONSTANT_0:.*]] = arith.constant 100 : index +! CHECK: %[[CONSTANT_1:.*]] = arith.constant 10 : index +! CHECK: %[[CONSTANT_2:.*]] = arith.constant 2 : index +! CHECK: %[[SHAPE_0:.*]] = fir.shape %[[CONSTANT_0]], %[[CONSTANT_1]], %[[CONSTANT_2]] : (index, index, index) -> !fir.shape<3> +! CHECK: %[[CONSTANT_3:.*]] = arith.constant 100 : index +! CHECK: %[[CONSTANT_4:.*]] = arith.constant 10 : index +! CHECK: %[[CONSTANT_5:.*]] = arith.constant 2 : index +! CHECK: %[[SHAPE_1:.*]] = fir.shape %[[CONSTANT_3]], %[[CONSTANT_4]], %[[CONSTANT_5]] : (index, index, index) -> !fir.shape<3> +! CHECK: %[[CONSTANT_6:.*]] = arith.constant 1 : index +! CHECK: fir.do_loop %[[VAL_2:.*]] = %[[CONSTANT_6]] to %[[CONSTANT_2]] step %[[CONSTANT_6]] unordered { +! CHECK: fir.do_loop %[[VAL_3:.*]] = %[[CONSTANT_6]] to %[[CONSTANT_1]] step %[[CONSTANT_6]] unordered { +! CHECK: fir.do_loop %[[VAL_4:.*]] = %[[CONSTANT_6]] to %[[CONSTANT_0]] step %[[CONSTANT_6]] unordered { +! CHECK: %[[DESIGNATE_0:.*]] = hlfir.designate %[[VAL_1]] (%[[VAL_4]], %[[VAL_3]], %[[VAL_2]]) : (!fir.ref<!fir.array<100x10x2xi32>>, index, index, index) -> !fir.ref<i32> +! CHECK: %[[LOAD_0:.*]] = fir.load %[[DESIGNATE_0]] : !fir.ref<i32> +! CHECK: %[[DESIGNATE_1:.*]] = hlfir.designate %[[VAL_0]] (%[[VAL_4]], %[[VAL_3]], %[[VAL_2]]) : (!fir.ref<!fir.array<100x10x2xi32>>, index, index, index) -> !fir.ref<i32> +! CHECK: %[[LOAD_1:.*]] = fir.load %[[DESIGNATE_1]] : !fir.ref<i32> +! CHECK: %[[ADDI_0:.*]] = arith.addi %[[LOAD_1]], %[[LOAD_0]] : i32 +! CHECK: hlfir.assign %[[ADDI_0]] to %[[DESIGNATE_1]] : i32, !fir.ref<i32> +! CHECK: } +! CHECK: } +! CHECK: } +! CHECK: acc.yield %[[VAL_0]] : !fir.ref<!fir.array<100x10x2xi32>> +! CHECK: } + +! CHECK-LABEL: acc.reduction.recipe @reduction_add_ref_100x10xi32 : !fir.ref<!fir.array<100x10xi32>> reduction_operator <add> init { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<!fir.array<100x10xi32>>): +! CHECK: %[[CONSTANT_0:.*]] = arith.constant 0 : i32 +! CHECK: %[[CONSTANT_1:.*]] = arith.constant 100 : index +! CHECK: %[[CONSTANT_2:.*]] = arith.constant 10 : index +! CHECK: %[[SHAPE_0:.*]] = fir.shape %[[CONSTANT_1]], %[[CONSTANT_2]] : (index, index) -> !fir.shape<2> +! CHECK: %[[ALLOCA_0:.*]] = fir.alloca !fir.array<100x10xi32> +! CHECK: %[[DECLARE_0:.*]]:2 = hlfir.declare %[[ALLOCA_0]](%[[SHAPE_0]]) {uniq_name = "acc.reduction.init"} : (!fir.ref<!fir.array<100x10xi32>>, !fir.shape<2>) -> (!fir.ref<!fir.array<100x10xi32>>, !fir.ref<!fir.array<100x10xi32>>) +! CHECK: %[[CONSTANT_3:.*]] = arith.constant 0 : index +! CHECK: %[[CONSTANT_4:.*]] = arith.constant 9 : index +! CHECK: %[[CONSTANT_5:.*]] = arith.constant 1 : index +! CHECK: fir.do_loop %[[VAL_1:.*]] = %[[CONSTANT_3]] to %[[CONSTANT_4]] step %[[CONSTANT_5]] { +! CHECK: %[[CONSTANT_6:.*]] = arith.constant 0 : index +! CHECK: %[[CONSTANT_7:.*]] = arith.constant 99 : index +! CHECK: %[[CONSTANT_8:.*]] = arith.constant 1 : index +! CHECK: fir.do_loop %[[VAL_2:.*]] = %[[CONSTANT_6]] to %[[CONSTANT_7]] step %[[CONSTANT_8]] { +! CHECK: %[[COORDINATE_OF_0:.*]] = fir.coordinate_of %[[DECLARE_0]]#0, %[[VAL_2]], %[[VAL_1]] : (!fir.ref<!fir.array<100x10xi32>>, index, index) -> !fir.ref<i32> +! CHECK: fir.store %[[CONSTANT_0]] to %[[COORDINATE_OF_0]] : !fir.ref<i32> +! CHECK: } +! CHECK: } +! CHECK: acc.yield %[[DECLARE_0]]#0 : !fir.ref<!fir.array<100x10xi32>> + +! CHECK-LABEL: } combiner { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<!fir.array<100x10xi32>>, %[[VAL_1:.*]]: !fir.ref<!fir.array<100x10xi32>>): +! CHECK: %[[CONSTANT_0:.*]] = arith.constant 100 : index +! CHECK: %[[CONSTANT_1:.*]] = arith.constant 10 : index +! CHECK: %[[SHAPE_0:.*]] = fir.shape %[[CONSTANT_0]], %[[CONSTANT_1]] : (index, index) -> !fir.shape<2> +! CHECK: %[[CONSTANT_2:.*]] = arith.constant 100 : index +! CHECK: %[[CONSTANT_3:.*]] = arith.constant 10 : index +! CHECK: %[[SHAPE_1:.*]] = fir.shape %[[CONSTANT_2]], %[[CONSTANT_3]] : (index, index) -> !fir.shape<2> +! CHECK: %[[CONSTANT_4:.*]] = arith.constant 1 : index +! CHECK: fir.do_loop %[[VAL_2:.*]] = %[[CONSTANT_4]] to %[[CONSTANT_1]] step %[[CONSTANT_4]] unordered { +! CHECK: fir.do_loop %[[VAL_3:.*]] = %[[CONSTANT_4]] to %[[CONSTANT_0]] step %[[CONSTANT_4]] unordered { +! CHECK: %[[DESIGNATE_0:.*]] = hlfir.designate %[[VAL_1]] (%[[VAL_3]], %[[VAL_2]]) : (!fir.ref<!fir.array<100x10xi32>>, index, index) -> !fir.ref<i32> +! CHECK: %[[LOAD_0:.*]] = fir.load %[[DESIGNATE_0]] : !fir.ref<i32> +! CHECK: %[[DESIGNATE_1:.*]] = hlfir.designate %[[VAL_0]] (%[[VAL_3]], %[[VAL_2]]) : (!fir.ref<!fir.array<100x10xi32>>, index, index) -> !fir.ref<i32> +! CHECK: %[[LOAD_1:.*]] = fir.load %[[DESIGNATE_1]] : !fir.ref<i32> +! CHECK: %[[ADDI_0:.*]] = arith.addi %[[LOAD_1]], %[[LOAD_0]] : i32 +! CHECK: hlfir.assign %[[ADDI_0]] to %[[DESIGNATE_1]] : i32, !fir.ref<i32> +! CHECK: } +! CHECK: } +! CHECK: acc.yield %[[VAL_0]] : !fir.ref<!fir.array<100x10xi32>> +! CHECK: } + +! CHECK-LABEL: acc.reduction.recipe @reduction_add_ref_100xi32 : !fir.ref<!fir.array<100xi32>> reduction_operator <add> init { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<!fir.array<100xi32>>): +! CHECK: %[[CONSTANT_0:.*]] = arith.constant 0 : i32 +! CHECK: %[[CONSTANT_1:.*]] = arith.constant 100 : index +! CHECK: %[[SHAPE_0:.*]] = fir.shape %[[CONSTANT_1]] : (index) -> !fir.shape<1> +! CHECK: %[[ALLOCA_0:.*]] = fir.alloca !fir.array<100xi32> +! CHECK: %[[DECLARE_0:.*]]:2 = hlfir.declare %[[ALLOCA_0]](%[[SHAPE_0]]) {uniq_name = "acc.reduction.init"} : (!fir.ref<!fir.array<100xi32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<100xi32>>, !fir.ref<!fir.array<100xi32>>) +! CHECK: %[[CONSTANT_2:.*]] = arith.constant 0 : index +! CHECK: %[[CONSTANT_3:.*]] = arith.constant 99 : index +! CHECK: %[[CONSTANT_4:.*]] = arith.constant 1 : index +! CHECK: fir.do_loop %[[VAL_1:.*]] = %[[CONSTANT_2]] to %[[CONSTANT_3]] step %[[CONSTANT_4]] { +! CHECK: %[[COORDINATE_OF_0:.*]] = fir.coordinate_of %[[DECLARE_0]]#0, %[[VAL_1]] : (!fir.ref<!fir.array<100xi32>>, index) -> !fir.ref<i32> +! CHECK: fir.store %[[CONSTANT_0]] to %[[COORDINATE_OF_0]] : !fir.ref<i32> +! CHECK: } +! CHECK: acc.yield %[[DECLARE_0]]#0 : !fir.ref<!fir.array<100xi32>> + +! CHECK-LABEL: } combiner { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<!fir.array<100xi32>>, %[[VAL_1:.*]]: !fir.ref<!fir.array<100xi32>>): +! CHECK: %[[CONSTANT_0:.*]] = arith.constant 100 : index +! CHECK: %[[SHAPE_0:.*]] = fir.shape %[[CONSTANT_0]] : (index) -> !fir.shape<1> +! CHECK: %[[CONSTANT_1:.*]] = arith.constant 100 : index +! CHECK: %[[SHAPE_1:.*]] = fir.shape %[[CONSTANT_1]] : (index) -> !fir.shape<1> +! CHECK: %[[CONSTANT_2:.*]] = arith.constant 1 : index +! CHECK: fir.do_loop %[[VAL_2:.*]] = %[[CONSTANT_2]] to %[[CONSTANT_0]] step %[[CONSTANT_2]] unordered { +! CHECK: %[[DESIGNATE_0:.*]] = hlfir.designate %[[VAL_1]] (%[[VAL_2]]) : (!fir.ref<!fir.array<100xi32>>, index) -> !fir.ref<i32> +! CHECK: %[[LOAD_0:.*]] = fir.load %[[DESIGNATE_0]] : !fir.ref<i32> +! CHECK: %[[DESIGNATE_1:.*]] = hlfir.designate %[[VAL_0]] (%[[VAL_2]]) : (!fir.ref<!fir.array<100xi32>>, index) -> !fir.ref<i32> +! CHECK: %[[LOAD_1:.*]] = fir.load %[[DESIGNATE_1]] : !fir.ref<i32> +! CHECK: %[[ADDI_0:.*]] = arith.addi %[[LOAD_1]], %[[LOAD_0]] : i32 +! CHECK: hlfir.assign %[[ADDI_0]] to %[[DESIGNATE_1]] : i32, !fir.ref<i32> +! CHECK: } +! CHECK: acc.yield %[[VAL_0]] : !fir.ref<!fir.array<100xi32>> +! CHECK: } + +! CHECK-LABEL: acc.private.recipe @privatization_ref_i32 : !fir.ref<i32> init { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<i32>): +! CHECK: %[[ALLOCA_0:.*]] = fir.alloca i32 +! CHECK: %[[DECLARE_0:.*]]:2 = hlfir.declare %[[ALLOCA_0]] {uniq_name = "acc.private.init"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: acc.yield %[[DECLARE_0]]#0 : !fir.ref<i32> +! CHECK: } + +! CHECK-LABEL: acc.reduction.recipe @reduction_add_ref_i32 : !fir.ref<i32> reduction_operator <add> init { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<i32>): +! CHECK: %[[CONSTANT_0:.*]] = arith.constant 0 : i32 +! CHECK: %[[ALLOCA_0:.*]] = fir.alloca i32 +! CHECK: %[[DECLARE_0:.*]]:2 = hlfir.declare %[[ALLOCA_0]] {uniq_name = "acc.reduction.init"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: fir.store %[[CONSTANT_0]] to %[[DECLARE_0]]#0 : !fir.ref<i32> +! CHECK: acc.yield %[[DECLARE_0]]#0 : !fir.ref<i32> + +! CHECK-LABEL: } combiner { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<i32>, %[[VAL_1:.*]]: !fir.ref<i32>): +! CHECK: %[[LOAD_0:.*]] = fir.load %[[VAL_1]] : !fir.ref<i32> +! CHECK: %[[LOAD_1:.*]] = fir.load %[[VAL_0]] : !fir.ref<i32> +! CHECK: %[[ADDI_0:.*]] = arith.addi %[[LOAD_1]], %[[LOAD_0]] : i32 +! CHECK: hlfir.assign %[[ADDI_0]] to %[[VAL_0]] : i32, !fir.ref<i32> +! CHECK: acc.yield %[[VAL_0]] : !fir.ref<i32> +! CHECK: } subroutine acc_reduction_add_int(a, b) integer :: a(100) @@ -767,8 +1222,8 @@ end subroutine ! CHECK-LABEL: func.func @_QPacc_reduction_add_int( ! CHECK-SAME: %{{.*}}: !fir.ref<!fir.array<100xi32>> {fir.bindc_name = "a"}, %[[B:.*]]: !fir.ref<i32> {fir.bindc_name = "b"}) ! CHECK: %[[DECLB:.*]]:2 = hlfir.declare %[[B]] -! CHECK: %[[RED_B:.*]] = acc.reduction varPtr(%[[DECLB]]#0 : !fir.ref<i32>) -> !fir.ref<i32> {name = "b"} -! CHECK: acc.loop {{.*}} reduction(@reduction_add_ref_i32 -> %[[RED_B]] : !fir.ref<i32>) +! CHECK: %[[RED_B:.*]] = acc.reduction varPtr(%[[DECLB]]#0 : !fir.ref<i32>) recipe(@reduction_add_ref_i32) -> !fir.ref<i32> {name = "b"} +! CHECK: acc.loop {{.*}} reduction(%[[RED_B]] : !fir.ref<i32>) subroutine acc_reduction_add_int_array_1d(a, b) integer :: a(100) @@ -783,8 +1238,8 @@ end subroutine ! CHECK-LABEL: func.func @_QPacc_reduction_add_int_array_1d( ! CHECK-SAME: %{{.*}}: !fir.ref<!fir.array<100xi32>> {fir.bindc_name = "a"}, %[[B:.*]]: !fir.ref<!fir.array<100xi32>> {fir.bindc_name = "b"}) ! CHECK: %[[DECLB:.*]]:2 = hlfir.declare %[[B]] -! CHECK: %[[RED_B:.*]] = acc.reduction varPtr(%[[DECLB]]#0 : !fir.ref<!fir.array<100xi32>>) -> !fir.ref<!fir.array<100xi32>> {name = "b"} -! CHECK: acc.loop {{.*}} reduction(@reduction_add_ref_100xi32 -> %[[RED_B]] : !fir.ref<!fir.array<100xi32>>) +! CHECK: %[[RED_B:.*]] = acc.reduction varPtr(%[[DECLB]]#0 : !fir.ref<!fir.array<100xi32>>) recipe(@reduction_add_ref_100xi32) -> !fir.ref<!fir.array<100xi32>> {name = "b"} +! CHECK: acc.loop {{.*}} reduction(%[[RED_B]] : !fir.ref<!fir.array<100xi32>>) subroutine acc_reduction_add_int_array_2d(a, b) integer :: a(100, 10), b(100, 10) @@ -801,8 +1256,8 @@ end subroutine ! CHECK-LABEL: func.func @_QPacc_reduction_add_int_array_2d( ! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.array<100x10xi32>> {fir.bindc_name = "a"}, %[[ARG1:.*]]: !fir.ref<!fir.array<100x10xi32>> {fir.bindc_name = "b"}) { ! CHECK: %[[DECLARG1:.*]]:2 = hlfir.declare %[[ARG1]] -! CHECK: %[[RED_ARG1:.*]] = acc.reduction varPtr(%[[DECLARG1]]#0 : !fir.ref<!fir.array<100x10xi32>>) -> !fir.ref<!fir.array<100x10xi32>> {name = "b"} -! CHECK: acc.loop {{.*}} reduction(@reduction_add_ref_100x10xi32 -> %[[RED_ARG1]] : !fir.ref<!fir.array<100x10xi32>>) +! CHECK: %[[RED_ARG1:.*]] = acc.reduction varPtr(%[[DECLARG1]]#0 : !fir.ref<!fir.array<100x10xi32>>) recipe(@reduction_add_ref_100x10xi32) -> !fir.ref<!fir.array<100x10xi32>> {name = "b"} +! CHECK: acc.loop {{.*}} reduction(%[[RED_ARG1]] : !fir.ref<!fir.array<100x10xi32>>) ! CHECK: } attributes {collapse = [2]{{.*}} subroutine acc_reduction_add_int_array_3d(a, b) @@ -822,8 +1277,8 @@ end subroutine ! CHECK-LABEL: func.func @_QPacc_reduction_add_int_array_3d( ! CHECK-SAME: %{{.*}}: !fir.ref<!fir.array<100x10x2xi32>> {fir.bindc_name = "a"}, %[[ARG1:.*]]: !fir.ref<!fir.array<100x10x2xi32>> {fir.bindc_name = "b"}) ! CHECK: %[[DECLARG1:.*]]:2 = hlfir.declare %[[ARG1]] -! CHECK: %[[RED_ARG1:.*]] = acc.reduction varPtr(%[[DECLARG1]]#0 : !fir.ref<!fir.array<100x10x2xi32>>) -> !fir.ref<!fir.array<100x10x2xi32>> {name = "b"} -! CHECK: acc.loop {{.*}} reduction(@reduction_add_ref_100x10x2xi32 -> %[[RED_ARG1]] : !fir.ref<!fir.array<100x10x2xi32>>) +! CHECK: %[[RED_ARG1:.*]] = acc.reduction varPtr(%[[DECLARG1]]#0 : !fir.ref<!fir.array<100x10x2xi32>>) recipe(@reduction_add_ref_100x10x2xi32) -> !fir.ref<!fir.array<100x10x2xi32>> {name = "b"} +! CHECK: acc.loop {{.*}} reduction(%[[RED_ARG1]] : !fir.ref<!fir.array<100x10x2xi32>>) ! CHECK: } attributes {collapse = [3]{{.*}} subroutine acc_reduction_add_float(a, b) @@ -839,8 +1294,8 @@ end subroutine ! CHECK-LABEL: func.func @_QPacc_reduction_add_float( ! CHECK-SAME: %{{.*}}: !fir.ref<!fir.array<100xf32>> {fir.bindc_name = "a"}, %[[B:.*]]: !fir.ref<f32> {fir.bindc_name = "b"}) ! CHECK: %[[DECLB:.*]]:2 = hlfir.declare %[[B]] -! CHECK: %[[RED_B:.*]] = acc.reduction varPtr(%[[DECLB]]#0 : !fir.ref<f32>) -> !fir.ref<f32> {name = "b"} -! CHECK: acc.loop {{.*}} reduction(@reduction_add_ref_f32 -> %[[RED_B]] : !fir.ref<f32>) +! CHECK: %[[RED_B:.*]] = acc.reduction varPtr(%[[DECLB]]#0 : !fir.ref<f32>) recipe(@reduction_add_ref_f32) -> !fir.ref<f32> {name = "b"} +! CHECK: acc.loop {{.*}} reduction(%[[RED_B]] : !fir.ref<f32>) subroutine acc_reduction_add_float_array_1d(a, b) real :: a(100), b(100) @@ -855,8 +1310,8 @@ end subroutine ! CHECK-LABEL: func.func @_QPacc_reduction_add_float_array_1d( ! CHECK-SAME: %{{.*}}: !fir.ref<!fir.array<100xf32>> {fir.bindc_name = "a"}, %[[B:.*]]: !fir.ref<!fir.array<100xf32>> {fir.bindc_name = "b"}) ! CHECK: %[[DECLB:.*]]:2 = hlfir.declare %[[B]] -! CHECK: %[[RED_B:.*]] = acc.reduction varPtr(%[[DECLB]]#0 : !fir.ref<!fir.array<100xf32>>) -> !fir.ref<!fir.array<100xf32>> {name = "b"} -! CHECK: acc.loop {{.*}} reduction(@reduction_add_ref_100xf32 -> %[[RED_B]] : !fir.ref<!fir.array<100xf32>>) +! CHECK: %[[RED_B:.*]] = acc.reduction varPtr(%[[DECLB]]#0 : !fir.ref<!fir.array<100xf32>>) recipe(@reduction_add_ref_100xf32) -> !fir.ref<!fir.array<100xf32>> {name = "b"} +! CHECK: acc.loop {{.*}} reduction(%[[RED_B]] : !fir.ref<!fir.array<100xf32>>) subroutine acc_reduction_mul_int(a, b) integer :: a(100) @@ -871,8 +1326,8 @@ end subroutine ! CHECK-LABEL: func.func @_QPacc_reduction_mul_int( ! CHECK-SAME: %{{.*}}: !fir.ref<!fir.array<100xi32>> {fir.bindc_name = "a"}, %[[B:.*]]: !fir.ref<i32> {fir.bindc_name = "b"}) ! CHECK: %[[DECLB:.*]]:2 = hlfir.declare %[[B]] -! CHECK: %[[RED_B:.*]] = acc.reduction varPtr(%[[DECLB]]#0 : !fir.ref<i32>) -> !fir.ref<i32> {name = "b"} -! CHECK: acc.loop {{.*}} reduction(@reduction_mul_ref_i32 -> %[[RED_B]] : !fir.ref<i32>) +! CHECK: %[[RED_B:.*]] = acc.reduction varPtr(%[[DECLB]]#0 : !fir.ref<i32>) recipe(@reduction_mul_ref_i32) -> !fir.ref<i32> {name = "b"} +! CHECK: acc.loop {{.*}} reduction(%[[RED_B]] : !fir.ref<i32>) subroutine acc_reduction_mul_int_array_1d(a, b) integer :: a(100) @@ -887,8 +1342,8 @@ end subroutine ! CHECK-LABEL: func.func @_QPacc_reduction_mul_int_array_1d( ! CHECK-SAME: %{{.*}}: !fir.ref<!fir.array<100xi32>> {fir.bindc_name = "a"}, %[[B:.*]]: !fir.ref<!fir.array<100xi32>> {fir.bindc_name = "b"}) ! CHECK: %[[DECLB:.*]]:2 = hlfir.declare %[[B]] -! CHECK: %[[RED_B:.*]] = acc.reduction varPtr(%[[DECLB]]#0 : !fir.ref<!fir.array<100xi32>>) -> !fir.ref<!fir.array<100xi32>> {name = "b"} -! CHECK: acc.loop {{.*}} reduction(@reduction_mul_ref_100xi32 -> %[[RED_B]] : !fir.ref<!fir.array<100xi32>>) +! CHECK: %[[RED_B:.*]] = acc.reduction varPtr(%[[DECLB]]#0 : !fir.ref<!fir.array<100xi32>>) recipe(@reduction_mul_ref_100xi32) -> !fir.ref<!fir.array<100xi32>> {name = "b"} +! CHECK: acc.loop {{.*}} reduction(%[[RED_B]] : !fir.ref<!fir.array<100xi32>>) subroutine acc_reduction_mul_float(a, b) real :: a(100), b @@ -903,8 +1358,8 @@ end subroutine ! CHECK-LABEL: func.func @_QPacc_reduction_mul_float( ! CHECK-SAME: %{{.*}}: !fir.ref<!fir.array<100xf32>> {fir.bindc_name = "a"}, %[[B:.*]]: !fir.ref<f32> {fir.bindc_name = "b"}) ! CHECK: %[[DECLB:.*]]:2 = hlfir.declare %[[B]] -! CHECK: %[[RED_B:.*]] = acc.reduction varPtr(%[[DECLB]]#0 : !fir.ref<f32>) -> !fir.ref<f32> {name = "b"} -! CHECK: acc.loop {{.*}} reduction(@reduction_mul_ref_f32 -> %[[RED_B]] : !fir.ref<f32>) +! CHECK: %[[RED_B:.*]] = acc.reduction varPtr(%[[DECLB]]#0 : !fir.ref<f32>) recipe(@reduction_mul_ref_f32) -> !fir.ref<f32> {name = "b"} +! CHECK: acc.loop {{.*}} reduction(%[[RED_B]] : !fir.ref<f32>) subroutine acc_reduction_mul_float_array_1d(a, b) real :: a(100), b(100) @@ -919,8 +1374,8 @@ end subroutine ! CHECK-LABEL: func.func @_QPacc_reduction_mul_float_array_1d( ! CHECK-SAME: %{{.*}}: !fir.ref<!fir.array<100xf32>> {fir.bindc_name = "a"}, %[[B:.*]]: !fir.ref<!fir.array<100xf32>> {fir.bindc_name = "b"}) ! CHECK: %[[DECLB:.*]]:2 = hlfir.declare %[[B]] -! CHECK: %[[RED_B:.*]] = acc.reduction varPtr(%[[DECLB]]#0 : !fir.ref<!fir.array<100xf32>>) -> !fir.ref<!fir.array<100xf32>> {name = "b"} -! CHECK: acc.loop {{.*}} reduction(@reduction_mul_ref_100xf32 -> %[[RED_B]] : !fir.ref<!fir.array<100xf32>>) +! CHECK: %[[RED_B:.*]] = acc.reduction varPtr(%[[DECLB]]#0 : !fir.ref<!fir.array<100xf32>>) recipe(@reduction_mul_ref_100xf32) -> !fir.ref<!fir.array<100xf32>> {name = "b"} +! CHECK: acc.loop {{.*}} reduction(%[[RED_B]] : !fir.ref<!fir.array<100xf32>>) subroutine acc_reduction_min_int(a, b) integer :: a(100) @@ -935,8 +1390,8 @@ end subroutine ! CHECK-LABEL: func.func @_QPacc_reduction_min_int( ! CHECK-SAME: %{{.*}}: !fir.ref<!fir.array<100xi32>> {fir.bindc_name = "a"}, %[[B:.*]]: !fir.ref<i32> {fir.bindc_name = "b"}) ! CHECK: %[[DECLB:.*]]:2 = hlfir.declare %[[B]] -! CHECK: %[[RED_B:.*]] = acc.reduction varPtr(%[[DECLB]]#0 : !fir.ref<i32>) -> !fir.ref<i32> {name = "b"} -! CHECK: acc.loop {{.*}} reduction(@reduction_min_ref_i32 -> %[[RED_B]] : !fir.ref<i32>) +! CHECK: %[[RED_B:.*]] = acc.reduction varPtr(%[[DECLB]]#0 : !fir.ref<i32>) recipe(@reduction_min_ref_i32) -> !fir.ref<i32> {name = "b"} +! CHECK: acc.loop {{.*}} reduction(%[[RED_B]] : !fir.ref<i32>) subroutine acc_reduction_min_int_array_1d(a, b) integer :: a(100), b(100) @@ -951,8 +1406,8 @@ end subroutine ! CHECK-LABEL: func.func @_QPacc_reduction_min_int_array_1d( ! CHECK-SAME: %{{.*}}: !fir.ref<!fir.array<100xi32>> {fir.bindc_name = "a"}, %[[ARG1:.*]]: !fir.ref<!fir.array<100xi32>> {fir.bindc_name = "b"}) ! CHECK: %[[DECLARG1:.*]]:2 = hlfir.declare %[[ARG1]] -! CHECK: %[[RED_ARG1:.*]] = acc.reduction varPtr(%[[DECLARG1]]#0 : !fir.ref<!fir.array<100xi32>>) -> !fir.ref<!fir.array<100xi32>> {name = "b"} -! CHECK: acc.loop {{.*}} reduction(@reduction_min_ref_100xi32 -> %[[RED_ARG1]] : !fir.ref<!fir.array<100xi32>>) +! CHECK: %[[RED_ARG1:.*]] = acc.reduction varPtr(%[[DECLARG1]]#0 : !fir.ref<!fir.array<100xi32>>) recipe(@reduction_min_ref_100xi32) -> !fir.ref<!fir.array<100xi32>> {name = "b"} +! CHECK: acc.loop {{.*}} reduction(%[[RED_ARG1]] : !fir.ref<!fir.array<100xi32>>) subroutine acc_reduction_min_float(a, b) real :: a(100), b @@ -967,8 +1422,8 @@ end subroutine ! CHECK-LABEL: func.func @_QPacc_reduction_min_float( ! CHECK-SAME: %{{.*}}: !fir.ref<!fir.array<100xf32>> {fir.bindc_name = "a"}, %[[B:.*]]: !fir.ref<f32> {fir.bindc_name = "b"}) ! CHECK: %[[DECLB:.*]]:2 = hlfir.declare %[[B]] -! CHECK: %[[RED_B:.*]] = acc.reduction varPtr(%[[DECLB]]#0 : !fir.ref<f32>) -> !fir.ref<f32> {name = "b"} -! CHECK: acc.loop {{.*}} reduction(@reduction_min_ref_f32 -> %[[RED_B]] : !fir.ref<f32>) +! CHECK: %[[RED_B:.*]] = acc.reduction varPtr(%[[DECLB]]#0 : !fir.ref<f32>) recipe(@reduction_min_ref_f32) -> !fir.ref<f32> {name = "b"} +! CHECK: acc.loop {{.*}} reduction(%[[RED_B]] : !fir.ref<f32>) subroutine acc_reduction_min_float_array2d(a, b) real :: a(100, 10), b(100, 10) @@ -985,8 +1440,8 @@ end subroutine ! CHECK-LABEL: func.func @_QPacc_reduction_min_float_array2d( ! CHECK-SAME: %{{.*}}: !fir.ref<!fir.array<100x10xf32>> {fir.bindc_name = "a"}, %[[ARG1:.*]]: !fir.ref<!fir.array<100x10xf32>> {fir.bindc_name = "b"}) ! CHECK: %[[DECLARG1:.*]]:2 = hlfir.declare %[[ARG1]] -! CHECK: %[[RED_ARG1:.*]] = acc.reduction varPtr(%[[DECLARG1]]#0 : !fir.ref<!fir.array<100x10xf32>>) -> !fir.ref<!fir.array<100x10xf32>> {name = "b"} -! CHECK: acc.loop {{.*}} reduction(@reduction_min_ref_100x10xf32 -> %[[RED_ARG1]] : !fir.ref<!fir.array<100x10xf32>>) +! CHECK: %[[RED_ARG1:.*]] = acc.reduction varPtr(%[[DECLARG1]]#0 : !fir.ref<!fir.array<100x10xf32>>) recipe(@reduction_min_ref_100x10xf32) -> !fir.ref<!fir.array<100x10xf32>> {name = "b"} +! CHECK: acc.loop {{.*}} reduction(%[[RED_ARG1]] : !fir.ref<!fir.array<100x10xf32>>) ! CHECK: attributes {collapse = [2]{{.*}} subroutine acc_reduction_max_int(a, b) @@ -1002,8 +1457,8 @@ end subroutine ! CHECK-LABEL: func.func @_QPacc_reduction_max_int( ! CHECK-SAME: %{{.*}}: !fir.ref<!fir.array<100xi32>> {fir.bindc_name = "a"}, %[[B:.*]]: !fir.ref<i32> {fir.bindc_name = "b"}) ! CHECK: %[[DECLB:.*]]:2 = hlfir.declare %[[B]] -! CHECK: %[[RED_B:.*]] = acc.reduction varPtr(%[[DECLB]]#0 : !fir.ref<i32>) -> !fir.ref<i32> {name = "b"} -! CHECK: acc.loop {{.*}} reduction(@reduction_max_ref_i32 -> %[[RED_B]] : !fir.ref<i32>) +! CHECK: %[[RED_B:.*]] = acc.reduction varPtr(%[[DECLB]]#0 : !fir.ref<i32>) recipe(@reduction_max_ref_i32) -> !fir.ref<i32> {name = "b"} +! CHECK: acc.loop {{.*}} reduction(%[[RED_B]] : !fir.ref<i32>) subroutine acc_reduction_max_int_array2d(a, b) integer :: a(100, 10), b(100, 10) @@ -1020,8 +1475,8 @@ end subroutine ! CHECK-LABEL: func.func @_QPacc_reduction_max_int_array2d( ! CHECK-SAME: %{{.*}}: !fir.ref<!fir.array<100x10xi32>> {fir.bindc_name = "a"}, %[[ARG1:.*]]: !fir.ref<!fir.array<100x10xi32>> {fir.bindc_name = "b"}) ! CHECK: %[[DECLARG1:.*]]:2 = hlfir.declare %[[ARG1]] -! CHECK: %[[RED_ARG1:.*]] = acc.reduction varPtr(%[[DECLARG1]]#0 : !fir.ref<!fir.array<100x10xi32>>) -> !fir.ref<!fir.array<100x10xi32>> {name = "b"} -! CHECK: acc.loop {{.*}} reduction(@reduction_max_ref_100x10xi32 -> %[[RED_ARG1]] : !fir.ref<!fir.array<100x10xi32>>) +! CHECK: %[[RED_ARG1:.*]] = acc.reduction varPtr(%[[DECLARG1]]#0 : !fir.ref<!fir.array<100x10xi32>>) recipe(@reduction_max_ref_100x10xi32) -> !fir.ref<!fir.array<100x10xi32>> {name = "b"} +! CHECK: acc.loop {{.*}} reduction(%[[RED_ARG1]] : !fir.ref<!fir.array<100x10xi32>>) subroutine acc_reduction_max_float(a, b) real :: a(100), b @@ -1036,8 +1491,8 @@ end subroutine ! CHECK-LABEL: func.func @_QPacc_reduction_max_float( ! CHECK-SAME: %{{.*}}: !fir.ref<!fir.array<100xf32>> {fir.bindc_name = "a"}, %[[B:.*]]: !fir.ref<f32> {fir.bindc_name = "b"}) ! CHECK: %[[DECLB:.*]]:2 = hlfir.declare %[[B]] -! CHECK: %[[RED_B:.*]] = acc.reduction varPtr(%[[DECLB]]#0 : !fir.ref<f32>) -> !fir.ref<f32> {name = "b"} -! CHECK: acc.loop {{.*}} reduction(@reduction_max_ref_f32 -> %[[RED_B]] : !fir.ref<f32>) +! CHECK: %[[RED_B:.*]] = acc.reduction varPtr(%[[DECLB]]#0 : !fir.ref<f32>) recipe(@reduction_max_ref_f32) -> !fir.ref<f32> {name = "b"} +! CHECK: acc.loop {{.*}} reduction(%[[RED_B]] : !fir.ref<f32>) subroutine acc_reduction_max_float_array1d(a, b) real :: a(100), b(100) @@ -1052,8 +1507,8 @@ end subroutine ! CHECK-LABEL: func.func @_QPacc_reduction_max_float_array1d( ! CHECK-SAME: %{{.*}}: !fir.ref<!fir.array<100xf32>> {fir.bindc_name = "a"}, %[[ARG1:.*]]: !fir.ref<!fir.array<100xf32>> {fir.bindc_name = "b"}) ! CHECK: %[[DECLARG1:.*]]:2 = hlfir.declare %[[ARG1]] -! CHECK: %[[RED_ARG1:.*]] = acc.reduction varPtr(%[[DECLARG1]]#0 : !fir.ref<!fir.array<100xf32>>) -> !fir.ref<!fir.array<100xf32>> {name = "b"} -! CHECK: acc.loop {{.*}} reduction(@reduction_max_ref_100xf32 -> %[[RED_ARG1]] : !fir.ref<!fir.array<100xf32>>) +! CHECK: %[[RED_ARG1:.*]] = acc.reduction varPtr(%[[DECLARG1]]#0 : !fir.ref<!fir.array<100xf32>>) recipe(@reduction_max_ref_100xf32) -> !fir.ref<!fir.array<100xf32>> {name = "b"} +! CHECK: acc.loop {{.*}} reduction(%[[RED_ARG1]] : !fir.ref<!fir.array<100xf32>>) subroutine acc_reduction_iand() integer :: i @@ -1062,8 +1517,8 @@ subroutine acc_reduction_iand() end subroutine ! CHECK-LABEL: func.func @_QPacc_reduction_iand() -! CHECK: %[[RED:.*]] = acc.reduction varPtr(%{{.*}} : !fir.ref<i32>) -> !fir.ref<i32> {name = "i"} -! CHECK: acc.parallel reduction(@reduction_iand_ref_i32 -> %[[RED]] : !fir.ref<i32>) +! CHECK: %[[RED:.*]] = acc.reduction varPtr(%{{.*}} : !fir.ref<i32>) recipe(@reduction_iand_ref_i32) -> !fir.ref<i32> {name = "i"} +! CHECK: acc.parallel reduction(%[[RED]] : !fir.ref<i32>) subroutine acc_reduction_ior() integer :: i @@ -1072,8 +1527,8 @@ subroutine acc_reduction_ior() end subroutine ! CHECK-LABEL: func.func @_QPacc_reduction_ior() -! CHECK: %[[RED:.*]] = acc.reduction varPtr(%{{.*}} : !fir.ref<i32>) -> !fir.ref<i32> {name = "i"} -! CHECK: acc.parallel reduction(@reduction_ior_ref_i32 -> %[[RED]] : !fir.ref<i32>) +! CHECK: %[[RED:.*]] = acc.reduction varPtr(%{{.*}} : !fir.ref<i32>) recipe(@reduction_ior_ref_i32) -> !fir.ref<i32> {name = "i"} +! CHECK: acc.parallel reduction(%[[RED]] : !fir.ref<i32>) subroutine acc_reduction_ieor() integer :: i @@ -1082,8 +1537,8 @@ subroutine acc_reduction_ieor() end subroutine ! CHECK-LABEL: func.func @_QPacc_reduction_ieor() -! CHECK: %[[RED:.*]] = acc.reduction varPtr(%{{.*}} : !fir.ref<i32>) -> !fir.ref<i32> {name = "i"} -! CHECK: acc.parallel reduction(@reduction_xor_ref_i32 -> %[[RED]] : !fir.ref<i32>) +! CHECK: %[[RED:.*]] = acc.reduction varPtr(%{{.*}} : !fir.ref<i32>) recipe(@reduction_xor_ref_i32) -> !fir.ref<i32> {name = "i"} +! CHECK: acc.parallel reduction(%[[RED]] : !fir.ref<i32>) subroutine acc_reduction_and() logical :: l @@ -1094,8 +1549,8 @@ end subroutine ! CHECK-LABEL: func.func @_QPacc_reduction_and() ! CHECK: %[[L:.*]] = fir.alloca !fir.logical<4> {bindc_name = "l", uniq_name = "_QFacc_reduction_andEl"} ! CHECK: %[[DECLL:.*]]:2 = hlfir.declare %[[L]] -! CHECK: %[[RED:.*]] = acc.reduction varPtr(%[[DECLL]]#0 : !fir.ref<!fir.logical<4>>) -> !fir.ref<!fir.logical<4>> {name = "l"} -! CHECK: acc.parallel reduction(@reduction_land_ref_l32 -> %[[RED]] : !fir.ref<!fir.logical<4>>) +! CHECK: %[[RED:.*]] = acc.reduction varPtr(%[[DECLL]]#0 : !fir.ref<!fir.logical<4>>) recipe(@reduction_land_ref_l32) -> !fir.ref<!fir.logical<4>> {name = "l"} +! CHECK: acc.parallel reduction(%[[RED]] : !fir.ref<!fir.logical<4>>) subroutine acc_reduction_or() logical :: l @@ -1104,8 +1559,8 @@ subroutine acc_reduction_or() end subroutine ! CHECK-LABEL: func.func @_QPacc_reduction_or() -! CHECK: %[[RED:.*]] = acc.reduction varPtr(%{{.*}} : !fir.ref<!fir.logical<4>>) -> !fir.ref<!fir.logical<4>> {name = "l"} -! CHECK: acc.parallel reduction(@reduction_lor_ref_l32 -> %[[RED]] : !fir.ref<!fir.logical<4>>) +! CHECK: %[[RED:.*]] = acc.reduction varPtr(%{{.*}} : !fir.ref<!fir.logical<4>>) recipe(@reduction_lor_ref_l32) -> !fir.ref<!fir.logical<4>> {name = "l"} +! CHECK: acc.parallel reduction(%[[RED]] : !fir.ref<!fir.logical<4>>) subroutine acc_reduction_eqv() logical :: l @@ -1114,8 +1569,8 @@ subroutine acc_reduction_eqv() end subroutine ! CHECK-LABEL: func.func @_QPacc_reduction_eqv() -! CHECK: %[[RED:.*]] = acc.reduction varPtr(%{{.*}} : !fir.ref<!fir.logical<4>>) -> !fir.ref<!fir.logical<4>> {name = "l"} -! CHECK: acc.parallel reduction(@reduction_eqv_ref_l32 -> %[[RED]] : !fir.ref<!fir.logical<4>>) +! CHECK: %[[RED:.*]] = acc.reduction varPtr(%{{.*}} : !fir.ref<!fir.logical<4>>) recipe(@reduction_eqv_ref_l32) -> !fir.ref<!fir.logical<4>> {name = "l"} +! CHECK: acc.parallel reduction(%[[RED]] : !fir.ref<!fir.logical<4>>) subroutine acc_reduction_neqv() logical :: l @@ -1124,8 +1579,8 @@ subroutine acc_reduction_neqv() end subroutine ! CHECK-LABEL: func.func @_QPacc_reduction_neqv() -! CHECK: %[[RED:.*]] = acc.reduction varPtr(%{{.*}} : !fir.ref<!fir.logical<4>>) -> !fir.ref<!fir.logical<4>> {name = "l"} -! CHECK: acc.parallel reduction(@reduction_neqv_ref_l32 -> %[[RED]] : !fir.ref<!fir.logical<4>>) +! CHECK: %[[RED:.*]] = acc.reduction varPtr(%{{.*}} : !fir.ref<!fir.logical<4>>) recipe(@reduction_neqv_ref_l32) -> !fir.ref<!fir.logical<4>> {name = "l"} +! CHECK: acc.parallel reduction(%[[RED]] : !fir.ref<!fir.logical<4>>) subroutine acc_reduction_add_cmplx() complex :: c @@ -1134,8 +1589,8 @@ subroutine acc_reduction_add_cmplx() end subroutine ! CHECK-LABEL: func.func @_QPacc_reduction_add_cmplx() -! CHECK: %[[RED:.*]] = acc.reduction varPtr(%{{.*}} : !fir.ref<complex<f32>>) -> !fir.ref<complex<f32>> {name = "c"} -! CHECK: acc.parallel reduction(@reduction_add_ref_z32 -> %[[RED]] : !fir.ref<complex<f32>>) +! CHECK: %[[RED:.*]] = acc.reduction varPtr(%{{.*}} : !fir.ref<complex<f32>>) recipe(@reduction_add_ref_z32) -> !fir.ref<complex<f32>> {name = "c"} +! CHECK: acc.parallel reduction(%[[RED]] : !fir.ref<complex<f32>>) subroutine acc_reduction_mul_cmplx() complex :: c @@ -1144,8 +1599,8 @@ subroutine acc_reduction_mul_cmplx() end subroutine ! CHECK-LABEL: func.func @_QPacc_reduction_mul_cmplx() -! CHECK: %[[RED:.*]] = acc.reduction varPtr(%{{.*}} : !fir.ref<complex<f32>>) -> !fir.ref<complex<f32>> {name = "c"} -! CHECK: acc.parallel reduction(@reduction_mul_ref_z32 -> %[[RED]] : !fir.ref<complex<f32>>) +! CHECK: %[[RED:.*]] = acc.reduction varPtr(%{{.*}} : !fir.ref<complex<f32>>) recipe(@reduction_mul_ref_z32) -> !fir.ref<complex<f32>> {name = "c"} +! CHECK: acc.parallel reduction(%[[RED]] : !fir.ref<complex<f32>>) subroutine acc_reduction_add_alloc() integer, allocatable :: i @@ -1157,8 +1612,8 @@ end subroutine ! CHECK-LABEL: func.func @_QPacc_reduction_add_alloc() ! CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.box<!fir.heap<i32>> {bindc_name = "i", uniq_name = "_QFacc_reduction_add_allocEi"} ! CHECK: %[[DECL:.*]]:2 = hlfir.declare %[[ALLOCA]] -! CHECK: %[[RED:.*]] = acc.reduction varPtr(%[[DECL]]#0 : !fir.ref<!fir.box<!fir.heap<i32>>>) -> !fir.ref<!fir.box<!fir.heap<i32>>> {name = "i"} -! CHECK: acc.parallel reduction(@reduction_add_ref_box_heap_i32 -> %[[RED]] : !fir.ref<!fir.box<!fir.heap<i32>>>) +! CHECK: %[[RED:.*]] = acc.reduction varPtr(%[[DECL]]#0 : !fir.ref<!fir.box<!fir.heap<i32>>>) recipe(@reduction_add_ref_box_heap_i32) -> !fir.ref<!fir.box<!fir.heap<i32>>> {name = "i"} +! CHECK: acc.parallel reduction(%[[RED]] : !fir.ref<!fir.box<!fir.heap<i32>>>) subroutine acc_reduction_add_pointer(i) integer, pointer :: i @@ -1169,8 +1624,8 @@ end subroutine ! CHECK-LABEL: func.func @_QPacc_reduction_add_pointer( ! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.box<!fir.ptr<i32>>> {fir.bindc_name = "i"}) ! CHECK: %[[DECLARG0:.*]]:2 = hlfir.declare %[[ARG0]] -! CHECK: %[[RED:.*]] = acc.reduction varPtr(%[[DECLARG0]]#0 : !fir.ref<!fir.box<!fir.ptr<i32>>>) -> !fir.ref<!fir.box<!fir.ptr<i32>>> {name = "i"} -! CHECK: acc.parallel reduction(@reduction_add_ref_box_ptr_i32 -> %[[RED]] : !fir.ref<!fir.box<!fir.ptr<i32>>>) +! CHECK: %[[RED:.*]] = acc.reduction varPtr(%[[DECLARG0]]#0 : !fir.ref<!fir.box<!fir.ptr<i32>>>) recipe(@reduction_add_ref_box_ptr_i32) -> !fir.ref<!fir.box<!fir.ptr<i32>>> {name = "i"} +! CHECK: acc.parallel reduction(%[[RED]] : !fir.ref<!fir.box<!fir.ptr<i32>>>) subroutine acc_reduction_add_static_slice(a) integer :: a(100) @@ -1186,8 +1641,8 @@ end subroutine ! CHECK: %[[LB:.*]] = arith.constant 10 : index ! CHECK: %[[UB:.*]] = arith.constant 19 : index ! CHECK: %[[BOUND:.*]] = acc.bounds lowerbound(%[[LB]] : index) upperbound(%[[UB]] : index) extent(%[[C100]] : index) stride(%[[C1]] : index) startIdx(%[[C1]] : index) -! CHECK: %[[RED:.*]] = acc.reduction varPtr(%[[DECLARG0]]#0 : !fir.ref<!fir.array<100xi32>>) bounds(%[[BOUND]]) -> !fir.ref<!fir.array<100xi32>> {name = "a(11:20)"} -! CHECK: acc.parallel reduction(@reduction_add_section_lb10.ub19_ref_100xi32 -> %[[RED]] : !fir.ref<!fir.array<100xi32>>) +! CHECK: %[[RED:.*]] = acc.reduction varPtr(%[[DECLARG0]]#0 : !fir.ref<!fir.array<100xi32>>) bounds(%[[BOUND]]) recipe(@reduction_add_section_lb10.ub19_ref_100xi32) -> !fir.ref<!fir.array<100xi32>> {name = "a(11:20)"} +! CHECK: acc.parallel reduction(%[[RED]] : !fir.ref<!fir.array<100xi32>>) subroutine acc_reduction_add_static_slice_2d(a) integer :: a(10,20) @@ -1208,9 +1663,9 @@ end subroutine ! CHECK: %[[UB19:.*]] = arith.constant 19 : index ! CHECK: %[[BOUND1:.*]] = acc.bounds lowerbound(%[[LB]] : index) upperbound(%[[UB19]] : index) extent(%[[C20]] : index) ! stride(%[[STRIDE1]] : index) startIdx(%[[C1]] : index) -! CHECK: %[[RED:.*]] = acc.reduction varPtr(%[[DECLARG0]]#0 : !fir.ref<!fir.array<10x20xi32>>) bounds(%[[BOUND0]], %[[BOUND1]]) -> +! CHECK: %[[RED:.*]] = acc.reduction varPtr(%[[DECLARG0]]#0 : !fir.ref<!fir.array<10x20xi32>>) bounds(%[[BOUND0]], %[[BOUND1]]) recipe(@reduction_add_section_lb0.ub9xlb0.ub19_ref_10x20xi32) -> ! !fir.ref<!fir.array<10x20xi32>> {name = "a(:10,:20)"} -! CHECK: acc.parallel reduction(@reduction_add_section_lb0.ub9xlb0.ub19_ref_10x20xi32 -> %[[RED]] : !fir.ref<!fir.array<10x20xi32>>) +! CHECK: acc.parallel reduction(%[[RED]] : !fir.ref<!fir.array<10x20xi32>>) subroutine acc_reduction_add_dynamic_extent_add(a) integer :: a(:) @@ -1221,8 +1676,8 @@ end subroutine ! CHECK-LABEL: func.func @_QPacc_reduction_add_dynamic_extent_add( ! CHECK-SAME: %[[ARG0:.*]]: !fir.box<!fir.array<?xi32>> {fir.bindc_name = "a"}) ! CHECK: %[[DECLARG0:.*]]:2 = hlfir.declare %[[ARG0]] -! CHECK: %[[RED:.*]] = acc.reduction var(%{{.*}} : !fir.box<!fir.array<?xi32>>) -> !fir.box<!fir.array<?xi32>> {name = "a"} -! CHECK: acc.parallel reduction(@reduction_add_box_Uxi32 -> %[[RED:.*]] : !fir.box<!fir.array<?xi32>>) +! CHECK: %[[RED:.*]] = acc.reduction var(%{{.*}} : !fir.box<!fir.array<?xi32>>) recipe(@reduction_add_box_Uxi32) -> !fir.box<!fir.array<?xi32>> {name = "a"} +! CHECK: acc.parallel reduction(%[[RED:.*]] : !fir.box<!fir.array<?xi32>>) subroutine acc_reduction_add_assumed_shape_max(a) real :: a(:) @@ -1233,8 +1688,8 @@ end subroutine ! CHECK-LABEL: func.func @_QPacc_reduction_add_assumed_shape_max( ! CHECK-SAME: %[[ARG0:.*]]: !fir.box<!fir.array<?xf32>> {fir.bindc_name = "a"}) ! CHECK: %[[DECLARG0:.*]]:2 = hlfir.declare %[[ARG0]] -! CHECK: %[[RED:.*]] = acc.reduction var(%{{.*}} : !fir.box<!fir.array<?xf32>>) -> !fir.box<!fir.array<?xf32>> {name = "a"} -! CHECK: acc.parallel reduction(@reduction_max_box_Uxf32 -> %[[RED]] : !fir.box<!fir.array<?xf32>>) { +! CHECK: %[[RED:.*]] = acc.reduction var(%{{.*}} : !fir.box<!fir.array<?xf32>>) recipe(@reduction_max_box_Uxf32) -> !fir.box<!fir.array<?xf32>> {name = "a"} +! CHECK: acc.parallel reduction(%[[RED]] : !fir.box<!fir.array<?xf32>>) { subroutine acc_reduction_add_dynamic_extent_add_with_section(a) integer :: a(:) @@ -1244,10 +1699,10 @@ end subroutine ! CHECK-LABEL: func.func @_QPacc_reduction_add_dynamic_extent_add_with_section( ! CHECK-SAME: %[[ARG0:.*]]: !fir.box<!fir.array<?xi32>> {fir.bindc_name = "a"}) -! CHECK: %[[DECL:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFacc_reduction_add_dynamic_extent_add_with_sectionEa"} : (!fir.box<!fir.array<?xi32>>, !fir.dscope) -> (!fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>>) +! CHECK: %[[DECL:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFacc_reduction_add_dynamic_extent_add_with_sectionEa"} : (!fir.box<!fir.array<?xi32>>, !fir.dscope) -> (!fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>>) ! CHECK: %[[BOUND:.*]] = acc.bounds lowerbound(%c1{{.*}} : index) upperbound(%c3{{.*}} : index) extent(%{{.*}}#1 : index) stride(%{{.*}}#2 : index) startIdx(%{{.*}} : index) {strideInBytes = true} -! CHECK: %[[RED:.*]] = acc.reduction var(%[[DECL]]#0 : !fir.box<!fir.array<?xi32>>) bounds(%[[BOUND]]) -> !fir.box<!fir.array<?xi32>> {name = "a(2:4)"} -! CHECK: acc.parallel reduction(@reduction_add_section_lb1.ub3_box_Uxi32 -> %[[RED]] : !fir.box<!fir.array<?xi32>>) +! CHECK: %[[RED:.*]] = acc.reduction var(%[[DECL]]#0 : !fir.box<!fir.array<?xi32>>) bounds(%[[BOUND]]) recipe(@reduction_add_section_lb1.ub3_box_Uxi32) -> !fir.box<!fir.array<?xi32>> {name = "a(2:4)"} +! CHECK: acc.parallel reduction(%[[RED]] : !fir.box<!fir.array<?xi32>>) subroutine acc_reduction_add_allocatable(a) real, allocatable :: a(:) @@ -1257,9 +1712,9 @@ end subroutine ! CHECK-LABEL: func.func @_QPacc_reduction_add_allocatable( ! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>> {fir.bindc_name = "a"}) -! CHECK: %[[DECL:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFacc_reduction_add_allocatableEa"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>) -! CHECK: %[[RED:.*]] = acc.reduction varPtr(%[[DECL]]#0 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>> {name = "a"} -! CHECK: acc.parallel reduction(@reduction_max_ref_box_heap_Uxf32 -> %[[RED]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>) +! CHECK: %[[DECL:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFacc_reduction_add_allocatableEa"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>) +! CHECK: %[[RED:.*]] = acc.reduction varPtr(%[[DECL]]#0 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>) recipe(@reduction_max_ref_box_heap_Uxf32) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>> {name = "a"} +! CHECK: acc.parallel reduction(%[[RED]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>) subroutine acc_reduction_add_pointer_array(a) real, pointer :: a(:) @@ -1269,9 +1724,9 @@ end subroutine ! CHECK-LABEL: func.func @_QPacc_reduction_add_pointer_array( ! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>> {fir.bindc_name = "a"}) -! CHECK: %[[DECL:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFacc_reduction_add_pointer_arrayEa"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>) -! CHECK: %[[RED:.*]] = acc.reduction varPtr(%[[DECL]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>) -> !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>> {name = "a"} -! CHECK: acc.parallel reduction(@reduction_max_ref_box_ptr_Uxf32 -> %[[RED]] : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>) +! CHECK: %[[DECL:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFacc_reduction_add_pointer_arrayEa"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>) +! CHECK: %[[RED:.*]] = acc.reduction varPtr(%[[DECL]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>) recipe(@reduction_max_ref_box_ptr_Uxf32) -> !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>> {name = "a"} +! CHECK: acc.parallel reduction(%[[RED]] : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>) subroutine acc_reduction_max_dynamic_extent_max(a, n) integer :: n @@ -1282,6 +1737,6 @@ end subroutine ! CHECK-LABEL: func.func @_QPacc_reduction_max_dynamic_extent_max( ! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.array<?x?xf32>> {fir.bindc_name = "a"}, %{{.*}}: !fir.ref<i32> {fir.bindc_name = "n"}) -! CHECK: %[[DECL_A:.*]]:2 = hlfir.declare %[[ARG0]](%{{.*}}) dummy_scope %{{[0-9]+}} {uniq_name = "_QFacc_reduction_max_dynamic_extent_maxEa"} : (!fir.ref<!fir.array<?x?xf32>>, !fir.shape<2>, !fir.dscope) -> (!fir.box<!fir.array<?x?xf32>>, !fir.ref<!fir.array<?x?xf32>>) -! CHECK: %[[RED:.*]] = acc.reduction var(%[[DECL_A]]#0 : !fir.box<!fir.array<?x?xf32>>) -> !fir.box<!fir.array<?x?xf32>> {name = "a"} -! CHECK: acc.parallel reduction(@reduction_max_box_UxUxf32 -> %[[RED]] : !fir.box<!fir.array<?x?xf32>>) +! CHECK: %[[DECL_A:.*]]:2 = hlfir.declare %[[ARG0]](%{{.*}}) dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFacc_reduction_max_dynamic_extent_maxEa"} : (!fir.ref<!fir.array<?x?xf32>>, !fir.shape<2>, !fir.dscope) -> (!fir.box<!fir.array<?x?xf32>>, !fir.ref<!fir.array<?x?xf32>>) +! CHECK: %[[RED:.*]] = acc.reduction var(%[[DECL_A]]#0 : !fir.box<!fir.array<?x?xf32>>) recipe(@reduction_max_box_UxUxf32) -> !fir.box<!fir.array<?x?xf32>> {name = "a"} +! CHECK: acc.parallel reduction(%[[RED]] : !fir.box<!fir.array<?x?xf32>>) diff --git a/flang/test/Lower/OpenACC/acc-routine-named.f90 b/flang/test/Lower/OpenACC/acc-routine-named.f90 index de9784a..24d47e5 100644 --- a/flang/test/Lower/OpenACC/acc-routine-named.f90 +++ b/flang/test/Lower/OpenACC/acc-routine-named.f90 @@ -14,7 +14,7 @@ contains subroutine acc1() end subroutine -! CHECK-LABEL: func.func @_QMacc_routinesPacc1() +! CHECK-LABEL: func.func @_QMacc_routinesPacc1() ! CHECK-SAME:attributes {acc.routine_info = #acc.routine_info<[@[[r1]]]>} subroutine acc2() diff --git a/flang/test/Lower/OpenACC/acc-routine.f90 b/flang/test/Lower/OpenACC/acc-routine.f90 index 1a63b41..c281ca5 100644 --- a/flang/test/Lower/OpenACC/acc-routine.f90 +++ b/flang/test/Lower/OpenACC/acc-routine.f90 @@ -127,13 +127,13 @@ subroutine acc_routine16() end subroutine subroutine acc_routine17() - !$acc routine device_type(host) worker dtype(multicore) vector + !$acc routine device_type(host) worker dtype(multicore) vector end subroutine subroutine acc_routine18() - !$acc routine device_type(host) bind(acc_routine17) dtype(multicore) bind(acc_routine16) + !$acc routine device_type(host) bind(acc_routine17) dtype(multicore) bind(acc_routine16) end subroutine subroutine acc_routine19() - !$acc routine device_type(host,default) bind(acc_routine17) dtype(multicore) bind(acc_routine16) + !$acc routine device_type(host,default) bind(acc_routine17) dtype(multicore) bind(acc_routine16) end subroutine diff --git a/flang/test/Lower/OpenACC/acc-routine02.f90 b/flang/test/Lower/OpenACC/acc-routine02.f90 index 1c15cb4..dd07cba 100644 --- a/flang/test/Lower/OpenACC/acc-routine02.f90 +++ b/flang/test/Lower/OpenACC/acc-routine02.f90 @@ -17,4 +17,4 @@ end program ! CHECK-LABEL: acc.routine @acc_routine_0 func(@_QPsub1) -! CHECK: func.func @_QPsub1(%ar{{.*}}: !fir.ref<!fir.array<?xf32>> {fir.bindc_name = "a"}, %arg1: !fir.ref<i32> {fir.bindc_name = "n"}) attributes {acc.routine_info = #acc.routine_info<[@acc_routine_0]>} +! CHECK: func.func @_QPsub1(%ar{{.*}}: !fir.ref<!fir.array<?xf32>> {fir.bindc_name = "a"}, %arg1: !fir.ref<i32> {fir.bindc_name = "n"}) attributes {acc.routine_info = #acc.routine_info<[@acc_routine_0]>} diff --git a/flang/test/Lower/OpenACC/acc-routine03.f90 b/flang/test/Lower/OpenACC/acc-routine03.f90 index ddd6bda..3fc3077 100644 --- a/flang/test/Lower/OpenACC/acc-routine03.f90 +++ b/flang/test/Lower/OpenACC/acc-routine03.f90 @@ -20,7 +20,7 @@ interface !$acc routine worker bind(sub2) real :: a(:) end subroutine - + subroutine sub2(a) !$acc routine worker nohost real :: a(:) diff --git a/flang/test/Lower/OpenACC/acc-routine04.f90 b/flang/test/Lower/OpenACC/acc-routine04.f90 index 655e276..4704407 100644 --- a/flang/test/Lower/OpenACC/acc-routine04.f90 +++ b/flang/test/Lower/OpenACC/acc-routine04.f90 @@ -14,17 +14,17 @@ end module program test_acc_routine use dummy_mod - + !$acc routine(sub2) seq - + implicit none - + integer :: i contains subroutine sub2() end subroutine - + end program ! CHECK: acc.routine @acc_routine_1 func(@_QFPsub2) seq diff --git a/flang/test/Lower/OpenACC/acc-serial-loop.f90 b/flang/test/Lower/OpenACC/acc-serial-loop.f90 index cad0ee7..b5bff63 100644 --- a/flang/test/Lower/OpenACC/acc-serial-loop.f90 +++ b/flang/test/Lower/OpenACC/acc-serial-loop.f90 @@ -301,7 +301,7 @@ subroutine acc_serial_loop END DO ! CHECK: %[[CREATE_A:.*]] = acc.create varPtr(%[[DECLA]]#0 : !fir.ref<!fir.array<10xf32>>) -> !fir.ref<!fir.array<10xf32>> {dataClause = #acc<data_clause acc_copyout>, name = "a"} -! CHECK: %[[CREATE_B:.*]] = acc.create varPtr(%[[DECLB]]#0 : !fir.ref<!fir.array<10xf32>>) -> !fir.ref<!fir.array<10xf32>> {dataClause = #acc<data_clause acc_copyout>, name = "b"} +! CHECK: %[[CREATE_B:.*]] = acc.create varPtr(%[[DECLB]]#0 : !fir.ref<!fir.array<10xf32>>) -> !fir.ref<!fir.array<10xf32>> {dataClause = #acc<data_clause acc_copyout_zero>, name = "b"} ! CHECK: acc.serial {{.*}} dataOperands(%[[CREATE_A]], %[[CREATE_B]] : !fir.ref<!fir.array<10xf32>>, !fir.ref<!fir.array<10xf32>>) { ! CHECK: acc.loop {{.*}} { ! CHECK: acc.yield @@ -309,7 +309,7 @@ subroutine acc_serial_loop ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} ! CHECK: acc.copyout accPtr(%[[CREATE_A]] : !fir.ref<!fir.array<10xf32>>) to varPtr(%[[DECLA]]#0 : !fir.ref<!fir.array<10xf32>>) {name = "a"} -! CHECK: acc.copyout accPtr(%[[CREATE_B]] : !fir.ref<!fir.array<10xf32>>) to varPtr(%[[DECLB]]#0 : !fir.ref<!fir.array<10xf32>>) {name = "b"} +! CHECK: acc.copyout accPtr(%[[CREATE_B]] : !fir.ref<!fir.array<10xf32>>) to varPtr(%[[DECLB]]#0 : !fir.ref<!fir.array<10xf32>>) {dataClause = #acc<data_clause acc_copyout_zero>, name = "b"} !$acc serial loop create(b) create(zero: a) DO i = 1, n @@ -392,10 +392,10 @@ subroutine acc_serial_loop a(i) = b(i) END DO -! CHECK: %[[ACC_FPRIVATE_B:.*]] = acc.firstprivate varPtr(%[[DECLB]]#0 : !fir.ref<!fir.array<10xf32>>) -> !fir.ref<!fir.array<10xf32>> {name = "b"} -! CHECK: acc.serial {{.*}} firstprivate(@firstprivatization_ref_10xf32 -> %[[ACC_FPRIVATE_B]] : !fir.ref<!fir.array<10xf32>>) { -! CHECK: %[[ACC_PRIVATE_A:.*]] = acc.private varPtr(%[[DECLA]]#0 : !fir.ref<!fir.array<10xf32>>) -> !fir.ref<!fir.array<10xf32>> {name = "a"} -! CHECK: acc.loop {{.*}} private({{.*}}@privatization_ref_10xf32 -> %[[ACC_PRIVATE_A]] : !fir.ref<!fir.array<10xf32>>{{.*}}) +! CHECK: %[[ACC_FPRIVATE_B:.*]] = acc.firstprivate varPtr(%[[DECLB]]#0 : !fir.ref<!fir.array<10xf32>>) recipe(@firstprivatization_ref_10xf32) -> !fir.ref<!fir.array<10xf32>> {name = "b"} +! CHECK: acc.serial {{.*}} firstprivate(%[[ACC_FPRIVATE_B]] : !fir.ref<!fir.array<10xf32>>) { +! CHECK: %[[ACC_PRIVATE_A:.*]] = acc.private varPtr(%[[DECLA]]#0 : !fir.ref<!fir.array<10xf32>>) recipe(@privatization_ref_10xf32) -> !fir.ref<!fir.array<10xf32>> {name = "a"} +! CHECK: acc.loop {{.*}} private(%[[ACC_PRIVATE_A]]{{.*}} : !fir.ref<!fir.array<10xf32>>{{.*}}) ! CHECK-NOT: fir.do_loop ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -661,7 +661,9 @@ subroutine acc_serial_loop ! CHECK: %[[COPYINREDR:.*]] = acc.copyin varPtr(%{{.*}} : !fir.ref<f32>) -> !fir.ref<f32> {dataClause = #acc<data_clause acc_reduction>, implicit = true, name = "reduction_r"} ! CHECK: %[[COPYINREDI:.*]] = acc.copyin varPtr(%{{.*}} : !fir.ref<i32>) -> !fir.ref<i32> {dataClause = #acc<data_clause acc_reduction>, implicit = true, name = "reduction_i"} ! CHECK: acc.serial {{.*}} dataOperands(%[[COPYINREDR]], %[[COPYINREDI]] : !fir.ref<f32>, !fir.ref<i32>) { -! CHECK: acc.loop {{.*}} reduction(@reduction_add_ref_f32 -> %{{.*}} : !fir.ref<f32>, @reduction_mul_ref_i32 -> %{{.*}} : !fir.ref<i32>) +! CHECK: %[[REDUCTION_R:.*]] = acc.reduction varPtr(%{{.*}} : !fir.ref<f32>) recipe(@reduction_add_ref_f32) -> !fir.ref<f32> {name = "reduction_r"} +! CHECK: %[[REDUCTION_I:.*]] = acc.reduction varPtr(%{{.*}} : !fir.ref<i32>) recipe(@reduction_mul_ref_i32) -> !fir.ref<i32> {name = "reduction_i"} +! CHECK: acc.loop {{.*}} reduction(%[[REDUCTION_R]], %[[REDUCTION_I]] : !fir.ref<f32>, !fir.ref<i32>) ! CHECK-NOT: fir.do_loop ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} diff --git a/flang/test/Lower/OpenACC/acc-serial.f90 b/flang/test/Lower/OpenACC/acc-serial.f90 index 1e4f32f..a6d3528 100644 --- a/flang/test/Lower/OpenACC/acc-serial.f90 +++ b/flang/test/Lower/OpenACC/acc-serial.f90 @@ -201,13 +201,13 @@ subroutine acc_serial !$acc end serial ! CHECK: %[[CREATE_A:.*]] = acc.create varPtr(%[[DECLA]]#0 : !fir.ref<!fir.array<10x10xf32>>) -> !fir.ref<!fir.array<10x10xf32>> {dataClause = #acc<data_clause acc_copyout>, name = "a"} -! CHECK: %[[CREATE_B:.*]] = acc.create varPtr(%[[DECLB]]#0 : !fir.ref<!fir.array<10x10xf32>>) -> !fir.ref<!fir.array<10x10xf32>> {dataClause = #acc<data_clause acc_copyout>, name = "b"} +! CHECK: %[[CREATE_B:.*]] = acc.create varPtr(%[[DECLB]]#0 : !fir.ref<!fir.array<10x10xf32>>) -> !fir.ref<!fir.array<10x10xf32>> {dataClause = #acc<data_clause acc_copyout_zero>, name = "b"} ! CHECK: %[[CREATE_C:.*]] = acc.create varPtr(%[[DECLC]]#0 : !fir.ref<!fir.array<10x10xf32>>) -> !fir.ref<!fir.array<10x10xf32>> {dataClause = #acc<data_clause acc_copyout>, name = "c"} ! CHECK: acc.serial dataOperands(%[[CREATE_A]], %[[CREATE_B]], %[[CREATE_C]] : !fir.ref<!fir.array<10x10xf32>>, !fir.ref<!fir.array<10x10xf32>>, !fir.ref<!fir.array<10x10xf32>>) { ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} ! CHECK: acc.copyout accPtr(%[[CREATE_A]] : !fir.ref<!fir.array<10x10xf32>>) to varPtr(%[[DECLA]]#0 : !fir.ref<!fir.array<10x10xf32>>) {name = "a"} -! CHECK: acc.copyout accPtr(%[[CREATE_B]] : !fir.ref<!fir.array<10x10xf32>>) to varPtr(%[[DECLB]]#0 : !fir.ref<!fir.array<10x10xf32>>) {name = "b"} +! CHECK: acc.copyout accPtr(%[[CREATE_B]] : !fir.ref<!fir.array<10x10xf32>>) to varPtr(%[[DECLB]]#0 : !fir.ref<!fir.array<10x10xf32>>) {dataClause = #acc<data_clause acc_copyout_zero>, name = "b"} ! CHECK: acc.copyout accPtr(%[[CREATE_C]] : !fir.ref<!fir.array<10x10xf32>>) to varPtr(%[[DECLC]]#0 : !fir.ref<!fir.array<10x10xf32>>) {name = "c"} !$acc serial create(a, b) create(zero: c) @@ -272,17 +272,19 @@ subroutine acc_serial !$acc serial private(a) firstprivate(b) private(c) !$acc end serial -! CHECK: %[[ACC_PRIVATE_A:.*]] = acc.private varPtr(%[[DECLA]]#0 : !fir.ref<!fir.array<10x10xf32>>) -> !fir.ref<!fir.array<10x10xf32>> {name = "a"} -! CHECK: %[[ACC_FPRIVATE_B:.*]] = acc.firstprivate varPtr(%[[DECLB]]#0 : !fir.ref<!fir.array<10x10xf32>>) -> !fir.ref<!fir.array<10x10xf32>> {name = "b"} -! CHECK: %[[ACC_PRIVATE_C:.*]] = acc.private varPtr(%[[DECLC]]#0 : !fir.ref<!fir.array<10x10xf32>>) -> !fir.ref<!fir.array<10x10xf32>> {name = "c"} -! CHECK: acc.serial firstprivate(@firstprivatization_ref_10x10xf32 -> %[[ACC_FPRIVATE_B]] : !fir.ref<!fir.array<10x10xf32>>) private(@privatization_ref_10x10xf32 -> %[[ACC_PRIVATE_A]] : !fir.ref<!fir.array<10x10xf32>>, @privatization_ref_10x10xf32 -> %[[ACC_PRIVATE_C]] : !fir.ref<!fir.array<10x10xf32>>) { +! CHECK: %[[ACC_PRIVATE_A:.*]] = acc.private varPtr(%[[DECLA]]#0 : !fir.ref<!fir.array<10x10xf32>>) recipe(@privatization_ref_10x10xf32) -> !fir.ref<!fir.array<10x10xf32>> {name = "a"} +! CHECK: %[[ACC_FPRIVATE_B:.*]] = acc.firstprivate varPtr(%[[DECLB]]#0 : !fir.ref<!fir.array<10x10xf32>>) recipe(@firstprivatization_ref_10x10xf32) -> !fir.ref<!fir.array<10x10xf32>> {name = "b"} +! CHECK: %[[ACC_PRIVATE_C:.*]] = acc.private varPtr(%[[DECLC]]#0 : !fir.ref<!fir.array<10x10xf32>>) recipe(@privatization_ref_10x10xf32) -> !fir.ref<!fir.array<10x10xf32>> {name = "c"} +! CHECK: acc.serial firstprivate(%[[ACC_FPRIVATE_B]] : !fir.ref<!fir.array<10x10xf32>>) private(%[[ACC_PRIVATE_A]], %[[ACC_PRIVATE_C]] : !fir.ref<!fir.array<10x10xf32>>, !fir.ref<!fir.array<10x10xf32>>) { ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} !$acc serial reduction(+:reduction_r) reduction(*:reduction_i) !$acc end serial -! CHECK: acc.serial reduction(@reduction_add_ref_f32 -> %{{.*}} : !fir.ref<f32>, @reduction_mul_ref_i32 -> %{{.*}} : !fir.ref<i32>) { +! CHECK: %[[REDUCTION_R:.*]] = acc.reduction varPtr(%{{.*}} : !fir.ref<f32>) recipe(@reduction_add_ref_f32) -> !fir.ref<f32> {name = "reduction_r"} +! CHECK: %[[REDUCTION_I:.*]] = acc.reduction varPtr(%{{.*}} : !fir.ref<i32>) recipe(@reduction_mul_ref_i32) -> !fir.ref<i32> {name = "reduction_i"} +! CHECK: acc.serial reduction(%[[REDUCTION_R]], %[[REDUCTION_I]] : !fir.ref<f32>, !fir.ref<i32>) { ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} diff --git a/flang/test/Lower/OpenACC/acc-shutdown.f90 b/flang/test/Lower/OpenACC/acc-shutdown.f90 index 304dd4f..de6191d 100644 --- a/flang/test/Lower/OpenACC/acc-shutdown.f90 +++ b/flang/test/Lower/OpenACC/acc-shutdown.f90 @@ -23,9 +23,9 @@ subroutine acc_shutdown !$acc shutdown device_num(1) device_type(default, nvidia) !CHECK: [[DEVNUM:%.*]] = arith.constant 1 : i32 -!CHECK: acc.shutdown device_num([[DEVNUM]] : i32) attributes {device_types = [#acc.device_type<default>, #acc.device_type<nvidia>]} +!CHECK: acc.shutdown device_num([[DEVNUM]] : i32) attributes {device_types = [#acc.device_type<default>, #acc.device_type<nvidia>]} !$acc shutdown device_type(default) device_type(nvidia) -!CHECK: acc.shutdown attributes {device_types = [#acc.device_type<default>, #acc.device_type<nvidia>]} +!CHECK: acc.shutdown attributes {device_types = [#acc.device_type<default>, #acc.device_type<nvidia>]} end subroutine acc_shutdown diff --git a/flang/test/Lower/OpenACC/acc-terminator.f90 b/flang/test/Lower/OpenACC/acc-terminator.f90 index 53ae1a5..16100f9 100644 --- a/flang/test/Lower/OpenACC/acc-terminator.f90 +++ b/flang/test/Lower/OpenACC/acc-terminator.f90 @@ -17,7 +17,7 @@ program main !$acc data copyin(a(:,:,i),b(:,:,i),c(:,:,i)) copyout(c2(:,:,i)) !$acc host_data use_device(a(:,:,i),b(:,:,i),c(:,:,i)) - + !$acc end host_data if ( stat .ne. 0 ) then diff --git a/flang/test/Lower/OpenACC/acc-unstructured.f90 b/flang/test/Lower/OpenACC/acc-unstructured.f90 index c42c7dd..bbbf897 100644 --- a/flang/test/Lower/OpenACC/acc-unstructured.f90 +++ b/flang/test/Lower/OpenACC/acc-unstructured.f90 @@ -1,5 +1,4 @@ ! RUN: bbc -fopenacc -emit-hlfir %s -o - | FileCheck %s -! XFAIL: * subroutine test_unstructured1(a, b, c) integer :: i, j, k @@ -55,10 +54,11 @@ subroutine test_unstructured2(a, b, c) ! CHECK-LABEL: func.func @_QPtest_unstructured2 ! CHECK: acc.parallel -! CHECK: acc.loop +! CHECK: acc.loop combined(parallel) private(%{{.*}} : !fir.ref<i32>) { ! CHECK: fir.call @_FortranAStopStatementText ! CHECK: acc.yield ! CHECK: acc.yield +! CHECK: } attributes {independent = [#acc.device_type<none>], unstructured} ! CHECK: acc.yield end subroutine diff --git a/flang/test/Lower/OpenACC/acc-use-device.f90 b/flang/test/Lower/OpenACC/acc-use-device.f90 index 081a6e3..4f9ed2d 100644 --- a/flang/test/Lower/OpenACC/acc-use-device.f90 +++ b/flang/test/Lower/OpenACC/acc-use-device.f90 @@ -9,7 +9,7 @@ subroutine test() ! CHECK: %[[A0:.*]] = fir.alloca !fir.array<?xf64>, %{{.*}} {bindc_name = "b", uniq_name = "_QFtestEb"} ! CHECK: %[[A1:.*]] = fir.shape_shift {{.*}} : (index, index) -> !fir.shapeshift<1> ! CHECK: %[[A:.*]]:2 = hlfir.declare %[[A0]](%[[A1]]) {uniq_name = "_QFtestEb"} : (!fir.ref<!fir.array<?xf64>>, !fir.shapeshift<1>) -> (!fir.box<!fir.array<?xf64>>, !fir.ref<!fir.array<?xf64>>) - + !$acc data copy(b) ! CHECK: %[[B:.*]] = acc.copyin var(%[[A]]#0 : !fir.box<!fir.array<?xf64>>) -> !fir.box<!fir.array<?xf64>> {dataClause = #acc<data_clause acc_copy>, name = "b"} ! CHECK: acc.data dataOperands(%[[B]] : !fir.box<!fir.array<?xf64>>) { @@ -23,7 +23,7 @@ subroutine test() ! CHECK: fir.call @_QPvadd(%[[A]]#1) fastmath<contract> : (!fir.ref<!fir.array<?xf64>>) -> () !$acc end data ! CHECK: acc.copyout accVar(%[[B]] : !fir.box<!fir.array<?xf64>>) to var(%[[A]]#0 : !fir.box<!fir.array<?xf64>>) {dataClause = #acc<data_clause acc_copy>, name = "b"} -end +end ! Test for allocatable, pointer and assumed-shape variables appearing in use_device clause. subroutine test2(a, b, c) @@ -36,9 +36,9 @@ subroutine test2(a, b, c) call allocate(d(N)) c => d ! CHECK: %[[DS:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[E:.*]]:2 = hlfir.declare %arg0 dummy_scope %[[DS]] {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFtest2Ea"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf64>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf64>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xf64>>>>) -! CHECK: %[[F:.*]]:2 = hlfir.declare %arg1 dummy_scope %[[DS]] {uniq_name = "_QFtest2Eb"} : (!fir.box<!fir.array<?xf64>>, !fir.dscope) -> (!fir.box<!fir.array<?xf64>>, !fir.box<!fir.array<?xf64>>) -! CHECK: %[[G:.*]]:2 = hlfir.declare %arg2 dummy_scope %[[DS]] {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFtest2Ec"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf64>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf64>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf64>>>>) +! CHECK: %[[E:.*]]:2 = hlfir.declare %arg0 dummy_scope %[[DS]] {{.*}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFtest2Ea"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf64>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf64>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xf64>>>>) +! CHECK: %[[F:.*]]:2 = hlfir.declare %arg1 dummy_scope %[[DS]] {{.*}} {uniq_name = "_QFtest2Eb"} : (!fir.box<!fir.array<?xf64>>, !fir.dscope) -> (!fir.box<!fir.array<?xf64>>, !fir.box<!fir.array<?xf64>>) +! CHECK: %[[G:.*]]:2 = hlfir.declare %arg2 dummy_scope %[[DS]] {{.*}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFtest2Ec"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf64>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf64>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf64>>>>) !$acc data copy(a,b,c,d) !$acc host_data use_device(a,b,c) diff --git a/flang/test/Lower/OpenACC/do-loops-to-acc-loops.f90 b/flang/test/Lower/OpenACC/do-loops-to-acc-loops.f90 index eaf734f..2bfc561 100644 --- a/flang/test/Lower/OpenACC/do-loops-to-acc-loops.f90 +++ b/flang/test/Lower/OpenACC/do-loops-to-acc-loops.f90 @@ -18,8 +18,8 @@ subroutine basic_do_loop() !$acc end kernels ! CHECK: acc.kernels { -! CHECK: %[[PRIVATE_IV:.*]] = acc.private varPtr(%{{.*}} : !fir.ref<i32>) -> !fir.ref<i32> {implicit = true, name = "i"} -! CHECK: acc.loop private(@privatization_ref_i32 -> %[[PRIVATE_IV]] : !fir.ref<i32>) control(%{{.*}} : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) +! CHECK: %[[PRIVATE_IV:.*]] = acc.private varPtr(%{{.*}} : !fir.ref<i32>) recipe(@privatization_ref_i32) -> !fir.ref<i32> {implicit = true, name = "i"} +! CHECK: acc.loop private(%[[PRIVATE_IV]] : !fir.ref<i32>) control(%{{.*}} : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) ! CHECK: %[[PRIVATE_DECLARE:.*]]:2 = hlfir.declare %[[PRIVATE_IV]] {uniq_name = "_QFbasic_do_loopEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: fir.store %{{.*}} to %[[PRIVATE_DECLARE]]#0 : !fir.ref<i32> ! CHECK: %{{.*}} = fir.load %[[PRIVATE_DECLARE]]#0 : !fir.ref<i32> @@ -47,8 +47,8 @@ subroutine basic_do_concurrent() !$acc end kernels ! CHECK: acc.kernels { -! CHECK: %[[PRIVATE_IV:.*]] = acc.private varPtr(%{{.*}} : !fir.ref<i32>) -> !fir.ref<i32> {implicit = true, name = "i"} -! CHECK: acc.loop private(@privatization_ref_i32 -> %[[PRIVATE_IV]] : !fir.ref<i32>) control(%{{.*}} : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) +! CHECK: %[[PRIVATE_IV:.*]] = acc.private varPtr(%{{.*}} : !fir.ref<i32>) recipe(@privatization_ref_i32) -> !fir.ref<i32> {implicit = true, name = "i"} +! CHECK: acc.loop private(%[[PRIVATE_IV]] : !fir.ref<i32>) control(%{{.*}} : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) ! CHECK: %[[PRIVATE_DECLARE:.*]]:2 = hlfir.declare %[[PRIVATE_IV]] {uniq_name = "_QFbasic_do_concurrentEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: fir.store %{{.*}} to %[[PRIVATE_DECLARE]]#0 : !fir.ref<i32> ! CHECK: %{{.*}} = fir.load %[[PRIVATE_DECLARE]]#0 : !fir.ref<i32> @@ -76,8 +76,8 @@ subroutine basic_do_loop_parallel() !$acc end parallel ! CHECK: acc.parallel { -! CHECK: %[[PRIVATE_IV:.*]] = acc.private varPtr(%{{.*}} : !fir.ref<i32>) -> !fir.ref<i32> {implicit = true, name = "i"} -! CHECK: acc.loop private(@privatization_ref_i32 -> %[[PRIVATE_IV]] : !fir.ref<i32>) control(%{{.*}} : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) +! CHECK: %[[PRIVATE_IV:.*]] = acc.private varPtr(%{{.*}} : !fir.ref<i32>) recipe(@privatization_ref_i32) -> !fir.ref<i32> {implicit = true, name = "i"} +! CHECK: acc.loop private(%[[PRIVATE_IV]] : !fir.ref<i32>) control(%{{.*}} : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) ! CHECK: %[[PRIVATE_DECLARE:.*]]:2 = hlfir.declare %[[PRIVATE_IV]] {uniq_name = "_QFbasic_do_loop_parallelEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: fir.store %{{.*}} to %[[PRIVATE_DECLARE]]#0 : !fir.ref<i32> ! CHECK: %{{.*}} = fir.load %[[PRIVATE_DECLARE]]#0 : !fir.ref<i32> @@ -105,8 +105,8 @@ subroutine basic_do_loop_serial() !$acc end serial ! CHECK: acc.serial { -! CHECK: %[[PRIVATE_IV:.*]] = acc.private varPtr(%{{.*}} : !fir.ref<i32>) -> !fir.ref<i32> {implicit = true, name = "i"} -! CHECK: acc.loop private(@privatization_ref_i32 -> %[[PRIVATE_IV]] : !fir.ref<i32>) control(%{{.*}} : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) +! CHECK: %[[PRIVATE_IV:.*]] = acc.private varPtr(%{{.*}} : !fir.ref<i32>) recipe(@privatization_ref_i32) -> !fir.ref<i32> {implicit = true, name = "i"} +! CHECK: acc.loop private(%[[PRIVATE_IV]] : !fir.ref<i32>) control(%{{.*}} : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) ! CHECK: %[[PRIVATE_DECLARE:.*]]:2 = hlfir.declare %[[PRIVATE_IV]] {uniq_name = "_QFbasic_do_loop_serialEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: fir.store %{{.*}} to %[[PRIVATE_DECLARE]]#0 : !fir.ref<i32> ! CHECK: %{{.*}} = fir.load %[[PRIVATE_DECLARE]]#0 : !fir.ref<i32> @@ -134,8 +134,8 @@ subroutine basic_do_concurrent_parallel() !$acc end parallel ! CHECK: acc.parallel { -! CHECK: %[[PRIVATE_IV:.*]] = acc.private varPtr(%{{.*}} : !fir.ref<i32>) -> !fir.ref<i32> {implicit = true, name = "i"} -! CHECK: acc.loop private(@privatization_ref_i32 -> %[[PRIVATE_IV]] : !fir.ref<i32>) control(%{{.*}} : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) +! CHECK: %[[PRIVATE_IV:.*]] = acc.private varPtr(%{{.*}} : !fir.ref<i32>) recipe(@privatization_ref_i32) -> !fir.ref<i32> {implicit = true, name = "i"} +! CHECK: acc.loop private(%[[PRIVATE_IV]] : !fir.ref<i32>) control(%{{.*}} : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) ! CHECK: %[[PRIVATE_DECLARE:.*]]:2 = hlfir.declare %[[PRIVATE_IV]] {uniq_name = "_QFbasic_do_concurrent_parallelEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: fir.store %{{.*}} to %[[PRIVATE_DECLARE]]#0 : !fir.ref<i32> ! CHECK: %{{.*}} = fir.load %[[PRIVATE_DECLARE]]#0 : !fir.ref<i32> @@ -163,8 +163,8 @@ subroutine basic_do_concurrent_serial() !$acc end serial ! CHECK: acc.serial { -! CHECK: %[[PRIVATE_IV:.*]] = acc.private varPtr(%{{.*}} : !fir.ref<i32>) -> !fir.ref<i32> {implicit = true, name = "i"} -! CHECK: acc.loop private(@privatization_ref_i32 -> %[[PRIVATE_IV]] : !fir.ref<i32>) control(%{{.*}} : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) +! CHECK: %[[PRIVATE_IV:.*]] = acc.private varPtr(%{{.*}} : !fir.ref<i32>) recipe(@privatization_ref_i32) -> !fir.ref<i32> {implicit = true, name = "i"} +! CHECK: acc.loop private(%[[PRIVATE_IV]] : !fir.ref<i32>) control(%{{.*}} : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) ! CHECK: %[[PRIVATE_DECLARE:.*]]:2 = hlfir.declare %[[PRIVATE_IV]] {uniq_name = "_QFbasic_do_concurrent_serialEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: fir.store %{{.*}} to %[[PRIVATE_DECLARE]]#0 : !fir.ref<i32> ! CHECK: %{{.*}} = fir.load %[[PRIVATE_DECLARE]]#0 : !fir.ref<i32> @@ -192,10 +192,10 @@ subroutine multi_dimension_do_concurrent() !$acc end kernels ! CHECK: acc.kernels { -! CHECK-DAG: %[[PRIVATE_I:.*]] = acc.private varPtr(%{{.*}} : !fir.ref<i32>) -> !fir.ref<i32> {implicit = true, name = "i"} -! CHECK-DAG: %[[PRIVATE_J:.*]] = acc.private varPtr(%{{.*}} : !fir.ref<i32>) -> !fir.ref<i32> {implicit = true, name = "j"} -! CHECK-DAG: %[[PRIVATE_K:.*]] = acc.private varPtr(%{{.*}} : !fir.ref<i32>) -> !fir.ref<i32> {implicit = true, name = "k"} -! CHECK: acc.loop private(@privatization_ref_i32 -> %[[PRIVATE_I]] : !fir.ref<i32>, @privatization_ref_i32 -> %[[PRIVATE_J]] : !fir.ref<i32>, @privatization_ref_i32 -> %[[PRIVATE_K]] : !fir.ref<i32>) control(%{{.*}} : i32, %{{.*}} : i32, %{{.*}} : i32) = (%c1{{.*}}, %c1{{.*}}, %c1{{.*}} : i32, i32, i32) to (%{{.*}}, %{{.*}}, %{{.*}} : i32, i32, i32) step (%c1{{.*}}, %c1{{.*}}, %c1{{.*}} : i32, i32, i32) +! CHECK-DAG: %[[PRIVATE_I:.*]] = acc.private varPtr(%{{.*}} : !fir.ref<i32>) recipe(@privatization_ref_i32) -> !fir.ref<i32> {implicit = true, name = "i"} +! CHECK-DAG: %[[PRIVATE_J:.*]] = acc.private varPtr(%{{.*}} : !fir.ref<i32>) recipe(@privatization_ref_i32) -> !fir.ref<i32> {implicit = true, name = "j"} +! CHECK-DAG: %[[PRIVATE_K:.*]] = acc.private varPtr(%{{.*}} : !fir.ref<i32>) recipe(@privatization_ref_i32) -> !fir.ref<i32> {implicit = true, name = "k"} +! CHECK: acc.loop private(%[[PRIVATE_I]], %[[PRIVATE_J]], %[[PRIVATE_K]] : !fir.ref<i32>, !fir.ref<i32>, !fir.ref<i32>) control(%{{.*}} : i32, %{{.*}} : i32, %{{.*}} : i32) = (%c1{{.*}}, %c1{{.*}}, %c1{{.*}} : i32, i32, i32) to (%{{.*}}, %{{.*}}, %{{.*}} : i32, i32, i32) step (%c1{{.*}}, %c1{{.*}}, %c1{{.*}} : i32, i32, i32) ! CHECK-DAG: %[[PRIVATE_I_DECLARE:.*]]:2 = hlfir.declare %[[PRIVATE_I]] {uniq_name = "_QFmulti_dimension_do_concurrentEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK-DAG: %[[PRIVATE_J_DECLARE:.*]]:2 = hlfir.declare %[[PRIVATE_J]] {uniq_name = "_QFmulti_dimension_do_concurrentEj"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK-DAG: %[[PRIVATE_K_DECLARE:.*]]:2 = hlfir.declare %[[PRIVATE_K]] {uniq_name = "_QFmulti_dimension_do_concurrentEk"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) @@ -234,12 +234,12 @@ subroutine nested_do_loops() !$acc end kernels ! CHECK: acc.kernels { -! CHECK-DAG: %[[PRIVATE_I:.*]] = acc.private varPtr(%{{.*}} : !fir.ref<i32>) -> !fir.ref<i32> {implicit = true, name = "i"} -! CHECK: acc.loop private(@privatization_ref_i32 -> %[[PRIVATE_I]] : !fir.ref<i32>) control(%{{.*}} : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) +! CHECK-DAG: %[[PRIVATE_I:.*]] = acc.private varPtr(%{{.*}} : !fir.ref<i32>) recipe(@privatization_ref_i32) -> !fir.ref<i32> {implicit = true, name = "i"} +! CHECK: acc.loop private(%[[PRIVATE_I]] : !fir.ref<i32>) control(%{{.*}} : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) ! CHECK-DAG: %[[PRIVATE_I_DECLARE:.*]]:2 = hlfir.declare %[[PRIVATE_I]] {uniq_name = "_QFnested_do_loopsEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: fir.store %{{.*}} to %[[PRIVATE_I_DECLARE]]#0 : !fir.ref<i32> -! CHECK-DAG: %[[PRIVATE_J:.*]] = acc.private varPtr(%{{.*}} : !fir.ref<i32>) -> !fir.ref<i32> {implicit = true, name = "j"} -! CHECK: acc.loop private(@privatization_ref_i32 -> %[[PRIVATE_J]] : !fir.ref<i32>) control(%{{.*}} : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) +! CHECK-DAG: %[[PRIVATE_J:.*]] = acc.private varPtr(%{{.*}} : !fir.ref<i32>) recipe(@privatization_ref_i32) -> !fir.ref<i32> {implicit = true, name = "j"} +! CHECK: acc.loop private(%[[PRIVATE_J]] : !fir.ref<i32>) control(%{{.*}} : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) ! CHECK-DAG: %[[PRIVATE_J_DECLARE:.*]]:2 = hlfir.declare %[[PRIVATE_J]] {uniq_name = "_QFnested_do_loopsEj"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: fir.store %{{.*}} to %[[PRIVATE_J_DECLARE]]#0 : !fir.ref<i32> ! CHECK: %{{.*}} = fir.load %[[PRIVATE_I_DECLARE]]#0 : !fir.ref<i32> @@ -271,8 +271,8 @@ subroutine variable_bounds_and_step(n, start_val, step_val) !$acc end kernels ! CHECK: acc.kernels { -! CHECK: %[[PRIVATE_IV:.*]] = acc.private varPtr(%{{.*}} : !fir.ref<i32>) -> !fir.ref<i32> {implicit = true, name = "i"} -! CHECK: acc.loop private(@privatization_ref_i32 -> %[[PRIVATE_IV]] : !fir.ref<i32>) control(%{{.*}} : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) +! CHECK: %[[PRIVATE_IV:.*]] = acc.private varPtr(%{{.*}} : !fir.ref<i32>) recipe(@privatization_ref_i32) -> !fir.ref<i32> {implicit = true, name = "i"} +! CHECK: acc.loop private(%[[PRIVATE_IV]] : !fir.ref<i32>) control(%{{.*}} : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) ! CHECK: %[[PRIVATE_DECLARE:.*]]:2 = hlfir.declare %[[PRIVATE_IV]] {uniq_name = "_QFvariable_bounds_and_stepEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: fir.store %{{.*}} to %[[PRIVATE_DECLARE]]#0 : !fir.ref<i32> ! CHECK: %{{.*}} = fir.load %[[PRIVATE_DECLARE]]#0 : !fir.ref<i32> @@ -314,22 +314,22 @@ subroutine different_iv_types() !$acc end kernels ! CHECK: acc.kernels { -! CHECK: %[[PRIVATE_I8:.*]] = acc.private varPtr(%{{.*}} : !fir.ref<i64>) -> !fir.ref<i64> {implicit = true, name = "i8"} -! CHECK: acc.loop private(@privatization_ref_i64 -> %[[PRIVATE_I8]] : !fir.ref<i64>) control(%{{.*}} : i64) = (%{{.*}} : i64) to (%{{.*}} : i64) step (%{{.*}} : i64) +! CHECK: %[[PRIVATE_I8:.*]] = acc.private varPtr(%{{.*}} : !fir.ref<i64>) recipe(@privatization_ref_i64) -> !fir.ref<i64> {implicit = true, name = "i8"} +! CHECK: acc.loop private(%[[PRIVATE_I8]] : !fir.ref<i64>) control(%{{.*}} : i64) = (%{{.*}} : i64) to (%{{.*}} : i64) step (%{{.*}} : i64) ! CHECK: %[[PRIVATE_I8_DECLARE:.*]]:2 = hlfir.declare %[[PRIVATE_I8]] {uniq_name = "_QFdifferent_iv_typesEi8"} : (!fir.ref<i64>) -> (!fir.ref<i64>, !fir.ref<i64>) ! CHECK: fir.store %{{.*}} to %[[PRIVATE_I8_DECLARE]]#0 : !fir.ref<i64> ! CHECK: %{{.*}} = fir.load %[[PRIVATE_I8_DECLARE]]#0 : !fir.ref<i64> ! CHECK: %{{.*}} = fir.load %[[PRIVATE_I8_DECLARE]]#0 : !fir.ref<i64> ! CHECK: acc.kernels { -! CHECK: %[[PRIVATE_I4:.*]] = acc.private varPtr(%{{.*}} : !fir.ref<i32>) -> !fir.ref<i32> {implicit = true, name = "i4"} -! CHECK: acc.loop private(@privatization_ref_i32 -> %[[PRIVATE_I4]] : !fir.ref<i32>) control(%{{.*}} : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) +! CHECK: %[[PRIVATE_I4:.*]] = acc.private varPtr(%{{.*}} : !fir.ref<i32>) recipe(@privatization_ref_i32) -> !fir.ref<i32> {implicit = true, name = "i4"} +! CHECK: acc.loop private(%[[PRIVATE_I4]] : !fir.ref<i32>) control(%{{.*}} : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) ! CHECK: %[[PRIVATE_I4_DECLARE:.*]]:2 = hlfir.declare %[[PRIVATE_I4]] {uniq_name = "_QFdifferent_iv_typesEi4"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: fir.store %{{.*}} to %[[PRIVATE_I4_DECLARE]]#0 : !fir.ref<i32> ! CHECK: %{{.*}} = fir.load %[[PRIVATE_I4_DECLARE]]#0 : !fir.ref<i32> ! CHECK: %{{.*}} = fir.load %[[PRIVATE_I4_DECLARE]]#0 : !fir.ref<i32> ! CHECK: acc.kernels { -! CHECK: %[[PRIVATE_I2:.*]] = acc.private varPtr(%{{.*}} : !fir.ref<i16>) -> !fir.ref<i16> {implicit = true, name = "i2"} -! CHECK: acc.loop private(@privatization_ref_i16 -> %[[PRIVATE_I2]] : !fir.ref<i16>) control(%{{.*}} : i16) = (%{{.*}} : i16) to (%{{.*}} : i16) step (%{{.*}} : i16) +! CHECK: %[[PRIVATE_I2:.*]] = acc.private varPtr(%{{.*}} : !fir.ref<i16>) recipe(@privatization_ref_i16) -> !fir.ref<i16> {implicit = true, name = "i2"} +! CHECK: acc.loop private(%[[PRIVATE_I2]] : !fir.ref<i16>) control(%{{.*}} : i16) = (%{{.*}} : i16) to (%{{.*}} : i16) step (%{{.*}} : i16) ! CHECK: %[[PRIVATE_I2_DECLARE:.*]]:2 = hlfir.declare %[[PRIVATE_I2]] {uniq_name = "_QFdifferent_iv_typesEi2"} : (!fir.ref<i16>) -> (!fir.ref<i16>, !fir.ref<i16>) ! CHECK: fir.store %{{.*}} to %[[PRIVATE_I2_DECLARE]]#0 : !fir.ref<i16> ! CHECK: %{{.*}} = fir.load %[[PRIVATE_I2_DECLARE]]#0 : !fir.ref<i16> @@ -359,14 +359,14 @@ subroutine nested_loop_with_reduction(x, y) !$acc end parallel ! CHECK: acc.parallel { -! CHECK: %[[REDUCTION_X:.*]] = acc.reduction varPtr(%{{.*}} : !fir.ref<i32>) -> !fir.ref<i32> {name = "x"} -! CHECK: %[[REDUCTION_Y:.*]] = acc.reduction varPtr(%{{.*}} : !fir.ref<i32>) -> !fir.ref<i32> {name = "y"} -! CHECK: %[[PRIVATE_I:.*]] = acc.private varPtr(%{{.*}} : !fir.ref<i32>) -> !fir.ref<i32> {implicit = true, name = "i"} -! CHECK: acc.loop private(@privatization_ref_i32 -> %[[PRIVATE_I]] : !fir.ref<i32>) reduction(@reduction_add_ref_i32 -> %[[REDUCTION_X]] : !fir.ref<i32>, @reduction_add_ref_i32 -> %[[REDUCTION_Y]] : !fir.ref<i32>) control(%{{.*}} : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) +! CHECK: %[[REDUCTION_X:.*]] = acc.reduction varPtr(%{{.*}} : !fir.ref<i32>) recipe(@reduction_add_ref_i32) -> !fir.ref<i32> {name = "x"} +! CHECK: %[[REDUCTION_Y:.*]] = acc.reduction varPtr(%{{.*}} : !fir.ref<i32>) recipe(@reduction_add_ref_i32) -> !fir.ref<i32> {name = "y"} +! CHECK: %[[PRIVATE_I:.*]] = acc.private varPtr(%{{.*}} : !fir.ref<i32>) recipe(@privatization_ref_i32) -> !fir.ref<i32> {implicit = true, name = "i"} +! CHECK: acc.loop private(%[[PRIVATE_I]] : !fir.ref<i32>) reduction(%[[REDUCTION_X]], %[[REDUCTION_Y]] : !fir.ref<i32>, !fir.ref<i32>) control(%{{.*}} : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) ! CHECK: %[[PRIVATE_I_DECLARE:.*]]:2 = hlfir.declare %[[PRIVATE_I]] {uniq_name = "_QFnested_loop_with_reductionEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: fir.store %{{.*}} to %[[PRIVATE_I_DECLARE]]#0 : !fir.ref<i32> -! CHECK: %[[PRIVATE_J:.*]] = acc.private varPtr(%{{.*}} : !fir.ref<i32>) -> !fir.ref<i32> {implicit = true, name = "j"} -! CHECK: acc.loop private(@privatization_ref_i32 -> %[[PRIVATE_J]] : !fir.ref<i32>) control(%{{.*}} : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) +! CHECK: %[[PRIVATE_J:.*]] = acc.private varPtr(%{{.*}} : !fir.ref<i32>) recipe(@privatization_ref_i32) -> !fir.ref<i32> {implicit = true, name = "j"} +! CHECK: acc.loop private(%[[PRIVATE_J]] : !fir.ref<i32>) control(%{{.*}} : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) ! CHECK: %[[PRIVATE_J_DECLARE:.*]]:2 = hlfir.declare %[[PRIVATE_J]] {uniq_name = "_QFnested_loop_with_reductionEj"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: fir.store %{{.*}} to %[[PRIVATE_J_DECLARE]]#0 : !fir.ref<i32> ! CHECK: %{{.*}} = fir.load %{{.*}} : !fir.ref<i32> diff --git a/flang/test/Lower/OpenACC/locations.f90 b/flang/test/Lower/OpenACC/locations.f90 index 69873b3..8e00721 100644 --- a/flang/test/Lower/OpenACC/locations.f90 +++ b/flang/test/Lower/OpenACC/locations.f90 @@ -114,7 +114,7 @@ module acc_locations subroutine atomic_read_loc() integer(4) :: x integer(8) :: y - + !$acc atomic read y = x end @@ -123,10 +123,10 @@ module acc_locations subroutine atomic_capture_loc() implicit none integer :: k, v, i - + k = 1 v = 0 - + !$acc atomic capture v = k k = (i + 1) * 3.14 @@ -142,13 +142,13 @@ module acc_locations subroutine atomic_update_loc() implicit none integer :: x, y, z - - !$acc atomic + + !$acc atomic y = y + 1 ! CHECK: acc.atomic.update %{{.*}} : !fir.ref<i32> { ! CHECK: ^bb0(%{{.*}}: i32 loc("{{.*}}locations.f90":142:3)): ! CHECK: } loc("{{.*}}locations.f90":142:3) - + !$acc atomic update z = x * z end subroutine @@ -183,5 +183,3 @@ module acc_locations !CHECK-SAME: loc("{{.*}}locations.f90":181:11) end subroutine end module - - diff --git a/flang/test/Lower/OpenMP/DelayedPrivatization/target-private-allocatable.f90 b/flang/test/Lower/OpenMP/DelayedPrivatization/target-private-allocatable.f90 index 272f34f..e0fb568 100644 --- a/flang/test/Lower/OpenMP/DelayedPrivatization/target-private-allocatable.f90 +++ b/flang/test/Lower/OpenMP/DelayedPrivatization/target-private-allocatable.f90 @@ -72,8 +72,8 @@ end subroutine target_allocatable ! CPU-SAME: {bindc_name = "alloc_var", {{.*}}} ! CPU: %[[VAR_DECL:.*]]:2 = hlfir.declare %[[VAR_ALLOC]] ! CPU: %[[BASE_ADDR:.*]] = fir.box_offset %[[VAR_DECL]]#0 base_addr : (!fir.ref<!fir.box<!fir.heap<i32>>>) -> [[MEMBER_TYPE:.*]] -! CPU: %[[MEMBER:.*]] = omp.map.info var_ptr(%[[VAR_DECL]]#0 : [[TYPE]], i32) map_clauses(to) capture(ByRef) var_ptr_ptr(%[[BASE_ADDR]] : [[MEMBER_TYPE:.*]]) -> {{.*}} -! CPU: %[[MAP_VAR:.*]] = omp.map.info var_ptr(%[[VAR_DECL]]#0 : [[TYPE]], [[DESC_TYPE]]) map_clauses(to) capture(ByRef) members(%[[MEMBER]] : [0] : !fir.llvm_ptr<!fir.ref<i32>>) -> !fir.ref<!fir.box<!fir.heap<i32>>> +! CPU: %[[MEMBER:.*]] = omp.map.info var_ptr(%[[VAR_DECL]]#0 : [[TYPE]], i32) map_clauses(tofrom) capture(ByRef) var_ptr_ptr(%[[BASE_ADDR]] : [[MEMBER_TYPE:.*]]) -> {{.*}} +! CPU: %[[MAP_VAR:.*]] = omp.map.info var_ptr(%[[VAR_DECL]]#0 : [[TYPE]], [[DESC_TYPE]]) map_clauses(always, to) capture(ByRef) members(%[[MEMBER]] : [0] : !fir.llvm_ptr<!fir.ref<i32>>) -> !fir.ref<!fir.box<!fir.heap<i32>>> ! CPU: omp.target map_entries(%[[MAP_VAR]] -> %arg0, %[[MEMBER]] -> %arg1 : [[TYPE]], [[MEMBER_TYPE]]) private( ! CPU-SAME: @[[VAR_PRIVATIZER_SYM]] %[[VAR_DECL]]#0 -> %{{.*}} [map_idx=0] : [[TYPE]]) { diff --git a/flang/test/Lower/OpenMP/DelayedPrivatization/target-private-multiple-variables.f90 b/flang/test/Lower/OpenMP/DelayedPrivatization/target-private-multiple-variables.f90 index f3b9397..a6394ea 100644 --- a/flang/test/Lower/OpenMP/DelayedPrivatization/target-private-multiple-variables.f90 +++ b/flang/test/Lower/OpenMP/DelayedPrivatization/target-private-multiple-variables.f90 @@ -156,7 +156,7 @@ end subroutine target_allocatable ! CHECK-SAME: %[[REAL_ARR_DESC_MAP]] -> %[[MAPPED_ARG2:[^,]+]] ! CHECK-SAME: %[[CHAR_VAR_DESC_MAP]] -> %[[MAPPED_ARG3:.[^,]+]] ! CHECK-SAME: %[[MAPPED_MI0]] -> %[[MAPPED_ARG0:[^,]+]] -! CHECK-SAME: !fir.ref<!fir.box<!fir.heap<i32>>>, !fir.ref<!fir.box<!fir.array<?xf32>>>, !fir.ref<!fir.boxchar<1>>, !fir.ref<i32>, !fir.llvm_ptr<!fir.ref<i32>>, !fir.llvm_ptr<!fir.ref<!fir.array<?xf32>>>, !fir.ref<!fir.boxchar<1>> +! CHECK-SAME: !fir.ref<!fir.box<!fir.heap<i32>>>, !fir.ref<!fir.box<!fir.array<?xf32>>>, !fir.ref<!fir.boxchar<1>>, !fir.ref<i32>, !fir.llvm_ptr<!fir.ref<i32>>, !fir.llvm_ptr<!fir.ref<!fir.array<?xf32>>>, !fir.llvm_ptr<!fir.ref<!fir.char<1,?>>> ! CHECK-SAME: private( ! CHECK-SAME: @[[ALLOC_PRIVATIZER_SYM]] %{{[^[:space:]]+}}#0 -> %[[ALLOC_ARG:[^,]+]] [map_idx=0], ! CHECK-SAME: @[[REAL_PRIVATIZER_SYM]] %{{[^[:space:]]+}}#0 -> %[[REAL_ARG:[^,]+]], diff --git a/flang/test/Lower/OpenMP/DelayedPrivatization/target-teams-private-implicit-scalar-map.f90 b/flang/test/Lower/OpenMP/DelayedPrivatization/target-teams-private-implicit-scalar-map.f90 index 126f341..d476b48 100644 --- a/flang/test/Lower/OpenMP/DelayedPrivatization/target-teams-private-implicit-scalar-map.f90 +++ b/flang/test/Lower/OpenMP/DelayedPrivatization/target-teams-private-implicit-scalar-map.f90 @@ -28,7 +28,7 @@ program test_default_implicit_firstprivate !CHECK: %[[VAL_9:.*]] = omp.map.info var_ptr(%[[VAL_4]] : !fir.ref<i32>, i32) map_clauses(implicit) capture(ByCopy) -> !fir.ref<i32> {name = "k"} !CHECK: %[[VAL_10:.*]] = fir.box_offset %[[VAL_0]] base_addr : (!fir.ref<!fir.box<!fir.heap<!fir.array<?x?x?xi32>>>>) -> !fir.llvm_ptr<!fir.ref<!fir.array<?x?x?xi32>>> !CHECK: %[[VAL_11:.*]] = omp.map.info var_ptr(%[[VAL_0]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?x?x?xi32>>>>, i32) map_clauses(implicit, tofrom) capture(ByRef) var_ptr_ptr(%[[VAL_10]] : !fir.llvm_ptr<!fir.ref<!fir.array<?x?x?xi32>>>) bounds({{.*}}) -> !fir.llvm_ptr<!fir.ref<!fir.array<?x?x?xi32>>> {name = ""} -!CHECK: %[[VAL_12:.*]] = omp.map.info var_ptr(%[[VAL_0]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?x?x?xi32>>>>, !fir.box<!fir.heap<!fir.array<?x?x?xi32>>>) map_clauses(implicit, to) capture(ByRef) members(%[[VAL_11]] : [0] : !fir.llvm_ptr<!fir.ref<!fir.array<?x?x?xi32>>>) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?x?x?xi32>>>> {name = "allocarr"} +!CHECK: %[[VAL_12:.*]] = omp.map.info var_ptr(%[[VAL_0]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?x?x?xi32>>>>, !fir.box<!fir.heap<!fir.array<?x?x?xi32>>>) map_clauses(always, implicit, to) capture(ByRef) members(%[[VAL_11]] : [0] : !fir.llvm_ptr<!fir.ref<!fir.array<?x?x?xi32>>>) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?x?x?xi32>>>> {name = "allocarr"} !CHECK: %[[VAL_13:.*]] = omp.map.info var_ptr(%[[VAL_1]] : !fir.ref<!fir.array<10x10x10xi32>>, !fir.array<10x10x10xi32>) map_clauses(implicit, tofrom) capture(ByRef) bounds({{.*}}) -> !fir.ref<!fir.array<10x10x10xi32>> {name = "arr"} !CHECK: %[[VAL_14:.*]] = omp.map.info var_ptr(%[[VAL_6]] : !fir.ref<i32>, i32) map_clauses(to) capture(ByCopy) -> !fir.ref<i32> !CHECK: %[[VAL_15:.*]] = omp.map.info var_ptr(%[[VAL_5]] : !fir.ref<i32>, i32) map_clauses(to) capture(ByCopy) -> !fir.ref<i32> diff --git a/flang/test/Lower/OpenMP/Todo/defaultmap-clause-firstprivate.f90 b/flang/test/Lower/OpenMP/Todo/defaultmap-clause-firstprivate.f90 index 6818c39f..1e0d969 100644 --- a/flang/test/Lower/OpenMP/Todo/defaultmap-clause-firstprivate.f90 +++ b/flang/test/Lower/OpenMP/Todo/defaultmap-clause-firstprivate.f90 @@ -6,7 +6,7 @@ subroutine f00 ! NOTE: This is implemented for scalars as it is the default behaviour, so we utilise ! a different data type. integer, allocatable :: i - !CHECK: not yet implemented: Firstprivate and None are currently unsupported defaultmap behaviour + !CHECK: not yet implemented: Firstprivate is currently unsupported defaultmap behaviour !$omp target defaultmap(firstprivate) i = 10 !$omp end target diff --git a/flang/test/Lower/OpenMP/Todo/defaultmap-clause-none.f90 b/flang/test/Lower/OpenMP/Todo/defaultmap-clause-none.f90 deleted file mode 100644 index 287eb4a..0000000 --- a/flang/test/Lower/OpenMP/Todo/defaultmap-clause-none.f90 +++ /dev/null @@ -1,11 +0,0 @@ -!RUN: %not_todo_cmd bbc -emit-hlfir -fopenmp -fopenmp-version=51 -o - %s 2>&1 | FileCheck %s -!RUN: %not_todo_cmd %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=51 -o - %s 2>&1 | FileCheck %s - -subroutine f00 - implicit none - integer :: i - !CHECK: not yet implemented: Firstprivate and None are currently unsupported defaultmap behaviour - !$omp target defaultmap(none) - i = 10 - !$omp end target -end diff --git a/flang/test/Lower/OpenMP/Todo/omp-clause-indirect.f90 b/flang/test/Lower/OpenMP/Todo/omp-clause-indirect.f90 index d441cac..82efa88 100644 --- a/flang/test/Lower/OpenMP/Todo/omp-clause-indirect.f90 +++ b/flang/test/Lower/OpenMP/Todo/omp-clause-indirect.f90 @@ -1,6 +1,6 @@ ! This test checks the lowering of OpenMP Indirect Clause when used with the Declare Target directive -! RUN: not flang -fc1 -emit-fir -fopenmp -fopenmp-version=52 %s 2>&1 | FileCheck %s +! RUN: not %flang_fc1 -emit-fir -fopenmp -fopenmp-version=52 %s 2>&1 | FileCheck %s module functions implicit none diff --git a/flang/test/Lower/OpenMP/Todo/omp-declarative-allocate-align.f90 b/flang/test/Lower/OpenMP/Todo/omp-declarative-allocate-align.f90 index 8daf20e..fec146a 100644 --- a/flang/test/Lower/OpenMP/Todo/omp-declarative-allocate-align.f90 +++ b/flang/test/Lower/OpenMP/Todo/omp-declarative-allocate-align.f90 @@ -5,6 +5,6 @@ program main integer :: x - ! CHECK: not yet implemented: OpenMPDeclarativeAllocate + ! CHECK: not yet implemented: OmpAllocateDirective !$omp allocate(x) align(32) end diff --git a/flang/test/Lower/OpenMP/Todo/omp-declarative-allocate.f90 b/flang/test/Lower/OpenMP/Todo/omp-declarative-allocate.f90 index e83b433..7cae805 100644 --- a/flang/test/Lower/OpenMP/Todo/omp-declarative-allocate.f90 +++ b/flang/test/Lower/OpenMP/Todo/omp-declarative-allocate.f90 @@ -1,10 +1,10 @@ ! This test checks lowering of OpenMP allocate Directive. -! RUN: not flang -fc1 -emit-fir -fopenmp %s 2>&1 | FileCheck %s +! RUN: not %flang_fc1 -emit-fir -fopenmp %s 2>&1 | FileCheck %s program main integer :: x, y - ! CHECK: not yet implemented: OpenMPDeclarativeAllocate + ! CHECK: not yet implemented: OmpAllocateDirective !$omp allocate(x, y) end diff --git a/flang/test/Lower/OpenMP/Todo/omp-declare-reduction-advanced-types.f90 b/flang/test/Lower/OpenMP/Todo/omp-declare-reduction-advanced-types.f90 new file mode 100644 index 0000000..e40e3d9 --- /dev/null +++ b/flang/test/Lower/OpenMP/Todo/omp-declare-reduction-advanced-types.f90 @@ -0,0 +1,19 @@ +! This test checks lowering of OpenMP declare reduction with non-trivial types + +! RUN: not %flang_fc1 -emit-fir -fopenmp %s 2>&1 | FileCheck %s + +module mymod + type advancedtype + integer(4)::myarray(10) + integer(4)::val + integer(4)::otherval + end type advancedtype + !CHECK: not yet implemented: declare reduction currently only supports trival types or derived types containing trivial types + !$omp declare reduction(myreduction: advancedtype: omp_out = omp_in) initializer(omp_priv = omp_orig) +end module mymod + +program mymaxtest + use mymod + +end program + diff --git a/flang/test/Lower/OpenMP/Todo/omp-declare-reduction-initsub.f90 b/flang/test/Lower/OpenMP/Todo/omp-declare-reduction-initsub.f90 deleted file mode 100644 index 3063046..0000000 --- a/flang/test/Lower/OpenMP/Todo/omp-declare-reduction-initsub.f90 +++ /dev/null @@ -1,28 +0,0 @@ -! This test checks lowering of OpenMP declare reduction Directive, with initialization -! via a subroutine. This functionality is currently not implemented. - -! RUN: not flang -fc1 -emit-fir -fopenmp %s 2>&1 | FileCheck %s - -!CHECK: not yet implemented: OpenMPDeclareReductionConstruct -subroutine initme(x,n) - integer x,n - x=n -end subroutine initme - -function func(x, n, init) - integer func - integer x(n) - integer res - interface - subroutine initme(x,n) - integer x,n - end subroutine initme - end interface -!$omp declare reduction(red_add:integer(4):omp_out=omp_out+omp_in) initializer(initme(omp_priv,0)) - res=init -!$omp simd reduction(red_add:res) - do i=1,n - res=res+x(i) - enddo - func=res -end function func diff --git a/flang/test/Lower/OpenMP/Todo/omp-declare-reduction.f90 b/flang/test/Lower/OpenMP/Todo/omp-declare-reduction.f90 deleted file mode 100644 index db50c9a..0000000 --- a/flang/test/Lower/OpenMP/Todo/omp-declare-reduction.f90 +++ /dev/null @@ -1,10 +0,0 @@ -! This test checks lowering of OpenMP declare reduction Directive. - -! RUN: not flang -fc1 -emit-fir -fopenmp %s 2>&1 | FileCheck %s - -subroutine declare_red() - integer :: my_var - !CHECK: not yet implemented: OpenMPDeclareReductionConstruct - !$omp declare reduction (my_red : integer : omp_out = omp_in) initializer (omp_priv = 0) - my_var = 0 -end subroutine declare_red diff --git a/flang/test/Lower/OpenMP/Todo/omp-declare-simd.f90 b/flang/test/Lower/OpenMP/Todo/omp-declare-simd.f90 index be1ac2d..a63bfb2 100644 --- a/flang/test/Lower/OpenMP/Todo/omp-declare-simd.f90 +++ b/flang/test/Lower/OpenMP/Todo/omp-declare-simd.f90 @@ -1,6 +1,6 @@ ! This test checks lowering of OpenMP declare simd Directive. -// RUN: not flang -fc1 -emit-fir -fopenmp %s 2>&1 | FileCheck %s +// RUN: not %flang_fc1 -emit-fir -fopenmp %s 2>&1 | FileCheck %s subroutine sub(x, y) real, intent(inout) :: x, y diff --git a/flang/test/Lower/OpenMP/Todo/omp-do-simd-linear.f90 b/flang/test/Lower/OpenMP/Todo/omp-do-simd-linear.f90 deleted file mode 100644 index db8f5c2..0000000 --- a/flang/test/Lower/OpenMP/Todo/omp-do-simd-linear.f90 +++ /dev/null @@ -1,14 +0,0 @@ -! This test checks lowering of OpenMP do simd linear() pragma - -! RUN: %not_todo_cmd bbc -emit-fir -fopenmp -o - %s 2>&1 | FileCheck %s -! RUN: %not_todo_cmd %flang_fc1 -emit-fir -fopenmp -o - %s 2>&1 | FileCheck %s -subroutine testDoSimdLinear(int_array) - integer :: int_array(:) -!CHECK: not yet implemented: Unhandled clause LINEAR in SIMD construct -!$omp do simd linear(int_array) - do index_ = 1, 10 - end do -!$omp end do simd - -end subroutine testDoSimdLinear - diff --git a/flang/test/Lower/OpenMP/Todo/reduction-task.f90 b/flang/test/Lower/OpenMP/Todo/reduction-task.f90 index b8bfc37..adc8de0 100644 --- a/flang/test/Lower/OpenMP/Todo/reduction-task.f90 +++ b/flang/test/Lower/OpenMP/Todo/reduction-task.f90 @@ -8,5 +8,5 @@ subroutine reduction_task() !$omp parallel reduction(task, +:i) i = i + 1 - !$omp end parallel + !$omp end parallel end subroutine reduction_task diff --git a/flang/test/Lower/OpenMP/Todo/taskloop-inreduction.f90 b/flang/test/Lower/OpenMP/Todo/taskloop-inreduction.f90 deleted file mode 100644 index 8acc399..0000000 --- a/flang/test/Lower/OpenMP/Todo/taskloop-inreduction.f90 +++ /dev/null @@ -1,13 +0,0 @@ -! RUN: %not_todo_cmd bbc -emit-fir -fopenmp -fopenmp-version=50 -o - %s 2>&1 | FileCheck %s -! RUN: %not_todo_cmd %flang_fc1 -emit-fir -fopenmp -fopenmp-version=50 -o - %s 2>&1 | FileCheck %s - -! CHECK: not yet implemented: Unhandled clause IN_REDUCTION in TASKLOOP construct -subroutine omp_taskloop_inreduction() - integer x - x = 0 - !$omp taskloop in_reduction(+:x) - do i = 1, 100 - x = x + 1 - end do - !$omp end taskloop -end subroutine omp_taskloop_inreduction diff --git a/flang/test/Lower/OpenMP/Todo/taskloop-reduction.f90 b/flang/test/Lower/OpenMP/Todo/taskloop-reduction.f90 deleted file mode 100644 index 0c16bd2..0000000 --- a/flang/test/Lower/OpenMP/Todo/taskloop-reduction.f90 +++ /dev/null @@ -1,13 +0,0 @@ -! RUN: %not_todo_cmd bbc -emit-fir -fopenmp -fopenmp-version=50 -o - %s 2>&1 | FileCheck %s -! RUN: %not_todo_cmd %flang_fc1 -emit-fir -fopenmp -fopenmp-version=50 -o - %s 2>&1 | FileCheck %s - -! CHECK: not yet implemented: Unhandled clause REDUCTION in TASKLOOP construct -subroutine omp_taskloop_reduction() - integer x - x = 0 - !$omp taskloop reduction(+:x) - do i = 1, 100 - x = x + 1 - end do - !$omp end taskloop -end subroutine omp_taskloop_reduction diff --git a/flang/test/Lower/OpenMP/Todo/threadset.f90 b/flang/test/Lower/OpenMP/Todo/threadset.f90 new file mode 100644 index 0000000..b022baf --- /dev/null +++ b/flang/test/Lower/OpenMP/Todo/threadset.f90 @@ -0,0 +1,10 @@ +! RUN: %not_todo_cmd %flang_fc1 -emit-fir -fopenmp -fopenmp-version=60 -o - %s 2>&1 | FileCheck %s + +! CHECK: not yet implemented: THREADSET clause is not implemented yet + +subroutine f00(x) + integer :: x(10) + !$omp task threadset(omp_pool) + x = x + 1 + !$omp end task +end diff --git a/flang/test/Lower/OpenMP/allocatable-array-bounds.f90 b/flang/test/Lower/OpenMP/allocatable-array-bounds.f90 index 96d779c..ade197b 100644 --- a/flang/test/Lower/OpenMP/allocatable-array-bounds.f90 +++ b/flang/test/Lower/OpenMP/allocatable-array-bounds.f90 @@ -24,7 +24,7 @@ !HOST: %[[BOUNDS_1:.*]] = omp.map.bounds lower_bound(%[[LB_1]] : index) upper_bound(%[[UB_1]] : index) extent(%[[BOX_3]]#1 : index) stride(%[[BOX_2]]#2 : index) start_idx(%[[BOX_1]]#0 : index) {stride_in_bytes = true} !HOST: %[[VAR_PTR_PTR:.*]] = fir.box_offset %[[DECLARE_1]]#1 base_addr : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) -> !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>> !HOST: %[[MAP_INFO_MEMBER:.*]] = omp.map.info var_ptr(%[[DECLARE_1]]#1 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, i32) map_clauses(tofrom) capture(ByRef) var_ptr_ptr(%[[VAR_PTR_PTR]] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) bounds(%[[BOUNDS_1]]) -> !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>> {name = ""} -!HOST: %[[MAP_INFO_1:.*]] = omp.map.info var_ptr(%[[DECLARE_1]]#1 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.box<!fir.heap<!fir.array<?xi32>>>) map_clauses(to) capture(ByRef) members(%[[MAP_INFO_MEMBER]] : [0] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> {name = "sp_read(2:5)"} +!HOST: %[[MAP_INFO_1:.*]] = omp.map.info var_ptr(%[[DECLARE_1]]#1 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.box<!fir.heap<!fir.array<?xi32>>>) map_clauses(always, to) capture(ByRef) members(%[[MAP_INFO_MEMBER]] : [0] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> {name = "sp_read(2:5)"} !HOST: %[[LOAD_3:.*]] = fir.load %[[DECLARE_2]]#0 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> !HOST: %[[LOAD_4:.*]] = fir.load %[[DECLARE_2]]#0 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> @@ -42,12 +42,12 @@ !HOST: %[[BOUNDS_2:.*]] = omp.map.bounds lower_bound(%[[LB_2]] : index) upper_bound(%[[UB_2]] : index) extent(%[[BOX_5]]#1 : index) stride(%[[BOX_4]]#2 : index) start_idx(%[[BOX_3]]#0 : index) {stride_in_bytes = true} !HOST: %[[VAR_PTR_PTR:.*]] = fir.box_offset %[[DECLARE_2]]#1 base_addr : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) -> !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>> !HOST: %[[MAP_INFO_MEMBER:.*]] = omp.map.info var_ptr(%[[DECLARE_2]]#1 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, i32) map_clauses(tofrom) capture(ByRef) var_ptr_ptr(%[[VAR_PTR_PTR]] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) bounds(%[[BOUNDS_2]]) -> !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>> {name = ""} -!HOST: %[[MAP_INFO_2:.*]] = omp.map.info var_ptr(%[[DECLARE_2]]#1 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.box<!fir.heap<!fir.array<?xi32>>>) map_clauses(to) capture(ByRef) members(%[[MAP_INFO_MEMBER]] : [0] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> {name = "sp_write(2:5)"} +!HOST: %[[MAP_INFO_2:.*]] = omp.map.info var_ptr(%[[DECLARE_2]]#1 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.box<!fir.heap<!fir.array<?xi32>>>) map_clauses(always, to) capture(ByRef) members(%[[MAP_INFO_MEMBER]] : [0] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> {name = "sp_write(2:5)"} subroutine read_write_section() integer, allocatable :: sp_read(:) integer, allocatable :: sp_write(:) - allocate(sp_read(10)) + allocate(sp_read(10)) allocate(sp_write(10)) sp_write = (/0,0,0,0,0,0,0,0,0,0/) sp_read = (/1,2,3,4,5,6,7,8,9,10/) @@ -64,7 +64,7 @@ module assumed_allocatable_array_routines !HOST-LABEL: func.func @_QMassumed_allocatable_array_routinesPassumed_shape_array( -!HOST: %[[DECLARE:.*]]:2 = hlfir.declare %[[ARG:.*]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable, intent_inout>, uniq_name = "_QMassumed_allocatable_array_routinesFassumed_shape_arrayEarr_read_write"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) +!HOST: %[[DECLARE:.*]]:2 = hlfir.declare %[[ARG:.*]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable, intent_inout>, uniq_name = "_QMassumed_allocatable_array_routinesFassumed_shape_arrayEarr_read_write"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) !HOST: %[[LOAD_1:.*]] = fir.load %[[DECLARE]]#0 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> !HOST: %[[LOAD_2:.*]] = fir.load %[[DECLARE]]#0 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> !HOST: %[[CONSTANT_1:.*]] = arith.constant 0 : index @@ -81,8 +81,7 @@ module assumed_allocatable_array_routines !HOST: %[[BOUNDS:.*]] = omp.map.bounds lower_bound(%[[LB]] : index) upper_bound(%[[UB]] : index) extent(%[[BOX_3]]#1 : index) stride(%[[BOX_2]]#2 : index) start_idx(%[[BOX_1]]#0 : index) {stride_in_bytes = true} !HOST: %[[VAR_PTR_PTR:.*]] = fir.box_offset %[[DECLARE]]#1 base_addr : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) -> !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>> !HOST: %[[MAP_INFO_MEMBER:.*]] = omp.map.info var_ptr(%[[DECLARE]]#1 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, i32) map_clauses(tofrom) capture(ByRef) var_ptr_ptr(%[[VAR_PTR_PTR]] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) bounds(%[[BOUNDS]]) -> !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>> {name = ""} -!HOST: %[[MAP_INFO:.*]] = omp.map.info var_ptr(%[[DECLARE]]#1 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.box<!fir.heap<!fir.array<?xi32>>>) map_clauses(to) capture(ByRef) members(%[[MAP_INFO_MEMBER]] : [0] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> {name = "arr_read_write(2:5)"} - +!HOST: %[[MAP_INFO:.*]] = omp.map.info var_ptr(%[[DECLARE]]#1 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.box<!fir.heap<!fir.array<?xi32>>>) map_clauses(always, to) capture(ByRef) members(%[[MAP_INFO_MEMBER]] : [0] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> {name = "arr_read_write(2:5)"} subroutine assumed_shape_array(arr_read_write) integer, allocatable, intent(inout) :: arr_read_write(:) diff --git a/flang/test/Lower/OpenMP/allocatable-map.f90 b/flang/test/Lower/OpenMP/allocatable-map.f90 index ee1c621..e1c4694 100644 --- a/flang/test/Lower/OpenMP/allocatable-map.f90 +++ b/flang/test/Lower/OpenMP/allocatable-map.f90 @@ -3,10 +3,10 @@ !HLFIRDIALECT: %[[POINTER:.*]]:2 = hlfir.declare %{{.*}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFpointer_routineEpoint"} : (!fir.ref<!fir.box<!fir.ptr<i32>>>) -> (!fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.ref<!fir.box<!fir.ptr<i32>>>) !HLFIRDIALECT: %[[BOX_OFF:.*]] = fir.box_offset %[[POINTER]]#1 base_addr : (!fir.ref<!fir.box<!fir.ptr<i32>>>) -> !fir.llvm_ptr<!fir.ref<i32>> !HLFIRDIALECT: %[[POINTER_MAP_MEMBER:.*]] = omp.map.info var_ptr(%[[POINTER]]#1 : !fir.ref<!fir.box<!fir.ptr<i32>>>, i32) map_clauses(tofrom) capture(ByRef) var_ptr_ptr(%[[BOX_OFF]] : !fir.llvm_ptr<!fir.ref<i32>>) -> !fir.llvm_ptr<!fir.ref<i32>> {name = ""} -!HLFIRDIALECT: %[[POINTER_MAP:.*]] = omp.map.info var_ptr(%[[POINTER]]#1 : !fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.box<!fir.ptr<i32>>) map_clauses(to) capture(ByRef) members(%[[POINTER_MAP_MEMBER]] : [0] : !fir.llvm_ptr<!fir.ref<i32>>) -> !fir.ref<!fir.box<!fir.ptr<i32>>> {name = "point"} +!HLFIRDIALECT: %[[POINTER_MAP:.*]] = omp.map.info var_ptr(%[[POINTER]]#1 : !fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.box<!fir.ptr<i32>>) map_clauses(always, to) capture(ByRef) members(%[[POINTER_MAP_MEMBER]] : [0] : !fir.llvm_ptr<!fir.ref<i32>>) -> !fir.ref<!fir.box<!fir.ptr<i32>>> {name = "point"} !HLFIRDIALECT: omp.target map_entries(%[[POINTER_MAP]] -> {{.*}}, %[[POINTER_MAP_MEMBER]] -> {{.*}} : !fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.llvm_ptr<!fir.ref<i32>>) { subroutine pointer_routine() - integer, pointer :: point + integer, pointer :: point !$omp target map(tofrom:point) point = 1 !$omp end target diff --git a/flang/test/Lower/OpenMP/array-bounds.f90 b/flang/test/Lower/OpenMP/array-bounds.f90 index 8f98d67..6707842 100644 --- a/flang/test/Lower/OpenMP/array-bounds.f90 +++ b/flang/test/Lower/OpenMP/array-bounds.f90 @@ -41,7 +41,7 @@ module assumed_array_routines !HOST-LABEL: func.func @_QMassumed_array_routinesPassumed_shape_array( !HOST-SAME: %[[ARG0:.*]]: !fir.box<!fir.array<?xi32>> {fir.bindc_name = "arr_read_write"}) { !HOST: %[[INTERMEDIATE_ALLOCA:.*]] = fir.alloca !fir.box<!fir.array<?xi32>> -!HOST: %[[ARG0_DECL:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<intent_inout>, uniq_name = "_QMassumed_array_routinesFassumed_shape_arrayEarr_read_write"} : (!fir.box<!fir.array<?xi32>>, !fir.dscope) -> (!fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>>) +!HOST: %[[ARG0_DECL:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<intent_inout>, uniq_name = "_QMassumed_array_routinesFassumed_shape_arrayEarr_read_write"} : (!fir.box<!fir.array<?xi32>>, !fir.dscope) -> (!fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>>) !HOST: %[[C0:.*]] = arith.constant 1 : index !HOST: %[[C1:.*]] = arith.constant 0 : index !HOST: %[[DIMS0:.*]]:3 = fir.box_dims %[[ARG0_DECL]]#0, %[[C1]] : (!fir.box<!fir.array<?xi32>>, index) -> (index, index, index) @@ -52,7 +52,7 @@ module assumed_array_routines !HOST: %[[BOUNDS:.*]] = omp.map.bounds lower_bound(%[[C3]] : index) upper_bound(%[[C4]] : index) extent(%[[DIMS1]]#1 : index) stride(%[[DIMS0]]#2 : index) start_idx(%[[C0]] : index) {stride_in_bytes = true} !HOST: %[[VAR_PTR_PTR:.*]] = fir.box_offset %[[INTERMEDIATE_ALLOCA]] base_addr : (!fir.ref<!fir.box<!fir.array<?xi32>>>) -> !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>> !HOST: %[[MAP_INFO_MEMBER:.*]] = omp.map.info var_ptr(%[[INTERMEDIATE_ALLOCA]] : !fir.ref<!fir.box<!fir.array<?xi32>>>, i32) map_clauses(tofrom) capture(ByRef) var_ptr_ptr(%[[VAR_PTR_PTR]] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) bounds(%[[BOUNDS]]) -> !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>> {name = ""} -!HOST: %[[MAP:.*]] = omp.map.info var_ptr(%[[INTERMEDIATE_ALLOCA]] : !fir.ref<!fir.box<!fir.array<?xi32>>>, !fir.box<!fir.array<?xi32>>) map_clauses(to) capture(ByRef) members(%[[MAP_INFO_MEMBER]] : [0] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) -> !fir.ref<!fir.array<?xi32>> {name = "arr_read_write(2:5)"} +!HOST: %[[MAP:.*]] = omp.map.info var_ptr(%[[INTERMEDIATE_ALLOCA]] : !fir.ref<!fir.box<!fir.array<?xi32>>>, !fir.box<!fir.array<?xi32>>) map_clauses(always, to) capture(ByRef) members(%[[MAP_INFO_MEMBER]] : [0] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) -> !fir.ref<!fir.array<?xi32>> {name = "arr_read_write(2:5)"} !HOST: omp.target map_entries(%[[MAP]] -> %{{.*}}, {{.*}} -> {{.*}}, %[[MAP_INFO_MEMBER]] -> %{{.*}} : !fir.ref<!fir.array<?xi32>>, !fir.ref<i32>, !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) { subroutine assumed_shape_array(arr_read_write) integer, intent(inout) :: arr_read_write(:) @@ -68,7 +68,7 @@ module assumed_array_routines !HOST-LABEL: func.func @_QMassumed_array_routinesPassumed_size_array( !HOST-SAME: %[[ARG0:.*]]: !fir.ref<!fir.array<?xi32>> {fir.bindc_name = "arr_read_write"}) { !HOST: %[[ARG0_SHAPE:.*]] = fir.shape %{{.*}} : (index) -> !fir.shape<1> -!HOST: %[[ARG0_DECL:.*]]:2 = hlfir.declare %[[ARG0]](%[[ARG0_SHAPE]]) dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<intent_inout>, uniq_name = "_QMassumed_array_routinesFassumed_size_arrayEarr_read_write"} : (!fir.ref<!fir.array<?xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.box<!fir.array<?xi32>>, !fir.ref<!fir.array<?xi32>>) +!HOST: %[[ARG0_DECL:.*]]:2 = hlfir.declare %[[ARG0]](%[[ARG0_SHAPE]]) dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<intent_inout>, uniq_name = "_QMassumed_array_routinesFassumed_size_arrayEarr_read_write"} : (!fir.ref<!fir.array<?xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.box<!fir.array<?xi32>>, !fir.ref<!fir.array<?xi32>>) !HOST: %[[ALLOCA:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QMassumed_array_routinesFassumed_size_arrayEi"} !HOST: %[[DIMS0:.*]]:3 = fir.box_dims %[[ARG0_DECL]]#0, %c0{{.*}} : (!fir.box<!fir.array<?xi32>>, index) -> (index, index, index) !HOST: %[[C4_1:.*]] = arith.subi %c4, %c1{{.*}} : index diff --git a/flang/test/Lower/OpenMP/atomic-capture.f90 b/flang/test/Lower/OpenMP/atomic-capture.f90 index 14fd0c9..f561dea 100644 --- a/flang/test/Lower/OpenMP/atomic-capture.f90 +++ b/flang/test/Lower/OpenMP/atomic-capture.f90 @@ -7,7 +7,7 @@ program OmpAtomicCapture - use omp_lib + use omp_lib !CHECK: %[[VAL_X_ALLOCA:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFEx"} !CHECK: %[[VAL_X_DECLARE:.*]]:2 = hlfir.declare %[[VAL_X_ALLOCA]] {{.*}} @@ -25,7 +25,7 @@ program OmpAtomicCapture !CHECK: omp.atomic.read %[[VAL_X_DECLARE]]#0 = %[[VAL_Y_DECLARE]]#0 : !fir.ref<i32>, !fir.ref<i32>, i32 !CHECK: } !$omp atomic hint(omp_sync_hint_uncontended) capture - y = x * y + y = x * y x = y !$omp end atomic @@ -43,7 +43,7 @@ program OmpAtomicCapture !CHECK: } !$omp atomic hint(omp_lock_hint_nonspeculative) capture acquire x = y - y = 2 * 10 + (8 - x) + y = 2 * 10 + (8 - x) !$omp end atomic end program diff --git a/flang/test/Lower/OpenMP/atomic-read-complex.f90 b/flang/test/Lower/OpenMP/atomic-read-complex.f90 index 2f51f03..cd20c5d 100644 --- a/flang/test/Lower/OpenMP/atomic-read-complex.f90 +++ b/flang/test/Lower/OpenMP/atomic-read-complex.f90 @@ -15,7 +15,7 @@ program atomic_read_complex complex(4) :: c41, c42 ! Test complex(8) - double precision (16 bytes) complex(8) :: c81, c82 - + c42 = (1.0_4, 1.0_4) c82 = (1.0_8, 1.0_8) @@ -25,7 +25,7 @@ program atomic_read_complex ! CHECK: call void @__atomic_load(i64 8, ptr {{.*}}, ptr {{.*}}, i32 {{.*}}) !$omp atomic read c41 = c42 - + ! Double precision complex: 16 bytes (this was broken before the fix) ! CHECK: call void @__atomic_load(i64 16, ptr {{.*}}, ptr {{.*}}, i32 {{.*}}) !$omp atomic read diff --git a/flang/test/Lower/OpenMP/atomic-update-capture-complex-part.f90 b/flang/test/Lower/OpenMP/atomic-update-capture-complex-part.f90 new file mode 100644 index 0000000..ee15b88 --- /dev/null +++ b/flang/test/Lower/OpenMP/atomic-update-capture-complex-part.f90 @@ -0,0 +1,17 @@ +!RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=60 %s -o - | FileCheck %s + +! Check that this compiles successfully. + +!CHECK: omp.atomic.capture +!CHECK: omp.atomic.read +!CHECK: omp.atomic.update +subroutine f00 + implicit none + real :: c + complex, allocatable :: x + !$omp atomic update capture + c = x%re + x%re = x%re + 1.0 + !$omp end atomic +end + diff --git a/flang/test/Lower/OpenMP/atomic-update.f90 b/flang/test/Lower/OpenMP/atomic-update.f90 index f88bbea..05adee3 100644 --- a/flang/test/Lower/OpenMP/atomic-update.f90 +++ b/flang/test/Lower/OpenMP/atomic-update.f90 @@ -73,7 +73,7 @@ program OmpAtomicUpdate !CHECK: omp.yield(%[[TEMP]] : i32) !CHECK: } !$omp atomic update - a = a + b + a = a + b !CHECK: %[[VAL_c1:.*]] = arith.constant 1 : i32 !CHECK: omp.atomic.update %[[VAL_Y_DECLARE]]#0 : !fir.ref<i32> { @@ -81,7 +81,7 @@ program OmpAtomicUpdate !CHECK: %[[TEMP:.*]] = arith.addi %[[ARG]], %[[VAL_c1]] : i32 !CHECK: omp.yield(%[[TEMP]] : i32) !CHECK: } - !$omp atomic + !$omp atomic y = y + 1 !CHECK: %[[VAL_X_LOADED:.*]] = fir.load %[[VAL_X_DECLARE]]#0 : !fir.ref<i32> @@ -91,7 +91,7 @@ program OmpAtomicUpdate !CHECK: omp.yield(%[[TEMP]] : i32) !CHECK: } !$omp atomic update - z = x * z + z = x * z !CHECK: %[[VAL_c1:.*]] = arith.constant 1 : i32 !CHECK: omp.atomic.update hint(uncontended) memory_order(relaxed) %[[VAL_X_DECLARE]]#0 : !fir.ref<i32> { @@ -110,7 +110,7 @@ program OmpAtomicUpdate !CHECK: %[[TEMP:.*]] = arith.select {{.*}} : i32 !CHECK: omp.yield(%[[TEMP]] : i32) !CHECK: } - !$omp atomic update relaxed + !$omp atomic update relaxed y = max(y, c, d) !CHECK: %[[VAL_X_LOADED:.*]] = fir.load %[[VAL_X_DECLARE]]#0 : !fir.ref<i32> @@ -211,7 +211,7 @@ program OmpAtomicUpdate !CHECK: %[[RESULT:.*]] = fir.convert %[[EXT]] : (f32) -> i32 !CHECK: omp.yield(%[[RESULT]] : i32) !$omp atomic update - w = w + g + w = w + g end program OmpAtomicUpdate ! Check that the clean-ups associated with the function call diff --git a/flang/test/Lower/OpenMP/atomic-write-complex.f90 b/flang/test/Lower/OpenMP/atomic-write-complex.f90 index 48cfe26..4e975bf 100644 --- a/flang/test/Lower/OpenMP/atomic-write-complex.f90 +++ b/flang/test/Lower/OpenMP/atomic-write-complex.f90 @@ -13,19 +13,19 @@ program atomic_write_complex ! Test complex(4) - single precision (8 bytes) complex(4) :: c41, c42 - ! Test complex(8) - double precision (16 bytes) + ! Test complex(8) - double precision (16 bytes) complex(8) :: c81, c82 - + c42 = (1.0_4, 1.0_4) c82 = (1.0_8, 1.0_8) ! CHECK-LABEL: define {{.*}} @_QQmain - + ! Single precision complex: 8 bytes ! CHECK: call void @__atomic_store(i64 8, ptr {{.*}}, ptr {{.*}}, i32 {{.*}}) !$omp atomic write c41 = c42 - + ! Double precision complex: 16 bytes (this was broken before the fix) ! CHECK: call void @__atomic_store(i64 16, ptr {{.*}}, ptr {{.*}}, i32 {{.*}}) !$omp atomic write diff --git a/flang/test/Lower/OpenMP/cancel.f90 b/flang/test/Lower/OpenMP/cancel.f90 index fd1f110..8870572 100644 --- a/flang/test/Lower/OpenMP/cancel.f90 +++ b/flang/test/Lower/OpenMP/cancel.f90 @@ -85,7 +85,7 @@ end subroutine ! CHECK-LABEL: func.func @_QPcancel_parallel_if( ! CHECK-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<!fir.logical<4>> {fir.bindc_name = "cond"}) { ! CHECK: %[[VAL_1:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] {uniq_name = "_QFcancel_parallel_ifEcond"} : (!fir.ref<!fir.logical<4>>, !fir.dscope) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] arg {{[0-9]+}} {uniq_name = "_QFcancel_parallel_ifEcond"} : (!fir.ref<!fir.logical<4>>, !fir.dscope) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) ! CHECK: omp.parallel { ! CHECK: %[[VAL_3:.*]] = fir.load %[[VAL_2]]#0 : !fir.ref<!fir.logical<4>> ! CHECK: %[[VAL_4:.*]] = fir.convert %[[VAL_3]] : (!fir.logical<4>) -> i1 @@ -106,7 +106,7 @@ end subroutine ! CHECK-LABEL: func.func @_QPcancel_do_if( ! CHECK-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<!fir.logical<4>> {fir.bindc_name = "cond"}) { ! CHECK: %[[VAL_1:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] {uniq_name = "_QFcancel_do_ifEcond"} : (!fir.ref<!fir.logical<4>>, !fir.dscope) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] arg {{[0-9]+}} {uniq_name = "_QFcancel_do_ifEcond"} : (!fir.ref<!fir.logical<4>>, !fir.dscope) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) ! CHECK: %[[VAL_3:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFcancel_do_ifEi"} ! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_3]] {uniq_name = "_QFcancel_do_ifEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: omp.parallel { @@ -138,7 +138,7 @@ end subroutine ! CHECK-LABEL: func.func @_QPcancel_sections_if( ! CHECK-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<!fir.logical<4>> {fir.bindc_name = "cond"}) { ! CHECK: %[[VAL_1:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] {uniq_name = "_QFcancel_sections_ifEcond"} : (!fir.ref<!fir.logical<4>>, !fir.dscope) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] arg {{[0-9]+}} {uniq_name = "_QFcancel_sections_ifEcond"} : (!fir.ref<!fir.logical<4>>, !fir.dscope) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) ! CHECK: omp.sections { ! CHECK: omp.section { ! CHECK: %[[VAL_3:.*]] = fir.load %[[VAL_2]]#0 : !fir.ref<!fir.logical<4>> @@ -162,7 +162,7 @@ end subroutine ! CHECK-LABEL: func.func @_QPcancel_taskgroup_if( ! CHECK-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<!fir.logical<4>> {fir.bindc_name = "cond"}) { ! CHECK: %[[VAL_1:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] {uniq_name = "_QFcancel_taskgroup_ifEcond"} : (!fir.ref<!fir.logical<4>>, !fir.dscope) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] arg {{[0-9]+}} {uniq_name = "_QFcancel_taskgroup_ifEcond"} : (!fir.ref<!fir.logical<4>>, !fir.dscope) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) ! CHECK: omp.taskgroup { ! CHECK: omp.task { ! CHECK: %[[VAL_3:.*]] = fir.load %[[VAL_2]]#0 : !fir.ref<!fir.logical<4>> diff --git a/flang/test/Lower/OpenMP/compiler-directives-loop.f90 b/flang/test/Lower/OpenMP/compiler-directives-loop.f90 new file mode 100644 index 0000000..916b5a9f --- /dev/null +++ b/flang/test/Lower/OpenMP/compiler-directives-loop.f90 @@ -0,0 +1,31 @@ +!RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=60 %s -o - | FileCheck %s + +! Check that we generate proper body of the do-construct. + +!CHECK: omp.loop_nest (%[[ARG1:arg[0-9]+]]) : i32 = (%c1_i32) to (%c10_i32) inclusive step (%c1_i32_1) { +!CHECK: %[[V0:[0-9]+]]:2 = hlfir.declare %arg0 {uniq_name = "_QFEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: hlfir.assign %[[ARG1]] to %[[V0]]#0 : i32, !fir.ref<i32> +!CHECK: %[[V1:[0-9]+]] = fir.load %[[V0]]#0 : !fir.ref<i32> +!CHECK: %[[V2:[0-9]+]] = fir.convert %[[V1]] : (i32) -> f32 +!CHECK: %[[V3:[0-9]+]] = fir.load %[[V0]]#0 : !fir.ref<i32> +!CHECK: %[[V4:[0-9]+]] = fir.convert %[[V3]] : (i32) -> i64 +!CHECK: %[[V5:[0-9]+]] = hlfir.designate %3#0 (%[[V4]]) : (!fir.ref<!fir.array<10xf32>>, i64) -> !fir.ref<f32> +!CHECK: hlfir.assign %[[V2]] to %[[V5]] : f32, !fir.ref<f32> +!CHECK: omp.yield +!CHECK: } + +program omp_cdir_codegen + implicit none + integer, parameter :: n = 10 + real :: a(n) + integer :: i + +!$omp parallel do +!dir$ unroll + do i = 1, n + a(i) = real(i) + end do +!$omp end parallel do + + print *, 'a(1)=', a(1), ' a(n)=', a(n) +end program omp_cdir_codegen diff --git a/flang/test/Lower/OpenMP/copyin.f90 b/flang/test/Lower/OpenMP/copyin.f90 index 129d8bd..6cdbbd2c 100644 --- a/flang/test/Lower/OpenMP/copyin.f90 +++ b/flang/test/Lower/OpenMP/copyin.f90 @@ -335,7 +335,7 @@ subroutine common_2() integer :: y common /d/ x, y !$omp threadprivate(/d/) - + !$omp parallel do copyin(/d/) do i = 1, x y = y + i diff --git a/flang/test/Lower/OpenMP/cray-pointers01.f90 b/flang/test/Lower/OpenMP/cray-pointers01.f90 index d3a5a3c..01c6b8b 100644 --- a/flang/test/Lower/OpenMP/cray-pointers01.f90 +++ b/flang/test/Lower/OpenMP/cray-pointers01.f90 @@ -1,5 +1,5 @@ ! Test lowering of Cray pointee references. -! RUN: flang -fc1 -emit-hlfir -fopenmp %s -o - 2>&1 | FileCheck %s +! RUN: %flang_fc1 -emit-hlfir -fopenmp %s -o - 2>&1 | FileCheck %s module test_host_assoc_cray_pointer ! CHECK-LABEL: fir.global @_QMtest_host_assoc_cray_pointerEivar : i64 diff --git a/flang/test/Lower/OpenMP/cray-pointers02.f90 b/flang/test/Lower/OpenMP/cray-pointers02.f90 index 79d8387..4dd1c9e 100644 --- a/flang/test/Lower/OpenMP/cray-pointers02.f90 +++ b/flang/test/Lower/OpenMP/cray-pointers02.f90 @@ -1,5 +1,5 @@ ! Test lowering of Cray pointee references. -! RUN: flang -fc1 -emit-hlfir -fopenmp %s -o - 2>&1 | FileCheck %s +! RUN: %flang_fc1 -emit-hlfir -fopenmp %s -o - 2>&1 | FileCheck %s ! CHECK-LABEL: func.func @_QQmain() attributes {fir.bindc_name = "TEST_CRAY_POINTERS_02"} program test_cray_pointers_02 diff --git a/flang/test/Lower/OpenMP/declare-mapper.f90 b/flang/test/Lower/OpenMP/declare-mapper.f90 index c389d0f..7eda1a4 100644 --- a/flang/test/Lower/OpenMP/declare-mapper.f90 +++ b/flang/test/Lower/OpenMP/declare-mapper.f90 @@ -6,7 +6,11 @@ ! RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=50 %t/omp-declare-mapper-3.f90 -o - | FileCheck %t/omp-declare-mapper-3.f90 ! RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=50 %t/omp-declare-mapper-4.f90 -o - | FileCheck %t/omp-declare-mapper-4.f90 ! RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=50 %t/omp-declare-mapper-5.f90 -o - | FileCheck %t/omp-declare-mapper-5.f90 -! RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=51 %t/omp-declare-mapper-6.f90 -o - | FileCheck %t/omp-declare-mapper-6.f90 +! RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=50 %t/omp-declare-mapper-6.f90 -o - | FileCheck %t/omp-declare-mapper-6.f90 +! RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=50 -module-dir %t %t/omp-declare-mapper-7.mod.f90 -o - >/dev/null +! RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=50 -J %t %t/omp-declare-mapper-7.use.f90 -o - | FileCheck %t/omp-declare-mapper-7.use.f90 +! RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=50 -module-dir %t %t/omp-declare-mapper-8.mod.f90 -o - >/dev/null +! RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=50 -J %t %t/omp-declare-mapper-8.use.f90 -o - | FileCheck %t/omp-declare-mapper-8.use.f90 !--- omp-declare-mapper-1.f90 subroutine declare_mapper_1 @@ -24,7 +28,7 @@ subroutine declare_mapper_1 end type type(my_type2) :: t real :: x, y(nvals) - !CHECK:omp.declare_mapper @[[MY_TYPE_MAPPER:_QQFdeclare_mapper_1my_type\.omp\.default\.mapper]] : [[MY_TYPE:!fir\.type<_QFdeclare_mapper_1Tmy_type\{num_vals:i32,values:!fir\.box<!fir\.heap<!fir\.array<\?xi32>>>\}>]] { + !CHECK:omp.declare_mapper @[[MY_TYPE_MAPPER:_QQFdeclare_mapper_1my_type_omp_default_mapper]] : [[MY_TYPE:!fir\.type<_QFdeclare_mapper_1Tmy_type\{num_vals:i32,values:!fir\.box<!fir\.heap<!fir\.array<\?xi32>>>\}>]] { !CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<[[MY_TYPE]]>): !CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = "_QFdeclare_mapper_1Evar"} : (!fir.ref<[[MY_TYPE]]>) -> (!fir.ref<[[MY_TYPE]]>, !fir.ref<[[MY_TYPE]]>) !CHECK: %[[VAL_2:.*]] = hlfir.designate %[[VAL_1]]#0{"values"} {fortran_attrs = #fir.var_attrs<allocatable>} : (!fir.ref<[[MY_TYPE]]>) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> @@ -45,7 +49,7 @@ subroutine declare_mapper_1 !CHECK: %[[VAL_18:.*]] = fir.coordinate_of %[[VAL_1]]#0, values : (!fir.ref<[[MY_TYPE]]>) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> !CHECK: %[[VAL_19:.*]] = fir.box_offset %[[VAL_18]] base_addr : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) -> !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>> !CHECK: %[[VAL_20:.*]] = omp.map.info var_ptr(%[[VAL_18]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, i32) map_clauses(tofrom) capture(ByRef) var_ptr_ptr(%[[VAL_19]] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) bounds(%[[VAL_16]]) -> !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>> {name = ""} - !CHECK: %[[VAL_21:.*]] = omp.map.info var_ptr(%[[VAL_18]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.box<!fir.heap<!fir.array<?xi32>>>) map_clauses(to) capture(ByRef) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> {name = "var%[[VAL_22:.*]](1:var%[[VAL_23:.*]])"} + !CHECK: %[[VAL_21:.*]] = omp.map.info var_ptr(%[[VAL_18]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.box<!fir.heap<!fir.array<?xi32>>>) map_clauses(always, to) capture(ByRef) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> {name = "var%[[VAL_22:.*]](1:var%[[VAL_23:.*]])"} !CHECK: %[[VAL_24:.*]] = omp.map.info var_ptr(%[[VAL_1]]#1 : !fir.ref<[[MY_TYPE]]>, [[MY_TYPE]]) map_clauses(tofrom) capture(ByRef) members(%[[VAL_21]], %[[VAL_20]] : [1], [1, 0] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) -> !fir.ref<[[MY_TYPE]]> {name = "var"} !CHECK: omp.declare_mapper.info map_entries(%[[VAL_24]], %[[VAL_21]], %[[VAL_20]] : !fir.ref<[[MY_TYPE]]>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) !CHECK: } @@ -137,7 +141,7 @@ subroutine declare_mapper_3 !CHECK: %[[VAL_18:.*]] = fir.coordinate_of %[[VAL_1]]#0, values : (!fir.ref<[[MY_TYPE]]>) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> !CHECK: %[[VAL_19:.*]] = fir.box_offset %[[VAL_18]] base_addr : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) -> !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>> !CHECK: %[[VAL_20:.*]] = omp.map.info var_ptr(%[[VAL_18]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, i32) map_clauses(tofrom) capture(ByRef) var_ptr_ptr(%[[VAL_19]] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) bounds(%[[VAL_16]]) -> !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>> {name = ""} - !CHECK: %[[VAL_21:.*]] = omp.map.info var_ptr(%[[VAL_18]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.box<!fir.heap<!fir.array<?xi32>>>) map_clauses(to) capture(ByRef) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> {name = "var%[[VAL_22:.*]](1:var%[[VAL_23:.*]])"} + !CHECK: %[[VAL_21:.*]] = omp.map.info var_ptr(%[[VAL_18]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.box<!fir.heap<!fir.array<?xi32>>>) map_clauses(always, to) capture(ByRef) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> {name = "var%[[VAL_22:.*]](1:var%[[VAL_23:.*]])"} !CHECK: %[[VAL_24:.*]] = omp.map.info var_ptr(%[[VAL_1]]#1 : !fir.ref<[[MY_TYPE]]>, [[MY_TYPE]]) map_clauses(tofrom) capture(ByRef) members(%[[VAL_21]], %[[VAL_20]] : [1], [1, 0] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) -> !fir.ref<[[MY_TYPE]]> {name = "var"} !CHECK: omp.declare_mapper.info map_entries(%[[VAL_24]], %[[VAL_21]], %[[VAL_20]] : !fir.ref<[[MY_TYPE]]>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) !CHECK: } @@ -151,7 +155,7 @@ subroutine declare_mapper_4 integer :: num end type - !CHECK: omp.declare_mapper @[[MY_TYPE_MAPPER:_QQFdeclare_mapper_4my_type.omp.default.mapper]] : [[MY_TYPE:!fir\.type<_QFdeclare_mapper_4Tmy_type\{num:i32\}>]] + !CHECK: omp.declare_mapper @[[MY_TYPE_MAPPER:_QQFdeclare_mapper_4my_type_omp_default_mapper]] : [[MY_TYPE:!fir\.type<_QFdeclare_mapper_4Tmy_type\{num:i32\}>]] !$omp declare mapper (my_type :: var) map (var%num) type(my_type) :: a @@ -163,7 +167,7 @@ subroutine declare_mapper_4 b = 20 !$omp end target - !CHECK: %{{.*}} = omp.map.info var_ptr(%{{.*}} : !fir.ref<i32>, i32) map_clauses(tofrom) capture(ByRef) mapper(@[[MY_TYPE_MAPPER]]) -> !fir.ref<i32> {name = "a%{{.*}}"} + !CHECK: %{{.*}} = omp.map.info var_ptr(%{{.*}} : !fir.ref<i32>, i32) map_clauses(tofrom) capture(ByRef) -> !fir.ref<i32> {name = "a%{{.*}}"} !$omp target map(a%num) a%num = 30 !$omp end target @@ -183,9 +187,9 @@ program declare_mapper_5 end type !CHECK: omp.declare_mapper @[[INNER_MAPPER_NAMED:_QQFFuse_innermy_mapper]] : [[MY_TYPE:!fir\.type<_QFTmytype\{x:i32,y:i32\}>]] - !CHECK: omp.declare_mapper @[[INNER_MAPPER_DEFAULT:_QQFFuse_innermytype.omp.default.mapper]] : [[MY_TYPE]] + !CHECK: omp.declare_mapper @[[INNER_MAPPER_DEFAULT:_QQFFuse_innermytype_omp_default_mapper]] : [[MY_TYPE]] !CHECK: omp.declare_mapper @[[OUTER_MAPPER_NAMED:_QQFmy_mapper]] : [[MY_TYPE]] - !CHECK: omp.declare_mapper @[[OUTER_MAPPER_DEFAULT:_QQFmytype.omp.default.mapper]] : [[MY_TYPE]] + !CHECK: omp.declare_mapper @[[OUTER_MAPPER_DEFAULT:_QQFmytype_omp_default_mapper]] : [[MY_TYPE]] !$omp declare mapper(mytype :: var) map(tofrom: var%x) !$omp declare mapper(my_mapper : mytype :: var) map(tofrom: var%y) @@ -301,3 +305,58 @@ subroutine declare_mapper_nested_parent r%real_arr = r%base_arr(1) + r%inner%deep_arr(1) !$omp end target end subroutine declare_mapper_nested_parent + +!--- omp-declare-mapper-7.mod.f90 +! Module with DECLARE MAPPER to be compiled separately +module m_mod + implicit none + type :: mty + integer :: x + end type mty + !$omp declare mapper(mymap : mty :: v) map(tofrom: v%x) +end module m_mod + +!--- omp-declare-mapper-7.use.f90 +! Consumer program that USEs the module and applies the mapper by name. +! CHECK: %{{.*}} = omp.map.info {{.*}} mapper(@{{.*mymap}}) {{.*}} {name = "a"} +program use_module_mapper + use m_mod + implicit none + type(mty) :: a + !$omp target map(mapper(mymap) : a) + a%x = 42 + !$omp end target +end program use_module_mapper + +!--- omp-declare-mapper-8.mod.f90 +! Module with a default DECLARE MAPPER to be compiled separately. +module default_mapper_mod + implicit none + type :: dtype + integer :: x + end type dtype + !$omp declare mapper(dtype :: v) map(tofrom: v%x) +end module default_mapper_mod + +!--- omp-declare-mapper-8.use.f90 +! Consumer program that USEs the module and relies on the default mapper. +! CHECK: omp.declare_mapper @{{.*dtype_omp_default_mapper}} : !fir.type<_QMdefault_mapper_modTdtype{x:i32}> +! CHECK: %{{.*}} = omp.map.info {{.*}} map_clauses(tofrom) {{.*}} mapper(@{{.*dtype_omp_default_mapper}}) {{.*}} {name = "a"} +! CHECK: %{{.*}} = omp.map.info {{.*}} map_clauses(tofrom) {{.*}} mapper(@{{.*dtype_omp_default_mapper}}) {{.*}} {name = "a"} +! CHECK: %{{.*}} = omp.map.info {{.*}} map_clauses(implicit, tofrom) {{.*}} mapper(@{{.*dtype_omp_default_mapper}}) {{.*}} {name = "a"} +program use_module_default_mapper + use default_mapper_mod + implicit none + type(dtype) :: a + !$omp target map(a) + a%x = 7 + !$omp end target + + !$omp target map(mapper(default) : a) + a%x = 8 + !$omp end target + + !$omp target + a%x = 8 + !$omp end target +end program use_module_default_mapper diff --git a/flang/test/Lower/OpenMP/declare-target-deferred-marking-reductions.f90 b/flang/test/Lower/OpenMP/declare-target-deferred-marking-reductions.f90 new file mode 100644 index 0000000..66697ef --- /dev/null +++ b/flang/test/Lower/OpenMP/declare-target-deferred-marking-reductions.f90 @@ -0,0 +1,37 @@ +!RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=52 %s -o - | FileCheck %s +!RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=52 -fopenmp-is-device %s -o - | FileCheck %s + +program main + use, intrinsic :: iso_c_binding + implicit none + interface + subroutine myinit(priv, orig) bind(c,name="myinit") + use, intrinsic :: iso_c_binding + implicit none + integer::priv, orig + end subroutine myinit + + function mycombine(lhs, rhs) bind(c,name="mycombine") + use, intrinsic :: iso_c_binding + implicit none + integer::lhs, rhs, mycombine + end function mycombine + end interface + !$omp declare reduction(myreduction:integer:omp_out = mycombine(omp_out, omp_in)) initializer(myinit(omp_priv, omp_orig)) + + integer :: i, s, a(10) + !$omp target + s = 0 + !$omp do reduction(myreduction:s) + do i = 1, 10 + s = mycombine(s, a(i)) + enddo + !$omp end do + !$omp end target + end program main + +!CHECK: func.func {{.*}} @myinit(!fir.ref<i32>, !fir.ref<i32>) +!CHECK-SAME: {{.*}}, omp.declare_target = #omp.declaretarget<device_type = (nohost), capture_clause = (to), automap = false>{{.*}} +!CHECK-LABEL: func.func {{.*}} @mycombine(!fir.ref<i32>, !fir.ref<i32>) +!CHECK-SAME: {{.*}}, omp.declare_target = #omp.declaretarget<device_type = (nohost), capture_clause = (to), automap = false>{{.*}} + diff --git a/flang/test/Lower/OpenMP/declare-target-func-and-subr.f90 b/flang/test/Lower/OpenMP/declare-target-func-and-subr.f90 index 4abf750..d6175dd 100644 --- a/flang/test/Lower/OpenMP/declare-target-func-and-subr.f90 +++ b/flang/test/Lower/OpenMP/declare-target-func-and-subr.f90 @@ -1,8 +1,8 @@ !RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=52 %s -o - | FileCheck %s --check-prefixes ALL,HOST !RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=52 -fopenmp-is-device %s -o - | FileCheck %s --check-prefixes ALL,DEVICE -! Check specification valid forms of declare target with functions -! utilising device_type and to clauses as well as the default +! Check specification valid forms of declare target with functions +! utilising device_type and to clauses as well as the default ! zero clause declare target ! DEVICE-LABEL: func.func @_QPfunc_t_device() @@ -94,8 +94,8 @@ END FUNCTION FUNC_NAME_AS_RESULT !! ----- -! Check specification valid forms of declare target with subroutines -! utilising device_type and to clauses as well as the default +! Check specification valid forms of declare target with subroutines +! utilising device_type and to clauses as well as the default ! zero clause declare target ! DEVICE-LABEL: func.func @_QPsubr_t_device() diff --git a/flang/test/Lower/OpenMP/declare-target-link-tarop-cap.f90 b/flang/test/Lower/OpenMP/declare-target-link-tarop-cap.f90 index cfdcd9e..0fba1ee 100644 --- a/flang/test/Lower/OpenMP/declare-target-link-tarop-cap.f90 +++ b/flang/test/Lower/OpenMP/declare-target-link-tarop-cap.f90 @@ -35,7 +35,7 @@ program test_link allocate(test_ptr1) test_ptr1 = 1 - !CHECK-DAG: {{%.*}} = omp.map.info var_ptr({{%.*}} : !fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.box<!fir.ptr<i32>>) map_clauses(implicit, to) capture(ByRef) members({{%.*}} : !fir.llvm_ptr<!fir.ref<i32>>) -> !fir.ref<!fir.box<!fir.ptr<i32>>> {name = "test_ptr1"} + !CHECK-DAG: {{%.*}} = omp.map.info var_ptr({{%.*}} : !fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.box<!fir.ptr<i32>>) map_clauses(always, implicit, to) capture(ByRef) members({{%.*}} : !fir.llvm_ptr<!fir.ref<i32>>) -> !fir.ref<!fir.box<!fir.ptr<i32>>> {name = "test_ptr1"} !$omp target test_ptr1 = test_ptr1 + 1 !$omp end target @@ -46,7 +46,7 @@ program test_link !$omp end target - !CHECK-DAG: {{%.*}} = omp.map.info var_ptr({{%.*}} : !fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.box<!fir.ptr<i32>>) map_clauses(implicit, to) capture(ByRef) members({{%.*}} : !fir.llvm_ptr<!fir.ref<i32>>) -> !fir.ref<!fir.box<!fir.ptr<i32>>> {name = "test_ptr2"} + !CHECK-DAG: {{%.*}} = omp.map.info var_ptr({{%.*}} : !fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.box<!fir.ptr<i32>>) map_clauses(always, implicit, to) capture(ByRef) members({{%.*}} : !fir.llvm_ptr<!fir.ref<i32>>) -> !fir.ref<!fir.box<!fir.ptr<i32>>> {name = "test_ptr2"} test_ptr2 => test_target !$omp target test_ptr2 = test_ptr2 + 1 diff --git a/flang/test/Lower/OpenMP/default-clause-byref.f90 b/flang/test/Lower/OpenMP/default-clause-byref.f90 index af51c4c..0d473af 100644 --- a/flang/test/Lower/OpenMP/default-clause-byref.f90 +++ b/flang/test/Lower/OpenMP/default-clause-byref.f90 @@ -197,21 +197,21 @@ subroutine nested_default_clause_tests !CHECK: } !CHECK: omp.terminator !CHECK: } - !$omp parallel firstprivate(x) private(y) shared(w) default(private) + !$omp parallel firstprivate(x) private(y) shared(w) default(private) !$omp parallel default(private) y = 20 - x = 10 - !$omp end parallel + x = 10 + !$omp end parallel - !$omp parallel default(firstprivate) shared(y) private(w) + !$omp parallel default(firstprivate) shared(y) private(w) y = 30 - w = 40 + w = 40 z = 50 k = 40 !$omp end parallel !$omp end parallel - - + + !CHECK: omp.parallel private({{.*}} {{.*}}#0 -> %[[PRIVATE_X:.*]], {{.*}} {{.*}}#0 -> %[[PRIVATE_Y:.*]], {{.*}} {{.*}}#0 -> %[[PRIVATE_Z:.*]] : {{.*}}) { !CHECK: %[[PRIVATE_X_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_X]] {uniq_name = "_QFnested_default_clause_testsEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) !CHECK: %[[PRIVATE_Y_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_Y]] {uniq_name = "_QFnested_default_clause_testsEy"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) @@ -240,8 +240,8 @@ subroutine nested_default_clause_tests !$omp parallel default(private) shared(z) w = x + z !$omp end parallel - !$omp end parallel - + !$omp end parallel + !CHECK: omp.parallel private({{.*}} {{.*}}#0 -> %[[PRIVATE_X:.*]], {{.*}} {{.*}}#0 -> %[[PRIVATE_Y:.*]], {{.*}} {{.*}}#0 -> %[[PRIVATE_W:.*]], {{.*}} {{.*}}#0 -> %[[PRIVATE_Z:.*]] : {{.*}}) { !CHECK: %[[PRIVATE_X_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_X]] {uniq_name = "_QFnested_default_clause_testsEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) !CHECK: %[[PRIVATE_Y_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_Y]] {uniq_name = "_QFnested_default_clause_testsEy"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) @@ -283,7 +283,7 @@ subroutine nested_default_clause_tests !CHECK: omp.terminator !CHECK: } !CHECK: return -!CHECK: } +!CHECK: } !$omp parallel default(firstprivate) !$omp single x = y diff --git a/flang/test/Lower/OpenMP/default-clause.f90 b/flang/test/Lower/OpenMP/default-clause.f90 index 7772583..c16d19c 100644 --- a/flang/test/Lower/OpenMP/default-clause.f90 +++ b/flang/test/Lower/OpenMP/default-clause.f90 @@ -432,7 +432,7 @@ end subroutine !CHECK: %[[VAR_X_DECLARE_INNER:.*]] = hlfir.declare %[[CONVERT_INNER]] storage(%[[BLK_THREADPRIVATE_INNER]][0]) {uniq_name = "_QFthreadprivate_with_defaultEx"} : (!fir.ref<i32>, !fir.ref<!fir.array<4xi8>>) -> (!fir.ref<i32>, !fir.ref<i32>) subroutine threadprivate_with_default integer :: x - common /blk/ x + common /blk/ x !$omp threadprivate (/blk/) !$omp parallel do default(private) diff --git a/flang/test/Lower/OpenMP/defaultmap.f90 b/flang/test/Lower/OpenMP/defaultmap.f90 index b9c902f..30351f5 100644 --- a/flang/test/Lower/OpenMP/defaultmap.f90 +++ b/flang/test/Lower/OpenMP/defaultmap.f90 @@ -6,7 +6,7 @@ subroutine defaultmap_allocatable_present() integer, dimension(:), allocatable :: arr ! CHECK: %[[MAP_1:.*]] = omp.map.info var_ptr({{.*}} : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, i32) map_clauses(implicit, present) capture(ByRef) var_ptr_ptr({{.*}}) bounds({{.*}}) -> !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>> {name = ""} -! CHECK: %[[MAP_2:.*]] = omp.map.info var_ptr({{.*}} : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.box<!fir.heap<!fir.array<?xi32>>>) map_clauses(implicit, to) capture(ByRef) members({{.*}}) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> {name = "arr"} +! CHECK: %[[MAP_2:.*]] = omp.map.info var_ptr({{.*}} : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.box<!fir.heap<!fir.array<?xi32>>>) map_clauses(always, implicit, to) capture(ByRef) members({{.*}}) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> {name = "arr"} !$omp target defaultmap(present: allocatable) arr(1) = 10 !$omp end target @@ -34,7 +34,7 @@ subroutine defaultmap_all_default() ! CHECK: %[[MAP_1:.*]] = omp.map.info var_ptr({{.*}} : !fir.ref<i32>, i32) map_clauses(implicit) capture(ByCopy) -> !fir.ref<i32> {name = "scalar_int"} ! CHECK: %[[MAP_2:.*]] = omp.map.info var_ptr({{.*}} : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, i32) map_clauses(implicit, tofrom) capture(ByRef) var_ptr_ptr({{.*}}) bounds({{.*}}) -> !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>> {name = ""} -! CHECK: %[[MAP_3:.*]] = omp.map.info var_ptr({{.*}} : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.box<!fir.heap<!fir.array<?xi32>>>) map_clauses(implicit, to) capture(ByRef) members({{.*}}) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> {name = "arr"} +! CHECK: %[[MAP_3:.*]] = omp.map.info var_ptr({{.*}} : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.box<!fir.heap<!fir.array<?xi32>>>) map_clauses(always, implicit, to) capture(ByRef) members({{.*}}) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> {name = "arr"} ! CHECK: %[[MAP_4:.*]] = omp.map.info var_ptr({{.*}} : !fir.ref<!fir.array<16xi32>>, !fir.array<16xi32>) map_clauses(implicit, tofrom) capture(ByRef) bounds({{.*}}) -> !fir.ref<!fir.array<16xi32>> {name = "aggregate"} !$omp target defaultmap(default: all) @@ -52,7 +52,7 @@ subroutine defaultmap_pointer_to() ! CHECK-NO-FPRIV: %[[MAP_1:.*]] = omp.map.info var_ptr({{.*}} : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>, i32) map_clauses(implicit, to) capture(ByRef) var_ptr_ptr({{.*}}) bounds({{.*}}) -> !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>> {name = ""} ! CHECK-FPRIV: %[[MAP_1:.*]] = omp.map.info var_ptr({{.*}} : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>, i32) map_clauses(implicit, to) capture(ByRef) var_ptr_ptr({{.*}}) bounds({{.*}}) -> !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>> {name = ""} -! CHECK: %[[MAP_2:.*]] = omp.map.info var_ptr({{.*}} : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>, !fir.box<!fir.ptr<!fir.array<?xi32>>>) map_clauses(implicit, to) capture(ByRef) members({{.*}}) -> !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>> {name = "arr_ptr"} +! CHECK: %[[MAP_2:.*]] = omp.map.info var_ptr({{.*}} : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>, !fir.box<!fir.ptr<!fir.array<?xi32>>>) map_clauses(always, implicit, to) capture(ByRef) members({{.*}}) -> !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>> {name = "arr_ptr"} ! CHECK-FPRIV: %[[MAP_3:.*]] = omp.map.info var_ptr({{.*}} : !fir.ref<i32>, i32) map_clauses(to) capture(ByCopy) -> !fir.ref<i32> ! CHECK-NO-FPRIV: %[[MAP_3:.*]] = omp.map.info var_ptr({{.*}} : !fir.ref<i32>, i32) map_clauses(implicit) capture(ByCopy) -> !fir.ref<i32> {name = "scalar_int"} !$omp target defaultmap(to: pointer) diff --git a/flang/test/Lower/OpenMP/delayed-privatization-private-firstprivate.f90 b/flang/test/Lower/OpenMP/delayed-privatization-private-firstprivate.f90 index ad53703..d79f97d 100644 --- a/flang/test/Lower/OpenMP/delayed-privatization-private-firstprivate.f90 +++ b/flang/test/Lower/OpenMP/delayed-privatization-private-firstprivate.f90 @@ -31,6 +31,6 @@ end subroutine ! CHECK: %[[VAR2_DECL:.*]]:2 = hlfir.declare %[[VAR2_ALLOC]] ! CHECK: omp.parallel private( -! CHECK-SAME: @[[VAR1_PRIVATIZER_SYM]] %[[VAR1_DECL]]#0 -> %{{[^,]+}}, +! CHECK-SAME: @[[VAR1_PRIVATIZER_SYM]] %[[VAR1_DECL]]#0 -> %{{[^,]+}}, ! CHECK-SAME: @[[VAR2_PRIVATIZER_SYM]] %[[VAR2_DECL]]#0 -> %{{.*}} : ! CHECK-SAME: !fir.ref<i32>, !fir.ref<i32>) { diff --git a/flang/test/Lower/OpenMP/delayed-privatization-reduction-byref.f90 b/flang/test/Lower/OpenMP/delayed-privatization-reduction-byref.f90 index 4b6a643..4c7b6ac 100644 --- a/flang/test/Lower/OpenMP/delayed-privatization-reduction-byref.f90 +++ b/flang/test/Lower/OpenMP/delayed-privatization-reduction-byref.f90 @@ -22,7 +22,7 @@ end subroutine ! CHECK-SAME: @[[PRIVATIZER_SYM:.*]] : i32 ! CHECK-LABEL: omp.declare_reduction -! CHECK-SAME: @[[REDUCTION_SYM:.*]] : !fir.ref<i32> alloc +! CHECK-SAME: @[[REDUCTION_SYM:.*]] : !fir.ref<i32> attributes {byref_element_type = i32} alloc ! CHECK-LABEL: _QPred_and_delayed_private ! CHECK: omp.parallel diff --git a/flang/test/Lower/OpenMP/depend-complex.f90 b/flang/test/Lower/OpenMP/depend-complex.f90 index 488696b..84c4cb5 100644 --- a/flang/test/Lower/OpenMP/depend-complex.f90 +++ b/flang/test/Lower/OpenMP/depend-complex.f90 @@ -5,7 +5,7 @@ subroutine depend_complex(z) ! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<complex<f32>> {fir.bindc_name = "z"}) { complex :: z ! CHECK: %[[VAL_0:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %[[VAL_0]] {uniq_name = "_QFdepend_complexEz"} : (!fir.ref<complex<f32>>, !fir.dscope) -> (!fir.ref<complex<f32>>, !fir.ref<complex<f32>>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %[[VAL_0]] arg {{[0-9]+}} {uniq_name = "_QFdepend_complexEz"} : (!fir.ref<complex<f32>>, !fir.dscope) -> (!fir.ref<complex<f32>>, !fir.ref<complex<f32>>) !$omp task depend(in:z%re) ! CHECK: %[[VAL_2:.*]] = hlfir.designate %[[VAL_1]]#0 real : (!fir.ref<complex<f32>>) -> !fir.ref<f32> ! CHECK: omp.task depend(taskdependin -> %[[VAL_2]] : !fir.ref<f32>) { diff --git a/flang/test/Lower/OpenMP/depend-substring.f90 b/flang/test/Lower/OpenMP/depend-substring.f90 index 5de11e0..eab6cd49 100644 --- a/flang/test/Lower/OpenMP/depend-substring.f90 +++ b/flang/test/Lower/OpenMP/depend-substring.f90 @@ -8,7 +8,7 @@ end ! CHECK-LABEL: func.func @_QPsubstring_0( ! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.box<!fir.ptr<!fir.char<1,?>>>> {fir.bindc_name = "c"}) { ! CHECK: %[[VAL_0:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %[[VAL_0]] {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFsubstring_0Ec"} : (!fir.ref<!fir.box<!fir.ptr<!fir.char<1,?>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.char<1,?>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.char<1,?>>>>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %[[VAL_0]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFsubstring_0Ec"} : (!fir.ref<!fir.box<!fir.ptr<!fir.char<1,?>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.char<1,?>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.char<1,?>>>>) ! CHECK: %[[VAL_2:.*]] = fir.load %[[VAL_1]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.char<1,?>>>> ! CHECK: %[[VAL_3:.*]] = fir.box_addr %[[VAL_2]] : (!fir.box<!fir.ptr<!fir.char<1,?>>>) -> !fir.ptr<!fir.char<1,?>> ! CHECK: %[[VAL_4:.*]] = fir.load %[[VAL_1]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.char<1,?>>>> @@ -41,7 +41,7 @@ end ! CHECK-LABEL: func.func @_QPsubstring_1( ! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.box<!fir.ptr<!fir.char<1,?>>>> {fir.bindc_name = "c"}) { ! CHECK: %[[VAL_0:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %[[VAL_0]] {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFsubstring_1Ec"} : (!fir.ref<!fir.box<!fir.ptr<!fir.char<1,?>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.char<1,?>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.char<1,?>>>>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %[[VAL_0]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFsubstring_1Ec"} : (!fir.ref<!fir.box<!fir.ptr<!fir.char<1,?>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.char<1,?>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.char<1,?>>>>) ! CHECK: %[[VAL_2:.*]] = fir.load %[[VAL_1]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.char<1,?>>>> ! CHECK: %[[VAL_3:.*]] = fir.box_addr %[[VAL_2]] : (!fir.box<!fir.ptr<!fir.char<1,?>>>) -> !fir.ptr<!fir.char<1,?>> ! CHECK: %[[VAL_4:.*]] = fir.load %[[VAL_1]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.char<1,?>>>> @@ -74,7 +74,7 @@ end ! CHECK-LABEL: func.func @_QPsubstring_2( ! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.box<!fir.ptr<!fir.char<1,?>>>> {fir.bindc_name = "c"}) { ! CHECK: %[[VAL_0:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %[[VAL_0]] {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFsubstring_2Ec"} : (!fir.ref<!fir.box<!fir.ptr<!fir.char<1,?>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.char<1,?>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.char<1,?>>>>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %[[VAL_0]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFsubstring_2Ec"} : (!fir.ref<!fir.box<!fir.ptr<!fir.char<1,?>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.char<1,?>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.char<1,?>>>>) ! CHECK: %[[VAL_2:.*]] = fir.load %[[VAL_1]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.char<1,?>>>> ! CHECK: %[[VAL_3:.*]] = fir.box_addr %[[VAL_2]] : (!fir.box<!fir.ptr<!fir.char<1,?>>>) -> !fir.ptr<!fir.char<1,?>> ! CHECK: %[[VAL_4:.*]] = fir.load %[[VAL_1]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.char<1,?>>>> @@ -98,7 +98,7 @@ end ! CHECK-LABEL: func.func @_QPsubstring_4( ! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.box<!fir.ptr<!fir.char<1,?>>>> {fir.bindc_name = "c"}) { ! CHECK: %[[VAL_0:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %[[VAL_0]] {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFsubstring_4Ec"} : (!fir.ref<!fir.box<!fir.ptr<!fir.char<1,?>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.char<1,?>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.char<1,?>>>>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %[[VAL_0]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFsubstring_4Ec"} : (!fir.ref<!fir.box<!fir.ptr<!fir.char<1,?>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.char<1,?>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.char<1,?>>>>) ! CHECK: %[[VAL_2:.*]] = fir.load %[[VAL_1]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.char<1,?>>>> ! CHECK: %[[VAL_3:.*]] = fir.box_addr %[[VAL_2]] : (!fir.box<!fir.ptr<!fir.char<1,?>>>) -> !fir.ptr<!fir.char<1,?>> ! CHECK: omp.task depend(taskdependout -> %[[VAL_3]] : !fir.ptr<!fir.char<1,?>>) { diff --git a/flang/test/Lower/OpenMP/derived-type-allocatable-map.f90 b/flang/test/Lower/OpenMP/derived-type-allocatable-map.f90 index d19a572..74aee4d 100644 --- a/flang/test/Lower/OpenMP/derived-type-allocatable-map.f90 +++ b/flang/test/Lower/OpenMP/derived-type-allocatable-map.f90 @@ -6,7 +6,7 @@ !CHECK: %[[MEMBER_COORD:.*]] = fir.coordinate_of %[[DECLARE]]#0, array_j : (!fir.ref<!fir.type<[[ONE_LAYER_TY]]>>) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> !CHECK: %[[MEMBER_BASE_ADDR:.*]] = fir.box_offset %[[MEMBER_COORD]] base_addr : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) -> !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>> !CHECK: %[[MAP_MEMBER_BASE_ADDR:.*]] = omp.map.info var_ptr(%[[MEMBER_COORD]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, i32) map_clauses(tofrom) capture(ByRef) var_ptr_ptr(%[[MEMBER_BASE_ADDR]] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) bounds(%[[BOUNDS]]) -> !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>> {{.*}} -!CHECK: %[[MAP_MEMBER_DESCRIPTOR:.*]] = omp.map.info var_ptr(%[[MEMBER_COORD]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.box<!fir.heap<!fir.array<?xi32>>>) map_clauses(to) capture(ByRef) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> {{.*}} +!CHECK: %[[MAP_MEMBER_DESCRIPTOR:.*]] = omp.map.info var_ptr(%[[MEMBER_COORD]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.box<!fir.heap<!fir.array<?xi32>>>) map_clauses(always, to) capture(ByRef) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> {{.*}} !CHECK: %[[MAP_PARENT:.*]] = omp.map.info var_ptr(%[[DECLARE]]#1 : !fir.ref<!fir.type<[[ONE_LAYER_TY]]>>, !fir.type<[[ONE_LAYER_TY]]>) map_clauses(tofrom) capture(ByRef) members(%[[MAP_MEMBER_DESCRIPTOR]], %[[MAP_MEMBER_BASE_ADDR]] : [4], [4, 0] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) -> !fir.ref<!fir.type<[[ONE_LAYER_TY]]>> {{{.*}} partial_map = true} !CHECK: omp.target map_entries(%[[MAP_PARENT]] -> %[[ARG0:.*]], %[[MAP_MEMBER_DESCRIPTOR]] -> %[[ARG1:.*]], %[[MAP_MEMBER_BASE_ADDR]] -> %[[ARG2:.*]] : !fir.ref<!fir.type<[[ONE_LAYER_TY]]>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) { !CHECK: %{{.*}}:2 = hlfir.declare %[[ARG0]] {{{.*}}} : (!fir.ref<!fir.type<[[ONE_LAYER_TY]]>>) -> (!fir.ref<!fir.type<[[ONE_LAYER_TY]]>>, !fir.ref<!fir.type<[[ONE_LAYER_TY]]>>) @@ -35,14 +35,14 @@ end subroutine !CHECK: %[[LOAD_DTYPE:.*]] = fir.load %[[DECLARE]]#0 : !fir.ref<!fir.box<!fir.heap<!fir.type<[[REC_TY]]>>>> !CHECK: %[[MEMBER_COORD:.*]] = fir.coordinate_of %[[LOAD_DTYPE]], array_j : (!fir.box<!fir.heap<!fir.type<[[REC_TY]]>>>) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> !CHECK: %[[MEMBER_BASE_ADDR:.*]] = fir.box_offset %[[MEMBER_COORD]] base_addr : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) -> !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>> -!CHECK: %[[MAP_MEMBER_BASE_ADDR:.*]] = omp.map.info var_ptr(%[[MEMBER_COORD]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, i32) map_clauses(tofrom) capture(ByRef) var_ptr_ptr(%[[MEMBER_BASE_ADDR]] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) bounds(%[[BOUNDS]]) -> !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>> {{.*}} -!CHECK: %[[MAP_MEMBER_DESC:.*]] = omp.map.info var_ptr(%[[MEMBER_COORD]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.box<!fir.heap<!fir.array<?xi32>>>) map_clauses(to) capture(ByRef) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> {{.*}} +!CHECK: %[[MAP_MEMBER_BASE_ADDR:.*]] = omp.map.info var_ptr(%[[MEMBER_COORD]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, i32) map_clauses(tofrom) capture(ByRef) var_ptr_ptr(%[[MEMBER_BASE_ADDR]] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) bounds(%[[BOUNDS]]) -> !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>> {{.*}} +!CHECK: %[[MAP_MEMBER_DESC:.*]] = omp.map.info var_ptr(%[[MEMBER_COORD]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.box<!fir.heap<!fir.array<?xi32>>>) map_clauses(always, to) capture(ByRef) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> {{.*}} !CHECK: %[[LOAD_DTYPE:.*]] = fir.load %[[DECLARE]]#0 : !fir.ref<!fir.box<!fir.heap<!fir.type<[[REC_TY]]>>>> !CHECK: %[[REGULAR_MEMBER:.*]] = fir.coordinate_of %[[LOAD_DTYPE]], k : (!fir.box<!fir.heap<!fir.type<[[REC_TY]]>>>) -> !fir.ref<i32> !CHECK: %[[MAP_REGULAR_MEMBER:.*]] = omp.map.info var_ptr(%[[REGULAR_MEMBER]] : !fir.ref<i32>, i32) map_clauses(tofrom) capture(ByRef) -> !fir.ref<i32> {{.*}} !CHECK: %[[DTYPE_BASE_ADDR:.*]] = fir.box_offset %[[DECLARE]]#1 base_addr : (!fir.ref<!fir.box<!fir.heap<!fir.type<[[REC_TY]]>>>>) -> !fir.llvm_ptr<!fir.ref<!fir.type<[[REC_TY]]>>> -!CHECK: %[[MAP_DTYPE_BASE_ADDR:.*]] = omp.map.info var_ptr(%[[DECLARE]]#1 : !fir.ref<!fir.box<!fir.heap<!fir.type<[[REC_TY]]>>>>, !fir.type<[[REC_TY]]>) map_clauses(tofrom) capture(ByRef) var_ptr_ptr(%[[DTYPE_BASE_ADDR]] : !fir.llvm_ptr<!fir.ref<!fir.type<[[REC_TY]]>>>) -> !fir.llvm_ptr<!fir.ref<!fir.type<[[REC_TY]]>>> {{.*}} -!CHECK: %[[MAP_DTYPE_DESC:.*]] = omp.map.info var_ptr(%[[DECLARE]]#1 : !fir.ref<!fir.box<!fir.heap<!fir.type<[[REC_TY]]>>>>, !fir.box<!fir.heap<!fir.type<[[REC_TY]]>>>) map_clauses(to) capture(ByRef) members(%[[MAP_DTYPE_BASE_ADDR]], %[[MAP_MEMBER_DESC]], %[[MAP_MEMBER_BASE_ADDR]], %[[MAP_REGULAR_MEMBER]] : [0], [0, 4], [0, 4, 0], [0, 5] : !fir.llvm_ptr<!fir.ref<!fir.type<[[REC_TY]]>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>, !fir.ref<i32>) -> !fir.ref<!fir.box<!fir.heap<!fir.type<[[REC_TY]]>>>> {{.*}} +!CHECK: %[[MAP_DTYPE_BASE_ADDR:.*]] = omp.map.info var_ptr(%[[DECLARE]]#1 : !fir.ref<!fir.box<!fir.heap<!fir.type<[[REC_TY]]>>>>, !fir.type<[[REC_TY]]>) map_clauses(tofrom) capture(ByRef) var_ptr_ptr(%[[DTYPE_BASE_ADDR]] : !fir.llvm_ptr<!fir.ref<!fir.type<[[REC_TY]]>>>) -> !fir.llvm_ptr<!fir.ref<!fir.type<[[REC_TY]]>>> {{.*}} +!CHECK: %[[MAP_DTYPE_DESC:.*]] = omp.map.info var_ptr(%[[DECLARE]]#1 : !fir.ref<!fir.box<!fir.heap<!fir.type<[[REC_TY]]>>>>, !fir.box<!fir.heap<!fir.type<[[REC_TY]]>>>) map_clauses(always, to) capture(ByRef) members(%[[MAP_DTYPE_BASE_ADDR]], %[[MAP_MEMBER_DESC]], %[[MAP_MEMBER_BASE_ADDR]], %[[MAP_REGULAR_MEMBER]] : [0], [0, 4], [0, 4, 0], [0, 5] : !fir.llvm_ptr<!fir.ref<!fir.type<[[REC_TY]]>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>, !fir.ref<i32>) -> !fir.ref<!fir.box<!fir.heap<!fir.type<[[REC_TY]]>>>> {{.*}} !CHECK: omp.target map_entries(%[[MAP_DTYPE_DESC]] -> %[[ARG0:.*]], %[[MAP_DTYPE_BASE_ADDR]] -> %[[ARG1:.*]], %[[MAP_MEMBER_DESC]] -> %[[ARG2:.*]], %[[MAP_MEMBER_BASE_ADDR]] -> %[[ARG3:.*]], %[[MAP_REGULAR_MEMBER]] -> %[[ARG4:.*]] : !fir.ref<!fir.box<!fir.heap<!fir.type<[[REC_TY]]>>>>, !fir.llvm_ptr<!fir.ref<!fir.type<[[REC_TY]]>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>, !fir.ref<i32>) { !CHECK: %{{.*}}:2 = hlfir.declare %[[ARG0]] {{{.*}}} : (!fir.ref<!fir.box<!fir.heap<!fir.type<[[REC_TY]]>>>>) -> (!fir.ref<!fir.box<!fir.heap<!fir.type<[[REC_TY]]>>>>, !fir.ref<!fir.box<!fir.heap<!fir.type<[[REC_TY]]>>>>) subroutine alloca_dtype_op_block_add() @@ -74,14 +74,14 @@ end subroutine !CHECK: %[[NESTED_MEMBER_COORD:.*]] = fir.coordinate_of %[[NESTED_DTYPE_COORD]], array_k : (!fir.ref<!fir.type<[[REC_TY2]]>>) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> !CHECK: %[[NESTED_MEMBER_BASE_ADDR:.*]] = fir.box_offset %[[NESTED_MEMBER_COORD]] base_addr : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) -> !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>> !CHECK: %[[MAP_NESTED_MEMBER_BASE_ADDR:.*]] = omp.map.info var_ptr(%[[NESTED_MEMBER_COORD]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, i32) map_clauses(tofrom) capture(ByRef) var_ptr_ptr(%[[NESTED_MEMBER_BASE_ADDR]] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) bounds(%[[BOUNDS]]) -> !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>> {{.*}} -!CHECK: %[[MAP_NESTED_MEMBER_COORD:.*]] = omp.map.info var_ptr(%[[NESTED_MEMBER_COORD]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.box<!fir.heap<!fir.array<?xi32>>>) map_clauses(to) capture(ByRef) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> {{.*}} +!CHECK: %[[MAP_NESTED_MEMBER_COORD:.*]] = omp.map.info var_ptr(%[[NESTED_MEMBER_COORD]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.box<!fir.heap<!fir.array<?xi32>>>) map_clauses(always, to) capture(ByRef) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> {{.*}} !CHECK: %[[LOAD:.*]] = fir.load %[[DECLARE]]#0 : !fir.ref<!fir.box<!fir.heap<!fir.type<[[REC_TY]]>}>>>> !CHECK: %[[NESTED_DTYPE_COORD:.*]] = fir.coordinate_of %[[LOAD]], nest : (!fir.box<!fir.heap<!fir.type<[[REC_TY]]>}>>>) -> !fir.ref<!fir.type<[[REC_TY2]]>> !CHECK: %[[REGULAR_NESTED_MEMBER_COORD:.*]] = fir.coordinate_of %[[NESTED_DTYPE_COORD]], k : (!fir.ref<!fir.type<[[REC_TY2]]>>) -> !fir.ref<i32> !CHECK: %[[MAP_REGULAR_NESTED_MEMBER:.*]] = omp.map.info var_ptr(%[[REGULAR_NESTED_MEMBER_COORD]] : !fir.ref<i32>, i32) map_clauses(tofrom) capture(ByRef) -> !fir.ref<i32> {{.*}} !CHECK: %[[DTYPE_BASE_ADDR:.*]] = fir.box_offset %[[DECLARE]]#1 base_addr : (!fir.ref<!fir.box<!fir.heap<!fir.type<[[REC_TY]]>}>>>>) -> !fir.llvm_ptr<!fir.ref<!fir.type<[[REC_TY]]>}>>> !CHECK: %[[MAP_DTYPE_BASE_ADDR:.*]] = omp.map.info var_ptr(%[[DECLARE]]#1 : !fir.ref<!fir.box<!fir.heap<!fir.type<[[REC_TY]]>}>>>>, !fir.type<[[REC_TY]]>}>) map_clauses(tofrom) capture(ByRef) var_ptr_ptr(%[[DTYPE_BASE_ADDR]] : !fir.llvm_ptr<!fir.ref<!fir.type<[[REC_TY]]>}>>>) -> !fir.llvm_ptr<!fir.ref<!fir.type<[[REC_TY]]>}>>> {{.*}} -!CHECK: %[[MAP_DTYPE:.*]] = omp.map.info var_ptr(%[[DECLARE]]#1 : !fir.ref<!fir.box<!fir.heap<!fir.type<[[REC_TY]]>}>>>>, !fir.box<!fir.heap<!fir.type<[[REC_TY]]>}>>>) map_clauses(to) capture(ByRef) members(%[[MAP_DTYPE_BASE_ADDR]], %[[MAP_NESTED_MEMBER_COORD]], %[[MAP_NESTED_MEMBER_BASE_ADDR]], %[[MAP_REGULAR_NESTED_MEMBER]] : [0], [0, 6, 2], [0, 6, 2, 0], [0, 6, 3] : !fir.llvm_ptr<!fir.ref<!fir.type<[[REC_TY]]>}>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>, !fir.ref<i32>) -> !fir.ref<!fir.box<!fir.heap<!fir.type<[[REC_TY]]>}>>>> {{.*}} +!CHECK: %[[MAP_DTYPE:.*]] = omp.map.info var_ptr(%[[DECLARE]]#1 : !fir.ref<!fir.box<!fir.heap<!fir.type<[[REC_TY]]>}>>>>, !fir.box<!fir.heap<!fir.type<[[REC_TY]]>}>>>) map_clauses(always, to) capture(ByRef) members(%[[MAP_DTYPE_BASE_ADDR]], %[[MAP_NESTED_MEMBER_COORD]], %[[MAP_NESTED_MEMBER_BASE_ADDR]], %[[MAP_REGULAR_NESTED_MEMBER]] : [0], [0, 6, 2], [0, 6, 2, 0], [0, 6, 3] : !fir.llvm_ptr<!fir.ref<!fir.type<[[REC_TY]]>}>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>, !fir.ref<i32>) -> !fir.ref<!fir.box<!fir.heap<!fir.type<[[REC_TY]]>}>>>> {{.*}} !CHECK: omp.target map_entries(%[[MAP_DTYPE]] -> %[[ARG0:.*]], %[[MAP_DTYPE_BASE_ADDR]] -> %[[ARG1:.*]], %[[MAP_NESTED_MEMBER_COORD]] -> %[[ARG2:.*]], %[[MAP_NESTED_MEMBER_BASE_ADDR]] -> %[[ARG3:.*]], %[[MAP_REGULAR_NESTED_MEMBER]] -> %[[ARG4:.*]] : !fir.ref<!fir.box<!fir.heap<!fir.type<[[REC_TY]]>}>>>>, !fir.llvm_ptr<!fir.ref<!fir.type<[[REC_TY]]>}>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>, !fir.ref<i32>) { !CHECK: %{{.*}}:2 = hlfir.declare %[[ARG0]] {{.*}} : (!fir.ref<!fir.box<!fir.heap<!fir.type<[[REC_TY]]>}>>>>) -> (!fir.ref<!fir.box<!fir.heap<!fir.type<[[REC_TY]]>}>>>>, !fir.ref<!fir.box<!fir.heap<!fir.type<[[REC_TY]]>}>>>>) subroutine alloca_nest_dype_map_op_block_add() @@ -120,7 +120,7 @@ end subroutine !CHECK: %[[NESTED_MEMBER_COORD:.*]] = fir.coordinate_of %[[NESTED_DTYPE_COORD]], array_k : (!fir.ref<!fir.type<[[REC_TY2]]>>) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> !CHECK: %[[NESTED_MEMBER_BASE_ADDR:.*]] = fir.box_offset %[[NESTED_MEMBER_COORD]] base_addr : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) -> !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>> !CHECK: %[[MAP_NESTED_MEMBER_BASE_ADDR:.*]] = omp.map.info var_ptr(%[[NESTED_MEMBER_COORD]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, i32) map_clauses(tofrom) capture(ByRef) var_ptr_ptr(%[[NESTED_MEMBER_BASE_ADDR]] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) bounds(%[[BOUNDS]]) -> !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>> {{.*}} -!CHECK: %[[MAP_NESTED_MEMBER_DESC:.*]] = omp.map.info var_ptr(%[[NESTED_MEMBER_COORD]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.box<!fir.heap<!fir.array<?xi32>>>) map_clauses(to) capture(ByRef) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> {{.*}} +!CHECK: %[[MAP_NESTED_MEMBER_DESC:.*]] = omp.map.info var_ptr(%[[NESTED_MEMBER_COORD]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.box<!fir.heap<!fir.array<?xi32>>>) map_clauses(always, to) capture(ByRef) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> {{.*}} !CHECK: %[[MAP_PARENT:.*]] = omp.map.info var_ptr(%[[DECLARE]]#1 : !fir.ref<!fir.type<[[REC_TY]]>>, !fir.type<[[REC_TY]]>) map_clauses(tofrom) capture(ByRef) members(%[[MAP_NESTED_MEMBER_DESC]], %[[MAP_NESTED_MEMBER_BASE_ADDR]] : [6, 2], [6, 2, 0] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) -> !fir.ref<!fir.type<[[REC_TY]]>> {{.*}} !CHECK: omp.target map_entries(%[[MAP_PARENT]] -> %[[ARG0:.*]], %[[MAP_NESTED_MEMBER_DESC]] -> %[[ARG1:.*]], %[[MAP_NESTED_MEMBER_BASE_ADDR]] -> %[[ARG2:.*]] : !fir.ref<!fir.type<[[REC_TY]]>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) { !CHECK: %{{.*}}:2 = hlfir.declare %[[ARG0]] {{.*}} : (!fir.ref<!fir.type<[[REC_TY]]>>) -> (!fir.ref<!fir.type<[[REC_TY]]>>, !fir.ref<!fir.type<[[REC_TY]]>>) diff --git a/flang/test/Lower/OpenMP/derived-type-map.f90 b/flang/test/Lower/OpenMP/derived-type-map.f90 index 279cdde..fb4b88a 100644 --- a/flang/test/Lower/OpenMP/derived-type-map.f90 +++ b/flang/test/Lower/OpenMP/derived-type-map.f90 @@ -1,5 +1,6 @@ !RUN: %flang_fc1 -emit-hlfir -fopenmp %s -o - | FileCheck %s +!CHECK: omp.declare_mapper @[[MAPPER1:_QQFmaptype_derived_implicit_allocatablescalar_and_array_omp_default_mapper]] : !fir.type<_QFmaptype_derived_implicit_allocatableTscalar_and_array{real:f32,array:!fir.array<10xi32>,int:i32}> { !CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.type<_QFmaptype_derived_implicitTscalar_and_array{real:f32,array:!fir.array<10xi32>,int:i32}> {bindc_name = "scalar_arr", uniq_name = "_QFmaptype_derived_implicitEscalar_arr"} !CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %[[ALLOCA]] {uniq_name = "_QFmaptype_derived_implicitEscalar_arr"} : (!fir.ref<!fir.type<_QFmaptype_derived_implicitTscalar_and_array{real:f32,array:!fir.array<10xi32>,int:i32}>>) -> (!fir.ref<!fir.type<_QFmaptype_derived_implicitTscalar_and_array{real:f32,array:!fir.array<10xi32>,int:i32}>>, !fir.ref<!fir.type<_QFmaptype_derived_implicitTscalar_and_array{real:f32,array:!fir.array<10xi32>,int:i32}>>) @@ -11,13 +12,33 @@ subroutine mapType_derived_implicit integer(4) :: array(10) integer(4) :: int end type scalar_and_array - type(scalar_and_array) :: scalar_arr - + type(scalar_and_array) :: scalar_arr + !$omp target scalar_arr%int = 1 !$omp end target end subroutine mapType_derived_implicit +!CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.box<!fir.heap<!fir.type<_QFmaptype_derived_implicit_allocatableTscalar_and_array{real:f32,array:!fir.array<10xi32>,int:i32}>>> {bindc_name = "scalar_arr", uniq_name = "_QFmaptype_derived_implicit_allocatableEscalar_arr"} +!CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %[[ALLOCA]] {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFmaptype_derived_implicit_allocatableEscalar_arr"} : (!fir.ref<!fir.box<!fir.heap<!fir.type<_QFmaptype_derived_implicit_allocatableTscalar_and_array{real:f32,array:!fir.array<10xi32>,int:i32}>>>>) -> (!fir.ref<!fir.box<!fir.heap<!fir.type<_QFmaptype_derived_implicit_allocatableTscalar_and_array{real:f32,array:!fir.array<10xi32>,int:i32}>>>>, !fir.ref<!fir.box<!fir.heap<!fir.type<_QFmaptype_derived_implicit_allocatableTscalar_and_array{real:f32,array:!fir.array<10xi32>,int:i32}>>>>) +!CHECK: %[[BOX_ADDR:.*]] = fir.box_offset %[[DECLARE]]#1 base_addr : (!fir.ref<!fir.box<!fir.heap<!fir.type<_QFmaptype_derived_implicit_allocatableTscalar_and_array{real:f32,array:!fir.array<10xi32>,int:i32}>>>>) -> !fir.llvm_ptr<!fir.ref<!fir.type<_QFmaptype_derived_implicit_allocatableTscalar_and_array{real:f32,array:!fir.array<10xi32>,int:i32}>>> +!CHECK: %[[BASE_MAP:.*]] = omp.map.info var_ptr(%[[DECLARE]]#1 : !fir.ref<!fir.box<!fir.heap<!fir.type<_QFmaptype_derived_implicit_allocatableTscalar_and_array{real:f32,array:!fir.array<10xi32>,int:i32}>>>>, !fir.type<_QFmaptype_derived_implicit_allocatableTscalar_and_array{real:f32,array:!fir.array<10xi32>,int:i32}>) map_clauses(implicit, tofrom) capture(ByRef) var_ptr_ptr(%[[BOX_ADDR]] : !fir.llvm_ptr<!fir.ref<!fir.type<_QFmaptype_derived_implicit_allocatableTscalar_and_array{real:f32,array:!fir.array<10xi32>,int:i32}>>>) mapper(@[[MAPPER1]]) -> !fir.llvm_ptr<!fir.ref<!fir.type<_QFmaptype_derived_implicit_allocatableTscalar_and_array{real:f32,array:!fir.array<10xi32>,int:i32}>>> {name = ""} +!CHECK: %[[DESC_MAP:.*]] = omp.map.info var_ptr(%[[DECLARE]]#1 : !fir.ref<!fir.box<!fir.heap<!fir.type<_QFmaptype_derived_implicit_allocatableTscalar_and_array{real:f32,array:!fir.array<10xi32>,int:i32}>>>>, !fir.box<!fir.heap<!fir.type<_QFmaptype_derived_implicit_allocatableTscalar_and_array{real:f32,array:!fir.array<10xi32>,int:i32}>>>) map_clauses(always, implicit, to) capture(ByRef) members(%[[BASE_MAP]] : [0] : !fir.llvm_ptr<!fir.ref<!fir.type<_QFmaptype_derived_implicit_allocatableTscalar_and_array{real:f32,array:!fir.array<10xi32>,int:i32}>>>) -> !fir.ref<!fir.box<!fir.heap<!fir.type<_QFmaptype_derived_implicit_allocatableTscalar_and_array{real:f32,array:!fir.array<10xi32>,int:i32}>>>> {name = "scalar_arr"} +!CHECK: omp.target map_entries(%[[DESC_MAP]] -> %[[ARG0:.*]], %[[BASE_MAP]] -> %[[ARG1:.*]] : !fir.ref<!fir.box<!fir.heap<!fir.type<_QFmaptype_derived_implicit_allocatableTscalar_and_array{real:f32,array:!fir.array<10xi32>,int:i32}>>>>, !fir.llvm_ptr<!fir.ref<!fir.type<_QFmaptype_derived_implicit_allocatableTscalar_and_array{real:f32,array:!fir.array<10xi32>,int:i32}>>>) { +subroutine mapType_derived_implicit_allocatable + type :: scalar_and_array + real(4) :: real + integer(4) :: array(10) + integer(4) :: int + end type scalar_and_array + type(scalar_and_array), allocatable :: scalar_arr + + allocate (scalar_arr) + !$omp target + scalar_arr%int = 1 + !$omp end target +end subroutine mapType_derived_implicit_allocatable + !CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.type<_QFmaptype_derived_explicitTscalar_and_array{real:f32,array:!fir.array<10xi32>,int:i32}> {bindc_name = "scalar_arr", uniq_name = "_QFmaptype_derived_explicitEscalar_arr"} !CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %[[ALLOCA]] {uniq_name = "_QFmaptype_derived_explicitEscalar_arr"} : (!fir.ref<!fir.type<_QFmaptype_derived_explicitTscalar_and_array{real:f32,array:!fir.array<10xi32>,int:i32}>>) -> (!fir.ref<!fir.type<_QFmaptype_derived_explicitTscalar_and_array{real:f32,array:!fir.array<10xi32>,int:i32}>>, !fir.ref<!fir.type<_QFmaptype_derived_explicitTscalar_and_array{real:f32,array:!fir.array<10xi32>,int:i32}>>) !CHECK: %[[MAP:.*]] = omp.map.info var_ptr(%[[DECLARE]]#1 : !fir.ref<!fir.type<_QFmaptype_derived_explicitTscalar_and_array{real:f32,array:!fir.array<10xi32>,int:i32}>>, !fir.type<_QFmaptype_derived_explicitTscalar_and_array{real:f32,array:!fir.array<10xi32>,int:i32}>) map_clauses(tofrom) capture(ByRef) -> !fir.ref<!fir.type<_QFmaptype_derived_explicitTscalar_and_array{real:f32,array:!fir.array<10xi32>,int:i32}>> {name = "scalar_arr"} @@ -28,8 +49,8 @@ subroutine mapType_derived_explicit integer(4) :: array(10) integer(4) :: int end type scalar_and_array - type(scalar_and_array) :: scalar_arr - + type(scalar_and_array) :: scalar_arr + !$omp target map(tofrom: scalar_arr) scalar_arr%int = 1 !$omp end target @@ -48,8 +69,8 @@ subroutine mapType_derived_explicit_single_member integer(4) :: array(10) integer(4) :: int end type scalar_and_array - type(scalar_and_array) :: scalar_arr - + type(scalar_and_array) :: scalar_arr + !$omp target map(tofrom: scalar_arr%array) scalar_arr%array(1) = 1 !$omp end target @@ -69,13 +90,13 @@ subroutine mapType_derived_explicit_multiple_members integer(4) :: array(10) integer(4) :: int end type scalar_and_array - type(scalar_and_array) :: scalar_arr - + type(scalar_and_array) :: scalar_arr + !$omp target map(tofrom: scalar_arr%int, scalar_arr%real) scalar_arr%int = 1 !$omp end target end subroutine mapType_derived_explicit_multiple_members - + !CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.type<_QFmaptype_derived_explicit_member_with_boundsTscalar_and_array{real:f32,array:!fir.array<10xi32>,int:i32}> {bindc_name = "scalar_arr", uniq_name = "_QFmaptype_derived_explicit_member_with_boundsEscalar_arr"} !CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %[[ALLOCA]] {uniq_name = "_QFmaptype_derived_explicit_member_with_boundsEscalar_arr"} : (!fir.ref<!fir.type<_QFmaptype_derived_explicit_member_with_boundsTscalar_and_array{real:f32,array:!fir.array<10xi32>,int:i32}>>) -> (!fir.ref<!fir.type<_QFmaptype_derived_explicit_member_with_boundsTscalar_and_array{real:f32,array:!fir.array<10xi32>,int:i32}>>, !fir.ref<!fir.type<_QFmaptype_derived_explicit_member_with_boundsTscalar_and_array{real:f32,array:!fir.array<10xi32>,int:i32}>>) !CHECK: %[[MEMBER:.*]] = hlfir.designate %[[DECLARE]]#0{"array"} shape %{{.*}} : (!fir.ref<!fir.type<_QFmaptype_derived_explicit_member_with_boundsTscalar_and_array{real:f32,array:!fir.array<10xi32>,int:i32}>>, !fir.shape<1>) -> !fir.ref<!fir.array<10xi32>> @@ -92,8 +113,8 @@ subroutine mapType_derived_explicit_member_with_bounds integer(4) :: array(10) integer(4) :: int end type scalar_and_array - type(scalar_and_array) :: scalar_arr - + type(scalar_and_array) :: scalar_arr + !$omp target map(tofrom: scalar_arr%array(2:5)) scalar_arr%array(3) = 3 !$omp end target @@ -120,8 +141,8 @@ subroutine mapType_derived_nested_explicit_single_member type(nested) :: nest integer(4) :: int end type scalar_and_array - - type(scalar_and_array) :: scalar_arr + + type(scalar_and_array) :: scalar_arr !$omp target map(tofrom: scalar_arr%nest%array) scalar_arr%nest%array(1) = 1 @@ -152,7 +173,7 @@ subroutine mapType_derived_nested_explicit_multiple_members integer(4) :: int end type scalar_and_array - type(scalar_and_array) :: scalar_arr + type(scalar_and_array) :: scalar_arr !$omp target map(tofrom: scalar_arr%nest%int, scalar_arr%nest%real) scalar_arr%nest%int = 1 @@ -184,9 +205,9 @@ subroutine mapType_derived_nested_explicit_member_with_bounds type(nested) :: nest integer(4) :: int end type scalar_and_array - - type(scalar_and_array) :: scalar_arr - + + type(scalar_and_array) :: scalar_arr + !$omp target map(tofrom: scalar_arr%nest%array(2:5)) scalar_arr%nest%array(3) = 3 !$omp end target @@ -218,7 +239,7 @@ subroutine mapType_multilpe_derived_nested_explicit_member type(nested) :: nest integer(4) :: int end type scalar_and_array - + type(scalar_and_array) :: scalar_arr1 type(scalar_and_array) :: scalar_arr2 diff --git a/flang/test/Lower/OpenMP/distribute.f90 b/flang/test/Lower/OpenMP/distribute.f90 index ea57d35..bd0e220 100644 --- a/flang/test/Lower/OpenMP/distribute.f90 +++ b/flang/test/Lower/OpenMP/distribute.f90 @@ -104,7 +104,7 @@ subroutine distribute_allocate() ! CHECK-NEXT: omp.loop_nest do i = 1, 10 x = i - ! CHECK: omp.yield + ! CHECK: omp.yield end do !$omp end distribute diff --git a/flang/test/Lower/OpenMP/do-simd-firstprivate-lastprivate.f90 b/flang/test/Lower/OpenMP/do-simd-firstprivate-lastprivate.f90 new file mode 100644 index 0000000..4294099 --- /dev/null +++ b/flang/test/Lower/OpenMP/do-simd-firstprivate-lastprivate.f90 @@ -0,0 +1,89 @@ +! Test for DO SIMD with the same variable in both firstprivate and lastprivate clauses +! This tests the fix for issue #168306 + +! RUN: %flang_fc1 -fopenmp -mmlir --enable-delayed-privatization-staging=true -emit-hlfir %s -o - | FileCheck %s + +! Test case 1: Basic test with firstprivate + lastprivate on same variable +! CHECK-LABEL: func.func @_QPdo_simd_first_last_same_var +subroutine do_simd_first_last_same_var() + integer :: a + integer :: i + a = 10 + + ! CHECK: omp.wsloop + ! CHECK-SAME: private(@{{.*}}firstprivate{{.*}} %{{.*}} -> %[[FIRSTPRIV_A:.*]], @{{.*}}private{{.*}} %{{.*}} -> %[[PRIV_I:.*]] : !fir.ref<i32>, !fir.ref<i32>) + ! CHECK-NEXT: omp.simd + ! CHECK-NOT: private + ! CHECK-NEXT: omp.loop_nest (%[[IV:.*]]) : i32 + !$omp do simd firstprivate(a) lastprivate(a) + do i = 1, 1 + ! CHECK: %[[FIRSTPRIV_A_DECL:.*]]:2 = hlfir.declare %[[FIRSTPRIV_A]] + ! CHECK: %[[PRIV_I_DECL:.*]]:2 = hlfir.declare %[[PRIV_I]] + ! The private copy should be initialized from firstprivate (value 10) + ! and then modified to 20 + a = 20 + end do + !$omp end do simd + ! After the loop, 'a' should be 20 due to lastprivate +end subroutine do_simd_first_last_same_var + +! Test case 2: Test with lastprivate and firstprivate in reverse order +! CHECK-LABEL: func.func @_QPdo_simd_last_first_reverse +subroutine do_simd_last_first_reverse() + integer :: a + integer :: i + a = 10 + + ! CHECK: omp.wsloop + ! CHECK-SAME: private(@{{.*}}firstprivate{{.*}} %{{.*}} -> %[[FIRSTPRIV_A:.*]], @{{.*}}private{{.*}} %{{.*}} -> %[[PRIV_I:.*]] : !fir.ref<i32>, !fir.ref<i32>) + ! CHECK-NEXT: omp.simd + ! CHECK-NOT: private + !$omp do simd lastprivate(a) firstprivate(a) + do i = 1, 1 + a = 20 + end do + !$omp end do simd +end subroutine do_simd_last_first_reverse + +! Test case 3: Multiple variables with mixed privatization +! CHECK-LABEL: func.func @_QPdo_simd_multiple_vars +subroutine do_simd_multiple_vars() + integer :: a, b, c + integer :: i + a = 10 + b = 20 + c = 30 + + ! CHECK: omp.wsloop + ! CHECK-SAME: private(@{{.*}}firstprivate{{.*}} %{{.*}} -> %{{.*}}, @{{.*}}firstprivate{{.*}} %{{.*}} -> %{{.*}}, @{{.*}}private{{.*}} %{{.*}} -> %{{.*}} : !fir.ref<i32>, !fir.ref<i32>, !fir.ref<i32>) + ! CHECK-NEXT: omp.simd + ! CHECK-NOT: private + !$omp do simd firstprivate(a, b) lastprivate(a) private(c) + do i = 1, 5 + a = a + 1 + b = b + 1 + c = i + end do + !$omp end do simd +end subroutine do_simd_multiple_vars + +! Test case 4: Reproducer from issue #168306 +! CHECK-LABEL: func.func @_QPissue_168306_reproducer +subroutine issue_168306_reproducer() + integer :: a + integer :: i + a = 10 + + ! CHECK: omp.wsloop + ! CHECK-SAME: private(@{{.*}}firstprivate{{.*}} %{{.*}} -> %[[FIRSTPRIV_A:.*]], @{{.*}}private{{.*}} %{{.*}} -> %[[PRIV_I:.*]] : !fir.ref<i32>, !fir.ref<i32>) + ! CHECK-NEXT: omp.simd + ! CHECK-NOT: private + !$omp do simd lastprivate(a) firstprivate(a) + do i = 1, 1 + ! Inside the loop, 'a' should start at 10 (from firstprivate) + ! This is the key behavior that was broken + a = 20 + end do + !$omp end do simd + ! After the loop, 'a' should be 20 (from lastprivate) +end subroutine issue_168306_reproducer diff --git a/flang/test/Lower/OpenMP/dynamic-len-char-bounds-gen.f90 b/flang/test/Lower/OpenMP/dynamic-len-char-bounds-gen.f90 new file mode 100644 index 0000000..07b4f04 --- /dev/null +++ b/flang/test/Lower/OpenMP/dynamic-len-char-bounds-gen.f90 @@ -0,0 +1,19 @@ +! RUN: %flang_fc1 -emit-hlfir -fopenmp -o - %s 2>&1 | FileCheck %s + +subroutine TestCharLenBounds(clen) + + character(len=*) :: clen + + !$omp target map(clen) + !$omp end target +end subroutine TestCharLenBounds + +!CHECK: %[[DUMMY:.*]] = fir.dummy_scope : !fir.dscope +!CHECK: %[[UNBOX:.*]]:2 = fir.unboxchar %{{.*}} : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index) +!CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %[[UNBOX]]#0 typeparams %2#1 dummy_scope %[[DUMMY]] arg {{[0-9]+}} {uniq_name = "_QFtestcharlenboundsEclen"} : (!fir.ref<!fir.char<1,?>>, index, !fir.dscope) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>) +!CHECK: %[[LB_START_IDX:.*]] = arith.constant 0 : index +!CHECK: %[[STRIDE:.*]] = arith.constant 1 : index +!CHECK: %[[EXTENT:.*]]:2 = fir.unboxchar %[[DECLARE]]#0 : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index) +!CHECK: %[[UB:.*]] = arith.subi %[[EXTENT]]#1, %[[STRIDE]] : index +!CHECK: %[[BOUNDS:.*]] = omp.map.bounds lower_bound(%[[LB_START_IDX]] : index) upper_bound(%[[UB]] : index) extent(%[[EXTENT]]#1 : index) stride(%[[STRIDE]] : index) start_idx(%[[LB_START_IDX]] : index) {stride_in_bytes = true} +!CHECK: %{{.*}} = omp.map.info {{.*}} bounds(%[[BOUNDS]]) {{.*}} diff --git a/flang/test/Lower/OpenMP/flush.f90 b/flang/test/Lower/OpenMP/flush.f90 index 03e9f3b..f9d90e3 100644 --- a/flang/test/Lower/OpenMP/flush.f90 +++ b/flang/test/Lower/OpenMP/flush.f90 @@ -7,9 +7,9 @@ subroutine flush_standalone(a, b, c) integer, intent(inout) :: a, b, c -!CHECK: %[[A:.*]]:2 = hlfir.declare %[[ARG_A]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<intent_inout>, uniq_name = "_QFflush_standaloneEa"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) -!CHECK: %[[B:.*]]:2 = hlfir.declare %[[ARG_B]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<intent_inout>, uniq_name = "_QFflush_standaloneEb"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) -!CHECK: %[[C:.*]]:2 = hlfir.declare %[[ARG_C]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<intent_inout>, uniq_name = "_QFflush_standaloneEc"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: %[[A:.*]]:2 = hlfir.declare %[[ARG_A]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<intent_inout>, uniq_name = "_QFflush_standaloneEa"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: %[[B:.*]]:2 = hlfir.declare %[[ARG_B]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<intent_inout>, uniq_name = "_QFflush_standaloneEb"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: %[[C:.*]]:2 = hlfir.declare %[[ARG_C]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<intent_inout>, uniq_name = "_QFflush_standaloneEc"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) !CHECK: omp.flush(%[[A]]#0, %[[B]]#0, %[[C]]#0 : !fir.ref<i32>, !fir.ref<i32>, !fir.ref<i32>) !CHECK: omp.flush !$omp flush(a,b,c) @@ -21,9 +21,9 @@ end subroutine flush_standalone !CHECK-SAME: %[[ARG_A:.*]]: !fir.ref<i32> {fir.bindc_name = "a"}, %[[ARG_B:.*]]: !fir.ref<i32> {fir.bindc_name = "b"}, %[[ARG_C:.*]]: !fir.ref<i32> {fir.bindc_name = "c"}) subroutine flush_parallel(a, b, c) integer, intent(inout) :: a, b, c -!CHECK: %[[A:.*]]:2 = hlfir.declare %[[ARG_A]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<intent_inout>, uniq_name = "_QFflush_parallelEa"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) -!CHECK: %[[B:.*]]:2 = hlfir.declare %[[ARG_B]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<intent_inout>, uniq_name = "_QFflush_parallelEb"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) -!CHECK: %[[C:.*]]:2 = hlfir.declare %[[ARG_C]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<intent_inout>, uniq_name = "_QFflush_parallelEc"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: %[[A:.*]]:2 = hlfir.declare %[[ARG_A]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<intent_inout>, uniq_name = "_QFflush_parallelEa"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: %[[B:.*]]:2 = hlfir.declare %[[ARG_B]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<intent_inout>, uniq_name = "_QFflush_parallelEb"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: %[[C:.*]]:2 = hlfir.declare %[[ARG_C]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<intent_inout>, uniq_name = "_QFflush_parallelEc"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) !$omp parallel !CHECK: omp.parallel diff --git a/flang/test/Lower/OpenMP/generic-loop-rewriting.f90 b/flang/test/Lower/OpenMP/generic-loop-rewriting.f90 index eaf31e3..75731a6 100644 --- a/flang/test/Lower/OpenMP/generic-loop-rewriting.f90 +++ b/flang/test/Lower/OpenMP/generic-loop-rewriting.f90 @@ -38,12 +38,12 @@ end subroutine target_teams_loop !CHECK: %[[UB:.*]] = arith.constant 10 : i32 !CHECK: %[[STEP:.*]] = arith.constant 1 : i32 -!CHECK: omp.parallel private(@{{.*}} %[[I_DECL]]#0 +!CHECK: omp.parallel private(@{{.*}} %[[I_DECL]]#0 !CHECK-SAME: -> %[[I_PRIV_ARG:[^[:space:]]+]] : !fir.ref<i32>) { !CHECK: omp.distribute { !CHECK: omp.wsloop { -!CHECK: omp.loop_nest (%{{.*}}) : i32 = +!CHECK: omp.loop_nest (%{{.*}}) : i32 = !CHECK-SAME: (%[[LB]]) to (%[[UB]]) inclusive step (%[[STEP]]) { !CHECK: %[[I_PRIV_DECL:.*]]:2 = hlfir.declare %[[I_PRIV_ARG]] !CHECK: hlfir.assign %{{.*}} to %[[I_PRIV_DECL]]#0 : i32, !fir.ref<i32> diff --git a/flang/test/Lower/OpenMP/host-eval.f90 b/flang/test/Lower/OpenMP/host-eval.f90 index fe5b959..cd759a9 100644 --- a/flang/test/Lower/OpenMP/host-eval.f90 +++ b/flang/test/Lower/OpenMP/host-eval.f90 @@ -7,7 +7,7 @@ subroutine teams() ! BOTH: omp.target ! HOST-SAME: host_eval(%{{.*}} -> %[[NUM_TEAMS:.*]], %{{.*}} -> %[[THREAD_LIMIT:.*]] : i32, i32) - + ! DEVICE-NOT: host_eval({{.*}}) ! DEVICE-SAME: { !$omp target @@ -32,9 +32,9 @@ end subroutine teams ! BOTH-LABEL: func.func @_QPdistribute_parallel_do subroutine distribute_parallel_do() ! BOTH: omp.target - + ! HOST-SAME: host_eval(%{{.*}} -> %[[LB:.*]], %{{.*}} -> %[[UB:.*]], %{{.*}} -> %[[STEP:.*]], %{{.*}} -> %[[NUM_THREADS:.*]] : i32, i32, i32, i32) - + ! DEVICE-NOT: host_eval({{.*}}) ! DEVICE-SAME: { @@ -94,9 +94,9 @@ end subroutine distribute_parallel_do ! BOTH-LABEL: func.func @_QPdistribute_parallel_do_simd subroutine distribute_parallel_do_simd() ! BOTH: omp.target - + ! HOST-SAME: host_eval(%{{.*}} -> %[[LB:.*]], %{{.*}} -> %[[UB:.*]], %{{.*}} -> %[[STEP:.*]], %{{.*}} -> %[[NUM_THREADS:.*]] : i32, i32, i32, i32) - + ! DEVICE-NOT: host_eval({{.*}}) ! DEVICE-SAME: { @@ -159,9 +159,9 @@ end subroutine distribute_parallel_do_simd ! BOTH-LABEL: func.func @_QPdistribute subroutine distribute() ! BOTH: omp.target - + ! HOST-SAME: host_eval(%{{.*}} -> %[[LB:.*]], %{{.*}} -> %[[UB:.*]], %{{.*}} -> %[[STEP:.*]] : i32, i32, i32) - + ! DEVICE-NOT: host_eval({{.*}}) ! DEVICE-SAME: { @@ -209,9 +209,9 @@ end subroutine distribute ! BOTH-LABEL: func.func @_QPdistribute_simd subroutine distribute_simd() ! BOTH: omp.target - + ! HOST-SAME: host_eval(%{{.*}} -> %[[LB:.*]], %{{.*}} -> %[[UB:.*]], %{{.*}} -> %[[STEP:.*]] : i32, i32, i32) - + ! DEVICE-NOT: host_eval({{.*}}) ! DEVICE-SAME: { @@ -262,9 +262,9 @@ end subroutine distribute_simd ! BOTH-LABEL: func.func @_QPloop subroutine loop() ! BOTH: omp.target - + ! HOST-SAME: host_eval(%{{.*}} -> %[[LB:.*]], %{{.*}} -> %[[UB:.*]], %{{.*}} -> %[[STEP:.*]] : i32, i32, i32) - + ! DEVICE-NOT: host_eval({{.*}}) ! DEVICE-SAME: { diff --git a/flang/test/Lower/OpenMP/if-clause.f90 b/flang/test/Lower/OpenMP/if-clause.f90 index 3ae9018..e8f69b4 100644 --- a/flang/test/Lower/OpenMP/if-clause.f90 +++ b/flang/test/Lower/OpenMP/if-clause.f90 @@ -12,7 +12,6 @@ program main ! - PARALLEL SECTIONS ! - PARALLEL WORKSHARE ! - TARGET UPDATE - ! - TASKLOOP ! - TASKLOOP SIMD ! ---------------------------------------------------------------------------- @@ -1580,4 +1579,29 @@ program main !$omp teams if(teams: .true.) i = 1 !$omp end teams + + ! ---------------------------------------------------------------------------- + ! TASKLOOP + ! ---------------------------------------------------------------------------- + + ! CHECK: omp.taskloop + ! CHECK-NOT: if({{.*}}) + !$omp taskloop + do i = 1, 10 + end do + !$omp end taskloop + + ! CHECK: omp.taskloop + ! CHECK-SAME: if({{.*}}) + !$omp taskloop if(.true.) + do i = 1, 10 + end do + !$omp end taskloop + + ! CHECK: omp.taskloop + ! CHECK-SAME: if({{.*}}) + !$omp taskloop if(taskloop: .true.) + do i = 1, 10 + end do + !$omp end taskloop end program main diff --git a/flang/test/Lower/OpenMP/implicit-dsa.f90 b/flang/test/Lower/OpenMP/implicit-dsa.f90 index 0d2db63..9d01460 100644 --- a/flang/test/Lower/OpenMP/implicit-dsa.f90 +++ b/flang/test/Lower/OpenMP/implicit-dsa.f90 @@ -6,6 +6,36 @@ ! Privatizers ! CHECK-LABEL: omp.private +! CHECK-SAME: {type = private} @[[TASKLOOP_TEST3_I_PRIVATE:.*]] : i32 +! CHECK-NOT: copy { + +! CHECK-LABEL: omp.private +! CHECK-SAME: {type = firstprivate} @[[TASKLOOP_TEST3_X_FIRSTPRIVATE:.*]] : i32 +! CHECK-SAME: copy { +! CHECK: hlfir.assign + +! CHECK-LABEL: omp.private +! CHECK-SAME: {type = private} @[[TASKLOOP_TEST2_X_PRIVATE:.*]] : i32 +! CHECK-NOT: copy { + +! CHECK-LABEL: omp.private +! CHECK-SAME: {type = private} @[[TASKLOOP_TEST2_I_PRIVATE:.*]] : i32 +! CHECK-NOT: copy { + +! CHECK-LABEL: omp.private +! CHECK-SAME: {type = private} @[[TASKLOOP_TEST1_I_PRIVATE:.*]] : i32 +! CHECK-NOT: copy { + +! CHECK-LABEL: omp.private +! CHECK-SAME: {type = firstprivate} @[[TASKLOOP_TEST1_X_FIRSTPRIVATE:.*]] : i32 +! CHECK-SAME: copy { +! CHECK: hlfir.assign + +! CHECK-LABEL: omp.private +! CHECK-SAME: {type = private} @[[TASKLOOP_TEST1_Y_PRIVATE:.*]] : i32 +! CHECK-NOT: copy { + +! CHECK-LABEL: omp.private ! CHECK-SAME: {type = firstprivate} @[[TEST7_Y_FIRSTPRIV:.*]] : i32 ! CHECK-SAME: copy { @@ -310,4 +340,100 @@ subroutine implicit_dsa_test7 !$omp end task end subroutine -! TODO Test taskloop +! Test taskloop +! CHECK-LABEL: func.func @_QPimplicit_dsa_taskloop_test1 +! CHECK: %[[ALLOCA_I:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFimplicit_dsa_taskloop_test1Ei"} +! CHECK: %[[DECL_I:.*]]:2 = hlfir.declare %[[ALLOCA_I]] {uniq_name = "_QFimplicit_dsa_taskloop_test1Ei"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[ALLOCA_X:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFimplicit_dsa_taskloop_test1Ex"} +! CHECK: %[[DECL_X:.*]]:2 = hlfir.declare %[[ALLOCA_X]] {uniq_name = "_QFimplicit_dsa_taskloop_test1Ex"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[ALLOCA_Y:.*]] = fir.alloca i32 {bindc_name = "y", uniq_name = "_QFimplicit_dsa_taskloop_test1Ey"} +! CHECK: %[[DECL_Y:.*]]:2 = hlfir.declare %[[ALLOCA_Y]] {uniq_name = "_QFimplicit_dsa_taskloop_test1Ey"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[ALLOCA_Z:.*]] = fir.alloca i32 {bindc_name = "z", uniq_name = "_QFimplicit_dsa_taskloop_test1Ez"} +! CHECK: %[[DECL_Z:.*]]:2 = hlfir.declare %[[ALLOCA_Z]] {uniq_name = "_QFimplicit_dsa_taskloop_test1Ez"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +subroutine implicit_dsa_taskloop_test1 + integer :: x, y, z + ! CHECK: omp.taskloop private( + ! CHECK-SAME: @[[TASKLOOP_TEST1_Y_PRIVATE]] %[[DECL_Y]]#0 -> %[[ARG0:.*]], @[[TASKLOOP_TEST1_X_FIRSTPRIVATE]] %[[DECL_X]]#0 -> %[[ARG1:.*]], @[[TASKLOOP_TEST1_I_PRIVATE]] %[[DECL_I]]#0 -> %[[ARG2:.*]] : !fir.ref<i32>, !fir.ref<i32>, !fir.ref<i32>) { + ! CHECK: omp.loop_nest (%{{.*}}) : i32 = (%{{.*}}) to (%{{.*}}) inclusive step (%{{.*}}) { + !$omp taskloop private(y) shared(z) + do i = 1, 100 + ! CHECK: %[[Y_VAL:.*]]:2 = hlfir.declare %[[ARG0]] {uniq_name = "_QFimplicit_dsa_taskloop_test1Ey"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) + ! CHECK: %[[X_VAL:.*]]:2 = hlfir.declare %[[ARG1]] {uniq_name = "_QFimplicit_dsa_taskloop_test1Ex"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) + ! CHECK: %[[LOAD_Z:.*]] = fir.load %[[DECL_Z]]#0 : !fir.ref<i32> + x = y + z + ! CHECK: hlfir.assign %{{.*}} to %[[X_VAL]]#0 : i32, !fir.ref<i32> + end do + !$omp end taskloop + + ! CHECK: omp.taskloop private(@[[TASKLOOP_TEST1_I_PRIVATE]] %[[DECL_I]]#0 -> %[[ARG0:.*]] : !fir.ref<i32>) { + !$omp taskloop default(shared) + do i = 1, 100 + ! CHECK: %[[LOAD_Y:.*]] = fir.load %[[DECL_Y]]#0 : !fir.ref<i32> + ! CHECK: %[[LOAD_Z:.*]] = fir.load %[[DECL_Z]]#0 : !fir.ref<i32> + ! CHECK: %[[ADD_VAL:.*]] = arith.addi %[[LOAD_Y]], %[[LOAD_Z]] : i32 + x = y + z + ! CHECK: hlfir.assign %[[ADD_VAL]] to %[[DECL_X]]#0 : i32, !fir.ref<i32> + end do + !$omp end taskloop +end subroutine + +! Nested taskloop with implicit shared DSA variables. +! CHECK-LABEL: func @_QPimplicit_dsa_taskloop_test2 +! CHECK: %[[I:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFimplicit_dsa_taskloop_test2Ei"} +! CHECK: %[[I_DECL:.*]]:2 = hlfir.declare %[[I]] {uniq_name = "_QFimplicit_dsa_taskloop_test2Ei"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[X:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFimplicit_dsa_taskloop_test2Ex"} +! CHECK: %[[X_DECL:.*]]:2 = hlfir.declare %[[X]] {uniq_name = "_QFimplicit_dsa_taskloop_test2Ex"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +subroutine implicit_dsa_taskloop_test2 + integer :: x + ! CHECK: omp.parallel { + !$omp parallel + ! CHECK: omp.taskloop private(@[[TASKLOOP_TEST2_I_PRIVATE]] %[[I_DECL]]#0 -> %[[ARG0:.*]] : !fir.ref<i32>) { + !$omp taskloop + do i = 1, 100 + ! CHECK: hlfir.assign %{{.*}} to %[[X_DECL]]#0 : i32, !fir.ref<i32> + x = 2 + end do + !$omp end taskloop + + ! CHECK: omp.taskloop private(@[[TASKLOOP_TEST2_X_PRIVATE]] %[[X_DECL]]#0 -> %[[ARG0]], @[[TASKLOOP_TEST2_I_PRIVATE]] %[[I_DECL]]#0 -> %[[ARG1:.*]] : !fir.ref<i32>, !fir.ref<i32>) { + !$omp taskloop private(x) + do i = 1, 10 + ! CHECK: %[[DECL_PRIV_X:.*]]:2 = hlfir.declare %[[ARG0]] {uniq_name = "_QFimplicit_dsa_taskloop_test2Ex"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) + ! CHECK: %[[LOAD_X:.*]] = fir.load %[[DECL_PRIV_X]]#0 : !fir.ref<i32> + x = x + 1 + ! CHECK: hlfir.assign %{{.*}} to %[[DECL_PRIV_X]]#0 : i32, !fir.ref<i32> + end do + !$omp end parallel + +end subroutine + +! Taskloop with implicit firstprivate DSA variables, enclosed in private context. + +! CHECK-LABEL: func @_QPimplicit_dsa_taskloop_test3 +! CHECK: %[[I:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFimplicit_dsa_taskloop_test3Ei"} +! CHECK: %[[I_DECL:.*]]:2 = hlfir.declare %[[I]] {uniq_name = "_QFimplicit_dsa_taskloop_test3Ei"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[X:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFimplicit_dsa_taskloop_test3Ex"} +! CHECK: %[[X_DECL:.*]]:2 = hlfir.declare %[[X]] {uniq_name = "_QFimplicit_dsa_taskloop_test3Ex"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[Y:.*]] = fir.alloca i32 {bindc_name = "y", uniq_name = "_QFimplicit_dsa_taskloop_test3Ey"} +! CHECK: %[[Y_DECL:.*]]:2 = hlfir.declare %[[Y]] {uniq_name = "_QFimplicit_dsa_taskloop_test3Ey"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[Z:.*]] = fir.alloca i32 {bindc_name = "z", uniq_name = "_QFimplicit_dsa_taskloop_test3Ez"} +! CHECK: %[[Z_DECL:.*]]:2 = hlfir.declare %[[Z]] {uniq_name = "_QFimplicit_dsa_taskloop_test3Ez"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) + +subroutine implicit_dsa_taskloop_test3 + integer :: x, y, z + ! CHECK: omp.parallel private(@[[TASKLOOP_TEST3_X_FIRSTPRIVATE]] %[[X_DECL]]#0 -> %[[ARG0:.*]] : !fir.ref<i32>) { + ! CHECK: %[[X_PRIV_VAL:.*]]:2 = hlfir.declare %[[ARG0]] {uniq_name = "_QFimplicit_dsa_taskloop_test3Ex"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) + !$omp parallel firstprivate(x) + ! CHECK: omp.taskloop private(@[[TASKLOOP_TEST3_X_FIRSTPRIVATE]] %[[X_PRIV_VAL]]#0 -> %[[ARG1:.*]], @[[TASKLOOP_TEST3_I_PRIVATE]] %[[I_DECL]]#0 -> %[[ARG2:.*]] : !fir.ref<i32>, !fir.ref<i32>) { + !$omp taskloop + ! CHECK: %[[X_VAL:.*]]:2 = hlfir.declare %[[ARG1]] {uniq_name = "_QFimplicit_dsa_taskloop_test3Ex"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) + do i = 1, 100 + ! CHECK: %[[LOAD_Y:.*]] = fir.load %[[Y_DECL]]#0 : !fir.ref<i32> + ! CHECK: %[[LOAD_Z:.*]] = fir.load %[[Z_DECL]]#0 : !fir.ref<i32> + x = y + z + ! CHECK: hlfir.assign %{{.*}} to %[[X_VAL]]#0 : i32, !fir.ref<i32> + end do + !$omp end taskloop + !$omp end parallel +end subroutine + diff --git a/flang/test/Lower/OpenMP/lastprivate-iv.f90 b/flang/test/Lower/OpenMP/lastprivate-iv.f90 index 114ea6c..795838d 100644 --- a/flang/test/Lower/OpenMP/lastprivate-iv.f90 +++ b/flang/test/Lower/OpenMP/lastprivate-iv.f90 @@ -96,7 +96,7 @@ subroutine lastprivate_iv_i1 end subroutine !CHECK: omp.wsloop private(@_QFlastprivate_iv_pointerEi_private_box_ptr_i32 %{{.*}}#0 -> %[[PRIVATE_IV:.*]] : !fir.ref<!fir.box<!fir.ptr<i32>>>) { -!CHECK: omp.loop_nest (%[[LOOP_INDEX:.*]]) : i64 +!CHECK: omp.loop_nest (%[[LOOP_INDEX:.*]]) : i64 !CHECK: %[[PRIVATE_IV_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_IV]] {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFlastprivate_iv_pointerEi"} : (!fir.ref<!fir.box<!fir.ptr<i32>>>) -> (!fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.ref<!fir.box<!fir.ptr<i32>>>) !CHECK: %[[LOOP_INDEX_INCR:.*]] = arith.addi %[[LOOP_INDEX]], %{{.*}} : i64 !CHECK: fir.if %{{.*}} { diff --git a/flang/test/Lower/OpenMP/loop-directive.f90 b/flang/test/Lower/OpenMP/loop-directive.f90 index a974f26..05770c0 100644 --- a/flang/test/Lower/OpenMP/loop-directive.f90 +++ b/flang/test/Lower/OpenMP/loop-directive.f90 @@ -112,7 +112,7 @@ subroutine test_nested_directives ! CHECK: omp.teams { - ! Verify the first `loop` directive was combined with `target teams` into + ! Verify the first `loop` directive was combined with `target teams` into ! `target teams distribute parallel do`. ! CHECK: omp.parallel {{.*}} { ! CHECK: omp.distribute { @@ -371,7 +371,7 @@ subroutine teams_loop_cannot_be_parallel_for_with_reductions ! CHECK: %[[ADD_RED:.*]]:2 = hlfir.declare %{{.*}} {uniq_name = "_QF{{.*}}Ex"} ! CHECK: %[[MUL_RED:.*]]:2 = hlfir.declare %{{.*}} {uniq_name = "_QF{{.*}}Ey"} ! CHECK: omp.teams reduction( - ! CHECK-SAME: @add_reduction_i32 %[[ADD_RED]]#0 -> %[[ADD_RED_ARG:[^[:space:]]*]], + ! CHECK-SAME: @add_reduction_i32 %[[ADD_RED]]#0 -> %[[ADD_RED_ARG:[^[:space:]]*]], ! CHECK-SAME: @multiply_reduction_i32 %[[MUL_RED]]#0 -> %[[MUL_RED_ARG:.*]] : {{.*}}) { ! CHECK: omp.distribute private(@{{.*}} %{{.*}} -> %{{.*}}, @{{.*}} %{{.*}} -> %{{.*}} : {{.*}}) { diff --git a/flang/test/Lower/OpenMP/map-character.f90 b/flang/test/Lower/OpenMP/map-character.f90 index cefd3ac..c4197261 100644 --- a/flang/test/Lower/OpenMP/map-character.f90 +++ b/flang/test/Lower/OpenMP/map-character.f90 @@ -39,8 +39,11 @@ end subroutine TestOfCharacter !CHECK: %[[A1_UB:.*]] = arith.subi %[[UNBOXED_ARG1]]#1, %[[CONST_ONE]] : index !CHECK: %[[BOUNDS_A1_BOXCHAR:.*]] = omp.map.bounds lower_bound(%[[CONST_ZERO]] : index) upper_bound(%[[A1_UB]] : index) extent(%[[UNBOXED_ARG1]]#1 : index) !CHECK-SAME: stride(%[[CONST_ONE]] : index) start_idx(%[[CONST_ZERO]] : index) {stride_in_bytes = true} -!CHECK: %[[A1_BOXCHAR_MAP:.*]] = omp.map.info var_ptr(%[[A1_BOXCHAR_ALLOCA]] : !fir.ref<!fir.boxchar<1>>, !fir.boxchar<1>) map_clauses(implicit, to) -!CHECK-SAME: capture(ByRef) bounds(%[[BOUNDS_A1_BOXCHAR]]) -> !fir.ref<!fir.boxchar<1>> {name = ""} +!CHECK: %[[A1_BOX_ADDR:.*]] = fir.box_offset %[[A1_BOXCHAR_ALLOCA]] base_addr : (!fir.ref<!fir.boxchar<1>>) -> !fir.llvm_ptr<!fir.ref<!fir.char<1,?>>> +!CHECK: %[[A1_BOXCHAR_MAP:.*]] = omp.map.info var_ptr(%[[A1_BOXCHAR_ALLOCA]] : !fir.ref<!fir.boxchar<1>>, !fir.char<1,?>) map_clauses(implicit, to) +!CHECK-SAME: capture(ByRef) var_ptr_ptr(%[[A1_BOX_ADDR]] : !fir.llvm_ptr<!fir.ref<!fir.char<1,?>>>) bounds(%[[BOUNDS_A1_BOXCHAR]]) -> !fir.llvm_ptr<!fir.ref<!fir.char<1,?>>> {name = ""} +!CHECK: %[[A1_BOXCHAR_MAP_2:.*]] = omp.map.info var_ptr(%[[A1_BOXCHAR_ALLOCA]] : !fir.ref<!fir.boxchar<1>>, !fir.boxchar<1>) +!CHECK-SAME: map_clauses(always, implicit, to) capture(ByRef) members(%[[A1_BOXCHAR_MAP]] : [0] : !fir.llvm_ptr<!fir.ref<!fir.char<1,?>>>) -> !fir.ref<!fir.boxchar<1>> {name = ""} !CHECK: fir.store %[[ARG0]] to %[[A0_BOXCHAR_ALLOCA]] : !fir.ref<!fir.boxchar<1>> !CHECK: %[[CONST_ZERO:.*]] = arith.constant 0 : index !CHECK: %[[CONST_ONE:.*]] = arith.constant 1 : index @@ -48,9 +51,12 @@ end subroutine TestOfCharacter !CHECK: %[[A0_UB:.*]] = arith.subi %[[UNBOXED_ARG0]]#1, %[[CONST_ONE]] : index !CHECK: %[[BOUNDS_A0_BOXCHAR:.*]] = omp.map.bounds lower_bound(%[[CONST_ZERO]] : index) upper_bound(%[[A0_UB]] : index) extent(%[[UNBOXED_ARG0]]#1 : index) !CHECK-SAME: stride(%[[CONST_ONE]] : index) start_idx(%[[CONST_ZERO]] : index) {stride_in_bytes = true} -!CHECK: %[[A0_BOXCHAR_MAP:.*]] = omp.map.info var_ptr(%[[A0_BOXCHAR_ALLOCA]] : !fir.ref<!fir.boxchar<1>>, !fir.boxchar<1>) map_clauses(implicit, to) -!CHECK-SAME: capture(ByRef) bounds(%[[BOUNDS_A0_BOXCHAR]]) -> !fir.ref<!fir.boxchar<1>> {name = ""} -!CHECK: omp.target map_entries(%[[A0_MAP]] -> %[[TGT_A0:.*]], %[[A1_MAP]] -> %[[TGT_A1:.*]], %[[A1_BOXCHAR_MAP]] -> %[[TGT_A1_BOXCHAR:.*]], %[[A0_BOXCHAR_MAP]] -> %[[TGT_A0_BOXCHAR:.*]] : !fir.ref<!fir.char<1,?>>, !fir.ref<!fir.char<1,?>>, !fir.ref<!fir.boxchar<1>>, !fir.ref<!fir.boxchar<1>>) { +!CHECK: %[[A0_BOX_ADDR:.*]] = fir.box_offset %[[A0_BOXCHAR_ALLOCA]] base_addr : (!fir.ref<!fir.boxchar<1>>) -> !fir.llvm_ptr<!fir.ref<!fir.char<1,?>>> +!CHECK: %[[A0_BOXCHAR_MAP:.*]] = omp.map.info var_ptr(%[[A0_BOXCHAR_ALLOCA]] : !fir.ref<!fir.boxchar<1>>, !fir.char<1,?>) map_clauses(implicit, to) +!CHECK-SAME: capture(ByRef) var_ptr_ptr(%[[A0_BOX_ADDR]] : !fir.llvm_ptr<!fir.ref<!fir.char<1,?>>>) bounds(%24) -> !fir.llvm_ptr<!fir.ref<!fir.char<1,?>>> {name = ""} +!CHECK: %[[A0_BOXCHAR_MAP_2:.*]] = omp.map.info var_ptr(%[[A0_BOXCHAR_ALLOCA]] : !fir.ref<!fir.boxchar<1>>, !fir.boxchar<1>) map_clauses(always, implicit, to) +!CHECK-SAME: capture(ByRef) members(%[[A0_BOXCHAR_MAP]] : [0] : !fir.llvm_ptr<!fir.ref<!fir.char<1,?>>>) -> !fir.ref<!fir.boxchar<1>> {name = ""} +!CHECK: omp.target map_entries(%[[A0_MAP]] -> %[[TGT_A0:.*]], %[[A1_MAP]] -> %[[TGT_A1:.*]], %[[A1_BOXCHAR_MAP_2]] -> %[[TGT_A1_BOXCHAR:.*]], %[[A0_BOXCHAR_MAP_2]] -> %[[TGT_A0_BOXCHAR:.*]], %[[A1_BOXCHAR_MAP]] -> %[[TGT_A1_BOXCHAR2:.*]], %[[A0_BOXCHAR_MAP]] -> %[[TGT_A0_BOXCHAR2:.*]] : !fir.ref<!fir.char<1,?>>, !fir.ref<!fir.char<1,?>>, !fir.ref<!fir.boxchar<1>>, !fir.ref<!fir.boxchar<1>>, !fir.llvm_ptr<!fir.ref<!fir.char<1,?>>>, !fir.llvm_ptr<!fir.ref<!fir.char<1,?>>>) { !CHECK: %[[TGT_A0_BC_LD:.*]] = fir.load %[[TGT_A0_BOXCHAR]] : !fir.ref<!fir.boxchar<1>> !CHECK: %[[TGT_A1_BC_LD:.*]] = fir.load %[[TGT_A1_BOXCHAR]] : !fir.ref<!fir.boxchar<1>> !CHECK: %[[UNBOXED_TGT_A1:.*]]:2 = fir.unboxchar %[[TGT_A1_BC_LD]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index) diff --git a/flang/test/Lower/OpenMP/map-descriptor-deferral.f90 b/flang/test/Lower/OpenMP/map-descriptor-deferral.f90 index daea2f3..a7165c3 100644 --- a/flang/test/Lower/OpenMP/map-descriptor-deferral.f90 +++ b/flang/test/Lower/OpenMP/map-descriptor-deferral.f90 @@ -23,7 +23,7 @@ end subroutine !CHECK: omp.target_enter_data map_entries(%[[MAP_ADDR]] : !fir.ref<!fir.array<?xi32>>) !CHECK: %[[BOX_ADDR:.*]] = fir.box_offset %{{.*}} base_addr : (!fir.ref<!fir.box<!fir.array<?xi32>>>) -> !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>> !CHECK: %[[MAP_ADDR:.*]] = omp.map.info var_ptr(%{{.*}} : !fir.ref<!fir.box<!fir.array<?xi32>>>, i32) map_clauses(implicit, tofrom) capture(ByRef) var_ptr_ptr(%[[BOX_ADDR]] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) bounds(%{{.*}}) -> !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>> {name = ""} -!CHECK: %[[MAP_BOX:.*]] = omp.map.info var_ptr(%{{.*}} : !fir.ref<!fir.box<!fir.array<?xi32>>>, !fir.box<!fir.array<?xi32>>) map_clauses(implicit, to) capture(ByRef) members(%{{.*}} : [0] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) -> !fir.ref<!fir.array<?xi32>> {name = "assumed_arr"} +!CHECK: %[[MAP_BOX:.*]] = omp.map.info var_ptr(%{{.*}} : !fir.ref<!fir.box<!fir.array<?xi32>>>, !fir.box<!fir.array<?xi32>>) map_clauses(always, implicit, to) capture(ByRef) members(%{{.*}} : [0] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) -> !fir.ref<!fir.array<?xi32>> {name = "assumed_arr"} !CHECK: omp.target map_entries(%[[MAP_BOX]] -> %{{.*}}, %[[MAP_ADDR]] -> %{{.*}} : !fir.ref<!fir.array<?xi32>>, !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) { !CHECK: %[[BOX_ADDR:.*]] = fir.box_offset %{{.*}} base_addr : (!fir.ref<!fir.box<!fir.array<?xi32>>>) -> !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>> !CHECK: %[[LOAD_BOX:.*]] = fir.load %[[BOX_ADDR]] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>> @@ -42,11 +42,11 @@ end subroutine !CHECK-LABEL: func.func @_QPassume_alloca_map_target_enter_exit( !CHECK: %[[BOX_ADDR:.*]] = fir.box_offset %{{.*}} base_addr : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) -> !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>> !CHECK: %[[BOX_ADDR_MAP:.*]] = omp.map.info var_ptr(%{{.*}} : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, i32) map_clauses(to) capture(ByRef) var_ptr_ptr(%[[BOX_ADDR]] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) bounds(%{{.*}}) -> !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>> {name = ""} -!CHECK: %[[DESC_MAP:.*]] = omp.map.info var_ptr(%{{.*}} : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.box<!fir.heap<!fir.array<?xi32>>>) map_clauses(to) capture(ByRef) members(%[[BOX_ADDR_MAP]] : [0] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> {name = "assumed_arr"} +!CHECK: %[[DESC_MAP:.*]] = omp.map.info var_ptr(%{{.*}} : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.box<!fir.heap<!fir.array<?xi32>>>) map_clauses(always, to) capture(ByRef) members(%[[BOX_ADDR_MAP]] : [0] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> {name = "assumed_arr"} !CHECK: omp.target_enter_data map_entries(%[[DESC_MAP]], %[[BOX_ADDR_MAP]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) !CHECK: %[[BOX_ADDR:.*]] = fir.box_offset %{{.*}} base_addr : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) -> !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>> !CHECK: %[[BOX_ADDR_MAP:.*]] = omp.map.info var_ptr(%{{.*}} : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, i32) map_clauses(implicit, tofrom) capture(ByRef) var_ptr_ptr(%[[BOX_ADDR]] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) bounds(%{{.*}}) -> !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>> {name = ""} -!CHECK: %[[DESC_MAP:.*]] = omp.map.info var_ptr(%{{.*}} : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.box<!fir.heap<!fir.array<?xi32>>>) map_clauses(implicit, to) capture(ByRef) members(%[[BOX_ADDR_MAP]] : [0] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> {name = "assumed_arr"} +!CHECK: %[[DESC_MAP:.*]] = omp.map.info var_ptr(%{{.*}} : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.box<!fir.heap<!fir.array<?xi32>>>) map_clauses(always, implicit, to) capture(ByRef) members(%[[BOX_ADDR_MAP]] : [0] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> {name = "assumed_arr"} !CHECK: omp.target map_entries(%[[DESC_MAP]] -> %[[VAL_28:.*]], %[[BOX_ADDR_MAP]] -> %[[VAL_29:.*]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) { !CHECK: %[[BOX_ADDR:.*]] = fir.box_offset %{{.*}} base_addr : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) -> !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>> !CHECK: %[[BOX_ADDR_MAP:.*]] = omp.map.info var_ptr(%{{.*}} : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, i32) map_clauses(from) capture(ByRef) var_ptr_ptr(%[[BOX_ADDR]] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) bounds(%{{.*}}) -> !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>> {name = ""} @@ -65,11 +65,11 @@ end subroutine !CHECK-LABEL: func.func @_QPassume_pointer_map_target_enter_exit( !CHECK: %[[BOX_ADDR:.*]] = fir.box_offset %{{.*}} base_addr : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>) -> !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>> !CHECK: %[[BOX_ADDR_MAP:.*]] = omp.map.info var_ptr(%{{.*}} : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>, i32) map_clauses(to) capture(ByRef) var_ptr_ptr(%[[BOX_ADDR]] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) bounds(%{{.*}}) -> !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>> {name = ""} -!CHECK: %[[DESC_MAP:.*]] = omp.map.info var_ptr(%{{.*}} : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>, !fir.box<!fir.ptr<!fir.array<?xi32>>>) map_clauses(to) capture(ByRef) members(%[[BOX_ADDR_MAP]] : [0] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) -> !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>> {name = "assumed_arr"} +!CHECK: %[[DESC_MAP:.*]] = omp.map.info var_ptr(%{{.*}} : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>, !fir.box<!fir.ptr<!fir.array<?xi32>>>) map_clauses(always, to) capture(ByRef) members(%[[BOX_ADDR_MAP]] : [0] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) -> !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>> {name = "assumed_arr"} !CHECK: omp.target_enter_data map_entries(%[[DESC_MAP]], %[[BOX_ADDR_MAP]] : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>, !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) !CHECK: %[[BOX_ADDR:.*]] = fir.box_offset %{{.*}} base_addr : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>) -> !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>> !CHECK: %[[BOX_ADDR_MAP:.*]] = omp.map.info var_ptr(%{{.*}} : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>, i32) map_clauses(implicit, tofrom) capture(ByRef) var_ptr_ptr(%[[BOX_ADDR]] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) bounds(%{{.*}}) -> !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>> {name = ""} -!CHECK: %[[DESC_MAP:.*]] = omp.map.info var_ptr(%{{.*}} : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>, !fir.box<!fir.ptr<!fir.array<?xi32>>>) map_clauses(implicit, to) capture(ByRef) members(%[[BOX_ADDR_MAP]] : [0] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) -> !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>> {name = "assumed_arr"} +!CHECK: %[[DESC_MAP:.*]] = omp.map.info var_ptr(%{{.*}} : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>, !fir.box<!fir.ptr<!fir.array<?xi32>>>) map_clauses(always, implicit, to) capture(ByRef) members(%[[BOX_ADDR_MAP]] : [0] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) -> !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>> {name = "assumed_arr"} !CHECK: omp.target map_entries(%[[DESC_MAP]] -> %[[VAL_28:.*]], %[[BOX_ADDR_MAP]] -> %[[VAL_29:.*]] : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>, !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) { !CHECK: %[[BOX_ADDR:.*]] = fir.box_offset %{{.*}} base_addr : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>) -> !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>> !CHECK: %[[BOX_ADDR_MAP:.*]] = omp.map.info var_ptr(%{{.*}} : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>, i32) map_clauses(from) capture(ByRef) var_ptr_ptr(%[[BOX_ADDR]] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) bounds(%{{.*}}) -> !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>> {name = ""} @@ -88,9 +88,9 @@ end subroutine !CHECK-LABEL: func.func @_QPassume_map_target_data( !CHECK: %[[BOX_ADDR:.*]] = fir.box_offset %{{.*}} base_addr : (!fir.ref<!fir.box<!fir.array<?xi32>>>) -> !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>> !CHECK: %[[MAP_ADDR:.*]] = omp.map.info var_ptr(%{{.*}} : !fir.ref<!fir.box<!fir.array<?xi32>>>, i32) map_clauses(to) capture(ByRef) var_ptr_ptr(%[[BOX_ADDR]] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) bounds(%{{.*}}) -> !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>> {name = ""} -!CHECK: %[[MAP_BOX:.*]] = omp.map.info var_ptr(%{{.*}} : !fir.ref<!fir.box<!fir.array<?xi32>>>, !fir.box<!fir.array<?xi32>>) map_clauses(to) capture(ByRef) members(%[[MAP_ADDR]] : [0] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) -> !fir.ref<!fir.array<?xi32>> {name = "assumed_arr"} +!CHECK: %[[MAP_BOX:.*]] = omp.map.info var_ptr(%{{.*}} : !fir.ref<!fir.box<!fir.array<?xi32>>>, !fir.box<!fir.array<?xi32>>) map_clauses(always, to) capture(ByRef) members(%[[MAP_ADDR]] : [0] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) -> !fir.ref<!fir.array<?xi32>> {name = "assumed_arr"} !CHECK: omp.target_data map_entries(%[[MAP_BOX]], %[[MAP_ADDR]] : !fir.ref<!fir.array<?xi32>>, !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) { !CHECK: %[[BOX_ADDR:.*]] = fir.box_offset %{{.*}} base_addr : (!fir.ref<!fir.box<!fir.array<?xi32>>>) -> !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>> !CHECK: %[[MAP_ADDR:.*]] = omp.map.info var_ptr(%{{.*}} : !fir.ref<!fir.box<!fir.array<?xi32>>>, i32) map_clauses(implicit, tofrom) capture(ByRef) var_ptr_ptr(%[[BOX_ADDR]] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) bounds(%{{.*}}) -> !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>> {name = ""} -!CHECK: %[[MAP_BOX:.*]] = omp.map.info var_ptr(%{{.*}} : !fir.ref<!fir.box<!fir.array<?xi32>>>, !fir.box<!fir.array<?xi32>>) map_clauses(implicit, to) capture(ByRef) members(%[[MAP_ADDR]] : [0] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) -> !fir.ref<!fir.array<?xi32>> {name = "assumed_arr"} +!CHECK: %[[MAP_BOX:.*]] = omp.map.info var_ptr(%{{.*}} : !fir.ref<!fir.box<!fir.array<?xi32>>>, !fir.box<!fir.array<?xi32>>) map_clauses(always, implicit, to) capture(ByRef) members(%[[MAP_ADDR]] : [0] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) -> !fir.ref<!fir.array<?xi32>> {name = "assumed_arr"} !CHECK: omp.target map_entries(%[[MAP_BOX]] -> %{{.*}}, %[[MAP_ADDR]] -> %{{.*}} : !fir.ref<!fir.array<?xi32>>, !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) { diff --git a/flang/test/Lower/OpenMP/map-mapper.f90 b/flang/test/Lower/OpenMP/map-mapper.f90 index 91564bf..8934fbb 100644 --- a/flang/test/Lower/OpenMP/map-mapper.f90 +++ b/flang/test/Lower/OpenMP/map-mapper.f90 @@ -8,7 +8,7 @@ program p !$omp declare mapper(xx : t1 :: nn) map(to: nn, nn%x) !$omp declare mapper(t1 :: nn) map(from: nn) - !CHECK-LABEL: omp.declare_mapper @_QQFt1.omp.default.mapper : !fir.type<_QFTt1{x:!fir.array<256xi32>}> + !CHECK-LABEL: omp.declare_mapper @_QQFt1_omp_default_mapper : !fir.type<_QFTt1{x:!fir.array<256xi32>}> !CHECK-LABEL: omp.declare_mapper @_QQFxx : !fir.type<_QFTt1{x:!fir.array<256xi32>}> type(t1) :: a, b @@ -20,7 +20,7 @@ program p end do !$omp end target - !CHECK: %[[MAP_B:.*]] = omp.map.info var_ptr(%{{.*}} : {{.*}}, {{.*}}) map_clauses(tofrom) capture(ByRef) mapper(@_QQFt1.omp.default.mapper) -> {{.*}} {name = "b"} + !CHECK: %[[MAP_B:.*]] = omp.map.info var_ptr(%{{.*}} : {{.*}}, {{.*}}) map_clauses(tofrom) capture(ByRef) mapper(@_QQFt1_omp_default_mapper) -> {{.*}} {name = "b"} !CHECK: omp.target map_entries(%[[MAP_B]] -> %{{.*}}, %{{.*}} -> %{{.*}} : {{.*}}, {{.*}}) { !$omp target map(mapper(default) : b) do i = 1, n diff --git a/flang/test/Lower/OpenMP/map-neg-alloca-derived-type-array.f90 b/flang/test/Lower/OpenMP/map-neg-alloca-derived-type-array.f90 index dd8721b..0e3e8d7 100644 --- a/flang/test/Lower/OpenMP/map-neg-alloca-derived-type-array.f90 +++ b/flang/test/Lower/OpenMP/map-neg-alloca-derived-type-array.f90 @@ -24,4 +24,4 @@ end subroutine ! CHECK: %[[VAL_11:.*]] = fir.coordinate_of %[[VAL_10]], data : (!fir.ref<!fir.type<_QFmap_negative_bounds_allocatable_dtypeTderived_type{data:!fir.box<!fir.ptr<!fir.array<?x?x?xf32>>>}>>) -> !fir.ref<!fir.box<!fir.ptr<!fir.array<?x?x?xf32>>>> ! CHECK: %[[VAL_12:.*]] = fir.box_offset %[[VAL_11]] base_addr : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?x?x?xf32>>>>) -> !fir.llvm_ptr<!fir.ref<!fir.array<?x?x?xf32>>> ! CHECK: %[[VAL_13:.*]] = omp.map.info var_ptr(%[[VAL_11]] : !fir.ref<!fir.box<!fir.ptr<!fir.array<?x?x?xf32>>>>, f32) map_clauses(tofrom) capture(ByRef) var_ptr_ptr(%[[VAL_12]] : !fir.llvm_ptr<!fir.ref<!fir.array<?x?x?xf32>>>) bounds({{.*}}) -> !fir.llvm_ptr<!fir.ref<!fir.array<?x?x?xf32>>> {name = ""} -! CHECK: %[[VAL_14:.*]] = omp.map.info var_ptr(%[[VAL_11]] : !fir.ref<!fir.box<!fir.ptr<!fir.array<?x?x?xf32>>>>, !fir.box<!fir.ptr<!fir.array<?x?x?xf32>>>) map_clauses(to) capture(ByRef) -> !fir.ref<!fir.box<!fir.ptr<!fir.array<?x?x?xf32>>>> {name = {{.*}}} +! CHECK: %[[VAL_14:.*]] = omp.map.info var_ptr(%[[VAL_11]] : !fir.ref<!fir.box<!fir.ptr<!fir.array<?x?x?xf32>>>>, !fir.box<!fir.ptr<!fir.array<?x?x?xf32>>>) map_clauses(always, to) capture(ByRef) -> !fir.ref<!fir.box<!fir.ptr<!fir.array<?x?x?xf32>>>> {name = {{.*}}} diff --git a/flang/test/Lower/OpenMP/map-no-modifier-v60.f90 b/flang/test/Lower/OpenMP/map-no-modifier-v60.f90 index bcc37e4..d84ea73 100644 --- a/flang/test/Lower/OpenMP/map-no-modifier-v60.f90 +++ b/flang/test/Lower/OpenMP/map-no-modifier-v60.f90 @@ -9,4 +9,3 @@ subroutine f00 !$omp target map(x) !$omp end target end - diff --git a/flang/test/Lower/OpenMP/masked_taskloop.f90 b/flang/test/Lower/OpenMP/masked_taskloop.f90 index abe20ec..4ace6fe 100644 --- a/flang/test/Lower/OpenMP/masked_taskloop.f90 +++ b/flang/test/Lower/OpenMP/masked_taskloop.f90 @@ -3,18 +3,18 @@ ! RUN: bbc -emit-hlfir -fopenmp -o - %s 2>&1 | FileCheck %s ! RUN: %flang_fc1 -emit-hlfir -fopenmp -o - %s 2>&1 | FileCheck %s -! CHECK-LABEL: omp.private {type = private} +! CHECK-LABEL: omp.private {type = private} ! CHECK-SAME: @[[I_PRIVATE:.*]] : i32 -! CHECK-LABEL: omp.private -! CHECK-SAME: {type = firstprivate} @[[J_FIRSTPRIVATE:.*]] : i32 +! CHECK-LABEL: omp.private +! CHECK-SAME: {type = firstprivate} @[[J_FIRSTPRIVATE:.*]] : i32 ! CHECK-SAME: copy { -! CHECK: hlfir.assign +! CHECK: hlfir.assign ! CHECK-LABEL: func.func @_QPtest_masked_taskloop() { ! CHECK: %[[VAL_0:.*]] = fir.dummy_scope : !fir.dscope ! CHECK: %[[ALLOCA_I:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFtest_masked_taskloopEi"} -! CHECK: %[[DECL_I:.*]]:2 = hlfir.declare %[[ALLOCA_I]] +! CHECK: %[[DECL_I:.*]]:2 = hlfir.declare %[[ALLOCA_I]] ! CHECK-SAME: {uniq_name = "_QFtest_masked_taskloopEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[ALLOCA_J:.*]] = fir.address_of(@_QFtest_masked_taskloopEj) : !fir.ref<i32> ! CHECK: %[[DECL_J:.*]]:2 = hlfir.declare %[[ALLOCA_J]] {uniq_name = "_QFtest_masked_taskloopEj"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) @@ -51,5 +51,5 @@ subroutine test_masked_taskloop do i=1,10 j = j + 1 end do - !$omp end masked taskloop + !$omp end masked taskloop end subroutine diff --git a/flang/test/Lower/OpenMP/master_taskloop_simd.f90 b/flang/test/Lower/OpenMP/master_taskloop_simd.f90 index e928afd..a5f5b9f3 100644 --- a/flang/test/Lower/OpenMP/master_taskloop_simd.f90 +++ b/flang/test/Lower/OpenMP/master_taskloop_simd.f90 @@ -6,7 +6,7 @@ subroutine test_master_taskloop_simd() integer :: i, j = 1 !CHECK: not yet implemented: Composite TASKLOOP SIMD - !$omp master taskloop simd + !$omp master taskloop simd do i=1,10 j = j + 1 end do diff --git a/flang/test/Lower/OpenMP/multiple-entry-points.f90 b/flang/test/Lower/OpenMP/multiple-entry-points.f90 index 2b8caa7..604b9cd 100644 --- a/flang/test/Lower/OpenMP/multiple-entry-points.f90 +++ b/flang/test/Lower/OpenMP/multiple-entry-points.f90 @@ -36,7 +36,7 @@ subroutine process_a(n, a) return entry process_b(n, b) - + !$omp parallel do i = 1, n a(i) = i * i diff --git a/flang/test/Lower/OpenMP/nested-loop-transformation-construct02.f90 b/flang/test/Lower/OpenMP/nested-loop-transformation-construct02.f90 index cdc628a..5200777 100644 --- a/flang/test/Lower/OpenMP/nested-loop-transformation-construct02.f90 +++ b/flang/test/Lower/OpenMP/nested-loop-transformation-construct02.f90 @@ -9,7 +9,7 @@ program loop_transformation_construct integer :: y(I) !$omp do - !$omp unroll + !$omp unroll partial(2) do x = 1, I y(x) = y(x) * 5 end do diff --git a/flang/test/Lower/OpenMP/omp-declare-reduction-combsub.f90 b/flang/test/Lower/OpenMP/omp-declare-reduction-combsub.f90 new file mode 100644 index 0000000..098b3f8 --- /dev/null +++ b/flang/test/Lower/OpenMP/omp-declare-reduction-combsub.f90 @@ -0,0 +1,60 @@ +! This test checks lowering of OpenMP declare reduction Directive, with combiner +! via a subroutine call. + +!RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=52 %s -o - | FileCheck %s + +subroutine combine_me(out, in) + integer out, in + out = out + in +end subroutine combine_me + +function func(x, n) + integer func + integer x(n) + integer res + interface + subroutine combine_me(out, in) + integer out, in + end subroutine combine_me + end interface +!CHECK: omp.declare_reduction @red_add : i32 init { +!CHECK: ^bb0(%[[OMP_ORIG_ARG_I:.*]]: i32): +!CHECK: %[[OMP_PRIV:.*]] = fir.alloca i32 +!CHECK: %[[OMP_ORIG:.*]] = fir.alloca i32 +!CHECK: fir.store %[[OMP_ORIG_ARG_I]] to %[[OMP_ORIG]] : !fir.ref<i32> +!CHECK: %[[OMP_ORIG_DECL:.*]]:2 = hlfir.declare %[[OMP_ORIG]] {uniq_name = "omp_orig"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: fir.store %[[OMP_ORIG_ARG_I]] to %[[OMP_PRIV]] : !fir.ref<i32> +!CHECK: %[[OMP_PRIV_DECL:.*]]:2 = hlfir.declare %[[OMP_PRIV]] {uniq_name = "omp_priv"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: %[[CONST_0:.*]] = arith.constant 0 : i32 +!CHECK: omp.yield(%[[CONST_0]] : i32) +!CHECK: } combiner { +!CHECK: ^bb0(%[[LHS_ARG:.*]]: i32, %[[RHS_ARG:.*]]: i32): +!CHECK: %[[OMP_OUT:.*]] = fir.alloca i32 +!CHECK: %[[OMP_IN:.*]] = fir.alloca i32 +!CHECK: fir.store %[[RHS_ARG]] to %[[OMP_IN]] : !fir.ref<i32> +!CHECK: %[[OMP_IN_DECL:.*]]:2 = hlfir.declare %[[OMP_IN]] {uniq_name = "omp_in"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: fir.store %[[LHS_ARG]] to %[[OMP_OUT]] : !fir.ref<i32> +!CHECK: %[[OMP_OUT_DECL:.*]]:2 = hlfir.declare %[[OMP_OUT]] {uniq_name = "omp_out"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: fir.call @_QPcombine_me(%[[OMP_OUT_DECL]]#0, %[[OMP_IN_DECL]]#0) fastmath<contract> : (!fir.ref<i32>, !fir.ref<i32>) -> () +!CHECK: %[[OMP_OUT_VAL:.*]] = fir.load %[[OMP_OUT_DECL]]#0 : !fir.ref<i32> +!CHECK: omp.yield(%[[OMP_OUT_VAL]] : i32) +!CHECK: } +!CHECK: func.func @_QPcombine_me(%[[OUT:.*]]: !fir.ref<i32> {fir.bindc_name = "out"}, %[[IN:.*]]: !fir.ref<i32> {fir.bindc_name = "in"}) { +!CHECK: %[[SCOPE:.*]] = fir.dummy_scope : !fir.dscope +!CHECK: %[[IN_DECL:.*]]:2 = hlfir.declare %[[IN]] dummy_scope %[[SCOPE]] arg 2 {uniq_name = "_QFcombine_meEin"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: %[[OUT_DECL:.*]]:2 = hlfir.declare %[[OUT]] dummy_scope %[[SCOPE]] arg 1 {uniq_name = "_QFcombine_meEout"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: %[[OUT_VAL:.*]] = fir.load %[[OUT_DECL]]#0 : !fir.ref<i32> +!CHECK: %[[IN_VAL:.*]] = fir.load %[[IN_DECL]]#0 : !fir.ref<i32> +!CHECK: %[[SUM:.*]] = arith.addi %[[OUT_VAL]], %[[IN_VAL]] : i32 +!CHECK: hlfir.assign %[[SUM]] to %[[OUT_DECL]]#0 : i32, !fir.ref<i32> +!CHECK: return +!CHECK: } +!$omp declare reduction(red_add:integer(4):combine_me(omp_out,omp_in)) initializer(omp_priv=0) + res=0 +!$omp simd reduction(red_add:res) + do i=1,n + res=res+x(i) + enddo + func=res +end function func + diff --git a/flang/test/Lower/OpenMP/omp-declare-reduction-derivedtype.f90 b/flang/test/Lower/OpenMP/omp-declare-reduction-derivedtype.f90 new file mode 100644 index 0000000..36bb131 --- /dev/null +++ b/flang/test/Lower/OpenMP/omp-declare-reduction-derivedtype.f90 @@ -0,0 +1,112 @@ +! This test checks lowering of OpenMP declare reduction Directive, with initialization +! via a subroutine. This functionality is currently not implemented. + +!RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=52 %s -o - | FileCheck %s +module maxtype_mod + implicit none + + type maxtype + integer::sumval + integer::maxval + end type maxtype + +contains + + subroutine initme(x,n) + type(maxtype) :: x,n + x%sumval=0 + x%maxval=0 + end subroutine initme + + function mycombine(lhs, rhs) + type(maxtype) :: lhs, rhs + type(maxtype) :: mycombine + mycombine%sumval = lhs%sumval + rhs%sumval + mycombine%maxval = max(lhs%maxval, rhs%maxval) + end function mycombine + + function func(x, n, init) + type(maxtype) :: func + integer :: n, i + type(maxtype) :: x(n) + type(maxtype) :: init + type(maxtype) :: res +!$omp declare reduction(red_add_max:maxtype:omp_out=mycombine(omp_out,omp_in)) initializer(initme(omp_priv,omp_orig)) + res=init +!$omp simd reduction(red_add_max:res) + do i=1,n + res=mycombine(res,x(i)) + enddo + func=res + end function func + +end module maxtype_mod +!CHECK: omp.declare_reduction @red_add_max : [[MAXTYPE:.*]] init { +!CHECK: ^bb0(%[[OMP_ORIG_ARG_I:.*]]: [[MAXTYPE]]): +!CHECK: %[[OMP_PRIV:.*]] = fir.alloca [[MAXTYPE]] +!CHECK: %[[OMP_ORIG:.*]] = fir.alloca [[MAXTYPE]] +!CHECK: fir.store %[[OMP_ORIG_ARG_I]] to %[[OMP_ORIG]] : !fir.ref<[[MAXTYPE]]> +!CHECK: %[[OMP_ORIG_DECL:.*]]:2 = hlfir.declare %[[OMP_ORIG]] {uniq_name = "omp_orig"} : (!fir.ref<[[MAXTYPE]]>) -> (!fir.ref<[[MAXTYPE]]>, !fir.ref<[[MAXTYPE]]>) +!CHECK: fir.store %[[OMP_ORIG_ARG_I]] to %[[OMP_PRIV]] : !fir.ref<[[MAXTYPE]]> +!CHECK: %[[OMP_PRIV_DECL:.*]]:2 = hlfir.declare %[[OMP_PRIV]] {uniq_name = "omp_priv"} : (!fir.ref<[[MAXTYPE]]>) -> (!fir.ref<[[MAXTYPE]]>, !fir.ref<[[MAXTYPE]]>) +!CHECK: fir.call @_QMmaxtype_modPinitme(%[[OMP_PRIV_DECL]]#0, %[[OMP_ORIG_DECL]]#0) fastmath<contract> : (!fir.ref<[[MAXTYPE]]>, !fir.ref<[[MAXTYPE]]>) -> () +!CHECK: %[[OMP_PRIV_VAL:.*]] = fir.load %[[OMP_PRIV_DECL]]#0 : !fir.ref<[[MAXTYPE]]> +!CHECK: omp.yield(%[[OMP_PRIV_VAL]] : [[MAXTYPE]]) +!CHECK: } combiner { +!CHECK: ^bb0(%[[LHS_ARG:.*]]: [[MAXTYPE]], %[[RHS_ARG:.*]]: [[MAXTYPE]]): +!CHECK: %[[RESULT:.*]] = fir.alloca [[MAXTYPE]] {bindc_name = ".result"} +!CHECK: %[[OMP_OUT:.*]] = fir.alloca [[MAXTYPE]] +!CHECK: %[[OMP_IN:.*]] = fir.alloca [[MAXTYPE]] +!CHECK: fir.store %[[RHS_ARG]] to %[[OMP_IN]] : !fir.ref<[[MAXTYPE]]> +!CHECK: %[[OMP_IN_DECL:.*]]:2 = hlfir.declare %[[OMP_IN]] {uniq_name = "omp_in"} : (!fir.ref<[[MAXTYPE]]>) -> (!fir.ref<[[MAXTYPE]]>, !fir.ref<[[MAXTYPE]]>) +!CHECK: fir.store %[[LHS_ARG]] to %[[OMP_OUT]] : !fir.ref<[[MAXTYPE]]> +!CHECK: %[[OMP_OUT_DECL:.*]]:2 = hlfir.declare %[[OMP_OUT]] {uniq_name = "omp_out"} : (!fir.ref<[[MAXTYPE]]>) -> (!fir.ref<[[MAXTYPE]]>, !fir.ref<[[MAXTYPE]]>) +!CHECK: %[[COMBINE_RESULT:.*]] = fir.call @_QMmaxtype_modPmycombine(%[[OMP_OUT_DECL]]#0, %[[OMP_IN_DECL]]#0) fastmath<contract> : (!fir.ref<[[MAXTYPE]]>, !fir.ref<[[MAXTYPE]]>) -> [[MAXTYPE]] +!CHECK: fir.save_result %[[COMBINE_RESULT]] to %[[RESULT]] : [[MAXTYPE]], !fir.ref<[[MAXTYPE]]> +!CHECK: %[[TMPRESULT:.*]]:2 = hlfir.declare %[[RESULT]] {uniq_name = ".tmp.func_result"} : (!fir.ref<[[MAXTYPE]]>) -> (!fir.ref<[[MAXTYPE]]>, !fir.ref<[[MAXTYPE]]>) +!CHECK: %false = arith.constant false +!CHECK: %[[EXPRRESULT:.*]] = hlfir.as_expr %[[TMPRESULT]]#0 move %false : (!fir.ref<[[MAXTYPE]]>, i1) -> !hlfir.expr<[[MAXTYPE]]> +!CHECK: %[[ASSOCIATE:.*]]:3 = hlfir.associate %[[EXPRRESULT]] {adapt.valuebyref} : (!hlfir.expr<[[MAXTYPE]]>) -> (!fir.ref<[[MAXTYPE]]>, !fir.ref<[[MAXTYPE]]>, i1) +!CHECK: %[[RESULT_VAL:.*]] = fir.load %[[ASSOCIATE]]#0 : !fir.ref<[[MAXTYPE]]> +!CHECK: hlfir.end_associate %[[ASSOCIATE]]#1, %[[ASSOCIATE]]#2 : !fir.ref<[[MAXTYPE]]>, i1 +!CHECK: omp.yield(%[[RESULT_VAL]] : [[MAXTYPE]]) +!CHECK: } + +!CHECK: func.func @_QMmaxtype_modPinitme(%[[X_ARG:.*]]: !fir.ref<[[MAXTYPE]]> {fir.bindc_name = "x"}, %[[N_ARG:.*]]: !fir.ref<[[MAXTYPE]]> {fir.bindc_name = "n"}) { +!CHECK: %[[SCOPE:.*]] = fir.dummy_scope : !fir.dscope +!CHECK: %[[N_DECL:.*]]:2 = hlfir.declare %[[N_ARG]] dummy_scope %[[SCOPE]] arg 2 {uniq_name = "_QMmaxtype_modFinitmeEn"} : (!fir.ref<[[MAXTYPE]]>, !fir.dscope) -> (!fir.ref<[[MAXTYPE]]>, !fir.ref<[[MAXTYPE]]>) +!CHECK: %[[X_DECL:.*]]:2 = hlfir.declare %[[X_ARG]] dummy_scope %[[SCOPE]] arg 1 {uniq_name = "_QMmaxtype_modFinitmeEx"} : (!fir.ref<[[MAXTYPE]]>, !fir.dscope) -> (!fir.ref<[[MAXTYPE]]>, !fir.ref<[[MAXTYPE]]>) +!CHECK: %[[ZERO_0:.*]] = arith.constant 0 : i32 +!CHECK: %[[X_DESIGNATE_SUMVAL:.*]] = hlfir.designate %[[X_DECL]]#0{"sumval"} : (!fir.ref<[[MAXTYPE]]>) -> !fir.ref<i32> +!CHECK: hlfir.assign %[[ZERO_0]] to %[[X_DESIGNATE_SUMVAL]] : i32, !fir.ref<i32> +!CHECK: %[[ZERO_1:.*]] = arith.constant 0 : i32 +!CHECK: %[[X_DESIGNATE_MAXVAL:.*]] = hlfir.designate %[[X_DECL]]#0{"maxval"} : (!fir.ref<[[MAXTYPE]]>) -> !fir.ref<i32> +!CHECK: hlfir.assign %[[ZERO_1]] to %[[X_DESIGNATE_MAXVAL]] : i32, !fir.ref<i32> +!CHECK: return +!CHECK: } + + +!CHECK: func.func @_QMmaxtype_modPmycombine(%[[LHS:.*]]: !fir.ref<[[MAXTYPE]]> {fir.bindc_name = "lhs"}, %[[RHS:.*]]: !fir.ref<[[MAXTYPE]]> {fir.bindc_name = "rhs"}) -> [[MAXTYPE]] { +!CHECK: %[[SCOPE:.*]] = fir.dummy_scope : !fir.dscope +!CHECK: %[[LHS_DECL:.*]]:2 = hlfir.declare %[[LHS]] dummy_scope %[[SCOPE]] arg 1 {uniq_name = "_QMmaxtype_modFmycombineElhs"} : (!fir.ref<[[MAXTYPE]]>, !fir.dscope) -> (!fir.ref<[[MAXTYPE]]>, !fir.ref<[[MAXTYPE]]>) +!CHECK: %[[RESULT_ALLOC:.*]] = fir.alloca [[MAXTYPE]] {bindc_name = "mycombine", uniq_name = "_QMmaxtype_modFmycombineEmycombine"} +!CHECK: %[[RESULT_DECL:.*]]:2 = hlfir.declare %[[RESULT_ALLOC]] {uniq_name = "_QMmaxtype_modFmycombineEmycombine"} : (!fir.ref<[[MAXTYPE]]>) -> (!fir.ref<[[MAXTYPE]]>, !fir.ref<[[MAXTYPE]]>) +!CHECK: %[[RHS_DECL:.*]]:2 = hlfir.declare %[[RHS]] dummy_scope %[[SCOPE]] arg 2 {uniq_name = "_QMmaxtype_modFmycombineErhs"} : (!fir.ref<[[MAXTYPE]]>, !fir.dscope) -> (!fir.ref<[[MAXTYPE]]>, !fir.ref<[[MAXTYPE]]>) +!CHECK: %[[LHS_DESIGNATE_SUMVAL:.*]] = hlfir.designate %[[LHS_DECL]]#0{"sumval"} : (!fir.ref<[[MAXTYPE]]>) -> !fir.ref<i32> +!CHECK: %[[LHS_SUMVAL:.*]] = fir.load %[[LHS_DESIGNATE_SUMVAL]] : !fir.ref<i32> +!CHECK: %[[RHS_DESIGNATE_SUMVAL:.*]] = hlfir.designate %[[RHS_DECL]]#0{"sumval"} : (!fir.ref<[[MAXTYPE]]>) -> !fir.ref<i32> +!CHECK: %[[RHS_SUMVAL:.*]] = fir.load %[[RHS_DESIGNATE_SUMVAL]] : !fir.ref<i32> +!CHECK: %[[SUM:.*]] = arith.addi %[[LHS_SUMVAL]], %[[RHS_SUMVAL]] : i32 +!CHECK: %[[RESULT_DESIGNATE_SUMVAL:.*]] = hlfir.designate %[[RESULT_DECL]]#0{"sumval"} : (!fir.ref<[[MAXTYPE]]>) -> !fir.ref<i32> +!CHECK: hlfir.assign %[[SUM]] to %[[RESULT_DESIGNATE_SUMVAL]] : i32, !fir.ref<i32> +!CHECK: %[[LHS_DESIGNATE_MAXVAL:.*]] = hlfir.designate %[[LHS_DECL]]#0{"maxval"} : (!fir.ref<[[MAXTYPE]]>) -> !fir.ref<i32> +!CHECK: %[[LHS_MAXVAL:.*]] = fir.load %[[LHS_DESIGNATE_MAXVAL]] : !fir.ref<i32> +!CHECK: %[[RHS_DESIGNATE_MAXVAL:.*]] = hlfir.designate %[[RHS_DECL]]#0{"maxval"} : (!fir.ref<[[MAXTYPE]]>) -> !fir.ref<i32> +!CHECK: %[[RHS_MAXVAL:.*]] = fir.load %[[RHS_DESIGNATE_MAXVAL]] : !fir.ref<i32> +!CHECK: %[[CMP:.*]] = arith.cmpi sgt, %[[LHS_MAXVAL]], %[[RHS_MAXVAL]] : i32 +!CHECK: %[[MAX_VAL:.*]] = arith.select %[[CMP]], %[[LHS_MAXVAL]], %[[RHS_MAXVAL]] : i32 +!CHECK: %[[RESULT_DESIGNAGE_MAXVAL:.*]] = hlfir.designate %[[RESULT_DECL]]#0{"maxval"} : (!fir.ref<[[MAXTYPE]]>) -> !fir.ref<i32> +!CHECK: hlfir.assign %[[MAX_VAL]] to %[[RESULT_DESIGNAGE_MAXVAL]] : i32, !fir.ref<i32> +!CHECK: %[[RESULT:.*]] = fir.load %[[RESULT_DECL]]#0 : !fir.ref<[[MAXTYPE]]> +!CHECK: return %[[RESULT]] : [[MAXTYPE]] +!CHECK: } diff --git a/flang/test/Lower/OpenMP/omp-declare-reduction-initsub.f90 b/flang/test/Lower/OpenMP/omp-declare-reduction-initsub.f90 new file mode 100644 index 0000000..4aacc7c --- /dev/null +++ b/flang/test/Lower/OpenMP/omp-declare-reduction-initsub.f90 @@ -0,0 +1,59 @@ +! This test checks lowering of OpenMP declare reduction Directive, with initialization +! via a subroutine. This functionality is currently not implemented. + +!RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=52 %s -o - | FileCheck %s + +subroutine initme(x,n) + integer x,n + x=0 +end subroutine initme + +function func(x, n, init) + integer func + integer x(n) + integer res + interface + subroutine initme(x,n) + integer x,n + end subroutine initme + end interface +!CHECK: omp.declare_reduction @red_add : i32 init { +!CHECK: ^bb0(%[[OMP_ORIG_ARG_I:.*]]: i32): +!CHECK: %[[OMP_PRIV:.*]] = fir.alloca i32 +!CHECK: %[[OMP_ORIG:.*]] = fir.alloca i32 +!CHECK: fir.store %[[OMP_ORIG_ARG_I]] to %[[OMP_ORIG]] : !fir.ref<i32> +!CHECK: %[[OMP_ORIG_DECL:.*]]:2 = hlfir.declare %[[OMP_ORIG]] {uniq_name = "omp_orig"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: fir.store %[[OMP_ORIG_ARG_I]] to %[[OMP_PRIV]] : !fir.ref<i32> +!CHECK: %[[OMP_PRIV_DECL:.*]]:2 = hlfir.declare %[[OMP_PRIV]] {uniq_name = "omp_priv"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: fir.call @_QPinitme(%[[OMP_PRIV_DECL]]#0, %[[OMP_ORIG_DECL]]#0) fastmath<contract> : (!fir.ref<i32>, !fir.ref<i32>) -> () +!CHECK: %[[OMP_PRIV_VAL:.*]] = fir.load %[[OMP_PRIV_DECL]]#0 : !fir.ref<i32> +!CHECK: omp.yield(%[[OMP_PRIV_VAL]] : i32) +!CHECK: } combiner { +!CHECK: ^bb0(%[[LHS_ARG:.*]]: i32, %[[RHS_ARG:.*]]: i32): +!CHECK: %[[OMP_OUT:.*]] = fir.alloca i32 +!CHECK: %[[OMP_IN:.*]] = fir.alloca i32 +!CHECK: fir.store %[[RHS_ARG]] to %[[OMP_IN]] : !fir.ref<i32> +!CHECK: %[[OMP_IN_DECL:.*]]:2 = hlfir.declare %[[OMP_IN]] {uniq_name = "omp_in"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: fir.store %[[LHS_ARG]] to %[[OMP_OUT]] : !fir.ref<i32> +!CHECK: %[[OMP_OUT_DECL:.*]]:2 = hlfir.declare %[[OMP_OUT]] {uniq_name = "omp_out"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: %[[OMP_OUT_VAL:.*]] = fir.load %[[OMP_OUT_DECL]]#0 : !fir.ref<i32> +!CHECK: %[[OMP_IN_VAL:.*]] = fir.load %[[OMP_IN_DECL]]#0 : !fir.ref<i32> +!CHECK: %[[SUM:.*]] = arith.addi %[[OMP_OUT_VAL]], %[[OMP_IN_VAL]] : i32 +!CHECK: omp.yield(%[[SUM]] : i32) +!CHECK: } +!CHECK: func.func @_QPinitme(%[[X:.*]]: !fir.ref<i32> {fir.bindc_name = "x"}, %[[N:.*]]: !fir.ref<i32> {fir.bindc_name = "n"}) { +!CHECK: %[[SCOPE:.*]] = fir.dummy_scope : !fir.dscope +!CHECK: %[[N_DECL:.*]]:2 = hlfir.declare %[[N]] dummy_scope %[[SCOPE]] arg 2 {uniq_name = "_QFinitmeEn"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: %[[X_DECL:.*]]:2 = hlfir.declare %[[X]] dummy_scope %[[OMP_OUT]] arg 1 {uniq_name = "_QFinitmeEx"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: %[[CONST_0:.*]] = arith.constant 0 : i32 +!CHECK: hlfir.assign %[[CONST_0]] to %[[X_DECL]]#0 : i32, !fir.ref<i32> +!CHECK: return +!CHECK: } +!$omp declare reduction(red_add:integer(4):omp_out=omp_out+omp_in) initializer(initme(omp_priv,omp_orig)) + res=init +!$omp simd reduction(red_add:res) + do i=1,n + res=res+x(i) + enddo + func=res +end function func diff --git a/flang/test/Lower/OpenMP/omp-declare-reduction.f90 b/flang/test/Lower/OpenMP/omp-declare-reduction.f90 new file mode 100644 index 0000000..a41f6b2 --- /dev/null +++ b/flang/test/Lower/OpenMP/omp-declare-reduction.f90 @@ -0,0 +1,33 @@ +! This test checks lowering of OpenMP declare reduction Directive. + +!RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=52 %s -o - | FileCheck %s + +subroutine declare_red() + integer :: my_var +!CHECK: omp.declare_reduction @my_red : i32 init { +!CHECK: ^bb0(%[[OMP_ORIG_ARG_I:.*]]: i32): +!CHECK: %[[OMP_PRIV:.*]] = fir.alloca i32 +!CHECK: %[[OMP_ORIG:.*]] = fir.alloca i32 +!CHECK: fir.store %[[OMP_ORIG_ARG_I]] to %[[OMP_ORIG]] : !fir.ref<i32> +!CHECK: %[[OMP_ORIG_DECL:.*]]:2 = hlfir.declare %[[OMP_ORIG]] {uniq_name = "omp_orig"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: fir.store %[[OMP_ORIG_ARG_I]] to %[[OMP_PRIV]] : !fir.ref<i32> +!CHECK: %[[OMP_PRIV_DECL:.*]]:2 = hlfir.declare %[[OMP_PRIV]] {uniq_name = "omp_priv"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: %[[CONST_0:.*]] = arith.constant 0 : i32 +!CHECK: omp.yield(%[[CONST_0]] : i32) +!CHECK: } combiner { +!CHECK: ^bb0(%[[LHS_ARG:.*]]: i32, %[[RHS_ARG:.*]]: i32): +!CHECK: %[[OMP_OUT:.*]] = fir.alloca i32 +!CHECK: %[[OMP_IN:.*]] = fir.alloca i32 +!CHECK: fir.store %[[RHS_ARG]] to %[[OMP_IN]] : !fir.ref<i32> +!CHECK: %[[OMP_IN_DECL:.*]]:2 = hlfir.declare %[[OMP_IN]] {uniq_name = "omp_in"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: fir.store %[[LHS_ARG]] to %[[OMP_OUT]] : !fir.ref<i32> +!CHECK: %[[OMP_OUT_DECL:.*]]:2 = hlfir.declare %[[OMP_OUT]] {uniq_name = "omp_out"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: %[[OMP_OUT_VAL:.*]] = fir.load %[[OMP_OUT_DECL]]#0 : !fir.ref<i32> +!CHECK: %[[OMP_IN_VAL:.*]] = fir.load %[[OMP_IN_DECL]]#0 : !fir.ref<i32> +!CHECK: %[[SUM:.*]] = arith.addi %[[OMP_OUT_VAL]], %[[OMP_IN_VAL]] : i32 +!CHECK: omp.yield(%[[SUM]] : i32) +!CHECK: } + + !$omp declare reduction (my_red : integer : omp_out = omp_out + omp_in) initializer (omp_priv = 0) + my_var = 0 +end subroutine declare_red diff --git a/flang/test/Lower/OpenMP/optional-argument-map-2.f90 b/flang/test/Lower/OpenMP/optional-argument-map-2.f90 index 791d509..7b67fd3 100644 --- a/flang/test/Lower/OpenMP/optional-argument-map-2.f90 +++ b/flang/test/Lower/OpenMP/optional-argument-map-2.f90 @@ -28,7 +28,7 @@ end module mod ! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>> {fir.bindc_name = "a", fir.optional}) { ! CHECK: %[[VAL_0:.*]] = fir.alloca !fir.box<!fir.heap<!fir.array<?xf32>>> ! CHECK: %[[VAL_1:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %[[VAL_1]] {fortran_attrs = #fir.var_attrs<allocatable, intent_inout, optional>, uniq_name = "_QMmodFroutine_boxEa"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %[[VAL_1]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable, intent_inout, optional>, uniq_name = "_QMmodFroutine_boxEa"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>) ! CHECK: %[[VAL_8:.*]] = fir.is_present %[[VAL_2]]#1 : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>) -> i1 ! CHECK: %[[VAL_9:.*]]:5 = fir.if %[[VAL_8]] -> (index, index, index, index, index) { ! CHECK: %[[VAL_10:.*]] = fir.load %[[VAL_2]]#0 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>> @@ -58,7 +58,7 @@ end module mod ! CHECK: %[[VAL_0:.*]] = fir.alloca !fir.boxchar<1> ! CHECK: %[[VAL_1:.*]] = fir.dummy_scope : !fir.dscope ! CHECK: %[[VAL_2:.*]]:2 = fir.unboxchar %[[ARG0]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index) -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]]#0 typeparams %[[VAL_2]]#1 dummy_scope %[[VAL_1]] {fortran_attrs = #fir.var_attrs<intent_in, optional>, uniq_name = "_QMmodFroutine_boxcharEa"} : (!fir.ref<!fir.char<1,?>>, index, !fir.dscope) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]]#0 typeparams %[[VAL_2]]#1 dummy_scope %[[VAL_1]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<intent_in, optional>, uniq_name = "_QMmodFroutine_boxcharEa"} : (!fir.ref<!fir.char<1,?>>, index, !fir.dscope) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>) ! CHECK: %[[VAL_4:.*]] = arith.constant 4 : index ! CHECK: %[[VAL_5:.*]] = fir.alloca !fir.char<1,4> {bindc_name = "b", uniq_name = "_QMmodFroutine_boxcharEb"} ! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_5]] typeparams %[[VAL_4]] {uniq_name = "_QMmodFroutine_boxcharEb"} : (!fir.ref<!fir.char<1,4>>, index) -> (!fir.ref<!fir.char<1,4>>, !fir.ref<!fir.char<1,4>>) @@ -71,11 +71,10 @@ end module mod ! CHECK-FPRIV: %[[VAL_12:.*]]:2 = fir.unboxchar %[[VAL_8]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index) ! CHECK-FPRIV: %[[VAL_13:.*]] = arith.subi %[[VAL_12]]#1, %[[VAL_11]] : index ! CHECK-FPRIV: %[[VAL_14:.*]] = omp.map.bounds lower_bound(%[[VAL_10]] : index) upper_bound(%[[VAL_13]] : index) extent(%[[VAL_12]]#1 : index) stride(%[[VAL_11]] : index) start_idx(%[[VAL_10]] : index) {stride_in_bytes = true} -! CHECK-FPRIV: %[[VAL_15:.*]] = fir.load %[[VAL_0]] : !fir.ref<!fir.boxchar<1>> ! CHECK-FPRIV: %[[VAL_16:.*]] = fir.box_offset %[[VAL_0]] base_addr : (!fir.ref<!fir.boxchar<1>>) -> !fir.llvm_ptr<!fir.ref<!fir.char<1,?>>> -! CHECK-FPRIV: %[[VAL_17:.*]] = omp.map.info var_ptr(%[[VAL_0]] : !fir.ref<!fir.boxchar<1>>, !fir.char<1,?>) map_clauses(implicit, to) capture(ByRef) var_ptr_ptr(%[[VAL_16]] : !fir.llvm_ptr<!fir.ref<!fir.char<1,?>>>) bounds(%[[VAL_14]]) -> !fir.ref<!fir.boxchar<1>> -! CHECK-FPRIV: %[[VAL_18:.*]] = omp.map.info var_ptr(%[[VAL_0]] : !fir.ref<!fir.boxchar<1>>, !fir.boxchar<1>) map_clauses(to) capture(ByRef) members(%[[VAL_17]] : [0] : !fir.ref<!fir.boxchar<1>>) -> !fir.ref<!fir.boxchar<1>> -! CHECK-FPRIV: omp.target map_entries(%[[VAL_7]] -> %[[VAL_19:.*]], %[[VAL_18]] -> %[[VAL_20:.*]], %[[VAL_17]] -> %[[VAL_21:.*]] : !fir.ref<!fir.char<1,4>>, !fir.ref<!fir.boxchar<1>>, !fir.ref<!fir.boxchar<1>>) private(@_QMmodFroutine_boxcharEa_firstprivate_boxchar_c8xU %[[VAL_3]]#0 -> %[[VAL_22:.*]] [map_idx=1] : !fir.boxchar<1>) { +! CHECK-FPRIV: %[[VAL_17:.*]] = omp.map.info var_ptr(%[[VAL_0]] : !fir.ref<!fir.boxchar<1>>, !fir.char<1,?>) map_clauses(tofrom) capture(ByRef) var_ptr_ptr(%[[VAL_16]] : !fir.llvm_ptr<!fir.ref<!fir.char<1,?>>>) bounds(%[[VAL_14]]) -> !fir.llvm_ptr<!fir.ref<!fir.char<1,?>>> {name = ""} +! CHECK-FPRIV: %[[VAL_18:.*]] = omp.map.info var_ptr(%[[VAL_0]] : !fir.ref<!fir.boxchar<1>>, !fir.boxchar<1>) map_clauses(always, to) capture(ByRef) members(%[[VAL_17]] : [0] : !fir.llvm_ptr<!fir.ref<!fir.char<1,?>>>) -> !fir.ref<!fir.boxchar<1>> +! CHECK-FPRIV: omp.target map_entries(%[[VAL_7]] -> %[[VAL_19:.*]], %[[VAL_18]] -> %[[VAL_20:.*]], %[[VAL_17]] -> %[[VAL_21:.*]] : !fir.ref<!fir.char<1,4>>, !fir.ref<!fir.boxchar<1>>, !fir.llvm_ptr<!fir.ref<!fir.char<1,?>>>) private(@_QMmodFroutine_boxcharEa_firstprivate_boxchar_c8xU %[[VAL_3]]#0 -> %[[VAL_22:.*]] [map_idx=1] : !fir.boxchar<1>) { ! CHECK-FPRIV: %[[VAL_23:.*]] = arith.constant 4 : index ! CHECK-FPRIV: %[[VAL_24:.*]]:2 = hlfir.declare %[[VAL_19]] typeparams %[[VAL_23]] {uniq_name = "_QMmodFroutine_boxcharEb"} : (!fir.ref<!fir.char<1,4>>, index) -> (!fir.ref<!fir.char<1,4>>, !fir.ref<!fir.char<1,4>>) ! CHECK-FPRIV: %[[VAL_25:.*]]:2 = fir.unboxchar %[[VAL_22]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index) @@ -103,14 +102,16 @@ end module mod ! CHECK-NO-FPRIV: %[[VAL_19:.*]]:2 = fir.unboxchar %[[ARG0]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index) ! CHECK-NO-FPRIV: %[[VAL_20:.*]] = arith.subi %[[VAL_19]]#1, %[[VAL_18]] : index ! CHECK-NO-FPRIV: %[[VAL_21:.*]] = omp.map.bounds lower_bound(%[[VAL_17]] : index) upper_bound(%[[VAL_20]] : index) extent(%[[VAL_19]]#1 : index) stride(%[[VAL_18]] : index) start_idx(%[[VAL_17]] : index) {stride_in_bytes = true} -! CHECK-NO-FPRIV: %[[VAL_22:.*]] = omp.map.info var_ptr(%[[VAL_0]] : !fir.ref<!fir.boxchar<1>>, !fir.boxchar<1>) map_clauses(implicit, to) capture(ByRef) bounds(%[[VAL_21]]) -> !fir.ref<!fir.boxchar<1>> {name = ""} -! CHECK-NO-FPRIV: omp.target map_entries(%[[VAL_7]] -> %[[VAL_23:.*]], %[[VAL_16]] -> %[[VAL_24:.*]], %[[VAL_22]] -> %[[VAL_25:.*]] : !fir.ref<!fir.char<1,4>>, !fir.ref<!fir.char<1,?>>, !fir.ref<!fir.boxchar<1>>) { -! CHECK-NO-FPRIV: %[[VAL_26:.*]] = fir.load %[[VAL_25]] : !fir.ref<!fir.boxchar<1>> -! CHECK-NO-FPRIV: %[[VAL_27:.*]]:2 = fir.unboxchar %[[VAL_26]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index) -! CHECK-NO-FPRIV: %[[VAL_28:.*]] = arith.constant 4 : index -! CHECK-NO-FPRIV: %[[VAL_29:.*]]:2 = hlfir.declare %[[VAL_23]] typeparams %[[VAL_28]] {uniq_name = "_QMmodFroutine_boxcharEb"} : (!fir.ref<!fir.char<1,4>>, index) -> (!fir.ref<!fir.char<1,4>>, !fir.ref<!fir.char<1,4>>) -! CHECK-NO-FPRIV: %[[VAL_30:.*]]:2 = hlfir.declare %[[VAL_24]] typeparams %[[VAL_27]]#1 {fortran_attrs = #fir.var_attrs<intent_in, optional>, uniq_name = "_QMmodFroutine_boxcharEa"} : (!fir.ref<!fir.char<1,?>>, index) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>) -! CHECK-NO-FPRIV: hlfir.assign %[[VAL_30]]#0 to %[[VAL_29]]#0 : !fir.boxchar<1>, !fir.ref<!fir.char<1,4>> +! CHECK-NO-FPRIV: %[[VAL_22:.*]] = fir.box_offset %[[VAL_0]] base_addr : (!fir.ref<!fir.boxchar<1>>) -> !fir.llvm_ptr<!fir.ref<!fir.char<1,?>>> +! CHECK-NO-FPRIV: %[[VAL_23:.*]] = omp.map.info var_ptr(%[[VAL_0]] : !fir.ref<!fir.boxchar<1>>, !fir.char<1,?>) map_clauses(implicit, to) capture(ByRef) var_ptr_ptr(%[[VAL_22]] : !fir.llvm_ptr<!fir.ref<!fir.char<1,?>>>) bounds(%14) -> !fir.llvm_ptr<!fir.ref<!fir.char<1,?>>> {name = ""} +! CHECK-NO-FPRIV: %[[VAL_24:.*]] = omp.map.info var_ptr(%[[VAL_0]] : !fir.ref<!fir.boxchar<1>>, !fir.boxchar<1>) map_clauses(always, implicit, to) capture(ByRef) members(%[[VAL_23]] : [0] : !fir.llvm_ptr<!fir.ref<!fir.char<1,?>>>) -> !fir.ref<!fir.boxchar<1>> {name = ""} +! CHECK-NO-FPRIV: omp.target map_entries(%[[VAL_7]] -> %[[VAL_25:.*]], %[[VAL_16]] -> %[[VAL_26:.*]], %[[VAL_24]] -> %[[VAL_27:.*]], %[[VAL_23]] -> %[[VAL_28:.*]] : !fir.ref<!fir.char<1,4>>, !fir.ref<!fir.char<1,?>>, !fir.ref<!fir.boxchar<1>>, !fir.llvm_ptr<!fir.ref<!fir.char<1,?>>>) { +! CHECK-NO-FPRIV: %[[VAL_29:.*]] = fir.load %[[VAL_27]] : !fir.ref<!fir.boxchar<1>> +! CHECK-NO-FPRIV: %[[VAL_30:.*]]:2 = fir.unboxchar %[[VAL_29]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index) +! CHECK-NO-FPRIV: %[[VAL_31:.*]] = arith.constant 4 : index +! CHECK-NO-FPRIV: %[[VAL_32:.*]]:2 = hlfir.declare %[[VAL_25]] typeparams %[[VAL_31]] {uniq_name = "_QMmodFroutine_boxcharEb"} : (!fir.ref<!fir.char<1,4>>, index) -> (!fir.ref<!fir.char<1,4>>, !fir.ref<!fir.char<1,4>>) +! CHECK-NO-FPRIV: %[[VAL_33:.*]]:2 = hlfir.declare %[[VAL_26]] typeparams %[[VAL_30]]#1 {fortran_attrs = #fir.var_attrs<intent_in, optional>, uniq_name = "_QMmodFroutine_boxcharEa"} : (!fir.ref<!fir.char<1,?>>, index) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>) +! CHECK-NO-FPRIV: hlfir.assign %[[VAL_33]]#0 to %[[VAL_32]]#0 : !fir.boxchar<1>, !fir.ref<!fir.char<1,4>> ! CHECK-NO-FPRIV: omp.terminator ! CHECK-NO-FPRIV: } ! CHECK-NO-FPRIV: return diff --git a/flang/test/Lower/OpenMP/optional-argument-map-3.f90 b/flang/test/Lower/OpenMP/optional-argument-map-3.f90 index 7e2a24e..4dab002 100644 --- a/flang/test/Lower/OpenMP/optional-argument-map-3.f90 +++ b/flang/test/Lower/OpenMP/optional-argument-map-3.f90 @@ -33,7 +33,7 @@ end module ! CHECK: } ! CHECK: %[[VAL_3:.*]] = fir.box_offset %[[VAL_0]] base_addr : (!fir.ref<!fir.box<!fir.array<?xf32>>>) -> !fir.llvm_ptr<!fir.ref<!fir.array<?xf32>>> ! CHECK: %[[VAL_4:.*]] = omp.map.info var_ptr(%[[VAL_0]] : !fir.ref<!fir.box<!fir.array<?xf32>>>, f32) map_clauses(implicit, tofrom) capture(ByRef) var_ptr_ptr(%[[VAL_3]] : !fir.llvm_ptr<!fir.ref<!fir.array<?xf32>>>) bounds(%{{.*}}) -> !fir.llvm_ptr<!fir.ref<!fir.array<?xf32>>> {name = ""} -! CHECK: %[[VAL_5:.*]] = omp.map.info var_ptr(%[[VAL_0]] : !fir.ref<!fir.box<!fir.array<?xf32>>>, !fir.box<!fir.array<?xf32>>) map_clauses(implicit, to) capture(ByRef) members(%[[VAL_4]] : [0] : !fir.llvm_ptr<!fir.ref<!fir.array<?xf32>>>) -> !fir.ref<!fir.array<?xf32>> {name = "dt"} +! CHECK: %[[VAL_5:.*]] = omp.map.info var_ptr(%[[VAL_0]] : !fir.ref<!fir.box<!fir.array<?xf32>>>, !fir.box<!fir.array<?xf32>>) map_clauses(always, implicit, to) capture(ByRef) members(%[[VAL_4]] : [0] : !fir.llvm_ptr<!fir.ref<!fir.array<?xf32>>>) -> !fir.ref<!fir.array<?xf32>> {name = "dt"} ! CHECK: omp.target host_eval({{.*}}) map_entries({{.*}}%[[VAL_5]] -> {{.*}}, %[[VAL_4]] -> {{.*}} : {{.*}}) { ! CHECK: } else { ! CHECK: %[[VAL_6:.*]] = fir.is_present %[[VAL_1]]#1 : (!fir.box<!fir.array<?xf32>>) -> i1 @@ -42,5 +42,5 @@ end module ! CHECK: } ! CHECK: %[[VAL_7:.*]] = fir.box_offset %[[VAL_0]] base_addr : (!fir.ref<!fir.box<!fir.array<?xf32>>>) -> !fir.llvm_ptr<!fir.ref<!fir.array<?xf32>>> ! CHECK: %[[VAL_8:.*]] = omp.map.info var_ptr(%[[VAL_0]] : !fir.ref<!fir.box<!fir.array<?xf32>>>, f32) map_clauses(implicit, tofrom) capture(ByRef) var_ptr_ptr(%[[VAL_7]] : !fir.llvm_ptr<!fir.ref<!fir.array<?xf32>>>) bounds(%{{.*}}) -> !fir.llvm_ptr<!fir.ref<!fir.array<?xf32>>> {name = ""} -! CHECK: %[[VAL_9:.*]] = omp.map.info var_ptr(%[[VAL_0]] : !fir.ref<!fir.box<!fir.array<?xf32>>>, !fir.box<!fir.array<?xf32>>) map_clauses(implicit, to) capture(ByRef) members(%[[VAL_8]] : [0] : !fir.llvm_ptr<!fir.ref<!fir.array<?xf32>>>) -> !fir.ref<!fir.array<?xf32>> {name = "dt"} +! CHECK: %[[VAL_9:.*]] = omp.map.info var_ptr(%[[VAL_0]] : !fir.ref<!fir.box<!fir.array<?xf32>>>, !fir.box<!fir.array<?xf32>>) map_clauses(always, implicit, to) capture(ByRef) members(%[[VAL_8]] : [0] : !fir.llvm_ptr<!fir.ref<!fir.array<?xf32>>>) -> !fir.ref<!fir.array<?xf32>> {name = "dt"} ! CHECK: omp.target host_eval({{.*}}) map_entries({{.*}}, %[[VAL_9]] ->{{.*}}, %[[VAL_8]] -> {{.*}} : {{.*}}) { diff --git a/flang/test/Lower/OpenMP/order-clause.f90 b/flang/test/Lower/OpenMP/order-clause.f90 index d579907..9da7d90 100644 --- a/flang/test/Lower/OpenMP/order-clause.f90 +++ b/flang/test/Lower/OpenMP/order-clause.f90 @@ -36,15 +36,15 @@ end subroutine do_order !CHECK-LABEL: func.func @_QPdo_simd_order() { subroutine do_simd_order - !CHECK: omp.wsloop order(reproducible:concurrent) { + !CHECK: omp.wsloop order(reproducible:concurrent) !$omp do simd order(concurrent) do i = 1, 10 end do - !CHECK: omp.wsloop order(reproducible:concurrent) { + !CHECK: omp.wsloop order(reproducible:concurrent) !$omp do simd order(reproducible:concurrent) do i = 1, 10 end do - !CHECK: omp.wsloop order(unconstrained:concurrent) { + !CHECK: omp.wsloop order(unconstrained:concurrent) !$omp do simd order(unconstrained:concurrent) do i = 1, 10 end do @@ -53,7 +53,7 @@ end subroutine do_simd_order !CHECK-LABEL: func.func @_QPdo_simd_order_parallel() { subroutine do_simd_order_parallel !CHECK: omp.parallel { - !CHECK: omp.wsloop order(reproducible:concurrent) { + !CHECK: omp.wsloop order(reproducible:concurrent) !$omp parallel do simd order(reproducible:concurrent) do i = 1, 10 end do diff --git a/flang/test/Lower/OpenMP/parallel-firstprivate-clause-scalar.f90 b/flang/test/Lower/OpenMP/parallel-firstprivate-clause-scalar.f90 index 416d1ab..a049b43 100644 --- a/flang/test/Lower/OpenMP/parallel-firstprivate-clause-scalar.f90 +++ b/flang/test/Lower/OpenMP/parallel-firstprivate-clause-scalar.f90 @@ -23,8 +23,8 @@ !CHECK: } !CHECK-DAG: func @_QPfirstprivate_complex(%[[ARG1:.*]]: !fir.ref<complex<f32>>{{.*}}, %[[ARG2:.*]]: !fir.ref<complex<f64>>{{.*}}) { -!CHECK: %[[ARG1_DECL:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFfirstprivate_complexEarg1"} : (!fir.ref<complex<f32>>, !fir.dscope) -> (!fir.ref<complex<f32>>, !fir.ref<complex<f32>>) -!CHECK: %[[ARG2_DECL:.*]]:2 = hlfir.declare %[[ARG2]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFfirstprivate_complexEarg2"} : (!fir.ref<complex<f64>>, !fir.dscope) -> (!fir.ref<complex<f64>>, !fir.ref<complex<f64>>) +!CHECK: %[[ARG1_DECL:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFfirstprivate_complexEarg1"} : (!fir.ref<complex<f32>>, !fir.dscope) -> (!fir.ref<complex<f32>>, !fir.ref<complex<f32>>) +!CHECK: %[[ARG2_DECL:.*]]:2 = hlfir.declare %[[ARG2]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFfirstprivate_complexEarg2"} : (!fir.ref<complex<f64>>, !fir.dscope) -> (!fir.ref<complex<f64>>, !fir.ref<complex<f64>>) !CHECK: omp.parallel private(@[[ARG1_COMPLEX_PRIVATIZER]] %{{.*}}#0 -> %[[ARG1_PVT:.*]], @[[ARG2_COMPLEX_PRIVATIZER]] %{{.*}}#0 -> %[[ARG2_PVT:.*]] : {{.*}}) { !CHECK: %[[ARG1_PVT_DECL:.*]]:2 = hlfir.declare %[[ARG1_PVT]] {uniq_name = "_QFfirstprivate_complexEarg1"} : (!fir.ref<complex<f32>>) -> (!fir.ref<complex<f32>>, !fir.ref<complex<f32>>) !CHECK: %[[ARG2_PVT_DECL:.*]]:2 = hlfir.declare %[[ARG2_PVT]] {uniq_name = "_QFfirstprivate_complexEarg2"} : (!fir.ref<complex<f64>>) -> (!fir.ref<complex<f64>>, !fir.ref<complex<f64>>) @@ -43,12 +43,12 @@ subroutine firstprivate_complex(arg1, arg2) end subroutine !CHECK-DAG: func @_QPfirstprivate_integer(%[[ARG1:.*]]: !fir.ref<i32>{{.*}}, %[[ARG2:.*]]: !fir.ref<i8>{{.*}}, %[[ARG3:.*]]: !fir.ref<i16>{{.*}}, %[[ARG4:.*]]: !fir.ref<i32>{{.*}}, %[[ARG5:.*]]: !fir.ref<i64>{{.*}}, %[[ARG6:.*]]: !fir.ref<i128>{{.*}}) { -!CHECK: %[[ARG1_DECL:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFfirstprivate_integerEarg1"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) -!CHECK: %[[ARG2_DECL:.*]]:2 = hlfir.declare %[[ARG2]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFfirstprivate_integerEarg2"} : (!fir.ref<i8>, !fir.dscope) -> (!fir.ref<i8>, !fir.ref<i8>) -!CHECK: %[[ARG3_DECL:.*]]:2 = hlfir.declare %[[ARG3]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFfirstprivate_integerEarg3"} : (!fir.ref<i16>, !fir.dscope) -> (!fir.ref<i16>, !fir.ref<i16>) -!CHECK: %[[ARG4_DECL:.*]]:2 = hlfir.declare %[[ARG4]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFfirstprivate_integerEarg4"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) -!CHECK: %[[ARG5_DECL:.*]]:2 = hlfir.declare %[[ARG5]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFfirstprivate_integerEarg5"} : (!fir.ref<i64>, !fir.dscope) -> (!fir.ref<i64>, !fir.ref<i64>) -!CHECK: %[[ARG6_DECL:.*]]:2 = hlfir.declare %[[ARG6]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFfirstprivate_integerEarg6"} : (!fir.ref<i128>, !fir.dscope) -> (!fir.ref<i128>, !fir.ref<i128>) +!CHECK: %[[ARG1_DECL:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFfirstprivate_integerEarg1"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: %[[ARG2_DECL:.*]]:2 = hlfir.declare %[[ARG2]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFfirstprivate_integerEarg2"} : (!fir.ref<i8>, !fir.dscope) -> (!fir.ref<i8>, !fir.ref<i8>) +!CHECK: %[[ARG3_DECL:.*]]:2 = hlfir.declare %[[ARG3]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFfirstprivate_integerEarg3"} : (!fir.ref<i16>, !fir.dscope) -> (!fir.ref<i16>, !fir.ref<i16>) +!CHECK: %[[ARG4_DECL:.*]]:2 = hlfir.declare %[[ARG4]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFfirstprivate_integerEarg4"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: %[[ARG5_DECL:.*]]:2 = hlfir.declare %[[ARG5]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFfirstprivate_integerEarg5"} : (!fir.ref<i64>, !fir.dscope) -> (!fir.ref<i64>, !fir.ref<i64>) +!CHECK: %[[ARG6_DECL:.*]]:2 = hlfir.declare %[[ARG6]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFfirstprivate_integerEarg6"} : (!fir.ref<i128>, !fir.dscope) -> (!fir.ref<i128>, !fir.ref<i128>) !CHECK: omp.parallel private({{.*firstprivate.*}} {{.*}}#0 -> %[[ARG1_PVT:.*]], {{.*firstprivate.*}} {{.*}}#0 -> %[[ARG2_PVT:.*]], {{.*firstprivate.*}} {{.*}}#0 -> %[[ARG3_PVT:.*]], {{.*firstprivate.*}} {{.*}}#0 -> %[[ARG4_PVT:.*]], {{.*firstprivate.*}} {{.*}}#0 -> %[[ARG5_PVT:.*]], {{.*firstprivate.*}} {{.*}}#0 -> %[[ARG6_PVT:.*]] : {{.*}}) { !CHECK: %[[ARG1_PVT_DECL:.*]]:2 = hlfir.declare %[[ARG1_PVT]] {uniq_name = "_QFfirstprivate_integerEarg1"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) !CHECK: %[[ARG2_PVT_DECL:.*]]:2 = hlfir.declare %[[ARG2_PVT]] {uniq_name = "_QFfirstprivate_integerEarg2"} : (!fir.ref<i8>) -> (!fir.ref<i8>, !fir.ref<i8>) @@ -76,11 +76,11 @@ subroutine firstprivate_integer(arg1, arg2, arg3, arg4, arg5, arg6) end subroutine !CHECK-DAG: func @_QPfirstprivate_logical(%[[ARG1:.*]]: !fir.ref<!fir.logical<4>>{{.*}}, %[[ARG2:.*]]: !fir.ref<!fir.logical<1>>{{.*}}, %[[ARG3:.*]]: !fir.ref<!fir.logical<2>>{{.*}}, %[[ARG4:.*]]: !fir.ref<!fir.logical<4>>{{.*}}, %[[ARG5:.*]]: !fir.ref<!fir.logical<8>>{{.*}}) { -!CHECK: %[[ARG1_DECL:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFfirstprivate_logicalEarg1"} : (!fir.ref<!fir.logical<4>>, !fir.dscope) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) -!CHECK: %[[ARG2_DECL:.*]]:2 = hlfir.declare %[[ARG2]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFfirstprivate_logicalEarg2"} : (!fir.ref<!fir.logical<1>>, !fir.dscope) -> (!fir.ref<!fir.logical<1>>, !fir.ref<!fir.logical<1>>) -!CHECK: %[[ARG3_DECL:.*]]:2 = hlfir.declare %[[ARG3]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFfirstprivate_logicalEarg3"} : (!fir.ref<!fir.logical<2>>, !fir.dscope) -> (!fir.ref<!fir.logical<2>>, !fir.ref<!fir.logical<2>>) -!CHECK: %[[ARG4_DECL:.*]]:2 = hlfir.declare %[[ARG4]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFfirstprivate_logicalEarg4"} : (!fir.ref<!fir.logical<4>>, !fir.dscope) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) -!CHECK: %[[ARG5_DECL:.*]]:2 = hlfir.declare %[[ARG5]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFfirstprivate_logicalEarg5"} : (!fir.ref<!fir.logical<8>>, !fir.dscope) -> (!fir.ref<!fir.logical<8>>, !fir.ref<!fir.logical<8>>) +!CHECK: %[[ARG1_DECL:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFfirstprivate_logicalEarg1"} : (!fir.ref<!fir.logical<4>>, !fir.dscope) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) +!CHECK: %[[ARG2_DECL:.*]]:2 = hlfir.declare %[[ARG2]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFfirstprivate_logicalEarg2"} : (!fir.ref<!fir.logical<1>>, !fir.dscope) -> (!fir.ref<!fir.logical<1>>, !fir.ref<!fir.logical<1>>) +!CHECK: %[[ARG3_DECL:.*]]:2 = hlfir.declare %[[ARG3]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFfirstprivate_logicalEarg3"} : (!fir.ref<!fir.logical<2>>, !fir.dscope) -> (!fir.ref<!fir.logical<2>>, !fir.ref<!fir.logical<2>>) +!CHECK: %[[ARG4_DECL:.*]]:2 = hlfir.declare %[[ARG4]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFfirstprivate_logicalEarg4"} : (!fir.ref<!fir.logical<4>>, !fir.dscope) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) +!CHECK: %[[ARG5_DECL:.*]]:2 = hlfir.declare %[[ARG5]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFfirstprivate_logicalEarg5"} : (!fir.ref<!fir.logical<8>>, !fir.dscope) -> (!fir.ref<!fir.logical<8>>, !fir.ref<!fir.logical<8>>) !CHECK: omp.parallel private(@[[ARG1_LOGICAL_PRIVATIZER]] {{.*}}#0 -> %[[ARG1_PVT:.*]], @[[ARG2_LOGICAL_PRIVATIZER]] {{.*}}#0 -> %[[ARG2_PVT:.*]], {{.*firstprivate.*}} {{.*}}#0 -> %[[ARG3_PVT:.*]], {{.*firstprivate.*}} {{.*}}#0 -> %[[ARG4_PVT:.*]], {{.*firstprivate.*}} {{.*}}#0 -> %[[ARG5_PVT:.*]] : {{.*}}) { !CHECK: %[[ARG1_PVT_DECL:.*]]:2 = hlfir.declare %[[ARG1_PVT]] {uniq_name = "_QFfirstprivate_logicalEarg1"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) !CHECK: %[[ARG2_PVT_DECL:.*]]:2 = hlfir.declare %[[ARG2_PVT]] {uniq_name = "_QFfirstprivate_logicalEarg2"} : (!fir.ref<!fir.logical<1>>) -> (!fir.ref<!fir.logical<1>>, !fir.ref<!fir.logical<1>>) @@ -106,10 +106,10 @@ end subroutine !CHECK-LABEL: func @_QPfirstprivate_real( !CHECK-SAME: %[[ARG1:.*]]: !fir.ref<f32>{{.*}}, %[[ARG2:.*]]: !fir.ref<f16>{{.*}}, %[[ARG3:.*]]: !fir.ref<f32>{{.*}}, %[[ARG4:.*]]: !fir.ref<f64>{{.*}}) { -!CHECK: %[[ARG1_DECL:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFfirstprivate_realEarg1"} : (!fir.ref<f32>, !fir.dscope) -> (!fir.ref<f32>, !fir.ref<f32>) -!CHECK: %[[ARG2_DECL:.*]]:2 = hlfir.declare %[[ARG2]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFfirstprivate_realEarg2"} : (!fir.ref<f16>, !fir.dscope) -> (!fir.ref<f16>, !fir.ref<f16>) -!CHECK: %[[ARG3_DECL:.*]]:2 = hlfir.declare %[[ARG3]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFfirstprivate_realEarg3"} : (!fir.ref<f32>, !fir.dscope) -> (!fir.ref<f32>, !fir.ref<f32>) -!CHECK: %[[ARG4_DECL:.*]]:2 = hlfir.declare %[[ARG4]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFfirstprivate_realEarg4"} : (!fir.ref<f64>, !fir.dscope) -> (!fir.ref<f64>, !fir.ref<f64>) +!CHECK: %[[ARG1_DECL:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFfirstprivate_realEarg1"} : (!fir.ref<f32>, !fir.dscope) -> (!fir.ref<f32>, !fir.ref<f32>) +!CHECK: %[[ARG2_DECL:.*]]:2 = hlfir.declare %[[ARG2]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFfirstprivate_realEarg2"} : (!fir.ref<f16>, !fir.dscope) -> (!fir.ref<f16>, !fir.ref<f16>) +!CHECK: %[[ARG3_DECL:.*]]:2 = hlfir.declare %[[ARG3]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFfirstprivate_realEarg3"} : (!fir.ref<f32>, !fir.dscope) -> (!fir.ref<f32>, !fir.ref<f32>) +!CHECK: %[[ARG4_DECL:.*]]:2 = hlfir.declare %[[ARG4]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFfirstprivate_realEarg4"} : (!fir.ref<f64>, !fir.dscope) -> (!fir.ref<f64>, !fir.ref<f64>) !CHECK: omp.parallel private({{.*firstprivate.*}} {{.*}}#0 -> %[[ARG1_PVT:.*]], {{.*firstprivate.*}} {{.*}}#0 -> %[[ARG2_PVT:.*]], {{.*firstprivate.*}} {{.*}}#0 -> %[[ARG3_PVT:.*]], {{.*firstprivate.*}} {{.*}}#0 -> %[[ARG4_PVT:.*]] : {{.*}}) { !CHECK: %[[ARG1_PVT_DECL:.*]]:2 = hlfir.declare %[[ARG1_PVT]] {uniq_name = "_QFfirstprivate_realEarg1"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>) !CHECK: %[[ARG2_PVT_DECL:.*]]:2 = hlfir.declare %[[ARG2_PVT]] {uniq_name = "_QFfirstprivate_realEarg2"} : (!fir.ref<f16>) -> (!fir.ref<f16>, !fir.ref<f16>) @@ -132,7 +132,7 @@ end subroutine !CHECK-KIND10-LABEL: func @_QPfirstprivate_real10( !CHECK-KIND10-SAME: %[[ARG1:.*]]: !fir.ref<f80>{{.*}}) { -!CHECK-KIND10: %[[ARG1_DECL:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFfirstprivate_real10Earg1"} : (!fir.ref<f80>, !fir.dscope) -> (!fir.ref<f80>, !fir.ref<f80>) +!CHECK-KIND10: %[[ARG1_DECL:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFfirstprivate_real10Earg1"} : (!fir.ref<f80>, !fir.dscope) -> (!fir.ref<f80>, !fir.ref<f80>) !CHECK-KIND10: omp.parallel private({{.*firstprivate.*}} {{.*}}#0 -> %[[ARG1_PVT:.*]] : {{.*}}) { !CHECK-KIND10: %[[ARG1_PVT_DECL:.*]]:2 = hlfir.declare %[[ARG1_PVT]] {uniq_name = "_QFfirstprivate_real10Earg1"} : (!fir.ref<f80>) -> (!fir.ref<f80>, !fir.ref<f80>) !CHECK-KIND10: fir.call @_QPqux10(%[[ARG1_PVT_DECL]]#0) {{.*}} : (!fir.ref<f80>) -> () @@ -148,7 +148,7 @@ end subroutine !CHECK-KIND16-LABEL: func @_QPfirstprivate_real16( !CHECK-KIND16-SAME: %[[ARG1:.*]]: !fir.ref<f128>{{.*}}) { -!CHECK-KIND16: %[[ARG1_DECL:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFfirstprivate_real16Earg1"} : (!fir.ref<f128>, !fir.dscope) -> (!fir.ref<f128>, !fir.ref<f128>) +!CHECK-KIND16: %[[ARG1_DECL:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFfirstprivate_real16Earg1"} : (!fir.ref<f128>, !fir.dscope) -> (!fir.ref<f128>, !fir.ref<f128>) !CHECK-KIND16: omp.parallel private({{.*firstprivate.*}} {{.*}}#0 -> %[[ARG1_PVT:.*]] : {{.*}}) { !CHECK-KIND16: %[[ARG1_PVT_DECL:.*]]:2 = hlfir.declare %[[ARG1_PVT]] {uniq_name = "_QFfirstprivate_real16Earg1"} : (!fir.ref<f128>) -> (!fir.ref<f128>, !fir.ref<f128>) !CHECK-KIND16: fir.call @_QPqux16(%[[ARG1_PVT_DECL]]#0) {{.*}} : (!fir.ref<f128>) -> () @@ -165,8 +165,8 @@ end subroutine !CHECK-LABEL: func.func @_QPmultiple_firstprivate( !CHECK-SAME: %[[A_ADDR:.*]]: !fir.ref<i32> {fir.bindc_name = "a"}, !CHECK-SAME: %[[B_ADDR:.*]]: !fir.ref<i32> {fir.bindc_name = "b"}) { -!CHECK: %[[A_DECL:.*]]:2 = hlfir.declare %[[A_ADDR]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFmultiple_firstprivateEa"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) -!CHECK: %[[B_DECL:.*]]:2 = hlfir.declare %[[B_ADDR]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFmultiple_firstprivateEb"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: %[[A_DECL:.*]]:2 = hlfir.declare %[[A_ADDR]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFmultiple_firstprivateEa"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: %[[B_DECL:.*]]:2 = hlfir.declare %[[B_ADDR]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFmultiple_firstprivateEb"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) !CHECK: omp.parallel private({{.*firstprivate.*}} {{.*}}#0 -> %[[A_PRIV_ADDR:.*]], {{.*firstprivate.*}} {{.*}}#0 -> %[[B_PRIV_ADDR:.*]] : {{.*}}) { !CHECK: %[[A_PRIV_DECL:.*]]:2 = hlfir.declare %[[A_PRIV_ADDR]] {uniq_name = "_QFmultiple_firstprivateEa"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) !CHECK: %[[B_PRIV_DECL:.*]]:2 = hlfir.declare %[[B_PRIV_ADDR]] {uniq_name = "_QFmultiple_firstprivateEb"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) diff --git a/flang/test/Lower/OpenMP/parallel-lastprivate-clause-scalar.f90 b/flang/test/Lower/OpenMP/parallel-lastprivate-clause-scalar.f90 index 5d37010..a6de357 100644 --- a/flang/test/Lower/OpenMP/parallel-lastprivate-clause-scalar.f90 +++ b/flang/test/Lower/OpenMP/parallel-lastprivate-clause-scalar.f90 @@ -1,13 +1,13 @@ ! This test checks lowering of `LASTPRIVATE` clause for scalar types. ! RUN: bbc -fopenmp -emit-hlfir %s -o - | FileCheck %s -! RUN: flang -fc1 -fopenmp -emit-hlfir %s -o - | FileCheck %s +! RUN: %flang_fc1 -fopenmp -emit-hlfir %s -o - | FileCheck %s !CHECK: func @_QPlastprivate_character(%[[ARG1:.*]]: !fir.boxchar<1>{{.*}}) { !CHECK-DAG: %[[ARG1_UNBOX:.*]]:2 = fir.unboxchar !CHECK-DAG: %[[FIVE:.*]] = arith.constant 5 : index !CHECK-DAG: %[[ARG1_REF:.*]] = fir.convert %[[ARG1_UNBOX]]#0 : (!fir.ref<!fir.char<1,?>>) -> !fir.ref<!fir.char<1,5>> -!CHECK-DAG: %[[ARG1_DECL:.*]]:2 = hlfir.declare %[[ARG1_REF]] typeparams %[[FIVE]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFlastprivate_characterEarg1"} : (!fir.ref<!fir.char<1,5>>, index, !fir.dscope) -> (!fir.ref<!fir.char<1,5>>, !fir.ref<!fir.char<1,5>>) +!CHECK-DAG: %[[ARG1_DECL:.*]]:2 = hlfir.declare %[[ARG1_REF]] typeparams %[[FIVE]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFlastprivate_characterEarg1"} : (!fir.ref<!fir.char<1,5>>, index, !fir.dscope) -> (!fir.ref<!fir.char<1,5>>, !fir.ref<!fir.char<1,5>>) !CHECK: omp.parallel { @@ -18,10 +18,10 @@ !CHECK: %[[ARG1_PVT_DECL:.*]]:2 = hlfir.declare %[[ARG1_PVT]] typeparams %[[FIVE]] {uniq_name = "_QFlastprivate_characterEarg1"} : (!fir.ref<!fir.char<1,5>>, index) -> (!fir.ref<!fir.char<1,5>>, !fir.ref<!fir.char<1,5>>) !CHECK: %[[UNIT:.*]] = arith.constant 6 : i32 !CHECK-NEXT: %[[ADDR:.*]] = fir.address_of(@_QQclX -!CHECK-NEXT: %[[CVT0:.*]] = fir.convert %[[ADDR]] +!CHECK-NEXT: %[[CVT0:.*]] = fir.convert %[[ADDR]] !CHECK-NEXT: %[[CNST:.*]] = arith.constant !CHECK-NEXT: %[[CALL_BEGIN_IO:.*]] = fir.call @_FortranAioBeginExternalListOutput(%[[UNIT]], %[[CVT0]], %[[CNST]]) {{.*}}: (i32, !fir.ref<i8>, i32) -> !fir.ref<i8> -!CHECK-NEXT: %[[CVT_0_1:.*]] = fir.convert %[[ARG1_PVT_DECL]]#0 +!CHECK-NEXT: %[[CVT_0_1:.*]] = fir.convert %[[ARG1_PVT_DECL]]#0 !CHECK-NEXT: %[[CVT_0_2:.*]] = fir.convert %[[FIVE]] !CHECK-NEXT: %[[CALL_OP_ASCII:.*]] = fir.call @_FortranAioOutputAscii(%[[CALL_BEGIN_IO]], %[[CVT_0_1]], %[[CVT_0_2]]) !CHECK-NEXT: %[[CALL_END_IO:.*]] = fir.call @_FortranAioEndIoStatement(%[[CALL_BEGIN_IO]]) @@ -45,7 +45,7 @@ subroutine lastprivate_character(arg1) character(5) :: arg1 -!$OMP PARALLEL +!$OMP PARALLEL !$OMP DO LASTPRIVATE(arg1) do n = 1, 5 arg1(n:n) = 'c' @@ -56,7 +56,7 @@ end do end subroutine !CHECK: func @_QPlastprivate_int(%[[ARG1:.*]]: !fir.ref<i32> {fir.bindc_name = "arg1"}) { -!CHECK: %[[ARG1_DECL:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFlastprivate_intEarg1"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: %[[ARG1_DECL:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFlastprivate_intEarg1"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) !CHECK-DAG: omp.parallel { !CHECK: omp.wsloop private(@{{.*}} %{{.*}}#0 -> %[[CLONE:.*]], @{{.*}} %{{.*}}#0 -> %{{.*}} : !fir.ref<i32>, !{{.*}}) { !CHECK-NEXT: omp.loop_nest (%[[INDX_WS:.*]]) : {{.*}} { @@ -82,7 +82,7 @@ end subroutine subroutine lastprivate_int(arg1) integer :: arg1 -!$OMP PARALLEL +!$OMP PARALLEL !$OMP DO LASTPRIVATE(arg1) do n = 1, 5 arg1 = 2 @@ -94,8 +94,8 @@ print *, arg1 end subroutine !CHECK: func.func @_QPmult_lastprivate_int(%[[ARG1:.*]]: !fir.ref<i32> {fir.bindc_name = "arg1"}, %[[ARG2:.*]]: !fir.ref<i32> {fir.bindc_name = "arg2"}) { -!CHECK: %[[ARG1_DECL:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFmult_lastprivate_intEarg1"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) -!CHECK: %[[ARG2_DECL:.*]]:2 = hlfir.declare %[[ARG2]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFmult_lastprivate_intEarg2"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: %[[ARG1_DECL:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFmult_lastprivate_intEarg1"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: %[[ARG2_DECL:.*]]:2 = hlfir.declare %[[ARG2]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFmult_lastprivate_intEarg2"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) !CHECK: omp.parallel { !CHECK: omp.wsloop private(@{{.*}} %{{.*}}#0 -> %[[CLONE1:.*]], @{{.*}} %{{.*}}#0 -> %[[CLONE2:.*]], @{{.*}} %{{.*}}#0 -> %{{.*}} : !fir.ref<i32>, !fir.ref<i32>, !{{.*}}) { !CHECK-NEXT: omp.loop_nest (%[[INDX_WS:.*]]) : {{.*}} { @@ -123,7 +123,7 @@ end subroutine subroutine mult_lastprivate_int(arg1, arg2) integer :: arg1, arg2 -!$OMP PARALLEL +!$OMP PARALLEL !$OMP DO LASTPRIVATE(arg1) LASTPRIVATE(arg2) do n = 1, 5 arg1 = 2 @@ -136,8 +136,8 @@ print *, arg1, arg2 end subroutine !CHECK: func.func @_QPmult_lastprivate_int2(%[[ARG1:.*]]: !fir.ref<i32> {fir.bindc_name = "arg1"}, %[[ARG2:.*]]: !fir.ref<i32> {fir.bindc_name = "arg2"}) { -!CHECK: %[[ARG1_DECL:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFmult_lastprivate_int2Earg1"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) -!CHECK: %[[ARG2_DECL:.*]]:2 = hlfir.declare %[[ARG2]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFmult_lastprivate_int2Earg2"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: %[[ARG1_DECL:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFmult_lastprivate_int2Earg1"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: %[[ARG2_DECL:.*]]:2 = hlfir.declare %[[ARG2]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFmult_lastprivate_int2Earg2"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) !CHECK: omp.parallel { !CHECK: omp.wsloop private(@{{.*}} %{{.*}}#0 -> %[[CLONE1:.*]], @{{.*}} %{{.*}}#0 -> %[[CLONE2:.*]], @{{.*}} %{{.*}}#0 -> %{{.*}} : !fir.ref<i32>, !fir.ref<i32>, !{{.*}}) { !CHECK-NEXT: omp.loop_nest (%[[INDX_WS:.*]]) : {{.*}} { @@ -165,7 +165,7 @@ end subroutine subroutine mult_lastprivate_int2(arg1, arg2) integer :: arg1, arg2 -!$OMP PARALLEL +!$OMP PARALLEL !$OMP DO LASTPRIVATE(arg1, arg2) do n = 1, 5 arg1 = 2 @@ -178,8 +178,8 @@ print *, arg1, arg2 end subroutine !CHECK: func.func @_QPfirstpriv_lastpriv_int(%[[ARG1:.*]]: !fir.ref<i32> {fir.bindc_name = "arg1"}, %[[ARG2:.*]]: !fir.ref<i32> {fir.bindc_name = "arg2"}) { -!CHECK: %[[ARG1_DECL:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFfirstpriv_lastpriv_intEarg1"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) -!CHECK: %[[ARG2_DECL:.*]]:2 = hlfir.declare %[[ARG2]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFfirstpriv_lastpriv_intEarg2"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: %[[ARG1_DECL:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFfirstpriv_lastpriv_intEarg1"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: %[[ARG2_DECL:.*]]:2 = hlfir.declare %[[ARG2]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFfirstpriv_lastpriv_intEarg2"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) !CHECK: omp.parallel { ! Firstprivate update !CHECK-NOT: omp.barrier @@ -207,7 +207,7 @@ end subroutine subroutine firstpriv_lastpriv_int(arg1, arg2) integer :: arg1, arg2 -!$OMP PARALLEL +!$OMP PARALLEL !$OMP DO FIRSTPRIVATE(arg1) LASTPRIVATE(arg2) do n = 1, 5 arg1 = 2 @@ -220,7 +220,7 @@ print *, arg1, arg2 end subroutine !CHECK: func.func @_QPfirstpriv_lastpriv_int2(%[[ARG1:.*]]: !fir.ref<i32> {fir.bindc_name = "arg1"}) { -!CHECK: %[[ARG1_DECL:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFfirstpriv_lastpriv_int2Earg1"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: %[[ARG1_DECL:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFfirstpriv_lastpriv_int2Earg1"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) !CHECK: omp.parallel { ! Firstprivate update @@ -250,7 +250,7 @@ end subroutine subroutine firstpriv_lastpriv_int2(arg1) integer :: arg1 -!$OMP PARALLEL +!$OMP PARALLEL !$OMP DO FIRSTPRIVATE(arg1) LASTPRIVATE(arg1) do n = 1, 5 arg1 = 2 diff --git a/flang/test/Lower/OpenMP/parallel-masked-taskloop.f90 b/flang/test/Lower/OpenMP/parallel-masked-taskloop.f90 index 497cc39..e686d08 100644 --- a/flang/test/Lower/OpenMP/parallel-masked-taskloop.f90 +++ b/flang/test/Lower/OpenMP/parallel-masked-taskloop.f90 @@ -3,7 +3,7 @@ ! RUN: bbc -emit-hlfir -fopenmp -fopenmp-version=50 -o - %s 2>&1 | FileCheck %s ! RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=50 -o - %s 2>&1 | FileCheck %s -! CHECK-LABEL: omp.private {type = private} +! CHECK-LABEL: omp.private {type = private} ! CHECK-SAME: @[[I_PRIVATE:.*]] : i32 ! CHECK-LABEL: func.func @_QPtest_parallel_master_taskloop() { ! CHECK: %[[VAL0:.*]] = fir.dummy_scope : !fir.dscope @@ -44,5 +44,5 @@ subroutine test_parallel_master_taskloop do i=1,10 j = j + 1 end do - !$omp end parallel masked taskloop + !$omp end parallel masked taskloop end subroutine diff --git a/flang/test/Lower/OpenMP/parallel-master-taskloop-simd.f90 b/flang/test/Lower/OpenMP/parallel-master-taskloop-simd.f90 index 086ed01..3854556 100644 --- a/flang/test/Lower/OpenMP/parallel-master-taskloop-simd.f90 +++ b/flang/test/Lower/OpenMP/parallel-master-taskloop-simd.f90 @@ -6,7 +6,7 @@ subroutine test_parallel_master_taskloop_simd integer :: i, j = 1 !CHECK: not yet implemented: Composite TASKLOOP SIMD - !$omp parallel master taskloop simd + !$omp parallel master taskloop simd do i=1,10 j = j + 1 end do diff --git a/flang/test/Lower/OpenMP/parallel-private-clause-fixes.f90 b/flang/test/Lower/OpenMP/parallel-private-clause-fixes.f90 index 3bb4083..e2fbd8b 100644 --- a/flang/test/Lower/OpenMP/parallel-private-clause-fixes.f90 +++ b/flang/test/Lower/OpenMP/parallel-private-clause-fixes.f90 @@ -35,7 +35,7 @@ ! CHECK-LABEL: @_QPmultiple_private_fix( ! CHECK-SAME: %[[GAMA:.*]]: !fir.ref<i32> {fir.bindc_name = "gama"} -! CHECK-DAG: %[[GAMA_DECL:.*]]:2 = hlfir.declare %[[GAMA]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFmultiple_private_fixEgama"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK-DAG: %[[GAMA_DECL:.*]]:2 = hlfir.declare %[[GAMA]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFmultiple_private_fixEgama"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK-DAG: %[[VAL_0:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFmultiple_private_fixEi"} ! CHECK-DAG: %[[I_DECL:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = "_QFmultiple_private_fixEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK-DAG: %[[VAL_1:.*]] = fir.alloca i32 {bindc_name = "j", uniq_name = "_QFmultiple_private_fixEj"} @@ -124,7 +124,7 @@ end subroutine ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.heap<!fir.char<1,?>>>> {fir.bindc_name = "aaa"}) { ! CHECK: %[[VAL_1:.*]] = fir.load %[[VAL_0]] : !fir.ref<!fir.box<!fir.heap<!fir.char<1,?>>>> ! CHECK: %[[VAL_2:.*]] = fir.box_elesize %[[VAL_1]] : (!fir.box<!fir.heap<!fir.char<1,?>>>) -> index -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] typeparams %[[VAL_2]] dummy_scope %{{[0-9]+}} {fortran_attrs = #{{.*}}<allocatable>, uniq_name = "_QFsub01Eaaa"} : (!fir.ref<!fir.box<!fir.heap<!fir.char<1,?>>>>, index, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.char<1,?>>>>, !fir.ref<!fir.box<!fir.heap<!fir.char<1,?>>>>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] typeparams %[[VAL_2]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #{{.*}}<allocatable>, uniq_name = "_QFsub01Eaaa"} : (!fir.ref<!fir.box<!fir.heap<!fir.char<1,?>>>>, index, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.char<1,?>>>>, !fir.ref<!fir.box<!fir.heap<!fir.char<1,?>>>>) ! CHECK: omp.parallel private(@[[BOX_HEAP_CHAR_PRIVATIZER]] %[[VAL_3]]#0 -> %{{.*}} : {{.*}}) { ! CHECK: omp.terminator ! CHECK: } @@ -139,7 +139,7 @@ end subroutine ! CHECK-LABEL: func.func @_QPsub02( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.heap<!fir.char<1,?>>>> {fir.bindc_name = "bbb"}) { -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {fortran_attrs = #{{.*}}<allocatable>, uniq_name = "_QFsub02Ebbb"} : (!fir.ref<!fir.box<!fir.heap<!fir.char<1,?>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.char<1,?>>>>, !fir.ref<!fir.box<!fir.heap<!fir.char<1,?>>>>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #{{.*}}<allocatable>, uniq_name = "_QFsub02Ebbb"} : (!fir.ref<!fir.box<!fir.heap<!fir.char<1,?>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.char<1,?>>>>, !fir.ref<!fir.box<!fir.heap<!fir.char<1,?>>>>) ! CHECK: omp.parallel private(@{{.*}} %[[VAL_1]]#0 -> %[[PRIV_ARG:.*]] : {{.*}}) { ! CHECK: %{{.*}}:2 = hlfir.declare %[[PRIV_ARG]] {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFsub02Ebbb"} : (!fir.ref<!fir.box<!fir.heap<!fir.char<1,?>>>>) ! CHECK: omp.terminator diff --git a/flang/test/Lower/OpenMP/parallel-private-clause-str.f90 b/flang/test/Lower/OpenMP/parallel-private-clause-str.f90 index a08c0b2..7d364c0 100644 --- a/flang/test/Lower/OpenMP/parallel-private-clause-str.f90 +++ b/flang/test/Lower/OpenMP/parallel-private-clause-str.f90 @@ -65,7 +65,7 @@ subroutine test_allocatable_string(n) end subroutine !CHECK: func.func @_QPtest_allocatable_string_array(%[[ARG0:.*]]: !fir.ref<i32> {fir.bindc_name = "n"}) { -!CHECK: %{{.*}} = hlfir.declare %[[ARG0]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFtest_allocatable_string_arrayEn"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: %{{.*}} = hlfir.declare %[[ARG0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFtest_allocatable_string_arrayEn"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) !CHECK: %[[C_BOX_REF:.*]] = fir.alloca !fir.box<!fir.heap<!fir.array<?x!fir.char<1,?>>>> {bindc_name = "c", uniq_name = "_QFtest_allocatable_string_arrayEc"} !CHECK: %[[C_BOX:.*]] = fir.embox %{{.*}}(%{{.*}}) typeparams %{{.*}} : (!fir.heap<!fir.array<?x!fir.char<1,?>>>, !fir.shape<1>, i32) -> !fir.box<!fir.heap<!fir.array<?x!fir.char<1,?>>>> !CHECK: fir.store %[[C_BOX]] to %[[C_BOX_REF]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.char<1,?>>>>> diff --git a/flang/test/Lower/OpenMP/parallel-private-clause.f90 b/flang/test/Lower/OpenMP/parallel-private-clause.f90 index 3934435..3a7fc22 100644 --- a/flang/test/Lower/OpenMP/parallel-private-clause.f90 +++ b/flang/test/Lower/OpenMP/parallel-private-clause.f90 @@ -231,14 +231,14 @@ end subroutine increment_list_items !FIRDialect-DAG: %[[Z1:.*]] = fir.alloca i32 {bindc_name = "z1", fir.target, uniq_name = "_QFparallel_pointerEz1"} !FIRDialect-DAG: %[[Z1_DECL:.*]]:2 = hlfir.declare %[[Z1]] {fortran_attrs = #fir.var_attrs<target>, uniq_name = "_QFparallel_pointerEz1"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) !FIRDialect-DAG: %[[Z2:.*]] = fir.alloca !fir.array<10xi32> {bindc_name = "z2", fir.target, uniq_name = "_QFparallel_pointerEz2"} -!FIRDialect-DAG: %[[Z2_DECL:.*]]:2 = hlfir.declare %[[Z2]](%{{.*}}) {fortran_attrs = #fir.var_attrs<target>, uniq_name = "_QFparallel_pointerEz2"} : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>) +!FIRDialect-DAG: %[[Z2_DECL:.*]]:2 = hlfir.declare %[[Z2]](%[[Z2_SHAPE:.*]]) {fortran_attrs = #fir.var_attrs<target>, uniq_name = "_QFparallel_pointerEz2"} : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>) !FIRDialect: omp.parallel private(@{{.*}} %{{.*}}#0 -> %[[Y1_PVT:.*]], @{{.*}} %{{.*}}#0 -> %[[Y2_PVT:.*]] : {{.*}}) { !FIRDialect-DAG: %[[Y1_PVT_DECL:.*]]:2 = hlfir.declare %[[Y1_PVT]] {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFparallel_pointerEy1"} : (!fir.ref<!fir.box<!fir.ptr<i32>>>) -> (!fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.ref<!fir.box<!fir.ptr<i32>>>) !FIRDialect-DAG: %[[Y2_PVT_DECL:.*]]:2 = hlfir.declare %[[Y2_PVT]] {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFparallel_pointerEy2"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>) !FIRDialect-DAG: %[[PP18:.*]] = fir.embox %[[Z1_DECL]]#0 : (!fir.ref<i32>) -> !fir.box<!fir.ptr<i32>> !FIRDialect: fir.store %[[PP18]] to %[[Y1_PVT_DECL]]#0 : !fir.ref<!fir.box<!fir.ptr<i32>>> -!FIRDialect-DAG: %[[PP19:.*]] = fir.shape %c10 : (index) -> !fir.shape<1> -!FIRDialect-DAG: %[[PP20:.*]] = fir.embox %[[Z2_DECL]]#0(%[[PP19]]) : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>) -> !fir.box<!fir.ptr<!fir.array<?xi32>>> +!FIRDialect: %[[Z2_CAST:.*]] = fir.convert %[[Z2_DECL]]#0 : (!fir.ref<!fir.array<10xi32>>) -> !fir.ref<!fir.array<?xi32>> +!FIRDialect-DAG: %[[PP20:.*]] = fir.embox %[[Z2_CAST]](%[[Z2_SHAPE]]) : (!fir.ref<!fir.array<?xi32>>, !fir.shape<1>) -> !fir.box<!fir.ptr<!fir.array<?xi32>>> !FIRDialect: fir.store %[[PP20]] to %[[Y2_PVT_DECL]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>> !FIRDialect: omp.terminator !FIRDialect: } diff --git a/flang/test/Lower/OpenMP/parallel-reduction-allocatable-array.f90 b/flang/test/Lower/OpenMP/parallel-reduction-allocatable-array.f90 index 41c7d69..f56875d 100644 --- a/flang/test/Lower/OpenMP/parallel-reduction-allocatable-array.f90 +++ b/flang/test/Lower/OpenMP/parallel-reduction-allocatable-array.f90 @@ -18,7 +18,7 @@ print *,r end program -! CHECK-LABEL: omp.declare_reduction @add_reduction_byref_box_heap_Uxi32 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> alloc { +! CHECK-LABEL: omp.declare_reduction @add_reduction_byref_box_heap_Uxi32 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> attributes {byref_element_type = !fir.array<?xi32>} alloc { ! CHECK: %[[VAL_10:.*]] = fir.alloca !fir.box<!fir.heap<!fir.array<?xi32>>> ! CHECK: omp.yield(%[[VAL_10]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) ! CHECK-LABEL: } init { diff --git a/flang/test/Lower/OpenMP/parallel-reduction-array-lb.f90 b/flang/test/Lower/OpenMP/parallel-reduction-array-lb.f90 index aa91e1e..d9ba3bed 100644 --- a/flang/test/Lower/OpenMP/parallel-reduction-array-lb.f90 +++ b/flang/test/Lower/OpenMP/parallel-reduction-array-lb.f90 @@ -12,7 +12,7 @@ print *,i end program -! CHECK-LABEL: omp.declare_reduction @add_reduction_byref_box_3x2xi32 : !fir.ref<!fir.box<!fir.array<3x2xi32>>> alloc { +! CHECK-LABEL: omp.declare_reduction @add_reduction_byref_box_3x2xi32 : !fir.ref<!fir.box<!fir.array<3x2xi32>>> {{.*}} alloc { ! CHECK: %[[VAL_15:.*]] = fir.alloca !fir.box<!fir.array<3x2xi32>> ! CHECK: omp.yield(%[[VAL_15]] : !fir.ref<!fir.box<!fir.array<3x2xi32>>>) ! CHECK-LABEL: } init { diff --git a/flang/test/Lower/OpenMP/parallel-reduction-array.f90 b/flang/test/Lower/OpenMP/parallel-reduction-array.f90 index 59595de..636660f 100644 --- a/flang/test/Lower/OpenMP/parallel-reduction-array.f90 +++ b/flang/test/Lower/OpenMP/parallel-reduction-array.f90 @@ -17,7 +17,7 @@ i(3) = 3 print *,i end program -! CPU-LABEL: omp.declare_reduction @add_reduction_byref_box_3xi32 : !fir.ref<!fir.box<!fir.array<3xi32>>> alloc { +! CPU-LABEL: omp.declare_reduction @add_reduction_byref_box_3xi32 : !fir.ref<!fir.box<!fir.array<3xi32>>> attributes {byref_element_type = !fir.array<3xi32>} alloc { ! CPU: %[[VAL_8:.*]] = fir.alloca !fir.box<!fir.array<3xi32>> ! CPU: omp.yield(%[[VAL_8]] : !fir.ref<!fir.box<!fir.array<3xi32>>>) ! CPU-LABEL: } init { diff --git a/flang/test/Lower/OpenMP/parallel-reduction-array2.f90 b/flang/test/Lower/OpenMP/parallel-reduction-array2.f90 index 14338c6..9cf8a63 100644 --- a/flang/test/Lower/OpenMP/parallel-reduction-array2.f90 +++ b/flang/test/Lower/OpenMP/parallel-reduction-array2.f90 @@ -13,7 +13,7 @@ i(3) = i(3) + 3 print *,i end program -! CHECK-LABEL: omp.declare_reduction @add_reduction_byref_box_3xi32 : !fir.ref<!fir.box<!fir.array<3xi32>>> alloc { +! CHECK-LABEL: omp.declare_reduction @add_reduction_byref_box_3xi32 : !fir.ref<!fir.box<!fir.array<3xi32>>> {{.*}} alloc { ! CHECK: %[[VAL_8:.*]] = fir.alloca !fir.box<!fir.array<3xi32>> ! CHECK: omp.yield(%[[VAL_8]] : !fir.ref<!fir.box<!fir.array<3xi32>>>) ! CHECK-LABEL: } init { diff --git a/flang/test/Lower/OpenMP/parallel-reduction-mixed.f90 b/flang/test/Lower/OpenMP/parallel-reduction-mixed.f90 index f769fd3..17ee6d0 100644 --- a/flang/test/Lower/OpenMP/parallel-reduction-mixed.f90 +++ b/flang/test/Lower/OpenMP/parallel-reduction-mixed.f90 @@ -8,7 +8,7 @@ subroutine proc implicit none real(8),allocatable :: F(:) real(8),allocatable :: A(:) - + integer :: I !$omp parallel private(A) reduction(+:F,I) @@ -20,7 +20,7 @@ end subroutine proc !CHECK: call void (ptr, i32, ptr, ...) !CHECK-SAME: @__kmpc_fork_call(ptr {{.*}}, i32 1, ptr @[[OMP_PAR:.*]], {{.*}}) -!CHECK: define internal void @[[OMP_PAR]](ptr {{.*}} %[[TID_ADDR:.*]], ptr noalias +!CHECK: define internal void @[[OMP_PAR]](ptr {{.*}} %[[TID_ADDR:.*]], ptr noalias !CHECK: %[[TID_LOCAL:.*]] = alloca i32 !CHECK: %[[TID:.*]] = load i32, ptr %[[TID_ADDR]] !CHECK: store i32 %[[TID]], ptr %[[TID_LOCAL]] diff --git a/flang/test/Lower/OpenMP/parallel-reduction-pointer-array.f90 b/flang/test/Lower/OpenMP/parallel-reduction-pointer-array.f90 index 3634445..3de2ba8 100644 --- a/flang/test/Lower/OpenMP/parallel-reduction-pointer-array.f90 +++ b/flang/test/Lower/OpenMP/parallel-reduction-pointer-array.f90 @@ -19,7 +19,7 @@ deallocate(r) end program -! CHECK-LABEL: omp.declare_reduction @add_reduction_byref_box_ptr_Uxi32 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>> alloc { +! CHECK-LABEL: omp.declare_reduction @add_reduction_byref_box_ptr_Uxi32 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>> attributes {byref_element_type = !fir.array<?xi32>} alloc { ! CHECK: %[[VAL_3:.*]] = fir.alloca !fir.box<!fir.ptr<!fir.array<?xi32>>> ! CHECK: omp.yield(%[[VAL_3]] : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>) ! CHECK-LABEL: } init { diff --git a/flang/test/Lower/OpenMP/parallel-reduction3.f90 b/flang/test/Lower/OpenMP/parallel-reduction3.f90 index 9af1837..7437e1d 100644 --- a/flang/test/Lower/OpenMP/parallel-reduction3.f90 +++ b/flang/test/Lower/OpenMP/parallel-reduction3.f90 @@ -1,7 +1,7 @@ ! RUN: bbc -emit-hlfir -fopenmp -o - %s 2>&1 | FileCheck %s ! RUN: %flang_fc1 -emit-hlfir -fopenmp -o - %s 2>&1 | FileCheck %s -! CHECK-LABEL: omp.declare_reduction @add_reduction_byref_box_Uxi32 : !fir.ref<!fir.box<!fir.array<?xi32>>> alloc { +! CHECK-LABEL: omp.declare_reduction @add_reduction_byref_box_Uxi32 : !fir.ref<!fir.box<!fir.array<?xi32>>> {{.*}} alloc { ! CHECK: %[[VAL_8:.*]] = fir.alloca !fir.box<!fir.array<?xi32>> ! CHECK: omp.yield(%[[VAL_8]] : !fir.ref<!fir.box<!fir.array<?xi32>>>) ! CHECK-LABEL: } init { @@ -54,7 +54,7 @@ ! CHECK-LABEL: func.func @_QPs( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<i32> {fir.bindc_name = "x"}) { -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFsEx"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFsEx"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_2:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFsEi"} ! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]] {uniq_name = "_QFsEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_4:.*]] = fir.load %[[VAL_1]]#0 : !fir.ref<i32> diff --git a/flang/test/Lower/OpenMP/parallel-wsloop-firstpriv.f90 b/flang/test/Lower/OpenMP/parallel-wsloop-firstpriv.f90 index 55eceaa..6532858d 100644 --- a/flang/test/Lower/OpenMP/parallel-wsloop-firstpriv.f90 +++ b/flang/test/Lower/OpenMP/parallel-wsloop-firstpriv.f90 @@ -3,9 +3,9 @@ ! RUN: bbc -fopenmp -emit-hlfir %s -o - | FileCheck %s -! CHECK: func @_QPomp_do_firstprivate(%[[ARG0:.*]]: !fir.ref<i32> {fir.bindc_name = "a"}) +! CHECK: func @_QPomp_do_firstprivate(%[[ARG0:.*]]: !fir.ref<i32> {fir.bindc_name = "a"}) subroutine omp_do_firstprivate(a) - ! CHECK: %[[ARG0_DECL:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFomp_do_firstprivateEa"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) + ! CHECK: %[[ARG0_DECL:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFomp_do_firstprivateEa"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) integer::a integer::n n = a+1 @@ -31,10 +31,10 @@ subroutine omp_do_firstprivate(a) call bar(a) end subroutine omp_do_firstprivate -! CHECK: func @_QPomp_do_firstprivate2(%[[ARG0:.*]]: !fir.ref<i32> {fir.bindc_name = "a"}, %[[ARG1:.*]]: !fir.ref<i32> {fir.bindc_name = "n"}) +! CHECK: func @_QPomp_do_firstprivate2(%[[ARG0:.*]]: !fir.ref<i32> {fir.bindc_name = "a"}, %[[ARG1:.*]]: !fir.ref<i32> {fir.bindc_name = "n"}) subroutine omp_do_firstprivate2(a, n) - ! CHECK: %[[ARG0_DECL:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFomp_do_firstprivate2Ea"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) - ! CHECK: %[[ARG1_DECL:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFomp_do_firstprivate2En"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) + ! CHECK: %[[ARG0_DECL:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFomp_do_firstprivate2Ea"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) + ! CHECK: %[[ARG1_DECL:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFomp_do_firstprivate2En"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) integer::a integer::n n = a+1 diff --git a/flang/test/Lower/OpenMP/parallel-wsloop-lastpriv.f90 b/flang/test/Lower/OpenMP/parallel-wsloop-lastpriv.f90 index faf8f71..b3d52a0 100644 --- a/flang/test/Lower/OpenMP/parallel-wsloop-lastpriv.f90 +++ b/flang/test/Lower/OpenMP/parallel-wsloop-lastpriv.f90 @@ -5,7 +5,7 @@ ! CHECK: func @_QPomp_do_lastprivate(%[[ARG0:.*]]: !fir.ref<i32> {fir.bindc_name = "a"}) subroutine omp_do_lastprivate(a) - ! CHECK: %[[ARG0_DECL:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFomp_do_lastprivateEa"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) + ! CHECK: %[[ARG0_DECL:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFomp_do_lastprivateEa"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) integer::a integer::n n = a+1 @@ -50,8 +50,8 @@ end subroutine omp_do_lastprivate ! CHECK: func @_QPomp_do_lastprivate2(%[[ARG0:.*]]: !fir.ref<i32> {fir.bindc_name = "a"}, %[[ARG1:.*]]: !fir.ref<i32> {fir.bindc_name = "n"}) subroutine omp_do_lastprivate2(a, n) - ! CHECK: %[[ARG0_DECL:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFomp_do_lastprivate2Ea"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) - ! CHECK: %[[ARG1_DECL:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFomp_do_lastprivate2En"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) + ! CHECK: %[[ARG0_DECL:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFomp_do_lastprivate2Ea"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) + ! CHECK: %[[ARG1_DECL:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFomp_do_lastprivate2En"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) integer::a integer::n n = a+1 @@ -96,7 +96,7 @@ end subroutine omp_do_lastprivate2 ! CHECK: func @_QPomp_do_lastprivate_collapse2(%[[ARG0:.*]]: !fir.ref<i32> {fir.bindc_name = "a"}) subroutine omp_do_lastprivate_collapse2(a) - ! CHECK: %[[ARG0_DECL:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFomp_do_lastprivate_collapse2Ea"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) + ! CHECK: %[[ARG0_DECL:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFomp_do_lastprivate_collapse2Ea"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) integer::a !$omp parallel do lastprivate(a) collapse(2) ! CHECK: omp.parallel { @@ -158,7 +158,7 @@ end subroutine omp_do_lastprivate_collapse2 ! CHECK: func @_QPomp_do_lastprivate_collapse3(%[[ARG0:.*]]: !fir.ref<i32> {fir.bindc_name = "a"}) subroutine omp_do_lastprivate_collapse3(a) - ! CHECK: %[[ARG0_DECL:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFomp_do_lastprivate_collapse3Ea"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) + ! CHECK: %[[ARG0_DECL:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFomp_do_lastprivate_collapse3Ea"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) integer::a !$omp parallel do lastprivate(a) collapse(3) ! CHECK: omp.parallel { diff --git a/flang/test/Lower/OpenMP/parallel-wsloop-reduction-byref.f90 b/flang/test/Lower/OpenMP/parallel-wsloop-reduction-byref.f90 index 3f44f29..23d387a 100644 --- a/flang/test/Lower/OpenMP/parallel-wsloop-reduction-byref.f90 +++ b/flang/test/Lower/OpenMP/parallel-wsloop-reduction-byref.f90 @@ -1,7 +1,7 @@ ! Check that for parallel do, reduction is only processed for the loop ! RUN: bbc -fopenmp --force-byref-reduction -emit-hlfir %s -o - | FileCheck %s -! RUN: flang -fc1 -fopenmp -mmlir --force-byref-reduction -emit-hlfir %s -o - | FileCheck %s +! RUN: %flang_fc1 -fopenmp -mmlir --force-byref-reduction -emit-hlfir %s -o - | FileCheck %s ! CHECK: omp.parallel { ! CHECK: omp.wsloop private({{.*}}) reduction(byref @add_reduction_byref_i32 diff --git a/flang/test/Lower/OpenMP/parallel-wsloop-reduction.f90 b/flang/test/Lower/OpenMP/parallel-wsloop-reduction.f90 index a206eef..225f829 100644 --- a/flang/test/Lower/OpenMP/parallel-wsloop-reduction.f90 +++ b/flang/test/Lower/OpenMP/parallel-wsloop-reduction.f90 @@ -1,7 +1,7 @@ ! Check that for parallel do, reduction is only processed for the loop ! RUN: bbc -fopenmp -emit-hlfir %s -o - | FileCheck %s -! RUN: flang -fc1 -fopenmp -emit-hlfir %s -o - | FileCheck %s +! RUN: %flang_fc1 -fopenmp -emit-hlfir %s -o - | FileCheck %s ! CHECK: omp.parallel { ! CHECK: omp.wsloop private({{.*}}) reduction(@add_reduction_i32 diff --git a/flang/test/Lower/OpenMP/parallel-wsloop.f90 b/flang/test/Lower/OpenMP/parallel-wsloop.f90 index 15a68e2..5a9be40 100644 --- a/flang/test/Lower/OpenMP/parallel-wsloop.f90 +++ b/flang/test/Lower/OpenMP/parallel-wsloop.f90 @@ -27,8 +27,8 @@ end subroutine ! CHECK-LABEL: func @_QPparallel_do_with_parallel_clauses ! CHECK-SAME: %[[COND_REF:.*]]: !fir.ref<!fir.logical<4>> {fir.bindc_name = "cond"}, %[[NT_REF:.*]]: !fir.ref<i32> {fir.bindc_name = "nt"} subroutine parallel_do_with_parallel_clauses(cond, nt) - ! CHECK: %[[COND_DECL:.*]]:2 = hlfir.declare %[[COND_REF]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFparallel_do_with_parallel_clausesEcond"} : (!fir.ref<!fir.logical<4>>, !fir.dscope) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) - ! CHECK: %[[NT_DECL:.*]]:2 = hlfir.declare %[[NT_REF]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFparallel_do_with_parallel_clausesEnt"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) + ! CHECK: %[[COND_DECL:.*]]:2 = hlfir.declare %[[COND_REF]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFparallel_do_with_parallel_clausesEcond"} : (!fir.ref<!fir.logical<4>>, !fir.dscope) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) + ! CHECK: %[[NT_DECL:.*]]:2 = hlfir.declare %[[NT_REF]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFparallel_do_with_parallel_clausesEnt"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) logical :: cond integer :: nt integer :: i @@ -56,7 +56,7 @@ end subroutine ! CHECK-LABEL: func @_QPparallel_do_with_clauses ! CHECK-SAME: %[[NT_REF:.*]]: !fir.ref<i32> {fir.bindc_name = "nt"} subroutine parallel_do_with_clauses(nt) - ! CHECK: %[[NT_DECL:.*]]:2 = hlfir.declare %[[NT_REF]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFparallel_do_with_clausesEnt"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) + ! CHECK: %[[NT_DECL:.*]]:2 = hlfir.declare %[[NT_REF]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFparallel_do_with_clausesEnt"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) integer :: nt integer :: i ! CHECK: %[[NT:.*]] = fir.load %[[NT_DECL]]#0 : !fir.ref<i32> @@ -86,8 +86,8 @@ end subroutine ! CHECK-LABEL: func @_QPparallel_do_with_privatisation_clauses ! CHECK-SAME: %[[COND_REF:.*]]: !fir.ref<!fir.logical<4>> {fir.bindc_name = "cond"}, %[[NT_REF:.*]]: !fir.ref<i32> {fir.bindc_name = "nt"} subroutine parallel_do_with_privatisation_clauses(cond,nt) - ! CHECK: %[[COND_DECL:.*]]:2 = hlfir.declare %[[COND_REF]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFparallel_do_with_privatisation_clausesEcond"} : (!fir.ref<!fir.logical<4>>, !fir.dscope) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) - ! CHECK: %[[NT_DECL:.*]]:2 = hlfir.declare %[[NT_REF]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFparallel_do_with_privatisation_clausesEnt"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) + ! CHECK: %[[COND_DECL:.*]]:2 = hlfir.declare %[[COND_REF]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFparallel_do_with_privatisation_clausesEcond"} : (!fir.ref<!fir.logical<4>>, !fir.dscope) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) + ! CHECK: %[[NT_DECL:.*]]:2 = hlfir.declare %[[NT_REF]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFparallel_do_with_privatisation_clausesEnt"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) logical :: cond integer :: nt integer :: i @@ -139,7 +139,7 @@ end subroutine parallel_private_do ! CHECK-LABEL: func.func @_QPparallel_private_do( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.logical<4>> {fir.bindc_name = "cond"}, ! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref<i32> {fir.bindc_name = "nt"}) { -! CHECK: %[[NT_DECL:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFparallel_private_doEnt"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[NT_DECL:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFparallel_private_doEnt"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: omp.parallel private(@{{.*}} %{{.*}}#0 -> %[[COND_ADDR:.*]], @{{.*firstprivate.*}} %{{.*}}#0 -> %[[NT_PRIV_ADDR:.*]] : {{.*}}) { ! CHECK: %[[COND_DECL:.*]]:2 = hlfir.declare %[[COND_ADDR]] {uniq_name = "_QFparallel_private_doEcond"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) @@ -182,8 +182,8 @@ end subroutine omp_parallel_multiple_firstprivate_do ! CHECK-LABEL: func.func @_QPomp_parallel_multiple_firstprivate_do( ! CHECK-SAME: %[[A_ADDR:.*]]: !fir.ref<i32> {fir.bindc_name = "a"}, ! CHECK-SAME: %[[B_ADDR:.*]]: !fir.ref<i32> {fir.bindc_name = "b"}) { -! CHECK: %[[A_DECL:.*]]:2 = hlfir.declare %[[A_ADDR]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFomp_parallel_multiple_firstprivate_doEa"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) -! CHECK: %[[B_DECL:.*]]:2 = hlfir.declare %[[B_ADDR]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFomp_parallel_multiple_firstprivate_doEb"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[A_DECL:.*]]:2 = hlfir.declare %[[A_ADDR]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFomp_parallel_multiple_firstprivate_doEa"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[B_DECL:.*]]:2 = hlfir.declare %[[B_ADDR]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFomp_parallel_multiple_firstprivate_doEb"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: omp.parallel private(@{{.*firstprivate.*}} %{{.*}}#0 -> %[[A_PRIV_ADDR:.*]], @{{.*firstprivate.*}} %{{.*}}#0 -> %[[B_PRIV_ADDR:.*]] : {{.*}}) { ! CHECK: %[[A_PRIV_DECL:.*]]:2 = hlfir.declare %[[A_PRIV_ADDR]] {uniq_name = "_QFomp_parallel_multiple_firstprivate_doEa"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) @@ -229,7 +229,7 @@ end subroutine parallel_do_private ! CHECK-LABEL: func.func @_QPparallel_do_private( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.logical<4>> {fir.bindc_name = "cond"}, ! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref<i32> {fir.bindc_name = "nt"}) { -! CHECK: %[[NT_DECL:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFparallel_do_privateEnt"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[NT_DECL:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFparallel_do_privateEnt"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: omp.parallel { ! CHECK: %[[VAL_7:.*]] = arith.constant 1 : i32 ! CHECK: %[[VAL_8:.*]] = arith.constant 9 : i32 @@ -270,8 +270,8 @@ end subroutine omp_parallel_do_multiple_firstprivate ! CHECK-LABEL: func.func @_QPomp_parallel_do_multiple_firstprivate( ! CHECK-SAME: %[[A_ADDR:.*]]: !fir.ref<i32> {fir.bindc_name = "a"}, ! CHECK-SAME: %[[B_ADDR:.*]]: !fir.ref<i32> {fir.bindc_name = "b"}) { -! CHECK: %[[A_DECL:.*]]:2 = hlfir.declare %[[A_ADDR]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFomp_parallel_do_multiple_firstprivateEa"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) -! CHECK: %[[B_DECL:.*]]:2 = hlfir.declare %[[B_ADDR]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFomp_parallel_do_multiple_firstprivateEb"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32> +! CHECK: %[[A_DECL:.*]]:2 = hlfir.declare %[[A_ADDR]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFomp_parallel_do_multiple_firstprivateEa"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[B_DECL:.*]]:2 = hlfir.declare %[[B_ADDR]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFomp_parallel_do_multiple_firstprivateEb"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32> ! CHECK: omp.parallel { ! CHECK: %[[VAL_8:.*]] = arith.constant 1 : i32 ! CHECK: %[[VAL_9:.*]] = arith.constant 10 : i32 diff --git a/flang/test/Lower/OpenMP/private-commonblock.f90 b/flang/test/Lower/OpenMP/private-commonblock.f90 index 241e9fa..df2702d 100644 --- a/flang/test/Lower/OpenMP/private-commonblock.f90 +++ b/flang/test/Lower/OpenMP/private-commonblock.f90 @@ -75,7 +75,7 @@ subroutine private_clause_commonblock() real::b(10) character(5):: c, d(5) common /blk/ a, b, c, d - + call sub1(a, b, c, d) !$omp parallel private(/blk/) call sub2(a, b, c, d) diff --git a/flang/test/Lower/OpenMP/privatize_predetermined_only_when_defined_by_eval.f90 b/flang/test/Lower/OpenMP/privatize_predetermined_only_when_defined_by_eval.f90 index 7671073..5e9e622 100644 --- a/flang/test/Lower/OpenMP/privatize_predetermined_only_when_defined_by_eval.f90 +++ b/flang/test/Lower/OpenMP/privatize_predetermined_only_when_defined_by_eval.f90 @@ -15,7 +15,7 @@ subroutine privatize_predetermined_when_defined_by_eval enddo enddo - !$omp do + !$omp do do j=1,ii enddo !$omp end parallel diff --git a/flang/test/Lower/OpenMP/reduction-array-intrinsic.f90 b/flang/test/Lower/OpenMP/reduction-array-intrinsic.f90 index 8b94d51..7793227 100644 --- a/flang/test/Lower/OpenMP/reduction-array-intrinsic.f90 +++ b/flang/test/Lower/OpenMP/reduction-array-intrinsic.f90 @@ -9,7 +9,7 @@ subroutine max_array_reduction(l, r) !$omp end parallel end subroutine -! CHECK-LABEL: omp.declare_reduction @max_byref_box_Uxi32 : !fir.ref<!fir.box<!fir.array<?xi32>>> alloc { +! CHECK-LABEL: omp.declare_reduction @max_byref_box_Uxi32 : !fir.ref<!fir.box<!fir.array<?xi32>>> {{.*}} alloc { ! CHECK: %[[VAL_3:.*]] = fir.alloca !fir.box<!fir.array<?xi32>> ! CHECK: omp.yield(%[[VAL_3]] : !fir.ref<!fir.box<!fir.array<?xi32>>>) ! CHECK-LABEL: } init { @@ -65,8 +65,8 @@ end subroutine ! CHECK-SAME: %[[VAL_1:.*]]: !fir.box<!fir.array<?xi32>> {fir.bindc_name = "r"}) { ! CHECK: %[[VAL_5:.*]] = fir.alloca !fir.box<!fir.array<?xi32>> ! CHECK: %[[VAL_2:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_2]] {uniq_name = "_QFmax_array_reductionEl"} : (!fir.box<!fir.array<?xi32>>, !fir.dscope) -> (!fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>>) -! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %[[VAL_2]] {uniq_name = "_QFmax_array_reductionEr"} : (!fir.box<!fir.array<?xi32>>, !fir.dscope) -> (!fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_2]] arg {{[0-9]+}} {uniq_name = "_QFmax_array_reductionEl"} : (!fir.box<!fir.array<?xi32>>, !fir.dscope) -> (!fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>>) +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %[[VAL_2]] arg {{[0-9]+}} {uniq_name = "_QFmax_array_reductionEr"} : (!fir.box<!fir.array<?xi32>>, !fir.dscope) -> (!fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>>) ! CHECK: fir.store %[[VAL_3]]#0 to %[[VAL_5]] : !fir.ref<!fir.box<!fir.array<?xi32>>> ! CHECK: omp.parallel reduction(byref @max_byref_box_Uxi32 %[[VAL_5]] -> %[[VAL_6:.*]] : !fir.ref<!fir.box<!fir.array<?xi32>>>) { ! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_6]] {uniq_name = "_QFmax_array_reductionEl"} : (!fir.ref<!fir.box<!fir.array<?xi32>>>) -> (!fir.ref<!fir.box<!fir.array<?xi32>>>, !fir.ref<!fir.box<!fir.array<?xi32>>>) diff --git a/flang/test/Lower/OpenMP/sections-array-reduction.f90 b/flang/test/Lower/OpenMP/sections-array-reduction.f90 index 2f2808c..57e46c7 100644 --- a/flang/test/Lower/OpenMP/sections-array-reduction.f90 +++ b/flang/test/Lower/OpenMP/sections-array-reduction.f90 @@ -14,7 +14,7 @@ subroutine sectionsReduction(x) end subroutine -! CHECK-LABEL: omp.declare_reduction @add_reduction_byref_box_Uxf32 : !fir.ref<!fir.box<!fir.array<?xf32>>> alloc { +! CHECK-LABEL: omp.declare_reduction @add_reduction_byref_box_Uxf32 : !fir.ref<!fir.box<!fir.array<?xf32>>> {{.*}} alloc { ! [...] ! CHECK: omp.yield ! CHECK-LABEL: } init { @@ -31,7 +31,7 @@ end subroutine ! CHECK-LABEL: func.func @_QPsectionsreduction( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.box<!fir.array<?xf32>> {fir.bindc_name = "x"}) { ! CHECK: %[[VAL_1:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] {uniq_name = "_QFsectionsreductionEx"} : (!fir.box<!fir.array<?xf32>>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.box<!fir.array<?xf32>>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] arg {{[0-9]+}} {uniq_name = "_QFsectionsreductionEx"} : (!fir.box<!fir.array<?xf32>>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.box<!fir.array<?xf32>>) ! CHECK: omp.parallel { ! CHECK: %[[VAL_3:.*]] = fir.alloca !fir.box<!fir.array<?xf32>> ! CHECK: fir.store %[[VAL_2]]#0 to %[[VAL_3]] : !fir.ref<!fir.box<!fir.array<?xf32>>> diff --git a/flang/test/Lower/OpenMP/sections-reduction.f90 b/flang/test/Lower/OpenMP/sections-reduction.f90 index 27da965..09fd1c2 100644 --- a/flang/test/Lower/OpenMP/sections-reduction.f90 +++ b/flang/test/Lower/OpenMP/sections-reduction.f90 @@ -37,8 +37,8 @@ end subroutine ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<f32> {fir.bindc_name = "x"}, ! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref<f32> {fir.bindc_name = "y"}) { ! CHECK: %[[VAL_2:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_2]] {uniq_name = "_QFsectionsreductionEx"} : (!fir.ref<f32>, !fir.dscope) -> (!fir.ref<f32>, !fir.ref<f32>) -! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %[[VAL_2]] {uniq_name = "_QFsectionsreductionEy"} : (!fir.ref<f32>, !fir.dscope) -> (!fir.ref<f32>, !fir.ref<f32>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_2]] arg {{[0-9]+}} {uniq_name = "_QFsectionsreductionEx"} : (!fir.ref<f32>, !fir.dscope) -> (!fir.ref<f32>, !fir.ref<f32>) +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %[[VAL_2]] arg {{[0-9]+}} {uniq_name = "_QFsectionsreductionEy"} : (!fir.ref<f32>, !fir.dscope) -> (!fir.ref<f32>, !fir.ref<f32>) ! CHECK: omp.parallel { ! CHECK: omp.sections reduction(@add_reduction_f32 %[[VAL_3]]#0 -> %[[VAL_5:.*]], @add_reduction_f32 %[[VAL_4]]#0 -> %[[VAL_6:.*]] : !fir.ref<f32>, !fir.ref<f32>) { ! CHECK: omp.section { diff --git a/flang/test/Lower/OpenMP/sections.f90 b/flang/test/Lower/OpenMP/sections.f90 index b77c46e..599e570 100644 --- a/flang/test/Lower/OpenMP/sections.f90 +++ b/flang/test/Lower/OpenMP/sections.f90 @@ -12,7 +12,7 @@ !CHECK: %[[CONST_1:.*]] = arith.constant 4 : i64 !CHECK: %[[PRIVATE_ETA:.*]] = fir.alloca f32 {bindc_name = "eta", pinned, uniq_name = "_QFEeta"} !CHECK: %[[PRIVATE_ETA_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_ETA]] {uniq_name = "_QFEeta"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>) -!CHECK: %[[PRIVATE_DOUBLE_COUNT:.*]] = fir.alloca i32 {bindc_name = "double_count", pinned, uniq_name = "_QFEdouble_count"} +!CHECK: %[[PRIVATE_DOUBLE_COUNT:.*]] = fir.alloca i32 {bindc_name = "double_count", pinned, uniq_name = "_QFEdouble_count"} !CHECK: %[[PRIVATE_DOUBLE_COUNT_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_DOUBLE_COUNT]] {uniq_name = "_QFEdouble_count"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) !CHECK: omp.sections allocate(%[[CONST_1]] : i64 -> %[[COUNT_DECL]]#0 : !fir.ref<i32>) { !CHECK: omp.section { @@ -79,7 +79,7 @@ program sample end program sample !CHECK: func @_QPfirstprivate(%[[ARG:.*]]: !fir.ref<f32> {fir.bindc_name = "alpha"}) { -!CHECK: %[[ARG_DECL:.*]]:2 = hlfir.declare %[[ARG]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFfirstprivateEalpha"} : (!fir.ref<f32>, !fir.dscope) -> (!fir.ref<f32>, !fir.ref<f32>) +!CHECK: %[[ARG_DECL:.*]]:2 = hlfir.declare %[[ARG]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFfirstprivateEalpha"} : (!fir.ref<f32>, !fir.dscope) -> (!fir.ref<f32>, !fir.ref<f32>) !CHECK: %[[PRIVATE_ALPHA:.*]] = fir.alloca f32 {bindc_name = "alpha", pinned, uniq_name = "_QFfirstprivateEalpha"} !CHECK: %[[PRIVATE_ALPHA_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_ALPHA]] {uniq_name = "_QFfirstprivateEalpha"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>) !CHECK: %[[TEMP:.*]] = fir.load %[[ARG_DECL]]#0 : !fir.ref<f32> diff --git a/flang/test/Lower/OpenMP/shared-loop.f90 b/flang/test/Lower/OpenMP/shared-loop.f90 index 48ad553..eb277ef 100644 --- a/flang/test/Lower/OpenMP/shared-loop.f90 +++ b/flang/test/Lower/OpenMP/shared-loop.f90 @@ -2,14 +2,14 @@ ! RUN: %flang_fc1 -emit-hlfir -fopenmp %s -o - | FileCheck %s ! --- Check that with shared(i) the variable outside the parallel section -! --- is updated. +! --- is updated. ! CHECK-LABEL: func.func @_QPomploop() ! CHECK: %[[ALLOC_I:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFomploopEi"} ! CHECK: %[[DECL_I:.*]]:2 = hlfir.declare %[[ALLOC_I]] {uniq_name = "_QFomploopEi"} : ! CHECK: omp.parallel { ! CHECK: omp.sections { ! CHECK: omp.section { -! CHECK: %[[RES:.*]] = fir.do_loop %[[ARG0:.*]] = %{{.*}} to %{{.*}} step %{{.*}} iter_args(%[[ARG1:.*]] = +! CHECK: %[[RES:.*]] = fir.do_loop %[[ARG0:.*]] = %{{.*}} to %{{.*}} step %{{.*}} iter_args(%[[ARG1:.*]] = ! CHECK: fir.store %[[ARG1]] to %[[DECL_I]]#0 ! CHECK: hlfir.assign ! CHECK: %[[LOAD_I:.*]] = fir.load %[[DECL_I]]#0 @@ -47,7 +47,7 @@ end subroutine ! CHECK: %[[DECL_PRIV_I:.*]]:2 = hlfir.declare %[[ALLOC_PRIV_I]] ! CHECK: omp.sections { ! CHECK: omp.section { -! CHECK: %[[RES:.*]] = fir.do_loop %[[ARG0:.*]] = %{{.*}} to %{{.*}} step %{{.*}} iter_args(%[[ARG1:.*]] = +! CHECK: %[[RES:.*]] = fir.do_loop %[[ARG0:.*]] = %{{.*}} to %{{.*}} step %{{.*}} iter_args(%[[ARG1:.*]] = ! CHECK-NOT: fir.store %[[ARG1]] to %[[DECL_I]]#1 ! CHECK: fir.store %[[ARG1]] to %[[DECL_PRIV_I]]#0 ! CHECK: hlfir.assign @@ -87,7 +87,7 @@ end subroutine ! CHECK: %[[DECL_PRIV_I:.*]]:2 = hlfir.declare %[[ALLOC_PRIV_I]] ! CHECK: omp.sections { ! CHECK: omp.section { -! CHECK: %[[RES:.*]] = fir.do_loop %[[ARG0:.*]] = %{{.*}} to %{{.*}} step %{{.*}} iter_args(%[[ARG1:.*]] = +! CHECK: %[[RES:.*]] = fir.do_loop %[[ARG0:.*]] = %{{.*}} to %{{.*}} step %{{.*}} iter_args(%[[ARG1:.*]] = ! CHECK-NOT: fir.store %[[ARG1]] to %[[DECL_I]]#1 ! CHECK: fir.store %[[ARG1]] to %[[DECL_PRIV_I]]#0 ! CHECK: hlfir.assign @@ -115,6 +115,3 @@ subroutine omploop3 !$omp end sections !$omp end parallel end subroutine - - - diff --git a/flang/test/Lower/OpenMP/simd-linear.f90 b/flang/test/Lower/OpenMP/simd-linear.f90 new file mode 100644 index 0000000..b6c7668 --- /dev/null +++ b/flang/test/Lower/OpenMP/simd-linear.f90 @@ -0,0 +1,57 @@ +! This test checks lowering of OpenMP SIMD Directive +! with linear clause + +! RUN: %flang_fc1 -fopenmp -emit-hlfir %s -o - 2>&1 | FileCheck %s + +!CHECK: %[[X_alloca:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFsimple_linearEx"} +!CHECK: %[[X:.*]]:2 = hlfir.declare %[[X_alloca]] {uniq_name = "_QFsimple_linearEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: %[[const:.*]] = arith.constant 1 : i32 +subroutine simple_linear + implicit none + integer :: x, y, i + !CHECK: omp.simd linear(%[[X]]#0 = %[[const]] : !fir.ref<i32>) {{.*}} + !$omp simd linear(x) + !CHECK: %[[LOAD:.*]] = fir.load %[[X]]#0 : !fir.ref<i32> + !CHECK: %[[const:.*]] = arith.constant 2 : i32 + !CHECK: %[[RESULT:.*]] = arith.addi %[[LOAD]], %[[const]] : i32 + do i = 1, 10 + y = x + 2 + end do + !CHECK: } {linear_var_types = [i32]} +end subroutine + + +!CHECK: %[[X_alloca:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFlinear_stepEx"} +!CHECK: %[[X:.*]]:2 = hlfir.declare %[[X_alloca]] {uniq_name = "_QFlinear_stepEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +subroutine linear_step + implicit none + integer :: x, y, i + !CHECK: %[[const:.*]] = arith.constant 4 : i32 + !CHECK: omp.simd linear(%[[X]]#0 = %[[const]] : !fir.ref<i32>) {{.*}} + !$omp simd linear(x:4) + !CHECK: %[[LOAD:.*]] = fir.load %[[X]]#0 : !fir.ref<i32> + !CHECK: %[[const:.*]] = arith.constant 2 : i32 + !CHECK: %[[RESULT:.*]] = arith.addi %[[LOAD]], %[[const]] : i32 + do i = 1, 10 + y = x + 2 + end do + !CHECK: } {linear_var_types = [i32]} +end subroutine + +!CHECK: %[[A_alloca:.*]] = fir.alloca i32 {bindc_name = "a", uniq_name = "_QFlinear_exprEa"} +!CHECK: %[[A:.*]]:2 = hlfir.declare %[[A_alloca]] {uniq_name = "_QFlinear_exprEa"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: %[[X_alloca:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFlinear_exprEx"} +!CHECK: %[[X:.*]]:2 = hlfir.declare %[[X_alloca]] {uniq_name = "_QFlinear_exprEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +subroutine linear_expr + implicit none + integer :: x, y, i, a + !CHECK: %[[LOAD_A:.*]] = fir.load %[[A]]#0 : !fir.ref<i32> + !CHECK: %[[const:.*]] = arith.constant 4 : i32 + !CHECK: %[[LINEAR_EXPR:.*]] = arith.addi %[[LOAD_A]], %[[const]] : i32 + !CHECK: omp.simd linear(%[[X]]#0 = %[[LINEAR_EXPR]] : !fir.ref<i32>) {{.*}} + !$omp simd linear(x:a+4) + do i = 1, 10 + y = x + 2 + end do + !CHECK: } {linear_var_types = [i32]} +end subroutine diff --git a/flang/test/Lower/OpenMP/simd.f90 b/flang/test/Lower/OpenMP/simd.f90 index 369b5eb..a3af762 100644 --- a/flang/test/Lower/OpenMP/simd.f90 +++ b/flang/test/Lower/OpenMP/simd.f90 @@ -26,7 +26,7 @@ end subroutine !CHECK-LABEL: func @_QPsimd_with_if_clause subroutine simd_with_if_clause(n, threshold) - ! CHECK: %[[ARG_N:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %{{[0-9]+}} {uniq_name = "_QFsimd_with_if_clauseEn"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) + ! CHECK: %[[ARG_N:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFsimd_with_if_clauseEn"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) integer :: i, n, threshold !$OMP SIMD IF( n .GE. threshold ) ! CHECK: %[[COND:.*]] = arith.cmpi sge @@ -46,7 +46,7 @@ end subroutine !CHECK-LABEL: func @_QPsimd_with_simdlen_clause subroutine simd_with_simdlen_clause(n, threshold) - ! CHECK: %[[ARG_N:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %{{[0-9]+}} {uniq_name = "_QFsimd_with_simdlen_clauseEn"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) + ! CHECK: %[[ARG_N:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFsimd_with_simdlen_clauseEn"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) integer :: i, n, threshold !$OMP SIMD SIMDLEN(2) ! CHECK: %[[LB:.*]] = arith.constant 1 : i32 @@ -65,7 +65,7 @@ end subroutine !CHECK-LABEL: func @_QPsimd_with_simdlen_clause_from_param subroutine simd_with_simdlen_clause_from_param(n, threshold) - ! CHECK: %[[ARG_N:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %{{[0-9]+}} {uniq_name = "_QFsimd_with_simdlen_clause_from_paramEn"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) + ! CHECK: %[[ARG_N:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFsimd_with_simdlen_clause_from_paramEn"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) integer :: i, n, threshold integer, parameter :: simdlen = 2; !$OMP SIMD SIMDLEN(simdlen) @@ -85,7 +85,7 @@ end subroutine !CHECK-LABEL: func @_QPsimd_with_simdlen_clause_from_expr_from_param subroutine simd_with_simdlen_clause_from_expr_from_param(n, threshold) - ! CHECK: %[[ARG_N:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %{{[0-9]+}} {uniq_name = "_QFsimd_with_simdlen_clause_from_expr_from_paramEn"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) + ! CHECK: %[[ARG_N:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFsimd_with_simdlen_clause_from_expr_from_paramEn"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) integer :: i, n, threshold integer, parameter :: simdlen = 2; !$OMP SIMD SIMDLEN(simdlen*2 + 2) @@ -105,7 +105,7 @@ end subroutine !CHECK-LABEL: func @_QPsimd_with_safelen_clause subroutine simd_with_safelen_clause(n, threshold) - ! CHECK: %[[ARG_N:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %{{[0-9]+}} {uniq_name = "_QFsimd_with_safelen_clauseEn"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) + ! CHECK: %[[ARG_N:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFsimd_with_safelen_clauseEn"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) integer :: i, n, threshold !$OMP SIMD SAFELEN(2) ! CHECK: %[[LB:.*]] = arith.constant 1 : i32 @@ -124,7 +124,7 @@ end subroutine !CHECK-LABEL: func @_QPsimd_with_safelen_clause_from_expr_from_param subroutine simd_with_safelen_clause_from_expr_from_param(n, threshold) - ! CHECK: %[[ARG_N:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %{{[0-9]+}} {uniq_name = "_QFsimd_with_safelen_clause_from_expr_from_paramEn"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) + ! CHECK: %[[ARG_N:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFsimd_with_safelen_clause_from_expr_from_paramEn"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) integer :: i, n, threshold integer, parameter :: safelen = 2; !$OMP SIMD SAFELEN(safelen*2 + 2) @@ -144,7 +144,7 @@ end subroutine !CHECK-LABEL: func @_QPsimd_with_simdlen_safelen_clause subroutine simd_with_simdlen_safelen_clause(n, threshold) - ! CHECK: %[[ARG_N:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %{{[0-9]+}} {uniq_name = "_QFsimd_with_simdlen_safelen_clauseEn"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) + ! CHECK: %[[ARG_N:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFsimd_with_simdlen_safelen_clauseEn"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) integer :: i, n, threshold !$OMP SIMD SIMDLEN(1) SAFELEN(2) ! CHECK: %[[LB:.*]] = arith.constant 1 : i32 @@ -270,7 +270,7 @@ subroutine lastprivate_with_simd integer :: i real :: sum - + !CHECK: omp.simd private(@_QFlastprivate_with_simdEsum_private_f32 %[[VAR_SUM_DECLARE]]#0 -> %[[VAR_SUM_PINNED:.*]], @{{.*}}) { !CHECK: omp.loop_nest (%[[ARG:.*]]) : i32 = ({{.*}} to ({{.*}}) inclusive step ({{.*}}) { !CHECK: %[[VAR_SUM_PINNED_DECLARE:.*]]:2 = hlfir.declare %[[VAR_SUM_PINNED]] {{.*}} diff --git a/flang/test/Lower/OpenMP/single.f90 b/flang/test/Lower/OpenMP/single.f90 index 59b76e3..69c4563 100644 --- a/flang/test/Lower/OpenMP/single.f90 +++ b/flang/test/Lower/OpenMP/single.f90 @@ -11,7 +11,7 @@ !CHECK-SAME: (%[[X:.*]]: !fir.ref<i32> {fir.bindc_name = "x"}) subroutine omp_single(x) integer, intent(inout) :: x - !CHECK: %[[X_DECL:.*]]:2 = hlfir.declare %[[X]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<intent_inout>, uniq_name = "_QFomp_singleEx"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) + !CHECK: %[[X_DECL:.*]]:2 = hlfir.declare %[[X]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<intent_inout>, uniq_name = "_QFomp_singleEx"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) !CHECK: omp.parallel !$omp parallel !CHECK: omp.single @@ -34,7 +34,7 @@ end subroutine omp_single !CHECK-SAME: (%[[X:.*]]: !fir.ref<i32> {fir.bindc_name = "x"}) subroutine omp_single_nowait(x) integer, intent(inout) :: x - !CHECK: %[[X_DECL:.*]]:2 = hlfir.declare %[[X]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<intent_inout>, uniq_name = "_QFomp_single_nowaitEx"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) + !CHECK: %[[X_DECL:.*]]:2 = hlfir.declare %[[X]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<intent_inout>, uniq_name = "_QFomp_single_nowaitEx"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) !CHECK: omp.parallel !$omp parallel !CHECK: omp.single nowait @@ -74,10 +74,10 @@ end subroutine single_allocate !=============================================================================== ! CHECK-LABEL: func.func @_QPsingle_privatization( -! CHECK-SAME: %[[X:.*]]: !fir.ref<f32> {fir.bindc_name = "x"}, +! CHECK-SAME: %[[X:.*]]: !fir.ref<f32> {fir.bindc_name = "x"}, ! CHECK-SAME: %[[Y:.*]]: !fir.ref<f64> {fir.bindc_name = "y"}) { -! CHECK: %[[X_DECL:.*]]:2 = hlfir.declare %[[X]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFsingle_privatizationEx"} : (!fir.ref<f32>, !fir.dscope) -> (!fir.ref<f32>, !fir.ref<f32>) -! CHECK: %[[Y_DECL:.*]]:2 = hlfir.declare %[[Y]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFsingle_privatizationEy"} : (!fir.ref<f64>, !fir.dscope) -> (!fir.ref<f64>, !fir.ref<f64>) +! CHECK: %[[X_DECL:.*]]:2 = hlfir.declare %[[X]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFsingle_privatizationEx"} : (!fir.ref<f32>, !fir.dscope) -> (!fir.ref<f32>, !fir.ref<f32>) +! CHECK: %[[Y_DECL:.*]]:2 = hlfir.declare %[[Y]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFsingle_privatizationEy"} : (!fir.ref<f64>, !fir.dscope) -> (!fir.ref<f64>, !fir.ref<f64>) ! CHECK: omp.single { ! CHECK: %[[X_PVT:.*]] = fir.alloca f32 {bindc_name = "x", pinned, uniq_name = "_QFsingle_privatizationEx"} ! CHECK: %[[X_PVT_DECL:.*]]:2 = hlfir.declare %[[X_PVT]] {uniq_name = "_QFsingle_privatizationEx"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>) @@ -103,8 +103,8 @@ end subroutine ! CHECK-LABEL: func.func @_QPsingle_privatization2( ! CHECK-SAME: %[[X:.*]]: !fir.ref<f32> {fir.bindc_name = "x"}, ! CHECK-SAME: %[[Y:.*]]: !fir.ref<f64> {fir.bindc_name = "y"}) { -! CHECK: %[[X_DECL:.*]]:2 = hlfir.declare %[[X]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFsingle_privatization2Ex"} : (!fir.ref<f32>, !fir.dscope) -> (!fir.ref<f32>, !fir.ref<f32>) -! CHECK: %[[Y_DECL:.*]]:2 = hlfir.declare %[[Y]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFsingle_privatization2Ey"} : (!fir.ref<f64>, !fir.dscope) -> (!fir.ref<f64>, !fir.ref<f64>) +! CHECK: %[[X_DECL:.*]]:2 = hlfir.declare %[[X]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFsingle_privatization2Ex"} : (!fir.ref<f32>, !fir.dscope) -> (!fir.ref<f32>, !fir.ref<f32>) +! CHECK: %[[Y_DECL:.*]]:2 = hlfir.declare %[[Y]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFsingle_privatization2Ey"} : (!fir.ref<f64>, !fir.dscope) -> (!fir.ref<f64>, !fir.ref<f64>) ! CHECK: omp.parallel { ! CHECK: omp.single { ! CHECK: %[[X_PVT:.*]] = fir.alloca f32 {bindc_name = "x", pinned, uniq_name = "_QFsingle_privatization2Ex"} diff --git a/flang/test/Lower/OpenMP/target-enter-data-default-openmp52.f90 b/flang/test/Lower/OpenMP/target-enter-data-default-openmp52.f90 index 0d4fd964..a717b38 100644 --- a/flang/test/Lower/OpenMP/target-enter-data-default-openmp52.f90 +++ b/flang/test/Lower/OpenMP/target-enter-data-default-openmp52.f90 @@ -11,7 +11,7 @@ contains allocate(A) !$omp target enter data map(A) !CHECK-52: omp.map.info var_ptr(%2 : !fir.ref<!fir.box<!fir.heap<f32>>>, f32) map_clauses(to) capture(ByRef) var_ptr_ptr(%5 : !fir.llvm_ptr<!fir.ref<f32>>) -> !fir.llvm_ptr<!fir.ref<f32>> {name = ""} - !CHECK-52: omp.map.info var_ptr(%2 : !fir.ref<!fir.box<!fir.heap<f32>>>, !fir.box<!fir.heap<f32>>) map_clauses(to) capture(ByRef) members(%6 : [0] : !fir.llvm_ptr<!fir.ref<f32>>) -> !fir.ref<!fir.box<!fir.heap<f32>>> {name = "a"} + !CHECK-52: omp.map.info var_ptr(%2 : !fir.ref<!fir.box<!fir.heap<f32>>>, !fir.box<!fir.heap<f32>>) map_clauses(always, to) capture(ByRef) members(%6 : [0] : !fir.llvm_ptr<!fir.ref<f32>>) -> !fir.ref<!fir.box<!fir.heap<f32>>> {name = "a"} !CHECK-51: to and alloc map types are permitted end subroutine initialize @@ -22,6 +22,6 @@ contains !CHECK-52: omp.map.info var_ptr(%2 : !fir.ref<!fir.box<!fir.heap<f32>>>, !fir.box<!fir.heap<f32>>) map_clauses(from) capture(ByRef) members(%4 : [0] : !fir.llvm_ptr<!fir.ref<f32>>) -> !fir.ref<!fir.box<!fir.heap<f32>>> {name = "a"} !CHECK-51: from, release and delete map types are permitted deallocate(A) - + end subroutine finalize end module test diff --git a/flang/test/Lower/OpenMP/target.f90 b/flang/test/Lower/OpenMP/target.f90 index 26bd62e..c5d3969 100644 --- a/flang/test/Lower/OpenMP/target.f90 +++ b/flang/test/Lower/OpenMP/target.f90 @@ -465,7 +465,7 @@ end subroutine omp_target_implicit_nested !CHECK: %[[VAL_0:.*]]: !fir.ref<i32> {fir.bindc_name = "n"}) { subroutine omp_target_implicit_bounds(n) !CHECK: %[[VAL_COPY:.*]] = fir.alloca i32 - !CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFomp_target_implicit_boundsEn"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) + !CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFomp_target_implicit_boundsEn"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) !CHECK: %[[VAL_2:.*]] = fir.load %[[VAL_1]]#0 : !fir.ref<i32> !CHECK: fir.store %[[VAL_2]] to %[[VAL_COPY]] : !fir.ref<i32> !CHECK: %[[VAL_3:.*]] = fir.convert %[[VAL_2]] : (i32) -> i64 @@ -529,7 +529,7 @@ subroutine omp_target_device_ptr use iso_c_binding, only : c_ptr, c_loc type(c_ptr) :: a integer, target :: b - !CHECK: %[[MAP:.*]] = omp.map.info var_ptr({{.*}}) map_clauses(tofrom) capture(ByRef) -> {{.*}} {name = "a"} + !CHECK: %[[MAP:.*]] = omp.map.info var_ptr({{.*}}) map_clauses(tofrom) capture(ByRef) mapper(@[[CPTR_DEFAULT:_QQM__fortran_builtinsc_ptr_omp_default_mapper]]) -> {{.*}} {name = "a"} !CHECK: omp.target_data map_entries(%[[MAP]]{{.*}}) use_device_ptr({{.*}} -> %[[VAL_1:.*]] : !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>) !$omp target data map(tofrom: a) use_device_ptr(a) !CHECK: {{.*}} = fir.coordinate_of %[[VAL_1:.*]], __address : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>) -> !fir.ref<i64> @@ -549,9 +549,9 @@ subroutine omp_target_device_addr !CHECK: %[[VAL_0:.*]] = fir.alloca !fir.box<!fir.ptr<i32>> {bindc_name = "a", uniq_name = "_QFomp_target_device_addrEa"} !CHECK: %[[VAL_0_DECL:.*]]:2 = hlfir.declare %[[VAL_0]] {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFomp_target_device_addrEa"} : (!fir.ref<!fir.box<!fir.ptr<i32>>>) -> (!fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.ref<!fir.box<!fir.ptr<i32>>>) !CHECK: %[[MAP_MEMBERS:.*]] = omp.map.info var_ptr({{.*}} : !fir.ref<!fir.box<!fir.ptr<i32>>>, i32) map_clauses(tofrom) capture(ByRef) var_ptr_ptr({{.*}} : !fir.llvm_ptr<!fir.ref<i32>>) -> !fir.llvm_ptr<!fir.ref<i32>> {name = ""} - !CHECK: %[[MAP:.*]] = omp.map.info var_ptr({{.*}} : !fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.box<!fir.ptr<i32>>) map_clauses(to) capture(ByRef) members(%[[MAP_MEMBERS]] : [0] : !fir.llvm_ptr<!fir.ref<i32>>) -> !fir.ref<!fir.box<!fir.ptr<i32>>> {name = "a"} + !CHECK: %[[MAP:.*]] = omp.map.info var_ptr({{.*}} : !fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.box<!fir.ptr<i32>>) map_clauses(always, to) capture(ByRef) members(%[[MAP_MEMBERS]] : [0] : !fir.llvm_ptr<!fir.ref<i32>>) -> !fir.ref<!fir.box<!fir.ptr<i32>>> {name = "a"} !CHECK: %[[DEV_ADDR_MEMBERS:.*]] = omp.map.info var_ptr({{.*}} : !fir.ref<!fir.box<!fir.ptr<i32>>>, i32) map_clauses(return_param) capture(ByRef) var_ptr_ptr({{.*}} : !fir.llvm_ptr<!fir.ref<i32>>) -> !fir.llvm_ptr<!fir.ref<i32>> {name = ""} - !CHECK: %[[DEV_ADDR:.*]] = omp.map.info var_ptr({{.*}} : !fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.box<!fir.ptr<i32>>) map_clauses(to) capture(ByRef) members(%[[DEV_ADDR_MEMBERS]] : [0] : !fir.llvm_ptr<!fir.ref<i32>>) -> !fir.ref<!fir.box<!fir.ptr<i32>>> {name = "a"} + !CHECK: %[[DEV_ADDR:.*]] = omp.map.info var_ptr({{.*}} : !fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.box<!fir.ptr<i32>>) map_clauses(always, to) capture(ByRef) members(%[[DEV_ADDR_MEMBERS]] : [0] : !fir.llvm_ptr<!fir.ref<i32>>) -> !fir.ref<!fir.box<!fir.ptr<i32>>> {name = "a"} !CHECK: omp.target_data map_entries(%[[MAP]], %[[MAP_MEMBERS]] : {{.*}}) use_device_addr(%[[DEV_ADDR]] -> %[[ARG_0:.*]], %[[DEV_ADDR_MEMBERS]] -> %[[ARG_1:.*]] : !fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.llvm_ptr<!fir.ref<i32>>) { !$omp target data map(tofrom: a) use_device_addr(a) !CHECK: %[[VAL_1_DECL:.*]]:2 = hlfir.declare %[[ARG_0]] {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFomp_target_device_addrEa"} : (!fir.ref<!fir.box<!fir.ptr<i32>>>) -> (!fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.ref<!fir.box<!fir.ptr<i32>>>) @@ -567,6 +567,36 @@ end subroutine omp_target_device_addr !=============================================================================== +! Target `is_device_ptr` clause +!=============================================================================== + +!CHECK-LABEL: func.func @_QPomp_target_is_device_ptr() { +subroutine omp_target_is_device_ptr + use iso_c_binding, only: c_ptr + implicit none + integer :: i + integer :: arr(4) + type(c_ptr) :: p + + i = 0 + arr = 0 + + !CHECK: %[[P_STORAGE:.*]] = omp.map.info {{.*}}{name = "p"} + !CHECK: %[[P_IS:.*]] = omp.map.info {{.*}}{name = "p"} + !CHECK: %[[ARR_MAP:.*]] = omp.map.info {{.*}}{name = "arr"} + !CHECK: omp.target is_device_ptr(%[[P_IS]] : + !CHECK-SAME: has_device_addr(%[[P_STORAGE]] -> + !CHECK-SAME: map_entries({{.*}}%[[ARR_MAP]] -> + !$omp target is_device_ptr(p) + i = i + 1 + arr(1) = i + !$omp end target + !CHECK: omp.terminator + !CHECK: } +end subroutine omp_target_is_device_ptr + + +!=============================================================================== ! Target Data with unstructured code !=============================================================================== !CHECK-LABEL: func.func @_QPsb diff --git a/flang/test/Lower/OpenMP/target_cpu_features.f90 b/flang/test/Lower/OpenMP/target_cpu_features.f90 index 4532593..341cfc79 100644 --- a/flang/test/Lower/OpenMP/target_cpu_features.f90 +++ b/flang/test/Lower/OpenMP/target_cpu_features.f90 @@ -11,8 +11,8 @@ !AMDGCN-SAME: fir.target_features = #llvm.target_features<["+16-bit-insts", "+ci-insts", !AMDGCN-SAME: "+dl-insts", "+dot1-insts", "+dot10-insts", "+dot2-insts", "+dot3-insts", !AMDGCN-SAME: "+dot4-insts", "+dot5-insts", "+dot6-insts", "+dot7-insts", "+dpp", -!AMDGCN-SAME: "+gfx8-insts", "+gfx9-insts", "+gws", "+image-insts", "+mai-insts", -!AMDGCN-SAME: "+s-memrealtime", "+s-memtime-inst", "+vmem-to-lds-load-insts", "+wavefrontsize64"]> +!AMDGCN-SAME: "+gfx8-insts", "+gfx9-insts", "+gws", "+image-insts", "+lerp-inst", "+mai-insts", +!AMDGCN-SAME: "+qsad-insts", "+s-memrealtime", "+s-memtime-inst", "+sad-insts", "+vmem-to-lds-load-insts", "+wavefrontsize64"]> !NVPTX: module attributes { !NVPTX-SAME: fir.target_cpu = "sm_80" diff --git a/flang/test/Lower/OpenMP/task-depend-array-section.f90 b/flang/test/Lower/OpenMP/task-depend-array-section.f90 index 4033b8e..ab2bfd7 100644 --- a/flang/test/Lower/OpenMP/task-depend-array-section.f90 +++ b/flang/test/Lower/OpenMP/task-depend-array-section.f90 @@ -12,7 +12,7 @@ end subroutine ! CHECK: %[[VAL_1:.*]] = fir.dummy_scope : !fir.dscope ! CHECK: %[[VAL_2:.*]] = arith.constant 10 : index ! CHECK: %[[VAL_3:.*]] = fir.shape %[[VAL_2]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_3]]) dummy_scope %[[VAL_1]] {uniq_name = "_QFknownshapeEarray"} : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>) +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_3]]) dummy_scope %[[VAL_1]] arg {{[0-9]+}} {uniq_name = "_QFknownshapeEarray"} : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>) ! CHECK: %[[VAL_5:.*]] = arith.constant 2 : index ! CHECK: %[[VAL_6:.*]] = arith.constant 8 : index ! CHECK: %[[VAL_7:.*]] = arith.constant 1 : index @@ -36,7 +36,7 @@ end subroutine ! CHECK-LABEL: func.func @_QPassumedshape( ! CHECK-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.box<!fir.array<?xi32>> {fir.bindc_name = "array"}) { ! CHECK: %[[VAL_1:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] {uniq_name = "_QFassumedshapeEarray"} : (!fir.box<!fir.array<?xi32>>, !fir.dscope) -> (!fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] arg {{[0-9]+}} {uniq_name = "_QFassumedshapeEarray"} : (!fir.box<!fir.array<?xi32>>, !fir.dscope) -> (!fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>>) ! CHECK: %[[VAL_3:.*]] = arith.constant 2 : index ! CHECK: %[[VAL_4:.*]] = arith.constant 8 : index ! CHECK: %[[VAL_5:.*]] = arith.constant 2 : index @@ -61,8 +61,8 @@ end subroutine ! CHECK-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.box<!fir.array<?xi32>> {fir.bindc_name = "array"}, ! CHECK-SAME: %[[VAL_1:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.box<!fir.array<?xi32>> {fir.bindc_name = "indices"}) { ! CHECK: %[[VAL_2:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_2]] {uniq_name = "_QFvectorsubscriptarraysectionEarray"} : (!fir.box<!fir.array<?xi32>>, !fir.dscope) -> (!fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>>) -! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %[[VAL_2]] {uniq_name = "_QFvectorsubscriptarraysectionEindices"} : (!fir.box<!fir.array<?xi32>>, !fir.dscope) -> (!fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_2]] arg {{[0-9]+}} {uniq_name = "_QFvectorsubscriptarraysectionEarray"} : (!fir.box<!fir.array<?xi32>>, !fir.dscope) -> (!fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>>) +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %[[VAL_2]] arg {{[0-9]+}} {uniq_name = "_QFvectorsubscriptarraysectionEindices"} : (!fir.box<!fir.array<?xi32>>, !fir.dscope) -> (!fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>>) ! CHECK: %[[VAL_5:.*]] = arith.constant 0 : index ! CHECK: %[[VAL_6:.*]]:3 = fir.box_dims %[[VAL_4]]#0, %[[VAL_5]] : (!fir.box<!fir.array<?xi32>>, index) -> (index, index, index) ! CHECK: %[[VAL_7:.*]] = fir.shape %[[VAL_6]]#1 : (index) -> !fir.shape<1> diff --git a/flang/test/Lower/OpenMP/task.f90 b/flang/test/Lower/OpenMP/task.f90 index 67194fa..75c7a3f 100644 --- a/flang/test/Lower/OpenMP/task.f90 +++ b/flang/test/Lower/OpenMP/task.f90 @@ -212,7 +212,7 @@ subroutine task_firstprivate type mytype integer :: x end type mytype - + !CHECK: %[[INT_ALLOCA:.+]] = fir.alloca i32 {bindc_name = "int_var", uniq_name = "_QFtask_firstprivateEint_var"} !CHECK: %[[INT_VAR:.+]]:2 = hlfir.declare %[[INT_ALLOCA]] {uniq_name = "_QFtask_firstprivateEint_var"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) !CHECK: %[[MYTYPE_ALLOCA:.+]] = fir.alloca !fir.type<_QFtask_firstprivateTmytype{x:i32}> {bindc_name = "mytype_var", uniq_name = "_QFtask_firstprivateEmytype_var"} diff --git a/flang/test/Lower/OpenMP/taskgroup-task-array-reduction.f90 b/flang/test/Lower/OpenMP/taskgroup-task-array-reduction.f90 index 18a4f75..cdc9182 100644 --- a/flang/test/Lower/OpenMP/taskgroup-task-array-reduction.f90 +++ b/flang/test/Lower/OpenMP/taskgroup-task-array-reduction.f90 @@ -1,7 +1,7 @@ ! RUN: bbc -emit-hlfir -fopenmp -fopenmp-version=50 -o - %s 2>&1 | FileCheck %s ! RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=50 -o - %s 2>&1 | FileCheck %s -! CHECK-LABEL: omp.declare_reduction @add_reduction_byref_box_Uxf32 : !fir.ref<!fir.box<!fir.array<?xf32>>> alloc { +! CHECK-LABEL: omp.declare_reduction @add_reduction_byref_box_Uxf32 : !fir.ref<!fir.box<!fir.array<?xf32>>> {{.*}} alloc { ! [...] ! CHECK: omp.yield ! CHECK-LABEL: } init { @@ -24,7 +24,7 @@ ! CHECK: %[[VAL_3:.*]] = fir.alloca !fir.box<!fir.array<?xf32>> ! CHECK: fir.store %[[VAL_2]]#0 to %[[VAL_3]] : !fir.ref<!fir.box<!fir.array<?xf32>>> ! CHECK: omp.taskgroup task_reduction(byref @add_reduction_byref_box_Uxf32 %[[VAL_3]] -> %[[VAL_4:.*]]: !fir.ref<!fir.box<!fir.array<?xf32>>>) { -! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_4]] +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_4]] ! CHECK-SAME: {uniq_name = "_QFtask_reductionEx"} : (!fir.ref<!fir.box<!fir.array<?xf32>>>) -> (!fir.ref<!fir.box<!fir.array<?xf32>>>, !fir.ref<!fir.box<!fir.array<?xf32>>>) ! CHECK: omp.task in_reduction(byref @add_reduction_byref_box_Uxf32 %[[VAL_5]]#0 -> %[[VAL_6:.*]] : !fir.ref<!fir.box<!fir.array<?xf32>>>) { ! [...] diff --git a/flang/test/Lower/OpenMP/taskgroup-task_reduction01.f90 b/flang/test/Lower/OpenMP/taskgroup-task_reduction01.f90 index be4d319..e9f2225 100644 --- a/flang/test/Lower/OpenMP/taskgroup-task_reduction01.f90 +++ b/flang/test/Lower/OpenMP/taskgroup-task_reduction01.f90 @@ -16,7 +16,7 @@ !CHECK: %[[VAL_0:.*]] = fir.alloca i32 {bindc_name = "res", uniq_name = "_QFomp_taskgroup_task_reductionEres"} !CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = "_QFomp_taskgroup_task_reductionEres"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) !CHECK: omp.taskgroup task_reduction(@[[RED_I32_NAME]] %[[VAL_1]]#0 -> %[[VAL_2:.*]] : !fir.ref<i32>) { -!CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]] +!CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]] !CHECK-SAME: {uniq_name = "_QFomp_taskgroup_task_reductionEres"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) !CHECK: %[[VAL_4:.*]] = fir.load %[[VAL_3]]#0 : !fir.ref<i32> !CHECK: %[[VAL_5:.*]] = arith.constant 1 : i32 diff --git a/flang/test/Lower/OpenMP/taskloop-cancel.f90 b/flang/test/Lower/OpenMP/taskloop-cancel.f90 index 2bc0f17..7106177 100644 --- a/flang/test/Lower/OpenMP/taskloop-cancel.f90 +++ b/flang/test/Lower/OpenMP/taskloop-cancel.f90 @@ -1,7 +1,7 @@ ! RUN: bbc -emit-hlfir -fopenmp -o - %s -fopenmp-version=50 2>&1 | FileCheck %s ! RUN: %flang_fc1 -emit-hlfir -fopenmp -o - %s -fopenmp-version=50 2>&1 | FileCheck %s -! CHECK-LABEL: omp.private {type = private} +! CHECK-LABEL: omp.private {type = private} ! CHECK-SAME: @[[I_PRIVATE:.*]] : i32 ! CHECK-LABEL: func.func @_QPomp_taskloop() { diff --git a/flang/test/Lower/OpenMP/taskloop-collapse.f90 b/flang/test/Lower/OpenMP/taskloop-collapse.f90 new file mode 100644 index 0000000..4824364 --- /dev/null +++ b/flang/test/Lower/OpenMP/taskloop-collapse.f90 @@ -0,0 +1,34 @@ +! Test the collapse clause when being used with the taskloop construct +! RUN: bbc -emit-hlfir -fopenmp -fopenmp-version=45 %s -o - 2>&1 | FileCheck %s +! RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=45 %s -o - 2>&1 | FileCheck %s + +! CHECK-LABEL: omp.private +! CHECK-SAME: {type = private} @[[J_PRIVATE:.*]] : i32 +! CHECK-LABEL: omp.private +! CHECK-SAME: {type = private} @[[I_PRIVATE:.*]] : i32 +! CHECK-LABEL: omp.private +! CHECK-SAME: {type = firstprivate} @[[SUM_FIRSTPRIVATE:.*]] : i32 copy + +! CHECK-LABEL: func.func @_QPtest() +! CHECK: %[[ALLOCA_I:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFtestEi"} +! CHECK: %[[DECLARE_I:.*]]:2 = hlfir.declare %1 {uniq_name = "_QFtestEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[ALLOCA_J:.*]] = fir.alloca i32 {bindc_name = "j", uniq_name = "_QFtestEj"} +! CHECK: %[[DECLARE_J:.*]]:2 = hlfir.declare %3 {uniq_name = "_QFtestEj"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[ALLOCA_SUM:.*]] = fir.alloca i32 {bindc_name = "sum", uniq_name = "_QFtestEsum"} +! CHECK: %[[DECLARE_SUM:.*]]:2 = hlfir.declare %5 {uniq_name = "_QFtestEsum"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) + +subroutine test() + integer :: i, j, sum + + !$omp taskloop collapse(2) + ! CHECK-LABEL: omp.taskloop + ! CHECK-SAME: private(@_QFtestEsum_firstprivate_i32 %[[DECLARE_SUM]]#0 -> %arg0, @_QFtestEi_private_i32 %[[DECLARE_I]]#0 -> %arg1, @_QFtestEj_private_i32 %[[DECLARE_J]]#0 -> %arg2 : !fir.ref<i32>, !fir.ref<i32>, !fir.ref<i32>) + ! CHECK-LABEL: omp.loop_nest + ! CHECK-SAME: (%arg3, %arg4) : i32 = (%c1_i32, %c1_i32_1) to (%c10_i32, %c5_i32) inclusive step (%c1_i32_0, %c1_i32_2) collapse(2) + do i = 1, 10 + do j = 1, 5 + sum = sum + i + j + end do + end do + !$omp end taskloop +end subroutine diff --git a/flang/test/Lower/OpenMP/taskloop-grainsize.f90 b/flang/test/Lower/OpenMP/taskloop-grainsize.f90 index 43db8acd..8aee5f6 100644 --- a/flang/test/Lower/OpenMP/taskloop-grainsize.f90 +++ b/flang/test/Lower/OpenMP/taskloop-grainsize.f90 @@ -27,7 +27,7 @@ ! CHECK: %[[GRAINSIZE:.*]] = arith.constant 10 : i32 subroutine test_grainsize integer :: i, x - ! CHECK: omp.taskloop grainsize(%[[GRAINSIZE]]: i32) + ! CHECK: omp.taskloop grainsize(%[[GRAINSIZE]]: i32) ! CHECK-SAME: private(@[[X_FIRSTPRIVATE]] %[[DECL_X]]#0 -> %[[ARG0:.*]], @[[I_PRIVATE]] %[[DECL_I]]#0 -> %[[ARG1:.*]] : !fir.ref<i32>, !fir.ref<i32>) { ! CHECK: omp.loop_nest (%[[ARG2:.*]]) : i32 = (%{{.*}}) to (%{{.*}}) inclusive step (%{{.*}}) { !$omp taskloop grainsize(10) diff --git a/flang/test/Lower/OpenMP/taskloop-numtasks.f90 b/flang/test/Lower/OpenMP/taskloop-numtasks.f90 index f68f3a2..e5b7a49 100644 --- a/flang/test/Lower/OpenMP/taskloop-numtasks.f90 +++ b/flang/test/Lower/OpenMP/taskloop-numtasks.f90 @@ -27,7 +27,7 @@ ! CHECK: %[[VAL_NUMTASKS:.*]] = arith.constant 10 : i32 subroutine test_num_tasks integer :: i, x - ! CHECK: omp.taskloop num_tasks(%[[VAL_NUMTASKS]]: i32) + ! CHECK: omp.taskloop num_tasks(%[[VAL_NUMTASKS]]: i32) ! CHECK-SAME: private(@[[X_FIRSTPRIVATE]] %[[DECL_X]]#0 -> %[[ARG0:.*]], @[[I_PRIVATE]] %[[DECL_I]]#0 -> %[[ARG1:.*]] : !fir.ref<i32>, !fir.ref<i32>) { ! CHECK: omp.loop_nest (%[[ARG2:.*]]) : i32 = (%{{.*}}) to (%{{.*}}) inclusive step (%{{.*}}) { !$omp taskloop num_tasks(10) diff --git a/flang/test/Lower/OpenMP/taskloop.f90 b/flang/test/Lower/OpenMP/taskloop.f90 index 79b0c20..bfe4fe7 100644 --- a/flang/test/Lower/OpenMP/taskloop.f90 +++ b/flang/test/Lower/OpenMP/taskloop.f90 @@ -1,19 +1,50 @@ -! RUN: bbc -emit-hlfir -fopenmp -fopenmp-version=50 -o - %s 2>&1 | FileCheck %s -! RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=50 -o - %s 2>&1 | FileCheck %s +! REQUIRES: openmp_runtime +! RUN: bbc -emit-hlfir %openmp_flags -o - %s 2>&1 | FileCheck %s +! RUN: %flang_fc1 -emit-hlfir %openmp_flags -o - %s 2>&1 | FileCheck %s -! CHECK-LABEL: omp.private +! CHECK-LABEL: omp.private +! CHECK-SAME: {type = private} @[[LAST_PRIVATE_I:.*]] : i32 + +! CHECK-LABEL: omp.private +! CHECK-SAME: {type = private} @[[LAST_PRIVATE_X:.*]] : i32 + +! CHECK-LABEL: omp.private +! CHECK-SAME: {type = private} @[[QFOMP_TASKLOOP_NOGROUPEI_PRIVATE_I32:.*]] : i32 + +! CHECK-LABEL: omp.private +! CHECK-SAME: {type = private} @[[OMP_TASKLOOP_UNTIEDEI_PRIVATE_I32:.*]] : i32 + +! CHECK-LABEL: omp.private +! CHECK-SAME: {type = private} @[[QFTEST_PRIORITYEI_PRIVATE_I32:.*]] : i32 + +! CHECK-LABEL: omp.private +! CHECK-SAME: {type = private} @[[QFTEST_MERGEABLEEI_PRIVATE_I32:.*]] : i32 + +! CHECK-LABEL: omp.private +! CHECK-SAME: {type = private} @[[I_PRIVATE_IF_TEST1:.*]] : i32 + +! CHECK-LABEL: omp.private +! CHECK-SAME: {type = private} @[[I_PRIVATE_FINAL:.*]] : i32 + +! CHECK-LABEL: omp.private +! CHECK-SAME: {type = private} @[[I_PRIVATE_TEST_ALLOCATE:.*]] : i32 + +! CHECK-LABEL: omp.private +! CHECK-SAME: {type = private} @[[X_PRIVATE_TEST_ALLOCATE:.*]] : i32 + +! CHECK-LABEL: omp.private ! CHECK-SAME: {type = private} @[[I_PRIVATE_TEST2:.*]] : i32 -! CHECK-LABEL: omp.private +! CHECK-LABEL: omp.private ! CHECK-SAME: {type = private} @[[RES_PRIVATE_TEST2:.*]] : i32 -! CHECK-LABEL: omp.private +! CHECK-LABEL: omp.private ! CHECK-SAME: {type = private} @[[I_PRIVATE:.*]] : i32 -! CHECK-LABEL: omp.private -! CHECK-SAME: {type = firstprivate} @[[RES_FIRSTPRIVATE:.*]] : i32 +! CHECK-LABEL: omp.private +! CHECK-SAME: {type = firstprivate} @[[RES_FIRSTPRIVATE:.*]] : i32 ! CHECK-SAME: copy { -! CHECK: hlfir.assign +! CHECK: hlfir.assign ! CHECK-LABEL: func.func @_QPomp_taskloop ! CHECK: %[[ALLOCA_I:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFomp_taskloopEi"} @@ -70,3 +101,149 @@ subroutine omp_taskloop_private ! CHECK: } !$omp end taskloop end subroutine omp_taskloop_private + +!=============================================================================== +! `allocate` clause +!=============================================================================== + +! CHECK-LABEL: func.func @_QPtaskloop_allocate +! CHECK: %[[ALLOCA_I:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFtaskloop_allocateEi"} +! CHECK: %[[DECL_I:.*]]:2 = hlfir.declare %[[ALLOCA_I]] {uniq_name = "_QFtaskloop_allocateEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[ALLOCA_X:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFtaskloop_allocateEx"} +! CHECK: %[[DECL_X:.*]]:2 = hlfir.declare %[[ALLOCA_X]] {uniq_name = "_QFtaskloop_allocateEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +subroutine taskloop_allocate() + use omp_lib + integer :: x + ! CHECK: omp.taskloop allocate(%{{.*}} : i64 -> %[[DECL_X]]#0 : !fir.ref<i32>) + ! CHECK-SAME: private(@[[X_PRIVATE_TEST_ALLOCATE]] %[[DECL_X]]#0 -> %[[ARG0:.*]], @[[I_PRIVATE_TEST_ALLOCATE]] %[[DECL_I]]#0 -> %[[ARG1:.*]] : !fir.ref<i32>, !fir.ref<i32>) { + !$omp taskloop allocate(omp_high_bw_mem_alloc: x) private(x) + do i = 1, 100 + ! CHECK: arith.addi + x = x + 12 + ! CHECK: omp.yield + end do + !$omp end taskloop +end subroutine taskloop_allocate + +!=============================================================================== +! `final` clause +!=============================================================================== + +! CHECK-LABEL: func.func @_QPtaskloop_final +! CHECK: %[[ALLOCA_I:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFtaskloop_finalEi"} +! CHECK: %[[DECL_I:.*]]:2 = hlfir.declare %[[ALLOCA_I]] {uniq_name = "_QFtaskloop_finalEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +subroutine taskloop_final() + ! CHECK: omp.taskloop final(%true) private(@[[I_PRIVATE_FINAL]] %[[DECL_I]]#0 -> %[[ARG0:.*]] : !fir.ref<i32>) { + !$omp taskloop final(.true.) + do i = 1, 100 + ! CHECK: fir.call @_QPfoo() + call foo() + end do + !$omp end taskloop +end subroutine + +!=============================================================================== +! `if` clause +!=============================================================================== + +! CHECK-LABEL: func.func @_QPomp_taskloop_if +! CHECK: %[[DECL_BAR:.*]]:2 = hlfir.declare %[[ARG0:.*]] dummy_scope %{{.*}} +! CHECK: %[[ALLOCA_I:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFomp_taskloop_ifEi"} +! CHECK: %[[DECL_I:.*]]:2 = hlfir.declare %[[ALLOCA_I]] {uniq_name = "_QFomp_taskloop_ifEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[LOAD_VAL:.*]] = fir.load %[[DECL_BAR]]#0 : !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_BAR:.*]] = fir.convert %[[LOAD_VAL]] : (!fir.logical<4>) -> i1 +subroutine omp_taskloop_if(bar) + logical, intent(inout) :: bar + !CHECK: omp.taskloop if(%[[VAL_BAR]]) private(@[[I_PRIVATE_IF_TEST1]] %[[DECL_I]]#0 -> %[[ARG1:.*]] : !fir.ref<i32>) { + !$omp taskloop if(bar) + do i = 1, 10 + call foo() + end do + !$omp end taskloop +end subroutine omp_taskloop_if + +!=============================================================================== +! `mergeable` clause +!=============================================================================== + +! CHECK-LABEL: func.func @_QPtest_mergeable +subroutine test_mergeable + ! CHECK: omp.taskloop mergeable + !$omp taskloop mergeable + do i = 1, 10 + end do + !$omp end taskloop +end subroutine test_mergeable + +!=============================================================================== +! `priority` clause +!=============================================================================== + +! CHECK-LABEL: func.func @_QPtest_priority +! CHECK: %[[VAL1:.*]]:2 = hlfir.declare %[[ARG0:.*]] dummy_scope %{{.*}} +! CHECK: %[[LOAD_VAL:.*]] = fir.load %[[VAL1]]#0 : !fir.ref<i32> +subroutine test_priority(n) + integer, intent(inout) :: n + ! CHECK: omp.taskloop priority(%[[LOAD_VAL]] : i32) + !$omp taskloop priority(n) + do i = 1, 10 + end do + !$omp end taskloop +end subroutine test_priority + +!=============================================================================== +! `untied` clause +!=============================================================================== + +! CHECK-LABEL: func.func @_QPomp_taskloop_untied +subroutine omp_taskloop_untied() + ! CHECK: omp.taskloop untied + !$omp taskloop untied + do i = 1, 10 + call foo() + end do + !$omp end taskloop +end subroutine + +!=============================================================================== +! `nogroup` clause +!=============================================================================== + +subroutine omp_taskloop_nogroup() + ! CHECK: omp.taskloop nogroup + !$omp taskloop nogroup + do i = 1, 10 + call foo() + end do + !$omp end taskloop +end subroutine + +!=============================================================================== +! `lastprivate` clause +!=============================================================================== + +! CHECK-LABEL: func.func @_QPomp_taskloop_lastprivate +! CHECK: %[[ALLOCA_I:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFomp_taskloop_lastprivateEi"} +! CHECK: %[[DECL_I:.*]]:2 = hlfir.declare %[[ALLOCA_I]] {uniq_name = "_QFomp_taskloop_lastprivateEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[ALLOCA_X:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFomp_taskloop_lastprivateEx"} +! CHECK: %[[DECL_X:.*]]:2 = hlfir.declare %[[ALLOCA_X]] {uniq_name = "_QFomp_taskloop_lastprivateEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +subroutine omp_taskloop_lastprivate() + integer x + x = 0 + ! CHECK: omp.taskloop private(@[[LAST_PRIVATE_X]] %[[DECL_X]]#0 -> %[[ARG0]], @[[LAST_PRIVATE_I]] %[[DECL_I]]#0 -> %[[ARG1]] : !fir.ref<i32>, !fir.ref<i32>) { + !$omp taskloop lastprivate(x) + do i = 1, 100 + ! CHECK: %[[DECL_ARG0:.*]]:2 = hlfir.declare %[[ARG0]] {uniq_name = "_QFomp_taskloop_lastprivateEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) + ! CHECK: %[[LOAD_ARG0:.*]] = fir.load %[[DECL_ARG0]]#0 : !fir.ref<i32> + ! CHECK: %[[RES_ADD:.*]] = arith.addi %[[LOAD_ARG0]], %{{.*}} : i32 + ! CHECK: hlfir.assign %[[RES_ADD]] to %[[DECL_ARG0]]#0 : i32, !fir.ref<i32> + x = x + 1 + ! CHECK: %[[SELCT_RESULT:.*]] = arith.select %{{.*}}, %{{.*}}, %{{.*}} : i1 + ! CHECK: fir.if %[[SELCT_RESULT]] { + ! CHECK: %[[LOADED_SUM:.*]] = fir.load %[[DECL_ARG0]]#0 : !fir.ref<i32> + ! CHECK: hlfir.assign %[[LOADED_SUM]] to %[[DECL_X]]#0 : i32, !fir.ref<i32> + ! CHECK: } + ! CHECK: omp.yield + end do + !$omp end taskloop +end subroutine omp_taskloop_lastprivate diff --git a/flang/test/Lower/OpenMP/tile01.f90 b/flang/test/Lower/OpenMP/tile01.f90 index 7603eee..fc5a485b 100644 --- a/flang/test/Lower/OpenMP/tile01.f90 +++ b/flang/test/Lower/OpenMP/tile01.f90 @@ -20,11 +20,11 @@ end subroutine omp_tile01 ! CHECK: %[[VAL_0:.*]] = fir.dummy_scope : !fir.dscope ! CHECK: %[[VAL_1:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFomp_tile01Ei"} ! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "_QFomp_tile01Ei"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[ARG2]] dummy_scope %[[VAL_0]] {uniq_name = "_QFomp_tile01Einc"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) -! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %[[VAL_0]] {uniq_name = "_QFomp_tile01Elb"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[ARG2]] dummy_scope %[[VAL_0]] arg {{[0-9]+}} {uniq_name = "_QFomp_tile01Einc"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %[[VAL_0]] arg {{[0-9]+}} {uniq_name = "_QFomp_tile01Elb"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_5:.*]] = fir.alloca i32 {bindc_name = "res", uniq_name = "_QFomp_tile01Eres"} ! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_5]] {uniq_name = "_QFomp_tile01Eres"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) -! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %[[VAL_0]] {uniq_name = "_QFomp_tile01Eub"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %[[VAL_0]] arg {{[0-9]+}} {uniq_name = "_QFomp_tile01Eub"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_8:.*]] = arith.constant 4 : i32 ! CHECK: %[[VAL_9:.*]] = fir.load %[[VAL_4]]#0 : !fir.ref<i32> ! CHECK: %[[VAL_10:.*]] = fir.load %[[VAL_7]]#0 : !fir.ref<i32> diff --git a/flang/test/Lower/OpenMP/tile02.f90 b/flang/test/Lower/OpenMP/tile02.f90 index 5df506d17..266c310 100644 --- a/flang/test/Lower/OpenMP/tile02.f90 +++ b/flang/test/Lower/OpenMP/tile02.f90 @@ -22,13 +22,13 @@ end subroutine omp_tile02 ! CHECK: %[[VAL_0:.*]] = fir.dummy_scope : !fir.dscope ! CHECK: %[[VAL_1:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFomp_tile02Ei"} ! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "_QFomp_tile02Ei"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[ARG2]] dummy_scope %[[VAL_0]] {uniq_name = "_QFomp_tile02Einc"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[ARG2]] dummy_scope %[[VAL_0]] arg {{[0-9]+}} {uniq_name = "_QFomp_tile02Einc"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_4:.*]] = fir.alloca i32 {bindc_name = "j", uniq_name = "_QFomp_tile02Ej"} ! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_4]] {uniq_name = "_QFomp_tile02Ej"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) -! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %[[VAL_0]] {uniq_name = "_QFomp_tile02Elb"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %[[VAL_0]] arg {{[0-9]+}} {uniq_name = "_QFomp_tile02Elb"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_7:.*]] = fir.alloca i32 {bindc_name = "res", uniq_name = "_QFomp_tile02Eres"} ! CHECK: %[[VAL_8:.*]]:2 = hlfir.declare %[[VAL_7]] {uniq_name = "_QFomp_tile02Eres"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) -! CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %[[VAL_0]] {uniq_name = "_QFomp_tile02Eub"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %[[VAL_0]] arg {{[0-9]+}} {uniq_name = "_QFomp_tile02Eub"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_10:.*]] = arith.constant 3 : i32 ! CHECK: %[[VAL_11:.*]] = arith.constant 7 : i32 ! CHECK: %[[VAL_12:.*]] = fir.load %[[VAL_6]]#0 : !fir.ref<i32> diff --git a/flang/test/Lower/OpenMP/unroll-heuristic01.f90 b/flang/test/Lower/OpenMP/unroll-heuristic01.f90 index 34020eb..3ec96a9 100644 --- a/flang/test/Lower/OpenMP/unroll-heuristic01.f90 +++ b/flang/test/Lower/OpenMP/unroll-heuristic01.f90 @@ -20,11 +20,11 @@ end subroutine omp_unroll_heuristic01 ! CHECK: %[[VAL_0:.*]] = fir.dummy_scope : !fir.dscope ! CHECK: %[[VAL_1:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFomp_unroll_heuristic01Ei"} ! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "_QFomp_unroll_heuristic01Ei"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[ARG2]] dummy_scope %[[VAL_0]] {uniq_name = "_QFomp_unroll_heuristic01Einc"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) -! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %[[VAL_0]] {uniq_name = "_QFomp_unroll_heuristic01Elb"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[ARG2]] dummy_scope %[[VAL_0]] arg {{[0-9]+}} {uniq_name = "_QFomp_unroll_heuristic01Einc"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %[[VAL_0]] arg {{[0-9]+}} {uniq_name = "_QFomp_unroll_heuristic01Elb"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_5:.*]] = fir.alloca i32 {bindc_name = "res", uniq_name = "_QFomp_unroll_heuristic01Eres"} ! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_5]] {uniq_name = "_QFomp_unroll_heuristic01Eres"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) -! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %[[VAL_0]] {uniq_name = "_QFomp_unroll_heuristic01Eub"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %[[VAL_0]] arg {{[0-9]+}} {uniq_name = "_QFomp_unroll_heuristic01Eub"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_8:.*]] = fir.load %[[VAL_4]]#0 : !fir.ref<i32> ! CHECK: %[[VAL_9:.*]] = fir.load %[[VAL_7]]#0 : !fir.ref<i32> ! CHECK: %[[VAL_10:.*]] = fir.load %[[VAL_3]]#0 : !fir.ref<i32> diff --git a/flang/test/Lower/OpenMP/unroll-heuristic02.f90 b/flang/test/Lower/OpenMP/unroll-heuristic02.f90 index fdb1366..20b5c50 100644 --- a/flang/test/Lower/OpenMP/unroll-heuristic02.f90 +++ b/flang/test/Lower/OpenMP/unroll-heuristic02.f90 @@ -27,14 +27,14 @@ end subroutine omp_unroll_heuristic_nested02 !CHECK: %[[VAL_0:.*]] = fir.dummy_scope : !fir.dscope !CHECK: %[[VAL_1:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFomp_unroll_heuristic_nested02Ei"} !CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "_QFomp_unroll_heuristic_nested02Ei"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) -!CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[ARG5]] dummy_scope %[[VAL_0]] {uniq_name = "_QFomp_unroll_heuristic_nested02Einner_inc"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) -!CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[ARG3]] dummy_scope %[[VAL_0]] {uniq_name = "_QFomp_unroll_heuristic_nested02Einner_lb"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) -!CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[ARG4]] dummy_scope %[[VAL_0]] {uniq_name = "_QFomp_unroll_heuristic_nested02Einner_ub"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[ARG5]] dummy_scope %[[VAL_0]] arg {{[0-9]+}} {uniq_name = "_QFomp_unroll_heuristic_nested02Einner_inc"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[ARG3]] dummy_scope %[[VAL_0]] arg {{[0-9]+}} {uniq_name = "_QFomp_unroll_heuristic_nested02Einner_lb"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[ARG4]] dummy_scope %[[VAL_0]] arg {{[0-9]+}} {uniq_name = "_QFomp_unroll_heuristic_nested02Einner_ub"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) !CHECK: %[[VAL_6:.*]] = fir.alloca i32 {bindc_name = "j", uniq_name = "_QFomp_unroll_heuristic_nested02Ej"} !CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_6]] {uniq_name = "_QFomp_unroll_heuristic_nested02Ej"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) -!CHECK: %[[VAL_8:.*]]:2 = hlfir.declare %[[ARG2]] dummy_scope %[[VAL_0]] {uniq_name = "_QFomp_unroll_heuristic_nested02Eouter_inc"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) -!CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %[[VAL_0]] {uniq_name = "_QFomp_unroll_heuristic_nested02Eouter_lb"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) -!CHECK: %[[VAL_10:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %[[VAL_0]] {uniq_name = "_QFomp_unroll_heuristic_nested02Eouter_ub"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: %[[VAL_8:.*]]:2 = hlfir.declare %[[ARG2]] dummy_scope %[[VAL_0]] arg {{[0-9]+}} {uniq_name = "_QFomp_unroll_heuristic_nested02Eouter_inc"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %[[VAL_0]] arg {{[0-9]+}} {uniq_name = "_QFomp_unroll_heuristic_nested02Eouter_lb"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: %[[VAL_10:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %[[VAL_0]] arg {{[0-9]+}} {uniq_name = "_QFomp_unroll_heuristic_nested02Eouter_ub"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) !CHECK: %[[VAL_11:.*]] = fir.alloca i32 {bindc_name = "res", uniq_name = "_QFomp_unroll_heuristic_nested02Eres"} !CHECK: %[[VAL_12:.*]]:2 = hlfir.declare %[[VAL_11]] {uniq_name = "_QFomp_unroll_heuristic_nested02Eres"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) !CHECK: %[[VAL_13:.*]] = fir.load %[[VAL_9]]#0 : !fir.ref<i32> diff --git a/flang/test/Lower/OpenMP/unroll-heuristic03.f90 b/flang/test/Lower/OpenMP/unroll-heuristic03.f90 index 308c149..c0aead2 100644 --- a/flang/test/Lower/OpenMP/unroll-heuristic03.f90 +++ b/flang/test/Lower/OpenMP/unroll-heuristic03.f90 @@ -23,11 +23,11 @@ end subroutine omp_unroll_heuristic03 ! CHECK: %[[VAL_0:.*]] = fir.dummy_scope : !fir.dscope ! CHECK: %[[VAL_1:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFomp_unroll_heuristic03Ei"} ! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "_QFomp_unroll_heuristic03Ei"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[ARG2]] dummy_scope %[[VAL_0]] {uniq_name = "_QFomp_unroll_heuristic03Einc"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) -! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %[[VAL_0]] {uniq_name = "_QFomp_unroll_heuristic03Elb"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[ARG2]] dummy_scope %[[VAL_0]] arg {{[0-9]+}} {uniq_name = "_QFomp_unroll_heuristic03Einc"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %[[VAL_0]] arg {{[0-9]+}} {uniq_name = "_QFomp_unroll_heuristic03Elb"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_5:.*]] = fir.alloca i32 {bindc_name = "res", uniq_name = "_QFomp_unroll_heuristic03Eres"} ! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_5]] {uniq_name = "_QFomp_unroll_heuristic03Eres"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) -! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %[[VAL_0]] {uniq_name = "_QFomp_unroll_heuristic03Eub"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %[[VAL_0]] arg {{[0-9]+}} {uniq_name = "_QFomp_unroll_heuristic03Eub"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: omp.parallel private(@_QFomp_unroll_heuristic03Ei_private_i32 %[[VAL_2]]#0 -> %[[VAL_8:.*]] : !fir.ref<i32>) { ! CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[VAL_8]] {uniq_name = "_QFomp_unroll_heuristic03Ei"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_10:.*]] = fir.load %[[VAL_4]]#0 : !fir.ref<i32> diff --git a/flang/test/Lower/OpenMP/workdistribute-saxpy-two-2d.f90 b/flang/test/Lower/OpenMP/workdistribute-saxpy-two-2d.f90 index 4aeb2e8..a9b3656 100644 --- a/flang/test/Lower/OpenMP/workdistribute-saxpy-two-2d.f90 +++ b/flang/test/Lower/OpenMP/workdistribute-saxpy-two-2d.f90 @@ -21,7 +21,7 @@ subroutine target_teams_workdistribute(a, x, y, rows, cols) ! CHECK: fir.do_loop y = a * x + y - + ! CHECK: omp.target ! CHECK: omp.teams ! CHECK: omp.parallel @@ -29,7 +29,7 @@ subroutine target_teams_workdistribute(a, x, y, rows, cols) ! CHECK: omp.wsloop ! CHECK: omp.loop_nest ! CHECK: fir.do_loop - + y = a * y + x !$omp end target teams workdistribute @@ -54,14 +54,14 @@ subroutine teams_workdistribute(a, x, y, rows, cols) ! CHECK: fir.do_loop y = a * x + y - + ! CHECK: omp.teams ! CHECK: omp.parallel ! CHECK: omp.distribute ! CHECK: omp.wsloop ! CHECK: omp.loop_nest ! CHECK: fir.do_loop - + y = a * y + x !$omp end teams workdistribute diff --git a/flang/test/Lower/OpenMP/workdistribute-scalar-assign.f90 b/flang/test/Lower/OpenMP/workdistribute-scalar-assign.f90 index 3062b35..e0f7733 100644 --- a/flang/test/Lower/OpenMP/workdistribute-scalar-assign.f90 +++ b/flang/test/Lower/OpenMP/workdistribute-scalar-assign.f90 @@ -11,7 +11,7 @@ subroutine target_teams_workdistribute_scalar_assign() ! CHECK: omp.distribute ! CHECK: omp.wsloop ! CHECK: omp.loop_nest - + !$omp target teams workdistribute aa = 20 !$omp end target teams workdistribute diff --git a/flang/test/Lower/OpenMP/wsloop-chunks.f90 b/flang/test/Lower/OpenMP/wsloop-chunks.f90 index f3f11d8..68e2a38 100644 --- a/flang/test/Lower/OpenMP/wsloop-chunks.f90 +++ b/flang/test/Lower/OpenMP/wsloop-chunks.f90 @@ -50,7 +50,7 @@ do i=1, 9 ! CHECK: omp.yield ! CHECK: } ! CHECK: } - + end do !$OMP END DO NOWAIT chunk = 6 diff --git a/flang/test/Lower/OpenMP/wsloop-linear.f90 b/flang/test/Lower/OpenMP/wsloop-linear.f90 new file mode 100644 index 0000000..0145be6a --- /dev/null +++ b/flang/test/Lower/OpenMP/wsloop-linear.f90 @@ -0,0 +1,60 @@ +! This test checks lowering of OpenMP DO Directive (Worksharing) +! with linear clause + +! RUN: %flang_fc1 -fopenmp -emit-hlfir %s -o - 2>&1 | FileCheck %s + +!CHECK: %[[X_alloca:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFsimple_linearEx"} +!CHECK: %[[X:.*]]:2 = hlfir.declare %[[X_alloca]] {uniq_name = "_QFsimple_linearEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: %[[const:.*]] = arith.constant 1 : i32 +subroutine simple_linear + implicit none + integer :: x, y, i + !CHECK: omp.wsloop linear(%[[X]]#0 = %[[const]] : !fir.ref<i32>) {{.*}} + !$omp do linear(x) + !CHECK: %[[LOAD:.*]] = fir.load %[[X]]#0 : !fir.ref<i32> + !CHECK: %[[const:.*]] = arith.constant 2 : i32 + !CHECK: %[[RESULT:.*]] = arith.addi %[[LOAD]], %[[const]] : i32 + do i = 1, 10 + y = x + 2 + end do + !$omp end do + !CHECK: } {linear_var_types = [i32]} +end subroutine + + +!CHECK: %[[X_alloca:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFlinear_stepEx"} +!CHECK: %[[X:.*]]:2 = hlfir.declare %[[X_alloca]] {uniq_name = "_QFlinear_stepEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +subroutine linear_step + implicit none + integer :: x, y, i + !CHECK: %[[const:.*]] = arith.constant 4 : i32 + !CHECK: omp.wsloop linear(%[[X]]#0 = %[[const]] : !fir.ref<i32>) {{.*}} + !$omp do linear(x:4) + !CHECK: %[[LOAD:.*]] = fir.load %[[X]]#0 : !fir.ref<i32> + !CHECK: %[[const:.*]] = arith.constant 2 : i32 + !CHECK: %[[RESULT:.*]] = arith.addi %[[LOAD]], %[[const]] : i32 + do i = 1, 10 + y = x + 2 + end do + !$omp end do + !CHECK: } {linear_var_types = [i32]} +end subroutine + +!CHECK: %[[A_alloca:.*]] = fir.alloca i32 {bindc_name = "a", uniq_name = "_QFlinear_exprEa"} +!CHECK: %[[A:.*]]:2 = hlfir.declare %[[A_alloca]] {uniq_name = "_QFlinear_exprEa"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: %[[X_alloca:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFlinear_exprEx"} +!CHECK: %[[X:.*]]:2 = hlfir.declare %[[X_alloca]] {uniq_name = "_QFlinear_exprEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +subroutine linear_expr + implicit none + integer :: x, y, i, a + !CHECK: %[[LOAD_A:.*]] = fir.load %[[A]]#0 : !fir.ref<i32> + !CHECK: %[[const:.*]] = arith.constant 4 : i32 + !CHECK: %[[LINEAR_EXPR:.*]] = arith.addi %[[LOAD_A]], %[[const]] : i32 + !CHECK: omp.wsloop linear(%[[X]]#0 = %[[LINEAR_EXPR]] : !fir.ref<i32>) {{.*}} + !$omp do linear(x:a+4) + do i = 1, 10 + y = x + 2 + end do + !$omp end do + !CHECK: } {linear_var_types = [i32]} +end subroutine diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-allocatable-array-minmax.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-allocatable-array-minmax.f90 index 2cd953d..ed81577 100644 --- a/flang/test/Lower/OpenMP/wsloop-reduction-allocatable-array-minmax.f90 +++ b/flang/test/Lower/OpenMP/wsloop-reduction-allocatable-array-minmax.f90 @@ -32,7 +32,7 @@ program reduce15 print *,"min: ", mins end program -! CHECK-LABEL: omp.declare_reduction @min_byref_box_heap_Uxi32 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> alloc { +! CHECK-LABEL: omp.declare_reduction @min_byref_box_heap_Uxi32 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> {{.*}} alloc { ! CHECK: %[[VAL_3:.*]] = fir.alloca !fir.box<!fir.heap<!fir.array<?xi32>>> ! CHECK: omp.yield(%[[VAL_3]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) ! CHECK-LABEL: } init { @@ -93,7 +93,7 @@ end program ! CHECK: omp.yield ! CHECK: } -! CHECK-LABEL: omp.declare_reduction @max_byref_box_heap_Uxi32 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> alloc { +! CHECK-LABEL: omp.declare_reduction @max_byref_box_heap_Uxi32 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> {{.*}} alloc { ! CHECK: %[[VAL_3:.*]] = fir.alloca !fir.box<!fir.heap<!fir.array<?xi32>>> ! CHECK: omp.yield(%[[VAL_3]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) ! CHECK-LABEL: } init { diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-allocatable.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-allocatable.f90 index 663851c..d8c0a36d 100644 --- a/flang/test/Lower/OpenMP/wsloop-reduction-allocatable.f90 +++ b/flang/test/Lower/OpenMP/wsloop-reduction-allocatable.f90 @@ -18,7 +18,7 @@ print *,r end program -! CHECK-LABEL: omp.declare_reduction @add_reduction_byref_box_heap_i32 : !fir.ref<!fir.box<!fir.heap<i32>>> alloc { +! CHECK-LABEL: omp.declare_reduction @add_reduction_byref_box_heap_i32 : !fir.ref<!fir.box<!fir.heap<i32>>> attributes {byref_element_type = i32} alloc { ! CHECK: %[[VAL_2:.*]] = fir.alloca !fir.box<!fir.heap<i32>> ! CHECK: omp.yield(%[[VAL_2]] : !fir.ref<!fir.box<!fir.heap<i32>>>) ! CHECK-LABEL: } init { diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-array-assumed-shape.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-array-assumed-shape.f90 index 209ee9a..7ce1be0 100644 --- a/flang/test/Lower/OpenMP/wsloop-reduction-array-assumed-shape.f90 +++ b/flang/test/Lower/OpenMP/wsloop-reduction-array-assumed-shape.f90 @@ -22,7 +22,7 @@ subroutine reduce(r) end subroutine end program -! CHECK-LABEL: omp.declare_reduction @add_reduction_byref_box_Uxf64 : !fir.ref<!fir.box<!fir.array<?xf64>>> alloc { +! CHECK-LABEL: omp.declare_reduction @add_reduction_byref_box_Uxf64 : !fir.ref<!fir.box<!fir.array<?xf64>>> {{.*}} alloc { ! CHECK: %[[VAL_8:.*]] = fir.alloca !fir.box<!fir.array<?xf64>> ! CHECK: omp.yield(%[[VAL_8]] : !fir.ref<!fir.box<!fir.array<?xf64>>>) ! CHECK-LABEL: } init { @@ -77,7 +77,7 @@ end program ! CHECK-SAME: %[[VAL_0:.*]]: !fir.box<!fir.array<?xf64>> {fir.bindc_name = "r"}) attributes {{.*}} { ! CHECK: %[[VAL_1:.*]] = fir.address_of(@_QFFreduceEi) : !fir.ref<i32> ! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "_QFFreduceEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {fortran_attrs = {{.*}}, uniq_name = "_QFFreduceEr"} : (!fir.box<!fir.array<?xf64>>, !fir.dscope) -> (!fir.box<!fir.array<?xf64>>, !fir.box<!fir.array<?xf64>>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = {{.*}}, uniq_name = "_QFFreduceEr"} : (!fir.box<!fir.array<?xf64>>, !fir.dscope) -> (!fir.box<!fir.array<?xf64>>, !fir.box<!fir.array<?xf64>>) ! CHECK: omp.parallel { ! CHECK: %[[VAL_4:.*]] = fir.alloca !fir.box<!fir.array<?xf64>> ! CHECK: fir.store %[[VAL_3]]#0 to %[[VAL_4]] : !fir.ref<!fir.box<!fir.array<?xf64>>> diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-array-lb.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-array-lb.f90 index 2233a74..ec448cf 100644 --- a/flang/test/Lower/OpenMP/wsloop-reduction-array-lb.f90 +++ b/flang/test/Lower/OpenMP/wsloop-reduction-array-lb.f90 @@ -11,7 +11,7 @@ program reduce !$omp end parallel do end program -! CHECK-LABEL: omp.declare_reduction @add_reduction_byref_box_2xi32 : !fir.ref<!fir.box<!fir.array<2xi32>>> alloc { +! CHECK-LABEL: omp.declare_reduction @add_reduction_byref_box_2xi32 : !fir.ref<!fir.box<!fir.array<2xi32>>> {{.*}} alloc { ! CHECK: } combiner { ! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref<!fir.box<!fir.array<2xi32>>>, %[[ARG1:.*]]: !fir.ref<!fir.box<!fir.array<2xi32>>>): ! CHECK: %[[ARR0:.*]] = fir.load %[[ARG0]] : !fir.ref<!fir.box<!fir.array<2xi32>>> diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-array-lb2.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-array-lb2.f90 index 211bde1..9da05a2 100644 --- a/flang/test/Lower/OpenMP/wsloop-reduction-array-lb2.f90 +++ b/flang/test/Lower/OpenMP/wsloop-reduction-array-lb2.f90 @@ -19,7 +19,7 @@ contains end program -! CHECK-LABEL: omp.declare_reduction @add_reduction_byref_box_Uxi32 : !fir.ref<!fir.box<!fir.array<?xi32>>> alloc { +! CHECK-LABEL: omp.declare_reduction @add_reduction_byref_box_Uxi32 : !fir.ref<!fir.box<!fir.array<?xi32>>> {{.*}} alloc { ! CHECK: } combiner { ! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref<!fir.box<!fir.array<?xi32>>>, %[[ARG1:.*]]: !fir.ref<!fir.box<!fir.array<?xi32>>>): ! CHECK: %[[ARR0:.*]] = fir.load %[[ARG0]] : !fir.ref<!fir.box<!fir.array<?xi32>>> diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-array.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-array.f90 index afaeba2..14b657c 100644 --- a/flang/test/Lower/OpenMP/wsloop-reduction-array.f90 +++ b/flang/test/Lower/OpenMP/wsloop-reduction-array.f90 @@ -14,7 +14,7 @@ enddo print *,r end program -! CHECK-LABEL: omp.declare_reduction @add_reduction_byref_box_2xi32 : !fir.ref<!fir.box<!fir.array<2xi32>>> alloc { +! CHECK-LABEL: omp.declare_reduction @add_reduction_byref_box_2xi32 : !fir.ref<!fir.box<!fir.array<2xi32>>> attributes {byref_element_type = !fir.array<2xi32>} alloc { ! CHECK: %[[VAL_8:.*]] = fir.alloca !fir.box<!fir.array<2xi32>> ! CHECK: omp.yield(%[[VAL_8]] : !fir.ref<!fir.box<!fir.array<2xi32>>>) ! CHECK-LABEL: } init { diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-array2.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-array2.f90 index 25b2e97..d0a0c38 100644 --- a/flang/test/Lower/OpenMP/wsloop-reduction-array2.f90 +++ b/flang/test/Lower/OpenMP/wsloop-reduction-array2.f90 @@ -14,7 +14,7 @@ enddo print *,r end program -! CHECK-LABEL: omp.declare_reduction @add_reduction_byref_box_2xi32 : !fir.ref<!fir.box<!fir.array<2xi32>>> alloc { +! CHECK-LABEL: omp.declare_reduction @add_reduction_byref_box_2xi32 : !fir.ref<!fir.box<!fir.array<2xi32>>> {{.*}} alloc { ! CHECK: %[[VAL_8:.*]] = fir.alloca !fir.box<!fir.array<2xi32>> ! CHECK: omp.yield(%[[VAL_8]] : !fir.ref<!fir.box<!fir.array<2xi32>>>) ! CHECK-LABEL: } init { diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-iand-byref.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-iand-byref.f90 index 501dd04..634f07e 100644 --- a/flang/test/Lower/OpenMP/wsloop-reduction-iand-byref.f90 +++ b/flang/test/Lower/OpenMP/wsloop-reduction-iand-byref.f90 @@ -28,7 +28,7 @@ ! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "_QFreduction_iandEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_3:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFreduction_iandEx"} ! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_3]] {uniq_name = "_QFreduction_iandEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) -! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFreduction_iandEy"} : (!fir.box<!fir.array<?xi32>>, !fir.dscope) -> (!fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>>) +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFreduction_iandEy"} : (!fir.box<!fir.array<?xi32>>, !fir.dscope) -> (!fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>>) ! CHECK: %[[VAL_6:.*]] = arith.constant 0 : i32 ! CHECK: hlfir.assign %[[VAL_6]] to %[[VAL_4]]#0 : i32, !fir.ref<i32> ! CHECK: omp.parallel { diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-iand.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-iand.f90 index 8243c73..b9b911c 100644 --- a/flang/test/Lower/OpenMP/wsloop-reduction-iand.f90 +++ b/flang/test/Lower/OpenMP/wsloop-reduction-iand.f90 @@ -20,7 +20,7 @@ ! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "_QFreduction_iandEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_3:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFreduction_iandEx"} ! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_3]] {uniq_name = "_QFreduction_iandEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) -! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFreduction_iandEy"} : (!fir.box<!fir.array<?xi32>>, !fir.dscope) -> (!fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>>) +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFreduction_iandEy"} : (!fir.box<!fir.array<?xi32>>, !fir.dscope) -> (!fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>>) ! CHECK: %[[VAL_6:.*]] = arith.constant 0 : i32 ! CHECK: hlfir.assign %[[VAL_6]] to %[[VAL_4]]#0 : i32, !fir.ref<i32> ! CHECK: omp.parallel { diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-ieor-byref.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-ieor-byref.f90 index 84814b8..795e417 100644 --- a/flang/test/Lower/OpenMP/wsloop-reduction-ieor-byref.f90 +++ b/flang/test/Lower/OpenMP/wsloop-reduction-ieor-byref.f90 @@ -24,7 +24,7 @@ !CHECK-SAME: %[[Y_BOX:.*]]: !fir.box<!fir.array<?xi32>> !CHECK: %[[X_REF:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFreduction_ieorEx"} !CHECK: %[[X_DECL:.*]]:2 = hlfir.declare %[[X_REF]] {uniq_name = "_QFreduction_ieorEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) -!CHECK: %[[Y_DECL:.*]]:2 = hlfir.declare %[[Y_BOX]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFreduction_ieorEy"} : (!fir.box<!fir.array<?xi32>>, !fir.dscope) -> (!fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>>) +!CHECK: %[[Y_DECL:.*]]:2 = hlfir.declare %[[Y_BOX]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFreduction_ieorEy"} : (!fir.box<!fir.array<?xi32>>, !fir.dscope) -> (!fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>>) !CHECK: omp.parallel diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-ieor.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-ieor.f90 index c474f6d..5482887 100644 --- a/flang/test/Lower/OpenMP/wsloop-reduction-ieor.f90 +++ b/flang/test/Lower/OpenMP/wsloop-reduction-ieor.f90 @@ -13,7 +13,7 @@ !CHECK-SAME: %[[Y_BOX:.*]]: !fir.box<!fir.array<?xi32>> !CHECK: %[[X_REF:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFreduction_ieorEx"} !CHECK: %[[X_DECL:.*]]:2 = hlfir.declare %[[X_REF]] {uniq_name = "_QFreduction_ieorEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) -!CHECK: %[[Y_DECL:.*]]:2 = hlfir.declare %[[Y_BOX]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFreduction_ieorEy"} : (!fir.box<!fir.array<?xi32>>, !fir.dscope) -> (!fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>>) +!CHECK: %[[Y_DECL:.*]]:2 = hlfir.declare %[[Y_BOX]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFreduction_ieorEy"} : (!fir.box<!fir.array<?xi32>>, !fir.dscope) -> (!fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>>) !CHECK: omp.parallel diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-ior-byref.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-ior-byref.f90 index 550945d..83aa396 100644 --- a/flang/test/Lower/OpenMP/wsloop-reduction-ior-byref.f90 +++ b/flang/test/Lower/OpenMP/wsloop-reduction-ior-byref.f90 @@ -26,7 +26,7 @@ ! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "_QFreduction_iorEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_3:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFreduction_iorEx"} ! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_3]] {uniq_name = "_QFreduction_iorEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) -! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFreduction_iorEy"} : (!fir.box<!fir.array<?xi32>>, !fir.dscope) -> (!fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>>) +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFreduction_iorEy"} : (!fir.box<!fir.array<?xi32>>, !fir.dscope) -> (!fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>>) ! CHECK: %[[VAL_6:.*]] = arith.constant 0 : i32 ! CHECK: hlfir.assign %[[VAL_6]] to %[[VAL_4]]#0 : i32, !fir.ref<i32> ! CHECK: omp.parallel diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-ior.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-ior.f90 index 8de6eb7..14a5997 100644 --- a/flang/test/Lower/OpenMP/wsloop-reduction-ior.f90 +++ b/flang/test/Lower/OpenMP/wsloop-reduction-ior.f90 @@ -20,7 +20,7 @@ ! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "_QFreduction_iorEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_3:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFreduction_iorEx"} ! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_3]] {uniq_name = "_QFreduction_iorEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) -! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFreduction_iorEy"} : (!fir.box<!fir.array<?xi32>>, !fir.dscope) -> (!fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>>) +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFreduction_iorEy"} : (!fir.box<!fir.array<?xi32>>, !fir.dscope) -> (!fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>>) ! CHECK: %[[VAL_6:.*]] = arith.constant 0 : i32 ! CHECK: hlfir.assign %[[VAL_6]] to %[[VAL_4]]#0 : i32, !fir.ref<i32> ! CHECK: omp.parallel diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-logical-and-byref.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-logical-and-byref.f90 index cf5c1b1..fc73fb5 100644 --- a/flang/test/Lower/OpenMP/wsloop-reduction-logical-and-byref.f90 +++ b/flang/test/Lower/OpenMP/wsloop-reduction-logical-and-byref.f90 @@ -34,7 +34,7 @@ ! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_3]] {uniq_name = "_QFsimple_reductionEx"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) ! CHECK: %[[VAL_5:.*]] = arith.constant 100 : index ! CHECK: %[[VAL_6:.*]] = fir.shape %[[VAL_5]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_6]]) dummy_scope %{{[0-9]+}} {uniq_name = "_QFsimple_reductionEy"} : (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.ref<!fir.array<100x!fir.logical<4>>>) +! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_6]]) dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFsimple_reductionEy"} : (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.ref<!fir.array<100x!fir.logical<4>>>) ! CHECK: %[[VAL_8:.*]] = arith.constant true ! CHECK: %[[VAL_9:.*]] = fir.convert %[[VAL_8]] : (i1) -> !fir.logical<4> ! CHECK: hlfir.assign %[[VAL_9]] to %[[VAL_4]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>> @@ -82,7 +82,7 @@ end subroutine simple_reduction ! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_3]] {uniq_name = "_QFsimple_reduction_switch_orderEx"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) ! CHECK: %[[VAL_5:.*]] = arith.constant 100 : index ! CHECK: %[[VAL_6:.*]] = fir.shape %[[VAL_5]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_6]]) dummy_scope %{{[0-9]+}} {uniq_name = "_QFsimple_reduction_switch_orderEy"} : (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.ref<!fir.array<100x!fir.logical<4>>>) +! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_6]]) dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFsimple_reduction_switch_orderEy"} : (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.ref<!fir.array<100x!fir.logical<4>>>) ! CHECK: %[[VAL_8:.*]] = arith.constant true ! CHECK: %[[VAL_9:.*]] = fir.convert %[[VAL_8]] : (i1) -> !fir.logical<4> ! CHECK: hlfir.assign %[[VAL_9]] to %[[VAL_4]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>> @@ -127,7 +127,7 @@ end subroutine ! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "_QFmultiple_reductionsEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_3:.*]] = arith.constant 100 : index ! CHECK: %[[VAL_4:.*]] = fir.shape %[[VAL_3]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_4]]) dummy_scope %{{[0-9]+}} {uniq_name = "_QFmultiple_reductionsEw"} : (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.ref<!fir.array<100x!fir.logical<4>>>) +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_4]]) dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFmultiple_reductionsEw"} : (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.ref<!fir.array<100x!fir.logical<4>>>) ! CHECK: %[[VAL_6:.*]] = fir.alloca !fir.logical<4> {bindc_name = "x", uniq_name = "_QFmultiple_reductionsEx"} ! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_6]] {uniq_name = "_QFmultiple_reductionsEx"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) ! CHECK: %[[VAL_8:.*]] = fir.alloca !fir.logical<4> {bindc_name = "y", uniq_name = "_QFmultiple_reductionsEy"} diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-logical-and.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-logical-and.f90 index eff97aa..2cf4593 100644 --- a/flang/test/Lower/OpenMP/wsloop-reduction-logical-and.f90 +++ b/flang/test/Lower/OpenMP/wsloop-reduction-logical-and.f90 @@ -26,7 +26,7 @@ ! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_3]] {uniq_name = "_QFsimple_reductionEx"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) ! CHECK: %[[VAL_5:.*]] = arith.constant 100 : index ! CHECK: %[[VAL_6:.*]] = fir.shape %[[VAL_5]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_6]]) dummy_scope %{{[0-9]+}} {uniq_name = "_QFsimple_reductionEy"} : (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.ref<!fir.array<100x!fir.logical<4>>>) +! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_6]]) dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFsimple_reductionEy"} : (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.ref<!fir.array<100x!fir.logical<4>>>) ! CHECK: %[[VAL_8:.*]] = arith.constant true ! CHECK: %[[VAL_9:.*]] = fir.convert %[[VAL_8]] : (i1) -> !fir.logical<4> ! CHECK: hlfir.assign %[[VAL_9]] to %[[VAL_4]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>> @@ -74,7 +74,7 @@ end subroutine simple_reduction ! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_3]] {uniq_name = "_QFsimple_reduction_switch_orderEx"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) ! CHECK: %[[VAL_5:.*]] = arith.constant 100 : index ! CHECK: %[[VAL_6:.*]] = fir.shape %[[VAL_5]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_6]]) dummy_scope %{{[0-9]+}} {uniq_name = "_QFsimple_reduction_switch_orderEy"} : (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.ref<!fir.array<100x!fir.logical<4>>>) +! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_6]]) dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFsimple_reduction_switch_orderEy"} : (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.ref<!fir.array<100x!fir.logical<4>>>) ! CHECK: %[[VAL_8:.*]] = arith.constant true ! CHECK: %[[VAL_9:.*]] = fir.convert %[[VAL_8]] : (i1) -> !fir.logical<4> ! CHECK: hlfir.assign %[[VAL_9]] to %[[VAL_4]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>> @@ -119,7 +119,7 @@ end subroutine ! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "_QFmultiple_reductionsEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_3:.*]] = arith.constant 100 : index ! CHECK: %[[VAL_4:.*]] = fir.shape %[[VAL_3]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_4]]) dummy_scope %{{[0-9]+}} {uniq_name = "_QFmultiple_reductionsEw"} : (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.ref<!fir.array<100x!fir.logical<4>>>) +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_4]]) dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFmultiple_reductionsEw"} : (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.ref<!fir.array<100x!fir.logical<4>>>) ! CHECK: %[[VAL_6:.*]] = fir.alloca !fir.logical<4> {bindc_name = "x", uniq_name = "_QFmultiple_reductionsEx"} ! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_6]] {uniq_name = "_QFmultiple_reductionsEx"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) ! CHECK: %[[VAL_8:.*]] = fir.alloca !fir.logical<4> {bindc_name = "y", uniq_name = "_QFmultiple_reductionsEy"} diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-logical-eqv-byref.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-logical-eqv-byref.f90 index bbe4bf0..d2f27ba 100644 --- a/flang/test/Lower/OpenMP/wsloop-reduction-logical-eqv-byref.f90 +++ b/flang/test/Lower/OpenMP/wsloop-reduction-logical-eqv-byref.f90 @@ -34,7 +34,7 @@ ! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_3]] {uniq_name = "_QFsimple_reductionEx"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) ! CHECK: %[[VAL_5:.*]] = arith.constant 100 : index ! CHECK: %[[VAL_6:.*]] = fir.shape %[[VAL_5]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_6]]) dummy_scope %{{[0-9]+}} {uniq_name = "_QFsimple_reductionEy"} : (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.ref<!fir.array<100x!fir.logical<4>>>) +! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_6]]) dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFsimple_reductionEy"} : (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.ref<!fir.array<100x!fir.logical<4>>>) ! CHECK: %[[VAL_8:.*]] = arith.constant true ! CHECK: %[[VAL_9:.*]] = fir.convert %[[VAL_8]] : (i1) -> !fir.logical<4> ! CHECK: hlfir.assign %[[VAL_9]] to %[[VAL_4]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>> @@ -81,7 +81,7 @@ end subroutine ! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_3]] {uniq_name = "_QFsimple_reduction_switch_orderEx"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) ! CHECK: %[[VAL_5:.*]] = arith.constant 100 : index ! CHECK: %[[VAL_6:.*]] = fir.shape %[[VAL_5]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_6]]) dummy_scope %{{[0-9]+}} {uniq_name = "_QFsimple_reduction_switch_orderEy"} : (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.ref<!fir.array<100x!fir.logical<4>>>) +! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_6]]) dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFsimple_reduction_switch_orderEy"} : (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.ref<!fir.array<100x!fir.logical<4>>>) ! CHECK: %[[VAL_8:.*]] = arith.constant true ! CHECK: %[[VAL_9:.*]] = fir.convert %[[VAL_8]] : (i1) -> !fir.logical<4> ! CHECK: hlfir.assign %[[VAL_9]] to %[[VAL_4]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>> @@ -126,7 +126,7 @@ end subroutine ! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "_QFmultiple_reductionsEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_3:.*]] = arith.constant 100 : index ! CHECK: %[[VAL_4:.*]] = fir.shape %[[VAL_3]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_4]]) dummy_scope %{{[0-9]+}} {uniq_name = "_QFmultiple_reductionsEw"} : (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.ref<!fir.array<100x!fir.logical<4>>>) +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_4]]) dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFmultiple_reductionsEw"} : (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.ref<!fir.array<100x!fir.logical<4>>>) ! CHECK: %[[VAL_6:.*]] = fir.alloca !fir.logical<4> {bindc_name = "x", uniq_name = "_QFmultiple_reductionsEx"} ! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_6]] {uniq_name = "_QFmultiple_reductionsEx"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) ! CHECK: %[[VAL_8:.*]] = fir.alloca !fir.logical<4> {bindc_name = "y", uniq_name = "_QFmultiple_reductionsEy"} diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-logical-eqv.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-logical-eqv.f90 index 304c7ee..7b9b6b8 100644 --- a/flang/test/Lower/OpenMP/wsloop-reduction-logical-eqv.f90 +++ b/flang/test/Lower/OpenMP/wsloop-reduction-logical-eqv.f90 @@ -26,7 +26,7 @@ ! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_3]] {uniq_name = "_QFsimple_reductionEx"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) ! CHECK: %[[VAL_5:.*]] = arith.constant 100 : index ! CHECK: %[[VAL_6:.*]] = fir.shape %[[VAL_5]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_6]]) dummy_scope %{{[0-9]+}} {uniq_name = "_QFsimple_reductionEy"} : (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.ref<!fir.array<100x!fir.logical<4>>>) +! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_6]]) dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFsimple_reductionEy"} : (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.ref<!fir.array<100x!fir.logical<4>>>) ! CHECK: %[[VAL_8:.*]] = arith.constant true ! CHECK: %[[VAL_9:.*]] = fir.convert %[[VAL_8]] : (i1) -> !fir.logical<4> ! CHECK: hlfir.assign %[[VAL_9]] to %[[VAL_4]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>> @@ -73,7 +73,7 @@ end subroutine ! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_3]] {uniq_name = "_QFsimple_reduction_switch_orderEx"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) ! CHECK: %[[VAL_5:.*]] = arith.constant 100 : index ! CHECK: %[[VAL_6:.*]] = fir.shape %[[VAL_5]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_6]]) dummy_scope %{{[0-9]+}} {uniq_name = "_QFsimple_reduction_switch_orderEy"} : (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.ref<!fir.array<100x!fir.logical<4>>>) +! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_6]]) dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFsimple_reduction_switch_orderEy"} : (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.ref<!fir.array<100x!fir.logical<4>>>) ! CHECK: %[[VAL_8:.*]] = arith.constant true ! CHECK: %[[VAL_9:.*]] = fir.convert %[[VAL_8]] : (i1) -> !fir.logical<4> ! CHECK: hlfir.assign %[[VAL_9]] to %[[VAL_4]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>> @@ -118,7 +118,7 @@ end subroutine ! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "_QFmultiple_reductionsEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_3:.*]] = arith.constant 100 : index ! CHECK: %[[VAL_4:.*]] = fir.shape %[[VAL_3]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_4]]) dummy_scope %{{[0-9]+}} {uniq_name = "_QFmultiple_reductionsEw"} : (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.ref<!fir.array<100x!fir.logical<4>>>) +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_4]]) dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFmultiple_reductionsEw"} : (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.ref<!fir.array<100x!fir.logical<4>>>) ! CHECK: %[[VAL_6:.*]] = fir.alloca !fir.logical<4> {bindc_name = "x", uniq_name = "_QFmultiple_reductionsEx"} ! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_6]] {uniq_name = "_QFmultiple_reductionsEx"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) ! CHECK: %[[VAL_8:.*]] = fir.alloca !fir.logical<4> {bindc_name = "y", uniq_name = "_QFmultiple_reductionsEy"} diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-logical-neqv-byref.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-logical-neqv-byref.f90 index 8c86995..94a24bd 100644 --- a/flang/test/Lower/OpenMP/wsloop-reduction-logical-neqv-byref.f90 +++ b/flang/test/Lower/OpenMP/wsloop-reduction-logical-neqv-byref.f90 @@ -34,7 +34,7 @@ ! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_3]] {uniq_name = "_QFsimple_reductionEx"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) ! CHECK: %[[VAL_5:.*]] = arith.constant 100 : index ! CHECK: %[[VAL_6:.*]] = fir.shape %[[VAL_5]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_6]]) dummy_scope %{{[0-9]+}} {uniq_name = "_QFsimple_reductionEy"} : (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.ref<!fir.array<100x!fir.logical<4>>>) +! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_6]]) dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFsimple_reductionEy"} : (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.ref<!fir.array<100x!fir.logical<4>>>) ! CHECK: %[[VAL_8:.*]] = arith.constant true ! CHECK: %[[VAL_9:.*]] = fir.convert %[[VAL_8]] : (i1) -> !fir.logical<4> ! CHECK: hlfir.assign %[[VAL_9]] to %[[VAL_4]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>> @@ -82,7 +82,7 @@ end subroutine ! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_3]] {uniq_name = "_QFsimple_reduction_switch_orderEx"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) ! CHECK: %[[VAL_5:.*]] = arith.constant 100 : index ! CHECK: %[[VAL_6:.*]] = fir.shape %[[VAL_5]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_6]]) dummy_scope %{{[0-9]+}} {uniq_name = "_QFsimple_reduction_switch_orderEy"} : (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.ref<!fir.array<100x!fir.logical<4>>>) +! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_6]]) dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFsimple_reduction_switch_orderEy"} : (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.ref<!fir.array<100x!fir.logical<4>>>) ! CHECK: %[[VAL_8:.*]] = arith.constant true ! CHECK: %[[VAL_9:.*]] = fir.convert %[[VAL_8]] : (i1) -> !fir.logical<4> ! CHECK: hlfir.assign %[[VAL_9]] to %[[VAL_4]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>> @@ -129,7 +129,7 @@ end subroutine ! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "_QFmultiple_reductionsEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_3:.*]] = arith.constant 100 : index ! CHECK: %[[VAL_4:.*]] = fir.shape %[[VAL_3]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_4]]) dummy_scope %{{[0-9]+}} {uniq_name = "_QFmultiple_reductionsEw"} : (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.ref<!fir.array<100x!fir.logical<4>>>) +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_4]]) dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFmultiple_reductionsEw"} : (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.ref<!fir.array<100x!fir.logical<4>>>) ! CHECK: %[[VAL_6:.*]] = fir.alloca !fir.logical<4> {bindc_name = "x", uniq_name = "_QFmultiple_reductionsEx"} ! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_6]] {uniq_name = "_QFmultiple_reductionsEx"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) ! CHECK: %[[VAL_8:.*]] = fir.alloca !fir.logical<4> {bindc_name = "y", uniq_name = "_QFmultiple_reductionsEy"} diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-logical-neqv.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-logical-neqv.f90 index e0901be..3f7f97f 100644 --- a/flang/test/Lower/OpenMP/wsloop-reduction-logical-neqv.f90 +++ b/flang/test/Lower/OpenMP/wsloop-reduction-logical-neqv.f90 @@ -26,7 +26,7 @@ ! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_3]] {uniq_name = "_QFsimple_reductionEx"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) ! CHECK: %[[VAL_5:.*]] = arith.constant 100 : index ! CHECK: %[[VAL_6:.*]] = fir.shape %[[VAL_5]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_6]]) dummy_scope %{{[0-9]+}} {uniq_name = "_QFsimple_reductionEy"} : (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.ref<!fir.array<100x!fir.logical<4>>>) +! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_6]]) dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFsimple_reductionEy"} : (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.ref<!fir.array<100x!fir.logical<4>>>) ! CHECK: %[[VAL_8:.*]] = arith.constant true ! CHECK: %[[VAL_9:.*]] = fir.convert %[[VAL_8]] : (i1) -> !fir.logical<4> ! CHECK: hlfir.assign %[[VAL_9]] to %[[VAL_4]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>> @@ -74,7 +74,7 @@ end subroutine ! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_3]] {uniq_name = "_QFsimple_reduction_switch_orderEx"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) ! CHECK: %[[VAL_5:.*]] = arith.constant 100 : index ! CHECK: %[[VAL_6:.*]] = fir.shape %[[VAL_5]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_6]]) dummy_scope %{{[0-9]+}} {uniq_name = "_QFsimple_reduction_switch_orderEy"} : (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.ref<!fir.array<100x!fir.logical<4>>>) +! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_6]]) dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFsimple_reduction_switch_orderEy"} : (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.ref<!fir.array<100x!fir.logical<4>>>) ! CHECK: %[[VAL_8:.*]] = arith.constant true ! CHECK: %[[VAL_9:.*]] = fir.convert %[[VAL_8]] : (i1) -> !fir.logical<4> ! CHECK: hlfir.assign %[[VAL_9]] to %[[VAL_4]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>> @@ -121,7 +121,7 @@ end subroutine ! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "_QFmultiple_reductionsEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_3:.*]] = arith.constant 100 : index ! CHECK: %[[VAL_4:.*]] = fir.shape %[[VAL_3]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_4]]) dummy_scope %{{[0-9]+}} {uniq_name = "_QFmultiple_reductionsEw"} : (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.ref<!fir.array<100x!fir.logical<4>>>) +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_4]]) dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFmultiple_reductionsEw"} : (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.ref<!fir.array<100x!fir.logical<4>>>) ! CHECK: %[[VAL_6:.*]] = fir.alloca !fir.logical<4> {bindc_name = "x", uniq_name = "_QFmultiple_reductionsEx"} ! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_6]] {uniq_name = "_QFmultiple_reductionsEx"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) ! CHECK: %[[VAL_8:.*]] = fir.alloca !fir.logical<4> {bindc_name = "y", uniq_name = "_QFmultiple_reductionsEy"} diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-logical-or-byref.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-logical-or-byref.f90 index bb09e25..4c1496b 100644 --- a/flang/test/Lower/OpenMP/wsloop-reduction-logical-or-byref.f90 +++ b/flang/test/Lower/OpenMP/wsloop-reduction-logical-or-byref.f90 @@ -33,7 +33,7 @@ ! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_3]] {uniq_name = "_QFsimple_reductionEx"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) ! CHECK: %[[VAL_5:.*]] = arith.constant 100 : index ! CHECK: %[[VAL_6:.*]] = fir.shape %[[VAL_5]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_6]]) dummy_scope %{{[0-9]+}} {uniq_name = "_QFsimple_reductionEy"} : (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.ref<!fir.array<100x!fir.logical<4>>>) +! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_6]]) dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFsimple_reductionEy"} : (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.ref<!fir.array<100x!fir.logical<4>>>) ! CHECK: %[[VAL_8:.*]] = arith.constant true ! CHECK: %[[VAL_9:.*]] = fir.convert %[[VAL_8]] : (i1) -> !fir.logical<4> ! CHECK: hlfir.assign %[[VAL_9]] to %[[VAL_4]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>> @@ -80,7 +80,7 @@ end subroutine ! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_3]] {uniq_name = "_QFsimple_reduction_switch_orderEx"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) ! CHECK: %[[VAL_5:.*]] = arith.constant 100 : index ! CHECK: %[[VAL_6:.*]] = fir.shape %[[VAL_5]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_6]]) dummy_scope %{{[0-9]+}} {uniq_name = "_QFsimple_reduction_switch_orderEy"} : (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.ref<!fir.array<100x!fir.logical<4>>>) +! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_6]]) dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFsimple_reduction_switch_orderEy"} : (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.ref<!fir.array<100x!fir.logical<4>>>) ! CHECK: %[[VAL_8:.*]] = arith.constant true ! CHECK: %[[VAL_9:.*]] = fir.convert %[[VAL_8]] : (i1) -> !fir.logical<4> ! CHECK: hlfir.assign %[[VAL_9]] to %[[VAL_4]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>> @@ -125,7 +125,7 @@ end subroutine ! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "_QFmultiple_reductionsEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_3:.*]] = arith.constant 100 : index ! CHECK: %[[VAL_4:.*]] = fir.shape %[[VAL_3]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_4]]) dummy_scope %{{[0-9]+}} {uniq_name = "_QFmultiple_reductionsEw"} : (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.ref<!fir.array<100x!fir.logical<4>>>) +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_4]]) dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFmultiple_reductionsEw"} : (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.ref<!fir.array<100x!fir.logical<4>>>) ! CHECK: %[[VAL_6:.*]] = fir.alloca !fir.logical<4> {bindc_name = "x", uniq_name = "_QFmultiple_reductionsEx"} ! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_6]] {uniq_name = "_QFmultiple_reductionsEx"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) ! CHECK: %[[VAL_8:.*]] = fir.alloca !fir.logical<4> {bindc_name = "y", uniq_name = "_QFmultiple_reductionsEy"} diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-logical-or.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-logical-or.f90 index 5c9bcbf..6d457f4 100644 --- a/flang/test/Lower/OpenMP/wsloop-reduction-logical-or.f90 +++ b/flang/test/Lower/OpenMP/wsloop-reduction-logical-or.f90 @@ -26,7 +26,7 @@ ! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_3]] {uniq_name = "_QFsimple_reductionEx"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) ! CHECK: %[[VAL_5:.*]] = arith.constant 100 : index ! CHECK: %[[VAL_6:.*]] = fir.shape %[[VAL_5]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_6]]) dummy_scope %{{[0-9]+}} {uniq_name = "_QFsimple_reductionEy"} : (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.ref<!fir.array<100x!fir.logical<4>>>) +! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_6]]) dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFsimple_reductionEy"} : (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.ref<!fir.array<100x!fir.logical<4>>>) ! CHECK: %[[VAL_8:.*]] = arith.constant true ! CHECK: %[[VAL_9:.*]] = fir.convert %[[VAL_8]] : (i1) -> !fir.logical<4> ! CHECK: hlfir.assign %[[VAL_9]] to %[[VAL_4]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>> @@ -73,7 +73,7 @@ end subroutine ! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_3]] {uniq_name = "_QFsimple_reduction_switch_orderEx"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) ! CHECK: %[[VAL_5:.*]] = arith.constant 100 : index ! CHECK: %[[VAL_6:.*]] = fir.shape %[[VAL_5]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_6]]) dummy_scope %{{[0-9]+}} {uniq_name = "_QFsimple_reduction_switch_orderEy"} : (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.ref<!fir.array<100x!fir.logical<4>>>) +! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_6]]) dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFsimple_reduction_switch_orderEy"} : (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.ref<!fir.array<100x!fir.logical<4>>>) ! CHECK: %[[VAL_8:.*]] = arith.constant true ! CHECK: %[[VAL_9:.*]] = fir.convert %[[VAL_8]] : (i1) -> !fir.logical<4> ! CHECK: hlfir.assign %[[VAL_9]] to %[[VAL_4]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>> @@ -118,7 +118,7 @@ end subroutine ! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "_QFmultiple_reductionsEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_3:.*]] = arith.constant 100 : index ! CHECK: %[[VAL_4:.*]] = fir.shape %[[VAL_3]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_4]]) dummy_scope %{{[0-9]+}} {uniq_name = "_QFmultiple_reductionsEw"} : (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.ref<!fir.array<100x!fir.logical<4>>>) +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_4]]) dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFmultiple_reductionsEw"} : (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.ref<!fir.array<100x!fir.logical<4>>>) ! CHECK: %[[VAL_6:.*]] = fir.alloca !fir.logical<4> {bindc_name = "x", uniq_name = "_QFmultiple_reductionsEx"} ! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_6]] {uniq_name = "_QFmultiple_reductionsEx"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) ! CHECK: %[[VAL_8:.*]] = fir.alloca !fir.logical<4> {bindc_name = "y", uniq_name = "_QFmultiple_reductionsEy"} diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-max-byref.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-max-byref.f90 index 6921933..73a8885 100644 --- a/flang/test/Lower/OpenMP/wsloop-reduction-max-byref.f90 +++ b/flang/test/Lower/OpenMP/wsloop-reduction-max-byref.f90 @@ -41,7 +41,7 @@ ! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "_QFreduction_max_intEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_3:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFreduction_max_intEx"} ! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_3]] {uniq_name = "_QFreduction_max_intEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) -! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFreduction_max_intEy"} : (!fir.box<!fir.array<?xi32>>, !fir.dscope) -> (!fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>>) +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFreduction_max_intEy"} : (!fir.box<!fir.array<?xi32>>, !fir.dscope) -> (!fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>>) ! CHECK: %[[VAL_6:.*]] = arith.constant 0 : i32 ! CHECK: hlfir.assign %[[VAL_6]] to %[[VAL_4]]#0 : i32, !fir.ref<i32> ! CHECK: omp.parallel { @@ -70,7 +70,7 @@ ! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "_QFreduction_max_realEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_3:.*]] = fir.alloca f32 {bindc_name = "x", uniq_name = "_QFreduction_max_realEx"} ! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_3]] {uniq_name = "_QFreduction_max_realEx"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>) -! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFreduction_max_realEy"} : (!fir.box<!fir.array<?xf32>>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.box<!fir.array<?xf32>>) +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFreduction_max_realEy"} : (!fir.box<!fir.array<?xf32>>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.box<!fir.array<?xf32>>) ! CHECK: %[[VAL_6:.*]] = arith.constant 0.000000e+00 : f32 ! CHECK: hlfir.assign %[[VAL_6]] to %[[VAL_4]]#0 : f32, !fir.ref<f32> ! CHECK: omp.parallel { diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-max.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-max.f90 index 83582d2..cebd779 100644 --- a/flang/test/Lower/OpenMP/wsloop-reduction-max.f90 +++ b/flang/test/Lower/OpenMP/wsloop-reduction-max.f90 @@ -31,7 +31,7 @@ ! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "_QFreduction_max_intEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_3:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFreduction_max_intEx"} ! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_3]] {uniq_name = "_QFreduction_max_intEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) -! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFreduction_max_intEy"} : (!fir.box<!fir.array<?xi32>>, !fir.dscope) -> (!fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>>) +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFreduction_max_intEy"} : (!fir.box<!fir.array<?xi32>>, !fir.dscope) -> (!fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>>) ! CHECK: %[[VAL_6:.*]] = arith.constant 0 : i32 ! CHECK: hlfir.assign %[[VAL_6]] to %[[VAL_4]]#0 : i32, !fir.ref<i32> ! CHECK: omp.parallel { @@ -60,7 +60,7 @@ ! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "_QFreduction_max_realEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_3:.*]] = fir.alloca f32 {bindc_name = "x", uniq_name = "_QFreduction_max_realEx"} ! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_3]] {uniq_name = "_QFreduction_max_realEx"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>) -! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFreduction_max_realEy"} : (!fir.box<!fir.array<?xf32>>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.box<!fir.array<?xf32>>) +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFreduction_max_realEy"} : (!fir.box<!fir.array<?xf32>>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.box<!fir.array<?xf32>>) ! CHECK: %[[VAL_6:.*]] = arith.constant 0.000000e+00 : f32 ! CHECK: hlfir.assign %[[VAL_6]] to %[[VAL_4]]#0 : f32, !fir.ref<f32> ! CHECK: omp.parallel { diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-min-byref.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-min-byref.f90 index f691d57..1a6bc37 100644 --- a/flang/test/Lower/OpenMP/wsloop-reduction-min-byref.f90 +++ b/flang/test/Lower/OpenMP/wsloop-reduction-min-byref.f90 @@ -41,7 +41,7 @@ ! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "_QFreduction_min_intEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_3:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFreduction_min_intEx"} ! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_3]] {uniq_name = "_QFreduction_min_intEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) -! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFreduction_min_intEy"} : (!fir.box<!fir.array<?xi32>>, !fir.dscope) -> (!fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>>) +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFreduction_min_intEy"} : (!fir.box<!fir.array<?xi32>>, !fir.dscope) -> (!fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>>) ! CHECK: %[[VAL_6:.*]] = arith.constant 0 : i32 ! CHECK: hlfir.assign %[[VAL_6]] to %[[VAL_4]]#0 : i32, !fir.ref<i32> ! CHECK: omp.parallel { @@ -70,7 +70,7 @@ ! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "_QFreduction_min_realEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_3:.*]] = fir.alloca f32 {bindc_name = "x", uniq_name = "_QFreduction_min_realEx"} ! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_3]] {uniq_name = "_QFreduction_min_realEx"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>) -! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFreduction_min_realEy"} : (!fir.box<!fir.array<?xf32>>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.box<!fir.array<?xf32>>) +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFreduction_min_realEy"} : (!fir.box<!fir.array<?xf32>>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.box<!fir.array<?xf32>>) ! CHECK: %[[VAL_6:.*]] = arith.constant 0.000000e+00 : f32 ! CHECK: hlfir.assign %[[VAL_6]] to %[[VAL_4]]#0 : f32, !fir.ref<f32> ! CHECK: omp.parallel { diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-min.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-min.f90 index 3ee2ecc..b3a899d 100644 --- a/flang/test/Lower/OpenMP/wsloop-reduction-min.f90 +++ b/flang/test/Lower/OpenMP/wsloop-reduction-min.f90 @@ -31,7 +31,7 @@ ! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "_QFreduction_min_intEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_3:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFreduction_min_intEx"} ! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_3]] {uniq_name = "_QFreduction_min_intEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) -! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFreduction_min_intEy"} : (!fir.box<!fir.array<?xi32>>, !fir.dscope) -> (!fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>>) +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFreduction_min_intEy"} : (!fir.box<!fir.array<?xi32>>, !fir.dscope) -> (!fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>>) ! CHECK: %[[VAL_6:.*]] = arith.constant 0 : i32 ! CHECK: hlfir.assign %[[VAL_6]] to %[[VAL_4]]#0 : i32, !fir.ref<i32> ! CHECK: omp.parallel { @@ -60,7 +60,7 @@ ! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "_QFreduction_min_realEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_3:.*]] = fir.alloca f32 {bindc_name = "x", uniq_name = "_QFreduction_min_realEx"} ! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_3]] {uniq_name = "_QFreduction_min_realEx"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>) -! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFreduction_min_realEy"} : (!fir.box<!fir.array<?xf32>>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.box<!fir.array<?xf32>>) +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFreduction_min_realEy"} : (!fir.box<!fir.array<?xf32>>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.box<!fir.array<?xf32>>) ! CHECK: %[[VAL_6:.*]] = arith.constant 0.000000e+00 : f32 ! CHECK: hlfir.assign %[[VAL_6]] to %[[VAL_4]]#0 : f32, !fir.ref<f32> ! CHECK: omp.parallel { diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-multiple-clauses.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-multiple-clauses.f90 index edd2bcb..60a162d 100644 --- a/flang/test/Lower/OpenMP/wsloop-reduction-multiple-clauses.f90 +++ b/flang/test/Lower/OpenMP/wsloop-reduction-multiple-clauses.f90 @@ -24,7 +24,7 @@ program main endprogram -! CHECK-LABEL: omp.declare_reduction @add_reduction_byref_box_3x3xf64 : !fir.ref<!fir.box<!fir.array<3x3xf64>>> alloc { +! CHECK-LABEL: omp.declare_reduction @add_reduction_byref_box_3x3xf64 : !fir.ref<!fir.box<!fir.array<3x3xf64>>> {{.*}} alloc { ! CHECK: %[[VAL_3:.*]] = fir.alloca !fir.box<!fir.array<3x3xf64>> ! CHECK: omp.yield(%[[VAL_3]] : !fir.ref<!fir.box<!fir.array<3x3xf64>>>) ! CHECK-LABEL: } init { diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-pointer.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-pointer.f90 index 27b7263..f640f5c 100644 --- a/flang/test/Lower/OpenMP/wsloop-reduction-pointer.f90 +++ b/flang/test/Lower/OpenMP/wsloop-reduction-pointer.f90 @@ -18,7 +18,7 @@ program reduce_pointer deallocate(v) end program -! CHECK-LABEL: omp.declare_reduction @add_reduction_byref_box_ptr_i32 : !fir.ref<!fir.box<!fir.ptr<i32>>> alloc { +! CHECK-LABEL: omp.declare_reduction @add_reduction_byref_box_ptr_i32 : !fir.ref<!fir.box<!fir.ptr<i32>>> {{.*}} alloc { ! CHECK: %[[VAL_3:.*]] = fir.alloca !fir.box<!fir.ptr<i32>> ! CHECK: omp.yield(%[[VAL_3]] : !fir.ref<!fir.box<!fir.ptr<i32>>>) ! CHECK-LABEL: } init { diff --git a/flang/test/Lower/OpenMP/wsloop-simd.f90 b/flang/test/Lower/OpenMP/wsloop-simd.f90 index 03e35de..b18bc29 100644 --- a/flang/test/Lower/OpenMP/wsloop-simd.f90 +++ b/flang/test/Lower/OpenMP/wsloop-simd.f90 @@ -71,16 +71,13 @@ end subroutine do_simd_reduction subroutine do_simd_private() integer, allocatable :: tmp ! CHECK: omp.wsloop + ! CHECK-SAME: private(@[[PRIV_IVAR_SYM:.*]] %{{.*}} -> %[[PRIV_IVAR:.*]] : !fir.ref<i32>) ! CHECK-NEXT: omp.simd - ! CHECK-SAME: private(@[[PRIV_BOX_SYM:.*]] %{{.*}} -> %[[PRIV_BOX:.*]], @[[PRIV_IVAR_SYM:.*]] %{{.*}} -> %[[PRIV_IVAR:.*]] : !fir.ref<!fir.box<!fir.heap<i32>>>, !fir.ref<i32>) ! CHECK-NEXT: omp.loop_nest (%[[IVAR:.*]]) : i32 !$omp do simd private(tmp) do i=1, 10 - ! CHECK: %[[PRIV_BOX_DECL:.*]]:2 = hlfir.declare %[[PRIV_BOX]] ! CHECK: %[[PRIV_IVAR_DECL:.*]]:2 = hlfir.declare %[[PRIV_IVAR]] ! CHECK: hlfir.assign %[[IVAR]] to %[[PRIV_IVAR_DECL]]#0 - ! CHECK: %[[PRIV_BOX_LOAD:.*]] = fir.load %[[PRIV_BOX_DECL]] - ! CHECK: hlfir.assign %{{.*}} to %[[PRIV_BOX_DECL]]#0 ! CHECK: omp.yield tmp = tmp + 1 end do @@ -90,13 +87,11 @@ end subroutine do_simd_private subroutine do_simd_lastprivate_firstprivate() integer :: a ! CHECK: omp.wsloop - ! CHECK-SAME: private(@[[FIRSTPRIVATE_A_SYM:.*]] %{{.*}} -> %[[FIRSTPRIVATE_A:.*]] : !fir.ref<i32>) + ! CHECK-SAME: private(@[[FIRSTPRIVATE_A_SYM:.*]] %{{.*}} -> %[[FIRSTPRIVATE_A:.*]], @[[PRIVATE_I_SYM:.*]] %{{.*}} -> %[[PRIVATE_I:.*]] : !fir.ref<i32>, !fir.ref<i32>) ! CHECK-NEXT: omp.simd - ! CHECK-SAME: private(@[[PRIVATE_A_SYM:.*]] %{{.*}} -> %[[PRIVATE_A:.*]], @[[PRIVATE_I_SYM:.*]] %{{.*}} -> %[[PRIVATE_I:.*]] : !fir.ref<i32>, !fir.ref<i32>) !$omp do simd lastprivate(a) firstprivate(a) do i = 1, 10 ! CHECK: %[[FIRSTPRIVATE_A_DECL:.*]]:2 = hlfir.declare %[[FIRSTPRIVATE_A]] - ! CHECK: %[[PRIVATE_A_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_A]] ! CHECK: %[[PRIVATE_I_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_I]] a = a + 1 end do diff --git a/flang/test/Lower/PowerPC/ppc-vec-load-elem-order.f90 b/flang/test/Lower/PowerPC/ppc-vec-load-elem-order.f90 index 355fd6c..b17c3f1 100644 --- a/flang/test/Lower/PowerPC/ppc-vec-load-elem-order.f90 +++ b/flang/test/Lower/PowerPC/ppc-vec-load-elem-order.f90 @@ -394,7 +394,7 @@ subroutine vec_xl_testi8a(arg1, arg2, res) vector(integer(1)) :: res res = vec_xl(arg1, arg2) - + ! LLVMIR: %[[arg1:.*]] = load i8, ptr %0, align 1 ! LLVMIR: %[[addr:.*]] = getelementptr i8, ptr %1, i8 %[[arg1]] ! LLVMIR: %[[ld:.*]] = load <16 x i8>, ptr %[[addr]], align 1 @@ -481,7 +481,7 @@ subroutine vec_xl_be_testi8a(arg1, arg2, res) vector(integer(1)) :: res res = vec_xl_be(arg1, arg2) - + ! LLVMIR: %4 = load i8, ptr %0, align 1 ! LLVMIR: %5 = getelementptr i8, ptr %1, i8 %4 ! LLVMIR: %6 = load <16 x i8>, ptr %5, align 1 diff --git a/flang/test/Lower/PowerPC/ppc-vec-sel.f90 b/flang/test/Lower/PowerPC/ppc-vec-sel.f90 index c3de8ba..93641d1 100644 --- a/flang/test/Lower/PowerPC/ppc-vec-sel.f90 +++ b/flang/test/Lower/PowerPC/ppc-vec-sel.f90 @@ -136,7 +136,7 @@ subroutine vec_sel_testu8(arg1, arg2, arg3) vector(unsigned(8)) :: arg1, arg2, r vector(unsigned(8)) :: arg3 r = vec_sel(arg1, arg2, arg3) - + ! LLVMIR: %[[arg1:.*]] = load <2 x i64>, ptr %{{.*}}, align 16 ! LLVMIR: %[[arg2:.*]] = load <2 x i64>, ptr %{{.*}}, align 16 diff --git a/flang/test/Lower/PowerPC/ppc-vec-store-elem-order.f90 b/flang/test/Lower/PowerPC/ppc-vec-store-elem-order.f90 index caf6d54..947c8b1 100644 --- a/flang/test/Lower/PowerPC/ppc-vec-store-elem-order.f90 +++ b/flang/test/Lower/PowerPC/ppc-vec-store-elem-order.f90 @@ -14,7 +14,7 @@ subroutine vec_st_test(arg1, arg2, arg3) ! LLVMIR: %[[arg1:.*]] = load <8 x i16>, ptr %0, align 16 ! LLVMIR: %[[arg2:.*]] = load i32, ptr %1, align 4 ! LLVMIR: %[[addr:.*]] = getelementptr i8, ptr %2, i32 %[[arg2]] -! LLVMIR: %[[bc:.*]] = bitcast <8 x i16> %[[arg1]] to <4 x i32> +! LLVMIR: %[[bc:.*]] = bitcast <8 x i16> %[[arg1]] to <4 x i32> ! LLVMIR: %[[shf:.*]] = shufflevector <4 x i32> %[[bc]], <4 x i32> undef, <4 x i32> <i32 3, i32 2, i32 1, i32 0> ! LLVMIR: call void @llvm.ppc.altivec.stvx(<4 x i32> %[[shf]], ptr %[[addr]]) end subroutine vec_st_test @@ -28,7 +28,7 @@ subroutine vec_ste_test(arg1, arg2, arg3) integer(4) :: arg2 real(4) :: arg3 call vec_ste(arg1, arg2, arg3) - + ! LLVMIR: %[[arg1:.*]] = load <4 x float>, ptr %0, align 16 ! LLVMIR: %[[arg2:.*]] = load i32, ptr %1, align 4 ! LLVMIR: %[[addr]] = getelementptr i8, ptr %2, i32 %[[arg2]] diff --git a/flang/test/Lower/PowerPC/ppc-vec-store.f90 b/flang/test/Lower/PowerPC/ppc-vec-store.f90 index c25cc8b..1c3ab96 100644 --- a/flang/test/Lower/PowerPC/ppc-vec-store.f90 +++ b/flang/test/Lower/PowerPC/ppc-vec-store.f90 @@ -300,7 +300,7 @@ subroutine vec_xst_test_vr4i2r4(arg1, arg2, arg3) real(4) :: arg3 call vec_xst(arg1, arg2, arg3) - + ! LLVMIR: %[[arg1:.*]] = load <4 x float>, ptr %{{.*}}, align 16 ! LLVMIR: %[[arg2:.*]] = load i16, ptr %{{.*}}, align 2 ! LLVMIR: %[[addr:.*]] = getelementptr i8, ptr %{{.*}}, i16 %[[arg2]] @@ -432,7 +432,7 @@ subroutine vec_xst_be_test_vi4i4vai4(arg1, arg2, arg3, i) ! LLVMIR: %[[iadd:.*]] = add nsw i64 %[[imul2]], 0 ! LLVMIR: %[[gep1:.*]] = getelementptr <4 x i32>, ptr %2, i64 %[[iadd]] ! LLVMIR: %[[arg1:.*]] = load <4 x i32>, ptr %0, align 16 -! LLVMIR: %[[arg2:.*]] = load i32, ptr %1, align 4 +! LLVMIR: %[[arg2:.*]] = load i32, ptr %1, align 4 ! LLVMIR: %[[gep2:.*]] = getelementptr i8, ptr %[[gep1]], i32 %[[arg2]] ! LLVMIR: %[[src:.*]] = shufflevector <4 x i32> %[[arg1]], <4 x i32> undef, <4 x i32> <i32 3, i32 2, i32 1, i32 0> ! LLVMIR: store <4 x i32> %[[src]], ptr %[[gep2]], align 16 @@ -449,7 +449,7 @@ subroutine vec_xstd2_test_vr4i2r4(arg1, arg2, arg3) real(4) :: arg3 call vec_xstd2(arg1, arg2, arg3) - + ! LLVMIR: %[[arg1:.*]] = load <4 x float>, ptr %{{.*}}, align 16 ! LLVMIR: %[[arg2:.*]] = load i16, ptr %{{.*}}, align 2 ! LLVMIR: %[[addr:.*]] = getelementptr i8, ptr %{{.*}}, i16 %[[arg2]] @@ -509,7 +509,7 @@ subroutine vec_xstd2_test_vi4i4vai4(arg1, arg2, arg3, i) ! LLVMIR: %[[iadd:.*]] = add nsw i64 %[[imul2]], 0 ! LLVMIR: %[[gep1:.*]] = getelementptr <4 x i32>, ptr %2, i64 %[[iadd]] ! LLVMIR: %[[arg1:.*]] = load <4 x i32>, ptr %0, align 16 -! LLVMIR: %[[arg2:.*]] = load i32, ptr %1, align 4 +! LLVMIR: %[[arg2:.*]] = load i32, ptr %1, align 4 ! LLVMIR: %[[gep2:.*]] = getelementptr i8, ptr %[[gep1]], i32 %[[arg2]] ! LLVMIR: %[[src:.*]] = bitcast <4 x i32> %[[arg1]] to <2 x i64> ! LLVMIR: store <2 x i64> %[[src]], ptr %[[gep2]], align 16 @@ -526,7 +526,7 @@ subroutine vec_xstw4_test_vr4i2r4(arg1, arg2, arg3) real(4) :: arg3 call vec_xstw4(arg1, arg2, arg3) - + ! LLVMIR: %[[arg1:.*]] = load <4 x float>, ptr %{{.*}}, align 16 ! LLVMIR: %[[arg2:.*]] = load i16, ptr %{{.*}}, align 2 ! LLVMIR: %[[addr:.*]] = getelementptr i8, ptr %{{.*}}, i16 %[[arg2]] @@ -584,7 +584,7 @@ subroutine vec_xstw4_test_vi4i4vai4(arg1, arg2, arg3, i) ! LLVMIR: %[[iadd:.*]] = add nsw i64 %[[imul2]], 0 ! LLVMIR: %[[gep1:.*]] = getelementptr <4 x i32>, ptr %2, i64 %[[iadd]] ! LLVMIR: %[[arg1:.*]] = load <4 x i32>, ptr %0, align 16 -! LLVMIR: %[[arg2:.*]] = load i32, ptr %1, align 4 +! LLVMIR: %[[arg2:.*]] = load i32, ptr %1, align 4 ! LLVMIR: %[[gep2:.*]] = getelementptr i8, ptr %[[gep1]], i32 %[[arg2]] ! LLVMIR: store <4 x i32> %[[arg1]], ptr %[[gep2]], align 16 end subroutine vec_xstw4_test_vi4i4vai4 diff --git a/flang/test/Lower/allocatable-assignment.f90 b/flang/test/Lower/allocatable-assignment.f90 index 71385aa..b6b2f7b 100644 --- a/flang/test/Lower/allocatable-assignment.f90 +++ b/flang/test/Lower/allocatable-assignment.f90 @@ -18,7 +18,7 @@ end subroutine ! CHECK-LABEL: func.func @_QMalloc_assignPtest_simple_scalar( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.heap<f32>>> {fir.bindc_name = "x"}) { ! CHECK: %[[VAL_1:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QMalloc_assignFtest_simple_scalarEx"} : (!fir.ref<!fir.box<!fir.heap<f32>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<f32>>>, !fir.ref<!fir.box<!fir.heap<f32>>>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QMalloc_assignFtest_simple_scalarEx"} : (!fir.ref<!fir.box<!fir.heap<f32>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<f32>>>, !fir.ref<!fir.box<!fir.heap<f32>>>) ! CHECK: %[[VAL_3:.*]] = arith.constant 4.200000e+01 : f32 ! CHECK: hlfir.assign %[[VAL_3]] to %[[VAL_2]]#0 realloc : f32, !fir.ref<!fir.box<!fir.heap<f32>>> @@ -47,7 +47,7 @@ end subroutine ! CHECK-LABEL: func.func @_QMalloc_assignPtest_deferred_char_scalar( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.heap<!fir.char<1,?>>>> {fir.bindc_name = "x"}) { ! CHECK: %[[VAL_1:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QMalloc_assignFtest_deferred_char_scalarEx"} : (!fir.ref<!fir.box<!fir.heap<!fir.char<1,?>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.char<1,?>>>>, !fir.ref<!fir.box<!fir.heap<!fir.char<1,?>>>>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QMalloc_assignFtest_deferred_char_scalarEx"} : (!fir.ref<!fir.box<!fir.heap<!fir.char<1,?>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.char<1,?>>>>, !fir.ref<!fir.box<!fir.heap<!fir.char<1,?>>>>) ! CHECK: %[[VAL_3:.*]] = fir.address_of(@_QQclX48656C6C6F20776F726C6421) : !fir.ref<!fir.char<1,12>> ! CHECK: %[[VAL_4:.*]] = arith.constant 12 : index ! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_3]] typeparams %[[VAL_4]] {fortran_attrs = #fir.var_attrs<parameter>, uniq_name = "_QQclX48656C6C6F20776F726C6421"} : (!fir.ref<!fir.char<1,12>>, index) -> (!fir.ref<!fir.char<1,12>>, !fir.ref<!fir.char<1,12>>) @@ -61,7 +61,7 @@ end subroutine ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.heap<!fir.char<1,10>>>> {fir.bindc_name = "x"}) { ! CHECK: %[[VAL_1:.*]] = fir.dummy_scope : !fir.dscope ! CHECK: %[[VAL_2:.*]] = arith.constant 10 : index -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] typeparams %[[VAL_2]] dummy_scope %[[VAL_1]] {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QMalloc_assignFtest_cst_char_scalarEx"} : (!fir.ref<!fir.box<!fir.heap<!fir.char<1,10>>>>, index, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.char<1,10>>>>, !fir.ref<!fir.box<!fir.heap<!fir.char<1,10>>>>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] typeparams %[[VAL_2]] dummy_scope %[[VAL_1]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QMalloc_assignFtest_cst_char_scalarEx"} : (!fir.ref<!fir.box<!fir.heap<!fir.char<1,10>>>>, index, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.char<1,10>>>>, !fir.ref<!fir.box<!fir.heap<!fir.char<1,10>>>>) ! CHECK: %[[VAL_4:.*]] = fir.address_of(@_QQclX48656C6C6F20776F726C6421) : !fir.ref<!fir.char<1,12>> ! CHECK: %[[VAL_5:.*]] = arith.constant 12 : index ! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_4]] typeparams %[[VAL_5]] {fortran_attrs = #fir.var_attrs<parameter>, uniq_name = "_QQclX48656C6C6F20776F726C6421"} : (!fir.ref<!fir.char<1,12>>, index) -> (!fir.ref<!fir.char<1,12>>, !fir.ref<!fir.char<1,12>>) @@ -76,12 +76,12 @@ end subroutine ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.heap<!fir.char<1,?>>>> {fir.bindc_name = "x"}, ! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref<i32> {fir.bindc_name = "n"}) { ! CHECK: %[[VAL_2:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %[[VAL_2]] {uniq_name = "_QMalloc_assignFtest_dyn_char_scalarEn"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %[[VAL_2]] arg {{[0-9]+}} {uniq_name = "_QMalloc_assignFtest_dyn_char_scalarEn"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_4:.*]] = fir.load %[[VAL_3]]#0 : !fir.ref<i32> ! CHECK: %[[VAL_5:.*]] = arith.constant 0 : i32 ! CHECK: %[[VAL_6:.*]] = arith.cmpi sgt, %[[VAL_4]], %[[VAL_5]] : i32 ! CHECK: %[[VAL_7:.*]] = arith.select %[[VAL_6]], %[[VAL_4]], %[[VAL_5]] : i32 -! CHECK: %[[VAL_8:.*]]:2 = hlfir.declare %[[VAL_0]] typeparams %[[VAL_7]] dummy_scope %[[VAL_2]] {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QMalloc_assignFtest_dyn_char_scalarEx"} : (!fir.ref<!fir.box<!fir.heap<!fir.char<1,?>>>>, i32, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.char<1,?>>>>, !fir.ref<!fir.box<!fir.heap<!fir.char<1,?>>>>) +! CHECK: %[[VAL_8:.*]]:2 = hlfir.declare %[[VAL_0]] typeparams %[[VAL_7]] dummy_scope %[[VAL_2]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QMalloc_assignFtest_dyn_char_scalarEx"} : (!fir.ref<!fir.box<!fir.heap<!fir.char<1,?>>>>, i32, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.char<1,?>>>>, !fir.ref<!fir.box<!fir.heap<!fir.char<1,?>>>>) ! CHECK: %[[VAL_9:.*]] = fir.address_of(@_QQclX48656C6C6F20776F726C6421) : !fir.ref<!fir.char<1,12>> ! CHECK: %[[VAL_10:.*]] = arith.constant 12 : index ! CHECK: %[[VAL_11:.*]]:2 = hlfir.declare %[[VAL_9]] typeparams %[[VAL_10]] {fortran_attrs = #fir.var_attrs<parameter>, uniq_name = "_QQclX48656C6C6F20776F726C6421"} : (!fir.ref<!fir.char<1,12>>, index) -> (!fir.ref<!fir.char<1,12>>, !fir.ref<!fir.char<1,12>>) @@ -96,8 +96,8 @@ end subroutine ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.heap<!fir.type<_QMalloc_assignTt{i:i32}>>>> {fir.bindc_name = "x"}, ! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref<!fir.type<_QMalloc_assignTt{i:i32}>> {fir.bindc_name = "s"}) { ! CHECK: %[[VAL_2:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %[[VAL_2]] {uniq_name = "_QMalloc_assignFtest_derived_scalarEs"} : (!fir.ref<!fir.type<_QMalloc_assignTt{i:i32}>>, !fir.dscope) -> (!fir.ref<!fir.type<_QMalloc_assignTt{i:i32}>>, !fir.ref<!fir.type<_QMalloc_assignTt{i:i32}>>) -! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_2]] {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QMalloc_assignFtest_derived_scalarEx"} : (!fir.ref<!fir.box<!fir.heap<!fir.type<_QMalloc_assignTt{i:i32}>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.type<_QMalloc_assignTt{i:i32}>>>>, !fir.ref<!fir.box<!fir.heap<!fir.type<_QMalloc_assignTt{i:i32}>>>>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %[[VAL_2]] arg {{[0-9]+}} {uniq_name = "_QMalloc_assignFtest_derived_scalarEs"} : (!fir.ref<!fir.type<_QMalloc_assignTt{i:i32}>>, !fir.dscope) -> (!fir.ref<!fir.type<_QMalloc_assignTt{i:i32}>>, !fir.ref<!fir.type<_QMalloc_assignTt{i:i32}>>) +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_2]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QMalloc_assignFtest_derived_scalarEx"} : (!fir.ref<!fir.box<!fir.heap<!fir.type<_QMalloc_assignTt{i:i32}>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.type<_QMalloc_assignTt{i:i32}>>>>, !fir.ref<!fir.box<!fir.heap<!fir.type<_QMalloc_assignTt{i:i32}>>>>) ! CHECK: hlfir.assign %[[VAL_3]]#0 to %[[VAL_4]]#0 realloc : !fir.ref<!fir.type<_QMalloc_assignTt{i:i32}>>, !fir.ref<!fir.box<!fir.heap<!fir.type<_QMalloc_assignTt{i:i32}>>>> ! ----------------------------------------------------------------------------- @@ -113,11 +113,11 @@ end subroutine ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.heap<!fir.array<?x?xf32>>>> {fir.bindc_name = "x"}, ! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref<!fir.array<2x3xf32>> {fir.bindc_name = "y"}) { ! CHECK: %[[VAL_2:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_2]] {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QMalloc_assignFtest_from_cst_shape_arrayEx"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?x?xf32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?x?xf32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?x?xf32>>>>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_2]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QMalloc_assignFtest_from_cst_shape_arrayEx"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?x?xf32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?x?xf32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?x?xf32>>>>) ! CHECK: %[[VAL_4:.*]] = arith.constant 2 : index ! CHECK: %[[VAL_5:.*]] = arith.constant 3 : index ! CHECK: %[[VAL_6:.*]] = fir.shape %[[VAL_4]], %[[VAL_5]] : (index, index) -> !fir.shape<2> -! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_1]](%[[VAL_6]]) dummy_scope %[[VAL_2]] {uniq_name = "_QMalloc_assignFtest_from_cst_shape_arrayEy"} : (!fir.ref<!fir.array<2x3xf32>>, !fir.shape<2>, !fir.dscope) -> (!fir.ref<!fir.array<2x3xf32>>, !fir.ref<!fir.array<2x3xf32>>) +! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_1]](%[[VAL_6]]) dummy_scope %[[VAL_2]] arg {{[0-9]+}} {uniq_name = "_QMalloc_assignFtest_from_cst_shape_arrayEy"} : (!fir.ref<!fir.array<2x3xf32>>, !fir.shape<2>, !fir.dscope) -> (!fir.ref<!fir.array<2x3xf32>>, !fir.ref<!fir.array<2x3xf32>>) ! CHECK: hlfir.assign %[[VAL_7]]#0 to %[[VAL_3]]#0 realloc : !fir.ref<!fir.array<2x3xf32>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?x?xf32>>>> subroutine test_from_dyn_shape_array(x, y) @@ -129,8 +129,8 @@ end subroutine ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.heap<!fir.array<?x?xf32>>>> {fir.bindc_name = "x"}, ! CHECK-SAME: %[[VAL_1:.*]]: !fir.box<!fir.array<?x?xf32>> {fir.bindc_name = "y"}) { ! CHECK: %[[VAL_2:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_2]] {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QMalloc_assignFtest_from_dyn_shape_arrayEx"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?x?xf32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?x?xf32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?x?xf32>>>>) -! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %[[VAL_2]] {uniq_name = "_QMalloc_assignFtest_from_dyn_shape_arrayEy"} : (!fir.box<!fir.array<?x?xf32>>, !fir.dscope) -> (!fir.box<!fir.array<?x?xf32>>, !fir.box<!fir.array<?x?xf32>>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_2]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QMalloc_assignFtest_from_dyn_shape_arrayEx"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?x?xf32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?x?xf32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?x?xf32>>>>) +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %[[VAL_2]] arg {{[0-9]+}} {uniq_name = "_QMalloc_assignFtest_from_dyn_shape_arrayEy"} : (!fir.box<!fir.array<?x?xf32>>, !fir.dscope) -> (!fir.box<!fir.array<?x?xf32>>, !fir.box<!fir.array<?x?xf32>>) ! CHECK: hlfir.assign %[[VAL_4]]#0 to %[[VAL_3]]#0 realloc : !fir.box<!fir.array<?x?xf32>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?x?xf32>>>> subroutine test_with_lbounds(x, y) @@ -142,13 +142,13 @@ end subroutine ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.heap<!fir.array<?x?xf32>>>> {fir.bindc_name = "x"}, ! CHECK-SAME: %[[VAL_1:.*]]: !fir.box<!fir.array<?x?xf32>> {fir.bindc_name = "y"}) { ! CHECK: %[[VAL_2:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_2]] {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QMalloc_assignFtest_with_lboundsEx"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?x?xf32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?x?xf32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?x?xf32>>>>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_2]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QMalloc_assignFtest_with_lboundsEx"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?x?xf32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?x?xf32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?x?xf32>>>>) ! CHECK: %[[VAL_4:.*]] = arith.constant 10 : i64 ! CHECK: %[[VAL_5:.*]] = fir.convert %[[VAL_4]] : (i64) -> index ! CHECK: %[[VAL_6:.*]] = arith.constant 20 : i64 ! CHECK: %[[VAL_7:.*]] = fir.convert %[[VAL_6]] : (i64) -> index ! CHECK: %[[VAL_8:.*]] = fir.shift %[[VAL_5]], %[[VAL_7]] : (index, index) -> !fir.shift<2> -! CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[VAL_1]](%[[VAL_8]]) dummy_scope %[[VAL_2]] {uniq_name = "_QMalloc_assignFtest_with_lboundsEy"} : (!fir.box<!fir.array<?x?xf32>>, !fir.shift<2>, !fir.dscope) -> (!fir.box<!fir.array<?x?xf32>>, !fir.box<!fir.array<?x?xf32>>) +! CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[VAL_1]](%[[VAL_8]]) dummy_scope %[[VAL_2]] arg {{[0-9]+}} {uniq_name = "_QMalloc_assignFtest_with_lboundsEy"} : (!fir.box<!fir.array<?x?xf32>>, !fir.shift<2>, !fir.dscope) -> (!fir.box<!fir.array<?x?xf32>>, !fir.box<!fir.array<?x?xf32>>) ! CHECK: hlfir.assign %[[VAL_9]]#0 to %[[VAL_3]]#0 realloc : !fir.box<!fir.array<?x?xf32>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?x?xf32>>>> subroutine test_runtime_shape(x) @@ -164,7 +164,7 @@ end subroutine ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.heap<!fir.array<?x?xf32>>>> {fir.bindc_name = "x"}) { ! CHECK: %[[VAL_1:.*]] = fir.alloca !fir.box<!fir.ptr<!fir.array<?x?xf32>>> {bindc_name = ".result"} ! CHECK: %[[VAL_2:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_2]] {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QMalloc_assignFtest_runtime_shapeEx"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?x?xf32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?x?xf32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?x?xf32>>>>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_2]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QMalloc_assignFtest_runtime_shapeEx"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?x?xf32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?x?xf32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?x?xf32>>>>) ! CHECK: %[[VAL_4:.*]] = fir.call @_QPreturn_pointer() fastmath<contract> : () -> !fir.box<!fir.ptr<!fir.array<?x?xf32>>> ! CHECK: fir.save_result %[[VAL_4]] to %[[VAL_1]] : !fir.box<!fir.ptr<!fir.array<?x?xf32>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?x?xf32>>>> ! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = ".tmp.func_result"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?x?xf32>>>>) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?x?xf32>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?x?xf32>>>>) @@ -180,8 +180,8 @@ end subroutine ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>> {fir.bindc_name = "x"}, ! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref<f32> {fir.bindc_name = "y"}) { ! CHECK: %[[VAL_2:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_2]] {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QMalloc_assignFtest_scalar_rhsEx"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>) -! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %[[VAL_2]] {uniq_name = "_QMalloc_assignFtest_scalar_rhsEy"} : (!fir.ref<f32>, !fir.dscope) -> (!fir.ref<f32>, !fir.ref<f32>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_2]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QMalloc_assignFtest_scalar_rhsEx"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>) +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %[[VAL_2]] arg {{[0-9]+}} {uniq_name = "_QMalloc_assignFtest_scalar_rhsEy"} : (!fir.ref<f32>, !fir.dscope) -> (!fir.ref<f32>, !fir.ref<f32>) ! CHECK: %[[VAL_5:.*]] = fir.load %[[VAL_4]]#0 : !fir.ref<f32> ! CHECK: hlfir.assign %[[VAL_5]] to %[[VAL_3]]#0 realloc : f32, !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>> @@ -205,7 +205,7 @@ end subroutine ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.char<1,10>>>>> {fir.bindc_name = "x"}) { ! CHECK: %[[VAL_1:.*]] = fir.dummy_scope : !fir.dscope ! CHECK: %[[VAL_2:.*]] = arith.constant 10 : index -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] typeparams %[[VAL_2]] dummy_scope %[[VAL_1]] {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QMalloc_assignFtest_cst_char_rhs_scalarEx"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.char<1,10>>>>>, index, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.char<1,10>>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.char<1,10>>>>>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] typeparams %[[VAL_2]] dummy_scope %[[VAL_1]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QMalloc_assignFtest_cst_char_rhs_scalarEx"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.char<1,10>>>>>, index, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.char<1,10>>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.char<1,10>>>>>) ! CHECK: %[[VAL_4:.*]] = fir.address_of(@_QQclX48656C6C6F20776F726C6421) : !fir.ref<!fir.char<1,12>> ! CHECK: %[[VAL_5:.*]] = arith.constant 12 : index ! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_4]] typeparams %[[VAL_5]] {fortran_attrs = #fir.var_attrs<parameter>, uniq_name = "_QQclX48656C6C6F20776F726C6421"} : (!fir.ref<!fir.char<1,12>>, index) -> (!fir.ref<!fir.char<1,12>>, !fir.ref<!fir.char<1,12>>) @@ -221,12 +221,12 @@ end subroutine ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.char<1,?>>>>> {fir.bindc_name = "x"}, ! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref<i32> {fir.bindc_name = "n"}) { ! CHECK: %[[VAL_2:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %[[VAL_2]] {uniq_name = "_QMalloc_assignFtest_dyn_char_rhs_scalarEn"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %[[VAL_2]] arg {{[0-9]+}} {uniq_name = "_QMalloc_assignFtest_dyn_char_rhs_scalarEn"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_4:.*]] = fir.load %[[VAL_3]]#0 : !fir.ref<i32> ! CHECK: %[[VAL_5:.*]] = arith.constant 0 : i32 ! CHECK: %[[VAL_6:.*]] = arith.cmpi sgt, %[[VAL_4]], %[[VAL_5]] : i32 ! CHECK: %[[VAL_7:.*]] = arith.select %[[VAL_6]], %[[VAL_4]], %[[VAL_5]] : i32 -! CHECK: %[[VAL_8:.*]]:2 = hlfir.declare %[[VAL_0]] typeparams %[[VAL_7]] dummy_scope %[[VAL_2]] {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QMalloc_assignFtest_dyn_char_rhs_scalarEx"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.char<1,?>>>>>, i32, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.char<1,?>>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.char<1,?>>>>>) +! CHECK: %[[VAL_8:.*]]:2 = hlfir.declare %[[VAL_0]] typeparams %[[VAL_7]] dummy_scope %[[VAL_2]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QMalloc_assignFtest_dyn_char_rhs_scalarEx"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.char<1,?>>>>>, i32, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.char<1,?>>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.char<1,?>>>>>) ! CHECK: %[[VAL_9:.*]] = fir.address_of(@_QQclX48656C6C6F20776F726C6421) : !fir.ref<!fir.char<1,12>> ! CHECK: %[[VAL_10:.*]] = arith.constant 12 : index ! CHECK: %[[VAL_11:.*]]:2 = hlfir.declare %[[VAL_9]] typeparams %[[VAL_10]] {fortran_attrs = #fir.var_attrs<parameter>, uniq_name = "_QQclX48656C6C6F20776F726C6421"} : (!fir.ref<!fir.char<1,12>>, index) -> (!fir.ref<!fir.char<1,12>>, !fir.ref<!fir.char<1,12>>) @@ -253,9 +253,9 @@ end subroutine ! CHECK: %[[VAL_5:.*]] = arith.constant 12 : index ! CHECK: %[[VAL_6:.*]] = arith.constant 20 : index ! CHECK: %[[VAL_7:.*]] = fir.shape %[[VAL_6]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_8:.*]]:2 = hlfir.declare %[[VAL_4]](%[[VAL_7]]) typeparams %[[VAL_5]] dummy_scope %[[VAL_2]] {uniq_name = "_QMalloc_assignFtest_cst_charEc"} : (!fir.ref<!fir.array<20x!fir.char<1,12>>>, !fir.shape<1>, index, !fir.dscope) -> (!fir.ref<!fir.array<20x!fir.char<1,12>>>, !fir.ref<!fir.array<20x!fir.char<1,12>>>) +! CHECK: %[[VAL_8:.*]]:2 = hlfir.declare %[[VAL_4]](%[[VAL_7]]) typeparams %[[VAL_5]] dummy_scope %[[VAL_2]] arg {{[0-9]+}} {uniq_name = "_QMalloc_assignFtest_cst_charEc"} : (!fir.ref<!fir.array<20x!fir.char<1,12>>>, !fir.shape<1>, index, !fir.dscope) -> (!fir.ref<!fir.array<20x!fir.char<1,12>>>, !fir.ref<!fir.array<20x!fir.char<1,12>>>) ! CHECK: %[[VAL_9:.*]] = arith.constant 10 : index -! CHECK: %[[VAL_10:.*]]:2 = hlfir.declare %[[VAL_0]] typeparams %[[VAL_9]] dummy_scope %[[VAL_2]] {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QMalloc_assignFtest_cst_charEx"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.char<1,10>>>>>, index, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.char<1,10>>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.char<1,10>>>>>) +! CHECK: %[[VAL_10:.*]]:2 = hlfir.declare %[[VAL_0]] typeparams %[[VAL_9]] dummy_scope %[[VAL_2]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QMalloc_assignFtest_cst_charEx"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.char<1,10>>>>>, index, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.char<1,10>>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.char<1,10>>>>>) ! CHECK: hlfir.assign %[[VAL_8]]#0 to %[[VAL_10]]#0 realloc keep_lhs_len : !fir.ref<!fir.array<20x!fir.char<1,12>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.char<1,10>>>>> subroutine test_dyn_char(x, n, c) @@ -273,32 +273,32 @@ end subroutine ! CHECK: %[[VAL_5:.*]] = fir.convert %[[VAL_4]]#0 : (!fir.ref<!fir.char<1,?>>) -> !fir.ref<!fir.array<20x!fir.char<1,?>>> ! CHECK: %[[VAL_6:.*]] = arith.constant 20 : index ! CHECK: %[[VAL_7:.*]] = fir.shape %[[VAL_6]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_8:.*]]:2 = hlfir.declare %[[VAL_5]](%[[VAL_7]]) typeparams %[[VAL_4]]#1 dummy_scope %[[VAL_3]] {uniq_name = "_QMalloc_assignFtest_dyn_charEc"} : (!fir.ref<!fir.array<20x!fir.char<1,?>>>, !fir.shape<1>, index, !fir.dscope) -> (!fir.box<!fir.array<20x!fir.char<1,?>>>, !fir.ref<!fir.array<20x!fir.char<1,?>>>) -! CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %[[VAL_3]] {uniq_name = "_QMalloc_assignFtest_dyn_charEn"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_8:.*]]:2 = hlfir.declare %[[VAL_5]](%[[VAL_7]]) typeparams %[[VAL_4]]#1 dummy_scope %[[VAL_3]] arg {{[0-9]+}} {uniq_name = "_QMalloc_assignFtest_dyn_charEc"} : (!fir.ref<!fir.array<20x!fir.char<1,?>>>, !fir.shape<1>, index, !fir.dscope) -> (!fir.box<!fir.array<20x!fir.char<1,?>>>, !fir.ref<!fir.array<20x!fir.char<1,?>>>) +! CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %[[VAL_3]] arg {{[0-9]+}} {uniq_name = "_QMalloc_assignFtest_dyn_charEn"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_10:.*]] = fir.load %[[VAL_9]]#0 : !fir.ref<i32> ! CHECK: %[[VAL_11:.*]] = arith.constant 0 : i32 ! CHECK: %[[VAL_12:.*]] = arith.cmpi sgt, %[[VAL_10]], %[[VAL_11]] : i32 ! CHECK: %[[VAL_13:.*]] = arith.select %[[VAL_12]], %[[VAL_10]], %[[VAL_11]] : i32 -! CHECK: %[[VAL_14:.*]]:2 = hlfir.declare %[[VAL_0]] typeparams %[[VAL_13]] dummy_scope %[[VAL_3]] {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QMalloc_assignFtest_dyn_charEx"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.char<1,?>>>>>, i32, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.char<1,?>>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.char<1,?>>>>>) +! CHECK: %[[VAL_14:.*]]:2 = hlfir.declare %[[VAL_0]] typeparams %[[VAL_13]] dummy_scope %[[VAL_3]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QMalloc_assignFtest_dyn_charEx"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.char<1,?>>>>>, i32, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.char<1,?>>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.char<1,?>>>>>) ! CHECK: hlfir.assign %[[VAL_8]]#0 to %[[VAL_14]]#0 realloc keep_lhs_len : !fir.box<!fir.array<20x!fir.char<1,?>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.char<1,?>>>>> subroutine test_derived_with_init(x, y) - type t + type t integer, allocatable :: a(:) - end type - type(t), allocatable :: x - type(t) :: y + end type + type(t), allocatable :: x + type(t) :: y ! The allocatable component of `x` need to be initialized ! during the automatic allocation (setting its rank and allocation - ! status) before it is assigned with the component of `y` + ! status) before it is assigned with the component of `y` x = y end subroutine ! CHECK-LABEL: func.func @_QMalloc_assignPtest_derived_with_init( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.heap<!fir.type<_QMalloc_assignFtest_derived_with_initTt{a:!fir.box<!fir.heap<!fir.array<?xi32>>>}>>>> {fir.bindc_name = "x"}, ! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref<!fir.type<_QMalloc_assignFtest_derived_with_initTt{a:!fir.box<!fir.heap<!fir.array<?xi32>>>}>> {fir.bindc_name = "y"}) { ! CHECK: %[[VAL_2:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_2]] {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QMalloc_assignFtest_derived_with_initEx"} : (!fir.ref<!fir.box<!fir.heap<!fir.type<_QMalloc_assignFtest_derived_with_initTt{a:!fir.box<!fir.heap<!fir.array<?xi32>>>}>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.type<_QMalloc_assignFtest_derived_with_initTt{a:!fir.box<!fir.heap<!fir.array<?xi32>>>}>>>>, !fir.ref<!fir.box<!fir.heap<!fir.type<_QMalloc_assignFtest_derived_with_initTt{a:!fir.box<!fir.heap<!fir.array<?xi32>>>}>>>>) -! CHECK: %[[VAL_10:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %[[VAL_2]] {uniq_name = "_QMalloc_assignFtest_derived_with_initEy"} : (!fir.ref<!fir.type<_QMalloc_assignFtest_derived_with_initTt{a:!fir.box<!fir.heap<!fir.array<?xi32>>>}>>, !fir.dscope) -> (!fir.ref<!fir.type<_QMalloc_assignFtest_derived_with_initTt{a:!fir.box<!fir.heap<!fir.array<?xi32>>>}>>, !fir.ref<!fir.type<_QMalloc_assignFtest_derived_with_initTt{a:!fir.box<!fir.heap<!fir.array<?xi32>>>}>>) +! CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_2]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QMalloc_assignFtest_derived_with_initEx"} : (!fir.ref<!fir.box<!fir.heap<!fir.type<_QMalloc_assignFtest_derived_with_initTt{a:!fir.box<!fir.heap<!fir.array<?xi32>>>}>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.type<_QMalloc_assignFtest_derived_with_initTt{a:!fir.box<!fir.heap<!fir.array<?xi32>>>}>>>>, !fir.ref<!fir.box<!fir.heap<!fir.type<_QMalloc_assignFtest_derived_with_initTt{a:!fir.box<!fir.heap<!fir.array<?xi32>>>}>>>>) +! CHECK: %[[VAL_10:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %[[VAL_2]] arg {{[0-9]+}} {uniq_name = "_QMalloc_assignFtest_derived_with_initEy"} : (!fir.ref<!fir.type<_QMalloc_assignFtest_derived_with_initTt{a:!fir.box<!fir.heap<!fir.array<?xi32>>>}>>, !fir.dscope) -> (!fir.ref<!fir.type<_QMalloc_assignFtest_derived_with_initTt{a:!fir.box<!fir.heap<!fir.array<?xi32>>>}>>, !fir.ref<!fir.type<_QMalloc_assignFtest_derived_with_initTt{a:!fir.box<!fir.heap<!fir.array<?xi32>>>}>>) ! CHECK: hlfir.assign %[[VAL_10]]#0 to %[[VAL_9]]#0 realloc : !fir.ref<!fir.type<_QMalloc_assignFtest_derived_with_initTt{a:!fir.box<!fir.heap<!fir.array<?xi32>>>}>>, !fir.ref<!fir.box<!fir.heap<!fir.type<_QMalloc_assignFtest_derived_with_initTt{a:!fir.box<!fir.heap<!fir.array<?xi32>>>}>>>> subroutine test_vector_subscript(x, y, v) @@ -314,9 +314,9 @@ end subroutine ! CHECK-SAME: %[[VAL_1:.*]]: !fir.box<!fir.array<?xi32>> {fir.bindc_name = "y"}, ! CHECK-SAME: %[[VAL_2:.*]]: !fir.box<!fir.array<?xi32>> {fir.bindc_name = "v"}) { ! CHECK: %[[VAL_3:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_2]] dummy_scope %[[VAL_3]] {uniq_name = "_QMalloc_assignFtest_vector_subscriptEv"} : (!fir.box<!fir.array<?xi32>>, !fir.dscope) -> (!fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>>) -! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_3]] {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QMalloc_assignFtest_vector_subscriptEx"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) -! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %[[VAL_3]] {uniq_name = "_QMalloc_assignFtest_vector_subscriptEy"} : (!fir.box<!fir.array<?xi32>>, !fir.dscope) -> (!fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>>) +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_2]] dummy_scope %[[VAL_3]] arg {{[0-9]+}} {uniq_name = "_QMalloc_assignFtest_vector_subscriptEv"} : (!fir.box<!fir.array<?xi32>>, !fir.dscope) -> (!fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>>) +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_3]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QMalloc_assignFtest_vector_subscriptEx"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) +! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %[[VAL_3]] arg {{[0-9]+}} {uniq_name = "_QMalloc_assignFtest_vector_subscriptEy"} : (!fir.box<!fir.array<?xi32>>, !fir.dscope) -> (!fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>>) ! CHECK: %[[VAL_16:.*]] = hlfir.elemental %{{.*}} unordered : (!fir.shape<1>) -> !hlfir.expr<?xi32> { ! CHECK: hlfir.assign %[[VAL_16]] to %[[VAL_5]]#0 realloc : !hlfir.expr<?xi32>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> @@ -332,7 +332,7 @@ end subroutine ! CHECK-LABEL: func.func @_QMalloc_assignPtest_both_sides_with_elemental_call( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>> {fir.bindc_name = "x"}) { ! CHECK: %[[VAL_1:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QMalloc_assignFtest_both_sides_with_elemental_callEx"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QMalloc_assignFtest_both_sides_with_elemental_callEx"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>) ! CHECK: %[[VAL_3:.*]] = fir.load %[[VAL_2]]#0 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>> ! CHECK: %[[VAL_4:.*]] = arith.constant 0 : index ! CHECK: %[[VAL_5:.*]]:3 = fir.box_dims %[[VAL_3]], %[[VAL_4]] : (!fir.box<!fir.heap<!fir.array<?xf32>>>, index) -> (index, index, index) @@ -357,7 +357,7 @@ end module ! real :: y(2, 3) = reshape([1,2,3,4,5,6], [2,3]) ! real, allocatable :: x (:, :) ! allocate(x(2,2)) -! call test_with_lbounds(x, y) +! call test_with_lbounds(x, y) ! print *, x(10, 20) ! print *, x !end diff --git a/flang/test/Lower/allocatable-globals.f90 b/flang/test/Lower/allocatable-globals.f90 index 9d386688..8b7420a 100644 --- a/flang/test/Lower/allocatable-globals.f90 +++ b/flang/test/Lower/allocatable-globals.f90 @@ -12,7 +12,7 @@ module mod_allocatables character(10), allocatable :: c(:) end module - + ! CHECK-LABEL: func @_QPtest_mod_allocatables() subroutine test_mod_allocatables() use mod_allocatables, only: c diff --git a/flang/test/Lower/allocatable-polymorphic.f90 b/flang/test/Lower/allocatable-polymorphic.f90 index e6a8c5e..d528fd8 100644 --- a/flang/test/Lower/allocatable-polymorphic.f90 +++ b/flang/test/Lower/allocatable-polymorphic.f90 @@ -460,7 +460,7 @@ contains ! CHECK: %[[X_DECL:.*]]:2 = hlfir.declare %[[X]](%{{.*}}) {uniq_name = "_QMpolyFtest_allocate_with_moldEx"} : (!fir.ref<!fir.array<10x!fir.type<_QMpolyTp2{p1:!fir.type<_QMpolyTp1{a:i32,b:i32}>,c:i32}>>>, !fir.shape<1>) -> (!fir.ref<!fir.array<10x!fir.type<_QMpolyTp2{p1:!fir.type<_QMpolyTp1{a:i32,b:i32}>,c:i32}>>>, !fir.ref<!fir.array<10x!fir.type<_QMpolyTp2{p1:!fir.type<_QMpolyTp1{a:i32,b:i32}>,c:i32}>>>) ! CHECK: %[[EMBOX_X:.*]] = fir.embox %[[X_DECL]]#0(%{{.*}}) : (!fir.ref<!fir.array<10x!fir.type<_QMpolyTp2{p1:!fir.type<_QMpolyTp1{a:i32,b:i32}>,c:i32}>>>, !fir.shape<1>) -> !fir.box<!fir.array<10x!fir.type<_QMpolyTp2{p1:!fir.type<_QMpolyTp1{a:i32,b:i32}>,c:i32}>>> -! CHECK: %[[RANK:.*]] = arith.constant 1 : i32 +! CHECK: %[[RANK:.*]] = arith.constant 1 : i32 ! CHECK: %[[P_BOX_NONE:.*]] = fir.convert %[[P_DECL]]#0 : (!fir.ref<!fir.class<!fir.ptr<!fir.array<?x!fir.type<_QMpolyTp1{a:i32,b:i32}>>>>>) -> !fir.ref<!fir.box<none>> ! CHECK: %[[X_BOX_NONE:.*]] = fir.convert %[[EMBOX_X]] : (!fir.box<!fir.array<10x!fir.type<_QMpolyTp2{p1:!fir.type<_QMpolyTp1{a:i32,b:i32}>,c:i32}>>>) -> !fir.box<none> ! CHECK: fir.call @_FortranAPointerApplyMold(%[[P_BOX_NONE]], %[[X_BOX_NONE]], %[[RANK]]) {{.*}} : (!fir.ref<!fir.box<none>>, !fir.box<none>, i32) -> () @@ -520,8 +520,8 @@ contains ! CHECK-LABEL: func.func @_QMpolyPtest_allocatable_up_from_up_mold( ! CHECK-SAME: %[[A:.*]]: !fir.ref<!fir.class<!fir.heap<none>>> {fir.bindc_name = "a"}, %[[B:.*]]: !fir.ref<!fir.class<!fir.ptr<none>>> {fir.bindc_name = "b"}) { -! CHECK: %[[A_DECL:.*]]:2 = hlfir.declare %[[A]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QMpolyFtest_allocatable_up_from_up_moldEa"} : (!fir.ref<!fir.class<!fir.heap<none>>>, !fir.dscope) -> (!fir.ref<!fir.class<!fir.heap<none>>>, !fir.ref<!fir.class<!fir.heap<none>>>) -! CHECK: %[[B_DECL:.*]]:2 = hlfir.declare %[[B]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QMpolyFtest_allocatable_up_from_up_moldEb"} : (!fir.ref<!fir.class<!fir.ptr<none>>>, !fir.dscope) -> (!fir.ref<!fir.class<!fir.ptr<none>>>, !fir.ref<!fir.class<!fir.ptr<none>>>) +! CHECK: %[[A_DECL:.*]]:2 = hlfir.declare %[[A]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QMpolyFtest_allocatable_up_from_up_moldEa"} : (!fir.ref<!fir.class<!fir.heap<none>>>, !fir.dscope) -> (!fir.ref<!fir.class<!fir.heap<none>>>, !fir.ref<!fir.class<!fir.heap<none>>>) +! CHECK: %[[B_DECL:.*]]:2 = hlfir.declare %[[B]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QMpolyFtest_allocatable_up_from_up_moldEb"} : (!fir.ref<!fir.class<!fir.ptr<none>>>, !fir.dscope) -> (!fir.ref<!fir.class<!fir.ptr<none>>>, !fir.ref<!fir.class<!fir.ptr<none>>>) ! CHECK: %[[LOAD_B:.*]] = fir.load %[[B_DECL]]#0 : !fir.ref<!fir.class<!fir.ptr<none>>> ! CHECK: %[[RANK:.*]] = arith.constant 0 : i32 ! CHECK: %[[A_BOX_NONE:.*]] = fir.convert %[[A_DECL]]#0 : (!fir.ref<!fir.class<!fir.heap<none>>>) -> !fir.ref<!fir.box<none>> @@ -539,7 +539,7 @@ contains ! CHECK-LABEL: func.func @_QMpolyPtest_allocatable_up_from_mold_rank( ! CHECK-SAME: %[[A:.*]]: !fir.ref<!fir.class<!fir.heap<!fir.array<?xnone>>>> {fir.bindc_name = "a"}) { ! CHECK: %[[VALUE_10:.*]] = fir.alloca i32 -! CHECK: %[[A_DECL:.*]]:2 = hlfir.declare %[[A]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QMpolyFtest_allocatable_up_from_mold_rankEa"} : (!fir.ref<!fir.class<!fir.heap<!fir.array<?xnone>>>>, !fir.dscope) -> (!fir.ref<!fir.class<!fir.heap<!fir.array<?xnone>>>>, !fir.ref<!fir.class<!fir.heap<!fir.array<?xnone>>>>) +! CHECK: %[[A_DECL:.*]]:2 = hlfir.declare %[[A]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QMpolyFtest_allocatable_up_from_mold_rankEa"} : (!fir.ref<!fir.class<!fir.heap<!fir.array<?xnone>>>>, !fir.dscope) -> (!fir.ref<!fir.class<!fir.heap<!fir.array<?xnone>>>>, !fir.ref<!fir.class<!fir.heap<!fir.array<?xnone>>>>) ! CHECK: %[[C10:.*]] = arith.constant 10 : i32 ! CHECK: fir.store %[[C10]] to %[[VALUE_10]] : !fir.ref<i32> ! CHECK: %[[EMBOX_10:.*]] = fir.embox %[[VALUE_10]] : (!fir.ref<i32>) -> !fir.box<i32> @@ -614,10 +614,10 @@ end ! LLVM: %[[TYPE_CODE:.*]] = load i8, ptr %[[TYPE_CODE_GEP]] ! LLVM-NEXT: %[[EXT_TYPE_CODE:.*]] = sext i8 %[[TYPE_CODE]] to i32 ! LLVM: %{{.*}} = insertvalue { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] } undef, i64 %[[ELEM_SIZE]], 1 -! LLVM: %[[TRUNC_TYPE_CODE:.*]] = trunc i32 %[[EXT_TYPE_CODE]] to i8 +! LLVM: %[[TRUNC_TYPE_CODE:.*]] = trunc i32 %[[EXT_TYPE_CODE]] to i8 ! LLVM: %{{.*}} = insertvalue { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] } %{{.*}}, i8 %[[TRUNC_TYPE_CODE]], 4 ! LLVM: store { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] } %{{.*}}, ptr %[[TMP:.*]] -! LLVM: call void %{{.*}}(ptr %{{.*}}) +! LLVM: call void %{{.*}}(ptr %{{.*}}) ! LLVM: call void @llvm.memcpy.p0.p0.i32 ! LLVM: %[[GEP_TDESC_C2:.*]] = getelementptr { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] }, ptr %{{.*}}, i32 0, i32 7 @@ -628,7 +628,7 @@ end ! LLVM: %[[TYPE_CODE:.*]] = load i8, ptr %[[TYPE_CODE_GEP]] ! LLVM-NEXT: %[[EXT_TYPE_CODE:.*]] = sext i8 %[[TYPE_CODE]] to i32 ! LLVM: %{{.*}} = insertvalue { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] } undef, i64 %[[ELEM_SIZE]], 1 -! LLVM: %[[TRUNC_TYPE_CODE:.*]] = trunc i32 %[[EXT_TYPE_CODE]] to i8 +! LLVM: %[[TRUNC_TYPE_CODE:.*]] = trunc i32 %[[EXT_TYPE_CODE]] to i8 ! LLVM: %{{.*}} = insertvalue { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] } %{{.*}}, i8 %[[TRUNC_TYPE_CODE]], 4 ! LLVM: store { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] } %{{.*}}, ptr %{{.*}} ! LLVM: call void %{{.*}}(ptr %{{.*}}) diff --git a/flang/test/Lower/allocatables.f90 b/flang/test/Lower/allocatables.f90 index e62f92f..60b7de3 100644 --- a/flang/test/Lower/allocatables.f90 +++ b/flang/test/Lower/allocatables.f90 @@ -56,7 +56,7 @@ subroutine foodim1() ! CHECK-DAG: fir.load %[[xAddrVar]] : !fir.ref<!fir.heap<!fir.array<?xf32>>> deallocate(x) - ! CHECK: %[[xAddr1:.*]] = fir.load %1 : !fir.ref<!fir.heap<!fir.array<?xf32>>> + ! CHECK: %[[xAddr1:.*]] = fir.load %{{.*}} : !fir.ref<!fir.heap<!fir.array<?xf32>>> ! CHECK: fir.freemem %[[xAddr1]] ! CHECK: %[[nullAddr1:.*]] = fir.zero_bits !fir.heap<!fir.array<?xf32>> ! CHECK: fir.store %[[nullAddr1]] to %[[xAddrVar]] : !fir.ref<!fir.heap<!fir.array<?xf32>>> @@ -67,10 +67,6 @@ subroutine foodim2() ! Test lowering of local allocatable specification real, allocatable :: x(:, :) ! CHECK-DAG: fir.alloca !fir.heap<!fir.array<?x?xf32>> {{{.*}}uniq_name = "_QFfoodim2Ex.addr"} - ! CHECK-DAG: fir.alloca index {{{.*}}uniq_name = "_QFfoodim2Ex.lb0"} - ! CHECK-DAG: fir.alloca index {{{.*}}uniq_name = "_QFfoodim2Ex.ext0"} - ! CHECK-DAG: fir.alloca index {{{.*}}uniq_name = "_QFfoodim2Ex.lb1"} - ! CHECK-DAG: fir.alloca index {{{.*}}uniq_name = "_QFfoodim2Ex.ext1"} end subroutine ! test lowering of character allocatables. Focus is placed on the length handling diff --git a/flang/test/Lower/allocated.f90 b/flang/test/Lower/allocated.f90 index 6e8420f..11e856f 100644 --- a/flang/test/Lower/allocated.f90 +++ b/flang/test/Lower/allocated.f90 @@ -15,4 +15,3 @@ subroutine allocated_test(scalar, array) ! CHECK: cmpi ne, %[[addrToInt1]], %c0{{.*}} print *, allocated(array) end subroutine -
\ No newline at end of file diff --git a/flang/test/Lower/array-character.f90 b/flang/test/Lower/array-character.f90 index e2899d9..85f5af0 100644 --- a/flang/test/Lower/array-character.f90 +++ b/flang/test/Lower/array-character.f90 @@ -15,12 +15,12 @@ end subroutine ! CHECK: %[[VAL_5:.*]] = arith.constant 4 : index ! CHECK: %[[VAL_6:.*]] = arith.constant 3 : index ! CHECK: %[[VAL_7:.*]] = fir.shape %[[VAL_6]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_8:.*]]:2 = hlfir.declare %[[VAL_4]](%[[VAL_7]]) typeparams %[[VAL_5]] dummy_scope %[[VAL_2]] {uniq_name = "_QFissueEc1"} : (!fir.ref<!fir.array<3x!fir.char<1,4>>>, !fir.shape<1>, index, !fir.dscope) -> (!fir.ref<!fir.array<3x!fir.char<1,4>>>, !fir.ref<!fir.array<3x!fir.char<1,4>>>) +! CHECK: %[[VAL_8:.*]]:2 = hlfir.declare %[[VAL_4]](%[[VAL_7]]) typeparams %[[VAL_5]] dummy_scope %[[VAL_2]] arg {{[0-9]+}} {uniq_name = "_QFissueEc1"} : (!fir.ref<!fir.array<3x!fir.char<1,4>>>, !fir.shape<1>, index, !fir.dscope) -> (!fir.ref<!fir.array<3x!fir.char<1,4>>>, !fir.ref<!fir.array<3x!fir.char<1,4>>>) ! CHECK: %[[VAL_9:.*]]:2 = fir.unboxchar %[[VAL_1]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index) ! CHECK: %[[VAL_10:.*]] = fir.convert %[[VAL_9]]#0 : (!fir.ref<!fir.char<1,?>>) -> !fir.ref<!fir.array<3x!fir.char<1,?>>> ! CHECK: %[[VAL_11:.*]] = arith.constant 3 : index ! CHECK: %[[VAL_12:.*]] = fir.shape %[[VAL_11]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_13:.*]]:2 = hlfir.declare %[[VAL_10]](%[[VAL_12]]) typeparams %[[VAL_9]]#1 dummy_scope %[[VAL_2]] {uniq_name = "_QFissueEc2"} : (!fir.ref<!fir.array<3x!fir.char<1,?>>>, !fir.shape<1>, index, !fir.dscope) -> (!fir.box<!fir.array<3x!fir.char<1,?>>>, !fir.ref<!fir.array<3x!fir.char<1,?>>>) +! CHECK: %[[VAL_13:.*]]:2 = hlfir.declare %[[VAL_10]](%[[VAL_12]]) typeparams %[[VAL_9]]#1 dummy_scope %[[VAL_2]] arg {{[0-9]+}} {uniq_name = "_QFissueEc2"} : (!fir.ref<!fir.array<3x!fir.char<1,?>>>, !fir.shape<1>, index, !fir.dscope) -> (!fir.box<!fir.array<3x!fir.char<1,?>>>, !fir.ref<!fir.array<3x!fir.char<1,?>>>) ! CHECK: hlfir.assign %[[VAL_13]]#0 to %[[VAL_8]]#0 : !fir.box<!fir.array<3x!fir.char<1,?>>>, !fir.ref<!fir.array<3x!fir.char<1,4>>> program p diff --git a/flang/test/Lower/array-elemental-calls-2.f90 b/flang/test/Lower/array-elemental-calls-2.f90 index 2674b07..60c9257 100644 --- a/flang/test/Lower/array-elemental-calls-2.f90 +++ b/flang/test/Lower/array-elemental-calls-2.f90 @@ -172,7 +172,7 @@ end subroutine subroutine check_parentheses_derived(a) type t integer :: i - end type + end type interface integer elemental function elem_func_derived(x) import :: t diff --git a/flang/test/Lower/array-elemental-calls-char-byval.f90 b/flang/test/Lower/array-elemental-calls-char-byval.f90 index 04a4375..8fb3e7f 100644 --- a/flang/test/Lower/array-elemental-calls-char-byval.f90 +++ b/flang/test/Lower/array-elemental-calls-char-byval.f90 @@ -27,13 +27,13 @@ end subroutine ! CHECK: %[[VAL_5:.*]] = fir.convert %[[VAL_4]]#0 : (!fir.ref<!fir.char<1,?>>) -> !fir.ref<!fir.array<10x!fir.char<1,?>>> ! CHECK: %[[VAL_6:.*]] = arith.constant 10 : index ! CHECK: %[[VAL_7:.*]] = fir.shape %[[VAL_6]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_8:.*]]:2 = hlfir.declare %[[VAL_5]](%[[VAL_7]]) typeparams %[[VAL_4]]#1 dummy_scope %[[VAL_3]] {uniq_name = "_QMchar_elem_byvalFfoo1Ec"} : (!fir.ref<!fir.array<10x!fir.char<1,?>>>, !fir.shape<1>, index, !fir.dscope) -> (!fir.box<!fir.array<10x!fir.char<1,?>>>, !fir.ref<!fir.array<10x!fir.char<1,?>>>) +! CHECK: %[[VAL_8:.*]]:2 = hlfir.declare %[[VAL_5]](%[[VAL_7]]) typeparams %[[VAL_4]]#1 dummy_scope %[[VAL_3]] arg {{[0-9]+}} {uniq_name = "_QMchar_elem_byvalFfoo1Ec"} : (!fir.ref<!fir.array<10x!fir.char<1,?>>>, !fir.shape<1>, index, !fir.dscope) -> (!fir.box<!fir.array<10x!fir.char<1,?>>>, !fir.ref<!fir.array<10x!fir.char<1,?>>>) ! CHECK: %[[VAL_9:.*]] = arith.constant 10 : index ! CHECK: %[[VAL_10:.*]] = fir.shape %[[VAL_9]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_11:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_10]]) dummy_scope %[[VAL_3]] {uniq_name = "_QMchar_elem_byvalFfoo1Ei"} : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>) +! CHECK: %[[VAL_11:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_10]]) dummy_scope %[[VAL_3]] arg {{[0-9]+}} {uniq_name = "_QMchar_elem_byvalFfoo1Ei"} : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>) ! CHECK: %[[VAL_12:.*]] = arith.constant 10 : index ! CHECK: %[[VAL_13:.*]] = fir.shape %[[VAL_12]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_14:.*]]:2 = hlfir.declare %[[VAL_1]](%[[VAL_13]]) dummy_scope %[[VAL_3]] {uniq_name = "_QMchar_elem_byvalFfoo1Ej"} : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>) +! CHECK: %[[VAL_14:.*]]:2 = hlfir.declare %[[VAL_1]](%[[VAL_13]]) dummy_scope %[[VAL_3]] arg {{[0-9]+}} {uniq_name = "_QMchar_elem_byvalFfoo1Ej"} : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>) ! CHECK: %[[VAL_15:.*]] = hlfir.elemental %[[VAL_7]] unordered : (!fir.shape<1>) -> !hlfir.expr<10xi32> { ! CHECK: ^bb0(%[[VAL_16:.*]]: index): ! CHECK: %[[VAL_17:.*]] = hlfir.designate %[[VAL_8]]#0 (%[[VAL_16]]) typeparams %[[VAL_4]]#1 : (!fir.box<!fir.array<10x!fir.char<1,?>>>, index, index) -> !fir.boxchar<1> @@ -60,13 +60,13 @@ end subroutine ! CHECK-SAME: %[[VAL_2:.*]]: !fir.boxchar<1> {fir.bindc_name = "c"}) { ! CHECK: %[[VAL_3:.*]] = fir.dummy_scope : !fir.dscope ! CHECK: %[[VAL_4:.*]]:2 = fir.unboxchar %[[VAL_2]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index) -! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_4]]#0 typeparams %[[VAL_4]]#1 dummy_scope %[[VAL_3]] {uniq_name = "_QMchar_elem_byvalFfoo2Ec"} : (!fir.ref<!fir.char<1,?>>, index, !fir.dscope) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>) +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_4]]#0 typeparams %[[VAL_4]]#1 dummy_scope %[[VAL_3]] arg {{[0-9]+}} {uniq_name = "_QMchar_elem_byvalFfoo2Ec"} : (!fir.ref<!fir.char<1,?>>, index, !fir.dscope) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>) ! CHECK: %[[VAL_6:.*]] = arith.constant 10 : index ! CHECK: %[[VAL_7:.*]] = fir.shape %[[VAL_6]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_8:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_7]]) dummy_scope %[[VAL_3]] {uniq_name = "_QMchar_elem_byvalFfoo2Ei"} : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>) +! CHECK: %[[VAL_8:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_7]]) dummy_scope %[[VAL_3]] arg {{[0-9]+}} {uniq_name = "_QMchar_elem_byvalFfoo2Ei"} : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>) ! CHECK: %[[VAL_9:.*]] = arith.constant 10 : index ! CHECK: %[[VAL_10:.*]] = fir.shape %[[VAL_9]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_11:.*]]:2 = hlfir.declare %[[VAL_1]](%[[VAL_10]]) dummy_scope %[[VAL_3]] {uniq_name = "_QMchar_elem_byvalFfoo2Ej"} : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>) +! CHECK: %[[VAL_11:.*]]:2 = hlfir.declare %[[VAL_1]](%[[VAL_10]]) dummy_scope %[[VAL_3]] arg {{[0-9]+}} {uniq_name = "_QMchar_elem_byvalFfoo2Ej"} : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>) ! CHECK: %[[VAL_12:.*]] = hlfir.elemental %[[VAL_10]] unordered : (!fir.shape<1>) -> !hlfir.expr<10xi32> { ! CHECK: ^bb0(%[[VAL_13:.*]]: index): ! CHECK: %[[VAL_14:.*]] = hlfir.as_expr %[[VAL_5]]#0 : (!fir.boxchar<1>) -> !hlfir.expr<!fir.char<1,?>> @@ -92,10 +92,10 @@ end subroutine ! CHECK: %[[VAL_3:.*]] = fir.dummy_scope : !fir.dscope ! CHECK: %[[VAL_4:.*]] = arith.constant 10 : index ! CHECK: %[[VAL_5:.*]] = fir.shape %[[VAL_4]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_5]]) dummy_scope %[[VAL_3]] {uniq_name = "_QMchar_elem_byvalFfoo3Ei"} : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>) +! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_5]]) dummy_scope %[[VAL_3]] arg {{[0-9]+}} {uniq_name = "_QMchar_elem_byvalFfoo3Ei"} : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>) ! CHECK: %[[VAL_7:.*]] = arith.constant 10 : index ! CHECK: %[[VAL_8:.*]] = fir.shape %[[VAL_7]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[VAL_1]](%[[VAL_8]]) dummy_scope %[[VAL_3]] {uniq_name = "_QMchar_elem_byvalFfoo3Ej"} : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>) +! CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[VAL_1]](%[[VAL_8]]) dummy_scope %[[VAL_3]] arg {{[0-9]+}} {uniq_name = "_QMchar_elem_byvalFfoo3Ej"} : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>) ! CHECK: %[[VAL_10:.*]] = hlfir.elemental %[[VAL_8]] unordered : (!fir.shape<1>) -> !hlfir.expr<10xi64> { ! CHECK: ^bb0(%[[VAL_11:.*]]: index): ! CHECK: %[[VAL_12:.*]] = hlfir.designate %[[VAL_9]]#0 (%[[VAL_11]]) : (!fir.ref<!fir.array<10xi32>>, index) -> !fir.ref<i32> @@ -143,10 +143,10 @@ end subroutine ! CHECK: %[[VAL_3:.*]] = fir.dummy_scope : !fir.dscope ! CHECK: %[[VAL_4:.*]] = arith.constant 10 : index ! CHECK: %[[VAL_5:.*]] = fir.shape %[[VAL_4]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_5]]) dummy_scope %[[VAL_3]] {uniq_name = "_QMchar_elem_byvalFfoo4Ei"} : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>) +! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_5]]) dummy_scope %[[VAL_3]] arg {{[0-9]+}} {uniq_name = "_QMchar_elem_byvalFfoo4Ei"} : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>) ! CHECK: %[[VAL_7:.*]] = arith.constant 10 : index ! CHECK: %[[VAL_8:.*]] = fir.shape %[[VAL_7]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[VAL_1]](%[[VAL_8]]) dummy_scope %[[VAL_3]] {uniq_name = "_QMchar_elem_byvalFfoo4Ej"} : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>) +! CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[VAL_1]](%[[VAL_8]]) dummy_scope %[[VAL_3]] arg {{[0-9]+}} {uniq_name = "_QMchar_elem_byvalFfoo4Ej"} : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>) ! CHECK: %[[VAL_10:.*]] = arith.constant 1 : index ! CHECK: %[[VAL_11:.*]] = hlfir.designate %[[VAL_9]]#0 (%[[VAL_10]]) : (!fir.ref<!fir.array<10xi32>>, index) -> !fir.ref<i32> ! CHECK: %[[VAL_12:.*]] = fir.load %[[VAL_11]] : !fir.ref<i32> @@ -186,10 +186,10 @@ end subroutine ! CHECK: %[[VAL_2:.*]] = fir.dummy_scope : !fir.dscope ! CHECK: %[[VAL_3:.*]] = arith.constant 10 : index ! CHECK: %[[VAL_4:.*]] = fir.shape %[[VAL_3]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_4]]) dummy_scope %[[VAL_2]] {uniq_name = "_QMchar_elem_byvalFfoo5Ei"} : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>) +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_4]]) dummy_scope %[[VAL_2]] arg {{[0-9]+}} {uniq_name = "_QMchar_elem_byvalFfoo5Ei"} : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>) ! CHECK: %[[VAL_6:.*]] = arith.constant 10 : index ! CHECK: %[[VAL_7:.*]] = fir.shape %[[VAL_6]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_8:.*]]:2 = hlfir.declare %[[VAL_1]](%[[VAL_7]]) dummy_scope %[[VAL_2]] {uniq_name = "_QMchar_elem_byvalFfoo5Ej"} : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>) +! CHECK: %[[VAL_8:.*]]:2 = hlfir.declare %[[VAL_1]](%[[VAL_7]]) dummy_scope %[[VAL_2]] arg {{[0-9]+}} {uniq_name = "_QMchar_elem_byvalFfoo5Ej"} : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>) ! CHECK: %[[VAL_9:.*]] = fir.address_of(@_QQclX68656C6C6F) : !fir.ref<!fir.char<1,5>> ! CHECK: %[[VAL_10:.*]] = arith.constant 5 : index ! CHECK: %[[VAL_11:.*]]:2 = hlfir.declare %[[VAL_9]] typeparams %[[VAL_10]] {fortran_attrs = #fir.var_attrs<parameter>, uniq_name = "_QQclX68656C6C6F"} : (!fir.ref<!fir.char<1,5>>, index) -> (!fir.ref<!fir.char<1,5>>, !fir.ref<!fir.char<1,5>>) diff --git a/flang/test/Lower/array-elemental-calls-char-dynamic.f90 b/flang/test/Lower/array-elemental-calls-char-dynamic.f90 index 9671669..24b7989 100644 --- a/flang/test/Lower/array-elemental-calls-char-dynamic.f90 +++ b/flang/test/Lower/array-elemental-calls-char-dynamic.f90 @@ -19,8 +19,8 @@ end subroutine ! CHECK-SAME: %[[ARG0:.*]]: !fir.box<!fir.array<?x!fir.char<1,?>>> {fir.bindc_name = "c"}, ! CHECK-SAME: %[[ARG1:.*]]: !fir.box<!fir.array<?xi64>> {fir.bindc_name = "vector_subscript"}) { ! CHECK: %[[VAL_0:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %[[VAL_0]] {uniq_name = "_QFtest_vector_subscripted_argEc"} : (!fir.box<!fir.array<?x!fir.char<1,?>>>, !fir.dscope) -> (!fir.box<!fir.array<?x!fir.char<1,?>>>, !fir.box<!fir.array<?x!fir.char<1,?>>>) -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %[[VAL_0]] {uniq_name = "_QFtest_vector_subscripted_argEvector_subscript"} : (!fir.box<!fir.array<?xi64>>, !fir.dscope) -> (!fir.box<!fir.array<?xi64>>, !fir.box<!fir.array<?xi64>>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %[[VAL_0]] arg {{[0-9]+}} {uniq_name = "_QFtest_vector_subscripted_argEc"} : (!fir.box<!fir.array<?x!fir.char<1,?>>>, !fir.dscope) -> (!fir.box<!fir.array<?x!fir.char<1,?>>>, !fir.box<!fir.array<?x!fir.char<1,?>>>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %[[VAL_0]] arg {{[0-9]+}} {uniq_name = "_QFtest_vector_subscripted_argEvector_subscript"} : (!fir.box<!fir.array<?xi64>>, !fir.dscope) -> (!fir.box<!fir.array<?xi64>>, !fir.box<!fir.array<?xi64>>) ! CHECK: %[[VAL_3:.*]] = fir.box_elesize %[[VAL_1]]#1 : (!fir.box<!fir.array<?x!fir.char<1,?>>>) -> index ! CHECK: %[[VAL_4:.*]] = arith.constant 0 : index ! CHECK: %[[VAL_5:.*]]:3 = fir.box_dims %[[VAL_2]]#0, %[[VAL_4]] : (!fir.box<!fir.array<?xi64>>, index) -> (index, index, index) @@ -80,8 +80,8 @@ end subroutine ! CHECK-SAME: %[[ARG0:.*]]: !fir.box<!fir.array<?x!fir.char<1,?>>> {fir.bindc_name = "c"}, ! CHECK-SAME: %[[ARG1:.*]]: !fir.box<!fir.array<?xf32>> {fir.bindc_name = "x"}) { ! CHECK: %[[VAL_0:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %[[VAL_0]] {uniq_name = "_QFtest_module_variableEc"} : (!fir.box<!fir.array<?x!fir.char<1,?>>>, !fir.dscope) -> (!fir.box<!fir.array<?x!fir.char<1,?>>>, !fir.box<!fir.array<?x!fir.char<1,?>>>) -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %[[VAL_0]] {uniq_name = "_QFtest_module_variableEx"} : (!fir.box<!fir.array<?xf32>>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.box<!fir.array<?xf32>>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %[[VAL_0]] arg {{[0-9]+}} {uniq_name = "_QFtest_module_variableEc"} : (!fir.box<!fir.array<?x!fir.char<1,?>>>, !fir.dscope) -> (!fir.box<!fir.array<?x!fir.char<1,?>>>, !fir.box<!fir.array<?x!fir.char<1,?>>>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %[[VAL_0]] arg {{[0-9]+}} {uniq_name = "_QFtest_module_variableEx"} : (!fir.box<!fir.array<?xf32>>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.box<!fir.array<?xf32>>) ! CHECK: %[[VAL_3:.*]] = arith.constant 0 : index ! CHECK: %[[VAL_4:.*]]:3 = fir.box_dims %[[VAL_2]]#0, %[[VAL_3]] : (!fir.box<!fir.array<?xf32>>, index) -> (index, index, index) ! CHECK: %[[VAL_5:.*]] = fir.shape %[[VAL_4]]#1 : (index) -> !fir.shape<1> @@ -129,9 +129,9 @@ end subroutine ! CHECK-SAME: %[[ARG1:.*]]: !fir.box<!fir.array<?xf32>> {fir.bindc_name = "x"}, ! CHECK-SAME: %[[ARG2:.*]]: !fir.box<!fir.array<?xf32>> {fir.bindc_name = "opt", fir.optional}) { ! CHECK: %[[VAL_0:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[ARG2]] dummy_scope %[[VAL_0]] {fortran_attrs = #fir.var_attrs<optional>, uniq_name = "_QFtest_presentEopt"} : (!fir.box<!fir.array<?xf32>>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.box<!fir.array<?xf32>>) -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %[[VAL_0]] {uniq_name = "_QFtest_presentEres"} : (!fir.box<!fir.array<?x!fir.char<1,?>>>, !fir.dscope) -> (!fir.box<!fir.array<?x!fir.char<1,?>>>, !fir.box<!fir.array<?x!fir.char<1,?>>>) -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %[[VAL_0]] {uniq_name = "_QFtest_presentEx"} : (!fir.box<!fir.array<?xf32>>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.box<!fir.array<?xf32>>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[ARG2]] dummy_scope %[[VAL_0]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<optional>, uniq_name = "_QFtest_presentEopt"} : (!fir.box<!fir.array<?xf32>>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.box<!fir.array<?xf32>>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %[[VAL_0]] arg {{[0-9]+}} {uniq_name = "_QFtest_presentEres"} : (!fir.box<!fir.array<?x!fir.char<1,?>>>, !fir.dscope) -> (!fir.box<!fir.array<?x!fir.char<1,?>>>, !fir.box<!fir.array<?x!fir.char<1,?>>>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %[[VAL_0]] arg {{[0-9]+}} {uniq_name = "_QFtest_presentEx"} : (!fir.box<!fir.array<?xf32>>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.box<!fir.array<?xf32>>) ! CHECK: %[[VAL_4:.*]] = fir.is_present %[[VAL_1]]#0 : (!fir.box<!fir.array<?xf32>>) -> i1 ! CHECK: %[[VAL_5:.*]] = arith.constant 0 : index ! CHECK: %[[VAL_6:.*]]:3 = fir.box_dims %[[VAL_3]]#0, %[[VAL_5]] : (!fir.box<!fir.array<?xf32>>, index) -> (index, index, index) @@ -197,9 +197,9 @@ end subroutine ! CHECK-SAME: %[[ARG1:.*]]: !fir.class<!fir.array<?x!fir.type<_QFtest_polymorphicTt>>> {fir.bindc_name = "p1"}, ! CHECK-SAME: %[[ARG2:.*]]: !fir.class<!fir.array<?x!fir.type<_QFtest_polymorphicTt>>> {fir.bindc_name = "p2"}) { ! CHECK: %[[VAL_0:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %[[VAL_0]] {fortran_attrs = #fir.var_attrs<intent_in>, uniq_name = "_QFtest_polymorphicEp1"} : (!fir.class<!fir.array<?x!fir.type<_QFtest_polymorphicTt>>>, !fir.dscope) -> (!fir.class<!fir.array<?x!fir.type<_QFtest_polymorphicTt>>>, !fir.class<!fir.array<?x!fir.type<_QFtest_polymorphicTt>>>) -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[ARG2]] dummy_scope %[[VAL_0]] {fortran_attrs = #fir.var_attrs<intent_in>, uniq_name = "_QFtest_polymorphicEp2"} : (!fir.class<!fir.array<?x!fir.type<_QFtest_polymorphicTt>>>, !fir.dscope) -> (!fir.class<!fir.array<?x!fir.type<_QFtest_polymorphicTt>>>, !fir.class<!fir.array<?x!fir.type<_QFtest_polymorphicTt>>>) -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %[[VAL_0]] {uniq_name = "_QFtest_polymorphicEres"} : (!fir.box<!fir.array<?x!fir.char<1,?>>>, !fir.dscope) -> (!fir.box<!fir.array<?x!fir.char<1,?>>>, !fir.box<!fir.array<?x!fir.char<1,?>>>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %[[VAL_0]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<intent_in>, uniq_name = "_QFtest_polymorphicEp1"} : (!fir.class<!fir.array<?x!fir.type<_QFtest_polymorphicTt>>>, !fir.dscope) -> (!fir.class<!fir.array<?x!fir.type<_QFtest_polymorphicTt>>>, !fir.class<!fir.array<?x!fir.type<_QFtest_polymorphicTt>>>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[ARG2]] dummy_scope %[[VAL_0]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<intent_in>, uniq_name = "_QFtest_polymorphicEp2"} : (!fir.class<!fir.array<?x!fir.type<_QFtest_polymorphicTt>>>, !fir.dscope) -> (!fir.class<!fir.array<?x!fir.type<_QFtest_polymorphicTt>>>, !fir.class<!fir.array<?x!fir.type<_QFtest_polymorphicTt>>>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %[[VAL_0]] arg {{[0-9]+}} {uniq_name = "_QFtest_polymorphicEres"} : (!fir.box<!fir.array<?x!fir.char<1,?>>>, !fir.dscope) -> (!fir.box<!fir.array<?x!fir.char<1,?>>>, !fir.box<!fir.array<?x!fir.char<1,?>>>) ! CHECK: %[[VAL_4:.*]] = arith.constant 0 : index ! CHECK: %[[VAL_5:.*]]:3 = fir.box_dims %[[VAL_1]]#0, %[[VAL_4]] : (!fir.class<!fir.array<?x!fir.type<_QFtest_polymorphicTt>>>, index) -> (index, index, index) ! CHECK: %[[VAL_6:.*]] = fir.shape %[[VAL_5]]#1 : (index) -> !fir.shape<1> @@ -258,7 +258,7 @@ end subroutine ! CHECK-LABEL: func.func @_QPtest_value( ! CHECK-SAME: %[[ARG0:.*]]: !fir.box<!fir.array<?x!fir.char<1,?>>> {fir.bindc_name = "c"}) { ! CHECK: %[[VAL_0:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %[[VAL_0]] {uniq_name = "_QFtest_valueEc"} : (!fir.box<!fir.array<?x!fir.char<1,?>>>, !fir.dscope) -> (!fir.box<!fir.array<?x!fir.char<1,?>>>, !fir.box<!fir.array<?x!fir.char<1,?>>>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %[[VAL_0]] arg {{[0-9]+}} {uniq_name = "_QFtest_valueEc"} : (!fir.box<!fir.array<?x!fir.char<1,?>>>, !fir.dscope) -> (!fir.box<!fir.array<?x!fir.char<1,?>>>, !fir.box<!fir.array<?x!fir.char<1,?>>>) ! CHECK: %[[VAL_2:.*]] = arith.constant 0 : index ! CHECK: %[[VAL_3:.*]]:3 = fir.box_dims %[[VAL_1]]#0, %[[VAL_2]] : (!fir.box<!fir.array<?x!fir.char<1,?>>>, index) -> (index, index, index) ! CHECK: %[[VAL_4:.*]] = fir.shape %[[VAL_3]]#1 : (index) -> !fir.shape<1> diff --git a/flang/test/Lower/array-elemental-calls-char.f90 b/flang/test/Lower/array-elemental-calls-char.f90 index a75b335..f99bce4 100644 --- a/flang/test/Lower/array-elemental-calls-char.f90 +++ b/flang/test/Lower/array-elemental-calls-char.f90 @@ -31,10 +31,10 @@ end subroutine ! CHECK: %[[VAL_4:.*]] = fir.convert %[[VAL_3]]#0 : (!fir.ref<!fir.char<1,?>>) -> !fir.ref<!fir.array<10x!fir.char<1,?>>> ! CHECK: %[[VAL_5:.*]] = arith.constant 10 : index ! CHECK: %[[VAL_6:.*]] = fir.shape %[[VAL_5]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_4]](%[[VAL_6]]) typeparams %[[VAL_3]]#1 dummy_scope %[[VAL_2]] {uniq_name = "_QMchar_elemFfoo1Ec"} : (!fir.ref<!fir.array<10x!fir.char<1,?>>>, !fir.shape<1>, index, !fir.dscope) -> (!fir.box<!fir.array<10x!fir.char<1,?>>>, !fir.ref<!fir.array<10x!fir.char<1,?>>>) +! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_4]](%[[VAL_6]]) typeparams %[[VAL_3]]#1 dummy_scope %[[VAL_2]] arg {{[0-9]+}} {uniq_name = "_QMchar_elemFfoo1Ec"} : (!fir.ref<!fir.array<10x!fir.char<1,?>>>, !fir.shape<1>, index, !fir.dscope) -> (!fir.box<!fir.array<10x!fir.char<1,?>>>, !fir.ref<!fir.array<10x!fir.char<1,?>>>) ! CHECK: %[[VAL_8:.*]] = arith.constant 10 : index ! CHECK: %[[VAL_9:.*]] = fir.shape %[[VAL_8]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_10:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_9]]) dummy_scope %[[VAL_2]] {uniq_name = "_QMchar_elemFfoo1Ei"} : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>) +! CHECK: %[[VAL_10:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_9]]) dummy_scope %[[VAL_2]] arg {{[0-9]+}} {uniq_name = "_QMchar_elemFfoo1Ei"} : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>) ! CHECK: %[[VAL_11:.*]] = hlfir.elemental %[[VAL_6]] unordered : (!fir.shape<1>) -> !hlfir.expr<10xi32> { ! CHECK: ^bb0(%[[VAL_12:.*]]: index): ! CHECK: %[[VAL_13:.*]] = hlfir.designate %[[VAL_7]]#0 (%[[VAL_12]]) typeparams %[[VAL_3]]#1 : (!fir.box<!fir.array<10x!fir.char<1,?>>>, index, index) -> !fir.boxchar<1> @@ -60,10 +60,10 @@ end subroutine ! CHECK: %[[VAL_5:.*]] = arith.constant 10 : index ! CHECK: %[[VAL_6:.*]] = arith.constant 10 : index ! CHECK: %[[VAL_7:.*]] = fir.shape %[[VAL_6]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_8:.*]]:2 = hlfir.declare %[[VAL_4]](%[[VAL_7]]) typeparams %[[VAL_5]] dummy_scope %[[VAL_2]] {uniq_name = "_QMchar_elemFfoo1bEc"} : (!fir.ref<!fir.array<10x!fir.char<1,10>>>, !fir.shape<1>, index, !fir.dscope) -> (!fir.ref<!fir.array<10x!fir.char<1,10>>>, !fir.ref<!fir.array<10x!fir.char<1,10>>>) +! CHECK: %[[VAL_8:.*]]:2 = hlfir.declare %[[VAL_4]](%[[VAL_7]]) typeparams %[[VAL_5]] dummy_scope %[[VAL_2]] arg {{[0-9]+}} {uniq_name = "_QMchar_elemFfoo1bEc"} : (!fir.ref<!fir.array<10x!fir.char<1,10>>>, !fir.shape<1>, index, !fir.dscope) -> (!fir.ref<!fir.array<10x!fir.char<1,10>>>, !fir.ref<!fir.array<10x!fir.char<1,10>>>) ! CHECK: %[[VAL_9:.*]] = arith.constant 10 : index ! CHECK: %[[VAL_10:.*]] = fir.shape %[[VAL_9]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_11:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_10]]) dummy_scope %[[VAL_2]] {uniq_name = "_QMchar_elemFfoo1bEi"} : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>) +! CHECK: %[[VAL_11:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_10]]) dummy_scope %[[VAL_2]] arg {{[0-9]+}} {uniq_name = "_QMchar_elemFfoo1bEi"} : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>) ! CHECK: %[[VAL_12:.*]] = hlfir.elemental %[[VAL_7]] unordered : (!fir.shape<1>) -> !hlfir.expr<10xi32> { ! CHECK: ^bb0(%[[VAL_13:.*]]: index): ! CHECK: %[[VAL_14:.*]] = hlfir.designate %[[VAL_8]]#0 (%[[VAL_13]]) typeparams %[[VAL_5]] : (!fir.ref<!fir.array<10x!fir.char<1,10>>>, index, index) -> !fir.ref<!fir.char<1,10>> @@ -87,13 +87,13 @@ end subroutine ! CHECK-SAME: %[[VAL_2:.*]]: !fir.boxchar<1> {fir.bindc_name = "c"}) { ! CHECK: %[[VAL_3:.*]] = fir.dummy_scope : !fir.dscope ! CHECK: %[[VAL_4:.*]]:2 = fir.unboxchar %[[VAL_2]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index) -! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_4]]#0 typeparams %[[VAL_4]]#1 dummy_scope %[[VAL_3]] {uniq_name = "_QMchar_elemFfoo2Ec"} : (!fir.ref<!fir.char<1,?>>, index, !fir.dscope) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>) +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_4]]#0 typeparams %[[VAL_4]]#1 dummy_scope %[[VAL_3]] arg {{[0-9]+}} {uniq_name = "_QMchar_elemFfoo2Ec"} : (!fir.ref<!fir.char<1,?>>, index, !fir.dscope) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>) ! CHECK: %[[VAL_6:.*]] = arith.constant 10 : index ! CHECK: %[[VAL_7:.*]] = fir.shape %[[VAL_6]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_8:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_7]]) dummy_scope %[[VAL_3]] {uniq_name = "_QMchar_elemFfoo2Ei"} : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>) +! CHECK: %[[VAL_8:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_7]]) dummy_scope %[[VAL_3]] arg {{[0-9]+}} {uniq_name = "_QMchar_elemFfoo2Ei"} : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>) ! CHECK: %[[VAL_9:.*]] = arith.constant 10 : index ! CHECK: %[[VAL_10:.*]] = fir.shape %[[VAL_9]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_11:.*]]:2 = hlfir.declare %[[VAL_1]](%[[VAL_10]]) dummy_scope %[[VAL_3]] {uniq_name = "_QMchar_elemFfoo2Ej"} : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>) +! CHECK: %[[VAL_11:.*]]:2 = hlfir.declare %[[VAL_1]](%[[VAL_10]]) dummy_scope %[[VAL_3]] arg {{[0-9]+}} {uniq_name = "_QMchar_elemFfoo2Ej"} : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>) ! CHECK: %[[VAL_12:.*]] = hlfir.elemental %[[VAL_10]] unordered : (!fir.shape<1>) -> !hlfir.expr<10xi32> { ! CHECK: ^bb0(%[[VAL_13:.*]]: index): ! CHECK: %[[VAL_14:.*]] = hlfir.designate %[[VAL_11]]#0 (%[[VAL_13]]) : (!fir.ref<!fir.array<10xi32>>, index) -> !fir.ref<i32> @@ -118,13 +118,13 @@ end subroutine ! CHECK: %[[VAL_4:.*]]:2 = fir.unboxchar %[[VAL_2]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index) ! CHECK: %[[VAL_5:.*]] = fir.convert %[[VAL_4]]#0 : (!fir.ref<!fir.char<1,?>>) -> !fir.ref<!fir.char<1,10>> ! CHECK: %[[VAL_6:.*]] = arith.constant 10 : index -! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_5]] typeparams %[[VAL_6]] dummy_scope %[[VAL_3]] {uniq_name = "_QMchar_elemFfoo2bEc"} : (!fir.ref<!fir.char<1,10>>, index, !fir.dscope) -> (!fir.ref<!fir.char<1,10>>, !fir.ref<!fir.char<1,10>>) +! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_5]] typeparams %[[VAL_6]] dummy_scope %[[VAL_3]] arg {{[0-9]+}} {uniq_name = "_QMchar_elemFfoo2bEc"} : (!fir.ref<!fir.char<1,10>>, index, !fir.dscope) -> (!fir.ref<!fir.char<1,10>>, !fir.ref<!fir.char<1,10>>) ! CHECK: %[[VAL_8:.*]] = arith.constant 10 : index ! CHECK: %[[VAL_9:.*]] = fir.shape %[[VAL_8]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_10:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_9]]) dummy_scope %[[VAL_3]] {uniq_name = "_QMchar_elemFfoo2bEi"} : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>) +! CHECK: %[[VAL_10:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_9]]) dummy_scope %[[VAL_3]] arg {{[0-9]+}} {uniq_name = "_QMchar_elemFfoo2bEi"} : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>) ! CHECK: %[[VAL_11:.*]] = arith.constant 10 : index ! CHECK: %[[VAL_12:.*]] = fir.shape %[[VAL_11]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_13:.*]]:2 = hlfir.declare %[[VAL_1]](%[[VAL_12]]) dummy_scope %[[VAL_3]] {uniq_name = "_QMchar_elemFfoo2bEj"} : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>) +! CHECK: %[[VAL_13:.*]]:2 = hlfir.declare %[[VAL_1]](%[[VAL_12]]) dummy_scope %[[VAL_3]] arg {{[0-9]+}} {uniq_name = "_QMchar_elemFfoo2bEj"} : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>) ! CHECK: %[[VAL_14:.*]] = hlfir.elemental %[[VAL_12]] unordered : (!fir.shape<1>) -> !hlfir.expr<10xi32> { ! CHECK: ^bb0(%[[VAL_15:.*]]: index): ! CHECK: %[[VAL_16:.*]] = fir.emboxchar %[[VAL_7]]#0, %[[VAL_6]] : (!fir.ref<!fir.char<1,10>>, index) -> !fir.boxchar<1> @@ -148,10 +148,10 @@ end subroutine ! CHECK: %[[VAL_3:.*]] = fir.dummy_scope : !fir.dscope ! CHECK: %[[VAL_4:.*]] = arith.constant 10 : index ! CHECK: %[[VAL_5:.*]] = fir.shape %[[VAL_4]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_5]]) dummy_scope %[[VAL_3]] {uniq_name = "_QMchar_elemFfoo3Ei"} : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>) +! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_5]]) dummy_scope %[[VAL_3]] arg {{[0-9]+}} {uniq_name = "_QMchar_elemFfoo3Ei"} : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>) ! CHECK: %[[VAL_7:.*]] = arith.constant 10 : index ! CHECK: %[[VAL_8:.*]] = fir.shape %[[VAL_7]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[VAL_1]](%[[VAL_8]]) dummy_scope %[[VAL_3]] {uniq_name = "_QMchar_elemFfoo3Ej"} : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>) +! CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[VAL_1]](%[[VAL_8]]) dummy_scope %[[VAL_3]] arg {{[0-9]+}} {uniq_name = "_QMchar_elemFfoo3Ej"} : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>) ! CHECK: %[[VAL_10:.*]] = hlfir.elemental %[[VAL_8]] unordered : (!fir.shape<1>) -> !hlfir.expr<10xi64> { ! CHECK: ^bb0(%[[VAL_11:.*]]: index): ! CHECK: %[[VAL_12:.*]] = hlfir.designate %[[VAL_9]]#0 (%[[VAL_11]]) : (!fir.ref<!fir.array<10xi32>>, index) -> !fir.ref<i32> @@ -197,10 +197,10 @@ end subroutine ! CHECK: %[[VAL_2:.*]] = fir.dummy_scope : !fir.dscope ! CHECK: %[[VAL_3:.*]] = arith.constant 10 : index ! CHECK: %[[VAL_4:.*]] = fir.shape %[[VAL_3]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_4]]) dummy_scope %[[VAL_2]] {uniq_name = "_QMchar_elemFfoo4Ei"} : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>) +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_4]]) dummy_scope %[[VAL_2]] arg {{[0-9]+}} {uniq_name = "_QMchar_elemFfoo4Ei"} : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>) ! CHECK: %[[VAL_6:.*]] = arith.constant 10 : index ! CHECK: %[[VAL_7:.*]] = fir.shape %[[VAL_6]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_8:.*]]:2 = hlfir.declare %[[VAL_1]](%[[VAL_7]]) dummy_scope %[[VAL_2]] {uniq_name = "_QMchar_elemFfoo4Ej"} : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>) +! CHECK: %[[VAL_8:.*]]:2 = hlfir.declare %[[VAL_1]](%[[VAL_7]]) dummy_scope %[[VAL_2]] arg {{[0-9]+}} {uniq_name = "_QMchar_elemFfoo4Ej"} : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>) ! CHECK: %[[VAL_9:.*]] = fir.address_of(@_QQclX68656C6C6F) : !fir.ref<!fir.char<1,5>> ! CHECK: %[[VAL_10:.*]] = arith.constant 5 : index ! CHECK: %[[VAL_11:.*]]:2 = hlfir.declare %[[VAL_9]] typeparams %[[VAL_10]] {fortran_attrs = #fir.var_attrs<parameter>, uniq_name = "_QQclX68656C6C6F"} : (!fir.ref<!fir.char<1,5>>, index) -> (!fir.ref<!fir.char<1,5>>, !fir.ref<!fir.char<1,5>>) @@ -239,7 +239,7 @@ end subroutine ! CHECK: %[[VAL_3:.*]] = fir.convert %[[VAL_2]]#0 : (!fir.ref<!fir.char<1,?>>) -> !fir.ref<!fir.array<10x!fir.char<1,?>>> ! CHECK: %[[VAL_4:.*]] = arith.constant 10 : index ! CHECK: %[[VAL_5:.*]] = fir.shape %[[VAL_4]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_3]](%[[VAL_5]]) typeparams %[[VAL_2]]#1 dummy_scope %[[VAL_1]] {uniq_name = "_QMchar_elemFfoo6Ec"} : (!fir.ref<!fir.array<10x!fir.char<1,?>>>, !fir.shape<1>, index, !fir.dscope) -> (!fir.box<!fir.array<10x!fir.char<1,?>>>, !fir.ref<!fir.array<10x!fir.char<1,?>>>) +! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_3]](%[[VAL_5]]) typeparams %[[VAL_2]]#1 dummy_scope %[[VAL_1]] arg {{[0-9]+}} {uniq_name = "_QMchar_elemFfoo6Ec"} : (!fir.ref<!fir.array<10x!fir.char<1,?>>>, !fir.shape<1>, index, !fir.dscope) -> (!fir.box<!fir.array<10x!fir.char<1,?>>>, !fir.ref<!fir.array<10x!fir.char<1,?>>>) ! CHECK: %[[VAL_7:.*]] = fir.convert %c1_i64 : (i64) -> !fir.ref<!fir.char<1,?>> ! CHECK: %[[VAL_8:.*]]:2 = hlfir.declare %[[VAL_7]] typeparams %[[VAL_2]]#1 {fortran_attrs = #fir.var_attrs<intent_in>, uniq_name = "_QMchar_elemFelem_return_charEc"} : (!fir.ref<!fir.char<1,?>>, index) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>) ! CHECK: %[[VAL_9:.*]] = fir.convert %[[VAL_2]]#1 : (index) -> i64 diff --git a/flang/test/Lower/array-elemental-calls.f90 b/flang/test/Lower/array-elemental-calls.f90 index 853807b..93d2979 100644 --- a/flang/test/Lower/array-elemental-calls.f90 +++ b/flang/test/Lower/array-elemental-calls.f90 @@ -57,7 +57,7 @@ subroutine test_loop_order(i, j) integer, intent(in) :: j end function end interface - + i = 42 + pure_func(j) i = 42 + impure_func(j) end subroutine diff --git a/flang/test/Lower/array-expression-assumed-size.f90 b/flang/test/Lower/array-expression-assumed-size.f90 index a498148..b51dc00 100644 --- a/flang/test/Lower/array-expression-assumed-size.f90 +++ b/flang/test/Lower/array-expression-assumed-size.f90 @@ -16,8 +16,8 @@ end subroutine assumed_size_forall_test ! CHECK-LABEL: func @_QPassumed_size_test( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.array<10x?xi32>>{{.*}}) { -! CHECK: %[[VAL_1A:.*]] = fir.convert %c10{{.*}} : (i64) -> index -! CHECK: %[[VAL_1B:.*]] = arith.cmpi sgt, %[[VAL_1A]], %c0{{.*}} : index +! CHECK: %[[VAL_1A:.*]] = fir.convert %c10{{.*}} : (i64) -> index +! CHECK: %[[VAL_1B:.*]] = arith.cmpi sgt, %[[VAL_1A]], %c0{{.*}} : index ! CHECK: %[[VAL_1:.*]] = arith.select %[[VAL_1B]], %[[VAL_1A]], %c0{{.*}} : index ! CHECK: %[[VAL_2:.*]] = fir.assumed_size_extent : index ! CHECK: %[[VAL_3:.*]] = arith.constant 1 : index @@ -79,8 +79,8 @@ end subroutine assumed_size_forall_test ! CHECK-LABEL: func @_QPassumed_size_forall_test( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.array<10x?xi32>>{{.*}}) { ! CHECK: %[[VAL_1:.*]] = fir.alloca i32 {adapt.valuebyref, bindc_name = "i"} -! CHECK: %[[VAL_2A:.*]] = fir.convert %c10{{.*}} : (i64) -> index -! CHECK: %[[VAL_2B:.*]] = arith.cmpi sgt, %[[VAL_2A]], %c0{{.*}} : index +! CHECK: %[[VAL_2A:.*]] = fir.convert %c10{{.*}} : (i64) -> index +! CHECK: %[[VAL_2B:.*]] = arith.cmpi sgt, %[[VAL_2A]], %c0{{.*}} : index ! CHECK: %[[VAL_2:.*]] = arith.select %[[VAL_2B]], %[[VAL_2A]], %c0{{.*}} : index ! CHECK: %[[VAL_3:.*]] = fir.assumed_size_extent : index ! CHECK: %[[VAL_4:.*]] = arith.constant 2 : i32 diff --git a/flang/test/Lower/array-substring.f90 b/flang/test/Lower/array-substring.f90 index 7544fbb..0ede04f 100644 --- a/flang/test/Lower/array-substring.f90 +++ b/flang/test/Lower/array-substring.f90 @@ -46,5 +46,5 @@ function test(C) logical :: test(1) character*12 C(1) - test = C(1:1)(1:8) == (/'ABCDabcd'/) + test = C(1:1)(1:8) == (/'ABCDabcd'/) end function test diff --git a/flang/test/Lower/array-wide-char.f90 b/flang/test/Lower/array-wide-char.f90 index 8bad280..44fcd45 100644 --- a/flang/test/Lower/array-wide-char.f90 +++ b/flang/test/Lower/array-wide-char.f90 @@ -2,7 +2,7 @@ character(LEN=128, KIND=4), PARAMETER :: conarr(3) = & [ character(128,4) :: "now is the time", "for all good men to come", & - "to the aid of the country" ] + "to the aid of the country" ] character(LEN=10, KIND=4) :: arr(3) = & [ character(10,4) :: "good buddy", "best buddy", " " ] call action_on_char4(conarr) diff --git a/flang/test/Lower/array.f90 b/flang/test/Lower/array.f90 index 7101757..cd12d7f 100644 --- a/flang/test/Lower/array.f90 +++ b/flang/test/Lower/array.f90 @@ -93,7 +93,7 @@ subroutine s(i,j,k,ii,jj,kk,a1,a2,a3,a4,a5,a6,a7) ! CHECK: fir.coordinate_of %[[a7]], %[[t7]] : ! CHECK-LABEL: EndIoStatement print *, a7(kk, jj, ii) - + end subroutine s ! CHECK-LABEL: range diff --git a/flang/test/Lower/assignment.f90 b/flang/test/Lower/assignment.f90 index defeec5..94d11da 100644 --- a/flang/test/Lower/assignment.f90 +++ b/flang/test/Lower/assignment.f90 @@ -26,7 +26,7 @@ end integer function negi(a) integer :: a negi = -a -end +end ! CHECK-LABEL: func @_QPnegi( ! CHECK-SAME: %[[A:.*]]: !fir.ref<i32> {fir.bindc_name = "a"}) -> i32 { @@ -41,7 +41,7 @@ end real function negr(a) real :: a negr = -a -end +end ! CHECK-LABEL: func @_QPnegr( ! CHECK-SAME: %[[A:.*]]: !fir.ref<f32> {fir.bindc_name = "a"}) -> f32 { @@ -55,7 +55,7 @@ end complex function negc(a) complex :: a negc = -a -end +end ! CHECK-LABEL: func @_QPnegc( ! CHECK-SAME: %[[A:.*]]: !fir.ref<complex<f32>> {fir.bindc_name = "a"}) -> complex<f32> { diff --git a/flang/test/Lower/assumed-shape-callee.f90 b/flang/test/Lower/assumed-shape-callee.f90 index a40ee10..69abf05 100644 --- a/flang/test/Lower/assumed-shape-callee.f90 +++ b/flang/test/Lower/assumed-shape-callee.f90 @@ -8,7 +8,7 @@ ! of making a new fir.box and this would break all these tests. In fact, for non ! contiguous arrays, this is the case. Find a better way to tests symbol lowering/mapping. -! CHECK-LABEL: func @_QPtest_assumed_shape_1(%arg0: !fir.box<!fir.array<?xi32>> {fir.bindc_name = "x", fir.contiguous}) +! CHECK-LABEL: func @_QPtest_assumed_shape_1(%arg0: !fir.box<!fir.array<?xi32>> {fir.bindc_name = "x", fir.contiguous}) subroutine test_assumed_shape_1(x) integer, contiguous :: x(:) ! CHECK: %[[addr:.*]] = fir.box_addr %arg0 : (!fir.box<!fir.array<?xi32>>) -> !fir.ref<!fir.array<?xi32>> diff --git a/flang/test/Lower/assumed-shape-caller.f90 b/flang/test/Lower/assumed-shape-caller.f90 index 5277dc7..5a289e6 100644 --- a/flang/test/Lower/assumed-shape-caller.f90 +++ b/flang/test/Lower/assumed-shape-caller.f90 @@ -59,7 +59,7 @@ subroutine test_vector_subcripted_section_to_box(v, x) end subroutine end interface integer :: v(:) - real :: x(:) + real :: x(:) call takes_box(x(v)) ! CHECK: %[[VAL_2:.*]] = arith.constant 1 : index ! CHECK: %[[VAL_3:.*]] = arith.constant 0 : index diff --git a/flang/test/Lower/big-integer-parameter.f90 b/flang/test/Lower/big-integer-parameter.f90 index ca90b8a..b991dd9 100644 --- a/flang/test/Lower/big-integer-parameter.f90 +++ b/flang/test/Lower/big-integer-parameter.f90 @@ -31,7 +31,7 @@ end ! CHECK-LABEL: fir.global internal @_QFECx constant : i128 { ! CHECK-NEXT: %{{.*}} = arith.constant 9223372036854775808 : i128 - + ! CHECK-LABEL: fir.global internal @_QFECy constant : i128 { ! CHECK-NEXT: %{{.*}} = arith.constant -9223372036854775809 : i128 diff --git a/flang/test/Lower/box-address.f90 b/flang/test/Lower/box-address.f90 index 04f1418..d43fb55 100644 --- a/flang/test/Lower/box-address.f90 +++ b/flang/test/Lower/box-address.f90 @@ -18,7 +18,7 @@ end module m3 ! CHECK-LABEL: func.func @_QMm3Pchk( ! CHECK-SAME: %[[ARG0:.*]]: !fir.class<!fir.array<3x!fir.type<_QMm3Tx1{ix1:i32}>>> {fir.bindc_name = "c1"}) { ! CHECK: %[[DUMMY_SCOPE:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %[[DUMMY_SCOPE]] {uniq_name = "_QMm3FdummyEc1"} : (!fir.class<!fir.array<3x!fir.type<_QMm3Tx1{ix1:i32}>>>, !fir.dscope) -> (!fir.class<!fir.array<3x!fir.type<_QMm3Tx1{ix1:i32}>>>, !fir.class<!fir.array<3x!fir.type<_QMm3Tx1{ix1:i32}>>>) +! CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %[[DUMMY_SCOPE]] {{.*}} {uniq_name = "_QMm3FdummyEc1"} : (!fir.class<!fir.array<3x!fir.type<_QMm3Tx1{ix1:i32}>>>, !fir.dscope) -> (!fir.class<!fir.array<3x!fir.type<_QMm3Tx1{ix1:i32}>>>, !fir.class<!fir.array<3x!fir.type<_QMm3Tx1{ix1:i32}>>>) subroutine s1 use m3 diff --git a/flang/test/Lower/c-interoperability.f90 b/flang/test/Lower/c-interoperability.f90 index cbd6c1f..613f874 100644 --- a/flang/test/Lower/c-interoperability.f90 +++ b/flang/test/Lower/c-interoperability.f90 @@ -26,7 +26,7 @@ module c_interoperability_test end type thing_with_pointer type(thing_with_pointer) :: this_thing - + contains function get_a_thing() type(thing_with_pointer) :: get_a_thing diff --git a/flang/test/Lower/call-by-value-attr.f90 b/flang/test/Lower/call-by-value-attr.f90 index 14776be..9b90767 100644 --- a/flang/test/Lower/call-by-value-attr.f90 +++ b/flang/test/Lower/call-by-value-attr.f90 @@ -45,7 +45,7 @@ end subroutine subri ! CHECK: %[[VAL_1:.*]] = fir.dummy_scope : !fir.dscope ! CHECK: %[[VAL_2:.*]] = fir.alloca i32 ! CHECK: fir.store %[[VAL_0]] to %[[VAL_2]] : !fir.ref<i32> -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]] dummy_scope %[[VAL_1]] {fortran_attrs = #fir.var_attrs<value>, uniq_name = "_QFsubriEval"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]] dummy_scope %[[VAL_1]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<value>, uniq_name = "_QFsubriEval"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: fir.call @_QPtest_numeric_scalar_value(%[[VAL_3]]#0) fastmath<contract> : (!fir.ref<i32>) -> () ! CHECK: return ! CHECK: } diff --git a/flang/test/Lower/call-character-array-to-polymorphic-pointer.f90 b/flang/test/Lower/call-character-array-to-polymorphic-pointer.f90 index 8644a4a..b0f94a2 100644 --- a/flang/test/Lower/call-character-array-to-polymorphic-pointer.f90 +++ b/flang/test/Lower/call-character-array-to-polymorphic-pointer.f90 @@ -20,7 +20,7 @@ end subroutine char_explicit_shape_array ! CHECK: %[[VAL_3:.*]] = fir.convert %[[VAL_2]]#0 : (!fir.ref<!fir.char<1,?>>) -> !fir.ref<!fir.array<100x!fir.char<1,?>>> ! CHECK: %[[VAL_4:.*]] = arith.constant 100 : index ! CHECK: %[[VAL_5:.*]] = fir.shape %[[VAL_4]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_3]](%[[VAL_5]]) typeparams %[[VAL_2]]#1 dummy_scope %[[VAL_1]] {fortran_attrs = #fir.var_attrs<target>, uniq_name = "_QFchar_explicit_shape_arrayEa2"} : (!fir.ref<!fir.array<100x!fir.char<1,?>>>, !fir.shape<1>, index, !fir.dscope) -> (!fir.box<!fir.array<100x!fir.char<1,?>>>, !fir.ref<!fir.array<100x!fir.char<1,?>>>) +! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_3]](%[[VAL_5]]) typeparams %[[VAL_2]]#1 dummy_scope %[[VAL_1]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<target>, uniq_name = "_QFchar_explicit_shape_arrayEa2"} : (!fir.ref<!fir.array<100x!fir.char<1,?>>>, !fir.shape<1>, index, !fir.dscope) -> (!fir.box<!fir.array<100x!fir.char<1,?>>>, !fir.ref<!fir.array<100x!fir.char<1,?>>>) ! CHECK: %[[VAL_7:.*]] = fir.shape %[[VAL_4]] : (index) -> !fir.shape<1> ! CHECK: %[[VAL_8:.*]] = fir.embox %[[VAL_6]]#1(%[[VAL_7]]) typeparams %[[VAL_2]]#1 : (!fir.ref<!fir.array<100x!fir.char<1,?>>>, !fir.shape<1>, index) -> !fir.class<!fir.ptr<!fir.array<?xnone>>> ! CHECK: fir.store %[[VAL_8]] to %[[VAL_0]] : !fir.ref<!fir.class<!fir.ptr<!fir.array<?xnone>>>> diff --git a/flang/test/Lower/call-copy-in-out.f90 b/flang/test/Lower/call-copy-in-out.f90 index 1eb2c3f..65141dc 100644 --- a/flang/test/Lower/call-copy-in-out.f90 +++ b/flang/test/Lower/call-copy-in-out.f90 @@ -120,7 +120,7 @@ subroutine test_intent_out(x) ! CHECK: %[[cast:.*]] = fir.convert %[[addr]] : (!fir.heap<!fir.array<?xf32>>) -> !fir.ref<!fir.array<100xf32>> ! CHECK: fir.call @_QPbar_intent_out(%[[cast]]) {{.*}}: (!fir.ref<!fir.array<100xf32>>) -> () call bar_intent_out(x) - + ! CHECK: fir.if %[[not_contiguous]] ! CHECK: fir.call @_FortranACopyOutAssign ! CHECK: return @@ -224,7 +224,7 @@ subroutine test_char(x) ! CHECK: %[[VAL_32:.*]] = fir.convert %[[TMP_BOX_REF]] : (!fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.char<1,10>>>>>) -> !fir.ref<!fir.box<none>> ! CHECK: fir.call @_FortranACopyOutAssign(%[[VAL_31]], %[[VAL_32]], %{{.*}}, %{{.*}}) fastmath<contract> : (!fir.ref<!fir.box<none>>, !fir.ref<!fir.box<none>>, !fir.ref<i8>, i32) -> () ! CHECK: } - + character(10) :: x(:) call bar_char(x) ! CHECK: return diff --git a/flang/test/Lower/character-local-variables.f90 b/flang/test/Lower/character-local-variables.f90 index d5b959e..6325229 100644 --- a/flang/test/Lower/character-local-variables.f90 +++ b/flang/test/Lower/character-local-variables.f90 @@ -8,6 +8,7 @@ subroutine scalar_cst_len() character(10) :: c ! CHECK: fir.alloca !fir.char<1,10> {{{.*}}uniq_name = "_QFscalar_cst_lenEc"} + print *, c end subroutine ! CHECK-LABEL: func @_QPscalar_dyn_len @@ -19,12 +20,14 @@ subroutine scalar_dyn_len(l) ! CHECK: %[[is_positive:.*]] = arith.cmpi sgt, %[[lexpr]], %c0{{.*}} : i32 ! CHECK: %[[l:.*]] = arith.select %[[is_positive]], %[[lexpr]], %c0{{.*}} : i32 ! CHECK: fir.alloca !fir.char<1,?>(%[[l]] : i32) {{{.*}}uniq_name = "_QFscalar_dyn_lenEc"} + print *, c end subroutine ! CHECK-LABEL: func @_QPcst_array_cst_len subroutine cst_array_cst_len() character(10) :: c(20) ! CHECK: fir.alloca !fir.array<20x!fir.char<1,10>> {{{.*}}uniq_name = "_QFcst_array_cst_lenEc"} + print *, c(1) end subroutine ! CHECK-LABEL: func @_QPcst_array_dyn_len @@ -36,6 +39,7 @@ subroutine cst_array_dyn_len(l) ! CHECK: %[[is_positive:.*]] = arith.cmpi sgt, %[[lexpr]], %c0{{.*}} : i32 ! CHECK: %[[l:.*]] = arith.select %[[is_positive]], %[[lexpr]], %c0{{.*}} : i32 ! CHECK: fir.alloca !fir.array<10x!fir.char<1,?>>(%[[l]] : i32) {{{.*}}uniq_name = "_QFcst_array_dyn_lenEc"} + print *, c(1) end subroutine ! CHECK-LABEL: func @_QPdyn_array_cst_len @@ -48,6 +52,7 @@ subroutine dyn_array_cst_len(n) ! CHECK: %[[is_positive:.*]] = arith.cmpi sgt, %[[ni]], %c0{{.*}} : index ! CHECK: %[[extent:.*]] = arith.select %[[is_positive]], %[[ni]], %c0{{.*}} : index ! CHECK: fir.alloca !fir.array<?x!fir.char<1,10>>, %[[extent]] {{{.*}}uniq_name = "_QFdyn_array_cst_lenEc"} + print *, c(1) end subroutine ! CHECK: func @_QPdyn_array_dyn_len @@ -63,12 +68,14 @@ subroutine dyn_array_dyn_len(l, n) ! CHECK: %[[is_positive:.*]] = arith.cmpi sgt, %[[ni]], %c0{{.*}} : index ! CHECK: %[[extent:.*]] = arith.select %[[is_positive]], %[[ni]], %c0{{.*}} : index ! CHECK: fir.alloca !fir.array<?x!fir.char<1,?>>(%[[l]] : i32), %[[extent]] {{{.*}}uniq_name = "_QFdyn_array_dyn_lenEc"} + print *, c(1) end subroutine ! CHECK-LABEL: func @_QPcst_array_cst_len_lb subroutine cst_array_cst_len_lb() character(10) :: c(11:30) ! CHECK: fir.alloca !fir.array<20x!fir.char<1,10>> {{{.*}}uniq_name = "_QFcst_array_cst_len_lbEc"} + print *, c(11) end subroutine ! CHECK-LABEL: func @_QPcst_array_dyn_len_lb @@ -80,6 +87,7 @@ subroutine cst_array_dyn_len_lb(l) ! CHECK: %[[is_positive:.*]] = arith.cmpi sgt, %[[lexpr]], %c0{{.*}} : i64 ! CHECK: %[[l:.*]] = arith.select %[[is_positive]], %[[lexpr]], %c0{{.*}} : i64 ! CHECK: fir.alloca !fir.array<10x!fir.char<1,?>>(%[[l]] : i64) {{{.*}}uniq_name = "_QFcst_array_dyn_len_lbEc"} + print *, c(11) end subroutine ! CHECK-LABEL: func @_QPdyn_array_cst_len_lb @@ -94,6 +102,7 @@ subroutine dyn_array_cst_len_lb(n) ! CHECK: %[[is_positive:.*]] = arith.cmpi sgt, %[[raw_extent]], %c0{{.*}} : index ! CHECK: %[[extent:.*]] = arith.select %[[is_positive]], %[[raw_extent]], %c0{{.*}} : index ! CHECK: fir.alloca !fir.array<?x!fir.char<1,10>>, %[[extent]] {{{.*}}uniq_name = "_QFdyn_array_cst_len_lbEc"} + print *, c(11) end subroutine ! CHECK-LABEL: func @_QPdyn_array_dyn_len_lb @@ -111,6 +120,7 @@ subroutine dyn_array_dyn_len_lb(l, n) ! CHECK: %[[is_positive:.*]] = arith.cmpi sgt, %[[raw_extent]], %c0{{.*}} : index ! CHECK: %[[extent:.*]] = arith.select %[[is_positive]], %[[raw_extent]], %c0{{.*}} : index ! CHECK: fir.alloca !fir.array<?x!fir.char<1,?>>(%[[l]] : i64), %[[extent]] {{{.*}}uniq_name = "_QFdyn_array_dyn_len_lbEc"} + print *, c(11) end subroutine ! Test that the length of assumed length parameter is correctly deduced in lowering. @@ -129,4 +139,5 @@ end subroutine scalar_cst_neg_len() character(-1) :: c ! CHECK: fir.alloca !fir.char<1,0> {{{.*}}uniq_name = "_QFscalar_cst_neg_lenEc"} + print *, c end subroutine diff --git a/flang/test/Lower/character-substrings.f90 b/flang/test/Lower/character-substrings.f90 index 3834311..69e1dc8 100644 --- a/flang/test/Lower/character-substrings.f90 +++ b/flang/test/Lower/character-substrings.f90 @@ -10,8 +10,8 @@ end subroutine scalar_substring_embox ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<i64> {fir.bindc_name = "i"}, ! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref<i64> {fir.bindc_name = "j"}) { ! CHECK: %[[VAL_2:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_2]] {uniq_name = "_QFscalar_substring_emboxEi"} : (!fir.ref<i64>, !fir.dscope) -> (!fir.ref<i64>, !fir.ref<i64>) -! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %[[VAL_2]] {uniq_name = "_QFscalar_substring_emboxEj"} : (!fir.ref<i64>, !fir.dscope) -> (!fir.ref<i64>, !fir.ref<i64>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_2]] arg {{[0-9]+}} {uniq_name = "_QFscalar_substring_emboxEi"} : (!fir.ref<i64>, !fir.dscope) -> (!fir.ref<i64>, !fir.ref<i64>) +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %[[VAL_2]] arg {{[0-9]+}} {uniq_name = "_QFscalar_substring_emboxEj"} : (!fir.ref<i64>, !fir.dscope) -> (!fir.ref<i64>, !fir.ref<i64>) ! CHECK: %[[VAL_5:.*]] = fir.address_of(@_QQclX61626348656C6C6F20576F726C6421646667) : !fir.ref<!fir.char<1,18>> ! CHECK: %[[VAL_6:.*]] = arith.constant 18 : index ! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_5]] typeparams %[[VAL_6]] {fortran_attrs = #fir.var_attrs<parameter>, uniq_name = ".stringlit"} : (!fir.ref<!fir.char<1,18>>, index) -> (!fir.ref<!fir.char<1,18>>, !fir.ref<!fir.char<1,18>>) @@ -53,7 +53,7 @@ end subroutine array_substring_embox ! CHECK: %[[VAL_4:.*]] = arith.constant 7 : index ! CHECK: %[[VAL_5:.*]] = arith.constant 4 : index ! CHECK: %[[VAL_6:.*]] = fir.shape %[[VAL_5]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_3]](%[[VAL_6]]) typeparams %[[VAL_4]] dummy_scope %[[VAL_1]] {uniq_name = "_QFarray_substring_emboxEarr"} : (!fir.ref<!fir.array<4x!fir.char<1,7>>>, !fir.shape<1>, index, !fir.dscope) -> (!fir.ref<!fir.array<4x!fir.char<1,7>>>, !fir.ref<!fir.array<4x!fir.char<1,7>>>) +! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_3]](%[[VAL_6]]) typeparams %[[VAL_4]] dummy_scope %[[VAL_1]] arg {{[0-9]+}} {uniq_name = "_QFarray_substring_emboxEarr"} : (!fir.ref<!fir.array<4x!fir.char<1,7>>>, !fir.shape<1>, index, !fir.dscope) -> (!fir.ref<!fir.array<4x!fir.char<1,7>>>, !fir.ref<!fir.array<4x!fir.char<1,7>>>) ! CHECK: %[[VAL_8:.*]] = arith.constant 1 : index ! CHECK: %[[VAL_9:.*]] = arith.constant 1 : index ! CHECK: %[[VAL_10:.*]] = arith.constant 4 : index @@ -79,11 +79,11 @@ end subroutine substring_assignment ! CHECK: %[[VAL_3:.*]]:2 = fir.unboxchar %[[VAL_0]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index) ! CHECK: %[[VAL_4:.*]] = fir.convert %[[VAL_3]]#0 : (!fir.ref<!fir.char<1,?>>) -> !fir.ref<!fir.char<1,4>> ! CHECK: %[[VAL_5:.*]] = arith.constant 4 : index -! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_4]] typeparams %[[VAL_5]] dummy_scope %[[VAL_2]] {uniq_name = "_QFsubstring_assignmentEa"} : (!fir.ref<!fir.char<1,4>>, index, !fir.dscope) -> (!fir.ref<!fir.char<1,4>>, !fir.ref<!fir.char<1,4>>) +! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_4]] typeparams %[[VAL_5]] dummy_scope %[[VAL_2]] arg {{[0-9]+}} {uniq_name = "_QFsubstring_assignmentEa"} : (!fir.ref<!fir.char<1,4>>, index, !fir.dscope) -> (!fir.ref<!fir.char<1,4>>, !fir.ref<!fir.char<1,4>>) ! CHECK: %[[VAL_7:.*]]:2 = fir.unboxchar %[[VAL_1]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index) ! CHECK: %[[VAL_8:.*]] = fir.convert %[[VAL_7]]#0 : (!fir.ref<!fir.char<1,?>>) -> !fir.ref<!fir.char<1,4>> ! CHECK: %[[VAL_9:.*]] = arith.constant 4 : index -! CHECK: %[[VAL_10:.*]]:2 = hlfir.declare %[[VAL_8]] typeparams %[[VAL_9]] dummy_scope %[[VAL_2]] {uniq_name = "_QFsubstring_assignmentEb"} : (!fir.ref<!fir.char<1,4>>, index, !fir.dscope) -> (!fir.ref<!fir.char<1,4>>, !fir.ref<!fir.char<1,4>>) +! CHECK: %[[VAL_10:.*]]:2 = hlfir.declare %[[VAL_8]] typeparams %[[VAL_9]] dummy_scope %[[VAL_2]] arg {{[0-9]+}} {uniq_name = "_QFsubstring_assignmentEb"} : (!fir.ref<!fir.char<1,4>>, index, !fir.dscope) -> (!fir.ref<!fir.char<1,4>>, !fir.ref<!fir.char<1,4>>) ! CHECK: %[[VAL_11:.*]] = arith.constant 3 : index ! CHECK: %[[VAL_12:.*]] = arith.constant 4 : index ! CHECK: %[[VAL_13:.*]] = arith.constant 2 : index @@ -109,7 +109,7 @@ end subroutine array_substring_assignment ! CHECK: %[[VAL_4:.*]] = arith.constant 5 : index ! CHECK: %[[VAL_5:.*]] = arith.constant 6 : index ! CHECK: %[[VAL_6:.*]] = fir.shape %[[VAL_5]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_3]](%[[VAL_6]]) typeparams %[[VAL_4]] dummy_scope %[[VAL_1]] {uniq_name = "_QFarray_substring_assignmentEa"} : (!fir.ref<!fir.array<6x!fir.char<1,5>>>, !fir.shape<1>, index, !fir.dscope) -> (!fir.ref<!fir.array<6x!fir.char<1,5>>>, !fir.ref<!fir.array<6x!fir.char<1,5>>>) +! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_3]](%[[VAL_6]]) typeparams %[[VAL_4]] dummy_scope %[[VAL_1]] arg {{[0-9]+}} {uniq_name = "_QFarray_substring_assignmentEa"} : (!fir.ref<!fir.array<6x!fir.char<1,5>>>, !fir.shape<1>, index, !fir.dscope) -> (!fir.ref<!fir.array<6x!fir.char<1,5>>>, !fir.ref<!fir.array<6x!fir.char<1,5>>>) ! CHECK: %[[VAL_8:.*]] = fir.address_of(@_QQclX424144) : !fir.ref<!fir.char<1,3>> ! CHECK: %[[VAL_9:.*]] = arith.constant 3 : index ! CHECK: %[[VAL_10:.*]]:2 = hlfir.declare %[[VAL_8]] typeparams %[[VAL_9]] {fortran_attrs = #fir.var_attrs<parameter>, uniq_name = "_QQclX424144"} : (!fir.ref<!fir.char<1,3>>, index) -> (!fir.ref<!fir.char<1,3>>, !fir.ref<!fir.char<1,3>>) @@ -138,7 +138,7 @@ end subroutine array_substring_assignment2 ! CHECK: %[[VAL_1:.*]] = fir.dummy_scope : !fir.dscope ! CHECK: %[[VAL_8:.*]] = arith.constant 8 : index ! CHECK: %[[VAL_9:.*]] = fir.shape %[[VAL_8]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_10:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_9]]) dummy_scope %[[VAL_1]] {uniq_name = "_QFarray_substring_assignment2Ea"} : (!fir.ref<!fir.array<8x!fir.type<_QFarray_substring_assignment2Tt{ch:!fir.char<1,7>}>>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<8x!fir.type<_QFarray_substring_assignment2Tt{ch:!fir.char<1,7>}>>>, !fir.ref<!fir.array<8x!fir.type<_QFarray_substring_assignment2Tt{ch:!fir.char<1,7>}>>>) +! CHECK: %[[VAL_10:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_9]]) dummy_scope %[[VAL_1]] arg {{[0-9]+}} {uniq_name = "_QFarray_substring_assignment2Ea"} : (!fir.ref<!fir.array<8x!fir.type<_QFarray_substring_assignment2Tt{ch:!fir.char<1,7>}>>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<8x!fir.type<_QFarray_substring_assignment2Tt{ch:!fir.char<1,7>}>>>, !fir.ref<!fir.array<8x!fir.type<_QFarray_substring_assignment2Tt{ch:!fir.char<1,7>}>>>) ! CHECK: %[[VAL_18:.*]] = fir.address_of(@_QQclX6E696365) : !fir.ref<!fir.char<1,4>> ! CHECK: %[[VAL_19:.*]] = arith.constant 4 : index ! CHECK: %[[VAL_20:.*]]:2 = hlfir.declare %[[VAL_18]] typeparams %[[VAL_19]] {fortran_attrs = #fir.var_attrs<parameter>, uniq_name = "_QQclX6E696365"} : (!fir.ref<!fir.char<1,4>>, index) -> (!fir.ref<!fir.char<1,4>>, !fir.ref<!fir.char<1,4>>) @@ -164,10 +164,10 @@ end subroutine array_substring_assignment3 ! CHECK: %[[VAL_2:.*]] = fir.dummy_scope : !fir.dscope ! CHECK: %[[VAL_9:.*]] = arith.constant 8 : index ! CHECK: %[[VAL_10:.*]] = fir.shape %[[VAL_9]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_11:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_10]]) dummy_scope %[[VAL_2]] {uniq_name = "_QFarray_substring_assignment3Ea"} : (!fir.ref<!fir.array<8x!fir.type<_QFarray_substring_assignment3Tt{ch:!fir.char<1,7>}>>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<8x!fir.type<_QFarray_substring_assignment3Tt{ch:!fir.char<1,7>}>>>, !fir.ref<!fir.array<8x!fir.type<_QFarray_substring_assignment3Tt{ch:!fir.char<1,7>}>>>) +! CHECK: %[[VAL_11:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_10]]) dummy_scope %[[VAL_2]] arg {{[0-9]+}} {uniq_name = "_QFarray_substring_assignment3Ea"} : (!fir.ref<!fir.array<8x!fir.type<_QFarray_substring_assignment3Tt{ch:!fir.char<1,7>}>>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<8x!fir.type<_QFarray_substring_assignment3Tt{ch:!fir.char<1,7>}>>>, !fir.ref<!fir.array<8x!fir.type<_QFarray_substring_assignment3Tt{ch:!fir.char<1,7>}>>>) ! CHECK: %[[VAL_12:.*]] = arith.constant 8 : index ! CHECK: %[[VAL_13:.*]] = fir.shape %[[VAL_12]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_14:.*]]:2 = hlfir.declare %[[VAL_1]](%[[VAL_13]]) dummy_scope %[[VAL_2]] {uniq_name = "_QFarray_substring_assignment3Eb"} : (!fir.ref<!fir.array<8x!fir.type<_QFarray_substring_assignment3Tt{ch:!fir.char<1,7>}>>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<8x!fir.type<_QFarray_substring_assignment3Tt{ch:!fir.char<1,7>}>>>, !fir.ref<!fir.array<8x!fir.type<_QFarray_substring_assignment3Tt{ch:!fir.char<1,7>}>>>) +! CHECK: %[[VAL_14:.*]]:2 = hlfir.declare %[[VAL_1]](%[[VAL_13]]) dummy_scope %[[VAL_2]] arg {{[0-9]+}} {uniq_name = "_QFarray_substring_assignment3Eb"} : (!fir.ref<!fir.array<8x!fir.type<_QFarray_substring_assignment3Tt{ch:!fir.char<1,7>}>>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<8x!fir.type<_QFarray_substring_assignment3Tt{ch:!fir.char<1,7>}>>>, !fir.ref<!fir.array<8x!fir.type<_QFarray_substring_assignment3Tt{ch:!fir.char<1,7>}>>>) ! CHECK: %[[VAL_22:.*]] = arith.constant 2 : index ! CHECK: %[[VAL_23:.*]] = arith.constant 5 : index ! CHECK: %[[VAL_24:.*]] = arith.constant 4 : index diff --git a/flang/test/Lower/charconvert.f90 b/flang/test/Lower/charconvert.f90 index e3f7f66..1cf2552 100644 --- a/flang/test/Lower/charconvert.f90 +++ b/flang/test/Lower/charconvert.f90 @@ -1,30 +1,30 @@ ! RUN: bbc -emit-hlfir %s -o - | FileCheck %s subroutine test_c1_to_c4(c4, c1) - character(len=*, kind=4) :: c4 - character(len=*, kind=1) :: c1 - c4 = c1 -end subroutine + character(len=*, kind=4) :: c4 + character(len=*, kind=1) :: c1 + c4 = c1 +end subroutine subroutine test_c4_to_c1(c4, c1) - character(len=*, kind=4) :: c4 - character(len=*, kind=1) :: c1 - c1 = c4 -end subroutine - + character(len=*, kind=4) :: c4 + character(len=*, kind=1) :: c1 + c1 = c4 +end subroutine + ! CHECK: func.func @_QPtest_c1_to_c4(%[[ARG0:.*]]: !fir.boxchar<4> {fir.bindc_name = "c4"}, %[[ARG1:.*]]: !fir.boxchar<1> {fir.bindc_name = "c1"}) { ! CHECK: %[[VAL_0:.*]]:2 = fir.unboxchar %[[ARG1]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index) -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]]#0 typeparams %[[VAL_0]]#1 dummy_scope %{{[0-9]+}} {uniq_name = "_QFtest_c1_to_c4Ec1"} : (!fir.ref<!fir.char<1,?>>, index, !fir.dscope) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]]#0 typeparams %[[VAL_0]]#1 dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFtest_c1_to_c4Ec1"} : (!fir.ref<!fir.char<1,?>>, index, !fir.dscope) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>) ! CHECK: %[[VAL_2:.*]]:2 = fir.unboxchar %[[ARG0]] : (!fir.boxchar<4>) -> (!fir.ref<!fir.char<4,?>>, index) -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]]#0 typeparams %[[VAL_2]]#1 dummy_scope %{{[0-9]+}} {uniq_name = "_QFtest_c1_to_c4Ec4"} : (!fir.ref<!fir.char<4,?>>, index, !fir.dscope) -> (!fir.boxchar<4>, !fir.ref<!fir.char<4,?>>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]]#0 typeparams %[[VAL_2]]#1 dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFtest_c1_to_c4Ec4"} : (!fir.ref<!fir.char<4,?>>, index, !fir.dscope) -> (!fir.boxchar<4>, !fir.ref<!fir.char<4,?>>) ! CHECK: %[[VAL_4:.*]] = fir.alloca !fir.char<4,?>(%[[VAL_0]]#1 : index) ! CHECK: fir.char_convert %[[VAL_1]]#1 for %[[VAL_0]]#1 to %[[VAL_4:.*]] : !fir.ref<!fir.char<1,?>>, index, !fir.ref<!fir.char<4,?>> ! CHECK: func.func @_QPtest_c4_to_c1(%[[ARG0:.*]]: !fir.boxchar<4> {fir.bindc_name = "c4"}, %[[ARG1:.*]]: !fir.boxchar<1> {fir.bindc_name = "c1"}) { ! CHECK: %[[VAL_0:.*]]:2 = fir.unboxchar %[[ARG1]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index) -! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]]#0 typeparams %[[VAL_0]]#1 dummy_scope %{{[0-9]+}} {uniq_name = "_QFtest_c4_to_c1Ec1"} : (!fir.ref<!fir.char<1,?>>, index, !fir.dscope) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>) +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]]#0 typeparams %[[VAL_0]]#1 dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFtest_c4_to_c1Ec1"} : (!fir.ref<!fir.char<1,?>>, index, !fir.dscope) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>) ! CHECK: %[[VAL_2:.*]]:2 = fir.unboxchar %[[ARG0]] : (!fir.boxchar<4>) -> (!fir.ref<!fir.char<4,?>>, index) -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]]#0 typeparams %[[VAL_2]]#1 dummy_scope %{{[0-9]+}} {uniq_name = "_QFtest_c4_to_c1Ec4"} : (!fir.ref<!fir.char<4,?>>, index, !fir.dscope) -> (!fir.boxchar<4>, !fir.ref<!fir.char<4,?>>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]]#0 typeparams %[[VAL_2]]#1 dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFtest_c4_to_c1Ec4"} : (!fir.ref<!fir.char<4,?>>, index, !fir.dscope) -> (!fir.boxchar<4>, !fir.ref<!fir.char<4,?>>) ! CHECK: %[[C4:.*]] = arith.constant 4 : index ! CHECK: %[[VAL_4:.*]] = arith.muli %[[VAL_2]]#1, %[[C4]] : index ! CHECK: %[[VAL_5:.*]] = fir.alloca !fir.char<1,?>(%[[VAL_4]] : index) diff --git a/flang/test/Lower/components.f90 b/flang/test/Lower/components.f90 index f0caddb..82e1de1 100644 --- a/flang/test/Lower/components.f90 +++ b/flang/test/Lower/components.f90 @@ -29,8 +29,8 @@ contains ! CHECK: %[[VAL_2:.*]] = fir.dummy_scope : !fir.dscope ! CHECK: %[[VAL_3:.*]] = fir.address_of(@_QMcomponents_testEinstance) : !fir.ref<!fir.type<_QMcomponents_testTt3 ! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_3]] {uniq_name = "_QMcomponents_testEinstance"} : (!fir.ref<!fir.type<_QMcomponents_testTt3 -! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_2]] {uniq_name = "_QMcomponents_testFs1Ei"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) -! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %[[VAL_2]] {uniq_name = "_QMcomponents_testFs1Ej"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_2]] arg {{[0-9]+}} {uniq_name = "_QMcomponents_testFs1Ei"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %[[VAL_2]] arg {{[0-9]+}} {uniq_name = "_QMcomponents_testFs1Ej"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_7:.*]] = arith.constant 4 : index ! CHECK: %[[VAL_8:.*]] = fir.shape %[[VAL_7]] : (index) -> !fir.shape<1> ! CHECK: %[[VAL_9:.*]] = arith.constant 2 : index @@ -130,7 +130,7 @@ end subroutine ! CHECK: %[[VAL_1:.*]] = fir.dummy_scope : !fir.dscope ! CHECK: %[[VAL_2:.*]] = arith.constant 10 : index ! CHECK: %[[VAL_3:.*]] = fir.shape %[[VAL_2]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_3]]) dummy_scope %[[VAL_1]] {uniq_name = "_QFlhs_char_sectionEa"} : (!fir.ref<!fir.array<10x!fir.type<_QFlhs_char_sectionTt +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_3]]) dummy_scope %[[VAL_1]] arg {{[0-9]+}} {uniq_name = "_QFlhs_char_sectionEa"} : (!fir.ref<!fir.array<10x!fir.type<_QFlhs_char_sectionTt ! CHECK: %[[VAL_5:.*]] = fir.address_of(@_QQclX68656C6C6F) : !fir.ref<!fir.char<1,5>> ! CHECK: %[[VAL_6:.*]] = arith.constant 5 : index ! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_5]] typeparams %[[VAL_6]] {fortran_attrs = #fir.var_attrs<parameter>, uniq_name = "_QQclX68656C6C6F"} : (!fir.ref<!fir.char<1,5>>, index) -> (!fir.ref<!fir.char<1,5>>, !fir.ref<!fir.char<1,5>>) @@ -154,13 +154,13 @@ end subroutine ! CHECK: %[[VAL_2:.*]] = fir.dummy_scope : !fir.dscope ! CHECK: %[[VAL_3:.*]] = arith.constant 10 : index ! CHECK: %[[VAL_4:.*]] = fir.shape %[[VAL_3]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_4]]) dummy_scope %[[VAL_2]] {uniq_name = "_QFrhs_char_sectionEa"} : (!fir.ref<!fir.array<10x!fir.type<_QFrhs_char_sectionTt +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_4]]) dummy_scope %[[VAL_2]] arg {{[0-9]+}} {uniq_name = "_QFrhs_char_sectionEa"} : (!fir.ref<!fir.array<10x!fir.type<_QFrhs_char_sectionTt ! CHECK: %[[VAL_6:.*]]:2 = fir.unboxchar %[[VAL_1]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index) ! CHECK: %[[VAL_7:.*]] = fir.convert %[[VAL_6]]#0 : (!fir.ref<!fir.char<1,?>>) -> !fir.ref<!fir.array<10x!fir.char<1,10>>> ! CHECK: %[[VAL_8:.*]] = arith.constant 10 : index ! CHECK: %[[VAL_9:.*]] = arith.constant 10 : index ! CHECK: %[[VAL_10:.*]] = fir.shape %[[VAL_9]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_11:.*]]:2 = hlfir.declare %[[VAL_7]](%[[VAL_10]]) typeparams %[[VAL_8]] dummy_scope %[[VAL_2]] {uniq_name = "_QFrhs_char_sectionEc"} : (!fir.ref<!fir.array<10x!fir.char<1,10>>>, !fir.shape<1>, index, !fir.dscope) -> (!fir.ref<!fir.array<10x!fir.char<1,10>>>, !fir.ref<!fir.array<10x!fir.char<1,10>>>) +! CHECK: %[[VAL_11:.*]]:2 = hlfir.declare %[[VAL_7]](%[[VAL_10]]) typeparams %[[VAL_8]] dummy_scope %[[VAL_2]] arg {{[0-9]+}} {uniq_name = "_QFrhs_char_sectionEc"} : (!fir.ref<!fir.array<10x!fir.char<1,10>>>, !fir.shape<1>, index, !fir.dscope) -> (!fir.ref<!fir.array<10x!fir.char<1,10>>>, !fir.ref<!fir.array<10x!fir.char<1,10>>>) ! CHECK: %[[VAL_12:.*]] = arith.constant 10 : index ! CHECK: %[[VAL_13:.*]] = hlfir.designate %[[VAL_5]]#0{"c"} shape %[[VAL_4]] typeparams %[[VAL_12]] : (!fir.ref<!fir.array<10x!fir.type<_QFrhs_char_sectionTt ! CHECK: hlfir.assign %[[VAL_13]] to %[[VAL_11]]#0 : !fir.ref<!fir.array<10x!fir.char<1,10>>>, !fir.ref<!fir.array<10x!fir.char<1,10>>> @@ -181,10 +181,10 @@ end subroutine ! CHECK: %[[VAL_2:.*]] = fir.dummy_scope : !fir.dscope ! CHECK: %[[VAL_3:.*]] = arith.constant 10 : index ! CHECK: %[[VAL_4:.*]] = fir.shape %[[VAL_3]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_4]]) dummy_scope %[[VAL_2]] {uniq_name = "_QFelemental_char_sectionEa"} : (!fir.ref<!fir.array<10x!fir.type<_QFelemental_char_sectionTt +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_4]]) dummy_scope %[[VAL_2]] arg {{[0-9]+}} {uniq_name = "_QFelemental_char_sectionEa"} : (!fir.ref<!fir.array<10x!fir.type<_QFelemental_char_sectionTt ! CHECK: %[[VAL_6:.*]] = arith.constant 10 : index ! CHECK: %[[VAL_7:.*]] = fir.shape %[[VAL_6]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_8:.*]]:2 = hlfir.declare %[[VAL_1]](%[[VAL_7]]) dummy_scope %[[VAL_2]] {uniq_name = "_QFelemental_char_sectionEi"} : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>) +! CHECK: %[[VAL_8:.*]]:2 = hlfir.declare %[[VAL_1]](%[[VAL_7]]) dummy_scope %[[VAL_2]] arg {{[0-9]+}} {uniq_name = "_QFelemental_char_sectionEi"} : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>) ! CHECK: %[[VAL_9:.*]] = arith.constant 10 : index ! CHECK: %[[VAL_10:.*]] = hlfir.designate %[[VAL_5]]#0{"c"} shape %[[VAL_4]] typeparams %[[VAL_9]] : (!fir.ref<!fir.array<10x!fir.type<_QFelemental_char_sectionTt ! CHECK: %[[VAL_11:.*]] = fir.address_of(@_QQclX68656C6C6F) : !fir.ref<!fir.char<1,5>> diff --git a/flang/test/Lower/control-flow.f90 b/flang/test/Lower/control-flow.f90 index ef66c9e..b1929b0 100644 --- a/flang/test/Lower/control-flow.f90 +++ b/flang/test/Lower/control-flow.f90 @@ -22,4 +22,4 @@ subroutine one(a,b,c) ! CHECK: ^bb[[EXIT]]: ! CHECK-NEXT: return end subroutine one - + diff --git a/flang/test/Lower/default-initialization.f90 b/flang/test/Lower/default-initialization.f90 index 7b93db4..750c504 100644 --- a/flang/test/Lower/default-initialization.f90 +++ b/flang/test/Lower/default-initialization.f90 @@ -3,14 +3,14 @@ module test_dinit type t - integer :: i = 42 + integer :: i = 42 end type type t_alloc_comp real, allocatable :: i(:) end type type tseq sequence - integer :: i = 42 + integer :: i = 42 end type contains @@ -26,7 +26,7 @@ contains !CHECK: fir.copy %[[ADDR]] to %[[x]] no_overlap : !fir.ref<!fir.type<_QMtest_dinitTt{i:i32}>>, !fir.ref<!fir.type<_QMtest_dinitTt{i:i32}>> type(t) :: x print *, x%i - end subroutine + end subroutine ! Test local array is default initialized ! CHECK-LABEL: func @_QMtest_dinitPlocal_array() @@ -38,7 +38,7 @@ contains ! CHECK: fir.call @_FortranAInitialize(%[[xboxNone]], %{{.*}}, %{{.*}}) {{.*}}: (!fir.box<none>, !fir.ref<i8>, i32) -> () type(t) :: x(4) print *, x(2)%i - end subroutine + end subroutine ! Test allocatable component triggers default initialization of local ! scalars. @@ -48,7 +48,7 @@ contains !CHECK: %[[ADDR:.*]] = fir.address_of(@_QQ_QMtest_dinitTt_alloc_comp.DerivedInit) : !fir.ref<!fir.type<_QMtest_dinitTt_alloc_comp{i:!fir.box<!fir.heap<!fir.array<?xf32>>>}>> !CHECK: fir.copy %[[ADDR]] to %[[x]] no_overlap : !fir.ref<!fir.type<_QMtest_dinitTt_alloc_comp{i:!fir.box<!fir.heap<!fir.array<?xf32>>>}>>, !fir.ref<!fir.type<_QMtest_dinitTt_alloc_comp{i:!fir.box<!fir.heap<!fir.array<?xf32>>>}>> type(t_alloc_comp) :: x - end subroutine + end subroutine ! Test function results are default initialized. ! CHECK-LABEL: func @_QMtest_dinitPresult() -> !fir.type<_QMtest_dinitTt{i:i32}> @@ -110,7 +110,7 @@ contains ! CHECK: %[[ADDR:.*]] = fir.address_of(@_QQ_QMtest_dinitTtseq.DerivedInit) : !fir.ref<!fir.type<_QMtest_dinitTtseq{i:i32}>> ! CHECK: fir.copy %[[ADDR]] to %[[x]] no_overlap : !fir.ref<!fir.type<_QMtest_dinitTtseq{i:i32}>>, !fir.ptr<!fir.type<_QMtest_dinitTtseq{i:i32}>> - + ! CHECK: %[[ycoor:.*]] = fir.coordinate_of %[[equiv]], %c0{{.*}} : (!fir.ref<!fir.array<4xi8>>, index) -> !fir.ref<i8> ! CHECK: %[[y:.*]] = fir.convert %[[ycoor]] : (!fir.ref<i8>) -> !fir.ptr<!fir.type<_QMtest_dinitTtseq{i:i32}>> ! CHECK: %[[ADDR:.*]] = fir.address_of(@_QQ_QMtest_dinitTtseq.DerivedInit) : !fir.ref<!fir.type<_QMtest_dinitTtseq{i:i32}>> @@ -129,14 +129,14 @@ contains ! CHECK-NOT: fir.call @_FortranAInitialize type(t), allocatable :: x ! CHECK: return - end subroutine + end subroutine ! CHECK-LABEL: func @_QMtest_dinitPnoinit_local_pointer subroutine noinit_local_pointer ! CHECK-NOT: fir.call @_FortranAInitialize type(t), pointer :: x ! CHECK: return - end subroutine + end subroutine ! CHECK-LABEL: func @_QMtest_dinitPnoinit_normal_dummy subroutine noinit_normal_dummy(x) @@ -150,7 +150,7 @@ contains ! CHECK-NOT: fir.call @_FortranAInitialize type(t), intent(inout) :: x ! CHECK: return - end subroutine + end subroutine subroutine test_pointer_intentout(a, b) diff --git a/flang/test/Lower/derived-allocatable-components.f90 b/flang/test/Lower/derived-allocatable-components.f90 index 1debb27..bc508fb 100644 --- a/flang/test/Lower/derived-allocatable-components.f90 +++ b/flang/test/Lower/derived-allocatable-components.f90 @@ -241,9 +241,9 @@ subroutine ref_scalar_def_char_a(a0_0, a1_0, a0_1, a1_1) ! CHECK-DAG: %[[len:.*]] = fir.box_elesize %[[box]] ! CHECK-DAG: %[[base:.*]] = fir.box_addr %[[box]] ! CHECK: %[[cast:.*]] = fir.convert %[[base]] : (!fir.heap<!fir.array<?x!fir.char<1,?>>>) -> !fir.ref<!fir.array<?x!fir.char<1,?>>> - ! CHECK: %[[c7:.*]] = fir.convert %c7{{.*}} : (i64) -> index - ! CHECK: %[[sub:.*]] = arith.subi %[[c7]], %[[dims]]#0 : index - ! CHECK: %[[mul:.*]] = arith.muli %[[len]], %[[sub]] : index + ! CHECK: %[[c7:.*]] = fir.convert %c7{{.*}} : (i64) -> index + ! CHECK: %[[sub:.*]] = arith.subi %[[c7]], %[[dims]]#0 : index + ! CHECK: %[[mul:.*]] = arith.muli %[[len]], %[[sub]] : index ! CHECK: %[[offset:.*]] = arith.addi %[[mul]], %c0{{.*}} : index ! CHECK: %[[cnvt:.*]] = fir.convert %[[cast]] ! CHECK: %[[addr:.*]] = fir.coordinate_of %[[cnvt]], %[[offset]] @@ -260,9 +260,9 @@ subroutine ref_scalar_def_char_a(a0_0, a1_0, a0_1, a1_1) ! CHECK-DAG: %[[len:.*]] = fir.box_elesize %[[box]] ! CHECK-DAG: %[[base:.*]] = fir.box_addr %[[box]] ! CHECK: %[[cast:.*]] = fir.convert %[[base]] : (!fir.heap<!fir.array<?x!fir.char<1,?>>>) -> !fir.ref<!fir.array<?x!fir.char<1,?>>> - ! CHECK: %[[c7:.*]] = fir.convert %c7{{.*}} : (i64) -> index - ! CHECK: %[[sub:.*]] = arith.subi %[[c7]], %[[dims]]#0 : index - ! CHECK: %[[mul:.*]] = arith.muli %[[len]], %[[sub]] : index + ! CHECK: %[[c7:.*]] = fir.convert %c7{{.*}} : (i64) -> index + ! CHECK: %[[sub:.*]] = arith.subi %[[c7]], %[[dims]]#0 : index + ! CHECK: %[[mul:.*]] = arith.muli %[[len]], %[[sub]] : index ! CHECK: %[[offset:.*]] = arith.addi %[[mul]], %c0{{.*}} : index ! CHECK: %[[cnvt:.*]] = fir.convert %[[cast]] ! CHECK: %[[addr:.*]] = fir.coordinate_of %[[cnvt]], %[[offset]] diff --git a/flang/test/Lower/derived-assignments.f90 b/flang/test/Lower/derived-assignments.f90 index 5870ea1..3e0950d 100644 --- a/flang/test/Lower/derived-assignments.f90 +++ b/flang/test/Lower/derived-assignments.f90 @@ -57,8 +57,8 @@ contains end subroutine t_to_t ! CHECK-LABEL: func.func @_QMm2Pt_to_t( ! CHECK: %[[VAL_2:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare {{.*}} dummy_scope %[[VAL_2]] {fortran_attrs = #fir.var_attrs<intent_out>, uniq_name = "_QMm2Ft_to_tEa1"} : (!fir.ref<!fir.type<_QMm2Tt -! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %[[VAL_2]] {fortran_attrs = #fir.var_attrs<intent_in>, uniq_name = "_QMm2Ft_to_tEb1"} : (!fir.ref<!fir.type<_QMm2Tt +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare {{.*}} dummy_scope %[[VAL_2]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<intent_out>, uniq_name = "_QMm2Ft_to_tEa1"} : (!fir.ref<!fir.type<_QMm2Tt +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %[[VAL_2]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<intent_in>, uniq_name = "_QMm2Ft_to_tEb1"} : (!fir.ref<!fir.type<_QMm2Tt ! CHECK: %[[VAL_5:.*]] = hlfir.designate %[[VAL_4]]#0{"b"} : (!fir.ref<!fir.type<_QMm2Tt ! CHECK: %[[VAL_6:.*]] = fir.load %[[VAL_5]] : !fir.ref<i32> ! CHECK: %[[VAL_7:.*]] = hlfir.designate %[[VAL_3]]#0{"a"} : (!fir.ref<!fir.type<_QMm2Tt @@ -99,8 +99,8 @@ subroutine test_array_comp(t1, t2) end subroutine ! CHECK-LABEL: func.func @_QPtest_array_comp( ! CHECK: %[[VAL_2:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %[[VAL_2]] {uniq_name = "_QFtest_array_compEt1"} : (!fir.ref<!fir.type<_QFtest_array_compTt -! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %[[VAL_2]] {uniq_name = "_QFtest_array_compEt2"} : (!fir.ref<!fir.type<_QFtest_array_compTt +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %[[VAL_2]] arg {{[0-9]+}} {uniq_name = "_QFtest_array_compEt1"} : (!fir.ref<!fir.type<_QFtest_array_compTt +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %[[VAL_2]] arg {{[0-9]+}} {uniq_name = "_QFtest_array_compEt2"} : (!fir.ref<!fir.type<_QFtest_array_compTt ! CHECK: hlfir.assign %[[VAL_4]]#0 to %[[VAL_3]]#0 : !fir.ref<!fir.type<_QFtest_array_compTt ! CHECK: return ! CHECK: } @@ -116,8 +116,8 @@ subroutine test_ptr_comp(t1, t2) end subroutine ! CHECK-LABEL: func.func @_QPtest_ptr_comp( ! CHECK: %[[VAL_2:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %[[VAL_2]] {uniq_name = "_QFtest_ptr_compEt1"} : (!fir.ref<!fir.type<_QFtest_ptr_compTt -! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %[[VAL_2]] {uniq_name = "_QFtest_ptr_compEt2"} : (!fir.ref<!fir.type<_QFtest_ptr_compTt +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %[[VAL_2]] arg {{[0-9]+}} {uniq_name = "_QFtest_ptr_compEt1"} : (!fir.ref<!fir.type<_QFtest_ptr_compTt +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %[[VAL_2]] arg {{[0-9]+}} {uniq_name = "_QFtest_ptr_compEt2"} : (!fir.ref<!fir.type<_QFtest_ptr_compTt ! CHECK: hlfir.assign %[[VAL_4]]#0 to %[[VAL_3]]#0 : !fir.ref<!fir.type<_QFtest_ptr_compTt ! CHECK: return ! CHECK: } @@ -134,8 +134,8 @@ subroutine test_box_assign(t1, t2) end subroutine ! CHECK-LABEL: func.func @_QPtest_box_assign( ! CHECK: %[[VAL_2:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %[[VAL_2]] {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFtest_box_assignEt1"} : (!fir.ref<!fir.box<!fir.ptr<!fir.type<_QFtest_box_assignTt -! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %[[VAL_2]] {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFtest_box_assignEt2"} : (!fir.ref<!fir.box<!fir.ptr<!fir.type<_QFtest_box_assignTt +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %[[VAL_2]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFtest_box_assignEt1"} : (!fir.ref<!fir.box<!fir.ptr<!fir.type<_QFtest_box_assignTt +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %[[VAL_2]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFtest_box_assignEt2"} : (!fir.ref<!fir.box<!fir.ptr<!fir.type<_QFtest_box_assignTt ! CHECK: %[[VAL_5:.*]] = fir.load %[[VAL_4]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.type<_QFtest_box_assignTt ! CHECK: %[[VAL_6:.*]] = fir.box_addr %[[VAL_5]] : (!fir.box<!fir.ptr<!fir.type<_QFtest_box_assignTt ! CHECK: %[[VAL_7:.*]] = fir.load %[[VAL_3]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.type<_QFtest_box_assignTt @@ -156,8 +156,8 @@ subroutine test_alloc_comp(t1, t2) end subroutine ! CHECK-LABEL: func.func @_QPtest_alloc_comp( ! CHECK: %[[VAL_2:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %[[VAL_2]] {uniq_name = "_QFtest_alloc_compEt1"} : (!fir.ref<!fir.type<_QFtest_alloc_compTt -! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %[[VAL_2]] {uniq_name = "_QFtest_alloc_compEt2"} : (!fir.ref<!fir.type<_QFtest_alloc_compTt +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %[[VAL_2]] arg {{[0-9]+}} {uniq_name = "_QFtest_alloc_compEt1"} : (!fir.ref<!fir.type<_QFtest_alloc_compTt +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %[[VAL_2]] arg {{[0-9]+}} {uniq_name = "_QFtest_alloc_compEt2"} : (!fir.ref<!fir.type<_QFtest_alloc_compTt ! CHECK: hlfir.assign %[[VAL_4]]#0 to %[[VAL_3]]#0 : !fir.ref<!fir.type<_QFtest_alloc_compTt ! CHECK: return ! CHECK: } @@ -192,8 +192,8 @@ contains end subroutine ! CHECK-LABEL: func.func @_QMcomponent_with_user_def_assignPtest( ! CHECK: %[[VAL_2:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %[[VAL_2]] {uniq_name = "_QMcomponent_with_user_def_assignFtestEt1"} : (!fir.ref<!fir.type<_QMcomponent_with_user_def_assignTt -! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %[[VAL_2]] {uniq_name = "_QMcomponent_with_user_def_assignFtestEt2"} : (!fir.ref<!fir.type<_QMcomponent_with_user_def_assignTt +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %[[VAL_2]] arg {{[0-9]+}} {uniq_name = "_QMcomponent_with_user_def_assignFtestEt1"} : (!fir.ref<!fir.type<_QMcomponent_with_user_def_assignTt +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %[[VAL_2]] arg {{[0-9]+}} {uniq_name = "_QMcomponent_with_user_def_assignFtestEt2"} : (!fir.ref<!fir.type<_QMcomponent_with_user_def_assignTt ! CHECK: hlfir.assign %[[VAL_4]]#0 to %[[VAL_3]]#0 : !fir.ref<!fir.type<_QMcomponent_with_user_def_assignTt ! CHECK: return ! CHECK: } diff --git a/flang/test/Lower/derived-type-descriptor.f90 b/flang/test/Lower/derived-type-descriptor.f90 index 22f7bf1..46e4e2b 100644 --- a/flang/test/Lower/derived-type-descriptor.f90 +++ b/flang/test/Lower/derived-type-descriptor.f90 @@ -39,7 +39,7 @@ end subroutine ! CHECK: } subroutine char_comp_init() - implicit none + implicit none type t character(8) :: name='Empty' end type t diff --git a/flang/test/Lower/derived-types-bindc.f90 b/flang/test/Lower/derived-types-bindc.f90 index 309b2b7..c3c007d 100644 --- a/flang/test/Lower/derived-types-bindc.f90 +++ b/flang/test/Lower/derived-types-bindc.f90 @@ -41,4 +41,10 @@ subroutine s1() end type type(t4) :: xt4 ! CHECK-DAG: %_QFs1Tt4 = type <{ i16, [2 x i8], { double, double }, [1 x i8], [3 x i8] }> + + xt0%x2 = 1. + xt1%x2 = 1. + xt2%x2 = 1. + xt3%x2 = (1., 1.) + xt4%x2 = (1., 1.) end subroutine s1 diff --git a/flang/test/Lower/derived-types.f90 b/flang/test/Lower/derived-types.f90 index 4d36a76..142e70a 100644 --- a/flang/test/Lower/derived-types.f90 +++ b/flang/test/Lower/derived-types.f90 @@ -19,7 +19,7 @@ module d contains ! ----------------------------------------------------------------------------- -! Test simple derived type symbol lowering +! Test simple derived type symbol lowering ! ----------------------------------------------------------------------------- ! CHECK-LABEL: func @_QMdPderived_dummy( @@ -35,6 +35,8 @@ subroutine local_derived() ! CHECK-DAG: fir.alloca !fir.type<_QMdTr{x:f32}> type(r) :: some_r type(c2) :: some_c2 + print *, some_c2%ch_array(1,1) + print *, some_r%x end subroutine ! CHECK-LABEL: func @_QMdPsaved_derived( @@ -48,7 +50,7 @@ end subroutine ! ----------------------------------------------------------------------------- -! Test simple derived type references +! Test simple derived type references ! ----------------------------------------------------------------------------- ! CHECK-LABEL: func @_QMdPscalar_numeric_ref( @@ -155,7 +157,7 @@ end subroutine end module ! ----------------------------------------------------------------------------- -! Test derived type with pointer/allocatable components +! Test derived type with pointer/allocatable components ! ----------------------------------------------------------------------------- module d2 @@ -172,7 +174,7 @@ end subroutine end module ! ----------------------------------------------------------------------------- -! Test global derived type symbol lowering +! Test global derived type symbol lowering ! ----------------------------------------------------------------------------- module data_mod diff --git a/flang/test/Lower/dispatch-table-abstract.f90 b/flang/test/Lower/dispatch-table-abstract.f90 new file mode 100644 index 0000000..cb4eb0c --- /dev/null +++ b/flang/test/Lower/dispatch-table-abstract.f90 @@ -0,0 +1,21 @@ +! Test lowering of ASBTRACT type to fir.type_info +! RUN: %flang_fc1 -emit-hlfir %s -o - | FileCheck %s + +module m_abstract_info + type, abstract :: abstract_type + contains + procedure(proc_iface), nopass, deferred :: proc + end type + interface + subroutine proc_iface() + end subroutine + end interface +end module + +subroutine test(x) + use m_abstract_info, only : abstract_type + class(abstract_type) :: x +end subroutine + +!CHECK-LABEL: fir.type_info @_QMm_abstract_infoTabstract_type abstract noinit nodestroy nofinal : !fir.type<_QMm_abstract_infoTabstract_type> dispatch_table { +!CHECK: fir.dt_entry "proc", @_QPproc_iface deferred diff --git a/flang/test/Lower/dispatch.f90 b/flang/test/Lower/dispatch.f90 index 0233806..863a26c 100644 --- a/flang/test/Lower/dispatch.f90 +++ b/flang/test/Lower/dispatch.f90 @@ -151,11 +151,11 @@ module call_dispatch ! CHECK-LABEL: func.func @_QMcall_dispatchPcheck_dispatch( ! CHECK-SAME: %[[P:.*]]: !fir.class<!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>> {fir.bindc_name = "p"}) { -! CHECK: %[[P_DECL:.*]]:2 = hlfir.declare %[[P]] dummy_scope %{{[0-9]+}} {uniq_name = "_QMcall_dispatchFcheck_dispatchEp"} : (!fir.class<!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>, !fir.dscope) -> (!fir.class<!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>, !fir.class<!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>) +! CHECK: %[[P_DECL:.*]]:2 = hlfir.declare %[[P]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QMcall_dispatchFcheck_dispatchEp"} : (!fir.class<!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>, !fir.dscope) -> (!fir.class<!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>, !fir.class<!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>) ! CHECK: fir.dispatch "tbp_nopass"(%[[P_DECL]]#1 : !fir.class<!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>){{$}} ! CHECK: fir.dispatch "tbp_pass"(%[[P_DECL]]#0 : !fir.class<!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>) (%[[P_DECL]]#0 : !fir.class<!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>) {pass_arg_pos = 0 : i32} ! CHECK: fir.dispatch "tbp_pass_arg0"(%[[P_DECL]]#0 : !fir.class<!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>) (%[[P_DECL]]#0 : !fir.class<!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>) {pass_arg_pos = 0 : i32} -! CHECK: fir.dispatch "tbp_pass_arg1"(%[[P_DECL]]#0 : !fir.class<!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>) (%{{.*}}, %[[P_DECL]]#0 : !fir.ref<i32>, !fir.class<!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>) {pass_arg_pos = 1 : i32} +! CHECK: fir.dispatch "tbp_pass_arg1"(%[[P_DECL]]#0 : !fir.class<!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>) (%{{.*}}, %[[P_DECL]]#0 : !fir.ref<i32>, !fir.class<!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>) {pass_arg_pos = 1 : i32} ! CHECK: fir.dispatch "proc1"(%[[P_DECL]]#1 : !fir.class<!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>){{$}} ! CHECK: fir.dispatch "proc2"(%[[P_DECL]]#0 : !fir.class<!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>) (%[[P_DECL]]#0 : !fir.class<!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>) {pass_arg_pos = 0 : i32} @@ -174,10 +174,10 @@ module call_dispatch end subroutine ! CHECK-LABEL: func.func @_QMcall_dispatchPcheck_dispatch_deferred( -! CHECK-SAME: %[[ARG0:.*]]: !fir.class<!fir.type<_QMcall_dispatchTa1{a:f32,b:f32}>> {fir.bindc_name = "a"}, +! CHECK-SAME: %[[ARG0:.*]]: !fir.class<!fir.type<_QMcall_dispatchTa1{a:f32,b:f32}>> {fir.bindc_name = "a"}, ! CHECK-SAME: %[[ARG1:.*]]: !fir.box<!fir.array<?xf32>> {fir.bindc_name = "x"}) { -! CHECK: %[[ARG0_DECL:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{[0-9]+}} {uniq_name = "_QMcall_dispatchFcheck_dispatch_deferredEa"} : (!fir.class<!fir.type<_QMcall_dispatchTa1{a:f32,b:f32}>>, !fir.dscope) -> (!fir.class<!fir.type<_QMcall_dispatchTa1{a:f32,b:f32}>>, !fir.class<!fir.type<_QMcall_dispatchTa1{a:f32,b:f32}>>) -! CHECK: %[[ARG1_DECL:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %{{[0-9]+}} {uniq_name = "_QMcall_dispatchFcheck_dispatch_deferredEx"} : (!fir.box<!fir.array<?xf32>>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.box<!fir.array<?xf32>>) +! CHECK: %[[ARG0_DECL:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QMcall_dispatchFcheck_dispatch_deferredEa"} : (!fir.class<!fir.type<_QMcall_dispatchTa1{a:f32,b:f32}>>, !fir.dscope) -> (!fir.class<!fir.type<_QMcall_dispatchTa1{a:f32,b:f32}>>, !fir.class<!fir.type<_QMcall_dispatchTa1{a:f32,b:f32}>>) +! CHECK: %[[ARG1_DECL:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QMcall_dispatchFcheck_dispatch_deferredEx"} : (!fir.box<!fir.array<?xf32>>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.box<!fir.array<?xf32>>) ! CHECK: fir.dispatch "nopassd"(%[[ARG0_DECL]]#1 : !fir.class<!fir.type<_QMcall_dispatchTa1{a:f32,b:f32}>>) (%[[ARG1_DECL]]#0 : !fir.box<!fir.array<?xf32>>) subroutine check_dispatch_scalar_allocatable(p) @@ -187,7 +187,7 @@ module call_dispatch ! CHECK-LABEL: func.func @_QMcall_dispatchPcheck_dispatch_scalar_allocatable( ! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.class<!fir.heap<!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>> {fir.bindc_name = "p"}) { -! CHECK: %[[ARG0_DECL:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QMcall_dispatchFcheck_dispatch_scalar_allocatableEp"} : (!fir.ref<!fir.class<!fir.heap<!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>>, !fir.dscope) -> (!fir.ref<!fir.class<!fir.heap<!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>>, !fir.ref<!fir.class<!fir.heap<!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>>) +! CHECK: %[[ARG0_DECL:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QMcall_dispatchFcheck_dispatch_scalar_allocatableEp"} : (!fir.ref<!fir.class<!fir.heap<!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>>, !fir.dscope) -> (!fir.ref<!fir.class<!fir.heap<!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>>, !fir.ref<!fir.class<!fir.heap<!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>>) ! CHECK: %[[LOAD:.*]] = fir.load %[[ARG0_DECL]]#0 : !fir.ref<!fir.class<!fir.heap<!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>> ! CHECK: %[[REBOX:.*]] = fir.rebox %[[LOAD]] : (!fir.class<!fir.heap<!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>) -> !fir.class<!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>> ! CHECK: fir.dispatch "tbp_pass"(%[[REBOX]] : !fir.class<!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>) (%[[REBOX]] : !fir.class<!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>) {pass_arg_pos = 0 : i32} @@ -199,7 +199,7 @@ module call_dispatch ! CHECK-LABEL: func.func @_QMcall_dispatchPcheck_dispatch_scalar_pointer( ! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.class<!fir.ptr<!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>> {fir.bindc_name = "p"}) { -! CHECK: %[[ARG0_DECL:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QMcall_dispatchFcheck_dispatch_scalar_pointerEp"} : (!fir.ref<!fir.class<!fir.ptr<!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>>, !fir.dscope) -> (!fir.ref<!fir.class<!fir.ptr<!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>>, !fir.ref<!fir.class<!fir.ptr<!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>>) +! CHECK: %[[ARG0_DECL:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QMcall_dispatchFcheck_dispatch_scalar_pointerEp"} : (!fir.ref<!fir.class<!fir.ptr<!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>>, !fir.dscope) -> (!fir.ref<!fir.class<!fir.ptr<!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>>, !fir.ref<!fir.class<!fir.ptr<!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>>) ! CHECK: %[[LOAD:.*]] = fir.load %[[ARG0_DECL]]#0 : !fir.ref<!fir.class<!fir.ptr<!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>> ! CHECK: %[[REBOX:.*]] = fir.rebox %[[LOAD]] : (!fir.class<!fir.ptr<!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>) -> !fir.class<!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>> ! CHECK: fir.dispatch "tbp_pass"(%[[REBOX]] : !fir.class<!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>) (%[[REBOX]] : !fir.class<!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>) {pass_arg_pos = 0 : i32} @@ -218,10 +218,10 @@ module call_dispatch end subroutine ! CHECK-LABEL: func.func @_QMcall_dispatchPcheck_dispatch_static_array( -! CHECK-SAME: %[[ARG0:.*]]: !fir.class<!fir.array<10x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>> {fir.bindc_name = "p"}, +! CHECK-SAME: %[[ARG0:.*]]: !fir.class<!fir.array<10x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>> {fir.bindc_name = "p"}, ! CHECK-SAME: %[[ARG1:.*]]: !fir.ref<!fir.array<10x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>> {fir.bindc_name = "t"}) { -! CHECK: %[[ARG0_DECL:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{[0-9]+}} {uniq_name = "_QMcall_dispatchFcheck_dispatch_static_arrayEp"} : (!fir.class<!fir.array<10x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>, !fir.dscope) -> (!fir.class<!fir.array<10x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>, !fir.class<!fir.array<10x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>) -! CHECK: %[[ARG1_DECL:.*]]:2 = hlfir.declare %[[ARG1]](%{{.*}}) dummy_scope %{{[0-9]+}} {uniq_name = "_QMcall_dispatchFcheck_dispatch_static_arrayEt"} : (!fir.ref<!fir.array<10x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<10x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>, !fir.ref<!fir.array<10x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>) +! CHECK: %[[ARG0_DECL:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QMcall_dispatchFcheck_dispatch_static_arrayEp"} : (!fir.class<!fir.array<10x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>, !fir.dscope) -> (!fir.class<!fir.array<10x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>, !fir.class<!fir.array<10x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>) +! CHECK: %[[ARG1_DECL:.*]]:2 = hlfir.declare %[[ARG1]](%{{.*}}) dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QMcall_dispatchFcheck_dispatch_static_arrayEt"} : (!fir.ref<!fir.array<10x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<10x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>, !fir.ref<!fir.array<10x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>) ! CHECK: fir.do_loop {{.*}} { ! CHECK: %[[DESIGNATE:.*]] = hlfir.designate %[[ARG0_DECL]]#0 (%{{.*}}) : (!fir.class<!fir.array<10x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>, i64) -> !fir.class<!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>> ! CHECK: fir.dispatch "tbp_pass"(%[[DESIGNATE]] : !fir.class<!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>) (%[[DESIGNATE]] : !fir.class<!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>) {pass_arg_pos = 0 : i32} @@ -246,10 +246,10 @@ module call_dispatch end subroutine ! CHECK-LABEL: func.func @_QMcall_dispatchPcheck_dispatch_dynamic_array( -! CHECK-SAME: %[[ARG0:.*]]: !fir.class<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>> {fir.bindc_name = "p"}, +! CHECK-SAME: %[[ARG0:.*]]: !fir.class<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>> {fir.bindc_name = "p"}, ! CHECK-SAME: %[[ARG1:.*]]: !fir.box<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>> {fir.bindc_name = "t"}) { -! CHECK: %[[ARG0_DECL:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{[0-9]+}} {uniq_name = "_QMcall_dispatchFcheck_dispatch_dynamic_arrayEp"} : (!fir.class<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>, !fir.dscope) -> (!fir.class<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>, !fir.class<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>) -! CHECK: %[[ARG1_DECL:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %{{[0-9]+}} {uniq_name = "_QMcall_dispatchFcheck_dispatch_dynamic_arrayEt"} : (!fir.box<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>, !fir.dscope) -> (!fir.box<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>, !fir.box<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>) +! CHECK: %[[ARG0_DECL:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QMcall_dispatchFcheck_dispatch_dynamic_arrayEp"} : (!fir.class<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>, !fir.dscope) -> (!fir.class<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>, !fir.class<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>) +! CHECK: %[[ARG1_DECL:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QMcall_dispatchFcheck_dispatch_dynamic_arrayEt"} : (!fir.box<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>, !fir.dscope) -> (!fir.box<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>, !fir.box<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>) ! CHECK: %{{.*}} = fir.do_loop {{.*}} { ! CHECK: %[[DESIGNATE:.*]] = hlfir.designate %[[ARG0_DECL]]#0 (%{{.*}}) : (!fir.class<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>, i64) -> !fir.class<!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>> ! CHECK: fir.dispatch "tbp_pass"(%[[DESIGNATE]] : !fir.class<!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>) (%[[DESIGNATE]] : !fir.class<!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>) {pass_arg_pos = 0 : i32} @@ -274,10 +274,10 @@ module call_dispatch end subroutine ! CHECK-LABEL: func.func @_QMcall_dispatchPcheck_dispatch_allocatable_array( -! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.class<!fir.heap<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>>> {fir.bindc_name = "p"}, +! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.class<!fir.heap<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>>> {fir.bindc_name = "p"}, ! CHECK-SAME: %[[ARG1:.*]]: !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>>> {fir.bindc_name = "t"}) { -! CHECK: %[[ARG0_DECL:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QMcall_dispatchFcheck_dispatch_allocatable_arrayEp"} : (!fir.ref<!fir.class<!fir.heap<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>>>, !fir.dscope) -> (!fir.ref<!fir.class<!fir.heap<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>>>, !fir.ref<!fir.class<!fir.heap<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>>>) -! CHECK: %[[ARG1_DECL:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QMcall_dispatchFcheck_dispatch_allocatable_arrayEt"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>>>) +! CHECK: %[[ARG0_DECL:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QMcall_dispatchFcheck_dispatch_allocatable_arrayEp"} : (!fir.ref<!fir.class<!fir.heap<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>>>, !fir.dscope) -> (!fir.ref<!fir.class<!fir.heap<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>>>, !fir.ref<!fir.class<!fir.heap<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>>>) +! CHECK: %[[ARG1_DECL:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QMcall_dispatchFcheck_dispatch_allocatable_arrayEt"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>>>) ! CHECK: %{{.*}} = fir.do_loop {{.*}} { ! CHECK: %[[LOAD_ARG0:.*]] = fir.load %[[ARG0_DECL]]#0 : !fir.ref<!fir.class<!fir.heap<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>>> ! CHECK: %[[DESIGNATE:.*]] = hlfir.designate %[[LOAD_ARG0]] (%{{.*}}) : (!fir.class<!fir.heap<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>>, i64) -> !fir.class<!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>> @@ -304,10 +304,10 @@ module call_dispatch end subroutine ! CHECK-LABEL: func.func @_QMcall_dispatchPcheck_dispatch_pointer_array( -! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.class<!fir.ptr<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>>> {fir.bindc_name = "p"}, +! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.class<!fir.ptr<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>>> {fir.bindc_name = "p"}, ! CHECK-SAME: %[[ARG1:.*]]: !fir.ref<!fir.box<!fir.ptr<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>>> {fir.bindc_name = "t"}) { -! CHECK: %[[ARG0_DECL:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QMcall_dispatchFcheck_dispatch_pointer_arrayEp"} : (!fir.ref<!fir.class<!fir.ptr<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>>>, !fir.dscope) -> (!fir.ref<!fir.class<!fir.ptr<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>>>, !fir.ref<!fir.class<!fir.ptr<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>>>) -! CHECK: %[[ARG1_DECL:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QMcall_dispatchFcheck_dispatch_pointer_arrayEt"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>>>) +! CHECK: %[[ARG0_DECL:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QMcall_dispatchFcheck_dispatch_pointer_arrayEp"} : (!fir.ref<!fir.class<!fir.ptr<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>>>, !fir.dscope) -> (!fir.ref<!fir.class<!fir.ptr<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>>>, !fir.ref<!fir.class<!fir.ptr<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>>>) +! CHECK: %[[ARG1_DECL:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QMcall_dispatchFcheck_dispatch_pointer_arrayEt"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>>>) ! CHECK: %{{.*}} = fir.do_loop {{.*}} { ! CHECK: %[[LOAD_ARG0:.*]] = fir.load %[[ARG0_DECL]]#0 : !fir.ref<!fir.class<!fir.ptr<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>>> @@ -332,10 +332,10 @@ module call_dispatch end subroutine ! CHECK-LABEL: func.func @_QMcall_dispatchPcheck_dispatch_dynamic_array_copy( -! CHECK-SAME: %[[ARG0:.*]]: !fir.class<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>> {fir.bindc_name = "p"}, +! CHECK-SAME: %[[ARG0:.*]]: !fir.class<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>> {fir.bindc_name = "p"}, ! CHECK-SAME: %[[ARG1:.*]]: !fir.class<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>> {fir.bindc_name = "o"}) { -! CHECK: %[[ARG1_DECL:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %{{[0-9]+}} {uniq_name = "_QMcall_dispatchFcheck_dispatch_dynamic_array_copyEo"} : (!fir.class<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>, !fir.dscope) -> (!fir.class<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>, !fir.class<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>) -! CHECK: %[[ARG0_DECL:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{[0-9]+}} {uniq_name = "_QMcall_dispatchFcheck_dispatch_dynamic_array_copyEp"} : (!fir.class<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>, !fir.dscope) -> (!fir.class<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>, !fir.class<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>) +! CHECK: %[[ARG1_DECL:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QMcall_dispatchFcheck_dispatch_dynamic_array_copyEo"} : (!fir.class<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>, !fir.dscope) -> (!fir.class<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>, !fir.class<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>) +! CHECK: %[[ARG0_DECL:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QMcall_dispatchFcheck_dispatch_dynamic_array_copyEp"} : (!fir.class<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>, !fir.dscope) -> (!fir.class<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>, !fir.class<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>) ! CHECK: %{{.*}} = fir.do_loop {{.*}} { ! CHECK: %[[DESIGNATE0:.*]] = hlfir.designate %[[ARG0_DECL]]#0 (%{{.*}}) : (!fir.class<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>, i64) -> !fir.class<!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>> diff --git a/flang/test/Lower/do_concurrent_delayed_locality.f90 b/flang/test/Lower/do_concurrent_delayed_locality.f90 index 6cae0eb..9d1efcd 100644 --- a/flang/test/Lower/do_concurrent_delayed_locality.f90 +++ b/flang/test/Lower/do_concurrent_delayed_locality.f90 @@ -7,7 +7,7 @@ subroutine do_concurrent_with_locality_specs do concurrent (i=1:10) local(local_var) local_init(local_init_var) if (i < 5) then local_var = 42 - else + else local_init_var = 84 end if end do diff --git a/flang/test/Lower/do_concurrent_reduce.f90 b/flang/test/Lower/do_concurrent_reduce.f90 index 8591a21..6d6d56c 100644 --- a/flang/test/Lower/do_concurrent_reduce.f90 +++ b/flang/test/Lower/do_concurrent_reduce.f90 @@ -26,7 +26,7 @@ end ! CHECK: fir.do_concurrent { ! CHECK: %[[VAL_0:.*]] = fir.alloca i32 {bindc_name = "i"} ! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = "_QFdo_concurrent_reduceEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) -! CHECK: fir.do_concurrent.loop (%{{.*}}) = (%{{.*}}) to (%{{.*}}) step (%{{[^[:space:]]+}}) +! CHECK: fir.do_concurrent.loop (%{{.*}}) = (%{{.*}}) to (%{{.*}}) step (%{{[^[:space:]]+}}) ! CHECK-SAME: reduce(@add_reduction_i32 #fir.reduce_attr<add> %[[S_DECL]]#0 -> %[[S_ARG:.*]] : !fir.ref<i32>) { ! CHECK: %[[S_ARG_DECL:.*]]:2 = hlfir.declare %[[S_ARG]] {uniq_name = "_QFdo_concurrent_reduceEs"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) diff --git a/flang/test/Lower/do_concurrent_reduce_allocatable.f90 b/flang/test/Lower/do_concurrent_reduce_allocatable.f90 index 873fd10..4fb67c0 100644 --- a/flang/test/Lower/do_concurrent_reduce_allocatable.f90 +++ b/flang/test/Lower/do_concurrent_reduce_allocatable.f90 @@ -8,7 +8,7 @@ subroutine do_concurrent_allocatable end do end subroutine -! CHECK: fir.declare_reduction @[[RED_OP:.*]] : ![[RED_TYPE:.*]] alloc { +! CHECK: fir.declare_reduction @[[RED_OP:.*]] : ![[RED_TYPE:.*]] attributes {byref_element_type = !fir.array<?x?xf32>} alloc { ! CHECK: %[[ALLOC:.*]] = fir.alloca ! CHECK: fir.yield(%[[ALLOC]] : ![[RED_TYPE]]) ! CHECK: } init { diff --git a/flang/test/Lower/do_loop.f90 b/flang/test/Lower/do_loop.f90 index 065324a..d353528 100644 --- a/flang/test/Lower/do_loop.f90 +++ b/flang/test/Lower/do_loop.f90 @@ -3,7 +3,7 @@ ! RUN: %flang_fc1 -mllvm --use-desc-for-alloc=false -emit-fir -flang-deprecated-no-hlfir -fwrapv -o - %s | FileCheck %s --check-prefix=NO-NSW ! Simple tests for structured ordered loops with loop-control. -! Tests the structure of the loop, storage to index variable and return and +! Tests the structure of the loop, storage to index variable and return and ! storage of the final value of the index variable. ! NO-NSW-NOT: overflow<nsw> diff --git a/flang/test/Lower/do_loop_unstructured.f90 b/flang/test/Lower/do_loop_unstructured.f90 index 3b03850..9c7d874 100644 --- a/flang/test/Lower/do_loop_unstructured.f90 +++ b/flang/test/Lower/do_loop_unstructured.f90 @@ -235,6 +235,7 @@ end subroutine subroutine unstructured_do_concurrent logical :: success do concurrent (i=1:10) local(success) + success = .false. error stop "fail" enddo end diff --git a/flang/test/Lower/dummy-argument-contiguous.f90 b/flang/test/Lower/dummy-argument-contiguous.f90 index 118370c..19bc3818 100644 --- a/flang/test/Lower/dummy-argument-contiguous.f90 +++ b/flang/test/Lower/dummy-argument-contiguous.f90 @@ -2,7 +2,7 @@ ! RUN: bbc -emit-fir -hlfir=false -gen-array-coor %s -o - | FileCheck %s --check-prefix=ArrayCoorCHECK ! Test that non-contiguous assumed-shape memory layout is handled in lowering. -! In practice, test that input fir.box is propagated to fir operations +! In practice, test that input fir.box is propagated to fir operations ! Also test that when the contiguous keyword is present, lowering adds the ! attribute to the fir argument and that is takes the contiguity into account diff --git a/flang/test/Lower/dummy-procedure-character.f90 b/flang/test/Lower/dummy-procedure-character.f90 index a9a8a5a..7a6bb24 100644 --- a/flang/test/Lower/dummy-procedure-character.f90 +++ b/flang/test/Lower/dummy-procedure-character.f90 @@ -234,7 +234,7 @@ end subroutine ! CHECK-SAME: %[[VAL_0:.*]]: tuple<!fir.boxproc<() -> ()>, i64> {fir.char_proc}) subroutine host2(f) ! Test that dummy length is overridden by local length even when used - ! in the internal procedure. + ! in the internal procedure. character*(42) :: f external :: f ! CHECK: %[[VAL_3:.*]] = fir.coordinate_of %[[VAL_1:.*]], %{{.*}} : (!fir.ref<tuple<tuple<!fir.boxproc<() -> ()>, i64>>>, i32) -> !fir.ref<tuple<!fir.boxproc<() -> ()>, i64>> diff --git a/flang/test/Lower/dummy-procedure.f90 b/flang/test/Lower/dummy-procedure.f90 index a84c351..a02aa21 100644 --- a/flang/test/Lower/dummy-procedure.f90 +++ b/flang/test/Lower/dummy-procedure.f90 @@ -141,7 +141,7 @@ subroutine test_iabs() call foo_iabs(iabs) end subroutine -! TODO: exhaustive test of unrestricted intrinsic table 16.2 +! TODO: exhaustive test of unrestricted intrinsic table 16.2 ! TODO: improve dummy procedure types when interface is given. ! CHECK: func @_QPtodo3( diff --git a/flang/test/Lower/entry-statement.f90 b/flang/test/Lower/entry-statement.f90 index f1e535a..387cd05 100644 --- a/flang/test/Lower/entry-statement.f90 +++ b/flang/test/Lower/entry-statement.f90 @@ -198,7 +198,7 @@ subroutine ashapec(asc) ! CHECK: %[[VAL_2:.*]] = fir.alloca !fir.box<!fir.heap<!fir.array<?xi32>>> ! CHECK: %[[VAL_3:.*]] = fir.dummy_scope : !fir.dscope ! CHECK: %[[VAL_4:.*]] = arith.constant 1 : index -! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_0]] typeparams %[[VAL_4]] dummy_scope %[[VAL_3]] {uniq_name = "_QFashapecEasc"} : (!fir.box<!fir.array<?x!fir.char<1>>>, index, !fir.dscope) -> (!fir.box<!fir.array<?x!fir.char<1>>>, !fir.box<!fir.array<?x!fir.char<1>>>) +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_0]] typeparams %[[VAL_4]] dummy_scope %[[VAL_3]] arg {{[0-9]+}} {uniq_name = "_QFashapecEasc"} : (!fir.box<!fir.array<?x!fir.char<1>>>, index, !fir.dscope) -> (!fir.box<!fir.array<?x!fir.char<1>>>, !fir.box<!fir.array<?x!fir.char<1>>>) ! CHECK: %[[VAL_6:.*]] = fir.zero_bits !fir.heap<!fir.array<?xi32>> ! CHECK: %[[VAL_7:.*]] = arith.constant 0 : index ! CHECK: %[[VAL_8:.*]] = fir.shape %[[VAL_7]] : (index) -> !fir.shape<1> @@ -252,7 +252,7 @@ entry ashapei(asi) ! CHECK: %[[VAL_12:.*]] = fir.box_addr %[[VAL_8]] : (!fir.box<!fir.heap<!fir.array<?x!fir.char<1>>>>) -> !fir.heap<!fir.array<?x!fir.char<1>>> ! CHECK: %[[VAL_13:.*]] = fir.shape_shift %[[VAL_10]]#0, %[[VAL_10]]#1 : (index, index) -> !fir.shapeshift<1> ! CHECK: %[[VAL_14:.*]]:2 = hlfir.declare %[[VAL_12]](%[[VAL_13]]) typeparams %[[VAL_11]] {uniq_name = "_QFashapecEasc"} : (!fir.heap<!fir.array<?x!fir.char<1>>>, !fir.shapeshift<1>, index) -> (!fir.box<!fir.array<?x!fir.char<1>>>, !fir.heap<!fir.array<?x!fir.char<1>>>) -! CHECK: %[[VAL_15:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_3]] {uniq_name = "_QFashapecEasi"} : (!fir.box<!fir.array<?xi32>>, !fir.dscope) -> (!fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>>) +! CHECK: %[[VAL_15:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_3]] arg {{[0-9]+}} {uniq_name = "_QFashapecEasi"} : (!fir.box<!fir.array<?xi32>>, !fir.dscope) -> (!fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>>) ! CHECK: %[[VAL_16:.*]] = fir.zero_bits !fir.heap<!fir.array<?xcomplex<f32>>> ! CHECK: %[[VAL_17:.*]] = arith.constant 0 : index ! CHECK: %[[VAL_18:.*]] = fir.shape %[[VAL_17]] : (index) -> !fir.shape<1> @@ -303,7 +303,7 @@ end ! CHECK: %[[VAL_22:.*]] = fir.box_addr %[[VAL_19]] : (!fir.box<!fir.heap<!fir.array<?xi32>>>) -> !fir.heap<!fir.array<?xi32>> ! CHECK: %[[VAL_23:.*]] = fir.shape_shift %[[VAL_21]]#0, %[[VAL_21]]#1 : (index, index) -> !fir.shapeshift<1> ! CHECK: %[[VAL_24:.*]]:2 = hlfir.declare %[[VAL_22]](%[[VAL_23]]) {uniq_name = "_QFashapecEasi"} : (!fir.heap<!fir.array<?xi32>>, !fir.shapeshift<1>) -> (!fir.box<!fir.array<?xi32>>, !fir.heap<!fir.array<?xi32>>) -! CHECK: %[[VAL_25:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_3]] {uniq_name = "_QFashapecEasx"} : (!fir.box<!fir.array<?xcomplex<f32>>>, !fir.dscope) -> (!fir.box<!fir.array<?xcomplex<f32>>>, !fir.box<!fir.array<?xcomplex<f32>>>) +! CHECK: %[[VAL_25:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_3]] arg {{[0-9]+}} {uniq_name = "_QFashapecEasx"} : (!fir.box<!fir.array<?xcomplex<f32>>>, !fir.dscope) -> (!fir.box<!fir.array<?xcomplex<f32>>>, !fir.box<!fir.array<?xcomplex<f32>>>) ! CHECK: cf.br ^bb1 ! CHECK: ^bb1: ! CHECK: hlfir.assign %{{.*}} to %[[VAL_25]]#0 : complex<f32>, !fir.box<!fir.array<?xcomplex<f32>>> @@ -343,7 +343,7 @@ function f1(n1) result(res1) ! CHECK-SAME: %[[VAL_1:.*]]: index, ! CHECK-SAME: %[[VAL_2:.*]]: !fir.ref<i32> {fir.bindc_name = "n1"}) -> !fir.boxchar<1> { ! CHECK: %[[VAL_3:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_2]] dummy_scope %[[VAL_3]] {uniq_name = "_QFf1En1"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_2]] dummy_scope %[[VAL_3]] arg {{[0-9]+}} {uniq_name = "_QFf1En1"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_5:.*]] = fir.alloca i32 {bindc_name = "n2", uniq_name = "_QFf1En2"} ! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_5]] {uniq_name = "_QFf1En2"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_7:.*]] = arith.constant 5 : index @@ -391,7 +391,7 @@ entry f2(n2) ! CHECK: %[[VAL_3:.*]] = fir.dummy_scope : !fir.dscope ! CHECK: %[[VAL_4:.*]] = fir.alloca i32 {bindc_name = "n1", uniq_name = "_QFf1En1"} ! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_4]] {uniq_name = "_QFf1En1"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) -! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_2]] dummy_scope %[[VAL_3]] {uniq_name = "_QFf1En2"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_2]] dummy_scope %[[VAL_3]] arg {{[0-9]+}} {uniq_name = "_QFf1En2"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_7:.*]] = arith.constant 5 : index ! CHECK: %[[VAL_8:.*]]:2 = hlfir.declare %[[VAL_0]] typeparams %[[VAL_7]] {uniq_name = "_QFf1Eres1"} : (!fir.ref<!fir.char<1,5>>, index) -> (!fir.ref<!fir.char<1,5>>, !fir.ref<!fir.char<1,5>>) ! CHECK: %[[VAL_9:.*]] = arith.constant 5 : index @@ -493,7 +493,7 @@ end subroutine ! CHECK: %[[VAL_1:.*]] = fir.dummy_scope : !fir.dscope ! CHECK: %[[VAL_2:.*]] = fir.assumed_size_extent : index ! CHECK: %[[VAL_3:.*]] = fir.shape %[[VAL_2]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_3]]) dummy_scope %[[VAL_1]] {uniq_name = "_QFassumed_sizeEx"} : (!fir.ref<!fir.array<?xf32>>, !fir.shape<1>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.ref<!fir.array<?xf32>>) +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_3]]) dummy_scope %[[VAL_1]] arg {{[0-9]+}} {uniq_name = "_QFassumed_sizeEx"} : (!fir.ref<!fir.array<?xf32>>, !fir.shape<1>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.ref<!fir.array<?xf32>>) ! CHECK: cf.br ^bb1 ! CHECK: ^bb1: ! CHECK: return diff --git a/flang/test/Lower/equivalence-1.f90 b/flang/test/Lower/equivalence-1.f90 index 133accd..deb3a5b 100644 --- a/flang/test/Lower/equivalence-1.f90 +++ b/flang/test/Lower/equivalence-1.f90 @@ -53,7 +53,7 @@ SUBROUTINE s3 ! CHECK: %{{.*}} = fir.load %[[v2loc]] : !fir.ref<f32> PRINT *, r(9) END SUBROUTINE s3 - + ! test that equivalence in main program containing arrays are placed in global memory. ! CHECK: fir.global internal @_QFEa : !fir.array<400000000xi8> integer :: a, b(100000000) diff --git a/flang/test/Lower/equivalence-2.f90 b/flang/test/Lower/equivalence-2.f90 index 2cea88e..1c45060 100644 --- a/flang/test/Lower/equivalence-2.f90 +++ b/flang/test/Lower/equivalence-2.f90 @@ -61,7 +61,7 @@ end subroutine subroutine eq_and_entry_foo SAVE x, i DIMENSION :: x(2) - EQUIVALENCE (x(2), i) + EQUIVALENCE (x(2), i) call foo1(x, i) ! CHECK: %[[xi:.*]] = fir.address_of(@_QFeq_and_entry_fooEi) : !fir.ref<!fir.array<8xi8>> diff --git a/flang/test/Lower/explicit-interface-results.f90 b/flang/test/Lower/explicit-interface-results.f90 index 612d57b..8d51786 100644 --- a/flang/test/Lower/explicit-interface-results.f90 +++ b/flang/test/Lower/explicit-interface-results.f90 @@ -313,7 +313,7 @@ contains function result_depends_on_equiv_sym() character(l) :: result_depends_on_equiv_sym call set_result_with_some_value(result_depends_on_equiv_sym) - end function + end function end module ! CHECK-LABEL: func @_QPtest_result_depends_on_equiv_sym @@ -387,7 +387,7 @@ function test_recursion(n) result(res) if (n.eq.1) then res = char(some_local(1)) ! CHECK: else - else + else ! CHECK-NOT: fir.alloca !fir.array<?xi32> ! verify that the actual argument for symbol n ("n-1") is used to allocate diff --git a/flang/test/Lower/forall-pointer-assignment.f90 b/flang/test/Lower/forall-pointer-assignment.f90 index ec142e3..62184a7 100644 --- a/flang/test/Lower/forall-pointer-assignment.f90 +++ b/flang/test/Lower/forall-pointer-assignment.f90 @@ -1,4 +1,4 @@ -! Test lower of FORALL pointer assignment +! Test lower of FORALL pointer assignment ! RUN: bbc -emit-fir %s -o - | FileCheck %s @@ -70,7 +70,7 @@ ! CHECK: %[[V_11:[0-9]+]] = fir.alloca !fir.array<10x!fir.type<_QFforallpolymorphic2Tdt{ptr:!fir.box<!fir.ptr<!fir.array<?x!fir.type<_QFforallpolymorphic2Tdt>>>>}>> {bindc_name = "t", uniq_name = "_QFforallpolymorphic2Et"} ! CHECK: %[[V_12:[0-9]+]] = fir.shape %c10 : (index) -> !fir.shape<1> ! CHECK: %[[V_13:[0-9]+]] = fir.declare %[[V_11]](%[[V_12]]) {uniq_name = "_QFforallpolymorphic2Et"} : (!fir.ref<!fir.array<10x!fir.type<_QFforallpolymorphic2Tdt{ptr:!fir.box<!fir.ptr<!fir.array<?x!fir.type<_QFforallpolymorphic2Tdt>>>>}>>>, !fir.shape<1>) -> !fir.ref<!fir.array<10x!fir.type<_QFforallpolymorphic2Tdt{ptr:!fir.box<!fir.ptr<!fir.array<?x!fir.type<_QFforallpolymorphic2Tdt>>>>}>>> -! CHECK: %[[V_18:[0-9]+]] = fir.declare %arg0 dummy_scope %0 {fortran_attrs = #fir.var_attrs<allocatable, target>, uniq_name = "_QFforallpolymorphic2Etar1"} : (!fir.ref<!fir.class<!fir.heap<!fir.array<?x!fir.type<_QFforallpolymorphic2Tdt{ptr:!fir.box<!fir.ptr<!fir.array<?x!fir.type<_QFforallpolymorphic2Tdt>>>>}>>>>>, !fir.dscope) -> !fir.ref<!fir.class<!fir.heap<!fir.array<?x!fir.type<_QFforallpolymorphic2Tdt{ptr:!fir.box<!fir.ptr<!fir.array<?x!fir.type<_QFforallpolymorphic2Tdt>>>>}>>>>> +! CHECK: %[[V_18:[0-9]+]] = fir.declare %arg0 dummy_scope %0 {{.*}} {fortran_attrs = #fir.var_attrs<allocatable, target>, uniq_name = "_QFforallpolymorphic2Etar1"} : (!fir.ref<!fir.class<!fir.heap<!fir.array<?x!fir.type<_QFforallpolymorphic2Tdt{ptr:!fir.box<!fir.ptr<!fir.array<?x!fir.type<_QFforallpolymorphic2Tdt>>>>}>>>>>, !fir.dscope) -> !fir.ref<!fir.class<!fir.heap<!fir.array<?x!fir.type<_QFforallpolymorphic2Tdt{ptr:!fir.box<!fir.ptr<!fir.array<?x!fir.type<_QFforallpolymorphic2Tdt>>>>}>>>>> ! CHECK: %[[V_30:[0-9]+]] = fir.convert %c1_i32 : (i32) -> index ! CHECK: %[[V_31:[0-9]+]] = fir.convert %c10_i32 : (i32) -> index ! CHECK: fir.do_loop %arg1 = %[[V_30]] to %[[V_31]] step %c1 diff --git a/flang/test/Lower/forall/array-pointer.f90 b/flang/test/Lower/forall/array-pointer.f90 index fd3efed..6b8c564 100644 --- a/flang/test/Lower/forall/array-pointer.f90 +++ b/flang/test/Lower/forall/array-pointer.f90 @@ -318,7 +318,6 @@ end subroutine s2_3 ! CHECK-LABEL: func @_QPs2_3( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.box<!fir.array<?x!fir.type<_QMarray_of_pointer_testTt{ip:!fir.box<!fir.ptr<i32>>}>>> {fir.bindc_name = "x"}) { ! CHECK: %[[VAL_1:.*]] = fir.alloca i32 {adapt.valuebyref, bindc_name = "i"} -! CHECK: %[[VAL_2:.*]] = fir.alloca !fir.box<!fir.heap<!fir.array<?xi32>>> {bindc_name = "y", fir.target, uniq_name = "_QFs2_3Ey"} ! CHECK: %[[VAL_3:.*]] = fir.alloca !fir.heap<!fir.array<?xi32>> {uniq_name = "_QFs2_3Ey.addr"} ! CHECK: %[[VAL_4:.*]] = fir.alloca index {uniq_name = "_QFs2_3Ey.lb0"} ! CHECK: %[[VAL_5:.*]] = fir.alloca index {uniq_name = "_QFs2_3Ey.ext0"} diff --git a/flang/test/Lower/forall/forall-2.f90 b/flang/test/Lower/forall/forall-2.f90 index cdafb4f..c6a20f5 100644 --- a/flang/test/Lower/forall/forall-2.f90 +++ b/flang/test/Lower/forall/forall-2.f90 @@ -16,7 +16,7 @@ subroutine implied_iters_allocatable(thing, a1) end type t type(t) :: thing(:) integer :: i - + forall (i=5:13) ! commenting out this test for the moment (hits assert) ! thing(i)%arr = a1 @@ -32,7 +32,7 @@ subroutine conflicting_allocatable(thing, lo, hi) end type t type(t) :: thing(:) integer :: i - + forall (i = lo:hi) ! commenting out this test for the moment (hits assert) ! thing(i)%arr = thing(hi-i)%arr diff --git a/flang/test/Lower/forall/forall-allocatable.f90 b/flang/test/Lower/forall/forall-allocatable.f90 index 96cd37e..8e54d28 100644 --- a/flang/test/Lower/forall/forall-allocatable.f90 +++ b/flang/test/Lower/forall/forall-allocatable.f90 @@ -13,20 +13,19 @@ end subroutine forall_with_allocatable ! CHECK-LABEL: func @_QPforall_with_allocatable( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.box<!fir.array<?xf32>>{{.*}}) { ! CHECK: %[[VAL_1:.*]] = fir.alloca i32 {adapt.valuebyref, bindc_name = "i"} -! CHECK: %[[VAL_2:.*]] = fir.alloca !fir.box<!fir.heap<!fir.array<?xf32>>> {bindc_name = "arr", uniq_name = "_QFforall_with_allocatableEarr"} -! CHECK: %[[VAL_3:.*]] = fir.alloca !fir.heap<!fir.array<?xf32>> {uniq_name = "_QFforall_with_allocatableEarr.addr"} -! CHECK: %[[VAL_4:.*]] = fir.alloca index {uniq_name = "_QFforall_with_allocatableEarr.lb0"} -! CHECK: %[[VAL_5:.*]] = fir.alloca index {uniq_name = "_QFforall_with_allocatableEarr.ext0"} -! CHECK: %[[VAL_6:.*]] = fir.zero_bits !fir.heap<!fir.array<?xf32>> -! CHECK: fir.store %[[VAL_6]] to %[[VAL_3]] : !fir.ref<!fir.heap<!fir.array<?xf32>>> +! CHECK: %[[VAL_2:.*]] = fir.alloca !fir.heap<!fir.array<?xf32>> {uniq_name = "_QFforall_with_allocatableEarr.addr"} +! CHECK: %[[VAL_3:.*]] = fir.alloca index {uniq_name = "_QFforall_with_allocatableEarr.lb0"} +! CHECK: %[[VAL_4:.*]] = fir.alloca index {uniq_name = "_QFforall_with_allocatableEarr.ext0"} +! CHECK: %[[VAL_5:.*]] = fir.zero_bits !fir.heap<!fir.array<?xf32>> +! CHECK: fir.store %[[VAL_5]] to %[[VAL_2]] : !fir.ref<!fir.heap<!fir.array<?xf32>>> ! CHECK: %[[VAL_7:.*]] = arith.constant 5 : i32 ! CHECK: %[[VAL_8:.*]] = fir.convert %[[VAL_7]] : (i32) -> index ! CHECK: %[[VAL_9:.*]] = arith.constant 15 : i32 ! CHECK: %[[VAL_10:.*]] = fir.convert %[[VAL_9]] : (i32) -> index ! CHECK: %[[VAL_11:.*]] = arith.constant 1 : index -! CHECK: %[[VAL_12:.*]] = fir.load %[[VAL_4]] : !fir.ref<index> -! CHECK: %[[VAL_13:.*]] = fir.load %[[VAL_5]] : !fir.ref<index> -! CHECK: %[[VAL_14:.*]] = fir.load %[[VAL_3]] : !fir.ref<!fir.heap<!fir.array<?xf32>>> +! CHECK: %[[VAL_12:.*]] = fir.load %[[VAL_3]] : !fir.ref<index> +! CHECK: %[[VAL_13:.*]] = fir.load %[[VAL_4]] : !fir.ref<index> +! CHECK: %[[VAL_14:.*]] = fir.load %[[VAL_2]] : !fir.ref<!fir.heap<!fir.array<?xf32>>> ! CHECK: %[[VAL_15:.*]] = fir.shape_shift %[[VAL_12]], %[[VAL_13]] : (index, index) -> !fir.shapeshift<1> ! CHECK: %[[VAL_16:.*]] = fir.array_load %[[VAL_14]](%[[VAL_15]]) : (!fir.heap<!fir.array<?xf32>>, !fir.shapeshift<1>) -> !fir.array<?xf32> ! CHECK: %[[VAL_17:.*]] = fir.array_load %[[VAL_0]] : (!fir.box<!fir.array<?xf32>>) -> !fir.array<?xf32> diff --git a/flang/test/Lower/forall/forall-ranked.f90 b/flang/test/Lower/forall/forall-ranked.f90 index 9e56be9..f508c67 100644 --- a/flang/test/Lower/forall/forall-ranked.f90 +++ b/flang/test/Lower/forall/forall-ranked.f90 @@ -68,7 +68,7 @@ subroutine test_forall_with_ranked_dimension integer :: arr(11) end type t type(t) :: a(10,10) - + forall (i=1:5) a(i,:)%arr(i+4) = f(i) end forall diff --git a/flang/test/Lower/forall/forall-where-2.f90 b/flang/test/Lower/forall/forall-where-2.f90 index c075508..85aab87 100644 --- a/flang/test/Lower/forall/forall-where-2.f90 +++ b/flang/test/Lower/forall/forall-where-2.f90 @@ -6,7 +6,7 @@ ! Test a FORALL construct with a nested WHERE construct where the mask ! contains temporary array expressions. -subroutine test_nested_forall_where_with_temp_in_mask(a,b) +subroutine test_nested_forall_where_with_temp_in_mask(a,b) interface function temp_foo(i, j) integer :: i, j @@ -28,10 +28,10 @@ end subroutine ! CHECK: func @_QPtest_nested_forall_where_with_temp_in_mask({{.*}}) { ! CHECK: %[[tempResultBox:.*]] = fir.alloca !fir.box<!fir.heap<!fir.array<?xf32>>> {bindc_name = ".result"} - ! Where condition pre-evaluation + ! Where condition pre-evaluation ! CHECK: fir.do_loop {{.*}} { ! CHECK: fir.do_loop {{.*}} { - ! Evaluation of mask for iteration (i,j) into ragged array temp + ! Evaluation of mask for iteration (i,j) into ragged array temp ! CHECK: %[[tempResult:.*]] = fir.call @_QPtemp_foo ! CHECK: fir.save_result %[[tempResult]] to %[[tempResultBox]] : !fir.box<!fir.heap<!fir.array<?xf32>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>> ! CHECK: fir.if {{.*}} { @@ -52,7 +52,7 @@ end subroutine ! CHECK: fir.do_loop {{.*}} { ! Array assignment at iteration (i, j) ! CHECK: fir.do_loop {{.*}} { -! CHECK: fir.if {{.*}} { +! CHECK: fir.if {{.*}} { ! CHECK: arith.divf ! CHECK: } else { ! CHECK: } @@ -64,7 +64,7 @@ end subroutine ! CHECK: fir.do_loop {{.*}} { ! Array assignment at iteration (i, j) ! CHECK: fir.do_loop {{.*}} { -! CHECK: fir.if {{.*}} { +! CHECK: fir.if {{.*}} { ! CHECK: } else { ! CHECK: arith.negf ! CHECK: } diff --git a/flang/test/Lower/forall/forall-where.f90 b/flang/test/Lower/forall/forall-where.f90 index 54ff2bd..3202edb 100644 --- a/flang/test/Lower/forall/forall-where.f90 +++ b/flang/test/Lower/forall/forall-where.f90 @@ -6,7 +6,7 @@ ! This has both an explicit and implicit iteration space. The WHERE construct ! makes the assignments conditional and the where mask evaluation must happen ! prior to evaluating the array assignment statement. -subroutine test_nested_forall_where(a,b) +subroutine test_nested_forall_where(a,b) type t real data(100) end type t diff --git a/flang/test/Lower/forall/scalar-substring.f90 b/flang/test/Lower/forall/scalar-substring.f90 index f70221a..8ed2406 100644 --- a/flang/test/Lower/forall/scalar-substring.f90 +++ b/flang/test/Lower/forall/scalar-substring.f90 @@ -12,7 +12,7 @@ end subroutine s ! CHECK: %[[VAL_2:.*]]:2 = fir.unboxchar %[[VAL_0]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index) ! CHECK: %[[VAL_3:.*]] = fir.convert %[[VAL_2]]#0 : (!fir.ref<!fir.char<1,?>>) -> !fir.ref<!fir.char<1,10>> ! CHECK: %[[VAL_4:.*]] = arith.constant 10 : index -! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_3]] typeparams %[[VAL_4]] dummy_scope %[[VAL_1]] {uniq_name = "_QFsEch"} : (!fir.ref<!fir.char<1,10>>, index, !fir.dscope) -> (!fir.ref<!fir.char<1,10>>, !fir.ref<!fir.char<1,10>>) +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_3]] typeparams %[[VAL_4]] dummy_scope %[[VAL_1]] arg {{[0-9]+}} {uniq_name = "_QFsEch"} : (!fir.ref<!fir.char<1,10>>, index, !fir.dscope) -> (!fir.ref<!fir.char<1,10>>, !fir.ref<!fir.char<1,10>>) ! CHECK: %[[VAL_6:.*]] = arith.constant 1 : i32 ! CHECK: %[[VAL_7:.*]] = arith.constant 4 : i32 ! CHECK: hlfir.forall lb { diff --git a/flang/test/Lower/force-temp.f90 b/flang/test/Lower/force-temp.f90 index d9ba543..093e098 100644 --- a/flang/test/Lower/force-temp.f90 +++ b/flang/test/Lower/force-temp.f90 @@ -27,6 +27,14 @@ module test integer, intent(out) :: buf(5) end subroutine end interface + + ! Used by call_s6() and others below + type base + integer :: i = -1 + end type + type, extends (base) :: child + real :: r = -2.0 + end type contains subroutine s1(buf) !CHECK-LABEL: func.func @_QMtestPs1 @@ -79,4 +87,54 @@ contains p => x(::2) ! pointer to non-contiguous array section call pass_intent_out(p) end subroutine + subroutine call_s6() + interface + subroutine s6(b) + import :: base + type(base), intent(inout) :: b(:) + end subroutine s6 + end interface + class(base), pointer :: pb(:) + type(child), target :: c(2) +!CHECK-LABEL: func.func @_QMtestPcall_s6 +!CHECK-NOT: hlfir.copy_in +!CHECK: fir.call @_QPs6 +!CHECK-NOT: hlfir.copy_out + pb => c + call s6(pb) + end subroutine call_s6 + subroutine call_s7() + interface + subroutine s7(b1, b2, n) + import :: base + integer :: n + type(base), intent(inout) :: b1(n) + type(base), intent(inout) :: b2(*) + end subroutine + end interface + integer, parameter :: n = 7 + class(base), allocatable :: c1(:), c2(:) +!CHECK-LABEL: func.func @_QMtestPcall_s7 +!CHECK: hlfir.copy_in +!CHECK: hlfir.copy_in +!CHECK: fir.call @_QPs7 +!CHECK: hlfir.copy_out +!CHECK: hlfir.copy_out + call s7(c1, c2, n) + end subroutine call_s7 + subroutine call_s8() + interface + subroutine s8(buf) + ! IGNORE_TKR(C) takes precendence over CONTIGUOUS + !DIR$ IGNORE_TKR(C) buf + real, contiguous :: buf(:) + end subroutine + end interface + real a(10) +!CHECK-LABEL: func.func @_QMtestPcall_s8 +!CHECK-NOT: hlfir.copy_in +!CHECK: fir.call @_QPs8 +!CHECK-NOT: hlfir.copy_out + call s8(a(1:5:2)) + end subroutine call_s8 end module diff --git a/flang/test/Lower/host-associated.f90 b/flang/test/Lower/host-associated.f90 index d539241..d1f3b35 100644 --- a/flang/test/Lower/host-associated.f90 +++ b/flang/test/Lower/host-associated.f90 @@ -135,7 +135,7 @@ subroutine test3(p,q,i) if (p(2) .ne. -42.0) then print *, "failed" end if - + contains ! CHECK-LABEL: func private @_QFtest3Ptest3_inner( ! CHECK-SAME: %[[tup:.*]]: !fir.ref<tuple<!fir.box<!fir.array<?xf32>>, !fir.box<!fir.array<?xf32>>>> {fir.host_assoc}) attributes {fir.host_symbol = {{.*}}, llvm.linkage = #llvm.linkage<internal>} { @@ -182,7 +182,7 @@ subroutine test3a(p) if (p(1) .ne. -42.0) then print *, "failed" end if - + contains ! CHECK: func private @_QFtest3aPtest3a_inner( ! CHECK-SAME: %[[tup:.*]]: !fir.ref<tuple<!fir.box<!fir.array<10xf32>>, !fir.box<!fir.array<10xf32>>>> {fir.host_assoc}) attributes {fir.host_symbol = {{.*}}, llvm.linkage = #llvm.linkage<internal>} { @@ -226,7 +226,7 @@ subroutine test4 if (p .ne. -42.0) then print *, "failed" end if - + contains ! CHECK-LABEL: func private @_QFtest4Ptest4_inner( ! CHECK-SAME:%[[tup:.*]]: !fir.ref<tuple<!fir.ref<!fir.box<!fir.ptr<f32>>>, !fir.ref<!fir.box<!fir.heap<f32>>>>> {fir.host_assoc}) attributes {fir.host_symbol = {{.*}}, llvm.linkage = #llvm.linkage<internal>} { @@ -268,7 +268,7 @@ subroutine test5 if (p(1) .ne. -42.0) then print *, "failed" end if - + contains ! CHECK-LABEL: func private @_QFtest5Ptest5_inner( ! CHECK-SAME:%[[tup:.*]]: !fir.ref<tuple<!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>>> {fir.host_assoc}) attributes {fir.host_symbol = {{.*}}, llvm.linkage = #llvm.linkage<internal>} { @@ -420,7 +420,7 @@ contains subroutine bar() ! CHECK: %[[tupAddr:.*]] = fir.coordinate_of %[[tup]], %c0{{.*}} : (!fir.ref<tuple<!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>>>, i32) -> !fir.llvm_ptr<!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>> ! CHECK: fir.load %[[tupAddr]] : !fir.llvm_ptr<!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>> - read (88, NML = a_namelist) + read (88, NML = a_namelist) end subroutine end subroutine @@ -642,7 +642,7 @@ end subroutine test_proc_dummy_char function get_message(a) character(40) :: get_message character(*) :: a - get_message = "message is: " // a() + get_message = "message is: " // a() end function get_message ! CHECK-LABEL: func @_QPtest_11a() { diff --git a/flang/test/Lower/identical-block-merge-disable.f90 b/flang/test/Lower/identical-block-merge-disable.f90 index cc3120a..ff3ff67 100644 --- a/flang/test/Lower/identical-block-merge-disable.f90 +++ b/flang/test/Lower/identical-block-merge-disable.f90 @@ -6,7 +6,7 @@ MODULE DMUMPS_SOL_LR IMPLICIT NONE TYPE BLR_STRUC_T - INTEGER, DIMENSION(:), POINTER :: PANELS_L + INTEGER, DIMENSION(:), POINTER :: PANELS_L INTEGER, DIMENSION(:), POINTER :: PANELS_U INTEGER, DIMENSION(:), POINTER :: BEGS_BLR_STATIC END TYPE BLR_STRUC_T @@ -32,7 +32,7 @@ SUBROUTINE DMUMPS_SOL_FWD_LR_SU( IWHDLR, MTYPE ) ENDIF ENDIF -END SUBROUTINE DMUMPS_SOL_FWD_LR_SU +END SUBROUTINE DMUMPS_SOL_FWD_LR_SU END MODULE DMUMPS_SOL_LR diff --git a/flang/test/Lower/ifconvert.f90 b/flang/test/Lower/ifconvert.f90 index 50ced6b..cbd1e79 100644 --- a/flang/test/Lower/ifconvert.f90 +++ b/flang/test/Lower/ifconvert.f90 @@ -1,4 +1,4 @@ -! RUN: bbc -fdebug-dump-pre-fir %s 2>&1 | FileCheck %s +! RUN: %flang_fc1 -fdebug-dump-pft %s 2>&1 | FileCheck %s ! Note: PFT dump output is fairly stable, including node indexes and ! annotations, so all output is CHECKed. diff --git a/flang/test/Lower/implicit-interface.f90 b/flang/test/Lower/implicit-interface.f90 index f924a3f..0be5020 100644 --- a/flang/test/Lower/implicit-interface.f90 +++ b/flang/test/Lower/implicit-interface.f90 @@ -22,7 +22,7 @@ subroutine test_passing_char_array ! CHECK-DAG: %[[c3:.*]] = arith.constant 3 : index ! CHECK-DAG: %[[xbuff:.*]] = fir.convert %[[xarray]] : (!fir.ref<!fir.array<4x!fir.char<1,3>>>) -> !fir.ref<!fir.char<1,?>> ! CHECK: %[[boxchar:.*]] = fir.emboxchar %[[xbuff]], %[[c3]] : (!fir.ref<!fir.char<1,?>>, index) -> !fir.boxchar<1> - ! CHECK: fir.call @_QPsub_taking_a_char_array(%[[boxchar]]) {{.*}}: (!fir.boxchar<1>) -> () + ! CHECK: fir.call @_QPsub_taking_a_char_array(%[[boxchar]]) {{.*}}: (!fir.boxchar<1>) -> () end subroutine ! TODO more implicit interface cases with/without explicit interface diff --git a/flang/test/Lower/inline_directive.f90 b/flang/test/Lower/inline_directive.f90 index 347df85..5748690 100644 --- a/flang/test/Lower/inline_directive.f90 +++ b/flang/test/Lower/inline_directive.f90 @@ -11,7 +11,7 @@ subroutine test_inline() y = g(x) !CHECK: %[[VAL_4:.*]] = fir.call @_QFtest_inlinePg(%[[VAL_1]]) fastmath<contract> {inline_attr = #fir.inline_attrs<always_inline>} : (!fir.ref<i32>) -> i32 !CHECK: fir.store %[[VAL_4]] to %[[VAL_3]] : !fir.ref<i32> - + !dir$ forceinline call f(x, y) !CHECK: fir.call @_QFtest_inlinePf(%[[VAL_1]], %[[VAL_3]]) fastmath<contract> {inline_attr = #fir.inline_attrs<always_inline>} : (!fir.ref<i32>, !fir.ref<i32>) -> () diff --git a/flang/test/Lower/io-statement-1.f90 b/flang/test/Lower/io-statement-1.f90 index ac78745..ecf2e2d 100644 --- a/flang/test/Lower/io-statement-1.f90 +++ b/flang/test/Lower/io-statement-1.f90 @@ -19,7 +19,7 @@ ! CHECK: call {{.*}}BeginFlush ! CHECK: call {{.*}}EndIoStatement flush(8) - + ! CHECK: call {{.*}}BeginRewind ! CHECK: call {{.*}}EndIoStatement rewind(8) diff --git a/flang/test/Lower/io-write.f90 b/flang/test/Lower/io-write.f90 index 234fcda..3159dcf 100644 --- a/flang/test/Lower/io-write.f90 +++ b/flang/test/Lower/io-write.f90 @@ -1,6 +1,6 @@ ! RUN: bbc -emit-fir -hlfir=false %s -o - | FileCheck %s -! Test that IO item calls stackrestore in the right place +! Test that IO item calls stackrestore in the right place ! CHECK-LABEL: func.func @_QQmain() { character(3) string diff --git a/flang/test/Lower/ivdep.f90 b/flang/test/Lower/ivdep.f90 new file mode 100644 index 0000000..93bcdae --- /dev/null +++ b/flang/test/Lower/ivdep.f90 @@ -0,0 +1,94 @@ +! RUN: %flang_fc1 -emit-hlfir -o - %s | FileCheck %s + +! CHECK: #access_group = #llvm.access_group<id = distinct[0]<>> +! CHECK: #access_group1 = #llvm.access_group<id = distinct[1]<>> +! CHECK: #access_group2 = #llvm.access_group<id = distinct[2]<>> +! CHECK: #loop_vectorize = #llvm.loop_vectorize<disable = false> +! CHECK: #loop_annotation = #llvm.loop_annotation<vectorize = #loop_vectorize, parallelAccesses = #access_group> +! CHECK: #loop_annotation1 = #llvm.loop_annotation<vectorize = #loop_vectorize, parallelAccesses = #access_group1> +! CHECK: #loop_annotation2 = #llvm.loop_annotation<vectorize = #loop_vectorize, parallelAccesses = #access_group2> + +! CHECK-LABEL: ivdep_test1 +subroutine ivdep_test1 + integer :: a(10) + !dir$ ivdep + !CHECK: fir.do_loop {{.*}} attributes {loopAnnotation = #loop_annotation} + do i=1,10 + a(i)=i + !CHECK: fir.store %[[ARG1:.*]] to %[[VAL_4:.*]]#0 {accessGroups = [#access_group]} + !CHECK: %[[VAL_9:.*]] = fir.load %[[VAL_4]]#0 {accessGroups = [#access_group]} + !CHECK: %[[VAL_10:.*]] = fir.load %[[VAL_4]]#0 {accessGroups = [#access_group]} + !CHECK: %[[VAL_11:.*]] = fir.convert %[[VAL_10]] : (i32) -> i64 + !CHECK: %[[VAL_12:.*]] = hlfir.designate %[[VAL_2:.*]]#0 (%[[VAL_11]]) : (!fir.ref<!fir.array<10xi32>>, i64) + !CHECK: hlfir.assign %[[VAL_9]] to %[[VAL_12]] {access_groups = [#access_group]} : i32, !fir.ref<i32> + !CHECK: %[[VAL_14:.*]] = fir.convert %[[C1:.*]] : (index) -> i32 + !CHECK: %[[VAL_15:.*]] = fir.load %[[VAL_4]]#0 {accessGroups = [#access_group]} + !CHECK: %[[VAL_16:.*]] = arith.addi %[[VAL_15]], %[[VAL_14]] overflow<nsw> : i32 + !CHECK: fir.result %[[VAL_16]] : i32 + end do +end subroutine ivdep_test1 + + +! CHECK-LABEL: ivdep_test2 +subroutine ivdep_test2 + integer :: a(10), b(10), c(10) + !dir$ ivdep + !dir$ unknown + !CHECK: fir.do_loop {{.*}} attributes {loopAnnotation = #loop_annotation1} + do i=1,10 + a(i)=b(i)+c(i) + !CHECK: fir.store %[[ARG1:.*]] to %[[VAL_10:.*]]#0 {accessGroups = [#access_group1]} + !CHECK: %[[VAL_15:.*]] = fir.load %[[VAL_10]]#0 {accessGroups = [#access_group1]} + !CHECK: %[[VAL_16:.*]] = fir.convert %[[VAL_15]] : (i32) -> i64 + !CHECK: %[[VAL_17:.*]] = hlfir.designate %[[VAL_5:.*]]#0 (%[[VAL_16]]) : (!fir.ref<!fir.array<10xi32>>, i64) + !CHECK: %[[VAL_18:.*]] = fir.load %[[VAL_17]] {accessGroups = [#access_group1]} + !CHECK: %[[VAL_19:.*]] = fir.load %[[VAL_10]]#0 {accessGroups = [#access_group1]} + !CHECK: %[[VAL_20:.*]] = fir.convert %[[VAL_19]] : (i32) -> i64 + !CHECK: %[[VAL_21:.*]] = hlfir.designate %[[VAL_8:.*]]#0 (%[[VAL_20]]) : (!fir.ref<!fir.array<10xi32>>, i64) + !CHECK: %[[VAL_22:.*]] = fir.load %[[VAL_21]] {accessGroups = [#access_group1]} + !CHECK: %[[VAL_23:.*]] = arith.addi %[[VAL_18]], %[[VAL_22]] : i32 + !CHECK: %[[VAL_24:.*]] = fir.load %[[VAL_10]]#0 {accessGroups = [#access_group1]} + !CHECK: %[[VAL_25:.*]] = fir.convert %[[VAL_24]] : (i32) -> i64 + !CHECK: %[[VAL_26:.*]] = hlfir.designate %[[VAL_2:.*]]#0 (%[[VAL_25]]) : (!fir.ref<!fir.array<10xi32>>, i64) + !CHECK: hlfir.assign %[[VAL_23]] to %[[VAL_26]] {access_groups = [#access_group1]} : i32, !fir.ref<i32> + !CHECK: %[[VAL_28:.*]] = fir.convert %[[C1:.*]] : (index) -> i32 + !CHECK: %[[VAL_29:.*]] = fir.load %[[VAL_10]]#0 {accessGroups = [#access_group1]} + !CHECK: %[[VAL_30:.*]] = arith.addi %[[VAL_29]], %[[VAL_28]] overflow<nsw> : i32 + !CHECK: fir.result %[[VAL_30]] : i32 + end do +end subroutine ivdep_test2 + + +! CHECK-LABEL: ivdep_test3 +subroutine ivdep_test3 + integer :: a(10), b(10), c(10) + !dir$ ivdep + !CHECK: fir.do_loop {{.*}} attributes {loopAnnotation = #loop_annotation2} + do i=1,10 + a(i)=b(i)+c(i) + call foo() + !CHECK: fir.store %[[ARG1:.*]] to %[[VAL_10:.*]]#0 {accessGroups = [#access_group2]} + !CHECK: %[[VAL_15:.*]] = fir.load %[[VAL_10]]#0 {accessGroups = [#access_group2]} + !CHECK: %[[VAL_16:.*]] = fir.convert %[[VAL_15]] : (i32) -> i64 + !CHECK: %[[VAL_17:.*]] = hlfir.designate %[[VAL_5:.*]]#0 (%[[VAL_16]]) : (!fir.ref<!fir.array<10xi32>>, i64) + !CHECK: %[[VAL_18:.*]] = fir.load %[[VAL_17]] {accessGroups = [#access_group2]} + !CHECK: %[[VAL_19:.*]] = fir.load %[[VAL_10]]#0 {accessGroups = [#access_group2]} + !CHECK: %[[VAL_20:.*]] = fir.convert %[[VAL_19]] : (i32) -> i64 + !CHECK: %[[VAL_21:.*]] = hlfir.designate %[[VAL_8:.*]]#0 (%[[VAL_20]]) : (!fir.ref<!fir.array<10xi32>>, i64) + !CHECK: %[[VAL_22:.*]] = fir.load %[[VAL_21]] {accessGroups = [#access_group2]} + !CHECK: %[[VAL_23:.*]] = arith.addi %[[VAL_18]], %[[VAL_22]] : i32 + !CHECK: %[[VAL_24:.*]] = fir.load %[[VAL_10]]#0 {accessGroups = [#access_group2]} + !CHECK: %[[VAL_25:.*]] = fir.convert %[[VAL_24]] : (i32) -> i64 + !CHECK: %[[VAL_26:.*]] = hlfir.designate %[[VAL_2:.*]]#0 (%[[VAL_25]]) : (!fir.ref<!fir.array<10xi32>>, i64) + !CHECK: hlfir.assign %[[VAL_23]] to %[[VAL_26]] {access_groups = [#access_group2]} : i32, !fir.ref<i32> + !CHECK: fir.call @_QFivdep_test3Pfoo() fastmath<contract> {accessGroups = [#access_group2]} + !CHECK: %[[VAL_28:.*]] = fir.convert %[[C1:.*]] : (index) -> i32 + !CHECK: %[[VAL_29:.*]] = fir.load %[[VAL_10]]#0 {accessGroups = [#access_group2]} + !CHECK: %[[VAL_30:.*]] = arith.addi %[[VAL_29]], %[[VAL_28]] overflow<nsw> : i32 + !CHECK: fir.result %[[VAL_30]] : i32 + end do + contains + subroutine foo() + end subroutine +end subroutine ivdep_test3 + diff --git a/flang/test/Lower/location.f90 b/flang/test/Lower/location.f90 index 95bf226..cdde1cc 100644 --- a/flang/test/Lower/location.f90 +++ b/flang/test/Lower/location.f90 @@ -3,7 +3,7 @@ program test include 'location0.inc' -end +end ! CHECK-LABEL: func.func @_QQmain() attributes {fir.bindc_name = "TEST"} { ! CHECK: fir.call @_FortranAioOutputAscii(%{{.*}}, %{{.*}}, %{{.*}}) fastmath<contract> : (!fir.ref<i8>, !fir.ref<i8>, i64) -> i1 loc(fused<#fir<loc_kind_array[ base, inclusion, inclusion]>>["{{.*}}location1.inc":1:10, "{{.*}}location0.inc":1:1, "{{.*}}location.f90":4:1]) diff --git a/flang/test/Lower/loops.f90 b/flang/test/Lower/loops.f90 index 2fea84b..5ee6562 100644 --- a/flang/test/Lower/loops.f90 +++ b/flang/test/Lower/loops.f90 @@ -90,7 +90,6 @@ subroutine lis(n) ! CHECK-DAG: fir.alloca !fir.array<?x?x?xi32>, %{{.*}}, %{{.*}}, %{{.*}} {bindc_name = "a", fir.target, uniq_name = "_QFlisEa"} ! CHECK-DAG: fir.alloca !fir.array<?x?xi32>, %{{.*}}, %{{.*}} {bindc_name = "r", uniq_name = "_QFlisEr"} ! CHECK-DAG: fir.alloca !fir.array<?x?xi32>, %{{.*}}, %{{.*}} {bindc_name = "s", uniq_name = "_QFlisEs"} - ! CHECK-DAG: fir.alloca !fir.array<?x?xi32>, %{{.*}}, %{{.*}} {bindc_name = "t", uniq_name = "_QFlisEt"} integer, target :: a(n,n,n) ! operand via p integer :: r(n,n) ! result, unspecified locality integer :: s(n,n) ! shared locality diff --git a/flang/test/Lower/module-debug-file-loc-linux.f90 b/flang/test/Lower/module-debug-file-loc-linux.f90 index 454fad9..1c67d83 100644 --- a/flang/test/Lower/module-debug-file-loc-linux.f90 +++ b/flang/test/Lower/module-debug-file-loc-linux.f90 @@ -2,7 +2,7 @@ ! RUN: %flang_fc1 -mmlir --mlir-print-debuginfo -emit-fir -o - %s | FileCheck %s -! REQUIRES: system-linux +! REQUIRES: system-linux || system-aix subroutine sb1() end subroutine diff --git a/flang/test/Lower/module_definition.f90 b/flang/test/Lower/module_definition.f90 index 0a05364..a96bc91 100644 --- a/flang/test/Lower/module_definition.f90 +++ b/flang/test/Lower/module_definition.f90 @@ -36,7 +36,7 @@ end module ! file. module modEq1 ! Equivalence, no initialization - real :: x1(10), x2(10), x3(10) + real :: x1(10), x2(10), x3(10) ! Equivalence with initialization real :: y1 = 42. real :: y2(10) diff --git a/flang/test/Lower/module_use.f90 b/flang/test/Lower/module_use.f90 index 92acbfb..e7f56f5 100644 --- a/flang/test/Lower/module_use.f90 +++ b/flang/test/Lower/module_use.f90 @@ -36,7 +36,7 @@ real function modCommon1Use() ! CHECK-DAG: fir.address_of(@named2_) : !fir.ref<!fir.array<4xi8>> ! CHECK-DAG: fir.address_of(@__BLNK__) : !fir.ref<!fir.array<4xi8>> ! CHECK-DAG: fir.address_of(@named1_) : !fir.ref<!fir.array<4xi8>> - modCommon1Use = x_blank + x_named1 + i_named2 + modCommon1Use = x_blank + x_named1 + i_named2 end function diff --git a/flang/test/Lower/module_use_in_same_file.f90 b/flang/test/Lower/module_use_in_same_file.f90 index 9e51bee..7ef64f0 100644 --- a/flang/test/Lower/module_use_in_same_file.f90 +++ b/flang/test/Lower/module_use_in_same_file.f90 @@ -35,7 +35,7 @@ end function ! Module modEq2 defines data that is equivalenced module modEq2 ! Equivalence, no initialization - real :: x1(10), x2(10), x3(10) + real :: x1(10), x2(10), x3(10) ! Equivalence with initialization real :: y1 = 42. real :: y2(10) @@ -109,7 +109,7 @@ real function test_no_equiv_conflicts() use modEq2 ! Same equivalences as in modEq2. Test that lowering does not mixes ! up the equivalence based on the similar offset inside the scope. - real :: x1l(10), x2l(10), x3l(10) + real :: x1l(10), x2l(10), x3l(10) real :: y1l = 42. real :: y2l(10) save :: x1l, x2l, x3l, y1l, y2l diff --git a/flang/test/Lower/namelist-common-block.f90 b/flang/test/Lower/namelist-common-block.f90 index d16f886d..54d4b9e 100644 --- a/flang/test/Lower/namelist-common-block.f90 +++ b/flang/test/Lower/namelist-common-block.f90 @@ -8,7 +8,7 @@ program nml_common real, pointer :: p(:) namelist /t/i,p common /c/i,p - + allocate(p(2)) call print_t() contains diff --git a/flang/test/Lower/nested-where.f90 b/flang/test/Lower/nested-where.f90 index 28aced2..1e37966 100644 --- a/flang/test/Lower/nested-where.f90 +++ b/flang/test/Lower/nested-where.f90 @@ -313,7 +313,7 @@ program nested_where ! CHECK: fir.call @_FortranARaggedArrayDeallocate(%[[VAL_278]]) {{.*}}: (!fir.llvm_ptr<i8>) -> () ! CHECK: %[[VAL_280:.*]] = fir.convert %[[VAL_4]] : (!fir.ref<tuple<i64, !fir.heap<!fir.array<?xi8>>, !fir.heap<!fir.array<?xi64>>>>) -> !fir.llvm_ptr<i8> ! CHECK: fir.call @_FortranARaggedArrayDeallocate(%[[VAL_280]]) {{.*}}: (!fir.llvm_ptr<i8>) -> () - + integer :: a(3) = 0 logical :: mask1(3) = (/ .true.,.false.,.true. /) logical :: mask2(3) = (/ .true.,.true.,.false. /) diff --git a/flang/test/Lower/nullify-polymorphic.f90 b/flang/test/Lower/nullify-polymorphic.f90 index 58eaa11..9a6a279 100644 --- a/flang/test/Lower/nullify-polymorphic.f90 +++ b/flang/test/Lower/nullify-polymorphic.f90 @@ -13,7 +13,7 @@ module poly contains procedure, nopass :: proc1 => proc1_p2 end type - + contains subroutine proc1_p1() @@ -23,7 +23,7 @@ contains subroutine proc1_p2() print*, 'call proc1_p2' end subroutine - + subroutine test_nullify() class(p1), pointer :: c @@ -31,7 +31,7 @@ contains call c%proc1() nullify(c) ! c dynamic type must be reset to p1 - + call c%proc1() end subroutine end module @@ -45,7 +45,7 @@ end ! CHECK: %[[C_DESC:.*]] = fir.alloca !fir.class<!fir.ptr<!fir.type<_QMpolyTp1{a:i32,b:i32}>>> {bindc_name = "c", uniq_name = "_QMpolyFtest_nullifyEc"} ! CHECK: %[[C_DESC_DECL:.*]]:2 = hlfir.declare %[[C_DESC]] {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QMpolyFtest_nullifyEc"} : (!fir.ref<!fir.class<!fir.ptr<!fir.type<_QMpolyTp1{a:i32,b:i32}>>>>) -> (!fir.ref<!fir.class<!fir.ptr<!fir.type<_QMpolyTp1{a:i32,b:i32}>>>>, !fir.ref<!fir.class<!fir.ptr<!fir.type<_QMpolyTp1{a:i32,b:i32}>>>>) ! CHECK: %{{.*}} = fir.call @_FortranAPointerAllocate(%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}) {{.*}}: (!fir.ref<!fir.box<none>>, i1, !fir.box<none>, !fir.ref<i8>, i32) -> i32 -! CHECK: %[[DECLARED_TYPE_DESC:.*]] = fir.type_desc !fir.type<_QMpolyTp1{a:i32,b:i32}> +! CHECK: %[[DECLARED_TYPE_DESC:.*]] = fir.type_desc !fir.type<_QMpolyTp1{a:i32,b:i32}> ! CHECK: %[[C_DESC_CAST:.*]] = fir.convert %[[C_DESC_DECL]]#0 : (!fir.ref<!fir.class<!fir.ptr<!fir.type<_QMpolyTp1{a:i32,b:i32}>>>>) -> !fir.ref<!fir.box<none>> ! CHECK: %[[TYPE_DESC_CAST:.*]] = fir.convert %[[DECLARED_TYPE_DESC]] : (!fir.tdesc<!fir.type<_QMpolyTp1{a:i32,b:i32}>>) -> !fir.ref<none> ! CHECK: %[[RANK:.*]] = arith.constant 0 : i32 diff --git a/flang/test/Lower/pause-statement.f90 b/flang/test/Lower/pause-statement.f90 index f4c8f6f..465d8244 100644 --- a/flang/test/Lower/pause-statement.f90 +++ b/flang/test/Lower/pause-statement.f90 @@ -2,7 +2,31 @@ ! CHECK-LABEL: pause_test subroutine pause_test() - ! CHECK: fir.call @_Fortran{{.*}}PauseStatement() - ! CHECK-NEXT: return pause + ! CHECK: fir.call @_FortranA{{.*}}PauseStatement() + ! CHECK-NEXT: return +end subroutine + +! CHECK-LABEL: pause_code +subroutine pause_code() + pause 42 + ! CHECK: %[[c42:.*]] = arith.constant 42 : i32 + ! CHECK: fir.call @_FortranA{{.*}}PauseStatementInt(%[[c42]]) + ! CHECK-NEXT: return end subroutine + +! CHECK-LABEL: pause_msg +subroutine pause_msg() + pause "hello" + ! CHECK-DAG: %[[five:.*]] = arith.constant 5 : index + ! CHECK-DAG: %[[addr:.*]] = fir.address_of(@_QQ{{.*}}) : !fir.ref<!fir.char<1,5>> + ! CHECK-DAG: %[[str:.*]]:2 = hlfir.declare %[[addr]] typeparams %[[five]] {fortran_attrs = #fir.var_attrs<parameter>, uniq_name = "_QQ{{.*}}"} : (!fir.ref<!fir.char<1,5>>, index) -> (!fir.ref<!fir.char<1,5>>, !fir.ref<!fir.char<1,5>>) + ! CHECK-DAG: %[[buff:.*]] = fir.convert %[[str]]#0 : (!fir.ref<!fir.char<1,5>>) -> !fir.ref<i8> + ! CHECK-DAG: %[[len:.*]] = fir.convert %[[five]] : (index) -> i64 + ! CHECK: fir.call @_FortranA{{.*}}PauseStatementText(%[[buff]], %[[len]]) + ! CHECK-NEXT: return +end subroutine + +! CHECK-DAG: func private @_FortranA{{.*}}PauseStatement +! CHECK-DAG: func private @_FortranA{{.*}}PauseStatementInt +! CHECK-DAG: func private @_FortranA{{.*}}PauseStatementText diff --git a/flang/test/Lower/pointer-association-polymorphic.f90 b/flang/test/Lower/pointer-association-polymorphic.f90 index 7d166e1..a82eebb 100644 --- a/flang/test/Lower/pointer-association-polymorphic.f90 +++ b/flang/test/Lower/pointer-association-polymorphic.f90 @@ -143,9 +143,9 @@ contains ! CHECK: %[[C4_LOAD:.*]] = fir.load %[[C4_DESC]] : !fir.ref<!fir.class<!fir.heap<!fir.array<?x!fir.type<_QMpolyTp1{a:i32,b:i32}>>>>> ! CHECK: %[[C4_REBOX:.*]] = fir.rebox %[[C4_LOAD]](%{{.*}}) : (!fir.class<!fir.heap<!fir.array<?x!fir.type<_QMpolyTp1{a:i32,b:i32}>>>>, !fir.shift<1>) -> !fir.class<!fir.array<?x!fir.type<_QMpolyTp1{a:i32,b:i32}>>> -! CHECK: %[[PA_CONV:.*]] = fir.convert %[[PA_DESC]] : (!fir.ref<!fir.class<!fir.ptr<!fir.array<?x!fir.type<_QMpolyTp1{a:i32,b:i32}>>>>>) -> !fir.ref<!fir.box<none>> -! CHECK: %[[C4_REBOX_CONV:.*]] = fir.convert %[[C4_REBOX]] : (!fir.class<!fir.array<?x!fir.type<_QMpolyTp1{a:i32,b:i32}>>>) -> !fir.box<none> -! CHECK: fir.call @_FortranAPointerAssociate(%[[PA_CONV]], %[[C4_REBOX_CONV]]) {{.*}} : (!fir.ref<!fir.box<none>>, !fir.box<none>) -> () +! CHECK: %[[PA_CONV:.*]] = fir.convert %[[PA_DESC]] : (!fir.ref<!fir.class<!fir.ptr<!fir.array<?x!fir.type<_QMpolyTp1{a:i32,b:i32}>>>>>) -> !fir.ref<!fir.box<none>> +! CHECK: %[[C4_REBOX_CONV:.*]] = fir.convert %[[C4_REBOX]] : (!fir.class<!fir.array<?x!fir.type<_QMpolyTp1{a:i32,b:i32}>>>) -> !fir.box<none> +! CHECK: fir.call @_FortranAPointerAssociate(%[[PA_CONV]], %[[C4_REBOX_CONV]]) {{.*}} : (!fir.ref<!fir.box<none>>, !fir.box<none>) -> () ! CHECK-LABEL: fir.do_loop ! CHECK: %[[PA_LOAD:.*]] = fir.load %[[PA_DESC]] : !fir.ref<!fir.class<!fir.ptr<!fir.array<?x!fir.type<_QMpolyTp1{a:i32,b:i32}>>>>> ! CHECK: %[[PA_COORD:.*]] = fir.coordinate_of %[[PA_LOAD]], %{{.*}} : (!fir.class<!fir.ptr<!fir.array<?x!fir.type<_QMpolyTp1{a:i32,b:i32}>>>>, i64) -> !fir.ref<!fir.type<_QMpolyTp1{a:i32,b:i32}>> @@ -165,8 +165,8 @@ contains ! CHECK: %[[SLICE:.*]] = fir.slice %[[C2_INDEX]], %[[C4_INDEX]], %[[C1_INDEX]] : (index, index, index) -> !fir.slice<1> ! CHECK: %[[SLICE_REBOX:.*]] = fir.rebox %[[C4_LOAD]](%[[SHIFT]]) [%[[SLICE]]] : (!fir.class<!fir.heap<!fir.array<?x!fir.type<_QMpolyTp1{a:i32,b:i32}>>>>, !fir.shift<1>, !fir.slice<1>) -> !fir.class<!fir.array<3x!fir.type<_QMpolyTp1{a:i32,b:i32}>>> ! CHECK: %[[PA_CONV:.*]] = fir.convert %[[PA_DESC]] : (!fir.ref<!fir.class<!fir.ptr<!fir.array<?x!fir.type<_QMpolyTp1{a:i32,b:i32}>>>>>) -> !fir.ref<!fir.box<none>> -! CHECK: %[[SLICE_REBOX_CONV:.*]] = fir.convert %[[SLICE_REBOX]] : (!fir.class<!fir.array<3x!fir.type<_QMpolyTp1{a:i32,b:i32}>>>) -> !fir.box<none> -! CHECK: fir.call @_FortranAPointerAssociate(%[[PA_CONV]], %[[SLICE_REBOX_CONV]]) {{.*}} : (!fir.ref<!fir.box<none>>, !fir.box<none>) -> () +! CHECK: %[[SLICE_REBOX_CONV:.*]] = fir.convert %[[SLICE_REBOX]] : (!fir.class<!fir.array<3x!fir.type<_QMpolyTp1{a:i32,b:i32}>>>) -> !fir.box<none> +! CHECK: fir.call @_FortranAPointerAssociate(%[[PA_CONV]], %[[SLICE_REBOX_CONV]]) {{.*}} : (!fir.ref<!fir.box<none>>, !fir.box<none>) -> () ! CHECK-LABEL: fir.do_loop ! CHECK: %[[PA_LOAD:.*]] = fir.load %[[PA_DESC]] : !fir.ref<!fir.class<!fir.ptr<!fir.array<?x!fir.type<_QMpolyTp1{a:i32,b:i32}>>>>> ! CHECK: %[[PA_COORD:.*]] = fir.coordinate_of %[[PA_LOAD]], %{{.*}} : (!fir.class<!fir.ptr<!fir.array<?x!fir.type<_QMpolyTp1{a:i32,b:i32}>>>>, i64) -> !fir.ref<!fir.type<_QMpolyTp1{a:i32,b:i32}>> diff --git a/flang/test/Lower/pointer-disassociate-character.f90 b/flang/test/Lower/pointer-disassociate-character.f90 new file mode 100644 index 0000000..5ee50fa --- /dev/null +++ b/flang/test/Lower/pointer-disassociate-character.f90 @@ -0,0 +1,69 @@ +! Test character_pointer => NULL() +! The main point is to check that non deferred length parameter is preserved +! inside the descriptor, and that the length is otherwise set to zero. +! RUN: %flang_fc1 -emit-hlfir %s -o - | FileCheck %s + +subroutine test_deferred(p) + character(:), pointer :: p + p => null() +end subroutine +subroutine test_cst(p) + character(10), pointer :: p + p => null() +end subroutine +subroutine test_explicit(p, n) + integer(8) :: n + character(n), pointer :: p + p => null() +end subroutine +subroutine test_assumed(p) + character(*), pointer :: p + p => null() +end subroutine +subroutine test_deferred_comp(p) + type t + character(:), pointer :: p + end type + type(t) :: x + x%p => null() +end subroutine +subroutine test_explicit_comp(p) + type t + character(10), pointer :: p + end type + type(t) :: x + x%p => null() +end subroutine + +! CHECK-LABEL: func.func @_QPtest_deferred( +! CHECK: %[[ZERO_BITS_0:.*]] = fir.zero_bits !fir.ptr<!fir.char<1,?>> +! CHECK: %[[CONSTANT_0:.*]] = arith.constant 0 : index +! CHECK: %[[EMBOX_0:.*]] = fir.embox %[[ZERO_BITS_0]] typeparams %[[CONSTANT_0]] : (!fir.ptr<!fir.char<1,?>>, index) -> !fir.box<!fir.ptr<!fir.char<1,?>>> + +! CHECK-LABEL: func.func @_QPtest_cst( +! CHECK: %[[ZERO_BITS_0:.*]] = fir.zero_bits !fir.ptr<!fir.char<1,10>> +! CHECK: %[[EMBOX_0:.*]] = fir.embox %[[ZERO_BITS_0]] : (!fir.ptr<!fir.char<1,10>>) -> !fir.box<!fir.ptr<!fir.char<1,10>>> + +! CHECK-LABEL: func.func @_QPtest_explicit( +! CHECK: %[[LOAD_0:.*]] = fir.load %{{.*}} : !fir.ref<i64> +! CHECK: %[[SELECT_0:.*]] = arith.select %{{.*}}, %[[LOAD_0]], %c0{{.*}} : i64 +! CHECK: %[[ZERO_BITS_0:.*]] = fir.zero_bits !fir.ptr<!fir.char<1,?>> +! CHECK: %[[EMBOX_0:.*]] = fir.embox %[[ZERO_BITS_0]] typeparams %[[SELECT_0]] : (!fir.ptr<!fir.char<1,?>>, i64) -> !fir.box<!fir.ptr<!fir.char<1,?>>> + +! CHECK-LABEL: func.func @_QPtest_assumed( +! CHECK: %[[LOAD_0:.*]] = fir.load %[[ARG0:.*]] : !fir.ref<!fir.box<!fir.ptr<!fir.char<1,?>>>> +! CHECK: %[[BOX_ELESIZE_0:.*]] = fir.box_elesize %[[LOAD_0]] : (!fir.box<!fir.ptr<!fir.char<1,?>>>) -> index +! CHECK: %[[DECLARE_0:.*]]:2 = hlfir.declare %[[ARG0]] +! CHECK: %[[ZERO_BITS_0:.*]] = fir.zero_bits !fir.ptr<!fir.char<1,?>> +! CHECK: %[[EMBOX_0:.*]] = fir.embox %[[ZERO_BITS_0]] typeparams %[[BOX_ELESIZE_0]] : (!fir.ptr<!fir.char<1,?>>, index) -> !fir.box<!fir.ptr<!fir.char<1,?>>> + +! CHECK-LABEL: func.func @_QPtest_deferred_comp( +! CHECK: %[[ZERO_BITS_0:.*]] = fir.zero_bits !fir.ptr<!fir.char<1,?>> +! CHECK: %[[CONSTANT_0:.*]] = arith.constant 0 : index +! CHECK: %[[EMBOX_0:.*]] = fir.embox %[[ZERO_BITS_0]] typeparams %[[CONSTANT_0]] : (!fir.ptr<!fir.char<1,?>>, index) -> !fir.box<!fir.ptr<!fir.char<1,?>>> +! CHECK: fir.store %[[EMBOX_0]] to %{{.*}} : !fir.ref<!fir.box<!fir.ptr<!fir.char<1,?>>>> + +! CHECK-LABEL: func.func @_QPtest_explicit_comp( +! CHECK: %[[ZERO_BITS_0:.*]] = fir.zero_bits !fir.ptr<!fir.char<1,10>> +! CHECK: %[[EMBOX_0:.*]] = fir.embox %[[ZERO_BITS_0]] : (!fir.ptr<!fir.char<1,10>>) -> !fir.box<!fir.ptr<!fir.char<1,10>>> +! CHECK: fir.store %[[EMBOX_0]] to %{{.*}} : !fir.ref<!fir.box<!fir.ptr<!fir.char<1,10>>>> diff --git a/flang/test/Lower/pointer-disassociate.f90 b/flang/test/Lower/pointer-disassociate.f90 index fb70fd7..6dfabdd 100644 --- a/flang/test/Lower/pointer-disassociate.f90 +++ b/flang/test/Lower/pointer-disassociate.f90 @@ -113,9 +113,9 @@ subroutine test_polymorphic_null(p) end subroutine ! CHECK-LABEL: func.func @_QPtest_polymorphic_null( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.class<!fir.ptr<!fir.array<?x!fir.type<_QFtest_polymorphic_nullTt>>>>> -! CHECK: %[[VAL_1:.*]] = fir.type_desc !fir.type<_QFtest_polymorphic_nullTt> +! CHECK: %[[VAL_1:.*]] = fir.type_desc !fir.type<_QFtest_polymorphic_nullTt> ! CHECK: %[[VAL_2:.*]] = fir.convert %[[VAL_0]] : (!fir.ref<!fir.class<!fir.ptr<!fir.array<?x!fir.type<_QFtest_polymorphic_nullTt>>>>>) -> !fir.ref<!fir.box<none>> -! CHECK: %[[VAL_3:.*]] = fir.convert %[[VAL_1]] : (!fir.tdesc<!fir.type<_QFtest_polymorphic_nullTt>>) -> !fir.ref<none> +! CHECK: %[[VAL_3:.*]] = fir.convert %[[VAL_1]] : (!fir.tdesc<!fir.type<_QFtest_polymorphic_nullTt>>) -> !fir.ref<none> ! CHECK: %[[VAL_4:.*]] = arith.constant 1 : i32 ! CHECK: %[[VAL_5:.*]] = arith.constant 0 : i32 ! CHECK: fir.call @_FortranAPointerNullifyDerived(%[[VAL_2]], %[[VAL_3]], %[[VAL_4]], %[[VAL_5]]) {{.*}}: (!fir.ref<!fir.box<none>>, !fir.ref<none>, i32, i32) -> () diff --git a/flang/test/Lower/polymorphic-temp.f90 b/flang/test/Lower/polymorphic-temp.f90 index ac3cbdb..391ec2b 100644 --- a/flang/test/Lower/polymorphic-temp.f90 +++ b/flang/test/Lower/polymorphic-temp.f90 @@ -24,7 +24,7 @@ contains call pass_unlimited_poly_1d(spread(p, dim=1, ncopies=2)) call pass_unlimited_poly_1d(spread(pa(1), dim=1, ncopies=2)) - + end subroutine ! CHECK-LABEL: func.func @_QMpoly_tmpPtest_temp_from_intrinsic_spread() { @@ -220,7 +220,7 @@ contains ! CHECK: %[[LOAD_I:.*]] = fir.load %[[I]] : !fir.ref<i32> ! CHECK: %[[C1:.*]] = arith.constant 1 : i32 ! CHECK: %[[CMPI:.*]] = arith.cmpi eq, %[[LOAD_I]], %[[C1]] : i32 -! CHECK: %[[A_REBOX:.*]] = fir.rebox %[[LOAD_A]] : (!fir.class<!fir.heap<!fir.type<_QMpoly_tmpTp1{a:i32}>>>) -> !fir.box<!fir.heap<!fir.type<_QMpoly_tmpTp1{a:i32}>>> +! CHECK: %[[A_REBOX:.*]] = fir.rebox %[[LOAD_A]] : (!fir.class<!fir.heap<!fir.type<_QMpoly_tmpTp1{a:i32}>>>) -> !fir.box<!fir.heap<!fir.type<_QMpoly_tmpTp1{a:i32}>>> ! CHECK: %{{.*}} = arith.select %[[CMPI]], %[[A_REBOX]], %[[LOAD_B]] : !fir.box<!fir.heap<!fir.type<_QMpoly_tmpTp1{a:i32}>>> subroutine check_unlimited_poly(a) diff --git a/flang/test/Lower/polymorphic-types.f90 b/flang/test/Lower/polymorphic-types.f90 index a06e0a2..93d08a4 100644 --- a/flang/test/Lower/polymorphic-types.f90 +++ b/flang/test/Lower/polymorphic-types.f90 @@ -1,6 +1,6 @@ ! RUN: bbc -emit-fir -hlfir=false %s -o - | FileCheck %s -! Tests the different possible type involving polymorphic entities. +! Tests the different possible type involving polymorphic entities. module polymorphic_types type p1 diff --git a/flang/test/Lower/polymorphic.f90 b/flang/test/Lower/polymorphic.f90 index f586380..689e223 100644 --- a/flang/test/Lower/polymorphic.f90 +++ b/flang/test/Lower/polymorphic.f90 @@ -126,7 +126,7 @@ module polymorphic_test ! CHECK: %[[CLASS1:.*]] = fir.embox %[[DT1]] : (!fir.ref<!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>>) -> !fir.class<!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>> ! CHECK: fir.call @_QMpolymorphic_testPprint(%[[CLASS1]]) {{.*}}: (!fir.class<!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>>) -> () ! CHECK: %[[BOX2:.*]] = fir.embox %[[DT2]] : (!fir.ref<!fir.type<_QMpolymorphic_testTp2{a:i32,b:i32,c:f32}>>) -> !fir.class<!fir.type<_QMpolymorphic_testTp2{a:i32,b:i32,c:f32}>> -! CHECK: %[[CLASS2:.*]] = fir.convert %[[BOX2]] : (!fir.class<!fir.type<_QMpolymorphic_testTp2{a:i32,b:i32,c:f32}>>) -> !fir.class<!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>> +! CHECK: %[[CLASS2:.*]] = fir.convert %[[BOX2]] : (!fir.class<!fir.type<_QMpolymorphic_testTp2{a:i32,b:i32,c:f32}>>) -> !fir.class<!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>> ! CHECK: fir.call @_QMpolymorphic_testPprint(%[[CLASS2]]) {{.*}}: (!fir.class<!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>>) -> () subroutine test_allocate_unlimited_polymorphic_non_derived() @@ -287,7 +287,6 @@ module polymorphic_test ! First test is here to have a reference with non polymorphic on both sides. ! CHECK-LABEL: func.func @_QMpolymorphic_testPpointer_assign_parent( ! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.type<_QMpolymorphic_testTp2{a:i32,b:i32,c:f32}>> {fir.bindc_name = "p", fir.target}) { -! CHECK: %[[TP:.*]] = fir.alloca !fir.box<!fir.ptr<!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>>> {bindc_name = "tp", uniq_name = "_QMpolymorphic_testFpointer_assign_parentEtp"} ! CHECK: %[[PTR:.*]] = fir.alloca !fir.ptr<!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>> {uniq_name = "_QMpolymorphic_testFpointer_assign_parentEtp.addr"} ! CHECK: %[[ZERO:.*]] = fir.zero_bits !fir.ptr<!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>> ! CHECK: fir.store %[[ZERO]] to %[[PTR]] : !fir.ref<!fir.ptr<!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>>> @@ -302,7 +301,6 @@ module polymorphic_test ! CHECK-LABEL: func.func @_QMpolymorphic_testPpointer_assign_non_poly( ! CHECK-SAME: %arg0: !fir.class<!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>> {fir.bindc_name = "p", fir.target}) { -! CHECK: %[[TP:.*]] = fir.alloca !fir.box<!fir.ptr<!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>>> {bindc_name = "tp", uniq_name = "_QMpolymorphic_testFpointer_assign_non_polyEtp"} ! CHECK: %[[PTR:.*]] = fir.alloca !fir.ptr<!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>> {uniq_name = "_QMpolymorphic_testFpointer_assign_non_polyEtp.addr"} ! CHECK: %[[ZERO:.*]] = fir.zero_bits !fir.ptr<!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>> ! CHECK: fir.store %[[ZERO]] to %[[PTR]] : !fir.ref<!fir.ptr<!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>>> @@ -318,7 +316,7 @@ module polymorphic_test ! CHECK-LABEL: func.func @_QMpolymorphic_testPnullify_pointer_array( ! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.type<_QMpolymorphic_testTp3{p:!fir.class<!fir.ptr<!fir.array<?x!fir.type<_QMpolymorphic_testTp3>>>>}>> {fir.bindc_name = "a"}) { ! CHECK: %[[COORD_P:.*]] = fir.coordinate_of %[[ARG0]], p : (!fir.ref<!fir.type<_QMpolymorphic_testTp3{p:!fir.class<!fir.ptr<!fir.array<?x!fir.type<_QMpolymorphic_testTp3>>>>}>>) -> !fir.ref<!fir.class<!fir.ptr<!fir.array<?x!fir.type<_QMpolymorphic_testTp3{p:!fir.class<!fir.ptr<!fir.array<?x!fir.type<_QMpolymorphic_testTp3>>>>}>>>>> -! CHECK: %[[TYPE_DESC:.*]] = fir.type_desc !fir.type<_QMpolymorphic_testTp3{p:!fir.class<!fir.ptr<!fir.array<?x!fir.type<_QMpolymorphic_testTp3>>>>}> +! CHECK: %[[TYPE_DESC:.*]] = fir.type_desc !fir.type<_QMpolymorphic_testTp3{p:!fir.class<!fir.ptr<!fir.array<?x!fir.type<_QMpolymorphic_testTp3>>>>}> ! CHECK: %[[CONV_P:.*]] = fir.convert %[[COORD_P]] : (!fir.ref<!fir.class<!fir.ptr<!fir.array<?x!fir.type<_QMpolymorphic_testTp3{p:!fir.class<!fir.ptr<!fir.array<?x!fir.type<_QMpolymorphic_testTp3>>>>}>>>>>) -> !fir.ref<!fir.box<none>> ! CHECK: %[[CONV_TDESC:.*]] = fir.convert %[[TYPE_DESC]] : (!fir.tdesc<!fir.type<_QMpolymorphic_testTp3{p:!fir.class<!fir.ptr<!fir.array<?x!fir.type<_QMpolymorphic_testTp3>>>>}>>) -> !fir.ref<none> ! CHECK: %[[C1:.*]] = arith.constant 1 : i32 @@ -519,7 +517,7 @@ module polymorphic_test subroutine host_assoc(this) class(p1) :: this - + call internal contains subroutine internal @@ -781,7 +779,7 @@ module polymorphic_test subroutine test_unlimited_polymorphic_alloc_array_ret() select type (a => unlimited_polymorphic_alloc_array_ret()) type is (real) - print*, 'type is real' + print*, 'type is real' end select end subroutine @@ -797,7 +795,7 @@ module polymorphic_test ! CHECK-LABEL: func.func @_QMpolymorphic_testPtest_unlimited_polymorphic_intentout( ! CHECK-SAME: %[[ARG0:.*]]: !fir.class<none> {fir.bindc_name = "a"}) { ! CHECK: %[[BOX_NONE:.*]] = fir.convert %[[ARG0]] : (!fir.class<none>) -> !fir.box<none> -! CHECK: fir.call @_FortranADestroy(%[[BOX_NONE]]) {{.*}} : (!fir.box<none>) -> () +! CHECK: fir.call @_FortranADestroy(%[[BOX_NONE]]) {{.*}} : (!fir.box<none>) -> () ! CHECK: %[[BOX_NONE:.*]] = fir.convert %[[ARG0]] : (!fir.class<none>) -> !fir.box<none> ! CHECK: fir.call @_FortranAInitialize(%[[BOX_NONE]], %{{.*}}, %{{.*}}) {{.*}} : (!fir.box<none>, !fir.ref<i8>, i32) -> () @@ -808,7 +806,7 @@ module polymorphic_test ! CHECK-LABEL: func.func @_QMpolymorphic_testPtest_polymorphic_intentout( ! CHECK-SAME: %[[ARG0:.*]]: !fir.class<!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>> {fir.bindc_name = "a"}) { ! CHECK: %[[BOX_NONE:.*]] = fir.convert %[[ARG0]] : (!fir.class<!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>>) -> !fir.box<none> -! CHECK: fir.call @_FortranADestroy(%[[BOX_NONE]]) {{.*}} : (!fir.box<none>) -> () +! CHECK: fir.call @_FortranADestroy(%[[BOX_NONE]]) {{.*}} : (!fir.box<none>) -> () ! CHECK: %[[BOX_NONE:.*]] = fir.convert %[[ARG0]] : (!fir.class<!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>>) -> !fir.box<none> ! CHECK: fir.call @_FortranAInitialize(%[[BOX_NONE]], %{{.*}}, %{{.*}}) {{.*}} : (!fir.box<none>, !fir.ref<i8>, i32) -> () @@ -1103,11 +1101,9 @@ module polymorphic_test ! CHECK-LABEL: func.func @_QMpolymorphic_testPclass_with_entry( ! CHECK-SAME: %[[A:.*]]: !fir.class<!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>> {fir.bindc_name = "a"}) { -! CHECK: %[[B:.*]] = fir.alloca !fir.class<!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>> {bindc_name = "b", uniq_name = "_QMpolymorphic_testFclass_with_entryEb"} ! CHECK-LABEL: func.func @_QMpolymorphic_testPd( ! CHECK-SAME: %[[B:.*]]: !fir.class<!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>> {fir.bindc_name = "b"}) { -! CHECK: %[[A:.*]] = fir.alloca !fir.class<!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>> {bindc_name = "a", uniq_name = "_QMpolymorphic_testFclass_with_entryEa"} subroutine class_array_with_entry(a) class(p1) :: a(:), b(:) diff --git a/flang/test/Lower/pre-fir-tree02.f90 b/flang/test/Lower/pre-fir-tree02.f90 index 65c33e9..d61dc80 100644 --- a/flang/test/Lower/pre-fir-tree02.f90 +++ b/flang/test/Lower/pre-fir-tree02.f90 @@ -148,7 +148,7 @@ end module test !! When derived type processing is implemented, remove all instances of: !! - !![disable] - !! - COM: + !! - COM: !![disable]type :: a_type !![disable] integer :: x !![disable]end type diff --git a/flang/test/Lower/procedure-declarations.f90 b/flang/test/Lower/procedure-declarations.f90 index b0dee60..95c8607 100644 --- a/flang/test/Lower/procedure-declarations.f90 +++ b/flang/test/Lower/procedure-declarations.f90 @@ -4,7 +4,7 @@ ! (passing a procedure and calling it), with and without definitions. ! Check that the definition type prevail if available and that casts are inserted to ! accommodate for the signature mismatch in the different location due to implicit -! typing rules and Fortran loose interface compatibility rule history. +! typing rules and Fortran loose interface compatibility rule history. ! Note: all the cases where their is a definition are exactly the same, @@ -25,7 +25,7 @@ subroutine call_foo(i) ! %[[argconvert:*]] = fir.convert %arg0 : ! fir.call @_QPfoo(%[[argconvert]]) {{.*}}: (!fir.ref<!fir.array<2x5xi32>>) -> () call foo(i) -end subroutine +end subroutine ! CHECK-LABEL: func @_QPfoo( ! CHECK-SAME: %{{.*}}: !fir.ref<!fir.array<2x5xi32>>{{.*}}) { subroutine foo(i) @@ -41,7 +41,7 @@ subroutine call_foo2(i) ! %[[argconvert:*]] = fir.convert %arg0 : ! fir.call @_QPfoo2(%[[argconvert]]) {{.*}}: (!fir.ref<!fir.array<2x5xi32>>) -> () call foo2(i) -end subroutine +end subroutine ! CHECK-LABEL: func @_QPpass_foo2() { subroutine pass_foo2() external :: foo2 @@ -64,7 +64,7 @@ subroutine call_foo3(i) ! %[[argconvert:*]] = fir.convert %arg0 : ! fir.call @_QPfoo3(%[[argconvert]]) {{.*}}: (!fir.ref<!fir.array<2x5xi32>>) -> () call foo3(i) -end subroutine +end subroutine ! CHECK-LABEL: func @_QPfoo3( ! CHECK-SAME: %{{.*}}: !fir.ref<!fir.array<2x5xi32>>{{.*}}) { subroutine foo3(i) @@ -93,7 +93,7 @@ subroutine call_foo4(i) ! %[[argconvert:*]] = fir.convert %arg0 : ! fir.call @_QPfoo4(%[[argconvert]]) {{.*}}: (!fir.ref<!fir.array<2x5xi32>>) -> () call foo4(i) -end subroutine +end subroutine ! CHECK-LABEL: func @_QPpass_foo4() { subroutine pass_foo4() external :: foo4 @@ -123,7 +123,7 @@ subroutine call_foo5(i) ! %[[argconvert:*]] = fir.convert %arg0 : ! fir.call @_QPfoo5(%[[argconvert]]) {{.*}}: (!fir.ref<!fir.array<2x5xi32>>) -> () call foo5(i) -end subroutine +end subroutine ! Test when there is no definition (declaration at the end of the mlir module) @@ -136,7 +136,7 @@ subroutine call_foo6(i) integer :: i(10) ! CHECK-NOT: convert call foo6(i) -end subroutine +end subroutine ! CHECK-LABEL: func @_QPpass_foo6() { subroutine pass_foo6() external :: foo6 @@ -160,7 +160,7 @@ function call_foo7(i) ! CHECK: %[[funccast:.*]] = fir.convert %[[f]] : (() -> ()) -> ((!fir.ref<!fir.array<10xi32>>) -> f32) ! CHECK: fir.call %[[funccast]](%arg0) {{.*}}: (!fir.ref<!fir.array<10xi32>>) -> f32 call_foo7 = foo7(i) -end function +end function ! call, call with different type @@ -170,14 +170,14 @@ subroutine call_foo8(i) integer :: i(10) ! CHECK-NOT: convert call foo8(i) -end subroutine +end subroutine ! CHECK-LABEL: func @_QPcall_foo8_2( ! CHECK-SAME: %{{.*}}: !fir.ref<!fir.array<2x5xi32>>{{.*}}) { subroutine call_foo8_2(i) integer :: i(2, 5) ! %[[argconvert:*]] = fir.convert %arg0 : call foo8(i) -end subroutine +end subroutine ! Test that target attribute is lowered in declaration of functions that are ! not defined in this file. diff --git a/flang/test/Lower/read-write-buffer.f90 b/flang/test/Lower/read-write-buffer.f90 index cfa25c8..ff4fabc 100644 --- a/flang/test/Lower/read-write-buffer.f90 +++ b/flang/test/Lower/read-write-buffer.f90 @@ -15,8 +15,8 @@ subroutine test_array_format ! CHECK: %[[fmtArg:.*]] = fir.zero_bits !fir.ref<i8> ! CHECK: %[[fmtLenArg:.*]] = fir.zero_bits i64 ! CHECK: %[[fmtDesc:.*]] = fir.convert %[[fmtBox]] : (!fir.box<!fir.array<2x!fir.char<1,10>>>) -> !fir.box<none> - ! CHECK: fir.call @_FortranAioBeginExternalFormattedOutput(%[[fmtArg]], %[[fmtLenArg]], %[[fmtDesc]], {{.*}}) - write(*, array) + ! CHECK: fir.call @_FortranAioBeginExternalFormattedOutput(%[[fmtArg]], %[[fmtLenArg]], %[[fmtDesc]], {{.*}}) + write(*, array) end subroutine ! A test to check the buffer and it's length. diff --git a/flang/test/Lower/select-case-statement.f90 b/flang/test/Lower/select-case-statement.f90 index 37bc4d2..b289024 100644 --- a/flang/test/Lower/select-case-statement.f90 +++ b/flang/test/Lower/select-case-statement.f90 @@ -1,18 +1,21 @@ -! RUN: bbc -emit-fir -hlfir=false -o - %s | FileCheck %s +! Note: character comparison is different: at -O0, flang-rt function is called, +! at -O1, inline character comparison is used. +! RUN: %flang_fc1 -emit-fir -O0 -o - %s | FileCheck %s --check-prefixes=CHECK,CHECK-O0 +! RUN: %flang_fc1 -emit-fir -O1 -o - %s | FileCheck %s --check-prefixes=CHECK,CHECK-O1 - ! CHECK-LABEL: sinteger + !CHECK-LABEL: sinteger function sinteger(n) integer sinteger nn = -88 - ! CHECK: fir.select_case {{.*}} : i32 - ! CHECK-SAME: upper, %c1 - ! CHECK-SAME: point, %c2 - ! CHECK-SAME: point, %c3 - ! CHECK-SAME: interval, %c4{{.*}} %c5 - ! CHECK-SAME: point, %c6 - ! CHECK-SAME: point, %c7 - ! CHECK-SAME: interval, %c8{{.*}} %c15 - ! CHECK-SAME: lower, %c21 + ! CHECK-DAG: fir.select_case {{.*}} : i32 + ! CHECK-SAME: upper, %c{{[0-9]+}}_i32, + ! CHECK-SAME: point, %c{{[0-9]+}}_i32, + ! CHECK-SAME: #fir.point, %c{{[0-9]+}}_i32, + ! CHECK-SAME: #fir.interval, %c{{[0-9]+}}_i32, %c{{[0-9]+}}_i32, + ! CHECK-SAME: #fir.point, %c{{[0-9]+}}_i32, + ! CHECK-SAME: #fir.point, %c{{[0-9]+}}_i32, + ! CHECK-SAME: #fir.interval, %c{{[0-9]+}}_i32, %c{{[0-9]+}}_i32, + ! CHECK-SAME: #fir.lower, %c{{[0-9]+}}_i32, ! CHECK-SAME: unit select case(n) case (:1) @@ -49,15 +52,14 @@ end select select case (L) - ! CHECK: cmpi eq, {{.*}} %false - ! CHECK: cond_br + ! CHECK: arith.cmpi eq, %{{[0-9]+}}, %false + ! CHECK: cf.cond_br case (.false.) n2 = 1 end select select case (L) - ! CHECK: cmpi eq, {{.*}} %true - ! CHECK: cond_br + ! CHECK: cf.cond_br case (.true.) n3 = 2 end select @@ -68,19 +70,18 @@ end select select case (L) - ! CHECK: cmpi eq, {{.*}} %false - ! CHECK: cond_br + ! CHECK: arith.cmpi eq, %{{[0-9]+}}, %false + ! CHECK: cf.cond_br case (.false.) n5 = 1 - ! CHECK: cmpi eq, {{.*}} %true - ! CHECK: cond_br + ! CHECK: cf.cond_br case (.true.) n5 = 2 end select select case (L) - ! CHECK: cmpi eq, {{.*}} %false - ! CHECK: cond_br + ! CHECK: arith.cmpi eq, %{{[0-9]+}}, %false + ! CHECK: cf.cond_br case (.false.) n6 = 1 case default @@ -88,8 +89,7 @@ end select select case (L) - ! CHECK: cmpi eq, {{.*}} %true - ! CHECK: cond_br + ! CHECK: cf.cond_br case (.true.) n7 = 2 case default @@ -97,15 +97,14 @@ end select select case (L) - ! CHECK: cmpi eq, {{.*}} %false - ! CHECK: cond_br + ! CHECK: arith.cmpi eq, %{{[0-9]+}}, %false + ! CHECK: cf.cond_br case (.false.) n8 = 1 - ! CHECK: cmpi eq, {{.*}} %true - ! CHECK: cond_br + ! CHECK: cf.cond_br case (.true.) n8 = 2 - ! CHECK-NOT: constant 888 + ! CHECK-NOT: 888 case default ! dead n8 = 888 end select @@ -120,64 +119,96 @@ select case (c) case default nn = -1 - ! CHECK: CharacterCompareScalar1 - ! CHECK-NEXT: constant 0 - ! CHECK-NEXT: cmpi sle, {{.*}} %c0 - ! CHECK-NEXT: cond_br + ! NOTE: common pattern of character comparison: at -O0, runtime function + ! is called, followed by comparison of i32 values. At -O1 and above, + ! inline comparison code is done using loops. The comparison code ends + ! with comparison of i8 values. At either -O0 or -O1, the comparison + ! ends with a conditional branch. This comparison pattern is used + ! throughout this file. + ! + ! <= 'd' + ! CHECK-O0: CharacterCompareScalar1 + ! CHECK-O0-NEXT: arith.cmpi sle, %{{[0-9]+}}, %c{{[0-9]+}}_i32 : i32 + ! CHECK-O1: fir.do_loop {{.*}} -> (i8) { + ! CHECK-O1: arith.cmpi sle, %{{[0-9]+}}, %c{{[0-9]+}}_i8 : i8 + ! CHECK-NEXT: cf.cond_br case (:'d') nn = 10 - ! CHECK: CharacterCompareScalar1 - ! CHECK-NEXT: constant 0 - ! CHECK-NEXT: cmpi sge, {{.*}} %c0 - ! CHECK-NEXT: cond_br - ! CHECK: CharacterCompareScalar1 - ! CHECK-NEXT: constant 0 - ! CHECK-NEXT: cmpi sle, {{.*}} %c0 - ! CHECK-NEXT: cond_br + ! 'ff' <= ... <= 'ffff' + ! CHECK-O0: CharacterCompareScalar1 + ! CHECK-O0-NEXT: arith.cmpi sge, %{{[0-9]+}}, %c{{[0-9]+}}_i32 : i32 + ! CHECK-O1: fir.do_loop {{.*}} -> (i8) { + ! CHECK-O1: arith.cmpi sge, %{{[0-9]+}}, %c{{[0-9]+}}_i8 : i8 + ! CHECK-NEXT: cf.cond_br + ! CHECK-O0: CharacterCompareScalar1 + ! CHECK-O0-NEXT: arith.cmpi sle, %{{[0-9]+}}, %c{{[0-9]+}}_i32 : i32 + ! CHECK-O1: fir.do_loop {{.*}} -> (i8) { + ! CHECK-O1: arith.cmpi sle, %{{[0-9]+}}, %c{{[0-9]+}}_i8 : i8 + ! CHECK-NEXT: cf.cond_br case ('ff':'ffff') nn = 20 - ! CHECK: CharacterCompareScalar1 - ! CHECK-NEXT: constant 0 - ! CHECK-NEXT: cmpi eq, {{.*}} %c0 - ! CHECK-NEXT: cond_br + ! == 'm' + ! CHECK-O0: CharacterCompareScalar1 + ! CHECK-O0-NEXT: arith.cmpi eq, %{{[0-9]+}}, %c{{[0-9]+}}_i32 : i32 + ! CHECK-O1: fir.do_loop {{.*}} -> (i8) { + ! CHECK-O1: arith.cmpi eq, %{{[0-9]+}}, %c{{[0-9]+}}_i8 : i8 + ! CHECK-NEXT: cf.cond_br case ('m') nn = 30 - ! CHECK: CharacterCompareScalar1 - ! CHECK-NEXT: constant 0 - ! CHECK-NEXT: cmpi eq, {{.*}} %c0 - ! CHECK-NEXT: cond_br + ! == 'qq' + ! CHECK-O0: CharacterCompareScalar1 + ! CHECK-O0-NEXT: arith.cmpi eq, %{{[0-9]+}}, %c{{[0-9]+}}_i32 : i32 + ! CHECK-O1: fir.do_loop {{.*}} -> (i8) { + ! CHECK-O1: arith.cmpi eq, %{{[0-9]+}}, %c{{[0-9]+}}_i8 : i8 + ! CHECK-NEXT: cf.cond_br case ('qq') nn = 40 - ! CHECK: CharacterCompareScalar1 - ! CHECK-NEXT: constant 0 - ! CHECK-NEXT: cmpi sge, {{.*}} %c0 - ! CHECK-NEXT: cond_br + ! >= 'x' + ! CHECK-O0: CharacterCompareScalar1 + ! CHECK-O0-NEXT: arith.cmpi sge, %{{[0-9]+}}, %c{{[0-9]+}}_i32 : i32 + ! CHECK-O1: fir.do_loop {{.*}} -> (i8) { + ! CHECK-O1: arith.cmpi sge, %{{[0-9]+}}, %c{{[0-9]+}}_i8 : i8 + ! CHECK-NEXT: cf.cond_br case ('x':) nn = 50 end select print*, nn end - ! CHECK-LABEL: func @_QPscharacter1 + ! CHECK-LABEL: func.func @_QPscharacter1 subroutine scharacter1(s) - ! CHECK-DAG: %[[V_0:[0-9]+]] = fir.alloca !fir.box<!fir.heap<!fir.char<1,?>>> character(len=3) :: s - ! CHECK-DAG: %[[V_1:[0-9]+]] = fir.alloca i32 {bindc_name = "n", uniq_name = "_QFscharacter1En"} - ! CHECK: fir.store %c0{{.*}} to %[[V_1]] : !fir.ref<i32> n = 0 - ! CHECK: %[[V_8:[0-9]+]] = fir.call @_FortranACharacterCompareScalar1 - ! CHECK: %[[V_9:[0-9]+]] = arith.cmpi sge, %[[V_8]], %c0{{.*}} : i32 - ! CHECK: cond_br %[[V_9]], ^bb1, ^bb16 - ! CHECK: ^bb1: // pred: ^bb0 + ! CHECK: %[[STR00:[0-9]+]] = fir.declare {{.*}} uniq_name = "_QQclX3030"} + ! CHECK: %[[STR00_CONV:[0-9]+]] = fir.convert %[[STR00]] + + ! CHECK-O0: fir.call @_FortranACharacterCompareScalar1({{.*}}, %[[STR00_CONV]] + ! CHECK-O0-NEXT: arith.cmpi sge, {{.*}}, %c0_i32 : i32 + ! CHECK-O1: fir.do_loop {{.*}} -> (i8) { + ! CHECK-O1: arith.cmpi sge, %{{[0-9]+}}, %c{{[0-9]+}}_i8 : i8 + ! CHECK-NEXT: cf.cond_br if (lge(s,'00')) then - ! CHECK: %[[V_18:[0-9]+]] = fir.load %[[V_0]] : !fir.ref<!fir.box<!fir.heap<!fir.char<1,?>>>> - ! CHECK: %[[V_20:[0-9]+]] = fir.box_addr %[[V_18]] : (!fir.box<!fir.heap<!fir.char<1,?>>>) -> !fir.heap<!fir.char<1,?>> - ! CHECK: %[[V_42:[0-9]+]] = fir.call @_FortranACharacterCompareScalar1 - ! CHECK: %[[V_43:[0-9]+]] = arith.cmpi eq, %[[V_42]], %c0{{.*}} : i32 - ! CHECK: cond_br %[[V_43]], ^bb3, ^bb2 - ! CHECK: ^bb2: // pred: ^bb1 + ! CHECK: fir.call @_FortranATrim + + ! All the strings in SELECT CASE + ! CHECK: %[[STR11:[0-9]+]] = fir.declare {{.*}} uniq_name = "_QQclX3131"} + ! CHECK: %[[STR22:[0-9]+]] = fir.declare {{.*}} uniq_name = "_QQclX3232"} + ! CHECK: %[[STR33:[0-9]+]] = fir.declare {{.*}} uniq_name = "_QQclX3333"} + ! CHECK: %[[STR44:[0-9]+]] = fir.declare {{.*}} uniq_name = "_QQclX3434"} + ! CHECK: %[[STR55:[0-9]+]] = fir.declare {{.*}} uniq_name = "_QQclX3535"} + ! CHECK: %[[STR66:[0-9]+]] = fir.declare {{.*}} uniq_name = "_QQclX3636"} + ! CHECK: %[[STR77:[0-9]+]] = fir.declare {{.*}} uniq_name = "_QQclX3737"} + ! CHECK: %[[STR88:[0-9]+]] = fir.declare {{.*}} uniq_name = "_QQclX3838"} + + ! == '11' + ! CHECK-O0: %[[STR11_CONV:[0-9]+]] = fir.convert %[[STR11]] + ! CHECK-O0: fir.call @_FortranACharacterCompareScalar1({{.*}}, %[[STR11_CONV]] + ! CHECK-O0-NEXT: arith.cmpi eq,{{.*}}, %c0_i32 : i32 + ! CHECK-O1: fir.do_loop {{.*}} -> (i8) { + ! CHECK-O1: arith.cmpi eq, %{{[0-9]+}}, %c{{[0-9]+}}_i8 : i8 + ! CHECK-NEXT: cf.cond_br select case(trim(s)) case('11') n = 1 @@ -185,182 +216,160 @@ case default continue - ! CHECK: %[[V_48:[0-9]+]] = fir.call @_FortranACharacterCompareScalar1 - ! CHECK: %[[V_49:[0-9]+]] = arith.cmpi eq, %[[V_48]], %c0{{.*}} : i32 - ! CHECK: cond_br %[[V_49]], ^bb6, ^bb5 - ! CHECK: ^bb3: // pred: ^bb1 - ! CHECK: fir.store %c1{{.*}} to %[[V_1]] : !fir.ref<i32> - ! CHECK: ^bb4: // pred: ^bb13 - ! CHECK: ^bb5: // pred: ^bb2 + ! == '22' + ! CHECK-O0: %[[STR22_CONV:[0-9]+]] = fir.convert %[[STR22]] + ! CHECK-O0: fir.call @_FortranACharacterCompareScalar1({{.*}}, %[[STR22_CONV]] + ! CHECK-O0-NEXT: arith.cmpi eq,{{.*}}, %c0_i32 : i32 + ! CHECK-O1: fir.do_loop {{.*}} -> (i8) { + ! CHECK-O1: arith.cmpi eq, %{{[0-9]+}}, %c{{[0-9]+}}_i8 : i8 + ! CHECK-NEXT: cf.cond_br case('22') n = 2 - ! CHECK: %[[V_54:[0-9]+]] = fir.call @_FortranACharacterCompareScalar1 - ! CHECK: %[[V_55:[0-9]+]] = arith.cmpi eq, %[[V_54]], %c0{{.*}} : i32 - ! CHECK: cond_br %[[V_55]], ^bb8, ^bb7 - ! CHECK: ^bb6: // pred: ^bb2 - ! CHECK: fir.store %c2{{.*}} to %[[V_1]] : !fir.ref<i32> - ! CHECK: ^bb7: // pred: ^bb5 + ! == '33' + ! CHECK-O0: %[[STR33_CONV:[0-9]+]] = fir.convert %[[STR33]] + ! CHECK-O0: fir.call @_FortranACharacterCompareScalar1({{.*}}, %[[STR33_CONV]] + ! CHECK-O0-NEXT: arith.cmpi eq,{{.*}}, %c0_i32 : i32 + ! CHECK-O1: fir.do_loop {{.*}} -> (i8) { + ! CHECK-O1: arith.cmpi eq, %{{[0-9]+}}, %c{{[0-9]+}}_i8 : i8 + ! CHECK-NEXT: cf.cond_br case('33') n = 3 + ! >= '44' + ! CHECK-O0: %[[STR44_CONV:[0-9]+]] = fir.convert %[[STR44]] + ! CHECK-O0: fir.call @_FortranACharacterCompareScalar1({{.*}}, %[[STR44_CONV]] + ! CHECK-O0-NEXT: arith.cmpi sge,{{.*}}, %c0_i32 : i32 + ! CHECK-O1: fir.do_loop {{.*}} -> (i8) { + ! CHECK-O1: arith.cmpi sge, %{{[0-9]+}}, %c{{[0-9]+}}_i8 : i8 + ! CHECK-NEXT: cf.cond_br + ! <= '55' + ! CHECK-O0: %[[STR55_CONV:[0-9]+]] = fir.convert %[[STR55]] + ! CHECK-O0: fir.call @_FortranACharacterCompareScalar1({{.*}}, %[[STR55_CONV]] + ! CHECK-O0-NEXT: arith.cmpi sle,{{.*}}, %c0_i32 : i32 + ! CHECK-O1: fir.do_loop {{.*}} -> (i8) { + ! CHECK-O1: arith.cmpi sle, %{{[0-9]+}}, %c{{[0-9]+}}_i8 : i8 + ! CHECK-NEXT: cf.cond_br + ! >= '66' + ! CHECK-O0: %[[STR66_CONV:[0-9]+]] = fir.convert %[[STR66]] + ! CHECK-O0: fir.call @_FortranACharacterCompareScalar1({{.*}}, %[[STR66_CONV]] + ! CHECK-O0-NEXT: arith.cmpi sge,{{.*}}, %c0_i32 : i32 + ! CHECK-O1: fir.do_loop {{.*}} -> (i8) { + ! CHECK-O1: arith.cmpi sge, %{{[0-9]+}}, %c{{[0-9]+}}_i8 : i8 + ! CHECK-NEXT: cf.cond_br + ! <= '77' + ! CHECK-O0: %[[STR77_CONV:[0-9]+]] = fir.convert %[[STR77]] + ! CHECK-O0: fir.call @_FortranACharacterCompareScalar1({{.*}}, %[[STR77_CONV]] + ! CHECK-O0-NEXT: arith.cmpi sle,{{.*}}, %c0_i32 : i32 + ! CHECK-O1: fir.do_loop {{.*}} -> (i8) { + ! CHECK-O1: arith.cmpi sle, %{{[0-9]+}}, %c{{[0-9]+}}_i8 : i8 + ! CHECK-NEXT: cf.cond_br + ! >= '88' + ! CHECK-O0: %[[STR88_CONV:[0-9]+]] = fir.convert %[[STR88]] + ! CHECK-O0: fir.call @_FortranACharacterCompareScalar1({{.*}}, %[[STR88_CONV]] + ! CHECK-O0-NEXT: arith.cmpi sge,{{.*}}, %c0_i32 : i32 + ! CHECK-O1: fir.do_loop {{.*}} -> (i8) { + ! CHECK-O1: arith.cmpi sge, %{{[0-9]+}}, %c{{[0-9]+}}_i8 : i8 + ! CHECK-NEXT: cf.cond_br case('44':'55','66':'77','88':) n = 4 - ! CHECK: %[[V_60:[0-9]+]] = fir.call @_FortranACharacterCompareScalar1 - ! CHECK: %[[V_61:[0-9]+]] = arith.cmpi sge, %[[V_60]], %c0{{.*}} : i32 - ! CHECK: cond_br %[[V_61]], ^bb9, ^bb10 - ! CHECK: ^bb8: // pred: ^bb5 - ! CHECK: fir.store %c3{{.*}} to %[[V_1]] : !fir.ref<i32> - ! CHECK: ^bb9: // pred: ^bb7 - ! CHECK: %[[V_66:[0-9]+]] = fir.call @_FortranACharacterCompareScalar1 - ! CHECK: %[[V_67:[0-9]+]] = arith.cmpi sle, %[[V_66]], %c0{{.*}} : i32 - ! CHECK: cond_br %[[V_67]], ^bb14, ^bb10 - ! CHECK: ^bb10: // 2 preds: ^bb7, ^bb9 - ! CHECK: %[[V_72:[0-9]+]] = fir.call @_FortranACharacterCompareScalar1 - ! CHECK: %[[V_73:[0-9]+]] = arith.cmpi sge, %[[V_72]], %c0{{.*}} : i32 - ! CHECK: cond_br %[[V_73]], ^bb11, ^bb12 - ! CHECK: ^bb11: // pred: ^bb10 - ! CHECK: %[[V_78:[0-9]+]] = fir.call @_FortranACharacterCompareScalar1 - ! CHECK: %[[V_79:[0-9]+]] = arith.cmpi sle, %[[V_78]], %c0{{.*}} : i32 - ! CHECK: ^bb12: // 2 preds: ^bb10, ^bb11 - ! CHECK: %[[V_84:[0-9]+]] = fir.call @_FortranACharacterCompareScalar1 - ! CHECK: %[[V_85:[0-9]+]] = arith.cmpi sge, %[[V_84]], %c0{{.*}} : i32 - ! CHECK: cond_br %[[V_85]], ^bb14, ^bb13 - ! CHECK: ^bb13: // pred: ^bb12 - ! CHECK: ^bb14: // 3 preds: ^bb9, ^bb11, ^bb12 - ! CHECK: fir.store %c4{{.*}} to %[[V_1]] : !fir.ref<i32> - ! CHECK: ^bb15: // 5 preds: ^bb3, ^bb4, ^bb6, ^bb8, ^bb14 - ! CHECK: fir.freemem %[[V_20]] : !fir.heap<!fir.char<1,?>> end select end if - ! CHECK: %[[V_89:[0-9]+]] = fir.load %[[V_1]] : !fir.ref<i32> print*, n end subroutine ! CHECK-LABEL: func @_QPscharacter2 subroutine scharacter2(s) - ! CHECK-DAG: %[[V_0:[0-9]+]] = fir.alloca !fir.box<!fir.heap<!fir.char<1,?>>> - ! CHECK: %[[V_1:[0-9]+]] = fir.alloca !fir.box<!fir.heap<!fir.char<1,?>>> character(len=3) :: s - + ! CHECK: %[[N:[0-9]+]] = fir.declare {{.*}} {uniq_name = "_QFscharacter2En"} + ! CHECK: fir.store %c-10_i32 to %[[N]] : !fir.ref<i32> n = -10 - ! CHECK: %[[V_12:[0-9]+]] = fir.load %[[V_1]] : !fir.ref<!fir.box<!fir.heap<!fir.char<1,?>>>> - ! CHECK: %[[V_13:[0-9]+]] = fir.box_addr %[[V_12]] : (!fir.box<!fir.heap<!fir.char<1,?>>>) -> !fir.heap<!fir.char<1,?>> - ! CHECK: br ^bb1 - ! CHECK: ^bb1: // pred: ^bb0 - ! CHECK: fir.store %c9{{.*}} - ! CHECK: br ^bb2 - ! CHECK: ^bb2: // pred: ^bb1 - ! CHECK: fir.freemem %[[V_13]] : !fir.heap<!fir.char<1,?>> + ! CHECK: fir.call @_FortranATrim( select case(trim(s)) case default + ! CHECK: fir.store %c9_i32 to %[[N]] : !fir.ref<i32> n = 9 end select + + ! CHECK: fir.call @_FortranAioBeginExternalListOutput( print*, n + ! CHECK: fir.store %c-2_i32 to %[[N]] : !fir.ref<i32> n = -2 - ! CHECK: %[[V_28:[0-9]+]] = fir.load %[[V_0]] : !fir.ref<!fir.box<!fir.heap<!fir.char<1,?>>>> - ! CHECK: %[[V_29:[0-9]+]] = fir.box_addr %[[V_28]] : (!fir.box<!fir.heap<!fir.char<1,?>>>) -> !fir.heap<!fir.char<1,?>> - ! CHECK: br ^bb3 - ! CHECK: ^bb3: // pred: ^bb2 - ! CHECK: fir.freemem %[[V_29]] : !fir.heap<!fir.char<1,?>> + + ! CHECK: fir.call @_FortranATrim( select case(trim(s)) end select + ! CHECK: fir.call @_FortranAioBeginExternalListOutput( print*, n end subroutine ! CHECK-LABEL: func @_QPsempty ! empty select case blocks subroutine sempty(n) - ! CHECK: %[[selectI1:[0-9]+]] = fir.load %arg0 : !fir.ref<i32> - ! CHECK: fir.select_case %[[selectI1]] : i32 [#fir.point, %c1{{.*}}, ^bb1, #fir.point, %c2{{.*}}, ^bb2, unit, ^bb3] - ! CHECK: ^bb1: // pred: ^bb0 - ! CHECK: fir.call @_FortranAioBeginExternalListOutput - ! CHECK: br ^bb4 - ! CHECK: ^bb2: // pred: ^bb0 - ! CHECK: br ^bb4 - ! CHECK: ^bb3: // pred: ^bb0 - ! CHECK: fir.call @_FortranAioBeginExternalListOutput - ! CHECK: br ^bb4 + !CHECK: fir.select_case {{.*}} : i32 [#fir.point, %c1_i32, ^bb1, #fir.point, %c2_i32, ^bb2, unit, ^bb3] select case (n) case (1) + !CHECK: ^bb1: + !CHECK: fir.call @_FortranAioBeginExternalListOutput( + !CHECK: cf.br ^bb4 print*, n, 'i:case 1' case (2) - ! print*, n, 'i:case 2' + !CHECK: ^bb2: + !CHECK-NEXT: cf.br ^bb4 + ! (empty) print*, n, 'i:case 2' case default print*, n, 'i:case default' end select - ! CHECK: ^bb4: // 3 preds: ^bb1, ^bb2, ^bb3 - ! CHECK: %[[cmpC1:[0-9]+]] = fir.call @_FortranACharacterCompareScalar1 - ! CHECK: %[[selectC1:[0-9]+]] = arith.cmpi eq, %[[cmpC1]], %c0{{.*}} : i32 - ! CHECK: cond_br %[[selectC1]], ^bb6, ^bb5 - ! CHECK: ^bb5: // pred: ^bb4 - ! CHECK: %[[cmpC2:[0-9]+]] = fir.call @_FortranACharacterCompareScalar1 - ! CHECK: %[[selectC2:[0-9]+]] = arith.cmpi eq, %[[cmpC2]], %c0{{.*}} : i32 - ! CHECK: cond_br %[[selectC2]], ^bb8, ^bb7 - ! CHECK: ^bb6: // pred: ^bb4 - ! CHECK: fir.call @_FortranAioBeginExternalListOutput - ! print*, n, 'c:case 2' - ! CHECK: br ^bb10 - ! CHECK: ^bb7: // pred: ^bb5 - ! CHECK: br ^bb9 - ! CHECK: ^bb8: // pred: ^bb5 - ! CHECK: br ^bb10 - ! CHECK: ^bb9: // pred: ^bb7 - ! CHECK: fir.call @_FortranAioBeginExternalListOutput - ! CHECK: br ^bb10 - ! CHECK: ^bb10: // 3 preds: ^bb6, ^bb8, ^bb9 select case (char(ichar('0')+n)) + ! == '1' + ! CHECK-O0: fir.call @_FortranACharacterCompareScalar1( + ! CHECK-O0-NEXT: arith.cmpi eq, {{.*}}, %c0_i32 : i32 + ! CHECK-O1: fir.do_loop {{.*}} -> (i8) { + ! CHECK-O1: arith.cmpi eq, %{{[0-9]+}}, %c{{[0-9]+}}_i8 : i8 + ! CHECK-NEXT: cf.cond_br case ('1') print*, n, 'c:case 1' case ('2') - ! print*, n, 'c:case 2' + ! == '2' + ! CHECK-O0: fir.call @_FortranACharacterCompareScalar1( + ! CHECK-O0-NEXT: arith.cmpi eq, {{.*}}, %c0_i32 : i32 + ! CHECK-O1: fir.do_loop {{.*}} -> (i8) { + ! CHECK-O1: arith.cmpi eq, %{{[0-9]+}}, %c{{[0-9]+}}_i8 : i8 + ! CHECK-NEXT: cf.cond_br + ! (empty) print*, n, 'c:case 2' case default print*, n, 'c:case default' end select - ! CHECK: return + ! CHECK: return end subroutine ! CHECK-LABEL: func @_QPsgoto ! select case with goto exit subroutine sgoto n = 0 + ! CHECK: cf.cond_br do i=1,8 - ! CHECK: %[[i:[0-9]+]] = fir.alloca {{.*}} "_QFsgotoEi" - ! CHECK: ^bb2: // pred: ^bb1 - ! CHECK: %[[selector:[0-9]+]] = fir.load %[[i]] : !fir.ref<i32> - ! CHECK: fir.select_case %[[selector]] : i32 [#fir.upper, %c2{{.*}}, ^bb3, #fir.lower, %c5{{.*}}, ^bb4, unit, ^bb7] - ! CHECK: ^bb3: // pred: ^bb2 - ! CHECK: arith.muli %c10{{[^0]}} - ! CHECK: br ^bb8 - ! CHECK: ^bb4: // pred: ^bb2 - ! CHECK: arith.muli %c1000{{[^0]}} - ! CHECK: cond_br {{.*}}, ^bb5, ^bb6 - ! CHECK: ^bb5: // pred: ^bb4 - ! CHECK: br ^bb8 - ! CHECK: ^bb6: // pred: ^bb4 - ! CHECK: arith.muli %c10000{{[^0]}} - ! CHECK: br ^bb8 - ! CHECK: ^bb7: // pred: ^bb2 - ! CHECK: arith.muli %c100{{[^0]}} - ! CHECK: br ^bb8 - ! CHECK: ^bb8: // 4 preds: ^bb3, ^bb5, ^bb6, ^bb7 - ! CHECK: fir.call @_FortranAioBeginExternalListOutput - ! CHECK: br ^bb1 - ! CHECK: ^bb9: // pred: ^bb1 + ! CHECK: fir.select_case %8 : i32 [#fir.upper, %c2_i32, ^bb{{.*}}, #fir.lower, %c5_i32, ^bb{{.*}}, unit, ^bb{{.*}}] select case(i) case (:2) + ! CHECK-DAG: arith.muli {{.*}}, %c10_i32 : i32 n = i * 10 case (5:) + ! CHECK-DAG: arith.muli {{.*}}, %c1000_i32 : i32 n = i * 1000 + ! CHECK-DAG: arith.cmpi sle, {{.*}}, %c6_i32 : i32 + ! CHECK-NEXT: cf.cond_br if (i <= 6) goto 9 + ! CHECK-DAG: arith.muli {{.*}}, %c10000_i32 : i32 n = i * 10000 case default + ! CHECK-DAG: arith.muli {{.*}}, %c100_i32 : i32 n = i * 100 9 end select print*, n enddo - ! CHECK: return + ! CHECK: return end ! CHECK-LABEL: func @_QPswhere @@ -372,19 +381,17 @@ array = 0.0 + ! CHECK: fir.select_case {{.*}} : i32 [#fir.point, %c1_i32, ^bb1, unit, ^bb2] select case (num) - ! CHECK: ^bb1: // pred: ^bb0 case (1) + ! CHECK: fir.do_loop where (array >= 0.0) array = 42 end where - ! CHECK: cf.br ^bb3 - ! CHECK: ^bb2: // pred: ^bb0 case default array = -1 end select ! CHECK: cf.br ^bb3 - ! CHECK: ^bb3: // 2 preds: ^bb1, ^bb2 print*, array(1) end subroutine swhere @@ -394,22 +401,19 @@ integer, intent(in) :: num real, dimension(1) :: array + integer :: i array = 0.0 + ! CHECK: fir.select_case {{.*}} : i32 [#fir.point, %c1_i32, ^bb1, unit, ^bb2] select case (num) - ! CHECK: ^bb1: // pred: ^bb0 case (1) - where (array >= 0.0) - array = 42 - end where - ! CHECK: cf.br ^bb3 - ! CHECK: ^bb2: // pred: ^bb0 + ! CHECK: fir.do_loop + forall (i = 1:size(array)) array(i) = 42 case default array = -1 end select ! CHECK: cf.br ^bb3 - ! CHECK: ^bb3: // 2 preds: ^bb1, ^bb2 print*, array(1) end subroutine sforall @@ -418,20 +422,26 @@ character(*), optional :: str integer :: num + ! CHECK: fir.is_present if (present(str)) then + ! CHECK: fir.call @_FortranATrim select case (trim(str)) + ! == 'a' + ! CHECK-O0: fir.call @_FortranACharacterCompareScalar1 + ! CHECK-O0-NEXT: arith.cmpi eq, {{.*}}, %c0_i32 : i32 + ! CHECK-O1: fir.do_loop {{.*}} -> (i8) { + ! CHECK-O1: arith.cmpi eq, %{{[0-9]+}}, %c{{[0-9]+}}_i8 : i8 case ('a') + ! CHECK-DAG: fir.store %c10_i32 to {{.*}} : !fir.ref<i32> num = 10 case default + ! CHECK-DAG: fir.store %c20_i32 to {{.*}} : !fir.ref<i32> num = 20 end select - ! CHECK: ^bb5: // 2 preds: ^bb3, ^bb4 - ! CHECK: fir.freemem %{{[0-9]+}} : !fir.heap<!fir.char<1,?>> - ! CHECK: cf.br ^bb7 else + ! CHECK-DAG: fir.store %c30_i32 to {{.*}} : !fir.ref<i32> num = 30 end if - ! CHECK: ^bb7: // 2 preds: ^bb5, ^bb6 end subroutine snested ! CHECK-LABEL: main @@ -485,7 +495,7 @@ call scharacter1('00 ') ! expected output: 0 call scharacter1('. ') ! expected output: 0 call scharacter1(' ') ! expected output: 0 - + print* call scharacter2('99 ') ! expected output: 9 -2 call scharacter2('22 ') ! expected output: 9 -2 @@ -499,7 +509,7 @@ call sempty(3) ! expected output: 3 i:case default; 3 c:case default print* - call sgoto ! expected output: 10 20 300 400 5000 6000 70000 80000 + call sgoto ! expected output: 10 20 300 400 5000 6000 70000 80000 print* call swhere(1) ! expected output: 42. diff --git a/flang/test/Lower/select-type.f90 b/flang/test/Lower/select-type.f90 index e2ca87a..246b653 100644 --- a/flang/test/Lower/select-type.f90 +++ b/flang/test/Lower/select-type.f90 @@ -38,7 +38,7 @@ contains allocate(negate, source=this) negate%a = -this%a end function - + subroutine select_type1(a) class(p1), intent(in) :: a @@ -275,7 +275,7 @@ contains ! CHECK-LABEL: func.func @_QMselect_type_lower_testPselect_type5( ! CHECK-SAME: %[[ARG0:.*]]: !fir.class<none> {fir.bindc_name = "a"}) ! CHECK: fir.select_type %[[ARG0]] : !fir.class<none> -! CHECK-SAME: [#fir.type_is<i8>, ^[[I8_BLK:.*]], #fir.type_is<i32>, ^[[I32_BLK:.*]], #fir.type_is<f32>, ^[[F32_BLK:.*]], #fir.type_is<!fir.logical<4>>, ^[[LOG_BLK:.*]], #fir.type_is<!fir.char<1,?>>, ^[[CHAR_BLK:.*]], unit, ^[[DEFAULT:.*]]] +! CHECK-SAME: [#fir.type_is<i8>, ^[[I8_BLK:.*]], #fir.type_is<i32>, ^[[I32_BLK:.*]], #fir.type_is<f32>, ^[[F32_BLK:.*]], #fir.type_is<!fir.logical<4>>, ^[[LOG_BLK:.*]], #fir.type_is<!fir.char<1,?>>, ^[[CHAR_BLK:.*]], unit, ^[[DEFAULT:.*]]] ! CHECK: ^[[I8_BLK]] ! CHECK: ^[[I32_BLK]] ! CHECK: ^[[F32_BLK]] @@ -467,7 +467,7 @@ contains ! CHECK: %[[SELECTOR:.*]] = fir.rebox %[[ARG0]] : (!fir.class<!fir.array<?xnone>>) -> !fir.class<!fir.array<?xnone>> ! CHECK: fir.select_type %[[SELECTOR]] : !fir.class<!fir.array<?xnone>> [#fir.type_is<i32>, ^{{.*}}, #fir.type_is<f32>, ^{{.*}}, #fir.type_is<!fir.char<1,?>>, ^bb{{.*}}, unit, ^{{.*}}] ! CHECK: ^bb{{.*}}: -! CHECK: %[[BOX:.*]] = fir.convert %[[SELECTOR]] : (!fir.class<!fir.array<?xnone>>) -> !fir.box<!fir.array<?xi32>> +! CHECK: %[[BOX:.*]] = fir.convert %[[SELECTOR]] : (!fir.class<!fir.array<?xnone>>) -> !fir.box<!fir.array<?xi32>> ! CHECK: %[[C0:.*]] = arith.constant 0 : index ! CHECK: %[[SELECTOR_DIMS:.*]]:3 = fir.box_dims %[[BOX]], %[[C0]] : (!fir.box<!fir.array<?xi32>>, index) -> (index, index, index) ! CHECK: %[[ARRAY_LOAD:.*]] = fir.array_load %[[BOX]] : (!fir.box<!fir.array<?xi32>>) -> !fir.array<?xi32> @@ -482,7 +482,7 @@ contains ! CHECK: fir.array_merge_store %[[ARRAY_LOAD]], %[[LOOP_RES]] to %[[BOX]] : !fir.array<?xi32>, !fir.array<?xi32>, !fir.box<!fir.array<?xi32>> ! CHECK: cf.br ^{{.*}} ! CHECK: ^bb{{.*}}: -! CHECK: %[[BOX:.*]] = fir.convert %[[SELECTOR]] : (!fir.class<!fir.array<?xnone>>) -> !fir.box<!fir.array<?xf32>> +! CHECK: %[[BOX:.*]] = fir.convert %[[SELECTOR]] : (!fir.class<!fir.array<?xnone>>) -> !fir.box<!fir.array<?xf32>> ! CHECK: %[[C0:.*]] = arith.constant 0 : index ! CHECK: %[[SELECTOR_DIMS:.*]]:3 = fir.box_dims %[[BOX]], %[[C0]] : (!fir.box<!fir.array<?xf32>>, index) -> (index, index, index) ! CHECK: %[[ARRAY_LOAD:.*]] = fir.array_load %[[BOX]] : (!fir.box<!fir.array<?xf32>>) -> !fir.array<?xf32> @@ -497,7 +497,7 @@ contains ! CHECK: fir.array_merge_store %[[ARRAY_LOAD]], %[[LOOP_RES]] to %[[BOX]] : !fir.array<?xf32>, !fir.array<?xf32>, !fir.box<!fir.array<?xf32>> ! CHECK: cf.br ^{{.*}} ! CHECK: ^bb{{.*}}: -! CHECK: %[[BOX:.*]] = fir.convert %{{[0-9]+}} : (!fir.class<!fir.array<?xnone>>) -> !fir.box<!fir.array<?x!fir.char<1,?>>> +! CHECK: %[[BOX:.*]] = fir.convert %{{[0-9]+}} : (!fir.class<!fir.array<?xnone>>) -> !fir.box<!fir.array<?x!fir.char<1,?>>> ! CHECK: cf.br ^bb{{.*}} ! CHECK: ^bb{{.*}}: ! CHECK: %[[EXACT_BOX:.*]] = fir.convert %[[SELECTOR]] : (!fir.class<!fir.array<?xnone>>) -> !fir.box<!fir.array<?x!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>>> @@ -517,7 +517,7 @@ contains ! CHECK: %[[BOX_DIMS:.*]]:3 = fir.box_dims %[[EXACT_BOX]], %[[C0]] : (!fir.box<!fir.array<?x!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>>>, index) -> (index, index, index) ! CHECK: %[[C1:.*]] = arith.constant 1 : index ! CHECK: %[[SLICE:.*]] = fir.slice %[[C1]], %[[BOX_DIMS]]#1, %[[C1]] path %[[FIELD_B]] : (index, index, index, !fir.field) -> !fir.slice<1> -! CHECK: %[[ARRAY_LOAD:.*]] = fir.array_load %[[EXACT_BOX]] [%[[SLICE]]] : (!fir.box<!fir.array<?x!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>>>, !fir.slice<1>) -> !fir.array<?xi32> +! CHECK: %[[ARRAY_LOAD:.*]] = fir.array_load %[[EXACT_BOX]] [%[[SLICE]]] : (!fir.box<!fir.array<?x!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>>>, !fir.slice<1>) -> !fir.array<?xi32> ! CHECK: %[[DO_RES:.*]] = fir.do_loop %[[IND:.*]] = %{{.*}} to %{{.*}} step %c{{.*}} unordered iter_args(%[[ARG:.*]] = %[[ARRAY_LOAD]]) -> (!fir.array<?xi32>) { ! CHECK: %[[ARR_UP:.*]] = fir.array_update %[[ARG]], %{{.*}}, %[[IND]] : (!fir.array<?xi32>, i32, index) -> !fir.array<?xi32> ! CHECK: fir.result %[[ARR_UP]] : !fir.array<?xi32> @@ -599,7 +599,7 @@ contains ! CHECK: %[[BOX_DIMS:.*]]:3 = fir.box_dims %[[EXACT_BOX]], %[[C0]] : (!fir.box<!fir.array<?x!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>>>, index) -> (index, index, index) ! CHECK: %[[C1:.*]] = arith.constant 1 : index ! CHECK: %[[SLICE:.*]] = fir.slice %[[C1]], %[[BOX_DIMS]]#1, %[[C1]] path %[[FIELD_B]] : (index, index, index, !fir.field) -> !fir.slice<1> -! CHECK: %[[ARRAY_LOAD:.*]] = fir.array_load %[[EXACT_BOX]] [%[[SLICE]]] : (!fir.box<!fir.array<?x!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>>>, !fir.slice<1>) -> !fir.array<?xi32> +! CHECK: %[[ARRAY_LOAD:.*]] = fir.array_load %[[EXACT_BOX]] [%[[SLICE]]] : (!fir.box<!fir.array<?x!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>>>, !fir.slice<1>) -> !fir.array<?xi32> ! CHECK: %[[DO_RES:.*]] = fir.do_loop %[[IND:.*]] = %{{.*}} to %{{.*}} step %c{{.*}} unordered iter_args(%[[ARG:.*]] = %[[ARRAY_LOAD]]) -> (!fir.array<?xi32>) { ! CHECK: %[[ARR_UP:.*]] = fir.array_update %[[ARG]], %{{.*}}, %[[IND]] : (!fir.array<?xi32>, i32, index) -> !fir.array<?xi32> ! CHECK: fir.result %[[ARR_UP]] : !fir.array<?xi32> @@ -607,7 +607,7 @@ contains ! CHECK: fir.array_merge_store %[[ARRAY_LOAD]], %[[DO_RES]] to %[[EXACT_BOX]][%[[SLICE]]] : !fir.array<?xi32>, !fir.array<?xi32>, !fir.box<!fir.array<?x!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>>>, !fir.slice<1> ! CHECK: cf.br ^bb{{.*}} ! CHECK: ^bb{{.*}}: -! CHECK: %[[EXACT_BOX:.*]] = fir.convert %[[SELECTOR]] : (!fir.class<!fir.array<?x!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>>>) -> !fir.box<!fir.array<?x!fir.type<_QMselect_type_lower_testTp2{a:i32,b:i32,c:i32}>>> +! CHECK: %[[EXACT_BOX:.*]] = fir.convert %[[SELECTOR]] : (!fir.class<!fir.array<?x!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>>>) -> !fir.box<!fir.array<?x!fir.type<_QMselect_type_lower_testTp2{a:i32,b:i32,c:i32}>>> ! CHECK: %[[FIELD_A:.*]] = fir.field_index a, !fir.type<_QMselect_type_lower_testTp2{a:i32,b:i32,c:i32}> ! CHECK: %[[C0:.*]] = arith.constant 0 : index ! CHECK: %[[BOX_DIMS:.*]]:3 = fir.box_dims %[[EXACT_BOX]], %[[C0]] : (!fir.box<!fir.array<?x!fir.type<_QMselect_type_lower_testTp2{a:i32,b:i32,c:i32}>>>, index) -> (index, index, index) diff --git a/flang/test/Lower/statement-function.f90 b/flang/test/Lower/statement-function.f90 index cfec06c..9dd26d4 100644 --- a/flang/test/Lower/statement-function.f90 +++ b/flang/test/Lower/statement-function.f90 @@ -21,7 +21,7 @@ end function ! Check this is not lowered as a simple macro: e.g. argument is only ! evaluated once even if it appears in several placed inside the -! statement function expression +! statement function expression ! CHECK-LABEL: func @_QPtest_stmt_only_eval_arg_once() -> f32 real(4) function test_stmt_only_eval_arg_once() real(4) :: only_once, x1 @@ -129,7 +129,6 @@ integer function test_stmt_character_with_different_length_2(c, n) character(n) :: argc character(*) :: c ! CHECK: %[[unboxed:.*]]:2 = fir.unboxchar %[[arg0]] : - ! CHECK: fir.load %[[arg1]] : !fir.ref<i32> ! CHECK: %[[n:.*]] = fir.load %[[arg1]] : !fir.ref<i32> ! CHECK: %[[n_is_positive:.*]] = arith.cmpi sgt, %[[n]], %c0{{.*}} : i32 ! CHECK: %[[len:.*]] = arith.select %[[n_is_positive]], %[[n]], %c0{{.*}} : i32 diff --git a/flang/test/Lower/structure-constructors-alloc-comp.f90 b/flang/test/Lower/structure-constructors-alloc-comp.f90 index 9df5be1..c624433 100644 --- a/flang/test/Lower/structure-constructors-alloc-comp.f90 +++ b/flang/test/Lower/structure-constructors-alloc-comp.f90 @@ -24,7 +24,7 @@ contains ! HLFIR-LABEL: func.func @_QMm_struct_ctorPtest_alloc1( ! HLFIR-SAME: %[[ARG_0:.*]]: !fir.ref<f32> {fir.bindc_name = "y"}) { ! HLFIR: %[[VAL_0:.*]] = fir.alloca !fir.type<_QMm_struct_ctorTt_alloc{x:f32,a:!fir.box<!fir.heap<!fir.array<?xi32>>>}> -! HLFIR: %[[VAL_12:.*]]:2 = hlfir.declare %[[ARG_0]] dummy_scope %{{[0-9]+}} {uniq_name = "_QMm_struct_ctorFtest_alloc1Ey"} : (!fir.ref<f32>, !fir.dscope) -> (!fir.ref<f32>, !fir.ref<f32>) +! HLFIR: %[[VAL_12:.*]]:2 = hlfir.declare %[[ARG_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QMm_struct_ctorFtest_alloc1Ey"} : (!fir.ref<f32>, !fir.dscope) -> (!fir.ref<f32>, !fir.ref<f32>) ! HLFIR: %[[VAL_13:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = "ctor.temp"} : (!fir.ref<!fir.type<_QMm_struct_ctorTt_alloc{x:f32,a:!fir.box<!fir.heap<!fir.array<?xi32>>>}>>) -> (!fir.ref<!fir.type<_QMm_struct_ctorTt_alloc{x:f32,a:!fir.box<!fir.heap<!fir.array<?xi32>>>}>>, !fir.ref<!fir.type<_QMm_struct_ctorTt_alloc{x:f32,a:!fir.box<!fir.heap<!fir.array<?xi32>>>}>>) ! HLFIR: %[[VAL_14:.*]] = fir.embox %[[VAL_13]]#0 : (!fir.ref<!fir.type<_QMm_struct_ctorTt_alloc{x:f32,a:!fir.box<!fir.heap<!fir.array<?xi32>>>}>>) -> !fir.box<!fir.type<_QMm_struct_ctorTt_alloc{x:f32,a:!fir.box<!fir.heap<!fir.array<?xi32>>>}>> ! HLFIR: %[[VAL_15:.*]] = fir.address_of(@_QQ{{.*}}) : !fir.ref<!fir.char<1,{{.*}}>> @@ -49,8 +49,8 @@ contains ! HLFIR: %[[VAL_0:.*]] = fir.alloca !fir.type<_QMm_struct_ctorTt_alloc{x:f32,a:!fir.box<!fir.heap<!fir.array<?xi32>>>}> ! HLFIR: %[[CONS_6:.*]] = arith.constant 5 : index ! HLFIR: %[[VAL_12:.*]] = fir.shape %[[CONS_6]] : (index) -> !fir.shape<1> -! HLFIR: %[[VAL_13:.*]]:2 = hlfir.declare %[[ARG_1]](%[[VAL_12]]) dummy_scope %{{[0-9]+}} {uniq_name = "_QMm_struct_ctorFtest_alloc2Eb"} : (!fir.ref<!fir.array<5xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<5xi32>>, !fir.ref<!fir.array<5xi32>>) -! HLFIR: %[[VAL_14:.*]]:2 = hlfir.declare %[[ARG_0]] dummy_scope %{{[0-9]+}} {uniq_name = "_QMm_struct_ctorFtest_alloc2Ey"} : (!fir.ref<f32>, !fir.dscope) -> (!fir.ref<f32>, !fir.ref<f32>) +! HLFIR: %[[VAL_13:.*]]:2 = hlfir.declare %[[ARG_1]](%[[VAL_12]]) dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QMm_struct_ctorFtest_alloc2Eb"} : (!fir.ref<!fir.array<5xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<5xi32>>, !fir.ref<!fir.array<5xi32>>) +! HLFIR: %[[VAL_14:.*]]:2 = hlfir.declare %[[ARG_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QMm_struct_ctorFtest_alloc2Ey"} : (!fir.ref<f32>, !fir.dscope) -> (!fir.ref<f32>, !fir.ref<f32>) ! HLFIR: %[[VAL_15:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = "ctor.temp"} : (!fir.ref<!fir.type<_QMm_struct_ctorTt_alloc{x:f32,a:!fir.box<!fir.heap<!fir.array<?xi32>>>}>>) -> (!fir.ref<!fir.type<_QMm_struct_ctorTt_alloc{x:f32,a:!fir.box<!fir.heap<!fir.array<?xi32>>>}>>, !fir.ref<!fir.type<_QMm_struct_ctorTt_alloc{x:f32,a:!fir.box<!fir.heap<!fir.array<?xi32>>>}>>) ! HLFIR: %[[VAL_16:.*]] = fir.embox %[[VAL_15]]#0 : (!fir.ref<!fir.type<_QMm_struct_ctorTt_alloc{x:f32,a:!fir.box<!fir.heap<!fir.array<?xi32>>>}>>) -> !fir.box<!fir.type<_QMm_struct_ctorTt_alloc{x:f32,a:!fir.box<!fir.heap<!fir.array<?xi32>>>}>> ! HLFIR: %[[VAL_17:.*]] = fir.address_of(@_QQ{{.*}}) : !fir.ref<!fir.char<1,{{.*}}>> diff --git a/flang/test/Lower/taskloop-inreduction.f90 b/flang/test/Lower/taskloop-inreduction.f90 new file mode 100644 index 0000000..e7d3f96 --- /dev/null +++ b/flang/test/Lower/taskloop-inreduction.f90 @@ -0,0 +1,40 @@ +! RUN: bbc -emit-hlfir -fopenmp -fopenmp-version=50 -o - %s 2>&1 | FileCheck %s +! RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=50 -o - %s 2>&1 | FileCheck %s + +! CHECK-LABEL: omp.private +! CHECK-SAME: {type = private} @[[PRIVATE_I:.*]] : i32 + +! CHECK-LABEL: omp.declare_reduction +! CHECK-SAME: @[[ADD_RED_I32:.*]] : i32 init { +! CHECK: ^bb0(%{{.*}}: i32): +! CHECK: %[[C0_I32:.*]] = arith.constant 0 : i32 +! CHECK: omp.yield(%[[C0_I32]] : i32) +! CHECK: } combiner { +! CHECK: ^bb0(%{{.*}}: i32, %{{.*}}: i32): +! CHECK: %[[RES:.*]] = arith.addi %{{.*}}, %{{.*}} : i32 +! CHECK: omp.yield(%[[RES]] : i32) +! CHECK: } + +! CHECK-LABEL: func.func @_QPomp_taskloop_inreduction +! CHECK: %[[ALLOCA_I:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFomp_taskloop_inreductionEi"} +! CHECK: %[[DECL_I:.*]]:2 = hlfir.declare %[[ALLOCA_I]] {uniq_name = "_QFomp_taskloop_inreductionEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[ALLOCA_X:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFomp_taskloop_inreductionEx"} +! CHECK: %[[DECL_X:.*]]:2 = hlfir.declare %[[ALLOCA_X]] {uniq_name = "_QFomp_taskloop_inreductionEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[INIT_X:.*]] = arith.constant 0 : i32 +! CHECK: hlfir.assign %[[INIT_X]] to %[[DECL_X]]#0 : i32, !fir.ref<i32> +subroutine omp_taskloop_inreduction() + integer x + x = 0 + ! CHECK: omp.taskloop in_reduction(@[[ADD_RED_I32]] + ! CHECK: %[[DECL_X]]#0 -> %[[ARG0:.*]] : !fir.ref<i32>) private(@[[PRIVATE_I]] %[[DECL_I]]#0 -> %[[ARG1:.*]] : !fir.ref<i32>) { + ! CHECK: %[[VAL_ARG1:.*]]:2 = hlfir.declare %[[ARG0]] + ! CHECK-SAME: {uniq_name = "_QFomp_taskloop_inreductionEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) + !$omp taskloop in_reduction(+:x) + do i = 1, 100 + ! CHECK: %[[X_VAL:.*]] = fir.load %[[VAL_ARG1]]#0 : !fir.ref<i32> + ! CHECK: %[[ADD_VAL:.*]] = arith.addi %[[X_VAL]], %{{.*}} : i32 + x = x + 1 + ! CHECK: hlfir.assign %[[ADD_VAL]] to %[[VAL_ARG1]]#0 : i32, !fir.ref<i32> + end do + !$omp end taskloop +end subroutine omp_taskloop_inreduction diff --git a/flang/test/Lower/taskloop-reduction.f90 b/flang/test/Lower/taskloop-reduction.f90 new file mode 100644 index 0000000..e45c018 --- /dev/null +++ b/flang/test/Lower/taskloop-reduction.f90 @@ -0,0 +1,39 @@ +! RUN: bbc -emit-hlfir -fopenmp -fopenmp-version=50 -o - %s 2>&1 | FileCheck %s +! RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=50 -o - %s 2>&1 | FileCheck %s + +! CHECK-LABEL: omp.private +! CHECK-SAME: {type = private} @[[PRIVATE_I:.*]] : i32 + +! CHECK-LABEL: omp.declare_reduction +! CHECK-SAME: @[[ADD_RED_I32:.*]] : i32 init { +! CHECK: ^bb0(%{{.*}}: i32): +! CHECK: %[[C0_I32:.*]] = arith.constant 0 : i32 +! CHECK: omp.yield(%[[C0_I32]] : i32) +! CHECK: } combiner { +! CHECK: ^bb0(%{{.*}}: i32, %{{.*}}: i32): +! CHECK: %[[RES:.*]] = arith.addi %{{.*}}, %{{.*}} : i32 +! CHECK: omp.yield(%[[RES]] : i32) +! CHECK: } + +! CHECK-LABEL: func.func @_QPomp_taskloop_reduction +! CHECK: %[[ALLOCA_I:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFomp_taskloop_reductionEi"} +! CHECK: %[[DECL_I:.*]]:2 = hlfir.declare %[[ALLOCA_I]] {uniq_name = "_QFomp_taskloop_reductionEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[ALLOCA_X:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFomp_taskloop_reductionEx"} +! CHECK: %[[DECL_X:.*]]:2 = hlfir.declare %[[ALLOCA_X]] {uniq_name = "_QFomp_taskloop_reductionEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[INIT_X:.*]] = arith.constant 0 : i32 +! CHECK: hlfir.assign %[[INIT_X]] to %[[DECL_X]]#0 : i32, !fir.ref<i32> +subroutine omp_taskloop_reduction() + integer x + x = 0 + ! CHECK: omp.taskloop private(@[[PRIVATE_I]] + ! CHECK-SAME: %[[DECL_I]]#0 -> %[[ARG0:.*]] : !fir.ref<i32>) reduction(@[[ADD_RED_I32]] %[[DECL_X]]#0 -> %[[ARG1:.*]] : !fir.ref<i32>) { + ! CHECK: %[[VAL_ARG1:.*]]:2 = hlfir.declare %[[ARG1]] + !$omp taskloop reduction(+:x) + do i = 1, 100 + ! CHECK: %[[X_VAL:.*]] = fir.load %[[VAL_ARG1]]#0 : !fir.ref<i32> + ! CHECK: %[[ADD_VAL:.*]] = arith.addi %[[X_VAL]], %{{.*}} : i32 + x = x + 1 + ! CHECK: hlfir.assign %[[ADD_VAL]] to %[[VAL_ARG1]]#0 : i32, !fir.ref<i32> + end do + !$omp end taskloop +end subroutine omp_taskloop_reduction diff --git a/flang/test/Lower/unsigned-ops.f90 b/flang/test/Lower/unsigned-ops.f90 index 13e1772..644f0c4 100644 --- a/flang/test/Lower/unsigned-ops.f90 +++ b/flang/test/Lower/unsigned-ops.f90 @@ -10,8 +10,8 @@ end !CHECK: %[[VAL_0:.*]] = fir.dummy_scope : !fir.dscope !CHECK: %[[VAL_1:.*]] = fir.alloca ui32 {bindc_name = "f01", uniq_name = "_QFf01Ef01"} !CHECK: %[[VAL_2:.*]] = fir.declare %[[VAL_1]] {uniq_name = "_QFf01Ef01"} : (!fir.ref<ui32>) -> !fir.ref<ui32> -!CHECK: %[[VAL_3:.*]] = fir.declare %[[ARG0]] dummy_scope %[[VAL_0]] {fortran_attrs = #fir.var_attrs<intent_in>, uniq_name = "_QFf01Eu"} : (!fir.ref<ui32>, !fir.dscope) -> !fir.ref<ui32> -!CHECK: %[[VAL_4:.*]] = fir.declare %[[ARG1]] dummy_scope %[[VAL_0]] {fortran_attrs = #fir.var_attrs<intent_in>, uniq_name = "_QFf01Ev"} : (!fir.ref<ui32>, !fir.dscope) -> !fir.ref<ui32> +!CHECK: %[[VAL_3:.*]] = fir.declare %[[ARG0]] dummy_scope %[[VAL_0]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<intent_in>, uniq_name = "_QFf01Eu"} : (!fir.ref<ui32>, !fir.dscope) -> !fir.ref<ui32> +!CHECK: %[[VAL_4:.*]] = fir.declare %[[ARG1]] dummy_scope %[[VAL_0]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<intent_in>, uniq_name = "_QFf01Ev"} : (!fir.ref<ui32>, !fir.dscope) -> !fir.ref<ui32> !CHECK: %[[VAL_5:.*]] = fir.load %[[VAL_3]] : !fir.ref<ui32> !CHECK: %[[VAL_6:.*]] = fir.load %[[VAL_4]] : !fir.ref<ui32> !CHECK: %[[VAL_7:.*]] = fir.convert %[[VAL_5]] : (ui32) -> i32 @@ -35,8 +35,8 @@ end !CHECK: %[[VAL_0:.*]] = fir.dummy_scope : !fir.dscope !CHECK: %[[VAL_1:.*]] = fir.alloca ui32 {bindc_name = "f02", uniq_name = "_QFf02Ef02"} !CHECK: %[[VAL_2:.*]] = fir.declare %[[VAL_1]] {uniq_name = "_QFf02Ef02"} : (!fir.ref<ui32>) -> !fir.ref<ui32> -!CHECK: %[[VAL_3:.*]] = fir.declare %[[ARG0]] dummy_scope %[[VAL_0]] {fortran_attrs = #fir.var_attrs<intent_in>, uniq_name = "_QFf02Eu"} : (!fir.ref<ui32>, !fir.dscope) -> !fir.ref<ui32> -!CHECK: %[[VAL_4:.*]] = fir.declare %[[ARG1]] dummy_scope %[[VAL_0]] {fortran_attrs = #fir.var_attrs<intent_in>, uniq_name = "_QFf02Ev"} : (!fir.ref<ui32>, !fir.dscope) -> !fir.ref<ui32> +!CHECK: %[[VAL_3:.*]] = fir.declare %[[ARG0]] dummy_scope %[[VAL_0]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<intent_in>, uniq_name = "_QFf02Eu"} : (!fir.ref<ui32>, !fir.dscope) -> !fir.ref<ui32> +!CHECK: %[[VAL_4:.*]] = fir.declare %[[ARG1]] dummy_scope %[[VAL_0]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<intent_in>, uniq_name = "_QFf02Ev"} : (!fir.ref<ui32>, !fir.dscope) -> !fir.ref<ui32> !CHECK: %[[VAL_5:.*]] = fir.load %[[VAL_3]] : !fir.ref<ui32> !CHECK: %[[VAL_6:.*]] = fir.load %[[VAL_4]] : !fir.ref<ui32> !CHECK: %[[VAL_7:.*]] = fir.convert %[[VAL_5]] : (ui32) -> i64 diff --git a/flang/test/Lower/variable.f90 b/flang/test/Lower/variable.f90 index 76d4a26..52cdb96 100644 --- a/flang/test/Lower/variable.f90 +++ b/flang/test/Lower/variable.f90 @@ -4,7 +4,7 @@ subroutine s ! CHECK-DAG: fir.alloca !fir.box<!fir.heap<i32>> {{{.*}}uniq_name = "{{.*}}Eally"} integer, allocatable :: ally - ! CHECK-DAG: fir.alloca !fir.box<!fir.ptr<i32>> {{{.*}}uniq_name = "{{.*}}Epointy"} + ! CHECK-DAG: fir.alloca !fir.box<!fir.ptr<i32>> {{{.*}}uniq_name = "{{.*}}Epointy"} integer, pointer :: pointy ! CHECK-DAG: fir.alloca i32 {{{.*}}fir.target{{.*}}uniq_name = "{{.*}}Ebullseye"} integer, target :: bullseye diff --git a/flang/test/Lower/vectorlength.f90 b/flang/test/Lower/vectorlength.f90 new file mode 100644 index 0000000..95753c3 --- /dev/null +++ b/flang/test/Lower/vectorlength.f90 @@ -0,0 +1,67 @@ +! RUN: %flang_fc1 -emit-hlfir -o - %s | FileCheck %s + +! CHECK: #[[FIXED:.*]] = #llvm.loop_vectorize<disable = false, scalableEnable = false> +! CHECK: #[[SCALABLE:.*]] = #llvm.loop_vectorize<disable = false, scalableEnable = true> +! CHECK: #[[WIDTH2:.*]] = #llvm.loop_vectorize<disable = false, width = 2 : i64> +! CHECK: #[[FIXED_WIDTH2:.*]] = #llvm.loop_vectorize<disable = false, scalableEnable = false, width = 2 : i64> +! CHECK: #[[SCALABLE_WIDTH2:.*]] = #llvm.loop_vectorize<disable = false, scalableEnable = true, width = 2 : i64> +! CHECK: #[[FIXED_TAG:.*]] = #llvm.loop_annotation<vectorize = #[[FIXED]]> +! CHECK: #[[SCALABLE_TAG:.*]] = #llvm.loop_annotation<vectorize = #[[SCALABLE]]> +! CHECK: #[[WIDTH2_TAG:.*]] = #llvm.loop_annotation<vectorize = #[[WIDTH2]]> +! CHECK: #[[FIXED_WIDTH2_TAG:.*]] = #llvm.loop_annotation<vectorize = #[[FIXED_WIDTH2]]> +! CHECK: #[[SCALABLE_WIDTH2_TAG:.*]] = #llvm.loop_annotation<vectorize = #[[SCALABLE_WIDTH2]]> + +! CHECK-LABEL: func.func @_QPfixed( +subroutine fixed(a, b, m) + integer :: i, m, a(m), b(m) + + !dir$ vector vectorlength(fixed) + ! CHECK: fir.do_loop {{.*}} attributes {loopAnnotation = #[[FIXED_TAG]]} + do i = 1, m + b(i) = a(i) + 1 + end do +end subroutine + +! CHECK-LABEL: func.func @_QPscalable( +subroutine scalable(a, b, m) + integer :: i, m, a(m), b(m) + + !dir$ vector vectorlength(scalable) + ! CHECK: fir.do_loop {{.*}} attributes {loopAnnotation = #[[SCALABLE_TAG]]} + do i = 1, m + b(i) = a(i) + 1 + end do +end subroutine + +! CHECK-LABEL: func.func @_QPlen2( +subroutine len2(a, b, m) + integer :: i, m, a(m), b(m) + + !dir$ vector vectorlength(2) + ! CHECK: fir.do_loop {{.*}} attributes {loopAnnotation = #[[WIDTH2_TAG]]} + do i = 1, m + b(i) = a(i) + 1 + end do +end subroutine + +! CHECK-LABEL: func.func @_QPlen2fixed( +subroutine len2fixed(a, b, m) + integer :: i, m, a(m), b(m) + + !dir$ vector vectorlength(2,fixed) + ! CHECK: fir.do_loop {{.*}} attributes {loopAnnotation = #[[FIXED_WIDTH2_TAG]]} + do i = 1, m + b(i) = a(i) + 1 + end do +end subroutine + +! CHECK-LABEL: func.func @_QPlen2scalable( +subroutine len2scalable(a, b, m) + integer :: i, m, a(m), b(m) + + !dir$ vector vectorlength(2,scalable) + ! CHECK: fir.do_loop {{.*}} attributes {loopAnnotation = #[[SCALABLE_WIDTH2_TAG]]} + do i = 1, m + b(i) = a(i) + 1 + end do +end subroutine diff --git a/flang/test/Lower/volatile-allocatable.f90 b/flang/test/Lower/volatile-allocatable.f90 index c33d368..3147698 100644 --- a/flang/test/Lower/volatile-allocatable.f90 +++ b/flang/test/Lower/volatile-allocatable.f90 @@ -42,7 +42,7 @@ subroutine test_scalar_volatile() ! Deferred-length characters allocate(character(20) :: c1) c1 = "volatile character" - + ! Allocation with components allocate(v3) deallocate(v1, v2, v3, c1) @@ -53,24 +53,24 @@ subroutine test_volatile_asynchronous() use derived_types class(base_type), allocatable, volatile, asynchronous :: v1(:) integer, allocatable, volatile, asynchronous :: i1(:) - + allocate(v1(4)) allocate(i1(4), source=[1, 2, 3, 4]) - + deallocate(v1, i1) end subroutine subroutine test_select_base_type_volatile() use derived_types class(base_type), allocatable, volatile :: v(:) - + allocate(v(2)) - + select type(v) class is (base_type) v(1)%i = 100 end select - + deallocate(v) end subroutine @@ -79,12 +79,12 @@ subroutine test_mold_allocation() use derived_types type(comp_type) :: template type(comp_type), allocatable, volatile :: v(:) - + template%str = "mold test" template%arr = [5, 6] - + allocate(v(3), mold=template) - + deallocate(v) end subroutine @@ -93,28 +93,28 @@ subroutine test_unlimited_polymorphic() use derived_types class(*), allocatable, volatile :: up class(*), allocatable, volatile :: upa(:) - + ! Scalar allocation allocate(integer :: up) select type(up) type is (integer) up = 123 end select - + ! Array allocation with source allocate(character(10) :: up) select type(up) type is (character(*)) up = "class(*)" end select - + ! Array allocation allocate(real :: upa(3)) select type(upa) type is (real) upa = [1.1, 2.2, 3.3] end select - + deallocate(up, upa) end subroutine diff --git a/flang/test/Lower/volatile-derived-type.f90 b/flang/test/Lower/volatile-derived-type.f90 index 963e4cf..9691df2 100644 --- a/flang/test/Lower/volatile-derived-type.f90 +++ b/flang/test/Lower/volatile-derived-type.f90 @@ -43,6 +43,6 @@ end ! CHECK-LABEL: func.func private @_QFPtest( ! CHECK-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.box<!fir.array<?xi32>> {fir.asynchronous, fir.bindc_name = "v"}) attributes {fir.host_symbol = @_QQmain, llvm.linkage = #llvm.linkage<internal>} { ! CHECK: %[[VAL_1:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] {fortran_attrs = #fir.var_attrs<asynchronous>, uniq_name = "_QFFtestEv"} : (!fir.box<!fir.array<?xi32>>, !fir.dscope) -> (!fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<asynchronous>, uniq_name = "_QFFtestEv"} : (!fir.box<!fir.array<?xi32>>, !fir.dscope) -> (!fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>>) ! CHECK: return ! CHECK: } diff --git a/flang/test/Lower/volatile-openmp.f90 b/flang/test/Lower/volatile-openmp.f90 index d1a844e..fb6cee4 100644 --- a/flang/test/Lower/volatile-openmp.f90 +++ b/flang/test/Lower/volatile-openmp.f90 @@ -36,7 +36,7 @@ end ! CHECK: %[[VAL_24:.*]] = fir.coordinate_of %[[VAL_13]]#0, array : (!fir.ref<!fir.type<_QFTt{array:!fir.box<!fir.ptr<!fir.array<?xi32>>>}>, volatile>) -> !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>> ! CHECK: %[[VAL_25:.*]] = fir.box_offset %[[VAL_24]] base_addr : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>) -> !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>> ! CHECK: %[[VAL_26:.*]] = omp.map.info var_ptr(%[[VAL_24]] : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>, i32) map_clauses(to) capture(ByRef) var_ptr_ptr(%[[VAL_25]] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) bounds(%[[VAL_23]]) -> !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>> {name = ""} -! CHECK: %[[VAL_27:.*]] = omp.map.info var_ptr(%[[VAL_24]] : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>, !fir.box<!fir.ptr<!fir.array<?xi32>>>) map_clauses(to) capture(ByRef) -> !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>> {name = "container%[[VAL_28:.*]]"} +! CHECK: %[[VAL_27:.*]] = omp.map.info var_ptr(%[[VAL_24]] : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>, !fir.box<!fir.ptr<!fir.array<?xi32>>>) map_clauses(always, to) capture(ByRef) -> !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>> {name = "container%[[VAL_28:.*]]"} ! CHECK: %[[VAL_29:.*]] = omp.map.info var_ptr(%[[VAL_13]]#1 : !fir.ref<!fir.type<_QFTt{array:!fir.box<!fir.ptr<!fir.array<?xi32>>>}>, volatile>, !fir.type<_QFTt{array:!fir.box<!fir.ptr<!fir.array<?xi32>>>}>) map_clauses(to) capture(ByRef) members(%[[VAL_27]], %[[VAL_26]] : [0], [0, 0] : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>, !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) -> !fir.ref<!fir.type<_QFTt{array:!fir.box<!fir.ptr<!fir.array<?xi32>>>}>, volatile> {name = "container", partial_map = true} ! CHECK: omp.target_enter_data map_entries(%[[VAL_29]], %[[VAL_27]], %[[VAL_26]] : !fir.ref<!fir.type<_QFTt{array:!fir.box<!fir.ptr<!fir.array<?xi32>>>}>, volatile>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>, !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) ! CHECK: %[[VAL_30:.*]] = fir.load %[[VAL_10]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, volatile> @@ -47,7 +47,7 @@ end ! CHECK: %[[VAL_35:.*]] = omp.map.bounds lower_bound(%[[VAL_0]] : index) upper_bound(%[[VAL_34]] : index) extent(%[[VAL_33]]#1 : index) stride(%[[VAL_33]]#2 : index) start_idx(%[[VAL_32]]#0 : index) {stride_in_bytes = true} ! CHECK: %[[VAL_36:.*]] = fir.box_offset %[[VAL_10]]#1 base_addr : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, volatile>) -> !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>> ! CHECK: %[[VAL_37:.*]] = omp.map.info var_ptr(%[[VAL_10]]#1 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, volatile>, i32) map_clauses(to) capture(ByRef) var_ptr_ptr(%[[VAL_36]] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) bounds(%[[VAL_35]]) -> !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>> {name = ""} -! CHECK: %[[VAL_38:.*]] = omp.map.info var_ptr(%[[VAL_10]]#1 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, volatile>, !fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>) map_clauses(to) capture(ByRef) members(%[[VAL_37]] : [0] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) -> !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, volatile> {name = "array1"} +! CHECK: %[[VAL_38:.*]] = omp.map.info var_ptr(%[[VAL_10]]#1 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, volatile>, !fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>) map_clauses(always, to) capture(ByRef) members(%[[VAL_37]] : [0] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) -> !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, volatile> {name = "array1"} ! CHECK: omp.target_enter_data map_entries(%[[VAL_38]], %[[VAL_37]] : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, volatile>, !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) ! CHECK: return ! CHECK: } diff --git a/flang/test/Lower/volatile-openmp1.f90 b/flang/test/Lower/volatile-openmp1.f90 index 07d81a1..74ab385 100644 --- a/flang/test/Lower/volatile-openmp1.f90 +++ b/flang/test/Lower/volatile-openmp1.f90 @@ -5,7 +5,7 @@ integer,volatile::a integer::n,i a=0 n=1000 -!$omp parallel +!$omp parallel !$omp do reduction(+:a) do i=1,n a=a+1 diff --git a/flang/test/Lower/volatile-string.f90 b/flang/test/Lower/volatile-string.f90 index 54f22af..f3e291d 100644 --- a/flang/test/Lower/volatile-string.f90 +++ b/flang/test/Lower/volatile-string.f90 @@ -76,7 +76,7 @@ end program ! CHECK: %[[VAL_3:.*]]:2 = fir.unboxchar %[[VAL_0]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index) ! CHECK: %[[VAL_4:.*]] = fir.convert %[[VAL_3]]#0 : (!fir.ref<!fir.char<1,?>>) -> !fir.ref<!fir.char<1,3>> ! CHECK: %[[VAL_5:.*]] = fir.volatile_cast %[[VAL_4]] : (!fir.ref<!fir.char<1,3>>) -> !fir.ref<!fir.char<1,3>, volatile> -! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_5]] typeparams %[[VAL_1]] dummy_scope %[[VAL_2]] {fortran_attrs = #fir.var_attrs<intent_inout, volatile>, uniq_name = "_QFFassign_same_lengthEx"} : (!fir.ref<!fir.char<1,3>, volatile>, index, !fir.dscope) -> (!fir.ref<!fir.char<1,3>, volatile>, !fir.ref<!fir.char<1,3>, volatile>) +! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_5]] typeparams %[[VAL_1]] dummy_scope %[[VAL_2]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<intent_inout, volatile>, uniq_name = "_QFFassign_same_lengthEx"} : (!fir.ref<!fir.char<1,3>, volatile>, index, !fir.dscope) -> (!fir.ref<!fir.char<1,3>, volatile>, !fir.ref<!fir.char<1,3>, volatile>) ! CHECK: %[[VAL_7:.*]] = fir.address_of(@_QQclX626172) : !fir.ref<!fir.char<1,3>> ! CHECK: %[[VAL_8:.*]]:2 = hlfir.declare %[[VAL_7]] typeparams %[[VAL_1]] {fortran_attrs = #fir.var_attrs<parameter>, uniq_name = "_QQclX626172"} : (!fir.ref<!fir.char<1,3>>, index) -> (!fir.ref<!fir.char<1,3>>, !fir.ref<!fir.char<1,3>>) ! CHECK: hlfir.assign %[[VAL_8]]#0 to %[[VAL_6]]#0 : !fir.ref<!fir.char<1,3>>, !fir.ref<!fir.char<1,3>, volatile> @@ -91,7 +91,7 @@ end program ! CHECK: %[[VAL_4:.*]]:2 = fir.unboxchar %[[VAL_0]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index) ! CHECK: %[[VAL_5:.*]] = fir.convert %[[VAL_4]]#0 : (!fir.ref<!fir.char<1,?>>) -> !fir.ref<!fir.char<1,3>> ! CHECK: %[[VAL_6:.*]] = fir.volatile_cast %[[VAL_5]] : (!fir.ref<!fir.char<1,3>>) -> !fir.ref<!fir.char<1,3>, volatile> -! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_6]] typeparams %[[VAL_2]] dummy_scope %[[VAL_3]] {fortran_attrs = #fir.var_attrs<intent_inout, volatile>, uniq_name = "_QFFassign_different_lengthEstring"} : (!fir.ref<!fir.char<1,3>, volatile>, index, !fir.dscope) -> (!fir.ref<!fir.char<1,3>, volatile>, !fir.ref<!fir.char<1,3>, volatile>) +! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_6]] typeparams %[[VAL_2]] dummy_scope %[[VAL_3]] arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<intent_inout, volatile>, uniq_name = "_QFFassign_different_lengthEstring"} : (!fir.ref<!fir.char<1,3>, volatile>, index, !fir.dscope) -> (!fir.ref<!fir.char<1,3>, volatile>, !fir.ref<!fir.char<1,3>, volatile>) ! CHECK: %[[VAL_8:.*]] = fir.address_of(@_QQclX626F) : !fir.ref<!fir.char<1,2>> ! CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[VAL_8]] typeparams %[[VAL_1]] {fortran_attrs = #fir.var_attrs<parameter>, uniq_name = "_QQclX626F"} : (!fir.ref<!fir.char<1,2>>, index) -> (!fir.ref<!fir.char<1,2>>, !fir.ref<!fir.char<1,2>>) ! CHECK: hlfir.assign %[[VAL_9]]#0 to %[[VAL_7]]#0 : !fir.ref<!fir.char<1,2>>, !fir.ref<!fir.char<1,3>, volatile> diff --git a/flang/test/Lower/volatile3.f90 b/flang/test/Lower/volatile3.f90 index a32f29d..d5eaa8e 100644 --- a/flang/test/Lower/volatile3.f90 +++ b/flang/test/Lower/volatile3.f90 @@ -69,199 +69,199 @@ contains end subroutine end program - -! CHECK-LABEL: func.func @_QQmain() attributes {fir.bindc_name = "P"} { -! CHECK: %[[VAL_0:.*]] = arith.constant 1 : index -! CHECK: %[[VAL_1:.*]] = arith.constant 0 : index -! CHECK: %[[VAL_2:.*]] = arith.constant 10 : index -! CHECK: %[[VAL_3:.*]] = fir.alloca !fir.box<!fir.ptr<i32>, volatile> -! CHECK: %[[VAL_4:.*]] = fir.alloca !fir.box<!fir.ptr<!fir.array<?xi32>>, volatile> -! CHECK: %[[VAL_5:.*]] = fir.address_of(@_QFEnonvolatile_array) : !fir.ref<!fir.array<10xi32>> -! CHECK: %[[VAL_6:.*]] = fir.shape %[[VAL_2]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_5]](%[[VAL_6]]) {uniq_name = "_QFEnonvolatile_array"} : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>) -! CHECK: %[[VAL_8:.*]] = fir.address_of(@_QFEnonvolatile_array_pointer) : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>> -! CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[VAL_8]] {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFEnonvolatile_array_pointer"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>) -! CHECK: %[[VAL_10:.*]] = fir.address_of(@_QFEnonvolatile_array_target) : !fir.ref<!fir.array<10xi32>> -! CHECK: %[[VAL_11:.*]]:2 = hlfir.declare %[[VAL_10]](%[[VAL_6]]) {fortran_attrs = #fir.var_attrs<target>, uniq_name = "_QFEnonvolatile_array_target"} : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>) -! CHECK: %[[VAL_12:.*]] = fir.address_of(@_QFEnonvolatile_integer_target) : !fir.ref<i32> -! CHECK: %[[VAL_13:.*]]:2 = hlfir.declare %[[VAL_12]] {fortran_attrs = #fir.var_attrs<target>, uniq_name = "_QFEnonvolatile_integer_target"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) -! CHECK: %[[VAL_14:.*]] = fir.address_of(@_QFEvolatile_array) : !fir.ref<!fir.array<10xi32>> -! CHECK: %[[VAL_15:.*]] = fir.volatile_cast %[[VAL_14]] : (!fir.ref<!fir.array<10xi32>>) -> !fir.ref<!fir.array<10xi32>, volatile> -! CHECK: %[[VAL_16:.*]]:2 = hlfir.declare %[[VAL_15]](%[[VAL_6]]) {fortran_attrs = #fir.var_attrs<volatile>, uniq_name = "_QFEvolatile_array"} : (!fir.ref<!fir.array<10xi32>, volatile>, !fir.shape<1>) -> (!fir.ref<!fir.array<10xi32>, volatile>, !fir.ref<!fir.array<10xi32>, volatile>) -! CHECK: %[[VAL_17:.*]] = fir.address_of(@_QFEvolatile_array_2d) : !fir.ref<!fir.array<10x10xi32>> -! CHECK: %[[VAL_18:.*]] = fir.shape %[[VAL_2]], %[[VAL_2]] : (index, index) -> !fir.shape<2> -! CHECK: %[[VAL_19:.*]] = fir.volatile_cast %[[VAL_17]] : (!fir.ref<!fir.array<10x10xi32>>) -> !fir.ref<!fir.array<10x10xi32>, volatile> -! CHECK: %[[VAL_20:.*]]:2 = hlfir.declare %[[VAL_19]](%[[VAL_18]]) {fortran_attrs = #fir.var_attrs<volatile>, uniq_name = "_QFEvolatile_array_2d"} : (!fir.ref<!fir.array<10x10xi32>, volatile>, !fir.shape<2>) -> (!fir.ref<!fir.array<10x10xi32>, volatile>, !fir.ref<!fir.array<10x10xi32>, volatile>) -! CHECK: %[[VAL_21:.*]] = fir.address_of(@_QFEvolatile_array_pointer) : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>> -! CHECK: %[[VAL_22:.*]] = fir.volatile_cast %[[VAL_21]] : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>) -> !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, volatile> -! CHECK: %[[VAL_23:.*]]:2 = hlfir.declare %[[VAL_22]] {fortran_attrs = #fir.var_attrs<pointer, volatile>, uniq_name = "_QFEvolatile_array_pointer"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, volatile>) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, volatile>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, volatile>) -! CHECK: %[[VAL_24:.*]] = fir.address_of(@_QFEvolatile_array_target) : !fir.ref<!fir.array<10xi32>> -! CHECK: %[[VAL_25:.*]] = fir.volatile_cast %[[VAL_24]] : (!fir.ref<!fir.array<10xi32>>) -> !fir.ref<!fir.array<10xi32>, volatile> -! CHECK: %[[VAL_26:.*]]:2 = hlfir.declare %[[VAL_25]](%[[VAL_6]]) {fortran_attrs = #fir.var_attrs<target, volatile>, uniq_name = "_QFEvolatile_array_target"} : (!fir.ref<!fir.array<10xi32>, volatile>, !fir.shape<1>) -> (!fir.ref<!fir.array<10xi32>, volatile>, !fir.ref<!fir.array<10xi32>, volatile>) -! CHECK: %[[VAL_27:.*]] = fir.alloca i32 {bindc_name = "volatile_integer", uniq_name = "_QFEvolatile_integer"} -! CHECK: %[[VAL_28:.*]] = fir.volatile_cast %[[VAL_27]] : (!fir.ref<i32>) -> !fir.ref<i32, volatile> -! CHECK: %[[VAL_29:.*]]:2 = hlfir.declare %[[VAL_28]] {fortran_attrs = #fir.var_attrs<volatile>, uniq_name = "_QFEvolatile_integer"} : (!fir.ref<i32, volatile>) -> (!fir.ref<i32, volatile>, !fir.ref<i32, volatile>) -! CHECK: %[[VAL_30:.*]] = fir.alloca !fir.box<!fir.ptr<i32>> {bindc_name = "volatile_integer_pointer", uniq_name = "_QFEvolatile_integer_pointer"} -! CHECK: %[[VAL_31:.*]] = fir.zero_bits !fir.ptr<i32> -! CHECK: %[[VAL_32:.*]] = fir.embox %[[VAL_31]] : (!fir.ptr<i32>) -> !fir.box<!fir.ptr<i32>> -! CHECK: fir.store %[[VAL_32]] to %[[VAL_30]] : !fir.ref<!fir.box<!fir.ptr<i32>>> -! CHECK: %[[VAL_33:.*]] = fir.volatile_cast %[[VAL_30]] : (!fir.ref<!fir.box<!fir.ptr<i32>>>) -> !fir.ref<!fir.box<!fir.ptr<i32>, volatile>, volatile> -! CHECK: %[[VAL_34:.*]]:2 = hlfir.declare %[[VAL_33]] {fortran_attrs = #fir.var_attrs<pointer, volatile>, uniq_name = "_QFEvolatile_integer_pointer"} : (!fir.ref<!fir.box<!fir.ptr<i32>, volatile>, volatile>) -> (!fir.ref<!fir.box<!fir.ptr<i32>, volatile>, volatile>, !fir.ref<!fir.box<!fir.ptr<i32>, volatile>, volatile>) -! CHECK: %[[VAL_35:.*]] = fir.address_of(@_QFEvolatile_integer_target) : !fir.ref<i32> -! CHECK: %[[VAL_36:.*]] = fir.volatile_cast %[[VAL_35]] : (!fir.ref<i32>) -> !fir.ref<i32, volatile> -! CHECK: %[[VAL_37:.*]]:2 = hlfir.declare %[[VAL_36]] {fortran_attrs = #fir.var_attrs<target, volatile>, uniq_name = "_QFEvolatile_integer_target"} : (!fir.ref<i32, volatile>) -> (!fir.ref<i32, volatile>, !fir.ref<i32, volatile>) -! CHECK: %[[VAL_38:.*]] = fir.embox %[[VAL_26]]#0(%[[VAL_6]]) : (!fir.ref<!fir.array<10xi32>, volatile>, !fir.shape<1>) -> !fir.box<!fir.ptr<!fir.array<?xi32>>, volatile> -! CHECK: fir.store %[[VAL_38]] to %[[VAL_23]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, volatile> -! CHECK: %[[VAL_39:.*]] = fir.embox %[[VAL_11]]#0(%[[VAL_6]]) : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>) -> !fir.box<!fir.ptr<!fir.array<?xi32>>> -! CHECK: %[[VAL_40:.*]] = fir.volatile_cast %[[VAL_39]] : (!fir.box<!fir.ptr<!fir.array<?xi32>>>) -> !fir.box<!fir.ptr<!fir.array<?xi32>>, volatile> -! CHECK: fir.store %[[VAL_40]] to %[[VAL_23]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, volatile> -! CHECK: %[[VAL_41:.*]] = fir.zero_bits !fir.ptr<!fir.array<?xi32>> -! CHECK: %[[VAL_42:.*]] = fir.shape %[[VAL_1]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_43:.*]] = fir.embox %[[VAL_41]](%[[VAL_42]]) : (!fir.ptr<!fir.array<?xi32>>, !fir.shape<1>) -> !fir.box<!fir.ptr<!fir.array<?xi32>>, volatile> -! CHECK: fir.store %[[VAL_43]] to %[[VAL_4]] : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>> -! CHECK: %[[VAL_44:.*]]:2 = hlfir.declare %[[VAL_4]] {uniq_name = ".tmp.intrinsic_result"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>>) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>>) -! CHECK: %[[VAL_45:.*]] = fir.load %[[VAL_44]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>> -! CHECK: %[[VAL_46:.*]]:3 = fir.box_dims %[[VAL_45]], %[[VAL_1]] : (!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, index) -> (index, index, index) -! CHECK: %[[VAL_47:.*]] = fir.shift %[[VAL_46]]#0 : (index) -> !fir.shift<1> -! CHECK: %[[VAL_48:.*]] = fir.rebox %[[VAL_45]](%[[VAL_47]]) : (!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, !fir.shift<1>) -> !fir.box<!fir.ptr<!fir.array<?xi32>>, volatile> -! CHECK: fir.store %[[VAL_48]] to %[[VAL_23]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, volatile> -! CHECK: %[[VAL_49:.*]] = fir.volatile_cast %[[VAL_38]] : (!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>) -> !fir.box<!fir.ptr<!fir.array<?xi32>>> -! CHECK: fir.store %[[VAL_49]] to %[[VAL_9]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>> -! CHECK: fir.store %[[VAL_39]] to %[[VAL_9]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>> -! CHECK: %[[VAL_50:.*]] = fir.embox %[[VAL_37]]#0 : (!fir.ref<i32, volatile>) -> !fir.box<!fir.ptr<i32>, volatile> -! CHECK: fir.store %[[VAL_50]] to %[[VAL_34]]#0 : !fir.ref<!fir.box<!fir.ptr<i32>, volatile>, volatile> -! CHECK: %[[VAL_51:.*]] = fir.embox %[[VAL_31]] : (!fir.ptr<i32>) -> !fir.box<!fir.ptr<i32>, volatile> -! CHECK: fir.store %[[VAL_51]] to %[[VAL_3]] : !fir.ref<!fir.box<!fir.ptr<i32>, volatile>> -! CHECK: %[[VAL_52:.*]]:2 = hlfir.declare %[[VAL_3]] {uniq_name = ".tmp.intrinsic_result"} : (!fir.ref<!fir.box<!fir.ptr<i32>, volatile>>) -> (!fir.ref<!fir.box<!fir.ptr<i32>, volatile>>, !fir.ref<!fir.box<!fir.ptr<i32>, volatile>>) -! CHECK: %[[VAL_53:.*]] = fir.load %[[VAL_52]]#0 : !fir.ref<!fir.box<!fir.ptr<i32>, volatile>> -! CHECK: %[[VAL_54:.*]] = fir.box_addr %[[VAL_53]] : (!fir.box<!fir.ptr<i32>, volatile>) -> !fir.ptr<i32> -! CHECK: %[[VAL_55:.*]] = fir.embox %[[VAL_54]] : (!fir.ptr<i32>) -> !fir.box<!fir.ptr<i32>> -! CHECK: %[[VAL_56:.*]] = fir.volatile_cast %[[VAL_55]] : (!fir.box<!fir.ptr<i32>>) -> !fir.box<!fir.ptr<i32>, volatile> -! CHECK: fir.store %[[VAL_56]] to %[[VAL_34]]#0 : !fir.ref<!fir.box<!fir.ptr<i32>, volatile>, volatile> -! CHECK: %[[VAL_57:.*]] = fir.volatile_cast %[[VAL_16]]#0 : (!fir.ref<!fir.array<10xi32>, volatile>) -> !fir.ref<!fir.array<10xi32>> -! CHECK: fir.call @_QFPsub_nonvolatile_array(%[[VAL_57]]) fastmath<contract> : (!fir.ref<!fir.array<10xi32>>) -> () -! CHECK: %[[VAL_58:.*]] = fir.embox %[[VAL_16]]#0(%[[VAL_6]]) : (!fir.ref<!fir.array<10xi32>, volatile>, !fir.shape<1>) -> !fir.box<!fir.array<10xi32>, volatile> -! CHECK: %[[VAL_59:.*]] = fir.volatile_cast %[[VAL_58]] : (!fir.box<!fir.array<10xi32>, volatile>) -> !fir.box<!fir.array<10xi32>> -! CHECK: %[[VAL_60:.*]] = fir.convert %[[VAL_59]] : (!fir.box<!fir.array<10xi32>>) -> !fir.box<!fir.array<?xi32>> -! CHECK: fir.call @_QFPsub_volatile_array_assumed_shape(%[[VAL_60]]) fastmath<contract> : (!fir.box<!fir.array<?xi32>>) -> () -! CHECK: fir.call @_QFPsub_volatile_array(%[[VAL_57]]) fastmath<contract> : (!fir.ref<!fir.array<10xi32>>) -> () -! CHECK: %[[VAL_61:.*]] = fir.embox %[[VAL_7]]#0(%[[VAL_6]]) : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>) -> !fir.box<!fir.array<10xi32>> -! CHECK: %[[VAL_62:.*]] = fir.convert %[[VAL_61]] : (!fir.box<!fir.array<10xi32>>) -> !fir.box<!fir.array<?xi32>> -! CHECK: fir.call @_QFPsub_volatile_array_assumed_shape(%[[VAL_62]]) fastmath<contract> : (!fir.box<!fir.array<?xi32>>) -> () -! CHECK: fir.call @_QFPsub_volatile_array(%[[VAL_7]]#0) fastmath<contract> : (!fir.ref<!fir.array<10xi32>>) -> () -! CHECK: %[[VAL_63:.*]] = fir.convert %[[VAL_23]]#0 : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, volatile>) -> !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>, volatile> -! CHECK: fir.call @_QFPsub_volatile_array_pointer(%[[VAL_63]]) fastmath<contract> : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>, volatile>) -> () -! CHECK: %[[VAL_64:.*]] = fir.volatile_cast %[[VAL_9]]#0 : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>) -> !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>, volatile> -! CHECK: fir.call @_QFPsub_volatile_array_pointer(%[[VAL_64]]) fastmath<contract> : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>, volatile>) -> () -! CHECK: %[[VAL_65:.*]] = hlfir.designate %[[VAL_16]]#0 (%[[VAL_0]]:%[[VAL_2]]:%[[VAL_0]]) shape %[[VAL_6]] : (!fir.ref<!fir.array<10xi32>, volatile>, index, index, index, !fir.shape<1>) -> !fir.ref<!fir.array<10xi32>, volatile> -! CHECK: %[[VAL_66:.*]] = fir.embox %[[VAL_65]](%[[VAL_6]]) : (!fir.ref<!fir.array<10xi32>, volatile>, !fir.shape<1>) -> !fir.box<!fir.array<10xi32>, volatile> -! CHECK: %[[VAL_67:.*]] = fir.volatile_cast %[[VAL_66]] : (!fir.box<!fir.array<10xi32>, volatile>) -> !fir.box<!fir.array<10xi32>> -! CHECK: %[[VAL_68:.*]] = fir.convert %[[VAL_67]] : (!fir.box<!fir.array<10xi32>>) -> !fir.box<!fir.array<?xi32>> -! CHECK: fir.call @_QFPsub_volatile_array_assumed_shape(%[[VAL_68]]) fastmath<contract> : (!fir.box<!fir.array<?xi32>>) -> () -! CHECK: %[[VAL_69:.*]] = hlfir.designate %[[VAL_20]]#0 (%[[VAL_0]]:%[[VAL_2]]:%[[VAL_0]], %[[VAL_0]]:%[[VAL_2]]:%[[VAL_0]]) shape %[[VAL_18]] : (!fir.ref<!fir.array<10x10xi32>, volatile>, index, index, index, index, index, index, !fir.shape<2>) -> !fir.box<!fir.array<10x10xi32>, volatile> -! CHECK: %[[VAL_70:.*]] = fir.volatile_cast %[[VAL_69]] : (!fir.box<!fir.array<10x10xi32>, volatile>) -> !fir.box<!fir.array<10x10xi32>> -! CHECK: %[[VAL_71:.*]] = fir.convert %[[VAL_70]] : (!fir.box<!fir.array<10x10xi32>>) -> !fir.box<!fir.array<?x?xi32>> -! CHECK: fir.call @_QFPsub_volatile_array_assumed_shape_2d(%[[VAL_71]]) fastmath<contract> : (!fir.box<!fir.array<?x?xi32>>) -> () -! CHECK: %[[VAL_72:.*]] = fir.convert %[[VAL_59]] : (!fir.box<!fir.array<10xi32>>) -> !fir.box<!fir.array<*:i32>> -! CHECK: fir.call @_QFPsub_select_rank(%[[VAL_72]]) fastmath<contract> : (!fir.box<!fir.array<*:i32>>) -> () -! CHECK: %[[VAL_73:.*]] = fir.embox %[[VAL_20]]#0(%[[VAL_18]]) : (!fir.ref<!fir.array<10x10xi32>, volatile>, !fir.shape<2>) -> !fir.box<!fir.array<10x10xi32>, volatile> -! CHECK: %[[VAL_74:.*]] = fir.volatile_cast %[[VAL_73]] : (!fir.box<!fir.array<10x10xi32>, volatile>) -> !fir.box<!fir.array<10x10xi32>> -! CHECK: %[[VAL_75:.*]] = fir.convert %[[VAL_74]] : (!fir.box<!fir.array<10x10xi32>>) -> !fir.box<!fir.array<*:i32>> -! CHECK: fir.call @_QFPsub_select_rank(%[[VAL_75]]) fastmath<contract> : (!fir.box<!fir.array<*:i32>>) -> () +! CHECK-LABEL: func.func @_QQmain() {{.*}} { +! CHECK: %[[CONSTANT_0:.*]] = arith.constant 1 : index +! CHECK: %[[CONSTANT_1:.*]] = arith.constant 0 : index +! CHECK: %[[CONSTANT_2:.*]] = arith.constant 10 : index +! CHECK: %[[ALLOCA_0:.*]] = fir.alloca !fir.box<!fir.ptr<i32>, volatile> +! CHECK: %[[ALLOCA_1:.*]] = fir.alloca !fir.box<!fir.ptr<!fir.array<?xi32>>, volatile> +! CHECK: %[[DUMMY_SCOPE_0:.*]] = fir.dummy_scope : !fir.dscope +! CHECK: %[[ADDRESS_OF_0:.*]] = fir.address_of(@_QFEnonvolatile_array) : !fir.ref<!fir.array<10xi32>> +! CHECK: %[[SHAPE_0:.*]] = fir.shape %[[CONSTANT_2]] : (index) -> !fir.shape<1> +! CHECK: %[[DECLARE_0:.*]]:2 = hlfir.declare %[[ADDRESS_OF_0]](%[[SHAPE_0]]) {uniq_name = "_QFEnonvolatile_array"} : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>) +! CHECK: %[[ADDRESS_OF_1:.*]] = fir.address_of(@_QFEnonvolatile_array_pointer) : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>> +! CHECK: %[[DECLARE_1:.*]]:2 = hlfir.declare %[[ADDRESS_OF_1]] {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFEnonvolatile_array_pointer"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>) +! CHECK: %[[ADDRESS_OF_2:.*]] = fir.address_of(@_QFEnonvolatile_array_target) : !fir.ref<!fir.array<10xi32>> +! CHECK: %[[DECLARE_2:.*]]:2 = hlfir.declare %[[ADDRESS_OF_2]](%[[SHAPE_0]]) {fortran_attrs = #fir.var_attrs<target>, uniq_name = "_QFEnonvolatile_array_target"} : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>) +! CHECK: %[[ADDRESS_OF_3:.*]] = fir.address_of(@_QFEnonvolatile_integer_target) : !fir.ref<i32> +! CHECK: %[[DECLARE_3:.*]]:2 = hlfir.declare %[[ADDRESS_OF_3]] {fortran_attrs = #fir.var_attrs<target>, uniq_name = "_QFEnonvolatile_integer_target"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[ADDRESS_OF_4:.*]] = fir.address_of(@_QFEvolatile_array) : !fir.ref<!fir.array<10xi32>> +! CHECK: %[[VOLATILE_CAST_0:.*]] = fir.volatile_cast %[[ADDRESS_OF_4]] : (!fir.ref<!fir.array<10xi32>>) -> !fir.ref<!fir.array<10xi32>, volatile> +! CHECK: %[[DECLARE_4:.*]]:2 = hlfir.declare %[[VOLATILE_CAST_0]](%[[SHAPE_0]]) {fortran_attrs = #fir.var_attrs<volatile>, uniq_name = "_QFEvolatile_array"} : (!fir.ref<!fir.array<10xi32>, volatile>, !fir.shape<1>) -> (!fir.ref<!fir.array<10xi32>, volatile>, !fir.ref<!fir.array<10xi32>, volatile>) +! CHECK: %[[ADDRESS_OF_5:.*]] = fir.address_of(@_QFEvolatile_array_2d) : !fir.ref<!fir.array<10x10xi32>> +! CHECK: %[[SHAPE_1:.*]] = fir.shape %[[CONSTANT_2]], %[[CONSTANT_2]] : (index, index) -> !fir.shape<2> +! CHECK: %[[VOLATILE_CAST_1:.*]] = fir.volatile_cast %[[ADDRESS_OF_5]] : (!fir.ref<!fir.array<10x10xi32>>) -> !fir.ref<!fir.array<10x10xi32>, volatile> +! CHECK: %[[DECLARE_5:.*]]:2 = hlfir.declare %[[VOLATILE_CAST_1]](%[[SHAPE_1]]) {fortran_attrs = #fir.var_attrs<volatile>, uniq_name = "_QFEvolatile_array_2d"} : (!fir.ref<!fir.array<10x10xi32>, volatile>, !fir.shape<2>) -> (!fir.ref<!fir.array<10x10xi32>, volatile>, !fir.ref<!fir.array<10x10xi32>, volatile>) +! CHECK: %[[ADDRESS_OF_6:.*]] = fir.address_of(@_QFEvolatile_array_pointer) : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>> +! CHECK: %[[VOLATILE_CAST_2:.*]] = fir.volatile_cast %[[ADDRESS_OF_6]] : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>) -> !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, volatile> +! CHECK: %[[DECLARE_6:.*]]:2 = hlfir.declare %[[VOLATILE_CAST_2]] {fortran_attrs = #fir.var_attrs<pointer, volatile>, uniq_name = "_QFEvolatile_array_pointer"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, volatile>) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, volatile>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, volatile>) +! CHECK: %[[ADDRESS_OF_7:.*]] = fir.address_of(@_QFEvolatile_array_target) : !fir.ref<!fir.array<10xi32>> +! CHECK: %[[VOLATILE_CAST_3:.*]] = fir.volatile_cast %[[ADDRESS_OF_7]] : (!fir.ref<!fir.array<10xi32>>) -> !fir.ref<!fir.array<10xi32>, volatile> +! CHECK: %[[DECLARE_7:.*]]:2 = hlfir.declare %[[VOLATILE_CAST_3]](%[[SHAPE_0]]) {fortran_attrs = #fir.var_attrs<target, volatile>, uniq_name = "_QFEvolatile_array_target"} : (!fir.ref<!fir.array<10xi32>, volatile>, !fir.shape<1>) -> (!fir.ref<!fir.array<10xi32>, volatile>, !fir.ref<!fir.array<10xi32>, volatile>) +! CHECK: %[[ALLOCA_2:.*]] = fir.alloca i32 {bindc_name = "volatile_integer", uniq_name = "_QFEvolatile_integer"} +! CHECK: %[[VOLATILE_CAST_4:.*]] = fir.volatile_cast %[[ALLOCA_2]] : (!fir.ref<i32>) -> !fir.ref<i32, volatile> +! CHECK: %[[DECLARE_8:.*]]:2 = hlfir.declare %[[VOLATILE_CAST_4]] {fortran_attrs = #fir.var_attrs<volatile>, uniq_name = "_QFEvolatile_integer"} : (!fir.ref<i32, volatile>) -> (!fir.ref<i32, volatile>, !fir.ref<i32, volatile>) +! CHECK: %[[ALLOCA_3:.*]] = fir.alloca !fir.box<!fir.ptr<i32>> {bindc_name = "volatile_integer_pointer", uniq_name = "_QFEvolatile_integer_pointer"} +! CHECK: %[[ZERO_BITS_0:.*]] = fir.zero_bits !fir.ptr<i32> +! CHECK: %[[EMBOX_0:.*]] = fir.embox %[[ZERO_BITS_0]] : (!fir.ptr<i32>) -> !fir.box<!fir.ptr<i32>> +! CHECK: fir.store %[[EMBOX_0]] to %[[ALLOCA_3]] : !fir.ref<!fir.box<!fir.ptr<i32>>> +! CHECK: %[[VOLATILE_CAST_5:.*]] = fir.volatile_cast %[[ALLOCA_3]] : (!fir.ref<!fir.box<!fir.ptr<i32>>>) -> !fir.ref<!fir.box<!fir.ptr<i32>, volatile>, volatile> +! CHECK: %[[DECLARE_9:.*]]:2 = hlfir.declare %[[VOLATILE_CAST_5]] {fortran_attrs = #fir.var_attrs<pointer, volatile>, uniq_name = "_QFEvolatile_integer_pointer"} : (!fir.ref<!fir.box<!fir.ptr<i32>, volatile>, volatile>) -> (!fir.ref<!fir.box<!fir.ptr<i32>, volatile>, volatile>, !fir.ref<!fir.box<!fir.ptr<i32>, volatile>, volatile>) +! CHECK: %[[ADDRESS_OF_8:.*]] = fir.address_of(@_QFEvolatile_integer_target) : !fir.ref<i32> +! CHECK: %[[VOLATILE_CAST_6:.*]] = fir.volatile_cast %[[ADDRESS_OF_8]] : (!fir.ref<i32>) -> !fir.ref<i32, volatile> +! CHECK: %[[DECLARE_10:.*]]:2 = hlfir.declare %[[VOLATILE_CAST_6]] {fortran_attrs = #fir.var_attrs<target, volatile>, uniq_name = "_QFEvolatile_integer_target"} : (!fir.ref<i32, volatile>) -> (!fir.ref<i32, volatile>, !fir.ref<i32, volatile>) +! CHECK: %[[CONVERT_0:.*]] = fir.convert %[[DECLARE_7]]#0 : (!fir.ref<!fir.array<10xi32>, volatile>) -> !fir.ref<!fir.array<?xi32>, volatile> +! CHECK: %[[EMBOX_1:.*]] = fir.embox %[[CONVERT_0]](%[[SHAPE_0]]) : (!fir.ref<!fir.array<?xi32>, volatile>, !fir.shape<1>) -> !fir.box<!fir.ptr<!fir.array<?xi32>>, volatile> +! CHECK: fir.store %[[EMBOX_1]] to %[[DECLARE_6]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, volatile> +! CHECK: %[[VOLATILE_CAST_7:.*]] = fir.volatile_cast %[[DECLARE_2]]#0 : (!fir.ref<!fir.array<10xi32>>) -> !fir.ref<!fir.array<10xi32>, volatile> +! CHECK: %[[CONVERT_1:.*]] = fir.convert %[[VOLATILE_CAST_7]] : (!fir.ref<!fir.array<10xi32>, volatile>) -> !fir.ref<!fir.array<?xi32>, volatile> +! CHECK: %[[EMBOX_2:.*]] = fir.embox %[[CONVERT_1]](%[[SHAPE_0]]) : (!fir.ref<!fir.array<?xi32>, volatile>, !fir.shape<1>) -> !fir.box<!fir.ptr<!fir.array<?xi32>>, volatile> +! CHECK: fir.store %[[EMBOX_2]] to %[[DECLARE_6]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, volatile> +! CHECK: %[[ZERO_BITS_1:.*]] = fir.zero_bits !fir.ptr<!fir.array<?xi32>> +! CHECK: %[[SHAPE_2:.*]] = fir.shape %[[CONSTANT_1]] : (index) -> !fir.shape<1> +! CHECK: %[[EMBOX_3:.*]] = fir.embox %[[ZERO_BITS_1]](%[[SHAPE_2]]) : (!fir.ptr<!fir.array<?xi32>>, !fir.shape<1>) -> !fir.box<!fir.ptr<!fir.array<?xi32>>, volatile> +! CHECK: fir.store %[[EMBOX_3]] to %[[ALLOCA_1]] : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>> +! CHECK: %[[DECLARE_11:.*]]:2 = hlfir.declare %[[ALLOCA_1]] {uniq_name = ".tmp.intrinsic_result"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>>) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>>) +! CHECK: %[[LOAD_0:.*]] = fir.load %[[DECLARE_11]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>> +! CHECK: fir.store %[[LOAD_0]] to %[[DECLARE_6]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, volatile> +! CHECK: %[[VOLATILE_CAST_8:.*]] = fir.volatile_cast %[[DECLARE_7]]#0 : (!fir.ref<!fir.array<10xi32>, volatile>) -> !fir.ref<!fir.array<10xi32>> +! CHECK: %[[CONVERT_2:.*]] = fir.convert %[[VOLATILE_CAST_8]] : (!fir.ref<!fir.array<10xi32>>) -> !fir.ref<!fir.array<?xi32>> +! CHECK: %[[EMBOX_4:.*]] = fir.embox %[[CONVERT_2]](%[[SHAPE_0]]) : (!fir.ref<!fir.array<?xi32>>, !fir.shape<1>) -> !fir.box<!fir.ptr<!fir.array<?xi32>>> +! CHECK: fir.store %[[EMBOX_4]] to %[[DECLARE_1]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>> +! CHECK: %[[CONVERT_3:.*]] = fir.convert %[[DECLARE_2]]#0 : (!fir.ref<!fir.array<10xi32>>) -> !fir.ref<!fir.array<?xi32>> +! CHECK: %[[EMBOX_5:.*]] = fir.embox %[[CONVERT_3]](%[[SHAPE_0]]) : (!fir.ref<!fir.array<?xi32>>, !fir.shape<1>) -> !fir.box<!fir.ptr<!fir.array<?xi32>>> +! CHECK: fir.store %[[EMBOX_5]] to %[[DECLARE_1]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>> +! CHECK: %[[EMBOX_6:.*]] = fir.embox %[[DECLARE_10]]#0 : (!fir.ref<i32, volatile>) -> !fir.box<!fir.ptr<i32>, volatile> +! CHECK: fir.store %[[EMBOX_6]] to %[[DECLARE_9]]#0 : !fir.ref<!fir.box<!fir.ptr<i32>, volatile>, volatile> +! CHECK: %[[EMBOX_7:.*]] = fir.embox %[[ZERO_BITS_0]] : (!fir.ptr<i32>) -> !fir.box<!fir.ptr<i32>, volatile> +! CHECK: fir.store %[[EMBOX_7]] to %[[ALLOCA_0]] : !fir.ref<!fir.box<!fir.ptr<i32>, volatile>> +! CHECK: %[[DECLARE_12:.*]]:2 = hlfir.declare %[[ALLOCA_0]] {uniq_name = ".tmp.intrinsic_result"} : (!fir.ref<!fir.box<!fir.ptr<i32>, volatile>>) -> (!fir.ref<!fir.box<!fir.ptr<i32>, volatile>>, !fir.ref<!fir.box<!fir.ptr<i32>, volatile>>) +! CHECK: %[[LOAD_1:.*]] = fir.load %[[DECLARE_12]]#0 : !fir.ref<!fir.box<!fir.ptr<i32>, volatile>> +! CHECK: fir.store %[[LOAD_1]] to %[[DECLARE_9]]#0 : !fir.ref<!fir.box<!fir.ptr<i32>, volatile>, volatile> +! CHECK: %[[VOLATILE_CAST_9:.*]] = fir.volatile_cast %[[DECLARE_4]]#0 : (!fir.ref<!fir.array<10xi32>, volatile>) -> !fir.ref<!fir.array<10xi32>> +! CHECK: fir.call @_QFPsub_nonvolatile_array(%[[VOLATILE_CAST_9]]) fastmath<contract> : (!fir.ref<!fir.array<10xi32>>) -> () +! CHECK: %[[EMBOX_8:.*]] = fir.embox %[[DECLARE_4]]#0(%[[SHAPE_0]]) : (!fir.ref<!fir.array<10xi32>, volatile>, !fir.shape<1>) -> !fir.box<!fir.array<10xi32>, volatile> +! CHECK: %[[VOLATILE_CAST_10:.*]] = fir.volatile_cast %[[EMBOX_8]] : (!fir.box<!fir.array<10xi32>, volatile>) -> !fir.box<!fir.array<10xi32>> +! CHECK: %[[CONVERT_4:.*]] = fir.convert %[[VOLATILE_CAST_10]] : (!fir.box<!fir.array<10xi32>>) -> !fir.box<!fir.array<?xi32>> +! CHECK: fir.call @_QFPsub_volatile_array_assumed_shape(%[[CONVERT_4]]) fastmath<contract> : (!fir.box<!fir.array<?xi32>>) -> () +! CHECK: fir.call @_QFPsub_volatile_array(%[[VOLATILE_CAST_9]]) fastmath<contract> : (!fir.ref<!fir.array<10xi32>>) -> () +! CHECK: %[[EMBOX_9:.*]] = fir.embox %[[DECLARE_0]]#0(%[[SHAPE_0]]) : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>) -> !fir.box<!fir.array<10xi32>> +! CHECK: %[[CONVERT_5:.*]] = fir.convert %[[EMBOX_9]] : (!fir.box<!fir.array<10xi32>>) -> !fir.box<!fir.array<?xi32>> +! CHECK: fir.call @_QFPsub_volatile_array_assumed_shape(%[[CONVERT_5]]) fastmath<contract> : (!fir.box<!fir.array<?xi32>>) -> () +! CHECK: fir.call @_QFPsub_volatile_array(%[[DECLARE_0]]#0) fastmath<contract> : (!fir.ref<!fir.array<10xi32>>) -> () +! CHECK: %[[CONVERT_6:.*]] = fir.convert %[[DECLARE_6]]#0 : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, volatile>) -> !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>, volatile> +! CHECK: fir.call @_QFPsub_volatile_array_pointer(%[[CONVERT_6]]) fastmath<contract> : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>, volatile>) -> () +! CHECK: %[[VOLATILE_CAST_11:.*]] = fir.volatile_cast %[[DECLARE_1]]#0 : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>) -> !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>, volatile> +! CHECK: fir.call @_QFPsub_volatile_array_pointer(%[[VOLATILE_CAST_11]]) fastmath<contract> : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>, volatile>) -> () +! CHECK: %[[DESIGNATE_0:.*]] = hlfir.designate %[[DECLARE_4]]#0 (%[[CONSTANT_0]]:%[[CONSTANT_2]]:%[[CONSTANT_0]]) shape %[[SHAPE_0]] : (!fir.ref<!fir.array<10xi32>, volatile>, index, index, index, !fir.shape<1>) -> !fir.ref<!fir.array<10xi32>, volatile> +! CHECK: %[[EMBOX_10:.*]] = fir.embox %[[DESIGNATE_0]](%[[SHAPE_0]]) : (!fir.ref<!fir.array<10xi32>, volatile>, !fir.shape<1>) -> !fir.box<!fir.array<10xi32>, volatile> +! CHECK: %[[VOLATILE_CAST_12:.*]] = fir.volatile_cast %[[EMBOX_10]] : (!fir.box<!fir.array<10xi32>, volatile>) -> !fir.box<!fir.array<10xi32>> +! CHECK: %[[CONVERT_7:.*]] = fir.convert %[[VOLATILE_CAST_12]] : (!fir.box<!fir.array<10xi32>>) -> !fir.box<!fir.array<?xi32>> +! CHECK: fir.call @_QFPsub_volatile_array_assumed_shape(%[[CONVERT_7]]) fastmath<contract> : (!fir.box<!fir.array<?xi32>>) -> () +! CHECK: %[[DESIGNATE_1:.*]] = hlfir.designate %[[DECLARE_5]]#0 (%[[CONSTANT_0]]:%[[CONSTANT_2]]:%[[CONSTANT_0]], %[[CONSTANT_0]]:%[[CONSTANT_2]]:%[[CONSTANT_0]]) shape %[[SHAPE_1]] : (!fir.ref<!fir.array<10x10xi32>, volatile>, index, index, index, index, index, index, !fir.shape<2>) -> !fir.box<!fir.array<10x10xi32>, volatile> +! CHECK: %[[VOLATILE_CAST_13:.*]] = fir.volatile_cast %[[DESIGNATE_1]] : (!fir.box<!fir.array<10x10xi32>, volatile>) -> !fir.box<!fir.array<10x10xi32>> +! CHECK: %[[CONVERT_8:.*]] = fir.convert %[[VOLATILE_CAST_13]] : (!fir.box<!fir.array<10x10xi32>>) -> !fir.box<!fir.array<?x?xi32>> +! CHECK: fir.call @_QFPsub_volatile_array_assumed_shape_2d(%[[CONVERT_8]]) fastmath<contract> : (!fir.box<!fir.array<?x?xi32>>) -> () +! CHECK: %[[CONVERT_9:.*]] = fir.convert %[[VOLATILE_CAST_10]] : (!fir.box<!fir.array<10xi32>>) -> !fir.box<!fir.array<*:i32>> +! CHECK: fir.call @_QFPsub_select_rank(%[[CONVERT_9]]) fastmath<contract> : (!fir.box<!fir.array<*:i32>>) -> () +! CHECK: %[[EMBOX_11:.*]] = fir.embox %[[DECLARE_5]]#0(%[[SHAPE_1]]) : (!fir.ref<!fir.array<10x10xi32>, volatile>, !fir.shape<2>) -> !fir.box<!fir.array<10x10xi32>, volatile> +! CHECK: %[[VOLATILE_CAST_14:.*]] = fir.volatile_cast %[[EMBOX_11]] : (!fir.box<!fir.array<10x10xi32>, volatile>) -> !fir.box<!fir.array<10x10xi32>> +! CHECK: %[[CONVERT_10:.*]] = fir.convert %[[VOLATILE_CAST_14]] : (!fir.box<!fir.array<10x10xi32>>) -> !fir.box<!fir.array<*:i32>> +! CHECK: fir.call @_QFPsub_select_rank(%[[CONVERT_10]]) fastmath<contract> : (!fir.box<!fir.array<*:i32>>) -> () ! CHECK: return ! CHECK: } ! CHECK-LABEL: func.func private @_QFPsub_nonvolatile_array( -! CHECK-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<!fir.array<10xi32>> {fir.bindc_name = "arr"}) attributes {fir.host_symbol = @_QQmain, llvm.linkage = #llvm.linkage<internal>} { -! CHECK: %[[VAL_1:.*]] = arith.constant 1 : index -! CHECK: %[[VAL_2:.*]] = arith.constant 5 : i32 -! CHECK: %[[VAL_3:.*]] = arith.constant 10 : index -! CHECK: %[[VAL_4:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_5:.*]] = fir.shape %[[VAL_3]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_5]]) dummy_scope %[[VAL_4]] {uniq_name = "_QFFsub_nonvolatile_arrayEarr"} : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>) -! CHECK: %[[VAL_7:.*]] = hlfir.designate %[[VAL_6]]#0 (%[[VAL_1]]) : (!fir.ref<!fir.array<10xi32>>, index) -> !fir.ref<i32> -! CHECK: hlfir.assign %[[VAL_2]] to %[[VAL_7]] : i32, !fir.ref<i32> +! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.array<10xi32>> {fir.bindc_name = "arr"}) {{.*}} { +! CHECK: %[[CONSTANT_0:.*]] = arith.constant 1 : index +! CHECK: %[[CONSTANT_1:.*]] = arith.constant 5 : i32 +! CHECK: %[[CONSTANT_2:.*]] = arith.constant 10 : index +! CHECK: %[[DUMMY_SCOPE_0:.*]] = fir.dummy_scope : !fir.dscope +! CHECK: %[[SHAPE_0:.*]] = fir.shape %[[CONSTANT_2]] : (index) -> !fir.shape<1> +! CHECK: %[[DECLARE_0:.*]]:2 = hlfir.declare %[[ARG0]](%[[SHAPE_0]]) dummy_scope %[[DUMMY_SCOPE_0]] arg 1 {uniq_name = "_QFFsub_nonvolatile_arrayEarr"} : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>) +! CHECK: %[[DESIGNATE_0:.*]] = hlfir.designate %[[DECLARE_0]]#0 (%[[CONSTANT_0]]) : (!fir.ref<!fir.array<10xi32>>, index) -> !fir.ref<i32> +! CHECK: hlfir.assign %[[CONSTANT_1]] to %[[DESIGNATE_0]] : i32, !fir.ref<i32> ! CHECK: return ! CHECK: } ! CHECK-LABEL: func.func private @_QFPsub_volatile_array_assumed_shape( -! CHECK-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.box<!fir.array<?xi32>> {fir.bindc_name = "arr"}) attributes {fir.host_symbol = @_QQmain, llvm.linkage = #llvm.linkage<internal>} { -! CHECK: %[[VAL_1:.*]] = arith.constant 1 : index -! CHECK: %[[VAL_2:.*]] = arith.constant 5 : i32 -! CHECK: %[[VAL_3:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_4:.*]] = fir.volatile_cast %[[VAL_0]] : (!fir.box<!fir.array<?xi32>>) -> !fir.box<!fir.array<?xi32>, volatile> -! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_4]] dummy_scope %[[VAL_3]] {fortran_attrs = #fir.var_attrs<volatile>, uniq_name = "_QFFsub_volatile_array_assumed_shapeEarr"} : (!fir.box<!fir.array<?xi32>, volatile>, !fir.dscope) -> (!fir.box<!fir.array<?xi32>, volatile>, !fir.box<!fir.array<?xi32>, volatile>) -! CHECK: %[[VAL_6:.*]] = hlfir.designate %[[VAL_5]]#0 (%[[VAL_1]]) : (!fir.box<!fir.array<?xi32>, volatile>, index) -> !fir.ref<i32, volatile> -! CHECK: hlfir.assign %[[VAL_2]] to %[[VAL_6]] : i32, !fir.ref<i32, volatile> +! CHECK-SAME: %[[ARG0:.*]]: !fir.box<!fir.array<?xi32>> {fir.bindc_name = "arr"}) {{.*}} { +! CHECK: %[[CONSTANT_0:.*]] = arith.constant 1 : index +! CHECK: %[[CONSTANT_1:.*]] = arith.constant 5 : i32 +! CHECK: %[[DUMMY_SCOPE_0:.*]] = fir.dummy_scope : !fir.dscope +! CHECK: %[[VOLATILE_CAST_0:.*]] = fir.volatile_cast %[[ARG0]] : (!fir.box<!fir.array<?xi32>>) -> !fir.box<!fir.array<?xi32>, volatile> +! CHECK: %[[DECLARE_0:.*]]:2 = hlfir.declare %[[VOLATILE_CAST_0]] dummy_scope %[[DUMMY_SCOPE_0]] arg 1 {fortran_attrs = #fir.var_attrs<volatile>, uniq_name = "_QFFsub_volatile_array_assumed_shapeEarr"} : (!fir.box<!fir.array<?xi32>, volatile>, !fir.dscope) -> (!fir.box<!fir.array<?xi32>, volatile>, !fir.box<!fir.array<?xi32>, volatile>) +! CHECK: %[[DESIGNATE_0:.*]] = hlfir.designate %[[DECLARE_0]]#0 (%[[CONSTANT_0]]) : (!fir.box<!fir.array<?xi32>, volatile>, index) -> !fir.ref<i32, volatile> +! CHECK: hlfir.assign %[[CONSTANT_1]] to %[[DESIGNATE_0]] : i32, !fir.ref<i32, volatile> ! CHECK: return ! CHECK: } ! CHECK-LABEL: func.func private @_QFPsub_volatile_array_assumed_shape_2d( -! CHECK-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.box<!fir.array<?x?xi32>> {fir.bindc_name = "arr"}) attributes {fir.host_symbol = @_QQmain, llvm.linkage = #llvm.linkage<internal>} { -! CHECK: %[[VAL_1:.*]] = arith.constant 1 : index -! CHECK: %[[VAL_2:.*]] = arith.constant 5 : i32 -! CHECK: %[[VAL_3:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_4:.*]] = fir.volatile_cast %[[VAL_0]] : (!fir.box<!fir.array<?x?xi32>>) -> !fir.box<!fir.array<?x?xi32>, volatile> -! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_4]] dummy_scope %[[VAL_3]] {fortran_attrs = #fir.var_attrs<volatile>, uniq_name = "_QFFsub_volatile_array_assumed_shape_2dEarr"} : (!fir.box<!fir.array<?x?xi32>, volatile>, !fir.dscope) -> (!fir.box<!fir.array<?x?xi32>, volatile>, !fir.box<!fir.array<?x?xi32>, volatile>) -! CHECK: %[[VAL_6:.*]] = hlfir.designate %[[VAL_5]]#0 (%[[VAL_1]], %[[VAL_1]]) : (!fir.box<!fir.array<?x?xi32>, volatile>, index, index) -> !fir.ref<i32, volatile> -! CHECK: hlfir.assign %[[VAL_2]] to %[[VAL_6]] : i32, !fir.ref<i32, volatile> +! CHECK-SAME: %[[ARG0:.*]]: !fir.box<!fir.array<?x?xi32>> {fir.bindc_name = "arr"}) {{.*}} { +! CHECK: %[[CONSTANT_0:.*]] = arith.constant 1 : index +! CHECK: %[[CONSTANT_1:.*]] = arith.constant 5 : i32 +! CHECK: %[[DUMMY_SCOPE_0:.*]] = fir.dummy_scope : !fir.dscope +! CHECK: %[[VOLATILE_CAST_0:.*]] = fir.volatile_cast %[[ARG0]] : (!fir.box<!fir.array<?x?xi32>>) -> !fir.box<!fir.array<?x?xi32>, volatile> +! CHECK: %[[DECLARE_0:.*]]:2 = hlfir.declare %[[VOLATILE_CAST_0]] dummy_scope %[[DUMMY_SCOPE_0]] arg 1 {fortran_attrs = #fir.var_attrs<volatile>, uniq_name = "_QFFsub_volatile_array_assumed_shape_2dEarr"} : (!fir.box<!fir.array<?x?xi32>, volatile>, !fir.dscope) -> (!fir.box<!fir.array<?x?xi32>, volatile>, !fir.box<!fir.array<?x?xi32>, volatile>) +! CHECK: %[[DESIGNATE_0:.*]] = hlfir.designate %[[DECLARE_0]]#0 (%[[CONSTANT_0]], %[[CONSTANT_0]]) : (!fir.box<!fir.array<?x?xi32>, volatile>, index, index) -> !fir.ref<i32, volatile> +! CHECK: hlfir.assign %[[CONSTANT_1]] to %[[DESIGNATE_0]] : i32, !fir.ref<i32, volatile> ! CHECK: return ! CHECK: } ! CHECK-LABEL: func.func private @_QFPsub_volatile_array( -! CHECK-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<!fir.array<10xi32>> {fir.bindc_name = "arr"}) attributes {fir.host_symbol = @_QQmain, llvm.linkage = #llvm.linkage<internal>} { -! CHECK: %[[VAL_1:.*]] = arith.constant 1 : index -! CHECK: %[[VAL_2:.*]] = arith.constant 5 : i32 -! CHECK: %[[VAL_3:.*]] = arith.constant 10 : index -! CHECK: %[[VAL_4:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_5:.*]] = fir.shape %[[VAL_3]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_6:.*]] = fir.volatile_cast %[[VAL_0]] : (!fir.ref<!fir.array<10xi32>>) -> !fir.ref<!fir.array<10xi32>, volatile> -! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_6]](%[[VAL_5]]) dummy_scope %[[VAL_4]] {fortran_attrs = #fir.var_attrs<volatile>, uniq_name = "_QFFsub_volatile_arrayEarr"} : (!fir.ref<!fir.array<10xi32>, volatile>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<10xi32>, volatile>, !fir.ref<!fir.array<10xi32>, volatile>) -! CHECK: %[[VAL_8:.*]] = hlfir.designate %[[VAL_7]]#0 (%[[VAL_1]]) : (!fir.ref<!fir.array<10xi32>, volatile>, index) -> !fir.ref<i32, volatile> -! CHECK: hlfir.assign %[[VAL_2]] to %[[VAL_8]] : i32, !fir.ref<i32, volatile> +! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.array<10xi32>> {fir.bindc_name = "arr"}) {{.*}} { +! CHECK: %[[CONSTANT_0:.*]] = arith.constant 1 : index +! CHECK: %[[CONSTANT_1:.*]] = arith.constant 5 : i32 +! CHECK: %[[CONSTANT_2:.*]] = arith.constant 10 : index +! CHECK: %[[DUMMY_SCOPE_0:.*]] = fir.dummy_scope : !fir.dscope +! CHECK: %[[SHAPE_0:.*]] = fir.shape %[[CONSTANT_2]] : (index) -> !fir.shape<1> +! CHECK: %[[VOLATILE_CAST_0:.*]] = fir.volatile_cast %[[ARG0]] : (!fir.ref<!fir.array<10xi32>>) -> !fir.ref<!fir.array<10xi32>, volatile> +! CHECK: %[[DECLARE_0:.*]]:2 = hlfir.declare %[[VOLATILE_CAST_0]](%[[SHAPE_0]]) dummy_scope %[[DUMMY_SCOPE_0]] arg 1 {fortran_attrs = #fir.var_attrs<volatile>, uniq_name = "_QFFsub_volatile_arrayEarr"} : (!fir.ref<!fir.array<10xi32>, volatile>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<10xi32>, volatile>, !fir.ref<!fir.array<10xi32>, volatile>) +! CHECK: %[[DESIGNATE_0:.*]] = hlfir.designate %[[DECLARE_0]]#0 (%[[CONSTANT_0]]) : (!fir.ref<!fir.array<10xi32>, volatile>, index) -> !fir.ref<i32, volatile> +! CHECK: hlfir.assign %[[CONSTANT_1]] to %[[DESIGNATE_0]] : i32, !fir.ref<i32, volatile> ! CHECK: return ! CHECK: } ! CHECK-LABEL: func.func private @_QFPsub_volatile_array_pointer( -! CHECK-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>, volatile> {fir.bindc_name = "arr"}) attributes {fir.host_symbol = @_QQmain, llvm.linkage = #llvm.linkage<internal>} { -! CHECK: %[[VAL_1:.*]] = arith.constant 1 : index -! CHECK: %[[VAL_2:.*]] = arith.constant 5 : i32 -! CHECK: %[[VAL_3:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_4:.*]] = fir.volatile_cast %[[VAL_0]] : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>, volatile>) -> !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, volatile> -! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_4]] dummy_scope %[[VAL_3]] {fortran_attrs = #fir.var_attrs<pointer, volatile>, uniq_name = "_QFFsub_volatile_array_pointerEarr"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, volatile>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, volatile>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, volatile>) -! CHECK: %[[VAL_6:.*]] = fir.load %[[VAL_5]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, volatile> -! CHECK: %[[VAL_7:.*]] = hlfir.designate %[[VAL_6]] (%[[VAL_1]]) : (!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, index) -> !fir.ref<i32, volatile> -! CHECK: hlfir.assign %[[VAL_2]] to %[[VAL_7]] : i32, !fir.ref<i32, volatile> +! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>, volatile> {fir.bindc_name = "arr"}) {{.*}} { +! CHECK: %[[CONSTANT_0:.*]] = arith.constant 1 : index +! CHECK: %[[CONSTANT_1:.*]] = arith.constant 5 : i32 +! CHECK: %[[DUMMY_SCOPE_0:.*]] = fir.dummy_scope : !fir.dscope +! CHECK: %[[VOLATILE_CAST_0:.*]] = fir.volatile_cast %[[ARG0]] : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>, volatile>) -> !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, volatile> +! CHECK: %[[DECLARE_0:.*]]:2 = hlfir.declare %[[VOLATILE_CAST_0]] dummy_scope %[[DUMMY_SCOPE_0]] arg 1 {fortran_attrs = #fir.var_attrs<pointer, volatile>, uniq_name = "_QFFsub_volatile_array_pointerEarr"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, volatile>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, volatile>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, volatile>) +! CHECK: %[[LOAD_0:.*]] = fir.load %[[DECLARE_0]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, volatile> +! CHECK: %[[DESIGNATE_0:.*]] = hlfir.designate %[[LOAD_0]] (%[[CONSTANT_0]]) : (!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, index) -> !fir.ref<i32, volatile> +! CHECK: hlfir.assign %[[CONSTANT_1]] to %[[DESIGNATE_0]] : i32, !fir.ref<i32, volatile> ! CHECK: return ! CHECK: } ! CHECK-LABEL: func.func private @_QFPsub_select_rank( -! CHECK-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.box<!fir.array<*:i32>> {fir.bindc_name = "arr"}) attributes {fir.host_symbol = @_QQmain, llvm.linkage = #llvm.linkage<internal>} { -! CHECK: %[[VAL_1:.*]] = arith.constant 1 : index -! CHECK: %[[VAL_2:.*]] = arith.constant 5 : i32 -! CHECK: %[[VAL_3:.*]] = arith.constant 4 : i8 -! CHECK: %[[VAL_4:.*]] = arith.constant 1 : i8 -! CHECK: %[[VAL_5:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_6:.*]] = fir.volatile_cast %[[VAL_0]] : (!fir.box<!fir.array<*:i32>>) -> !fir.box<!fir.array<*:i32>, volatile> -! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_6]] dummy_scope %[[VAL_5]] {fortran_attrs = #fir.var_attrs<volatile>, uniq_name = "_QFFsub_select_rankEarr"} : (!fir.box<!fir.array<*:i32>, volatile>, !fir.dscope) -> (!fir.box<!fir.array<*:i32>, volatile>, !fir.box<!fir.array<*:i32>, volatile>) -! CHECK: %[[VAL_8:.*]] = fir.volatile_cast %[[VAL_7]]#0 : (!fir.box<!fir.array<*:i32>, volatile>) -> !fir.box<!fir.array<*:i32>> -! CHECK: %[[VAL_9:.*]] = fir.convert %[[VAL_8]] : (!fir.box<!fir.array<*:i32>>) -> !fir.box<none> -! CHECK: %[[VAL_10:.*]] = fir.call @_FortranAIsAssumedSize(%[[VAL_9]]) : (!fir.box<none>) -> i1 -! CHECK: cf.cond_br %[[VAL_10]], ^bb4, ^bb1 +! CHECK-SAME: %[[ARG0:.*]]: !fir.box<!fir.array<*:i32>> {fir.bindc_name = "arr"}) {{.*}} { +! CHECK: %[[CONSTANT_0:.*]] = arith.constant 1 : index +! CHECK: %[[CONSTANT_1:.*]] = arith.constant 5 : i32 +! CHECK: %[[CONSTANT_2:.*]] = arith.constant 4 : i8 +! CHECK: %[[CONSTANT_3:.*]] = arith.constant 1 : i8 +! CHECK: %[[DUMMY_SCOPE_0:.*]] = fir.dummy_scope : !fir.dscope +! CHECK: %[[VOLATILE_CAST_0:.*]] = fir.volatile_cast %[[ARG0]] : (!fir.box<!fir.array<*:i32>>) -> !fir.box<!fir.array<*:i32>, volatile> +! CHECK: %[[DECLARE_0:.*]]:2 = hlfir.declare %[[VOLATILE_CAST_0]] dummy_scope %[[DUMMY_SCOPE_0]] arg 1 {fortran_attrs = #fir.var_attrs<volatile>, uniq_name = "_QFFsub_select_rankEarr"} : (!fir.box<!fir.array<*:i32>, volatile>, !fir.dscope) -> (!fir.box<!fir.array<*:i32>, volatile>, !fir.box<!fir.array<*:i32>, volatile>) +! CHECK: %[[VOLATILE_CAST_1:.*]] = fir.volatile_cast %[[DECLARE_0]]#0 : (!fir.box<!fir.array<*:i32>, volatile>) -> !fir.box<!fir.array<*:i32>> +! CHECK: %[[CONVERT_0:.*]] = fir.convert %[[VOLATILE_CAST_1]] : (!fir.box<!fir.array<*:i32>>) -> !fir.box<none> +! CHECK: %[[CALL_0:.*]] = fir.call @_FortranAIsAssumedSize(%[[CONVERT_0]]) : (!fir.box<none>) -> i1 +! CHECK: cf.cond_br %[[CALL_0]], ^bb4, ^bb1 ! CHECK: ^bb1: -! CHECK: %[[VAL_11:.*]] = fir.box_rank %[[VAL_7]]#0 : (!fir.box<!fir.array<*:i32>, volatile>) -> i8 -! CHECK: fir.select_case %[[VAL_11]] : i8 [#fir.point, %[[VAL_4]], ^bb2, #fir.point, %[[VAL_3]], ^bb3, unit, ^bb4] +! CHECK: %[[BOX_RANK_0:.*]] = fir.box_rank %[[DECLARE_0]]#0 : (!fir.box<!fir.array<*:i32>, volatile>) -> i8 +! CHECK: fir.select_case %[[BOX_RANK_0]] : i8 [#fir.point, %[[CONSTANT_3]], ^bb2, #fir.point, %[[CONSTANT_2]], ^bb3, unit, ^bb4] ! CHECK: ^bb2: -! CHECK: %[[VAL_12:.*]] = fir.convert %[[VAL_7]]#0 : (!fir.box<!fir.array<*:i32>, volatile>) -> !fir.box<!fir.array<?xi32>, volatile> -! CHECK: %[[VAL_13:.*]]:2 = hlfir.declare %[[VAL_12]] {fortran_attrs = #fir.var_attrs<volatile>, uniq_name = "_QFFsub_select_rankEarr"} : (!fir.box<!fir.array<?xi32>, volatile>) -> (!fir.box<!fir.array<?xi32>, volatile>, !fir.box<!fir.array<?xi32>, volatile>) -! CHECK: %[[VAL_14:.*]] = hlfir.designate %[[VAL_13]]#0 (%[[VAL_1]]) : (!fir.box<!fir.array<?xi32>, volatile>, index) -> !fir.ref<i32, volatile> -! CHECK: hlfir.assign %[[VAL_2]] to %[[VAL_14]] : i32, !fir.ref<i32, volatile> +! CHECK: %[[CONVERT_1:.*]] = fir.convert %[[DECLARE_0]]#0 : (!fir.box<!fir.array<*:i32>, volatile>) -> !fir.box<!fir.array<?xi32>, volatile> +! CHECK: %[[DECLARE_1:.*]]:2 = hlfir.declare %[[CONVERT_1]] {fortran_attrs = #fir.var_attrs<volatile>, uniq_name = "_QFFsub_select_rankEarr"} : (!fir.box<!fir.array<?xi32>, volatile>) -> (!fir.box<!fir.array<?xi32>, volatile>, !fir.box<!fir.array<?xi32>, volatile>) +! CHECK: %[[DESIGNATE_0:.*]] = hlfir.designate %[[DECLARE_1]]#0 (%[[CONSTANT_0]]) : (!fir.box<!fir.array<?xi32>, volatile>, index) -> !fir.ref<i32, volatile> +! CHECK: hlfir.assign %[[CONSTANT_1]] to %[[DESIGNATE_0]] : i32, !fir.ref<i32, volatile> ! CHECK: cf.br ^bb4 ! CHECK: ^bb3: -! CHECK: %[[VAL_15:.*]] = fir.convert %[[VAL_7]]#0 : (!fir.box<!fir.array<*:i32>, volatile>) -> !fir.box<!fir.array<?x?x?x?xi32>, volatile> -! CHECK: %[[VAL_16:.*]]:2 = hlfir.declare %[[VAL_15]] {fortran_attrs = #fir.var_attrs<volatile>, uniq_name = "_QFFsub_select_rankEarr"} : (!fir.box<!fir.array<?x?x?x?xi32>, volatile>) -> (!fir.box<!fir.array<?x?x?x?xi32>, volatile>, !fir.box<!fir.array<?x?x?x?xi32>, volatile>) -! CHECK: %[[VAL_17:.*]] = hlfir.designate %[[VAL_16]]#0 (%[[VAL_1]], %[[VAL_1]], %[[VAL_1]], %[[VAL_1]]) : (!fir.box<!fir.array<?x?x?x?xi32>, volatile>, index, index, index, index) -> !fir.ref<i32, volatile> -! CHECK: hlfir.assign %[[VAL_2]] to %[[VAL_17]] : i32, !fir.ref<i32, volatile> +! CHECK: %[[CONVERT_2:.*]] = fir.convert %[[DECLARE_0]]#0 : (!fir.box<!fir.array<*:i32>, volatile>) -> !fir.box<!fir.array<?x?x?x?xi32>, volatile> +! CHECK: %[[DECLARE_2:.*]]:2 = hlfir.declare %[[CONVERT_2]] {fortran_attrs = #fir.var_attrs<volatile>, uniq_name = "_QFFsub_select_rankEarr"} : (!fir.box<!fir.array<?x?x?x?xi32>, volatile>) -> (!fir.box<!fir.array<?x?x?x?xi32>, volatile>, !fir.box<!fir.array<?x?x?x?xi32>, volatile>) +! CHECK: %[[DESIGNATE_1:.*]] = hlfir.designate %[[DECLARE_2]]#0 (%[[CONSTANT_0]], %[[CONSTANT_0]], %[[CONSTANT_0]], %[[CONSTANT_0]]) : (!fir.box<!fir.array<?x?x?x?xi32>, volatile>, index, index, index, index) -> !fir.ref<i32, volatile> +! CHECK: hlfir.assign %[[CONSTANT_1]] to %[[DESIGNATE_1]] : i32, !fir.ref<i32, volatile> ! CHECK: cf.br ^bb4 ! CHECK: ^bb4: ! CHECK: return diff --git a/flang/test/Lower/volatile4.f90 b/flang/test/Lower/volatile4.f90 index 83ce2b8..9b17d2c 100644 --- a/flang/test/Lower/volatile4.f90 +++ b/flang/test/Lower/volatile4.f90 @@ -17,76 +17,64 @@ contains end subroutine end program -! CHECK-LABEL: func.func @_QQmain() attributes {{.+}} { -! CHECK: %[[VAL_0:.*]] = arith.constant 1 : i32 -! CHECK: %[[VAL_1:.*]] = arith.constant 0 : i32 -! CHECK: %[[VAL_2:.*]] = arith.constant 10 : index -! CHECK: %[[VAL_3:.*]] = fir.address_of(@_QFEarr) : !fir.ref<!fir.array<10xi32>> -! CHECK: %[[VAL_4:.*]] = fir.shape %[[VAL_2]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_5:.*]] = fir.volatile_cast %[[VAL_3]] : (!fir.ref<!fir.array<10xi32>>) -> !fir.ref<!fir.array<10xi32>, volatile> -! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_5]](%[[VAL_4]]) {{.+}} : (!fir.ref<!fir.array<10xi32>, volatile>, !fir.shape<1>) -> (!fir.ref<!fir.array<10xi32>, volatile>, !fir.ref<!fir.array<10xi32>, volatile>) -! CHECK: %[[VAL_7:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFEi"} -! CHECK: %[[VAL_8:.*]] = fir.volatile_cast %[[VAL_7]] : (!fir.ref<i32>) -> !fir.ref<i32, volatile> -! CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[VAL_8]] {{.+}} : (!fir.ref<i32, volatile>) -> (!fir.ref<i32, volatile>, !fir.ref<i32, volatile>) -! CHECK: %[[VAL_10:.*]] = fir.address_of(@_QFEptr) : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>> -! CHECK: %[[VAL_11:.*]] = fir.volatile_cast %[[VAL_10]] : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>) -> !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, volatile> -! CHECK: %[[VAL_12:.*]]:2 = hlfir.declare %[[VAL_11]] {{.+}} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, volatile>) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, volatile>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, volatile>) -! CHECK: %[[VAL_13:.*]] = fir.address_of(@_QFEtgt) : !fir.ref<!fir.array<10xi32>> -! CHECK: %[[VAL_14:.*]] = fir.volatile_cast %[[VAL_13]] : (!fir.ref<!fir.array<10xi32>>) -> !fir.ref<!fir.array<10xi32>, volatile> -! CHECK: %[[VAL_15:.*]]:2 = hlfir.declare %[[VAL_14]](%[[VAL_4]]) {{.+}} : (!fir.ref<!fir.array<10xi32>, volatile>, !fir.shape<1>) -> (!fir.ref<!fir.array<10xi32>, volatile>, !fir.ref<!fir.array<10xi32>, volatile>) -! CHECK: %[[VAL_16:.*]] = fir.alloca tuple<!fir.ref<i32>> -! CHECK: %[[VAL_17:.*]] = fir.coordinate_of %[[VAL_16]], %[[VAL_1]] : (!fir.ref<tuple<!fir.ref<i32>>>, i32) -> !fir.llvm_ptr<!fir.ref<i32>> -! CHECK: %[[VAL_18:.*]] = fir.volatile_cast %[[VAL_9]]#0 : (!fir.ref<i32, volatile>) -> !fir.ref<i32> -! CHECK: fir.store %[[VAL_18]] to %[[VAL_17]] : !fir.llvm_ptr<!fir.ref<i32>> -! CHECK: %[[VAL_19:.*]] = fir.embox %[[VAL_15]]#0(%[[VAL_4]]) : (!fir.ref<!fir.array<10xi32>, volatile>, !fir.shape<1>) -> !fir.box<!fir.ptr<!fir.array<?xi32>>, volatile> -! CHECK: fir.store %[[VAL_19]] to %[[VAL_12]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, volatile> -! CHECK: hlfir.assign %[[VAL_1]] to %[[VAL_9]]#0 : i32, !fir.ref<i32, volatile> -! CHECK: hlfir.assign %[[VAL_0]] to %[[VAL_6]]#0 : i32, !fir.ref<!fir.array<10xi32>, volatile> -! CHECK: fir.call @_QFPhost_assoc(%[[VAL_16]]) fastmath<contract> : (!fir.ref<tuple<!fir.ref<i32>>>) -> () +! CHECK-LABEL: func.func @_QQmain() {{.*}} { +! CHECK: %[[CONSTANT_0:.*]] = arith.constant 1 : i32 +! CHECK: %[[CONSTANT_1:.*]] = arith.constant 0 : i32 +! CHECK: %[[CONSTANT_2:.*]] = arith.constant 10 : index +! CHECK: %[[DUMMY_SCOPE_0:.*]] = fir.dummy_scope : !fir.dscope +! CHECK: %[[ADDRESS_OF_0:.*]] = fir.address_of(@_QFEarr) : !fir.ref<!fir.array<10xi32>> +! CHECK: %[[SHAPE_0:.*]] = fir.shape %[[CONSTANT_2]] : (index) -> !fir.shape<1> +! CHECK: %[[VOLATILE_CAST_0:.*]] = fir.volatile_cast %[[ADDRESS_OF_0]] : (!fir.ref<!fir.array<10xi32>>) -> !fir.ref<!fir.array<10xi32>, volatile> +! CHECK: %[[DECLARE_0:.*]]:2 = hlfir.declare %[[VOLATILE_CAST_0]](%[[SHAPE_0]]) {fortran_attrs = #fir.var_attrs<volatile, internal_assoc>, uniq_name = "_QFEarr"} : (!fir.ref<!fir.array<10xi32>, volatile>, !fir.shape<1>) -> (!fir.ref<!fir.array<10xi32>, volatile>, !fir.ref<!fir.array<10xi32>, volatile>) +! CHECK: %[[ALLOCA_0:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFEi"} +! CHECK: %[[VOLATILE_CAST_1:.*]] = fir.volatile_cast %[[ALLOCA_0]] : (!fir.ref<i32>) -> !fir.ref<i32, volatile> +! CHECK: %[[DECLARE_1:.*]]:2 = hlfir.declare %[[VOLATILE_CAST_1]] {fortran_attrs = #fir.var_attrs<volatile, internal_assoc>, uniq_name = "_QFEi"} : (!fir.ref<i32, volatile>) -> (!fir.ref<i32, volatile>, !fir.ref<i32, volatile>) +! CHECK: %[[ADDRESS_OF_1:.*]] = fir.address_of(@_QFEptr) : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>> +! CHECK: %[[VOLATILE_CAST_2:.*]] = fir.volatile_cast %[[ADDRESS_OF_1]] : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>) -> !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, volatile> +! CHECK: %[[DECLARE_2:.*]]:2 = hlfir.declare %[[VOLATILE_CAST_2]] {fortran_attrs = #fir.var_attrs<pointer, volatile, internal_assoc>, uniq_name = "_QFEptr"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, volatile>) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, volatile>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, volatile>) +! CHECK: %[[ADDRESS_OF_2:.*]] = fir.address_of(@_QFEtgt) : !fir.ref<!fir.array<10xi32>> +! CHECK: %[[VOLATILE_CAST_3:.*]] = fir.volatile_cast %[[ADDRESS_OF_2]] : (!fir.ref<!fir.array<10xi32>>) -> !fir.ref<!fir.array<10xi32>, volatile> +! CHECK: %[[DECLARE_3:.*]]:2 = hlfir.declare %[[VOLATILE_CAST_3]](%[[SHAPE_0]]) {fortran_attrs = #fir.var_attrs<target, volatile, internal_assoc>, uniq_name = "_QFEtgt"} : (!fir.ref<!fir.array<10xi32>, volatile>, !fir.shape<1>) -> (!fir.ref<!fir.array<10xi32>, volatile>, !fir.ref<!fir.array<10xi32>, volatile>) +! CHECK: %[[ALLOCA_1:.*]] = fir.alloca tuple<!fir.ref<i32>> +! CHECK: %[[COORDINATE_OF_0:.*]] = fir.coordinate_of %[[ALLOCA_1]], %[[CONSTANT_1]] : (!fir.ref<tuple<!fir.ref<i32>>>, i32) -> !fir.llvm_ptr<!fir.ref<i32>> +! CHECK: %[[VOLATILE_CAST_4:.*]] = fir.volatile_cast %[[DECLARE_1]]#0 : (!fir.ref<i32, volatile>) -> !fir.ref<i32> +! CHECK: fir.store %[[VOLATILE_CAST_4]] to %[[COORDINATE_OF_0]] : !fir.llvm_ptr<!fir.ref<i32>> +! CHECK: %[[CONVERT_0:.*]] = fir.convert %[[DECLARE_1]]#0 : (!fir.ref<i32, volatile>) -> i64 +! CHECK: %[[CONVERT_1:.*]] = fir.convert %[[CONVERT_0]] : (i64) -> i32 +! CHECK: hlfir.assign %[[CONVERT_1]] to %[[DECLARE_1]]#0 : i32, !fir.ref<i32, volatile> +! CHECK: %[[CONVERT_2:.*]] = fir.convert %[[DECLARE_3]]#0 : (!fir.ref<!fir.array<10xi32>, volatile>) -> !fir.ref<!fir.array<?xi32>, volatile> +! CHECK: %[[EMBOX_0:.*]] = fir.embox %[[CONVERT_2]](%[[SHAPE_0]]) : (!fir.ref<!fir.array<?xi32>, volatile>, !fir.shape<1>) -> !fir.box<!fir.ptr<!fir.array<?xi32>>, volatile> +! CHECK: fir.store %[[EMBOX_0]] to %[[DECLARE_2]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, volatile> +! CHECK: hlfir.assign %[[CONSTANT_1]] to %[[DECLARE_1]]#0 : i32, !fir.ref<i32, volatile> +! CHECK: hlfir.assign %[[CONSTANT_0]] to %[[DECLARE_0]]#0 : i32, !fir.ref<!fir.array<10xi32>, volatile> +! CHECK: fir.call @_QFPhost_assoc(%[[ALLOCA_1]]) fastmath<contract> : (!fir.ref<tuple<!fir.ref<i32>>>) -> () ! CHECK: return ! CHECK: } ! CHECK-LABEL: func.func private @_QFPhost_assoc( -! CHECK-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<tuple<!fir.ref<i32>>> {fir.host_assoc}) attributes {{.+}} { -! CHECK: %[[VAL_1:.*]] = arith.constant 1 : i32 -! CHECK: %[[VAL_2:.*]] = arith.constant 0 : i32 -! CHECK: %[[VAL_3:.*]] = arith.constant 10 : index -! CHECK: %[[VAL_4:.*]] = fir.dummy_scope : !fir.dscope -! CHECK: %[[VAL_5:.*]] = fir.address_of(@_QFEarr) : !fir.ref<!fir.array<10xi32>> -! CHECK: %[[VAL_6:.*]] = fir.shape %[[VAL_3]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_7:.*]] = fir.volatile_cast %[[VAL_5]] : (!fir.ref<!fir.array<10xi32>>) -> !fir.ref<!fir.array<10xi32>, volatile> -! CHECK: %[[VAL_8:.*]]:2 = hlfir.declare %[[VAL_7]](%[[VAL_6]]) {{.+}} : (!fir.ref<!fir.array<10xi32>, volatile>, !fir.shape<1>) -> (!fir.ref<!fir.array<10xi32>, volatile>, !fir.ref<!fir.array<10xi32>, volatile>) -! CHECK: %[[VAL_9:.*]] = fir.address_of(@_QFEptr) : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>> -! CHECK: %[[VAL_10:.*]] = fir.volatile_cast %[[VAL_9]] : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>) -> !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, volatile> -! CHECK: %[[VAL_11:.*]]:2 = hlfir.declare %[[VAL_10]] {{.+}} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, volatile>) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, volatile>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, volatile>) -! CHECK: %[[VAL_12:.*]] = fir.address_of(@_QFEtgt) : !fir.ref<!fir.array<10xi32>> -! CHECK: %[[VAL_13:.*]] = fir.volatile_cast %[[VAL_12]] : (!fir.ref<!fir.array<10xi32>>) -> !fir.ref<!fir.array<10xi32>, volatile> -! CHECK: %[[VAL_14:.*]]:2 = hlfir.declare %[[VAL_13]](%[[VAL_6]]) {{.+}} : (!fir.ref<!fir.array<10xi32>, volatile>, !fir.shape<1>) -> (!fir.ref<!fir.array<10xi32>, volatile>, !fir.ref<!fir.array<10xi32>, volatile>) -! CHECK: %[[VAL_15:.*]] = fir.coordinate_of %[[VAL_0]], %[[VAL_2]] : (!fir.ref<tuple<!fir.ref<i32>>>, i32) -> !fir.llvm_ptr<!fir.ref<i32>> -! CHECK: %[[VAL_16:.*]] = fir.load %[[VAL_15]] : !fir.llvm_ptr<!fir.ref<i32>> -! CHECK: %[[VAL_17:.*]] = fir.volatile_cast %[[VAL_16]] : (!fir.ref<i32>) -> !fir.ref<i32, volatile> -! CHECK: %[[VAL_18:.*]]:2 = hlfir.declare %[[VAL_17]] {{.+}} : (!fir.ref<i32, volatile>) -> (!fir.ref<i32, volatile>, !fir.ref<i32, volatile>) -! CHECK: %[[VAL_19:.*]] = fir.embox %[[VAL_14]]#0(%[[VAL_6]]) : (!fir.ref<!fir.array<10xi32>, volatile>, !fir.shape<1>) -> !fir.box<!fir.ptr<!fir.array<?xi32>>, volatile> -! CHECK: fir.store %[[VAL_19]] to %[[VAL_11]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, volatile> -! CHECK: hlfir.assign %[[VAL_2]] to %[[VAL_18]]#0 : i32, !fir.ref<i32, volatile> -! CHECK: hlfir.assign %[[VAL_1]] to %[[VAL_8]]#0 : i32, !fir.ref<!fir.array<10xi32>, volatile> +! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<tuple<!fir.ref<i32>>> {fir.host_assoc}) {{.*}} { +! CHECK: %[[CONSTANT_0:.*]] = arith.constant 1 : i32 +! CHECK: %[[CONSTANT_1:.*]] = arith.constant 0 : i32 +! CHECK: %[[CONSTANT_2:.*]] = arith.constant 10 : index +! CHECK: %[[DUMMY_SCOPE_0:.*]] = fir.dummy_scope : !fir.dscope +! CHECK: %[[ADDRESS_OF_0:.*]] = fir.address_of(@_QFEarr) : !fir.ref<!fir.array<10xi32>> +! CHECK: %[[SHAPE_0:.*]] = fir.shape %[[CONSTANT_2]] : (index) -> !fir.shape<1> +! CHECK: %[[VOLATILE_CAST_0:.*]] = fir.volatile_cast %[[ADDRESS_OF_0]] : (!fir.ref<!fir.array<10xi32>>) -> !fir.ref<!fir.array<10xi32>, volatile> +! CHECK: %[[DECLARE_0:.*]]:2 = hlfir.declare %[[VOLATILE_CAST_0]](%[[SHAPE_0]]) {fortran_attrs = #fir.var_attrs<volatile>, uniq_name = "_QFEarr"} : (!fir.ref<!fir.array<10xi32>, volatile>, !fir.shape<1>) -> (!fir.ref<!fir.array<10xi32>, volatile>, !fir.ref<!fir.array<10xi32>, volatile>) +! CHECK: %[[ADDRESS_OF_1:.*]] = fir.address_of(@_QFEptr) : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>> +! CHECK: %[[VOLATILE_CAST_1:.*]] = fir.volatile_cast %[[ADDRESS_OF_1]] : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>) -> !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, volatile> +! CHECK: %[[DECLARE_1:.*]]:2 = hlfir.declare %[[VOLATILE_CAST_1]] {fortran_attrs = #fir.var_attrs<pointer, volatile>, uniq_name = "_QFEptr"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, volatile>) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, volatile>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, volatile>) +! CHECK: %[[ADDRESS_OF_2:.*]] = fir.address_of(@_QFEtgt) : !fir.ref<!fir.array<10xi32>> +! CHECK: %[[VOLATILE_CAST_2:.*]] = fir.volatile_cast %[[ADDRESS_OF_2]] : (!fir.ref<!fir.array<10xi32>>) -> !fir.ref<!fir.array<10xi32>, volatile> +! CHECK: %[[DECLARE_2:.*]]:2 = hlfir.declare %[[VOLATILE_CAST_2]](%[[SHAPE_0]]) {fortran_attrs = #fir.var_attrs<target, volatile>, uniq_name = "_QFEtgt"} : (!fir.ref<!fir.array<10xi32>, volatile>, !fir.shape<1>) -> (!fir.ref<!fir.array<10xi32>, volatile>, !fir.ref<!fir.array<10xi32>, volatile>) +! CHECK: %[[COORDINATE_OF_0:.*]] = fir.coordinate_of %[[ARG0]], %[[CONSTANT_1]] : (!fir.ref<tuple<!fir.ref<i32>>>, i32) -> !fir.llvm_ptr<!fir.ref<i32>> +! CHECK: %[[LOAD_0:.*]] = fir.load %[[COORDINATE_OF_0]] : !fir.llvm_ptr<!fir.ref<i32>> +! CHECK: %[[VOLATILE_CAST_3:.*]] = fir.volatile_cast %[[LOAD_0]] : (!fir.ref<i32>) -> !fir.ref<i32, volatile> +! CHECK: %[[DECLARE_3:.*]]:2 = hlfir.declare %[[VOLATILE_CAST_3]] {fortran_attrs = #fir.var_attrs<volatile, host_assoc>, uniq_name = "_QFEi"} : (!fir.ref<i32, volatile>) -> (!fir.ref<i32, volatile>, !fir.ref<i32, volatile>) +! CHECK: %[[CONVERT_0:.*]] = fir.convert %[[DECLARE_2]]#0 : (!fir.ref<!fir.array<10xi32>, volatile>) -> !fir.ref<!fir.array<?xi32>, volatile> +! CHECK: %[[EMBOX_0:.*]] = fir.embox %[[CONVERT_0]](%[[SHAPE_0]]) : (!fir.ref<!fir.array<?xi32>, volatile>, !fir.shape<1>) -> !fir.box<!fir.ptr<!fir.array<?xi32>>, volatile> +! CHECK: fir.store %[[EMBOX_0]] to %[[DECLARE_1]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, volatile> +! CHECK: hlfir.assign %[[CONSTANT_1]] to %[[DECLARE_3]]#0 : i32, !fir.ref<i32, volatile> +! CHECK: hlfir.assign %[[CONSTANT_0]] to %[[DECLARE_0]]#0 : i32, !fir.ref<!fir.array<10xi32>, volatile> ! CHECK: return ! CHECK: } - -! CHECK-LABEL: fir.global internal @_QFEarr : !fir.array<10xi32> { -! CHECK: %[[VAL_0:.*]] = fir.zero_bits !fir.array<10xi32> -! CHECK: fir.has_value %[[VAL_0]] : !fir.array<10xi32> -! CHECK: } - -! CHECK-LABEL: fir.global internal @_QFEptr : !fir.box<!fir.ptr<!fir.array<?xi32>>> { -! CHECK: %[[VAL_0:.*]] = arith.constant 0 : index -! CHECK: %[[VAL_1:.*]] = fir.zero_bits !fir.ptr<!fir.array<?xi32>> -! CHECK: %[[VAL_2:.*]] = fir.shape %[[VAL_0]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_3:.*]] = fir.embox %[[VAL_1]](%[[VAL_2]]) : (!fir.ptr<!fir.array<?xi32>>, !fir.shape<1>) -> !fir.box<!fir.ptr<!fir.array<?xi32>>> -! CHECK: fir.has_value %[[VAL_3]] : !fir.box<!fir.ptr<!fir.array<?xi32>>> -! CHECK: } - -! CHECK-LABEL: fir.global internal @_QFEtgt target : !fir.array<10xi32> { -! CHECK: %[[VAL_0:.*]] = fir.zero_bits !fir.array<10xi32> -! CHECK: fir.has_value %[[VAL_0]] : !fir.array<10xi32> -! CHECK: } diff --git a/flang/test/Parser/OpenMP/allocate-align-tree.f90 b/flang/test/Parser/OpenMP/allocate-align-tree.f90 index 0d247cd..e440d239 100644 --- a/flang/test/Parser/OpenMP/allocate-align-tree.f90 +++ b/flang/test/Parser/OpenMP/allocate-align-tree.f90 @@ -16,27 +16,33 @@ program allocate_align_tree allocate(j(z), xarray(t)) end program allocate_align_tree -!CHECK: | | DeclarationConstruct -> SpecificationConstruct -> TypeDeclarationStmt -!CHECK-NEXT: | | | DeclarationTypeSpec -> IntrinsicTypeSpec -> IntegerTypeSpec -> -!CHECK-NEXT: | | | AttrSpec -> Allocatable -!CHECK-NEXT: | | | EntityDecl -!CHECK-NEXT: | | | | Name = 'j' +!CHECK: DeclarationConstruct -> SpecificationConstruct -> TypeDeclarationStmt +!CHECK-NEXT: | DeclarationTypeSpec -> IntrinsicTypeSpec -> IntegerTypeSpec -> +!CHECK-NEXT: | AttrSpec -> Allocatable +!CHECK-NEXT: | EntityDecl +!CHECK-NEXT: | | Name = 'j' +!CHECK: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OmpAllocateDirective +!CHECK-NEXT: | OmpBeginDirective +!CHECK-NEXT: | | OmpDirectiveName -> llvm::omp::Directive = allocate +!CHECK-NEXT: | | OmpArgumentList -> OmpArgument -> OmpLocator -> OmpObject -> Designator -> DataRef -> Name = 'j' +!CHECK-NEXT: | | OmpClauseList -> OmpClause -> Align -> OmpAlignClause -> Scalar -> Integer -> Constant -> Expr = '16_4' +!CHECK-NEXT: | | | LiteralConstant -> IntLiteralConstant = '16' +!CHECK-NEXT: | | Flags = {} +!CHECK-NEXT: | Block +!CHECK-NEXT: | | ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OmpAllocateDirective +!CHECK-NEXT: | | | OmpBeginDirective +!CHECK-NEXT: | | | | OmpDirectiveName -> llvm::omp::Directive = allocate +!CHECK-NEXT: | | | | OmpArgumentList -> OmpArgument -> OmpLocator -> OmpObject -> Designator -> DataRef -> Name = 'xarray' +!CHECK-NEXT: | | | | OmpClauseList -> OmpClause -> Align -> OmpAlignClause -> Scalar -> Integer -> Constant -> Expr = '32_4' +!CHECK-NEXT: | | | | | LiteralConstant -> IntLiteralConstant = '32' +!CHECK-NEXT: | | | | OmpClause -> Allocator -> Scalar -> Integer -> Expr = '2_8' +!CHECK-NEXT: | | | | | Designator -> DataRef -> Name = 'omp_large_cap_mem_alloc' +!CHECK-NEXT: | | | | Flags = {} +!CHECK-NEXT: | | | Block +!CHECK-NEXT: | | | | ExecutionPartConstruct -> ExecutableConstruct -> ActionStmt -> AllocateStmt -!CHECK: | | ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPExecutableAllocate -!CHECK-NEXT: | | | Verbatim -!CHECK-NEXT: | | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'xarray' -!CHECK-NEXT: | | | OmpClauseList -> OmpClause -> Align -> OmpAlignClause -> Scalar -> Integer -> Constant -> Expr = '32_4' -!CHECK-NEXT: | | | | LiteralConstant -> IntLiteralConstant = '32' -!CHECK-NEXT: | | | OmpClause -> Allocator -> Scalar -> Integer -> Expr = '2_8' -!CHECK-NEXT: | | | | Designator -> DataRef -> Name = 'omp_large_cap_mem_alloc' -!CHECK-NEXT: | | | OpenMPDeclarativeAllocate -!CHECK-NEXT: | | | | Verbatim -!CHECK-NEXT: | | | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'j' -!CHECK-NEXT: | | | | OmpClauseList -> OmpClause -> Align -> OmpAlignClause -> Scalar -> Integer -> Constant -> Expr = '16_4' -!CHECK-NEXT: | | | | | LiteralConstant -> IntLiteralConstant = '16' -!CHECK-NEXT: | | | AllocateStmt +!UNPARSE: !$OMP ALLOCATE(j) ALIGN(16_4) +!UNPARSE-NEXT: !$OMP ALLOCATE(xarray) ALIGN(32_4) ALLOCATOR(2_8) +!UNPARSE-NEXT: ALLOCATE(j(z), xarray(t)) -!UNPARSE: !$OMP ALLOCATE (j) ALIGN(16_4) -!UNPARSE: !$OMP ALLOCATE (xarray) ALIGN(32_4) ALLOCATOR(2_8) -!UNPARSE-NEXT: ALLOCATE(j(z), xarray(t)) diff --git a/flang/test/Parser/OpenMP/allocate-tree-spec-part.f90 b/flang/test/Parser/OpenMP/allocate-tree-spec-part.f90 index afcaf44..92ddbbdc 100644 --- a/flang/test/Parser/OpenMP/allocate-tree-spec-part.f90 +++ b/flang/test/Parser/OpenMP/allocate-tree-spec-part.f90 @@ -17,33 +17,48 @@ program allocate_tree allocate (w, xarray(4), zarray(5, f)) end program allocate_tree -!CHECK: | | DeclarationConstruct -> SpecificationConstruct -> OpenMPDeclarativeConstruct -> OpenMPDeclarativeAllocate -!CHECK-NEXT: | | | Verbatim -!CHECK-NEXT: | | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'f' -!CHECK-NEXT: | | | OmpClauseList -> OmpClause -> Allocator -> Scalar -> Integer -> Expr = -!CHECK-NEXT: | | | | Designator -> DataRef -> Name = +!CHECK: | | DeclarationConstruct -> SpecificationConstruct -> OpenMPDeclarativeConstruct -> OmpAllocateDirective +!CHECK-NEXT: | | | OmpBeginDirective +!CHECK-NEXT: | | | | OmpDirectiveName -> llvm::omp::Directive = allocate +!CHECK-NEXT: | | | | OmpArgumentList -> OmpArgument -> OmpLocator -> OmpObject -> Designator -> DataRef -> Name = 'f' +!CHECK-NEXT: | | | | OmpClauseList -> OmpClause -> Allocator -> Scalar -> Integer -> Expr = '1_8' +!CHECK-NEXT: | | | | | Designator -> DataRef -> Name = 'omp_default_mem_alloc' +!CHECK-NEXT: | | | | Flags = {} +!CHECK-NEXT: | | | Block !CHECK-NEXT: | ExecutionPart -> Block !CHECK-NEXT: | | ExecutionPartConstruct -> ExecutableConstruct -> ActionStmt -> AssignmentStmt = 'f=2_4' !CHECK-NEXT: | | | Variable = 'f' !CHECK-NEXT: | | | | Designator -> DataRef -> Name = 'f' !CHECK-NEXT: | | | Expr = '2_4' !CHECK-NEXT: | | | | LiteralConstant -> IntLiteralConstant = '2' -!CHECK-NEXT: | | ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPExecutableAllocate -!CHECK-NEXT: | | | Verbatim -!CHECK-NEXT: | | | OmpClauseList -> -!CHECK-NEXT: | | | OpenMPDeclarativeAllocate -!CHECK-NEXT: | | | | Verbatim -!CHECK-NEXT: | | | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'w' -!CHECK-NEXT: | | | | OmpClauseList -> OmpClause -> Allocator -> Scalar -> Integer -> Expr = -!CHECK-NEXT: | | | | | Designator -> DataRef -> Name = -!CHECK-NEXT: | | | OpenMPDeclarativeAllocate -!CHECK-NEXT: | | | | Verbatim -!CHECK-NEXT: | | | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'xarray' -!CHECK-NEXT: | | | | OmpClauseList -> OmpClause -> Allocator -> Scalar -> Integer -> Expr = -!CHECK-NEXT: | | | | | Designator -> DataRef -> Name = -!CHECK-NEXT: | | | OpenMPDeclarativeAllocate -!CHECK-NEXT: | | | | Verbatim -!CHECK-NEXT: | | | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'zarray' -!CHECK-NEXT: | | | | OmpClauseList -> OmpClause -> Allocator -> Scalar -> Integer -> Expr = -!CHECK-NEXT: | | | | | Designator -> DataRef -> Name = -!CHECK-NEXT: | | | AllocateStmt +!CHECK-NEXT: | | ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OmpAllocateDirective +!CHECK-NEXT: | | | OmpBeginDirective +!CHECK-NEXT: | | | | OmpDirectiveName -> llvm::omp::Directive = allocate +!CHECK-NEXT: | | | | OmpArgumentList -> OmpArgument -> OmpLocator -> OmpObject -> Designator -> DataRef -> Name = 'w' +!CHECK-NEXT: | | | | OmpClauseList -> OmpClause -> Allocator -> Scalar -> Integer -> Expr = '3_8' +!CHECK-NEXT: | | | | | Designator -> DataRef -> Name = 'omp_const_mem_alloc' +!CHECK-NEXT: | | | | Flags = {} +!CHECK-NEXT: | | | Block +!CHECK-NEXT: | | | | ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OmpAllocateDirective +!CHECK-NEXT: | | | | | OmpBeginDirective +!CHECK-NEXT: | | | | | | OmpDirectiveName -> llvm::omp::Directive = allocate +!CHECK-NEXT: | | | | | | OmpArgumentList -> OmpArgument -> OmpLocator -> OmpObject -> Designator -> DataRef -> Name = 'xarray' +!CHECK-NEXT: | | | | | | OmpClauseList -> OmpClause -> Allocator -> Scalar -> Integer -> Expr = '2_8' +!CHECK-NEXT: | | | | | | | Designator -> DataRef -> Name = 'omp_large_cap_mem_alloc' +!CHECK-NEXT: | | | | | | Flags = {} +!CHECK-NEXT: | | | | | Block +!CHECK-NEXT: | | | | | | ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OmpAllocateDirective +!CHECK-NEXT: | | | | | | | OmpBeginDirective +!CHECK-NEXT: | | | | | | | | OmpDirectiveName -> llvm::omp::Directive = allocate +!CHECK-NEXT: | | | | | | | | OmpArgumentList -> OmpArgument -> OmpLocator -> OmpObject -> Designator -> DataRef -> Name = 'zarray' +!CHECK-NEXT: | | | | | | | | OmpClauseList -> OmpClause -> Allocator -> Scalar -> Integer -> Expr = '1_8' +!CHECK-NEXT: | | | | | | | | | Designator -> DataRef -> Name = 'omp_default_mem_alloc' +!CHECK-NEXT: | | | | | | | | Flags = {} +!CHECK-NEXT: | | | | | | | Block +!CHECK-NEXT: | | | | | | | | ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OmpAllocateDirective +!CHECK-NEXT: | | | | | | | | | OmpBeginDirective +!CHECK-NEXT: | | | | | | | | | | OmpDirectiveName -> llvm::omp::Directive = allocate +!CHECK-NEXT: | | | | | | | | | | OmpClauseList -> +!CHECK-NEXT: | | | | | | | | | | Flags = {} +!CHECK-NEXT: | | | | | | | | | Block +!CHECK-NEXT: | | | | | | | | | | ExecutionPartConstruct -> ExecutableConstruct -> ActionStmt -> AllocateStmt diff --git a/flang/test/Parser/OpenMP/allocate-tree.f90 b/flang/test/Parser/OpenMP/allocate-tree.f90 index bf413d5..17ffb76 100644 --- a/flang/test/Parser/OpenMP/allocate-tree.f90 +++ b/flang/test/Parser/OpenMP/allocate-tree.f90 @@ -7,52 +7,54 @@ program allocate_tree use omp_lib - integer, allocatable :: w, xarray(:), zarray(:, :) - integer :: z, t + integer, allocatable :: xarray(:), zarray(:, :) + integer :: z, t, w +!$omp allocate(w) allocator(omp_const_mem_alloc) t = 2 z = 3 -!$omp allocate(w) allocator(omp_const_mem_alloc) !$omp allocate(xarray) allocator(omp_large_cap_mem_alloc) !$omp allocate(zarray) allocator(omp_default_mem_alloc) !$omp allocate - allocate(w, xarray(4), zarray(t, z)) + allocate(xarray(4), zarray(t, z)) end program allocate_tree -!CHECK: | | DeclarationConstruct -> SpecificationConstruct -> TypeDeclarationStmt -!CHECK-NEXT: | | | DeclarationTypeSpec -> IntrinsicTypeSpec -> IntegerTypeSpec -> -!CHECK-NEXT: | | | AttrSpec -> Allocatable -!CHECK-NEXT: | | | EntityDecl -!CHECK-NEXT: | | | | Name = 'w' -!CHECK-NEXT: | | | EntityDecl -!CHECK-NEXT: | | | | Name = 'xarray' -!CHECK-NEXT: | | | | ArraySpec -> DeferredShapeSpecList -> int = '1' -!CHECK-NEXT: | | | EntityDecl -!CHECK-NEXT: | | | | Name = 'zarray' -!CHECK-NEXT: | | | | ArraySpec -> DeferredShapeSpecList -> int = '2' - +!CHECK: DeclarationConstruct -> SpecificationConstruct -> OpenMPDeclarativeConstruct -> OmpAllocateDirective +!CHECK-NEXT: | OmpBeginDirective +!CHECK-NEXT: | | OmpDirectiveName -> llvm::omp::Directive = allocate +!CHECK-NEXT: | | OmpArgumentList -> OmpArgument -> OmpLocator -> OmpObject -> Designator -> DataRef -> Name = 'w' +!CHECK-NEXT: | | OmpClauseList -> OmpClause -> Allocator -> Scalar -> Integer -> Expr = '3_8' +!CHECK-NEXT: | | | Designator -> DataRef -> Name = 'omp_const_mem_alloc' +!CHECK-NEXT: | | Flags = {} +!CHECK-NEXT: | Block -!CHECK: | | ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPExecutableAllocate -!CHECK-NEXT: | | | Verbatim -!CHECK-NEXT: | | | OmpClauseList -> -!CHECK-NEXT: | | | OpenMPDeclarativeAllocate -!CHECK-NEXT: | | | | Verbatim -!CHECK-NEXT: | | | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'w' -!CHECK-NEXT: | | | | OmpClauseList -> OmpClause -> Allocator -> Scalar -> Integer -> Expr = -!CHECK-NEXT: | | | | | Designator -> DataRef -> Name = -!CHECK-NEXT: | | | OpenMPDeclarativeAllocate -!CHECK-NEXT: | | | | Verbatim -!CHECK-NEXT: | | | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'xarray' -!CHECK-NEXT: | | | | OmpClauseList -> OmpClause -> Allocator -> Scalar -> Integer -> Expr = -!CHECK-NEXT: | | | | | Designator -> DataRef -> Name = -!CHECK-NEXT: | | | OpenMPDeclarativeAllocate -!CHECK-NEXT: | | | | Verbatim -!CHECK-NEXT: | | | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'zarray' -!CHECK-NEXT: | | | | OmpClauseList -> OmpClause -> Allocator -> Scalar -> Integer -> Expr = -!CHECK-NEXT: | | | | | Designator -> DataRef -> Name = -!CHECK-NEXT: | | | AllocateStmt +!CHECK: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OmpAllocateDirective +!CHECK-NEXT: | OmpBeginDirective +!CHECK-NEXT: | | OmpDirectiveName -> llvm::omp::Directive = allocate +!CHECK-NEXT: | | OmpArgumentList -> OmpArgument -> OmpLocator -> OmpObject -> Designator -> DataRef -> Name = 'xarray' +!CHECK-NEXT: | | OmpClauseList -> OmpClause -> Allocator -> Scalar -> Integer -> Expr = '2_8' +!CHECK-NEXT: | | | Designator -> DataRef -> Name = 'omp_large_cap_mem_alloc' +!CHECK-NEXT: | | Flags = {} +!CHECK-NEXT: | Block +!CHECK-NEXT: | | ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OmpAllocateDirective +!CHECK-NEXT: | | | OmpBeginDirective +!CHECK-NEXT: | | | | OmpDirectiveName -> llvm::omp::Directive = allocate +!CHECK-NEXT: | | | | OmpArgumentList -> OmpArgument -> OmpLocator -> OmpObject -> Designator -> DataRef -> Name = 'zarray' +!CHECK-NEXT: | | | | OmpClauseList -> OmpClause -> Allocator -> Scalar -> Integer -> Expr = '1_8' +!CHECK-NEXT: | | | | | Designator -> DataRef -> Name = 'omp_default_mem_alloc' +!CHECK-NEXT: | | | | Flags = {} +!CHECK-NEXT: | | | Block +!CHECK-NEXT: | | | | ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OmpAllocateDirective +!CHECK-NEXT: | | | | | OmpBeginDirective +!CHECK-NEXT: | | | | | | OmpDirectiveName -> llvm::omp::Directive = allocate +!CHECK-NEXT: | | | | | | OmpClauseList -> +!CHECK-NEXT: | | | | | | Flags = {} +!CHECK-NEXT: | | | | | Block +!CHECK-NEXT: | | | | | | ExecutionPartConstruct -> ExecutableConstruct -> ActionStmt -> AllocateStmt -!UNPARSE: !$OMP ALLOCATE (w) ALLOCATOR(3_8) -!UNPARSE-NEXT: !$OMP ALLOCATE (xarray) ALLOCATOR(2_8) -!UNPARSE-NEXT: !$OMP ALLOCATE (zarray) ALLOCATOR(1_8) +!UNPARSE: !$OMP ALLOCATE(w) ALLOCATOR(3_8) +!UNPARSE-NEXT: t=2_4 +!UNPARSE-NEXT: z=3_4 +!UNPARSE-NEXT: !$OMP ALLOCATE(xarray) ALLOCATOR(2_8) +!UNPARSE-NEXT: !$OMP ALLOCATE(zarray) ALLOCATOR(1_8) !UNPARSE-NEXT: !$OMP ALLOCATE -!UNPARSE-NEXT: ALLOCATE(w, xarray(4_4), zarray(t,z)) +!UNPARSE-NEXT: ALLOCATE(xarray(4_4), zarray(t,z)) diff --git a/flang/test/Parser/OpenMP/allocate-unparse.f90 b/flang/test/Parser/OpenMP/allocate-unparse.f90 index 94bc2ad..b61a971 100644 --- a/flang/test/Parser/OpenMP/allocate-unparse.f90 +++ b/flang/test/Parser/OpenMP/allocate-unparse.f90 @@ -9,6 +9,7 @@ integer :: a, b, j, m, n, t, x, y, z ! 2.11.3 declarative allocate +!$omp allocate !$omp allocate(x, y) !$omp allocate(x, y) allocator(omp_default_mem_alloc) @@ -28,19 +29,24 @@ integer :: a, b, j, m, n, t, x, y, z !$omp allocate(j) align(16) allocate ( darray(z, t) ) +!$omp allocate + allocate ( darray(a, b) ) end program allocate_unparse -!CHECK:!$OMP ALLOCATE (x,y) -!CHECK:!$OMP ALLOCATE (x,y) ALLOCATOR(omp_default_mem_alloc) -!CHECK:!$OMP ALLOCATE (a,b) +!CHECK:!$OMP ALLOCATE{{[ ]*$}} +!CHECK:!$OMP ALLOCATE(x, y) +!CHECK:!$OMP ALLOCATE(x, y) ALLOCATOR(omp_default_mem_alloc) +!CHECK:!$OMP ALLOCATE(a, b) !CHECK:ALLOCATE(darray(a,b)) !CHECK:!$OMP ALLOCATE ALLOCATOR(omp_default_mem_alloc) !CHECK:ALLOCATE(darray(a,b)) -!CHECK:!$OMP ALLOCATE (a,b) ALLOCATOR(omp_default_mem_alloc) +!CHECK:!$OMP ALLOCATE(a, b) ALLOCATOR(omp_default_mem_alloc) !CHECK:ALLOCATE(darray(a,b)) -!CHECK:!$OMP ALLOCATE (t) ALLOCATOR(omp_const_mem_alloc) -!CHECK:!$OMP ALLOCATE (z) ALLOCATOR(omp_default_mem_alloc) -!CHECK:!$OMP ALLOCATE (m) ALLOCATOR(omp_default_mem_alloc) -!CHECK:!$OMP ALLOCATE (n) -!CHECK:!$OMP ALLOCATE (j) ALIGN(16) +!CHECK:!$OMP ALLOCATE(t) ALLOCATOR(omp_const_mem_alloc) +!CHECK:!$OMP ALLOCATE(z) ALLOCATOR(omp_default_mem_alloc) +!CHECK:!$OMP ALLOCATE(m) ALLOCATOR(omp_default_mem_alloc) +!CHECK:!$OMP ALLOCATE(n) +!CHECK:!$OMP ALLOCATE(j) ALIGN(16) !CHECK:ALLOCATE(darray(z,t)) +!CHECK:!$OMP ALLOCATE{{[ ]*$}} +!CHECK:ALLOCATE(darray(a,b)) diff --git a/flang/test/Parser/OpenMP/allocators-unparse.f90 b/flang/test/Parser/OpenMP/allocators-unparse.f90 index 079d6ac..31c7ed5 100644 --- a/flang/test/Parser/OpenMP/allocators-unparse.f90 +++ b/flang/test/Parser/OpenMP/allocators-unparse.f90 @@ -33,7 +33,7 @@ end subroutine allocate !PARSE-TREE-NEXT: | | OmpClauseList -> OmpClause -> Allocate -> OmpAllocateClause !PARSE-TREE-NEXT: | | | Modifier -> OmpAllocatorSimpleModifier -> Scalar -> Integer -> Expr -> Designator -> DataRef -> Name = 'omp_default_mem_alloc' !PARSE-TREE-NEXT: | | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'arr1' -!PARSE-TREE-NEXT: | | Flags = None +!PARSE-TREE-NEXT: | | Flags = {} !PARSE-TREE-NEXT: | Block !PARSE-TREE-NEXT: | | ExecutionPartConstruct -> ExecutableConstruct -> ActionStmt -> AllocateStmt !PARSE-TREE-NEXT: | | | Allocation @@ -49,7 +49,7 @@ end subroutine allocate !PARSE-TREE-NEXT: | | OmpClause -> Allocate -> OmpAllocateClause !PARSE-TREE-NEXT: | | | Modifier -> OmpAllocatorSimpleModifier -> Scalar -> Integer -> Expr -> Designator -> DataRef -> Name = 'omp_default_mem_alloc' !PARSE-TREE-NEXT: | | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'arr2' -!PARSE-TREE-NEXT: | | Flags = None +!PARSE-TREE-NEXT: | | Flags = {} !PARSE-TREE-NEXT: | Block !PARSE-TREE-NEXT: | | ExecutionPartConstruct -> ExecutableConstruct -> ActionStmt -> AllocateStmt !PARSE-TREE-NEXT: | | | Allocation @@ -61,7 +61,7 @@ end subroutine allocate !PARSE-TREE-NEXT: | | OmpClauseList -> OmpClause -> Allocate -> OmpAllocateClause !PARSE-TREE-NEXT: | | | Modifier -> OmpAlignModifier -> Scalar -> Integer -> Expr -> LiteralConstant -> IntLiteralConstant = '32' !PARSE-TREE-NEXT: | | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'arr2' -!PARSE-TREE-NEXT: | | Flags = None +!PARSE-TREE-NEXT: | | Flags = {} !PARSE-TREE-NEXT: | Block !PARSE-TREE-NEXT: | | ExecutionPartConstruct -> ExecutableConstruct -> ActionStmt -> AllocateStmt !PARSE-TREE-NEXT: | | | Allocation @@ -73,4 +73,4 @@ end subroutine allocate !PARSE-TREE-NEXT: | OmpEndDirective !PARSE-TREE-NEXT: | | OmpDirectiveName -> llvm::omp::Directive = allocators !PARSE-TREE-NEXT: | | OmpClauseList -> -!PARSE-TREE-NEXT: | | Flags = None +!PARSE-TREE-NEXT: | | Flags = {} diff --git a/flang/test/Parser/OpenMP/assumption.f90 b/flang/test/Parser/OpenMP/assumption.f90 index 86cbad9..fd5cfab 100644 --- a/flang/test/Parser/OpenMP/assumption.f90 +++ b/flang/test/Parser/OpenMP/assumption.f90 @@ -43,39 +43,39 @@ end subroutine sub1 !PARSE-TREE: | OmpBeginDirective !PARSE-TREE: | | OmpDirectiveName -> llvm::omp::Directive = assume !PARSE-TREE: | | OmpClauseList -> OmpClause -> NoOpenmp -!PARSE-TREE: | | Flags = None +!PARSE-TREE: | | Flags = {} !PARSE-TREE: | Block !PARSE-TREE: | OmpEndDirective !PARSE-TREE: | | OmpDirectiveName -> llvm::omp::Directive = assume !PARSE-TREE: | | OmpClauseList -> -!PARSE-TREE: | | Flags = None +!PARSE-TREE: | | Flags = {} !PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPAssumeConstruct !PARSE-TREE: | OmpBeginDirective !PARSE-TREE: | | OmpDirectiveName -> llvm::omp::Directive = assume !PARSE-TREE: | | OmpClauseList -> OmpClause -> NoParallelism -!PARSE-TREE: | | Flags = None +!PARSE-TREE: | | Flags = {} !PARSE-TREE: | Block !PARSE-TREE: | OmpEndDirective !PARSE-TREE: | | OmpDirectiveName -> llvm::omp::Directive = assume !PARSE-TREE: | | OmpClauseList -> -!PARSE-TREE: | | Flags = None +!PARSE-TREE: | | Flags = {} !PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPAssumeConstruct !PARSE-TREE: | OmpBeginDirective !PARSE-TREE: | | OmpDirectiveName -> llvm::omp::Directive = assume !PARSE-TREE: | | OmpClauseList -> OmpClause -> NoOpenmpRoutines -!PARSE-TREE: | | Flags = None +!PARSE-TREE: | | Flags = {} !PARSE-TREE: | Block !PARSE-TREE: | OmpEndDirective !PARSE-TREE: | | OmpDirectiveName -> llvm::omp::Directive = assume !PARSE-TREE: | | OmpClauseList -> -!PARSE-TREE: | | Flags = None +!PARSE-TREE: | | Flags = {} !PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPAssumeConstruct !PARSE-TREE: | OmpBeginDirective !PARSE-TREE: | | OmpDirectiveName -> llvm::omp::Directive = assume !PARSE-TREE: | | OmpClauseList -> OmpClause -> Absent -> OmpAbsentClause -> llvm::omp::Directive = allocate !PARSE-TREE: | | OmpClause -> Contains -> OmpContainsClause -> llvm::omp::Directive = workshare !PARSE-TREE: | | llvm::omp::Directive = task -!PARSE-TREE: | | Flags = None +!PARSE-TREE: | | Flags = {} !PARSE-TREE: | Block !PARSE-TREE: | | ExecutionPartConstruct -> ExecutableConstruct -> BlockConstruct !PARSE-TREE: | | | BlockStmt -> @@ -89,7 +89,7 @@ end subroutine sub1 !PARSE-TREE: | | OmpClauseList -> OmpClause -> Holds -> OmpHoldsClause -> Expr -> EQ !PARSE-TREE: | | | Expr -> LiteralConstant -> IntLiteralConstant = '1' !PARSE-TREE: | | | Expr -> LiteralConstant -> IntLiteralConstant = '1' -!PARSE-TREE: | | Flags = None +!PARSE-TREE: | | Flags = {} !PARSE-TREE: | Block !PARSE-TREE: | | ExecutionPartConstruct -> ExecutableConstruct -> BlockConstruct !PARSE-TREE: | | | BlockStmt -> @@ -124,7 +124,7 @@ end subroutine sub2 !PARSE-TREE: | OmpBeginDirective !PARSE-TREE: | | OmpDirectiveName -> llvm::omp::Directive = assume !PARSE-TREE: | | OmpClauseList -> OmpClause -> NoOpenmp -!PARSE-TREE: | | Flags = None +!PARSE-TREE: | | Flags = {} !PARSE-TREE: | Block !PARSE-TREE: | | ExecutionPartConstruct -> ExecutableConstruct -> ActionStmt -> AssignmentStmt !PARSE-TREE: | | | Variable -> Designator -> DataRef -> Name = 'r' @@ -134,7 +134,7 @@ end subroutine sub2 !PARSE-TREE: | OmpEndDirective !PARSE-TREE: | | OmpDirectiveName -> llvm::omp::Directive = assume !PARSE-TREE: | | OmpClauseList -> -!PARSE-TREE: | | Flags = None +!PARSE-TREE: | | Flags = {} program p !$omp assumes no_openmp @@ -147,5 +147,5 @@ end program p !PARSE-TREE: OpenMPDeclarativeConstruct -> OpenMPDeclarativeAssumes -> OmpDirectiveSpecification !PARSE-TREE: | OmpDirectiveName -> llvm::omp::Directive = assumes !PARSE-TREE: | OmpClauseList -> OmpClause -> NoOpenmp -!PARSE-TREE: | Flags = None +!PARSE-TREE: | Flags = {} !PARSE-TREE: ImplicitPart -> diff --git a/flang/test/Parser/OpenMP/atomic-compare.f90 b/flang/test/Parser/OpenMP/atomic-compare.f90 index 9b9c4f0..7e80b9c 100644 --- a/flang/test/Parser/OpenMP/atomic-compare.f90 +++ b/flang/test/Parser/OpenMP/atomic-compare.f90 @@ -20,7 +20,7 @@ end !PARSE-TREE: | | OmpDirectiveName -> llvm::omp::Directive = atomic !PARSE-TREE: | | OmpClauseList -> OmpClause -> Update -> !PARSE-TREE: | | OmpClause -> Compare -!PARSE-TREE: | | Flags = None +!PARSE-TREE: | | Flags = {} !PARSE-TREE: | Block !PARSE-TREE: | | ExecutionPartConstruct -> ExecutableConstruct -> ActionStmt -> IfStmt !PARSE-TREE: | | | Scalar -> Logical -> Expr = 'x<a' @@ -58,7 +58,7 @@ end !PARSE-TREE: | | OmpDirectiveName -> llvm::omp::Directive = atomic !PARSE-TREE: | | OmpClauseList -> OmpClause -> Update -> !PARSE-TREE: | | OmpClause -> Compare -!PARSE-TREE: | | Flags = None +!PARSE-TREE: | | Flags = {} !PARSE-TREE: | Block !PARSE-TREE: | | ExecutionPartConstruct -> ExecutableConstruct -> IfConstruct !PARSE-TREE: | | | IfThenStmt @@ -112,7 +112,7 @@ end !PARSE-TREE: | | OmpDirectiveName -> llvm::omp::Directive = atomic !PARSE-TREE: | | OmpClauseList -> OmpClause -> Update -> !PARSE-TREE: | | OmpClause -> Compare -!PARSE-TREE: | | Flags = None +!PARSE-TREE: | | Flags = {} !PARSE-TREE: | Block !PARSE-TREE: | | ExecutionPartConstruct -> ExecutableConstruct -> IfConstruct !PARSE-TREE: | | | IfThenStmt @@ -150,7 +150,7 @@ end !PARSE-TREE: | | OmpClauseList -> OmpClause -> Update -> !PARSE-TREE: | | OmpClause -> Capture !PARSE-TREE: | | OmpClause -> Compare -!PARSE-TREE: | | Flags = None +!PARSE-TREE: | | Flags = {} !PARSE-TREE: | Block !PARSE-TREE: | | ExecutionPartConstruct -> ExecutableConstruct -> ActionStmt -> AssignmentStmt = 'v=x' !PARSE-TREE: | | | Variable = 'v' @@ -172,7 +172,7 @@ end !PARSE-TREE: | OmpEndDirective !PARSE-TREE: | | OmpDirectiveName -> llvm::omp::Directive = atomic !PARSE-TREE: | | OmpClauseList -> -!PARSE-TREE: | | Flags = None +!PARSE-TREE: | | Flags = {} subroutine g01(a, b) integer :: a, b @@ -202,7 +202,7 @@ end !PARSE-TREE: | | OmpClauseList -> OmpClause -> Update -> !PARSE-TREE: | | OmpClause -> Capture !PARSE-TREE: | | OmpClause -> Compare -!PARSE-TREE: | | Flags = None +!PARSE-TREE: | | Flags = {} !PARSE-TREE: | Block !PARSE-TREE: | | ExecutionPartConstruct -> ExecutableConstruct -> ActionStmt -> AssignmentStmt = 'v=x' !PARSE-TREE: | | | Variable = 'v' @@ -227,7 +227,7 @@ end !PARSE-TREE: | OmpEndDirective !PARSE-TREE: | | OmpDirectiveName -> llvm::omp::Directive = atomic !PARSE-TREE: | | OmpClauseList -> -!PARSE-TREE: | | Flags = None +!PARSE-TREE: | | Flags = {} subroutine g02(a, b) integer :: a, b @@ -259,7 +259,7 @@ end !PARSE-TREE: | | OmpClauseList -> OmpClause -> Update -> !PARSE-TREE: | | OmpClause -> Capture !PARSE-TREE: | | OmpClause -> Compare -!PARSE-TREE: | | Flags = None +!PARSE-TREE: | | Flags = {} !PARSE-TREE: | Block !PARSE-TREE: | | ExecutionPartConstruct -> ExecutableConstruct -> IfConstruct !PARSE-TREE: | | | IfThenStmt @@ -287,4 +287,4 @@ end !PARSE-TREE: | OmpEndDirective !PARSE-TREE: | | OmpDirectiveName -> llvm::omp::Directive = atomic !PARSE-TREE: | | OmpClauseList -> -!PARSE-TREE: | | Flags = None +!PARSE-TREE: | | Flags = {} diff --git a/flang/test/Parser/OpenMP/atomic-end.f90 b/flang/test/Parser/OpenMP/atomic-end.f90 index b971bb6f..fd1f444 100644 --- a/flang/test/Parser/OpenMP/atomic-end.f90 +++ b/flang/test/Parser/OpenMP/atomic-end.f90 @@ -19,7 +19,7 @@ end !PARSE-TREE: | OmpBeginDirective !PARSE-TREE: | | OmpDirectiveName -> llvm::omp::Directive = atomic !PARSE-TREE: | | OmpClauseList -> OmpClause -> Read -!PARSE-TREE: | | Flags = None +!PARSE-TREE: | | Flags = {} !PARSE-TREE: | Block !PARSE-TREE: | | ExecutionPartConstruct -> ExecutableConstruct -> ActionStmt -> AssignmentStmt = 'v=x' !PARSE-TREE: | | | Variable = 'v' @@ -29,7 +29,7 @@ end !PARSE-TREE: | OmpEndDirective !PARSE-TREE: | | OmpDirectiveName -> llvm::omp::Directive = atomic !PARSE-TREE: | | OmpClauseList -> -!PARSE-TREE: | | Flags = None +!PARSE-TREE: | | Flags = {} subroutine f01 @@ -50,7 +50,7 @@ end !PARSE-TREE: | OmpBeginDirective !PARSE-TREE: | | OmpDirectiveName -> llvm::omp::Directive = atomic !PARSE-TREE: | | OmpClauseList -> OmpClause -> Read -!PARSE-TREE: | | Flags = None +!PARSE-TREE: | | Flags = {} !PARSE-TREE: | Block !PARSE-TREE: | | ExecutionPartConstruct -> ExecutableConstruct -> ActionStmt -> AssignmentStmt = 'v=x' !PARSE-TREE: | | | Variable = 'v' @@ -60,4 +60,4 @@ end !PARSE-TREE: | OmpEndDirective !PARSE-TREE: | | OmpDirectiveName -> llvm::omp::Directive = atomic !PARSE-TREE: | | OmpClauseList -> -!PARSE-TREE: | | Flags = None +!PARSE-TREE: | | Flags = {} diff --git a/flang/test/Parser/OpenMP/atomic-label-do.f90 b/flang/test/Parser/OpenMP/atomic-label-do.f90 new file mode 100644 index 0000000..1c7037f --- /dev/null +++ b/flang/test/Parser/OpenMP/atomic-label-do.f90 @@ -0,0 +1,39 @@ +!RUN: %flang_fc1 -fdebug-unparse -fopenmp %s | FileCheck --ignore-case --check-prefix="UNPARSE" %s +!RUN: %flang_fc1 -fdebug-dump-parse-tree -fopenmp %s | FileCheck --check-prefix="PARSE-TREE" %s + +subroutine f + integer :: i, x + do 100 i = 1, 10 + !$omp atomic write + 100 x = i +end + +!UNPARSE: SUBROUTINE f +!UNPARSE: INTEGER i, x +!UNPARSE: DO i=1_4,10_4 +!UNPARSE: !$OMP ATOMIC WRITE +!UNPARSE: 100 x=i +!UNPARSE: END DO +!UNPARSE: END SUBROUTINE + +!PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> DoConstruct +!PARSE-TREE: | NonLabelDoStmt +!PARSE-TREE: | | LoopControl -> LoopBounds +!PARSE-TREE: | | | Scalar -> Name = 'i' +!PARSE-TREE: | | | Scalar -> Expr = '1_4' +!PARSE-TREE: | | | | LiteralConstant -> IntLiteralConstant = '1' +!PARSE-TREE: | | | Scalar -> Expr = '10_4' +!PARSE-TREE: | | | | LiteralConstant -> IntLiteralConstant = '10' +!PARSE-TREE: | Block +!PARSE-TREE: | | ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPAtomicConstruct +!PARSE-TREE: | | | OmpBeginDirective +!PARSE-TREE: | | | | OmpDirectiveName -> llvm::omp::Directive = atomic +!PARSE-TREE: | | | | OmpClauseList -> OmpClause -> Write +!PARSE-TREE: | | | | Flags = {CrossesLabelDo} +!PARSE-TREE: | | | Block +!PARSE-TREE: | | | | ExecutionPartConstruct -> ExecutableConstruct -> ActionStmt -> AssignmentStmt = 'x=i' +!PARSE-TREE: | | | | | Variable = 'x' +!PARSE-TREE: | | | | | | Designator -> DataRef -> Name = 'x' +!PARSE-TREE: | | | | | Expr = 'i' +!PARSE-TREE: | | | | | | Designator -> DataRef -> Name = 'i' +!PARSE-TREE: | EndDoStmt -> diff --git a/flang/test/Parser/OpenMP/atomic-unparse.f90 b/flang/test/Parser/OpenMP/atomic-unparse.f90 index 16dc7a1..9a21d2c 100644 --- a/flang/test/Parser/OpenMP/atomic-unparse.f90 +++ b/flang/test/Parser/OpenMP/atomic-unparse.f90 @@ -151,7 +151,7 @@ program main if (i .eq. j + 1) then i = j end if - + !$omp atomic compare acquire if (i .eq. j) then i = k @@ -178,7 +178,7 @@ program main if (i .eq. k) then i = j end if - + !ATOMIC !$omp atomic i = j diff --git a/flang/test/Parser/OpenMP/bind-clause.f90 b/flang/test/Parser/OpenMP/bind-clause.f90 index a4fb3aa..af89719 100644 --- a/flang/test/Parser/OpenMP/bind-clause.f90 +++ b/flang/test/Parser/OpenMP/bind-clause.f90 @@ -21,6 +21,6 @@ end !PARSE-TREE: | OmpBeginLoopDirective !PARSE-TREE: | | OmpDirectiveName -> llvm::omp::Directive = loop !PARSE-TREE: | | OmpClauseList -> OmpClause -> Bind -> OmpBindClause -> Binding = Parallel -!PARSE-TREE: | | Flags = None -!PARSE-TREE: | DoConstruct +!PARSE-TREE: | | Flags = {} +!PARSE-TREE: | ExecutionPartConstruct -> ExecutableConstruct -> DoConstruct diff --git a/flang/test/Parser/OpenMP/construct-prefix-conflict.f90 b/flang/test/Parser/OpenMP/construct-prefix-conflict.f90 index 4573a83..d344f9a 100644 --- a/flang/test/Parser/OpenMP/construct-prefix-conflict.f90 +++ b/flang/test/Parser/OpenMP/construct-prefix-conflict.f90 @@ -79,7 +79,7 @@ end !PARSE-TREE: | | | OmpClauseList -> OmpClause -> Map -> OmpMapClause !PARSE-TREE: | | | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'x' !PARSE-TREE: | | | | bool = 'true' -!PARSE-TREE: | | | Flags = None +!PARSE-TREE: | | | Flags = {} !PARSE-TREE: | | ExecutionPartConstruct -> ExecutableConstruct -> ActionStmt -> AssignmentStmt !PARSE-TREE: | | | Variable -> Designator -> DataRef -> Name = 'x' !PARSE-TREE: | | | Expr -> Add @@ -118,7 +118,7 @@ end !PARSE-TREE: | | | OmpClauseList -> OmpClause -> Map -> OmpMapClause !PARSE-TREE: | | | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'x' !PARSE-TREE: | | | | bool = 'true' -!PARSE-TREE: | | | Flags = None +!PARSE-TREE: | | | Flags = {} !PARSE-TREE: | | ExecutionPartConstruct -> ExecutableConstruct -> ActionStmt -> AssignmentStmt !PARSE-TREE: | | | Variable -> Designator -> DataRef -> Name = 'x' !PARSE-TREE: | | | Expr -> Add @@ -157,7 +157,7 @@ end !PARSE-TREE: | | | OmpClauseList -> OmpClause -> To -> OmpToClause !PARSE-TREE: | | | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'x' !PARSE-TREE: | | | | bool = 'true' -!PARSE-TREE: | | | Flags = None +!PARSE-TREE: | | | Flags = {} !PARSE-TREE: | | ExecutionPartConstruct -> ExecutableConstruct -> ActionStmt -> AssignmentStmt !PARSE-TREE: | | | Variable -> Designator -> DataRef -> Name = 'x' !PARSE-TREE: | | | Expr -> Add diff --git a/flang/test/Parser/OpenMP/cross-label-do.f90 b/flang/test/Parser/OpenMP/cross-label-do.f90 new file mode 100644 index 0000000..f1a406c --- /dev/null +++ b/flang/test/Parser/OpenMP/cross-label-do.f90 @@ -0,0 +1,48 @@ +!RUN: %flang_fc1 -fdebug-unparse -fopenmp %s | FileCheck --ignore-case --check-prefix="UNPARSE" %s +!RUN: %flang_fc1 -fdebug-dump-parse-tree -fopenmp %s | FileCheck --check-prefix="PARSE-TREE" %s + +subroutine f00 + integer :: i, j + do 100 i = 1,10 +!$omp do + do 100 j = 1,10 + 100 continue +end + +!UNPARSE: SUBROUTINE f00 +!UNPARSE: INTEGER i, j +!UNPARSE: DO i=1_4,10_4 +!UNPARSE: !$OMP DO +!UNPARSE: DO j=1_4,10_4 +!UNPARSE: 100 CONTINUE +!UNPARSE: END DO +!UNPARSE: END DO +!UNPARSE: END SUBROUTINE + +!PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> DoConstruct +!PARSE-TREE: | NonLabelDoStmt +!PARSE-TREE: | | LoopControl -> LoopBounds +!PARSE-TREE: | | | Scalar -> Name = 'i' +!PARSE-TREE: | | | Scalar -> Expr = '1_4' +!PARSE-TREE: | | | | LiteralConstant -> IntLiteralConstant = '1' +!PARSE-TREE: | | | Scalar -> Expr = '10_4' +!PARSE-TREE: | | | | LiteralConstant -> IntLiteralConstant = '10' +!PARSE-TREE: | Block +!PARSE-TREE: | | ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPLoopConstruct +!PARSE-TREE: | | | OmpBeginLoopDirective +!PARSE-TREE: | | | | OmpDirectiveName -> llvm::omp::Directive = do +!PARSE-TREE: | | | | OmpClauseList -> +!PARSE-TREE: | | | | Flags = {CrossesLabelDo} +!PARSE-TREE: | | | Block +!PARSE-TREE: | | | | ExecutionPartConstruct -> ExecutableConstruct -> DoConstruct +!PARSE-TREE: | | | | | NonLabelDoStmt +!PARSE-TREE: | | | | | | LoopControl -> LoopBounds +!PARSE-TREE: | | | | | | | Scalar -> Name = 'j' +!PARSE-TREE: | | | | | | | Scalar -> Expr = '1_4' +!PARSE-TREE: | | | | | | | | LiteralConstant -> IntLiteralConstant = '1' +!PARSE-TREE: | | | | | | | Scalar -> Expr = '10_4' +!PARSE-TREE: | | | | | | | | LiteralConstant -> IntLiteralConstant = '10' +!PARSE-TREE: | | | | | Block +!PARSE-TREE: | | | | | | ExecutionPartConstruct -> ExecutableConstruct -> ActionStmt -> ContinueStmt +!PARSE-TREE: | | | | | EndDoStmt -> +!PARSE-TREE: | EndDoStmt -> diff --git a/flang/test/Parser/OpenMP/declare-mapper-unparse.f90 b/flang/test/Parser/OpenMP/declare-mapper-unparse.f90 index b53bf5c..9da6674 100644 --- a/flang/test/Parser/OpenMP/declare-mapper-unparse.f90 +++ b/flang/test/Parser/OpenMP/declare-mapper-unparse.f90 @@ -29,7 +29,7 @@ program main !PARSE-TREE: OpenMPDeclareMapperConstruct !PARSE-TREE: OmpMapperSpecifier -!PARSE-TREE: string = 'ty.omp.default.mapper' +!PARSE-TREE: string = 'ty_omp_default_mapper' !PARSE-TREE: TypeSpec -> DerivedTypeSpec !PARSE-TREE: Name = 'ty' !PARSE-TREE: Name = 'mapped' diff --git a/flang/test/Parser/OpenMP/declare-reduction-multi.f90 b/flang/test/Parser/OpenMP/declare-reduction-multi.f90 index 8856661..7e462e0 100644 --- a/flang/test/Parser/OpenMP/declare-reduction-multi.f90 +++ b/flang/test/Parser/OpenMP/declare-reduction-multi.f90 @@ -63,7 +63,7 @@ program omp_examples !PARSE-TREE: | | | | | Name = 'r' !PARSE-TREE: | | | Expr = '0_4' !PARSE-TREE: | | | | LiteralConstant -> IntLiteralConstant = '0' -!PARSE-TREE: | Flags = None +!PARSE-TREE: | Flags = {} !$omp declare reduction(*:tt:omp_out%r = omp_out%r * omp_in%r) initializer(omp_priv%r = 1) !CHECK-NEXT: !$OMP DECLARE REDUCTION(*:tt: omp_out%r = omp_out%r * omp_in%r) INITIALIZER(om& @@ -103,7 +103,7 @@ program omp_examples !PARSE-TREE: | | | | | Name = 'r' !PARSE-TREE: | | | Expr = '1_4' !PARSE-TREE: | | | | LiteralConstant -> IntLiteralConstant = '1' -!PARSE-TREE: | Flags = None +!PARSE-TREE: | Flags = {} !$omp declare reduction(max:tt:omp_out = mymax(omp_out, omp_in)) initializer(omp_priv%r = 0) !CHECK-NEXT: !$OMP DECLARE REDUCTION(max:tt: omp_out = mymax(omp_out, omp_in)) INITIALIZER(& @@ -140,7 +140,7 @@ program omp_examples !PARSE-TREE: | | | | | Name = 'r' !PARSE-TREE: | | | Expr = '0_4' !PARSE-TREE: | | | | LiteralConstant -> IntLiteralConstant = '0' -!PARSE-TREE: | Flags = None +!PARSE-TREE: | Flags = {} !$omp declare reduction(min:tt:omp_out%r = min(omp_out%r, omp_in%r)) initializer(omp_priv%r = 1) !CHECK-NEXT: !$OMP DECLARE REDUCTION(min:tt: omp_out%r = min(omp_out%r, omp_in%r)) INITIALI& @@ -183,7 +183,7 @@ program omp_examples !PARSE-TREE: | | | | | Name = 'r' !PARSE-TREE: | | | Expr = '1_4' !PARSE-TREE: | | | | LiteralConstant -> IntLiteralConstant = '1' -!PARSE-TREE: | Flags = None +!PARSE-TREE: | Flags = {} call random_number(values%r) @@ -197,8 +197,9 @@ program omp_examples !PARSE-TREE: | | OmpClauseList -> OmpClause -> Reduction -> OmpReductionClause !PARSE-TREE: | | | Modifier -> OmpReductionIdentifier -> DefinedOperator -> IntrinsicOperator = Add !PARSE-TREE: | | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'sum' -!PARSE-TREE: | | Flags = None -!PARSE-TREE: | DoConstruct +!PARSE-TREE: | | Flags = {} +!PARSE-TREE: | Block +!PARSE-TREE: | | ExecutionPartConstruct -> ExecutableConstruct -> DoConstruct do i = 1, n sum%r = sum%r + values(i)%r @@ -214,8 +215,9 @@ program omp_examples !PARSE-TREE: | | OmpClauseList -> OmpClause -> Reduction -> OmpReductionClause !PARSE-TREE: | | | Modifier -> OmpReductionIdentifier -> DefinedOperator -> IntrinsicOperator = Multiply !PARSE-TREE: | | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'prod' -!PARSE-TREE: | | Flags = None -!PARSE-TREE: | DoConstruct +!PARSE-TREE: | | Flags = {} +!PARSE-TREE: | Block +!PARSE-TREE: | | ExecutionPartConstruct -> ExecutableConstruct -> DoConstruct do i = 1, n prod%r = prod%r * (values(i)%r+0.6) @@ -231,8 +233,9 @@ program omp_examples !PARSE-TREE: | | OmpClauseList -> OmpClause -> Reduction -> OmpReductionClause !PARSE-TREE: | | | Modifier -> OmpReductionIdentifier -> ProcedureDesignator -> Name = 'max' !PARSE-TREE: | | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'big' -!PARSE-TREE: | | Flags = None -!PARSE-TREE: | DoConstruct +!PARSE-TREE: | | Flags = {} +!PARSE-TREE: | Block +!PARSE-TREE: | | ExecutionPartConstruct -> ExecutableConstruct -> DoConstruct do i = 1, n big = mymax(values(i), big) @@ -248,8 +251,9 @@ program omp_examples !PARSE-TREE: | | OmpClauseList -> OmpClause -> Reduction -> OmpReductionClause !PARSE-TREE: | | | Modifier -> OmpReductionIdentifier -> ProcedureDesignator -> Name = 'min' !PARSE-TREE: | | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'small' -!PARSE-TREE: | | Flags = None -!PARSE-TREE: | DoConstruct +!PARSE-TREE: | | Flags = {} +!PARSE-TREE: | Block +!PARSE-TREE: | | ExecutionPartConstruct -> ExecutableConstruct -> DoConstruct do i = 1, n small%r = min(values(i)%r, small%r) diff --git a/flang/test/Parser/OpenMP/declare-reduction-operator.f90 b/flang/test/Parser/OpenMP/declare-reduction-operator.f90 index 0d337c1..c104e94 100644 --- a/flang/test/Parser/OpenMP/declare-reduction-operator.f90 +++ b/flang/test/Parser/OpenMP/declare-reduction-operator.f90 @@ -11,7 +11,7 @@ subroutine reduce_1 ( n, tts ) real(8) :: x real(8) :: y end type - + integer :: n type(tt) :: tts(n) type(tt2) :: tts2(n) @@ -73,10 +73,10 @@ subroutine reduce_1 ( n, tts ) !PARSE-TREE: | | | | | ComponentSpec !PARSE-TREE: | | | | | | ComponentDataSource -> Expr = '0_4' !PARSE-TREE: | | | | | | | LiteralConstant -> IntLiteralConstant = '0' -!PARSE-TREE: | Flags = None +!PARSE-TREE: | Flags = {} !$omp declare reduction(+ : tt : omp_out = tt(omp_out%x - omp_in%x , omp_out%y - omp_in%y)) initializer(omp_priv = tt(0,0)) - + !CHECK: !$OMP DECLARE REDUCTION(+:tt2: omp_out = tt2(omp_out%x - omp_in%x , omp_out%y & !CHECK: !$OMP&- omp_in%y)) INITIALIZER(omp_priv = tt2(0,0)) @@ -134,9 +134,9 @@ subroutine reduce_1 ( n, tts ) !PARSE-TREE: | | | | | ComponentSpec !PARSE-TREE: | | | | | | ComponentDataSource -> Expr = '0_4' !PARSE-TREE: | | | | | | | LiteralConstant -> IntLiteralConstant = '0' -!PARSE-TREE: | Flags = None +!PARSE-TREE: | Flags = {} !$omp declare reduction(+ :tt2 : omp_out = tt2(omp_out%x - omp_in%x , omp_out%y - omp_in%y)) initializer(omp_priv = tt2(0,0)) - + type(tt) :: diffp = tt( 0, 0 ) type(tt2) :: diffp2 = tt2( 0, 0 ) integer :: i diff --git a/flang/test/Parser/OpenMP/declare-reduction-unparse.f90 b/flang/test/Parser/OpenMP/declare-reduction-unparse.f90 index 7897eb0..6ca7b0f 100644 --- a/flang/test/Parser/OpenMP/declare-reduction-unparse.f90 +++ b/flang/test/Parser/OpenMP/declare-reduction-unparse.f90 @@ -52,7 +52,7 @@ function func(x, n, init) !PARSE-TREE: | | | | ActualArgSpec !PARSE-TREE: | | | | | ActualArg -> Expr = '0_4' !PARSE-TREE: | | | | | | LiteralConstant -> IntLiteralConstant = '0' -!PARSE-TREE: | Flags = None +!PARSE-TREE: | Flags = {} res=init !$omp simd reduction(red_add:res) @@ -69,8 +69,9 @@ function func(x, n, init) !PARSE-TREE: | | OmpClauseList -> OmpClause -> Reduction -> OmpReductionClause !PARSE-TREE: | | | Modifier -> OmpReductionIdentifier -> ProcedureDesignator -> Name = 'red_add' !PARSE-TREE: | | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'res' -!PARSE-TREE: | | Flags = None -!PARSE-TREE: | DoConstruct +!PARSE-TREE: | | Flags = {} +!PARSE-TREE: | Block +!PARSE-TREE: | | ExecutionPartConstruct -> ExecutableConstruct -> DoConstruct do i=1,n res=res+x(i) @@ -118,4 +119,4 @@ end program main !PARSE-TREE: | | | | Designator -> DataRef -> Name = 'omp_priv' !PARSE-TREE: | | | Expr = '0_4' !PARSE-TREE: | | | | LiteralConstant -> IntLiteralConstant = '0' -!PARSE-TREE: | Flags = None +!PARSE-TREE: | Flags = {} diff --git a/flang/test/Parser/OpenMP/declare-target-indirect-tree.f90 b/flang/test/Parser/OpenMP/declare-target-indirect-tree.f90 index 16dc4eb..e2645ba 100644 --- a/flang/test/Parser/OpenMP/declare-target-indirect-tree.f90 +++ b/flang/test/Parser/OpenMP/declare-target-indirect-tree.f90 @@ -20,7 +20,7 @@ contains !CHECK-NEXT: | OmpClause -> Indirect -> OmpIndirectClause -> Scalar -> Logical -> Expr = '.true._4' !CHECK-NEXT: | | LiteralConstant -> LogicalLiteralConstant !CHECK-NEXT: | | | bool = 'true' - !CHECK-NEXT: | Flags = None + !CHECK-NEXT: | Flags = {} character(1) :: i i = 'a' return @@ -33,7 +33,7 @@ contains !CHECK-NEXT: | OmpClauseList -> OmpClause -> Enter -> OmpEnterClause !CHECK-NEXT: | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'func2' !CHECK-NEXT: | OmpClause -> Indirect -> OmpIndirectClause -> - !CHECK-NEXT: | Flags = None + !CHECK-NEXT: | Flags = {} character(1) :: i i = 'b' return diff --git a/flang/test/Parser/OpenMP/declare-target-to-clause.f90 b/flang/test/Parser/OpenMP/declare-target-to-clause.f90 index 8198f44..efcdc44 100644 --- a/flang/test/Parser/OpenMP/declare-target-to-clause.f90 +++ b/flang/test/Parser/OpenMP/declare-target-to-clause.f90 @@ -18,4 +18,4 @@ end !PARSE-TREE: | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'x' !PARSE-TREE: | | OmpObject -> Designator -> DataRef -> Name = 'y' !PARSE-TREE: | | bool = 'true' -!PARSE-TREE: | Flags = None +!PARSE-TREE: | Flags = {} diff --git a/flang/test/Parser/OpenMP/declare-variant.f90 b/flang/test/Parser/OpenMP/declare-variant.f90 index f5c34ab..07f65be 100644 --- a/flang/test/Parser/OpenMP/declare-variant.f90 +++ b/flang/test/Parser/OpenMP/declare-variant.f90 @@ -13,7 +13,7 @@ subroutine sub0 !PARSE-TREE: | | OmpTraitSetSelectorName -> Value = Construct !PARSE-TREE: | | OmpTraitSelector !PARSE-TREE: | | | OmpTraitSelectorName -> llvm::omp::Directive = parallel -!PARSE-TREE: | Flags = None +!PARSE-TREE: | Flags = {} !$omp declare variant (sub:vsub) match (construct={parallel}) contains @@ -43,7 +43,7 @@ contains !PARSE-TREE: | | OmpTraitSetSelectorName -> Value = Construct !PARSE-TREE: | | OmpTraitSelector !PARSE-TREE: | | | OmpTraitSelectorName -> llvm::omp::Directive = dispatch -!PARSE-TREE: | Flags = None +!PARSE-TREE: | Flags = {} !$omp declare variant(vsub), match(construct={dispatch}) integer, value :: v1 @@ -75,7 +75,7 @@ contains !PARSE-TREE: | | | OmpTraitSelectorName -> llvm::omp::Directive = dispatch !PARSE-TREE: | OmpClause -> AppendArgs -> OmpAppendArgsClause -> OmpAppendOp -> OmpInteropType -> Value = Target !PARSE-TREE: | OmpAppendOp -> OmpInteropType -> Value = Target -!PARSE-TREE: | Flags = None +!PARSE-TREE: | Flags = {} !$omp declare variant(vsub), match(construct={dispatch}), append_args (interop(target), interop(target)) integer, value :: v1 @@ -107,7 +107,7 @@ contains !PARSE-TREE: | OmpClause -> AdjustArgs -> OmpAdjustArgsClause !PARSE-TREE: | | OmpAdjustOp -> Value = Need_Device_Ptr !PARSE-TREE: | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'v2' -!PARSE-TREE: | Flags = None +!PARSE-TREE: | Flags = {} !$omp declare variant(vsub) match ( construct = { dispatch } ) adjust_args(nothing : v1 ) adjust_args(need_device_ptr : v2) end @@ -121,7 +121,7 @@ subroutine f y = 2 !omp simd call f2(x, y) - !omp end simd + !omp end simd contains subroutine f1 (x, y) real :: x, y @@ -143,4 +143,4 @@ end subroutine !PARSE-TREE: | | | OmpTraitSelectorName -> Value = Simd !PARSE-TREE: | | | Properties !PARSE-TREE: | | | | OmpTraitProperty -> OmpClause -> Uniform -> Name = 'y' -!PARSE-TREE: | Flags = None +!PARSE-TREE: | Flags = {} diff --git a/flang/test/Parser/OpenMP/declare_target-device_type.f90 b/flang/test/Parser/OpenMP/declare_target-device_type.f90 index 7df7962..a505b91 100644 --- a/flang/test/Parser/OpenMP/declare_target-device_type.f90 +++ b/flang/test/Parser/OpenMP/declare_target-device_type.f90 @@ -10,7 +10,7 @@ subroutine openmp_declare_target !PARSE-TREE: | OmpClauseList -> OmpClause -> DeviceType -> OmpDeviceTypeClause -> DeviceTypeDescription = Host !PARSE-TREE: | OmpClause -> Enter -> OmpEnterClause !PARSE-TREE: | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'x' -!PARSE-TREE: | Flags = None +!PARSE-TREE: | Flags = {} !$omp declare target device_type(host) enter(x) !CHECK: !$omp declare target device_type(nohost) enter(x) @@ -20,7 +20,7 @@ subroutine openmp_declare_target !PARSE-TREE: | OmpClauseList -> OmpClause -> DeviceType -> OmpDeviceTypeClause -> DeviceTypeDescription = Nohost !PARSE-TREE: | OmpClause -> Enter -> OmpEnterClause !PARSE-TREE: | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'x' -!PARSE-TREE: | Flags = None +!PARSE-TREE: | Flags = {} !$omp declare target device_type(nohost) enter(x) !CHECK: !$omp declare target device_type(any) enter(x) @@ -30,7 +30,7 @@ subroutine openmp_declare_target !PARSE-TREE: | OmpClauseList -> OmpClause -> DeviceType -> OmpDeviceTypeClause -> DeviceTypeDescription = Any !PARSE-TREE: | OmpClause -> Enter -> OmpEnterClause !PARSE-TREE: | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'x' -!PARSE-TREE: | Flags = None +!PARSE-TREE: | Flags = {} !$omp declare target device_type(any) enter(x) !CHECK: !$omp declare target device_type(host) to(x) @@ -41,7 +41,7 @@ subroutine openmp_declare_target !PARSE-TREE: | OmpClause -> To -> OmpToClause !PARSE-TREE: | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'x' !PARSE-TREE: | | bool = 'true' -!PARSE-TREE: | Flags = None +!PARSE-TREE: | Flags = {} !$omp declare target device_type(host) to(x) !CHECK: !$omp declare target device_type(nohost) to(x) @@ -52,7 +52,7 @@ subroutine openmp_declare_target !PARSE-TREE: | OmpClause -> To -> OmpToClause !PARSE-TREE: | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'x' !PARSE-TREE: | | bool = 'true' -!PARSE-TREE: | Flags = None +!PARSE-TREE: | Flags = {} !$omp declare target device_type(nohost) to(x) !CHECK: !$omp declare target device_type(any) to(x) @@ -63,7 +63,7 @@ subroutine openmp_declare_target !PARSE-TREE: | OmpClause -> To -> OmpToClause !PARSE-TREE: | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'x' !PARSE-TREE: | | bool = 'true' -!PARSE-TREE: | Flags = None +!PARSE-TREE: | Flags = {} !$omp declare target device_type(any) to(x) !CHECK: !$omp declare target device_type(host) enter(y) to(x) @@ -76,7 +76,7 @@ subroutine openmp_declare_target !PARSE-TREE: | OmpClause -> To -> OmpToClause !PARSE-TREE: | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'x' !PARSE-TREE: | | bool = 'true' -!PARSE-TREE: | Flags = None +!PARSE-TREE: | Flags = {} !$omp declare target device_type(host) enter(y) to(x) !CHECK: !$omp declare target device_type(nohost) enter(y) to(x) @@ -89,7 +89,7 @@ subroutine openmp_declare_target !PARSE-TREE: | OmpClause -> To -> OmpToClause !PARSE-TREE: | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'x' !PARSE-TREE: | | bool = 'true' -!PARSE-TREE: | Flags = None +!PARSE-TREE: | Flags = {} !$omp declare target device_type(nohost) enter(y) to(x) !CHECK: !$omp declare target device_type(any) enter(y) to(x) @@ -102,7 +102,7 @@ subroutine openmp_declare_target !PARSE-TREE: | OmpClause -> To -> OmpToClause !PARSE-TREE: | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'x' !PARSE-TREE: | | bool = 'true' -!PARSE-TREE: | Flags = None +!PARSE-TREE: | Flags = {} !$omp declare target device_type(any) enter(y) to(x) integer :: a(1024), i diff --git a/flang/test/Parser/OpenMP/defaultmap-unparse.f90 b/flang/test/Parser/OpenMP/defaultmap-unparse.f90 index fa05780..6e4d1fe 100644 --- a/flang/test/Parser/OpenMP/defaultmap-unparse.f90 +++ b/flang/test/Parser/OpenMP/defaultmap-unparse.f90 @@ -13,9 +13,9 @@ program main real :: arrA(N), arrB(N) integer, target :: arrC(N) - type(data01) :: data01_a + type(data01) :: data01_a integer, allocatable :: alloc_arr(:) - integer, pointer :: ptrArr(:) + integer, pointer :: ptrArr(:) arrA = 1.414 arrB = 3.14 @@ -26,8 +26,8 @@ program main alloc_arr = -1 -!CHECK: !$omp target defaultmap(tofrom:scalar) - !$omp target defaultmap(tofrom:scalar) +!CHECK: !$omp target defaultmap(tofrom:scalar) + !$omp target defaultmap(tofrom:scalar) do i = 1, N a = 3.14 enddo @@ -66,7 +66,7 @@ program main !CHECK: !$omp target defaultmap(none:scalar) !$omp target defaultmap(none:scalar) a = 4.78 -!CHECK: !$omp end target +!CHECK: !$omp end target !$omp end target !PARSE-TREE: OmpBeginDirective @@ -98,7 +98,7 @@ program main !PARSE-TREE: OmpClauseList -> OmpClause -> Defaultmap -> OmpDefaultmapClause !PARSE-TREE: ImplicitBehavior = Firstprivate !PARSE-TREE: Modifier -> OmpVariableCategory -> Value = Scalar - + !CHECK: !$omp target defaultmap(tofrom:aggregate) !$omp target defaultmap(tofrom:aggregate) arrC(1) = 10 @@ -113,8 +113,8 @@ program main !PARSE-TREE: OmpClauseList -> OmpClause -> Defaultmap -> OmpDefaultmapClause !PARSE-TREE: ImplicitBehavior = Tofrom !PARSE-TREE: Modifier -> OmpVariableCategory -> Value = Aggregate - -!CHECK: !$omp target defaultmap(tofrom:allocatable) + +!CHECK: !$omp target defaultmap(tofrom:allocatable) !$omp target defaultmap(tofrom:allocatable) alloc_arr(23) = 234 !CHECK: !$omp end target @@ -125,14 +125,14 @@ program main !PARSE-TREE: OmpClauseList -> OmpClause -> Defaultmap -> OmpDefaultmapClause !PARSE-TREE: ImplicitBehavior = Tofrom !PARSE-TREE: Modifier -> OmpVariableCategory -> Value = Allocatable - + !CHECK: !$omp target defaultmap(default:pointer) !$omp target defaultmap(default:pointer) ptrArr=>arrC ptrArr(2) = 5 prtArr(200) = 34 !CHECK: !$omp end target - !$omp end target + !$omp end target !PARSE-TREE: OmpBeginDirective !PARSE-TREE: OmpDirectiveName -> llvm::omp::Directive = target diff --git a/flang/test/Parser/OpenMP/dispatch.f90 b/flang/test/Parser/OpenMP/dispatch.f90 index 131b4d1..36f301c 100644 --- a/flang/test/Parser/OpenMP/dispatch.f90 +++ b/flang/test/Parser/OpenMP/dispatch.f90 @@ -33,14 +33,14 @@ subroutine sub(x) !PARSE-TREE: | | | | | LiteralConstant -> IntLiteralConstant = '1' !PARSE-TREE: | | | | Expr = '1_4' !PARSE-TREE: | | | | | LiteralConstant -> IntLiteralConstant = '1' -!PARSE-TREE: | | Flags = None +!PARSE-TREE: | | Flags = {} !PARSE-TREE: | Block !PARSE-TREE: | | ExecutionPartConstruct -> ExecutableConstruct -> ActionStmt -> AssignmentStmt ![...] !PARSE-TREE: | OmpEndDirective !PARSE-TREE: | | OmpDirectiveName -> llvm::omp::Directive = dispatch !PARSE-TREE: | | OmpClauseList -> -!PARSE-TREE: | | Flags = None +!PARSE-TREE: | | Flags = {} !$omp dispatch device(3) nowait nocontext(.false.) novariants(1.eq.1) r = func(a, b, c) @@ -57,7 +57,7 @@ subroutine sub(x) !PARSE-TREE: | | | Scalar -> Integer -> Expr = '3_4' !PARSE-TREE: | | | | LiteralConstant -> IntLiteralConstant = '3' !PARSE-TREE: | | OmpClause -> IsDevicePtr -> OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'x' -!PARSE-TREE: | | Flags = None +!PARSE-TREE: | | Flags = {} !PARSE-TREE: | Block !PARSE-TREE: | | ExecutionPartConstruct -> ExecutableConstruct -> ActionStmt -> AssignmentStmt !PARSE-TREE-NOT: OmpEndDirective diff --git a/flang/test/Parser/OpenMP/do-tile-size.f90 b/flang/test/Parser/OpenMP/do-tile-size.f90 index 9ba6a3a..b8d175c 100644 --- a/flang/test/Parser/OpenMP/do-tile-size.f90 +++ b/flang/test/Parser/OpenMP/do-tile-size.f90 @@ -21,9 +21,11 @@ subroutine openmp_do_tiles(x) !PARSE-TREE:| | ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPLoopConstruct !PARSE-TREE:| | | OmpBeginLoopDirective -!PARSE-TREE:| | | OpenMPLoopConstruct -!PARSE-TREE:| | | | OmpBeginLoopDirective -!PARSE-TREE:| | | | | OmpDirectiveName -> llvm::omp::Directive = tile -!PARSE-TREE:| | | | | OmpClauseList -> OmpClause -> Sizes -> Scalar -> Integer -> Expr = '2_4' -!PARSE-TREE: | | | | DoConstruct +!PARSE-TREE:| | | Block +!PARSE-TREE:| | | | ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPLoopConstruct +!PARSE-TREE:| | | | | OmpBeginLoopDirective +!PARSE-TREE:| | | | | | OmpDirectiveName -> llvm::omp::Directive = tile +!PARSE-TREE:| | | | | | OmpClauseList -> OmpClause -> Sizes -> Scalar -> Integer -> Expr = '2_4' +!PARSE-TREE:| | | | | Block +!PARSE-TREE:| | | | | | ExecutionPartConstruct -> ExecutableConstruct -> DoConstruct END subroutine openmp_do_tiles diff --git a/flang/test/Parser/OpenMP/dyn-groupprivate-clause.f90 b/flang/test/Parser/OpenMP/dyn-groupprivate-clause.f90 index 7d41efd..404f693 100644 --- a/flang/test/Parser/OpenMP/dyn-groupprivate-clause.f90 +++ b/flang/test/Parser/OpenMP/dyn-groupprivate-clause.f90 @@ -20,51 +20,51 @@ end !PARSE-TREE: | OmpClauseList -> OmpClause -> DynGroupprivate -> OmpDynGroupprivateClause !PARSE-TREE: | | Scalar -> Integer -> Expr = 'n' !PARSE-TREE: | | | Designator -> DataRef -> Name = 'n' -!PARSE-TREE: | Flags = None +!PARSE-TREE: | Flags = {} subroutine f01(n) implicit none integer :: n - !$omp target dyn_groupprivate(strict: n) + !$omp target dyn_groupprivate(fallback(abort): n) !$omp end target end !UNPARSE: SUBROUTINE f01 (n) !UNPARSE: IMPLICIT NONE !UNPARSE: INTEGER n -!UNPARSE: !$OMP TARGET DYN_GROUPPRIVATE(STRICT: n) +!UNPARSE: !$OMP TARGET DYN_GROUPPRIVATE(FALLBACK(ABORT): n) !UNPARSE: !$OMP END TARGET !UNPARSE: END SUBROUTINE !PARSE-TREE: OmpBeginDirective !PARSE-TREE: | OmpDirectiveName -> llvm::omp::Directive = target !PARSE-TREE: | OmpClauseList -> OmpClause -> DynGroupprivate -> OmpDynGroupprivateClause -!PARSE-TREE: | | Modifier -> OmpPrescriptiveness -> Value = Strict +!PARSE-TREE: | | Modifier -> OmpFallbackModifier -> Value = Abort !PARSE-TREE: | | Scalar -> Integer -> Expr = 'n' !PARSE-TREE: | | | Designator -> DataRef -> Name = 'n' -!PARSE-TREE: | Flags = None +!PARSE-TREE: | Flags = {} subroutine f02(n) implicit none integer :: n - !$omp target dyn_groupprivate(fallback, cgroup: n) + !$omp target dyn_groupprivate(fallback(default_mem), cgroup: n) !$omp end target end !UNPARSE: SUBROUTINE f02 (n) !UNPARSE: IMPLICIT NONE !UNPARSE: INTEGER n -!UNPARSE: !$OMP TARGET DYN_GROUPPRIVATE(FALLBACK, CGROUP: n) +!UNPARSE: !$OMP TARGET DYN_GROUPPRIVATE(FALLBACK(DEFAULT_MEM), CGROUP: n) !UNPARSE: !$OMP END TARGET !UNPARSE: END SUBROUTINE !PARSE-TREE: OmpBeginDirective !PARSE-TREE: | OmpDirectiveName -> llvm::omp::Directive = target !PARSE-TREE: | OmpClauseList -> OmpClause -> DynGroupprivate -> OmpDynGroupprivateClause -!PARSE-TREE: | | Modifier -> OmpPrescriptiveness -> Value = Fallback +!PARSE-TREE: | | Modifier -> OmpFallbackModifier -> Value = Default_Mem !PARSE-TREE: | | Modifier -> OmpAccessGroup -> Value = Cgroup !PARSE-TREE: | | Scalar -> Integer -> Expr = 'n' !PARSE-TREE: | | | Designator -> DataRef -> Name = 'n' -!PARSE-TREE: | Flags = None +!PARSE-TREE: | Flags = {} diff --git a/flang/test/Parser/OpenMP/enter-automap-modifier.f90 b/flang/test/Parser/OpenMP/enter-automap-modifier.f90 index bc5b5eb..71d8045 100644 --- a/flang/test/Parser/OpenMP/enter-automap-modifier.f90 +++ b/flang/test/Parser/OpenMP/enter-automap-modifier.f90 @@ -16,4 +16,4 @@ end program !PARSE-TREE: | OmpClauseList -> OmpClause -> Enter -> OmpEnterClause !PARSE-TREE: | | Modifier -> OmpAutomapModifier -> Value = Automap !PARSE-TREE: | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'x' -!PARSE-TREE: | Flags = None +!PARSE-TREE: | Flags = {} diff --git a/flang/test/Parser/OpenMP/fail-construct2.f90 b/flang/test/Parser/OpenMP/fail-construct2.f90 index b7f5736..3798c3d 100644 --- a/flang/test/Parser/OpenMP/fail-construct2.f90 +++ b/flang/test/Parser/OpenMP/fail-construct2.f90 @@ -1,5 +1,5 @@ ! RUN: not %flang_fc1 -fsyntax-only -fopenmp %s 2>&1 | FileCheck %s -! CHECK: error: expected OpenMP construct +! CHECK: error: Invalid OpenMP directive !$omp dummy end diff --git a/flang/test/Parser/OpenMP/fail-looprange.f90 b/flang/test/Parser/OpenMP/fail-looprange.f90 new file mode 100644 index 0000000..1c8a080 --- /dev/null +++ b/flang/test/Parser/OpenMP/fail-looprange.f90 @@ -0,0 +1,11 @@ +! RUN: not %flang_fc1 -fsyntax-only -fopenmp %s 2>&1 | FileCheck %s + +! CHECK: error: +!$omp fuse looprange + +! CHECK: error: +!$omp fuse looprange(1) + +! CHECK: error: +!$omp fuse looprange(1,2,3) +end diff --git a/flang/test/Parser/OpenMP/fuse-looprange.f90 b/flang/test/Parser/OpenMP/fuse-looprange.f90 new file mode 100644 index 0000000..d6e6416 --- /dev/null +++ b/flang/test/Parser/OpenMP/fuse-looprange.f90 @@ -0,0 +1,38 @@ +! RUN: %flang_fc1 -fdebug-unparse -fopenmp -fopenmp-version=60 %s | FileCheck --ignore-case %s +! RUN: %flang_fc1 -fdebug-dump-parse-tree -fopenmp -fopenmp-version=60 %s | FileCheck --check-prefix="PARSE-TREE" %s + +subroutine openmp_fuse(x) + + integer, intent(inout)::x + +!CHECK: !$omp fuse looprange +!$omp fuse looprange(1,2) +!CHECK: do + do x = 1, 100 + call F1() +!CHECK: end do + end do +!CHECK: do + do x = 1, 100 + call F1() +!CHECK: end do + end do +!CHECK: do + do x = 1, 100 + call F1() +!CHECK: end do + end do +!CHECK: !$omp end fuse +!$omp end fuse + +!PARSE-TREE: OpenMPConstruct -> OpenMPLoopConstruct +!PARSE-TREE: OmpBeginLoopDirective +!PARSE-TREE: OmpDirectiveName -> llvm::omp::Directive = fuse +!PARSE-TREE: OmpClauseList -> OmpClause -> Looprange -> OmpLooprangeClause +!PARSE-TREE: Scalar -> Integer -> Constant -> Expr = '1_4' +!PARSE-TREE: LiteralConstant -> IntLiteralConstant = '1' +!PARSE-TREE: Scalar -> Integer -> Constant -> Expr = '2_4' +!PARSE-TREE: LiteralConstant -> IntLiteralConstant = '2' + +END subroutine openmp_fuse + diff --git a/flang/test/Parser/OpenMP/fuse01.f90 b/flang/test/Parser/OpenMP/fuse01.f90 new file mode 100644 index 0000000..98ce0e3 --- /dev/null +++ b/flang/test/Parser/OpenMP/fuse01.f90 @@ -0,0 +1,28 @@ +! RUN: %flang_fc1 -fdebug-unparse -fopenmp %s | FileCheck --ignore-case %s +! RUN: %flang_fc1 -fdebug-dump-parse-tree -fopenmp %s | FileCheck --check-prefix="PARSE-TREE" %s + +subroutine openmp_fuse(x) + + integer, intent(inout)::x + +!CHECK: !$omp fuse +!$omp fuse +!CHECK: do + do x = 1, 100 + call F1() +!CHECK: end do + end do +!CHECK: do + do x = 1, 100 + call F1() +!CHECK: end do + end do +!CHECK: !$omp end fuse +!$omp end fuse + +!PARSE-TREE: OpenMPConstruct -> OpenMPLoopConstruct +!PARSE-TREE: OmpBeginLoopDirective +!PARSE-TREE: OmpDirectiveName -> llvm::omp::Directive = fuse + +END subroutine openmp_fuse + diff --git a/flang/test/Parser/OpenMP/fuse02.f90 b/flang/test/Parser/OpenMP/fuse02.f90 new file mode 100644 index 0000000..4b1819f --- /dev/null +++ b/flang/test/Parser/OpenMP/fuse02.f90 @@ -0,0 +1,97 @@ +! Test the Parse Tree to ensure the OpenMP Loop Transformation Construct Fuse can be constructed on another Fuse + +! RUN: %flang_fc1 -fdebug-dump-parse-tree -fopenmp -fopenmp-version=51 %s | FileCheck %s --check-prefix=CHECK-PARSE +! RUN: %flang_fc1 -fdebug-unparse -fopenmp -fopenmp-version=51 %s | FileCheck %s --check-prefix=CHECK-UNPARSE + +subroutine fuse_on_fuse + implicit none + integer :: I = 10 + integer :: j + + !$omp fuse + !$omp fuse + do i = 1, I + continue + end do + do j = 1, I + continue + end do + !$omp end fuse + do j = 1, I + continue + end do + !$omp end fuse +end subroutine + +!CHECK-PARSE: | ExecutionPart -> Block +!CHECK-PARSE-NEXT: | | ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPLoopConstruct +!CHECK-PARSE-NEXT: | | | OmpBeginLoopDirective +!CHECK-PARSE-NEXT: | | | | OmpDirectiveName -> llvm::omp::Directive = fuse +!CHECK-PARSE-NEXT: | | | | OmpClauseList -> +!CHECK-PARSE-NEXT: | | | | Flags = {} +!CHECK-PARSE-NEXT: | | | Block +!CHECK-PARSE-NEXT: | | | | ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPLoopConstruct +!CHECK-PARSE-NEXT: | | | | | OmpBeginLoopDirective +!CHECK-PARSE-NEXT: | | | | | | OmpDirectiveName -> llvm::omp::Directive = fuse +!CHECK-PARSE-NEXT: | | | | | | OmpClauseList -> +!CHECK-PARSE-NEXT: | | | | | | Flags = {} +!CHECK-PARSE-NEXT: | | | | | Block +!CHECK-PARSE-NEXT: | | | | | | ExecutionPartConstruct -> ExecutableConstruct -> DoConstruct +!CHECK-PARSE-NEXT: | | | | | | | NonLabelDoStmt +!CHECK-PARSE-NEXT: | | | | | | | | LoopControl -> LoopBounds +!CHECK-PARSE-NEXT: | | | | | | | | | Scalar -> Name = 'i' +!CHECK-PARSE-NEXT: | | | | | | | | | Scalar -> Expr = '1_4' +!CHECK-PARSE-NEXT: | | | | | | | | | | LiteralConstant -> IntLiteralConstant = '1' +!CHECK-PARSE-NEXT: | | | | | | | | | Scalar -> Expr = 'i' +!CHECK-PARSE-NEXT: | | | | | | | | | | Designator -> DataRef -> Name = 'i' +!CHECK-PARSE-NEXT: | | | | | | | Block +!CHECK-PARSE-NEXT: | | | | | | | | ExecutionPartConstruct -> ExecutableConstruct -> ActionStmt -> ContinueStmt +!CHECK-PARSE-NEXT: | | | | | | | EndDoStmt -> +!CHECK-PARSE-NEXT: | | | | | | ExecutionPartConstruct -> ExecutableConstruct -> DoConstruct +!CHECK-PARSE-NEXT: | | | | | | | NonLabelDoStmt +!CHECK-PARSE-NEXT: | | | | | | | | LoopControl -> LoopBounds +!CHECK-PARSE-NEXT: | | | | | | | | | Scalar -> Name = 'j' +!CHECK-PARSE-NEXT: | | | | | | | | | Scalar -> Expr = '1_4' +!CHECK-PARSE-NEXT: | | | | | | | | | | LiteralConstant -> IntLiteralConstant = '1' +!CHECK-PARSE-NEXT: | | | | | | | | | Scalar -> Expr = 'i' +!CHECK-PARSE-NEXT: | | | | | | | | | | Designator -> DataRef -> Name = 'i' +!CHECK-PARSE-NEXT: | | | | | | | Block +!CHECK-PARSE-NEXT: | | | | | | | | ExecutionPartConstruct -> ExecutableConstruct -> ActionStmt -> ContinueStmt +!CHECK-PARSE-NEXT: | | | | | | | EndDoStmt -> +!CHECK-PARSE-NEXT: | | | | | OmpEndLoopDirective +!CHECK-PARSE-NEXT: | | | | | | OmpDirectiveName -> llvm::omp::Directive = fuse +!CHECK-PARSE-NEXT: | | | | | | OmpClauseList -> +!CHECK-PARSE-NEXT: | | | | | | Flags = {} +!CHECK-PARSE-NEXT: | | | | ExecutionPartConstruct -> ExecutableConstruct -> DoConstruct +!CHECK-PARSE-NEXT: | | | | | NonLabelDoStmt +!CHECK-PARSE-NEXT: | | | | | | LoopControl -> LoopBounds +!CHECK-PARSE-NEXT: | | | | | | | Scalar -> Name = 'j' +!CHECK-PARSE-NEXT: | | | | | | | Scalar -> Expr = '1_4' +!CHECK-PARSE-NEXT: | | | | | | | | LiteralConstant -> IntLiteralConstant = '1' +!CHECK-PARSE-NEXT: | | | | | | | Scalar -> Expr = 'i' +!CHECK-PARSE-NEXT: | | | | | | | | Designator -> DataRef -> Name = 'i' +!CHECK-PARSE-NEXT: | | | | | Block +!CHECK-PARSE-NEXT: | | | | | | ExecutionPartConstruct -> ExecutableConstruct -> ActionStmt -> ContinueStmt +!CHECK-PARSE-NEXT: | | | | | EndDoStmt -> +!CHECK-PARSE-NEXT: | | | OmpEndLoopDirective +!CHECK-PARSE-NEXT: | | | | OmpDirectiveName -> llvm::omp::Directive = fuse +!CHECK-PARSE-NEXT: | | | | OmpClauseList -> +!CHECK-PARSE-NEXT: | | | | Flags = {} + +!CHECK-UNPARSE: SUBROUTINE fuse_on_fuse +!CHECK-UNPARSE-NEXT: IMPLICIT NONE +!CHECK-UNPARSE-NEXT: INTEGER :: i = 10_4 +!CHECK-UNPARSE-NEXT: INTEGER j +!CHECK-UNPARSE-NEXT: !$OMP FUSE +!CHECK-UNPARSE-NEXT: !$OMP FUSE +!CHECK-UNPARSE-NEXT: DO i=1_4,i +!CHECK-UNPARSE-NEXT: CONTINUE +!CHECK-UNPARSE-NEXT: END DO +!CHECK-UNPARSE-NEXT: DO j=1_4,i +!CHECK-UNPARSE-NEXT: CONTINUE +!CHECK-UNPARSE-NEXT: END DO +!CHECK-UNPARSE-NEXT: !$OMP END FUSE +!CHECK-UNPARSE-NEXT: DO j=1_4,i +!CHECK-UNPARSE-NEXT: CONTINUE +!CHECK-UNPARSE-NEXT: END DO +!CHECK-UNPARSE-NEXT: !$OMP END FUSE diff --git a/flang/test/Parser/OpenMP/groupprivate.f90 b/flang/test/Parser/OpenMP/groupprivate.f90 index 8bd8401..b069eb75 100644 --- a/flang/test/Parser/OpenMP/groupprivate.f90 +++ b/flang/test/Parser/OpenMP/groupprivate.f90 @@ -22,9 +22,9 @@ end module !PARSE-TREE: | OmpArgumentList -> OmpArgument -> OmpLocator -> OmpObject -> Designator -> DataRef -> Name = 'x' !PARSE-TREE: | OmpArgument -> OmpLocator -> OmpObject -> Designator -> DataRef -> Name = 'y' !PARSE-TREE: | OmpClauseList -> OmpClause -> DeviceType -> OmpDeviceTypeClause -> DeviceTypeDescription = Nohost -!PARSE-TREE: | Flags = None +!PARSE-TREE: | Flags = {} !PARSE-TREE: DeclarationConstruct -> SpecificationConstruct -> OpenMPDeclarativeConstruct -> OpenMPGroupprivate -> OmpDirectiveSpecification !PARSE-TREE: | OmpDirectiveName -> llvm::omp::Directive = groupprivate !PARSE-TREE: | OmpArgumentList -> OmpArgument -> OmpLocator -> OmpObject -> Designator -> DataRef -> Name = 'z' !PARSE-TREE: | OmpClauseList -> -!PARSE-TREE: | Flags = None +!PARSE-TREE: | Flags = {} diff --git a/flang/test/Parser/OpenMP/if-clause-unparse.f90 b/flang/test/Parser/OpenMP/if-clause-unparse.f90 index ce058ca..e0334f5 100644 --- a/flang/test/Parser/OpenMP/if-clause-unparse.f90 +++ b/flang/test/Parser/OpenMP/if-clause-unparse.f90 @@ -12,7 +12,7 @@ program if_unparse ! CHECK: !$OMP TARGET UPDATE ! CHECK-SAME: IF(TARGET UPDATE: cond) !$omp target update if(target update: cond) - + ! CHECK: !$OMP TARGET UPDATE ! CHECK-SAME: IF(TARGET UPDATE: cond) !$omp target update if(targetupdate: cond) diff --git a/flang/test/Parser/OpenMP/in-reduction-clause.f90 b/flang/test/Parser/OpenMP/in-reduction-clause.f90 index 6059fb2..eb39398 100644 --- a/flang/test/Parser/OpenMP/in-reduction-clause.f90 +++ b/flang/test/Parser/OpenMP/in-reduction-clause.f90 @@ -46,7 +46,7 @@ end subroutine omp_in_reduction_taskgroup !PARSE-TREE-NEXT: OmpClauseList -> OmpClause -> InReduction -> OmpInReductionClause !PARSE-TREE-NEXT: OmpReductionIdentifier -> DefinedOperator -> IntrinsicOperator = Add !PARSE-TREE-NEXT: OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'z' -!PARSE-TREE-NEXT: Flags = None +!PARSE-TREE-NEXT: Flags = {} subroutine omp_in_reduction_parallel() integer :: z @@ -77,5 +77,5 @@ end subroutine omp_in_reduction_parallel !PARSE-TREE-NEXT: OmpClauseList -> OmpClause -> InReduction -> OmpInReductionClause !PARSE-TREE-NEXT: OmpReductionIdentifier -> DefinedOperator -> IntrinsicOperator = Add !PARSE-TREE-NEXT: OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'z' -!PARSE-TREE-NEXT: Flags = None +!PARSE-TREE-NEXT: Flags = {} diff --git a/flang/test/Parser/OpenMP/interop-construct.f90 b/flang/test/Parser/OpenMP/interop-construct.f90 index 82a1b11..44632e7 100644 --- a/flang/test/Parser/OpenMP/interop-construct.f90 +++ b/flang/test/Parser/OpenMP/interop-construct.f90 @@ -1,5 +1,5 @@ ! REQUIRES: openmp_runtime -! RUN: %flang_fc1 -fdebug-unparse -fopenmp-version=52 %openmp_flags %s | FileCheck --ignore-case --check-prefix="UNPARSE" %s +! RUN: %flang_fc1 -fdebug-unparse -fopenmp-version=52 %openmp_flags %s | FileCheck --ignore-case --check-prefix="UNPARSE" %s ! RUN: %flang_fc1 -fdebug-dump-parse-tree-no-sema -fopenmp-version=52 %openmp_flags %s | FileCheck --check-prefix="PARSE-TREE" %s SUBROUTINE test_interop_01() @@ -15,13 +15,13 @@ END SUBROUTINE test_interop_01 !PARSE-TREE: | SubroutineStmt !PARSE-TREE: | | Name = 'test_interop_01' !PARSE-TREE: | SpecificationPart -!PARSE-TREE: | | ImplicitPart -> +!PARSE-TREE: | | ImplicitPart -> !PARSE-TREE: | ExecutionPart -> Block !PARSE-TREE: | | ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPStandaloneConstruct -> OpenMPInteropConstruct -> OmpDirectiveSpecification !PARSE-TREE: | | | OmpDirectiveName -> llvm::omp::Directive = interop !PARSE-TREE: | | | OmpClauseList -> OmpClause -> Device -> OmpDeviceClause !PARSE-TREE: | | | | Scalar -> Integer -> Expr -> LiteralConstant -> IntLiteralConstant = '1' -!PARSE-TREE: | | | Flags = None +!PARSE-TREE: | | | Flags = {} !PARSE-TREE: | | ExecutionPartConstruct -> ExecutableConstruct -> ActionStmt -> PrintStmt !PARSE-TREE: | | | Format -> Star !PARSE-TREE: | | | OutputItem -> Expr -> LiteralConstant -> CharLiteralConstant @@ -47,7 +47,7 @@ END SUBROUTINE test_interop_02 !PARSE-TREE: | SpecificationPart !PARSE-TREE: | | UseStmt !PARSE-TREE: | | | Name = 'omp_lib' -!PARSE-TREE: | | ImplicitPart -> +!PARSE-TREE: | | ImplicitPart -> !PARSE-TREE: | | DeclarationConstruct -> SpecificationConstruct -> TypeDeclarationStmt !PARSE-TREE: | | | DeclarationTypeSpec -> IntrinsicTypeSpec -> IntegerTypeSpec -> KindSelector -> Scalar -> Integer -> Constant -> Expr -> Designator -> DataRef -> Name = 'omp_interop_kind' !PARSE-TREE: | | | EntityDecl @@ -64,7 +64,7 @@ END SUBROUTINE test_interop_02 !PARSE-TREE: | | | | OmpObject -> Designator -> DataRef -> Name = 'obj' !PARSE-TREE: | | | OmpClause -> Use -> OmpUseClause -> OmpObject -> Designator -> DataRef -> Name = 'obj1' !PARSE-TREE: | | | OmpClause -> Destroy -> OmpDestroyClause -> OmpObject -> Designator -> DataRef -> Name = 'obj3' -!PARSE-TREE: | | | Flags = None +!PARSE-TREE: | | | Flags = {} !PARSE-TREE: | | ExecutionPartConstruct -> ExecutableConstruct -> ActionStmt -> PrintStmt !PARSE-TREE: | | | Format -> Star !PARSE-TREE: | | | OutputItem -> Expr -> LiteralConstant -> CharLiteralConstant @@ -90,7 +90,7 @@ END SUBROUTINE test_interop_03 !PARSE-TREE: | SpecificationPart !PARSE-TREE: | | UseStmt !PARSE-TREE: | | | Name = 'omp_lib' -!PARSE-TREE: | | ImplicitPart -> +!PARSE-TREE: | | ImplicitPart -> !PARSE-TREE: | | DeclarationConstruct -> SpecificationConstruct -> TypeDeclarationStmt !PARSE-TREE: | | | DeclarationTypeSpec -> IntrinsicTypeSpec -> IntegerTypeSpec -> KindSelector -> Scalar -> Integer -> Constant -> Expr -> Designator -> DataRef -> Name = 'omp_interop_kind' !PARSE-TREE: | | | EntityDecl @@ -104,7 +104,7 @@ END SUBROUTINE test_interop_03 !PARSE-TREE: | | | OmpClause -> Depend -> OmpDependClause -> TaskDep !PARSE-TREE: | | | | Modifier -> OmpTaskDependenceType -> Value = Inout !PARSE-TREE: | | | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'obj' -!PARSE-TREE: | | | Flags = None +!PARSE-TREE: | | | Flags = {} !PARSE-TREE: | | ExecutionPartConstruct -> ExecutableConstruct -> ActionStmt -> PrintStmt !PARSE-TREE: | | | Format -> Star !PARSE-TREE: | | | OutputItem -> Expr -> LiteralConstant -> CharLiteralConstant @@ -133,13 +133,13 @@ END SUBROUTINE test_interop_04 !PARSE-TREE: | SpecificationPart !PARSE-TREE: | | UseStmt !PARSE-TREE: | | | Name = 'omp_lib' -!PARSE-TREE: | | ImplicitPart -> +!PARSE-TREE: | | ImplicitPart -> !PARSE-TREE: | | DeclarationConstruct -> SpecificationConstruct -> TypeDeclarationStmt !PARSE-TREE: | | | DeclarationTypeSpec -> IntrinsicTypeSpec -> IntegerTypeSpec -> KindSelector -> Scalar -> Integer -> Constant -> Expr -> Designator -> DataRef -> Name = 'omp_interop_kind' !PARSE-TREE: | | | EntityDecl !PARSE-TREE: | | | | Name = 'obj' !PARSE-TREE: | | DeclarationConstruct -> SpecificationConstruct -> TypeDeclarationStmt -!PARSE-TREE: | | | DeclarationTypeSpec -> IntrinsicTypeSpec -> IntegerTypeSpec -> +!PARSE-TREE: | | | DeclarationTypeSpec -> IntrinsicTypeSpec -> IntegerTypeSpec -> !PARSE-TREE: | | | AttrSpec -> ArraySpec -> ExplicitShapeSpec !PARSE-TREE: | | | | SpecificationExpr -> Scalar -> Integer -> Expr -> LiteralConstant -> IntLiteralConstant = '1' !PARSE-TREE: | | | ExplicitShapeSpec @@ -159,7 +159,7 @@ END SUBROUTINE test_interop_04 !PARSE-TREE: | | | | Modifier -> OmpTaskDependenceType -> Value = Inout !PARSE-TREE: | | | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'arr' !PARSE-TREE: | | | OmpClause -> Nowait -!PARSE-TREE: | | | Flags = None +!PARSE-TREE: | | | Flags = {} !PARSE-TREE: | | ExecutionPartConstruct -> ExecutableConstruct -> ActionStmt -> PrintStmt !PARSE-TREE: | | | Format -> Star !PARSE-TREE: | | | OutputItem -> Expr -> LiteralConstant -> CharLiteralConstant @@ -185,7 +185,7 @@ END SUBROUTINE test_interop_05 !PARSE-TREE: | SpecificationPart !PARSE-TREE: | | UseStmt !PARSE-TREE: | | | Name = 'omp_lib' -!PARSE-TREE: | | ImplicitPart -> +!PARSE-TREE: | | ImplicitPart -> !PARSE-TREE: | | DeclarationConstruct -> SpecificationConstruct -> TypeDeclarationStmt !PARSE-TREE: | | | DeclarationTypeSpec -> IntrinsicTypeSpec -> IntegerTypeSpec -> KindSelector -> Scalar -> Integer -> Constant -> Expr -> Designator -> DataRef -> Name = 'omp_interop_kind' !PARSE-TREE: | | | EntityDecl @@ -200,7 +200,7 @@ END SUBROUTINE test_interop_05 !PARSE-TREE: | | | OmpClause -> Device -> OmpDeviceClause !PARSE-TREE: | | | | Modifier -> OmpDeviceModifier -> Value = Device_Num !PARSE-TREE: | | | | Scalar -> Integer -> Expr -> LiteralConstant -> IntLiteralConstant = '0' -!PARSE-TREE: | | | Flags = None +!PARSE-TREE: | | | Flags = {} !PARSE-TREE: | | ExecutionPartConstruct -> ExecutableConstruct -> ActionStmt -> PrintStmt !PARSE-TREE: | | | Format -> Star !PARSE-TREE: | | | OutputItem -> Expr -> LiteralConstant -> CharLiteralConstant diff --git a/flang/test/Parser/OpenMP/lastprivate-clause.f90 b/flang/test/Parser/OpenMP/lastprivate-clause.f90 index 6364b74..08ada74 100644 --- a/flang/test/Parser/OpenMP/lastprivate-clause.f90 +++ b/flang/test/Parser/OpenMP/lastprivate-clause.f90 @@ -1,4 +1,4 @@ -! RUN: %flang_fc1 -fdebug-unparse -fopenmp -fopenmp-version=50 %s | FileCheck --ignore-case --check-prefix="UNPARSE" %s +! RUN: %flang_fc1 -fdebug-unparse -fopenmp -fopenmp-version=50 %s | FileCheck --ignore-case --check-prefix="UNPARSE" %s ! RUN: %flang_fc1 -fdebug-dump-parse-tree -fopenmp -fopenmp-version=50 %s | FileCheck --check-prefix="PARSE-TREE" %s subroutine foo1() diff --git a/flang/test/Parser/OpenMP/linear-clause.f90 b/flang/test/Parser/OpenMP/linear-clause.f90 index b53dfe5..fb02f25 100644 --- a/flang/test/Parser/OpenMP/linear-clause.f90 +++ b/flang/test/Parser/OpenMP/linear-clause.f90 @@ -22,7 +22,7 @@ end !PARSE-TREE: | OmpClauseList -> OmpClause -> Linear -> OmpLinearClause !PARSE-TREE: | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'x' !PARSE-TREE: | | bool = 'true' -!PARSE-TREE: | Flags = None +!PARSE-TREE: | Flags = {} !PARSE-TREE: DoConstruct subroutine f01(x) @@ -48,7 +48,7 @@ end !PARSE-TREE: | | Modifier -> OmpStepSimpleModifier -> Scalar -> Integer -> Expr = '2_4' !PARSE-TREE: | | | LiteralConstant -> IntLiteralConstant = '2' !PARSE-TREE: | | bool = 'true' -!PARSE-TREE: | Flags = None +!PARSE-TREE: | Flags = {} !PARSE-TREE: DoConstruct subroutine f02(x) @@ -74,7 +74,7 @@ end !PARSE-TREE: | | Modifier -> OmpStepComplexModifier -> Scalar -> Integer -> Expr = '3_4' !PARSE-TREE: | | | LiteralConstant -> IntLiteralConstant = '3' !PARSE-TREE: | | bool = 'true' -!PARSE-TREE: | Flags = None +!PARSE-TREE: | Flags = {} !PARSE-TREE: DoConstruct subroutine f03(x) @@ -93,7 +93,7 @@ end !PARSE-TREE: | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'x' !PARSE-TREE: | | Modifier -> OmpLinearModifier -> Value = Uval !PARSE-TREE: | | bool = 'true' -!PARSE-TREE: | Flags = None +!PARSE-TREE: | Flags = {} subroutine f04(x) integer :: x @@ -113,4 +113,4 @@ end !PARSE-TREE: | | Modifier -> OmpStepComplexModifier -> Scalar -> Integer -> Expr = '3_4' !PARSE-TREE: | | | LiteralConstant -> IntLiteralConstant = '3' !PARSE-TREE: | | bool = 'true' -!PARSE-TREE: | Flags = None +!PARSE-TREE: | Flags = {} diff --git a/flang/test/Parser/OpenMP/loop-transformation-construct01.f90 b/flang/test/Parser/OpenMP/loop-transformation-construct01.f90 index 9595889..16154b3 100644 --- a/flang/test/Parser/OpenMP/loop-transformation-construct01.f90 +++ b/flang/test/Parser/OpenMP/loop-transformation-construct01.f90 @@ -10,7 +10,7 @@ subroutine loop_transformation_construct integer :: y(I) !$omp do - !$omp unroll + !$omp unroll partial(1) do i = 1, I y(i) = y(i) * 5 end do @@ -23,45 +23,48 @@ end subroutine !CHECK-PARSE-NEXT: | | | OmpBeginLoopDirective !CHECK-PARSE-NEXT: | | | | OmpDirectiveName -> llvm::omp::Directive = do !CHECK-PARSE-NEXT: | | | | OmpClauseList -> -!CHECK-PARSE-NEXT: | | | | Flags = None -!CHECK-PARSE-NEXT: | | | OpenMPLoopConstruct -!CHECK-PARSE-NEXT: | | | | OmpBeginLoopDirective -!CHECK-PARSE-NEXT: | | | | | OmpDirectiveName -> llvm::omp::Directive = unroll -!CHECK-PARSE-NEXT: | | | | | OmpClauseList -> -!CHECK-PARSE-NEXT: | | | | | Flags = None -!CHECK-PARSE-NEXT: | | | | DoConstruct -!CHECK-PARSE-NEXT: | | | | | NonLabelDoStmt -!CHECK-PARSE-NEXT: | | | | | | LoopControl -> LoopBounds -!CHECK-PARSE-NEXT: | | | | | | | Scalar -> Name = 'i' -!CHECK-PARSE-NEXT: | | | | | | | Scalar -> Expr = '1_4' -!CHECK-PARSE-NEXT: | | | | | | | | LiteralConstant -> IntLiteralConstant = '1' -!CHECK-PARSE-NEXT: | | | | | | | Scalar -> Expr = 'i' -!CHECK-PARSE-NEXT: | | | | | | | | Designator -> DataRef -> Name = 'i' +!CHECK-PARSE-NEXT: | | | | Flags = {} +!CHECK-PARSE-NEXT: | | | Block +!CHECK-PARSE-NEXT: | | | | ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPLoopConstruct +!CHECK-PARSE-NEXT: | | | | | OmpBeginLoopDirective +!CHECK-PARSE-NEXT: | | | | | | OmpDirectiveName -> llvm::omp::Directive = unroll +!CHECK-PARSE-NEXT: | | | | | | OmpClauseList -> OmpClause -> Partial -> Scalar -> Integer -> Constant -> Expr = '1_4' +!CHECK-PARSE-NEXT: | | | | | | | LiteralConstant -> IntLiteralConstant = '1' +!CHECK-PARSE-NEXT: | | | | | | Flags = {} !CHECK-PARSE-NEXT: | | | | | Block -!CHECK-PARSE-NEXT: | | | | | | ExecutionPartConstruct -> ExecutableConstruct -> ActionStmt -> AssignmentStmt = 'y(int(i,kind=8))=5_4*y(int(i,kind=8))' -!CHECK-PARSE-NEXT: | | | | | | | Variable = 'y(int(i,kind=8))' -!CHECK-PARSE-NEXT: | | | | | | | | Designator -> DataRef -> ArrayElement -!CHECK-PARSE-NEXT: | | | | | | | | | DataRef -> Name = 'y' -!CHECK-PARSE-NEXT: | | | | | | | | | SectionSubscript -> Integer -> Expr = 'i' +!CHECK-PARSE-NEXT: | | | | | | ExecutionPartConstruct -> ExecutableConstruct -> DoConstruct +!CHECK-PARSE-NEXT: | | | | | | | NonLabelDoStmt +!CHECK-PARSE-NEXT: | | | | | | | | LoopControl -> LoopBounds +!CHECK-PARSE-NEXT: | | | | | | | | | Scalar -> Name = 'i' +!CHECK-PARSE-NEXT: | | | | | | | | | Scalar -> Expr = '1_4' +!CHECK-PARSE-NEXT: | | | | | | | | | | LiteralConstant -> IntLiteralConstant = '1' +!CHECK-PARSE-NEXT: | | | | | | | | | Scalar -> Expr = 'i' !CHECK-PARSE-NEXT: | | | | | | | | | | Designator -> DataRef -> Name = 'i' -!CHECK-PARSE-NEXT: | | | | | | | Expr = '5_4*y(int(i,kind=8))' -!CHECK-PARSE-NEXT: | | | | | | | | Multiply -!CHECK-PARSE-NEXT: | | | | | | | | | Expr = 'y(int(i,kind=8))' +!CHECK-PARSE-NEXT: | | | | | | | Block +!CHECK-PARSE-NEXT: | | | | | | | | ExecutionPartConstruct -> ExecutableConstruct -> ActionStmt -> AssignmentStmt = 'y(int(i,kind=8))=5_4*y(int(i,kind=8))' +!CHECK-PARSE-NEXT: | | | | | | | | | Variable = 'y(int(i,kind=8))' !CHECK-PARSE-NEXT: | | | | | | | | | | Designator -> DataRef -> ArrayElement !CHECK-PARSE-NEXT: | | | | | | | | | | | DataRef -> Name = 'y' !CHECK-PARSE-NEXT: | | | | | | | | | | | SectionSubscript -> Integer -> Expr = 'i' !CHECK-PARSE-NEXT: | | | | | | | | | | | | Designator -> DataRef -> Name = 'i' -!CHECK-PARSE-NEXT: | | | | | | | | | Expr = '5_4' -!CHECK-PARSE-NEXT: | | | | | | | | | | LiteralConstant -> IntLiteralConstant = '5' -!CHECK-PARSE-NEXT: | | | | | EndDoStmt -> -!CHECK-PARSE-NEXT: | | | | OmpEndLoopDirective -!CHECK-PARSE-NEXT: | | | | | OmpDirectiveName -> llvm::omp::Directive = unroll -!CHECK-PARSE-NEXT: | | | | | OmpClauseList -> -!CHECK-PARSE-NEXT: | | | | | Flags = None +!CHECK-PARSE-NEXT: | | | | | | | | | Expr = '5_4*y(int(i,kind=8))' +!CHECK-PARSE-NEXT: | | | | | | | | | | Multiply +!CHECK-PARSE-NEXT: | | | | | | | | | | | Expr = 'y(int(i,kind=8))' +!CHECK-PARSE-NEXT: | | | | | | | | | | | | Designator -> DataRef -> ArrayElement +!CHECK-PARSE-NEXT: | | | | | | | | | | | | | DataRef -> Name = 'y' +!CHECK-PARSE-NEXT: | | | | | | | | | | | | | SectionSubscript -> Integer -> Expr = 'i' +!CHECK-PARSE-NEXT: | | | | | | | | | | | | | | Designator -> DataRef -> Name = 'i' +!CHECK-PARSE-NEXT: | | | | | | | | | | | Expr = '5_4' +!CHECK-PARSE-NEXT: | | | | | | | | | | | | LiteralConstant -> IntLiteralConstant = '5' +!CHECK-PARSE-NEXT: | | | | | | | EndDoStmt -> +!CHECK-PARSE-NEXT: | | | | | OmpEndLoopDirective +!CHECK-PARSE-NEXT: | | | | | | OmpDirectiveName -> llvm::omp::Directive = unroll +!CHECK-PARSE-NEXT: | | | | | | OmpClauseList -> +!CHECK-PARSE-NEXT: | | | | | | Flags = {} !CHECK-PARSE-NEXT: | | | OmpEndLoopDirective !CHECK-PARSE-NEXT: | | | | OmpDirectiveName -> llvm::omp::Directive = do !CHECK-PARSE-NEXT: | | | | OmpClauseList -> -!CHECK-PARSE-NEXT: | | | | Flags = None +!CHECK-PARSE-NEXT: | | | | Flags = {} !CHECK-UNPARSE: SUBROUTINE loop_transformation_construct !CHECK-UNPARSE-NEXT: IMPLICIT NONE @@ -69,7 +72,7 @@ end subroutine !CHECK-UNPARSE-NEXT: INTEGER x !CHECK-UNPARSE-NEXT: INTEGER y(i) !CHECK-UNPARSE-NEXT: !$OMP DO -!CHECK-UNPARSE-NEXT: !$OMP UNROLL +!CHECK-UNPARSE-NEXT: !$OMP UNROLL PARTIAL(1_4) !CHECK-UNPARSE-NEXT: DO i=1_4,i !CHECK-UNPARSE-NEXT: y(int(i,kind=8))=5_4*y(int(i,kind=8)) !CHECK-UNPARSE-NEXT: END DO diff --git a/flang/test/Parser/OpenMP/loop-transformation-construct02.f90 b/flang/test/Parser/OpenMP/loop-transformation-construct02.f90 index a876c77..52a7811 100644 --- a/flang/test/Parser/OpenMP/loop-transformation-construct02.f90 +++ b/flang/test/Parser/OpenMP/loop-transformation-construct02.f90 @@ -10,7 +10,7 @@ subroutine loop_transformation_construct integer :: y(I) !$omp do - !$omp unroll + !$omp unroll partial(1) !$omp tile sizes(2) do i = 1, I y(i) = y(i) * 5 @@ -25,55 +25,59 @@ end subroutine !CHECK-PARSE-NEXT: | | | OmpBeginLoopDirective !CHECK-PARSE-NEXT: | | | | OmpDirectiveName -> llvm::omp::Directive = do !CHECK-PARSE-NEXT: | | | | OmpClauseList -> -!CHECK-PARSE-NEXT: | | | | Flags = None -!CHECK-PARSE-NEXT: | | | OpenMPLoopConstruct -!CHECK-PARSE-NEXT: | | | | OmpBeginLoopDirective -!CHECK-PARSE-NEXT: | | | | | OmpDirectiveName -> llvm::omp::Directive = unroll -!CHECK-PARSE-NEXT: | | | | | OmpClauseList -> -!CHECK-PARSE-NEXT: | | | | | Flags = None -!CHECK-PARSE-NEXT: | | | | OpenMPLoopConstruct +!CHECK-PARSE-NEXT: | | | | Flags = {} +!CHECK-PARSE-NEXT: | | | Block +!CHECK-PARSE-NEXT: | | | | ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPLoopConstruct !CHECK-PARSE-NEXT: | | | | | OmpBeginLoopDirective -!CHECK-PARSE-NEXT: | | | | | | OmpDirectiveName -> llvm::omp::Directive = tile -!CHECK-PARSE-NEXT: | | | | | | OmpClauseList -> OmpClause -> Sizes -> Scalar -> Integer -> Expr = '2_4' -!CHECK-PARSE-NEXT: | | | | | | | LiteralConstant -> IntLiteralConstant = '2' -!CHECK-PARSE-NEXT: | | | | | | Flags = None -!CHECK-PARSE-NEXT: | | | | | DoConstruct -!CHECK-PARSE-NEXT: | | | | | | NonLabelDoStmt -!CHECK-PARSE-NEXT: | | | | | | | LoopControl -> LoopBounds -!CHECK-PARSE-NEXT: | | | | | | | | Scalar -> Name = 'i' -!CHECK-PARSE-NEXT: | | | | | | | | Scalar -> Expr = '1_4' -!CHECK-PARSE-NEXT: | | | | | | | | | LiteralConstant -> IntLiteralConstant = '1' -!CHECK-PARSE-NEXT: | | | | | | | | Scalar -> Expr = 'i' -!CHECK-PARSE-NEXT: | | | | | | | | | Designator -> DataRef -> Name = 'i' -!CHECK-PARSE-NEXT: | | | | | | Block -!CHECK-PARSE-NEXT: | | | | | | | ExecutionPartConstruct -> ExecutableConstruct -> ActionStmt -> AssignmentStmt = 'y(int(i,kind=8))=5_4*y(int(i,kind=8))' -!CHECK-PARSE-NEXT: | | | | | | | | Variable = 'y(int(i,kind=8))' -!CHECK-PARSE-NEXT: | | | | | | | | | Designator -> DataRef -> ArrayElement -!CHECK-PARSE-NEXT: | | | | | | | | | | DataRef -> Name = 'y' -!CHECK-PARSE-NEXT: | | | | | | | | | | SectionSubscript -> Integer -> Expr = 'i' -!CHECK-PARSE-NEXT: | | | | | | | | | | | Designator -> DataRef -> Name = 'i' -!CHECK-PARSE-NEXT: | | | | | | | | Expr = '5_4*y(int(i,kind=8))' -!CHECK-PARSE-NEXT: | | | | | | | | | Multiply -!CHECK-PARSE-NEXT: | | | | | | | | | | Expr = 'y(int(i,kind=8))' -!CHECK-PARSE-NEXT: | | | | | | | | | | | Designator -> DataRef -> ArrayElement -!CHECK-PARSE-NEXT: | | | | | | | | | | | | DataRef -> Name = 'y' -!CHECK-PARSE-NEXT: | | | | | | | | | | | | SectionSubscript -> Integer -> Expr = 'i' -!CHECK-PARSE-NEXT: | | | | | | | | | | | | | Designator -> DataRef -> Name = 'i' -!CHECK-PARSE-NEXT: | | | | | | | | | | Expr = '5_4' -!CHECK-PARSE-NEXT: | | | | | | | | | | | LiteralConstant -> IntLiteralConstant = '5' -!CHECK-PARSE-NEXT: | | | | | | EndDoStmt -> +!CHECK-PARSE-NEXT: | | | | | | OmpDirectiveName -> llvm::omp::Directive = unroll +!CHECK-PARSE-NEXT: | | | | | | OmpClauseList -> OmpClause -> Partial -> Scalar -> Integer -> Constant -> Expr = '1_4' +!CHECK-PARSE-NEXT: | | | | | | | LiteralConstant -> IntLiteralConstant = '1' +!CHECK-PARSE-NEXT: | | | | | | Flags = {} +!CHECK-PARSE-NEXT: | | | | | Block +!CHECK-PARSE-NEXT: | | | | | | ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPLoopConstruct +!CHECK-PARSE-NEXT: | | | | | | | OmpBeginLoopDirective +!CHECK-PARSE-NEXT: | | | | | | | | OmpDirectiveName -> llvm::omp::Directive = tile +!CHECK-PARSE-NEXT: | | | | | | | | OmpClauseList -> OmpClause -> Sizes -> Scalar -> Integer -> Expr = '2_4' +!CHECK-PARSE-NEXT: | | | | | | | | | LiteralConstant -> IntLiteralConstant = '2' +!CHECK-PARSE-NEXT: | | | | | | | | Flags = {} +!CHECK-PARSE-NEXT: | | | | | | | Block +!CHECK-PARSE-NEXT: | | | | | | | | ExecutionPartConstruct -> ExecutableConstruct -> DoConstruct +!CHECK-PARSE-NEXT: | | | | | | | | | NonLabelDoStmt +!CHECK-PARSE-NEXT: | | | | | | | | | | LoopControl -> LoopBounds +!CHECK-PARSE-NEXT: | | | | | | | | | | | Scalar -> Name = 'i' +!CHECK-PARSE-NEXT: | | | | | | | | | | | Scalar -> Expr = '1_4' +!CHECK-PARSE-NEXT: | | | | | | | | | | | | LiteralConstant -> IntLiteralConstant = '1' +!CHECK-PARSE-NEXT: | | | | | | | | | | | Scalar -> Expr = 'i' +!CHECK-PARSE-NEXT: | | | | | | | | | | | | Designator -> DataRef -> Name = 'i' +!CHECK-PARSE-NEXT: | | | | | | | | | Block +!CHECK-PARSE-NEXT: | | | | | | | | | | ExecutionPartConstruct -> ExecutableConstruct -> ActionStmt -> AssignmentStmt = 'y(int(i,kind=8))=5_4*y(int(i,kind=8))' +!CHECK-PARSE-NEXT: | | | | | | | | | | | Variable = 'y(int(i,kind=8))' +!CHECK-PARSE-NEXT: | | | | | | | | | | | | Designator -> DataRef -> ArrayElement +!CHECK-PARSE-NEXT: | | | | | | | | | | | | | DataRef -> Name = 'y' +!CHECK-PARSE-NEXT: | | | | | | | | | | | | | SectionSubscript -> Integer -> Expr = 'i' +!CHECK-PARSE-NEXT: | | | | | | | | | | | | | | Designator -> DataRef -> Name = 'i' +!CHECK-PARSE-NEXT: | | | | | | | | | | | Expr = '5_4*y(int(i,kind=8))' +!CHECK-PARSE-NEXT: | | | | | | | | | | | | Multiply +!CHECK-PARSE-NEXT: | | | | | | | | | | | | | Expr = 'y(int(i,kind=8))' +!CHECK-PARSE-NEXT: | | | | | | | | | | | | | | Designator -> DataRef -> ArrayElement +!CHECK-PARSE-NEXT: | | | | | | | | | | | | | | | DataRef -> Name = 'y' +!CHECK-PARSE-NEXT: | | | | | | | | | | | | | | | SectionSubscript -> Integer -> Expr = 'i' +!CHECK-PARSE-NEXT: | | | | | | | | | | | | | | | | Designator -> DataRef -> Name = 'i' +!CHECK-PARSE-NEXT: | | | | | | | | | | | | | Expr = '5_4' +!CHECK-PARSE-NEXT: | | | | | | | | | | | | | | LiteralConstant -> IntLiteralConstant = '5' +!CHECK-PARSE-NEXT: | | | | | | | | | EndDoStmt -> +!CHECK-PARSE-NEXT: | | | | | | | OmpEndLoopDirective +!CHECK-PARSE-NEXT: | | | | | | | | OmpDirectiveName -> llvm::omp::Directive = tile +!CHECK-PARSE-NEXT: | | | | | | | | OmpClauseList -> +!CHECK-PARSE-NEXT: | | | | | | | | Flags = {} !CHECK-PARSE-NEXT: | | | | | OmpEndLoopDirective -!CHECK-PARSE-NEXT: | | | | | | OmpDirectiveName -> llvm::omp::Directive = tile +!CHECK-PARSE-NEXT: | | | | | | OmpDirectiveName -> llvm::omp::Directive = unroll !CHECK-PARSE-NEXT: | | | | | | OmpClauseList -> -!CHECK-PARSE-NEXT: | | | | | | Flags = None -!CHECK-PARSE-NEXT: | | | | OmpEndLoopDirective -!CHECK-PARSE-NEXT: | | | | | OmpDirectiveName -> llvm::omp::Directive = unroll -!CHECK-PARSE-NEXT: | | | | | OmpClauseList -> -!CHECK-PARSE-NEXT: | | | | | Flags = None +!CHECK-PARSE-NEXT: | | | | | | Flags = {} !CHECK-PARSE-NEXT: | | | OmpEndLoopDirective !CHECK-PARSE-NEXT: | | | | OmpDirectiveName -> llvm::omp::Directive = do !CHECK-PARSE-NEXT: | | | | OmpClauseList -> -!CHECK-PARSE-NEXT: | | | | Flags = None +!CHECK-PARSE-NEXT: | | | | Flags = {} !CHECK-UNPARSE: SUBROUTINE loop_transformation_construct !CHECK-UNPARSE-NEXT: IMPLICIT NONE @@ -81,7 +85,7 @@ end subroutine !CHECK-UNPARSE-NEXT: INTEGER x !CHECK-UNPARSE-NEXT: INTEGER y(i) !CHECK-UNPARSE-NEXT: !$OMP DO -!CHECK-UNPARSE-NEXT: !$OMP UNROLL +!CHECK-UNPARSE-NEXT: !$OMP UNROLL PARTIAL(1_4) !CHECK-UNPARSE-NEXT: !$OMP TILE !CHECK-UNPARSE-NEXT: DO i=1_4,i !CHECK-UNPARSE-NEXT: y(int(i,kind=8))=5_4*y(int(i,kind=8)) diff --git a/flang/test/Parser/OpenMP/loop-transformation-construct03.f90 b/flang/test/Parser/OpenMP/loop-transformation-construct03.f90 index 8725025..10d87c4 100644 --- a/flang/test/Parser/OpenMP/loop-transformation-construct03.f90 +++ b/flang/test/Parser/OpenMP/loop-transformation-construct03.f90 @@ -25,42 +25,43 @@ end subroutine !CHECK-PARSE-NEXT: | | | | OmpClauseList -> OmpClause -> Collapse -> Scalar -> Integer -> Constant -> Expr = '2_4' !CHECK-PARSE-NEXT: | | | | | LiteralConstant -> IntLiteralConstant = '2' !CHECK-PARSE-NEXT: | | | | OmpClause -> Private -> OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'b' -!CHECK-PARSE-NEXT: | | | | Flags = None -!CHECK-PARSE-NEXT: | | | DoConstruct -!CHECK-PARSE-NEXT: | | | | NonLabelDoStmt -!CHECK-PARSE-NEXT: | | | | | LoopControl -> LoopBounds -!CHECK-PARSE-NEXT: | | | | | | Scalar -> Name = 'b' -!CHECK-PARSE-NEXT: | | | | | | Scalar -> Expr = '1_4' -!CHECK-PARSE-NEXT: | | | | | | | LiteralConstant -> IntLiteralConstant = '1' -!CHECK-PARSE-NEXT: | | | | | | Scalar -> Expr = '10_4' -!CHECK-PARSE-NEXT: | | | | | | | LiteralConstant -> IntLiteralConstant = '10' -!CHECK-PARSE-NEXT: | | | | Block -!CHECK-PARSE-NEXT: | | | | | ExecutionPartConstruct -> ExecutableConstruct -> DoConstruct -!CHECK-PARSE-NEXT: | | | | | | NonLabelDoStmt -!CHECK-PARSE-NEXT: | | | | | | | LoopControl -> LoopBounds -!CHECK-PARSE-NEXT: | | | | | | | | Scalar -> Name = 'c' -!CHECK-PARSE-NEXT: | | | | | | | | Scalar -> Expr = '1_4' -!CHECK-PARSE-NEXT: | | | | | | | | | LiteralConstant -> IntLiteralConstant = '1' -!CHECK-PARSE-NEXT: | | | | | | | | Scalar -> Expr = '10_4' -!CHECK-PARSE-NEXT: | | | | | | | | | LiteralConstant -> IntLiteralConstant = '10' -!CHECK-PARSE-NEXT: | | | | | | Block -!CHECK-PARSE-NEXT: | | | | | | | ExecutionPartConstruct -> ExecutableConstruct -> ActionStmt -> AssignmentStmt = 'a(int(b,kind=8),2_8)=a(int(c,kind=8),1_8)' -!CHECK-PARSE-NEXT: | | | | | | | | Variable = 'a(int(b,kind=8),2_8)' -!CHECK-PARSE-NEXT: | | | | | | | | | Designator -> DataRef -> ArrayElement -!CHECK-PARSE-NEXT: | | | | | | | | | | DataRef -> Name = 'a' -!CHECK-PARSE-NEXT: | | | | | | | | | | SectionSubscript -> Integer -> Expr = 'b' -!CHECK-PARSE-NEXT: | | | | | | | | | | | Designator -> DataRef -> Name = 'b' -!CHECK-PARSE-NEXT: | | | | | | | | | | SectionSubscript -> Integer -> Expr = '2_4' -!CHECK-PARSE-NEXT: | | | | | | | | | | | LiteralConstant -> IntLiteralConstant = '2' -!CHECK-PARSE-NEXT: | | | | | | | | Expr = 'a(int(c,kind=8),1_8)' -!CHECK-PARSE-NEXT: | | | | | | | | | Designator -> DataRef -> ArrayElement -!CHECK-PARSE-NEXT: | | | | | | | | | | DataRef -> Name = 'a' -!CHECK-PARSE-NEXT: | | | | | | | | | | SectionSubscript -> Integer -> Expr = 'c' -!CHECK-PARSE-NEXT: | | | | | | | | | | | Designator -> DataRef -> Name = 'c' -!CHECK-PARSE-NEXT: | | | | | | | | | | SectionSubscript -> Integer -> Expr = '1_4' -!CHECK-PARSE-NEXT: | | | | | | | | | | | LiteralConstant -> IntLiteralConstant = '1' -!CHECK-PARSE-NEXT: | | | | | | EndDoStmt -> -!CHECK-PARSE-NEXT: | | | | EndDoStmt -> +!CHECK-PARSE-NEXT: | | | | Flags = {} +!CHECK-PARSE-NEXT: | | | Block +!CHECK-PARSE-NEXT: | | | | ExecutionPartConstruct -> ExecutableConstruct -> DoConstruct +!CHECK-PARSE-NEXT: | | | | | NonLabelDoStmt +!CHECK-PARSE-NEXT: | | | | | | LoopControl -> LoopBounds +!CHECK-PARSE-NEXT: | | | | | | | Scalar -> Name = 'b' +!CHECK-PARSE-NEXT: | | | | | | | Scalar -> Expr = '1_4' +!CHECK-PARSE-NEXT: | | | | | | | | LiteralConstant -> IntLiteralConstant = '1' +!CHECK-PARSE-NEXT: | | | | | | | Scalar -> Expr = '10_4' +!CHECK-PARSE-NEXT: | | | | | | | | LiteralConstant -> IntLiteralConstant = '10' +!CHECK-PARSE-NEXT: | | | | | Block +!CHECK-PARSE-NEXT: | | | | | | ExecutionPartConstruct -> ExecutableConstruct -> DoConstruct +!CHECK-PARSE-NEXT: | | | | | | | NonLabelDoStmt +!CHECK-PARSE-NEXT: | | | | | | | | LoopControl -> LoopBounds +!CHECK-PARSE-NEXT: | | | | | | | | | Scalar -> Name = 'c' +!CHECK-PARSE-NEXT: | | | | | | | | | Scalar -> Expr = '1_4' +!CHECK-PARSE-NEXT: | | | | | | | | | | LiteralConstant -> IntLiteralConstant = '1' +!CHECK-PARSE-NEXT: | | | | | | | | | Scalar -> Expr = '10_4' +!CHECK-PARSE-NEXT: | | | | | | | | | | LiteralConstant -> IntLiteralConstant = '10' +!CHECK-PARSE-NEXT: | | | | | | | Block +!CHECK-PARSE-NEXT: | | | | | | | | ExecutionPartConstruct -> ExecutableConstruct -> ActionStmt -> AssignmentStmt = 'a(int(b,kind=8),2_8)=a(int(c,kind=8),1_8)' +!CHECK-PARSE-NEXT: | | | | | | | | | Variable = 'a(int(b,kind=8),2_8)' +!CHECK-PARSE-NEXT: | | | | | | | | | | Designator -> DataRef -> ArrayElement +!CHECK-PARSE-NEXT: | | | | | | | | | | | DataRef -> Name = 'a' +!CHECK-PARSE-NEXT: | | | | | | | | | | | SectionSubscript -> Integer -> Expr = 'b' +!CHECK-PARSE-NEXT: | | | | | | | | | | | | Designator -> DataRef -> Name = 'b' +!CHECK-PARSE-NEXT: | | | | | | | | | | | SectionSubscript -> Integer -> Expr = '2_4' +!CHECK-PARSE-NEXT: | | | | | | | | | | | | LiteralConstant -> IntLiteralConstant = '2' +!CHECK-PARSE-NEXT: | | | | | | | | | Expr = 'a(int(c,kind=8),1_8)' +!CHECK-PARSE-NEXT: | | | | | | | | | | Designator -> DataRef -> ArrayElement +!CHECK-PARSE-NEXT: | | | | | | | | | | | DataRef -> Name = 'a' +!CHECK-PARSE-NEXT: | | | | | | | | | | | SectionSubscript -> Integer -> Expr = 'c' +!CHECK-PARSE-NEXT: | | | | | | | | | | | | Designator -> DataRef -> Name = 'c' +!CHECK-PARSE-NEXT: | | | | | | | | | | | SectionSubscript -> Integer -> Expr = '1_4' +!CHECK-PARSE-NEXT: | | | | | | | | | | | | LiteralConstant -> IntLiteralConstant = '1' +!CHECK-PARSE-NEXT: | | | | | | | EndDoStmt -> +!CHECK-PARSE-NEXT: | | | | | EndDoStmt -> !CHECK-PARSE-NEXT: | EndSubroutineStmt -> !CHECK-UNPARSE: SUBROUTINE loop_transformation_construct7 diff --git a/flang/test/Parser/OpenMP/loop-transformation-construct04.f90 b/flang/test/Parser/OpenMP/loop-transformation-construct04.f90 new file mode 100644 index 0000000..4944347 --- /dev/null +++ b/flang/test/Parser/OpenMP/loop-transformation-construct04.f90 @@ -0,0 +1,80 @@ +! Test the Parse Tree to ensure the OpenMP Loop Transformation Construct Fuse constructs a correct sequence. + +! RUN: %flang_fc1 -fdebug-dump-parse-tree -fopenmp -fopenmp-version=51 %s | FileCheck %s --check-prefix=CHECK-PARSE +! RUN: %flang_fc1 -fdebug-unparse -fopenmp -fopenmp-version=51 %s | FileCheck %s --check-prefix=CHECK-UNPARSE + +subroutine loop_transformation_construct + implicit none + integer :: I = 10 + integer :: j + + !$omp do + !$omp fuse + do i = 1, I + continue + end do + do j = 1, I + continue + end do + !$omp end fuse + !$omp end do +end subroutine + +!CHECK-PARSE: | ExecutionPart -> Block +!CHECK-PARSE-NEXT: | | ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPLoopConstruct +!CHECK-PARSE-NEXT: | | | OmpBeginLoopDirective +!CHECK-PARSE-NEXT: | | | | OmpDirectiveName -> llvm::omp::Directive = do +!CHECK-PARSE-NEXT: | | | | OmpClauseList -> +!CHECK-PARSE-NEXT: | | | | Flags = {} +!CHECK-PARSE-NEXT: | | | Block +!CHECK-PARSE-NEXT: | | | | ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPLoopConstruct +!CHECK-PARSE-NEXT: | | | | | OmpBeginLoopDirective +!CHECK-PARSE-NEXT: | | | | | | OmpDirectiveName -> llvm::omp::Directive = fuse +!CHECK-PARSE-NEXT: | | | | | | OmpClauseList -> +!CHECK-PARSE-NEXT: | | | | | | Flags = {} +!CHECK-PARSE-NEXT: | | | | | Block +!CHECK-PARSE-NEXT: | | | | | | ExecutionPartConstruct -> ExecutableConstruct -> DoConstruct +!CHECK-PARSE-NEXT: | | | | | | | NonLabelDoStmt +!CHECK-PARSE-NEXT: | | | | | | | | LoopControl -> LoopBounds +!CHECK-PARSE-NEXT: | | | | | | | | | Scalar -> Name = 'i' +!CHECK-PARSE-NEXT: | | | | | | | | | Scalar -> Expr = '1_4' +!CHECK-PARSE-NEXT: | | | | | | | | | | LiteralConstant -> IntLiteralConstant = '1' +!CHECK-PARSE-NEXT: | | | | | | | | | Scalar -> Expr = 'i' +!CHECK-PARSE-NEXT: | | | | | | | | | | Designator -> DataRef -> Name = 'i' +!CHECK-PARSE-NEXT: | | | | | | | Block +!CHECK-PARSE-NEXT: | | | | | | | | ExecutionPartConstruct -> ExecutableConstruct -> ActionStmt -> ContinueStmt +!CHECK-PARSE-NEXT: | | | | | | | EndDoStmt -> +!CHECK-PARSE-NEXT: | | | | | | ExecutionPartConstruct -> ExecutableConstruct -> DoConstruct +!CHECK-PARSE-NEXT: | | | | | | | NonLabelDoStmt +!CHECK-PARSE-NEXT: | | | | | | | | LoopControl -> LoopBounds +!CHECK-PARSE-NEXT: | | | | | | | | | Scalar -> Name = 'j' +!CHECK-PARSE-NEXT: | | | | | | | | | Scalar -> Expr = '1_4' +!CHECK-PARSE-NEXT: | | | | | | | | | | LiteralConstant -> IntLiteralConstant = '1' +!CHECK-PARSE-NEXT: | | | | | | | | | Scalar -> Expr = 'i' +!CHECK-PARSE-NEXT: | | | | | | | | | | Designator -> DataRef -> Name = 'i' +!CHECK-PARSE-NEXT: | | | | | | | Block +!CHECK-PARSE-NEXT: | | | | | | | | ExecutionPartConstruct -> ExecutableConstruct -> ActionStmt -> ContinueStmt +!CHECK-PARSE-NEXT: | | | | | | | EndDoStmt -> +!CHECK-PARSE-NEXT: | | | | | OmpEndLoopDirective +!CHECK-PARSE-NEXT: | | | | | | OmpDirectiveName -> llvm::omp::Directive = fuse +!CHECK-PARSE-NEXT: | | | | | | OmpClauseList -> +!CHECK-PARSE-NEXT: | | | | | | Flags = {} +!CHECK-PARSE-NEXT: | | | OmpEndLoopDirective +!CHECK-PARSE-NEXT: | | | | OmpDirectiveName -> llvm::omp::Directive = do +!CHECK-PARSE-NEXT: | | | | OmpClauseList -> +!CHECK-PARSE-NEXT: | | | | Flags = {} + +!CHECK-UNPARSE: SUBROUTINE loop_transformation_construct +!CHECK-UNPARSE-NEXT: IMPLICIT NONE +!CHECK-UNPARSE-NEXT: INTEGER :: i = 10_4 +!CHECK-UNPARSE-NEXT: INTEGER j +!CHECK-UNPARSE-NEXT: !$OMP DO +!CHECK-UNPARSE-NEXT: !$OMP FUSE +!CHECK-UNPARSE-NEXT: DO i=1_4,i +!CHECK-UNPARSE-NEXT: CONTINUE +!CHECK-UNPARSE-NEXT: END DO +!CHECK-UNPARSE-NEXT: DO j=1_4,i +!CHECK-UNPARSE-NEXT: CONTINUE +!CHECK-UNPARSE-NEXT: END DO +!CHECK-UNPARSE-NEXT: !$OMP END FUSE +!CHECK-UNPARSE-NEXT: !$OMP END DO diff --git a/flang/test/Parser/OpenMP/loop-transformation-construct05.f90 b/flang/test/Parser/OpenMP/loop-transformation-construct05.f90 new file mode 100644 index 0000000..f266793 --- /dev/null +++ b/flang/test/Parser/OpenMP/loop-transformation-construct05.f90 @@ -0,0 +1,90 @@ +! Test the Parse Tree to ensure the OpenMP Loop Transformation Construct Fuse constructs a correct sequence +! and can correctly combine with loop nests + +! RUN: %flang_fc1 -fdebug-dump-parse-tree -fopenmp -fopenmp-version=51 %s | FileCheck %s --check-prefix=CHECK-PARSE +! RUN: %flang_fc1 -fdebug-unparse -fopenmp -fopenmp-version=51 %s | FileCheck %s --check-prefix=CHECK-UNPARSE + +subroutine loop_transformation_construct + implicit none + integer :: I = 10 + integer :: j + + !$omp do + !$omp fuse + do i = 1, I + continue + end do + !$omp tile sizes(2) + do j = 1, I + continue + end do + !$omp end fuse + !$omp end do +end subroutine + +!CHECK-PARSE: | ExecutionPart -> Block +!CHECK-PARSE-NEXT: | | ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPLoopConstruct +!CHECK-PARSE-NEXT: | | | OmpBeginLoopDirective +!CHECK-PARSE-NEXT: | | | | OmpDirectiveName -> llvm::omp::Directive = do +!CHECK-PARSE-NEXT: | | | | OmpClauseList -> +!CHECK-PARSE-NEXT: | | | | Flags = {} +!CHECK-PARSE-NEXT: | | | Block +!CHECK-PARSE-NEXT: | | | | ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPLoopConstruct +!CHECK-PARSE-NEXT: | | | | | OmpBeginLoopDirective +!CHECK-PARSE-NEXT: | | | | | | OmpDirectiveName -> llvm::omp::Directive = fuse +!CHECK-PARSE-NEXT: | | | | | | OmpClauseList -> +!CHECK-PARSE-NEXT: | | | | | | Flags = {} +!CHECK-PARSE-NEXT: | | | | | Block +!CHECK-PARSE-NEXT: | | | | | | ExecutionPartConstruct -> ExecutableConstruct -> DoConstruct +!CHECK-PARSE-NEXT: | | | | | | | NonLabelDoStmt +!CHECK-PARSE-NEXT: | | | | | | | | LoopControl -> LoopBounds +!CHECK-PARSE-NEXT: | | | | | | | | | Scalar -> Name = 'i' +!CHECK-PARSE-NEXT: | | | | | | | | | Scalar -> Expr = '1_4' +!CHECK-PARSE-NEXT: | | | | | | | | | | LiteralConstant -> IntLiteralConstant = '1' +!CHECK-PARSE-NEXT: | | | | | | | | | Scalar -> Expr = 'i' +!CHECK-PARSE-NEXT: | | | | | | | | | | Designator -> DataRef -> Name = 'i' +!CHECK-PARSE-NEXT: | | | | | | | Block +!CHECK-PARSE-NEXT: | | | | | | | | ExecutionPartConstruct -> ExecutableConstruct -> ActionStmt -> ContinueStmt +!CHECK-PARSE-NEXT: | | | | | | | EndDoStmt -> +!CHECK-PARSE-NEXT: | | | | | | ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPLoopConstruct +!CHECK-PARSE-NEXT: | | | | | | | OmpBeginLoopDirective +!CHECK-PARSE-NEXT: | | | | | | | | OmpDirectiveName -> llvm::omp::Directive = tile +!CHECK-PARSE-NEXT: | | | | | | | | OmpClauseList -> OmpClause -> Sizes -> Scalar -> Integer -> Expr = '2_4' +!CHECK-PARSE-NEXT: | | | | | | | | | LiteralConstant -> IntLiteralConstant = '2' +!CHECK-PARSE-NEXT: | | | | | | | | Flags = {} +!CHECK-PARSE-NEXT: | | | | | | | Block +!CHECK-PARSE-NEXT: | | | | | | | | ExecutionPartConstruct -> ExecutableConstruct -> DoConstruct +!CHECK-PARSE-NEXT: | | | | | | | | | NonLabelDoStmt +!CHECK-PARSE-NEXT: | | | | | | | | | | LoopControl -> LoopBounds +!CHECK-PARSE-NEXT: | | | | | | | | | | | Scalar -> Name = 'j' +!CHECK-PARSE-NEXT: | | | | | | | | | | | Scalar -> Expr = '1_4' +!CHECK-PARSE-NEXT: | | | | | | | | | | | | LiteralConstant -> IntLiteralConstant = '1' +!CHECK-PARSE-NEXT: | | | | | | | | | | | Scalar -> Expr = 'i' +!CHECK-PARSE-NEXT: | | | | | | | | | | | | Designator -> DataRef -> Name = 'i' +!CHECK-PARSE-NEXT: | | | | | | | | | Block +!CHECK-PARSE-NEXT: | | | | | | | | | | ExecutionPartConstruct -> ExecutableConstruct -> ActionStmt -> ContinueStmt +!CHECK-PARSE-NEXT: | | | | | | | | | EndDoStmt -> +!CHECK-PARSE-NEXT: | | | | | OmpEndLoopDirective +!CHECK-PARSE-NEXT: | | | | | | OmpDirectiveName -> llvm::omp::Directive = fuse +!CHECK-PARSE-NEXT: | | | | | | OmpClauseList -> +!CHECK-PARSE-NEXT: | | | | | | Flags = {} +!CHECK-PARSE-NEXT: | | | OmpEndLoopDirective +!CHECK-PARSE-NEXT: | | | | OmpDirectiveName -> llvm::omp::Directive = do +!CHECK-PARSE-NEXT: | | | | OmpClauseList -> +!CHECK-PARSE-NEXT: | | | | Flags = {} + +!CHECK-UNPARSE: SUBROUTINE loop_transformation_construct +!CHECK-UNPARSE-NEXT: IMPLICIT NONE +!CHECK-UNPARSE-NEXT: INTEGER :: i = 10_4 +!CHECK-UNPARSE-NEXT: INTEGER j +!CHECK-UNPARSE-NEXT: !$OMP DO +!CHECK-UNPARSE-NEXT: !$OMP FUSE +!CHECK-UNPARSE-NEXT: DO i=1_4,i +!CHECK-UNPARSE-NEXT: CONTINUE +!CHECK-UNPARSE-NEXT: END DO +!CHECK-UNPARSE-NEXT: !$OMP TILE +!CHECK-UNPARSE-NEXT: DO j=1_4,i +!CHECK-UNPARSE-NEXT: CONTINUE +!CHECK-UNPARSE-NEXT: END DO +!CHECK-UNPARSE-NEXT: !$OMP END FUSE +!CHECK-UNPARSE-NEXT: !$OMP END DO diff --git a/flang/test/Parser/OpenMP/map-modifiers-v61.f90 b/flang/test/Parser/OpenMP/map-modifiers-v61.f90 index 79bf73a..f1e41fb 100644 --- a/flang/test/Parser/OpenMP/map-modifiers-v61.f90 +++ b/flang/test/Parser/OpenMP/map-modifiers-v61.f90 @@ -19,7 +19,7 @@ end !PARSE-TREE: | | Modifier -> OmpAttachModifier -> Value = Always !PARSE-TREE: | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'x' !PARSE-TREE: | | bool = 'true' -!PARSE-TREE: | Flags = None +!PARSE-TREE: | Flags = {} subroutine f01(x) @@ -40,7 +40,7 @@ end !PARSE-TREE: | | Modifier -> OmpAttachModifier -> Value = Auto !PARSE-TREE: | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'x' !PARSE-TREE: | | bool = 'true' -!PARSE-TREE: | Flags = None +!PARSE-TREE: | Flags = {} subroutine f02(x) @@ -61,4 +61,4 @@ end !PARSE-TREE: | | Modifier -> OmpAttachModifier -> Value = Never !PARSE-TREE: | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'x' !PARSE-TREE: | | bool = 'true' -!PARSE-TREE: | Flags = None +!PARSE-TREE: | Flags = {} diff --git a/flang/test/Parser/OpenMP/map-modifiers.f90 b/flang/test/Parser/OpenMP/map-modifiers.f90 index 83662b7..7d9b885 100644 --- a/flang/test/Parser/OpenMP/map-modifiers.f90 +++ b/flang/test/Parser/OpenMP/map-modifiers.f90 @@ -320,7 +320,7 @@ subroutine f21(x, y) integer :: x(10) integer :: y integer, parameter :: p = 23 - !$omp target map(mapper(xx), from: x) + !$omp target map(mapper(default), from: x) x = x + 1 !$omp end target end @@ -329,7 +329,7 @@ end !UNPARSE: INTEGER x(10_4) !UNPARSE: INTEGER y !UNPARSE: INTEGER, PARAMETER :: p = 23_4 -!UNPARSE: !$OMP TARGET MAP(MAPPER(XX), FROM: X) +!UNPARSE: !$OMP TARGET MAP(MAPPER(DEFAULT), FROM: X) !UNPARSE: x=x+1_4 !UNPARSE: !$OMP END TARGET !UNPARSE: END SUBROUTINE @@ -337,7 +337,7 @@ end !PARSE-TREE: OmpBeginDirective !PARSE-TREE: | OmpDirectiveName -> llvm::omp::Directive = target !PARSE-TREE: | OmpClauseList -> OmpClause -> Map -> OmpMapClause -!PARSE-TREE: | | Modifier -> OmpMapper -> Name = 'xx' +!PARSE-TREE: | | Modifier -> OmpMapper -> Name = 'default' !PARSE-TREE: | | Modifier -> OmpMapType -> Value = From !PARSE-TREE: | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'x' @@ -375,4 +375,3 @@ end !PARSE-TREE: | | SectionSubscript -> Integer -> Expr = 'i' !PARSE-TREE: | | | Designator -> DataRef -> Name = 'i' !PARSE-TREE: | bool = 'true' - diff --git a/flang/test/Parser/OpenMP/masked-unparse.f90 b/flang/test/Parser/OpenMP/masked-unparse.f90 index 786b604..7156f4c 100644 --- a/flang/test/Parser/OpenMP/masked-unparse.f90 +++ b/flang/test/Parser/OpenMP/masked-unparse.f90 @@ -1,7 +1,7 @@ ! RUN: %flang_fc1 -fdebug-unparse -fopenmp %s | FileCheck --ignore-case %s ! RUN: %flang_fc1 -fdebug-dump-parse-tree -fopenmp %s | FileCheck --check-prefix="PARSE-TREE" %s -! Check for parsing of masked directive with filter clause. +! Check for parsing of masked directive with filter clause. subroutine test_masked() @@ -9,7 +9,7 @@ subroutine test_masked() !PARSE-TREE: OmpBeginDirective !PARSE-TREE-NEXT: OmpDirectiveName -> llvm::omp::Directive = masked !CHECK: !$omp masked - !$omp masked + !$omp masked c = c + 1 !$omp end masked !PARSE-TREE: OmpBeginDirective @@ -17,7 +17,7 @@ subroutine test_masked() !PARSE-TREE-NEXT: OmpClauseList -> OmpClause -> Filter -> Scalar -> Integer -> Expr = '1_4' !PARSE-TREE-NEXT: LiteralConstant -> IntLiteralConstant = '1' !CHECK: !$omp masked filter(1_4) - !$omp masked filter(1) + !$omp masked filter(1) c = c + 2 !$omp end masked end subroutine @@ -27,7 +27,7 @@ subroutine test_masked_taskloop_simd() !PARSE-TREE: OmpBeginLoopDirective !PARSE-TREE-NEXT: OmpDirectiveName -> llvm::omp::Directive = masked taskloop simd !CHECK: !$omp masked taskloop simd - !$omp masked taskloop simd + !$omp masked taskloop simd do i=1,10 j = j + 1 end do @@ -41,11 +41,11 @@ subroutine test_masked_taskloop !PARSE-TREE-NEXT: OmpClauseList -> OmpClause -> Filter -> Scalar -> Integer -> Expr = '2_4' !PARSE-TREE-NEXT: LiteralConstant -> IntLiteralConstant = '2' !CHECK: !$omp masked taskloop filter(2_4) - !$omp masked taskloop filter(2) + !$omp masked taskloop filter(2) do i=1,10 j = j + 1 end do - !$omp end masked taskloop + !$omp end masked taskloop end subroutine subroutine test_parallel_masked @@ -70,7 +70,7 @@ subroutine test_parallel_masked_taskloop_simd !PARSE-TREE: OmpBeginLoopDirective !PARSE-TREE-NEXT: OmpDirectiveName -> llvm::omp::Directive = parallel masked taskloop simd !CHECK: !$omp parallel masked taskloop simd - !$omp parallel masked taskloop simd + !$omp parallel masked taskloop simd do i=1,10 j = j + 1 end do @@ -84,9 +84,9 @@ subroutine test_parallel_masked_taskloop !PARSE-TREE-NEXT: OmpClauseList -> OmpClause -> Filter -> Scalar -> Integer -> Expr = '2_4' !PARSE-TREE-NEXT: LiteralConstant -> IntLiteralConstant = '2' !CHECK: !$omp parallel masked taskloop filter(2_4) - !$omp parallel masked taskloop filter(2) + !$omp parallel masked taskloop filter(2) do i=1,10 j = j + 1 end do - !$omp end parallel masked taskloop + !$omp end parallel masked taskloop end subroutine diff --git a/flang/test/Parser/OpenMP/master-unparse.f90 b/flang/test/Parser/OpenMP/master-unparse.f90 index 36935d4..bee6c96 100644 --- a/flang/test/Parser/OpenMP/master-unparse.f90 +++ b/flang/test/Parser/OpenMP/master-unparse.f90 @@ -9,7 +9,7 @@ subroutine test_master() !PARSE-TREE: OmpBeginDirective !PARSE-TREE-NEXT: OmpDirectiveName -> llvm::omp::Directive = master !CHECK: !$omp master - !$omp master + !$omp master c = c + 1 !$omp end master end subroutine @@ -19,7 +19,7 @@ subroutine test_master_taskloop_simd() !PARSE-TREE: OmpBeginLoopDirective !PARSE-TREE-NEXT: OmpDirectiveName -> llvm::omp::Directive = master taskloop simd !CHECK: !$omp master taskloop simd - !$omp master taskloop simd + !$omp master taskloop simd do i=1,10 j = j + 1 end do @@ -35,7 +35,7 @@ subroutine test_master_taskloop do i=1,10 j = j + 1 end do - !$omp end master taskloop + !$omp end master taskloop end subroutine subroutine test_parallel_master @@ -53,7 +53,7 @@ subroutine test_parallel_master_taskloop_simd !PARSE-TREE: OmpBeginLoopDirective !PARSE-TREE-NEXT: OmpDirectiveName -> llvm::omp::Directive = parallel master taskloop simd !CHECK: !$omp parallel master taskloop simd - !$omp parallel master taskloop simd + !$omp parallel master taskloop simd do i=1,10 j = j + 1 end do @@ -69,5 +69,5 @@ subroutine test_parallel_master_taskloop do i=1,10 j = j + 1 end do - !$omp end parallel master taskloop + !$omp end parallel master taskloop end subroutine diff --git a/flang/test/Parser/OpenMP/metadirective-dirspec.f90 b/flang/test/Parser/OpenMP/metadirective-dirspec.f90 index b64ceb1..a240271 100644 --- a/flang/test/Parser/OpenMP/metadirective-dirspec.f90 +++ b/flang/test/Parser/OpenMP/metadirective-dirspec.f90 @@ -164,7 +164,7 @@ end !PARSE-TREE: | | | | | | | | | | DataRef -> Name = 'omp_out' !PARSE-TREE: | | | | | | | | | | Name = 'x' !PARSE-TREE: | | | OmpClauseList -> -!PARSE-TREE: | | | Flags = None +!PARSE-TREE: | | | Flags = {} subroutine f04 !$omp metadirective when(user={condition(.true.)}: & diff --git a/flang/test/Parser/OpenMP/metadirective-flush.f90 b/flang/test/Parser/OpenMP/metadirective-flush.f90 index 0837910..e4e521e 100644 --- a/flang/test/Parser/OpenMP/metadirective-flush.f90 +++ b/flang/test/Parser/OpenMP/metadirective-flush.f90 @@ -25,7 +25,7 @@ end !PARSE-TREE: | | | OmpDirectiveName -> llvm::omp::Directive = flush !PARSE-TREE: | | | OmpArgumentList -> OmpArgument -> OmpLocator -> OmpObject -> Designator -> DataRef -> Name = 'x' !PARSE-TREE: | | | OmpClauseList -> OmpClause -> SeqCst -!PARSE-TREE: | | | Flags = DeprecatedSyntax +!PARSE-TREE: | | | Flags = {DeprecatedSyntax} subroutine f01() integer :: x @@ -51,4 +51,4 @@ end !PARSE-TREE: | | | OmpDirectiveName -> llvm::omp::Directive = flush !PARSE-TREE: | | | OmpArgumentList -> OmpArgument -> OmpLocator -> OmpObject -> Designator -> DataRef -> Name = 'x' !PARSE-TREE: | | | OmpClauseList -> OmpClause -> SeqCst -!PARSE-TREE: | | | Flags = None +!PARSE-TREE: | | | Flags = {} diff --git a/flang/test/Parser/OpenMP/name-with-space.f b/flang/test/Parser/OpenMP/name-with-space.f new file mode 100644 index 0000000..603ebc4 --- /dev/null +++ b/flang/test/Parser/OpenMP/name-with-space.f @@ -0,0 +1,15 @@ +! RUN: %flang_fc1 -fopenmp -fdebug-unparse-no-sema %s 2>&1 | FileCheck %s + + program name_with_space +!CHECK: !$OMP THREADPRIVATE(/cc/, var1) +!$omp threadprivate(/c c/, var 1) + +!CHECK: !$OMP PARALLEL PRIVATE(somevar,expr1,expr2) IF(expr2>expr1) +!$omp parallel private(some var, expr 1, ex pr2) +!$omp+ if (exp r2 > ex pr1) +!$omp critical (x_x) + print '(a)', 'Hello World' +!CHECK: !$OMP END CRITICAL(x_x) +!$omp end critical (x _x) +!$omp end parallel + end program name_with_space diff --git a/flang/test/Parser/OpenMP/nested-directive.f90 b/flang/test/Parser/OpenMP/nested-directive.f90 new file mode 100644 index 0000000..2a10bbe --- /dev/null +++ b/flang/test/Parser/OpenMP/nested-directive.f90 @@ -0,0 +1,7 @@ +! RUN: %flang_fc1 -fdebug-unparse -fopenmp %s 2>&1 | FileCheck %s --match-full-lines + +subroutine func + implicit none +! CHECK: !$OMP NOTHING + !$omp nothing !$omp Cannot nest directives inside directives; must be interpreted as a comment +end subroutine func diff --git a/flang/test/Parser/OpenMP/openmp6-directive-spellings.f90 b/flang/test/Parser/OpenMP/openmp6-directive-spellings.f90 index 50a38c6..9f39066 100644 --- a/flang/test/Parser/OpenMP/openmp6-directive-spellings.f90 +++ b/flang/test/Parser/OpenMP/openmp6-directive-spellings.f90 @@ -38,7 +38,7 @@ end !PARSE-TREE: | OmpDirectiveName -> llvm::omp::Directive = cancellation point !PARSE-TREE: | OmpClauseList -> OmpClause -> CancellationConstructType -> OmpCancellationConstructTypeClause !PARSE-TREE: | | OmpDirectiveName -> llvm::omp::Directive = parallel -!PARSE-TREE: | Flags = None +!PARSE-TREE: | Flags = {} subroutine f01 type :: t @@ -57,7 +57,7 @@ end !PARSE-TREE: DeclarationConstruct -> SpecificationConstruct -> OpenMPDeclarativeConstruct -> OpenMPDeclareMapperConstruct -> OmpDirectiveSpecification !PARSE-TREE: | OmpDirectiveName -> llvm::omp::Directive = declare mapper !PARSE-TREE: | OmpArgumentList -> OmpArgument -> OmpMapperSpecifier -!PARSE-TREE: | | string = 't.omp.default.mapper' +!PARSE-TREE: | | string = 't_omp_default_mapper' !PARSE-TREE: | | TypeSpec -> DerivedTypeSpec !PARSE-TREE: | | | Name = 't' !PARSE-TREE: | | Name = 'v' @@ -66,7 +66,7 @@ end !PARSE-TREE: | | | DataRef -> Name = 'v' !PARSE-TREE: | | | Name = 'x' !PARSE-TREE: | | bool = 'true' -!PARSE-TREE: | Flags = None +!PARSE-TREE: | Flags = {} subroutine f02 type :: t @@ -107,7 +107,7 @@ end !PARSE-TREE: | | | | | | | | DataRef -> Name = 'omp_in' !PARSE-TREE: | | | | | | | | Name = 'x' !PARSE-TREE: | OmpClauseList -> -!PARSE-TREE: | Flags = None +!PARSE-TREE: | Flags = {} subroutine f03 !$omp declare_simd @@ -120,7 +120,7 @@ end !PARSE-TREE: OpenMPDeclarativeConstruct -> OpenMPDeclareSimdConstruct -> OmpDirectiveSpecification !PARSE-TREE: | OmpDirectiveName -> llvm::omp::Directive = declare simd !PARSE-TREE: | OmpClauseList -> -!PARSE-TREE: | Flags = None +!PARSE-TREE: | Flags = {} subroutine f04 !$omp declare_target @@ -133,7 +133,7 @@ end !PARSE-TREE: OpenMPDeclarativeConstruct -> OpenMPDeclareTargetConstruct -> OmpDirectiveSpecification !PARSE-TREE: | OmpDirectiveName -> llvm::omp::Directive = declare target !PARSE-TREE: | OmpClauseList -> -!PARSE-TREE: | Flags = None +!PARSE-TREE: | Flags = {} subroutine f05 implicit none @@ -164,7 +164,7 @@ end !PARSE-TREE: | | | | OmpTraitProperty -> Scalar -> Expr = '.true._4' !PARSE-TREE: | | | | | LiteralConstant -> LogicalLiteralConstant !PARSE-TREE: | | | | | | bool = 'true' -!PARSE-TREE: | Flags = None +!PARSE-TREE: | Flags = {} subroutine f06 implicit none @@ -217,7 +217,7 @@ end !PARSE-TREE: | | Modifier -> OmpMapType -> Value = To !PARSE-TREE: | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'i' !PARSE-TREE: | | bool = 'true' -!PARSE-TREE: | Flags = None +!PARSE-TREE: | Flags = {} subroutine f08 implicit none @@ -237,7 +237,7 @@ end !PARSE-TREE: | | Modifier -> OmpMapType -> Value = From !PARSE-TREE: | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'i' !PARSE-TREE: | | bool = 'true' -!PARSE-TREE: | Flags = None +!PARSE-TREE: | Flags = {} subroutine f09 implicit none @@ -256,4 +256,4 @@ end !PARSE-TREE: | OmpClauseList -> OmpClause -> To -> OmpToClause !PARSE-TREE: | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'i' !PARSE-TREE: | | bool = 'true' -!PARSE-TREE: | Flags = None +!PARSE-TREE: | Flags = {} diff --git a/flang/test/Parser/OpenMP/order-clause01.f90 b/flang/test/Parser/OpenMP/order-clause01.f90 index 087e400..5fc1b58 100644 --- a/flang/test/Parser/OpenMP/order-clause01.f90 +++ b/flang/test/Parser/OpenMP/order-clause01.f90 @@ -18,7 +18,7 @@ end subroutine !PARSE-TREE-NEXT: OmpDirectiveName -> llvm::omp::Directive = do !PARSE-TREE-NEXT: OmpClauseList -> OmpClause -> Order -> OmpOrderClause !PARSE-TREE-NEXT: Ordering = Concurrent -!PARSE-TREE-NEXT: Flags = None +!PARSE-TREE-NEXT: Flags = {} subroutine test_simd_order_reproducible() integer :: i, j = 1 @@ -36,7 +36,7 @@ end subroutine !PARSE-TREE-NEXT: OmpClauseList -> OmpClause -> Order -> OmpOrderClause !PARSE-TREE-NEXT: OmpOrderModifier -> Value = Reproducible !PARSE-TREE-NEXT: Ordering = Concurrent -!PARSE-TREE-NEXT: Flags = None +!PARSE-TREE-NEXT: Flags = {} subroutine test_do_simd_order_unconstrained() integer :: i, j = 1 @@ -54,7 +54,7 @@ end subroutine !PARSE-TREE-NEXT: OmpClauseList -> OmpClause -> Order -> OmpOrderClause !PARSE-TREE-NEXT: OmpOrderModifier -> Value = Unconstrained !PARSE-TREE-NEXT: Ordering = Concurrent -!PARSE-TREE-NEXT: Flags = None +!PARSE-TREE-NEXT: Flags = {} subroutine test_parallel_do_order() integer :: i, j = 1 @@ -71,7 +71,7 @@ end subroutine !PARSE-TREE-NEXT: OmpDirectiveName -> llvm::omp::Directive = parallel do !PARSE-TREE-NEXT: OmpClauseList -> OmpClause -> Order -> OmpOrderClause !PARSE-TREE-NEXT: Ordering = Concurrent -!PARSE-TREE-NEXT: Flags = None +!PARSE-TREE-NEXT: Flags = {} subroutine test_parallel_do_simd_order_reproducible() integer :: i, j = 1 @@ -89,7 +89,7 @@ end subroutine !PARSE-TREE-NEXT: OmpClauseList -> OmpClause -> Order -> OmpOrderClause !PARSE-TREE-NEXT: OmpOrderModifier -> Value = Reproducible !PARSE-TREE-NEXT: Ordering = Concurrent -!PARSE-TREE-NEXT: Flags = None +!PARSE-TREE-NEXT: Flags = {} subroutine test_target_simd_order_unconstrained() integer :: i, j = 1 @@ -107,7 +107,7 @@ end subroutine !PARSE-TREE-NEXT: OmpClauseList -> OmpClause -> Order -> OmpOrderClause !PARSE-TREE-NEXT: OmpOrderModifier -> Value = Unconstrained !PARSE-TREE-NEXT: Ordering = Concurrent -!PARSE-TREE-NEXT: Flags = None +!PARSE-TREE-NEXT: Flags = {} subroutine test_target_parallel_do_order() integer :: i, j = 1 @@ -124,7 +124,7 @@ end subroutine !PARSE-TREE-NEXT: OmpDirectiveName -> llvm::omp::Directive = target parallel do !PARSE-TREE-NEXT: OmpClauseList -> OmpClause -> Order -> OmpOrderClause !PARSE-TREE-NEXT: Ordering = Concurrent -!PARSE-TREE-NEXT: Flags = None +!PARSE-TREE-NEXT: Flags = {} subroutine test_target_parallel_do_simd_order_reproducible() integer :: i, j = 1 @@ -142,7 +142,7 @@ end subroutine !PARSE-TREE-NEXT: OmpClauseList -> OmpClause -> Order -> OmpOrderClause !PARSE-TREE-NEXT: OmpOrderModifier -> Value = Reproducible !PARSE-TREE-NEXT: Ordering = Concurrent -!PARSE-TREE-NEXT: Flags = None +!PARSE-TREE-NEXT: Flags = {} subroutine test_teams_distribute_simd_order_unconstrained() integer :: i, j = 1 @@ -160,7 +160,7 @@ end subroutine !PARSE-TREE-NEXT: OmpClauseList -> OmpClause -> Order -> OmpOrderClause !PARSE-TREE-NEXT: OmpOrderModifier -> Value = Unconstrained !PARSE-TREE-NEXT: Ordering = Concurrent -!PARSE-TREE-NEXT: Flags = None +!PARSE-TREE-NEXT: Flags = {} subroutine test_teams_distribute_parallel_do_order() integer :: i, j = 1 @@ -177,7 +177,7 @@ end subroutine !PARSE-TREE-NEXT: OmpDirectiveName -> llvm::omp::Directive = teams distribute parallel do !PARSE-TREE-NEXT: OmpClauseList -> OmpClause -> Order -> OmpOrderClause !PARSE-TREE-NEXT: Ordering = Concurrent -!PARSE-TREE-NEXT: Flags = None +!PARSE-TREE-NEXT: Flags = {} subroutine test_teams_distribute_parallel_do_simd_order_reproducible() integer :: i, j = 1 @@ -195,7 +195,7 @@ end subroutine !PARSE-TREE-NEXT: OmpClauseList -> OmpClause -> Order -> OmpOrderClause !PARSE-TREE-NEXT: OmpOrderModifier -> Value = Reproducible !PARSE-TREE-NEXT: Ordering = Concurrent -!PARSE-TREE-NEXT: Flags = None +!PARSE-TREE-NEXT: Flags = {} subroutine test_target_teams_distribute_simd_order_unconstrained() integer :: i, j = 1 @@ -213,7 +213,7 @@ end subroutine !PARSE-TREE-NEXT: OmpClauseList -> OmpClause -> Order -> OmpOrderClause !PARSE-TREE-NEXT: OmpOrderModifier -> Value = Unconstrained !PARSE-TREE-NEXT: Ordering = Concurrent -!PARSE-TREE-NEXT: Flags = None +!PARSE-TREE-NEXT: Flags = {} subroutine test_target_teams_distribute_parallel_do_order() integer :: i, j = 1 @@ -230,7 +230,7 @@ end subroutine !PARSE-TREE-NEXT: OmpDirectiveName -> llvm::omp::Directive = target teams distribute parallel do !PARSE-TREE-NEXT: OmpClauseList -> OmpClause -> Order -> OmpOrderClause !PARSE-TREE-NEXT: Ordering = Concurrent -!PARSE-TREE-NEXT: Flags = None +!PARSE-TREE-NEXT: Flags = {} subroutine test_target_teams_distribute_parallel_do_simd_order_reproducible() integer :: i, j = 1 @@ -248,7 +248,7 @@ end subroutine !PARSE-TREE-NEXT: OmpClauseList -> OmpClause -> Order -> OmpOrderClause !PARSE-TREE-NEXT: OmpOrderModifier -> Value = Reproducible !PARSE-TREE-NEXT: Ordering = Concurrent -!PARSE-TREE-NEXT: Flags = None +!PARSE-TREE-NEXT: Flags = {} subroutine test_taskloop_simd_order_unconstrained() integer :: i, j = 1 @@ -266,4 +266,4 @@ end subroutine !PARSE-TREE-NEXT: OmpClauseList -> OmpClause -> Order -> OmpOrderClause !PARSE-TREE-NEXT: OmpOrderModifier -> Value = Unconstrained !PARSE-TREE-NEXT: Ordering = Concurrent -!PARSE-TREE-NEXT: Flags = None +!PARSE-TREE-NEXT: Flags = {} diff --git a/flang/test/Parser/OpenMP/ordered-block-vs-standalone.f90 b/flang/test/Parser/OpenMP/ordered-block-vs-standalone.f90 index 58f1eae..abc4258 100644 --- a/flang/test/Parser/OpenMP/ordered-block-vs-standalone.f90 +++ b/flang/test/Parser/OpenMP/ordered-block-vs-standalone.f90 @@ -11,7 +11,7 @@ subroutine standalone ! CHECK: OpenMPConstruct -> OpenMPStandaloneConstruct ! CHECK-NEXT: | OmpDirectiveName -> llvm::omp::Directive = ordered ! CHECK-NEXT: | OmpClauseList -> - ! CHECK-NEXT: | Flags = None + ! CHECK-NEXT: | Flags = {} !$omp ordered depend(source) x(i, j) = i + j end do @@ -29,7 +29,7 @@ subroutine strict_block ! CHECK-NEXT: | OmpBeginDirective ! CHECK-NEXT: | | OmpDirectiveName -> llvm::omp::Directive = ordered ! CHECK-NEXT: | | OmpClauseList -> - ! CHECK-NEXT: | | Flags = None + ! CHECK-NEXT: | | Flags = {} !$omp ordered block tmp = i + j @@ -50,7 +50,7 @@ subroutine loose_block ! CHECK-NEXT: | OmpBeginDirective ! CHECK-NEXT: | | OmpDirectiveName -> llvm::omp::Directive = ordered ! CHECK-NEXT: | | OmpClauseList -> - ! CHECK-NEXT: | | Flags = None + ! CHECK-NEXT: | | Flags = {} !$omp ordered tmp = i + j x(i, j) = tmp diff --git a/flang/test/Parser/OpenMP/replayable-clause.f90 b/flang/test/Parser/OpenMP/replayable-clause.f90 index c173344..24ccc01 100644 --- a/flang/test/Parser/OpenMP/replayable-clause.f90 +++ b/flang/test/Parser/OpenMP/replayable-clause.f90 @@ -17,7 +17,7 @@ end !PARSE-TREE: | OmpBeginDirective !PARSE-TREE: | | OmpDirectiveName -> llvm::omp::Directive = task !PARSE-TREE: | | OmpClauseList -> OmpClause -> Replayable -> -!PARSE-TREE: | | Flags = None +!PARSE-TREE: | | Flags = {} !PARSE-TREE: | Block @@ -41,7 +41,7 @@ end !PARSE-TREE: | OmpClause -> Replayable -> OmpReplayableClause -> Scalar -> Logical -> Constant -> Expr = '.true._4' !PARSE-TREE: | | LiteralConstant -> LogicalLiteralConstant !PARSE-TREE: | | | bool = 'true' -!PARSE-TREE: | Flags = None +!PARSE-TREE: | Flags = {} subroutine f02 @@ -57,4 +57,4 @@ end !PARSE-TREE: | OmpClauseList -> OmpClause -> Replayable -> OmpReplayableClause -> Scalar -> Logical -> Constant -> Expr = '.false._4' !PARSE-TREE: | | LiteralConstant -> LogicalLiteralConstant !PARSE-TREE: | | | bool = 'false' -!PARSE-TREE: | Flags = None +!PARSE-TREE: | Flags = {} diff --git a/flang/test/Parser/OpenMP/requires.f90 b/flang/test/Parser/OpenMP/requires.f90 index ab4f437..49d7873 100644 --- a/flang/test/Parser/OpenMP/requires.f90 +++ b/flang/test/Parser/OpenMP/requires.f90 @@ -8,7 +8,7 @@ !PARSE-TREE: OpenMPDeclarativeConstruct -> OpenMPRequiresConstruct -> OmpDirectiveSpecification !PARSE-TREE: | OmpDirectiveName -> llvm::omp::Directive = requires !PARSE-TREE: | OmpClauseList -> OmpClause -> AtomicDefaultMemOrder -> OmpAtomicDefaultMemOrderClause -> OmpMemoryOrderType = Seq_Cst -!PARSE-TREE: | Flags = None +!PARSE-TREE: | Flags = {} !$omp requires unified_shared_memory unified_address @@ -18,7 +18,7 @@ !PARSE-TREE: | OmpDirectiveName -> llvm::omp::Directive = requires !PARSE-TREE: | OmpClauseList -> OmpClause -> UnifiedSharedMemory !PARSE-TREE: | OmpClause -> UnifiedAddress -!PARSE-TREE: | Flags = None +!PARSE-TREE: | Flags = {} !$omp requires dynamic_allocators reverse_offload @@ -28,7 +28,7 @@ !PARSE-TREE: | OmpDirectiveName -> llvm::omp::Directive = requires !PARSE-TREE: | OmpClauseList -> OmpClause -> DynamicAllocators !PARSE-TREE: | OmpClause -> ReverseOffload -!PARSE-TREE: | Flags = None +!PARSE-TREE: | Flags = {} !$omp requires self_maps(.true.) unified_address(.false.) @@ -42,7 +42,7 @@ !PARSE-TREE: | OmpClause -> UnifiedAddress -> OmpUnifiedAddressClause -> Scalar -> Logical -> Constant -> Expr = '.false._4' !PARSE-TREE: | | LiteralConstant -> LogicalLiteralConstant !PARSE-TREE: | | | bool = 'false' -!PARSE-TREE: | Flags = None +!PARSE-TREE: | Flags = {} !$omp requires device_safesync @@ -51,6 +51,6 @@ !PARSE-TREE: OpenMPDeclarativeConstruct -> OpenMPRequiresConstruct -> OmpDirectiveSpecification !PARSE-TREE: | OmpDirectiveName -> llvm::omp::Directive = requires !PARSE-TREE: | OmpClauseList -> OmpClause -> DeviceSafesync -!PARSE-TREE: | Flags = None +!PARSE-TREE: | Flags = {} end diff --git a/flang/test/Parser/OpenMP/sections.f90 b/flang/test/Parser/OpenMP/sections.f90 index 76e6b90..54b3e66 100644 --- a/flang/test/Parser/OpenMP/sections.f90 +++ b/flang/test/Parser/OpenMP/sections.f90 @@ -17,13 +17,13 @@ subroutine openmp_sections(x, y) !PARSE-TREE: | OmpBeginSectionsDirective !PARSE-TREE: | | OmpDirectiveName -> llvm::omp::Directive = sections !PARSE-TREE: | | OmpClauseList -> -!PARSE-TREE: | | Flags = None +!PARSE-TREE: | | Flags = {} !PARSE-TREE: | OpenMPConstruct -> OpenMPSectionConstruct !PARSE-TREE: | | Block !PARSE-TREE: | OmpEndSectionsDirective !PARSE-TREE: | | OmpDirectiveName -> llvm::omp::Directive = sections !PARSE-TREE: | | OmpClauseList -> -!PARSE-TREE: | | Flags = None +!PARSE-TREE: | | Flags = {} !============================================================================== ! single section, without `!$omp section` @@ -39,7 +39,7 @@ subroutine openmp_sections(x, y) !PARSE-TREE: | OmpBeginSectionsDirective !PARSE-TREE: | | OmpDirectiveName -> llvm::omp::Directive = sections !PARSE-TREE: | | OmpClauseList -> -!PARSE-TREE: | | Flags = None +!PARSE-TREE: | | Flags = {} !PARSE-TREE: | OpenMPConstruct -> OpenMPSectionConstruct !PARSE-TREE: | | Block !PARSE-TREE: | | | ExecutionPartConstruct -> ExecutableConstruct -> ActionStmt -> CallStmt = 'CALL f1()' @@ -48,7 +48,7 @@ subroutine openmp_sections(x, y) !PARSE-TREE: | OmpEndSectionsDirective !PARSE-TREE: | | OmpDirectiveName -> llvm::omp::Directive = sections !PARSE-TREE: | | OmpClauseList -> -!PARSE-TREE: | | Flags = None +!PARSE-TREE: | | Flags = {} !============================================================================== ! single section with `!$omp section` @@ -66,12 +66,12 @@ subroutine openmp_sections(x, y) !PARSE-TREE: | OmpBeginSectionsDirective !PARSE-TREE: | | OmpDirectiveName -> llvm::omp::Directive = sections !PARSE-TREE: | | OmpClauseList -> -!PARSE-TREE: | | Flags = None +!PARSE-TREE: | | Flags = {} !PARSE-TREE: | OpenMPConstruct -> OpenMPSectionConstruct !PARSE-TREE: | | OmpDirectiveSpecification !PARSE-TREE: | | | OmpDirectiveName -> llvm::omp::Directive = section !PARSE-TREE: | | | OmpClauseList -> -!PARSE-TREE: | | | Flags = None +!PARSE-TREE: | | | Flags = {} !PARSE-TREE: | | Block !PARSE-TREE: | | | ExecutionPartConstruct -> ExecutableConstruct -> ActionStmt -> CallStmt = 'CALL f1()' !PARSE-TREE: | | | | Call @@ -79,7 +79,7 @@ subroutine openmp_sections(x, y) !PARSE-TREE: | OmpEndSectionsDirective !PARSE-TREE: | | OmpDirectiveName -> llvm::omp::Directive = sections !PARSE-TREE: | | OmpClauseList -> -!PARSE-TREE: | | Flags = None +!PARSE-TREE: | | Flags = {} !============================================================================== ! multiple sections @@ -105,12 +105,12 @@ subroutine openmp_sections(x, y) !PARSE-TREE: | OmpBeginSectionsDirective !PARSE-TREE: | | OmpDirectiveName -> llvm::omp::Directive = sections !PARSE-TREE: | | OmpClauseList -> -!PARSE-TREE: | | Flags = None +!PARSE-TREE: | | Flags = {} !PARSE-TREE: | OpenMPConstruct -> OpenMPSectionConstruct !PARSE-TREE: | | OmpDirectiveSpecification !PARSE-TREE: | | | OmpDirectiveName -> llvm::omp::Directive = section !PARSE-TREE: | | | OmpClauseList -> -!PARSE-TREE: | | | Flags = None +!PARSE-TREE: | | | Flags = {} !PARSE-TREE: | | Block !PARSE-TREE: | | | ExecutionPartConstruct -> ExecutableConstruct -> ActionStmt -> CallStmt = 'CALL f1()' !PARSE-TREE: | | | | Call @@ -119,7 +119,7 @@ subroutine openmp_sections(x, y) !PARSE-TREE: | | OmpDirectiveSpecification !PARSE-TREE: | | | OmpDirectiveName -> llvm::omp::Directive = section !PARSE-TREE: | | | OmpClauseList -> -!PARSE-TREE: | | | Flags = None +!PARSE-TREE: | | | Flags = {} !PARSE-TREE: | | Block !PARSE-TREE: | | | ExecutionPartConstruct -> ExecutableConstruct -> ActionStmt -> CallStmt = 'CALL f2()' !PARSE-TREE: | | | | Call @@ -128,7 +128,7 @@ subroutine openmp_sections(x, y) !PARSE-TREE: | | OmpDirectiveSpecification !PARSE-TREE: | | | OmpDirectiveName -> llvm::omp::Directive = section !PARSE-TREE: | | | OmpClauseList -> -!PARSE-TREE: | | | Flags = None +!PARSE-TREE: | | | Flags = {} !PARSE-TREE: | | Block !PARSE-TREE: | | | ExecutionPartConstruct -> ExecutableConstruct -> ActionStmt -> CallStmt = 'CALL f3()' !PARSE-TREE: | | | | Call @@ -136,7 +136,7 @@ subroutine openmp_sections(x, y) !PARSE-TREE: | OmpEndSectionsDirective !PARSE-TREE: | | OmpDirectiveName -> llvm::omp::Directive = sections !PARSE-TREE: | | OmpClauseList -> -!PARSE-TREE: | | Flags = None +!PARSE-TREE: | | Flags = {} !============================================================================== ! multiple sections with clauses @@ -163,12 +163,12 @@ subroutine openmp_sections(x, y) !PARSE-TREE: | | OmpDirectiveName -> llvm::omp::Directive = sections !PARSE-TREE: | | OmpClauseList -> OmpClause -> Private -> OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'x' !PARSE-TREE: | | OmpClause -> Firstprivate -> OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'y' -!PARSE-TREE: | | Flags = None +!PARSE-TREE: | | Flags = {} !PARSE-TREE: | OpenMPConstruct -> OpenMPSectionConstruct !PARSE-TREE: | | OmpDirectiveSpecification !PARSE-TREE: | | | OmpDirectiveName -> llvm::omp::Directive = section !PARSE-TREE: | | | OmpClauseList -> -!PARSE-TREE: | | | Flags = None +!PARSE-TREE: | | | Flags = {} !PARSE-TREE: | | Block !PARSE-TREE: | | | ExecutionPartConstruct -> ExecutableConstruct -> ActionStmt -> CallStmt = 'CALL f1()' !PARSE-TREE: | | | | Call @@ -177,7 +177,7 @@ subroutine openmp_sections(x, y) !PARSE-TREE: | | OmpDirectiveSpecification !PARSE-TREE: | | | OmpDirectiveName -> llvm::omp::Directive = section !PARSE-TREE: | | | OmpClauseList -> -!PARSE-TREE: | | | Flags = None +!PARSE-TREE: | | | Flags = {} !PARSE-TREE: | | Block !PARSE-TREE: | | | ExecutionPartConstruct -> ExecutableConstruct -> ActionStmt -> CallStmt = 'CALL f2()' !PARSE-TREE: | | | | Call @@ -186,7 +186,7 @@ subroutine openmp_sections(x, y) !PARSE-TREE: | | OmpDirectiveSpecification !PARSE-TREE: | | | OmpDirectiveName -> llvm::omp::Directive = section !PARSE-TREE: | | | OmpClauseList -> -!PARSE-TREE: | | | Flags = None +!PARSE-TREE: | | | Flags = {} !PARSE-TREE: | | Block !PARSE-TREE: | | | ExecutionPartConstruct -> ExecutableConstruct -> ActionStmt -> CallStmt = 'CALL f3()' !PARSE-TREE: | | | | Call @@ -194,6 +194,6 @@ subroutine openmp_sections(x, y) !PARSE-TREE: | OmpEndSectionsDirective !PARSE-TREE: | | OmpDirectiveName -> llvm::omp::Directive = sections !PARSE-TREE: | | OmpClauseList -> OmpClause -> Nowait -!PARSE-TREE: | | Flags = None +!PARSE-TREE: | | Flags = {} END subroutine openmp_sections diff --git a/flang/test/Parser/OpenMP/taskgraph.f90 b/flang/test/Parser/OpenMP/taskgraph.f90 index fa9994f..a596680 100644 --- a/flang/test/Parser/OpenMP/taskgraph.f90 +++ b/flang/test/Parser/OpenMP/taskgraph.f90 @@ -17,7 +17,7 @@ end !PARSE-TREE: | OmpBeginDirective !PARSE-TREE: | | OmpDirectiveName -> llvm::omp::Directive = taskgraph !PARSE-TREE: | | OmpClauseList -> -!PARSE-TREE: | | Flags = None +!PARSE-TREE: | | Flags = {} !PARSE-TREE: | Block !PARSE-TREE: | | ExecutionPartConstruct -> ExecutableConstruct -> BlockConstruct !PARSE-TREE: | | | BlockStmt -> @@ -54,23 +54,23 @@ end !PARSE-TREE: | | | Designator -> DataRef -> Name = 'x' !PARSE-TREE: | | OmpClause -> GraphReset -> OmpGraphResetClause -> Scalar -> Logical -> Expr = 'y' !PARSE-TREE: | | | Designator -> DataRef -> Name = 'y' -!PARSE-TREE: | | Flags = None +!PARSE-TREE: | | Flags = {} !PARSE-TREE: | Block !PARSE-TREE: | | ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OmpBlockConstruct !PARSE-TREE: | | | OmpBeginDirective !PARSE-TREE: | | | | OmpDirectiveName -> llvm::omp::Directive = task !PARSE-TREE: | | | | OmpClauseList -> -!PARSE-TREE: | | | | Flags = None +!PARSE-TREE: | | | | Flags = {} !PARSE-TREE: | | | Block !PARSE-TREE: | | | | ExecutionPartConstruct -> ExecutableConstruct -> ActionStmt -> ContinueStmt !PARSE-TREE: | | | OmpEndDirective !PARSE-TREE: | | | | OmpDirectiveName -> llvm::omp::Directive = task !PARSE-TREE: | | | | OmpClauseList -> -!PARSE-TREE: | | | | Flags = None +!PARSE-TREE: | | | | Flags = {} !PARSE-TREE: | OmpEndDirective !PARSE-TREE: | | OmpDirectiveName -> llvm::omp::Directive = taskgraph !PARSE-TREE: | | OmpClauseList -> -!PARSE-TREE: | | Flags = None +!PARSE-TREE: | | Flags = {} subroutine f02 @@ -87,9 +87,9 @@ end !PARSE-TREE: | OmpBeginDirective !PARSE-TREE: | | OmpDirectiveName -> llvm::omp::Directive = taskgraph !PARSE-TREE: | | OmpClauseList -> OmpClause -> GraphReset -> -!PARSE-TREE: | | Flags = None +!PARSE-TREE: | | Flags = {} !PARSE-TREE: | Block !PARSE-TREE: | OmpEndDirective !PARSE-TREE: | | OmpDirectiveName -> llvm::omp::Directive = taskgraph !PARSE-TREE: | | OmpClauseList -> -!PARSE-TREE: | | Flags = None +!PARSE-TREE: | | Flags = {} diff --git a/flang/test/Parser/OpenMP/threadprivate.f90 b/flang/test/Parser/OpenMP/threadprivate.f90 index 69b281f..b7dfd95 100644 --- a/flang/test/Parser/OpenMP/threadprivate.f90 +++ b/flang/test/Parser/OpenMP/threadprivate.f90 @@ -22,4 +22,4 @@ end module !PARSE-TREE: | OmpArgumentList -> OmpArgument -> OmpLocator -> OmpObject -> Name = 'blk' !PARSE-TREE: | OmpArgument -> OmpLocator -> OmpObject -> Designator -> DataRef -> Name = 'b' !PARSE-TREE: | OmpClauseList -> -!PARSE-TREE: | Flags = None +!PARSE-TREE: | Flags = {} diff --git a/flang/test/Parser/OpenMP/threadset-clause.f90 b/flang/test/Parser/OpenMP/threadset-clause.f90 new file mode 100644 index 0000000..3f19302 --- /dev/null +++ b/flang/test/Parser/OpenMP/threadset-clause.f90 @@ -0,0 +1,79 @@ +!RUN: %flang_fc1 -fdebug-unparse -fopenmp -fopenmp-version=60 %s | FileCheck --ignore-case --check-prefix="UNPARSE" %s +!RUN: %flang_fc1 -fdebug-dump-parse-tree -fopenmp -fopenmp-version=60 %s | FileCheck --check-prefix="PARSE-TREE" %s + +subroutine f00(x) + integer :: x(10) +!$omp task threadset(omp_pool) + x = x + 1 +!$omp end task +end + +!UNPARSE: SUBROUTINE f00 (x) +!UNPARSE: INTEGER x(10_4) +!UNPARSE: !$OMP TASK THREADSET(OMP_POOL) +!UNPARSE: x=x+1_4 +!UNPARSE: !$OMP END TASK +!UNPARSE: END SUBROUTINE + +!PARSE-TREE: OmpBeginDirective +!PARSE-TREE: | OmpDirectiveName -> llvm::omp::Directive = task +!PARSE-TREE: | OmpClauseList -> OmpClause -> Threadset -> OmpThreadsetClause -> ThreadsetPolicy = Omp_Pool + +subroutine f001(x) + integer :: x(10) +!$omp task threadset(omp_team) + x = x + 1 +!$omp end task +end + +!UNPARSE: SUBROUTINE f001 (x) +!UNPARSE: INTEGER x(10_4) +!UNPARSE: !$OMP TASK THREADSET(OMP_TEAM) +!UNPARSE: x=x+1_4 +!UNPARSE: !$OMP END TASK +!UNPARSE: END SUBROUTINE + +!PARSE-TREE: OmpBeginDirective +!PARSE-TREE: | OmpDirectiveName -> llvm::omp::Directive = task +!PARSE-TREE: | OmpClauseList -> OmpClause -> Threadset -> OmpThreadsetClause -> ThreadsetPolicy = Omp_Team + + +subroutine f002(x) + integer :: i +!$omp taskloop threadset(omp_team) + do i = 1, 10 + end do +!$omp end taskloop +end + +!UNPARSE: SUBROUTINE f002 (x) +!UNPARSE: INTEGER i +!UNPARSE: !$OMP TASKLOOP THREADSET(OMP_TEAM) +!UNPARSE: DO i=1_4,10_4 +!UNPARSE: END DO +!UNPARSE: !$OMP END TASK +!UNPARSE: END SUBROUTINE + +!PARSE-TREE: OmpBeginLoopDirective +!PARSE-TREE: | OmpDirectiveName -> llvm::omp::Directive = taskloop +!PARSE-TREE: | OmpClauseList -> OmpClause -> Threadset -> OmpThreadsetClause -> ThreadsetPolicy = Omp_Team + +subroutine f003(x) + integer :: i +!$omp taskloop threadset(omp_pool) + do i = 1, 10 + end do +!$omp end taskloop +end + +!UNPARSE: SUBROUTINE f003 (x) +!UNPARSE: INTEGER i +!UNPARSE: !$OMP TASKLOOP THREADSET(OMP_POOL) +!UNPARSE: DO i=1_4,10_4 +!UNPARSE: END DO +!UNPARSE: !$OMP END TASK +!UNPARSE: END SUBROUTINE + +!PARSE-TREE: OmpBeginLoopDirective +!PARSE-TREE: | OmpDirectiveName -> llvm::omp::Directive = taskloop +!PARSE-TREE: | OmpClauseList -> OmpClause -> Threadset -> OmpThreadsetClause -> ThreadsetPolicy = Omp_Pool diff --git a/flang/test/Parser/OpenMP/tile-fail.f90 b/flang/test/Parser/OpenMP/tile-fail.f90 index 0a92e5b..a69261a 100644 --- a/flang/test/Parser/OpenMP/tile-fail.f90 +++ b/flang/test/Parser/OpenMP/tile-fail.f90 @@ -8,17 +8,16 @@ ! Parser error subroutine stray_end1 - !CHECK: error: expected OpenMP construct + !CHECK: error: Misplaced OpenMP end-directive !$omp end tile end subroutine !--- stray_end2.f90 -! Semantic error subroutine stray_end2 print * - !CHECK: error: The END TILE directive must follow the DO loop associated with the loop construct + !CHECK: error: Misplaced OpenMP end-directive !$omp end tile end subroutine @@ -26,7 +25,7 @@ end subroutine !--- stray_begin.f90 subroutine stray_begin - !CHECK: error: A DO loop must follow the TILE directive + !CHECK: error: OpenMP loop construct should contain a DO-loop or a loop-nest-generating OpenMP construct !$omp tile sizes(2) end subroutine diff --git a/flang/test/Parser/OpenMP/tile.f90 b/flang/test/Parser/OpenMP/tile.f90 index 82004fd..483261f 100644 --- a/flang/test/Parser/OpenMP/tile.f90 +++ b/flang/test/Parser/OpenMP/tile.f90 @@ -19,7 +19,7 @@ subroutine openmp_tiles(x) !PARSE-TREE: OmpBeginLoopDirective !PARSE-TREE: OmpClauseList -> OmpClause -> Sizes -> Scalar -> Integer -> Expr = '2_4' !PARSE-TREE: LiteralConstant -> IntLiteralConstant = '2' -!PARSE-TREE: Flags = None +!PARSE-TREE: Flags = {} !PARSE-TREE: DoConstruct !PARSE-TREE: EndDoStmt !PARSE-TREE: OmpEndLoopDirective diff --git a/flang/test/Parser/OpenMP/transparent-clause.f90 b/flang/test/Parser/OpenMP/transparent-clause.f90 index 8f66954..f9471b5 100644 --- a/flang/test/Parser/OpenMP/transparent-clause.f90 +++ b/flang/test/Parser/OpenMP/transparent-clause.f90 @@ -25,7 +25,7 @@ end !PARSE-TREE: | | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'x' !PARSE-TREE: | | | bool = 'true' !PARSE-TREE: | | OmpClause -> Transparent -> -!PARSE-TREE: | | Flags = None +!PARSE-TREE: | | Flags = {} !PARSE-TREE: | Block @@ -44,12 +44,12 @@ end !PARSE-TREE: | | OmpDirectiveName -> llvm::omp::Directive = task !PARSE-TREE: | | OmpClauseList -> OmpClause -> Transparent -> OmpTransparentClause -> Scalar -> Integer -> Expr = '0_4' !PARSE-TREE: | | | LiteralConstant -> IntLiteralConstant = '0' -!PARSE-TREE: | | Flags = None +!PARSE-TREE: | | Flags = {} !PARSE-TREE: | Block !PARSE-TREE: | OmpEndDirective !PARSE-TREE: | | OmpDirectiveName -> llvm::omp::Directive = task !PARSE-TREE: | | OmpClauseList -> -!PARSE-TREE: | | Flags = None +!PARSE-TREE: | | Flags = {} subroutine f02 @@ -73,5 +73,6 @@ end !PARSE-TREE: | | OmpDirectiveName -> llvm::omp::Directive = taskloop !PARSE-TREE: | | OmpClauseList -> OmpClause -> Transparent -> OmpTransparentClause -> Scalar -> Integer -> Expr = '2_4' !PARSE-TREE: | | | LiteralConstant -> IntLiteralConstant = '2' -!PARSE-TREE: | | Flags = None -!PARSE-TREE: | DoConstruct +!PARSE-TREE: | | Flags = {} +!PARSE-TREE: | Block +!PARSE-TREE: | | ExecutionPartConstruct -> ExecutableConstruct -> DoConstruct diff --git a/flang/test/Parser/OpenMP/unroll-heuristic.f90 b/flang/test/Parser/OpenMP/unroll-heuristic.f90 index bbc2df3..6ce7b7e 100644 --- a/flang/test/Parser/OpenMP/unroll-heuristic.f90 +++ b/flang/test/Parser/OpenMP/unroll-heuristic.f90 @@ -22,24 +22,25 @@ END subroutine openmp_parse_unroll_heuristic !PTREE-NEXT: | OmpBeginLoopDirective !PTREE-NEXT: | | OmpDirectiveName -> llvm::omp::Directive = unroll !PTREE-NEXT: | | OmpClauseList -> -!PTREE-NEXT: | | Flags = None -!PTREE-NEXT: | DoConstruct -!PTREE-NEXT: | | NonLabelDoStmt -!PTREE-NEXT: | | | LoopControl -> LoopBounds -!PTREE-NEXT: | | | | Scalar -> Name = 'i' -!PTREE-NEXT: | | | | Scalar -> Expr = '1_4' -!PTREE-NEXT: | | | | | LiteralConstant -> IntLiteralConstant = '1' -!PTREE-NEXT: | | | | Scalar -> Expr = '100_4' -!PTREE-NEXT: | | | | | LiteralConstant -> IntLiteralConstant = '100' -!PTREE-NEXT: | | Block -!PTREE-NEXT: | | | ExecutionPartConstruct -> ExecutableConstruct -> ActionStmt -> CallStmt = 'CALL func(i)' -!PTREE-NEXT: | | | | | | Call -!PTREE-NEXT: | | | | | ProcedureDesignator -> Name = 'func' -!PTREE-NEXT: | | | | | ActualArgSpec -!PTREE-NEXT: | | | | | | ActualArg -> Expr = 'i' -!PTREE-NEXT: | | | | | | | Designator -> DataRef -> Name = 'i' -!PTREE-NEXT: | | EndDoStmt -> +!PTREE-NEXT: | | Flags = {} +!PTREE-NEXT: | Block +!PTREE-NEXT: | | ExecutionPartConstruct -> ExecutableConstruct -> DoConstruct +!PTREE-NEXT: | | | NonLabelDoStmt +!PTREE-NEXT: | | | | LoopControl -> LoopBounds +!PTREE-NEXT: | | | | | Scalar -> Name = 'i' +!PTREE-NEXT: | | | | | Scalar -> Expr = '1_4' +!PTREE-NEXT: | | | | | | LiteralConstant -> IntLiteralConstant = '1' +!PTREE-NEXT: | | | | | Scalar -> Expr = '100_4' +!PTREE-NEXT: | | | | | | LiteralConstant -> IntLiteralConstant = '100' +!PTREE-NEXT: | | | Block +!PTREE-NEXT: | | | | ExecutionPartConstruct -> ExecutableConstruct -> ActionStmt -> CallStmt = 'CALL func(i)' +!PTREE-NEXT: | | | | | | | Call +!PTREE-NEXT: | | | | | | ProcedureDesignator -> Name = 'func' +!PTREE-NEXT: | | | | | | ActualArgSpec +!PTREE-NEXT: | | | | | | | ActualArg -> Expr = 'i' +!PTREE-NEXT: | | | | | | | | Designator -> DataRef -> Name = 'i' +!PTREE-NEXT: | | | EndDoStmt -> !PTREE-NEXT: | OmpEndLoopDirective !PTREE-NEXT: | | OmpDirectiveName -> llvm::omp::Directive = unroll !PTREE-NEXT: | | OmpClauseList -> -!PTREE-NEXT: | | Flags = None +!PTREE-NEXT: | | Flags = {} diff --git a/flang/test/Parser/acc-data-statement.f90 b/flang/test/Parser/acc-data-statement.f90 index 40c76b2..c0b66d4 100644 --- a/flang/test/Parser/acc-data-statement.f90 +++ b/flang/test/Parser/acc-data-statement.f90 @@ -39,7 +39,7 @@ program acc_data_test print *, "After nested data" !$acc end data - ! Negative tests + ! Negative tests ! Basic data construct in program body !$acc data copy(a, b) create(d) bogus() !CHECK: acc-data-statement.f90: @@ -67,7 +67,7 @@ program acc_data_test !CHECK: acc-data-statement.f90: !CHECK-SAME: error: expected OpenACC end block directive !CHECK-NEXT: end if - !CHECK-NEXT: ^ + !CHECK-NEXT: ^ !CHECK-NEXT: in the context: OpenACC construct !CHECK-NEXT: !$acc data copyout(a) !CHECK-NEXT: ^ @@ -85,7 +85,7 @@ program acc_data_test !CHECK: acc-data-statement.f90: !CHECK-SAME: error: expected OpenACC end block directive !CHECK-NEXT: end do - !CHECK-NEXT: ^ + !CHECK-NEXT: ^ !CHECK-NEXT: in the context: OpenACC construct !CHECK-NEXT: !$acc data present(a) !CHECK-NEXT: ^ @@ -137,7 +137,7 @@ program acc_data_test contains subroutine positive_process_array(x) integer, intent(inout) :: x(:) - + ! Data construct in subroutine !$acc data copy(x) x = x + 1 @@ -148,17 +148,17 @@ contains function positive_compute_sum(x) result(total) integer, intent(in) :: x(:) integer :: total - + ! Data construct in function !$acc data copyin(x) copy(total) total = sum(x) !$acc end data print *, "Function finished" end function - + subroutine negative_process_array(x) integer, intent(inout) :: x(:) - + ! Data construct in subroutine !$acc data copy(x) x = x + 1 @@ -188,7 +188,7 @@ contains !CHECK: acc-data-statement.f90: !CHECK-SAME: error: expected OpenACC end block directive !CHECK-NEXT: end function - !CHECK-NEXT: ^ + !CHECK-NEXT: ^ !CHECK-NEXT: in the context: OpenACC construct !CHECK-NEXT: !$acc data copyin(x) copy(total) !CHECK-NEXT: ^ diff --git a/flang/test/Parser/assume-aligned.f90 b/flang/test/Parser/assume-aligned.f90 index c61c10d..3d2c358 100644 --- a/flang/test/Parser/assume-aligned.f90 +++ b/flang/test/Parser/assume-aligned.f90 @@ -8,13 +8,13 @@ SUBROUTINE aa(a, nn) !DIR$ assume_aligned a:16 !CHECK: !DIR$ ASSUME_ALIGNED a:16 !DIR$ assume_aligned a (1):16 -!CHECK: !DIR$ ASSUME_ALIGNED a(1):16 +!CHECK: !DIR$ ASSUME_ALIGNED a(1):16 !DIR$ assume_aligned a(1):16 !CHECK: !DIR$ ASSUME_ALIGNED a(1):16 !DIR$ assume_aligned a(nn):16 -!CHECK: !DIR$ ASSUME_ALIGNED a(nn):16 +!CHECK: !DIR$ ASSUME_ALIGNED a(nn):16 !DIR$ assume_aligned a(44):16 -!CHECK: !DIR$ ASSUME_ALIGNED a(44):16 +!CHECK: !DIR$ ASSUME_ALIGNED a(44):16 DO i=1,nn a(i)=a(i)+1.5 END DO @@ -31,22 +31,22 @@ END SUBROUTINE bb SUBROUTINE f(n) IMPLICIT NONE - TYPE node + TYPE node REAL(KIND=8), POINTER :: a(:,:) - END TYPE NODE - + END TYPE NODE + TYPE(NODE), POINTER :: nodes INTEGER :: i INTEGER, INTENT(IN) :: n - ALLOCATE(nodes) + ALLOCATE(nodes) ALLOCATE(nodes%a(1000,1000)) - !DIR$ ASSUME_ALIGNED nodes%a(1,1) : 16 + !DIR$ ASSUME_ALIGNED nodes%a(1,1) : 16 !CHECK: !DIR$ ASSUME_ALIGNED nodes%a(1,1):16 - DO i=1,n - nodes%a(1,i) = nodes%a(1,i)+1 - END DO + DO i=1,n + nodes%a(1,i) = nodes%a(1,i)+1 + END DO END SUBROUTINE f SUBROUTINE g(a, b) diff --git a/flang/test/Parser/compiler-directives.f90 b/flang/test/Parser/compiler-directives.f90 index b2fe4663..77c6b45 100644 --- a/flang/test/Parser/compiler-directives.f90 +++ b/flang/test/Parser/compiler-directives.f90 @@ -36,6 +36,28 @@ subroutine vector_always enddo end subroutine +subroutine vector_vectorlength + !dir$ vector vectorlength(fixed) + ! CHECK: !DIR$ VECTOR VECTORLENGTH (FIXED) + do i=1,10 + enddo + + !dir$ vector vectorlength(scalable) + ! CHECK: !DIR$ VECTOR VECTORLENGTH (SCALABLE) + do i=1,10 + enddo + + !dir$ vector vectorlength(8,scalable) + ! CHECK: !DIR$ VECTOR VECTORLENGTH (8, SCALABLE) + do i=1,10 + enddo + + !dir$ vector vectorlength(4) + ! CHECK: !DIR$ VECTOR VECTORLENGTH (4) + do i=1,10 + enddo +end subroutine + subroutine unroll !dir$ unroll ! CHECK: !DIR$ UNROLL @@ -46,7 +68,7 @@ subroutine unroll do i=1,10 enddo !dir$ nounroll - ! CHECK: !DIR$ NOUNROLL + ! CHECK: !DIR$ NOUNROLL do i=1,10 enddo end subroutine @@ -61,7 +83,7 @@ subroutine unroll_and_jam do i=1,10 enddo !dir$ nounroll_and_jam - ! CHECK: !DIR$ NOUNROLL_AND_JAM + ! CHECK: !DIR$ NOUNROLL_AND_JAM do i=1,10 enddo end subroutine @@ -75,16 +97,16 @@ end subroutine subroutine inline integer :: a - !dir$ forceinline - ! CHECK: !DIR$ FORCEINLINE + !dir$ forceinline + ! CHECK: !DIR$ FORCEINLINE a = f(2) - !dir$ inline - ! CHECK: !DIR$ INLINE + !dir$ inline + ! CHECK: !DIR$ INLINE call g() - !dir$ noinline - ! CHECK: !DIR$ NOINLINE + !dir$ noinline + ! CHECK: !DIR$ NOINLINE call g() contains @@ -96,3 +118,10 @@ subroutine inline subroutine g() end subroutine end subroutine + +subroutine ivdep + !dir$ ivdep + ! CHECK: !DIR$ IVDEP + do i=1,10 + enddo +end subroutine diff --git a/flang/test/Parser/prefetch.f90 b/flang/test/Parser/prefetch.f90 new file mode 100644 index 0000000..1013a09 --- /dev/null +++ b/flang/test/Parser/prefetch.f90 @@ -0,0 +1,80 @@ +!RUN: %flang_fc1 -fdebug-unparse-no-sema %s 2>&1 | FileCheck %s -check-prefix=UNPARSE +!RUN: %flang_fc1 -fdebug-dump-parse-tree-no-sema %s 2>&1 | FileCheck %s -check-prefix=TREE + +subroutine test_prefetch_01(a, b) + integer, intent(in) :: a + integer, intent(inout) :: b(5) + integer :: i = 2 + integer :: res + +!TREE: | | DeclarationConstruct -> SpecificationConstruct -> CompilerDirective -> Prefetch -> Designator -> DataRef -> Name = 'a' + +!UNPARSE: !DIR$ PREFETCH a + !dir$ prefetch a + b(1) = a + +!TREE: | | ExecutionPartConstruct -> ExecutableConstruct -> CompilerDirective -> Prefetch -> Designator -> DataRef -> Name = 'b' + +!UNPARSE: !DIR$ PREFETCH b + !dir$ prefetch b + res = sum(b) + +!TREE: | | ExecutionPartConstruct -> ExecutableConstruct -> CompilerDirective -> Prefetch -> Designator -> DataRef -> Name = 'a' +!TREE: | | Designator -> DataRef -> ArrayElement +!TREE: | | | DataRef -> Name = 'b' +!TREE: | | | SectionSubscript -> SubscriptTriplet +!TREE: | | | | Scalar -> Integer -> Expr -> LiteralConstant -> IntLiteralConstant = '3' +!TREE: | | | | Scalar -> Integer -> Expr -> LiteralConstant -> IntLiteralConstant = '5' + +!UNPARSE: !DIR$ PREFETCH a, b(3:5) + !dir$ prefetch a, b(3:5) + res = a + b(4) + +!TREE: | | ExecutionPartConstruct -> ExecutableConstruct -> CompilerDirective -> Prefetch -> Designator -> DataRef -> Name = 'res' +!TREE: | | Designator -> DataRef -> ArrayElement +!TREE: | | | DataRef -> Name = 'b' +!TREE: | | | SectionSubscript -> Integer -> Expr -> Add +!TREE: | | | | Expr -> Designator -> DataRef -> Name = 'i' +!TREE: | | | | Expr -> LiteralConstant -> IntLiteralConstant = '2' + +!UNPARSE: !DIR$ PREFETCH res, b(i+2) + !dir$ prefetch res, b(i+2) + res = res + b(i+2) +end subroutine + +subroutine test_prefetch_02(n, a) + integer, intent(in) :: n + integer, intent(in) :: a(n) + type :: t + real, allocatable :: x(:, :) + end type t + type(t) :: p + + do i = 1, n +!TREE: | | | | ExecutionPartConstruct -> ExecutableConstruct -> CompilerDirective -> Prefetch -> Designator -> DataRef -> ArrayElement +!TREE: | | | | | DataRef -> StructureComponent +!TREE: | | | | | | DataRef -> Name = 'p' +!TREE: | | | | | | Name = 'x' +!TREE: | | | | | SectionSubscript -> Integer -> Expr -> Designator -> DataRef -> Name = 'i' +!TREE: | | | | | SectionSubscript -> SubscriptTriplet +!TREE: | | | | Designator -> DataRef -> Name = 'a' + +!UNPARSE: !DIR$ PREFETCH p%x(i,:), a + !dir$ prefetch p%x(i, :), a + do j = 1, n +!TREE: | | | | | | ExecutionPartConstruct -> ExecutableConstruct -> CompilerDirective -> Prefetch -> Designator -> DataRef -> ArrayElement +!TREE: | | | | | | | DataRef -> StructureComponent +!TREE: | | | | | | | | DataRef -> Name = 'p' +!TREE: | | | | | | | | Name = 'x' +!TREE: | | | | | | | SectionSubscript -> Integer -> Expr -> Designator -> DataRef -> Name = 'i' +!TREE: | | | | | | | SectionSubscript -> Integer -> Expr -> Designator -> DataRef -> Name = 'j' +!TREE: | | | | | | Designator -> DataRef -> ArrayElement +!TREE: | | | | | | | DataRef -> Name = 'a' +!TREE: | | | | | | | SectionSubscript -> Integer -> Expr -> Designator -> DataRef -> Name = 'i' + +!UNPARSE: !DIR$ PREFETCH p%x(i,j), a(i) + !dir$ prefetch p%x(i, j), a(i) + p%x(i, j) = p%x(i, j) ** a(j) + end do + end do +end subroutine diff --git a/flang/test/Preprocessing/bug168077.F90 b/flang/test/Preprocessing/bug168077.F90 new file mode 100644 index 0000000..d6c1bb0 --- /dev/null +++ b/flang/test/Preprocessing/bug168077.F90 @@ -0,0 +1,6 @@ +!RUN: %flang -E -DNVAR=2+1+0+0 %s 2>&1 | FileCheck %s +!CHECK: pass +#if NVAR > 2 +call pass +#endif +end diff --git a/flang/test/Preprocessing/compiler_defined_macros.F90 b/flang/test/Preprocessing/compiler_defined_macros.F90 index f5f955b..0b80fa2 100644 --- a/flang/test/Preprocessing/compiler_defined_macros.F90 +++ b/flang/test/Preprocessing/compiler_defined_macros.F90 @@ -5,7 +5,7 @@ !CHECK: flang_patchlevel = {{[0-9]+$}} !RUN: %flang -E %s | FileCheck --ignore-case %s - + integer, parameter :: flang_major = __flang_major__ integer, parameter :: flang_minor = __flang_minor__ integer, parameter :: flang_patchlevel = __flang_patchlevel__ diff --git a/flang/test/Preprocessing/pp132.f90 b/flang/test/Preprocessing/pp132.f90 index a0fdf46..95b43b0 100644 --- a/flang/test/Preprocessing/pp132.f90 +++ b/flang/test/Preprocessing/pp132.f90 @@ -18,6 +18,6 @@ subroutine foo !$acc data copyin(super_very_long_name_for_the_variable, another_super_wordy_variable_to_test) !$acc end data - + !$OMP something something end subroutine foo diff --git a/flang/test/Semantics/Inputs/modfile73-a.f90 b/flang/test/Semantics/Inputs/modfile73-a.f90 index 45a93f6..ea247c9 100644 --- a/flang/test/Semantics/Inputs/modfile73-a.f90 +++ b/flang/test/Semantics/Inputs/modfile73-a.f90 @@ -1,197 +1,197 @@ MODULE modfile73a PUBLIC re_alloc, defaults -integersp +integersp integerselected_real_kind0 integer:: i8b = selected_int_kind(8) interface subroutine alloc_error_report_interf(str,code) - end + end subroutine alloc_memory_event_interf(bytes,name) - end + end end interface -procedure()alloc_error_report -procedure()alloc_memory_event +procedure()alloc_error_report +procedure()alloc_memory_event interface de_alloc end interface - charactercharacter, DEFAULT_ROUTINE + charactercharacter, DEFAULT_ROUTINE type allocDefaults logical copy logical shrink integer imin characterroutine - end type + end type type(allocDefaults)DEFAULT integer IERR logical ASSOCIATED_ARRAY, NEEDS_ALLOC, NEEDS_COPY, NEEDS_DEALLOC CONTAINS subroutine set_alloc_event_handler(func) - end + end subroutine set_alloc_error_handler(func) - end + end subroutine dummy_alloc_memory_event(bytes,name) - end + end subroutine dummy_alloc_error_report(name,code) - end + end SUBROUTINE alloc_default( old, new, restore, routine, copy, shrink, imin ) -END +END SUBROUTINE realloc_i1( array, i1min, i1max, name, routine, copy, shrink ) -END +END SUBROUTINE realloc_i2( array, i1min,i1max, i2min,i2max, name, routine, copy, shrink ) -END +END SUBROUTINE realloc_i3( array, i1min,i1max, i2min,i2max, i3min,i3max, name, routine, copy, shrink ) -END +END SUBROUTINE realloc_i4( array, i1min,i1max, i2min,i2max, i3min,i3max, i4min,i4max, name, routine, copy, shrink ) -END +END SUBROUTINE realloc_i5( array, i1min,i1max, i2min,i2max, i3min,i3max, i4min, i4max, i5min, i5max, name, routine, copy, shrink ) -END +END SUBROUTINE realloc_E1( array, i1min, i1max, name, routine, copy, shrink ) -END +END SUBROUTINE realloc_r1( array, i1min, i1max, name, routine, copy, shrink ) -END +END SUBROUTINE realloc_r2( array, i1min,i1max, i2min,i2max, name, routine, copy, shrink ) -END +END SUBROUTINE realloc_r3( array, i1min,i1max, i2min,i2max, i3min,i3max, name, routine, copy, shrink ) -END +END SUBROUTINE realloc_r4( array, i1min,i1max, i2min,i2max, i3min,i3max, i4min,i4max, name, routine, copy, shrink ) -END +END SUBROUTINE realloc_r5( array, i1min,i1max, i2min,i2max, i3min,i3max, i4min, i4max, i5min, i5max, name, routine, copy, shrink ) -END +END SUBROUTINE realloc_d1( array, i1min, i1max, name, routine, copy, shrink ) -END +END SUBROUTINE realloc_d2( array, i1min,i1max, i2min,i2max, name, routine, copy, shrink ) -END +END SUBROUTINE realloc_d3( array, i1min,i1max, i2min,i2max, i3min,i3max, name, routine, copy, shrink ) -END +END SUBROUTINE realloc_d4( array, i1min,i1max, i2min,i2max, i3min,i3max, i4min,i4max, name, routine, copy, shrink ) -END +END SUBROUTINE realloc_d5( array, i1min,i1max, i2min,i2max, i3min,i3max, i4min,i4max, i5min,i5max, name, routine, copy, shrink ) -END +END SUBROUTINE realloc_c1( array, i1min, i1max, name, routine, copy, shrink ) -END +END SUBROUTINE realloc_c2( array, i1min,i1max, i2min,i2max, name, routine, copy, shrink ) -END +END SUBROUTINE realloc_c3( array, i1min,i1max, i2min,i2max, i3min,i3max, name, routine, copy, shrink ) -END +END SUBROUTINE realloc_c4( array, i1min,i1max, i2min,i2max, i3min,i3max, i4min,i4max, name, routine, copy, shrink ) -END +END SUBROUTINE realloc_c5( array, i1min,i1max, i2min,i2max, i3min,i3max, i4min, i4max, i5min, i5max, name, routine, copy, shrink ) -END +END SUBROUTINE realloc_z1( array, i1min, i1max, name, routine, copy, shrink ) -END +END SUBROUTINE realloc_z2( array, i1min,i1max, i2min,i2max, name, routine, copy, shrink ) -END +END SUBROUTINE realloc_z3( array, i1min,i1max, i2min,i2max, i3min,i3max, name, routine, copy, shrink ) -END +END SUBROUTINE realloc_z4( array, i1min,i1max, i2min,i2max, i3min,i3max, i4min,i4max, name, routine, copy, shrink ) -END +END SUBROUTINE realloc_z5( array, i1min,i1max, i2min,i2max, i3min,i3max, i4min, i4max, i5min, i5max, name, routine, copy, shrink ) -END +END SUBROUTINE realloc_l1( array, i1min,i1max, name, routine, copy, shrink ) -END +END SUBROUTINE realloc_l2( array, i1min,i1max, i2min,i2max, name, routine, copy, shrink ) -END +END SUBROUTINE realloc_l3( array, i1min,i1max, i2min,i2max, i3min,i3max, name, routine, copy, shrink ) -END +END SUBROUTINE realloc_l4( array, i1min,i1max, i2min,i2max, i3min,i3max, i4min,i4max, name, routine, copy, shrink ) -END +END SUBROUTINE realloc_l5( array, i1min,i1max, i2min,i2max, i3min,i3max, i4min, i4max, i5min, i5max, name, routine, copy, shrink ) -END +END SUBROUTINE realloc_i1s( array, i1max, name, routine, copy, shrink ) -END +END SUBROUTINE realloc_i2s( array, i1max, i2max, name, routine, copy, shrink ) -END +END SUBROUTINE realloc_i3s( array, i1max, i2max, i3max, name, routine, copy, shrink ) -END +END SUBROUTINE realloc_r1s( array, i1max, name, routine, copy, shrink ) -END +END SUBROUTINE realloc_r2s( array, i1max, i2max, name, routine, copy, shrink ) -END +END SUBROUTINE realloc_r3s( array, i1max, i2max, i3max, name, routine, copy, shrink ) -END +END SUBROUTINE realloc_r4s( array, i1max, i2max, i3max, i4max, name, routine, copy, shrink ) -END +END SUBROUTINE realloc_d1s( array, i1max, name, routine, copy, shrink ) -END +END SUBROUTINE realloc_d3s( array, i1max, i2max, i3max, name, routine, copy, shrink ) -END +END SUBROUTINE realloc_d4s( array, i1max, i2max, i3max, i4max, name, routine, copy, shrink ) -END +END SUBROUTINE realloc_l1s( array, i1max, name, routine, copy, shrink ) -END +END SUBROUTINE realloc_l2s( array, i1max, i2max, name, routine, copy, shrink ) -END +END SUBROUTINE realloc_l3s( array, i1max, i2max, i3max, name, routine, copy, shrink ) -END +END SUBROUTINE realloc_s1( array, i1min, i1max, name, routine, copy, shrink ) -END +END SUBROUTINE dealloc_i1( array, name, routine ) -END +END SUBROUTINE dealloc_i2( array, name, routine ) -END +END SUBROUTINE dealloc_i3( array, name, routine ) -END +END SUBROUTINE dealloc_i4( array, name, routine ) - END + END SUBROUTINE dealloc_i5( array, name, routine ) - END + END SUBROUTINE dealloc_E1( array, name, routine ) -END +END SUBROUTINE dealloc_r1( array, name, routine ) -END +END SUBROUTINE dealloc_r2( array, name, routine ) -END +END SUBROUTINE dealloc_r3( array, name, routine ) -END +END SUBROUTINE dealloc_r4( array, name, routine ) -END +END SUBROUTINE dealloc_r5( array, name, routine ) -END +END SUBROUTINE dealloc_d1( array, name, routine ) -END +END SUBROUTINE dealloc_d2( array, name, routine ) -END +END SUBROUTINE dealloc_d3( array, name, routine ) -END +END SUBROUTINE dealloc_d4( array, name, routine ) -END +END SUBROUTINE dealloc_d5( array, name, routine ) -END +END SUBROUTINE dealloc_c1( array, name, routine ) -END +END SUBROUTINE dealloc_c2( array, name, routine ) -END +END SUBROUTINE dealloc_c3( array, name, routine ) -END +END SUBROUTINE dealloc_c4( array, name, routine ) -END +END SUBROUTINE dealloc_c5( array, name, routine ) - END + END SUBROUTINE dealloc_z1( array, name, routine ) -END +END SUBROUTINE dealloc_z2( array, name, routine ) -END +END SUBROUTINE dealloc_z3( array, name, routine ) -END +END SUBROUTINE dealloc_z4( array, name, routine ) -END +END SUBROUTINE dealloc_z5( array, name, routine ) - END + END SUBROUTINE dealloc_l1( array, name, routine ) -END +END SUBROUTINE dealloc_l2( array, name, routine ) -END +END SUBROUTINE dealloc_l3( array, name, routine ) -END +END SUBROUTINE dealloc_l4( array, name, routine ) - END + END SUBROUTINE dealloc_l5( array, name, routine ) - END + END SUBROUTINE dealloc_s1( array, name, routine ) -END +END SUBROUTINE options( final_bounds, common_bounds, old_bounds, new_bounds, copy, shrink ) -END +END SUBROUTINE alloc_err( ierr, name, routine, bounds ) -END +END SUBROUTINE alloc_count( delta_size, type, name, routine ) -END +END END diff --git a/flang/test/Semantics/Inputs/modfile73-b.f90 b/flang/test/Semantics/Inputs/modfile73-b.f90 index 3b9c72a..7432995 100644 --- a/flang/test/Semantics/Inputs/modfile73-b.f90 +++ b/flang/test/Semantics/Inputs/modfile73-b.f90 @@ -2,9 +2,9 @@ module modfile73ba use modfile73a, only: re_alloc, de_alloc charactermod_name type lData1D - integer refCount - character id - character name + integer refCount + character id + character name end type type TYPE_NAME type(lData1D), pointer :: data => null() @@ -17,37 +17,37 @@ module modfile73ba end interface CONTAINS subroutine init_(this) - end + end subroutine delete_(this) - end + end subroutine assign_(this, other) - end + end function initialized_(thisinit) - end + end function same_(this1,this2same) - end + end function refcount_(thiscount) - end + end function id_(thisstr) - end + end function name_(this) result(str) type(TYPE_NAME) this character(len_trim(this%data%name)) str - end + end subroutine tag_new_object(this) - end + end subroutine delete_Data(a1d_data) - end -end + end +end module modfile73bb use modfile73a, only: re_alloc, de_alloc charactermod_name type lData1D - integer refCount - character id - character name -logical, pointer :: val => null() + integer refCount + character id + character name +logical, pointer :: val => null() end type TYPE_NAME type(lData1D), pointer :: data => null() @@ -63,27 +63,27 @@ logical, pointer :: val => null() end interface interface initialized subroutine die(str) - end + end end interface CONTAINS subroutine init_(this) - end + end subroutine delete_(this) - end + end subroutine assign_(this, other) - end + end function initialized_(thisinit) - end + end function same_(this1,this2same) - end + end function refcount_(thiscount) - end + end function id_(thisstr) - end + end function name_(thisstr) - end + end subroutine tag_new_object(this) - end + end subroutine delete_Data(a1d_data) - end + end end diff --git a/flang/test/Semantics/Inputs/modfile73-c.f90 b/flang/test/Semantics/Inputs/modfile73-c.f90 index abf7644..8d4f2d1 100644 --- a/flang/test/Semantics/Inputs/modfile73-c.f90 +++ b/flang/test/Semantics/Inputs/modfile73-c.f90 @@ -1,4 +1,4 @@ module modfile73c type OrbitalDistribution_ - end type - end + end type + end diff --git a/flang/test/Semantics/OpenACC/acc-atomic-validity.f90 b/flang/test/Semantics/OpenACC/acc-atomic-validity.f90 index 5c8d33f..9f84504 100644 --- a/flang/test/Semantics/OpenACC/acc-atomic-validity.f90 +++ b/flang/test/Semantics/OpenACC/acc-atomic-validity.f90 @@ -37,7 +37,7 @@ program openacc_atomic_validity !$acc atomic read i = c(i) - + !$acc atomic read if(.true.) i = c(i) @@ -45,12 +45,12 @@ program openacc_atomic_validity i = c(i) !$acc end atomic - !$acc atomic read if(l) + !$acc atomic read if(l) i = c(i) !$acc end atomic !ERROR: FINALIZE clause is not allowed on the ATOMIC READ FINALIZE IF(L) - !$acc atomic read finalize if(l) + !$acc atomic read finalize if(l) i = c(i) !$acc end atomic @@ -65,7 +65,7 @@ program openacc_atomic_validity c(1) = c(2) c(1) = c(3) !$acc end atomic - + !ERROR: The assignments in this atomic capture construct do not update a variable and capture either its initial or final value !$acc atomic capture c(1) = c(2) diff --git a/flang/test/Semantics/OpenACC/acc-default-none-function.f90 b/flang/test/Semantics/OpenACC/acc-default-none-function.f90 index f0a697f..accd03a 100644 --- a/flang/test/Semantics/OpenACC/acc-default-none-function.f90 +++ b/flang/test/Semantics/OpenACC/acc-default-none-function.f90 @@ -8,7 +8,7 @@ contains dosomething = res + 1 end function end module - + program main use mm_acc_rout_function implicit none diff --git a/flang/test/Semantics/OpenACC/acc-error.f90 b/flang/test/Semantics/OpenACC/acc-error.f90 index 69ee59f..b930c25 100644 --- a/flang/test/Semantics/OpenACC/acc-error.f90 +++ b/flang/test/Semantics/OpenACC/acc-error.f90 @@ -8,7 +8,7 @@ subroutine test(a, n) !ERROR: expected OpenACC directive !$acc p integer :: i,j - + i = 0 !ERROR: expected OpenACC directive !$acc p diff --git a/flang/test/Semantics/OpenACC/acc-parallel.f90 b/flang/test/Semantics/OpenACC/acc-parallel.f90 index 45c0faf..b3120e6 100644 --- a/flang/test/Semantics/OpenACC/acc-parallel.f90 +++ b/flang/test/Semantics/OpenACC/acc-parallel.f90 @@ -204,7 +204,7 @@ end program openacc_parallel_validity subroutine acc_parallel_default_none integer :: i, l real :: a(10,10) - l = 10 + l = 10 !$acc parallel default(none) !$acc loop !ERROR: The DEFAULT(NONE) clause requires that 'l' must be listed in a data-mapping clause diff --git a/flang/test/Semantics/OpenACC/acc-reduction-validity.f90 b/flang/test/Semantics/OpenACC/acc-reduction-validity.f90 index fd83e41..4f73d51 100644 --- a/flang/test/Semantics/OpenACC/acc-reduction-validity.f90 +++ b/flang/test/Semantics/OpenACC/acc-reduction-validity.f90 @@ -171,14 +171,14 @@ program openacc_reduction_validity !ERROR: No explicit type declared for 'xyz' !$acc parallel reduction(+:xyz) - !$acc end parallel + !$acc end parallel end program subroutine sum() !ERROR: 'sum' is already declared in this scoping unit - integer :: i,sum + integer :: i,sum sum = 0 !$acc parallel !ERROR: Only variables are allowed in data clauses on the LOOP directive diff --git a/flang/test/Semantics/OpenMP/allocate-align01.f90 b/flang/test/Semantics/OpenMP/allocate-align01.f90 index 88bcd6d..4a1e60c 100644 --- a/flang/test/Semantics/OpenMP/allocate-align01.f90 +++ b/flang/test/Semantics/OpenMP/allocate-align01.f90 @@ -11,9 +11,9 @@ program allocate_align_tree integer :: z, t, xx t = 2 z = 3 + !WARNING: The executable form of the OpenMP ALLOCATE directive has been deprecated, please use ALLOCATORS instead [-Wopen-mp-usage] !ERROR: Must be a constant value !$omp allocate(j) align(xx) - !WARNING: The executable form of the OpenMP ALLOCATE directive has been deprecated, please use ALLOCATORS instead [-Wopen-mp-usage] !ERROR: The alignment should be positive !$omp allocate(xarray) align(-32) allocator(omp_large_cap_mem_alloc) allocate(j(z), xarray(t)) diff --git a/flang/test/Semantics/OpenMP/allocate-directive.f90 b/flang/test/Semantics/OpenMP/allocate-directive.f90 index 18a14b8..e34125b 100644 --- a/flang/test/Semantics/OpenMP/allocate-directive.f90 +++ b/flang/test/Semantics/OpenMP/allocate-directive.f90 @@ -11,7 +11,7 @@ integer :: x, y integer, allocatable :: a, b, m, n, t, z !$omp allocate(x, y) !$omp allocate(x, y) allocator(omp_default_mem_alloc) - + continue !$omp allocate(a, b) allocate ( a, b ) diff --git a/flang/test/Semantics/OpenMP/allocate01.f90 b/flang/test/Semantics/OpenMP/allocate01.f90 index 229fd4d..5fe4efd 100644 --- a/flang/test/Semantics/OpenMP/allocate01.f90 +++ b/flang/test/Semantics/OpenMP/allocate01.f90 @@ -17,7 +17,7 @@ use omp_lib !ERROR: A list item on a declarative ALLOCATE must be declared in the same scope in which the directive appears !$omp allocate(y) - print *, a + print *, a !WARNING: The executable form of the OpenMP ALLOCATE directive has been deprecated, please use ALLOCATORS instead [-Wopen-mp-usage] !$omp allocate(x) allocator(omp_default_mem_alloc) diff --git a/flang/test/Semantics/OpenMP/allocate02.f90 b/flang/test/Semantics/OpenMP/allocate02.f90 index 8f0579e..a1e6847 100644 --- a/flang/test/Semantics/OpenMP/allocate02.f90 +++ b/flang/test/Semantics/OpenMP/allocate02.f90 @@ -16,6 +16,7 @@ use omp_lib !ERROR: At most one ALLOCATOR clause can appear on the ALLOCATE directive !$omp allocate(x, y) allocator(omp_default_mem_alloc) allocator(omp_default_mem_alloc) + continue !$omp allocate(darray) allocator(omp_default_mem_alloc) allocate ( darray(a, b) ) diff --git a/flang/test/Semantics/OpenMP/allocate03.f90 b/flang/test/Semantics/OpenMP/allocate03.f90 index e35115f..3609f38 100644 --- a/flang/test/Semantics/OpenMP/allocate03.f90 +++ b/flang/test/Semantics/OpenMP/allocate03.f90 @@ -17,6 +17,7 @@ use omp_lib !ERROR: A variable that is part of another variable (as an array or structure element) cannot appear on the ALLOCATE directive !$omp allocate(my_var%array) + continue !ERROR: A variable that is part of another variable (as an array or structure element) cannot appear on the ALLOCATE directive !$omp allocate(darray, my_var%array) allocator(omp_default_mem_alloc) diff --git a/flang/test/Semantics/OpenMP/allocate06.f90 b/flang/test/Semantics/OpenMP/allocate06.f90 index 9b57322..272094a 100644 --- a/flang/test/Semantics/OpenMP/allocate06.f90 +++ b/flang/test/Semantics/OpenMP/allocate06.f90 @@ -13,7 +13,7 @@ use omp_lib !ERROR: A list item in a declarative ALLOCATE cannot have the ALLOCATABLE or POINTER attribute !$omp allocate(darray) allocator(omp_default_mem_alloc) - + continue !$omp allocate(darray) allocator(omp_default_mem_alloc) allocate(darray(a, b)) diff --git a/flang/test/Semantics/OpenMP/allocate08.f90 b/flang/test/Semantics/OpenMP/allocate08.f90 index f4f11e2..3f59493 100644 --- a/flang/test/Semantics/OpenMP/allocate08.f90 +++ b/flang/test/Semantics/OpenMP/allocate08.f90 @@ -1,11 +1,11 @@ ! REQUIRES: openmp_runtime -! RUN: %python %S/../test_errors.py %s %flang_fc1 %openmp_flags -! OpenMP Version 5.0 +! RUN: %python %S/../test_errors.py %s %flang_fc1 %openmp_flags -fopenmp-version=51 +! OpenMP Version 5.1 ! 2.11.3 allocate Directive ! If list items within the ALLOCATE directive have the SAVE attribute, are a -! common block name, or are declared in the scope of a module, then only -! predefined memory allocator parameters can be used in the allocator clause +! common block name, then only predefined memory allocator parameters can be +! used in the allocator clause module AllocateModule INTEGER :: z diff --git a/flang/test/Semantics/OpenMP/allocate09.f90 b/flang/test/Semantics/OpenMP/allocate09.f90 index 0f93a34..8b8d07c 100644 --- a/flang/test/Semantics/OpenMP/allocate09.f90 +++ b/flang/test/Semantics/OpenMP/allocate09.f90 @@ -23,11 +23,11 @@ use omp_lib !$omp allocate allocate(e(5), f(6), g(7)) - !ERROR: Object 'i' in ALLOCATE directive not found in corresponding ALLOCATE statement + !ERROR: A list item on an executable ALLOCATE must be specified on the associated ALLOCATE statement !$omp allocate(h, i) allocator(omp_default_mem_alloc) allocate(h(8)) - !ERROR: Object 'j' in ALLOCATE directive not found in corresponding ALLOCATE statement + !ERROR: A list item on an executable ALLOCATE must be specified on the associated ALLOCATE statement !$omp allocate(j, k) allocator(omp_default_mem_alloc) !$omp allocate(l) allocator(omp_default_mem_alloc) allocate(k(9), l(10)) diff --git a/flang/test/Semantics/OpenMP/allocate10.f90 b/flang/test/Semantics/OpenMP/allocate10.f90 new file mode 100644 index 0000000..0a9e85b --- /dev/null +++ b/flang/test/Semantics/OpenMP/allocate10.f90 @@ -0,0 +1,11 @@ +!RUN: %python %S/../test_errors.py %s %flang_fc1 %openmp_flags -fopenmp-version=51 + +subroutine f00 + integer, allocatable :: x, y + + continue + !$omp allocate + !ERROR: If multiple directives are present in an executable ALLOCATE directive, at most one of them may specify no list items + !$omp allocate + allocate(x, y) +end diff --git a/flang/test/Semantics/OpenMP/allocate11.f90 b/flang/test/Semantics/OpenMP/allocate11.f90 new file mode 100644 index 0000000..89beaa0 --- /dev/null +++ b/flang/test/Semantics/OpenMP/allocate11.f90 @@ -0,0 +1,27 @@ +! REQUIRES: openmp_runtime + +! RUN: %python %S/../test_errors.py %s %flang_fc1 %openmp_flags -fopenmp-version=50 +! OpenMP Version 5.0 +! 2.11.3 allocate Directive +! If list items within the ALLOCATE directive have the SAVE attribute, are a +! common block name, or are declared in the scope of a module, then only +! predefined memory allocator parameters can be used in the allocator clause + +module AllocateModule + INTEGER :: z + !ERROR: If a list item is a named common block, has SAVE attribute or is declared in the scope of a module, an ALLOCATOR clause must be present with a predefined allocator + !$omp allocate(z) +end module + +subroutine allocate(custom_allocator) +use omp_lib +use AllocateModule + integer, SAVE :: x + integer :: w + COMMON /CommonName/ y + + integer(kind=omp_allocator_handle_kind) :: custom_allocator + + !ERROR: If a list item is a named common block, has SAVE attribute or is declared in the scope of a module, an ALLOCATOR clause must be present with a predefined allocator + !$omp allocate(x) +end subroutine allocate diff --git a/flang/test/Semantics/OpenMP/allocate12.f90 b/flang/test/Semantics/OpenMP/allocate12.f90 new file mode 100644 index 0000000..2b3b510f --- /dev/null +++ b/flang/test/Semantics/OpenMP/allocate12.f90 @@ -0,0 +1,16 @@ +!RUN: %python %S/../test_errors.py %s %flang_fc1 %openmp_flags -fopenmp-version=51 + +subroutine f00 + integer, allocatable :: x + continue + !ERROR: An executable ALLOCATE directive must be associated with an ALLOCATE statement + !$omp allocate(x) +end + +subroutine f01 + integer, allocatable :: x + continue + !$omp allocate(x) + !ERROR: The statement associated with executable ALLOCATE directive must be an ALLOCATE statement + continue +end diff --git a/flang/test/Semantics/OpenMP/allocators01.f90 b/flang/test/Semantics/OpenMP/allocators01.f90 index ff92fa3..a334206 100644 --- a/flang/test/Semantics/OpenMP/allocators01.f90 +++ b/flang/test/Semantics/OpenMP/allocators01.f90 @@ -16,7 +16,7 @@ use omp_lib allocate(arr3(3), arr4(4, 4)) !$omp end allocators - !ERROR: Object 'arr1' in ALLOCATORS directive not found in corresponding ALLOCATE statement + !ERROR: A list item in an ALLOCATORS construct must be specified on the associated ALLOCATE statement !$omp allocators allocate(omp_default_mem_alloc: arr1, arr2) allocate(arr2(2, 2)) diff --git a/flang/test/Semantics/OpenMP/allocators04.f90 b/flang/test/Semantics/OpenMP/allocators04.f90 deleted file mode 100644 index 212e48f..0000000 --- a/flang/test/Semantics/OpenMP/allocators04.f90 +++ /dev/null @@ -1,31 +0,0 @@ -! REQUIRES: openmp_runtime - -! RUN: %python %S/../test_errors.py %s %flang_fc1 %openmp_flags -fopenmp-version=50 -! OpenMP Version 5.2 -! Inherited from 2.11.3 allocate Directive -! If list items within the ALLOCATE directive have the SAVE attribute, are a common block name, or are declared in the scope of a -! module, then only predefined memory allocator parameters can be used in the allocator clause -! SAVE and common block names can't be declared as allocatable, only module scope variables are tested - -module AllocateModule - integer, allocatable :: a, b -end module - -subroutine allocate() - use omp_lib - use AllocateModule - - integer(kind=omp_allocator_handle_kind) :: custom_allocator - type(omp_alloctrait) :: trait(1) - - trait(1)%key = fallback - trait(1)%value = default_mem_fb - custom_allocator = omp_init_allocator(omp_default_mem_space, 1, trait) - - !$omp allocators allocate(omp_default_mem_alloc: a) - allocate(a) - - !ERROR: If list items within the ALLOCATORS directive have the SAVE attribute, are a common block name, or are declared in the scope of a module, then only predefined memory allocator parameters can be used in the allocator clause - !$omp allocators allocate(custom_allocator: b) - allocate(b) -end subroutine diff --git a/flang/test/Semantics/OpenMP/allocators05.f90 b/flang/test/Semantics/OpenMP/allocators05.f90 index efacdfa..f49182f 100644 --- a/flang/test/Semantics/OpenMP/allocators05.f90 +++ b/flang/test/Semantics/OpenMP/allocators05.f90 @@ -17,7 +17,7 @@ subroutine allocate() !$omp target private(a, b) !$omp allocators allocate(omp_default_mem_alloc: a) allocate(a(LEN)) - !ERROR: ALLOCATORS directives that appear in a TARGET region must specify an allocator + !ERROR: An ALLOCATE clause in a TARGET region must specify an allocator or REQUIRES(DYNAMIC_ALLOCATORS) must be specified !$omp allocators allocate(b) allocate(b(LEN)) !$omp end target diff --git a/flang/test/Semantics/OpenMP/allocators07.f90 b/flang/test/Semantics/OpenMP/allocators07.f90 index a28f706..baaacee 100644 --- a/flang/test/Semantics/OpenMP/allocators07.f90 +++ b/flang/test/Semantics/OpenMP/allocators07.f90 @@ -5,7 +5,7 @@ subroutine f00 integer, allocatable :: a(:) !$omp allocators allocate(a) -!ERROR: The body of the ALLOCATORS construct should be an ALLOCATE statement +!ERROR: The body of an ALLOCATORS construct should be an ALLOCATE statement continue end @@ -13,7 +13,7 @@ subroutine f01 implicit none integer, allocatable :: a(:) -!ERROR: The ALLOCATORS construct should contain a single ALLOCATE statement +!ERROR: The body of an ALLOCATORS construct should be an ALLOCATE statement !$omp allocators allocate(a) !$omp end allocators end @@ -22,6 +22,6 @@ subroutine f02 implicit none integer, allocatable :: a(:) -!ERROR: The ALLOCATORS construct should contain a single ALLOCATE statement +!ERROR: The body of an ALLOCATORS construct should be an ALLOCATE statement !$omp allocators allocate(a) end diff --git a/flang/test/Semantics/OpenMP/clause-validity01.f90 b/flang/test/Semantics/OpenMP/clause-validity01.f90 index 5f74978..ad0b764 100644 --- a/flang/test/Semantics/OpenMP/clause-validity01.f90 +++ b/flang/test/Semantics/OpenMP/clause-validity01.f90 @@ -252,7 +252,7 @@ use omp_lib !$omp parallel do if(target:a>1.) do i = 1, N enddo - !ERROR: Unmatched END SIMD directive + !ERROR: Misplaced OpenMP end-directive !$omp end simd ! 2.7.2 sections-clause -> private-clause | @@ -574,7 +574,7 @@ use omp_lib do i = 1, N a = a + 3.14 enddo - !ERROR: Unmatched END TASKLOOP directive + !ERROR: Misplaced OpenMP end-directive !$omp end taskloop !ERROR: GRAINSIZE and NUM_TASKS clauses are mutually exclusive and may not appear on the same TASKLOOP SIMD directive diff --git a/flang/test/Semantics/OpenMP/compiler-directives-loop.f90 b/flang/test/Semantics/OpenMP/compiler-directives-loop.f90 new file mode 100644 index 0000000..48b9529 --- /dev/null +++ b/flang/test/Semantics/OpenMP/compiler-directives-loop.f90 @@ -0,0 +1,21 @@ +!RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=60 %s -o - | FileCheck %s + +! Check that this compiles successfully, but not rely on any specific output. + +!CHECK: omp.parallel + +program omp_cdir_crash + implicit none + integer, parameter :: n = 10 + real :: a(n) + integer :: i + +!$omp parallel do +!dir$ unroll + do i = 1, n + a(i) = real(i) + end do +!$omp end parallel do + + print *, 'a(1)=', a(1), ' a(n)=', a(n) +end program omp_cdir_crash diff --git a/flang/test/Semantics/OpenMP/declare-mapper-modfile.f90 b/flang/test/Semantics/OpenMP/declare-mapper-modfile.f90 new file mode 100644 index 0000000..480f87b --- /dev/null +++ b/flang/test/Semantics/OpenMP/declare-mapper-modfile.f90 @@ -0,0 +1,14 @@ +! RUN: split-file %s %t +! RUN: %flang_fc1 -fsyntax-only -fopenmp -fopenmp-version=50 -module-dir %t %t/m.f90 +! RUN: cat %t/m.mod | FileCheck --ignore-case %s + +!--- m.f90 +module m + implicit none + type :: t + integer :: x + end type t + !$omp declare mapper(mymap : t :: v) map(v%x) +end module m + +!CHECK: !$OMP DECLARE MAPPER(mymap:t::v) MAP(v%x) diff --git a/flang/test/Semantics/OpenMP/declare-mapper-symbols.f90 b/flang/test/Semantics/OpenMP/declare-mapper-symbols.f90 index e57a5c0..9a1b867 100644 --- a/flang/test/Semantics/OpenMP/declare-mapper-symbols.f90 +++ b/flang/test/Semantics/OpenMP/declare-mapper-symbols.f90 @@ -11,9 +11,9 @@ program main !$omp declare mapper(ty :: maptwo) map(maptwo, maptwo%x) !! Note, symbols come out in their respective scope, but not in declaration order. -!CHECK: mymapper: Misc ConstructName +!CHECK: mymapper: MapperDetails !CHECK: ty: DerivedType components: x -!CHECK: ty.omp.default.mapper: Misc ConstructName +!CHECK: ty_omp_default_mapper: MapperDetails !CHECK: DerivedType scope: ty !CHECK: OtherConstruct scope: !CHECK: mapped (OmpMapToFrom) {{.*}} ObjectEntity type: TYPE(ty) @@ -21,4 +21,3 @@ program main !CHECK: maptwo (OmpMapToFrom) {{.*}} ObjectEntity type: TYPE(ty) end program main - diff --git a/flang/test/Semantics/OpenMP/defaultmap-clause-none.f90 b/flang/test/Semantics/OpenMP/defaultmap-clause-none.f90 new file mode 100644 index 0000000..0b74e341 --- /dev/null +++ b/flang/test/Semantics/OpenMP/defaultmap-clause-none.f90 @@ -0,0 +1,133 @@ +! RUN: %python %S/../test_errors.py %s %flang -fopenmp -fopenmp-version=51 + +subroutine defaultmap_all_none_no_errors + implicit none + real :: array(10) + integer, pointer :: ptr(:) + real, allocatable :: alloca + integer :: index + + !$omp target defaultmap(none) map(to: index, alloca) map(tofrom: array, ptr) + do index = 1, 10 + ptr(index) = array(index) + alloca + end do + !$omp end target +end subroutine defaultmap_all_none_no_errors + +subroutine defaultmap_all_none + implicit none + real :: array(10) + integer, pointer :: ptr(:) + real, allocatable :: alloca + integer :: index + !$omp target defaultmap(none) +!ERROR: The DEFAULTMAP(NONE) clause requires that 'index' must be listed in a data-sharing attribute, data-mapping attribute, or is_device_ptr clause + do index = 1, 10 +!ERROR: The DEFAULTMAP(NONE) clause requires that 'ptr' must be listed in a data-sharing attribute, data-mapping attribute, or is_device_ptr clause +!ERROR: The DEFAULTMAP(NONE) clause requires that 'index' must be listed in a data-sharing attribute, data-mapping attribute, or is_device_ptr clause +!ERROR: The DEFAULTMAP(NONE) clause requires that 'array' must be listed in a data-sharing attribute, data-mapping attribute, or is_device_ptr clause +!ERROR: The DEFAULTMAP(NONE) clause requires that 'index' must be listed in a data-sharing attribute, data-mapping attribute, or is_device_ptr clause +!ERROR: The DEFAULTMAP(NONE) clause requires that 'alloca' must be listed in a data-sharing attribute, data-mapping attribute, or is_device_ptr clause + ptr(index) = array(index) + alloca + end do + !$omp end target +end subroutine defaultmap_all_none + +subroutine defaultmap_scalar_none + implicit none + real :: array(10) + integer, pointer :: ptr(:) + real, allocatable :: alloca + integer :: index + + !$omp target defaultmap(none: scalar) +!ERROR: The DEFAULTMAP(NONE) clause requires that 'index' must be listed in a data-sharing attribute, data-mapping attribute, or is_device_ptr clause + do index = 1, 10 +!ERROR: The DEFAULTMAP(NONE) clause requires that 'index' must be listed in a data-sharing attribute, data-mapping attribute, or is_device_ptr clause +!ERROR: The DEFAULTMAP(NONE) clause requires that 'index' must be listed in a data-sharing attribute, data-mapping attribute, or is_device_ptr clause + ptr(index) = array(index) + alloca + end do + !$omp end target +end subroutine defaultmap_scalar_none + +subroutine defaultmap_pointer_none + implicit none + real :: array(10) + integer, pointer :: ptr(:) + real, allocatable :: alloca + integer :: index + + !$omp target defaultmap(none: pointer) + do index = 1, 10 +!ERROR: The DEFAULTMAP(NONE) clause requires that 'ptr' must be listed in a data-sharing attribute, data-mapping attribute, or is_device_ptr clause + ptr(index) = array(index) + alloca + end do + !$omp end target +end subroutine defaultmap_pointer_none + +subroutine defaultmap_allocatable_none + implicit none + real :: array(10) + integer, pointer :: ptr(:) + real, allocatable :: alloca + integer :: index + + !$omp target defaultmap(none: allocatable) + do index = 1, 10 +!ERROR: The DEFAULTMAP(NONE) clause requires that 'alloca' must be listed in a data-sharing attribute, data-mapping attribute, or is_device_ptr clause + ptr(index) = array(index) + alloca + end do + !$omp end target +end subroutine defaultmap_allocatable_none + +subroutine defaultmap_aggregate_none + implicit none + real :: array(10) + integer, pointer :: ptr(:) + real, allocatable :: alloca + integer :: index + + !$omp target defaultmap(none: aggregate) + do index = 1, 10 +!ERROR: The DEFAULTMAP(NONE) clause requires that 'array' must be listed in a data-sharing attribute, data-mapping attribute, or is_device_ptr clause + ptr(index) = array(index) + alloca + end do + !$omp end target +end subroutine defaultmap_aggregate_none + +! Verify we do not catch null in defaultmap(none) +subroutine defaultmap_builtin_none + implicit none + integer, pointer :: ptr(:) + + !$omp target defaultmap(none) map(ptr) +!CHECK-NOT: The DEFAULTMAP(NONE) clause requires that 'null' must be listed in a data-sharing attribute, data-mapping attribute, or is_device_ptr clause + ptr => null() + !$omp end target +end subroutine defaultmap_builtin_none + +module pro + implicit none +contains + + function test_procedure() result(ret) + integer :: ret + ret = 1 + end function test_procedure + +! Verify we do not catch a function symbol in defaultmap(none) +! but do catch procedure pointers +subroutine defaultmap_func_and_procedure_pointer() + implicit none + procedure(test_procedure), pointer :: f1 + integer :: i + + f1 => test_procedure + + !$omp target defaultmap(none) map(i) +!ERROR: The DEFAULTMAP(NONE) clause requires that 'f1' must be listed in a data-sharing attribute, data-mapping attribute, or is_device_ptr clause + i = f1() + i = test_procedure() + !$omp end target +end subroutine defaultmap_func_and_procedure_pointer +end module diff --git a/flang/test/Semantics/OpenMP/do21.f90 b/flang/test/Semantics/OpenMP/do21.f90 index 2f5815c..e6fe7dd 100644 --- a/flang/test/Semantics/OpenMP/do21.f90 +++ b/flang/test/Semantics/OpenMP/do21.f90 @@ -2,26 +2,26 @@ ! Check for existence of loop following a DO directive subroutine do1 - !ERROR: A DO loop must follow the DO directive + !ERROR: OpenMP loop construct should contain a DO-loop or a loop-nest-generating OpenMP construct !$omp do end subroutine subroutine do2 - !ERROR: A DO loop must follow the PARALLEL DO directive + !ERROR: OpenMP loop construct should contain a DO-loop or a loop-nest-generating OpenMP construct !$omp parallel do end subroutine subroutine do3 - !ERROR: A DO loop must follow the SIMD directive + !ERROR: OpenMP loop construct should contain a DO-loop or a loop-nest-generating OpenMP construct !$omp simd end subroutine subroutine do4 - !ERROR: A DO loop must follow the DO SIMD directive + !ERROR: OpenMP loop construct should contain a DO-loop or a loop-nest-generating OpenMP construct !$omp do simd end subroutine subroutine do5 - !ERROR: A DO loop must follow the LOOP directive + !ERROR: OpenMP loop construct should contain a DO-loop or a loop-nest-generating OpenMP construct !$omp loop end subroutine diff --git a/flang/test/Semantics/OpenMP/dyn-groupprivate.f90 b/flang/test/Semantics/OpenMP/dyn-groupprivate.f90 new file mode 100644 index 0000000..f77a0b0 --- /dev/null +++ b/flang/test/Semantics/OpenMP/dyn-groupprivate.f90 @@ -0,0 +1,8 @@ +!RUN: %python %S/../test_errors.py %s %flang -fopenmp -fopenmp-version=61 + +subroutine f00(x) + integer :: x + !ERROR: The access-group modifier can only occur on a single clause in a construct + !$omp target dyn_groupprivate(cgroup: x), dyn_groupprivate(10) + !$omp end target +end diff --git a/flang/test/Semantics/OpenMP/in-reduction.f90 b/flang/test/Semantics/OpenMP/in-reduction.f90 index 1b82134..3f1e735 100644 --- a/flang/test/Semantics/OpenMP/in-reduction.f90 +++ b/flang/test/Semantics/OpenMP/in-reduction.f90 @@ -47,6 +47,7 @@ subroutine f06 integer :: a(10) end type type(t) :: x +!ERROR: A variable that is part of another variable cannot appear on the IN_REDUCTION clause !ERROR: The base expression of an array element or section in IN_REDUCTION clause must be an identifier !$omp target in_reduction(+: x%a(2)) !$omp end target @@ -57,6 +58,7 @@ subroutine f07 integer :: a(10) end type type(t) :: x +!ERROR: A variable that is part of another variable cannot appear on the IN_REDUCTION clause !ERROR: The base expression of an array element or section in IN_REDUCTION clause must be an identifier !$omp target in_reduction(+: x%a(1:10)) !$omp end target diff --git a/flang/test/Semantics/OpenMP/loop-association.f90 b/flang/test/Semantics/OpenMP/loop-association.f90 index 9fac508..7070ff5 100644 --- a/flang/test/Semantics/OpenMP/loop-association.f90 +++ b/flang/test/Semantics/OpenMP/loop-association.f90 @@ -17,11 +17,13 @@ !$omp end parallel !$omp parallel do + !ERROR: DO CONCURRENT loops cannot form part of a loop nest. DO CONCURRENT (i = 1:N) a = 3.14 END DO !$omp parallel do simd + !ERROR: The associated loop of a loop-associated directive cannot be a DO WHILE. outer: DO WHILE (c > 1) inner: do while (b > 100) a = 3.14 @@ -32,6 +34,8 @@ ! Accept directives between parallel do and actual loop. !$OMP PARALLEL DO + !WARNING: Unrecognized compiler directive was ignored [-Wignored-directive] + !WARNING: Compiler directives are not allowed inside OpenMP loop constructs !DIR$ VECTOR ALIGNED DO 20 i=1,N a = a + 0.5 @@ -39,11 +43,14 @@ !$OMP END PARALLEL DO c = 16 - !ERROR: DO loop after the PARALLEL DO directive must have loop control !$omp parallel do + !ERROR: Loop control is not present in the DO LOOP + !ERROR: The associated loop of a loop-associated directive cannot be a DO without control. do a = 3.14 c = c - 1 + !ERROR: EXIT to construct outside of PARALLEL DO construct is not allowed + !ERROR: EXIT statement terminates associated loop of an OpenMP DO construct if (c < 1) exit enddo @@ -57,9 +64,10 @@ do 100 j=1, N a = 3.14 100 continue - !ERROR: The ENDDO directive must follow the DO loop associated with the loop construct + !ERROR: END DO directive is not allowed when the construct does not contain all loops that share a loop-terminating statement !$omp enddo + !ERROR: Non-THREADPRIVATE object 'a' in COPYIN clause !$omp parallel do copyin(a) do i = 1, N !$omp parallel do @@ -74,7 +82,7 @@ do i = 1, N enddo !$omp end parallel do - !ERROR: The END PARALLEL DO directive must follow the DO loop associated with the loop construct + !ERROR: Misplaced OpenMP end-directive !$omp end parallel do !$omp parallel @@ -84,26 +92,27 @@ enddo !$omp end do simd + !ERROR: Non-THREADPRIVATE object 'a' in COPYIN clause !$omp parallel do copyin(a) do i = 1, N enddo !$omp end parallel a = 0.0 - !ERROR: The END PARALLEL DO directive must follow the DO loop associated with the loop construct + !ERROR: Misplaced OpenMP end-directive !$omp end parallel do !$omp parallel do private(c) do i = 1, N do j = 1, N - !ERROR: A DO loop must follow the PARALLEL DO directive + !ERROR: OpenMP loop construct should contain a DO-loop or a loop-nest-generating OpenMP construct !$omp parallel do shared(b) a = 3.14 enddo - !ERROR: The END PARALLEL DO directive must follow the DO loop associated with the loop construct + !ERROR: Misplaced OpenMP end-directive !$omp end parallel do enddo a = 1.414 - !ERROR: The END PARALLEL DO directive must follow the DO loop associated with the loop construct + !ERROR: Misplaced OpenMP end-directive !$omp end parallel do do i = 1, N @@ -112,16 +121,16 @@ a = 3.14 enddo enddo - !ERROR: The END PARALLEL DO directive must follow the DO loop associated with the loop construct + !ERROR: Misplaced OpenMP end-directive !$omp end parallel do - !ERROR: A DO loop must follow the PARALLEL DO directive + !ERROR: OpenMP loop construct should contain a DO-loop or a loop-nest-generating OpenMP construct !$omp parallel do private(c) 5 FORMAT (1PE12.4, I10) do i=1, N a = 3.14 enddo - !ERROR: The END PARALLEL DO directive must follow the DO loop associated with the loop construct + !ERROR: Misplaced OpenMP end-directive !$omp end parallel do !$omp parallel do simd @@ -129,12 +138,13 @@ a = 3.14 enddo !$omp end parallel do simd - !ERROR: The END PARALLEL DO SIMD directive must follow the DO loop associated with the loop construct + !ERROR: Misplaced OpenMP end-directive !$omp end parallel do simd - !ERROR: A DO loop must follow the SIMD directive + !ERROR: OpenMP loop construct should contain a DO-loop or a loop-nest-generating OpenMP construct !$omp simd a = i + 1 - !ERROR: The END SIMD directive must follow the DO loop associated with the loop construct + !ERROR: Misplaced OpenMP end-directive !$omp end simd + a = i + 1 end diff --git a/flang/test/Semantics/OpenMP/loop-transformation-clauses01.f90 b/flang/test/Semantics/OpenMP/loop-transformation-clauses01.f90 new file mode 100644 index 0000000..9ca0e8c --- /dev/null +++ b/flang/test/Semantics/OpenMP/loop-transformation-clauses01.f90 @@ -0,0 +1,66 @@ +! Testing the Semantics of clauses on loop transformation directives + +!RUN: %python %S/../test_errors.py %s %flang -fopenmp -fopenmp-version=60 + + +subroutine loop_transformation_construct1 + implicit none + integer, parameter:: i = 5 + integer :: x + integer :: a + integer :: v(i) + + !ERROR: At most one LOOPRANGE clause can appear on the FUSE directive + !$omp fuse looprange(1,2) looprange(1,2) + do x = 1, i + v(x) = x * 2 + end do + do x = 1, i + v(x) = x * 2 + end do + !$omp end fuse + + !ERROR: The loop range indicated in the LOOPRANGE(5,2) clause must not be out of the bounds of the Loop Sequence following the construct. + !$omp fuse looprange(5,2) + do x = 1, i + v(x) = x * 2 + end do + do x = 1, i + v(x) = x * 2 + end do + !$omp end fuse + + !ERROR: The parameter of the LOOPRANGE clause must be a constant positive integer expression + !$omp fuse looprange(0,1) + do x = 1, i + v(x) = x * 2 + end do + do x = 1, i + v(x) = x * 2 + end do + !$omp end fuse + + !ERROR: The parameter of the LOOPRANGE clause must be a constant positive integer expression + !$omp fuse looprange(1,-1) + do x = 1, i + v(x) = x * 2 + end do + do x = 1, i + v(x) = x * 2 + end do + !$omp end fuse + + !ERROR: Must be a constant value + !$omp fuse looprange(a,2) + do x = 1, i + v(x) = x * 2 + end do + !$omp end fuse + + !ERROR: Must be a constant value + !$omp fuse looprange(1,a) + do x = 1, i + v(x) = x * 2 + end do + !$omp end fuse +end subroutine diff --git a/flang/test/Semantics/OpenMP/loop-transformation-construct01.f90 b/flang/test/Semantics/OpenMP/loop-transformation-construct01.f90 index f718efc..caa8f3f 100644 --- a/flang/test/Semantics/OpenMP/loop-transformation-construct01.f90 +++ b/flang/test/Semantics/OpenMP/loop-transformation-construct01.f90 @@ -5,96 +5,100 @@ subroutine loop_transformation_construct1 implicit none + !ERROR: OpenMP loop construct cannot apply to a fully unrolled loop !$omp do - !ERROR: A DO loop must follow the UNROLL directive + !ERROR: OpenMP loop construct should contain a DO-loop or a loop-nest-generating OpenMP construct !$omp unroll end subroutine subroutine loop_transformation_construct2 implicit none - integer :: i = 5 - integer :: y + integer, parameter :: i = 5 + integer :: x integer :: v(i) !$omp do + !ERROR: At least one of SIZES clause must appear on the TILE directive !$omp tile do x = 1, i - v(x) = x(x) * 2 + v(x) = v(x) * 2 end do !$omp end tile !$omp end do - !ERROR: The END TILE directive must follow the DO loop associated with the loop construct - !$omp end tile end subroutine -subroutine loop_transformation_construct2 +subroutine loop_transformation_construct3 implicit none - integer :: i = 5 - integer :: y + integer, parameter :: i = 5 + integer :: x integer :: v(i) !$omp do - !ERROR: Only Loop Transformation Constructs or Loop Nests can be nested within Loop Constructs + !ERROR: Only loop-transforming OpenMP constructs are allowed inside OpenMP loop constructs !$omp parallel do do x = 1, i - v(x) = x(x) * 2 + v(x) = v(x) * 2 end do end subroutine -subroutine loop_transformation_construct3 +subroutine loop_transformation_construct4 implicit none - integer :: i = 5 - integer :: y + integer, parameter :: i = 5 + integer :: x integer :: v(i) !$omp do do x = 1, i - v(x) = x(x) * 2 + v(x) = v(x) * 2 end do - !ERROR: A DO loop must follow the TILE directive + !ERROR: OpenMP loop construct should contain a DO-loop or a loop-nest-generating OpenMP construct + !ERROR: At least one of SIZES clause must appear on the TILE directive !$omp tile end subroutine -subroutine loop_transformation_construct4 +subroutine loop_transformation_construct5 implicit none - integer :: i = 5 - integer :: y + integer, parameter :: i = 5 + integer :: x integer :: v(i) !$omp do - !ERROR: If a loop construct has been fully unrolled, it cannot then be tiled + !ERROR: OpenMP loop construct cannot apply to a fully unrolled loop + !ERROR: At least one of SIZES clause must appear on the TILE directive !$omp tile !$omp unroll full do x = 1, i - v(x) = x(x) * 2 + v(x) = v(x) * 2 end do end subroutine -subroutine loop_transformation_construct5 +subroutine loop_transformation_construct6 implicit none - integer :: i = 5 - integer :: y + integer, parameter :: i = 5 + integer :: x integer :: v(i) !$omp do - !ERROR: If a loop construct has been fully unrolled, it cannot then be tiled + !ERROR: OpenMP loop construct cannot apply to a fully unrolled loop + !ERROR: At least one of SIZES clause must appear on the TILE directive !$omp tile !$omp unroll do x = 1, i - v(x) = x(x) * 2 + v(x) = v(x) * 2 end do end subroutine -subroutine loop_transformation_construct6 +subroutine loop_transformation_construct7 implicit none - integer :: i = 5 - integer :: y + integer, parameter :: i = 5 + integer :: x integer :: v(i) !$omp do + !ERROR: At least one of SIZES clause must appear on the TILE directive !$omp tile !$omp unroll partial(2) do x = 1, i - v(x) = x(x) * 2 + v(x) = v(x) * 2 end do end subroutine diff --git a/flang/test/Semantics/OpenMP/loop-transformation-construct02.f90 b/flang/test/Semantics/OpenMP/loop-transformation-construct02.f90 new file mode 100644 index 0000000..1b15c93 --- /dev/null +++ b/flang/test/Semantics/OpenMP/loop-transformation-construct02.f90 @@ -0,0 +1,94 @@ +! Testing the Semantics of loop sequences combined with +! nested Loop Transformation Constructs + +!RUN: %python %S/../test_errors.py %s %flang -fopenmp -fopenmp-version=60 + +subroutine loop_transformation_construct1 + implicit none + + !$omp do + !ERROR: OpenMP loop construct should contain a DO-loop or a loop-nest-generating OpenMP construct + !$omp fuse +end subroutine + +subroutine loop_transformation_construct2 + implicit none + + !$omp do + !ERROR: OpenMP loop construct should contain a DO-loop or a loop-nest-generating OpenMP construct + !$omp fuse + !$omp end fuse +end subroutine + +subroutine loop_transformation_construct3 + implicit none + integer, parameter :: i = 5 + integer :: x + integer :: v(i) + + !$omp do + !$omp fuse + do x = 1, i + v(x) = v(x) * 2 + end do + do x = 1, i + v(x) = v(x) * 2 + end do + !$omp end fuse + !$omp end do + !ERROR: Misplaced OpenMP end-directive + !$omp end fuse +end subroutine + +subroutine loop_transformation_construct4 + implicit none + integer, parameter :: i = 5 + integer :: x + integer :: v(i) + + !$omp do + do x = 1, i + v(x) = v(x) * 2 + end do + !ERROR: OpenMP loop construct should contain a DO-loop or a loop-nest-generating OpenMP construct + !$omp fuse + !$omp end fuse +end subroutine + +subroutine loop_transformation_construct5 + implicit none + integer, parameter :: i = 5 + integer :: x + integer :: v(i) + + !$omp do + !ERROR: OpenMP loop construct cannot apply to a fully unrolled loop + !$omp fuse + !$omp unroll full + do x = 1, i + v(x) = v(x) * 2 + end do + do x = 1, i + v(x) = v(x) * 2 + end do + !$omp end fuse +end subroutine + +subroutine loop_transformation_construct6 + implicit none + integer, parameter :: i = 5 + integer :: x + integer :: v(i) + + !ERROR: The loop sequence following the DO construct must be fully fused first. + !$omp do + !$omp fuse looprange(1,1) + !$omp unroll partial(2) + do x = 1, i + v(x) = v(x) * 2 + end do + do x = 1, i + v(x) = v(x) * 2 + end do + !$omp end fuse +end subroutine diff --git a/flang/test/Semantics/OpenMP/loop-transformation-construct03.f90 b/flang/test/Semantics/OpenMP/loop-transformation-construct03.f90 new file mode 100644 index 0000000..578c55b --- /dev/null +++ b/flang/test/Semantics/OpenMP/loop-transformation-construct03.f90 @@ -0,0 +1,39 @@ +! Testing the Semantic failure of forming loop sequences under regular OpenMP directives + +!RUN: %python %S/../test_errors.py %s %flang -fopenmp -fopenmp-version=60 + +subroutine loop_transformation_construct1 + implicit none + integer, parameter :: i = 5 + integer :: x + integer :: v(i) + + ! Only 1 do loop is associated with the OMP DO directive so the END DO directive is unmatched + !$omp do + do x = 1, i + v(x) = v(x) * 2 + end do + do x = 1, i + v(x) = v(x) * 2 + end do + !ERROR: Misplaced OpenMP end-directive + !$omp end do +end subroutine + +subroutine loop_transformation_construct2 + implicit none + integer, parameter :: i = 5 + integer :: x + integer :: v(i) + + ! Only 1 do loop is associated with the OMP TILE directive so the END TILE directive is unmatched + !$omp tile sizes(2) + do x = 1, i + v(x) = v(x) * 2 + end do + do x = 1, i + v(x) = v(x) * 2 + end do + !ERROR: Misplaced OpenMP end-directive + !$omp end tile +end subroutine diff --git a/flang/test/Semantics/OpenMP/loop-transformation-construct04.f90 b/flang/test/Semantics/OpenMP/loop-transformation-construct04.f90 new file mode 100644 index 0000000..2856247 --- /dev/null +++ b/flang/test/Semantics/OpenMP/loop-transformation-construct04.f90 @@ -0,0 +1,47 @@ +! Testing the Semantic failure of forming loop sequences under regular OpenMP directives + +!RUN: %python %S/../test_errors.py %s %flang -fopenmp -fopenmp-version=60 + +subroutine loop_transformation_construct3 + implicit none + integer, parameter :: i = 5 + integer :: x + integer :: v(i) + + !ERROR: The loop sequence following the DO construct must be fully fused first. + !$omp do + !$omp fuse looprange(1,2) + do x = 1, i + v(x) = x * 2 + end do + do x = 1, i + v(x) = x * 2 + end do + do x = 1, i + v(x) = x * 2 + end do + !$omp end fuse + !$omp end do +end subroutine + +subroutine loop_transformation_construct4 + implicit none + integer, parameter :: i = 5 + integer :: x + integer :: v(i) + + !ERROR: The loop sequence following the TILE construct must be fully fused first. + !$omp tile sizes(2) + !$omp fuse looprange(1,2) + do x = 1, i + v(x) = x * 2 + end do + do x = 1, i + v(x) = x * 2 + end do + do x = 1, i + v(x) = x * 2 + end do + !$omp end fuse + !$omp end tile +end subroutine diff --git a/flang/test/Semantics/OpenMP/map-clause-symbols.f90 b/flang/test/Semantics/OpenMP/map-clause-symbols.f90 index 1d6315b..3b723e8 100644 --- a/flang/test/Semantics/OpenMP/map-clause-symbols.f90 +++ b/flang/test/Semantics/OpenMP/map-clause-symbols.f90 @@ -1,14 +1,16 @@ ! RUN: %flang_fc1 -fdebug-dump-symbols -fopenmp -fopenmp-version=50 %s | FileCheck %s program main !CHECK-LABEL: MainProgram scope: MAIN + type ty + real(4) :: x + end type ty + !$omp declare mapper(xx : ty :: v) map(v) integer, parameter :: n = 256 - real(8) :: a(256) + type(ty) :: a(256) !$omp target map(mapper(xx), from:a) do i=1,n - a(i) = 4.2 + a(i)%x = 4.2 end do !$omp end target -!CHECK: OtherConstruct scope: size=0 alignment=1 sourceRange=74 bytes -!CHECK: OtherClause scope: size=0 alignment=1 sourceRange=0 bytes -!CHECK: xx: Misc ConstructName +!CHECK: xx: MapperDetails end program main diff --git a/flang/test/Semantics/OpenMP/reduction15.f90 b/flang/test/Semantics/OpenMP/reduction15.f90 index 1d4de6f..61fa417 100644 --- a/flang/test/Semantics/OpenMP/reduction15.f90 +++ b/flang/test/Semantics/OpenMP/reduction15.f90 @@ -13,6 +13,7 @@ contains subroutine f00 type(t) :: x + !ERROR: A variable that is part of another variable cannot appear on the REDUCTION clause !ERROR: The base expression of an array element or section in REDUCTION clause must be an identifier !$omp do reduction (+ : x%a(2)) do i = 1, 10 @@ -22,6 +23,7 @@ contains subroutine f01 type(t) :: x + !ERROR: A variable that is part of another variable cannot appear on the REDUCTION clause !ERROR: The base expression of an array element or section in REDUCTION clause must be an identifier !$omp do reduction (+ : x%a(1:10)) do i = 1, 10 diff --git a/flang/test/Semantics/OpenMP/reduction17.f90 b/flang/test/Semantics/OpenMP/reduction17.f90 new file mode 100644 index 0000000..5b6e8e9 --- /dev/null +++ b/flang/test/Semantics/OpenMP/reduction17.f90 @@ -0,0 +1,18 @@ +! Test that Structure Component Array Elements are caught by Semantics and return an error +! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp -fopenmp-version=45 + +type test_type + integer :: array(2) +end type + +contains + subroutine test + type(test_type) :: x + + !ERROR: A variable that is part of another variable cannot appear on the REDUCTION clause + !$omp do reduction(+: x%array(2)) + do i=1, 2 + end do + !$omp end do + end subroutine +end diff --git a/flang/test/Semantics/OpenMP/simd-only.f90 b/flang/test/Semantics/OpenMP/simd-only.f90 index e137ef7..4e29329 100644 --- a/flang/test/Semantics/OpenMP/simd-only.f90 +++ b/flang/test/Semantics/OpenMP/simd-only.f90 @@ -10,7 +10,7 @@ subroutine test_simd() ! CHECK: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPLoopConstruct ! CHECK: OmpDirectiveName -> llvm::omp::Directive = simd - ! CHECK-NOT: ExecutionPartConstruct -> ExecutableConstruct -> DoConstruct + ! CHECK: ExecutionPartConstruct -> ExecutableConstruct -> DoConstruct !$omp simd do i = 1, 100 end do @@ -22,7 +22,7 @@ subroutine test_do_simd() ! CHECK: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPLoopConstruct ! CHECK: OmpDirectiveName -> llvm::omp::Directive = do simd - ! CHECK-NOT: ExecutionPartConstruct -> ExecutableConstruct -> DoConstruct + ! CHECK: ExecutionPartConstruct -> ExecutableConstruct -> DoConstruct !$omp do simd do i = 1, 100 end do @@ -35,7 +35,7 @@ subroutine test_parallel_do_simd() ! CHECK: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPLoopConstruct ! CHECK: OmpDirectiveName -> llvm::omp::Directive = parallel do simd - ! CHECK-NOT: ExecutionPartConstruct -> ExecutableConstruct -> DoConstruct + ! CHECK: ExecutionPartConstruct -> ExecutableConstruct -> DoConstruct !$omp parallel do simd do i = 1, 100 end do @@ -65,7 +65,7 @@ subroutine test_simd_atomic() ! CHECK: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPLoopConstruct ! CHECK: OmpDirectiveName -> llvm::omp::Directive = simd - ! CHECK-NOT: ExecutionPartConstruct -> ExecutableConstruct -> DoConstruct + ! CHECK: ExecutionPartConstruct -> ExecutableConstruct -> DoConstruct !$omp simd do i = 1, 100 ! CHECK-NOT: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPAtomicConstruct diff --git a/flang/test/Semantics/OpenMP/target-loop-still-there.f90 b/flang/test/Semantics/OpenMP/target-loop-still-there.f90 new file mode 100644 index 0000000..2d3b182 --- /dev/null +++ b/flang/test/Semantics/OpenMP/target-loop-still-there.f90 @@ -0,0 +1,10 @@ +!RUN: %flang_fc1 -fsyntax-only -fopenmp -fopenmp-version=60 -Werror %s | FileCheck --allow-empty %s + +!CHECK-NOT: deprecated +subroutine f00 + implicit none + integer :: i + !$omp target loop + do i = 1, 10 + end do +end diff --git a/flang/test/Semantics/OpenMP/target-teams-nesting.f90 b/flang/test/Semantics/OpenMP/target-teams-nesting.f90 new file mode 100644 index 0000000..c1760af --- /dev/null +++ b/flang/test/Semantics/OpenMP/target-teams-nesting.f90 @@ -0,0 +1,20 @@ +! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp + +program main + implicit none + integer, parameter :: n = 100 + integer, parameter :: expected = n+2 + integer :: i + integer :: counter + + counter = 0 + !ERROR: TARGET construct with nested TEAMS region contains statements or directives outside of the TEAMS construct + !$omp target map(tofrom:counter) + counter = counter+1 + !$omp teams distribute reduction(+:counter) + do i=1, n + counter = counter+1 + end do + counter = counter+1 + !$omp end target + end program diff --git a/flang/test/Semantics/OpenMP/task-reduction.f90 b/flang/test/Semantics/OpenMP/task-reduction.f90 index 5a18ee4..f76b07a 100644 --- a/flang/test/Semantics/OpenMP/task-reduction.f90 +++ b/flang/test/Semantics/OpenMP/task-reduction.f90 @@ -47,6 +47,7 @@ subroutine f06 integer :: a(10) end type type(t) :: x +!ERROR: A variable that is part of another variable cannot appear on the TASK_REDUCTION clause !ERROR: The base expression of an array element or section in TASK_REDUCTION clause must be an identifier !$omp taskgroup task_reduction(+: x%a(2)) !$omp end taskgroup @@ -57,6 +58,7 @@ subroutine f07 integer :: a(10) end type type(t) :: x +!ERROR: A variable that is part of another variable cannot appear on the TASK_REDUCTION clause !ERROR: The base expression of an array element or section in TASK_REDUCTION clause must be an identifier !$omp taskgroup task_reduction(+: x%a(1:10)) !$omp end taskgroup diff --git a/flang/test/Semantics/OpenMP/taskloop04.f90 b/flang/test/Semantics/OpenMP/taskloop04.f90 new file mode 100644 index 0000000..4ffcf84 --- /dev/null +++ b/flang/test/Semantics/OpenMP/taskloop04.f90 @@ -0,0 +1,15 @@ +! When lowering Taskloop, it is possible for the TileSizes clause to be lowered, but this is not a supported clause. +! We should make sure that any use of Tilesizes with Taskloop is correctly rejected by the Semantics. +! RUN: %python %S/../test_errors.py %s %flang -fopenmp + +subroutine test + integer :: i, sum + + !ERROR: TILE cannot follow TASKLOOP + !ERROR: SIZES clause is not allowed on the TASKLOOP directive + !$omp taskloop tile sizes(2) + do i=1,10 + sum = sum + i + end do + !$omp end taskloop +end subroutine diff --git a/flang/test/Semantics/OpenMP/threadset-clause.f90 b/flang/test/Semantics/OpenMP/threadset-clause.f90 new file mode 100644 index 0000000..59cd3ef --- /dev/null +++ b/flang/test/Semantics/OpenMP/threadset-clause.f90 @@ -0,0 +1,9 @@ +!RUN: %python %S/../test_errors.py %s %flang -fopenmp -fopenmp-version=45 + +subroutine f00(x) + integer :: x(10) +!ERROR: THREADSET clause is not allowed on directive TASK in OpenMP v4.5, try -fopenmp-version=60 +!$omp task threadset(omp_pool) + x = x + 1 +!$omp end task +end diff --git a/flang/test/Semantics/OpenMP/tile02.f90 b/flang/test/Semantics/OpenMP/tile02.f90 index 6767963..5b70f94 100644 --- a/flang/test/Semantics/OpenMP/tile02.f90 +++ b/flang/test/Semantics/OpenMP/tile02.f90 @@ -6,7 +6,7 @@ subroutine on_unroll implicit none integer i - !ERROR: If a loop construct has been fully unrolled, it cannot then be tiled + !ERROR: OpenMP loop construct cannot apply to a fully unrolled loop !$omp tile sizes(2) !$omp unroll do i = 1, 5 diff --git a/flang/test/Semantics/allocate14.f90 b/flang/test/Semantics/allocate14.f90 index a97cf5a..bbd7a41 100644 --- a/flang/test/Semantics/allocate14.f90 +++ b/flang/test/Semantics/allocate14.f90 @@ -2,7 +2,7 @@ ! Check for semantic errors in ALLOCATE statements program allocate14 - + integer, allocatable :: i1, i2 character(200), allocatable :: msg1, msg2 type t @@ -53,4 +53,3 @@ program allocate14 !TODO: ERRMSG variable in DEALLOCATE must not be the variable being deallocated deallocate(ts, stat=ts(1)%i, errmsg=ts(1)%msg) end program - diff --git a/flang/test/Semantics/bindings01.f90 b/flang/test/Semantics/bindings01.f90 index 3283ac3..ae02b8f 100644 --- a/flang/test/Semantics/bindings01.f90 +++ b/flang/test/Semantics/bindings01.f90 @@ -147,7 +147,7 @@ module m2 procedure proc end type child contains - subroutine proc + subroutine proc end subroutine end module m2 diff --git a/flang/test/Semantics/bug168099.f90 b/flang/test/Semantics/bug168099.f90 new file mode 100644 index 0000000..bc08933d --- /dev/null +++ b/flang/test/Semantics/bug168099.f90 @@ -0,0 +1,28 @@ +!RUN: %python %S/test_errors.py %s %flang_fc1 +module m1 + type pair + end type + interface pair + module procedure f + end interface + contains + type(pair) function f(n) + integer, intent(in) :: n + f = pair() + end +end +module m2 + type pair + end type +end +module m3 + type pair + end type +end +program main + use m1 + use m2 + use m3 + !ERROR: Reference to 'pair' is ambiguous + type(pair) error +end diff --git a/flang/test/Semantics/c_f_pointer.f90 b/flang/test/Semantics/c_f_pointer.f90 index 8a22175..29b1127 100644 --- a/flang/test/Semantics/c_f_pointer.f90 +++ b/flang/test/Semantics/c_f_pointer.f90 @@ -46,13 +46,17 @@ program test call c_f_pointer(scalarC, multiDimIntF, shape=[1_8]) !ERROR: SHAPE= argument to C_F_POINTER() must be a rank-one array. call c_f_pointer(scalarC, multiDimIntF, shape=rankTwoArray) - !WARNING: FPTR= argument to C_F_POINTER() should not be unlimited polymorphic [-Winteroperability] + + !These warnings have been disabled because the C_F_POINTER's restrictions + !are dependent on the source of the CPTR= argument. Each warning here + !might be a false positive for a valid program. + !!WARNING: FPTR= argument to C_F_POINTER() should not be unlimited polymorphic [-Winteroperability] call c_f_pointer(scalarC, unlimited) - !PORTABILITY: FPTR= argument to C_F_POINTER() should not have a derived type that is not BIND(C) [-Wportability] + !!PORTABILITY: FPTR= argument to C_F_POINTER() should not have a derived type that is not BIND(C) [-Wportability] call c_f_pointer(scalarC, notBindC) - !WARNING: FPTR= argument to C_F_POINTER() should not have the non-interoperable character length CHARACTER(KIND=1,LEN=2_8) [-Wcharacter-interoperability] + !!WARNING: FPTR= argument to C_F_POINTER() should not have the non-interoperable character length CHARACTER(KIND=1,LEN=2_8) [-Wcharacter-interoperability] call c_f_pointer(scalarC, c2ptr) - !WARNING: FPTR= argument to C_F_POINTER() should not have the non-interoperable intrinsic type or kind CHARACTER(KIND=4,LEN=1_8) [-Winteroperability] + !!WARNING: FPTR= argument to C_F_POINTER() should not have the non-interoperable intrinsic type or kind CHARACTER(KIND=4,LEN=1_8) [-Winteroperability] call c_f_pointer(scalarC, unicodePtr) !ERROR: SHAPE= argument to C_F_POINTER() may not appear when FPTR= is scalar diff --git a/flang/test/Semantics/coarrays02.f90 b/flang/test/Semantics/coarrays02.f90 index b16e0cc..e866dd8 100644 --- a/flang/test/Semantics/coarrays02.f90 +++ b/flang/test/Semantics/coarrays02.f90 @@ -16,6 +16,8 @@ program main type(event_type) event !ERROR: Variable 'lock' with EVENT_TYPE or LOCK_TYPE must be a coarray type(lock_type) lock + !ERROR: Variable 'notify' with NOTIFY_TYPE must be a coarray + type(notify_type) notify integer :: local[*] ! ok in main end @@ -120,3 +122,18 @@ subroutine s4 !ERROR: Subscripts must appear in a coindexed reference when its base is an array print *, ta(1)%a[1] end + +subroutine s5(a, notify, res) + use iso_fortran_env + type t + type(notify_type) :: a + end type + real, intent(in) :: a[*] + type(event_type), intent(in) :: notify[*] + !ERROR: An INTENT(OUT) dummy argument may not be, or contain, NOTIFY_TYPE + type(notify_type), intent(out) :: res[*] + !ERROR: Variable 'bad' with NOTIFY_TYPE potential component '%a' must be a coarray + type(t) :: bad + !ERROR: NOTIFY= specifier must have type NOTIFY_TYPE from ISO_FORTRAN_ENV + print *, a[1, NOTIFY=notify] +end diff --git a/flang/test/Semantics/collectives05.f90 b/flang/test/Semantics/collectives05.f90 index 0dea7e6..8dd996e 100644 --- a/flang/test/Semantics/collectives05.f90 +++ b/flang/test/Semantics/collectives05.f90 @@ -56,7 +56,7 @@ program main allocate(foo_t :: polymorphic) ! Test all statically verifiable semantic requirements on co_reduce arguments - ! Note: We cannot check requirements that relate to "corresponding references." + ! Note: We cannot check requirements that relate to "corresponding references." ! References can correspond only if they execute on differing images. A code that ! executes in a single image might be standard-conforming even if the same code ! executing in multiple images is not. diff --git a/flang/test/Semantics/data03.f90 b/flang/test/Semantics/data03.f90 index d9bead7..cf3ff85 100644 --- a/flang/test/Semantics/data03.f90 +++ b/flang/test/Semantics/data03.f90 @@ -44,7 +44,7 @@ module m DATA(a[i], i = 1, 5) / 5 * 1 / !C875 !ERROR: Data object variable must not be a function reference - DATA f(1) / 1 / + DATA f(1) / 1 / !C875 !ERROR: Data object must have constant subscripts DATA b(ind) / 1 / diff --git a/flang/test/Semantics/doconcurrent01.f90 b/flang/test/Semantics/doconcurrent01.f90 index ab14d97..827c533 100644 --- a/flang/test/Semantics/doconcurrent01.f90 +++ b/flang/test/Semantics/doconcurrent01.f90 @@ -1,6 +1,6 @@ ! RUN: %python %S/test_errors.py %s %flang_fc1 ! C1141 -! A reference to the procedure IEEE_SET_HALTING_MODE ! from the intrinsic +! A reference to the procedure IEEE_SET_HALTING_MODE ! from the intrinsic ! module IEEE_EXCEPTIONS, shall not ! appear within a DO CONCURRENT construct. ! ! C1137 @@ -211,6 +211,7 @@ subroutine s7() type(procTypeNotPure) :: procVarNotPure type(procTypePure) :: procVarPure integer :: ivar + real :: rvar procVarPure%pureProcComponent => pureFunc @@ -239,6 +240,14 @@ subroutine s7() ivar = generic() end do + ! This should generate an error + do concurrent (i = 1:10) +!ERROR: Impure procedure 'irand' may not be referenced in DO CONCURRENT + ivar = irand() +!ERROR: Impure procedure 'rand' may not be referenced in DO CONCURRENT + rvar = rand() + end do + contains integer function notPureFunc() notPureFunc = 2 diff --git a/flang/test/Semantics/doconcurrent05.f90 b/flang/test/Semantics/doconcurrent05.f90 index a826e06..cedc914 100644 --- a/flang/test/Semantics/doconcurrent05.f90 +++ b/flang/test/Semantics/doconcurrent05.f90 @@ -1,5 +1,5 @@ ! RUN: %python %S/test_errors.py %s %flang_fc1 -! C1167 -- An exit-stmt shall not appear within a DO CONCURRENT construct if +! C1167 -- An exit-stmt shall not appear within a DO CONCURRENT construct if ! it belongs to that construct or an outer construct. subroutine do_concurrent_test1(n) diff --git a/flang/test/Semantics/doconcurrent06.f90 b/flang/test/Semantics/doconcurrent06.f90 index 917554d..4ea49f5 100644 --- a/flang/test/Semantics/doconcurrent06.f90 +++ b/flang/test/Semantics/doconcurrent06.f90 @@ -1,5 +1,5 @@ ! RUN: %python %S/test_errors.py %s %flang_fc1 -! C1167 -- An exit-stmt shall not appear within a DO CONCURRENT construct if +! C1167 -- An exit-stmt shall not appear within a DO CONCURRENT construct if ! it belongs to that construct or an outer construct. subroutine do_concurrent_test1(n) diff --git a/flang/test/Semantics/doconcurrent08.f90 b/flang/test/Semantics/doconcurrent08.f90 index 48d653f..0dff79d 100644 --- a/flang/test/Semantics/doconcurrent08.f90 +++ b/flang/test/Semantics/doconcurrent08.f90 @@ -1,5 +1,5 @@ ! RUN: %python %S/test_errors.py %s %flang_fc1 -! C1140 -- A statement that might result in the deallocation of a polymorphic +! C1140 -- A statement that might result in the deallocation of a polymorphic ! entity shall not appear within a DO CONCURRENT construct. module m1 ! Base type with scalar components diff --git a/flang/test/Semantics/dosemantics05.f90 b/flang/test/Semantics/dosemantics05.f90 index b77e078..89eebce 100644 --- a/flang/test/Semantics/dosemantics05.f90 +++ b/flang/test/Semantics/dosemantics05.f90 @@ -29,7 +29,7 @@ subroutine s1() p_or_c => c jvar = 5 - + ! References in this DO CONCURRENT are OK since there's no DEFAULT(NONE) ! locality-spec associate (avar => ivar) @@ -46,7 +46,7 @@ subroutine s1() mvar = 3.5 end do end associate - + associate (avar => ivar) !ERROR: DO CONCURRENT step expression may not be zero do concurrent (i = 1:2:0) default(none) shared(jvar) local(kvar) @@ -95,5 +95,5 @@ subroutine s1() end select x = 5.0 ! OK, we're not in a DO CONCURRENT - + end subroutine s1 diff --git a/flang/test/Semantics/dosemantics08.f90 b/flang/test/Semantics/dosemantics08.f90 index 1dc5ba6..6518df0 100644 --- a/flang/test/Semantics/dosemantics08.f90 +++ b/flang/test/Semantics/dosemantics08.f90 @@ -1,5 +1,5 @@ ! RUN: %python %S/test_errors.py %s %flang_fc1 -! C1138 -- +! C1138 -- ! A branch (11.2) within a DO CONCURRENT construct shall not have a branch ! target that is outside the construct. diff --git a/flang/test/Semantics/dosemantics09.f90 b/flang/test/Semantics/dosemantics09.f90 index 9e6bca2..28be110 100644 --- a/flang/test/Semantics/dosemantics09.f90 +++ b/flang/test/Semantics/dosemantics09.f90 @@ -1,5 +1,5 @@ ! RUN: %python %S/test_errors.py %s %flang_fc1 -!C1129 +!C1129 !A variable that is referenced by the scalar-mask-expr of a !concurrent-header or by any concurrent-limit or concurrent-step in that !concurrent-header shall not appear in a LOCAL locality-spec in the same DO diff --git a/flang/test/Semantics/dosemantics11.f90 b/flang/test/Semantics/dosemantics11.f90 index 5ceb834..5f09abf 100644 --- a/flang/test/Semantics/dosemantics11.f90 +++ b/flang/test/Semantics/dosemantics11.f90 @@ -1,11 +1,11 @@ ! RUN: %python %S/test_errors.py %s %flang_fc1 -! C1135 A cycle-stmt shall not appear within a CHANGE TEAM, CRITICAL, or DO +! C1135 A cycle-stmt shall not appear within a CHANGE TEAM, CRITICAL, or DO ! CONCURRENT construct if it belongs to an outer construct. ! -! C1167 -- An exit-stmt shall not appear within a DO CONCURRENT construct if +! C1167 -- An exit-stmt shall not appear within a DO CONCURRENT construct if ! it belongs to that construct or an outer construct. ! -! C1168 -- An exit-stmt shall not appear within a CHANGE TEAM or CRITICAL +! C1168 -- An exit-stmt shall not appear within a CHANGE TEAM or CRITICAL ! construct if it belongs to an outer construct. subroutine s1() diff --git a/flang/test/Semantics/dosemantics12.f90 b/flang/test/Semantics/dosemantics12.f90 index 3416142..8ec8a5d 100644 --- a/flang/test/Semantics/dosemantics12.f90 +++ b/flang/test/Semantics/dosemantics12.f90 @@ -14,7 +14,7 @@ ! limitations under the License. ! !Section 11.1.7.4.3, paragraph 2 states: -! Except for the incrementation of the DO variable that occurs in step (3), +! Except for the incrementation of the DO variable that occurs in step (3), ! the DO variable shall neither be redefined nor become undefined while the ! DO construct is active. @@ -176,14 +176,14 @@ subroutine s7() integer :: iostatVar, nextrecVar, numberVar, posVar, reclVar, sizeVar - inquire(3, iostat=iostatVar, nextrec=nextrecVar, number=numberVar, & + inquire(3, iostat=iostatVar, nextrec=nextrecVar, number=numberVar, & pos=posVar, recl=reclVar, size=sizeVar) ! Redefinition via use in IOSTAT specifier (section 19.6.5, case (10)) do iostatVar = 1,20 print *, "hello" !ERROR: Cannot redefine DO variable 'iostatvar' - inquire(3, iostat=iostatVar, nextrec=nextrecVar, number=numberVar, & + inquire(3, iostat=iostatVar, nextrec=nextrecVar, number=numberVar, & pos=posVar, recl=reclVar, size=sizeVar) end do @@ -191,7 +191,7 @@ subroutine s7() do concurrent (iostatVar = 1:10) print *, "hello" !ERROR: Cannot redefine DO variable 'iostatvar' - inquire(3, iostat=iostatVar, nextrec=nextrecVar, number=numberVar, & + inquire(3, iostat=iostatVar, nextrec=nextrecVar, number=numberVar, & pos=posVar, recl=reclVar, size=sizeVar) end do @@ -199,7 +199,7 @@ subroutine s7() do nextrecVar = 1,20 print *, "hello" !ERROR: Cannot redefine DO variable 'nextrecvar' - inquire(3, iostat=iostatVar, nextrec=nextrecVar, number=numberVar, & + inquire(3, iostat=iostatVar, nextrec=nextrecVar, number=numberVar, & pos=posVar, recl=reclVar, size=sizeVar) end do @@ -207,7 +207,7 @@ subroutine s7() do concurrent (nextrecVar = 1:10) print *, "hello" !ERROR: Cannot redefine DO variable 'nextrecvar' - inquire(3, iostat=iostatVar, nextrec=nextrecVar, number=numberVar, & + inquire(3, iostat=iostatVar, nextrec=nextrecVar, number=numberVar, & pos=posVar, recl=reclVar, size=sizeVar) end do @@ -215,7 +215,7 @@ subroutine s7() do numberVar = 1,20 print *, "hello" !ERROR: Cannot redefine DO variable 'numbervar' - inquire(3, iostat=iostatVar, nextrec=nextrecVar, number=numberVar, & + inquire(3, iostat=iostatVar, nextrec=nextrecVar, number=numberVar, & pos=posVar, recl=reclVar, size=sizeVar) end do @@ -223,14 +223,14 @@ subroutine s7() do concurrent (numberVar = 1:10) print *, "hello" !ERROR: Cannot redefine DO variable 'numbervar' - inquire(3, iostat=iostatVar, nextrec=nextrecVar, number=numberVar, & + inquire(3, iostat=iostatVar, nextrec=nextrecVar, number=numberVar, & pos=posVar, recl=reclVar, size=sizeVar) end do ! Redefinition via use in RECL specifier (section 19.6.5, case (10)) do reclVar = 1,20 print *, "hello" - inquire(3, iostat=iostatVar, nextrec=nextrecVar, number=numberVar, & + inquire(3, iostat=iostatVar, nextrec=nextrecVar, number=numberVar, & !ERROR: Cannot redefine DO variable 'reclvar' pos=posVar, recl=reclVar, size=sizeVar) end do @@ -238,7 +238,7 @@ subroutine s7() ! Redefinition via use in RECL specifier (section 19.6.5, case (10)) do concurrent (reclVar = 1:10) print *, "hello" - inquire(3, iostat=iostatVar, nextrec=nextrecVar, number=numberVar, & + inquire(3, iostat=iostatVar, nextrec=nextrecVar, number=numberVar, & !ERROR: Cannot redefine DO variable 'reclvar' pos=posVar, recl=reclVar, size=sizeVar) end do @@ -246,7 +246,7 @@ subroutine s7() ! Redefinition via use in POS specifier (section 19.6.5, case (10)) do posVar = 1,20 print *, "hello" - inquire(3, iostat=iostatVar, nextrec=nextrecVar, number=numberVar, & + inquire(3, iostat=iostatVar, nextrec=nextrecVar, number=numberVar, & !ERROR: Cannot redefine DO variable 'posvar' pos=posVar, recl=reclVar, size=sizeVar) end do @@ -254,7 +254,7 @@ subroutine s7() ! Redefinition via use in POS specifier (section 19.6.5, case (10)) do concurrent (posVar = 1:10) print *, "hello" - inquire(3, iostat=iostatVar, nextrec=nextrecVar, number=numberVar, & + inquire(3, iostat=iostatVar, nextrec=nextrecVar, number=numberVar, & !ERROR: Cannot redefine DO variable 'posvar' pos=posVar, recl=reclVar, size=sizeVar) end do @@ -262,7 +262,7 @@ subroutine s7() ! Redefinition via use in SIZE specifier (section 19.6.5, case (10)) do sizeVar = 1,20 print *, "hello" - inquire(3, iostat=iostatVar, nextrec=nextrecVar, number=numberVar, & + inquire(3, iostat=iostatVar, nextrec=nextrecVar, number=numberVar, & !ERROR: Cannot redefine DO variable 'sizevar' pos=posVar, recl=reclVar, size=sizeVar) end do @@ -270,7 +270,7 @@ subroutine s7() ! Redefinition via use in SIZE specifier (section 19.6.5, case (10)) do concurrent (sizeVar = 1:10) print *, "hello" - inquire(3, iostat=iostatVar, nextrec=nextrecVar, number=numberVar, & + inquire(3, iostat=iostatVar, nextrec=nextrecVar, number=numberVar, & !ERROR: Cannot redefine DO variable 'sizevar' pos=posVar, recl=reclVar, size=sizeVar) end do diff --git a/flang/test/Semantics/equiv-kind.f90 b/flang/test/Semantics/equiv-kind.f90 new file mode 100644 index 0000000..d54fe62 --- /dev/null +++ b/flang/test/Semantics/equiv-kind.f90 @@ -0,0 +1,19 @@ +! RUN: %flang_fc1 -fdebug-unparse %s 2>&1 | FileCheck %s +module equiv_kind_m + implicit none + integer, parameter :: knd = kind(42) + integer, parameter :: dim_2 = 1_knd + integer, parameter :: n = 3_knd + integer, parameter :: i_start = 1_knd +contains +subroutine test() + integer(knd) :: a(n),b(n,n) + character(len=5) :: small_ch + character(len=20) :: large_ch + + equivalence (a(1_knd),b(1_knd,dim_2)) + !CHECK: EQUIVALENCE (a(1_4), b(1_4,1_4)) + equivalence (small_ch, large_ch(i_start:5_knd)) + !CHECK: EQUIVALENCE (small_ch, large_ch(1_4:5_4)) +end subroutine test +end module equiv_kind_m diff --git a/flang/test/Semantics/etime.f90 b/flang/test/Semantics/etime.f90 index 28735c2..fc62942 100644 --- a/flang/test/Semantics/etime.f90 +++ b/flang/test/Semantics/etime.f90 @@ -7,7 +7,7 @@ subroutine bad_kind_error(values, time) !ERROR: Actual argument for 'values=' has bad type or kind 'REAL(8)' call etime(values, time) end subroutine bad_kind_error - + subroutine bad_args_error(values) REAL(KIND=4), DIMENSION(2) :: values !ERROR: missing mandatory 'time=' argument diff --git a/flang/test/Semantics/getcwd.f90 b/flang/test/Semantics/getcwd.f90 index b6ff16e..1ad39ea 100644 --- a/flang/test/Semantics/getcwd.f90 +++ b/flang/test/Semantics/getcwd.f90 @@ -7,7 +7,7 @@ subroutine bad_kind_error(cwd, status) !ERROR: Actual argument for 'status=' has bad type or kind 'INTEGER(2)' call getcwd(cwd, status) end subroutine bad_kind_error - + subroutine bad_args_error() !ERROR: missing mandatory 'c=' argument call getcwd() diff --git a/flang/test/Semantics/getdefinition05.f90 b/flang/test/Semantics/getdefinition05.f90 index c504711..f139d9e 100644 --- a/flang/test/Semantics/getdefinition05.f90 +++ b/flang/test/Semantics/getdefinition05.f90 @@ -1,4 +1,4 @@ -! Tests -fget-symbols-sources with BLOCK that contains same variable name as +! Tests -fget-symbols-sources with BLOCK that contains same variable name as ! another in an outer scope. program main integer :: x diff --git a/flang/test/Semantics/indirect01.f90 b/flang/test/Semantics/indirect01.f90 index 5985066..81fcfbc 100644 --- a/flang/test/Semantics/indirect01.f90 +++ b/flang/test/Semantics/indirect01.f90 @@ -1,6 +1,6 @@ ! This test checks the lowering of OpenMP Indirect Clause when used with the Declare Target directive -! RUN: not flang -fopenmp -fopenmp-version=52 %s 2>&1 | FileCheck %s +! RUN: not %flang -fopenmp -fopenmp-version=52 %s 2>&1 | FileCheck %s module functions implicit none diff --git a/flang/test/Semantics/indirect02.f90 b/flang/test/Semantics/indirect02.f90 index 273f885..cfae406 100644 --- a/flang/test/Semantics/indirect02.f90 +++ b/flang/test/Semantics/indirect02.f90 @@ -1,7 +1,7 @@ ! This test checks the lowering of OpenMP Indirect Clause when used with the Declare Target directive -! RUN: not flang -fopenmp -fopenmp-version=50 %s 2>&1 | FileCheck %s --check-prefix="CHECK-50" -! RUN: not flang -fopenmp -fopenmp-version=52 %s 2>&1 | FileCheck %s --check-prefix="CHECK-52" +! RUN: not %flang -fopenmp -fopenmp-version=50 %s 2>&1 | FileCheck %s --check-prefix="CHECK-50" +! RUN: not %flang -fopenmp -fopenmp-version=52 %s 2>&1 | FileCheck %s --check-prefix="CHECK-52" module functions implicit none diff --git a/flang/test/Semantics/io11.f90 b/flang/test/Semantics/io11.f90 index 6bb7a71..8eced0c 100644 --- a/flang/test/Semantics/io11.f90 +++ b/flang/test/Semantics/io11.f90 @@ -521,7 +521,7 @@ contains end module module m21 - ! Test read and write defined input/output procedures specified as a + ! Test read and write defined input/output procedures specified as a ! type-bound procedure and as a generic for the same derived type with a ! KIND type parameter where they both have the same value type t(typeParam) @@ -647,7 +647,7 @@ contains end module module m24 - ! Test read and write defined input/output procedures specified as a + ! Test read and write defined input/output procedures specified as a ! type-bound procedure and as a generic for the same derived type with a ! LEN type parameter where they are both assumed type t(typeParam) diff --git a/flang/test/Semantics/kinds02.f90 b/flang/test/Semantics/kinds02.f90 index 02b1e6c..1adf582 100644 --- a/flang/test/Semantics/kinds02.f90 +++ b/flang/test/Semantics/kinds02.f90 @@ -1,17 +1,17 @@ ! REQUIRES: x86_64-registered-target ! RUN: %python %S/test_errors.py %s %flang_fc1 -! C712 The value of scalar-int-constant-expr shall be nonnegative and +! C712 The value of scalar-int-constant-expr shall be nonnegative and ! shall specify a representation method that exists on the processor. ! C714 The value of kind-param shall be nonnegative. -! C715 The value of kind-param shall specify a representation method that +! C715 The value of kind-param shall specify a representation method that ! exists on the processor. -! C719 The value of scalar-int-constant-expr shall be nonnegative and shall +! C719 The value of scalar-int-constant-expr shall be nonnegative and shall ! specify a representation method that exists on the processor. -! C725 The optional comma in a length-selector is permitted only if no +! C725 The optional comma in a length-selector is permitted only if no ! double-colon separator appears in the typedeclaration- stmt. -! C727 The value of kind-param shall specify a representation method that +! C727 The value of kind-param shall specify a representation method that ! exists on the processor. -! C728 The value of kind-param shall specify a representation method that +! C728 The value of kind-param shall specify a representation method that ! exists on the processor. ! !ERROR: INTEGER(KIND=0) is not a supported type diff --git a/flang/test/Semantics/notifywait03.f90 b/flang/test/Semantics/notifywait03.f90 index 0fc56f6..a336a7a 100644 --- a/flang/test/Semantics/notifywait03.f90 +++ b/flang/test/Semantics/notifywait03.f90 @@ -10,6 +10,7 @@ program test_notify_wait implicit none ! notify_type variables must be coarrays + !ERROR: Variable 'non_coarray' with NOTIFY_TYPE must be a coarray type(notify_type) :: non_coarray type(notify_type) :: notify_var[*], notify_array(2)[*] diff --git a/flang/test/Semantics/structconst12.f90 b/flang/test/Semantics/structconst12.f90 new file mode 100644 index 0000000..c8715f8 --- /dev/null +++ b/flang/test/Semantics/structconst12.f90 @@ -0,0 +1,13 @@ +!RUN: %flang_fc1 -fdebug-unparse %s 2>&1 | FileCheck %s +type t1(k1a,k1b) + integer, kind :: k1a, k1b + integer(k1a) :: j = -666 + integer(k1b) :: c1 = k1a +end type +type t2(k2a,k2b) + integer, kind:: k2a, k2b + type(t1(k2a+1,k2b*2)) :: c2 = t1(k2a+1,k2b*2)(j=777) +end type +type (t2(3,4)), parameter :: x = t2(3,4)() +!CHECK: TYPE(t2(3_4,4_4)), PARAMETER :: x = t2(k2a=3_4,k2b=4_4)(c2=t1(k1a=4_4,k1b=8_4)(j=777_4,c1=4_8)) +END diff --git a/flang/test/Semantics/val-tkr.f90 b/flang/test/Semantics/val-tkr.f90 new file mode 100644 index 0000000..bed41f3 --- /dev/null +++ b/flang/test/Semantics/val-tkr.f90 @@ -0,0 +1,22 @@ +! RUN: %python %S/test_errors.py %s %flang_fc1 +implicit none +interface + subroutine s(b) + !dir$ ignore_tkr(tr) b + real, value :: b + end + subroutine s1(b) + !dir$ ignore_tkr(r) b + integer, value :: b + end +end interface +integer :: a(5), a1 +! forbid array to scalar with VALUE and ignore_tkr(r) +!ERROR: Array actual argument may not be associated with IGNORE_TKR(R) scalar dummy argument 'b=' with VALUE attribute +call s(a) +!ERROR: Array actual argument may not be associated with IGNORE_TKR(R) scalar dummy argument 'b=' with VALUE attribute +call s1(a) +! allow scalar to scalar with VALUE +call s(a1) +call s1(a(1)) +end diff --git a/flang/test/Transforms/DoConcurrent/basic_host.f90 b/flang/test/Transforms/DoConcurrent/basic_host.f90 index 6f24b34..b4eb158 100644 --- a/flang/test/Transforms/DoConcurrent/basic_host.f90 +++ b/flang/test/Transforms/DoConcurrent/basic_host.f90 @@ -4,7 +4,7 @@ ! RUN: | FileCheck %s ! RUN: bbc -emit-hlfir -fopenmp -fdo-concurrent-to-openmp=host %s -o - \ ! RUN: | FileCheck %s - + ! CHECK-LABEL: DO_CONCURRENT_BASIC program do_concurrent_basic ! CHECK: %[[ARR:.*]]:2 = hlfir.declare %{{.*}}(%{{.*}}) {uniq_name = "_QFEa"} : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>) diff --git a/flang/test/Transforms/DoConcurrent/map_shape_info.f90 b/flang/test/Transforms/DoConcurrent/map_shape_info.f90 index 40f66c1..95bfc23 100644 --- a/flang/test/Transforms/DoConcurrent/map_shape_info.f90 +++ b/flang/test/Transforms/DoConcurrent/map_shape_info.f90 @@ -28,7 +28,7 @@ end program do_concurrent_shape ! CHECK: omp.map.info ! CHECK: omp.map.info -! CHECK: %[[DIM0_EXT_MAP:.*]] = omp.map.info +! CHECK: %[[DIM0_EXT_MAP:.*]] = omp.map.info ! CHECK-SAME: var_ptr(%[[DIM0_EXT]] : !fir.ref<index>, index) ! CHECK-SAME: map_clauses(implicit) ! CHECK-SAME: capture(ByCopy) -> !fir.ref<index> {name = "_QFEa.extent.dim0"} @@ -77,9 +77,9 @@ end subroutine do_concurrent_shape_shift ! CHECK: omp.map.info ! CHECK: omp.map.info -! CHECK: %[[DIM0_STRT_MAP:.*]] = omp.map.info +! CHECK: %[[DIM0_STRT_MAP:.*]] = omp.map.info ! CHECK-SAME: var_ptr(%[[DIM0_STRT]] : !fir.ref<index>, index) -! CHECK-SAME: map_clauses(implicit) +! CHECK-SAME: map_clauses(implicit) ! CHECK-SAME: capture(ByCopy) -> !fir.ref<index> {name = "_QF{{.*}}Ea.start_idx.dim0"} ! CHECK: %[[DIM0_EXT_MAP:.*]] = omp.map.info diff --git a/flang/test/Transforms/DoConcurrent/use_loop_bounds_in_body.f90 b/flang/test/Transforms/DoConcurrent/use_loop_bounds_in_body.f90 index b467747..07a3b5b 100644 --- a/flang/test/Transforms/DoConcurrent/use_loop_bounds_in_body.f90 +++ b/flang/test/Transforms/DoConcurrent/use_loop_bounds_in_body.f90 @@ -14,7 +14,7 @@ subroutine foo(a, n) do concurrent (i=1:n) a(i) = n end do -end subroutine +end subroutine ! CHECK-LABEL: func.func @_QPfoo ! CHECK: omp.target diff --git a/flang/test/Transforms/OpenACC/acc-implicit-copy-reduction.fir b/flang/test/Transforms/OpenACC/acc-implicit-copy-reduction.fir new file mode 100644 index 0000000..5cccb07 --- /dev/null +++ b/flang/test/Transforms/OpenACC/acc-implicit-copy-reduction.fir @@ -0,0 +1,134 @@ +// RUN: fir-opt %s --pass-pipeline="builtin.module(acc-initialize-fir-analyses,acc-implicit-data{enable-implicit-reduction-copy=true})" -split-input-file | FileCheck %s --check-prefix=COPY +// RUN: fir-opt %s --pass-pipeline="builtin.module(acc-initialize-fir-analyses,acc-implicit-data{enable-implicit-reduction-copy=false})" -split-input-file | FileCheck %s --check-prefix=FIRSTPRIVATE + +// Test case: integer reduction in parallel loop +// This corresponds to Fortran code: +// integer :: r, i +// r = 0 +// !$acc parallel +// !$acc loop gang reduction(+:r) +// do i = 1, N +// r = r + 1 +// enddo +// !$acc end parallel + +acc.reduction.recipe @reduction_add_ref_i32 : !fir.ref<i32> reduction_operator <add> init { +^bb0(%arg0: !fir.ref<i32>): + %c0_i32 = arith.constant 0 : i32 + %0 = fir.alloca i32 + %1 = fir.declare %0 {uniq_name = "acc.reduction.init"} : (!fir.ref<i32>) -> !fir.ref<i32> + fir.store %c0_i32 to %1 : !fir.ref<i32> + acc.yield %1 : !fir.ref<i32> +} combiner { +^bb0(%arg0: !fir.ref<i32>, %arg1: !fir.ref<i32>): + %0 = fir.load %arg0 : !fir.ref<i32> + %1 = fir.load %arg1 : !fir.ref<i32> + %2 = arith.addi %0, %1 : i32 + fir.store %2 to %arg0 : !fir.ref<i32> + acc.yield %arg0 : !fir.ref<i32> +} + +func.func @test_reduction_implicit_copy() { + %c1_i32 = arith.constant 1 : i32 + %cN = arith.constant 100 : i32 + %r = fir.alloca i32 {bindc_name = "r", uniq_name = "_QFEr"} + %i = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFEi"} + %r_decl = fir.declare %r {uniq_name = "_QFEr"} : (!fir.ref<i32>) -> !fir.ref<i32> + %i_decl = fir.declare %i {uniq_name = "_QFEi"} : (!fir.ref<i32>) -> !fir.ref<i32> + %c0_i32 = arith.constant 0 : i32 + fir.store %c0_i32 to %r_decl : !fir.ref<i32> + + acc.parallel { + %red_var = acc.reduction varPtr(%r_decl : !fir.ref<i32>) recipe(@reduction_add_ref_i32) -> !fir.ref<i32> {name = "r"} + acc.loop reduction(%red_var : !fir.ref<i32>) control(%iv : i32) = (%c1_i32 : i32) to (%cN : i32) step (%c1_i32 : i32) { + fir.store %iv to %i_decl : !fir.ref<i32> + %cur_r = fir.load %red_var : !fir.ref<i32> + %new_r = arith.addi %cur_r, %c1_i32 : i32 + fir.store %new_r to %red_var : !fir.ref<i32> + acc.yield + } attributes {inclusiveUpperbound = array<i1: true>, independent = [#acc.device_type<none>]} + acc.yield + } + return +} + +// When enable-implicit-reduction-copy=true: expect copyin/copyout for reduction variable +// COPY: %[[COPYIN:.*]] = acc.copyin varPtr({{.*}} : !fir.ref<i32>) -> !fir.ref<i32> {dataClause = #acc<data_clause acc_reduction>, implicit = true, name = "r"} +// COPY: acc.copyout accPtr(%[[COPYIN]] : !fir.ref<i32>) to varPtr({{.*}} : !fir.ref<i32>) {dataClause = #acc<data_clause acc_copy>, implicit = true, name = "r"} + +// When enable-implicit-reduction-copy=false: expect firstprivate for reduction variable +// FIRSTPRIVATE: acc.firstprivate varPtr({{.*}} : !fir.ref<i32>) recipe({{.*}}) -> !fir.ref<i32> {implicit = true, name = "r"} +// FIRSTPRIVATE-NOT: acc.copyin +// FIRSTPRIVATE-NOT: acc.copyout + +// ----- + +// Test case: reduction variable used both in loop and outside (should be firstprivate) +// This corresponds to Fortran code: +// integer :: r = 0, i, out +// !$acc parallel num_gangs(1) +// !$acc loop reduction(+:r) copyout(out) +// do i = 1, N +// r = r + 1 +// enddo +// out = r +// !$acc end parallel + +acc.reduction.recipe @reduction_add_ref_i32 : !fir.ref<i32> reduction_operator <add> init { +^bb0(%arg0: !fir.ref<i32>): + %c0_i32 = arith.constant 0 : i32 + %0 = fir.alloca i32 + %1 = fir.declare %0 {uniq_name = "acc.reduction.init"} : (!fir.ref<i32>) -> !fir.ref<i32> + fir.store %c0_i32 to %1 : !fir.ref<i32> + acc.yield %1 : !fir.ref<i32> +} combiner { +^bb0(%arg0: !fir.ref<i32>, %arg1: !fir.ref<i32>): + %0 = fir.load %arg0 : !fir.ref<i32> + %1 = fir.load %arg1 : !fir.ref<i32> + %2 = arith.addi %0, %1 : i32 + fir.store %2 to %arg0 : !fir.ref<i32> + acc.yield %arg0 : !fir.ref<i32> +} + +func.func @test_reduction_with_usage_outside_loop() { + %c1_i32 = arith.constant 1 : i32 + %cN = arith.constant 100 : i32 + %c0_i32 = arith.constant 0 : i32 + + %r = fir.alloca i32 {bindc_name = "r", uniq_name = "_QFEr"} + %i = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFEi"} + %out = fir.alloca i32 {bindc_name = "out", uniq_name = "_QFEout"} + + %r_decl = fir.declare %r {uniq_name = "_QFEr"} : (!fir.ref<i32>) -> !fir.ref<i32> + %i_decl = fir.declare %i {uniq_name = "_QFEi"} : (!fir.ref<i32>) -> !fir.ref<i32> + %out_decl = fir.declare %out {uniq_name = "_QFEout"} : (!fir.ref<i32>) -> !fir.ref<i32> + fir.store %c0_i32 to %r_decl : !fir.ref<i32> + + %out_copyout = acc.create varPtr(%out_decl : !fir.ref<i32>) -> !fir.ref<i32> {dataClause = #acc<data_clause acc_copyout>, name = "out"} + acc.parallel dataOperands(%out_copyout : !fir.ref<i32>) { + %red_var = acc.reduction varPtr(%r_decl : !fir.ref<i32>) recipe(@reduction_add_ref_i32) -> !fir.ref<i32> {name = "r"} + acc.loop reduction(%red_var : !fir.ref<i32>) control(%iv : i32) = (%c1_i32 : i32) to (%cN : i32) step (%c1_i32 : i32) { + fir.store %iv to %i_decl : !fir.ref<i32> + %cur_r = fir.load %red_var : !fir.ref<i32> + %new_r = arith.addi %cur_r, %c1_i32 : i32 + fir.store %new_r to %red_var : !fir.ref<i32> + acc.yield + } attributes {inclusiveUpperbound = array<i1: true>, independent = [#acc.device_type<none>]} + // out = r (usage of r outside the loop) + %final_r = fir.load %r_decl : !fir.ref<i32> + fir.store %final_r to %out_copyout : !fir.ref<i32> + acc.yield + } + acc.copyout accPtr(%out_copyout : !fir.ref<i32>) to varPtr(%out_decl : !fir.ref<i32>) {dataClause = #acc<data_clause acc_copyout>, name = "out"} + return +} + +// In this case, r should be firstprivate regardless of the flag setting because it's used outside the reduction context +// COPY-LABEL: func.func @test_reduction_with_usage_outside_loop +// COPY: acc.firstprivate varPtr({{.*}} : !fir.ref<i32>) recipe({{.*}}) -> !fir.ref<i32> {implicit = true, name = "r"} +// COPY-NOT: acc.copyin varPtr({{.*}} : !fir.ref<i32>) -> !fir.ref<i32> {{.*}} name = "r" + +// FIRSTPRIVATE-LABEL: func.func @test_reduction_with_usage_outside_loop +// FIRSTPRIVATE: acc.firstprivate varPtr({{.*}} : !fir.ref<i32>) recipe({{.*}}) -> !fir.ref<i32> {implicit = true, name = "r"} +// FIRSTPRIVATE-NOT: acc.copyin varPtr({{.*}} : !fir.ref<i32>) -> !fir.ref<i32> {{.*}} name = "r" + diff --git a/flang/test/Transforms/OpenACC/acc-implicit-data-derived-type-member.F90 b/flang/test/Transforms/OpenACC/acc-implicit-data-derived-type-member.F90 new file mode 100644 index 0000000..71e7d79 --- /dev/null +++ b/flang/test/Transforms/OpenACC/acc-implicit-data-derived-type-member.F90 @@ -0,0 +1,38 @@ +!RUN: rm -rf %t && mkdir %t && cd %t && \ +!RUN: bbc %s -fopenacc -emit-hlfir -o - \ +!RUN: | fir-opt --pass-pipeline="builtin.module(acc-initialize-fir-analyses,acc-implicit-data)" \ +!RUN: | FileCheck %s + +! This test exercises whether the ACCImplicitData pass inserts its new +! data operations in appropriate position so that parents are copied in before +! their children. + +module types + type derivc8r4 + complex(8) :: member0 + real(4) :: member1 + end type derivc8r4 +end module +program test + use types + implicit none + type (derivc8r4) :: d2 + type (derivc8r4) :: d4 + integer(4) :: i0 + d2%member0 = 123 + !$acc serial copyin(d2%member0) copyout(d4%member0) + do i0 = 1, 1 + d4%member0 = d2%member0 + end do + !$acc end serial +end program + +!CHECK: acc.copyin {{.*}} {dataClause = #acc<data_clause acc_copy>, implicit = true, name = "d2"} +!CHECK: acc.copyin {{.*}} {name = "d2%member0"} +!CHECK: acc.copyin {{.*}} {dataClause = #acc<data_clause acc_copy>, implicit = true, name = "d4"} +!CHECK: acc.create {{.*}} {dataClause = #acc<data_clause acc_copyout>, name = "d4%member0"} +!CHECK: acc.delete {{.*}} {dataClause = #acc<data_clause acc_copyin>, name = "d2%member0"} +!CHECK: acc.copyout {{.*}} {dataClause = #acc<data_clause acc_copy>, implicit = true, name = "d2"} +!CHECK: acc.copyout {{.*}} {name = "d4%member0"} +!CHECK: acc.copyout {{.*}} {dataClause = #acc<data_clause acc_copy>, implicit = true, name = "d4"} + diff --git a/flang/test/Transforms/OpenACC/acc-implicit-data-fortran.F90 b/flang/test/Transforms/OpenACC/acc-implicit-data-fortran.F90 new file mode 100644 index 0000000..2be07d7 --- /dev/null +++ b/flang/test/Transforms/OpenACC/acc-implicit-data-fortran.F90 @@ -0,0 +1,79 @@ +!RUN: rm -rf %t && mkdir %t && cd %t && \ +!RUN: bbc %s -fopenacc -emit-hlfir -o - \ +!RUN: | fir-opt --pass-pipeline="builtin.module(acc-initialize-fir-analyses,acc-implicit-data)" \ +!RUN: | FileCheck %s --check-prefix=CHECKHLFIR + +!RUN: rm -rf %t && mkdir %t && cd %t && \ +!RUN: bbc %s -fopenacc -emit-hlfir -o - \ +!RUN: | fir-opt --pass-pipeline="builtin.module(cse,acc-initialize-fir-analyses,acc-implicit-data)" \ +!RUN: | FileCheck %s --check-prefix=CHECKCSE + +!RUN: rm -rf %t && mkdir %t && cd %t && \ +!RUN: bbc %s -fopenacc -emit-fir -o - \ +!RUN: | fir-opt --pass-pipeline="builtin.module(cse,acc-initialize-fir-analyses,acc-implicit-data)" \ +!RUN: | FileCheck %s --check-prefix=CHECKCSE + +! This test uses bbc to generate both HLFIR and FIR for this test. The intent is +! that it is exercising the acc implicit data pipeline and ensures that +! correct clauses are generated. It also runs CSE which eliminates redundant +! interior pointer computations (and thus different live-ins are found). + +program main + type aggr + real :: field + end type + type nested + type(aggr) :: outer + end type + type(aggr) :: aggrvar + type(nested) :: nestaggrvar + real :: scalarvar + real :: arrayvar(10) + complex :: scalarcomp + + aggrvar%field = 1 + scalarvar = aggrvar%field + nestaggrvar%outer%field = scalarvar + scalarcomp = scalarvar + arrayvar = real(scalarcomp) + arrayvar(2) = aggrvar%field + + !$acc kernels + arrayvar = aggrvar%field + scalarvar + nestaggrvar%outer%field + real(scalarcomp) + arrayvar(2) + !$acc end kernels + + !$acc parallel + arrayvar = aggrvar%field + scalarvar + nestaggrvar%outer%field + real(scalarcomp) + arrayvar(2) + !$acc end parallel +end program + +!CHECKHLFIR-LABEL: @_QQmain +!CHECKHLFIR-DAG: acc.copyin varPtr(%{{.*}} : !fir.ref<!fir.type<_QFTaggr{field:f32}>>) -> !fir.ref<!fir.type<_QFTaggr{field:f32}>> {dataClause = #acc<data_clause acc_copy>, implicit = true, name = "aggrvar"} +!CHECKHLFIR-DAG: acc.copyin varPtr(%{{.*}} : !fir.ref<!fir.array<10xf32>>) -> !fir.ref<!fir.array<10xf32>> {dataClause = #acc<data_clause acc_copy>, implicit = true, name = "arrayvar"} +!CHECKHLFIR-DAG: acc.copyin varPtr(%{{.*}} : !fir.ref<!fir.type<_QFTnested{outer:!fir.type<_QFTaggr{field:f32}>}>>) -> !fir.ref<!fir.type<_QFTnested{outer:!fir.type<_QFTaggr{field:f32}>}>> {dataClause = #acc<data_clause acc_copy>, implicit = true, name = "nestaggrvar"} +!CHECKHLFIR-DAG: acc.copyin varPtr(%{{.*}} : !fir.ref<complex<f32>>) -> !fir.ref<complex<f32>> {dataClause = #acc<data_clause acc_copy>, implicit = true, name = "scalarcomp"} +!CHECKHLFIR-DAG: acc.copyin varPtr(%{{.*}} : !fir.ref<f32>) -> !fir.ref<f32> {dataClause = #acc<data_clause acc_copy>, implicit = true, name = "scalarvar"} +!CHECKHLFIR: acc.kernels +!CHECKHLFIR-DAG: acc.copyin varPtr(%{{.*}} : !fir.ref<!fir.type<_QFTaggr{field:f32}>>) -> !fir.ref<!fir.type<_QFTaggr{field:f32}>> {dataClause = #acc<data_clause acc_copy>, implicit = true, name = "aggrvar"} +!CHECKHLFIR-DAG: acc.copyin varPtr(%{{.*}} : !fir.ref<!fir.array<10xf32>>) -> !fir.ref<!fir.array<10xf32>> {dataClause = #acc<data_clause acc_copy>, implicit = true, name = "arrayvar"} +!CHECKHLFIR-DAG: acc.copyin varPtr(%{{.*}} : !fir.ref<!fir.type<_QFTnested{outer:!fir.type<_QFTaggr{field:f32}>}>>) -> !fir.ref<!fir.type<_QFTnested{outer:!fir.type<_QFTaggr{field:f32}>}>> {dataClause = #acc<data_clause acc_copy>, implicit = true, name = "nestaggrvar"} +!CHECKHLFIR-DAG: acc.firstprivate varPtr(%{{.*}} : !fir.ref<complex<f32>>) recipe({{.*}}) -> !fir.ref<complex<f32>> {implicit = true, name = "scalarcomp"} +!CHECKHLFIR-DAG: acc.firstprivate varPtr(%{{.*}} : !fir.ref<f32>) recipe({{.*}}) -> !fir.ref<f32> {implicit = true, name = "scalarvar"} +!CHECKHLFIR: acc.parallel + +!CHECKCSE-LABEL: @_QQmain +!CHECKCSE-DAG: acc.copyin varPtr(%{{.*}} : !fir.ref<!fir.array<10xf32>>) -> !fir.ref<!fir.array<10xf32>> {dataClause = #acc<data_clause acc_copy>, implicit = true, name = "arrayvar"} +!CHECKCSE-DAG: acc.copyin varPtr(%{{.*}} : !fir.ref<complex<f32>>) -> !fir.ref<complex<f32>> {dataClause = #acc<data_clause acc_copy>, implicit = true, name = "scalarcomp"} +!CHECKCSE-DAG: acc.copyin varPtr(%{{.*}} : !fir.ref<f32>) -> !fir.ref<f32> {dataClause = #acc<data_clause acc_copy>, implicit = true, name = "scalarvar"} +!CHECKCSE-DAG: acc.copyin varPtr(%{{.*}} : !fir.ref<f32>) -> !fir.ref<f32> {dataClause = #acc<data_clause acc_copy>, implicit = true, name = "aggrvar%field"} +!CHECKCSE-DAG: acc.copyin varPtr(%{{.*}} : !fir.ref<f32>) -> !fir.ref<f32> {dataClause = #acc<data_clause acc_copy>, implicit = true, name = "nestaggrvar%outer%field"} +!CHECKCSE-DAG: acc.copyin varPtr(%{{.*}} : !fir.ref<f32>) -> !fir.ref<f32> {dataClause = #acc<data_clause acc_copy>, implicit = true, name = "arrayvar(2)"} +!CHECKCSE: acc.kernels +!CHECKCSE-DAG: acc.copyin varPtr(%{{.*}} : !fir.ref<!fir.array<10xf32>>) -> !fir.ref<!fir.array<10xf32>> {dataClause = #acc<data_clause acc_copy>, implicit = true, name = "arrayvar"} +!CHECKCSE-DAG: acc.firstprivate varPtr(%{{.*}} : !fir.ref<complex<f32>>) recipe({{.*}}) -> !fir.ref<complex<f32>> {implicit = true, name = "scalarcomp"} +!CHECKCSE-DAG: acc.firstprivate varPtr(%{{.*}} : !fir.ref<f32>) recipe({{.*}}) -> !fir.ref<f32> {implicit = true, name = "scalarvar"} +!CHECKCSE-DAG: acc.copyin varPtr(%{{.*}} : !fir.ref<f32>) -> !fir.ref<f32> {dataClause = #acc<data_clause acc_copy>, implicit = true, name = "aggrvar%field"} +!CHECKCSE-DAG: acc.copyin varPtr(%{{.*}} : !fir.ref<f32>) -> !fir.ref<f32> {dataClause = #acc<data_clause acc_copy>, implicit = true, name = "nestaggrvar%outer%field"} +!CHECKCSE-DAG: acc.copyin varPtr(%{{.*}} : !fir.ref<f32>) -> !fir.ref<f32> {dataClause = #acc<data_clause acc_copy>, implicit = true, name = "arrayvar(2)"} +!CHECKCSE: acc.parallel + diff --git a/flang/test/Transforms/OpenACC/acc-implicit-data.fir b/flang/test/Transforms/OpenACC/acc-implicit-data.fir new file mode 100644 index 0000000..058390a --- /dev/null +++ b/flang/test/Transforms/OpenACC/acc-implicit-data.fir @@ -0,0 +1,358 @@ +// RUN: fir-opt %s --pass-pipeline="builtin.module(acc-initialize-fir-analyses,acc-implicit-data)" -split-input-file | FileCheck %s + +// ----- + +func.func @test_fir_scalar_in_serial() { + %livein = fir.alloca i64 {bindc_name = "scalarvar"} + acc.serial { + %load = fir.load %livein : !fir.ref<i64> + acc.yield + } + return +} + +// CHECK: acc.firstprivate varPtr({{.*}} : !fir.ref<i64>) recipe({{.*}}) -> !fir.ref<i64> {implicit = true, name = "scalarvar"} + +// ----- + +func.func @test_fir_scalar_in_parallel() { + %livein = fir.alloca f32 {bindc_name = "scalarvar"} + acc.parallel { + %load = fir.load %livein : !fir.ref<f32> + acc.yield + } + return +} + +// CHECK: acc.firstprivate varPtr({{.*}} : !fir.ref<f32>) recipe({{.*}}) -> !fir.ref<f32> {implicit = true, name = "scalarvar"} + +// ----- + +func.func @test_fir_scalar_in_kernels() { + %livein = fir.alloca f64 {bindc_name = "scalarvar"} + acc.kernels { + %load = fir.load %livein : !fir.ref<f64> + acc.terminator + } + return +} + +// CHECK: %[[COPYIN:.*]] = acc.copyin varPtr({{.*}} : !fir.ref<f64>) -> !fir.ref<f64> {dataClause = #acc<data_clause acc_copy>, implicit = true, name = "scalarvar"} +// CHECK: acc.copyout accPtr(%[[COPYIN]] : !fir.ref<f64>) to varPtr({{.*}} : !fir.ref<f64>) {dataClause = #acc<data_clause acc_copy>, implicit = true, name = "scalarvar"} + +// ----- + +func.func @test_fir_scalar_in_parallel_defaultnone() { + %livein = fir.alloca f32 {bindc_name = "scalarvar"} + acc.parallel { + %load = fir.load %livein : !fir.ref<f32> + acc.yield + } attributes {defaultAttr = #acc<defaultvalue none>} + return +} + +// CHECK-NOT: acc.firstprivate + +// ----- + +func.func @test_fir_scalar_in_kernels_defaultnone() { + %livein = fir.alloca f64 {bindc_name = "scalarvar"} + acc.kernels { + %load = fir.load %livein : !fir.ref<f64> + acc.terminator + } attributes {defaultAttr = #acc<defaultvalue none>} + return +} + +// CHECK-NOT: acc.copyin + +// ----- + +func.func @test_fir_derivedtype_in_parallel() { + %livein = fir.alloca !fir.type<_QFTaggr{field:f32}> {bindc_name = "aggrvar"} + acc.parallel { + %load = fir.load %livein : !fir.ref<!fir.type<_QFTaggr{field:f32}>> + acc.yield + } + return +} + +// CHECK: %[[COPYIN:.*]] = acc.copyin varPtr({{.*}} : !fir.ref<!fir.type<_QFTaggr{field:f32}>>) -> !fir.ref<!fir.type<_QFTaggr{field:f32}>> {dataClause = #acc<data_clause acc_copy>, implicit = true, name = "aggrvar"} +// CHECK: acc.copyout accPtr(%[[COPYIN]] : !fir.ref<!fir.type<_QFTaggr{field:f32}>>) to varPtr({{.*}} : !fir.ref<!fir.type<_QFTaggr{field:f32}>>) {dataClause = #acc<data_clause acc_copy>, implicit = true, name = "aggrvar"} + +// ----- + +func.func @test_fir_derivedtype_in_kernels() { + %livein = fir.alloca !fir.type<_QFTaggr{field:f32}> {bindc_name = "aggrvar"} + acc.kernels { + %load = fir.load %livein : !fir.ref<!fir.type<_QFTaggr{field:f32}>> + acc.terminator + } + return +} + +// CHECK: %[[COPYIN:.*]] = acc.copyin varPtr({{.*}} : !fir.ref<!fir.type<_QFTaggr{field:f32}>>) -> !fir.ref<!fir.type<_QFTaggr{field:f32}>> {dataClause = #acc<data_clause acc_copy>, implicit = true, name = "aggrvar"} +// CHECK: acc.copyout accPtr(%[[COPYIN]] : !fir.ref<!fir.type<_QFTaggr{field:f32}>>) to varPtr({{.*}} : !fir.ref<!fir.type<_QFTaggr{field:f32}>>) {dataClause = #acc<data_clause acc_copy>, implicit = true, name = "aggrvar"} + +// ----- + +func.func @test_fir_array_in_parallel() { + %livein = fir.alloca !fir.array<10xf32> {bindc_name = "arrayvar"} + acc.parallel { + %load = fir.load %livein : !fir.ref<!fir.array<10xf32>> + acc.yield + } + return +} + +// CHECK: %[[COPYIN:.*]] = acc.copyin varPtr({{.*}} : !fir.ref<!fir.array<10xf32>>) -> !fir.ref<!fir.array<10xf32>> {dataClause = #acc<data_clause acc_copy>, implicit = true, name = "arrayvar"} +// CHECK: acc.copyout accPtr(%[[COPYIN]] : !fir.ref<!fir.array<10xf32>>) to varPtr({{.*}} : !fir.ref<!fir.array<10xf32>>) {dataClause = #acc<data_clause acc_copy>, implicit = true, name = "arrayvar"} + +// ----- + +func.func @test_fir_array_in_kernels() { + %livein = fir.alloca !fir.array<10xf32> {bindc_name = "arrayvar"} + acc.kernels { + %load = fir.load %livein : !fir.ref<!fir.array<10xf32>> + acc.terminator + } + return +} + +// CHECK: %[[COPYIN:.*]] = acc.copyin varPtr({{.*}} : !fir.ref<!fir.array<10xf32>>) -> !fir.ref<!fir.array<10xf32>> {dataClause = #acc<data_clause acc_copy>, implicit = true, name = "arrayvar"} +// CHECK: acc.copyout accPtr(%[[COPYIN]] : !fir.ref<!fir.array<10xf32>>) to varPtr({{.*}} : !fir.ref<!fir.array<10xf32>>) {dataClause = #acc<data_clause acc_copy>, implicit = true, name = "arrayvar"} + +// ----- + +func.func @test_fir_derivedtype_in_parallel_defaultpresent() { + %livein = fir.alloca !fir.type<_QFTaggr{field:f32}> {bindc_name = "aggrvar"} + acc.parallel { + %load = fir.load %livein : !fir.ref<!fir.type<_QFTaggr{field:f32}>> + acc.yield + } attributes {defaultAttr = #acc<defaultvalue present>} + return +} + +// CHECK: %[[PRESENT:.*]] = acc.present varPtr({{.*}} : !fir.ref<!fir.type<_QFTaggr{field:f32}>>) -> !fir.ref<!fir.type<_QFTaggr{field:f32}>> {acc.from_default, implicit = true, name = "aggrvar"} +// CHECK: acc.delete accPtr(%[[PRESENT]] : !fir.ref<!fir.type<_QFTaggr{field:f32}>>) {dataClause = #acc<data_clause acc_present>, implicit = true, name = "aggrvar"} + +// ----- + +func.func @test_fir_derivedtype_in_kernels_defaultpresent() { + %livein = fir.alloca !fir.type<_QFTaggr{field:f32}> {bindc_name = "aggrvar"} + acc.kernels { + %load = fir.load %livein : !fir.ref<!fir.type<_QFTaggr{field:f32}>> + acc.terminator + } attributes {defaultAttr = #acc<defaultvalue present>} + return +} + +// CHECK: %[[PRESENT:.*]] = acc.present varPtr({{.*}} : !fir.ref<!fir.type<_QFTaggr{field:f32}>>) -> !fir.ref<!fir.type<_QFTaggr{field:f32}>> {acc.from_default, implicit = true, name = "aggrvar"} +// CHECK: acc.delete accPtr(%[[PRESENT]] : !fir.ref<!fir.type<_QFTaggr{field:f32}>>) {dataClause = #acc<data_clause acc_present>, implicit = true, name = "aggrvar"} + +// ----- + +func.func @test_fir_array_in_parallel_defaultpresent() { + %livein = fir.alloca !fir.array<10xf32> {bindc_name = "arrayvar"} + acc.parallel { + %load = fir.load %livein : !fir.ref<!fir.array<10xf32>> + acc.yield + } attributes {defaultAttr = #acc<defaultvalue present>} + return +} + +// CHECK: %[[PRESENT:.*]] = acc.present varPtr({{.*}} : !fir.ref<!fir.array<10xf32>>) -> !fir.ref<!fir.array<10xf32>> {acc.from_default, implicit = true, name = "arrayvar"} +// CHECK: acc.delete accPtr(%[[PRESENT]] : !fir.ref<!fir.array<10xf32>>) {dataClause = #acc<data_clause acc_present>, implicit = true, name = "arrayvar"} + +// ----- + +func.func @test_fir_array_in_kernels_defaultpresent() { + %livein = fir.alloca !fir.array<10xf32> {bindc_name = "arrayvar"} + acc.kernels { + %load = fir.load %livein : !fir.ref<!fir.array<10xf32>> + acc.terminator + } attributes {defaultAttr = #acc<defaultvalue present>} + return +} + +// CHECK: %[[PRESENT:.*]] = acc.present varPtr({{.*}} : !fir.ref<!fir.array<10xf32>>) -> !fir.ref<!fir.array<10xf32>> {acc.from_default, implicit = true, name = "arrayvar"} +// CHECK: acc.delete accPtr(%[[PRESENT]] : !fir.ref<!fir.array<10xf32>>) {dataClause = #acc<data_clause acc_present>, implicit = true, name = "arrayvar"} + +// ----- + +func.func @test_fir_scalar_in_parallel_defaultpresent() { + %livein = fir.alloca f32 {bindc_name = "scalarvar"} + acc.parallel { + %load = fir.load %livein : !fir.ref<f32> + acc.yield + } attributes {defaultAttr = #acc<defaultvalue present>} + return +} + +// CHECK: acc.firstprivate varPtr({{.*}} : !fir.ref<f32>) recipe({{.*}}) -> !fir.ref<f32> {implicit = true, name = "scalarvar"} + +// ----- + +func.func @test_fir_scalar_in_kernels_defaultpresent() { + %livein = fir.alloca f64 {bindc_name = "scalarvar"} + acc.kernels { + %load = fir.load %livein : !fir.ref<f64> + acc.terminator + } attributes {defaultAttr = #acc<defaultvalue present>} + return +} + +// CHECK: %[[COPYIN:.*]] = acc.copyin varPtr({{.*}} : !fir.ref<f64>) -> !fir.ref<f64> {dataClause = #acc<data_clause acc_copy>, implicit = true, name = "scalarvar"} +// CHECK: acc.copyout accPtr(%[[COPYIN]] : !fir.ref<f64>) to varPtr({{.*}} : !fir.ref<f64>) {dataClause = #acc<data_clause acc_copy>, implicit = true, name = "scalarvar"} + +// ----- + +func.func @test_fir_box_ref() { + %livein = fir.alloca !fir.box<!fir.array<?xi32>> {bindc_name = "descriptor"} + acc.parallel { + %load = fir.load %livein : !fir.ref<!fir.box<!fir.array<?xi32>>> + acc.yield + } + return +} + +// CHECK: %[[COPYIN:.*]] = acc.copyin varPtr({{.*}} : !fir.ref<!fir.box<!fir.array<?xi32>>>) -> !fir.ref<!fir.box<!fir.array<?xi32>>> {dataClause = #acc<data_clause acc_copy>, implicit = true, name = "descriptor"} +// CHECK: acc.copyout accPtr(%[[COPYIN]] : !fir.ref<!fir.box<!fir.array<?xi32>>>) to varPtr({{.*}} : !fir.ref<!fir.box<!fir.array<?xi32>>>) {dataClause = #acc<data_clause acc_copy>, implicit = true, name = "descriptor"} + +// ----- + +func.func @test_fir_box_val() { + %desc = fir.alloca !fir.box<!fir.array<?xi32>> {bindc_name = "descriptor"} + %livein = fir.load %desc : !fir.ref<!fir.box<!fir.array<?xi32>>> + acc.parallel { + %addr = fir.box_addr %livein : (!fir.box<!fir.array<?xi32>>) -> !fir.ref<!fir.array<?xi32>> + acc.yield + } + return +} + +// CHECK: %[[COPYIN:.*]] = acc.copyin var({{.*}} : !fir.box<!fir.array<?xi32>>) -> !fir.box<!fir.array<?xi32>> {dataClause = #acc<data_clause acc_copy>, implicit = true, name = "descriptor"} +// CHECK: acc.copyout accVar(%[[COPYIN]] : !fir.box<!fir.array<?xi32>>) to var({{.*}} : !fir.box<!fir.array<?xi32>>) {dataClause = #acc<data_clause acc_copy>, implicit = true, name = "descriptor"} + + +// ----- + +// This test has an explicit data clause for the box - but the pointer held +// inside the box is used in the region instead of the box itself. Test that +// implicit present is actually used. +func.func @test_explicit_box_implicit_ptr() { + %c1 = arith.constant 1 : index + %c10 = arith.constant 10 : index + %arr = fir.alloca !fir.array<10xf32> {bindc_name = "aa"} + %shape = fir.shape %c10 : (index) -> !fir.shape<1> + %arr_decl = fir.declare %arr(%shape) {uniq_name = "aa"} : (!fir.ref<!fir.array<10xf32>>, !fir.shape<1>) -> !fir.ref<!fir.array<10xf32>> + %box = fir.embox %arr_decl(%shape) : (!fir.ref<!fir.array<10xf32>>, !fir.shape<1>) -> !fir.box<!fir.array<10xf32>> + %copyin = acc.copyin var(%box : !fir.box<!fir.array<10xf32>>) -> !fir.box<!fir.array<10xf32>> {dataClause = #acc<data_clause acc_copy>, name = "aa"} + acc.serial dataOperands(%copyin : !fir.box<!fir.array<10xf32>>) { + // Use the pointer, not the box + %elem = fir.array_coor %arr_decl(%shape) %c1 : (!fir.ref<!fir.array<10xf32>>, !fir.shape<1>, index) -> !fir.ref<f32> + acc.yield + } + acc.copyout accVar(%copyin : !fir.box<!fir.array<10xf32>>) to var(%box : !fir.box<!fir.array<10xf32>>) {dataClause = #acc<data_clause acc_copy>, name = "aa"} + return +} + +// CHECK: acc.present varPtr(%{{.*}} : !fir.ref<!fir.array<10xf32>>){{.*}}-> !fir.ref<!fir.array<10xf32>> {implicit = true, name = "aa"} + +// ----- + +// This test uses an explicit-shape array with no data clause - it also has +// an optimization where the pointer is used instead of the boxed entity. +// It tests that the implicit data pass is able to recover the size despite +// it not being encoded in the FIR type. +// It was generated from the following Fortran source: +// subroutine array(aa,nn) +// integer :: nn +// real :: aa(10:nn) +// !$acc kernels loop +// do ii = 10, nn +// aa(ii) = ii +// end do +// !$acc end kernels +// end subroutine + +func.func @_QParray(%arg0: !fir.ref<!fir.array<?xf32>> {fir.bindc_name = "aa"}, %arg1: !fir.ref<i32> {fir.bindc_name = "nn"}) { + %c0 = arith.constant 0 : index + %c1 = arith.constant 1 : index + %c10_i64 = arith.constant 10 : i64 + %0 = fir.dummy_scope : !fir.dscope + %1 = fir.declare %arg1 dummy_scope %0 {uniq_name = "_QFarrayEnn"} : (!fir.ref<i32>, !fir.dscope) -> !fir.ref<i32> + %4 = fir.convert %c10_i64 : (i64) -> index + %5 = fir.load %1 : !fir.ref<i32> + %6 = fir.convert %5 : (i32) -> i64 + %7 = fir.convert %6 : (i64) -> index + %8 = arith.subi %7, %4 : index + %9 = arith.addi %8, %c1 : index + %10 = arith.cmpi sgt, %9, %c0 : index + %11 = arith.select %10, %9, %c0 : index + %12 = fir.shape_shift %4, %11 : (index, index) -> !fir.shapeshift<1> + %13 = fir.declare %arg0(%12) dummy_scope %0 {uniq_name = "_QFarrayEaa"} : (!fir.ref<!fir.array<?xf32>>, !fir.shapeshift<1>, !fir.dscope) -> !fir.ref<!fir.array<?xf32>> + acc.kernels { + %elem = fir.array_coor %13(%12) %4 : (!fir.ref<!fir.array<?xf32>>, !fir.shapeshift<1>, index) -> !fir.ref<f32> + acc.terminator + } + return +} + +// This tries to confirm that the acc.bounds operation is as expected. +// Effectively the extent needs to be max(0, nn), stride needs to be 1, +// adjusted lowerbound is 0, and actual language start index is 10. +// CHECK: %[[NN:.*]] = fir.declare %{{.*}} dummy_scope %{{.*}} {uniq_name = "_QFarrayEnn"} : (!fir.ref<i32>, !fir.dscope) -> !fir.ref<i32> +// CHECK: %[[C10:.*]] = fir.convert %c10{{.*}} : (i64) -> index +// CHECK: %[[LOADEDNN:.*]] = fir.load %[[NN]] : !fir.ref<i32> +// CHECK: %[[CAST1:.*]] = fir.convert %[[LOADEDNN]] : (i32) -> i64 +// CHECK: %[[CAST2:.*]] = fir.convert %[[CAST1]] : (i64) -> index +// CHECK: %[[SUBI:.*]] = arith.subi %[[CAST2]], %[[C10]] : index +// CHECK: %[[ADDI:.*]] = arith.addi %[[SUBI]], %c1{{.*}} : index +// CHECK: %[[CMPI:.*]] = arith.cmpi sgt, %[[ADDI]], %c0{{.*}} : index +// CHECK: %[[SELECT:.*]] = arith.select %[[CMPI]], %[[ADDI]], %c0{{.*}} : index +// CHECK: %[[BOUNDS:.*]] = acc.bounds lowerbound(%c0{{.*}} : index) upperbound(%{{.*}} : index) extent(%[[SELECT]] : index) stride(%c1{{.*}} : index) startIdx(%[[C10]] : index) +// CHECK: acc.copyin varPtr(%{{.*}} : !fir.ref<!fir.array<?xf32>>) bounds(%[[BOUNDS]]) -> !fir.ref<!fir.array<?xf32>> {dataClause = #acc<data_clause acc_copy>, implicit = true, name = "aa"} + +// ----- + +// Test to confirm that a copyin clause is not implicitly generated for deviceptr symbol. +func.func @test_deviceptr_no_implicit_copy() { + %c10 = arith.constant 10 : index + %arr = fir.alloca !fir.array<10xf64> {bindc_name = "a"} + %shape = fir.shape %c10 : (index) -> !fir.shape<1> + %arr_box = fir.embox %arr(%shape) : (!fir.ref<!fir.array<10xf64>>, !fir.shape<1>) -> !fir.box<!fir.array<10xf64>> + %devptr = acc.deviceptr var(%arr_box : !fir.box<!fir.array<10xf64>>) -> !fir.box<!fir.array<10xf64>> {name = "a"} + acc.parallel dataOperands(%devptr : !fir.box<!fir.array<10xf64>>) { + %elem = fir.box_addr %arr_box : (!fir.box<!fir.array<10xf64>>) -> !fir.ref<!fir.array<10xf64>> + acc.yield + } + return +} + +// CHECK-NOT: acc.copyin +// CHECK: acc.deviceptr + +// ----- + +// Test that acc.declare with deviceptr doesn't generate implicit copyin +func.func @test_acc_declare_deviceptr() { + %c10 = arith.constant 10 : index + %arr = fir.alloca !fir.array<10xf64> {bindc_name = "a"} + %shape = fir.shape %c10 : (index) -> !fir.shape<1> + %arr_box = fir.embox %arr(%shape) : (!fir.ref<!fir.array<10xf64>>, !fir.shape<1>) -> !fir.box<!fir.array<10xf64>> + %devptr = acc.deviceptr var(%arr_box : !fir.box<!fir.array<10xf64>>) -> !fir.box<!fir.array<10xf64>> {name = "a"} + %token = acc.declare_enter dataOperands(%devptr : !fir.box<!fir.array<10xf64>>) + acc.parallel { + %elem = fir.box_addr %arr_box : (!fir.box<!fir.array<10xf64>>) -> !fir.ref<!fir.array<10xf64>> + acc.yield + } + acc.declare_exit token(%token) + return +} + +// CHECK-LABEL: func.func @test_acc_declare_deviceptr +// CHECK: acc.deviceptr +// CHECK-NOT: acc.copyin +// CHECK: acc.deviceptr + diff --git a/flang/test/Transforms/OpenACC/acc-implicit-firstprivate.fir b/flang/test/Transforms/OpenACC/acc-implicit-firstprivate.fir new file mode 100644 index 0000000..3a3288a --- /dev/null +++ b/flang/test/Transforms/OpenACC/acc-implicit-firstprivate.fir @@ -0,0 +1,284 @@ +// RUN: fir-opt %s --pass-pipeline="builtin.module(acc-initialize-fir-analyses,acc-implicit-data)" -split-input-file | FileCheck %s + +// Test implicit firstprivate behavior for various scalar types in parallel and serial constructs. +// Scalars in parallel/serial constructs should be implicitly firstprivate according to OpenACC spec. + +// ----- + +// CHECK-LABEL: acc.firstprivate.recipe @firstprivatization_ref_i32 : !fir.ref<i32> init { +// CHECK: ^bb0(%{{.*}}: !fir.ref<i32>): +// CHECK: %[[ALLOC:.*]] = fir.alloca i32 +// CHECK: %[[DECL:.*]]:2 = hlfir.declare %[[ALLOC]] +// CHECK: acc.yield %[[DECL]]#0 : !fir.ref<i32> +// CHECK: } copy { +// CHECK: ^bb0(%[[SRC:.*]]: !fir.ref<i32>, %[[DST:.*]]: !fir.ref<i32>): +// CHECK: %[[LOADED:.*]] = fir.load %[[SRC]] : !fir.ref<i32> +// CHECK: fir.store %[[LOADED]] to %[[DST]] : !fir.ref<i32> +// CHECK: acc.terminator +// CHECK: } + +// CHECK-LABEL: func.func @test_i32_scalar_in_parallel +func.func @test_i32_scalar_in_parallel() { + %scalar = fir.alloca i32 {bindc_name = "i32_var"} + acc.parallel { + %load = fir.load %scalar : !fir.ref<i32> + acc.yield + } + return +} + +// CHECK: %[[FIRSTPRIV:.*]] = acc.firstprivate varPtr(%{{.*}} : !fir.ref<i32>) recipe(@firstprivatization_ref_i32) -> !fir.ref<i32> {implicit = true, name = "i32_var"} +// CHECK: acc.parallel firstprivate(%[[FIRSTPRIV]] : !fir.ref<i32>) + +// ----- + +// CHECK-LABEL: acc.firstprivate.recipe @firstprivatization_ref_i64 : !fir.ref<i64> init { +// CHECK: ^bb0(%{{.*}}: !fir.ref<i64>): +// CHECK: %[[ALLOC:.*]] = fir.alloca i64 +// CHECK: %[[DECL:.*]]:2 = hlfir.declare %[[ALLOC]] +// CHECK: acc.yield %[[DECL]]#0 : !fir.ref<i64> +// CHECK: } copy { +// CHECK: ^bb0(%[[SRC:.*]]: !fir.ref<i64>, %[[DST:.*]]: !fir.ref<i64>): +// CHECK: %[[LOADED:.*]] = fir.load %[[SRC]] : !fir.ref<i64> +// CHECK: fir.store %[[LOADED]] to %[[DST]] : !fir.ref<i64> +// CHECK: acc.terminator +// CHECK: } + +// CHECK-LABEL: func.func @test_i64_scalar_in_parallel +func.func @test_i64_scalar_in_parallel() { + %scalar = fir.alloca i64 {bindc_name = "i64_var"} + acc.parallel { + %load = fir.load %scalar : !fir.ref<i64> + acc.yield + } + return +} + +// CHECK: %[[FIRSTPRIV:.*]] = acc.firstprivate varPtr(%{{.*}} : !fir.ref<i64>) recipe(@firstprivatization_ref_i64) -> !fir.ref<i64> {implicit = true, name = "i64_var"} +// CHECK: acc.parallel firstprivate(%[[FIRSTPRIV]] : !fir.ref<i64>) + +// ----- + +// CHECK-LABEL: acc.firstprivate.recipe @firstprivatization_ref_f32 : !fir.ref<f32> init { +// CHECK: ^bb0(%{{.*}}: !fir.ref<f32>): +// CHECK: %[[ALLOC:.*]] = fir.alloca f32 +// CHECK: %[[DECL:.*]]:2 = hlfir.declare %[[ALLOC]] +// CHECK: acc.yield %[[DECL]]#0 : !fir.ref<f32> +// CHECK: } copy { +// CHECK: ^bb0(%[[SRC:.*]]: !fir.ref<f32>, %[[DST:.*]]: !fir.ref<f32>): +// CHECK: %[[LOADED:.*]] = fir.load %[[SRC]] : !fir.ref<f32> +// CHECK: fir.store %[[LOADED]] to %[[DST]] : !fir.ref<f32> +// CHECK: acc.terminator +// CHECK: } + +// CHECK-LABEL: func.func @test_f32_scalar_in_parallel +func.func @test_f32_scalar_in_parallel() { + %scalar = fir.alloca f32 {bindc_name = "f32_var"} + acc.parallel { + %load = fir.load %scalar : !fir.ref<f32> + acc.yield + } + return +} + +// CHECK: %[[FIRSTPRIV:.*]] = acc.firstprivate varPtr(%{{.*}} : !fir.ref<f32>) recipe(@firstprivatization_ref_f32) -> !fir.ref<f32> {implicit = true, name = "f32_var"} +// CHECK: acc.parallel firstprivate(%[[FIRSTPRIV]] : !fir.ref<f32>) + +// ----- + +// CHECK-LABEL: acc.firstprivate.recipe @firstprivatization_ref_f64 : !fir.ref<f64> init { +// CHECK: ^bb0(%{{.*}}: !fir.ref<f64>): +// CHECK: %[[ALLOC:.*]] = fir.alloca f64 +// CHECK: %[[DECL:.*]]:2 = hlfir.declare %[[ALLOC]] +// CHECK: acc.yield %[[DECL]]#0 : !fir.ref<f64> +// CHECK: } copy { +// CHECK: ^bb0(%[[SRC:.*]]: !fir.ref<f64>, %[[DST:.*]]: !fir.ref<f64>): +// CHECK: %[[LOADED:.*]] = fir.load %[[SRC]] : !fir.ref<f64> +// CHECK: fir.store %[[LOADED]] to %[[DST]] : !fir.ref<f64> +// CHECK: acc.terminator +// CHECK: } + +// CHECK-LABEL: func.func @test_f64_scalar_in_parallel +func.func @test_f64_scalar_in_parallel() { + %scalar = fir.alloca f64 {bindc_name = "f64_var"} + acc.parallel { + %load = fir.load %scalar : !fir.ref<f64> + acc.yield + } + return +} + +// CHECK: %[[FIRSTPRIV:.*]] = acc.firstprivate varPtr(%{{.*}} : !fir.ref<f64>) recipe(@firstprivatization_ref_f64) -> !fir.ref<f64> {implicit = true, name = "f64_var"} +// CHECK: acc.parallel firstprivate(%[[FIRSTPRIV]] : !fir.ref<f64>) + +// ----- + +// CHECK-LABEL: acc.firstprivate.recipe @firstprivatization_ref_l32 : !fir.ref<!fir.logical<4>> init { +// CHECK: ^bb0(%{{.*}}: !fir.ref<!fir.logical<4>>): +// CHECK: %[[ALLOC:.*]] = fir.alloca !fir.logical<4> +// CHECK: %[[DECL:.*]]:2 = hlfir.declare %[[ALLOC]] +// CHECK: acc.yield %[[DECL]]#0 : !fir.ref<!fir.logical<4>> +// CHECK: } copy { +// CHECK: ^bb0(%[[SRC:.*]]: !fir.ref<!fir.logical<4>>, %[[DST:.*]]: !fir.ref<!fir.logical<4>>): +// CHECK: %[[LOADED:.*]] = fir.load %[[SRC]] : !fir.ref<!fir.logical<4>> +// CHECK: fir.store %[[LOADED]] to %[[DST]] : !fir.ref<!fir.logical<4>> +// CHECK: acc.terminator +// CHECK: } + +// CHECK-LABEL: func.func @test_logical_scalar_in_parallel +func.func @test_logical_scalar_in_parallel() { + %scalar = fir.alloca !fir.logical<4> {bindc_name = "logical_var"} + acc.parallel { + %load = fir.load %scalar : !fir.ref<!fir.logical<4>> + acc.yield + } + return +} + +// CHECK: %[[FIRSTPRIV:.*]] = acc.firstprivate varPtr(%{{.*}} : !fir.ref<!fir.logical<4>>) recipe(@firstprivatization_ref_l32) -> !fir.ref<!fir.logical<4>> {implicit = true, name = "logical_var"} +// CHECK: acc.parallel firstprivate(%[[FIRSTPRIV]] : !fir.ref<!fir.logical<4>>) + +// ----- + +// CHECK-LABEL: acc.firstprivate.recipe @firstprivatization_ref_z32 : !fir.ref<complex<f32>> init { +// CHECK: ^bb0(%{{.*}}: !fir.ref<complex<f32>>): +// CHECK: %[[ALLOC:.*]] = fir.alloca complex<f32> +// CHECK: %[[DECL:.*]]:2 = hlfir.declare %[[ALLOC]] +// CHECK: acc.yield %[[DECL]]#0 : !fir.ref<complex<f32>> +// CHECK: } copy { +// CHECK: ^bb0(%[[SRC:.*]]: !fir.ref<complex<f32>>, %[[DST:.*]]: !fir.ref<complex<f32>>): +// CHECK: %[[LOADED:.*]] = fir.load %[[SRC]] : !fir.ref<complex<f32>> +// CHECK: fir.store %[[LOADED]] to %[[DST]] : !fir.ref<complex<f32>> +// CHECK: acc.terminator +// CHECK: } + +// CHECK-LABEL: func.func @test_complex_scalar_in_parallel +func.func @test_complex_scalar_in_parallel() { + %scalar = fir.alloca complex<f32> {bindc_name = "complex_var"} + acc.parallel { + %load = fir.load %scalar : !fir.ref<complex<f32>> + acc.yield + } + return +} + +// CHECK: %[[FIRSTPRIV:.*]] = acc.firstprivate varPtr(%{{.*}} : !fir.ref<complex<f32>>) recipe(@firstprivatization_ref_z32) -> !fir.ref<complex<f32>> {implicit = true, name = "complex_var"} +// CHECK: acc.parallel firstprivate(%[[FIRSTPRIV]] : !fir.ref<complex<f32>>) + +// ----- + +// CHECK-LABEL: acc.firstprivate.recipe @firstprivatization_ref_z64 : !fir.ref<complex<f64>> init { +// CHECK: ^bb0(%{{.*}}: !fir.ref<complex<f64>>): +// CHECK: %[[ALLOC:.*]] = fir.alloca complex<f64> +// CHECK: %[[DECL:.*]]:2 = hlfir.declare %[[ALLOC]] +// CHECK: acc.yield %[[DECL]]#0 : !fir.ref<complex<f64>> +// CHECK: } copy { +// CHECK: ^bb0(%[[SRC:.*]]: !fir.ref<complex<f64>>, %[[DST:.*]]: !fir.ref<complex<f64>>): +// CHECK: %[[LOADED:.*]] = fir.load %[[SRC]] : !fir.ref<complex<f64>> +// CHECK: fir.store %[[LOADED]] to %[[DST]] : !fir.ref<complex<f64>> +// CHECK: acc.terminator +// CHECK: } + +// CHECK-LABEL: func.func @test_complex8_scalar_in_parallel +func.func @test_complex8_scalar_in_parallel() { + %scalar = fir.alloca complex<f64> {bindc_name = "complex8_var"} + acc.parallel { + %load = fir.load %scalar : !fir.ref<complex<f64>> + acc.yield + } + return +} + +// CHECK: %[[FIRSTPRIV:.*]] = acc.firstprivate varPtr(%{{.*}} : !fir.ref<complex<f64>>) recipe(@firstprivatization_ref_z64) -> !fir.ref<complex<f64>> {implicit = true, name = "complex8_var"} +// CHECK: acc.parallel firstprivate(%[[FIRSTPRIV]] : !fir.ref<complex<f64>>) + +// ----- + +// Test with serial construct + +// CHECK-LABEL: func.func @test_i32_scalar_in_serial +func.func @test_i32_scalar_in_serial() { + %scalar = fir.alloca i32 {bindc_name = "serial_i32_var"} + acc.serial { + %load = fir.load %scalar : !fir.ref<i32> + acc.yield + } + return +} + +// CHECK: %[[FIRSTPRIV:.*]] = acc.firstprivate varPtr(%{{.*}} : !fir.ref<i32>) recipe(@firstprivatization_ref_i32) -> !fir.ref<i32> {implicit = true, name = "serial_i32_var"} +// CHECK: acc.serial firstprivate(%[[FIRSTPRIV]] : !fir.ref<i32>) + +// ----- + +// Test with serial construct and f64 + +// CHECK-LABEL: func.func @test_f64_scalar_in_serial +func.func @test_f64_scalar_in_serial() { + %scalar = fir.alloca f64 {bindc_name = "serial_f64_var"} + acc.serial { + %load = fir.load %scalar : !fir.ref<f64> + acc.yield + } + return +} + +// CHECK: %[[FIRSTPRIV:.*]] = acc.firstprivate varPtr(%{{.*}} : !fir.ref<f64>) recipe(@firstprivatization_ref_f64) -> !fir.ref<f64> {implicit = true, name = "serial_f64_var"} +// CHECK: acc.serial firstprivate(%[[FIRSTPRIV]] : !fir.ref<f64>) + +// ----- + +// Test i8 and i16 scalar types + +// CHECK-LABEL: acc.firstprivate.recipe @firstprivatization_ref_i8 : !fir.ref<i8> init { +// CHECK: ^bb0(%{{.*}}: !fir.ref<i8>): +// CHECK: %[[ALLOC:.*]] = fir.alloca i8 +// CHECK: %[[DECL:.*]]:2 = hlfir.declare %[[ALLOC]] +// CHECK: acc.yield %[[DECL]]#0 : !fir.ref<i8> +// CHECK: } copy { +// CHECK: ^bb0(%[[SRC:.*]]: !fir.ref<i8>, %[[DST:.*]]: !fir.ref<i8>): +// CHECK: %[[LOADED:.*]] = fir.load %[[SRC]] : !fir.ref<i8> +// CHECK: fir.store %[[LOADED]] to %[[DST]] : !fir.ref<i8> +// CHECK: acc.terminator +// CHECK: } + +// CHECK-LABEL: func.func @test_i8_scalar_in_parallel +func.func @test_i8_scalar_in_parallel() { + %scalar = fir.alloca i8 {bindc_name = "i8_var"} + acc.parallel { + %load = fir.load %scalar : !fir.ref<i8> + acc.yield + } + return +} + +// CHECK: %[[FIRSTPRIV:.*]] = acc.firstprivate varPtr(%{{.*}} : !fir.ref<i8>) recipe(@firstprivatization_ref_i8) -> !fir.ref<i8> {implicit = true, name = "i8_var"} +// CHECK: acc.parallel firstprivate(%[[FIRSTPRIV]] : !fir.ref<i8>) + +// ----- + +// CHECK-LABEL: acc.firstprivate.recipe @firstprivatization_ref_i16 : !fir.ref<i16> init { +// CHECK: ^bb0(%{{.*}}: !fir.ref<i16>): +// CHECK: %[[ALLOC:.*]] = fir.alloca i16 +// CHECK: %[[DECL:.*]]:2 = hlfir.declare %[[ALLOC]] +// CHECK: acc.yield %[[DECL]]#0 : !fir.ref<i16> +// CHECK: } copy { +// CHECK: ^bb0(%[[SRC:.*]]: !fir.ref<i16>, %[[DST:.*]]: !fir.ref<i16>): +// CHECK: %[[LOADED:.*]] = fir.load %[[SRC]] : !fir.ref<i16> +// CHECK: fir.store %[[LOADED]] to %[[DST]] : !fir.ref<i16> +// CHECK: acc.terminator +// CHECK: } + +// CHECK-LABEL: func.func @test_i16_scalar_in_parallel +func.func @test_i16_scalar_in_parallel() { + %scalar = fir.alloca i16 {bindc_name = "i16_var"} + acc.parallel { + %load = fir.load %scalar : !fir.ref<i16> + acc.yield + } + return +} + +// CHECK: %[[FIRSTPRIV:.*]] = acc.firstprivate varPtr(%{{.*}} : !fir.ref<i16>) recipe(@firstprivatization_ref_i16) -> !fir.ref<i16> {implicit = true, name = "i16_var"} +// CHECK: acc.parallel firstprivate(%[[FIRSTPRIV]] : !fir.ref<i16>) + diff --git a/flang/test/Transforms/debug-common-block.fir b/flang/test/Transforms/debug-common-block.fir index d68b524..1d2beae 100644 --- a/flang/test/Transforms/debug-common-block.fir +++ b/flang/test/Transforms/debug-common-block.fir @@ -16,18 +16,18 @@ module { %1 = fir.convert %0 : (!fir.ref<tuple<i32, !fir.array<8xi8>>>) -> !fir.ref<!fir.array<?xi8>> %2 = fir.coordinate_of %1, %c0 : (!fir.ref<!fir.array<?xi8>>, index) -> !fir.ref<i8> %3 = fir.convert %2 : (!fir.ref<i8>) -> !fir.ref<f32> - %4 = fircg.ext_declare %3 {uniq_name = "_QFf1Ex"} : (!fir.ref<f32>) -> !fir.ref<f32> loc(#loc4) + %4 = fircg.ext_declare %3 storage(%0[0]) {uniq_name = "_QFf1Ex"} : (!fir.ref<f32>, !fir.ref<tuple<i32, !fir.array<8xi8>>>) -> !fir.ref<f32> loc(#loc4) %5 = fir.address_of(@a_) : !fir.ref<tuple<i32, !fir.array<8xi8>>> %6 = fir.convert %5 : (!fir.ref<tuple<i32, !fir.array<8xi8>>>) -> !fir.ref<!fir.array<?xi8>> %7 = fir.coordinate_of %6, %c0 : (!fir.ref<!fir.array<?xi8>>, index) -> !fir.ref<i8> %8 = fir.convert %7 : (!fir.ref<i8>) -> !fir.ref<f32> - %9 = fircg.ext_declare %8 {uniq_name = "_QFf1Exa"} : (!fir.ref<f32>) -> !fir.ref<f32> loc(#loc5) + %9 = fircg.ext_declare %8 storage(%5[0]) {uniq_name = "_QFf1Exa"} : (!fir.ref<f32>, !fir.ref<tuple<i32, !fir.array<8xi8>>>) -> !fir.ref<f32> loc(#loc5) %10 = fir.coordinate_of %1, %c4 : (!fir.ref<!fir.array<?xi8>>, index) -> !fir.ref<i8> %11 = fir.convert %10 : (!fir.ref<i8>) -> !fir.ref<f32> - %12 = fircg.ext_declare %11 {uniq_name = "_QFf1Ey"} : (!fir.ref<f32>) -> !fir.ref<f32> loc(#loc6) + %12 = fircg.ext_declare %11 storage(%0[4]) {uniq_name = "_QFf1Ey"} : (!fir.ref<f32>, !fir.ref<tuple<i32, !fir.array<8xi8>>>) -> !fir.ref<f32> loc(#loc6) %13 = fir.coordinate_of %6, %c4 : (!fir.ref<!fir.array<?xi8>>, index) -> !fir.ref<i8> %14 = fir.convert %13 : (!fir.ref<i8>) -> !fir.ref<f32> - %15 = fircg.ext_declare %14 {uniq_name = "_QFf1Eya"} : (!fir.ref<f32>) -> !fir.ref<f32> loc(#loc7) + %15 = fircg.ext_declare %14 storage(%5[4]) {uniq_name = "_QFf1Eya"} : (!fir.ref<f32>, !fir.ref<tuple<i32, !fir.array<8xi8>>>) -> !fir.ref<f32> loc(#loc7) return } loc(#loc3) func.func @f2() { @@ -40,24 +40,24 @@ module { %1 = fir.convert %0 : (!fir.ref<tuple<i32, !fir.array<8xi8>>>) -> !fir.ref<!fir.array<?xi8>> %2 = fir.coordinate_of %1, %c0 : (!fir.ref<!fir.array<?xi8>>, index) -> !fir.ref<i8> %3 = fir.convert %2 : (!fir.ref<i8>) -> !fir.ref<f32> - %4 = fircg.ext_declare %3 {uniq_name = "_QFf2Ex"} : (!fir.ref<f32>) -> !fir.ref<f32> loc(#loc9) + %4 = fircg.ext_declare %3 storage(%0[0]) {uniq_name = "_QFf2Ex"} : (!fir.ref<f32>, !fir.ref<tuple<i32, !fir.array<8xi8>>>) -> !fir.ref<f32> loc(#loc9) %5 = fir.address_of(@a_) : !fir.ref<tuple<i32, !fir.array<8xi8>>> %6 = fir.convert %5 : (!fir.ref<tuple<i32, !fir.array<8xi8>>>) -> !fir.ref<!fir.array<?xi8>> %7 = fir.coordinate_of %6, %c0 : (!fir.ref<!fir.array<?xi8>>, index) -> !fir.ref<i8> %8 = fir.convert %7 : (!fir.ref<i8>) -> !fir.ref<f32> - %9 = fircg.ext_declare %8 {uniq_name = "_QFf2Exa"} : (!fir.ref<f32>) -> !fir.ref<f32> loc(#loc10) + %9 = fircg.ext_declare %8 storage(%5[0]) {uniq_name = "_QFf2Exa"} : (!fir.ref<f32>, !fir.ref<tuple<i32, !fir.array<8xi8>>>) -> !fir.ref<f32> loc(#loc10) %10 = fir.coordinate_of %1, %c4 : (!fir.ref<!fir.array<?xi8>>, index) -> !fir.ref<i8> %11 = fir.convert %10 : (!fir.ref<i8>) -> !fir.ref<f32> - %12 = fircg.ext_declare %11 {uniq_name = "_QFf2Ey"} : (!fir.ref<f32>) -> !fir.ref<f32> loc(#loc11) + %12 = fircg.ext_declare %11 storage(%0[4]) {uniq_name = "_QFf2Ey"} : (!fir.ref<f32>, !fir.ref<tuple<i32, !fir.array<8xi8>>>) -> !fir.ref<f32> loc(#loc11) %13 = fir.coordinate_of %6, %c4 : (!fir.ref<!fir.array<?xi8>>, index) -> !fir.ref<i8> %14 = fir.convert %13 : (!fir.ref<i8>) -> !fir.ref<f32> - %15 = fircg.ext_declare %14 {uniq_name = "_QFf2Eya"} : (!fir.ref<f32>) -> !fir.ref<f32> loc(#loc12) + %15 = fircg.ext_declare %14 storage(%5[4]) {uniq_name = "_QFf2Eya"} : (!fir.ref<f32>, !fir.ref<tuple<i32, !fir.array<8xi8>>>) -> !fir.ref<f32> loc(#loc12) %16 = fir.coordinate_of %1, %c8 : (!fir.ref<!fir.array<?xi8>>, index) -> !fir.ref<i8> %17 = fir.convert %16 : (!fir.ref<i8>) -> !fir.ref<f32> - %18 = fircg.ext_declare %17 {uniq_name = "_QFf2Ez"} : (!fir.ref<f32>) -> !fir.ref<f32> loc(#loc13) + %18 = fircg.ext_declare %17 storage(%0[8]) {uniq_name = "_QFf2Ez"} : (!fir.ref<f32>, !fir.ref<tuple<i32, !fir.array<8xi8>>>) -> !fir.ref<f32> loc(#loc13) %19 = fir.coordinate_of %6, %c8 : (!fir.ref<!fir.array<?xi8>>, index) -> !fir.ref<i8> %20 = fir.convert %19 : (!fir.ref<i8>) -> !fir.ref<f32> - %21 = fircg.ext_declare %20 {uniq_name = "_QFf2Eza"} : (!fir.ref<f32>) -> !fir.ref<f32> loc(#loc14) + %21 = fircg.ext_declare %20 storage(%5[8]) {uniq_name = "_QFf2Eza"} : (!fir.ref<f32>, !fir.ref<tuple<i32, !fir.array<8xi8>>>) -> !fir.ref<f32> loc(#loc14) return } loc(#loc8) func.func @f3() { @@ -69,12 +69,12 @@ module { %1 = fir.convert %0 : (!fir.ref<tuple<i32, !fir.array<8xi8>>>) -> !fir.ref<!fir.array<?xi8>> %2 = fir.coordinate_of %1, %c0 : (!fir.ref<!fir.array<?xi8>>, index) -> !fir.ref<i8> %3 = fir.convert %2 : (!fir.ref<i8>) -> !fir.ref<i32> - %4 = fircg.ext_declare %3 {uniq_name = "_QFf3Ex"} : (!fir.ref<i32>) -> !fir.ref<i32> loc(#loc16) + %4 = fircg.ext_declare %3 storage(%0[0]) {uniq_name = "_QFf3Ex"} : (!fir.ref<i32>, !fir.ref<tuple<i32, !fir.array<8xi8>>>) -> !fir.ref<i32> loc(#loc16) %5 = fir.address_of(@a_) : !fir.ref<tuple<i32, !fir.array<8xi8>>> %6 = fir.convert %5 : (!fir.ref<tuple<i32, !fir.array<8xi8>>>) -> !fir.ref<!fir.array<?xi8>> %7 = fir.coordinate_of %6, %c0 : (!fir.ref<!fir.array<?xi8>>, index) -> !fir.ref<i8> %8 = fir.convert %7 : (!fir.ref<i8>) -> !fir.ref<i32> - %9 = fircg.ext_declare %8 {uniq_name = "_QFf3Exa"} : (!fir.ref<i32>) -> !fir.ref<i32> loc(#loc17) + %9 = fircg.ext_declare %8 storage(%5[0]) {uniq_name = "_QFf3Exa"} : (!fir.ref<i32>, !fir.ref<tuple<i32, !fir.array<8xi8>>>) -> !fir.ref<i32> loc(#loc17) return } loc(#loc15) func.func @test() { @@ -87,24 +87,24 @@ module { %1 = fir.convert %0 : (!fir.ref<tuple<i32, !fir.array<8xi8>>>) -> !fir.ref<!fir.array<?xi8>> %2 = fir.coordinate_of %1, %c0 : (!fir.ref<!fir.array<?xi8>>, index) -> !fir.ref<i8> %3 = fir.convert %2 : (!fir.ref<i8>) -> !fir.ref<f32> - %4 = fircg.ext_declare %3 {uniq_name = "_QFEv1"} : (!fir.ref<f32>) -> !fir.ref<f32> loc(#loc19) + %4 = fircg.ext_declare %3 storage(%0[0]) {uniq_name = "_QFEv1"} : (!fir.ref<f32>, !fir.ref<tuple<i32, !fir.array<8xi8>>>) -> !fir.ref<f32> loc(#loc19) %5 = fir.coordinate_of %1, %c4 : (!fir.ref<!fir.array<?xi8>>, index) -> !fir.ref<i8> %6 = fir.convert %5 : (!fir.ref<i8>) -> !fir.ref<f32> - %7 = fircg.ext_declare %6 {uniq_name = "_QFEv2"} : (!fir.ref<f32>) -> !fir.ref<f32> loc(#loc20) + %7 = fircg.ext_declare %6 storage(%0[4]) {uniq_name = "_QFEv2"} : (!fir.ref<f32>, !fir.ref<tuple<i32, !fir.array<8xi8>>>) -> !fir.ref<f32> loc(#loc20) %8 = fir.coordinate_of %1, %c8 : (!fir.ref<!fir.array<?xi8>>, index) -> !fir.ref<i8> %9 = fir.convert %8 : (!fir.ref<i8>) -> !fir.ref<f32> - %10 = fircg.ext_declare %9 {uniq_name = "_QFEv3"} : (!fir.ref<f32>) -> !fir.ref<f32> loc(#loc21) + %10 = fircg.ext_declare %9 storage(%0[8]) {uniq_name = "_QFEv3"} : (!fir.ref<f32>, !fir.ref<tuple<i32, !fir.array<8xi8>>>) -> !fir.ref<f32> loc(#loc21) %11 = fir.address_of(@a_) : !fir.ref<tuple<i32, !fir.array<8xi8>>> %12 = fir.convert %11 : (!fir.ref<tuple<i32, !fir.array<8xi8>>>) -> !fir.ref<!fir.array<?xi8>> %13 = fir.coordinate_of %12, %c0 : (!fir.ref<!fir.array<?xi8>>, index) -> !fir.ref<i8> %14 = fir.convert %13 : (!fir.ref<i8>) -> !fir.ref<f32> - %15 = fircg.ext_declare %14 {uniq_name = "_QFEva1"} : (!fir.ref<f32>) -> !fir.ref<f32> loc(#loc22) + %15 = fircg.ext_declare %14 storage(%11[0]) {uniq_name = "_QFEva1"} : (!fir.ref<f32>, !fir.ref<tuple<i32, !fir.array<8xi8>>>) -> !fir.ref<f32> loc(#loc22) %16 = fir.coordinate_of %12, %c4 : (!fir.ref<!fir.array<?xi8>>, index) -> !fir.ref<i8> %17 = fir.convert %16 : (!fir.ref<i8>) -> !fir.ref<f32> - %18 = fircg.ext_declare %17 {uniq_name = "_QFEva2"} : (!fir.ref<f32>) -> !fir.ref<f32> loc(#loc23) + %18 = fircg.ext_declare %17 storage(%11[4]) {uniq_name = "_QFEva2"} : (!fir.ref<f32>, !fir.ref<tuple<i32, !fir.array<8xi8>>>) -> !fir.ref<f32> loc(#loc23) %19 = fir.coordinate_of %12, %c8 : (!fir.ref<!fir.array<?xi8>>, index) -> !fir.ref<i8> %20 = fir.convert %19 : (!fir.ref<i8>) -> !fir.ref<f32> - %21 = fircg.ext_declare %20 {uniq_name = "_QFEva3"} : (!fir.ref<f32>) -> !fir.ref<f32> loc(#loc24) + %21 = fircg.ext_declare %20 storage(%11[8]) {uniq_name = "_QFEva3"} : (!fir.ref<f32>, !fir.ref<tuple<i32, !fir.array<8xi8>>>) -> !fir.ref<f32> loc(#loc24) return } loc(#loc18) } diff --git a/flang/test/Transforms/debug-dummy-argument-inline.fir b/flang/test/Transforms/debug-dummy-argument-inline.fir new file mode 100644 index 0000000..02f0d5c --- /dev/null +++ b/flang/test/Transforms/debug-dummy-argument-inline.fir @@ -0,0 +1,36 @@ +// Tests that inlined calls arguments are not mistaken for the arguments of the +// procedure where the calls were inlined. +// RUN: fir-opt --add-debug-info --mlir-print-debuginfo %s -o - | FileCheck %s + +// CHECK: #di_local_variable = #llvm.di_local_variable<scope = #di_subprogram, name = "i", file = #di_file, line = 6, arg = 1, type = #di_basic_type> +// CHECK: #di_local_variable1 = #llvm.di_local_variable<scope = #di_subprogram, name = "i", file = #di_file, line = 1, type = #di_basic_type> + +func.func @foo_(%arg0: !fir.ref<i32> {fir.bindc_name = "i"} loc("debug-dummy-argument-inline.f90":5:1)) attributes {fir.internal_name = "_QPfoo"} { + %0 = fir.undefined !fir.dscope loc(#loc5) + %1 = fircg.ext_declare %arg0 dummy_scope %0 arg 1 {uniq_name = "_QFfooEi"} : (!fir.ref<i32>, !fir.dscope) -> !fir.ref<i32> loc(#loc6) + %2 = fir.undefined !fir.dscope loc(#loc11) + %3 = fircg.ext_declare %1 dummy_scope %2 arg 1 {uniq_name = "_QFbarEi"} : (!fir.ref<i32>, !fir.dscope) -> !fir.ref<i32> loc(#loc12) + fir.call @buzz_(%3) fastmath<contract> : (!fir.ref<i32>) -> () loc(#loc13) + %4 = fir.undefined !fir.dscope loc(#loc14) + %5 = fircg.ext_declare %1 dummy_scope %4 arg 1 {uniq_name = "_QFbarEi"} : (!fir.ref<i32>, !fir.dscope) -> !fir.ref<i32> loc(#loc15) + fir.call @buzz_(%5) fastmath<contract> : (!fir.ref<i32>) -> () loc(#loc16) + return loc(#loc9) +} loc(#loc5) +func.func private @buzz_(!fir.ref<i32>) attributes {fir.internal_name = "_QPbuzz"} loc(#loc10) +#loc = loc("debug-dummy-argument-inline.f90":0:0) +#loc1 = loc("debug-dummy-argument-inline.f90":1:1) +#loc2 = loc("debug-dummy-argument-inline.f90":2:14) +#loc3 = loc("debug-dummy-argument-inline.f90":3:3) +#loc4 = loc("debug-dummy-argument-inline.f90":4:1) +#loc5 = loc("debug-dummy-argument-inline.f90":5:1) +#loc6 = loc("debug-dummy-argument-inline.f90":6:14) +#loc7 = loc("debug-dummy-argument-inline.f90":7:3) +#loc8 = loc("debug-dummy-argument-inline.f90":8:3) +#loc9 = loc("debug-dummy-argument-inline.f90":9:1) +#loc10 = loc("debug-dummy-argument-inline.f90":3:8) +#loc11 = loc(callsite(#loc1 at #loc7)) +#loc12 = loc(callsite(#loc2 at #loc7)) +#loc13 = loc(callsite(#loc3 at #loc7)) +#loc14 = loc(callsite(#loc1 at #loc8)) +#loc15 = loc(callsite(#loc2 at #loc8)) +#loc16 = loc(callsite(#loc3 at #loc8)) diff --git a/flang/test/Transforms/debug-dummy-argument.fir b/flang/test/Transforms/debug-dummy-argument.fir index fb677e6..6186253 100644 --- a/flang/test/Transforms/debug-dummy-argument.fir +++ b/flang/test/Transforms/debug-dummy-argument.fir @@ -23,7 +23,7 @@ module attributes {dlti.dl_spec = #dlti.dl_spec<i128 = dense<128> : vector<2xi64>, f80 = dense<128> : vector<2xi64>, i1 = dense<8> : vector<2xi64>, !llvm.ptr<271> = dense<32> : vector<4xi64>, !llvm.ptr = dense<64> : vector<4xi64>, i64 = dense<64> : vector<2xi64>, !llvm.ptr<272> = dense<64> : vector<4xi64>, i32 = dense<32> : vector<2xi64>, i16 = dense<16> : vector<2xi64>, !llvm.ptr<270> = dense<32> : vector<4xi64>, i8 = dense<8> : vector<2xi64>, f128 = dense<128> : vector<2xi64>, f16 = dense<16> : vector<2xi64>, f64 = dense<64> : vector<2xi64>, "dlti.stack_alignment" = 128 : i64, "dlti.mangling_mode" = "e", "dlti.endianness" = "little">, fir.defaultkind = "a1c4d8i4l4r4", fir.kindmap = "", fir.target_cpu = "x86-64", llvm.data_layout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128", llvm.ident = "flang", llvm.target_triple = "x86_64-unknown-linux-gnu"} { func.func @test_(%arg0: !fir.ref<i32> {fir.bindc_name = "expected"} loc("debug-dummy-argument.f90":1:1), %arg1: !fir.box<!fir.array<?xi32>> {fir.bindc_name = "x"} loc("debug-dummy-argument.f90":1:1)) attributes {fir.internal_name = "_QPtest"} { %0 = fir.undefined !fir.dscope loc(#loc1) - %1 = fircg.ext_declare %arg0 dummy_scope %0 {uniq_name = "_QFtestEexpected"} : (!fir.ref<i32>, !fir.dscope) -> !fir.ref<i32> loc(#loc3) + %1 = fircg.ext_declare %arg0 dummy_scope %0 arg 1 {uniq_name = "_QFtestEexpected"} : (!fir.ref<i32>, !fir.dscope) -> !fir.ref<i32> loc(#loc3) %2 = fir.is_present %arg1 : (!fir.box<!fir.array<?xi32>>) -> i1 loc(#loc4) cf.cond_br %2, ^bb5(%arg1 : !fir.box<!fir.array<?xi32>>), ^bb5(%arg1 : !fir.box<!fir.array<?xi32>>) loc(#loc4) ^bb5(%17: !fir.box<!fir.array<?xi32>> loc("debug-dummy-argument.f90":2:14)): // 2 preds: ^bb3, ^bb4 diff --git a/flang/test/Transforms/debug-dwarf-version.fir b/flang/test/Transforms/debug-dwarf-version.fir index fe27002..0136d24 100644 --- a/flang/test/Transforms/debug-dwarf-version.fir +++ b/flang/test/Transforms/debug-dwarf-version.fir @@ -8,7 +8,7 @@ // RUN: | FileCheck --check-prefix=CHECK-DWARF2 %s // RUN: fir-opt --add-debug-info= --mlir-print-debuginfo %s \ // RUN: | FileCheck --check-prefix=CHECK-WITHOUT-VERSION %s -// REQUIRES: system-linux +// REQUIRES: system-linux || system-aix module { } loc(#loc) diff --git a/flang/test/Transforms/debug-line-table-existing.fir b/flang/test/Transforms/debug-line-table-existing.fir index 03eefd0..98ca3dc 100644 --- a/flang/test/Transforms/debug-line-table-existing.fir +++ b/flang/test/Transforms/debug-line-table-existing.fir @@ -1,6 +1,6 @@ // RUN: fir-opt --add-debug-info --mlir-print-debuginfo %s | FileCheck %s -// REQUIRES: system-linux +// REQUIRES: system-linux || system-aix // Test that there are no changes to a function with existed fused loc debug module { diff --git a/flang/test/Transforms/debug-line-table-inc-file.fir b/flang/test/Transforms/debug-line-table-inc-file.fir index 32c9f51..d29e2fd 100644 --- a/flang/test/Transforms/debug-line-table-inc-file.fir +++ b/flang/test/Transforms/debug-line-table-inc-file.fir @@ -1,6 +1,6 @@ // RUN: fir-opt --add-debug-info="debug-level=LineTablesOnly" --mlir-print-debuginfo %s | FileCheck %s -// REQUIRES: system-linux +// REQUIRES: system-linux || system-aix // Test for included functions that have a different debug location than the current file module { diff --git a/flang/test/Transforms/debug-line-table-inc-same-file.fir b/flang/test/Transforms/debug-line-table-inc-same-file.fir index aaa8d03..5265c79 100644 --- a/flang/test/Transforms/debug-line-table-inc-same-file.fir +++ b/flang/test/Transforms/debug-line-table-inc-same-file.fir @@ -1,6 +1,6 @@ // RUN: fir-opt --add-debug-info --mlir-print-debuginfo %s | FileCheck %s -// REQUIRES: system-linux +// REQUIRES: system-linux || system-aix // Test that there is only one FileAttribute generated for multiple functions // in the same file. diff --git a/flang/test/Transforms/debug-local-var.fir b/flang/test/Transforms/debug-local-var.fir index d39017e..863d86c 100644 --- a/flang/test/Transforms/debug-local-var.fir +++ b/flang/test/Transforms/debug-local-var.fir @@ -22,9 +22,9 @@ module { } loc(#loc7) func.func private @_QFPfn1(%arg0: !fir.ref<i32> {fir.bindc_name = "a1"}, %arg1: !fir.ref<f64> {fir.bindc_name = "b1"}, %arg2: !fir.ref<!fir.logical<1>> {fir.bindc_name = "c1"}) -> i64 attributes {fir.host_symbol = @_QQmain, llvm.linkage = #llvm.linkage<internal>} { %0 = fir.undefined !fir.dscope loc(#loc11) - %1 = fircg.ext_declare %arg0 dummy_scope %0 {uniq_name = "_QFFfn1Ea1"} : (!fir.ref<i32>, !fir.dscope) -> !fir.ref<i32> loc(#loc8) - %2 = fircg.ext_declare %arg1 dummy_scope %0 {uniq_name = "_QFFfn1Eb1"} : (!fir.ref<f64>, !fir.dscope) -> !fir.ref<f64> loc(#loc9) - %3 = fircg.ext_declare %arg2 dummy_scope %0 {uniq_name = "_QFFfn1Ec1"} : (!fir.ref<!fir.logical<1>>, !fir.dscope) -> !fir.ref<!fir.logical<1>> loc(#loc10) + %1 = fircg.ext_declare %arg0 dummy_scope %0 arg 1 {uniq_name = "_QFFfn1Ea1"} : (!fir.ref<i32>, !fir.dscope) -> !fir.ref<i32> loc(#loc8) + %2 = fircg.ext_declare %arg1 dummy_scope %0 arg 2 {uniq_name = "_QFFfn1Eb1"} : (!fir.ref<f64>, !fir.dscope) -> !fir.ref<f64> loc(#loc9) + %3 = fircg.ext_declare %arg2 dummy_scope %0 arg 3 {uniq_name = "_QFFfn1Ec1"} : (!fir.ref<!fir.logical<1>>, !fir.dscope) -> !fir.ref<!fir.logical<1>> loc(#loc10) %4 = fir.alloca i64 {bindc_name = "res1", uniq_name = "_QFFfn1Eres1"} loc(#loc15) %5 = fircg.ext_declare %4 {uniq_name = "_QFFfn1Eres1"} : (!fir.ref<i64>) -> !fir.ref<i64> loc(#loc11) %6 = fir.load %1 : !fir.ref<i32> @@ -38,9 +38,9 @@ module { } loc(#loc12) func.func private @_QFPfn2(%arg0: !fir.ref<i64> {fir.bindc_name = "a2"}, %arg1: !fir.ref<f32> {fir.bindc_name = "b2"}, %arg2: !fir.ref<!fir.logical<4>> {fir.bindc_name = "c2"}) -> i32 attributes {fir.host_symbol = @_QQmain, llvm.linkage = #llvm.linkage<internal>} { %0 = fir.undefined !fir.dscope - %1 = fircg.ext_declare %arg0 dummy_scope %0 {uniq_name = "_QFFfn2Ea2"} : (!fir.ref<i64>, !fir.dscope) -> !fir.ref<i64> loc(#loc13) - %2 = fircg.ext_declare %arg1 dummy_scope %0 {uniq_name = "_QFFfn2Eb2"} : (!fir.ref<f32>, !fir.dscope) -> !fir.ref<f32> loc(#loc14) - %3 = fircg.ext_declare %arg2 dummy_scope %0 {uniq_name = "_QFFfn2Ec2"} : (!fir.ref<!fir.logical<4>>, !fir.dscope) -> !fir.ref<!fir.logical<4>> loc(#loc15) + %1 = fircg.ext_declare %arg0 dummy_scope %0 arg 1 {uniq_name = "_QFFfn2Ea2"} : (!fir.ref<i64>, !fir.dscope) -> !fir.ref<i64> loc(#loc13) + %2 = fircg.ext_declare %arg1 dummy_scope %0 arg 2 {uniq_name = "_QFFfn2Eb2"} : (!fir.ref<f32>, !fir.dscope) -> !fir.ref<f32> loc(#loc14) + %3 = fircg.ext_declare %arg2 dummy_scope %0 arg 3 {uniq_name = "_QFFfn2Ec2"} : (!fir.ref<!fir.logical<4>>, !fir.dscope) -> !fir.ref<!fir.logical<4>> loc(#loc15) %4 = fir.alloca i32 {bindc_name = "res2", uniq_name = "_QFFfn2Eres2"} %5 = fircg.ext_declare %4 {uniq_name = "_QFFfn2Eres2"} : (!fir.ref<i32>) -> !fir.ref<i32> loc(#loc16) %6 = fir.load %1 : !fir.ref<i64> diff --git a/flang/test/Transforms/debug-proc-ptr.fir b/flang/test/Transforms/debug-proc-ptr.fir new file mode 100644 index 0000000..2963557 --- /dev/null +++ b/flang/test/Transforms/debug-proc-ptr.fir @@ -0,0 +1,41 @@ +// RUN: fir-opt --add-debug-info --mlir-print-debuginfo %s | FileCheck %s + +module { + func.func @_QQmain() attributes {fir.bindc_name = "test"} { + %0 = fir.alloca (!fir.ref<i32>) -> i32 {bindc_name = "fun_ptr", uniq_name = "_QFEfun_ptr"} + %1 = fircg.ext_declare %0 {uniq_name = "_QFEfun_ptr"} : (!fir.ref<(!fir.ref<i32>) -> i32>) -> !fir.ref<(!fir.ref<i32>) -> i32> loc(#loc1) + + // Procedure pointer with no return: procedure(sub1), pointer :: sub_ptr + %2 = fir.alloca () -> () {bindc_name = "sub_ptr", uniq_name = "_QFEsub_ptr"} + %3 = fircg.ext_declare %2 {uniq_name = "_QFEsub_ptr"} : (!fir.ref<() -> ()>) -> !fir.ref<() -> ()> loc(#loc2) + + // Procedure pointer with multiple args: procedure(func2), pointer :: func_ptr + %4 = fir.alloca (!fir.ref<i32>, !fir.ref<f64>) -> f32 {bindc_name = "func_ptr", uniq_name = "_QFEfunc_ptr"} + %5 = fircg.ext_declare %4 {uniq_name = "_QFEfunc_ptr"} : (!fir.ref<(!fir.ref<i32>, !fir.ref<f64>) -> f32>) -> !fir.ref<(!fir.ref<i32>, !fir.ref<f64>) -> f32> loc(#loc3) + + return + } loc(#loc) +} +#loc = loc("test.f90":1:1) +#loc1 = loc("test.f90":2:30) +#loc2 = loc("test.f90":3:30) +#loc3 = loc("test.f90":4:30) + +// CHECK-DAG: #[[INT:.*]] = #llvm.di_basic_type<tag = DW_TAG_base_type, name = "integer", sizeInBits = 32, encoding = DW_ATE_signed> +// CHECK-DAG: #[[REAL32:.*]] = #llvm.di_basic_type<tag = DW_TAG_base_type, name = "real", sizeInBits = 32, encoding = DW_ATE_float> +// CHECK-DAG: #[[REAL:.*]] = #llvm.di_basic_type<tag = DW_TAG_base_type, name = "real(kind=8)", sizeInBits = 64, encoding = DW_ATE_float> + +// CHECK-DAG: #[[PTR_INT:.*]] = #llvm.di_derived_type<tag = DW_TAG_pointer_type{{.*}}baseType = #[[INT]]{{.*}}> +// CHECK-DAG: #[[PTR_REAL:.*]] = #llvm.di_derived_type<tag = DW_TAG_pointer_type{{.*}}baseType = #[[REAL]]{{.*}}> + +// CHECK-DAG: #[[SUB1:.*]] = #llvm.di_subroutine_type<types = #[[INT]], #[[PTR_INT]]> +// CHECK-DAG: #[[PTR_SUB1:.*]] = #llvm.di_derived_type<tag = DW_TAG_pointer_type{{.*}}baseType = #[[SUB1]]{{.*}}> +// CHECK-DAG: #llvm.di_local_variable<{{.*}}name = "fun_ptr"{{.*}}type = #[[PTR_SUB1]]{{.*}}> + +// CHECK-DAG: #di_subroutine_type{{.*}} = #llvm.di_subroutine_type<types = #di_null_type> +// CHECK-DAG: #di_local_variable{{.*}} = #llvm.di_local_variable<{{.*}}name = "sub_ptr"{{.*}}type = #di_derived_type{{.*}}> +// CHECK-DAG: #di_derived_type{{.*}} = #llvm.di_derived_type<tag = DW_TAG_pointer_type{{.*}}baseType = #di_subroutine_type{{.*}}{{.*}}> + +// CHECK-DAG: #[[SUB3:.*]] = #llvm.di_subroutine_type<types = #[[REAL32]], #[[PTR_INT]], #[[PTR_REAL]]> +// CHECK-DAG: #[[PTR_SUB3:.*]] = #llvm.di_derived_type<tag = DW_TAG_pointer_type{{.*}}baseType = #[[SUB3]]{{.*}}> +// CHECK-DAG: #llvm.di_local_variable<{{.*}}name = "func_ptr"{{.*}}type = #[[PTR_SUB3]]{{.*}}> diff --git a/flang/test/Transforms/omp-map-info-finalization.fir b/flang/test/Transforms/omp-map-info-finalization.fir index b30a2fc..a808b81 100644 --- a/flang/test/Transforms/omp-map-info-finalization.fir +++ b/flang/test/Transforms/omp-map-info-finalization.fir @@ -32,11 +32,11 @@ func.func @test_descriptor_expansion_pass(%arg0: !fir.box<!fir.array<?xi32>>) { // CHECK: %[[BOUNDS:.*]] = omp.map.bounds lower_bound(%{{.*}} : index) upper_bound(%{{.*}} : index) extent(%{{.*}} : index) stride(%{{.*}} : index) start_idx(%{{.*}} : index) {stride_in_bytes = true} // CHECK: %[[BASE_ADDR_OFF:.*]] = fir.box_offset %[[DECLARE2]]#1 base_addr : (!fir.ref<!fir.box<!fir.heap<i32>>>) -> !fir.llvm_ptr<!fir.ref<i32>> // CHECK: %[[DESC_MEMBER_MAP:.*]] = omp.map.info var_ptr(%[[DECLARE2]]#1 : !fir.ref<!fir.box<!fir.heap<i32>>>, i32) map_clauses(tofrom) capture(ByRef) var_ptr_ptr(%[[BASE_ADDR_OFF]] : !fir.llvm_ptr<!fir.ref<i32>>) -> !fir.llvm_ptr<!fir.ref<i32>> {name = ""} -// CHECK: %[[DESC_PARENT_MAP:.*]] = omp.map.info var_ptr(%[[DECLARE2]]#1 : !fir.ref<!fir.box<!fir.heap<i32>>>, !fir.box<!fir.heap<i32>>) map_clauses(to) capture(ByRef) members(%[[DESC_MEMBER_MAP]] : [0] : !fir.llvm_ptr<!fir.ref<i32>>) -> !fir.ref<!fir.box<!fir.heap<i32>>> +// CHECK: %[[DESC_PARENT_MAP:.*]] = omp.map.info var_ptr(%[[DECLARE2]]#1 : !fir.ref<!fir.box<!fir.heap<i32>>>, !fir.box<!fir.heap<i32>>) map_clauses(always, to) capture(ByRef) members(%[[DESC_MEMBER_MAP]] : [0] : !fir.llvm_ptr<!fir.ref<i32>>) -> !fir.ref<!fir.box<!fir.heap<i32>>> // CHECK: fir.store %[[DECLARE1]]#1 to %[[ALLOCA]] : !fir.ref<!fir.box<!fir.array<?xi32>>> // CHECK: %[[BASE_ADDR_OFF_2:.*]] = fir.box_offset %[[ALLOCA]] base_addr : (!fir.ref<!fir.box<!fir.array<?xi32>>>) -> !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>> // CHECK: %[[DESC_MEMBER_MAP_2:.*]] = omp.map.info var_ptr(%[[ALLOCA]] : !fir.ref<!fir.box<!fir.array<?xi32>>>, i32) map_clauses(from) capture(ByRef) var_ptr_ptr(%[[BASE_ADDR_OFF_2]] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) bounds(%[[BOUNDS]]) -> !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>> {name = ""} -// CHECK: %[[DESC_PARENT_MAP_2:.*]] = omp.map.info var_ptr(%[[ALLOCA]] : !fir.ref<!fir.box<!fir.array<?xi32>>>, !fir.box<!fir.array<?xi32>>) map_clauses(to) capture(ByRef) members(%[[DESC_MEMBER_MAP_2]] : [0] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) -> !fir.ref<!fir.array<?xi32>> +// CHECK: %[[DESC_PARENT_MAP_2:.*]] = omp.map.info var_ptr(%[[ALLOCA]] : !fir.ref<!fir.box<!fir.array<?xi32>>>, !fir.box<!fir.array<?xi32>>) map_clauses(always, to) capture(ByRef) members(%[[DESC_MEMBER_MAP_2]] : [0] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) -> !fir.ref<!fir.array<?xi32>> // CHECK: omp.target map_entries(%[[DESC_PARENT_MAP]] -> %[[ARG1:.*]], %[[DESC_PARENT_MAP_2]] -> %[[ARG2:.*]], %[[DESC_MEMBER_MAP]] -> %[[ARG3:.*]], %[[DESC_MEMBER_MAP_2]] -> %[[ARG4:.*]] : {{.*}}) { // ----- @@ -112,7 +112,7 @@ func.func @dtype_alloca_op_block_add(%arg0: !fir.ref<!fir.type<_QFtest_derived_t // CHECK: %[[MEMBER_COORD:.*]] = fir.coordinate_of %[[ALLOCA]]#0, array_j : (!fir.ref<[[REC_TY]]>>) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> // CHECK: %[[MEMBER_BASE_ADDR:.*]] = fir.box_offset %[[MEMBER_COORD:.*]] base_addr : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) -> !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>> // CHECK: %[[MAP_MEMBER_BASE_ADDR:.*]] = omp.map.info var_ptr(%[[MEMBER_COORD]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, i32) map_clauses(tofrom) capture(ByRef) var_ptr_ptr(%[[MEMBER_BASE_ADDR]] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) bounds(%[[BOUNDS]]) -> !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>> {{.*}} -// CHECK: %[[MAP_MEMBER_DESCRIPTOR:.*]] = omp.map.info var_ptr(%[[MEMBER_COORD]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.box<!fir.heap<!fir.array<?xi32>>>) map_clauses(to) capture(ByRef) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> {name = "one_l%array_j"} +// CHECK: %[[MAP_MEMBER_DESCRIPTOR:.*]] = omp.map.info var_ptr(%[[MEMBER_COORD]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.box<!fir.heap<!fir.array<?xi32>>>) map_clauses(always, to) capture(ByRef) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> {name = "one_l%array_j"} // CHECK: %[[MAP_MEMBER_PARENT:.*]] = omp.map.info var_ptr(%[[ALLOCA]]#0 : !fir.ref<[[REC_TY]]>>, [[REC_TY]]>) map_clauses(tofrom) capture(ByRef) members(%10, %9 : [4], [4, 0] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) -> !fir.ref<[[REC_TY]]>> {{.*}} // CHECK: omp.target map_entries(%[[MAP_MEMBER_PARENT]] -> %[[ARG1:.*]], %[[MAP_MEMBER_DESCRIPTOR]] -> %[[ARG2:.*]], %[[MAP_MEMBER_BASE_ADDR]] -> %[[ARG3:.*]] : !fir.ref<[[REC_TY]]>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) { @@ -152,13 +152,13 @@ func.func @alloca_dtype_map_op_block_add(%arg0 : !fir.ref<!fir.box<!fir.heap<!fi // CHECK: %[[ALLOCATABLE_MEMBER_COORD:.*]] = fir.coordinate_of %[[LOAD_ALLOCA]], array_j : (!fir.box<!fir.heap<!fir.type<[[REC_TY]]>>>) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> // CHECK: %[[ALLOCATABLE_MEMBER_BASE_ADDR:.*]] = fir.box_offset %[[ALLOCATABLE_MEMBER_COORD]] base_addr : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) -> !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>> // CHECK: %[[MAP_ALLOCA_MEMBER_BASE_ADDR:.*]] = omp.map.info var_ptr(%[[ALLOCATABLE_MEMBER_COORD]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, i32) map_clauses(tofrom) capture(ByRef) var_ptr_ptr(%[[ALLOCATABLE_MEMBER_BASE_ADDR]] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) bounds(%[[BOUNDS]]) -> !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>> {{.*}} -// CHECK: %[[MAP_ALLOCA_MEMBER_DESCRIPTOR:.*]] = omp.map.info var_ptr(%[[ALLOCATABLE_MEMBER_COORD]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.box<!fir.heap<!fir.array<?xi32>>>) map_clauses(to) capture(ByRef) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> {{.*}} +// CHECK: %[[MAP_ALLOCA_MEMBER_DESCRIPTOR:.*]] = omp.map.info var_ptr(%[[ALLOCATABLE_MEMBER_COORD]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.box<!fir.heap<!fir.array<?xi32>>>) map_clauses(always, to) capture(ByRef) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> {{.*}} // CHECK: %[[LOAD_ALLOCA2:.*]] = fir.load %[[ALLOCA]]#0 : !fir.ref<!fir.box<!fir.heap<!fir.type<[[REC_TY]]>>>> // CHECK: %[[REGULAR_MEMBER_COORD:.*]] = fir.coordinate_of %[[LOAD_ALLOCA2]], k : (!fir.box<!fir.heap<!fir.type<[[REC_TY]]>>>) -> !fir.ref<i32> // CHECK: %[[MAP_REGULAR_MEMBER:.*]] = omp.map.info var_ptr(%[[REGULAR_MEMBER_COORD]] : !fir.ref<i32>, i32) map_clauses(tofrom) capture(ByRef) -> !fir.ref<i32> {{.*}} // CHECK: %[[ALLOCATABLE_PARENT_BASE_ADDR:.*]] = fir.box_offset %[[ALLOCA]]#1 base_addr : (!fir.ref<!fir.box<!fir.heap<!fir.type<[[REC_TY]]>>>>) -> !fir.llvm_ptr<!fir.ref<!fir.type<[[REC_TY]]>>> // CHECK: %[[MAP_ALLOCA_PARENT_BASE_ADDR:.*]] = omp.map.info var_ptr(%[[ALLOCA]]#1 : !fir.ref<!fir.box<!fir.heap<!fir.type<[[REC_TY]]>>>>, !fir.type<[[REC_TY]]>) map_clauses(tofrom) capture(ByRef) var_ptr_ptr(%[[ALLOCATABLE_PARENT_BASE_ADDR]] : !fir.llvm_ptr<!fir.ref<!fir.type<[[REC_TY]]>>>) -> !fir.llvm_ptr<!fir.ref<!fir.type<[[REC_TY]]>>> {{.*}} -// CHECK: %[[MAP_PARENT_DESCRIPTOR:.*]] = omp.map.info var_ptr(%[[ALLOCA]]#1 : !fir.ref<!fir.box<!fir.heap<!fir.type<[[REC_TY]]>>>>, !fir.box<!fir.heap<!fir.type<[[REC_TY]]>>>) map_clauses(to) capture(ByRef) members(%18, %13, %12, %16 : [0], [0, 4], [0, 4, 0], [0, 5] : !fir.llvm_ptr<!fir.ref<!fir.type<[[REC_TY]]>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>, !fir.ref<i32>) -> !fir.ref<!fir.box<!fir.heap<!fir.type<[[REC_TY]]>>>> {{.*}} +// CHECK: %[[MAP_PARENT_DESCRIPTOR:.*]] = omp.map.info var_ptr(%[[ALLOCA]]#1 : !fir.ref<!fir.box<!fir.heap<!fir.type<[[REC_TY]]>>>>, !fir.box<!fir.heap<!fir.type<[[REC_TY]]>>>) map_clauses(always, to) capture(ByRef) members(%18, %13, %12, %16 : [0], [0, 4], [0, 4, 0], [0, 5] : !fir.llvm_ptr<!fir.ref<!fir.type<[[REC_TY]]>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>, !fir.ref<i32>) -> !fir.ref<!fir.box<!fir.heap<!fir.type<[[REC_TY]]>>>> {{.*}} // CHECK: omp.target map_entries(%[[MAP_PARENT_DESCRIPTOR]] -> %[[ARG1:.*]], %[[MAP_ALLOCA_PARENT_BASE_ADDR]] -> %[[ARG2:.*]], %[[MAP_ALLOCA_MEMBER_DESCRIPTOR]] -> %[[ARG3:.*]], %[[MAP_ALLOCA_MEMBER_BASE_ADDR]] -> %[[ARG4:.*]], %[[MAP_REGULAR_MEMBER]] -> %[[ARG5:.*]] : !fir.ref<!fir.box<!fir.heap<!fir.type<[[REC_TY]]>>>>, !fir.llvm_ptr<!fir.ref<!fir.type<[[REC_TY]]>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>, !fir.ref<i32>) { // ----- @@ -202,14 +202,14 @@ func.func @alloca_dtype_map_op_block_add(%arg0 : !fir.ref<!fir.box<!fir.heap<!fi // CHECK: %[[NESTED_ALLOCA_MEMBER:.*]] = fir.coordinate_of %[[INTERMEDIATE_DTYPE_NESTED_MEMBER]], array_k : (!fir.ref<!fir.type<[[REC_TY2]]>>) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> // CHECK: %[[NESTED_ALLOCA_MEMBER_BASE_ADDR:.*]] = fir.box_offset %[[NESTED_ALLOCA_MEMBER]] base_addr : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) -> !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>> // CHECK: %[[MAP_NESTED_ALLOCA_MEMBER_BASE_ADDR:.*]] = omp.map.info var_ptr(%[[NESTED_ALLOCA_MEMBER]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, i32) map_clauses(tofrom) capture(ByRef) var_ptr_ptr(%[[NESTED_ALLOCA_MEMBER_BASE_ADDR]] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) bounds(%[[BOUNDS]]) -> !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>> {{.*}} -// CHECK: %[[MAP_NESTED_ALLOCA_MEMBER:.*]] = omp.map.info var_ptr(%[[NESTED_ALLOCA_MEMBER]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.box<!fir.heap<!fir.array<?xi32>>>) map_clauses(to) capture(ByRef) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> {{.*}} +// CHECK: %[[MAP_NESTED_ALLOCA_MEMBER:.*]] = omp.map.info var_ptr(%[[NESTED_ALLOCA_MEMBER]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.box<!fir.heap<!fir.array<?xi32>>>) map_clauses(always, to) capture(ByRef) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> {{.*}} // CHECK: %[[ALLOCA_LOAD2:.*]] = fir.load %[[ALLOCA]]#0 : !fir.ref<!fir.box<!fir.heap<!fir.type<[[REC_TY]]>>>> // CHECK: %[[INTERMEDIATE_DTYPE_NESTED_MEMBER2:.*]] = fir.coordinate_of %[[ALLOCA_LOAD2]], nest : (!fir.box<!fir.heap<!fir.type<[[REC_TY]]>>>) -> !fir.ref<!fir.type<[[REC_TY2]]>> // CHECK: %[[NESTED_REGULAR_MEMBER:.*]] = fir.coordinate_of %[[INTERMEDIATE_DTYPE_NESTED_MEMBER2]], k : (!fir.ref<!fir.type<[[REC_TY2]]>>) -> !fir.ref<i32> // CHECK: %[[MAP_NESTED_REGULAR_MEMBER:.*]] = omp.map.info var_ptr(%[[NESTED_REGULAR_MEMBER:.*]] : !fir.ref<i32>, i32) map_clauses(tofrom) capture(ByRef) -> !fir.ref<i32> {{.*}} // CHECK: %[[ALLOCATABLE_PARENT_BASE_ADDR:.*]] = fir.box_offset %[[ALLOCA]]#1 base_addr : (!fir.ref<!fir.box<!fir.heap<!fir.type<[[REC_TY]]>>>>) -> !fir.llvm_ptr<!fir.ref<!fir.type<[[REC_TY]]>>> // CHECK: %[[MAP_ALLOCATABLE_PARENT_BASE_ADDR:.*]] = omp.map.info var_ptr(%[[ALLOCA]]#1 : !fir.ref<!fir.box<!fir.heap<!fir.type<[[REC_TY]]>>>>, !fir.type<[[REC_TY]]>) map_clauses(tofrom) capture(ByRef) var_ptr_ptr(%[[ALLOCATABLE_PARENT_BASE_ADDR]] : !fir.llvm_ptr<!fir.ref<!fir.type<[[REC_TY]]>>>) -> !fir.llvm_ptr<!fir.ref<!fir.type<[[REC_TY]]>>> {{.*}} -// CHECK: %[[MAP_ALLOCATABLE_PARENT_DESCRIPTOR:.*]] = omp.map.info var_ptr(%[[ALLOCA]]#1 : !fir.ref<!fir.box<!fir.heap<!fir.type<[[REC_TY]]>>>>, !fir.box<!fir.heap<!fir.type<[[REC_TY]]>>>) map_clauses(to) capture(ByRef) members(%21, %15, %14, %19 : [0], [0, 6, 2], [0, 6, 2, 0], [0, 6, 3] : !fir.llvm_ptr<!fir.ref<!fir.type<[[REC_TY]]>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>, !fir.ref<i32>) -> !fir.ref<!fir.box<!fir.heap<!fir.type<[[REC_TY]]>>>> {{.*}} +// CHECK: %[[MAP_ALLOCATABLE_PARENT_DESCRIPTOR:.*]] = omp.map.info var_ptr(%[[ALLOCA]]#1 : !fir.ref<!fir.box<!fir.heap<!fir.type<[[REC_TY]]>>>>, !fir.box<!fir.heap<!fir.type<[[REC_TY]]>>>) map_clauses(always, to) capture(ByRef) members(%21, %15, %14, %19 : [0], [0, 6, 2], [0, 6, 2, 0], [0, 6, 3] : !fir.llvm_ptr<!fir.ref<!fir.type<[[REC_TY]]>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>, !fir.ref<i32>) -> !fir.ref<!fir.box<!fir.heap<!fir.type<[[REC_TY]]>>>> {{.*}} // CHECK: omp.target map_entries(%[[MAP_ALLOCATABLE_PARENT_DESCRIPTOR]] -> %[[ARG1:.*]], %[[MAP_ALLOCATABLE_PARENT_BASE_ADDR]] -> %[[ARG2:.*]], %[[MAP_NESTED_ALLOCA_MEMBER]] -> %[[ARG3:.*]], %[[MAP_NESTED_ALLOCA_MEMBER_BASE_ADDR]] -> %[[ARG4:.*]], %[[MAP_NESTED_REGULAR_MEMBER]] -> %[[ARG5:.*]] : !fir.ref<!fir.box<!fir.heap<!fir.type<[[REC_TY]]>>>>, !fir.llvm_ptr<!fir.ref<!fir.type<[[REC_TY]]>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>, !fir.ref<i32>) { // ----- @@ -245,7 +245,7 @@ func.func @alloca_dtype_map_op_block_add(%arg0 : !fir.ref<!fir.box<!fir.heap<!fi // CHECK: %[[ALLOCATABLE_MEMBER:.*]] = fir.coordinate_of %[[NESTED_DTYPE_COORD]], array_k : (!fir.ref<!fir.type<[[REC_TY2]]>>) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> // CHECK: %[[ALLOCATABLE_MEMBER_BASE_ADDR:.*]] = fir.box_offset %[[ALLOCATABLE_MEMBER]] base_addr : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) -> !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>> // CHECK: %[[MAP_ALLOCATABLE_MEMBER_BASE_ADDR:.*]] = omp.map.info var_ptr(%[[ALLOCATABLE_MEMBER]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, i32) map_clauses(tofrom) capture(ByRef) var_ptr_ptr(%[[ALLOCATABLE_MEMBER_BASE_ADDR]] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) bounds(%[[BOUNDS]]) -> !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>> {{.*}} -// CHECK: %[[MAP_ALLOCATABLE_MEMBER_DESCRIPTOR:.*]] = omp.map.info var_ptr(%[[ALLOCATABLE_MEMBER]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.box<!fir.heap<!fir.array<?xi32>>>) map_clauses(to) capture(ByRef) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> {{.*}} +// CHECK: %[[MAP_ALLOCATABLE_MEMBER_DESCRIPTOR:.*]] = omp.map.info var_ptr(%[[ALLOCATABLE_MEMBER]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.box<!fir.heap<!fir.array<?xi32>>>) map_clauses(always, to) capture(ByRef) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> {{.*}} // CHECK: %[[MAP_PARENT:.*]] = omp.map.info var_ptr(%[[ALLOCA]]#0 : !fir.ref<!fir.type<[[REC_TY]]>>, !fir.type<[[REC_TY]]>) map_clauses(tofrom) capture(ByRef) members(%12, %11 : [6, 2], [6, 2, 0] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) -> !fir.ref<!fir.type<[[REC_TY]]>> {{.*}} // CHECK: omp.target map_entries(%[[MAP_PARENT]] -> %[[ARG1:.*]], %[[MAP_ALLOCATABLE_MEMBER_DESCRIPTOR]] -> %[[ARG2:.*]], %[[MAP_ALLOCATABLE_MEMBER_BASE_ADDR]] -> %[[ARG3:.*]] : !fir.ref<!fir.type<[[REC_TY]]>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) { @@ -278,13 +278,13 @@ func.func @alloca_dtype_map_op_block_add(%arg0 : !fir.ref<!fir.box<!fir.heap<!fi // CHECK: %[[DESC_1:.*]] = fir.coordinate_of %[[DECLARE]]#0, vertexes : (!fir.ref<!fir.type<[[REC_TY]]>>) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.type<[[REC_TY2:_QFmaptype_nested_derived_type_member_idxTvertexes{test:i32,vertexx:!fir.box<!fir.heap<!fir.array<\?xi32>>>,vertexy:!fir.box<!fir.heap<!fir.array<\?xi32>>>}]]>>>>> // CHECK: %[[BASE_ADDR_1:.*]] = fir.box_offset %[[DESC_1]] base_addr : (!fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.type<[[REC_TY2]]>>>>>) -> !fir.llvm_ptr<!fir.ref<!fir.array<?x!fir.type<[[REC_TY2]]>>>> // CHECK: %[[BASE_ADDR_MAP_1:.*]] = omp.map.info var_ptr(%[[DESC_1]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.type<[[REC_TY2]]>>>>>, !fir.type<[[REC_TY2]]>) map_clauses(storage) capture(ByRef) var_ptr_ptr(%[[BASE_ADDR_1]] : !fir.llvm_ptr<!fir.ref<!fir.array<?x!fir.type<[[REC_TY2]]>>>>) bounds(%{{.*}}) -> !fir.llvm_ptr<!fir.ref<!fir.array<?x!fir.type<[[REC_TY2]]>>>> {{.*}} -// CHECK: %[[DESC_MAP_1:.*]] = omp.map.info var_ptr(%[[DESC_1]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.type<[[REC_TY2]]>>>>>, !fir.box<!fir.heap<!fir.array<?x!fir.type<[[REC_TY2]]>>>>) map_clauses(to) capture(ByRef) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.type<[[REC_TY2]]>>>>> {{.*}} +// CHECK: %[[DESC_MAP_1:.*]] = omp.map.info var_ptr(%[[DESC_1]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.type<[[REC_TY2]]>>>>>, !fir.box<!fir.heap<!fir.array<?x!fir.type<[[REC_TY2]]>>>>) map_clauses(always, to) capture(ByRef) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.type<[[REC_TY2]]>>>>> {{.*}} // CHECK: %[[DESC_LD_1:.*]] = fir.load %[[DESC_1]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.type<[[REC_TY2]]>>>>> // CHECK: %[[MEMBER_ACCESS_1:.*]] = fir.coordinate_of %[[DESC_LD_1]], %{{.*}} : (!fir.box<!fir.heap<!fir.array<?x!fir.type<[[REC_TY2]]>>>>, index) -> !fir.ref<!fir.type<[[REC_TY2]]>> // CHECK: %[[DESC_2:.*]] = fir.coordinate_of %[[MEMBER_ACCESS_1]], vertexy : (!fir.ref<!fir.type<[[REC_TY2]]>>) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> // CHECK: %[[BASE_ADDR_2:.*]] = fir.box_offset %[[DESC_2]] base_addr : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) -> !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>> // CHECK: %[[BASE_ADDR_MAP_2:.*]] = omp.map.info var_ptr(%[[DESC_2]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, i32) map_clauses(tofrom) capture(ByRef) var_ptr_ptr(%[[BASE_ADDR_2]] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) bounds(%{{.*}}) -> !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>> {{.*}} -// CHECK: %[[DESC_MAP_2:.*]] = omp.map.info var_ptr(%[[DESC_2]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.box<!fir.heap<!fir.array<?xi32>>>) map_clauses(to) capture(ByRef) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> {{.*}} +// CHECK: %[[DESC_MAP_2:.*]] = omp.map.info var_ptr(%[[DESC_2]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.box<!fir.heap<!fir.array<?xi32>>>) map_clauses(always, to) capture(ByRef) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> {{.*}} // CHECK: %[[TOP_PARENT_MAP:.*]] = omp.map.info var_ptr(%0#1 : !fir.ref<!fir.type<[[REC_TY]]>>, !fir.type<[[REC_TY]]>) map_clauses(storage) capture(ByRef) members(%6, %5, %14, %13 : [1], [1, 0], [1, 0, 2], [1, 0, 2, 0] : !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.type<[[REC_TY2]]>>>>>, !fir.llvm_ptr<!fir.ref<!fir.array<?x!fir.type<[[REC_TY2]]>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) -> !fir.ref<!fir.type<[[REC_TY]]>> {{{.*}} partial_map = true} // CHECK: omp.target map_entries(%[[TOP_PARENT_MAP]] -> %{{.*}}, %[[DESC_MAP_1]] -> %{{.*}}, %[[BASE_ADDR_MAP_1]] -> %{{.*}}, %[[DESC_MAP_2]] -> %{{.*}}, %[[BASE_ADDR_MAP_2]] -> %{{.*}} : !fir.ref<!fir.type<[[REC_TY]]>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.type<[[REC_TY2]]>>>>>, !fir.llvm_ptr<!fir.ref<!fir.array<?x!fir.type<[[REC_TY2]]>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) { @@ -381,11 +381,10 @@ func.func @_QPrealtest(%arg0: !fir.boxchar<1>) { // CHECK: %[[VAL_8:.*]]:2 = fir.unboxchar %[[VAL_4]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index) // CHECK: %[[VAL_9:.*]] = arith.subi %[[VAL_8]]#1, %[[VAL_7]] : index // CHECK: %[[VAL_10:.*]] = omp.map.bounds lower_bound(%[[VAL_6]] : index) upper_bound(%[[VAL_9]] : index) extent(%[[VAL_8]]#1 : index) stride(%[[VAL_7]] : index) start_idx(%[[VAL_6]] : index) {stride_in_bytes = true} -// CHECK: %[[VAL_11:.*]] = fir.load %[[VAL_0]] : !fir.ref<!fir.boxchar<1>> // CHECK: %[[VAL_12:.*]] = fir.box_offset %[[VAL_0]] base_addr : (!fir.ref<!fir.boxchar<1>>) -> !fir.llvm_ptr<!fir.ref<!fir.char<1,?>>> -// CHECK: %[[VAL_13:.*]] = omp.map.info var_ptr(%[[VAL_0]] : !fir.ref<!fir.boxchar<1>>, !fir.char<1,?>) map_clauses(implicit, to) capture(ByRef) var_ptr_ptr(%[[VAL_12]] : !fir.llvm_ptr<!fir.ref<!fir.char<1,?>>>) bounds(%[[VAL_10]]) -> !fir.ref<!fir.boxchar<1>> -// CHECK: %[[VAL_14:.*]] = omp.map.info var_ptr(%[[VAL_0]] : !fir.ref<!fir.boxchar<1>>, !fir.boxchar<1>) map_clauses(to) capture(ByRef) members(%[[VAL_13]] : [0] : !fir.ref<!fir.boxchar<1>>) -> !fir.ref<!fir.boxchar<1>> -// CHECK: omp.target map_entries(%[[VAL_14]] -> %[[VAL_15:.*]], %[[VAL_13]] -> %[[VAL_16:.*]] : !fir.ref<!fir.boxchar<1>>, !fir.ref<!fir.boxchar<1>>) private(@boxchar.privatizer %[[VAL_3]]#0 -> %[[VAL_17:.*]] [map_idx=0] : !fir.boxchar<1>) { +// CHECK: %[[VAL_13:.*]] = omp.map.info var_ptr(%[[VAL_0]] : !fir.ref<!fir.boxchar<1>>, !fir.char<1,?>) map_clauses(to) capture(ByRef) var_ptr_ptr(%[[VAL_12]] : !fir.llvm_ptr<!fir.ref<!fir.char<1,?>>>) bounds(%[[VAL_10]]) -> !fir.llvm_ptr<!fir.ref<!fir.char<1,?>>> +// CHECK: %[[VAL_14:.*]] = omp.map.info var_ptr(%[[VAL_0]] : !fir.ref<!fir.boxchar<1>>, !fir.boxchar<1>) map_clauses(always, to) capture(ByRef) members(%[[VAL_13]] : [0] : !fir.llvm_ptr<!fir.ref<!fir.char<1,?>>>) -> !fir.ref<!fir.boxchar<1>> +// CHECK: omp.target map_entries(%[[VAL_14]] -> %[[VAL_15:.*]], %[[VAL_13]] -> %[[VAL_16:.*]] : !fir.ref<!fir.boxchar<1>>, !fir.llvm_ptr<!fir.ref<!fir.char<1,?>>>) private(@boxchar.privatizer %[[VAL_3]]#0 -> %[[VAL_17:.*]] [map_idx=0] : !fir.boxchar<1>) { // CHECK: %[[VAL_18:.*]]:2 = fir.unboxchar %[[VAL_17]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index) // CHECK: %[[VAL_19:.*]]:2 = hlfir.declare %[[VAL_18]]#0 typeparams %[[VAL_18]]#1 {uniq_name = "tgt_a0"} : (!fir.ref<!fir.char<1,?>>, index) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>) // CHECK: omp.terminator diff --git a/flang/test/Transforms/omp-maps-for-privatized-symbols.fir b/flang/test/Transforms/omp-maps-for-privatized-symbols.fir index 10a7612..6054c70a 100644 --- a/flang/test/Transforms/omp-maps-for-privatized-symbols.fir +++ b/flang/test/Transforms/omp-maps-for-privatized-symbols.fir @@ -6,7 +6,12 @@ module attributes {omp.is_target_device = false} { // extract box address, see if it is null, etc omp.yield(%arg1: !fir.ref<!fir.box<!fir.heap<i32>>>) } - + omp.private {type = firstprivate} @_QFtarget_simpleEfp_int_firstprivate_i32 : i32 copy { + ^bb0(%arg0: !fir.ref<i32>, %arg1: !fir.ref<i32>): + %0 = fir.load %arg0 : !fir.ref<i32> + hlfir.assign %0 to %arg1 : i32, !fir.ref<i32> + omp.yield(%arg1 : !fir.ref<i32>) + } func.func @_QPtarget_simple() { %0 = fir.alloca i32 {bindc_name = "a", uniq_name = "_QFtarget_simpleEa"} %1:2 = hlfir.declare %0 {uniq_name = "_QFtarget_simpleEa"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) @@ -15,34 +20,18 @@ module attributes {omp.is_target_device = false} { %4 = fir.embox %3 : (!fir.heap<i32>) -> !fir.box<!fir.heap<i32>> fir.store %4 to %2 : !fir.ref<!fir.box<!fir.heap<i32>>> %5:2 = hlfir.declare %2 {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFtarget_simpleEsimple_var"} : (!fir.ref<!fir.box<!fir.heap<i32>>>) -> (!fir.ref<!fir.box<!fir.heap<i32>>>, !fir.ref<!fir.box<!fir.heap<i32>>>) + %6 = fir.alloca i32 {bindc_name = "fp_int", uniq_name = "_QFtarget_simpleEfp_int"} + %7:2 = hlfir.declare %6 {uniq_name = "_QFtarget_simpleEfp_int"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) %c2_i32 = arith.constant 2 : i32 hlfir.assign %c2_i32 to %1#0 : i32, !fir.ref<i32> - %6 = omp.map.info var_ptr(%1#1 : !fir.ref<i32>, i32) map_clauses(to) capture(ByRef) -> !fir.ref<i32> {name = "a"} - omp.target map_entries(%6 -> %arg0 : !fir.ref<i32>) private(@_QFtarget_simpleEsimple_var_private_ref_box_heap_i32 %5#0 -> %arg1 : !fir.ref<!fir.box<!fir.heap<i32>>>) { - %11:2 = hlfir.declare %arg0 {uniq_name = "_QFtarget_simpleEa"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) - %12:2 = hlfir.declare %arg1 {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFtarget_simpleEsimple_var"} : (!fir.ref<!fir.box<!fir.heap<i32>>>) -> (!fir.ref<!fir.box<!fir.heap<i32>>>, !fir.ref<!fir.box<!fir.heap<i32>>>) - %c10_i32 = arith.constant 10 : i32 - %13 = fir.load %11#0 : !fir.ref<i32> - %14 = arith.addi %c10_i32, %13 : i32 - hlfir.assign %14 to %12#0 realloc : i32, !fir.ref<!fir.box<!fir.heap<i32>>> + %8 = omp.map.info var_ptr(%1#1 : !fir.ref<i32>, i32) map_clauses(to) capture(ByRef) -> !fir.ref<i32> {name = "a"} + omp.target map_entries(%8 -> %arg0 : !fir.ref<i32>) private(@_QFtarget_simpleEsimple_var_private_ref_box_heap_i32 %5#0 -> %arg1, @_QFtarget_simpleEfp_int_firstprivate_i32 %7#0 -> %arg2 : !fir.ref<!fir.box<!fir.heap<i32>>>, !fir.ref<i32>) { omp.terminator } - %7 = fir.load %5#1 : !fir.ref<!fir.box<!fir.heap<i32>>> - %8 = fir.box_addr %7 : (!fir.box<!fir.heap<i32>>) -> !fir.heap<i32> - %9 = fir.convert %8 : (!fir.heap<i32>) -> i64 - %c0_i64 = arith.constant 0 : i64 - %10 = arith.cmpi ne, %9, %c0_i64 : i64 - fir.if %10 { - %11 = fir.load %5#1 : !fir.ref<!fir.box<!fir.heap<i32>>> - %12 = fir.box_addr %11 : (!fir.box<!fir.heap<i32>>) -> !fir.heap<i32> - fir.freemem %12 : !fir.heap<i32> - %13 = fir.zero_bits !fir.heap<i32> - %14 = fir.embox %13 : (!fir.heap<i32>) -> !fir.box<!fir.heap<i32>> - fir.store %14 to %5#1 : !fir.ref<!fir.box<!fir.heap<i32>>> - } return } } // CHECK: %[[MAP0:.*]] = omp.map.info var_ptr({{.*}} : !fir.ref<i32>, i32) map_clauses(to) capture(ByRef) -> !fir.ref<i32> {name = "a"} -// CHECK: %[[MAP1:.*]] = omp.map.info var_ptr({{.*}} : !fir.ref<!fir.box<!fir.heap<i32>>>, !fir.box<!fir.heap<i32>>) map_clauses(to) capture(ByRef) -> !fir.ref<!fir.box<!fir.heap<i32>>> -// CHECK: omp.target map_entries(%[[MAP0]] -> %arg0, %[[MAP1]] -> %arg1 : !fir.ref<i32>, !fir.ref<!fir.box<!fir.heap<i32>>>) +// CHECK: %[[MAP1:.*]] = omp.map.info var_ptr({{.*}} : !fir.ref<!fir.box<!fir.heap<i32>>>, !fir.box<!fir.heap<i32>>) map_clauses(tofrom) capture(ByRef) -> !fir.ref<!fir.box<!fir.heap<i32>>> +// CHECK: %[[MAP2:.*]] = omp.map.info var_ptr({{.*}} : !fir.ref<i32>, i32) map_clauses(to) capture(ByCopy) -> !fir.ref<i32> +// CHECK: omp.target map_entries(%[[MAP0]] -> %arg0, %[[MAP1]] -> %arg1, %[[MAP2]] -> %arg2 : !fir.ref<i32>, !fir.ref<!fir.box<!fir.heap<i32>>>, !fir.ref<i32>) diff --git a/flang/test/Transforms/set-runtime-call-attributes.fir b/flang/test/Transforms/set-runtime-call-attributes.fir index ecb2dd5..bdc47c8 100644 --- a/flang/test/Transforms/set-runtime-call-attributes.fir +++ b/flang/test/Transforms/set-runtime-call-attributes.fir @@ -23,7 +23,7 @@ module { // CHECK-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: i32, // CHECK-SAME: %[[VAL_1:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<i8>, // CHECK-SAME: %[[VAL_2:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: i32) -> !fir.ref<i8> { -// CHECK: %[[VAL_3:.*]] = fir.call @_FortranAioBeginBackspace(%[[VAL_0]], %[[VAL_1]], %[[VAL_2]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite>, llvm.nocallback, llvm.nosync} : (i32, !fir.ref<i8>, i32) -> !fir.ref<i8> +// CHECK: %[[VAL_3:.*]] = fir.call @_FortranAioBeginBackspace(%[[VAL_0]], %[[VAL_1]], %[[VAL_2]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite, errnoMem = none, targetMem0 = none, targetMem1 = none>, llvm.nocallback, llvm.nosync} : (i32, !fir.ref<i8>, i32) -> !fir.ref<i8> // CHECK: return %[[VAL_3]] : !fir.ref<i8> // CHECK: } func.func @test__FortranAioBeginBackspace(%arg0: i32, %arg1: !fir.ref<i8>, %arg2: i32) -> !fir.ref<i8> { @@ -34,7 +34,7 @@ module { // CHECK-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: i32, // CHECK-SAME: %[[VAL_1:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<i8>, // CHECK-SAME: %[[VAL_2:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: i32) -> !fir.ref<i8> { -// CHECK: %[[VAL_3:.*]] = fir.call @_FortranAioBeginClose(%[[VAL_0]], %[[VAL_1]], %[[VAL_2]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite>, llvm.nocallback, llvm.nosync} : (i32, !fir.ref<i8>, i32) -> !fir.ref<i8> +// CHECK: %[[VAL_3:.*]] = fir.call @_FortranAioBeginClose(%[[VAL_0]], %[[VAL_1]], %[[VAL_2]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite, errnoMem = none, targetMem0 = none, targetMem1 = none>, llvm.nocallback, llvm.nosync} : (i32, !fir.ref<i8>, i32) -> !fir.ref<i8> // CHECK: return %[[VAL_3]] : !fir.ref<i8> // CHECK: } func.func @test__FortranAioBeginClose(%arg0: i32, %arg1: !fir.ref<i8>, %arg2: i32) -> !fir.ref<i8> { @@ -45,7 +45,7 @@ module { // CHECK-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: i32, // CHECK-SAME: %[[VAL_1:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<i8>, // CHECK-SAME: %[[VAL_2:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: i32) -> !fir.ref<i8> { -// CHECK: %[[VAL_3:.*]] = fir.call @_FortranAioBeginEndfile(%[[VAL_0]], %[[VAL_1]], %[[VAL_2]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite>, llvm.nocallback, llvm.nosync} : (i32, !fir.ref<i8>, i32) -> !fir.ref<i8> +// CHECK: %[[VAL_3:.*]] = fir.call @_FortranAioBeginEndfile(%[[VAL_0]], %[[VAL_1]], %[[VAL_2]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite, errnoMem = none, targetMem0 = none, targetMem1 = none>, llvm.nocallback, llvm.nosync} : (i32, !fir.ref<i8>, i32) -> !fir.ref<i8> // CHECK: return %[[VAL_3]] : !fir.ref<i8> // CHECK: } func.func @test__FortranAioBeginEndfile(%arg0: i32, %arg1: !fir.ref<i8>, %arg2: i32) -> !fir.ref<i8> { @@ -84,7 +84,7 @@ module { // CHECK-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: i32, // CHECK-SAME: %[[VAL_1:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<i8>, // CHECK-SAME: %[[VAL_2:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: i32) -> !fir.ref<i8> { -// CHECK: %[[VAL_3:.*]] = fir.call @_FortranAioBeginExternalListInput(%[[VAL_0]], %[[VAL_1]], %[[VAL_2]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite>, llvm.nocallback, llvm.nosync} : (i32, !fir.ref<i8>, i32) -> !fir.ref<i8> +// CHECK: %[[VAL_3:.*]] = fir.call @_FortranAioBeginExternalListInput(%[[VAL_0]], %[[VAL_1]], %[[VAL_2]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite, errnoMem = none, targetMem0 = none, targetMem1 = none>, llvm.nocallback, llvm.nosync} : (i32, !fir.ref<i8>, i32) -> !fir.ref<i8> // CHECK: return %[[VAL_3]] : !fir.ref<i8> // CHECK: } func.func @test__FortranAioBeginExternalListInput(%arg0: i32, %arg1: !fir.ref<i8>, %arg2: i32) -> !fir.ref<i8> { @@ -95,7 +95,7 @@ module { // CHECK-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: i32, // CHECK-SAME: %[[VAL_1:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<i8>, // CHECK-SAME: %[[VAL_2:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: i32) -> !fir.ref<i8> { -// CHECK: %[[VAL_3:.*]] = fir.call @_FortranAioBeginExternalListOutput(%[[VAL_0]], %[[VAL_1]], %[[VAL_2]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite>, llvm.nocallback, llvm.nosync} : (i32, !fir.ref<i8>, i32) -> !fir.ref<i8> +// CHECK: %[[VAL_3:.*]] = fir.call @_FortranAioBeginExternalListOutput(%[[VAL_0]], %[[VAL_1]], %[[VAL_2]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite, errnoMem = none, targetMem0 = none, targetMem1 = none>, llvm.nocallback, llvm.nosync} : (i32, !fir.ref<i8>, i32) -> !fir.ref<i8> // CHECK: return %[[VAL_3]] : !fir.ref<i8> // CHECK: } func.func @test__FortranAioBeginExternalListOutput(%arg0: i32, %arg1: !fir.ref<i8>, %arg2: i32) -> !fir.ref<i8> { @@ -106,7 +106,7 @@ module { // CHECK-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: i32, // CHECK-SAME: %[[VAL_1:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<i8>, // CHECK-SAME: %[[VAL_2:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: i32) -> !fir.ref<i8> { -// CHECK: %[[VAL_3:.*]] = fir.call @_FortranAioBeginFlush(%[[VAL_0]], %[[VAL_1]], %[[VAL_2]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite>, llvm.nocallback, llvm.nosync} : (i32, !fir.ref<i8>, i32) -> !fir.ref<i8> +// CHECK: %[[VAL_3:.*]] = fir.call @_FortranAioBeginFlush(%[[VAL_0]], %[[VAL_1]], %[[VAL_2]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite, errnoMem = none, targetMem0 = none, targetMem1 = none>, llvm.nocallback, llvm.nosync} : (i32, !fir.ref<i8>, i32) -> !fir.ref<i8> // CHECK: return %[[VAL_3]] : !fir.ref<i8> // CHECK: } func.func @test__FortranAioBeginFlush(%arg0: i32, %arg1: !fir.ref<i8>, %arg2: i32) -> !fir.ref<i8> { @@ -118,7 +118,7 @@ module { // CHECK-SAME: %[[VAL_1:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: i64, // CHECK-SAME: %[[VAL_2:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<i8>, // CHECK-SAME: %[[VAL_3:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: i32) -> !fir.ref<i8> { -// CHECK: %[[VAL_4:.*]] = fir.call @_FortranAioBeginInquireFile(%[[VAL_0]], %[[VAL_1]], %[[VAL_2]], %[[VAL_3]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>, i64, !fir.ref<i8>, i32) -> !fir.ref<i8> +// CHECK: %[[VAL_4:.*]] = fir.call @_FortranAioBeginInquireFile(%[[VAL_0]], %[[VAL_1]], %[[VAL_2]], %[[VAL_3]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite, errnoMem = none, targetMem0 = none, targetMem1 = none>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>, i64, !fir.ref<i8>, i32) -> !fir.ref<i8> // CHECK: return %[[VAL_4]] : !fir.ref<i8> // CHECK: } func.func @test__FortranAioBeginInquireFile(%arg0: !fir.ref<i8>, %arg1: i64, %arg2: !fir.ref<i8>, %arg3: i32) -> !fir.ref<i8> { @@ -128,7 +128,7 @@ module { // CHECK-LABEL: func.func @test__FortranAioBeginInquireIoLength( // CHECK-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<i8>, // CHECK-SAME: %[[VAL_1:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: i32) -> !fir.ref<i8> { -// CHECK: %[[VAL_2:.*]] = fir.call @_FortranAioBeginInquireIoLength(%[[VAL_0]], %[[VAL_1]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>, i32) -> !fir.ref<i8> +// CHECK: %[[VAL_2:.*]] = fir.call @_FortranAioBeginInquireIoLength(%[[VAL_0]], %[[VAL_1]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite, errnoMem = none, targetMem0 = none, targetMem1 = none>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>, i32) -> !fir.ref<i8> // CHECK: return %[[VAL_2]] : !fir.ref<i8> // CHECK: } func.func @test__FortranAioBeginInquireIoLength(%arg0: !fir.ref<i8>, %arg1: i32) -> !fir.ref<i8> { @@ -139,7 +139,7 @@ module { // CHECK-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: i32, // CHECK-SAME: %[[VAL_1:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<i8>, // CHECK-SAME: %[[VAL_2:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: i32) -> !fir.ref<i8> { -// CHECK: %[[VAL_3:.*]] = fir.call @_FortranAioBeginInquireUnit(%[[VAL_0]], %[[VAL_1]], %[[VAL_2]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite>, llvm.nocallback, llvm.nosync} : (i32, !fir.ref<i8>, i32) -> !fir.ref<i8> +// CHECK: %[[VAL_3:.*]] = fir.call @_FortranAioBeginInquireUnit(%[[VAL_0]], %[[VAL_1]], %[[VAL_2]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite, errnoMem = none, targetMem0 = none, targetMem1 = none>, llvm.nocallback, llvm.nosync} : (i32, !fir.ref<i8>, i32) -> !fir.ref<i8> // CHECK: return %[[VAL_3]] : !fir.ref<i8> // CHECK: } func.func @test__FortranAioBeginInquireUnit(%arg0: i32, %arg1: !fir.ref<i8>, %arg2: i32) -> !fir.ref<i8> { @@ -269,7 +269,7 @@ module { // CHECK-LABEL: func.func @test__FortranAioBeginOpenNewUnit( // CHECK-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<i8>, // CHECK-SAME: %[[VAL_1:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: i32) -> !fir.ref<i8> { -// CHECK: %[[VAL_2:.*]] = fir.call @_FortranAioBeginOpenNewUnit(%[[VAL_0]], %[[VAL_1]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>, i32) -> !fir.ref<i8> +// CHECK: %[[VAL_2:.*]] = fir.call @_FortranAioBeginOpenNewUnit(%[[VAL_0]], %[[VAL_1]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite, errnoMem = none, targetMem0 = none, targetMem1 = none>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>, i32) -> !fir.ref<i8> // CHECK: return %[[VAL_2]] : !fir.ref<i8> // CHECK: } func.func @test__FortranAioBeginOpenNewUnit(%arg0: !fir.ref<i8>, %arg1: i32) -> !fir.ref<i8> { @@ -280,7 +280,7 @@ module { // CHECK-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: i32, // CHECK-SAME: %[[VAL_1:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<i8>, // CHECK-SAME: %[[VAL_2:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: i32) -> !fir.ref<i8> { -// CHECK: %[[VAL_3:.*]] = fir.call @_FortranAioBeginOpenUnit(%[[VAL_0]], %[[VAL_1]], %[[VAL_2]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite>, llvm.nocallback, llvm.nosync} : (i32, !fir.ref<i8>, i32) -> !fir.ref<i8> +// CHECK: %[[VAL_3:.*]] = fir.call @_FortranAioBeginOpenUnit(%[[VAL_0]], %[[VAL_1]], %[[VAL_2]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite, errnoMem = none, targetMem0 = none, targetMem1 = none>, llvm.nocallback, llvm.nosync} : (i32, !fir.ref<i8>, i32) -> !fir.ref<i8> // CHECK: return %[[VAL_3]] : !fir.ref<i8> // CHECK: } func.func @test__FortranAioBeginOpenUnit(%arg0: i32, %arg1: !fir.ref<i8>, %arg2: i32) -> !fir.ref<i8> { @@ -291,7 +291,7 @@ module { // CHECK-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: i32, // CHECK-SAME: %[[VAL_1:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<i8>, // CHECK-SAME: %[[VAL_2:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: i32) -> !fir.ref<i8> { -// CHECK: %[[VAL_3:.*]] = fir.call @_FortranAioBeginRewind(%[[VAL_0]], %[[VAL_1]], %[[VAL_2]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite>, llvm.nocallback, llvm.nosync} : (i32, !fir.ref<i8>, i32) -> !fir.ref<i8> +// CHECK: %[[VAL_3:.*]] = fir.call @_FortranAioBeginRewind(%[[VAL_0]], %[[VAL_1]], %[[VAL_2]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite, errnoMem = none, targetMem0 = none, targetMem1 = none>, llvm.nocallback, llvm.nosync} : (i32, !fir.ref<i8>, i32) -> !fir.ref<i8> // CHECK: return %[[VAL_3]] : !fir.ref<i8> // CHECK: } func.func @test__FortranAioBeginRewind(%arg0: i32, %arg1: !fir.ref<i8>, %arg2: i32) -> !fir.ref<i8> { @@ -302,7 +302,7 @@ module { // CHECK-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: i32, // CHECK-SAME: %[[VAL_1:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<i8>, // CHECK-SAME: %[[VAL_2:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: i32) -> !fir.ref<i8> { -// CHECK: %[[VAL_3:.*]] = fir.call @_FortranAioBeginUnformattedInput(%[[VAL_0]], %[[VAL_1]], %[[VAL_2]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite>, llvm.nocallback, llvm.nosync} : (i32, !fir.ref<i8>, i32) -> !fir.ref<i8> +// CHECK: %[[VAL_3:.*]] = fir.call @_FortranAioBeginUnformattedInput(%[[VAL_0]], %[[VAL_1]], %[[VAL_2]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite, errnoMem = none, targetMem0 = none, targetMem1 = none>, llvm.nocallback, llvm.nosync} : (i32, !fir.ref<i8>, i32) -> !fir.ref<i8> // CHECK: return %[[VAL_3]] : !fir.ref<i8> // CHECK: } func.func @test__FortranAioBeginUnformattedInput(%arg0: i32, %arg1: !fir.ref<i8>, %arg2: i32) -> !fir.ref<i8> { @@ -313,7 +313,7 @@ module { // CHECK-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: i32, // CHECK-SAME: %[[VAL_1:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<i8>, // CHECK-SAME: %[[VAL_2:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: i32) -> !fir.ref<i8> { -// CHECK: %[[VAL_3:.*]] = fir.call @_FortranAioBeginUnformattedOutput(%[[VAL_0]], %[[VAL_1]], %[[VAL_2]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite>, llvm.nocallback, llvm.nosync} : (i32, !fir.ref<i8>, i32) -> !fir.ref<i8> +// CHECK: %[[VAL_3:.*]] = fir.call @_FortranAioBeginUnformattedOutput(%[[VAL_0]], %[[VAL_1]], %[[VAL_2]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite, errnoMem = none, targetMem0 = none, targetMem1 = none>, llvm.nocallback, llvm.nosync} : (i32, !fir.ref<i8>, i32) -> !fir.ref<i8> // CHECK: return %[[VAL_3]] : !fir.ref<i8> // CHECK: } func.func @test__FortranAioBeginUnformattedOutput(%arg0: i32, %arg1: !fir.ref<i8>, %arg2: i32) -> !fir.ref<i8> { @@ -325,7 +325,7 @@ module { // CHECK-SAME: %[[VAL_1:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: i32, // CHECK-SAME: %[[VAL_2:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<i8>, // CHECK-SAME: %[[VAL_3:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: i32) -> !fir.ref<i8> { -// CHECK: %[[VAL_4:.*]] = fir.call @_FortranAioBeginWait(%[[VAL_0]], %[[VAL_1]], %[[VAL_2]], %[[VAL_3]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite>, llvm.nocallback, llvm.nosync} : (i32, i32, !fir.ref<i8>, i32) -> !fir.ref<i8> +// CHECK: %[[VAL_4:.*]] = fir.call @_FortranAioBeginWait(%[[VAL_0]], %[[VAL_1]], %[[VAL_2]], %[[VAL_3]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite, errnoMem = none, targetMem0 = none, targetMem1 = none>, llvm.nocallback, llvm.nosync} : (i32, i32, !fir.ref<i8>, i32) -> !fir.ref<i8> // CHECK: return %[[VAL_4]] : !fir.ref<i8> // CHECK: } func.func @test__FortranAioBeginWait(%arg0: i32, %arg1: i32, %arg2: !fir.ref<i8>, %arg3: i32) -> !fir.ref<i8> { @@ -336,7 +336,7 @@ module { // CHECK-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: i32, // CHECK-SAME: %[[VAL_1:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<i8>, // CHECK-SAME: %[[VAL_2:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: i32) -> !fir.ref<i8> { -// CHECK: %[[VAL_3:.*]] = fir.call @_FortranAioBeginWaitAll(%[[VAL_0]], %[[VAL_1]], %[[VAL_2]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite>, llvm.nocallback, llvm.nosync} : (i32, !fir.ref<i8>, i32) -> !fir.ref<i8> +// CHECK: %[[VAL_3:.*]] = fir.call @_FortranAioBeginWaitAll(%[[VAL_0]], %[[VAL_1]], %[[VAL_2]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite, errnoMem = none, targetMem0 = none, targetMem1 = none>, llvm.nocallback, llvm.nosync} : (i32, !fir.ref<i8>, i32) -> !fir.ref<i8> // CHECK: return %[[VAL_3]] : !fir.ref<i8> // CHECK: } func.func @test__FortranAioBeginWaitAll(%arg0: i32, %arg1: !fir.ref<i8>, %arg2: i32) -> !fir.ref<i8> { @@ -350,7 +350,7 @@ module { // CHECK-SAME: %[[VAL_3:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: i64, // CHECK-SAME: %[[VAL_4:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<i8>, // CHECK-SAME: %[[VAL_5:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: i32) -> i32 { -// CHECK: %[[VAL_6:.*]] = fir.call @_FortranAioCheckUnitNumberInRange128(%[[VAL_0]], %[[VAL_1]], %[[VAL_2]], %[[VAL_3]], %[[VAL_4]], %[[VAL_5]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite>, llvm.nocallback, llvm.nosync} : (i128, i1, !fir.ref<i8>, i64, !fir.ref<i8>, i32) -> i32 +// CHECK: %[[VAL_6:.*]] = fir.call @_FortranAioCheckUnitNumberInRange128(%[[VAL_0]], %[[VAL_1]], %[[VAL_2]], %[[VAL_3]], %[[VAL_4]], %[[VAL_5]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite, errnoMem = none, targetMem0 = none, targetMem1 = none>, llvm.nocallback, llvm.nosync} : (i128, i1, !fir.ref<i8>, i64, !fir.ref<i8>, i32) -> i32 // CHECK: return %[[VAL_6]] : i32 // CHECK: } func.func @test__FortranAioCheckUnitNumberInRange128(%arg0: i128, %arg1: i1, %arg2: !fir.ref<i8>, %arg3: i64, %arg4: !fir.ref<i8>, %arg5: i32) -> i32 { @@ -364,7 +364,7 @@ module { // CHECK-SAME: %[[VAL_3:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: i64, // CHECK-SAME: %[[VAL_4:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<i8>, // CHECK-SAME: %[[VAL_5:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: i32) -> i32 { -// CHECK: %[[VAL_6:.*]] = fir.call @_FortranAioCheckUnitNumberInRange64(%[[VAL_0]], %[[VAL_1]], %[[VAL_2]], %[[VAL_3]], %[[VAL_4]], %[[VAL_5]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite>, llvm.nocallback, llvm.nosync} : (i64, i1, !fir.ref<i8>, i64, !fir.ref<i8>, i32) -> i32 +// CHECK: %[[VAL_6:.*]] = fir.call @_FortranAioCheckUnitNumberInRange64(%[[VAL_0]], %[[VAL_1]], %[[VAL_2]], %[[VAL_3]], %[[VAL_4]], %[[VAL_5]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite, errnoMem = none, targetMem0 = none, targetMem1 = none>, llvm.nocallback, llvm.nosync} : (i64, i1, !fir.ref<i8>, i64, !fir.ref<i8>, i32) -> i32 // CHECK: return %[[VAL_6]] : i32 // CHECK: } func.func @test__FortranAioCheckUnitNumberInRange64(%arg0: i64, %arg1: i1, %arg2: !fir.ref<i8>, %arg3: i64, %arg4: !fir.ref<i8>, %arg5: i32) -> i32 { @@ -378,7 +378,7 @@ module { // CHECK-SAME: %[[VAL_3:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: i1, // CHECK-SAME: %[[VAL_4:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: i1, // CHECK-SAME: %[[VAL_5:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: i1) { -// CHECK: fir.call @_FortranAioEnableHandlers(%[[VAL_0]], %[[VAL_1]], %[[VAL_2]], %[[VAL_3]], %[[VAL_4]], %[[VAL_5]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>, i1, i1, i1, i1, i1) -> () +// CHECK: fir.call @_FortranAioEnableHandlers(%[[VAL_0]], %[[VAL_1]], %[[VAL_2]], %[[VAL_3]], %[[VAL_4]], %[[VAL_5]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite, errnoMem = none, targetMem0 = none, targetMem1 = none>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>, i1, i1, i1, i1, i1) -> () // CHECK: return // CHECK: } func.func @test__FortranAioEnableHandlers(%arg0: !fir.ref<i8>, %arg1: i1, %arg2: i1, %arg3: i1, %arg4: i1, %arg5: i1) { @@ -387,7 +387,7 @@ module { } // CHECK-LABEL: func.func @test__FortranAioEndIoStatement( // CHECK-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<i8>) -> i32 { -// CHECK: %[[VAL_1:.*]] = fir.call @_FortranAioEndIoStatement(%[[VAL_0]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>) -> i32 +// CHECK: %[[VAL_1:.*]] = fir.call @_FortranAioEndIoStatement(%[[VAL_0]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite, errnoMem = none, targetMem0 = none, targetMem1 = none>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>) -> i32 // CHECK: return %[[VAL_1]] : i32 // CHECK: } func.func @test__FortranAioEndIoStatement(%arg0: !fir.ref<i8>) -> i32 { @@ -396,7 +396,7 @@ module { } // CHECK-LABEL: func.func @test__FortranAioGetAsynchronousId( // CHECK-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<i8>) -> i32 { -// CHECK: %[[VAL_1:.*]] = fir.call @_FortranAioGetAsynchronousId(%[[VAL_0]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>) -> i32 +// CHECK: %[[VAL_1:.*]] = fir.call @_FortranAioGetAsynchronousId(%[[VAL_0]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite, errnoMem = none, targetMem0 = none, targetMem1 = none>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>) -> i32 // CHECK: return %[[VAL_1]] : i32 // CHECK: } func.func @test__FortranAioGetAsynchronousId(%arg0: !fir.ref<i8>) -> i32 { @@ -405,7 +405,7 @@ module { } // CHECK-LABEL: func.func @test__FortranAioGetIoLength( // CHECK-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<i8>) -> i64 { -// CHECK: %[[VAL_1:.*]] = fir.call @_FortranAioGetIoLength(%[[VAL_0]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>) -> i64 +// CHECK: %[[VAL_1:.*]] = fir.call @_FortranAioGetIoLength(%[[VAL_0]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite, errnoMem = none, targetMem0 = none, targetMem1 = none>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>) -> i64 // CHECK: return %[[VAL_1]] : i64 // CHECK: } func.func @test__FortranAioGetIoLength(%arg0: !fir.ref<i8>) -> i64 { @@ -416,7 +416,7 @@ module { // CHECK-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<i8>, // CHECK-SAME: %[[VAL_1:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<i8>, // CHECK-SAME: %[[VAL_2:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: i64) { -// CHECK: fir.call @_FortranAioGetIoMsg(%[[VAL_0]], %[[VAL_1]], %[[VAL_2]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>, !fir.ref<i8>, i64) -> () +// CHECK: fir.call @_FortranAioGetIoMsg(%[[VAL_0]], %[[VAL_1]], %[[VAL_2]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite, errnoMem = none, targetMem0 = none, targetMem1 = none>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>, !fir.ref<i8>, i64) -> () // CHECK: return // CHECK: } func.func @test__FortranAioGetIoMsg(%arg0: !fir.ref<i8>, %arg1: !fir.ref<i8>, %arg2: i64) { @@ -427,7 +427,7 @@ module { // CHECK-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<i8>, // CHECK-SAME: %[[VAL_1:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<i32>, // CHECK-SAME: %[[VAL_2:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: i32) -> i1 { -// CHECK: %[[VAL_3:.*]] = fir.call @_FortranAioGetNewUnit(%[[VAL_0]], %[[VAL_1]], %[[VAL_2]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>, !fir.ref<i32>, i32) -> i1 +// CHECK: %[[VAL_3:.*]] = fir.call @_FortranAioGetNewUnit(%[[VAL_0]], %[[VAL_1]], %[[VAL_2]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite, errnoMem = none, targetMem0 = none, targetMem1 = none>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>, !fir.ref<i32>, i32) -> i1 // CHECK: return %[[VAL_3]] : i1 // CHECK: } func.func @test__FortranAioGetNewUnit(%arg0: !fir.ref<i8>, %arg1: !fir.ref<i32>, %arg2: i32) -> i1 { @@ -436,7 +436,7 @@ module { } // CHECK-LABEL: func.func @test__FortranAioGetSize( // CHECK-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<i8>) -> i64 { -// CHECK: %[[VAL_1:.*]] = fir.call @_FortranAioGetSize(%[[VAL_0]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>) -> i64 +// CHECK: %[[VAL_1:.*]] = fir.call @_FortranAioGetSize(%[[VAL_0]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite, errnoMem = none, targetMem0 = none, targetMem1 = none>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>) -> i64 // CHECK: return %[[VAL_1]] : i64 // CHECK: } func.func @test__FortranAioGetSize(%arg0: !fir.ref<i8>) -> i64 { @@ -447,7 +447,7 @@ module { // CHECK-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<i8>, // CHECK-SAME: %[[VAL_1:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<i8>, // CHECK-SAME: %[[VAL_2:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: i64) -> i1 { -// CHECK: %[[VAL_3:.*]] = fir.call @_FortranAioInputAscii(%[[VAL_0]], %[[VAL_1]], %[[VAL_2]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>, !fir.ref<i8>, i64) -> i1 +// CHECK: %[[VAL_3:.*]] = fir.call @_FortranAioInputAscii(%[[VAL_0]], %[[VAL_1]], %[[VAL_2]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite, errnoMem = none, targetMem0 = none, targetMem1 = none>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>, !fir.ref<i8>, i64) -> i1 // CHECK: return %[[VAL_3]] : i1 // CHECK: } func.func @test__FortranAioInputAscii(%arg0: !fir.ref<i8>, %arg1: !fir.ref<i8>, %arg2: i64) -> i1 { @@ -457,7 +457,7 @@ module { // CHECK-LABEL: func.func @test__FortranAioInputComplex32( // CHECK-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<i8>, // CHECK-SAME: %[[VAL_1:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<f32>) -> i1 { -// CHECK: %[[VAL_2:.*]] = fir.call @_FortranAioInputComplex32(%[[VAL_0]], %[[VAL_1]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>, !fir.ref<f32>) -> i1 +// CHECK: %[[VAL_2:.*]] = fir.call @_FortranAioInputComplex32(%[[VAL_0]], %[[VAL_1]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite, errnoMem = none, targetMem0 = none, targetMem1 = none>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>, !fir.ref<f32>) -> i1 // CHECK: return %[[VAL_2]] : i1 // CHECK: } func.func @test__FortranAioInputComplex32(%arg0: !fir.ref<i8>, %arg1: !fir.ref<f32>) -> i1 { @@ -467,7 +467,7 @@ module { // CHECK-LABEL: func.func @test__FortranAioInputComplex64( // CHECK-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<i8>, // CHECK-SAME: %[[VAL_1:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<f64>) -> i1 { -// CHECK: %[[VAL_2:.*]] = fir.call @_FortranAioInputComplex64(%[[VAL_0]], %[[VAL_1]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>, !fir.ref<f64>) -> i1 +// CHECK: %[[VAL_2:.*]] = fir.call @_FortranAioInputComplex64(%[[VAL_0]], %[[VAL_1]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite, errnoMem = none, targetMem0 = none, targetMem1 = none>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>, !fir.ref<f64>) -> i1 // CHECK: return %[[VAL_2]] : i1 // CHECK: } func.func @test__FortranAioInputComplex64(%arg0: !fir.ref<i8>, %arg1: !fir.ref<f64>) -> i1 { @@ -499,7 +499,7 @@ module { // CHECK-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<i8>, // CHECK-SAME: %[[VAL_1:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<i64>, // CHECK-SAME: %[[VAL_2:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: i32) -> i1 { -// CHECK: %[[VAL_3:.*]] = fir.call @_FortranAioInputInteger(%[[VAL_0]], %[[VAL_1]], %[[VAL_2]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>, !fir.ref<i64>, i32) -> i1 +// CHECK: %[[VAL_3:.*]] = fir.call @_FortranAioInputInteger(%[[VAL_0]], %[[VAL_1]], %[[VAL_2]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite, errnoMem = none, targetMem0 = none, targetMem1 = none>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>, !fir.ref<i64>, i32) -> i1 // CHECK: return %[[VAL_3]] : i1 // CHECK: } func.func @test__FortranAioInputInteger(%arg0: !fir.ref<i8>, %arg1: !fir.ref<i64>, %arg2: i32) -> i1 { @@ -509,7 +509,7 @@ module { // CHECK-LABEL: func.func @test__FortranAioInputLogical( // CHECK-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<i8>, // CHECK-SAME: %[[VAL_1:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<i1>) -> i1 { -// CHECK: %[[VAL_2:.*]] = fir.call @_FortranAioInputLogical(%[[VAL_0]], %[[VAL_1]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>, !fir.ref<i1>) -> i1 +// CHECK: %[[VAL_2:.*]] = fir.call @_FortranAioInputLogical(%[[VAL_0]], %[[VAL_1]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite, errnoMem = none, targetMem0 = none, targetMem1 = none>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>, !fir.ref<i1>) -> i1 // CHECK: return %[[VAL_2]] : i1 // CHECK: } func.func @test__FortranAioInputLogical(%arg0: !fir.ref<i8>, %arg1: !fir.ref<i1>) -> i1 { @@ -529,7 +529,7 @@ module { // CHECK-LABEL: func.func @test__FortranAioInputReal32( // CHECK-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<i8>, // CHECK-SAME: %[[VAL_1:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<f32>) -> i1 { -// CHECK: %[[VAL_2:.*]] = fir.call @_FortranAioInputReal32(%[[VAL_0]], %[[VAL_1]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>, !fir.ref<f32>) -> i1 +// CHECK: %[[VAL_2:.*]] = fir.call @_FortranAioInputReal32(%[[VAL_0]], %[[VAL_1]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite, errnoMem = none, targetMem0 = none, targetMem1 = none>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>, !fir.ref<f32>) -> i1 // CHECK: return %[[VAL_2]] : i1 // CHECK: } func.func @test__FortranAioInputReal32(%arg0: !fir.ref<i8>, %arg1: !fir.ref<f32>) -> i1 { @@ -539,7 +539,7 @@ module { // CHECK-LABEL: func.func @test__FortranAioInputReal64( // CHECK-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<i8>, // CHECK-SAME: %[[VAL_1:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<f64>) -> i1 { -// CHECK: %[[VAL_2:.*]] = fir.call @_FortranAioInputReal64(%[[VAL_0]], %[[VAL_1]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>, !fir.ref<f64>) -> i1 +// CHECK: %[[VAL_2:.*]] = fir.call @_FortranAioInputReal64(%[[VAL_0]], %[[VAL_1]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite, errnoMem = none, targetMem0 = none, targetMem1 = none>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>, !fir.ref<f64>) -> i1 // CHECK: return %[[VAL_2]] : i1 // CHECK: } func.func @test__FortranAioInputReal64(%arg0: !fir.ref<i8>, %arg1: !fir.ref<f64>) -> i1 { @@ -551,7 +551,7 @@ module { // CHECK-SAME: %[[VAL_1:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: i64, // CHECK-SAME: %[[VAL_2:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<i8>, // CHECK-SAME: %[[VAL_3:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: i64) -> i1 { -// CHECK: %[[VAL_4:.*]] = fir.call @_FortranAioInquireCharacter(%[[VAL_0]], %[[VAL_1]], %[[VAL_2]], %[[VAL_3]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>, i64, !fir.ref<i8>, i64) -> i1 +// CHECK: %[[VAL_4:.*]] = fir.call @_FortranAioInquireCharacter(%[[VAL_0]], %[[VAL_1]], %[[VAL_2]], %[[VAL_3]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite, errnoMem = none, targetMem0 = none, targetMem1 = none>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>, i64, !fir.ref<i8>, i64) -> i1 // CHECK: return %[[VAL_4]] : i1 // CHECK: } func.func @test__FortranAioInquireCharacter(%arg0: !fir.ref<i8>, %arg1: i64, %arg2: !fir.ref<i8>, %arg3: i64) -> i1 { @@ -563,7 +563,7 @@ module { // CHECK-SAME: %[[VAL_1:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: i64, // CHECK-SAME: %[[VAL_2:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<i64>, // CHECK-SAME: %[[VAL_3:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: i32) -> i1 { -// CHECK: %[[VAL_4:.*]] = fir.call @_FortranAioInquireInteger64(%[[VAL_0]], %[[VAL_1]], %[[VAL_2]], %[[VAL_3]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>, i64, !fir.ref<i64>, i32) -> i1 +// CHECK: %[[VAL_4:.*]] = fir.call @_FortranAioInquireInteger64(%[[VAL_0]], %[[VAL_1]], %[[VAL_2]], %[[VAL_3]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite, errnoMem = none, targetMem0 = none, targetMem1 = none>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>, i64, !fir.ref<i64>, i32) -> i1 // CHECK: return %[[VAL_4]] : i1 // CHECK: } func.func @test__FortranAioInquireInteger64(%arg0: !fir.ref<i8>, %arg1: i64, %arg2: !fir.ref<i64>, %arg3: i32) -> i1 { @@ -574,7 +574,7 @@ module { // CHECK-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<i8>, // CHECK-SAME: %[[VAL_1:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: i64, // CHECK-SAME: %[[VAL_2:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<i1>) -> i1 { -// CHECK: %[[VAL_3:.*]] = fir.call @_FortranAioInquireLogical(%[[VAL_0]], %[[VAL_1]], %[[VAL_2]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>, i64, !fir.ref<i1>) -> i1 +// CHECK: %[[VAL_3:.*]] = fir.call @_FortranAioInquireLogical(%[[VAL_0]], %[[VAL_1]], %[[VAL_2]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite, errnoMem = none, targetMem0 = none, targetMem1 = none>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>, i64, !fir.ref<i1>) -> i1 // CHECK: return %[[VAL_3]] : i1 // CHECK: } func.func @test__FortranAioInquireLogical(%arg0: !fir.ref<i8>, %arg1: i64, %arg2: !fir.ref<i1>) -> i1 { @@ -585,7 +585,7 @@ module { // CHECK-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<i8>, // CHECK-SAME: %[[VAL_1:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: i32, // CHECK-SAME: %[[VAL_2:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<i1>) -> i1 { -// CHECK: %[[VAL_3:.*]] = fir.call @_FortranAioInquirePendingId(%[[VAL_0]], %[[VAL_1]], %[[VAL_2]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>, i32, !fir.ref<i1>) -> i1 +// CHECK: %[[VAL_3:.*]] = fir.call @_FortranAioInquirePendingId(%[[VAL_0]], %[[VAL_1]], %[[VAL_2]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite, errnoMem = none, targetMem0 = none, targetMem1 = none>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>, i32, !fir.ref<i1>) -> i1 // CHECK: return %[[VAL_3]] : i1 // CHECK: } func.func @test__FortranAioInquirePendingId(%arg0: !fir.ref<i8>, %arg1: i32, %arg2: !fir.ref<i1>) -> i1 { @@ -596,7 +596,7 @@ module { // CHECK-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<i8>, // CHECK-SAME: %[[VAL_1:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<i8>, // CHECK-SAME: %[[VAL_2:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: i64) -> i1 { -// CHECK: %[[VAL_3:.*]] = fir.call @_FortranAioOutputAscii(%[[VAL_0]], %[[VAL_1]], %[[VAL_2]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>, !fir.ref<i8>, i64) -> i1 +// CHECK: %[[VAL_3:.*]] = fir.call @_FortranAioOutputAscii(%[[VAL_0]], %[[VAL_1]], %[[VAL_2]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite, errnoMem = none, targetMem0 = none, targetMem1 = none>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>, !fir.ref<i8>, i64) -> i1 // CHECK: return %[[VAL_3]] : i1 // CHECK: } func.func @test__FortranAioOutputAscii(%arg0: !fir.ref<i8>, %arg1: !fir.ref<i8>, %arg2: i64) -> i1 { @@ -607,7 +607,7 @@ module { // CHECK-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<i8>, // CHECK-SAME: %[[VAL_1:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: f32, // CHECK-SAME: %[[VAL_2:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: f32) -> i1 { -// CHECK: %[[VAL_3:.*]] = fir.call @_FortranAioOutputComplex32(%[[VAL_0]], %[[VAL_1]], %[[VAL_2]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>, f32, f32) -> i1 +// CHECK: %[[VAL_3:.*]] = fir.call @_FortranAioOutputComplex32(%[[VAL_0]], %[[VAL_1]], %[[VAL_2]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite, errnoMem = none, targetMem0 = none, targetMem1 = none>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>, f32, f32) -> i1 // CHECK: return %[[VAL_3]] : i1 // CHECK: } func.func @test__FortranAioOutputComplex32(%arg0: !fir.ref<i8>, %arg1: f32, %arg2: f32) -> i1 { @@ -618,7 +618,7 @@ module { // CHECK-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<i8>, // CHECK-SAME: %[[VAL_1:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: f64, // CHECK-SAME: %[[VAL_2:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: f64) -> i1 { -// CHECK: %[[VAL_3:.*]] = fir.call @_FortranAioOutputComplex64(%[[VAL_0]], %[[VAL_1]], %[[VAL_2]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>, f64, f64) -> i1 +// CHECK: %[[VAL_3:.*]] = fir.call @_FortranAioOutputComplex64(%[[VAL_0]], %[[VAL_1]], %[[VAL_2]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite, errnoMem = none, targetMem0 = none, targetMem1 = none>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>, f64, f64) -> i1 // CHECK: return %[[VAL_3]] : i1 // CHECK: } func.func @test__FortranAioOutputComplex64(%arg0: !fir.ref<i8>, %arg1: f64, %arg2: f64) -> i1 { @@ -649,7 +649,7 @@ module { // CHECK-LABEL: func.func @test__FortranAioOutputInteger128( // CHECK-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<i8>, // CHECK-SAME: %[[VAL_1:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: i128) -> i1 { -// CHECK: %[[VAL_2:.*]] = fir.call @_FortranAioOutputInteger128(%[[VAL_0]], %[[VAL_1]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>, i128) -> i1 +// CHECK: %[[VAL_2:.*]] = fir.call @_FortranAioOutputInteger128(%[[VAL_0]], %[[VAL_1]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite, errnoMem = none, targetMem0 = none, targetMem1 = none>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>, i128) -> i1 // CHECK: return %[[VAL_2]] : i1 // CHECK: } func.func @test__FortranAioOutputInteger128(%arg0: !fir.ref<i8>, %arg1: i128) -> i1 { @@ -659,7 +659,7 @@ module { // CHECK-LABEL: func.func @test__FortranAioOutputInteger16( // CHECK-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<i8>, // CHECK-SAME: %[[VAL_1:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: i16) -> i1 { -// CHECK: %[[VAL_2:.*]] = fir.call @_FortranAioOutputInteger16(%[[VAL_0]], %[[VAL_1]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>, i16) -> i1 +// CHECK: %[[VAL_2:.*]] = fir.call @_FortranAioOutputInteger16(%[[VAL_0]], %[[VAL_1]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite, errnoMem = none, targetMem0 = none, targetMem1 = none>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>, i16) -> i1 // CHECK: return %[[VAL_2]] : i1 // CHECK: } func.func @test__FortranAioOutputInteger16(%arg0: !fir.ref<i8>, %arg1: i16) -> i1 { @@ -669,7 +669,7 @@ module { // CHECK-LABEL: func.func @test__FortranAioOutputInteger32( // CHECK-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<i8>, // CHECK-SAME: %[[VAL_1:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: i32) -> i1 { -// CHECK: %[[VAL_2:.*]] = fir.call @_FortranAioOutputInteger32(%[[VAL_0]], %[[VAL_1]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>, i32) -> i1 +// CHECK: %[[VAL_2:.*]] = fir.call @_FortranAioOutputInteger32(%[[VAL_0]], %[[VAL_1]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite, errnoMem = none, targetMem0 = none, targetMem1 = none>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>, i32) -> i1 // CHECK: return %[[VAL_2]] : i1 // CHECK: } func.func @test__FortranAioOutputInteger32(%arg0: !fir.ref<i8>, %arg1: i32) -> i1 { @@ -679,7 +679,7 @@ module { // CHECK-LABEL: func.func @test__FortranAioOutputInteger64( // CHECK-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<i8>, // CHECK-SAME: %[[VAL_1:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: i64) -> i1 { -// CHECK: %[[VAL_2:.*]] = fir.call @_FortranAioOutputInteger64(%[[VAL_0]], %[[VAL_1]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>, i64) -> i1 +// CHECK: %[[VAL_2:.*]] = fir.call @_FortranAioOutputInteger64(%[[VAL_0]], %[[VAL_1]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite, errnoMem = none, targetMem0 = none, targetMem1 = none>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>, i64) -> i1 // CHECK: return %[[VAL_2]] : i1 // CHECK: } func.func @test__FortranAioOutputInteger64(%arg0: !fir.ref<i8>, %arg1: i64) -> i1 { @@ -689,7 +689,7 @@ module { // CHECK-LABEL: func.func @test__FortranAioOutputInteger8( // CHECK-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<i8>, // CHECK-SAME: %[[VAL_1:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: i8) -> i1 { -// CHECK: %[[VAL_2:.*]] = fir.call @_FortranAioOutputInteger8(%[[VAL_0]], %[[VAL_1]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>, i8) -> i1 +// CHECK: %[[VAL_2:.*]] = fir.call @_FortranAioOutputInteger8(%[[VAL_0]], %[[VAL_1]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite, errnoMem = none, targetMem0 = none, targetMem1 = none>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>, i8) -> i1 // CHECK: return %[[VAL_2]] : i1 // CHECK: } func.func @test__FortranAioOutputInteger8(%arg0: !fir.ref<i8>, %arg1: i8) -> i1 { @@ -699,7 +699,7 @@ module { // CHECK-LABEL: func.func @test__FortranAioOutputLogical( // CHECK-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<i8>, // CHECK-SAME: %[[VAL_1:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: i1) -> i1 { -// CHECK: %[[VAL_2:.*]] = fir.call @_FortranAioOutputLogical(%[[VAL_0]], %[[VAL_1]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>, i1) -> i1 +// CHECK: %[[VAL_2:.*]] = fir.call @_FortranAioOutputLogical(%[[VAL_0]], %[[VAL_1]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite, errnoMem = none, targetMem0 = none, targetMem1 = none>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>, i1) -> i1 // CHECK: return %[[VAL_2]] : i1 // CHECK: } func.func @test__FortranAioOutputLogical(%arg0: !fir.ref<i8>, %arg1: i1) -> i1 { @@ -719,7 +719,7 @@ module { // CHECK-LABEL: func.func @test__FortranAioOutputReal32( // CHECK-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<i8>, // CHECK-SAME: %[[VAL_1:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: f32) -> i1 { -// CHECK: %[[VAL_2:.*]] = fir.call @_FortranAioOutputReal32(%[[VAL_0]], %[[VAL_1]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>, f32) -> i1 +// CHECK: %[[VAL_2:.*]] = fir.call @_FortranAioOutputReal32(%[[VAL_0]], %[[VAL_1]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite, errnoMem = none, targetMem0 = none, targetMem1 = none>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>, f32) -> i1 // CHECK: return %[[VAL_2]] : i1 // CHECK: } func.func @test__FortranAioOutputReal32(%arg0: !fir.ref<i8>, %arg1: f32) -> i1 { @@ -729,7 +729,7 @@ module { // CHECK-LABEL: func.func @test__FortranAioOutputReal64( // CHECK-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<i8>, // CHECK-SAME: %[[VAL_1:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: f64) -> i1 { -// CHECK: %[[VAL_2:.*]] = fir.call @_FortranAioOutputReal64(%[[VAL_0]], %[[VAL_1]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>, f64) -> i1 +// CHECK: %[[VAL_2:.*]] = fir.call @_FortranAioOutputReal64(%[[VAL_0]], %[[VAL_1]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite, errnoMem = none, targetMem0 = none, targetMem1 = none>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>, f64) -> i1 // CHECK: return %[[VAL_2]] : i1 // CHECK: } func.func @test__FortranAioOutputReal64(%arg0: !fir.ref<i8>, %arg1: f64) -> i1 { @@ -740,7 +740,7 @@ module { // CHECK-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<i8>, // CHECK-SAME: %[[VAL_1:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<i8>, // CHECK-SAME: %[[VAL_2:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: i64) -> i1 { -// CHECK: %[[VAL_3:.*]] = fir.call @_FortranAioSetAccess(%[[VAL_0]], %[[VAL_1]], %[[VAL_2]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>, !fir.ref<i8>, i64) -> i1 +// CHECK: %[[VAL_3:.*]] = fir.call @_FortranAioSetAccess(%[[VAL_0]], %[[VAL_1]], %[[VAL_2]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite, errnoMem = none, targetMem0 = none, targetMem1 = none>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>, !fir.ref<i8>, i64) -> i1 // CHECK: return %[[VAL_3]] : i1 // CHECK: } func.func @test__FortranAioSetAccess(%arg0: !fir.ref<i8>, %arg1: !fir.ref<i8>, %arg2: i64) -> i1 { @@ -751,7 +751,7 @@ module { // CHECK-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<i8>, // CHECK-SAME: %[[VAL_1:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<i8>, // CHECK-SAME: %[[VAL_2:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: i64) -> i1 { -// CHECK: %[[VAL_3:.*]] = fir.call @_FortranAioSetAction(%[[VAL_0]], %[[VAL_1]], %[[VAL_2]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>, !fir.ref<i8>, i64) -> i1 +// CHECK: %[[VAL_3:.*]] = fir.call @_FortranAioSetAction(%[[VAL_0]], %[[VAL_1]], %[[VAL_2]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite, errnoMem = none, targetMem0 = none, targetMem1 = none>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>, !fir.ref<i8>, i64) -> i1 // CHECK: return %[[VAL_3]] : i1 // CHECK: } func.func @test__FortranAioSetAction(%arg0: !fir.ref<i8>, %arg1: !fir.ref<i8>, %arg2: i64) -> i1 { @@ -762,7 +762,7 @@ module { // CHECK-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<i8>, // CHECK-SAME: %[[VAL_1:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<i8>, // CHECK-SAME: %[[VAL_2:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: i64) -> i1 { -// CHECK: %[[VAL_3:.*]] = fir.call @_FortranAioSetAdvance(%[[VAL_0]], %[[VAL_1]], %[[VAL_2]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>, !fir.ref<i8>, i64) -> i1 +// CHECK: %[[VAL_3:.*]] = fir.call @_FortranAioSetAdvance(%[[VAL_0]], %[[VAL_1]], %[[VAL_2]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite, errnoMem = none, targetMem0 = none, targetMem1 = none>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>, !fir.ref<i8>, i64) -> i1 // CHECK: return %[[VAL_3]] : i1 // CHECK: } func.func @test__FortranAioSetAdvance(%arg0: !fir.ref<i8>, %arg1: !fir.ref<i8>, %arg2: i64) -> i1 { @@ -773,7 +773,7 @@ module { // CHECK-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<i8>, // CHECK-SAME: %[[VAL_1:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<i8>, // CHECK-SAME: %[[VAL_2:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: i64) -> i1 { -// CHECK: %[[VAL_3:.*]] = fir.call @_FortranAioSetAsynchronous(%[[VAL_0]], %[[VAL_1]], %[[VAL_2]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>, !fir.ref<i8>, i64) -> i1 +// CHECK: %[[VAL_3:.*]] = fir.call @_FortranAioSetAsynchronous(%[[VAL_0]], %[[VAL_1]], %[[VAL_2]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite, errnoMem = none, targetMem0 = none, targetMem1 = none>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>, !fir.ref<i8>, i64) -> i1 // CHECK: return %[[VAL_3]] : i1 // CHECK: } func.func @test__FortranAioSetAsynchronous(%arg0: !fir.ref<i8>, %arg1: !fir.ref<i8>, %arg2: i64) -> i1 { @@ -784,7 +784,7 @@ module { // CHECK-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<i8>, // CHECK-SAME: %[[VAL_1:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<i8>, // CHECK-SAME: %[[VAL_2:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: i64) -> i1 { -// CHECK: %[[VAL_3:.*]] = fir.call @_FortranAioSetBlank(%[[VAL_0]], %[[VAL_1]], %[[VAL_2]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>, !fir.ref<i8>, i64) -> i1 +// CHECK: %[[VAL_3:.*]] = fir.call @_FortranAioSetBlank(%[[VAL_0]], %[[VAL_1]], %[[VAL_2]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite, errnoMem = none, targetMem0 = none, targetMem1 = none>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>, !fir.ref<i8>, i64) -> i1 // CHECK: return %[[VAL_3]] : i1 // CHECK: } func.func @test__FortranAioSetBlank(%arg0: !fir.ref<i8>, %arg1: !fir.ref<i8>, %arg2: i64) -> i1 { @@ -795,7 +795,7 @@ module { // CHECK-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<i8>, // CHECK-SAME: %[[VAL_1:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<i8>, // CHECK-SAME: %[[VAL_2:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: i64) -> i1 { -// CHECK: %[[VAL_3:.*]] = fir.call @_FortranAioSetCarriagecontrol(%[[VAL_0]], %[[VAL_1]], %[[VAL_2]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>, !fir.ref<i8>, i64) -> i1 +// CHECK: %[[VAL_3:.*]] = fir.call @_FortranAioSetCarriagecontrol(%[[VAL_0]], %[[VAL_1]], %[[VAL_2]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite, errnoMem = none, targetMem0 = none, targetMem1 = none>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>, !fir.ref<i8>, i64) -> i1 // CHECK: return %[[VAL_3]] : i1 // CHECK: } func.func @test__FortranAioSetCarriagecontrol(%arg0: !fir.ref<i8>, %arg1: !fir.ref<i8>, %arg2: i64) -> i1 { @@ -806,7 +806,7 @@ module { // CHECK-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<i8>, // CHECK-SAME: %[[VAL_1:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<i8>, // CHECK-SAME: %[[VAL_2:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: i64) -> i1 { -// CHECK: %[[VAL_3:.*]] = fir.call @_FortranAioSetConvert(%[[VAL_0]], %[[VAL_1]], %[[VAL_2]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>, !fir.ref<i8>, i64) -> i1 +// CHECK: %[[VAL_3:.*]] = fir.call @_FortranAioSetConvert(%[[VAL_0]], %[[VAL_1]], %[[VAL_2]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite, errnoMem = none, targetMem0 = none, targetMem1 = none>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>, !fir.ref<i8>, i64) -> i1 // CHECK: return %[[VAL_3]] : i1 // CHECK: } func.func @test__FortranAioSetConvert(%arg0: !fir.ref<i8>, %arg1: !fir.ref<i8>, %arg2: i64) -> i1 { @@ -817,7 +817,7 @@ module { // CHECK-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<i8>, // CHECK-SAME: %[[VAL_1:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<i8>, // CHECK-SAME: %[[VAL_2:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: i64) -> i1 { -// CHECK: %[[VAL_3:.*]] = fir.call @_FortranAioSetDecimal(%[[VAL_0]], %[[VAL_1]], %[[VAL_2]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>, !fir.ref<i8>, i64) -> i1 +// CHECK: %[[VAL_3:.*]] = fir.call @_FortranAioSetDecimal(%[[VAL_0]], %[[VAL_1]], %[[VAL_2]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite, errnoMem = none, targetMem0 = none, targetMem1 = none>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>, !fir.ref<i8>, i64) -> i1 // CHECK: return %[[VAL_3]] : i1 // CHECK: } func.func @test__FortranAioSetDecimal(%arg0: !fir.ref<i8>, %arg1: !fir.ref<i8>, %arg2: i64) -> i1 { @@ -828,7 +828,7 @@ module { // CHECK-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<i8>, // CHECK-SAME: %[[VAL_1:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<i8>, // CHECK-SAME: %[[VAL_2:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: i64) -> i1 { -// CHECK: %[[VAL_3:.*]] = fir.call @_FortranAioSetDelim(%[[VAL_0]], %[[VAL_1]], %[[VAL_2]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>, !fir.ref<i8>, i64) -> i1 +// CHECK: %[[VAL_3:.*]] = fir.call @_FortranAioSetDelim(%[[VAL_0]], %[[VAL_1]], %[[VAL_2]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite, errnoMem = none, targetMem0 = none, targetMem1 = none>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>, !fir.ref<i8>, i64) -> i1 // CHECK: return %[[VAL_3]] : i1 // CHECK: } func.func @test__FortranAioSetDelim(%arg0: !fir.ref<i8>, %arg1: !fir.ref<i8>, %arg2: i64) -> i1 { @@ -839,7 +839,7 @@ module { // CHECK-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<i8>, // CHECK-SAME: %[[VAL_1:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<i8>, // CHECK-SAME: %[[VAL_2:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: i64) -> i1 { -// CHECK: %[[VAL_3:.*]] = fir.call @_FortranAioSetEncoding(%[[VAL_0]], %[[VAL_1]], %[[VAL_2]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>, !fir.ref<i8>, i64) -> i1 +// CHECK: %[[VAL_3:.*]] = fir.call @_FortranAioSetEncoding(%[[VAL_0]], %[[VAL_1]], %[[VAL_2]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite, errnoMem = none, targetMem0 = none, targetMem1 = none>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>, !fir.ref<i8>, i64) -> i1 // CHECK: return %[[VAL_3]] : i1 // CHECK: } func.func @test__FortranAioSetEncoding(%arg0: !fir.ref<i8>, %arg1: !fir.ref<i8>, %arg2: i64) -> i1 { @@ -850,7 +850,7 @@ module { // CHECK-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<i8>, // CHECK-SAME: %[[VAL_1:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<i8>, // CHECK-SAME: %[[VAL_2:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: i64) -> i1 { -// CHECK: %[[VAL_3:.*]] = fir.call @_FortranAioSetFile(%[[VAL_0]], %[[VAL_1]], %[[VAL_2]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>, !fir.ref<i8>, i64) -> i1 +// CHECK: %[[VAL_3:.*]] = fir.call @_FortranAioSetFile(%[[VAL_0]], %[[VAL_1]], %[[VAL_2]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite, errnoMem = none, targetMem0 = none, targetMem1 = none>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>, !fir.ref<i8>, i64) -> i1 // CHECK: return %[[VAL_3]] : i1 // CHECK: } func.func @test__FortranAioSetFile(%arg0: !fir.ref<i8>, %arg1: !fir.ref<i8>, %arg2: i64) -> i1 { @@ -861,7 +861,7 @@ module { // CHECK-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<i8>, // CHECK-SAME: %[[VAL_1:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<i8>, // CHECK-SAME: %[[VAL_2:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: i64) -> i1 { -// CHECK: %[[VAL_3:.*]] = fir.call @_FortranAioSetForm(%[[VAL_0]], %[[VAL_1]], %[[VAL_2]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>, !fir.ref<i8>, i64) -> i1 +// CHECK: %[[VAL_3:.*]] = fir.call @_FortranAioSetForm(%[[VAL_0]], %[[VAL_1]], %[[VAL_2]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite, errnoMem = none, targetMem0 = none, targetMem1 = none>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>, !fir.ref<i8>, i64) -> i1 // CHECK: return %[[VAL_3]] : i1 // CHECK: } func.func @test__FortranAioSetForm(%arg0: !fir.ref<i8>, %arg1: !fir.ref<i8>, %arg2: i64) -> i1 { @@ -872,7 +872,7 @@ module { // CHECK-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<i8>, // CHECK-SAME: %[[VAL_1:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<i8>, // CHECK-SAME: %[[VAL_2:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: i64) -> i1 { -// CHECK: %[[VAL_3:.*]] = fir.call @_FortranAioSetPad(%[[VAL_0]], %[[VAL_1]], %[[VAL_2]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>, !fir.ref<i8>, i64) -> i1 +// CHECK: %[[VAL_3:.*]] = fir.call @_FortranAioSetPad(%[[VAL_0]], %[[VAL_1]], %[[VAL_2]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite, errnoMem = none, targetMem0 = none, targetMem1 = none>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>, !fir.ref<i8>, i64) -> i1 // CHECK: return %[[VAL_3]] : i1 // CHECK: } func.func @test__FortranAioSetPad(%arg0: !fir.ref<i8>, %arg1: !fir.ref<i8>, %arg2: i64) -> i1 { @@ -882,7 +882,7 @@ module { // CHECK-LABEL: func.func @test__FortranAioSetPos( // CHECK-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<i8>, // CHECK-SAME: %[[VAL_1:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: i64) -> i1 { -// CHECK: %[[VAL_2:.*]] = fir.call @_FortranAioSetPos(%[[VAL_0]], %[[VAL_1]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>, i64) -> i1 +// CHECK: %[[VAL_2:.*]] = fir.call @_FortranAioSetPos(%[[VAL_0]], %[[VAL_1]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite, errnoMem = none, targetMem0 = none, targetMem1 = none>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>, i64) -> i1 // CHECK: return %[[VAL_2]] : i1 // CHECK: } func.func @test__FortranAioSetPos(%arg0: !fir.ref<i8>, %arg1: i64) -> i1 { @@ -893,7 +893,7 @@ module { // CHECK-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<i8>, // CHECK-SAME: %[[VAL_1:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<i8>, // CHECK-SAME: %[[VAL_2:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: i64) -> i1 { -// CHECK: %[[VAL_3:.*]] = fir.call @_FortranAioSetPosition(%[[VAL_0]], %[[VAL_1]], %[[VAL_2]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>, !fir.ref<i8>, i64) -> i1 +// CHECK: %[[VAL_3:.*]] = fir.call @_FortranAioSetPosition(%[[VAL_0]], %[[VAL_1]], %[[VAL_2]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite, errnoMem = none, targetMem0 = none, targetMem1 = none>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>, !fir.ref<i8>, i64) -> i1 // CHECK: return %[[VAL_3]] : i1 // CHECK: } func.func @test__FortranAioSetPosition(%arg0: !fir.ref<i8>, %arg1: !fir.ref<i8>, %arg2: i64) -> i1 { @@ -903,7 +903,7 @@ module { // CHECK-LABEL: func.func @test__FortranAioSetRec( // CHECK-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<i8>, // CHECK-SAME: %[[VAL_1:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: i64) -> i1 { -// CHECK: %[[VAL_2:.*]] = fir.call @_FortranAioSetRec(%[[VAL_0]], %[[VAL_1]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>, i64) -> i1 +// CHECK: %[[VAL_2:.*]] = fir.call @_FortranAioSetRec(%[[VAL_0]], %[[VAL_1]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite, errnoMem = none, targetMem0 = none, targetMem1 = none>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>, i64) -> i1 // CHECK: return %[[VAL_2]] : i1 // CHECK: } func.func @test__FortranAioSetRec(%arg0: !fir.ref<i8>, %arg1: i64) -> i1 { @@ -913,7 +913,7 @@ module { // CHECK-LABEL: func.func @test__FortranAioSetRecl( // CHECK-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<i8>, // CHECK-SAME: %[[VAL_1:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: i64) -> i1 { -// CHECK: %[[VAL_2:.*]] = fir.call @_FortranAioSetRecl(%[[VAL_0]], %[[VAL_1]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>, i64) -> i1 +// CHECK: %[[VAL_2:.*]] = fir.call @_FortranAioSetRecl(%[[VAL_0]], %[[VAL_1]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite, errnoMem = none, targetMem0 = none, targetMem1 = none>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>, i64) -> i1 // CHECK: return %[[VAL_2]] : i1 // CHECK: } func.func @test__FortranAioSetRecl(%arg0: !fir.ref<i8>, %arg1: i64) -> i1 { @@ -924,7 +924,7 @@ module { // CHECK-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<i8>, // CHECK-SAME: %[[VAL_1:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<i8>, // CHECK-SAME: %[[VAL_2:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: i64) -> i1 { -// CHECK: %[[VAL_3:.*]] = fir.call @_FortranAioSetRound(%[[VAL_0]], %[[VAL_1]], %[[VAL_2]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>, !fir.ref<i8>, i64) -> i1 +// CHECK: %[[VAL_3:.*]] = fir.call @_FortranAioSetRound(%[[VAL_0]], %[[VAL_1]], %[[VAL_2]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite, errnoMem = none, targetMem0 = none, targetMem1 = none>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>, !fir.ref<i8>, i64) -> i1 // CHECK: return %[[VAL_3]] : i1 // CHECK: } func.func @test__FortranAioSetRound(%arg0: !fir.ref<i8>, %arg1: !fir.ref<i8>, %arg2: i64) -> i1 { @@ -935,7 +935,7 @@ module { // CHECK-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<i8>, // CHECK-SAME: %[[VAL_1:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<i8>, // CHECK-SAME: %[[VAL_2:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: i64) -> i1 { -// CHECK: %[[VAL_3:.*]] = fir.call @_FortranAioSetSign(%[[VAL_0]], %[[VAL_1]], %[[VAL_2]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>, !fir.ref<i8>, i64) -> i1 +// CHECK: %[[VAL_3:.*]] = fir.call @_FortranAioSetSign(%[[VAL_0]], %[[VAL_1]], %[[VAL_2]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite, errnoMem = none, targetMem0 = none, targetMem1 = none>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>, !fir.ref<i8>, i64) -> i1 // CHECK: return %[[VAL_3]] : i1 // CHECK: } func.func @test__FortranAioSetSign(%arg0: !fir.ref<i8>, %arg1: !fir.ref<i8>, %arg2: i64) -> i1 { @@ -946,7 +946,7 @@ module { // CHECK-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<i8>, // CHECK-SAME: %[[VAL_1:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<i8>, // CHECK-SAME: %[[VAL_2:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: i64) -> i1 { -// CHECK: %[[VAL_3:.*]] = fir.call @_FortranAioSetStatus(%[[VAL_0]], %[[VAL_1]], %[[VAL_2]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>, !fir.ref<i8>, i64) -> i1 +// CHECK: %[[VAL_3:.*]] = fir.call @_FortranAioSetStatus(%[[VAL_0]], %[[VAL_1]], %[[VAL_2]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite, errnoMem = none, targetMem0 = none, targetMem1 = none>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>, !fir.ref<i8>, i64) -> i1 // CHECK: return %[[VAL_3]] : i1 // CHECK: } func.func @test__FortranAioSetStatus(%arg0: !fir.ref<i8>, %arg1: !fir.ref<i8>, %arg2: i64) -> i1 { diff --git a/flang/test/Transforms/stack-arrays.fir b/flang/test/Transforms/stack-arrays.fir index 4a417ed..25fc731 100644 --- a/flang/test/Transforms/stack-arrays.fir +++ b/flang/test/Transforms/stack-arrays.fir @@ -3,13 +3,17 @@ // Simplest transformation func.func @simple() { %0 = fir.allocmem !fir.array<42xi32> + %c0_s = arith.constant 0 : index + %c0_i32_s = arith.constant 0 : i32 + %ref_s = fir.convert %0 : (!fir.heap<!fir.array<42xi32>>) -> !fir.ref<!fir.array<42xi32>> + %elt_s = fir.coordinate_of %ref_s, %c0_s : (!fir.ref<!fir.array<42xi32>>, index) -> !fir.ref<i32> + fir.store %c0_i32_s to %elt_s : !fir.ref<i32> fir.freemem %0 : !fir.heap<!fir.array<42xi32>> return } -// CHECK: func.func @simple() { -// CHECK-NEXT: fir.alloca !fir.array<42xi32> -// CHECK-NEXT: return -// CHECK-NEXT: } +// CHECK: func.func @simple() +// CHECK: fir.alloca !fir.array<42xi32> +// CHECK: return // Check fir.must_be_heap allocations are not moved func.func @must_be_heap() { @@ -17,7 +21,7 @@ func.func @must_be_heap() { fir.freemem %0 : !fir.heap<!fir.array<42xi32>> return } -// CHECK: func.func @must_be_heap() { +// CHECK-LABEL: func.func @must_be_heap() // CHECK-NEXT: %[[ALLOC:.*]] = fir.allocmem !fir.array<42xi32> {fir.must_be_heap = true} // CHECK-NEXT: fir.freemem %[[ALLOC]] : !fir.heap<!fir.array<42xi32>> // CHECK-NEXT: return @@ -36,7 +40,7 @@ func.func @dfa1(%arg0: !fir.ref<!fir.logical<4>> {fir.bindc_name = "cond"}) { } return } -// CHECK: func.func @dfa1(%arg0: !fir.ref<!fir.logical<4>> {fir.bindc_name = "cond"}) { +// CHECK-LABEL: func.func @dfa1(%arg0: !fir.ref<!fir.logical<4>> {fir.bindc_name = "cond"}) // CHECK-NEXT: %[[C42:.*]] = arith.constant 42 : index // CHECK-NEXT: %[[MEM:.*]] = fir.allocmem !fir.array<?xi32>, %[[C42]] {uniq_name = "_QFdfa1Earr.alloc"} // CHECK-NEXT: %[[LOGICAL:.*]] = fir.load %arg0 : !fir.ref<!fir.logical<4>> @@ -57,7 +61,7 @@ func.func @dfa2(%arg0: i1) { } return } -// CHECK: func.func @dfa2(%arg0: i1) { +// CHECK-LABEL: func.func @dfa2(%arg0: i1) // CHECK-NEXT: %[[MEM:.*]] = fir.allocmem !fir.array<1xi8> // CHECK-NEXT: scf.if %arg0 { // CHECK-NEXT: fir.freemem %[[MEM]] : !fir.heap<!fir.array<1xi8>> @@ -74,15 +78,16 @@ func.func @dfa3(%arg0: i1) { } else { fir.freemem %a : !fir.heap<!fir.array<1xi8>> } + %c0_d3 = arith.constant 0 : index + %c0_i8_d3 = arith.constant 0 : i8 + %ref_d3 = fir.convert %a : (!fir.heap<!fir.array<1xi8>>) -> !fir.ref<!fir.array<1xi8>> + %elt_d3 = fir.coordinate_of %ref_d3, %c0_d3 : (!fir.ref<!fir.array<1xi8>>, index) -> !fir.ref<i8> + fir.store %c0_i8_d3 to %elt_d3 : !fir.ref<i8> return } -// CHECK: func.func @dfa3(%arg0: i1) { -// CHECK-NEXT: %[[MEM:.*]] = fir.alloca !fir.array<1xi8> -// CHECK-NEXT: fir.if %arg0 { -// CHECK-NEXT: } else { -// CHECK-NEXT: } -// CHECK-NEXT: return -// CHECK-NEXT: } +// CHECK: func.func @dfa3(%arg0: i1) +// CHECK: %[[MEM:.*]] = fir.alloca !fir.array<1xi8> +// CHECK: return func.func private @dfa3a_foo(!fir.ref<!fir.array<1xi8>>) -> () func.func private @dfa3a_bar(!fir.ref<!fir.array<1xi8>>) -> () @@ -101,7 +106,7 @@ func.func @dfa3a(%arg0: i1) { } return } -// CHECK: func.func @dfa3a(%arg0: i1) { +// CHECK-LABEL: func.func @dfa3a(%arg0: i1) // CHECK-NEXT: %[[MEM:.*]] = fir.alloca !fir.array<1xi8> // CHECK-NEXT: %[[HEAP:.*]] = fir.convert %[[MEM]] : (!fir.ref<!fir.array<1xi8>>) -> !fir.heap<!fir.array<1xi8>> // CHECK-NEXT: fir.if %arg0 { @@ -123,13 +128,18 @@ func.func @placement1() { // operand is now available %4 = fir.allocmem !fir.array<?xi32>, %3 // ... + %c0 = arith.constant 0 : index + %c0_i32 = arith.constant 0 : i32 + %ref1 = fir.convert %4 : (!fir.heap<!fir.array<?xi32>>) -> !fir.ref<!fir.array<?xi32>> + %elt1 = fir.coordinate_of %ref1, %c0 : (!fir.ref<!fir.array<?xi32>>, index) -> !fir.ref<i32> + fir.store %c0_i32 to %elt1 : !fir.ref<i32> fir.freemem %4 : !fir.heap<!fir.array<?xi32>> return } -// CHECK: func.func @placement1() { +// CHECK-LABEL: func.func @placement1() // CHECK-NEXT: %[[ARG:.*]] = arith.constant 3 : index // CHECK-NEXT: %[[MEM:.*]] = fir.alloca !fir.array<?xi32>, %[[ARG]] -// CHECK-NEXT: return +// CHECK: return // CHECK-NEXT: } // check that if there are no operands, then the alloca is placed early @@ -140,16 +150,21 @@ func.func @placement2() { %3 = arith.addi %1, %2 : index %4 = fir.allocmem !fir.array<42xi32> // ... + %c0_p2 = arith.constant 0 : index + %c0_i32_p2 = arith.constant 0 : i32 + %ref_p2 = fir.convert %4 : (!fir.heap<!fir.array<42xi32>>) -> !fir.ref<!fir.array<42xi32>> + %elt_p2 = fir.coordinate_of %ref_p2, %c0_p2 : (!fir.ref<!fir.array<42xi32>>, index) -> !fir.ref<i32> + fir.store %c0_i32_p2 to %elt_p2 : !fir.ref<i32> fir.freemem %4 : !fir.heap<!fir.array<42xi32>> return } -// CHECK: func.func @placement2() { -// CHECK-NEXT: %[[MEM:.*]] = fir.alloca !fir.array<42xi32> -// CHECK-NEXT: %[[ONE:.*]] = arith.constant 1 : index -// CHECK-NEXT: %[[TWO:.*]] = arith.constant 2 : index -// CHECK-NEXT: %[[SUM:.*]] = arith.addi %[[ONE]], %[[TWO]] : index -// CHECK-NEXT: return -// CHECK-NEXT: } +// CHECK-LABEL: func.func @placement2() +// CHECK: %[[MEM:.*]] = fir.alloca !fir.array<42xi32> +// CHECK: %[[ONE:.*]] = arith.constant 1 : index +// CHECK: %[[TWO:.*]] = arith.constant 2 : index +// CHECK: %[[SUM:.*]] = arith.addi %[[ONE]], %[[TWO]] : index +// CHECK: return +// CHECK: } // check that stack allocations which must be placed in loops use stacksave func.func @placement3() { @@ -162,12 +177,17 @@ func.func @placement3() { // operand is now available %4 = fir.allocmem !fir.array<?xi32>, %3 // ... + %c0 = arith.constant 0 : index + %c0_i32 = arith.constant 0 : i32 + %ref2 = fir.convert %4 : (!fir.heap<!fir.array<?xi32>>) -> !fir.ref<!fir.array<?xi32>> + %elt2 = fir.coordinate_of %ref2, %c0 : (!fir.ref<!fir.array<?xi32>>, index) -> !fir.ref<i32> + fir.store %c0_i32 to %elt2 : !fir.ref<i32> fir.freemem %4 : !fir.heap<!fir.array<?xi32>> fir.result %3, %c1_i32 : index, i32 } return } -// CHECK: func.func @placement3() { +// CHECK-LABEL: func.func @placement3() // CHECK-NEXT: %[[C1:.*]] = arith.constant 1 : index // CHECK-NEXT: %[[C1_I32:.*]] = fir.convert %[[C1]] : (index) -> i32 // CHECK-NEXT: %[[C2:.*]] = arith.constant 2 : index @@ -176,7 +196,7 @@ func.func @placement3() { // CHECK-NEXT: %[[SUM:.*]] = arith.addi %[[C1]], %[[C2]] : index // CHECK-NEXT: %[[SP:.*]] = llvm.intr.stacksave : !llvm.ptr // CHECK-NEXT: %[[MEM:.*]] = fir.alloca !fir.array<?xi32>, %[[SUM]] -// CHECK-NEXT: llvm.intr.stackrestore %[[SP]] : !llvm.ptr +// CHECK: llvm.intr.stackrestore %[[SP]] : !llvm.ptr // CHECK-NEXT: fir.result // CHECK-NEXT: } // CHECK-NEXT: return @@ -194,12 +214,17 @@ func.func @placement4(%arg0 : i1) { // operand is now available %4 = fir.allocmem !fir.array<?xi32>, %3 // ... + %c0 = arith.constant 0 : index + %c0_i32 = arith.constant 0 : i32 + %ref3 = fir.convert %4 : (!fir.heap<!fir.array<?xi32>>) -> !fir.ref<!fir.array<?xi32>> + %elt3 = fir.coordinate_of %ref3, %c0 : (!fir.ref<!fir.array<?xi32>>, index) -> !fir.ref<i32> + fir.store %c0_i32 to %elt3 : !fir.ref<i32> fir.freemem %4 : !fir.heap<!fir.array<?xi32>> cf.cond_br %arg0, ^bb1, ^bb2 ^bb2: return } -// CHECK: func.func @placement4(%arg0: i1) { +// CHECK-LABEL: func.func @placement4(%arg0: i1) // CHECK-NEXT: %[[C1:.*]] = arith.constant 1 : index // CHECK-NEXT: %[[C1_I32:.*]] = fir.convert %[[C1]] : (index) -> i32 // CHECK-NEXT: %[[C10:.*]] = arith.constant 10 : index @@ -208,7 +233,7 @@ func.func @placement4(%arg0 : i1) { // CHECK-NEXT: %[[C3:.*]] = arith.constant 3 : index // CHECK-NEXT: %[[SP:.*]] = llvm.intr.stacksave : !llvm.ptr // CHECK-NEXT: %[[MEM:.*]] = fir.alloca !fir.array<?xi32>, %[[C3]] -// CHECK-NEXT: llvm.intr.stackrestore %[[SP]] : !llvm.ptr +// CHECK: llvm.intr.stackrestore %[[SP]] : !llvm.ptr // CHECK-NEXT: cf.cond_br %arg0, ^bb1, ^bb2 // CHECK-NEXT: ^bb2: // CHECK-NEXT: return @@ -230,7 +255,7 @@ func.func @placement5() { } return } -// CHECK: func.func @placement5() { +// CHECK-LABEL: func.func @placement5() // CHECK-NEXT: %[[C1:.*]] = arith.constant 1 : index // CHECK-NEXT: %[[C1_I32:.*]] = fir.convert %[[C1]] : (index) -> i32 // CHECK-NEXT: %[[C2:.*]] = arith.constant 2 : index @@ -268,7 +293,7 @@ func.func @placement6(%arg0: i1) { fir.freemem %4 : !fir.heap<!fir.array<?xi32>> cf.br ^bb1 } -// CHECK: func.func @placement6(%arg0: i1) { +// CHECK-LABEL: func.func @placement6(%arg0: i1) // CHECK-NEXT: %[[c1:.*]] = arith.constant 1 : index // CHECK-NEXT: %[[c1_i32:.*]] = fir.convert %[[c1]] : (index) -> i32 // CHECK-NEXT: %[[c2:.*]] = arith.constant 2 : index @@ -289,6 +314,11 @@ func.func @placement6(%arg0: i1) { // Check multiple returns, where the memory is always freed func.func @returns(%arg0: i1) { %0 = fir.allocmem !fir.array<42xi32> + %c0_ret = arith.constant 0 : index + %c0_i32_ret = arith.constant 0 : i32 + %ref_ret = fir.convert %0 : (!fir.heap<!fir.array<42xi32>>) -> !fir.ref<!fir.array<42xi32>> + %elt_ret = fir.coordinate_of %ref_ret, %c0_ret : (!fir.ref<!fir.array<42xi32>>, index) -> !fir.ref<i32> + fir.store %c0_i32_ret to %elt_ret : !fir.ref<i32> cf.cond_br %arg0, ^bb1, ^bb2 ^bb1: fir.freemem %0 : !fir.heap<!fir.array<42xi32>> @@ -297,9 +327,9 @@ func.func @returns(%arg0: i1) { fir.freemem %0 : !fir.heap<!fir.array<42xi32>> return } -// CHECK: func.func @returns(%[[COND:.*]]: i1) { -// CHECK-NEXT: %[[ALLOC:.*]] = fir.alloca !fir.array<42xi32> -// CHECK-NEXT: cf.cond_br %[[COND]], ^bb1, ^bb2 +// CHECK-LABEL: func.func @returns( +// CHECK: %[[ALLOC:.*]] = fir.alloca !fir.array<42xi32> +// CHECK: cf.cond_br %{{.*}}, ^bb1, ^bb2 // CHECK-NEXT: ^bb1: // CHECK-NEXT: return // CHECK-NEXT: ^bb2: @@ -309,6 +339,11 @@ func.func @returns(%arg0: i1) { // Check multiple returns, where the memory is not freed on one branch func.func @returns2(%arg0: i1) { %0 = fir.allocmem !fir.array<42xi32> + %c0_ret2 = arith.constant 0 : index + %c0_i32_ret2 = arith.constant 0 : i32 + %ref_ret2 = fir.convert %0 : (!fir.heap<!fir.array<42xi32>>) -> !fir.ref<!fir.array<42xi32>> + %elt_ret2 = fir.coordinate_of %ref_ret2, %c0_ret2 : (!fir.ref<!fir.array<42xi32>>, index) -> !fir.ref<i32> + fir.store %c0_i32_ret2 to %elt_ret2 : !fir.ref<i32> cf.cond_br %arg0, ^bb1, ^bb2 ^bb1: fir.freemem %0 : !fir.heap<!fir.array<42xi32>> @@ -316,9 +351,9 @@ func.func @returns2(%arg0: i1) { ^bb2: return } -// CHECK: func.func @returns2(%[[COND:.*]]: i1) { -// CHECK-NEXT: %[[ALLOC:.*]] = fir.allocmem !fir.array<42xi32> -// CHECK-NEXT: cf.cond_br %[[COND]], ^bb1, ^bb2 +// CHECK-LABEL: func.func @returns2( +// CHECK: %[[ALLOC:.*]] = fir.allocmem !fir.array<42xi32> +// CHECK: cf.cond_br %{{.*}}, ^bb1, ^bb2 // CHECK-NEXT: ^bb1: // CHECK-NEXT: fir.freemem %[[ALLOC]] : !fir.heap<!fir.array<42xi32>> // CHECK-NEXT: return @@ -338,7 +373,7 @@ func.func @omp_placement1() { } return } -// CHECK: func.func @omp_placement1() { +// CHECK-LABEL: func.func @omp_placement1() // CHECK-NEXT: %[[MEM:.*]] = fir.alloca !fir.array<42xi32> // CHECK-NEXT: %[[MEM_CONV:.*]] = fir.convert %[[MEM]] : (!fir.ref<!fir.array<42xi32>>) -> !fir.heap<!fir.array<42xi32>> // CHECK-NEXT: omp.sections { @@ -353,19 +388,21 @@ func.func @omp_placement1() { // function terminated by stop statement func.func @stop_terminator() { %0 = fir.allocmem !fir.array<42xi32> + %c0 = arith.constant 0 : index + %c0_i32_st = arith.constant 0 : i32 + %ref4 = fir.convert %0 : (!fir.heap<!fir.array<42xi32>>) -> !fir.ref<!fir.array<42xi32>> + %elt4 = fir.coordinate_of %ref4, %c0 : (!fir.ref<!fir.array<42xi32>>, index) -> !fir.ref<i32> + fir.store %c0_i32_st to %elt4 : !fir.ref<i32> fir.freemem %0 : !fir.heap<!fir.array<42xi32>> %c0_i32 = arith.constant 0 : i32 %false = arith.constant false fir.call @_FortranAStopStatement(%c0_i32, %false, %false) : (i32, i1, i1) -> () fir.unreachable } -// CHECK: func.func @stop_terminator() { -// CHECK-NEXT: fir.alloca !fir.array<42xi32> -// CHECK-NEXT: %[[ZERO:.*]] = arith.constant 0 : i32 -// CHECK-NEXT: %[[FALSE:.*]] = arith.constant false -// CHECK-NEXT: fir.call @_FortranAStopStatement(%[[ZERO]], %[[FALSE]], %[[FALSE]]) : (i32, i1, i1) -> () -// CHECK-NEXT: fir.unreachable -// CHECK-NEXT: } +// CHECK-LABEL: func.func @stop_terminator() +// CHECK: fir.alloca !fir.array<42xi32> +// CHECK: fir.call @_FortranAStopStatement( +// CHECK: fir.unreachable // check that stack allocations that use fir.declare which must be placed in loops @@ -387,7 +424,7 @@ func.func @placement_loop_declare() { } return } -// CHECK: func.func @placement_loop_declare() { +// CHECK-LABEL: func.func @placement_loop_declare() // CHECK-NEXT: %[[C1:.*]] = arith.constant 1 : index // CHECK-NEXT: %[[C1_I32:.*]] = fir.convert %[[C1]] : (index) -> i32 // CHECK-NEXT: %[[C2:.*]] = arith.constant 2 : index @@ -415,7 +452,7 @@ func.func @lookthrough() { fir.freemem %4 : !fir.heap<!fir.array<42xi32>> return } -// CHECK: func.func @lookthrough() { +// CHECK-LABEL: func.func @lookthrough() // CHECK: fir.alloca !fir.array<42xi32> // CHECK-NOT: fir.freemem @@ -457,6 +494,6 @@ func.func @finding_freemem_in_block() { ^bb3: // pred: ^bb1 return } -// CHECK: func.func @finding_freemem_in_block() { +// CHECK-LABEL: func.func @finding_freemem_in_block() // CHECK: fir.alloca !fir.array<?xi32> // CHECK-NOT: fir.freemem diff --git a/flang/tools/f18/CMakeLists.txt b/flang/tools/f18/CMakeLists.txt index 715992c7..58ea782 100644 --- a/flang/tools/f18/CMakeLists.txt +++ b/flang/tools/f18/CMakeLists.txt @@ -23,6 +23,7 @@ set(MODULES "iso_c_binding" "iso_fortran_env" "iso_fortran_env_impl" + "flang_debug" ) # Check if 128-bit float computations can be done via long double. diff --git a/flang/tools/flang-driver/CMakeLists.txt b/flang/tools/flang-driver/CMakeLists.txt index b5d6727..4dfc0d4 100644 --- a/flang/tools/flang-driver/CMakeLists.txt +++ b/flang/tools/flang-driver/CMakeLists.txt @@ -26,6 +26,7 @@ target_link_libraries(flang clang_target_link_libraries(flang PRIVATE clangDriver + clangOptions clangBasic ) diff --git a/flang/tools/flang-driver/driver.cpp b/flang/tools/flang-driver/driver.cpp index bd878b7..0840255 100644 --- a/flang/tools/flang-driver/driver.cpp +++ b/flang/tools/flang-driver/driver.cpp @@ -52,9 +52,9 @@ createAndPopulateDiagOpts(llvm::ArrayRef<const char *> argv) { // Any errors that would be diagnosed here will also be diagnosed later, // when the DiagnosticsEngine actually exists. unsigned missingArgIndex, missingArgCount; - llvm::opt::InputArgList args = clang::driver::getDriverOptTable().ParseArgs( + llvm::opt::InputArgList args = clang::getDriverOptTable().ParseArgs( argv.slice(1), missingArgIndex, missingArgCount, - llvm::opt::Visibility(clang::driver::options::FlangOption)); + llvm::opt::Visibility(clang::options::FlangOption)); (void)Fortran::frontend::parseDiagnosticArgs(*diagOpts, args); diff --git a/flang/unittests/Optimizer/FortranVariableTest.cpp b/flang/unittests/Optimizer/FortranVariableTest.cpp index 57a04dc..7b36359 100644 --- a/flang/unittests/Optimizer/FortranVariableTest.cpp +++ b/flang/unittests/Optimizer/FortranVariableTest.cpp @@ -51,7 +51,8 @@ TEST_F(FortranVariableTest, SimpleScalar) { /*shape=*/mlir::Value{}, /*typeParams=*/mlir::ValueRange{}, /*dummy_scope=*/nullptr, /*storage=*/nullptr, /*storage_offset=*/0, name, /*fortran_attrs=*/fir::FortranVariableFlagsAttr{}, - /*data_attr=*/cuf::DataAttributeAttr{}); + /*data_attr=*/cuf::DataAttributeAttr{}, + /*dummy_arg_no=*/mlir::IntegerAttr{}); fir::FortranVariableOpInterface fortranVariable = declare; EXPECT_FALSE(fortranVariable.isArray()); @@ -78,7 +79,8 @@ TEST_F(FortranVariableTest, CharacterScalar) { /*shape=*/mlir::Value{}, typeParams, /*dummy_scope=*/nullptr, /*storage=*/nullptr, /*storage_offset=*/0, name, /*fortran_attrs=*/fir::FortranVariableFlagsAttr{}, - /*data_attr=*/cuf::DataAttributeAttr{}); + /*data_attr=*/cuf::DataAttributeAttr{}, + /*dummy_arg_no=*/mlir::IntegerAttr{}); fir::FortranVariableOpInterface fortranVariable = declare; EXPECT_FALSE(fortranVariable.isArray()); @@ -110,7 +112,8 @@ TEST_F(FortranVariableTest, SimpleArray) { shape, /*typeParams=*/mlir::ValueRange{}, /*dummy_scope=*/nullptr, /*storage=*/nullptr, /*storage_offset=*/0, name, /*fortran_attrs=*/fir::FortranVariableFlagsAttr{}, - /*data_attr=*/cuf::DataAttributeAttr{}); + /*data_attr=*/cuf::DataAttributeAttr{}, + /*dummy_arg_no=*/mlir::IntegerAttr{}); fir::FortranVariableOpInterface fortranVariable = declare; EXPECT_TRUE(fortranVariable.isArray()); @@ -142,7 +145,8 @@ TEST_F(FortranVariableTest, CharacterArray) { shape, typeParams, /*dummy_scope=*/nullptr, /*storage=*/nullptr, /*storage_offset=*/0, name, /*fortran_attrs=*/fir::FortranVariableFlagsAttr{}, - /*data_attr=*/cuf::DataAttributeAttr{}); + /*data_attr=*/cuf::DataAttributeAttr{}, + /*dummy_arg_no=*/mlir::IntegerAttr{}); fir::FortranVariableOpInterface fortranVariable = declare; EXPECT_TRUE(fortranVariable.isArray()); |
