xref: /llvm-project/flang/lib/Lower/OpenMP/Utils.cpp (revision 2f2f16f32bb2a6c250b19adbc229d9dc3b38640c)
1 //===-- Utils..cpp ----------------------------------------------*- C++ -*-===//
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/
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "Utils.h"
14 #include "Clauses.h"
15 
16 #include <flang/Lower/AbstractConverter.h>
17 #include <flang/Lower/ConvertType.h>
18 #include <flang/Optimizer/Builder/FIRBuilder.h>
19 #include <flang/Parser/parse-tree.h>
20 #include <flang/Parser/tools.h>
21 #include <flang/Semantics/tools.h>
22 #include <llvm/Support/CommandLine.h>
23 
24 llvm::cl::opt<bool> treatIndexAsSection(
25     "openmp-treat-index-as-section",
26     llvm::cl::desc("In the OpenMP data clauses treat `a(N)` as `a(N:N)`."),
27     llvm::cl::init(true));
28 
29 llvm::cl::opt<bool> enableDelayedPrivatization(
30     "openmp-enable-delayed-privatization",
31     llvm::cl::desc(
32         "Emit `[first]private` variables as clauses on the MLIR ops."),
33     llvm::cl::init(false));
34 
35 namespace Fortran {
36 namespace lower {
37 namespace omp {
38 
39 void genObjectList(const ObjectList &objects,
40                    Fortran::lower::AbstractConverter &converter,
41                    llvm::SmallVectorImpl<mlir::Value> &operands) {
42   for (const Object &object : objects) {
43     const Fortran::semantics::Symbol *sym = object.id();
44     assert(sym && "Expected Symbol");
45     if (mlir::Value variable = converter.getSymbolAddress(*sym)) {
46       operands.push_back(variable);
47     } else if (const auto *details =
48                    sym->detailsIf<Fortran::semantics::HostAssocDetails>()) {
49       operands.push_back(converter.getSymbolAddress(details->symbol()));
50       converter.copySymbolBinding(details->symbol(), *sym);
51     }
52   }
53 }
54 
55 void genObjectList2(const Fortran::parser::OmpObjectList &objectList,
56                     Fortran::lower::AbstractConverter &converter,
57                     llvm::SmallVectorImpl<mlir::Value> &operands) {
58   auto addOperands = [&](Fortran::lower::SymbolRef sym) {
59     const mlir::Value variable = converter.getSymbolAddress(sym);
60     if (variable) {
61       operands.push_back(variable);
62     } else if (const auto *details =
63                    sym->detailsIf<Fortran::semantics::HostAssocDetails>()) {
64       operands.push_back(converter.getSymbolAddress(details->symbol()));
65       converter.copySymbolBinding(details->symbol(), sym);
66     }
67   };
68   for (const Fortran::parser::OmpObject &ompObject : objectList.v) {
69     Fortran::semantics::Symbol *sym = getOmpObjectSymbol(ompObject);
70     addOperands(*sym);
71   }
72 }
73 
74 mlir::Type getLoopVarType(Fortran::lower::AbstractConverter &converter,
75                           std::size_t loopVarTypeSize) {
76   // OpenMP runtime requires 32-bit or 64-bit loop variables.
77   loopVarTypeSize = loopVarTypeSize * 8;
78   if (loopVarTypeSize < 32) {
79     loopVarTypeSize = 32;
80   } else if (loopVarTypeSize > 64) {
81     loopVarTypeSize = 64;
82     mlir::emitWarning(converter.getCurrentLocation(),
83                       "OpenMP loop iteration variable cannot have more than 64 "
84                       "bits size and will be narrowed into 64 bits.");
85   }
86   assert((loopVarTypeSize == 32 || loopVarTypeSize == 64) &&
87          "OpenMP loop iteration variable size must be transformed into 32-bit "
88          "or 64-bit");
89   return converter.getFirOpBuilder().getIntegerType(loopVarTypeSize);
90 }
91 
92 void gatherFuncAndVarSyms(
93     const ObjectList &objects, mlir::omp::DeclareTargetCaptureClause clause,
94     llvm::SmallVectorImpl<DeclareTargetCapturePair> &symbolAndClause) {
95   for (const Object &object : objects)
96     symbolAndClause.emplace_back(clause, *object.id());
97 }
98 
99 Fortran::semantics::Symbol *
100 getOmpObjectSymbol(const Fortran::parser::OmpObject &ompObject) {
101   Fortran::semantics::Symbol *sym = nullptr;
102   std::visit(
103       Fortran::common::visitors{
104           [&](const Fortran::parser::Designator &designator) {
105             if (auto *arrayEle =
106                     Fortran::parser::Unwrap<Fortran::parser::ArrayElement>(
107                         designator)) {
108               sym = GetFirstName(arrayEle->base).symbol;
109             } else if (auto *structComp = Fortran::parser::Unwrap<
110                            Fortran::parser::StructureComponent>(designator)) {
111               sym = structComp->component.symbol;
112             } else if (const Fortran::parser::Name *name =
113                            Fortran::semantics::getDesignatorNameIfDataRef(
114                                designator)) {
115               sym = name->symbol;
116             }
117           },
118           [&](const Fortran::parser::Name &name) { sym = name.symbol; }},
119       ompObject.u);
120   return sym;
121 }
122 
123 } // namespace omp
124 } // namespace lower
125 } // namespace Fortran
126