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-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file implements MemorySlot-related interfaces for CIR dialect 10 // operations. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "clang/CIR/Dialect/IR/CIRDialect.h" 15 16 using namespace mlir; 17 18 /// Conditions the deletion of the operation to the removal of all its uses. 19 static 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 AllocaOp 29 //===----------------------------------------------------------------------===// 30 31 llvm::SmallVector<MemorySlot> cir::AllocaOp::getPromotableSlots() { 32 return {MemorySlot{getResult(), getAllocaType()}}; 33 } 34 35 Value cir::AllocaOp::getDefaultValue(const MemorySlot &slot, 36 OpBuilder &builder) { 37 return builder.create<cir::ConstantOp>(getLoc(), 38 cir::UndefAttr::get(slot.elemType)); 39 } 40 41 void cir::AllocaOp::handleBlockArgument(const MemorySlot &slot, 42 BlockArgument argument, 43 OpBuilder &builder) {} 44 45 std::optional<PromotableAllocationOpInterface> 46 cir::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 LoadOp 56 //===----------------------------------------------------------------------===// 57 58 bool cir::LoadOp::loadsFrom(const MemorySlot &slot) { 59 return getAddr() == slot.ptr; 60 } 61 62 bool cir::LoadOp::storesTo(const MemorySlot &slot) { return false; } 63 64 Value 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 69 bool 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 80 DeletionKind 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 StoreOp 90 //===----------------------------------------------------------------------===// 91 92 bool cir::StoreOp::loadsFrom(const MemorySlot &slot) { return false; } 93 94 bool cir::StoreOp::storesTo(const MemorySlot &slot) { 95 return getAddr() == slot.ptr; 96 } 97 98 Value cir::StoreOp::getStored(const MemorySlot &slot, OpBuilder &builder, 99 Value reachingDef, const DataLayout &dataLayout) { 100 return getValue(); 101 } 102 103 bool 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 114 DeletionKind 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 CastOp 123 //===----------------------------------------------------------------------===// 124 125 bool cir::CastOp::canUsesBeRemoved( 126 const SmallPtrSetImpl<OpOperand *> &blockingUses, 127 SmallVectorImpl<OpOperand *> &newBlockingUses, 128 const DataLayout &dataLayout) { 129 if (getKind() == cir::CastKind::bitcast) 130 return forwardToUsers(*this, newBlockingUses); 131 return false; 132 } 133 134 DeletionKind cir::CastOp::removeBlockingUses( 135 const SmallPtrSetImpl<OpOperand *> &blockingUses, OpBuilder &builder) { 136 return DeletionKind::Delete; 137 } 138