[flang-commits] [flang] 9a659fa - [flang] fix MAXVAL(x%array_comp_with_custom_lower_bounds) (#129684)

via flang-commits flang-commits at lists.llvm.org
Tue Mar 4 08:52:08 PST 2025


Author: jeanPerier
Date: 2025-03-04T17:52:05+01:00
New Revision: 9a659fac2f40754dcef273f0ee4bb3352e4a6ee9

URL: https://github.com/llvm/llvm-project/commit/9a659fac2f40754dcef273f0ee4bb3352e4a6ee9
DIFF: https://github.com/llvm/llvm-project/commit/9a659fac2f40754dcef273f0ee4bb3352e4a6ee9.diff

LOG: [flang] fix MAXVAL(x%array_comp_with_custom_lower_bounds) (#129684)

The HLFIR inlining of MAXVAL kicks in at O1 and more when the argument
is an array component reference but the implementation did not account
for the rare cases where the array components have non default lower
bounds.

This patch fixes the issue by using `getElementAt` to compute the
element address.
Rename `indices` to `oneBasedIndices` for more clarity.

Added: 
    

Modified: 
    flang/lib/Optimizer/HLFIR/Transforms/OptimizedBufferization.cpp
    flang/test/HLFIR/maxval-elemental.fir

Removed: 
    


################################################################################
diff  --git a/flang/lib/Optimizer/HLFIR/Transforms/OptimizedBufferization.cpp b/flang/lib/Optimizer/HLFIR/Transforms/OptimizedBufferization.cpp
index 3d506abbaa454..96a3622f4afee 100644
--- a/flang/lib/Optimizer/HLFIR/Transforms/OptimizedBufferization.cpp
+++ b/flang/lib/Optimizer/HLFIR/Transforms/OptimizedBufferization.cpp
@@ -910,22 +910,25 @@ class ReductionConversion : public mlir::OpRewritePattern<Op> {
     }
 
     auto inlineSource =
-        [elemental, &designate](
-            fir::FirOpBuilder builder, mlir::Location loc,
-            const llvm::SmallVectorImpl<mlir::Value> &indices) -> mlir::Value {
+        [elemental,
+         &designate](fir::FirOpBuilder builder, mlir::Location loc,
+                     const llvm::SmallVectorImpl<mlir::Value> &oneBasedIndices)
+        -> mlir::Value {
       if (elemental) {
         // Inline the elemental and get the value from it.
-        auto yield = inlineElementalOp(loc, builder, elemental, indices);
+        auto yield =
+            inlineElementalOp(loc, builder, elemental, oneBasedIndices);
         auto tmp = yield.getElementValue();
         yield->erase();
         return tmp;
       }
       if (designate) {
-        // Create a designator over designator, then load the reference.
-        auto resEntity = hlfir::Entity{designate.getResult()};
-        auto tmp = builder.create<hlfir::DesignateOp>(
-            loc, getVariableElementType(resEntity), designate, indices);
-        return builder.create<fir::LoadOp>(loc, tmp);
+        // Create a designator over the array designator, then load the
+        // reference.
+        mlir::Value elementAddr = hlfir::getElementAt(
+            loc, builder, hlfir::Entity{designate.getResult()},
+            oneBasedIndices);
+        return builder.create<fir::LoadOp>(loc, elementAddr);
       }
       llvm_unreachable("unsupported type");
     };
@@ -936,38 +939,41 @@ class ReductionConversion : public mlir::OpRewritePattern<Op> {
     GenBodyFn genBodyFn;
     if constexpr (std::is_same_v<Op, hlfir::AnyOp>) {
       init = builder.createIntegerConstant(loc, builder.getI1Type(), 0);
-      genBodyFn =
-          [inlineSource](fir::FirOpBuilder builder, mlir::Location loc,
-                         mlir::Value reduction,
-                         const llvm::SmallVectorImpl<mlir::Value> &indices)
+      genBodyFn = [inlineSource](
+                      fir::FirOpBuilder builder, mlir::Location loc,
+                      mlir::Value reduction,
+                      const llvm::SmallVectorImpl<mlir::Value> &oneBasedIndices)
           -> mlir::Value {
         // Conditionally set the reduction variable.
         mlir::Value cond = builder.create<fir::ConvertOp>(
-            loc, builder.getI1Type(), inlineSource(builder, loc, indices));
+            loc, builder.getI1Type(),
+            inlineSource(builder, loc, oneBasedIndices));
         return builder.create<mlir::arith::OrIOp>(loc, reduction, cond);
       };
     } else if constexpr (std::is_same_v<Op, hlfir::AllOp>) {
       init = builder.createIntegerConstant(loc, builder.getI1Type(), 1);
-      genBodyFn =
-          [inlineSource](fir::FirOpBuilder builder, mlir::Location loc,
-                         mlir::Value reduction,
-                         const llvm::SmallVectorImpl<mlir::Value> &indices)
+      genBodyFn = [inlineSource](
+                      fir::FirOpBuilder builder, mlir::Location loc,
+                      mlir::Value reduction,
+                      const llvm::SmallVectorImpl<mlir::Value> &oneBasedIndices)
           -> mlir::Value {
         // Conditionally set the reduction variable.
         mlir::Value cond = builder.create<fir::ConvertOp>(
-            loc, builder.getI1Type(), inlineSource(builder, loc, indices));
+            loc, builder.getI1Type(),
+            inlineSource(builder, loc, oneBasedIndices));
         return builder.create<mlir::arith::AndIOp>(loc, reduction, cond);
       };
     } else if constexpr (std::is_same_v<Op, hlfir::CountOp>) {
       init = builder.createIntegerConstant(loc, op.getType(), 0);
-      genBodyFn =
-          [inlineSource](fir::FirOpBuilder builder, mlir::Location loc,
-                         mlir::Value reduction,
-                         const llvm::SmallVectorImpl<mlir::Value> &indices)
+      genBodyFn = [inlineSource](
+                      fir::FirOpBuilder builder, mlir::Location loc,
+                      mlir::Value reduction,
+                      const llvm::SmallVectorImpl<mlir::Value> &oneBasedIndices)
           -> mlir::Value {
         // Conditionally add one to the current value
         mlir::Value cond = builder.create<fir::ConvertOp>(
-            loc, builder.getI1Type(), inlineSource(builder, loc, indices));
+            loc, builder.getI1Type(),
+            inlineSource(builder, loc, oneBasedIndices));
         mlir::Value one =
             builder.createIntegerConstant(loc, reduction.getType(), 1);
         mlir::Value add1 =
@@ -984,12 +990,12 @@ class ReductionConversion : public mlir::OpRewritePattern<Op> {
                          std::is_same_v<Op, hlfir::MinvalOp>) {
       bool isMax = std::is_same_v<Op, hlfir::MaxvalOp>;
       init = makeMinMaxInitValGenerator(isMax)(builder, loc, op.getType());
-      genBodyFn = [inlineSource,
-                   isMax](fir::FirOpBuilder builder, mlir::Location loc,
-                          mlir::Value reduction,
-                          const llvm::SmallVectorImpl<mlir::Value> &indices)
+      genBodyFn = [inlineSource, isMax](
+                      fir::FirOpBuilder builder, mlir::Location loc,
+                      mlir::Value reduction,
+                      const llvm::SmallVectorImpl<mlir::Value> &oneBasedIndices)
           -> mlir::Value {
-        mlir::Value val = inlineSource(builder, loc, indices);
+        mlir::Value val = inlineSource(builder, loc, oneBasedIndices);
         mlir::Value cmp =
             generateMinMaxComparison(builder, loc, val, reduction, isMax);
         return builder.create<mlir::arith::SelectOp>(loc, cmp, val, reduction);

diff  --git a/flang/test/HLFIR/maxval-elemental.fir b/flang/test/HLFIR/maxval-elemental.fir
index 9dc028abe8da3..a21b4858412de 100644
--- a/flang/test/HLFIR/maxval-elemental.fir
+++ b/flang/test/HLFIR/maxval-elemental.fir
@@ -93,3 +93,25 @@ func.func @_QPtest_float(%arg0: !fir.box<!fir.array<?xf32>> {fir.bindc_name = "a
 // CHECK-NEXT:    hlfir.assign %[[V6]] to %3#0 : f32, !fir.ref<f32>
 // CHECK-NEXT:    return
 // CHECK-NEXT:  }
+
+// Verify that lower bounds of designator are applied in the indexing inside
+// the generated loop (hlfir.designate takes indices relative to the base lower
+// bounds).
+func.func @component_lower_bounds(%arg0: !fir.ref<!fir.type<sometype{i:!fir.array<10xi32>}>>) -> i32 {
+  %c10 = arith.constant 10 : index
+  %c101 = arith.constant 101 : index
+  %4 = fir.shape_shift %c101, %c10 : (index, index) -> !fir.shapeshift<1>
+  %5 = hlfir.designate %arg0{"i"}   shape %4 : (!fir.ref<!fir.type<sometype{i:!fir.array<10xi32>}>>, !fir.shapeshift<1>) -> !fir.box<!fir.array<10xi32>>
+  %6 = hlfir.maxval %5 : (!fir.box<!fir.array<10xi32>>) -> i32
+  return %6 : i32
+}
+// CHECK-LABEL:   func.func @component_lower_bounds(
+// CHECK:  %[[VAL_1:.*]] = arith.constant 100 : index
+// CHECK:  %[[VAL_2:.*]] = arith.constant 1 : index
+// CHECK:  %[[VAL_4:.*]] = arith.constant 10 : index
+// CHECK:  %[[VAL_5:.*]] = arith.constant 101 : index
+// CHECK:  %[[VAL_6:.*]] = fir.shape_shift %[[VAL_5]], %[[VAL_4]] : (index, index) -> !fir.shapeshift<1>
+// CHECK:  %[[VAL_7:.*]] = hlfir.designate %{{.*}}{"i"}   shape %[[VAL_6]] : (!fir.ref<!fir.type<sometype{i:!fir.array<10xi32>}>>, !fir.shapeshift<1>) -> !fir.box<!fir.array<10xi32>>
+// CHECK:  %[[VAL_8:.*]] = fir.do_loop %[[VAL_9:.*]] = %[[VAL_2]] to %[[VAL_4]] {{.*}}
+// CHECK:    %[[VAL_11:.*]] = arith.addi %[[VAL_9]], %[[VAL_1]] : index
+// CHECK:    hlfir.designate %[[VAL_7]] (%[[VAL_11]])  : (!fir.box<!fir.array<10xi32>>, index) -> !fir.ref<i32>


        


More information about the flang-commits mailing list