brintos

brintos / llvm-project-archived public Read only

0
0
Text · 3.0 KiB · 74b22fa Raw
91 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#include "PassDetail.h"10#include "mlir/Dialect/Func/IR/FuncOps.h"11#include "mlir/IR/PatternMatch.h"12#include "mlir/Support/LogicalResult.h"13#include "mlir/Transforms/DialectConversion.h"14#include "mlir/Transforms/GreedyPatternRewriteDriver.h"15#include "clang/CIR/Dialect/IR/CIRDialect.h"16#include "clang/CIR/Dialect/Passes.h"17#include "clang/CIR/MissingFeatures.h"18#include "llvm/Support/TimeProfiler.h"19 20using namespace mlir;21using namespace cir;22 23namespace mlir {24#define GEN_PASS_DEF_HOISTALLOCAS25#include "clang/CIR/Dialect/Passes.h.inc"26} // namespace mlir27 28namespace {29 30struct HoistAllocasPass : public impl::HoistAllocasBase<HoistAllocasPass> {31 32  HoistAllocasPass() = default;33  void runOnOperation() override;34};35 36static void process(mlir::ModuleOp mod, cir::FuncOp func) {37  if (func.getRegion().empty())38    return;39 40  // Hoist all static allocas to the entry block.41  mlir::Block &entryBlock = func.getRegion().front();42  mlir::Operation *insertPoint = &*entryBlock.begin();43 44  // Post-order is the default, but the code below requires it, so45  // let's not depend on the default staying that way.46  func.getBody().walk<mlir::WalkOrder::PostOrder>([&](cir::AllocaOp alloca) {47    if (alloca->getBlock() == &entryBlock)48      return;49    // Don't hoist allocas with dynamic alloca size.50    if (alloca.getDynAllocSize())51      return;52 53    // Hoist allocas into the entry block.54 55    // Preserving the `const` attribute on hoisted allocas can cause LLVM to56    // incorrectly introduce invariant group metadata in some circumstances.57    // The incubator performs some analysis to determine whether the attribute58    // can be preserved, but it only runs this analysis when optimizations are59    // enabled. Until we start tracking the optimization level, we can just60    // always remove the `const` attribute.61    assert(!cir::MissingFeatures::optInfoAttr());62    if (alloca.getConstant())63      alloca.setConstant(false);64 65    alloca->moveBefore(insertPoint);66  });67}68 69void HoistAllocasPass::runOnOperation() {70  llvm::TimeTraceScope scope("Hoist Allocas");71  llvm::SmallVector<Operation *, 16> ops;72 73  Operation *op = getOperation();74  auto mod = mlir::dyn_cast<mlir::ModuleOp>(op);75  if (!mod)76    mod = op->getParentOfType<mlir::ModuleOp>();77 78  // If we ever introduce nested cir.function ops, we'll need to make this79  // walk in post-order and recurse into nested functions.80  getOperation()->walk<mlir::WalkOrder::PreOrder>([&](cir::FuncOp op) {81    process(mod, op);82    return mlir::WalkResult::skip();83  });84}85 86} // namespace87 88std::unique_ptr<Pass> mlir::createHoistAllocasPass() {89  return std::make_unique<HoistAllocasPass>();90}91