================ @@ -0,0 +1,524 @@ +//===-- SimdOnly.cpp ------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "flang/Optimizer/Builder/FIRBuilder.h" +#include "flang/Optimizer/Transforms/Utils.h" +#include "mlir/Dialect/Arith/IR/Arith.h" +#include "mlir/Dialect/ControlFlow/IR/ControlFlowOps.h" +#include "mlir/Dialect/Func/IR/FuncOps.h" +#include "mlir/Dialect/OpenMP/OpenMPDialect.h" +#include "mlir/IR/MLIRContext.h" +#include "mlir/IR/Operation.h" +#include "mlir/IR/PatternMatch.h" +#include "mlir/Pass/Pass.h" +#include "mlir/Support/LLVM.h" +#include "mlir/Transforms/GreedyPatternRewriteDriver.h" +#include "llvm/Support/Debug.h" + +namespace flangomp { +#define GEN_PASS_DEF_SIMDONLYPASS +#include "flang/Optimizer/OpenMP/Passes.h.inc" +} // namespace flangomp + +namespace { + +#define DEBUG_TYPE "omp-simd-only-pass" + +class SimdOnlyConversionPattern : public mlir::RewritePattern { +public: + SimdOnlyConversionPattern(mlir::MLIRContext *ctx) + : mlir::RewritePattern(MatchAnyOpTypeTag{}, 1, ctx) {} + + mlir::LogicalResult + matchAndRewrite(mlir::Operation *op, + mlir::PatternRewriter &rewriter) const override { + if (op->getDialect()->getNamespace() != + mlir::omp::OpenMPDialect::getDialectNamespace()) + return rewriter.notifyMatchFailure(op, "Not an OpenMP op"); + + if (auto simdOp = mlir::dyn_cast<mlir::omp::SimdOp>(op)) { + // Remove the composite attr given that the op will no longer be composite + if (simdOp.isComposite()) { + simdOp.setComposite(false); + return mlir::success(); + } + + return rewriter.notifyMatchFailure(op, "Op is a plain SimdOp"); + } + + if (op->getParentOfType<mlir::omp::SimdOp>() && + (mlir::isa<mlir::omp::YieldOp>(op) || + mlir::isa<mlir::omp::LoopNestOp>(op) || + mlir::isa<mlir::omp::TerminatorOp>(op))) + return rewriter.notifyMatchFailure(op, "Op is part of a simd construct"); + + if (!mlir::isa<mlir::func::FuncOp>(op->getParentOp()) && + (mlir::isa<mlir::omp::TerminatorOp>(op) || + mlir::isa<mlir::omp::YieldOp>(op))) + return rewriter.notifyMatchFailure(op, + "Non top-level yield or terminator"); + + if (mlir::isa<mlir::omp::UnrollHeuristicOp>(op)) + return rewriter.notifyMatchFailure( + op, "UnrollHeuristic has special handling"); + + // SectionOp overrides its BlockArgInterface based on the parent SectionsOp. + // We need to make sure we only rewrite omp.sections once all omp.section + // ops inside it have been rewritten, otherwise the individual omp.section + // ops will not be able to access their argument values. + if (auto sectionsOp = mlir::dyn_cast<mlir::omp::SectionsOp>(op)) { + for (auto &opInSections : sectionsOp.getRegion().getOps()) + if (mlir::isa<mlir::omp::SectionOp>(opInSections)) + return rewriter.notifyMatchFailure( + op, "SectionsOp still contains individual sections"); + } + + LLVM_DEBUG(llvm::dbgs() << "SimdOnlyPass matched OpenMP op:\n"); + LLVM_DEBUG(op->dump()); + + auto eraseUnlessUsedBySimd = [&](mlir::Operation *ompOp, + mlir::StringAttr name) { + if (auto uses = + mlir::SymbolTable::getSymbolUses(name, op->getParentOp())) { + for (auto &use : *uses) + if (mlir::isa<mlir::omp::SimdOp>(use.getUser())) + return rewriter.notifyMatchFailure(op, + "Op used by a simd construct"); + } + rewriter.eraseOp(ompOp); + return mlir::success(); + }; + + if (auto ompOp = mlir::dyn_cast<mlir::omp::PrivateClauseOp>(op)) + return eraseUnlessUsedBySimd(ompOp, ompOp.getSymNameAttr()); + if (auto ompOp = mlir::dyn_cast<mlir::omp::DeclareReductionOp>(op)) + return eraseUnlessUsedBySimd(ompOp, ompOp.getSymNameAttr()); + if (auto ompOp = mlir::dyn_cast<mlir::omp::CriticalDeclareOp>(op)) + return eraseUnlessUsedBySimd(ompOp, ompOp.getSymNameAttr()); + if (auto ompOp = mlir::dyn_cast<mlir::omp::DeclareMapperOp>(op)) + return eraseUnlessUsedBySimd(ompOp, ompOp.getSymNameAttr()); + + // Erase ops that don't need any special handling + if (mlir::isa<mlir::omp::BarrierOp>(op) || + mlir::isa<mlir::omp::FlushOp>(op) || + mlir::isa<mlir::omp::TaskyieldOp>(op) || + mlir::isa<mlir::omp::MapBoundsOp>(op) || + mlir::isa<mlir::omp::TargetEnterDataOp>(op) || + mlir::isa<mlir::omp::TargetExitDataOp>(op) || + mlir::isa<mlir::omp::TargetUpdateOp>(op) || + mlir::isa<mlir::omp::OrderedOp>(op) || + mlir::isa<mlir::omp::CancelOp>(op) || + mlir::isa<mlir::omp::CancellationPointOp>(op) || + mlir::isa<mlir::omp::ScanOp>(op) || ---------------- anchuraj wrote:
Scan Op can appear if simd has scan reduction https://github.com/llvm/llvm-project/pull/150269 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits