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

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


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-flang-fir-hlfir

Author: Slava Zakharin (vzakhari)

<details>
<summary>Changes</summary>

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.


---

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


7 Files Affected:

- (modified) flang/include/flang/Optimizer/HLFIR/Passes.h (+1) 
- (modified) flang/include/flang/Optimizer/HLFIR/Passes.td (+16-1) 
- (modified) flang/lib/Optimizer/HLFIR/Transforms/SimplifyHLFIRIntrinsics.cpp (+161-35) 
- (modified) flang/lib/Optimizer/Passes/Pipelines.cpp (+6-4) 
- (added) flang/test/HLFIR/simplify-hlfir-intrinsics-maxmin.fir (+557) 
- (modified) flang/test/HLFIR/simplify-hlfir-intrinsics-maxval.fir (+7-7) 
- (modified) flang/test/HLFIR/simplify-hlfir-intrinsics-minval.fir (+7-7) 


``````````diff
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_lo...
[truncated]

``````````

</details>


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


More information about the flang-commits mailing list