[flang-commits] [flang] 9f867a3 - [flang][hlfir] Add assignment mask operations
Jean Perier via flang-commits
flang-commits at lists.llvm.org
Thu May 4 01:02:28 PDT 2023
Author: Jean Perier
Date: 2023-05-04T10:00:36+02:00
New Revision: 9f867a3c46d0067c2fd65650de23ecb75a9c817b
URL: https://github.com/llvm/llvm-project/commit/9f867a3c46d0067c2fd65650de23ecb75a9c817b
DIFF: https://github.com/llvm/llvm-project/commit/9f867a3c46d0067c2fd65650de23ecb75a9c817b.diff
LOG: [flang][hlfir] Add assignment mask operations
Add hlfir.forall_mask, hlfir.where, and hlfir.elsewhere operations that
are operations that holds (optionally for hlfir.elsewhere) the
evaluation of a logical mask that controls the evaluation of nested
operations.
They allow representing Fortran forall control mask, as well as where
and eslewhere statements/constructs.
They use the OrderedAssignmentTreeOpInterface since they can all be used
inside Forall and their masks should be fully evaluated for all the
index-value set induced by parent Forall before any of the nested
operations in their body is evaluated.
I initially tried making them into a single operation with some attributes
to make a difference, but I felt this made the verifier/parser/printer and
usages messier/tricky compared to making three distinct operations that
represent the three Fortran feature in a vanilla way.
Differential Revision: https://reviews.llvm.org/D149754
Added:
flang/test/HLFIR/elsewhere.fir
flang/test/HLFIR/forall_mask.fir
flang/test/HLFIR/where.fir
Modified:
flang/include/flang/Optimizer/HLFIR/HLFIROps.td
flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp
flang/test/HLFIR/invalid.fir
Removed:
################################################################################
diff --git a/flang/include/flang/Optimizer/HLFIR/HLFIROps.td b/flang/include/flang/Optimizer/HLFIR/HLFIROps.td
index 792cfe1d005a9..de21464ae79ce 100644
--- a/flang/include/flang/Optimizer/HLFIR/HLFIROps.td
+++ b/flang/include/flang/Optimizer/HLFIR/HLFIROps.td
@@ -939,7 +939,7 @@ def hlfir_RegionAssignOp : hlfir_Op<"region_assign", [hlfir_OrderedAssignmentTre
}
def hlfir_YieldOp : hlfir_Op<"yield", [Terminator, ParentOneOf<["RegionAssignOp",
- "ElementalAddrOp", "ForallOp"]>,
+ "ElementalAddrOp", "ForallOp", "ForallMaskOp", "WhereOp", "ElseWhereOp"]>,
SingleBlockImplicitTerminator<"fir::FirEndOp">]> {
let summary = "Yield a value or variable inside a forall, where or region assignment";
@@ -1114,4 +1114,123 @@ def hlfir_ForallOp : hlfir_Op<"forall", [hlfir_OrderedAssignmentTreeOpInterface]
}];
}
+/// Shared definition for hlfir.forall_mask and hlfir.where
+/// that have the same structure and assembly format, but not the same
+/// constraints.
+class hlfir_AssignmentMaskOp<string mnemonic> : hlfir_Op<mnemonic,
+ [hlfir_OrderedAssignmentTreeOpInterface]> {
+ let regions = (region SizedRegion<1>:$mask_region,
+ SizedRegion<1>:$body);
+
+ let extraClassDeclaration = [{
+ void getLeafRegions(llvm::SmallVectorImpl<mlir::Region*>& regions) {
+ regions.push_back(&getMaskRegion());
+ }
+ mlir::Region* getSubTreeRegion() { return &getBody(); }
+ }];
+
+ let assemblyFormat = [{
+ $mask_region
+ attr-dict `do`
+ custom<AssignmentMaskOpBody>($body)
+ }];
+}
+
+def hlfir_ForallMaskOp : hlfir_AssignmentMaskOp<"forall_mask"> {
+ let summary = "Represent a Fortran forall mask";
+ let description = [{
+ Fortran Forall can have a scalar mask expression that depends on the
+ Forall index-name value.
+ hlfir.forall_mask allows representing this mask. The expression
+ evaluation is held in the mask region that must yield an i1 scalar
+ value.
+ An hlfir.forall_mask must be directly nested in the body region of
+ an hlfir.forall. It is a separate operation so that it can use the
+ index SSA value defined by the hlfir.forall body region.
+
+ Example: "FORALL(I=1:10, SOME_CONDITION(I)) X(I) = FOO(I)"
+ ```
+ hlfir.forall lb {
+ hlfir.yield %c1 : index
+ } ub {
+ hlfir.yield %c10 : index
+ } (%i : index) {
+ hlfir.forall_mask {
+ %mask = fir.call @some_condition(%i) : (index) -> i1
+ hlfir.yield %mask : i1
+ } do {
+ hlfir.region_assign {
+ %res = fir.call @foo(%i) : (index) -> f32
+ hlfir.yield %res : f32
+ } to {
+ %xi = hlfir.designate %x(%i) : (!fir.box<!fir.array<?xf32>>, index) -> !fir.ref<f32>
+ hlfir.yield %xi : !fir.ref<f32>
+ }
+ }
+ }
+ ```
+ }];
+ let hasVerifier = 1;
+}
+
+def hlfir_WhereOp : hlfir_AssignmentMaskOp<"where"> {
+ let summary = "Represent a Fortran where construct or statement";
+ let description = [{
+ Represent Fortran "where" construct or statement. The mask
+ expression evaluation is held in the mask region that must yield
+ logical array that has the same shape as all the nested
+ hlfir.region_assign left-hand sides, and all the nested hlfir.where
+ or hlfir.elsewhere masks.
+
+ The values of the where and elsewhere masks form a control mask that
+ controls all the nested hlfir.region_assign: only the array element for
+ which the related control mask value is true are assigned. Any right-hand
+ side elemental expression is only evaluated for elements where the control
+ mask is true. See Fortran standard 2018 section 10.2.3 for more detailed
+ about the control mask semantic.
+
+ An hlfir.where must not contain any hlfir.forall but it may be contained
+ in such operation. This matches Fortran rules.
+ }];
+ let hasVerifier = 1;
+}
+
+def hlfir_ElseWhereOp : hlfir_Op<"elsewhere", [Terminator,
+ ParentOneOf<["WhereOp", "ElseWhereOp"]>, hlfir_OrderedAssignmentTreeOpInterface]> {
+ let summary = "Represent a Fortran elsewhere statement";
+
+ let description = [{
+ Represent Fortran "elsewhere" construct or statement.
+
+ It has an optional mask region to hold the evaluation of Fortran
+ optional elsewhere mask expressions. If this region is provided,
+ it must satisfy the same constraints as hlfir.where mask region.
+
+ An hlfir.elsewhere must be the last operation of an hlfir.where or,
+ hlfir.elsewhere body, which is enforced by its terminator property.
+
+ Like in Fortran, an hlfir.elsewhere negate the current control mask,
+ and if provided, adds the mask the resulting control mask (with a logical
+ AND).
+ }];
+
+ let regions = (region MaxSizedRegion<1>:$mask_region,
+ SizedRegion<1>:$body);
+
+ let extraClassDeclaration = [{
+ void getLeafRegions(llvm::SmallVectorImpl<mlir::Region*>& regions) {
+ if (!getMaskRegion().empty())
+ regions.push_back(&getMaskRegion());
+ }
+ mlir::Region* getSubTreeRegion() { return &getBody(); }
+ }];
+
+ let assemblyFormat = [{
+ (`mask` $mask_region^)?
+ attr-dict `do`
+ custom<AssignmentMaskOpBody>($body)
+ }];
+ let hasVerifier = 1;
+}
+
#endif // FORTRAN_DIALECT_HLFIR_OPS
diff --git a/flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp b/flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp
index c03b7c92248fb..7220c0860fc27 100644
--- a/flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp
+++ b/flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp
@@ -1151,6 +1151,81 @@ static bool yieldsIntegerOrEmpty(mlir::Region ®ion) {
return yield && fir::isa_integer(yield.getEntity().getType());
}
+//===----------------------------------------------------------------------===//
+// ForallMaskOp
+//===----------------------------------------------------------------------===//
+
+static mlir::ParseResult parseAssignmentMaskOpBody(mlir::OpAsmParser &parser,
+ mlir::Region &body) {
+ if (parser.parseRegion(body))
+ return mlir::failure();
+ ensureTerminator(body, parser.getBuilder(),
+ parser.getBuilder().getUnknownLoc());
+ return mlir::success();
+}
+
+template <typename ConcreteOp>
+static void printAssignmentMaskOpBody(mlir::OpAsmPrinter &p, ConcreteOp,
+ mlir::Region &body) {
+ // ElseWhereOp is a WhereOp/ElseWhereOp terminator that should be printed.
+ bool printBlockTerminators =
+ !body.empty() &&
+ mlir::isa_and_nonnull<hlfir::ElseWhereOp>(body.back().getTerminator());
+ p.printRegion(body, /*printEntryBlockArgs=*/false, printBlockTerminators);
+}
+
+static bool yieldsLogical(mlir::Region ®ion, bool mustBeScalarI1) {
+ if (region.empty())
+ return false;
+ auto yield = mlir::dyn_cast_or_null<hlfir::YieldOp>(getTerminator(region));
+ if (!yield)
+ return false;
+ mlir::Type yieldType = yield.getEntity().getType();
+ if (mustBeScalarI1)
+ return hlfir::isI1Type(yieldType);
+ return hlfir::isMaskArgument(yieldType) &&
+ hlfir::getFortranElementOrSequenceType(yieldType)
+ .isa<fir::SequenceType>();
+}
+
+mlir::LogicalResult hlfir::ForallMaskOp::verify() {
+ if (!yieldsLogical(getMaskRegion(), /*mustBeScalarI1=*/true))
+ return emitOpError("mask region must yield a scalar i1");
+ mlir::Operation *op = getOperation();
+ hlfir::ForallOp forallOp =
+ mlir::dyn_cast_or_null<hlfir::ForallOp>(op->getParentOp());
+ if (!forallOp || op->getParentRegion() != &forallOp.getBody())
+ return emitOpError("must be inside the body region of an hlfir.forall");
+ return mlir::success();
+}
+
+//===----------------------------------------------------------------------===//
+// WhereOp and ElseWhereOp
+//===----------------------------------------------------------------------===//
+
+template <typename ConcreteOp>
+static mlir::LogicalResult verifyWhereAndElseWhereBody(ConcreteOp &concreteOp) {
+ for (mlir::Operation &op : concreteOp.getBody().front())
+ if (mlir::isa<hlfir::ForallOp>(op))
+ return concreteOp.emitOpError(
+ "body region must not contain hlfir.forall");
+ return mlir::success();
+}
+
+mlir::LogicalResult hlfir::WhereOp::verify() {
+ if (!yieldsLogical(getMaskRegion(), /*mustBeScalarI1=*/false))
+ return emitOpError("mask region must yield a logical array");
+ return verifyWhereAndElseWhereBody(*this);
+}
+
+mlir::LogicalResult hlfir::ElseWhereOp::verify() {
+ if (!getMaskRegion().empty())
+ if (!yieldsLogical(getMaskRegion(), /*mustBeScalarI1=*/false))
+ return emitOpError(
+ "mask region must yield a logical array when provided");
+ return verifyWhereAndElseWhereBody(*this);
+}
+
#include "flang/Optimizer/HLFIR/HLFIROpInterfaces.cpp.inc"
#define GET_OP_CLASSES
#include "flang/Optimizer/HLFIR/HLFIROps.cpp.inc"
diff --git a/flang/test/HLFIR/elsewhere.fir b/flang/test/HLFIR/elsewhere.fir
new file mode 100644
index 0000000000000..b0033a6dc5b4f
--- /dev/null
+++ b/flang/test/HLFIR/elsewhere.fir
@@ -0,0 +1,82 @@
+// Test hlfir.elsewhere operation parse, verify (no errors), and unparse.
+// RUN: fir-opt %s | fir-opt | FileCheck %s
+
+func.func @test_elsewhere(%mask: !fir.ref<!fir.array<10x!fir.logical<4>>>, %x: !fir.ref<!fir.array<10xf32>>, %y: !fir.box<!fir.array<?xf32>>) {
+ hlfir.where {
+ hlfir.yield %mask : !fir.ref<!fir.array<10x!fir.logical<4>>>
+ } do {
+ hlfir.elsewhere do {
+ hlfir.region_assign {
+ hlfir.yield %y : !fir.box<!fir.array<?xf32>>
+ } to {
+ hlfir.yield %x : !fir.ref<!fir.array<10xf32>>
+ }
+ }
+ }
+ return
+}
+// CHECK-LABEL: func.func @test_elsewhere(
+// CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.array<10x!fir.logical<4>>>,
+// CHECK-SAME: %[[VAL_1:.*]]: !fir.ref<!fir.array<10xf32>>,
+// CHECK-SAME: %[[VAL_2:.*]]: !fir.box<!fir.array<?xf32>>) {
+// CHECK: hlfir.where {
+// CHECK: hlfir.yield %[[VAL_0]] : !fir.ref<!fir.array<10x!fir.logical<4>>>
+// CHECK: } do {
+// CHECK: hlfir.elsewhere do {
+// CHECK: hlfir.region_assign {
+// CHECK: hlfir.yield %[[VAL_2]] : !fir.box<!fir.array<?xf32>>
+// CHECK: } to {
+// CHECK: hlfir.yield %[[VAL_1]] : !fir.ref<!fir.array<10xf32>>
+// CHECK: }
+// CHECK: }
+// CHECK: }
+
+func.func @test_masked_elsewhere(%mask: !fir.ref<!fir.array<10x!fir.logical<4>>>, %x: !fir.ref<!fir.array<10xf32>>, %y: !fir.box<!fir.array<?xf32>>) {
+ hlfir.where {
+ hlfir.yield %mask : !fir.ref<!fir.array<10x!fir.logical<4>>>
+ } do {
+ hlfir.elsewhere mask {
+ %other_mask = fir.call @get_mask() : () -> !fir.ptr<!fir.array<10x!fir.logical<4>>>
+ hlfir.yield %other_mask : !fir.ptr<!fir.array<10x!fir.logical<4>>>
+ } do {
+ hlfir.region_assign {
+ hlfir.yield %y : !fir.box<!fir.array<?xf32>>
+ } to {
+ hlfir.yield %x : !fir.ref<!fir.array<10xf32>>
+ }
+ hlfir.elsewhere do {
+ hlfir.region_assign {
+ hlfir.yield %x : !fir.ref<!fir.array<10xf32>>
+ } to {
+ hlfir.yield %y : !fir.box<!fir.array<?xf32>>
+ }
+ }
+ }
+ }
+ return
+}
+// CHECK-LABEL: func.func @test_masked_elsewhere(
+// CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.array<10x!fir.logical<4>>>,
+// CHECK-SAME: %[[VAL_1:.*]]: !fir.ref<!fir.array<10xf32>>,
+// CHECK-SAME: %[[VAL_2:.*]]: !fir.box<!fir.array<?xf32>>) {
+// CHECK: hlfir.where {
+// CHECK: hlfir.yield %[[VAL_0]] : !fir.ref<!fir.array<10x!fir.logical<4>>>
+// CHECK: } do {
+// CHECK: hlfir.elsewhere mask {
+// CHECK: %[[VAL_3:.*]] = fir.call @get_mask() : () -> !fir.ptr<!fir.array<10x!fir.logical<4>>>
+// CHECK: hlfir.yield %[[VAL_3]] : !fir.ptr<!fir.array<10x!fir.logical<4>>>
+// CHECK: } do {
+// CHECK: hlfir.region_assign {
+// CHECK: hlfir.yield %[[VAL_2]] : !fir.box<!fir.array<?xf32>>
+// CHECK: } to {
+// CHECK: hlfir.yield %[[VAL_1]] : !fir.ref<!fir.array<10xf32>>
+// CHECK: }
+// CHECK: hlfir.elsewhere do {
+// CHECK: hlfir.region_assign {
+// CHECK: hlfir.yield %[[VAL_1]] : !fir.ref<!fir.array<10xf32>>
+// CHECK: } to {
+// CHECK: hlfir.yield %[[VAL_2]] : !fir.box<!fir.array<?xf32>>
+// CHECK: }
+// CHECK: }
+// CHECK: }
+// CHECK: }
diff --git a/flang/test/HLFIR/forall_mask.fir b/flang/test/HLFIR/forall_mask.fir
new file mode 100644
index 0000000000000..b0ca270084e38
--- /dev/null
+++ b/flang/test/HLFIR/forall_mask.fir
@@ -0,0 +1,49 @@
+// Test hlfir.forall_mask operation parse, verify (no errors), and unparse.
+// RUN: fir-opt %s | fir-opt | FileCheck %s
+
+func.func @forall_mask_test(%x: !fir.box<!fir.array<?xf32>>) {
+ %c1 = arith.constant 1 : index
+ %c10 = arith.constant 10 : index
+ hlfir.forall lb {
+ hlfir.yield %c1 : index
+ } ub {
+ hlfir.yield %c10 : index
+ } (%i : index) {
+ hlfir.forall_mask {
+ %mask = fir.call @some_condition(%i) : (index) -> i1
+ hlfir.yield %mask : i1
+ } do {
+ hlfir.region_assign {
+ %res = fir.call @foo(%i) : (index) -> f32
+ hlfir.yield %res : f32
+ } to {
+ %xi = hlfir.designate %x(%i) : (!fir.box<!fir.array<?xf32>>, index) -> !fir.ref<f32>
+ hlfir.yield %xi : !fir.ref<f32>
+ }
+ }
+ }
+ return
+}
+
+// CHECK-LABEL: func.func @forall_mask_test(
+// CHECK-SAME: %[[VAL_0:.*]]: !fir.box<!fir.array<?xf32>>) {
+// CHECK: %[[VAL_1:.*]] = arith.constant 1 : index
+// CHECK: %[[VAL_2:.*]] = arith.constant 10 : index
+// CHECK: hlfir.forall lb {
+// CHECK: hlfir.yield %[[VAL_1]] : index
+// CHECK: } ub {
+// CHECK: hlfir.yield %[[VAL_2]] : index
+// CHECK: } (%[[VAL_3:.*]]: index) {
+// CHECK: hlfir.forall_mask {
+// CHECK: %[[VAL_4:.*]] = fir.call @some_condition(%[[VAL_3]]) : (index) -> i1
+// CHECK: hlfir.yield %[[VAL_4]] : i1
+// CHECK: } do {
+// CHECK: hlfir.region_assign {
+// CHECK: %[[VAL_5:.*]] = fir.call @foo(%[[VAL_3]]) : (index) -> f32
+// CHECK: hlfir.yield %[[VAL_5]] : f32
+// CHECK: } to {
+// CHECK: %[[VAL_6:.*]] = hlfir.designate %[[VAL_0]] (%[[VAL_3]]) : (!fir.box<!fir.array<?xf32>>, index) -> !fir.ref<f32>
+// CHECK: hlfir.yield %[[VAL_6]] : !fir.ref<f32>
+// CHECK: }
+// CHECK: }
+// CHECK: }
diff --git a/flang/test/HLFIR/invalid.fir b/flang/test/HLFIR/invalid.fir
index c1bcdaf687c78..29b61f0487c21 100644
--- a/flang/test/HLFIR/invalid.fir
+++ b/flang/test/HLFIR/invalid.fir
@@ -642,3 +642,110 @@ func.func @bad_forall_2(%x : !fir.box<!fir.array<10xf32>>, %y: f32) {
}
return
}
+
+// -----
+func.func @bad_forall_mask(%i: index) {
+ // expected-error at +1 {{'hlfir.forall_mask' op must be inside the body region of an hlfir.forall}}
+ hlfir.forall_mask {
+ %mask = fir.call @some_condition(%i) : (index) -> i1
+ hlfir.yield %mask : i1
+ } do {
+ }
+ return
+}
+
+// -----
+func.func @bad_forall_mask_2(%mask: !fir.ref<!fir.array<10x!fir.logical<4>>>) {
+ %c1 = arith.constant 1 : index
+ hlfir.forall lb {
+ hlfir.yield %c1 : index
+ } ub {
+ hlfir.yield %c1 : index
+ } (%i: index) {
+ // expected-error at +1 {{'hlfir.forall_mask' op mask region must yield a scalar i1}}
+ hlfir.forall_mask {
+ hlfir.yield %mask : !fir.ref<!fir.array<10x!fir.logical<4>>>
+ } do {
+ }
+ }
+ return
+}
+
+// -----
+func.func @bad_where_1(%bad_mask: !fir.ref<!fir.array<10xf32>>) {
+ // expected-error at +1 {{'hlfir.where' op mask region must yield a logical array}}
+ hlfir.where {
+ hlfir.yield %bad_mask : !fir.ref<!fir.array<10xf32>>
+ } do {
+ }
+ return
+}
+
+// -----
+func.func @bad_where_2(%bad_mask: i1) {
+ // expected-error at +1 {{'hlfir.where' op mask region must yield a logical array}}
+ hlfir.where {
+ hlfir.yield %bad_mask : i1
+ } do {
+ }
+ return
+}
+
+// -----
+func.func @bad_where_3(%mask: !fir.ref<!fir.array<10x!fir.logical<4>>>, %n: index) {
+ // expected-error at +1 {{'hlfir.where' op body region must not contain hlfir.forall}}
+ hlfir.where {
+ hlfir.yield %mask : !fir.ref<!fir.array<10x!fir.logical<4>>>
+ } do {
+ hlfir.forall lb {
+ hlfir.yield %n : index
+ } ub {
+ hlfir.yield %n : index
+ } (%i: index) {
+ }
+ }
+ return
+}
+
+// -----
+func.func @bad_elsewhere_1(%mask: !fir.ref<!fir.array<10x!fir.logical<4>>>, %bad_mask: i1) {
+ hlfir.where {
+ hlfir.yield %mask : !fir.ref<!fir.array<10x!fir.logical<4>>>
+ } do {
+ // expected-error at +1 {{'hlfir.elsewhere' op mask region must yield a logical array when provided}}
+ hlfir.elsewhere mask {
+ hlfir.yield %bad_mask : i1
+ } do {
+ }
+ }
+ return
+}
+
+// -----
+func.func @bad_elsewhere_2(%mask: !fir.ref<!fir.array<10x!fir.logical<4>>>) {
+ // expected-error at +1 {{'hlfir.elsewhere' op expects parent op to be one of 'hlfir.where, hlfir.elsewhere'}}
+ hlfir.elsewhere mask {
+ hlfir.yield %mask : !fir.ref<!fir.array<10x!fir.logical<4>>>
+ } do {
+ }
+ return
+}
+
+// -----
+func.func @bad_elsewhere_3(%mask: !fir.ref<!fir.array<10x!fir.logical<4>>>, %x: !fir.ref<!fir.array<10xf32>>, %y: !fir.box<!fir.array<?xf32>>) {
+ hlfir.where {
+ hlfir.yield %mask : !fir.ref<!fir.array<10x!fir.logical<4>>>
+ } do {
+ // expected-error at +1 {{'hlfir.elsewhere' op must be the last operation in the parent block}}
+ hlfir.elsewhere mask {
+ hlfir.yield %mask : !fir.ref<!fir.array<10x!fir.logical<4>>>
+ } do {
+ }
+ hlfir.region_assign {
+ hlfir.yield %y : !fir.box<!fir.array<?xf32>>
+ } to {
+ hlfir.yield %x : !fir.ref<!fir.array<10xf32>>
+ }
+ }
+ return
+}
diff --git a/flang/test/HLFIR/where.fir b/flang/test/HLFIR/where.fir
new file mode 100644
index 0000000000000..2aa242c9491df
--- /dev/null
+++ b/flang/test/HLFIR/where.fir
@@ -0,0 +1,28 @@
+// Test hlfir.where operation parse, verify (no errors), and unparse.
+// RUN: fir-opt %s | fir-opt | FileCheck %s
+
+func.func @test_where(%mask: !fir.ref<!fir.array<10x!fir.logical<4>>>, %x: !fir.ref<!fir.array<10xf32>>, %y: !fir.box<!fir.array<?xf32>>) {
+ hlfir.where {
+ hlfir.yield %mask : !fir.ref<!fir.array<10x!fir.logical<4>>>
+ } do {
+ hlfir.region_assign {
+ hlfir.yield %y : !fir.box<!fir.array<?xf32>>
+ } to {
+ hlfir.yield %x : !fir.ref<!fir.array<10xf32>>
+ }
+ }
+ return
+}
+// CHECK-LABEL: func.func @test_where(
+// CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.array<10x!fir.logical<4>>>,
+// CHECK-SAME: %[[VAL_1:.*]]: !fir.ref<!fir.array<10xf32>>,
+// CHECK-SAME: %[[VAL_2:.*]]: !fir.box<!fir.array<?xf32>>) {
+// CHECK: hlfir.where {
+// CHECK: hlfir.yield %[[VAL_0]] : !fir.ref<!fir.array<10x!fir.logical<4>>>
+// CHECK: } do {
+// CHECK: hlfir.region_assign {
+// CHECK: hlfir.yield %[[VAL_2]] : !fir.box<!fir.array<?xf32>>
+// CHECK: } to {
+// CHECK: hlfir.yield %[[VAL_1]] : !fir.ref<!fir.array<10xf32>>
+// CHECK: }
+// CHECK: }
More information about the flang-commits
mailing list