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