brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.8 KiB · 406b1a5 Raw
140 lines · cpp
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 Loop Stmt node as CIR code.10//11//===----------------------------------------------------------------------===//12 13#include "CIRGenBuilder.h"14#include "CIRGenFunction.h"15 16#include "clang/AST/StmtOpenACC.h"17 18#include "mlir/Dialect/OpenACC/OpenACC.h"19 20using namespace clang;21using namespace clang::CIRGen;22using namespace cir;23using namespace mlir::acc;24 25void CIRGenFunction::updateLoopOpParallelism(mlir::acc::LoopOp &op,26                                             bool isOrphan,27                                             OpenACCDirectiveKind dk) {28  // Check that at least one of auto, independent, or seq is present29  // for the device-independent default clauses.30  if (op.hasParallelismFlag(mlir::acc::DeviceType::None))31    return;32 33  switch (dk) {34  default:35    llvm_unreachable("Invalid parent directive kind");36  case OpenACCDirectiveKind::Invalid:37  case OpenACCDirectiveKind::Parallel:38  case OpenACCDirectiveKind::ParallelLoop:39    op.addIndependent(builder.getContext(), {});40    return;41  case OpenACCDirectiveKind::Kernels:42  case OpenACCDirectiveKind::KernelsLoop:43    op.addAuto(builder.getContext(), {});44    return;45  case OpenACCDirectiveKind::Serial:46  case OpenACCDirectiveKind::SerialLoop:47    if (op.hasDefaultGangWorkerVector())48      op.addAuto(builder.getContext(), {});49    else50      op.addSeq(builder.getContext(), {});51    return;52  };53}54 55mlir::LogicalResult56CIRGenFunction::emitOpenACCLoopConstruct(const OpenACCLoopConstruct &s) {57  mlir::Location start = getLoc(s.getSourceRange().getBegin());58  mlir::Location end = getLoc(s.getSourceRange().getEnd());59  llvm::SmallVector<mlir::Type> retTy;60  llvm::SmallVector<mlir::Value> operands;61  auto op = LoopOp::create(builder, start, retTy, operands);62 63  // TODO(OpenACC): In the future we are going to need to come up with a64  // transformation here that can teach the acc.loop how to figure out the65  // 'lowerbound', 'upperbound', and 'step'.66  //67  // -'upperbound' should fortunately be pretty easy as it should be68  // in the initialization section of the cir.for loop. In Sema, we limit to69  // just the forms 'Var = init', `Type Var = init`, or `Var = init` (where it70  // is an operator= call)`.  However, as those are all necessary to emit for71  // the init section of the for loop, they should be inside the initial72  // cir.scope.73  //74  // -'upperbound' should be somewhat easy to determine. Sema is limiting this75  // to: ==, <, >, !=,  <=, >= builtin operators, the overloaded 'comparison'76  // operations, and member-call expressions.77  //78  // For the builtin comparison operators, we can pretty well deduce based on79  // the comparison what the 'end' object is going to be, and the inclusive80  // nature of it.81  //82  // For the overloaded operators, Sema will ensure that at least one side of83  // the operator is the init variable, so we can deduce the comparison there84  // too. The standard places no real bounds on WHAT the comparison operators do85  // for a `RandomAccessIterator` however, so we'll have to just 'assume' they86  // do the right thing? Note that this might be incrementing by a different87  // 'object', not an integral, so it isn't really clear to me what we can do to88  // determine the other side.89  //90  // Member-call expressions are the difficult ones. I don't think there is91  // anything we can deduce from this to determine the 'end', so we might end up92  // having to go back to Sema and make this ill-formed.93  //94  // HOWEVER: What ACC dialect REALLY cares about is the tripcount, which you95  // cannot get (in the case of `RandomAccessIterator`) from JUST 'upperbound'96  // and 'lowerbound'. We will likely have to provide a 'recipe' equivalent to97  // `std::distance` instead.  In the case of integer/pointers, it is fairly98  // simple to find: it is just the mathematical subtraction. Howver, in the99  // case of `RandomAccessIterator`, we have to enable the use of `operator-`.100  // FORTUNATELY the standard requires this to work correctly for101  // `RandomAccessIterator`, so we don't have to implement a `std::distance`102  // that loops through, like we would for a forward/etc iterator.103  //104  // 'step': Sema is currently allowing builtin ++,--, +=, -=, *=, /=, and =105  // operators. Additionally, it allows the equivalent for the operator-call, as106  // well as member-call.107  //108  // For builtin operators, we perhaps should refine the assignment here. It109  // doesn't really help us know the 'step' count at all, but we could perhaps110  // do one more step of analysis in Sema to allow something like Var = Var + 1.111  // For the others, this should get us the step reasonably well.112  //113  // For the overloaded operators, we have the same problems as for114  // 'upperbound', plus not really knowing what they do. Member-call expressions115  // are again difficult, and we might want to reconsider allowing these in116  // Sema.117  //118 119  // Emit all clauses.120  emitOpenACCClauses(op, s.getDirectiveKind(), s.clauses());121 122  updateLoopOpParallelism(op, s.isOrphanedLoopConstruct(),123                          s.getParentComputeConstructKind());124 125  mlir::LogicalResult stmtRes = mlir::success();126  // Emit body.127  {128    mlir::Block &block = op.getRegion().emplaceBlock();129    mlir::OpBuilder::InsertionGuard guardCase(builder);130    builder.setInsertionPointToEnd(&block);131    LexicalScope ls{*this, start, builder.getInsertionBlock()};132    ActiveOpenACCLoopRAII activeLoop{*this, &op};133 134    stmtRes = emitStmt(s.getLoop(), /*useCurrentScope=*/true);135    mlir::acc::YieldOp::create(builder, end);136  }137 138  return stmtRes;139}140