[flang-commits] [flang] 9231134 - [flang][hlfir] user defined assignment codegen

Jean Perier via flang-commits flang-commits at lists.llvm.org
Mon Jun 26 04:25:00 PDT 2023


Author: Jean Perier
Date: 2023-06-26T13:24:36+02:00
New Revision: 9231134708a40f25b3e43085f432470ded081cba

URL: https://github.com/llvm/llvm-project/commit/9231134708a40f25b3e43085f432470ded081cba
DIFF: https://github.com/llvm/llvm-project/commit/9231134708a40f25b3e43085f432470ded081cba.diff

LOG: [flang][hlfir] user defined assignment codegen

Add codegen support for hlfir.region_assign with user defined
assignment.

It is currently a bit pessimistic, because outside of forall, it
does not use the PURE aspect, if any, of the assignment routine to
rule out that the routine can write to something else than the LHS that
could overlap with the RHS.
However, the current lowering is anyway adding parenthesis around the
RHS, so this should not cause performance regressions.

Differential Revision: https://reviews.llvm.org/D153516

Added: 
    flang/test/HLFIR/order_assignments/user-defined-assignment.fir

Modified: 
    flang/lib/Optimizer/HLFIR/Transforms/LowerHLFIROrderedAssignments.cpp
    flang/lib/Optimizer/HLFIR/Transforms/ScheduleOrderedAssignments.cpp

Removed: 
    


################################################################################
diff  --git a/flang/lib/Optimizer/HLFIR/Transforms/LowerHLFIROrderedAssignments.cpp b/flang/lib/Optimizer/HLFIR/Transforms/LowerHLFIROrderedAssignments.cpp
index e811d3afbfe3d..84f91c3b1d98c 100644
--- a/flang/lib/Optimizer/HLFIR/Transforms/LowerHLFIROrderedAssignments.cpp
+++ b/flang/lib/Optimizer/HLFIR/Transforms/LowerHLFIROrderedAssignments.cpp
@@ -364,6 +364,45 @@ void OrderedAssignmentRewriter::post(hlfir::ForallMaskOp forallMaskOp) {
   builder.setInsertionPointAfter(constructStack.pop_back_val());
 }
 
