@@ -814,29 +814,35 @@ namespace patchestry::passes {
814814 * @param patch_module The module containing the patch function.
815815 */
816816 void InstrumentationPass::apply_before_patch (
817- mlir::Operation *call_op , const PatchMatch &match, const PatchInfo &patch,
817+ mlir::Operation *target_op , const PatchMatch &match, const PatchInfo &patch,
818818 mlir::ModuleOp patch_module
819819 ) {
820- if (call_op == nullptr ) {
820+ if (target_op == nullptr ) {
821821 LOG (ERROR ) << " Patch before: Operation is null" ;
822822 return ;
823823 }
824824
825- mlir::OpBuilder builder (call_op );
826- builder.setInsertionPoint (call_op );
827- auto module = call_op ->getParentOfType < mlir::ModuleOp >();
825+ mlir::OpBuilder builder (target_op );
826+ builder.setInsertionPoint (target_op );
827+ auto module = target_op ->getParentOfType < mlir::ModuleOp >();
828828
829829 std::string patch_function_name = namifyPatchFunction (patch.patch_function );
830- auto input_types = llvm::to_vector (call_op ->getOperandTypes ());
830+ auto input_types = llvm::to_vector (target_op ->getOperandTypes ());
831831 if (!patch_module.lookupSymbol < cir::FuncOp >(patch_function_name)) {
832832 LOG (ERROR ) << " Patch module not found or patch function not defined\n " ;
833833 return ;
834834 }
835835
836- auto result = merge_module_symbol (module , patch_module, patch_function_name);
837- if (mlir::failed (result)) {
838- LOG (ERROR ) << " Failed to insert symbol into module\n " ;
839- return ;
836+ // check if the patch function is already in the module, if not, merge it
837+ if (!module .lookupSymbol < cir::FuncOp >(patch_function_name)) {
838+ auto result = merge_module_symbol (module , patch_module, patch_function_name);
839+ if (mlir::failed (result)) {
840+ LOG (ERROR ) << " Failed to insert symbol into module\n " ;
841+ return ;
842+ }
843+ } else {
844+ LOG (INFO ) << " Patch function " << patch_function_name
845+ << " already exists in module, skipping merge\n " ;
840846 }
841847
842848 auto patch_func = module .lookupSymbol < cir::FuncOp >(patch_function_name);
@@ -847,28 +853,19 @@ namespace patchestry::passes {
847853 }
848854
849855 auto symbol_ref =
850- mlir::FlatSymbolRefAttr::get (call_op ->getContext (), patch_function_name);
856+ mlir::FlatSymbolRefAttr::get (target_op ->getContext (), patch_function_name);
851857 llvm::SmallVector< mlir::Value > function_args;
852- prepare_call_arguments (builder, call_op , patch_func, patch, function_args);
858+ prepare_call_arguments (builder, target_op , patch_func, patch, function_args);
853859 auto patch_call_op = builder.create < cir::CallOp >(
854- call_op ->getLoc (), symbol_ref,
860+ target_op ->getLoc (), symbol_ref,
855861 patch_func->getResultTypes ().size () != 0 ? patch_func->getResultTypes ().front ()
856862 : mlir::Type (),
857863 function_args
858864 );
859865
860- // Add extra attributes for the patched call function
861- if (auto orig_call_op = mlir::dyn_cast< cir::CallOp >(call_op)) {
862- patch_call_op->setAttr (" extra_attrs" , orig_call_op.getExtraAttrs ());
863- } else {
864- mlir::NamedAttrList empty;
865- patch_call_op->setAttr (
866- " extra_attrs" ,
867- cir::ExtraFuncAttributesAttr::get (
868- call_op->getContext (), empty.getDictionary (call_op->getContext ())
869- )
870- );
871- }
866+ // Set appropriate attributes based on operation type
867+ set_patch_call_attributes (patch_call_op, target_op);
868+
872869 if (patch_options.enable_inlining ) {
873870 inline_worklists.push_back (patch_call_op);
874871 }
@@ -885,29 +882,35 @@ namespace patchestry::passes {
885882 * @param patch_module The module containing the patch function.
886883 */
887884 void InstrumentationPass::apply_after_patch (
888- mlir::Operation *call_op , const PatchMatch &match, const PatchInfo &patch,
885+ mlir::Operation *target_op , const PatchMatch &match, const PatchInfo &patch,
889886 mlir::ModuleOp patch_module
890887 ) {
891- if (call_op == nullptr ) {
888+ if (target_op == nullptr ) {
892889 LOG (ERROR ) << " Patch after: Operation is null" ;
893890 return ;
894891 }
895892
896- mlir::OpBuilder builder (call_op );
897- auto module = call_op ->getParentOfType < mlir::ModuleOp >();
898- builder.setInsertionPointAfter (call_op );
893+ mlir::OpBuilder builder (target_op );
894+ auto module = target_op ->getParentOfType < mlir::ModuleOp >();
895+ builder.setInsertionPointAfter (target_op );
899896
900897 std::string patch_function_name = namifyPatchFunction (patch.patch_function );
901- auto input_types = llvm::to_vector (call_op ->getResultTypes ());
898+ auto input_types = llvm::to_vector (target_op ->getResultTypes ());
902899 if (!patch_module.lookupSymbol < cir::FuncOp >(patch_function_name)) {
903900 LOG (ERROR ) << " Patch module not found or patch function not defined\n " ;
904901 return ;
905902 }
906903
907- auto result = merge_module_symbol (module , patch_module, patch_function_name);
908- if (mlir::failed (result)) {
909- LOG (ERROR ) << " Failed to insert symbol into module\n " ;
910- return ;
904+ // check if the patch function is already in the module, if not, merge it
905+ if (!module .lookupSymbol < cir::FuncOp >(patch_function_name)) {
906+ auto result = merge_module_symbol (module , patch_module, patch_function_name);
907+ if (mlir::failed (result)) {
908+ LOG (ERROR ) << " Failed to insert symbol into module\n " ;
909+ return ;
910+ }
911+ } else {
912+ LOG (INFO ) << " Patch function " << patch_function_name
913+ << " already exists in module, skipping merge\n " ;
911914 }
912915
913916 auto patch_func = module .lookupSymbol < cir::FuncOp >(patch_function_name);
@@ -918,28 +921,19 @@ namespace patchestry::passes {
918921 }
919922
920923 auto symbol_ref =
921- mlir::FlatSymbolRefAttr::get (call_op ->getContext (), patch_function_name);
924+ mlir::FlatSymbolRefAttr::get (target_op ->getContext (), patch_function_name);
922925 llvm::SmallVector< mlir::Value > function_args;
923- prepare_call_arguments (builder, call_op , patch_func, patch, function_args);
926+ prepare_call_arguments (builder, target_op , patch_func, patch, function_args);
924927 auto patch_call_op = builder.create < cir::CallOp >(
925- call_op ->getLoc (), symbol_ref,
928+ target_op ->getLoc (), symbol_ref,
926929 patch_func->getResultTypes ().size () != 0 ? patch_func->getResultTypes ().front ()
927930 : mlir::Type (),
928931 function_args
929932 );
930933
931- // Add extra attributes for the patched call function
932- if (auto orig_call_op = mlir::dyn_cast< cir::CallOp >(call_op)) {
933- patch_call_op->setAttr (" extra_attrs" , orig_call_op.getExtraAttrs ());
934- } else {
935- mlir::NamedAttrList empty;
936- patch_call_op->setAttr (
937- " extra_attrs" ,
938- cir::ExtraFuncAttributesAttr::get (
939- call_op->getContext (), empty.getDictionary (patch_call_op->getContext ())
940- )
941- );
942- }
934+ // Set appropriate attributes based on operation type
935+ set_patch_call_attributes (patch_call_op, target_op);
936+
943937 if (patch_options.enable_inlining ) {
944938 inline_worklists.push_back (patch_call_op);
945939 }
@@ -957,32 +951,38 @@ namespace patchestry::passes {
957951 */
958952
959953 void InstrumentationPass::replace_call (
960- cir::CallOp op , const PatchMatch &match, const PatchInfo &patch,
954+ cir::CallOp call_op , const PatchMatch &match, const PatchInfo &patch,
961955 mlir::ModuleOp patch_module
962956 ) {
963- mlir::OpBuilder builder (op );
964- auto loc = op .getLoc ();
965- auto *ctx = op ->getContext ();
966- auto module = op ->getParentOfType < mlir::ModuleOp >();
957+ mlir::OpBuilder builder (call_op );
958+ auto loc = call_op .getLoc ();
959+ auto *ctx = call_op ->getContext ();
960+ auto module = call_op ->getParentOfType < mlir::ModuleOp >();
967961 assert (module && " Wrap around patch: no module found" );
968962
969- builder.setInsertionPoint (op );
963+ builder.setInsertionPoint (call_op );
970964
971- auto callee_name = op .getCallee ()->str ();
965+ auto callee_name = call_op .getCallee ()->str ();
972966 assert (!callee_name.empty () && " Wrap around patch: callee name is empty" );
973967
974968 auto patch_function_name = namifyPatchFunction (patch.patch_function );
975- auto result_types = llvm::to_vector (op .getResultTypes ());
969+ auto result_types = llvm::to_vector (call_op .getResultTypes ());
976970
977971 if (!patch_module.lookupSymbol < cir::FuncOp >(patch_function_name)) {
978972 LOG (ERROR ) << " Patch module not found or patch function not defined\n " ;
979973 return ;
980974 }
981975
982- auto result = merge_module_symbol (module , patch_module, patch_function_name);
983- if (mlir::failed (result)) {
984- LOG (ERROR ) << " Failed to insert symbol into module\n " ;
985- return ;
976+ // check if the patch function is already in the module, if not, merge it
977+ if (!module .lookupSymbol < cir::FuncOp >(patch_function_name)) {
978+ auto result = merge_module_symbol (module , patch_module, patch_function_name);
979+ if (mlir::failed (result)) {
980+ LOG (ERROR ) << " Failed to insert symbol into module\n " ;
981+ return ;
982+ }
983+ } else {
984+ LOG (INFO ) << " Patch function " << patch_function_name
985+ << " already exists in module, skipping merge\n " ;
986986 }
987987
988988 auto wrap_func = module .lookupSymbol < cir::FuncOp >(patch_function_name);
@@ -995,14 +995,50 @@ namespace patchestry::passes {
995995 auto wrap_func_ref = mlir::FlatSymbolRefAttr::get (ctx, patch_function_name);
996996 auto wrap_call_op = builder.create < cir::CallOp >(
997997 loc, wrap_func_ref, result_types.size () != 0 ? result_types.front () : mlir::Type (),
998- op .getArgOperands ()
998+ call_op .getArgOperands ()
999999 );
1000- wrap_call_op->setAttr (" extra_attrs" , op.getExtraAttrs ());
1001- op.replaceAllUsesWith (wrap_call_op);
1002- op.erase ();
1000+
1001+ // Set appropriate attributes based on operation type
1002+ set_patch_call_attributes (wrap_call_op, call_op);
1003+
1004+ call_op.replaceAllUsesWith (wrap_call_op);
1005+ call_op.erase ();
10031006 (void ) match;
10041007 }
10051008
1009+ /* *
1010+ * @brief Sets appropriate attributes for the patch call operation.
1011+ *
1012+ * This function handles setting attributes on the patch call based on the
1013+ * type of the original operation being instrumented.
1014+ *
1015+ * @param patch_call_op The patch call operation to set attributes on
1016+ * @param target_op The original operation being instrumented
1017+ */
1018+ void InstrumentationPass::set_patch_call_attributes (
1019+ cir::CallOp patch_call_op, mlir::Operation *target_op
1020+ ) {
1021+ if (auto orig_call_op = mlir::dyn_cast< cir::CallOp >(target_op)) {
1022+ // For CallOp operations, preserve the original extra attributes
1023+ patch_call_op->setAttr (" extra_attrs" , orig_call_op.getExtraAttrs ());
1024+ } else {
1025+ // For non-CallOp operations, create empty extra attributes
1026+ mlir::NamedAttrList empty;
1027+ patch_call_op->setAttr (
1028+ " extra_attrs" ,
1029+ cir::ExtraFuncAttributesAttr::get (
1030+ target_op->getContext (), empty.getDictionary (target_op->getContext ())
1031+ )
1032+ );
1033+ }
1034+
1035+ // Add operation-specific attributes for debugging
1036+ patch_call_op->setAttr (
1037+ " patched_operation" ,
1038+ mlir::StringAttr::get (target_op->getContext (), target_op->getName ().getStringRef ())
1039+ );
1040+ }
1041+
10061042 /* *
10071043 * @brief Loads a patch module from a string representation.
10081044 *
0 commit comments