[flang-commits] [flang] ba1fdf4 - [flang] Do not set nuw on RESHAPE index arithmetic involving lower bounds (#229733)
via flang-commits
flang-commits at lists.llvm.org
Thu Oct 8 02:48:46 PDT 2026
Author: jeanPerier
Date: 2026-10-08T11:48:40+02:00
New Revision: ba1fdf4469150eb9e10fd72a2374d4ff7f92f1e7
URL: https://github.com/llvm/llvm-project/commit/ba1fdf4469150eb9e10fd72a2374d4ff7f92f1e7
DIFF: https://github.com/llvm/llvm-project/commit/ba1fdf4469150eb9e10fd72a2374d4ff7f92f1e7.diff
LOG: [flang] Do not set nuw on RESHAPE index arithmetic involving lower bounds (#229733)
The no-unsigned-wrap flag set on the builder by the RESHAPE inlining was
also applied to the lower bound adjustments generated when accessing
ARRAY, SHAPE and PAD elements, which is invalid when lower bounds are
zero or negative. Use nsw by default and only keep nuw on the linear
index computations.
Fixes #229709
Assisted-by: AI
Added:
Modified:
flang/lib/Optimizer/HLFIR/Transforms/SimplifyHLFIRIntrinsics.cpp
flang/test/HLFIR/simplify-hlfir-intrinsics-reshape.fir
Removed:
################################################################################
diff --git a/flang/lib/Optimizer/HLFIR/Transforms/SimplifyHLFIRIntrinsics.cpp b/flang/lib/Optimizer/HLFIR/Transforms/SimplifyHLFIRIntrinsics.cpp
index d145dad9e5412..a17eacd2c7e9f 100644
--- a/flang/lib/Optimizer/HLFIR/Transforms/SimplifyHLFIRIntrinsics.cpp
+++ b/flang/lib/Optimizer/HLFIR/Transforms/SimplifyHLFIRIntrinsics.cpp
@@ -3188,8 +3188,12 @@ class ReshapeAsElementalConversion
mlir::Location loc = reshape.getLoc();
fir::FirOpBuilder builder{rewriter, reshape.getOperation()};
// Assume that all the indices arithmetic does not overflow
- // the IndexType.
- builder.setIntegerOverflowFlags(mlir::arith::IntegerOverflowFlags::nuw);
+ // the signed IndexType. No-unsigned-wrap is only valid for the
+ // zero-based linear index computations (see LinearIndexArithScope),
+ // it must not be set on the computations involving the lower bounds
+ // of ARRAY, SHAPE or PAD (e.g., in hlfir::getElementAt), since they
+ // may be zero or negative.
+ builder.setIntegerOverflowFlags(mlir::arith::IntegerOverflowFlags::nsw);
llvm::SmallVector<mlir::Value, 1> typeParams;
hlfir::genLengthParameters(loc, builder, array, typeParams);
@@ -3233,8 +3237,11 @@ class ReshapeAsElementalConversion
hlfir::genExtentsVector(loc, builder, hlfir::Entity{pad});
// Subtract the ARRAY size from the zero-based linear index
// to get the zero-based linear index into PAD.
- mlir::Value padLinearIndex =
- mlir::arith::SubIOp::create(builder, loc, linearIndex, arraySize);
+ mlir::Value padLinearIndex = [&]() {
+ LinearIndexArithScope scope{builder};
+ return mlir::arith::SubIOp::create(builder, loc, linearIndex,
+ arraySize);
+ }();
llvm::SmallVector<mlir::Value, Fortran::common::maxRank> padIndices =
delinearizeIndex(loc, builder, padExtents, padLinearIndex,
/*wrapAround=*/true);
@@ -3271,6 +3278,24 @@ class ReshapeAsElementalConversion
}
private:
+ /// Sets nsw and nuw on the arithmetic operations created while
+ /// it is alive. Only valid for the computations of the array sizes,
+ /// and the zero-based linear indices and their one-based counterparts,
+ /// which are all non-negative.
+ class LinearIndexArithScope {
+ public:
+ LinearIndexArithScope(fir::FirOpBuilder &builder)
+ : builder{builder}, savedFlags{builder.getIntegerOverflowFlags()} {
+ builder.setIntegerOverflowFlags(mlir::arith::IntegerOverflowFlags::nsw |
+ mlir::arith::IntegerOverflowFlags::nuw);
+ }
+ ~LinearIndexArithScope() { builder.setIntegerOverflowFlags(savedFlags); }
+
+ private:
+ fir::FirOpBuilder &builder;
+ mlir::arith::IntegerOverflowFlags savedFlags;
+ };
+
/// Compute zero-based linear index given an array extents
/// and one-based indices:
/// \p extents: [e0, e1, ..., en]
@@ -3284,6 +3309,7 @@ class ReshapeAsElementalConversion
mlir::ValueRange indices) {
std::size_t rank = extents.size();
assert(rank == indices.size());
+ LinearIndexArithScope scope{builder};
mlir::Type indexType = builder.getIndexType();
mlir::Value zero = builder.createIntegerConstant(loc, indexType, 0);
mlir::Value one = builder.createIntegerConstant(loc, indexType, 1);
@@ -3324,6 +3350,7 @@ class ReshapeAsElementalConversion
delinearizeIndex(mlir::Location loc, fir::FirOpBuilder &builder,
mlir::ValueRange extents, mlir::Value linearIndex,
bool wrapAround) {
+ LinearIndexArithScope scope{builder};
llvm::SmallVector<mlir::Value, Fortran::common::maxRank> indices;
mlir::Type indexType = builder.getIndexType();
mlir::Value one = builder.createIntegerConstant(loc, indexType, 1);
@@ -3349,6 +3376,7 @@ class ReshapeAsElementalConversion
static mlir::Value computeArraySize(mlir::Location loc,
fir::FirOpBuilder &builder,
mlir::ValueRange extents) {
+ LinearIndexArithScope scope{builder};
mlir::Type indexType = builder.getIndexType();
mlir::Value size = builder.createIntegerConstant(loc, indexType, 1);
for (auto extent : extents)
diff --git a/flang/test/HLFIR/simplify-hlfir-intrinsics-reshape.fir b/flang/test/HLFIR/simplify-hlfir-intrinsics-reshape.fir
index afbd3bcd6d98c..d612c77899f75 100644
--- a/flang/test/HLFIR/simplify-hlfir-intrinsics-reshape.fir
+++ b/flang/test/HLFIR/simplify-hlfir-intrinsics-reshape.fir
@@ -16,8 +16,8 @@ func.func @reshape_simple(%arg0: !fir.box<!fir.array<?xf32>>, %arg1: !fir.ref<!f
// CHECK: %[[VAL_7:.*]] = hlfir.elemental %[[VAL_6]] unordered : (!fir.shape<1>) -> !hlfir.expr<?xf32> {
// CHECK: ^bb0(%[[VAL_8:.*]]: index):
// CHECK: %[[VAL_9:.*]]:3 = fir.box_dims %[[VAL_0]], %[[VAL_3]] : (!fir.box<!fir.array<?xf32>>, index) -> (index, index, index)
-// CHECK: %[[VAL_10:.*]] = arith.subi %[[VAL_9]]#0, %[[VAL_2]] overflow<nuw> : index
-// CHECK: %[[VAL_11:.*]] = arith.addi %[[VAL_8]], %[[VAL_10]] overflow<nuw> : index
+// CHECK: %[[VAL_10:.*]] = arith.subi %[[VAL_9]]#0, %[[VAL_2]] overflow<nsw> : index
+// CHECK: %[[VAL_11:.*]] = arith.addi %[[VAL_8]], %[[VAL_10]] overflow<nsw> : index
// CHECK: %[[VAL_12:.*]] = hlfir.designate %[[VAL_0]] (%[[VAL_11]]) : (!fir.box<!fir.array<?xf32>>, index) -> !fir.ref<f32>
// CHECK: %[[VAL_13:.*]] = fir.load %[[VAL_12]] : !fir.ref<f32>
// CHECK: hlfir.yield_element %[[VAL_13]] : f32
@@ -39,8 +39,8 @@ func.func @reshape_with_pad(%arg0: !fir.box<!fir.array<?x?x?xf32>>, %arg1: !fir.
// CHECK: %[[ARRAY_DIM0:.*]]:3 = fir.box_dims %[[VAL_0]], %[[VAL_5]] : (!fir.box<!fir.array<?x?x?xf32>>, index) -> (index, index, index)
// CHECK: %[[ARRAY_DIM1:.*]]:3 = fir.box_dims %[[VAL_0]], %[[VAL_4]] : (!fir.box<!fir.array<?x?x?xf32>>, index) -> (index, index, index)
// CHECK: %[[ARRAY_DIM2:.*]]:3 = fir.box_dims %[[VAL_0]], %[[VAL_3]] : (!fir.box<!fir.array<?x?x?xf32>>, index) -> (index, index, index)
-// CHECK: %[[VAL_9:.*]] = arith.muli %[[ARRAY_DIM0]]#1, %[[ARRAY_DIM1]]#1 overflow<nuw> : index
-// CHECK: %[[ARRAY_SIZE:.*]] = arith.muli %[[VAL_9]], %[[ARRAY_DIM2]]#1 overflow<nuw> : index
+// CHECK: %[[VAL_9:.*]] = arith.muli %[[ARRAY_DIM0]]#1, %[[ARRAY_DIM1]]#1 overflow<nsw, nuw> : index
+// CHECK: %[[ARRAY_SIZE:.*]] = arith.muli %[[VAL_9]], %[[ARRAY_DIM2]]#1 overflow<nsw, nuw> : index
// CHECK: %[[VAL_16:.*]] = hlfir.designate %[[VAL_1]] (%[[VAL_4]]) : (!fir.ref<!fir.array<2xi32>>, index) -> !fir.ref<i32>
// CHECK: %[[VAL_17:.*]] = fir.load %[[VAL_16]] : !fir.ref<i32>
// CHECK: %[[VAL_18:.*]] = hlfir.designate %[[VAL_1]] (%[[VAL_3]]) : (!fir.ref<!fir.array<2xi32>>, index) -> !fir.ref<i32>
@@ -48,29 +48,29 @@ func.func @reshape_with_pad(%arg0: !fir.box<!fir.array<?x?x?xf32>>, %arg1: !fir.
// CHECK: %[[VAL_20:.*]] = fir.shape %[[VAL_17]], %[[VAL_19]] : (i32, i32) -> !fir.shape<2>
// CHECK: %[[VAL_21:.*]] = hlfir.elemental %[[VAL_20]] unordered : (!fir.shape<2>) -> !hlfir.expr<?x?xf32> {
// CHECK: ^bb0(%[[VAL_22:.*]]: index, %[[VAL_23:.*]]: index):
-// CHECK: %[[VAL_24:.*]] = arith.subi %[[VAL_23]], %[[VAL_4]] overflow<nuw> : index
+// CHECK: %[[VAL_24:.*]] = arith.subi %[[VAL_23]], %[[VAL_4]] overflow<nsw, nuw> : index
// CHECK: %[[VAL_25:.*]] = fir.convert %[[VAL_17]] : (i32) -> index
-// CHECK: %[[VAL_26:.*]] = arith.muli %[[VAL_24]], %[[VAL_25]] overflow<nuw> : index
-// CHECK: %[[VAL_27:.*]] = arith.subi %[[VAL_22]], %[[VAL_4]] overflow<nuw> : index
-// CHECK: %[[LINEAR_INDEX:.*]] = arith.addi %[[VAL_26]], %[[VAL_27]] overflow<nuw> : index
+// CHECK: %[[VAL_26:.*]] = arith.muli %[[VAL_24]], %[[VAL_25]] overflow<nsw, nuw> : index
+// CHECK: %[[VAL_27:.*]] = arith.subi %[[VAL_22]], %[[VAL_4]] overflow<nsw, nuw> : index
+// CHECK: %[[LINEAR_INDEX:.*]] = arith.addi %[[VAL_26]], %[[VAL_27]] overflow<nsw, nuw> : index
// CHECK: %[[IS_WITHIN_ARRAY:.*]] = arith.cmpi ult, %[[LINEAR_INDEX]], %[[ARRAY_SIZE]] : index
// CHECK: %[[VAL_30:.*]] = fir.if %[[IS_WITHIN_ARRAY]] -> (f32) {
// CHECK: %[[VAL_31:.*]] = arith.remui %[[LINEAR_INDEX]], %[[ARRAY_DIM0]]#1 : index
// CHECK: %[[VAL_32:.*]] = arith.divui %[[LINEAR_INDEX]], %[[ARRAY_DIM0]]#1 : index
-// CHECK: %[[ARRAY_IDX0:.*]] = arith.addi %[[VAL_31]], %[[VAL_4]] overflow<nuw> : index
+// CHECK: %[[ARRAY_IDX0:.*]] = arith.addi %[[VAL_31]], %[[VAL_4]] overflow<nsw, nuw> : index
// CHECK: %[[VAL_34:.*]] = arith.remui %[[VAL_32]], %[[ARRAY_DIM1]]#1 : index
// CHECK: %[[VAL_35:.*]] = arith.divui %[[VAL_32]], %[[ARRAY_DIM1]]#1 : index
-// CHECK: %[[ARRAY_IDX1:.*]] = arith.addi %[[VAL_34]], %[[VAL_4]] overflow<nuw> : index
-// CHECK: %[[ARRAY_IDX2:.*]] = arith.addi %[[VAL_35]], %[[VAL_4]] overflow<nuw> : index
+// CHECK: %[[ARRAY_IDX1:.*]] = arith.addi %[[VAL_34]], %[[VAL_4]] overflow<nsw, nuw> : index
+// CHECK: %[[ARRAY_IDX2:.*]] = arith.addi %[[VAL_35]], %[[VAL_4]] overflow<nsw, nuw> : index
// CHECK: %[[VAL_38:.*]]:3 = fir.box_dims %[[VAL_0]], %[[VAL_5]] : (!fir.box<!fir.array<?x?x?xf32>>, index) -> (index, index, index)
// CHECK: %[[VAL_39:.*]]:3 = fir.box_dims %[[VAL_0]], %[[VAL_4]] : (!fir.box<!fir.array<?x?x?xf32>>, index) -> (index, index, index)
// CHECK: %[[VAL_40:.*]]:3 = fir.box_dims %[[VAL_0]], %[[VAL_3]] : (!fir.box<!fir.array<?x?x?xf32>>, index) -> (index, index, index)
-// CHECK: %[[VAL_41:.*]] = arith.subi %[[VAL_38]]#0, %[[VAL_4]] overflow<nuw> : index
-// CHECK: %[[VAL_42:.*]] = arith.addi %[[ARRAY_IDX0]], %[[VAL_41]] overflow<nuw> : index
-// CHECK: %[[VAL_43:.*]] = arith.subi %[[VAL_39]]#0, %[[VAL_4]] overflow<nuw> : index
-// CHECK: %[[VAL_44:.*]] = arith.addi %[[ARRAY_IDX1]], %[[VAL_43]] overflow<nuw> : index
-// CHECK: %[[VAL_45:.*]] = arith.subi %[[VAL_40]]#0, %[[VAL_4]] overflow<nuw> : index
-// CHECK: %[[VAL_46:.*]] = arith.addi %[[ARRAY_IDX2]], %[[VAL_45]] overflow<nuw> : index
+// CHECK: %[[VAL_41:.*]] = arith.subi %[[VAL_38]]#0, %[[VAL_4]] overflow<nsw> : index
+// CHECK: %[[VAL_42:.*]] = arith.addi %[[ARRAY_IDX0]], %[[VAL_41]] overflow<nsw> : index
+// CHECK: %[[VAL_43:.*]] = arith.subi %[[VAL_39]]#0, %[[VAL_4]] overflow<nsw> : index
+// CHECK: %[[VAL_44:.*]] = arith.addi %[[ARRAY_IDX1]], %[[VAL_43]] overflow<nsw> : index
+// CHECK: %[[VAL_45:.*]] = arith.subi %[[VAL_40]]#0, %[[VAL_4]] overflow<nsw> : index
+// CHECK: %[[VAL_46:.*]] = arith.addi %[[ARRAY_IDX2]], %[[VAL_45]] overflow<nsw> : index
// CHECK: %[[VAL_47:.*]] = hlfir.designate %[[VAL_0]] (%[[VAL_42]], %[[VAL_44]], %[[VAL_46]]) : (!fir.box<!fir.array<?x?x?xf32>>, index, index, index) -> !fir.ref<f32>
// CHECK: %[[VAL_48:.*]] = fir.load %[[VAL_47]] : !fir.ref<f32>
// CHECK: fir.result %[[VAL_48]] : f32
@@ -78,24 +78,24 @@ func.func @reshape_with_pad(%arg0: !fir.box<!fir.array<?x?x?xf32>>, %arg1: !fir.
// CHECK: %[[PAD_DIM0:.*]]:3 = fir.box_dims %[[VAL_2]], %[[VAL_5]] : (!fir.box<!fir.array<?x?x?xf32>>, index) -> (index, index, index)
// CHECK: %[[PAD_DIM1:.*]]:3 = fir.box_dims %[[VAL_2]], %[[VAL_4]] : (!fir.box<!fir.array<?x?x?xf32>>, index) -> (index, index, index)
// CHECK: %[[PAD_DIM2:.*]]:3 = fir.box_dims %[[VAL_2]], %[[VAL_3]] : (!fir.box<!fir.array<?x?x?xf32>>, index) -> (index, index, index)
-// CHECK: %[[PAD_LINEAR_INDEX:.*]] = arith.subi %[[LINEAR_INDEX]], %[[ARRAY_SIZE]] overflow<nuw> : index
+// CHECK: %[[PAD_LINEAR_INDEX:.*]] = arith.subi %[[LINEAR_INDEX]], %[[ARRAY_SIZE]] overflow<nsw, nuw> : index
// CHECK: %[[VAL_51:.*]] = arith.remui %[[PAD_LINEAR_INDEX]], %[[PAD_DIM0]]#1 : index
// CHECK: %[[VAL_52:.*]] = arith.divui %[[PAD_LINEAR_INDEX]], %[[PAD_DIM0]]#1 : index
-// CHECK: %[[PAD_IDX0:.*]] = arith.addi %[[VAL_51]], %[[VAL_4]] overflow<nuw> : index
+// CHECK: %[[PAD_IDX0:.*]] = arith.addi %[[VAL_51]], %[[VAL_4]] overflow<nsw, nuw> : index
// CHECK: %[[VAL_54:.*]] = arith.remui %[[VAL_52]], %[[PAD_DIM1]]#1 : index
// CHECK: %[[VAL_55:.*]] = arith.divui %[[VAL_52]], %[[PAD_DIM1]]#1 : index
-// CHECK: %[[PAD_IDX1:.*]] = arith.addi %[[VAL_54]], %[[VAL_4]] overflow<nuw> : index
+// CHECK: %[[PAD_IDX1:.*]] = arith.addi %[[VAL_54]], %[[VAL_4]] overflow<nsw, nuw> : index
// CHECK: %[[VAL_56:.*]] = arith.remui %[[VAL_55]], %[[PAD_DIM2]]#1 : index
-// CHECK: %[[PAD_IDX2:.*]] = arith.addi %[[VAL_56]], %[[VAL_4]] overflow<nuw> : index
+// CHECK: %[[PAD_IDX2:.*]] = arith.addi %[[VAL_56]], %[[VAL_4]] overflow<nsw, nuw> : index
// CHECK: %[[VAL_58:.*]]:3 = fir.box_dims %[[VAL_2]], %[[VAL_5]] : (!fir.box<!fir.array<?x?x?xf32>>, index) -> (index, index, index)
// CHECK: %[[VAL_59:.*]]:3 = fir.box_dims %[[VAL_2]], %[[VAL_4]] : (!fir.box<!fir.array<?x?x?xf32>>, index) -> (index, index, index)
// CHECK: %[[VAL_60:.*]]:3 = fir.box_dims %[[VAL_2]], %[[VAL_3]] : (!fir.box<!fir.array<?x?x?xf32>>, index) -> (index, index, index)
-// CHECK: %[[VAL_61:.*]] = arith.subi %[[VAL_58]]#0, %[[VAL_4]] overflow<nuw> : index
-// CHECK: %[[VAL_62:.*]] = arith.addi %[[PAD_IDX0]], %[[VAL_61]] overflow<nuw> : index
-// CHECK: %[[VAL_63:.*]] = arith.subi %[[VAL_59]]#0, %[[VAL_4]] overflow<nuw> : index
-// CHECK: %[[VAL_64:.*]] = arith.addi %[[PAD_IDX1]], %[[VAL_63]] overflow<nuw> : index
-// CHECK: %[[VAL_65:.*]] = arith.subi %[[VAL_60]]#0, %[[VAL_4]] overflow<nuw> : index
-// CHECK: %[[VAL_66:.*]] = arith.addi %[[PAD_IDX2]], %[[VAL_65]] overflow<nuw> : index
+// CHECK: %[[VAL_61:.*]] = arith.subi %[[VAL_58]]#0, %[[VAL_4]] overflow<nsw> : index
+// CHECK: %[[VAL_62:.*]] = arith.addi %[[PAD_IDX0]], %[[VAL_61]] overflow<nsw> : index
+// CHECK: %[[VAL_63:.*]] = arith.subi %[[VAL_59]]#0, %[[VAL_4]] overflow<nsw> : index
+// CHECK: %[[VAL_64:.*]] = arith.addi %[[PAD_IDX1]], %[[VAL_63]] overflow<nsw> : index
+// CHECK: %[[VAL_65:.*]] = arith.subi %[[VAL_60]]#0, %[[VAL_4]] overflow<nsw> : index
+// CHECK: %[[VAL_66:.*]] = arith.addi %[[PAD_IDX2]], %[[VAL_65]] overflow<nsw> : index
// CHECK: %[[VAL_67:.*]] = hlfir.designate %[[VAL_2]] (%[[VAL_62]], %[[VAL_64]], %[[VAL_66]]) : (!fir.box<!fir.array<?x?x?xf32>>, index, index, index) -> !fir.ref<f32>
// CHECK: %[[VAL_68:.*]] = fir.load %[[VAL_67]] : !fir.ref<f32>
// CHECK: fir.result %[[VAL_68]] : f32
@@ -158,8 +158,8 @@ func.func @reshape_poly_obj(%arg0: !fir.class<!fir.array<?x!fir.type<whatever>>>
// CHECK: %[[VAL_7:.*]] = hlfir.elemental %[[VAL_6]] mold %[[VAL_0]] unordered : (!fir.shape<1>, !fir.class<!fir.array<?x!fir.type<whatever>>>) -> !hlfir.expr<?x!fir.type<whatever>?> {
// CHECK: ^bb0(%[[VAL_8:.*]]: index):
// CHECK: %[[VAL_9:.*]]:3 = fir.box_dims %[[VAL_0]], %[[VAL_3]] : (!fir.class<!fir.array<?x!fir.type<whatever>>>, index) -> (index, index, index)
-// CHECK: %[[VAL_10:.*]] = arith.subi %[[VAL_9]]#0, %[[VAL_2]] overflow<nuw> : index
-// CHECK: %[[VAL_11:.*]] = arith.addi %[[VAL_8]], %[[VAL_10]] overflow<nuw> : index
+// CHECK: %[[VAL_10:.*]] = arith.subi %[[VAL_9]]#0, %[[VAL_2]] overflow<nsw> : index
+// CHECK: %[[VAL_11:.*]] = arith.addi %[[VAL_8]], %[[VAL_10]] overflow<nsw> : index
// CHECK: %[[VAL_12:.*]] = hlfir.designate %[[VAL_0]] (%[[VAL_11]]) : (!fir.class<!fir.array<?x!fir.type<whatever>>>, index) -> !fir.class<!fir.type<whatever>>
// CHECK: hlfir.yield_element %[[VAL_12]] : !fir.class<!fir.type<whatever>>
// CHECK: }
@@ -205,14 +205,45 @@ func.func @reshape_char(%arg0: !fir.box<!fir.array<?x!fir.char<2,?>>>, %arg1: !f
// CHECK: %[[VAL_12:.*]] = fir.box_elesize %[[VAL_0]] : (!fir.box<!fir.array<?x!fir.char<2,?>>>) -> index
// CHECK: %[[VAL_13:.*]] = arith.divsi %[[VAL_12]], %[[VAL_4]] : index
// CHECK: %[[VAL_14:.*]]:3 = fir.box_dims %[[VAL_0]], %[[VAL_3]] : (!fir.box<!fir.array<?x!fir.char<2,?>>>, index) -> (index, index, index)
-// CHECK: %[[VAL_15:.*]] = arith.subi %[[VAL_14]]#0, %[[VAL_2]] overflow<nuw> : index
-// CHECK: %[[VAL_16:.*]] = arith.addi %[[VAL_11]], %[[VAL_15]] overflow<nuw> : index
+// CHECK: %[[VAL_15:.*]] = arith.subi %[[VAL_14]]#0, %[[VAL_2]] overflow<nsw> : index
+// CHECK: %[[VAL_16:.*]] = arith.addi %[[VAL_11]], %[[VAL_15]] overflow<nsw> : index
// CHECK: %[[VAL_17:.*]] = hlfir.designate %[[VAL_0]] (%[[VAL_16]]) typeparams %[[VAL_13]] : (!fir.box<!fir.array<?x!fir.char<2,?>>>, index, index) -> !fir.boxchar<2>
// CHECK: hlfir.yield_element %[[VAL_17]] : !fir.boxchar<2>
// CHECK: }
// CHECK: return %[[VAL_10]] : !hlfir.expr<?x!fir.char<2,?>>
// CHECK: }
+// The lower bounds of ARRAY and SHAPE may be zero or negative, so
+// the index computations involving them must not be nuw.
+func.func @reshape_zero_lbounds(%arg0: !fir.ref<!fir.array<4xi32>>, %arg1: !fir.ref<!fir.array<1xi32>>) -> !hlfir.expr<?xi32> {
+ %c0 = arith.constant 0 : index
+ %c1 = arith.constant 1 : index
+ %c4 = arith.constant 4 : index
+ %array_shape = fir.shape_shift %c0, %c4 : (index, index) -> !fir.shapeshift<1>
+ %array:2 = hlfir.declare %arg0(%array_shape) uniq_name("array") : (!fir.ref<!fir.array<4xi32>>, !fir.shapeshift<1>) -> (!fir.box<!fir.array<4xi32>>, !fir.ref<!fir.array<4xi32>>)
+ %shape_shape = fir.shape_shift %c0, %c1 : (index, index) -> !fir.shapeshift<1>
+ %shape:2 = hlfir.declare %arg1(%shape_shape) uniq_name("shape") : (!fir.ref<!fir.array<1xi32>>, !fir.shapeshift<1>) -> (!fir.box<!fir.array<1xi32>>, !fir.ref<!fir.array<1xi32>>)
+ %res = hlfir.reshape %array#0 %shape#0 : (!fir.box<!fir.array<4xi32>>, !fir.box<!fir.array<1xi32>>) -> !hlfir.expr<?xi32>
+ return %res : !hlfir.expr<?xi32>
+}
+// CHECK-LABEL: func.func @reshape_zero_lbounds(
+// CHECK: %[[VAL_0:.*]] = arith.constant -1 : index
+// CHECK: %[[VAL_1:.*]] = arith.constant 0 : index
+// CHECK: %[[ARRAY:.*]]:2 = hlfir.declare {{.*}}uniq_name("array")
+// CHECK: %[[SHAPE:.*]]:2 = hlfir.declare {{.*}}uniq_name("shape")
+// CHECK: %[[VAL_2:.*]] = hlfir.designate %[[SHAPE]]#0 (%[[VAL_1]]) : (!fir.box<!fir.array<1xi32>>, index) -> !fir.ref<i32>
+// CHECK: %[[VAL_3:.*]] = fir.load %[[VAL_2]] : !fir.ref<i32>
+// CHECK: %[[VAL_4:.*]] = fir.shape %[[VAL_3]] : (i32) -> !fir.shape<1>
+// CHECK: %[[VAL_5:.*]] = hlfir.elemental %[[VAL_4]] unordered : (!fir.shape<1>) -> !hlfir.expr<?xi32> {
+// CHECK: ^bb0(%[[VAL_6:.*]]: index):
+// CHECK: %[[VAL_7:.*]] = arith.addi %[[VAL_6]], %[[VAL_0]] overflow<nsw> : index
+// CHECK: %[[VAL_8:.*]] = hlfir.designate %[[ARRAY]]#0 (%[[VAL_7]]) : (!fir.box<!fir.array<4xi32>>, index) -> !fir.ref<i32>
+// CHECK: %[[VAL_9:.*]] = fir.load %[[VAL_8]] : !fir.ref<i32>
+// CHECK: hlfir.yield_element %[[VAL_9]] : i32
+// CHECK: }
+// CHECK: return %[[VAL_5]] : !hlfir.expr<?xi32>
+// CHECK: }
+
func.func @reshape_negative_result_array_have_
diff erent_types(%arg0: !fir.box<!fir.array<?x!fir.char<2,1>>>, %arg1: !fir.ref<!fir.array<1xi32>>) -> !hlfir.expr<?x!fir.char<2,2>> {
%res = hlfir.reshape %arg0 %arg1 : (!fir.box<!fir.array<?x!fir.char<2,1>>>, !fir.ref<!fir.array<1xi32>>) -> !hlfir.expr<?x!fir.char<2,2>>
return %res : !hlfir.expr<?x!fir.char<2,2>>
More information about the flang-commits
mailing list