Skip to content

Commit f46bfff

Browse files
schweitzpgipsteinfeld
authored andcommitted
[flang] Handle substrings when they are on arguments to elemental functions.
Passing substrings as arguments to elemental functions needed fixing. Specifically, when an array of characters with a substring operation on the entire array was passed, the receiving procedure was getting the array without the substring. RefOpaque was not handling subscript operations in the action loop. Also refactor the LEN computation code so it does not require an ArrayLoad.
1 parent 6f3b18a commit f46bfff

File tree

4 files changed

+72
-7
lines changed

4 files changed

+72
-7
lines changed

flang/include/flang/Optimizer/Builder/FIRBuilder.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -504,6 +504,11 @@ mlir::Value genLenOfCharacter(fir::FirOpBuilder &builder, mlir::Location loc,
504504
fir::ArrayLoadOp arrLoad,
505505
llvm::ArrayRef<mlir::Value> path,
506506
llvm::ArrayRef<mlir::Value> substring);
507+
mlir::Value genLenOfCharacter(fir::FirOpBuilder &builder, mlir::Location loc,
508+
fir::SequenceType seqTy, mlir::Value memref,
509+
llvm::ArrayRef<mlir::Value> typeParams,
510+
llvm::ArrayRef<mlir::Value> path,
511+
llvm::ArrayRef<mlir::Value> substring);
507512

508513
} // namespace fir::factory
509514

flang/lib/Lower/ConvertExpr.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4912,6 +4912,19 @@ class ArrayExprLowering {
49124912
mlir::Value coor = builder.create<fir::ArrayCoorOp>(
49134913
loc, refEleTy, memref, shape, slice, indices,
49144914
fir::getTypeParams(extMemref));
4915+
if (auto charTy = eleTy.dyn_cast<fir::CharacterType>()) {
4916+
llvm::SmallVector<mlir::Value> substringBounds;
4917+
populateBounds(substringBounds, components.substring);
4918+
if (!substringBounds.empty()) {
4919+
mlir::Value dstLen = fir::factory::genLenOfCharacter(
4920+
builder, loc, arrTy.cast<fir::SequenceType>(), memref,
4921+
fir::getTypeParams(extMemref), iters.iterVec(),
4922+
substringBounds);
4923+
fir::CharBoxValue dstChar(coor, dstLen);
4924+
return fir::factory::CharacterExprHelper{builder, loc}
4925+
.createSubstring(dstChar, substringBounds);
4926+
}
4927+
}
49154928
return fir::factory::arraySectionElementToExtendedValue(
49164929
builder, loc, extMemref, coor, slice);
49174930
};