+/// Convert an entity to the type of a given mold.
+/// This is intended to help with cases where hlfir entity is a value while
+/// it must be used as a variable or vice-versa. These mismatches may occur
+/// between the type of user defined assignment block arguments and the actual
+/// argument that was lowered for them. The actual may be an in-memory copy
+/// while the block argument expects an hlfir.expr.
+static hlfir::Entity
+convertToMoldType(mlir::Location loc, fir::FirOpBuilder &builder,
+                  hlfir::Entity input, hlfir::Entity mold,
+                  llvm::SmallVectorImpl<hlfir::CleanupFunction> &cleanups) {
+  if (input.getType() == mold.getType())
+    return input;
+  fir::FirOpBuilder *b = &builder;
+  if (input.isVariable() && mold.isValue()) {
+    if (fir::isa_trivial(mold.getType())) {
+      // fir.ref<T> to T.
+      mlir::Value load = builder.create<fir::LoadOp>(loc, input);
+      return hlfir::Entity{builder.createConvert(loc, mold.getType(), load)};
+    }
+    // fir.ref<T> to hlfir.expr<T>.
+    mlir::Value asExpr = builder.create<hlfir::AsExprOp>(loc, input);
+    if (asExpr.getType() != mold.getType())
+      TODO(loc, "hlfir.expr conversion");
+    cleanups.emplace_back([=]() { b->create<hlfir::DestroyOp>(loc, asExpr); });
+    return hlfir::Entity{asExpr};
+  }
+  if (input.isValue() && mold.isVariable()) {
+    // T to fir.ref<T>, or hlfir.expr<T> to fir.ref<T>.
+    hlfir::AssociateOp associate = hlfir::genAssociateExpr(
+        loc, builder, input, mold.getFortranElementType(), ".tmp.val2ref");
+    cleanups.emplace_back(
+        [=]() { b->create<hlfir::EndAssociateOp>(loc, associate); });
+    return hlfir::Entity{associate.getBase()};
+  }
+  // Variable to Variable mismatch (e.g., fir.heap<T> vs fir.ref<T>), or value
+  // to Value mismatch (e.g. i1 vs fir.logical<4>).
+  return hlfir::Entity{builder.createConvert(loc, mold.getType(), input)};
+}
+
 void OrderedAssignmentRewriter::pre(hlfir::RegionAssignOp regionAssignOp) {
   mlir::Location loc = regionAssignOp.getLoc();
   auto [rhs, oldRhsYield] =
@@ -372,11 +411,45 @@ void OrderedAssignmentRewriter::pre(hlfir::RegionAssignOp regionAssignOp) {
     TODO(loc, "assignment to vector subscripted entity");
   auto [lhs, oldLhsYield] =
       generateYieldedEntity(regionAssignOp.getLhsRegion());
-  if (!regionAssignOp.getUserDefinedAssignment().empty())
-    TODO(loc, "user defined assignment inside FORALL or WHERE");
-  // TODO: preserve allocatable assignment aspects for forall once
-  // they are conveyed in hlfir.region_assign.
-  builder.create<hlfir::AssignOp>(loc, rhs, lhs);
+  if (!regionAssignOp.getUserDefinedAssignment().empty()) {
+    hlfir::Entity userAssignLhs{regionAssignOp.getUserAssignmentLhs()};
+    hlfir::Entity userAssignRhs{regionAssignOp.getUserAssignmentRhs()};
+    hlfir::Entity lhsEntity{lhs};
+    hlfir::Entity rhsEntity{rhs};
+    fir::DoLoopOp outerElementalLoop = nullptr;
+    if (lhsEntity.isArray() && userAssignLhs.isScalar()) {
+      // Elemental assignment with array argument (the RHS cannot be an array
+      // if the LHS is not).
+      mlir::Value shape = hlfir::genShape(loc, builder, lhsEntity);
+      hlfir::LoopNest elementalLoopNest =
+          hlfir::genLoopNest(loc, builder, shape);
+      outerElementalLoop = elementalLoopNest.outerLoop;
+      builder.setInsertionPointToStart(elementalLoopNest.innerLoop.getBody());
+      lhsEntity = hlfir::getElementAt(loc, builder, lhsEntity,
+                                      elementalLoopNest.oneBasedIndices);
+      rhsEntity = hlfir::getElementAt(loc, builder, rhsEntity,
+                                      elementalLoopNest.oneBasedIndices);
+    }
+
+    llvm::SmallVector<hlfir::CleanupFunction, 2> argConversionCleanups;
+    lhsEntity = convertToMoldType(loc, builder, lhsEntity, userAssignLhs,
+                                  argConversionCleanups);
+    rhsEntity = convertToMoldType(loc, builder, rhsEntity, userAssignRhs,
+                                  argConversionCleanups);
+    mapper.map(userAssignLhs, lhsEntity);
+    mapper.map(userAssignRhs, rhsEntity);
+    for (auto &op :
+         regionAssignOp.getUserDefinedAssignment().front().without_terminator())
+      (void)builder.clone(op, mapper);
+    for (auto &cleanupConversion : argConversionCleanups)
+      cleanupConversion();
+    if (outerElementalLoop)
+      builder.setInsertionPointAfter(outerElementalLoop);
+  } else {
+    // TODO: preserve allocatable assignment aspects for forall once
+    // they are conveyed in hlfir.region_assign.
+    builder.create<hlfir::AssignOp>(loc, rhs, lhs);
+  }
   generateCleanupIfAny(oldRhsYield);
   generateCleanupIfAny(oldLhsYield);
 }
@@ -995,12 +1068,12 @@ class RegionAssignConversion
   mlir::LogicalResult
   matchAndRewrite(hlfir::RegionAssignOp regionAssignOp,
                   mlir::PatternRewriter &rewriter) const override {
+    auto root = mlir::cast<hlfir::OrderedAssignmentTreeOpInterface>(
+        regionAssignOp.getOperation());
     if (!regionAssignOp.getUserDefinedAssignment().empty())
-      TODO(regionAssignOp.getLoc(), "user defined assignment in HLFIR");
-    else
-      TODO(regionAssignOp.getLoc(),
-           "assignments to vector subscripted entity in HLFIR");
-    return mlir::failure();
+      return ::rewrite(root, /*tryFusingAssignments=*/false, rewriter);
+    TODO(regionAssignOp.getLoc(),
+         "assignments to vector subscripted entity in HLFIR");
   }
 };
 

