diff --git a/mlir/lib/Transforms/lab4/kruglov_alexey/CMakeLists.txt b/mlir/lib/Transforms/lab4/kruglov_alexey/CMakeLists.txt new file mode 100644 index 0000000000000..4124a23fd8ae0 --- /dev/null +++ b/mlir/lib/Transforms/lab4/kruglov_alexey/CMakeLists.txt @@ -0,0 +1,21 @@ +set(PluginName KruglovFunctionCallCntPass) + +file(GLOB_RECURSE ALL_SOURCE_FILES *.cpp *.h) +add_llvm_pass_plugin(${PluginName} + ${ALL_SOURCE_FILES} + DEPENDS + intrinsics_gen + MLIRBuiltinLocationAttributesIncGen + MLIROpAsmInterfaceIncGen + MLIRBuiltinTypeInterfacesIncGen + MLIRBytecodeOpInterfaceIncGen + MLIRRegionKindInterfaceIncGen + MLIRSymbolInterfacesIncGen + MLIRSideEffectInterfacesIncGen + MLIRCallInterfacesIncGen + MLIRControlFlowInterfacesIncGen + MLIRInferTypeOpInterfaceIncGen + BUILDTREE_ONLY + ) + +set(MLIR_TEST_DEPENDS ${PluginName} ${MLIR_TEST_DEPENDS} PARENT_SCOPE) diff --git a/mlir/lib/Transforms/lab4/kruglov_alexey/FunctionCallCntrPass.cpp b/mlir/lib/Transforms/lab4/kruglov_alexey/FunctionCallCntrPass.cpp new file mode 100644 index 0000000000000..bf4e3ac34a5f0 --- /dev/null +++ b/mlir/lib/Transforms/lab4/kruglov_alexey/FunctionCallCntrPass.cpp @@ -0,0 +1,47 @@ +#include "mlir/Dialect/LLVMIR/LLVMDialect.h" +#include "mlir/Pass/Pass.h" +#include "mlir/Tools/Plugins/PassPlugin.h" + +using namespace mlir; + +namespace { +class CallCounterPass + : public PassWrapper> { +public: + StringRef getArgument() const final { return "KruglovFunctionCallCntPass"; } + StringRef getDescription() const final { + return "Counts the number of calls to each function in the module"; + } + + void runOnOperation() override { + llvm::DenseMap callCounter; + + getOperation()->walk([&](LLVM::CallOp callOp) { + if (auto callee = callOp.getCallee()) { + callCounter[callee.value()]++; + } + }); + + getOperation()->walk([&](LLVM::LLVMFuncOp funcOp) { + StringRef funcName = funcOp.getName(); + int callCount = callCounter.lookup(funcName); + funcOp->setAttr( + "CallCount", + IntegerAttr::get(IntegerType::get(funcOp.getContext(), 32), + callCount)); + }); + } +}; +} // namespace + +MLIR_DECLARE_EXPLICIT_TYPE_ID(CallCounterPass) +MLIR_DEFINE_EXPLICIT_TYPE_ID(CallCounterPass) + +PassPluginLibraryInfo getCallCounterPassPluginInfo() { + return {MLIR_PLUGIN_API_VERSION, "KruglovFunctionCallCntPass", + LLVM_VERSION_STRING, []() { PassRegistration(); }}; +} + +extern "C" LLVM_ATTRIBUTE_WEAK PassPluginLibraryInfo mlirGetPassPluginInfo() { + return getCallCounterPassPluginInfo(); +} diff --git a/mlir/test/Transforms/lab4/kruglov_alexey/tests.mlir b/mlir/test/Transforms/lab4/kruglov_alexey/tests.mlir new file mode 100644 index 0000000000000..3501479317e7d --- /dev/null +++ b/mlir/test/Transforms/lab4/kruglov_alexey/tests.mlir @@ -0,0 +1,56 @@ +// RUN: mlir-opt -load-pass-plugin=%mlir_lib_dir/KruglovFunctionCallCntPass%shlibext --pass-pipeline="builtin.module(KruglovFunctionCallCntPass)" %s | FileCheck %s + +module attributes {dlti.dl_spec = #dlti.dl_spec<#dlti.dl_entry, dense<32> : vector<4xi32>>, #dlti.dl_entry, dense<64> : vector<4xi32>>, #dlti.dl_entry, dense<32> : vector<4xi32>>, #dlti.dl_entry : vector<2xi32>>, #dlti.dl_entry : vector<2xi32>>, #dlti.dl_entry : vector<2xi32>>, #dlti.dl_entry : vector<2xi32>>, #dlti.dl_entry : vector<2xi32>>, #dlti.dl_entry : vector<4xi32>>, #dlti.dl_entry : vector<2xi32>>, #dlti.dl_entry : vector<2xi32>>, #dlti.dl_entry : vector<2xi32>>, #dlti.dl_entry : vector<2xi32>>, #dlti.dl_entry<"dlti.stack_alignment", 128 : i32>, #dlti.dl_entry<"dlti.endianness", "little">>} { + llvm.func @_Z5func1v() -> (i32 {llvm.noundef}) attributes {passthrough = ["mustprogress", "noinline", "nounwind", "optnone", ["uwtable", "2"], ["frame-pointer", "all"], ["min-legal-vector-width", "0"], ["no-trapping-math", "true"], ["stack-protector-buffer-size", "8"], ["target-cpu", "x86-64"], ["target-features", "+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87"], ["tune-cpu", "generic"]]} { + // CHECK: llvm.func @_Z5func1v() {{.*}}attributes + // CHECK-SAME: {{.*}}CallCount = 5 : i32 + %0 = llvm.mlir.constant(1 : i32) : i32 + %1 = llvm.mlir.constant(2 : i32) : i32 + %2 = llvm.alloca %0 x i32 {alignment = 4 : i64} : (i32) -> !llvm.ptr + llvm.store %1, %2 {alignment = 4 : i64} : i32, !llvm.ptr + %3 = llvm.load %2 {alignment = 4 : i64} : !llvm.ptr -> i32 + %4 = llvm.add %3, %1 : i32 + llvm.return %4 : i32 + } + llvm.func @_Z5func2v() -> (i32 {llvm.noundef}) attributes {passthrough = ["mustprogress", "noinline", "nounwind", "optnone", ["uwtable", "2"], ["frame-pointer", "all"], ["min-legal-vector-width", "0"], ["no-trapping-math", "true"], ["stack-protector-buffer-size", "8"], ["target-cpu", "x86-64"], ["target-features", "+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87"], ["tune-cpu", "generic"]]} { + // CHECK: llvm.func @_Z5func2v() {{.*}}attributes + // CHECK-SAME: {{.*}}CallCount = 2 : i32 + %0 = llvm.call @_Z5func1v() : () -> i32 + %1 = llvm.call @_Z5func1v() : () -> i32 + %2 = llvm.add %0, %1 : i32 + llvm.return %2 : i32 + } + llvm.func @_Z5func3v() attributes {passthrough = ["mustprogress", "noinline", "nounwind", "optnone", ["uwtable", "2"], ["frame-pointer", "all"], ["min-legal-vector-width", "0"], ["no-trapping-math", "true"], ["stack-protector-buffer-size", "8"], ["target-cpu", "x86-64"], ["target-features", "+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87"], ["tune-cpu", "generic"]]} { + // CHECK: llvm.func @_Z5func3v() {{.*}}attributes + // CHECK-SAME: {{.*}}CallCount = 0 : i32 + %0 = llvm.mlir.constant(1 : i32) : i32 + %1 = llvm.alloca %0 x i32 {alignment = 4 : i64} : (i32) -> !llvm.ptr + %2 = llvm.call @_Z5func1v() : () -> i32 + %3 = llvm.call @_Z5func2v() : () -> i32 + %4 = llvm.add %2, %3 : i32 + llvm.store %4, %1 {alignment = 4 : i64} : i32, !llvm.ptr + llvm.return + } + llvm.func @main() -> (i32 {llvm.noundef}) attributes {passthrough = ["mustprogress", "noinline", "norecurse", "nounwind", "optnone", ["uwtable", "2"], ["frame-pointer", "all"], ["min-legal-vector-width", "0"], ["no-trapping-math", "true"], ["stack-protector-buffer-size", "8"], ["target-cpu", "x86-64"], ["target-features", "+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87"], ["tune-cpu", "generic"]]} { + // CHECK: llvm.func @main() {{.*}}attributes + // CHECK-SAME: {{.*}}CallCount = 0 : i32 + %0 = llvm.mlir.constant(1 : i32) : i32 + %1 = llvm.mlir.constant(0 : i32) : i32 + %2 = llvm.alloca %0 x i32 {alignment = 4 : i64} : (i32) -> !llvm.ptr + %3 = llvm.alloca %0 x i32 {alignment = 4 : i64} : (i32) -> !llvm.ptr + %4 = llvm.alloca %0 x i32 {alignment = 4 : i64} : (i32) -> !llvm.ptr + %5 = llvm.alloca %0 x i32 {alignment = 4 : i64} : (i32) -> !llvm.ptr + llvm.store %1, %2 {alignment = 4 : i64} : i32, !llvm.ptr + %6 = llvm.call @_Z5func1v() : () -> i32 + llvm.store %6, %3 {alignment = 4 : i64} : i32, !llvm.ptr + %7 = llvm.call @_Z5func2v() : () -> i32 + llvm.store %7, %4 {alignment = 4 : i64} : i32, !llvm.ptr + %8 = llvm.call @_Z5func1v() : () -> i32 + %9 = llvm.load %3 {alignment = 4 : i64} : !llvm.ptr -> i32 + %10 = llvm.add %8, %9 : i32 + %11 = llvm.load %4 {alignment = 4 : i64} : !llvm.ptr -> i32 + %12 = llvm.add %10, %11 : i32 + llvm.store %12, %5 {alignment = 4 : i64} : i32, !llvm.ptr + llvm.return %1 : i32 + } +}