[flang-commits] [flang] [flang] Inline max/minval according to -ffp-maxmin-behavior. (PR #185148)

Slava Zakharin via flang-commits flang-commits at lists.llvm.org
Fri Mar 6 19:36:37 PST 2026


https://github.com/vzakhari created https://github.com/llvm/llvm-project/pull/185148

This patch takes into account the option setting when inlining
max/minval intrinsics. It is not an NFC change for Flang, because:
  * Inlining for integer types now uses arith.max/minsi operations.
  * We do not mark the reduction loops as `unordered`
    under `reassoc` FMF. I think this was not quite correct.

Otherwise, the default Legacy setting should produce the same
MLIR as before.


>From 1211262c47d44c18c9dd2076e0ede23d19a3d172 Mon Sep 17 00:00:00 2001
From: Slava Zakharin <szakharin at nvidia.com>
Date: Fri, 6 Mar 2026 17:39:22 -0800
Subject: [PATCH] [flang] Inline max/minval according to -ffp-maxmin-behavior.

This patch takes into account the option setting when inlining
max/minval intrinsics. It is not an NFC change for Flang, because:
  * Inlining for integer types now uses arith.max/minsi operations.
  * We do not mark the reduction loops as `unordered`
    under `reassoc` FMF. I think this was not quite correct.

Otherwise, the default Legacy setting should produce the same
MLIR as before.
---
 flang/include/flang/Optimizer/HLFIR/Passes.h  |   1 +
 flang/include/flang/Optimizer/HLFIR/Passes.td |  17 +-
 .../Transforms/SimplifyHLFIRIntrinsics.cpp    | 196 ++++--
 flang/lib/Optimizer/Passes/Pipelines.cpp      |  10 +-
 .../simplify-hlfir-intrinsics-maxmin.fir      | 557 ++++++++++++++++++
 .../simplify-hlfir-intrinsics-maxval.fir      |  14 +-
 .../simplify-hlfir-intrinsics-minval.fir      |  14 +-
 7 files changed, 755 insertions(+), 54 deletions(-)
 create mode 100644 flang/test/HLFIR/simplify-hlfir-intrinsics-maxmin.fir

diff --git a/flang/include/flang/Optimizer/HLFIR/Passes.h b/flang/include/flang/Optimizer/HLFIR/Passes.h
index 83388d0527e19..2ae1ecd51391e 100644
--- a/flang/include/flang/Optimizer/HLFIR/Passes.h
+++ b/flang/include/flang/Optimizer/HLFIR/Passes.h
@@ -13,6 +13,7 @@
 #ifndef FORTRAN_OPTIMIZER_HLFIR_PASSES_H
 #define FORTRAN_OPTIMIZER_HLFIR_PASSES_H
 
+#include "flang/Support/FPMaxminBehavior.h"
 #include "mlir/Dialect/Func/IR/FuncOps.h"
 #include "mlir/Pass/Pass.h"
 #include "mlir/Pass/PassRegistry.h"
diff --git a/flang/include/flang/Optimizer/HLFIR/Passes.td b/flang/include/flang/Optimizer/HLFIR/Passes.td
index bfff458f7a6c5..dbce6c3c4ebc9 100644
--- a/flang/include/flang/Optimizer/HLFIR/Passes.td
+++ b/flang/include/flang/Optimizer/HLFIR/Passes.td
@@ -58,7 +58,22 @@ def SimplifyHLFIRIntrinsics : Pass<"simplify-hlfir-intrinsics"> {
                         "argument of hlfir.eval_in_mem, which may block "
                         "some existing MLIR transformations (e.g. CSE) "
                         "that otherwise would have been possible across "
-                        "the hlfir.matmul.">];
+                        "the hlfir.matmul.">,
+                 Option<"fpMaxminBehavior", "fp-maxmin-behavior",
+                        "Fortran::common::FPMaxminBehavior",
+                        /*default=*/"Fortran::common::FPMaxminBehavior::Legacy",
+                        "This option defines the FP max/min behavior.",
+                        [{::llvm::cl::values(
+               clEnumValN(Fortran::common::FPMaxminBehavior::Legacy,
+                          "legacy", "cmp+select"),
+               clEnumValN(Fortran::common::FPMaxminBehavior::Portable,
+                          "portable", "same as legacy, except that "
+                          "arith.max/minnumf may be used when nnan "
+                          "and nsz fast math flags are enabled"),
+               clEnumValN(Fortran::common::FPMaxminBehavior::Extremum,
+                          "extremum", "arith.max/minimumf"),
+               clEnumValN(Fortran::common::FPMaxminBehavior::ExtremeNum,
+                          "extremenum", "arith.max/minnumf"))}]>];
 }
 
 def ExpressionSimplification : Pass<"hlfir-expression-simplification"> {
diff --git a/flang/lib/Optimizer/HLFIR/Transforms/SimplifyHLFIRIntrinsics.cpp b/flang/lib/Optimizer/HLFIR/Transforms/SimplifyHLFIRIntrinsics.cpp
index cc396520289d2..f47353dc30f64 100644
--- a/flang/lib/Optimizer/HLFIR/Transforms/SimplifyHLFIRIntrinsics.cpp
+++ b/flang/lib/Optimizer/HLFIR/Transforms/SimplifyHLFIRIntrinsics.cpp
@@ -15,6 +15,7 @@
 #include "flang/Optimizer/Builder/FIRBuilder.h"
 #include "flang/Optimizer/Builder/HLFIRTools.h"
 #include "flang/Optimizer/Builder/IntrinsicCall.h"
+#include "flang/Optimizer/Builder/Todo.h"
 #include "flang/Optimizer/Dialect/FIRDialect.h"
 #include "flang/Optimizer/HLFIR/HLFIRDialect.h"
 #include "flang/Optimizer/HLFIR/HLFIROps.h"
@@ -476,8 +477,10 @@ class MinMaxlocAsElementalConverter : public ReductionAsElementalConverter {
   using Base = ReductionAsElementalConverter;
 
 public:
-  MinMaxlocAsElementalConverter(T op, mlir::PatternRewriter &rewriter)
-      : Base{op.getOperation(), rewriter} {}
+  MinMaxlocAsElementalConverter(
+      T op, mlir::PatternRewriter &rewriter,
+      Fortran::common::FPMaxminBehavior fpMaxminBehavior)
+      : Base{op.getOperation(), rewriter}, fpMaxminBehavior{fpMaxminBehavior} {}
 
 private:
   virtual mlir::Value getSource() const final { return getOp().getArray(); }
@@ -558,6 +561,12 @@ class MinMaxlocAsElementalConverter : public ReductionAsElementalConverter {
   // value to +/-LARGEST; the coordinates are guaranteed to be updated
   // properly for non-empty input without NaNs.
   bool useIsFirst() const { return getMask() && honorNans(); }
+
+  // Specifies the behavior of max/min idiom.
+  // TODO: for consistency, maxloc/minloc should probably take
+  // this control into account, though, we need to define what
+  // this means exactly.
+  [[maybe_unused]] Fortran::common::FPMaxminBehavior fpMaxminBehavior;
 };
 
 template <typename T>
@@ -762,8 +771,10 @@ class MinMaxvalAsElementalConverter
   using Base = NumericReductionAsElementalConverterBase<T>;
 
 public:
-  MinMaxvalAsElementalConverter(T op, mlir::PatternRewriter &rewriter)
-      : Base{op, rewriter} {}
+  MinMaxvalAsElementalConverter(
+      T op, mlir::PatternRewriter &rewriter,
+      Fortran::common::FPMaxminBehavior fpMaxminBehavior)
+      : Base{op, rewriter}, fpMaxminBehavior{fpMaxminBehavior} {}
 
 private:
   virtual mlir::LogicalResult isConvertible() const final {
@@ -771,6 +782,12 @@ class MinMaxvalAsElementalConverter
       return this->rewriter.notifyMatchFailure(
           this->getOp(),
           "CHARACTER type is not supported for MINVAL/MAXVAL inlining");
+    if (auto intType =
+            mlir::dyn_cast<mlir::IntegerType>(this->getSourceElementType()))
+      if (intType.isUnsigned())
+        return this->rewriter.notifyMatchFailure(
+            this->getOp(),
+            "UNSIGNED type is not supported for MINVAL/MAXVAL inlining");
     return mlir::success();
   }
 
@@ -789,16 +806,21 @@ class MinMaxvalAsElementalConverter
     hlfir::Entity elementValue =
         hlfir::loadElementAt(loc, builder, array, oneBasedIndices);
     mlir::Value currentMinMax = getCurrentMinMax(currentValue);
-    mlir::Value cmp =
-        genMinMaxComparison<isMax>(loc, builder, elementValue, currentMinMax);
-    if (useIsFirst())
-      cmp = mlir::arith::OrIOp::create(builder, loc, cmp,
-                                       getIsFirst(currentValue));
-    mlir::Value newMinMax = mlir::arith::SelectOp::create(
-        builder, loc, cmp, elementValue, currentMinMax);
-    result.push_back(newMinMax);
-    if (useIsFirst())
-      result.push_back(builder.createBool(loc, false));
+    if (isUnordered()) {
+      result.push_back(
+          reduceOneElementUnordered(loc, builder, elementValue, currentMinMax));
+    } else {
+      mlir::Value cmp =
+          genMinMaxComparison<isMax>(loc, builder, elementValue, currentMinMax);
+      if (useIsFirst())
+        cmp = mlir::arith::OrIOp::create(builder, loc, cmp,
+                                         getIsFirst(currentValue));
+      mlir::Value newMinMax = mlir::arith::SelectOp::create(
+          builder, loc, cmp, elementValue, currentMinMax);
+      result.push_back(newMinMax);
+      if (useIsFirst())
+        result.push_back(builder.createBool(loc, false));
+    }
     return result;
   }
 
@@ -830,8 +852,8 @@ class MinMaxvalAsElementalConverter
   // Return true iff the input can contain NaNs, and they should be
   // honored, such that all-NaNs input must produce NaN result.
   bool honorNans() const {
-    return !static_cast<bool>(this->getFastMath() &
-                              mlir::arith::FastMathFlags::nnan);
+    return !mlir::arith::bitEnumContainsAny(this->getFastMath(),
+                                            mlir::arith::FastMathFlags::nnan);
   }
 
   // Return true iff we have to use the loop-carried IsFirst predicate.
@@ -839,9 +861,82 @@ class MinMaxvalAsElementalConverter
   // the first elements of the input.
   // If NaNs are not honored, we can initialize the starting MIN/MAX
   // value to +/-LARGEST.
-  bool useIsFirst() const { return this->getMask() && honorNans(); }
+  bool useIsFirst() const {
+    return this->getMask() && honorNans() && !isUnordered();
+  }
+
+  // Return true iff the max/min reduction can be unordered.
+  // This is always true for integer type.
+  // For FP type, this is only true for Extremum and ExtremeNum modes,
+  // and for Portble mode when nnan and nsz are present.
+  // We used to mark the reduction loop unordered when reassoc
+  // FMF was present - it is unclear if it should indeed behave
+  // this way.
+  virtual bool isUnordered() const override {
+    if (mlir::isa<mlir::IntegerType>(this->getSourceElementType()))
+      return true;
+
+    return fpMaxminBehavior == Fortran::common::FPMaxminBehavior::Extremum ||
+           fpMaxminBehavior == Fortran::common::FPMaxminBehavior::ExtremeNum ||
+           (fpMaxminBehavior == Fortran::common::FPMaxminBehavior::Portable &&
+            mlir::arith::bitEnumContainsAll(
+                this->getFastMath(), mlir::arith::FastMathFlags::nnan |
+                                         mlir::arith::FastMathFlags::nsz));
+  }
+
+  // Generate arith.max/minsi, arith.max/minimumf or arith.max/minnumf to reduce
+  // a single element.
+  mlir::Value reduceOneElementUnordered(mlir::Location loc,
+                                        fir::FirOpBuilder &builder,
+                                        mlir::Value elementValue,
+                                        mlir::Value currentMinMax) {
+    assert(!useIsFirst() &&
+           "unordered max/min reduction must not use first predicate");
+
+    if (mlir::isa<fir::CharacterType>(this->getSourceElementType()))
+      TODO(loc, "max/minval with CHARACTER type");
+
+    if (auto intType =
+            mlir::dyn_cast<mlir::IntegerType>(this->getSourceElementType())) {
+      if (intType.isUnsigned())
+        TODO(loc, "max/minval with UNSIGNED type");
+
+      if constexpr (isMax)
+        return mlir::arith::MaxSIOp::create(builder, loc, elementValue,
+                                            currentMinMax);
+      else
+        return mlir::arith::MinSIOp::create(builder, loc, elementValue,
+                                            currentMinMax);
+    }
+
+    if (fpMaxminBehavior == Fortran::common::FPMaxminBehavior::Extremum) {
+      if constexpr (isMax)
+        return mlir::arith::MaximumFOp::create(builder, loc, elementValue,
+                                               currentMinMax);
+      else
+        return mlir::arith::MinimumFOp::create(builder, loc, elementValue,
+                                               currentMinMax);
+    }
+
+    if (fpMaxminBehavior == Fortran::common::FPMaxminBehavior::ExtremeNum ||
+        (fpMaxminBehavior == Fortran::common::FPMaxminBehavior::Portable &&
+         mlir::arith::bitEnumContainsAll(
+             this->getFastMath(), mlir::arith::FastMathFlags::nnan |
+                                      mlir::arith::FastMathFlags::nsz))) {
+      if constexpr (isMax)
+        return mlir::arith::MaxNumFOp::create(builder, loc, elementValue,
+                                              currentMinMax);
+      else
+        return mlir::arith::MinNumFOp::create(builder, loc, elementValue,
+                                              currentMinMax);
+    }
+
+    llvm_unreachable("unhandled unordered max/min reduction");
+  }
 
   std::size_t getNumReductions() const { return useIsFirst() ? 2 : 1; }
+
+  Fortran::common::FPMaxminBehavior fpMaxminBehavior;
 };
 
 template <typename T>
