mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-02-24 20:44:09 +00:00
Revert "[fir] Add fir.extract_value and fir.insert_value conversion"
This reverts commit ea55503d7ca5b6ded73b0fd01a8c528f68e00521.
This commit is contained in:
parent
456a7e5231
commit
7a189fb267
@ -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);
|
||||
|
@ -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
|
@ -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>
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user