-
Notifications
You must be signed in to change notification settings - Fork 10.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Flang] Add a HLFIR Minloc intrinsic #74436
Conversation
@llvm/pr-subscribers-flang-fir-hlfir Author: David Green (davemgreen) ChangesThe adds a hlfir minloc intrinsic, similar to the minval intrinsic already added, to help in the lowering of minloc. The idea is to later add maxloc too, and from there add a simplification for producing minloc with inlined elemental and hopefully less temporaries. Patch is 84.87 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/74436.diff 10 Files Affected:
diff --git a/flang/include/flang/Optimizer/HLFIR/HLFIROps.td b/flang/include/flang/Optimizer/HLFIR/HLFIROps.td
index f4933785a8caa..ba30a6e8a19b3 100644
--- a/flang/include/flang/Optimizer/HLFIR/HLFIROps.td
+++ b/flang/include/flang/Optimizer/HLFIR/HLFIROps.td
@@ -458,6 +458,33 @@ def hlfir_MinvalOp : hlfir_Op<"minval", [AttrSizedOperandSegments,
let hasVerifier = 1;
}
+def hlfir_MinlocOp : hlfir_Op<"minloc", [AttrSizedOperandSegments,
+ DeclareOpInterfaceMethods<ArithFastMathInterface>,
+ DeclareOpInterfaceMethods<MemoryEffectsOpInterface>]> {
+ let summary = "MINLOC transformational intrinsic";
+ let description = [{
+ Minlocs of an array.
+ }];
+
+ let arguments = (ins
+ AnyFortranArrayObject:$array,
+ Optional<AnyIntegerType>:$dim,
+ Optional<AnyFortranLogicalOrI1ArrayObject>:$mask,
+ Optional<AnyIntegerType>:$kind,
+ Optional<Type<AnyLogicalLike.predicate>>:$back,
+ DefaultValuedAttr<Arith_FastMathAttr,
+ "::mlir::arith::FastMathFlags::none">:$fastmath
+ );
+
+ let results = (outs AnyFortranValue);
+
+ let assemblyFormat = [{
+ $array (`dim` $dim^)? (`mask` $mask^)? (`kind` $kind^)? (`back` $back^)? attr-dict `:` functional-type(operands, results)
+ }];
+
+ let hasVerifier = 1;
+}
+
def hlfir_ProductOp : hlfir_Op<"product", [AttrSizedOperandSegments,
DeclareOpInterfaceMethods<ArithFastMathInterface>,
DeclareOpInterfaceMethods<MemoryEffectsOpInterface>]> {
diff --git a/flang/lib/Lower/HlfirIntrinsics.cpp b/flang/lib/Lower/HlfirIntrinsics.cpp
index 9f764b6142522..666c039975d71 100644
--- a/flang/lib/Lower/HlfirIntrinsics.cpp
+++ b/flang/lib/Lower/HlfirIntrinsics.cpp
@@ -93,6 +93,19 @@ using HlfirMinvalLowering = HlfirReductionIntrinsic<hlfir::MinvalOp, true>;
using HlfirAnyLowering = HlfirReductionIntrinsic<hlfir::AnyOp, false>;
using HlfirAllLowering = HlfirReductionIntrinsic<hlfir::AllOp, false>;
+template <typename OP>
+class HlfirMinMaxLocIntrinsic : public HlfirTransformationalIntrinsic {
+public:
+ using HlfirTransformationalIntrinsic::HlfirTransformationalIntrinsic;
+
+protected:
+ mlir::Value
+ lowerImpl(const Fortran::lower::PreparedActualArguments &loweredActuals,
+ const fir::IntrinsicArgumentLoweringRules *argLowering,
+ mlir::Type stmtResultType) override;
+};
+using HlfirMinlocLowering = HlfirMinMaxLocIntrinsic<hlfir::MinlocOp>;
+
template <typename OP>
class HlfirProductIntrinsic : public HlfirTransformationalIntrinsic {
public:
@@ -206,6 +219,8 @@ llvm::SmallVector<mlir::Value> HlfirTransformationalIntrinsic::getOperandVector(
else if (!argRules.handleDynamicOptional &&
argRules.lowerAs != fir::LowerIntrinsicArgAs::Inquired)
valArg = hlfir::derefPointersAndAllocatables(loc, builder, actual);
+ else if (argRules.lowerAs == fir::LowerIntrinsicArgAs::Value)
+ valArg = hlfir::loadTrivialScalar(loc, builder, actual);
else if (argRules.handleDynamicOptional)
TODO(loc, "hlfir transformational intrinsic dynamically optional "
"argument without box lowering");
@@ -260,6 +275,30 @@ mlir::Value HlfirReductionIntrinsic<OP, HAS_MASK>::lowerImpl(
return op;
}
+template <typename OP>
+mlir::Value HlfirMinMaxLocIntrinsic<OP>::lowerImpl(
+ const Fortran::lower::PreparedActualArguments &loweredActuals,
+ const fir::IntrinsicArgumentLoweringRules *argLowering,
+ mlir::Type stmtResultType) {
+ auto operands = getOperandVector(loweredActuals, argLowering);
+ mlir::Value array = operands[0];
+ mlir::Value dim = operands[1];
+ mlir::Value mask = operands[2];
+ mlir::Value kind = operands[3];
+ mlir::Value back = operands[4];
+ // dim, mask, kind and back can be NULL if these arguments are not given.
+ if (dim)
+ dim = hlfir::loadTrivialScalar(loc, builder, hlfir::Entity{dim});
+ if (kind)
+ kind = hlfir::loadTrivialScalar(loc, builder, hlfir::Entity{kind});
+ if (back)
+ back = hlfir::loadTrivialScalar(loc, builder, hlfir::Entity{back});
+
+ mlir::Type resultTy = computeResultType(array, stmtResultType);
+
+ return createOp<OP>(resultTy, array, dim, mask, kind, back);
+}
+
template <typename OP>
mlir::Value HlfirProductIntrinsic<OP>::lowerImpl(
const Fortran::lower::PreparedActualArguments &loweredActuals,
@@ -364,6 +403,9 @@ std::optional<hlfir::EntityWithAttributes> Fortran::lower::lowerHlfirIntrinsic(
if (name == "minval")
return HlfirMinvalLowering{builder, loc}.lower(loweredActuals, argLowering,
stmtResultType);
+ if (name == "minloc")
+ return HlfirMinlocLowering{builder, loc}.lower(loweredActuals, argLowering,
+ stmtResultType);
if (mlir::isa<fir::CharacterType>(stmtResultType)) {
if (name == "min")
return HlfirCharExtremumLowering{builder, loc,
diff --git a/flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp b/flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp
index a276e5fc65dd5..94a2213306bfd 100644
--- a/flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp
+++ b/flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp
@@ -870,6 +870,81 @@ void hlfir::MinvalOp::getEffects(
getIntrinsicEffects(getOperation(), effects);
}
+//===----------------------------------------------------------------------===//
+// MinlocOp
+//===----------------------------------------------------------------------===//
+
+mlir::LogicalResult hlfir::MinlocOp::verify() {
+ mlir::Operation *op = getOperation();
+
+ auto results = op->getResultTypes();
+ assert(results.size() == 1);
+ mlir::Value array = getArray();
+ mlir::Value dim = getDim();
+ mlir::Value mask = getMask();
+
+ fir::SequenceType arrayTy =
+ hlfir::getFortranElementOrSequenceType(array.getType())
+ .cast<fir::SequenceType>();
+ llvm::ArrayRef<int64_t> arrayShape = arrayTy.getShape();
+
+ if (mask) {
+ fir::SequenceType maskSeq =
+ hlfir::getFortranElementOrSequenceType(mask.getType())
+ .dyn_cast<fir::SequenceType>();
+ llvm::ArrayRef<int64_t> maskShape;
+
+ if (maskSeq)
+ maskShape = maskSeq.getShape();
+
+ if (!maskShape.empty()) {
+ if (maskShape.size() != arrayShape.size())
+ return emitWarning("MASK must be conformable to ARRAY");
+ static_assert(fir::SequenceType::getUnknownExtent() ==
+ hlfir::ExprType::getUnknownExtent());
+ constexpr int64_t unknownExtent = fir::SequenceType::getUnknownExtent();
+ for (std::size_t i = 0; i < arrayShape.size(); ++i) {
+ int64_t arrayExtent = arrayShape[i];
+ int64_t maskExtent = maskShape[i];
+ if ((arrayExtent != maskExtent) && (arrayExtent != unknownExtent) &&
+ (maskExtent != unknownExtent))
+ return emitWarning("MASK must be conformable to ARRAY");
+ }
+ }
+ }
+
+ mlir::Type resultType = results[0];
+ if (dim && arrayShape.size() == 1) {
+ if (!fir::isa_integer(resultType))
+ return emitOpError("result must be scalar integer");
+ } else if (auto resultExpr =
+ mlir::dyn_cast_or_null<hlfir::ExprType>(resultType)) {
+ if (!resultExpr.isArray())
+ return emitOpError("result must be an array");
+
+ if (!fir::isa_integer(resultExpr.getEleTy()))
+ return emitOpError("result must have integer elements");
+
+ llvm::ArrayRef<int64_t> resultShape = resultExpr.getShape();
+ // With dim the result has rank n-1
+ if (dim && resultShape.size() != (arrayShape.size() - 1))
+ return emitOpError("result rank must be one less than ARRAY");
+ // With dim the result has rank n
+ if (!dim && resultShape.size() != 1)
+ return emitOpError("result rank must be 1");
+ } else {
+ return emitOpError("result must be of numerical expr type");
+ }
+ return mlir::success();
+}
+
+void hlfir::MinlocOp::getEffects(
+ llvm::SmallVectorImpl<
+ mlir::SideEffects::EffectInstance<mlir::MemoryEffects::Effect>>
+ &effects) {
+ getIntrinsicEffects(getOperation(), effects);
+}
+
//===----------------------------------------------------------------------===//
// SetLengthOp
//===----------------------------------------------------------------------===//
diff --git a/flang/lib/Optimizer/HLFIR/Transforms/LowerHLFIRIntrinsics.cpp b/flang/lib/Optimizer/HLFIR/Transforms/LowerHLFIRIntrinsics.cpp
index f2628fcb970bc..70826e9179b82 100644
--- a/flang/lib/Optimizer/HLFIR/Transforms/LowerHLFIRIntrinsics.cpp
+++ b/flang/lib/Optimizer/HLFIR/Transforms/LowerHLFIRIntrinsics.cpp
@@ -201,6 +201,19 @@ class HlfirReductionIntrinsicConversion : public HlfirIntrinsicConversion<OP> {
return lowerArguments(operation, inArgs, rewriter, argLowering);
};
+ auto buildMinMaxLocArgs(OP operation, mlir::Type i32, mlir::Type logicalType,
+ mlir::PatternRewriter &rewriter,
+ std::string opName) const {
+ llvm::SmallVector<IntrinsicArgument, 3> inArgs;
+ inArgs.push_back({operation.getArray(), operation.getArray().getType()});
+ inArgs.push_back({operation.getDim(), i32});
+ inArgs.push_back({operation.getMask(), logicalType});
+ inArgs.push_back({operation.getKind(), i32});
+ inArgs.push_back({operation.getBack(), i32});
+ auto *argLowering = fir::getIntrinsicArgumentLowering(opName);
+ return lowerArguments(operation, inArgs, rewriter, argLowering);
+ };
+
auto buildLogicalArgs(OP operation, mlir::Type i32, mlir::Type logicalType,
mlir::PatternRewriter &rewriter,
std::string opName) const {
@@ -224,6 +237,8 @@ class HlfirReductionIntrinsicConversion : public HlfirIntrinsicConversion<OP> {
opName = "maxval";
} else if constexpr (std::is_same_v<OP, hlfir::MinvalOp>) {
opName = "minval";
+ } else if constexpr (std::is_same_v<OP, hlfir::MinlocOp>) {
+ opName = "minloc";
} else if constexpr (std::is_same_v<OP, hlfir::AnyOp>) {
opName = "any";
} else if constexpr (std::is_same_v<OP, hlfir::AllOp>) {
@@ -246,6 +261,8 @@ class HlfirReductionIntrinsicConversion : public HlfirIntrinsicConversion<OP> {
std::is_same_v<OP, hlfir::MaxvalOp> ||
std::is_same_v<OP, hlfir::MinvalOp>) {
args = buildNumericalArgs(operation, i32, logicalType, rewriter, opName);
+ } else if constexpr (std::is_same_v<OP, hlfir::MinlocOp>) {
+ args = buildMinMaxLocArgs(operation, i32, logicalType, rewriter, opName);
} else {
args = buildLogicalArgs(operation, i32, logicalType, rewriter, opName);
}
@@ -269,6 +286,8 @@ using MaxvalOpConversion = HlfirReductionIntrinsicConversion<hlfir::MaxvalOp>;
using MinvalOpConversion = HlfirReductionIntrinsicConversion<hlfir::MinvalOp>;
+using MinlocOpConversion = HlfirReductionIntrinsicConversion<hlfir::MinlocOp>;
+
using AnyOpConversion = HlfirReductionIntrinsicConversion<hlfir::AnyOp>;
using AllOpConversion = HlfirReductionIntrinsicConversion<hlfir::AllOp>;
@@ -441,12 +460,12 @@ class LowerHLFIRIntrinsics
mlir::ModuleOp module = this->getOperation();
mlir::MLIRContext *context = &getContext();
mlir::RewritePatternSet patterns(context);
- patterns
- .insert<MatmulOpConversion, MatmulTransposeOpConversion,
- AllOpConversion, AnyOpConversion, SumOpConversion,
- ProductOpConversion, TransposeOpConversion, CountOpConversion,
- DotProductOpConversion, MaxvalOpConversion, MinvalOpConversion>(
- context);
+ patterns.insert<MatmulOpConversion, MatmulTransposeOpConversion,
+ AllOpConversion, AnyOpConversion, SumOpConversion,
+ ProductOpConversion, TransposeOpConversion,
+ CountOpConversion, DotProductOpConversion,
+ MaxvalOpConversion, MinvalOpConversion, MinlocOpConversion>(
+ context);
mlir::ConversionTarget target(*context);
target.addLegalDialect<mlir::BuiltinDialect, mlir::arith::ArithDialect,
mlir::func::FuncDialect, fir::FIROpsDialect,
@@ -454,7 +473,7 @@ class LowerHLFIRIntrinsics
target.addIllegalOp<hlfir::MatmulOp, hlfir::MatmulTransposeOp, hlfir::SumOp,
hlfir::ProductOp, hlfir::TransposeOp, hlfir::AnyOp,
hlfir::AllOp, hlfir::DotProductOp, hlfir::CountOp,
- hlfir::MaxvalOp, hlfir::MinvalOp>();
+ hlfir::MaxvalOp, hlfir::MinvalOp, hlfir::MinlocOp>();
target.markUnknownOpDynamicallyLegal(
[](mlir::Operation *) { return true; });
if (mlir::failed(
diff --git a/flang/test/HLFIR/invalid.fir b/flang/test/HLFIR/invalid.fir
index 09165f09766b9..ce0d728749b96 100644
--- a/flang/test/HLFIR/invalid.fir
+++ b/flang/test/HLFIR/invalid.fir
@@ -548,6 +548,74 @@ func.func @bad_minval13(%arg0: !hlfir.expr<?x?x!fir.char<1,?>>, %arg1: i32){
%0 = hlfir.minval %arg0 dim %arg1 : (!hlfir.expr<?x?x!fir.char<1,?>>, i32) -> !hlfir.expr<!fir.char<1,?>>
}
+// -----
+func.func @bad_minloc1(%arg0: !hlfir.expr<?xi32>, %arg1: i32, %arg2: !fir.box<!fir.logical<4>>) {
+ // expected-error@+1 {{'hlfir.minloc' op result must be scalar integer}}
+ %0 = hlfir.minloc %arg0 dim %arg1 mask %arg2 : (!hlfir.expr<?xi32>, i32, !fir.box<!fir.logical<4>>) -> f32
+}
+
+// -----
+func.func @bad_minloc2(%arg0: !hlfir.expr<?xi32>, %arg1: i32, %arg2: !fir.box<!fir.array<?x?x?x?x?x!fir.logical<4>>>) {
+ // expected-warning@+1 {{MASK must be conformable to ARRAY}}
+ %0 = hlfir.minloc %arg0 dim %arg1 mask %arg2 : (!hlfir.expr<?xi32>, i32, !fir.box<!fir.array<?x?x?x?x?x!fir.logical<4>>>) -> !hlfir.expr<i32>
+}
+
+// -----
+func.func @bad_minloc3(%arg0: !hlfir.expr<?x5x?xi32>, %arg1: i32, %arg2: !fir.box<!fir.array<2x6x?x!fir.logical<4>>>) {
+ // expected-warning@+1 {{MASK must be conformable to ARRAY}}
+ %0 = hlfir.minloc %arg0 dim %arg1 mask %arg2 : (!hlfir.expr<?x5x?xi32>, i32, !fir.box<!fir.array<2x6x?x!fir.logical<4>>>) -> !hlfir.expr<i32>
+}
+
+// -----
+func.func @bad_minloc4(%arg0: !hlfir.expr<?x?xi32>, %arg1: i32, %arg2: !fir.box<!fir.logical<4>>) {
+ // expected-error@+1 {{'hlfir.minloc' op result rank must be one less than ARRAY}}
+ %0 = hlfir.minloc %arg0 dim %arg1 mask %arg2 : (!hlfir.expr<?x?xi32>, i32, !fir.box<!fir.logical<4>>) -> !hlfir.expr<?x?xi32>
+}
+
+// -----
+func.func @bad_minloc5(%arg0: !hlfir.expr<?xi32>, %arg1: i32, %arg2: !fir.box<!fir.logical<4>>) {
+ // expected-error@+1 {{'hlfir.minloc' op result must be scalar integer}}
+ %0 = hlfir.minloc %arg0 dim %arg1 mask %arg2 : (!hlfir.expr<?xi32>, i32, !fir.box<!fir.logical<4>>) -> !fir.logical<4>
+}
+
+// -----
+func.func @bad_minloc6(%arg0: !hlfir.expr<?x?xi32>, %arg1: i32){
+ // expected-error@+1 {{'hlfir.minloc' op result must be an array}}
+ %0 = hlfir.minloc %arg0 dim %arg1 : (!hlfir.expr<?x?xi32>, i32) -> !hlfir.expr<i32>
+}
+
+// -----
+func.func @bad_minloc7(%arg0: !hlfir.expr<?xi32>){
+ // expected-error@+1 {{'hlfir.minloc' op result must be of numerical expr type}}
+ %0 = hlfir.minloc %arg0 : (!hlfir.expr<?xi32>) -> i32
+}
+
+// -----
+func.func @bad_minloc8(%arg0: !hlfir.expr<?xi32>){
+ // expected-error@+1 {{'hlfir.minloc' op result must have integer elements}}
+ %0 = hlfir.minloc %arg0 : (!hlfir.expr<?xi32>) -> !hlfir.expr<?xf32>
+}
+
+// -----
+func.func @bad_minloc9(%arg0: !hlfir.expr<?x!fir.char<1,?>>, %arg1: i32, %arg2: !fir.box<!fir.array<?x?x?x?x?x!fir.logical<4>>>) {
+ // expected-warning@+1 {{MASK must be conformable to ARRAY}}
+ %0 = hlfir.minloc %arg0 dim %arg1 mask %arg2 : (!hlfir.expr<?x!fir.char<1,?>>, i32, !fir.box<!fir.array<?x?x?x?x?x!fir.logical<4>>>) -> !hlfir.expr<!fir.char<1,?>>
+}
+
+// -----
+func.func @bad_minloc10(%arg0: !hlfir.expr<?x5x?x!fir.char<1,?>>, %arg1: i32, %arg2: !fir.box<!fir.array<2x6x?x!fir.logical<4>>>) {
+ // expected-warning@+1 {{MASK must be conformable to ARRAY}}
+ %0 = hlfir.minloc %arg0 dim %arg1 mask %arg2 : (!hlfir.expr<?x5x?x!fir.char<1,?>>, i32, !fir.box<!fir.array<2x6x?x!fir.logical<4>>>) -> !hlfir.expr<!fir.char<1,?>>
+}
+
+// -----
+func.func @bad_minloc11(%arg0: !hlfir.expr<?x?x!fir.char<1,?>>, %arg1: i32, %arg2: !fir.box<!fir.logical<4>>) {
+ // expected-error@+1 {{'hlfir.minloc' op result rank must be one less than ARRAY}}
+ %0 = hlfir.minloc %arg0 dim %arg1 mask %arg2 : (!hlfir.expr<?x?x!fir.char<1,?>>, i32, !fir.box<!fir.logical<4>>) -> !hlfir.expr<?x?xi32>
+}
+
+
+
// -----
func.func @bad_product1(%arg0: !hlfir.expr<?xi32>, %arg1: i32, %arg2: !fir.box<!fir.logical<4>>) {
// expected-error@+1 {{'hlfir.product' op result must have the same element type as ARRAY argument}}
diff --git a/flang/test/HLFIR/memory-effects.fir b/flang/test/HLFIR/memory-effects.fir
index 4b2a0d575db1a..c68c71f43a17d 100644
--- a/flang/test/HLFIR/memory-effects.fir
+++ b/flang/test/HLFIR/memory-effects.fir
@@ -122,6 +122,21 @@ func.func @minval_effects(%arg0: !fir.ref<!fir.array<2x2xf32>>, %arg1: i32) {
return
}
+func.func @minloc_effects_simple(%arg0: !hlfir.expr<?xf32>) {
+// expected-remark@+1 {{found an instance of 'allocate' on a value, on resource '<Default>'}}
+ %minloc = hlfir.minloc %arg0 : (!hlfir.expr<?xf32>) -> !hlfir.expr<?xi32>
+// expected-remark@+1 {{operation has no memory effects}}
+ return
+}
+
+func.func @minloc_effects(%arg0: !fir.ref<!fir.array<2x2xf32>>, %arg1: i32) {
+// expected-remark@+2 {{found an instance of 'allocate' on a value, on resource '<Default>'}}
+// expected-remark@+1 {{found an instance of 'read' on a value, on resource '<Default>'}}
+ %minloc = hlfir.minloc %arg0 dim %arg1 : (!fir.ref<!fir.array<2x2xf32>>, i32) -> !hlfir.expr<2xi32>
+// expected-remark@+1 {{operation has no memory effects}}
+ return
+}
+
func.func @dot_product_no_effects(%arg0: !hlfir.expr<?xf32>, %arg1: !hlfir.expr<?xf32>) {
// expected-remark@+1 {{operation has no memory effects}}
%0 = hlfir.dot_product %arg0 %arg1 : (!hlfir.expr<?xf32>, !hlfir.expr<?xf32>) -> f32
diff --git a/flang/test/HLFIR/minloc-lowering.fir b/flang/test/HLFIR/minloc-lowering.fir
new file mode 100644
index 0000000000000..f5434186a5aae
--- /dev/null
+++ b/flang/test/HLFIR/minloc-lowering.fir
@@ -0,0 +1,336 @@
+// Test hlfir.minloc operation lowering to fir runtime call
+// RUN: fir-opt %s -lower-hlfir-intrinsics | FileCheck %s
+
+// simple one argument minloc
+func.func @_QPminloc1(%arg0: !fir.box<!fir.array<?xi32>> {fir.bindc_name = "a"}, %arg1: !fir.box<!fir.array<?xi32>> {fir.bindc_name = "s"}) {
+ %0:2 = hlfir.declare %arg0 {uniq_name = "_QFminloc1Ea"} : (!fir.box<!fir.array<?xi32>>) -> (!fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>>)
+ %1:2 = hlfir.declare %arg1 {uniq_name = "_QFminloc1Es"} : (!fir.box<!fir.array<?xi32>>) -> (!fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>>)
+ %2 = hlfir.minloc %0#0 {fastmath = #arith.fastmath<contract>} : (!fir.box<!fir.array<?xi32>>) -> !hlfir.expr<?xi32>
+ hlfir.assign %2 to %1#0 : !hlfir.expr<?xi32>, !fir.box<!fir.array<?xi32>>
+ hlfir.destroy %2 : !hlfir.expr<?xi32>
+ return
+}
+// CHECK-LABEL: func.func @_QPminloc1(
+// CHECK: %[[ARG0:.*]]: !fir.box<!fir.array<?xi32>> {fir.bindc_name = "a"}
+// CHECK: %[[ARG1:.*]]: !fir.box<!fir.array<?xi32>> {fir.bindc_name = "s"}
+// CHECK-NEXT: %[[V0:.*]] = fir.alloca !fir.box<!fir.heap<!fir.array<?xi32>>>
+// CHECK-NEXT: %[[V1:.*]]:2 = hlfir.declare %[[ARG0]] {uniq_name = "_QFminloc1Ea"} : (!fir.box<!fir.array<?xi32>>) -> (!fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>>)
+// CHECK-NEXT: %[[V2:.*]]:2 = hlfir.declare %[[ARG1]] {uniq_name = "_QFminloc1Es"} : (!fir.box<!fir.array<?xi32>>) -> (!fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>>)
+// CHECK-NEXT: %[[V3:.*]] = fir.absent !fir.box<i1>
+// CHECK-NEXT: %c4 = arith.constant 4 : index
+// CHECK-NEXT: %false = arith.constant false
+// CHECK-NEXT: %[[V4:.*]] = fir.zero_bits !fir.heap<!fir.array<?xi32>>
+// CHECK-NEXT: %c0 = arith.constant 0 : index
+// CHECK-NEXT: %[[V5:.*]] = fir.shape %c0 : (index) -> !fir.shape<1>
+// CHECK-NEXT: %[[V6:.*]] = fir.embox %[[V4]](%[[V5]]) : (!fir.heap<!fir.array<?xi32>>, !fir.shape<1>) -> !fir.box<!fir.heap<!fir.array<?xi32>>>
+// CHECK-NEXT: fir.store %[[V6]] to %[[V0]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>
+// CHECK: %[[V8:.*]] = fir.convert %[[V0]] : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) -> !fir.ref<!fir.box<none>>
+// CHECK-NEXT: %[[V9:.*]] = fir.conv...
[truncated]
|
Is the SimplifyIntrinsics pass not working anymore for Minloc? (
Eitherway, simplifying while lowering from HLFIR Ops is probably the right direction. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for working on this
The adds a hlfir minloc intrinsic, similar to the minval intrinsic already added, to help in the lowering of minloc. The idea is to later add maxloc too, and from there add a simplification for producing minloc with inlined elemental and hopefully less temporaries.
Thanks for the review. |
335b854
to
a21f2e4
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks great to me! Thanks for your work.
Please wait for Jean's approval as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great, thanks for addressing the comments!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
Similar to minloc from llvm#74436, this adds a hlfir maxloc intrinsic so that we can keep them symmetrical. It's just a bit of copy and pasting.
Similar to minloc from #74436, this adds a hlfir maxloc intrinsic so that we can keep them symmetrical. It's just a bit of copy and pasting.
The adds a hlfir minloc intrinsic, similar to the minval intrinsic already added, to help in the lowering of minloc. The idea is to later add maxloc too, and from there add a simplification for producing minloc with inlined elemental and hopefully less temporaries.