@@ -52,10 +52,13 @@ namespace lower {
52
52
// / operations.
53
53
struct AddrAndBoundsInfo {
54
54
explicit AddrAndBoundsInfo () {}
55
- explicit AddrAndBoundsInfo (mlir::Value addr) : addr(addr) {}
56
- explicit AddrAndBoundsInfo (mlir::Value addr, mlir::Value isPresent)
57
- : addr(addr), isPresent(isPresent) {}
55
+ explicit AddrAndBoundsInfo (mlir::Value addr, mlir::Value rawInput)
56
+ : addr(addr), rawInput(rawInput) {}
57
+ explicit AddrAndBoundsInfo (mlir::Value addr, mlir::Value rawInput,
58
+ mlir::Value isPresent)
59
+ : addr(addr), rawInput(rawInput), isPresent(isPresent) {}
58
60
mlir::Value addr = nullptr ;
61
+ mlir::Value rawInput = nullptr ;
59
62
mlir::Value isPresent = nullptr ;
60
63
};
61
64
@@ -615,20 +618,30 @@ getDataOperandBaseAddr(Fortran::lower::AbstractConverter &converter,
615
618
fir::FirOpBuilder &builder,
616
619
Fortran::lower::SymbolRef sym, mlir::Location loc) {
617
620
mlir::Value symAddr = converter.getSymbolAddress (sym);
621
+ mlir::Value rawInput = symAddr;
618
622
if (auto declareOp =
619
- mlir::dyn_cast_or_null<hlfir::DeclareOp>(symAddr.getDefiningOp ()))
623
+ mlir::dyn_cast_or_null<hlfir::DeclareOp>(symAddr.getDefiningOp ())) {
620
624
symAddr = declareOp.getResults ()[0 ];
625
+ rawInput = declareOp.getResults ()[1 ];
626
+ }
621
627
622
628
// TODO: Might need revisiting to handle for non-shared clauses
623
629
if (!symAddr) {
624
630
if (const auto *details =
625
- sym->detailsIf <Fortran::semantics::HostAssocDetails>())
631
+ sym->detailsIf <Fortran::semantics::HostAssocDetails>()) {
626
632
symAddr = converter.getSymbolAddress (details->symbol ());
633
+ rawInput = symAddr;
634
+ }
627
635
}
628
636
629
637
if (!symAddr)
630
638
llvm::report_fatal_error (" could not retrieve symbol address" );
631
639
640
+ mlir::Value isPresent;
641
+ if (Fortran::semantics::IsOptional (sym))
642
+ isPresent =
643
+ builder.create <fir::IsPresentOp>(loc, builder.getI1Type (), rawInput);
644
+
632
645
if (auto boxTy =
633
646
fir::unwrapRefType (symAddr.getType ()).dyn_cast <fir::BaseBoxType>()) {
634
647
if (boxTy.getEleTy ().isa <fir::RecordType>())
@@ -638,8 +651,6 @@ getDataOperandBaseAddr(Fortran::lower::AbstractConverter &converter,
638
651
// `fir.ref<fir.class<T>>` type.
639
652
if (symAddr.getType ().isa <fir::ReferenceType>()) {
640
653
if (Fortran::semantics::IsOptional (sym)) {
641
- mlir::Value isPresent =
642
- builder.create <fir::IsPresentOp>(loc, builder.getI1Type (), symAddr);
643
654
mlir::Value addr =
644
655
builder.genIfOp (loc, {boxTy}, isPresent, /* withElseRegion=*/ true )
645
656
.genThen ([&]() {
@@ -652,14 +663,13 @@ getDataOperandBaseAddr(Fortran::lower::AbstractConverter &converter,
652
663
builder.create <fir::ResultOp>(loc, mlir::ValueRange{absent});
653
664
})
654
665
.getResults ()[0 ];
655
- return AddrAndBoundsInfo (addr, isPresent);
666
+ return AddrAndBoundsInfo (addr, rawInput, isPresent);
656
667
}
657
668
mlir::Value addr = builder.create <fir::LoadOp>(loc, symAddr);
658
- return AddrAndBoundsInfo (addr);
659
- ;
669
+ return AddrAndBoundsInfo (addr, rawInput, isPresent);
660
670
}
661
671
}
662
- return AddrAndBoundsInfo (symAddr);
672
+ return AddrAndBoundsInfo (symAddr, rawInput, isPresent );
663
673
}
664
674
665
675
template <typename BoundsOp, typename BoundsType>
@@ -807,7 +817,7 @@ genBoundsOps(fir::FirOpBuilder &builder, mlir::Location loc,
807
817
Fortran::lower::StatementContext &stmtCtx,
808
818
const std::list<Fortran::parser::SectionSubscript> &subscripts,
809
819
std::stringstream &asFortran, fir::ExtendedValue &dataExv,
810
- bool dataExvIsAssumedSize, mlir::Value baseAddr ,
820
+ bool dataExvIsAssumedSize, AddrAndBoundsInfo &info ,
811
821
bool treatIndexAsSection = false ) {
812
822
int dimension = 0 ;
813
823
mlir::Type idxTy = builder.getIndexType ();
@@ -831,11 +841,30 @@ genBoundsOps(fir::FirOpBuilder &builder, mlir::Location loc,
831
841
mlir::Value stride = one;
832
842
bool strideInBytes = false ;
833
843
834
- if (fir::unwrapRefType (baseAddr.getType ()).isa <fir::BaseBoxType>()) {
835
- mlir::Value d = builder.createIntegerConstant (loc, idxTy, dimension);
836
- auto dimInfo = builder.create <fir::BoxDimsOp>(loc, idxTy, idxTy, idxTy,
837
- baseAddr, d);
838
- stride = dimInfo.getByteStride ();
844
+ if (fir::unwrapRefType (info.addr .getType ()).isa <fir::BaseBoxType>()) {
845
+ if (info.isPresent ) {
846
+ stride =
847
+ builder
848
+ .genIfOp (loc, idxTy, info.isPresent , /* withElseRegion=*/ true )
849
+ .genThen ([&]() {
850
+ mlir::Value d =
851
+ builder.createIntegerConstant (loc, idxTy, dimension);
852
+ auto dimInfo = builder.create <fir::BoxDimsOp>(
853
+ loc, idxTy, idxTy, idxTy, info.addr , d);
854
+ builder.create <fir::ResultOp>(loc, dimInfo.getByteStride ());
855
+ })
856
+ .genElse ([&] {
857
+ mlir::Value zero =
858
+ builder.createIntegerConstant (loc, idxTy, 0 );
859
+ builder.create <fir::ResultOp>(loc, zero);
860
+ })
861
+ .getResults ()[0 ];
862
+ } else {
863
+ mlir::Value d = builder.createIntegerConstant (loc, idxTy, dimension);
864
+ auto dimInfo = builder.create <fir::BoxDimsOp>(loc, idxTy, idxTy,
865
+ idxTy, info.addr , d);
866
+ stride = dimInfo.getByteStride ();
867
+ }
839
868
strideInBytes = true ;
840
869
}
841
870
@@ -919,7 +948,26 @@ genBoundsOps(fir::FirOpBuilder &builder, mlir::Location loc,
919
948
}
920
949
}
921
950
922
- extent = fir::factory::readExtent (builder, loc, dataExv, dimension);
951
+ if (info.isPresent &&
952
+ fir::unwrapRefType (info.addr .getType ()).isa <fir::BaseBoxType>()) {
953
+ extent =
954
+ builder
955
+ .genIfOp (loc, idxTy, info.isPresent , /* withElseRegion=*/ true )
956
+ .genThen ([&]() {
957
+ mlir::Value ext = fir::factory::readExtent (
958
+ builder, loc, dataExv, dimension);
959
+ builder.create <fir::ResultOp>(loc, ext);
960
+ })
961
+ .genElse ([&] {
962
+ mlir::Value zero =
963
+ builder.createIntegerConstant (loc, idxTy, 0 );
964
+ builder.create <fir::ResultOp>(loc, zero);
965
+ })
966
+ .getResults ()[0 ];
967
+ } else {
968
+ extent = fir::factory::readExtent (builder, loc, dataExv, dimension);
969
+ }
970
+
923
971
if (dataExvIsAssumedSize && dimension + 1 == dataExvRank) {
924
972
extent = zero;
925
973
if (ubound && lbound) {
@@ -976,6 +1024,7 @@ AddrAndBoundsInfo gatherDataOperandAddrAndBounds(
976
1024
dataExv = converter.genExprAddr (operandLocation, *exprBase,
977
1025
stmtCtx);
978
1026
info.addr = fir::getBase (dataExv);
1027
+ info.rawInput = info.addr ;
979
1028
asFortran << (*exprBase).AsFortran ();
980
1029
} else {
981
1030
const Fortran::parser::Name &name =
@@ -993,14 +1042,15 @@ AddrAndBoundsInfo gatherDataOperandAddrAndBounds(
993
1042
bounds = genBoundsOps<BoundsOp, BoundsType>(
994
1043
builder, operandLocation, converter, stmtCtx,
995
1044
arrayElement->subscripts , asFortran, dataExv,
996
- dataExvIsAssumedSize, info. addr , treatIndexAsSection);
1045
+ dataExvIsAssumedSize, info, treatIndexAsSection);
997
1046
}
998
1047
asFortran << ' )' ;
999
1048
} else if (auto structComp = Fortran::parser::Unwrap<
1000
1049
Fortran::parser::StructureComponent>(designator)) {
1001
1050
fir::ExtendedValue compExv =
1002
1051
converter.genExprAddr (operandLocation, *expr, stmtCtx);
1003
1052
info.addr = fir::getBase (compExv);
1053
+ info.rawInput = info.addr ;
1004
1054
if (fir::unwrapRefType (info.addr .getType ())
1005
1055
.isa <fir::SequenceType>())
1006
1056
bounds = genBaseBoundsOps<BoundsOp, BoundsType>(
@@ -1012,14 +1062,15 @@ AddrAndBoundsInfo gatherDataOperandAddrAndBounds(
1012
1062
*Fortran::parser::GetLastName (*structComp).symbol );
1013
1063
if (isOptional)
1014
1064
info.isPresent = builder.create <fir::IsPresentOp>(
1015
- operandLocation, builder.getI1Type (), info.addr );
1065
+ operandLocation, builder.getI1Type (), info.rawInput );
1016
1066
1017
1067
if (auto loadOp = mlir::dyn_cast_or_null<fir::LoadOp>(
1018
1068
info.addr .getDefiningOp ())) {
1019
1069
if (fir::isAllocatableType (loadOp.getType ()) ||
1020
1070
fir::isPointerType (loadOp.getType ()))
1021
1071
info.addr = builder.create <fir::BoxAddrOp>(operandLocation,
1022
1072
info.addr );
1073
+ info.rawInput = info.addr ;
1023
1074
}
1024
1075
1025
1076
// If the component is an allocatable or pointer the result of
@@ -1029,6 +1080,7 @@ AddrAndBoundsInfo gatherDataOperandAddrAndBounds(
1029
1080
if (auto boxAddrOp = mlir::dyn_cast_or_null<fir::BoxAddrOp>(
1030
1081
info.addr .getDefiningOp ())) {
1031
1082
info.addr = boxAddrOp.getVal ();
1083
+ info.rawInput = info.addr ;
1032
1084
bounds = genBoundsOpsFromBox<BoundsOp, BoundsType>(
1033
1085
builder, operandLocation, converter, compExv, info);
1034
1086
}
@@ -1043,6 +1095,7 @@ AddrAndBoundsInfo gatherDataOperandAddrAndBounds(
1043
1095
fir::ExtendedValue compExv =
1044
1096
converter.genExprAddr (operandLocation, *expr, stmtCtx);
1045
1097
info.addr = fir::getBase (compExv);
1098
+ info.rawInput = info.addr ;
1046
1099
asFortran << (*expr).AsFortran ();
1047
1100
} else if (const auto *dataRef{
1048
1101
std::get_if<Fortran::parser::DataRef>(
0 commit comments