[flang]: This is to fix the HLFIR path for PPC Vector type intrinsics. (#66547)
[llvm-project.git] / flang / lib / Optimizer / HLFIR / IR / HLFIRDialect.cpp
blob08b2b0538c732a2bba837e9e3df1fc9a25ff1188
1 //===-- HLFIRDialect.cpp --------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // Coding style: https://mlir.llvm.org/getting_started/DeveloperGuide/
11 //===----------------------------------------------------------------------===//
13 #include "flang/Optimizer/HLFIR/HLFIRDialect.h"
14 #include "flang/Optimizer/Dialect/FIROps.h"
15 #include "flang/Optimizer/Dialect/FIRType.h"
16 #include "flang/Optimizer/HLFIR/HLFIROps.h"
17 #include "mlir/Dialect/Arith/IR/Arith.h"
18 #include "mlir/IR/Builders.h"
19 #include "mlir/IR/BuiltinTypes.h"
20 #include "mlir/IR/DialectImplementation.h"
21 #include "mlir/IR/Matchers.h"
22 #include "mlir/IR/OpImplementation.h"
23 #include "llvm/ADT/SmallVector.h"
24 #include "llvm/ADT/TypeSwitch.h"
26 #include "flang/Optimizer/HLFIR/HLFIRDialect.cpp.inc"
28 #define GET_TYPEDEF_CLASSES
29 #include "flang/Optimizer/HLFIR/HLFIRTypes.cpp.inc"
31 #define GET_ATTRDEF_CLASSES
32 #include "flang/Optimizer/HLFIR/HLFIRAttributes.cpp.inc"
34 void hlfir::hlfirDialect::initialize() {
35 addTypes<
36 #define GET_TYPEDEF_LIST
37 #include "flang/Optimizer/HLFIR/HLFIRTypes.cpp.inc"
38 >();
39 addOperations<
40 #define GET_OP_LIST
41 #include "flang/Optimizer/HLFIR/HLFIROps.cpp.inc"
42 >();
45 // `expr` `<` `*` | bounds (`x` bounds)* `:` type [`?`] `>`
46 // bounds ::= `?` | int-lit
47 mlir::Type hlfir::ExprType::parse(mlir::AsmParser &parser) {
48 if (parser.parseLess())
49 return {};
50 ExprType::Shape shape;
51 if (parser.parseOptionalStar()) {
52 if (parser.parseDimensionList(shape, /*allowDynamic=*/true))
53 return {};
54 } else if (parser.parseColon()) {
55 return {};
57 mlir::Type eleTy;
58 if (parser.parseType(eleTy))
59 return {};
60 const bool polymorphic = mlir::succeeded(parser.parseOptionalQuestion());
61 if (parser.parseGreater())
62 return {};
63 return ExprType::get(parser.getContext(), shape, eleTy, polymorphic);
66 void hlfir::ExprType::print(mlir::AsmPrinter &printer) const {
67 auto shape = getShape();
68 printer << '<';
69 if (shape.size()) {
70 for (const auto &b : shape) {
71 if (b >= 0)
72 printer << b << 'x';
73 else
74 printer << "?x";
77 printer << getEleTy();
78 if (isPolymorphic())
79 printer << '?';
80 printer << '>';
83 bool hlfir::isFortranVariableType(mlir::Type type) {
84 return llvm::TypeSwitch<mlir::Type, bool>(type)
85 .Case<fir::ReferenceType, fir::PointerType, fir::HeapType>([](auto p) {
86 mlir::Type eleType = p.getEleTy();
87 return eleType.isa<fir::BaseBoxType>() || !fir::hasDynamicSize(eleType);
89 .Case<fir::BaseBoxType, fir::BoxCharType>([](auto) { return true; })
90 .Case<fir::VectorType>([](auto) { return true; })
91 .Default([](mlir::Type) { return false; });
94 bool hlfir::isFortranScalarCharacterType(mlir::Type type) {
95 return isFortranScalarCharacterExprType(type) ||
96 type.isa<fir::BoxCharType>() ||
97 fir::unwrapPassByRefType(fir::unwrapRefType(type))
98 .isa<fir::CharacterType>();
101 bool hlfir::isFortranScalarCharacterExprType(mlir::Type type) {
102 if (auto exprType = type.dyn_cast<hlfir::ExprType>())
103 return exprType.isScalar() &&
104 exprType.getElementType().isa<fir::CharacterType>();
105 return false;
108 bool hlfir::isFortranArrayCharacterExprType(mlir::Type type) {
109 if (auto exprType = mlir::dyn_cast<hlfir::ExprType>(type))
110 return exprType.isArray() &&
111 mlir::isa<fir::CharacterType>(exprType.getElementType());
113 return false;
116 bool hlfir::isFortranScalarNumericalType(mlir::Type type) {
117 return fir::isa_integer(type) || fir::isa_real(type) ||
118 fir::isa_complex(type);
121 bool hlfir::isFortranNumericalArrayObject(mlir::Type type) {
122 if (isBoxAddressType(type))
123 return false;
124 if (auto arrayTy =
125 getFortranElementOrSequenceType(type).dyn_cast<fir::SequenceType>())
126 return isFortranScalarNumericalType(arrayTy.getEleTy());
127 return false;
130 bool hlfir::isFortranNumericalOrLogicalArrayObject(mlir::Type type) {
131 if (isBoxAddressType(type))
132 return false;
133 if (auto arrayTy =
134 getFortranElementOrSequenceType(type).dyn_cast<fir::SequenceType>()) {
135 mlir::Type eleTy = arrayTy.getEleTy();
136 return isFortranScalarNumericalType(eleTy) ||
137 mlir::isa<fir::LogicalType>(eleTy);
139 return false;
142 bool hlfir::isFortranArrayObject(mlir::Type type) {
143 if (isBoxAddressType(type))
144 return false;
145 return !!getFortranElementOrSequenceType(type).dyn_cast<fir::SequenceType>();
148 bool hlfir::isPassByRefOrIntegerType(mlir::Type type) {
149 mlir::Type unwrappedType = fir::unwrapPassByRefType(type);
150 return fir::isa_integer(unwrappedType);
153 bool hlfir::isI1Type(mlir::Type type) {
154 if (mlir::IntegerType integer = type.dyn_cast<mlir::IntegerType>())
155 if (integer.getWidth() == 1)
156 return true;
157 return false;
160 bool hlfir::isFortranLogicalArrayObject(mlir::Type type) {
161 if (isBoxAddressType(type))
162 return false;
163 if (auto arrayTy =
164 getFortranElementOrSequenceType(type).dyn_cast<fir::SequenceType>()) {
165 mlir::Type eleTy = arrayTy.getEleTy();
166 return mlir::isa<fir::LogicalType>(eleTy);
168 return false;
171 bool hlfir::isMaskArgument(mlir::Type type) {
172 if (isBoxAddressType(type))
173 return false;
175 mlir::Type unwrappedType = fir::unwrapPassByRefType(fir::unwrapRefType(type));
176 mlir::Type elementType = getFortranElementType(unwrappedType);
177 if (unwrappedType != elementType)
178 // input type is an array
179 return mlir::isa<fir::LogicalType>(elementType);
181 // input is a scalar, so allow i1 too
182 return mlir::isa<fir::LogicalType>(elementType) || isI1Type(elementType);
185 bool hlfir::isPolymorphicObject(mlir::Type type) {
186 if (auto exprType = mlir::dyn_cast<hlfir::ExprType>(type))
187 return exprType.isPolymorphic();
189 return fir::isPolymorphicType(type);
192 mlir::Value hlfir::genExprShape(mlir::OpBuilder &builder,
193 const mlir::Location &loc,
194 const hlfir::ExprType &expr) {
195 mlir::IndexType indexTy = builder.getIndexType();
196 llvm::SmallVector<mlir::Value> extents;
197 extents.reserve(expr.getRank());
199 for (std::int64_t extent : expr.getShape()) {
200 if (extent == hlfir::ExprType::getUnknownExtent())
201 return {};
202 extents.emplace_back(builder.create<mlir::arith::ConstantOp>(
203 loc, indexTy, builder.getIntegerAttr(indexTy, extent)));
206 fir::ShapeType shapeTy =
207 fir::ShapeType::get(builder.getContext(), expr.getRank());
208 fir::ShapeOp shape = builder.create<fir::ShapeOp>(loc, shapeTy, extents);
209 return shape.getResult();
212 bool hlfir::mayHaveAllocatableComponent(mlir::Type ty) {
213 return fir::isPolymorphicType(ty) || fir::isUnlimitedPolymorphicType(ty) ||
214 fir::isRecordWithAllocatableMember(hlfir::getFortranElementType(ty));