Revert "[fir] Add fir.extract_value and fir.insert_value conversion"

This reverts commit ea55503d7ca5b6ded73b0fd01a8c528f68e00521.
This commit is contained in:
Valentin Clement 2021-11-05 22:16:37 +01:00
parent 456a7e5231
commit 7a189fb267
No known key found for this signature in database
GPG Key ID: 086D54783C928776
4 changed files with 4 additions and 330 deletions

View File

@ -296,105 +296,6 @@ struct ZeroOpConversion : public FIROpConversion<fir::ZeroOp> {
}
};
// Code shared between insert_value and extract_value Ops.
struct ValueOpCommon {
// Translate the arguments pertaining to any multidimensional array to
// row-major order for LLVM-IR.
static void toRowMajor(SmallVectorImpl<mlir::Attribute> &attrs,
mlir::Type ty) {
assert(ty && "type is null");
const auto end = attrs.size();
for (std::remove_const_t<decltype(end)> i = 0; i < end; ++i) {
if (auto seq = ty.dyn_cast<mlir::LLVM::LLVMArrayType>()) {
const auto dim = getDimension(seq);
if (dim > 1) {
auto ub = std::min(i + dim, end);
std::reverse(attrs.begin() + i, attrs.begin() + ub);
i += dim - 1;
}
ty = getArrayElementType(seq);
} else if (auto st = ty.dyn_cast<mlir::LLVM::LLVMStructType>()) {
ty = st.getBody()[attrs[i].cast<mlir::IntegerAttr>().getInt()];
} else {
llvm_unreachable("index into invalid type");
}
}
}
static llvm::SmallVector<mlir::Attribute>
collectIndices(mlir::ConversionPatternRewriter &rewriter,
mlir::ArrayAttr arrAttr) {
llvm::SmallVector<mlir::Attribute> attrs;
for (auto i = arrAttr.begin(), e = arrAttr.end(); i != e; ++i) {
if (i->isa<mlir::IntegerAttr>()) {
attrs.push_back(*i);
} else {
auto fieldName = i->cast<mlir::StringAttr>().getValue();
++i;
auto ty = i->cast<mlir::TypeAttr>().getValue();
auto index = ty.cast<fir::RecordType>().getFieldIndex(fieldName);
attrs.push_back(mlir::IntegerAttr::get(rewriter.getI32Type(), index));
}
}
return attrs;
}
private:
static unsigned getDimension(mlir::LLVM::LLVMArrayType ty) {
unsigned result = 1;
for (auto eleTy = ty.getElementType().dyn_cast<mlir::LLVM::LLVMArrayType>();
eleTy;
eleTy = eleTy.getElementType().dyn_cast<mlir::LLVM::LLVMArrayType>())
++result;
return result;
}
static mlir::Type getArrayElementType(mlir::LLVM::LLVMArrayType ty) {
auto eleTy = ty.getElementType();
while (auto arrTy = eleTy.dyn_cast<mlir::LLVM::LLVMArrayType>())
eleTy = arrTy.getElementType();
return eleTy;
}
};
/// Extract a subobject value from an ssa-value of aggregate type
struct ExtractValueOpConversion
: public FIROpAndTypeConversion<fir::ExtractValueOp>,
public ValueOpCommon {
using FIROpAndTypeConversion::FIROpAndTypeConversion;
mlir::LogicalResult
doRewrite(fir::ExtractValueOp extractVal, mlir::Type ty, OpAdaptor adaptor,
mlir::ConversionPatternRewriter &rewriter) const override {
auto attrs = collectIndices(rewriter, extractVal.coor());
toRowMajor(attrs, adaptor.getOperands()[0].getType());
auto position = mlir::ArrayAttr::get(extractVal.getContext(), attrs);
rewriter.replaceOpWithNewOp<mlir::LLVM::ExtractValueOp>(
extractVal, ty, adaptor.getOperands()[0], position);
return success();
}
};
/// InsertValue is the generalized instruction for the composition of new
/// aggregate type values.
struct InsertValueOpConversion
: public FIROpAndTypeConversion<fir::InsertValueOp>,
public ValueOpCommon {
using FIROpAndTypeConversion::FIROpAndTypeConversion;
mlir::LogicalResult
doRewrite(fir::InsertValueOp insertVal, mlir::Type ty, OpAdaptor adaptor,
mlir::ConversionPatternRewriter &rewriter) const override {
auto attrs = collectIndices(rewriter, insertVal.coor());
toRowMajor(attrs, adaptor.getOperands()[0].getType());
auto position = mlir::ArrayAttr::get(insertVal.getContext(), attrs);
rewriter.replaceOpWithNewOp<mlir::LLVM::InsertValueOp>(
insertVal, ty, adaptor.getOperands()[0], adaptor.getOperands()[1],
position);
return success();
}
};
/// InsertOnRange inserts a value into a sequence over a range of offsets.
struct InsertOnRangeOpConversion
: public FIROpAndTypeConversion<fir::InsertOnRangeOp> {
@ -488,11 +389,10 @@ public:
auto *context = getModule().getContext();
fir::LLVMTypeConverter typeConverter{getModule()};
mlir::OwningRewritePatternList pattern(context);
pattern.insert<
AddrOfOpConversion, ExtractValueOpConversion, HasValueOpConversion,
GlobalOpConversion, InsertOnRangeOpConversion, InsertValueOpConversion,
SelectOpConversion, SelectRankOpConversion, UndefOpConversion,
UnreachableOpConversion, ZeroOpConversion>(typeConverter);
pattern.insert<AddrOfOpConversion, HasValueOpConversion, GlobalOpConversion,
InsertOnRangeOpConversion, SelectOpConversion,
SelectRankOpConversion, UnreachableOpConversion,
ZeroOpConversion, UndefOpConversion>(typeConverter);
mlir::populateStdToLLVMConversionPatterns(typeConverter, pattern);
mlir::arith::populateArithmeticToLLVMConversionPatterns(typeConverter,
pattern);

View File

@ -1,134 +0,0 @@
//===-- DescriptorModel.h -- model of descriptors for codegen ---*- C++ -*-===//
//
// 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
//
//===----------------------------------------------------------------------===//
// LLVM IR dialect models of C++ types.
//
// This supplies a set of model builders to decompose the C declaration of a
// descriptor (as encoded in ISO_Fortran_binding.h and elsewhere) and
// reconstruct that type in the LLVM IR dialect.
//
// TODO: It is understood that this is deeply incorrect as far as building a
// portability layer for cross-compilation as these reflected types are those of
// the build machine and not necessarily that of either the host or the target.
// This assumption that build == host == target is actually pervasive across the
// compiler (https://llvm.org/PR52418).
//
//===----------------------------------------------------------------------===//
#ifndef OPTIMIZER_DESCRIPTOR_MODEL_H
#define OPTIMIZER_DESCRIPTOR_MODEL_H
#include "flang/ISO_Fortran_binding.h"
#include "flang/Runtime/descriptor.h"
#include "mlir/Dialect/LLVMIR/LLVMTypes.h"
#include "llvm/Support/ErrorHandling.h"
#include <tuple>
namespace fir {
using TypeBuilderFunc = mlir::Type (*)(mlir::MLIRContext *);
/// Get the LLVM IR dialect model for building a particular C++ type, `T`.
template <typename T>
TypeBuilderFunc getModel();
template <>
TypeBuilderFunc getModel<void *>() {
return [](mlir::MLIRContext *context) -> mlir::Type {
return mlir::LLVM::LLVMPointerType::get(mlir::IntegerType::get(context, 8));
};
}
template <>
TypeBuilderFunc getModel<unsigned>() {
return [](mlir::MLIRContext *context) -> mlir::Type {
return mlir::IntegerType::get(context, sizeof(unsigned) * 8);
};
}
template <>
TypeBuilderFunc getModel<int>() {
return [](mlir::MLIRContext *context) -> mlir::Type {
return mlir::IntegerType::get(context, sizeof(int) * 8);
};
}
template <>
TypeBuilderFunc getModel<unsigned long>() {
return [](mlir::MLIRContext *context) -> mlir::Type {
return mlir::IntegerType::get(context, sizeof(unsigned long) * 8);
};
}
template <>
TypeBuilderFunc getModel<unsigned long long>() {
return [](mlir::MLIRContext *context) -> mlir::Type {
return mlir::IntegerType::get(context, sizeof(unsigned long long) * 8);
};
}
template <>
TypeBuilderFunc getModel<long long>() {
return [](mlir::MLIRContext *context) -> mlir::Type {
return mlir::IntegerType::get(context, sizeof(long long) * 8);
};
}
template <>
TypeBuilderFunc getModel<Fortran::ISO::CFI_rank_t>() {
return [](mlir::MLIRContext *context) -> mlir::Type {
return mlir::IntegerType::get(context,
sizeof(Fortran::ISO::CFI_rank_t) * 8);
};
}
template <>
TypeBuilderFunc getModel<Fortran::ISO::CFI_type_t>() {
return [](mlir::MLIRContext *context) -> mlir::Type {
return mlir::IntegerType::get(context,
sizeof(Fortran::ISO::CFI_type_t) * 8);
};
}
template <>
TypeBuilderFunc getModel<Fortran::ISO::CFI_dim_t>() {
return [](mlir::MLIRContext *context) -> mlir::Type {
auto indexTy = getModel<Fortran::ISO::CFI_index_t>()(context);
return mlir::LLVM::LLVMArrayType::get(indexTy, 3);
};
}
template <>
TypeBuilderFunc
getModel<Fortran::ISO::cfi_internal::FlexibleArray<Fortran::ISO::CFI_dim_t>>() {
return getModel<Fortran::ISO::CFI_dim_t>();
}
//===----------------------------------------------------------------------===//
// Descriptor reflection
//===----------------------------------------------------------------------===//
/// Get the type model of the field number `Field` in an ISO CFI descriptor.
template <int Field>
static constexpr TypeBuilderFunc getDescFieldTypeModel() {
Fortran::ISO::Fortran_2018::CFI_cdesc_t dummyDesc{};
// check that the descriptor is exactly 8 fields as specified in CFI_cdesc_t
// in flang/include/flang/ISO_Fortran_binding.h.
auto [a, b, c, d, e, f, g, h] = dummyDesc;
auto tup = std::tie(a, b, c, d, e, f, g, h);
auto field = std::get<Field>(tup);
return getModel<decltype(field)>();
}
/// An extended descriptor is defined by a class in runtime/descriptor.h. The
/// three fields in the class are hard-coded here, unlike the reflection used on
/// the ISO parts, which are a POD.
template <int Field>
static constexpr TypeBuilderFunc getExtendedDescFieldTypeModel() {
if constexpr (Field == 8) {
return getModel<void *>();
} else if constexpr (Field == 9) {
return getModel<Fortran::runtime::typeInfo::TypeParameterValue>();
} else {
llvm_unreachable("extended ISO descriptor only has 10 fields");
}
}
} // namespace fir
#endif // OPTIMIZER_DESCRIPTOR_MODEL_H

View File

@ -13,9 +13,6 @@
#ifndef FORTRAN_OPTIMIZER_CODEGEN_TYPECONVERTER_H
#define FORTRAN_OPTIMIZER_CODEGEN_TYPECONVERTER_H
#include "DescriptorModel.h"
#include "flang/Lower/Todo.h" // remove when TODO's are done
#include "llvm/ADT/StringMap.h"
#include "llvm/Support/Debug.h"
namespace fir {
@ -29,35 +26,10 @@ public:
LLVM_DEBUG(llvm::dbgs() << "FIR type converter\n");
// Each conversion should return a value of type mlir::Type.
addConversion(
[&](fir::RecordType derived) { return convertRecordType(derived); });
addConversion(
[&](fir::ReferenceType ref) { return convertPointerLike(ref); });
addConversion(
[&](SequenceType sequence) { return convertSequenceType(sequence); });
addConversion([&](mlir::TupleType tuple) {
LLVM_DEBUG(llvm::dbgs() << "type convert: " << tuple << '\n');
llvm::SmallVector<mlir::Type> inMembers;
tuple.getFlattenedTypes(inMembers);
llvm::SmallVector<mlir::Type> members;
for (auto mem : inMembers)
members.push_back(convertType(mem).cast<mlir::Type>());
return mlir::LLVM::LLVMStructType::getLiteral(&getContext(), members,
/*isPacked=*/false);
});
}
// fir.type<name(p : TY'...){f : TY...}> --> llvm<"%name = { ty... }">
mlir::Type convertRecordType(fir::RecordType derived) {
auto name = derived.getName();
auto st = mlir::LLVM::LLVMStructType::getIdentified(&getContext(), name);
llvm::SmallVector<mlir::Type> members;
for (auto mem : derived.getTypeList()) {
members.push_back(convertType(mem.second).cast<mlir::Type>());
}
if (mlir::succeeded(st.setBody(members, /*isPacked=*/false)))
return st;
return mlir::Type();
}
template <typename A>

View File

@ -259,67 +259,3 @@ func @select_rank(%arg : i32, %arg2 : i32) -> i32 {
// CHECK: 3: ^bb3(%[[ARG1]], %[[C2]] : i32, i32),
// CHECK: 4: ^bb4(%[[C1]] : i32)
// CHECK: ]
// -----
// Test fir.extract_value operation conversion with derived type.
func @extract_derived_type() -> f32 {
%0 = fir.undefined !fir.type<derived{f:f32}>
%1 = fir.extract_value %0, ["f", !fir.type<derived{f:f32}>] : (!fir.type<derived{f:f32}>) -> f32
return %1 : f32
}
// CHECK-LABEL: llvm.func @extract_derived_type
// CHECK: %[[STRUCT:.*]] = llvm.mlir.undef : !llvm.struct<"derived", (f32)>
// CHECK: %[[VALUE:.*]] = llvm.extractvalue %[[STRUCT]][0 : i32] : !llvm.struct<"derived", (f32)>
// CHECK: llvm.return %[[VALUE]] : f32
// -----
// Test fir.extract_value operation conversion with a multi-dimensional array
// of tuple.
func @extract_array(%a : !fir.array<10x10xtuple<i32, f32>>) -> f32 {
%0 = fir.extract_value %a, [5 : index, 4 : index, 1 : index] : (!fir.array<10x10xtuple<i32, f32>>) -> f32
return %0 : f32
}
// CHECK-LABEL: llvm.func @extract_array(
// CHECK-SAME: %[[ARR:.*]]: !llvm.array<10 x array<10 x struct<(i32, f32)>>>
// CHECK: %[[VALUE:.*]] = llvm.extractvalue %[[ARR]][4 : index, 5 : index, 1 : index] : !llvm.array<10 x array<10 x struct<(i32, f32)>>>
// CHECK: llvm.return %[[VALUE]] : f32
// -----
// Test fir.insert_value operation conversion with a multi-dimensional array
// of tuple.
func @extract_array(%a : !fir.array<10x10xtuple<i32, f32>>) {
%f = arith.constant 2.0 : f32
%i = arith.constant 1 : i32
%0 = fir.insert_value %a, %i, [5 : index, 4 : index, 0 : index] : (!fir.array<10x10xtuple<i32, f32>>, i32) -> !fir.array<10x10xtuple<i32, f32>>
%1 = fir.insert_value %a, %f, [5 : index, 4 : index, 1 : index] : (!fir.array<10x10xtuple<i32, f32>>, f32) -> !fir.array<10x10xtuple<i32, f32>>
return
}
// CHECK-LABEL: llvm.func @extract_array(
// CHECK-SAME: %[[ARR:.*]]: !llvm.array<10 x array<10 x struct<(i32, f32)>>>
// CHECK: %{{.*}} = llvm.insertvalue %{{.*}}, %[[ARR]][4 : index, 5 : index, 0 : index] : !llvm.array<10 x array<10 x struct<(i32, f32)>>>
// CHECK: %{{.*}} = llvm.insertvalue %{{.*}}, %[[ARR]][4 : index, 5 : index, 1 : index] : !llvm.array<10 x array<10 x struct<(i32, f32)>>>
// CHECK: llvm.return
// -----
// Test fir.insert_value operation conversion with derived type.
func @insert_tuple(%a : tuple<i32, f32>) {
%f = arith.constant 2.0 : f32
%1 = fir.insert_value %a, %f, [1 : index] : (tuple<i32, f32>, f32) -> tuple<i32, f32>
return
}
// CHECK-LABEL: func @insert_tuple(
// CHECK-SAME: %[[TUPLE:.*]]: !llvm.struct<(i32, f32)>
// CHECK: %{{.*}} = llvm.insertvalue %{{.*}}, %[[TUPLE]][1 : index] : !llvm.struct<(i32, f32)>
// CHECK: llvm.return