clang 24.0.0git
CIRGenOpenACCRecipe.h
Go to the documentation of this file.
1//===----------------------------------------------------------------------===//
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// Emit OpenACC clause recipes as CIR code.
10//
11//===----------------------------------------------------------------------===//
12
13#include "CIRGenCXXABI.h"
14#include "CIRGenFunction.h"
15
17#include "clang/AST/DeclBase.h"
18#include "clang/AST/Expr.h"
19#include "clang/AST/ExprCXX.h"
21#include "clang/AST/TypeBase.h"
23
24#include "mlir/Dialect/OpenACC/OpenACC.h"
25
26namespace clang::CIRGen {
28 // makes the copy of the addresses of an alloca to the previous allocation.
29 void makeAllocaCopy(mlir::Location loc, mlir::Type copyType,
30 mlir::Value numEltsToCopy, mlir::Value offsetPerSubarray,
31 mlir::Value destAlloca, mlir::Value srcAlloca);
32 // This function generates the required alloca, similar to
33 // 'emitAutoVarAlloca', except for the OpenACC array/pointer types.
34 mlir::Value makeBoundsAlloca(mlir::Block *block, SourceRange exprRange,
35 mlir::Location loc, std::string_view allocaName,
36 size_t numBounds,
37 llvm::ArrayRef<QualType> boundTypes);
38
39 void makeBoundsInit(mlir::Value alloca, mlir::Location loc,
40 mlir::Block *block, const VarDecl *allocaDecl,
41 QualType origType, bool isInitSection);
42
43protected:
46
47 mlir::Block *createRecipeBlock(mlir::Region &region, mlir::Type opTy,
48 mlir::Location loc, size_t numBounds,
49 bool isInit);
50 // Creates a loop through an 'acc.bounds', leaving the 'insertion' point to be
51 // the inside of the loop body. Traverses LB->UB UNLESS `inverse` is set.
52 // Returns the 'subscriptedValue' changed with the new bounds subscript.
53 std::pair<mlir::Value, mlir::Value>
54 createBoundsLoop(mlir::Value subscriptedValue, mlir::Value subscriptedValue2,
55 mlir::Value bound, mlir::Location loc, bool inverse);
56
57 mlir::Value createBoundsLoop(mlir::Value subscriptedValue, mlir::Value bound,
58 mlir::Location loc, bool inverse) {
59 return createBoundsLoop(subscriptedValue, {}, bound, loc, inverse).first;
60 }
61
62 mlir::acc::ReductionOperator convertReductionOp(OpenACCReductionOperator op);
63
64 // This function generates the 'combiner' section for a reduction recipe. Note
65 // that this function is not 'insertion point' clean, in that it alters the
66 // insertion point to be inside of the 'combiner' section of the recipe, but
67 // doesn't restore it aftewards.
69 mlir::Location loc, mlir::Location locEnd, mlir::Value mainOp,
70 mlir::acc::ReductionRecipeOp recipe, size_t numBounds, QualType origType,
72
73 void createInitRecipe(mlir::Location loc, mlir::Location locEnd,
74 SourceRange exprRange, mlir::Value mainOp,
75 mlir::Region &recipeInitRegion, size_t numBounds,
76 llvm::ArrayRef<QualType> boundTypes,
77 const VarDecl *allocaDecl, QualType origType,
78 bool emitInitExpr);
79
80 void createFirstprivateRecipeCopy(mlir::Location loc, mlir::Location locEnd,
81 mlir::Value mainOp,
82 const VarDecl *allocaDecl,
83 const VarDecl *temporary,
84 mlir::Region &copyRegion, size_t numBounds);
85
86 void createRecipeDestroySection(mlir::Location loc, mlir::Location locEnd,
87 mlir::Value mainOp, CharUnits alignment,
88 QualType origType, size_t numBounds,
89 QualType baseType,
90 mlir::Region &destroyRegion);
91
95};
96
97template <typename RecipeTy>
99 std::string getRecipeName(SourceRange loc, QualType baseType,
100 unsigned numBounds,
101 OpenACCReductionOperator reductionOp) {
102 std::string recipeName;
103 {
104 llvm::raw_string_ostream stream(recipeName);
105
106 if constexpr (std::is_same_v<RecipeTy, mlir::acc::PrivateRecipeOp>) {
107 stream << "privatization_";
108 } else if constexpr (std::is_same_v<RecipeTy,
109 mlir::acc::FirstprivateRecipeOp>) {
110 stream << "firstprivatization_";
111
112 } else if constexpr (std::is_same_v<RecipeTy,
113 mlir::acc::ReductionRecipeOp>) {
114 stream << "reduction_";
115 // Values here are a little weird (for bitwise and/or is 'i' prefix, and
116 // logical ops with 'l'), but are chosen to be the same as the MLIR
117 // dialect names as well as to match the Flang versions of these.
118 switch (reductionOp) {
120 stream << "add_";
121 break;
123 stream << "mul_";
124 break;
126 stream << "max_";
127 break;
129 stream << "min_";
130 break;
132 stream << "iand_";
133 break;
135 stream << "ior_";
136 break;
138 stream << "xor_";
139 break;
141 stream << "land_";
142 break;
144 stream << "lor_";
145 break;
147 llvm_unreachable("invalid reduction operator");
148 }
149 } else {
150 static_assert(!sizeof(RecipeTy), "Unknown Recipe op kind");
151 }
152
153 // The naming convention from Flang with bounds doesn't map to C++ types
154 // very well, so we're just going to choose our own here.
155 if (numBounds)
156 stream << "_Bcnt" << numBounds << '_';
157
158 MangleContext &mc = cgf.cgm.getCXXABI().getMangleContext();
159 mc.mangleCanonicalTypeName(baseType, stream);
160 }
161 return recipeName;
162 }
163
164public:
169 ASTContext &astCtx, mlir::OpBuilder::InsertPoint &insertLocation,
170 const Expr *varRef, const VarDecl *varRecipe, const VarDecl *temporary,
171 OpenACCReductionOperator reductionOp, DeclContext *dc, QualType origType,
172 size_t numBounds, llvm::ArrayRef<QualType> boundTypes, QualType baseType,
173 mlir::Value mainOp,
175 reductionCombinerRecipes) {
176 assert(!varRecipe->getType()->isSpecificBuiltinType(
177 BuiltinType::ArraySection) &&
178 "array section shouldn't make it to recipe creation");
179
180 mlir::ModuleOp mod = builder.getBlock()
181 ->getParent()
182 ->template getParentOfType<mlir::ModuleOp>();
183
184 std::string recipeName = getRecipeName(varRef->getSourceRange(), baseType,
185 numBounds, reductionOp);
186 if (auto recipe = mod.lookupSymbol<RecipeTy>(recipeName))
187 return recipe;
188
189 mlir::Location loc = cgf.cgm.getLoc(varRef->getBeginLoc());
190 mlir::Location locEnd = cgf.cgm.getLoc(varRef->getEndLoc());
191
192 mlir::OpBuilder modBuilder(mod.getBodyRegion());
193 if (insertLocation.isSet())
194 modBuilder.restoreInsertionPoint(insertLocation);
195 RecipeTy recipe;
196
197 if constexpr (std::is_same_v<RecipeTy, mlir::acc::ReductionRecipeOp>) {
198 recipe = RecipeTy::create(modBuilder, loc, recipeName,
199 /*sym_visibility=*/nullptr, mainOp.getType(),
200 convertReductionOp(reductionOp));
201 } else {
202 recipe = RecipeTy::create(modBuilder, loc, recipeName,
203 /*sym_visibility=*/nullptr, mainOp.getType());
204 }
205 insertLocation = modBuilder.saveInsertionPoint();
206
207 if constexpr (std::is_same_v<RecipeTy, mlir::acc::PrivateRecipeOp>) {
208 createInitRecipe(loc, locEnd, varRef->getSourceRange(), mainOp,
209 recipe.getInitRegion(), numBounds, boundTypes, varRecipe,
210 origType, /*emitInitExpr=*/true);
211 } else if constexpr (std::is_same_v<RecipeTy,
212 mlir::acc::ReductionRecipeOp>) {
213 createInitRecipe(loc, locEnd, varRef->getSourceRange(), mainOp,
214 recipe.getInitRegion(), numBounds, boundTypes, varRecipe,
215 origType, /*emitInitExpr=*/true);
216 createReductionRecipeCombiner(loc, locEnd, mainOp, recipe, numBounds,
217 origType, reductionCombinerRecipes);
218 } else {
219 static_assert(std::is_same_v<RecipeTy, mlir::acc::FirstprivateRecipeOp>);
220 createInitRecipe(loc, locEnd, varRef->getSourceRange(), mainOp,
221 recipe.getInitRegion(), numBounds, boundTypes, varRecipe,
222 origType, /*emitInitExpr=*/false);
223 createFirstprivateRecipeCopy(loc, locEnd, mainOp, varRecipe, temporary,
224 recipe.getCopyRegion(), numBounds);
225 }
226
227 if (origType.isDestructedType())
229 loc, locEnd, mainOp, cgf.getContext().getDeclAlign(varRecipe),
230 origType, numBounds, baseType, recipe.getDestroyRegion());
231 return recipe;
232 }
233};
234} // namespace clang::CIRGen
Defines the clang::ASTContext interface.
Defines the clang::Expr interface and subclasses for C++ expressions.
Defines some OpenACC-specific enums and functions.
C Language Family Type Representation.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:239
void createReductionRecipeCombiner(mlir::Location loc, mlir::Location locEnd, mlir::Value mainOp, mlir::acc::ReductionRecipeOp recipe, size_t numBounds, QualType origType, llvm::ArrayRef< OpenACCReductionRecipe::CombinerRecipe > combinerRecipes)
OpenACCRecipeBuilderBase(CIRGen::CIRGenFunction &cgf, CIRGen::CIRGenBuilderTy &builder)
mlir::Value createBoundsLoop(mlir::Value subscriptedValue, mlir::Value bound, mlir::Location loc, bool inverse)
void createInitRecipe(mlir::Location loc, mlir::Location locEnd, SourceRange exprRange, mlir::Value mainOp, mlir::Region &recipeInitRegion, size_t numBounds, llvm::ArrayRef< QualType > boundTypes, const VarDecl *allocaDecl, QualType origType, bool emitInitExpr)
void createFirstprivateRecipeCopy(mlir::Location loc, mlir::Location locEnd, mlir::Value mainOp, const VarDecl *allocaDecl, const VarDecl *temporary, mlir::Region &copyRegion, size_t numBounds)
mlir::acc::ReductionOperator convertReductionOp(OpenACCReductionOperator op)
std::pair< mlir::Value, mlir::Value > createBoundsLoop(mlir::Value subscriptedValue, mlir::Value subscriptedValue2, mlir::Value bound, mlir::Location loc, bool inverse)
void createRecipeDestroySection(mlir::Location loc, mlir::Location locEnd, mlir::Value mainOp, CharUnits alignment, QualType origType, size_t numBounds, QualType baseType, mlir::Region &destroyRegion)
mlir::Block * createRecipeBlock(mlir::Region &region, mlir::Type opTy, mlir::Location loc, size_t numBounds, bool isInit)
OpenACCRecipeBuilder(CIRGen::CIRGenFunction &cgf, CIRGen::CIRGenBuilderTy &builder)
RecipeTy getOrCreateRecipe(ASTContext &astCtx, mlir::OpBuilder::InsertPoint &insertLocation, const Expr *varRef, const VarDecl *varRecipe, const VarDecl *temporary, OpenACCReductionOperator reductionOp, DeclContext *dc, QualType origType, size_t numBounds, llvm::ArrayRef< QualType > boundTypes, QualType baseType, mlir::Value mainOp, llvm::ArrayRef< OpenACCReductionRecipe::CombinerRecipe > reductionCombinerRecipes)
CharUnits - This is an opaque type for sizes expressed in character units.
Definition CharUnits.h:38
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
Definition DeclBase.h:1466
This represents one expression.
Definition Expr.h:113
MangleContext - Context for tracking state which persists across multiple calls to the C++ name mangl...
Definition Mangle.h:56
virtual void mangleCanonicalTypeName(QualType T, raw_ostream &, bool NormalizeIntegers=false)=0
Generates a unique string for an externally visible type for use with TBAA or type uniquing.
A (possibly-)qualified type.
Definition TypeBase.h:938
DestructionKind isDestructedType() const
Returns a nonzero value if objects of this type require non-trivial work to clean up after.
Definition TypeBase.h:1561
A trivial tuple used to represent a source range.
SourceLocation getEndLoc() const LLVM_READONLY
Definition Stmt.cpp:367
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition Stmt.cpp:343
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Stmt.cpp:355
bool isSpecificBuiltinType(unsigned K) const
Test for a particular builtin type.
Definition TypeBase.h:8996
QualType getType() const
Definition Decl.h:724
Represents a variable declaration or definition.
Definition Decl.h:933
OpenACCReductionOperator
@ Invalid
Invalid Reduction Clause Kind.