@@ -854,7 +949,8 @@ MinMaxvalAsElementalConverter<T>::genReductionInitValues(
   mlir::Location loc = this->loc;
 
   fir::IfOp ifOp;
-  if (!useIsFirst() && honorNans()) {
+  // Unordered max/min reductions use +/-LARGEST always.
+  if (!useIsFirst() && honorNans() && !isUnordered()) {
     // Check if we can load the value of the first element in the array
     // or its section (for partial reduction).
     assert(!this->getMask() &&
@@ -1292,15 +1388,7 @@ class ReductionConversion : public mlir::OpRewritePattern<Op> {
 
   llvm::LogicalResult
   matchAndRewrite(Op op, mlir::PatternRewriter &rewriter) const override {
-    if constexpr (std::is_same_v<Op, hlfir::MaxlocOp> ||
-                  std::is_same_v<Op, hlfir::MinlocOp>) {
-      MinMaxlocAsElementalConverter<Op> converter(op, rewriter);
-      return converter.convert();
-    } else if constexpr (std::is_same_v<Op, hlfir::MaxvalOp> ||
-                         std::is_same_v<Op, hlfir::MinvalOp>) {
-      MinMaxvalAsElementalConverter<Op> converter(op, rewriter);
-      return converter.convert();
-    } else if constexpr (std::is_same_v<Op, hlfir::CountOp>) {
+    if constexpr (std::is_same_v<Op, hlfir::CountOp>) {
       CountAsElementalConverter converter(op, rewriter);
       return converter.convert();
     } else if constexpr (std::is_same_v<Op, hlfir::AllOp> ||
@@ -1318,6 +1406,40 @@ class ReductionConversion : public mlir::OpRewritePattern<Op> {
   }
 };
 
+/// Convert an operation that is a partial or total max/min reduction
+/// over an array of values into a reduction loop[-nest]
+/// optionally wrapped into hlfir.elemental.
+template <typename Op>
+class ExtremumReductionConversion : public mlir::OpRewritePattern<Op> {
+public:
+  using mlir::OpRewritePattern<Op>::OpRewritePattern;
+
+  ExtremumReductionConversion(
+      mlir::MLIRContext *ctx,
+      Fortran::common::FPMaxminBehavior fpMaxminBehavior =
+          Fortran::common::FPMaxminBehavior::Legacy)
+      : mlir::OpRewritePattern<Op>{ctx}, fpMaxminBehavior{fpMaxminBehavior} {}
+
+  llvm::LogicalResult
+  matchAndRewrite(Op op, mlir::PatternRewriter &rewriter) const override {
+    if constexpr (std::is_same_v<Op, hlfir::MaxlocOp> ||
+                  std::is_same_v<Op, hlfir::MinlocOp>) {
+      MinMaxlocAsElementalConverter<Op> converter(op, rewriter,
+                                                  fpMaxminBehavior);
+      return converter.convert();
+    } else if constexpr (std::is_same_v<Op, hlfir::MaxvalOp> ||
+                         std::is_same_v<Op, hlfir::MinvalOp>) {
+      MinMaxvalAsElementalConverter<Op> converter(op, rewriter,
+                                                  fpMaxminBehavior);
+      return converter.convert();
+    }
+    return rewriter.notifyMatchFailure(op, "unexpected reduction operation");
+  }
+
+private:
+  Fortran::common::FPMaxminBehavior fpMaxminBehavior;
+};
+
 template <typename Op>
 class ArrayShiftConversion : public mlir::OpRewritePattern<Op> {
 public:
@@ -1869,10 +1991,10 @@ class ArrayShiftConversion : public mlir::OpRewritePattern<Op> {
     // For CSHIFT, shiftVal is the normalized shift value that satisfies
     // (SH >= 0 && SH < SIZE(ARRAY,DIM)).
     //
-    auto genDimensionShift = [&](mlir::Location loc, fir::FirOpBuilder &builder,
-                                 mlir::Value shiftVal, mlir::Value boundary,
-                                 bool exposeContiguity,
-                                 mlir::ValueRange oneBasedIndices)
+    auto genDimensionShift =
+        [&](mlir::Location loc, fir::FirOpBuilder &builder,
+            mlir::Value shiftVal, [[maybe_unused]] mlir::Value boundary,
+            bool exposeContiguity, mlir::ValueRange oneBasedIndices)
         -> llvm::SmallVector<mlir::Value, 0> {
       // Create a vector of indices (s(1), ..., s(dim-1), nullptr, s(dim+1),
       // ..., s(n)) so that we can update the dimVal index as needed.
@@ -3210,10 +3332,14 @@ class SimplifyHLFIRIntrinsics
     patterns.insert<ReductionConversion<hlfir::CountOp>>(context);
     patterns.insert<ReductionConversion<hlfir::AnyOp>>(context);
     patterns.insert<ReductionConversion<hlfir::AllOp>>(context);
-    patterns.insert<ReductionConversion<hlfir::MaxlocOp>>(context);
-    patterns.insert<ReductionConversion<hlfir::MinlocOp>>(context);
-    patterns.insert<ReductionConversion<hlfir::MaxvalOp>>(context);
-    patterns.insert<ReductionConversion<hlfir::MinvalOp>>(context);
+    patterns.insert<ExtremumReductionConversion<hlfir::MaxlocOp>>(
+        context, this->fpMaxminBehavior);
+    patterns.insert<ExtremumReductionConversion<hlfir::MinlocOp>>(
+        context, this->fpMaxminBehavior);
+    patterns.insert<ExtremumReductionConversion<hlfir::MaxvalOp>>(
+        context, this->fpMaxminBehavior);
+    patterns.insert<ExtremumReductionConversion<hlfir::MinvalOp>>(
+        context, this->fpMaxminBehavior);
 
     // If forceMatmulAsElemental is false, then hlfir.matmul inlining
     // will introduce hlfir.eval_in_mem operation with new memory side
diff --git a/flang/lib/Optimizer/Passes/Pipelines.cpp b/flang/lib/Optimizer/Passes/Pipelines.cpp
index b6a34e0e5aad5..658077ea2f548 100644
--- a/flang/lib/Optimizer/Passes/Pipelines.cpp
+++ b/flang/lib/Optimizer/Passes/Pipelines.cpp
@@ -267,8 +267,10 @@ void createHLFIRToFIRPassPipeline(mlir::PassManager &pm,
   }
   if (optLevel.isOptimizingForSpeed()) {
     addCanonicalizerPassWithoutRegionSimplification(pm);
-    addNestedPassToAllTopLevelOperations<PassConstructor>(
-        pm, hlfir::createSimplifyHLFIRIntrinsics);
+    addNestedPassToAllTopLevelOperations(pm, [&]() {
+      return hlfir::createSimplifyHLFIRIntrinsics(
+          {/*allowNewSideEffects=*/false, config.fpMaxminBehavior});
+    });
   }
   addNestedPassToAllTopLevelOperations<PassConstructor>(
       pm, hlfir::createInlineElementals);
@@ -277,9 +279,9 @@ void createHLFIRToFIRPassPipeline(mlir::PassManager &pm,
     pm.addPass(mlir::createCSEPass());
     // Run SimplifyHLFIRIntrinsics pass late after CSE,
     // and allow introducing operations with new side effects.
-    addNestedPassToAllTopLevelOperations<PassConstructor>(pm, []() {
+    addNestedPassToAllTopLevelOperations(pm, [&]() {
       return hlfir::createSimplifyHLFIRIntrinsics(
-          {/*allowNewSideEffects=*/true});
+          {/*allowNewSideEffects=*/true, config.fpMaxminBehavior});
     });
     addNestedPassToAllTopLevelOperations<PassConstructor>(
         pm, hlfir::createPropagateFortranVariableAttributes);
diff --git a/flang/test/HLFIR/simplify-hlfir-intrinsics-maxmin.fir b/flang/test/HLFIR/simplify-hlfir-intrinsics-maxmin.fir
new file mode 100644
index 0000000000000..96ffb61c7605d
--- /dev/null
+++ b/flang/test/HLFIR/simplify-hlfir-intrinsics-maxmin.fir
@@ -0,0 +1,557 @@
+// RUN: fir-opt %s --simplify-hlfir-intrinsics=fp-maxmin-behavior=portable --split-input-file | FileCheck %s --check-prefixes=ALL,PORTABLE
+// RUN: fir-opt %s --simplify-hlfir-intrinsics=fp-maxmin-behavior=extremum --split-input-file | FileCheck %s --check-prefixes=ALL,UNORDERED,EXTREMUM
+// RUN: fir-opt %s --simplify-hlfir-intrinsics=fp-maxmin-behavior=extremenum --split-input-file | FileCheck %s --check-prefixes=ALL,UNORDERED,EXTREMENUM
+
+func.func @_QPtest_unmasked_max(%arg0: !fir.ref<f32> {fir.bindc_name = "x"}, %arg1: !fir.ref<!fir.array<100xf32>> {fir.bindc_name = "y"}) {
+  %c100 = arith.constant 100 : index
+  %0 = fir.dummy_scope : !fir.dscope
+  %1:2 = hlfir.declare %arg0 dummy_scope %0 arg 1 {uniq_name = "_QFtest_unmasked_maxEx"} : (!fir.ref<f32>, !fir.dscope) -> (!fir.ref<f32>, !fir.ref<f32>)
+  %2 = fir.shape %c100 : (index) -> !fir.shape<1>
+  %3:2 = hlfir.declare %arg1(%2) dummy_scope %0 arg 2 {uniq_name = "_QFtest_unmasked_maxEy"} : (!fir.ref<!fir.array<100xf32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100xf32>>, !fir.ref<!fir.array<100xf32>>)
+  %4 = hlfir.maxval %3#0 {fastmath = #arith.fastmath<contract>} : (!fir.ref<!fir.array<100xf32>>) -> f32
+  hlfir.assign %4 to %1#0 : f32, !fir.ref<f32>
+  return
+}
+
+// ALL-LABEL:   func.func @_QPtest_unmasked_max(
+// PORTABLE:           %[[CONSTANT_0:.*]] = arith.constant true
+// PORTABLE:           %[[CONSTANT_1:.*]] = arith.constant -3.40282347E+38 : f32
+// PORTABLE:           %[[CONSTANT_2:.*]] = arith.constant 1 : index
+// PORTABLE:           %[[CONSTANT_3:.*]] = arith.constant 100 : index
+// PORTABLE:           %[[IF_0:.*]] = fir.if %[[CONSTANT_0]] -> (f32) {
+// PORTABLE:           } else {
+// PORTABLE:             fir.result %[[CONSTANT_1]] : f32
+// PORTABLE:           }
+// PORTABLE:           %[[DO_LOOP_0:.*]] = fir.do_loop %[[VAL_0:.*]] = %[[CONSTANT_2]] to %[[CONSTANT_3]] step %[[CONSTANT_2]] iter_args(%[[VAL_1:.*]] = %[[IF_0]]) -> (f32) {
+// PORTABLE:             %[[CMPF_0:.*]] = arith.cmpf ogt, %[[LOAD_1:.*]], %[[VAL_1]] fastmath<contract> : f32
+// PORTABLE:             %[[CMPF_1:.*]] = arith.cmpf une, %[[VAL_1]], %[[VAL_1]] fastmath<contract> : f32
+// PORTABLE:             %[[CMPF_2:.*]] = arith.cmpf oeq, %[[LOAD_1]], %[[LOAD_1]] fastmath<contract> : f32
+// PORTABLE:             %[[ANDI_0:.*]] = arith.andi %[[CMPF_1]], %[[CMPF_2]] : i1
+// PORTABLE:             %[[ORI_0:.*]] = arith.ori %[[CMPF_0]], %[[ANDI_0]] : i1
+// PORTABLE:             %[[SELECT_0:.*]] = arith.select %[[ORI_0]], %[[LOAD_1]], %[[VAL_1]] : f32
+
+// UNORDERED:           %[[CONSTANT_0:.*]] = arith.constant 1 : index
+// UNORDERED:           %[[CONSTANT_1:.*]] = arith.constant -3.40282347E+38 : f32
+// UNORDERED:           %[[CONSTANT_2:.*]] = arith.constant 100 : index
+// UNORDERED:           %[[DO_LOOP_0:.*]] = fir.do_loop %[[VAL_0:.*]] = %[[CONSTANT_0]] to %[[CONSTANT_2]] step %[[CONSTANT_0]] unordered iter_args(%[[VAL_1:.*]] = %[[CONSTANT_1]]) -> (f32) {
+// EXTREMUM:            %[[MAXIMUMF_0:.*]] = arith.maximumf %[[LOAD_0:.*]], %[[VAL_1]] fastmath<contract> : f32
+// EXTREMENUM:          %[[MAXNUMF_0:.*]] = arith.maxnumf %[[LOAD_0:.*]], %[[VAL_1]] fastmath<contract> : f32
+
+// -----
+
+func.func @_QPtest_unmasked_max(%arg0: !fir.ref<f32> {fir.bindc_name = "x"}, %arg1: !fir.ref<!fir.array<100xf32>> {fir.bindc_name = "y"}) {
+  %c100 = arith.constant 100 : index
+  %0 = fir.dummy_scope : !fir.dscope
+  %1:2 = hlfir.declare %arg0 dummy_scope %0 arg 1 {uniq_name = "_QFtest_unmasked_maxEx"} : (!fir.ref<f32>, !fir.dscope) -> (!fir.ref<f32>, !fir.ref<f32>)
+  %2 = fir.shape %c100 : (index) -> !fir.shape<1>
+  %3:2 = hlfir.declare %arg1(%2) dummy_scope %0 arg 2 {uniq_name = "_QFtest_unmasked_maxEy"} : (!fir.ref<!fir.array<100xf32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100xf32>>, !fir.ref<!fir.array<100xf32>>)
+  %4 = hlfir.maxval %3#0 {fastmath = #arith.fastmath<nnan>} : (!fir.ref<!fir.array<100xf32>>) -> f32
+  hlfir.assign %4 to %1#0 : f32, !fir.ref<f32>
+  return
+}
+
+// ALL-LABEL:   func.func @_QPtest_unmasked_max(
+// PORTABLE:           %[[CONSTANT_0:.*]] = arith.constant 1 : index
+// PORTABLE:           %[[CONSTANT_1:.*]] = arith.constant -3.40282347E+38 : f32
+// PORTABLE:           %[[CONSTANT_2:.*]] = arith.constant 100 : index
+// PORTABLE:           %[[DO_LOOP_0:.*]] = fir.do_loop %[[VAL_0:.*]] = %[[CONSTANT_0]] to %[[CONSTANT_2]] step %[[CONSTANT_0]] iter_args(%[[VAL_1:.*]] = %[[CONSTANT_1]]) -> (f32) {
+// PORTABLE:             %[[CMPF_0:.*]] = arith.cmpf ogt, %[[LOAD_0:.*]], %[[VAL_1]] fastmath<nnan> : f32
+// PORTABLE:             %[[CMPF_1:.*]] = arith.cmpf une, %[[VAL_1]], %[[VAL_1]] fastmath<nnan> : f32
+// PORTABLE:             %[[CMPF_2:.*]] = arith.cmpf oeq, %[[LOAD_0]], %[[LOAD_0]] fastmath<nnan> : f32
+// PORTABLE:             %[[ANDI_0:.*]] = arith.andi %[[CMPF_1]], %[[CMPF_2]] : i1
+// PORTABLE:             %[[ORI_0:.*]] = arith.ori %[[CMPF_0]], %[[ANDI_0]] : i1
+// PORTABLE:             %[[SELECT_0:.*]] = arith.select %[[ORI_0]], %[[LOAD_0]], %[[VAL_1]] : f32
+
+// UNORDERED:           %[[CONSTANT_0:.*]] = arith.constant 1 : index
+// UNORDERED:           %[[CONSTANT_1:.*]] = arith.constant -3.40282347E+38 : f32
+// UNORDERED:           %[[CONSTANT_2:.*]] = arith.constant 100 : index
+// UNORDERED:           %[[DO_LOOP_0:.*]] = fir.do_loop %[[VAL_0:.*]] = %[[CONSTANT_0]] to %[[CONSTANT_2]] step %[[CONSTANT_0]] unordered iter_args(%[[VAL_1:.*]] = %[[CONSTANT_1]]) -> (f32) {
+// EXTREMUM:            %[[MAXIMUMF_0:.*]] = arith.maximumf %[[LOAD_0:.*]], %[[VAL_1]] fastmath<nnan> : f32
+// EXTREMENUM:          %[[MAXNUMF_0:.*]] = arith.maxnumf %[[LOAD_0:.*]], %[[VAL_1]] fastmath<nnan> : f32
+
+// -----
+
+func.func @_QPtest_unmasked_max(%arg0: !fir.ref<f32> {fir.bindc_name = "x"}, %arg1: !fir.ref<!fir.array<100xf32>> {fir.bindc_name = "y"}) {
+  %c100 = arith.constant 100 : index
+  %0 = fir.dummy_scope : !fir.dscope
+  %1:2 = hlfir.declare %arg0 dummy_scope %0 arg 1 {uniq_name = "_QFtest_unmasked_maxEx"} : (!fir.ref<f32>, !fir.dscope) -> (!fir.ref<f32>, !fir.ref<f32>)
+  %2 = fir.shape %c100 : (index) -> !fir.shape<1>
+  %3:2 = hlfir.declare %arg1(%2) dummy_scope %0 arg 2 {uniq_name = "_QFtest_unmasked_maxEy"} : (!fir.ref<!fir.array<100xf32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100xf32>>, !fir.ref<!fir.array<100xf32>>)
+  %4 = hlfir.maxval %3#0 {fastmath = #arith.fastmath<nsz>} : (!fir.ref<!fir.array<100xf32>>) -> f32
+  hlfir.assign %4 to %1#0 : f32, !fir.ref<f32>
+  return
+}
+
+// ALL-LABEL:   func.func @_QPtest_unmasked_max(
+// PORTABLE:           %[[CONSTANT_0:.*]] = arith.constant true
+// PORTABLE:           %[[CONSTANT_1:.*]] = arith.constant -3.40282347E+38 : f32
+// PORTABLE:           %[[CONSTANT_2:.*]] = arith.constant 1 : index
+// PORTABLE:           %[[CONSTANT_3:.*]] = arith.constant 100 : index
+// PORTABLE:           %[[IF_0:.*]] = fir.if %[[CONSTANT_0]] -> (f32) {
+// PORTABLE:           } else {
+// PORTABLE:             fir.result %[[CONSTANT_1]] : f32
+// PORTABLE:           }
+// PORTABLE:           %[[DO_LOOP_0:.*]] = fir.do_loop %[[VAL_0:.*]] = %[[CONSTANT_2]] to %[[CONSTANT_3]] step %[[CONSTANT_2]] iter_args(%[[VAL_1:.*]] = %[[IF_0]]) -> (f32) {
+// PORTABLE:             %[[CMPF_0:.*]] = arith.cmpf ogt, %[[LOAD_1:.*]], %[[VAL_1]] fastmath<nsz> : f32
+// PORTABLE:             %[[CMPF_1:.*]] = arith.cmpf une, %[[VAL_1]], %[[VAL_1]] fastmath<nsz> : f32
+// PORTABLE:             %[[CMPF_2:.*]] = arith.cmpf oeq, %[[LOAD_1]], %[[LOAD_1]] fastmath<nsz> : f32
+// PORTABLE:             %[[ANDI_0:.*]] = arith.andi %[[CMPF_1]], %[[CMPF_2]] : i1
+// PORTABLE:             %[[ORI_0:.*]] = arith.ori %[[CMPF_0]], %[[ANDI_0]] : i1
+// PORTABLE:             %[[SELECT_0:.*]] = arith.select %[[ORI_0]], %[[LOAD_1]], %[[VAL_1]] : f32
+
+// UNORDERED:           %[[CONSTANT_0:.*]] = arith.constant 1 : index
+// UNORDERED:           %[[CONSTANT_1:.*]] = arith.constant -3.40282347E+38 : f32
+// UNORDERED:           %[[CONSTANT_2:.*]] = arith.constant 100 : index
+// UNORDERED:           %[[DO_LOOP_0:.*]] = fir.do_loop %[[VAL_0:.*]] = %[[CONSTANT_0]] to %[[CONSTANT_2]] step %[[CONSTANT_0]] unordered iter_args(%[[VAL_1:.*]] = %[[CONSTANT_1]]) -> (f32) {
+// EXTREMUM:            %[[MAXIMUMF_0:.*]] = arith.maximumf %[[LOAD_0:.*]], %[[VAL_1]] fastmath<nsz> : f32
+// EXTREMENUM:          %[[MAXNUMF_0:.*]] = arith.maxnumf %[[LOAD_0:.*]], %[[VAL_1]] fastmath<nsz> : f32
+
+// -----
+
+func.func @_QPtest_unmasked_max(%arg0: !fir.ref<f32> {fir.bindc_name = "x"}, %arg1: !fir.ref<!fir.array<100xf32>> {fir.bindc_name = "y"}) {
+  %c100 = arith.constant 100 : index
+  %0 = fir.dummy_scope : !fir.dscope
+  %1:2 = hlfir.declare %arg0 dummy_scope %0 arg 1 {uniq_name = "_QFtest_unmasked_maxEx"} : (!fir.ref<f32>, !fir.dscope) -> (!fir.ref<f32>, !fir.ref<f32>)
+  %2 = fir.shape %c100 : (index) -> !fir.shape<1>
+  %3:2 = hlfir.declare %arg1(%2) dummy_scope %0 arg 2 {uniq_name = "_QFtest_unmasked_maxEy"} : (!fir.ref<!fir.array<100xf32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100xf32>>, !fir.ref<!fir.array<100xf32>>)
+  %4 = hlfir.maxval %3#0 {fastmath = #arith.fastmath<nnan,nsz>} : (!fir.ref<!fir.array<100xf32>>) -> f32
+  hlfir.assign %4 to %1#0 : f32, !fir.ref<f32>
+  return
+}
+
+// ALL-LABEL:   func.func @_QPtest_unmasked_max(
+// PORTABLE:           %[[CONSTANT_0:.*]] = arith.constant 1 : index
+// PORTABLE:           %[[CONSTANT_1:.*]] = arith.constant -3.40282347E+38 : f32
+// PORTABLE:           %[[CONSTANT_2:.*]] = arith.constant 100 : index
+// PORTABLE:           %[[DO_LOOP_0:.*]] = fir.do_loop %[[VAL_0:.*]] = %[[CONSTANT_0]] to %[[CONSTANT_2]] step %[[CONSTANT_0]] unordered iter_args(%[[VAL_1:.*]] = %[[CONSTANT_1]]) -> (f32) {
+// PORTABLE:             %[[MAXNUMF_0:.*]] = arith.maxnumf %[[LOAD_0:.*]], %[[VAL_1]] fastmath<nnan,nsz> : f32
+
+// UNORDERED:           %[[CONSTANT_0:.*]] = arith.constant 1 : index
+// UNORDERED:           %[[CONSTANT_1:.*]] = arith.constant -3.40282347E+38 : f32
+// UNORDERED:           %[[CONSTANT_2:.*]] = arith.constant 100 : index
+// UNORDERED:           %[[DO_LOOP_0:.*]] = fir.do_loop %[[VAL_0:.*]] = %[[CONSTANT_0]] to %[[CONSTANT_2]] step %[[CONSTANT_0]] unordered iter_args(%[[VAL_1:.*]] = %[[CONSTANT_1]]) -> (f32) {
+// EXTREMUM:            %[[MAXIMUMF_0:.*]] = arith.maximumf %[[LOAD_0:.*]], %[[VAL_1]] fastmath<nnan,nsz> : f32
+// EXTREMENUM:          %[[MAXNUMF_0:.*]] = arith.maxnumf %[[LOAD_0:.*]], %[[VAL_1]] fastmath<nnan,nsz> : f32
+
+// -----
+
+func.func @_QPtest_masked_max(%arg0: !fir.ref<f32> {fir.bindc_name = "x"}, %arg1: !fir.ref<!fir.array<100xf32>> {fir.bindc_name = "y"}, %arg2: !fir.ref<!fir.array<100x!fir.logical<4>>> {fir.bindc_name = "l"}) {
+  %c100 = arith.constant 100 : index
+  %0 = fir.dummy_scope : !fir.dscope
+  %1 = fir.shape %c100 : (index) -> !fir.shape<1>
+  %2:2 = hlfir.declare %arg2(%1) dummy_scope %0 arg 3 {uniq_name = "_QFtest_masked_maxEl"} : (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.ref<!fir.array<100x!fir.logical<4>>>)
+  %3:2 = hlfir.declare %arg0 dummy_scope %0 arg 1 {uniq_name = "_QFtest_masked_maxEx"} : (!fir.ref<f32>, !fir.dscope) -> (!fir.ref<f32>, !fir.ref<f32>)
+  %4 = fir.shape %c100 : (index) -> !fir.shape<1>
+  %5:2 = hlfir.declare %arg1(%4) dummy_scope %0 arg 2 {uniq_name = "_QFtest_masked_maxEy"} : (!fir.ref<!fir.array<100xf32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100xf32>>, !fir.ref<!fir.array<100xf32>>)
+  %6 = hlfir.maxval %5#0 mask %2#0 {fastmath = #arith.fastmath<contract>} : (!fir.ref<!fir.array<100xf32>>, !fir.ref<!fir.array<100x!fir.logical<4>>>) -> f32
+  hlfir.assign %6 to %3#0 : f32, !fir.ref<f32>
+  return
+}
+
+// ALL-LABEL:   func.func @_QPtest_masked_max(
+// PORTABLE:           %[[CONSTANT_0:.*]] = arith.constant false
+// PORTABLE:           %[[CONSTANT_1:.*]] = arith.constant 1 : index
+// PORTABLE:           %[[CONSTANT_2:.*]] = arith.constant true
+// PORTABLE:           %[[CONSTANT_3:.*]] = arith.constant -3.40282347E+38 : f32
+// PORTABLE:           %[[CONSTANT_4:.*]] = arith.constant 100 : index
+// PORTABLE:           %[[DO_LOOP_0:.*]]:2 = fir.do_loop %[[VAL_0:.*]] = %[[CONSTANT_1]] to %[[CONSTANT_4]] step %[[CONSTANT_1]] iter_args(%[[VAL_1:.*]] = %[[CONSTANT_3]], %[[VAL_2:.*]] = %[[CONSTANT_2]]) -> (f32, i1) {
+// PORTABLE:             %[[IF_0:.*]]:2 = fir.if %[[CONVERT_0:.*]] -> (f32, i1) {
+// PORTABLE:               %[[CMPF_0:.*]] = arith.cmpf ogt, %[[LOAD_1:.*]], %[[VAL_1]] fastmath<contract> : f32
+// PORTABLE:               %[[CMPF_1:.*]] = arith.cmpf une, %[[VAL_1]], %[[VAL_1]] fastmath<contract> : f32
+// PORTABLE:               %[[CMPF_2:.*]] = arith.cmpf oeq, %[[LOAD_1]], %[[LOAD_1]] fastmath<contract> : f32
+// PORTABLE:               %[[ANDI_0:.*]] = arith.andi %[[CMPF_1]], %[[CMPF_2]] : i1
+// PORTABLE:               %[[ORI_0:.*]] = arith.ori %[[CMPF_0]], %[[ANDI_0]] : i1
+// PORTABLE:               %[[ORI_1:.*]] = arith.ori %[[ORI_0]], %[[VAL_2]] : i1
+// PORTABLE:               %[[SELECT_0:.*]] = arith.select %[[ORI_1]], %[[LOAD_1]], %[[VAL_1]] : f32
+
+// UNORDERED:           %[[CONSTANT_0:.*]] = arith.constant 1 : index
+// UNORDERED:           %[[CONSTANT_1:.*]] = arith.constant -3.40282347E+38 : f32
+// UNORDERED:           %[[CONSTANT_2:.*]] = arith.constant 100 : index
+// UNORDERED:           %[[DO_LOOP_0:.*]] = fir.do_loop %[[VAL_0:.*]] = %[[CONSTANT_0]] to %[[CONSTANT_2]] step %[[CONSTANT_0]] unordered iter_args(%[[VAL_1:.*]] = %[[CONSTANT_1]]) -> (f32) {
+// UNORDERED:             %[[IF_0:.*]] = fir.if %[[CONVERT_0:.*]] -> (f32) {
+// EXTREMUM:                %[[MAXIMUMF_0:.*]] = arith.maximumf %[[LOAD_1:.*]], %[[VAL_1]] fastmath<contract> : f32
+// EXTREMENUM:              %[[MAXNUMF_0:.*]] = arith.maxnumf %[[LOAD_0:.*]], %[[VAL_1]] fastmath<contract> : f32
+
+// -----
+
+func.func @_QPtest_masked_max(%arg0: !fir.ref<f32> {fir.bindc_name = "x"}, %arg1: !fir.ref<!fir.array<100xf32>> {fir.bindc_name = "y"}, %arg2: !fir.ref<!fir.array<100x!fir.logical<4>>> {fir.bindc_name = "l"}) {
+  %c100 = arith.constant 100 : index
+  %0 = fir.dummy_scope : !fir.dscope
+  %1 = fir.shape %c100 : (index) -> !fir.shape<1>
+  %2:2 = hlfir.declare %arg2(%1) dummy_scope %0 arg 3 {uniq_name = "_QFtest_masked_maxEl"} : (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.ref<!fir.array<100x!fir.logical<4>>>)
+  %3:2 = hlfir.declare %arg0 dummy_scope %0 arg 1 {uniq_name = "_QFtest_masked_maxEx"} : (!fir.ref<f32>, !fir.dscope) -> (!fir.ref<f32>, !fir.ref<f32>)
+  %4 = fir.shape %c100 : (index) -> !fir.shape<1>
+  %5:2 = hlfir.declare %arg1(%4) dummy_scope %0 arg 2 {uniq_name = "_QFtest_masked_maxEy"} : (!fir.ref<!fir.array<100xf32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100xf32>>, !fir.ref<!fir.array<100xf32>>)
+  %6 = hlfir.maxval %5#0 mask %2#0 {fastmath = #arith.fastmath<nnan>} : (!fir.ref<!fir.array<100xf32>>, !fir.ref<!fir.array<100x!fir.logical<4>>>) -> f32
+  hlfir.assign %6 to %3#0 : f32, !fir.ref<f32>
+  return
+}
+
+// ALL-LABEL:   func.func @_QPtest_masked_max(
+// PORTABLE:           %[[CONSTANT_0:.*]] = arith.constant 1 : index
+// PORTABLE:           %[[CONSTANT_1:.*]] = arith.constant -3.40282347E+38 : f32
+// PORTABLE:           %[[CONSTANT_2:.*]] = arith.constant 100 : index
+// PORTABLE:           %[[DO_LOOP_0:.*]] = fir.do_loop %[[VAL_0:.*]] = %[[CONSTANT_0]] to %[[CONSTANT_2]] step %[[CONSTANT_0]] iter_args(%[[VAL_1:.*]] = %[[CONSTANT_1]]) -> (f32) {
+// PORTABLE:             %[[IF_0:.*]] = fir.if %[[CONVERT_0:.*]] -> (f32) {
+// PORTABLE:               %[[CMPF_0:.*]] = arith.cmpf ogt, %[[LOAD_1:.*]], %[[VAL_1]] fastmath<nnan> : f32
+// PORTABLE:               %[[CMPF_1:.*]] = arith.cmpf une, %[[VAL_1]], %[[VAL_1]] fastmath<nnan> : f32
+// PORTABLE:               %[[CMPF_2:.*]] = arith.cmpf oeq, %[[LOAD_1]], %[[LOAD_1]] fastmath<nnan> : f32
+// PORTABLE:               %[[ANDI_0:.*]] = arith.andi %[[CMPF_1]], %[[CMPF_2]] : i1
+// PORTABLE:               %[[ORI_0:.*]] = arith.ori %[[CMPF_0]], %[[ANDI_0]] : i1
+// PORTABLE:               %[[SELECT_0:.*]] = arith.select %[[ORI_0]], %[[LOAD_1]], %[[VAL_1]] : f32
+
+// UNORDERED:           %[[CONSTANT_0:.*]] = arith.constant 1 : index
+// UNORDERED:           %[[CONSTANT_1:.*]] = arith.constant -3.40282347E+38 : f32
+// UNORDERED:           %[[CONSTANT_2:.*]] = arith.constant 100 : index
+// UNORDERED:           %[[DO_LOOP_0:.*]] = fir.do_loop %[[VAL_0:.*]] = %[[CONSTANT_0]] to %[[CONSTANT_2]] step %[[CONSTANT_0]] unordered iter_args(%[[VAL_1:.*]] = %[[CONSTANT_1]]) -> (f32) {
+// UNORDERED:             %[[IF_0:.*]] = fir.if %[[CONVERT_0:.*]] -> (f32) {
+// EXTREMUM:                %[[MAXIMUMF_0:.*]] = arith.maximumf %[[LOAD_1:.*]], %[[VAL_1]] fastmath<nnan> : f32
+// EXTREMENUM:              %[[MAXNUMF_0:.*]] = arith.maxnumf %[[LOAD_0:.*]], %[[VAL_1]] fastmath<nnan> : f32
+
+// -----
+
+func.func @_QPtest_masked_max(%arg0: !fir.ref<f32> {fir.bindc_name = "x"}, %arg1: !fir.ref<!fir.array<100xf32>> {fir.bindc_name = "y"}, %arg2: !fir.ref<!fir.array<100x!fir.logical<4>>> {fir.bindc_name = "l"}) {
+  %c100 = arith.constant 100 : index
+  %0 = fir.dummy_scope : !fir.dscope
+  %1 = fir.shape %c100 : (index) -> !fir.shape<1>
+  %2:2 = hlfir.declare %arg2(%1) dummy_scope %0 arg 3 {uniq_name = "_QFtest_masked_maxEl"} : (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.ref<!fir.array<100x!fir.logical<4>>>)
+  %3:2 = hlfir.declare %arg0 dummy_scope %0 arg 1 {uniq_name = "_QFtest_masked_maxEx"} : (!fir.ref<f32>, !fir.dscope) -> (!fir.ref<f32>, !fir.ref<f32>)
+  %4 = fir.shape %c100 : (index) -> !fir.shape<1>
+  %5:2 = hlfir.declare %arg1(%4) dummy_scope %0 arg 2 {uniq_name = "_QFtest_masked_maxEy"} : (!fir.ref<!fir.array<100xf32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100xf32>>, !fir.ref<!fir.array<100xf32>>)
+  %6 = hlfir.maxval %5#0 mask %2#0 {fastmath = #arith.fastmath<nsz>} : (!fir.ref<!fir.array<100xf32>>, !fir.ref<!fir.array<100x!fir.logical<4>>>) -> f32
+  hlfir.assign %6 to %3#0 : f32, !fir.ref<f32>
+  return
+}
+
+// ALL-LABEL:   func.func @_QPtest_masked_max(
+// PORTABLE:           %[[CONSTANT_0:.*]] = arith.constant false
+// PORTABLE:           %[[CONSTANT_1:.*]] = arith.constant 1 : index
+// PORTABLE:           %[[CONSTANT_2:.*]] = arith.constant true
+// PORTABLE:           %[[CONSTANT_3:.*]] = arith.constant -3.40282347E+38 : f32
+// PORTABLE:           %[[CONSTANT_4:.*]] = arith.constant 100 : index
+// PORTABLE:           %[[DO_LOOP_0:.*]]:2 = fir.do_loop %[[VAL_0:.*]] = %[[CONSTANT_1]] to %[[CONSTANT_4]] step %[[CONSTANT_1]] iter_args(%[[VAL_1:.*]] = %[[CONSTANT_3]], %[[VAL_2:.*]] = %[[CONSTANT_2]]) -> (f32, i1) {
+// PORTABLE:             %[[IF_0:.*]]:2 = fir.if %[[CONVERT_0:.*]] -> (f32, i1) {
+// PORTABLE:               %[[CMPF_0:.*]] = arith.cmpf ogt, %[[LOAD_1:.*]], %[[VAL_1]] fastmath<nsz> : f32
+// PORTABLE:               %[[CMPF_1:.*]] = arith.cmpf une, %[[VAL_1]], %[[VAL_1]] fastmath<nsz> : f32
+// PORTABLE:               %[[CMPF_2:.*]] = arith.cmpf oeq, %[[LOAD_1]], %[[LOAD_1]] fastmath<nsz> : f32
+// PORTABLE:               %[[ANDI_0:.*]] = arith.andi %[[CMPF_1]], %[[CMPF_2]] : i1
+// PORTABLE:               %[[ORI_0:.*]] = arith.ori %[[CMPF_0]], %[[ANDI_0]] : i1
+// PORTABLE:               %[[ORI_1:.*]] = arith.ori %[[ORI_0]], %[[VAL_2]] : i1
+// PORTABLE:               %[[SELECT_0:.*]] = arith.select %[[ORI_1]], %[[LOAD_1]], %[[VAL_1]] : f32
+
+// UNORDERED:           %[[CONSTANT_0:.*]] = arith.constant 1 : index
+// UNORDERED:           %[[CONSTANT_1:.*]] = arith.constant -3.40282347E+38 : f32
+// UNORDERED:           %[[CONSTANT_2:.*]] = arith.constant 100 : index
+// UNORDERED:           %[[DO_LOOP_0:.*]] = fir.do_loop %[[VAL_0:.*]] = %[[CONSTANT_0]] to %[[CONSTANT_2]] step %[[CONSTANT_0]] unordered iter_args(%[[VAL_1:.*]] = %[[CONSTANT_1]]) -> (f32) {
+// UNORDERED:             %[[IF_0:.*]] = fir.if %[[CONVERT_0:.*]] -> (f32) {
+// EXTREMUM:                %[[MAXIMUMF_0:.*]] = arith.maximumf %[[LOAD_1:.*]], %[[VAL_1]] fastmath<nsz> : f32
+// EXTREMENUM:              %[[MAXNUMF_0:.*]] = arith.maxnumf %[[LOAD_0:.*]], %[[VAL_1]] fastmath<nsz> : f32
+
+// -----
+
+func.func @_QPtest_masked_max(%arg0: !fir.ref<f32> {fir.bindc_name = "x"}, %arg1: !fir.ref<!fir.array<100xf32>> {fir.bindc_name = "y"}, %arg2: !fir.ref<!fir.array<100x!fir.logical<4>>> {fir.bindc_name = "l"}) {
+  %c100 = arith.constant 100 : index
+  %0 = fir.dummy_scope : !fir.dscope
+  %1 = fir.shape %c100 : (index) -> !fir.shape<1>
+  %2:2 = hlfir.declare %arg2(%1) dummy_scope %0 arg 3 {uniq_name = "_QFtest_masked_maxEl"} : (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.ref<!fir.array<100x!fir.logical<4>>>)
+  %3:2 = hlfir.declare %arg0 dummy_scope %0 arg 1 {uniq_name = "_QFtest_masked_maxEx"} : (!fir.ref<f32>, !fir.dscope) -> (!fir.ref<f32>, !fir.ref<f32>)
+  %4 = fir.shape %c100 : (index) -> !fir.shape<1>
+  %5:2 = hlfir.declare %arg1(%4) dummy_scope %0 arg 2 {uniq_name = "_QFtest_masked_maxEy"} : (!fir.ref<!fir.array<100xf32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100xf32>>, !fir.ref<!fir.array<100xf32>>)
+  %6 = hlfir.maxval %5#0 mask %2#0 {fastmath = #arith.fastmath<nnan,nsz>} : (!fir.ref<!fir.array<100xf32>>, !fir.ref<!fir.array<100x!fir.logical<4>>>) -> f32
+  hlfir.assign %6 to %3#0 : f32, !fir.ref<f32>
+  return
+}
+
+// ALL-LABEL:   func.func @_QPtest_masked_max(
+// PORTABLE:           %[[CONSTANT_0:.*]] = arith.constant 1 : index
+// PORTABLE:           %[[CONSTANT_1:.*]] = arith.constant -3.40282347E+38 : f32
+// PORTABLE:           %[[CONSTANT_2:.*]] = arith.constant 100 : index
+// PORTABLE:           %[[DO_LOOP_0:.*]] = fir.do_loop %[[VAL_0:.*]] = %[[CONSTANT_0]] to %[[CONSTANT_2]] step %[[CONSTANT_0]] unordered iter_args(%[[VAL_1:.*]] = %[[CONSTANT_1]]) -> (f32) {
+// PORTABLE:             %[[IF_0:.*]] = fir.if %[[CONVERT_0:.*]] -> (f32) {
+// PORTABLE:               %[[MAXNUMF_0:.*]] = arith.maxnumf %[[LOAD_1]], %[[VAL_1]] fastmath<nnan,nsz> : f32
+
+// UNORDERED:           %[[CONSTANT_0:.*]] = arith.constant 1 : index
+// UNORDERED:           %[[CONSTANT_1:.*]] = arith.constant -3.40282347E+38 : f32
+// UNORDERED:           %[[CONSTANT_2:.*]] = arith.constant 100 : index
+// UNORDERED:           %[[DO_LOOP_0:.*]] = fir.do_loop %[[VAL_0:.*]] = %[[CONSTANT_0]] to %[[CONSTANT_2]] step %[[CONSTANT_0]] unordered iter_args(%[[VAL_1:.*]] = %[[CONSTANT_1]]) -> (f32) {
+// UNORDERED:             %[[IF_0:.*]] = fir.if %[[CONVERT_0:.*]] -> (f32) {
+// EXTREMUM:                %[[MAXIMUMF_0:.*]] = arith.maximumf %[[LOAD_1:.*]], %[[VAL_1]] fastmath<nnan,nsz> : f32
+// EXTREMENUM:              %[[MAXNUMF_0:.*]] = arith.maxnumf %[[LOAD_0:.*]], %[[VAL_1]] fastmath<nnan,nsz> : f32
+
+// -----
+
+func.func @_QPtest_unmasked_min(%arg0: !fir.ref<f32> {fir.bindc_name = "x"}, %arg1: !fir.ref<!fir.array<100xf32>> {fir.bindc_name = "y"}) {
+  %c100 = arith.constant 100 : index
+  %0 = fir.dummy_scope : !fir.dscope
+  %1:2 = hlfir.declare %arg0 dummy_scope %0 arg 1 {uniq_name = "_QFtest_unmasked_minEx"} : (!fir.ref<f32>, !fir.dscope) -> (!fir.ref<f32>, !fir.ref<f32>)
+  %2 = fir.shape %c100 : (index) -> !fir.shape<1>
+  %3:2 = hlfir.declare %arg1(%2) dummy_scope %0 arg 2 {uniq_name = "_QFtest_unmasked_minEy"} : (!fir.ref<!fir.array<100xf32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100xf32>>, !fir.ref<!fir.array<100xf32>>)
+  %4 = hlfir.minval %3#0 {fastmath = #arith.fastmath<contract>} : (!fir.ref<!fir.array<100xf32>>) -> f32
+  hlfir.assign %4 to %1#0 : f32, !fir.ref<f32>
+  return
+}
+
+// ALL-LABEL:   func.func @_QPtest_unmasked_min(
+// PORTABLE:           %[[CONSTANT_0:.*]] = arith.constant true
+// PORTABLE:           %[[CONSTANT_1:.*]] = arith.constant 3.40282347E+38 : f32
+// PORTABLE:           %[[CONSTANT_2:.*]] = arith.constant 1 : index
+// PORTABLE:           %[[CONSTANT_3:.*]] = arith.constant 100 : index
+// PORTABLE:           %[[IF_0:.*]] = fir.if %[[CONSTANT_0]] -> (f32) {
+// PORTABLE:           } else {
+// PORTABLE:             fir.result %[[CONSTANT_1]] : f32
+// PORTABLE:           }
+// PORTABLE:           %[[DO_LOOP_0:.*]] = fir.do_loop %[[VAL_0:.*]] = %[[CONSTANT_2]] to %[[CONSTANT_3]] step %[[CONSTANT_2]] iter_args(%[[VAL_1:.*]] = %[[IF_0]]) -> (f32) {
+// PORTABLE:             %[[CMPF_0:.*]] = arith.cmpf olt, %[[LOAD_1:.*]], %[[VAL_1]] fastmath<contract> : f32
+// PORTABLE:             %[[CMPF_1:.*]] = arith.cmpf une, %[[VAL_1]], %[[VAL_1]] fastmath<contract> : f32
+// PORTABLE:             %[[CMPF_2:.*]] = arith.cmpf oeq, %[[LOAD_1]], %[[LOAD_1]] fastmath<contract> : f32
+// PORTABLE:             %[[ANDI_0:.*]] = arith.andi %[[CMPF_1]], %[[CMPF_2]] : i1
+// PORTABLE:             %[[ORI_0:.*]] = arith.ori %[[CMPF_0]], %[[ANDI_0]] : i1
+// PORTABLE:             %[[SELECT_0:.*]] = arith.select %[[ORI_0]], %[[LOAD_1]], %[[VAL_1]] : f32
+
+// UNORDERED:           %[[CONSTANT_0:.*]] = arith.constant 1 : index
+// UNORDERED:           %[[CONSTANT_1:.*]] = arith.constant 3.40282347E+38 : f32
+// UNORDERED:           %[[CONSTANT_2:.*]] = arith.constant 100 : index
+// UNORDERED:           %[[DO_LOOP_0:.*]] = fir.do_loop %[[VAL_0:.*]] = %[[CONSTANT_0]] to %[[CONSTANT_2]] step %[[CONSTANT_0]] unordered iter_args(%[[VAL_1:.*]] = %[[CONSTANT_1]]) -> (f32) {
+// EXTREMUM:            %[[MINIMUMF_0:.*]] = arith.minimumf %[[LOAD_0:.*]], %[[VAL_1]] fastmath<contract> : f32
+// EXTREMENUM:          %[[MINNUMF_0:.*]] = arith.minnumf %[[LOAD_0:.*]], %[[VAL_1]] fastmath<contract> : f32
+
+// -----
+
+func.func @_QPtest_unmasked_min(%arg0: !fir.ref<f32> {fir.bindc_name = "x"}, %arg1: !fir.ref<!fir.array<100xf32>> {fir.bindc_name = "y"}) {
+  %c100 = arith.constant 100 : index
+  %0 = fir.dummy_scope : !fir.dscope
+  %1:2 = hlfir.declare %arg0 dummy_scope %0 arg 1 {uniq_name = "_QFtest_unmasked_minEx"} : (!fir.ref<f32>, !fir.dscope) -> (!fir.ref<f32>, !fir.ref<f32>)
+  %2 = fir.shape %c100 : (index) -> !fir.shape<1>
+  %3:2 = hlfir.declare %arg1(%2) dummy_scope %0 arg 2 {uniq_name = "_QFtest_unmasked_minEy"} : (!fir.ref<!fir.array<100xf32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100xf32>>, !fir.ref<!fir.array<100xf32>>)
+  %4 = hlfir.minval %3#0 {fastmath = #arith.fastmath<nnan>} : (!fir.ref<!fir.array<100xf32>>) -> f32
+  hlfir.assign %4 to %1#0 : f32, !fir.ref<f32>
+  return
+}
+
+// ALL-LABEL:   func.func @_QPtest_unmasked_min(
+// PORTABLE:           %[[CONSTANT_0:.*]] = arith.constant 1 : index
+// PORTABLE:           %[[CONSTANT_1:.*]] = arith.constant 3.40282347E+38 : f32
+// PORTABLE:           %[[CONSTANT_2:.*]] = arith.constant 100 : index
+// PORTABLE:           %[[DO_LOOP_0:.*]] = fir.do_loop %[[VAL_0:.*]] = %[[CONSTANT_0]] to %[[CONSTANT_2]] step %[[CONSTANT_0]] iter_args(%[[VAL_1:.*]] = %[[CONSTANT_1]]) -> (f32) {
+// PORTABLE:             %[[CMPF_0:.*]] = arith.cmpf olt, %[[LOAD_0:.*]], %[[VAL_1]] fastmath<nnan> : f32
+// PORTABLE:             %[[CMPF_1:.*]] = arith.cmpf une, %[[VAL_1]], %[[VAL_1]] fastmath<nnan> : f32
+// PORTABLE:             %[[CMPF_2:.*]] = arith.cmpf oeq, %[[LOAD_0]], %[[LOAD_0]] fastmath<nnan> : f32
+// PORTABLE:             %[[ANDI_0:.*]] = arith.andi %[[CMPF_1]], %[[CMPF_2]] : i1
+// PORTABLE:             %[[ORI_0:.*]] = arith.ori %[[CMPF_0]], %[[ANDI_0]] : i1
+// PORTABLE:             %[[SELECT_0:.*]] = arith.select %[[ORI_0]], %[[LOAD_0]], %[[VAL_1]] : f32
+
+// UNORDERED:           %[[CONSTANT_0:.*]] = arith.constant 1 : index
+// UNORDERED:           %[[CONSTANT_1:.*]] = arith.constant 3.40282347E+38 : f32
+// UNORDERED:           %[[CONSTANT_2:.*]] = arith.constant 100 : index
+// UNORDERED:           %[[DO_LOOP_0:.*]] = fir.do_loop %[[VAL_0:.*]] = %[[CONSTANT_0]] to %[[CONSTANT_2]] step %[[CONSTANT_0]] unordered iter_args(%[[VAL_1:.*]] = %[[CONSTANT_1]]) -> (f32) {
+// EXTREMUM:            %[[MINIMUMF_0:.*]] = arith.minimumf %[[LOAD_0:.*]], %[[VAL_1]] fastmath<nnan> : f32
+// EXTREMENUM:          %[[MINNUMF_0:.*]] = arith.minnumf %[[LOAD_0:.*]], %[[VAL_1]] fastmath<nnan> : f32
+
+// -----
+
+func.func @_QPtest_unmasked_min(%arg0: !fir.ref<f32> {fir.bindc_name = "x"}, %arg1: !fir.ref<!fir.array<100xf32>> {fir.bindc_name = "y"}) {
+  %c100 = arith.constant 100 : index
+  %0 = fir.dummy_scope : !fir.dscope
+  %1:2 = hlfir.declare %arg0 dummy_scope %0 arg 1 {uniq_name = "_QFtest_unmasked_minEx"} : (!fir.ref<f32>, !fir.dscope) -> (!fir.ref<f32>, !fir.ref<f32>)
+  %2 = fir.shape %c100 : (index) -> !fir.shape<1>
+  %3:2 = hlfir.declare %arg1(%2) dummy_scope %0 arg 2 {uniq_name = "_QFtest_unmasked_minEy"} : (!fir.ref<!fir.array<100xf32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100xf32>>, !fir.ref<!fir.array<100xf32>>)
+  %4 = hlfir.minval %3#0 {fastmath = #arith.fastmath<nsz>} : (!fir.ref<!fir.array<100xf32>>) -> f32
+  hlfir.assign %4 to %1#0 : f32, !fir.ref<f32>
+  return
+}
+
+// ALL-LABEL:   func.func @_QPtest_unmasked_min(
+// PORTABLE:           %[[CONSTANT_0:.*]] = arith.constant true
+// PORTABLE:           %[[CONSTANT_1:.*]] = arith.constant 3.40282347E+38 : f32
+// PORTABLE:           %[[CONSTANT_2:.*]] = arith.constant 1 : index
+// PORTABLE:           %[[CONSTANT_3:.*]] = arith.constant 100 : index
+// PORTABLE:           %[[IF_0:.*]] = fir.if %[[CONSTANT_0]] -> (f32) {
+// PORTABLE:           } else {
+// PORTABLE:             fir.result %[[CONSTANT_1]] : f32
+// PORTABLE:           }
+// PORTABLE:           %[[DO_LOOP_0:.*]] = fir.do_loop %[[VAL_0:.*]] = %[[CONSTANT_2]] to %[[CONSTANT_3]] step %[[CONSTANT_2]] iter_args(%[[VAL_1:.*]] = %[[IF_0]]) -> (f32) {
+// PORTABLE:             %[[CMPF_0:.*]] = arith.cmpf olt, %[[LOAD_1:.*]], %[[VAL_1]] fastmath<nsz> : f32
+// PORTABLE:             %[[CMPF_1:.*]] = arith.cmpf une, %[[VAL_1]], %[[VAL_1]] fastmath<nsz> : f32
+// PORTABLE:             %[[CMPF_2:.*]] = arith.cmpf oeq, %[[LOAD_1]], %[[LOAD_1]] fastmath<nsz> : f32
+// PORTABLE:             %[[ANDI_0:.*]] = arith.andi %[[CMPF_1]], %[[CMPF_2]] : i1
+// PORTABLE:             %[[ORI_0:.*]] = arith.ori %[[CMPF_0]], %[[ANDI_0]] : i1
+// PORTABLE:             %[[SELECT_0:.*]] = arith.select %[[ORI_0]], %[[LOAD_1]], %[[VAL_1]] : f32
+
+// UNORDERED:           %[[CONSTANT_0:.*]] = arith.constant 1 : index
+// UNORDERED:           %[[CONSTANT_1:.*]] = arith.constant 3.40282347E+38 : f32
+// UNORDERED:           %[[CONSTANT_2:.*]] = arith.constant 100 : index
+// UNORDERED:           %[[DO_LOOP_0:.*]] = fir.do_loop %[[VAL_0:.*]] = %[[CONSTANT_0]] to %[[CONSTANT_2]] step %[[CONSTANT_0]] unordered iter_args(%[[VAL_1:.*]] = %[[CONSTANT_1]]) -> (f32) {
+// EXTREMUM:            %[[MINIMUMF_0:.*]] = arith.minimumf %[[LOAD_0:.*]], %[[VAL_1]] fastmath<nsz> : f32
+// EXTREMENUM:          %[[MINNUMF_0:.*]] = arith.minnumf %[[LOAD_0:.*]], %[[VAL_1]] fastmath<nsz> : f32
+
+// -----
+
+func.func @_QPtest_unmasked_min(%arg0: !fir.ref<f32> {fir.bindc_name = "x"}, %arg1: !fir.ref<!fir.array<100xf32>> {fir.bindc_name = "y"}) {
+  %c100 = arith.constant 100 : index
+  %0 = fir.dummy_scope : !fir.dscope
+  %1:2 = hlfir.declare %arg0 dummy_scope %0 arg 1 {uniq_name = "_QFtest_unmasked_minEx"} : (!fir.ref<f32>, !fir.dscope) -> (!fir.ref<f32>, !fir.ref<f32>)
+  %2 = fir.shape %c100 : (index) -> !fir.shape<1>
+  %3:2 = hlfir.declare %arg1(%2) dummy_scope %0 arg 2 {uniq_name = "_QFtest_unmasked_minEy"} : (!fir.ref<!fir.array<100xf32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100xf32>>, !fir.ref<!fir.array<100xf32>>)
+  %4 = hlfir.minval %3#0 {fastmath = #arith.fastmath<nnan,nsz>} : (!fir.ref<!fir.array<100xf32>>) -> f32
+  hlfir.assign %4 to %1#0 : f32, !fir.ref<f32>
+  return
+}
+
+// ALL-LABEL:   func.func @_QPtest_unmasked_min(
+// PORTABLE:           %[[CONSTANT_0:.*]] = arith.constant 1 : index
+// PORTABLE:           %[[CONSTANT_1:.*]] = arith.constant 3.40282347E+38 : f32
+// PORTABLE:           %[[CONSTANT_2:.*]] = arith.constant 100 : index
+// PORTABLE:           %[[DO_LOOP_0:.*]] = fir.do_loop %[[VAL_0:.*]] = %[[CONSTANT_0]] to %[[CONSTANT_2]] step %[[CONSTANT_0]] unordered iter_args(%[[VAL_1:.*]] = %[[CONSTANT_1]]) -> (f32) {
+// PORTABLE:             %[[MAXNUMF_0:.*]] = arith.minnumf %[[LOAD_0:.*]], %[[VAL_1]] fastmath<nnan,nsz> : f32
+
+// UNORDERED:           %[[CONSTANT_0:.*]] = arith.constant 1 : index
+// UNORDERED:           %[[CONSTANT_1:.*]] = arith.constant 3.40282347E+38 : f32
+// UNORDERED:           %[[CONSTANT_2:.*]] = arith.constant 100 : index
+// UNORDERED:           %[[DO_LOOP_0:.*]] = fir.do_loop %[[VAL_0:.*]] = %[[CONSTANT_0]] to %[[CONSTANT_2]] step %[[CONSTANT_0]] unordered iter_args(%[[VAL_1:.*]] = %[[CONSTANT_1]]) -> (f32) {
+// EXTREMUM:            %[[MINIMUMF_0:.*]] = arith.minimumf %[[LOAD_0:.*]], %[[VAL_1]] fastmath<nnan,nsz> : f32
+// EXTREMENUM:          %[[MINNUMF_0:.*]] = arith.minnumf %[[LOAD_0:.*]], %[[VAL_1]] fastmath<nnan,nsz> : f32
+
+// -----
+
+func.func @_QPtest_masked_min(%arg0: !fir.ref<f32> {fir.bindc_name = "x"}, %arg1: !fir.ref<!fir.array<100xf32>> {fir.bindc_name = "y"}, %arg2: !fir.ref<!fir.array<100x!fir.logical<4>>> {fir.bindc_name = "l"}) {
+  %c100 = arith.constant 100 : index
+  %0 = fir.dummy_scope : !fir.dscope
+  %1 = fir.shape %c100 : (index) -> !fir.shape<1>
+  %2:2 = hlfir.declare %arg2(%1) dummy_scope %0 arg 3 {uniq_name = "_QFtest_masked_minEl"} : (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.ref<!fir.array<100x!fir.logical<4>>>)
+  %3:2 = hlfir.declare %arg0 dummy_scope %0 arg 1 {uniq_name = "_QFtest_masked_minEx"} : (!fir.ref<f32>, !fir.dscope) -> (!fir.ref<f32>, !fir.ref<f32>)
+  %4 = fir.shape %c100 : (index) -> !fir.shape<1>
+  %5:2 = hlfir.declare %arg1(%4) dummy_scope %0 arg 2 {uniq_name = "_QFtest_masked_minEy"} : (!fir.ref<!fir.array<100xf32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100xf32>>, !fir.ref<!fir.array<100xf32>>)
+  %6 = hlfir.minval %5#0 mask %2#0 {fastmath = #arith.fastmath<contract>} : (!fir.ref<!fir.array<100xf32>>, !fir.ref<!fir.array<100x!fir.logical<4>>>) -> f32
+  hlfir.assign %6 to %3#0 : f32, !fir.ref<f32>
+  return
+}
+
+// ALL-LABEL:   func.func @_QPtest_masked_min(
+// PORTABLE:           %[[CONSTANT_0:.*]] = arith.constant false
+// PORTABLE:           %[[CONSTANT_1:.*]] = arith.constant 1 : index
+// PORTABLE:           %[[CONSTANT_2:.*]] = arith.constant true
+// PORTABLE:           %[[CONSTANT_3:.*]] = arith.constant 3.40282347E+38 : f32
+// PORTABLE:           %[[CONSTANT_4:.*]] = arith.constant 100 : index
+// PORTABLE:           %[[DO_LOOP_0:.*]]:2 = fir.do_loop %[[VAL_0:.*]] = %[[CONSTANT_1]] to %[[CONSTANT_4]] step %[[CONSTANT_1]] iter_args(%[[VAL_1:.*]] = %[[CONSTANT_3]], %[[VAL_2:.*]] = %[[CONSTANT_2]]) -> (f32, i1) {
+// PORTABLE:             %[[IF_0:.*]]:2 = fir.if %[[CONVERT_0:.*]] -> (f32, i1) {
+// PORTABLE:               %[[CMPF_0:.*]] = arith.cmpf olt, %[[LOAD_1:.*]], %[[VAL_1]] fastmath<contract> : f32
+// PORTABLE:               %[[CMPF_1:.*]] = arith.cmpf une, %[[VAL_1]], %[[VAL_1]] fastmath<contract> : f32
+// PORTABLE:               %[[CMPF_2:.*]] = arith.cmpf oeq, %[[LOAD_1]], %[[LOAD_1]] fastmath<contract> : f32
+// PORTABLE:               %[[ANDI_0:.*]] = arith.andi %[[CMPF_1]], %[[CMPF_2]] : i1
+// PORTABLE:               %[[ORI_0:.*]] = arith.ori %[[CMPF_0]], %[[ANDI_0]] : i1
+// PORTABLE:               %[[ORI_1:.*]] = arith.ori %[[ORI_0]], %[[VAL_2]] : i1
+// PORTABLE:               %[[SELECT_0:.*]] = arith.select %[[ORI_1]], %[[LOAD_1]], %[[VAL_1]] : f32
+
+// UNORDERED:           %[[CONSTANT_0:.*]] = arith.constant 1 : index
+// UNORDERED:           %[[CONSTANT_1:.*]] = arith.constant 3.40282347E+38 : f32
+// UNORDERED:           %[[CONSTANT_2:.*]] = arith.constant 100 : index
+// UNORDERED:           %[[DO_LOOP_0:.*]] = fir.do_loop %[[VAL_0:.*]] = %[[CONSTANT_0]] to %[[CONSTANT_2]] step %[[CONSTANT_0]] unordered iter_args(%[[VAL_1:.*]] = %[[CONSTANT_1]]) -> (f32) {
+// UNORDERED:             %[[IF_0:.*]] = fir.if %[[CONVERT_0:.*]] -> (f32) {
+// EXTREMUM:                %[[MINIMUMF_0:.*]] = arith.minimumf %[[LOAD_1:.*]], %[[VAL_1]] fastmath<contract> : f32
+// EXTREMENUM:              %[[MINNUMF_0:.*]] = arith.minnumf %[[LOAD_0:.*]], %[[VAL_1]] fastmath<contract> : f32
+
+// -----
+
+func.func @_QPtest_masked_min(%arg0: !fir.ref<f32> {fir.bindc_name = "x"}, %arg1: !fir.ref<!fir.array<100xf32>> {fir.bindc_name = "y"}, %arg2: !fir.ref<!fir.array<100x!fir.logical<4>>> {fir.bindc_name = "l"}) {
+  %c100 = arith.constant 100 : index
+  %0 = fir.dummy_scope : !fir.dscope
+  %1 = fir.shape %c100 : (index) -> !fir.shape<1>
+  %2:2 = hlfir.declare %arg2(%1) dummy_scope %0 arg 3 {uniq_name = "_QFtest_masked_minEl"} : (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.ref<!fir.array<100x!fir.logical<4>>>)
+  %3:2 = hlfir.declare %arg0 dummy_scope %0 arg 1 {uniq_name = "_QFtest_masked_minEx"} : (!fir.ref<f32>, !fir.dscope) -> (!fir.ref<f32>, !fir.ref<f32>)
+  %4 = fir.shape %c100 : (index) -> !fir.shape<1>
+  %5:2 = hlfir.declare %arg1(%4) dummy_scope %0 arg 2 {uniq_name = "_QFtest_masked_minEy"} : (!fir.ref<!fir.array<100xf32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100xf32>>, !fir.ref<!fir.array<100xf32>>)
+  %6 = hlfir.minval %5#0 mask %2#0 {fastmath = #arith.fastmath<nnan>} : (!fir.ref<!fir.array<100xf32>>, !fir.ref<!fir.array<100x!fir.logical<4>>>) -> f32
+  hlfir.assign %6 to %3#0 : f32, !fir.ref<f32>
+  return
+}
+
+// ALL-LABEL:   func.func @_QPtest_masked_min(
+// PORTABLE:           %[[CONSTANT_0:.*]] = arith.constant 1 : index
+// PORTABLE:           %[[CONSTANT_1:.*]] = arith.constant 3.40282347E+38 : f32
+// PORTABLE:           %[[CONSTANT_2:.*]] = arith.constant 100 : index
+// PORTABLE:           %[[DO_LOOP_0:.*]] = fir.do_loop %[[VAL_0:.*]] = %[[CONSTANT_0]] to %[[CONSTANT_2]] step %[[CONSTANT_0]] iter_args(%[[VAL_1:.*]] = %[[CONSTANT_1]]) -> (f32) {
+// PORTABLE:             %[[IF_0:.*]] = fir.if %[[CONVERT_0:.*]] -> (f32) {
+// PORTABLE:               %[[CMPF_0:.*]] = arith.cmpf olt, %[[LOAD_1:.*]], %[[VAL_1]] fastmath<nnan> : f32
+// PORTABLE:               %[[CMPF_1:.*]] = arith.cmpf une, %[[VAL_1]], %[[VAL_1]] fastmath<nnan> : f32
+// PORTABLE:               %[[CMPF_2:.*]] = arith.cmpf oeq, %[[LOAD_1]], %[[LOAD_1]] fastmath<nnan> : f32
+// PORTABLE:               %[[ANDI_0:.*]] = arith.andi %[[CMPF_1]], %[[CMPF_2]] : i1
+// PORTABLE:               %[[ORI_0:.*]] = arith.ori %[[CMPF_0]], %[[ANDI_0]] : i1
+// PORTABLE:               %[[SELECT_0:.*]] = arith.select %[[ORI_0]], %[[LOAD_1]], %[[VAL_1]] : f32
+
+// UNORDERED:           %[[CONSTANT_0:.*]] = arith.constant 1 : index
+// UNORDERED:           %[[CONSTANT_1:.*]] = arith.constant 3.40282347E+38 : f32
+// UNORDERED:           %[[CONSTANT_2:.*]] = arith.constant 100 : index
+// UNORDERED:           %[[DO_LOOP_0:.*]] = fir.do_loop %[[VAL_0:.*]] = %[[CONSTANT_0]] to %[[CONSTANT_2]] step %[[CONSTANT_0]] unordered iter_args(%[[VAL_1:.*]] = %[[CONSTANT_1]]) -> (f32) {
+// UNORDERED:             %[[IF_0:.*]] = fir.if %[[CONVERT_0:.*]] -> (f32) {
+// EXTREMUM:                %[[MINIMUMF_0:.*]] = arith.minimumf %[[LOAD_1:.*]], %[[VAL_1]] fastmath<nnan> : f32
+// EXTREMENUM:              %[[MINNUMF_0:.*]] = arith.minnumf %[[LOAD_0:.*]], %[[VAL_1]] fastmath<nnan> : f32
+
+// -----
+
+func.func @_QPtest_masked_min(%arg0: !fir.ref<f32> {fir.bindc_name = "x"}, %arg1: !fir.ref<!fir.array<100xf32>> {fir.bindc_name = "y"}, %arg2: !fir.ref<!fir.array<100x!fir.logical<4>>> {fir.bindc_name = "l"}) {
+  %c100 = arith.constant 100 : index
+  %0 = fir.dummy_scope : !fir.dscope
+  %1 = fir.shape %c100 : (index) -> !fir.shape<1>
+  %2:2 = hlfir.declare %arg2(%1) dummy_scope %0 arg 3 {uniq_name = "_QFtest_masked_minEl"} : (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.ref<!fir.array<100x!fir.logical<4>>>)
+  %3:2 = hlfir.declare %arg0 dummy_scope %0 arg 1 {uniq_name = "_QFtest_masked_minEx"} : (!fir.ref<f32>, !fir.dscope) -> (!fir.ref<f32>, !fir.ref<f32>)
+  %4 = fir.shape %c100 : (index) -> !fir.shape<1>
+  %5:2 = hlfir.declare %arg1(%4) dummy_scope %0 arg 2 {uniq_name = "_QFtest_masked_minEy"} : (!fir.ref<!fir.array<100xf32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100xf32>>, !fir.ref<!fir.array<100xf32>>)
+  %6 = hlfir.minval %5#0 mask %2#0 {fastmath = #arith.fastmath<nsz>} : (!fir.ref<!fir.array<100xf32>>, !fir.ref<!fir.array<100x!fir.logical<4>>>) -> f32
+  hlfir.assign %6 to %3#0 : f32, !fir.ref<f32>
+  return
+}
+
+// ALL-LABEL:   func.func @_QPtest_masked_min(
+// PORTABLE:           %[[CONSTANT_0:.*]] = arith.constant false
+// PORTABLE:           %[[CONSTANT_1:.*]] = arith.constant 1 : index
+// PORTABLE:           %[[CONSTANT_2:.*]] = arith.constant true
+// PORTABLE:           %[[CONSTANT_3:.*]] = arith.constant 3.40282347E+38 : f32
+// PORTABLE:           %[[CONSTANT_4:.*]] = arith.constant 100 : index
+// PORTABLE:           %[[DO_LOOP_0:.*]]:2 = fir.do_loop %[[VAL_0:.*]] = %[[CONSTANT_1]] to %[[CONSTANT_4]] step %[[CONSTANT_1]] iter_args(%[[VAL_1:.*]] = %[[CONSTANT_3]], %[[VAL_2:.*]] = %[[CONSTANT_2]]) -> (f32, i1) {
+// PORTABLE:             %[[IF_0:.*]]:2 = fir.if %[[CONVERT_0:.*]] -> (f32, i1) {
+// PORTABLE:               %[[CMPF_0:.*]] = arith.cmpf olt, %[[LOAD_1:.*]], %[[VAL_1]] fastmath<nsz> : f32
+// PORTABLE:               %[[CMPF_1:.*]] = arith.cmpf une, %[[VAL_1]], %[[VAL_1]] fastmath<nsz> : f32
+// PORTABLE:               %[[CMPF_2:.*]] = arith.cmpf oeq, %[[LOAD_1]], %[[LOAD_1]] fastmath<nsz> : f32
+// PORTABLE:               %[[ANDI_0:.*]] = arith.andi %[[CMPF_1]], %[[CMPF_2]] : i1
+// PORTABLE:               %[[ORI_0:.*]] = arith.ori %[[CMPF_0]], %[[ANDI_0]] : i1
+// PORTABLE:               %[[ORI_1:.*]] = arith.ori %[[ORI_0]], %[[VAL_2]] : i1
+// PORTABLE:               %[[SELECT_0:.*]] = arith.select %[[ORI_1]], %[[LOAD_1]], %[[VAL_1]] : f32
+
+// UNORDERED:           %[[CONSTANT_0:.*]] = arith.constant 1 : index
+// UNORDERED:           %[[CONSTANT_1:.*]] = arith.constant 3.40282347E+38 : f32
+// UNORDERED:           %[[CONSTANT_2:.*]] = arith.constant 100 : index
+// UNORDERED:           %[[DO_LOOP_0:.*]] = fir.do_loop %[[VAL_0:.*]] = %[[CONSTANT_0]] to %[[CONSTANT_2]] step %[[CONSTANT_0]] unordered iter_args(%[[VAL_1:.*]] = %[[CONSTANT_1]]) -> (f32) {
+// UNORDERED:             %[[IF_0:.*]] = fir.if %[[CONVERT_0:.*]] -> (f32) {
+// EXTREMUM:                %[[MINIMUMF_0:.*]] = arith.minimumf %[[LOAD_1:.*]], %[[VAL_1]] fastmath<nsz> : f32
+// EXTREMENUM:              %[[MINNUMF_0:.*]] = arith.minnumf %[[LOAD_0:.*]], %[[VAL_1]] fastmath<nsz> : f32
+
+// -----
+
+func.func @_QPtest_masked_min(%arg0: !fir.ref<f32> {fir.bindc_name = "x"}, %arg1: !fir.ref<!fir.array<100xf32>> {fir.bindc_name = "y"}, %arg2: !fir.ref<!fir.array<100x!fir.logical<4>>> {fir.bindc_name = "l"}) {
+  %c100 = arith.constant 100 : index
+  %0 = fir.dummy_scope : !fir.dscope
+  %1 = fir.shape %c100 : (index) -> !fir.shape<1>
+  %2:2 = hlfir.declare %arg2(%1) dummy_scope %0 arg 3 {uniq_name = "_QFtest_masked_minEl"} : (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.ref<!fir.array<100x!fir.logical<4>>>)
+  %3:2 = hlfir.declare %arg0 dummy_scope %0 arg 1 {uniq_name = "_QFtest_masked_minEx"} : (!fir.ref<f32>, !fir.dscope) -> (!fir.ref<f32>, !fir.ref<f32>)
+  %4 = fir.shape %c100 : (index) -> !fir.shape<1>
+  %5:2 = hlfir.declare %arg1(%4) dummy_scope %0 arg 2 {uniq_name = "_QFtest_masked_minEy"} : (!fir.ref<!fir.array<100xf32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100xf32>>, !fir.ref<!fir.array<100xf32>>)
+  %6 = hlfir.minval %5#0 mask %2#0 {fastmath = #arith.fastmath<nnan,nsz>} : (!fir.ref<!fir.array<100xf32>>, !fir.ref<!fir.array<100x!fir.logical<4>>>) -> f32
+  hlfir.assign %6 to %3#0 : f32, !fir.ref<f32>
+  return
+}
+
+// ALL-LABEL:   func.func @_QPtest_masked_min(
+// PORTABLE:           %[[CONSTANT_0:.*]] = arith.constant 1 : index
+// PORTABLE:           %[[CONSTANT_1:.*]] = arith.constant 3.40282347E+38 : f32
+// PORTABLE:           %[[CONSTANT_2:.*]] = arith.constant 100 : index
+// PORTABLE:           %[[DO_LOOP_0:.*]] = fir.do_loop %[[VAL_0:.*]] = %[[CONSTANT_0]] to %[[CONSTANT_2]] step %[[CONSTANT_0]] unordered iter_args(%[[VAL_1:.*]] = %[[CONSTANT_1]]) -> (f32) {
+// PORTABLE:             %[[IF_0:.*]] = fir.if %[[CONVERT_0:.*]] -> (f32) {
+// PORTABLE:               %[[MAXNUMF_0:.*]] = arith.minnumf %[[LOAD_1]], %[[VAL_1]] fastmath<nnan,nsz> : f32
+
+// UNORDERED:           %[[CONSTANT_0:.*]] = arith.constant 1 : index
+// UNORDERED:           %[[CONSTANT_1:.*]] = arith.constant 3.40282347E+38 : f32
+// UNORDERED:           %[[CONSTANT_2:.*]] = arith.constant 100 : index
+// UNORDERED:           %[[DO_LOOP_0:.*]] = fir.do_loop %[[VAL_0:.*]] = %[[CONSTANT_0]] to %[[CONSTANT_2]] step %[[CONSTANT_0]] unordered iter_args(%[[VAL_1:.*]] = %[[CONSTANT_1]]) -> (f32) {
+// UNORDERED:             %[[IF_0:.*]] = fir.if %[[CONVERT_0:.*]] -> (f32) {
+// EXTREMUM:                %[[MINIMUMF_0:.*]] = arith.minimumf %[[LOAD_1:.*]], %[[VAL_1]] fastmath<nnan,nsz> : f32
+// EXTREMENUM:              %[[MINNUMF_0:.*]] = arith.minnumf %[[LOAD_0:.*]], %[[VAL_1]] fastmath<nnan,nsz> : f32
diff --git a/flang/test/HLFIR/simplify-hlfir-intrinsics-maxval.fir b/flang/test/HLFIR/simplify-hlfir-intrinsics-maxval.fir
index 87ed365f9de26..3cb7ae7c6b71c 100644
--- a/flang/test/HLFIR/simplify-hlfir-intrinsics-maxval.fir
+++ b/flang/test/HLFIR/simplify-hlfir-intrinsics-maxval.fir
@@ -56,7 +56,7 @@ func.func @test_partial_expr(%input: !hlfir.expr<?x?xf64>, %mask: !hlfir.expr<?x
 // CHECK:           %[[VAL_7:.*]] = fir.shape %[[VAL_6]] : (index) -> !fir.shape<1>
 // CHECK:           %[[VAL_8:.*]] = hlfir.elemental %[[VAL_7]] unordered : (!fir.shape<1>) -> !hlfir.expr<?xf64> {
 // CHECK:           ^bb0(%[[VAL_9:.*]]: index):
-// CHECK:             %[[VAL_10:.*]]:2 = fir.do_loop %[[VAL_11:.*]] = %[[VAL_2]] to %[[VAL_5]] step %[[VAL_2]] unordered iter_args(%[[VAL_12:.*]] = %[[VAL_3]], %[[FIRST:.*]] = %[[TRUE]]) -> (f64, i1) {
+// CHECK:             %[[VAL_10:.*]]:2 = fir.do_loop %[[VAL_11:.*]] = %[[VAL_2]] to %[[VAL_5]] step %[[VAL_2]] iter_args(%[[VAL_12:.*]] = %[[VAL_3]], %[[FIRST:.*]] = %[[TRUE]]) -> (f64, i1) {
 // CHECK:               %[[VAL_13:.*]] = hlfir.apply %[[VAL_1]], %[[VAL_11]], %[[VAL_9]] : (!hlfir.expr<?x?x!fir.logical<4>>, index, index) -> !fir.logical<4>
 // CHECK:               %[[VAL_14:.*]] = fir.convert %[[VAL_13]] : (!fir.logical<4>) -> i1
 // CHECK:               %[[VAL_15:.*]]:2 = fir.if %[[VAL_14]] -> (f64, i1) {
@@ -91,8 +91,8 @@ func.func @test_total_var(%input: !fir.box<!fir.array<?x?xf16>>, %mask: !fir.ref
 // CHECK:           %[[VAL_4:.*]] = arith.constant 0 : index
 // CHECK:           %[[VAL_5:.*]]:3 = fir.box_dims %[[VAL_0]], %[[VAL_4]] : (!fir.box<!fir.array<?x?xf16>>, index) -> (index, index, index)
 // CHECK:           %[[VAL_6:.*]]:3 = fir.box_dims %[[VAL_0]], %[[VAL_3]] : (!fir.box<!fir.array<?x?xf16>>, index) -> (index, index, index)
-// CHECK:           %[[VAL_7:.*]]:2 = fir.do_loop %[[VAL_8:.*]] = %[[VAL_3]] to %[[VAL_6]]#1 step %[[VAL_3]] unordered iter_args(%[[VAL_9:.*]] = %[[VAL_2]], %[[FIRST1:.*]] = %[[TRUE]]) -> (f16, i1) {
-// CHECK:             %[[VAL_10:.*]]:2 = fir.do_loop %[[VAL_11:.*]] = %[[VAL_3]] to %[[VAL_5]]#1 step %[[VAL_3]] unordered iter_args(%[[VAL_12:.*]] = %[[VAL_9]], %[[FIRST2:.*]] = %[[FIRST1]]) -> (f16, i1) {
+// CHECK:           %[[VAL_7:.*]]:2 = fir.do_loop %[[VAL_8:.*]] = %[[VAL_3]] to %[[VAL_6]]#1 step %[[VAL_3]] iter_args(%[[VAL_9:.*]] = %[[VAL_2]], %[[FIRST1:.*]] = %[[TRUE]]) -> (f16, i1) {
+// CHECK:             %[[VAL_10:.*]]:2 = fir.do_loop %[[VAL_11:.*]] = %[[VAL_3]] to %[[VAL_5]]#1 step %[[VAL_3]] iter_args(%[[VAL_12:.*]] = %[[VAL_9]], %[[FIRST2:.*]] = %[[FIRST1]]) -> (f16, i1) {
 // CHECK:               %[[VAL_13:.*]] = hlfir.designate %[[VAL_1]] (%[[VAL_11]], %[[VAL_8]])  : (!fir.ref<!fir.array<2x2x!fir.logical<1>>>, index, index) -> !fir.ref<!fir.logical<1>>
 // CHECK:               %[[VAL_14:.*]] = fir.load %[[VAL_13]] : !fir.ref<!fir.logical<1>>
 // CHECK:               %[[VAL_15:.*]] = fir.convert %[[VAL_14]] : (!fir.logical<1>) -> i1
@@ -142,7 +142,7 @@ func.func @test_partial_var(%input: !fir.box<!fir.array<?x?xf16>>, %mask: !fir.b
 // CHECK:           %[[VAL_9:.*]] = fir.is_present %[[VAL_1]] : (!fir.box<!fir.array<2x2x!fir.logical<1>>>) -> i1
 // CHECK:           %[[VAL_10:.*]] = hlfir.elemental %[[VAL_8]] unordered : (!fir.shape<1>) -> !hlfir.expr<?xf16> {
 // CHECK:           ^bb0(%[[VAL_11:.*]]: index):
-// CHECK:             %[[VAL_12:.*]]:2 = fir.do_loop %[[VAL_13:.*]] = %[[VAL_4]] to %[[VAL_7]]#1 step %[[VAL_4]] unordered iter_args(%[[VAL_14:.*]] = %[[VAL_3]], %[[FIRST:.*]] = %[[TRUE]]) -> (f16, i1) {
+// CHECK:             %[[VAL_12:.*]]:2 = fir.do_loop %[[VAL_13:.*]] = %[[VAL_4]] to %[[VAL_7]]#1 step %[[VAL_4]] iter_args(%[[VAL_14:.*]] = %[[VAL_3]], %[[FIRST:.*]] = %[[TRUE]]) -> (f16, i1) {
 // CHECK:               %[[VAL_15:.*]] = fir.if %[[VAL_9]] -> (!fir.logical<1>) {
 // CHECK:                 %[[VAL_16:.*]]:3 = fir.box_dims %[[VAL_1]], %[[VAL_5]] : (!fir.box<!fir.array<2x2x!fir.logical<1>>>, index) -> (index, index, index)
 // CHECK:                 %[[VAL_17:.*]]:3 = fir.box_dims %[[VAL_1]], %[[VAL_4]] : (!fir.box<!fir.array<2x2x!fir.logical<1>>>, index) -> (index, index, index)
@@ -208,7 +208,7 @@ func.func @test_partial_expr_nomask(%input: !hlfir.expr<?x?xf64>) -> !hlfir.expr
 // CHECK:             } else {
 // CHECK:               fir.result %[[VAL_1]] : f64
 // CHECK:             }
-// CHECK:             %[[VAL_13:.*]] = fir.do_loop %[[VAL_14:.*]] = %[[VAL_2]] to %[[VAL_5]] step %[[VAL_2]] unordered iter_args(%[[VAL_15:.*]] = %[[VAL_11]]) -> (f64) {
+// CHECK:             %[[VAL_13:.*]] = fir.do_loop %[[VAL_14:.*]] = %[[VAL_2]] to %[[VAL_5]] step %[[VAL_2]] iter_args(%[[VAL_15:.*]] = %[[VAL_11]]) -> (f64) {
 // CHECK:               %[[VAL_16:.*]] = hlfir.apply %[[VAL_0]], %[[VAL_14]], %[[VAL_9]] : (!hlfir.expr<?x?xf64>, index, index) -> f64
 // CHECK:               %[[VAL_17:.*]] = arith.cmpf ogt, %[[VAL_16]], %[[VAL_15]] fastmath<reassoc> : f64
 // CHECK:               %[[VAL_18:.*]] = arith.cmpf une, %[[VAL_15]], %[[VAL_15]] fastmath<reassoc> : f64
@@ -246,8 +246,8 @@ func.func @test_total_var_nomask(%input: !fir.box<!fir.array<?x?xf16>>) -> f16 {
 // CHECK:           } else {
 // CHECK:             fir.result %[[VAL_1]] : f16
 // CHECK:           }
-// CHECK:           %[[VAL_14:.*]] = fir.do_loop %[[VAL_15:.*]] = %[[VAL_2]] to %[[VAL_5]]#1 step %[[VAL_2]] unordered iter_args(%[[VAL_16:.*]] = %[[VAL_9]]) -> (f16) {
-// CHECK:             %[[VAL_17:.*]] = fir.do_loop %[[VAL_18:.*]] = %[[VAL_2]] to %[[VAL_4]]#1 step %[[VAL_2]] unordered iter_args(%[[VAL_19:.*]] = %[[VAL_16]]) -> (f16) {
+// CHECK:           %[[VAL_14:.*]] = fir.do_loop %[[VAL_15:.*]] = %[[VAL_2]] to %[[VAL_5]]#1 step %[[VAL_2]] iter_args(%[[VAL_16:.*]] = %[[VAL_9]]) -> (f16) {
+// CHECK:             %[[VAL_17:.*]] = fir.do_loop %[[VAL_18:.*]] = %[[VAL_2]] to %[[VAL_4]]#1 step %[[VAL_2]] iter_args(%[[VAL_19:.*]] = %[[VAL_16]]) -> (f16) {
 // CHECK:               %[[VAL_20:.*]]:3 = fir.box_dims %[[VAL_0]], %[[VAL_3]] : (!fir.box<!fir.array<?x?xf16>>, index) -> (index, index, index)
 // CHECK:               %[[VAL_21:.*]]:3 = fir.box_dims %[[VAL_0]], %[[VAL_2]] : (!fir.box<!fir.array<?x?xf16>>, index) -> (index, index, index)
 // CHECK:               %[[VAL_22:.*]] = arith.subi %[[VAL_20]]#0, %[[VAL_2]] : index
diff --git a/flang/test/HLFIR/simplify-hlfir-intrinsics-minval.fir b/flang/test/HLFIR/simplify-hlfir-intrinsics-minval.fir
index 9ab419893c6f3..be9ce2c94c094 100644
--- a/flang/test/HLFIR/simplify-hlfir-intrinsics-minval.fir
+++ b/flang/test/HLFIR/simplify-hlfir-intrinsics-minval.fir
@@ -56,7 +56,7 @@ func.func @test_partial_expr(%input: !hlfir.expr<?x?xf64>, %mask: !hlfir.expr<?x
 // CHECK:           %[[VAL_7:.*]] = fir.shape %[[VAL_6]] : (index) -> !fir.shape<1>
 // CHECK:           %[[VAL_8:.*]] = hlfir.elemental %[[VAL_7]] unordered : (!fir.shape<1>) -> !hlfir.expr<?xf64> {
 // CHECK:           ^bb0(%[[VAL_9:.*]]: index):
-// CHECK:             %[[VAL_10:.*]]:2 = fir.do_loop %[[VAL_11:.*]] = %[[VAL_2]] to %[[VAL_5]] step %[[VAL_2]] unordered iter_args(%[[VAL_12:.*]] = %[[VAL_3]], %[[FIRST:.*]] = %[[TRUE]]) -> (f64, i1) {
+// CHECK:             %[[VAL_10:.*]]:2 = fir.do_loop %[[VAL_11:.*]] = %[[VAL_2]] to %[[VAL_5]] step %[[VAL_2]] iter_args(%[[VAL_12:.*]] = %[[VAL_3]], %[[FIRST:.*]] = %[[TRUE]]) -> (f64, i1) {
 // CHECK:               %[[VAL_13:.*]] = hlfir.apply %[[VAL_1]], %[[VAL_11]], %[[VAL_9]] : (!hlfir.expr<?x?x!fir.logical<4>>, index, index) -> !fir.logical<4>
 // CHECK:               %[[VAL_14:.*]] = fir.convert %[[VAL_13]] : (!fir.logical<4>) -> i1
 // CHECK:               %[[VAL_15:.*]]:2 = fir.if %[[VAL_14]] -> (f64, i1) {
@@ -91,8 +91,8 @@ func.func @test_total_var(%input: !fir.box<!fir.array<?x?xf16>>, %mask: !fir.ref
 // CHECK:           %[[VAL_4:.*]] = arith.constant 0 : index
 // CHECK:           %[[VAL_5:.*]]:3 = fir.box_dims %[[VAL_0]], %[[VAL_4]] : (!fir.box<!fir.array<?x?xf16>>, index) -> (index, index, index)
 // CHECK:           %[[VAL_6:.*]]:3 = fir.box_dims %[[VAL_0]], %[[VAL_3]] : (!fir.box<!fir.array<?x?xf16>>, index) -> (index, index, index)
-// CHECK:           %[[VAL_7:.*]]:2 = fir.do_loop %[[VAL_8:.*]] = %[[VAL_3]] to %[[VAL_6]]#1 step %[[VAL_3]] unordered iter_args(%[[VAL_9:.*]] = %[[VAL_2]], %[[FIRST1:.*]] = %[[TRUE]]) -> (f16, i1) {
-// CHECK:             %[[VAL_10:.*]]:2 = fir.do_loop %[[VAL_11:.*]] = %[[VAL_3]] to %[[VAL_5]]#1 step %[[VAL_3]] unordered iter_args(%[[VAL_12:.*]] = %[[VAL_9]], %[[FIRST2:.*]] = %[[FIRST1]]) -> (f16, i1) {
+// CHECK:           %[[VAL_7:.*]]:2 = fir.do_loop %[[VAL_8:.*]] = %[[VAL_3]] to %[[VAL_6]]#1 step %[[VAL_3]] iter_args(%[[VAL_9:.*]] = %[[VAL_2]], %[[FIRST1:.*]] = %[[TRUE]]) -> (f16, i1) {
+// CHECK:             %[[VAL_10:.*]]:2 = fir.do_loop %[[VAL_11:.*]] = %[[VAL_3]] to %[[VAL_5]]#1 step %[[VAL_3]] iter_args(%[[VAL_12:.*]] = %[[VAL_9]], %[[FIRST2:.*]] = %[[FIRST1]]) -> (f16, i1) {
 // CHECK:               %[[VAL_13:.*]] = hlfir.designate %[[VAL_1]] (%[[VAL_11]], %[[VAL_8]])  : (!fir.ref<!fir.array<2x2x!fir.logical<1>>>, index, index) -> !fir.ref<!fir.logical<1>>
 // CHECK:               %[[VAL_14:.*]] = fir.load %[[VAL_13]] : !fir.ref<!fir.logical<1>>
 // CHECK:               %[[VAL_15:.*]] = fir.convert %[[VAL_14]] : (!fir.logical<1>) -> i1
@@ -142,7 +142,7 @@ func.func @test_partial_var(%input: !fir.box<!fir.array<?x?xf16>>, %mask: !fir.b
 // CHECK:           %[[VAL_9:.*]] = fir.is_present %[[VAL_1]] : (!fir.box<!fir.array<2x2x!fir.logical<1>>>) -> i1
 // CHECK:           %[[VAL_10:.*]] = hlfir.elemental %[[VAL_8]] unordered : (!fir.shape<1>) -> !hlfir.expr<?xf16> {
 // CHECK:           ^bb0(%[[VAL_11:.*]]: index):
-// CHECK:             %[[VAL_12:.*]]:2 = fir.do_loop %[[VAL_13:.*]] = %[[VAL_4]] to %[[VAL_7]]#1 step %[[VAL_4]] unordered iter_args(%[[VAL_14:.*]] = %[[VAL_3]], %[[FIRST:.*]] = %[[TRUE]]) -> (f16, i1) {
+// CHECK:             %[[VAL_12:.*]]:2 = fir.do_loop %[[VAL_13:.*]] = %[[VAL_4]] to %[[VAL_7]]#1 step %[[VAL_4]] iter_args(%[[VAL_14:.*]] = %[[VAL_3]], %[[FIRST:.*]] = %[[TRUE]]) -> (f16, i1) {
 // CHECK:               %[[VAL_15:.*]] = fir.if %[[VAL_9]] -> (!fir.logical<1>) {
 // CHECK:                 %[[VAL_16:.*]]:3 = fir.box_dims %[[VAL_1]], %[[VAL_5]] : (!fir.box<!fir.array<2x2x!fir.logical<1>>>, index) -> (index, index, index)
 // CHECK:                 %[[VAL_17:.*]]:3 = fir.box_dims %[[VAL_1]], %[[VAL_4]] : (!fir.box<!fir.array<2x2x!fir.logical<1>>>, index) -> (index, index, index)
@@ -208,7 +208,7 @@ func.func @test_partial_expr_nomask(%input: !hlfir.expr<?x?xf64>) -> !hlfir.expr
 // CHECK:             } else {
 // CHECK:               fir.result %[[VAL_1]] : f64
 // CHECK:             }
-// CHECK:             %[[VAL_13:.*]] = fir.do_loop %[[VAL_14:.*]] = %[[VAL_2]] to %[[VAL_5]] step %[[VAL_2]] unordered iter_args(%[[VAL_15:.*]] = %[[VAL_11]]) -> (f64) {
+// CHECK:             %[[VAL_13:.*]] = fir.do_loop %[[VAL_14:.*]] = %[[VAL_2]] to %[[VAL_5]] step %[[VAL_2]] iter_args(%[[VAL_15:.*]] = %[[VAL_11]]) -> (f64) {
 // CHECK:               %[[VAL_16:.*]] = hlfir.apply %[[VAL_0]], %[[VAL_14]], %[[VAL_9]] : (!hlfir.expr<?x?xf64>, index, index) -> f64
 // CHECK:               %[[VAL_17:.*]] = arith.cmpf olt, %[[VAL_16]], %[[VAL_15]] fastmath<reassoc> : f64
 // CHECK:               %[[VAL_18:.*]] = arith.cmpf une, %[[VAL_15]], %[[VAL_15]] fastmath<reassoc> : f64
@@ -246,8 +246,8 @@ func.func @test_total_var_nomask(%input: !fir.box<!fir.array<?x?xf16>>) -> f16 {
 // CHECK:           } else {
 // CHECK:             fir.result %[[VAL_1]] : f16
 // CHECK:           }
-// CHECK:           %[[VAL_14:.*]] = fir.do_loop %[[VAL_15:.*]] = %[[VAL_2]] to %[[VAL_5]]#1 step %[[VAL_2]] unordered iter_args(%[[VAL_16:.*]] = %[[VAL_9]]) -> (f16) {
-// CHECK:             %[[VAL_17:.*]] = fir.do_loop %[[VAL_18:.*]] = %[[VAL_2]] to %[[VAL_4]]#1 step %[[VAL_2]] unordered iter_args(%[[VAL_19:.*]] = %[[VAL_16]]) -> (f16) {
+// CHECK:           %[[VAL_14:.*]] = fir.do_loop %[[VAL_15:.*]] = %[[VAL_2]] to %[[VAL_5]]#1 step %[[VAL_2]] iter_args(%[[VAL_16:.*]] = %[[VAL_9]]) -> (f16) {
+// CHECK:             %[[VAL_17:.*]] = fir.do_loop %[[VAL_18:.*]] = %[[VAL_2]] to %[[VAL_4]]#1 step %[[VAL_2]] iter_args(%[[VAL_19:.*]] = %[[VAL_16]]) -> (f16) {
 // CHECK:               %[[VAL_20:.*]]:3 = fir.box_dims %[[VAL_0]], %[[VAL_3]] : (!fir.box<!fir.array<?x?xf16>>, index) -> (index, index, index)
 // CHECK:               %[[VAL_21:.*]]:3 = fir.box_dims %[[VAL_0]], %[[VAL_2]] : (!fir.box<!fir.array<?x?xf16>>, index) -> (index, index, index)
 // CHECK:               %[[VAL_22:.*]] = arith.subi %[[VAL_20]]#0, %[[VAL_2]] : index



More information about the flang-commits mailing list