brintos

brintos / llvm-project-archived public Read only

0
0
Text · 10.1 KiB · 745d424 Raw
232 lines · c
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-exception6//7//===----------------------------------------------------------------------===//8//9// Emit OpenACC clause recipes as CIR code.10//11//===----------------------------------------------------------------------===//12 13#include "CIRGenCXXABI.h"14#include "CIRGenFunction.h"15 16#include "clang/AST/ASTContext.h"17#include "clang/AST/DeclBase.h"18#include "clang/AST/Expr.h"19#include "clang/AST/ExprCXX.h"20#include "clang/AST/TypeBase.h"21#include "clang/Basic/OpenACCKinds.h"22 23#include "mlir/Dialect/OpenACC/OpenACC.h"24 25namespace clang::CIRGen {26class OpenACCRecipeBuilderBase {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 to32  // '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:43  CIRGen::CIRGenFunction &cgf;44  CIRGen::CIRGenBuilderTy &builder;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 be50  // 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. Note64  // that this function is not 'insertion point' clean, in that it alters the65  // insertion point to be inside of the 'combiner' section of the recipe, but66  // doesn't restore it aftewards.67  void createReductionRecipeCombiner(68      mlir::Location loc, mlir::Location locEnd, mlir::Value mainOp,69      mlir::acc::ReductionRecipeOp recipe, size_t numBounds, QualType origType,70      llvm::ArrayRef<OpenACCReductionRecipe::CombinerRecipe> combinerRecipes);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 91  OpenACCRecipeBuilderBase(CIRGen::CIRGenFunction &cgf,92                           CIRGen::CIRGenBuilderTy &builder)93      : cgf(cgf), builder(builder) {}94};95 96template <typename RecipeTy>97class OpenACCRecipeBuilder : OpenACCRecipeBuilderBase {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, and115        // logical ops with 'l'), but are chosen to be the same as the MLIR116        // dialect names as well as to match the Flang versions of these.117        switch (reductionOp) {118        case OpenACCReductionOperator::Addition:119          stream << "add_";120          break;121        case OpenACCReductionOperator::Multiplication:122          stream << "mul_";123          break;124        case OpenACCReductionOperator::Max:125          stream << "max_";126          break;127        case OpenACCReductionOperator::Min:128          stream << "min_";129          break;130        case OpenACCReductionOperator::BitwiseAnd:131          stream << "iand_";132          break;133        case OpenACCReductionOperator::BitwiseOr:134          stream << "ior_";135          break;136        case OpenACCReductionOperator::BitwiseXOr:137          stream << "xor_";138          break;139        case OpenACCReductionOperator::And:140          stream << "land_";141          break;142        case OpenACCReductionOperator::Or:143          stream << "lor_";144          break;145        case OpenACCReductionOperator::Invalid: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++ types153      //  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:164  OpenACCRecipeBuilder(CIRGen::CIRGenFunction &cgf,165                       CIRGen::CIRGenBuilderTy &builder)166      : OpenACCRecipeBuilderBase(cgf, builder) {}167  RecipeTy getOrCreateRecipe(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      llvm::ArrayRef<OpenACCReductionRecipe::CombinerRecipe>174          reductionCombinerRecipes) {175    assert(!varRecipe->getType()->isSpecificBuiltinType(176               BuiltinType::ArraySection) &&177           "array section shouldn't make it to recipe creation");178 179    mlir::ModuleOp mod = builder.getBlock()180                             ->getParent()181                             ->template getParentOfType<mlir::ModuleOp>();182 183    std::string recipeName = getRecipeName(varRef->getSourceRange(), baseType,184                                           numBounds, reductionOp);185    if (auto recipe = mod.lookupSymbol<RecipeTy>(recipeName))186      return recipe;187 188    mlir::Location loc = cgf.cgm.getLoc(varRef->getBeginLoc());189    mlir::Location locEnd = cgf.cgm.getLoc(varRef->getEndLoc());190 191    mlir::OpBuilder modBuilder(mod.getBodyRegion());192    if (insertLocation.isSet())193      modBuilder.restoreInsertionPoint(insertLocation);194    RecipeTy recipe;195 196    if constexpr (std::is_same_v<RecipeTy, mlir::acc::ReductionRecipeOp>) {197      recipe = RecipeTy::create(modBuilder, loc, recipeName, mainOp.getType(),198                                convertReductionOp(reductionOp));199    } else {200      recipe = RecipeTy::create(modBuilder, loc, recipeName, mainOp.getType());201    }202    insertLocation = modBuilder.saveInsertionPoint();203 204    if constexpr (std::is_same_v<RecipeTy, mlir::acc::PrivateRecipeOp>) {205      createInitRecipe(loc, locEnd, varRef->getSourceRange(), mainOp,206                       recipe.getInitRegion(), numBounds, boundTypes, varRecipe,207                       origType, /*emitInitExpr=*/true);208    } else if constexpr (std::is_same_v<RecipeTy,209                                        mlir::acc::ReductionRecipeOp>) {210      createInitRecipe(loc, locEnd, varRef->getSourceRange(), mainOp,211                       recipe.getInitRegion(), numBounds, boundTypes, varRecipe,212                       origType, /*emitInitExpr=*/true);213      createReductionRecipeCombiner(loc, locEnd, mainOp, recipe, numBounds,214                                    origType, reductionCombinerRecipes);215    } else {216      static_assert(std::is_same_v<RecipeTy, mlir::acc::FirstprivateRecipeOp>);217      createInitRecipe(loc, locEnd, varRef->getSourceRange(), mainOp,218                       recipe.getInitRegion(), numBounds, boundTypes, varRecipe,219                       origType, /*emitInitExpr=*/false);220      createFirstprivateRecipeCopy(loc, locEnd, mainOp, varRecipe, temporary,221                                   recipe.getCopyRegion(), numBounds);222    }223 224    if (origType.isDestructedType())225      createRecipeDestroySection(226          loc, locEnd, mainOp, cgf.getContext().getDeclAlign(varRecipe),227          origType, numBounds, baseType, recipe.getDestroyRegion());228    return recipe;229  }230};231} // namespace clang::CIRGen232