From ed657c639f6438f18379418abe0636869988aa38 Mon Sep 17 00:00:00 2001 From: Jean Perier Date: Tue, 7 Oct 2025 07:58:10 -0700 Subject: [PATCH 1/3] [flang][HLFIR] add skip_rebox option to hlfir.declare --- flang/include/flang/Optimizer/HLFIR/HLFIROps.td | 8 +++++++- flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp | 5 ++++- flang/lib/Optimizer/HLFIR/Transforms/ConvertToFIR.cpp | 11 ++++++++--- flang/test/HLFIR/declare-codegen.fir | 9 +++++++++ flang/test/HLFIR/invalid.fir | 9 +++++++++ 5 files changed, 37 insertions(+), 5 deletions(-) diff --git a/flang/include/flang/Optimizer/HLFIR/HLFIROps.td b/flang/include/flang/Optimizer/HLFIR/HLFIROps.td index 218435a44c24f..b7563a2f752f0 100644 --- a/flang/include/flang/Optimizer/HLFIR/HLFIROps.td +++ b/flang/include/flang/Optimizer/HLFIR/HLFIROps.td @@ -73,6 +73,10 @@ def hlfir_DeclareOp local lower bound values. It is intended to be used when generating FIR from HLFIR in order to avoid descriptor creation for simple entities. + The attribute skip_rebox can be set to indicate that the second and first + result are known to be the same descriptors (the input descriptor is known + to already have the correct attributes and lower bounds). + Example: CHARACTER(n) :: c(10:n, 20:n) @@ -98,7 +102,8 @@ def hlfir_DeclareOp DefaultValuedAttr:$storage_offset, Builtin_StringAttr:$uniq_name, OptionalAttr:$fortran_attrs, - OptionalAttr:$data_attr); + OptionalAttr:$data_attr, + OptionalAttr:$skip_rebox); let results = (outs AnyFortranVariable, AnyRefOrBoxLike); @@ -106,6 +111,7 @@ def hlfir_DeclareOp $memref (`(` $shape^ `)`)? (`typeparams` $typeparams^)? (`dummy_scope` $dummy_scope^)? (`storage` `(` $storage^ `[` $storage_offset `]` `)`)? + (`skip_rebox` $skip_rebox^)? attr-dict `:` functional-type(operands, results) }]; diff --git a/flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp b/flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp index 0cc65f939723e..1332dc57fb086 100644 --- a/flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp +++ b/flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp @@ -281,7 +281,7 @@ void hlfir::DeclareOp::build(mlir::OpBuilder &builder, getDeclareOutputTypes(inputType, hasExplicitLbs); build(builder, result, {hlfirVariableType, firVarType}, memref, shape, typeparams, dummy_scope, storage, storage_offset, nameAttr, - fortran_attrs, data_attr); + fortran_attrs, data_attr, /*skip_rebox=*/mlir::UnitAttr{}); } llvm::LogicalResult hlfir::DeclareOp::verify() { @@ -294,6 +294,9 @@ llvm::LogicalResult hlfir::DeclareOp::verify() { return emitOpError("first result type is inconsistent with variable " "properties: expected ") << hlfirVariableType; + if (getSkipRebox() && !llvm::isa(getMemref().getType())) + return emitOpError( + "skip_rebox attribute must only be set when the input is a box"); // The rest of the argument verification is done by the // FortranVariableInterface verifier. auto fortranVar = diff --git a/flang/lib/Optimizer/HLFIR/Transforms/ConvertToFIR.cpp b/flang/lib/Optimizer/HLFIR/Transforms/ConvertToFIR.cpp index 8104e53920c27..6a57bf2ae6fec 100644 --- a/flang/lib/Optimizer/HLFIR/Transforms/ConvertToFIR.cpp +++ b/flang/lib/Optimizer/HLFIR/Transforms/ConvertToFIR.cpp @@ -23,6 +23,7 @@ #include "flang/Optimizer/HLFIR/HLFIROps.h" #include "flang/Optimizer/HLFIR/Passes.h" #include "mlir/Transforms/DialectConversion.h" +#include "llvm/ADT/SmallSet.h" namespace hlfir { #define GEN_PASS_DEF_CONVERTHLFIRTOFIR @@ -312,10 +313,12 @@ class DeclareOpConversion : public mlir::OpRewritePattern { // Propagate other attributes from hlfir.declare to fir.declare. // OpenACC's acc.declare is one example. Right now, the propagation // is verbatim. - mlir::NamedAttrList elidedAttrs = - mlir::NamedAttrList{firDeclareOp->getAttrs()}; + llvm::SmallSet elidedAttrs; + for (const mlir::NamedAttribute &firAttr : firDeclareOp->getAttrs()) + elidedAttrs.insert(firAttr.getName()); + elidedAttrs.insert(declareOp.getSkipReboxAttrName()); for (const mlir::NamedAttribute &attr : declareOp->getAttrs()) - if (!elidedAttrs.get(attr.getName())) + if (!elidedAttrs.contains(attr.getName())) firDeclareOp->setAttr(attr.getName(), attr.getValue()); auto firBase = firDeclareOp.getResult(); @@ -328,6 +331,8 @@ class DeclareOpConversion : public mlir::OpRewritePattern { auto genHlfirBox = [&]() -> mlir::Value { if (auto baseBoxType = mlir::dyn_cast(firBase.getType())) { + if (declareOp.getSkipRebox()) + return firBase; // Rebox so that lower bounds and attributes are correct. if (baseBoxType.isAssumedRank()) return fir::ReboxAssumedRankOp::create( diff --git a/flang/test/HLFIR/declare-codegen.fir b/flang/test/HLFIR/declare-codegen.fir index b3f0b73158603..04c2ddcece4a7 100644 --- a/flang/test/HLFIR/declare-codegen.fir +++ b/flang/test/HLFIR/declare-codegen.fir @@ -124,6 +124,15 @@ func.func @array_declare_box_2(%arg0: !fir.box>) { // CHECK: %[[VAL_1:.*]] = fir.declare %[[VAL_0]] {uniq_name = "x"} : (!fir.box>) -> !fir.box> // CHECK: %[[VAL_2:.*]] = fir.rebox %[[VAL_1]] : (!fir.box>) -> !fir.box> +func.func @array_declare_box_3(%arg0: !fir.box>) -> !fir.box> { + %0:2 = hlfir.declare %arg0 skip_rebox {uniq_name = "x"} : (!fir.box>) -> (!fir.box>, !fir.box>) + return %0#0 : !fir.box> +} +// CHECK-LABEL: func.func @array_declare_box_3( +// CHECK-SAME: %[[VAL_0:.*]]: !fir.box>) -> !fir.box> { +// CHECK: %[[VAL_1:.*]] = fir.declare %[[VAL_0]] {uniq_name = "x"} : (!fir.box>) -> !fir.box> +// CHECK: return %[[VAL_1]] + func.func @array_declare_char_box(%arg0: !fir.box>>) { %0:2 = hlfir.declare %arg0 {uniq_name = "x"} : (!fir.box>>) -> (!fir.box>>, !fir.box>>) return diff --git a/flang/test/HLFIR/invalid.fir b/flang/test/HLFIR/invalid.fir index 887113959429c..91e9ed6c2e4c4 100644 --- a/flang/test/HLFIR/invalid.fir +++ b/flang/test/HLFIR/invalid.fir @@ -36,6 +36,15 @@ func.func @bad_array_declare(%arg0: !fir.ref>) { return } +// ----- +func.func @bad_declare_skip_rebox(%arg0: !fir.ref) { + // expected-error@+1 {{'hlfir.declare' op skip_rebox attribute must only be set when the input is a box}} + %0:2 = hlfir.declare %arg0 skip_rebox {uniq_name = "x"} : (!fir.ref) -> (!fir.ref, !fir.ref) + return +} + +// ----- + // ----- func.func @bad_assign_scalar_character(%arg0: !fir.boxchar<1>, %arg1: !fir.char<1,?>) { // expected-error@+1 {{'hlfir.assign' op operand #0 must be any Fortran value or variable type, but got '!fir.char<1,?>'}} From a5f77a654142f43d0de7a8ca421824986ed0475b Mon Sep 17 00:00:00 2001 From: Jean Perier Date: Tue, 7 Oct 2025 07:59:10 -0700 Subject: [PATCH 2/3] [flang][openacc] map data operand results to symbols inside compute region Variable references inside OpenACC compute and loop region were currently always lowered to usages of the same SSA values than in the host thread, even for variables that appear in data clauses and for which acc data operations are created. This makes it a non-trivial task to identify implicit data usages vs usage of data appearing in clauses because the SSA addresses used in the region may have a non-trivial SSA relationship with the SSA addresses used as inputs of the data operations, especially after CSE runs that may merge component or array element addressing operations with similar addressing on the host thread (fir.coordinate/hlfir.designate). This patch updates OpenACC lowering to remap the Symbol that appear in data clauses to the related acc data operation result for the scope of the compute or loop region. To allow FIR passes to reason about these addresses, a new hlfir.declare operation is created with the acc data operation result. This gives access to the shape, contiguity, attributes, and dummy argument relationships inside the region without having FIR extended to understand the data operations. --- flang/include/flang/Lower/AbstractConverter.h | 4 + flang/lib/Lower/Bridge.cpp | 2 + flang/lib/Lower/OpenACC.cpp | 321 +++++++--- .../OpenACC/acc-data-operands-remapping.f90 | 601 ++++++++++++++++++ ...tprivate-derived-allocatable-component.f90 | 26 +- ...firstprivate-derived-pointer-component.f90 | 26 +- .../acc-firstprivate-derived-user-assign.f90 | 21 +- .../OpenACC/acc-firstprivate-derived.f90 | 21 +- flang/test/Lower/OpenACC/acc-loop-exit.f90 | 2 +- flang/test/Lower/OpenACC/acc-private.f90 | 2 +- .../Lower/OpenACC/do-loops-to-acc-loops.f90 | 30 +- 11 files changed, 922 insertions(+), 134 deletions(-) create mode 100644 flang/test/Lower/OpenACC/acc-data-operands-remapping.f90 diff --git a/flang/include/flang/Lower/AbstractConverter.h b/flang/include/flang/Lower/AbstractConverter.h index 0ffe27ea038e8..f8322a50effc4 100644 --- a/flang/include/flang/Lower/AbstractConverter.h +++ b/flang/include/flang/Lower/AbstractConverter.h @@ -123,6 +123,10 @@ class AbstractConverter { virtual Fortran::lower::SymMap::StorageDesc getSymbolStorage(SymbolRef sym) = 0; + /// Return the Symbol Map used to map semantics::Symbol to their SSA + /// values in the generated MLIR. + virtual Fortran::lower::SymMap &getSymbolMap() = 0; + /// Override lowering of expression with pre-lowered values. /// Associate mlir::Value to evaluate::Expr. All subsequent call to /// genExprXXX() will replace any occurrence of an overridden diff --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp index 780d56f085f69..3a022e188bbdd 100644 --- a/flang/lib/Lower/Bridge.cpp +++ b/flang/lib/Lower/Bridge.cpp @@ -643,6 +643,8 @@ class FirConverter : public Fortran::lower::AbstractConverter { return localSymbols.lookupStorage(sym); } + Fortran::lower::SymMap &getSymbolMap() override final { return localSymbols; } + void overrideExprValues(const Fortran::lower::ExprToValueMap *map) override final { exprValueOverrides = map; diff --git a/flang/lib/Lower/OpenACC.cpp b/flang/lib/Lower/OpenACC.cpp index 4a9e49435a907..f164b3b629f6d 100644 --- a/flang/lib/Lower/OpenACC.cpp +++ b/flang/lib/Lower/OpenACC.cpp @@ -20,6 +20,7 @@ #include "flang/Lower/PFTBuilder.h" #include "flang/Lower/StatementContext.h" #include "flang/Lower/Support/Utils.h" +#include "flang/Lower/SymbolMap.h" #include "flang/Optimizer/Builder/BoxValue.h" #include "flang/Optimizer/Builder/Complex.h" #include "flang/Optimizer/Builder/FIRBuilder.h" @@ -33,6 +34,7 @@ #include "flang/Semantics/scope.h" #include "flang/Semantics/tools.h" #include "mlir/Dialect/ControlFlow/IR/ControlFlowOps.h" +#include "mlir/IR/IRMapping.h" #include "mlir/IR/MLIRContext.h" #include "mlir/Support/LLVM.h" #include "llvm/ADT/STLExtras.h" @@ -60,6 +62,16 @@ static llvm::cl::opt lowerDoLoopToAccLoop( llvm::cl::desc("Whether to lower do loops as `acc.loop` operations."), llvm::cl::init(true)); +static llvm::cl::opt enableSymbolRemapping( + "openacc-remap-symbols", + llvm::cl::desc("Whether to remap symbols that appears in data clauses."), + llvm::cl::init(true)); + +static llvm::cl::opt enableDevicePtrRemap( + "openacc-remap-device-ptr-symbols", + llvm::cl::desc("sub-option of openacc-remap-symbols for deviceptr clause"), + llvm::cl::init(false)); + // Special value for * passed in device_type or gang clauses. static constexpr std::int64_t starCst = -1; @@ -624,17 +636,19 @@ void genAtomicCapture(Fortran::lower::AbstractConverter &converter, } template -static void -genDataOperandOperations(const Fortran::parser::AccObjectList &objectList, - Fortran::lower::AbstractConverter &converter, - Fortran::semantics::SemanticsContext &semanticsContext, - Fortran::lower::StatementContext &stmtCtx, - llvm::SmallVectorImpl &dataOperands, - mlir::acc::DataClause dataClause, bool structured, - bool implicit, llvm::ArrayRef async, - llvm::ArrayRef asyncDeviceTypes, - llvm::ArrayRef asyncOnlyDeviceTypes, - bool setDeclareAttr = false) { +static void genDataOperandOperations( + const Fortran::parser::AccObjectList &objectList, + Fortran::lower::AbstractConverter &converter, + Fortran::semantics::SemanticsContext &semanticsContext, + Fortran::lower::StatementContext &stmtCtx, + llvm::SmallVectorImpl &dataOperands, + mlir::acc::DataClause dataClause, bool structured, bool implicit, + llvm::ArrayRef async, + llvm::ArrayRef asyncDeviceTypes, + llvm::ArrayRef asyncOnlyDeviceTypes, + bool setDeclareAttr = false, + llvm::SmallVectorImpl> + *symbolPairs = nullptr) { fir::FirOpBuilder &builder = converter.getFirOpBuilder(); Fortran::evaluate::ExpressionAnalyzer ea{semanticsContext}; const bool unwrapBoxAddr = true; @@ -655,6 +669,9 @@ genDataOperandOperations(const Fortran::parser::AccObjectList &objectList, /*strideIncludeLowerExtent=*/strideIncludeLowerExtent); LLVM_DEBUG(llvm::dbgs() << __func__ << "\n"; info.dump(llvm::dbgs())); + bool isWholeSymbol = + !designator || Fortran::evaluate::UnwrapWholeSymbolDataRef(*designator); + // If the input value is optional and is not a descriptor, we use the // rawInput directly. mlir::Value baseAddr = ((fir::unwrapRefType(info.addr.getType()) != @@ -668,6 +685,11 @@ genDataOperandOperations(const Fortran::parser::AccObjectList &objectList, asyncOnlyDeviceTypes, unwrapBoxAddr, info.isPresent); dataOperands.push_back(op.getAccVar()); + // Track the symbol and its corresponding mlir::Value if requested + if (symbolPairs && isWholeSymbol) + symbolPairs->emplace_back(op.getAccVar(), + Fortran::semantics::SymbolRef(symbol)); + // For UseDeviceOp, if operand is one of a pair resulting from a // declare operation, create a UseDeviceOp for the other operand as well. if constexpr (std::is_same_v) { @@ -681,6 +703,8 @@ genDataOperandOperations(const Fortran::parser::AccObjectList &objectList, asyncDeviceTypes, asyncOnlyDeviceTypes, unwrapBoxAddr, info.isPresent); dataOperands.push_back(op.getAccVar()); + // Not adding this to symbolPairs because it only make sense to + // map the symbol to a single value. } } } @@ -1264,7 +1288,9 @@ static void genPrivatizationRecipes( llvm::SmallVector &privatizationRecipes, llvm::ArrayRef async, llvm::ArrayRef asyncDeviceTypes, - llvm::ArrayRef asyncOnlyDeviceTypes) { + llvm::ArrayRef asyncOnlyDeviceTypes, + llvm::SmallVectorImpl> + *symbolPairs = nullptr) { fir::FirOpBuilder &builder = converter.getFirOpBuilder(); Fortran::evaluate::ExpressionAnalyzer ea{semanticsContext}; for (const auto &accObject : objectList.v) { @@ -1284,6 +1310,9 @@ static void genPrivatizationRecipes( /*strideIncludeLowerExtent=*/strideIncludeLowerExtent); LLVM_DEBUG(llvm::dbgs() << __func__ << "\n"; info.dump(llvm::dbgs())); + bool isWholeSymbol = + !designator || Fortran::evaluate::UnwrapWholeSymbolDataRef(*designator); + RecipeOp recipe; mlir::Type retTy = getTypeFromBounds(bounds, info.addr.getType()); if constexpr (std::is_same_v) { @@ -1297,6 +1326,11 @@ static void genPrivatizationRecipes( /*implicit=*/false, mlir::acc::DataClause::acc_private, retTy, async, asyncDeviceTypes, asyncOnlyDeviceTypes, /*unwrapBoxAddr=*/true); dataOperands.push_back(op.getAccVar()); + + // Track the symbol and its corresponding mlir::Value if requested + if (symbolPairs && isWholeSymbol) + symbolPairs->emplace_back(op.getAccVar(), + Fortran::semantics::SymbolRef(symbol)); } else { std::string suffix = areAllBoundConstant(bounds) ? getBoundsString(bounds) : ""; @@ -1310,6 +1344,11 @@ static void genPrivatizationRecipes( async, asyncDeviceTypes, asyncOnlyDeviceTypes, /*unwrapBoxAddr=*/true); dataOperands.push_back(op.getAccVar()); + + // Track the symbol and its corresponding mlir::Value if requested + if (symbolPairs && isWholeSymbol) + symbolPairs->emplace_back(op.getAccVar(), + Fortran::semantics::SymbolRef(symbol)); } privatizationRecipes.push_back(mlir::SymbolRefAttr::get( builder.getContext(), recipe.getSymName().str())); @@ -1949,15 +1988,16 @@ mlir::Type getTypeFromIvTypeSize(fir::FirOpBuilder &builder, return builder.getIntegerType(ivTypeSize * 8); } -static void -privatizeIv(Fortran::lower::AbstractConverter &converter, - const Fortran::semantics::Symbol &sym, mlir::Location loc, - llvm::SmallVector &ivTypes, - llvm::SmallVector &ivLocs, - llvm::SmallVector &privateOperands, - llvm::SmallVector &ivPrivate, - llvm::SmallVector &privatizationRecipes, - bool isDoConcurrent = false) { +static void privatizeIv( + Fortran::lower::AbstractConverter &converter, + const Fortran::semantics::Symbol &sym, mlir::Location loc, + llvm::SmallVector &ivTypes, + llvm::SmallVector &ivLocs, + llvm::SmallVector &privateOperands, + llvm::SmallVector> + &ivPrivate, + llvm::SmallVector &privatizationRecipes, + bool isDoConcurrent = false) { fir::FirOpBuilder &builder = converter.getFirOpBuilder(); mlir::Type ivTy = getTypeFromIvTypeSize(builder, sym); @@ -2001,15 +2041,8 @@ privatizeIv(Fortran::lower::AbstractConverter &converter, builder.getContext(), recipe.getSymName().str())); } - // Map the new private iv to its symbol for the scope of the loop. bindSymbol - // might create a hlfir.declare op, if so, we map its result in order to - // use the sym value in the scope. - converter.bindSymbol(sym, mlir::acc::getAccVar(privateOp)); - auto privateValue = converter.getSymbolAddress(sym); - if (auto declareOp = - mlir::dyn_cast(privateValue.getDefiningOp())) - privateValue = declareOp.getResults()[0]; - ivPrivate.push_back(privateValue); + ivPrivate.emplace_back(mlir::acc::getAccVar(privateOp), + Fortran::semantics::SymbolRef(sym)); } static void determineDefaultLoopParMode( @@ -2088,7 +2121,8 @@ static void processDoLoopBounds( llvm::SmallVector &upperbounds, llvm::SmallVector &steps, llvm::SmallVector &privateOperands, - llvm::SmallVector &ivPrivate, + llvm::SmallVector> + &ivPrivate, llvm::SmallVector &privatizationRecipes, llvm::SmallVector &ivTypes, llvm::SmallVector &ivLocs, @@ -2178,26 +2212,122 @@ static void processDoLoopBounds( } } -static mlir::acc::LoopOp -buildACCLoopOp(Fortran::lower::AbstractConverter &converter, - mlir::Location currentLocation, - Fortran::semantics::SemanticsContext &semanticsContext, - Fortran::lower::StatementContext &stmtCtx, - const Fortran::parser::DoConstruct &outerDoConstruct, - Fortran::lower::pft::Evaluation &eval, - llvm::SmallVector &privateOperands, - llvm::SmallVector &privatizationRecipes, - llvm::SmallVector &gangOperands, - llvm::SmallVector &workerNumOperands, - llvm::SmallVector &vectorOperands, - llvm::SmallVector &tileOperands, - llvm::SmallVector &cacheOperands, - llvm::SmallVector &reductionOperands, - llvm::SmallVector &retTy, mlir::Value yieldValue, - uint64_t loopsToProcess) { +/// Remap symbols that appeared in OpenACC data clauses to use the results of +/// the corresponding data operations. This allows isolating symbol accesses +/// inside the OpenACC region from accesses in the host and other regions while +/// preserving Fortran information about the symbols for optimizations. +template +static void remapDataOperandSymbols( + Fortran::lower::AbstractConverter &converter, fir::FirOpBuilder &builder, + RegionOp ®ionOp, + const llvm::SmallVector< + std::pair> + &dataOperandSymbolPairs) { + if (!enableSymbolRemapping || dataOperandSymbolPairs.empty()) + return; + + // Map Symbols that appeared inside data clauses to a new hlfir.declare whose + // input is the acc data operation result. + // This allows isolating all the symbol accesses inside the compute region + // from accesses in the host and other regions while preserving the Fortran + // information about the symbols for Fortran specific optimizations inside the + // region. + Fortran::lower::SymMap &symbolMap = converter.getSymbolMap(); + mlir::OpBuilder::InsertionGuard insertGuard(builder); + builder.setInsertionPointToStart(®ionOp.getRegion().front()); + llvm::SmallPtrSet seenSymbols; + mlir::IRMapping mapper; + for (auto [value, symbol] : dataOperandSymbolPairs) { + + // If A symbol appears on several data clause, just map it to the first + // result (all data operations results for a symbol are pointing same + // memory, so it does not matter which one is used). + if (seenSymbols.contains(&symbol.get())) + continue; + seenSymbols.insert(&symbol.get()); + std::optional hostDef = + symbolMap.lookupVariableDefinition(symbol); + assert(hostDef.has_value() && llvm::isa(*hostDef) && + "expected symbol to be mapped to hlfir.declare"); + auto hostDeclare = llvm::cast(*hostDef); + // Replace base input and DummyScope inputs. + mlir::Value hostInput = hostDeclare.getMemref(); + mlir::Type hostType = hostInput.getType(); + mlir::Type computeType = value.getType(); + if (hostType == computeType) { + mapper.map(hostInput, value); + } else if (llvm::isa(computeType)) { + assert(!llvm::isa(hostType) && + "box type mismatch between compute region variable and " + "hlfir.declare input unexpected"); + if (Fortran::semantics::IsOptional(symbol)) + TODO(regionOp.getLoc(), + "remapping OPTIONAL symbol in OpenACC compute region"); + auto rawValue = + fir::BoxAddrOp::create(builder, regionOp.getLoc(), hostType, value); + mapper.map(hostInput, rawValue); + } else { + assert(!llvm::isa(hostType) && + "compute region variable should not be raw address when host " + "hlfir.declare input was a box"); + assert(fir::isBoxAddress(hostType) == fir::isBoxAddress(computeType) && + "compute region variable should be a pointer/allocatable if and " + "only if host is"); + assert(fir::isa_ref_type(hostType) && fir::isa_ref_type(computeType) && + "compute region variable and host variable should both be raw " + "addresses"); + mlir::Value cast = + builder.createConvert(regionOp.getLoc(), hostType, value); + mapper.map(hostInput, cast); + } + if (mlir::Value dummyScope = hostDeclare.getDummyScope()) { + // Copy the dummy scope into the region so that aliasing rules about + // Fortran dummies are understood inside the region and the abstract dummy + // scope type does not have to cross the OpenACC compute region boundary. + if (!mapper.contains(dummyScope)) { + mlir::Operation *hostDummyScopeOp = dummyScope.getDefiningOp(); + assert(hostDummyScopeOp && + "dummyScope defining operation must be visible in lowering"); + (void)builder.clone(*hostDummyScopeOp, mapper); + } + } + + mlir::Operation *computeDef = + builder.clone(*hostDeclare.getOperation(), mapper); + + // The input box already went through an hlfir.declare. It has the correct + // local lower bounds and attribute. Do not generate a new fir.rebox. + if (llvm::isa(hostDeclare.getMemref().getType())) + llvm::cast(*computeDef).setSkipRebox(true); + + symbolMap.addVariableDefinition( + symbol, llvm::cast(computeDef)); + } +} + +static mlir::acc::LoopOp buildACCLoopOp( + Fortran::lower::AbstractConverter &converter, + mlir::Location currentLocation, + Fortran::semantics::SemanticsContext &semanticsContext, + Fortran::lower::StatementContext &stmtCtx, + const Fortran::parser::DoConstruct &outerDoConstruct, + Fortran::lower::pft::Evaluation &eval, + llvm::SmallVector &privateOperands, + llvm::SmallVector &privatizationRecipes, + llvm::SmallVector> + &dataOperandSymbolPairs, + llvm::SmallVector &gangOperands, + llvm::SmallVector &workerNumOperands, + llvm::SmallVector &vectorOperands, + llvm::SmallVector &tileOperands, + llvm::SmallVector &cacheOperands, + llvm::SmallVector &reductionOperands, + llvm::SmallVector &retTy, mlir::Value yieldValue, + uint64_t loopsToProcess) { fir::FirOpBuilder &builder = converter.getFirOpBuilder(); - llvm::SmallVector ivPrivate; + llvm::SmallVector> + ivPrivate; llvm::SmallVector ivTypes; llvm::SmallVector ivLocs; llvm::SmallVector inclusiveBounds; @@ -2231,10 +2361,25 @@ buildACCLoopOp(Fortran::lower::AbstractConverter &converter, builder, builder.getFusedLoc(locs), currentLocation, eval, operands, operandSegments, /*outerCombined=*/false, retTy, yieldValue, ivTypes, ivLocs); - - for (auto [arg, value] : llvm::zip( - loopOp.getLoopRegions().front()->front().getArguments(), ivPrivate)) - fir::StoreOp::create(builder, currentLocation, arg, value); + // Ensure the iv symbol is mapped to private iv SSA value for the scope of + // the loop even if it did not appear explicitly in a PRIVATE clause (if it + // appeared explicitly in such clause, that is also fine because duplicates + // in the list are ignored). + dataOperandSymbolPairs.append(ivPrivate.begin(), ivPrivate.end()); + // 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. + auto privateValue = + converter.getSymbolAddress(std::get(iv)); + // if (auto declareOp = + // mlir::dyn_cast(privateValue.getDefiningOp())) + // privateValue = declareOp.getResults()[0]; + fir::StoreOp::create(builder, currentLocation, arg, privateValue); + } loopOp.setInclusiveUpperbound(inclusiveBounds); @@ -2260,6 +2405,10 @@ static mlir::acc::LoopOp createLoopOp( llvm::SmallVector tileOperandsSegments, gangOperandsSegments; llvm::SmallVector collapseValues; + // Vector to track mlir::Value results and their corresponding Fortran symbols + llvm::SmallVector> + dataOperandSymbolPairs; + llvm::SmallVector gangArgTypes; llvm::SmallVector seqDeviceTypes, independentDeviceTypes, autoDeviceTypes, vectorOperandsDeviceTypes, workerNumOperandsDeviceTypes, @@ -2380,7 +2529,8 @@ static mlir::acc::LoopOp createLoopOp( genPrivatizationRecipes( privateClause->v, converter, semanticsContext, stmtCtx, privateOperands, privatizationRecipes, /*async=*/{}, - /*asyncDeviceTypes=*/{}, /*asyncOnlyDeviceTypes=*/{}); + /*asyncDeviceTypes=*/{}, /*asyncOnlyDeviceTypes=*/{}, + &dataOperandSymbolPairs); } else if (const auto *reductionClause = std::get_if( &clause.u)) { @@ -2436,9 +2586,9 @@ static mlir::acc::LoopOp createLoopOp( Fortran::lower::getLoopCountForCollapseAndTile(accClauseList); auto loopOp = buildACCLoopOp( converter, currentLocation, semanticsContext, stmtCtx, outerDoConstruct, - eval, privateOperands, privatizationRecipes, gangOperands, - workerNumOperands, vectorOperands, tileOperands, cacheOperands, - reductionOperands, retTy, yieldValue, loopsToProcess); + eval, privateOperands, privatizationRecipes, dataOperandSymbolPairs, + gangOperands, workerNumOperands, vectorOperands, tileOperands, + cacheOperands, reductionOperands, retTy, yieldValue, loopsToProcess); if (!gangDeviceTypes.empty()) loopOp.setGangAttr(builder.getArrayAttr(gangDeviceTypes)); @@ -2568,7 +2718,9 @@ static void genDataOperandOperationsWithModifier( llvm::ArrayRef async, llvm::ArrayRef asyncDeviceTypes, llvm::ArrayRef asyncOnlyDeviceTypes, - bool setDeclareAttr = false) { + bool setDeclareAttr = false, + llvm::SmallVectorImpl> + *symbolPairs = nullptr) { const Fortran::parser::AccObjectListWithModifier &listWithModifier = x->v; const auto &accObjectList = std::get(listWithModifier.t); @@ -2581,7 +2733,7 @@ static void genDataOperandOperationsWithModifier( stmtCtx, dataClauseOperands, dataClause, /*structured=*/true, /*implicit=*/false, async, asyncDeviceTypes, asyncOnlyDeviceTypes, - setDeclareAttr); + setDeclareAttr, symbolPairs); } template @@ -2612,6 +2764,10 @@ static Op createComputeOp( llvm::SmallVector privatizationRecipes, firstPrivatizationRecipes, reductionRecipes; + // Vector to track mlir::Value results and their corresponding Fortran symbols + llvm::SmallVector> + dataOperandSymbolPairs; + // Self clause has optional values but can be present with // no value as well. When there is no value, the op has an attribute to // represent the clause. @@ -2732,7 +2888,8 @@ static Op createComputeOp( copyClause->v, converter, semanticsContext, stmtCtx, dataClauseOperands, mlir::acc::DataClause::acc_copy, /*structured=*/true, /*implicit=*/false, async, asyncDeviceTypes, - asyncOnlyDeviceTypes); + asyncOnlyDeviceTypes, /*setDeclareAttr=*/false, + &dataOperandSymbolPairs); copyEntryOperands.append(dataClauseOperands.begin() + crtDataStart, dataClauseOperands.end()); } else if (const auto *copyinClause = @@ -2744,7 +2901,8 @@ static Op createComputeOp( Fortran::parser::AccDataModifier::Modifier::ReadOnly, dataClauseOperands, mlir::acc::DataClause::acc_copyin, mlir::acc::DataClause::acc_copyin_readonly, async, asyncDeviceTypes, - asyncOnlyDeviceTypes); + asyncOnlyDeviceTypes, /*setDeclareAttr=*/false, + &dataOperandSymbolPairs); copyinEntryOperands.append(dataClauseOperands.begin() + crtDataStart, dataClauseOperands.end()); } else if (const auto *copyoutClause = @@ -2757,7 +2915,8 @@ static Op createComputeOp( Fortran::parser::AccDataModifier::Modifier::ReadOnly, dataClauseOperands, mlir::acc::DataClause::acc_copyout, mlir::acc::DataClause::acc_copyout_zero, async, asyncDeviceTypes, - asyncOnlyDeviceTypes); + asyncOnlyDeviceTypes, /*setDeclareAttr=*/false, + &dataOperandSymbolPairs); copyoutEntryOperands.append(dataClauseOperands.begin() + crtDataStart, dataClauseOperands.end()); } else if (const auto *createClause = @@ -2769,7 +2928,8 @@ static Op createComputeOp( Fortran::parser::AccDataModifier::Modifier::Zero, dataClauseOperands, mlir::acc::DataClause::acc_create, mlir::acc::DataClause::acc_create_zero, async, asyncDeviceTypes, - asyncOnlyDeviceTypes); + asyncOnlyDeviceTypes, /*setDeclareAttr=*/false, + &dataOperandSymbolPairs); createEntryOperands.append(dataClauseOperands.begin() + crtDataStart, dataClauseOperands.end()); } else if (const auto *noCreateClause = @@ -2780,7 +2940,8 @@ static Op createComputeOp( noCreateClause->v, converter, semanticsContext, stmtCtx, dataClauseOperands, mlir::acc::DataClause::acc_no_create, /*structured=*/true, /*implicit=*/false, async, asyncDeviceTypes, - asyncOnlyDeviceTypes); + asyncOnlyDeviceTypes, /*setDeclareAttr=*/false, + &dataOperandSymbolPairs); nocreateEntryOperands.append(dataClauseOperands.begin() + crtDataStart, dataClauseOperands.end()); } else if (const auto *presentClause = @@ -2791,17 +2952,21 @@ static Op createComputeOp( presentClause->v, converter, semanticsContext, stmtCtx, dataClauseOperands, mlir::acc::DataClause::acc_present, /*structured=*/true, /*implicit=*/false, async, asyncDeviceTypes, - asyncOnlyDeviceTypes); + asyncOnlyDeviceTypes, /*setDeclareAttr=*/false, + &dataOperandSymbolPairs); presentEntryOperands.append(dataClauseOperands.begin() + crtDataStart, dataClauseOperands.end()); } else if (const auto *devicePtrClause = std::get_if( &clause.u)) { + llvm::SmallVectorImpl< + std::pair> *symPairs = + enableDevicePtrRemap ? &dataOperandSymbolPairs : nullptr; genDataOperandOperations( devicePtrClause->v, converter, semanticsContext, stmtCtx, dataClauseOperands, mlir::acc::DataClause::acc_deviceptr, /*structured=*/true, /*implicit=*/false, async, asyncDeviceTypes, - asyncOnlyDeviceTypes); + asyncOnlyDeviceTypes, /*setDeclareAttr=*/false, symPairs); } else if (const auto *attachClause = std::get_if(&clause.u)) { auto crtDataStart = dataClauseOperands.size(); @@ -2809,7 +2974,8 @@ static Op createComputeOp( attachClause->v, converter, semanticsContext, stmtCtx, dataClauseOperands, mlir::acc::DataClause::acc_attach, /*structured=*/true, /*implicit=*/false, async, asyncDeviceTypes, - asyncOnlyDeviceTypes); + asyncOnlyDeviceTypes, /*setDeclareAttr=*/false, + &dataOperandSymbolPairs); attachEntryOperands.append(dataClauseOperands.begin() + crtDataStart, dataClauseOperands.end()); } else if (const auto *privateClause = @@ -2819,14 +2985,14 @@ static Op createComputeOp( genPrivatizationRecipes( privateClause->v, converter, semanticsContext, stmtCtx, privateOperands, privatizationRecipes, async, asyncDeviceTypes, - asyncOnlyDeviceTypes); + asyncOnlyDeviceTypes, &dataOperandSymbolPairs); } else if (const auto *firstprivateClause = std::get_if( &clause.u)) { genPrivatizationRecipes( firstprivateClause->v, converter, semanticsContext, stmtCtx, firstprivateOperands, firstPrivatizationRecipes, async, - asyncDeviceTypes, asyncOnlyDeviceTypes); + asyncDeviceTypes, asyncOnlyDeviceTypes, &dataOperandSymbolPairs); } else if (const auto *reductionClause = std::get_if( &clause.u)) { @@ -2846,7 +3012,8 @@ static Op createComputeOp( converter, semanticsContext, stmtCtx, dataClauseOperands, mlir::acc::DataClause::acc_reduction, /*structured=*/true, /*implicit=*/true, async, asyncDeviceTypes, - asyncOnlyDeviceTypes); + asyncOnlyDeviceTypes, /*setDeclareAttr=*/false, + &dataOperandSymbolPairs); copyEntryOperands.append(dataClauseOperands.begin() + crtDataStart, dataClauseOperands.end()); } @@ -2945,6 +3112,11 @@ static Op createComputeOp( computeOp.setCombinedAttr(builder.getUnitAttr()); auto insPt = builder.saveInsertionPoint(); + + // Remap symbols from data clauses to use data operation results + remapDataOperandSymbols(converter, builder, computeOp, + dataOperandSymbolPairs); + builder.setInsertionPointAfter(computeOp); // Create the exit operations after the region. @@ -4921,6 +5093,8 @@ mlir::Operation *Fortran::lower::genOpenACCLoopFromDoConstruct( reductionOperands; llvm::SmallVector privatizationRecipes; llvm::SmallVector retTy; + llvm::SmallVector> + dataOperandSymbolPairs; mlir::Value yieldValue; uint64_t loopsToProcess = 1; // Single loop construct @@ -4929,9 +5103,10 @@ mlir::Operation *Fortran::lower::genOpenACCLoopFromDoConstruct( Fortran::lower::StatementContext stmtCtx; auto loopOp = buildACCLoopOp( converter, converter.getCurrentLocation(), semanticsContext, stmtCtx, - doConstruct, eval, privateOperands, privatizationRecipes, gangOperands, - workerNumOperands, vectorOperands, tileOperands, cacheOperands, - reductionOperands, retTy, yieldValue, loopsToProcess); + doConstruct, eval, privateOperands, privatizationRecipes, + dataOperandSymbolPairs, gangOperands, workerNumOperands, vectorOperands, + tileOperands, cacheOperands, reductionOperands, retTy, yieldValue, + loopsToProcess); fir::FirOpBuilder &builder = converter.getFirOpBuilder(); if (!privatizationRecipes.empty()) diff --git a/flang/test/Lower/OpenACC/acc-data-operands-remapping.f90 b/flang/test/Lower/OpenACC/acc-data-operands-remapping.f90 new file mode 100644 index 0000000000000..9d36f6a99e8a7 --- /dev/null +++ b/flang/test/Lower/OpenACC/acc-data-operands-remapping.f90 @@ -0,0 +1,601 @@ +! Test remapping of variables appearing in OpenACC data clauses +! 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 + +module m +interface +subroutine takes_scalar(x) + real :: x +end subroutine +subroutine takes_scalar_character(c, l) + integer :: l + character(l) :: c +end subroutine +subroutine takes_explicit_cst_shape(x) + real :: x(100) +end subroutine +subroutine takes_explicit_shape(x, n) + real :: x(n) +end subroutine +subroutine takes_assumed_shape(x) + real :: x(:) +end subroutine +subroutine takes_pointer(x) + real, pointer :: x(:) +end subroutine + +subroutine takes_optional_scalar(x) + real, optional :: x +end subroutine +subroutine takes_optional_explicit_cst_shape(x) + real, optional :: x(100) +end subroutine +subroutine takes_optional_explicit_shape(x, n) + real, optional :: x(n) +end subroutine +subroutine takes_optional_assumed_shape(x) + real, optional :: x(:) +end subroutine +subroutine takes_optional_pointer(x) + real, optional, pointer :: x(:) +end subroutine +end interface +contains + +! ----------------------------- Test forwarding ------------------------------ ! + + subroutine test_scalar(x) + real :: x + !$acc parallel copy(x) + call takes_scalar(x) + !$acc end parallel + end subroutine + + subroutine test_scalar_character(c, l) + integer :: l + character(l) :: c + !$acc parallel copy(x) + call takes_scalar_character(c, len(c)) + !$acc end parallel + end subroutine + + subroutine test_cst_shape(x) + real :: x(100) + !$acc parallel copy(x) + call takes_explicit_cst_shape(x) + !$acc end parallel + end subroutine + + subroutine test_explicit_shape(x, n) + real :: x(n) + !$acc parallel copy(x) + call takes_explicit_shape(x, size(x,dim=1)) + !$acc end parallel + end subroutine + + subroutine test_assumed_shape(x, n) + real :: x(:) + !$acc parallel copy(x) + call takes_assumed_shape(x) + !$acc end parallel + end subroutine + + subroutine test_contiguous_assumed_shape(x, n) + real, contiguous :: x(:) + !$acc parallel copy(x) + call takes_explicit_shape(x, size(x,dim=1)) + !$acc end parallel + end subroutine + + subroutine test_pointer(x, n) + real, pointer :: x(:) + !$acc parallel copy(x) + call takes_pointer(x) + !$acc end parallel + end subroutine + + subroutine test_using_both_results(x, n) + real :: x(n) + !$acc parallel copy(x) + ! using hlfir.declare result #0 + call takes_assumed_shape(x) + ! using hlfir.declare result #1 + call takes_explicit_shape(x, size(x,dim=1)) + !$acc end parallel + end subroutine + +! ------------------------- Test array addressing ---------------------------- ! + + subroutine addressing_cst_shape(x) + real :: x(10, 20) + !$acc parallel copy(x) + call takes_scalar(x(2,3)) + !$acc end parallel + end subroutine + + subroutine addressing_explicit_shape(x, n, m) + real :: x(n, m) + !$acc parallel copy(x) + call takes_scalar(x(2,3)) + !$acc end parallel + end subroutine + + subroutine addressing_assumed_shape(x, n) + real :: x(:, :) + !$acc parallel copy(x) + call takes_scalar(x(2,3)) + !$acc end parallel + end subroutine + + subroutine addressing_contiguous_assumed_shape(x, n) + real, contiguous :: x(:, :) + !$acc parallel copy(x) + call takes_scalar(x(2,3)) + !$acc end parallel + end subroutine + + subroutine addressing_pointer(x) + real, pointer :: x(:, :) + !$acc parallel copy(x) + call takes_scalar(x(2,3)) + !$acc end parallel + end subroutine + +! ------------------------ Test OPTIONAL handling ---------------------------- ! + + subroutine test_optional_scalar(x) + real, optional :: x + !$acc parallel copy(x) + call takes_optional_scalar(x) + !$acc end parallel + end subroutine + + subroutine test_optional_explicit_cst_shape(x) + real, optional :: x(100) + !$acc parallel copy(x) + call takes_optional_explicit_cst_shape(x) + !$acc end parallel + end subroutine + + subroutine test_optional_explicit_shape(x, n) + real, optional :: x(n) + !$acc parallel copy(x) + call takes_optional_explicit_shape(x, n) + !$acc end parallel + end subroutine + + subroutine test_optional_assumed_shape(x) + real, optional :: x(:) + !$acc parallel copy(x) + call takes_optional_assumed_shape(x) + !$acc end parallel + end subroutine + + subroutine test_optional_pointer(x) + real, optional, pointer :: x(:) + !$acc parallel copy(x) + call takes_optional_pointer(x) + !$acc end parallel + end subroutine + +end module + +! CHECK-LABEL: func.func @_QMmPtest_scalar( +! CHECK-SAME: %[[ARG0:.*]]: !fir.ref {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, !fir.dscope) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_2:.*]] = acc.copyin varPtr(%[[VAL_1]]#0 : !fir.ref) -> !fir.ref {dataClause = #acc, name = "x"} +! CHECK: acc.parallel dataOperands(%[[VAL_2]] : !fir.ref) { +! 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, !fir.dscope) -> (!fir.ref, !fir.ref) +! CHECK: fir.call @_QPtakes_scalar(%[[VAL_4]]#0) fastmath : (!fir.ref) -> () +! CHECK: acc.yield +! CHECK: } +! CHECK: acc.copyout accPtr(%[[VAL_2]] : !fir.ref) to varPtr(%[[VAL_1]]#0 : !fir.ref) {dataClause = #acc, name = "x"} +! CHECK: return +! CHECK: } + +! CHECK-LABEL: func.func @_QMmPtest_scalar_character( +! CHECK-SAME: %[[ARG0:.*]]: !fir.boxchar<1> {fir.bindc_name = "c"}, +! CHECK-SAME: %[[ARG1:.*]]: !fir.ref {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, !fir.dscope) -> (!fir.ref, !fir.ref) +! 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) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_4:.*]]:2 = fir.unboxchar %[[ARG0]] : (!fir.boxchar<1>) -> (!fir.ref>, index) +! CHECK: %[[VAL_5:.*]] = fir.load %[[VAL_1]]#0 : !fir.ref +! 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>, i32, !fir.dscope) -> (!fir.boxchar<1>, !fir.ref>) +! CHECK: %[[VAL_10:.*]] = acc.copyin varPtr(%[[VAL_3]]#0 : !fir.ref) -> !fir.ref {dataClause = #acc, name = "x"} +! CHECK: acc.parallel dataOperands(%[[VAL_10]] : !fir.ref) { +! CHECK: %[[VAL_11:.*]]:2 = hlfir.declare %[[VAL_10]] {uniq_name = "_QMmFtest_scalar_characterEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_12:.*]]:3 = hlfir.associate %[[VAL_8]] {adapt.valuebyref} : (i32) -> (!fir.ref, !fir.ref, i1) +! CHECK: fir.call @_QPtakes_scalar_character(%[[VAL_9]]#0, %[[VAL_12]]#0) fastmath : (!fir.boxchar<1>, !fir.ref) -> () +! CHECK: hlfir.end_associate %[[VAL_12]]#1, %[[VAL_12]]#2 : !fir.ref, i1 +! CHECK: acc.yield +! CHECK: } +! CHECK: acc.copyout accPtr(%[[VAL_10]] : !fir.ref) to varPtr(%[[VAL_3]]#0 : !fir.ref) {dataClause = #acc, name = "x"} +! CHECK: return +! CHECK: } + +! CHECK-LABEL: func.func @_QMmPtest_cst_shape( +! CHECK-SAME: %[[ARG0:.*]]: !fir.ref> {fir.bindc_name = "x"}) { +! 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.shape<1>, !fir.dscope) -> (!fir.ref>, !fir.ref>) +! CHECK: %[[VAL_4:.*]] = acc.copyin varPtr(%[[VAL_3]]#0 : !fir.ref>) -> !fir.ref> {dataClause = #acc, name = "x"} +! CHECK: acc.parallel dataOperands(%[[VAL_4]] : !fir.ref>) { +! 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.shape<1>, !fir.dscope) -> (!fir.ref>, !fir.ref>) +! CHECK: fir.call @_QPtakes_explicit_cst_shape(%[[VAL_6]]#0) fastmath : (!fir.ref>) -> () +! CHECK: acc.yield +! CHECK: } +! CHECK: acc.copyout accPtr(%[[VAL_4]] : !fir.ref>) to varPtr(%[[VAL_3]]#0 : !fir.ref>) {dataClause = #acc, name = "x"} +! CHECK: return +! CHECK: } + +! CHECK-LABEL: func.func @_QMmPtest_explicit_shape( +! CHECK-SAME: %[[ARG0:.*]]: !fir.ref> {fir.bindc_name = "x"}, +! CHECK-SAME: %[[ARG1:.*]]: !fir.ref {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, !fir.dscope) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_2:.*]] = fir.load %[[VAL_1]]#0 : !fir.ref +! CHECK: %[[VAL_3:.*]] = fir.convert %[[VAL_2]] : (i32) -> i64 +! CHECK: %[[VAL_4:.*]] = fir.convert %[[VAL_3]] : (i64) -> index +! CHECK: %[[VAL_5:.*]] = arith.constant 0 : index +! 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.shape<1>, !fir.dscope) -> (!fir.box>, !fir.ref>) +! CHECK: %[[VAL_10:.*]] = acc.copyin var(%[[VAL_9]]#0 : !fir.box>) -> !fir.box> {dataClause = #acc, name = "x"} +! CHECK: acc.parallel dataOperands(%[[VAL_10]] : !fir.box>) { +! CHECK: %[[VAL_11:.*]] = fir.box_addr %[[VAL_10]] : (!fir.box>) -> !fir.ref> +! 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.shape<1>, !fir.dscope) -> (!fir.box>, !fir.ref>) +! 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, !fir.ref, i1) +! CHECK: fir.call @_QPtakes_explicit_shape(%[[VAL_13]]#1, %[[VAL_16]]#0) fastmath : (!fir.ref>, !fir.ref) -> () +! CHECK: hlfir.end_associate %[[VAL_16]]#1, %[[VAL_16]]#2 : !fir.ref, i1 +! CHECK: acc.yield +! CHECK: } +! CHECK: acc.copyout accVar(%[[VAL_10]] : !fir.box>) to var(%[[VAL_9]]#0 : !fir.box>) {dataClause = #acc, name = "x"} +! CHECK: return +! CHECK: } + +! CHECK-LABEL: func.func @_QMmPtest_assumed_shape( +! CHECK-SAME: %[[ARG0:.*]]: !fir.box> {fir.bindc_name = "x"}, +! CHECK-SAME: %[[ARG1:.*]]: !fir.ref {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, !fir.dscope) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %[[VAL_0]] {uniq_name = "_QMmFtest_assumed_shapeEx"} : (!fir.box>, !fir.dscope) -> (!fir.box>, !fir.box>) +! CHECK: %[[VAL_3:.*]] = acc.copyin var(%[[VAL_2]]#0 : !fir.box>) -> !fir.box> {dataClause = #acc, name = "x"} +! CHECK: acc.parallel dataOperands(%[[VAL_3]] : !fir.box>) { +! 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.dscope) -> (!fir.box>, !fir.box>) +! CHECK: fir.call @_QPtakes_assumed_shape(%[[VAL_5]]#0) fastmath : (!fir.box>) -> () +! CHECK: acc.yield +! CHECK: } +! CHECK: acc.copyout accVar(%[[VAL_3]] : !fir.box>) to var(%[[VAL_2]]#0 : !fir.box>) {dataClause = #acc, name = "x"} +! CHECK: return +! CHECK: } + +! CHECK-LABEL: func.func @_QMmPtest_contiguous_assumed_shape( +! CHECK-SAME: %[[ARG0:.*]]: !fir.box> {fir.bindc_name = "x", fir.contiguous}, +! CHECK-SAME: %[[ARG1:.*]]: !fir.ref {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, !fir.dscope) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_2:.*]] = fir.box_addr %[[ARG0]] : (!fir.box>) -> !fir.ref> +! CHECK: %[[VAL_3:.*]] = arith.constant 0 : index +! CHECK: %[[VAL_4:.*]]:3 = fir.box_dims %[[ARG0]], %[[VAL_3]] : (!fir.box>, 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, uniq_name = "_QMmFtest_contiguous_assumed_shapeEx"} : (!fir.ref>, !fir.shapeshift<1>, !fir.dscope) -> (!fir.box>, !fir.ref>) +! CHECK: %[[VAL_8:.*]] = acc.copyin var(%[[VAL_7]]#0 : !fir.box>) -> !fir.box> {dataClause = #acc, name = "x"} +! CHECK: acc.parallel dataOperands(%[[VAL_8]] : !fir.box>) { +! CHECK: %[[VAL_9:.*]] = fir.box_addr %[[VAL_8]] : (!fir.box>) -> !fir.ref> +! 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, uniq_name = "_QMmFtest_contiguous_assumed_shapeEx"} : (!fir.ref>, !fir.shapeshift<1>, !fir.dscope) -> (!fir.box>, !fir.ref>) +! 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, !fir.ref, i1) +! CHECK: fir.call @_QPtakes_explicit_shape(%[[VAL_11]]#1, %[[VAL_14]]#0) fastmath : (!fir.ref>, !fir.ref) -> () +! CHECK: hlfir.end_associate %[[VAL_14]]#1, %[[VAL_14]]#2 : !fir.ref, i1 +! CHECK: acc.yield +! CHECK: } +! CHECK: acc.copyout accVar(%[[VAL_8]] : !fir.box>) to var(%[[VAL_7]]#0 : !fir.box>) {dataClause = #acc, name = "x"} +! CHECK: return +! CHECK: } + +! CHECK-LABEL: func.func @_QMmPtest_pointer( +! CHECK-SAME: %[[ARG0:.*]]: !fir.ref>>> {fir.bindc_name = "x"}, +! CHECK-SAME: %[[ARG1:.*]]: !fir.ref {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, !fir.dscope) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %[[VAL_0]] {fortran_attrs = #fir.var_attrs, uniq_name = "_QMmFtest_pointerEx"} : (!fir.ref>>>, !fir.dscope) -> (!fir.ref>>>, !fir.ref>>>) +! CHECK: %[[VAL_3:.*]] = acc.copyin varPtr(%[[VAL_2]]#0 : !fir.ref>>>) -> !fir.ref>>> {dataClause = #acc, name = "x"} +! CHECK: acc.parallel dataOperands(%[[VAL_3]] : !fir.ref>>>) { +! 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, uniq_name = "_QMmFtest_pointerEx"} : (!fir.ref>>>, !fir.dscope) -> (!fir.ref>>>, !fir.ref>>>) +! CHECK: fir.call @_QPtakes_pointer(%[[VAL_5]]#0) fastmath : (!fir.ref>>>) -> () +! CHECK: acc.yield +! CHECK: } +! CHECK: acc.copyout accPtr(%[[VAL_3]] : !fir.ref>>>) to varPtr(%[[VAL_2]]#0 : !fir.ref>>>) {dataClause = #acc, name = "x"} +! CHECK: return +! CHECK: } + +! CHECK-LABEL: func.func @_QMmPtest_using_both_results( +! CHECK-SAME: %[[ARG0:.*]]: !fir.ref> {fir.bindc_name = "x"}, +! CHECK-SAME: %[[ARG1:.*]]: !fir.ref {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, !fir.dscope) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_2:.*]] = fir.load %[[VAL_1]]#0 : !fir.ref +! CHECK: %[[VAL_3:.*]] = fir.convert %[[VAL_2]] : (i32) -> i64 +! CHECK: %[[VAL_4:.*]] = fir.convert %[[VAL_3]] : (i64) -> index +! CHECK: %[[VAL_5:.*]] = arith.constant 0 : index +! 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.shape<1>, !fir.dscope) -> (!fir.box>, !fir.ref>) +! CHECK: %[[VAL_10:.*]] = acc.copyin var(%[[VAL_9]]#0 : !fir.box>) -> !fir.box> {dataClause = #acc, name = "x"} +! CHECK: acc.parallel dataOperands(%[[VAL_10]] : !fir.box>) { +! CHECK: %[[VAL_11:.*]] = fir.box_addr %[[VAL_10]] : (!fir.box>) -> !fir.ref> +! 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.shape<1>, !fir.dscope) -> (!fir.box>, !fir.ref>) +! CHECK: fir.call @_QPtakes_assumed_shape(%[[VAL_13]]#0) fastmath : (!fir.box>) -> () +! 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, !fir.ref, i1) +! CHECK: fir.call @_QPtakes_explicit_shape(%[[VAL_13]]#1, %[[VAL_16]]#0) fastmath : (!fir.ref>, !fir.ref) -> () +! CHECK: hlfir.end_associate %[[VAL_16]]#1, %[[VAL_16]]#2 : !fir.ref, i1 +! CHECK: acc.yield +! CHECK: } +! CHECK: acc.copyout accVar(%[[VAL_10]] : !fir.box>) to var(%[[VAL_9]]#0 : !fir.box>) {dataClause = #acc, name = "x"} +! CHECK: return +! CHECK: } + +! CHECK-LABEL: func.func @_QMmPaddressing_cst_shape( +! CHECK-SAME: %[[ARG0:.*]]: !fir.ref> {fir.bindc_name = "x"}) { +! CHECK: %[[VAL_0:.*]] = fir.dummy_scope : !fir.dscope +! 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.shape<2>, !fir.dscope) -> (!fir.ref>, !fir.ref>) +! CHECK: %[[VAL_5:.*]] = acc.copyin varPtr(%[[VAL_4]]#0 : !fir.ref>) -> !fir.ref> {dataClause = #acc, name = "x"} +! CHECK: acc.parallel dataOperands(%[[VAL_5]] : !fir.ref>) { +! 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.shape<2>, !fir.dscope) -> (!fir.ref>, !fir.ref>) +! 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>, index, index) -> !fir.ref +! CHECK: fir.call @_QPtakes_scalar(%[[VAL_10]]) fastmath : (!fir.ref) -> () +! CHECK: acc.yield +! CHECK: } +! CHECK: acc.copyout accPtr(%[[VAL_5]] : !fir.ref>) to varPtr(%[[VAL_4]]#0 : !fir.ref>) {dataClause = #acc, name = "x"} +! CHECK: return +! CHECK: } + +! CHECK-LABEL: func.func @_QMmPaddressing_explicit_shape( +! CHECK-SAME: %[[ARG0:.*]]: !fir.ref> {fir.bindc_name = "x"}, +! CHECK-SAME: %[[ARG1:.*]]: !fir.ref {fir.bindc_name = "n"}, +! CHECK-SAME: %[[ARG2:.*]]: !fir.ref {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, !fir.dscope) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %[[VAL_0]] {uniq_name = "_QMmFaddressing_explicit_shapeEn"} : (!fir.ref, !fir.dscope) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_3:.*]] = fir.load %[[VAL_2]]#0 : !fir.ref +! CHECK: %[[VAL_4:.*]] = fir.convert %[[VAL_3]] : (i32) -> i64 +! CHECK: %[[VAL_5:.*]] = fir.convert %[[VAL_4]] : (i64) -> index +! CHECK: %[[VAL_6:.*]] = arith.constant 0 : index +! 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.load %[[VAL_1]]#0 : !fir.ref +! CHECK: %[[VAL_10:.*]] = fir.convert %[[VAL_9]] : (i32) -> i64 +! CHECK: %[[VAL_11:.*]] = fir.convert %[[VAL_10]] : (i64) -> index +! CHECK: %[[VAL_12:.*]] = arith.constant 0 : index +! 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.shape<2>, !fir.dscope) -> (!fir.box>, !fir.ref>) +! CHECK: %[[VAL_17:.*]] = acc.copyin var(%[[VAL_16]]#0 : !fir.box>) -> !fir.box> {dataClause = #acc, name = "x"} +! CHECK: acc.parallel dataOperands(%[[VAL_17]] : !fir.box>) { +! CHECK: %[[VAL_18:.*]] = fir.box_addr %[[VAL_17]] : (!fir.box>) -> !fir.ref> +! 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.shape<2>, !fir.dscope) -> (!fir.box>, !fir.ref>) +! 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>, index, index) -> !fir.ref +! CHECK: fir.call @_QPtakes_scalar(%[[VAL_23]]) fastmath : (!fir.ref) -> () +! CHECK: acc.yield +! CHECK: } +! CHECK: acc.copyout accVar(%[[VAL_17]] : !fir.box>) to var(%[[VAL_16]]#0 : !fir.box>) {dataClause = #acc, name = "x"} +! CHECK: return +! CHECK: } + +! CHECK-LABEL: func.func @_QMmPaddressing_assumed_shape( +! CHECK-SAME: %[[ARG0:.*]]: !fir.box> {fir.bindc_name = "x"}, +! CHECK-SAME: %[[ARG1:.*]]: !fir.ref {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, !fir.dscope) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %[[VAL_0]] {uniq_name = "_QMmFaddressing_assumed_shapeEx"} : (!fir.box>, !fir.dscope) -> (!fir.box>, !fir.box>) +! CHECK: %[[VAL_3:.*]] = acc.copyin var(%[[VAL_2]]#0 : !fir.box>) -> !fir.box> {dataClause = #acc, name = "x"} +! CHECK: acc.parallel dataOperands(%[[VAL_3]] : !fir.box>) { +! 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.dscope) -> (!fir.box>, !fir.box>) +! 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>, index, index) -> !fir.ref +! CHECK: fir.call @_QPtakes_scalar(%[[VAL_8]]) fastmath : (!fir.ref) -> () +! CHECK: acc.yield +! CHECK: } +! CHECK: acc.copyout accVar(%[[VAL_3]] : !fir.box>) to var(%[[VAL_2]]#0 : !fir.box>) {dataClause = #acc, name = "x"} +! CHECK: return +! CHECK: } + +! CHECK-LABEL: func.func @_QMmPaddressing_contiguous_assumed_shape( +! CHECK-SAME: %[[ARG0:.*]]: !fir.box> {fir.bindc_name = "x", fir.contiguous}, +! CHECK-SAME: %[[ARG1:.*]]: !fir.ref {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, !fir.dscope) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_2:.*]] = fir.box_addr %[[ARG0]] : (!fir.box>) -> !fir.ref> +! CHECK: %[[VAL_3:.*]] = arith.constant 0 : index +! CHECK: %[[VAL_4:.*]]:3 = fir.box_dims %[[ARG0]], %[[VAL_3]] : (!fir.box>, index) -> (index, index, index) +! CHECK: %[[VAL_5:.*]] = arith.constant 1 : index +! CHECK: %[[VAL_6:.*]] = arith.constant 1 : index +! CHECK: %[[VAL_7:.*]]:3 = fir.box_dims %[[ARG0]], %[[VAL_6]] : (!fir.box>, 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, uniq_name = "_QMmFaddressing_contiguous_assumed_shapeEx"} : (!fir.ref>, !fir.shapeshift<2>, !fir.dscope) -> (!fir.box>, !fir.ref>) +! CHECK: %[[VAL_11:.*]] = acc.copyin var(%[[VAL_10]]#0 : !fir.box>) -> !fir.box> {dataClause = #acc, name = "x"} +! CHECK: acc.parallel dataOperands(%[[VAL_11]] : !fir.box>) { +! CHECK: %[[VAL_12:.*]] = fir.box_addr %[[VAL_11]] : (!fir.box>) -> !fir.ref> +! 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, uniq_name = "_QMmFaddressing_contiguous_assumed_shapeEx"} : (!fir.ref>, !fir.shapeshift<2>, !fir.dscope) -> (!fir.box>, !fir.ref>) +! 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>, index, index) -> !fir.ref +! CHECK: fir.call @_QPtakes_scalar(%[[VAL_17]]) fastmath : (!fir.ref) -> () +! CHECK: acc.yield +! CHECK: } +! CHECK: acc.copyout accVar(%[[VAL_11]] : !fir.box>) to var(%[[VAL_10]]#0 : !fir.box>) {dataClause = #acc, name = "x"} +! CHECK: return +! CHECK: } + +! CHECK-LABEL: func.func @_QMmPaddressing_pointer( +! CHECK-SAME: %[[ARG0:.*]]: !fir.ref>>> {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, uniq_name = "_QMmFaddressing_pointerEx"} : (!fir.ref>>>, !fir.dscope) -> (!fir.ref>>>, !fir.ref>>>) +! CHECK: %[[VAL_2:.*]] = acc.copyin varPtr(%[[VAL_1]]#0 : !fir.ref>>>) -> !fir.ref>>> {dataClause = #acc, name = "x"} +! CHECK: acc.parallel dataOperands(%[[VAL_2]] : !fir.ref>>>) { +! 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, uniq_name = "_QMmFaddressing_pointerEx"} : (!fir.ref>>>, !fir.dscope) -> (!fir.ref>>>, !fir.ref>>>) +! CHECK: %[[VAL_5:.*]] = fir.load %[[VAL_4]]#0 : !fir.ref>>> +! CHECK: %[[VAL_6:.*]] = arith.constant 2 : index +! CHECK: %[[VAL_7:.*]] = arith.constant 3 : index +! CHECK: %[[VAL_8:.*]] = hlfir.designate %[[VAL_5]] (%[[VAL_6]], %[[VAL_7]]) : (!fir.box>>, index, index) -> !fir.ref +! CHECK: fir.call @_QPtakes_scalar(%[[VAL_8]]) fastmath : (!fir.ref) -> () +! CHECK: acc.yield +! CHECK: } +! CHECK: acc.copyout accPtr(%[[VAL_2]] : !fir.ref>>>) to varPtr(%[[VAL_1]]#0 : !fir.ref>>>) {dataClause = #acc, name = "x"} +! CHECK: return +! CHECK: } + +! CHECK-LABEL: func.func @_QMmPtest_optional_scalar( +! CHECK-SAME: %[[ARG0:.*]]: !fir.ref {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, uniq_name = "_QMmFtest_optional_scalarEx"} : (!fir.ref, !fir.dscope) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_2:.*]] = acc.copyin varPtr(%[[VAL_1]]#0 : !fir.ref) -> !fir.ref {dataClause = #acc, name = "x"} +! CHECK: acc.parallel dataOperands(%[[VAL_2]] : !fir.ref) { +! 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, uniq_name = "_QMmFtest_optional_scalarEx"} : (!fir.ref, !fir.dscope) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_5:.*]] = fir.is_present %[[VAL_4]]#0 : (!fir.ref) -> i1 +! CHECK: %[[VAL_6:.*]] = fir.if %[[VAL_5]] -> (!fir.ref) { +! CHECK: fir.result %[[VAL_4]]#0 : !fir.ref +! CHECK: } else { +! CHECK: %[[VAL_7:.*]] = fir.absent !fir.ref +! CHECK: fir.result %[[VAL_7]] : !fir.ref +! CHECK: } +! CHECK: fir.call @_QPtakes_optional_scalar(%[[VAL_6]]) fastmath : (!fir.ref) -> () +! CHECK: acc.yield +! CHECK: } +! CHECK: acc.copyout accPtr(%[[VAL_2]] : !fir.ref) to varPtr(%[[VAL_1]]#0 : !fir.ref) {dataClause = #acc, name = "x"} +! CHECK: return +! CHECK: } + +! CHECK-LABEL: func.func @_QMmPtest_optional_explicit_cst_shape( +! CHECK-SAME: %[[ARG0:.*]]: !fir.ref> {fir.bindc_name = "x", fir.optional}) { +! 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, uniq_name = "_QMmFtest_optional_explicit_cst_shapeEx"} : (!fir.ref>, !fir.shape<1>, !fir.dscope) -> (!fir.ref>, !fir.ref>) +! CHECK: %[[VAL_4:.*]] = acc.copyin varPtr(%[[VAL_3]]#0 : !fir.ref>) -> !fir.ref> {dataClause = #acc, name = "x"} +! CHECK: acc.parallel dataOperands(%[[VAL_4]] : !fir.ref>) { +! 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, uniq_name = "_QMmFtest_optional_explicit_cst_shapeEx"} : (!fir.ref>, !fir.shape<1>, !fir.dscope) -> (!fir.ref>, !fir.ref>) +! CHECK: %[[VAL_7:.*]] = fir.is_present %[[VAL_6]]#0 : (!fir.ref>) -> i1 +! CHECK: %[[VAL_8:.*]] = fir.if %[[VAL_7]] -> (!fir.ref>) { +! CHECK: fir.result %[[VAL_6]]#0 : !fir.ref> +! CHECK: } else { +! CHECK: %[[VAL_9:.*]] = fir.absent !fir.ref> +! CHECK: fir.result %[[VAL_9]] : !fir.ref> +! CHECK: } +! CHECK: fir.call @_QPtakes_optional_explicit_cst_shape(%[[VAL_8]]) fastmath : (!fir.ref>) -> () +! CHECK: acc.yield +! CHECK: } +! CHECK: acc.copyout accPtr(%[[VAL_4]] : !fir.ref>) to varPtr(%[[VAL_3]]#0 : !fir.ref>) {dataClause = #acc, name = "x"} +! CHECK: return +! CHECK: } + +! CHECK-LABEL: func.func @_QMmPtest_optional_explicit_shape( +! CHECK-SAME: %[[ARG0:.*]]: !fir.ref> {fir.bindc_name = "x", fir.optional}, +! CHECK-SAME: %[[ARG1:.*]]: !fir.ref {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, !fir.dscope) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_2:.*]] = fir.load %[[VAL_1]]#0 : !fir.ref +! CHECK: %[[VAL_3:.*]] = fir.convert %[[VAL_2]] : (i32) -> i64 +! CHECK: %[[VAL_4:.*]] = fir.convert %[[VAL_3]] : (i64) -> index +! CHECK: %[[VAL_5:.*]] = arith.constant 0 : index +! 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, uniq_name = "_QMmFtest_optional_explicit_shapeEx"} : (!fir.ref>, !fir.shape<1>, !fir.dscope) -> (!fir.box>, !fir.ref>) +! CHECK: %[[VAL_10:.*]] = acc.copyin varPtr(%[[VAL_9]]#1 : !fir.ref>) -> !fir.ref> {dataClause = #acc, name = "x"} +! CHECK: acc.parallel dataOperands(%[[VAL_10]] : !fir.ref>) { +! 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, uniq_name = "_QMmFtest_optional_explicit_shapeEx"} : (!fir.ref>, !fir.shape<1>, !fir.dscope) -> (!fir.box>, !fir.ref>) +! CHECK: %[[VAL_13:.*]] = fir.is_present %[[VAL_12]]#0 : (!fir.box>) -> i1 +! CHECK: %[[VAL_14:.*]] = fir.if %[[VAL_13]] -> (!fir.ref>) { +! CHECK: fir.result %[[VAL_12]]#1 : !fir.ref> +! CHECK: } else { +! CHECK: %[[VAL_15:.*]] = fir.absent !fir.ref> +! CHECK: fir.result %[[VAL_15]] : !fir.ref> +! CHECK: } +! CHECK: fir.call @_QPtakes_optional_explicit_shape(%[[VAL_14]], %[[VAL_1]]#0) fastmath : (!fir.ref>, !fir.ref) -> () +! CHECK: acc.yield +! CHECK: } +! CHECK: acc.copyout accPtr(%[[VAL_10]] : !fir.ref>) to varPtr(%[[VAL_9]]#1 : !fir.ref>) {dataClause = #acc, name = "x"} +! CHECK: return +! CHECK: } + +! CHECK-LABEL: func.func @_QMmPtest_optional_assumed_shape( +! CHECK-SAME: %[[ARG0:.*]]: !fir.box> {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, uniq_name = "_QMmFtest_optional_assumed_shapeEx"} : (!fir.box>, !fir.dscope) -> (!fir.box>, !fir.box>) +! CHECK: %[[VAL_2:.*]] = acc.copyin var(%[[VAL_1]]#0 : !fir.box>) -> !fir.box> {dataClause = #acc, name = "x"} +! CHECK: acc.parallel dataOperands(%[[VAL_2]] : !fir.box>) { +! 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, uniq_name = "_QMmFtest_optional_assumed_shapeEx"} : (!fir.box>, !fir.dscope) -> (!fir.box>, !fir.box>) +! CHECK: %[[VAL_5:.*]] = fir.is_present %[[VAL_4]]#0 : (!fir.box>) -> i1 +! CHECK: %[[VAL_6:.*]] = fir.if %[[VAL_5]] -> (!fir.box>) { +! CHECK: fir.result %[[VAL_4]]#0 : !fir.box> +! CHECK: } else { +! CHECK: %[[VAL_7:.*]] = fir.absent !fir.box> +! CHECK: fir.result %[[VAL_7]] : !fir.box> +! CHECK: } +! CHECK: fir.call @_QPtakes_optional_assumed_shape(%[[VAL_6]]) fastmath : (!fir.box>) -> () +! CHECK: acc.yield +! CHECK: } +! CHECK: acc.copyout accVar(%[[VAL_2]] : !fir.box>) to var(%[[VAL_1]]#0 : !fir.box>) {dataClause = #acc, name = "x"} +! CHECK: return +! CHECK: } + +! CHECK-LABEL: func.func @_QMmPtest_optional_pointer( +! CHECK-SAME: %[[ARG0:.*]]: !fir.ref>>> {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, uniq_name = "_QMmFtest_optional_pointerEx"} : (!fir.ref>>>, !fir.dscope) -> (!fir.ref>>>, !fir.ref>>>) +! CHECK: %[[VAL_2:.*]] = acc.copyin varPtr(%[[VAL_1]]#0 : !fir.ref>>>) -> !fir.ref>>> {dataClause = #acc, name = "x"} +! CHECK: acc.parallel dataOperands(%[[VAL_2]] : !fir.ref>>>) { +! 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, uniq_name = "_QMmFtest_optional_pointerEx"} : (!fir.ref>>>, !fir.dscope) -> (!fir.ref>>>, !fir.ref>>>) +! CHECK: fir.call @_QPtakes_optional_pointer(%[[VAL_4]]#0) fastmath : (!fir.ref>>>) -> () +! CHECK: acc.yield +! CHECK: } +! CHECK: acc.copyout accPtr(%[[VAL_2]] : !fir.ref>>>) to varPtr(%[[VAL_1]]#0 : !fir.ref>>>) {dataClause = #acc, name = "x"} +! CHECK: return +! CHECK: } 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 bc94837b0e4f3..429f207bb5669 100644 --- a/flang/test/Lower/OpenACC/acc-firstprivate-derived-allocatable-component.f90 +++ b/flang/test/Lower/OpenACC/acc-firstprivate-derived-allocatable-component.f90 @@ -41,19 +41,21 @@ subroutine test(a) ! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_4]] {uniq_name = "_QMm_firstprivate_derived_alloc_compFtestEn"} : (!fir.ref) -> (!fir.ref, !fir.ref) ! CHECK: %[[VAL_6:.*]] = acc.firstprivate varPtr(%[[VAL_1]]#0 : !fir.ref>>}>>) -> !fir.ref>>}>> {name = "a"} ! CHECK: acc.parallel combined(loop) firstprivate(@firstprivatization_ref_rec__QMm_firstprivate_derived_alloc_compTpoint -> %[[VAL_6]] : !fir.ref>>}>>) { -! CHECK: %[[VAL_7:.*]] = arith.constant 1 : i32 -! CHECK: %[[VAL_8:.*]] = fir.load %[[VAL_5]]#0 : !fir.ref +! 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.dscope) -> (!fir.ref>>}>>, !fir.ref>>}>>) ! CHECK: %[[VAL_9:.*]] = arith.constant 1 : i32 -! CHECK: %[[VAL_10:.*]] = acc.private varPtr(%[[VAL_3]]#0 : !fir.ref) -> !fir.ref {implicit = true, name = "i"} -! CHECK: %[[VAL_11:.*]]:2 = hlfir.declare %[[VAL_10]] {uniq_name = "_QMm_firstprivate_derived_alloc_compFtestEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) -! CHECK: acc.loop combined(parallel) private(@privatization_ref_i32 -> %[[VAL_10]] : !fir.ref) control(%[[VAL_12:.*]] : i32) = (%[[VAL_7]] : i32) to (%[[VAL_8]] : i32) step (%[[VAL_9]] : i32) { -! CHECK: fir.store %[[VAL_12]] to %[[VAL_11]]#0 : !fir.ref -! CHECK: %[[VAL_13:.*]] = arith.constant 1.000000e+00 : f32 -! CHECK: %[[VAL_14:.*]] = hlfir.designate %[[VAL_1]]#0{"x"} {fortran_attrs = #fir.var_attrs} : (!fir.ref>>}>>) -> !fir.ref>>> -! CHECK: %[[VAL_15:.*]] = fir.load %[[VAL_14]] : !fir.ref>>> -! CHECK: %[[VAL_16:.*]] = arith.constant 10 : index -! CHECK: %[[VAL_17:.*]] = hlfir.designate %[[VAL_15]] (%[[VAL_16]]) : (!fir.box>>, index) -> !fir.ref -! CHECK: hlfir.assign %[[VAL_13]] to %[[VAL_17]] : f32, !fir.ref +! CHECK: %[[VAL_10:.*]] = fir.load %[[VAL_5]]#0 : !fir.ref +! CHECK: %[[VAL_11:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_12:.*]] = acc.private varPtr(%[[VAL_3]]#0 : !fir.ref) -> !fir.ref {implicit = true, name = "i"} +! CHECK: acc.loop combined(parallel) private(@privatization_ref_i32 -> %[[VAL_12]] : !fir.ref) 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) -> (!fir.ref, !fir.ref) +! CHECK: fir.store %[[VAL_14]] to %[[VAL_13]]#0 : !fir.ref +! CHECK: %[[VAL_15:.*]] = arith.constant 1.000000e+00 : f32 +! CHECK: %[[VAL_16:.*]] = hlfir.designate %[[VAL_8]]#0{"x"} {fortran_attrs = #fir.var_attrs} : (!fir.ref>>}>>) -> !fir.ref>>> +! CHECK: %[[VAL_17:.*]] = fir.load %[[VAL_16]] : !fir.ref>>> +! CHECK: %[[VAL_18:.*]] = arith.constant 10 : index +! CHECK: %[[VAL_19:.*]] = hlfir.designate %[[VAL_17]] (%[[VAL_18]]) : (!fir.box>>, index) -> !fir.ref +! CHECK: hlfir.assign %[[VAL_15]] to %[[VAL_19]] : f32, !fir.ref ! CHECK: acc.yield ! CHECK: } attributes {inclusiveUpperbound = array, independent = [#acc.device_type]} ! CHECK: acc.yield 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 f18d722921710..9ef4fe6913551 100644 --- a/flang/test/Lower/OpenACC/acc-firstprivate-derived-pointer-component.f90 +++ b/flang/test/Lower/OpenACC/acc-firstprivate-derived-pointer-component.f90 @@ -41,19 +41,21 @@ subroutine test(a) ! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_4]] {uniq_name = "_QMm_firstprivate_derived_ptr_compFtestEn"} : (!fir.ref) -> (!fir.ref, !fir.ref) ! CHECK: %[[VAL_6:.*]] = acc.firstprivate varPtr(%[[VAL_1]]#0 : !fir.ref>>}>>) -> !fir.ref>>}>> {name = "a"} ! CHECK: acc.parallel combined(loop) firstprivate(@firstprivatization_ref_rec__QMm_firstprivate_derived_ptr_compTpoint -> %[[VAL_6]] : !fir.ref>>}>>) { -! CHECK: %[[VAL_7:.*]] = arith.constant 1 : i32 -! CHECK: %[[VAL_8:.*]] = fir.load %[[VAL_5]]#0 : !fir.ref +! 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.dscope) -> (!fir.ref>>}>>, !fir.ref>>}>>) ! CHECK: %[[VAL_9:.*]] = arith.constant 1 : i32 -! CHECK: %[[VAL_10:.*]] = acc.private varPtr(%[[VAL_3]]#0 : !fir.ref) -> !fir.ref {implicit = true, name = "i"} -! CHECK: %[[VAL_11:.*]]:2 = hlfir.declare %[[VAL_10]] {uniq_name = "_QMm_firstprivate_derived_ptr_compFtestEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) -! CHECK: acc.loop combined(parallel) private(@privatization_ref_i32 -> %[[VAL_10]] : !fir.ref) control(%[[VAL_12:.*]] : i32) = (%[[VAL_7]] : i32) to (%[[VAL_8]] : i32) step (%[[VAL_9]] : i32) { -! CHECK: fir.store %[[VAL_12]] to %[[VAL_11]]#0 : !fir.ref -! CHECK: %[[VAL_13:.*]] = arith.constant 1.000000e+00 : f32 -! CHECK: %[[VAL_14:.*]] = hlfir.designate %[[VAL_1]]#0{"x"} {fortran_attrs = #fir.var_attrs} : (!fir.ref>>}>>) -> !fir.ref>>> -! CHECK: %[[VAL_15:.*]] = fir.load %[[VAL_14]] : !fir.ref>>> -! CHECK: %[[VAL_16:.*]] = arith.constant 10 : index -! CHECK: %[[VAL_17:.*]] = hlfir.designate %[[VAL_15]] (%[[VAL_16]]) : (!fir.box>>, index) -> !fir.ref -! CHECK: hlfir.assign %[[VAL_13]] to %[[VAL_17]] : f32, !fir.ref +! CHECK: %[[VAL_10:.*]] = fir.load %[[VAL_5]]#0 : !fir.ref +! CHECK: %[[VAL_11:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_12:.*]] = acc.private varPtr(%[[VAL_3]]#0 : !fir.ref) -> !fir.ref {implicit = true, name = "i"} +! CHECK: acc.loop combined(parallel) private(@privatization_ref_i32 -> %[[VAL_12]] : !fir.ref) 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) -> (!fir.ref, !fir.ref) +! CHECK: fir.store %[[VAL_14]] to %[[VAL_13]]#0 : !fir.ref +! CHECK: %[[VAL_15:.*]] = arith.constant 1.000000e+00 : f32 +! CHECK: %[[VAL_16:.*]] = hlfir.designate %[[VAL_8]]#0{"x"} {fortran_attrs = #fir.var_attrs} : (!fir.ref>>}>>) -> !fir.ref>>> +! CHECK: %[[VAL_17:.*]] = fir.load %[[VAL_16]] : !fir.ref>>> +! CHECK: %[[VAL_18:.*]] = arith.constant 10 : index +! CHECK: %[[VAL_19:.*]] = hlfir.designate %[[VAL_17]] (%[[VAL_18]]) : (!fir.box>>, index) -> !fir.ref +! CHECK: hlfir.assign %[[VAL_15]] to %[[VAL_19]] : f32, !fir.ref ! CHECK: acc.yield ! CHECK: } attributes {inclusiveUpperbound = array, independent = [#acc.device_type]} ! CHECK: acc.yield 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 f389c46cca55a..e90ec323bd4c7 100644 --- a/flang/test/Lower/OpenACC/acc-firstprivate-derived-user-assign.f90 +++ b/flang/test/Lower/OpenACC/acc-firstprivate-derived-user-assign.f90 @@ -55,16 +55,17 @@ subroutine test() ! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_5]] {uniq_name = "_QMm_firstprivate_derived_user_defFtestEn"} : (!fir.ref) -> (!fir.ref, !fir.ref) ! CHECK: %[[VAL_7:.*]] = acc.firstprivate varPtr(%[[VAL_2]]#0 : !fir.ref>) -> !fir.ref> {name = "a"} ! CHECK: acc.parallel combined(loop) firstprivate(@firstprivatization_ref_rec__QMm_firstprivate_derived_user_defTpoint -> %[[VAL_7]] : !fir.ref>) { -! CHECK: %[[VAL_8:.*]] = arith.constant 1 : i32 -! CHECK: %[[VAL_9:.*]] = fir.load %[[VAL_6]]#0 : !fir.ref -! CHECK: %[[VAL_10:.*]] = arith.constant 1 : i32 -! CHECK: %[[VAL_11:.*]] = acc.private varPtr(%[[VAL_4]]#0 : !fir.ref) -> !fir.ref {implicit = true, name = "i"} -! CHECK: %[[VAL_12:.*]]:2 = hlfir.declare %[[VAL_11]] {uniq_name = "_QMm_firstprivate_derived_user_defFtestEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) -! CHECK: acc.loop combined(parallel) private(@privatization_ref_i32 -> %[[VAL_11]] : !fir.ref) control(%[[VAL_13:.*]] : i32) = (%[[VAL_8]] : i32) to (%[[VAL_9]] : i32) step (%[[VAL_10]] : i32) { -! CHECK: fir.store %[[VAL_13]] to %[[VAL_12]]#0 : !fir.ref -! CHECK: %[[VAL_14:.*]] = arith.constant 1.000000e+00 : f32 -! CHECK: %[[VAL_15:.*]] = hlfir.designate %[[VAL_2]]#0{"x"} : (!fir.ref>) -> !fir.ref -! CHECK: hlfir.assign %[[VAL_14]] to %[[VAL_15]] : f32, !fir.ref +! CHECK: %[[VAL_8:.*]]:2 = hlfir.declare %[[VAL_7]] {uniq_name = "_QMm_firstprivate_derived_user_defFtestEa"} : (!fir.ref>) -> (!fir.ref>, !fir.ref>) +! CHECK: %[[VAL_9:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_10:.*]] = fir.load %[[VAL_6]]#0 : !fir.ref +! CHECK: %[[VAL_11:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_12:.*]] = acc.private varPtr(%[[VAL_4]]#0 : !fir.ref) -> !fir.ref {implicit = true, name = "i"} +! CHECK: acc.loop combined(parallel) private(@privatization_ref_i32 -> %[[VAL_12]] : !fir.ref) 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) -> (!fir.ref, !fir.ref) +! CHECK: fir.store %[[VAL_14]] to %[[VAL_13]]#0 : !fir.ref +! CHECK: %[[VAL_15:.*]] = arith.constant 1.000000e+00 : f32 +! CHECK: %[[VAL_16:.*]] = hlfir.designate %[[VAL_8]]#0{"x"} : (!fir.ref>) -> !fir.ref +! CHECK: hlfir.assign %[[VAL_15]] to %[[VAL_16]] : f32, !fir.ref ! CHECK: acc.yield ! CHECK: } attributes {inclusiveUpperbound = array, independent = [#acc.device_type]} ! CHECK: acc.yield diff --git a/flang/test/Lower/OpenACC/acc-firstprivate-derived.f90 b/flang/test/Lower/OpenACC/acc-firstprivate-derived.f90 index 677c3aea4f554..e91fc9b45cd29 100644 --- a/flang/test/Lower/OpenACC/acc-firstprivate-derived.f90 +++ b/flang/test/Lower/OpenACC/acc-firstprivate-derived.f90 @@ -41,16 +41,17 @@ subroutine test() ! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_5]] {uniq_name = "_QMm_firstprivate_derivedFtestEn"} : (!fir.ref) -> (!fir.ref, !fir.ref) ! CHECK: %[[VAL_7:.*]] = acc.firstprivate varPtr(%[[VAL_2]]#0 : !fir.ref>) -> !fir.ref> {name = "a"} ! CHECK: acc.parallel combined(loop) firstprivate(@firstprivatization_ref_rec__QMm_firstprivate_derivedTpoint -> %[[VAL_7]] : !fir.ref>) { -! CHECK: %[[VAL_8:.*]] = arith.constant 1 : i32 -! CHECK: %[[VAL_9:.*]] = fir.load %[[VAL_6]]#0 : !fir.ref -! CHECK: %[[VAL_10:.*]] = arith.constant 1 : i32 -! CHECK: %[[VAL_11:.*]] = acc.private varPtr(%[[VAL_4]]#0 : !fir.ref) -> !fir.ref {implicit = true, name = "i"} -! CHECK: %[[VAL_12:.*]]:2 = hlfir.declare %[[VAL_11]] {uniq_name = "_QMm_firstprivate_derivedFtestEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) -! CHECK: acc.loop combined(parallel) private(@privatization_ref_i32 -> %[[VAL_11]] : !fir.ref) control(%[[VAL_13:.*]] : i32) = (%[[VAL_8]] : i32) to (%[[VAL_9]] : i32) step (%[[VAL_10]] : i32) { -! CHECK: fir.store %[[VAL_13]] to %[[VAL_12]]#0 : !fir.ref -! CHECK: %[[VAL_14:.*]] = arith.constant 1.000000e+00 : f32 -! CHECK: %[[VAL_15:.*]] = hlfir.designate %[[VAL_2]]#0{"x"} : (!fir.ref>) -> !fir.ref -! CHECK: hlfir.assign %[[VAL_14]] to %[[VAL_15]] : f32, !fir.ref +! CHECK: %[[VAL_8:.*]]:2 = hlfir.declare %[[VAL_7]] {uniq_name = "_QMm_firstprivate_derivedFtestEa"} : (!fir.ref>) -> (!fir.ref>, !fir.ref>) +! CHECK: %[[VAL_9:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_10:.*]] = fir.load %[[VAL_6]]#0 : !fir.ref +! CHECK: %[[VAL_11:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_12:.*]] = acc.private varPtr(%[[VAL_4]]#0 : !fir.ref) -> !fir.ref {implicit = true, name = "i"} +! CHECK: acc.loop combined(parallel) private(@privatization_ref_i32 -> %[[VAL_12]] : !fir.ref) 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) -> (!fir.ref, !fir.ref) +! CHECK: fir.store %[[VAL_14]] to %[[VAL_13]]#0 : !fir.ref +! CHECK: %[[VAL_15:.*]] = arith.constant 1.000000e+00 : f32 +! CHECK: %[[VAL_16:.*]] = hlfir.designate %[[VAL_8]]#0{"x"} : (!fir.ref>) -> !fir.ref +! CHECK: hlfir.assign %[[VAL_15]] to %[[VAL_16]] : f32, !fir.ref ! CHECK: acc.yield ! CHECK: } attributes {inclusiveUpperbound = array, independent = [#acc.device_type]} ! CHECK: acc.yield diff --git a/flang/test/Lower/OpenACC/acc-loop-exit.f90 b/flang/test/Lower/OpenACC/acc-loop-exit.f90 index 85394e4a5b74c..af11b34d5f65f 100644 --- a/flang/test/Lower/OpenACC/acc-loop-exit.f90 +++ b/flang/test/Lower/OpenACC/acc-loop-exit.f90 @@ -16,8 +16,8 @@ subroutine sub1(x, a) ! CHECK-LABEL: func.func @_QPsub1 ! CHECK: %[[A:.*]]:2 = hlfir.declare %arg1 dummy_scope %{{[0-9]+}} {uniq_name = "_QFsub1Ea"} : (!fir.ref, !fir.dscope) -> (!fir.ref, !fir.ref) ! CHECK: %[[I:.*]]:2 = hlfir.declare %{{[0-9]+}} {uniq_name = "_QFsub1Ei"} : (!fir.ref) -> (!fir.ref, !fir.ref) -! CHECK: %[[I:.*]]:2 = hlfir.declare %{{[0-9]+}} {uniq_name = "_QFsub1Ei"} : (!fir.ref) -> (!fir.ref, !fir.ref) ! CHECK: %[[EXIT_COND:.*]] = acc.loop +! CHECK: %[[I:.*]]:2 = hlfir.declare %{{[0-9]+}} {uniq_name = "_QFsub1Ei"} : (!fir.ref) -> (!fir.ref, !fir.ref) ! CHECK: ^bb{{.*}}: ! CHECK: ^bb{{.*}}: ! CHECK: %[[LOAD_I:.*]] = fir.load %[[I]]#0 : !fir.ref diff --git a/flang/test/Lower/OpenACC/acc-private.f90 b/flang/test/Lower/OpenACC/acc-private.f90 index 5ca08a39a1e1c..d37eb8d7aaf6d 100644 --- a/flang/test/Lower/OpenACC/acc-private.f90 +++ b/flang/test/Lower/OpenACC/acc-private.f90 @@ -426,7 +426,7 @@ subroutine acc_private_use() ! CHECK: %[[DECL_I:.*]]:2 = hlfir.declare %[[I]] {uniq_name = "_QFacc_private_useEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) ! CHECK: acc.parallel ! CHECK: %[[PRIV_I:.*]] = acc.private varPtr(%[[DECL_I]]#0 : !fir.ref) -> !fir.ref {implicit = true, name = "i"} -! CHECK: %[[DECL_PRIV_I:.*]]:2 = hlfir.declare %[[PRIV_I]] {uniq_name = "_QFacc_private_useEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) ! CHECK: acc.loop {{.*}} private(@privatization_ref_i32 -> %[[PRIV_I]] : !fir.ref) 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) -> (!fir.ref, !fir.ref) ! CHECK: fir.store %[[IV0]] to %[[DECL_PRIV_I]]#0 : !fir.ref ! CHECK: %{{.*}} = fir.load %[[DECL_PRIV_I]]#0 : !fir.ref 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 a75a022690fcc..eaf734f155157 100644 --- a/flang/test/Lower/OpenACC/do-loops-to-acc-loops.f90 +++ b/flang/test/Lower/OpenACC/do-loops-to-acc-loops.f90 @@ -19,8 +19,8 @@ subroutine basic_do_loop() ! CHECK: acc.kernels { ! CHECK: %[[PRIVATE_IV:.*]] = acc.private varPtr(%{{.*}} : !fir.ref) -> !fir.ref {implicit = true, name = "i"} -! CHECK: %[[PRIVATE_DECLARE:.*]]:2 = hlfir.declare %[[PRIVATE_IV]] {uniq_name = "_QFbasic_do_loopEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) ! CHECK: acc.loop private(@privatization_ref_i32 -> %[[PRIVATE_IV]] : !fir.ref) control(%{{.*}} : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) +! CHECK: %[[PRIVATE_DECLARE:.*]]:2 = hlfir.declare %[[PRIVATE_IV]] {uniq_name = "_QFbasic_do_loopEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) ! CHECK: fir.store %{{.*}} to %[[PRIVATE_DECLARE]]#0 : !fir.ref ! CHECK: %{{.*}} = fir.load %[[PRIVATE_DECLARE]]#0 : !fir.ref ! CHECK: %{{.*}} = fir.load %[[PRIVATE_DECLARE]]#0 : !fir.ref @@ -48,8 +48,8 @@ subroutine basic_do_concurrent() ! CHECK: acc.kernels { ! CHECK: %[[PRIVATE_IV:.*]] = acc.private varPtr(%{{.*}} : !fir.ref) -> !fir.ref {implicit = true, name = "i"} -! CHECK: %[[PRIVATE_DECLARE:.*]]:2 = hlfir.declare %[[PRIVATE_IV]] {uniq_name = "_QFbasic_do_concurrentEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) ! CHECK: acc.loop private(@privatization_ref_i32 -> %[[PRIVATE_IV]] : !fir.ref) control(%{{.*}} : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) +! CHECK: %[[PRIVATE_DECLARE:.*]]:2 = hlfir.declare %[[PRIVATE_IV]] {uniq_name = "_QFbasic_do_concurrentEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) ! CHECK: fir.store %{{.*}} to %[[PRIVATE_DECLARE]]#0 : !fir.ref ! CHECK: %{{.*}} = fir.load %[[PRIVATE_DECLARE]]#0 : !fir.ref ! CHECK: %{{.*}} = fir.load %[[PRIVATE_DECLARE]]#0 : !fir.ref @@ -77,8 +77,8 @@ subroutine basic_do_loop_parallel() ! CHECK: acc.parallel { ! CHECK: %[[PRIVATE_IV:.*]] = acc.private varPtr(%{{.*}} : !fir.ref) -> !fir.ref {implicit = true, name = "i"} -! CHECK: %[[PRIVATE_DECLARE:.*]]:2 = hlfir.declare %[[PRIVATE_IV]] {uniq_name = "_QFbasic_do_loop_parallelEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) ! CHECK: acc.loop private(@privatization_ref_i32 -> %[[PRIVATE_IV]] : !fir.ref) control(%{{.*}} : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) +! CHECK: %[[PRIVATE_DECLARE:.*]]:2 = hlfir.declare %[[PRIVATE_IV]] {uniq_name = "_QFbasic_do_loop_parallelEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) ! CHECK: fir.store %{{.*}} to %[[PRIVATE_DECLARE]]#0 : !fir.ref ! CHECK: %{{.*}} = fir.load %[[PRIVATE_DECLARE]]#0 : !fir.ref ! CHECK: %{{.*}} = fir.load %[[PRIVATE_DECLARE]]#0 : !fir.ref @@ -106,8 +106,8 @@ subroutine basic_do_loop_serial() ! CHECK: acc.serial { ! CHECK: %[[PRIVATE_IV:.*]] = acc.private varPtr(%{{.*}} : !fir.ref) -> !fir.ref {implicit = true, name = "i"} -! CHECK: %[[PRIVATE_DECLARE:.*]]:2 = hlfir.declare %[[PRIVATE_IV]] {uniq_name = "_QFbasic_do_loop_serialEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) ! CHECK: acc.loop private(@privatization_ref_i32 -> %[[PRIVATE_IV]] : !fir.ref) control(%{{.*}} : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) +! CHECK: %[[PRIVATE_DECLARE:.*]]:2 = hlfir.declare %[[PRIVATE_IV]] {uniq_name = "_QFbasic_do_loop_serialEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) ! CHECK: fir.store %{{.*}} to %[[PRIVATE_DECLARE]]#0 : !fir.ref ! CHECK: %{{.*}} = fir.load %[[PRIVATE_DECLARE]]#0 : !fir.ref ! CHECK: %{{.*}} = fir.load %[[PRIVATE_DECLARE]]#0 : !fir.ref @@ -135,8 +135,8 @@ subroutine basic_do_concurrent_parallel() ! CHECK: acc.parallel { ! CHECK: %[[PRIVATE_IV:.*]] = acc.private varPtr(%{{.*}} : !fir.ref) -> !fir.ref {implicit = true, name = "i"} -! CHECK: %[[PRIVATE_DECLARE:.*]]:2 = hlfir.declare %[[PRIVATE_IV]] {uniq_name = "_QFbasic_do_concurrent_parallelEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) ! CHECK: acc.loop private(@privatization_ref_i32 -> %[[PRIVATE_IV]] : !fir.ref) control(%{{.*}} : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) +! CHECK: %[[PRIVATE_DECLARE:.*]]:2 = hlfir.declare %[[PRIVATE_IV]] {uniq_name = "_QFbasic_do_concurrent_parallelEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) ! CHECK: fir.store %{{.*}} to %[[PRIVATE_DECLARE]]#0 : !fir.ref ! CHECK: %{{.*}} = fir.load %[[PRIVATE_DECLARE]]#0 : !fir.ref ! CHECK: %{{.*}} = fir.load %[[PRIVATE_DECLARE]]#0 : !fir.ref @@ -164,8 +164,8 @@ subroutine basic_do_concurrent_serial() ! CHECK: acc.serial { ! CHECK: %[[PRIVATE_IV:.*]] = acc.private varPtr(%{{.*}} : !fir.ref) -> !fir.ref {implicit = true, name = "i"} -! CHECK: %[[PRIVATE_DECLARE:.*]]:2 = hlfir.declare %[[PRIVATE_IV]] {uniq_name = "_QFbasic_do_concurrent_serialEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) ! CHECK: acc.loop private(@privatization_ref_i32 -> %[[PRIVATE_IV]] : !fir.ref) control(%{{.*}} : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) +! CHECK: %[[PRIVATE_DECLARE:.*]]:2 = hlfir.declare %[[PRIVATE_IV]] {uniq_name = "_QFbasic_do_concurrent_serialEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) ! CHECK: fir.store %{{.*}} to %[[PRIVATE_DECLARE]]#0 : !fir.ref ! CHECK: %{{.*}} = fir.load %[[PRIVATE_DECLARE]]#0 : !fir.ref ! CHECK: %{{.*}} = fir.load %[[PRIVATE_DECLARE]]#0 : !fir.ref @@ -195,10 +195,10 @@ subroutine multi_dimension_do_concurrent() ! CHECK-DAG: %[[PRIVATE_I:.*]] = acc.private varPtr(%{{.*}} : !fir.ref) -> !fir.ref {implicit = true, name = "i"} ! CHECK-DAG: %[[PRIVATE_J:.*]] = acc.private varPtr(%{{.*}} : !fir.ref) -> !fir.ref {implicit = true, name = "j"} ! CHECK-DAG: %[[PRIVATE_K:.*]] = acc.private varPtr(%{{.*}} : !fir.ref) -> !fir.ref {implicit = true, name = "k"} +! CHECK: acc.loop private(@privatization_ref_i32 -> %[[PRIVATE_I]] : !fir.ref, @privatization_ref_i32 -> %[[PRIVATE_J]] : !fir.ref, @privatization_ref_i32 -> %[[PRIVATE_K]] : !fir.ref) 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) -> (!fir.ref, !fir.ref) ! CHECK-DAG: %[[PRIVATE_J_DECLARE:.*]]:2 = hlfir.declare %[[PRIVATE_J]] {uniq_name = "_QFmulti_dimension_do_concurrentEj"} : (!fir.ref) -> (!fir.ref, !fir.ref) ! CHECK-DAG: %[[PRIVATE_K_DECLARE:.*]]:2 = hlfir.declare %[[PRIVATE_K]] {uniq_name = "_QFmulti_dimension_do_concurrentEk"} : (!fir.ref) -> (!fir.ref, !fir.ref) -! CHECK: acc.loop private(@privatization_ref_i32 -> %[[PRIVATE_I]] : !fir.ref, @privatization_ref_i32 -> %[[PRIVATE_J]] : !fir.ref, @privatization_ref_i32 -> %[[PRIVATE_K]] : !fir.ref) control(%{{.*}} : i32, %{{.*}} : i32, %{{.*}} : i32) = (%c1{{.*}}, %c1{{.*}}, %c1{{.*}} : i32, i32, i32) to (%{{.*}}, %{{.*}}, %{{.*}} : i32, i32, i32) step (%c1{{.*}}, %c1{{.*}}, %c1{{.*}} : i32, i32, i32) ! CHECK: fir.store %{{.*}} to %[[PRIVATE_I_DECLARE]]#0 : !fir.ref ! CHECK: fir.store %{{.*}} to %[[PRIVATE_J_DECLARE]]#0 : !fir.ref ! CHECK: fir.store %{{.*}} to %[[PRIVATE_K_DECLARE]]#0 : !fir.ref @@ -235,12 +235,12 @@ subroutine nested_do_loops() ! CHECK: acc.kernels { ! CHECK-DAG: %[[PRIVATE_I:.*]] = acc.private varPtr(%{{.*}} : !fir.ref) -> !fir.ref {implicit = true, name = "i"} -! CHECK-DAG: %[[PRIVATE_I_DECLARE:.*]]:2 = hlfir.declare %[[PRIVATE_I]] {uniq_name = "_QFnested_do_loopsEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) ! CHECK: acc.loop private(@privatization_ref_i32 -> %[[PRIVATE_I]] : !fir.ref) control(%{{.*}} : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) +! CHECK-DAG: %[[PRIVATE_I_DECLARE:.*]]:2 = hlfir.declare %[[PRIVATE_I]] {uniq_name = "_QFnested_do_loopsEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) ! CHECK: fir.store %{{.*}} to %[[PRIVATE_I_DECLARE]]#0 : !fir.ref ! CHECK-DAG: %[[PRIVATE_J:.*]] = acc.private varPtr(%{{.*}} : !fir.ref) -> !fir.ref {implicit = true, name = "j"} -! CHECK-DAG: %[[PRIVATE_J_DECLARE:.*]]:2 = hlfir.declare %[[PRIVATE_J]] {uniq_name = "_QFnested_do_loopsEj"} : (!fir.ref) -> (!fir.ref, !fir.ref) ! CHECK: acc.loop private(@privatization_ref_i32 -> %[[PRIVATE_J]] : !fir.ref) control(%{{.*}} : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) +! CHECK-DAG: %[[PRIVATE_J_DECLARE:.*]]:2 = hlfir.declare %[[PRIVATE_J]] {uniq_name = "_QFnested_do_loopsEj"} : (!fir.ref) -> (!fir.ref, !fir.ref) ! CHECK: fir.store %{{.*}} to %[[PRIVATE_J_DECLARE]]#0 : !fir.ref ! CHECK: %{{.*}} = fir.load %[[PRIVATE_I_DECLARE]]#0 : !fir.ref ! CHECK: %{{.*}} = fir.load %[[PRIVATE_J_DECLARE]]#0 : !fir.ref @@ -272,8 +272,8 @@ subroutine variable_bounds_and_step(n, start_val, step_val) ! CHECK: acc.kernels { ! CHECK: %[[PRIVATE_IV:.*]] = acc.private varPtr(%{{.*}} : !fir.ref) -> !fir.ref {implicit = true, name = "i"} -! CHECK: %[[PRIVATE_DECLARE:.*]]:2 = hlfir.declare %[[PRIVATE_IV]] {uniq_name = "_QFvariable_bounds_and_stepEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) ! CHECK: acc.loop private(@privatization_ref_i32 -> %[[PRIVATE_IV]] : !fir.ref) control(%{{.*}} : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) +! CHECK: %[[PRIVATE_DECLARE:.*]]:2 = hlfir.declare %[[PRIVATE_IV]] {uniq_name = "_QFvariable_bounds_and_stepEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) ! CHECK: fir.store %{{.*}} to %[[PRIVATE_DECLARE]]#0 : !fir.ref ! CHECK: %{{.*}} = fir.load %[[PRIVATE_DECLARE]]#0 : !fir.ref ! CHECK: %{{.*}} = fir.load %[[PRIVATE_DECLARE]]#0 : !fir.ref @@ -315,22 +315,22 @@ subroutine different_iv_types() ! CHECK: acc.kernels { ! CHECK: %[[PRIVATE_I8:.*]] = acc.private varPtr(%{{.*}} : !fir.ref) -> !fir.ref {implicit = true, name = "i8"} -! CHECK: %[[PRIVATE_I8_DECLARE:.*]]:2 = hlfir.declare %[[PRIVATE_I8]] {uniq_name = "_QFdifferent_iv_typesEi8"} : (!fir.ref) -> (!fir.ref, !fir.ref) ! CHECK: acc.loop private(@privatization_ref_i64 -> %[[PRIVATE_I8]] : !fir.ref) control(%{{.*}} : i64) = (%{{.*}} : i64) to (%{{.*}} : i64) step (%{{.*}} : i64) +! CHECK: %[[PRIVATE_I8_DECLARE:.*]]:2 = hlfir.declare %[[PRIVATE_I8]] {uniq_name = "_QFdifferent_iv_typesEi8"} : (!fir.ref) -> (!fir.ref, !fir.ref) ! CHECK: fir.store %{{.*}} to %[[PRIVATE_I8_DECLARE]]#0 : !fir.ref ! CHECK: %{{.*}} = fir.load %[[PRIVATE_I8_DECLARE]]#0 : !fir.ref ! CHECK: %{{.*}} = fir.load %[[PRIVATE_I8_DECLARE]]#0 : !fir.ref ! CHECK: acc.kernels { ! CHECK: %[[PRIVATE_I4:.*]] = acc.private varPtr(%{{.*}} : !fir.ref) -> !fir.ref {implicit = true, name = "i4"} -! CHECK: %[[PRIVATE_I4_DECLARE:.*]]:2 = hlfir.declare %[[PRIVATE_I4]] {uniq_name = "_QFdifferent_iv_typesEi4"} : (!fir.ref) -> (!fir.ref, !fir.ref) ! CHECK: acc.loop private(@privatization_ref_i32 -> %[[PRIVATE_I4]] : !fir.ref) control(%{{.*}} : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) +! CHECK: %[[PRIVATE_I4_DECLARE:.*]]:2 = hlfir.declare %[[PRIVATE_I4]] {uniq_name = "_QFdifferent_iv_typesEi4"} : (!fir.ref) -> (!fir.ref, !fir.ref) ! CHECK: fir.store %{{.*}} to %[[PRIVATE_I4_DECLARE]]#0 : !fir.ref ! CHECK: %{{.*}} = fir.load %[[PRIVATE_I4_DECLARE]]#0 : !fir.ref ! CHECK: %{{.*}} = fir.load %[[PRIVATE_I4_DECLARE]]#0 : !fir.ref ! CHECK: acc.kernels { ! CHECK: %[[PRIVATE_I2:.*]] = acc.private varPtr(%{{.*}} : !fir.ref) -> !fir.ref {implicit = true, name = "i2"} -! CHECK: %[[PRIVATE_I2_DECLARE:.*]]:2 = hlfir.declare %[[PRIVATE_I2]] {uniq_name = "_QFdifferent_iv_typesEi2"} : (!fir.ref) -> (!fir.ref, !fir.ref) ! CHECK: acc.loop private(@privatization_ref_i16 -> %[[PRIVATE_I2]] : !fir.ref) control(%{{.*}} : i16) = (%{{.*}} : i16) to (%{{.*}} : i16) step (%{{.*}} : i16) +! CHECK: %[[PRIVATE_I2_DECLARE:.*]]:2 = hlfir.declare %[[PRIVATE_I2]] {uniq_name = "_QFdifferent_iv_typesEi2"} : (!fir.ref) -> (!fir.ref, !fir.ref) ! CHECK: fir.store %{{.*}} to %[[PRIVATE_I2_DECLARE]]#0 : !fir.ref ! CHECK: %{{.*}} = fir.load %[[PRIVATE_I2_DECLARE]]#0 : !fir.ref ! CHECK: %{{.*}} = fir.load %[[PRIVATE_I2_DECLARE]]#0 : !fir.ref @@ -362,12 +362,12 @@ subroutine nested_loop_with_reduction(x, y) ! CHECK: %[[REDUCTION_X:.*]] = acc.reduction varPtr(%{{.*}} : !fir.ref) -> !fir.ref {name = "x"} ! CHECK: %[[REDUCTION_Y:.*]] = acc.reduction varPtr(%{{.*}} : !fir.ref) -> !fir.ref {name = "y"} ! CHECK: %[[PRIVATE_I:.*]] = acc.private varPtr(%{{.*}} : !fir.ref) -> !fir.ref {implicit = true, name = "i"} -! CHECK: %[[PRIVATE_I_DECLARE:.*]]:2 = hlfir.declare %[[PRIVATE_I]] {uniq_name = "_QFnested_loop_with_reductionEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) ! CHECK: acc.loop private(@privatization_ref_i32 -> %[[PRIVATE_I]] : !fir.ref) reduction(@reduction_add_ref_i32 -> %[[REDUCTION_X]] : !fir.ref, @reduction_add_ref_i32 -> %[[REDUCTION_Y]] : !fir.ref) control(%{{.*}} : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) +! CHECK: %[[PRIVATE_I_DECLARE:.*]]:2 = hlfir.declare %[[PRIVATE_I]] {uniq_name = "_QFnested_loop_with_reductionEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) ! CHECK: fir.store %{{.*}} to %[[PRIVATE_I_DECLARE]]#0 : !fir.ref ! CHECK: %[[PRIVATE_J:.*]] = acc.private varPtr(%{{.*}} : !fir.ref) -> !fir.ref {implicit = true, name = "j"} -! CHECK: %[[PRIVATE_J_DECLARE:.*]]:2 = hlfir.declare %[[PRIVATE_J]] {uniq_name = "_QFnested_loop_with_reductionEj"} : (!fir.ref) -> (!fir.ref, !fir.ref) ! CHECK: acc.loop private(@privatization_ref_i32 -> %[[PRIVATE_J]] : !fir.ref) control(%{{.*}} : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) +! CHECK: %[[PRIVATE_J_DECLARE:.*]]:2 = hlfir.declare %[[PRIVATE_J]] {uniq_name = "_QFnested_loop_with_reductionEj"} : (!fir.ref) -> (!fir.ref, !fir.ref) ! CHECK: fir.store %{{.*}} to %[[PRIVATE_J_DECLARE]]#0 : !fir.ref ! CHECK: %{{.*}} = fir.load %{{.*}} : !fir.ref ! CHECK: %{{.*}} = arith.addi %{{.*}}, %{{.*}} : i32 From 8d87ac242969261d80acef973be76b9ca1e282cb Mon Sep 17 00:00:00 2001 From: Jean Perier Date: Wed, 8 Oct 2025 01:44:37 -0700 Subject: [PATCH 3/3] remove dead code --- flang/lib/Lower/OpenACC.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/flang/lib/Lower/OpenACC.cpp b/flang/lib/Lower/OpenACC.cpp index f164b3b629f6d..742f58f3645bf 100644 --- a/flang/lib/Lower/OpenACC.cpp +++ b/flang/lib/Lower/OpenACC.cpp @@ -2373,11 +2373,8 @@ static mlir::acc::LoopOp buildACCLoopOp( llvm::zip(loopOp.getLoopRegions().front()->front().getArguments(), ivPrivate)) { // Store block argument to the related iv private variable. - auto privateValue = + mlir::Value privateValue = converter.getSymbolAddress(std::get(iv)); - // if (auto declareOp = - // mlir::dyn_cast(privateValue.getDefiningOp())) - // privateValue = declareOp.getResults()[0]; fir::StoreOp::create(builder, currentLocation, arg, privateValue); }