|
15 | 15 | #include "flang/Optimizer/Builder/DirectivesCommon.h"
|
16 | 16 | #include "flang/Optimizer/Builder/FIRBuilder.h"
|
17 | 17 | #include "flang/Optimizer/Builder/HLFIRTools.h"
|
| 18 | +#include "flang/Optimizer/CodeGen/CGOps.h" |
18 | 19 | #include "flang/Optimizer/Dialect/FIROps.h"
|
19 | 20 | #include "flang/Optimizer/Dialect/FIROpsSupport.h"
|
20 | 21 | #include "flang/Optimizer/Dialect/FIRType.h"
|
|
24 | 25 | #include "mlir/Dialect/OpenACC/OpenACC.h"
|
25 | 26 | #include "mlir/IR/BuiltinOps.h"
|
26 | 27 | #include "mlir/Support/LLVM.h"
|
| 28 | +#include "llvm/ADT/TypeSwitch.h" |
27 | 29 |
|
28 | 30 | namespace fir::acc {
|
29 | 31 |
|
@@ -224,4 +226,145 @@ OpenACCMappableModel<fir::BaseBoxType>::generateAccBounds(
|
224 | 226 | return {};
|
225 | 227 | }
|
226 | 228 |
|
| 229 | +static bool isScalarLike(mlir::Type type) { |
| 230 | + return fir::isa_trivial(type) || fir::isa_ref_type(type); |
| 231 | +} |
| 232 | + |
| 233 | +static bool isArrayLike(mlir::Type type) { |
| 234 | + return mlir::isa<fir::SequenceType>(type); |
| 235 | +} |
| 236 | + |
| 237 | +static bool isCompositeLike(mlir::Type type) { |
| 238 | + return mlir::isa<fir::RecordType, fir::ClassType, mlir::TupleType>(type); |
| 239 | +} |
| 240 | + |
| 241 | +template <> |
| 242 | +mlir::acc::VariableTypeCategory |
| 243 | +OpenACCMappableModel<fir::SequenceType>::getTypeCategory( |
| 244 | + mlir::Type type, mlir::Value var) const { |
| 245 | + return mlir::acc::VariableTypeCategory::array; |
| 246 | +} |
| 247 | + |
| 248 | +template <> |
| 249 | +mlir::acc::VariableTypeCategory |
| 250 | +OpenACCMappableModel<fir::BaseBoxType>::getTypeCategory(mlir::Type type, |
| 251 | + mlir::Value var) const { |
| 252 | + |
| 253 | + mlir::Type eleTy = fir::dyn_cast_ptrOrBoxEleTy(type); |
| 254 | + |
| 255 | + // If the type enclosed by the box is a mappable type, then have it |
| 256 | + // provide the type category. |
| 257 | + if (auto mappableTy = mlir::dyn_cast<mlir::acc::MappableType>(eleTy)) |
| 258 | + return mappableTy.getTypeCategory(var); |
| 259 | + |
| 260 | + // For all arrays, despite whether they are allocatable, pointer, assumed, |
| 261 | + // etc, we'd like to categorize them as "array". |
| 262 | + if (isArrayLike(eleTy)) |
| 263 | + return mlir::acc::VariableTypeCategory::array; |
| 264 | + |
| 265 | + // We got here because we don't have an array nor a mappable type. At this |
| 266 | + // point, we know we have a type that fits the "aggregate" definition since it |
| 267 | + // is a type with a descriptor. Try to refine it by checking if it matches the |
| 268 | + // "composite" definition. |
| 269 | + if (isCompositeLike(eleTy)) |
| 270 | + return mlir::acc::VariableTypeCategory::composite; |
| 271 | + |
| 272 | + // Even if we have a scalar type - simply because it is wrapped in a box |
| 273 | + // we want to categorize it as "nonscalar". Anything else would've been |
| 274 | + // non-scalar anyway. |
| 275 | + return mlir::acc::VariableTypeCategory::nonscalar; |
| 276 | +} |
| 277 | + |
| 278 | +static mlir::TypedValue<mlir::acc::PointerLikeType> |
| 279 | +getBaseRef(mlir::TypedValue<mlir::acc::PointerLikeType> varPtr) { |
| 280 | + // If there is no defining op - the unwrapped reference is the base one. |
| 281 | + mlir::Operation *op = varPtr.getDefiningOp(); |
| 282 | + if (!op) |
| 283 | + return varPtr; |
| 284 | + |
| 285 | + // Look to find if this value originates from an interior pointer |
| 286 | + // calculation op. |
| 287 | + mlir::Value baseRef = |
| 288 | + llvm::TypeSwitch<mlir::Operation *, mlir::Value>(op) |
| 289 | + .Case<hlfir::DesignateOp>([&](auto op) { |
| 290 | + // Get the base object. |
| 291 | + return op.getMemref(); |
| 292 | + }) |
| 293 | + .Case<fir::ArrayCoorOp, fir::cg::XArrayCoorOp>([&](auto op) { |
| 294 | + // Get the base array on which the coordinate is being applied. |
| 295 | + return op.getMemref(); |
| 296 | + }) |
| 297 | + .Case<fir::CoordinateOp>([&](auto op) { |
| 298 | + // For coordinate operation which is applied on derived type |
| 299 | + // object, get the base object. |
| 300 | + return op.getRef(); |
| 301 | + }) |
| 302 | + .Default([&](mlir::Operation *) { return varPtr; }); |
| 303 | + |
| 304 | + return mlir::cast<mlir::TypedValue<mlir::acc::PointerLikeType>>(baseRef); |
| 305 | +} |
| 306 | + |
| 307 | +static mlir::acc::VariableTypeCategory |
| 308 | +categorizePointee(mlir::Type pointer, |
| 309 | + mlir::TypedValue<mlir::acc::PointerLikeType> varPtr, |
| 310 | + mlir::Type varType) { |
| 311 | + // FIR uses operations to compute interior pointers. |
| 312 | + // So for example, an array element or composite field access to a float |
| 313 | + // value would both be represented as !fir.ref<f32>. We do not want to treat |
| 314 | + // such a reference as a scalar. Thus unwrap interior pointer calculations. |
| 315 | + auto baseRef = getBaseRef(varPtr); |
| 316 | + mlir::Type eleTy = baseRef.getType().getElementType(); |
| 317 | + |
| 318 | + if (auto mappableTy = mlir::dyn_cast<mlir::acc::MappableType>(eleTy)) |
| 319 | + return mappableTy.getTypeCategory(varPtr); |
| 320 | + |
| 321 | + if (isScalarLike(eleTy)) |
| 322 | + return mlir::acc::VariableTypeCategory::scalar; |
| 323 | + if (isArrayLike(eleTy)) |
| 324 | + return mlir::acc::VariableTypeCategory::array; |
| 325 | + if (isCompositeLike(eleTy)) |
| 326 | + return mlir::acc::VariableTypeCategory::composite; |
| 327 | + if (mlir::isa<fir::CharacterType, mlir::FunctionType>(eleTy)) |
| 328 | + return mlir::acc::VariableTypeCategory::nonscalar; |
| 329 | + // "pointers" - in the sense of raw address point-of-view, are considered |
| 330 | + // scalars. However |
| 331 | + if (mlir::isa<fir::LLVMPointerType>(eleTy)) |
| 332 | + return mlir::acc::VariableTypeCategory::scalar; |
| 333 | + |
| 334 | + // Without further checking, this type cannot be categorized. |
| 335 | + return mlir::acc::VariableTypeCategory::uncategorized; |
| 336 | +} |
| 337 | + |
| 338 | +template <> |
| 339 | +mlir::acc::VariableTypeCategory |
| 340 | +OpenACCPointerLikeModel<fir::ReferenceType>::getPointeeTypeCategory( |
| 341 | + mlir::Type pointer, mlir::TypedValue<mlir::acc::PointerLikeType> varPtr, |
| 342 | + mlir::Type varType) const { |
| 343 | + return categorizePointee(pointer, varPtr, varType); |
| 344 | +} |
| 345 | + |
| 346 | +template <> |
| 347 | +mlir::acc::VariableTypeCategory |
| 348 | +OpenACCPointerLikeModel<fir::PointerType>::getPointeeTypeCategory( |
| 349 | + mlir::Type pointer, mlir::TypedValue<mlir::acc::PointerLikeType> varPtr, |
| 350 | + mlir::Type varType) const { |
| 351 | + return categorizePointee(pointer, varPtr, varType); |
| 352 | +} |
| 353 | + |
| 354 | +template <> |
| 355 | +mlir::acc::VariableTypeCategory |
| 356 | +OpenACCPointerLikeModel<fir::HeapType>::getPointeeTypeCategory( |
| 357 | + mlir::Type pointer, mlir::TypedValue<mlir::acc::PointerLikeType> varPtr, |
| 358 | + mlir::Type varType) const { |
| 359 | + return categorizePointee(pointer, varPtr, varType); |
| 360 | +} |
| 361 | + |
| 362 | +template <> |
| 363 | +mlir::acc::VariableTypeCategory |
| 364 | +OpenACCPointerLikeModel<fir::LLVMPointerType>::getPointeeTypeCategory( |
| 365 | + mlir::Type pointer, mlir::TypedValue<mlir::acc::PointerLikeType> varPtr, |
| 366 | + mlir::Type varType) const { |
| 367 | + return categorizePointee(pointer, varPtr, varType); |
| 368 | +} |
| 369 | + |
227 | 370 | } // namespace fir::acc
|
0 commit comments