diff --git a/flang/include/flang/Optimizer/Builder/HLFIRTools.h b/flang/include/flang/Optimizer/Builder/HLFIRTools.h index 2cbad6e268a38..49dfc85dc76e6 100644 --- a/flang/include/flang/Optimizer/Builder/HLFIRTools.h +++ b/flang/include/flang/Optimizer/Builder/HLFIRTools.h @@ -542,6 +542,14 @@ Entity gen1DSection(mlir::Location loc, fir::FirOpBuilder &builder, /// contiguous. bool designatePreservesContinuity(hlfir::DesignateOp op); +/// Return true iff the given \p base desribes an object +/// that is contiguous. If \p checkWhole is true, then +/// the object must be contiguous in all dimensions, +/// otherwise, it must be contiguous in the innermost dimension. +/// This function is an extension of hlfir::Entity::isSimplyContiguous(), +/// and it can be used on pure FIR representation as well as on HLFIR. +bool isSimplyContiguous(mlir::Value base, bool checkWhole = true); + } // namespace hlfir #endif // FORTRAN_OPTIMIZER_BUILDER_HLFIRTOOLS_H diff --git a/flang/include/flang/Optimizer/Dialect/FIROpsSupport.h b/flang/include/flang/Optimizer/Dialect/FIROpsSupport.h index 0a2337be7455e..ae471eb0d2e04 100644 --- a/flang/include/flang/Optimizer/Dialect/FIROpsSupport.h +++ b/flang/include/flang/Optimizer/Dialect/FIROpsSupport.h @@ -238,7 +238,19 @@ std::optional getAllocaByteSize(fir::AllocaOp alloca, /// When \p checkWhole is false, then the checking is only done /// for continuity in the innermost dimension, otherwise, /// the checking is done for continuity of the whole result of rebox. -bool reboxPreservesContinuity(fir::ReboxOp rebox, bool checkWhole = true); +/// The caller may specify \p mayHaveNonDefaultLowerBounds, if it is known, +/// to allow better handling of the rebox operations representing +/// full array slices. +bool reboxPreservesContinuity(fir::ReboxOp rebox, + bool mayHaveNonDefaultLowerBounds = true, + bool checkWhole = true); + +/// Return true, if \p embox operation produces a contiguous +/// entity. +/// When \p checkWhole is false, then the checking is only done +/// for continuity in the innermost dimension, otherwise, +/// the checking is done for continuity of the whole result of embox +bool isContiguousEmbox(fir::EmboxOp embox, bool checkWhole = true); } // namespace fir diff --git a/flang/include/flang/Optimizer/Transforms/Passes.h b/flang/include/flang/Optimizer/Transforms/Passes.h index dc8a5b9141ad2..6f5dff4687cbb 100644 --- a/flang/include/flang/Optimizer/Transforms/Passes.h +++ b/flang/include/flang/Optimizer/Transforms/Passes.h @@ -31,39 +31,7 @@ namespace fir { // Passes defined in Passes.td //===----------------------------------------------------------------------===// -#define GEN_PASS_DECL_ABSTRACTRESULTOPT -#define GEN_PASS_DECL_AFFINEDIALECTPROMOTION -#define GEN_PASS_DECL_AFFINEDIALECTDEMOTION -#define GEN_PASS_DECL_ANNOTATECONSTANTOPERANDS -#define GEN_PASS_DECL_ARRAYVALUECOPY -#define GEN_PASS_DECL_ASSUMEDRANKOPCONVERSION -#define GEN_PASS_DECL_CHARACTERCONVERSION -#define GEN_PASS_DECL_CFGCONVERSION -#define GEN_PASS_DECL_CUFADDCONSTRUCTOR -#define GEN_PASS_DECL_CUFDEVICEGLOBAL -#define GEN_PASS_DECL_CUFGPUTOLLVMCONVERSION -#define GEN_PASS_DECL_CUFOPCONVERSION -#define GEN_PASS_DECL_CUFCOMPUTESHAREDMEMORYOFFSETSANDSIZE -#define GEN_PASS_DECL_EXTERNALNAMECONVERSION -#define GEN_PASS_DECL_MEMREFDATAFLOWOPT -#define GEN_PASS_DECL_SIMPLIFYINTRINSICS -#define GEN_PASS_DECL_MEMORYALLOCATIONOPT -#define GEN_PASS_DECL_SIMPLIFYREGIONLITE -#define GEN_PASS_DECL_ALGEBRAICSIMPLIFICATION -#define GEN_PASS_DECL_POLYMORPHICOPCONVERSION -#define GEN_PASS_DECL_OPENACCDATAOPERANDCONVERSION -#define GEN_PASS_DECL_ADDDEBUGINFO -#define GEN_PASS_DECL_STACKARRAYS -#define GEN_PASS_DECL_STACKRECLAIM -#define GEN_PASS_DECL_LOOPVERSIONING -#define GEN_PASS_DECL_ADDALIASTAGS -#define GEN_PASS_DECL_VSCALEATTR -#define GEN_PASS_DECL_FUNCTIONATTR -#define GEN_PASS_DECL_CONSTANTARGUMENTGLOBALISATIONOPT -#define GEN_PASS_DECL_COMPILERGENERATEDNAMESCONVERSION -#define GEN_PASS_DECL_SETRUNTIMECALLATTRIBUTES -#define GEN_PASS_DECL_GENRUNTIMECALLSFORTEST -#define GEN_PASS_DECL_SIMPLIFYFIROPERATIONS +#define GEN_PASS_DECL #include "flang/Optimizer/Transforms/Passes.h.inc" diff --git a/flang/include/flang/Optimizer/Transforms/Passes.td b/flang/include/flang/Optimizer/Transforms/Passes.td index 34842f9785942..b230f60b4c59e 100644 --- a/flang/include/flang/Optimizer/Transforms/Passes.td +++ b/flang/include/flang/Optimizer/Transforms/Passes.td @@ -551,4 +551,14 @@ def SimplifyFIROperations : Pass<"simplify-fir-operations", "mlir::ModuleOp"> { "Prefer expanding without using Fortran runtime calls.">]; } +def OptimizeArrayRepacking + : Pass<"optimize-array-repacking", "mlir::func::FuncOp"> { + let summary = "Optimizes redundant array repacking operations"; + let description = [{ + If the source of fir.pack_array is known to be contiguous, + then this pass erases such operations. The corresponding + fir.unpack_array operations are also removed. + }]; +} + #endif // FLANG_OPTIMIZER_TRANSFORMS_PASSES diff --git a/flang/lib/Optimizer/Builder/HLFIRTools.cpp b/flang/lib/Optimizer/Builder/HLFIRTools.cpp index b54cccbef14fa..e59a6bf2bf224 100644 --- a/flang/lib/Optimizer/Builder/HLFIRTools.cpp +++ b/flang/lib/Optimizer/Builder/HLFIRTools.cpp @@ -212,10 +212,17 @@ bool hlfir::Entity::mayHaveNonDefaultLowerBounds() const { if (auto varIface = getIfVariableInterface()) return isShapeWithLowerBounds(varIface.getShape()); // Go through chain of fir.box converts. - if (auto convert = getDefiningOp()) + if (auto convert = getDefiningOp()) { return hlfir::Entity{convert.getValue()}.mayHaveNonDefaultLowerBounds(); - // TODO: Embox and Rebox do not have hlfir variable interface, but are - // easy to reason about. + } else if (auto rebox = getDefiningOp()) { + // If slicing is involved, then the resulting box has + // default lower bounds. If there is no slicing, + // then the result depends on the shape operand + // (whether it has non default lower bounds or not). + return !rebox.getSlice() && isShapeWithLowerBounds(rebox.getShape()); + } else if (auto embox = getDefiningOp()) { + return !embox.getSlice() && isShapeWithLowerBounds(embox.getShape()); + } return true; } @@ -1646,3 +1653,30 @@ bool hlfir::designatePreservesContinuity(hlfir::DesignateOp op) { } return true; } + +bool hlfir::isSimplyContiguous(mlir::Value base, bool checkWhole) { + hlfir::Entity entity{base}; + if (entity.isSimplyContiguous()) + return true; + + // Look at the definition. + mlir::Operation *def = base.getDefiningOp(); + if (!def) + return false; + + return mlir::TypeSwitch(def) + .Case( + [&](auto op) { return fir::isContiguousEmbox(op, checkWhole); }) + .Case([&](auto op) { + hlfir::Entity box{op.getBox()}; + return fir::reboxPreservesContinuity( + op, box.mayHaveNonDefaultLowerBounds(), checkWhole) && + isSimplyContiguous(box, checkWhole); + }) + .Case([&](auto op) { + return isSimplyContiguous(op.getMemref(), checkWhole); + }) + .Case( + [&](auto op) { return isSimplyContiguous(op.getValue()); }) + .Default([](auto &&) { return false; }); +} diff --git a/flang/lib/Optimizer/Dialect/FIROps.cpp b/flang/lib/Optimizer/Dialect/FIROps.cpp index ecfa2939e96a6..372b7b4610e05 100644 --- a/flang/lib/Optimizer/Dialect/FIROps.cpp +++ b/flang/lib/Optimizer/Dialect/FIROps.cpp @@ -1944,6 +1944,128 @@ llvm::LogicalResult fir::EmboxOp::verify() { return mlir::success(); } +/// Returns true if \p extent matches the extent of the \p box's +/// dimension \p dim. +static bool isBoxExtent(mlir::Value box, std::int64_t dim, mlir::Value extent) { + if (auto op = extent.getDefiningOp()) + if (op.getVal() == box && op.getExtent() == extent) + if (auto dimOperand = fir::getIntIfConstant(op.getDim())) + return *dimOperand == dim; + return false; +} + +/// Returns true if \p lb matches the lower bound of the \p box's +/// dimension \p dim. If \p mayHaveNonDefaultLowerBounds is false, +/// then \p lb may be an integer constant 1. +static bool isBoxLb(mlir::Value box, std::int64_t dim, mlir::Value lb, + bool mayHaveNonDefaultLowerBounds = true) { + if (auto op = lb.getDefiningOp()) { + if (op.getVal() == box && op.getLowerBound() == lb) + if (auto dimOperand = fir::getIntIfConstant(op.getDim())) + return *dimOperand == dim; + } else if (!mayHaveNonDefaultLowerBounds) { + if (auto constantLb = fir::getIntIfConstant(lb)) + return *constantLb == 1; + } + return false; +} + +/// Returns true if \p ub matches the upper bound of the \p box's +/// dimension \p dim. If \p mayHaveNonDefaultLowerBounds is false, +/// then the dimension's lower bound may be an integer constant 1. +/// Note that the upper bound is usually a result of computation +/// involving the lower bound and the extent, and the function +/// tries its best to recognize the computation pattern. +/// The conservative result 'false' does not necessarily mean +/// that \p ub is not an actual upper bound value. +static bool isBoxUb(mlir::Value box, std::int64_t dim, mlir::Value ub, + bool mayHaveNonDefaultLowerBounds = true) { + if (auto sub1 = ub.getDefiningOp()) { + auto one = fir::getIntIfConstant(sub1.getOperand(1)); + if (!one || *one != 1) + return false; + if (auto add = sub1.getOperand(0).getDefiningOp()) + if ((isBoxLb(box, dim, add.getOperand(0)) && + isBoxExtent(box, dim, add.getOperand(1))) || + (isBoxLb(box, dim, add.getOperand(1)) && + isBoxExtent(box, dim, add.getOperand(0)))) + return true; + } else if (!mayHaveNonDefaultLowerBounds) { + return isBoxExtent(box, dim, ub); + } + return false; +} + +/// Checks if the given \p sliceOp specifies a contiguous +/// array slice. If \p checkWhole is true, then the check +/// is done for all dimensions, otherwise, only for the innermost +/// dimension. +/// The simplest way to prove that this is an contiguous slice +/// is to check whether the slice stride(s) is 1. +/// For more complex cases, extra information must be provided +/// by the caller: +/// * \p origBox - if not null, then the source array is represented +/// with this !fir.box value. The box is used to recognize +/// the full dimension slices, which are specified by the triplets +/// computed from the dimensions' lower bounds and extents. +/// * \p mayHaveNonDefaultLowerBounds may be set to false to indicate +/// that the source entity has default lower bounds, so the full +/// dimension slices computations may use 1 for the lower bound. +static bool isContiguousArraySlice(fir::SliceOp sliceOp, bool checkWhole = true, + mlir::Value origBox = nullptr, + bool mayHaveNonDefaultLowerBounds = true) { + if (sliceOp.getFields().empty() && sliceOp.getSubstr().empty()) { + // TODO: generalize code for the triples analysis with + // hlfir::designatePreservesContinuity, especially when + // recognition of the whole dimension slices is added. + auto triples = sliceOp.getTriples(); + assert((triples.size() % 3) == 0 && "invalid triples size"); + + // A slice with step=1 in the innermost dimension preserves + // the continuity of the array in the innermost dimension. + // If checkWhole is false, then check only the innermost slice triples. + std::size_t checkUpTo = checkWhole ? triples.size() : 3; + checkUpTo = std::min(checkUpTo, triples.size()); + for (std::size_t i = 0; i < checkUpTo; i += 3) { + if (triples[i] != triples[i + 1]) { + // This is a section of the dimension. Only allow it + // to be the first triple, if the source of the slice + // is a boxed array. If it is a raw pointer, then + // the result will still be contiguous, as long as + // the strides are all ones. + // When origBox is not null, we must prove that the triple + // covers the whole dimension and the stride is one, + // before claiming contiguity for this dimension. + if (i != 0 && origBox) { + std::int64_t dim = i / 3; + if (!isBoxLb(origBox, dim, triples[i], + mayHaveNonDefaultLowerBounds) || + !isBoxUb(origBox, dim, triples[i + 1], + mayHaveNonDefaultLowerBounds)) + return false; + } + auto constantStep = fir::getIntIfConstant(triples[i + 2]); + if (!constantStep || *constantStep != 1) + return false; + } + } + return true; + } + return false; +} + +bool fir::isContiguousEmbox(fir::EmboxOp embox, bool checkWhole) { + auto sliceArg = embox.getSlice(); + if (!sliceArg) + return true; + + if (auto sliceOp = + mlir::dyn_cast_or_null(sliceArg.getDefiningOp())) + return isContiguousArraySlice(sliceOp, checkWhole); + + return false; +} + //===----------------------------------------------------------------------===// // EmboxCharOp //===----------------------------------------------------------------------===// @@ -4794,7 +4916,9 @@ mlir::Type fir::applyPathToType(mlir::Type eleTy, mlir::ValueRange path) { return eleTy; } -bool fir::reboxPreservesContinuity(fir::ReboxOp rebox, bool checkWhole) { +bool fir::reboxPreservesContinuity(fir::ReboxOp rebox, + bool mayHaveNonDefaultLowerBounds, + bool checkWhole) { // If slicing is not involved, then the rebox does not affect // the continuity of the array. auto sliceArg = rebox.getSlice(); @@ -4802,33 +4926,10 @@ bool fir::reboxPreservesContinuity(fir::ReboxOp rebox, bool checkWhole) { return true; if (auto sliceOp = - mlir::dyn_cast_or_null(sliceArg.getDefiningOp())) { - if (sliceOp.getFields().empty() && sliceOp.getSubstr().empty()) { - // TODO: generalize code for the triples analysis with - // hlfir::designatePreservesContinuity, especially when - // recognition of the whole dimension slices is added. - auto triples = sliceOp.getTriples(); - assert((triples.size() % 3) == 0 && "invalid triples size"); - - // A slice with step=1 in the innermost dimension preserves - // the continuity of the array in the innermost dimension. - // If checkWhole is false, then check only the innermost slice triples. - std::size_t checkUpTo = checkWhole ? triples.size() : 3; - checkUpTo = std::min(checkUpTo, triples.size()); - for (std::size_t i = 0; i < checkUpTo; i += 3) { - if (triples[i] != triples[i + 1]) { - // This is a section of the dimension. Only allow it - // to be the first triple. - if (i != 0) - return false; - auto constantStep = fir::getIntIfConstant(triples[i + 2]); - if (!constantStep || *constantStep != 1) - return false; - } - } - return true; - } - } + mlir::dyn_cast_or_null(sliceArg.getDefiningOp())) + return isContiguousArraySlice(sliceOp, checkWhole, rebox.getBox(), + mayHaveNonDefaultLowerBounds); + return false; } diff --git a/flang/lib/Optimizer/Passes/Pipelines.cpp b/flang/lib/Optimizer/Passes/Pipelines.cpp index 333bfc8b7aed8..ca8e820608688 100644 --- a/flang/lib/Optimizer/Passes/Pipelines.cpp +++ b/flang/lib/Optimizer/Passes/Pipelines.cpp @@ -207,6 +207,10 @@ void createDefaultFIROptimizerPassPipeline(mlir::PassManager &pm, pm.addPass(fir::createPolymorphicOpConversion()); pm.addPass(fir::createAssumedRankOpConversion()); + // Optimize redundant array repacking operations, + // if the source is known to be contiguous. + if (pc.OptLevel.isOptimizingForSpeed()) + pm.addPass(fir::createOptimizeArrayRepacking()); pm.addPass(fir::createLowerRepackArraysPass()); // Expand FIR operations that may use SCF dialect for their // implementation. This is a mandatory pass. diff --git a/flang/lib/Optimizer/Transforms/CMakeLists.txt b/flang/lib/Optimizer/Transforms/CMakeLists.txt index 846d6c64dbd04..a8812e08c1ccd 100644 --- a/flang/lib/Optimizer/Transforms/CMakeLists.txt +++ b/flang/lib/Optimizer/Transforms/CMakeLists.txt @@ -34,6 +34,7 @@ add_flang_library(FIRTransforms SetRuntimeCallAttributes.cpp GenRuntimeCallsForTest.cpp SimplifyFIROperations.cpp + OptimizeArrayRepacking.cpp DEPENDS CUFAttrs diff --git a/flang/lib/Optimizer/Transforms/LoopVersioning.cpp b/flang/lib/Optimizer/Transforms/LoopVersioning.cpp index 50e7ee5599ab1..056bdf63d914f 100644 --- a/flang/lib/Optimizer/Transforms/LoopVersioning.cpp +++ b/flang/lib/Optimizer/Transforms/LoopVersioning.cpp @@ -214,7 +214,9 @@ static mlir::Value unwrapPassThroughOps(mlir::Value val) { /// of the value, otherwise return the value static mlir::Value unwrapReboxOp(mlir::Value val) { while (fir::ReboxOp rebox = val.getDefiningOp()) { - if (!fir::reboxPreservesContinuity(rebox, /*checkWhole=*/false)) { + if (!fir::reboxPreservesContinuity(rebox, + /*mayHaveNonDefaultLowerBounds=*/true, + /*checkWhole=*/false)) { LLVM_DEBUG(llvm::dbgs() << "REBOX may produce non-contiguous array: " << rebox << '\n'); break; diff --git a/flang/lib/Optimizer/Transforms/OptimizeArrayRepacking.cpp b/flang/lib/Optimizer/Transforms/OptimizeArrayRepacking.cpp new file mode 100644 index 0000000000000..1688f2887a57a --- /dev/null +++ b/flang/lib/Optimizer/Transforms/OptimizeArrayRepacking.cpp @@ -0,0 +1,90 @@ +//===- OptimizeArrayRepacking.cpp -----------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +/// \file +/// This pass removes redundant fir.pack_array operations, if it can prove +/// that the source array is contiguous. In this case, it relink all uses +/// of fir.pack_array result to the source. If such a rewrite happens, +/// it may turn the using fir.unpack_array operation into one with the same +/// temp and original operands - these are also removed as redundant. +//===----------------------------------------------------------------------===// +#include "flang/Optimizer/Builder/HLFIRTools.h" +#include "flang/Optimizer/Dialect/FIRDialect.h" +#include "flang/Optimizer/Dialect/FIROps.h" +#include "flang/Optimizer/Support/Utils.h" +#include "flang/Optimizer/Transforms/Passes.h" +#include "mlir/Transforms/GreedyPatternRewriteDriver.h" + +namespace fir { +#define GEN_PASS_DEF_OPTIMIZEARRAYREPACKING +#include "flang/Optimizer/Transforms/Passes.h.inc" +} // namespace fir + +namespace { +class OptimizeArrayRepackingPass + : public fir::impl::OptimizeArrayRepackingBase { +public: + void runOnOperation() override; +}; + +/// Relinks all uses of redundant fir.pack_array to the source. +class PackingOfContiguous : public mlir::OpRewritePattern { +public: + using OpRewritePattern::OpRewritePattern; + mlir::LogicalResult matchAndRewrite(fir::PackArrayOp, + mlir::PatternRewriter &) const override; +}; + +/// Erases fir.unpack_array with have the matching temp and original +/// operands. +class NoopUnpacking : public mlir::OpRewritePattern { +public: + using OpRewritePattern::OpRewritePattern; + mlir::LogicalResult matchAndRewrite(fir::UnpackArrayOp, + mlir::PatternRewriter &) const override; +}; +} // namespace + +mlir::LogicalResult +PackingOfContiguous::matchAndRewrite(fir::PackArrayOp op, + mlir::PatternRewriter &rewriter) const { + mlir::Value box = op.getArray(); + if (hlfir::isSimplyContiguous(box, !op.getInnermost())) { + rewriter.replaceAllUsesWith(op, box); + rewriter.eraseOp(op); + return mlir::success(); + } + return mlir::failure(); +} + +mlir::LogicalResult +NoopUnpacking::matchAndRewrite(fir::UnpackArrayOp op, + mlir::PatternRewriter &rewriter) const { + if (op.getTemp() == op.getOriginal()) { + rewriter.eraseOp(op); + return mlir::success(); + } + return mlir::failure(); +} + +void OptimizeArrayRepackingPass::runOnOperation() { + mlir::func::FuncOp funcOp = getOperation(); + mlir::MLIRContext *context = &getContext(); + mlir::RewritePatternSet patterns(context); + mlir::GreedyRewriteConfig config; + config.setRegionSimplificationLevel( + mlir::GreedySimplifyRegionLevel::Disabled); + patterns.insert(context); + patterns.insert(context); + if (mlir::failed( + mlir::applyPatternsGreedily(funcOp, std::move(patterns), config))) { + mlir::emitError(funcOp.getLoc(), "failure in array repacking optimization"); + signalPassFailure(); + } +} diff --git a/flang/test/Driver/bbc-mlir-pass-pipeline.f90 b/flang/test/Driver/bbc-mlir-pass-pipeline.f90 index 137c19608c38f..f3791fe9f8dc3 100644 --- a/flang/test/Driver/bbc-mlir-pass-pipeline.f90 +++ b/flang/test/Driver/bbc-mlir-pass-pipeline.f90 @@ -47,6 +47,8 @@ ! CHECK-NEXT: PolymorphicOpConversion ! CHECK-NEXT: AssumedRankOpConversion +! CHECK-NEXT: 'func.func' Pipeline +! CHECK-NEXT: OptimizeArrayRepacking ! CHECK-NEXT: LowerRepackArraysPass ! CHECK-NEXT: SimplifyFIROperations diff --git a/flang/test/Driver/mlir-pass-pipeline.f90 b/flang/test/Driver/mlir-pass-pipeline.f90 index 99f192ce7aec2..0bcd055a84b87 100644 --- a/flang/test/Driver/mlir-pass-pipeline.f90 +++ b/flang/test/Driver/mlir-pass-pipeline.f90 @@ -105,6 +105,8 @@ ! ALL-NEXT: PolymorphicOpConversion ! ALL-NEXT: AssumedRankOpConversion +! O2-NEXT: 'func.func' Pipeline +! O2-NEXT: OptimizeArrayRepacking ! ALL-NEXT: LowerRepackArraysPass ! ALL-NEXT: SimplifyFIROperations ! O2-NEXT: AddAliasTags diff --git a/flang/test/Fir/basic-program.fir b/flang/test/Fir/basic-program.fir index 7ac8b92f48953..c9fe53bf093a1 100644 --- a/flang/test/Fir/basic-program.fir +++ b/flang/test/Fir/basic-program.fir @@ -103,6 +103,8 @@ func.func @_QQmain() { // PASSES-NEXT: PolymorphicOpConversion // PASSES-NEXT: AssumedRankOpConversion +// PASSES-NEXT: 'func.func' Pipeline +// PASSES-NEXT: OptimizeArrayRepacking // PASSES-NEXT: LowerRepackArraysPass // PASSES-NEXT: SimplifyFIROperations // PASSES-NEXT: AddAliasTags diff --git a/flang/test/HLFIR/simplify-hlfir-intrinsics-cshift.fir b/flang/test/HLFIR/simplify-hlfir-intrinsics-cshift.fir index 35530c66f4038..8684a429ea5b4 100644 --- a/flang/test/HLFIR/simplify-hlfir-intrinsics-cshift.fir +++ b/flang/test/HLFIR/simplify-hlfir-intrinsics-cshift.fir @@ -41,19 +41,11 @@ func.func @cshift_vector(%arg0: !fir.box>, %arg1: !fir.ref index // CHECK: fir.do_loop %[[VAL_28:.*]] = %[[VAL_2]] to %[[VAL_27]] step %[[VAL_2]] unordered { // CHECK: %[[VAL_29:.*]] = fir.convert %[[VAL_28]] : (index) -> i64 -// CHECK: %[[VAL_30:.*]]:3 = fir.box_dims %[[VAL_26]], %[[VAL_5]] : (!fir.box>, index) -> (index, index, index) -// CHECK: %[[VAL_31:.*]] = fir.convert %[[VAL_29]] : (i64) -> index -// CHECK: %[[VAL_32:.*]] = arith.subi %[[VAL_30]]#0, %[[VAL_2]] overflow : index -// CHECK: %[[VAL_33:.*]] = arith.addi %[[VAL_31]], %[[VAL_32]] overflow : index -// CHECK: %[[VAL_34:.*]] = hlfir.designate %[[VAL_26]] (%[[VAL_33]]) : (!fir.box>, index) -> !fir.ref +// CHECK: %[[VAL_34:.*]] = hlfir.designate %[[VAL_26]] (%[[VAL_29]]) : (!fir.box>, i64) -> !fir.ref // CHECK: %[[VAL_35:.*]] = fir.load %[[VAL_34]] : !fir.ref // CHECK: %[[VAL_36:.*]] = arith.subi %[[VAL_8]], %[[VAL_17]] overflow : i64 // CHECK: %[[VAL_37:.*]] = arith.addi %[[VAL_29]], %[[VAL_36]] overflow : i64 -// CHECK: %[[VAL_38:.*]]:3 = fir.box_dims %[[VAL_20]], %[[VAL_5]] : (!fir.box>, index) -> (index, index, index) -// CHECK: %[[VAL_39:.*]] = fir.convert %[[VAL_37]] : (i64) -> index -// CHECK: %[[VAL_40:.*]] = arith.subi %[[VAL_38]]#0, %[[VAL_2]] overflow : index -// CHECK: %[[VAL_41:.*]] = arith.addi %[[VAL_39]], %[[VAL_40]] overflow : index -// CHECK: %[[VAL_42:.*]] = hlfir.designate %[[VAL_20]] (%[[VAL_41]]) : (!fir.box>, index) -> !fir.ref +// CHECK: %[[VAL_42:.*]] = hlfir.designate %[[VAL_20]] (%[[VAL_37]]) : (!fir.box>, i64) -> !fir.ref // CHECK: hlfir.assign %[[VAL_35]] to %[[VAL_42]] : i32, !fir.ref // CHECK: } // CHECK: %[[VAL_43:.*]] = arith.subi %[[VAL_8]], %[[VAL_17]] overflow : i64 @@ -61,17 +53,9 @@ func.func @cshift_vector(%arg0: !fir.box>, %arg1: !fir.ref i64 // CHECK: %[[VAL_47:.*]] = arith.addi %[[VAL_46]], %[[VAL_17]] overflow : i64 -// CHECK: %[[VAL_48:.*]]:3 = fir.box_dims %[[VAL_26]], %[[VAL_5]] : (!fir.box>, index) -> (index, index, index) -// CHECK: %[[VAL_49:.*]] = fir.convert %[[VAL_47]] : (i64) -> index -// CHECK: %[[VAL_50:.*]] = arith.subi %[[VAL_48]]#0, %[[VAL_2]] overflow : index -// CHECK: %[[VAL_51:.*]] = arith.addi %[[VAL_49]], %[[VAL_50]] overflow : index -// CHECK: %[[VAL_52:.*]] = hlfir.designate %[[VAL_26]] (%[[VAL_51]]) : (!fir.box>, index) -> !fir.ref +// CHECK: %[[VAL_52:.*]] = hlfir.designate %[[VAL_26]] (%[[VAL_47]]) : (!fir.box>, i64) -> !fir.ref // CHECK: %[[VAL_53:.*]] = fir.load %[[VAL_52]] : !fir.ref -// CHECK: %[[VAL_54:.*]]:3 = fir.box_dims %[[VAL_20]], %[[VAL_5]] : (!fir.box>, index) -> (index, index, index) -// CHECK: %[[VAL_55:.*]] = fir.convert %[[VAL_46]] : (i64) -> index -// CHECK: %[[VAL_56:.*]] = arith.subi %[[VAL_54]]#0, %[[VAL_2]] overflow : index -// CHECK: %[[VAL_57:.*]] = arith.addi %[[VAL_55]], %[[VAL_56]] overflow : index -// CHECK: %[[VAL_58:.*]] = hlfir.designate %[[VAL_20]] (%[[VAL_57]]) : (!fir.box>, index) -> !fir.ref +// CHECK: %[[VAL_58:.*]] = hlfir.designate %[[VAL_20]] (%[[VAL_46]]) : (!fir.box>, i64) -> !fir.ref // CHECK: hlfir.assign %[[VAL_53]] to %[[VAL_58]] : i32, !fir.ref // CHECK: } // CHECK: } else { @@ -86,11 +70,7 @@ func.func @cshift_vector(%arg0: !fir.box>, %arg1: !fir.ref // CHECK: %[[VAL_68:.*]] = arith.subi %[[VAL_8]], %[[VAL_17]] overflow : i64 // CHECK: %[[VAL_69:.*]] = arith.addi %[[VAL_61]], %[[VAL_68]] overflow : i64 -// CHECK: %[[VAL_70:.*]]:3 = fir.box_dims %[[VAL_20]], %[[VAL_5]] : (!fir.box>, index) -> (index, index, index) -// CHECK: %[[VAL_71:.*]] = fir.convert %[[VAL_69]] : (i64) -> index -// CHECK: %[[VAL_72:.*]] = arith.subi %[[VAL_70]]#0, %[[VAL_2]] overflow : index -// CHECK: %[[VAL_73:.*]] = arith.addi %[[VAL_71]], %[[VAL_72]] overflow : index -// CHECK: %[[VAL_74:.*]] = hlfir.designate %[[VAL_20]] (%[[VAL_73]]) : (!fir.box>, index) -> !fir.ref +// CHECK: %[[VAL_74:.*]] = hlfir.designate %[[VAL_20]] (%[[VAL_69]]) : (!fir.box>, i64) -> !fir.ref // CHECK: hlfir.assign %[[VAL_67]] to %[[VAL_74]] : i32, !fir.ref // CHECK: } // CHECK: %[[VAL_75:.*]] = arith.subi %[[VAL_8]], %[[VAL_17]] overflow : i64 @@ -104,11 +84,7 @@ func.func @cshift_vector(%arg0: !fir.box>, %arg1: !fir.ref : index // CHECK: %[[VAL_84:.*]] = hlfir.designate %[[VAL_0]] (%[[VAL_83]]) : (!fir.box>, index) -> !fir.ref // CHECK: %[[VAL_85:.*]] = fir.load %[[VAL_84]] : !fir.ref -// CHECK: %[[VAL_86:.*]]:3 = fir.box_dims %[[VAL_20]], %[[VAL_5]] : (!fir.box>, index) -> (index, index, index) -// CHECK: %[[VAL_87:.*]] = fir.convert %[[VAL_78]] : (i64) -> index -// CHECK: %[[VAL_88:.*]] = arith.subi %[[VAL_86]]#0, %[[VAL_2]] overflow : index -// CHECK: %[[VAL_89:.*]] = arith.addi %[[VAL_87]], %[[VAL_88]] overflow : index -// CHECK: %[[VAL_90:.*]] = hlfir.designate %[[VAL_20]] (%[[VAL_89]]) : (!fir.box>, index) -> !fir.ref +// CHECK: %[[VAL_90:.*]] = hlfir.designate %[[VAL_20]] (%[[VAL_78]]) : (!fir.box>, i64) -> !fir.ref // CHECK: hlfir.assign %[[VAL_85]] to %[[VAL_90]] : i32, !fir.ref // CHECK: } // CHECK: } diff --git a/flang/test/HLFIR/simplify-hlfir-intrinsics-matmul.fir b/flang/test/HLFIR/simplify-hlfir-intrinsics-matmul.fir index d29e9a26c20ba..73e6e5c2421ff 100644 --- a/flang/test/HLFIR/simplify-hlfir-intrinsics-matmul.fir +++ b/flang/test/HLFIR/simplify-hlfir-intrinsics-matmul.fir @@ -13,7 +13,6 @@ func.func @matmul_matrix_matrix_integer(%arg0: !hlfir.expr, %arg1: !hlf // NOANSE: hlfir.matmul -// ANSE: %[[VAL_2:.*]] = arith.constant 0 : index // ANSE: %[[VAL_3:.*]] = arith.constant 1 : index // ANSE: %[[VAL_4:.*]] = arith.constant 0 : i32 // ANSE: %[[VAL_5:.*]] = hlfir.shape_of %[[VAL_0]] : (!hlfir.expr) -> !fir.shape<2> @@ -27,26 +26,14 @@ func.func @matmul_matrix_matrix_integer(%arg0: !hlfir.expr, %arg1: !hlf // ANSE: %[[VAL_13:.*]] = fir.embox %[[VAL_12]](%[[VAL_10]]) : (!fir.ref>, !fir.shape<2>) -> !fir.box> // ANSE: fir.do_loop %[[VAL_14:.*]] = %[[VAL_3]] to %[[VAL_9]] step %[[VAL_3]] unordered { // ANSE: fir.do_loop %[[VAL_15:.*]] = %[[VAL_3]] to %[[VAL_6]] step %[[VAL_3]] unordered { -// ANSE: %[[VAL_16:.*]]:3 = fir.box_dims %[[VAL_13]], %[[VAL_2]] : (!fir.box>, index) -> (index, index, index) -// ANSE: %[[VAL_17:.*]]:3 = fir.box_dims %[[VAL_13]], %[[VAL_3]] : (!fir.box>, index) -> (index, index, index) -// ANSE: %[[VAL_18:.*]] = arith.subi %[[VAL_16]]#0, %[[VAL_3]] : index -// ANSE: %[[VAL_19:.*]] = arith.addi %[[VAL_15]], %[[VAL_18]] : index -// ANSE: %[[VAL_20:.*]] = arith.subi %[[VAL_17]]#0, %[[VAL_3]] : index -// ANSE: %[[VAL_21:.*]] = arith.addi %[[VAL_14]], %[[VAL_20]] : index -// ANSE: %[[VAL_22:.*]] = hlfir.designate %[[VAL_13]] (%[[VAL_19]], %[[VAL_21]]) : (!fir.box>, index, index) -> !fir.ref +// ANSE: %[[VAL_22:.*]] = hlfir.designate %[[VAL_13]] (%[[VAL_15]], %[[VAL_14]]) : (!fir.box>, index, index) -> !fir.ref // ANSE: hlfir.assign %[[VAL_4]] to %[[VAL_22]] : i32, !fir.ref // ANSE: } // ANSE: } // ANSE: fir.do_loop %[[VAL_23:.*]] = %[[VAL_3]] to %[[VAL_7]] step %[[VAL_3]] unordered { // ANSE: fir.do_loop %[[VAL_24:.*]] = %[[VAL_3]] to %[[VAL_9]] step %[[VAL_3]] unordered { // ANSE: fir.do_loop %[[VAL_25:.*]] = %[[VAL_3]] to %[[VAL_6]] step %[[VAL_3]] unordered { -// ANSE: %[[VAL_26:.*]]:3 = fir.box_dims %[[VAL_13]], %[[VAL_2]] : (!fir.box>, index) -> (index, index, index) -// ANSE: %[[VAL_27:.*]]:3 = fir.box_dims %[[VAL_13]], %[[VAL_3]] : (!fir.box>, index) -> (index, index, index) -// ANSE: %[[VAL_28:.*]] = arith.subi %[[VAL_26]]#0, %[[VAL_3]] : index -// ANSE: %[[VAL_29:.*]] = arith.addi %[[VAL_25]], %[[VAL_28]] : index -// ANSE: %[[VAL_30:.*]] = arith.subi %[[VAL_27]]#0, %[[VAL_3]] : index -// ANSE: %[[VAL_31:.*]] = arith.addi %[[VAL_24]], %[[VAL_30]] : index -// ANSE: %[[VAL_32:.*]] = hlfir.designate %[[VAL_13]] (%[[VAL_29]], %[[VAL_31]]) : (!fir.box>, index, index) -> !fir.ref +// ANSE: %[[VAL_32:.*]] = hlfir.designate %[[VAL_13]] (%[[VAL_25]], %[[VAL_24]]) : (!fir.box>, index, index) -> !fir.ref // ANSE: %[[VAL_33:.*]] = fir.load %[[VAL_32]] : !fir.ref // ANSE: %[[VAL_34:.*]] = hlfir.apply %[[VAL_0]], %[[VAL_25]], %[[VAL_23]] : (!hlfir.expr, index, index) -> i16 // ANSE: %[[VAL_35:.*]] = hlfir.apply %[[VAL_1]], %[[VAL_23]], %[[VAL_24]] : (!hlfir.expr, index, index) -> i32 @@ -94,7 +81,6 @@ func.func @matmul_matrix_matrix_real(%arg0: !hlfir.expr, %arg1: !hlfir. // NOANSE: hlfir.matmul -// ANSE: %[[VAL_2:.*]] = arith.constant 0 : index // ANSE: %[[VAL_3:.*]] = arith.constant 1 : index // ANSE: %[[VAL_4:.*]] = arith.constant 0.000000e+00 : f32 // ANSE: %[[VAL_5:.*]] = hlfir.shape_of %[[VAL_0]] : (!hlfir.expr) -> !fir.shape<2> @@ -108,26 +94,14 @@ func.func @matmul_matrix_matrix_real(%arg0: !hlfir.expr, %arg1: !hlfir. // ANSE: %[[VAL_13:.*]] = fir.embox %[[VAL_12]](%[[VAL_10]]) : (!fir.ref>, !fir.shape<2>) -> !fir.box> // ANSE: fir.do_loop %[[VAL_14:.*]] = %[[VAL_3]] to %[[VAL_9]] step %[[VAL_3]] unordered { // ANSE: fir.do_loop %[[VAL_15:.*]] = %[[VAL_3]] to %[[VAL_6]] step %[[VAL_3]] unordered { -// ANSE: %[[VAL_16:.*]]:3 = fir.box_dims %[[VAL_13]], %[[VAL_2]] : (!fir.box>, index) -> (index, index, index) -// ANSE: %[[VAL_17:.*]]:3 = fir.box_dims %[[VAL_13]], %[[VAL_3]] : (!fir.box>, index) -> (index, index, index) -// ANSE: %[[VAL_18:.*]] = arith.subi %[[VAL_16]]#0, %[[VAL_3]] : index -// ANSE: %[[VAL_19:.*]] = arith.addi %[[VAL_15]], %[[VAL_18]] : index -// ANSE: %[[VAL_20:.*]] = arith.subi %[[VAL_17]]#0, %[[VAL_3]] : index -// ANSE: %[[VAL_21:.*]] = arith.addi %[[VAL_14]], %[[VAL_20]] : index -// ANSE: %[[VAL_22:.*]] = hlfir.designate %[[VAL_13]] (%[[VAL_19]], %[[VAL_21]]) : (!fir.box>, index, index) -> !fir.ref +// ANSE: %[[VAL_22:.*]] = hlfir.designate %[[VAL_13]] (%[[VAL_15]], %[[VAL_14]]) : (!fir.box>, index, index) -> !fir.ref // ANSE: hlfir.assign %[[VAL_4]] to %[[VAL_22]] : f32, !fir.ref // ANSE: } // ANSE: } // ANSE: fir.do_loop %[[VAL_23:.*]] = %[[VAL_3]] to %[[VAL_7]] step %[[VAL_3]] { // ANSE: fir.do_loop %[[VAL_24:.*]] = %[[VAL_3]] to %[[VAL_9]] step %[[VAL_3]] { // ANSE: fir.do_loop %[[VAL_25:.*]] = %[[VAL_3]] to %[[VAL_6]] step %[[VAL_3]] { -// ANSE: %[[VAL_26:.*]]:3 = fir.box_dims %[[VAL_13]], %[[VAL_2]] : (!fir.box>, index) -> (index, index, index) -// ANSE: %[[VAL_27:.*]]:3 = fir.box_dims %[[VAL_13]], %[[VAL_3]] : (!fir.box>, index) -> (index, index, index) -// ANSE: %[[VAL_28:.*]] = arith.subi %[[VAL_26]]#0, %[[VAL_3]] : index -// ANSE: %[[VAL_29:.*]] = arith.addi %[[VAL_25]], %[[VAL_28]] : index -// ANSE: %[[VAL_30:.*]] = arith.subi %[[VAL_27]]#0, %[[VAL_3]] : index -// ANSE: %[[VAL_31:.*]] = arith.addi %[[VAL_24]], %[[VAL_30]] : index -// ANSE: %[[VAL_32:.*]] = hlfir.designate %[[VAL_13]] (%[[VAL_29]], %[[VAL_31]]) : (!fir.box>, index, index) -> !fir.ref +// ANSE: %[[VAL_32:.*]] = hlfir.designate %[[VAL_13]] (%[[VAL_25]], %[[VAL_24]]) : (!fir.box>, index, index) -> !fir.ref // ANSE: %[[VAL_33:.*]] = fir.load %[[VAL_32]] : !fir.ref // ANSE: %[[VAL_34:.*]] = hlfir.apply %[[VAL_0]], %[[VAL_25]], %[[VAL_23]] : (!hlfir.expr, index, index) -> f32 // ANSE: %[[VAL_35:.*]] = hlfir.apply %[[VAL_1]], %[[VAL_23]], %[[VAL_24]] : (!hlfir.expr, index, index) -> f16 @@ -175,7 +149,6 @@ func.func @matmul_matrix_matrix_complex(%arg0: !hlfir.expr>, %a // NOANSE: hlfir.matmul -// ANSE: %[[VAL_2:.*]] = arith.constant 0 : index // ANSE: %[[VAL_3:.*]] = arith.constant 1 : index // ANSE: %[[VAL_4:.*]] = arith.constant 0.000000e+00 : f32 // ANSE: %[[VAL_5:.*]] = hlfir.shape_of %[[VAL_0]] : (!hlfir.expr>) -> !fir.shape<2> @@ -192,26 +165,14 @@ func.func @matmul_matrix_matrix_complex(%arg0: !hlfir.expr>, %a // ANSE: %[[VAL_16:.*]] = fir.insert_value %[[VAL_15]], %[[VAL_4]], [1 : index] : (complex, f32) -> complex // ANSE: fir.do_loop %[[VAL_17:.*]] = %[[VAL_3]] to %[[VAL_9]] step %[[VAL_3]] unordered { // ANSE: fir.do_loop %[[VAL_18:.*]] = %[[VAL_3]] to %[[VAL_6]] step %[[VAL_3]] unordered { -// ANSE: %[[VAL_19:.*]]:3 = fir.box_dims %[[VAL_13]], %[[VAL_2]] : (!fir.box>>, index) -> (index, index, index) -// ANSE: %[[VAL_20:.*]]:3 = fir.box_dims %[[VAL_13]], %[[VAL_3]] : (!fir.box>>, index) -> (index, index, index) -// ANSE: %[[VAL_21:.*]] = arith.subi %[[VAL_19]]#0, %[[VAL_3]] : index -// ANSE: %[[VAL_22:.*]] = arith.addi %[[VAL_18]], %[[VAL_21]] : index -// ANSE: %[[VAL_23:.*]] = arith.subi %[[VAL_20]]#0, %[[VAL_3]] : index -// ANSE: %[[VAL_24:.*]] = arith.addi %[[VAL_17]], %[[VAL_23]] : index -// ANSE: %[[VAL_25:.*]] = hlfir.designate %[[VAL_13]] (%[[VAL_22]], %[[VAL_24]]) : (!fir.box>>, index, index) -> !fir.ref> +// ANSE: %[[VAL_25:.*]] = hlfir.designate %[[VAL_13]] (%[[VAL_18]], %[[VAL_17]]) : (!fir.box>>, index, index) -> !fir.ref> // ANSE: hlfir.assign %[[VAL_16]] to %[[VAL_25]] : complex, !fir.ref> // ANSE: } // ANSE: } // ANSE: fir.do_loop %[[VAL_26:.*]] = %[[VAL_3]] to %[[VAL_7]] step %[[VAL_3]] { // ANSE: fir.do_loop %[[VAL_27:.*]] = %[[VAL_3]] to %[[VAL_9]] step %[[VAL_3]] { // ANSE: fir.do_loop %[[VAL_28:.*]] = %[[VAL_3]] to %[[VAL_6]] step %[[VAL_3]] { -// ANSE: %[[VAL_29:.*]]:3 = fir.box_dims %[[VAL_13]], %[[VAL_2]] : (!fir.box>>, index) -> (index, index, index) -// ANSE: %[[VAL_30:.*]]:3 = fir.box_dims %[[VAL_13]], %[[VAL_3]] : (!fir.box>>, index) -> (index, index, index) -// ANSE: %[[VAL_31:.*]] = arith.subi %[[VAL_29]]#0, %[[VAL_3]] : index -// ANSE: %[[VAL_32:.*]] = arith.addi %[[VAL_28]], %[[VAL_31]] : index -// ANSE: %[[VAL_33:.*]] = arith.subi %[[VAL_30]]#0, %[[VAL_3]] : index -// ANSE: %[[VAL_34:.*]] = arith.addi %[[VAL_27]], %[[VAL_33]] : index -// ANSE: %[[VAL_35:.*]] = hlfir.designate %[[VAL_13]] (%[[VAL_32]], %[[VAL_34]]) : (!fir.box>>, index, index) -> !fir.ref> +// ANSE: %[[VAL_35:.*]] = hlfir.designate %[[VAL_13]] (%[[VAL_28]], %[[VAL_27]]) : (!fir.box>>, index, index) -> !fir.ref> // ANSE: %[[VAL_36:.*]] = fir.load %[[VAL_35]] : !fir.ref> // ANSE: %[[VAL_37:.*]] = hlfir.apply %[[VAL_0]], %[[VAL_28]], %[[VAL_26]] : (!hlfir.expr>, index, index) -> complex // ANSE: %[[VAL_38:.*]] = hlfir.apply %[[VAL_1]], %[[VAL_26]], %[[VAL_27]] : (!hlfir.expr>, index, index) -> complex @@ -262,7 +223,6 @@ func.func @matmul_matrix_matrix_complex_real(%arg0: !hlfir.expr // NOANSE: hlfir.matmul -// ANSE: %[[VAL_2:.*]] = arith.constant 0 : index // ANSE: %[[VAL_3:.*]] = arith.constant 1 : index // ANSE: %[[VAL_4:.*]] = arith.constant 0.000000e+00 : f32 // ANSE: %[[VAL_5:.*]] = hlfir.shape_of %[[VAL_0]] : (!hlfir.expr>) -> !fir.shape<2> @@ -279,26 +239,14 @@ func.func @matmul_matrix_matrix_complex_real(%arg0: !hlfir.expr // ANSE: %[[VAL_16:.*]] = fir.insert_value %[[VAL_15]], %[[VAL_4]], [1 : index] : (complex, f32) -> complex // ANSE: fir.do_loop %[[VAL_17:.*]] = %[[VAL_3]] to %[[VAL_9]] step %[[VAL_3]] unordered { // ANSE: fir.do_loop %[[VAL_18:.*]] = %[[VAL_3]] to %[[VAL_6]] step %[[VAL_3]] unordered { -// ANSE: %[[VAL_19:.*]]:3 = fir.box_dims %[[VAL_13]], %[[VAL_2]] : (!fir.box>>, index) -> (index, index, index) -// ANSE: %[[VAL_20:.*]]:3 = fir.box_dims %[[VAL_13]], %[[VAL_3]] : (!fir.box>>, index) -> (index, index, index) -// ANSE: %[[VAL_21:.*]] = arith.subi %[[VAL_19]]#0, %[[VAL_3]] : index -// ANSE: %[[VAL_22:.*]] = arith.addi %[[VAL_18]], %[[VAL_21]] : index -// ANSE: %[[VAL_23:.*]] = arith.subi %[[VAL_20]]#0, %[[VAL_3]] : index -// ANSE: %[[VAL_24:.*]] = arith.addi %[[VAL_17]], %[[VAL_23]] : index -// ANSE: %[[VAL_25:.*]] = hlfir.designate %[[VAL_13]] (%[[VAL_22]], %[[VAL_24]]) : (!fir.box>>, index, index) -> !fir.ref> +// ANSE: %[[VAL_25:.*]] = hlfir.designate %[[VAL_13]] (%[[VAL_18]], %[[VAL_17]]) : (!fir.box>>, index, index) -> !fir.ref> // ANSE: hlfir.assign %[[VAL_16]] to %[[VAL_25]] : complex, !fir.ref> // ANSE: } // ANSE: } // ANSE: fir.do_loop %[[VAL_26:.*]] = %[[VAL_3]] to %[[VAL_7]] step %[[VAL_3]] { // ANSE: fir.do_loop %[[VAL_27:.*]] = %[[VAL_3]] to %[[VAL_9]] step %[[VAL_3]] { // ANSE: fir.do_loop %[[VAL_28:.*]] = %[[VAL_3]] to %[[VAL_6]] step %[[VAL_3]] { -// ANSE: %[[VAL_29:.*]]:3 = fir.box_dims %[[VAL_13]], %[[VAL_2]] : (!fir.box>>, index) -> (index, index, index) -// ANSE: %[[VAL_30:.*]]:3 = fir.box_dims %[[VAL_13]], %[[VAL_3]] : (!fir.box>>, index) -> (index, index, index) -// ANSE: %[[VAL_31:.*]] = arith.subi %[[VAL_29]]#0, %[[VAL_3]] : index -// ANSE: %[[VAL_32:.*]] = arith.addi %[[VAL_28]], %[[VAL_31]] : index -// ANSE: %[[VAL_33:.*]] = arith.subi %[[VAL_30]]#0, %[[VAL_3]] : index -// ANSE: %[[VAL_34:.*]] = arith.addi %[[VAL_27]], %[[VAL_33]] : index -// ANSE: %[[VAL_35:.*]] = hlfir.designate %[[VAL_13]] (%[[VAL_32]], %[[VAL_34]]) : (!fir.box>>, index, index) -> !fir.ref> +// ANSE: %[[VAL_35:.*]] = hlfir.designate %[[VAL_13]] (%[[VAL_28]], %[[VAL_27]]) : (!fir.box>>, index, index) -> !fir.ref> // ANSE: %[[VAL_36:.*]] = fir.load %[[VAL_35]] : !fir.ref> // ANSE: %[[VAL_37:.*]] = hlfir.apply %[[VAL_0]], %[[VAL_28]], %[[VAL_26]] : (!hlfir.expr>, index, index) -> complex // ANSE: %[[VAL_38:.*]] = hlfir.apply %[[VAL_1]], %[[VAL_26]], %[[VAL_27]] : (!hlfir.expr, index, index) -> f16 @@ -357,7 +305,6 @@ func.func @matmul_matrix_matrix_logical(%arg0: !hlfir.expr>, // NOANSE: hlfir.matmul -// ANSE: %[[VAL_2:.*]] = arith.constant 0 : index // ANSE: %[[VAL_3:.*]] = arith.constant 1 : index // ANSE: %[[VAL_4:.*]] = arith.constant false // ANSE: %[[VAL_5:.*]] = hlfir.shape_of %[[VAL_0]] : (!hlfir.expr>) -> !fir.shape<2> @@ -372,26 +319,14 @@ func.func @matmul_matrix_matrix_logical(%arg0: !hlfir.expr>, // ANSE: %[[VAL_14:.*]] = fir.convert %[[VAL_4]] : (i1) -> !fir.logical<4> // ANSE: fir.do_loop %[[VAL_15:.*]] = %[[VAL_3]] to %[[VAL_9]] step %[[VAL_3]] unordered { // ANSE: fir.do_loop %[[VAL_16:.*]] = %[[VAL_3]] to %[[VAL_6]] step %[[VAL_3]] unordered { -// ANSE: %[[VAL_17:.*]]:3 = fir.box_dims %[[VAL_13]], %[[VAL_2]] : (!fir.box>>, index) -> (index, index, index) -// ANSE: %[[VAL_18:.*]]:3 = fir.box_dims %[[VAL_13]], %[[VAL_3]] : (!fir.box>>, index) -> (index, index, index) -// ANSE: %[[VAL_19:.*]] = arith.subi %[[VAL_17]]#0, %[[VAL_3]] : index -// ANSE: %[[VAL_20:.*]] = arith.addi %[[VAL_16]], %[[VAL_19]] : index -// ANSE: %[[VAL_21:.*]] = arith.subi %[[VAL_18]]#0, %[[VAL_3]] : index -// ANSE: %[[VAL_22:.*]] = arith.addi %[[VAL_15]], %[[VAL_21]] : index -// ANSE: %[[VAL_23:.*]] = hlfir.designate %[[VAL_13]] (%[[VAL_20]], %[[VAL_22]]) : (!fir.box>>, index, index) -> !fir.ref> +// ANSE: %[[VAL_23:.*]] = hlfir.designate %[[VAL_13]] (%[[VAL_16]], %[[VAL_15]]) : (!fir.box>>, index, index) -> !fir.ref> // ANSE: hlfir.assign %[[VAL_14]] to %[[VAL_23]] : !fir.logical<4>, !fir.ref> // ANSE: } // ANSE: } // ANSE: fir.do_loop %[[VAL_24:.*]] = %[[VAL_3]] to %[[VAL_7]] step %[[VAL_3]] unordered { // ANSE: fir.do_loop %[[VAL_25:.*]] = %[[VAL_3]] to %[[VAL_9]] step %[[VAL_3]] unordered { // ANSE: fir.do_loop %[[VAL_26:.*]] = %[[VAL_3]] to %[[VAL_6]] step %[[VAL_3]] unordered { -// ANSE: %[[VAL_27:.*]]:3 = fir.box_dims %[[VAL_13]], %[[VAL_2]] : (!fir.box>>, index) -> (index, index, index) -// ANSE: %[[VAL_28:.*]]:3 = fir.box_dims %[[VAL_13]], %[[VAL_3]] : (!fir.box>>, index) -> (index, index, index) -// ANSE: %[[VAL_29:.*]] = arith.subi %[[VAL_27]]#0, %[[VAL_3]] : index -// ANSE: %[[VAL_30:.*]] = arith.addi %[[VAL_26]], %[[VAL_29]] : index -// ANSE: %[[VAL_31:.*]] = arith.subi %[[VAL_28]]#0, %[[VAL_3]] : index -// ANSE: %[[VAL_32:.*]] = arith.addi %[[VAL_25]], %[[VAL_31]] : index -// ANSE: %[[VAL_33:.*]] = hlfir.designate %[[VAL_13]] (%[[VAL_30]], %[[VAL_32]]) : (!fir.box>>, index, index) -> !fir.ref> +// ANSE: %[[VAL_33:.*]] = hlfir.designate %[[VAL_13]] (%[[VAL_26]], %[[VAL_25]]) : (!fir.box>>, index, index) -> !fir.ref> // ANSE: %[[VAL_34:.*]] = fir.load %[[VAL_33]] : !fir.ref> // ANSE: %[[VAL_35:.*]] = hlfir.apply %[[VAL_0]], %[[VAL_26]], %[[VAL_24]] : (!hlfir.expr>, index, index) -> !fir.logical<1> // ANSE: %[[VAL_36:.*]] = hlfir.apply %[[VAL_1]], %[[VAL_24]], %[[VAL_25]] : (!hlfir.expr>, index, index) -> !fir.logical<4> @@ -446,7 +381,6 @@ func.func @matmul_matrix_vector_real(%arg0: !hlfir.expr, %arg1: !hlfir. // NOANSE: hlfir.matmul -// ANSE: %[[VAL_2:.*]] = arith.constant 0 : index // ANSE: %[[VAL_3:.*]] = arith.constant 1 : index // ANSE: %[[VAL_4:.*]] = arith.constant 0.000000e+00 : f32 // ANSE: %[[VAL_5:.*]] = hlfir.shape_of %[[VAL_0]] : (!hlfir.expr) -> !fir.shape<2> @@ -457,18 +391,12 @@ func.func @matmul_matrix_vector_real(%arg0: !hlfir.expr, %arg1: !hlfir. // ANSE: ^bb0(%[[VAL_10:.*]]: !fir.ref>): // ANSE: %[[VAL_11:.*]] = fir.embox %[[VAL_10]](%[[VAL_8]]) : (!fir.ref>, !fir.shape<1>) -> !fir.box> // ANSE: fir.do_loop %[[VAL_12:.*]] = %[[VAL_3]] to %[[VAL_6]] step %[[VAL_3]] unordered { -// ANSE: %[[VAL_13:.*]]:3 = fir.box_dims %[[VAL_11]], %[[VAL_2]] : (!fir.box>, index) -> (index, index, index) -// ANSE: %[[VAL_14:.*]] = arith.subi %[[VAL_13]]#0, %[[VAL_3]] : index -// ANSE: %[[VAL_15:.*]] = arith.addi %[[VAL_12]], %[[VAL_14]] : index -// ANSE: %[[VAL_16:.*]] = hlfir.designate %[[VAL_11]] (%[[VAL_15]]) : (!fir.box>, index) -> !fir.ref +// ANSE: %[[VAL_16:.*]] = hlfir.designate %[[VAL_11]] (%[[VAL_12]]) : (!fir.box>, index) -> !fir.ref // ANSE: hlfir.assign %[[VAL_4]] to %[[VAL_16]] : f32, !fir.ref // ANSE: } // ANSE: fir.do_loop %[[VAL_17:.*]] = %[[VAL_3]] to %[[VAL_7]] step %[[VAL_3]] { // ANSE: fir.do_loop %[[VAL_18:.*]] = %[[VAL_3]] to %[[VAL_6]] step %[[VAL_3]] { -// ANSE: %[[VAL_19:.*]]:3 = fir.box_dims %[[VAL_11]], %[[VAL_2]] : (!fir.box>, index) -> (index, index, index) -// ANSE: %[[VAL_20:.*]] = arith.subi %[[VAL_19]]#0, %[[VAL_3]] : index -// ANSE: %[[VAL_21:.*]] = arith.addi %[[VAL_18]], %[[VAL_20]] : index -// ANSE: %[[VAL_22:.*]] = hlfir.designate %[[VAL_11]] (%[[VAL_21]]) : (!fir.box>, index) -> !fir.ref +// ANSE: %[[VAL_22:.*]] = hlfir.designate %[[VAL_11]] (%[[VAL_18]]) : (!fir.box>, index) -> !fir.ref // ANSE: %[[VAL_23:.*]] = fir.load %[[VAL_22]] : !fir.ref // ANSE: %[[VAL_24:.*]] = hlfir.apply %[[VAL_0]], %[[VAL_18]], %[[VAL_17]] : (!hlfir.expr, index, index) -> f32 // ANSE: %[[VAL_25:.*]] = hlfir.apply %[[VAL_1]], %[[VAL_17]] : (!hlfir.expr, index) -> f16 @@ -513,7 +441,6 @@ func.func @matmul_vector_matrix_real(%arg0: !hlfir.expr, %arg1: !hlfir.ex // NOANSE: hlfir.matmul -// ANSE: %[[VAL_2:.*]] = arith.constant 0 : index // ANSE: %[[VAL_3:.*]] = arith.constant 1 : index // ANSE: %[[VAL_4:.*]] = arith.constant 0.000000e+00 : f32 // ANSE: %[[VAL_5:.*]] = hlfir.shape_of %[[VAL_0]] : (!hlfir.expr) -> !fir.shape<1> @@ -525,18 +452,12 @@ func.func @matmul_vector_matrix_real(%arg0: !hlfir.expr, %arg1: !hlfir.ex // ANSE: ^bb0(%[[VAL_11:.*]]: !fir.ref>): // ANSE: %[[VAL_12:.*]] = fir.embox %[[VAL_11]](%[[VAL_9]]) : (!fir.ref>, !fir.shape<1>) -> !fir.box> // ANSE: fir.do_loop %[[VAL_13:.*]] = %[[VAL_3]] to %[[VAL_8]] step %[[VAL_3]] unordered { -// ANSE: %[[VAL_14:.*]]:3 = fir.box_dims %[[VAL_12]], %[[VAL_2]] : (!fir.box>, index) -> (index, index, index) -// ANSE: %[[VAL_15:.*]] = arith.subi %[[VAL_14]]#0, %[[VAL_3]] : index -// ANSE: %[[VAL_16:.*]] = arith.addi %[[VAL_13]], %[[VAL_15]] : index -// ANSE: %[[VAL_17:.*]] = hlfir.designate %[[VAL_12]] (%[[VAL_16]]) : (!fir.box>, index) -> !fir.ref +// ANSE: %[[VAL_17:.*]] = hlfir.designate %[[VAL_12]] (%[[VAL_13]]) : (!fir.box>, index) -> !fir.ref // ANSE: hlfir.assign %[[VAL_4]] to %[[VAL_17]] : f32, !fir.ref // ANSE: } // ANSE: fir.do_loop %[[VAL_18:.*]] = %[[VAL_3]] to %[[VAL_6]] step %[[VAL_3]] { // ANSE: fir.do_loop %[[VAL_19:.*]] = %[[VAL_3]] to %[[VAL_8]] step %[[VAL_3]] { -// ANSE: %[[VAL_20:.*]]:3 = fir.box_dims %[[VAL_12]], %[[VAL_2]] : (!fir.box>, index) -> (index, index, index) -// ANSE: %[[VAL_21:.*]] = arith.subi %[[VAL_20]]#0, %[[VAL_3]] : index -// ANSE: %[[VAL_22:.*]] = arith.addi %[[VAL_19]], %[[VAL_21]] : index -// ANSE: %[[VAL_23:.*]] = hlfir.designate %[[VAL_12]] (%[[VAL_22]]) : (!fir.box>, index) -> !fir.ref +// ANSE: %[[VAL_23:.*]] = hlfir.designate %[[VAL_12]] (%[[VAL_19]]) : (!fir.box>, index) -> !fir.ref // ANSE: %[[VAL_24:.*]] = fir.load %[[VAL_23]] : !fir.ref // ANSE: %[[VAL_25:.*]] = hlfir.apply %[[VAL_0]], %[[VAL_18]] : (!hlfir.expr, index) -> f32 // ANSE: %[[VAL_26:.*]] = hlfir.apply %[[VAL_1]], %[[VAL_18]], %[[VAL_19]] : (!hlfir.expr, index, index) -> f16 diff --git a/flang/test/Transforms/optimize-array-repacking.fir b/flang/test/Transforms/optimize-array-repacking.fir new file mode 100644 index 0000000000000..6269fa441fe44 --- /dev/null +++ b/flang/test/Transforms/optimize-array-repacking.fir @@ -0,0 +1,660 @@ +// Test that the redundant fir.[un]pack_array operations +// are optimized away, when the source is statically known +// to be contiguous. +// RUN: fir-opt --optimize-array-repacking %s | FileCheck %s + +// FIR is produced by compiling the sources with -mllvm -inline-all. +// module inner +// contains +// subroutine inner_repack1(x) +// real :: x(:) +// end subroutine inner_repack1 +// subroutine inner_repack2(x) +// real :: x(:,:) +// end subroutine inner_repack2 +// end module inner + +// subroutine test_explicit_shape_cst(x) +// real :: x(100) +// call repack(x(1:50)) +// contains +// subroutine repack(x) +// real :: x(:) +// end subroutine repack +// end subroutine test_explicit_shape_cst +// +// CHECK-LABEL: func.func @_QPtest_explicit_shape_cst( +// CHECK-NOT: fir.{{.*}}pack_array +func.func @_QPtest_explicit_shape_cst(%arg0: !fir.ref> {fir.bindc_name = "x"}) { + %c50 = arith.constant 50 : index + %c1 = arith.constant 1 : index + %c100 = arith.constant 100 : index + %0 = fir.dummy_scope : !fir.dscope + %1 = fir.shape %c100 : (index) -> !fir.shape<1> + %2 = fir.declare %arg0(%1) dummy_scope %0 {uniq_name = "_QFtest_explicit_shape_cstEx"} : (!fir.ref>, !fir.shape<1>, !fir.dscope) -> !fir.ref> + %3 = fir.shape %c50 : (index) -> !fir.shape<1> + %4 = fir.array_coor %2(%1) %c1 : (!fir.ref>, !fir.shape<1>, index) -> !fir.ref + %5 = fir.convert %4 : (!fir.ref) -> !fir.ref> + %6 = fir.embox %5(%3) : (!fir.ref>, !fir.shape<1>) -> !fir.box> + %7 = fir.convert %6 : (!fir.box>) -> !fir.box> + %8 = fir.dummy_scope : !fir.dscope + %9 = fir.pack_array %7 heap whole : (!fir.box>) -> !fir.box> + %10 = fir.declare %9 dummy_scope %8 {uniq_name = "_QFtest_explicit_shape_cstFrepackEx"} : (!fir.box>, !fir.dscope) -> !fir.box> + fir.unpack_array %9 to %7 heap : !fir.box> + return +} + +// subroutine test_explicit_shape_var(x, n, l, u) +// integer :: n, l, u +// real :: x(n) +// call repack(x(l:u)) +// contains +// subroutine repack(x) +// real :: x(:) +// end subroutine repack +// end subroutine test_explicit_shape_var +// +// CHECK-LABEL: func.func @_QPtest_explicit_shape_var( +// CHECK-NOT: fir.{{.*}}pack_array +func.func @_QPtest_explicit_shape_var(%arg0: !fir.ref> {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "n"}, %arg2: !fir.ref {fir.bindc_name = "l"}, %arg3: !fir.ref {fir.bindc_name = "u"}) { + %c1 = arith.constant 1 : index + %c0 = arith.constant 0 : index + %0 = fir.dummy_scope : !fir.dscope + %1 = fir.declare %arg2 dummy_scope %0 {uniq_name = "_QFtest_explicit_shape_varEl"} : (!fir.ref, !fir.dscope) -> !fir.ref + %2 = fir.declare %arg1 dummy_scope %0 {uniq_name = "_QFtest_explicit_shape_varEn"} : (!fir.ref, !fir.dscope) -> !fir.ref + %3 = fir.declare %arg3 dummy_scope %0 {uniq_name = "_QFtest_explicit_shape_varEu"} : (!fir.ref, !fir.dscope) -> !fir.ref + %4 = fir.load %2 : !fir.ref + %5 = fir.convert %4 : (i32) -> index + %6 = arith.cmpi sgt, %5, %c0 : index + %7 = arith.select %6, %5, %c0 : index + %8 = fir.shape %7 : (index) -> !fir.shape<1> + %9 = fir.declare %arg0(%8) dummy_scope %0 {uniq_name = "_QFtest_explicit_shape_varEx"} : (!fir.ref>, !fir.shape<1>, !fir.dscope) -> !fir.ref> + %10 = fir.load %1 : !fir.ref + %11 = fir.load %3 : !fir.ref + %12 = fir.convert %10 : (i32) -> index + %13 = fir.convert %11 : (i32) -> index + %14 = fir.slice %12, %13, %c1 : (index, index, index) -> !fir.slice<1> + %15 = fir.embox %9(%8) [%14] : (!fir.ref>, !fir.shape<1>, !fir.slice<1>) -> !fir.box> + %16 = fir.dummy_scope : !fir.dscope + %17 = fir.pack_array %15 heap whole : (!fir.box>) -> !fir.box> + %18 = fir.declare %17 dummy_scope %16 {uniq_name = "_QFtest_explicit_shape_varFrepackEx"} : (!fir.box>, !fir.dscope) -> !fir.box> + fir.unpack_array %17 to %15 heap : !fir.box> + return +} + +// subroutine test_assumed_size_cst(x) +// real :: x(*) +// call repack(x(1:50)) +// contains +// subroutine repack(x) +// real :: x(:) +// end subroutine repack +// end subroutine test_assumed_size_cst +// +// CHECK-LABEL: func.func @_QPtest_assumed_size_cst( +// CHECK-NOT: fir.{{.*}}pack_array +func.func @_QPtest_assumed_size_cst(%arg0: !fir.ref> {fir.bindc_name = "x"}) { + %c50 = arith.constant 50 : index + %c1 = arith.constant 1 : index + %c-1 = arith.constant -1 : index + %0 = fir.dummy_scope : !fir.dscope + %1 = fir.shape %c-1 : (index) -> !fir.shape<1> + %2 = fir.declare %arg0(%1) dummy_scope %0 {uniq_name = "_QFtest_assumed_size_cstEx"} : (!fir.ref>, !fir.shape<1>, !fir.dscope) -> !fir.ref> + %3 = fir.shape %c50 : (index) -> !fir.shape<1> + %4 = fir.array_coor %2(%1) %c1 : (!fir.ref>, !fir.shape<1>, index) -> !fir.ref + %5 = fir.convert %4 : (!fir.ref) -> !fir.ref> + %6 = fir.embox %5(%3) : (!fir.ref>, !fir.shape<1>) -> !fir.box> + %7 = fir.convert %6 : (!fir.box>) -> !fir.box> + %8 = fir.dummy_scope : !fir.dscope + %9 = fir.pack_array %7 heap whole : (!fir.box>) -> !fir.box> + %10 = fir.declare %9 dummy_scope %8 {uniq_name = "_QFtest_assumed_size_cstFrepackEx"} : (!fir.box>, !fir.dscope) -> !fir.box> + fir.unpack_array %9 to %7 heap : !fir.box> + return +} + +// subroutine test_assumed_size_var(x, l, u) +// integer :: l, u +// real :: x(*) +// call repack(x(l:u)) +// contains +// subroutine repack(x) +// real :: x(:) +// end subroutine repack +// end subroutine test_assumed_size_var +// +// CHECK-LABEL: func.func @_QPtest_assumed_size_var( +// CHECK-NOT: fir.{{.*}}pack_array +func.func @_QPtest_assumed_size_var(%arg0: !fir.ref> {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "l"}, %arg2: !fir.ref {fir.bindc_name = "u"}) { + %c1 = arith.constant 1 : index + %c-1 = arith.constant -1 : index + %0 = fir.dummy_scope : !fir.dscope + %1 = fir.declare %arg1 dummy_scope %0 {uniq_name = "_QFtest_assumed_size_varEl"} : (!fir.ref, !fir.dscope) -> !fir.ref + %2 = fir.declare %arg2 dummy_scope %0 {uniq_name = "_QFtest_assumed_size_varEu"} : (!fir.ref, !fir.dscope) -> !fir.ref + %3 = fir.shape %c-1 : (index) -> !fir.shape<1> + %4 = fir.declare %arg0(%3) dummy_scope %0 {uniq_name = "_QFtest_assumed_size_varEx"} : (!fir.ref>, !fir.shape<1>, !fir.dscope) -> !fir.ref> + %5 = fir.load %1 : !fir.ref + %6 = fir.load %2 : !fir.ref + %7 = fir.convert %5 : (i32) -> index + %8 = fir.convert %6 : (i32) -> index + %9 = fir.slice %7, %8, %c1 : (index, index, index) -> !fir.slice<1> + %10 = fir.embox %4(%3) [%9] : (!fir.ref>, !fir.shape<1>, !fir.slice<1>) -> !fir.box> + %11 = fir.dummy_scope : !fir.dscope + %12 = fir.pack_array %10 heap whole : (!fir.box>) -> !fir.box> + %13 = fir.declare %12 dummy_scope %11 {uniq_name = "_QFtest_assumed_size_varFrepackEx"} : (!fir.box>, !fir.dscope) -> !fir.box> + fir.unpack_array %12 to %10 heap : !fir.box> + return +} + +// subroutine test_allocatable_cst(x) +// real, allocatable :: x(:) +// call repack(x(10:50)) +// contains +// subroutine repack(x) +// real :: x(:) +// end subroutine repack +// end subroutine test_allocatable_cst +// +// CHECK-LABEL: func.func @_QPtest_allocatable_cst( +// CHECK-NOT: fir.{{.*}}pack_array +func.func @_QPtest_allocatable_cst(%arg0: !fir.ref>>> {fir.bindc_name = "x"}) { + %c0 = arith.constant 0 : index + %c41 = arith.constant 41 : index + %c10 = arith.constant 10 : index + %0 = fir.dummy_scope : !fir.dscope + %1 = fir.declare %arg0 dummy_scope %0 {fortran_attrs = #fir.var_attrs, uniq_name = "_QFtest_allocatable_cstEx"} : (!fir.ref>>>, !fir.dscope) -> !fir.ref>>> + %2 = fir.load %1 : !fir.ref>>> + %3 = fir.shape %c41 : (index) -> !fir.shape<1> + %4 = fir.box_addr %2 : (!fir.box>>) -> !fir.heap> + %5:3 = fir.box_dims %2, %c0 : (!fir.box>>, index) -> (index, index, index) + %6 = fir.shape_shift %5#0, %5#1 : (index, index) -> !fir.shapeshift<1> + %7 = fir.array_coor %4(%6) %c10 : (!fir.heap>, !fir.shapeshift<1>, index) -> !fir.ref + %8 = fir.convert %7 : (!fir.ref) -> !fir.ref> + %9 = fir.embox %8(%3) : (!fir.ref>, !fir.shape<1>) -> !fir.box> + %10 = fir.convert %9 : (!fir.box>) -> !fir.box> + %11 = fir.dummy_scope : !fir.dscope + %12 = fir.pack_array %10 heap whole : (!fir.box>) -> !fir.box> + %13 = fir.declare %12 dummy_scope %11 {uniq_name = "_QFtest_allocatable_cstFrepackEx"} : (!fir.box>, !fir.dscope) -> !fir.box> + fir.unpack_array %12 to %10 heap : !fir.box> + return +} + +// subroutine test_allocatable_var(x, l, u) +// integer :: l, u +// real, allocatable :: x(:) +// call repack(x(l:u)) +// contains +// subroutine repack(x) +// real :: x(:) +// end subroutine repack +// end subroutine test_allocatable_var +// +// CHECK-LABEL: func.func @_QPtest_allocatable_var( +// CHECK-NOT: fir.{{.*}}pack_array +func.func @_QPtest_allocatable_var(%arg0: !fir.ref>>> {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "l"}, %arg2: !fir.ref {fir.bindc_name = "u"}) { + %c0 = arith.constant 0 : index + %c1 = arith.constant 1 : index + %0 = fir.dummy_scope : !fir.dscope + %1 = fir.declare %arg1 dummy_scope %0 {uniq_name = "_QFtest_allocatable_varEl"} : (!fir.ref, !fir.dscope) -> !fir.ref + %2 = fir.declare %arg2 dummy_scope %0 {uniq_name = "_QFtest_allocatable_varEu"} : (!fir.ref, !fir.dscope) -> !fir.ref + %3 = fir.declare %arg0 dummy_scope %0 {fortran_attrs = #fir.var_attrs, uniq_name = "_QFtest_allocatable_varEx"} : (!fir.ref>>>, !fir.dscope) -> !fir.ref>>> + %4 = fir.load %3 : !fir.ref>>> + %5 = fir.load %1 : !fir.ref + %6 = fir.load %2 : !fir.ref + %7 = fir.convert %5 : (i32) -> index + %8 = fir.convert %6 : (i32) -> index + %9 = fir.box_addr %4 : (!fir.box>>) -> !fir.heap> + %10:3 = fir.box_dims %4, %c0 : (!fir.box>>, index) -> (index, index, index) + %11 = fir.shape_shift %10#0, %10#1 : (index, index) -> !fir.shapeshift<1> + %12 = fir.slice %7, %8, %c1 : (index, index, index) -> !fir.slice<1> + %13 = fir.embox %9(%11) [%12] : (!fir.heap>, !fir.shapeshift<1>, !fir.slice<1>) -> !fir.box> + %14 = fir.dummy_scope : !fir.dscope + %15 = fir.pack_array %13 heap whole : (!fir.box>) -> !fir.box> + %16 = fir.declare %15 dummy_scope %14 {uniq_name = "_QFtest_allocatable_varFrepackEx"} : (!fir.box>, !fir.dscope) -> !fir.box> + fir.unpack_array %15 to %13 heap : !fir.box> + return +} + +// subroutine test_allocatable_full(x) +// real, allocatable :: x(:,:) +// call repack(x(:,:)) +// contains +// subroutine repack(x) +// real :: x(:,:) +// end subroutine repack +// end subroutine test_allocatable_full +// +// CHECK-LABEL: func.func @_QPtest_allocatable_full( +// CHECK-NOT: fir.{{.*}}pack_array +func.func @_QPtest_allocatable_full(%arg0: !fir.ref>>> {fir.bindc_name = "x"}) { + %c1 = arith.constant 1 : index + %c0 = arith.constant 0 : index + %0 = fir.dummy_scope : !fir.dscope + %1 = fir.declare %arg0 dummy_scope %0 {fortran_attrs = #fir.var_attrs, uniq_name = "_QFtest_allocatable_fullEx"} : (!fir.ref>>>, !fir.dscope) -> !fir.ref>>> + %2 = fir.load %1 : !fir.ref>>> + %3:3 = fir.box_dims %2, %c0 : (!fir.box>>, index) -> (index, index, index) + %4:3 = fir.box_dims %2, %c1 : (!fir.box>>, index) -> (index, index, index) + %5 = arith.addi %3#0, %3#1 : index + %6 = arith.subi %5, %c1 : index + %7 = arith.addi %4#0, %4#1 : index + %8 = arith.subi %7, %c1 : index + %9 = fir.box_addr %2 : (!fir.box>>) -> !fir.heap> + %10 = fir.shape_shift %3#0, %3#1, %4#0, %4#1 : (index, index, index, index) -> !fir.shapeshift<2> + %11 = fir.slice %3#0, %6, %c1, %4#0, %8, %c1 : (index, index, index, index, index, index) -> !fir.slice<2> + %12 = fir.embox %9(%10) [%11] : (!fir.heap>, !fir.shapeshift<2>, !fir.slice<2>) -> !fir.box> + %13 = fir.dummy_scope : !fir.dscope + %14 = fir.pack_array %12 heap innermost : (!fir.box>) -> !fir.box> + %15 = fir.declare %14 dummy_scope %13 {uniq_name = "_QFtest_allocatable_fullFrepackEx"} : (!fir.box>, !fir.dscope) -> !fir.box> + fir.unpack_array %14 to %12 heap : !fir.box> + return +} + +// subroutine test_explicit_shape_cst_chain(x) +// real :: x(100) +// call repack(x(1:50)) +// contains +// subroutine repack(x) +// use inner +// real :: x(:) +// call inner_repack1(x) +// end subroutine repack +// end subroutine test_explicit_shape_cst_chain +// +// CHECK-LABEL: func.func @_QPtest_explicit_shape_cst_chain( +// CHECK-NOT: fir.{{.*}}pack_array +func.func @_QPtest_explicit_shape_cst_chain(%arg0: !fir.ref> {fir.bindc_name = "x"}) { + %c50 = arith.constant 50 : index + %c1 = arith.constant 1 : index + %c100 = arith.constant 100 : index + %0 = fir.dummy_scope : !fir.dscope + %1 = fir.shape %c100 : (index) -> !fir.shape<1> + %2 = fir.declare %arg0(%1) dummy_scope %0 {uniq_name = "_QFtest_explicit_shape_cst_chainEx"} : (!fir.ref>, !fir.shape<1>, !fir.dscope) -> !fir.ref> + %3 = fir.shape %c50 : (index) -> !fir.shape<1> + %4 = fir.array_coor %2(%1) %c1 : (!fir.ref>, !fir.shape<1>, index) -> !fir.ref + %5 = fir.convert %4 : (!fir.ref) -> !fir.ref> + %6 = fir.embox %5(%3) : (!fir.ref>, !fir.shape<1>) -> !fir.box> + %7 = fir.convert %6 : (!fir.box>) -> !fir.box> + %8 = fir.dummy_scope : !fir.dscope + %9 = fir.pack_array %7 heap whole : (!fir.box>) -> !fir.box> + %10 = fir.declare %9 dummy_scope %8 {uniq_name = "_QFtest_explicit_shape_cst_chainFrepackEx"} : (!fir.box>, !fir.dscope) -> !fir.box> + %11 = fir.rebox %10 : (!fir.box>) -> !fir.box> + %12 = fir.dummy_scope : !fir.dscope + %13 = fir.pack_array %11 heap whole : (!fir.box>) -> !fir.box> + %14 = fir.declare %13 dummy_scope %12 {uniq_name = "_QMinnerFinner_repack1Ex"} : (!fir.box>, !fir.dscope) -> !fir.box> + fir.unpack_array %13 to %11 heap : !fir.box> + fir.unpack_array %9 to %7 heap : !fir.box> + return +} + +// subroutine test_explicit_shape_var_chain(x, n, l, u) +// integer :: n, l, u +// real :: x(n) +// call repack(x(l:u)) +// contains +// subroutine repack(x) +// use inner +// real :: x(:) +// call inner_repack1(x) +// end subroutine repack +// end subroutine test_explicit_shape_var_chain +// +// CHECK-LABEL: func.func @_QPtest_explicit_shape_var_chain( +// CHECK-NOT: fir.{{.*}}pack_array +func.func @_QPtest_explicit_shape_var_chain(%arg0: !fir.ref> {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "n"}, %arg2: !fir.ref {fir.bindc_name = "l"}, %arg3: !fir.ref {fir.bindc_name = "u"}) { + %c1 = arith.constant 1 : index + %c0 = arith.constant 0 : index + %0 = fir.dummy_scope : !fir.dscope + %1 = fir.declare %arg2 dummy_scope %0 {uniq_name = "_QFtest_explicit_shape_var_chainEl"} : (!fir.ref, !fir.dscope) -> !fir.ref + %2 = fir.declare %arg1 dummy_scope %0 {uniq_name = "_QFtest_explicit_shape_var_chainEn"} : (!fir.ref, !fir.dscope) -> !fir.ref + %3 = fir.declare %arg3 dummy_scope %0 {uniq_name = "_QFtest_explicit_shape_var_chainEu"} : (!fir.ref, !fir.dscope) -> !fir.ref + %4 = fir.load %2 : !fir.ref + %5 = fir.convert %4 : (i32) -> index + %6 = arith.cmpi sgt, %5, %c0 : index + %7 = arith.select %6, %5, %c0 : index + %8 = fir.shape %7 : (index) -> !fir.shape<1> + %9 = fir.declare %arg0(%8) dummy_scope %0 {uniq_name = "_QFtest_explicit_shape_var_chainEx"} : (!fir.ref>, !fir.shape<1>, !fir.dscope) -> !fir.ref> + %10 = fir.load %1 : !fir.ref + %11 = fir.load %3 : !fir.ref + %12 = fir.convert %10 : (i32) -> index + %13 = fir.convert %11 : (i32) -> index + %14 = fir.slice %12, %13, %c1 : (index, index, index) -> !fir.slice<1> + %15 = fir.embox %9(%8) [%14] : (!fir.ref>, !fir.shape<1>, !fir.slice<1>) -> !fir.box> + %16 = fir.dummy_scope : !fir.dscope + %17 = fir.pack_array %15 heap whole : (!fir.box>) -> !fir.box> + %18 = fir.declare %17 dummy_scope %16 {uniq_name = "_QFtest_explicit_shape_var_chainFrepackEx"} : (!fir.box>, !fir.dscope) -> !fir.box> + %19 = fir.rebox %18 : (!fir.box>) -> !fir.box> + %20 = fir.dummy_scope : !fir.dscope + %21 = fir.pack_array %19 heap whole : (!fir.box>) -> !fir.box> + %22 = fir.declare %21 dummy_scope %20 {uniq_name = "_QMinnerFinner_repack1Ex"} : (!fir.box>, !fir.dscope) -> !fir.box> + fir.unpack_array %21 to %19 heap : !fir.box> + fir.unpack_array %17 to %15 heap : !fir.box> + return +} + +// subroutine test_assumed_size_cst_chain(x) +// real :: x(*) +// call repack(x(1:50)) +// contains +// subroutine repack(x) +// use inner +// real :: x(:) +// call inner_repack1(x) +// end subroutine repack +// end subroutine test_assumed_size_cst_chain +// +// CHECK-LABEL: func.func @_QPtest_assumed_size_cst_chain( +// CHECK-NOT: fir.{{.*}}pack_array +func.func @_QPtest_assumed_size_cst_chain(%arg0: !fir.ref> {fir.bindc_name = "x"}) { + %c50 = arith.constant 50 : index + %c1 = arith.constant 1 : index + %c-1 = arith.constant -1 : index + %0 = fir.dummy_scope : !fir.dscope + %1 = fir.shape %c-1 : (index) -> !fir.shape<1> + %2 = fir.declare %arg0(%1) dummy_scope %0 {uniq_name = "_QFtest_assumed_size_cst_chainEx"} : (!fir.ref>, !fir.shape<1>, !fir.dscope) -> !fir.ref> + %3 = fir.shape %c50 : (index) -> !fir.shape<1> + %4 = fir.array_coor %2(%1) %c1 : (!fir.ref>, !fir.shape<1>, index) -> !fir.ref + %5 = fir.convert %4 : (!fir.ref) -> !fir.ref> + %6 = fir.embox %5(%3) : (!fir.ref>, !fir.shape<1>) -> !fir.box> + %7 = fir.convert %6 : (!fir.box>) -> !fir.box> + %8 = fir.dummy_scope : !fir.dscope + %9 = fir.pack_array %7 heap whole : (!fir.box>) -> !fir.box> + %10 = fir.declare %9 dummy_scope %8 {uniq_name = "_QFtest_assumed_size_cst_chainFrepackEx"} : (!fir.box>, !fir.dscope) -> !fir.box> + %11 = fir.rebox %10 : (!fir.box>) -> !fir.box> + %12 = fir.dummy_scope : !fir.dscope + %13 = fir.pack_array %11 heap whole : (!fir.box>) -> !fir.box> + %14 = fir.declare %13 dummy_scope %12 {uniq_name = "_QMinnerFinner_repack1Ex"} : (!fir.box>, !fir.dscope) -> !fir.box> + fir.unpack_array %13 to %11 heap : !fir.box> + fir.unpack_array %9 to %7 heap : !fir.box> + return +} + +// subroutine test_assumed_size_var_chain(x, l, u) +// integer :: l, u +// real :: x(*) +// call repack(x(l:u)) +// contains +// subroutine repack(x) +// use inner +// real :: x(:) +// call inner_repack1(x) +// end subroutine repack +// end subroutine test_assumed_size_var_chain +// +// CHECK-LABEL: func.func @_QPtest_assumed_size_var_chain( +// CHECK-NOT: fir.{{.*}}pack_array +func.func @_QPtest_assumed_size_var_chain(%arg0: !fir.ref> {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "l"}, %arg2: !fir.ref {fir.bindc_name = "u"}) { + %c1 = arith.constant 1 : index + %c-1 = arith.constant -1 : index + %0 = fir.dummy_scope : !fir.dscope + %1 = fir.declare %arg1 dummy_scope %0 {uniq_name = "_QFtest_assumed_size_var_chainEl"} : (!fir.ref, !fir.dscope) -> !fir.ref + %2 = fir.declare %arg2 dummy_scope %0 {uniq_name = "_QFtest_assumed_size_var_chainEu"} : (!fir.ref, !fir.dscope) -> !fir.ref + %3 = fir.shape %c-1 : (index) -> !fir.shape<1> + %4 = fir.declare %arg0(%3) dummy_scope %0 {uniq_name = "_QFtest_assumed_size_var_chainEx"} : (!fir.ref>, !fir.shape<1>, !fir.dscope) -> !fir.ref> + %5 = fir.load %1 : !fir.ref + %6 = fir.load %2 : !fir.ref + %7 = fir.convert %5 : (i32) -> index + %8 = fir.convert %6 : (i32) -> index + %9 = fir.slice %7, %8, %c1 : (index, index, index) -> !fir.slice<1> + %10 = fir.embox %4(%3) [%9] : (!fir.ref>, !fir.shape<1>, !fir.slice<1>) -> !fir.box> + %11 = fir.dummy_scope : !fir.dscope + %12 = fir.pack_array %10 heap whole : (!fir.box>) -> !fir.box> + %13 = fir.declare %12 dummy_scope %11 {uniq_name = "_QFtest_assumed_size_var_chainFrepackEx"} : (!fir.box>, !fir.dscope) -> !fir.box> + %14 = fir.rebox %13 : (!fir.box>) -> !fir.box> + %15 = fir.dummy_scope : !fir.dscope + %16 = fir.pack_array %14 heap whole : (!fir.box>) -> !fir.box> + %17 = fir.declare %16 dummy_scope %15 {uniq_name = "_QMinnerFinner_repack1Ex"} : (!fir.box>, !fir.dscope) -> !fir.box> + fir.unpack_array %16 to %14 heap : !fir.box> + fir.unpack_array %12 to %10 heap : !fir.box> + return +} + +// subroutine test_allocatable_cst_chain(x) +// real, allocatable :: x(:) +// call repack(x(10:50)) +// contains +// subroutine repack(x) +// use inner +// real :: x(:) +// call inner_repack1(x) +// end subroutine repack +// end subroutine test_allocatable_cst_chain +// +// CHECK-LABEL: func.func @_QPtest_allocatable_cst_chain( +// CHECK-NOT: fir.{{.*}}pack_array +func.func @_QPtest_allocatable_cst_chain(%arg0: !fir.ref>>> {fir.bindc_name = "x"}) { + %c0 = arith.constant 0 : index + %c41 = arith.constant 41 : index + %c10 = arith.constant 10 : index + %0 = fir.dummy_scope : !fir.dscope + %1 = fir.declare %arg0 dummy_scope %0 {fortran_attrs = #fir.var_attrs, uniq_name = "_QFtest_allocatable_cst_chainEx"} : (!fir.ref>>>, !fir.dscope) -> !fir.ref>>> + %2 = fir.load %1 : !fir.ref>>> + %3 = fir.shape %c41 : (index) -> !fir.shape<1> + %4 = fir.box_addr %2 : (!fir.box>>) -> !fir.heap> + %5:3 = fir.box_dims %2, %c0 : (!fir.box>>, index) -> (index, index, index) + %6 = fir.shape_shift %5#0, %5#1 : (index, index) -> !fir.shapeshift<1> + %7 = fir.array_coor %4(%6) %c10 : (!fir.heap>, !fir.shapeshift<1>, index) -> !fir.ref + %8 = fir.convert %7 : (!fir.ref) -> !fir.ref> + %9 = fir.embox %8(%3) : (!fir.ref>, !fir.shape<1>) -> !fir.box> + %10 = fir.convert %9 : (!fir.box>) -> !fir.box> + %11 = fir.dummy_scope : !fir.dscope + %12 = fir.pack_array %10 heap whole : (!fir.box>) -> !fir.box> + %13 = fir.declare %12 dummy_scope %11 {uniq_name = "_QFtest_allocatable_cst_chainFrepackEx"} : (!fir.box>, !fir.dscope) -> !fir.box> + %14 = fir.rebox %13 : (!fir.box>) -> !fir.box> + %15 = fir.dummy_scope : !fir.dscope + %16 = fir.pack_array %14 heap whole : (!fir.box>) -> !fir.box> + %17 = fir.declare %16 dummy_scope %15 {uniq_name = "_QMinnerFinner_repack1Ex"} : (!fir.box>, !fir.dscope) -> !fir.box> + fir.unpack_array %16 to %14 heap : !fir.box> + fir.unpack_array %12 to %10 heap : !fir.box> + return +} + +// subroutine test_allocatable_var_chain(x, l, u) +// integer :: l, u +// real, allocatable :: x(:) +// call repack(x(l:u)) +// contains +// subroutine repack(x) +// use inner +// real :: x(:) +// call inner_repack1(x) +// end subroutine repack +// end subroutine test_allocatable_var_chain +// +// CHECK-LABEL: func.func @_QPtest_allocatable_var_chain( +// CHECK-NOT: fir.{{.*}}pack_array +func.func @_QPtest_allocatable_var_chain(%arg0: !fir.ref>>> {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "l"}, %arg2: !fir.ref {fir.bindc_name = "u"}) { + %c0 = arith.constant 0 : index + %c1 = arith.constant 1 : index + %0 = fir.dummy_scope : !fir.dscope + %1 = fir.declare %arg1 dummy_scope %0 {uniq_name = "_QFtest_allocatable_var_chainEl"} : (!fir.ref, !fir.dscope) -> !fir.ref + %2 = fir.declare %arg2 dummy_scope %0 {uniq_name = "_QFtest_allocatable_var_chainEu"} : (!fir.ref, !fir.dscope) -> !fir.ref + %3 = fir.declare %arg0 dummy_scope %0 {fortran_attrs = #fir.var_attrs, uniq_name = "_QFtest_allocatable_var_chainEx"} : (!fir.ref>>>, !fir.dscope) -> !fir.ref>>> + %4 = fir.load %3 : !fir.ref>>> + %5 = fir.load %1 : !fir.ref + %6 = fir.load %2 : !fir.ref + %7 = fir.convert %5 : (i32) -> index + %8 = fir.convert %6 : (i32) -> index + %9 = fir.box_addr %4 : (!fir.box>>) -> !fir.heap> + %10:3 = fir.box_dims %4, %c0 : (!fir.box>>, index) -> (index, index, index) + %11 = fir.shape_shift %10#0, %10#1 : (index, index) -> !fir.shapeshift<1> + %12 = fir.slice %7, %8, %c1 : (index, index, index) -> !fir.slice<1> + %13 = fir.embox %9(%11) [%12] : (!fir.heap>, !fir.shapeshift<1>, !fir.slice<1>) -> !fir.box> + %14 = fir.dummy_scope : !fir.dscope + %15 = fir.pack_array %13 heap whole : (!fir.box>) -> !fir.box> + %16 = fir.declare %15 dummy_scope %14 {uniq_name = "_QFtest_allocatable_var_chainFrepackEx"} : (!fir.box>, !fir.dscope) -> !fir.box> + %17 = fir.rebox %16 : (!fir.box>) -> !fir.box> + %18 = fir.dummy_scope : !fir.dscope + %19 = fir.pack_array %17 heap whole : (!fir.box>) -> !fir.box> + %20 = fir.declare %19 dummy_scope %18 {uniq_name = "_QMinnerFinner_repack1Ex"} : (!fir.box>, !fir.dscope) -> !fir.box> + fir.unpack_array %19 to %17 heap : !fir.box> + fir.unpack_array %15 to %13 heap : !fir.box> + return +} + +// subroutine test_allocatable_full_chain(x) +// real, allocatable :: x(:,:) +// call repack(x(:,:)) +// contains +// subroutine repack(x) +// use inner +// real :: x(:,:) +// call inner_repack2(x) +// end subroutine repack +// end subroutine test_allocatable_full_chain +// +// CHECK-LABEL: func.func @_QPtest_allocatable_full_chain( +// CHECK-NOT: fir.{{.*}}pack_array +func.func @_QPtest_allocatable_full_chain(%arg0: !fir.ref>>> {fir.bindc_name = "x"}) { + %c1 = arith.constant 1 : index + %c0 = arith.constant 0 : index + %0 = fir.dummy_scope : !fir.dscope + %1 = fir.declare %arg0 dummy_scope %0 {fortran_attrs = #fir.var_attrs, uniq_name = "_QFtest_allocatable_full_chainEx"} : (!fir.ref>>>, !fir.dscope) -> !fir.ref>>> + %2 = fir.load %1 : !fir.ref>>> + %3:3 = fir.box_dims %2, %c0 : (!fir.box>>, index) -> (index, index, index) + %4:3 = fir.box_dims %2, %c1 : (!fir.box>>, index) -> (index, index, index) + %5 = arith.addi %3#0, %3#1 : index + %6 = arith.subi %5, %c1 : index + %7 = arith.addi %4#0, %4#1 : index + %8 = arith.subi %7, %c1 : index + %9 = fir.box_addr %2 : (!fir.box>>) -> !fir.heap> + %10 = fir.shape_shift %3#0, %3#1, %4#0, %4#1 : (index, index, index, index) -> !fir.shapeshift<2> + %11 = fir.slice %3#0, %6, %c1, %4#0, %8, %c1 : (index, index, index, index, index, index) -> !fir.slice<2> + %12 = fir.embox %9(%10) [%11] : (!fir.heap>, !fir.shapeshift<2>, !fir.slice<2>) -> !fir.box> + %13 = fir.dummy_scope : !fir.dscope + %14 = fir.pack_array %12 heap innermost : (!fir.box>) -> !fir.box> + %15 = fir.declare %14 dummy_scope %13 {uniq_name = "_QFtest_allocatable_full_chainFrepackEx"} : (!fir.box>, !fir.dscope) -> !fir.box> + %16 = fir.rebox %15 : (!fir.box>) -> !fir.box> + %17 = fir.dummy_scope : !fir.dscope + %18 = fir.pack_array %16 heap innermost : (!fir.box>) -> !fir.box> + %19 = fir.declare %18 dummy_scope %17 {uniq_name = "_QMinnerFinner_repack2Ex"} : (!fir.box>, !fir.dscope) -> !fir.box> + fir.unpack_array %18 to %16 heap : !fir.box> + fir.unpack_array %14 to %12 heap : !fir.box> + return +} + +// TODO: if both fir.pack_array have the same property, +// then the second one is redundant, because the first +// repack makes 'x' contiguous. +// subroutine neg_test_assumed_shape(x) +// real :: x(:) +// call repack(x(1:50)) +// contains +// subroutine repack(x) +// real :: x(:) +// end subroutine repack +// end subroutine neg_test_assumed_shape +// +// CHECK-LABEL: func.func @_QPneg_test_assumed_shape( +// CHECK: fir.pack_array +// CHECK: fir.pack_array +// CHECK: fir.unpack_array +// CHECK: fir.unpack_array +func.func @_QPneg_test_assumed_shape(%arg0: !fir.box> {fir.bindc_name = "x"}) { + %c50 = arith.constant 50 : index + %c1 = arith.constant 1 : index + %0 = fir.dummy_scope : !fir.dscope + %1 = fir.pack_array %arg0 heap whole : (!fir.box>) -> !fir.box> + %2 = fir.declare %1 dummy_scope %0 {uniq_name = "_QFneg_test_assumed_shapeEx"} : (!fir.box>, !fir.dscope) -> !fir.box> + %3 = fir.rebox %2 : (!fir.box>) -> !fir.box> + %4 = fir.slice %c1, %c50, %c1 : (index, index, index) -> !fir.slice<1> + %5 = fir.rebox %3 [%4] : (!fir.box>, !fir.slice<1>) -> !fir.box> + %6 = fir.convert %5 : (!fir.box>) -> !fir.box> + %7 = fir.dummy_scope : !fir.dscope + %8 = fir.pack_array %6 heap whole : (!fir.box>) -> !fir.box> + %9 = fir.declare %8 dummy_scope %7 {uniq_name = "_QFneg_test_assumed_shapeFrepackEx"} : (!fir.box>, !fir.dscope) -> !fir.box> + fir.unpack_array %8 to %6 heap : !fir.box> + fir.unpack_array %1 to %arg0 heap : !fir.box> + return +} + +// subroutine neg_test_non_contig_slice_cst(x) +// real :: x(100) +// call repack(x(1:50:2)) +// contains +// subroutine repack(x) +// real :: x(:) +// end subroutine repack +// end subroutine neg_test_non_contig_slice_cst +// +// CHECK-LABEL: func.func @_QPneg_test_non_contig_slice_cst( +// CHECK: fir.pack_array +// CHECK: fir.unpack_array +func.func @_QPneg_test_non_contig_slice_cst(%arg0: !fir.ref> {fir.bindc_name = "x"}) { + %c2 = arith.constant 2 : index + %c50 = arith.constant 50 : index + %c1 = arith.constant 1 : index + %c100 = arith.constant 100 : index + %0 = fir.dummy_scope : !fir.dscope + %1 = fir.shape %c100 : (index) -> !fir.shape<1> + %2 = fir.declare %arg0(%1) dummy_scope %0 {uniq_name = "_QFneg_test_non_contig_slice_cstEx"} : (!fir.ref>, !fir.shape<1>, !fir.dscope) -> !fir.ref> + %3 = fir.slice %c1, %c50, %c2 : (index, index, index) -> !fir.slice<1> + %4 = fir.embox %2(%1) [%3] : (!fir.ref>, !fir.shape<1>, !fir.slice<1>) -> !fir.box> + %5 = fir.convert %4 : (!fir.box>) -> !fir.box> + %6 = fir.dummy_scope : !fir.dscope + %7 = fir.pack_array %5 heap whole : (!fir.box>) -> !fir.box> + %8 = fir.declare %7 dummy_scope %6 {uniq_name = "_QFneg_test_non_contig_slice_cstFrepackEx"} : (!fir.box>, !fir.dscope) -> !fir.box> + fir.unpack_array %7 to %5 heap : !fir.box> + return +} + +// subroutine neg_test_non_contig_slice_var(x, s) +// integer :: s +// real :: x(100) +// call repack(x(1:50:s)) +// contains +// subroutine repack(x) +// real :: x(:) +// end subroutine repack +// end subroutine neg_test_non_contig_slice_var +// +// CHECK-LABEL: func.func @_QPneg_test_non_contig_slice_var( +// CHECK: fir.pack_array +// CHECK: fir.unpack_array +func.func @_QPneg_test_non_contig_slice_var(%arg0: !fir.ref> {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "s"}) { + %c50 = arith.constant 50 : index + %c1 = arith.constant 1 : index + %c100 = arith.constant 100 : index + %0 = fir.dummy_scope : !fir.dscope + %1 = fir.declare %arg1 dummy_scope %0 {uniq_name = "_QFneg_test_non_contig_slice_varEs"} : (!fir.ref, !fir.dscope) -> !fir.ref + %2 = fir.shape %c100 : (index) -> !fir.shape<1> + %3 = fir.declare %arg0(%2) dummy_scope %0 {uniq_name = "_QFneg_test_non_contig_slice_varEx"} : (!fir.ref>, !fir.shape<1>, !fir.dscope) -> !fir.ref> + %4 = fir.load %1 : !fir.ref + %5 = fir.convert %4 : (i32) -> index + %6 = fir.slice %c1, %c50, %5 : (index, index, index) -> !fir.slice<1> + %7 = fir.embox %3(%2) [%6] : (!fir.ref>, !fir.shape<1>, !fir.slice<1>) -> !fir.box> + %8 = fir.dummy_scope : !fir.dscope + %9 = fir.pack_array %7 heap whole : (!fir.box>) -> !fir.box> + %10 = fir.declare %9 dummy_scope %8 {uniq_name = "_QFneg_test_non_contig_slice_varFrepackEx"} : (!fir.box>, !fir.dscope) -> !fir.box> + fir.unpack_array %9 to %7 heap : !fir.box> + return +} + +// subroutine neg_test_pointer(x) +// real, pointer :: x(:) +// call repack(x(1:50)) +// contains +// subroutine repack(x) +// real :: x(:) +// end subroutine repack +// end subroutine neg_test_pointer +// +// CHECK-LABEL: func.func @_QPneg_test_pointer( +// CHECK: fir.pack_array +// CHECK: fir.unpack_array +func.func @_QPneg_test_pointer(%arg0: !fir.ref>>> {fir.bindc_name = "x"}) { + %c0 = arith.constant 0 : index + %c50 = arith.constant 50 : index + %c1 = arith.constant 1 : index + %0 = fir.dummy_scope : !fir.dscope + %1 = fir.declare %arg0 dummy_scope %0 {fortran_attrs = #fir.var_attrs, uniq_name = "_QFneg_test_pointerEx"} : (!fir.ref>>>, !fir.dscope) -> !fir.ref>>> + %2 = fir.load %1 : !fir.ref>>> + %3:3 = fir.box_dims %2, %c0 : (!fir.box>>, index) -> (index, index, index) + %4 = fir.shift %3#0 : (index) -> !fir.shift<1> + %5 = fir.slice %c1, %c50, %c1 : (index, index, index) -> !fir.slice<1> + %6 = fir.rebox %2(%4) [%5] : (!fir.box>>, !fir.shift<1>, !fir.slice<1>) -> !fir.box> + %7 = fir.convert %6 : (!fir.box>) -> !fir.box> + %8 = fir.dummy_scope : !fir.dscope + %9 = fir.pack_array %7 heap whole : (!fir.box>) -> !fir.box> + %10 = fir.declare %9 dummy_scope %8 {uniq_name = "_QFneg_test_pointerFrepackEx"} : (!fir.box>, !fir.dscope) -> !fir.box> + fir.unpack_array %9 to %7 heap : !fir.box> + return +}