Path: blob/main/contrib/llvm-project/clang/lib/CIR/CodeGen/CIRGenStmtOpenACCLoop.cpp
213799 views
//===----------------------------------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// Emit OpenACC Loop Stmt node as CIR code.9//10//===----------------------------------------------------------------------===//1112#include "CIRGenBuilder.h"13#include "CIRGenFunction.h"1415#include "clang/AST/StmtOpenACC.h"1617#include "mlir/Dialect/OpenACC/OpenACC.h"1819using namespace clang;20using namespace clang::CIRGen;21using namespace cir;22using namespace mlir::acc;2324void CIRGenFunction::updateLoopOpParallelism(mlir::acc::LoopOp &op,25bool isOrphan,26OpenACCDirectiveKind dk) {27// Check that at least one of auto, independent, or seq is present28// for the device-independent default clauses.29if (op.hasParallelismFlag(mlir::acc::DeviceType::None))30return;3132switch (dk) {33default:34llvm_unreachable("Invalid parent directive kind");35case OpenACCDirectiveKind::Invalid:36case OpenACCDirectiveKind::Parallel:37case OpenACCDirectiveKind::ParallelLoop:38op.addIndependent(builder.getContext(), {});39return;40case OpenACCDirectiveKind::Kernels:41case OpenACCDirectiveKind::KernelsLoop:42op.addAuto(builder.getContext(), {});43return;44case OpenACCDirectiveKind::Serial:45case OpenACCDirectiveKind::SerialLoop:46if (op.hasDefaultGangWorkerVector())47op.addAuto(builder.getContext(), {});48else49op.addSeq(builder.getContext(), {});50return;51};52}5354mlir::LogicalResult55CIRGenFunction::emitOpenACCLoopConstruct(const OpenACCLoopConstruct &s) {56mlir::Location start = getLoc(s.getSourceRange().getBegin());57mlir::Location end = getLoc(s.getSourceRange().getEnd());58llvm::SmallVector<mlir::Type> retTy;59llvm::SmallVector<mlir::Value> operands;60auto op = builder.create<LoopOp>(start, retTy, operands);6162// TODO(OpenACC): In the future we are going to need to come up with a63// transformation here that can teach the acc.loop how to figure out the64// 'lowerbound', 'upperbound', and 'step'.65//66// -'upperbound' should fortunately be pretty easy as it should be67// in the initialization section of the cir.for loop. In Sema, we limit to68// just the forms 'Var = init', `Type Var = init`, or `Var = init` (where it69// is an operator= call)`. However, as those are all necessary to emit for70// the init section of the for loop, they should be inside the initial71// cir.scope.72//73// -'upperbound' should be somewhat easy to determine. Sema is limiting this74// to: ==, <, >, !=, <=, >= builtin operators, the overloaded 'comparison'75// operations, and member-call expressions.76//77// For the builtin comparison operators, we can pretty well deduce based on78// the comparison what the 'end' object is going to be, and the inclusive79// nature of it.80//81// For the overloaded operators, Sema will ensure that at least one side of82// the operator is the init variable, so we can deduce the comparison there83// too. The standard places no real bounds on WHAT the comparison operators do84// for a `RandomAccessIterator` however, so we'll have to just 'assume' they85// do the right thing? Note that this might be incrementing by a different86// 'object', not an integral, so it isn't really clear to me what we can do to87// determine the other side.88//89// Member-call expressions are the difficult ones. I don't think there is90// anything we can deduce from this to determine the 'end', so we might end up91// having to go back to Sema and make this ill-formed.92//93// HOWEVER: What ACC dialect REALLY cares about is the tripcount, which you94// cannot get (in the case of `RandomAccessIterator`) from JUST 'upperbound'95// and 'lowerbound'. We will likely have to provide a 'recipe' equivalent to96// `std::distance` instead. In the case of integer/pointers, it is fairly97// simple to find: it is just the mathematical subtraction. Howver, in the98// case of `RandomAccessIterator`, we have to enable the use of `operator-`.99// FORTUNATELY the standard requires this to work correctly for100// `RandomAccessIterator`, so we don't have to implement a `std::distance`101// that loops through, like we would for a forward/etc iterator.102//103// 'step': Sema is currently allowing builtin ++,--, +=, -=, *=, /=, and =104// operators. Additionally, it allows the equivalent for the operator-call, as105// well as member-call.106//107// For builtin operators, we perhaps should refine the assignment here. It108// doesn't really help us know the 'step' count at all, but we could perhaps109// do one more step of analysis in Sema to allow something like Var = Var + 1.110// For the others, this should get us the step reasonably well.111//112// For the overloaded operators, we have the same problems as for113// 'upperbound', plus not really knowing what they do. Member-call expressions114// are again difficult, and we might want to reconsider allowing these in115// Sema.116//117118// Emit all clauses.119emitOpenACCClauses(op, s.getDirectiveKind(), s.getDirectiveLoc(),120s.clauses());121122updateLoopOpParallelism(op, s.isOrphanedLoopConstruct(),123s.getParentComputeConstructKind());124125mlir::LogicalResult stmtRes = mlir::success();126// Emit body.127{128mlir::Block &block = op.getRegion().emplaceBlock();129mlir::OpBuilder::InsertionGuard guardCase(builder);130builder.setInsertionPointToEnd(&block);131LexicalScope ls{*this, start, builder.getInsertionBlock()};132ActiveOpenACCLoopRAII activeLoop{*this, &op};133134stmtRes = emitStmt(s.getLoop(), /*useCurrentScope=*/true);135builder.create<mlir::acc::YieldOp>(end);136}137138return stmtRes;139}140141142