[flang-commits] [flang] 20fba03 - [Flang] Add Any and All intrinsics to simplify intrinsics pass
Mats Petersson via flang-commits
flang-commits at lists.llvm.org
Thu Feb 9 11:53:10 PST 2023
Author: Sacha Ballantyne
Date: 2023-02-09T19:52:15Z
New Revision: 20fba03f96b43d4e6903e0a7c24ae7b665ab9a58
URL: https://github.com/llvm/llvm-project/commit/20fba03f96b43d4e6903e0a7c24ae7b665ab9a58
DIFF: https://github.com/llvm/llvm-project/commit/20fba03f96b43d4e6903e0a7c24ae7b665ab9a58.diff
LOG: [Flang] Add Any and All intrinsics to simplify intrinsics pass
This patch provides a simplified version of the Any intrinsic as well as the All intrinsic
that can be used for inlining or simpiler use cases. These changes are targeting exchange2, and
provide a ~9% performance increase.
Reviewed By: Leporacanthicus, vzakhari
Differential Revision: https://reviews.llvm.org/D142977
Added:
Modified:
flang/lib/Optimizer/Transforms/SimplifyIntrinsics.cpp
flang/test/Lower/array-derived.f90
flang/test/Transforms/simplifyintrinsics.fir
Removed:
################################################################################
diff --git a/flang/lib/Optimizer/Transforms/SimplifyIntrinsics.cpp b/flang/lib/Optimizer/Transforms/SimplifyIntrinsics.cpp
index de65c487a0348..89e6e0810e577 100644
--- a/flang/lib/Optimizer/Transforms/SimplifyIntrinsics.cpp
+++ b/flang/lib/Optimizer/Transforms/SimplifyIntrinsics.cpp
@@ -27,6 +27,7 @@
#include "flang/Optimizer/Builder/Todo.h"
#include "flang/Optimizer/Dialect/FIROps.h"
#include "flang/Optimizer/Dialect/FIRType.h"
+#include "flang/Optimizer/HLFIR/HLFIRDialect.h"
#include "flang/Optimizer/Support/FIRContext.h"
#include "flang/Optimizer/Transforms/Passes.h"
#include "flang/Runtime/entry-names.h"
@@ -39,6 +40,10 @@
#include "mlir/Transforms/RegionUtils.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
+#include <mlir/IR/Location.h>
+#include <mlir/IR/MLIRContext.h>
+#include <mlir/IR/Value.h>
+#include <mlir/Support/LLVM.h>
#include <optional>
namespace fir {
@@ -57,7 +62,8 @@ class SimplifyIntrinsicsPass
using FunctionBodyGeneratorTy =
llvm::function_ref<void(fir::FirOpBuilder &, mlir::func::FuncOp &)>;
using GenReductionBodyTy = llvm::function_ref<void(
- fir::FirOpBuilder &builder, mlir::func::FuncOp &funcOp, unsigned rank)>;
+ fir::FirOpBuilder &builder, mlir::func::FuncOp &funcOp, unsigned rank,
+ mlir::Type elementType)>;
public:
/// Generate a new function implementing a simplified version
@@ -82,13 +88,17 @@ class SimplifyIntrinsicsPass
void simplifyIntOrFloatReduction(fir::CallOp call,
const fir::KindMapping &kindMap,
GenReductionBodyTy genBodyFunc);
- void simplifyLogicalReduction(fir::CallOp call,
- const fir::KindMapping &kindMap,
- GenReductionBodyTy genBodyFunc);
+ void simplifyLogicalDim0Reduction(fir::CallOp call,
+ const fir::KindMapping &kindMap,
+ GenReductionBodyTy genBodyFunc);
+ void simplifyLogicalDim1Reduction(fir::CallOp call,
+ const fir::KindMapping &kindMap,
+ GenReductionBodyTy genBodyFunc);
void simplifyReductionBody(fir::CallOp call, const fir::KindMapping &kindMap,
GenReductionBodyTy genBodyFunc,
fir::FirOpBuilder &builder,
- const mlir::StringRef &basename);
+ const mlir::StringRef &basename,
+ mlir::Type elementType);
};
} // namespace
@@ -136,22 +146,30 @@ using BodyOpGeneratorTy = llvm::function_ref<mlir::Value(
mlir::Value)>;
using InitValGeneratorTy = llvm::function_ref<mlir::Value(
fir::FirOpBuilder &, mlir::Location, const mlir::Type &)>;
+using ContinueLoopGenTy = llvm::function_ref<llvm::SmallVector<mlir::Value>(
+ fir::FirOpBuilder &, mlir::Location, mlir::Value)>;
/// Generate the reduction loop into \p funcOp.
///
-/// \p elementType is the type of the elements in the input array,
-/// which may be
diff erent to the return type.
/// \p initVal is a function, called to get the initial value for
/// the reduction value
/// \p genBody is called to fill in the actual reduciton operation
/// for example add for SUM, MAX for MAXVAL, etc.
/// \p rank is the rank of the input argument.
-static void genReductionLoop(fir::FirOpBuilder &builder, mlir::Type elementType,
- mlir::func::FuncOp &funcOp,
- InitValGeneratorTy initVal,
- BodyOpGeneratorTy genBody, unsigned rank) {
- auto loc = mlir::UnknownLoc::get(builder.getContext());
- builder.setInsertionPointToEnd(funcOp.addEntryBlock());
+/// \p elementType is the type of the elements in the input array,
+/// which may be
diff erent to the return type.
+/// \p loopCond is called to generate the condition to continue or
+/// not for IterWhile loops
+/// \p unorderedOrInitalLoopCond contains either a boolean or bool
+/// mlir constant, and controls the inital value for while loops
+/// or if DoLoop is ordered/unordered.
+
+template <typename OP, typename T, int resultIndex>
+static void
+genReductionLoop(fir::FirOpBuilder &builder, mlir::func::FuncOp &funcOp,
+ InitValGeneratorTy initVal, ContinueLoopGenTy loopCond,
+ T unorderedOrInitialLoopCond, BodyOpGeneratorTy genBody,
+ unsigned rank, mlir::Type elementType, mlir::Location loc) {
mlir::IndexType idxTy = builder.getIndexType();
@@ -186,8 +204,7 @@ static void genReductionLoop(fir::FirOpBuilder &builder, mlir::Type elementType,
mlir::Value loopCount = builder.create<mlir::arith::SubIOp>(loc, len, one);
bounds.push_back(loopCount);
}
-
- // Create a loop nest consisting of DoLoopOp operations.
+ // Create a loop nest consisting of OP operations.
// Collect the loops' induction variables into indices array,
// which will be used in the innermost loop to load the input
// array's element.
@@ -197,9 +214,9 @@ static void genReductionLoop(fir::FirOpBuilder &builder, mlir::Type elementType,
for (unsigned i = rank; 0 < i; --i) {
mlir::Value step = one;
mlir::Value loopCount = bounds[i - 1];
- auto loop = builder.create<fir::DoLoopOp>(loc, zeroIdx, loopCount, step,
- /*unordered=*/false,
- /*finalCountValue=*/false, init);
+ auto loop = builder.create<OP>(loc, zeroIdx, loopCount, step,
+ unorderedOrInitialLoopCond,
+ /*finalCountValue=*/false, init);
init = loop.getRegionIterArgs()[0];
indices.push_back(loop.getInductionVar());
// Set insertion point to the loop body so that the next loop
@@ -210,31 +227,38 @@ static void genReductionLoop(fir::FirOpBuilder &builder, mlir::Type elementType,
// Reverse the indices such that they are ordered as:
// <dim-0-idx, dim-1-idx, ...>
std::reverse(indices.begin(), indices.end());
-
// We are in the innermost loop: generate the reduction body.
mlir::Type eleRefTy = builder.getRefType(elementType);
mlir::Value addr =
builder.create<fir::CoordinateOp>(loc, eleRefTy, array, indices);
mlir::Value elem = builder.create<fir::LoadOp>(loc, addr);
-
mlir::Value reductionVal = genBody(builder, loc, elementType, elem, init);
+ // Generate vector with condition to continue while loop at [0] and result
+ // from current loop at [1] for IterWhileOp loops, just result at [0] for
+ // DoLoopOp loops.
+ llvm::SmallVector<mlir::Value> results = loopCond(builder, loc, reductionVal);
// Unwind the loop nest and insert ResultOp on each level
// to return the updated value of the reduction to the enclosing
// loops.
for (unsigned i = 0; i < rank; ++i) {
- auto result = builder.create<fir::ResultOp>(loc, reductionVal);
+ auto result = builder.create<fir::ResultOp>(loc, results);
// Proceed to the outer loop.
- auto loop = mlir::cast<fir::DoLoopOp>(result->getParentOp());
- reductionVal = loop.getResult(0);
+ auto loop = mlir::cast<OP>(result->getParentOp());
+ results = loop.getResults();
// Set insertion point after the loop operation that we have
// just processed.
builder.setInsertionPointAfter(loop.getOperation());
}
-
// End of loop nest. The insertion point is after the outermost loop.
// Return the reduction value from the function.
- builder.create<mlir::func::ReturnOp>(loc, reductionVal);
+ builder.create<mlir::func::ReturnOp>(loc, results[resultIndex]);
+}
+
+static llvm::SmallVector<mlir::Value> nopLoopCond(fir::FirOpBuilder &builder,
+ mlir::Location,
+ mlir::Value reductionVal) {
+ return {reductionVal};
}
/// Generate function body of the simplified version of RTNAME(Sum)
@@ -243,7 +267,8 @@ static void genReductionLoop(fir::FirOpBuilder &builder, mlir::Type elementType,
/// \p funcOp is expected to be empty on entry to this function.
/// \p rank specifies the rank of the input argument.
static void genRuntimeSumBody(fir::FirOpBuilder &builder,
- mlir::func::FuncOp &funcOp, unsigned rank) {
+ mlir::func::FuncOp &funcOp, unsigned rank,
+ mlir::Type elementType) {
// function RTNAME(Sum)<T>x<rank>_simplified(arr)
// T, dimension(:) :: arr
// T sum = 0
@@ -275,13 +300,17 @@ static void genRuntimeSumBody(fir::FirOpBuilder &builder,
return {};
};
- mlir::Type elementType = funcOp.getResultTypes()[0];
+ mlir::Location loc = mlir::UnknownLoc::get(builder.getContext());
+ builder.setInsertionPointToEnd(funcOp.addEntryBlock());
- genReductionLoop(builder, elementType, funcOp, zero, genBodyOp, rank);
+ genReductionLoop<fir::DoLoopOp, bool, 0>(builder, funcOp, zero, nopLoopCond,
+ false, genBodyOp, rank, elementType,
+ loc);
}
static void genRuntimeMaxvalBody(fir::FirOpBuilder &builder,
- mlir::func::FuncOp &funcOp, unsigned rank) {
+ mlir::func::FuncOp &funcOp, unsigned rank,
+ mlir::Type elementType) {
auto init = [](fir::FirOpBuilder builder, mlir::Location loc,
mlir::Type elementType) {
if (auto ty = elementType.dyn_cast<mlir::FloatType>()) {
@@ -306,13 +335,17 @@ static void genRuntimeMaxvalBody(fir::FirOpBuilder &builder,
return {};
};
- mlir::Type elementType = funcOp.getResultTypes()[0];
+ mlir::Location loc = mlir::UnknownLoc::get(builder.getContext());
+ builder.setInsertionPointToEnd(funcOp.addEntryBlock());
- genReductionLoop(builder, elementType, funcOp, init, genBodyOp, rank);
+ genReductionLoop<fir::DoLoopOp, bool, 0>(builder, funcOp, init, nopLoopCond,
+ false, genBodyOp, rank, elementType,
+ loc);
}
static void genRuntimeCountBody(fir::FirOpBuilder &builder,
- mlir::func::FuncOp &funcOp, unsigned rank) {
+ mlir::func::FuncOp &funcOp, unsigned rank,
+ mlir::Type elementType) {
auto zero = [](fir::FirOpBuilder builder, mlir::Location loc,
mlir::Type elementType) {
unsigned bits = elementType.getIntOrFloatBitWidth();
@@ -334,9 +367,78 @@ static void genRuntimeCountBody(fir::FirOpBuilder &builder,
return builder.create<mlir::arith::AddIOp>(loc, select, elem2);
};
- mlir::Type elementType = builder.getI32Type();
+ // Count always gets I32 for elementType as it converts logical input to
+ // logical<4> before passing to the function.
+ mlir::Location loc = mlir::UnknownLoc::get(builder.getContext());
+ builder.setInsertionPointToEnd(funcOp.addEntryBlock());
- genReductionLoop(builder, elementType, funcOp, zero, genBodyOp, rank);
+ genReductionLoop<fir::DoLoopOp, bool, 0>(builder, funcOp, zero, nopLoopCond,
+ false, genBodyOp, rank, elementType,
+ loc);
+}
+
+static void genRuntimeAnyBody(fir::FirOpBuilder &builder,
+ mlir::func::FuncOp &funcOp, unsigned rank,
+ mlir::Type elementType) {
+ auto zero = [](fir::FirOpBuilder builder, mlir::Location loc,
+ mlir::Type elementType) {
+ return builder.createIntegerConstant(loc, elementType, 0);
+ };
+
+ auto genBodyOp = [](fir::FirOpBuilder builder, mlir::Location loc,
+ mlir::Type elementType, mlir::Value elem1,
+ mlir::Value elem2) -> mlir::Value {
+ auto zero = builder.createIntegerConstant(loc, elementType, 0);
+ return builder.create<mlir::arith::CmpIOp>(
+ loc, mlir::arith::CmpIPredicate::ne, elem1, zero);
+ };
+
+ auto continueCond = [](fir::FirOpBuilder builder, mlir::Location loc,
+ mlir::Value reductionVal) {
+ auto one1 = builder.createIntegerConstant(loc, builder.getI1Type(), 1);
+ auto eor = builder.create<mlir::arith::XOrIOp>(loc, reductionVal, one1);
+ llvm::SmallVector<mlir::Value> results = {eor, reductionVal};
+ return results;
+ };
+
+ mlir::Location loc = mlir::UnknownLoc::get(builder.getContext());
+ builder.setInsertionPointToEnd(funcOp.addEntryBlock());
+ mlir::Value ok = builder.createBool(loc, true);
+
+ genReductionLoop<fir::IterWhileOp, mlir::Value, 1>(
+ builder, funcOp, zero, continueCond, ok, genBodyOp, rank, elementType,
+ loc);
+}
+
+static void genRuntimeAllBody(fir::FirOpBuilder &builder,
+ mlir::func::FuncOp &funcOp, unsigned rank,
+ mlir::Type elementType) {
+ auto one = [](fir::FirOpBuilder builder, mlir::Location loc,
+ mlir::Type elementType) {
+ return builder.createIntegerConstant(loc, elementType, 1);
+ };
+
+ auto genBodyOp = [](fir::FirOpBuilder builder, mlir::Location loc,
+ mlir::Type elementType, mlir::Value elem1,
+ mlir::Value elem2) -> mlir::Value {
+ auto zero = builder.createIntegerConstant(loc, elementType, 0);
+ return builder.create<mlir::arith::CmpIOp>(
+ loc, mlir::arith::CmpIPredicate::ne, elem1, zero);
+ };
+
+ auto continueCond = [](fir::FirOpBuilder builder, mlir::Location loc,
+ mlir::Value reductionVal) {
+ llvm::SmallVector<mlir::Value> results = {reductionVal, reductionVal};
+ return results;
+ };
+
+ mlir::Location loc = mlir::UnknownLoc::get(builder.getContext());
+ builder.setInsertionPointToEnd(funcOp.addEntryBlock());
+ mlir::Value ok = builder.createBool(loc, true);
+
+ genReductionLoop<fir::IterWhileOp, mlir::Value, 1>(
+ builder, funcOp, one, continueCond, ok, genBodyOp, rank, elementType,
+ loc);
}
/// Generate function type for the simplified version of RTNAME(DotProduct)
@@ -612,10 +714,11 @@ void SimplifyIntrinsicsPass::simplifyIntOrFloatReduction(
(fmfString.empty() ? mlir::Twine{} : mlir::Twine{"_", fmfString}))
.str();
- simplifyReductionBody(call, kindMap, genBodyFunc, builder, funcName);
+ simplifyReductionBody(call, kindMap, genBodyFunc, builder, funcName,
+ resultType);
}
-void SimplifyIntrinsicsPass::simplifyLogicalReduction(
+void SimplifyIntrinsicsPass::simplifyLogicalDim0Reduction(
fir::CallOp call, const fir::KindMapping &kindMap,
GenReductionBodyTy genBodyFunc) {
@@ -623,26 +726,79 @@ void SimplifyIntrinsicsPass::simplifyLogicalReduction(
const mlir::Value &dim = args[3];
unsigned rank = getDimCount(args[0]);
- // Rank is set to 0 for assumed shape arrays, don't simplify
- // in these cases
+ // getDimCount returns a rank of 0 for assumed shape arrays, don't simplify in
+ // these cases.
if (!(isZero(dim) && rank > 0))
return;
+ mlir::Value inputBox = findBoxDef(args[0]);
+ LLVM_DEBUG(llvm::dbgs() << "Boxdef was: " << inputBox << '\n');
+
+ mlir::Type elementType = hlfir::getFortranElementType(inputBox.getType());
mlir::SymbolRefAttr callee = call.getCalleeAttr();
fir::FirOpBuilder builder{getSimplificationBuilder(call, kindMap)};
+
+ LLVM_DEBUG(llvm::dbgs() << "In DIM0 simplify" << '\n');
+ // Treating logicals as integers makes things a lot easier
+ fir::LogicalType logicalType = {elementType.dyn_cast<fir::LogicalType>()};
+ LLVM_DEBUG(llvm::dbgs() << "Done logical cast, got: " << logicalType << '\n');
+ fir::KindTy kind = logicalType.getFKind();
+ mlir::Type intElementType =
+ mlir::IntegerType::get(builder.getContext(), kind * 8);
+
+ // Mangle kind into function name as it is not done by default
std::string funcName =
- (mlir::Twine{callee.getLeafReference().getValue(), "x"} +
- mlir::Twine{rank})
+ (mlir::Twine{callee.getLeafReference().getValue(), "Logical"} +
+ mlir::Twine{kind} + "x" + mlir::Twine{rank})
+ .str();
+
+ LLVM_DEBUG(llvm::dbgs() << "end of DIM0" << '\n');
+
+ simplifyReductionBody(call, kindMap, genBodyFunc, builder, funcName,
+ intElementType);
+}
+
+void SimplifyIntrinsicsPass::simplifyLogicalDim1Reduction(
+ fir::CallOp call, const fir::KindMapping &kindMap,
+ GenReductionBodyTy genBodyFunc) {
+
+ mlir::Operation::operand_range args = call.getArgs();
+ mlir::SymbolRefAttr callee = call.getCalleeAttr();
+ mlir::StringRef funcNameBase = callee.getLeafReference().getValue();
+ unsigned rank = getDimCount(args[0]);
+
+ // getDimCount returns a rank of 0 for assumed shape arrays, don't simplify in
+ // these cases. We check for Dim at the end as some logical functions (Any,
+ // All) set dim to 1 instead of 0 when the argument is not present.
+ if (funcNameBase.ends_with("Dim") || !(rank > 0))
+ return;
+
+ mlir::Value inputBox = findBoxDef(args[0]);
+ mlir::Type elementType = hlfir::getFortranElementType(inputBox.getType());
+
+ fir::FirOpBuilder builder{getSimplificationBuilder(call, kindMap)};
+
+ // Treating logicals as integers makes things a lot easier
+ fir::LogicalType logicalType = {elementType.dyn_cast<fir::LogicalType>()};
+ fir::KindTy kind = logicalType.getFKind();
+ mlir::Type intElementType =
+ mlir::IntegerType::get(builder.getContext(), kind * 8);
+
+ // Mangle kind into function name as it is not done by default
+ std::string funcName =
+ (mlir::Twine{callee.getLeafReference().getValue(), "Logical"} +
+ mlir::Twine{kind} + "x" + mlir::Twine{rank})
.str();
- simplifyReductionBody(call, kindMap, genBodyFunc, builder, funcName);
+ simplifyReductionBody(call, kindMap, genBodyFunc, builder, funcName,
+ intElementType);
}
void SimplifyIntrinsicsPass::simplifyReductionBody(
fir::CallOp call, const fir::KindMapping &kindMap,
GenReductionBodyTy genBodyFunc, fir::FirOpBuilder &builder,
- const mlir::StringRef &funcName) {
+ const mlir::StringRef &funcName, mlir::Type elementType) {
mlir::Operation::operand_range args = call.getArgs();
@@ -654,9 +810,10 @@ void SimplifyIntrinsicsPass::simplifyReductionBody(
auto typeGenerator = [&resultType](fir::FirOpBuilder &builder) {
return genNoneBoxType(builder, resultType);
};
- auto bodyGenerator = [&rank, &genBodyFunc](fir::FirOpBuilder &builder,
- mlir::func::FuncOp &funcOp) {
- genBodyFunc(builder, funcOp, rank);
+ auto bodyGenerator = [&rank, &genBodyFunc,
+ &elementType](fir::FirOpBuilder &builder,
+ mlir::func::FuncOp &funcOp) {
+ genBodyFunc(builder, funcOp, rank, elementType);
};
// Mangle the function name with the rank value as "x<rank>".
mlir::func::FuncOp newFunc =
@@ -761,7 +918,17 @@ void SimplifyIntrinsicsPass::runOnOperation() {
return;
}
if (funcName.startswith(RTNAME_STRING(Count))) {
- simplifyLogicalReduction(call, kindMap, genRuntimeCountBody);
+ LLVM_DEBUG(llvm::dbgs() << "Count" << '\n');
+ simplifyLogicalDim0Reduction(call, kindMap, genRuntimeCountBody);
+ return;
+ }
+ if (funcName.startswith(RTNAME_STRING(Any))) {
+ LLVM_DEBUG(llvm::dbgs() << "Any" << '\n');
+ simplifyLogicalDim1Reduction(call, kindMap, genRuntimeAnyBody);
+ return;
+ }
+ if (funcName.endswith(RTNAME_STRING(All))) {
+ simplifyLogicalDim1Reduction(call, kindMap, genRuntimeAllBody);
return;
}
}
diff --git a/flang/test/Lower/array-derived.f90 b/flang/test/Lower/array-derived.f90
index 00df7beef9afd..1ad8a53ef92b8 100644
--- a/flang/test/Lower/array-derived.f90
+++ b/flang/test/Lower/array-derived.f90
@@ -29,7 +29,7 @@ function c1(e, c)
! CHECK: %[[slice0:.*]] = fir.slice %c1{{.*}}, %[[ext0]]#1, %c1{{.*}} path %[[fldn]] : (index, index, index, !fir.field) -> !fir.slice<1>
! CHECK-DAG: = fir.array_coor %[[arg1]] [%[[slice1]]] %[[index:.*]] : (!fir.box<!fir.array<?x!fir.type<_QMcsTr{n:i32,d:i32}>>>, !fir.slice<1>, index) -> !fir.ref<i32>
! CHECK-DAG: = fir.array_coor %[[arg0]] [%[[slice0]]] %[[index]] : (!fir.box<!fir.array<?x!fir.type<_QMcsTr{n:i32,d:i32}>>>, !fir.slice<1>, index) -> !fir.ref<i32>
- ! CHECK: = fir.call @_FortranAAll(
+ ! CHECK: = fir.call @_FortranAAllLogical4x1_simplified(
c1 = all(c%n == e%n)
end function c1
diff --git a/flang/test/Transforms/simplifyintrinsics.fir b/flang/test/Transforms/simplifyintrinsics.fir
index 282fafcd49186..d21cf19a72862 100644
--- a/flang/test/Transforms/simplifyintrinsics.fir
+++ b/flang/test/Transforms/simplifyintrinsics.fir
@@ -1132,13 +1132,13 @@ fir.global linkonce @_QQcl.2E2F746573746661696C2E66393000 constant : !fir.char<1
// CHECK: %[[A_BOX_LOGICAL:.*]] = fir.embox %{{.*}}(%[[SHAPE]]) : (!fir.ref<!fir.array<10x!fir.logical<4>>>, !fir.shape<1>) -> !fir.box<!fir.array<10x!fir.logical<4>>>
// CHECK: %[[A_BOX_NONE:.*]] = fir.convert %[[A_BOX_LOGICAL]] : (!fir.box<!fir.array<10x!fir.logical<4>>>) -> !fir.box<none>
// CHECK-NOT: fir.call @_FortranACount({{.*}})
-// CHECK: %[[RES:.*]] = fir.call @_FortranACountx1_simplified(%[[A_BOX_NONE]]) fastmath<contract> : (!fir.box<none>) -> i64
+// CHECK: %[[RES:.*]] = fir.call @_FortranACountLogical4x1_simplified(%[[A_BOX_NONE]]) fastmath<contract> : (!fir.box<none>) -> i64
// CHECK-NOT: fir.call @_FortranACount({{.*}})
// CHECK: return %{{.*}} : i32
// CHECK: }
// CHECK: func.func private @_FortranACount(!fir.box<none>, !fir.ref<i8>, i32, i32) -> i64 attributes {fir.runtime}
-// CHECK-LABEL: func.func private @_FortranACountx1_simplified(
+// CHECK-LABEL: func.func private @_FortranACountLogical4x1_simplified(
// CHECK-SAME: %[[ARR:.*]]: !fir.box<none>) -> i64 attributes {llvm.linkage = #llvm.linkage<linkonce_odr>} {
// CHECK: %[[C_INDEX0:.*]] = arith.constant 0 : index
// CHECK: %[[ARR_BOX_I32:.*]] = fir.convert %[[ARR]] : (!fir.box<none>) -> !fir.box<!fir.array<?xi32>>
@@ -1211,9 +1211,9 @@ func.func private @_FortranACountDim(!fir.ref<!fir.box<none>>, !fir.box<none>, i
// CHECK-LABEL: func.func @_QMtestPcount_generate_mask(
// CHECK-SAME: %[[A:.*]]: !fir.ref<!fir.array<10x10x!fir.logical<4>>> {fir.bindc_name = "mask"}) -> !fir.array<10xi32> {
-// CHECK-NOT fir.call @_FortranACountDim_simplified({{.*}})
+// CHECK-NOT fir.call @_FortranACountDimLogical4_simplified({{.*}})
// CHECK: %[[RES:.*]] = fir.call @_FortranACountDim({{.*}}) fastmath<contract> : (!fir.ref<!fir.box<none>>, !fir.box<none>, i32, i32, !fir.ref<i8>, i32) -> none
-// CHECK-NOT fir.call @_FortranACountDim_simplified({{.*}})
+// CHECK-NOT fir.call @_FortranACountDimLogical4_simplified({{.*}})
// -----
// Ensure count isn't simplified for unknown dimension arrays
@@ -1236,6 +1236,345 @@ func.func private @_FortranACount(!fir.box<none>, !fir.ref<i8>, i32, i32) -> i64
// CHECK-LABEL: func.func @_QPmc(
// CHECK-SAME: %[[VAL_0:.*]]: !fir.box<!fir.array<?x?x?x!fir.logical<4>>> {fir.bindc_name = "m"}) -> i32 {
-// CHECK-NOT fir.call @_FortranACount_simplified({{.*}})
+// CHECK-NOT fir.call @_FortranACountLogical4_simplified({{.*}})
// CHECK: %[[RES:.*]] = fir.call @_FortranACount({{.*}}) fastmath<contract> : (!fir.box<none>, !fir.ref<i8>, i32, i32) -> i64
-// CHECK-NOT fir.call @_FortranACount_simplified({{.*}})
+// CHECK-NOT fir.call @_FortranACountLogical4_simplified({{.*}})
+
+// -----
+// Ensure Any is simplified in correct usage
+
+func.func @_QPtestAny_NoDimArg(%arg0: !fir.ref<!fir.array<10x!fir.logical<4>>> {fir.bindc_name = "a"}) -> !fir.logical<4> {
+ %c10 = arith.constant 10 : index
+ %0 = fir.alloca !fir.logical<4> {bindc_name = "testAny_NoDimArg", uniq_name = "_QFtestAny_NoDimArgEtestAny_NoDimArg"}
+ %1 = fir.shape %c10 : (index) -> !fir.shape<1>
+ %2 = fir.embox %arg0(%1) : (!fir.ref<!fir.array<10x!fir.logical<4>>>, !fir.shape<1>) -> !fir.box<!fir.array<10x!fir.logical<4>>>
+ %c1 = arith.constant 1 : index
+ %3 = fir.address_of(@_QQcl.04ab56883945fd2c21a3b6d132f0bb37) : !fir.ref<!fir.char<1,48>>
+ %c3_i32 = arith.constant 3 : i32
+ %4 = fir.convert %2 : (!fir.box<!fir.array<10x!fir.logical<4>>>) -> !fir.box<none>
+ %5 = fir.convert %3 : (!fir.ref<!fir.char<1,48>>) -> !fir.ref<i8>
+ %6 = fir.convert %c1 : (index) -> i32
+ %7 = fir.call @_FortranAAny(%4, %5, %c3_i32, %6) fastmath<contract> : (!fir.box<none>, !fir.ref<i8>, i32, i32) -> i1
+ %8 = fir.convert %7 : (i1) -> !fir.logical<4>
+ fir.store %8 to %0 : !fir.ref<!fir.logical<4>>
+ %9 = fir.load %0 : !fir.ref<!fir.logical<4>>
+ return %9 : !fir.logical<4>
+}
+func.func private @_FortranAAny(!fir.box<none>, !fir.ref<i8>, i32, i32) -> i1 attributes {fir.runtime}
+
+// CHECK-LABEL: func.func @_QPtestAny_NoDimArg(
+// CHECK-SAME: %[[ARR:.*]]: !fir.ref<!fir.array<10x!fir.logical<4>>> {fir.bindc_name = "a"}) -> !fir.logical<4> {
+// CHECK: %[[SIZE:.*]] = arith.constant 10 : index
+// CHECK: %[[SHAPE:.*]] = fir.shape %[[SIZE]] : (index) -> !fir.shape<1>
+// CHECK: %[[A_BOX_LOGICAL:.*]] = fir.embox %[[ARR]](%[[SHAPE]]) : (!fir.ref<!fir.array<10x!fir.logical<4>>>, !fir.shape<1>) -> !fir.box<!fir.array<10x!fir.logical<4>>>
+// CHECK: %[[A_BOX_NONE:.*]] = fir.convert %[[A_BOX_LOGICAL]] : (!fir.box<!fir.array<10x!fir.logical<4>>>) -> !fir.box<none>
+// CHECK: %[[RES:.*]] = fir.call @_FortranAAnyLogical4x1_simplified(%[[A_BOX_NONE]]) fastmath<contract> : (!fir.box<none>) -> i1
+// CHECK: }
+
+// CHECK-LABEL: func.func private @_FortranAAnyLogical4x1_simplified(
+// CHECK-SAME: %[[ARR:.*]]: !fir.box<none>) -> i1 attributes {llvm.linkage = #llvm.linkage<linkonce_odr>} {
+// CHECK: %[[INIT_COND:.*]] = arith.constant true
+// CHECK: %[[C_INDEX0:.*]] = arith.constant 0 : index
+// CHECK: %[[A_BOX_I32:.*]] = fir.convert %[[ARR]] : (!fir.box<none>) -> !fir.box<!fir.array<?xi32>>
+// CHECK: %[[FALSE:.*]] = arith.constant false
+// CHECK: %[[C_INDEX1:.*]] = arith.constant 1 : index
+// CHECK: %[[DIM_IDX0:.*]] = arith.constant 0 : index
+// CHECK: %[[DIMS:.*]]:3 = fir.box_dims %[[A_BOX_I32]], %[[DIM_IDX0]] : (!fir.box<!fir.array<?xi32>>, index) -> (index, index, index)
+// CHECK: %[[EXTENT:.*]] = arith.subi %[[DIMS]]#1, %[[C_INDEX1]] : index
+// CHECK: %[[RES:.*]]:2 = fir.iterate_while (%[[ITER:.*]] = %[[C_INDEX0]] to %[[EXTENT]] step %[[C_INDEX1]]) and (%[[OK:.*]] = %[[INIT_COND]]) iter_args(%[[INIT:.*]] = %[[FALSE]]) -> (i1) {
+// CHECK: %[[ITEM:.*]] = fir.coordinate_of %[[A_BOX_I32]], %[[ITER]] : (!fir.box<!fir.array<?xi32>>, index) -> !fir.ref<i32>
+// CHECK: %[[ITEM_VAL:.*]] = fir.load %[[ITEM]] : !fir.ref<i32>
+// CHECK: %[[I32_0:.*]] = arith.constant 0 : i32
+// CHECK: %[[CMP:.*]] = arith.cmpi ne, %[[ITEM_VAL]], %[[I32_0]] : i32
+// CHECK: %[[I1_1:.*]] = arith.constant true
+// CHECK: %[[CONTINUE:.*]] = arith.xori %[[CMP]], %[[I1_1]] : i1
+// CHECK: fir.result %[[CONTINUE]], %[[CMP]] : i1, i1
+// CHECK: }
+// CHECK: return %[[RES:.*]]#1 : i1
+// CHECK: }
+
+// -----
+// Ensure Any is simpified correctly for
diff erent kind logical
+
+func.func @_QPtestAny_NoDimArgLogical8(%arg0: !fir.ref<!fir.array<10x!fir.logical<8>>> {fir.bindc_name = "a"}) -> !fir.logical<8> {
+ %c10 = arith.constant 10 : index
+ %0 = fir.alloca !fir.logical<8> {bindc_name = "testAny_NoDimArgLogical8", uniq_name = "_QFtestAny_NoDimArgLogical8EtestAny_NoDimArgLogical8"}
+ %1 = fir.shape %c10 : (index) -> !fir.shape<1>
+ %2 = fir.embox %arg0(%1) : (!fir.ref<!fir.array<10x!fir.logical<8>>>, !fir.shape<1>) -> !fir.box<!fir.array<10x!fir.logical<8>>>
+ %c1 = arith.constant 1 : index
+ %3 = fir.address_of(@_QQcl.04ab56883945fd2c21a3b6d132f0bb37) : !fir.ref<!fir.char<1,48>>
+ %c3_i32 = arith.constant 3 : i32
+ %4 = fir.convert %2 : (!fir.box<!fir.array<10x!fir.logical<8>>>) -> !fir.box<none>
+ %5 = fir.convert %3 : (!fir.ref<!fir.char<1,48>>) -> !fir.ref<i8>
+ %6 = fir.convert %c1 : (index) -> i32
+ %7 = fir.call @_FortranAAny(%4, %5, %c3_i32, %6) fastmath<contract> : (!fir.box<none>, !fir.ref<i8>, i32, i32) -> i1
+ %8 = fir.convert %7 : (i1) -> !fir.logical<8>
+ fir.store %8 to %0 : !fir.ref<!fir.logical<8>>
+ %9 = fir.load %0 : !fir.ref<!fir.logical<8>>
+ return %9 : !fir.logical<8>
+}
+func.func private @_FortranAAny(!fir.box<none>, !fir.ref<i8>, i32, i32) -> i1 attributes {fir.runtime}
+
+// CHECK-LABEL: func.func @_QPtestAny_NoDimArgLogical8(
+// CHECK-SAME: %[[ARR:.*]]: !fir.ref<!fir.array<10x!fir.logical<8>>> {fir.bindc_name = "a"}) -> !fir.logical<8> {
+// CHECK: %[[SIZE:.*]] = arith.constant 10 : index
+// CHECK: %[[SHAPE:.*]] = fir.shape %[[SIZE]] : (index) -> !fir.shape<1>
+// CHECK: %[[A_BOX_LOGICAL:.*]] = fir.embox %[[ARR]](%[[SHAPE]]) : (!fir.ref<!fir.array<10x!fir.logical<8>>>, !fir.shape<1>) -> !fir.box<!fir.array<10x!fir.logical<8>>>
+// CHECK: %[[A_BOX_NONE:.*]] = fir.convert %[[A_BOX_LOGICAL]] : (!fir.box<!fir.array<10x!fir.logical<8>>>) -> !fir.box<none>
+// CHECK: %[[RES:.*]] = fir.call @_FortranAAnyLogical8x1_simplified(%[[A_BOX_NONE]]) fastmath<contract> : (!fir.box<none>) -> i1
+// CHECK: }
+
+// CHECK-LABEL: func.func private @_FortranAAnyLogical8x1_simplified(
+// CHECK-SAME: %[[ARR:.*]]: !fir.box<none>) -> i1 attributes {llvm.linkage = #llvm.linkage<linkonce_odr>} {
+// CHECK: %[[INIT_COND:.*]] = arith.constant true
+// CHECK: %[[C_INDEX0:.*]] = arith.constant 0 : index
+// CHECK: %[[A_BOX_I64:.*]] = fir.convert %[[ARR]] : (!fir.box<none>) -> !fir.box<!fir.array<?xi64>>
+// CHECK: %[[FALSE:.*]] = arith.constant false
+// CHECK: %[[C_INDEX1:.*]] = arith.constant 1 : index
+// CHECK: %[[DIM_IDX0:.*]] = arith.constant 0 : index
+// CHECK: %[[DIMS:.*]]:3 = fir.box_dims %[[A_BOX_I64]], %[[DIM_IDX0]] : (!fir.box<!fir.array<?xi64>>, index) -> (index, index, index)
+// CHECK: %[[EXTENT:.*]] = arith.subi %[[DIMS]]#1, %[[C_INDEX1]] : index
+// CHECK: %[[RES:.*]]:2 = fir.iterate_while (%[[ITER:.*]] = %[[C_INDEX0]] to %[[EXTENT]] step %[[C_INDEX1]]) and (%[[OK:.*]] = %[[INIT_COND]]) iter_args(%[[INIT:.*]] = %[[FALSE]]) -> (i1) {
+// CHECK: %[[ITEM:.*]] = fir.coordinate_of %[[A_BOX_I64]], %[[ITER]] : (!fir.box<!fir.array<?xi64>>, index) -> !fir.ref<i64>
+// CHECK: %[[ITEM_VAL:.*]] = fir.load %[[ITEM]] : !fir.ref<i64>
+// CHECK: %[[I64_0:.*]] = arith.constant 0 : i64
+// CHECK: %[[CMP:.*]] = arith.cmpi ne, %[[ITEM_VAL]], %[[I64_0]] : i64
+// CHECK: %[[I1_1:.*]] = arith.constant true
+// CHECK: %[[CONTINUE:.*]] = arith.xori %[[CMP]], %[[I1_1]] : i1
+// CHECK: fir.result %[[CONTINUE]], %[[CMP]] : i1, i1
+// CHECK: }
+// CHECK: return %[[RES:.*]]#1 : i1
+// CHECK: }
+
+// -----
+// Ensure Any is not simplified when call ends in 'Dim'
+
+func.func @_QPtestAny_DimArg(%arg0: !fir.ref<!fir.array<10x10x!fir.logical<4>>> {fir.bindc_name = "a"}) -> !fir.array<10x!fir.logical<4>> {
+ %0 = fir.alloca !fir.box<!fir.heap<!fir.array<?x!fir.logical<4>>>>
+ %c10 = arith.constant 10 : index
+ %c10_0 = arith.constant 10 : index
+ %c10_1 = arith.constant 10 : index
+ %1 = fir.alloca !fir.array<10x!fir.logical<4>> {bindc_name = "testAny_DimArg", uniq_name = "_QFtestAny_DimArgEtestAny_DimArg"}
+ %2 = fir.shape %c10_1 : (index) -> !fir.shape<1>
+ %3 = fir.array_load %1(%2) : (!fir.ref<!fir.array<10x!fir.logical<4>>>, !fir.shape<1>) -> !fir.array<10x!fir.logical<4>>
+ %c2_i32 = arith.constant 2 : i32
+ %4 = fir.shape %c10, %c10_0 : (index, index) -> !fir.shape<2>
+ %5 = fir.embox %arg0(%4) : (!fir.ref<!fir.array<10x10x!fir.logical<4>>>, !fir.shape<2>) -> !fir.box<!fir.array<10x10x!fir.logical<4>>>
+ %6 = fir.zero_bits !fir.heap<!fir.array<?x!fir.logical<4>>>
+ %c0 = arith.constant 0 : index
+ %7 = fir.shape %c0 : (index) -> !fir.shape<1>
+ %8 = fir.embox %6(%7) : (!fir.heap<!fir.array<?x!fir.logical<4>>>, !fir.shape<1>) -> !fir.box<!fir.heap<!fir.array<?x!fir.logical<4>>>>
+ fir.store %8 to %0 : !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.logical<4>>>>>
+ %9 = fir.address_of(@_QQcl.04ab56883945fd2c21a3b6d132f0bb37) : !fir.ref<!fir.char<1,48>>
+ %c3_i32 = arith.constant 3 : i32
+ %10 = fir.convert %0 : (!fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.logical<4>>>>>) -> !fir.ref<!fir.box<none>>
+ %11 = fir.convert %5 : (!fir.box<!fir.array<10x10x!fir.logical<4>>>) -> !fir.box<none>
+ %12 = fir.convert %9 : (!fir.ref<!fir.char<1,48>>) -> !fir.ref<i8>
+ %13 = fir.call @_FortranAAnyDim(%10, %11, %c2_i32, %12, %c3_i32) fastmath<contract> : (!fir.ref<!fir.box<none>>, !fir.box<none>, i32, !fir.ref<i8>, i32) -> none
+ %14 = fir.load %0 : !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.logical<4>>>>>
+ %c0_2 = arith.constant 0 : index
+ %15:3 = fir.box_dims %14, %c0_2 : (!fir.box<!fir.heap<!fir.array<?x!fir.logical<4>>>>, index) -> (index, index, index)
+ %16 = fir.box_addr %14 : (!fir.box<!fir.heap<!fir.array<?x!fir.logical<4>>>>) -> !fir.heap<!fir.array<?x!fir.logical<4>>>
+ %17 = fir.shape_shift %15#0, %15#1 : (index, index) -> !fir.shapeshift<1>
+ %18 = fir.array_load %16(%17) : (!fir.heap<!fir.array<?x!fir.logical<4>>>, !fir.shapeshift<1>) -> !fir.array<?x!fir.logical<4>>
+ %c1 = arith.constant 1 : index
+ %c0_3 = arith.constant 0 : index
+ %19 = arith.subi %c10_1, %c1 : index
+ %20 = fir.do_loop %arg1 = %c0_3 to %19 step %c1 unordered iter_args(%arg2 = %3) -> (!fir.array<10x!fir.logical<4>>) {
+ %22 = fir.array_fetch %18, %arg1 : (!fir.array<?x!fir.logical<4>>, index) -> !fir.logical<4>
+ %23 = fir.array_update %arg2, %22, %arg1 : (!fir.array<10x!fir.logical<4>>, !fir.logical<4>, index) -> !fir.array<10x!fir.logical<4>>
+ fir.result %23 : !fir.array<10x!fir.logical<4>>
+ }
+ fir.array_merge_store %3, %20 to %1 : !fir.array<10x!fir.logical<4>>, !fir.array<10x!fir.logical<4>>, !fir.ref<!fir.array<10x!fir.logical<4>>>
+ fir.freemem %16 : !fir.heap<!fir.array<?x!fir.logical<4>>>
+ %21 = fir.load %1 : !fir.ref<!fir.array<10x!fir.logical<4>>>
+ return %21 : !fir.array<10x!fir.logical<4>>
+}
+func.func private @_FortranAAnyDim(!fir.ref<!fir.box<none>>, !fir.box<none>, i32, !fir.ref<i8>, i32) -> none attributes {fir.runtime}
+
+// CHECK-LABEL: func.func @_QPtestAny_DimArg(
+// CHECK-SAME: %[[ARR:.*]]: !fir.ref<!fir.array<10x10x!fir.logical<4>>> {fir.bindc_name = "a"}) -> !fir.array<10x!fir.logical<4>> {
+// CHECK-NOT fir.call @_FortranAAnyDimLogical4x1_simplified({{.*}})
+// CHECK: fir.call @_FortranAAnyDim({{.*}}) fastmath<contract> : (!fir.ref<!fir.box<none>>, !fir.box<none>, i32, !fir.ref<i8>, i32) -> none
+// CHECK-NOT fir.call @_FortranAAnyDimLogical4x1_simplified({{.*}})
+
+// -----
+// Ensure Any is not simplified for unknown dimension arrays
+
+func.func @_QPtestAny_UnknownDim(%arg0: !fir.box<!fir.array<?x!fir.logical<4>>> {fir.bindc_name = "a"}) -> !fir.logical<4> {
+ %0 = fir.alloca !fir.logical<4> {bindc_name = "testAny_UnknownDim", uniq_name = "_QFtestAny_UnknownDimEtestAny_UnknownDim"}
+ %c1 = arith.constant 1 : index
+ %1 = fir.address_of(@_QQcl.04ab56883945fd2c21a3b6d132f0bb37) : !fir.ref<!fir.char<1,48>>
+ %c3_i32 = arith.constant 3 : i32
+ %2 = fir.convert %arg0 : (!fir.box<!fir.array<?x!fir.logical<4>>>) -> !fir.box<none>
+ %3 = fir.convert %1 : (!fir.ref<!fir.char<1,48>>) -> !fir.ref<i8>
+ %4 = fir.convert %c1 : (index) -> i32
+ %5 = fir.call @_FortranAAny(%2, %3, %c3_i32, %4) fastmath<contract> : (!fir.box<none>, !fir.ref<i8>, i32, i32) -> i1
+ %6 = fir.convert %5 : (i1) -> !fir.logical<4>
+ fir.store %6 to %0 : !fir.ref<!fir.logical<4>>
+ %7 = fir.load %0 : !fir.ref<!fir.logical<4>>
+ return %7 : !fir.logical<4>
+}
+func.func private @_FortranAAny(!fir.box<none>, !fir.ref<i8>, i32, i32) -> i1 attributes {fir.runtime}
+
+// CHECK-LABEL: func.func @_QPtestAny_UnknownDim(
+// CHECK-SAME: %[[VAL_0:.*]]: !fir.box<!fir.array<?x!fir.logical<4>>> {fir.bindc_name = "a"}) -> !fir.logical<4> {
+// CHECK-NOT fir.call @_FortranAAnyLogical4x1_simplified({{.*}})
+// CHECK: fir.call @_FortranAAny({{.*}}) fastmath<contract> : (!fir.box<none>, !fir.ref<i8>, i32, i32) -> i1
+// CHECK-NOT fir.call @_FortranAAnyLogical4x1_simplified({{.*}})
+
+// -----
+// Ensure All is simplified in correct usage
+
+func.func @_QPtestAll_NoDimArg(%arg0: !fir.ref<!fir.array<10x!fir.logical<4>>> {fir.bindc_name = "a"}) -> !fir.logical<4> {
+ %c10 = arith.constant 10 : index
+ %0 = fir.alloca !fir.logical<4> {bindc_name = "testAll_NoDimArg", uniq_name = "_QFtestAll_NoDimArgEtestAll_NoDimArg"}
+ %1 = fir.shape %c10 : (index) -> !fir.shape<1>
+ %2 = fir.embox %arg0(%1) : (!fir.ref<!fir.array<10x!fir.logical<4>>>, !fir.shape<1>) -> !fir.box<!fir.array<10x!fir.logical<4>>>
+ %c1 = arith.constant 1 : index
+ %3 = fir.address_of(@_QQcl.04ab56883945fd2c21a3b6d132f0bb37) : !fir.ref<!fir.char<1,48>>
+ %c3_i32 = arith.constant 3 : i32
+ %4 = fir.convert %2 : (!fir.box<!fir.array<10x!fir.logical<4>>>) -> !fir.box<none>
+ %5 = fir.convert %3 : (!fir.ref<!fir.char<1,48>>) -> !fir.ref<i8>
+ %6 = fir.convert %c1 : (index) -> i32
+ %7 = fir.call @_FortranAAll(%4, %5, %c3_i32, %6) fastmath<contract> : (!fir.box<none>, !fir.ref<i8>, i32, i32) -> i1
+ %8 = fir.convert %7 : (i1) -> !fir.logical<4>
+ fir.store %8 to %0 : !fir.ref<!fir.logical<4>>
+ %9 = fir.load %0 : !fir.ref<!fir.logical<4>>
+ return %9 : !fir.logical<4>
+}
+func.func private @_FortranAAll(!fir.box<none>, !fir.ref<i8>, i32, i32) -> i1 attributes {fir.runtime}
+
+// CHECK-LABEL: func.func @_QPtestAll_NoDimArg(
+// CHECK-SAME: %[[ARR:.*]]: !fir.ref<!fir.array<10x!fir.logical<4>>> {fir.bindc_name = "a"}) -> !fir.logical<4> {
+// CHECK: %[[SIZE:.*]] = arith.constant 10 : index
+// CHECK: %[[SHAPE:.*]] = fir.shape %[[SIZE]] : (index) -> !fir.shape<1>
+// CHECK: %[[A_BOX_LOGICAL:.*]] = fir.embox %[[ARR]](%[[SHAPE]]) : (!fir.ref<!fir.array<10x!fir.logical<4>>>, !fir.shape<1>) -> !fir.box<!fir.array<10x!fir.logical<4>>>
+// CHECK: %[[A_BOX_NONE:.*]] = fir.convert %[[A_BOX_LOGICAL]] : (!fir.box<!fir.array<10x!fir.logical<4>>>) -> !fir.box<none>
+// CHECK: %[[RES:.*]] = fir.call @_FortranAAllLogical4x1_simplified(%[[A_BOX_NONE]]) fastmath<contract> : (!fir.box<none>) -> i1
+// CHECK: }
+
+// CHECK-LABEL: func.func private @_FortranAAllLogical4x1_simplified(
+// CHECK-SAME: %[[ARR:.*]]: !fir.box<none>) -> i1 attributes {llvm.linkage = #llvm.linkage<linkonce_odr>} {
+// CHECK: %[[INIT_COND:.*]] = arith.constant true
+// CHECK: %[[C_INDEX0:.*]] = arith.constant 0 : index
+// CHECK: %[[A_BOX_I32:.*]] = fir.convert %[[ARR]] : (!fir.box<none>) -> !fir.box<!fir.array<?xi32>>
+// CHECK: %[[TRUE:.*]] = arith.constant true
+// CHECK: %[[C_INDEX1:.*]] = arith.constant 1 : index
+// CHECK: %[[DIM_INDEX0:.*]] = arith.constant 0 : index
+// CHECK: %[[DIMS:.*]]:3 = fir.box_dims %[[A_BOX_I32]], %[[DIM_INDEX0]] : (!fir.box<!fir.array<?xi32>>, index) -> (index, index, index)
+// CHECK: %[[EXTENT:.*]] = arith.subi %[[DIMS]]#1, %[[C_INDEX1]] : index
+// CHECK: %[[RES:.*]]:2 = fir.iterate_while (%[[ITER:.*]] = %[[C_INDEX0]] to %[[EXTENT]] step %[[C_INDEX1]]) and (%[[OK:.*]] = %[[INIT_COND]]) iter_args(%[[INIT:.*]] = %[[TRUE]]) -> (i1) {
+// CHECK: %[[ITEM:.*]] = fir.coordinate_of %[[A_BOX_I32]], %[[ITER]] : (!fir.box<!fir.array<?xi32>>, index) -> !fir.ref<i32>
+// CHECK: %[[ITEM_VAL:.*]] = fir.load %[[ITEM]] : !fir.ref<i32>
+// CHECK: %[[I32_0:.*]] = arith.constant 0 : i32
+// CHECK: %[[CMP_AND_CONTINUE:.*]] = arith.cmpi ne, %[[ITEM_VAL]], %[[I32_0]] : i32
+// CHECK: fir.result %[[CMP_AND_CONTINUE]], %[[CMP_AND_CONTINUE]] : i1, i1
+// CHECK: }
+// CHECK: return %[[RES:.*]]#1 : i1
+// CHECK: }
+
+// -----
+// Ensure All is correctly simplified for
diff erent kind logical
+
+
+func.func @_QPtestAll_NoDimArgLogical1(%arg0: !fir.ref<!fir.array<10x!fir.logical<1>>> {fir.bindc_name = "a"}) -> !fir.logical<1> {
+ %c10 = arith.constant 10 : index
+ %0 = fir.alloca !fir.logical<1> {bindc_name = "testAll_NoDimArgLogical1", uniq_name = "_QFtestAll_NoDimArgLogical1EtestAll_NoDimArgLogical1"}
+ %1 = fir.shape %c10 : (index) -> !fir.shape<1>
+ %2 = fir.embox %arg0(%1) : (!fir.ref<!fir.array<10x!fir.logical<1>>>, !fir.shape<1>) -> !fir.box<!fir.array<10x!fir.logical<1>>>
+ %c1 = arith.constant 1 : index
+ %3 = fir.address_of(@_QQcl.04ab56883945fd2c21a3b6d132f0bb37) : !fir.ref<!fir.char<1,48>>
+ %c3_i32 = arith.constant 3 : i32
+ %4 = fir.convert %2 : (!fir.box<!fir.array<10x!fir.logical<1>>>) -> !fir.box<none>
+ %5 = fir.convert %3 : (!fir.ref<!fir.char<1,48>>) -> !fir.ref<i8>
+ %6 = fir.convert %c1 : (index) -> i32
+ %7 = fir.call @_FortranAAll(%4, %5, %c3_i32, %6) fastmath<contract> : (!fir.box<none>, !fir.ref<i8>, i32, i32) -> i1
+ %8 = fir.convert %7 : (i1) -> !fir.logical<1>
+ fir.store %8 to %0 : !fir.ref<!fir.logical<1>>
+ %9 = fir.load %0 : !fir.ref<!fir.logical<1>>
+ return %9 : !fir.logical<1>
+}
+func.func private @_FortranAAll(!fir.box<none>, !fir.ref<i8>, i32, i32) -> i1 attributes {fir.runtime}
+
+// CHECK-LABEL: func.func @_QPtestAll_NoDimArgLogical1(
+// CHECK-SAME: %[[ARR:.*]]: !fir.ref<!fir.array<10x!fir.logical<1>>> {fir.bindc_name = "a"}) -> !fir.logical<1> {
+// CHECK: %[[SIZE:.*]] = arith.constant 10 : index
+// CHECK: %[[SHAPE:.*]] = fir.shape %[[SIZE]] : (index) -> !fir.shape<1>
+// CHECK: %[[A_BOX_LOGICAL:.*]] = fir.embox %[[ARR]](%[[SHAPE]]) : (!fir.ref<!fir.array<10x!fir.logical<1>>>, !fir.shape<1>) -> !fir.box<!fir.array<10x!fir.logical<1>>>
+// CHECK: %[[A_BOX_NONE:.*]] = fir.convert %[[A_BOX_LOGICAL]] : (!fir.box<!fir.array<10x!fir.logical<1>>>) -> !fir.box<none>
+// CHECK: %[[RES:.*]] = fir.call @_FortranAAllLogical1x1_simplified(%[[A_BOX_NONE]]) fastmath<contract> : (!fir.box<none>) -> i1
+// CHECK: }
+
+// CHECK-LABEL: func.func private @_FortranAAllLogical1x1_simplified(
+// CHECK-SAME: %[[ARR:.*]]: !fir.box<none>) -> i1 attributes {llvm.linkage = #llvm.linkage<linkonce_odr>} {
+// CHECK: %[[INIT_COND:.*]] = arith.constant true
+// CHECK: %[[C_INDEX0:.*]] = arith.constant 0 : index
+// CHECK: %[[A_BOX_I8:.*]] = fir.convert %[[ARR]] : (!fir.box<none>) -> !fir.box<!fir.array<?xi8>>
+// CHECK: %[[TRUE:.*]] = arith.constant true
+// CHECK: %[[C_INDEX1:.*]] = arith.constant 1 : index
+// CHECK: %[[DIM_INDEX0:.*]] = arith.constant 0 : index
+// CHECK: %[[DIMS:.*]]:3 = fir.box_dims %[[A_BOX_I8]], %[[DIM_INDEX0]] : (!fir.box<!fir.array<?xi8>>, index) -> (index, index, index)
+// CHECK: %[[EXTENT:.*]] = arith.subi %[[DIMS]]#1, %[[C_INDEX1]] : index
+// CHECK: %[[RES:.*]]:2 = fir.iterate_while (%[[ITER:.*]] = %[[C_INDEX0]] to %[[EXTENT]] step %[[C_INDEX1]]) and (%[[OK:.*]] = %[[INIT_COND]]) iter_args(%[[INIT:.*]] = %[[TRUE]]) -> (i1) {
+// CHECK: %[[ITEM:.*]] = fir.coordinate_of %[[A_BOX_I8]], %[[ITER]] : (!fir.box<!fir.array<?xi8>>, index) -> !fir.ref<i8>
+// CHECK: %[[ITEM_VAL:.*]] = fir.load %[[ITEM]] : !fir.ref<i8>
+// CHECK: %[[I8_0:.*]] = arith.constant 0 : i8
+// CHECK: %[[CMP_AND_CONTINUE:.*]] = arith.cmpi ne, %[[ITEM_VAL]], %[[I8_0]] : i8
+// CHECK: fir.result %[[CMP_AND_CONTINUE]], %[[CMP_AND_CONTINUE]] : i1, i1
+// CHECK: }
+// CHECK: return %[[RES:.*]]#1 : i1
+// CHECK: }
+
+
+// -----
+// Ensure All is not simplified when call ends in 'Dim'
+
+func.func @_QPtestAll_DimArg(%arg0: !fir.ref<!fir.array<10x10x!fir.logical<4>>> {fir.bindc_name = "a"}) -> !fir.array<10x!fir.logical<4>> {
+ %0 = fir.alloca !fir.box<!fir.heap<!fir.array<?x!fir.logical<4>>>>
+ %c10 = arith.constant 10 : index
+ %c10_0 = arith.constant 10 : index
+ %c10_1 = arith.constant 10 : index
+ %1 = fir.alloca !fir.array<10x!fir.logical<4>> {bindc_name = "testAll_DimArg", uniq_name = "_QFtestAll_DimArgEtestAll_DimArg"}
+ %2 = fir.shape %c10_1 : (index) -> !fir.shape<1>
+ %3 = fir.array_load %1(%2) : (!fir.ref<!fir.array<10x!fir.logical<4>>>, !fir.shape<1>) -> !fir.array<10x!fir.logical<4>>
+ %c1_i32 = arith.constant 1 : i32
+ %4 = fir.shape %c10, %c10_0 : (index, index) -> !fir.shape<2>
+ %5 = fir.embox %arg0(%4) : (!fir.ref<!fir.array<10x10x!fir.logical<4>>>, !fir.shape<2>) -> !fir.box<!fir.array<10x10x!fir.logical<4>>>
+ %6 = fir.zero_bits !fir.heap<!fir.array<?x!fir.logical<4>>>
+ %c0 = arith.constant 0 : index
+ %7 = fir.shape %c0 : (index) -> !fir.shape<1>
+ %8 = fir.embox %6(%7) : (!fir.heap<!fir.array<?x!fir.logical<4>>>, !fir.shape<1>) -> !fir.box<!fir.heap<!fir.array<?x!fir.logical<4>>>>
+ fir.store %8 to %0 : !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.logical<4>>>>>
+ %9 = fir.address_of(@_QQcl.04ab56883945fd2c21a3b6d132f0bb37) : !fir.ref<!fir.char<1,48>>
+ %c3_i32 = arith.constant 3 : i32
+ %10 = fir.convert %0 : (!fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.logical<4>>>>>) -> !fir.ref<!fir.box<none>>
+ %11 = fir.convert %5 : (!fir.box<!fir.array<10x10x!fir.logical<4>>>) -> !fir.box<none>
+ %12 = fir.convert %9 : (!fir.ref<!fir.char<1,48>>) -> !fir.ref<i8>
+ %13 = fir.call @_FortranAAllDim(%10, %11, %c1_i32, %12, %c3_i32) fastmath<contract> : (!fir.ref<!fir.box<none>>, !fir.box<none>, i32, !fir.ref<i8>, i32) -> none
+ %14 = fir.load %0 : !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.logical<4>>>>>
+ %c0_2 = arith.constant 0 : index
+ %15:3 = fir.box_dims %14, %c0_2 : (!fir.box<!fir.heap<!fir.array<?x!fir.logical<4>>>>, index) -> (index, index, index)
+ %16 = fir.box_addr %14 : (!fir.box<!fir.heap<!fir.array<?x!fir.logical<4>>>>) -> !fir.heap<!fir.array<?x!fir.logical<4>>>
+ %17 = fir.shape_shift %15#0, %15#1 : (index, index) -> !fir.shapeshift<1>
+ %18 = fir.array_load %16(%17) : (!fir.heap<!fir.array<?x!fir.logical<4>>>, !fir.shapeshift<1>) -> !fir.array<?x!fir.logical<4>>
+ %c1 = arith.constant 1 : index
+ %c0_3 = arith.constant 0 : index
+ %19 = arith.subi %c10_1, %c1 : index
+ %20 = fir.do_loop %arg1 = %c0_3 to %19 step %c1 unordered iter_args(%arg2 = %3) -> (!fir.array<10x!fir.logical<4>>) {
+ %22 = fir.array_fetch %18, %arg1 : (!fir.array<?x!fir.logical<4>>, index) -> !fir.logical<4>
+ %23 = fir.array_update %arg2, %22, %arg1 : (!fir.array<10x!fir.logical<4>>, !fir.logical<4>, index) -> !fir.array<10x!fir.logical<4>>
+ fir.result %23 : !fir.array<10x!fir.logical<4>>
+ }
+ fir.array_merge_store %3, %20 to %1 : !fir.array<10x!fir.logical<4>>, !fir.array<10x!fir.logical<4>>, !fir.ref<!fir.array<10x!fir.logical<4>>>
+ fir.freemem %16 : !fir.heap<!fir.array<?x!fir.logical<4>>>
+ %21 = fir.load %1 : !fir.ref<!fir.array<10x!fir.logical<4>>>
+ return %21 : !fir.array<10x!fir.logical<4>>
+}
+func.func private @_FortranAAllDim(!fir.ref<!fir.box<none>>, !fir.box<none>, i32, !fir.ref<i8>, i32) -> none attributes {fir.runtime}
+
+// CHECK-LABEL: func.func @_QPtestAll_DimArg(
+// CHECK-SAME: %[[ARR:.*]]: !fir.ref<!fir.array<10x10x!fir.logical<4>>> {fir.bindc_name = "a"}) -> !fir.array<10x!fir.logical<4>> {
+// CHECK-NOT fir.call @_FortranAAllDimLogical4x1_simplified({{.*}})
+// CHECK: fir.call @_FortranAAllDim({{.*}}) fastmath<contract> : (!fir.ref<!fir.box<none>>, !fir.box<none>, i32, !fir.ref<i8>, i32) -> none
+// CHECK-NOT fir.call @_FortranAAllDimLogical4x1_simplified({{.*}})
More information about the flang-commits
mailing list