177 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// This file implements MemorySlot-related interfaces for CIR dialect10// operations.11//12//===----------------------------------------------------------------------===//13 14#include "clang/CIR/Dialect/IR/CIRDialect.h"15 16using namespace mlir;17 18/// Conditions the deletion of the operation to the removal of all its uses.19static bool forwardToUsers(Operation *op,20 SmallVectorImpl<OpOperand *> &newBlockingUses) {21 for (Value result : op->getResults())22 for (OpOperand &use : result.getUses())23 newBlockingUses.push_back(&use);24 return true;25}26 27//===----------------------------------------------------------------------===//28// Interfaces for AllocaOp29//===----------------------------------------------------------------------===//30 31llvm::SmallVector<MemorySlot> cir::AllocaOp::getPromotableSlots() {32 return {MemorySlot{getResult(), getAllocaType()}};33}34 35Value cir::AllocaOp::getDefaultValue(const MemorySlot &slot,36 OpBuilder &builder) {37 return cir::ConstantOp::create(builder, getLoc(),38 cir::UndefAttr::get(slot.elemType));39}40 41void cir::AllocaOp::handleBlockArgument(const MemorySlot &slot,42 BlockArgument argument,43 OpBuilder &builder) {}44 45std::optional<PromotableAllocationOpInterface>46cir::AllocaOp::handlePromotionComplete(const MemorySlot &slot,47 Value defaultValue, OpBuilder &builder) {48 if (defaultValue && defaultValue.use_empty())49 defaultValue.getDefiningOp()->erase();50 this->erase();51 return std::nullopt;52}53 54//===----------------------------------------------------------------------===//55// Interfaces for LoadOp56//===----------------------------------------------------------------------===//57 58bool cir::LoadOp::loadsFrom(const MemorySlot &slot) {59 return getAddr() == slot.ptr;60}61 62bool cir::LoadOp::storesTo(const MemorySlot &slot) { return false; }63 64Value cir::LoadOp::getStored(const MemorySlot &slot, OpBuilder &builder,65 Value reachingDef, const DataLayout &dataLayout) {66 llvm_unreachable("getStored should not be called on LoadOp");67}68 69bool cir::LoadOp::canUsesBeRemoved(70 const MemorySlot &slot, const SmallPtrSetImpl<OpOperand *> &blockingUses,71 SmallVectorImpl<OpOperand *> &newBlockingUses,72 const DataLayout &dataLayout) {73 if (blockingUses.size() != 1)74 return false;75 Value blockingUse = (*blockingUses.begin())->get();76 return blockingUse == slot.ptr && getAddr() == slot.ptr &&77 getType() == slot.elemType;78}79 80DeletionKind cir::LoadOp::removeBlockingUses(81 const MemorySlot &slot, const SmallPtrSetImpl<OpOperand *> &blockingUses,82 OpBuilder &builder, Value reachingDefinition,83 const DataLayout &dataLayout) {84 getResult().replaceAllUsesWith(reachingDefinition);85 return DeletionKind::Delete;86}87 88//===----------------------------------------------------------------------===//89// Interfaces for StoreOp90//===----------------------------------------------------------------------===//91 92bool cir::StoreOp::loadsFrom(const MemorySlot &slot) { return false; }93 94bool cir::StoreOp::storesTo(const MemorySlot &slot) {95 return getAddr() == slot.ptr;96}97 98Value cir::StoreOp::getStored(const MemorySlot &slot, OpBuilder &builder,99 Value reachingDef, const DataLayout &dataLayout) {100 return getValue();101}102 103bool cir::StoreOp::canUsesBeRemoved(104 const MemorySlot &slot, const SmallPtrSetImpl<OpOperand *> &blockingUses,105 SmallVectorImpl<OpOperand *> &newBlockingUses,106 const DataLayout &dataLayout) {107 if (blockingUses.size() != 1)108 return false;109 Value blockingUse = (*blockingUses.begin())->get();110 return blockingUse == slot.ptr && getAddr() == slot.ptr &&111 getValue() != slot.ptr && slot.elemType == getValue().getType();112}113 114DeletionKind cir::StoreOp::removeBlockingUses(115 const MemorySlot &slot, const SmallPtrSetImpl<OpOperand *> &blockingUses,116 OpBuilder &builder, Value reachingDefinition,117 const DataLayout &dataLayout) {118 return DeletionKind::Delete;119}120 121//===----------------------------------------------------------------------===//122// Interfaces for CopyOp123//===----------------------------------------------------------------------===//124 125bool cir::CopyOp::loadsFrom(const MemorySlot &slot) {126 return getSrc() == slot.ptr;127}128 129bool cir::CopyOp::storesTo(const MemorySlot &slot) {130 return getDst() == slot.ptr;131}132 133Value cir::CopyOp::getStored(const MemorySlot &slot, OpBuilder &builder,134 Value reachingDef, const DataLayout &dataLayout) {135 return cir::LoadOp::create(builder, getLoc(), slot.elemType, getSrc());136}137 138DeletionKind cir::CopyOp::removeBlockingUses(139 const MemorySlot &slot, const SmallPtrSetImpl<OpOperand *> &blockingUses,140 OpBuilder &builder, mlir::Value reachingDefinition,141 const DataLayout &dataLayout) {142 if (loadsFrom(slot))143 cir::StoreOp::create(builder, getLoc(), reachingDefinition, getDst(),144 /*isVolatile=*/false,145 /*alignment=*/mlir::IntegerAttr{},146 /*mem-order=*/cir::MemOrderAttr());147 return DeletionKind::Delete;148}149 150bool cir::CopyOp::canUsesBeRemoved(151 const MemorySlot &slot, const SmallPtrSetImpl<OpOperand *> &blockingUses,152 SmallVectorImpl<OpOperand *> &newBlockingUses,153 const DataLayout &dataLayout) {154 if (getDst() == getSrc())155 return false;156 157 return getLength(dataLayout) == dataLayout.getTypeSize(slot.elemType);158}159 160//===----------------------------------------------------------------------===//161// Interfaces for CastOp162//===----------------------------------------------------------------------===//163 164bool cir::CastOp::canUsesBeRemoved(165 const SmallPtrSetImpl<OpOperand *> &blockingUses,166 SmallVectorImpl<OpOperand *> &newBlockingUses,167 const DataLayout &dataLayout) {168 if (getKind() == cir::CastKind::bitcast)169 return forwardToUsers(*this, newBlockingUses);170 return false;171}172 173DeletionKind cir::CastOp::removeBlockingUses(174 const SmallPtrSetImpl<OpOperand *> &blockingUses, OpBuilder &builder) {175 return DeletionKind::Delete;176}177