xref: /freebsd/contrib/llvm-project/clang/lib/CIR/CodeGen/CIRGenOpenACC.cpp (revision 700637cbb5e582861067a11aaca4d053546871d2)
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 // Generic OpenACC lowering functions not Stmt, Decl, or clause specific.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "CIRGenFunction.h"
14 #include "mlir/Dialect/Arith/IR/Arith.h"
15 #include "mlir/Dialect/OpenACC/OpenACC.h"
16 #include "clang/AST/ExprCXX.h"
17 
18 using namespace clang;
19 using namespace clang::CIRGen;
20 
21 namespace {
createBound(CIRGenFunction & cgf,CIRGen::CIRGenBuilderTy & builder,mlir::Location boundLoc,mlir::Value lowerBound,mlir::Value upperBound,mlir::Value extent)22 mlir::Value createBound(CIRGenFunction &cgf, CIRGen::CIRGenBuilderTy &builder,
23                         mlir::Location boundLoc, mlir::Value lowerBound,
24                         mlir::Value upperBound, mlir::Value extent) {
25   // Arrays always have a start-idx of 0.
26   mlir::Value startIdx = cgf.createOpenACCConstantInt(boundLoc, 64, 0);
27   // Stride is always 1 in C/C++.
28   mlir::Value stride = cgf.createOpenACCConstantInt(boundLoc, 64, 1);
29 
30   auto bound =
31       builder.create<mlir::acc::DataBoundsOp>(boundLoc, lowerBound, upperBound);
32   bound.getStartIdxMutable().assign(startIdx);
33   if (extent)
34     bound.getExtentMutable().assign(extent);
35   bound.getStrideMutable().assign(stride);
36 
37   return bound;
38 }
39 } // namespace
40 
emitOpenACCIntExpr(const Expr * intExpr)41 mlir::Value CIRGenFunction::emitOpenACCIntExpr(const Expr *intExpr) {
42   mlir::Value expr = emitScalarExpr(intExpr);
43   mlir::Location exprLoc = cgm.getLoc(intExpr->getBeginLoc());
44 
45   mlir::IntegerType targetType = mlir::IntegerType::get(
46       &getMLIRContext(), getContext().getIntWidth(intExpr->getType()),
47       intExpr->getType()->isSignedIntegerOrEnumerationType()
48           ? mlir::IntegerType::SignednessSemantics::Signed
49           : mlir::IntegerType::SignednessSemantics::Unsigned);
50 
51   auto conversionOp = builder.create<mlir::UnrealizedConversionCastOp>(
52       exprLoc, targetType, expr);
53   return conversionOp.getResult(0);
54 }
55 
createOpenACCConstantInt(mlir::Location loc,unsigned width,int64_t value)56 mlir::Value CIRGenFunction::createOpenACCConstantInt(mlir::Location loc,
57                                                      unsigned width,
58                                                      int64_t value) {
59   mlir::IntegerType ty =
60       mlir::IntegerType::get(&getMLIRContext(), width,
61                              mlir::IntegerType::SignednessSemantics::Signless);
62   auto constOp = builder.create<mlir::arith::ConstantOp>(
63       loc, builder.getIntegerAttr(ty, value));
64 
65   return constOp.getResult();
66 }
67 
68 CIRGenFunction::OpenACCDataOperandInfo
getOpenACCDataOperandInfo(const Expr * e)69 CIRGenFunction::getOpenACCDataOperandInfo(const Expr *e) {
70   const Expr *curVarExpr = e->IgnoreParenImpCasts();
71 
72   mlir::Location exprLoc = cgm.getLoc(curVarExpr->getBeginLoc());
73   llvm::SmallVector<mlir::Value> bounds;
74 
75   std::string exprString;
76   llvm::raw_string_ostream os(exprString);
77   e->printPretty(os, nullptr, getContext().getPrintingPolicy());
78 
79   while (isa<ArraySectionExpr, ArraySubscriptExpr>(curVarExpr)) {
80     mlir::Location boundLoc = cgm.getLoc(curVarExpr->getBeginLoc());
81     mlir::Value lowerBound;
82     mlir::Value upperBound;
83     mlir::Value extent;
84 
85     if (const auto *section = dyn_cast<ArraySectionExpr>(curVarExpr)) {
86       if (const Expr *lb = section->getLowerBound())
87         lowerBound = emitOpenACCIntExpr(lb);
88       else
89         lowerBound = createOpenACCConstantInt(boundLoc, 64, 0);
90 
91       if (const Expr *len = section->getLength()) {
92         extent = emitOpenACCIntExpr(len);
93       } else {
94         QualType baseTy = ArraySectionExpr::getBaseOriginalType(
95             section->getBase()->IgnoreParenImpCasts());
96         // We know this is the case as implicit lengths are only allowed for
97         // array types with a constant size, or a dependent size.  AND since
98         // we are codegen we know we're not dependent.
99         auto *arrayTy = getContext().getAsConstantArrayType(baseTy);
100         // Rather than trying to calculate the extent based on the
101         // lower-bound, we can just emit this as an upper bound.
102         upperBound = createOpenACCConstantInt(boundLoc, 64,
103                                               arrayTy->getLimitedSize() - 1);
104       }
105 
106       curVarExpr = section->getBase()->IgnoreParenImpCasts();
107     } else {
108       const auto *subscript = cast<ArraySubscriptExpr>(curVarExpr);
109 
110       lowerBound = emitOpenACCIntExpr(subscript->getIdx());
111       // Length of an array index is always 1.
112       extent = createOpenACCConstantInt(boundLoc, 64, 1);
113       curVarExpr = subscript->getBase()->IgnoreParenImpCasts();
114     }
115 
116     bounds.push_back(createBound(*this, this->builder, boundLoc, lowerBound,
117                                  upperBound, extent));
118   }
119 
120   if (const auto *memExpr = dyn_cast<MemberExpr>(curVarExpr))
121     return {exprLoc, emitMemberExpr(memExpr).getPointer(), exprString,
122             std::move(bounds)};
123 
124   // Sema has made sure that only 4 types of things can get here, array
125   // subscript, array section, member expr, or DRE to a var decl (or the
126   // former 3 wrapping a var-decl), so we should be able to assume this is
127   // right.
128   const auto *dre = cast<DeclRefExpr>(curVarExpr);
129   return {exprLoc, emitDeclRefLValue(dre).getPointer(), exprString,
130           std::move(bounds)};
131 }
132