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