brintos

brintos / llvm-project-archived public Read only

0
0
Text · 4.7 KiB · 405037f Raw
127 lines · cpp
1//===- PropagateFortranVariableAttributes.cpp -----------------------------===//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/// \file9/// This file defines a pass that propagates FortranVariableFlagsAttr10/// attributes through HLFIR. For example, it can set contiguous attribute11/// on hlfir.designate that produces a contiguous slice of a contiguous12/// Fortran array. This pass can be applied multiple times to expose13/// more Fortran attributes, e.g. after inlining and constant propagation.14//===----------------------------------------------------------------------===//15 16#include "flang/Optimizer/Builder/HLFIRTools.h"17#include "flang/Optimizer/Dialect/FIROpsSupport.h"18#include "flang/Optimizer/HLFIR/HLFIRDialect.h"19#include "flang/Optimizer/HLFIR/HLFIROps.h"20#include "flang/Optimizer/HLFIR/Passes.h"21#include "llvm/ADT/TypeSwitch.h"22 23namespace hlfir {24#define GEN_PASS_DEF_PROPAGATEFORTRANVARIABLEATTRIBUTES25#include "flang/Optimizer/HLFIR/Passes.h.inc"26} // namespace hlfir27 28#define DEBUG_TYPE "propagate-fortran-attrs"29 30namespace {31class PropagateFortranVariableAttributes32    : public hlfir::impl::PropagateFortranVariableAttributesBase<33          PropagateFortranVariableAttributes> {34public:35  using PropagateFortranVariableAttributesBase<36      PropagateFortranVariableAttributes>::37      PropagateFortranVariableAttributesBase;38  void runOnOperation() override;39};40 41class Propagator {42public:43  void process(mlir::Operation *op);44 45private:46  static bool isContiguous(mlir::Operation *op) {47    // Treat data allocations as contiguous, so that we can propagate48    // the continuity from them. Allocations of fir.box must not be treated49    // as contiguous.50    if (mlir::isa<fir::AllocaOp, fir::AllocMemOp>(op) &&51        !mlir::isa<fir::BaseBoxType>(52            fir::unwrapRefType(op->getResult(0).getType())))53      return true;54    auto varOp = mlir::dyn_cast<fir::FortranVariableOpInterface>(op);55    if (!varOp)56      return false;57    return hlfir::Entity{varOp}.isSimplyContiguous();58  }59 60  static void setContiguousAttr(fir::FortranVariableOpInterface op);61};62} // namespace63 64void Propagator::setContiguousAttr(fir::FortranVariableOpInterface op) {65  LLVM_DEBUG(llvm::dbgs() << "Setting continuity for:\n" << op << "\n");66  fir::FortranVariableFlagsEnum attrs =67      op.getFortranAttrs().value_or(fir::FortranVariableFlagsEnum::None);68  attrs = attrs | fir::FortranVariableFlagsEnum::contiguous;69  op.setFortranAttrs(attrs);70}71 72void Propagator::process(mlir::Operation *op) {73  if (!isContiguous(op))74    return;75  llvm::SmallVector<mlir::Operation *> workList{op};76  while (!workList.empty()) {77    mlir::Operation *current = workList.pop_back_val();78    LLVM_DEBUG(llvm::dbgs() << "Propagating continuity from operation:\n"79                            << *current << "\n");80 81    for (mlir::OpOperand &use : current->getUses()) {82      mlir::Operation *useOp = use.getOwner();83      if (auto varOp = mlir::dyn_cast<fir::FortranVariableOpInterface>(useOp)) {84        // If the user is not currently contiguous, set the contiguous85        // attribute and skip it. The propagation will pick it up later.86        mlir::Value memref;87        mlir::TypeSwitch<mlir::Operation *, void>(useOp)88            .Case<hlfir::DeclareOp, hlfir::DesignateOp>(89                [&](auto op) { memref = op.getMemref(); })90            .Default([&](auto op) {});91 92        if (memref == use.get() && !isContiguous(varOp)) {93          // Make additional checks for hlfir.designate.94          if (auto designateOp = mlir::dyn_cast<hlfir::DesignateOp>(useOp))95            if (!hlfir::designatePreservesContinuity(designateOp))96              continue;97 98          setContiguousAttr(varOp);99        }100        continue;101      }102      mlir::TypeSwitch<mlir::Operation *, void>(useOp)103          .Case(104              [&](fir::ConvertOp op) { workList.push_back(op.getOperation()); })105          .Case([&](fir::EmboxOp op) {106            if (op.getMemref() == use.get())107              workList.push_back(op.getOperation());108          })109          .Case([&](fir::ReboxOp op) {110            if (op.getBox() == use.get() && fir::reboxPreservesContinuity(op))111              workList.push_back(op.getOperation());112          });113    }114  }115}116 117void PropagateFortranVariableAttributes::runOnOperation() {118  mlir::Operation *rootOp = getOperation();119  mlir::MLIRContext *context = &getContext();120  mlir::RewritePatternSet patterns(context);121  Propagator propagator;122  rootOp->walk<mlir::WalkOrder::PreOrder>([&](mlir::Operation *op) {123    propagator.process(op);124    return mlir::WalkResult::advance();125  });126}127