[flang-commits] [flang] c67a874 - [flang] Add more diagnostics to fir.coordinate_of
Valentin Clement via flang-commits
flang-commits at lists.llvm.org
Tue Jun 21 11:43:33 PDT 2022
Author: Valentin Clement
Date: 2022-06-21T20:43:22+02:00
New Revision: c67a87444f5585aafa659c52544ac912f283e7e3
URL: https://github.com/llvm/llvm-project/commit/c67a87444f5585aafa659c52544ac912f283e7e3
DIFF: https://github.com/llvm/llvm-project/commit/c67a87444f5585aafa659c52544ac912f283e7e3.diff
LOG: [flang] Add more diagnostics to fir.coordinate_of
Add more diagnostics to fir.coordinate_of to provide better checking
that the IR is sane.
This patch is part of the upstreaming effort from fir-dev branch.
Reviewed By: PeteSteinfeld
Differential Revision: https://reviews.llvm.org/D128255
Co-authored-by: Eric Schweitz <eschweitz at nvidia.com>
Added:
flang/test/Fir/coordinate_of_1.fir
flang/test/Fir/coordinateof.fir
Modified:
flang/include/flang/Optimizer/Dialect/FIROps.td
flang/lib/Optimizer/CodeGen/BoxedProcedure.cpp
flang/lib/Optimizer/Dialect/FIROps.cpp
flang/test/Fir/convert-to-llvm.fir
flang/test/Fir/invalid.fir
Removed:
flang/test/Fir/Todo/coordinate_of_1.fir
flang/test/Fir/Todo/coordinate_of_5.fir
flang/test/Fir/Todo/coordinate_of_6.fir
################################################################################
diff --git a/flang/include/flang/Optimizer/Dialect/FIROps.td b/flang/include/flang/Optimizer/Dialect/FIROps.td
index b9ba0a7a2cd24..6dc6bae6afde9 100644
--- a/flang/include/flang/Optimizer/Dialect/FIROps.td
+++ b/flang/include/flang/Optimizer/Dialect/FIROps.td
@@ -1716,8 +1716,8 @@ def fir_FieldIndexOp : fir_OneResultOp<"field_index", [NoSideEffect]> {
"mlir::Type":$recTy, CArg<"mlir::ValueRange","{}">:$operands)>];
let extraClassDeclaration = [{
- static constexpr llvm::StringRef fieldAttrName() { return "field_id"; }
- static constexpr llvm::StringRef typeAttrName() { return "on_type"; }
+ static constexpr llvm::StringRef getFieldAttrName() { return "field_id"; }
+ static constexpr llvm::StringRef getTypeAttrName() { return "on_type"; }
llvm::StringRef getFieldName() { return getFieldId(); }
llvm::SmallVector<mlir::Attribute> getAttributes();
}];
@@ -1970,21 +1970,22 @@ def fir_LenParamIndexOp : fir_OneResultOp<"len_param_index", [NoSideEffect]> {
```
}];
- let arguments = (ins StrAttr:$field_id, TypeAttr:$on_type);
+ let arguments = (ins
+ StrAttr:$field_id,
+ TypeAttr:$on_type,
+ Variadic<AnyIntegerType>:$typeparams
+ );
let hasCustomAssemblyFormat = 1;
let builders = [OpBuilder<(ins "llvm::StringRef":$fieldName,
- "mlir::Type":$recTy),
- [{
- $_state.addAttribute(fieldAttrName(), $_builder.getStringAttr(fieldName));
- $_state.addAttribute(typeAttrName(), mlir::TypeAttr::get(recTy));
- }]
- >];
+ "mlir::Type":$recTy, CArg<"mlir::ValueRange","{}">:$operands)>];
let extraClassDeclaration = [{
- static constexpr llvm::StringRef fieldAttrName() { return "field_id"; }
- static constexpr llvm::StringRef typeAttrName() { return "on_type"; }
+ static constexpr llvm::StringRef getFieldAttrName() { return "field_id"; }
+ static constexpr llvm::StringRef getTypeAttrName() { return "on_type"; }
+ llvm::StringRef getParamName() { return getFieldId(); }
+ llvm::SmallVector<mlir::Attribute> getAttributes();
}];
}
diff --git a/flang/lib/Optimizer/CodeGen/BoxedProcedure.cpp b/flang/lib/Optimizer/CodeGen/BoxedProcedure.cpp
index 1bc490aade3af..e652ca75f207f 100644
--- a/flang/lib/Optimizer/CodeGen/BoxedProcedure.cpp
+++ b/flang/lib/Optimizer/CodeGen/BoxedProcedure.cpp
@@ -307,7 +307,7 @@ class BoxedProcedurePass : public BoxedProcedurePassBase<BoxedProcedurePass> {
auto toTy = typeConverter.convertType(ty);
auto toOnTy = typeConverter.convertType(onTy);
rewriter.replaceOpWithNewOp<LenParamIndexOp>(
- mem, toTy, index.getFieldId(), toOnTy);
+ mem, toTy, index.getFieldId(), toOnTy, index.getTypeparams());
}
} else if (op->getDialect() == firDialect) {
rewriter.startRootUpdate(op);
diff --git a/flang/lib/Optimizer/Dialect/FIROps.cpp b/flang/lib/Optimizer/Dialect/FIROps.cpp
index 05478ac5dd9a2..069fa4344c5d1 100644
--- a/flang/lib/Optimizer/Dialect/FIROps.cpp
+++ b/flang/lib/Optimizer/Dialect/FIROps.cpp
@@ -924,7 +924,7 @@ mlir::ParseResult fir::CoordinateOp::parse(mlir::OpAsmParser &parser,
}
mlir::LogicalResult fir::CoordinateOp::verify() {
- auto refTy = getRef().getType();
+ const mlir::Type refTy = getRef().getType();
if (fir::isa_ref_type(refTy)) {
auto eleTy = fir::dyn_cast_ptrEleTy(refTy);
if (auto arrTy = eleTy.dyn_cast<fir::SequenceType>()) {
@@ -935,18 +935,70 @@ mlir::LogicalResult fir::CoordinateOp::verify() {
}
if (!(fir::isa_aggregate(eleTy) || fir::isa_complex(eleTy) ||
fir::isa_char_string(eleTy)))
- return emitOpError("cannot apply coordinate_of to this type");
- }
- // Recovering a LEN type parameter only makes sense from a boxed value. For a
- // bare reference, the LEN type parameters must be passed as additional
- // arguments to `op`.
- for (auto co : getCoor())
- if (mlir::dyn_cast_or_null<fir::LenParamIndexOp>(co.getDefiningOp())) {
- if (getNumOperands() != 2)
- return emitOpError("len_param_index must be last argument");
- if (!getRef().getType().isa<BoxType>())
- return emitOpError("len_param_index must be used on box type");
+ return emitOpError("cannot apply to this element type");
+ }
+ auto eleTy = fir::dyn_cast_ptrOrBoxEleTy(refTy);
+ unsigned dimension = 0;
+ const unsigned numCoors = getCoor().size();
+ for (auto coorOperand : llvm::enumerate(getCoor())) {
+ auto co = coorOperand.value();
+ if (dimension == 0 && eleTy.isa<fir::SequenceType>()) {
+ dimension = eleTy.cast<fir::SequenceType>().getDimension();
+ if (dimension == 0)
+ return emitOpError("cannot apply to array of unknown rank");
}
+ if (auto *defOp = co.getDefiningOp()) {
+ if (auto index = mlir::dyn_cast<fir::LenParamIndexOp>(defOp)) {
+ // Recovering a LEN type parameter only makes sense from a boxed
+ // value. For a bare reference, the LEN type parameters must be
+ // passed as additional arguments to `index`.
+ if (refTy.isa<fir::BoxType>()) {
+ if (coorOperand.index() != numCoors - 1)
+ return emitOpError("len_param_index must be last argument");
+ if (getNumOperands() != 2)
+ return emitOpError("too many operands for len_param_index case");
+ }
+ if (eleTy != index.getOnType())
+ emitOpError(
+ "len_param_index type not compatible with reference type");
+ return mlir::success();
+ } else if (auto index = mlir::dyn_cast<fir::FieldIndexOp>(defOp)) {
+ if (eleTy != index.getOnType())
+ emitOpError("field_index type not compatible with reference type");
+ if (auto recTy = eleTy.dyn_cast<fir::RecordType>()) {
+ eleTy = recTy.getType(index.getFieldName());
+ continue;
+ }
+ return emitOpError("field_index not applied to !fir.type");
+ }
+ }
+ if (dimension) {
+ if (--dimension == 0)
+ eleTy = eleTy.cast<fir::SequenceType>().getEleTy();
+ } else {
+ if (auto t = eleTy.dyn_cast<mlir::TupleType>()) {
+ // FIXME: Generally, we don't know which field of the tuple is being
+ // referred to unless the operand is a constant. Just assume everything
+ // is good in the tuple case for now.
+ return mlir::success();
+ } else if (auto t = eleTy.dyn_cast<fir::RecordType>()) {
+ // FIXME: This is the same as the tuple case.
+ return mlir::success();
+ } else if (auto t = eleTy.dyn_cast<fir::ComplexType>()) {
+ eleTy = t.getElementType();
+ } else if (auto t = eleTy.dyn_cast<mlir::ComplexType>()) {
+ eleTy = t.getElementType();
+ } else if (auto t = eleTy.dyn_cast<fir::CharacterType>()) {
+ if (t.getLen() == fir::CharacterType::singleton())
+ return emitOpError("cannot apply to character singleton");
+ eleTy = fir::CharacterType::getSingleton(t.getContext(), t.getFKind());
+ if (fir::unwrapRefType(getType()) != eleTy)
+ return emitOpError("character type mismatch");
+ } else {
+ return emitOpError("invalid parameters (too many)");
+ }
+ }
+ }
return mlir::success();
}
@@ -1331,19 +1383,20 @@ void fir::GlobalLenOp::print(mlir::OpAsmPrinter &p) {
// FieldIndexOp
//===----------------------------------------------------------------------===//
-mlir::ParseResult fir::FieldIndexOp::parse(mlir::OpAsmParser &parser,
- mlir::OperationState &result) {
+template <typename TY>
+mlir::ParseResult parseFieldLikeOp(mlir::OpAsmParser &parser,
+ mlir::OperationState &result) {
llvm::StringRef fieldName;
auto &builder = parser.getBuilder();
mlir::Type recty;
if (parser.parseOptionalKeyword(&fieldName) || parser.parseComma() ||
parser.parseType(recty))
return mlir::failure();
- result.addAttribute(fir::FieldIndexOp::fieldAttrName(),
+ result.addAttribute(fir::FieldIndexOp::getFieldAttrName(),
builder.getStringAttr(fieldName));
if (!recty.dyn_cast<fir::RecordType>())
return mlir::failure();
- result.addAttribute(fir::FieldIndexOp::typeAttrName(),
+ result.addAttribute(fir::FieldIndexOp::getTypeAttrName(),
mlir::TypeAttr::get(recty));
if (!parser.parseOptionalLParen()) {
llvm::SmallVector<mlir::OpAsmParser::UnresolvedOperand> operands;
@@ -1354,23 +1407,30 @@ mlir::ParseResult fir::FieldIndexOp::parse(mlir::OpAsmParser &parser,
parser.resolveOperands(operands, types, loc, result.operands))
return mlir::failure();
}
- mlir::Type fieldType = fir::FieldType::get(builder.getContext());
+ mlir::Type fieldType = TY::get(builder.getContext());
if (parser.addTypeToList(fieldType, result.types))
return mlir::failure();
return mlir::success();
}
-void fir::FieldIndexOp::print(mlir::OpAsmPrinter &p) {
+mlir::ParseResult fir::FieldIndexOp::parse(mlir::OpAsmParser &parser,
+ mlir::OperationState &result) {
+ return parseFieldLikeOp<fir::FieldType>(parser, result);
+}
+
+template <typename OP>
+void printFieldLikeOp(mlir::OpAsmPrinter &p, OP &op) {
p << ' '
- << getOperation()
- ->getAttrOfType<mlir::StringAttr>(fir::FieldIndexOp::fieldAttrName())
+ << op.getOperation()
+ ->template getAttrOfType<mlir::StringAttr>(
+ fir::FieldIndexOp::getFieldAttrName())
.getValue()
- << ", " << getOperation()->getAttr(fir::FieldIndexOp::typeAttrName());
- if (getNumOperands()) {
+ << ", " << op.getOperation()->getAttr(fir::FieldIndexOp::getTypeAttrName());
+ if (op.getNumOperands()) {
p << '(';
- p.printOperands(getTypeparams());
- const auto *sep = ") : ";
- for (auto op : getTypeparams()) {
+ p.printOperands(op.getTypeparams());
+ auto sep = ") : ";
+ for (auto op : op.getTypeparams()) {
p << sep;
if (op)
p.printType(op.getType());
@@ -1381,12 +1441,16 @@ void fir::FieldIndexOp::print(mlir::OpAsmPrinter &p) {
}
}
+void fir::FieldIndexOp::print(mlir::OpAsmPrinter &p) {
+ printFieldLikeOp(p, *this);
+}
+
void fir::FieldIndexOp::build(mlir::OpBuilder &builder,
mlir::OperationState &result,
llvm::StringRef fieldName, mlir::Type recTy,
mlir::ValueRange operands) {
- result.addAttribute(fieldAttrName(), builder.getStringAttr(fieldName));
- result.addAttribute(typeAttrName(), mlir::TypeAttr::get(recTy));
+ result.addAttribute(getFieldAttrName(), builder.getStringAttr(fieldName));
+ result.addAttribute(getTypeAttrName(), mlir::TypeAttr::get(recTy));
result.addOperands(operands);
}
@@ -1767,31 +1831,27 @@ mlir::Value fir::IterWhileOp::blockArgToSourceOp(unsigned blockArgNum) {
mlir::ParseResult fir::LenParamIndexOp::parse(mlir::OpAsmParser &parser,
mlir::OperationState &result) {
- llvm::StringRef fieldName;
- auto &builder = parser.getBuilder();
- mlir::Type recty;
- if (parser.parseOptionalKeyword(&fieldName) || parser.parseComma() ||
- parser.parseType(recty))
- return mlir::failure();
- result.addAttribute(fir::LenParamIndexOp::fieldAttrName(),
- builder.getStringAttr(fieldName));
- if (!recty.dyn_cast<fir::RecordType>())
- return mlir::failure();
- result.addAttribute(fir::LenParamIndexOp::typeAttrName(),
- mlir::TypeAttr::get(recty));
- mlir::Type lenType = fir::LenType::get(builder.getContext());
- if (parser.addTypeToList(lenType, result.types))
- return mlir::failure();
- return mlir::success();
+ return parseFieldLikeOp<fir::LenType>(parser, result);
}
void fir::LenParamIndexOp::print(mlir::OpAsmPrinter &p) {
- p << ' '
- << getOperation()
- ->getAttrOfType<mlir::StringAttr>(
- fir::LenParamIndexOp::fieldAttrName())
- .getValue()
- << ", " << getOperation()->getAttr(fir::LenParamIndexOp::typeAttrName());
+ printFieldLikeOp(p, *this);
+}
+
+void fir::LenParamIndexOp::build(mlir::OpBuilder &builder,
+ mlir::OperationState &result,
+ llvm::StringRef fieldName, mlir::Type recTy,
+ mlir::ValueRange operands) {
+ result.addAttribute(getFieldAttrName(), builder.getStringAttr(fieldName));
+ result.addAttribute(getTypeAttrName(), mlir::TypeAttr::get(recTy));
+ result.addOperands(operands);
+}
+
+llvm::SmallVector<mlir::Attribute> fir::LenParamIndexOp::getAttributes() {
+ llvm::SmallVector<mlir::Attribute> attrs;
+ attrs.push_back(getFieldIdAttr());
+ attrs.push_back(getOnTypeAttr());
+ return attrs;
}
//===----------------------------------------------------------------------===//
diff --git a/flang/test/Fir/Todo/coordinate_of_1.fir b/flang/test/Fir/Todo/coordinate_of_1.fir
deleted file mode 100644
index 6dc90b8cca7ec..0000000000000
--- a/flang/test/Fir/Todo/coordinate_of_1.fir
+++ /dev/null
@@ -1,12 +0,0 @@
-// RUN: %not_todo_cmd fir-opt --fir-to-llvm-ir="target=x86_64-unknown-linux-gnu" %s 2>&1 | FileCheck %s
-
-// `fir.coordinate_of` - derived type with `fir.len_param_index`. As
-// `fir.len_param_index` is not implemented yet, that's the error that's
-// currently being generated (this error is generated before trying to convert
-// `fir.coordinate_of`)
-func.func @coordinate_box_derived_with_fir_len(%arg0: !fir.box<!fir.type<derived_2{len1:i32}>>) {
-// CHECK: not yet implemented: fir.len_param_index codegen
- %e = fir.len_param_index len1, !fir.type<derived_2{len1:i32}>
- %q = fir.coordinate_of %arg0, %e : (!fir.box<!fir.type<derived_2{len1:i32}>>, !fir.len) -> !fir.ref<i32>
- return
-}
diff --git a/flang/test/Fir/Todo/coordinate_of_5.fir b/flang/test/Fir/Todo/coordinate_of_5.fir
deleted file mode 100644
index 47737096ffd8d..0000000000000
--- a/flang/test/Fir/Todo/coordinate_of_5.fir
+++ /dev/null
@@ -1,8 +0,0 @@
-// RUN: %not_todo_cmd fir-opt --fir-to-llvm-ir="target=x86_64-unknown-linux-gnu" %s 2>&1 | FileCheck %s
-
-// CHECK: unsupported combination of coordinate operands
-func.func @test_coordinate_of(%arr : !fir.ref<!fir.array<2 x !fir.char<10, 2>>>, %arg1: index) {
- %1 = arith.constant 10 : i32
- %2 = fir.coordinate_of %arr, %arg1, %1 : (!fir.ref<!fir.array<2 x !fir.char<10, 2>>>, index, i32) -> !fir.ref<!fir.char<1,10>>
- return
-}
diff --git a/flang/test/Fir/Todo/coordinate_of_6.fir b/flang/test/Fir/Todo/coordinate_of_6.fir
deleted file mode 100644
index 647fe2fae0bdf..0000000000000
--- a/flang/test/Fir/Todo/coordinate_of_6.fir
+++ /dev/null
@@ -1,8 +0,0 @@
-// RUN: %not_todo_cmd fir-opt --fir-to-llvm-ir="target=x86_64-unknown-linux-gnu" %s 2>&1 | FileCheck %s
-
-// CHECK: unsupported combination of coordinate operands
-
-func.func @test_coordinate_of(%arr : !fir.ref<!fir.array<2 x i32>>, %arg1: index) {
- %2 = fir.coordinate_of %arr, %arg1, %arg1 : (!fir.ref<!fir.array<2 x i32>>, index, index) -> !fir.ref<i32>
- return
-}
diff --git a/flang/test/Fir/convert-to-llvm.fir b/flang/test/Fir/convert-to-llvm.fir
index 2ee507a00164d..ae46b3653115d 100644
--- a/flang/test/Fir/convert-to-llvm.fir
+++ b/flang/test/Fir/convert-to-llvm.fir
@@ -2642,13 +2642,13 @@ func.func @coordinate_ref_derived_nested(%arg0: !fir.ref<!fir.type<derived_5{fie
// 5.3 `fir.char`
func.func @test_coordinate_of_char(%arr : !fir.ref<!fir.char<10, 2>>) {
%1 = arith.constant 10 : i32
- %2 = fir.coordinate_of %arr, %1 : (!fir.ref<!fir.char<10, 2>>, i32) -> !fir.ref<i80>
+ %2 = fir.coordinate_of %arr, %1 : (!fir.ref<!fir.char<10, 2>>, i32) -> !fir.ref<!fir.char<10>>
return
}
// CHECK-LABEL: llvm.func @test_coordinate_of_char(
// CHECK-SAME: %[[VAL_0:.*]]: !llvm.ptr<array<2 x i80>>) {
// CHECK: %[[VAL_1:.*]] = llvm.mlir.constant(10 : i32) : i32
-// CHECK: %[[VAL_2:.*]] = llvm.getelementptr %[[VAL_0]]{{\[}}%[[VAL_1]]] : (!llvm.ptr<array<2 x i80>>, i32) -> !llvm.ptr<i80>
+// CHECK: %[[VAL_2:.*]] = llvm.getelementptr %[[VAL_0]]{{\[}}%[[VAL_1]]] : (!llvm.ptr<array<2 x i80>>, i32) -> !llvm.ptr<array<1 x i80>>
// CHECK: llvm.return
// CHECK: }
diff --git a/flang/test/Fir/coordinate_of_1.fir b/flang/test/Fir/coordinate_of_1.fir
new file mode 100644
index 0000000000000..ebde8c5a0d465
--- /dev/null
+++ b/flang/test/Fir/coordinate_of_1.fir
@@ -0,0 +1,49 @@
+// RUN: fir-opt --split-input-file --verify-diagnostics %s
+
+func.func @_QPcoordinate_box_derived_with_fir_len(%arg0: !fir.box<!fir.type<derived_2{len1:i32}>>) -> i32 {
+ %lp = arith.constant 22 : i32
+ %e = fir.len_param_index len1, !fir.type<derived_1{len1:i32}>(%lp : i32)
+ // expected-error at +1 {{'fir.coordinate_of' op len_param_index type not compatible with reference type}}
+ %q = fir.coordinate_of %arg0, %e : (!fir.box<!fir.type<derived_2{len1:i32}>>, !fir.len) -> !fir.ref<i32>
+ %val = fir.load %q : !fir.ref<i32>
+ return %val : i32
+}
+
+// -----
+
+func.func @_QPcoordinate_box_derived_with_fir_len2(%arg0: !fir.box<!fir.array<?x!fir.type<derived_2{len1:i32}>>>) -> i32 {
+ %lp = arith.constant 22 : i32
+ %e = fir.len_param_index len1, !fir.type<derived_1{len1:i32}>(%lp : i32)
+ // expected-error at +1 {{'fir.coordinate_of' op too many operands for len_param_index case}}
+ %q = fir.coordinate_of %arg0, %lp, %e : (!fir.box<!fir.array<?x!fir.type<derived_2{len1:i32}>>>, i32, !fir.len) -> !fir.ref<i32>
+ %val = fir.load %q : !fir.ref<i32>
+ return %val : i32
+}
+
+// -----
+
+func.func @_QPcoordinate_box_derived_with_fir_len3(%arg0: !fir.box<!fir.type<derived_2{len1:i32}>>) -> i32 {
+ %lp = arith.constant 22 : i32
+ %e = fir.len_param_index len1, !fir.type<derived_1{len1:i32}>(%lp : i32)
+ // expected-error at +1 {{'fir.coordinate_of' op len_param_index must be last argument}}
+ %q = fir.coordinate_of %arg0, %e, %e : (!fir.box<!fir.type<derived_2{len1:i32}>>, !fir.len, !fir.len) -> !fir.ref<i32>
+ %val = fir.load %q : !fir.ref<i32>
+ return %val : i32
+}
+
+// -----
+
+func.func @_QPtest_coordinate_of(%arr : !fir.ref<!fir.array<2 x !fir.char<10, 2>>>, %arg1: index) {
+ %1 = arith.constant 10 : i32
+ // expected-error at +1 {{'fir.coordinate_of' op character type mismatch}}
+ %2 = fir.coordinate_of %arr, %arg1, %1 : (!fir.ref<!fir.array<2 x !fir.char<10, 2>>>, index, i32) -> !fir.ref<!fir.char<1,10>>
+ return
+}
+
+// -----
+
+func.func @_QPtest_coordinate_of(%arr : !fir.ref<!fir.array<2 x i32>>, %arg1: index) {
+ // expected-error at +1 {{'fir.coordinate_of' op invalid parameters (too many)}}
+ %2 = fir.coordinate_of %arr, %arg1, %arg1 : (!fir.ref<!fir.array<2 x i32>>, index, index) -> !fir.ref<i32>
+ return
+}
diff --git a/flang/test/Fir/coordinateof.fir b/flang/test/Fir/coordinateof.fir
new file mode 100644
index 0000000000000..6603996fef60e
--- /dev/null
+++ b/flang/test/Fir/coordinateof.fir
@@ -0,0 +1,80 @@
+// RUN: fir-opt %s | tco | FileCheck %s
+
+// tests on coordinate_of op
+
+// CHECK-LABEL: @foo1
+func.func @foo1(%i : i32, %j : i32, %k : i32) -> !fir.ref<f32> {
+ %1 = fir.alloca !fir.array<10 x 20 x 30 x f32>
+ // CHECK: %[[alloca:.*]] = alloca [30 x [20 x [10 x float]]]
+ %2 = fir.convert %1 : (!fir.ref<!fir.array<10 x 20 x 30 x f32>>) -> !fir.ref<!fir.array<10 x 20 x ? x f32>>
+ // CHECK: getelementptr [20 x [10 x float]], ptr %[[alloca]]
+ %3 = fir.coordinate_of %2, %i, %j, %k : (!fir.ref<!fir.array<10 x 20 x ? x f32>>, i32, i32, i32) -> !fir.ref<f32>
+ return %3 : !fir.ref<f32>
+}
+
+// CHECK-LABEL: @foo2
+func.func @foo2(%i : i32, %j : i32, %k : i32) -> !fir.ref<f32> {
+ %1 = fir.alloca !fir.array<10 x 20 x 30 x f32>
+ // CHECK: %[[alloca:.*]] = alloca [30 x [20 x [10 x float]]]
+ %2 = fir.convert %1 : (!fir.ref<!fir.array<10 x 20 x 30 x f32>>) -> !fir.ref<!fir.array<?xf32>>
+ // CHECK: getelementptr float, ptr %[[alloca]]
+ %3 = fir.coordinate_of %2, %i : (!fir.ref<!fir.array<?xf32>>, i32) -> !fir.ref<f32>
+ return %3 : !fir.ref<f32>
+}
+
+// CHECK-LABEL: @foo3
+func.func @foo3(%box : !fir.box<!fir.array<?xi32>>, %i : i32) -> i32 {
+ // CHECK: %[[cvt:.*]] = sext i32 %
+ %ii = fir.convert %i : (i32) -> index
+ // CHECK: %[[gep0:.*]] = getelementptr { ptr
+ // CHECK: %[[boxptr:.*]] = load ptr, ptr %[[gep0]]
+ // CHECK: %[[gep1:.*]] = getelementptr { ptr, i64, {{.*}} i32 7
+ // CHECK: %[[stride:.*]] = load i64, ptr %[[gep1]]
+ // CHECK: %[[dimoffset:.*]] = mul i64 %[[cvt]], %[[stride]]
+ // CHECK: %[[offset:.*]] = add i64 %[[dimoffset]], 0
+ // CHECK: %[[gep2:.*]] = getelementptr i8, ptr %[[boxptr]], i64 %[[offset]]
+ %1 = fir.coordinate_of %box, %ii : (!fir.box<!fir.array<?xi32>>, index) -> !fir.ref<i32>
+ // CHECK: load i32, ptr %[[gep2]]
+ %rv = fir.load %1 : !fir.ref<i32>
+ return %rv : i32
+}
+
+// CHECK-LABEL: @foo4
+func.func @foo4(%a : !fir.ptr<!fir.array<5x15x25xi32>>, %i : i32, %j : i64, %k : index) -> i32 {
+ // CHECK: getelementptr [25 x [15 x [5 x
+ %1 = fir.coordinate_of %a, %k : (!fir.ptr<!fir.array<5x15x25xi32>>, index) -> !fir.ref<!fir.array<5x15xi32>>
+ // CHECK: getelementptr [15 x [5 x
+ %2 = fir.coordinate_of %1, %j : (!fir.ref<!fir.array<5x15xi32>>, i64) -> !fir.ref<!fir.array<5xi32>>
+ // CHECK: %[[ref:.*]] = getelementptr [5 x
+ %3 = fir.coordinate_of %2, %i : (!fir.ref<!fir.array<5xi32>>, i32) -> !fir.ref<i32>
+ // CHECK: load i32, ptr %[[ref]]
+ %4 = fir.load %3 : !fir.ref<i32>
+ return %4 : i32
+}
+
+// CHECK-LABEL: @foo5
+func.func @foo5(%box : !fir.box<!fir.ptr<!fir.array<?xi32>>>, %i : index) -> i32 {
+ // similar to foo3 test. Just check that the ptr type is not disturbing codegen.
+ %1 = fir.coordinate_of %box, %i : (!fir.box<!fir.ptr<!fir.array<?xi32>>>, index) -> !fir.ref<i32>
+ // CHECK: load i32, ptr %{{.*}}
+ %rv = fir.load %1 : !fir.ref<i32>
+ return %rv : i32
+}
+
+// CHECK-LABEL: @foo6
+// CHECK-SAME: (ptr %[[box:.*]], i64 %{{.*}}, ptr %{{.*}})
+func.func @foo6(%box : !fir.box<!fir.ptr<!fir.array<?x!fir.char<1>>>>, %i : i64 , %res : !fir.ref<!fir.char<1>>) {
+ // CHECK: %[[addr_gep:.*]] = getelementptr { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] }, ptr %[[box]], i32 0, i32 0
+ // CHECK: %[[addr:.*]] = load ptr, ptr %[[addr_gep]]
+ // CHECK: %[[stride_gep:.*]] = getelementptr { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] }, ptr %[[box]], i32 0, i32 7, i64 0, i32 2
+ // CHECK: %[[stride:.*]] = load i64, ptr %[[stride_gep]]
+ // CHECK: %[[mul:.*]] = mul i64 %{{.*}}, %[[stride]]
+ // CHECK: %[[offset:.*]] = add i64 %[[mul]], 0
+ // CHECK: %[[gep:.*]] = getelementptr i8, ptr %[[addr]], i64 %[[offset]]
+ %coor = fir.coordinate_of %box, %i : (!fir.box<!fir.ptr<!fir.array<?x!fir.char<1>>>>, i64) -> !fir.ref<!fir.char<1>>
+
+ // CHECK: load [1 x i8], ptr %[[gep]]
+ %load = fir.load %coor : !fir.ref<!fir.char<1>>
+ fir.store %load to %res : !fir.ref<!fir.char<1>>
+ return
+}
diff --git a/flang/test/Fir/invalid.fir b/flang/test/Fir/invalid.fir
index 43cef63362d5b..8d2a68fad87a6 100644
--- a/flang/test/Fir/invalid.fir
+++ b/flang/test/Fir/invalid.fir
@@ -287,17 +287,17 @@ func.func @test_coordinate_of(%arr : !fir.ref<!fir.array<*:f32>>) {
func.func @test_coordinate_of(%arr : !fir.ref<!fir.char<10>>) {
%1 = arith.constant 10 : i32
- // expected-error at +1 {{'fir.coordinate_of' op cannot apply coordinate_of to this type}}
- %2 = fir.coordinate_of %arr, %1 : (!fir.ref<!fir.char<10>>, i32) -> !fir.ref<f32>
+ // expected-error at +1 {{'fir.coordinate_of' op cannot apply to this element type}}
+ %2 = fir.coordinate_of %arr, %1 : (!fir.ref<!fir.char<10>>, i32) -> !fir.ref<!fir.char<10>>
return
}
// -----
-func.func @test_coordinate_of(%arr : !fir.ref<!fir.char<10, 1>>) {
+func.func @test_coordinate_of(%arr : !fir.ref<!fir.char<10, 2>>) {
%1 = arith.constant 10 : i32
- // expected-error at +1 {{'fir.coordinate_of' op cannot apply coordinate_of to this type}}
- %2 = fir.coordinate_of %arr, %1 : (!fir.ref<!fir.char<10, 1>>, i32) -> !fir.ref<f32>
+ // expected-error at +1 {{'fir.coordinate_of' op cannot apply to character singleton}}
+ %2 = fir.coordinate_of %arr, %1, %1 : (!fir.ref<!fir.char<10, 2>>, i32, i32) -> !fir.ref<!fir.char<10>>
return
}
More information about the flang-commits
mailing list