29
29
#include " flang/Lower/PFTBuilder.h"
30
30
#include " flang/Lower/StatementContext.h"
31
31
#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"
34
33
#include " flang/Optimizer/Builder/HLFIRTools.h"
35
- #include " flang/Optimizer/Builder/Todo.h"
36
34
#include " flang/Optimizer/Dialect/FIRType.h"
37
- #include " flang/Optimizer/HLFIR/HLFIROps.h"
38
35
#include " flang/Parser/parse-tree.h"
39
36
#include " flang/Semantics/openmp-directive-sets.h"
40
37
#include " flang/Semantics/tools.h"
49
46
namespace Fortran {
50
47
namespace lower {
51
48
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
-
77
49
// / Populates \p hint and \p memoryOrder with appropriate clause information
78
50
// / if present on atomic construct.
79
51
static inline void genOmpAtomicHintAndMemoryOrderClauses (
@@ -609,195 +581,13 @@ void createEmptyRegionBlocks(
609
581
}
610
582
}
611
583
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
652
585
getDataOperandBaseAddr (Fortran::lower::AbstractConverter &converter,
653
586
fir::FirOpBuilder &builder,
654
587
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);
801
591
}
802
592
803
593
namespace detail {
@@ -878,7 +668,7 @@ genBoundsOps(fir::FirOpBuilder &builder, mlir::Location loc,
878
668
Fortran::lower::StatementContext &stmtCtx,
879
669
const std::vector<Fortran::evaluate::Subscript> &subscripts,
880
670
std::stringstream &asFortran, fir::ExtendedValue &dataExv,
881
- bool dataExvIsAssumedSize, AddrAndBoundsInfo &info,
671
+ bool dataExvIsAssumedSize, fir::factory:: AddrAndBoundsInfo &info,
882
672
bool treatIndexAsSection = false ) {
883
673
int dimension = 0 ;
884
674
mlir::Type idxTy = builder.getIndexType ();
@@ -1083,7 +873,7 @@ std::optional<Ref> getRef(Expr &&expr) {
1083
873
} // namespace detail
1084
874
1085
875
template <typename BoundsOp, typename BoundsType>
1086
- AddrAndBoundsInfo gatherDataOperandAddrAndBounds (
876
+ fir::factory:: AddrAndBoundsInfo gatherDataOperandAddrAndBounds (
1087
877
Fortran::lower::AbstractConverter &converter, fir::FirOpBuilder &builder,
1088
878
semantics::SemanticsContext &semaCtx,
1089
879
Fortran::lower::StatementContext &stmtCtx,
@@ -1093,7 +883,7 @@ AddrAndBoundsInfo gatherDataOperandAddrAndBounds(
1093
883
llvm::SmallVector<mlir::Value> &bounds, bool treatIndexAsSection = false ) {
1094
884
using namespace Fortran ;
1095
885
1096
- AddrAndBoundsInfo info;
886
+ fir::factory:: AddrAndBoundsInfo info;
1097
887
1098
888
if (!maybeDesignator) {
1099
889
info = getDataOperandBaseAddr (converter, builder, symbol, operandLocation);
@@ -1158,9 +948,9 @@ AddrAndBoundsInfo gatherDataOperandAddrAndBounds(
1158
948
info.addr = fir::getBase (compExv);
1159
949
info.rawInput = info.addr ;
1160
950
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 );
1164
954
asFortran << designator.AsFortran ();
1165
955
1166
956
if (semantics::IsOptional (compRef->GetLastSymbol ())) {
@@ -1187,7 +977,7 @@ AddrAndBoundsInfo gatherDataOperandAddrAndBounds(
1187
977
info.addr = boxAddrOp.getVal ();
1188
978
info.boxType = info.addr .getType ();
1189
979
info.rawInput = info.addr ;
1190
- bounds = genBoundsOpsFromBox<BoundsOp, BoundsType>(
980
+ bounds = fir::factory:: genBoundsOpsFromBox<BoundsOp, BoundsType>(
1191
981
builder, operandLocation, compExv, info);
1192
982
}
1193
983
} else {
@@ -1205,13 +995,13 @@ AddrAndBoundsInfo gatherDataOperandAddrAndBounds(
1205
995
if (mlir::isa<fir::BaseBoxType>(
1206
996
fir::unwrapRefType (info.addr .getType ()))) {
1207
997
info.boxType = fir::unwrapRefType (info.addr .getType ());
1208
- bounds = genBoundsOpsFromBox<BoundsOp, BoundsType>(
998
+ bounds = fir::factory:: genBoundsOpsFromBox<BoundsOp, BoundsType>(
1209
999
builder, operandLocation, dataExv, info);
1210
1000
}
1211
1001
bool dataExvIsAssumedSize =
1212
1002
Fortran::semantics::IsAssumedSizeArray (symRef->get ().GetUltimate ());
1213
1003
if (mlir::isa<fir::SequenceType>(fir::unwrapRefType (info.addr .getType ())))
1214
- bounds = genBaseBoundsOps<BoundsOp, BoundsType>(
1004
+ bounds = fir::factory:: genBaseBoundsOps<BoundsOp, BoundsType>(
1215
1005
builder, operandLocation, dataExv, dataExvIsAssumedSize);
1216
1006
asFortran << symRef->get ().name ().ToString ();
1217
1007
} else { // Unsupported
@@ -1222,24 +1012,6 @@ AddrAndBoundsInfo gatherDataOperandAddrAndBounds(
1222
1012
return info;
1223
1013
}
1224
1014
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
- }
1243
1015
} // namespace lower
1244
1016
} // namespace Fortran
1245
1017
0 commit comments