#include "mlir/Dialect/Arith/IR/Arith.h" #include "mlir/Dialect/Tensor/IR/Tensor.h" #include "mlir/IR/BuiltinTypes.h" #include "llvm/ADT/SmallPtrSet.h" #include "src/Accelerators/PIM/Conversion/ONNXToSpatial/HostFoldability.hpp" #include "src/Accelerators/PIM/Dialect/Spatial/SpatialOps.hpp" #include "src/Dialect/ONNX/ONNXOps.hpp" using namespace mlir; namespace onnx_mlir { namespace { static bool hasStaticUnitStrides(tensor::ExtractSliceOp extractSliceOp) { return llvm::all_of(extractSliceOp.getStaticStrides(), [](int64_t stride) { return stride == 1; }); } static bool isStaticTensorResult(Operation* op) { return llvm::all_of(op->getResultTypes(), [](Type type) { auto shapedType = dyn_cast(type); return shapedType && shapedType.hasStaticShape(); }); } static bool isHostFoldableOpImpl(Operation* op, llvm::SmallPtrSetImpl& visited) { if (!op || !visited.insert(op).second) return false; if (isa(op)) return true; if (!isStaticTensorResult(op)) return false; if (auto transposeOp = dyn_cast(op)) return isHostFoldableValue(transposeOp.getData()); if (auto collapseShapeOp = dyn_cast(op)) return isHostFoldableValue(collapseShapeOp.getSrc()); if (auto expandShapeOp = dyn_cast(op)) return isHostFoldableValue(expandShapeOp.getSrc()); if (auto extractSliceOp = dyn_cast(op)) return hasStaticUnitStrides(extractSliceOp) && isHostFoldableValue(extractSliceOp.getSource()); if (auto extractRowsOp = dyn_cast(op)) return isHostFoldableValue(extractRowsOp.getInput()); if (auto concatOp = dyn_cast(op)) return llvm::all_of(concatOp.getInputs(), isHostFoldableValue); return false; } } // namespace bool isHostFoldableValue(Value value) { auto* definingOp = value.getDefiningOp(); if (!definingOp) return false; llvm::SmallPtrSet visited; return isHostFoldableOpImpl(definingOp, visited); } bool isHostFoldableOp(Operation* op) { llvm::SmallPtrSet visited; return isHostFoldableOpImpl(op, visited); } } // namespace onnx_mlir