1 //===- ModuleCombiner.h - MLIR SPIR-V Module Combiner -----------*- C++ -*-===// 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 declares the entry point to the SPIR-V module combiner library. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #ifndef MLIR_DIALECT_SPIRV_LINKING_MODULECOMBINER_H_ 14 #define MLIR_DIALECT_SPIRV_LINKING_MODULECOMBINER_H_ 15 16 #include "mlir/IR/OwningOpRef.h" 17 #include "mlir/Support/LLVM.h" 18 19 namespace mlir { 20 class OpBuilder; 21 22 namespace spirv { 23 class ModuleOp; 24 25 /// The listener function to receive symbol renaming events. 26 /// 27 /// `originalModule` is the input spirv::ModuleOp that contains the renamed 28 /// symbol. `oldSymbol` and `newSymbol` are the original and renamed symbol. 29 /// Note that it's the responsibility of the caller to properly retain the 30 /// storage underlying the passed StringRefs if the listener callback outlives 31 /// this function call. 32 using SymbolRenameListener = function_ref<void( 33 spirv::ModuleOp originalModule, StringRef oldSymbol, StringRef newSymbol)>; 34 35 /// Combines a list of SPIR-V `inputModules` into one. Returns the combined 36 /// module on success; returns a null module otherwise. 37 // 38 /// \param inputModules the list of modules to combine. They won't be modified. 39 /// \param combinedMdouleBuilder an OpBuilder for building the combined module. 40 /// \param symbRenameListener a listener that gets called everytime a symbol in 41 /// one of the input modules is renamed. 42 /// 43 /// To combine multiple SPIR-V modules, we move all the module-level ops 44 /// from all the input modules into one big combined module. To that end, the 45 /// combination process proceeds in 2 phases: 46 /// 47 /// 1. resolve conflicts between pairs of ops from different modules, 48 /// 2. deduplicate equivalent ops/sub-ops in the merged module. 49 /// 50 /// For the conflict resolution phase, the following rules are employed to 51 /// resolve such conflicts: 52 /// 53 /// - If 2 spirv.func's have the same symbol name, then rename one of the 54 /// functions. 55 /// - If an spirv.func and another op have the same symbol name, then rename the 56 /// other symbol. 57 /// - If none of the 2 conflicting ops are spirv.func, then rename either. 58 /// 59 /// For deduplication, the following 3 cases are taken into consideration: 60 /// 61 /// - If 2 spirv.GlobalVariable's have either the same descriptor set + binding 62 /// or the same build_in attribute value, then replace one of them using the 63 /// other. 64 /// - If 2 spirv.SpecConstant's have the same spec_id attribute value, then 65 /// replace one of them using the other. 66 /// - Deduplicating functions are not supported right now. 67 /// 68 /// In all cases, the references to the updated symbol (whether renamed or 69 /// deduplicated) are also updated to reflect the change. 70 OwningOpRef<spirv::ModuleOp> combine(ArrayRef<spirv::ModuleOp> inputModules, 71 OpBuilder &combinedModuleBuilder, 72 SymbolRenameListener symRenameListener); 73 } // namespace spirv 74 } // namespace mlir 75 76 #endif // MLIR_DIALECT_SPIRV_LINKING_MODULECOMBINER_H_ 77