Path: blob/main/contrib/llvm-project/clang/lib/CIR/Dialect/Transforms/HoistAllocas.cpp
213845 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//===----------------------------------------------------------------------===//78#include "PassDetail.h"9#include "mlir/Dialect/Func/IR/FuncOps.h"10#include "mlir/IR/PatternMatch.h"11#include "mlir/Support/LogicalResult.h"12#include "mlir/Transforms/DialectConversion.h"13#include "mlir/Transforms/GreedyPatternRewriteDriver.h"14#include "clang/CIR/Dialect/IR/CIRDialect.h"15#include "clang/CIR/Dialect/Passes.h"16#include "clang/CIR/MissingFeatures.h"17#include "llvm/Support/TimeProfiler.h"1819using namespace mlir;20using namespace cir;2122namespace {2324struct HoistAllocasPass : public HoistAllocasBase<HoistAllocasPass> {2526HoistAllocasPass() = default;27void runOnOperation() override;28};2930static void process(mlir::ModuleOp mod, cir::FuncOp func) {31if (func.getRegion().empty())32return;3334// Hoist all static allocas to the entry block.35mlir::Block &entryBlock = func.getRegion().front();36mlir::Operation *insertPoint = &*entryBlock.begin();3738// Post-order is the default, but the code below requires it, so39// let's not depend on the default staying that way.40func.getBody().walk<mlir::WalkOrder::PostOrder>([&](cir::AllocaOp alloca) {41if (alloca->getBlock() == &entryBlock)42return;43// Don't hoist allocas with dynamic alloca size.44assert(!cir::MissingFeatures::opAllocaDynAllocSize());4546// Hoist allocas into the entry block.4748// Preserving the `const` attribute on hoisted allocas can cause LLVM to49// incorrectly introduce invariant group metadata in some circumstances.50// The incubator performs some analysis to determine whether the attribute51// can be preserved, but it only runs this analysis when optimizations are52// enabled. Until we start tracking the optimization level, we can just53// always remove the `const` attribute.54assert(!cir::MissingFeatures::optInfoAttr());55if (alloca.getConstant())56alloca.setConstant(false);5758alloca->moveBefore(insertPoint);59});60}6162void HoistAllocasPass::runOnOperation() {63llvm::TimeTraceScope scope("Hoist Allocas");64llvm::SmallVector<Operation *, 16> ops;6566Operation *op = getOperation();67auto mod = mlir::dyn_cast<mlir::ModuleOp>(op);68if (!mod)69mod = op->getParentOfType<mlir::ModuleOp>();7071// If we ever introduce nested cir.function ops, we'll need to make this72// walk in post-order and recurse into nested functions.73getOperation()->walk<mlir::WalkOrder::PreOrder>([&](cir::FuncOp op) {74process(mod, op);75return mlir::WalkResult::skip();76});77}7879} // namespace8081std::unique_ptr<Pass> mlir::createHoistAllocasPass() {82return std::make_unique<HoistAllocasPass>();83}848586