diff  --git a/flang/lib/Optimizer/HLFIR/Transforms/ScheduleOrderedAssignments.cpp b/flang/lib/Optimizer/HLFIR/Transforms/ScheduleOrderedAssignments.cpp
index d9f0bc1abab4e..de0fd19eaa8a4 100644
--- a/flang/lib/Optimizer/HLFIR/Transforms/ScheduleOrderedAssignments.cpp
+++ b/flang/lib/Optimizer/HLFIR/Transforms/ScheduleOrderedAssignments.cpp
@@ -242,9 +242,21 @@ static void gatherAssignEffects(
          "assignment to vector subscripted entity in HLFIR");
   assignEffects.emplace_back(mlir::MemoryEffects::Write::get(), assignedVar);
 
-  // TODO: gather the read/write effects of user defined assignments.
-  if (!regionAssign.getUserDefinedAssignment().empty())
-    TODO(regionAssign.getLoc(), "user defined assignments");
+  if (!regionAssign.getUserDefinedAssignment().empty()) {
+    // The write effect on the INTENT(OUT) LHS argument is already taken
+    // into account above.
+    // This side effects are "defensive" and could be improved.
+    // On top of the passed RHS argument, user defined assignments (even when
+    // pure) may also read host/used/common variable. Impure user defined
+    // assignments may write to host/used/common variables not passed via
+    // arguments. For now, simply assume the worst. Once fir.call side effects
+    // analysis is improved, it would best to let the call side effects be used
+    // directly.
+    if (userDefAssignmentMayOnlyWriteToAssignedVariable)
+      assignEffects.emplace_back(mlir::MemoryEffects::Read::get());
+    else
+      assignEffects.emplace_back(mlir::MemoryEffects::Write::get());
+  }
 }
 
 //===----------------------------------------------------------------------===//

