2929#include " flang/Lower/PFTBuilder.h"
3030#include " flang/Lower/StatementContext.h"
3131#include " flang/Lower/Support/Utils.h"
32- #include " flang/Optimizer/Builder/BoxValue.h"
33- #include " flang/Optimizer/Builder/FIRBuilder.h"
32+ #include " flang/Optimizer/Builder/DirectivesCommon.h"
3433#include " flang/Optimizer/Builder/HLFIRTools.h"
35- #include " flang/Optimizer/Builder/Todo.h"
3634#include " flang/Optimizer/Dialect/FIRType.h"
37- #include " flang/Optimizer/HLFIR/HLFIROps.h"
3835#include " flang/Parser/parse-tree.h"
3936#include " flang/Semantics/openmp-directive-sets.h"
4037#include " flang/Semantics/tools.h"
4946namespace Fortran {
5047namespace lower {
5148
52- // / Information gathered to generate bounds operation and data entry/exit
53- // / operations.
54- struct AddrAndBoundsInfo {
55- explicit AddrAndBoundsInfo () {}
56- explicit AddrAndBoundsInfo (mlir::Value addr, mlir::Value rawInput)
57- : addr(addr), rawInput(rawInput) {}
58- explicit AddrAndBoundsInfo (mlir::Value addr, mlir::Value rawInput,
59- mlir::Value isPresent)
60- : addr(addr), rawInput(rawInput), isPresent(isPresent) {}
61- explicit AddrAndBoundsInfo (mlir::Value addr, mlir::Value rawInput,
62- mlir::Value isPresent, mlir::Type boxType)
63- : addr(addr), rawInput(rawInput), isPresent(isPresent), boxType(boxType) {
64- }
65- mlir::Value addr = nullptr ;
66- mlir::Value rawInput = nullptr ;
67- mlir::Value isPresent = nullptr ;
68- mlir::Type boxType = nullptr ;
69- void dump (llvm::raw_ostream &os) {
70- os << " AddrAndBoundsInfo addr: " << addr << " \n " ;
71- os << " AddrAndBoundsInfo rawInput: " << rawInput << " \n " ;
72- os << " AddrAndBoundsInfo isPresent: " << isPresent << " \n " ;
73- os << " AddrAndBoundsInfo boxType: " << boxType << " \n " ;
74- }
75- };
76-
7749// / Populates \p hint and \p memoryOrder with appropriate clause information
7850// / if present on atomic construct.
7951static inline void genOmpAtomicHintAndMemoryOrderClauses (
@@ -609,195 +581,13 @@ void createEmptyRegionBlocks(
609581 }
610582}
611583
612- inline AddrAndBoundsInfo getDataOperandBaseAddr (fir::FirOpBuilder &builder,
613- mlir::Value symAddr,
614- bool isOptional,
615- mlir::Location loc) {
616- mlir::Value rawInput = symAddr;
617- if (auto declareOp =
618- mlir::dyn_cast_or_null<hlfir::DeclareOp>(symAddr.getDefiningOp ())) {
619- symAddr = declareOp.getResults ()[0 ];
620- rawInput = declareOp.getResults ()[1 ];
621- }
622-
623- if (!symAddr)
624- llvm::report_fatal_error (" could not retrieve symbol address" );
625-
626- mlir::Value isPresent;
627- if (isOptional)
628- isPresent =
629- builder.create <fir::IsPresentOp>(loc, builder.getI1Type (), rawInput);
630-
631- if (auto boxTy = mlir::dyn_cast<fir::BaseBoxType>(
632- fir::unwrapRefType (symAddr.getType ()))) {
633- if (mlir::isa<fir::RecordType>(boxTy.getEleTy ()))
634- TODO (loc, " derived type" );
635-
636- // In case of a box reference, load it here to get the box value.
637- // This is preferrable because then the same box value can then be used for
638- // all address/dimension retrievals. For Fortran optional though, leave
639- // the load generation for later so it can be done in the appropriate
640- // if branches.
641- if (mlir::isa<fir::ReferenceType>(symAddr.getType ()) && !isOptional) {
642- mlir::Value addr = builder.create <fir::LoadOp>(loc, symAddr);
643- return AddrAndBoundsInfo (addr, rawInput, isPresent, boxTy);
644- }
645-
646- return AddrAndBoundsInfo (symAddr, rawInput, isPresent, boxTy);
647- }
648- return AddrAndBoundsInfo (symAddr, rawInput, isPresent);
649- }
650-
651- inline AddrAndBoundsInfo
584+ inline fir::factory::AddrAndBoundsInfo
652585getDataOperandBaseAddr (Fortran::lower::AbstractConverter &converter,
653586 fir::FirOpBuilder &builder,
654587 Fortran::lower::SymbolRef sym, mlir::Location loc) {
655- return getDataOperandBaseAddr (builder, converter.getSymbolAddress (sym),
656- Fortran::semantics::IsOptional (sym), loc);
657- }
658-
659- template <typename BoundsOp, typename BoundsType>
660- llvm::SmallVector<mlir::Value>
661- gatherBoundsOrBoundValues (fir::FirOpBuilder &builder, mlir::Location loc,
662- fir::ExtendedValue dataExv, mlir::Value box,
663- bool collectValuesOnly = false ) {
664- assert (box && " box must exist" );
665- llvm::SmallVector<mlir::Value> values;
666- mlir::Value byteStride;
667- mlir::Type idxTy = builder.getIndexType ();
668- mlir::Type boundTy = builder.getType <BoundsType>();
669- mlir::Value one = builder.createIntegerConstant (loc, idxTy, 1 );
670- for (unsigned dim = 0 ; dim < dataExv.rank (); ++dim) {
671- mlir::Value d = builder.createIntegerConstant (loc, idxTy, dim);
672- mlir::Value baseLb =
673- fir::factory::readLowerBound (builder, loc, dataExv, dim, one);
674- auto dimInfo =
675- builder.create <fir::BoxDimsOp>(loc, idxTy, idxTy, idxTy, box, d);
676- mlir::Value lb = builder.createIntegerConstant (loc, idxTy, 0 );
677- mlir::Value ub =
678- builder.create <mlir::arith::SubIOp>(loc, dimInfo.getExtent (), one);
679- if (dim == 0 ) // First stride is the element size.
680- byteStride = dimInfo.getByteStride ();
681- if (collectValuesOnly) {
682- values.push_back (lb);
683- values.push_back (ub);
684- values.push_back (dimInfo.getExtent ());
685- values.push_back (byteStride);
686- values.push_back (baseLb);
687- } else {
688- mlir::Value bound = builder.create <BoundsOp>(
689- loc, boundTy, lb, ub, dimInfo.getExtent (), byteStride, true , baseLb);
690- values.push_back (bound);
691- }
692- // Compute the stride for the next dimension.
693- byteStride = builder.create <mlir::arith::MulIOp>(loc, byteStride,
694- dimInfo.getExtent ());
695- }
696- return values;
697- }
698-
699- // / Generate the bounds operation from the descriptor information.
700- template <typename BoundsOp, typename BoundsType>
701- llvm::SmallVector<mlir::Value>
702- genBoundsOpsFromBox (fir::FirOpBuilder &builder, mlir::Location loc,
703- fir::ExtendedValue dataExv,
704- Fortran::lower::AddrAndBoundsInfo &info) {
705- llvm::SmallVector<mlir::Value> bounds;
706- mlir::Type idxTy = builder.getIndexType ();
707- mlir::Type boundTy = builder.getType <BoundsType>();
708-
709- assert (mlir::isa<fir::BaseBoxType>(info.boxType ) &&
710- " expect fir.box or fir.class" );
711- assert (fir::unwrapRefType (info.addr .getType ()) == info.boxType &&
712- " expected box type consistency" );
713-
714- if (info.isPresent ) {
715- llvm::SmallVector<mlir::Type> resTypes;
716- constexpr unsigned nbValuesPerBound = 5 ;
717- for (unsigned dim = 0 ; dim < dataExv.rank () * nbValuesPerBound; ++dim)
718- resTypes.push_back (idxTy);
719-
720- mlir::Operation::result_range ifRes =
721- builder.genIfOp (loc, resTypes, info.isPresent , /* withElseRegion=*/ true )
722- .genThen ([&]() {
723- mlir::Value box =
724- !fir::isBoxAddress (info.addr .getType ())
725- ? info.addr
726- : builder.create <fir::LoadOp>(loc, info.addr );
727- llvm::SmallVector<mlir::Value> boundValues =
728- gatherBoundsOrBoundValues<BoundsOp, BoundsType>(
729- builder, loc, dataExv, box,
730- /* collectValuesOnly=*/ true );
731- builder.create <fir::ResultOp>(loc, boundValues);
732- })
733- .genElse ([&] {
734- // Box is not present. Populate bound values with default values.
735- llvm::SmallVector<mlir::Value> boundValues;
736- mlir::Value zero = builder.createIntegerConstant (loc, idxTy, 0 );
737- mlir::Value mOne = builder.createMinusOneInteger (loc, idxTy);
738- for (unsigned dim = 0 ; dim < dataExv.rank (); ++dim) {
739- boundValues.push_back (zero); // lb
740- boundValues.push_back (mOne ); // ub
741- boundValues.push_back (zero); // extent
742- boundValues.push_back (zero); // byteStride
743- boundValues.push_back (zero); // baseLb
744- }
745- builder.create <fir::ResultOp>(loc, boundValues);
746- })
747- .getResults ();
748- // Create the bound operations outside the if-then-else with the if op
749- // results.
750- for (unsigned i = 0 ; i < ifRes.size (); i += nbValuesPerBound) {
751- mlir::Value bound = builder.create <BoundsOp>(
752- loc, boundTy, ifRes[i], ifRes[i + 1 ], ifRes[i + 2 ], ifRes[i + 3 ],
753- true , ifRes[i + 4 ]);
754- bounds.push_back (bound);
755- }
756- } else {
757- mlir::Value box = !fir::isBoxAddress (info.addr .getType ())
758- ? info.addr
759- : builder.create <fir::LoadOp>(loc, info.addr );
760- bounds = gatherBoundsOrBoundValues<BoundsOp, BoundsType>(builder, loc,
761- dataExv, box);
762- }
763- return bounds;
764- }
765-
766- // / Generate bounds operation for base array without any subscripts
767- // / provided.
768- template <typename BoundsOp, typename BoundsType>
769- llvm::SmallVector<mlir::Value>
770- genBaseBoundsOps (fir::FirOpBuilder &builder, mlir::Location loc,
771- fir::ExtendedValue dataExv, bool isAssumedSize) {
772- mlir::Type idxTy = builder.getIndexType ();
773- mlir::Type boundTy = builder.getType <BoundsType>();
774- llvm::SmallVector<mlir::Value> bounds;
775-
776- if (dataExv.rank () == 0 )
777- return bounds;
778-
779- mlir::Value one = builder.createIntegerConstant (loc, idxTy, 1 );
780- const unsigned rank = dataExv.rank ();
781- for (unsigned dim = 0 ; dim < rank; ++dim) {
782- mlir::Value baseLb =
783- fir::factory::readLowerBound (builder, loc, dataExv, dim, one);
784- mlir::Value zero = builder.createIntegerConstant (loc, idxTy, 0 );
785- mlir::Value ub;
786- mlir::Value lb = zero;
787- mlir::Value ext = fir::factory::readExtent (builder, loc, dataExv, dim);
788- if (isAssumedSize && dim + 1 == rank) {
789- ext = zero;
790- ub = lb;
791- } else {
792- // ub = extent - 1
793- ub = builder.create <mlir::arith::SubIOp>(loc, ext, one);
794- }
795-
796- mlir::Value bound =
797- builder.create <BoundsOp>(loc, boundTy, lb, ub, ext, one, false , baseLb);
798- bounds.push_back (bound);
799- }
800- return bounds;
588+ return fir::factory::getDataOperandBaseAddr (
589+ builder, converter.getSymbolAddress (sym),
590+ Fortran::semantics::IsOptional (sym), loc);
801591}
802592
803593namespace detail {
@@ -878,7 +668,7 @@ genBoundsOps(fir::FirOpBuilder &builder, mlir::Location loc,
878668 Fortran::lower::StatementContext &stmtCtx,
879669 const std::vector<Fortran::evaluate::Subscript> &subscripts,
880670 std::stringstream &asFortran, fir::ExtendedValue &dataExv,
881- bool dataExvIsAssumedSize, AddrAndBoundsInfo &info,
671+ bool dataExvIsAssumedSize, fir::factory:: AddrAndBoundsInfo &info,
882672 bool treatIndexAsSection = false ) {
883673 int dimension = 0 ;
884674 mlir::Type idxTy = builder.getIndexType ();
@@ -1083,7 +873,7 @@ std::optional<Ref> getRef(Expr &&expr) {
1083873} // namespace detail
1084874
1085875template <typename BoundsOp, typename BoundsType>
1086- AddrAndBoundsInfo gatherDataOperandAddrAndBounds (
876+ fir::factory:: AddrAndBoundsInfo gatherDataOperandAddrAndBounds (
1087877 Fortran::lower::AbstractConverter &converter, fir::FirOpBuilder &builder,
1088878 semantics::SemanticsContext &semaCtx,
1089879 Fortran::lower::StatementContext &stmtCtx,
@@ -1093,7 +883,7 @@ AddrAndBoundsInfo gatherDataOperandAddrAndBounds(
1093883 llvm::SmallVector<mlir::Value> &bounds, bool treatIndexAsSection = false ) {
1094884 using namespace Fortran ;
1095885
1096- AddrAndBoundsInfo info;
886+ fir::factory:: AddrAndBoundsInfo info;
1097887
1098888 if (!maybeDesignator) {
1099889 info = getDataOperandBaseAddr (converter, builder, symbol, operandLocation);
@@ -1158,9 +948,9 @@ AddrAndBoundsInfo gatherDataOperandAddrAndBounds(
1158948 info.addr = fir::getBase (compExv);
1159949 info.rawInput = info.addr ;
1160950 if (mlir::isa<fir::SequenceType>(fir::unwrapRefType (info.addr .getType ())))
1161- bounds = genBaseBoundsOps<BoundsOp, BoundsType>(builder, operandLocation,
1162- compExv,
1163- /* isAssumedSize=*/ false );
951+ bounds = fir::factory:: genBaseBoundsOps<BoundsOp, BoundsType>(
952+ builder, operandLocation, compExv,
953+ /* isAssumedSize=*/ false );
1164954 asFortran << designator.AsFortran ();
1165955
1166956 if (semantics::IsOptional (compRef->GetLastSymbol ())) {
@@ -1187,7 +977,7 @@ AddrAndBoundsInfo gatherDataOperandAddrAndBounds(
1187977 info.addr = boxAddrOp.getVal ();
1188978 info.boxType = info.addr .getType ();
1189979 info.rawInput = info.addr ;
1190- bounds = genBoundsOpsFromBox<BoundsOp, BoundsType>(
980+ bounds = fir::factory:: genBoundsOpsFromBox<BoundsOp, BoundsType>(
1191981 builder, operandLocation, compExv, info);
1192982 }
1193983 } else {
@@ -1205,13 +995,13 @@ AddrAndBoundsInfo gatherDataOperandAddrAndBounds(
1205995 if (mlir::isa<fir::BaseBoxType>(
1206996 fir::unwrapRefType (info.addr .getType ()))) {
1207997 info.boxType = fir::unwrapRefType (info.addr .getType ());
1208- bounds = genBoundsOpsFromBox<BoundsOp, BoundsType>(
998+ bounds = fir::factory:: genBoundsOpsFromBox<BoundsOp, BoundsType>(
1209999 builder, operandLocation, dataExv, info);
12101000 }
12111001 bool dataExvIsAssumedSize =
12121002 Fortran::semantics::IsAssumedSizeArray (symRef->get ().GetUltimate ());
12131003 if (mlir::isa<fir::SequenceType>(fir::unwrapRefType (info.addr .getType ())))
1214- bounds = genBaseBoundsOps<BoundsOp, BoundsType>(
1004+ bounds = fir::factory:: genBaseBoundsOps<BoundsOp, BoundsType>(
12151005 builder, operandLocation, dataExv, dataExvIsAssumedSize);
12161006 asFortran << symRef->get ().name ().ToString ();
12171007 } else { // Unsupported
@@ -1222,24 +1012,6 @@ AddrAndBoundsInfo gatherDataOperandAddrAndBounds(
12221012 return info;
12231013}
12241014
1225- template <typename BoundsOp, typename BoundsType>
1226- llvm::SmallVector<mlir::Value>
1227- genImplicitBoundsOps (fir::FirOpBuilder &builder, lower::AddrAndBoundsInfo &info,
1228- fir::ExtendedValue dataExv, bool dataExvIsAssumedSize,
1229- mlir::Location loc) {
1230- llvm::SmallVector<mlir::Value> bounds;
1231-
1232- mlir::Value baseOp = info.rawInput ;
1233- if (mlir::isa<fir::BaseBoxType>(fir::unwrapRefType (baseOp.getType ())))
1234- bounds = lower::genBoundsOpsFromBox<BoundsOp, BoundsType>(builder, loc,
1235- dataExv, info);
1236- if (mlir::isa<fir::SequenceType>(fir::unwrapRefType (baseOp.getType ()))) {
1237- bounds = lower::genBaseBoundsOps<BoundsOp, BoundsType>(
1238- builder, loc, dataExv, dataExvIsAssumedSize);
1239- }
1240-
1241- return bounds;
1242- }
12431015} // namespace lower
12441016} // namespace Fortran
12451017
0 commit comments