Skip to content

Commit 3328ccf

Browse files
authored
[flang] lower SHAPE intrinsic (#89785)
Semantics usually fold SHAPE into an array constructor, but sometimes it cannot (like when the source is a function result that cannot be duplicated in expression analysis). Add lowering handling for shape.
1 parent ca4dbc2 commit 3328ccf

File tree

3 files changed

+109
-0
lines changed

3 files changed

+109
-0
lines changed

flang/include/flang/Optimizer/Builder/IntrinsicCall.h

+2
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,8 @@ struct IntrinsicLibrary {
335335
mlir::Value genSelectedRealKind(mlir::Type, llvm::ArrayRef<mlir::Value>);
336336
mlir::Value genSetExponent(mlir::Type resultType,
337337
llvm::ArrayRef<mlir::Value> args);
338+
fir::ExtendedValue genShape(mlir::Type resultType,
339+
llvm::ArrayRef<fir::ExtendedValue>);
338340
template <typename Shift>
339341
mlir::Value genShift(mlir::Type resultType, llvm::ArrayRef<mlir::Value>);
340342
mlir::Value genShiftA(mlir::Type resultType, llvm::ArrayRef<mlir::Value>);

flang/lib/Optimizer/Builder/IntrinsicCall.cpp

+33
Original file line numberDiff line numberDiff line change
@@ -554,6 +554,10 @@ static constexpr IntrinsicHandler handlers[]{
554554
{"radix", asAddr, handleDynamicOptional}}},
555555
/*isElemental=*/false},
556556
{"set_exponent", &I::genSetExponent},
557+
{"shape",
558+
&I::genShape,
559+
{{{"source", asBox}, {"kind", asValue}}},
560+
/*isElemental=*/false},
557561
{"shifta", &I::genShiftA},
558562
{"shiftl", &I::genShift<mlir::arith::ShLIOp>},
559563
{"shiftr", &I::genShift<mlir::arith::ShRUIOp>},
@@ -5821,6 +5825,35 @@ mlir::Value IntrinsicLibrary::genSetExponent(mlir::Type resultType,
58215825
fir::getBase(args[1])));
58225826
}
58235827