diff  --git a/flang/test/HLFIR/order_assignments/user-defined-assignment.fir b/flang/test/HLFIR/order_assignments/user-defined-assignment.fir
new file mode 100644
index 0000000000000..aa3c6eb719165
--- /dev/null
+++ b/flang/test/HLFIR/order_assignments/user-defined-assignment.fir
@@ -0,0 +1,182 @@
+// Test code generation of hlfir.region_assign with user defined
+// assignment.
+// RUN: fir-opt %s --lower-hlfir-ordered-assignments | FileCheck %s
+
+func.func @test_simple_scalar(%i: !fir.ref<i32>, %l: !fir.ref<!fir.logical<4>>) {
+  hlfir.region_assign {
+    hlfir.yield %l : !fir.ref<!fir.logical<4>>
+  } to {
+    hlfir.yield %i : !fir.ref<i32>
+  } user_defined_assign (%arg0: !fir.ref<!fir.logical<4>>) to (%arg1: !fir.ref<i32>) {
+    fir.call @logical_to_numeric(%arg1, %arg0) : (!fir.ref<i32>, !fir.ref<!fir.logical<4>>) -> ()
+  }
+  return
+}
+// CHECK-LABEL:   func.func @test_simple_scalar(
+// CHECK-SAME:    %[[VAL_0:.*]]: !fir.ref<i32>,
+// CHECK-SAME:    %[[VAL_1:.*]]: !fir.ref<!fir.logical<4>>) {
+// CHECK:  %[[VAL_2:.*]] = fir.load %[[VAL_1]] : !fir.ref<!fir.logical<4>>
+// CHECK:  %[[VAL_3:.*]]:3 = hlfir.associate %[[VAL_2]] {uniq_name = ".tmp.forall"} : (!fir.logical<4>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>, i1)
+// CHECK:  fir.call @logical_to_numeric(%[[VAL_0]], %[[VAL_3]]#0) : (!fir.ref<i32>, !fir.ref<!fir.logical<4>>) -> ()
+// CHECK:  hlfir.end_associate %[[VAL_3]]#1, %[[VAL_3]]#2 : !fir.ref<!fir.logical<4>>, i1
+
+func.func @test_elemental_overlap(%i: !fir.ref<!fir.array<10xi32>>) {
+  %c0_i32 = arith.constant 0 : i32
+  %c10 = arith.constant 10 : index
+  %shape  = fir.shape %c10 : (index) -> !fir.shape<1>
+  hlfir.region_assign {
+    %cmp = hlfir.elemental %shape : (!fir.shape<1>) -> !hlfir.expr<10x!fir.logical<4>> {
+    ^bb0(%j: index):
+      %ielt = hlfir.designate %i (%j)  : (!fir.ref<!fir.array<10xi32>>, index) -> !fir.ref<i32>
+      %ielt_val = fir.load %ielt : !fir.ref<i32>
+      %smaller = arith.cmpi slt, %ielt_val, %c0_i32 : i32
+      %smaller_cast = fir.convert %smaller : (i1) -> !fir.logical<4>
+      hlfir.yield_element %smaller_cast : !fir.logical<4>
+    }
+    hlfir.yield %cmp : !hlfir.expr<10x!fir.logical<4>>
+  } to {
+    hlfir.yield %i : !fir.ref<!fir.array<10xi32>>
+  } user_defined_assign (%arg0: !fir.logical<4>) to (%arg1: !fir.ref<i32>) {
+    fir.call @logical_value_to_numeric(%arg1, %arg0) : (!fir.ref<i32>, !fir.logical<4>) -> ()
+  }
+  return
+}
+// CHECK-LABEL:   func.func @test_elemental_overlap(
+// CHECK-SAME:    %[[VAL_0:.*]]: !fir.ref<!fir.array<10xi32>>) {
+// CHECK:  %[[VAL_1:.*]] = arith.constant 0 : i32
+// CHECK:  %[[VAL_2:.*]] = arith.constant 10 : index
+// CHECK:  %[[VAL_3:.*]] = fir.shape %[[VAL_2]] : (index) -> !fir.shape<1>
+// CHECK:  %[[VAL_4:.*]] = hlfir.elemental %[[VAL_3]] : (!fir.shape<1>) -> !hlfir.expr<10x!fir.logical<4>> {
+// CHECK:  ^bb0(%[[VAL_5:.*]]: index):
+// CHECK:    %[[VAL_6:.*]] = hlfir.designate %[[VAL_0]] (%[[VAL_5]])  : (!fir.ref<!fir.array<10xi32>>, index) -> !fir.ref<i32>
+// CHECK:    %[[VAL_7:.*]] = fir.load %[[VAL_6]] : !fir.ref<i32>
+// CHECK:    %[[VAL_8:.*]] = arith.cmpi slt, %[[VAL_7]], %[[VAL_1]] : i32
+// CHECK:    %[[VAL_9:.*]] = fir.convert %[[VAL_8]] : (i1) -> !fir.logical<4>
+// CHECK:    hlfir.yield_element %[[VAL_9]] : !fir.logical<4>
+// CHECK:  }
+// CHECK:  %[[VAL_10:.*]]:3 = hlfir.associate %[[VAL_11:.*]](%[[VAL_3]]) {uniq_name = ".tmp.forall"} : (!hlfir.expr<10x!fir.logical<4>>, !fir.shape<1>) -> (!fir.ref<!fir.array<10x!fir.logical<4>>>, !fir.ref<!fir.array<10x!fir.logical<4>>>, i1)
+// CHECK:  %[[VAL_12:.*]] = arith.constant 10 : index
+// CHECK:  %[[VAL_13:.*]] = fir.shape %[[VAL_12]] : (index) -> !fir.shape<1>
+// CHECK:  %[[VAL_14:.*]] = arith.constant 1 : index
+// CHECK:  fir.do_loop %[[VAL_15:.*]] = %[[VAL_14]] to %[[VAL_12]] step %[[VAL_14]] {
+// CHECK:    %[[VAL_16:.*]] = hlfir.designate %[[VAL_0]] (%[[VAL_15]])  : (!fir.ref<!fir.array<10xi32>>, index) -> !fir.ref<i32>
+// CHECK:    %[[VAL_17:.*]] = hlfir.designate %[[VAL_10]]#0 (%[[VAL_15]])  : (!fir.ref<!fir.array<10x!fir.logical<4>>>, index) -> !fir.ref<!fir.logical<4>>
+// CHECK:    %[[VAL_18:.*]] = fir.load %[[VAL_17]] : !fir.ref<!fir.logical<4>>
+// CHECK:    fir.call @logical_value_to_numeric(%[[VAL_16]], %[[VAL_18]]) : (!fir.ref<i32>, !fir.logical<4>) -> ()
+// CHECK:  }
+// CHECK:  hlfir.end_associate %[[VAL_10]]#1, %[[VAL_10]]#2 : !fir.ref<!fir.array<10x!fir.logical<4>>>, i1
+
+func.func @test_array_overlap(%i: !fir.ref<!fir.array<10xi32>>) {
+  %c0_i32 = arith.constant 0 : i32
+  %c10 = arith.constant 10 : index
+  %shape  = fir.shape %c10 : (index) -> !fir.shape<1>
+  hlfir.region_assign {
+    %cmp = hlfir.elemental %shape : (!fir.shape<1>) -> !hlfir.expr<10x!fir.logical<4>> {
+    ^bb0(%j: index):
+      %ielt = hlfir.designate %i (%j)  : (!fir.ref<!fir.array<10xi32>>, index) -> !fir.ref<i32>
+      %ielt_val = fir.load %ielt : !fir.ref<i32>
+      %smaller = arith.cmpi slt, %ielt_val, %c0_i32 : i32
+      %smaller_cast = fir.convert %smaller : (i1) -> !fir.logical<4>
+      hlfir.yield_element %smaller_cast : !fir.logical<4>
+    }
+    hlfir.yield %cmp : !hlfir.expr<10x!fir.logical<4>>
+  } to {
+    hlfir.yield %i : !fir.ref<!fir.array<10xi32>>
+  } user_defined_assign (%arg0: !hlfir.expr<10x!fir.logical<4>>) to (%arg1: !fir.ref<!fir.array<10xi32>>) {
+     %1:3 = hlfir.associate %arg0(%shape) {uniq_name = "adapt.valuebyref"} : (!hlfir.expr<10x!fir.logical<4>>, !fir.shape<1>) -> (!fir.ref<!fir.array<10x!fir.logical<4>>>, !fir.ref<!fir.array<10x!fir.logical<4>>>, i1)
+    fir.call @logical_array_to_numeric(%arg1, %1#0) : (!fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10x!fir.logical<4>>>) -> ()
+     hlfir.end_associate %1#1, %1#2 : !fir.ref<!fir.array<10x!fir.logical<4>>>, i1
+  }
+  return
+}
+// CHECK-LABEL:   func.func @test_array_overlap(
+// CHECK-SAME:    %[[VAL_0:.*]]: !fir.ref<!fir.array<10xi32>>) {
+// CHECK:  %[[VAL_1:.*]] = arith.constant 0 : i32
+// CHECK:  %[[VAL_2:.*]] = arith.constant 10 : index
+// CHECK:  %[[VAL_3:.*]] = fir.shape %[[VAL_2]] : (index) -> !fir.shape<1>
+// CHECK:  %[[VAL_4:.*]] = hlfir.elemental %[[VAL_3]] : (!fir.shape<1>) -> !hlfir.expr<10x!fir.logical<4>> {
+// CHECK:  ^bb0(%[[VAL_5:.*]]: index):
+// CHECK:    %[[VAL_6:.*]] = hlfir.designate %[[VAL_0]] (%[[VAL_5]])  : (!fir.ref<!fir.array<10xi32>>, index) -> !fir.ref<i32>
+// CHECK:    %[[VAL_7:.*]] = fir.load %[[VAL_6]] : !fir.ref<i32>
+// CHECK:    %[[VAL_8:.*]] = arith.cmpi slt, %[[VAL_7]], %[[VAL_1]] : i32
+// CHECK:    %[[VAL_9:.*]] = fir.convert %[[VAL_8]] : (i1) -> !fir.logical<4>
+// CHECK:    hlfir.yield_element %[[VAL_9]] : !fir.logical<4>
+// CHECK:  }
+// CHECK:  %[[VAL_10:.*]]:3 = hlfir.associate %[[VAL_11:.*]](%[[VAL_3]]) {uniq_name = ".tmp.forall"} : (!hlfir.expr<10x!fir.logical<4>>, !fir.shape<1>) -> (!fir.ref<!fir.array<10x!fir.logical<4>>>, !fir.ref<!fir.array<10x!fir.logical<4>>>, i1)
+// CHECK:  %[[VAL_12:.*]] = hlfir.as_expr %[[VAL_10]]#0 : (!fir.ref<!fir.array<10x!fir.logical<4>>>) -> !hlfir.expr<10x!fir.logical<4>>
+// CHECK:  %[[VAL_13:.*]]:3 = hlfir.associate %[[VAL_12]](%[[VAL_3]]) {uniq_name = "adapt.valuebyref"} : (!hlfir.expr<10x!fir.logical<4>>, !fir.shape<1>) -> (!fir.ref<!fir.array<10x!fir.logical<4>>>, !fir.ref<!fir.array<10x!fir.logical<4>>>, i1)
+// CHECK:  fir.call @logical_array_to_numeric(%[[VAL_0]], %[[VAL_13]]#0) : (!fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10x!fir.logical<4>>>) -> ()
+// CHECK:  hlfir.end_associate %[[VAL_13]]#1, %[[VAL_13]]#2 : !fir.ref<!fir.array<10x!fir.logical<4>>>, i1
+// CHECK:  hlfir.destroy %[[VAL_12]] : !hlfir.expr<10x!fir.logical<4>>
+// CHECK:  hlfir.end_associate %[[VAL_10]]#1, %[[VAL_10]]#2 : !fir.ref<!fir.array<10x!fir.logical<4>>>, i1
+
+func.func @test_scalar_forall_overlap(%i: !fir.ref<!fir.array<10xi32>>) {
+  %c0_i32 = arith.constant 0 : i32
+  %c1 = arith.constant 1 : index
+  %c10 = arith.constant 10 : index
+  %c11 = arith.constant 11 : index
+  hlfir.forall lb {
+    hlfir.yield %c1 : index
+  } ub {
+    hlfir.yield %c10 : index
+  }  (%j: index) {
+    hlfir.region_assign {
+      %reverse_j = arith.subi %c11, %j : index
+      %ielt = hlfir.designate %i (%reverse_j)  : (!fir.ref<!fir.array<10xi32>>, index) -> !fir.ref<i32>
+      %ielt_val = fir.load %ielt : !fir.ref<i32>
+      %smaller = arith.cmpi slt, %ielt_val, %c0_i32 : i32
+      hlfir.yield %smaller : i1
+    } to {
+      %ielt = hlfir.designate %i (%j)  : (!fir.ref<!fir.array<10xi32>>, index) -> !fir.ref<i32>
+      hlfir.yield %ielt : !fir.ref<i32>
+    } user_defined_assign (%arg0: i1) to (%arg1: !fir.ref<i32>) {
+      %cast = fir.convert %arg0 : (i1) -> !fir.logical<4>
+      fir.call @logical_value_to_numeric(%arg1, %cast) : (!fir.ref<i32>, !fir.logical<4>) -> ()
+    }
+  }
+  return
+}
+// CHECK-LABEL:   func.func @test_scalar_forall_overlap(
+// CHECK-SAME:    %[[VAL_0:.*]]: !fir.ref<!fir.array<10xi32>>) {
+// CHECK:  %[[VAL_1:.*]] = fir.alloca index
+// CHECK:  %[[VAL_2:.*]] = arith.constant 0 : i32
+// CHECK:  %[[VAL_3:.*]] = arith.constant 1 : index
+// CHECK:  %[[VAL_4:.*]] = arith.constant 10 : index
+// CHECK:  %[[VAL_5:.*]] = arith.constant 11 : index
+// CHECK:  %[[VAL_6:.*]] = arith.constant 1 : index
+// CHECK:  %[[VAL_7:.*]] = arith.constant 0 : index
+// CHECK:  %[[VAL_8:.*]] = arith.subi %[[VAL_4]], %[[VAL_3]] : index
+// CHECK:  %[[VAL_9:.*]] = arith.addi %[[VAL_8]], %[[VAL_6]] : index
+// CHECK:  %[[VAL_10:.*]] = arith.divsi %[[VAL_9]], %[[VAL_6]] : index
+// CHECK:  %[[VAL_11:.*]] = arith.cmpi sgt, %[[VAL_10]], %[[VAL_7]] : index
+// CHECK:  %[[VAL_12:.*]] = arith.select %[[VAL_11]], %[[VAL_10]], %[[VAL_7]] : index
+// CHECK:  %[[VAL_13:.*]] = arith.constant 1 : index
+// CHECK:  %[[VAL_14:.*]] = arith.constant 1 : index
+// CHECK:  fir.store %[[VAL_13]] to %[[VAL_1]] : !fir.ref<index>
+// CHECK:  %[[VAL_15:.*]] = fir.allocmem !fir.array<?xi1>, %[[VAL_12]] {bindc_name = ".tmp.forall", uniq_name = ""}
+// CHECK:  %[[VAL_16:.*]] = fir.shape %[[VAL_12]] : (index) -> !fir.shape<1>
+// CHECK:  %[[VAL_17:.*]]:2 = hlfir.declare %[[VAL_15]](%[[VAL_16]]) {uniq_name = ".tmp.forall"} : (!fir.heap<!fir.array<?xi1>>, !fir.shape<1>) -> (!fir.box<!fir.array<?xi1>>, !fir.heap<!fir.array<?xi1>>)
+// CHECK:  fir.do_loop %[[VAL_18:.*]] = %[[VAL_3]] to %[[VAL_4]] step %[[VAL_6]] {
+// CHECK:    %[[VAL_19:.*]] = arith.subi %[[VAL_5]], %[[VAL_18]] : index
+// CHECK:    %[[VAL_20:.*]] = hlfir.designate %[[VAL_0]] (%[[VAL_19]])  : (!fir.ref<!fir.array<10xi32>>, index) -> !fir.ref<i32>
+// CHECK:    %[[VAL_21:.*]] = fir.load %[[VAL_20]] : !fir.ref<i32>
+// CHECK:    %[[VAL_22:.*]] = arith.cmpi slt, %[[VAL_21]], %[[VAL_2]] : i32
+// CHECK:    %[[VAL_23:.*]] = fir.load %[[VAL_1]] : !fir.ref<index>
+// CHECK:    %[[VAL_24:.*]] = arith.addi %[[VAL_23]], %[[VAL_14]] : index
+// CHECK:    fir.store %[[VAL_24]] to %[[VAL_1]] : !fir.ref<index>
+// CHECK:    %[[VAL_25:.*]] = hlfir.designate %[[VAL_17]]#0 (%[[VAL_23]])  : (!fir.box<!fir.array<?xi1>>, index) -> !fir.ref<i1>
+// CHECK:    hlfir.assign %[[VAL_22]] to %[[VAL_25]] : i1, !fir.ref<i1>
+// CHECK:  }
+// CHECK:  %[[VAL_26:.*]] = arith.constant 1 : index
+// CHECK:  fir.store %[[VAL_13]] to %[[VAL_1]] : !fir.ref<index>
+// CHECK:  fir.do_loop %[[VAL_27:.*]] = %[[VAL_3]] to %[[VAL_4]] step %[[VAL_26]] {
+// CHECK:    %[[VAL_28:.*]] = fir.load %[[VAL_1]] : !fir.ref<index>
+// CHECK:    %[[VAL_29:.*]] = arith.addi %[[VAL_28]], %[[VAL_14]] : index
+// CHECK:    fir.store %[[VAL_29]] to %[[VAL_1]] : !fir.ref<index>
+// CHECK:    %[[VAL_30:.*]] = hlfir.designate %[[VAL_17]]#0 (%[[VAL_28]])  : (!fir.box<!fir.array<?xi1>>, index) -> !fir.ref<i1>
+// CHECK:    %[[VAL_31:.*]] = fir.load %[[VAL_30]] : !fir.ref<i1>
+// CHECK:    %[[VAL_32:.*]] = hlfir.designate %[[VAL_0]] (%[[VAL_27]])  : (!fir.ref<!fir.array<10xi32>>, index) -> !fir.ref<i32>
+// CHECK:    %[[VAL_33:.*]] = fir.convert %[[VAL_31]] : (i1) -> !fir.logical<4>
+// CHECK:    fir.call @logical_value_to_numeric(%[[VAL_32]], %[[VAL_33]]) : (!fir.ref<i32>, !fir.logical<4>) -> ()
+// CHECK:  }
+// CHECK:  fir.freemem %[[VAL_15]] : !fir.heap<!fir.array<?xi1>>


        


More information about the flang-commits mailing list