Skip to content

Commit 508d49a

Browse files
committed
[flang] lower product intrinsic to hlfir.product operation
Carries out the initial lowering of the product intrinsic into HLFIR following a similar method to sum, the --use-hlfir-intrinsic-ops flag in test/Lower/HLFIR/expr-box is set to false so that the tests will pass until hlfir.product is lowered into fir.call Depends on: D147624 Differential Revision: https://reviews.llvm.org/D148719
1 parent 41b5268 commit 508d49a

File tree

3 files changed

+149
-7
lines changed

3 files changed

+149
-7
lines changed

flang/lib/Lower/ConvertCall.cpp

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1338,20 +1338,49 @@ genHLFIRIntrinsicRefCore(PreparedActualArguments &loweredActuals,
13381338
return hlfir::ExprType::get(builder.getContext(), resultShape, elementType,
13391339
/*polymorphic=*/false);
13401340
};
1341-
const std::string intrinsicName = callContext.getProcedureName();
1342-
if (intrinsicName == "sum") {
1341+
1342+
auto buildSumOperation = [](fir::FirOpBuilder &builder, mlir::Location loc,
1343+
mlir::Type resultTy, mlir::Value array,
1344+
mlir::Value dim, mlir::Value mask) {
1345+
return builder.create<hlfir::SumOp>(loc, resultTy, array, dim, mask);
1346+
};
1347+
1348+
auto buildProductOperation = [](fir::FirOpBuilder &builder,
1349+
mlir::Location loc, mlir::Type resultTy,
1350+
mlir::Value array, mlir::Value dim,
1351+
mlir::Value mask) {
1352+
return builder.create<hlfir::ProductOp>(loc, resultTy, array, dim, mask);
1353+
};
1354+
1355+
auto buildReductionIntrinsic =
1356+
[&](PreparedActualArguments &loweredActuals, mlir::Location loc,
1357+
fir::FirOpBuilder &builder, CallContext &callContext,
1358+
std::function<mlir::Operation *(fir::FirOpBuilder &, mlir::Location,
1359+
mlir::Type, mlir::Value, mlir::Value,
1360+
mlir::Value)>
1361+
buildFunc) -> std::optional<hlfir::EntityWithAttributes> {
1362+
// shared logic for building the product and sum operations
13431363
llvm::SmallVector<mlir::Value> operands = getOperandVector(loweredActuals);
13441364
assert(operands.size() == 3);
1365+
// dim, mask can be NULL if these arguments were not given
13451366
mlir::Value array = operands[0];
13461367
mlir::Value dim = operands[1];
13471368
if (dim)
13481369
dim = hlfir::loadTrivialScalar(loc, builder, hlfir::Entity{dim});
13491370
mlir::Value mask = operands[2];
13501371
mlir::Type resultTy = computeResultType(array, *callContext.resultType);
1351-
// dim, mask can be NULL if these arguments were not given
1352-
hlfir::SumOp sumOp =
1353-
builder.create<hlfir::SumOp>(loc, resultTy, array, dim, mask);
1354-
return {hlfir::EntityWithAttributes{sumOp.getResult()}};
1372+
auto *intrinsicOp = buildFunc(builder, loc, resultTy, array, dim, mask);
1373+
return {hlfir::EntityWithAttributes{intrinsicOp->getResult(0)}};
1374+
};
1375+
1376+
const std::string intrinsicName = callContext.getProcedureName();
1377+
if (intrinsicName == "sum") {
1378+
return buildReductionIntrinsic(loweredActuals, loc, builder, callContext,
1379+
buildSumOperation);
1380+
}
1381+
if (intrinsicName == "product") {
1382+
return buildReductionIntrinsic(loweredActuals, loc, builder, callContext,
1383+
buildProductOperation);
13551384
}
13561385
if (intrinsicName == "matmul") {
13571386
llvm::SmallVector<mlir::Value> operands = getOperandVector(loweredActuals);

flang/test/Lower/HLFIR/expr-box.f90

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
! Test lowering of of expressions as fir.box
2-
! RUN: bbc -hlfir -o - %s 2>&1 | FileCheck %s
2+
! RUN: bbc -hlfir -o - %s 2>&1 --use-hlfir-intrinsic-ops=false | FileCheck %s
33

44
! CHECK-LABEL: func.func @_QPfoo(
55
! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.array<10xi32>>

flang/test/Lower/HLFIR/product.f90

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
! Test lowering of PRODUCT intrinsic to HLFIR
2+
! RUN: bbc -emit-fir -hlfir -o - %s 2>&1 | FileCheck %s
3+
4+
! simple 1 argument PRODUCT
5+
subroutine product1(a, s)
6+
integer :: a(:), s
7+
s = PRODUCT(a)
8+
end subroutine
9+
! CHECK-LABEL: func.func @_QPproduct1(
10+
! CHECK: %[[ARG0:.*]]: !fir.box<!fir.array<?xi32>> {fir.bindc_name = "a"}, %[[ARG1:.*]]: !fir.ref<i32>
11+
! CHECK-DAG: %[[ARRAY:.*]]:2 = hlfir.declare %[[ARG0]]
12+
! CHECK-DAG: %[[OUT:.*]]:2 = hlfir.declare %[[ARG1]]
13+
! CHECK-NEXT: %[[EXPR:.*]] = hlfir.product %[[ARRAY]]#0 {fastmath = #arith.fastmath<contract>} : (!fir.box<!fir.array<?xi32>>) -> !hlfir.expr<i32>
14+
! CHECK-NEXT: hlfir.assign %[[EXPR]] to %[[OUT]]#0 : !hlfir.expr<i32>, !fir.ref<i32>
15+
! CHECK-NEXT: hlfir.destroy %[[EXPR]]
16+
! CHECK-NEXT: return
17+
! CHECK-NEXT: }
18+
19+
! product with by-ref DIM argument
20+
subroutine product2(a, s, d)
21+
integer :: a(:,:), s(:), d
22+
s = PRODUCT(a, d)
23+
end subroutine
24+
! CHECK-LABEL: func.func @_QPproduct2(
25+
! CHECK: %[[ARG0:.*]]: !fir.box<!fir.array<?x?xi32>> {fir.bindc_name = "a"}, %[[ARG1:.*]]: !fir.box<!fir.array<?xi32>> {fir.bindc_name = "s"}, %[[ARG2:.*]]: !fir.ref<i32>
26+
! CHECK-DAG: %[[ARRAY:.*]]:2 = hlfir.declare %[[ARG0]]
27+
! CHECK-DAG: %[[OUT:.*]]:2 = hlfir.declare %[[ARG1]]
28+
! CHECK-DAG: %[[DIM_REF:.*]]:2 = hlfir.declare %[[ARG2]]
29+
! CHECK-NEXT: %[[DIM:.*]] = fir.load %[[DIM_REF]]#0 : !fir.ref<i32>
30+
! CHECK-NEXT: %[[EXPR:.*]] = hlfir.product %[[ARRAY]]#0 dim %[[DIM]] {fastmath = #arith.fastmath<contract>} : (!fir.box<!fir.array<?x?xi32>>, i32) -> !hlfir.expr<?xi32>
31+
! CHECK-NEXT: hlfir.assign %[[EXPR]] to %[[OUT]]#0 : !hlfir.expr<?xi32>, !fir.box<!fir.array<?xi32>>
32+
! CHECK-NEXT: hlfir.destroy %[[EXPR]]
33+
! CHECK-NEXT: return
34+
! CHECK-NEXT: }
35+
36+
! product with scalar mask argument
37+
subroutine product3(a, s, m)
38+
integer :: a(:), s
39+
logical :: m
40+
s = PRODUCT(a, m)
41+
end subroutine
42+
! CHECK-LABEL: func.func @_QPproduct3(
43+
! CHECK: %[[ARG0:.*]]: !fir.box<!fir.array<?xi32>> {fir.bindc_name = "a"}, %[[ARG1:.*]]: !fir.ref<i32> {fir.bindc_name = "s"}, %[[ARG2:.*]]: !fir.ref<!fir.logical<4>> {fir.bindc_name = "m"})
44+
! CHECK-DAG: %[[ARRAY:.*]]:2 = hlfir.declare %[[ARG0]]
45+
! CHECK-DAG: %[[OUT:.*]]:2 = hlfir.declare %[[ARG1]]
46+
! CHECK-DAG: %[[MASK:.*]]:2 = hlfir.declare %[[ARG2]]
47+
! CHECK-NEXT: %[[EXPR:.*]] = hlfir.product %[[ARRAY]]#0 mask %[[MASK]]#0 {fastmath = #arith.fastmath<contract>} : (!fir.box<!fir.array<?xi32>>, !fir.ref<!fir.logical<4>>) -> !hlfir.expr<i32>
48+
! CHECK-NEXT: hlfir.assign %[[EXPR]] to %[[OUT]]#0 : !hlfir.expr<i32>, !fir.ref<i32>
49+
! CHECK-NEXT: hlfir.destroy %[[EXPR]]
50+
! CHECK-NEXT: return
51+
! CHECK-NEXT: }
52+
53+
! product with array mask argument
54+
subroutine product4(a, s, m)
55+
integer :: a(:), s
56+
logical :: m(:)
57+
s = PRODUCT(a, m)
58+
end subroutine
59+
60+
! CHECK-LABEL: func.func @_QPproduct4(
61+
! CHECK: %[[ARG0:.*]]: !fir.box<!fir.array<?xi32>> {fir.bindc_name = "a"}, %arg1: !fir.ref<i32> {fir.bindc_name = "s"}, %arg2: !fir.box<!fir.array<?x!fir.logical<4>>> {fir.bindc_name = "m"})
62+
! CHECK-DAG: %[[ARRAY:.*]]:2 = hlfir.declare %[[ARG0]]
63+
! CHECK-DAG: %[[OUT:.*]]:2 = hlfir.declare %[[ARG1]]
64+
! CHECK-DAG: %[[MASK:.*]]:2 = hlfir.declare %[[ARG2]]
65+
! CHECK-NEXT: %[[EXPR:.*]] = hlfir.product %[[ARRAY]]#0 mask %[[MASK]]#0 {fastmath = #arith.fastmath<contract>} : (!fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?x!fir.logical<4>>>) -> !hlfir.expr<i32>
66+
! CHECK-NEXT: hlfir.assign %[[EXPR]] to %[[OUT]]#0 : !hlfir.expr<i32>, !fir.ref<i32>
67+
! CHECK-NEXT: hlfir.destroy %[[EXPR]]
68+
! CHECK-NEXT: return
69+
! CHECK-NEXT: }
70+
71+
! product with all 3 arguments, dim is by-val, array isn't boxed
72+
subroutine product5(s)
73+
integer :: s(2)
74+
integer :: a(2,2) = reshape((/1, 2, 3, 4/), [2,2])
75+
s = PRODUCT(a, 1, .true.)
76+
end subroutine
77+
78+
! CHECK-LABEL: func.func @_QPproduct5(
79+
! CHECK: %[[ARG0:.*]]: !fir.ref<!fir.array<2xi32>>
80+
! CHECK-DAG: %[[ADDR:.*]] = fir.address_of({{.*}}) : !fir.ref<!fir.array<2x2xi32>>
81+
! CHECK-DAG: %[[ARRAY_SHAPE:.*]] = fir.shape {{.*}} -> !fir.shape<2>
82+
! CHECK-DAG: %[[ARRAY:.*]]:2 = hlfir.declare %[[ADDR]](%[[ARRAY_SHAPE]])
83+
! CHECK-DAG: %[[OUT_SHAPE:.*]] = fir.shape {{.*}} -> !fir.shape<1>
84+
! CHECK-DAG: %[[OUT:.*]]:2 = hlfir.declare %[[ARG0]](%[[OUT_SHAPE]])
85+
! CHECK-DAG: %[[C1:.*]] = arith.constant 1 : i32
86+
! CHECK-DAG: %[[TRUE:.*]] = arith.constant true
87+
! CHECK-NEXT: %[[EXPR:.*]] = hlfir.product %[[ARRAY]]#0 dim %[[C1]] mask %[[TRUE]] {fastmath = #arith.fastmath<contract>} : (!fir.ref<!fir.array<2x2xi32>>, i32, i1) -> !hlfir.expr<2xi32>
88+
! CHECK-NEXT: hlfir.assign %[[EXPR]] to %[[OUT]]#0 : !hlfir.expr<2xi32>, !fir.ref<!fir.array<2xi32>>
89+
! CHECK-NEXT: hlfir.destroy %[[EXPR]] : !hlfir.expr<2xi32>
90+
! CHECK-NEXT: return
91+
! CHECK-NEXT: }
92+
93+
! product with dimesnsion from pointer
94+
subroutine product6(a, s, d)
95+
integer, pointer :: d
96+
real :: a(:,:), s(:)
97+
s = PRODUCT(a, (d))
98+
end subroutine
99+
100+
! CHECK-LABEL: func.func @_QPproduct6(
101+
! CHECK: %[[ARG0:.*]]: !fir.box<!fir.array<?x?xf32>> {fir.bindc_name = "a"}, %[[ARG1:.*]]: !fir.box<!fir.array<?xf32>> {fir.bindc_name = "s"}, %[[ARG2:.*]]: !fir.ref<!fir.box<!fir.ptr<i32>>> {fir.bindc_name = "d"})
102+
! CHECK-DAG: %[[ARRAY:.*]]:2 = hlfir.declare %[[ARG0]]
103+
! CHECK-DAG: %[[OUT:.*]]:2 = hlfir.declare %[[ARG1]]
104+
! CHECK-DAG: %[[DIM:.*]]:2 = hlfir.declare %[[ARG2]]
105+
! CHECK-NEXT: %[[DIM_BOX:.*]] = fir.load %[[DIM]]#0 : !fir.ref<!fir.box<!fir.ptr<i32>>>
106+
! CHECK-NEXT: %[[DIM_ADDR:.*]] = fir.box_addr %[[DIM_BOX]] : (!fir.box<!fir.ptr<i32>>) -> !fir.ptr<i32>
107+
! CHECK-NEXT: %[[DIM0:.*]] = fir.load %[[DIM_ADDR]] : !fir.ptr<i32>
108+
! CHECK-NEXT: %[[DIM1:.*]] = hlfir.no_reassoc %[[DIM0]] : i32
109+
! CHECK-NEXT: %[[EXPR:.*]] = hlfir.product %[[ARRAY]]#0 dim %[[DIM1]] {fastmath = #arith.fastmath<contract>} : (!fir.box<!fir.array<?x?xf32>>, i32) -> !hlfir.expr<?xf32>
110+
! CHECK-NEXT: hlfir.assign %[[EXPR]] to %[[OUT]]#0 : !hlfir.expr<?xf32>, !fir.box<!fir.array<?xf32>>
111+
! CHECK-NEXT: hlfir.destroy %[[EXPR]]
112+
! CHECK-NEXT: return
113+
! CHECK-NEXT: }

0 commit comments

Comments
 (0)