[flang-commits] [flang] [flang][hlfir] Add hlfir.minval intrinsic (PR #66306)

via flang-commits flang-commits at lists.llvm.org
Wed Sep 13 17:15:48 PDT 2023


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-flang-fir-hlfir
            
<details>
<summary>Changes</summary>
Adds a new HLFIR operation for the MINVAL intrinsic according to the design set out in flang/docs/HighLevelFIR.md.
--

Patch is 63.70 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/66306.diff

9 Files Affected:

- (modified) flang/include/flang/Optimizer/HLFIR/HLFIROps.td (+27) 
- (modified) flang/lib/Lower/HlfirIntrinsics.cpp (+4) 
- (modified) flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp (+25) 
- (modified) flang/lib/Optimizer/HLFIR/Transforms/LowerHLFIRIntrinsics.cpp (+9-3) 
- (modified) flang/test/HLFIR/invalid.fir (+78) 
- (modified) flang/test/HLFIR/memory-effects.fir (+15) 
- (added) flang/test/HLFIR/minval-lowering.fir (+218) 
- (added) flang/test/HLFIR/minval.fir (+249) 
- (added) flang/test/Lower/HLFIR/minval.f90 (+262) 


<pre>
diff --git a/flang/include/flang/Optimizer/HLFIR/HLFIROps.td b/flang/include/flang/Optimizer/HLFIR/HLFIROps.td
index aef3b1d976f16d9..1f584d6afd8fbcb 100644
--- a/flang/include/flang/Optimizer/HLFIR/HLFIROps.td
+++ b/flang/include/flang/Optimizer/HLFIR/HLFIROps.td
@@ -431,6 +431,33 @@ def hlfir_MaxvalOp : hlfir_Op&lt;&quot;maxval&quot;, [AttrSizedOperandSegments,
   let hasVerifier = 1;
 }
 
+def hlfir_MinvalOp : hlfir_Op&lt;&quot;minval&quot;, [AttrSizedOperandSegments,
+    DeclareOpInterfaceMethods&lt;ArithFastMathInterface&gt;,
+    DeclareOpInterfaceMethods&lt;MemoryEffectsOpInterface&gt;]&gt; {
+  let summary = &quot;MINVAL transformational intrinsic&quot;;
+  let description = [{
+    Minimum value(s) of an array.
+    If DIM is absent, the result is a scalar.
+    If DIM is present, the result is an array of rank n-1, where n is the rank of ARRAY.
+  }];
+
+  let arguments = (ins
+    AnyFortranArrayObject:$array,
+    Optional&lt;AnyIntegerType&gt;:$dim,
+    Optional&lt;AnyFortranLogicalOrI1ArrayObject&gt;:$mask,
+    DefaultValuedAttr&lt;Arith_FastMathAttr,
+                      &quot;::mlir::arith::FastMathFlags::none&quot;&gt;:$fastmath
+  );
+
+  let results = (outs AnyFortranValue);
+
+  let assemblyFormat = [{
+    $array (`dim` $dim^)? (`mask` $mask^)? attr-dict `:` functional-type(operands, results)
+  }];
+
+  let hasVerifier = 1;
+}
+
 def hlfir_ProductOp : hlfir_Op&lt;&quot;product&quot;, [AttrSizedOperandSegments,
     DeclareOpInterfaceMethods&lt;ArithFastMathInterface&gt;,
     DeclareOpInterfaceMethods&lt;MemoryEffectsOpInterface&gt;]&gt; {
diff --git a/flang/lib/Lower/HlfirIntrinsics.cpp b/flang/lib/Lower/HlfirIntrinsics.cpp
index 4d25c59bf79ca6c..62f63e376c815df 100644
--- a/flang/lib/Lower/HlfirIntrinsics.cpp
+++ b/flang/lib/Lower/HlfirIntrinsics.cpp
@@ -89,6 +89,7 @@ class HlfirReductionIntrinsic : public HlfirTransformationalIntrinsic {
 using HlfirSumLowering = HlfirReductionIntrinsic&lt;hlfir::SumOp, true&gt;;
 using HlfirProductLowering = HlfirReductionIntrinsic&lt;hlfir::ProductOp, true&gt;;
 using HlfirMaxvalLowering = HlfirReductionIntrinsic&lt;hlfir::MaxvalOp, true&gt;;
+using HlfirMinvalLowering = HlfirReductionIntrinsic&lt;hlfir::MinvalOp, true&gt;;
 using HlfirAnyLowering = HlfirReductionIntrinsic&lt;hlfir::AnyOp, false&gt;;
 using HlfirAllLowering = HlfirReductionIntrinsic&lt;hlfir::AllOp, false&gt;;
 
@@ -356,6 +357,9 @@ std::optional&lt;hlfir::EntityWithAttributes&gt; Fortran::lower::lowerHlfirIntrinsic(
   if (name == &quot;maxval&quot;)
     return HlfirMaxvalLowering{builder, loc}.lower(loweredActuals, argLowering,
                                                    stmtResultType);
+  if (name == &quot;minval&quot;)
+    return HlfirMinvalLowering{builder, loc}.lower(loweredActuals, argLowering,
+                                                   stmtResultType);
   if (mlir::isa&lt;fir::CharacterType&gt;(stmtResultType)) {
     if (name == &quot;min&quot;)
       return HlfirCharExtremumLowering{builder, loc,
diff --git a/flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp b/flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp
index 531a40c8dd4f920..760f7b343bdc736 100644
--- a/flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp
+++ b/flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp
@@ -845,6 +845,31 @@ void hlfir::MaxvalOp::getEffects(
   getIntrinsicEffects(getOperation(), effects);
 }
 
+//===----------------------------------------------------------------------===//
+// MinvalOp
+//===----------------------------------------------------------------------===//
+
+mlir::LogicalResult hlfir::MinvalOp::verify() {
+  mlir::Operation *op = getOperation();
+
+  auto results = op-&gt;getResultTypes();
+  assert(results.size() == 1);
+
+  auto resultExpr = mlir::dyn_cast&lt;hlfir::ExprType&gt;(results[0]);
+  if (resultExpr &amp;&amp; mlir::isa&lt;fir::CharacterType&gt;(resultExpr.getEleTy())) {
+    return verifyCharacterReductionOp&lt;hlfir::MinvalOp *&gt;(this);
+  } else {
+    return verifyNumericalReductionOp&lt;hlfir::MinvalOp *&gt;(this);
+  }
+}
+
+void hlfir::MinvalOp::getEffects(
+    llvm::SmallVectorImpl&lt;
+        mlir::SideEffects::EffectInstance&lt;mlir::MemoryEffects::Effect&gt;&gt;
+        &amp;effects) {
+  getIntrinsicEffects(getOperation(), effects);
+}
+
 //===----------------------------------------------------------------------===//
 // SetLengthOp
 //===----------------------------------------------------------------------===//
diff --git a/flang/lib/Optimizer/HLFIR/Transforms/LowerHLFIRIntrinsics.cpp b/flang/lib/Optimizer/HLFIR/Transforms/LowerHLFIRIntrinsics.cpp
index b6045fdef0987c0..f2628fcb970bc47 100644
--- a/flang/lib/Optimizer/HLFIR/Transforms/LowerHLFIRIntrinsics.cpp
+++ b/flang/lib/Optimizer/HLFIR/Transforms/LowerHLFIRIntrinsics.cpp
@@ -222,6 +222,8 @@ class HlfirReductionIntrinsicConversion : public HlfirIntrinsicConversion&lt;OP&gt; {
       opName = &quot;product&quot;;
     } else if constexpr (std::is_same_v&lt;OP, hlfir::MaxvalOp&gt;) {
       opName = &quot;maxval&quot;;
+    } else if constexpr (std::is_same_v&lt;OP, hlfir::MinvalOp&gt;) {
+      opName = &quot;minval&quot;;
     } else if constexpr (std::is_same_v&lt;OP, hlfir::AnyOp&gt;) {
       opName = &quot;any&quot;;
     } else if constexpr (std::is_same_v&lt;OP, hlfir::AllOp&gt;) {
@@ -241,7 +243,8 @@ class HlfirReductionIntrinsicConversion : public HlfirIntrinsicConversion&lt;OP&gt; {
 
     if constexpr (std::is_same_v&lt;OP, hlfir::SumOp&gt; ||
                   std::is_same_v&lt;OP, hlfir::ProductOp&gt; ||
-                  std::is_same_v&lt;OP, hlfir::MaxvalOp&gt;) {
+                  std::is_same_v&lt;OP, hlfir::MaxvalOp&gt; ||
+                  std::is_same_v&lt;OP, hlfir::MinvalOp&gt;) {
       args = buildNumericalArgs(operation, i32, logicalType, rewriter, opName);
     } else {
       args = buildLogicalArgs(operation, i32, logicalType, rewriter, opName);
@@ -264,6 +267,8 @@ using ProductOpConversion = HlfirReductionIntrinsicConversion&lt;hlfir::ProductOp&gt;;
 
 using MaxvalOpConversion = HlfirReductionIntrinsicConversion&lt;hlfir::MaxvalOp&gt;;
 
+using MinvalOpConversion = HlfirReductionIntrinsicConversion&lt;hlfir::MinvalOp&gt;;
+
 using AnyOpConversion = HlfirReductionIntrinsicConversion&lt;hlfir::AnyOp&gt;;
 
 using AllOpConversion = HlfirReductionIntrinsicConversion&lt;hlfir::AllOp&gt;;
@@ -440,7 +445,8 @@ class LowerHLFIRIntrinsics
         .insert&lt;MatmulOpConversion, MatmulTransposeOpConversion,
                 AllOpConversion, AnyOpConversion, SumOpConversion,
                 ProductOpConversion, TransposeOpConversion, CountOpConversion,
-                DotProductOpConversion, MaxvalOpConversion&gt;(context);
+                DotProductOpConversion, MaxvalOpConversion, MinvalOpConversion&gt;(
+            context);
     mlir::ConversionTarget target(*context);
     target.addLegalDialect&lt;mlir::BuiltinDialect, mlir::arith::ArithDialect,
                            mlir::func::FuncDialect, fir::FIROpsDialect,
@@ -448,7 +454,7 @@ class LowerHLFIRIntrinsics
     target.addIllegalOp&lt;hlfir::MatmulOp, hlfir::MatmulTransposeOp, hlfir::SumOp,
                         hlfir::ProductOp, hlfir::TransposeOp, hlfir::AnyOp,
                         hlfir::AllOp, hlfir::DotProductOp, hlfir::CountOp,
-                        hlfir::MaxvalOp&gt;();
+                        hlfir::MaxvalOp, hlfir::MinvalOp&gt;();
     target.markUnknownOpDynamicallyLegal(
         [](mlir::Operation *) { return true; });
     if (mlir::failed(
diff --git a/flang/test/HLFIR/invalid.fir b/flang/test/HLFIR/invalid.fir
index 00fe30988439542..112ab4be57f6bfc 100644
--- a/flang/test/HLFIR/invalid.fir
+++ b/flang/test/HLFIR/invalid.fir
@@ -470,6 +470,84 @@ func.func @bad_maxval13(%arg0: !hlfir.expr&lt;?x?x!fir.char&lt;1,?&gt;&gt;, %arg1: i32){
   %0 = hlfir.maxval %arg0 dim %arg1 : (!hlfir.expr&lt;?x?x!fir.char&lt;1,?&gt;&gt;, i32) -&gt; !hlfir.expr&lt;!fir.char&lt;1,?&gt;&gt;
 }
 
+// -----
+func.func @bad_minval1(%arg0: !hlfir.expr&lt;?xi32&gt;, %arg1: i32, %arg2: !fir.box&lt;!fir.logical&lt;4&gt;&gt;) {
+  // expected-error at +1 {{&#x27;hlfir.minval&#x27; op result must have the same element type as ARRAY argument}}
+  %0 = hlfir.minval %arg0 dim %arg1 mask %arg2 : (!hlfir.expr&lt;?xi32&gt;, i32, !fir.box&lt;!fir.logical&lt;4&gt;&gt;) -&gt; f32
+}
+
+// -----
+func.func @bad_minval2(%arg0: !hlfir.expr&lt;?xi32&gt;, %arg1: i32, %arg2: !fir.box&lt;!fir.array&lt;?x?x?x?x?x!fir.logical&lt;4&gt;&gt;&gt;) {
+  // expected-warning at +1 {{MASK must be conformable to ARRAY}}
+  %0 = hlfir.minval %arg0 dim %arg1 mask %arg2 : (!hlfir.expr&lt;?xi32&gt;, i32, !fir.box&lt;!fir.array&lt;?x?x?x?x?x!fir.logical&lt;4&gt;&gt;&gt;) -&gt; !hlfir.expr&lt;i32&gt;
+}
+
+// -----
+func.func @bad_minval3(%arg0: !hlfir.expr&lt;?x5x?xi32&gt;, %arg1: i32, %arg2: !fir.box&lt;!fir.array&lt;2x6x?x!fir.logical&lt;4&gt;&gt;&gt;) {
+  // expected-warning at +1 {{MASK must be conformable to ARRAY}}
+  %0 = hlfir.minval %arg0 dim %arg1 mask %arg2 : (!hlfir.expr&lt;?x5x?xi32&gt;, i32, !fir.box&lt;!fir.array&lt;2x6x?x!fir.logical&lt;4&gt;&gt;&gt;) -&gt; !hlfir.expr&lt;i32&gt;
+}
+
+// -----
+func.func @bad_minval4(%arg0: !hlfir.expr&lt;?x?xi32&gt;, %arg1: i32, %arg2: !fir.box&lt;!fir.logical&lt;4&gt;&gt;) {
+  // expected-error at +1 {{&#x27;hlfir.minval&#x27; op result rank must be one less than ARRAY}}
+  %0 = hlfir.minval %arg0 dim %arg1 mask %arg2 : (!hlfir.expr&lt;?x?xi32&gt;, i32, !fir.box&lt;!fir.logical&lt;4&gt;&gt;) -&gt; !hlfir.expr&lt;?x?xi32&gt;
+}
+
+// -----
+func.func @bad_minval5(%arg0: !hlfir.expr&lt;?xi32&gt;, %arg1: i32, %arg2: !fir.box&lt;!fir.logical&lt;4&gt;&gt;) {
+  // expected-error at +1 {{&#x27;hlfir.minval&#x27; op result must be of numerical scalar type}}
+  %0 = hlfir.minval %arg0 dim %arg1 mask %arg2 : (!hlfir.expr&lt;?xi32&gt;, i32, !fir.box&lt;!fir.logical&lt;4&gt;&gt;) -&gt; !fir.logical&lt;4&gt;
+}
+
+// -----
+func.func @bad_minval6(%arg0: !hlfir.expr&lt;?x?xi32&gt;, %arg1: i32){
+  // expected-error at +1 {{&#x27;hlfir.minval&#x27; op result must be an array}}
+  %0 = hlfir.minval %arg0 dim %arg1 : (!hlfir.expr&lt;?x?xi32&gt;, i32) -&gt; !hlfir.expr&lt;i32&gt;
+}
+
+// -----
+func.func @bad_minval7(%arg0: !hlfir.expr&lt;?xi32&gt;){
+  // expected-error at +1 {{&#x27;hlfir.minval&#x27; op result must be of numerical scalar type}}
+  %0 = hlfir.minval %arg0 : (!hlfir.expr&lt;?xi32&gt;) -&gt; !hlfir.expr&lt;i32&gt;
+}
+
+// -----
+func.func @bad_minval8(%arg0: !hlfir.expr&lt;?x!fir.char&lt;1,?&gt;&gt;, %arg1: i32, %arg2: !fir.box&lt;!fir.logical&lt;4&gt;&gt;) {
+  // expected-error at +1 {{&#x27;hlfir.minval&#x27; op result must have the same element type as ARRAY argument}}
+  %0 = hlfir.minval %arg0 dim %arg1 mask %arg2 : (!hlfir.expr&lt;?x!fir.char&lt;1,?&gt;&gt;, i32, !fir.box&lt;!fir.logical&lt;4&gt;&gt;) -&gt; i32
+}
+
+// -----
+func.func @bad_minval9(%arg0: !hlfir.expr&lt;?x!fir.char&lt;1,?&gt;&gt;, %arg1: i32, %arg2: !fir.box&lt;!fir.array&lt;?x?x?x?x?x!fir.logical&lt;4&gt;&gt;&gt;) {
+  // expected-warning at +1 {{MASK must be conformable to ARRAY}}
+  %0 = hlfir.minval %arg0 dim %arg1 mask %arg2 : (!hlfir.expr&lt;?x!fir.char&lt;1,?&gt;&gt;, i32, !fir.box&lt;!fir.array&lt;?x?x?x?x?x!fir.logical&lt;4&gt;&gt;&gt;) -&gt; !hlfir.expr&lt;!fir.char&lt;1,?&gt;&gt;
+}
+
+// -----
+func.func @bad_minval10(%arg0: !hlfir.expr&lt;?x5x?x!fir.char&lt;1,?&gt;&gt;, %arg1: i32, %arg2: !fir.box&lt;!fir.array&lt;2x6x?x!fir.logical&lt;4&gt;&gt;&gt;) {
+  // expected-warning at +1 {{MASK must be conformable to ARRAY}}
+  %0 = hlfir.minval %arg0 dim %arg1 mask %arg2 : (!hlfir.expr&lt;?x5x?x!fir.char&lt;1,?&gt;&gt;, i32, !fir.box&lt;!fir.array&lt;2x6x?x!fir.logical&lt;4&gt;&gt;&gt;) -&gt; !hlfir.expr&lt;!fir.char&lt;1,?&gt;&gt;
+}
+
+// -----
+func.func @bad_minval11(%arg0: !hlfir.expr&lt;?x?x!fir.char&lt;1,?&gt;&gt;, %arg1: i32, %arg2: !fir.box&lt;!fir.logical&lt;4&gt;&gt;) {
+  // expected-error at +1 {{&#x27;hlfir.minval&#x27; op result rank must be one less than ARRAY}}
+  %0 = hlfir.minval %arg0 dim %arg1 mask %arg2 : (!hlfir.expr&lt;?x?x!fir.char&lt;1,?&gt;&gt;, i32, !fir.box&lt;!fir.logical&lt;4&gt;&gt;) -&gt; !hlfir.expr&lt;?x?x!fir.char&lt;1,?&gt;&gt;
+}
+
+// -----
+func.func @bad_minval12(%arg0: !hlfir.expr&lt;?x!fir.char&lt;1,?&gt;&gt;, %arg1: i32, %arg2: !fir.box&lt;!fir.logical&lt;4&gt;&gt;) {
+  // expected-error at +1 {{&#x27;hlfir.minval&#x27; op result must be scalar character}}
+  %0 = hlfir.minval %arg0 dim %arg1 mask %arg2 : (!hlfir.expr&lt;?x!fir.char&lt;1,?&gt;&gt;, i32, !fir.box&lt;!fir.logical&lt;4&gt;&gt;) -&gt; !hlfir.expr&lt;?x!fir.char&lt;1,?&gt;&gt;
+}
+
+// -----
+func.func @bad_minval13(%arg0: !hlfir.expr&lt;?x?x!fir.char&lt;1,?&gt;&gt;, %arg1: i32){
+  // expected-error at +1 {{&#x27;hlfir.minval&#x27; op result must be an array}}
+  %0 = hlfir.minval %arg0 dim %arg1 : (!hlfir.expr&lt;?x?x!fir.char&lt;1,?&gt;&gt;, i32) -&gt; !hlfir.expr&lt;!fir.char&lt;1,?&gt;&gt;
+}
+
 // -----
 func.func @bad_product1(%arg0: !hlfir.expr&lt;?xi32&gt;, %arg1: i32, %arg2: !fir.box&lt;!fir.logical&lt;4&gt;&gt;) {
   // expected-error at +1 {{&#x27;hlfir.product&#x27; op result must have the same element type as ARRAY argument}}
diff --git a/flang/test/HLFIR/memory-effects.fir b/flang/test/HLFIR/memory-effects.fir
index f30d1b86c4d862a..4b2a0d575db1ac5 100644
--- a/flang/test/HLFIR/memory-effects.fir
+++ b/flang/test/HLFIR/memory-effects.fir
@@ -107,6 +107,21 @@ func.func @maxval_effects(%arg0: !fir.ref&lt;!fir.array&lt;2x2xf32&gt;&gt;, %arg1: i32) {
   return
 }
 
+func.func @minval_no_effects(%arg0: !hlfir.expr&lt;?xf32&gt;) {
+// expected-remark at +1 {{operation has no memory effects}}
+  %minval = hlfir.minval %arg0 : (!hlfir.expr&lt;?xf32&gt;) -&gt; f32
+// expected-remark at +1 {{operation has no memory effects}}
+  return
+}
+
+func.func @minval_effects(%arg0: !fir.ref&lt;!fir.array&lt;2x2xf32&gt;&gt;, %arg1: i32) {
+// expected-remark at +2 {{found an instance of &#x27;allocate&#x27; on a value, on resource &#x27;&lt;Default&gt;&#x27;}}
+// expected-remark at +1 {{found an instance of &#x27;read&#x27; on a value, on resource &#x27;&lt;Default&gt;&#x27;}}
+  %minval = hlfir.minval %arg0 dim %arg1 : (!fir.ref&lt;!fir.array&lt;2x2xf32&gt;&gt;, i32) -&gt; !hlfir.expr&lt;2xf32&gt;
+// expected-remark at +1 {{operation has no memory effects}}
+  return
+}
+
 func.func @dot_product_no_effects(%arg0: !hlfir.expr&lt;?xf32&gt;, %arg1: !hlfir.expr&lt;?xf32&gt;) {
 // expected-remark at +1 {{operation has no memory effects}}
   %0 = hlfir.dot_product %arg0 %arg1 : (!hlfir.expr&lt;?xf32&gt;, !hlfir.expr&lt;?xf32&gt;) -&gt; f32
diff --git a/flang/test/HLFIR/minval-lowering.fir b/flang/test/HLFIR/minval-lowering.fir
new file mode 100644
index 000000000000000..fc8fe92dc08a251
--- /dev/null
+++ b/flang/test/HLFIR/minval-lowering.fir
@@ -0,0 +1,218 @@
+// Test hlfir.minval operation lowering to fir runtime call
+// RUN: fir-opt %s -lower-hlfir-intrinsics | FileCheck %s
+
+// simple one argument minval
+func.func @_QPminval1(%arg0: !fir.box&lt;!fir.array&lt;?xi32&gt;&gt; {fir.bindc_name = &quot;a&quot;}, %arg1: !fir.ref&lt;i32&gt; {fir.bindc_name = &quot;s&quot;}) {
+  %0:2 = hlfir.declare %arg0 {uniq_name = &quot;_QFminval1Ea&quot;} : (!fir.box&lt;!fir.array&lt;?xi32&gt;&gt;) -&gt; (!fir.box&lt;!fir.array&lt;?xi32&gt;&gt;, !fir.box&lt;!fir.array&lt;?xi32&gt;&gt;)
+  %1:2 = hlfir.declare %arg1 {uniq_name = &quot;_QFminval1Es&quot;} : (!fir.ref&lt;i32&gt;) -&gt; (!fir.ref&lt;i32&gt;, !fir.ref&lt;i32&gt;)
+  %2 = hlfir.minval %0#0 {fastmath = #arith.fastmath&lt;contract&gt;} : (!fir.box&lt;!fir.array&lt;?xi32&gt;&gt;) -&gt; i32
+  hlfir.assign %2 to %1#0 : i32, !fir.ref&lt;i32&gt;
+  return
+}
+// CHECK-LABEL: func.func @_QPminval1(
+// CHECK:           %[[ARG0:.*]]: !fir.box&lt;!fir.array&lt;?xi32&gt;&gt;
+// CHECK:           %[[ARG1:.*]]: !fir.ref&lt;i32&gt;
+// CHECK-DAG:     %[[ARRAY:.*]]:2 = hlfir.declare %[[ARG0]]
+// CHECK-DAG:     %[[RES:.*]]:2 = hlfir.declare %[[ARG1]]
+// CHECK-DAG:     %[[MASK:.*]] = fir.absent !fir.box&lt;i1&gt;
+// CHECK-DAG:     %[[ARRAY_ARG:.*]] = fir.convert %[[ARRAY]]#1 : (!fir.box&lt;!fir.array&lt;?xi32&gt;&gt;) -&gt; !fir.box&lt;none&gt;
+// CHECK-DAG:     %[[MASK_ARG:.*]] = fir.convert %[[MASK]] : (!fir.box&lt;i1&gt;) -&gt; !fir.box&lt;none&gt;
+// CHECK:         %[[RET:.*]] = fir.call @_FortranAMinvalInteger4(%[[ARRAY_ARG]], %[[LOC_STR:.*]], %[[LOC_N:.*]], %[[INT:.*]], %[[MASK_ARG]]) fastmath&lt;contract&gt; : (!fir.box&lt;none&gt;, !fir.ref&lt;i8&gt;, i32, i32, !fir.box&lt;none&gt;) -&gt; i32
+// CHECK-NEXT:    hlfir.assign %[[RET]] to %[[RES]]#0 : i32, !fir.ref&lt;i32&gt;
+// CHECK-NEXT:    return
+// CHECK-NEXT:  }
+
+// minval with a by-ref dimension of index type
+func.func @_QPminval2(%arg0: !fir.box&lt;!fir.array&lt;?x?xi32&gt;&gt; {fir.bindc_name = &quot;a&quot;}, %arg1: !fir.box&lt;!fir.array&lt;?xi32&gt;&gt; {fir.bindc_name = &quot;s&quot;}, %arg2: !fir.ref&lt;index&gt; {fir.bindc_name = &quot;d&quot;}) {
+  %0:2 = hlfir.declare %arg0 {uniq_name = &quot;_QFminval2Ea&quot;} : (!fir.box&lt;!fir.array&lt;?x?xi32&gt;&gt;) -&gt; (!fir.box&lt;!fir.array&lt;?x?xi32&gt;&gt;, !fir.box&lt;!fir.array&lt;?x?xi32&gt;&gt;)
+  %1:2 = hlfir.declare %arg2 {uniq_name = &quot;_QFminval2Ed&quot;} : (!fir.ref&lt;index&gt;) -&gt; (!fir.ref&lt;index&gt;, !fir.ref&lt;index&gt;)
+  %2:2 = hlfir.declare %arg1 {uniq_name = &quot;_QFminval2Es&quot;} : (!fir.box&lt;!fir.array&lt;?xi32&gt;&gt;) -&gt; (!fir.box&lt;!fir.array&lt;?xi32&gt;&gt;, !fir.box&lt;!fir.array&lt;?xi32&gt;&gt;)
+  %3 = fir.load %1#0 : !fir.ref&lt;index&gt;
+  %4 = hlfir.minval %0#0 dim %3#0 {fastmath = #arith.fastmath&lt;contract&gt;} : (!fir.box&lt;!fir.array&lt;?x?xi32&gt;&gt;, index) -&gt; !hlfir.expr&lt;?xi32&gt;
+  hlfir.assign %4 to %2#0 : !hlfir.expr&lt;?xi32&gt;, !fir.box&lt;!fir.array&lt;?xi32&gt;&gt;
+  hlfir.destroy %4 : !hlfir.expr&lt;?xi32&gt;
+  return
+}
+// CHECK-LABEL: func.func @_QPminval2(
+// CHECK:           %[[ARG0:.*]]: !fir.box&lt;!fir.array&lt;?x?xi32&gt;&gt;
+// CHECK:           %[[ARG1:.*]]: !fir.box&lt;!fir.array&lt;?xi32&gt;&gt;
+// CHECK:           %[[ARG2:.*]]: !fir.ref&lt;index&gt;
+// CHECK-DAG:     %[[ARRAY:.*]]:2 = hlfir.declare %[[ARG0]]
+// CHECK-DAG:     %[[RES:.*]]:2 = hlfir.declare %[[ARG1]]
+// CHECK-DAG:     %[[DIM_VAR:.*]]:2 = hlfir.declare %[[ARG2]]
+
+// CHECK-DAG:     %[[RET_BOX:.*]] = fir.alloca !fir.box&lt;!fir.heap&lt;!fir.array&lt;?xi32&gt;&gt;&gt;
+// CHECK-DAG:     %[[RET_ADDR:.*]] = fir.zero_bits !fir.heap&lt;!fir.array&lt;?xi32&gt;&gt;
+// CHECK-DAG:     %[[C0:.*]] = arith.constant 0 : index
+// CHECK-DAG:     %[[RET_SHAPE:.*]] = fir.shape %[[C0]] : (index) -&gt; !fir.shape&lt;1&gt;
+// CHECK-DAG:     %[[RET_EMBOX:.*]] = fir.embox %[[RET_ADDR]](%[[RET_SHAPE]])
+// CHECK-DAG:     fir.store %[[RET_EMBOX]] to %[[RET_BOX]]
+
+// CHECK-DAG:     %[[MASK:.*]] = fir.absent !fir.box&lt;i1&gt;
+// CHECK-DAG:     %[[DIM_IDX:.*]] = fir.load %[[DIM_VAR]]#0 : !fir.ref&lt;index&gt;
+// CHECK-DAG:     %[[DIM:.*]] = fir.convert %[[DIM_IDX]] : (index) -&gt; i32
+
+// CHECK-DAG:     %[[RET_ARG:.*]] = fir.convert %[[RET_BOX]]
+// CHECK-DAG:     %[[ARRAY_ARG:.*]] = fir.convert %[[ARRAY]]#1 : (!fir.box&lt;!fir.array&lt;?x?xi32&gt;&gt;) -&gt; !fir.box&lt;none&gt;
+// CHECK-DAG:     %[[MASK_ARG:.*]] = fir.convert %[[MASK]] : (!fir.box&lt;i1&gt;) -&gt; !fir.box&lt;none&gt;
+// CHECK:         %[[NONE:.*]] = fir.call @_FortranAMinvalDim(%[[RET_ARG]], %[[ARRAY_ARG]], %[[DIM]], %[[LOC_STR:.*]], %[[LOC_N:.*]], %[[MASK_ARG]]) fastmath&lt;contract&gt; : (!fir.ref&lt;!fir.box&lt;none&gt;&gt;, !fir.box&lt;none&gt;, i32, !fir.ref&lt;i8&gt;, i32, !fir.box&lt;none&gt;) -&gt; none
+
+// CHECK:         %[[RET:.*]] = fir.load %[[RET_BOX]]
+// CHECK:         %[[BOX_DIMS:.*]]:3 = fir.box_dims %[[RET]]
+// CHECK-NEXT:    %[[ADDR:.*]] = fir.box_addr %[[RET]]
+// CHECK-NEXT:    %[[SHIFT:.*]] = fir.shape_shift %[[BOX_DIMS]]#0, %[[BOX_DIMS]]#1
+// TODO: fix alias analysis in hlfir.assign bufferization
+// CHECK-N...
<truncated>
</pre>
</details>


https://github.com/llvm/llvm-project/pull/66306


More information about the flang-commits mailing list