5828+
// SHAPE
5829+
fir::ExtendedValue
5830+
IntrinsicLibrary::genShape(mlir::Type resultType,
5831+
llvm::ArrayRef<fir::ExtendedValue> args) {
5832+
assert(args.size() >= 1);
5833+
const fir::ExtendedValue &array = args[0];
5834+
int rank = array.rank();
5835+
if (rank == 0)
5836+
TODO(loc, "shape intrinsic lowering with assumed-rank source");
5837+
mlir::Type indexType = builder.getIndexType();
5838+
mlir::Type extentType = fir::unwrapSequenceType(resultType);
5839+
mlir::Type seqType = fir::SequenceType::get(
5840+
{static_cast<fir::SequenceType::Extent>(rank)}, extentType);
5841+
mlir::Value shapeArray = builder.createTemporary(loc, seqType);
5842+
mlir::Type shapeAddrType = builder.getRefType(extentType);
5843+
for (int dim = 0; dim < rank; ++dim) {
5844+
mlir::Value extent = fir::factory::readExtent(builder, loc, array, dim);
5845+
extent = builder.createConvert(loc, extentType, extent);
5846+
auto index = builder.createIntegerConstant(loc, indexType, dim);
5847+
auto shapeAddr = builder.create<fir::CoordinateOp>(loc, shapeAddrType,
5848+
shapeArray, index);
5849+
builder.create<fir::StoreOp>(loc, extent, shapeAddr);
5850+
}
5851+
mlir::Value shapeArrayExtent =
5852+
builder.createIntegerConstant(loc, indexType, rank);
5853+
llvm::SmallVector<mlir::Value> extents{shapeArrayExtent};
5854+
return fir::ArrayBoxValue{shapeArray, extents};
5855+
}
5856+
58245857
// SHIFTL, SHIFTR
58255858
template <typename Shift>
58265859
mlir::Value IntrinsicLibrary::genShift(mlir::Type resultType,

flang/test/Lower/Intrinsics/shape.f90

+74
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
! Test SHAPE with function results
2+
! RUN: bbc -emit-hlfir -o - %s | FileCheck %s
3+
4+
subroutine test()
5+
interface
6+
function return_array()
7+
real, pointer :: return_array(:, :, :)
8+
end function
9+
end interface
10+
print *, shape(return_array())
11+
end subroutine
12+
! CHECK-LABEL: func.func @_QPtest() {
13+
! CHECK: %[[VAL_0:.*]] = fir.alloca !fir.array<3xi32>
14+
! CHECK: %[[VAL_7:.*]] = fir.call @_QPreturn_array() {{.*}}: () -> !fir.box<!fir.ptr<!fir.array<?x?x?xf32>>>
15+
! CHECK: fir.save_result %[[VAL_7]] to %[[VAL_1:.*]] : !fir.box<!fir.ptr<!fir.array<?x?x?xf32>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?x?x?xf32>>>>
16+
! CHECK: %[[VAL_8:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = ".tmp.func_result"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?x?x?xf32>>>>) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?x?x?xf32>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?x?x?xf32>>>>)
17+
! CHECK: %[[VAL_9:.*]] = fir.load %[[VAL_8]]#1 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?x?x?xf32>>>>
18+
! CHECK: %[[VAL_10:.*]] = arith.constant 0 : index
19+
! CHECK: %[[VAL_11:.*]]:3 = fir.box_dims %[[VAL_9]], %[[VAL_10]] : (!fir.box<!fir.ptr<!fir.array<?x?x?xf32>>>, index) -> (index, index, index)
20+
! CHECK: %[[VAL_12:.*]] = fir.convert %[[VAL_11]]#1 : (index) -> i32
21+
! CHECK: %[[VAL_13:.*]] = arith.constant 0 : index
22+
! CHECK: %[[VAL_14:.*]] = fir.coordinate_of %[[VAL_0]], %[[VAL_13]] : (!fir.ref<!fir.array<3xi32>>, index) -> !fir.ref<i32>
23+
! CHECK: fir.store %[[VAL_12]] to %[[VAL_14]] : !fir.ref<i32>
24+
! CHECK: %[[VAL_15:.*]] = arith.constant 1 : index
25+
! CHECK: %[[VAL_16:.*]]:3 = fir.box_dims %[[VAL_9]], %[[VAL_15]] : (!fir.box<!fir.ptr<!fir.array<?x?x?xf32>>>, index) -> (index, index, index)
26+
! CHECK: %[[VAL_17:.*]] = fir.convert %[[VAL_16]]#1 : (index) -> i32
27+
! CHECK: %[[VAL_18:.*]] = arith.constant 1 : index
28+
! CHECK: %[[VAL_19:.*]] = fir.coordinate_of %[[VAL_0]], %[[VAL_18]] : (!fir.ref<!fir.array<3xi32>>, index) -> !fir.ref<i32>
29+
! CHECK: fir.store %[[VAL_17]] to %[[VAL_19]] : !fir.ref<i32>
30+
! CHECK: %[[VAL_20:.*]] = arith.constant 2 : index
31+
! CHECK: %[[VAL_21:.*]]:3 = fir.box_dims %[[VAL_9]], %[[VAL_20]] : (!fir.box<!fir.ptr<!fir.array<?x?x?xf32>>>, index) -> (index, index, index)
32+
! CHECK: %[[VAL_22:.*]] = fir.convert %[[VAL_21]]#1 : (index) -> i32
33+
! CHECK: %[[VAL_23:.*]] = arith.constant 2 : index
34+
! CHECK: %[[VAL_24:.*]] = fir.coordinate_of %[[VAL_0]], %[[VAL_23]] : (!fir.ref<!fir.array<3xi32>>, index) -> !fir.ref<i32>
35+
! CHECK: fir.store %[[VAL_22]] to %[[VAL_24]] : !fir.ref<i32>
36+
! CHECK: %[[VAL_25:.*]] = arith.constant 3 : index
37+
! CHECK: %[[VAL_26:.*]] = fir.shape %[[VAL_25]] : (index) -> !fir.shape<1>
38+
! CHECK: %[[VAL_27:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_26]]) {uniq_name = ".tmp.intrinsic_result"} : (!fir.ref<!fir.array<3xi32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<3xi32>>, !fir.ref<!fir.array<3xi32>>)
39+
40+
subroutine test_kind()
41+
interface
42+
function return_array()
43+
real, pointer :: return_array(:, :, :)
44+
end function
45+
end interface
46+
print *, shape(return_array(), kind=8)
47+
end subroutine
48+
! CHECK-LABEL: func.func @_QPtest_kind() {
49+
! CHECK: %[[VAL_0:.*]] = fir.alloca !fir.array<3xi64>
50+
! CHECK: %[[VAL_7:.*]] = fir.call @_QPreturn_array() {{.*}}: () -> !fir.box<!fir.ptr<!fir.array<?x?x?xf32>>>
51+
! CHECK: fir.save_result %[[VAL_7]] to %[[VAL_1:.*]] : !fir.box<!fir.ptr<!fir.array<?x?x?xf32>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?x?x?xf32>>>>
52+
! CHECK: %[[VAL_8:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = ".tmp.func_result"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?x?x?xf32>>>>) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?x?x?xf32>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?x?x?xf32>>>>)
53+
! CHECK: %[[VAL_9:.*]] = fir.load %[[VAL_8]]#1 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?x?x?xf32>>>>
54+
! CHECK: %[[VAL_10:.*]] = arith.constant 0 : index
55+
! CHECK: %[[VAL_11:.*]]:3 = fir.box_dims %[[VAL_9]], %[[VAL_10]] : (!fir.box<!fir.ptr<!fir.array<?x?x?xf32>>>, index) -> (index, index, index)
56+
! CHECK: %[[VAL_12:.*]] = fir.convert %[[VAL_11]]#1 : (index) -> i64
57+
! CHECK: %[[VAL_13:.*]] = arith.constant 0 : index
58+
! CHECK: %[[VAL_14:.*]] = fir.coordinate_of %[[VAL_0]], %[[VAL_13]] : (!fir.ref<!fir.array<3xi64>>, index) -> !fir.ref<i64>
59+
! CHECK: fir.store %[[VAL_12]] to %[[VAL_14]] : !fir.ref<i64>
60+
! CHECK: %[[VAL_15:.*]] = arith.constant 1 : index
61+
! CHECK: %[[VAL_16:.*]]:3 = fir.box_dims %[[VAL_9]], %[[VAL_15]] : (!fir.box<!fir.ptr<!fir.array<?x?x?xf32>>>, index) -> (index, index, index)
62+
! CHECK: %[[VAL_17:.*]] = fir.convert %[[VAL_16]]#1 : (index) -> i64
63+
! CHECK: %[[VAL_18:.*]] = arith.constant 1 : index
64+
! CHECK: %[[VAL_19:.*]] = fir.coordinate_of %[[VAL_0]], %[[VAL_18]] : (!fir.ref<!fir.array<3xi64>>, index) -> !fir.ref<i64>
65+
! CHECK: fir.store %[[VAL_17]] to %[[VAL_19]] : !fir.ref<i64>
66+
! CHECK: %[[VAL_20:.*]] = arith.constant 2 : index
67+
! CHECK: %[[VAL_21:.*]]:3 = fir.box_dims %[[VAL_9]], %[[VAL_20]] : (!fir.box<!fir.ptr<!fir.array<?x?x?xf32>>>, index) -> (index, index, index)
68+
! CHECK: %[[VAL_22:.*]] = fir.convert %[[VAL_21]]#1 : (index) -> i64
69+
! CHECK: %[[VAL_23:.*]] = arith.constant 2 : index
70+
! CHECK: %[[VAL_24:.*]] = fir.coordinate_of %[[VAL_0]], %[[VAL_23]] : (!fir.ref<!fir.array<3xi64>>, index) -> !fir.ref<i64>
71+
! CHECK: fir.store %[[VAL_22]] to %[[VAL_24]] : !fir.ref<i64>
72+
! CHECK: %[[VAL_25:.*]] = arith.constant 3 : index
73+
! CHECK: %[[VAL_26:.*]] = fir.shape %[[VAL_25]] : (index) -> !fir.shape<1>
74+
! CHECK: %[[VAL_27:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_26]]) {uniq_name = ".tmp.intrinsic_result"} : (!fir.ref<!fir.array<3xi64>>, !fir.shape<1>) -> (!fir.ref<!fir.array<3xi64>>, !fir.ref<!fir.array<3xi64>>)

0 commit comments

Comments
 (0)