diff --git a/flang/include/flang/Optimizer/HLFIR/Passes.h b/flang/include/flang/Optimizer/HLFIR/Passes.h --- a/flang/include/flang/Optimizer/HLFIR/Passes.h +++ b/flang/include/flang/Optimizer/HLFIR/Passes.h @@ -23,6 +23,7 @@ std::unique_ptr createConvertHLFIRtoFIRPass(); std::unique_ptr createBufferizeHLFIRPass(); +std::unique_ptr createLowerHLFIRIntrinsicsPass(); #define GEN_PASS_REGISTRATION #include "flang/Optimizer/HLFIR/Passes.h.inc" diff --git a/flang/include/flang/Optimizer/HLFIR/Passes.td b/flang/include/flang/Optimizer/HLFIR/Passes.td --- a/flang/include/flang/Optimizer/HLFIR/Passes.td +++ b/flang/include/flang/Optimizer/HLFIR/Passes.td @@ -20,4 +20,9 @@ let constructor = "hlfir::createBufferizeHLFIRPass()"; } +def LowerHLFIRIntrinsics : Pass<"lower-hlfir-intrinsics", "::mlir::ModuleOp"> { + let summary = "Lower HLFIR transformational intrinsic operations"; + let constructor = "hlfir::createLowerHLFIRIntrinsicsPass()"; +} + #endif //FORTRAN_DIALECT_HLFIR_PASSES diff --git a/flang/lib/Optimizer/HLFIR/Transforms/BufferizeHLFIR.cpp b/flang/lib/Optimizer/HLFIR/Transforms/BufferizeHLFIR.cpp --- a/flang/lib/Optimizer/HLFIR/Transforms/BufferizeHLFIR.cpp +++ b/flang/lib/Optimizer/HLFIR/Transforms/BufferizeHLFIR.cpp @@ -15,8 +15,6 @@ #include "flang/Optimizer/Builder/Character.h" #include "flang/Optimizer/Builder/FIRBuilder.h" #include "flang/Optimizer/Builder/HLFIRTools.h" -#include "flang/Optimizer/Builder/IntrinsicCall.h" -#include "flang/Optimizer/Builder/MutableBox.h" #include "flang/Optimizer/Builder/Runtime/Assign.h" #include "flang/Optimizer/Builder/Todo.h" #include "flang/Optimizer/Dialect/FIRDialect.h" @@ -31,7 +29,6 @@ #include "mlir/Pass/PassManager.h" #include "mlir/Transforms/DialectConversion.h" #include -#include namespace hlfir { #define GEN_PASS_DEF_BUFFERIZEHLFIR @@ -510,219 +507,6 @@ } }; -/// Base class for passes converting transformational intrinsic operations into -/// runtime calls -template -class HlfirIntrinsicConversion : public mlir::OpConversionPattern { - using mlir::OpConversionPattern::OpConversionPattern; - -protected: - struct IntrinsicArgument { - mlir::Value val; // allowed to be null if the argument is absent - mlir::Type desiredType; - }; - - /// Lower the arguments to the intrinsic: adding nesecarry boxing and - /// conversion to match the signature of the intrinsic in the runtime library. - llvm::SmallVector - lowerArguments(mlir::Operation *op, - const llvm::ArrayRef &args, - mlir::ConversionPatternRewriter &rewriter, - const fir::IntrinsicArgumentLoweringRules *argLowering) const { - mlir::Location loc = op->getLoc(); - fir::KindMapping kindMapping{rewriter.getContext()}; - fir::FirOpBuilder builder{rewriter, kindMapping}; - - llvm::SmallVector ret; - - for (size_t i = 0; i < args.size(); ++i) { - mlir::Value arg = args[i].val; - mlir::Type desiredType = args[i].desiredType; - if (!arg) { - ret.emplace_back(fir::getAbsentIntrinsicArgument()); - continue; - } - hlfir::Entity entity{arg}; - - fir::ArgLoweringRule argRules = - fir::lowerIntrinsicArgumentAs(*argLowering, i); - switch (argRules.lowerAs) { - case fir::LowerIntrinsicArgAs::Value: { - if (args[i].desiredType != arg.getType()) { - arg = builder.createConvert(loc, desiredType, arg); - entity = hlfir::Entity{arg}; - } - auto [exv, cleanup] = hlfir::convertToValue(loc, builder, entity); - if (cleanup) - TODO(loc, "extended value cleanup"); - ret.emplace_back(exv); - } break; - case fir::LowerIntrinsicArgAs::Addr: { - auto [exv, cleanup] = - hlfir::convertToAddress(loc, builder, entity, desiredType); - if (cleanup) - TODO(loc, "extended value cleanup"); - ret.emplace_back(exv); - } break; - case fir::LowerIntrinsicArgAs::Box: { - auto [box, cleanup] = - hlfir::convertToBox(loc, builder, entity, desiredType); - if (cleanup) - TODO(loc, "extended value cleanup"); - ret.emplace_back(box); - } break; - case fir::LowerIntrinsicArgAs::Inquired: { - if (args[i].desiredType != arg.getType()) { - arg = builder.createConvert(loc, desiredType, arg); - entity = hlfir::Entity{arg}; - } - // Place hlfir.expr in memory, and unbox fir.boxchar. Other entities - // are translated to fir::ExtendedValue without transofrmation (notably, - // pointers/allocatable are not dereferenced). - // TODO: once lowering to FIR retires, UBOUND and LBOUND can be - // simplified since the fir.box lowered here are now guarenteed to - // contain the local lower bounds thanks to the hlfir.declare (the extra - // rebox can be removed). - auto [exv, cleanup] = - hlfir::translateToExtendedValue(loc, builder, entity); - if (cleanup) - TODO(loc, "extended value cleanup"); - ret.emplace_back(exv); - } break; - } - } - - return ret; - } - - void processReturnValue(mlir::Operation *op, - const fir::ExtendedValue &resultExv, bool mustBeFreed, - fir::FirOpBuilder &builder, - mlir::PatternRewriter &rewriter) const { - mlir::Location loc = op->getLoc(); - - mlir::Value firBase = fir::getBase(resultExv); - mlir::Type firBaseTy = firBase.getType(); - - std::optional resultEntity; - if (fir::isa_trivial(firBaseTy)) { - resultEntity = hlfir::EntityWithAttributes{firBase}; - } else { - resultEntity = - hlfir::genDeclare(loc, builder, resultExv, ".tmp.intrinsic_result", - fir::FortranVariableFlagsAttr{}); - } - - if (resultEntity->isVariable()) { - hlfir::AsExprOp asExpr = builder.create( - loc, *resultEntity, builder.createBool(loc, mustBeFreed)); - resultEntity = hlfir::EntityWithAttributes{asExpr.getResult()}; - } - - rewriter.replaceOp(op, resultEntity->getBase()); - } -}; - -struct SumOpConversion : public HlfirIntrinsicConversion { - using HlfirIntrinsicConversion::HlfirIntrinsicConversion; - - mlir::LogicalResult - matchAndRewrite(hlfir::SumOp sum, OpAdaptor adaptor, - mlir::ConversionPatternRewriter &rewriter) const override { - fir::KindMapping kindMapping{rewriter.getContext()}; - fir::FirOpBuilder builder{rewriter, kindMapping}; - const mlir::Location &loc = sum->getLoc(); - HLFIRListener listener{builder, rewriter}; - builder.setListener(&listener); - - mlir::Type i32 = builder.getI32Type(); - mlir::Type logicalType = fir::LogicalType::get( - builder.getContext(), builder.getKindMap().defaultLogicalKind()); - - llvm::SmallVector inArgs; - inArgs.push_back({sum.getArray(), sum.getArray().getType()}); - inArgs.push_back({sum.getDim(), i32}); - inArgs.push_back({sum.getMask(), logicalType}); - - auto *argLowering = fir::getIntrinsicArgumentLowering("sum"); - llvm::SmallVector args = - lowerArguments(sum, inArgs, rewriter, argLowering); - - mlir::Type scalarResultType = hlfir::getFortranElementType(sum.getType()); - - auto [resultExv, mustBeFreed] = - fir::genIntrinsicCall(builder, loc, "sum", scalarResultType, args); - - processReturnValue(sum, resultExv, mustBeFreed, builder, rewriter); - return mlir::success(); - } -}; - -struct MatmulOpConversion : public HlfirIntrinsicConversion { - using HlfirIntrinsicConversion::HlfirIntrinsicConversion; - - mlir::LogicalResult - matchAndRewrite(hlfir::MatmulOp matmul, OpAdaptor adaptor, - mlir::ConversionPatternRewriter &rewriter) const override { - fir::KindMapping kindMapping{rewriter.getContext()}; - fir::FirOpBuilder builder{rewriter, kindMapping}; - const mlir::Location &loc = matmul->getLoc(); - HLFIRListener listener{builder, rewriter}; - builder.setListener(&listener); - - mlir::Value lhs = matmul.getLhs(); - mlir::Value rhs = matmul.getRhs(); - llvm::SmallVector inArgs; - inArgs.push_back({lhs, lhs.getType()}); - inArgs.push_back({rhs, rhs.getType()}); - - auto *argLowering = fir::getIntrinsicArgumentLowering("matmul"); - llvm::SmallVector args = - lowerArguments(matmul, inArgs, rewriter, argLowering); - - mlir::Type scalarResultType = - hlfir::getFortranElementType(matmul.getType()); - - auto [resultExv, mustBeFreed] = - fir::genIntrinsicCall(builder, loc, "matmul", scalarResultType, args); - - processReturnValue(matmul, resultExv, mustBeFreed, builder, rewriter); - return mlir::success(); - } -}; - -class TransposeOpConversion - : public HlfirIntrinsicConversion { - using HlfirIntrinsicConversion::HlfirIntrinsicConversion; - - mlir::LogicalResult - matchAndRewrite(hlfir::TransposeOp transpose, OpAdaptor adaptor, - mlir::ConversionPatternRewriter &rewriter) const override { - fir::KindMapping kindMapping{rewriter.getContext()}; - fir::FirOpBuilder builder{rewriter, kindMapping}; - const mlir::Location &loc = transpose->getLoc(); - HLFIRListener listener{builder, rewriter}; - builder.setListener(&listener); - - mlir::Value arg = transpose.getArray(); - llvm::SmallVector inArgs; - inArgs.push_back({arg, arg.getType()}); - - auto *argLowering = fir::getIntrinsicArgumentLowering("transpose"); - llvm::SmallVector args = - lowerArguments(transpose, inArgs, rewriter, argLowering); - - mlir::Type scalarResultType = - hlfir::getFortranElementType(transpose.getType()); - - auto [resultExv, mustBeFreed] = fir::genIntrinsicCall( - builder, loc, "transpose", scalarResultType, args); - - processReturnValue(transpose, resultExv, mustBeFreed, builder, rewriter); - return mlir::success(); - } -}; - class BufferizeHLFIR : public hlfir::impl::BufferizeHLFIRBase { public: void runOnOperation() override { @@ -740,9 +524,7 @@ .insert( - context); + NoReassocOpConversion, SetLengthOpConversion>(context); mlir::ConversionTarget target(*context); target.addIllegalOp + +namespace hlfir { +#define GEN_PASS_DEF_LOWERHLFIRINTRINSICS +#include "flang/Optimizer/HLFIR/Passes.h.inc" +} // namespace hlfir + +namespace { + +/// Base class for passes converting transformational intrinsic operations into +/// runtime calls +template +class HlfirIntrinsicConversion : public mlir::OpRewritePattern { + using mlir::OpRewritePattern::OpRewritePattern; + +protected: + struct IntrinsicArgument { + mlir::Value val; // allowed to be null if the argument is absent + mlir::Type desiredType; + }; + + /// Lower the arguments to the intrinsic: adding nesecarry boxing and + /// conversion to match the signature of the intrinsic in the runtime library. + llvm::SmallVector + lowerArguments(mlir::Operation *op, + const llvm::ArrayRef &args, + mlir::PatternRewriter &rewriter, + const fir::IntrinsicArgumentLoweringRules *argLowering) const { + mlir::Location loc = op->getLoc(); + fir::KindMapping kindMapping{rewriter.getContext()}; + fir::FirOpBuilder builder{rewriter, kindMapping}; + + llvm::SmallVector ret; + + for (size_t i = 0; i < args.size(); ++i) { + mlir::Value arg = args[i].val; + mlir::Type desiredType = args[i].desiredType; + if (!arg) { + ret.emplace_back(fir::getAbsentIntrinsicArgument()); + continue; + } + hlfir::Entity entity{arg}; + + fir::ArgLoweringRule argRules = + fir::lowerIntrinsicArgumentAs(*argLowering, i); + switch (argRules.lowerAs) { + case fir::LowerIntrinsicArgAs::Value: { + if (args[i].desiredType != arg.getType()) { + arg = builder.createConvert(loc, desiredType, arg); + entity = hlfir::Entity{arg}; + } + auto [exv, cleanup] = hlfir::convertToValue(loc, builder, entity); + if (cleanup) + TODO(loc, "extended value cleanup"); + ret.emplace_back(exv); + } break; + case fir::LowerIntrinsicArgAs::Addr: { + auto [exv, cleanup] = + hlfir::convertToAddress(loc, builder, entity, desiredType); + if (cleanup) + TODO(loc, "extended value cleanup"); + ret.emplace_back(exv); + } break; + case fir::LowerIntrinsicArgAs::Box: { + auto [box, cleanup] = + hlfir::convertToBox(loc, builder, entity, desiredType); + if (cleanup) + TODO(loc, "extended value cleanup"); + ret.emplace_back(box); + } break; + case fir::LowerIntrinsicArgAs::Inquired: { + if (args[i].desiredType != arg.getType()) { + arg = builder.createConvert(loc, desiredType, arg); + entity = hlfir::Entity{arg}; + } + // Place hlfir.expr in memory, and unbox fir.boxchar. Other entities + // are translated to fir::ExtendedValue without transofrmation (notably, + // pointers/allocatable are not dereferenced). + // TODO: once lowering to FIR retires, UBOUND and LBOUND can be + // simplified since the fir.box lowered here are now guarenteed to + // contain the local lower bounds thanks to the hlfir.declare (the extra + // rebox can be removed). + auto [exv, cleanup] = + hlfir::translateToExtendedValue(loc, builder, entity); + if (cleanup) + TODO(loc, "extended value cleanup"); + ret.emplace_back(exv); + } break; + } + } + + return ret; + } + + void processReturnValue(mlir::Operation *op, + const fir::ExtendedValue &resultExv, bool mustBeFreed, + fir::FirOpBuilder &builder, + mlir::PatternRewriter &rewriter) const { + mlir::Location loc = op->getLoc(); + + mlir::Value firBase = fir::getBase(resultExv); + mlir::Type firBaseTy = firBase.getType(); + + std::optional resultEntity; + if (fir::isa_trivial(firBaseTy)) { + resultEntity = hlfir::EntityWithAttributes{firBase}; + } else { + resultEntity = + hlfir::genDeclare(loc, builder, resultExv, ".tmp.intrinsic_result", + fir::FortranVariableFlagsAttr{}); + } + + if (resultEntity->isVariable()) { + hlfir::AsExprOp asExpr = builder.create( + loc, *resultEntity, builder.createBool(loc, mustBeFreed)); + resultEntity = hlfir::EntityWithAttributes{asExpr.getResult()}; + } + + mlir::Value base = resultEntity->getBase(); + if (!mlir::isa(base.getType())) { + for (mlir::Operation *use : op->getResult(0).getUsers()) { + if (mlir::isa(use)) + rewriter.eraseOp(use); + } + } + rewriter.replaceAllUsesWith(op->getResults(), {base}); + rewriter.replaceOp(op, base); + } +}; + +struct SumOpConversion : public HlfirIntrinsicConversion { + using HlfirIntrinsicConversion::HlfirIntrinsicConversion; + + mlir::LogicalResult + matchAndRewrite(hlfir::SumOp sum, + mlir::PatternRewriter &rewriter) const override { + fir::KindMapping kindMapping{rewriter.getContext()}; + fir::FirOpBuilder builder{rewriter, kindMapping}; + const mlir::Location &loc = sum->getLoc(); + + mlir::Type i32 = builder.getI32Type(); + mlir::Type logicalType = fir::LogicalType::get( + builder.getContext(), builder.getKindMap().defaultLogicalKind()); + + llvm::SmallVector inArgs; + inArgs.push_back({sum.getArray(), sum.getArray().getType()}); + inArgs.push_back({sum.getDim(), i32}); + inArgs.push_back({sum.getMask(), logicalType}); + + auto *argLowering = fir::getIntrinsicArgumentLowering("sum"); + llvm::SmallVector args = + lowerArguments(sum, inArgs, rewriter, argLowering); + + mlir::Type scalarResultType = hlfir::getFortranElementType(sum.getType()); + + auto [resultExv, mustBeFreed] = + fir::genIntrinsicCall(builder, loc, "sum", scalarResultType, args); + + processReturnValue(sum, resultExv, mustBeFreed, builder, rewriter); + return mlir::success(); + } +}; + +struct MatmulOpConversion : public HlfirIntrinsicConversion { + using HlfirIntrinsicConversion::HlfirIntrinsicConversion; + + mlir::LogicalResult + matchAndRewrite(hlfir::MatmulOp matmul, + mlir::PatternRewriter &rewriter) const override { + fir::KindMapping kindMapping{rewriter.getContext()}; + fir::FirOpBuilder builder{rewriter, kindMapping}; + const mlir::Location &loc = matmul->getLoc(); + + mlir::Value lhs = matmul.getLhs(); + mlir::Value rhs = matmul.getRhs(); + llvm::SmallVector inArgs; + inArgs.push_back({lhs, lhs.getType()}); + inArgs.push_back({rhs, rhs.getType()}); + + auto *argLowering = fir::getIntrinsicArgumentLowering("matmul"); + llvm::SmallVector args = + lowerArguments(matmul, inArgs, rewriter, argLowering); + + mlir::Type scalarResultType = + hlfir::getFortranElementType(matmul.getType()); + + auto [resultExv, mustBeFreed] = + fir::genIntrinsicCall(builder, loc, "matmul", scalarResultType, args); + + processReturnValue(matmul, resultExv, mustBeFreed, builder, rewriter); + return mlir::success(); + } +}; + +class TransposeOpConversion + : public HlfirIntrinsicConversion { + using HlfirIntrinsicConversion::HlfirIntrinsicConversion; + + mlir::LogicalResult + matchAndRewrite(hlfir::TransposeOp transpose, + mlir::PatternRewriter &rewriter) const override { + fir::KindMapping kindMapping{rewriter.getContext()}; + fir::FirOpBuilder builder{rewriter, kindMapping}; + const mlir::Location &loc = transpose->getLoc(); + + mlir::Value arg = transpose.getArray(); + llvm::SmallVector inArgs; + inArgs.push_back({arg, arg.getType()}); + + auto *argLowering = fir::getIntrinsicArgumentLowering("transpose"); + llvm::SmallVector args = + lowerArguments(transpose, inArgs, rewriter, argLowering); + + mlir::Type scalarResultType = + hlfir::getFortranElementType(transpose.getType()); + + auto [resultExv, mustBeFreed] = fir::genIntrinsicCall( + builder, loc, "transpose", scalarResultType, args); + + processReturnValue(transpose, resultExv, mustBeFreed, builder, rewriter); + return mlir::success(); + } +}; + +class LowerHLFIRIntrinsics + : public hlfir::impl::LowerHLFIRIntrinsicsBase { +public: + void runOnOperation() override { + // TODO: make this a pass operating on FuncOp. The issue is that + // FirOpBuilder helpers may generate new FuncOp because of runtime/llvm + // intrinsics calls creation. This may create race conflict if the pass is + // scheduled on FuncOp. A solution could be to provide an optional mutex + // when building a FirOpBuilder and locking around FuncOp and GlobalOp + // creation, but this needs a bit more thinking, so at this point the pass + // is scheduled on the moduleOp. + auto module = this->getOperation(); + auto *context = &getContext(); + mlir::RewritePatternSet patterns(context); + patterns.insert( + context); + mlir::ConversionTarget target(*context); + target.addLegalDialect(); + target.addIllegalOp(); + if (mlir::failed( + mlir::applyFullConversion(module, target, std::move(patterns)))) { + mlir::emitError(mlir::UnknownLoc::get(context), + "failure in HLFIR intrinsic lowering"); + signalPassFailure(); + } + } +}; +} // namespace + +std::unique_ptr hlfir::createLowerHLFIRIntrinsicsPass() { + return std::make_unique(); +} diff --git a/flang/test/HLFIR/matmul-bufferization.fir b/flang/test/HLFIR/matmul-lowering.fir rename from flang/test/HLFIR/matmul-bufferization.fir rename to flang/test/HLFIR/matmul-lowering.fir --- a/flang/test/HLFIR/matmul-bufferization.fir +++ b/flang/test/HLFIR/matmul-lowering.fir @@ -1,5 +1,5 @@ // Test hlfir.matmul operation lowering to fir runtime call -// RUN: fir-opt %s -bufferize-hlfir | FileCheck %s +// RUN: fir-opt %s -lower-hlfir-intrinsics | FileCheck %s func.func @_QPmatmul1(%arg0: !fir.box> {fir.bindc_name = "lhs"}, %arg1: !fir.box> {fir.bindc_name = "rhs"}, %arg2: !fir.box> {fir.bindc_name = "res"}) { %0:2 = hlfir.declare %arg0 {uniq_name = "_QFmatmul1Elhs"} : (!fir.box>) -> (!fir.box>, !fir.box>) @@ -36,10 +36,10 @@ // CHECK-NEXT: %[[SHIFT:.*]] = fir.shape_shift %[[BOX_DIMS]]#0, %[[BOX_DIMS]]#1 // TODO: fix alias analysis in hlfir.assign bufferization // CHECK-NEXT: %[[TMP:.*]]:2 = hlfir.declare %[[ADDR]](%[[SHIFT]]) {uniq_name = ".tmp.intrinsic_result"} -// CHECK: %[[TUPLE0:.*]] = fir.undefined tuple>, i1> -// CHECK: %[[TUPLE1:.*]] = fir.insert_value %[[TUPLE0]], %[[TRUE:.*]], [1 : index] -// CHECK: %[[TUPLE2:.*]] = fir.insert_value %[[TUPLE1]], %[[TMP]]#0, [0 : index] -// CHECK: hlfir.assign %[[TMP]]#0 to %[[RES_VAR]]#0 -// CHECK: fir.freemem %[[TMP]]#1 +// TODO: add shape information from original intrinsic op +// CHECK: %[[TRUE:.*]] = arith.constant true +// CHECK: %[[ASEXPR:.*]] = hlfir.as_expr %[[TMP]]#0 move %[[TRUE]] : (!fir.box>, i1) -> !hlfir.expr +// CHECK: hlfir.assign %[[ASEXPR]] to %[[RES_VAR]]#0 +// CHECK: hlfir.destroy %[[ASEXPR]] // CHECK-NEXT: return // CHECK-NEXT: } diff --git a/flang/test/HLFIR/sum-bufferization.fir b/flang/test/HLFIR/sum-lowering.fir rename from flang/test/HLFIR/sum-bufferization.fir rename to flang/test/HLFIR/sum-lowering.fir --- a/flang/test/HLFIR/sum-bufferization.fir +++ b/flang/test/HLFIR/sum-lowering.fir @@ -1,5 +1,5 @@ // Test hlfir.sum operation lowering to fir runtime call -// RUN: fir-opt %s -bufferize-hlfir | FileCheck %s +// RUN: fir-opt %s -lower-hlfir-intrinsics | FileCheck %s // simple one argument sum func.func @_QPsum1(%arg0: !fir.box> {fir.bindc_name = "a"}, %arg1: !fir.ref {fir.bindc_name = "s"}) { @@ -64,11 +64,10 @@ // CHECK-NEXT: %[[SHIFT:.*]] = fir.shape_shift %[[BOX_DIMS]]#0, %[[BOX_DIMS]]#1 // TODO: fix alias analysis in hlfir.assign bufferization // CHECK-NEXT: %[[TMP:.*]]:2 = hlfir.declare %[[ADDR]](%[[SHIFT]]) {uniq_name = ".tmp.intrinsic_result"} -// CHECK: %[[TUPLE0:.*]] = fir.undefined tuple>, i1> -// CHECK: %[[TUPLE1:.*]] = fir.insert_value %[[TUPLE0]], %[[TRUE:.*]], [1 : index] -// CHECK: %[[TUPLE2:.*]] fir.insert_value %[[TUPLE1]], %[[TMP]]#0, [0 : index] -// CHECK: hlfir.assign %[[TMP]]#0 to %[[RES]]#0 -// CHECK: fir.freemem %[[TMP]]#1 +// CHECK: %[[TRUE:.*]] = arith.constant true +// CHECK: %[[ASEXPR:.*]] = hlfir.as_expr %[[TMP]]#0 move %[[TRUE]] : (!fir.box>, i1) -> !hlfir.expr +// CHECK: hlfir.assign %[[ASEXPR]] to %[[RES]]#0 +// CHECK: hlfir.destroy %[[ASEXPR]] // CHECK-NEXT: return // CHECK-NEXT: } diff --git a/flang/test/HLFIR/transpose-bufferization.fir b/flang/test/HLFIR/transpose-lowering.fir rename from flang/test/HLFIR/transpose-bufferization.fir rename to flang/test/HLFIR/transpose-lowering.fir --- a/flang/test/HLFIR/transpose-bufferization.fir +++ b/flang/test/HLFIR/transpose-lowering.fir @@ -1,5 +1,5 @@ // Test hlfir.transpose operation lowering to fir runtime call -// RUN: fir-opt %s -bufferize-hlfir | FileCheck %s +// RUN: fir-opt %s -lower-hlfir-intrinsics | FileCheck %s func.func @_QPtranspose1(%arg0: !fir.ref> {fir.bindc_name = "m"}, %arg1: !fir.ref> {fir.bindc_name = "res"}) { %c1 = arith.constant 1 : index @@ -40,10 +40,9 @@ // CHECK-NEXT: %[[SHIFT:.*]] = fir.shape_shift %[[BOX_DIMS]]#0, %[[BOX_DIMS]]#1 // TODO: fix alias analysis in hlfir.assign bufferization // CHECK-NEXT: %[[TMP:.*]]:2 = hlfir.declare %[[ADDR]](%[[SHIFT]]) {uniq_name = ".tmp.intrinsic_result"} -// CHECK: %[[TUPLE0:.*]] = fir.undefined tuple>, i1> -// CHECK: %[[TUPLE1:.*]] = fir.insert_value %[[TUPLE0]], %[[TRUE:.*]], [1 : index] -// CHECK: %[[TUPLE2:.*]] = fir.insert_value %[[TUPLE1]], %[[TMP]]#0, [0 : index] -// CHECK: hlfir.assign %[[TMP]]#0 to %[[RES_VAR]]#0 -// CHECK: fir.freemem %[[TMP]]#1 +// CHECK: %[[TRUE:.*]] = arith.constant true +// CHECK: %[[ASEXPR:.*]] = hlfir.as_expr %[[TMP]]#0 move %[[TRUE]] : (!fir.box>, i1) -> !hlfir.expr +// CHECK: hlfir.assign %[[ASEXPR]] to %[[RES_VAR]]#0 +// CHECK: hlfir.destroy %[[ASEXPR]] // CHECK-NEXT: return // CHECK-NEXT: }