Skip to content

Commit 8c58b68

Browse files
committed
transform: don't merge module if patch function is already merged and available in the module
1 parent 676a3b7 commit 8c58b68

7 files changed

Lines changed: 124 additions & 74 deletions

File tree

include/patchestry/Passes/InstrumentationPass.hpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,18 @@ namespace patchestry::passes { // NOLINT
272272
* @return bool True if the function should be excluded, false otherwise
273273
*/
274274
bool exclude_from_patching(cir::FuncOp func, const PatchSpec &spec);
275+
276+
/**
277+
* @brief Sets appropriate attributes for the patch call operation.
278+
*
279+
* This method handles setting attributes on the patch call based on the
280+
* type of the original operation being instrumented. It preserves relevant
281+
* attributes from CallOp operations and adds debugging information.
282+
*
283+
* @param patch_call_op The patch call operation to set attributes on
284+
* @param target_op The original operation being instrumented
285+
*/
286+
void set_patch_call_attributes(cir::CallOp patch_call_op, mlir::Operation *target_op);
275287
};
276288

277289
} // namespace patchestry::passes

lib/patchestry/Passes/InstrumentationPass.cpp

Lines changed: 102 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)