[flang-commits] [flang] [flang] Added ConditionallySpeculatable and Pure for some FIR ops. (PR #174013)
Slava Zakharin via flang-commits
flang-commits at lists.llvm.org
Fri Jan 16 10:30:58 PST 2026
https://github.com/vzakhari updated https://github.com/llvm/llvm-project/pull/174013
>From 3f987a25ed79ba6ee9c4063202a1bbf2c2d8bc50 Mon Sep 17 00:00:00 2001
From: Slava Zakharin <szakharin at nvidia.com>
Date: Tue, 30 Dec 2025 11:19:21 -0800
Subject: [PATCH 1/3] [flang] Added ConditionallySpeculatable and Pure for some
FIR ops.
This patch implements `ConditionallySpeculatable` interface for some
FIR operations (`embox`, `rebox`, `box_addr`, `box_dims` and `convert`).
It also adds `Pure` trait for `fir.shape`, `fir.shapeshift`,
`fir.shift and `fir.slice`.
I could have split this into multiple patches, but the changes
are better tested together on real apps, and the amount of affected
code is small.
There are more `NoMemoryEffect` operations for which I am planning
to do the same in future PRs.
---
.../include/flang/Optimizer/Dialect/FIROps.td | 29 ++-
flang/lib/Optimizer/Dialect/FIROps.cpp | 65 +++++++
flang/test/Transforms/licm.fir | 166 ++++++++++++++++--
3 files changed, 240 insertions(+), 20 deletions(-)
diff --git a/flang/include/flang/Optimizer/Dialect/FIROps.td b/flang/include/flang/Optimizer/Dialect/FIROps.td
index fda98c3050c98..a177fc483109e 100644
--- a/flang/include/flang/Optimizer/Dialect/FIROps.td
+++ b/flang/include/flang/Optimizer/Dialect/FIROps.td
@@ -856,6 +856,7 @@ def fir_HasValueOp : fir_Op<"has_value", [Terminator, HasParent<"GlobalOp">]> {
//===----------------------------------------------------------------------===//
def fir_EmboxOp : fir_Op<"embox", [NoMemoryEffect, AttrSizedOperandSegments,
+ ConditionallySpeculatable,
fir_FortranObjectViewOpInterface]> {
let summary = "boxes a given reference and (optional) dimension information";
@@ -923,10 +924,14 @@ def fir_EmboxOp : fir_Op<"embox", [NoMemoryEffect, AttrSizedOperandSegments,
// FortranObjectViewOpInterface methods:
mlir::Value getViewSource(mlir::OpResult) { return getMemref(); }
std::optional<std::int64_t> getViewOffset(mlir::OpResult);
+
+ // Interface method for ConditionallySpeculatable.
+ mlir::Speculation::Speculatability getSpeculatability();
}];
}
def fir_ReboxOp : fir_Op<"rebox", [NoMemoryEffect, AttrSizedOperandSegments,
+ ConditionallySpeculatable,
fir_FortranObjectViewOpInterface]> {
let summary =
"create a box given another box and (optional) dimension information";
@@ -982,6 +987,9 @@ def fir_ReboxOp : fir_Op<"rebox", [NoMemoryEffect, AttrSizedOperandSegments,
// FortranObjectViewOpInterface methods:
mlir::Value getViewSource(mlir::OpResult) { return getBox(); }
std::optional<std::int64_t> getViewOffset(mlir::OpResult);
+
+ // Interface method for ConditionallySpeculatable.
+ mlir::Speculation::Speculatability getSpeculatability();
}];
}
@@ -1133,6 +1141,7 @@ def fir_UnboxProcOp : fir_SimpleOp<"unboxproc", [NoMemoryEffect]> {
def fir_BoxAddrOp
: fir_SimpleOneResultOp<"box_addr", [NoMemoryEffect,
+ ConditionallySpeculatable,
fir_FortranObjectViewOpInterface]> {
let summary = "return a memory reference to the boxed value";
@@ -1161,6 +1170,9 @@ def fir_BoxAddrOp
// FortranObjectViewOpInterface methods:
mlir::Value getViewSource(mlir::OpResult) { return getVal(); }
std::optional<std::int64_t> getViewOffset(mlir::OpResult);
+
+ // Interface method for ConditionallySpeculatable.
+ mlir::Speculation::Speculatability getSpeculatability();
}];
}
@@ -1183,7 +1195,8 @@ def fir_BoxCharLenOp : fir_SimpleOp<"boxchar_len", [NoMemoryEffect]> {
let hasFolder = 1;
}
-def fir_BoxDimsOp : fir_Op<"box_dims", [NoMemoryEffect]> {
+def fir_BoxDimsOp
+ : fir_Op<"box_dims", [NoMemoryEffect, ConditionallySpeculatable]> {
let summary = "return the dynamic dimension information for the boxed value";
let description = [{
@@ -1215,6 +1228,8 @@ def fir_BoxDimsOp : fir_Op<"box_dims", [NoMemoryEffect]> {
mlir::Value getLowerBound() {return getResult(0);};
mlir::Value getExtent() {return getResult(1);};
mlir::Value getByteStride() {return getResult(2);};
+ // Interface method for ConditionallySpeculatable.
+ mlir::Speculation::Speculatability getSpeculatability();
}];
}
@@ -2012,7 +2027,7 @@ def fir_FieldIndexOp : fir_OneResultOp<"field_index", [NoMemoryEffect]> {
}];
}
-def fir_ShapeOp : fir_Op<"shape", [NoMemoryEffect]> {
+def fir_ShapeOp : fir_Op<"shape", [Pure]> {
let summary = "generate an abstract shape vector of type `!fir.shape`";
@@ -2041,7 +2056,7 @@ def fir_ShapeOp : fir_Op<"shape", [NoMemoryEffect]> {
let builders = [OpBuilder<(ins "mlir::ValueRange":$extents)>];
}
-def fir_ShapeShiftOp : fir_Op<"shape_shift", [NoMemoryEffect]> {
+def fir_ShapeShiftOp : fir_Op<"shape_shift", [Pure]> {
let summary = [{
generate an abstract shape and shift vector of type `!fir.shapeshift`
@@ -2091,7 +2106,7 @@ def fir_ShapeShiftOp : fir_Op<"shape_shift", [NoMemoryEffect]> {
}];
}
-def fir_ShiftOp : fir_Op<"shift", [NoMemoryEffect]> {
+def fir_ShiftOp : fir_Op<"shift", [Pure]> {
let summary = "generate an abstract shift vector of type `!fir.shift`";
@@ -2118,7 +2133,7 @@ def fir_ShiftOp : fir_Op<"shift", [NoMemoryEffect]> {
let hasVerifier = 1;
}
-def fir_SliceOp : fir_Op<"slice", [NoMemoryEffect, AttrSizedOperandSegments]> {
+def fir_SliceOp : fir_Op<"slice", [Pure, AttrSizedOperandSegments]> {
let summary = "generate an abstract slice vector of type `!fir.slice`";
@@ -2910,6 +2925,7 @@ def fir_VolatileCastOp : fir_SimpleOneResultOp<"volatile_cast", [Pure]> {
def fir_ConvertOp
: fir_SimpleOneResultOp<"convert", [NoMemoryEffect, ViewLikeOpInterface,
+ ConditionallySpeculatable,
fir_FortranObjectViewOpInterface]> {
let summary = "encapsulates all Fortran entity type conversions";
@@ -2955,6 +2971,9 @@ def fir_ConvertOp
// FortranObjectViewOpInterface methods:
mlir::Value getViewSource(mlir::OpResult) { return getValue(); }
std::optional<std::int64_t> getViewOffset(mlir::OpResult) { return 0; }
+
+ // Interface method for ConditionallySpeculatable.
+ mlir::Speculation::Speculatability getSpeculatability();
}];
let hasCanonicalizer = 1;
}
diff --git a/flang/lib/Optimizer/Dialect/FIROps.cpp b/flang/lib/Optimizer/Dialect/FIROps.cpp
index 15d0b027c3c62..9c30804ce7874 100644
--- a/flang/lib/Optimizer/Dialect/FIROps.cpp
+++ b/flang/lib/Optimizer/Dialect/FIROps.cpp
@@ -174,6 +174,34 @@ static void printAllocatableOp(mlir::OpAsmPrinter &p, OP &op) {
p.printOptionalAttrDict(op->getAttrs(), {"in_type", "operandSegmentSizes"});
}
+/// Returns true if the given box value may be absent.
+/// The given value must have BaseBoxType.
+static bool mayBeAbsentBox(mlir::Value val) {
+ assert(mlir::isa<fir::BaseBoxType>(val.getType()) && "expected box argument");
+ while (val) {
+ mlir::Operation *defOp = val.getDefiningOp();
+ if (!defOp)
+ return true;
+
+ if (auto varIface = mlir::dyn_cast<fir::FortranVariableOpInterface>(defOp))
+ return varIface.isOptional();
+
+ // Check for fir.embox and fir.rebox before checking for
+ // FortranObjectViewOpInterface, which they support.
+ // A box created by fir.embox/rebox cannot be absent.
+ if (mlir::isa<fir::ReboxOp, fir::EmboxOp, fir::LoadOp>(defOp))
+ return false;
+
+ if (auto viewIface =
+ mlir::dyn_cast<fir::FortranObjectViewOpInterface>(defOp)) {
+ val = viewIface.getViewSource(mlir::cast<mlir::OpResult>(val));
+ continue;
+ }
+ break;
+ }
+ return true;
+}
+
//===----------------------------------------------------------------------===//
// AllocaOp
//===----------------------------------------------------------------------===//
@@ -1128,6 +1156,11 @@ std::optional<std::int64_t> fir::BoxAddrOp::getViewOffset(mlir::OpResult) {
return 0;
}
+mlir::Speculation::Speculatability fir::BoxAddrOp::getSpeculatability() {
+ return mayBeAbsentBox(getVal()) ? mlir::Speculation::NotSpeculatable
+ : mlir::Speculation::Speculatable;
+}
+
//===----------------------------------------------------------------------===//
// BoxCharLenOp
//===----------------------------------------------------------------------===//
@@ -1152,6 +1185,11 @@ mlir::Type fir::BoxDimsOp::getTupleType() {
return mlir::TupleType::get(getContext(), triple);
}
+mlir::Speculation::Speculatability fir::BoxDimsOp::getSpeculatability() {
+ return mayBeAbsentBox(getVal()) ? mlir::Speculation::NotSpeculatable
+ : mlir::Speculation::Speculatable;
+}
+
//===----------------------------------------------------------------------===//
// BoxRankOp
//===----------------------------------------------------------------------===//
@@ -1630,6 +1668,22 @@ llvm::LogicalResult fir::ConvertOp::verify() {
<< getValue().getType() << " / " << getType();
}
+mlir::Speculation::Speculatability fir::ConvertOp::getSpeculatability() {
+ // fir.convert is speculatable, in general. The only concern may be
+ // converting from or/and to floating point types, which may trigger
+ // some FP exceptions. Disallow speculating such converts for the time being.
+ // Also disallow speculation for converts to/from non-FIR types, except
+ // for some builtin types.
+ auto canSpeculateType = [](mlir::Type ty) {
+ if (fir::isa_fir_type(ty) || fir::isa_integer(ty))
+ return true;
+ return false;
+ };
+ return (canSpeculateType(getValue().getType()) && canSpeculateType(getType()))
+ ? mlir::Speculation::Speculatable
+ : mlir::Speculation::NotSpeculatable;
+}
+
//===----------------------------------------------------------------------===//
// CoordinateOp
//===----------------------------------------------------------------------===//
@@ -2121,6 +2175,12 @@ std::optional<std::int64_t> fir::EmboxOp::getViewOffset(mlir::OpResult) {
return std::nullopt;
}
+mlir::Speculation::Speculatability fir::EmboxOp::getSpeculatability() {
+ return (getSourceBox() && mayBeAbsentBox(getSourceBox()))
+ ? mlir::Speculation::NotSpeculatable
+ : mlir::Speculation::Speculatable;
+}
+
//===----------------------------------------------------------------------===//
// EmboxCharOp
//===----------------------------------------------------------------------===//
@@ -3417,6 +3477,11 @@ std::optional<std::int64_t> fir::ReboxOp::getViewOffset(mlir::OpResult) {
return std::nullopt;
}
+mlir::Speculation::Speculatability fir::ReboxOp::getSpeculatability() {
+ return mayBeAbsentBox(getBox()) ? mlir::Speculation::NotSpeculatable
+ : mlir::Speculation::Speculatable;
+}
+
//===----------------------------------------------------------------------===//
// ReboxAssumedRankOp
//===----------------------------------------------------------------------===//
diff --git a/flang/test/Transforms/licm.fir b/flang/test/Transforms/licm.fir
index b568f62b6fca6..69383f6f117ca 100644
--- a/flang/test/Transforms/licm.fir
+++ b/flang/test/Transforms/licm.fir
@@ -103,9 +103,9 @@ func.func @_QPtest_dummy_scalar(%arg0: !fir.ref<!fir.array<?xi32>> {fir.bindc_na
// CHECK: %[[CONVERT_0:.*]] = fir.convert %[[LOAD_0]] : (i32) -> index
// CHECK: %[[CONVERT_1:.*]] = fir.convert %[[CONSTANT_0]] : (index) -> i32
// CHECK: %[[LOAD_1:.*]] = fir.load %[[DECLARE_3]] : !fir.ref<!fir.box<!fir.heap<i32>>>
+// CHECK: %[[BOX_ADDR_0:.*]] = fir.box_addr %[[LOAD_1]] : (!fir.box<!fir.heap<i32>>) -> !fir.heap<i32>
// CHECK: %[[DO_LOOP_0:.*]] = fir.do_loop %[[VAL_0:.*]] = %[[CONSTANT_0]] to %[[CONVERT_0]] step %[[CONSTANT_0]] iter_args(%[[VAL_1:.*]] = %[[CONVERT_1]]) -> (i32) {
// CHECK: fir.store %[[VAL_1]] to %[[DECLARE_0]] : !fir.ref<i32>
-// CHECK: %[[BOX_ADDR_0:.*]] = fir.box_addr %[[LOAD_1]] : (!fir.box<!fir.heap<i32>>) -> !fir.heap<i32>
// CHECK: %[[LOAD_2:.*]] = fir.load %[[BOX_ADDR_0]] : !fir.heap<i32>
// CHECK: %[[LOAD_3:.*]] = fir.load %[[DECLARE_0]] : !fir.ref<i32>
// CHECK: %[[CONVERT_2:.*]] = fir.convert %[[LOAD_3]] : (i32) -> i64
@@ -318,9 +318,9 @@ func.func @_QPtest_global_scalar(%arg0: !fir.ref<!fir.array<?xi32>> {fir.bindc_n
// CHECK: %[[CONVERT_0:.*]] = fir.convert %[[LOAD_0]] : (i32) -> index
// CHECK: %[[CONVERT_1:.*]] = fir.convert %[[CONSTANT_0]] : (index) -> i32
// CHECK: %[[LOAD_1:.*]] = fir.load %[[DECLARE_0]] : !fir.ref<!fir.box<!fir.heap<f32>>>
+// CHECK: %[[BOX_ADDR_0:.*]] = fir.box_addr %[[LOAD_1]] : (!fir.box<!fir.heap<f32>>) -> !fir.heap<f32>
// CHECK: %[[DO_LOOP_0:.*]] = fir.do_loop %[[VAL_0:.*]] = %[[CONSTANT_0]] to %[[CONVERT_0]] step %[[CONSTANT_0]] iter_args(%[[VAL_1:.*]] = %[[CONVERT_1]]) -> (i32) {
// CHECK: fir.store %[[VAL_1]] to %[[DECLARE_1]] : !fir.ref<i32>
-// CHECK: %[[BOX_ADDR_0:.*]] = fir.box_addr %[[LOAD_1]] : (!fir.box<!fir.heap<f32>>) -> !fir.heap<f32>
// CHECK: %[[LOAD_2:.*]] = fir.load %[[BOX_ADDR_0]] : !fir.heap<f32>
// CHECK: %[[CONVERT_2:.*]] = fir.convert %[[LOAD_2]] : (f32) -> i32
// CHECK: %[[LOAD_3:.*]] = fir.load %[[DECLARE_1]] : !fir.ref<i32>
@@ -391,9 +391,9 @@ func.func @_QPtest_global_scalar_allocatable(%arg0: !fir.ref<!fir.array<?xi32>>
// CHECK: %[[CONVERT_0:.*]] = fir.convert %[[LOAD_0]] : (i32) -> index
// CHECK: %[[CONVERT_1:.*]] = fir.convert %[[CONSTANT_0]] : (index) -> i32
// CHECK: %[[LOAD_1:.*]] = fir.load %[[DECLARE_0]] : !fir.ref<!fir.box<!fir.ptr<f32>>>
+// CHECK: %[[BOX_ADDR_0:.*]] = fir.box_addr %[[LOAD_1]] : (!fir.box<!fir.ptr<f32>>) -> !fir.ptr<f32>
// CHECK: %[[DO_LOOP_0:.*]] = fir.do_loop %[[VAL_0:.*]] = %[[CONSTANT_0]] to %[[CONVERT_0]] step %[[CONSTANT_0]] iter_args(%[[VAL_1:.*]] = %[[CONVERT_1]]) -> (i32) {
// CHECK: fir.store %[[VAL_1]] to %[[DECLARE_1]] : !fir.ref<i32>
-// CHECK: %[[BOX_ADDR_0:.*]] = fir.box_addr %[[LOAD_1]] : (!fir.box<!fir.ptr<f32>>) -> !fir.ptr<f32>
// CHECK: %[[LOAD_2:.*]] = fir.load %[[BOX_ADDR_0]] : !fir.ptr<f32>
// CHECK: %[[CONVERT_2:.*]] = fir.convert %[[LOAD_2]] : (f32) -> i32
// CHECK: %[[LOAD_3:.*]] = fir.load %[[DECLARE_1]] : !fir.ref<i32>
@@ -756,11 +756,11 @@ func.func @_QPtest_dummy_array(%arg0: !fir.ref<!fir.array<?xi32>> {fir.bindc_nam
// CHECK: %[[CONVERT_0:.*]] = fir.convert %[[LOAD_0]] : (i32) -> index
// CHECK: %[[CONVERT_1:.*]] = fir.convert %[[CONSTANT_1]] : (index) -> i32
// CHECK: %[[LOAD_1:.*]] = fir.load %[[DECLARE_3]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>
+// CHECK: %[[BOX_ADDR_0:.*]] = fir.box_addr %[[LOAD_1]] : (!fir.box<!fir.heap<!fir.array<?xi32>>>) -> !fir.heap<!fir.array<?xi32>>
+// CHECK: %[[BOX_DIMS_0:.*]]:3 = fir.box_dims %[[LOAD_1]], %[[CONSTANT_0]] : (!fir.box<!fir.heap<!fir.array<?xi32>>>, index) -> (index, index, index)
+// CHECK: %[[SHAPE_SHIFT_0:.*]] = fir.shape_shift %[[BOX_DIMS_0]]#0, %[[BOX_DIMS_0]]#1 : (index, index) -> !fir.shapeshift<1>
// CHECK: %[[DO_LOOP_0:.*]] = fir.do_loop %[[VAL_0:.*]] = %[[CONSTANT_1]] to %[[CONVERT_0]] step %[[CONSTANT_1]] iter_args(%[[VAL_1:.*]] = %[[CONVERT_1]]) -> (i32) {
// CHECK: fir.store %[[VAL_1]] to %[[DECLARE_0]] : !fir.ref<i32>
-// CHECK: %[[BOX_ADDR_0:.*]] = fir.box_addr %[[LOAD_1]] : (!fir.box<!fir.heap<!fir.array<?xi32>>>) -> !fir.heap<!fir.array<?xi32>>
-// CHECK: %[[BOX_DIMS_0:.*]]:3 = fir.box_dims %[[LOAD_1]], %[[CONSTANT_0]] : (!fir.box<!fir.heap<!fir.array<?xi32>>>, index) -> (index, index, index)
-// CHECK: %[[SHAPE_SHIFT_0:.*]] = fir.shape_shift %[[BOX_DIMS_0]]#0, %[[BOX_DIMS_0]]#1 : (index, index) -> !fir.shapeshift<1>
// CHECK: %[[ARRAY_COOR_0:.*]] = fir.array_coor %[[BOX_ADDR_0]](%[[SHAPE_SHIFT_0]]) %[[CONSTANT_1]] : (!fir.heap<!fir.array<?xi32>>, !fir.shapeshift<1>, index) -> !fir.ref<i32>
// CHECK: %[[LOAD_2:.*]] = fir.load %[[ARRAY_COOR_0]] : !fir.ref<i32>
// CHECK: %[[LOAD_3:.*]] = fir.load %[[DECLARE_0]] : !fir.ref<i32>
@@ -834,10 +834,10 @@ func.func @_QPtest_dummy_array_allocatable(%arg0: !fir.ref<!fir.array<?xi32>> {f
// CHECK: %[[CONVERT_0:.*]] = fir.convert %[[LOAD_0]] : (i32) -> index
// CHECK: %[[CONVERT_1:.*]] = fir.convert %[[CONSTANT_1]] : (index) -> i32
// CHECK: %[[LOAD_1:.*]] = fir.load %[[DECLARE_3]] : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>
+// CHECK: %[[BOX_DIMS_0:.*]]:3 = fir.box_dims %[[LOAD_1]], %[[CONSTANT_0]] : (!fir.box<!fir.ptr<!fir.array<?xi32>>>, index) -> (index, index, index)
+// CHECK: %[[SHIFT_0:.*]] = fir.shift %[[BOX_DIMS_0]]#0 : (index) -> !fir.shift<1>
// CHECK: %[[DO_LOOP_0:.*]] = fir.do_loop %[[VAL_0:.*]] = %[[CONSTANT_1]] to %[[CONVERT_0]] step %[[CONSTANT_1]] iter_args(%[[VAL_1:.*]] = %[[CONVERT_1]]) -> (i32) {
// CHECK: fir.store %[[VAL_1]] to %[[DECLARE_0]] : !fir.ref<i32>
-// CHECK: %[[BOX_DIMS_0:.*]]:3 = fir.box_dims %[[LOAD_1]], %[[CONSTANT_0]] : (!fir.box<!fir.ptr<!fir.array<?xi32>>>, index) -> (index, index, index)
-// CHECK: %[[SHIFT_0:.*]] = fir.shift %[[BOX_DIMS_0]]#0 : (index) -> !fir.shift<1>
// CHECK: %[[ARRAY_COOR_0:.*]] = fir.array_coor %[[LOAD_1]](%[[SHIFT_0]]) %[[CONSTANT_1]] : (!fir.box<!fir.ptr<!fir.array<?xi32>>>, !fir.shift<1>, index) -> !fir.ref<i32>
// CHECK: %[[LOAD_2:.*]] = fir.load %[[ARRAY_COOR_0]] : !fir.ref<i32>
// CHECK: %[[LOAD_3:.*]] = fir.load %[[DECLARE_0]] : !fir.ref<i32>
@@ -985,11 +985,11 @@ func.func @_QPtest_global_array(%arg0: !fir.ref<!fir.array<?xi32>> {fir.bindc_na
// CHECK: %[[CONVERT_0:.*]] = fir.convert %[[LOAD_0]] : (i32) -> index
// CHECK: %[[CONVERT_1:.*]] = fir.convert %[[CONSTANT_1]] : (index) -> i32
// CHECK: %[[LOAD_1:.*]] = fir.load %[[DECLARE_0]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>
+// CHECK: %[[BOX_ADDR_0:.*]] = fir.box_addr %[[LOAD_1]] : (!fir.box<!fir.heap<!fir.array<?xf32>>>) -> !fir.heap<!fir.array<?xf32>>
+// CHECK: %[[BOX_DIMS_0:.*]]:3 = fir.box_dims %[[LOAD_1]], %[[CONSTANT_0]] : (!fir.box<!fir.heap<!fir.array<?xf32>>>, index) -> (index, index, index)
+// CHECK: %[[SHAPE_SHIFT_0:.*]] = fir.shape_shift %[[BOX_DIMS_0]]#0, %[[BOX_DIMS_0]]#1 : (index, index) -> !fir.shapeshift<1>
// CHECK: %[[DO_LOOP_0:.*]] = fir.do_loop %[[VAL_0:.*]] = %[[CONSTANT_1]] to %[[CONVERT_0]] step %[[CONSTANT_1]] iter_args(%[[VAL_1:.*]] = %[[CONVERT_1]]) -> (i32) {
// CHECK: fir.store %[[VAL_1]] to %[[DECLARE_1]] : !fir.ref<i32>
-// CHECK: %[[BOX_ADDR_0:.*]] = fir.box_addr %[[LOAD_1]] : (!fir.box<!fir.heap<!fir.array<?xf32>>>) -> !fir.heap<!fir.array<?xf32>>
-// CHECK: %[[BOX_DIMS_0:.*]]:3 = fir.box_dims %[[LOAD_1]], %[[CONSTANT_0]] : (!fir.box<!fir.heap<!fir.array<?xf32>>>, index) -> (index, index, index)
-// CHECK: %[[SHAPE_SHIFT_0:.*]] = fir.shape_shift %[[BOX_DIMS_0]]#0, %[[BOX_DIMS_0]]#1 : (index, index) -> !fir.shapeshift<1>
// CHECK: %[[ARRAY_COOR_0:.*]] = fir.array_coor %[[BOX_ADDR_0]](%[[SHAPE_SHIFT_0]]) %[[CONSTANT_1]] : (!fir.heap<!fir.array<?xf32>>, !fir.shapeshift<1>, index) -> !fir.ref<f32>
// CHECK: %[[LOAD_2:.*]] = fir.load %[[ARRAY_COOR_0]] : !fir.ref<f32>
// CHECK: %[[CONVERT_2:.*]] = fir.convert %[[LOAD_2]] : (f32) -> i32
@@ -1066,10 +1066,10 @@ func.func @_QPtest_global_array_allocatable(%arg0: !fir.ref<!fir.array<?xi32>> {
// CHECK: %[[CONVERT_0:.*]] = fir.convert %[[LOAD_0]] : (i32) -> index
// CHECK: %[[CONVERT_1:.*]] = fir.convert %[[CONSTANT_1]] : (index) -> i32
// CHECK: %[[LOAD_1:.*]] = fir.load %[[DECLARE_0]] : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>
+// CHECK: %[[BOX_DIMS_0:.*]]:3 = fir.box_dims %[[LOAD_1]], %[[CONSTANT_0]] : (!fir.box<!fir.ptr<!fir.array<?xf32>>>, index) -> (index, index, index)
+// CHECK: %[[SHIFT_0:.*]] = fir.shift %[[BOX_DIMS_0]]#0 : (index) -> !fir.shift<1>
// CHECK: %[[DO_LOOP_0:.*]] = fir.do_loop %[[VAL_0:.*]] = %[[CONSTANT_1]] to %[[CONVERT_0]] step %[[CONSTANT_1]] iter_args(%[[VAL_1:.*]] = %[[CONVERT_1]]) -> (i32) {
// CHECK: fir.store %[[VAL_1]] to %[[DECLARE_1]] : !fir.ref<i32>
-// CHECK: %[[BOX_DIMS_0:.*]]:3 = fir.box_dims %[[LOAD_1]], %[[CONSTANT_0]] : (!fir.box<!fir.ptr<!fir.array<?xf32>>>, index) -> (index, index, index)
-// CHECK: %[[SHIFT_0:.*]] = fir.shift %[[BOX_DIMS_0]]#0 : (index) -> !fir.shift<1>
// CHECK: %[[ARRAY_COOR_0:.*]] = fir.array_coor %[[LOAD_1]](%[[SHIFT_0]]) %[[CONSTANT_1]] : (!fir.box<!fir.ptr<!fir.array<?xf32>>>, !fir.shift<1>, index) -> !fir.ref<f32>
// CHECK: %[[LOAD_2:.*]] = fir.load %[[ARRAY_COOR_0]] : !fir.ref<f32>
// CHECK: %[[CONVERT_2:.*]] = fir.convert %[[LOAD_2]] : (f32) -> i32
@@ -1530,8 +1530,8 @@ func.func @_QPtest_common_scalar(%arg0: !fir.ref<!fir.array<?xi32>> {fir.bindc_n
// CHECK: %[[DECLARE_2:.*]] = fir.declare %[[CONVERT_1]](%{{.*}}) storage(%[[ADDRESS_OF_0]][4]) {uniq_name = "_QFtest_common_arrayEc"} : (!fir.ref<!fir.array<10xf32>>, !fir.shape<1>, !fir.ref<!fir.array<44xi8>>) -> !fir.ref<!fir.array<10xf32>>
// CHECK: %[[DECLARE_4:.*]] = fir.declare %[[ARG2]] dummy_scope %{{.*}} arg 3 {uniq_name = "_QFtest_common_arrayEm"} : (!fir.ref<i32>, !fir.dscope) -> !fir.ref<i32>
// CHECK: %[[LOAD_1:.*]] = fir.load %[[DECLARE_4]] : !fir.ref<i32>
+// CHECK: %[[CONVERT_4:.*]] = fir.convert %[[LOAD_1]] : (i32) -> i64
// CHECK: %[[DO_LOOP_0:.*]] = fir.do_loop
-// CHECK: %[[CONVERT_4:.*]] = fir.convert %[[LOAD_1]] : (i32) -> i64
// CHECK: %[[ARRAY_COOR_0:.*]] = fir.array_coor %[[DECLARE_2]](%{{.*}}) %[[CONVERT_4]] : (!fir.ref<!fir.array<10xf32>>, !fir.shape<1>, i64) -> !fir.ref<f32>
// CHECK: %[[LOAD_2:.*]] = fir.load %[[ARRAY_COOR_0]] : !fir.ref<f32>
// CHECK: %[[CONVERT_5:.*]] = fir.convert %[[LOAD_2]] : (f32) -> i32
@@ -1660,7 +1660,6 @@ func.func @test_if_hoisting(%arg0: !fir.ref<!fir.array<?xi32>> {fir.bindc_name =
return
}
-// -----
// Check that fir.box_addr applied to the private box is not hoisted
// out of acc.loop. This breaks the assumptions taken by OpenACC
// transformations that the results of acc.private operations,
@@ -1727,3 +1726,140 @@ func.func @_QPtest_acc_loop_with_private(%arg0: !fir.ref<f32> {fir.bindc_name =
}
return
}
+
+// Test fir.slice and fir.rebox hoisting:
+// CHECK-LABEL: func.func @_QPtest_slice_rebox_licm(
+// CHECK-SAME: %[[ARG0:.*]]: !fir.box<!fir.array<?xf32>> {fir.bindc_name = "x"}) {
+// CHECK: %[[CONSTANT_0:.*]] = arith.constant 20 : index
+// CHECK: %[[CONSTANT_1:.*]] = arith.constant 10 : index
+// CHECK: %[[CONSTANT_2:.*]] = arith.constant 1 : index
+// CHECK: %[[DUMMY_SCOPE_0:.*]] = fir.dummy_scope : !fir.dscope
+// CHECK: %[[ALLOCA_0:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFtest_slice_rebox_licmEi"}
+// CHECK: %[[DECLARE_0:.*]] = fir.declare %[[ALLOCA_0]] {uniq_name = "_QFtest_slice_rebox_licmEi"} : (!fir.ref<i32>) -> !fir.ref<i32>
+// CHECK: %[[DECLARE_1:.*]] = fir.declare %[[ARG0]] dummy_scope %[[DUMMY_SCOPE_0]] arg 1 {uniq_name = "_QFtest_slice_rebox_licmEx"} : (!fir.box<!fir.array<?xf32>>, !fir.dscope) -> !fir.box<!fir.array<?xf32>>
+// CHECK: %[[REBOX_0:.*]] = fir.rebox %[[DECLARE_1]] : (!fir.box<!fir.array<?xf32>>) -> !fir.box<!fir.array<?xf32>>
+// CHECK: %[[CONVERT_0:.*]] = fir.convert %[[CONSTANT_2]] : (index) -> i32
+// CHECK: %[[SLICE_0:.*]] = fir.slice %[[CONSTANT_1]], %[[CONSTANT_0]], %[[CONSTANT_2]] : (index, index, index) -> !fir.slice<1>
+// CHECK: %[[REBOX_1:.*]] = fir.rebox %[[REBOX_0]] {{\[}}%[[SLICE_0]]] : (!fir.box<!fir.array<?xf32>>, !fir.slice<1>) -> !fir.box<!fir.array<11xf32>>
+// CHECK: %[[CONVERT_1:.*]] = fir.convert %[[REBOX_1]] : (!fir.box<!fir.array<11xf32>>) -> !fir.box<!fir.array<?xf32>>
+// CHECK: %[[DO_LOOP_0:.*]] = fir.do_loop %[[VAL_0:.*]] = %[[CONSTANT_2]] to %[[CONSTANT_1]] step %[[CONSTANT_2]] iter_args(%[[VAL_1:.*]] = %[[CONVERT_0]]) -> (i32) {
+// CHECK: fir.store %[[VAL_1]] to %[[DECLARE_0]] : !fir.ref<i32>
+// CHECK: fir.call @takes_assumed_shape(%[[CONVERT_1]]) : (!fir.box<!fir.array<?xf32>>) -> ()
+// CHECK: %[[LOAD_0:.*]] = fir.load %[[DECLARE_0]] : !fir.ref<i32>
+// CHECK: %[[ADDI_0:.*]] = arith.addi %[[LOAD_0]], %[[CONVERT_0]] overflow<nsw> : i32
+// CHECK: fir.result %[[ADDI_0]] : i32
+// CHECK: }
+func.func @_QPtest_slice_rebox_licm(%arg0: !fir.box<!fir.array<?xf32>> {fir.bindc_name = "x"}) {
+ %c20 = arith.constant 20 : index
+ %c10 = arith.constant 10 : index
+ %c1 = arith.constant 1 : index
+ %0 = fir.dummy_scope : !fir.dscope
+ %3 = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFtest_slice_rebox_licmEi"}
+ %4 = fir.declare %3 {uniq_name = "_QFtest_slice_rebox_licmEi"} : (!fir.ref<i32>) -> !fir.ref<i32>
+ %5 = fir.declare %arg0 dummy_scope %0 arg 1 {uniq_name = "_QFtest_slice_rebox_licmEx"} : (!fir.box<!fir.array<?xf32>>, !fir.dscope) -> !fir.box<!fir.array<?xf32>>
+ %6 = fir.rebox %5 : (!fir.box<!fir.array<?xf32>>) -> !fir.box<!fir.array<?xf32>>
+ %7 = fir.convert %c1 : (index) -> i32
+ %8 = fir.do_loop %arg2 = %c1 to %c10 step %c1 iter_args(%arg3 = %7) -> (i32) {
+ fir.store %arg3 to %4 : !fir.ref<i32>
+ %9 = fir.slice %c10, %c20, %c1 : (index, index, index) -> !fir.slice<1>
+ %10 = fir.rebox %6 [%9] : (!fir.box<!fir.array<?xf32>>, !fir.slice<1>) -> !fir.box<!fir.array<11xf32>>
+ %11 = fir.convert %10 : (!fir.box<!fir.array<11xf32>>) -> !fir.box<!fir.array<?xf32>>
+ fir.call @takes_assumed_shape(%11) : (!fir.box<!fir.array<?xf32>>) -> ()
+ %12 = fir.load %4 : !fir.ref<i32>
+ %13 = arith.addi %12, %7 overflow<nsw> : i32
+ fir.result %13 : i32
+ }
+ fir.store %8 to %4 : !fir.ref<i32>
+ return
+}
+func.func private @takes_assumed_shape(!fir.box<!fir.array<?xf32>>)
+
+// Test fir.shape and fir.embox hoisting:
+// CHECK-LABEL: func.func @_QPtest_shape_embox_licm(
+// CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.array<?xf32>> {fir.bindc_name = "x"}) {
+// CHECK: %[[CONSTANT_0:.*]] = arith.constant 11 : index
+// CHECK: %[[CONSTANT_1:.*]] = arith.constant 10 : index
+// CHECK: %[[CONSTANT_2:.*]] = arith.constant 1 : index
+// CHECK: %[[DUMMY_SCOPE_0:.*]] = fir.dummy_scope : !fir.dscope
+// CHECK: %[[ALLOCA_0:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFtest_shape_embox_licmEi"}
+// CHECK: %[[DECLARE_0:.*]] = fir.declare %[[ALLOCA_0]] {uniq_name = "_QFtest_shape_embox_licmEi"} : (!fir.ref<i32>) -> !fir.ref<i32>
+// CHECK: %[[ASSUMED_SIZE_EXTENT_0:.*]] = fir.assumed_size_extent : index
+// CHECK: %[[SHAPE_0:.*]] = fir.shape %[[ASSUMED_SIZE_EXTENT_0]] : (index) -> !fir.shape<1>
+// CHECK: %[[DECLARE_1:.*]] = fir.declare %[[ARG0]](%[[SHAPE_0]]) dummy_scope %[[DUMMY_SCOPE_0]] arg 1 {uniq_name = "_QFtest_shape_embox_licmEx"} : (!fir.ref<!fir.array<?xf32>>, !fir.shape<1>, !fir.dscope) -> !fir.ref<!fir.array<?xf32>>
+// CHECK: %[[CONVERT_0:.*]] = fir.convert %[[CONSTANT_2]] : (index) -> i32
+// CHECK: %[[ARRAY_COOR_0:.*]] = fir.array_coor %[[DECLARE_1]](%[[SHAPE_0]]) %[[CONSTANT_1]] : (!fir.ref<!fir.array<?xf32>>, !fir.shape<1>, index) -> !fir.ref<f32>
+// CHECK: %[[SHAPE_1:.*]] = fir.shape %[[CONSTANT_0]] : (index) -> !fir.shape<1>
+// CHECK: %[[CONVERT_1:.*]] = fir.convert %[[ARRAY_COOR_0]] : (!fir.ref<f32>) -> !fir.ref<!fir.array<11xf32>>
+// CHECK: %[[EMBOX_0:.*]] = fir.embox %[[CONVERT_1]](%[[SHAPE_1]]) : (!fir.ref<!fir.array<11xf32>>, !fir.shape<1>) -> !fir.box<!fir.array<11xf32>>
+// CHECK: %[[CONVERT_2:.*]] = fir.convert %[[EMBOX_0]] : (!fir.box<!fir.array<11xf32>>) -> !fir.box<!fir.array<?xf32>>
+// CHECK: %[[DO_LOOP_0:.*]] = fir.do_loop %[[VAL_0:.*]] = %[[CONSTANT_2]] to %[[CONSTANT_1]] step %[[CONSTANT_2]] iter_args(%[[VAL_1:.*]] = %[[CONVERT_0]]) -> (i32) {
+// CHECK: fir.store %[[VAL_1]] to %[[DECLARE_0]] : !fir.ref<i32>
+// CHECK: fir.call @takes_assumed_shape(%[[CONVERT_2]]) : (!fir.box<!fir.array<?xf32>>) -> ()
+// CHECK: %[[LOAD_0:.*]] = fir.load %[[DECLARE_0]] : !fir.ref<i32>
+// CHECK: %[[ADDI_0:.*]] = arith.addi %[[LOAD_0]], %[[CONVERT_0]] overflow<nsw> : i32
+// CHECK: fir.result %[[ADDI_0]] : i32
+// CHECK: }
+func.func @_QPtest_shape_embox_licm(%arg0: !fir.ref<!fir.array<?xf32>> {fir.bindc_name = "x"}) {
+ %c11 = arith.constant 11 : index
+ %c10 = arith.constant 10 : index
+ %c1 = arith.constant 1 : index
+ %0 = fir.dummy_scope : !fir.dscope
+ %1 = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFtest_shape_embox_licmEi"}
+ %2 = fir.declare %1 {uniq_name = "_QFtest_shape_embox_licmEi"} : (!fir.ref<i32>) -> !fir.ref<i32>
+ %3 = fir.assumed_size_extent : index
+ %4 = fir.shape %3 : (index) -> !fir.shape<1>
+ %5 = fir.declare %arg0(%4) dummy_scope %0 arg 1 {uniq_name = "_QFtest_shape_embox_licmEx"} : (!fir.ref<!fir.array<?xf32>>, !fir.shape<1>, !fir.dscope) -> !fir.ref<!fir.array<?xf32>>
+ %6 = fir.convert %c1 : (index) -> i32
+ %9 = fir.array_coor %5(%4) %c10 : (!fir.ref<!fir.array<?xf32>>, !fir.shape<1>, index) -> !fir.ref<f32>
+ %7 = fir.do_loop %arg1 = %c1 to %c10 step %c1 iter_args(%arg2 = %6) -> (i32) {
+ fir.store %arg2 to %2 : !fir.ref<i32>
+ %8 = fir.shape %c11 : (index) -> !fir.shape<1>
+ %10 = fir.convert %9 : (!fir.ref<f32>) -> !fir.ref<!fir.array<11xf32>>
+ %11 = fir.embox %10(%8) : (!fir.ref<!fir.array<11xf32>>, !fir.shape<1>) -> !fir.box<!fir.array<11xf32>>
+ %12 = fir.convert %11 : (!fir.box<!fir.array<11xf32>>) -> !fir.box<!fir.array<?xf32>>
+ fir.call @takes_assumed_shape(%12) : (!fir.box<!fir.array<?xf32>>) -> ()
+ %13 = fir.load %2 : !fir.ref<i32>
+ %14 = arith.addi %13, %6 overflow<nsw> : i32
+ fir.result %14 : i32
+ }
+ fir.store %7 to %2 : !fir.ref<i32>
+ return
+}
+
+// CHECK-LABEL: func.func @test_shapeshift_licm(
+// CHECK-SAME: %[[ARG0:.*]]: index) {
+// CHECK: %[[CONSTANT_0:.*]] = arith.constant 1 : index
+// CHECK: %[[CONSTANT_1:.*]] = arith.constant 10 : index
+// CHECK: %[[SHAPE_SHIFT_0:.*]] = fir.shape_shift %[[ARG0]], %[[ARG0]] : (index, index) -> !fir.shapeshift<1>
+// CHECK: fir.do_loop %[[VAL_0:.*]] = %[[CONSTANT_0]] to %[[CONSTANT_1]] step %[[CONSTANT_0]] {
+// CHECK: fir.call @takes_shape_shift(%[[SHAPE_SHIFT_0]]) : (!fir.shapeshift<1>) -> ()
+// CHECK: }
+func.func @test_shapeshift_licm(%arg0 : index) {
+ %c1 = arith.constant 1 : index
+ %c10 = arith.constant 10 : index
+ fir.do_loop %arg1 = %c1 to %c10 step %c1 {
+ %op = fir.shape_shift %arg0, %arg0 : (index, index) -> !fir.shapeshift<1>
+ fir.call @takes_shape_shift(%op) : (!fir.shapeshift<1>) -> ()
+ }
+ return
+}
+func.func private @takes_shape_shift(!fir.shapeshift<1>)
+
+// CHECK-LABEL: func.func @test_shift_licm(
+// CHECK-SAME: %[[ARG0:.*]]: index) {
+// CHECK: %[[CONSTANT_0:.*]] = arith.constant 1 : index
+// CHECK: %[[CONSTANT_1:.*]] = arith.constant 10 : index
+// CHECK: %[[SHIFT_0:.*]] = fir.shift %[[ARG0]] : (index) -> !fir.shift<1>
+// CHECK: fir.do_loop %[[VAL_0:.*]] = %[[CONSTANT_0]] to %[[CONSTANT_1]] step %[[CONSTANT_0]] {
+// CHECK: fir.call @takes_shift(%[[SHIFT_0]]) : (!fir.shift<1>) -> ()
+// CHECK: }
+func.func @test_shift_licm(%arg0 : index) {
+ %c1 = arith.constant 1 : index
+ %c10 = arith.constant 10 : index
+ fir.do_loop %arg1 = %c1 to %c10 step %c1 {
+ %op = fir.shift %arg0 : (index) -> !fir.shift<1>
+ fir.call @takes_shift(%op) : (!fir.shift<1>) -> ()
+ }
+ return
+}
+func.func private @takes_shift(!fir.shift<1>)
>From b0f6225f20b25958828e2a8c0fb2ded6c193fa1f Mon Sep 17 00:00:00 2001
From: Slava Zakharin <szakharin at nvidia.com>
Date: Tue, 30 Dec 2025 13:18:46 -0800
Subject: [PATCH 2/3] Avoid calling `mayBeAbsentBox` for `fir.box_addr` with
non-box/class input.
---
flang/lib/Optimizer/Dialect/FIROps.cpp | 4 ++++
flang/test/Transforms/licm.fir | 28 ++++++++++++++++++++++++++
2 files changed, 32 insertions(+)
diff --git a/flang/lib/Optimizer/Dialect/FIROps.cpp b/flang/lib/Optimizer/Dialect/FIROps.cpp
index 9c30804ce7874..c6f4a365de36d 100644
--- a/flang/lib/Optimizer/Dialect/FIROps.cpp
+++ b/flang/lib/Optimizer/Dialect/FIROps.cpp
@@ -1157,6 +1157,10 @@ std::optional<std::int64_t> fir::BoxAddrOp::getViewOffset(mlir::OpResult) {
}
mlir::Speculation::Speculatability fir::BoxAddrOp::getSpeculatability() {
+ // Do not speculate fir.box_addr with BoxProcType and BoxCharType
+ // inputs.
+ if (!mlir::isa<fir::BaseBoxType>(getVal().getType()))
+ mlir::Speculation::NotSpeculatable;
return mayBeAbsentBox(getVal()) ? mlir::Speculation::NotSpeculatable
: mlir::Speculation::Speculatable;
}
diff --git a/flang/test/Transforms/licm.fir b/flang/test/Transforms/licm.fir
index 69383f6f117ca..56bf6fc1a2302 100644
--- a/flang/test/Transforms/licm.fir
+++ b/flang/test/Transforms/licm.fir
@@ -1863,3 +1863,31 @@ func.func @test_shift_licm(%arg0 : index) {
return
}
func.func private @takes_shift(!fir.shift<1>)
+
+// Check that fir.box_addr of !fir.boxproc is not speculated.
+// For some reason, we do not produce proper [hl]fir.declare
+// for optional dummy procedure pointers.
+// CHECK-LABEL: func.func @_QPtest_box_addr_proc(
+// CHECK-NOT: fir.box_addr
+// CHECK: fir.do_loop
+// CHECK: fir.box_addr
+func.func @_QPtest_box_addr_proc(%arg0: !fir.ref<f32> {fir.bindc_name = "x"}, %arg1: !fir.boxproc<() -> ()>) {
+ %c10 = arith.constant 10 : index
+ %c1 = arith.constant 1 : index
+ %0 = fir.dummy_scope : !fir.dscope
+ %1 = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFtest_box_addr_procEi"}
+ %2 = fir.declare %1 {uniq_name = "_QFtest_box_addr_procEi"} : (!fir.ref<i32>) -> !fir.ref<i32>
+ %3 = fir.declare %arg0 dummy_scope %0 arg 1 {uniq_name = "_QFtest_box_addr_procEx"} : (!fir.ref<f32>, !fir.dscope) -> !fir.ref<f32>
+ %4 = fir.convert %c1 : (index) -> i32
+ %5 = fir.do_loop %arg2 = %c1 to %c10 step %c1 iter_args(%arg3 = %4) -> (i32) {
+ fir.store %arg3 to %2 : !fir.ref<i32>
+ %6 = fir.box_addr %arg1 : (!fir.boxproc<() -> ()>) -> (() -> f32)
+ %7 = fir.call %6() : () -> f32
+ fir.store %7 to %3 : !fir.ref<f32>
+ %8 = fir.load %2 : !fir.ref<i32>
+ %9 = arith.addi %8, %4 overflow<nsw> : i32
+ fir.result %9 : i32
+ }
+ fir.store %5 to %2 : !fir.ref<i32>
+ return
+}
>From bcade8238808c3d059f4b7b6a1d2432a263de19c Mon Sep 17 00:00:00 2001
From: Slava Zakharin <szakharin at nvidia.com>
Date: Tue, 30 Dec 2025 13:26:29 -0800
Subject: [PATCH 3/3] typo
---
flang/lib/Optimizer/Dialect/FIROps.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/flang/lib/Optimizer/Dialect/FIROps.cpp b/flang/lib/Optimizer/Dialect/FIROps.cpp
index c6f4a365de36d..38bb4aa102eeb 100644
--- a/flang/lib/Optimizer/Dialect/FIROps.cpp
+++ b/flang/lib/Optimizer/Dialect/FIROps.cpp
@@ -1160,7 +1160,7 @@ mlir::Speculation::Speculatability fir::BoxAddrOp::getSpeculatability() {
// Do not speculate fir.box_addr with BoxProcType and BoxCharType
// inputs.
if (!mlir::isa<fir::BaseBoxType>(getVal().getType()))
- mlir::Speculation::NotSpeculatable;
+ return mlir::Speculation::NotSpeculatable;
return mayBeAbsentBox(getVal()) ? mlir::Speculation::NotSpeculatable
: mlir::Speculation::Speculatable;
}
More information about the flang-commits
mailing list