clang 22.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"
20#include "clang/AST/TypeBase.h"
22
23#include "mlir/Dialect/OpenACC/OpenACC.h"
24
25namespace clang::CIRGen {
27 // makes the copy of the addresses of an alloca to the previous allocation.
28 void makeAllocaCopy(mlir::Location loc, mlir::Type copyType,
29 mlir::Value numEltsToCopy, mlir::Value offsetPerSubarray,
30 mlir::Value destAlloca, mlir::Value srcAlloca);
31 // This function generates the required alloca, similar to
32 // 'emitAutoVarAlloca', except for the OpenACC array/pointer types.
33 mlir::Value makeBoundsAlloca(mlir::Block *block, SourceRange exprRange,
34 mlir::Location loc, std::string_view allocaName,
35 size_t numBounds,
36 llvm::ArrayRef<QualType> boundTypes);
37
38 void makeBoundsInit(mlir::Value alloca, mlir::Location loc,
39 mlir::Block *block, const VarDecl *allocaDecl,
40 QualType origType, bool isInitSection);
41
42protected:
45
46 mlir::Block *createRecipeBlock(mlir::Region &region, mlir::Type opTy,
47 mlir::Location loc, size_t numBounds,
48 bool isInit);
49 // Creates a loop through an 'acc.bounds', leaving the 'insertion' point to be
50 // the inside of the loop body. Traverses LB->UB UNLESS `inverse` is set.
51 // Returns the 'subscriptedValue' changed with the new bounds subscript.
52 std::pair<mlir::Value, mlir::Value>
53 createBoundsLoop(mlir::Value subscriptedValue, mlir::Value subscriptedValue2,
54 mlir::Value bound, mlir::Location loc, bool inverse);
55
56 mlir::Value createBoundsLoop(mlir::Value subscriptedValue, mlir::Value bound,
57 mlir::Location loc, bool inverse) {
58 return createBoundsLoop(subscriptedValue, {}, bound, loc, inverse).first;
59 }
60
61 mlir::acc::ReductionOperator convertReductionOp(OpenACCReductionOperator op);
62
63 // This function generates the 'combiner' section for a reduction recipe. Note
64 // that this function is not 'insertion point' clean, in that it alters the
65 // insertion point to be inside of the 'combiner' section of the recipe, but
66 // doesn't restore it aftewards.
67 void createReductionRecipeCombiner(mlir::Location loc, mlir::Location locEnd,
68 mlir::Value mainOp,
69 mlir::acc::ReductionRecipeOp recipe,
70 size_t numBounds);
71
72 void createInitRecipe(mlir::Location loc, mlir::Location locEnd,
73 SourceRange exprRange, mlir::Value mainOp,
74 mlir::Region &recipeInitRegion, size_t numBounds,
75 llvm::ArrayRef<QualType> boundTypes,
76 const VarDecl *allocaDecl, QualType origType,
77 bool emitInitExpr);
78
79 void createFirstprivateRecipeCopy(mlir::Location loc, mlir::Location locEnd,
80 mlir::Value mainOp,
81 const VarDecl *allocaDecl,
82 const VarDecl *temporary,
83 mlir::Region &copyRegion, size_t numBounds);
84
85 void createRecipeDestroySection(mlir::Location loc, mlir::Location locEnd,
86 mlir::Value mainOp, CharUnits alignment,
87 QualType origType, size_t numBounds,
88 QualType baseType,
89 mlir::Region &destroyRegion);
90
94};
95
96template <typename RecipeTy>
98 std::string getRecipeName(SourceRange loc, QualType baseType,
99 unsigned numBounds,
100 OpenACCReductionOperator reductionOp) {
101 std::string recipeName;
102 {
103 llvm::raw_string_ostream stream(recipeName);
104
105 if constexpr (std::is_same_v<RecipeTy, mlir::acc::PrivateRecipeOp>) {
106 stream << "privatization_";
107 } else if constexpr (std::is_same_v<RecipeTy,
108 mlir::acc::FirstprivateRecipeOp>) {
109 stream << "firstprivatization_";
110
111 } else if constexpr (std::is_same_v<RecipeTy,
112 mlir::acc::ReductionRecipeOp>) {
113 stream << "reduction_";
114 // Values here are a little weird (for bitwise and/or is 'i' prefix, and
115 // logical ops with 'l'), but are chosen to be the same as the MLIR
116 // dialect names as well as to match the Flang versions of these.
117 switch (reductionOp) {
119 stream << "add_";
120 break;
122 stream << "mul_";
123 break;
125 stream << "max_";
126 break;
128 stream << "min_";
129 break;
131 stream << "iand_";
132 break;
134 stream << "ior_";
135 break;
137 stream << "xor_";
138 break;
140 stream << "land_";
141 break;
143 stream << "lor_";
144 break;
146 llvm_unreachable("invalid reduction operator");
147 }
148 } else {
149 static_assert(!sizeof(RecipeTy), "Unknown Recipe op kind");
150 }
151
152 // The naming convention from Flang with bounds doesn't map to C++ types
153 // very well, so we're just going to choose our own here.
154 if (numBounds)
155 stream << "_Bcnt" << numBounds << '_';
156
157 MangleContext &mc = cgf.cgm.getCXXABI().getMangleContext();
158 mc.mangleCanonicalTypeName(baseType, stream);
159 }
160 return recipeName;
161 }
162
163public:
168 ASTContext &astCtx, mlir::OpBuilder::InsertPoint &insertLocation,
169 const Expr *varRef, const VarDecl *varRecipe, const VarDecl *temporary,
170 OpenACCReductionOperator reductionOp, DeclContext *dc, QualType origType,
171 size_t numBounds, llvm::ArrayRef<QualType> boundTypes, QualType baseType,
172 mlir::Value mainOp) {
173 assert(!varRecipe->getType()->isSpecificBuiltinType(
174 BuiltinType::ArraySection) &&
175 "array section shouldn't make it to recipe creation");
176
177 mlir::ModuleOp mod = builder.getBlock()
178 ->getParent()
179 ->template getParentOfType<mlir::ModuleOp>();
180
181 std::string recipeName = getRecipeName(varRef->getSourceRange(), baseType,
182 numBounds, reductionOp);
183 if (auto recipe = mod.lookupSymbol<RecipeTy>(recipeName))
184 return recipe;
185
186 mlir::Location loc = cgf.cgm.getLoc(varRef->getBeginLoc());
187 mlir::Location locEnd = cgf.cgm.getLoc(varRef->getEndLoc());
188
189 mlir::OpBuilder modBuilder(mod.getBodyRegion());
190 if (insertLocation.isSet())
191 modBuilder.restoreInsertionPoint(insertLocation);
192 RecipeTy recipe;
193
194 if constexpr (std::is_same_v<RecipeTy, mlir::acc::ReductionRecipeOp>) {
195 recipe = RecipeTy::create(modBuilder, loc, recipeName, mainOp.getType(),
196 convertReductionOp(reductionOp));
197 } else {
198 recipe = RecipeTy::create(modBuilder, loc, recipeName, mainOp.getType());
199 }
200 insertLocation = modBuilder.saveInsertionPoint();
201
202 if constexpr (std::is_same_v<RecipeTy, mlir::acc::PrivateRecipeOp>) {
203 createInitRecipe(loc, locEnd, varRef->getSourceRange(), mainOp,
204 recipe.getInitRegion(), numBounds, boundTypes, varRecipe,
205 origType, /*emitInitExpr=*/true);
206 } else if constexpr (std::is_same_v<RecipeTy,
207 mlir::acc::ReductionRecipeOp>) {
208 createInitRecipe(loc, locEnd, varRef->getSourceRange(), mainOp,
209 recipe.getInitRegion(), numBounds, boundTypes, varRecipe,
210 origType, /*emitInitExpr=*/true);
211 createReductionRecipeCombiner(loc, locEnd, mainOp, recipe, numBounds);
212 } else {
213 static_assert(std::is_same_v<RecipeTy, mlir::acc::FirstprivateRecipeOp>);
214 createInitRecipe(loc, locEnd, varRef->getSourceRange(), mainOp,
215 recipe.getInitRegion(), numBounds, boundTypes, varRecipe,
216 origType, /*emitInitExpr=*/false);
217 createFirstprivateRecipeCopy(loc, locEnd, mainOp, varRecipe, temporary,
218 recipe.getCopyRegion(), numBounds);
219 }
220
221 if (origType.isDestructedType())
223 loc, locEnd, mainOp, cgf.getContext().getDeclAlign(varRecipe),
224 origType, numBounds, baseType, recipe.getDestroyRegion());
225 return recipe;
226 }
227};
228} // 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:220
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)
void createReductionRecipeCombiner(mlir::Location loc, mlir::Location locEnd, mlir::Value mainOp, mlir::acc::ReductionRecipeOp recipe, size_t numBounds)
mlir::Block * createRecipeBlock(mlir::Region &region, mlir::Type opTy, mlir::Location loc, size_t numBounds, bool isInit)
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)
OpenACCRecipeBuilder(CIRGen::CIRGenFunction &cgf, CIRGen::CIRGenBuilderTy &builder)
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:1449
This represents one expression.
Definition Expr.h:112
MangleContext - Context for tracking state which persists across multiple calls to the C++ name mangl...
Definition Mangle.h:52
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:937
DestructionKind isDestructedType() const
Returns a nonzero value if objects of this type require non-trivial work to clean up after.
Definition TypeBase.h:1545
A trivial tuple used to represent a source range.
SourceLocation getEndLoc() const LLVM_READONLY
Definition Stmt.cpp:358
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition Stmt.cpp:334
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Stmt.cpp:346
bool isSpecificBuiltinType(unsigned K) const
Test for a particular builtin type.
Definition TypeBase.h:8852
QualType getType() const
Definition Decl.h:723
Represents a variable declaration or definition.
Definition Decl.h:926
OpenACCReductionOperator
@ Invalid
Invalid Reduction Clause Kind.