From 55ecc96184f3b26cd99c690ed6ae17ce71e41aab Mon Sep 17 00:00:00 2001 From: Yashwant Singh Date: Thu, 25 Apr 2024 17:47:18 +0530 Subject: [PATCH 01/27] Add basic infra required to move Numba to NewPassManager Add separate classes and API endpoints for new pass manager and gradually plan on retiring/deleting legacy pass manger code. This can be treated as a self contained starter patch to move Numba to NewPassManager. In following patches things like hooks for all other passes, refprune pass, more tests, TODOs and FIXMEs can be taken care of. --- docs/source/user-guide/examples/npm-usage.py | 258 +++++++++++++++ docs/source/user-guide/examples/sum.py | 1 - ffi/CMakeLists.txt | 2 +- ffi/Makefile.linux | 4 +- ffi/newpassmanagers.cpp | 321 +++++++++++++++++++ llvmlite/binding/__init__.py | 1 + llvmlite/binding/ffi.py | 4 + llvmlite/binding/newpassmangers.py | 254 +++++++++++++++ llvmlite/tests/test_binding.py | 118 +++++++ 9 files changed, 959 insertions(+), 4 deletions(-) create mode 100644 docs/source/user-guide/examples/npm-usage.py create mode 100644 ffi/newpassmanagers.cpp create mode 100644 llvmlite/binding/newpassmangers.py diff --git a/docs/source/user-guide/examples/npm-usage.py b/docs/source/user-guide/examples/npm-usage.py new file mode 100644 index 000000000..51a6d673b --- /dev/null +++ b/docs/source/user-guide/examples/npm-usage.py @@ -0,0 +1,258 @@ +try: + import faulthandler; faulthandler.enable() +except ImportError: + pass + +import llvmlite.ir as ll +import llvmlite.binding as llvm + + +llvm.initialize() +llvm.initialize_native_target() +llvm.initialize_native_asmprinter() + + +fnty = ll.FunctionType(ll.IntType(32), [ll.IntType(32).as_pointer(), + ll.IntType(32)]) +module = ll.Module() +func = ll.Function(module, fnty, name="sum") +bb_entry = func.append_basic_block() +bb_loop = func.append_basic_block() +bb_exit = func.append_basic_block() +builder = ll.IRBuilder() +builder.position_at_end(bb_entry) +builder.branch(bb_loop) +builder.position_at_end(bb_loop) +index = builder.phi(ll.IntType(32)) +index.add_incoming(ll.Constant(index.type, 0), bb_entry) +accum = builder.phi(ll.IntType(32)) +accum.add_incoming(ll.Constant(accum.type, 0), bb_entry) +ptr = builder.gep(func.args[0], [index]) +value = builder.load(ptr) +added = builder.add(accum, ll.Constant(index.type, 0)) +accum.add_incoming(added, bb_loop) +indexp1 = builder.add(index, ll.Constant(index.type, 1)) +index.add_incoming(indexp1, bb_loop) +cond = builder.icmp_unsigned('<', indexp1, func.args[1]) +builder.cbranch(cond, bb_loop, bb_exit) +builder.position_at_end(bb_exit) +builder.ret(added) +strmod = str(module) + +strmod2 = """ +; RUN: opt -simplifycfg -S --preserve-ll-uselistorder %s | FileCheck %s +; REQUIRES: x86-registered-target +; CHECK-LABEL: @n +; CHECK: uselistorder i16 0, { 3, 2, 4, 1, 5, 0, 6 } +; Note: test was added in an effort to ensure determinism when updating memoryssa. See PR42574. +; If the uselistorder check becomes no longer relevant, the test can be disabled or removed. +%rec9 = type { i16, i32, i32 } +@a = global [1 x [1 x %rec9]] zeroinitializer +define i16 @n() { + br label %..split_crit_edge +..split_crit_edge: ; preds = %0 + br label %.split +bb4.us4: ; preds = %bb2.split.us32, %bb6.us28 + %i.4.01.us5 = phi i16 [ %_tmp49.us30, %bb6.us28 ] + br label %g.exit4.us21 +bb1.i.us14: ; preds = %bb4.us4 + br label %g.exit4.us21 +g.exit4.us21: ; preds = %bb1.i.us14, %g.exit4.critedge.us9 + %i.4.02.us22 = phi i16 [ %i.4.01.us5, %bb4.us4 ], [ %i.4.01.us5, %bb1.i.us14 ] + br label %bb6.us28 +bb5.us26: ; preds = %g.exit4.us21 + br label %bb6.us28 +bb6.us28: ; preds = %bb5.us26, %g.exit4.us21 + %i.4.03.us29 = phi i16 [ %i.4.02.us22, %bb5.us26 ], [ %i.4.02.us22, %g.exit4.us21 ] + %_tmp49.us30 = add nuw nsw i16 %i.4.03.us29, 1 + br label %bb4.us4 +bb4.us.us: ; preds = %bb2.split.us.us, %bb6.us.us + %i.4.01.us.us = phi i16 [ %_tmp49.us.us, %bb6.us.us ] + br label %bb1.i.us.us +bb1.i.us.us: ; preds = %bb4.us.us + br label %g.exit4.us.us +g.exit4.us.us: ; preds = %bb1.i.us.us, %g.exit4.critedge.us.us + %i.4.02.us.us = phi i16 [ %i.4.01.us.us, %bb1.i.us.us ] + br label %bb5.us.us +bb5.us.us: ; preds = %g.exit4.us.us + br label %bb6.us.us +bb6.us.us: ; preds = %bb5.us.us, %g.exit4.us.us + %i.4.03.us.us = phi i16 [ %i.4.02.us.us, %bb5.us.us ] + %_tmp49.us.us = add nuw nsw i16 %i.4.03.us.us, 1 + br label %bb4.us.us +.split: ; preds = %..split_crit_edge + br label %bb2 +bb2: ; preds = %.split, %bb7 + %h.3.0 = phi i16 [ undef, %.split ], [ %_tmp53, %bb7 ] + br label %bb2.bb2.split_crit_edge +bb2.bb2.split_crit_edge: ; preds = %bb2 + br label %bb2.split +bb2.split.us: ; preds = %bb2 + br label %bb4.us +bb4.us: ; preds = %bb6.us, %bb2.split.us + %i.4.01.us = phi i16 [ 0, %bb2.split.us ] + br label %bb1.i.us +g.exit4.critedge.us: ; preds = %bb4.us + br label %g.exit4.us +bb1.i.us: ; preds = %bb4.us + br label %g.exit4.us +g.exit4.us: ; preds = %bb1.i.us, %g.exit4.critedge.us + %i.4.02.us = phi i16 [ %i.4.01.us, %g.exit4.critedge.us ], [ %i.4.01.us, %bb1.i.us ] + br label %bb5.us +bb5.us: ; preds = %g.exit4.us + br label %bb7 +bb2.split: ; preds = %bb2.bb2.split_crit_edge + br label %bb4 + +bb4: ; preds = %bb2.split, %bb6 + %i.4.01 = phi i16 [ 0, %bb2.split ] + %_tmp16 = getelementptr [1 x [1 x %rec9]], [1 x [1 x %rec9]]* @a, i16 0, i16 %h.3.0, i16 %i.4.01, i32 0 + %_tmp17 = load i16, i16* %_tmp16, align 1 + br label %g.exit4.critedge + +bb1.i: ; preds = %bb4 + br label %g.exit4 + +g.exit4.critedge: ; preds = %bb4 + %_tmp28.c = getelementptr [1 x [1 x %rec9]], [1 x [1 x %rec9]]* @a, i16 0, i16 %h.3.0, i16 %i.4.01, i32 1 + %_tmp29.c = load i32, i32* %_tmp28.c, align 1 + %_tmp30.c = trunc i32 %_tmp29.c to i16 + br label %g.exit4 + +g.exit4: ; preds = %g.exit4.critedge, %bb1.i + %i.4.02 = phi i16 [ %i.4.01, %g.exit4.critedge ], [ %i.4.01, %bb1.i ] + %_tmp41 = getelementptr [1 x [1 x %rec9]], [1 x [1 x %rec9]]* @a, i16 0, i16 %h.3.0, i16 %i.4.02, i32 2 + br label %bb6 + +bb5: ; preds = %g.exit4 + br label %bb6 +bb6: ; preds = %bb5, %g.exit4 + %i.4.03 = phi i16 [ %i.4.02, %bb5 ], [ %i.4.02, %g.exit4 ] + %_tmp49 = add nuw nsw i16 %i.4.03, 1 + br label %bb7 +bb7: ; preds = %bb7.us-lcssa.us, %bb7.us-lcssa + %_tmp53 = add nsw i16 %h.3.0, 1 + br label %bb2 +} +""" + +strunroll = """ +define dso_local i32 @test(i64 %a, i64 %b, i64 %c) local_unnamed_addr { +entry: + br label %for.body + +for.cond.cleanup: ; preds = %for.body + %cmp6 = icmp eq i32 %val.2, 0 + %cond = zext i1 %cmp6 to i32 + ret i32 %cond + +for.body: ; preds = %for.body, %entry + %i.018 = phi i64 [ 0, %entry ], [ %inc, %for.body ] + %val.017 = phi i32 [ 0, %entry ], [ %val.2, %for.body ] + %a.addr.016 = phi i64 [ %a, %entry ], [ %add, %for.body ] + %b.addr.015 = phi i64 [ %b, %entry ], [ %add5, %for.body ] + %cmp1 = icmp ugt i64 %a.addr.016, %b.addr.015 + %add = add i64 %a.addr.016, %b.addr.015 + %cmp2 = icmp ugt i64 %b.addr.015, %c + %0 = or i1 %cmp2, %cmp1 + %val.2 = select i1 %0, i32 1, i32 %val.017 + %add5 = add i64 %b.addr.015, %c + %inc = add nuw nsw i64 %i.018, 1 + %exitcond = icmp eq i64 %inc, 100 + br i1 %exitcond, label %for.cond.cleanup, label %for.body, !llvm.loop !2 +} +; CHECK: [[VAL:r[0-9]+]] = w{{[0-9]+}} +; CHECK-NOT: [[VAL:r[0-9]+]] <<= 32 +; CHECK-NOT: [[VAL]] >>= 32 +; CHECK: if [[VAL]] == 0 goto + +!2 = distinct !{!2, !3} +!3 = !{!"llvm.loop.unroll.enable"} +""" + +strunroll2 = """ +define i32 @foo3(i32* noalias nocapture readonly %src) { +entry: + br label %loop.header + +loop.header: + %iv = phi i64 [ 0, %entry ], [ %inc, %loop.latch ] + %r1 = phi i32 [ 0, %entry ], [ %r3, %loop.latch ] + %arrayidx = getelementptr inbounds i32, i32* %src, i64 %iv + %src_element = load i32, i32* %arrayidx, align 4 + %cmp = icmp eq i32 0, %src_element + br i1 %cmp, label %loop.if, label %loop.latch + +loop.if: + %r2 = add i32 %r1, 1 + br label %loop.latch +loop.latch: + %r3 = phi i32 [%r1, %loop.header], [%r2, %loop.if] + %inc = add nuw nsw i64 %iv, 1 + %exitcond = icmp eq i64 %inc, 9 + br i1 %exitcond, label %loop.end, label %loop.header +loop.end: + %r.lcssa = phi i32 [ %r3, %loop.latch ] + ret i32 %r.lcssa +} +""" + +# check default pipeline + simplifycfg on module +npm2 = llvm.create_new_module_pass_manager() +llmod = llvm.parse_assembly(strmod) +print(llmod) +tm = llvm.Target.from_default_triple().create_target_machine() +pto = llvm.create_pipeline_options() +pto.opt_level = 2 # similarly more properties can be set +pb = llvm.create_pass_builder(tm, pto) +npm_o2 = pb.getNewModulePassManager() +npm_o2.run(llmod, pb) +print(llmod) + + +# npm.add_simplify_cfg_pass() +# npm.run(llmod2, pb) +# print("Simplified module 2 *******") +# print(llmod2) + + +# check default pipeline + simplifycfg on a function +llmod2 = llvm.parse_assembly(strmod2) +tm = llvm.Target.from_default_triple().create_target_machine() +pto = llvm.create_pipeline_options() +pto.opt_level = 3 # similarly more properties can be set +pb = llvm.create_pass_builder(tm, pto) +fun = llmod2.get_function("n") +print(fun) +fpm = pb.getNewFunctionPassManager() +fpm.add_simplify_cfg_pass() +fpm.run(fun, pb) +print(fun) + + +# Check loop_unrolling option in PTO +llmod_unroll = llvm.parse_assembly(strunroll2) +print(llmod_unroll) +tm = llvm.Target.from_default_triple().create_target_machine() +pto = llvm.create_pipeline_options() +pto.opt_level = 3 # similarly more properties can be set +pto.loop_unrolling = False +pb = llvm.create_pass_builder(tm, pto) +npm = pb.getNewModulePassManager() +# # Inplace optimize the IR module +npm.run(llmod_unroll, pb) +print(llmod_unroll) + + +# Check loop rotate +npm2 = llvm.create_new_module_pass_manager() +npm2.add_loop_rotate_pass() +npm2.run(llmod_unroll, pb) +print(llmod_unroll) + + +# Check instcombine +npm3 = llvm.create_new_module_pass_manager() +npm3.add_instruction_combine_pass() +npm3.run(llmod_unroll, pb) +print(llmod_unroll) diff --git a/docs/source/user-guide/examples/sum.py b/docs/source/user-guide/examples/sum.py index 4f7ddb66f..6134918b4 100644 --- a/docs/source/user-guide/examples/sum.py +++ b/docs/source/user-guide/examples/sum.py @@ -108,4 +108,3 @@ res = cfunc(A.ctypes.data_as(POINTER(c_int)), A.size) print(res, A.sum()) - diff --git a/ffi/CMakeLists.txt b/ffi/CMakeLists.txt index 907b1e1ec..d5b964bfe 100755 --- a/ffi/CMakeLists.txt +++ b/ffi/CMakeLists.txt @@ -44,7 +44,7 @@ endif() add_library(llvmlite SHARED assembly.cpp bitcode.cpp core.cpp initfini.cpp module.cpp value.cpp executionengine.cpp transforms.cpp type.cpp passmanagers.cpp targets.cpp dylib.cpp linker.cpp object_file.cpp - custom_passes.cpp orcjit.cpp memorymanager.cpp) + custom_passes.cpp orcjit.cpp memorymanager.cpp newpassmanagers.cpp) # Find the libraries that correspond to the LLVM components # that we wish to use. diff --git a/ffi/Makefile.linux b/ffi/Makefile.linux index bc80d6112..560d94de5 100644 --- a/ffi/Makefile.linux +++ b/ffi/Makefile.linux @@ -2,7 +2,7 @@ CXX ?= g++ # -flto and --exclude-libs allow us to remove those parts of LLVM we don't use -CXX_FLTO_FLAGS ?= -flto +#CXX_FLTO_FLAGS ?= -flto LD_FLTO_FLAGS ?= -flto -Wl,--exclude-libs=ALL # -fPIC is required when compiling objects for a shared library CXX_FPIC_FLAGS ?= -fPIC @@ -13,7 +13,7 @@ LIBS = $(LLVM_LIBS) INCLUDE = core.h OBJ = assembly.o bitcode.o core.o initfini.o module.o value.o \ executionengine.o transforms.o passmanagers.o targets.o type.o dylib.o \ - linker.o object_file.o custom_passes.o orcjit.o memorymanager.o + linker.o object_file.o custom_passes.o orcjit.o memorymanager.o newpassmanagers.o OUTPUT = libllvmlite.so all: $(OUTPUT) diff --git a/ffi/newpassmanagers.cpp b/ffi/newpassmanagers.cpp new file mode 100644 index 000000000..e89985a49 --- /dev/null +++ b/ffi/newpassmanagers.cpp @@ -0,0 +1,321 @@ +#include "core.h" +#include "llvm/Transforms/Scalar/SimplifyCFG.h" +#include "llvm/Analysis/AliasAnalysisEvaluator.h" +#include "llvm-c/TargetMachine.h" +#include "llvm/IR/Verifier.h" +#include "llvm/IR/PassManager.h" +#include "llvm/Passes/PassBuilder.h" +#include "llvm/Transforms/Scalar/LoopUnrollPass.h" +#include "llvm/Transforms/Scalar/LoopRotation.h" +#include "llvm/Transforms/InstCombine/InstCombine.h" +#include "llvm/Transforms/Scalar/JumpThreading.h" + +using namespace llvm; + +/* + * Exposed API + */ + +namespace llvm +{ + + +// TODO: Use DEFINE_SIMPLE_CONVERSION_FUNCTIONS llvm macro +struct OpaqueModulePassManager; +typedef OpaqueModulePassManager *LLVMModulePassManagerRef; + +static LLVMModulePassManagerRef wrap(ModulePassManager *MPM) { + return reinterpret_cast(MPM); +} + +static ModulePassManager *unwrap(LLVMModulePassManagerRef MPM) { + return reinterpret_cast(MPM); +} + +struct OpaqueFunctionPassManager; +typedef OpaqueFunctionPassManager *LLVMFunctionPassManagerRef; + +static LLVMFunctionPassManagerRef wrap(FunctionPassManager *FPM) { + return reinterpret_cast(FPM); +} + +static FunctionPassManager *unwrap(LLVMFunctionPassManagerRef FPM) { + return reinterpret_cast(FPM); +} + +struct OpaquePassBuilder; +typedef OpaquePassBuilder *LLVMPassBuilderRef; + +static LLVMPassBuilderRef wrap(PassBuilder *FPM) { + return reinterpret_cast(FPM); +} + +static PassBuilder *unwrap(LLVMPassBuilderRef FPM) { + return reinterpret_cast(FPM); +} + +struct OpaquePipelineTuningOptions; +typedef OpaquePipelineTuningOptions *LLVMPipelineTuningOptionsRef; + +static LLVMPipelineTuningOptionsRef wrap(PipelineTuningOptions *PTO) { + return reinterpret_cast(PTO); +} + +static PipelineTuningOptions *unwrap(LLVMPipelineTuningOptionsRef PTO) { + return reinterpret_cast(PTO); +} + +static TargetMachine *unwrap(LLVMTargetMachineRef P) { + return reinterpret_cast(P); +} + +} // namespace llvm + +extern "C" { + +// MPM + +API_EXPORT(LLVMModulePassManagerRef) +LLVMPY_CreateNewModulePassManager() { return llvm::wrap(new PassManager()); } + +API_EXPORT(void) +LLVMPY_NMPRun_module(LLVMModulePassManagerRef MPMRef, LLVMPassBuilderRef PBRef, LLVMModuleRef mod) { + + ModulePassManager *MPM = llvm::unwrap(MPMRef); + PassBuilder *PB = llvm::unwrap(PBRef); + Module *M = llvm::unwrap(mod); + + LoopAnalysisManager LAM; + FunctionAnalysisManager FAM; + CGSCCAnalysisManager CGAM; + ModuleAnalysisManager MAM; + PB->registerLoopAnalyses(LAM); + PB->registerFunctionAnalyses(FAM); + PB->registerCGSCCAnalyses(CGAM); + PB->registerModuleAnalyses(MAM); + PB->crossRegisterProxies(LAM, FAM, CGAM, MAM); + MPM->run(*M, MAM); +} + +API_EXPORT(void) +LLVMPY_AddVeriferPass(LLVMModulePassManagerRef MPM) { + llvm::unwrap(MPM)->addPass(VerifierPass()); +} + +API_EXPORT(void) +LLVMPY_AddAAEvalPassNMPM(LLVMModulePassManagerRef MPM) { + llvm::unwrap(MPM)->addPass(createModuleToFunctionPassAdaptor(AAEvaluator())); +} + +API_EXPORT(void) +LLVMPY_AddSimplifyCFGPass_module(LLVMModulePassManagerRef MPM) { + llvm::unwrap(MPM)->addPass(createModuleToFunctionPassAdaptor(SimplifyCFGPass())); +} + +API_EXPORT(void) +LLVMPY_AddLoopUnrollPass_module(LLVMModulePassManagerRef MPM) { + llvm::unwrap(MPM)->addPass(createModuleToFunctionPassAdaptor(LoopUnrollPass())); +} + +API_EXPORT(void) +LLVMPY_LLVMAddLoopRotatePass_module(LLVMModulePassManagerRef MPM) { + llvm::unwrap(MPM)->addPass(createModuleToFunctionPassAdaptor(createFunctionToLoopPassAdaptor(LoopRotatePass()))); +} + + +API_EXPORT(void) +LLVMPY_LLVMAddInstructionCombinePass_module(LLVMModulePassManagerRef MPM) { + llvm::unwrap(MPM)->addPass(createModuleToFunctionPassAdaptor(InstCombinePass())); +} + + +API_EXPORT(void) +LLVMPY_AddJumpThreadingPass_module(LLVMModulePassManagerRef MPM, int T) { + llvm::unwrap(MPM)->addPass(createModuleToFunctionPassAdaptor(JumpThreadingPass(T))); +} + +API_EXPORT(void) +LLVMPY_DisposeNewModulePassManger(LLVMModulePassManagerRef MPM){ + delete llvm::unwrap(MPM); +} + +// FPM + +API_EXPORT(LLVMFunctionPassManagerRef) +LLVMPY_CreateNewFunctionPassManager() { return llvm::wrap(new PassManager()); } + +API_EXPORT(void) +LLVMPY_NMPRun_function(LLVMFunctionPassManagerRef FPMRef, LLVMPassBuilderRef PBRef, LLVMValueRef FRef) { + + FunctionPassManager* FPM = llvm::unwrap(FPMRef); + PassBuilder* PB = llvm::unwrap(PBRef); + Function* F = reinterpret_cast(FRef); + + LoopAnalysisManager LAM; + FunctionAnalysisManager FAM; + CGSCCAnalysisManager CGAM; + ModuleAnalysisManager MAM; + PB->registerLoopAnalyses(LAM); + PB->registerFunctionAnalyses(FAM); + PB->registerCGSCCAnalyses(CGAM); + PB->registerModuleAnalyses(MAM); + PB->crossRegisterProxies(LAM, FAM, CGAM, MAM); + FPM->run(*F, FAM); +} + +API_EXPORT(void) +LLVMPY_AddAAEvalPassNFPM(LLVMFunctionPassManagerRef FPM) { + llvm::unwrap(FPM)->addPass(AAEvaluator()); +} + +API_EXPORT(void) +LLVMPY_AddSimplifyCFGPass_function(LLVMFunctionPassManagerRef FPM) { + llvm::unwrap(FPM)->addPass(SimplifyCFGPass()); +} + +API_EXPORT(void) +LLVMPY_AddLoopUnrollPass_Function(LLVMFunctionPassManagerRef FPM) { + llvm::unwrap(FPM)->addPass(LoopUnrollPass()); +} + +API_EXPORT(void) +LLVMPY_LLVMAddLoopRotatePass_function(LLVMFunctionPassManagerRef FPM) { + llvm::unwrap(FPM)->addPass(createFunctionToLoopPassAdaptor(LoopRotatePass())); +} + +API_EXPORT(void) +LLVMPY_LLVMAddInstructionCombinePass_function(LLVMFunctionPassManagerRef FPM) { + llvm::unwrap(FPM)->addPass(InstCombinePass()); +} + +API_EXPORT(void) +LLVMPY_AddJumpThreadingPass_function(LLVMFunctionPassManagerRef FPM, int T) { + llvm::unwrap(FPM)->addPass(JumpThreadingPass(T)); +} + +API_EXPORT(void) +LLVMPY_DisposeNewFunctionPassManger(LLVMFunctionPassManagerRef FPM){ + delete llvm::unwrap(FPM); +} + +// PTO + +API_EXPORT(LLVMPipelineTuningOptionsRef) +LLVMPY_CreatePipelineTuningOptions() { return llvm::wrap(new PipelineTuningOptions()); } + +API_EXPORT(bool) +LLVMPY_PTOGetLoopInterleaving(LLVMPipelineTuningOptionsRef PTO) { + return llvm::unwrap(PTO)->LoopInterleaving; +} + +API_EXPORT(void) +LLVMPY_PTOSetLoopInterleaving(LLVMPipelineTuningOptionsRef PTO, bool value) { + llvm::unwrap(PTO)->LoopInterleaving = value; +} + +API_EXPORT(bool) +LLVMPY_PTOGetLoopVectorization(LLVMPipelineTuningOptionsRef PTO) { + return llvm::unwrap(PTO)->LoopVectorization; +} + +API_EXPORT(void) +LLVMPY_PTOSetLoopVectorization(LLVMPipelineTuningOptionsRef PTO, bool value) { + llvm::unwrap(PTO)->LoopVectorization = value; +} + +API_EXPORT(bool) +LLVMPY_PTOGetSLPVectorization(LLVMPipelineTuningOptionsRef PTO) { + return llvm::unwrap(PTO)->SLPVectorization; +} + +API_EXPORT(void) +LLVMPY_PTOSetSLPVectorization(LLVMPipelineTuningOptionsRef PTO, bool value) { + llvm::unwrap(PTO)->SLPVectorization = value; +} + +API_EXPORT(bool) +LLVMPY_PTOGetLoopUnrolling(LLVMPipelineTuningOptionsRef PTO) { + return llvm::unwrap(PTO)->LoopUnrolling; +} + +API_EXPORT(void) +LLVMPY_PTOSetLoopUnrolling(LLVMPipelineTuningOptionsRef PTO, bool value) { + llvm::unwrap(PTO)->LoopUnrolling = value; +} + +// FIXME: Available from llvm16 +// API_EXPORT(int) +// LLVMPY_PTOGetInlinerThreshold(LLVMPipelineTuningOptionsRef PTO) { +// return llvm::unwrap(PTO)->InlinerThreshold; +// } + +// API_EXPORT(void) +// LLVMPY_PTOSetInlinerThreshold(LLVMPipelineTuningOptionsRef PTO, bool value) { +// llvm::unwrap(PTO)->InlinerThreshold = value; +// } + +API_EXPORT(void) +LLVMPY_DisposePipelineTuningOptions(LLVMPipelineTuningOptionsRef PTO){ + delete llvm::unwrap(PTO); +} + + +// PB + +API_EXPORT(LLVMPassBuilderRef) +LLVMPY_CreatePassBuilder(LLVMTargetMachineRef TM, LLVMPipelineTuningOptionsRef PTO) { + TargetMachine* target = llvm::unwrap(TM); + PipelineTuningOptions* pt = llvm::unwrap(PTO); + return llvm::wrap(new PassBuilder(target, *pt)); +} + +API_EXPORT(LLVMModulePassManagerRef) +LLVMPY_buildPerModuleDefaultPipeline(LLVMPassBuilderRef PBref, int opt_level) { + + PassBuilder* PB = llvm::unwrap(PBref); + ModulePassManager* MPM; + if(opt_level == 0){ + MPM = new ModulePassManager(PB->buildO0DefaultPipeline(OptimizationLevel::O0)); + return llvm::wrap(MPM); + } + + OptimizationLevel lvl; + if(opt_level == 1) + lvl = OptimizationLevel::O1; + else if(opt_level == 2) + lvl = OptimizationLevel::O2; + else + lvl = OptimizationLevel::O3; + + MPM = new ModulePassManager(PB->buildPerModuleDefaultPipeline(lvl)); + return llvm::wrap(MPM); +} + +API_EXPORT(LLVMFunctionPassManagerRef) +LLVMPY_buildFunctionSimplificationPipeline(LLVMPassBuilderRef PBref, int opt_level) { + + PassBuilder* PB = llvm::unwrap(PBref); + FunctionPassManager* FPM; + if(opt_level == 0){ + FPM = new FunctionPassManager(); + return llvm::wrap(FPM); + } + + OptimizationLevel lvl; + if(opt_level == 1) + lvl = OptimizationLevel::O1; + else if(opt_level == 2) + lvl = OptimizationLevel::O2; + else + lvl = OptimizationLevel::O3; + + FPM = new FunctionPassManager(PB->buildFunctionSimplificationPipeline(lvl, ThinOrFullLTOPhase::None)); + return llvm::wrap(FPM); +} + +API_EXPORT(void) +LLVMPY_DisposePassBuilder(LLVMPassBuilderRef PB){ + delete llvm::unwrap(PB); +} + +} // end extern "C" diff --git a/llvmlite/binding/__init__.py b/llvmlite/binding/__init__.py index efc234075..76f498e6f 100644 --- a/llvmlite/binding/__init__.py +++ b/llvmlite/binding/__init__.py @@ -7,6 +7,7 @@ from .linker import * from .module import * from .options import * +from .newpassmangers import * from .passmanagers import * from .targets import * from .transforms import * diff --git a/llvmlite/binding/ffi.py b/llvmlite/binding/ffi.py index d2f55f9a9..af32054b6 100644 --- a/llvmlite/binding/ffi.py +++ b/llvmlite/binding/ffi.py @@ -41,6 +41,10 @@ def _make_opaque_ref(name): LLVMOrcLLJITRef = _make_opaque_ref("LLVMOrcLLJITRef") LLVMOrcDylibTrackerRef = _make_opaque_ref("LLVMOrcDylibTrackerRef") +LLVMPipelineTuningOptionsRef = _make_opaque_ref("LLVMPipeLineTuningOptions") +LLVMModulePassManagerRef = _make_opaque_ref("LLVMModulePassManager") +LLVMFunctionPassManagerRef = _make_opaque_ref("LLVMFunctionPassManager") +LLVMPassBuilderRef = _make_opaque_ref("LLVMPassBuilder") class _LLVMLock: """A Lock to guarantee thread-safety for the LLVM C-API. diff --git a/llvmlite/binding/newpassmangers.py b/llvmlite/binding/newpassmangers.py new file mode 100644 index 000000000..8c4128745 --- /dev/null +++ b/llvmlite/binding/newpassmangers.py @@ -0,0 +1,254 @@ +from ctypes import (c_bool, c_int) +from llvmlite.binding import ffi +from llvmlite.binding.initfini import llvm_version_info + +llvm_version_major = llvm_version_info[0] + + +def create_new_module_pass_manager(): + return NewModulePassManager() + +def create_new_function_pass_manager(): + return NewFunctionPassManger() + +def create_pass_builder(tm, pto): + return PassBuilder(tm, pto) + +def create_pipeline_options(): + return PipelineTuningOptions() + +class NewModulePassManager(ffi.ObjectRef): + + def __init__(self, ptr=None): + if ptr is None: + ptr = ffi.lib.LLVMPY_CreateNewModulePassManager() + ffi.ObjectRef.__init__(self, ptr) + + def run(self, module, pb): + ffi.lib.LLVMPY_NMPRun_module(self, pb, module) + + def addVerifier(self): + ffi.lib.LLVMPY_AddVeriferPass(self) + + def add_aa_eval_pass(self): + ffi.lib.LLVMPY_AddAAEvalPassNMPM(self) + + def add_simplify_cfg_pass(self): + ffi.lib.LLVMPY_AddSimplifyCFGPass_module(self) + + def add_loop_unroll_pass(self): + ffi.lib.LLVMPY_AddLoopUnrollPass_module(self) + + def add_loop_rotate_pass(self): + ffi.lib.LLVMPY_LLVMAddLoopRotatePass_module(self) + + def add_instruction_combine_pass(self): + ffi.lib.LLVMPY_LLVMAddInstructionCombinePass_module(self) + + def add_jump_threading_pass(self, threshold=-1): + ffi.lib.LLVMPY_AddJumpThreadingPass_module(self, threshold) + + # What will happen to the pointer to objects created with run() method + def _dispose(self): + ffi.lib.LLVMPY_DisposeNewModulePassManger(self) + +class NewFunctionPassManger(ffi.ObjectRef): + + def __init__(self, ptr=None): + if ptr is None: + ptr = ffi.lib.LLVMPY_CreateNewFunctionPassManager() + ffi.ObjectRef.__init__(self, ptr) + + def add_aa_eval_pass(self): + ffi.lib.LLVMPY_AddAAEvalPassNFPM(self) + + def add_simplify_cfg_pass(self): + ffi.lib.LLVMPY_AddSimplifyCFGPass_function(self) + + def run(self, fun, pb): + ffi.lib.LLVMPY_NMPRun_function(self, pb, fun) + + def add_loop_unroll_pass(self): + ffi.lib.LLVMPY_AddLoopUnrollPass_Function(self) + + def add_loop_rotate_pass(self): + ffi.lib.LLVMPY_LLVMAddLoopRotatePass_function(self) + + def add_instruction_combine_pass(self): + ffi.lib.LLVMPY_LLVMAddInstructionCombinePass_function(self) + + def add_jump_threading_pass(self, threshold=-1): + ffi.lib.LLVMPY_AddJumpThreadingPass_function(self, threshold) + + def _dispose(self): + ffi.lib.LLVMPY_DisposeNewFunctionPassManger(self) + +# Make this nested class of PassBuilder? +class PipelineTuningOptions(ffi.ObjectRef): + + def __init__(self, ptr=None): + if ptr is None: + ptr = ffi.lib.LLVMPY_CreatePipelineTuningOptions() + self._opt_level = 3 + # self._size_level = 0 + ffi.ObjectRef.__init__(self, ptr) + + @property + def loop_interleaving(self): + return ffi.lib.LLVMPY_PTOGetLoopInterleaving(self) + + @loop_interleaving.setter + def loop_interleaving(self, value): + ffi.lib.LLVMPY_PTOSetLoopInterleaving(self, value) + + @property + def loop_vectorization(self): + return ffi.lib.LLVMPY_PTOGetLoopVectorization(self) + + @loop_vectorization.setter + def loop_vectorization(self, value): + ffi.lib.LLVMPY_PTOSetLoopVectorization(self, value) + + @property + def slp_vectorization(self): + return ffi.lib.LLVMPY_PTOGetSLPVectorization(self) + + @slp_vectorization.setter + def slp_vectorization(self, value): + ffi.lib.LLVMPY_PTOSetSLPVectorization(self, value) + + @property + def loop_unrolling(self): + return ffi.lib.LLVMPY_PTOGetLoopUnrolling(self) + + @loop_unrolling.setter + def loop_unrolling(self, value): + ffi.lib.LLVMPY_PTOSetLoopUnrolling(self, value) + + # // FIXME: Available from llvm16 + # @property + # def inlining_threshold(self): + # return ffi.lib.LLVMPY_PTOGetInlinerThreshold(self) + + # @inlining_threshold.setter + # def inlining_threshold(self, value): + # ffi.lib.LLVMPY_PTOSetInlinerThreshold(self, value) + + # Not part of PTO + @property + def opt_level(self): + """ + The general optimization level as an integer between 0 and 3. + """ + return self._opt_level + + @opt_level.setter + def opt_level(self, level): + self._opt_level = level + + # FIXME: Model optimization level combining opt level and size level similar to llvm + # @property + # def size_level(self): + # """ + # Whether and how much to optimize for size. An integer between 0 and 2. + # """ + # return self._size_level + + # @size_level.setter + # def size_level(self, size): + # self._size_level = size + + def _dispose(self): + ffi.lib.LLVMPY_DisposePipelineTuningOptions(self) + +class PassBuilder(ffi.ObjectRef): + + def __init__(self, tm, pto, ptr=None): + if ptr is None: + self._pto = pto + self._tm = tm + ptr = ffi.lib.LLVMPY_CreatePassBuilder(tm, pto) + ffi.ObjectRef.__init__(self, ptr) + + def getNewModulePassManager(self): + return NewModulePassManager( + ffi.lib.LLVMPY_buildPerModuleDefaultPipeline(self, self._pto.opt_level) + ) + + def getNewFunctionPassManager(self): + return NewFunctionPassManger( + ffi.lib.LLVMPY_buildFunctionSimplificationPipeline(self, self._pto.opt_level) + ) + + def _dispose(self): + # Should I explicitly delete pointer to pto and tm? + ffi.lib.LLVMPY_DisposePassBuilder(self) + + +# ============================================================================ +# FFI + + +ffi.lib.LLVMPY_CreateNewModulePassManager.restype = ffi.LLVMModulePassManagerRef + +ffi.lib.LLVMPY_NMPRun_module.argtypes = [ffi.LLVMModulePassManagerRef, + ffi.LLVMPassBuilderRef, + ffi.LLVMModuleRef,] + +ffi.lib.LLVMPY_AddVeriferPass.argtypes = [ffi.LLVMModulePassManagerRef,] +ffi.lib.LLVMPY_AddAAEvalPassNMPM.argtypes = [ffi.LLVMModulePassManagerRef,] +ffi.lib.LLVMPY_AddSimplifyCFGPass_module.argtypes = [ffi.LLVMModulePassManagerRef,] +ffi.lib.LLVMPY_AddLoopUnrollPass_module.argtypes = [ffi.LLVMModulePassManagerRef,] +ffi.lib.LLVMPY_LLVMAddLoopRotatePass_module.argtypes = [ffi.LLVMModulePassManagerRef,] +ffi.lib.LLVMPY_LLVMAddInstructionCombinePass_module.argtypes = [ffi.LLVMModulePassManagerRef,] +ffi.lib.LLVMPY_AddJumpThreadingPass_module.argtypes = [ffi.LLVMModulePassManagerRef,] +ffi.lib.LLVMPY_DisposeNewModulePassManger.argtypes = [ffi.LLVMModulePassManagerRef,] + +ffi.lib.LLVMPY_CreateNewFunctionPassManager.restype = ffi.LLVMFunctionPassManagerRef + +ffi.lib.LLVMPY_NMPRun_function.argtypes = [ffi.LLVMFunctionPassManagerRef, + ffi.LLVMPassBuilderRef, + ffi.LLVMValueRef,] + +ffi.lib.LLVMPY_AddAAEvalPassNFPM.argtypes = [ffi.LLVMFunctionPassManagerRef,] +ffi.lib.LLVMPY_AddSimplifyCFGPass_function.argtypes = [ffi.LLVMFunctionPassManagerRef,] +ffi.lib.LLVMPY_AddLoopUnrollPass_Function.argtypes = [ffi.LLVMFunctionPassManagerRef,] +ffi.lib.LLVMPY_LLVMAddLoopRotatePass_function.argtypes = [ffi.LLVMFunctionPassManagerRef,] +ffi.lib.LLVMPY_LLVMAddInstructionCombinePass_function.argtypes = [ffi.LLVMFunctionPassManagerRef,] +ffi.lib.LLVMPY_AddJumpThreadingPass_function.argtypes = [ffi.LLVMFunctionPassManagerRef, c_int,] +ffi.lib.LLVMPY_DisposeNewFunctionPassManger.argtypes = [ffi.LLVMFunctionPassManagerRef,] + +ffi.lib.LLVMPY_CreatePassBuilder.restype = ffi.LLVMPassBuilderRef +ffi.lib.LLVMPY_CreatePassBuilder.argtypes = [ffi.LLVMTargetMachineRef, + ffi.LLVMPipelineTuningOptionsRef,] + +ffi.lib.LLVMPY_buildPerModuleDefaultPipeline.restype = ffi.LLVMModulePassManagerRef +ffi.lib.LLVMPY_buildPerModuleDefaultPipeline.argtypes = [ffi.LLVMPassBuilderRef, c_int,] + +ffi.lib.LLVMPY_buildFunctionSimplificationPipeline.restype = ffi.LLVMFunctionPassManagerRef +ffi.lib.LLVMPY_buildFunctionSimplificationPipeline.argtypes = [ffi.LLVMPassBuilderRef, c_int,] + +ffi.lib.LLVMPY_DisposePassBuilder.argtypes = [ffi.LLVMPassBuilderRef,] + +ffi.lib.LLVMPY_CreatePipelineTuningOptions.restype = ffi.LLVMPipelineTuningOptionsRef + +ffi.lib.LLVMPY_PTOGetLoopInterleaving.restype = c_bool +ffi.lib.LLVMPY_PTOGetLoopInterleaving.argtypes = [ffi.LLVMPipelineTuningOptionsRef,] + +ffi.lib.LLVMPY_PTOSetLoopInterleaving.argtypes = [ffi.LLVMPipelineTuningOptionsRef, c_bool] + +ffi.lib.LLVMPY_PTOGetLoopVectorization.restype = c_bool +ffi.lib.LLVMPY_PTOGetLoopVectorization.argtypes = [ffi.LLVMPipelineTuningOptionsRef,] + +ffi.lib.LLVMPY_PTOSetLoopVectorization.argtypes = [ffi.LLVMPipelineTuningOptionsRef, c_bool] + +ffi.lib.LLVMPY_PTOGetSLPVectorization.restype = c_bool +ffi.lib.LLVMPY_PTOGetSLPVectorization.argtypes = [ffi.LLVMPipelineTuningOptionsRef,] + +ffi.lib.LLVMPY_PTOSetSLPVectorization.argtypes = [ffi.LLVMPipelineTuningOptionsRef, c_bool] + +ffi.lib.LLVMPY_PTOGetLoopUnrolling.restype = c_bool +ffi.lib.LLVMPY_PTOGetLoopUnrolling.argtypes = [ffi.LLVMPipelineTuningOptionsRef,] + +ffi.lib.LLVMPY_PTOSetLoopUnrolling.argtypes = [ffi.LLVMPipelineTuningOptionsRef, c_bool] +ffi.lib.LLVMPY_DisposePipelineTuningOptions.argtypes = [ffi.LLVMPipelineTuningOptionsRef,] diff --git a/llvmlite/tests/test_binding.py b/llvmlite/tests/test_binding.py index 215ee0f41..41a9d6fb5 100644 --- a/llvmlite/tests/test_binding.py +++ b/llvmlite/tests/test_binding.py @@ -78,6 +78,16 @@ def no_de_locale(): }} """ +asm_sum4 = r""" + ; ModuleID = '' + target triple = "{triple}" + + define i32 @sum(i32 %.1, i32 %.2) {{ + %.3 = add i32 %.1, %.2 + ret i32 0 + }} + """ + asm_mul = r""" ; ModuleID = '' target triple = "{triple}" @@ -2581,5 +2591,113 @@ def rel(): llvm.ffi.unregister_lock_callback(acq, rel) +class NewPassManagerMixin(object): + + def pipeline_tuning_options(self): + return llvm.create_pipeline_options() + + def pb(self, opt_level=0): + tm = self.target_machine(jit=False) + pto = self.pipeline_tuning_options() + pto.opt_level = opt_level + pb = llvm.create_pass_builder(tm, pto) + return pb + + +class TestPassBuilder(BaseTest, NewPassManagerMixin): + + def test_pto(self): + tm = self.target_machine(jit=False) + pto = self.pipeline_tuning_options() + pto.opt_level = 3 + pto.inlining_threshold = 2 + pb = llvm.create_pass_builder(tm, pto) + + def test_close(self): + pb = self.pb() + pb.close() + pb.close() + + def test_getMPM(self): + pb = self.pb() + mpm = pb.getNewModulePassManager() + pb.close() + + def test_getFPM(self): + pb = self.pb() + fpm = pb.getNewFunctionPassManager() + pb.close() + + +class TestNewModulePassManager(BaseTest, NewPassManagerMixin): + def pm(self): + return llvm.create_new_module_pass_manager() + + def test_close(self): + mpm = self.pm() + mpm.close() + + def test_run(self): + pb = self.pb(3) + mod = self.module() + orig_asm = str(mod) + mpm = pb.getNewModulePassManager() + mpm.run(mod, pb) + optimized_asm = str(mod) + self.assertIn("%.4", orig_asm) + self.assertNotIn("%.4", optimized_asm) + + def test_instcombine(self): + pb = self.pb() + mpm = self.pm() + mpm.add_instruction_combine_pass() + mod = self.module(asm_sum4) + orig_asm = str(mod) + mpm.run(mod, pb) + optimized_asm = str(mod) + self.assertIn("%.3", orig_asm) + self.assertNotIn("%.3", optimized_asm) + + def test_passes(self): + mpm = self.pm() + mpm.add_aa_eval_pass() + mpm.add_instruction_combine_pass() + mpm.add_jump_threading_pass() + mpm.add_loop_rotate_pass() + mpm.add_loop_unroll_pass() + mpm.add_simplify_cfg_pass() + mpm.addVerifier() + + +class TestNewFunctionPassManager(BaseTest, NewPassManagerMixin): + def pm(self): + return llvm.create_new_function_pass_manager() + + def test_close(self): + fpm = self.pm() + fpm.close() + + def test_run(self): + pb = self.pb(3) + mod = self.module() + fun = mod.get_function("sum") + orig_asm = str(fun) + fpm = pb.getNewFunctionPassManager() + fpm.run(fun, pb) + optimized_asm = str(fun) + self.assertIn("%.4", orig_asm) + self.assertNotIn("%.4", optimized_asm) + + def test_instcombine(self): + pb = self.pb() + fpm = self.pm() + fun = self.module(asm_sum4).get_function("sum") + fpm.add_instruction_combine_pass() + orig_asm = str(fun) + fpm.run(fun, pb) + optimized_asm = str(fun) + self.assertIn("%.3", orig_asm) + self.assertNotIn("%.3", optimized_asm) + if __name__ == "__main__": unittest.main() From de1832aaca0bf6cbaf93b8d2d961db2f4a3d7d4d Mon Sep 17 00:00:00 2001 From: Yashwant Singh Date: Fri, 3 May 2024 11:53:54 +0530 Subject: [PATCH 02/27] formatting --- ffi/newpassmanagers.cpp | 126 ++++++++++++----------- llvmlite/binding/ffi.py | 1 + llvmlite/binding/newpassmangers.py | 155 +++++++++++++++++++---------- llvmlite/tests/test_binding.py | 10 +- 4 files changed, 181 insertions(+), 111 deletions(-) diff --git a/ffi/newpassmanagers.cpp b/ffi/newpassmanagers.cpp index e89985a49..9c7058245 100644 --- a/ffi/newpassmanagers.cpp +++ b/ffi/newpassmanagers.cpp @@ -1,14 +1,14 @@ #include "core.h" -#include "llvm/Transforms/Scalar/SimplifyCFG.h" -#include "llvm/Analysis/AliasAnalysisEvaluator.h" #include "llvm-c/TargetMachine.h" -#include "llvm/IR/Verifier.h" +#include "llvm/Analysis/AliasAnalysisEvaluator.h" #include "llvm/IR/PassManager.h" +#include "llvm/IR/Verifier.h" #include "llvm/Passes/PassBuilder.h" -#include "llvm/Transforms/Scalar/LoopUnrollPass.h" -#include "llvm/Transforms/Scalar/LoopRotation.h" #include "llvm/Transforms/InstCombine/InstCombine.h" #include "llvm/Transforms/Scalar/JumpThreading.h" +#include "llvm/Transforms/Scalar/LoopRotation.h" +#include "llvm/Transforms/Scalar/LoopUnrollPass.h" +#include "llvm/Transforms/Scalar/SimplifyCFG.h" using namespace llvm; @@ -16,9 +16,7 @@ using namespace llvm; * Exposed API */ -namespace llvm -{ - +namespace llvm { // TODO: Use DEFINE_SIMPLE_CONVERSION_FUNCTIONS llvm macro struct OpaqueModulePassManager; @@ -66,7 +64,7 @@ static PipelineTuningOptions *unwrap(LLVMPipelineTuningOptionsRef PTO) { } static TargetMachine *unwrap(LLVMTargetMachineRef P) { - return reinterpret_cast(P); + return reinterpret_cast(P); } } // namespace llvm @@ -76,11 +74,14 @@ extern "C" { // MPM API_EXPORT(LLVMModulePassManagerRef) -LLVMPY_CreateNewModulePassManager() { return llvm::wrap(new PassManager()); } +LLVMPY_CreateNewModulePassManager() { + return llvm::wrap(new PassManager()); +} API_EXPORT(void) -LLVMPY_NMPRun_module(LLVMModulePassManagerRef MPMRef, LLVMPassBuilderRef PBRef, LLVMModuleRef mod) { - +LLVMPY_NMPRun_module(LLVMModulePassManagerRef MPMRef, LLVMPassBuilderRef PBRef, + LLVMModuleRef mod) { + ModulePassManager *MPM = llvm::unwrap(MPMRef); PassBuilder *PB = llvm::unwrap(PBRef); Module *M = llvm::unwrap(mod); @@ -103,53 +104,60 @@ LLVMPY_AddVeriferPass(LLVMModulePassManagerRef MPM) { } API_EXPORT(void) -LLVMPY_AddAAEvalPassNMPM(LLVMModulePassManagerRef MPM) { - llvm::unwrap(MPM)->addPass(createModuleToFunctionPassAdaptor(AAEvaluator())); +LLVMPY_AddAAEvalPass_module(LLVMModulePassManagerRef MPM) { + llvm::unwrap(MPM)->addPass( + createModuleToFunctionPassAdaptor(AAEvaluator())); } API_EXPORT(void) LLVMPY_AddSimplifyCFGPass_module(LLVMModulePassManagerRef MPM) { - llvm::unwrap(MPM)->addPass(createModuleToFunctionPassAdaptor(SimplifyCFGPass())); + llvm::unwrap(MPM)->addPass( + createModuleToFunctionPassAdaptor(SimplifyCFGPass())); } API_EXPORT(void) LLVMPY_AddLoopUnrollPass_module(LLVMModulePassManagerRef MPM) { - llvm::unwrap(MPM)->addPass(createModuleToFunctionPassAdaptor(LoopUnrollPass())); + llvm::unwrap(MPM)->addPass( + createModuleToFunctionPassAdaptor(LoopUnrollPass())); } API_EXPORT(void) LLVMPY_LLVMAddLoopRotatePass_module(LLVMModulePassManagerRef MPM) { - llvm::unwrap(MPM)->addPass(createModuleToFunctionPassAdaptor(createFunctionToLoopPassAdaptor(LoopRotatePass()))); + llvm::unwrap(MPM)->addPass(createModuleToFunctionPassAdaptor( + createFunctionToLoopPassAdaptor(LoopRotatePass()))); } - API_EXPORT(void) LLVMPY_LLVMAddInstructionCombinePass_module(LLVMModulePassManagerRef MPM) { - llvm::unwrap(MPM)->addPass(createModuleToFunctionPassAdaptor(InstCombinePass())); + llvm::unwrap(MPM)->addPass( + createModuleToFunctionPassAdaptor(InstCombinePass())); } - API_EXPORT(void) LLVMPY_AddJumpThreadingPass_module(LLVMModulePassManagerRef MPM, int T) { - llvm::unwrap(MPM)->addPass(createModuleToFunctionPassAdaptor(JumpThreadingPass(T))); + llvm::unwrap(MPM)->addPass( + createModuleToFunctionPassAdaptor(JumpThreadingPass(T))); } API_EXPORT(void) -LLVMPY_DisposeNewModulePassManger(LLVMModulePassManagerRef MPM){ +LLVMPY_DisposeNewModulePassManger(LLVMModulePassManagerRef MPM) { delete llvm::unwrap(MPM); } // FPM API_EXPORT(LLVMFunctionPassManagerRef) -LLVMPY_CreateNewFunctionPassManager() { return llvm::wrap(new PassManager()); } +LLVMPY_CreateNewFunctionPassManager() { + return llvm::wrap(new PassManager()); +} API_EXPORT(void) -LLVMPY_NMPRun_function(LLVMFunctionPassManagerRef FPMRef, LLVMPassBuilderRef PBRef, LLVMValueRef FRef) { +LLVMPY_NMPRun_function(LLVMFunctionPassManagerRef FPMRef, + LLVMPassBuilderRef PBRef, LLVMValueRef FRef) { - FunctionPassManager* FPM = llvm::unwrap(FPMRef); - PassBuilder* PB = llvm::unwrap(PBRef); - Function* F = reinterpret_cast(FRef); + FunctionPassManager *FPM = llvm::unwrap(FPMRef); + PassBuilder *PB = llvm::unwrap(PBRef); + Function *F = reinterpret_cast(FRef); LoopAnalysisManager LAM; FunctionAnalysisManager FAM; @@ -164,7 +172,7 @@ LLVMPY_NMPRun_function(LLVMFunctionPassManagerRef FPMRef, LLVMPassBuilderRef PBR } API_EXPORT(void) -LLVMPY_AddAAEvalPassNFPM(LLVMFunctionPassManagerRef FPM) { +LLVMPY_AddAAEvalPass_function(LLVMFunctionPassManagerRef FPM) { llvm::unwrap(FPM)->addPass(AAEvaluator()); } @@ -174,13 +182,14 @@ LLVMPY_AddSimplifyCFGPass_function(LLVMFunctionPassManagerRef FPM) { } API_EXPORT(void) -LLVMPY_AddLoopUnrollPass_Function(LLVMFunctionPassManagerRef FPM) { +LLVMPY_AddLoopUnrollPass_function(LLVMFunctionPassManagerRef FPM) { llvm::unwrap(FPM)->addPass(LoopUnrollPass()); } API_EXPORT(void) LLVMPY_LLVMAddLoopRotatePass_function(LLVMFunctionPassManagerRef FPM) { - llvm::unwrap(FPM)->addPass(createFunctionToLoopPassAdaptor(LoopRotatePass())); + llvm::unwrap(FPM)->addPass( + createFunctionToLoopPassAdaptor(LoopRotatePass())); } API_EXPORT(void) @@ -194,14 +203,16 @@ LLVMPY_AddJumpThreadingPass_function(LLVMFunctionPassManagerRef FPM, int T) { } API_EXPORT(void) -LLVMPY_DisposeNewFunctionPassManger(LLVMFunctionPassManagerRef FPM){ +LLVMPY_DisposeNewFunctionPassManger(LLVMFunctionPassManagerRef FPM) { delete llvm::unwrap(FPM); } // PTO API_EXPORT(LLVMPipelineTuningOptionsRef) -LLVMPY_CreatePipelineTuningOptions() { return llvm::wrap(new PipelineTuningOptions()); } +LLVMPY_CreatePipelineTuningOptions() { + return llvm::wrap(new PipelineTuningOptions()); +} API_EXPORT(bool) LLVMPY_PTOGetLoopInterleaving(LLVMPipelineTuningOptionsRef PTO) { @@ -255,34 +266,35 @@ LLVMPY_PTOSetLoopUnrolling(LLVMPipelineTuningOptionsRef PTO, bool value) { // } API_EXPORT(void) -LLVMPY_DisposePipelineTuningOptions(LLVMPipelineTuningOptionsRef PTO){ +LLVMPY_DisposePipelineTuningOptions(LLVMPipelineTuningOptionsRef PTO) { delete llvm::unwrap(PTO); } - // PB API_EXPORT(LLVMPassBuilderRef) -LLVMPY_CreatePassBuilder(LLVMTargetMachineRef TM, LLVMPipelineTuningOptionsRef PTO) { - TargetMachine* target = llvm::unwrap(TM); - PipelineTuningOptions* pt = llvm::unwrap(PTO); - return llvm::wrap(new PassBuilder(target, *pt)); +LLVMPY_CreatePassBuilder(LLVMTargetMachineRef TM, + LLVMPipelineTuningOptionsRef PTO) { + TargetMachine *target = llvm::unwrap(TM); + PipelineTuningOptions *pt = llvm::unwrap(PTO); + return llvm::wrap(new PassBuilder(target, *pt)); } API_EXPORT(LLVMModulePassManagerRef) -LLVMPY_buildPerModuleDefaultPipeline(LLVMPassBuilderRef PBref, int opt_level) { +LLVMPY_buildPerModuleDefaultPipeline(LLVMPassBuilderRef PBref, int opt_level) { - PassBuilder* PB = llvm::unwrap(PBref); - ModulePassManager* MPM; - if(opt_level == 0){ - MPM = new ModulePassManager(PB->buildO0DefaultPipeline(OptimizationLevel::O0)); + PassBuilder *PB = llvm::unwrap(PBref); + ModulePassManager *MPM; + if (opt_level == 0) { + MPM = new ModulePassManager( + PB->buildO0DefaultPipeline(OptimizationLevel::O0)); return llvm::wrap(MPM); } - + OptimizationLevel lvl; - if(opt_level == 1) + if (opt_level == 1) lvl = OptimizationLevel::O1; - else if(opt_level == 2) + else if (opt_level == 2) lvl = OptimizationLevel::O2; else lvl = OptimizationLevel::O3; @@ -292,30 +304,30 @@ LLVMPY_buildPerModuleDefaultPipeline(LLVMPassBuilderRef PBref, int opt_level) { } API_EXPORT(LLVMFunctionPassManagerRef) -LLVMPY_buildFunctionSimplificationPipeline(LLVMPassBuilderRef PBref, int opt_level) { +LLVMPY_buildFunctionSimplificationPipeline(LLVMPassBuilderRef PBref, + int opt_level) { - PassBuilder* PB = llvm::unwrap(PBref); - FunctionPassManager* FPM; - if(opt_level == 0){ + PassBuilder *PB = llvm::unwrap(PBref); + FunctionPassManager *FPM; + if (opt_level == 0) { FPM = new FunctionPassManager(); return llvm::wrap(FPM); } - + OptimizationLevel lvl; - if(opt_level == 1) + if (opt_level == 1) lvl = OptimizationLevel::O1; - else if(opt_level == 2) + else if (opt_level == 2) lvl = OptimizationLevel::O2; else lvl = OptimizationLevel::O3; - FPM = new FunctionPassManager(PB->buildFunctionSimplificationPipeline(lvl, ThinOrFullLTOPhase::None)); + FPM = new FunctionPassManager( + PB->buildFunctionSimplificationPipeline(lvl, ThinOrFullLTOPhase::None)); return llvm::wrap(FPM); } API_EXPORT(void) -LLVMPY_DisposePassBuilder(LLVMPassBuilderRef PB){ - delete llvm::unwrap(PB); -} +LLVMPY_DisposePassBuilder(LLVMPassBuilderRef PB) { delete llvm::unwrap(PB); } } // end extern "C" diff --git a/llvmlite/binding/ffi.py b/llvmlite/binding/ffi.py index af32054b6..da7bb9a3c 100644 --- a/llvmlite/binding/ffi.py +++ b/llvmlite/binding/ffi.py @@ -46,6 +46,7 @@ def _make_opaque_ref(name): LLVMFunctionPassManagerRef = _make_opaque_ref("LLVMFunctionPassManager") LLVMPassBuilderRef = _make_opaque_ref("LLVMPassBuilder") + class _LLVMLock: """A Lock to guarantee thread-safety for the LLVM C-API. diff --git a/llvmlite/binding/newpassmangers.py b/llvmlite/binding/newpassmangers.py index 8c4128745..06d1d1f22 100644 --- a/llvmlite/binding/newpassmangers.py +++ b/llvmlite/binding/newpassmangers.py @@ -8,15 +8,19 @@ def create_new_module_pass_manager(): return NewModulePassManager() + def create_new_function_pass_manager(): return NewFunctionPassManger() + def create_pass_builder(tm, pto): return PassBuilder(tm, pto) + def create_pipeline_options(): return PipelineTuningOptions() + class NewModulePassManager(ffi.ObjectRef): def __init__(self, ptr=None): @@ -29,19 +33,19 @@ def run(self, module, pb): def addVerifier(self): ffi.lib.LLVMPY_AddVeriferPass(self) - + def add_aa_eval_pass(self): - ffi.lib.LLVMPY_AddAAEvalPassNMPM(self) - + ffi.lib.LLVMPY_AddAAEvalPass_module(self) + def add_simplify_cfg_pass(self): ffi.lib.LLVMPY_AddSimplifyCFGPass_module(self) - + def add_loop_unroll_pass(self): ffi.lib.LLVMPY_AddLoopUnrollPass_module(self) - + def add_loop_rotate_pass(self): ffi.lib.LLVMPY_LLVMAddLoopRotatePass_module(self) - + def add_instruction_combine_pass(self): ffi.lib.LLVMPY_LLVMAddInstructionCombinePass_module(self) @@ -52,6 +56,7 @@ def add_jump_threading_pass(self, threshold=-1): def _dispose(self): ffi.lib.LLVMPY_DisposeNewModulePassManger(self) + class NewFunctionPassManger(ffi.ObjectRef): def __init__(self, ptr=None): @@ -60,17 +65,17 @@ def __init__(self, ptr=None): ffi.ObjectRef.__init__(self, ptr) def add_aa_eval_pass(self): - ffi.lib.LLVMPY_AddAAEvalPassNFPM(self) + ffi.lib.LLVMPY_AddAAEvalPass_function(self) def add_simplify_cfg_pass(self): ffi.lib.LLVMPY_AddSimplifyCFGPass_function(self) - + def run(self, fun, pb): ffi.lib.LLVMPY_NMPRun_function(self, pb, fun) def add_loop_unroll_pass(self): - ffi.lib.LLVMPY_AddLoopUnrollPass_Function(self) - + ffi.lib.LLVMPY_AddLoopUnrollPass_function(self) + def add_loop_rotate_pass(self): ffi.lib.LLVMPY_LLVMAddLoopRotatePass_function(self) @@ -79,10 +84,11 @@ def add_instruction_combine_pass(self): def add_jump_threading_pass(self, threshold=-1): ffi.lib.LLVMPY_AddJumpThreadingPass_function(self, threshold) - + def _dispose(self): ffi.lib.LLVMPY_DisposeNewFunctionPassManger(self) + # Make this nested class of PassBuilder? class PipelineTuningOptions(ffi.ObjectRef): @@ -92,7 +98,7 @@ def __init__(self, ptr=None): self._opt_level = 3 # self._size_level = 0 ffi.ObjectRef.__init__(self, ptr) - + @property def loop_interleaving(self): return ffi.lib.LLVMPY_PTOGetLoopInterleaving(self) @@ -116,7 +122,7 @@ def slp_vectorization(self): @slp_vectorization.setter def slp_vectorization(self, value): ffi.lib.LLVMPY_PTOSetSLPVectorization(self, value) - + @property def loop_unrolling(self): return ffi.lib.LLVMPY_PTOGetLoopUnrolling(self) @@ -146,21 +152,24 @@ def opt_level(self): def opt_level(self, level): self._opt_level = level - # FIXME: Model optimization level combining opt level and size level similar to llvm + # FIXME: Model optimization level combining opt level and + # size level similar to llvm # @property # def size_level(self): # """ - # Whether and how much to optimize for size. An integer between 0 and 2. + # Whether and how much to optimize for size. + # An integer between 0 and 2. # """ # return self._size_level # @size_level.setter # def size_level(self, size): # self._size_level = size - + def _dispose(self): ffi.lib.LLVMPY_DisposePipelineTuningOptions(self) + class PassBuilder(ffi.ObjectRef): def __init__(self, tm, pto, ptr=None): @@ -172,22 +181,24 @@ def __init__(self, tm, pto, ptr=None): def getNewModulePassManager(self): return NewModulePassManager( - ffi.lib.LLVMPY_buildPerModuleDefaultPipeline(self, self._pto.opt_level) + ffi.lib.LLVMPY_buildPerModuleDefaultPipeline( + self, self._pto.opt_level) ) def getNewFunctionPassManager(self): return NewFunctionPassManger( - ffi.lib.LLVMPY_buildFunctionSimplificationPipeline(self, self._pto.opt_level) + ffi.lib.LLVMPY_buildFunctionSimplificationPipeline( + self, self._pto.opt_level) ) - + def _dispose(self): # Should I explicitly delete pointer to pto and tm? ffi.lib.LLVMPY_DisposePassBuilder(self) - + # ============================================================================ # FFI - + ffi.lib.LLVMPY_CreateNewModulePassManager.restype = ffi.LLVMModulePassManagerRef @@ -196,59 +207,101 @@ def _dispose(self): ffi.LLVMModuleRef,] ffi.lib.LLVMPY_AddVeriferPass.argtypes = [ffi.LLVMModulePassManagerRef,] -ffi.lib.LLVMPY_AddAAEvalPassNMPM.argtypes = [ffi.LLVMModulePassManagerRef,] -ffi.lib.LLVMPY_AddSimplifyCFGPass_module.argtypes = [ffi.LLVMModulePassManagerRef,] -ffi.lib.LLVMPY_AddLoopUnrollPass_module.argtypes = [ffi.LLVMModulePassManagerRef,] -ffi.lib.LLVMPY_LLVMAddLoopRotatePass_module.argtypes = [ffi.LLVMModulePassManagerRef,] -ffi.lib.LLVMPY_LLVMAddInstructionCombinePass_module.argtypes = [ffi.LLVMModulePassManagerRef,] -ffi.lib.LLVMPY_AddJumpThreadingPass_module.argtypes = [ffi.LLVMModulePassManagerRef,] -ffi.lib.LLVMPY_DisposeNewModulePassManger.argtypes = [ffi.LLVMModulePassManagerRef,] +ffi.lib.LLVMPY_AddAAEvalPass_module.argtypes = [ffi.LLVMModulePassManagerRef,] +ffi.lib.LLVMPY_AddSimplifyCFGPass_module.argtypes = [ + ffi.LLVMModulePassManagerRef,] + +ffi.lib.LLVMPY_AddLoopUnrollPass_module.argtypes = [ + ffi.LLVMModulePassManagerRef,] + +ffi.lib.LLVMPY_LLVMAddLoopRotatePass_module.argtypes = [ + ffi.LLVMModulePassManagerRef,] -ffi.lib.LLVMPY_CreateNewFunctionPassManager.restype = ffi.LLVMFunctionPassManagerRef +ffi.lib.LLVMPY_LLVMAddInstructionCombinePass_module.argtypes = [ + ffi.LLVMModulePassManagerRef,] + +ffi.lib.LLVMPY_AddJumpThreadingPass_module.argtypes = [ + ffi.LLVMModulePassManagerRef,] + +ffi.lib.LLVMPY_DisposeNewModulePassManger.argtypes = [ + ffi.LLVMModulePassManagerRef,] + +ffi.lib.LLVMPY_CreateNewFunctionPassManager.restype = \ + ffi.LLVMFunctionPassManagerRef ffi.lib.LLVMPY_NMPRun_function.argtypes = [ffi.LLVMFunctionPassManagerRef, ffi.LLVMPassBuilderRef, ffi.LLVMValueRef,] -ffi.lib.LLVMPY_AddAAEvalPassNFPM.argtypes = [ffi.LLVMFunctionPassManagerRef,] -ffi.lib.LLVMPY_AddSimplifyCFGPass_function.argtypes = [ffi.LLVMFunctionPassManagerRef,] -ffi.lib.LLVMPY_AddLoopUnrollPass_Function.argtypes = [ffi.LLVMFunctionPassManagerRef,] -ffi.lib.LLVMPY_LLVMAddLoopRotatePass_function.argtypes = [ffi.LLVMFunctionPassManagerRef,] -ffi.lib.LLVMPY_LLVMAddInstructionCombinePass_function.argtypes = [ffi.LLVMFunctionPassManagerRef,] -ffi.lib.LLVMPY_AddJumpThreadingPass_function.argtypes = [ffi.LLVMFunctionPassManagerRef, c_int,] -ffi.lib.LLVMPY_DisposeNewFunctionPassManger.argtypes = [ffi.LLVMFunctionPassManagerRef,] +ffi.lib.LLVMPY_AddAAEvalPass_function.argtypes = [ + ffi.LLVMFunctionPassManagerRef,] + +ffi.lib.LLVMPY_AddSimplifyCFGPass_function.argtypes = [ + ffi.LLVMFunctionPassManagerRef,] + +ffi.lib.LLVMPY_AddLoopUnrollPass_function.argtypes = [ + ffi.LLVMFunctionPassManagerRef,] + +ffi.lib.LLVMPY_LLVMAddLoopRotatePass_function.argtypes = [ + ffi.LLVMFunctionPassManagerRef,] + +ffi.lib.LLVMPY_LLVMAddInstructionCombinePass_function.argtypes = [ + ffi.LLVMFunctionPassManagerRef,] + +ffi.lib.LLVMPY_AddJumpThreadingPass_function.argtypes = [ + ffi.LLVMFunctionPassManagerRef, c_int,] + +ffi.lib.LLVMPY_DisposeNewFunctionPassManger.argtypes = [ + ffi.LLVMFunctionPassManagerRef,] ffi.lib.LLVMPY_CreatePassBuilder.restype = ffi.LLVMPassBuilderRef -ffi.lib.LLVMPY_CreatePassBuilder.argtypes = [ffi.LLVMTargetMachineRef, +ffi.lib.LLVMPY_CreatePassBuilder.argtypes = [ffi.LLVMTargetMachineRef, ffi.LLVMPipelineTuningOptionsRef,] -ffi.lib.LLVMPY_buildPerModuleDefaultPipeline.restype = ffi.LLVMModulePassManagerRef -ffi.lib.LLVMPY_buildPerModuleDefaultPipeline.argtypes = [ffi.LLVMPassBuilderRef, c_int,] +ffi.lib.LLVMPY_buildPerModuleDefaultPipeline.restype = \ + ffi.LLVMModulePassManagerRef + +ffi.lib.LLVMPY_buildPerModuleDefaultPipeline.argtypes = [ + ffi.LLVMPassBuilderRef, c_int,] -ffi.lib.LLVMPY_buildFunctionSimplificationPipeline.restype = ffi.LLVMFunctionPassManagerRef -ffi.lib.LLVMPY_buildFunctionSimplificationPipeline.argtypes = [ffi.LLVMPassBuilderRef, c_int,] +ffi.lib.LLVMPY_buildFunctionSimplificationPipeline.restype = \ + ffi.LLVMFunctionPassManagerRef + +ffi.lib.LLVMPY_buildFunctionSimplificationPipeline.argtypes = [ + ffi.LLVMPassBuilderRef, c_int,] ffi.lib.LLVMPY_DisposePassBuilder.argtypes = [ffi.LLVMPassBuilderRef,] -ffi.lib.LLVMPY_CreatePipelineTuningOptions.restype = ffi.LLVMPipelineTuningOptionsRef +ffi.lib.LLVMPY_CreatePipelineTuningOptions.restype = \ + ffi.LLVMPipelineTuningOptionsRef ffi.lib.LLVMPY_PTOGetLoopInterleaving.restype = c_bool -ffi.lib.LLVMPY_PTOGetLoopInterleaving.argtypes = [ffi.LLVMPipelineTuningOptionsRef,] +ffi.lib.LLVMPY_PTOGetLoopInterleaving.argtypes = [ + ffi.LLVMPipelineTuningOptionsRef,] -ffi.lib.LLVMPY_PTOSetLoopInterleaving.argtypes = [ffi.LLVMPipelineTuningOptionsRef, c_bool] +ffi.lib.LLVMPY_PTOSetLoopInterleaving.argtypes = [ + ffi.LLVMPipelineTuningOptionsRef, c_bool] ffi.lib.LLVMPY_PTOGetLoopVectorization.restype = c_bool -ffi.lib.LLVMPY_PTOGetLoopVectorization.argtypes = [ffi.LLVMPipelineTuningOptionsRef,] +ffi.lib.LLVMPY_PTOGetLoopVectorization.argtypes = [ + ffi.LLVMPipelineTuningOptionsRef,] -ffi.lib.LLVMPY_PTOSetLoopVectorization.argtypes = [ffi.LLVMPipelineTuningOptionsRef, c_bool] +ffi.lib.LLVMPY_PTOSetLoopVectorization.argtypes = [ + ffi.LLVMPipelineTuningOptionsRef, c_bool] ffi.lib.LLVMPY_PTOGetSLPVectorization.restype = c_bool -ffi.lib.LLVMPY_PTOGetSLPVectorization.argtypes = [ffi.LLVMPipelineTuningOptionsRef,] +ffi.lib.LLVMPY_PTOGetSLPVectorization.argtypes = [ + ffi.LLVMPipelineTuningOptionsRef,] -ffi.lib.LLVMPY_PTOSetSLPVectorization.argtypes = [ffi.LLVMPipelineTuningOptionsRef, c_bool] +ffi.lib.LLVMPY_PTOSetSLPVectorization.argtypes = [ + ffi.LLVMPipelineTuningOptionsRef, c_bool] ffi.lib.LLVMPY_PTOGetLoopUnrolling.restype = c_bool -ffi.lib.LLVMPY_PTOGetLoopUnrolling.argtypes = [ffi.LLVMPipelineTuningOptionsRef,] +ffi.lib.LLVMPY_PTOGetLoopUnrolling.argtypes = [ + ffi.LLVMPipelineTuningOptionsRef,] + +ffi.lib.LLVMPY_PTOSetLoopUnrolling.argtypes = [ + ffi.LLVMPipelineTuningOptionsRef, c_bool] -ffi.lib.LLVMPY_PTOSetLoopUnrolling.argtypes = [ffi.LLVMPipelineTuningOptionsRef, c_bool] -ffi.lib.LLVMPY_DisposePipelineTuningOptions.argtypes = [ffi.LLVMPipelineTuningOptionsRef,] +ffi.lib.LLVMPY_DisposePipelineTuningOptions.argtypes = \ + [ffi.LLVMPipelineTuningOptionsRef,] diff --git a/llvmlite/tests/test_binding.py b/llvmlite/tests/test_binding.py index 41a9d6fb5..be0886da6 100644 --- a/llvmlite/tests/test_binding.py +++ b/llvmlite/tests/test_binding.py @@ -2612,20 +2612,23 @@ def test_pto(self): pto.opt_level = 3 pto.inlining_threshold = 2 pb = llvm.create_pass_builder(tm, pto) - + pb.close() + def test_close(self): pb = self.pb() pb.close() pb.close() - + def test_getMPM(self): pb = self.pb() mpm = pb.getNewModulePassManager() + mpm.run(self.module(), pb) pb.close() def test_getFPM(self): pb = self.pb() fpm = pb.getNewFunctionPassManager() + fpm.run(self.module().get_function("sum"), pb) pb.close() @@ -2657,7 +2660,7 @@ def test_instcombine(self): optimized_asm = str(mod) self.assertIn("%.3", orig_asm) self.assertNotIn("%.3", optimized_asm) - + def test_passes(self): mpm = self.pm() mpm.add_aa_eval_pass() @@ -2699,5 +2702,6 @@ def test_instcombine(self): self.assertIn("%.3", orig_asm) self.assertNotIn("%.3", optimized_asm) + if __name__ == "__main__": unittest.main() From 4ea3d86e438e639401f4fe9956796cc3da59a14d Mon Sep 17 00:00:00 2001 From: Yashwant Singh Date: Wed, 8 May 2024 16:24:27 +0530 Subject: [PATCH 03/27] Use DEFINE_SIMPLE_CONVERSION_FUNCTIONS macro --- ffi/newpassmanagers.cpp | 37 ++++--------------------------------- 1 file changed, 4 insertions(+), 33 deletions(-) diff --git a/ffi/newpassmanagers.cpp b/ffi/newpassmanagers.cpp index 9c7058245..8a9e920e0 100644 --- a/ffi/newpassmanagers.cpp +++ b/ffi/newpassmanagers.cpp @@ -18,50 +18,21 @@ using namespace llvm; namespace llvm { -// TODO: Use DEFINE_SIMPLE_CONVERSION_FUNCTIONS llvm macro struct OpaqueModulePassManager; typedef OpaqueModulePassManager *LLVMModulePassManagerRef; - -static LLVMModulePassManagerRef wrap(ModulePassManager *MPM) { - return reinterpret_cast(MPM); -} - -static ModulePassManager *unwrap(LLVMModulePassManagerRef MPM) { - return reinterpret_cast(MPM); -} +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ModulePassManager, LLVMModulePassManagerRef) struct OpaqueFunctionPassManager; typedef OpaqueFunctionPassManager *LLVMFunctionPassManagerRef; - -static LLVMFunctionPassManagerRef wrap(FunctionPassManager *FPM) { - return reinterpret_cast(FPM); -} - -static FunctionPassManager *unwrap(LLVMFunctionPassManagerRef FPM) { - return reinterpret_cast(FPM); -} +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(FunctionPassManager, LLVMFunctionPassManagerRef) struct OpaquePassBuilder; typedef OpaquePassBuilder *LLVMPassBuilderRef; - -static LLVMPassBuilderRef wrap(PassBuilder *FPM) { - return reinterpret_cast(FPM); -} - -static PassBuilder *unwrap(LLVMPassBuilderRef FPM) { - return reinterpret_cast(FPM); -} +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(PassBuilder, LLVMPassBuilderRef) struct OpaquePipelineTuningOptions; typedef OpaquePipelineTuningOptions *LLVMPipelineTuningOptionsRef; - -static LLVMPipelineTuningOptionsRef wrap(PipelineTuningOptions *PTO) { - return reinterpret_cast(PTO); -} - -static PipelineTuningOptions *unwrap(LLVMPipelineTuningOptionsRef PTO) { - return reinterpret_cast(PTO); -} +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(PipelineTuningOptions, LLVMPipelineTuningOptionsRef) static TargetMachine *unwrap(LLVMTargetMachineRef P) { return reinterpret_cast(P); From 445ebb46764ccea4726640dd2e0970b9213d70de Mon Sep 17 00:00:00 2001 From: Yashwant Singh Date: Thu, 9 May 2024 11:04:08 +0530 Subject: [PATCH 04/27] Map speed level, size level to appropriate OptimizationLevel --- ffi/newpassmanagers.cpp | 81 +++++++++++++++++------------- llvmlite/binding/newpassmangers.py | 30 ++++++----- 2 files changed, 61 insertions(+), 50 deletions(-) diff --git a/ffi/newpassmanagers.cpp b/ffi/newpassmanagers.cpp index 8a9e920e0..ff6133118 100644 --- a/ffi/newpassmanagers.cpp +++ b/ffi/newpassmanagers.cpp @@ -24,7 +24,8 @@ DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ModulePassManager, LLVMModulePassManagerRef) struct OpaqueFunctionPassManager; typedef OpaqueFunctionPassManager *LLVMFunctionPassManagerRef; -DEFINE_SIMPLE_CONVERSION_FUNCTIONS(FunctionPassManager, LLVMFunctionPassManagerRef) +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(FunctionPassManager, + LLVMFunctionPassManagerRef) struct OpaquePassBuilder; typedef OpaquePassBuilder *LLVMPassBuilderRef; @@ -32,7 +33,8 @@ DEFINE_SIMPLE_CONVERSION_FUNCTIONS(PassBuilder, LLVMPassBuilderRef) struct OpaquePipelineTuningOptions; typedef OpaquePipelineTuningOptions *LLVMPipelineTuningOptionsRef; -DEFINE_SIMPLE_CONVERSION_FUNCTIONS(PipelineTuningOptions, LLVMPipelineTuningOptionsRef) +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(PipelineTuningOptions, + LLVMPipelineTuningOptionsRef) static TargetMachine *unwrap(LLVMTargetMachineRef P) { return reinterpret_cast(P); @@ -251,50 +253,61 @@ LLVMPY_CreatePassBuilder(LLVMTargetMachineRef TM, return llvm::wrap(new PassBuilder(target, *pt)); } +static OptimizationLevel mapLevel(int speed_level, int size_level) { + switch (size_level) { + case 0: + switch (speed_level) { + case 0: + return OptimizationLevel::O0; + case 1: + return OptimizationLevel::O1; + case 2: + return OptimizationLevel::O2; + case 3: + return OptimizationLevel::O3; + default: + llvm_unreachable("Invalid optimization level"); + } + case 1: + if (speed_level == 1) + return OptimizationLevel::Os; + llvm_unreachable("Invalid optimization level for size level 1"); + case 2: + if (speed_level == 2) + return OptimizationLevel::Oz; + llvm_unreachable("Invalid optimization level for size level 2"); + default: + llvm_unreachable("Invalid size level"); + break; + } +} + API_EXPORT(LLVMModulePassManagerRef) -LLVMPY_buildPerModuleDefaultPipeline(LLVMPassBuilderRef PBref, int opt_level) { +LLVMPY_buildPerModuleDefaultPipeline(LLVMPassBuilderRef PBref, int speed_level, + int size_level) { PassBuilder *PB = llvm::unwrap(PBref); - ModulePassManager *MPM; - if (opt_level == 0) { - MPM = new ModulePassManager( - PB->buildO0DefaultPipeline(OptimizationLevel::O0)); - return llvm::wrap(MPM); + OptimizationLevel OL = mapLevel(speed_level, size_level); + if (OL == OptimizationLevel::O0) { + return llvm::wrap( + new ModulePassManager(PB->buildO0DefaultPipeline(OL))); } - OptimizationLevel lvl; - if (opt_level == 1) - lvl = OptimizationLevel::O1; - else if (opt_level == 2) - lvl = OptimizationLevel::O2; - else - lvl = OptimizationLevel::O3; - - MPM = new ModulePassManager(PB->buildPerModuleDefaultPipeline(lvl)); - return llvm::wrap(MPM); + return llvm::wrap( + new ModulePassManager(PB->buildPerModuleDefaultPipeline(OL))); } API_EXPORT(LLVMFunctionPassManagerRef) LLVMPY_buildFunctionSimplificationPipeline(LLVMPassBuilderRef PBref, - int opt_level) { + int speed_level, int size_level) { PassBuilder *PB = llvm::unwrap(PBref); - FunctionPassManager *FPM; - if (opt_level == 0) { - FPM = new FunctionPassManager(); - return llvm::wrap(FPM); - } - - OptimizationLevel lvl; - if (opt_level == 1) - lvl = OptimizationLevel::O1; - else if (opt_level == 2) - lvl = OptimizationLevel::O2; - else - lvl = OptimizationLevel::O3; + OptimizationLevel OL = mapLevel(speed_level, size_level); + if (OL == OptimizationLevel::O0) + return llvm::wrap(new FunctionPassManager()); - FPM = new FunctionPassManager( - PB->buildFunctionSimplificationPipeline(lvl, ThinOrFullLTOPhase::None)); + FunctionPassManager *FPM = new FunctionPassManager( + PB->buildFunctionSimplificationPipeline(OL, ThinOrFullLTOPhase::None)); return llvm::wrap(FPM); } diff --git a/llvmlite/binding/newpassmangers.py b/llvmlite/binding/newpassmangers.py index 06d1d1f22..45e786e77 100644 --- a/llvmlite/binding/newpassmangers.py +++ b/llvmlite/binding/newpassmangers.py @@ -95,8 +95,8 @@ class PipelineTuningOptions(ffi.ObjectRef): def __init__(self, ptr=None): if ptr is None: ptr = ffi.lib.LLVMPY_CreatePipelineTuningOptions() - self._opt_level = 3 - # self._size_level = 0 + self._opt_level = 2 + self._size_level = 0 ffi.ObjectRef.__init__(self, ptr) @property @@ -152,19 +152,17 @@ def opt_level(self): def opt_level(self, level): self._opt_level = level - # FIXME: Model optimization level combining opt level and - # size level similar to llvm - # @property - # def size_level(self): - # """ - # Whether and how much to optimize for size. - # An integer between 0 and 2. - # """ - # return self._size_level + @property + def size_level(self): + """ + Whether and how much to optimize for size. + An integer between 0 and 2. + """ + return self._size_level - # @size_level.setter - # def size_level(self, size): - # self._size_level = size + @size_level.setter + def size_level(self, size): + self._size_level = size def _dispose(self): ffi.lib.LLVMPY_DisposePipelineTuningOptions(self) @@ -182,13 +180,13 @@ def __init__(self, tm, pto, ptr=None): def getNewModulePassManager(self): return NewModulePassManager( ffi.lib.LLVMPY_buildPerModuleDefaultPipeline( - self, self._pto.opt_level) + self, self._pto.opt_level, self._pto.size_level) ) def getNewFunctionPassManager(self): return NewFunctionPassManger( ffi.lib.LLVMPY_buildFunctionSimplificationPipeline( - self, self._pto.opt_level) + self, self._pto.opt_level, self._pto.size_level) ) def _dispose(self): From 5e9c0b94ccdcb88e697a5274bc27c1c11499b312 Mon Sep 17 00:00:00 2001 From: Yashwant Singh Date: Mon, 13 May 2024 11:20:52 +0530 Subject: [PATCH 05/27] Prefix old pass manager code with "legacy" prefix Remove "new" prefix from new pass manager code Move transforms.* code into legacypassmanagers.* --- .../binding/optimization-passes.rst | 10 +- .../user-guide/binding/target-information.rst | 2 +- docs/source/user-guide/examples/npm-usage.py | 6 +- ffi/CMakeLists.txt | 6 +- ffi/Makefile.freebsd | 4 +- ffi/Makefile.linux | 4 +- ffi/Makefile.osx | 4 +- ffi/legacypassmanagers.cpp | 580 +++++++++ ffi/newpassmanagers.cpp | 317 ----- ffi/passmanagers.cpp | 560 +++------ ffi/transforms.cpp | 96 -- llvmlite/binding/__init__.py | 5 +- llvmlite/binding/legacypassmanagers.py | 1088 +++++++++++++++++ llvmlite/binding/newpassmangers.py | 305 ----- llvmlite/binding/passmanagers.py | 1046 ++++------------ llvmlite/binding/transforms.py | 151 --- llvmlite/tests/test_binding.py | 12 +- llvmlite/tests/test_refprune.py | 4 +- 18 files changed, 2097 insertions(+), 2103 deletions(-) create mode 100644 ffi/legacypassmanagers.cpp delete mode 100644 ffi/newpassmanagers.cpp delete mode 100644 ffi/transforms.cpp create mode 100644 llvmlite/binding/legacypassmanagers.py delete mode 100644 llvmlite/binding/newpassmangers.py delete mode 100644 llvmlite/binding/transforms.py diff --git a/docs/source/user-guide/binding/optimization-passes.rst b/docs/source/user-guide/binding/optimization-passes.rst index 7894e4785..5ec8865b3 100644 --- a/docs/source/user-guide/binding/optimization-passes.rst +++ b/docs/source/user-guide/binding/optimization-passes.rst @@ -8,10 +8,10 @@ LLVM gives you the opportunity to fine-tune optimization passes. Optimization passes are managed by a pass manager. There are 2 kinds of pass managers: -* :class:`FunctionPassManager`, for optimizations that work on +* :class:`LegacyFunctionPassManager`, for optimizations that work on single functions. -* :class:`ModulePassManager`, for optimizations that work on +* :class:`LegacyModulePassManager`, for optimizations that work on whole modules. To instantiate either of these pass managers, you first need to @@ -62,7 +62,7 @@ create and configure a :class:`PassManagerBuilder`. be enabled at the same time. -.. class:: PassManager +.. class:: LegacyPassManager The base class for pass managers. Use individual ``add_*`` methods or :meth:`PassManagerBuilder.populate` to add @@ -141,7 +141,7 @@ create and configure a :class:`PassManagerBuilder`. See `instnamer pass documentation `_. -.. class:: ModulePassManager() +.. class:: LegacyModulePassManager() Create a new pass manager to run optimization passes on a module. @@ -156,7 +156,7 @@ create and configure a :class:`PassManagerBuilder`. Returns ``True`` if the optimizations made any modification to the module. Otherwise returns ``False``. -.. class:: FunctionPassManager(module) +.. class:: LegacyFunctionPassManager(module) Create a new pass manager to run optimization passes on a function of the given *module*, a :class:`ModuleRef` instance. diff --git a/docs/source/user-guide/binding/target-information.rst b/docs/source/user-guide/binding/target-information.rst index 96376a072..33f941787 100644 --- a/docs/source/user-guide/binding/target-information.rst +++ b/docs/source/user-guide/binding/target-information.rst @@ -164,7 +164,7 @@ Classes * .. method:: add_analysis_passes(pm) Register analysis passes for this target machine with the - :class:`PassManager` instance *pm*. + :class:`LegacyPassManager` instance *pm*. * .. method:: emit_object(module) diff --git a/docs/source/user-guide/examples/npm-usage.py b/docs/source/user-guide/examples/npm-usage.py index 51a6d673b..4b957bce6 100644 --- a/docs/source/user-guide/examples/npm-usage.py +++ b/docs/source/user-guide/examples/npm-usage.py @@ -205,7 +205,7 @@ pto = llvm.create_pipeline_options() pto.opt_level = 2 # similarly more properties can be set pb = llvm.create_pass_builder(tm, pto) -npm_o2 = pb.getNewModulePassManager() +npm_o2 = pb.getModulePassManager() npm_o2.run(llmod, pb) print(llmod) @@ -224,7 +224,7 @@ pb = llvm.create_pass_builder(tm, pto) fun = llmod2.get_function("n") print(fun) -fpm = pb.getNewFunctionPassManager() +fpm = pb.getFunctionPassManager() fpm.add_simplify_cfg_pass() fpm.run(fun, pb) print(fun) @@ -238,7 +238,7 @@ pto.opt_level = 3 # similarly more properties can be set pto.loop_unrolling = False pb = llvm.create_pass_builder(tm, pto) -npm = pb.getNewModulePassManager() +npm = pb.getModulePassManager() # # Inplace optimize the IR module npm.run(llmod_unroll, pb) print(llmod_unroll) diff --git a/ffi/CMakeLists.txt b/ffi/CMakeLists.txt index d5b964bfe..41a41cf90 100755 --- a/ffi/CMakeLists.txt +++ b/ffi/CMakeLists.txt @@ -42,9 +42,9 @@ endif() # Define our shared library add_library(llvmlite SHARED assembly.cpp bitcode.cpp core.cpp initfini.cpp - module.cpp value.cpp executionengine.cpp transforms.cpp type.cpp - passmanagers.cpp targets.cpp dylib.cpp linker.cpp object_file.cpp - custom_passes.cpp orcjit.cpp memorymanager.cpp newpassmanagers.cpp) + module.cpp value.cpp executionengine.cpp type.cpp + legacypassmanagers.cpp targets.cpp dylib.cpp linker.cpp object_file.cpp + custom_passes.cpp orcjit.cpp memorymanager.cpp passmanagers.cpp) # Find the libraries that correspond to the LLVM components # that we wish to use. diff --git a/ffi/Makefile.freebsd b/ffi/Makefile.freebsd index 09635d910..ee9a1b752 100644 --- a/ffi/Makefile.freebsd +++ b/ffi/Makefile.freebsd @@ -10,9 +10,9 @@ LDFLAGS := $(LDFLAGS) $(LLVM_LDFLAGS) $(LD_FLTO_FLAGS) LIBS = $(LLVM_LIBS) INCLUDE = core.h SRC = assembly.cpp bitcode.cpp core.cpp initfini.cpp module.cpp value.cpp \ - executionengine.cpp transforms.cpp passmanagers.cpp type.cpp targets.cpp \ + executionengine.cpp legacypassmanagers.cpp type.cpp targets.cpp \ dylib.cpp linker.cpp object_file.cpp orcjit.cpp custom_passes.cpp \ - memorymanager.cpp + memorymanager.cpp passmanagers.cpp OUTPUT = libllvmlite.so all: $(OUTPUT) diff --git a/ffi/Makefile.linux b/ffi/Makefile.linux index 560d94de5..5cc02c7f7 100644 --- a/ffi/Makefile.linux +++ b/ffi/Makefile.linux @@ -12,8 +12,8 @@ LDFLAGS := $(LDFLAGS) $(LLVM_LDFLAGS) $(LD_FLTO_FLAGS) LIBS = $(LLVM_LIBS) INCLUDE = core.h OBJ = assembly.o bitcode.o core.o initfini.o module.o value.o \ - executionengine.o transforms.o passmanagers.o targets.o type.o dylib.o \ - linker.o object_file.o custom_passes.o orcjit.o memorymanager.o newpassmanagers.o + executionengine.o legacypassmanagers.o targets.o type.o dylib.o \ + linker.o object_file.o custom_passes.o orcjit.o memorymanager.o passmanagers.o OUTPUT = libllvmlite.so all: $(OUTPUT) diff --git a/ffi/Makefile.osx b/ffi/Makefile.osx index afe4f3bac..7feff8d0b 100644 --- a/ffi/Makefile.osx +++ b/ffi/Makefile.osx @@ -7,9 +7,9 @@ LDFLAGS := $(LDFLAGS) $(EXPORT) $(LLVM_LDFLAGS) LIBS = $(LLVM_LIBS) INCLUDE = core.h SRC = assembly.cpp bitcode.cpp core.cpp initfini.cpp module.cpp value.cpp \ - executionengine.cpp transforms.cpp passmanagers.cpp targets.cpp type.cpp \ + executionengine.cpp legacypassmanagers.cpp targets.cpp type.cpp \ dylib.cpp linker.cpp object_file.cpp custom_passes.cpp orcjit.cpp \ - memorymanager.cpp + memorymanager.cpp passmanagers.cpp OUTPUT = libllvmlite.dylib MACOSX_DEPLOYMENT_TARGET ?= 10.9 diff --git a/ffi/legacypassmanagers.cpp b/ffi/legacypassmanagers.cpp new file mode 100644 index 000000000..0bc7b4c87 --- /dev/null +++ b/ffi/legacypassmanagers.cpp @@ -0,0 +1,580 @@ +#include + +#include "core.h" + +#include "llvm-c/Transforms/IPO.h" +#include "llvm-c/Transforms/Scalar.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/IR/DiagnosticInfo.h" +#include "llvm/IR/DiagnosticPrinter.h" +#include "llvm/IR/LegacyPassManager.h" +#include "llvm/IR/Module.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/ToolOutputFile.h" +#include "llvm/Support/YAMLTraits.h" +#include "llvm/Support/raw_ostream.h" + +#include "core.h" +#include "llvm-c/Target.h" +#include "llvm-c/Transforms/IPO.h" +#include "llvm-c/Transforms/PassManagerBuilder.h" +#include "llvm-c/Transforms/Scalar.h" +#include "llvm/IR/LLVMRemarkStreamer.h" +#include "llvm/IR/LegacyPassManager.h" +#include "llvm/Remarks/RemarkStreamer.h" +#include "llvm/Transforms/IPO.h" +#include "llvm/Transforms/IPO/PassManagerBuilder.h" +#include "llvm/Transforms/Scalar.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +using namespace llvm; + +/* + * Exposed API + */ + +extern "C" { + +API_EXPORT(void) +LLVMPY_SetTimePasses(bool enable) { TimePassesIsEnabled = enable; } + +API_EXPORT(void) +LLVMPY_ReportAndResetTimings(const char **outmsg) { + std::string osbuf; + raw_string_ostream os(osbuf); + reportAndResetTimings(&os); + os.flush(); + *outmsg = LLVMPY_CreateString(os.str().c_str()); +} + +API_EXPORT(LLVMPassManagerRef) +LLVMPY_CreateLegacyPassManager() { return LLVMCreatePassManager(); } + +API_EXPORT(void) +LLVMPY_DisposeLegacyPassManager(LLVMPassManagerRef PM) { + return LLVMDisposePassManager(PM); +} + +API_EXPORT(LLVMPassManagerRef) +LLVMPY_CreateLegacyFunctionPassManager(LLVMModuleRef M) { + return LLVMCreateFunctionPassManagerForModule(M); +} + +API_EXPORT(int) +LLVMPY_RunPassManagerWithLegacyRemarks(LLVMPassManagerRef PM, LLVMModuleRef M, + const char *remarks_format, + const char *remarks_filter, + const char *record_filename) { + auto setupResult = llvm::setupLLVMOptimizationRemarks( + unwrap(M)->getContext(), record_filename, remarks_filter, + remarks_format, true); + if (!setupResult) { + return -1; + } + auto optimisationFile = std::move(*setupResult); + auto r = LLVMRunPassManager(PM, M); + + unwrap(M)->getContext().setMainRemarkStreamer(nullptr); + unwrap(M)->getContext().setLLVMRemarkStreamer(nullptr); + + optimisationFile->keep(); + optimisationFile->os().flush(); + return r; +} + +API_EXPORT(int) +LLVMPY_RunLegacyPassManager(LLVMPassManagerRef PM, LLVMModuleRef M) { + return LLVMRunPassManager(PM, M); +} + +API_EXPORT(int) +LLVMPY_RunLegacyFunctionPassManagerWithRemarks(LLVMPassManagerRef PM, + LLVMValueRef F, + const char *remarks_format, + const char *remarks_filter, + const char *record_filename) { + auto setupResult = llvm::setupLLVMOptimizationRemarks( + unwrap(F)->getContext(), record_filename, remarks_filter, + remarks_format, true); + if (!setupResult) { + return -1; + } + auto optimisationFile = std::move(*setupResult); + + auto r = LLVMRunFunctionPassManager(PM, F); + + unwrap(F)->getContext().setMainRemarkStreamer(nullptr); + unwrap(F)->getContext().setLLVMRemarkStreamer(nullptr); + + optimisationFile->keep(); + optimisationFile->os().flush(); + return r; +} + +API_EXPORT(int) +LLVMPY_RunLegacyFunctionPassManager(LLVMPassManagerRef PM, LLVMValueRef F) { + return LLVMRunFunctionPassManager(PM, F); +} + +API_EXPORT(int) +LLVMPY_InitializeLegacyFunctionPassManager(LLVMPassManagerRef FPM) { + return LLVMInitializeFunctionPassManager(FPM); +} + +API_EXPORT(int) +LLVMPY_FinalizeLegacyFunctionPassManager(LLVMPassManagerRef FPM) { + return LLVMFinalizeFunctionPassManager(FPM); +} + +API_EXPORT(void) +LLVMPY_AddAAEvalPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(llvm::createAAEvalPass()); +} + +API_EXPORT(void) +LLVMPY_AddBasicAAWrapperPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(llvm::createBasicAAWrapperPass()); +} + +API_EXPORT(void) +LLVMPY_AddDependenceAnalysisPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(llvm::createDependenceAnalysisWrapperPass()); +} + +API_EXPORT(void) +LLVMPY_AddCallGraphDOTPrinterPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(llvm::createCallGraphDOTPrinterPass()); +} + +API_EXPORT(void) +LLVMPY_AddDotDomPrinterPass(LLVMPassManagerRef PM, bool showBody) { +#if LLVM_VERSION_MAJOR > 14 + unwrap(PM)->add(showBody ? llvm::createDomPrinterWrapperPassPass() + : llvm::createDomOnlyPrinterWrapperPassPass()); +#else + unwrap(PM)->add(showBody ? llvm::createDomPrinterPass() + : llvm::createDomOnlyPrinterPass()); +#endif +} + +API_EXPORT(void) +LLVMPY_AddGlobalsModRefAAPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(llvm::createGlobalsAAWrapperPass()); +} + +API_EXPORT(void) +LLVMPY_AddDotPostDomPrinterPass(LLVMPassManagerRef PM, bool showBody) { +#if LLVM_VERSION_MAJOR > 14 + unwrap(PM)->add(showBody ? llvm::createPostDomPrinterWrapperPassPass() + : llvm::createPostDomOnlyPrinterWrapperPassPass()); +#else + unwrap(PM)->add(showBody ? llvm::createPostDomPrinterPass() + : llvm::createPostDomOnlyPrinterPass()); +#endif +} + +API_EXPORT(void) +LLVMPY_AddCFGPrinterPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(llvm::createCFGPrinterLegacyPassPass()); +} + +API_EXPORT(void) +LLVMPY_AddConstantMergePass(LLVMPassManagerRef PM) { + LLVMAddConstantMergePass(PM); +} + +API_EXPORT(void) +LLVMPY_AddDeadStoreEliminationPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(llvm::createDeadStoreEliminationPass()); +} + +API_EXPORT(void) +LLVMPY_AddReversePostOrderFunctionAttrsPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(llvm::createReversePostOrderFunctionAttrsPass()); +} + +API_EXPORT(void) +LLVMPY_AddDeadArgEliminationPass(LLVMPassManagerRef PM) { + LLVMAddDeadArgEliminationPass(PM); +} + +API_EXPORT(void) +LLVMPY_AddInstructionCountPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(llvm::createInstCountPass()); +} + +API_EXPORT(void) +LLVMPY_AddIVUsersPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(llvm::createIVUsersPass()); +} + +API_EXPORT(void) +LLVMPY_AddLazyValueInfoPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(llvm::createLazyValueInfoPass()); +} +API_EXPORT(void) +LLVMPY_AddLintPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(llvm::createLintLegacyPassPass()); +} +API_EXPORT(void) +LLVMPY_AddModuleDebugInfoPrinterPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(llvm::createModuleDebugInfoPrinterPass()); +} + +API_EXPORT(void) +LLVMPY_AddRegionInfoPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(llvm::createRegionInfoPass()); +} + +API_EXPORT(void) +LLVMPY_AddScalarEvolutionAAPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(llvm::createSCEVAAWrapperPass()); +} + +API_EXPORT(void) +LLVMPY_AddAggressiveDCEPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(llvm::createAggressiveDCEPass()); +} + +API_EXPORT(void) +LLVMPY_AddAlwaysInlinerPass(LLVMPassManagerRef PM, bool insertLifetime) { + unwrap(PM)->add(llvm::createAlwaysInlinerLegacyPass(insertLifetime)); +} + +#if LLVM_VERSION_MAJOR < 15 +API_EXPORT(void) +LLVMPY_AddArgPromotionPass(LLVMPassManagerRef PM, unsigned int maxElements) { + unwrap(PM)->add(llvm::createArgumentPromotionPass(maxElements)); +} +#endif + +API_EXPORT(void) +LLVMPY_AddBreakCriticalEdgesPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(llvm::createBreakCriticalEdgesPass()); +} + +API_EXPORT(void) +LLVMPY_AddFunctionAttrsPass(LLVMPassManagerRef PM) { + LLVMAddFunctionAttrsPass(PM); +} + +API_EXPORT(void) +LLVMPY_AddFunctionInliningPass(LLVMPassManagerRef PM, int Threshold) { + unwrap(PM)->add(createFunctionInliningPass(Threshold)); +} + +API_EXPORT(void) +LLVMPY_AddGlobalOptimizerPass(LLVMPassManagerRef PM) { + LLVMAddGlobalOptimizerPass(PM); +} + +API_EXPORT(void) +LLVMPY_AddGlobalDCEPass(LLVMPassManagerRef PM) { LLVMAddGlobalDCEPass(PM); } + +API_EXPORT(void) +LLVMPY_AddIPSCCPPass(LLVMPassManagerRef PM) { LLVMAddIPSCCPPass(PM); } + +API_EXPORT(void) +LLVMPY_AddDeadCodeEliminationPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createDeadCodeEliminationPass()); +} + +API_EXPORT(void) +LLVMPY_AddAggressiveInstructionCombiningPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createAggressiveInstCombinerPass()); +} + +API_EXPORT(void) +LLVMPY_AddInternalizePass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createInternalizePass()); +} + +API_EXPORT(void) +LLVMPY_AddJumpThreadingPass(LLVMPassManagerRef PM, int threshold) { + unwrap(PM)->add(createJumpThreadingPass(threshold)); +} + +API_EXPORT(void) +LLVMPY_AddLCSSAPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createLCSSAPass()); +} + +API_EXPORT(void) +LLVMPY_AddLoopDeletionPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createLoopDeletionPass()); +} + +API_EXPORT(void) +LLVMPY_AddLoopExtractorPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createLoopExtractorPass()); +} + +API_EXPORT(void) +LLVMPY_AddSingleLoopExtractorPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createSingleLoopExtractorPass()); +} + +API_EXPORT(void) +LLVMPY_AddLoopStrengthReducePass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createLoopStrengthReducePass()); +} + +API_EXPORT(void) +LLVMPY_AddLoopSimplificationPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createLoopSimplifyPass()); +} + +API_EXPORT(void) +LLVMPY_AddLoopUnrollPass(LLVMPassManagerRef PM) { LLVMAddLoopUnrollPass(PM); } + +API_EXPORT(void) +LLVMPY_AddLoopUnrollAndJamPass(LLVMPassManagerRef PM) { + LLVMAddLoopUnrollAndJamPass(PM); +} + +API_EXPORT(void) +LLVMPY_AddLoopUnswitchPass(LLVMPassManagerRef PM, bool optimizeForSize, + bool hasBranchDivergence) { +#if LLVM_VERSION_MAJOR > 14 + unwrap(PM)->add(createSimpleLoopUnswitchLegacyPass(optimizeForSize)); +#else + unwrap(PM)->add( + createLoopUnswitchPass(optimizeForSize, hasBranchDivergence)); +#endif +} + +API_EXPORT(void) +LLVMPY_AddLowerAtomicPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createLowerAtomicPass()); +} + +API_EXPORT(void) +LLVMPY_AddLowerInvokePass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createLowerInvokePass()); +} + +API_EXPORT(void) +LLVMPY_AddLowerSwitchPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createLowerSwitchPass()); +} + +API_EXPORT(void) +LLVMPY_AddMemCpyOptimizationPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createMemCpyOptPass()); +} + +API_EXPORT(void) +LLVMPY_AddMergeFunctionsPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createMergeFunctionsPass()); +} + +API_EXPORT(void) +LLVMPY_AddMergeReturnsPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createUnifyFunctionExitNodesPass()); +} + +API_EXPORT(void) +LLVMPY_AddPartialInliningPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createPartialInliningPass()); +} + +API_EXPORT(void) +LLVMPY_AddPruneExceptionHandlingPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createPruneEHPass()); +} + +API_EXPORT(void) +LLVMPY_AddReassociatePass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createReassociatePass()); +} + +API_EXPORT(void) +LLVMPY_AddDemoteRegisterToMemoryPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createDemoteRegisterToMemoryPass()); +} + +API_EXPORT(void) +LLVMPY_AddSinkPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createSinkingPass()); +} + +API_EXPORT(void) +LLVMPY_AddStripSymbolsPass(LLVMPassManagerRef PM, bool onlyDebugInfo) { + unwrap(PM)->add(createStripSymbolsPass(onlyDebugInfo)); +} + +API_EXPORT(void) +LLVMPY_AddStripDeadDebugInfoPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createStripDeadDebugInfoPass()); +} + +API_EXPORT(void) +LLVMPY_AddStripDeadPrototypesPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createStripDeadPrototypesPass()); +} + +API_EXPORT(void) +LLVMPY_AddStripDebugDeclarePrototypesPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createStripDebugDeclarePass()); +} + +API_EXPORT(void) +LLVMPY_AddStripNondebugSymbolsPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createStripNonDebugSymbolsPass()); +} + +API_EXPORT(void) +LLVMPY_AddTailCallEliminationPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createTailCallEliminationPass()); +} + +API_EXPORT(void) +LLVMPY_AddCFGSimplificationPass(LLVMPassManagerRef PM) { + LLVMAddCFGSimplificationPass(PM); +} + +API_EXPORT(void) +LLVMPY_AddGVNPass(LLVMPassManagerRef PM) { LLVMAddGVNPass(PM); } + +API_EXPORT(void) +LLVMPY_AddInstructionCombiningPass(LLVMPassManagerRef PM) { + LLVMAddInstructionCombiningPass(PM); +} + +API_EXPORT(void) +LLVMPY_AddLICMPass(LLVMPassManagerRef PM) { LLVMAddLICMPass(PM); } + +API_EXPORT(void) +LLVMPY_AddSCCPPass(LLVMPassManagerRef PM) { LLVMAddSCCPPass(PM); } + +API_EXPORT(void) +LLVMPY_AddSROAPass(LLVMPassManagerRef PM) { unwrap(PM)->add(createSROAPass()); } + +API_EXPORT(void) +LLVMPY_AddTypeBasedAliasAnalysisPass(LLVMPassManagerRef PM) { + LLVMAddTypeBasedAliasAnalysisPass(PM); +} + +API_EXPORT(void) +LLVMPY_AddBasicAliasAnalysisPass(LLVMPassManagerRef PM) { + LLVMAddBasicAliasAnalysisPass(PM); +} + +API_EXPORT(void) +LLVMPY_LLVMAddLoopRotatePass(LLVMPassManagerRef PM) { + LLVMAddLoopRotatePass(PM); +} + +API_EXPORT(void) +LLVMPY_AddInstructionNamerPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createInstructionNamerPass()); +} + +API_EXPORT(LLVMPassManagerBuilderRef) +LLVMPY_PassManagerBuilderCreate() { return LLVMPassManagerBuilderCreate(); } + +API_EXPORT(void) +LLVMPY_PassManagerBuilderDispose(LLVMPassManagerBuilderRef PMB) { + LLVMPassManagerBuilderDispose(PMB); +} + +API_EXPORT(void) +LLVMPY_PassManagerBuilderPopulateLegacyModulePassManager( + LLVMPassManagerBuilderRef PMB, LLVMPassManagerRef PM) { + LLVMPassManagerBuilderPopulateModulePassManager(PMB, PM); +} + +API_EXPORT(unsigned) +LLVMPY_PassManagerBuilderGetOptLevel(LLVMPassManagerBuilderRef PMB) { + llvm::PassManagerBuilder *pmb = llvm::unwrap(PMB); + return pmb->OptLevel; +} + +API_EXPORT(void) +LLVMPY_PassManagerBuilderSetOptLevel(LLVMPassManagerBuilderRef PMB, + unsigned OptLevel) { + LLVMPassManagerBuilderSetOptLevel(PMB, OptLevel); +} + +API_EXPORT(unsigned) +LLVMPY_PassManagerBuilderGetSizeLevel(LLVMPassManagerBuilderRef PMB) { + llvm::PassManagerBuilder *pmb = llvm::unwrap(PMB); + return pmb->SizeLevel; +} + +API_EXPORT(void) +LLVMPY_PassManagerBuilderSetSizeLevel(LLVMPassManagerBuilderRef PMB, + unsigned SizeLevel) { + LLVMPassManagerBuilderSetSizeLevel(PMB, SizeLevel); +} + +API_EXPORT(int) +LLVMPY_PassManagerBuilderGetDisableUnrollLoops(LLVMPassManagerBuilderRef PMB) { + llvm::PassManagerBuilder *pmb = llvm::unwrap(PMB); + return pmb->DisableUnrollLoops; +} + +API_EXPORT(void) +LLVMPY_PassManagerBuilderSetDisableUnrollLoops(LLVMPassManagerBuilderRef PMB, + LLVMBool Value) { + LLVMPassManagerBuilderSetDisableUnrollLoops(PMB, Value); +} + +API_EXPORT(void) +LLVMPY_PassManagerBuilderUseInlinerWithThreshold(LLVMPassManagerBuilderRef PMB, + unsigned Threshold) { + LLVMPassManagerBuilderUseInlinerWithThreshold(PMB, Threshold); +} + +API_EXPORT(void) +LLVMPY_PassManagerBuilderPopulateLegacyFunctionPassManager( + LLVMPassManagerBuilderRef PMB, LLVMPassManagerRef PM) { + LLVMPassManagerBuilderPopulateFunctionPassManager(PMB, PM); +} + +API_EXPORT(void) +LLVMPY_PassManagerBuilderSetLoopVectorize(LLVMPassManagerBuilderRef PMB, + int Value) { + llvm::PassManagerBuilder *pmb = llvm::unwrap(PMB); + pmb->LoopVectorize = Value; +} + +API_EXPORT(int) +LLVMPY_PassManagerBuilderGetLoopVectorize(LLVMPassManagerBuilderRef PMB) { + llvm::PassManagerBuilder *pmb = llvm::unwrap(PMB); + return pmb->LoopVectorize; +} + +API_EXPORT(void) +LLVMPY_PassManagerBuilderSetSLPVectorize(LLVMPassManagerBuilderRef PMB, + int Value) { + llvm::PassManagerBuilder *pmb = llvm::unwrap(PMB); + pmb->SLPVectorize = Value; +} + +API_EXPORT(int) +LLVMPY_PassManagerBuilderGetSLPVectorize(LLVMPassManagerBuilderRef PMB) { + llvm::PassManagerBuilder *pmb = llvm::unwrap(PMB); + return pmb->SLPVectorize; +} + +} // end extern "C" diff --git a/ffi/newpassmanagers.cpp b/ffi/newpassmanagers.cpp deleted file mode 100644 index ff6133118..000000000 --- a/ffi/newpassmanagers.cpp +++ /dev/null @@ -1,317 +0,0 @@ -#include "core.h" -#include "llvm-c/TargetMachine.h" -#include "llvm/Analysis/AliasAnalysisEvaluator.h" -#include "llvm/IR/PassManager.h" -#include "llvm/IR/Verifier.h" -#include "llvm/Passes/PassBuilder.h" -#include "llvm/Transforms/InstCombine/InstCombine.h" -#include "llvm/Transforms/Scalar/JumpThreading.h" -#include "llvm/Transforms/Scalar/LoopRotation.h" -#include "llvm/Transforms/Scalar/LoopUnrollPass.h" -#include "llvm/Transforms/Scalar/SimplifyCFG.h" - -using namespace llvm; - -/* - * Exposed API - */ - -namespace llvm { - -struct OpaqueModulePassManager; -typedef OpaqueModulePassManager *LLVMModulePassManagerRef; -DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ModulePassManager, LLVMModulePassManagerRef) - -struct OpaqueFunctionPassManager; -typedef OpaqueFunctionPassManager *LLVMFunctionPassManagerRef; -DEFINE_SIMPLE_CONVERSION_FUNCTIONS(FunctionPassManager, - LLVMFunctionPassManagerRef) - -struct OpaquePassBuilder; -typedef OpaquePassBuilder *LLVMPassBuilderRef; -DEFINE_SIMPLE_CONVERSION_FUNCTIONS(PassBuilder, LLVMPassBuilderRef) - -struct OpaquePipelineTuningOptions; -typedef OpaquePipelineTuningOptions *LLVMPipelineTuningOptionsRef; -DEFINE_SIMPLE_CONVERSION_FUNCTIONS(PipelineTuningOptions, - LLVMPipelineTuningOptionsRef) - -static TargetMachine *unwrap(LLVMTargetMachineRef P) { - return reinterpret_cast(P); -} - -} // namespace llvm - -extern "C" { - -// MPM - -API_EXPORT(LLVMModulePassManagerRef) -LLVMPY_CreateNewModulePassManager() { - return llvm::wrap(new PassManager()); -} - -API_EXPORT(void) -LLVMPY_NMPRun_module(LLVMModulePassManagerRef MPMRef, LLVMPassBuilderRef PBRef, - LLVMModuleRef mod) { - - ModulePassManager *MPM = llvm::unwrap(MPMRef); - PassBuilder *PB = llvm::unwrap(PBRef); - Module *M = llvm::unwrap(mod); - - LoopAnalysisManager LAM; - FunctionAnalysisManager FAM; - CGSCCAnalysisManager CGAM; - ModuleAnalysisManager MAM; - PB->registerLoopAnalyses(LAM); - PB->registerFunctionAnalyses(FAM); - PB->registerCGSCCAnalyses(CGAM); - PB->registerModuleAnalyses(MAM); - PB->crossRegisterProxies(LAM, FAM, CGAM, MAM); - MPM->run(*M, MAM); -} - -API_EXPORT(void) -LLVMPY_AddVeriferPass(LLVMModulePassManagerRef MPM) { - llvm::unwrap(MPM)->addPass(VerifierPass()); -} - -API_EXPORT(void) -LLVMPY_AddAAEvalPass_module(LLVMModulePassManagerRef MPM) { - llvm::unwrap(MPM)->addPass( - createModuleToFunctionPassAdaptor(AAEvaluator())); -} - -API_EXPORT(void) -LLVMPY_AddSimplifyCFGPass_module(LLVMModulePassManagerRef MPM) { - llvm::unwrap(MPM)->addPass( - createModuleToFunctionPassAdaptor(SimplifyCFGPass())); -} - -API_EXPORT(void) -LLVMPY_AddLoopUnrollPass_module(LLVMModulePassManagerRef MPM) { - llvm::unwrap(MPM)->addPass( - createModuleToFunctionPassAdaptor(LoopUnrollPass())); -} - -API_EXPORT(void) -LLVMPY_LLVMAddLoopRotatePass_module(LLVMModulePassManagerRef MPM) { - llvm::unwrap(MPM)->addPass(createModuleToFunctionPassAdaptor( - createFunctionToLoopPassAdaptor(LoopRotatePass()))); -} - -API_EXPORT(void) -LLVMPY_LLVMAddInstructionCombinePass_module(LLVMModulePassManagerRef MPM) { - llvm::unwrap(MPM)->addPass( - createModuleToFunctionPassAdaptor(InstCombinePass())); -} - -API_EXPORT(void) -LLVMPY_AddJumpThreadingPass_module(LLVMModulePassManagerRef MPM, int T) { - llvm::unwrap(MPM)->addPass( - createModuleToFunctionPassAdaptor(JumpThreadingPass(T))); -} - -API_EXPORT(void) -LLVMPY_DisposeNewModulePassManger(LLVMModulePassManagerRef MPM) { - delete llvm::unwrap(MPM); -} - -// FPM - -API_EXPORT(LLVMFunctionPassManagerRef) -LLVMPY_CreateNewFunctionPassManager() { - return llvm::wrap(new PassManager()); -} - -API_EXPORT(void) -LLVMPY_NMPRun_function(LLVMFunctionPassManagerRef FPMRef, - LLVMPassBuilderRef PBRef, LLVMValueRef FRef) { - - FunctionPassManager *FPM = llvm::unwrap(FPMRef); - PassBuilder *PB = llvm::unwrap(PBRef); - Function *F = reinterpret_cast(FRef); - - LoopAnalysisManager LAM; - FunctionAnalysisManager FAM; - CGSCCAnalysisManager CGAM; - ModuleAnalysisManager MAM; - PB->registerLoopAnalyses(LAM); - PB->registerFunctionAnalyses(FAM); - PB->registerCGSCCAnalyses(CGAM); - PB->registerModuleAnalyses(MAM); - PB->crossRegisterProxies(LAM, FAM, CGAM, MAM); - FPM->run(*F, FAM); -} - -API_EXPORT(void) -LLVMPY_AddAAEvalPass_function(LLVMFunctionPassManagerRef FPM) { - llvm::unwrap(FPM)->addPass(AAEvaluator()); -} - -API_EXPORT(void) -LLVMPY_AddSimplifyCFGPass_function(LLVMFunctionPassManagerRef FPM) { - llvm::unwrap(FPM)->addPass(SimplifyCFGPass()); -} - -API_EXPORT(void) -LLVMPY_AddLoopUnrollPass_function(LLVMFunctionPassManagerRef FPM) { - llvm::unwrap(FPM)->addPass(LoopUnrollPass()); -} - -API_EXPORT(void) -LLVMPY_LLVMAddLoopRotatePass_function(LLVMFunctionPassManagerRef FPM) { - llvm::unwrap(FPM)->addPass( - createFunctionToLoopPassAdaptor(LoopRotatePass())); -} - -API_EXPORT(void) -LLVMPY_LLVMAddInstructionCombinePass_function(LLVMFunctionPassManagerRef FPM) { - llvm::unwrap(FPM)->addPass(InstCombinePass()); -} - -API_EXPORT(void) -LLVMPY_AddJumpThreadingPass_function(LLVMFunctionPassManagerRef FPM, int T) { - llvm::unwrap(FPM)->addPass(JumpThreadingPass(T)); -} - -API_EXPORT(void) -LLVMPY_DisposeNewFunctionPassManger(LLVMFunctionPassManagerRef FPM) { - delete llvm::unwrap(FPM); -} - -// PTO - -API_EXPORT(LLVMPipelineTuningOptionsRef) -LLVMPY_CreatePipelineTuningOptions() { - return llvm::wrap(new PipelineTuningOptions()); -} - -API_EXPORT(bool) -LLVMPY_PTOGetLoopInterleaving(LLVMPipelineTuningOptionsRef PTO) { - return llvm::unwrap(PTO)->LoopInterleaving; -} - -API_EXPORT(void) -LLVMPY_PTOSetLoopInterleaving(LLVMPipelineTuningOptionsRef PTO, bool value) { - llvm::unwrap(PTO)->LoopInterleaving = value; -} - -API_EXPORT(bool) -LLVMPY_PTOGetLoopVectorization(LLVMPipelineTuningOptionsRef PTO) { - return llvm::unwrap(PTO)->LoopVectorization; -} - -API_EXPORT(void) -LLVMPY_PTOSetLoopVectorization(LLVMPipelineTuningOptionsRef PTO, bool value) { - llvm::unwrap(PTO)->LoopVectorization = value; -} - -API_EXPORT(bool) -LLVMPY_PTOGetSLPVectorization(LLVMPipelineTuningOptionsRef PTO) { - return llvm::unwrap(PTO)->SLPVectorization; -} - -API_EXPORT(void) -LLVMPY_PTOSetSLPVectorization(LLVMPipelineTuningOptionsRef PTO, bool value) { - llvm::unwrap(PTO)->SLPVectorization = value; -} - -API_EXPORT(bool) -LLVMPY_PTOGetLoopUnrolling(LLVMPipelineTuningOptionsRef PTO) { - return llvm::unwrap(PTO)->LoopUnrolling; -} - -API_EXPORT(void) -LLVMPY_PTOSetLoopUnrolling(LLVMPipelineTuningOptionsRef PTO, bool value) { - llvm::unwrap(PTO)->LoopUnrolling = value; -} - -// FIXME: Available from llvm16 -// API_EXPORT(int) -// LLVMPY_PTOGetInlinerThreshold(LLVMPipelineTuningOptionsRef PTO) { -// return llvm::unwrap(PTO)->InlinerThreshold; -// } - -// API_EXPORT(void) -// LLVMPY_PTOSetInlinerThreshold(LLVMPipelineTuningOptionsRef PTO, bool value) { -// llvm::unwrap(PTO)->InlinerThreshold = value; -// } - -API_EXPORT(void) -LLVMPY_DisposePipelineTuningOptions(LLVMPipelineTuningOptionsRef PTO) { - delete llvm::unwrap(PTO); -} - -// PB - -API_EXPORT(LLVMPassBuilderRef) -LLVMPY_CreatePassBuilder(LLVMTargetMachineRef TM, - LLVMPipelineTuningOptionsRef PTO) { - TargetMachine *target = llvm::unwrap(TM); - PipelineTuningOptions *pt = llvm::unwrap(PTO); - return llvm::wrap(new PassBuilder(target, *pt)); -} - -static OptimizationLevel mapLevel(int speed_level, int size_level) { - switch (size_level) { - case 0: - switch (speed_level) { - case 0: - return OptimizationLevel::O0; - case 1: - return OptimizationLevel::O1; - case 2: - return OptimizationLevel::O2; - case 3: - return OptimizationLevel::O3; - default: - llvm_unreachable("Invalid optimization level"); - } - case 1: - if (speed_level == 1) - return OptimizationLevel::Os; - llvm_unreachable("Invalid optimization level for size level 1"); - case 2: - if (speed_level == 2) - return OptimizationLevel::Oz; - llvm_unreachable("Invalid optimization level for size level 2"); - default: - llvm_unreachable("Invalid size level"); - break; - } -} - -API_EXPORT(LLVMModulePassManagerRef) -LLVMPY_buildPerModuleDefaultPipeline(LLVMPassBuilderRef PBref, int speed_level, - int size_level) { - - PassBuilder *PB = llvm::unwrap(PBref); - OptimizationLevel OL = mapLevel(speed_level, size_level); - if (OL == OptimizationLevel::O0) { - return llvm::wrap( - new ModulePassManager(PB->buildO0DefaultPipeline(OL))); - } - - return llvm::wrap( - new ModulePassManager(PB->buildPerModuleDefaultPipeline(OL))); -} - -API_EXPORT(LLVMFunctionPassManagerRef) -LLVMPY_buildFunctionSimplificationPipeline(LLVMPassBuilderRef PBref, - int speed_level, int size_level) { - - PassBuilder *PB = llvm::unwrap(PBref); - OptimizationLevel OL = mapLevel(speed_level, size_level); - if (OL == OptimizationLevel::O0) - return llvm::wrap(new FunctionPassManager()); - - FunctionPassManager *FPM = new FunctionPassManager( - PB->buildFunctionSimplificationPipeline(OL, ThinOrFullLTOPhase::None)); - return llvm::wrap(FPM); -} - -API_EXPORT(void) -LLVMPY_DisposePassBuilder(LLVMPassBuilderRef PB) { delete llvm::unwrap(PB); } - -} // end extern "C" diff --git a/ffi/passmanagers.cpp b/ffi/passmanagers.cpp index da4a076b4..0ab27d2dd 100644 --- a/ffi/passmanagers.cpp +++ b/ffi/passmanagers.cpp @@ -1,487 +1,317 @@ -#include - #include "core.h" +#include "llvm-c/TargetMachine.h" +#include "llvm/Analysis/AliasAnalysisEvaluator.h" +#include "llvm/IR/PassManager.h" +#include "llvm/IR/Verifier.h" +#include "llvm/Passes/PassBuilder.h" +#include "llvm/Transforms/InstCombine/InstCombine.h" +#include "llvm/Transforms/Scalar/JumpThreading.h" +#include "llvm/Transforms/Scalar/LoopRotation.h" +#include "llvm/Transforms/Scalar/LoopUnrollPass.h" +#include "llvm/Transforms/Scalar/SimplifyCFG.h" -#include "llvm-c/Transforms/IPO.h" -#include "llvm-c/Transforms/Scalar.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/IR/DiagnosticInfo.h" -#include "llvm/IR/DiagnosticPrinter.h" -#include "llvm/IR/LegacyPassManager.h" -#include "llvm/IR/Module.h" -#include "llvm/Support/FileSystem.h" -#include "llvm/Support/ToolOutputFile.h" -#include "llvm/Support/YAMLTraits.h" -#include "llvm/Support/raw_ostream.h" - -#include "llvm-c/Transforms/IPO.h" -#include "llvm-c/Transforms/Scalar.h" -#include "llvm/IR/LLVMRemarkStreamer.h" -#include "llvm/IR/LegacyPassManager.h" -#include "llvm/Remarks/RemarkStreamer.h" -#include "llvm/Transforms/IPO.h" -#include "llvm/Transforms/Scalar.h" - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include using namespace llvm; /* * Exposed API */ -extern "C" { - -API_EXPORT(void) -LLVMPY_SetTimePasses(bool enable) { TimePassesIsEnabled = enable; } - -API_EXPORT(void) -LLVMPY_ReportAndResetTimings(const char **outmsg) { - std::string osbuf; - raw_string_ostream os(osbuf); - reportAndResetTimings(&os); - os.flush(); - *outmsg = LLVMPY_CreateString(os.str().c_str()); -} - -API_EXPORT(LLVMPassManagerRef) -LLVMPY_CreatePassManager() { return LLVMCreatePassManager(); } - -API_EXPORT(void) -LLVMPY_DisposePassManager(LLVMPassManagerRef PM) { - return LLVMDisposePassManager(PM); -} - -API_EXPORT(LLVMPassManagerRef) -LLVMPY_CreateFunctionPassManager(LLVMModuleRef M) { - return LLVMCreateFunctionPassManagerForModule(M); -} - -API_EXPORT(int) -LLVMPY_RunPassManagerWithRemarks(LLVMPassManagerRef PM, LLVMModuleRef M, - const char *remarks_format, - const char *remarks_filter, - const char *record_filename) { - auto setupResult = llvm::setupLLVMOptimizationRemarks( - unwrap(M)->getContext(), record_filename, remarks_filter, - remarks_format, true); - if (!setupResult) { - return -1; - } - auto optimisationFile = std::move(*setupResult); - auto r = LLVMRunPassManager(PM, M); - - unwrap(M)->getContext().setMainRemarkStreamer(nullptr); - unwrap(M)->getContext().setLLVMRemarkStreamer(nullptr); - - optimisationFile->keep(); - optimisationFile->os().flush(); - return r; -} - -API_EXPORT(int) -LLVMPY_RunPassManager(LLVMPassManagerRef PM, LLVMModuleRef M) { - return LLVMRunPassManager(PM, M); -} +namespace llvm { -API_EXPORT(int) -LLVMPY_RunFunctionPassManagerWithRemarks(LLVMPassManagerRef PM, LLVMValueRef F, - const char *remarks_format, - const char *remarks_filter, - const char *record_filename) { - auto setupResult = llvm::setupLLVMOptimizationRemarks( - unwrap(F)->getContext(), record_filename, remarks_filter, - remarks_format, true); - if (!setupResult) { - return -1; - } - auto optimisationFile = std::move(*setupResult); +struct OpaqueModulePassManager; +typedef OpaqueModulePassManager *LLVMModulePassManagerRef; +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ModulePassManager, LLVMModulePassManagerRef) - auto r = LLVMRunFunctionPassManager(PM, F); +struct OpaqueFunctionPassManager; +typedef OpaqueFunctionPassManager *LLVMFunctionPassManagerRef; +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(FunctionPassManager, + LLVMFunctionPassManagerRef) - unwrap(F)->getContext().setMainRemarkStreamer(nullptr); - unwrap(F)->getContext().setLLVMRemarkStreamer(nullptr); +struct OpaquePassBuilder; +typedef OpaquePassBuilder *LLVMPassBuilderRef; +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(PassBuilder, LLVMPassBuilderRef) - optimisationFile->keep(); - optimisationFile->os().flush(); - return r; -} +struct OpaquePipelineTuningOptions; +typedef OpaquePipelineTuningOptions *LLVMPipelineTuningOptionsRef; +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(PipelineTuningOptions, + LLVMPipelineTuningOptionsRef) -API_EXPORT(int) -LLVMPY_RunFunctionPassManager(LLVMPassManagerRef PM, LLVMValueRef F) { - return LLVMRunFunctionPassManager(PM, F); +static TargetMachine *unwrap(LLVMTargetMachineRef P) { + return reinterpret_cast(P); } -API_EXPORT(int) -LLVMPY_InitializeFunctionPassManager(LLVMPassManagerRef FPM) { - return LLVMInitializeFunctionPassManager(FPM); -} +} // namespace llvm -API_EXPORT(int) -LLVMPY_FinalizeFunctionPassManager(LLVMPassManagerRef FPM) { - return LLVMFinalizeFunctionPassManager(FPM); -} - -API_EXPORT(void) -LLVMPY_AddAAEvalPass(LLVMPassManagerRef PM) { - unwrap(PM)->add(llvm::createAAEvalPass()); -} - -API_EXPORT(void) -LLVMPY_AddBasicAAWrapperPass(LLVMPassManagerRef PM) { - unwrap(PM)->add(llvm::createBasicAAWrapperPass()); -} - -API_EXPORT(void) -LLVMPY_AddDependenceAnalysisPass(LLVMPassManagerRef PM) { - unwrap(PM)->add(llvm::createDependenceAnalysisWrapperPass()); -} - -API_EXPORT(void) -LLVMPY_AddCallGraphDOTPrinterPass(LLVMPassManagerRef PM) { - unwrap(PM)->add(llvm::createCallGraphDOTPrinterPass()); -} - -API_EXPORT(void) -LLVMPY_AddDotDomPrinterPass(LLVMPassManagerRef PM, bool showBody) { -#if LLVM_VERSION_MAJOR > 14 - unwrap(PM)->add(showBody ? llvm::createDomPrinterWrapperPassPass() - : llvm::createDomOnlyPrinterWrapperPassPass()); -#else - unwrap(PM)->add(showBody ? llvm::createDomPrinterPass() - : llvm::createDomOnlyPrinterPass()); -#endif -} - -API_EXPORT(void) -LLVMPY_AddGlobalsModRefAAPass(LLVMPassManagerRef PM) { - unwrap(PM)->add(llvm::createGlobalsAAWrapperPass()); -} - -API_EXPORT(void) -LLVMPY_AddDotPostDomPrinterPass(LLVMPassManagerRef PM, bool showBody) { -#if LLVM_VERSION_MAJOR > 14 - unwrap(PM)->add(showBody ? llvm::createPostDomPrinterWrapperPassPass() - : llvm::createPostDomOnlyPrinterWrapperPassPass()); -#else - unwrap(PM)->add(showBody ? llvm::createPostDomPrinterPass() - : llvm::createPostDomOnlyPrinterPass()); -#endif -} - -API_EXPORT(void) -LLVMPY_AddCFGPrinterPass(LLVMPassManagerRef PM) { - unwrap(PM)->add(llvm::createCFGPrinterLegacyPassPass()); -} - -API_EXPORT(void) -LLVMPY_AddConstantMergePass(LLVMPassManagerRef PM) { - LLVMAddConstantMergePass(PM); -} - -API_EXPORT(void) -LLVMPY_AddDeadStoreEliminationPass(LLVMPassManagerRef PM) { - unwrap(PM)->add(llvm::createDeadStoreEliminationPass()); -} - -API_EXPORT(void) -LLVMPY_AddReversePostOrderFunctionAttrsPass(LLVMPassManagerRef PM) { - unwrap(PM)->add(llvm::createReversePostOrderFunctionAttrsPass()); -} - -API_EXPORT(void) -LLVMPY_AddDeadArgEliminationPass(LLVMPassManagerRef PM) { - LLVMAddDeadArgEliminationPass(PM); -} +extern "C" { -API_EXPORT(void) -LLVMPY_AddInstructionCountPass(LLVMPassManagerRef PM) { - unwrap(PM)->add(llvm::createInstCountPass()); -} +// MPM -API_EXPORT(void) -LLVMPY_AddIVUsersPass(LLVMPassManagerRef PM) { - unwrap(PM)->add(llvm::createIVUsersPass()); +API_EXPORT(LLVMModulePassManagerRef) +LLVMPY_CreateModulePassManager() { + return llvm::wrap(new PassManager()); } API_EXPORT(void) -LLVMPY_AddLazyValueInfoPass(LLVMPassManagerRef PM) { - unwrap(PM)->add(llvm::createLazyValueInfoPass()); -} -API_EXPORT(void) -LLVMPY_AddLintPass(LLVMPassManagerRef PM) { - unwrap(PM)->add(llvm::createLintLegacyPassPass()); -} -API_EXPORT(void) -LLVMPY_AddModuleDebugInfoPrinterPass(LLVMPassManagerRef PM) { - unwrap(PM)->add(llvm::createModuleDebugInfoPrinterPass()); -} +LLVMPY_RunModulePassManager(LLVMModulePassManagerRef MPMRef, + LLVMPassBuilderRef PBRef, LLVMModuleRef mod) { -API_EXPORT(void) -LLVMPY_AddRegionInfoPass(LLVMPassManagerRef PM) { - unwrap(PM)->add(llvm::createRegionInfoPass()); -} + ModulePassManager *MPM = llvm::unwrap(MPMRef); + PassBuilder *PB = llvm::unwrap(PBRef); + Module *M = llvm::unwrap(mod); -API_EXPORT(void) -LLVMPY_AddScalarEvolutionAAPass(LLVMPassManagerRef PM) { - unwrap(PM)->add(llvm::createSCEVAAWrapperPass()); + LoopAnalysisManager LAM; + FunctionAnalysisManager FAM; + CGSCCAnalysisManager CGAM; + ModuleAnalysisManager MAM; + PB->registerLoopAnalyses(LAM); + PB->registerFunctionAnalyses(FAM); + PB->registerCGSCCAnalyses(CGAM); + PB->registerModuleAnalyses(MAM); + PB->crossRegisterProxies(LAM, FAM, CGAM, MAM); + MPM->run(*M, MAM); } API_EXPORT(void) -LLVMPY_AddAggressiveDCEPass(LLVMPassManagerRef PM) { - unwrap(PM)->add(llvm::createAggressiveDCEPass()); +LLVMPY_AddVeriferPass(LLVMModulePassManagerRef MPM) { + llvm::unwrap(MPM)->addPass(VerifierPass()); } API_EXPORT(void) -LLVMPY_AddAlwaysInlinerPass(LLVMPassManagerRef PM, bool insertLifetime) { - unwrap(PM)->add(llvm::createAlwaysInlinerLegacyPass(insertLifetime)); +LLVMPY_AddAAEvalPass_module(LLVMModulePassManagerRef MPM) { + llvm::unwrap(MPM)->addPass( + createModuleToFunctionPassAdaptor(AAEvaluator())); } -#if LLVM_VERSION_MAJOR < 15 API_EXPORT(void) -LLVMPY_AddArgPromotionPass(LLVMPassManagerRef PM, unsigned int maxElements) { - unwrap(PM)->add(llvm::createArgumentPromotionPass(maxElements)); +LLVMPY_AddSimplifyCFGPass_module(LLVMModulePassManagerRef MPM) { + llvm::unwrap(MPM)->addPass( + createModuleToFunctionPassAdaptor(SimplifyCFGPass())); } -#endif API_EXPORT(void) -LLVMPY_AddBreakCriticalEdgesPass(LLVMPassManagerRef PM) { - unwrap(PM)->add(llvm::createBreakCriticalEdgesPass()); +LLVMPY_AddLoopUnrollPass_module(LLVMModulePassManagerRef MPM) { + llvm::unwrap(MPM)->addPass( + createModuleToFunctionPassAdaptor(LoopUnrollPass())); } API_EXPORT(void) -LLVMPY_AddFunctionAttrsPass(LLVMPassManagerRef PM) { - LLVMAddFunctionAttrsPass(PM); +LLVMPY_LLVMAddLoopRotatePass_module(LLVMModulePassManagerRef MPM) { + llvm::unwrap(MPM)->addPass(createModuleToFunctionPassAdaptor( + createFunctionToLoopPassAdaptor(LoopRotatePass()))); } API_EXPORT(void) -LLVMPY_AddFunctionInliningPass(LLVMPassManagerRef PM, int Threshold) { - unwrap(PM)->add(createFunctionInliningPass(Threshold)); +LLVMPY_LLVMAddInstructionCombinePass_module(LLVMModulePassManagerRef MPM) { + llvm::unwrap(MPM)->addPass( + createModuleToFunctionPassAdaptor(InstCombinePass())); } API_EXPORT(void) -LLVMPY_AddGlobalOptimizerPass(LLVMPassManagerRef PM) { - LLVMAddGlobalOptimizerPass(PM); +LLVMPY_AddJumpThreadingPass_module(LLVMModulePassManagerRef MPM, int T) { + llvm::unwrap(MPM)->addPass( + createModuleToFunctionPassAdaptor(JumpThreadingPass(T))); } API_EXPORT(void) -LLVMPY_AddGlobalDCEPass(LLVMPassManagerRef PM) { LLVMAddGlobalDCEPass(PM); } - -API_EXPORT(void) -LLVMPY_AddIPSCCPPass(LLVMPassManagerRef PM) { LLVMAddIPSCCPPass(PM); } - -API_EXPORT(void) -LLVMPY_AddDeadCodeEliminationPass(LLVMPassManagerRef PM) { - unwrap(PM)->add(createDeadCodeEliminationPass()); +LLVMPY_DisposeNewModulePassManger(LLVMModulePassManagerRef MPM) { + delete llvm::unwrap(MPM); } -API_EXPORT(void) -LLVMPY_AddAggressiveInstructionCombiningPass(LLVMPassManagerRef PM) { - unwrap(PM)->add(createAggressiveInstCombinerPass()); -} +// FPM -API_EXPORT(void) -LLVMPY_AddInternalizePass(LLVMPassManagerRef PM) { - unwrap(PM)->add(createInternalizePass()); +API_EXPORT(LLVMFunctionPassManagerRef) +LLVMPY_CreateNewFunctionPassManager() { + return llvm::wrap(new PassManager()); } API_EXPORT(void) -LLVMPY_AddJumpThreadingPass(LLVMPassManagerRef PM, int threshold) { - unwrap(PM)->add(createJumpThreadingPass(threshold)); -} +LLVMPY_RunFunctionPassManager(LLVMFunctionPassManagerRef FPMRef, + LLVMPassBuilderRef PBRef, LLVMValueRef FRef) { -API_EXPORT(void) -LLVMPY_AddLCSSAPass(LLVMPassManagerRef PM) { - unwrap(PM)->add(createLCSSAPass()); -} + FunctionPassManager *FPM = llvm::unwrap(FPMRef); + PassBuilder *PB = llvm::unwrap(PBRef); + Function *F = reinterpret_cast(FRef); -API_EXPORT(void) -LLVMPY_AddLoopDeletionPass(LLVMPassManagerRef PM) { - unwrap(PM)->add(createLoopDeletionPass()); + LoopAnalysisManager LAM; + FunctionAnalysisManager FAM; + CGSCCAnalysisManager CGAM; + ModuleAnalysisManager MAM; + PB->registerLoopAnalyses(LAM); + PB->registerFunctionAnalyses(FAM); + PB->registerCGSCCAnalyses(CGAM); + PB->registerModuleAnalyses(MAM); + PB->crossRegisterProxies(LAM, FAM, CGAM, MAM); + FPM->run(*F, FAM); } API_EXPORT(void) -LLVMPY_AddLoopExtractorPass(LLVMPassManagerRef PM) { - unwrap(PM)->add(createLoopExtractorPass()); +LLVMPY_AddAAEvalPass_function(LLVMFunctionPassManagerRef FPM) { + llvm::unwrap(FPM)->addPass(AAEvaluator()); } API_EXPORT(void) -LLVMPY_AddSingleLoopExtractorPass(LLVMPassManagerRef PM) { - unwrap(PM)->add(createSingleLoopExtractorPass()); +LLVMPY_AddSimplifyCFGPass_function(LLVMFunctionPassManagerRef FPM) { + llvm::unwrap(FPM)->addPass(SimplifyCFGPass()); } API_EXPORT(void) -LLVMPY_AddLoopStrengthReducePass(LLVMPassManagerRef PM) { - unwrap(PM)->add(createLoopStrengthReducePass()); +LLVMPY_AddLoopUnrollPass_function(LLVMFunctionPassManagerRef FPM) { + llvm::unwrap(FPM)->addPass(LoopUnrollPass()); } API_EXPORT(void) -LLVMPY_AddLoopSimplificationPass(LLVMPassManagerRef PM) { - unwrap(PM)->add(createLoopSimplifyPass()); +LLVMPY_LLVMAddLoopRotatePass_function(LLVMFunctionPassManagerRef FPM) { + llvm::unwrap(FPM)->addPass( + createFunctionToLoopPassAdaptor(LoopRotatePass())); } API_EXPORT(void) -LLVMPY_AddLoopUnrollPass(LLVMPassManagerRef PM) { LLVMAddLoopUnrollPass(PM); } - -API_EXPORT(void) -LLVMPY_AddLoopUnrollAndJamPass(LLVMPassManagerRef PM) { - LLVMAddLoopUnrollAndJamPass(PM); +LLVMPY_LLVMAddInstructionCombinePass_function(LLVMFunctionPassManagerRef FPM) { + llvm::unwrap(FPM)->addPass(InstCombinePass()); } API_EXPORT(void) -LLVMPY_AddLoopUnswitchPass(LLVMPassManagerRef PM, bool optimizeForSize, - bool hasBranchDivergence) { -#if LLVM_VERSION_MAJOR > 14 - unwrap(PM)->add(createSimpleLoopUnswitchLegacyPass(optimizeForSize)); -#else - unwrap(PM)->add( - createLoopUnswitchPass(optimizeForSize, hasBranchDivergence)); -#endif +LLVMPY_AddJumpThreadingPass_function(LLVMFunctionPassManagerRef FPM, int T) { + llvm::unwrap(FPM)->addPass(JumpThreadingPass(T)); } API_EXPORT(void) -LLVMPY_AddLowerAtomicPass(LLVMPassManagerRef PM) { - unwrap(PM)->add(createLowerAtomicPass()); +LLVMPY_DisposeNewFunctionPassManger(LLVMFunctionPassManagerRef FPM) { + delete llvm::unwrap(FPM); } -API_EXPORT(void) -LLVMPY_AddLowerInvokePass(LLVMPassManagerRef PM) { - unwrap(PM)->add(createLowerInvokePass()); -} +// PTO -API_EXPORT(void) -LLVMPY_AddLowerSwitchPass(LLVMPassManagerRef PM) { - unwrap(PM)->add(createLowerSwitchPass()); +API_EXPORT(LLVMPipelineTuningOptionsRef) +LLVMPY_CreatePipelineTuningOptions() { + return llvm::wrap(new PipelineTuningOptions()); } -API_EXPORT(void) -LLVMPY_AddMemCpyOptimizationPass(LLVMPassManagerRef PM) { - unwrap(PM)->add(createMemCpyOptPass()); +API_EXPORT(bool) +LLVMPY_PTOGetLoopInterleaving(LLVMPipelineTuningOptionsRef PTO) { + return llvm::unwrap(PTO)->LoopInterleaving; } API_EXPORT(void) -LLVMPY_AddMergeFunctionsPass(LLVMPassManagerRef PM) { - unwrap(PM)->add(createMergeFunctionsPass()); +LLVMPY_PTOSetLoopInterleaving(LLVMPipelineTuningOptionsRef PTO, bool value) { + llvm::unwrap(PTO)->LoopInterleaving = value; } -API_EXPORT(void) -LLVMPY_AddMergeReturnsPass(LLVMPassManagerRef PM) { - unwrap(PM)->add(createUnifyFunctionExitNodesPass()); +API_EXPORT(bool) +LLVMPY_PTOGetLoopVectorization(LLVMPipelineTuningOptionsRef PTO) { + return llvm::unwrap(PTO)->LoopVectorization; } API_EXPORT(void) -LLVMPY_AddPartialInliningPass(LLVMPassManagerRef PM) { - unwrap(PM)->add(createPartialInliningPass()); +LLVMPY_PTOSetLoopVectorization(LLVMPipelineTuningOptionsRef PTO, bool value) { + llvm::unwrap(PTO)->LoopVectorization = value; } -API_EXPORT(void) -LLVMPY_AddPruneExceptionHandlingPass(LLVMPassManagerRef PM) { - unwrap(PM)->add(createPruneEHPass()); +API_EXPORT(bool) +LLVMPY_PTOGetSLPVectorization(LLVMPipelineTuningOptionsRef PTO) { + return llvm::unwrap(PTO)->SLPVectorization; } API_EXPORT(void) -LLVMPY_AddReassociatePass(LLVMPassManagerRef PM) { - unwrap(PM)->add(createReassociatePass()); +LLVMPY_PTOSetSLPVectorization(LLVMPipelineTuningOptionsRef PTO, bool value) { + llvm::unwrap(PTO)->SLPVectorization = value; } -API_EXPORT(void) -LLVMPY_AddDemoteRegisterToMemoryPass(LLVMPassManagerRef PM) { - unwrap(PM)->add(createDemoteRegisterToMemoryPass()); +API_EXPORT(bool) +LLVMPY_PTOGetLoopUnrolling(LLVMPipelineTuningOptionsRef PTO) { + return llvm::unwrap(PTO)->LoopUnrolling; } API_EXPORT(void) -LLVMPY_AddSinkPass(LLVMPassManagerRef PM) { - unwrap(PM)->add(createSinkingPass()); +LLVMPY_PTOSetLoopUnrolling(LLVMPipelineTuningOptionsRef PTO, bool value) { + llvm::unwrap(PTO)->LoopUnrolling = value; } -API_EXPORT(void) -LLVMPY_AddStripSymbolsPass(LLVMPassManagerRef PM, bool onlyDebugInfo) { - unwrap(PM)->add(createStripSymbolsPass(onlyDebugInfo)); -} +// FIXME: Available from llvm16 +// API_EXPORT(int) +// LLVMPY_PTOGetInlinerThreshold(LLVMPipelineTuningOptionsRef PTO) { +// return llvm::unwrap(PTO)->InlinerThreshold; +// } -API_EXPORT(void) -LLVMPY_AddStripDeadDebugInfoPass(LLVMPassManagerRef PM) { - unwrap(PM)->add(createStripDeadDebugInfoPass()); -} +// API_EXPORT(void) +// LLVMPY_PTOSetInlinerThreshold(LLVMPipelineTuningOptionsRef PTO, bool value) { +// llvm::unwrap(PTO)->InlinerThreshold = value; +// } API_EXPORT(void) -LLVMPY_AddStripDeadPrototypesPass(LLVMPassManagerRef PM) { - unwrap(PM)->add(createStripDeadPrototypesPass()); +LLVMPY_DisposePipelineTuningOptions(LLVMPipelineTuningOptionsRef PTO) { + delete llvm::unwrap(PTO); } -API_EXPORT(void) -LLVMPY_AddStripDebugDeclarePrototypesPass(LLVMPassManagerRef PM) { - unwrap(PM)->add(createStripDebugDeclarePass()); -} +// PB -API_EXPORT(void) -LLVMPY_AddStripNondebugSymbolsPass(LLVMPassManagerRef PM) { - unwrap(PM)->add(createStripNonDebugSymbolsPass()); +API_EXPORT(LLVMPassBuilderRef) +LLVMPY_CreatePassBuilder(LLVMTargetMachineRef TM, + LLVMPipelineTuningOptionsRef PTO) { + TargetMachine *target = llvm::unwrap(TM); + PipelineTuningOptions *pt = llvm::unwrap(PTO); + return llvm::wrap(new PassBuilder(target, *pt)); } -API_EXPORT(void) -LLVMPY_AddTailCallEliminationPass(LLVMPassManagerRef PM) { - unwrap(PM)->add(createTailCallEliminationPass()); +static OptimizationLevel mapLevel(int speed_level, int size_level) { + switch (size_level) { + case 0: + switch (speed_level) { + case 0: + return OptimizationLevel::O0; + case 1: + return OptimizationLevel::O1; + case 2: + return OptimizationLevel::O2; + case 3: + return OptimizationLevel::O3; + default: + llvm_unreachable("Invalid optimization level"); + } + case 1: + if (speed_level == 1) + return OptimizationLevel::Os; + llvm_unreachable("Invalid optimization level for size level 1"); + case 2: + if (speed_level == 2) + return OptimizationLevel::Oz; + llvm_unreachable("Invalid optimization level for size level 2"); + default: + llvm_unreachable("Invalid size level"); + break; + } } -API_EXPORT(void) -LLVMPY_AddCFGSimplificationPass(LLVMPassManagerRef PM) { - LLVMAddCFGSimplificationPass(PM); -} +API_EXPORT(LLVMModulePassManagerRef) +LLVMPY_buildPerModuleDefaultPipeline(LLVMPassBuilderRef PBref, int speed_level, + int size_level) { -API_EXPORT(void) -LLVMPY_AddGVNPass(LLVMPassManagerRef PM) { LLVMAddGVNPass(PM); } + PassBuilder *PB = llvm::unwrap(PBref); + OptimizationLevel OL = mapLevel(speed_level, size_level); + if (OL == OptimizationLevel::O0) { + return llvm::wrap( + new ModulePassManager(PB->buildO0DefaultPipeline(OL))); + } -API_EXPORT(void) -LLVMPY_AddInstructionCombiningPass(LLVMPassManagerRef PM) { - LLVMAddInstructionCombiningPass(PM); + return llvm::wrap( + new ModulePassManager(PB->buildPerModuleDefaultPipeline(OL))); } -API_EXPORT(void) -LLVMPY_AddLICMPass(LLVMPassManagerRef PM) { LLVMAddLICMPass(PM); } - -API_EXPORT(void) -LLVMPY_AddSCCPPass(LLVMPassManagerRef PM) { LLVMAddSCCPPass(PM); } - -API_EXPORT(void) -LLVMPY_AddSROAPass(LLVMPassManagerRef PM) { unwrap(PM)->add(createSROAPass()); } - -API_EXPORT(void) -LLVMPY_AddTypeBasedAliasAnalysisPass(LLVMPassManagerRef PM) { - LLVMAddTypeBasedAliasAnalysisPass(PM); -} +API_EXPORT(LLVMFunctionPassManagerRef) +LLVMPY_buildFunctionSimplificationPipeline(LLVMPassBuilderRef PBref, + int speed_level, int size_level) { -API_EXPORT(void) -LLVMPY_AddBasicAliasAnalysisPass(LLVMPassManagerRef PM) { - LLVMAddBasicAliasAnalysisPass(PM); -} + PassBuilder *PB = llvm::unwrap(PBref); + OptimizationLevel OL = mapLevel(speed_level, size_level); + if (OL == OptimizationLevel::O0) + return llvm::wrap(new FunctionPassManager()); -API_EXPORT(void) -LLVMPY_LLVMAddLoopRotatePass(LLVMPassManagerRef PM) { - LLVMAddLoopRotatePass(PM); + FunctionPassManager *FPM = new FunctionPassManager( + PB->buildFunctionSimplificationPipeline(OL, ThinOrFullLTOPhase::None)); + return llvm::wrap(FPM); } API_EXPORT(void) -LLVMPY_AddInstructionNamerPass(LLVMPassManagerRef PM) { - unwrap(PM)->add(createInstructionNamerPass()); -} +LLVMPY_DisposePassBuilder(LLVMPassBuilderRef PB) { delete llvm::unwrap(PB); } } // end extern "C" diff --git a/ffi/transforms.cpp b/ffi/transforms.cpp deleted file mode 100644 index 8d6d7f391..000000000 --- a/ffi/transforms.cpp +++ /dev/null @@ -1,96 +0,0 @@ -#include "core.h" -#include "llvm-c/Target.h" -#include "llvm-c/Transforms/PassManagerBuilder.h" -#include "llvm/Transforms/IPO/PassManagerBuilder.h" - -extern "C" { - -API_EXPORT(LLVMPassManagerBuilderRef) -LLVMPY_PassManagerBuilderCreate() { return LLVMPassManagerBuilderCreate(); } - -API_EXPORT(void) -LLVMPY_PassManagerBuilderDispose(LLVMPassManagerBuilderRef PMB) { - LLVMPassManagerBuilderDispose(PMB); -} - -API_EXPORT(void) -LLVMPY_PassManagerBuilderPopulateModulePassManager( - LLVMPassManagerBuilderRef PMB, LLVMPassManagerRef PM) { - LLVMPassManagerBuilderPopulateModulePassManager(PMB, PM); -} - -API_EXPORT(unsigned) -LLVMPY_PassManagerBuilderGetOptLevel(LLVMPassManagerBuilderRef PMB) { - llvm::PassManagerBuilder *pmb = llvm::unwrap(PMB); - return pmb->OptLevel; -} - -API_EXPORT(void) -LLVMPY_PassManagerBuilderSetOptLevel(LLVMPassManagerBuilderRef PMB, - unsigned OptLevel) { - LLVMPassManagerBuilderSetOptLevel(PMB, OptLevel); -} - -API_EXPORT(unsigned) -LLVMPY_PassManagerBuilderGetSizeLevel(LLVMPassManagerBuilderRef PMB) { - llvm::PassManagerBuilder *pmb = llvm::unwrap(PMB); - return pmb->SizeLevel; -} - -API_EXPORT(void) -LLVMPY_PassManagerBuilderSetSizeLevel(LLVMPassManagerBuilderRef PMB, - unsigned SizeLevel) { - LLVMPassManagerBuilderSetSizeLevel(PMB, SizeLevel); -} - -API_EXPORT(int) -LLVMPY_PassManagerBuilderGetDisableUnrollLoops(LLVMPassManagerBuilderRef PMB) { - llvm::PassManagerBuilder *pmb = llvm::unwrap(PMB); - return pmb->DisableUnrollLoops; -} - -API_EXPORT(void) -LLVMPY_PassManagerBuilderSetDisableUnrollLoops(LLVMPassManagerBuilderRef PMB, - LLVMBool Value) { - LLVMPassManagerBuilderSetDisableUnrollLoops(PMB, Value); -} - -API_EXPORT(void) -LLVMPY_PassManagerBuilderUseInlinerWithThreshold(LLVMPassManagerBuilderRef PMB, - unsigned Threshold) { - LLVMPassManagerBuilderUseInlinerWithThreshold(PMB, Threshold); -} - -API_EXPORT(void) -LLVMPY_PassManagerBuilderPopulateFunctionPassManager( - LLVMPassManagerBuilderRef PMB, LLVMPassManagerRef PM) { - LLVMPassManagerBuilderPopulateFunctionPassManager(PMB, PM); -} - -API_EXPORT(void) -LLVMPY_PassManagerBuilderSetLoopVectorize(LLVMPassManagerBuilderRef PMB, - int Value) { - llvm::PassManagerBuilder *pmb = llvm::unwrap(PMB); - pmb->LoopVectorize = Value; -} - -API_EXPORT(int) -LLVMPY_PassManagerBuilderGetLoopVectorize(LLVMPassManagerBuilderRef PMB) { - llvm::PassManagerBuilder *pmb = llvm::unwrap(PMB); - return pmb->LoopVectorize; -} - -API_EXPORT(void) -LLVMPY_PassManagerBuilderSetSLPVectorize(LLVMPassManagerBuilderRef PMB, - int Value) { - llvm::PassManagerBuilder *pmb = llvm::unwrap(PMB); - pmb->SLPVectorize = Value; -} - -API_EXPORT(int) -LLVMPY_PassManagerBuilderGetSLPVectorize(LLVMPassManagerBuilderRef PMB) { - llvm::PassManagerBuilder *pmb = llvm::unwrap(PMB); - return pmb->SLPVectorize; -} - -} // end extern "C" diff --git a/llvmlite/binding/__init__.py b/llvmlite/binding/__init__.py index 76f498e6f..3fc1e48e0 100644 --- a/llvmlite/binding/__init__.py +++ b/llvmlite/binding/__init__.py @@ -7,13 +7,12 @@ from .linker import * from .module import * from .options import * -from .newpassmangers import * -from .passmanagers import * +from .legacypassmanagers import * from .targets import * -from .transforms import * from .value import * from .typeref import * from .analysis import * from .object_file import * from .context import * from .orcjit import * +from .passmanagers import * diff --git a/llvmlite/binding/legacypassmanagers.py b/llvmlite/binding/legacypassmanagers.py new file mode 100644 index 000000000..244e080db --- /dev/null +++ b/llvmlite/binding/legacypassmanagers.py @@ -0,0 +1,1088 @@ +from ctypes import (c_bool, c_char_p, c_int, c_size_t, c_uint, Structure, byref, + POINTER) +from collections import namedtuple +from enum import IntFlag +from llvmlite.binding import ffi +from llvmlite.binding.initfini import llvm_version_info +import os +from tempfile import mkstemp +from llvmlite.binding.common import _encode_string + +_prunestats = namedtuple('PruneStats', + ('basicblock diamond fanout fanout_raise')) + +llvm_version_major = llvm_version_info[0] + + +class PruneStats(_prunestats): + """ Holds statistics from reference count pruning. + """ + + def __add__(self, other): + if not isinstance(other, PruneStats): + msg = 'PruneStats can only be added to another PruneStats, got {}.' + raise TypeError(msg.format(type(other))) + return PruneStats(self.basicblock + other.basicblock, + self.diamond + other.diamond, + self.fanout + other.fanout, + self.fanout_raise + other.fanout_raise) + + def __sub__(self, other): + if not isinstance(other, PruneStats): + msg = ('PruneStats can only be subtracted from another PruneStats, ' + 'got {}.') + raise TypeError(msg.format(type(other))) + return PruneStats(self.basicblock - other.basicblock, + self.diamond - other.diamond, + self.fanout - other.fanout, + self.fanout_raise - other.fanout_raise) + + +class _c_PruneStats(Structure): + _fields_ = [ + ('basicblock', c_size_t), + ('diamond', c_size_t), + ('fanout', c_size_t), + ('fanout_raise', c_size_t)] + + +def dump_refprune_stats(printout=False): + """ Returns a namedtuple containing the current values for the refop pruning + statistics. If kwarg `printout` is True the stats are printed to stderr, + default is False. + """ + + stats = _c_PruneStats(0, 0, 0, 0) + do_print = c_bool(printout) + + ffi.lib.LLVMPY_DumpRefPruneStats(byref(stats), do_print) + return PruneStats(stats.basicblock, stats.diamond, stats.fanout, + stats.fanout_raise) + + +def set_time_passes(enable): + """Enable or disable the pass timers. + + Parameters + ---------- + enable : bool + Set to True to enable the pass timers. + Set to False to disable the pass timers. + """ + ffi.lib.LLVMPY_SetTimePasses(c_bool(enable)) + + +def report_and_reset_timings(): + """Returns the pass timings report and resets the LLVM internal timers. + + Pass timers are enabled by ``set_time_passes()``. If the timers are not + enabled, this function will return an empty string. + + Returns + ------- + res : str + LLVM generated timing report. + """ + with ffi.OutputString() as buf: + ffi.lib.LLVMPY_ReportAndResetTimings(buf) + return str(buf) + + +def create_module_pass_manager(): + return LegacyModulePassManager() + + +def create_function_pass_manager(module): + return LegacyFunctionPassManager(module) + + +class RefPruneSubpasses(IntFlag): + PER_BB = 0b0001 # noqa: E221 + DIAMOND = 0b0010 # noqa: E221 + FANOUT = 0b0100 # noqa: E221 + FANOUT_RAISE = 0b1000 + ALL = PER_BB | DIAMOND | FANOUT | FANOUT_RAISE + + +class LegacyPassManager(ffi.ObjectRef): + """LegacyPassManager + """ + + def _dispose(self): + self._capi.LLVMPY_DisposeLegacyPassManager(self) + + def add_aa_eval_pass(self): + """ + See https://llvm.org/docs/Passes.html#aa-eval-exhaustive-alias-analysis-precision-evaluator + + LLVM 14: `llvm::createAAEvalPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddAAEvalPass(self) + + def add_basic_aa_pass(self): + """ + See https://llvm.org/docs/Passes.html#basic-aa-basic-alias-analysis-stateless-aa-impl + + LLVM 14: `llvm::createBasicAAWrapperPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddBasicAAWrapperPass(self) + + def add_constant_merge_pass(self): + """ + See http://llvm.org/docs/Passes.html#constmerge-merge-duplicate-global-constants + + LLVM 14: `LLVMAddConstantMergePass` + """ # noqa E501 + ffi.lib.LLVMPY_AddConstantMergePass(self) + + def add_dead_arg_elimination_pass(self): + """ + See http://llvm.org/docs/Passes.html#deadargelim-dead-argument-elimination + + LLVM 14: `LLVMAddDeadArgEliminationPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddDeadArgEliminationPass(self) + + def add_dependence_analysis_pass(self): + """ + See https://llvm.org/docs/Passes.html#da-dependence-analysis + + LLVM 14: `llvm::createDependenceAnalysisWrapperPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddDependenceAnalysisPass(self) + + def add_dot_call_graph_pass(self): + """ + See https://llvm.org/docs/Passes.html#dot-callgraph-print-call-graph-to-dot-file + + LLVM 14: `llvm::createCallGraphDOTPrinterPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddCallGraphDOTPrinterPass(self) + + def add_dot_cfg_printer_pass(self): + """ + See https://llvm.org/docs/Passes.html#dot-cfg-print-cfg-of-function-to-dot-file + + LLVM 14: `llvm::createCFGPrinterLegacyPassPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddCFGPrinterPass(self) + + def add_dot_dom_printer_pass(self, show_body=False): + """ + See https://llvm.org/docs/Passes.html#dot-dom-print-dominance-tree-of-function-to-dot-file + + LLVM 14: `llvm::createDomPrinterPass` and `llvm::createDomOnlyPrinterPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddDotDomPrinterPass(self, show_body) + + def add_dot_postdom_printer_pass(self, show_body=False): + """ + See https://llvm.org/docs/Passes.html#dot-postdom-print-postdominance-tree-of-function-to-dot-file + + LLVM 14: `llvm::createPostDomPrinterPass` and `llvm::createPostDomOnlyPrinterPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddDotPostDomPrinterPass(self, show_body) + + def add_globals_mod_ref_aa_pass(self): + """ + See https://llvm.org/docs/Passes.html#globalsmodref-aa-simple-mod-ref-analysis-for-globals + + LLVM 14: `llvm::createGlobalsAAWrapperPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddGlobalsModRefAAPass(self) + + def add_iv_users_pass(self): + """ + See https://llvm.org/docs/Passes.html#iv-users-induction-variable-users + + LLVM 14: `llvm::createIVUsersPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddIVUsersPass(self) + + def add_lint_pass(self): + """ + See https://llvm.org/docs/Passes.html#lint-statically-lint-checks-llvm-ir + + LLVM 14: `llvm::createLintLegacyPassPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddLintPass(self) + + def add_lazy_value_info_pass(self): + """ + See https://llvm.org/docs/Passes.html#lazy-value-info-lazy-value-information-analysis + + LLVM 14: `llvm::createLazyValueInfoPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddLazyValueInfoPass(self) + + def add_module_debug_info_pass(self): + """ + See https://llvm.org/docs/Passes.html#module-debuginfo-decodes-module-level-debug-info + + LLVM 14: `llvm::createModuleDebugInfoPrinterPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddModuleDebugInfoPrinterPass(self) + + def add_region_info_pass(self): + """ + See https://llvm.org/docs/Passes.html#regions-detect-single-entry-single-exit-regions + + LLVM 14: `llvm::createRegionInfoPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddRegionInfoPass(self) + + def add_scalar_evolution_aa_pass(self): + """ + See https://llvm.org/docs/Passes.html#scev-aa-scalarevolution-based-alias-analysis + + LLVM 14: `llvm::createSCEVAAWrapperPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddScalarEvolutionAAPass(self) + + def add_aggressive_dead_code_elimination_pass(self): + """ + See https://llvm.org/docs/Passes.html#adce-aggressive-dead-code-elimination + + LLVM 14: `llvm::createAggressiveDCEPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddAggressiveDCEPass(self) + + def add_always_inliner_pass(self, insert_lifetime=True): + """ + See https://llvm.org/docs/Passes.html#always-inline-inliner-for-always-inline-functions + + LLVM 14: `llvm::createAlwaysInlinerLegacyPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddAlwaysInlinerPass(self, insert_lifetime) + + def add_arg_promotion_pass(self, max_elements=3): + """ + See https://llvm.org/docs/Passes.html#argpromotion-promote-by-reference-arguments-to-scalars + + LLVM 14: `llvm::createArgumentPromotionPass` + """ # noqa E501 + if llvm_version_major > 14: + raise RuntimeError('ArgumentPromotionPass unavailable in LLVM > 14') + ffi.lib.LLVMPY_AddArgPromotionPass(self, max_elements) + + def add_break_critical_edges_pass(self): + """ + See https://llvm.org/docs/Passes.html#break-crit-edges-break-critical-edges-in-cfg + + LLVM 14: `llvm::createBreakCriticalEdgesPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddBreakCriticalEdgesPass(self) + + def add_dead_store_elimination_pass(self): + """ + See https://llvm.org/docs/Passes.html#dse-dead-store-elimination + + LLVM 14: `llvm::createDeadStoreEliminationPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddDeadStoreEliminationPass(self) + + def add_reverse_post_order_function_attrs_pass(self): + """ + See https://llvm.org/docs/Passes.html#function-attrs-deduce-function-attributes + + LLVM 14: `llvm::createReversePostOrderFunctionAttrsPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddReversePostOrderFunctionAttrsPass(self) + + def add_function_attrs_pass(self): + """ + See http://llvm.org/docs/Passes.html#functionattrs-deduce-function-attributes + + LLVM 14: `LLVMAddFunctionAttrsPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddFunctionAttrsPass(self) + + def add_function_inlining_pass(self, threshold): + """ + See http://llvm.org/docs/Passes.html#inline-function-integration-inlining + + LLVM 14: `createFunctionInliningPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddFunctionInliningPass(self, threshold) + + def add_global_dce_pass(self): + """ + See http://llvm.org/docs/Passes.html#globaldce-dead-global-elimination + + LLVM 14: `LLVMAddGlobalDCEPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddGlobalDCEPass(self) + + def add_global_optimizer_pass(self): + """ + See http://llvm.org/docs/Passes.html#globalopt-global-variable-optimizer + + LLVM 14: `LLVMAddGlobalOptimizerPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddGlobalOptimizerPass(self) + + def add_ipsccp_pass(self): + """ + See http://llvm.org/docs/Passes.html#ipsccp-interprocedural-sparse-conditional-constant-propagation + + LLVM 14: `LLVMAddIPSCCPPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddIPSCCPPass(self) + + def add_dead_code_elimination_pass(self): + """ + See http://llvm.org/docs/Passes.html#dce-dead-code-elimination + LLVM 14: `llvm::createDeadCodeEliminationPass` + """ + ffi.lib.LLVMPY_AddDeadCodeEliminationPass(self) + + def add_aggressive_instruction_combining_pass(self): + """ + See https://llvm.org/docs/Passes.html#aggressive-instcombine-combine-expression-patterns + + LLVM 14: `llvm::createAggressiveInstCombinerPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddAggressiveInstructionCombiningPass(self) + + def add_internalize_pass(self): + """ + See https://llvm.org/docs/Passes.html#internalize-internalize-global-symbols + + LLVM 14: `llvm::createInternalizePass` + """ # noqa E501 + ffi.lib.LLVMPY_AddInternalizePass(self) + + def add_cfg_simplification_pass(self): + """ + See http://llvm.org/docs/Passes.html#simplifycfg-simplify-the-cfg + + LLVM 14: `LLVMAddCFGSimplificationPass` + """ + ffi.lib.LLVMPY_AddCFGSimplificationPass(self) + + def add_jump_threading_pass(self, threshold=-1): + """ + See https://llvm.org/docs/Passes.html#jump-threading-jump-threading + + LLVM 14: `llvm::createJumpThreadingPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddJumpThreadingPass(self, threshold) + + def add_lcssa_pass(self): + """ + See https://llvm.org/docs/Passes.html#lcssa-loop-closed-ssa-form-pass + + LLVM 14: `llvm::createLCSSAPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddLCSSAPass(self) + + def add_gvn_pass(self): + """ + See http://llvm.org/docs/Passes.html#gvn-global-value-numbering + + LLVM 14: `LLVMAddGVNPass` + """ + ffi.lib.LLVMPY_AddGVNPass(self) + + def add_instruction_combining_pass(self): + """ + See http://llvm.org/docs/Passes.html#passes-instcombine + + LLVM 14: `LLVMAddInstructionCombiningPass` + """ + ffi.lib.LLVMPY_AddInstructionCombiningPass(self) + + def add_licm_pass(self): + """ + See http://llvm.org/docs/Passes.html#licm-loop-invariant-code-motion + + LLVM 14: `LLVMAddLICMPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddLICMPass(self) + + def add_loop_deletion_pass(self): + """ + See https://llvm.org/docs/Passes.html#loop-deletion-delete-dead-loops + + LLVM 14: `llvm::createLoopDeletionPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddLoopDeletionPass(self) + + def add_loop_extractor_pass(self): + """ + See https://llvm.org/docs/Passes.html#loop-extract-extract-loops-into-new-functions + + LLVM 14: `llvm::createLoopExtractorPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddLoopExtractorPass(self) + + def add_single_loop_extractor_pass(self): + """ + See https://llvm.org/docs/Passes.html#loop-extract-single-extract-at-most-one-loop-into-a-new-function + + LLVM 14: `llvm::createSingleLoopExtractorPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddSingleLoopExtractorPass(self) + + def add_sccp_pass(self): + """ + See http://llvm.org/docs/Passes.html#sccp-sparse-conditional-constant-propagation + + LLVM 14: `LLVMAddSCCPPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddSCCPPass(self) + + def add_loop_strength_reduce_pass(self): + """ + See https://llvm.org/docs/Passes.html#loop-reduce-loop-strength-reduction + + LLVM 14: `llvm::createLoopStrengthReducePass` + """ # noqa E501 + ffi.lib.LLVMPY_AddLoopStrengthReducePass(self) + + def add_loop_simplification_pass(self): + """ + See https://llvm.org/docs/Passes.html#loop-simplify-canonicalize-natural-loops + + LLVM 14: `llvm::createLoopSimplifyPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddLoopSimplificationPass(self) + + def add_loop_unroll_pass(self): + """ + See https://llvm.org/docs/Passes.html#loop-unroll-unroll-loops + + LLVM 14: `LLVMAddLoopUnrollPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddLoopUnrollPass(self) + + def add_loop_unroll_and_jam_pass(self): + """ + See https://llvm.org/docs/Passes.html#loop-unroll-and-jam-unroll-and-jam-loops + + LLVM 14: `LLVMAddLoopUnrollAndJamPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddLoopUnrollAndJamPass(self) + + def add_loop_unswitch_pass(self, + optimize_for_size=False, + has_branch_divergence=False): + """ + See https://llvm.org/docs/Passes.html#loop-unswitch-unswitch-loops + + LLVM 14: `llvm::createLoopUnswitchPass` + LLVM 15: `llvm::createSimpleLoopUnswitchLegacyPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddLoopUnswitchPass(self, optimize_for_size, + has_branch_divergence) + + def add_lower_atomic_pass(self): + """ + See https://llvm.org/docs/Passes.html#loweratomic-lower-atomic-intrinsics-to-non-atomic-form + + LLVM 14: `llvm::createLowerAtomicPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddLowerAtomicPass(self) + + def add_lower_invoke_pass(self): + """ + See https://llvm.org/docs/Passes.html#lowerinvoke-lower-invokes-to-calls-for-unwindless-code-generators + + LLVM 14: `llvm::createLowerInvokePass` + """ # noqa E501 + ffi.lib.LLVMPY_AddLowerInvokePass(self) + + def add_lower_switch_pass(self): + """ + See https://llvm.org/docs/Passes.html#lowerswitch-lower-switchinsts-to-branches + + LLVM 14: `llvm::createLowerSwitchPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddLowerSwitchPass(self) + + def add_memcpy_optimization_pass(self): + """ + See https://llvm.org/docs/Passes.html#memcpyopt-memcpy-optimization + + LLVM 14: `llvm::createMemCpyOptPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddMemCpyOptimizationPass(self) + + def add_merge_functions_pass(self): + """ + See https://llvm.org/docs/Passes.html#mergefunc-merge-functions + + LLVM 14: `llvm::createMergeFunctionsPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddMergeFunctionsPass(self) + + def add_merge_returns_pass(self): + """ + See https://llvm.org/docs/Passes.html#mergereturn-unify-function-exit-nodes + + LLVM 14: `llvm::createUnifyFunctionExitNodesPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddMergeReturnsPass(self) + + def add_partial_inlining_pass(self): + """ + See https://llvm.org/docs/Passes.html#partial-inliner-partial-inliner + + LLVM 14: `llvm::createPartialInliningPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddPartialInliningPass(self) + + def add_prune_exception_handling_pass(self): + """ + See https://llvm.org/docs/Passes.html#prune-eh-remove-unused-exception-handling-info + + LLVM 14: `llvm::createPruneEHPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddPruneExceptionHandlingPass(self) + + def add_reassociate_expressions_pass(self): + """ + See https://llvm.org/docs/Passes.html#reassociate-reassociate-expressions + + LLVM 14: `llvm::createReassociatePass` + """ # noqa E501 + ffi.lib.LLVMPY_AddReassociatePass(self) + + def add_demote_register_to_memory_pass(self): + """ + See https://llvm.org/docs/Passes.html#rel-lookup-table-converter-relative-lookup-table-converter + + LLVM 14: `llvm::createDemoteRegisterToMemoryPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddDemoteRegisterToMemoryPass(self) + + def add_sroa_pass(self): + """ + See http://llvm.org/docs/Passes.html#scalarrepl-scalar-replacement-of-aggregates-dt + Note that this pass corresponds to the ``opt -sroa`` command-line option, + despite the link above. + + LLVM 14: `llvm::createSROAPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddSROAPass(self) + + def add_sink_pass(self): + """ + See https://llvm.org/docs/Passes.html#sink-code-sinking + + LLVM 14: `llvm::createSinkingPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddSinkPass(self) + + def add_strip_symbols_pass(self, only_debug=False): + """ + See https://llvm.org/docs/Passes.html#strip-strip-all-symbols-from-a-module + + LLVM 14: `llvm::createStripSymbolsPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddStripSymbolsPass(self, only_debug) + + def add_strip_dead_debug_info_pass(self): + """ + See https://llvm.org/docs/Passes.html#strip-dead-debug-info-strip-debug-info-for-unused-symbols + + LLVM 14: `llvm::createStripDeadDebugInfoPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddStripDeadDebugInfoPass(self) + + def add_strip_dead_prototypes_pass(self): + """ + See https://llvm.org/docs/Passes.html#strip-dead-prototypes-strip-unused-function-prototypes + + LLVM 14: `llvm::createStripDeadPrototypesPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddStripDeadPrototypesPass(self) + + def add_strip_debug_declare_pass(self): + """ + See https://llvm.org/docs/Passes.html#strip-debug-declare-strip-all-llvm-dbg-declare-intrinsics + + LLVM 14: `llvm::createStripDebugDeclarePass` + """ # noqa E501 + ffi.lib.LLVMPY_AddStripDebugDeclarePrototypesPass(self) + + def add_strip_nondebug_symbols_pass(self): + """ + See https://llvm.org/docs/Passes.html#strip-nondebug-strip-all-symbols-except-dbg-symbols-from-a-module + + LLVM 14: `llvm::createStripNonDebugSymbolsPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddStripNondebugSymbolsPass(self) + + def add_tail_call_elimination_pass(self): + """ + See https://llvm.org/docs/Passes.html#tailcallelim-tail-call-elimination + + LLVM 14: `llvm::createTailCallEliminationPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddTailCallEliminationPass(self) + + def add_type_based_alias_analysis_pass(self): + """ + LLVM 14: `LLVMAddTypeBasedAliasAnalysisPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddTypeBasedAliasAnalysisPass(self) + + def add_basic_alias_analysis_pass(self): + """ + See http://llvm.org/docs/AliasAnalysis.html#the-basicaa-pass + + LLVM 14: `LLVMAddBasicAliasAnalysisPass` + """ + ffi.lib.LLVMPY_AddBasicAliasAnalysisPass(self) + + def add_loop_rotate_pass(self): + """http://llvm.org/docs/Passes.html#loop-rotate-rotate-loops.""" + ffi.lib.LLVMPY_LLVMAddLoopRotatePass(self) + + def add_target_library_info(self, triple): + ffi.lib.LLVMPY_AddTargetLibraryInfoPass(self, _encode_string(triple)) + + def add_instruction_namer_pass(self): + """ + See https://llvm.org/docs/Passes.html#instnamer-assign-names-to-anonymous-instructions. + + LLVM 14: `llvm::createInstructionNamerPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddInstructionNamerPass(self) + + # Non-standard LLVM passes + + def add_refprune_pass(self, subpasses_flags=RefPruneSubpasses.ALL, + subgraph_limit=1000): + """Add Numba specific Reference count pruning pass. + + Parameters + ---------- + subpasses_flags : RefPruneSubpasses + A bitmask to control the subpasses to be enabled. + subgraph_limit : int + Limit the fanout pruners to working on a subgraph no bigger than + this number of basic-blocks to avoid spending too much time in very + large graphs. Default is 1000. Subject to change in future + versions. + """ + iflags = RefPruneSubpasses(subpasses_flags) + ffi.lib.LLVMPY_AddRefPrunePass(self, iflags, subgraph_limit) + + +class LegacyModulePassManager(LegacyPassManager): + + def __init__(self, ptr=None): + if ptr is None: + ptr = ffi.lib.LLVMPY_CreateLegacyPassManager() + LegacyPassManager.__init__(self, ptr) + + def run(self, module, remarks_file=None, remarks_format='yaml', + remarks_filter=''): + """ + Run optimization passes on the given module. + + Parameters + ---------- + module : llvmlite.binding.ModuleRef + The module to be optimized inplace + remarks_file : str; optional + If not `None`, it is the file to store the optimization remarks. + remarks_format : str; optional + The format to write; YAML is default + remarks_filter : str; optional + The filter that should be applied to the remarks output. + """ + if remarks_file is None: + return ffi.lib.LLVMPY_RunLegacyPassManager(self, module) + else: + r = ffi.lib.LLVMPY_RunPassManagerWithLegacyRemarks( + self, module, _encode_string(remarks_format), + _encode_string(remarks_filter), + _encode_string(remarks_file)) + if r == -1: + raise IOError("Failed to initialize remarks file.") + return r > 0 + + def run_with_remarks(self, module, remarks_format='yaml', + remarks_filter=''): + """ + Run optimization passes on the given module and returns the result and + the remarks data. + + Parameters + ---------- + module : llvmlite.binding.ModuleRef + The module to be optimized + remarks_format : str + The remarks output; YAML is the default + remarks_filter : str; optional + The filter that should be applied to the remarks output. + """ + remarkdesc, remarkfile = mkstemp() + try: + with os.fdopen(remarkdesc, 'r'): + pass + r = self.run(module, remarkfile, remarks_format, remarks_filter) + if r == -1: + raise IOError("Failed to initialize remarks file.") + with open(remarkfile) as f: + return bool(r), f.read() + finally: + os.unlink(remarkfile) + + +class LegacyFunctionPassManager(LegacyPassManager): + + def __init__(self, module): + ptr = ffi.lib.LLVMPY_CreateLegacyFunctionPassManager(module) + self._module = module + module._owned = True + LegacyPassManager.__init__(self, ptr) + + def initialize(self): + """ + Initialize the LegacyFunctionPassManager. Returns True if it produced + any changes (?). + """ + return ffi.lib.LLVMPY_InitializeLegacyFunctionPassManager(self) + + def finalize(self): + """ + Finalize the LegacyFunctionPassManager. Returns True if it produced + any changes (?). + """ + return ffi.lib.LLVMPY_FinalizeLegacyFunctionPassManager(self) + + def run(self, function, remarks_file=None, remarks_format='yaml', + remarks_filter=''): + """ + Run optimization passes on the given function. + + Parameters + ---------- + function : llvmlite.binding.FunctionRef + The function to be optimized inplace + remarks_file : str; optional + If not `None`, it is the file to store the optimization remarks. + remarks_format : str; optional + The format of the remarks file; the default is YAML + remarks_filter : str; optional + The filter that should be applied to the remarks output. + """ + if remarks_file is None: + return ffi.lib.LLVMPY_RunLegacyFunctionPassManager(self, function) + else: + r = ffi.lib.LLVMPY_RunLegacyFunctionPassManagerWithRemarks( + self, function, _encode_string(remarks_format), + _encode_string(remarks_filter), + _encode_string(remarks_file)) + if r == -1: + raise IOError("Failed to initialize remarks file.") + return bool(r) + + def run_with_remarks(self, function, remarks_format='yaml', + remarks_filter=''): + """ + Run optimization passes on the given function and returns the result + and the remarks data. + + Parameters + ---------- + function : llvmlite.binding.FunctionRef + The function to be optimized inplace + remarks_format : str; optional + The format of the remarks file; the default is YAML + remarks_filter : str; optional + The filter that should be applied to the remarks output. + """ + # LLVM is going to need to close this file and then reopen it, so we + # can't use an unlinked temporary file. + remarkdesc, remarkfile = mkstemp() + try: + # We get an open handle, but we need LLVM to write first, so close + # it. + with os.fdopen(remarkdesc, 'r'): + pass + r = self.run(function, remarkfile, remarks_format, remarks_filter) + if r == -1: + raise IOError("Failed to initialize remarks file.") + with open(remarkfile) as f: + return bool(r), f.read() + finally: + os.unlink(remarkfile) + + +def create_pass_manager_builder(): + return PassManagerBuilder() + + +class PassManagerBuilder(ffi.ObjectRef): + __slots__ = () + + def __init__(self, ptr=None): + if ptr is None: + ptr = ffi.lib.LLVMPY_PassManagerBuilderCreate() + ffi.ObjectRef.__init__(self, ptr) + + @property + def opt_level(self): + """ + The general optimization level as an integer between 0 and 3. + """ + return ffi.lib.LLVMPY_PassManagerBuilderGetOptLevel(self) + + @opt_level.setter + def opt_level(self, level): + ffi.lib.LLVMPY_PassManagerBuilderSetOptLevel(self, level) + + @property + def size_level(self): + """ + Whether and how much to optimize for size. An integer between 0 and 2. + """ + return ffi.lib.LLVMPY_PassManagerBuilderGetSizeLevel(self) + + @size_level.setter + def size_level(self, size): + ffi.lib.LLVMPY_PassManagerBuilderSetSizeLevel(self, size) + + @property + def inlining_threshold(self): + """ + The integer threshold for inlining a function into another. The higher, + the more likely inlining a function is. This attribute is write-only. + """ + raise NotImplementedError("inlining_threshold is write-only") + + @inlining_threshold.setter + def inlining_threshold(self, threshold): + ffi.lib.LLVMPY_PassManagerBuilderUseInlinerWithThreshold( + self, threshold) + + @property + def disable_unroll_loops(self): + """ + If true, disable loop unrolling. + """ + return ffi.lib.LLVMPY_PassManagerBuilderGetDisableUnrollLoops(self) + + @disable_unroll_loops.setter + def disable_unroll_loops(self, disable=True): + ffi.lib.LLVMPY_PassManagerBuilderSetDisableUnrollLoops(self, disable) + + @property + def loop_vectorize(self): + """ + If true, allow vectorizing loops. + """ + return ffi.lib.LLVMPY_PassManagerBuilderGetLoopVectorize(self) + + @loop_vectorize.setter + def loop_vectorize(self, enable=True): + return ffi.lib.LLVMPY_PassManagerBuilderSetLoopVectorize(self, enable) + + @property + def slp_vectorize(self): + """ + If true, enable the "SLP vectorizer", which uses a different algorithm + from the loop vectorizer. Both may be enabled at the same time. + """ + return ffi.lib.LLVMPY_PassManagerBuilderGetSLPVectorize(self) + + @slp_vectorize.setter + def slp_vectorize(self, enable=True): + return ffi.lib.LLVMPY_PassManagerBuilderSetSLPVectorize(self, enable) + + def _populate_module_pm(self, pm): + ffi.lib.LLVMPY_PassManagerBuilderPopulateLegacyModulePassManager( + self, pm) + + def _populate_function_pm(self, pm): + ffi.lib.LLVMPY_PassManagerBuilderPopulateLegacyFunctionPassManager( + self, pm) + + def populate(self, pm): + if isinstance(pm, LegacyModulePassManager): + self._populate_module_pm(pm) + elif isinstance(pm, LegacyFunctionPassManager): + self._populate_function_pm(pm) + else: + raise TypeError(pm) + + def _dispose(self): + self._capi.LLVMPY_PassManagerBuilderDispose(self) + + +# ============================================================================ +# FFI + +ffi.lib.LLVMPY_CreateLegacyPassManager.restype = ffi.LLVMPassManagerRef + +ffi.lib.LLVMPY_CreateLegacyFunctionPassManager.argtypes = [ffi.LLVMModuleRef] +ffi.lib.LLVMPY_CreateLegacyFunctionPassManager.restype = ffi.LLVMPassManagerRef + +ffi.lib.LLVMPY_DisposeLegacyPassManager.argtypes = [ffi.LLVMPassManagerRef] + +ffi.lib.LLVMPY_RunLegacyPassManager.argtypes = [ffi.LLVMPassManagerRef, + ffi.LLVMModuleRef] +ffi.lib.LLVMPY_RunLegacyPassManager.restype = c_bool + +ffi.lib.LLVMPY_RunPassManagerWithLegacyRemarks.argtypes = [ + ffi.LLVMPassManagerRef, ffi.LLVMModuleRef, c_char_p, c_char_p, c_char_p] + +ffi.lib.LLVMPY_RunPassManagerWithLegacyRemarks.restype = c_int + +ffi.lib.LLVMPY_InitializeLegacyFunctionPassManager.argtypes = [ + ffi.LLVMPassManagerRef] + +ffi.lib.LLVMPY_InitializeLegacyFunctionPassManager.restype = c_bool + +ffi.lib.LLVMPY_FinalizeLegacyFunctionPassManager.argtypes = [ + ffi.LLVMPassManagerRef] + +ffi.lib.LLVMPY_FinalizeLegacyFunctionPassManager.restype = c_bool + +ffi.lib.LLVMPY_RunLegacyFunctionPassManager.argtypes = [ffi.LLVMPassManagerRef, + ffi.LLVMValueRef] + +ffi.lib.LLVMPY_RunLegacyFunctionPassManager.restype = c_bool + +ffi.lib.LLVMPY_RunLegacyFunctionPassManagerWithRemarks.argtypes = [ + ffi.LLVMPassManagerRef, ffi.LLVMValueRef, c_char_p, c_char_p, c_char_p +] +ffi.lib.LLVMPY_RunLegacyFunctionPassManagerWithRemarks.restype = c_int + +ffi.lib.LLVMPY_AddAAEvalPass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddBasicAAWrapperPass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddConstantMergePass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddDeadArgEliminationPass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddDependenceAnalysisPass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddCallGraphDOTPrinterPass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddCFGPrinterPass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddDotDomPrinterPass.argtypes = [ffi.LLVMPassManagerRef, c_bool] +ffi.lib.LLVMPY_AddDotPostDomPrinterPass.argtypes = [ + ffi.LLVMPassManagerRef, + c_bool] +ffi.lib.LLVMPY_AddGlobalsModRefAAPass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddInstructionCountPass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddIVUsersPass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddLazyValueInfoPass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddLintPass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddModuleDebugInfoPrinterPass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddRegionInfoPass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddScalarEvolutionAAPass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddAggressiveDCEPass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddAlwaysInlinerPass.argtypes = [ffi.LLVMPassManagerRef, c_bool] + +if llvm_version_major < 15: + ffi.lib.LLVMPY_AddArgPromotionPass.argtypes = [ + ffi.LLVMPassManagerRef, c_uint] + +ffi.lib.LLVMPY_AddBreakCriticalEdgesPass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddDeadStoreEliminationPass.argtypes = [ + ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddReversePostOrderFunctionAttrsPass.argtypes = [ + ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddAggressiveInstructionCombiningPass.argtypes = [ + ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddInternalizePass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddLCSSAPass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddLoopDeletionPass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddLoopExtractorPass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddSingleLoopExtractorPass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddLoopStrengthReducePass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddLoopSimplificationPass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddLoopUnrollPass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddLoopUnrollAndJamPass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddLoopUnswitchPass.argtypes = [ffi.LLVMPassManagerRef, c_bool, + c_bool] +ffi.lib.LLVMPY_AddLowerAtomicPass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddLowerInvokePass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddLowerSwitchPass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddMemCpyOptimizationPass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddMergeFunctionsPass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddMergeReturnsPass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddPartialInliningPass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddPruneExceptionHandlingPass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddReassociatePass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddDemoteRegisterToMemoryPass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddSinkPass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddStripSymbolsPass.argtypes = [ffi.LLVMPassManagerRef, c_bool] +ffi.lib.LLVMPY_AddStripDeadDebugInfoPass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddStripDeadPrototypesPass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddStripDebugDeclarePrototypesPass.argtypes = [ + ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddStripNondebugSymbolsPass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddTailCallEliminationPass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddJumpThreadingPass.argtypes = [ffi.LLVMPassManagerRef, c_int] +ffi.lib.LLVMPY_AddFunctionAttrsPass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddFunctionInliningPass.argtypes = [ + ffi.LLVMPassManagerRef, c_int] +ffi.lib.LLVMPY_AddGlobalDCEPass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddGlobalOptimizerPass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddIPSCCPPass.argtypes = [ffi.LLVMPassManagerRef] + +ffi.lib.LLVMPY_AddDeadCodeEliminationPass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddCFGSimplificationPass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddGVNPass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddInstructionCombiningPass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddLICMPass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddSCCPPass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddSROAPass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddTypeBasedAliasAnalysisPass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddBasicAliasAnalysisPass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddTargetLibraryInfoPass.argtypes = [ffi.LLVMPassManagerRef, + c_char_p] +ffi.lib.LLVMPY_AddInstructionNamerPass.argtypes = [ffi.LLVMPassManagerRef] + +ffi.lib.LLVMPY_AddRefPrunePass.argtypes = [ffi.LLVMPassManagerRef, c_int, + c_size_t] + +ffi.lib.LLVMPY_DumpRefPruneStats.argtypes = [POINTER(_c_PruneStats), c_bool] + +ffi.lib.LLVMPY_PassManagerBuilderCreate.restype = ffi.LLVMPassManagerBuilderRef + +ffi.lib.LLVMPY_PassManagerBuilderDispose.argtypes = [ + ffi.LLVMPassManagerBuilderRef, +] + +ffi.lib.LLVMPY_PassManagerBuilderPopulateLegacyModulePassManager.argtypes = [ + ffi.LLVMPassManagerBuilderRef, + ffi.LLVMPassManagerRef, +] + +ffi.lib.LLVMPY_PassManagerBuilderPopulateLegacyFunctionPassManager.argtypes = [ + ffi.LLVMPassManagerBuilderRef, + ffi.LLVMPassManagerRef, +] + +# Unsigned int PassManagerBuilder properties + +for _func in (ffi.lib.LLVMPY_PassManagerBuilderSetOptLevel, + ffi.lib.LLVMPY_PassManagerBuilderSetSizeLevel, + ffi.lib.LLVMPY_PassManagerBuilderUseInlinerWithThreshold, + ): + _func.argtypes = [ffi.LLVMPassManagerBuilderRef, c_uint] + +for _func in (ffi.lib.LLVMPY_PassManagerBuilderGetOptLevel, + ffi.lib.LLVMPY_PassManagerBuilderGetSizeLevel, + ): + _func.argtypes = [ffi.LLVMPassManagerBuilderRef] + _func.restype = c_uint + +# Boolean PassManagerBuilder properties + +for _func in (ffi.lib.LLVMPY_PassManagerBuilderSetDisableUnrollLoops, + ffi.lib.LLVMPY_PassManagerBuilderSetLoopVectorize, + ffi.lib.LLVMPY_PassManagerBuilderSetSLPVectorize, + ): + _func.argtypes = [ffi.LLVMPassManagerBuilderRef, c_bool] + +for _func in (ffi.lib.LLVMPY_PassManagerBuilderGetDisableUnrollLoops, + ffi.lib.LLVMPY_PassManagerBuilderGetLoopVectorize, + ffi.lib.LLVMPY_PassManagerBuilderGetSLPVectorize, + ): + _func.argtypes = [ffi.LLVMPassManagerBuilderRef] + _func.restype = c_bool diff --git a/llvmlite/binding/newpassmangers.py b/llvmlite/binding/newpassmangers.py deleted file mode 100644 index 45e786e77..000000000 --- a/llvmlite/binding/newpassmangers.py +++ /dev/null @@ -1,305 +0,0 @@ -from ctypes import (c_bool, c_int) -from llvmlite.binding import ffi -from llvmlite.binding.initfini import llvm_version_info - -llvm_version_major = llvm_version_info[0] - - -def create_new_module_pass_manager(): - return NewModulePassManager() - - -def create_new_function_pass_manager(): - return NewFunctionPassManger() - - -def create_pass_builder(tm, pto): - return PassBuilder(tm, pto) - - -def create_pipeline_options(): - return PipelineTuningOptions() - - -class NewModulePassManager(ffi.ObjectRef): - - def __init__(self, ptr=None): - if ptr is None: - ptr = ffi.lib.LLVMPY_CreateNewModulePassManager() - ffi.ObjectRef.__init__(self, ptr) - - def run(self, module, pb): - ffi.lib.LLVMPY_NMPRun_module(self, pb, module) - - def addVerifier(self): - ffi.lib.LLVMPY_AddVeriferPass(self) - - def add_aa_eval_pass(self): - ffi.lib.LLVMPY_AddAAEvalPass_module(self) - - def add_simplify_cfg_pass(self): - ffi.lib.LLVMPY_AddSimplifyCFGPass_module(self) - - def add_loop_unroll_pass(self): - ffi.lib.LLVMPY_AddLoopUnrollPass_module(self) - - def add_loop_rotate_pass(self): - ffi.lib.LLVMPY_LLVMAddLoopRotatePass_module(self) - - def add_instruction_combine_pass(self): - ffi.lib.LLVMPY_LLVMAddInstructionCombinePass_module(self) - - def add_jump_threading_pass(self, threshold=-1): - ffi.lib.LLVMPY_AddJumpThreadingPass_module(self, threshold) - - # What will happen to the pointer to objects created with run() method - def _dispose(self): - ffi.lib.LLVMPY_DisposeNewModulePassManger(self) - - -class NewFunctionPassManger(ffi.ObjectRef): - - def __init__(self, ptr=None): - if ptr is None: - ptr = ffi.lib.LLVMPY_CreateNewFunctionPassManager() - ffi.ObjectRef.__init__(self, ptr) - - def add_aa_eval_pass(self): - ffi.lib.LLVMPY_AddAAEvalPass_function(self) - - def add_simplify_cfg_pass(self): - ffi.lib.LLVMPY_AddSimplifyCFGPass_function(self) - - def run(self, fun, pb): - ffi.lib.LLVMPY_NMPRun_function(self, pb, fun) - - def add_loop_unroll_pass(self): - ffi.lib.LLVMPY_AddLoopUnrollPass_function(self) - - def add_loop_rotate_pass(self): - ffi.lib.LLVMPY_LLVMAddLoopRotatePass_function(self) - - def add_instruction_combine_pass(self): - ffi.lib.LLVMPY_LLVMAddInstructionCombinePass_function(self) - - def add_jump_threading_pass(self, threshold=-1): - ffi.lib.LLVMPY_AddJumpThreadingPass_function(self, threshold) - - def _dispose(self): - ffi.lib.LLVMPY_DisposeNewFunctionPassManger(self) - - -# Make this nested class of PassBuilder? -class PipelineTuningOptions(ffi.ObjectRef): - - def __init__(self, ptr=None): - if ptr is None: - ptr = ffi.lib.LLVMPY_CreatePipelineTuningOptions() - self._opt_level = 2 - self._size_level = 0 - ffi.ObjectRef.__init__(self, ptr) - - @property - def loop_interleaving(self): - return ffi.lib.LLVMPY_PTOGetLoopInterleaving(self) - - @loop_interleaving.setter - def loop_interleaving(self, value): - ffi.lib.LLVMPY_PTOSetLoopInterleaving(self, value) - - @property - def loop_vectorization(self): - return ffi.lib.LLVMPY_PTOGetLoopVectorization(self) - - @loop_vectorization.setter - def loop_vectorization(self, value): - ffi.lib.LLVMPY_PTOSetLoopVectorization(self, value) - - @property - def slp_vectorization(self): - return ffi.lib.LLVMPY_PTOGetSLPVectorization(self) - - @slp_vectorization.setter - def slp_vectorization(self, value): - ffi.lib.LLVMPY_PTOSetSLPVectorization(self, value) - - @property - def loop_unrolling(self): - return ffi.lib.LLVMPY_PTOGetLoopUnrolling(self) - - @loop_unrolling.setter - def loop_unrolling(self, value): - ffi.lib.LLVMPY_PTOSetLoopUnrolling(self, value) - - # // FIXME: Available from llvm16 - # @property - # def inlining_threshold(self): - # return ffi.lib.LLVMPY_PTOGetInlinerThreshold(self) - - # @inlining_threshold.setter - # def inlining_threshold(self, value): - # ffi.lib.LLVMPY_PTOSetInlinerThreshold(self, value) - - # Not part of PTO - @property - def opt_level(self): - """ - The general optimization level as an integer between 0 and 3. - """ - return self._opt_level - - @opt_level.setter - def opt_level(self, level): - self._opt_level = level - - @property - def size_level(self): - """ - Whether and how much to optimize for size. - An integer between 0 and 2. - """ - return self._size_level - - @size_level.setter - def size_level(self, size): - self._size_level = size - - def _dispose(self): - ffi.lib.LLVMPY_DisposePipelineTuningOptions(self) - - -class PassBuilder(ffi.ObjectRef): - - def __init__(self, tm, pto, ptr=None): - if ptr is None: - self._pto = pto - self._tm = tm - ptr = ffi.lib.LLVMPY_CreatePassBuilder(tm, pto) - ffi.ObjectRef.__init__(self, ptr) - - def getNewModulePassManager(self): - return NewModulePassManager( - ffi.lib.LLVMPY_buildPerModuleDefaultPipeline( - self, self._pto.opt_level, self._pto.size_level) - ) - - def getNewFunctionPassManager(self): - return NewFunctionPassManger( - ffi.lib.LLVMPY_buildFunctionSimplificationPipeline( - self, self._pto.opt_level, self._pto.size_level) - ) - - def _dispose(self): - # Should I explicitly delete pointer to pto and tm? - ffi.lib.LLVMPY_DisposePassBuilder(self) - - -# ============================================================================ -# FFI - - -ffi.lib.LLVMPY_CreateNewModulePassManager.restype = ffi.LLVMModulePassManagerRef - -ffi.lib.LLVMPY_NMPRun_module.argtypes = [ffi.LLVMModulePassManagerRef, - ffi.LLVMPassBuilderRef, - ffi.LLVMModuleRef,] - -ffi.lib.LLVMPY_AddVeriferPass.argtypes = [ffi.LLVMModulePassManagerRef,] -ffi.lib.LLVMPY_AddAAEvalPass_module.argtypes = [ffi.LLVMModulePassManagerRef,] -ffi.lib.LLVMPY_AddSimplifyCFGPass_module.argtypes = [ - ffi.LLVMModulePassManagerRef,] - -ffi.lib.LLVMPY_AddLoopUnrollPass_module.argtypes = [ - ffi.LLVMModulePassManagerRef,] - -ffi.lib.LLVMPY_LLVMAddLoopRotatePass_module.argtypes = [ - ffi.LLVMModulePassManagerRef,] - -ffi.lib.LLVMPY_LLVMAddInstructionCombinePass_module.argtypes = [ - ffi.LLVMModulePassManagerRef,] - -ffi.lib.LLVMPY_AddJumpThreadingPass_module.argtypes = [ - ffi.LLVMModulePassManagerRef,] - -ffi.lib.LLVMPY_DisposeNewModulePassManger.argtypes = [ - ffi.LLVMModulePassManagerRef,] - -ffi.lib.LLVMPY_CreateNewFunctionPassManager.restype = \ - ffi.LLVMFunctionPassManagerRef - -ffi.lib.LLVMPY_NMPRun_function.argtypes = [ffi.LLVMFunctionPassManagerRef, - ffi.LLVMPassBuilderRef, - ffi.LLVMValueRef,] - -ffi.lib.LLVMPY_AddAAEvalPass_function.argtypes = [ - ffi.LLVMFunctionPassManagerRef,] - -ffi.lib.LLVMPY_AddSimplifyCFGPass_function.argtypes = [ - ffi.LLVMFunctionPassManagerRef,] - -ffi.lib.LLVMPY_AddLoopUnrollPass_function.argtypes = [ - ffi.LLVMFunctionPassManagerRef,] - -ffi.lib.LLVMPY_LLVMAddLoopRotatePass_function.argtypes = [ - ffi.LLVMFunctionPassManagerRef,] - -ffi.lib.LLVMPY_LLVMAddInstructionCombinePass_function.argtypes = [ - ffi.LLVMFunctionPassManagerRef,] - -ffi.lib.LLVMPY_AddJumpThreadingPass_function.argtypes = [ - ffi.LLVMFunctionPassManagerRef, c_int,] - -ffi.lib.LLVMPY_DisposeNewFunctionPassManger.argtypes = [ - ffi.LLVMFunctionPassManagerRef,] - -ffi.lib.LLVMPY_CreatePassBuilder.restype = ffi.LLVMPassBuilderRef -ffi.lib.LLVMPY_CreatePassBuilder.argtypes = [ffi.LLVMTargetMachineRef, - ffi.LLVMPipelineTuningOptionsRef,] - -ffi.lib.LLVMPY_buildPerModuleDefaultPipeline.restype = \ - ffi.LLVMModulePassManagerRef - -ffi.lib.LLVMPY_buildPerModuleDefaultPipeline.argtypes = [ - ffi.LLVMPassBuilderRef, c_int,] - -ffi.lib.LLVMPY_buildFunctionSimplificationPipeline.restype = \ - ffi.LLVMFunctionPassManagerRef - -ffi.lib.LLVMPY_buildFunctionSimplificationPipeline.argtypes = [ - ffi.LLVMPassBuilderRef, c_int,] - -ffi.lib.LLVMPY_DisposePassBuilder.argtypes = [ffi.LLVMPassBuilderRef,] - -ffi.lib.LLVMPY_CreatePipelineTuningOptions.restype = \ - ffi.LLVMPipelineTuningOptionsRef - -ffi.lib.LLVMPY_PTOGetLoopInterleaving.restype = c_bool -ffi.lib.LLVMPY_PTOGetLoopInterleaving.argtypes = [ - ffi.LLVMPipelineTuningOptionsRef,] - -ffi.lib.LLVMPY_PTOSetLoopInterleaving.argtypes = [ - ffi.LLVMPipelineTuningOptionsRef, c_bool] - -ffi.lib.LLVMPY_PTOGetLoopVectorization.restype = c_bool -ffi.lib.LLVMPY_PTOGetLoopVectorization.argtypes = [ - ffi.LLVMPipelineTuningOptionsRef,] - -ffi.lib.LLVMPY_PTOSetLoopVectorization.argtypes = [ - ffi.LLVMPipelineTuningOptionsRef, c_bool] - -ffi.lib.LLVMPY_PTOGetSLPVectorization.restype = c_bool -ffi.lib.LLVMPY_PTOGetSLPVectorization.argtypes = [ - ffi.LLVMPipelineTuningOptionsRef,] - -ffi.lib.LLVMPY_PTOSetSLPVectorization.argtypes = [ - ffi.LLVMPipelineTuningOptionsRef, c_bool] - -ffi.lib.LLVMPY_PTOGetLoopUnrolling.restype = c_bool -ffi.lib.LLVMPY_PTOGetLoopUnrolling.argtypes = [ - ffi.LLVMPipelineTuningOptionsRef,] - -ffi.lib.LLVMPY_PTOSetLoopUnrolling.argtypes = [ - ffi.LLVMPipelineTuningOptionsRef, c_bool] - -ffi.lib.LLVMPY_DisposePipelineTuningOptions.argtypes = \ - [ffi.LLVMPipelineTuningOptionsRef,] diff --git a/llvmlite/binding/passmanagers.py b/llvmlite/binding/passmanagers.py index af6152f63..8c1e83faa 100644 --- a/llvmlite/binding/passmanagers.py +++ b/llvmlite/binding/passmanagers.py @@ -1,939 +1,305 @@ -from ctypes import (c_bool, c_char_p, c_int, c_size_t, c_uint, Structure, byref, - POINTER) -from collections import namedtuple -from enum import IntFlag +from ctypes import (c_bool, c_int) from llvmlite.binding import ffi from llvmlite.binding.initfini import llvm_version_info -import os -from tempfile import mkstemp -from llvmlite.binding.common import _encode_string - -_prunestats = namedtuple('PruneStats', - ('basicblock diamond fanout fanout_raise')) llvm_version_major = llvm_version_info[0] -class PruneStats(_prunestats): - """ Holds statistics from reference count pruning. - """ - - def __add__(self, other): - if not isinstance(other, PruneStats): - msg = 'PruneStats can only be added to another PruneStats, got {}.' - raise TypeError(msg.format(type(other))) - return PruneStats(self.basicblock + other.basicblock, - self.diamond + other.diamond, - self.fanout + other.fanout, - self.fanout_raise + other.fanout_raise) - - def __sub__(self, other): - if not isinstance(other, PruneStats): - msg = ('PruneStats can only be subtracted from another PruneStats, ' - 'got {}.') - raise TypeError(msg.format(type(other))) - return PruneStats(self.basicblock - other.basicblock, - self.diamond - other.diamond, - self.fanout - other.fanout, - self.fanout_raise - other.fanout_raise) - - -class _c_PruneStats(Structure): - _fields_ = [ - ('basicblock', c_size_t), - ('diamond', c_size_t), - ('fanout', c_size_t), - ('fanout_raise', c_size_t)] - - -def dump_refprune_stats(printout=False): - """ Returns a namedtuple containing the current values for the refop pruning - statistics. If kwarg `printout` is True the stats are printed to stderr, - default is False. - """ - - stats = _c_PruneStats(0, 0, 0, 0) - do_print = c_bool(printout) - - ffi.lib.LLVMPY_DumpRefPruneStats(byref(stats), do_print) - return PruneStats(stats.basicblock, stats.diamond, stats.fanout, - stats.fanout_raise) - - -def set_time_passes(enable): - """Enable or disable the pass timers. - - Parameters - ---------- - enable : bool - Set to True to enable the pass timers. - Set to False to disable the pass timers. - """ - ffi.lib.LLVMPY_SetTimePasses(c_bool(enable)) - - -def report_and_reset_timings(): - """Returns the pass timings report and resets the LLVM internal timers. - - Pass timers are enabled by ``set_time_passes()``. If the timers are not - enabled, this function will return an empty string. - - Returns - ------- - res : str - LLVM generated timing report. - """ - with ffi.OutputString() as buf: - ffi.lib.LLVMPY_ReportAndResetTimings(buf) - return str(buf) - - -def create_module_pass_manager(): +def create_new_module_pass_manager(): return ModulePassManager() -def create_function_pass_manager(module): - return FunctionPassManager(module) - - -class RefPruneSubpasses(IntFlag): - PER_BB = 0b0001 # noqa: E221 - DIAMOND = 0b0010 # noqa: E221 - FANOUT = 0b0100 # noqa: E221 - FANOUT_RAISE = 0b1000 - ALL = PER_BB | DIAMOND | FANOUT | FANOUT_RAISE - - -class PassManager(ffi.ObjectRef): - """PassManager - """ - - def _dispose(self): - self._capi.LLVMPY_DisposePassManager(self) - - def add_aa_eval_pass(self): - """ - See https://llvm.org/docs/Passes.html#aa-eval-exhaustive-alias-analysis-precision-evaluator - - LLVM 14: `llvm::createAAEvalPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddAAEvalPass(self) - - def add_basic_aa_pass(self): - """ - See https://llvm.org/docs/Passes.html#basic-aa-basic-alias-analysis-stateless-aa-impl - - LLVM 14: `llvm::createBasicAAWrapperPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddBasicAAWrapperPass(self) - - def add_constant_merge_pass(self): - """ - See http://llvm.org/docs/Passes.html#constmerge-merge-duplicate-global-constants - - LLVM 14: `LLVMAddConstantMergePass` - """ # noqa E501 - ffi.lib.LLVMPY_AddConstantMergePass(self) - - def add_dead_arg_elimination_pass(self): - """ - See http://llvm.org/docs/Passes.html#deadargelim-dead-argument-elimination - - LLVM 14: `LLVMAddDeadArgEliminationPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddDeadArgEliminationPass(self) - - def add_dependence_analysis_pass(self): - """ - See https://llvm.org/docs/Passes.html#da-dependence-analysis - - LLVM 14: `llvm::createDependenceAnalysisWrapperPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddDependenceAnalysisPass(self) - - def add_dot_call_graph_pass(self): - """ - See https://llvm.org/docs/Passes.html#dot-callgraph-print-call-graph-to-dot-file - - LLVM 14: `llvm::createCallGraphDOTPrinterPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddCallGraphDOTPrinterPass(self) - - def add_dot_cfg_printer_pass(self): - """ - See https://llvm.org/docs/Passes.html#dot-cfg-print-cfg-of-function-to-dot-file - - LLVM 14: `llvm::createCFGPrinterLegacyPassPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddCFGPrinterPass(self) - - def add_dot_dom_printer_pass(self, show_body=False): - """ - See https://llvm.org/docs/Passes.html#dot-dom-print-dominance-tree-of-function-to-dot-file - - LLVM 14: `llvm::createDomPrinterPass` and `llvm::createDomOnlyPrinterPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddDotDomPrinterPass(self, show_body) - - def add_dot_postdom_printer_pass(self, show_body=False): - """ - See https://llvm.org/docs/Passes.html#dot-postdom-print-postdominance-tree-of-function-to-dot-file - - LLVM 14: `llvm::createPostDomPrinterPass` and `llvm::createPostDomOnlyPrinterPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddDotPostDomPrinterPass(self, show_body) - - def add_globals_mod_ref_aa_pass(self): - """ - See https://llvm.org/docs/Passes.html#globalsmodref-aa-simple-mod-ref-analysis-for-globals - - LLVM 14: `llvm::createGlobalsAAWrapperPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddGlobalsModRefAAPass(self) - - def add_iv_users_pass(self): - """ - See https://llvm.org/docs/Passes.html#iv-users-induction-variable-users - - LLVM 14: `llvm::createIVUsersPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddIVUsersPass(self) - - def add_lint_pass(self): - """ - See https://llvm.org/docs/Passes.html#lint-statically-lint-checks-llvm-ir - - LLVM 14: `llvm::createLintLegacyPassPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddLintPass(self) - - def add_lazy_value_info_pass(self): - """ - See https://llvm.org/docs/Passes.html#lazy-value-info-lazy-value-information-analysis - - LLVM 14: `llvm::createLazyValueInfoPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddLazyValueInfoPass(self) - - def add_module_debug_info_pass(self): - """ - See https://llvm.org/docs/Passes.html#module-debuginfo-decodes-module-level-debug-info - - LLVM 14: `llvm::createModuleDebugInfoPrinterPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddModuleDebugInfoPrinterPass(self) - - def add_region_info_pass(self): - """ - See https://llvm.org/docs/Passes.html#regions-detect-single-entry-single-exit-regions - - LLVM 14: `llvm::createRegionInfoPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddRegionInfoPass(self) - - def add_scalar_evolution_aa_pass(self): - """ - See https://llvm.org/docs/Passes.html#scev-aa-scalarevolution-based-alias-analysis - - LLVM 14: `llvm::createSCEVAAWrapperPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddScalarEvolutionAAPass(self) - - def add_aggressive_dead_code_elimination_pass(self): - """ - See https://llvm.org/docs/Passes.html#adce-aggressive-dead-code-elimination - - LLVM 14: `llvm::createAggressiveDCEPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddAggressiveDCEPass(self) - - def add_always_inliner_pass(self, insert_lifetime=True): - """ - See https://llvm.org/docs/Passes.html#always-inline-inliner-for-always-inline-functions - - LLVM 14: `llvm::createAlwaysInlinerLegacyPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddAlwaysInlinerPass(self, insert_lifetime) - - def add_arg_promotion_pass(self, max_elements=3): - """ - See https://llvm.org/docs/Passes.html#argpromotion-promote-by-reference-arguments-to-scalars - - LLVM 14: `llvm::createArgumentPromotionPass` - """ # noqa E501 - if llvm_version_major > 14: - raise RuntimeError('ArgumentPromotionPass unavailable in LLVM > 14') - ffi.lib.LLVMPY_AddArgPromotionPass(self, max_elements) - - def add_break_critical_edges_pass(self): - """ - See https://llvm.org/docs/Passes.html#break-crit-edges-break-critical-edges-in-cfg - - LLVM 14: `llvm::createBreakCriticalEdgesPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddBreakCriticalEdgesPass(self) - - def add_dead_store_elimination_pass(self): - """ - See https://llvm.org/docs/Passes.html#dse-dead-store-elimination - - LLVM 14: `llvm::createDeadStoreEliminationPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddDeadStoreEliminationPass(self) - - def add_reverse_post_order_function_attrs_pass(self): - """ - See https://llvm.org/docs/Passes.html#function-attrs-deduce-function-attributes - - LLVM 14: `llvm::createReversePostOrderFunctionAttrsPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddReversePostOrderFunctionAttrsPass(self) - - def add_function_attrs_pass(self): - """ - See http://llvm.org/docs/Passes.html#functionattrs-deduce-function-attributes - - LLVM 14: `LLVMAddFunctionAttrsPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddFunctionAttrsPass(self) - - def add_function_inlining_pass(self, threshold): - """ - See http://llvm.org/docs/Passes.html#inline-function-integration-inlining +def create_new_function_pass_manager(): + return FunctionPassManager() - LLVM 14: `createFunctionInliningPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddFunctionInliningPass(self, threshold) - def add_global_dce_pass(self): - """ - See http://llvm.org/docs/Passes.html#globaldce-dead-global-elimination +def create_pass_builder(tm, pto): + return PassBuilder(tm, pto) - LLVM 14: `LLVMAddGlobalDCEPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddGlobalDCEPass(self) - def add_global_optimizer_pass(self): - """ - See http://llvm.org/docs/Passes.html#globalopt-global-variable-optimizer +def create_pipeline_options(): + return PipelineTuningOptions() - LLVM 14: `LLVMAddGlobalOptimizerPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddGlobalOptimizerPass(self) - def add_ipsccp_pass(self): - """ - See http://llvm.org/docs/Passes.html#ipsccp-interprocedural-sparse-conditional-constant-propagation +class ModulePassManager(ffi.ObjectRef): - LLVM 14: `LLVMAddIPSCCPPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddIPSCCPPass(self) + def __init__(self, ptr=None): + if ptr is None: + ptr = ffi.lib.LLVMPY_CreateModulePassManager() + ffi.ObjectRef.__init__(self, ptr) - def add_dead_code_elimination_pass(self): - """ - See http://llvm.org/docs/Passes.html#dce-dead-code-elimination - LLVM 14: `llvm::createDeadCodeEliminationPass` - """ - ffi.lib.LLVMPY_AddDeadCodeEliminationPass(self) + def run(self, module, pb): + ffi.lib.LLVMPY_RunModulePassManager(self, pb, module) - def add_aggressive_instruction_combining_pass(self): - """ - See https://llvm.org/docs/Passes.html#aggressive-instcombine-combine-expression-patterns + def addVerifier(self): + ffi.lib.LLVMPY_AddVeriferPass(self) - LLVM 14: `llvm::createAggressiveInstCombinerPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddAggressiveInstructionCombiningPass(self) + def add_aa_eval_pass(self): + ffi.lib.LLVMPY_AddAAEvalPass_module(self) - def add_internalize_pass(self): - """ - See https://llvm.org/docs/Passes.html#internalize-internalize-global-symbols + def add_simplify_cfg_pass(self): + ffi.lib.LLVMPY_AddSimplifyCFGPass_module(self) - LLVM 14: `llvm::createInternalizePass` - """ # noqa E501 - ffi.lib.LLVMPY_AddInternalizePass(self) + def add_loop_unroll_pass(self): + ffi.lib.LLVMPY_AddLoopUnrollPass_module(self) - def add_cfg_simplification_pass(self): - """ - See http://llvm.org/docs/Passes.html#simplifycfg-simplify-the-cfg + def add_loop_rotate_pass(self): + ffi.lib.LLVMPY_LLVMAddLoopRotatePass_module(self) - LLVM 14: `LLVMAddCFGSimplificationPass` - """ - ffi.lib.LLVMPY_AddCFGSimplificationPass(self) + def add_instruction_combine_pass(self): + ffi.lib.LLVMPY_LLVMAddInstructionCombinePass_module(self) def add_jump_threading_pass(self, threshold=-1): - """ - See https://llvm.org/docs/Passes.html#jump-threading-jump-threading + ffi.lib.LLVMPY_AddJumpThreadingPass_module(self, threshold) - LLVM 14: `llvm::createJumpThreadingPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddJumpThreadingPass(self, threshold) + # What will happen to the pointer to objects created with run() method + def _dispose(self): + ffi.lib.LLVMPY_DisposeNewModulePassManger(self) - def add_lcssa_pass(self): - """ - See https://llvm.org/docs/Passes.html#lcssa-loop-closed-ssa-form-pass - LLVM 14: `llvm::createLCSSAPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddLCSSAPass(self) +class FunctionPassManager(ffi.ObjectRef): - def add_gvn_pass(self): - """ - See http://llvm.org/docs/Passes.html#gvn-global-value-numbering + def __init__(self, ptr=None): + if ptr is None: + ptr = ffi.lib.LLVMPY_CreateNewFunctionPassManager() + ffi.ObjectRef.__init__(self, ptr) - LLVM 14: `LLVMAddGVNPass` - """ - ffi.lib.LLVMPY_AddGVNPass(self) + def add_aa_eval_pass(self): + ffi.lib.LLVMPY_AddAAEvalPass_function(self) - def add_instruction_combining_pass(self): - """ - See http://llvm.org/docs/Passes.html#passes-instcombine + def add_simplify_cfg_pass(self): + ffi.lib.LLVMPY_AddSimplifyCFGPass_function(self) - LLVM 14: `LLVMAddInstructionCombiningPass` - """ - ffi.lib.LLVMPY_AddInstructionCombiningPass(self) + def run(self, fun, pb): + ffi.lib.LLVMPY_RunFunctionPassManager(self, pb, fun) - def add_licm_pass(self): - """ - See http://llvm.org/docs/Passes.html#licm-loop-invariant-code-motion + def add_loop_unroll_pass(self): + ffi.lib.LLVMPY_AddLoopUnrollPass_function(self) - LLVM 14: `LLVMAddLICMPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddLICMPass(self) + def add_loop_rotate_pass(self): + ffi.lib.LLVMPY_LLVMAddLoopRotatePass_function(self) - def add_loop_deletion_pass(self): - """ - See https://llvm.org/docs/Passes.html#loop-deletion-delete-dead-loops + def add_instruction_combine_pass(self): + ffi.lib.LLVMPY_LLVMAddInstructionCombinePass_function(self) - LLVM 14: `llvm::createLoopDeletionPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddLoopDeletionPass(self) + def add_jump_threading_pass(self, threshold=-1): + ffi.lib.LLVMPY_AddJumpThreadingPass_function(self, threshold) - def add_loop_extractor_pass(self): - """ - See https://llvm.org/docs/Passes.html#loop-extract-extract-loops-into-new-functions + def _dispose(self): + ffi.lib.LLVMPY_DisposeNewFunctionPassManger(self) - LLVM 14: `llvm::createLoopExtractorPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddLoopExtractorPass(self) - def add_single_loop_extractor_pass(self): - """ - See https://llvm.org/docs/Passes.html#loop-extract-single-extract-at-most-one-loop-into-a-new-function +# Make this nested class of PassBuilder? +class PipelineTuningOptions(ffi.ObjectRef): - LLVM 14: `llvm::createSingleLoopExtractorPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddSingleLoopExtractorPass(self) + def __init__(self, ptr=None): + if ptr is None: + ptr = ffi.lib.LLVMPY_CreatePipelineTuningOptions() + self._opt_level = 2 + self._size_level = 0 + ffi.ObjectRef.__init__(self, ptr) - def add_sccp_pass(self): - """ - See http://llvm.org/docs/Passes.html#sccp-sparse-conditional-constant-propagation + @property + def loop_interleaving(self): + return ffi.lib.LLVMPY_PTOGetLoopInterleaving(self) - LLVM 14: `LLVMAddSCCPPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddSCCPPass(self) + @loop_interleaving.setter + def loop_interleaving(self, value): + ffi.lib.LLVMPY_PTOSetLoopInterleaving(self, value) - def add_loop_strength_reduce_pass(self): - """ - See https://llvm.org/docs/Passes.html#loop-reduce-loop-strength-reduction + @property + def loop_vectorization(self): + return ffi.lib.LLVMPY_PTOGetLoopVectorization(self) - LLVM 14: `llvm::createLoopStrengthReducePass` - """ # noqa E501 - ffi.lib.LLVMPY_AddLoopStrengthReducePass(self) + @loop_vectorization.setter + def loop_vectorization(self, value): + ffi.lib.LLVMPY_PTOSetLoopVectorization(self, value) - def add_loop_simplification_pass(self): - """ - See https://llvm.org/docs/Passes.html#loop-simplify-canonicalize-natural-loops + @property + def slp_vectorization(self): + return ffi.lib.LLVMPY_PTOGetSLPVectorization(self) - LLVM 14: `llvm::createLoopSimplifyPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddLoopSimplificationPass(self) + @slp_vectorization.setter + def slp_vectorization(self, value): + ffi.lib.LLVMPY_PTOSetSLPVectorization(self, value) - def add_loop_unroll_pass(self): - """ - See https://llvm.org/docs/Passes.html#loop-unroll-unroll-loops + @property + def loop_unrolling(self): + return ffi.lib.LLVMPY_PTOGetLoopUnrolling(self) - LLVM 14: `LLVMAddLoopUnrollPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddLoopUnrollPass(self) + @loop_unrolling.setter + def loop_unrolling(self, value): + ffi.lib.LLVMPY_PTOSetLoopUnrolling(self, value) - def add_loop_unroll_and_jam_pass(self): - """ - See https://llvm.org/docs/Passes.html#loop-unroll-and-jam-unroll-and-jam-loops + # // FIXME: Available from llvm16 + # @property + # def inlining_threshold(self): + # return ffi.lib.LLVMPY_PTOGetInlinerThreshold(self) - LLVM 14: `LLVMAddLoopUnrollAndJamPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddLoopUnrollAndJamPass(self) + # @inlining_threshold.setter + # def inlining_threshold(self, value): + # ffi.lib.LLVMPY_PTOSetInlinerThreshold(self, value) - def add_loop_unswitch_pass(self, - optimize_for_size=False, - has_branch_divergence=False): + # Not part of PTO + @property + def opt_level(self): """ - See https://llvm.org/docs/Passes.html#loop-unswitch-unswitch-loops - - LLVM 14: `llvm::createLoopUnswitchPass` - LLVM 15: `llvm::createSimpleLoopUnswitchLegacyPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddLoopUnswitchPass(self, optimize_for_size, - has_branch_divergence) - - def add_lower_atomic_pass(self): + The general optimization level as an integer between 0 and 3. """ - See https://llvm.org/docs/Passes.html#loweratomic-lower-atomic-intrinsics-to-non-atomic-form + return self._opt_level - LLVM 14: `llvm::createLowerAtomicPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddLowerAtomicPass(self) + @opt_level.setter + def opt_level(self, level): + self._opt_level = level - def add_lower_invoke_pass(self): + @property + def size_level(self): """ - See https://llvm.org/docs/Passes.html#lowerinvoke-lower-invokes-to-calls-for-unwindless-code-generators - - LLVM 14: `llvm::createLowerInvokePass` - """ # noqa E501 - ffi.lib.LLVMPY_AddLowerInvokePass(self) - - def add_lower_switch_pass(self): + Whether and how much to optimize for size. + An integer between 0 and 2. """ - See https://llvm.org/docs/Passes.html#lowerswitch-lower-switchinsts-to-branches + return self._size_level - LLVM 14: `llvm::createLowerSwitchPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddLowerSwitchPass(self) + @size_level.setter + def size_level(self, size): + self._size_level = size - def add_memcpy_optimization_pass(self): - """ - See https://llvm.org/docs/Passes.html#memcpyopt-memcpy-optimization - - LLVM 14: `llvm::createMemCpyOptPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddMemCpyOptimizationPass(self) - - def add_merge_functions_pass(self): - """ - See https://llvm.org/docs/Passes.html#mergefunc-merge-functions - - LLVM 14: `llvm::createMergeFunctionsPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddMergeFunctionsPass(self) - - def add_merge_returns_pass(self): - """ - See https://llvm.org/docs/Passes.html#mergereturn-unify-function-exit-nodes + def _dispose(self): + ffi.lib.LLVMPY_DisposePipelineTuningOptions(self) - LLVM 14: `llvm::createUnifyFunctionExitNodesPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddMergeReturnsPass(self) - def add_partial_inlining_pass(self): - """ - See https://llvm.org/docs/Passes.html#partial-inliner-partial-inliner +class PassBuilder(ffi.ObjectRef): - LLVM 14: `llvm::createPartialInliningPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddPartialInliningPass(self) + def __init__(self, tm, pto, ptr=None): + if ptr is None: + self._pto = pto + self._tm = tm + ptr = ffi.lib.LLVMPY_CreatePassBuilder(tm, pto) + ffi.ObjectRef.__init__(self, ptr) + + def getModulePassManager(self): + return ModulePassManager( + ffi.lib.LLVMPY_buildPerModuleDefaultPipeline( + self, self._pto.opt_level, self._pto.size_level) + ) + + def getFunctionPassManager(self): + return FunctionPassManager( + ffi.lib.LLVMPY_buildFunctionSimplificationPipeline( + self, self._pto.opt_level, self._pto.size_level) + ) - def add_prune_exception_handling_pass(self): - """ - See https://llvm.org/docs/Passes.html#prune-eh-remove-unused-exception-handling-info + def _dispose(self): + # Should I explicitly delete pointer to pto and tm? + ffi.lib.LLVMPY_DisposePassBuilder(self) - LLVM 14: `llvm::createPruneEHPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddPruneExceptionHandlingPass(self) - def add_reassociate_expressions_pass(self): - """ - See https://llvm.org/docs/Passes.html#reassociate-reassociate-expressions +# ============================================================================ +# FFI - LLVM 14: `llvm::createReassociatePass` - """ # noqa E501 - ffi.lib.LLVMPY_AddReassociatePass(self) - def add_demote_register_to_memory_pass(self): - """ - See https://llvm.org/docs/Passes.html#rel-lookup-table-converter-relative-lookup-table-converter +ffi.lib.LLVMPY_CreateModulePassManager.restype = ffi.LLVMModulePassManagerRef - LLVM 14: `llvm::createDemoteRegisterToMemoryPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddDemoteRegisterToMemoryPass(self) +ffi.lib.LLVMPY_RunModulePassManager.argtypes = [ + ffi.LLVMModulePassManagerRef, ffi.LLVMPassBuilderRef, ffi.LLVMModuleRef,] - def add_sroa_pass(self): - """ - See http://llvm.org/docs/Passes.html#scalarrepl-scalar-replacement-of-aggregates-dt - Note that this pass corresponds to the ``opt -sroa`` command-line option, - despite the link above. +ffi.lib.LLVMPY_AddVeriferPass.argtypes = [ffi.LLVMModulePassManagerRef,] +ffi.lib.LLVMPY_AddAAEvalPass_module.argtypes = [ffi.LLVMModulePassManagerRef,] +ffi.lib.LLVMPY_AddSimplifyCFGPass_module.argtypes = [ + ffi.LLVMModulePassManagerRef,] - LLVM 14: `llvm::createSROAPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddSROAPass(self) +ffi.lib.LLVMPY_AddLoopUnrollPass_module.argtypes = [ + ffi.LLVMModulePassManagerRef,] - def add_sink_pass(self): - """ - See https://llvm.org/docs/Passes.html#sink-code-sinking +ffi.lib.LLVMPY_LLVMAddLoopRotatePass_module.argtypes = [ + ffi.LLVMModulePassManagerRef,] - LLVM 14: `llvm::createSinkingPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddSinkPass(self) +ffi.lib.LLVMPY_LLVMAddInstructionCombinePass_module.argtypes = [ + ffi.LLVMModulePassManagerRef,] - def add_strip_symbols_pass(self, only_debug=False): - """ - See https://llvm.org/docs/Passes.html#strip-strip-all-symbols-from-a-module +ffi.lib.LLVMPY_AddJumpThreadingPass_module.argtypes = [ + ffi.LLVMModulePassManagerRef,] - LLVM 14: `llvm::createStripSymbolsPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddStripSymbolsPass(self, only_debug) +ffi.lib.LLVMPY_DisposeNewModulePassManger.argtypes = [ + ffi.LLVMModulePassManagerRef,] - def add_strip_dead_debug_info_pass(self): - """ - See https://llvm.org/docs/Passes.html#strip-dead-debug-info-strip-debug-info-for-unused-symbols +ffi.lib.LLVMPY_CreateNewFunctionPassManager.restype = \ + ffi.LLVMFunctionPassManagerRef - LLVM 14: `llvm::createStripDeadDebugInfoPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddStripDeadDebugInfoPass(self) +ffi.lib.LLVMPY_RunFunctionPassManager.argtypes = [ + ffi.LLVMFunctionPassManagerRef, + ffi.LLVMPassBuilderRef, + ffi.LLVMValueRef,] - def add_strip_dead_prototypes_pass(self): - """ - See https://llvm.org/docs/Passes.html#strip-dead-prototypes-strip-unused-function-prototypes +ffi.lib.LLVMPY_AddAAEvalPass_function.argtypes = [ + ffi.LLVMFunctionPassManagerRef,] - LLVM 14: `llvm::createStripDeadPrototypesPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddStripDeadPrototypesPass(self) +ffi.lib.LLVMPY_AddSimplifyCFGPass_function.argtypes = [ + ffi.LLVMFunctionPassManagerRef,] - def add_strip_debug_declare_pass(self): - """ - See https://llvm.org/docs/Passes.html#strip-debug-declare-strip-all-llvm-dbg-declare-intrinsics +ffi.lib.LLVMPY_AddLoopUnrollPass_function.argtypes = [ + ffi.LLVMFunctionPassManagerRef,] - LLVM 14: `llvm::createStripDebugDeclarePass` - """ # noqa E501 - ffi.lib.LLVMPY_AddStripDebugDeclarePrototypesPass(self) +ffi.lib.LLVMPY_LLVMAddLoopRotatePass_function.argtypes = [ + ffi.LLVMFunctionPassManagerRef,] - def add_strip_nondebug_symbols_pass(self): - """ - See https://llvm.org/docs/Passes.html#strip-nondebug-strip-all-symbols-except-dbg-symbols-from-a-module +ffi.lib.LLVMPY_LLVMAddInstructionCombinePass_function.argtypes = [ + ffi.LLVMFunctionPassManagerRef,] - LLVM 14: `llvm::createStripNonDebugSymbolsPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddStripNondebugSymbolsPass(self) +ffi.lib.LLVMPY_AddJumpThreadingPass_function.argtypes = [ + ffi.LLVMFunctionPassManagerRef, c_int,] - def add_tail_call_elimination_pass(self): - """ - See https://llvm.org/docs/Passes.html#tailcallelim-tail-call-elimination +ffi.lib.LLVMPY_DisposeNewFunctionPassManger.argtypes = [ + ffi.LLVMFunctionPassManagerRef,] - LLVM 14: `llvm::createTailCallEliminationPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddTailCallEliminationPass(self) +ffi.lib.LLVMPY_CreatePassBuilder.restype = ffi.LLVMPassBuilderRef +ffi.lib.LLVMPY_CreatePassBuilder.argtypes = [ffi.LLVMTargetMachineRef, + ffi.LLVMPipelineTuningOptionsRef,] - def add_type_based_alias_analysis_pass(self): - """ - LLVM 14: `LLVMAddTypeBasedAliasAnalysisPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddTypeBasedAliasAnalysisPass(self) +ffi.lib.LLVMPY_buildPerModuleDefaultPipeline.restype = \ + ffi.LLVMModulePassManagerRef - def add_basic_alias_analysis_pass(self): - """ - See http://llvm.org/docs/AliasAnalysis.html#the-basicaa-pass +ffi.lib.LLVMPY_buildPerModuleDefaultPipeline.argtypes = [ + ffi.LLVMPassBuilderRef, c_int,] - LLVM 14: `LLVMAddBasicAliasAnalysisPass` - """ - ffi.lib.LLVMPY_AddBasicAliasAnalysisPass(self) +ffi.lib.LLVMPY_buildFunctionSimplificationPipeline.restype = \ + ffi.LLVMFunctionPassManagerRef - def add_loop_rotate_pass(self): - """http://llvm.org/docs/Passes.html#loop-rotate-rotate-loops.""" - ffi.lib.LLVMPY_LLVMAddLoopRotatePass(self) +ffi.lib.LLVMPY_buildFunctionSimplificationPipeline.argtypes = [ + ffi.LLVMPassBuilderRef, c_int,] - def add_target_library_info(self, triple): - ffi.lib.LLVMPY_AddTargetLibraryInfoPass(self, _encode_string(triple)) +ffi.lib.LLVMPY_DisposePassBuilder.argtypes = [ffi.LLVMPassBuilderRef,] - def add_instruction_namer_pass(self): - """ - See https://llvm.org/docs/Passes.html#instnamer-assign-names-to-anonymous-instructions. - - LLVM 14: `llvm::createInstructionNamerPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddInstructionNamerPass(self) - - # Non-standard LLVM passes - - def add_refprune_pass(self, subpasses_flags=RefPruneSubpasses.ALL, - subgraph_limit=1000): - """Add Numba specific Reference count pruning pass. - - Parameters - ---------- - subpasses_flags : RefPruneSubpasses - A bitmask to control the subpasses to be enabled. - subgraph_limit : int - Limit the fanout pruners to working on a subgraph no bigger than - this number of basic-blocks to avoid spending too much time in very - large graphs. Default is 1000. Subject to change in future - versions. - """ - iflags = RefPruneSubpasses(subpasses_flags) - ffi.lib.LLVMPY_AddRefPrunePass(self, iflags, subgraph_limit) +ffi.lib.LLVMPY_CreatePipelineTuningOptions.restype = \ + ffi.LLVMPipelineTuningOptionsRef +ffi.lib.LLVMPY_PTOGetLoopInterleaving.restype = c_bool +ffi.lib.LLVMPY_PTOGetLoopInterleaving.argtypes = [ + ffi.LLVMPipelineTuningOptionsRef,] -class ModulePassManager(PassManager): +ffi.lib.LLVMPY_PTOSetLoopInterleaving.argtypes = [ + ffi.LLVMPipelineTuningOptionsRef, c_bool] - def __init__(self, ptr=None): - if ptr is None: - ptr = ffi.lib.LLVMPY_CreatePassManager() - PassManager.__init__(self, ptr) +ffi.lib.LLVMPY_PTOGetLoopVectorization.restype = c_bool +ffi.lib.LLVMPY_PTOGetLoopVectorization.argtypes = [ + ffi.LLVMPipelineTuningOptionsRef,] - def run(self, module, remarks_file=None, remarks_format='yaml', - remarks_filter=''): - """ - Run optimization passes on the given module. - - Parameters - ---------- - module : llvmlite.binding.ModuleRef - The module to be optimized inplace - remarks_file : str; optional - If not `None`, it is the file to store the optimization remarks. - remarks_format : str; optional - The format to write; YAML is default - remarks_filter : str; optional - The filter that should be applied to the remarks output. - """ - if remarks_file is None: - return ffi.lib.LLVMPY_RunPassManager(self, module) - else: - r = ffi.lib.LLVMPY_RunPassManagerWithRemarks( - self, module, _encode_string(remarks_format), - _encode_string(remarks_filter), - _encode_string(remarks_file)) - if r == -1: - raise IOError("Failed to initialize remarks file.") - return r > 0 - - def run_with_remarks(self, module, remarks_format='yaml', - remarks_filter=''): - """ - Run optimization passes on the given module and returns the result and - the remarks data. - - Parameters - ---------- - module : llvmlite.binding.ModuleRef - The module to be optimized - remarks_format : str - The remarks output; YAML is the default - remarks_filter : str; optional - The filter that should be applied to the remarks output. - """ - remarkdesc, remarkfile = mkstemp() - try: - with os.fdopen(remarkdesc, 'r'): - pass - r = self.run(module, remarkfile, remarks_format, remarks_filter) - if r == -1: - raise IOError("Failed to initialize remarks file.") - with open(remarkfile) as f: - return bool(r), f.read() - finally: - os.unlink(remarkfile) - - -class FunctionPassManager(PassManager): - - def __init__(self, module): - ptr = ffi.lib.LLVMPY_CreateFunctionPassManager(module) - self._module = module - module._owned = True - PassManager.__init__(self, ptr) - - def initialize(self): - """ - Initialize the FunctionPassManager. Returns True if it produced - any changes (?). - """ - return ffi.lib.LLVMPY_InitializeFunctionPassManager(self) +ffi.lib.LLVMPY_PTOSetLoopVectorization.argtypes = [ + ffi.LLVMPipelineTuningOptionsRef, c_bool] - def finalize(self): - """ - Finalize the FunctionPassManager. Returns True if it produced - any changes (?). - """ - return ffi.lib.LLVMPY_FinalizeFunctionPassManager(self) +ffi.lib.LLVMPY_PTOGetSLPVectorization.restype = c_bool +ffi.lib.LLVMPY_PTOGetSLPVectorization.argtypes = [ + ffi.LLVMPipelineTuningOptionsRef,] - def run(self, function, remarks_file=None, remarks_format='yaml', - remarks_filter=''): - """ - Run optimization passes on the given function. - - Parameters - ---------- - function : llvmlite.binding.FunctionRef - The function to be optimized inplace - remarks_file : str; optional - If not `None`, it is the file to store the optimization remarks. - remarks_format : str; optional - The format of the remarks file; the default is YAML - remarks_filter : str; optional - The filter that should be applied to the remarks output. - """ - if remarks_file is None: - return ffi.lib.LLVMPY_RunFunctionPassManager(self, function) - else: - r = ffi.lib.LLVMPY_RunFunctionPassManagerWithRemarks( - self, function, _encode_string(remarks_format), - _encode_string(remarks_filter), - _encode_string(remarks_file)) - if r == -1: - raise IOError("Failed to initialize remarks file.") - return bool(r) - - def run_with_remarks(self, function, remarks_format='yaml', - remarks_filter=''): - """ - Run optimization passes on the given function and returns the result - and the remarks data. - - Parameters - ---------- - function : llvmlite.binding.FunctionRef - The function to be optimized inplace - remarks_format : str; optional - The format of the remarks file; the default is YAML - remarks_filter : str; optional - The filter that should be applied to the remarks output. - """ - # LLVM is going to need to close this file and then reopen it, so we - # can't use an unlinked temporary file. - remarkdesc, remarkfile = mkstemp() - try: - # We get an open handle, but we need LLVM to write first, so close - # it. - with os.fdopen(remarkdesc, 'r'): - pass - r = self.run(function, remarkfile, remarks_format, remarks_filter) - if r == -1: - raise IOError("Failed to initialize remarks file.") - with open(remarkfile) as f: - return bool(r), f.read() - finally: - os.unlink(remarkfile) +ffi.lib.LLVMPY_PTOSetSLPVectorization.argtypes = [ + ffi.LLVMPipelineTuningOptionsRef, c_bool] +ffi.lib.LLVMPY_PTOGetLoopUnrolling.restype = c_bool +ffi.lib.LLVMPY_PTOGetLoopUnrolling.argtypes = [ + ffi.LLVMPipelineTuningOptionsRef,] -# ============================================================================ -# FFI +ffi.lib.LLVMPY_PTOSetLoopUnrolling.argtypes = [ + ffi.LLVMPipelineTuningOptionsRef, c_bool] -ffi.lib.LLVMPY_CreatePassManager.restype = ffi.LLVMPassManagerRef - -ffi.lib.LLVMPY_CreateFunctionPassManager.argtypes = [ffi.LLVMModuleRef] -ffi.lib.LLVMPY_CreateFunctionPassManager.restype = ffi.LLVMPassManagerRef - -ffi.lib.LLVMPY_DisposePassManager.argtypes = [ffi.LLVMPassManagerRef] - -ffi.lib.LLVMPY_RunPassManager.argtypes = [ffi.LLVMPassManagerRef, - ffi.LLVMModuleRef] -ffi.lib.LLVMPY_RunPassManager.restype = c_bool - -ffi.lib.LLVMPY_RunPassManagerWithRemarks.argtypes = [ffi.LLVMPassManagerRef, - ffi.LLVMModuleRef, - c_char_p, - c_char_p, - c_char_p] -ffi.lib.LLVMPY_RunPassManagerWithRemarks.restype = c_int - -ffi.lib.LLVMPY_InitializeFunctionPassManager.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_InitializeFunctionPassManager.restype = c_bool - -ffi.lib.LLVMPY_FinalizeFunctionPassManager.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_FinalizeFunctionPassManager.restype = c_bool - -ffi.lib.LLVMPY_RunFunctionPassManager.argtypes = [ffi.LLVMPassManagerRef, - ffi.LLVMValueRef] -ffi.lib.LLVMPY_RunFunctionPassManager.restype = c_bool - -ffi.lib.LLVMPY_RunFunctionPassManagerWithRemarks.argtypes = [ - ffi.LLVMPassManagerRef, ffi.LLVMValueRef, c_char_p, c_char_p, c_char_p -] -ffi.lib.LLVMPY_RunFunctionPassManagerWithRemarks.restype = c_int - -ffi.lib.LLVMPY_AddAAEvalPass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddBasicAAWrapperPass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddConstantMergePass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddDeadArgEliminationPass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddDependenceAnalysisPass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddCallGraphDOTPrinterPass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddCFGPrinterPass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddDotDomPrinterPass.argtypes = [ffi.LLVMPassManagerRef, c_bool] -ffi.lib.LLVMPY_AddDotPostDomPrinterPass.argtypes = [ - ffi.LLVMPassManagerRef, - c_bool] -ffi.lib.LLVMPY_AddGlobalsModRefAAPass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddInstructionCountPass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddIVUsersPass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddLazyValueInfoPass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddLintPass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddModuleDebugInfoPrinterPass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddRegionInfoPass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddScalarEvolutionAAPass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddAggressiveDCEPass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddAlwaysInlinerPass.argtypes = [ffi.LLVMPassManagerRef, c_bool] - -if llvm_version_major < 15: - ffi.lib.LLVMPY_AddArgPromotionPass.argtypes = [ - ffi.LLVMPassManagerRef, c_uint] - -ffi.lib.LLVMPY_AddBreakCriticalEdgesPass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddDeadStoreEliminationPass.argtypes = [ - ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddReversePostOrderFunctionAttrsPass.argtypes = [ - ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddAggressiveInstructionCombiningPass.argtypes = [ - ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddInternalizePass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddLCSSAPass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddLoopDeletionPass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddLoopExtractorPass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddSingleLoopExtractorPass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddLoopStrengthReducePass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddLoopSimplificationPass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddLoopUnrollPass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddLoopUnrollAndJamPass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddLoopUnswitchPass.argtypes = [ffi.LLVMPassManagerRef, c_bool, - c_bool] -ffi.lib.LLVMPY_AddLowerAtomicPass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddLowerInvokePass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddLowerSwitchPass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddMemCpyOptimizationPass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddMergeFunctionsPass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddMergeReturnsPass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddPartialInliningPass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddPruneExceptionHandlingPass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddReassociatePass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddDemoteRegisterToMemoryPass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddSinkPass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddStripSymbolsPass.argtypes = [ffi.LLVMPassManagerRef, c_bool] -ffi.lib.LLVMPY_AddStripDeadDebugInfoPass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddStripDeadPrototypesPass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddStripDebugDeclarePrototypesPass.argtypes = [ - ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddStripNondebugSymbolsPass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddTailCallEliminationPass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddJumpThreadingPass.argtypes = [ffi.LLVMPassManagerRef, c_int] -ffi.lib.LLVMPY_AddFunctionAttrsPass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddFunctionInliningPass.argtypes = [ - ffi.LLVMPassManagerRef, c_int] -ffi.lib.LLVMPY_AddGlobalDCEPass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddGlobalOptimizerPass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddIPSCCPPass.argtypes = [ffi.LLVMPassManagerRef] - -ffi.lib.LLVMPY_AddDeadCodeEliminationPass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddCFGSimplificationPass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddGVNPass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddInstructionCombiningPass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddLICMPass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddSCCPPass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddSROAPass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddTypeBasedAliasAnalysisPass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddBasicAliasAnalysisPass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddTargetLibraryInfoPass.argtypes = [ffi.LLVMPassManagerRef, - c_char_p] -ffi.lib.LLVMPY_AddInstructionNamerPass.argtypes = [ffi.LLVMPassManagerRef] - -ffi.lib.LLVMPY_AddRefPrunePass.argtypes = [ffi.LLVMPassManagerRef, c_int, - c_size_t] - -ffi.lib.LLVMPY_DumpRefPruneStats.argtypes = [POINTER(_c_PruneStats), c_bool] +ffi.lib.LLVMPY_DisposePipelineTuningOptions.argtypes = \ + [ffi.LLVMPipelineTuningOptionsRef,] diff --git a/llvmlite/binding/transforms.py b/llvmlite/binding/transforms.py deleted file mode 100644 index 82c5dc157..000000000 --- a/llvmlite/binding/transforms.py +++ /dev/null @@ -1,151 +0,0 @@ -from ctypes import c_uint, c_bool -from llvmlite.binding import ffi -from llvmlite.binding import passmanagers - - -def create_pass_manager_builder(): - return PassManagerBuilder() - - -class PassManagerBuilder(ffi.ObjectRef): - __slots__ = () - - def __init__(self, ptr=None): - if ptr is None: - ptr = ffi.lib.LLVMPY_PassManagerBuilderCreate() - ffi.ObjectRef.__init__(self, ptr) - - @property - def opt_level(self): - """ - The general optimization level as an integer between 0 and 3. - """ - return ffi.lib.LLVMPY_PassManagerBuilderGetOptLevel(self) - - @opt_level.setter - def opt_level(self, level): - ffi.lib.LLVMPY_PassManagerBuilderSetOptLevel(self, level) - - @property - def size_level(self): - """ - Whether and how much to optimize for size. An integer between 0 and 2. - """ - return ffi.lib.LLVMPY_PassManagerBuilderGetSizeLevel(self) - - @size_level.setter - def size_level(self, size): - ffi.lib.LLVMPY_PassManagerBuilderSetSizeLevel(self, size) - - @property - def inlining_threshold(self): - """ - The integer threshold for inlining a function into another. The higher, - the more likely inlining a function is. This attribute is write-only. - """ - raise NotImplementedError("inlining_threshold is write-only") - - @inlining_threshold.setter - def inlining_threshold(self, threshold): - ffi.lib.LLVMPY_PassManagerBuilderUseInlinerWithThreshold( - self, threshold) - - @property - def disable_unroll_loops(self): - """ - If true, disable loop unrolling. - """ - return ffi.lib.LLVMPY_PassManagerBuilderGetDisableUnrollLoops(self) - - @disable_unroll_loops.setter - def disable_unroll_loops(self, disable=True): - ffi.lib.LLVMPY_PassManagerBuilderSetDisableUnrollLoops(self, disable) - - @property - def loop_vectorize(self): - """ - If true, allow vectorizing loops. - """ - return ffi.lib.LLVMPY_PassManagerBuilderGetLoopVectorize(self) - - @loop_vectorize.setter - def loop_vectorize(self, enable=True): - return ffi.lib.LLVMPY_PassManagerBuilderSetLoopVectorize(self, enable) - - @property - def slp_vectorize(self): - """ - If true, enable the "SLP vectorizer", which uses a different algorithm - from the loop vectorizer. Both may be enabled at the same time. - """ - return ffi.lib.LLVMPY_PassManagerBuilderGetSLPVectorize(self) - - @slp_vectorize.setter - def slp_vectorize(self, enable=True): - return ffi.lib.LLVMPY_PassManagerBuilderSetSLPVectorize(self, enable) - - def _populate_module_pm(self, pm): - ffi.lib.LLVMPY_PassManagerBuilderPopulateModulePassManager(self, pm) - - def _populate_function_pm(self, pm): - ffi.lib.LLVMPY_PassManagerBuilderPopulateFunctionPassManager(self, pm) - - def populate(self, pm): - if isinstance(pm, passmanagers.ModulePassManager): - self._populate_module_pm(pm) - elif isinstance(pm, passmanagers.FunctionPassManager): - self._populate_function_pm(pm) - else: - raise TypeError(pm) - - def _dispose(self): - self._capi.LLVMPY_PassManagerBuilderDispose(self) - - -# ============================================================================ -# FFI - -ffi.lib.LLVMPY_PassManagerBuilderCreate.restype = ffi.LLVMPassManagerBuilderRef - -ffi.lib.LLVMPY_PassManagerBuilderDispose.argtypes = [ - ffi.LLVMPassManagerBuilderRef, -] - -ffi.lib.LLVMPY_PassManagerBuilderPopulateModulePassManager.argtypes = [ - ffi.LLVMPassManagerBuilderRef, - ffi.LLVMPassManagerRef, -] - -ffi.lib.LLVMPY_PassManagerBuilderPopulateFunctionPassManager.argtypes = [ - ffi.LLVMPassManagerBuilderRef, - ffi.LLVMPassManagerRef, -] - -# Unsigned int PassManagerBuilder properties - -for _func in (ffi.lib.LLVMPY_PassManagerBuilderSetOptLevel, - ffi.lib.LLVMPY_PassManagerBuilderSetSizeLevel, - ffi.lib.LLVMPY_PassManagerBuilderUseInlinerWithThreshold, - ): - _func.argtypes = [ffi.LLVMPassManagerBuilderRef, c_uint] - -for _func in (ffi.lib.LLVMPY_PassManagerBuilderGetOptLevel, - ffi.lib.LLVMPY_PassManagerBuilderGetSizeLevel, - ): - _func.argtypes = [ffi.LLVMPassManagerBuilderRef] - _func.restype = c_uint - -# Boolean PassManagerBuilder properties - -for _func in (ffi.lib.LLVMPY_PassManagerBuilderSetDisableUnrollLoops, - ffi.lib.LLVMPY_PassManagerBuilderSetLoopVectorize, - ffi.lib.LLVMPY_PassManagerBuilderSetSLPVectorize, - ): - _func.argtypes = [ffi.LLVMPassManagerBuilderRef, c_bool] - -for _func in (ffi.lib.LLVMPY_PassManagerBuilderGetDisableUnrollLoops, - ffi.lib.LLVMPY_PassManagerBuilderGetLoopVectorize, - ffi.lib.LLVMPY_PassManagerBuilderGetSLPVectorize, - ): - _func.argtypes = [ffi.LLVMPassManagerBuilderRef] - _func.restype = c_bool diff --git a/llvmlite/tests/test_binding.py b/llvmlite/tests/test_binding.py index be0886da6..fdab23110 100644 --- a/llvmlite/tests/test_binding.py +++ b/llvmlite/tests/test_binding.py @@ -2245,7 +2245,7 @@ def run(use_tli): mod = llvm.parse_assembly(asm_tli_exp2) target = llvm.Target.from_triple(mod.triple) tm = target.create_target_machine() - pm = llvm.ModulePassManager() + pm = llvm.LegacyModulePassManager() tm.add_analysis_passes(pm) if use_tli: pm.add_target_library_info(mod.triple) @@ -2267,7 +2267,7 @@ def test_instruction_namer_pass(self): mod = llvm.parse_assembly(asm) # Run instnamer pass - pm = llvm.ModulePassManager() + pm = llvm.LegacyModulePassManager() pm.add_instruction_namer_pass() pm.run(mod) @@ -2621,13 +2621,13 @@ def test_close(self): def test_getMPM(self): pb = self.pb() - mpm = pb.getNewModulePassManager() + mpm = pb.getModulePassManager() mpm.run(self.module(), pb) pb.close() def test_getFPM(self): pb = self.pb() - fpm = pb.getNewFunctionPassManager() + fpm = pb.getFunctionPassManager() fpm.run(self.module().get_function("sum"), pb) pb.close() @@ -2644,7 +2644,7 @@ def test_run(self): pb = self.pb(3) mod = self.module() orig_asm = str(mod) - mpm = pb.getNewModulePassManager() + mpm = pb.getModulePassManager() mpm.run(mod, pb) optimized_asm = str(mod) self.assertIn("%.4", orig_asm) @@ -2685,7 +2685,7 @@ def test_run(self): mod = self.module() fun = mod.get_function("sum") orig_asm = str(fun) - fpm = pb.getNewFunctionPassManager() + fpm = pb.getFunctionPassManager() fpm.run(fun, pb) optimized_asm = str(fun) self.assertIn("%.4", orig_asm) diff --git a/llvmlite/tests/test_refprune.py b/llvmlite/tests/test_refprune.py index 0c4208a26..1e15b918e 100644 --- a/llvmlite/tests/test_refprune.py +++ b/llvmlite/tests/test_refprune.py @@ -116,7 +116,7 @@ def generate_ir(self, nodes, edges): def apply_refprune(self, irmod): mod = llvm.parse_assembly(str(irmod)) - pm = llvm.ModulePassManager() + pm = llvm.LegacyModulePassManager() pm.add_refprune_pass() pm.run(mod) return mod @@ -168,7 +168,7 @@ class BaseTestByIR(TestCase): def check(self, irmod, subgraph_limit=None): mod = llvm.parse_assembly(f"{self.prologue}\n{irmod}") - pm = llvm.ModulePassManager() + pm = llvm.LegacyModulePassManager() if subgraph_limit is None: pm.add_refprune_pass(self.refprune_bitmask) else: From d07559b3f3db51ce78a4815178851325b7c42abb Mon Sep 17 00:00:00 2001 From: Yashwant Singh Date: Tue, 14 May 2024 16:51:54 +0530 Subject: [PATCH 06/27] Revert "Prefix old pass manager code with "legacy" prefix" This reverts commit 5e9c0b94ccdcb88e697a5274bc27c1c11499b312. --- .../binding/optimization-passes.rst | 10 +- .../user-guide/binding/target-information.rst | 2 +- docs/source/user-guide/examples/npm-usage.py | 6 +- ffi/CMakeLists.txt | 6 +- ffi/Makefile.freebsd | 4 +- ffi/Makefile.linux | 4 +- ffi/Makefile.osx | 4 +- ffi/legacypassmanagers.cpp | 580 --------- ffi/newpassmanagers.cpp | 317 +++++ ffi/passmanagers.cpp | 560 ++++++--- ffi/transforms.cpp | 96 ++ llvmlite/binding/__init__.py | 5 +- llvmlite/binding/legacypassmanagers.py | 1088 ----------------- llvmlite/binding/newpassmangers.py | 305 +++++ llvmlite/binding/passmanagers.py | 1046 ++++++++++++---- llvmlite/binding/transforms.py | 151 +++ llvmlite/tests/test_binding.py | 12 +- llvmlite/tests/test_refprune.py | 4 +- 18 files changed, 2103 insertions(+), 2097 deletions(-) delete mode 100644 ffi/legacypassmanagers.cpp create mode 100644 ffi/newpassmanagers.cpp create mode 100644 ffi/transforms.cpp delete mode 100644 llvmlite/binding/legacypassmanagers.py create mode 100644 llvmlite/binding/newpassmangers.py create mode 100644 llvmlite/binding/transforms.py diff --git a/docs/source/user-guide/binding/optimization-passes.rst b/docs/source/user-guide/binding/optimization-passes.rst index 5ec8865b3..7894e4785 100644 --- a/docs/source/user-guide/binding/optimization-passes.rst +++ b/docs/source/user-guide/binding/optimization-passes.rst @@ -8,10 +8,10 @@ LLVM gives you the opportunity to fine-tune optimization passes. Optimization passes are managed by a pass manager. There are 2 kinds of pass managers: -* :class:`LegacyFunctionPassManager`, for optimizations that work on +* :class:`FunctionPassManager`, for optimizations that work on single functions. -* :class:`LegacyModulePassManager`, for optimizations that work on +* :class:`ModulePassManager`, for optimizations that work on whole modules. To instantiate either of these pass managers, you first need to @@ -62,7 +62,7 @@ create and configure a :class:`PassManagerBuilder`. be enabled at the same time. -.. class:: LegacyPassManager +.. class:: PassManager The base class for pass managers. Use individual ``add_*`` methods or :meth:`PassManagerBuilder.populate` to add @@ -141,7 +141,7 @@ create and configure a :class:`PassManagerBuilder`. See `instnamer pass documentation `_. -.. class:: LegacyModulePassManager() +.. class:: ModulePassManager() Create a new pass manager to run optimization passes on a module. @@ -156,7 +156,7 @@ create and configure a :class:`PassManagerBuilder`. Returns ``True`` if the optimizations made any modification to the module. Otherwise returns ``False``. -.. class:: LegacyFunctionPassManager(module) +.. class:: FunctionPassManager(module) Create a new pass manager to run optimization passes on a function of the given *module*, a :class:`ModuleRef` instance. diff --git a/docs/source/user-guide/binding/target-information.rst b/docs/source/user-guide/binding/target-information.rst index 33f941787..96376a072 100644 --- a/docs/source/user-guide/binding/target-information.rst +++ b/docs/source/user-guide/binding/target-information.rst @@ -164,7 +164,7 @@ Classes * .. method:: add_analysis_passes(pm) Register analysis passes for this target machine with the - :class:`LegacyPassManager` instance *pm*. + :class:`PassManager` instance *pm*. * .. method:: emit_object(module) diff --git a/docs/source/user-guide/examples/npm-usage.py b/docs/source/user-guide/examples/npm-usage.py index 4b957bce6..51a6d673b 100644 --- a/docs/source/user-guide/examples/npm-usage.py +++ b/docs/source/user-guide/examples/npm-usage.py @@ -205,7 +205,7 @@ pto = llvm.create_pipeline_options() pto.opt_level = 2 # similarly more properties can be set pb = llvm.create_pass_builder(tm, pto) -npm_o2 = pb.getModulePassManager() +npm_o2 = pb.getNewModulePassManager() npm_o2.run(llmod, pb) print(llmod) @@ -224,7 +224,7 @@ pb = llvm.create_pass_builder(tm, pto) fun = llmod2.get_function("n") print(fun) -fpm = pb.getFunctionPassManager() +fpm = pb.getNewFunctionPassManager() fpm.add_simplify_cfg_pass() fpm.run(fun, pb) print(fun) @@ -238,7 +238,7 @@ pto.opt_level = 3 # similarly more properties can be set pto.loop_unrolling = False pb = llvm.create_pass_builder(tm, pto) -npm = pb.getModulePassManager() +npm = pb.getNewModulePassManager() # # Inplace optimize the IR module npm.run(llmod_unroll, pb) print(llmod_unroll) diff --git a/ffi/CMakeLists.txt b/ffi/CMakeLists.txt index 41a41cf90..d5b964bfe 100755 --- a/ffi/CMakeLists.txt +++ b/ffi/CMakeLists.txt @@ -42,9 +42,9 @@ endif() # Define our shared library add_library(llvmlite SHARED assembly.cpp bitcode.cpp core.cpp initfini.cpp - module.cpp value.cpp executionengine.cpp type.cpp - legacypassmanagers.cpp targets.cpp dylib.cpp linker.cpp object_file.cpp - custom_passes.cpp orcjit.cpp memorymanager.cpp passmanagers.cpp) + module.cpp value.cpp executionengine.cpp transforms.cpp type.cpp + passmanagers.cpp targets.cpp dylib.cpp linker.cpp object_file.cpp + custom_passes.cpp orcjit.cpp memorymanager.cpp newpassmanagers.cpp) # Find the libraries that correspond to the LLVM components # that we wish to use. diff --git a/ffi/Makefile.freebsd b/ffi/Makefile.freebsd index ee9a1b752..09635d910 100644 --- a/ffi/Makefile.freebsd +++ b/ffi/Makefile.freebsd @@ -10,9 +10,9 @@ LDFLAGS := $(LDFLAGS) $(LLVM_LDFLAGS) $(LD_FLTO_FLAGS) LIBS = $(LLVM_LIBS) INCLUDE = core.h SRC = assembly.cpp bitcode.cpp core.cpp initfini.cpp module.cpp value.cpp \ - executionengine.cpp legacypassmanagers.cpp type.cpp targets.cpp \ + executionengine.cpp transforms.cpp passmanagers.cpp type.cpp targets.cpp \ dylib.cpp linker.cpp object_file.cpp orcjit.cpp custom_passes.cpp \ - memorymanager.cpp passmanagers.cpp + memorymanager.cpp OUTPUT = libllvmlite.so all: $(OUTPUT) diff --git a/ffi/Makefile.linux b/ffi/Makefile.linux index 5cc02c7f7..560d94de5 100644 --- a/ffi/Makefile.linux +++ b/ffi/Makefile.linux @@ -12,8 +12,8 @@ LDFLAGS := $(LDFLAGS) $(LLVM_LDFLAGS) $(LD_FLTO_FLAGS) LIBS = $(LLVM_LIBS) INCLUDE = core.h OBJ = assembly.o bitcode.o core.o initfini.o module.o value.o \ - executionengine.o legacypassmanagers.o targets.o type.o dylib.o \ - linker.o object_file.o custom_passes.o orcjit.o memorymanager.o passmanagers.o + executionengine.o transforms.o passmanagers.o targets.o type.o dylib.o \ + linker.o object_file.o custom_passes.o orcjit.o memorymanager.o newpassmanagers.o OUTPUT = libllvmlite.so all: $(OUTPUT) diff --git a/ffi/Makefile.osx b/ffi/Makefile.osx index 7feff8d0b..afe4f3bac 100644 --- a/ffi/Makefile.osx +++ b/ffi/Makefile.osx @@ -7,9 +7,9 @@ LDFLAGS := $(LDFLAGS) $(EXPORT) $(LLVM_LDFLAGS) LIBS = $(LLVM_LIBS) INCLUDE = core.h SRC = assembly.cpp bitcode.cpp core.cpp initfini.cpp module.cpp value.cpp \ - executionengine.cpp legacypassmanagers.cpp targets.cpp type.cpp \ + executionengine.cpp transforms.cpp passmanagers.cpp targets.cpp type.cpp \ dylib.cpp linker.cpp object_file.cpp custom_passes.cpp orcjit.cpp \ - memorymanager.cpp passmanagers.cpp + memorymanager.cpp OUTPUT = libllvmlite.dylib MACOSX_DEPLOYMENT_TARGET ?= 10.9 diff --git a/ffi/legacypassmanagers.cpp b/ffi/legacypassmanagers.cpp deleted file mode 100644 index 0bc7b4c87..000000000 --- a/ffi/legacypassmanagers.cpp +++ /dev/null @@ -1,580 +0,0 @@ -#include - -#include "core.h" - -#include "llvm-c/Transforms/IPO.h" -#include "llvm-c/Transforms/Scalar.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/IR/DiagnosticInfo.h" -#include "llvm/IR/DiagnosticPrinter.h" -#include "llvm/IR/LegacyPassManager.h" -#include "llvm/IR/Module.h" -#include "llvm/Support/FileSystem.h" -#include "llvm/Support/ToolOutputFile.h" -#include "llvm/Support/YAMLTraits.h" -#include "llvm/Support/raw_ostream.h" - -#include "core.h" -#include "llvm-c/Target.h" -#include "llvm-c/Transforms/IPO.h" -#include "llvm-c/Transforms/PassManagerBuilder.h" -#include "llvm-c/Transforms/Scalar.h" -#include "llvm/IR/LLVMRemarkStreamer.h" -#include "llvm/IR/LegacyPassManager.h" -#include "llvm/Remarks/RemarkStreamer.h" -#include "llvm/Transforms/IPO.h" -#include "llvm/Transforms/IPO/PassManagerBuilder.h" -#include "llvm/Transforms/Scalar.h" - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -using namespace llvm; - -/* - * Exposed API - */ - -extern "C" { - -API_EXPORT(void) -LLVMPY_SetTimePasses(bool enable) { TimePassesIsEnabled = enable; } - -API_EXPORT(void) -LLVMPY_ReportAndResetTimings(const char **outmsg) { - std::string osbuf; - raw_string_ostream os(osbuf); - reportAndResetTimings(&os); - os.flush(); - *outmsg = LLVMPY_CreateString(os.str().c_str()); -} - -API_EXPORT(LLVMPassManagerRef) -LLVMPY_CreateLegacyPassManager() { return LLVMCreatePassManager(); } - -API_EXPORT(void) -LLVMPY_DisposeLegacyPassManager(LLVMPassManagerRef PM) { - return LLVMDisposePassManager(PM); -} - -API_EXPORT(LLVMPassManagerRef) -LLVMPY_CreateLegacyFunctionPassManager(LLVMModuleRef M) { - return LLVMCreateFunctionPassManagerForModule(M); -} - -API_EXPORT(int) -LLVMPY_RunPassManagerWithLegacyRemarks(LLVMPassManagerRef PM, LLVMModuleRef M, - const char *remarks_format, - const char *remarks_filter, - const char *record_filename) { - auto setupResult = llvm::setupLLVMOptimizationRemarks( - unwrap(M)->getContext(), record_filename, remarks_filter, - remarks_format, true); - if (!setupResult) { - return -1; - } - auto optimisationFile = std::move(*setupResult); - auto r = LLVMRunPassManager(PM, M); - - unwrap(M)->getContext().setMainRemarkStreamer(nullptr); - unwrap(M)->getContext().setLLVMRemarkStreamer(nullptr); - - optimisationFile->keep(); - optimisationFile->os().flush(); - return r; -} - -API_EXPORT(int) -LLVMPY_RunLegacyPassManager(LLVMPassManagerRef PM, LLVMModuleRef M) { - return LLVMRunPassManager(PM, M); -} - -API_EXPORT(int) -LLVMPY_RunLegacyFunctionPassManagerWithRemarks(LLVMPassManagerRef PM, - LLVMValueRef F, - const char *remarks_format, - const char *remarks_filter, - const char *record_filename) { - auto setupResult = llvm::setupLLVMOptimizationRemarks( - unwrap(F)->getContext(), record_filename, remarks_filter, - remarks_format, true); - if (!setupResult) { - return -1; - } - auto optimisationFile = std::move(*setupResult); - - auto r = LLVMRunFunctionPassManager(PM, F); - - unwrap(F)->getContext().setMainRemarkStreamer(nullptr); - unwrap(F)->getContext().setLLVMRemarkStreamer(nullptr); - - optimisationFile->keep(); - optimisationFile->os().flush(); - return r; -} - -API_EXPORT(int) -LLVMPY_RunLegacyFunctionPassManager(LLVMPassManagerRef PM, LLVMValueRef F) { - return LLVMRunFunctionPassManager(PM, F); -} - -API_EXPORT(int) -LLVMPY_InitializeLegacyFunctionPassManager(LLVMPassManagerRef FPM) { - return LLVMInitializeFunctionPassManager(FPM); -} - -API_EXPORT(int) -LLVMPY_FinalizeLegacyFunctionPassManager(LLVMPassManagerRef FPM) { - return LLVMFinalizeFunctionPassManager(FPM); -} - -API_EXPORT(void) -LLVMPY_AddAAEvalPass(LLVMPassManagerRef PM) { - unwrap(PM)->add(llvm::createAAEvalPass()); -} - -API_EXPORT(void) -LLVMPY_AddBasicAAWrapperPass(LLVMPassManagerRef PM) { - unwrap(PM)->add(llvm::createBasicAAWrapperPass()); -} - -API_EXPORT(void) -LLVMPY_AddDependenceAnalysisPass(LLVMPassManagerRef PM) { - unwrap(PM)->add(llvm::createDependenceAnalysisWrapperPass()); -} - -API_EXPORT(void) -LLVMPY_AddCallGraphDOTPrinterPass(LLVMPassManagerRef PM) { - unwrap(PM)->add(llvm::createCallGraphDOTPrinterPass()); -} - -API_EXPORT(void) -LLVMPY_AddDotDomPrinterPass(LLVMPassManagerRef PM, bool showBody) { -#if LLVM_VERSION_MAJOR > 14 - unwrap(PM)->add(showBody ? llvm::createDomPrinterWrapperPassPass() - : llvm::createDomOnlyPrinterWrapperPassPass()); -#else - unwrap(PM)->add(showBody ? llvm::createDomPrinterPass() - : llvm::createDomOnlyPrinterPass()); -#endif -} - -API_EXPORT(void) -LLVMPY_AddGlobalsModRefAAPass(LLVMPassManagerRef PM) { - unwrap(PM)->add(llvm::createGlobalsAAWrapperPass()); -} - -API_EXPORT(void) -LLVMPY_AddDotPostDomPrinterPass(LLVMPassManagerRef PM, bool showBody) { -#if LLVM_VERSION_MAJOR > 14 - unwrap(PM)->add(showBody ? llvm::createPostDomPrinterWrapperPassPass() - : llvm::createPostDomOnlyPrinterWrapperPassPass()); -#else - unwrap(PM)->add(showBody ? llvm::createPostDomPrinterPass() - : llvm::createPostDomOnlyPrinterPass()); -#endif -} - -API_EXPORT(void) -LLVMPY_AddCFGPrinterPass(LLVMPassManagerRef PM) { - unwrap(PM)->add(llvm::createCFGPrinterLegacyPassPass()); -} - -API_EXPORT(void) -LLVMPY_AddConstantMergePass(LLVMPassManagerRef PM) { - LLVMAddConstantMergePass(PM); -} - -API_EXPORT(void) -LLVMPY_AddDeadStoreEliminationPass(LLVMPassManagerRef PM) { - unwrap(PM)->add(llvm::createDeadStoreEliminationPass()); -} - -API_EXPORT(void) -LLVMPY_AddReversePostOrderFunctionAttrsPass(LLVMPassManagerRef PM) { - unwrap(PM)->add(llvm::createReversePostOrderFunctionAttrsPass()); -} - -API_EXPORT(void) -LLVMPY_AddDeadArgEliminationPass(LLVMPassManagerRef PM) { - LLVMAddDeadArgEliminationPass(PM); -} - -API_EXPORT(void) -LLVMPY_AddInstructionCountPass(LLVMPassManagerRef PM) { - unwrap(PM)->add(llvm::createInstCountPass()); -} - -API_EXPORT(void) -LLVMPY_AddIVUsersPass(LLVMPassManagerRef PM) { - unwrap(PM)->add(llvm::createIVUsersPass()); -} - -API_EXPORT(void) -LLVMPY_AddLazyValueInfoPass(LLVMPassManagerRef PM) { - unwrap(PM)->add(llvm::createLazyValueInfoPass()); -} -API_EXPORT(void) -LLVMPY_AddLintPass(LLVMPassManagerRef PM) { - unwrap(PM)->add(llvm::createLintLegacyPassPass()); -} -API_EXPORT(void) -LLVMPY_AddModuleDebugInfoPrinterPass(LLVMPassManagerRef PM) { - unwrap(PM)->add(llvm::createModuleDebugInfoPrinterPass()); -} - -API_EXPORT(void) -LLVMPY_AddRegionInfoPass(LLVMPassManagerRef PM) { - unwrap(PM)->add(llvm::createRegionInfoPass()); -} - -API_EXPORT(void) -LLVMPY_AddScalarEvolutionAAPass(LLVMPassManagerRef PM) { - unwrap(PM)->add(llvm::createSCEVAAWrapperPass()); -} - -API_EXPORT(void) -LLVMPY_AddAggressiveDCEPass(LLVMPassManagerRef PM) { - unwrap(PM)->add(llvm::createAggressiveDCEPass()); -} - -API_EXPORT(void) -LLVMPY_AddAlwaysInlinerPass(LLVMPassManagerRef PM, bool insertLifetime) { - unwrap(PM)->add(llvm::createAlwaysInlinerLegacyPass(insertLifetime)); -} - -#if LLVM_VERSION_MAJOR < 15 -API_EXPORT(void) -LLVMPY_AddArgPromotionPass(LLVMPassManagerRef PM, unsigned int maxElements) { - unwrap(PM)->add(llvm::createArgumentPromotionPass(maxElements)); -} -#endif - -API_EXPORT(void) -LLVMPY_AddBreakCriticalEdgesPass(LLVMPassManagerRef PM) { - unwrap(PM)->add(llvm::createBreakCriticalEdgesPass()); -} - -API_EXPORT(void) -LLVMPY_AddFunctionAttrsPass(LLVMPassManagerRef PM) { - LLVMAddFunctionAttrsPass(PM); -} - -API_EXPORT(void) -LLVMPY_AddFunctionInliningPass(LLVMPassManagerRef PM, int Threshold) { - unwrap(PM)->add(createFunctionInliningPass(Threshold)); -} - -API_EXPORT(void) -LLVMPY_AddGlobalOptimizerPass(LLVMPassManagerRef PM) { - LLVMAddGlobalOptimizerPass(PM); -} - -API_EXPORT(void) -LLVMPY_AddGlobalDCEPass(LLVMPassManagerRef PM) { LLVMAddGlobalDCEPass(PM); } - -API_EXPORT(void) -LLVMPY_AddIPSCCPPass(LLVMPassManagerRef PM) { LLVMAddIPSCCPPass(PM); } - -API_EXPORT(void) -LLVMPY_AddDeadCodeEliminationPass(LLVMPassManagerRef PM) { - unwrap(PM)->add(createDeadCodeEliminationPass()); -} - -API_EXPORT(void) -LLVMPY_AddAggressiveInstructionCombiningPass(LLVMPassManagerRef PM) { - unwrap(PM)->add(createAggressiveInstCombinerPass()); -} - -API_EXPORT(void) -LLVMPY_AddInternalizePass(LLVMPassManagerRef PM) { - unwrap(PM)->add(createInternalizePass()); -} - -API_EXPORT(void) -LLVMPY_AddJumpThreadingPass(LLVMPassManagerRef PM, int threshold) { - unwrap(PM)->add(createJumpThreadingPass(threshold)); -} - -API_EXPORT(void) -LLVMPY_AddLCSSAPass(LLVMPassManagerRef PM) { - unwrap(PM)->add(createLCSSAPass()); -} - -API_EXPORT(void) -LLVMPY_AddLoopDeletionPass(LLVMPassManagerRef PM) { - unwrap(PM)->add(createLoopDeletionPass()); -} - -API_EXPORT(void) -LLVMPY_AddLoopExtractorPass(LLVMPassManagerRef PM) { - unwrap(PM)->add(createLoopExtractorPass()); -} - -API_EXPORT(void) -LLVMPY_AddSingleLoopExtractorPass(LLVMPassManagerRef PM) { - unwrap(PM)->add(createSingleLoopExtractorPass()); -} - -API_EXPORT(void) -LLVMPY_AddLoopStrengthReducePass(LLVMPassManagerRef PM) { - unwrap(PM)->add(createLoopStrengthReducePass()); -} - -API_EXPORT(void) -LLVMPY_AddLoopSimplificationPass(LLVMPassManagerRef PM) { - unwrap(PM)->add(createLoopSimplifyPass()); -} - -API_EXPORT(void) -LLVMPY_AddLoopUnrollPass(LLVMPassManagerRef PM) { LLVMAddLoopUnrollPass(PM); } - -API_EXPORT(void) -LLVMPY_AddLoopUnrollAndJamPass(LLVMPassManagerRef PM) { - LLVMAddLoopUnrollAndJamPass(PM); -} - -API_EXPORT(void) -LLVMPY_AddLoopUnswitchPass(LLVMPassManagerRef PM, bool optimizeForSize, - bool hasBranchDivergence) { -#if LLVM_VERSION_MAJOR > 14 - unwrap(PM)->add(createSimpleLoopUnswitchLegacyPass(optimizeForSize)); -#else - unwrap(PM)->add( - createLoopUnswitchPass(optimizeForSize, hasBranchDivergence)); -#endif -} - -API_EXPORT(void) -LLVMPY_AddLowerAtomicPass(LLVMPassManagerRef PM) { - unwrap(PM)->add(createLowerAtomicPass()); -} - -API_EXPORT(void) -LLVMPY_AddLowerInvokePass(LLVMPassManagerRef PM) { - unwrap(PM)->add(createLowerInvokePass()); -} - -API_EXPORT(void) -LLVMPY_AddLowerSwitchPass(LLVMPassManagerRef PM) { - unwrap(PM)->add(createLowerSwitchPass()); -} - -API_EXPORT(void) -LLVMPY_AddMemCpyOptimizationPass(LLVMPassManagerRef PM) { - unwrap(PM)->add(createMemCpyOptPass()); -} - -API_EXPORT(void) -LLVMPY_AddMergeFunctionsPass(LLVMPassManagerRef PM) { - unwrap(PM)->add(createMergeFunctionsPass()); -} - -API_EXPORT(void) -LLVMPY_AddMergeReturnsPass(LLVMPassManagerRef PM) { - unwrap(PM)->add(createUnifyFunctionExitNodesPass()); -} - -API_EXPORT(void) -LLVMPY_AddPartialInliningPass(LLVMPassManagerRef PM) { - unwrap(PM)->add(createPartialInliningPass()); -} - -API_EXPORT(void) -LLVMPY_AddPruneExceptionHandlingPass(LLVMPassManagerRef PM) { - unwrap(PM)->add(createPruneEHPass()); -} - -API_EXPORT(void) -LLVMPY_AddReassociatePass(LLVMPassManagerRef PM) { - unwrap(PM)->add(createReassociatePass()); -} - -API_EXPORT(void) -LLVMPY_AddDemoteRegisterToMemoryPass(LLVMPassManagerRef PM) { - unwrap(PM)->add(createDemoteRegisterToMemoryPass()); -} - -API_EXPORT(void) -LLVMPY_AddSinkPass(LLVMPassManagerRef PM) { - unwrap(PM)->add(createSinkingPass()); -} - -API_EXPORT(void) -LLVMPY_AddStripSymbolsPass(LLVMPassManagerRef PM, bool onlyDebugInfo) { - unwrap(PM)->add(createStripSymbolsPass(onlyDebugInfo)); -} - -API_EXPORT(void) -LLVMPY_AddStripDeadDebugInfoPass(LLVMPassManagerRef PM) { - unwrap(PM)->add(createStripDeadDebugInfoPass()); -} - -API_EXPORT(void) -LLVMPY_AddStripDeadPrototypesPass(LLVMPassManagerRef PM) { - unwrap(PM)->add(createStripDeadPrototypesPass()); -} - -API_EXPORT(void) -LLVMPY_AddStripDebugDeclarePrototypesPass(LLVMPassManagerRef PM) { - unwrap(PM)->add(createStripDebugDeclarePass()); -} - -API_EXPORT(void) -LLVMPY_AddStripNondebugSymbolsPass(LLVMPassManagerRef PM) { - unwrap(PM)->add(createStripNonDebugSymbolsPass()); -} - -API_EXPORT(void) -LLVMPY_AddTailCallEliminationPass(LLVMPassManagerRef PM) { - unwrap(PM)->add(createTailCallEliminationPass()); -} - -API_EXPORT(void) -LLVMPY_AddCFGSimplificationPass(LLVMPassManagerRef PM) { - LLVMAddCFGSimplificationPass(PM); -} - -API_EXPORT(void) -LLVMPY_AddGVNPass(LLVMPassManagerRef PM) { LLVMAddGVNPass(PM); } - -API_EXPORT(void) -LLVMPY_AddInstructionCombiningPass(LLVMPassManagerRef PM) { - LLVMAddInstructionCombiningPass(PM); -} - -API_EXPORT(void) -LLVMPY_AddLICMPass(LLVMPassManagerRef PM) { LLVMAddLICMPass(PM); } - -API_EXPORT(void) -LLVMPY_AddSCCPPass(LLVMPassManagerRef PM) { LLVMAddSCCPPass(PM); } - -API_EXPORT(void) -LLVMPY_AddSROAPass(LLVMPassManagerRef PM) { unwrap(PM)->add(createSROAPass()); } - -API_EXPORT(void) -LLVMPY_AddTypeBasedAliasAnalysisPass(LLVMPassManagerRef PM) { - LLVMAddTypeBasedAliasAnalysisPass(PM); -} - -API_EXPORT(void) -LLVMPY_AddBasicAliasAnalysisPass(LLVMPassManagerRef PM) { - LLVMAddBasicAliasAnalysisPass(PM); -} - -API_EXPORT(void) -LLVMPY_LLVMAddLoopRotatePass(LLVMPassManagerRef PM) { - LLVMAddLoopRotatePass(PM); -} - -API_EXPORT(void) -LLVMPY_AddInstructionNamerPass(LLVMPassManagerRef PM) { - unwrap(PM)->add(createInstructionNamerPass()); -} - -API_EXPORT(LLVMPassManagerBuilderRef) -LLVMPY_PassManagerBuilderCreate() { return LLVMPassManagerBuilderCreate(); } - -API_EXPORT(void) -LLVMPY_PassManagerBuilderDispose(LLVMPassManagerBuilderRef PMB) { - LLVMPassManagerBuilderDispose(PMB); -} - -API_EXPORT(void) -LLVMPY_PassManagerBuilderPopulateLegacyModulePassManager( - LLVMPassManagerBuilderRef PMB, LLVMPassManagerRef PM) { - LLVMPassManagerBuilderPopulateModulePassManager(PMB, PM); -} - -API_EXPORT(unsigned) -LLVMPY_PassManagerBuilderGetOptLevel(LLVMPassManagerBuilderRef PMB) { - llvm::PassManagerBuilder *pmb = llvm::unwrap(PMB); - return pmb->OptLevel; -} - -API_EXPORT(void) -LLVMPY_PassManagerBuilderSetOptLevel(LLVMPassManagerBuilderRef PMB, - unsigned OptLevel) { - LLVMPassManagerBuilderSetOptLevel(PMB, OptLevel); -} - -API_EXPORT(unsigned) -LLVMPY_PassManagerBuilderGetSizeLevel(LLVMPassManagerBuilderRef PMB) { - llvm::PassManagerBuilder *pmb = llvm::unwrap(PMB); - return pmb->SizeLevel; -} - -API_EXPORT(void) -LLVMPY_PassManagerBuilderSetSizeLevel(LLVMPassManagerBuilderRef PMB, - unsigned SizeLevel) { - LLVMPassManagerBuilderSetSizeLevel(PMB, SizeLevel); -} - -API_EXPORT(int) -LLVMPY_PassManagerBuilderGetDisableUnrollLoops(LLVMPassManagerBuilderRef PMB) { - llvm::PassManagerBuilder *pmb = llvm::unwrap(PMB); - return pmb->DisableUnrollLoops; -} - -API_EXPORT(void) -LLVMPY_PassManagerBuilderSetDisableUnrollLoops(LLVMPassManagerBuilderRef PMB, - LLVMBool Value) { - LLVMPassManagerBuilderSetDisableUnrollLoops(PMB, Value); -} - -API_EXPORT(void) -LLVMPY_PassManagerBuilderUseInlinerWithThreshold(LLVMPassManagerBuilderRef PMB, - unsigned Threshold) { - LLVMPassManagerBuilderUseInlinerWithThreshold(PMB, Threshold); -} - -API_EXPORT(void) -LLVMPY_PassManagerBuilderPopulateLegacyFunctionPassManager( - LLVMPassManagerBuilderRef PMB, LLVMPassManagerRef PM) { - LLVMPassManagerBuilderPopulateFunctionPassManager(PMB, PM); -} - -API_EXPORT(void) -LLVMPY_PassManagerBuilderSetLoopVectorize(LLVMPassManagerBuilderRef PMB, - int Value) { - llvm::PassManagerBuilder *pmb = llvm::unwrap(PMB); - pmb->LoopVectorize = Value; -} - -API_EXPORT(int) -LLVMPY_PassManagerBuilderGetLoopVectorize(LLVMPassManagerBuilderRef PMB) { - llvm::PassManagerBuilder *pmb = llvm::unwrap(PMB); - return pmb->LoopVectorize; -} - -API_EXPORT(void) -LLVMPY_PassManagerBuilderSetSLPVectorize(LLVMPassManagerBuilderRef PMB, - int Value) { - llvm::PassManagerBuilder *pmb = llvm::unwrap(PMB); - pmb->SLPVectorize = Value; -} - -API_EXPORT(int) -LLVMPY_PassManagerBuilderGetSLPVectorize(LLVMPassManagerBuilderRef PMB) { - llvm::PassManagerBuilder *pmb = llvm::unwrap(PMB); - return pmb->SLPVectorize; -} - -} // end extern "C" diff --git a/ffi/newpassmanagers.cpp b/ffi/newpassmanagers.cpp new file mode 100644 index 000000000..ff6133118 --- /dev/null +++ b/ffi/newpassmanagers.cpp @@ -0,0 +1,317 @@ +#include "core.h" +#include "llvm-c/TargetMachine.h" +#include "llvm/Analysis/AliasAnalysisEvaluator.h" +#include "llvm/IR/PassManager.h" +#include "llvm/IR/Verifier.h" +#include "llvm/Passes/PassBuilder.h" +#include "llvm/Transforms/InstCombine/InstCombine.h" +#include "llvm/Transforms/Scalar/JumpThreading.h" +#include "llvm/Transforms/Scalar/LoopRotation.h" +#include "llvm/Transforms/Scalar/LoopUnrollPass.h" +#include "llvm/Transforms/Scalar/SimplifyCFG.h" + +using namespace llvm; + +/* + * Exposed API + */ + +namespace llvm { + +struct OpaqueModulePassManager; +typedef OpaqueModulePassManager *LLVMModulePassManagerRef; +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ModulePassManager, LLVMModulePassManagerRef) + +struct OpaqueFunctionPassManager; +typedef OpaqueFunctionPassManager *LLVMFunctionPassManagerRef; +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(FunctionPassManager, + LLVMFunctionPassManagerRef) + +struct OpaquePassBuilder; +typedef OpaquePassBuilder *LLVMPassBuilderRef; +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(PassBuilder, LLVMPassBuilderRef) + +struct OpaquePipelineTuningOptions; +typedef OpaquePipelineTuningOptions *LLVMPipelineTuningOptionsRef; +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(PipelineTuningOptions, + LLVMPipelineTuningOptionsRef) + +static TargetMachine *unwrap(LLVMTargetMachineRef P) { + return reinterpret_cast(P); +} + +} // namespace llvm + +extern "C" { + +// MPM + +API_EXPORT(LLVMModulePassManagerRef) +LLVMPY_CreateNewModulePassManager() { + return llvm::wrap(new PassManager()); +} + +API_EXPORT(void) +LLVMPY_NMPRun_module(LLVMModulePassManagerRef MPMRef, LLVMPassBuilderRef PBRef, + LLVMModuleRef mod) { + + ModulePassManager *MPM = llvm::unwrap(MPMRef); + PassBuilder *PB = llvm::unwrap(PBRef); + Module *M = llvm::unwrap(mod); + + LoopAnalysisManager LAM; + FunctionAnalysisManager FAM; + CGSCCAnalysisManager CGAM; + ModuleAnalysisManager MAM; + PB->registerLoopAnalyses(LAM); + PB->registerFunctionAnalyses(FAM); + PB->registerCGSCCAnalyses(CGAM); + PB->registerModuleAnalyses(MAM); + PB->crossRegisterProxies(LAM, FAM, CGAM, MAM); + MPM->run(*M, MAM); +} + +API_EXPORT(void) +LLVMPY_AddVeriferPass(LLVMModulePassManagerRef MPM) { + llvm::unwrap(MPM)->addPass(VerifierPass()); +} + +API_EXPORT(void) +LLVMPY_AddAAEvalPass_module(LLVMModulePassManagerRef MPM) { + llvm::unwrap(MPM)->addPass( + createModuleToFunctionPassAdaptor(AAEvaluator())); +} + +API_EXPORT(void) +LLVMPY_AddSimplifyCFGPass_module(LLVMModulePassManagerRef MPM) { + llvm::unwrap(MPM)->addPass( + createModuleToFunctionPassAdaptor(SimplifyCFGPass())); +} + +API_EXPORT(void) +LLVMPY_AddLoopUnrollPass_module(LLVMModulePassManagerRef MPM) { + llvm::unwrap(MPM)->addPass( + createModuleToFunctionPassAdaptor(LoopUnrollPass())); +} + +API_EXPORT(void) +LLVMPY_LLVMAddLoopRotatePass_module(LLVMModulePassManagerRef MPM) { + llvm::unwrap(MPM)->addPass(createModuleToFunctionPassAdaptor( + createFunctionToLoopPassAdaptor(LoopRotatePass()))); +} + +API_EXPORT(void) +LLVMPY_LLVMAddInstructionCombinePass_module(LLVMModulePassManagerRef MPM) { + llvm::unwrap(MPM)->addPass( + createModuleToFunctionPassAdaptor(InstCombinePass())); +} + +API_EXPORT(void) +LLVMPY_AddJumpThreadingPass_module(LLVMModulePassManagerRef MPM, int T) { + llvm::unwrap(MPM)->addPass( + createModuleToFunctionPassAdaptor(JumpThreadingPass(T))); +} + +API_EXPORT(void) +LLVMPY_DisposeNewModulePassManger(LLVMModulePassManagerRef MPM) { + delete llvm::unwrap(MPM); +} + +// FPM + +API_EXPORT(LLVMFunctionPassManagerRef) +LLVMPY_CreateNewFunctionPassManager() { + return llvm::wrap(new PassManager()); +} + +API_EXPORT(void) +LLVMPY_NMPRun_function(LLVMFunctionPassManagerRef FPMRef, + LLVMPassBuilderRef PBRef, LLVMValueRef FRef) { + + FunctionPassManager *FPM = llvm::unwrap(FPMRef); + PassBuilder *PB = llvm::unwrap(PBRef); + Function *F = reinterpret_cast(FRef); + + LoopAnalysisManager LAM; + FunctionAnalysisManager FAM; + CGSCCAnalysisManager CGAM; + ModuleAnalysisManager MAM; + PB->registerLoopAnalyses(LAM); + PB->registerFunctionAnalyses(FAM); + PB->registerCGSCCAnalyses(CGAM); + PB->registerModuleAnalyses(MAM); + PB->crossRegisterProxies(LAM, FAM, CGAM, MAM); + FPM->run(*F, FAM); +} + +API_EXPORT(void) +LLVMPY_AddAAEvalPass_function(LLVMFunctionPassManagerRef FPM) { + llvm::unwrap(FPM)->addPass(AAEvaluator()); +} + +API_EXPORT(void) +LLVMPY_AddSimplifyCFGPass_function(LLVMFunctionPassManagerRef FPM) { + llvm::unwrap(FPM)->addPass(SimplifyCFGPass()); +} + +API_EXPORT(void) +LLVMPY_AddLoopUnrollPass_function(LLVMFunctionPassManagerRef FPM) { + llvm::unwrap(FPM)->addPass(LoopUnrollPass()); +} + +API_EXPORT(void) +LLVMPY_LLVMAddLoopRotatePass_function(LLVMFunctionPassManagerRef FPM) { + llvm::unwrap(FPM)->addPass( + createFunctionToLoopPassAdaptor(LoopRotatePass())); +} + +API_EXPORT(void) +LLVMPY_LLVMAddInstructionCombinePass_function(LLVMFunctionPassManagerRef FPM) { + llvm::unwrap(FPM)->addPass(InstCombinePass()); +} + +API_EXPORT(void) +LLVMPY_AddJumpThreadingPass_function(LLVMFunctionPassManagerRef FPM, int T) { + llvm::unwrap(FPM)->addPass(JumpThreadingPass(T)); +} + +API_EXPORT(void) +LLVMPY_DisposeNewFunctionPassManger(LLVMFunctionPassManagerRef FPM) { + delete llvm::unwrap(FPM); +} + +// PTO + +API_EXPORT(LLVMPipelineTuningOptionsRef) +LLVMPY_CreatePipelineTuningOptions() { + return llvm::wrap(new PipelineTuningOptions()); +} + +API_EXPORT(bool) +LLVMPY_PTOGetLoopInterleaving(LLVMPipelineTuningOptionsRef PTO) { + return llvm::unwrap(PTO)->LoopInterleaving; +} + +API_EXPORT(void) +LLVMPY_PTOSetLoopInterleaving(LLVMPipelineTuningOptionsRef PTO, bool value) { + llvm::unwrap(PTO)->LoopInterleaving = value; +} + +API_EXPORT(bool) +LLVMPY_PTOGetLoopVectorization(LLVMPipelineTuningOptionsRef PTO) { + return llvm::unwrap(PTO)->LoopVectorization; +} + +API_EXPORT(void) +LLVMPY_PTOSetLoopVectorization(LLVMPipelineTuningOptionsRef PTO, bool value) { + llvm::unwrap(PTO)->LoopVectorization = value; +} + +API_EXPORT(bool) +LLVMPY_PTOGetSLPVectorization(LLVMPipelineTuningOptionsRef PTO) { + return llvm::unwrap(PTO)->SLPVectorization; +} + +API_EXPORT(void) +LLVMPY_PTOSetSLPVectorization(LLVMPipelineTuningOptionsRef PTO, bool value) { + llvm::unwrap(PTO)->SLPVectorization = value; +} + +API_EXPORT(bool) +LLVMPY_PTOGetLoopUnrolling(LLVMPipelineTuningOptionsRef PTO) { + return llvm::unwrap(PTO)->LoopUnrolling; +} + +API_EXPORT(void) +LLVMPY_PTOSetLoopUnrolling(LLVMPipelineTuningOptionsRef PTO, bool value) { + llvm::unwrap(PTO)->LoopUnrolling = value; +} + +// FIXME: Available from llvm16 +// API_EXPORT(int) +// LLVMPY_PTOGetInlinerThreshold(LLVMPipelineTuningOptionsRef PTO) { +// return llvm::unwrap(PTO)->InlinerThreshold; +// } + +// API_EXPORT(void) +// LLVMPY_PTOSetInlinerThreshold(LLVMPipelineTuningOptionsRef PTO, bool value) { +// llvm::unwrap(PTO)->InlinerThreshold = value; +// } + +API_EXPORT(void) +LLVMPY_DisposePipelineTuningOptions(LLVMPipelineTuningOptionsRef PTO) { + delete llvm::unwrap(PTO); +} + +// PB + +API_EXPORT(LLVMPassBuilderRef) +LLVMPY_CreatePassBuilder(LLVMTargetMachineRef TM, + LLVMPipelineTuningOptionsRef PTO) { + TargetMachine *target = llvm::unwrap(TM); + PipelineTuningOptions *pt = llvm::unwrap(PTO); + return llvm::wrap(new PassBuilder(target, *pt)); +} + +static OptimizationLevel mapLevel(int speed_level, int size_level) { + switch (size_level) { + case 0: + switch (speed_level) { + case 0: + return OptimizationLevel::O0; + case 1: + return OptimizationLevel::O1; + case 2: + return OptimizationLevel::O2; + case 3: + return OptimizationLevel::O3; + default: + llvm_unreachable("Invalid optimization level"); + } + case 1: + if (speed_level == 1) + return OptimizationLevel::Os; + llvm_unreachable("Invalid optimization level for size level 1"); + case 2: + if (speed_level == 2) + return OptimizationLevel::Oz; + llvm_unreachable("Invalid optimization level for size level 2"); + default: + llvm_unreachable("Invalid size level"); + break; + } +} + +API_EXPORT(LLVMModulePassManagerRef) +LLVMPY_buildPerModuleDefaultPipeline(LLVMPassBuilderRef PBref, int speed_level, + int size_level) { + + PassBuilder *PB = llvm::unwrap(PBref); + OptimizationLevel OL = mapLevel(speed_level, size_level); + if (OL == OptimizationLevel::O0) { + return llvm::wrap( + new ModulePassManager(PB->buildO0DefaultPipeline(OL))); + } + + return llvm::wrap( + new ModulePassManager(PB->buildPerModuleDefaultPipeline(OL))); +} + +API_EXPORT(LLVMFunctionPassManagerRef) +LLVMPY_buildFunctionSimplificationPipeline(LLVMPassBuilderRef PBref, + int speed_level, int size_level) { + + PassBuilder *PB = llvm::unwrap(PBref); + OptimizationLevel OL = mapLevel(speed_level, size_level); + if (OL == OptimizationLevel::O0) + return llvm::wrap(new FunctionPassManager()); + + FunctionPassManager *FPM = new FunctionPassManager( + PB->buildFunctionSimplificationPipeline(OL, ThinOrFullLTOPhase::None)); + return llvm::wrap(FPM); +} + +API_EXPORT(void) +LLVMPY_DisposePassBuilder(LLVMPassBuilderRef PB) { delete llvm::unwrap(PB); } + +} // end extern "C" diff --git a/ffi/passmanagers.cpp b/ffi/passmanagers.cpp index 0ab27d2dd..da4a076b4 100644 --- a/ffi/passmanagers.cpp +++ b/ffi/passmanagers.cpp @@ -1,317 +1,487 @@ +#include + #include "core.h" -#include "llvm-c/TargetMachine.h" -#include "llvm/Analysis/AliasAnalysisEvaluator.h" -#include "llvm/IR/PassManager.h" -#include "llvm/IR/Verifier.h" -#include "llvm/Passes/PassBuilder.h" -#include "llvm/Transforms/InstCombine/InstCombine.h" -#include "llvm/Transforms/Scalar/JumpThreading.h" -#include "llvm/Transforms/Scalar/LoopRotation.h" -#include "llvm/Transforms/Scalar/LoopUnrollPass.h" -#include "llvm/Transforms/Scalar/SimplifyCFG.h" +#include "llvm-c/Transforms/IPO.h" +#include "llvm-c/Transforms/Scalar.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/IR/DiagnosticInfo.h" +#include "llvm/IR/DiagnosticPrinter.h" +#include "llvm/IR/LegacyPassManager.h" +#include "llvm/IR/Module.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/ToolOutputFile.h" +#include "llvm/Support/YAMLTraits.h" +#include "llvm/Support/raw_ostream.h" + +#include "llvm-c/Transforms/IPO.h" +#include "llvm-c/Transforms/Scalar.h" +#include "llvm/IR/LLVMRemarkStreamer.h" +#include "llvm/IR/LegacyPassManager.h" +#include "llvm/Remarks/RemarkStreamer.h" +#include "llvm/Transforms/IPO.h" +#include "llvm/Transforms/Scalar.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include using namespace llvm; /* * Exposed API */ -namespace llvm { +extern "C" { -struct OpaqueModulePassManager; -typedef OpaqueModulePassManager *LLVMModulePassManagerRef; -DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ModulePassManager, LLVMModulePassManagerRef) +API_EXPORT(void) +LLVMPY_SetTimePasses(bool enable) { TimePassesIsEnabled = enable; } -struct OpaqueFunctionPassManager; -typedef OpaqueFunctionPassManager *LLVMFunctionPassManagerRef; -DEFINE_SIMPLE_CONVERSION_FUNCTIONS(FunctionPassManager, - LLVMFunctionPassManagerRef) +API_EXPORT(void) +LLVMPY_ReportAndResetTimings(const char **outmsg) { + std::string osbuf; + raw_string_ostream os(osbuf); + reportAndResetTimings(&os); + os.flush(); + *outmsg = LLVMPY_CreateString(os.str().c_str()); +} -struct OpaquePassBuilder; -typedef OpaquePassBuilder *LLVMPassBuilderRef; -DEFINE_SIMPLE_CONVERSION_FUNCTIONS(PassBuilder, LLVMPassBuilderRef) +API_EXPORT(LLVMPassManagerRef) +LLVMPY_CreatePassManager() { return LLVMCreatePassManager(); } -struct OpaquePipelineTuningOptions; -typedef OpaquePipelineTuningOptions *LLVMPipelineTuningOptionsRef; -DEFINE_SIMPLE_CONVERSION_FUNCTIONS(PipelineTuningOptions, - LLVMPipelineTuningOptionsRef) +API_EXPORT(void) +LLVMPY_DisposePassManager(LLVMPassManagerRef PM) { + return LLVMDisposePassManager(PM); +} -static TargetMachine *unwrap(LLVMTargetMachineRef P) { - return reinterpret_cast(P); +API_EXPORT(LLVMPassManagerRef) +LLVMPY_CreateFunctionPassManager(LLVMModuleRef M) { + return LLVMCreateFunctionPassManagerForModule(M); } -} // namespace llvm +API_EXPORT(int) +LLVMPY_RunPassManagerWithRemarks(LLVMPassManagerRef PM, LLVMModuleRef M, + const char *remarks_format, + const char *remarks_filter, + const char *record_filename) { + auto setupResult = llvm::setupLLVMOptimizationRemarks( + unwrap(M)->getContext(), record_filename, remarks_filter, + remarks_format, true); + if (!setupResult) { + return -1; + } + auto optimisationFile = std::move(*setupResult); + auto r = LLVMRunPassManager(PM, M); -extern "C" { + unwrap(M)->getContext().setMainRemarkStreamer(nullptr); + unwrap(M)->getContext().setLLVMRemarkStreamer(nullptr); + + optimisationFile->keep(); + optimisationFile->os().flush(); + return r; +} + +API_EXPORT(int) +LLVMPY_RunPassManager(LLVMPassManagerRef PM, LLVMModuleRef M) { + return LLVMRunPassManager(PM, M); +} + +API_EXPORT(int) +LLVMPY_RunFunctionPassManagerWithRemarks(LLVMPassManagerRef PM, LLVMValueRef F, + const char *remarks_format, + const char *remarks_filter, + const char *record_filename) { + auto setupResult = llvm::setupLLVMOptimizationRemarks( + unwrap(F)->getContext(), record_filename, remarks_filter, + remarks_format, true); + if (!setupResult) { + return -1; + } + auto optimisationFile = std::move(*setupResult); -// MPM + auto r = LLVMRunFunctionPassManager(PM, F); -API_EXPORT(LLVMModulePassManagerRef) -LLVMPY_CreateModulePassManager() { - return llvm::wrap(new PassManager()); + unwrap(F)->getContext().setMainRemarkStreamer(nullptr); + unwrap(F)->getContext().setLLVMRemarkStreamer(nullptr); + + optimisationFile->keep(); + optimisationFile->os().flush(); + return r; +} + +API_EXPORT(int) +LLVMPY_RunFunctionPassManager(LLVMPassManagerRef PM, LLVMValueRef F) { + return LLVMRunFunctionPassManager(PM, F); +} + +API_EXPORT(int) +LLVMPY_InitializeFunctionPassManager(LLVMPassManagerRef FPM) { + return LLVMInitializeFunctionPassManager(FPM); +} + +API_EXPORT(int) +LLVMPY_FinalizeFunctionPassManager(LLVMPassManagerRef FPM) { + return LLVMFinalizeFunctionPassManager(FPM); } API_EXPORT(void) -LLVMPY_RunModulePassManager(LLVMModulePassManagerRef MPMRef, - LLVMPassBuilderRef PBRef, LLVMModuleRef mod) { +LLVMPY_AddAAEvalPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(llvm::createAAEvalPass()); +} - ModulePassManager *MPM = llvm::unwrap(MPMRef); - PassBuilder *PB = llvm::unwrap(PBRef); - Module *M = llvm::unwrap(mod); +API_EXPORT(void) +LLVMPY_AddBasicAAWrapperPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(llvm::createBasicAAWrapperPass()); +} - LoopAnalysisManager LAM; - FunctionAnalysisManager FAM; - CGSCCAnalysisManager CGAM; - ModuleAnalysisManager MAM; - PB->registerLoopAnalyses(LAM); - PB->registerFunctionAnalyses(FAM); - PB->registerCGSCCAnalyses(CGAM); - PB->registerModuleAnalyses(MAM); - PB->crossRegisterProxies(LAM, FAM, CGAM, MAM); - MPM->run(*M, MAM); +API_EXPORT(void) +LLVMPY_AddDependenceAnalysisPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(llvm::createDependenceAnalysisWrapperPass()); } API_EXPORT(void) -LLVMPY_AddVeriferPass(LLVMModulePassManagerRef MPM) { - llvm::unwrap(MPM)->addPass(VerifierPass()); +LLVMPY_AddCallGraphDOTPrinterPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(llvm::createCallGraphDOTPrinterPass()); } API_EXPORT(void) -LLVMPY_AddAAEvalPass_module(LLVMModulePassManagerRef MPM) { - llvm::unwrap(MPM)->addPass( - createModuleToFunctionPassAdaptor(AAEvaluator())); +LLVMPY_AddDotDomPrinterPass(LLVMPassManagerRef PM, bool showBody) { +#if LLVM_VERSION_MAJOR > 14 + unwrap(PM)->add(showBody ? llvm::createDomPrinterWrapperPassPass() + : llvm::createDomOnlyPrinterWrapperPassPass()); +#else + unwrap(PM)->add(showBody ? llvm::createDomPrinterPass() + : llvm::createDomOnlyPrinterPass()); +#endif } API_EXPORT(void) -LLVMPY_AddSimplifyCFGPass_module(LLVMModulePassManagerRef MPM) { - llvm::unwrap(MPM)->addPass( - createModuleToFunctionPassAdaptor(SimplifyCFGPass())); +LLVMPY_AddGlobalsModRefAAPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(llvm::createGlobalsAAWrapperPass()); } API_EXPORT(void) -LLVMPY_AddLoopUnrollPass_module(LLVMModulePassManagerRef MPM) { - llvm::unwrap(MPM)->addPass( - createModuleToFunctionPassAdaptor(LoopUnrollPass())); +LLVMPY_AddDotPostDomPrinterPass(LLVMPassManagerRef PM, bool showBody) { +#if LLVM_VERSION_MAJOR > 14 + unwrap(PM)->add(showBody ? llvm::createPostDomPrinterWrapperPassPass() + : llvm::createPostDomOnlyPrinterWrapperPassPass()); +#else + unwrap(PM)->add(showBody ? llvm::createPostDomPrinterPass() + : llvm::createPostDomOnlyPrinterPass()); +#endif } API_EXPORT(void) -LLVMPY_LLVMAddLoopRotatePass_module(LLVMModulePassManagerRef MPM) { - llvm::unwrap(MPM)->addPass(createModuleToFunctionPassAdaptor( - createFunctionToLoopPassAdaptor(LoopRotatePass()))); +LLVMPY_AddCFGPrinterPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(llvm::createCFGPrinterLegacyPassPass()); } API_EXPORT(void) -LLVMPY_LLVMAddInstructionCombinePass_module(LLVMModulePassManagerRef MPM) { - llvm::unwrap(MPM)->addPass( - createModuleToFunctionPassAdaptor(InstCombinePass())); +LLVMPY_AddConstantMergePass(LLVMPassManagerRef PM) { + LLVMAddConstantMergePass(PM); } API_EXPORT(void) -LLVMPY_AddJumpThreadingPass_module(LLVMModulePassManagerRef MPM, int T) { - llvm::unwrap(MPM)->addPass( - createModuleToFunctionPassAdaptor(JumpThreadingPass(T))); +LLVMPY_AddDeadStoreEliminationPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(llvm::createDeadStoreEliminationPass()); } API_EXPORT(void) -LLVMPY_DisposeNewModulePassManger(LLVMModulePassManagerRef MPM) { - delete llvm::unwrap(MPM); +LLVMPY_AddReversePostOrderFunctionAttrsPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(llvm::createReversePostOrderFunctionAttrsPass()); } -// FPM +API_EXPORT(void) +LLVMPY_AddDeadArgEliminationPass(LLVMPassManagerRef PM) { + LLVMAddDeadArgEliminationPass(PM); +} -API_EXPORT(LLVMFunctionPassManagerRef) -LLVMPY_CreateNewFunctionPassManager() { - return llvm::wrap(new PassManager()); +API_EXPORT(void) +LLVMPY_AddInstructionCountPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(llvm::createInstCountPass()); } API_EXPORT(void) -LLVMPY_RunFunctionPassManager(LLVMFunctionPassManagerRef FPMRef, - LLVMPassBuilderRef PBRef, LLVMValueRef FRef) { +LLVMPY_AddIVUsersPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(llvm::createIVUsersPass()); +} - FunctionPassManager *FPM = llvm::unwrap(FPMRef); - PassBuilder *PB = llvm::unwrap(PBRef); - Function *F = reinterpret_cast(FRef); +API_EXPORT(void) +LLVMPY_AddLazyValueInfoPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(llvm::createLazyValueInfoPass()); +} +API_EXPORT(void) +LLVMPY_AddLintPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(llvm::createLintLegacyPassPass()); +} +API_EXPORT(void) +LLVMPY_AddModuleDebugInfoPrinterPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(llvm::createModuleDebugInfoPrinterPass()); +} - LoopAnalysisManager LAM; - FunctionAnalysisManager FAM; - CGSCCAnalysisManager CGAM; - ModuleAnalysisManager MAM; - PB->registerLoopAnalyses(LAM); - PB->registerFunctionAnalyses(FAM); - PB->registerCGSCCAnalyses(CGAM); - PB->registerModuleAnalyses(MAM); - PB->crossRegisterProxies(LAM, FAM, CGAM, MAM); - FPM->run(*F, FAM); +API_EXPORT(void) +LLVMPY_AddRegionInfoPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(llvm::createRegionInfoPass()); } API_EXPORT(void) -LLVMPY_AddAAEvalPass_function(LLVMFunctionPassManagerRef FPM) { - llvm::unwrap(FPM)->addPass(AAEvaluator()); +LLVMPY_AddScalarEvolutionAAPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(llvm::createSCEVAAWrapperPass()); } API_EXPORT(void) -LLVMPY_AddSimplifyCFGPass_function(LLVMFunctionPassManagerRef FPM) { - llvm::unwrap(FPM)->addPass(SimplifyCFGPass()); +LLVMPY_AddAggressiveDCEPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(llvm::createAggressiveDCEPass()); } API_EXPORT(void) -LLVMPY_AddLoopUnrollPass_function(LLVMFunctionPassManagerRef FPM) { - llvm::unwrap(FPM)->addPass(LoopUnrollPass()); +LLVMPY_AddAlwaysInlinerPass(LLVMPassManagerRef PM, bool insertLifetime) { + unwrap(PM)->add(llvm::createAlwaysInlinerLegacyPass(insertLifetime)); } +#if LLVM_VERSION_MAJOR < 15 API_EXPORT(void) -LLVMPY_LLVMAddLoopRotatePass_function(LLVMFunctionPassManagerRef FPM) { - llvm::unwrap(FPM)->addPass( - createFunctionToLoopPassAdaptor(LoopRotatePass())); +LLVMPY_AddArgPromotionPass(LLVMPassManagerRef PM, unsigned int maxElements) { + unwrap(PM)->add(llvm::createArgumentPromotionPass(maxElements)); } +#endif API_EXPORT(void) -LLVMPY_LLVMAddInstructionCombinePass_function(LLVMFunctionPassManagerRef FPM) { - llvm::unwrap(FPM)->addPass(InstCombinePass()); +LLVMPY_AddBreakCriticalEdgesPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(llvm::createBreakCriticalEdgesPass()); } API_EXPORT(void) -LLVMPY_AddJumpThreadingPass_function(LLVMFunctionPassManagerRef FPM, int T) { - llvm::unwrap(FPM)->addPass(JumpThreadingPass(T)); +LLVMPY_AddFunctionAttrsPass(LLVMPassManagerRef PM) { + LLVMAddFunctionAttrsPass(PM); } API_EXPORT(void) -LLVMPY_DisposeNewFunctionPassManger(LLVMFunctionPassManagerRef FPM) { - delete llvm::unwrap(FPM); +LLVMPY_AddFunctionInliningPass(LLVMPassManagerRef PM, int Threshold) { + unwrap(PM)->add(createFunctionInliningPass(Threshold)); } -// PTO +API_EXPORT(void) +LLVMPY_AddGlobalOptimizerPass(LLVMPassManagerRef PM) { + LLVMAddGlobalOptimizerPass(PM); +} + +API_EXPORT(void) +LLVMPY_AddGlobalDCEPass(LLVMPassManagerRef PM) { LLVMAddGlobalDCEPass(PM); } -API_EXPORT(LLVMPipelineTuningOptionsRef) -LLVMPY_CreatePipelineTuningOptions() { - return llvm::wrap(new PipelineTuningOptions()); +API_EXPORT(void) +LLVMPY_AddIPSCCPPass(LLVMPassManagerRef PM) { LLVMAddIPSCCPPass(PM); } + +API_EXPORT(void) +LLVMPY_AddDeadCodeEliminationPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createDeadCodeEliminationPass()); } -API_EXPORT(bool) -LLVMPY_PTOGetLoopInterleaving(LLVMPipelineTuningOptionsRef PTO) { - return llvm::unwrap(PTO)->LoopInterleaving; +API_EXPORT(void) +LLVMPY_AddAggressiveInstructionCombiningPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createAggressiveInstCombinerPass()); } API_EXPORT(void) -LLVMPY_PTOSetLoopInterleaving(LLVMPipelineTuningOptionsRef PTO, bool value) { - llvm::unwrap(PTO)->LoopInterleaving = value; +LLVMPY_AddInternalizePass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createInternalizePass()); } -API_EXPORT(bool) -LLVMPY_PTOGetLoopVectorization(LLVMPipelineTuningOptionsRef PTO) { - return llvm::unwrap(PTO)->LoopVectorization; +API_EXPORT(void) +LLVMPY_AddJumpThreadingPass(LLVMPassManagerRef PM, int threshold) { + unwrap(PM)->add(createJumpThreadingPass(threshold)); } API_EXPORT(void) -LLVMPY_PTOSetLoopVectorization(LLVMPipelineTuningOptionsRef PTO, bool value) { - llvm::unwrap(PTO)->LoopVectorization = value; +LLVMPY_AddLCSSAPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createLCSSAPass()); } -API_EXPORT(bool) -LLVMPY_PTOGetSLPVectorization(LLVMPipelineTuningOptionsRef PTO) { - return llvm::unwrap(PTO)->SLPVectorization; +API_EXPORT(void) +LLVMPY_AddLoopDeletionPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createLoopDeletionPass()); } API_EXPORT(void) -LLVMPY_PTOSetSLPVectorization(LLVMPipelineTuningOptionsRef PTO, bool value) { - llvm::unwrap(PTO)->SLPVectorization = value; +LLVMPY_AddLoopExtractorPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createLoopExtractorPass()); } -API_EXPORT(bool) -LLVMPY_PTOGetLoopUnrolling(LLVMPipelineTuningOptionsRef PTO) { - return llvm::unwrap(PTO)->LoopUnrolling; +API_EXPORT(void) +LLVMPY_AddSingleLoopExtractorPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createSingleLoopExtractorPass()); } API_EXPORT(void) -LLVMPY_PTOSetLoopUnrolling(LLVMPipelineTuningOptionsRef PTO, bool value) { - llvm::unwrap(PTO)->LoopUnrolling = value; +LLVMPY_AddLoopStrengthReducePass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createLoopStrengthReducePass()); } -// FIXME: Available from llvm16 -// API_EXPORT(int) -// LLVMPY_PTOGetInlinerThreshold(LLVMPipelineTuningOptionsRef PTO) { -// return llvm::unwrap(PTO)->InlinerThreshold; -// } +API_EXPORT(void) +LLVMPY_AddLoopSimplificationPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createLoopSimplifyPass()); +} -// API_EXPORT(void) -// LLVMPY_PTOSetInlinerThreshold(LLVMPipelineTuningOptionsRef PTO, bool value) { -// llvm::unwrap(PTO)->InlinerThreshold = value; -// } +API_EXPORT(void) +LLVMPY_AddLoopUnrollPass(LLVMPassManagerRef PM) { LLVMAddLoopUnrollPass(PM); } API_EXPORT(void) -LLVMPY_DisposePipelineTuningOptions(LLVMPipelineTuningOptionsRef PTO) { - delete llvm::unwrap(PTO); +LLVMPY_AddLoopUnrollAndJamPass(LLVMPassManagerRef PM) { + LLVMAddLoopUnrollAndJamPass(PM); } -// PB +API_EXPORT(void) +LLVMPY_AddLoopUnswitchPass(LLVMPassManagerRef PM, bool optimizeForSize, + bool hasBranchDivergence) { +#if LLVM_VERSION_MAJOR > 14 + unwrap(PM)->add(createSimpleLoopUnswitchLegacyPass(optimizeForSize)); +#else + unwrap(PM)->add( + createLoopUnswitchPass(optimizeForSize, hasBranchDivergence)); +#endif +} -API_EXPORT(LLVMPassBuilderRef) -LLVMPY_CreatePassBuilder(LLVMTargetMachineRef TM, - LLVMPipelineTuningOptionsRef PTO) { - TargetMachine *target = llvm::unwrap(TM); - PipelineTuningOptions *pt = llvm::unwrap(PTO); - return llvm::wrap(new PassBuilder(target, *pt)); +API_EXPORT(void) +LLVMPY_AddLowerAtomicPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createLowerAtomicPass()); } -static OptimizationLevel mapLevel(int speed_level, int size_level) { - switch (size_level) { - case 0: - switch (speed_level) { - case 0: - return OptimizationLevel::O0; - case 1: - return OptimizationLevel::O1; - case 2: - return OptimizationLevel::O2; - case 3: - return OptimizationLevel::O3; - default: - llvm_unreachable("Invalid optimization level"); - } - case 1: - if (speed_level == 1) - return OptimizationLevel::Os; - llvm_unreachable("Invalid optimization level for size level 1"); - case 2: - if (speed_level == 2) - return OptimizationLevel::Oz; - llvm_unreachable("Invalid optimization level for size level 2"); - default: - llvm_unreachable("Invalid size level"); - break; - } +API_EXPORT(void) +LLVMPY_AddLowerInvokePass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createLowerInvokePass()); } -API_EXPORT(LLVMModulePassManagerRef) -LLVMPY_buildPerModuleDefaultPipeline(LLVMPassBuilderRef PBref, int speed_level, - int size_level) { +API_EXPORT(void) +LLVMPY_AddLowerSwitchPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createLowerSwitchPass()); +} - PassBuilder *PB = llvm::unwrap(PBref); - OptimizationLevel OL = mapLevel(speed_level, size_level); - if (OL == OptimizationLevel::O0) { - return llvm::wrap( - new ModulePassManager(PB->buildO0DefaultPipeline(OL))); - } +API_EXPORT(void) +LLVMPY_AddMemCpyOptimizationPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createMemCpyOptPass()); +} + +API_EXPORT(void) +LLVMPY_AddMergeFunctionsPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createMergeFunctionsPass()); +} + +API_EXPORT(void) +LLVMPY_AddMergeReturnsPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createUnifyFunctionExitNodesPass()); +} + +API_EXPORT(void) +LLVMPY_AddPartialInliningPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createPartialInliningPass()); +} + +API_EXPORT(void) +LLVMPY_AddPruneExceptionHandlingPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createPruneEHPass()); +} + +API_EXPORT(void) +LLVMPY_AddReassociatePass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createReassociatePass()); +} - return llvm::wrap( - new ModulePassManager(PB->buildPerModuleDefaultPipeline(OL))); +API_EXPORT(void) +LLVMPY_AddDemoteRegisterToMemoryPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createDemoteRegisterToMemoryPass()); } -API_EXPORT(LLVMFunctionPassManagerRef) -LLVMPY_buildFunctionSimplificationPipeline(LLVMPassBuilderRef PBref, - int speed_level, int size_level) { +API_EXPORT(void) +LLVMPY_AddSinkPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createSinkingPass()); +} - PassBuilder *PB = llvm::unwrap(PBref); - OptimizationLevel OL = mapLevel(speed_level, size_level); - if (OL == OptimizationLevel::O0) - return llvm::wrap(new FunctionPassManager()); +API_EXPORT(void) +LLVMPY_AddStripSymbolsPass(LLVMPassManagerRef PM, bool onlyDebugInfo) { + unwrap(PM)->add(createStripSymbolsPass(onlyDebugInfo)); +} - FunctionPassManager *FPM = new FunctionPassManager( - PB->buildFunctionSimplificationPipeline(OL, ThinOrFullLTOPhase::None)); - return llvm::wrap(FPM); +API_EXPORT(void) +LLVMPY_AddStripDeadDebugInfoPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createStripDeadDebugInfoPass()); } API_EXPORT(void) -LLVMPY_DisposePassBuilder(LLVMPassBuilderRef PB) { delete llvm::unwrap(PB); } +LLVMPY_AddStripDeadPrototypesPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createStripDeadPrototypesPass()); +} + +API_EXPORT(void) +LLVMPY_AddStripDebugDeclarePrototypesPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createStripDebugDeclarePass()); +} + +API_EXPORT(void) +LLVMPY_AddStripNondebugSymbolsPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createStripNonDebugSymbolsPass()); +} + +API_EXPORT(void) +LLVMPY_AddTailCallEliminationPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createTailCallEliminationPass()); +} + +API_EXPORT(void) +LLVMPY_AddCFGSimplificationPass(LLVMPassManagerRef PM) { + LLVMAddCFGSimplificationPass(PM); +} + +API_EXPORT(void) +LLVMPY_AddGVNPass(LLVMPassManagerRef PM) { LLVMAddGVNPass(PM); } + +API_EXPORT(void) +LLVMPY_AddInstructionCombiningPass(LLVMPassManagerRef PM) { + LLVMAddInstructionCombiningPass(PM); +} + +API_EXPORT(void) +LLVMPY_AddLICMPass(LLVMPassManagerRef PM) { LLVMAddLICMPass(PM); } + +API_EXPORT(void) +LLVMPY_AddSCCPPass(LLVMPassManagerRef PM) { LLVMAddSCCPPass(PM); } + +API_EXPORT(void) +LLVMPY_AddSROAPass(LLVMPassManagerRef PM) { unwrap(PM)->add(createSROAPass()); } + +API_EXPORT(void) +LLVMPY_AddTypeBasedAliasAnalysisPass(LLVMPassManagerRef PM) { + LLVMAddTypeBasedAliasAnalysisPass(PM); +} + +API_EXPORT(void) +LLVMPY_AddBasicAliasAnalysisPass(LLVMPassManagerRef PM) { + LLVMAddBasicAliasAnalysisPass(PM); +} + +API_EXPORT(void) +LLVMPY_LLVMAddLoopRotatePass(LLVMPassManagerRef PM) { + LLVMAddLoopRotatePass(PM); +} + +API_EXPORT(void) +LLVMPY_AddInstructionNamerPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createInstructionNamerPass()); +} } // end extern "C" diff --git a/ffi/transforms.cpp b/ffi/transforms.cpp new file mode 100644 index 000000000..8d6d7f391 --- /dev/null +++ b/ffi/transforms.cpp @@ -0,0 +1,96 @@ +#include "core.h" +#include "llvm-c/Target.h" +#include "llvm-c/Transforms/PassManagerBuilder.h" +#include "llvm/Transforms/IPO/PassManagerBuilder.h" + +extern "C" { + +API_EXPORT(LLVMPassManagerBuilderRef) +LLVMPY_PassManagerBuilderCreate() { return LLVMPassManagerBuilderCreate(); } + +API_EXPORT(void) +LLVMPY_PassManagerBuilderDispose(LLVMPassManagerBuilderRef PMB) { + LLVMPassManagerBuilderDispose(PMB); +} + +API_EXPORT(void) +LLVMPY_PassManagerBuilderPopulateModulePassManager( + LLVMPassManagerBuilderRef PMB, LLVMPassManagerRef PM) { + LLVMPassManagerBuilderPopulateModulePassManager(PMB, PM); +} + +API_EXPORT(unsigned) +LLVMPY_PassManagerBuilderGetOptLevel(LLVMPassManagerBuilderRef PMB) { + llvm::PassManagerBuilder *pmb = llvm::unwrap(PMB); + return pmb->OptLevel; +} + +API_EXPORT(void) +LLVMPY_PassManagerBuilderSetOptLevel(LLVMPassManagerBuilderRef PMB, + unsigned OptLevel) { + LLVMPassManagerBuilderSetOptLevel(PMB, OptLevel); +} + +API_EXPORT(unsigned) +LLVMPY_PassManagerBuilderGetSizeLevel(LLVMPassManagerBuilderRef PMB) { + llvm::PassManagerBuilder *pmb = llvm::unwrap(PMB); + return pmb->SizeLevel; +} + +API_EXPORT(void) +LLVMPY_PassManagerBuilderSetSizeLevel(LLVMPassManagerBuilderRef PMB, + unsigned SizeLevel) { + LLVMPassManagerBuilderSetSizeLevel(PMB, SizeLevel); +} + +API_EXPORT(int) +LLVMPY_PassManagerBuilderGetDisableUnrollLoops(LLVMPassManagerBuilderRef PMB) { + llvm::PassManagerBuilder *pmb = llvm::unwrap(PMB); + return pmb->DisableUnrollLoops; +} + +API_EXPORT(void) +LLVMPY_PassManagerBuilderSetDisableUnrollLoops(LLVMPassManagerBuilderRef PMB, + LLVMBool Value) { + LLVMPassManagerBuilderSetDisableUnrollLoops(PMB, Value); +} + +API_EXPORT(void) +LLVMPY_PassManagerBuilderUseInlinerWithThreshold(LLVMPassManagerBuilderRef PMB, + unsigned Threshold) { + LLVMPassManagerBuilderUseInlinerWithThreshold(PMB, Threshold); +} + +API_EXPORT(void) +LLVMPY_PassManagerBuilderPopulateFunctionPassManager( + LLVMPassManagerBuilderRef PMB, LLVMPassManagerRef PM) { + LLVMPassManagerBuilderPopulateFunctionPassManager(PMB, PM); +} + +API_EXPORT(void) +LLVMPY_PassManagerBuilderSetLoopVectorize(LLVMPassManagerBuilderRef PMB, + int Value) { + llvm::PassManagerBuilder *pmb = llvm::unwrap(PMB); + pmb->LoopVectorize = Value; +} + +API_EXPORT(int) +LLVMPY_PassManagerBuilderGetLoopVectorize(LLVMPassManagerBuilderRef PMB) { + llvm::PassManagerBuilder *pmb = llvm::unwrap(PMB); + return pmb->LoopVectorize; +} + +API_EXPORT(void) +LLVMPY_PassManagerBuilderSetSLPVectorize(LLVMPassManagerBuilderRef PMB, + int Value) { + llvm::PassManagerBuilder *pmb = llvm::unwrap(PMB); + pmb->SLPVectorize = Value; +} + +API_EXPORT(int) +LLVMPY_PassManagerBuilderGetSLPVectorize(LLVMPassManagerBuilderRef PMB) { + llvm::PassManagerBuilder *pmb = llvm::unwrap(PMB); + return pmb->SLPVectorize; +} + +} // end extern "C" diff --git a/llvmlite/binding/__init__.py b/llvmlite/binding/__init__.py index 3fc1e48e0..76f498e6f 100644 --- a/llvmlite/binding/__init__.py +++ b/llvmlite/binding/__init__.py @@ -7,12 +7,13 @@ from .linker import * from .module import * from .options import * -from .legacypassmanagers import * +from .newpassmangers import * +from .passmanagers import * from .targets import * +from .transforms import * from .value import * from .typeref import * from .analysis import * from .object_file import * from .context import * from .orcjit import * -from .passmanagers import * diff --git a/llvmlite/binding/legacypassmanagers.py b/llvmlite/binding/legacypassmanagers.py deleted file mode 100644 index 244e080db..000000000 --- a/llvmlite/binding/legacypassmanagers.py +++ /dev/null @@ -1,1088 +0,0 @@ -from ctypes import (c_bool, c_char_p, c_int, c_size_t, c_uint, Structure, byref, - POINTER) -from collections import namedtuple -from enum import IntFlag -from llvmlite.binding import ffi -from llvmlite.binding.initfini import llvm_version_info -import os -from tempfile import mkstemp -from llvmlite.binding.common import _encode_string - -_prunestats = namedtuple('PruneStats', - ('basicblock diamond fanout fanout_raise')) - -llvm_version_major = llvm_version_info[0] - - -class PruneStats(_prunestats): - """ Holds statistics from reference count pruning. - """ - - def __add__(self, other): - if not isinstance(other, PruneStats): - msg = 'PruneStats can only be added to another PruneStats, got {}.' - raise TypeError(msg.format(type(other))) - return PruneStats(self.basicblock + other.basicblock, - self.diamond + other.diamond, - self.fanout + other.fanout, - self.fanout_raise + other.fanout_raise) - - def __sub__(self, other): - if not isinstance(other, PruneStats): - msg = ('PruneStats can only be subtracted from another PruneStats, ' - 'got {}.') - raise TypeError(msg.format(type(other))) - return PruneStats(self.basicblock - other.basicblock, - self.diamond - other.diamond, - self.fanout - other.fanout, - self.fanout_raise - other.fanout_raise) - - -class _c_PruneStats(Structure): - _fields_ = [ - ('basicblock', c_size_t), - ('diamond', c_size_t), - ('fanout', c_size_t), - ('fanout_raise', c_size_t)] - - -def dump_refprune_stats(printout=False): - """ Returns a namedtuple containing the current values for the refop pruning - statistics. If kwarg `printout` is True the stats are printed to stderr, - default is False. - """ - - stats = _c_PruneStats(0, 0, 0, 0) - do_print = c_bool(printout) - - ffi.lib.LLVMPY_DumpRefPruneStats(byref(stats), do_print) - return PruneStats(stats.basicblock, stats.diamond, stats.fanout, - stats.fanout_raise) - - -def set_time_passes(enable): - """Enable or disable the pass timers. - - Parameters - ---------- - enable : bool - Set to True to enable the pass timers. - Set to False to disable the pass timers. - """ - ffi.lib.LLVMPY_SetTimePasses(c_bool(enable)) - - -def report_and_reset_timings(): - """Returns the pass timings report and resets the LLVM internal timers. - - Pass timers are enabled by ``set_time_passes()``. If the timers are not - enabled, this function will return an empty string. - - Returns - ------- - res : str - LLVM generated timing report. - """ - with ffi.OutputString() as buf: - ffi.lib.LLVMPY_ReportAndResetTimings(buf) - return str(buf) - - -def create_module_pass_manager(): - return LegacyModulePassManager() - - -def create_function_pass_manager(module): - return LegacyFunctionPassManager(module) - - -class RefPruneSubpasses(IntFlag): - PER_BB = 0b0001 # noqa: E221 - DIAMOND = 0b0010 # noqa: E221 - FANOUT = 0b0100 # noqa: E221 - FANOUT_RAISE = 0b1000 - ALL = PER_BB | DIAMOND | FANOUT | FANOUT_RAISE - - -class LegacyPassManager(ffi.ObjectRef): - """LegacyPassManager - """ - - def _dispose(self): - self._capi.LLVMPY_DisposeLegacyPassManager(self) - - def add_aa_eval_pass(self): - """ - See https://llvm.org/docs/Passes.html#aa-eval-exhaustive-alias-analysis-precision-evaluator - - LLVM 14: `llvm::createAAEvalPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddAAEvalPass(self) - - def add_basic_aa_pass(self): - """ - See https://llvm.org/docs/Passes.html#basic-aa-basic-alias-analysis-stateless-aa-impl - - LLVM 14: `llvm::createBasicAAWrapperPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddBasicAAWrapperPass(self) - - def add_constant_merge_pass(self): - """ - See http://llvm.org/docs/Passes.html#constmerge-merge-duplicate-global-constants - - LLVM 14: `LLVMAddConstantMergePass` - """ # noqa E501 - ffi.lib.LLVMPY_AddConstantMergePass(self) - - def add_dead_arg_elimination_pass(self): - """ - See http://llvm.org/docs/Passes.html#deadargelim-dead-argument-elimination - - LLVM 14: `LLVMAddDeadArgEliminationPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddDeadArgEliminationPass(self) - - def add_dependence_analysis_pass(self): - """ - See https://llvm.org/docs/Passes.html#da-dependence-analysis - - LLVM 14: `llvm::createDependenceAnalysisWrapperPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddDependenceAnalysisPass(self) - - def add_dot_call_graph_pass(self): - """ - See https://llvm.org/docs/Passes.html#dot-callgraph-print-call-graph-to-dot-file - - LLVM 14: `llvm::createCallGraphDOTPrinterPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddCallGraphDOTPrinterPass(self) - - def add_dot_cfg_printer_pass(self): - """ - See https://llvm.org/docs/Passes.html#dot-cfg-print-cfg-of-function-to-dot-file - - LLVM 14: `llvm::createCFGPrinterLegacyPassPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddCFGPrinterPass(self) - - def add_dot_dom_printer_pass(self, show_body=False): - """ - See https://llvm.org/docs/Passes.html#dot-dom-print-dominance-tree-of-function-to-dot-file - - LLVM 14: `llvm::createDomPrinterPass` and `llvm::createDomOnlyPrinterPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddDotDomPrinterPass(self, show_body) - - def add_dot_postdom_printer_pass(self, show_body=False): - """ - See https://llvm.org/docs/Passes.html#dot-postdom-print-postdominance-tree-of-function-to-dot-file - - LLVM 14: `llvm::createPostDomPrinterPass` and `llvm::createPostDomOnlyPrinterPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddDotPostDomPrinterPass(self, show_body) - - def add_globals_mod_ref_aa_pass(self): - """ - See https://llvm.org/docs/Passes.html#globalsmodref-aa-simple-mod-ref-analysis-for-globals - - LLVM 14: `llvm::createGlobalsAAWrapperPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddGlobalsModRefAAPass(self) - - def add_iv_users_pass(self): - """ - See https://llvm.org/docs/Passes.html#iv-users-induction-variable-users - - LLVM 14: `llvm::createIVUsersPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddIVUsersPass(self) - - def add_lint_pass(self): - """ - See https://llvm.org/docs/Passes.html#lint-statically-lint-checks-llvm-ir - - LLVM 14: `llvm::createLintLegacyPassPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddLintPass(self) - - def add_lazy_value_info_pass(self): - """ - See https://llvm.org/docs/Passes.html#lazy-value-info-lazy-value-information-analysis - - LLVM 14: `llvm::createLazyValueInfoPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddLazyValueInfoPass(self) - - def add_module_debug_info_pass(self): - """ - See https://llvm.org/docs/Passes.html#module-debuginfo-decodes-module-level-debug-info - - LLVM 14: `llvm::createModuleDebugInfoPrinterPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddModuleDebugInfoPrinterPass(self) - - def add_region_info_pass(self): - """ - See https://llvm.org/docs/Passes.html#regions-detect-single-entry-single-exit-regions - - LLVM 14: `llvm::createRegionInfoPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddRegionInfoPass(self) - - def add_scalar_evolution_aa_pass(self): - """ - See https://llvm.org/docs/Passes.html#scev-aa-scalarevolution-based-alias-analysis - - LLVM 14: `llvm::createSCEVAAWrapperPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddScalarEvolutionAAPass(self) - - def add_aggressive_dead_code_elimination_pass(self): - """ - See https://llvm.org/docs/Passes.html#adce-aggressive-dead-code-elimination - - LLVM 14: `llvm::createAggressiveDCEPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddAggressiveDCEPass(self) - - def add_always_inliner_pass(self, insert_lifetime=True): - """ - See https://llvm.org/docs/Passes.html#always-inline-inliner-for-always-inline-functions - - LLVM 14: `llvm::createAlwaysInlinerLegacyPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddAlwaysInlinerPass(self, insert_lifetime) - - def add_arg_promotion_pass(self, max_elements=3): - """ - See https://llvm.org/docs/Passes.html#argpromotion-promote-by-reference-arguments-to-scalars - - LLVM 14: `llvm::createArgumentPromotionPass` - """ # noqa E501 - if llvm_version_major > 14: - raise RuntimeError('ArgumentPromotionPass unavailable in LLVM > 14') - ffi.lib.LLVMPY_AddArgPromotionPass(self, max_elements) - - def add_break_critical_edges_pass(self): - """ - See https://llvm.org/docs/Passes.html#break-crit-edges-break-critical-edges-in-cfg - - LLVM 14: `llvm::createBreakCriticalEdgesPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddBreakCriticalEdgesPass(self) - - def add_dead_store_elimination_pass(self): - """ - See https://llvm.org/docs/Passes.html#dse-dead-store-elimination - - LLVM 14: `llvm::createDeadStoreEliminationPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddDeadStoreEliminationPass(self) - - def add_reverse_post_order_function_attrs_pass(self): - """ - See https://llvm.org/docs/Passes.html#function-attrs-deduce-function-attributes - - LLVM 14: `llvm::createReversePostOrderFunctionAttrsPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddReversePostOrderFunctionAttrsPass(self) - - def add_function_attrs_pass(self): - """ - See http://llvm.org/docs/Passes.html#functionattrs-deduce-function-attributes - - LLVM 14: `LLVMAddFunctionAttrsPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddFunctionAttrsPass(self) - - def add_function_inlining_pass(self, threshold): - """ - See http://llvm.org/docs/Passes.html#inline-function-integration-inlining - - LLVM 14: `createFunctionInliningPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddFunctionInliningPass(self, threshold) - - def add_global_dce_pass(self): - """ - See http://llvm.org/docs/Passes.html#globaldce-dead-global-elimination - - LLVM 14: `LLVMAddGlobalDCEPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddGlobalDCEPass(self) - - def add_global_optimizer_pass(self): - """ - See http://llvm.org/docs/Passes.html#globalopt-global-variable-optimizer - - LLVM 14: `LLVMAddGlobalOptimizerPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddGlobalOptimizerPass(self) - - def add_ipsccp_pass(self): - """ - See http://llvm.org/docs/Passes.html#ipsccp-interprocedural-sparse-conditional-constant-propagation - - LLVM 14: `LLVMAddIPSCCPPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddIPSCCPPass(self) - - def add_dead_code_elimination_pass(self): - """ - See http://llvm.org/docs/Passes.html#dce-dead-code-elimination - LLVM 14: `llvm::createDeadCodeEliminationPass` - """ - ffi.lib.LLVMPY_AddDeadCodeEliminationPass(self) - - def add_aggressive_instruction_combining_pass(self): - """ - See https://llvm.org/docs/Passes.html#aggressive-instcombine-combine-expression-patterns - - LLVM 14: `llvm::createAggressiveInstCombinerPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddAggressiveInstructionCombiningPass(self) - - def add_internalize_pass(self): - """ - See https://llvm.org/docs/Passes.html#internalize-internalize-global-symbols - - LLVM 14: `llvm::createInternalizePass` - """ # noqa E501 - ffi.lib.LLVMPY_AddInternalizePass(self) - - def add_cfg_simplification_pass(self): - """ - See http://llvm.org/docs/Passes.html#simplifycfg-simplify-the-cfg - - LLVM 14: `LLVMAddCFGSimplificationPass` - """ - ffi.lib.LLVMPY_AddCFGSimplificationPass(self) - - def add_jump_threading_pass(self, threshold=-1): - """ - See https://llvm.org/docs/Passes.html#jump-threading-jump-threading - - LLVM 14: `llvm::createJumpThreadingPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddJumpThreadingPass(self, threshold) - - def add_lcssa_pass(self): - """ - See https://llvm.org/docs/Passes.html#lcssa-loop-closed-ssa-form-pass - - LLVM 14: `llvm::createLCSSAPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddLCSSAPass(self) - - def add_gvn_pass(self): - """ - See http://llvm.org/docs/Passes.html#gvn-global-value-numbering - - LLVM 14: `LLVMAddGVNPass` - """ - ffi.lib.LLVMPY_AddGVNPass(self) - - def add_instruction_combining_pass(self): - """ - See http://llvm.org/docs/Passes.html#passes-instcombine - - LLVM 14: `LLVMAddInstructionCombiningPass` - """ - ffi.lib.LLVMPY_AddInstructionCombiningPass(self) - - def add_licm_pass(self): - """ - See http://llvm.org/docs/Passes.html#licm-loop-invariant-code-motion - - LLVM 14: `LLVMAddLICMPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddLICMPass(self) - - def add_loop_deletion_pass(self): - """ - See https://llvm.org/docs/Passes.html#loop-deletion-delete-dead-loops - - LLVM 14: `llvm::createLoopDeletionPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddLoopDeletionPass(self) - - def add_loop_extractor_pass(self): - """ - See https://llvm.org/docs/Passes.html#loop-extract-extract-loops-into-new-functions - - LLVM 14: `llvm::createLoopExtractorPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddLoopExtractorPass(self) - - def add_single_loop_extractor_pass(self): - """ - See https://llvm.org/docs/Passes.html#loop-extract-single-extract-at-most-one-loop-into-a-new-function - - LLVM 14: `llvm::createSingleLoopExtractorPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddSingleLoopExtractorPass(self) - - def add_sccp_pass(self): - """ - See http://llvm.org/docs/Passes.html#sccp-sparse-conditional-constant-propagation - - LLVM 14: `LLVMAddSCCPPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddSCCPPass(self) - - def add_loop_strength_reduce_pass(self): - """ - See https://llvm.org/docs/Passes.html#loop-reduce-loop-strength-reduction - - LLVM 14: `llvm::createLoopStrengthReducePass` - """ # noqa E501 - ffi.lib.LLVMPY_AddLoopStrengthReducePass(self) - - def add_loop_simplification_pass(self): - """ - See https://llvm.org/docs/Passes.html#loop-simplify-canonicalize-natural-loops - - LLVM 14: `llvm::createLoopSimplifyPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddLoopSimplificationPass(self) - - def add_loop_unroll_pass(self): - """ - See https://llvm.org/docs/Passes.html#loop-unroll-unroll-loops - - LLVM 14: `LLVMAddLoopUnrollPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddLoopUnrollPass(self) - - def add_loop_unroll_and_jam_pass(self): - """ - See https://llvm.org/docs/Passes.html#loop-unroll-and-jam-unroll-and-jam-loops - - LLVM 14: `LLVMAddLoopUnrollAndJamPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddLoopUnrollAndJamPass(self) - - def add_loop_unswitch_pass(self, - optimize_for_size=False, - has_branch_divergence=False): - """ - See https://llvm.org/docs/Passes.html#loop-unswitch-unswitch-loops - - LLVM 14: `llvm::createLoopUnswitchPass` - LLVM 15: `llvm::createSimpleLoopUnswitchLegacyPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddLoopUnswitchPass(self, optimize_for_size, - has_branch_divergence) - - def add_lower_atomic_pass(self): - """ - See https://llvm.org/docs/Passes.html#loweratomic-lower-atomic-intrinsics-to-non-atomic-form - - LLVM 14: `llvm::createLowerAtomicPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddLowerAtomicPass(self) - - def add_lower_invoke_pass(self): - """ - See https://llvm.org/docs/Passes.html#lowerinvoke-lower-invokes-to-calls-for-unwindless-code-generators - - LLVM 14: `llvm::createLowerInvokePass` - """ # noqa E501 - ffi.lib.LLVMPY_AddLowerInvokePass(self) - - def add_lower_switch_pass(self): - """ - See https://llvm.org/docs/Passes.html#lowerswitch-lower-switchinsts-to-branches - - LLVM 14: `llvm::createLowerSwitchPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddLowerSwitchPass(self) - - def add_memcpy_optimization_pass(self): - """ - See https://llvm.org/docs/Passes.html#memcpyopt-memcpy-optimization - - LLVM 14: `llvm::createMemCpyOptPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddMemCpyOptimizationPass(self) - - def add_merge_functions_pass(self): - """ - See https://llvm.org/docs/Passes.html#mergefunc-merge-functions - - LLVM 14: `llvm::createMergeFunctionsPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddMergeFunctionsPass(self) - - def add_merge_returns_pass(self): - """ - See https://llvm.org/docs/Passes.html#mergereturn-unify-function-exit-nodes - - LLVM 14: `llvm::createUnifyFunctionExitNodesPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddMergeReturnsPass(self) - - def add_partial_inlining_pass(self): - """ - See https://llvm.org/docs/Passes.html#partial-inliner-partial-inliner - - LLVM 14: `llvm::createPartialInliningPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddPartialInliningPass(self) - - def add_prune_exception_handling_pass(self): - """ - See https://llvm.org/docs/Passes.html#prune-eh-remove-unused-exception-handling-info - - LLVM 14: `llvm::createPruneEHPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddPruneExceptionHandlingPass(self) - - def add_reassociate_expressions_pass(self): - """ - See https://llvm.org/docs/Passes.html#reassociate-reassociate-expressions - - LLVM 14: `llvm::createReassociatePass` - """ # noqa E501 - ffi.lib.LLVMPY_AddReassociatePass(self) - - def add_demote_register_to_memory_pass(self): - """ - See https://llvm.org/docs/Passes.html#rel-lookup-table-converter-relative-lookup-table-converter - - LLVM 14: `llvm::createDemoteRegisterToMemoryPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddDemoteRegisterToMemoryPass(self) - - def add_sroa_pass(self): - """ - See http://llvm.org/docs/Passes.html#scalarrepl-scalar-replacement-of-aggregates-dt - Note that this pass corresponds to the ``opt -sroa`` command-line option, - despite the link above. - - LLVM 14: `llvm::createSROAPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddSROAPass(self) - - def add_sink_pass(self): - """ - See https://llvm.org/docs/Passes.html#sink-code-sinking - - LLVM 14: `llvm::createSinkingPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddSinkPass(self) - - def add_strip_symbols_pass(self, only_debug=False): - """ - See https://llvm.org/docs/Passes.html#strip-strip-all-symbols-from-a-module - - LLVM 14: `llvm::createStripSymbolsPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddStripSymbolsPass(self, only_debug) - - def add_strip_dead_debug_info_pass(self): - """ - See https://llvm.org/docs/Passes.html#strip-dead-debug-info-strip-debug-info-for-unused-symbols - - LLVM 14: `llvm::createStripDeadDebugInfoPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddStripDeadDebugInfoPass(self) - - def add_strip_dead_prototypes_pass(self): - """ - See https://llvm.org/docs/Passes.html#strip-dead-prototypes-strip-unused-function-prototypes - - LLVM 14: `llvm::createStripDeadPrototypesPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddStripDeadPrototypesPass(self) - - def add_strip_debug_declare_pass(self): - """ - See https://llvm.org/docs/Passes.html#strip-debug-declare-strip-all-llvm-dbg-declare-intrinsics - - LLVM 14: `llvm::createStripDebugDeclarePass` - """ # noqa E501 - ffi.lib.LLVMPY_AddStripDebugDeclarePrototypesPass(self) - - def add_strip_nondebug_symbols_pass(self): - """ - See https://llvm.org/docs/Passes.html#strip-nondebug-strip-all-symbols-except-dbg-symbols-from-a-module - - LLVM 14: `llvm::createStripNonDebugSymbolsPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddStripNondebugSymbolsPass(self) - - def add_tail_call_elimination_pass(self): - """ - See https://llvm.org/docs/Passes.html#tailcallelim-tail-call-elimination - - LLVM 14: `llvm::createTailCallEliminationPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddTailCallEliminationPass(self) - - def add_type_based_alias_analysis_pass(self): - """ - LLVM 14: `LLVMAddTypeBasedAliasAnalysisPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddTypeBasedAliasAnalysisPass(self) - - def add_basic_alias_analysis_pass(self): - """ - See http://llvm.org/docs/AliasAnalysis.html#the-basicaa-pass - - LLVM 14: `LLVMAddBasicAliasAnalysisPass` - """ - ffi.lib.LLVMPY_AddBasicAliasAnalysisPass(self) - - def add_loop_rotate_pass(self): - """http://llvm.org/docs/Passes.html#loop-rotate-rotate-loops.""" - ffi.lib.LLVMPY_LLVMAddLoopRotatePass(self) - - def add_target_library_info(self, triple): - ffi.lib.LLVMPY_AddTargetLibraryInfoPass(self, _encode_string(triple)) - - def add_instruction_namer_pass(self): - """ - See https://llvm.org/docs/Passes.html#instnamer-assign-names-to-anonymous-instructions. - - LLVM 14: `llvm::createInstructionNamerPass` - """ # noqa E501 - ffi.lib.LLVMPY_AddInstructionNamerPass(self) - - # Non-standard LLVM passes - - def add_refprune_pass(self, subpasses_flags=RefPruneSubpasses.ALL, - subgraph_limit=1000): - """Add Numba specific Reference count pruning pass. - - Parameters - ---------- - subpasses_flags : RefPruneSubpasses - A bitmask to control the subpasses to be enabled. - subgraph_limit : int - Limit the fanout pruners to working on a subgraph no bigger than - this number of basic-blocks to avoid spending too much time in very - large graphs. Default is 1000. Subject to change in future - versions. - """ - iflags = RefPruneSubpasses(subpasses_flags) - ffi.lib.LLVMPY_AddRefPrunePass(self, iflags, subgraph_limit) - - -class LegacyModulePassManager(LegacyPassManager): - - def __init__(self, ptr=None): - if ptr is None: - ptr = ffi.lib.LLVMPY_CreateLegacyPassManager() - LegacyPassManager.__init__(self, ptr) - - def run(self, module, remarks_file=None, remarks_format='yaml', - remarks_filter=''): - """ - Run optimization passes on the given module. - - Parameters - ---------- - module : llvmlite.binding.ModuleRef - The module to be optimized inplace - remarks_file : str; optional - If not `None`, it is the file to store the optimization remarks. - remarks_format : str; optional - The format to write; YAML is default - remarks_filter : str; optional - The filter that should be applied to the remarks output. - """ - if remarks_file is None: - return ffi.lib.LLVMPY_RunLegacyPassManager(self, module) - else: - r = ffi.lib.LLVMPY_RunPassManagerWithLegacyRemarks( - self, module, _encode_string(remarks_format), - _encode_string(remarks_filter), - _encode_string(remarks_file)) - if r == -1: - raise IOError("Failed to initialize remarks file.") - return r > 0 - - def run_with_remarks(self, module, remarks_format='yaml', - remarks_filter=''): - """ - Run optimization passes on the given module and returns the result and - the remarks data. - - Parameters - ---------- - module : llvmlite.binding.ModuleRef - The module to be optimized - remarks_format : str - The remarks output; YAML is the default - remarks_filter : str; optional - The filter that should be applied to the remarks output. - """ - remarkdesc, remarkfile = mkstemp() - try: - with os.fdopen(remarkdesc, 'r'): - pass - r = self.run(module, remarkfile, remarks_format, remarks_filter) - if r == -1: - raise IOError("Failed to initialize remarks file.") - with open(remarkfile) as f: - return bool(r), f.read() - finally: - os.unlink(remarkfile) - - -class LegacyFunctionPassManager(LegacyPassManager): - - def __init__(self, module): - ptr = ffi.lib.LLVMPY_CreateLegacyFunctionPassManager(module) - self._module = module - module._owned = True - LegacyPassManager.__init__(self, ptr) - - def initialize(self): - """ - Initialize the LegacyFunctionPassManager. Returns True if it produced - any changes (?). - """ - return ffi.lib.LLVMPY_InitializeLegacyFunctionPassManager(self) - - def finalize(self): - """ - Finalize the LegacyFunctionPassManager. Returns True if it produced - any changes (?). - """ - return ffi.lib.LLVMPY_FinalizeLegacyFunctionPassManager(self) - - def run(self, function, remarks_file=None, remarks_format='yaml', - remarks_filter=''): - """ - Run optimization passes on the given function. - - Parameters - ---------- - function : llvmlite.binding.FunctionRef - The function to be optimized inplace - remarks_file : str; optional - If not `None`, it is the file to store the optimization remarks. - remarks_format : str; optional - The format of the remarks file; the default is YAML - remarks_filter : str; optional - The filter that should be applied to the remarks output. - """ - if remarks_file is None: - return ffi.lib.LLVMPY_RunLegacyFunctionPassManager(self, function) - else: - r = ffi.lib.LLVMPY_RunLegacyFunctionPassManagerWithRemarks( - self, function, _encode_string(remarks_format), - _encode_string(remarks_filter), - _encode_string(remarks_file)) - if r == -1: - raise IOError("Failed to initialize remarks file.") - return bool(r) - - def run_with_remarks(self, function, remarks_format='yaml', - remarks_filter=''): - """ - Run optimization passes on the given function and returns the result - and the remarks data. - - Parameters - ---------- - function : llvmlite.binding.FunctionRef - The function to be optimized inplace - remarks_format : str; optional - The format of the remarks file; the default is YAML - remarks_filter : str; optional - The filter that should be applied to the remarks output. - """ - # LLVM is going to need to close this file and then reopen it, so we - # can't use an unlinked temporary file. - remarkdesc, remarkfile = mkstemp() - try: - # We get an open handle, but we need LLVM to write first, so close - # it. - with os.fdopen(remarkdesc, 'r'): - pass - r = self.run(function, remarkfile, remarks_format, remarks_filter) - if r == -1: - raise IOError("Failed to initialize remarks file.") - with open(remarkfile) as f: - return bool(r), f.read() - finally: - os.unlink(remarkfile) - - -def create_pass_manager_builder(): - return PassManagerBuilder() - - -class PassManagerBuilder(ffi.ObjectRef): - __slots__ = () - - def __init__(self, ptr=None): - if ptr is None: - ptr = ffi.lib.LLVMPY_PassManagerBuilderCreate() - ffi.ObjectRef.__init__(self, ptr) - - @property - def opt_level(self): - """ - The general optimization level as an integer between 0 and 3. - """ - return ffi.lib.LLVMPY_PassManagerBuilderGetOptLevel(self) - - @opt_level.setter - def opt_level(self, level): - ffi.lib.LLVMPY_PassManagerBuilderSetOptLevel(self, level) - - @property - def size_level(self): - """ - Whether and how much to optimize for size. An integer between 0 and 2. - """ - return ffi.lib.LLVMPY_PassManagerBuilderGetSizeLevel(self) - - @size_level.setter - def size_level(self, size): - ffi.lib.LLVMPY_PassManagerBuilderSetSizeLevel(self, size) - - @property - def inlining_threshold(self): - """ - The integer threshold for inlining a function into another. The higher, - the more likely inlining a function is. This attribute is write-only. - """ - raise NotImplementedError("inlining_threshold is write-only") - - @inlining_threshold.setter - def inlining_threshold(self, threshold): - ffi.lib.LLVMPY_PassManagerBuilderUseInlinerWithThreshold( - self, threshold) - - @property - def disable_unroll_loops(self): - """ - If true, disable loop unrolling. - """ - return ffi.lib.LLVMPY_PassManagerBuilderGetDisableUnrollLoops(self) - - @disable_unroll_loops.setter - def disable_unroll_loops(self, disable=True): - ffi.lib.LLVMPY_PassManagerBuilderSetDisableUnrollLoops(self, disable) - - @property - def loop_vectorize(self): - """ - If true, allow vectorizing loops. - """ - return ffi.lib.LLVMPY_PassManagerBuilderGetLoopVectorize(self) - - @loop_vectorize.setter - def loop_vectorize(self, enable=True): - return ffi.lib.LLVMPY_PassManagerBuilderSetLoopVectorize(self, enable) - - @property - def slp_vectorize(self): - """ - If true, enable the "SLP vectorizer", which uses a different algorithm - from the loop vectorizer. Both may be enabled at the same time. - """ - return ffi.lib.LLVMPY_PassManagerBuilderGetSLPVectorize(self) - - @slp_vectorize.setter - def slp_vectorize(self, enable=True): - return ffi.lib.LLVMPY_PassManagerBuilderSetSLPVectorize(self, enable) - - def _populate_module_pm(self, pm): - ffi.lib.LLVMPY_PassManagerBuilderPopulateLegacyModulePassManager( - self, pm) - - def _populate_function_pm(self, pm): - ffi.lib.LLVMPY_PassManagerBuilderPopulateLegacyFunctionPassManager( - self, pm) - - def populate(self, pm): - if isinstance(pm, LegacyModulePassManager): - self._populate_module_pm(pm) - elif isinstance(pm, LegacyFunctionPassManager): - self._populate_function_pm(pm) - else: - raise TypeError(pm) - - def _dispose(self): - self._capi.LLVMPY_PassManagerBuilderDispose(self) - - -# ============================================================================ -# FFI - -ffi.lib.LLVMPY_CreateLegacyPassManager.restype = ffi.LLVMPassManagerRef - -ffi.lib.LLVMPY_CreateLegacyFunctionPassManager.argtypes = [ffi.LLVMModuleRef] -ffi.lib.LLVMPY_CreateLegacyFunctionPassManager.restype = ffi.LLVMPassManagerRef - -ffi.lib.LLVMPY_DisposeLegacyPassManager.argtypes = [ffi.LLVMPassManagerRef] - -ffi.lib.LLVMPY_RunLegacyPassManager.argtypes = [ffi.LLVMPassManagerRef, - ffi.LLVMModuleRef] -ffi.lib.LLVMPY_RunLegacyPassManager.restype = c_bool - -ffi.lib.LLVMPY_RunPassManagerWithLegacyRemarks.argtypes = [ - ffi.LLVMPassManagerRef, ffi.LLVMModuleRef, c_char_p, c_char_p, c_char_p] - -ffi.lib.LLVMPY_RunPassManagerWithLegacyRemarks.restype = c_int - -ffi.lib.LLVMPY_InitializeLegacyFunctionPassManager.argtypes = [ - ffi.LLVMPassManagerRef] - -ffi.lib.LLVMPY_InitializeLegacyFunctionPassManager.restype = c_bool - -ffi.lib.LLVMPY_FinalizeLegacyFunctionPassManager.argtypes = [ - ffi.LLVMPassManagerRef] - -ffi.lib.LLVMPY_FinalizeLegacyFunctionPassManager.restype = c_bool - -ffi.lib.LLVMPY_RunLegacyFunctionPassManager.argtypes = [ffi.LLVMPassManagerRef, - ffi.LLVMValueRef] - -ffi.lib.LLVMPY_RunLegacyFunctionPassManager.restype = c_bool - -ffi.lib.LLVMPY_RunLegacyFunctionPassManagerWithRemarks.argtypes = [ - ffi.LLVMPassManagerRef, ffi.LLVMValueRef, c_char_p, c_char_p, c_char_p -] -ffi.lib.LLVMPY_RunLegacyFunctionPassManagerWithRemarks.restype = c_int - -ffi.lib.LLVMPY_AddAAEvalPass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddBasicAAWrapperPass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddConstantMergePass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddDeadArgEliminationPass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddDependenceAnalysisPass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddCallGraphDOTPrinterPass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddCFGPrinterPass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddDotDomPrinterPass.argtypes = [ffi.LLVMPassManagerRef, c_bool] -ffi.lib.LLVMPY_AddDotPostDomPrinterPass.argtypes = [ - ffi.LLVMPassManagerRef, - c_bool] -ffi.lib.LLVMPY_AddGlobalsModRefAAPass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddInstructionCountPass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddIVUsersPass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddLazyValueInfoPass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddLintPass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddModuleDebugInfoPrinterPass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddRegionInfoPass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddScalarEvolutionAAPass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddAggressiveDCEPass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddAlwaysInlinerPass.argtypes = [ffi.LLVMPassManagerRef, c_bool] - -if llvm_version_major < 15: - ffi.lib.LLVMPY_AddArgPromotionPass.argtypes = [ - ffi.LLVMPassManagerRef, c_uint] - -ffi.lib.LLVMPY_AddBreakCriticalEdgesPass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddDeadStoreEliminationPass.argtypes = [ - ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddReversePostOrderFunctionAttrsPass.argtypes = [ - ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddAggressiveInstructionCombiningPass.argtypes = [ - ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddInternalizePass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddLCSSAPass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddLoopDeletionPass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddLoopExtractorPass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddSingleLoopExtractorPass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddLoopStrengthReducePass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddLoopSimplificationPass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddLoopUnrollPass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddLoopUnrollAndJamPass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddLoopUnswitchPass.argtypes = [ffi.LLVMPassManagerRef, c_bool, - c_bool] -ffi.lib.LLVMPY_AddLowerAtomicPass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddLowerInvokePass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddLowerSwitchPass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddMemCpyOptimizationPass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddMergeFunctionsPass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddMergeReturnsPass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddPartialInliningPass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddPruneExceptionHandlingPass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddReassociatePass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddDemoteRegisterToMemoryPass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddSinkPass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddStripSymbolsPass.argtypes = [ffi.LLVMPassManagerRef, c_bool] -ffi.lib.LLVMPY_AddStripDeadDebugInfoPass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddStripDeadPrototypesPass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddStripDebugDeclarePrototypesPass.argtypes = [ - ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddStripNondebugSymbolsPass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddTailCallEliminationPass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddJumpThreadingPass.argtypes = [ffi.LLVMPassManagerRef, c_int] -ffi.lib.LLVMPY_AddFunctionAttrsPass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddFunctionInliningPass.argtypes = [ - ffi.LLVMPassManagerRef, c_int] -ffi.lib.LLVMPY_AddGlobalDCEPass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddGlobalOptimizerPass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddIPSCCPPass.argtypes = [ffi.LLVMPassManagerRef] - -ffi.lib.LLVMPY_AddDeadCodeEliminationPass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddCFGSimplificationPass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddGVNPass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddInstructionCombiningPass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddLICMPass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddSCCPPass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddSROAPass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddTypeBasedAliasAnalysisPass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddBasicAliasAnalysisPass.argtypes = [ffi.LLVMPassManagerRef] -ffi.lib.LLVMPY_AddTargetLibraryInfoPass.argtypes = [ffi.LLVMPassManagerRef, - c_char_p] -ffi.lib.LLVMPY_AddInstructionNamerPass.argtypes = [ffi.LLVMPassManagerRef] - -ffi.lib.LLVMPY_AddRefPrunePass.argtypes = [ffi.LLVMPassManagerRef, c_int, - c_size_t] - -ffi.lib.LLVMPY_DumpRefPruneStats.argtypes = [POINTER(_c_PruneStats), c_bool] - -ffi.lib.LLVMPY_PassManagerBuilderCreate.restype = ffi.LLVMPassManagerBuilderRef - -ffi.lib.LLVMPY_PassManagerBuilderDispose.argtypes = [ - ffi.LLVMPassManagerBuilderRef, -] - -ffi.lib.LLVMPY_PassManagerBuilderPopulateLegacyModulePassManager.argtypes = [ - ffi.LLVMPassManagerBuilderRef, - ffi.LLVMPassManagerRef, -] - -ffi.lib.LLVMPY_PassManagerBuilderPopulateLegacyFunctionPassManager.argtypes = [ - ffi.LLVMPassManagerBuilderRef, - ffi.LLVMPassManagerRef, -] - -# Unsigned int PassManagerBuilder properties - -for _func in (ffi.lib.LLVMPY_PassManagerBuilderSetOptLevel, - ffi.lib.LLVMPY_PassManagerBuilderSetSizeLevel, - ffi.lib.LLVMPY_PassManagerBuilderUseInlinerWithThreshold, - ): - _func.argtypes = [ffi.LLVMPassManagerBuilderRef, c_uint] - -for _func in (ffi.lib.LLVMPY_PassManagerBuilderGetOptLevel, - ffi.lib.LLVMPY_PassManagerBuilderGetSizeLevel, - ): - _func.argtypes = [ffi.LLVMPassManagerBuilderRef] - _func.restype = c_uint - -# Boolean PassManagerBuilder properties - -for _func in (ffi.lib.LLVMPY_PassManagerBuilderSetDisableUnrollLoops, - ffi.lib.LLVMPY_PassManagerBuilderSetLoopVectorize, - ffi.lib.LLVMPY_PassManagerBuilderSetSLPVectorize, - ): - _func.argtypes = [ffi.LLVMPassManagerBuilderRef, c_bool] - -for _func in (ffi.lib.LLVMPY_PassManagerBuilderGetDisableUnrollLoops, - ffi.lib.LLVMPY_PassManagerBuilderGetLoopVectorize, - ffi.lib.LLVMPY_PassManagerBuilderGetSLPVectorize, - ): - _func.argtypes = [ffi.LLVMPassManagerBuilderRef] - _func.restype = c_bool diff --git a/llvmlite/binding/newpassmangers.py b/llvmlite/binding/newpassmangers.py new file mode 100644 index 000000000..45e786e77 --- /dev/null +++ b/llvmlite/binding/newpassmangers.py @@ -0,0 +1,305 @@ +from ctypes import (c_bool, c_int) +from llvmlite.binding import ffi +from llvmlite.binding.initfini import llvm_version_info + +llvm_version_major = llvm_version_info[0] + + +def create_new_module_pass_manager(): + return NewModulePassManager() + + +def create_new_function_pass_manager(): + return NewFunctionPassManger() + + +def create_pass_builder(tm, pto): + return PassBuilder(tm, pto) + + +def create_pipeline_options(): + return PipelineTuningOptions() + + +class NewModulePassManager(ffi.ObjectRef): + + def __init__(self, ptr=None): + if ptr is None: + ptr = ffi.lib.LLVMPY_CreateNewModulePassManager() + ffi.ObjectRef.__init__(self, ptr) + + def run(self, module, pb): + ffi.lib.LLVMPY_NMPRun_module(self, pb, module) + + def addVerifier(self): + ffi.lib.LLVMPY_AddVeriferPass(self) + + def add_aa_eval_pass(self): + ffi.lib.LLVMPY_AddAAEvalPass_module(self) + + def add_simplify_cfg_pass(self): + ffi.lib.LLVMPY_AddSimplifyCFGPass_module(self) + + def add_loop_unroll_pass(self): + ffi.lib.LLVMPY_AddLoopUnrollPass_module(self) + + def add_loop_rotate_pass(self): + ffi.lib.LLVMPY_LLVMAddLoopRotatePass_module(self) + + def add_instruction_combine_pass(self): + ffi.lib.LLVMPY_LLVMAddInstructionCombinePass_module(self) + + def add_jump_threading_pass(self, threshold=-1): + ffi.lib.LLVMPY_AddJumpThreadingPass_module(self, threshold) + + # What will happen to the pointer to objects created with run() method + def _dispose(self): + ffi.lib.LLVMPY_DisposeNewModulePassManger(self) + + +class NewFunctionPassManger(ffi.ObjectRef): + + def __init__(self, ptr=None): + if ptr is None: + ptr = ffi.lib.LLVMPY_CreateNewFunctionPassManager() + ffi.ObjectRef.__init__(self, ptr) + + def add_aa_eval_pass(self): + ffi.lib.LLVMPY_AddAAEvalPass_function(self) + + def add_simplify_cfg_pass(self): + ffi.lib.LLVMPY_AddSimplifyCFGPass_function(self) + + def run(self, fun, pb): + ffi.lib.LLVMPY_NMPRun_function(self, pb, fun) + + def add_loop_unroll_pass(self): + ffi.lib.LLVMPY_AddLoopUnrollPass_function(self) + + def add_loop_rotate_pass(self): + ffi.lib.LLVMPY_LLVMAddLoopRotatePass_function(self) + + def add_instruction_combine_pass(self): + ffi.lib.LLVMPY_LLVMAddInstructionCombinePass_function(self) + + def add_jump_threading_pass(self, threshold=-1): + ffi.lib.LLVMPY_AddJumpThreadingPass_function(self, threshold) + + def _dispose(self): + ffi.lib.LLVMPY_DisposeNewFunctionPassManger(self) + + +# Make this nested class of PassBuilder? +class PipelineTuningOptions(ffi.ObjectRef): + + def __init__(self, ptr=None): + if ptr is None: + ptr = ffi.lib.LLVMPY_CreatePipelineTuningOptions() + self._opt_level = 2 + self._size_level = 0 + ffi.ObjectRef.__init__(self, ptr) + + @property + def loop_interleaving(self): + return ffi.lib.LLVMPY_PTOGetLoopInterleaving(self) + + @loop_interleaving.setter + def loop_interleaving(self, value): + ffi.lib.LLVMPY_PTOSetLoopInterleaving(self, value) + + @property + def loop_vectorization(self): + return ffi.lib.LLVMPY_PTOGetLoopVectorization(self) + + @loop_vectorization.setter + def loop_vectorization(self, value): + ffi.lib.LLVMPY_PTOSetLoopVectorization(self, value) + + @property + def slp_vectorization(self): + return ffi.lib.LLVMPY_PTOGetSLPVectorization(self) + + @slp_vectorization.setter + def slp_vectorization(self, value): + ffi.lib.LLVMPY_PTOSetSLPVectorization(self, value) + + @property + def loop_unrolling(self): + return ffi.lib.LLVMPY_PTOGetLoopUnrolling(self) + + @loop_unrolling.setter + def loop_unrolling(self, value): + ffi.lib.LLVMPY_PTOSetLoopUnrolling(self, value) + + # // FIXME: Available from llvm16 + # @property + # def inlining_threshold(self): + # return ffi.lib.LLVMPY_PTOGetInlinerThreshold(self) + + # @inlining_threshold.setter + # def inlining_threshold(self, value): + # ffi.lib.LLVMPY_PTOSetInlinerThreshold(self, value) + + # Not part of PTO + @property + def opt_level(self): + """ + The general optimization level as an integer between 0 and 3. + """ + return self._opt_level + + @opt_level.setter + def opt_level(self, level): + self._opt_level = level + + @property + def size_level(self): + """ + Whether and how much to optimize for size. + An integer between 0 and 2. + """ + return self._size_level + + @size_level.setter + def size_level(self, size): + self._size_level = size + + def _dispose(self): + ffi.lib.LLVMPY_DisposePipelineTuningOptions(self) + + +class PassBuilder(ffi.ObjectRef): + + def __init__(self, tm, pto, ptr=None): + if ptr is None: + self._pto = pto + self._tm = tm + ptr = ffi.lib.LLVMPY_CreatePassBuilder(tm, pto) + ffi.ObjectRef.__init__(self, ptr) + + def getNewModulePassManager(self): + return NewModulePassManager( + ffi.lib.LLVMPY_buildPerModuleDefaultPipeline( + self, self._pto.opt_level, self._pto.size_level) + ) + + def getNewFunctionPassManager(self): + return NewFunctionPassManger( + ffi.lib.LLVMPY_buildFunctionSimplificationPipeline( + self, self._pto.opt_level, self._pto.size_level) + ) + + def _dispose(self): + # Should I explicitly delete pointer to pto and tm? + ffi.lib.LLVMPY_DisposePassBuilder(self) + + +# ============================================================================ +# FFI + + +ffi.lib.LLVMPY_CreateNewModulePassManager.restype = ffi.LLVMModulePassManagerRef + +ffi.lib.LLVMPY_NMPRun_module.argtypes = [ffi.LLVMModulePassManagerRef, + ffi.LLVMPassBuilderRef, + ffi.LLVMModuleRef,] + +ffi.lib.LLVMPY_AddVeriferPass.argtypes = [ffi.LLVMModulePassManagerRef,] +ffi.lib.LLVMPY_AddAAEvalPass_module.argtypes = [ffi.LLVMModulePassManagerRef,] +ffi.lib.LLVMPY_AddSimplifyCFGPass_module.argtypes = [ + ffi.LLVMModulePassManagerRef,] + +ffi.lib.LLVMPY_AddLoopUnrollPass_module.argtypes = [ + ffi.LLVMModulePassManagerRef,] + +ffi.lib.LLVMPY_LLVMAddLoopRotatePass_module.argtypes = [ + ffi.LLVMModulePassManagerRef,] + +ffi.lib.LLVMPY_LLVMAddInstructionCombinePass_module.argtypes = [ + ffi.LLVMModulePassManagerRef,] + +ffi.lib.LLVMPY_AddJumpThreadingPass_module.argtypes = [ + ffi.LLVMModulePassManagerRef,] + +ffi.lib.LLVMPY_DisposeNewModulePassManger.argtypes = [ + ffi.LLVMModulePassManagerRef,] + +ffi.lib.LLVMPY_CreateNewFunctionPassManager.restype = \ + ffi.LLVMFunctionPassManagerRef + +ffi.lib.LLVMPY_NMPRun_function.argtypes = [ffi.LLVMFunctionPassManagerRef, + ffi.LLVMPassBuilderRef, + ffi.LLVMValueRef,] + +ffi.lib.LLVMPY_AddAAEvalPass_function.argtypes = [ + ffi.LLVMFunctionPassManagerRef,] + +ffi.lib.LLVMPY_AddSimplifyCFGPass_function.argtypes = [ + ffi.LLVMFunctionPassManagerRef,] + +ffi.lib.LLVMPY_AddLoopUnrollPass_function.argtypes = [ + ffi.LLVMFunctionPassManagerRef,] + +ffi.lib.LLVMPY_LLVMAddLoopRotatePass_function.argtypes = [ + ffi.LLVMFunctionPassManagerRef,] + +ffi.lib.LLVMPY_LLVMAddInstructionCombinePass_function.argtypes = [ + ffi.LLVMFunctionPassManagerRef,] + +ffi.lib.LLVMPY_AddJumpThreadingPass_function.argtypes = [ + ffi.LLVMFunctionPassManagerRef, c_int,] + +ffi.lib.LLVMPY_DisposeNewFunctionPassManger.argtypes = [ + ffi.LLVMFunctionPassManagerRef,] + +ffi.lib.LLVMPY_CreatePassBuilder.restype = ffi.LLVMPassBuilderRef +ffi.lib.LLVMPY_CreatePassBuilder.argtypes = [ffi.LLVMTargetMachineRef, + ffi.LLVMPipelineTuningOptionsRef,] + +ffi.lib.LLVMPY_buildPerModuleDefaultPipeline.restype = \ + ffi.LLVMModulePassManagerRef + +ffi.lib.LLVMPY_buildPerModuleDefaultPipeline.argtypes = [ + ffi.LLVMPassBuilderRef, c_int,] + +ffi.lib.LLVMPY_buildFunctionSimplificationPipeline.restype = \ + ffi.LLVMFunctionPassManagerRef + +ffi.lib.LLVMPY_buildFunctionSimplificationPipeline.argtypes = [ + ffi.LLVMPassBuilderRef, c_int,] + +ffi.lib.LLVMPY_DisposePassBuilder.argtypes = [ffi.LLVMPassBuilderRef,] + +ffi.lib.LLVMPY_CreatePipelineTuningOptions.restype = \ + ffi.LLVMPipelineTuningOptionsRef + +ffi.lib.LLVMPY_PTOGetLoopInterleaving.restype = c_bool +ffi.lib.LLVMPY_PTOGetLoopInterleaving.argtypes = [ + ffi.LLVMPipelineTuningOptionsRef,] + +ffi.lib.LLVMPY_PTOSetLoopInterleaving.argtypes = [ + ffi.LLVMPipelineTuningOptionsRef, c_bool] + +ffi.lib.LLVMPY_PTOGetLoopVectorization.restype = c_bool +ffi.lib.LLVMPY_PTOGetLoopVectorization.argtypes = [ + ffi.LLVMPipelineTuningOptionsRef,] + +ffi.lib.LLVMPY_PTOSetLoopVectorization.argtypes = [ + ffi.LLVMPipelineTuningOptionsRef, c_bool] + +ffi.lib.LLVMPY_PTOGetSLPVectorization.restype = c_bool +ffi.lib.LLVMPY_PTOGetSLPVectorization.argtypes = [ + ffi.LLVMPipelineTuningOptionsRef,] + +ffi.lib.LLVMPY_PTOSetSLPVectorization.argtypes = [ + ffi.LLVMPipelineTuningOptionsRef, c_bool] + +ffi.lib.LLVMPY_PTOGetLoopUnrolling.restype = c_bool +ffi.lib.LLVMPY_PTOGetLoopUnrolling.argtypes = [ + ffi.LLVMPipelineTuningOptionsRef,] + +ffi.lib.LLVMPY_PTOSetLoopUnrolling.argtypes = [ + ffi.LLVMPipelineTuningOptionsRef, c_bool] + +ffi.lib.LLVMPY_DisposePipelineTuningOptions.argtypes = \ + [ffi.LLVMPipelineTuningOptionsRef,] diff --git a/llvmlite/binding/passmanagers.py b/llvmlite/binding/passmanagers.py index 8c1e83faa..af6152f63 100644 --- a/llvmlite/binding/passmanagers.py +++ b/llvmlite/binding/passmanagers.py @@ -1,305 +1,939 @@ -from ctypes import (c_bool, c_int) +from ctypes import (c_bool, c_char_p, c_int, c_size_t, c_uint, Structure, byref, + POINTER) +from collections import namedtuple +from enum import IntFlag from llvmlite.binding import ffi from llvmlite.binding.initfini import llvm_version_info +import os +from tempfile import mkstemp +from llvmlite.binding.common import _encode_string + +_prunestats = namedtuple('PruneStats', + ('basicblock diamond fanout fanout_raise')) llvm_version_major = llvm_version_info[0] -def create_new_module_pass_manager(): - return ModulePassManager() +class PruneStats(_prunestats): + """ Holds statistics from reference count pruning. + """ + def __add__(self, other): + if not isinstance(other, PruneStats): + msg = 'PruneStats can only be added to another PruneStats, got {}.' + raise TypeError(msg.format(type(other))) + return PruneStats(self.basicblock + other.basicblock, + self.diamond + other.diamond, + self.fanout + other.fanout, + self.fanout_raise + other.fanout_raise) -def create_new_function_pass_manager(): - return FunctionPassManager() + def __sub__(self, other): + if not isinstance(other, PruneStats): + msg = ('PruneStats can only be subtracted from another PruneStats, ' + 'got {}.') + raise TypeError(msg.format(type(other))) + return PruneStats(self.basicblock - other.basicblock, + self.diamond - other.diamond, + self.fanout - other.fanout, + self.fanout_raise - other.fanout_raise) -def create_pass_builder(tm, pto): - return PassBuilder(tm, pto) +class _c_PruneStats(Structure): + _fields_ = [ + ('basicblock', c_size_t), + ('diamond', c_size_t), + ('fanout', c_size_t), + ('fanout_raise', c_size_t)] -def create_pipeline_options(): - return PipelineTuningOptions() +def dump_refprune_stats(printout=False): + """ Returns a namedtuple containing the current values for the refop pruning + statistics. If kwarg `printout` is True the stats are printed to stderr, + default is False. + """ + stats = _c_PruneStats(0, 0, 0, 0) + do_print = c_bool(printout) -class ModulePassManager(ffi.ObjectRef): + ffi.lib.LLVMPY_DumpRefPruneStats(byref(stats), do_print) + return PruneStats(stats.basicblock, stats.diamond, stats.fanout, + stats.fanout_raise) - def __init__(self, ptr=None): - if ptr is None: - ptr = ffi.lib.LLVMPY_CreateModulePassManager() - ffi.ObjectRef.__init__(self, ptr) - def run(self, module, pb): - ffi.lib.LLVMPY_RunModulePassManager(self, pb, module) +def set_time_passes(enable): + """Enable or disable the pass timers. - def addVerifier(self): - ffi.lib.LLVMPY_AddVeriferPass(self) + Parameters + ---------- + enable : bool + Set to True to enable the pass timers. + Set to False to disable the pass timers. + """ + ffi.lib.LLVMPY_SetTimePasses(c_bool(enable)) - def add_aa_eval_pass(self): - ffi.lib.LLVMPY_AddAAEvalPass_module(self) - def add_simplify_cfg_pass(self): - ffi.lib.LLVMPY_AddSimplifyCFGPass_module(self) +def report_and_reset_timings(): + """Returns the pass timings report and resets the LLVM internal timers. - def add_loop_unroll_pass(self): - ffi.lib.LLVMPY_AddLoopUnrollPass_module(self) + Pass timers are enabled by ``set_time_passes()``. If the timers are not + enabled, this function will return an empty string. - def add_loop_rotate_pass(self): - ffi.lib.LLVMPY_LLVMAddLoopRotatePass_module(self) + Returns + ------- + res : str + LLVM generated timing report. + """ + with ffi.OutputString() as buf: + ffi.lib.LLVMPY_ReportAndResetTimings(buf) + return str(buf) - def add_instruction_combine_pass(self): - ffi.lib.LLVMPY_LLVMAddInstructionCombinePass_module(self) - def add_jump_threading_pass(self, threshold=-1): - ffi.lib.LLVMPY_AddJumpThreadingPass_module(self, threshold) +def create_module_pass_manager(): + return ModulePassManager() - # What will happen to the pointer to objects created with run() method - def _dispose(self): - ffi.lib.LLVMPY_DisposeNewModulePassManger(self) +def create_function_pass_manager(module): + return FunctionPassManager(module) -class FunctionPassManager(ffi.ObjectRef): - def __init__(self, ptr=None): - if ptr is None: - ptr = ffi.lib.LLVMPY_CreateNewFunctionPassManager() - ffi.ObjectRef.__init__(self, ptr) +class RefPruneSubpasses(IntFlag): + PER_BB = 0b0001 # noqa: E221 + DIAMOND = 0b0010 # noqa: E221 + FANOUT = 0b0100 # noqa: E221 + FANOUT_RAISE = 0b1000 + ALL = PER_BB | DIAMOND | FANOUT | FANOUT_RAISE + + +class PassManager(ffi.ObjectRef): + """PassManager + """ + + def _dispose(self): + self._capi.LLVMPY_DisposePassManager(self) def add_aa_eval_pass(self): - ffi.lib.LLVMPY_AddAAEvalPass_function(self) + """ + See https://llvm.org/docs/Passes.html#aa-eval-exhaustive-alias-analysis-precision-evaluator + + LLVM 14: `llvm::createAAEvalPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddAAEvalPass(self) - def add_simplify_cfg_pass(self): - ffi.lib.LLVMPY_AddSimplifyCFGPass_function(self) + def add_basic_aa_pass(self): + """ + See https://llvm.org/docs/Passes.html#basic-aa-basic-alias-analysis-stateless-aa-impl - def run(self, fun, pb): - ffi.lib.LLVMPY_RunFunctionPassManager(self, pb, fun) + LLVM 14: `llvm::createBasicAAWrapperPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddBasicAAWrapperPass(self) - def add_loop_unroll_pass(self): - ffi.lib.LLVMPY_AddLoopUnrollPass_function(self) + def add_constant_merge_pass(self): + """ + See http://llvm.org/docs/Passes.html#constmerge-merge-duplicate-global-constants - def add_loop_rotate_pass(self): - ffi.lib.LLVMPY_LLVMAddLoopRotatePass_function(self) + LLVM 14: `LLVMAddConstantMergePass` + """ # noqa E501 + ffi.lib.LLVMPY_AddConstantMergePass(self) + + def add_dead_arg_elimination_pass(self): + """ + See http://llvm.org/docs/Passes.html#deadargelim-dead-argument-elimination + + LLVM 14: `LLVMAddDeadArgEliminationPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddDeadArgEliminationPass(self) + + def add_dependence_analysis_pass(self): + """ + See https://llvm.org/docs/Passes.html#da-dependence-analysis + + LLVM 14: `llvm::createDependenceAnalysisWrapperPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddDependenceAnalysisPass(self) + + def add_dot_call_graph_pass(self): + """ + See https://llvm.org/docs/Passes.html#dot-callgraph-print-call-graph-to-dot-file + + LLVM 14: `llvm::createCallGraphDOTPrinterPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddCallGraphDOTPrinterPass(self) + + def add_dot_cfg_printer_pass(self): + """ + See https://llvm.org/docs/Passes.html#dot-cfg-print-cfg-of-function-to-dot-file + + LLVM 14: `llvm::createCFGPrinterLegacyPassPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddCFGPrinterPass(self) + + def add_dot_dom_printer_pass(self, show_body=False): + """ + See https://llvm.org/docs/Passes.html#dot-dom-print-dominance-tree-of-function-to-dot-file + + LLVM 14: `llvm::createDomPrinterPass` and `llvm::createDomOnlyPrinterPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddDotDomPrinterPass(self, show_body) + + def add_dot_postdom_printer_pass(self, show_body=False): + """ + See https://llvm.org/docs/Passes.html#dot-postdom-print-postdominance-tree-of-function-to-dot-file + + LLVM 14: `llvm::createPostDomPrinterPass` and `llvm::createPostDomOnlyPrinterPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddDotPostDomPrinterPass(self, show_body) + + def add_globals_mod_ref_aa_pass(self): + """ + See https://llvm.org/docs/Passes.html#globalsmodref-aa-simple-mod-ref-analysis-for-globals + + LLVM 14: `llvm::createGlobalsAAWrapperPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddGlobalsModRefAAPass(self) + + def add_iv_users_pass(self): + """ + See https://llvm.org/docs/Passes.html#iv-users-induction-variable-users + + LLVM 14: `llvm::createIVUsersPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddIVUsersPass(self) + + def add_lint_pass(self): + """ + See https://llvm.org/docs/Passes.html#lint-statically-lint-checks-llvm-ir + + LLVM 14: `llvm::createLintLegacyPassPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddLintPass(self) + + def add_lazy_value_info_pass(self): + """ + See https://llvm.org/docs/Passes.html#lazy-value-info-lazy-value-information-analysis + + LLVM 14: `llvm::createLazyValueInfoPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddLazyValueInfoPass(self) + + def add_module_debug_info_pass(self): + """ + See https://llvm.org/docs/Passes.html#module-debuginfo-decodes-module-level-debug-info + + LLVM 14: `llvm::createModuleDebugInfoPrinterPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddModuleDebugInfoPrinterPass(self) + + def add_region_info_pass(self): + """ + See https://llvm.org/docs/Passes.html#regions-detect-single-entry-single-exit-regions + + LLVM 14: `llvm::createRegionInfoPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddRegionInfoPass(self) + + def add_scalar_evolution_aa_pass(self): + """ + See https://llvm.org/docs/Passes.html#scev-aa-scalarevolution-based-alias-analysis + + LLVM 14: `llvm::createSCEVAAWrapperPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddScalarEvolutionAAPass(self) + + def add_aggressive_dead_code_elimination_pass(self): + """ + See https://llvm.org/docs/Passes.html#adce-aggressive-dead-code-elimination + + LLVM 14: `llvm::createAggressiveDCEPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddAggressiveDCEPass(self) + + def add_always_inliner_pass(self, insert_lifetime=True): + """ + See https://llvm.org/docs/Passes.html#always-inline-inliner-for-always-inline-functions + + LLVM 14: `llvm::createAlwaysInlinerLegacyPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddAlwaysInlinerPass(self, insert_lifetime) + + def add_arg_promotion_pass(self, max_elements=3): + """ + See https://llvm.org/docs/Passes.html#argpromotion-promote-by-reference-arguments-to-scalars + + LLVM 14: `llvm::createArgumentPromotionPass` + """ # noqa E501 + if llvm_version_major > 14: + raise RuntimeError('ArgumentPromotionPass unavailable in LLVM > 14') + ffi.lib.LLVMPY_AddArgPromotionPass(self, max_elements) + + def add_break_critical_edges_pass(self): + """ + See https://llvm.org/docs/Passes.html#break-crit-edges-break-critical-edges-in-cfg + + LLVM 14: `llvm::createBreakCriticalEdgesPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddBreakCriticalEdgesPass(self) + + def add_dead_store_elimination_pass(self): + """ + See https://llvm.org/docs/Passes.html#dse-dead-store-elimination + + LLVM 14: `llvm::createDeadStoreEliminationPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddDeadStoreEliminationPass(self) + + def add_reverse_post_order_function_attrs_pass(self): + """ + See https://llvm.org/docs/Passes.html#function-attrs-deduce-function-attributes + + LLVM 14: `llvm::createReversePostOrderFunctionAttrsPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddReversePostOrderFunctionAttrsPass(self) + + def add_function_attrs_pass(self): + """ + See http://llvm.org/docs/Passes.html#functionattrs-deduce-function-attributes + + LLVM 14: `LLVMAddFunctionAttrsPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddFunctionAttrsPass(self) + + def add_function_inlining_pass(self, threshold): + """ + See http://llvm.org/docs/Passes.html#inline-function-integration-inlining + + LLVM 14: `createFunctionInliningPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddFunctionInliningPass(self, threshold) + + def add_global_dce_pass(self): + """ + See http://llvm.org/docs/Passes.html#globaldce-dead-global-elimination + + LLVM 14: `LLVMAddGlobalDCEPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddGlobalDCEPass(self) + + def add_global_optimizer_pass(self): + """ + See http://llvm.org/docs/Passes.html#globalopt-global-variable-optimizer + + LLVM 14: `LLVMAddGlobalOptimizerPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddGlobalOptimizerPass(self) + + def add_ipsccp_pass(self): + """ + See http://llvm.org/docs/Passes.html#ipsccp-interprocedural-sparse-conditional-constant-propagation - def add_instruction_combine_pass(self): - ffi.lib.LLVMPY_LLVMAddInstructionCombinePass_function(self) + LLVM 14: `LLVMAddIPSCCPPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddIPSCCPPass(self) + + def add_dead_code_elimination_pass(self): + """ + See http://llvm.org/docs/Passes.html#dce-dead-code-elimination + LLVM 14: `llvm::createDeadCodeEliminationPass` + """ + ffi.lib.LLVMPY_AddDeadCodeEliminationPass(self) + + def add_aggressive_instruction_combining_pass(self): + """ + See https://llvm.org/docs/Passes.html#aggressive-instcombine-combine-expression-patterns + + LLVM 14: `llvm::createAggressiveInstCombinerPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddAggressiveInstructionCombiningPass(self) + + def add_internalize_pass(self): + """ + See https://llvm.org/docs/Passes.html#internalize-internalize-global-symbols + + LLVM 14: `llvm::createInternalizePass` + """ # noqa E501 + ffi.lib.LLVMPY_AddInternalizePass(self) + + def add_cfg_simplification_pass(self): + """ + See http://llvm.org/docs/Passes.html#simplifycfg-simplify-the-cfg + + LLVM 14: `LLVMAddCFGSimplificationPass` + """ + ffi.lib.LLVMPY_AddCFGSimplificationPass(self) def add_jump_threading_pass(self, threshold=-1): - ffi.lib.LLVMPY_AddJumpThreadingPass_function(self, threshold) + """ + See https://llvm.org/docs/Passes.html#jump-threading-jump-threading - def _dispose(self): - ffi.lib.LLVMPY_DisposeNewFunctionPassManger(self) + LLVM 14: `llvm::createJumpThreadingPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddJumpThreadingPass(self, threshold) + def add_lcssa_pass(self): + """ + See https://llvm.org/docs/Passes.html#lcssa-loop-closed-ssa-form-pass -# Make this nested class of PassBuilder? -class PipelineTuningOptions(ffi.ObjectRef): + LLVM 14: `llvm::createLCSSAPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddLCSSAPass(self) - def __init__(self, ptr=None): - if ptr is None: - ptr = ffi.lib.LLVMPY_CreatePipelineTuningOptions() - self._opt_level = 2 - self._size_level = 0 - ffi.ObjectRef.__init__(self, ptr) + def add_gvn_pass(self): + """ + See http://llvm.org/docs/Passes.html#gvn-global-value-numbering - @property - def loop_interleaving(self): - return ffi.lib.LLVMPY_PTOGetLoopInterleaving(self) + LLVM 14: `LLVMAddGVNPass` + """ + ffi.lib.LLVMPY_AddGVNPass(self) - @loop_interleaving.setter - def loop_interleaving(self, value): - ffi.lib.LLVMPY_PTOSetLoopInterleaving(self, value) + def add_instruction_combining_pass(self): + """ + See http://llvm.org/docs/Passes.html#passes-instcombine - @property - def loop_vectorization(self): - return ffi.lib.LLVMPY_PTOGetLoopVectorization(self) + LLVM 14: `LLVMAddInstructionCombiningPass` + """ + ffi.lib.LLVMPY_AddInstructionCombiningPass(self) - @loop_vectorization.setter - def loop_vectorization(self, value): - ffi.lib.LLVMPY_PTOSetLoopVectorization(self, value) + def add_licm_pass(self): + """ + See http://llvm.org/docs/Passes.html#licm-loop-invariant-code-motion - @property - def slp_vectorization(self): - return ffi.lib.LLVMPY_PTOGetSLPVectorization(self) + LLVM 14: `LLVMAddLICMPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddLICMPass(self) - @slp_vectorization.setter - def slp_vectorization(self, value): - ffi.lib.LLVMPY_PTOSetSLPVectorization(self, value) + def add_loop_deletion_pass(self): + """ + See https://llvm.org/docs/Passes.html#loop-deletion-delete-dead-loops - @property - def loop_unrolling(self): - return ffi.lib.LLVMPY_PTOGetLoopUnrolling(self) + LLVM 14: `llvm::createLoopDeletionPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddLoopDeletionPass(self) - @loop_unrolling.setter - def loop_unrolling(self, value): - ffi.lib.LLVMPY_PTOSetLoopUnrolling(self, value) + def add_loop_extractor_pass(self): + """ + See https://llvm.org/docs/Passes.html#loop-extract-extract-loops-into-new-functions + + LLVM 14: `llvm::createLoopExtractorPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddLoopExtractorPass(self) - # // FIXME: Available from llvm16 - # @property - # def inlining_threshold(self): - # return ffi.lib.LLVMPY_PTOGetInlinerThreshold(self) + def add_single_loop_extractor_pass(self): + """ + See https://llvm.org/docs/Passes.html#loop-extract-single-extract-at-most-one-loop-into-a-new-function - # @inlining_threshold.setter - # def inlining_threshold(self, value): - # ffi.lib.LLVMPY_PTOSetInlinerThreshold(self, value) + LLVM 14: `llvm::createSingleLoopExtractorPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddSingleLoopExtractorPass(self) - # Not part of PTO - @property - def opt_level(self): + def add_sccp_pass(self): """ - The general optimization level as an integer between 0 and 3. + See http://llvm.org/docs/Passes.html#sccp-sparse-conditional-constant-propagation + + LLVM 14: `LLVMAddSCCPPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddSCCPPass(self) + + def add_loop_strength_reduce_pass(self): """ - return self._opt_level + See https://llvm.org/docs/Passes.html#loop-reduce-loop-strength-reduction - @opt_level.setter - def opt_level(self, level): - self._opt_level = level + LLVM 14: `llvm::createLoopStrengthReducePass` + """ # noqa E501 + ffi.lib.LLVMPY_AddLoopStrengthReducePass(self) - @property - def size_level(self): + def add_loop_simplification_pass(self): """ - Whether and how much to optimize for size. - An integer between 0 and 2. + See https://llvm.org/docs/Passes.html#loop-simplify-canonicalize-natural-loops + + LLVM 14: `llvm::createLoopSimplifyPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddLoopSimplificationPass(self) + + def add_loop_unroll_pass(self): """ - return self._size_level + See https://llvm.org/docs/Passes.html#loop-unroll-unroll-loops - @size_level.setter - def size_level(self, size): - self._size_level = size + LLVM 14: `LLVMAddLoopUnrollPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddLoopUnrollPass(self) - def _dispose(self): - ffi.lib.LLVMPY_DisposePipelineTuningOptions(self) + def add_loop_unroll_and_jam_pass(self): + """ + See https://llvm.org/docs/Passes.html#loop-unroll-and-jam-unroll-and-jam-loops + LLVM 14: `LLVMAddLoopUnrollAndJamPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddLoopUnrollAndJamPass(self) -class PassBuilder(ffi.ObjectRef): + def add_loop_unswitch_pass(self, + optimize_for_size=False, + has_branch_divergence=False): + """ + See https://llvm.org/docs/Passes.html#loop-unswitch-unswitch-loops - def __init__(self, tm, pto, ptr=None): - if ptr is None: - self._pto = pto - self._tm = tm - ptr = ffi.lib.LLVMPY_CreatePassBuilder(tm, pto) - ffi.ObjectRef.__init__(self, ptr) - - def getModulePassManager(self): - return ModulePassManager( - ffi.lib.LLVMPY_buildPerModuleDefaultPipeline( - self, self._pto.opt_level, self._pto.size_level) - ) - - def getFunctionPassManager(self): - return FunctionPassManager( - ffi.lib.LLVMPY_buildFunctionSimplificationPipeline( - self, self._pto.opt_level, self._pto.size_level) - ) + LLVM 14: `llvm::createLoopUnswitchPass` + LLVM 15: `llvm::createSimpleLoopUnswitchLegacyPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddLoopUnswitchPass(self, optimize_for_size, + has_branch_divergence) - def _dispose(self): - # Should I explicitly delete pointer to pto and tm? - ffi.lib.LLVMPY_DisposePassBuilder(self) + def add_lower_atomic_pass(self): + """ + See https://llvm.org/docs/Passes.html#loweratomic-lower-atomic-intrinsics-to-non-atomic-form + LLVM 14: `llvm::createLowerAtomicPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddLowerAtomicPass(self) -# ============================================================================ -# FFI + def add_lower_invoke_pass(self): + """ + See https://llvm.org/docs/Passes.html#lowerinvoke-lower-invokes-to-calls-for-unwindless-code-generators + LLVM 14: `llvm::createLowerInvokePass` + """ # noqa E501 + ffi.lib.LLVMPY_AddLowerInvokePass(self) -ffi.lib.LLVMPY_CreateModulePassManager.restype = ffi.LLVMModulePassManagerRef + def add_lower_switch_pass(self): + """ + See https://llvm.org/docs/Passes.html#lowerswitch-lower-switchinsts-to-branches -ffi.lib.LLVMPY_RunModulePassManager.argtypes = [ - ffi.LLVMModulePassManagerRef, ffi.LLVMPassBuilderRef, ffi.LLVMModuleRef,] + LLVM 14: `llvm::createLowerSwitchPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddLowerSwitchPass(self) -ffi.lib.LLVMPY_AddVeriferPass.argtypes = [ffi.LLVMModulePassManagerRef,] -ffi.lib.LLVMPY_AddAAEvalPass_module.argtypes = [ffi.LLVMModulePassManagerRef,] -ffi.lib.LLVMPY_AddSimplifyCFGPass_module.argtypes = [ - ffi.LLVMModulePassManagerRef,] + def add_memcpy_optimization_pass(self): + """ + See https://llvm.org/docs/Passes.html#memcpyopt-memcpy-optimization -ffi.lib.LLVMPY_AddLoopUnrollPass_module.argtypes = [ - ffi.LLVMModulePassManagerRef,] + LLVM 14: `llvm::createMemCpyOptPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddMemCpyOptimizationPass(self) -ffi.lib.LLVMPY_LLVMAddLoopRotatePass_module.argtypes = [ - ffi.LLVMModulePassManagerRef,] + def add_merge_functions_pass(self): + """ + See https://llvm.org/docs/Passes.html#mergefunc-merge-functions -ffi.lib.LLVMPY_LLVMAddInstructionCombinePass_module.argtypes = [ - ffi.LLVMModulePassManagerRef,] + LLVM 14: `llvm::createMergeFunctionsPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddMergeFunctionsPass(self) -ffi.lib.LLVMPY_AddJumpThreadingPass_module.argtypes = [ - ffi.LLVMModulePassManagerRef,] + def add_merge_returns_pass(self): + """ + See https://llvm.org/docs/Passes.html#mergereturn-unify-function-exit-nodes -ffi.lib.LLVMPY_DisposeNewModulePassManger.argtypes = [ - ffi.LLVMModulePassManagerRef,] + LLVM 14: `llvm::createUnifyFunctionExitNodesPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddMergeReturnsPass(self) -ffi.lib.LLVMPY_CreateNewFunctionPassManager.restype = \ - ffi.LLVMFunctionPassManagerRef + def add_partial_inlining_pass(self): + """ + See https://llvm.org/docs/Passes.html#partial-inliner-partial-inliner -ffi.lib.LLVMPY_RunFunctionPassManager.argtypes = [ - ffi.LLVMFunctionPassManagerRef, - ffi.LLVMPassBuilderRef, - ffi.LLVMValueRef,] + LLVM 14: `llvm::createPartialInliningPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddPartialInliningPass(self) -ffi.lib.LLVMPY_AddAAEvalPass_function.argtypes = [ - ffi.LLVMFunctionPassManagerRef,] + def add_prune_exception_handling_pass(self): + """ + See https://llvm.org/docs/Passes.html#prune-eh-remove-unused-exception-handling-info -ffi.lib.LLVMPY_AddSimplifyCFGPass_function.argtypes = [ - ffi.LLVMFunctionPassManagerRef,] + LLVM 14: `llvm::createPruneEHPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddPruneExceptionHandlingPass(self) -ffi.lib.LLVMPY_AddLoopUnrollPass_function.argtypes = [ - ffi.LLVMFunctionPassManagerRef,] + def add_reassociate_expressions_pass(self): + """ + See https://llvm.org/docs/Passes.html#reassociate-reassociate-expressions + + LLVM 14: `llvm::createReassociatePass` + """ # noqa E501 + ffi.lib.LLVMPY_AddReassociatePass(self) + + def add_demote_register_to_memory_pass(self): + """ + See https://llvm.org/docs/Passes.html#rel-lookup-table-converter-relative-lookup-table-converter + + LLVM 14: `llvm::createDemoteRegisterToMemoryPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddDemoteRegisterToMemoryPass(self) + + def add_sroa_pass(self): + """ + See http://llvm.org/docs/Passes.html#scalarrepl-scalar-replacement-of-aggregates-dt + Note that this pass corresponds to the ``opt -sroa`` command-line option, + despite the link above. + + LLVM 14: `llvm::createSROAPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddSROAPass(self) + + def add_sink_pass(self): + """ + See https://llvm.org/docs/Passes.html#sink-code-sinking + + LLVM 14: `llvm::createSinkingPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddSinkPass(self) -ffi.lib.LLVMPY_LLVMAddLoopRotatePass_function.argtypes = [ - ffi.LLVMFunctionPassManagerRef,] + def add_strip_symbols_pass(self, only_debug=False): + """ + See https://llvm.org/docs/Passes.html#strip-strip-all-symbols-from-a-module -ffi.lib.LLVMPY_LLVMAddInstructionCombinePass_function.argtypes = [ - ffi.LLVMFunctionPassManagerRef,] + LLVM 14: `llvm::createStripSymbolsPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddStripSymbolsPass(self, only_debug) + + def add_strip_dead_debug_info_pass(self): + """ + See https://llvm.org/docs/Passes.html#strip-dead-debug-info-strip-debug-info-for-unused-symbols + + LLVM 14: `llvm::createStripDeadDebugInfoPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddStripDeadDebugInfoPass(self) + + def add_strip_dead_prototypes_pass(self): + """ + See https://llvm.org/docs/Passes.html#strip-dead-prototypes-strip-unused-function-prototypes + + LLVM 14: `llvm::createStripDeadPrototypesPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddStripDeadPrototypesPass(self) + + def add_strip_debug_declare_pass(self): + """ + See https://llvm.org/docs/Passes.html#strip-debug-declare-strip-all-llvm-dbg-declare-intrinsics + + LLVM 14: `llvm::createStripDebugDeclarePass` + """ # noqa E501 + ffi.lib.LLVMPY_AddStripDebugDeclarePrototypesPass(self) + + def add_strip_nondebug_symbols_pass(self): + """ + See https://llvm.org/docs/Passes.html#strip-nondebug-strip-all-symbols-except-dbg-symbols-from-a-module -ffi.lib.LLVMPY_AddJumpThreadingPass_function.argtypes = [ - ffi.LLVMFunctionPassManagerRef, c_int,] + LLVM 14: `llvm::createStripNonDebugSymbolsPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddStripNondebugSymbolsPass(self) -ffi.lib.LLVMPY_DisposeNewFunctionPassManger.argtypes = [ - ffi.LLVMFunctionPassManagerRef,] + def add_tail_call_elimination_pass(self): + """ + See https://llvm.org/docs/Passes.html#tailcallelim-tail-call-elimination -ffi.lib.LLVMPY_CreatePassBuilder.restype = ffi.LLVMPassBuilderRef -ffi.lib.LLVMPY_CreatePassBuilder.argtypes = [ffi.LLVMTargetMachineRef, - ffi.LLVMPipelineTuningOptionsRef,] + LLVM 14: `llvm::createTailCallEliminationPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddTailCallEliminationPass(self) -ffi.lib.LLVMPY_buildPerModuleDefaultPipeline.restype = \ - ffi.LLVMModulePassManagerRef + def add_type_based_alias_analysis_pass(self): + """ + LLVM 14: `LLVMAddTypeBasedAliasAnalysisPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddTypeBasedAliasAnalysisPass(self) -ffi.lib.LLVMPY_buildPerModuleDefaultPipeline.argtypes = [ - ffi.LLVMPassBuilderRef, c_int,] + def add_basic_alias_analysis_pass(self): + """ + See http://llvm.org/docs/AliasAnalysis.html#the-basicaa-pass -ffi.lib.LLVMPY_buildFunctionSimplificationPipeline.restype = \ - ffi.LLVMFunctionPassManagerRef + LLVM 14: `LLVMAddBasicAliasAnalysisPass` + """ + ffi.lib.LLVMPY_AddBasicAliasAnalysisPass(self) -ffi.lib.LLVMPY_buildFunctionSimplificationPipeline.argtypes = [ - ffi.LLVMPassBuilderRef, c_int,] + def add_loop_rotate_pass(self): + """http://llvm.org/docs/Passes.html#loop-rotate-rotate-loops.""" + ffi.lib.LLVMPY_LLVMAddLoopRotatePass(self) -ffi.lib.LLVMPY_DisposePassBuilder.argtypes = [ffi.LLVMPassBuilderRef,] + def add_target_library_info(self, triple): + ffi.lib.LLVMPY_AddTargetLibraryInfoPass(self, _encode_string(triple)) -ffi.lib.LLVMPY_CreatePipelineTuningOptions.restype = \ - ffi.LLVMPipelineTuningOptionsRef + def add_instruction_namer_pass(self): + """ + See https://llvm.org/docs/Passes.html#instnamer-assign-names-to-anonymous-instructions. + + LLVM 14: `llvm::createInstructionNamerPass` + """ # noqa E501 + ffi.lib.LLVMPY_AddInstructionNamerPass(self) + + # Non-standard LLVM passes + + def add_refprune_pass(self, subpasses_flags=RefPruneSubpasses.ALL, + subgraph_limit=1000): + """Add Numba specific Reference count pruning pass. + + Parameters + ---------- + subpasses_flags : RefPruneSubpasses + A bitmask to control the subpasses to be enabled. + subgraph_limit : int + Limit the fanout pruners to working on a subgraph no bigger than + this number of basic-blocks to avoid spending too much time in very + large graphs. Default is 1000. Subject to change in future + versions. + """ + iflags = RefPruneSubpasses(subpasses_flags) + ffi.lib.LLVMPY_AddRefPrunePass(self, iflags, subgraph_limit) -ffi.lib.LLVMPY_PTOGetLoopInterleaving.restype = c_bool -ffi.lib.LLVMPY_PTOGetLoopInterleaving.argtypes = [ - ffi.LLVMPipelineTuningOptionsRef,] -ffi.lib.LLVMPY_PTOSetLoopInterleaving.argtypes = [ - ffi.LLVMPipelineTuningOptionsRef, c_bool] +class ModulePassManager(PassManager): -ffi.lib.LLVMPY_PTOGetLoopVectorization.restype = c_bool -ffi.lib.LLVMPY_PTOGetLoopVectorization.argtypes = [ - ffi.LLVMPipelineTuningOptionsRef,] + def __init__(self, ptr=None): + if ptr is None: + ptr = ffi.lib.LLVMPY_CreatePassManager() + PassManager.__init__(self, ptr) -ffi.lib.LLVMPY_PTOSetLoopVectorization.argtypes = [ - ffi.LLVMPipelineTuningOptionsRef, c_bool] + def run(self, module, remarks_file=None, remarks_format='yaml', + remarks_filter=''): + """ + Run optimization passes on the given module. + + Parameters + ---------- + module : llvmlite.binding.ModuleRef + The module to be optimized inplace + remarks_file : str; optional + If not `None`, it is the file to store the optimization remarks. + remarks_format : str; optional + The format to write; YAML is default + remarks_filter : str; optional + The filter that should be applied to the remarks output. + """ + if remarks_file is None: + return ffi.lib.LLVMPY_RunPassManager(self, module) + else: + r = ffi.lib.LLVMPY_RunPassManagerWithRemarks( + self, module, _encode_string(remarks_format), + _encode_string(remarks_filter), + _encode_string(remarks_file)) + if r == -1: + raise IOError("Failed to initialize remarks file.") + return r > 0 + + def run_with_remarks(self, module, remarks_format='yaml', + remarks_filter=''): + """ + Run optimization passes on the given module and returns the result and + the remarks data. + + Parameters + ---------- + module : llvmlite.binding.ModuleRef + The module to be optimized + remarks_format : str + The remarks output; YAML is the default + remarks_filter : str; optional + The filter that should be applied to the remarks output. + """ + remarkdesc, remarkfile = mkstemp() + try: + with os.fdopen(remarkdesc, 'r'): + pass + r = self.run(module, remarkfile, remarks_format, remarks_filter) + if r == -1: + raise IOError("Failed to initialize remarks file.") + with open(remarkfile) as f: + return bool(r), f.read() + finally: + os.unlink(remarkfile) + + +class FunctionPassManager(PassManager): + + def __init__(self, module): + ptr = ffi.lib.LLVMPY_CreateFunctionPassManager(module) + self._module = module + module._owned = True + PassManager.__init__(self, ptr) + + def initialize(self): + """ + Initialize the FunctionPassManager. Returns True if it produced + any changes (?). + """ + return ffi.lib.LLVMPY_InitializeFunctionPassManager(self) -ffi.lib.LLVMPY_PTOGetSLPVectorization.restype = c_bool -ffi.lib.LLVMPY_PTOGetSLPVectorization.argtypes = [ - ffi.LLVMPipelineTuningOptionsRef,] + def finalize(self): + """ + Finalize the FunctionPassManager. Returns True if it produced + any changes (?). + """ + return ffi.lib.LLVMPY_FinalizeFunctionPassManager(self) -ffi.lib.LLVMPY_PTOSetSLPVectorization.argtypes = [ - ffi.LLVMPipelineTuningOptionsRef, c_bool] + def run(self, function, remarks_file=None, remarks_format='yaml', + remarks_filter=''): + """ + Run optimization passes on the given function. + + Parameters + ---------- + function : llvmlite.binding.FunctionRef + The function to be optimized inplace + remarks_file : str; optional + If not `None`, it is the file to store the optimization remarks. + remarks_format : str; optional + The format of the remarks file; the default is YAML + remarks_filter : str; optional + The filter that should be applied to the remarks output. + """ + if remarks_file is None: + return ffi.lib.LLVMPY_RunFunctionPassManager(self, function) + else: + r = ffi.lib.LLVMPY_RunFunctionPassManagerWithRemarks( + self, function, _encode_string(remarks_format), + _encode_string(remarks_filter), + _encode_string(remarks_file)) + if r == -1: + raise IOError("Failed to initialize remarks file.") + return bool(r) + + def run_with_remarks(self, function, remarks_format='yaml', + remarks_filter=''): + """ + Run optimization passes on the given function and returns the result + and the remarks data. + + Parameters + ---------- + function : llvmlite.binding.FunctionRef + The function to be optimized inplace + remarks_format : str; optional + The format of the remarks file; the default is YAML + remarks_filter : str; optional + The filter that should be applied to the remarks output. + """ + # LLVM is going to need to close this file and then reopen it, so we + # can't use an unlinked temporary file. + remarkdesc, remarkfile = mkstemp() + try: + # We get an open handle, but we need LLVM to write first, so close + # it. + with os.fdopen(remarkdesc, 'r'): + pass + r = self.run(function, remarkfile, remarks_format, remarks_filter) + if r == -1: + raise IOError("Failed to initialize remarks file.") + with open(remarkfile) as f: + return bool(r), f.read() + finally: + os.unlink(remarkfile) -ffi.lib.LLVMPY_PTOGetLoopUnrolling.restype = c_bool -ffi.lib.LLVMPY_PTOGetLoopUnrolling.argtypes = [ - ffi.LLVMPipelineTuningOptionsRef,] -ffi.lib.LLVMPY_PTOSetLoopUnrolling.argtypes = [ - ffi.LLVMPipelineTuningOptionsRef, c_bool] +# ============================================================================ +# FFI -ffi.lib.LLVMPY_DisposePipelineTuningOptions.argtypes = \ - [ffi.LLVMPipelineTuningOptionsRef,] +ffi.lib.LLVMPY_CreatePassManager.restype = ffi.LLVMPassManagerRef + +ffi.lib.LLVMPY_CreateFunctionPassManager.argtypes = [ffi.LLVMModuleRef] +ffi.lib.LLVMPY_CreateFunctionPassManager.restype = ffi.LLVMPassManagerRef + +ffi.lib.LLVMPY_DisposePassManager.argtypes = [ffi.LLVMPassManagerRef] + +ffi.lib.LLVMPY_RunPassManager.argtypes = [ffi.LLVMPassManagerRef, + ffi.LLVMModuleRef] +ffi.lib.LLVMPY_RunPassManager.restype = c_bool + +ffi.lib.LLVMPY_RunPassManagerWithRemarks.argtypes = [ffi.LLVMPassManagerRef, + ffi.LLVMModuleRef, + c_char_p, + c_char_p, + c_char_p] +ffi.lib.LLVMPY_RunPassManagerWithRemarks.restype = c_int + +ffi.lib.LLVMPY_InitializeFunctionPassManager.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_InitializeFunctionPassManager.restype = c_bool + +ffi.lib.LLVMPY_FinalizeFunctionPassManager.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_FinalizeFunctionPassManager.restype = c_bool + +ffi.lib.LLVMPY_RunFunctionPassManager.argtypes = [ffi.LLVMPassManagerRef, + ffi.LLVMValueRef] +ffi.lib.LLVMPY_RunFunctionPassManager.restype = c_bool + +ffi.lib.LLVMPY_RunFunctionPassManagerWithRemarks.argtypes = [ + ffi.LLVMPassManagerRef, ffi.LLVMValueRef, c_char_p, c_char_p, c_char_p +] +ffi.lib.LLVMPY_RunFunctionPassManagerWithRemarks.restype = c_int + +ffi.lib.LLVMPY_AddAAEvalPass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddBasicAAWrapperPass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddConstantMergePass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddDeadArgEliminationPass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddDependenceAnalysisPass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddCallGraphDOTPrinterPass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddCFGPrinterPass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddDotDomPrinterPass.argtypes = [ffi.LLVMPassManagerRef, c_bool] +ffi.lib.LLVMPY_AddDotPostDomPrinterPass.argtypes = [ + ffi.LLVMPassManagerRef, + c_bool] +ffi.lib.LLVMPY_AddGlobalsModRefAAPass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddInstructionCountPass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddIVUsersPass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddLazyValueInfoPass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddLintPass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddModuleDebugInfoPrinterPass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddRegionInfoPass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddScalarEvolutionAAPass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddAggressiveDCEPass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddAlwaysInlinerPass.argtypes = [ffi.LLVMPassManagerRef, c_bool] + +if llvm_version_major < 15: + ffi.lib.LLVMPY_AddArgPromotionPass.argtypes = [ + ffi.LLVMPassManagerRef, c_uint] + +ffi.lib.LLVMPY_AddBreakCriticalEdgesPass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddDeadStoreEliminationPass.argtypes = [ + ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddReversePostOrderFunctionAttrsPass.argtypes = [ + ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddAggressiveInstructionCombiningPass.argtypes = [ + ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddInternalizePass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddLCSSAPass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddLoopDeletionPass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddLoopExtractorPass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddSingleLoopExtractorPass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddLoopStrengthReducePass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddLoopSimplificationPass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddLoopUnrollPass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddLoopUnrollAndJamPass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddLoopUnswitchPass.argtypes = [ffi.LLVMPassManagerRef, c_bool, + c_bool] +ffi.lib.LLVMPY_AddLowerAtomicPass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddLowerInvokePass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddLowerSwitchPass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddMemCpyOptimizationPass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddMergeFunctionsPass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddMergeReturnsPass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddPartialInliningPass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddPruneExceptionHandlingPass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddReassociatePass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddDemoteRegisterToMemoryPass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddSinkPass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddStripSymbolsPass.argtypes = [ffi.LLVMPassManagerRef, c_bool] +ffi.lib.LLVMPY_AddStripDeadDebugInfoPass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddStripDeadPrototypesPass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddStripDebugDeclarePrototypesPass.argtypes = [ + ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddStripNondebugSymbolsPass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddTailCallEliminationPass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddJumpThreadingPass.argtypes = [ffi.LLVMPassManagerRef, c_int] +ffi.lib.LLVMPY_AddFunctionAttrsPass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddFunctionInliningPass.argtypes = [ + ffi.LLVMPassManagerRef, c_int] +ffi.lib.LLVMPY_AddGlobalDCEPass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddGlobalOptimizerPass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddIPSCCPPass.argtypes = [ffi.LLVMPassManagerRef] + +ffi.lib.LLVMPY_AddDeadCodeEliminationPass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddCFGSimplificationPass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddGVNPass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddInstructionCombiningPass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddLICMPass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddSCCPPass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddSROAPass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddTypeBasedAliasAnalysisPass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddBasicAliasAnalysisPass.argtypes = [ffi.LLVMPassManagerRef] +ffi.lib.LLVMPY_AddTargetLibraryInfoPass.argtypes = [ffi.LLVMPassManagerRef, + c_char_p] +ffi.lib.LLVMPY_AddInstructionNamerPass.argtypes = [ffi.LLVMPassManagerRef] + +ffi.lib.LLVMPY_AddRefPrunePass.argtypes = [ffi.LLVMPassManagerRef, c_int, + c_size_t] + +ffi.lib.LLVMPY_DumpRefPruneStats.argtypes = [POINTER(_c_PruneStats), c_bool] diff --git a/llvmlite/binding/transforms.py b/llvmlite/binding/transforms.py new file mode 100644 index 000000000..82c5dc157 --- /dev/null +++ b/llvmlite/binding/transforms.py @@ -0,0 +1,151 @@ +from ctypes import c_uint, c_bool +from llvmlite.binding import ffi +from llvmlite.binding import passmanagers + + +def create_pass_manager_builder(): + return PassManagerBuilder() + + +class PassManagerBuilder(ffi.ObjectRef): + __slots__ = () + + def __init__(self, ptr=None): + if ptr is None: + ptr = ffi.lib.LLVMPY_PassManagerBuilderCreate() + ffi.ObjectRef.__init__(self, ptr) + + @property + def opt_level(self): + """ + The general optimization level as an integer between 0 and 3. + """ + return ffi.lib.LLVMPY_PassManagerBuilderGetOptLevel(self) + + @opt_level.setter + def opt_level(self, level): + ffi.lib.LLVMPY_PassManagerBuilderSetOptLevel(self, level) + + @property + def size_level(self): + """ + Whether and how much to optimize for size. An integer between 0 and 2. + """ + return ffi.lib.LLVMPY_PassManagerBuilderGetSizeLevel(self) + + @size_level.setter + def size_level(self, size): + ffi.lib.LLVMPY_PassManagerBuilderSetSizeLevel(self, size) + + @property + def inlining_threshold(self): + """ + The integer threshold for inlining a function into another. The higher, + the more likely inlining a function is. This attribute is write-only. + """ + raise NotImplementedError("inlining_threshold is write-only") + + @inlining_threshold.setter + def inlining_threshold(self, threshold): + ffi.lib.LLVMPY_PassManagerBuilderUseInlinerWithThreshold( + self, threshold) + + @property + def disable_unroll_loops(self): + """ + If true, disable loop unrolling. + """ + return ffi.lib.LLVMPY_PassManagerBuilderGetDisableUnrollLoops(self) + + @disable_unroll_loops.setter + def disable_unroll_loops(self, disable=True): + ffi.lib.LLVMPY_PassManagerBuilderSetDisableUnrollLoops(self, disable) + + @property + def loop_vectorize(self): + """ + If true, allow vectorizing loops. + """ + return ffi.lib.LLVMPY_PassManagerBuilderGetLoopVectorize(self) + + @loop_vectorize.setter + def loop_vectorize(self, enable=True): + return ffi.lib.LLVMPY_PassManagerBuilderSetLoopVectorize(self, enable) + + @property + def slp_vectorize(self): + """ + If true, enable the "SLP vectorizer", which uses a different algorithm + from the loop vectorizer. Both may be enabled at the same time. + """ + return ffi.lib.LLVMPY_PassManagerBuilderGetSLPVectorize(self) + + @slp_vectorize.setter + def slp_vectorize(self, enable=True): + return ffi.lib.LLVMPY_PassManagerBuilderSetSLPVectorize(self, enable) + + def _populate_module_pm(self, pm): + ffi.lib.LLVMPY_PassManagerBuilderPopulateModulePassManager(self, pm) + + def _populate_function_pm(self, pm): + ffi.lib.LLVMPY_PassManagerBuilderPopulateFunctionPassManager(self, pm) + + def populate(self, pm): + if isinstance(pm, passmanagers.ModulePassManager): + self._populate_module_pm(pm) + elif isinstance(pm, passmanagers.FunctionPassManager): + self._populate_function_pm(pm) + else: + raise TypeError(pm) + + def _dispose(self): + self._capi.LLVMPY_PassManagerBuilderDispose(self) + + +# ============================================================================ +# FFI + +ffi.lib.LLVMPY_PassManagerBuilderCreate.restype = ffi.LLVMPassManagerBuilderRef + +ffi.lib.LLVMPY_PassManagerBuilderDispose.argtypes = [ + ffi.LLVMPassManagerBuilderRef, +] + +ffi.lib.LLVMPY_PassManagerBuilderPopulateModulePassManager.argtypes = [ + ffi.LLVMPassManagerBuilderRef, + ffi.LLVMPassManagerRef, +] + +ffi.lib.LLVMPY_PassManagerBuilderPopulateFunctionPassManager.argtypes = [ + ffi.LLVMPassManagerBuilderRef, + ffi.LLVMPassManagerRef, +] + +# Unsigned int PassManagerBuilder properties + +for _func in (ffi.lib.LLVMPY_PassManagerBuilderSetOptLevel, + ffi.lib.LLVMPY_PassManagerBuilderSetSizeLevel, + ffi.lib.LLVMPY_PassManagerBuilderUseInlinerWithThreshold, + ): + _func.argtypes = [ffi.LLVMPassManagerBuilderRef, c_uint] + +for _func in (ffi.lib.LLVMPY_PassManagerBuilderGetOptLevel, + ffi.lib.LLVMPY_PassManagerBuilderGetSizeLevel, + ): + _func.argtypes = [ffi.LLVMPassManagerBuilderRef] + _func.restype = c_uint + +# Boolean PassManagerBuilder properties + +for _func in (ffi.lib.LLVMPY_PassManagerBuilderSetDisableUnrollLoops, + ffi.lib.LLVMPY_PassManagerBuilderSetLoopVectorize, + ffi.lib.LLVMPY_PassManagerBuilderSetSLPVectorize, + ): + _func.argtypes = [ffi.LLVMPassManagerBuilderRef, c_bool] + +for _func in (ffi.lib.LLVMPY_PassManagerBuilderGetDisableUnrollLoops, + ffi.lib.LLVMPY_PassManagerBuilderGetLoopVectorize, + ffi.lib.LLVMPY_PassManagerBuilderGetSLPVectorize, + ): + _func.argtypes = [ffi.LLVMPassManagerBuilderRef] + _func.restype = c_bool diff --git a/llvmlite/tests/test_binding.py b/llvmlite/tests/test_binding.py index fdab23110..be0886da6 100644 --- a/llvmlite/tests/test_binding.py +++ b/llvmlite/tests/test_binding.py @@ -2245,7 +2245,7 @@ def run(use_tli): mod = llvm.parse_assembly(asm_tli_exp2) target = llvm.Target.from_triple(mod.triple) tm = target.create_target_machine() - pm = llvm.LegacyModulePassManager() + pm = llvm.ModulePassManager() tm.add_analysis_passes(pm) if use_tli: pm.add_target_library_info(mod.triple) @@ -2267,7 +2267,7 @@ def test_instruction_namer_pass(self): mod = llvm.parse_assembly(asm) # Run instnamer pass - pm = llvm.LegacyModulePassManager() + pm = llvm.ModulePassManager() pm.add_instruction_namer_pass() pm.run(mod) @@ -2621,13 +2621,13 @@ def test_close(self): def test_getMPM(self): pb = self.pb() - mpm = pb.getModulePassManager() + mpm = pb.getNewModulePassManager() mpm.run(self.module(), pb) pb.close() def test_getFPM(self): pb = self.pb() - fpm = pb.getFunctionPassManager() + fpm = pb.getNewFunctionPassManager() fpm.run(self.module().get_function("sum"), pb) pb.close() @@ -2644,7 +2644,7 @@ def test_run(self): pb = self.pb(3) mod = self.module() orig_asm = str(mod) - mpm = pb.getModulePassManager() + mpm = pb.getNewModulePassManager() mpm.run(mod, pb) optimized_asm = str(mod) self.assertIn("%.4", orig_asm) @@ -2685,7 +2685,7 @@ def test_run(self): mod = self.module() fun = mod.get_function("sum") orig_asm = str(fun) - fpm = pb.getFunctionPassManager() + fpm = pb.getNewFunctionPassManager() fpm.run(fun, pb) optimized_asm = str(fun) self.assertIn("%.4", orig_asm) diff --git a/llvmlite/tests/test_refprune.py b/llvmlite/tests/test_refprune.py index 1e15b918e..0c4208a26 100644 --- a/llvmlite/tests/test_refprune.py +++ b/llvmlite/tests/test_refprune.py @@ -116,7 +116,7 @@ def generate_ir(self, nodes, edges): def apply_refprune(self, irmod): mod = llvm.parse_assembly(str(irmod)) - pm = llvm.LegacyModulePassManager() + pm = llvm.ModulePassManager() pm.add_refprune_pass() pm.run(mod) return mod @@ -168,7 +168,7 @@ class BaseTestByIR(TestCase): def check(self, irmod, subgraph_limit=None): mod = llvm.parse_assembly(f"{self.prologue}\n{irmod}") - pm = llvm.LegacyModulePassManager() + pm = llvm.ModulePassManager() if subgraph_limit is None: pm.add_refprune_pass(self.refprune_bitmask) else: From 5c90df33bb2bc83784b090102c42c35eea56480a Mon Sep 17 00:00:00 2001 From: Yashwant Singh Date: Tue, 14 May 2024 16:55:25 +0530 Subject: [PATCH 07/27] fix makefiles --- ffi/Makefile.freebsd | 2 +- ffi/Makefile.osx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ffi/Makefile.freebsd b/ffi/Makefile.freebsd index 09635d910..f4a4ad400 100644 --- a/ffi/Makefile.freebsd +++ b/ffi/Makefile.freebsd @@ -12,7 +12,7 @@ INCLUDE = core.h SRC = assembly.cpp bitcode.cpp core.cpp initfini.cpp module.cpp value.cpp \ executionengine.cpp transforms.cpp passmanagers.cpp type.cpp targets.cpp \ dylib.cpp linker.cpp object_file.cpp orcjit.cpp custom_passes.cpp \ - memorymanager.cpp + memorymanager.cpp newpassmanagers.cpp OUTPUT = libllvmlite.so all: $(OUTPUT) diff --git a/ffi/Makefile.osx b/ffi/Makefile.osx index afe4f3bac..321a14a16 100644 --- a/ffi/Makefile.osx +++ b/ffi/Makefile.osx @@ -9,7 +9,7 @@ INCLUDE = core.h SRC = assembly.cpp bitcode.cpp core.cpp initfini.cpp module.cpp value.cpp \ executionengine.cpp transforms.cpp passmanagers.cpp targets.cpp type.cpp \ dylib.cpp linker.cpp object_file.cpp custom_passes.cpp orcjit.cpp \ - memorymanager.cpp + memorymanager.cpp newpassmanagers.cpp OUTPUT = libllvmlite.dylib MACOSX_DEPLOYMENT_TARGET ?= 10.9 From dfc2f3491e538684832f2f07fe2b899ba03ba5a6 Mon Sep 17 00:00:00 2001 From: Yashwant Singh Date: Tue, 14 May 2024 16:59:25 +0530 Subject: [PATCH 08/27] Fix some function names --- ffi/newpassmanagers.cpp | 4 ++-- llvmlite/binding/newpassmangers.py | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/ffi/newpassmanagers.cpp b/ffi/newpassmanagers.cpp index ff6133118..0ca7942b1 100644 --- a/ffi/newpassmanagers.cpp +++ b/ffi/newpassmanagers.cpp @@ -52,7 +52,7 @@ LLVMPY_CreateNewModulePassManager() { } API_EXPORT(void) -LLVMPY_NMPRun_module(LLVMModulePassManagerRef MPMRef, LLVMPassBuilderRef PBRef, +LLVMPY_RunNewModulePassManager(LLVMModulePassManagerRef MPMRef, LLVMPassBuilderRef PBRef, LLVMModuleRef mod) { ModulePassManager *MPM = llvm::unwrap(MPMRef); @@ -125,7 +125,7 @@ LLVMPY_CreateNewFunctionPassManager() { } API_EXPORT(void) -LLVMPY_NMPRun_function(LLVMFunctionPassManagerRef FPMRef, +LLVMPY_RunNewFunctionPassManager(LLVMFunctionPassManagerRef FPMRef, LLVMPassBuilderRef PBRef, LLVMValueRef FRef) { FunctionPassManager *FPM = llvm::unwrap(FPMRef); diff --git a/llvmlite/binding/newpassmangers.py b/llvmlite/binding/newpassmangers.py index 45e786e77..ed3f14140 100644 --- a/llvmlite/binding/newpassmangers.py +++ b/llvmlite/binding/newpassmangers.py @@ -29,7 +29,7 @@ def __init__(self, ptr=None): ffi.ObjectRef.__init__(self, ptr) def run(self, module, pb): - ffi.lib.LLVMPY_NMPRun_module(self, pb, module) + ffi.lib.LLVMPY_RunNewModulePassManager(self, pb, module) def addVerifier(self): ffi.lib.LLVMPY_AddVeriferPass(self) @@ -71,7 +71,7 @@ def add_simplify_cfg_pass(self): ffi.lib.LLVMPY_AddSimplifyCFGPass_function(self) def run(self, fun, pb): - ffi.lib.LLVMPY_NMPRun_function(self, pb, fun) + ffi.lib.LLVMPY_RunNewFunctionPassManager(self, pb, fun) def add_loop_unroll_pass(self): ffi.lib.LLVMPY_AddLoopUnrollPass_function(self) @@ -200,7 +200,7 @@ def _dispose(self): ffi.lib.LLVMPY_CreateNewModulePassManager.restype = ffi.LLVMModulePassManagerRef -ffi.lib.LLVMPY_NMPRun_module.argtypes = [ffi.LLVMModulePassManagerRef, +ffi.lib.LLVMPY_RunNewModulePassManager.argtypes = [ffi.LLVMModulePassManagerRef, ffi.LLVMPassBuilderRef, ffi.LLVMModuleRef,] @@ -227,7 +227,7 @@ def _dispose(self): ffi.lib.LLVMPY_CreateNewFunctionPassManager.restype = \ ffi.LLVMFunctionPassManagerRef -ffi.lib.LLVMPY_NMPRun_function.argtypes = [ffi.LLVMFunctionPassManagerRef, +ffi.lib.LLVMPY_RunNewFunctionPassManager.argtypes = [ffi.LLVMFunctionPassManagerRef, ffi.LLVMPassBuilderRef, ffi.LLVMValueRef,] From 24772184b4b1987d3c9c324b00b2e0c8a379bbb7 Mon Sep 17 00:00:00 2001 From: Yashwant Singh Date: Thu, 16 May 2024 10:01:23 +0530 Subject: [PATCH 09/27] More formatting --- ffi/newpassmanagers.cpp | 6 +++--- llvmlite/binding/newpassmangers.py | 11 ++++++----- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/ffi/newpassmanagers.cpp b/ffi/newpassmanagers.cpp index 0ca7942b1..33b8df0dc 100644 --- a/ffi/newpassmanagers.cpp +++ b/ffi/newpassmanagers.cpp @@ -52,8 +52,8 @@ LLVMPY_CreateNewModulePassManager() { } API_EXPORT(void) -LLVMPY_RunNewModulePassManager(LLVMModulePassManagerRef MPMRef, LLVMPassBuilderRef PBRef, - LLVMModuleRef mod) { +LLVMPY_RunNewModulePassManager(LLVMModulePassManagerRef MPMRef, + LLVMPassBuilderRef PBRef, LLVMModuleRef mod) { ModulePassManager *MPM = llvm::unwrap(MPMRef); PassBuilder *PB = llvm::unwrap(PBRef); @@ -126,7 +126,7 @@ LLVMPY_CreateNewFunctionPassManager() { API_EXPORT(void) LLVMPY_RunNewFunctionPassManager(LLVMFunctionPassManagerRef FPMRef, - LLVMPassBuilderRef PBRef, LLVMValueRef FRef) { + LLVMPassBuilderRef PBRef, LLVMValueRef FRef) { FunctionPassManager *FPM = llvm::unwrap(FPMRef); PassBuilder *PB = llvm::unwrap(PBRef); diff --git a/llvmlite/binding/newpassmangers.py b/llvmlite/binding/newpassmangers.py index ed3f14140..f8be44b9b 100644 --- a/llvmlite/binding/newpassmangers.py +++ b/llvmlite/binding/newpassmangers.py @@ -201,8 +201,8 @@ def _dispose(self): ffi.lib.LLVMPY_CreateNewModulePassManager.restype = ffi.LLVMModulePassManagerRef ffi.lib.LLVMPY_RunNewModulePassManager.argtypes = [ffi.LLVMModulePassManagerRef, - ffi.LLVMPassBuilderRef, - ffi.LLVMModuleRef,] + ffi.LLVMPassBuilderRef, + ffi.LLVMModuleRef,] ffi.lib.LLVMPY_AddVeriferPass.argtypes = [ffi.LLVMModulePassManagerRef,] ffi.lib.LLVMPY_AddAAEvalPass_module.argtypes = [ffi.LLVMModulePassManagerRef,] @@ -227,9 +227,10 @@ def _dispose(self): ffi.lib.LLVMPY_CreateNewFunctionPassManager.restype = \ ffi.LLVMFunctionPassManagerRef -ffi.lib.LLVMPY_RunNewFunctionPassManager.argtypes = [ffi.LLVMFunctionPassManagerRef, - ffi.LLVMPassBuilderRef, - ffi.LLVMValueRef,] +ffi.lib.LLVMPY_RunNewFunctionPassManager.argtypes = [ + ffi.LLVMFunctionPassManagerRef, + ffi.LLVMPassBuilderRef, + ffi.LLVMValueRef,] ffi.lib.LLVMPY_AddAAEvalPass_function.argtypes = [ ffi.LLVMFunctionPassManagerRef,] From 63a4237d7840ca41f23c1a7b91583004efef564a Mon Sep 17 00:00:00 2001 From: Yashwant Singh Date: Thu, 16 May 2024 11:06:25 +0530 Subject: [PATCH 10/27] Add new pass manager examples, split npm-usage.py --- docs/source/user-guide/examples/npm-usage.py | 258 ------------------- examples/optimization-passes-npm.py | 56 ++++ examples/optimization-pipeline-npm.py | 68 +++++ 3 files changed, 124 insertions(+), 258 deletions(-) delete mode 100644 docs/source/user-guide/examples/npm-usage.py create mode 100644 examples/optimization-passes-npm.py create mode 100644 examples/optimization-pipeline-npm.py diff --git a/docs/source/user-guide/examples/npm-usage.py b/docs/source/user-guide/examples/npm-usage.py deleted file mode 100644 index 51a6d673b..000000000 --- a/docs/source/user-guide/examples/npm-usage.py +++ /dev/null @@ -1,258 +0,0 @@ -try: - import faulthandler; faulthandler.enable() -except ImportError: - pass - -import llvmlite.ir as ll -import llvmlite.binding as llvm - - -llvm.initialize() -llvm.initialize_native_target() -llvm.initialize_native_asmprinter() - - -fnty = ll.FunctionType(ll.IntType(32), [ll.IntType(32).as_pointer(), - ll.IntType(32)]) -module = ll.Module() -func = ll.Function(module, fnty, name="sum") -bb_entry = func.append_basic_block() -bb_loop = func.append_basic_block() -bb_exit = func.append_basic_block() -builder = ll.IRBuilder() -builder.position_at_end(bb_entry) -builder.branch(bb_loop) -builder.position_at_end(bb_loop) -index = builder.phi(ll.IntType(32)) -index.add_incoming(ll.Constant(index.type, 0), bb_entry) -accum = builder.phi(ll.IntType(32)) -accum.add_incoming(ll.Constant(accum.type, 0), bb_entry) -ptr = builder.gep(func.args[0], [index]) -value = builder.load(ptr) -added = builder.add(accum, ll.Constant(index.type, 0)) -accum.add_incoming(added, bb_loop) -indexp1 = builder.add(index, ll.Constant(index.type, 1)) -index.add_incoming(indexp1, bb_loop) -cond = builder.icmp_unsigned('<', indexp1, func.args[1]) -builder.cbranch(cond, bb_loop, bb_exit) -builder.position_at_end(bb_exit) -builder.ret(added) -strmod = str(module) - -strmod2 = """ -; RUN: opt -simplifycfg -S --preserve-ll-uselistorder %s | FileCheck %s -; REQUIRES: x86-registered-target -; CHECK-LABEL: @n -; CHECK: uselistorder i16 0, { 3, 2, 4, 1, 5, 0, 6 } -; Note: test was added in an effort to ensure determinism when updating memoryssa. See PR42574. -; If the uselistorder check becomes no longer relevant, the test can be disabled or removed. -%rec9 = type { i16, i32, i32 } -@a = global [1 x [1 x %rec9]] zeroinitializer -define i16 @n() { - br label %..split_crit_edge -..split_crit_edge: ; preds = %0 - br label %.split -bb4.us4: ; preds = %bb2.split.us32, %bb6.us28 - %i.4.01.us5 = phi i16 [ %_tmp49.us30, %bb6.us28 ] - br label %g.exit4.us21 -bb1.i.us14: ; preds = %bb4.us4 - br label %g.exit4.us21 -g.exit4.us21: ; preds = %bb1.i.us14, %g.exit4.critedge.us9 - %i.4.02.us22 = phi i16 [ %i.4.01.us5, %bb4.us4 ], [ %i.4.01.us5, %bb1.i.us14 ] - br label %bb6.us28 -bb5.us26: ; preds = %g.exit4.us21 - br label %bb6.us28 -bb6.us28: ; preds = %bb5.us26, %g.exit4.us21 - %i.4.03.us29 = phi i16 [ %i.4.02.us22, %bb5.us26 ], [ %i.4.02.us22, %g.exit4.us21 ] - %_tmp49.us30 = add nuw nsw i16 %i.4.03.us29, 1 - br label %bb4.us4 -bb4.us.us: ; preds = %bb2.split.us.us, %bb6.us.us - %i.4.01.us.us = phi i16 [ %_tmp49.us.us, %bb6.us.us ] - br label %bb1.i.us.us -bb1.i.us.us: ; preds = %bb4.us.us - br label %g.exit4.us.us -g.exit4.us.us: ; preds = %bb1.i.us.us, %g.exit4.critedge.us.us - %i.4.02.us.us = phi i16 [ %i.4.01.us.us, %bb1.i.us.us ] - br label %bb5.us.us -bb5.us.us: ; preds = %g.exit4.us.us - br label %bb6.us.us -bb6.us.us: ; preds = %bb5.us.us, %g.exit4.us.us - %i.4.03.us.us = phi i16 [ %i.4.02.us.us, %bb5.us.us ] - %_tmp49.us.us = add nuw nsw i16 %i.4.03.us.us, 1 - br label %bb4.us.us -.split: ; preds = %..split_crit_edge - br label %bb2 -bb2: ; preds = %.split, %bb7 - %h.3.0 = phi i16 [ undef, %.split ], [ %_tmp53, %bb7 ] - br label %bb2.bb2.split_crit_edge -bb2.bb2.split_crit_edge: ; preds = %bb2 - br label %bb2.split -bb2.split.us: ; preds = %bb2 - br label %bb4.us -bb4.us: ; preds = %bb6.us, %bb2.split.us - %i.4.01.us = phi i16 [ 0, %bb2.split.us ] - br label %bb1.i.us -g.exit4.critedge.us: ; preds = %bb4.us - br label %g.exit4.us -bb1.i.us: ; preds = %bb4.us - br label %g.exit4.us -g.exit4.us: ; preds = %bb1.i.us, %g.exit4.critedge.us - %i.4.02.us = phi i16 [ %i.4.01.us, %g.exit4.critedge.us ], [ %i.4.01.us, %bb1.i.us ] - br label %bb5.us -bb5.us: ; preds = %g.exit4.us - br label %bb7 -bb2.split: ; preds = %bb2.bb2.split_crit_edge - br label %bb4 - -bb4: ; preds = %bb2.split, %bb6 - %i.4.01 = phi i16 [ 0, %bb2.split ] - %_tmp16 = getelementptr [1 x [1 x %rec9]], [1 x [1 x %rec9]]* @a, i16 0, i16 %h.3.0, i16 %i.4.01, i32 0 - %_tmp17 = load i16, i16* %_tmp16, align 1 - br label %g.exit4.critedge - -bb1.i: ; preds = %bb4 - br label %g.exit4 - -g.exit4.critedge: ; preds = %bb4 - %_tmp28.c = getelementptr [1 x [1 x %rec9]], [1 x [1 x %rec9]]* @a, i16 0, i16 %h.3.0, i16 %i.4.01, i32 1 - %_tmp29.c = load i32, i32* %_tmp28.c, align 1 - %_tmp30.c = trunc i32 %_tmp29.c to i16 - br label %g.exit4 - -g.exit4: ; preds = %g.exit4.critedge, %bb1.i - %i.4.02 = phi i16 [ %i.4.01, %g.exit4.critedge ], [ %i.4.01, %bb1.i ] - %_tmp41 = getelementptr [1 x [1 x %rec9]], [1 x [1 x %rec9]]* @a, i16 0, i16 %h.3.0, i16 %i.4.02, i32 2 - br label %bb6 - -bb5: ; preds = %g.exit4 - br label %bb6 -bb6: ; preds = %bb5, %g.exit4 - %i.4.03 = phi i16 [ %i.4.02, %bb5 ], [ %i.4.02, %g.exit4 ] - %_tmp49 = add nuw nsw i16 %i.4.03, 1 - br label %bb7 -bb7: ; preds = %bb7.us-lcssa.us, %bb7.us-lcssa - %_tmp53 = add nsw i16 %h.3.0, 1 - br label %bb2 -} -""" - -strunroll = """ -define dso_local i32 @test(i64 %a, i64 %b, i64 %c) local_unnamed_addr { -entry: - br label %for.body - -for.cond.cleanup: ; preds = %for.body - %cmp6 = icmp eq i32 %val.2, 0 - %cond = zext i1 %cmp6 to i32 - ret i32 %cond - -for.body: ; preds = %for.body, %entry - %i.018 = phi i64 [ 0, %entry ], [ %inc, %for.body ] - %val.017 = phi i32 [ 0, %entry ], [ %val.2, %for.body ] - %a.addr.016 = phi i64 [ %a, %entry ], [ %add, %for.body ] - %b.addr.015 = phi i64 [ %b, %entry ], [ %add5, %for.body ] - %cmp1 = icmp ugt i64 %a.addr.016, %b.addr.015 - %add = add i64 %a.addr.016, %b.addr.015 - %cmp2 = icmp ugt i64 %b.addr.015, %c - %0 = or i1 %cmp2, %cmp1 - %val.2 = select i1 %0, i32 1, i32 %val.017 - %add5 = add i64 %b.addr.015, %c - %inc = add nuw nsw i64 %i.018, 1 - %exitcond = icmp eq i64 %inc, 100 - br i1 %exitcond, label %for.cond.cleanup, label %for.body, !llvm.loop !2 -} -; CHECK: [[VAL:r[0-9]+]] = w{{[0-9]+}} -; CHECK-NOT: [[VAL:r[0-9]+]] <<= 32 -; CHECK-NOT: [[VAL]] >>= 32 -; CHECK: if [[VAL]] == 0 goto - -!2 = distinct !{!2, !3} -!3 = !{!"llvm.loop.unroll.enable"} -""" - -strunroll2 = """ -define i32 @foo3(i32* noalias nocapture readonly %src) { -entry: - br label %loop.header - -loop.header: - %iv = phi i64 [ 0, %entry ], [ %inc, %loop.latch ] - %r1 = phi i32 [ 0, %entry ], [ %r3, %loop.latch ] - %arrayidx = getelementptr inbounds i32, i32* %src, i64 %iv - %src_element = load i32, i32* %arrayidx, align 4 - %cmp = icmp eq i32 0, %src_element - br i1 %cmp, label %loop.if, label %loop.latch - -loop.if: - %r2 = add i32 %r1, 1 - br label %loop.latch -loop.latch: - %r3 = phi i32 [%r1, %loop.header], [%r2, %loop.if] - %inc = add nuw nsw i64 %iv, 1 - %exitcond = icmp eq i64 %inc, 9 - br i1 %exitcond, label %loop.end, label %loop.header -loop.end: - %r.lcssa = phi i32 [ %r3, %loop.latch ] - ret i32 %r.lcssa -} -""" - -# check default pipeline + simplifycfg on module -npm2 = llvm.create_new_module_pass_manager() -llmod = llvm.parse_assembly(strmod) -print(llmod) -tm = llvm.Target.from_default_triple().create_target_machine() -pto = llvm.create_pipeline_options() -pto.opt_level = 2 # similarly more properties can be set -pb = llvm.create_pass_builder(tm, pto) -npm_o2 = pb.getNewModulePassManager() -npm_o2.run(llmod, pb) -print(llmod) - - -# npm.add_simplify_cfg_pass() -# npm.run(llmod2, pb) -# print("Simplified module 2 *******") -# print(llmod2) - - -# check default pipeline + simplifycfg on a function -llmod2 = llvm.parse_assembly(strmod2) -tm = llvm.Target.from_default_triple().create_target_machine() -pto = llvm.create_pipeline_options() -pto.opt_level = 3 # similarly more properties can be set -pb = llvm.create_pass_builder(tm, pto) -fun = llmod2.get_function("n") -print(fun) -fpm = pb.getNewFunctionPassManager() -fpm.add_simplify_cfg_pass() -fpm.run(fun, pb) -print(fun) - - -# Check loop_unrolling option in PTO -llmod_unroll = llvm.parse_assembly(strunroll2) -print(llmod_unroll) -tm = llvm.Target.from_default_triple().create_target_machine() -pto = llvm.create_pipeline_options() -pto.opt_level = 3 # similarly more properties can be set -pto.loop_unrolling = False -pb = llvm.create_pass_builder(tm, pto) -npm = pb.getNewModulePassManager() -# # Inplace optimize the IR module -npm.run(llmod_unroll, pb) -print(llmod_unroll) - - -# Check loop rotate -npm2 = llvm.create_new_module_pass_manager() -npm2.add_loop_rotate_pass() -npm2.run(llmod_unroll, pb) -print(llmod_unroll) - - -# Check instcombine -npm3 = llvm.create_new_module_pass_manager() -npm3.add_instruction_combine_pass() -npm3.run(llmod_unroll, pb) -print(llmod_unroll) diff --git a/examples/optimization-passes-npm.py b/examples/optimization-passes-npm.py new file mode 100644 index 000000000..869d9aa75 --- /dev/null +++ b/examples/optimization-passes-npm.py @@ -0,0 +1,56 @@ +try: + import faulthandler; faulthandler.enable() +except ImportError: + pass + +import llvmlite.ir as ll +import llvmlite.binding as llvm + + +llvm.initialize() +llvm.initialize_native_target() +llvm.initialize_native_asmprinter() + +strmod = """ +define i32 @foo3(i32* noalias nocapture readonly %src) { +entry: + br label %loop.header + +loop.header: + %iv = phi i64 [ 0, %entry ], [ %inc, %loop.latch ] + %r1 = phi i32 [ 0, %entry ], [ %r3, %loop.latch ] + %arrayidx = getelementptr inbounds i32, i32* %src, i64 %iv + %src_element = load i32, i32* %arrayidx, align 4 + %cmp = icmp eq i32 0, %src_element + br i1 %cmp, label %loop.if, label %loop.latch + +loop.if: + %r2 = add i32 %r1, 1 + br label %loop.latch +loop.latch: + %r3 = phi i32 [%r1, %loop.header], [%r2, %loop.if] + %inc = add nuw nsw i64 %iv, 1 + %exitcond = icmp eq i64 %inc, 9 + br i1 %exitcond, label %loop.end, label %loop.header +loop.end: + %r.lcssa = phi i32 [ %r3, %loop.latch ] + ret i32 %r.lcssa +} +""" + +# Run loop-unroll + simplifycfg on module + +llmod = llvm.parse_assembly(strmod) +print(llmod) + +target_machine = llvm.Target.from_default_triple().create_target_machine() +pto = llvm.create_pipeline_options() +pto.opt_level = 0 +pb = llvm.create_pass_builder(target_machine, pto) + +pm = llvm.create_new_module_pass_manager() +pm.add_loop_unroll_pass() +pm.add_simplify_cfg_pass() +pm.run(llmod, pb) + +print(llmod) diff --git a/examples/optimization-pipeline-npm.py b/examples/optimization-pipeline-npm.py new file mode 100644 index 000000000..33641d189 --- /dev/null +++ b/examples/optimization-pipeline-npm.py @@ -0,0 +1,68 @@ +try: + import faulthandler; faulthandler.enable() +except ImportError: + pass + +from ctypes import CFUNCTYPE, c_int, POINTER +import llvmlite.ir as ll +import llvmlite.binding as llvm + + +llvm.initialize() +llvm.initialize_native_target() +llvm.initialize_native_asmprinter() + +strmod = """ +define i32 @foo3(i32* noalias nocapture readonly %src) { +entry: + br label %loop.header + +loop.header: + %iv = phi i64 [ 0, %entry ], [ %inc, %loop.latch ] + %r1 = phi i32 [ 0, %entry ], [ %r3, %loop.latch ] + %arrayidx = getelementptr inbounds i32, i32* %src, i64 %iv + %src_element = load i32, i32* %arrayidx, align 4 + %cmp = icmp eq i32 0, %src_element + br i1 %cmp, label %loop.if, label %loop.latch + +loop.if: + %r2 = add i32 %r1, 1 + br label %loop.latch +loop.latch: + %r3 = phi i32 [%r1, %loop.header], [%r2, %loop.if] + %inc = add nuw nsw i64 %iv, 1 + %exitcond = icmp eq i64 %inc, 9 + br i1 %exitcond, label %loop.end, label %loop.header +loop.end: + %r.lcssa = phi i32 [ %r3, %loop.latch ] + ret i32 %r.lcssa +} +""" + +# Run -O3 optimization pipeline on the module + +llmod = llvm.parse_assembly(strmod) +print(llmod) + +target_machine = llvm.Target.from_default_triple().create_target_machine() +pto = llvm.create_pipeline_options() +pto.opt_level = 3 +pb = llvm.create_pass_builder(target_machine, pto) + +pm = pb.getNewModulePassManager() +pm.run(llmod, pb) +print(llmod) + +with llvm.create_mcjit_compiler(llmod, target_machine) as ee: + ee.finalize_object() + cfptr = ee.get_function_address("sum") + + print("-- JIT compile:") + + print(target_machine.emit_assembly(llmod)) + + cfunc = CFUNCTYPE(c_int, POINTER(c_int), c_int)(cfptr) + A = np.arange(10, dtype=np.int32) + res = cfunc(A.ctypes.data_as(POINTER(c_int)), A.size) + + print(res, A.sum()) From 592c7b9c4d0ed4a8f745155e9bd2cda76c93036e Mon Sep 17 00:00:00 2001 From: Yashwant Singh Date: Thu, 16 May 2024 11:40:15 +0530 Subject: [PATCH 11/27] Re-add -flto --- ffi/Makefile.linux | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ffi/Makefile.linux b/ffi/Makefile.linux index 560d94de5..448a920f9 100644 --- a/ffi/Makefile.linux +++ b/ffi/Makefile.linux @@ -2,7 +2,7 @@ CXX ?= g++ # -flto and --exclude-libs allow us to remove those parts of LLVM we don't use -#CXX_FLTO_FLAGS ?= -flto +CXX_FLTO_FLAGS ?= -flto LD_FLTO_FLAGS ?= -flto -Wl,--exclude-libs=ALL # -fPIC is required when compiling objects for a shared library CXX_FPIC_FLAGS ?= -fPIC From 20aeaa4fa06b223330555219ffed7f2a2329d865 Mon Sep 17 00:00:00 2001 From: Yashwant Singh Date: Thu, 16 May 2024 12:36:40 +0530 Subject: [PATCH 12/27] New pass manager documentation --- .../binding/optimization-passes.rst | 104 ++++++++++++++++++ 1 file changed, 104 insertions(+) diff --git a/docs/source/user-guide/binding/optimization-passes.rst b/docs/source/user-guide/binding/optimization-passes.rst index 7894e4785..591ef9194 100644 --- a/docs/source/user-guide/binding/optimization-passes.rst +++ b/docs/source/user-guide/binding/optimization-passes.rst @@ -14,6 +14,110 @@ kinds of pass managers: * :class:`ModulePassManager`, for optimizations that work on whole modules. +For optimization pipeline LLVM supports 2 different pass managing mechanisms. +The old one is now renamed to LegacyPassManager and is deprecated. From `llvm17` +LegacyPassManager's support is no longer reliable with many passes not working +with it. + +`llvmlite` right now supports both the `LegacyPassManager` and the `NewPassManager`, +but consider `LegacyPassManager` deprecated and you are advised to shift your +code to `NewPassManager` APIs. + +New Pass Manager +=================== + +To manage the optimization attributes we first need to instantiate +.. class:: PipelineTuningOptions() + + Creates a new PipelineTuningOptions object + + The following writable attributes are available: + + * .. attribute:: loop_interleaving + + If ``False``, disable loop interleaving. + + * .. attribute:: loop_vectorization + + If ``True``, allow vectorizing loops. + + * .. attribute:: slp_vectorize + + If ``True``, enable the SLP vectorizer, which uses a + different algorithm than the loop vectorizer. Both may + be enabled at the same time. + + * .. attribute:: loop_unrolling + + If ``False``, disable loop unrolling. + +.. FIXME: Available from llvm16 +.. * .. attribute:: inlining_threshold + +.. The integer threshold for inlining one function into +.. another. The higher the number, the more likely that +.. inlining will occur. This attribute is write-only. + + * .. attribute:: opt_level + + The general optimization level, as an integer between 0 + and 3. + + * .. attribute:: size_level + + Whether and how much to optimize for size, as an integer + between 0 and 2. + + +Similar to `LegacyPassManager` we need a `PassBuilder` object to manage the +respective `function` and `module` pass managers. + +.. class:: PassBuilder(target_machine, pipeline_tuning_options) + + Create a new pass builder. This takes :class:`TargetMachine` and + :class:`PipelineTuningOptions` objects as parameters. + + .. method:: getNewModulePassManager() + + Return a populated `ModulePassManager` object based on PTO settings. + + .. method:: getNewFunctionPassManager() + + Return a populated `FunctionPassManager` object based on PTO settings. + + +.. class:: NewModulePassManager() + + Create a new pass manager to run optimization passes on a + llvm module. + + .. method:: run(module, passbuilder) + + Run optimization passes on the + *module*, a :class:`ModuleRef` instance. + + Use individual ``add_*`` methods to add optimization passes + or use :meth:`PassBuilder.getNewModulePassManager` to get + optimization passes populated `NewModulePassManager` object. + +.. class:: NewFunctionPassManager() + + Create a new pass manager to run optimization passes on a + llvm function. + + .. method:: run(function, passbuilder) + + Run optimization passes on the + *function*, a :class:`ValueRef` instance. + + Use individual ``add_*`` methods to add optimization passes + or use :meth:`PassBuilder.getNewFunctionPassManager` to get + optimization passes populated `NewFunctionPassManager` object. + + +Legacy Pass Manager +=================== + To instantiate either of these pass managers, you first need to create and configure a :class:`PassManagerBuilder`. From e2da92fdf7c90270ea1daff493dff4c899331036 Mon Sep 17 00:00:00 2001 From: Yashwant Singh Date: Thu, 16 May 2024 18:32:11 +0530 Subject: [PATCH 13/27] fix example --- examples/optimization-pipeline-npm.py | 53 +++++++++++++++------------ 1 file changed, 29 insertions(+), 24 deletions(-) diff --git a/examples/optimization-pipeline-npm.py b/examples/optimization-pipeline-npm.py index 33641d189..3f8600916 100644 --- a/examples/optimization-pipeline-npm.py +++ b/examples/optimization-pipeline-npm.py @@ -7,35 +7,33 @@ import llvmlite.ir as ll import llvmlite.binding as llvm +import numpy as np llvm.initialize() llvm.initialize_native_target() llvm.initialize_native_asmprinter() strmod = """ -define i32 @foo3(i32* noalias nocapture readonly %src) { -entry: - br label %loop.header - -loop.header: - %iv = phi i64 [ 0, %entry ], [ %inc, %loop.latch ] - %r1 = phi i32 [ 0, %entry ], [ %r3, %loop.latch ] - %arrayidx = getelementptr inbounds i32, i32* %src, i64 %iv - %src_element = load i32, i32* %arrayidx, align 4 - %cmp = icmp eq i32 0, %src_element - br i1 %cmp, label %loop.if, label %loop.latch - -loop.if: - %r2 = add i32 %r1, 1 - br label %loop.latch -loop.latch: - %r3 = phi i32 [%r1, %loop.header], [%r2, %loop.if] - %inc = add nuw nsw i64 %iv, 1 - %exitcond = icmp eq i64 %inc, 9 - br i1 %exitcond, label %loop.end, label %loop.header -loop.end: - %r.lcssa = phi i32 [ %r3, %loop.latch ] - ret i32 %r.lcssa +; ModuleID = '' +source_filename = "" +target triple = "unknown-unknown-unknown" + +define i32 @sum(i32* %.1, i32 %.2) { +.4: + br label %.5 + +.5: ; preds = %.5, %.4 + %.8 = phi i32 [ 0, %.4 ], [ %.13, %.5 ] + %.9 = phi i32 [ 0, %.4 ], [ %.12, %.5 ] + %.10 = getelementptr i32, i32* %.1, i32 %.8 + %.11 = load i32, i32* %.10, align 4 + %.12 = add i32 %.9, %.11 + %.13 = add i32 %.8, 1 + %.14 = icmp ult i32 %.13, %.2 + br i1 %.14, label %.5, label %.6 + +.6: ; preds = %.5 + ret i32 %.12 } """ @@ -45,12 +43,19 @@ print(llmod) target_machine = llvm.Target.from_default_triple().create_target_machine() + pto = llvm.create_pipeline_options() pto.opt_level = 3 pb = llvm.create_pass_builder(target_machine, pto) - pm = pb.getNewModulePassManager() pm.run(llmod, pb) + +# pmb = llvm.create_pass_manager_builder() +# pmb.opt_level = 2 +# pm = llvm.create_module_pass_manager() +# pmb.populate(pm) +# pm.run(llmod) + print(llmod) with llvm.create_mcjit_compiler(llmod, target_machine) as ee: From ebb5c1ec852dfcaebdb8a2e62a54ada5c6e51861 Mon Sep 17 00:00:00 2001 From: Graham Markall Date: Fri, 17 May 2024 12:12:23 +0100 Subject: [PATCH 14/27] Tidy up new pass manager bindings - Move around interfaces in newpassmanagers.cpp / .py such that the order of them is the same in both files (easier to read / compare) - Add comments delineating the functions for different types in newpassmanagers.py - `LLVMPY_buildPerModuleDefaultPipeline` and `LLVMPY_buildFunctionSimplificationPipeline` take two ints (not one) for the speed and size levels. --- ffi/newpassmanagers.cpp | 6 ++--- llvmlite/binding/newpassmangers.py | 41 +++++++++++++++++------------- 2 files changed, 27 insertions(+), 20 deletions(-) diff --git a/ffi/newpassmanagers.cpp b/ffi/newpassmanagers.cpp index 33b8df0dc..91d64fc82 100644 --- a/ffi/newpassmanagers.cpp +++ b/ffi/newpassmanagers.cpp @@ -253,6 +253,9 @@ LLVMPY_CreatePassBuilder(LLVMTargetMachineRef TM, return llvm::wrap(new PassBuilder(target, *pt)); } +API_EXPORT(void) +LLVMPY_DisposePassBuilder(LLVMPassBuilderRef PB) { delete llvm::unwrap(PB); } + static OptimizationLevel mapLevel(int speed_level, int size_level) { switch (size_level) { case 0: @@ -311,7 +314,4 @@ LLVMPY_buildFunctionSimplificationPipeline(LLVMPassBuilderRef PBref, return llvm::wrap(FPM); } -API_EXPORT(void) -LLVMPY_DisposePassBuilder(LLVMPassBuilderRef PB) { delete llvm::unwrap(PB); } - } // end extern "C" diff --git a/llvmlite/binding/newpassmangers.py b/llvmlite/binding/newpassmangers.py index f8be44b9b..e17ad7f44 100644 --- a/llvmlite/binding/newpassmangers.py +++ b/llvmlite/binding/newpassmangers.py @@ -197,6 +197,7 @@ def _dispose(self): # ============================================================================ # FFI +# ModulePassManager ffi.lib.LLVMPY_CreateNewModulePassManager.restype = ffi.LLVMModulePassManagerRef @@ -224,6 +225,8 @@ def _dispose(self): ffi.lib.LLVMPY_DisposeNewModulePassManger.argtypes = [ ffi.LLVMModulePassManagerRef,] +# FunctionPassManager + ffi.lib.LLVMPY_CreateNewFunctionPassManager.restype = \ ffi.LLVMFunctionPassManagerRef @@ -253,23 +256,7 @@ def _dispose(self): ffi.lib.LLVMPY_DisposeNewFunctionPassManger.argtypes = [ ffi.LLVMFunctionPassManagerRef,] -ffi.lib.LLVMPY_CreatePassBuilder.restype = ffi.LLVMPassBuilderRef -ffi.lib.LLVMPY_CreatePassBuilder.argtypes = [ffi.LLVMTargetMachineRef, - ffi.LLVMPipelineTuningOptionsRef,] - -ffi.lib.LLVMPY_buildPerModuleDefaultPipeline.restype = \ - ffi.LLVMModulePassManagerRef - -ffi.lib.LLVMPY_buildPerModuleDefaultPipeline.argtypes = [ - ffi.LLVMPassBuilderRef, c_int,] - -ffi.lib.LLVMPY_buildFunctionSimplificationPipeline.restype = \ - ffi.LLVMFunctionPassManagerRef - -ffi.lib.LLVMPY_buildFunctionSimplificationPipeline.argtypes = [ - ffi.LLVMPassBuilderRef, c_int,] - -ffi.lib.LLVMPY_DisposePassBuilder.argtypes = [ffi.LLVMPassBuilderRef,] +# PipelineTuningOptions ffi.lib.LLVMPY_CreatePipelineTuningOptions.restype = \ ffi.LLVMPipelineTuningOptionsRef @@ -304,3 +291,23 @@ def _dispose(self): ffi.lib.LLVMPY_DisposePipelineTuningOptions.argtypes = \ [ffi.LLVMPipelineTuningOptionsRef,] + +# PassBuilder + +ffi.lib.LLVMPY_CreatePassBuilder.restype = ffi.LLVMPassBuilderRef +ffi.lib.LLVMPY_CreatePassBuilder.argtypes = [ffi.LLVMTargetMachineRef, + ffi.LLVMPipelineTuningOptionsRef,] + +ffi.lib.LLVMPY_DisposePassBuilder.argtypes = [ffi.LLVMPassBuilderRef,] + +# Pipeline builders + +ffi.lib.LLVMPY_buildPerModuleDefaultPipeline.restype = \ + ffi.LLVMModulePassManagerRef +ffi.lib.LLVMPY_buildPerModuleDefaultPipeline.argtypes = [ + ffi.LLVMPassBuilderRef, c_int, c_int] + +ffi.lib.LLVMPY_buildFunctionSimplificationPipeline.restype = \ + ffi.LLVMFunctionPassManagerRef +ffi.lib.LLVMPY_buildFunctionSimplificationPipeline.argtypes = [ + ffi.LLVMPassBuilderRef, c_int, c_int] From 0833c1d0587741523ff042118eb9f89587228bf3 Mon Sep 17 00:00:00 2001 From: Yashwant Singh Date: Mon, 20 May 2024 12:16:20 +0530 Subject: [PATCH 15/27] Address review comments Remove redundant imports Rename create_pipeline_options Use super().__init__(ptr) to initialize parent classes Fix typos Remove 'for review' comments Fix PassBuilder constructor Remove 'New' from passbuilder APIs --- .../binding/optimization-passes.rst | 8 ++-- examples/optimization-passes-npm.py | 2 +- examples/optimization-pipeline-npm.py | 4 +- ffi/newpassmanagers.cpp | 10 ++-- ffi/passmanagers.cpp | 2 +- llvmlite/binding/newpassmangers.py | 46 ++++++++----------- llvmlite/binding/passmanagers.py | 2 +- llvmlite/tests/test_binding.py | 10 ++-- 8 files changed, 39 insertions(+), 45 deletions(-) diff --git a/docs/source/user-guide/binding/optimization-passes.rst b/docs/source/user-guide/binding/optimization-passes.rst index 591ef9194..2d189e5a1 100644 --- a/docs/source/user-guide/binding/optimization-passes.rst +++ b/docs/source/user-guide/binding/optimization-passes.rst @@ -77,11 +77,11 @@ respective `function` and `module` pass managers. Create a new pass builder. This takes :class:`TargetMachine` and :class:`PipelineTuningOptions` objects as parameters. - .. method:: getNewModulePassManager() + .. method:: getModulePassManager() Return a populated `ModulePassManager` object based on PTO settings. - .. method:: getNewFunctionPassManager() + .. method:: getFunctionPassManager() Return a populated `FunctionPassManager` object based on PTO settings. @@ -97,7 +97,7 @@ respective `function` and `module` pass managers. *module*, a :class:`ModuleRef` instance. Use individual ``add_*`` methods to add optimization passes - or use :meth:`PassBuilder.getNewModulePassManager` to get + or use :meth:`PassBuilder.getModulePassManager` to get optimization passes populated `NewModulePassManager` object. .. class:: NewFunctionPassManager() @@ -111,7 +111,7 @@ respective `function` and `module` pass managers. *function*, a :class:`ValueRef` instance. Use individual ``add_*`` methods to add optimization passes - or use :meth:`PassBuilder.getNewFunctionPassManager` to get + or use :meth:`PassBuilder.getFunctionPassManager` to get optimization passes populated `NewFunctionPassManager` object. diff --git a/examples/optimization-passes-npm.py b/examples/optimization-passes-npm.py index 869d9aa75..9bb3a60f3 100644 --- a/examples/optimization-passes-npm.py +++ b/examples/optimization-passes-npm.py @@ -44,7 +44,7 @@ print(llmod) target_machine = llvm.Target.from_default_triple().create_target_machine() -pto = llvm.create_pipeline_options() +pto = llvm.create_pipeline_tuning_options() pto.opt_level = 0 pb = llvm.create_pass_builder(target_machine, pto) diff --git a/examples/optimization-pipeline-npm.py b/examples/optimization-pipeline-npm.py index 3f8600916..513547f64 100644 --- a/examples/optimization-pipeline-npm.py +++ b/examples/optimization-pipeline-npm.py @@ -44,10 +44,10 @@ target_machine = llvm.Target.from_default_triple().create_target_machine() -pto = llvm.create_pipeline_options() +pto = llvm.create_pipeline_tuning_options() pto.opt_level = 3 pb = llvm.create_pass_builder(target_machine, pto) -pm = pb.getNewModulePassManager() +pm = pb.getModulePassManager() pm.run(llmod, pb) # pmb = llvm.create_pass_manager_builder() diff --git a/ffi/newpassmanagers.cpp b/ffi/newpassmanagers.cpp index 91d64fc82..0f066e041 100644 --- a/ffi/newpassmanagers.cpp +++ b/ffi/newpassmanagers.cpp @@ -72,7 +72,7 @@ LLVMPY_RunNewModulePassManager(LLVMModulePassManagerRef MPMRef, } API_EXPORT(void) -LLVMPY_AddVeriferPass(LLVMModulePassManagerRef MPM) { +LLVMPY_AddVerifierPass(LLVMModulePassManagerRef MPM) { llvm::unwrap(MPM)->addPass(VerifierPass()); } @@ -95,13 +95,13 @@ LLVMPY_AddLoopUnrollPass_module(LLVMModulePassManagerRef MPM) { } API_EXPORT(void) -LLVMPY_LLVMAddLoopRotatePass_module(LLVMModulePassManagerRef MPM) { +LLVMPY_AddLoopRotatePass_module(LLVMModulePassManagerRef MPM) { llvm::unwrap(MPM)->addPass(createModuleToFunctionPassAdaptor( createFunctionToLoopPassAdaptor(LoopRotatePass()))); } API_EXPORT(void) -LLVMPY_LLVMAddInstructionCombinePass_module(LLVMModulePassManagerRef MPM) { +LLVMPY_AddInstructionCombinePass_module(LLVMModulePassManagerRef MPM) { llvm::unwrap(MPM)->addPass( createModuleToFunctionPassAdaptor(InstCombinePass())); } @@ -160,13 +160,13 @@ LLVMPY_AddLoopUnrollPass_function(LLVMFunctionPassManagerRef FPM) { } API_EXPORT(void) -LLVMPY_LLVMAddLoopRotatePass_function(LLVMFunctionPassManagerRef FPM) { +LLVMPY_AddLoopRotatePass_function(LLVMFunctionPassManagerRef FPM) { llvm::unwrap(FPM)->addPass( createFunctionToLoopPassAdaptor(LoopRotatePass())); } API_EXPORT(void) -LLVMPY_LLVMAddInstructionCombinePass_function(LLVMFunctionPassManagerRef FPM) { +LLVMPY_AddInstructionCombinePass_function(LLVMFunctionPassManagerRef FPM) { llvm::unwrap(FPM)->addPass(InstCombinePass()); } diff --git a/ffi/passmanagers.cpp b/ffi/passmanagers.cpp index da4a076b4..915a684be 100644 --- a/ffi/passmanagers.cpp +++ b/ffi/passmanagers.cpp @@ -475,7 +475,7 @@ LLVMPY_AddBasicAliasAnalysisPass(LLVMPassManagerRef PM) { } API_EXPORT(void) -LLVMPY_LLVMAddLoopRotatePass(LLVMPassManagerRef PM) { +LLVMPY_AddLoopRotatePass(LLVMPassManagerRef PM) { LLVMAddLoopRotatePass(PM); } diff --git a/llvmlite/binding/newpassmangers.py b/llvmlite/binding/newpassmangers.py index e17ad7f44..251f1fd39 100644 --- a/llvmlite/binding/newpassmangers.py +++ b/llvmlite/binding/newpassmangers.py @@ -1,8 +1,5 @@ -from ctypes import (c_bool, c_int) +from ctypes import c_bool, c_int from llvmlite.binding import ffi -from llvmlite.binding.initfini import llvm_version_info - -llvm_version_major = llvm_version_info[0] def create_new_module_pass_manager(): @@ -17,7 +14,7 @@ def create_pass_builder(tm, pto): return PassBuilder(tm, pto) -def create_pipeline_options(): +def create_pipeline_tuning_options(): return PipelineTuningOptions() @@ -26,13 +23,13 @@ class NewModulePassManager(ffi.ObjectRef): def __init__(self, ptr=None): if ptr is None: ptr = ffi.lib.LLVMPY_CreateNewModulePassManager() - ffi.ObjectRef.__init__(self, ptr) + super().__init__(ptr) def run(self, module, pb): ffi.lib.LLVMPY_RunNewModulePassManager(self, pb, module) def addVerifier(self): - ffi.lib.LLVMPY_AddVeriferPass(self) + ffi.lib.LLVMPY_AddVerifierPass(self) def add_aa_eval_pass(self): ffi.lib.LLVMPY_AddAAEvalPass_module(self) @@ -44,15 +41,14 @@ def add_loop_unroll_pass(self): ffi.lib.LLVMPY_AddLoopUnrollPass_module(self) def add_loop_rotate_pass(self): - ffi.lib.LLVMPY_LLVMAddLoopRotatePass_module(self) + ffi.lib.LLVMPY_AddLoopRotatePass_module(self) def add_instruction_combine_pass(self): - ffi.lib.LLVMPY_LLVMAddInstructionCombinePass_module(self) + ffi.lib.LLVMPY_AddInstructionCombinePass_module(self) def add_jump_threading_pass(self, threshold=-1): ffi.lib.LLVMPY_AddJumpThreadingPass_module(self, threshold) - # What will happen to the pointer to objects created with run() method def _dispose(self): ffi.lib.LLVMPY_DisposeNewModulePassManger(self) @@ -62,7 +58,7 @@ class NewFunctionPassManger(ffi.ObjectRef): def __init__(self, ptr=None): if ptr is None: ptr = ffi.lib.LLVMPY_CreateNewFunctionPassManager() - ffi.ObjectRef.__init__(self, ptr) + super().__init__(ptr) def add_aa_eval_pass(self): ffi.lib.LLVMPY_AddAAEvalPass_function(self) @@ -77,10 +73,10 @@ def add_loop_unroll_pass(self): ffi.lib.LLVMPY_AddLoopUnrollPass_function(self) def add_loop_rotate_pass(self): - ffi.lib.LLVMPY_LLVMAddLoopRotatePass_function(self) + ffi.lib.LLVMPY_AddLoopRotatePass_function(self) def add_instruction_combine_pass(self): - ffi.lib.LLVMPY_LLVMAddInstructionCombinePass_function(self) + ffi.lib.LLVMPY_AddInstructionCombinePass_function(self) def add_jump_threading_pass(self, threshold=-1): ffi.lib.LLVMPY_AddJumpThreadingPass_function(self, threshold) @@ -89,7 +85,6 @@ def _dispose(self): ffi.lib.LLVMPY_DisposeNewFunctionPassManger(self) -# Make this nested class of PassBuilder? class PipelineTuningOptions(ffi.ObjectRef): def __init__(self, ptr=None): @@ -97,7 +92,7 @@ def __init__(self, ptr=None): ptr = ffi.lib.LLVMPY_CreatePipelineTuningOptions() self._opt_level = 2 self._size_level = 0 - ffi.ObjectRef.__init__(self, ptr) + super().__init__(ptr) @property def loop_interleaving(self): @@ -172,25 +167,24 @@ class PassBuilder(ffi.ObjectRef): def __init__(self, tm, pto, ptr=None): if ptr is None: - self._pto = pto - self._tm = tm ptr = ffi.lib.LLVMPY_CreatePassBuilder(tm, pto) - ffi.ObjectRef.__init__(self, ptr) + self._pto = pto + self._tm = tm + super().__init__(ptr) - def getNewModulePassManager(self): + def getModulePassManager(self): return NewModulePassManager( ffi.lib.LLVMPY_buildPerModuleDefaultPipeline( self, self._pto.opt_level, self._pto.size_level) ) - def getNewFunctionPassManager(self): + def getFunctionPassManager(self): return NewFunctionPassManger( ffi.lib.LLVMPY_buildFunctionSimplificationPipeline( self, self._pto.opt_level, self._pto.size_level) ) def _dispose(self): - # Should I explicitly delete pointer to pto and tm? ffi.lib.LLVMPY_DisposePassBuilder(self) @@ -205,7 +199,7 @@ def _dispose(self): ffi.LLVMPassBuilderRef, ffi.LLVMModuleRef,] -ffi.lib.LLVMPY_AddVeriferPass.argtypes = [ffi.LLVMModulePassManagerRef,] +ffi.lib.LLVMPY_AddVerifierPass.argtypes = [ffi.LLVMModulePassManagerRef,] ffi.lib.LLVMPY_AddAAEvalPass_module.argtypes = [ffi.LLVMModulePassManagerRef,] ffi.lib.LLVMPY_AddSimplifyCFGPass_module.argtypes = [ ffi.LLVMModulePassManagerRef,] @@ -213,10 +207,10 @@ def _dispose(self): ffi.lib.LLVMPY_AddLoopUnrollPass_module.argtypes = [ ffi.LLVMModulePassManagerRef,] -ffi.lib.LLVMPY_LLVMAddLoopRotatePass_module.argtypes = [ +ffi.lib.LLVMPY_AddLoopRotatePass_module.argtypes = [ ffi.LLVMModulePassManagerRef,] -ffi.lib.LLVMPY_LLVMAddInstructionCombinePass_module.argtypes = [ +ffi.lib.LLVMPY_AddInstructionCombinePass_module.argtypes = [ ffi.LLVMModulePassManagerRef,] ffi.lib.LLVMPY_AddJumpThreadingPass_module.argtypes = [ @@ -244,10 +238,10 @@ def _dispose(self): ffi.lib.LLVMPY_AddLoopUnrollPass_function.argtypes = [ ffi.LLVMFunctionPassManagerRef,] -ffi.lib.LLVMPY_LLVMAddLoopRotatePass_function.argtypes = [ +ffi.lib.LLVMPY_AddLoopRotatePass_function.argtypes = [ ffi.LLVMFunctionPassManagerRef,] -ffi.lib.LLVMPY_LLVMAddInstructionCombinePass_function.argtypes = [ +ffi.lib.LLVMPY_AddInstructionCombinePass_function.argtypes = [ ffi.LLVMFunctionPassManagerRef,] ffi.lib.LLVMPY_AddJumpThreadingPass_function.argtypes = [ diff --git a/llvmlite/binding/passmanagers.py b/llvmlite/binding/passmanagers.py index af6152f63..d983ce9d5 100644 --- a/llvmlite/binding/passmanagers.py +++ b/llvmlite/binding/passmanagers.py @@ -638,7 +638,7 @@ def add_basic_alias_analysis_pass(self): def add_loop_rotate_pass(self): """http://llvm.org/docs/Passes.html#loop-rotate-rotate-loops.""" - ffi.lib.LLVMPY_LLVMAddLoopRotatePass(self) + ffi.lib.LLVMPY_AddLoopRotatePass(self) def add_target_library_info(self, triple): ffi.lib.LLVMPY_AddTargetLibraryInfoPass(self, _encode_string(triple)) diff --git a/llvmlite/tests/test_binding.py b/llvmlite/tests/test_binding.py index be0886da6..13a449ae1 100644 --- a/llvmlite/tests/test_binding.py +++ b/llvmlite/tests/test_binding.py @@ -2594,7 +2594,7 @@ def rel(): class NewPassManagerMixin(object): def pipeline_tuning_options(self): - return llvm.create_pipeline_options() + return llvm.create_pipeline_tuning_options() def pb(self, opt_level=0): tm = self.target_machine(jit=False) @@ -2621,13 +2621,13 @@ def test_close(self): def test_getMPM(self): pb = self.pb() - mpm = pb.getNewModulePassManager() + mpm = pb.getModulePassManager() mpm.run(self.module(), pb) pb.close() def test_getFPM(self): pb = self.pb() - fpm = pb.getNewFunctionPassManager() + fpm = pb.getFunctionPassManager() fpm.run(self.module().get_function("sum"), pb) pb.close() @@ -2644,7 +2644,7 @@ def test_run(self): pb = self.pb(3) mod = self.module() orig_asm = str(mod) - mpm = pb.getNewModulePassManager() + mpm = pb.getModulePassManager() mpm.run(mod, pb) optimized_asm = str(mod) self.assertIn("%.4", orig_asm) @@ -2685,7 +2685,7 @@ def test_run(self): mod = self.module() fun = mod.get_function("sum") orig_asm = str(fun) - fpm = pb.getNewFunctionPassManager() + fpm = pb.getFunctionPassManager() fpm.run(fun, pb) optimized_asm = str(fun) self.assertIn("%.4", orig_asm) From 9fa47bdb98766ffea477469b84da4f0aeed5f4db Mon Sep 17 00:00:00 2001 From: Yashwant Singh Date: Mon, 20 May 2024 12:38:12 +0530 Subject: [PATCH 16/27] Make opt_level and size_level public attributes of PTO set in __init__() --- examples/optimization-passes-npm.py | 3 +-- examples/optimization-pipeline-npm.py | 3 +-- ffi/passmanagers.cpp | 4 +--- llvmlite/binding/newpassmangers.py | 34 ++++----------------------- 4 files changed, 8 insertions(+), 36 deletions(-) diff --git a/examples/optimization-passes-npm.py b/examples/optimization-passes-npm.py index 9bb3a60f3..b193e2b4c 100644 --- a/examples/optimization-passes-npm.py +++ b/examples/optimization-passes-npm.py @@ -44,8 +44,7 @@ print(llmod) target_machine = llvm.Target.from_default_triple().create_target_machine() -pto = llvm.create_pipeline_tuning_options() -pto.opt_level = 0 +pto = llvm.create_pipeline_tuning_options(opt_level=0) pb = llvm.create_pass_builder(target_machine, pto) pm = llvm.create_new_module_pass_manager() diff --git a/examples/optimization-pipeline-npm.py b/examples/optimization-pipeline-npm.py index 513547f64..2963ab517 100644 --- a/examples/optimization-pipeline-npm.py +++ b/examples/optimization-pipeline-npm.py @@ -44,8 +44,7 @@ target_machine = llvm.Target.from_default_triple().create_target_machine() -pto = llvm.create_pipeline_tuning_options() -pto.opt_level = 3 +pto = llvm.create_pipeline_tuning_options(opt_level=3) pb = llvm.create_pass_builder(target_machine, pto) pm = pb.getModulePassManager() pm.run(llmod, pb) diff --git a/ffi/passmanagers.cpp b/ffi/passmanagers.cpp index 915a684be..d3fd11ccf 100644 --- a/ffi/passmanagers.cpp +++ b/ffi/passmanagers.cpp @@ -475,9 +475,7 @@ LLVMPY_AddBasicAliasAnalysisPass(LLVMPassManagerRef PM) { } API_EXPORT(void) -LLVMPY_AddLoopRotatePass(LLVMPassManagerRef PM) { - LLVMAddLoopRotatePass(PM); -} +LLVMPY_AddLoopRotatePass(LLVMPassManagerRef PM) { LLVMAddLoopRotatePass(PM); } API_EXPORT(void) LLVMPY_AddInstructionNamerPass(LLVMPassManagerRef PM) { diff --git a/llvmlite/binding/newpassmangers.py b/llvmlite/binding/newpassmangers.py index 251f1fd39..3bbe01c38 100644 --- a/llvmlite/binding/newpassmangers.py +++ b/llvmlite/binding/newpassmangers.py @@ -14,8 +14,8 @@ def create_pass_builder(tm, pto): return PassBuilder(tm, pto) -def create_pipeline_tuning_options(): - return PipelineTuningOptions() +def create_pipeline_tuning_options(opt_level=2, size_level=0): + return PipelineTuningOptions(opt_level=opt_level, size_level=size_level) class NewModulePassManager(ffi.ObjectRef): @@ -87,11 +87,11 @@ def _dispose(self): class PipelineTuningOptions(ffi.ObjectRef): - def __init__(self, ptr=None): + def __init__(self, ptr=None, opt_level=2, size_level=0): if ptr is None: ptr = ffi.lib.LLVMPY_CreatePipelineTuningOptions() - self._opt_level = 2 - self._size_level = 0 + self.opt_level = opt_level + self.size_level = size_level super().__init__(ptr) @property @@ -135,30 +135,6 @@ def loop_unrolling(self, value): # def inlining_threshold(self, value): # ffi.lib.LLVMPY_PTOSetInlinerThreshold(self, value) - # Not part of PTO - @property - def opt_level(self): - """ - The general optimization level as an integer between 0 and 3. - """ - return self._opt_level - - @opt_level.setter - def opt_level(self, level): - self._opt_level = level - - @property - def size_level(self): - """ - Whether and how much to optimize for size. - An integer between 0 and 2. - """ - return self._size_level - - @size_level.setter - def size_level(self, size): - self._size_level = size - def _dispose(self): ffi.lib.LLVMPY_DisposePipelineTuningOptions(self) From 687a2b899ca58a6bfd7b9beb07790104f745e101 Mon Sep 17 00:00:00 2001 From: Yashwant Singh Date: Tue, 21 May 2024 09:59:08 +0530 Subject: [PATCH 17/27] Remove 'New' from class names, remove ptr initialization of classes wherever possible --- .../binding/optimization-passes.rst | 8 +++---- llvmlite/binding/newpassmangers.py | 24 ++++++++----------- 2 files changed, 14 insertions(+), 18 deletions(-) diff --git a/docs/source/user-guide/binding/optimization-passes.rst b/docs/source/user-guide/binding/optimization-passes.rst index 2d189e5a1..b4be86a23 100644 --- a/docs/source/user-guide/binding/optimization-passes.rst +++ b/docs/source/user-guide/binding/optimization-passes.rst @@ -86,7 +86,7 @@ respective `function` and `module` pass managers. Return a populated `FunctionPassManager` object based on PTO settings. -.. class:: NewModulePassManager() +.. class:: ModulePassManager() Create a new pass manager to run optimization passes on a llvm module. @@ -98,9 +98,9 @@ respective `function` and `module` pass managers. Use individual ``add_*`` methods to add optimization passes or use :meth:`PassBuilder.getModulePassManager` to get - optimization passes populated `NewModulePassManager` object. + optimization passes populated `ModulePassManager` object. -.. class:: NewFunctionPassManager() +.. class:: FunctionPassManager() Create a new pass manager to run optimization passes on a llvm function. @@ -112,7 +112,7 @@ respective `function` and `module` pass managers. Use individual ``add_*`` methods to add optimization passes or use :meth:`PassBuilder.getFunctionPassManager` to get - optimization passes populated `NewFunctionPassManager` object. + optimization passes populated `FunctionPassManager` object. Legacy Pass Manager diff --git a/llvmlite/binding/newpassmangers.py b/llvmlite/binding/newpassmangers.py index 3bbe01c38..7f8d5882b 100644 --- a/llvmlite/binding/newpassmangers.py +++ b/llvmlite/binding/newpassmangers.py @@ -3,11 +3,11 @@ def create_new_module_pass_manager(): - return NewModulePassManager() + return ModulePassManager() def create_new_function_pass_manager(): - return NewFunctionPassManger() + return FunctionPassManager() def create_pass_builder(tm, pto): @@ -18,7 +18,7 @@ def create_pipeline_tuning_options(opt_level=2, size_level=0): return PipelineTuningOptions(opt_level=opt_level, size_level=size_level) -class NewModulePassManager(ffi.ObjectRef): +class ModulePassManager(ffi.ObjectRef): def __init__(self, ptr=None): if ptr is None: @@ -53,7 +53,7 @@ def _dispose(self): ffi.lib.LLVMPY_DisposeNewModulePassManger(self) -class NewFunctionPassManger(ffi.ObjectRef): +class FunctionPassManager(ffi.ObjectRef): def __init__(self, ptr=None): if ptr is None: @@ -87,12 +87,10 @@ def _dispose(self): class PipelineTuningOptions(ffi.ObjectRef): - def __init__(self, ptr=None, opt_level=2, size_level=0): - if ptr is None: - ptr = ffi.lib.LLVMPY_CreatePipelineTuningOptions() + def __init__(self, opt_level=2, size_level=0): + super().__init__(ffi.lib.LLVMPY_CreatePipelineTuningOptions()) self.opt_level = opt_level self.size_level = size_level - super().__init__(ptr) @property def loop_interleaving(self): @@ -141,21 +139,19 @@ def _dispose(self): class PassBuilder(ffi.ObjectRef): - def __init__(self, tm, pto, ptr=None): - if ptr is None: - ptr = ffi.lib.LLVMPY_CreatePassBuilder(tm, pto) + def __init__(self, tm, pto): + super().__init__(ffi.lib.LLVMPY_CreatePassBuilder(tm, pto)) self._pto = pto self._tm = tm - super().__init__(ptr) def getModulePassManager(self): - return NewModulePassManager( + return ModulePassManager( ffi.lib.LLVMPY_buildPerModuleDefaultPipeline( self, self._pto.opt_level, self._pto.size_level) ) def getFunctionPassManager(self): - return NewFunctionPassManger( + return FunctionPassManager( ffi.lib.LLVMPY_buildFunctionSimplificationPipeline( self, self._pto.opt_level, self._pto.size_level) ) From af7a79c011996c5ddc59b34a21a29ad950df05d2 Mon Sep 17 00:00:00 2001 From: Yashwant Singh Date: Thu, 23 May 2024 10:16:40 +0530 Subject: [PATCH 18/27] Add opt_level asserts Add constraints check in opt_level and size_level setters, similar to how llvm's OptimizationLevel's constructor does it. --- ffi/newpassmanagers.cpp | 2 ++ llvmlite/binding/newpassmangers.py | 30 ++++++++++++++++++++++++++++-- llvmlite/tests/test_binding.py | 28 ++++++++++++++++++++-------- 3 files changed, 50 insertions(+), 10 deletions(-) diff --git a/ffi/newpassmanagers.cpp b/ffi/newpassmanagers.cpp index 0f066e041..b72b28855 100644 --- a/ffi/newpassmanagers.cpp +++ b/ffi/newpassmanagers.cpp @@ -291,6 +291,8 @@ LLVMPY_buildPerModuleDefaultPipeline(LLVMPassBuilderRef PBref, int speed_level, PassBuilder *PB = llvm::unwrap(PBref); OptimizationLevel OL = mapLevel(speed_level, size_level); + + // FXIME: No need to explicitly take care of O0 from LLVM 17 if (OL == OptimizationLevel::O0) { return llvm::wrap( new ModulePassManager(PB->buildO0DefaultPipeline(OL))); diff --git a/llvmlite/binding/newpassmangers.py b/llvmlite/binding/newpassmangers.py index 7f8d5882b..835128924 100644 --- a/llvmlite/binding/newpassmangers.py +++ b/llvmlite/binding/newpassmangers.py @@ -15,7 +15,7 @@ def create_pass_builder(tm, pto): def create_pipeline_tuning_options(opt_level=2, size_level=0): - return PipelineTuningOptions(opt_level=opt_level, size_level=size_level) + return PipelineTuningOptions(opt_level, size_level) class ModulePassManager(ffi.ObjectRef): @@ -88,9 +88,35 @@ def _dispose(self): class PipelineTuningOptions(ffi.ObjectRef): def __init__(self, opt_level=2, size_level=0): - super().__init__(ffi.lib.LLVMPY_CreatePipelineTuningOptions()) + self._opt_level = None + self._size_level = None self.opt_level = opt_level self.size_level = size_level + super().__init__(ffi.lib.LLVMPY_CreatePipelineTuningOptions()) + + @property + def opt_level(self): + return self._opt_level + + @opt_level.setter + def opt_level(self, value): + if not 0 <= value <= 3: + raise ValueError( + "Optimization level for speed should be 0, 1, 2, or 3") + self._opt_level = value + + @property + def size_level(self): + return self._size_level + + @size_level.setter + def size_level(self, value): + if not 0 <= value <= 2: + raise ValueError("Optimization level for size should be 0, 1, or 2") + if value != 0 and self.opt_level != 2: + raise ValueError( + "Optimize for size should be encoded with speedup level == 2") + self._size_level = value @property def loop_interleaving(self): diff --git a/llvmlite/tests/test_binding.py b/llvmlite/tests/test_binding.py index 13a449ae1..206e63998 100644 --- a/llvmlite/tests/test_binding.py +++ b/llvmlite/tests/test_binding.py @@ -2593,13 +2593,9 @@ def rel(): class NewPassManagerMixin(object): - def pipeline_tuning_options(self): - return llvm.create_pipeline_tuning_options() - - def pb(self, opt_level=0): + def pb(self, opt_level=0, size_level=0): tm = self.target_machine(jit=False) - pto = self.pipeline_tuning_options() - pto.opt_level = opt_level + pto = llvm.create_pipeline_tuning_options(opt_level, size_level) pb = llvm.create_pass_builder(tm, pto) return pb @@ -2608,12 +2604,28 @@ class TestPassBuilder(BaseTest, NewPassManagerMixin): def test_pto(self): tm = self.target_machine(jit=False) - pto = self.pipeline_tuning_options() - pto.opt_level = 3 + pto = llvm.create_pipeline_tuning_options(3, 0) pto.inlining_threshold = 2 pb = llvm.create_pass_builder(tm, pto) pb.close() + def test_opt_level_constraints(self): + pto = llvm.create_pipeline_tuning_options() + with self.assertRaises(ValueError): + pto.opt_level = 4 + with self.assertRaises(ValueError): + pto.opt_level = -1 + + def test_size_level_constraints(self): + pto = llvm.create_pipeline_tuning_options() + with self.assertRaises(ValueError): + pto.size_level = 3 + with self.assertRaises(ValueError): + pto.opt_level = -1 + with self.assertRaises(ValueError): + pto.opt_level = 3 + pto.size_level = 2 + def test_close(self): pb = self.pb() pb.close() From e33bdca17e609f90e0109117ba625d54583e5d78 Mon Sep 17 00:00:00 2001 From: Yashwant Singh Date: Tue, 28 May 2024 11:45:19 +0530 Subject: [PATCH 19/27] Add pto tests --- llvmlite/tests/test_binding.py | 94 ++++++++++++++++++++++++++++------ 1 file changed, 79 insertions(+), 15 deletions(-) diff --git a/llvmlite/tests/test_binding.py b/llvmlite/tests/test_binding.py index 206e63998..8d62ebd01 100644 --- a/llvmlite/tests/test_binding.py +++ b/llvmlite/tests/test_binding.py @@ -2591,33 +2591,74 @@ def rel(): llvm.ffi.unregister_lock_callback(acq, rel) -class NewPassManagerMixin(object): +class TestPipelineTuningOptions(BaseTest): - def pb(self, opt_level=0, size_level=0): - tm = self.target_machine(jit=False) - pto = llvm.create_pipeline_tuning_options(opt_level, size_level) - pb = llvm.create_pass_builder(tm, pto) - return pb - - -class TestPassBuilder(BaseTest, NewPassManagerMixin): + def pto(self): + return llvm.PipelineTuningOptions() def test_pto(self): - tm = self.target_machine(jit=False) pto = llvm.create_pipeline_tuning_options(3, 0) - pto.inlining_threshold = 2 - pb = llvm.create_pass_builder(tm, pto) - pb.close() + pto.close() + + def test_opt_level(self): + pto = self.pto() + self.assertIsInstance(pto.opt_level, int) + for i in range(4): + pto.opt_level = i + self.assertEqual(pto.opt_level, i) + + def test_size_level(self): + pto = self.pto() + self.assertIsInstance(pto.size_level, int) + for i in range(3): + pto.size_level = i + self.assertEqual(pto.size_level, i) + + # // FIXME: Available from llvm16 + # def test_inlining_threshold(self): + # pto = self.pto() + # with self.assertRaises(NotImplementedError): + # pto.inlining_threshold + # for i in (25, 80, 350): + # pto.inlining_threshold = i + + def test_loop_interleaving(self): + pto = self.pto() + self.assertIsInstance(pto.loop_interleaving, bool) + for b in (True, False): + pto.loop_interleaving = b + self.assertEqual(pto.loop_interleaving, b) + + def test_loop_vectorization(self): + pto = self.pto() + self.assertIsInstance(pto.loop_vectorization, bool) + for b in (True, False): + pto.loop_vectorization = b + self.assertEqual(pto.loop_vectorization, b) + + def test_slp_vectorization(self): + pto = self.pto() + self.assertIsInstance(pto.slp_vectorization, bool) + for b in (True, False): + pto.slp_vectorization = b + self.assertEqual(pto.slp_vectorization, b) + + def test_loop_unrolling(self): + pto = self.pto() + self.assertIsInstance(pto.loop_unrolling, bool) + for b in (True, False): + pto.loop_unrolling = b + self.assertEqual(pto.loop_unrolling, b) def test_opt_level_constraints(self): - pto = llvm.create_pipeline_tuning_options() + pto = self.pto() with self.assertRaises(ValueError): pto.opt_level = 4 with self.assertRaises(ValueError): pto.opt_level = -1 def test_size_level_constraints(self): - pto = llvm.create_pipeline_tuning_options() + pto = self.pto() with self.assertRaises(ValueError): pto.size_level = 3 with self.assertRaises(ValueError): @@ -2626,6 +2667,29 @@ def test_size_level_constraints(self): pto.opt_level = 3 pto.size_level = 2 + +class NewPassManagerMixin(object): + + def pb(self, opt_level=0, size_level=0): + tm = self.target_machine(jit=False) + pto = llvm.create_pipeline_tuning_options(opt_level, size_level) + pb = llvm.create_pass_builder(tm, pto) + return pb + + +class TestPassBuilder(BaseTest, NewPassManagerMixin): + + def test_pto(self): + tm = self.target_machine(jit=False) + pto = llvm.create_pipeline_tuning_options(3, 0) + pto.inlining_threshold = 2 + pto.loop_interleaving = True + pto.loop_vectorization = True + pto.slp_vectorization = True + pto.loop_unrolling = False + pb = llvm.create_pass_builder(tm, pto) + pb.close() + def test_close(self): pb = self.pb() pb.close() From 1babc4e3ae4e7c5f1d73e4c836ec614692adb43c Mon Sep 17 00:00:00 2001 From: Graham Markall Date: Thu, 23 May 2024 13:23:43 +0100 Subject: [PATCH 20/27] Update NPM docs --- .../binding/optimization-passes.rst | 213 +++++++++++------- 1 file changed, 129 insertions(+), 84 deletions(-) diff --git a/docs/source/user-guide/binding/optimization-passes.rst b/docs/source/user-guide/binding/optimization-passes.rst index b4be86a23..6d6e54271 100644 --- a/docs/source/user-guide/binding/optimization-passes.rst +++ b/docs/source/user-guide/binding/optimization-passes.rst @@ -4,9 +4,8 @@ Optimization passes .. currentmodule:: llvmlite.binding -LLVM gives you the opportunity to fine-tune optimization passes. -Optimization passes are managed by a pass manager. There are 2 -kinds of pass managers: +LLVM gives you the opportunity to fine-tune optimization passes. Optimization +passes are managed by a pass manager. There are two kinds of pass managers: * :class:`FunctionPassManager`, for optimizations that work on single functions. @@ -14,106 +13,148 @@ kinds of pass managers: * :class:`ModulePassManager`, for optimizations that work on whole modules. -For optimization pipeline LLVM supports 2 different pass managing mechanisms. -The old one is now renamed to LegacyPassManager and is deprecated. From `llvm17` -LegacyPassManager's support is no longer reliable with many passes not working -with it. +llvmlite provides bindings for LLVM's *New* and *Legacy* pass managers, which +have slightly different APIs and behaviour. The differences between them and the +motivations for the New Pass Manager are outlined in the `LLVM Blog post on the +New Pass Manager +`_. -`llvmlite` right now supports both the `LegacyPassManager` and the `NewPassManager`, -but consider `LegacyPassManager` deprecated and you are advised to shift your -code to `NewPassManager` APIs. +In a future version of llvmlite, likely coinciding with a minimum LLVM version +requirement of 17, support for the Legacy Pass Manager will be removed. It is +recommended that new code using llvmlite uses the New Pass Manager, and existing +code using the Legacy Pass Manager be updated to use the New Pass Manager. -New Pass Manager -=================== -To manage the optimization attributes we first need to instantiate -.. class:: PipelineTuningOptions() +New Pass Manager APIs +===================== + +To manage the optimization attributes we first need to instantiate a +:class:`PipelineTuningOptions` instance: + +.. class:: PipelineTuningOptions(speed_level=2, size_level=0) - Creates a new PipelineTuningOptions object + Creates a new PipelineTuningOptions object. - The following writable attributes are available: + The following writable attributes are available, whose default values depend + on the initial setting of the speed and size optimization levels: - * .. attribute:: loop_interleaving + * .. attribute:: loop_interleaving - If ``False``, disable loop interleaving. + Enable loop interleaving. - * .. attribute:: loop_vectorization + * .. attribute:: loop_vectorization - If ``True``, allow vectorizing loops. + Enable loop vectorization. - * .. attribute:: slp_vectorize + * .. attribute:: slp_vectorization - If ``True``, enable the SLP vectorizer, which uses a - different algorithm than the loop vectorizer. Both may - be enabled at the same time. + Enable SLP vectorization, which uses a different algorithm to + loop vectorization. Both may be enabled at the same time. - * .. attribute:: loop_unrolling + * .. attribute:: loop_unrolling - If ``False``, disable loop unrolling. + Enable loop unrolling. -.. FIXME: Available from llvm16 -.. * .. attribute:: inlining_threshold + * .. attribute:: speed_level -.. The integer threshold for inlining one function into -.. another. The higher the number, the more likely that -.. inlining will occur. This attribute is write-only. + The level of optimization for speed, as an integer between 0 and 3. - * .. attribute:: opt_level + * .. attribute:: size_level - The general optimization level, as an integer between 0 - and 3. + The level of optimization for size, as an integer between 0 and 2. - * .. attribute:: size_level +.. FIXME: Available from llvm16 +.. * .. attribute:: inlining_threshold - Whether and how much to optimize for size, as an integer - between 0 and 2. +.. The integer threshold for inlining one function into +.. another. The higher the number, the more likely that +.. inlining will occur. This attribute is write-only. -Similar to `LegacyPassManager` we need a `PassBuilder` object to manage the -respective `function` and `module` pass managers. +We also need a :class:`PassBuilder` object to manage the respective function +and module pass managers: .. class:: PassBuilder(target_machine, pipeline_tuning_options) - Create a new pass builder. This takes :class:`TargetMachine` and - :class:`PipelineTuningOptions` objects as parameters. + A pass builder that uses the given :class:`TargetMachine` and + :class:`PipelineTuningOptions` instances. - .. method:: getModulePassManager() + .. method:: getModulePassManager() - Return a populated `ModulePassManager` object based on PTO settings. + Return a populated :class:`ModulePassManager` object based on PTO settings. - .. method:: getFunctionPassManager() + .. method:: getFunctionPassManager() - Return a populated `FunctionPassManager` object based on PTO settings. + Return a populated :class:`FunctionPassManager` object based on PTO + settings. +The :class:`ModulePassManager` and :class:`FunctionPassManager` classes +implement the module and function pass managers. These can be created with +passes populated by using the :meth:`PassBuilder.getModulePassManager` and +:meth:`PassBuilder.getFunctionPassManager` methods, or they can be instantiated +directly, then passes can be added using the ``add_*`` methods. + .. class:: ModulePassManager() - Create a new pass manager to run optimization passes on a - llvm module. + A pass manager for running optimization passes on an LLVM module. - .. method:: run(module, passbuilder) + .. method:: add_verifier() + + Add the `Module Verifier + `_ pass. + + .. method:: run(module, passbuilder) - Run optimization passes on the - *module*, a :class:`ModuleRef` instance. + Run optimization passes on *module*, a :class:`ModuleRef` instance. - Use individual ``add_*`` methods to add optimization passes - or use :meth:`PassBuilder.getModulePassManager` to get - optimization passes populated `ModulePassManager` object. .. class:: FunctionPassManager() - Create a new pass manager to run optimization passes on a - llvm function. + A pass manager for running optimization passes on an LLVM function. + + .. method:: run(function, passbuilder) + + Run optimization passes on *function*, a :class:`ValueRef` instance. - .. method:: run(function, passbuilder) - - Run optimization passes on the - *function*, a :class:`ValueRef` instance. - Use individual ``add_*`` methods to add optimization passes - or use :meth:`PassBuilder.getFunctionPassManager` to get - optimization passes populated `FunctionPassManager` object. +The ``add_*`` methods supported by both pass manager classes are: +.. currentmodule:: None + +.. method:: add_aa_eval_pass() + + Add the `Exhaustive Alias Analysis Precision Evaluator + `_ + pass. + +.. method:: add_loop_unroll_pass() + + Add the `Loop Unroll + `_ pass. + +.. method:: add_loop_rotate_pass() + + Add the `Loop Rotate + `_ pass. + +.. method:: add_instruction_combine_pass() + + Add the `Combine Redundant Instructions + `_ + pass. + +.. method:: add_jump_threading_pass() + + Add the `Jump Threading + `_ pass. + +.. method:: add_simplify_cfg_pass() + + Add the `Simplify CFG + `_ pass. + +.. currentmodule:: llvmlite.binding Legacy Pass Manager =================== @@ -128,42 +169,42 @@ create and configure a :class:`PassManagerBuilder`. The ``populate`` method is available: - .. method:: populate(pm) + .. method:: populate(pm) - Populate the pass manager *pm* with the optimization passes - configured in this pass manager builder. + Populate the pass manager *pm* with the optimization passes + configured in this pass manager builder. - The following writable attributes are available: + The following writable attributes are available: - * .. attribute:: disable_unroll_loops + * .. attribute:: disable_unroll_loops - If ``True``, disable loop unrolling. + If ``True``, disable loop unrolling. - * .. attribute:: inlining_threshold + * .. attribute:: inlining_threshold - The integer threshold for inlining one function into - another. The higher the number, the more likely that - inlining will occur. This attribute is write-only. + The integer threshold for inlining one function into + another. The higher the number, the more likely that + inlining will occur. This attribute is write-only. - * .. attribute:: loop_vectorize + * .. attribute:: loop_vectorize - If ``True``, allow vectorizing loops. + If ``True``, allow vectorizing loops. - * .. attribute:: opt_level + * .. attribute:: opt_level - The general optimization level, as an integer between 0 - and 3. + The general optimization level, as an integer between 0 + and 3. - * .. attribute:: size_level + * .. attribute:: size_level - Whether and how much to optimize for size, as an integer - between 0 and 2. + Whether and how much to optimize for size, as an integer + between 0 and 2. - * .. attribute:: slp_vectorize + * .. attribute:: slp_vectorize - If ``True``, enable the SLP vectorizer, which uses a - different algorithm than the loop vectorizer. Both may - be enabled at the same time. + If ``True``, enable the SLP vectorizer, which uses a + different algorithm than the loop vectorizer. Both may + be enabled at the same time. .. class:: PassManager @@ -246,6 +287,7 @@ create and configure a :class:`PassManagerBuilder`. See `instnamer pass documentation `_. .. class:: ModulePassManager() + :no-index: Create a new pass manager to run optimization passes on a module. @@ -253,6 +295,7 @@ create and configure a :class:`PassManagerBuilder`. The ``run`` method is available: .. method:: run(module) + :no-index: Run optimization passes on the *module*, a :class:`ModuleRef` instance. @@ -261,6 +304,7 @@ create and configure a :class:`PassManagerBuilder`. to the module. Otherwise returns ``False``. .. class:: FunctionPassManager(module) + :no-index: Create a new pass manager to run optimization passes on a function of the given *module*, a :class:`ModuleRef` instance. @@ -276,6 +320,7 @@ create and configure a :class:`PassManagerBuilder`. Run all the initializers of the optimization passes. * .. method:: run(function) + :no-index: Run optimization passes on *function*, a :class:`ValueRef` instance. From 1b36ab19cc31e1e49ce42a4ce7f12e42e464b134 Mon Sep 17 00:00:00 2001 From: Graham Markall Date: Thu, 30 May 2024 16:43:19 +0100 Subject: [PATCH 21/27] Add notes on how to correctly create new pass manager instances --- .../binding/optimization-passes.rst | 27 ++++++++++++++----- 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/docs/source/user-guide/binding/optimization-passes.rst b/docs/source/user-guide/binding/optimization-passes.rst index 6d6e54271..4dd129e9a 100644 --- a/docs/source/user-guide/binding/optimization-passes.rst +++ b/docs/source/user-guide/binding/optimization-passes.rst @@ -90,10 +90,7 @@ and module pass managers: The :class:`ModulePassManager` and :class:`FunctionPassManager` classes -implement the module and function pass managers. These can be created with -passes populated by using the :meth:`PassBuilder.getModulePassManager` and -:meth:`PassBuilder.getFunctionPassManager` methods, or they can be instantiated -directly, then passes can be added using the ``add_*`` methods. +implement the module and function pass managers: .. class:: ModulePassManager() @@ -118,6 +115,24 @@ directly, then passes can be added using the ``add_*`` methods. Run optimization passes on *function*, a :class:`ValueRef` instance. +These can be created with passes populated by using the +:meth:`PassBuilder.getModulePassManager` and +:meth:`PassBuilder.getFunctionPassManager` methods, or they can be instantiated +unpopulated, then passes can be added using the ``add_*`` methods. + +To instantiate the unpopulated instances, use: + +.. function:: create_new_module_pass_manager() + + Create an unpopulated :class:`ModulePassManager` instance. + +and + +.. function:: create_new_function_pass_manager() + + Create an unpopulated :class:`FunctionPassManager` instance. + + The ``add_*`` methods supported by both pass manager classes are: .. currentmodule:: None @@ -156,8 +171,8 @@ The ``add_*`` methods supported by both pass manager classes are: .. currentmodule:: llvmlite.binding -Legacy Pass Manager -=================== +Legacy Pass Manager APIs +======================== To instantiate either of these pass managers, you first need to create and configure a :class:`PassManagerBuilder`. From a90a3ac1ed1175af438faf3da61f410e8405d07e Mon Sep 17 00:00:00 2001 From: Graham Markall Date: Thu, 30 May 2024 17:16:40 +0100 Subject: [PATCH 22/27] Tidy up the examples --- docs/source/user-guide/examples/sum.py | 1 + ...timization-passes-npm.py => npm_passes.py} | 44 +++++++--- examples/npm_pipeline.py | 87 +++++++++++++++++++ examples/optimization-pipeline-npm.py | 72 --------------- 4 files changed, 119 insertions(+), 85 deletions(-) rename examples/{optimization-passes-npm.py => npm_passes.py} (53%) create mode 100644 examples/npm_pipeline.py delete mode 100644 examples/optimization-pipeline-npm.py diff --git a/docs/source/user-guide/examples/sum.py b/docs/source/user-guide/examples/sum.py index 6134918b4..4f7ddb66f 100644 --- a/docs/source/user-guide/examples/sum.py +++ b/docs/source/user-guide/examples/sum.py @@ -108,3 +108,4 @@ res = cfunc(A.ctypes.data_as(POINTER(c_int)), A.size) print(res, A.sum()) + diff --git a/examples/optimization-passes-npm.py b/examples/npm_passes.py similarity index 53% rename from examples/optimization-passes-npm.py rename to examples/npm_passes.py index b193e2b4c..df8a42093 100644 --- a/examples/optimization-passes-npm.py +++ b/examples/npm_passes.py @@ -1,16 +1,20 @@ -try: - import faulthandler; faulthandler.enable() -except ImportError: - pass +""" +This example demonstrates how to use the new module pass manager to optimize a +module using the loop unrolling and CFG simplification passes. +""" -import llvmlite.ir as ll +import faulthandler import llvmlite.binding as llvm +# Dump Python traceback in the event of a segfault +faulthandler.enable() +# All are required to initialize LLVM llvm.initialize() llvm.initialize_native_target() llvm.initialize_native_asmprinter() +# Module to optimize strmod = """ define i32 @foo3(i32* noalias nocapture readonly %src) { entry: @@ -38,18 +42,32 @@ } """ -# Run loop-unroll + simplifycfg on module -llmod = llvm.parse_assembly(strmod) -print(llmod) +module = llvm.parse_assembly(strmod) -target_machine = llvm.Target.from_default_triple().create_target_machine() -pto = llvm.create_pipeline_tuning_options(opt_level=0) -pb = llvm.create_pass_builder(target_machine, pto) +print("Module before optimization:\n") +print(module) +# Set up the module pass manager used to run our optimization pipeline. +# We create it unpopulated, and then add the loop unroll and simplify CFG +# passes. pm = llvm.create_new_module_pass_manager() pm.add_loop_unroll_pass() pm.add_simplify_cfg_pass() -pm.run(llmod, pb) -print(llmod) + +# To run the pass manager, we need a pass builder object - we create pipeline +# tuning options with no optimization, then use that to create a pass builder. +target_machine = llvm.Target.from_default_triple().create_target_machine() +pto = llvm.create_pipeline_tuning_options(opt_level=0) +pb = llvm.create_pass_builder(target_machine, pto) + +# Now we can run the pass manager on our module +pm.run(module, pb) + + +# We should observer a fully unrolled loop, and the function now consists of a +# single basic block executing all the iterations of the loop in a straight +# line. +print("\nModule after optimization:\n") +print(module) diff --git a/examples/npm_pipeline.py b/examples/npm_pipeline.py new file mode 100644 index 000000000..a884d2142 --- /dev/null +++ b/examples/npm_pipeline.py @@ -0,0 +1,87 @@ +""" +This example demonstrates how to optimize a module with a module pass manager +pre-populated with passes according to a given optimization level. + +The optimized module is executed using the MCJIT bindings. +""" + +from ctypes import CFUNCTYPE, c_int, POINTER +import faulthandler +import llvmlite.binding as llvm + +import numpy as np + +# Dump Python traceback in the event of a segfault +faulthandler.enable() + +# All are required to initialize LLVM +llvm.initialize() +llvm.initialize_native_target() +llvm.initialize_native_asmprinter() + +# Module to optimize and execute +strmod = """ +; ModuleID = '' +source_filename = "" +target triple = "unknown-unknown-unknown" + +define i32 @sum(i32* %.1, i32 %.2) { +.4: + br label %.5 + +.5: ; preds = %.5, %.4 + %.8 = phi i32 [ 0, %.4 ], [ %.13, %.5 ] + %.9 = phi i32 [ 0, %.4 ], [ %.12, %.5 ] + %.10 = getelementptr i32, i32* %.1, i32 %.8 + %.11 = load i32, i32* %.10, align 4 + %.12 = add i32 %.9, %.11 + %.13 = add i32 %.8, 1 + %.14 = icmp ult i32 %.13, %.2 + br i1 %.14, label %.5, label %.6 + +.6: ; preds = %.5 + ret i32 %.12 +} +""" + + +module = llvm.parse_assembly(strmod) + +print("Module before optimization:\n") +print(module) + +# Create a ModulePassManager for speed optimization level 3 +target_machine = llvm.Target.from_default_triple().create_target_machine() +pto = llvm.create_pipeline_tuning_options(opt_level=3) +pb = llvm.create_pass_builder(target_machine, pto) +pm = pb.getModulePassManager() + +# Run the optimization pipeline on the module +pm.run(module, pb) + +# O3 optimization will likely have vectorized the loop. The resulting code will +# be more complex, but more performant. +print("\nModule after optimization:\n") +print(module) + +with llvm.create_mcjit_compiler(module, target_machine) as ee: + # Generate code and get a pointer to it for calling + ee.finalize_object() + cfptr = ee.get_function_address("sum") + + # We should also observe vector instructions in the generated assembly + print("\nAssembly code generated from module\n") + print(target_machine.emit_assembly(module)) + + # Create an array of integers and call our optimized sum function with them + cfunc = CFUNCTYPE(c_int, POINTER(c_int), c_int)(cfptr) + A = np.arange(10, dtype=np.int32) + res = cfunc(A.ctypes.data_as(POINTER(c_int)), A.size) + + # Print results, which should be identical + print(f"Result of executing the optimized function: {res}") + print(f"Expected result: {A.sum()}") + + # Sanity check + np.testing.assert_equal(res, A.sum()) + print("Success!") diff --git a/examples/optimization-pipeline-npm.py b/examples/optimization-pipeline-npm.py deleted file mode 100644 index 2963ab517..000000000 --- a/examples/optimization-pipeline-npm.py +++ /dev/null @@ -1,72 +0,0 @@ -try: - import faulthandler; faulthandler.enable() -except ImportError: - pass - -from ctypes import CFUNCTYPE, c_int, POINTER -import llvmlite.ir as ll -import llvmlite.binding as llvm - -import numpy as np - -llvm.initialize() -llvm.initialize_native_target() -llvm.initialize_native_asmprinter() - -strmod = """ -; ModuleID = '' -source_filename = "" -target triple = "unknown-unknown-unknown" - -define i32 @sum(i32* %.1, i32 %.2) { -.4: - br label %.5 - -.5: ; preds = %.5, %.4 - %.8 = phi i32 [ 0, %.4 ], [ %.13, %.5 ] - %.9 = phi i32 [ 0, %.4 ], [ %.12, %.5 ] - %.10 = getelementptr i32, i32* %.1, i32 %.8 - %.11 = load i32, i32* %.10, align 4 - %.12 = add i32 %.9, %.11 - %.13 = add i32 %.8, 1 - %.14 = icmp ult i32 %.13, %.2 - br i1 %.14, label %.5, label %.6 - -.6: ; preds = %.5 - ret i32 %.12 -} -""" - -# Run -O3 optimization pipeline on the module - -llmod = llvm.parse_assembly(strmod) -print(llmod) - -target_machine = llvm.Target.from_default_triple().create_target_machine() - -pto = llvm.create_pipeline_tuning_options(opt_level=3) -pb = llvm.create_pass_builder(target_machine, pto) -pm = pb.getModulePassManager() -pm.run(llmod, pb) - -# pmb = llvm.create_pass_manager_builder() -# pmb.opt_level = 2 -# pm = llvm.create_module_pass_manager() -# pmb.populate(pm) -# pm.run(llmod) - -print(llmod) - -with llvm.create_mcjit_compiler(llmod, target_machine) as ee: - ee.finalize_object() - cfptr = ee.get_function_address("sum") - - print("-- JIT compile:") - - print(target_machine.emit_assembly(llmod)) - - cfunc = CFUNCTYPE(c_int, POINTER(c_int), c_int)(cfptr) - A = np.arange(10, dtype=np.int32) - res = cfunc(A.ctypes.data_as(POINTER(c_int)), A.size) - - print(res, A.sum()) From a5b5467221973d5c20e03f0e43674861d58a4070 Mon Sep 17 00:00:00 2001 From: Yashwant Singh Date: Fri, 31 May 2024 11:22:06 +0530 Subject: [PATCH 23/27] Rename opt_level to speed_level and typos --- examples/npm_passes.py | 2 +- examples/npm_pipeline.py | 2 +- llvmlite/binding/newpassmangers.py | 28 ++++++++++++++-------------- llvmlite/tests/test_binding.py | 24 ++++++++++++------------ 4 files changed, 28 insertions(+), 28 deletions(-) diff --git a/examples/npm_passes.py b/examples/npm_passes.py index df8a42093..44dec9148 100644 --- a/examples/npm_passes.py +++ b/examples/npm_passes.py @@ -59,7 +59,7 @@ # To run the pass manager, we need a pass builder object - we create pipeline # tuning options with no optimization, then use that to create a pass builder. target_machine = llvm.Target.from_default_triple().create_target_machine() -pto = llvm.create_pipeline_tuning_options(opt_level=0) +pto = llvm.create_pipeline_tuning_options(speed_level=0) pb = llvm.create_pass_builder(target_machine, pto) # Now we can run the pass manager on our module diff --git a/examples/npm_pipeline.py b/examples/npm_pipeline.py index a884d2142..6cd12e52b 100644 --- a/examples/npm_pipeline.py +++ b/examples/npm_pipeline.py @@ -52,7 +52,7 @@ # Create a ModulePassManager for speed optimization level 3 target_machine = llvm.Target.from_default_triple().create_target_machine() -pto = llvm.create_pipeline_tuning_options(opt_level=3) +pto = llvm.create_pipeline_tuning_options(speed_level=3) pb = llvm.create_pass_builder(target_machine, pto) pm = pb.getModulePassManager() diff --git a/llvmlite/binding/newpassmangers.py b/llvmlite/binding/newpassmangers.py index 835128924..981b949e0 100644 --- a/llvmlite/binding/newpassmangers.py +++ b/llvmlite/binding/newpassmangers.py @@ -14,8 +14,8 @@ def create_pass_builder(tm, pto): return PassBuilder(tm, pto) -def create_pipeline_tuning_options(opt_level=2, size_level=0): - return PipelineTuningOptions(opt_level, size_level) +def create_pipeline_tuning_options(speed_level=2, size_level=0): + return PipelineTuningOptions(speed_level, size_level) class ModulePassManager(ffi.ObjectRef): @@ -28,7 +28,7 @@ def __init__(self, ptr=None): def run(self, module, pb): ffi.lib.LLVMPY_RunNewModulePassManager(self, pb, module) - def addVerifier(self): + def add_verifier(self): ffi.lib.LLVMPY_AddVerifierPass(self) def add_aa_eval_pass(self): @@ -87,23 +87,23 @@ def _dispose(self): class PipelineTuningOptions(ffi.ObjectRef): - def __init__(self, opt_level=2, size_level=0): - self._opt_level = None + def __init__(self, speed_level=2, size_level=0): + self._speed_level = None self._size_level = None - self.opt_level = opt_level + self.speed_level = speed_level self.size_level = size_level super().__init__(ffi.lib.LLVMPY_CreatePipelineTuningOptions()) @property - def opt_level(self): - return self._opt_level + def speed_level(self): + return self._speed_level - @opt_level.setter - def opt_level(self, value): + @speed_level.setter + def speed_level(self, value): if not 0 <= value <= 3: raise ValueError( "Optimization level for speed should be 0, 1, 2, or 3") - self._opt_level = value + self._speed_level = value @property def size_level(self): @@ -113,7 +113,7 @@ def size_level(self): def size_level(self, value): if not 0 <= value <= 2: raise ValueError("Optimization level for size should be 0, 1, or 2") - if value != 0 and self.opt_level != 2: + if value != 0 and self.speed_level != 2: raise ValueError( "Optimize for size should be encoded with speedup level == 2") self._size_level = value @@ -173,13 +173,13 @@ def __init__(self, tm, pto): def getModulePassManager(self): return ModulePassManager( ffi.lib.LLVMPY_buildPerModuleDefaultPipeline( - self, self._pto.opt_level, self._pto.size_level) + self, self._pto.speed_level, self._pto.size_level) ) def getFunctionPassManager(self): return FunctionPassManager( ffi.lib.LLVMPY_buildFunctionSimplificationPipeline( - self, self._pto.opt_level, self._pto.size_level) + self, self._pto.speed_level, self._pto.size_level) ) def _dispose(self): diff --git a/llvmlite/tests/test_binding.py b/llvmlite/tests/test_binding.py index 8d62ebd01..604548e3e 100644 --- a/llvmlite/tests/test_binding.py +++ b/llvmlite/tests/test_binding.py @@ -2600,12 +2600,12 @@ def test_pto(self): pto = llvm.create_pipeline_tuning_options(3, 0) pto.close() - def test_opt_level(self): + def test_speed_level(self): pto = self.pto() - self.assertIsInstance(pto.opt_level, int) + self.assertIsInstance(pto.speed_level, int) for i in range(4): - pto.opt_level = i - self.assertEqual(pto.opt_level, i) + pto.speed_level = i + self.assertEqual(pto.speed_level, i) def test_size_level(self): pto = self.pto() @@ -2650,29 +2650,29 @@ def test_loop_unrolling(self): pto.loop_unrolling = b self.assertEqual(pto.loop_unrolling, b) - def test_opt_level_constraints(self): + def test_speed_level_constraints(self): pto = self.pto() with self.assertRaises(ValueError): - pto.opt_level = 4 + pto.speed_level = 4 with self.assertRaises(ValueError): - pto.opt_level = -1 + pto.speed_level = -1 def test_size_level_constraints(self): pto = self.pto() with self.assertRaises(ValueError): pto.size_level = 3 with self.assertRaises(ValueError): - pto.opt_level = -1 + pto.speed_level = -1 with self.assertRaises(ValueError): - pto.opt_level = 3 + pto.speed_level = 3 pto.size_level = 2 class NewPassManagerMixin(object): - def pb(self, opt_level=0, size_level=0): + def pb(self, speed_level=0, size_level=0): tm = self.target_machine(jit=False) - pto = llvm.create_pipeline_tuning_options(opt_level, size_level) + pto = llvm.create_pipeline_tuning_options(speed_level, size_level) pb = llvm.create_pass_builder(tm, pto) return pb @@ -2745,7 +2745,7 @@ def test_passes(self): mpm.add_loop_rotate_pass() mpm.add_loop_unroll_pass() mpm.add_simplify_cfg_pass() - mpm.addVerifier() + mpm.add_verifier() class TestNewFunctionPassManager(BaseTest, NewPassManagerMixin): From b49dabd27f2eaa7245034b8c3066fa0c1806258c Mon Sep 17 00:00:00 2001 From: Yashwant Singh Date: Fri, 31 May 2024 12:01:20 +0530 Subject: [PATCH 24/27] fix tests --- llvmlite/binding/newpassmangers.py | 6 ++--- llvmlite/tests/test_binding.py | 40 ++++++++++++++++++------------ 2 files changed, 27 insertions(+), 19 deletions(-) diff --git a/llvmlite/binding/newpassmangers.py b/llvmlite/binding/newpassmangers.py index 981b949e0..8ade7c92f 100644 --- a/llvmlite/binding/newpassmangers.py +++ b/llvmlite/binding/newpassmangers.py @@ -60,15 +60,15 @@ def __init__(self, ptr=None): ptr = ffi.lib.LLVMPY_CreateNewFunctionPassManager() super().__init__(ptr) + def run(self, fun, pb): + ffi.lib.LLVMPY_RunNewFunctionPassManager(self, pb, fun) + def add_aa_eval_pass(self): ffi.lib.LLVMPY_AddAAEvalPass_function(self) def add_simplify_cfg_pass(self): ffi.lib.LLVMPY_AddSimplifyCFGPass_function(self) - def run(self, fun, pb): - ffi.lib.LLVMPY_RunNewFunctionPassManager(self, pb, fun) - def add_loop_unroll_pass(self): ffi.lib.LLVMPY_AddLoopUnrollPass_function(self) diff --git a/llvmlite/tests/test_binding.py b/llvmlite/tests/test_binding.py index 604548e3e..c1ce3d08d 100644 --- a/llvmlite/tests/test_binding.py +++ b/llvmlite/tests/test_binding.py @@ -2594,10 +2594,10 @@ def rel(): class TestPipelineTuningOptions(BaseTest): def pto(self): - return llvm.PipelineTuningOptions() + return llvm.create_pipeline_tuning_options() - def test_pto(self): - pto = llvm.create_pipeline_tuning_options(3, 0) + def test_close(self): + pto = self.pto() pto.close() def test_speed_level(self): @@ -2679,6 +2679,10 @@ def pb(self, speed_level=0, size_level=0): class TestPassBuilder(BaseTest, NewPassManagerMixin): + def test_close(self): + pb = self.pb() + pb.close() + def test_pto(self): tm = self.target_machine(jit=False) pto = llvm.create_pipeline_tuning_options(3, 0) @@ -2690,18 +2694,13 @@ def test_pto(self): pb = llvm.create_pass_builder(tm, pto) pb.close() - def test_close(self): - pb = self.pb() - pb.close() - pb.close() - - def test_getMPM(self): + def test_get_module_pass_manager(self): pb = self.pb() mpm = pb.getModulePassManager() mpm.run(self.module(), pb) pb.close() - def test_getFPM(self): + def test_get_function_pass_manager(self): pb = self.pb() fpm = pb.getFunctionPassManager() fpm.run(self.module().get_function("sum"), pb) @@ -2717,7 +2716,7 @@ def test_close(self): mpm.close() def test_run(self): - pb = self.pb(3) + pb = self.pb(speed_level=3, size_level=0) mod = self.module() orig_asm = str(mod) mpm = pb.getModulePassManager() @@ -2737,15 +2736,15 @@ def test_instcombine(self): self.assertIn("%.3", orig_asm) self.assertNotIn("%.3", optimized_asm) - def test_passes(self): + def test_add_passes(self): mpm = self.pm() + mpm.add_verifier() mpm.add_aa_eval_pass() + mpm.add_simplify_cfg_pass() + mpm.add_loop_unroll_pass() + mpm.add_loop_rotate_pass() mpm.add_instruction_combine_pass() mpm.add_jump_threading_pass() - mpm.add_loop_rotate_pass() - mpm.add_loop_unroll_pass() - mpm.add_simplify_cfg_pass() - mpm.add_verifier() class TestNewFunctionPassManager(BaseTest, NewPassManagerMixin): @@ -2778,6 +2777,15 @@ def test_instcombine(self): self.assertIn("%.3", orig_asm) self.assertNotIn("%.3", optimized_asm) + def test_add_passes(self): + fpm = self.pm() + fpm.add_aa_eval_pass() + fpm.add_simplify_cfg_pass() + fpm.add_loop_unroll_pass() + fpm.add_loop_rotate_pass() + fpm.add_instruction_combine_pass() + fpm.add_jump_threading_pass() + if __name__ == "__main__": unittest.main() From 707a0381b24a4951956dfe0971e10766b3540486 Mon Sep 17 00:00:00 2001 From: Yashwant Singh Date: Fri, 31 May 2024 17:23:53 +0530 Subject: [PATCH 25/27] Typo Co-authored-by: Graham Markall <535640+gmarkall@users.noreply.github.com> --- ffi/newpassmanagers.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ffi/newpassmanagers.cpp b/ffi/newpassmanagers.cpp index b72b28855..d6f2100c7 100644 --- a/ffi/newpassmanagers.cpp +++ b/ffi/newpassmanagers.cpp @@ -292,7 +292,7 @@ LLVMPY_buildPerModuleDefaultPipeline(LLVMPassBuilderRef PBref, int speed_level, PassBuilder *PB = llvm::unwrap(PBref); OptimizationLevel OL = mapLevel(speed_level, size_level); - // FXIME: No need to explicitly take care of O0 from LLVM 17 + // FIXME: No need to explicitly take care of O0 from LLVM 17 if (OL == OptimizationLevel::O0) { return llvm::wrap( new ModulePassManager(PB->buildO0DefaultPipeline(OL))); From 76171d09b5d2e386863e870ea2a2fcea27c46bca Mon Sep 17 00:00:00 2001 From: Yashwant Singh Date: Fri, 31 May 2024 17:24:33 +0530 Subject: [PATCH 26/27] Edit error message Co-authored-by: Graham Markall <535640+gmarkall@users.noreply.github.com> --- llvmlite/binding/newpassmangers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvmlite/binding/newpassmangers.py b/llvmlite/binding/newpassmangers.py index 8ade7c92f..f1dd20cc7 100644 --- a/llvmlite/binding/newpassmangers.py +++ b/llvmlite/binding/newpassmangers.py @@ -115,7 +115,7 @@ def size_level(self, value): raise ValueError("Optimization level for size should be 0, 1, or 2") if value != 0 and self.speed_level != 2: raise ValueError( - "Optimize for size should be encoded with speedup level == 2") + "Optimization for size should be encoded with speed level == 2") self._size_level = value @property From 4194dbb96629f35f12296ea20cf28cb80ef8ba1a Mon Sep 17 00:00:00 2001 From: Yashwant Singh Date: Fri, 31 May 2024 18:12:48 +0530 Subject: [PATCH 27/27] Fix typo in file name --- llvmlite/binding/__init__.py | 2 +- llvmlite/binding/{newpassmangers.py => newpassmanagers.py} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename llvmlite/binding/{newpassmangers.py => newpassmanagers.py} (100%) diff --git a/llvmlite/binding/__init__.py b/llvmlite/binding/__init__.py index 76f498e6f..2eb177184 100644 --- a/llvmlite/binding/__init__.py +++ b/llvmlite/binding/__init__.py @@ -7,7 +7,7 @@ from .linker import * from .module import * from .options import * -from .newpassmangers import * +from .newpassmanagers import * from .passmanagers import * from .targets import * from .transforms import * diff --git a/llvmlite/binding/newpassmangers.py b/llvmlite/binding/newpassmanagers.py similarity index 100% rename from llvmlite/binding/newpassmangers.py rename to llvmlite/binding/newpassmanagers.py