[flang-commits] [flang] [flang] add nsw to operations in subscripts (PR #110060)
Yusuke MINATO via flang-commits
flang-commits at lists.llvm.org
Wed Oct 2 17:04:48 PDT 2024
https://github.com/yus3710-fj updated https://github.com/llvm/llvm-project/pull/110060
>From 831ce62d8d778c69b0f6f714b52a5e31ea023160 Mon Sep 17 00:00:00 2001
From: Yusuke MINATO <minato.yusuke at fujitsu.com>
Date: Tue, 3 Sep 2024 18:28:26 +0900
Subject: [PATCH 1/4] [flang] add nsw to operations in subscripts
This patch adds nsw to operations when lowering subscripts.
See also the discussion in the following discourse post.
https://discourse.llvm.org/t/rfc-add-nsw-flags-to-arithmetic-integer-operations-using-the-option-fno-wrapv/77584/9
---
flang/docs/Extensions.md | 6 +
flang/include/flang/Lower/LoweringOptions.def | 5 +
.../flang/Optimizer/Builder/FIRBuilder.h | 21 ++-
flang/lib/Lower/ConvertCall.cpp | 17 ++
flang/lib/Lower/ConvertExpr.cpp | 20 ++-
flang/lib/Lower/ConvertExprToHLFIR.cpp | 25 ++-
flang/test/Lower/HLFIR/binary-ops.f90 | 27 +++
.../Lower/HLFIR/vector-subscript-as-value.f90 | 40 +++++
.../test/Lower/HLFIR/vector-subscript-lhs.f90 | 37 ++++
flang/test/Lower/Intrinsics/bge.f90 | 17 ++
flang/test/Lower/Intrinsics/bgt.f90 | 17 ++
flang/test/Lower/Intrinsics/ble.f90 | 17 ++
flang/test/Lower/Intrinsics/blt.f90 | 17 ++
flang/test/Lower/array.f90 | 162 ++++++++++++++++++
flang/test/Lower/forall/array-pointer.f90 | 54 +++++-
flang/tools/bbc/bbc.cpp | 7 +
16 files changed, 481 insertions(+), 8 deletions(-)
diff --git a/flang/docs/Extensions.md b/flang/docs/Extensions.md
index ed1ef49f8b77a5..3ffd2949e45bf4 100644
--- a/flang/docs/Extensions.md
+++ b/flang/docs/Extensions.md
@@ -780,6 +780,12 @@ character j
print *, [(j,j=1,10)]
```
+* The Fortran standard doesn't mention integer overflow explicitly. In many cases,
+ however, integer overflow makes programs non-conforming.
+ F18 follows other widely-used Fortran compilers. Specifically, f18 assumes
+ integer overflow never occurs in address calculations and increment of
+ do-variable unless the option `-fwrapv` is enabled.
+
## De Facto Standard Features
* `EXTENDS_TYPE_OF()` returns `.TRUE.` if both of its arguments have the
diff --git a/flang/include/flang/Lower/LoweringOptions.def b/flang/include/flang/Lower/LoweringOptions.def
index 7594a57a262914..1b24af5f97d1ee 100644
--- a/flang/include/flang/Lower/LoweringOptions.def
+++ b/flang/include/flang/Lower/LoweringOptions.def
@@ -34,8 +34,13 @@ ENUM_LOWERINGOPT(NoPPCNativeVecElemOrder, unsigned, 1, 0)
/// On by default.
ENUM_LOWERINGOPT(Underscoring, unsigned, 1, 1)
+/// If true, assume the behavior of integer overflow is defined
+/// (i.e. wraps around as two's complement). On by default.
+ENUM_LOWERINGOPT(IntegerWrapAround, unsigned, 1, 1)
+
/// If true, add nsw flags to loop variable increments.
/// Off by default.
+/// TODO: integrate this option with the above
ENUM_LOWERINGOPT(NSWOnLoopVarInc, unsigned, 1, 0)
#undef LOWERINGOPT
diff --git a/flang/include/flang/Optimizer/Builder/FIRBuilder.h b/flang/include/flang/Optimizer/Builder/FIRBuilder.h
index 180e2c8ab33ea2..09f7b892f1ecbe 100644
--- a/flang/include/flang/Optimizer/Builder/FIRBuilder.h
+++ b/flang/include/flang/Optimizer/Builder/FIRBuilder.h
@@ -85,13 +85,16 @@ class FirOpBuilder : public mlir::OpBuilder, public mlir::OpBuilder::Listener {
// The listener self-reference has to be updated in case of copy-construction.
FirOpBuilder(const FirOpBuilder &other)
: OpBuilder(other), OpBuilder::Listener(), kindMap{other.kindMap},
- fastMathFlags{other.fastMathFlags}, symbolTable{other.symbolTable} {
+ fastMathFlags{other.fastMathFlags},
+ integerOverflowFlags{other.integerOverflowFlags},
+ symbolTable{other.symbolTable} {
setListener(this);
}
FirOpBuilder(FirOpBuilder &&other)
: OpBuilder(other), OpBuilder::Listener(),
kindMap{std::move(other.kindMap)}, fastMathFlags{other.fastMathFlags},
+ integerOverflowFlags{other.integerOverflowFlags},
symbolTable{other.symbolTable} {
setListener(this);
}
@@ -521,6 +524,18 @@ class FirOpBuilder : public mlir::OpBuilder, public mlir::OpBuilder::Listener {
return fmfString;
}
+ /// Set default IntegerOverflowFlags value for all operations
+ /// supporting mlir::arith::IntegerOverflowFlagsAttr that will be created
+ /// by this builder.
+ void setIntegerOverflowFlags(mlir::arith::IntegerOverflowFlags flags) {
+ integerOverflowFlags = flags;
+ }
+
+ /// Get current IntegerOverflowFlags value.
+ mlir::arith::IntegerOverflowFlags getIntegerOverflowFlags() const {
+ return integerOverflowFlags;
+ }
+
/// Dump the current function. (debug)
LLVM_DUMP_METHOD void dumpFunc();
@@ -547,6 +562,10 @@ class FirOpBuilder : public mlir::OpBuilder, public mlir::OpBuilder::Listener {
/// mlir::arith::FastMathAttr.
mlir::arith::FastMathFlags fastMathFlags{};
+ /// IntegerOverflowFlags that need to be set for operations that support
+ /// mlir::arith::IntegerOverflowFlagsAttr.
+ mlir::arith::IntegerOverflowFlags integerOverflowFlags{};
+
/// fir::GlobalOp and func::FuncOp symbol table to speed-up
/// lookups.
mlir::SymbolTable *symbolTable = nullptr;
diff --git a/flang/lib/Lower/ConvertCall.cpp b/flang/lib/Lower/ConvertCall.cpp
index ee5eb225f0d7e3..59f29c409c799e 100644
--- a/flang/lib/Lower/ConvertCall.cpp
+++ b/flang/lib/Lower/ConvertCall.cpp
@@ -2570,9 +2570,26 @@ genIntrinsicRef(const Fortran::evaluate::SpecificIntrinsic *intrinsic,
hlfir::Entity{*var}, /*isPresent=*/std::nullopt});
continue;
}
+ // arguments of bitwise comparison functions may not have nsw flag
+ // even if -fno-wrapv is enabled
+ mlir::arith::IntegerOverflowFlags iofBackup{};
+ auto isBitwiseComparison = [](const std::string intrinsicName) -> bool {
+ if (intrinsicName == "bge" || intrinsicName == "bgt" ||
+ intrinsicName == "ble" || intrinsicName == "blt")
+ return true;
+ return false;
+ };
+ if (isBitwiseComparison(callContext.getProcedureName())) {
+ iofBackup = callContext.getBuilder().getIntegerOverflowFlags();
+ callContext.getBuilder().setIntegerOverflowFlags(
+ mlir::arith::IntegerOverflowFlags::none);
+ }
auto loweredActual = Fortran::lower::convertExprToHLFIR(
loc, callContext.converter, *expr, callContext.symMap,
callContext.stmtCtx);
+ if (isBitwiseComparison(callContext.getProcedureName()))
+ callContext.getBuilder().setIntegerOverflowFlags(iofBackup);
+
std::optional<mlir::Value> isPresent;
if (argLowering) {
fir::ArgLoweringRule argRules =
diff --git a/flang/lib/Lower/ConvertExpr.cpp b/flang/lib/Lower/ConvertExpr.cpp
index 62a7615e1af13c..dd8c43588b7018 100644
--- a/flang/lib/Lower/ConvertExpr.cpp
+++ b/flang/lib/Lower/ConvertExpr.cpp
@@ -1065,7 +1065,15 @@ class ScalarExprLowering {
mlir::Value lhs = fir::getBase(left);
mlir::Value rhs = fir::getBase(right);
assert(lhs.getType() == rhs.getType() && "types must be the same");
- return builder.create<OpTy>(getLoc(), lhs, rhs);
+ if constexpr (std::is_same_v<OpTy, mlir::arith::AddIOp> ||
+ std::is_same_v<OpTy, mlir::arith::SubIOp> ||
+ std::is_same_v<OpTy, mlir::arith::MulIOp>) {
+ auto iofAttr = mlir::arith::IntegerOverflowFlagsAttr::get(
+ builder.getContext(), builder.getIntegerOverflowFlags());
+ return builder.create<OpTy>(getLoc(), lhs, rhs, iofAttr);
+ } else {
+ return builder.create<OpTy>(getLoc(), lhs, rhs);
+ }
}
template <typename OpTy, typename A>
@@ -1397,7 +1405,15 @@ class ScalarExprLowering {
fir::emitFatalError(getLoc(), "subscript triple notation is not scalar");
}
ExtValue genSubscript(const Fortran::evaluate::Subscript &subs) {
- return genval(subs);
+ mlir::arith::IntegerOverflowFlags iofBackup{};
+ if (!converter.getLoweringOptions().getIntegerWrapAround()) {
+ iofBackup = builder.getIntegerOverflowFlags();
+ builder.setIntegerOverflowFlags(mlir::arith::IntegerOverflowFlags::nsw);
+ }
+ auto val = genval(subs);
+ if (!converter.getLoweringOptions().getIntegerWrapAround())
+ builder.setIntegerOverflowFlags(iofBackup);
+ return val;
}
ExtValue gen(const Fortran::evaluate::DataRef &dref) {
diff --git a/flang/lib/Lower/ConvertExprToHLFIR.cpp b/flang/lib/Lower/ConvertExprToHLFIR.cpp
index 1933f38f735b57..5db3b08afb7490 100644
--- a/flang/lib/Lower/ConvertExprToHLFIR.cpp
+++ b/flang/lib/Lower/ConvertExprToHLFIR.cpp
@@ -968,8 +968,17 @@ struct BinaryOp {};
fir::FirOpBuilder &builder, \
const Op &, hlfir::Entity lhs, \
hlfir::Entity rhs) { \
- return hlfir::EntityWithAttributes{ \
- builder.create<GenBinFirOp>(loc, lhs, rhs)}; \
+ if constexpr (std::is_same_v<GenBinFirOp, mlir::arith::AddIOp> || \
+ std::is_same_v<GenBinFirOp, mlir::arith::SubIOp> || \
+ std::is_same_v<GenBinFirOp, mlir::arith::MulIOp>) { \
+ auto iofAttr = mlir::arith::IntegerOverflowFlagsAttr::get( \
+ builder.getContext(), builder.getIntegerOverflowFlags()); \
+ return hlfir::EntityWithAttributes{ \
+ builder.create<GenBinFirOp>(loc, lhs, rhs, iofAttr)}; \
+ } else { \
+ return hlfir::EntityWithAttributes{ \
+ builder.create<GenBinFirOp>(loc, lhs, rhs)}; \
+ } \
} \
};
@@ -1584,9 +1593,12 @@ class HlfirBuilder {
auto rightVal = hlfir::loadTrivialScalar(l, b, rightElement);
return binaryOp.gen(l, b, op.derived(), leftVal, rightVal);
};
+ auto iofBackup = builder.getIntegerOverflowFlags();
+ builder.setIntegerOverflowFlags(mlir::arith::IntegerOverflowFlags::none);
mlir::Value elemental = hlfir::genElementalOp(loc, builder, elementType,
shape, typeParams, genKernel,
/*isUnordered=*/true);
+ builder.setIntegerOverflowFlags(iofBackup);
fir::FirOpBuilder *bldr = &builder;
getStmtCtx().attachCleanup(
[=]() { bldr->create<hlfir::DestroyOp>(loc, elemental); });
@@ -1899,10 +1911,17 @@ class HlfirBuilder {
template <typename T>
hlfir::Entity
HlfirDesignatorBuilder::genSubscript(const Fortran::evaluate::Expr<T> &expr) {
+ fir::FirOpBuilder &builder = getBuilder();
+ mlir::arith::IntegerOverflowFlags iofBackup{};
+ if (!getConverter().getLoweringOptions().getIntegerWrapAround()) {
+ iofBackup = builder.getIntegerOverflowFlags();
+ builder.setIntegerOverflowFlags(mlir::arith::IntegerOverflowFlags::nsw);
+ }
auto loweredExpr =
HlfirBuilder(getLoc(), getConverter(), getSymMap(), getStmtCtx())
.gen(expr);
- fir::FirOpBuilder &builder = getBuilder();
+ if (!getConverter().getLoweringOptions().getIntegerWrapAround())
+ builder.setIntegerOverflowFlags(iofBackup);
// Skip constant conversions that litters designators and makes generated
// IR harder to read: directly use index constants for constant subscripts.
mlir::Type idxTy = builder.getIndexType();
diff --git a/flang/test/Lower/HLFIR/binary-ops.f90 b/flang/test/Lower/HLFIR/binary-ops.f90
index 912cea0f5e0e66..20300cfce4aa5c 100644
--- a/flang/test/Lower/HLFIR/binary-ops.f90
+++ b/flang/test/Lower/HLFIR/binary-ops.f90
@@ -1,5 +1,6 @@
! Test lowering of binary intrinsic operations to HLFIR
! RUN: bbc -emit-hlfir -o - %s 2>&1 | FileCheck %s
+! RUN: bbc -emit-hlfir -o - -fwrapv %s 2>&1 | FileCheck %s --check-prefix=NO-NSW
subroutine int_add(x, y, z)
integer :: x, y, z
@@ -209,6 +210,32 @@ subroutine extremum(c, n, l)
! CHECK: %[[VAL_13:.*]] = arith.cmpi sgt, %[[VAL_11]], %[[VAL_12]] : i64
! CHECK: arith.select %[[VAL_13]], %[[VAL_11]], %[[VAL_12]] : i64
+subroutine subscript(a, i, j, k)
+ integer :: a(:,:,:), i, j, k
+ a(i+1, j-2, k*3) = 5
+end subroutine
+! CHECK-LABEL: func.func @_QPsubscript(
+! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %{{.*}}i"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>)
+! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %{{.*}}j"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>)
+! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %{{.*}}k"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>)
+! CHECK: %[[VAL_7:.*]] = fir.load %[[VAL_4]]#0 : !fir.ref<i32>
+! CHECK: %[[VAL_8:.*]] = arith.addi %[[VAL_7]], %c1{{[^ ]*}} overflow<nsw> : i32
+! CHECK: %[[VAL_9:.*]] = fir.load %[[VAL_5]]#0 : !fir.ref<i32>
+! CHECK: %[[VAL_10:.*]] = arith.subi %[[VAL_9]], %c2{{[^ ]*}} overflow<nsw> : i32
+! CHECK: %[[VAL_11:.*]] = fir.load %[[VAL_6]]#0 : !fir.ref<i32>
+! CHECK: %[[VAL_12:.*]] = arith.muli %c3{{[^ ]*}}, %[[VAL_11]] overflow<nsw> : i32
+
+! NO-NSW-LABEL: func.func @_QPsubscript(
+! NO-NSW: %[[VAL_4:.*]]:2 = hlfir.declare %{{.*}}i"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>)
+! NO-NSW: %[[VAL_5:.*]]:2 = hlfir.declare %{{.*}}j"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>)
+! NO-NSW: %[[VAL_6:.*]]:2 = hlfir.declare %{{.*}}k"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>)
+! NO-NSW: %[[VAL_7:.*]] = fir.load %[[VAL_4]]#0 : !fir.ref<i32>
+! NO-NSW: %[[VAL_8:.*]] = arith.addi %[[VAL_7]], %c1{{[^ ]*}} : i32
+! NO-NSW: %[[VAL_9:.*]] = fir.load %[[VAL_5]]#0 : !fir.ref<i32>
+! NO-NSW: %[[VAL_10:.*]] = arith.subi %[[VAL_9]], %c2{{[^ ]*}} : i32
+! NO-NSW: %[[VAL_11:.*]] = fir.load %[[VAL_6]]#0 : !fir.ref<i32>
+! NO-NSW: %[[VAL_12:.*]] = arith.muli %c3{{[^ ]*}}, %[[VAL_11]] : i32
+
subroutine cmp_int(l, x, y)
logical :: l
integer :: x, y
diff --git a/flang/test/Lower/HLFIR/vector-subscript-as-value.f90 b/flang/test/Lower/HLFIR/vector-subscript-as-value.f90
index 7161ee088b57a4..850ace1a8d9dec 100644
--- a/flang/test/Lower/HLFIR/vector-subscript-as-value.f90
+++ b/flang/test/Lower/HLFIR/vector-subscript-as-value.f90
@@ -1,6 +1,7 @@
! Test lowering of vector subscript designators outside of the
! assignment left-and side and input IO context.
! RUN: bbc -emit-hlfir -o - -I nw %s 2>&1 | FileCheck %s
+! RUN: bbc -emit-hlfir -o - -I nw -fwrapv %s 2>&1 | FileCheck %s
subroutine foo(x, y)
integer :: x(100)
@@ -150,6 +151,45 @@ subroutine foo4(at1, vector, i, j, k, l, step)
! CHECK: hlfir.yield_element %[[VAL_50]] : f32
! CHECK: }
+subroutine foo5(x, y, z)
+ integer :: x(100)
+ integer(8) :: y(20), z(20)
+ call bar(x(y+z))
+end subroutine
+! CHECK-LABEL: func.func @_QPfoo5(
+! CHECK: %[[VAL_3:.*]] = arith.constant 100 : index
+! CHECK: %[[VAL_4:.*]] = fir.shape %[[VAL_3]] : (index) -> !fir.shape<1>
+! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_0:[a-z0-9]*]](%[[VAL_4]]) {{.*}}Ex
+! CHECK: %[[VAL_6:.*]] = arith.constant 20 : index
+! CHECK: %[[VAL_7:.*]] = fir.shape %[[VAL_6]] : (index) -> !fir.shape<1>
+! CHECK: %[[VAL_8:.*]]:2 = hlfir.declare %[[VAL_1:[a-z0-9]*]](%[[VAL_7]]) {{.*}}Ey
+! CHECK: %[[VAL_9:.*]] = arith.constant 20 : index
+! CHECK: %[[VAL_10:.*]] = fir.shape %[[VAL_9]] : (index) -> !fir.shape<1>
+! CHECK: %[[VAL_11:.*]]:2 = hlfir.declare %[[VAL_2:[a-z0-9]*]](%[[VAL_10]]) {{.*}}Ez
+! CHECK: %[[VAL_12:.*]] = hlfir.elemental %[[VAL_7]] unordered : (!fir.shape<1>) -> !hlfir.expr<20xi64> {
+! CHECK: ^bb0(%[[VAL_13:.*]]: index):
+! CHECK: %[[VAL_14:.*]] = hlfir.designate %[[VAL_8]]#0 (%[[VAL_13]]) : (!fir.ref<!fir.array<20xi64>>, index) -> !fir.ref<i64>
+! CHECK: %[[VAL_15:.*]] = hlfir.designate %[[VAL_11]]#0 (%[[VAL_13]]) : (!fir.ref<!fir.array<20xi64>>, index) -> !fir.ref<i64>
+! CHECK: %[[VAL_16:.*]] = fir.load %[[VAL_14]] : !fir.ref<i64>
+! CHECK: %[[VAL_17:.*]] = fir.load %[[VAL_15]] : !fir.ref<i64>
+! CHECK: %[[VAL_18:.*]] = arith.addi %[[VAL_16]], %[[VAL_17]] : i64
+! CHECK: hlfir.yield_element %[[VAL_18]] : i64
+! CHECK: }
+! CHECK: %[[VAL_19:.*]] = arith.constant 20 : index
+! CHECK: %[[VAL_20:.*]] = fir.shape %[[VAL_19]] : (index) -> !fir.shape<1>
+! CHECK: %[[VAL_21:.*]] = hlfir.elemental %[[VAL_20]] unordered : (!fir.shape<1>) -> !hlfir.expr<20xi32> {
+! CHECK: ^bb0(%[[VAL_22:.*]]: index):
+! CHECK: %[[VAL_23:.*]] = hlfir.apply %[[VAL_12]], %[[VAL_22]] : (!hlfir.expr<20xi64>, index) -> i64
+! CHECK: %[[VAL_24:.*]] = hlfir.designate %[[VAL_5]]#0 (%[[VAL_23]]) : (!fir.ref<!fir.array<100xi32>>, i64) -> !fir.ref<i32>
+! CHECK: %[[VAL_25:.*]] = fir.load %[[VAL_24]] : !fir.ref<i32>
+! CHECK: hlfir.yield_element %[[VAL_25]] : i32
+! CHECK: }
+! CHECK: %[[VAL_26:.*]]:3 = hlfir.associate %[[VAL_21]](%[[VAL_20]]) {adapt.valuebyref} : (!hlfir.expr<20xi32>, !fir.shape<1>) -> (!fir.ref<!fir.array<20xi32>>, !fir.ref<!fir.array<20xi32>>, i1)
+! CHECK: fir.call @_QPbar(%[[VAL_26]]#1) fastmath<contract> : (!fir.ref<!fir.array<20xi32>>) -> ()
+! CHECK: hlfir.end_associate %[[VAL_26]]#1, %[[VAL_26]]#2 : !fir.ref<!fir.array<20xi32>>, i1
+! CHECK: hlfir.destroy %[[VAL_21]] : !hlfir.expr<20xi32>
+! CHECK: hlfir.destroy %[[VAL_12]] : !hlfir.expr<20xi64>
+
subroutine substring(c, vector, i, j)
character(*) :: c(:)
integer(8) :: vector(:), step, i, j
diff --git a/flang/test/Lower/HLFIR/vector-subscript-lhs.f90 b/flang/test/Lower/HLFIR/vector-subscript-lhs.f90
index 74236b39ebf4f6..1885e7c2fecb0b 100644
--- a/flang/test/Lower/HLFIR/vector-subscript-lhs.f90
+++ b/flang/test/Lower/HLFIR/vector-subscript-lhs.f90
@@ -1,6 +1,7 @@
! Test lowering of vector subscripted designators in assignment
! left-hand sides.
! RUN: bbc -emit-hlfir -o - -I nw %s 2>&1 | FileCheck %s
+! RUN: bbc -emit-hlfir -o - -I nw -fwrapv %s 2>&1 | FileCheck %s
subroutine test_simple(x, vector)
integer(8) :: vector(10)
@@ -97,6 +98,42 @@ subroutine test_nested_vectors(x, vector1, vector2, vector3)
! CHECK: }
! CHECK: }
+subroutine test_added_vectors(x, vector1, vector2)
+ integer(8) :: vector1(10), vector2(10)
+ real :: x(:)
+ x(vector1+vector2) = 42.
+end subroutine
+! CHECK-LABEL: func.func @_QPtest_added_vectors(
+! CHECK: %[[VAL_2:.*]] = arith.constant 10 : index
+! CHECK: %[[VAL_3:.*]] = fir.shape %[[VAL_2]] : (index) -> !fir.shape<1>
+! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare {{.*}}Evector1
+! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare {{.*}}Evector2
+! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare {{.*}}Ex
+! CHECK: hlfir.region_assign {
+! CHECK: %[[VAL_7:.*]] = arith.constant 4.200000e+01 : f32
+! CHECK: hlfir.yield %[[VAL_7]] : f32
+! CHECK: } to {
+! CHECK: %[[VAL_8:.*]] = hlfir.elemental %[[VAL_3]] unordered : (!fir.shape<1>) -> !hlfir.expr<10xi64> {
+! CHECK: ^bb0(%[[VAL_9:.*]]: index):
+! CHECK: %[[VAL_10:.*]] = hlfir.designate %[[VAL_4]]#0 (%[[VAL_9]]) : (!fir.ref<!fir.array<10xi64>>, index) -> !fir.ref<i64>
+! CHECK: %[[VAL_11:.*]] = hlfir.designate %[[VAL_5]]#0 (%[[VAL_9]]) : (!fir.ref<!fir.array<10xi64>>, index) -> !fir.ref<i64>
+! CHECK: %[[VAL_12:.*]] = fir.load %[[VAL_10]] : !fir.ref<i64>
+! CHECK: %[[VAL_13:.*]] = fir.load %[[VAL_11]] : !fir.ref<i64>
+! CHECK: %[[VAL_14:.*]] = arith.addi %[[VAL_12]], %[[VAL_13]] : i64
+! CHECK: hlfir.yield_element %[[VAL_14]] : i64
+! CHECK: }
+! CHECK: %[[VAL_27:.*]] = arith.constant 10 : index
+! CHECK: %[[VAL_28:.*]] = fir.shape %[[VAL_27]] : (index) -> !fir.shape<1>
+! CHECK: hlfir.elemental_addr %[[VAL_28]] unordered : !fir.shape<1> {
+! CHECK: ^bb0(%[[VAL_29:.*]]: index):
+! CHECK: %[[VAL_31:.*]] = hlfir.apply %[[VAL_8]], %[[VAL_29]] : (!hlfir.expr<10xi64>, index) -> i64
+! CHECK: %[[VAL_32:.*]] = hlfir.designate %[[VAL_6]]#0 (%[[VAL_31]]) : (!fir.box<!fir.array<?xf32>>, i64) -> !fir.ref<f32>
+! CHECK: hlfir.yield %[[VAL_32]] : !fir.ref<f32>
+! CHECK: } cleanup {
+! CHECK: hlfir.destroy %[[VAL_8]] : !hlfir.expr<10xi64>
+! CHECK: }
+! CHECK: }
+
subroutine test_substring(x, vector)
integer(8) :: vector(10), ifoo, ibar
external :: ifoo, ibar
diff --git a/flang/test/Lower/Intrinsics/bge.f90 b/flang/test/Lower/Intrinsics/bge.f90
index 19ddf7d95c3881..ccd5a7152f4fbb 100644
--- a/flang/test/Lower/Intrinsics/bge.f90
+++ b/flang/test/Lower/Intrinsics/bge.f90
@@ -156,3 +156,20 @@ subroutine bge_test11(c)
! CHECK: %[[V:.*]] = fir.convert %[[R]] : (i1) -> !fir.logical<4>
! CHECK: fir.store %[[V]] to %[[C]] : !fir.ref<!fir.logical<4>>
end subroutine bge_test11
+
+! CHECK-LABEL: bge_test12
+! CHECK-SAME: %[[A:.*]]: !fir.ref<i32>{{.*}}, %[[B:.*]]: !fir.ref<i32>{{.*}}, %[[C:.*]]: !fir.ref<!fir.logical<4>>{{.*}}
+subroutine bge_test12(a, b, c)
+ integer :: a, b
+ logical :: c
+ ! CHECK: %[[A_VAL:.*]] = fir.load %[[A]] : !fir.ref<i32>
+ ! CHECK: %[[B_VAL:.*]] = fir.load %[[B]] : !fir.ref<i32>
+ ! CHECK: %[[LHS:.*]] = arith.addi %[[A_VAL]], %[[B_VAL]] : i32
+ ! CHECK: %[[A_VAL2:.*]] = fir.load %[[A]] : !fir.ref<i32>
+ ! CHECK: %[[B_VAL2:.*]] = fir.load %[[B]] : !fir.ref<i32>
+ ! CHECK: %[[RHS:.*]] = arith.subi %[[A_VAL2]], %[[B_VAL2]] : i32
+ c = bge(a+b, a-b)
+ ! CHECK: %[[C_CMP:.*]] = arith.cmpi uge, %[[LHS]], %[[RHS]] : i32
+ ! CHECK: %[[C_VAL:.*]] = fir.convert %[[C_CMP]] : (i1) -> !fir.logical<4>
+ ! CHECK: fir.store %[[C_VAL]] to %[[C]] : !fir.ref<!fir.logical<4>>
+end subroutine bge_test12
diff --git a/flang/test/Lower/Intrinsics/bgt.f90 b/flang/test/Lower/Intrinsics/bgt.f90
index fea8611c17014e..18c2afeae13d8f 100644
--- a/flang/test/Lower/Intrinsics/bgt.f90
+++ b/flang/test/Lower/Intrinsics/bgt.f90
@@ -156,3 +156,20 @@ subroutine bgt_test11(c)
! CHECK: %[[V:.*]] = fir.convert %[[R]] : (i1) -> !fir.logical<4>
! CHECK: fir.store %[[V]] to %[[C]] : !fir.ref<!fir.logical<4>>
end subroutine bgt_test11
+
+! CHECK-LABEL: bgt_test12
+! CHECK-SAME: %[[A:.*]]: !fir.ref<i32>{{.*}}, %[[B:.*]]: !fir.ref<i32>{{.*}}, %[[C:.*]]: !fir.ref<!fir.logical<4>>{{.*}}
+subroutine bgt_test12(a, b, c)
+ integer :: a, b
+ logical :: c
+ ! CHECK: %[[A_VAL:.*]] = fir.load %[[A]] : !fir.ref<i32>
+ ! CHECK: %[[B_VAL:.*]] = fir.load %[[B]] : !fir.ref<i32>
+ ! CHECK: %[[LHS:.*]] = arith.addi %[[A_VAL]], %[[B_VAL]] : i32
+ ! CHECK: %[[A_VAL2:.*]] = fir.load %[[A]] : !fir.ref<i32>
+ ! CHECK: %[[B_VAL2:.*]] = fir.load %[[B]] : !fir.ref<i32>
+ ! CHECK: %[[RHS:.*]] = arith.subi %[[A_VAL2]], %[[B_VAL2]] : i32
+ c = bgt(a+b, a-b)
+ ! CHECK: %[[C_CMP:.*]] = arith.cmpi ugt, %[[LHS]], %[[RHS]] : i32
+ ! CHECK: %[[C_VAL:.*]] = fir.convert %[[C_CMP]] : (i1) -> !fir.logical<4>
+ ! CHECK: fir.store %[[C_VAL]] to %[[C]] : !fir.ref<!fir.logical<4>>
+end subroutine bgt_test12
diff --git a/flang/test/Lower/Intrinsics/ble.f90 b/flang/test/Lower/Intrinsics/ble.f90
index 1c996a963e4309..8a92efd3153dfb 100644
--- a/flang/test/Lower/Intrinsics/ble.f90
+++ b/flang/test/Lower/Intrinsics/ble.f90
@@ -156,3 +156,20 @@ subroutine ble_test11(c)
! CHECK: %[[V:.*]] = fir.convert %[[R]] : (i1) -> !fir.logical<4>
! CHECK: fir.store %[[V]] to %[[C]] : !fir.ref<!fir.logical<4>>
end subroutine ble_test11
+
+! CHECK-LABEL: ble_test12
+! CHECK-SAME: %[[A:.*]]: !fir.ref<i32>{{.*}}, %[[B:.*]]: !fir.ref<i32>{{.*}}, %[[C:.*]]: !fir.ref<!fir.logical<4>>{{.*}}
+subroutine ble_test12(a, b, c)
+ integer :: a, b
+ logical :: c
+ ! CHECK: %[[A_VAL:.*]] = fir.load %[[A]] : !fir.ref<i32>
+ ! CHECK: %[[B_VAL:.*]] = fir.load %[[B]] : !fir.ref<i32>
+ ! CHECK: %[[LHS:.*]] = arith.addi %[[A_VAL]], %[[B_VAL]] : i32
+ ! CHECK: %[[A_VAL2:.*]] = fir.load %[[A]] : !fir.ref<i32>
+ ! CHECK: %[[B_VAL2:.*]] = fir.load %[[B]] : !fir.ref<i32>
+ ! CHECK: %[[RHS:.*]] = arith.subi %[[A_VAL2]], %[[B_VAL2]] : i32
+ c = ble(a+b, a-b)
+ ! CHECK: %[[C_CMP:.*]] = arith.cmpi ule, %[[LHS]], %[[RHS]] : i32
+ ! CHECK: %[[C_VAL:.*]] = fir.convert %[[C_CMP]] : (i1) -> !fir.logical<4>
+ ! CHECK: fir.store %[[C_VAL]] to %[[C]] : !fir.ref<!fir.logical<4>>
+end subroutine ble_test12
diff --git a/flang/test/Lower/Intrinsics/blt.f90 b/flang/test/Lower/Intrinsics/blt.f90
index 06a57fb579e6bb..58f5fb12d0883e 100644
--- a/flang/test/Lower/Intrinsics/blt.f90
+++ b/flang/test/Lower/Intrinsics/blt.f90
@@ -156,3 +156,20 @@ subroutine blt_test11(c)
! CHECK: %[[V:.*]] = fir.convert %[[R]] : (i1) -> !fir.logical<4>
! CHECK: fir.store %[[V]] to %[[C]] : !fir.ref<!fir.logical<4>>
end subroutine blt_test11
+
+! CHECK-LABEL: blt_test12
+! CHECK-SAME: %[[A:.*]]: !fir.ref<i32>{{.*}}, %[[B:.*]]: !fir.ref<i32>{{.*}}, %[[C:.*]]: !fir.ref<!fir.logical<4>>{{.*}}
+subroutine blt_test12(a, b, c)
+ integer :: a, b
+ logical :: c
+ ! CHECK: %[[A_VAL:.*]] = fir.load %[[A]] : !fir.ref<i32>
+ ! CHECK: %[[B_VAL:.*]] = fir.load %[[B]] : !fir.ref<i32>
+ ! CHECK: %[[LHS:.*]] = arith.addi %[[A_VAL]], %[[B_VAL]] : i32
+ ! CHECK: %[[A_VAL2:.*]] = fir.load %[[A]] : !fir.ref<i32>
+ ! CHECK: %[[B_VAL2:.*]] = fir.load %[[B]] : !fir.ref<i32>
+ ! CHECK: %[[RHS:.*]] = arith.subi %[[A_VAL2]], %[[B_VAL2]] : i32
+ c = blt(a+b, a-b)
+ ! CHECK: %[[C_CMP:.*]] = arith.cmpi ult, %[[LHS]], %[[RHS]] : i32
+ ! CHECK: %[[C_VAL:.*]] = fir.convert %[[C_CMP]] : (i1) -> !fir.logical<4>
+ ! CHECK: fir.store %[[C_VAL]] to %[[C]] : !fir.ref<!fir.logical<4>>
+end subroutine blt_test12
diff --git a/flang/test/Lower/array.f90 b/flang/test/Lower/array.f90
index a2ab3d1384955b..f0c95d950766ca 100644
--- a/flang/test/Lower/array.f90
+++ b/flang/test/Lower/array.f90
@@ -1,4 +1,5 @@
! RUN: bbc -hlfir=false -o - %s | FileCheck %s
+! RUN: bbc -hlfir=false -fwrapv -o - %s | FileCheck %s --check-prefix=NO-NSW
! CHECK-LABEL: fir.global @block_
! CHECK-DAG: %[[VAL_1:.*]] = arith.constant 1.000000e+00 : f32
@@ -96,6 +97,167 @@ subroutine s(i,j,k,ii,jj,kk,a1,a2,a3,a4,a5,a6,a7)
end subroutine s
+! CHECK-LABEL: func.func @_QPs2
+! NO-NSW-LABEL: func.func @_QPs2
+subroutine s2(i,j,k,ii,jj,kk,a1,a2,a3,a4,a5,a6,a7)
+ integer i, j, k, ii, jj, kk
+
+ ! extents are compile-time constant
+ real a1(10,20)
+ integer a2(30,*)
+ real a3(2:40,3:50)
+ integer a4(4:60, 5:*)
+
+ ! extents computed at run-time
+ real a5(i:j)
+ integer a6(6:i,j:*)
+ real a7(i:70,7:j,k:80)
+
+ ! CHECK-LABEL: BeginExternalListOutput
+ ! CHECK: fir.load %arg3 :
+ ! CHECK: arith.subi %{{.*}}, %[[one32:c1[^ ]*]] overflow<nsw> : i32
+ ! CHECK: %[[i1:.*]] = arith.subi %{{.*}}, %[[one64:c1[^ ]*]] : i64
+ ! CHECK: fir.load %arg4 :
+ ! CHECK: arith.addi %{{.*}}, %[[one32]] overflow<nsw> : i32
+ ! CHECK: %[[j1:.*]] = arith.subi %{{.*}}, %[[one64]] : i64
+ ! CHECK: fir.coordinate_of %arg6, %[[i1]], %[[j1]] :
+ ! CHECK-LABEL: EndIoStatement
+
+ ! NO-NSW-LABEL: BeginExternalListOutput
+ ! NO-NSW: fir.load %arg3 :
+ ! NO-NSW: arith.subi %{{.*}}, %[[one32:c1[^ ]*]] : i32
+ ! NO-NSW: %[[i1:.*]] = arith.subi %{{.*}}, %[[one64:c1[^ ]*]] : i64
+ ! NO-NSW: fir.load %arg4 :
+ ! NO-NSW: arith.addi %{{.*}}, %[[one32]] : i32
+ ! NO-NSW: %[[j1:.*]] = arith.subi %{{.*}}, %[[one64]] : i64
+ ! NO-NSW: fir.coordinate_of %arg6, %[[i1]], %[[j1]] :
+ ! NO-NSW-LABEL: EndIoStatement
+ print *, a1(ii-1,jj+1)
+ ! CHECK-LABEL: BeginExternalListOutput
+ ! CHECK: arith.muli %{{.*}}, %[[two32:c2[^ ]*]] overflow<nsw> : i32
+ ! CHECK: fir.coordinate_of %{{[0-9]+}}, %{{[0-9]+}} : {{.*}} -> !fir.ref<i32>
+ ! CHECK-LABEL: EndIoStatement
+
+ ! NO-NSW-LABEL: BeginExternalListOutput
+ ! NO-NSW: arith.muli %{{.*}}, %[[two32:c2[^ ]*]] : i32
+ ! NO-NSW: fir.coordinate_of %{{[0-9]+}}, %{{[0-9]+}} : {{.*}} -> !fir.ref<i32>
+ ! NO-NSW-LABEL: EndIoStatement
+ print *, a2(ii,2*jj)
+ ! CHECK-LABEL: BeginExternalListOutput
+ ! CHECK: fir.load %arg3 :
+ ! CHECK: arith.subi %c40{{.*}}, %{{[^ ]*}} overflow<nsw> : i32
+ ! CHECK: %[[cc2:.*]] = fir.convert %c2{{.*}} :
+ ! CHECK: %[[i2:.*]] = arith.subi %{{.*}}, %[[cc2]] : i64
+ ! CHECK: fir.load %arg4 :
+ ! CHECK: arith.subi %{{.*}}, %[[three32:c3[^ ]*]] overflow<nsw> : i32
+ ! CHECK: %[[cc3:.*]] = fir.convert %c3{{.*}} :
+ ! CHECK: %[[j2:.*]] = arith.subi %{{.*}}, %[[cc3]] : i64
+ ! CHECK: fir.coordinate_of %arg8, %[[i2]], %[[j2]] :
+ ! CHECK-LABEL: EndIoStatement
+
+ ! NO-NSW-LABEL: BeginExternalListOutput
+ ! NO-NSW: fir.load %arg3 :
+ ! NO-NSW: arith.subi %c40{{.*}}, %{{[^ ]*}} : i32
+ ! NO-NSW: %[[cc2:.*]] = fir.convert %c2{{.*}} :
+ ! NO-NSW: %[[i2:.*]] = arith.subi %{{.*}}, %[[cc2]] : i64
+ ! NO-NSW: fir.load %arg4 :
+ ! NO-NSW: arith.subi %{{.*}}, %[[three32:c3[^ ]*]] : i32
+ ! NO-NSW: %[[cc3:.*]] = fir.convert %c3{{.*}} :
+ ! NO-NSW: %[[j2:.*]] = arith.subi %{{.*}}, %[[cc3]] : i64
+ ! NO-NSW: fir.coordinate_of %arg8, %[[i2]], %[[j2]] :
+ ! NO-NSW-LABEL: EndIoStatement
+ print *, a3(40-ii,jj-3)
+ ! CHECK-LABEL: BeginExternalListOutput
+ ! CHECK: arith.muli %{{.*}}, %[[two32]] overflow<nsw> : i32
+ ! CHECK: arith.subi %{{.*}}, %[[one32]] overflow<nsw> : i32
+ ! CHECK-LABEL: EndIoStatement
+
+ ! NO-NSW-LABEL: BeginExternalListOutput
+ ! NO-NSW: arith.muli %{{.*}}, %[[two32]] : i32
+ ! NO-NSW: arith.subi %{{.*}}, %[[one32]] : i32
+ ! NO-NSW-LABEL: EndIoStatement
+ print *, a4(ii*2,jj-1)
+ ! CHECK-LABEL: BeginExternalListOutput
+ ! CHECK: fir.load %arg5 :
+ ! CHECK: arith.addi %{{.*}}, %{{[^ ]*}} overflow<nsw> : i32
+ ! CHECK: %[[x5:.*]] = arith.subi %{{.*}}, %{{[^ ]*}} : i64
+ ! CHECK: fir.coordinate_of %arg10, %[[x5]] :
+ ! CHECK-LABEL: EndIoStatement
+
+ ! NO-NSW-LABEL: BeginExternalListOutput
+ ! NO-NSW: fir.load %arg5 :
+ ! NO-NSW: arith.addi %{{.*}}, %{{[^ ]*}} : i32
+ ! NO-NSW: %[[x5:.*]] = arith.subi %{{.*}}, %{{[^ ]*}} : i64
+ ! NO-NSW: fir.coordinate_of %arg10, %[[x5]] :
+ ! NO-NSW-LABEL: EndIoStatement
+ print *, a5(kk+i)
+ ! CHECK-LABEL: BeginExternalListOutput
+ ! CHECK: %[[a6:.*]] = fir.convert %arg11 : {{.*}} -> !fir.ref<!fir.array<?xi32>>
+ ! CHECK: fir.load %arg3 :
+ ! CHECK: arith.muli %{{.*}}, %{{[^ ]*}} overflow<nsw> : i32
+ ! CHECK: %[[x6:.*]] = arith.subi %{{.*}}, %{{[^ ]*}} : index
+ ! CHECK: fir.load %arg4 :
+ ! CHECK: arith.subi %{{.*}}, %{{[^ ]*}} overflow<nsw> : i32
+ ! CHECK: %[[y6:.*]] = arith.subi %{{.*}}, %{{[^ ]*}} : index
+ ! CHECK: %[[z6:.*]] = arith.muli %{{.}}, %[[y6]] : index
+ ! CHECK: %[[w6:.*]] = arith.addi %[[z6]], %[[x6]] : index
+ ! CHECK: fir.coordinate_of %[[a6]], %[[w6]] :
+ ! CHECK-LABEL: EndIoStatement
+
+ ! NO-NSW-LABEL: BeginExternalListOutput
+ ! NO-NSW: %[[a6:.*]] = fir.convert %arg11 : {{.*}} -> !fir.ref<!fir.array<?xi32>>
+ ! NO-NSW: fir.load %arg3 :
+ ! NO-NSW: arith.muli %{{.*}}, %{{[^ ]*}} : i32
+ ! NO-NSW: %[[x6:.*]] = arith.subi %{{.*}}, %{{[^ ]*}} : index
+ ! NO-NSW: fir.load %arg4 :
+ ! NO-NSW: arith.subi %{{.*}}, %{{[^ ]*}} : i32
+ ! NO-NSW: %[[y6:.*]] = arith.subi %{{.*}}, %{{[^ ]*}} : index
+ ! NO-NSW: %[[z6:.*]] = arith.muli %{{.}}, %[[y6]] : index
+ ! NO-NSW: %[[w6:.*]] = arith.addi %[[z6]], %[[x6]] : index
+ ! NO-NSW: fir.coordinate_of %[[a6]], %[[w6]] :
+ ! NO-NSW-LABEL: EndIoStatement
+ print *, a6(ii*i, jj-j)
+ ! CHECK-LABEL: BeginExternalListOutput
+ ! CHECK: %[[a7:.*]] = fir.convert %arg12 : {{.*}} -> !fir.ref<!fir.array<?xf32>>
+ ! CHECK: fir.load %arg5 :
+ ! CHECK: arith.addi %{{.*}}, %{{[^ ]*}} overflow<nsw> : i32
+ ! CHECK: %[[x7:.*]] = arith.subi %{{.*}}, %{{[^ ]*}} : index
+ ! CHECK: fir.load %arg4 :
+ ! CHECK: arith.subi %{{.*}}, %{{[^ ]*}} overflow<nsw> : i32
+ ! CHECK: %[[y7:.*]] = arith.subi %{{.*}}, %{{[^ ]*}} : index
+ ! CHECK: %[[z7:.*]] = arith.muli %[[u7:.*]], %[[y7]] : index
+ ! CHECK: %[[w7:.*]] = arith.addi %[[z7]], %[[x7]] : index
+ ! CHECK: %[[v7:.*]] = arith.muli %[[u7]], %{{.*}} : index
+ ! CHECK: fir.load %arg3 :
+ ! CHECK: arith.muli %{{.*}}, %{{[^ ]*}} overflow<nsw> : i32
+ ! CHECK: %[[r7:.*]] = arith.subi %{{.*}}, %{{[^ ]*}} : index
+ ! CHECK: %[[s7:.*]] = arith.muli %[[v7]], %[[r7]] : index
+ ! CHECK: %[[t7:.*]] = arith.addi %[[s7]], %[[w7]] : index
+ ! CHECK: fir.coordinate_of %[[a7]], %[[t7]] :
+ ! CHECK-LABEL: EndIoStatement
+
+ ! NO-NSW-LABEL: BeginExternalListOutput
+ ! NO-NSW: %[[a7:.*]] = fir.convert %arg12 : {{.*}} -> !fir.ref<!fir.array<?xf32>>
+ ! NO-NSW: fir.load %arg5 :
+ ! NO-NSW: arith.addi %{{.*}}, %{{[^ ]*}} : i32
+ ! NO-NSW: %[[x7:.*]] = arith.subi %{{.*}}, %{{[^ ]*}} : index
+ ! NO-NSW: fir.load %arg4 :
+ ! NO-NSW: arith.subi %{{.*}}, %{{[^ ]*}} : i32
+ ! NO-NSW: %[[y7:.*]] = arith.subi %{{.*}}, %{{[^ ]*}} : index
+ ! NO-NSW: %[[z7:.*]] = arith.muli %[[u7:.*]], %[[y7]] : index
+ ! NO-NSW: %[[w7:.*]] = arith.addi %[[z7]], %[[x7]] : index
+ ! NO-NSW: %[[v7:.*]] = arith.muli %[[u7]], %{{.*}} : index
+ ! NO-NSW: fir.load %arg3 :
+ ! NO-NSW: arith.muli %{{.*}}, %{{[^ ]*}} : i32
+ ! NO-NSW: %[[r7:.*]] = arith.subi %{{.*}}, %{{[^ ]*}} : index
+ ! NO-NSW: %[[s7:.*]] = arith.muli %[[v7]], %[[r7]] : index
+ ! NO-NSW: %[[t7:.*]] = arith.addi %[[s7]], %[[w7]] : index
+ ! NO-NSW: fir.coordinate_of %[[a7]], %[[t7]] :
+ ! NO-NSW-LABEL: EndIoStatement
+ print *, a7(kk+k, jj-j, ii*i)
+
+end subroutine s2
+
! CHECK-LABEL range
subroutine range()
! Compile-time initalized arrays
diff --git a/flang/test/Lower/forall/array-pointer.f90 b/flang/test/Lower/forall/array-pointer.f90
index 1e8f7a6a55002c..82adb6dad86b1d 100644
--- a/flang/test/Lower/forall/array-pointer.f90
+++ b/flang/test/Lower/forall/array-pointer.f90
@@ -7,6 +7,7 @@
! Fortran.
! RUN: bbc --use-desc-for-alloc=false -emit-fir -hlfir=false %s -o - | FileCheck %s
+! RUN: bbc --use-desc-for-alloc=false -emit-fir -hlfir=false -fwrapv %s -o - | FileCheck %s --check-prefix=NO-NSW
module array_of_pointer_test
type t
@@ -651,9 +652,9 @@ end subroutine s7
! CHECK: %[[VAL_15:.*]] = arith.constant 1 : index
! CHECK: %[[VAL_16:.*]] = fir.load %[[VAL_2]] : !fir.ref<i32>
! CHECK: %[[VAL_17:.*]] = arith.constant 1 : i32
-! CHECK: %[[VAL_18:.*]] = arith.addi %[[VAL_16]], %[[VAL_17]] : i32
+! CHECK: %[[VAL_18:.*]] = arith.addi %[[VAL_16]], %[[VAL_17]] overflow<nsw> : i32
! CHECK: %[[VAL_19:.*]] = fir.load %[[VAL_3]] : !fir.ref<i32>
-! CHECK: %[[VAL_20:.*]] = arith.subi %[[VAL_18]], %[[VAL_19]] : i32
+! CHECK: %[[VAL_20:.*]] = arith.subi %[[VAL_18]], %[[VAL_19]] overflow<nsw> : i32
! CHECK: %[[VAL_21:.*]] = fir.convert %[[VAL_20]] : (i32) -> i64
! CHECK: %[[VAL_22:.*]] = arith.constant 1 : i64
! CHECK: %[[VAL_23:.*]] = arith.subi %[[VAL_21]], %[[VAL_22]] : i64
@@ -682,6 +683,55 @@ end subroutine s7
! CHECK: return
! CHECK: }
+! NO-NSW-LABEL: func @_QPs7(
+! NO-NSW-SAME: %[[VAL_0:.*]]: !fir.box<!fir.array<?x!fir.type<_QMarray_of_pointer_testTt{ip:!fir.box<!fir.ptr<i32>>}>>> {fir.bindc_name = "x"},
+! NO-NSW-SAME: %[[VAL_1:.*]]: !fir.box<!fir.array<?xi32>> {fir.bindc_name = "y", fir.target},
+! NO-NSW-SAME: %[[VAL_2:.*]]: !fir.ref<i32> {fir.bindc_name = "n"}) {
+! NO-NSW: %[[VAL_3:.*]] = fir.alloca i32 {adapt.valuebyref, bindc_name = "i"}
+! NO-NSW: %[[VAL_4:.*]] = arith.constant 1 : i32
+! NO-NSW: %[[VAL_5:.*]] = fir.convert %[[VAL_4]] : (i32) -> index
+! NO-NSW: %[[VAL_6:.*]] = fir.load %[[VAL_2]] : !fir.ref<i32>
+! NO-NSW: %[[VAL_7:.*]] = fir.convert %[[VAL_6]] : (i32) -> index
+! NO-NSW: %[[VAL_8:.*]] = arith.constant 1 : index
+! NO-NSW: %[[VAL_9:.*]] = fir.array_load %[[VAL_0]] : (!fir.box<!fir.array<?x!fir.type<_QMarray_of_pointer_testTt{ip:!fir.box<!fir.ptr<i32>>}>>>) -> !fir.array<?x!fir.type<_QMarray_of_pointer_testTt{ip:!fir.box<!fir.ptr<i32>>}>>
+! NO-NSW: %[[VAL_10:.*]] = fir.array_load %[[VAL_1]] : (!fir.box<!fir.array<?xi32>>) -> !fir.array<?xi32>
+! NO-NSW: %[[VAL_11:.*]] = fir.do_loop %[[VAL_12:.*]] = %[[VAL_5]] to %[[VAL_7]] step %[[VAL_8]] unordered iter_args(%[[VAL_13:.*]] = %[[VAL_9]]) -> (!fir.array<?x!fir.type<_QMarray_of_pointer_testTt{ip:!fir.box<!fir.ptr<i32>>}>>) {
+! NO-NSW: %[[VAL_14:.*]] = fir.convert %[[VAL_12]] : (index) -> i32
+! NO-NSW: fir.store %[[VAL_14]] to %[[VAL_3]] : !fir.ref<i32>
+! NO-NSW: %[[VAL_15:.*]] = arith.constant 1 : index
+! NO-NSW: %[[VAL_16:.*]] = fir.load %[[VAL_2]] : !fir.ref<i32>
+! NO-NSW: %[[VAL_17:.*]] = arith.constant 1 : i32
+! NO-NSW: %[[VAL_18:.*]] = arith.addi %[[VAL_16]], %[[VAL_17]] : i32
+! NO-NSW: %[[VAL_19:.*]] = fir.load %[[VAL_3]] : !fir.ref<i32>
+! NO-NSW: %[[VAL_20:.*]] = arith.subi %[[VAL_18]], %[[VAL_19]] : i32
+! NO-NSW: %[[VAL_21:.*]] = fir.convert %[[VAL_20]] : (i32) -> i64
+! NO-NSW: %[[VAL_22:.*]] = arith.constant 1 : i64
+! NO-NSW: %[[VAL_23:.*]] = arith.subi %[[VAL_21]], %[[VAL_22]] : i64
+! NO-NSW: %[[VAL_24:.*]] = fir.coordinate_of %[[VAL_0]], %[[VAL_23]] : (!fir.box<!fir.array<?x!fir.type<_QMarray_of_pointer_testTt{ip:!fir.box<!fir.ptr<i32>>}>>>, i64) -> !fir.ref<!fir.type<_QMarray_of_pointer_testTt{ip:!fir.box<!fir.ptr<i32>>}>>
+! NO-NSW: %[[VAL_25:.*]] = fir.field_index ip, !fir.type<_QMarray_of_pointer_testTt{ip:!fir.box<!fir.ptr<i32>>}>
+! NO-NSW: %[[VAL_26:.*]] = fir.coordinate_of %[[VAL_24]], %[[VAL_25]] : (!fir.ref<!fir.type<_QMarray_of_pointer_testTt{ip:!fir.box<!fir.ptr<i32>>}>>, !fir.field) -> !fir.ref<!fir.box<!fir.ptr<i32>>>
+! NO-NSW: %[[VAL_27:.*]] = fir.load %[[VAL_26]] : !fir.ref<!fir.box<!fir.ptr<i32>>>
+! NO-NSW: %[[VAL_28:.*]] = fir.box_addr %[[VAL_27]] : (!fir.box<!fir.ptr<i32>>) -> !fir.ptr<i32>
+! NO-NSW: %[[VAL_29:.*]] = fir.load %[[VAL_28]] : !fir.ptr<i32>
+! NO-NSW: %[[VAL_30:.*]] = fir.convert %[[VAL_29]] : (i32) -> i64
+! NO-NSW: %[[VAL_31:.*]] = fir.convert %[[VAL_30]] : (i64) -> index
+! NO-NSW: %[[VAL_32:.*]] = arith.subi %[[VAL_31]], %[[VAL_15]] : index
+! NO-NSW: %[[VAL_33:.*]] = fir.array_access %[[VAL_10]], %[[VAL_32]] : (!fir.array<?xi32>, index) -> !fir.ref<i32>
+! NO-NSW: %[[VAL_34:.*]] = fir.convert %[[VAL_33]] : (!fir.ref<i32>) -> !fir.ptr<i32>
+! NO-NSW: %[[VAL_35:.*]] = fir.embox %[[VAL_34]] : (!fir.ptr<i32>) -> !fir.box<!fir.ptr<i32>>
+! NO-NSW: %[[VAL_36:.*]] = arith.constant 1 : index
+! NO-NSW: %[[VAL_37:.*]] = fir.load %[[VAL_3]] : !fir.ref<i32>
+! NO-NSW: %[[VAL_38:.*]] = fir.convert %[[VAL_37]] : (i32) -> i64
+! NO-NSW: %[[VAL_39:.*]] = fir.convert %[[VAL_38]] : (i64) -> index
+! NO-NSW: %[[VAL_40:.*]] = arith.subi %[[VAL_39]], %[[VAL_36]] : index
+! NO-NSW: %[[VAL_41:.*]] = fir.field_index ip, !fir.type<_QMarray_of_pointer_testTt{ip:!fir.box<!fir.ptr<i32>>}>
+! NO-NSW: %[[VAL_42:.*]] = fir.array_update %[[VAL_13]], %[[VAL_35]], %[[VAL_40]], %[[VAL_41]] : (!fir.array<?x!fir.type<_QMarray_of_pointer_testTt{ip:!fir.box<!fir.ptr<i32>>}>>, !fir.box<!fir.ptr<i32>>, index, !fir.field) -> !fir.array<?x!fir.type<_QMarray_of_pointer_testTt{ip:!fir.box<!fir.ptr<i32>>}>>
+! NO-NSW: fir.result %[[VAL_42]] : !fir.array<?x!fir.type<_QMarray_of_pointer_testTt{ip:!fir.box<!fir.ptr<i32>>}>>
+! NO-NSW: }
+! NO-NSW: fir.array_merge_store %[[VAL_9]], %[[VAL_43:.*]] to %[[VAL_0]] : !fir.array<?x!fir.type<_QMarray_of_pointer_testTt{ip:!fir.box<!fir.ptr<i32>>}>>, !fir.array<?x!fir.type<_QMarray_of_pointer_testTt{ip:!fir.box<!fir.ptr<i32>>}>>, !fir.box<!fir.array<?x!fir.type<_QMarray_of_pointer_testTt{ip:!fir.box<!fir.ptr<i32>>}>>>
+! NO-NSW: return
+! NO-NSW: }
+
subroutine s8(x,y,n)
use array_of_pointer_test
type(ta) x(:)
diff --git a/flang/tools/bbc/bbc.cpp b/flang/tools/bbc/bbc.cpp
index 0a008d577cc255..3a05f5f9844875 100644
--- a/flang/tools/bbc/bbc.cpp
+++ b/flang/tools/bbc/bbc.cpp
@@ -228,6 +228,12 @@ static llvm::cl::opt<std::string>
llvm::cl::desc("Override host target triple"),
llvm::cl::init(""));
+static llvm::cl::opt<bool> integerWrapAround(
+ "fwrapv",
+ llvm::cl::desc("Treat signed integer overflow as two's complement"),
+ llvm::cl::init(false));
+
+// TODO: integrate this option with the above
static llvm::cl::opt<bool>
setNSW("integer-overflow",
llvm::cl::desc("add nsw flag to internal operations"),
@@ -373,6 +379,7 @@ static llvm::LogicalResult convertFortranSourceToMLIR(
Fortran::lower::LoweringOptions loweringOptions{};
loweringOptions.setNoPPCNativeVecElemOrder(enableNoPPCNativeVecElemOrder);
loweringOptions.setLowerToHighLevelFIR(useHLFIR || emitHLFIR);
+ loweringOptions.setIntegerWrapAround(integerWrapAround);
loweringOptions.setNSWOnLoopVarInc(setNSW);
std::vector<Fortran::lower::EnvironmentDefault> envDefaults = {};
constexpr const char *tuneCPU = "";
>From 2559ee1982f8f7de115cf0603c5393a0b012c11d Mon Sep 17 00:00:00 2001
From: Yusuke MINATO <minato.yusuke at fujitsu.com>
Date: Fri, 27 Sep 2024 11:45:05 +0900
Subject: [PATCH 2/4] remove the implementation for non HLFIR lowering and move
tests for new file
---
flang/lib/Lower/ConvertExpr.cpp | 20 +--
flang/test/Lower/HLFIR/binary-ops.f90 | 27 ---
.../Lower/HLFIR/vector-subscript-as-value.f90 | 40 -----
.../test/Lower/HLFIR/vector-subscript-lhs.f90 | 37 ----
flang/test/Lower/Intrinsics/bge.f90 | 17 --
flang/test/Lower/Intrinsics/bgt.f90 | 17 --
flang/test/Lower/Intrinsics/ble.f90 | 17 --
flang/test/Lower/Intrinsics/blt.f90 | 17 --
flang/test/Lower/array.f90 | 162 ------------------
flang/test/Lower/forall/array-pointer.f90 | 54 +-----
flang/test/Lower/nsw.f90 | 61 +++++++
11 files changed, 65 insertions(+), 404 deletions(-)
create mode 100644 flang/test/Lower/nsw.f90
diff --git a/flang/lib/Lower/ConvertExpr.cpp b/flang/lib/Lower/ConvertExpr.cpp
index dd8c43588b7018..62a7615e1af13c 100644
--- a/flang/lib/Lower/ConvertExpr.cpp
+++ b/flang/lib/Lower/ConvertExpr.cpp
@@ -1065,15 +1065,7 @@ class ScalarExprLowering {
mlir::Value lhs = fir::getBase(left);
mlir::Value rhs = fir::getBase(right);
assert(lhs.getType() == rhs.getType() && "types must be the same");
- if constexpr (std::is_same_v<OpTy, mlir::arith::AddIOp> ||
- std::is_same_v<OpTy, mlir::arith::SubIOp> ||
- std::is_same_v<OpTy, mlir::arith::MulIOp>) {
- auto iofAttr = mlir::arith::IntegerOverflowFlagsAttr::get(
- builder.getContext(), builder.getIntegerOverflowFlags());
- return builder.create<OpTy>(getLoc(), lhs, rhs, iofAttr);
- } else {
- return builder.create<OpTy>(getLoc(), lhs, rhs);
- }
+ return builder.create<OpTy>(getLoc(), lhs, rhs);
}
template <typename OpTy, typename A>
@@ -1405,15 +1397,7 @@ class ScalarExprLowering {
fir::emitFatalError(getLoc(), "subscript triple notation is not scalar");
}
ExtValue genSubscript(const Fortran::evaluate::Subscript &subs) {
- mlir::arith::IntegerOverflowFlags iofBackup{};
- if (!converter.getLoweringOptions().getIntegerWrapAround()) {
- iofBackup = builder.getIntegerOverflowFlags();
- builder.setIntegerOverflowFlags(mlir::arith::IntegerOverflowFlags::nsw);
- }
- auto val = genval(subs);
- if (!converter.getLoweringOptions().getIntegerWrapAround())
- builder.setIntegerOverflowFlags(iofBackup);
- return val;
+ return genval(subs);
}
ExtValue gen(const Fortran::evaluate::DataRef &dref) {
diff --git a/flang/test/Lower/HLFIR/binary-ops.f90 b/flang/test/Lower/HLFIR/binary-ops.f90
index 20300cfce4aa5c..912cea0f5e0e66 100644
--- a/flang/test/Lower/HLFIR/binary-ops.f90
+++ b/flang/test/Lower/HLFIR/binary-ops.f90
@@ -1,6 +1,5 @@
! Test lowering of binary intrinsic operations to HLFIR
! RUN: bbc -emit-hlfir -o - %s 2>&1 | FileCheck %s
-! RUN: bbc -emit-hlfir -o - -fwrapv %s 2>&1 | FileCheck %s --check-prefix=NO-NSW
subroutine int_add(x, y, z)
integer :: x, y, z
@@ -210,32 +209,6 @@ subroutine extremum(c, n, l)
! CHECK: %[[VAL_13:.*]] = arith.cmpi sgt, %[[VAL_11]], %[[VAL_12]] : i64
! CHECK: arith.select %[[VAL_13]], %[[VAL_11]], %[[VAL_12]] : i64
-subroutine subscript(a, i, j, k)
- integer :: a(:,:,:), i, j, k
- a(i+1, j-2, k*3) = 5
-end subroutine
-! CHECK-LABEL: func.func @_QPsubscript(
-! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %{{.*}}i"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>)
-! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %{{.*}}j"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>)
-! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %{{.*}}k"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>)
-! CHECK: %[[VAL_7:.*]] = fir.load %[[VAL_4]]#0 : !fir.ref<i32>
-! CHECK: %[[VAL_8:.*]] = arith.addi %[[VAL_7]], %c1{{[^ ]*}} overflow<nsw> : i32
-! CHECK: %[[VAL_9:.*]] = fir.load %[[VAL_5]]#0 : !fir.ref<i32>
-! CHECK: %[[VAL_10:.*]] = arith.subi %[[VAL_9]], %c2{{[^ ]*}} overflow<nsw> : i32
-! CHECK: %[[VAL_11:.*]] = fir.load %[[VAL_6]]#0 : !fir.ref<i32>
-! CHECK: %[[VAL_12:.*]] = arith.muli %c3{{[^ ]*}}, %[[VAL_11]] overflow<nsw> : i32
-
-! NO-NSW-LABEL: func.func @_QPsubscript(
-! NO-NSW: %[[VAL_4:.*]]:2 = hlfir.declare %{{.*}}i"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>)
-! NO-NSW: %[[VAL_5:.*]]:2 = hlfir.declare %{{.*}}j"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>)
-! NO-NSW: %[[VAL_6:.*]]:2 = hlfir.declare %{{.*}}k"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>)
-! NO-NSW: %[[VAL_7:.*]] = fir.load %[[VAL_4]]#0 : !fir.ref<i32>
-! NO-NSW: %[[VAL_8:.*]] = arith.addi %[[VAL_7]], %c1{{[^ ]*}} : i32
-! NO-NSW: %[[VAL_9:.*]] = fir.load %[[VAL_5]]#0 : !fir.ref<i32>
-! NO-NSW: %[[VAL_10:.*]] = arith.subi %[[VAL_9]], %c2{{[^ ]*}} : i32
-! NO-NSW: %[[VAL_11:.*]] = fir.load %[[VAL_6]]#0 : !fir.ref<i32>
-! NO-NSW: %[[VAL_12:.*]] = arith.muli %c3{{[^ ]*}}, %[[VAL_11]] : i32
-
subroutine cmp_int(l, x, y)
logical :: l
integer :: x, y
diff --git a/flang/test/Lower/HLFIR/vector-subscript-as-value.f90 b/flang/test/Lower/HLFIR/vector-subscript-as-value.f90
index 850ace1a8d9dec..7161ee088b57a4 100644
--- a/flang/test/Lower/HLFIR/vector-subscript-as-value.f90
+++ b/flang/test/Lower/HLFIR/vector-subscript-as-value.f90
@@ -1,7 +1,6 @@
! Test lowering of vector subscript designators outside of the
! assignment left-and side and input IO context.
! RUN: bbc -emit-hlfir -o - -I nw %s 2>&1 | FileCheck %s
-! RUN: bbc -emit-hlfir -o - -I nw -fwrapv %s 2>&1 | FileCheck %s
subroutine foo(x, y)
integer :: x(100)
@@ -151,45 +150,6 @@ subroutine foo4(at1, vector, i, j, k, l, step)
! CHECK: hlfir.yield_element %[[VAL_50]] : f32
! CHECK: }
-subroutine foo5(x, y, z)
- integer :: x(100)
- integer(8) :: y(20), z(20)
- call bar(x(y+z))
-end subroutine
-! CHECK-LABEL: func.func @_QPfoo5(
-! CHECK: %[[VAL_3:.*]] = arith.constant 100 : index
-! CHECK: %[[VAL_4:.*]] = fir.shape %[[VAL_3]] : (index) -> !fir.shape<1>
-! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_0:[a-z0-9]*]](%[[VAL_4]]) {{.*}}Ex
-! CHECK: %[[VAL_6:.*]] = arith.constant 20 : index
-! CHECK: %[[VAL_7:.*]] = fir.shape %[[VAL_6]] : (index) -> !fir.shape<1>
-! CHECK: %[[VAL_8:.*]]:2 = hlfir.declare %[[VAL_1:[a-z0-9]*]](%[[VAL_7]]) {{.*}}Ey
-! CHECK: %[[VAL_9:.*]] = arith.constant 20 : index
-! CHECK: %[[VAL_10:.*]] = fir.shape %[[VAL_9]] : (index) -> !fir.shape<1>
-! CHECK: %[[VAL_11:.*]]:2 = hlfir.declare %[[VAL_2:[a-z0-9]*]](%[[VAL_10]]) {{.*}}Ez
-! CHECK: %[[VAL_12:.*]] = hlfir.elemental %[[VAL_7]] unordered : (!fir.shape<1>) -> !hlfir.expr<20xi64> {
-! CHECK: ^bb0(%[[VAL_13:.*]]: index):
-! CHECK: %[[VAL_14:.*]] = hlfir.designate %[[VAL_8]]#0 (%[[VAL_13]]) : (!fir.ref<!fir.array<20xi64>>, index) -> !fir.ref<i64>
-! CHECK: %[[VAL_15:.*]] = hlfir.designate %[[VAL_11]]#0 (%[[VAL_13]]) : (!fir.ref<!fir.array<20xi64>>, index) -> !fir.ref<i64>
-! CHECK: %[[VAL_16:.*]] = fir.load %[[VAL_14]] : !fir.ref<i64>
-! CHECK: %[[VAL_17:.*]] = fir.load %[[VAL_15]] : !fir.ref<i64>
-! CHECK: %[[VAL_18:.*]] = arith.addi %[[VAL_16]], %[[VAL_17]] : i64
-! CHECK: hlfir.yield_element %[[VAL_18]] : i64
-! CHECK: }
-! CHECK: %[[VAL_19:.*]] = arith.constant 20 : index
-! CHECK: %[[VAL_20:.*]] = fir.shape %[[VAL_19]] : (index) -> !fir.shape<1>
-! CHECK: %[[VAL_21:.*]] = hlfir.elemental %[[VAL_20]] unordered : (!fir.shape<1>) -> !hlfir.expr<20xi32> {
-! CHECK: ^bb0(%[[VAL_22:.*]]: index):
-! CHECK: %[[VAL_23:.*]] = hlfir.apply %[[VAL_12]], %[[VAL_22]] : (!hlfir.expr<20xi64>, index) -> i64
-! CHECK: %[[VAL_24:.*]] = hlfir.designate %[[VAL_5]]#0 (%[[VAL_23]]) : (!fir.ref<!fir.array<100xi32>>, i64) -> !fir.ref<i32>
-! CHECK: %[[VAL_25:.*]] = fir.load %[[VAL_24]] : !fir.ref<i32>
-! CHECK: hlfir.yield_element %[[VAL_25]] : i32
-! CHECK: }
-! CHECK: %[[VAL_26:.*]]:3 = hlfir.associate %[[VAL_21]](%[[VAL_20]]) {adapt.valuebyref} : (!hlfir.expr<20xi32>, !fir.shape<1>) -> (!fir.ref<!fir.array<20xi32>>, !fir.ref<!fir.array<20xi32>>, i1)
-! CHECK: fir.call @_QPbar(%[[VAL_26]]#1) fastmath<contract> : (!fir.ref<!fir.array<20xi32>>) -> ()
-! CHECK: hlfir.end_associate %[[VAL_26]]#1, %[[VAL_26]]#2 : !fir.ref<!fir.array<20xi32>>, i1
-! CHECK: hlfir.destroy %[[VAL_21]] : !hlfir.expr<20xi32>
-! CHECK: hlfir.destroy %[[VAL_12]] : !hlfir.expr<20xi64>
-
subroutine substring(c, vector, i, j)
character(*) :: c(:)
integer(8) :: vector(:), step, i, j
diff --git a/flang/test/Lower/HLFIR/vector-subscript-lhs.f90 b/flang/test/Lower/HLFIR/vector-subscript-lhs.f90
index 1885e7c2fecb0b..74236b39ebf4f6 100644
--- a/flang/test/Lower/HLFIR/vector-subscript-lhs.f90
+++ b/flang/test/Lower/HLFIR/vector-subscript-lhs.f90
@@ -1,7 +1,6 @@
! Test lowering of vector subscripted designators in assignment
! left-hand sides.
! RUN: bbc -emit-hlfir -o - -I nw %s 2>&1 | FileCheck %s
-! RUN: bbc -emit-hlfir -o - -I nw -fwrapv %s 2>&1 | FileCheck %s
subroutine test_simple(x, vector)
integer(8) :: vector(10)
@@ -98,42 +97,6 @@ subroutine test_nested_vectors(x, vector1, vector2, vector3)
! CHECK: }
! CHECK: }
-subroutine test_added_vectors(x, vector1, vector2)
- integer(8) :: vector1(10), vector2(10)
- real :: x(:)
- x(vector1+vector2) = 42.
-end subroutine
-! CHECK-LABEL: func.func @_QPtest_added_vectors(
-! CHECK: %[[VAL_2:.*]] = arith.constant 10 : index
-! CHECK: %[[VAL_3:.*]] = fir.shape %[[VAL_2]] : (index) -> !fir.shape<1>
-! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare {{.*}}Evector1
-! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare {{.*}}Evector2
-! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare {{.*}}Ex
-! CHECK: hlfir.region_assign {
-! CHECK: %[[VAL_7:.*]] = arith.constant 4.200000e+01 : f32
-! CHECK: hlfir.yield %[[VAL_7]] : f32
-! CHECK: } to {
-! CHECK: %[[VAL_8:.*]] = hlfir.elemental %[[VAL_3]] unordered : (!fir.shape<1>) -> !hlfir.expr<10xi64> {
-! CHECK: ^bb0(%[[VAL_9:.*]]: index):
-! CHECK: %[[VAL_10:.*]] = hlfir.designate %[[VAL_4]]#0 (%[[VAL_9]]) : (!fir.ref<!fir.array<10xi64>>, index) -> !fir.ref<i64>
-! CHECK: %[[VAL_11:.*]] = hlfir.designate %[[VAL_5]]#0 (%[[VAL_9]]) : (!fir.ref<!fir.array<10xi64>>, index) -> !fir.ref<i64>
-! CHECK: %[[VAL_12:.*]] = fir.load %[[VAL_10]] : !fir.ref<i64>
-! CHECK: %[[VAL_13:.*]] = fir.load %[[VAL_11]] : !fir.ref<i64>
-! CHECK: %[[VAL_14:.*]] = arith.addi %[[VAL_12]], %[[VAL_13]] : i64
-! CHECK: hlfir.yield_element %[[VAL_14]] : i64
-! CHECK: }
-! CHECK: %[[VAL_27:.*]] = arith.constant 10 : index
-! CHECK: %[[VAL_28:.*]] = fir.shape %[[VAL_27]] : (index) -> !fir.shape<1>
-! CHECK: hlfir.elemental_addr %[[VAL_28]] unordered : !fir.shape<1> {
-! CHECK: ^bb0(%[[VAL_29:.*]]: index):
-! CHECK: %[[VAL_31:.*]] = hlfir.apply %[[VAL_8]], %[[VAL_29]] : (!hlfir.expr<10xi64>, index) -> i64
-! CHECK: %[[VAL_32:.*]] = hlfir.designate %[[VAL_6]]#0 (%[[VAL_31]]) : (!fir.box<!fir.array<?xf32>>, i64) -> !fir.ref<f32>
-! CHECK: hlfir.yield %[[VAL_32]] : !fir.ref<f32>
-! CHECK: } cleanup {
-! CHECK: hlfir.destroy %[[VAL_8]] : !hlfir.expr<10xi64>
-! CHECK: }
-! CHECK: }
-
subroutine test_substring(x, vector)
integer(8) :: vector(10), ifoo, ibar
external :: ifoo, ibar
diff --git a/flang/test/Lower/Intrinsics/bge.f90 b/flang/test/Lower/Intrinsics/bge.f90
index ccd5a7152f4fbb..19ddf7d95c3881 100644
--- a/flang/test/Lower/Intrinsics/bge.f90
+++ b/flang/test/Lower/Intrinsics/bge.f90
@@ -156,20 +156,3 @@ subroutine bge_test11(c)
! CHECK: %[[V:.*]] = fir.convert %[[R]] : (i1) -> !fir.logical<4>
! CHECK: fir.store %[[V]] to %[[C]] : !fir.ref<!fir.logical<4>>
end subroutine bge_test11
-
-! CHECK-LABEL: bge_test12
-! CHECK-SAME: %[[A:.*]]: !fir.ref<i32>{{.*}}, %[[B:.*]]: !fir.ref<i32>{{.*}}, %[[C:.*]]: !fir.ref<!fir.logical<4>>{{.*}}
-subroutine bge_test12(a, b, c)
- integer :: a, b
- logical :: c
- ! CHECK: %[[A_VAL:.*]] = fir.load %[[A]] : !fir.ref<i32>
- ! CHECK: %[[B_VAL:.*]] = fir.load %[[B]] : !fir.ref<i32>
- ! CHECK: %[[LHS:.*]] = arith.addi %[[A_VAL]], %[[B_VAL]] : i32
- ! CHECK: %[[A_VAL2:.*]] = fir.load %[[A]] : !fir.ref<i32>
- ! CHECK: %[[B_VAL2:.*]] = fir.load %[[B]] : !fir.ref<i32>
- ! CHECK: %[[RHS:.*]] = arith.subi %[[A_VAL2]], %[[B_VAL2]] : i32
- c = bge(a+b, a-b)
- ! CHECK: %[[C_CMP:.*]] = arith.cmpi uge, %[[LHS]], %[[RHS]] : i32
- ! CHECK: %[[C_VAL:.*]] = fir.convert %[[C_CMP]] : (i1) -> !fir.logical<4>
- ! CHECK: fir.store %[[C_VAL]] to %[[C]] : !fir.ref<!fir.logical<4>>
-end subroutine bge_test12
diff --git a/flang/test/Lower/Intrinsics/bgt.f90 b/flang/test/Lower/Intrinsics/bgt.f90
index 18c2afeae13d8f..fea8611c17014e 100644
--- a/flang/test/Lower/Intrinsics/bgt.f90
+++ b/flang/test/Lower/Intrinsics/bgt.f90
@@ -156,20 +156,3 @@ subroutine bgt_test11(c)
! CHECK: %[[V:.*]] = fir.convert %[[R]] : (i1) -> !fir.logical<4>
! CHECK: fir.store %[[V]] to %[[C]] : !fir.ref<!fir.logical<4>>
end subroutine bgt_test11
-
-! CHECK-LABEL: bgt_test12
-! CHECK-SAME: %[[A:.*]]: !fir.ref<i32>{{.*}}, %[[B:.*]]: !fir.ref<i32>{{.*}}, %[[C:.*]]: !fir.ref<!fir.logical<4>>{{.*}}
-subroutine bgt_test12(a, b, c)
- integer :: a, b
- logical :: c
- ! CHECK: %[[A_VAL:.*]] = fir.load %[[A]] : !fir.ref<i32>
- ! CHECK: %[[B_VAL:.*]] = fir.load %[[B]] : !fir.ref<i32>
- ! CHECK: %[[LHS:.*]] = arith.addi %[[A_VAL]], %[[B_VAL]] : i32
- ! CHECK: %[[A_VAL2:.*]] = fir.load %[[A]] : !fir.ref<i32>
- ! CHECK: %[[B_VAL2:.*]] = fir.load %[[B]] : !fir.ref<i32>
- ! CHECK: %[[RHS:.*]] = arith.subi %[[A_VAL2]], %[[B_VAL2]] : i32
- c = bgt(a+b, a-b)
- ! CHECK: %[[C_CMP:.*]] = arith.cmpi ugt, %[[LHS]], %[[RHS]] : i32
- ! CHECK: %[[C_VAL:.*]] = fir.convert %[[C_CMP]] : (i1) -> !fir.logical<4>
- ! CHECK: fir.store %[[C_VAL]] to %[[C]] : !fir.ref<!fir.logical<4>>
-end subroutine bgt_test12
diff --git a/flang/test/Lower/Intrinsics/ble.f90 b/flang/test/Lower/Intrinsics/ble.f90
index 8a92efd3153dfb..1c996a963e4309 100644
--- a/flang/test/Lower/Intrinsics/ble.f90
+++ b/flang/test/Lower/Intrinsics/ble.f90
@@ -156,20 +156,3 @@ subroutine ble_test11(c)
! CHECK: %[[V:.*]] = fir.convert %[[R]] : (i1) -> !fir.logical<4>
! CHECK: fir.store %[[V]] to %[[C]] : !fir.ref<!fir.logical<4>>
end subroutine ble_test11
-
-! CHECK-LABEL: ble_test12
-! CHECK-SAME: %[[A:.*]]: !fir.ref<i32>{{.*}}, %[[B:.*]]: !fir.ref<i32>{{.*}}, %[[C:.*]]: !fir.ref<!fir.logical<4>>{{.*}}
-subroutine ble_test12(a, b, c)
- integer :: a, b
- logical :: c
- ! CHECK: %[[A_VAL:.*]] = fir.load %[[A]] : !fir.ref<i32>
- ! CHECK: %[[B_VAL:.*]] = fir.load %[[B]] : !fir.ref<i32>
- ! CHECK: %[[LHS:.*]] = arith.addi %[[A_VAL]], %[[B_VAL]] : i32
- ! CHECK: %[[A_VAL2:.*]] = fir.load %[[A]] : !fir.ref<i32>
- ! CHECK: %[[B_VAL2:.*]] = fir.load %[[B]] : !fir.ref<i32>
- ! CHECK: %[[RHS:.*]] = arith.subi %[[A_VAL2]], %[[B_VAL2]] : i32
- c = ble(a+b, a-b)
- ! CHECK: %[[C_CMP:.*]] = arith.cmpi ule, %[[LHS]], %[[RHS]] : i32
- ! CHECK: %[[C_VAL:.*]] = fir.convert %[[C_CMP]] : (i1) -> !fir.logical<4>
- ! CHECK: fir.store %[[C_VAL]] to %[[C]] : !fir.ref<!fir.logical<4>>
-end subroutine ble_test12
diff --git a/flang/test/Lower/Intrinsics/blt.f90 b/flang/test/Lower/Intrinsics/blt.f90
index 58f5fb12d0883e..06a57fb579e6bb 100644
--- a/flang/test/Lower/Intrinsics/blt.f90
+++ b/flang/test/Lower/Intrinsics/blt.f90
@@ -156,20 +156,3 @@ subroutine blt_test11(c)
! CHECK: %[[V:.*]] = fir.convert %[[R]] : (i1) -> !fir.logical<4>
! CHECK: fir.store %[[V]] to %[[C]] : !fir.ref<!fir.logical<4>>
end subroutine blt_test11
-
-! CHECK-LABEL: blt_test12
-! CHECK-SAME: %[[A:.*]]: !fir.ref<i32>{{.*}}, %[[B:.*]]: !fir.ref<i32>{{.*}}, %[[C:.*]]: !fir.ref<!fir.logical<4>>{{.*}}
-subroutine blt_test12(a, b, c)
- integer :: a, b
- logical :: c
- ! CHECK: %[[A_VAL:.*]] = fir.load %[[A]] : !fir.ref<i32>
- ! CHECK: %[[B_VAL:.*]] = fir.load %[[B]] : !fir.ref<i32>
- ! CHECK: %[[LHS:.*]] = arith.addi %[[A_VAL]], %[[B_VAL]] : i32
- ! CHECK: %[[A_VAL2:.*]] = fir.load %[[A]] : !fir.ref<i32>
- ! CHECK: %[[B_VAL2:.*]] = fir.load %[[B]] : !fir.ref<i32>
- ! CHECK: %[[RHS:.*]] = arith.subi %[[A_VAL2]], %[[B_VAL2]] : i32
- c = blt(a+b, a-b)
- ! CHECK: %[[C_CMP:.*]] = arith.cmpi ult, %[[LHS]], %[[RHS]] : i32
- ! CHECK: %[[C_VAL:.*]] = fir.convert %[[C_CMP]] : (i1) -> !fir.logical<4>
- ! CHECK: fir.store %[[C_VAL]] to %[[C]] : !fir.ref<!fir.logical<4>>
-end subroutine blt_test12
diff --git a/flang/test/Lower/array.f90 b/flang/test/Lower/array.f90
index f0c95d950766ca..a2ab3d1384955b 100644
--- a/flang/test/Lower/array.f90
+++ b/flang/test/Lower/array.f90
@@ -1,5 +1,4 @@
! RUN: bbc -hlfir=false -o - %s | FileCheck %s
-! RUN: bbc -hlfir=false -fwrapv -o - %s | FileCheck %s --check-prefix=NO-NSW
! CHECK-LABEL: fir.global @block_
! CHECK-DAG: %[[VAL_1:.*]] = arith.constant 1.000000e+00 : f32
@@ -97,167 +96,6 @@ subroutine s(i,j,k,ii,jj,kk,a1,a2,a3,a4,a5,a6,a7)
end subroutine s
-! CHECK-LABEL: func.func @_QPs2
-! NO-NSW-LABEL: func.func @_QPs2
-subroutine s2(i,j,k,ii,jj,kk,a1,a2,a3,a4,a5,a6,a7)
- integer i, j, k, ii, jj, kk
-
- ! extents are compile-time constant
- real a1(10,20)
- integer a2(30,*)
- real a3(2:40,3:50)
- integer a4(4:60, 5:*)
-
- ! extents computed at run-time
- real a5(i:j)
- integer a6(6:i,j:*)
- real a7(i:70,7:j,k:80)
-
- ! CHECK-LABEL: BeginExternalListOutput
- ! CHECK: fir.load %arg3 :
- ! CHECK: arith.subi %{{.*}}, %[[one32:c1[^ ]*]] overflow<nsw> : i32
- ! CHECK: %[[i1:.*]] = arith.subi %{{.*}}, %[[one64:c1[^ ]*]] : i64
- ! CHECK: fir.load %arg4 :
- ! CHECK: arith.addi %{{.*}}, %[[one32]] overflow<nsw> : i32
- ! CHECK: %[[j1:.*]] = arith.subi %{{.*}}, %[[one64]] : i64
- ! CHECK: fir.coordinate_of %arg6, %[[i1]], %[[j1]] :
- ! CHECK-LABEL: EndIoStatement
-
- ! NO-NSW-LABEL: BeginExternalListOutput
- ! NO-NSW: fir.load %arg3 :
- ! NO-NSW: arith.subi %{{.*}}, %[[one32:c1[^ ]*]] : i32
- ! NO-NSW: %[[i1:.*]] = arith.subi %{{.*}}, %[[one64:c1[^ ]*]] : i64
- ! NO-NSW: fir.load %arg4 :
- ! NO-NSW: arith.addi %{{.*}}, %[[one32]] : i32
- ! NO-NSW: %[[j1:.*]] = arith.subi %{{.*}}, %[[one64]] : i64
- ! NO-NSW: fir.coordinate_of %arg6, %[[i1]], %[[j1]] :
- ! NO-NSW-LABEL: EndIoStatement
- print *, a1(ii-1,jj+1)
- ! CHECK-LABEL: BeginExternalListOutput
- ! CHECK: arith.muli %{{.*}}, %[[two32:c2[^ ]*]] overflow<nsw> : i32
- ! CHECK: fir.coordinate_of %{{[0-9]+}}, %{{[0-9]+}} : {{.*}} -> !fir.ref<i32>
- ! CHECK-LABEL: EndIoStatement
-
- ! NO-NSW-LABEL: BeginExternalListOutput
- ! NO-NSW: arith.muli %{{.*}}, %[[two32:c2[^ ]*]] : i32
- ! NO-NSW: fir.coordinate_of %{{[0-9]+}}, %{{[0-9]+}} : {{.*}} -> !fir.ref<i32>
- ! NO-NSW-LABEL: EndIoStatement
- print *, a2(ii,2*jj)
- ! CHECK-LABEL: BeginExternalListOutput
- ! CHECK: fir.load %arg3 :
- ! CHECK: arith.subi %c40{{.*}}, %{{[^ ]*}} overflow<nsw> : i32
- ! CHECK: %[[cc2:.*]] = fir.convert %c2{{.*}} :
- ! CHECK: %[[i2:.*]] = arith.subi %{{.*}}, %[[cc2]] : i64
- ! CHECK: fir.load %arg4 :
- ! CHECK: arith.subi %{{.*}}, %[[three32:c3[^ ]*]] overflow<nsw> : i32
- ! CHECK: %[[cc3:.*]] = fir.convert %c3{{.*}} :
- ! CHECK: %[[j2:.*]] = arith.subi %{{.*}}, %[[cc3]] : i64
- ! CHECK: fir.coordinate_of %arg8, %[[i2]], %[[j2]] :
- ! CHECK-LABEL: EndIoStatement
-
- ! NO-NSW-LABEL: BeginExternalListOutput
- ! NO-NSW: fir.load %arg3 :
- ! NO-NSW: arith.subi %c40{{.*}}, %{{[^ ]*}} : i32
- ! NO-NSW: %[[cc2:.*]] = fir.convert %c2{{.*}} :
- ! NO-NSW: %[[i2:.*]] = arith.subi %{{.*}}, %[[cc2]] : i64
- ! NO-NSW: fir.load %arg4 :
- ! NO-NSW: arith.subi %{{.*}}, %[[three32:c3[^ ]*]] : i32
- ! NO-NSW: %[[cc3:.*]] = fir.convert %c3{{.*}} :
- ! NO-NSW: %[[j2:.*]] = arith.subi %{{.*}}, %[[cc3]] : i64
- ! NO-NSW: fir.coordinate_of %arg8, %[[i2]], %[[j2]] :
- ! NO-NSW-LABEL: EndIoStatement
- print *, a3(40-ii,jj-3)
- ! CHECK-LABEL: BeginExternalListOutput
- ! CHECK: arith.muli %{{.*}}, %[[two32]] overflow<nsw> : i32
- ! CHECK: arith.subi %{{.*}}, %[[one32]] overflow<nsw> : i32
- ! CHECK-LABEL: EndIoStatement
-
- ! NO-NSW-LABEL: BeginExternalListOutput
- ! NO-NSW: arith.muli %{{.*}}, %[[two32]] : i32
- ! NO-NSW: arith.subi %{{.*}}, %[[one32]] : i32
- ! NO-NSW-LABEL: EndIoStatement
- print *, a4(ii*2,jj-1)
- ! CHECK-LABEL: BeginExternalListOutput
- ! CHECK: fir.load %arg5 :
- ! CHECK: arith.addi %{{.*}}, %{{[^ ]*}} overflow<nsw> : i32
- ! CHECK: %[[x5:.*]] = arith.subi %{{.*}}, %{{[^ ]*}} : i64
- ! CHECK: fir.coordinate_of %arg10, %[[x5]] :
- ! CHECK-LABEL: EndIoStatement
-
- ! NO-NSW-LABEL: BeginExternalListOutput
- ! NO-NSW: fir.load %arg5 :
- ! NO-NSW: arith.addi %{{.*}}, %{{[^ ]*}} : i32
- ! NO-NSW: %[[x5:.*]] = arith.subi %{{.*}}, %{{[^ ]*}} : i64
- ! NO-NSW: fir.coordinate_of %arg10, %[[x5]] :
- ! NO-NSW-LABEL: EndIoStatement
- print *, a5(kk+i)
- ! CHECK-LABEL: BeginExternalListOutput
- ! CHECK: %[[a6:.*]] = fir.convert %arg11 : {{.*}} -> !fir.ref<!fir.array<?xi32>>
- ! CHECK: fir.load %arg3 :
- ! CHECK: arith.muli %{{.*}}, %{{[^ ]*}} overflow<nsw> : i32
- ! CHECK: %[[x6:.*]] = arith.subi %{{.*}}, %{{[^ ]*}} : index
- ! CHECK: fir.load %arg4 :
- ! CHECK: arith.subi %{{.*}}, %{{[^ ]*}} overflow<nsw> : i32
- ! CHECK: %[[y6:.*]] = arith.subi %{{.*}}, %{{[^ ]*}} : index
- ! CHECK: %[[z6:.*]] = arith.muli %{{.}}, %[[y6]] : index
- ! CHECK: %[[w6:.*]] = arith.addi %[[z6]], %[[x6]] : index
- ! CHECK: fir.coordinate_of %[[a6]], %[[w6]] :
- ! CHECK-LABEL: EndIoStatement
-
- ! NO-NSW-LABEL: BeginExternalListOutput
- ! NO-NSW: %[[a6:.*]] = fir.convert %arg11 : {{.*}} -> !fir.ref<!fir.array<?xi32>>
- ! NO-NSW: fir.load %arg3 :
- ! NO-NSW: arith.muli %{{.*}}, %{{[^ ]*}} : i32
- ! NO-NSW: %[[x6:.*]] = arith.subi %{{.*}}, %{{[^ ]*}} : index
- ! NO-NSW: fir.load %arg4 :
- ! NO-NSW: arith.subi %{{.*}}, %{{[^ ]*}} : i32
- ! NO-NSW: %[[y6:.*]] = arith.subi %{{.*}}, %{{[^ ]*}} : index
- ! NO-NSW: %[[z6:.*]] = arith.muli %{{.}}, %[[y6]] : index
- ! NO-NSW: %[[w6:.*]] = arith.addi %[[z6]], %[[x6]] : index
- ! NO-NSW: fir.coordinate_of %[[a6]], %[[w6]] :
- ! NO-NSW-LABEL: EndIoStatement
- print *, a6(ii*i, jj-j)
- ! CHECK-LABEL: BeginExternalListOutput
- ! CHECK: %[[a7:.*]] = fir.convert %arg12 : {{.*}} -> !fir.ref<!fir.array<?xf32>>
- ! CHECK: fir.load %arg5 :
- ! CHECK: arith.addi %{{.*}}, %{{[^ ]*}} overflow<nsw> : i32
- ! CHECK: %[[x7:.*]] = arith.subi %{{.*}}, %{{[^ ]*}} : index
- ! CHECK: fir.load %arg4 :
- ! CHECK: arith.subi %{{.*}}, %{{[^ ]*}} overflow<nsw> : i32
- ! CHECK: %[[y7:.*]] = arith.subi %{{.*}}, %{{[^ ]*}} : index
- ! CHECK: %[[z7:.*]] = arith.muli %[[u7:.*]], %[[y7]] : index
- ! CHECK: %[[w7:.*]] = arith.addi %[[z7]], %[[x7]] : index
- ! CHECK: %[[v7:.*]] = arith.muli %[[u7]], %{{.*}} : index
- ! CHECK: fir.load %arg3 :
- ! CHECK: arith.muli %{{.*}}, %{{[^ ]*}} overflow<nsw> : i32
- ! CHECK: %[[r7:.*]] = arith.subi %{{.*}}, %{{[^ ]*}} : index
- ! CHECK: %[[s7:.*]] = arith.muli %[[v7]], %[[r7]] : index
- ! CHECK: %[[t7:.*]] = arith.addi %[[s7]], %[[w7]] : index
- ! CHECK: fir.coordinate_of %[[a7]], %[[t7]] :
- ! CHECK-LABEL: EndIoStatement
-
- ! NO-NSW-LABEL: BeginExternalListOutput
- ! NO-NSW: %[[a7:.*]] = fir.convert %arg12 : {{.*}} -> !fir.ref<!fir.array<?xf32>>
- ! NO-NSW: fir.load %arg5 :
- ! NO-NSW: arith.addi %{{.*}}, %{{[^ ]*}} : i32
- ! NO-NSW: %[[x7:.*]] = arith.subi %{{.*}}, %{{[^ ]*}} : index
- ! NO-NSW: fir.load %arg4 :
- ! NO-NSW: arith.subi %{{.*}}, %{{[^ ]*}} : i32
- ! NO-NSW: %[[y7:.*]] = arith.subi %{{.*}}, %{{[^ ]*}} : index
- ! NO-NSW: %[[z7:.*]] = arith.muli %[[u7:.*]], %[[y7]] : index
- ! NO-NSW: %[[w7:.*]] = arith.addi %[[z7]], %[[x7]] : index
- ! NO-NSW: %[[v7:.*]] = arith.muli %[[u7]], %{{.*}} : index
- ! NO-NSW: fir.load %arg3 :
- ! NO-NSW: arith.muli %{{.*}}, %{{[^ ]*}} : i32
- ! NO-NSW: %[[r7:.*]] = arith.subi %{{.*}}, %{{[^ ]*}} : index
- ! NO-NSW: %[[s7:.*]] = arith.muli %[[v7]], %[[r7]] : index
- ! NO-NSW: %[[t7:.*]] = arith.addi %[[s7]], %[[w7]] : index
- ! NO-NSW: fir.coordinate_of %[[a7]], %[[t7]] :
- ! NO-NSW-LABEL: EndIoStatement
- print *, a7(kk+k, jj-j, ii*i)
-
-end subroutine s2
-
! CHECK-LABEL range
subroutine range()
! Compile-time initalized arrays
diff --git a/flang/test/Lower/forall/array-pointer.f90 b/flang/test/Lower/forall/array-pointer.f90
index 82adb6dad86b1d..1e8f7a6a55002c 100644
--- a/flang/test/Lower/forall/array-pointer.f90
+++ b/flang/test/Lower/forall/array-pointer.f90
@@ -7,7 +7,6 @@
! Fortran.
! RUN: bbc --use-desc-for-alloc=false -emit-fir -hlfir=false %s -o - | FileCheck %s
-! RUN: bbc --use-desc-for-alloc=false -emit-fir -hlfir=false -fwrapv %s -o - | FileCheck %s --check-prefix=NO-NSW
module array_of_pointer_test
type t
@@ -652,9 +651,9 @@ end subroutine s7
! CHECK: %[[VAL_15:.*]] = arith.constant 1 : index
! CHECK: %[[VAL_16:.*]] = fir.load %[[VAL_2]] : !fir.ref<i32>
! CHECK: %[[VAL_17:.*]] = arith.constant 1 : i32
-! CHECK: %[[VAL_18:.*]] = arith.addi %[[VAL_16]], %[[VAL_17]] overflow<nsw> : i32
+! CHECK: %[[VAL_18:.*]] = arith.addi %[[VAL_16]], %[[VAL_17]] : i32
! CHECK: %[[VAL_19:.*]] = fir.load %[[VAL_3]] : !fir.ref<i32>
-! CHECK: %[[VAL_20:.*]] = arith.subi %[[VAL_18]], %[[VAL_19]] overflow<nsw> : i32
+! CHECK: %[[VAL_20:.*]] = arith.subi %[[VAL_18]], %[[VAL_19]] : i32
! CHECK: %[[VAL_21:.*]] = fir.convert %[[VAL_20]] : (i32) -> i64
! CHECK: %[[VAL_22:.*]] = arith.constant 1 : i64
! CHECK: %[[VAL_23:.*]] = arith.subi %[[VAL_21]], %[[VAL_22]] : i64
@@ -683,55 +682,6 @@ end subroutine s7
! CHECK: return
! CHECK: }
-! NO-NSW-LABEL: func @_QPs7(
-! NO-NSW-SAME: %[[VAL_0:.*]]: !fir.box<!fir.array<?x!fir.type<_QMarray_of_pointer_testTt{ip:!fir.box<!fir.ptr<i32>>}>>> {fir.bindc_name = "x"},
-! NO-NSW-SAME: %[[VAL_1:.*]]: !fir.box<!fir.array<?xi32>> {fir.bindc_name = "y", fir.target},
-! NO-NSW-SAME: %[[VAL_2:.*]]: !fir.ref<i32> {fir.bindc_name = "n"}) {
-! NO-NSW: %[[VAL_3:.*]] = fir.alloca i32 {adapt.valuebyref, bindc_name = "i"}
-! NO-NSW: %[[VAL_4:.*]] = arith.constant 1 : i32
-! NO-NSW: %[[VAL_5:.*]] = fir.convert %[[VAL_4]] : (i32) -> index
-! NO-NSW: %[[VAL_6:.*]] = fir.load %[[VAL_2]] : !fir.ref<i32>
-! NO-NSW: %[[VAL_7:.*]] = fir.convert %[[VAL_6]] : (i32) -> index
-! NO-NSW: %[[VAL_8:.*]] = arith.constant 1 : index
-! NO-NSW: %[[VAL_9:.*]] = fir.array_load %[[VAL_0]] : (!fir.box<!fir.array<?x!fir.type<_QMarray_of_pointer_testTt{ip:!fir.box<!fir.ptr<i32>>}>>>) -> !fir.array<?x!fir.type<_QMarray_of_pointer_testTt{ip:!fir.box<!fir.ptr<i32>>}>>
-! NO-NSW: %[[VAL_10:.*]] = fir.array_load %[[VAL_1]] : (!fir.box<!fir.array<?xi32>>) -> !fir.array<?xi32>
-! NO-NSW: %[[VAL_11:.*]] = fir.do_loop %[[VAL_12:.*]] = %[[VAL_5]] to %[[VAL_7]] step %[[VAL_8]] unordered iter_args(%[[VAL_13:.*]] = %[[VAL_9]]) -> (!fir.array<?x!fir.type<_QMarray_of_pointer_testTt{ip:!fir.box<!fir.ptr<i32>>}>>) {
-! NO-NSW: %[[VAL_14:.*]] = fir.convert %[[VAL_12]] : (index) -> i32
-! NO-NSW: fir.store %[[VAL_14]] to %[[VAL_3]] : !fir.ref<i32>
-! NO-NSW: %[[VAL_15:.*]] = arith.constant 1 : index
-! NO-NSW: %[[VAL_16:.*]] = fir.load %[[VAL_2]] : !fir.ref<i32>
-! NO-NSW: %[[VAL_17:.*]] = arith.constant 1 : i32
-! NO-NSW: %[[VAL_18:.*]] = arith.addi %[[VAL_16]], %[[VAL_17]] : i32
-! NO-NSW: %[[VAL_19:.*]] = fir.load %[[VAL_3]] : !fir.ref<i32>
-! NO-NSW: %[[VAL_20:.*]] = arith.subi %[[VAL_18]], %[[VAL_19]] : i32
-! NO-NSW: %[[VAL_21:.*]] = fir.convert %[[VAL_20]] : (i32) -> i64
-! NO-NSW: %[[VAL_22:.*]] = arith.constant 1 : i64
-! NO-NSW: %[[VAL_23:.*]] = arith.subi %[[VAL_21]], %[[VAL_22]] : i64
-! NO-NSW: %[[VAL_24:.*]] = fir.coordinate_of %[[VAL_0]], %[[VAL_23]] : (!fir.box<!fir.array<?x!fir.type<_QMarray_of_pointer_testTt{ip:!fir.box<!fir.ptr<i32>>}>>>, i64) -> !fir.ref<!fir.type<_QMarray_of_pointer_testTt{ip:!fir.box<!fir.ptr<i32>>}>>
-! NO-NSW: %[[VAL_25:.*]] = fir.field_index ip, !fir.type<_QMarray_of_pointer_testTt{ip:!fir.box<!fir.ptr<i32>>}>
-! NO-NSW: %[[VAL_26:.*]] = fir.coordinate_of %[[VAL_24]], %[[VAL_25]] : (!fir.ref<!fir.type<_QMarray_of_pointer_testTt{ip:!fir.box<!fir.ptr<i32>>}>>, !fir.field) -> !fir.ref<!fir.box<!fir.ptr<i32>>>
-! NO-NSW: %[[VAL_27:.*]] = fir.load %[[VAL_26]] : !fir.ref<!fir.box<!fir.ptr<i32>>>
-! NO-NSW: %[[VAL_28:.*]] = fir.box_addr %[[VAL_27]] : (!fir.box<!fir.ptr<i32>>) -> !fir.ptr<i32>
-! NO-NSW: %[[VAL_29:.*]] = fir.load %[[VAL_28]] : !fir.ptr<i32>
-! NO-NSW: %[[VAL_30:.*]] = fir.convert %[[VAL_29]] : (i32) -> i64
-! NO-NSW: %[[VAL_31:.*]] = fir.convert %[[VAL_30]] : (i64) -> index
-! NO-NSW: %[[VAL_32:.*]] = arith.subi %[[VAL_31]], %[[VAL_15]] : index
-! NO-NSW: %[[VAL_33:.*]] = fir.array_access %[[VAL_10]], %[[VAL_32]] : (!fir.array<?xi32>, index) -> !fir.ref<i32>
-! NO-NSW: %[[VAL_34:.*]] = fir.convert %[[VAL_33]] : (!fir.ref<i32>) -> !fir.ptr<i32>
-! NO-NSW: %[[VAL_35:.*]] = fir.embox %[[VAL_34]] : (!fir.ptr<i32>) -> !fir.box<!fir.ptr<i32>>
-! NO-NSW: %[[VAL_36:.*]] = arith.constant 1 : index
-! NO-NSW: %[[VAL_37:.*]] = fir.load %[[VAL_3]] : !fir.ref<i32>
-! NO-NSW: %[[VAL_38:.*]] = fir.convert %[[VAL_37]] : (i32) -> i64
-! NO-NSW: %[[VAL_39:.*]] = fir.convert %[[VAL_38]] : (i64) -> index
-! NO-NSW: %[[VAL_40:.*]] = arith.subi %[[VAL_39]], %[[VAL_36]] : index
-! NO-NSW: %[[VAL_41:.*]] = fir.field_index ip, !fir.type<_QMarray_of_pointer_testTt{ip:!fir.box<!fir.ptr<i32>>}>
-! NO-NSW: %[[VAL_42:.*]] = fir.array_update %[[VAL_13]], %[[VAL_35]], %[[VAL_40]], %[[VAL_41]] : (!fir.array<?x!fir.type<_QMarray_of_pointer_testTt{ip:!fir.box<!fir.ptr<i32>>}>>, !fir.box<!fir.ptr<i32>>, index, !fir.field) -> !fir.array<?x!fir.type<_QMarray_of_pointer_testTt{ip:!fir.box<!fir.ptr<i32>>}>>
-! NO-NSW: fir.result %[[VAL_42]] : !fir.array<?x!fir.type<_QMarray_of_pointer_testTt{ip:!fir.box<!fir.ptr<i32>>}>>
-! NO-NSW: }
-! NO-NSW: fir.array_merge_store %[[VAL_9]], %[[VAL_43:.*]] to %[[VAL_0]] : !fir.array<?x!fir.type<_QMarray_of_pointer_testTt{ip:!fir.box<!fir.ptr<i32>>}>>, !fir.array<?x!fir.type<_QMarray_of_pointer_testTt{ip:!fir.box<!fir.ptr<i32>>}>>, !fir.box<!fir.array<?x!fir.type<_QMarray_of_pointer_testTt{ip:!fir.box<!fir.ptr<i32>>}>>>
-! NO-NSW: return
-! NO-NSW: }
-
subroutine s8(x,y,n)
use array_of_pointer_test
type(ta) x(:)
diff --git a/flang/test/Lower/nsw.f90 b/flang/test/Lower/nsw.f90
new file mode 100644
index 00000000000000..84435b71330427
--- /dev/null
+++ b/flang/test/Lower/nsw.f90
@@ -0,0 +1,61 @@
+! RUN: bbc -emit-fir %s -o - | FileCheck %s
+! RUN: bbc -emit-fir -fwrapv %s -o - | FileCheck %s --check-prefix=NO-NSW
+
+! NO-NSW-NOT: overflow<nsw>
+
+subroutine subscript(a, i, j, k)
+ integer :: a(:,:,:), i, j, k
+ a(i+1, j-2, k*3) = 5
+end subroutine
+! CHECK-LABEL: func.func @_QPsubscript(
+! CHECK: %[[VAL_4:.*]] = arith.constant 3 : i32
+! CHECK: %[[VAL_5:.*]] = arith.constant 2 : i32
+! CHECK: %[[VAL_6:.*]] = arith.constant 1 : i32
+! CHECK: %[[VAL_9:.*]] = fir.declare %{{.*}}a"} : (!fir.box<!fir.array<?x?x?xi32>>, !fir.dscope) -> !fir.box<!fir.array<?x?x?xi32>>
+! CHECK: %[[VAL_10:.*]] = fir.rebox %[[VAL_9]] : (!fir.box<!fir.array<?x?x?xi32>>) -> !fir.box<!fir.array<?x?x?xi32>>
+! CHECK: %[[VAL_11:.*]] = fir.declare %{{.*}}i"} : (!fir.ref<i32>, !fir.dscope) -> !fir.ref<i32>
+! CHECK: %[[VAL_12:.*]] = fir.declare %{{.*}}j"} : (!fir.ref<i32>, !fir.dscope) -> !fir.ref<i32>
+! CHECK: %[[VAL_13:.*]] = fir.declare %{{.*}}k"} : (!fir.ref<i32>, !fir.dscope) -> !fir.ref<i32>
+! CHECK: %[[VAL_14:.*]] = fir.load %[[VAL_11]] : !fir.ref<i32>
+! CHECK: %[[VAL_15:.*]] = arith.addi %[[VAL_14]], %[[VAL_6]] overflow<nsw> : i32
+! CHECK: %[[VAL_16:.*]] = fir.convert %[[VAL_15]] : (i32) -> i64
+! CHECK: %[[VAL_17:.*]] = fir.load %[[VAL_12]] : !fir.ref<i32>
+! CHECK: %[[VAL_18:.*]] = arith.subi %[[VAL_17]], %[[VAL_5]] overflow<nsw> : i32
+! CHECK: %[[VAL_19:.*]] = fir.convert %[[VAL_18]] : (i32) -> i64
+! CHECK: %[[VAL_20:.*]] = fir.load %[[VAL_13]] : !fir.ref<i32>
+! CHECK: %[[VAL_21:.*]] = arith.muli %[[VAL_20]], %[[VAL_4]] overflow<nsw> : i32
+! CHECK: %[[VAL_22:.*]] = fir.convert %[[VAL_21]] : (i32) -> i64
+! CHECK: %[[VAL_23:.*]] = fir.array_coor %[[VAL_10]] %[[VAL_16]], %[[VAL_19]], %[[VAL_22]] :
+
+! Test that nsw is never added to arith ops
+! on vector subscripts.
+subroutine vector_subscript_as_value(x, y, z)
+ integer :: x(100)
+ integer(8) :: y(20), z(20)
+ call bar(x(y+z))
+end subroutine
+! CHECK-LABEL: func.func @_QPvector_subscript_as_value(
+! CHECK-NOT: overflow<nsw>
+! CHECK: return
+
+subroutine vector_subscript_lhs(x, vector1, vector2)
+ integer(8) :: vector1(10), vector2(10)
+ real :: x(:)
+ x(vector1+vector2) = 42.
+end subroutine
+! CHECK-LABEL: func.func @_QPvector_subscript_lhs(
+! CHECK-NOT: overflow<nsw>
+! CHECK: return
+
+! Test that nsw is never added to arith ops
+! on arguments of bitwise comparison intrinsics.
+subroutine bitwise_comparison(a, b)
+ integer :: a, b
+ print *, bge(a+b, a-b)
+ print *, bgt(a+b, a-b)
+ print *, ble(a+b, a-b)
+ print *, blt(a+b, a-b)
+end subroutine
+! CHECK-LABEL: func.func @_QPbitwise_comparison(
+! CHECK-NOT: overflow<nsw>
+! CHECK: return
>From 6118e014cef3b6676aa48fcd2d3626ff2d903633 Mon Sep 17 00:00:00 2001
From: Yusuke MINATO <minato.yusuke at fujitsu.com>
Date: Fri, 27 Sep 2024 12:01:35 +0900
Subject: [PATCH 3/4] add some comments
---
flang/include/flang/Lower/LoweringOptions.def | 1 +
flang/lib/Lower/ConvertExprToHLFIR.cpp | 2 ++
2 files changed, 3 insertions(+)
diff --git a/flang/include/flang/Lower/LoweringOptions.def b/flang/include/flang/Lower/LoweringOptions.def
index 1b24af5f97d1ee..d3f17c3f939c16 100644
--- a/flang/include/flang/Lower/LoweringOptions.def
+++ b/flang/include/flang/Lower/LoweringOptions.def
@@ -36,6 +36,7 @@ ENUM_LOWERINGOPT(Underscoring, unsigned, 1, 1)
/// If true, assume the behavior of integer overflow is defined
/// (i.e. wraps around as two's complement). On by default.
+/// TODO: make the default off
ENUM_LOWERINGOPT(IntegerWrapAround, unsigned, 1, 1)
/// If true, add nsw flags to loop variable increments.
diff --git a/flang/lib/Lower/ConvertExprToHLFIR.cpp b/flang/lib/Lower/ConvertExprToHLFIR.cpp
index 5db3b08afb7490..c5379aeaf9f3d7 100644
--- a/flang/lib/Lower/ConvertExprToHLFIR.cpp
+++ b/flang/lib/Lower/ConvertExprToHLFIR.cpp
@@ -1594,6 +1594,8 @@ class HlfirBuilder {
return binaryOp.gen(l, b, op.derived(), leftVal, rightVal);
};
auto iofBackup = builder.getIntegerOverflowFlags();
+ // nsw is never added to operations on vector subscripts
+ // even if -fno-wrapv is enabled.
builder.setIntegerOverflowFlags(mlir::arith::IntegerOverflowFlags::none);
mlir::Value elemental = hlfir::genElementalOp(loc, builder, elementType,
shape, typeParams, genKernel,
>From 1874326c2930a6bace664142225fbaef73df1417 Mon Sep 17 00:00:00 2001
From: Yusuke MINATO <minato.yusuke at fujitsu.com>
Date: Tue, 1 Oct 2024 14:58:58 +0900
Subject: [PATCH 4/4] use `setCommonAttributes` rather than `gen`
---
flang/lib/Lower/ConvertExprToHLFIR.cpp | 13 +---
flang/lib/Optimizer/Builder/FIRBuilder.cpp | 25 +++++---
.../Optimizer/Builder/FIRBuilderTest.cpp | 59 +++++++++++++++++++
3 files changed, 78 insertions(+), 19 deletions(-)
diff --git a/flang/lib/Lower/ConvertExprToHLFIR.cpp b/flang/lib/Lower/ConvertExprToHLFIR.cpp
index c5379aeaf9f3d7..8a1effd75a492c 100644
--- a/flang/lib/Lower/ConvertExprToHLFIR.cpp
+++ b/flang/lib/Lower/ConvertExprToHLFIR.cpp
@@ -968,17 +968,8 @@ struct BinaryOp {};
fir::FirOpBuilder &builder, \
const Op &, hlfir::Entity lhs, \
hlfir::Entity rhs) { \
- if constexpr (std::is_same_v<GenBinFirOp, mlir::arith::AddIOp> || \
- std::is_same_v<GenBinFirOp, mlir::arith::SubIOp> || \
- std::is_same_v<GenBinFirOp, mlir::arith::MulIOp>) { \
- auto iofAttr = mlir::arith::IntegerOverflowFlagsAttr::get( \
- builder.getContext(), builder.getIntegerOverflowFlags()); \
- return hlfir::EntityWithAttributes{ \
- builder.create<GenBinFirOp>(loc, lhs, rhs, iofAttr)}; \
- } else { \
- return hlfir::EntityWithAttributes{ \
- builder.create<GenBinFirOp>(loc, lhs, rhs)}; \
- } \
+ return hlfir::EntityWithAttributes{ \
+ builder.create<GenBinFirOp>(loc, lhs, rhs)}; \
} \
};
diff --git a/flang/lib/Optimizer/Builder/FIRBuilder.cpp b/flang/lib/Optimizer/Builder/FIRBuilder.cpp
index 539235f01f5f74..9c26a36118557d 100644
--- a/flang/lib/Optimizer/Builder/FIRBuilder.cpp
+++ b/flang/lib/Optimizer/Builder/FIRBuilder.cpp
@@ -768,14 +768,23 @@ mlir::Value fir::FirOpBuilder::genAbsentOp(mlir::Location loc,
void fir::FirOpBuilder::setCommonAttributes(mlir::Operation *op) const {
auto fmi = mlir::dyn_cast<mlir::arith::ArithFastMathInterface>(*op);
- if (!fmi)
- return;
- // TODO: use fmi.setFastMathFlagsAttr() after D137114 is merged.
- // For now set the attribute by the name.
- llvm::StringRef arithFMFAttrName = fmi.getFastMathAttrName();
- if (fastMathFlags != mlir::arith::FastMathFlags::none)
- op->setAttr(arithFMFAttrName, mlir::arith::FastMathFlagsAttr::get(
- op->getContext(), fastMathFlags));
+ if (fmi) {
+ // TODO: use fmi.setFastMathFlagsAttr() after D137114 is merged.
+ // For now set the attribute by the name.
+ llvm::StringRef arithFMFAttrName = fmi.getFastMathAttrName();
+ if (fastMathFlags != mlir::arith::FastMathFlags::none)
+ op->setAttr(arithFMFAttrName, mlir::arith::FastMathFlagsAttr::get(
+ op->getContext(), fastMathFlags));
+ }
+ auto iofi =
+ mlir::dyn_cast<mlir::arith::ArithIntegerOverflowFlagsInterface>(*op);
+ if (iofi) {
+ llvm::StringRef arithIOFAttrName = iofi.getIntegerOverflowAttrName();
+ if (integerOverflowFlags != mlir::arith::IntegerOverflowFlags::none)
+ op->setAttr(arithIOFAttrName,
+ mlir::arith::IntegerOverflowFlagsAttr::get(
+ op->getContext(), integerOverflowFlags));
+ }
}
void fir::FirOpBuilder::setFastMathFlags(
diff --git a/flang/unittests/Optimizer/Builder/FIRBuilderTest.cpp b/flang/unittests/Optimizer/Builder/FIRBuilderTest.cpp
index e5e5454ee88ad2..f63afe41376838 100644
--- a/flang/unittests/Optimizer/Builder/FIRBuilderTest.cpp
+++ b/flang/unittests/Optimizer/Builder/FIRBuilderTest.cpp
@@ -585,3 +585,62 @@ TEST_F(FIRBuilderTest, genArithFastMath) {
auto op4_fmf = op4_fmi.getFastMathFlagsAttr().getValue();
EXPECT_EQ(op4_fmf, FMF1);
}
+
+TEST_F(FIRBuilderTest, genArithIntegerOverflow) {
+ auto builder = getBuilder();
+ auto ctx = builder.getContext();
+ auto loc = builder.getUnknownLoc();
+
+ auto intTy = IntegerType::get(ctx, 32);
+ auto arg = builder.create<fir::UndefOp>(loc, intTy);
+
+ // Test that IntegerOverflowFlags is 'none' by default.
+ mlir::Operation *op1 = builder.create<mlir::arith::AddIOp>(loc, arg, arg);
+ auto op1_iofi =
+ mlir::dyn_cast_or_null<mlir::arith::ArithIntegerOverflowFlagsInterface>(
+ op1);
+ EXPECT_TRUE(op1_iofi);
+ auto op1_ioff = op1_iofi.getOverflowAttr().getValue();
+ EXPECT_EQ(op1_ioff, arith::IntegerOverflowFlags::none);
+
+ // Test that the builder is copied properly.
+ fir::FirOpBuilder builder_copy(builder);
+
+ arith::IntegerOverflowFlags nsw = arith::IntegerOverflowFlags::nsw;
+ builder.setIntegerOverflowFlags(nsw);
+ arith::IntegerOverflowFlags nuw = arith::IntegerOverflowFlags::nuw;
+ builder_copy.setIntegerOverflowFlags(nuw);
+
+ // Modifying IntegerOverflowFlags for the copy must not affect the original
+ // builder.
+ mlir::Operation *op2 = builder.create<mlir::arith::AddIOp>(loc, arg, arg);
+ auto op2_iofi =
+ mlir::dyn_cast_or_null<mlir::arith::ArithIntegerOverflowFlagsInterface>(
+ op2);
+ EXPECT_TRUE(op2_iofi);
+ auto op2_ioff = op2_iofi.getOverflowAttr().getValue();
+ EXPECT_EQ(op2_ioff, nsw);
+
+ // Modifying IntegerOverflowFlags for the original builder must not affect the
+ // copy.
+ mlir::Operation *op3 =
+ builder_copy.create<mlir::arith::AddIOp>(loc, arg, arg);
+ auto op3_iofi =
+ mlir::dyn_cast_or_null<mlir::arith::ArithIntegerOverflowFlagsInterface>(
+ op3);
+ EXPECT_TRUE(op3_iofi);
+ auto op3_ioff = op3_iofi.getOverflowAttr().getValue();
+ EXPECT_EQ(op3_ioff, nuw);
+
+ // Test that the builder copy inherits IntegerOverflowFlags from the original.
+ fir::FirOpBuilder builder_copy2(builder);
+
+ mlir::Operation *op4 =
+ builder_copy2.create<mlir::arith::AddIOp>(loc, arg, arg);
+ auto op4_iofi =
+ mlir::dyn_cast_or_null<mlir::arith::ArithIntegerOverflowFlagsInterface>(
+ op4);
+ EXPECT_TRUE(op4_iofi);
+ auto op4_ioff = op4_iofi.getOverflowAttr().getValue();
+ EXPECT_EQ(op4_ioff, nsw);
+}
More information about the flang-commits
mailing list