flang/lib/Optimizer/Builder/FIRBuilder.cpp

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1025,6 +1025,16 @@ fir::factory::getRaggedArrayHeaderType(fir::FirOpBuilder &builder) {
10251025
mlir::Value fir::factory::genLenOfCharacter(
10261026
fir::FirOpBuilder &builder, mlir::Location loc, fir::ArrayLoadOp arrLoad,
10271027
llvm::ArrayRef<mlir::Value> path, llvm::ArrayRef<mlir::Value> substring) {
1028+
llvm::SmallVector<mlir::Value> typeParams(arrLoad.typeparams());
1029+
return genLenOfCharacter(builder, loc,
1030+
arrLoad.getType().cast<fir::SequenceType>(),
1031+
arrLoad.memref(), typeParams, path, substring);
1032+
}
1033+
1034+
mlir::Value fir::factory::genLenOfCharacter(
1035+
fir::FirOpBuilder &builder, mlir::Location loc, fir::SequenceType seqTy,
1036+
mlir::Value memref, llvm::ArrayRef<mlir::Value> typeParams,
1037+
llvm::ArrayRef<mlir::Value> path, llvm::ArrayRef<mlir::Value> substring) {
10281038
auto idxTy = builder.getIndexType();
10291039
auto zero = builder.createIntegerConstant(loc, idxTy, 0);
10301040
auto saturatedDiff = [&](mlir::Value lower, mlir::Value upper) {
@@ -1043,8 +1053,7 @@ mlir::Value fir::factory::genLenOfCharacter(
10431053
auto lower = zero;
10441054
if (substring.size() == 1)
10451055
lower = builder.createConvert(loc, idxTy, substring.front());
1046-
auto arrTy = arrLoad.getType().cast<fir::SequenceType>();
1047-
auto eleTy = fir::applyPathToType(arrTy, path);
1056+
auto eleTy = fir::applyPathToType(seqTy, path);
10481057
if (!fir::hasDynamicSize(eleTy)) {
10491058
if (auto charTy = eleTy.dyn_cast<fir::CharacterType>()) {
10501059
// Use LEN from the type.
@@ -1054,20 +1063,19 @@ mlir::Value fir::factory::genLenOfCharacter(
10541063
fir::emitFatalError(loc,
10551064
"application of path did not result in a !fir.char");
10561065
}
1057-
auto memref = arrLoad.memref();
10581066
if (fir::isa_box_type(memref.getType())) {
10591067
if (memref.getType().isa<fir::BoxCharType>())
10601068
return builder.create<fir::BoxCharLenOp>(loc, idxTy, memref);
10611069
if (memref.getType().isa<fir::BoxType>())
10621070
return CharacterExprHelper(builder, loc).readLengthFromBox(memref);
10631071
fir::emitFatalError(loc, "memref has wrong type");
10641072
}
1065-
if (arrLoad.typeparams().empty()) {
1073+
if (typeParams.empty()) {
10661074
fir::emitFatalError(loc, "array_load must have typeparams");
10671075
}
1068-
if (fir::isa_char(arrTy.getEleTy())) {
1069-
assert(arrLoad.typeparams().size() == 1 && "too many typeparams");
1070-
return arrLoad.typeparams().front();
1076+
if (fir::isa_char(seqTy.getEleTy())) {
1077+
assert(typeParams.size() == 1 && "too many typeparams");
1078+
return typeParams.front();
10711079
}
10721080
TODO(loc, "LEN of character must be computed at runtime");
10731081
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
! RUN: bbc %s -o - | FileCheck %s
2+
3+
! CHECK-LABEL: substring_main
4+
subroutine substring_main
5+
character*7 :: string(2) = ['12 ', '12 ']
6+
integer :: result(2)
7+
integer :: ival
8+
9+
ival = 1
10+
! CHECK: %[[a0:.*]] = fir.alloca i32 {bindc_name = "ival", uniq_name = "_QFsubstring_mainEival"}
11+
! CHECK: %[[a2:.*]] = fir.address_of(@_QFsubstring_mainEstring) : !fir.ref<!fir.array<2x!fir.char<1,7>>>
12+
! CHECK: fir.store {{.*}} to %[[a0]] : !fir.ref<i32>
13+
! CHECK: %[[a3:.*]] = fir.shape {{.*}} : (index) -> !fir.shape<1>
14+
! CHECK: %[[a4:.*]] = fir.slice {{.*}}, {{.*}}, {{.*}} : (index, index, index) -> !fir.slice<1>
15+
! CHECK: br ^bb1({{.*}}, {{.*}} : index, index)
16+
! CHECK: ^bb1(%[[a5:.*]]: index, %[[a6:.*]]: index): // 2 preds: ^bb0, ^bb2
17+
! CHECK: %[[a7:.*]] = arith.cmpi sgt, %[[a6]], {{.*}} : index
18+
! CHECK: cond_br %[[a7]], ^bb2, ^bb3
19+
! CHECK: ^bb2: // pred: ^bb1
20+
! CHECK: %[[a8:.*]] = arith.addi %[[a5]], {{.*}} : index
21+
! CHECK: %[[a9:.*]] = fir.array_coor %[[a2]](%[[a3]]) [%[[a4]]] %[[a8]] : (!fir.ref<!fir.array<2x!fir.char<1,7>>>, !fir.shape<1>, !fir.slice<1>, index) -> !fir.ref<!fir.char<1,7>>
22+
! CHECK: %[[a10:.*]] = fir.load %[[a0]] : !fir.ref<i32>
23+
! CHECK: %[[a11:.*]] = fir.convert %[[a10]] : (i32) -> index
24+
! CHECK: %[[a12:.*]] = arith.subi %[[a11]], {{.*}} : index
25+
! CHECK: %[[a13:.*]] = fir.convert %[[a9]] : (!fir.ref<!fir.char<1,7>>) -> !fir.ref<!fir.array<7x!fir.char<1>>>
26+
! CHECK: %[[a14:.*]] = fir.coordinate_of %[[a13]], %[[a12]] : (!fir.ref<!fir.array<7x!fir.char<1>>>, index) -> !fir.ref<!fir.char<1>>
27+
! CHECK: %[[a15:.*]] = fir.convert %[[a14]] : (!fir.ref<!fir.char<1>>) -> !fir.ref<!fir.char<1,?>>
28+
! CHECK: %[[a16:.*]] = fir.emboxchar %[[a15]], {{.*}} : (!fir.ref<!fir.char<1,?>>, index) -> !fir.boxchar<1>
29+
! CHECK: %[[a17:.*]] = fir.call @_QFsubstring_mainPinner(%[[a16]]) : (!fir.boxchar<1>) -> i32
30+
result = inner(string(1:2)(ival:ival))
31+
print *, result
32+
contains
33+
elemental function inner(arg)
34+
character(len=*), intent(in) :: arg
35+
integer :: inner
36+
37+
inner = len(arg)
38+
end function inner
39+
end subroutine substring_main

0 commit comments

Comments
 (0)