llvmlite 0.43.0rc1__tar.gz → 0.44.0rc2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of llvmlite might be problematic. Click here for more details.
- {llvmlite-0.43.0rc1 → llvmlite-0.44.0rc2}/PKG-INFO +7 -6
- {llvmlite-0.43.0rc1 → llvmlite-0.44.0rc2}/README.rst +4 -3
- llvmlite-0.44.0rc2/examples/npm_passes.py +73 -0
- llvmlite-0.44.0rc2/examples/npm_pipeline.py +87 -0
- llvmlite-0.44.0rc2/examples/opaque_pointers/llvmir.py +38 -0
- llvmlite-0.44.0rc2/examples/opaque_pointers/sum.py +115 -0
- {llvmlite-0.43.0rc1 → llvmlite-0.44.0rc2}/ffi/CMakeLists.txt +3 -1
- {llvmlite-0.43.0rc1 → llvmlite-0.44.0rc2}/ffi/Makefile.freebsd +1 -1
- {llvmlite-0.43.0rc1 → llvmlite-0.44.0rc2}/ffi/Makefile.linux +1 -1
- llvmlite-0.44.0rc2/ffi/Makefile.netbsd +24 -0
- {llvmlite-0.43.0rc1 → llvmlite-0.44.0rc2}/ffi/Makefile.osx +1 -1
- {llvmlite-0.43.0rc1 → llvmlite-0.44.0rc2}/ffi/build.py +27 -4
- {llvmlite-0.43.0rc1 → llvmlite-0.44.0rc2}/ffi/core.cpp +6 -8
- {llvmlite-0.43.0rc1 → llvmlite-0.44.0rc2}/ffi/core.h +4 -2
- {llvmlite-0.43.0rc1 → llvmlite-0.44.0rc2}/ffi/custom_passes.cpp +157 -63
- {llvmlite-0.43.0rc1 → llvmlite-0.44.0rc2}/ffi/initfini.cpp +2 -0
- {llvmlite-0.43.0rc1 → llvmlite-0.44.0rc2}/ffi/memorymanager.cpp +25 -14
- {llvmlite-0.43.0rc1 → llvmlite-0.44.0rc2}/ffi/memorymanager.h +12 -3
- llvmlite-0.44.0rc2/ffi/newpassmanagers.cpp +360 -0
- {llvmlite-0.43.0rc1 → llvmlite-0.44.0rc2}/ffi/orcjit.cpp +0 -9
- {llvmlite-0.43.0rc1 → llvmlite-0.44.0rc2}/ffi/passmanagers.cpp +5 -25
- {llvmlite-0.43.0rc1 → llvmlite-0.44.0rc2}/ffi/targets.cpp +26 -0
- {llvmlite-0.43.0rc1 → llvmlite-0.44.0rc2}/ffi/type.cpp +26 -0
- {llvmlite-0.43.0rc1 → llvmlite-0.44.0rc2}/ffi/value.cpp +5 -2
- llvmlite-0.44.0rc2/llvmlite/__init__.py +10 -0
- {llvmlite-0.43.0rc1 → llvmlite-0.44.0rc2}/llvmlite/_version.py +2 -2
- {llvmlite-0.43.0rc1 → llvmlite-0.44.0rc2}/llvmlite/binding/__init__.py +1 -0
- llvmlite-0.44.0rc2/llvmlite/binding/context.py +39 -0
- {llvmlite-0.43.0rc1 → llvmlite-0.44.0rc2}/llvmlite/binding/ffi.py +6 -1
- llvmlite-0.44.0rc2/llvmlite/binding/newpassmanagers.py +357 -0
- {llvmlite-0.43.0rc1 → llvmlite-0.44.0rc2}/llvmlite/binding/passmanagers.py +25 -18
- {llvmlite-0.43.0rc1 → llvmlite-0.44.0rc2}/llvmlite/binding/targets.py +75 -5
- {llvmlite-0.43.0rc1 → llvmlite-0.44.0rc2}/llvmlite/binding/typeref.py +88 -1
- {llvmlite-0.43.0rc1 → llvmlite-0.44.0rc2}/llvmlite/binding/value.py +14 -0
- {llvmlite-0.43.0rc1 → llvmlite-0.44.0rc2}/llvmlite/ir/builder.py +8 -7
- {llvmlite-0.43.0rc1 → llvmlite-0.44.0rc2}/llvmlite/ir/context.py +2 -2
- {llvmlite-0.43.0rc1 → llvmlite-0.44.0rc2}/llvmlite/ir/instructions.py +52 -25
- {llvmlite-0.43.0rc1 → llvmlite-0.44.0rc2}/llvmlite/ir/types.py +137 -17
- {llvmlite-0.43.0rc1 → llvmlite-0.44.0rc2}/llvmlite/ir/values.py +2 -2
- {llvmlite-0.43.0rc1 → llvmlite-0.44.0rc2}/llvmlite/tests/test_binding.py +663 -40
- {llvmlite-0.43.0rc1 → llvmlite-0.44.0rc2}/llvmlite/tests/test_ir.py +411 -146
- {llvmlite-0.43.0rc1 → llvmlite-0.44.0rc2}/llvmlite/tests/test_refprune.py +179 -6
- {llvmlite-0.43.0rc1 → llvmlite-0.44.0rc2}/setup.py +3 -3
- llvmlite-0.43.0rc1/llvmlite/__init__.py +0 -3
- llvmlite-0.43.0rc1/llvmlite/binding/context.py +0 -29
- {llvmlite-0.43.0rc1 → llvmlite-0.44.0rc2}/LICENSE +0 -0
- {llvmlite-0.43.0rc1 → llvmlite-0.44.0rc2}/examples/floatrep.py +0 -0
- {llvmlite-0.43.0rc1 → llvmlite-0.44.0rc2}/examples/ir_fpadd.py +0 -0
- {llvmlite-0.43.0rc1 → llvmlite-0.44.0rc2}/examples/ll_fpadd.py +0 -0
- {llvmlite-0.43.0rc1 → llvmlite-0.44.0rc2}/examples/lljit.py +0 -0
- {llvmlite-0.43.0rc1 → llvmlite-0.44.0rc2}/examples/llvmir.py +0 -0
- {llvmlite-0.43.0rc1 → llvmlite-0.44.0rc2}/examples/llvmir_iter.py +0 -0
- {llvmlite-0.43.0rc1 → llvmlite-0.44.0rc2}/examples/parseasm.py +0 -0
- {llvmlite-0.43.0rc1 → llvmlite-0.44.0rc2}/examples/sum.py +0 -0
- {llvmlite-0.43.0rc1 → llvmlite-0.44.0rc2}/examples/test.ll +0 -0
- {llvmlite-0.43.0rc1 → llvmlite-0.44.0rc2}/ffi/assembly.cpp +0 -0
- {llvmlite-0.43.0rc1 → llvmlite-0.44.0rc2}/ffi/bitcode.cpp +0 -0
- {llvmlite-0.43.0rc1 → llvmlite-0.44.0rc2}/ffi/dummy/CMakeLists.txt +0 -0
- {llvmlite-0.43.0rc1 → llvmlite-0.44.0rc2}/ffi/dylib.cpp +0 -0
- {llvmlite-0.43.0rc1 → llvmlite-0.44.0rc2}/ffi/executionengine.cpp +0 -0
- {llvmlite-0.43.0rc1 → llvmlite-0.44.0rc2}/ffi/linker.cpp +0 -0
- {llvmlite-0.43.0rc1 → llvmlite-0.44.0rc2}/ffi/module.cpp +0 -0
- {llvmlite-0.43.0rc1 → llvmlite-0.44.0rc2}/ffi/object_file.cpp +0 -0
- {llvmlite-0.43.0rc1 → llvmlite-0.44.0rc2}/ffi/transforms.cpp +0 -0
- {llvmlite-0.43.0rc1 → llvmlite-0.44.0rc2}/llvmlite/binding/analysis.py +0 -0
- {llvmlite-0.43.0rc1 → llvmlite-0.44.0rc2}/llvmlite/binding/common.py +0 -0
- {llvmlite-0.43.0rc1 → llvmlite-0.44.0rc2}/llvmlite/binding/dylib.py +0 -0
- {llvmlite-0.43.0rc1 → llvmlite-0.44.0rc2}/llvmlite/binding/executionengine.py +0 -0
- {llvmlite-0.43.0rc1 → llvmlite-0.44.0rc2}/llvmlite/binding/initfini.py +0 -0
- {llvmlite-0.43.0rc1 → llvmlite-0.44.0rc2}/llvmlite/binding/linker.py +0 -0
- {llvmlite-0.43.0rc1 → llvmlite-0.44.0rc2}/llvmlite/binding/module.py +0 -0
- {llvmlite-0.43.0rc1 → llvmlite-0.44.0rc2}/llvmlite/binding/object_file.py +0 -0
- {llvmlite-0.43.0rc1 → llvmlite-0.44.0rc2}/llvmlite/binding/options.py +0 -0
- {llvmlite-0.43.0rc1 → llvmlite-0.44.0rc2}/llvmlite/binding/orcjit.py +0 -0
- {llvmlite-0.43.0rc1 → llvmlite-0.44.0rc2}/llvmlite/binding/transforms.py +0 -0
- {llvmlite-0.43.0rc1 → llvmlite-0.44.0rc2}/llvmlite/ir/__init__.py +0 -0
- {llvmlite-0.43.0rc1 → llvmlite-0.44.0rc2}/llvmlite/ir/_utils.py +0 -0
- {llvmlite-0.43.0rc1 → llvmlite-0.44.0rc2}/llvmlite/ir/module.py +0 -0
- {llvmlite-0.43.0rc1 → llvmlite-0.44.0rc2}/llvmlite/ir/transforms.py +0 -0
- {llvmlite-0.43.0rc1 → llvmlite-0.44.0rc2}/llvmlite/tests/__init__.py +0 -0
- {llvmlite-0.43.0rc1 → llvmlite-0.44.0rc2}/llvmlite/tests/__main__.py +0 -0
- {llvmlite-0.43.0rc1 → llvmlite-0.44.0rc2}/llvmlite/tests/customize.py +0 -0
- {llvmlite-0.43.0rc1 → llvmlite-0.44.0rc2}/llvmlite/tests/refprune_proto.py +0 -0
- {llvmlite-0.43.0rc1 → llvmlite-0.44.0rc2}/llvmlite/tests/test_valuerepr.py +0 -0
- {llvmlite-0.43.0rc1 → llvmlite-0.44.0rc2}/llvmlite/utils.py +0 -0
- {llvmlite-0.43.0rc1 → llvmlite-0.44.0rc2}/run_coverage.py +0 -0
- {llvmlite-0.43.0rc1 → llvmlite-0.44.0rc2}/runtests.py +0 -0
- {llvmlite-0.43.0rc1 → llvmlite-0.44.0rc2}/versioneer.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: llvmlite
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.44.0rc2
|
|
4
4
|
Summary: lightweight wrapper around basic LLVM functionality
|
|
5
5
|
Home-page: http://llvmlite.readthedocs.io
|
|
6
6
|
License: BSD
|
|
@@ -10,13 +10,13 @@ Classifier: Intended Audience :: Developers
|
|
|
10
10
|
Classifier: Operating System :: OS Independent
|
|
11
11
|
Classifier: Programming Language :: Python
|
|
12
12
|
Classifier: Programming Language :: Python :: 3
|
|
13
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
14
13
|
Classifier: Programming Language :: Python :: 3.10
|
|
15
14
|
Classifier: Programming Language :: Python :: 3.11
|
|
16
15
|
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
17
17
|
Classifier: Topic :: Software Development :: Code Generators
|
|
18
18
|
Classifier: Topic :: Software Development :: Compilers
|
|
19
|
-
Requires-Python: >=3.
|
|
19
|
+
Requires-Python: >=3.10
|
|
20
20
|
License-File: LICENSE
|
|
21
21
|
License-File: LICENSE.thirdparty
|
|
22
22
|
|
|
@@ -79,17 +79,18 @@ Key Benefits
|
|
|
79
79
|
Compatibility
|
|
80
80
|
=============
|
|
81
81
|
|
|
82
|
-
llvmlite has been tested with Python 3.
|
|
82
|
+
llvmlite has been tested with Python 3.10 -- 3.13 and is likely to work with
|
|
83
83
|
greater versions.
|
|
84
84
|
|
|
85
|
-
As of version 0.
|
|
85
|
+
As of version 0.44.0, llvmlite requires LLVM 15.x.x on all architectures
|
|
86
86
|
|
|
87
87
|
Historical compatibility table:
|
|
88
88
|
|
|
89
89
|
================= ========================
|
|
90
90
|
llvmlite versions compatible LLVM versions
|
|
91
91
|
================= ========================
|
|
92
|
-
0.
|
|
92
|
+
0.44.0 - ...... 15.x.x
|
|
93
|
+
0.41.0 - 0.43.0 14.x.x
|
|
93
94
|
0.40.0 - 0.40.1 11.x.x and 14.x.x (12.x.x and 13.x.x untested but may work)
|
|
94
95
|
0.37.0 - 0.39.1 11.x.x
|
|
95
96
|
0.34.0 - 0.36.0 10.0.x (9.0.x for ``aarch64`` only)
|
|
@@ -57,17 +57,18 @@ Key Benefits
|
|
|
57
57
|
Compatibility
|
|
58
58
|
=============
|
|
59
59
|
|
|
60
|
-
llvmlite has been tested with Python 3.
|
|
60
|
+
llvmlite has been tested with Python 3.10 -- 3.13 and is likely to work with
|
|
61
61
|
greater versions.
|
|
62
62
|
|
|
63
|
-
As of version 0.
|
|
63
|
+
As of version 0.44.0, llvmlite requires LLVM 15.x.x on all architectures
|
|
64
64
|
|
|
65
65
|
Historical compatibility table:
|
|
66
66
|
|
|
67
67
|
================= ========================
|
|
68
68
|
llvmlite versions compatible LLVM versions
|
|
69
69
|
================= ========================
|
|
70
|
-
0.
|
|
70
|
+
0.44.0 - ...... 15.x.x
|
|
71
|
+
0.41.0 - 0.43.0 14.x.x
|
|
71
72
|
0.40.0 - 0.40.1 11.x.x and 14.x.x (12.x.x and 13.x.x untested but may work)
|
|
72
73
|
0.37.0 - 0.39.1 11.x.x
|
|
73
74
|
0.34.0 - 0.36.0 10.0.x (9.0.x for ``aarch64`` only)
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"""
|
|
2
|
+
This example demonstrates how to use the new module pass manager to optimize a
|
|
3
|
+
module using the loop unrolling and CFG simplification passes.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import faulthandler
|
|
7
|
+
import llvmlite.binding as llvm
|
|
8
|
+
|
|
9
|
+
# Dump Python traceback in the event of a segfault
|
|
10
|
+
faulthandler.enable()
|
|
11
|
+
|
|
12
|
+
# All are required to initialize LLVM
|
|
13
|
+
llvm.initialize()
|
|
14
|
+
llvm.initialize_native_target()
|
|
15
|
+
llvm.initialize_native_asmprinter()
|
|
16
|
+
|
|
17
|
+
# Module to optimize
|
|
18
|
+
strmod = """
|
|
19
|
+
define i32 @foo3(i32* noalias nocapture readonly %src) {
|
|
20
|
+
entry:
|
|
21
|
+
br label %loop.header
|
|
22
|
+
|
|
23
|
+
loop.header:
|
|
24
|
+
%iv = phi i64 [ 0, %entry ], [ %inc, %loop.latch ]
|
|
25
|
+
%r1 = phi i32 [ 0, %entry ], [ %r3, %loop.latch ]
|
|
26
|
+
%arrayidx = getelementptr inbounds i32, i32* %src, i64 %iv
|
|
27
|
+
%src_element = load i32, i32* %arrayidx, align 4
|
|
28
|
+
%cmp = icmp eq i32 0, %src_element
|
|
29
|
+
br i1 %cmp, label %loop.if, label %loop.latch
|
|
30
|
+
|
|
31
|
+
loop.if:
|
|
32
|
+
%r2 = add i32 %r1, 1
|
|
33
|
+
br label %loop.latch
|
|
34
|
+
loop.latch:
|
|
35
|
+
%r3 = phi i32 [%r1, %loop.header], [%r2, %loop.if]
|
|
36
|
+
%inc = add nuw nsw i64 %iv, 1
|
|
37
|
+
%exitcond = icmp eq i64 %inc, 9
|
|
38
|
+
br i1 %exitcond, label %loop.end, label %loop.header
|
|
39
|
+
loop.end:
|
|
40
|
+
%r.lcssa = phi i32 [ %r3, %loop.latch ]
|
|
41
|
+
ret i32 %r.lcssa
|
|
42
|
+
}
|
|
43
|
+
"""
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
module = llvm.parse_assembly(strmod)
|
|
47
|
+
|
|
48
|
+
print("Module before optimization:\n")
|
|
49
|
+
print(module)
|
|
50
|
+
|
|
51
|
+
# Set up the module pass manager used to run our optimization pipeline.
|
|
52
|
+
# We create it unpopulated, and then add the loop unroll and simplify CFG
|
|
53
|
+
# passes.
|
|
54
|
+
pm = llvm.create_new_module_pass_manager()
|
|
55
|
+
pm.add_loop_unroll_pass()
|
|
56
|
+
pm.add_simplify_cfg_pass()
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
# To run the pass manager, we need a pass builder object - we create pipeline
|
|
60
|
+
# tuning options with no optimization, then use that to create a pass builder.
|
|
61
|
+
target_machine = llvm.Target.from_default_triple().create_target_machine()
|
|
62
|
+
pto = llvm.create_pipeline_tuning_options(speed_level=0)
|
|
63
|
+
pb = llvm.create_pass_builder(target_machine, pto)
|
|
64
|
+
|
|
65
|
+
# Now we can run the pass manager on our module
|
|
66
|
+
pm.run(module, pb)
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
# We should observer a fully unrolled loop, and the function now consists of a
|
|
70
|
+
# single basic block executing all the iterations of the loop in a straight
|
|
71
|
+
# line.
|
|
72
|
+
print("\nModule after optimization:\n")
|
|
73
|
+
print(module)
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"""
|
|
2
|
+
This example demonstrates how to optimize a module with a module pass manager
|
|
3
|
+
pre-populated with passes according to a given optimization level.
|
|
4
|
+
|
|
5
|
+
The optimized module is executed using the MCJIT bindings.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from ctypes import CFUNCTYPE, c_int, POINTER
|
|
9
|
+
import faulthandler
|
|
10
|
+
import llvmlite.binding as llvm
|
|
11
|
+
|
|
12
|
+
import numpy as np
|
|
13
|
+
|
|
14
|
+
# Dump Python traceback in the event of a segfault
|
|
15
|
+
faulthandler.enable()
|
|
16
|
+
|
|
17
|
+
# All are required to initialize LLVM
|
|
18
|
+
llvm.initialize()
|
|
19
|
+
llvm.initialize_native_target()
|
|
20
|
+
llvm.initialize_native_asmprinter()
|
|
21
|
+
|
|
22
|
+
# Module to optimize and execute
|
|
23
|
+
strmod = """
|
|
24
|
+
; ModuleID = '<string>'
|
|
25
|
+
source_filename = "<string>"
|
|
26
|
+
target triple = "unknown-unknown-unknown"
|
|
27
|
+
|
|
28
|
+
define i32 @sum(i32* %.1, i32 %.2) {
|
|
29
|
+
.4:
|
|
30
|
+
br label %.5
|
|
31
|
+
|
|
32
|
+
.5: ; preds = %.5, %.4
|
|
33
|
+
%.8 = phi i32 [ 0, %.4 ], [ %.13, %.5 ]
|
|
34
|
+
%.9 = phi i32 [ 0, %.4 ], [ %.12, %.5 ]
|
|
35
|
+
%.10 = getelementptr i32, i32* %.1, i32 %.8
|
|
36
|
+
%.11 = load i32, i32* %.10, align 4
|
|
37
|
+
%.12 = add i32 %.9, %.11
|
|
38
|
+
%.13 = add i32 %.8, 1
|
|
39
|
+
%.14 = icmp ult i32 %.13, %.2
|
|
40
|
+
br i1 %.14, label %.5, label %.6
|
|
41
|
+
|
|
42
|
+
.6: ; preds = %.5
|
|
43
|
+
ret i32 %.12
|
|
44
|
+
}
|
|
45
|
+
"""
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
module = llvm.parse_assembly(strmod)
|
|
49
|
+
|
|
50
|
+
print("Module before optimization:\n")
|
|
51
|
+
print(module)
|
|
52
|
+
|
|
53
|
+
# Create a ModulePassManager for speed optimization level 3
|
|
54
|
+
target_machine = llvm.Target.from_default_triple().create_target_machine()
|
|
55
|
+
pto = llvm.create_pipeline_tuning_options(speed_level=3)
|
|
56
|
+
pb = llvm.create_pass_builder(target_machine, pto)
|
|
57
|
+
pm = pb.getModulePassManager()
|
|
58
|
+
|
|
59
|
+
# Run the optimization pipeline on the module
|
|
60
|
+
pm.run(module, pb)
|
|
61
|
+
|
|
62
|
+
# O3 optimization will likely have vectorized the loop. The resulting code will
|
|
63
|
+
# be more complex, but more performant.
|
|
64
|
+
print("\nModule after optimization:\n")
|
|
65
|
+
print(module)
|
|
66
|
+
|
|
67
|
+
with llvm.create_mcjit_compiler(module, target_machine) as ee:
|
|
68
|
+
# Generate code and get a pointer to it for calling
|
|
69
|
+
ee.finalize_object()
|
|
70
|
+
cfptr = ee.get_function_address("sum")
|
|
71
|
+
|
|
72
|
+
# We should also observe vector instructions in the generated assembly
|
|
73
|
+
print("\nAssembly code generated from module\n")
|
|
74
|
+
print(target_machine.emit_assembly(module))
|
|
75
|
+
|
|
76
|
+
# Create an array of integers and call our optimized sum function with them
|
|
77
|
+
cfunc = CFUNCTYPE(c_int, POINTER(c_int), c_int)(cfptr)
|
|
78
|
+
A = np.arange(10, dtype=np.int32)
|
|
79
|
+
res = cfunc(A.ctypes.data_as(POINTER(c_int)), A.size)
|
|
80
|
+
|
|
81
|
+
# Print results, which should be identical
|
|
82
|
+
print(f"Result of executing the optimized function: {res}")
|
|
83
|
+
print(f"Expected result: {A.sum()}")
|
|
84
|
+
|
|
85
|
+
# Sanity check
|
|
86
|
+
np.testing.assert_equal(res, A.sum())
|
|
87
|
+
print("Success!")
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import llvmlite
|
|
2
|
+
llvmlite.opaque_pointers_enabled = True
|
|
3
|
+
|
|
4
|
+
import llvmlite.ir as ll
|
|
5
|
+
|
|
6
|
+
fntype = ll.FunctionType(ll.IntType(32), [ll.IntType(32), ll.IntType(32)])
|
|
7
|
+
|
|
8
|
+
module = ll.Module()
|
|
9
|
+
|
|
10
|
+
func = ll.Function(module, fntype, name='foo')
|
|
11
|
+
bb_entry = func.append_basic_block()
|
|
12
|
+
|
|
13
|
+
builder = ll.IRBuilder()
|
|
14
|
+
builder.position_at_end(bb_entry)
|
|
15
|
+
|
|
16
|
+
stackint = builder.alloca(ll.IntType(32))
|
|
17
|
+
# Instead of stackint.type.pointee we can access stackint.allocated_type
|
|
18
|
+
# directly.
|
|
19
|
+
builder.store(ll.Constant(stackint.allocated_type, 123), stackint)
|
|
20
|
+
myint = builder.load(stackint)
|
|
21
|
+
|
|
22
|
+
addinstr = builder.add(func.args[0], func.args[1])
|
|
23
|
+
mulinstr = builder.mul(addinstr, ll.Constant(ll.IntType(32), 123))
|
|
24
|
+
pred = builder.icmp_signed('<', addinstr, mulinstr)
|
|
25
|
+
builder.ret(mulinstr)
|
|
26
|
+
|
|
27
|
+
bb_block = func.append_basic_block()
|
|
28
|
+
builder.position_at_end(bb_block)
|
|
29
|
+
|
|
30
|
+
bb_exit = func.append_basic_block()
|
|
31
|
+
|
|
32
|
+
pred = builder.trunc(addinstr, ll.IntType(1))
|
|
33
|
+
builder.cbranch(pred, bb_block, bb_exit)
|
|
34
|
+
|
|
35
|
+
builder.position_at_end(bb_exit)
|
|
36
|
+
builder.ret(myint)
|
|
37
|
+
|
|
38
|
+
print(module)
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
from __future__ import print_function
|
|
2
|
+
|
|
3
|
+
from ctypes import CFUNCTYPE, c_int, POINTER
|
|
4
|
+
import sys
|
|
5
|
+
try:
|
|
6
|
+
from time import perf_counter as time
|
|
7
|
+
except ImportError:
|
|
8
|
+
from time import time
|
|
9
|
+
|
|
10
|
+
import numpy as np
|
|
11
|
+
|
|
12
|
+
try:
|
|
13
|
+
import faulthandler; faulthandler.enable()
|
|
14
|
+
except ImportError:
|
|
15
|
+
pass
|
|
16
|
+
|
|
17
|
+
import llvmlite
|
|
18
|
+
llvmlite.opaque_pointers_enabled = True
|
|
19
|
+
|
|
20
|
+
import llvmlite.ir as ll
|
|
21
|
+
import llvmlite.binding as llvm
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
llvm.initialize()
|
|
25
|
+
llvm.initialize_native_target()
|
|
26
|
+
llvm.initialize_native_asmprinter()
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
t1 = time()
|
|
30
|
+
|
|
31
|
+
# Pointers are opaque, so we should define them as such here.
|
|
32
|
+
fnty = ll.FunctionType(ll.IntType(32), [ll.PointerType(), ll.IntType(32)])
|
|
33
|
+
module = ll.Module()
|
|
34
|
+
|
|
35
|
+
func = ll.Function(module, fnty, name="sum")
|
|
36
|
+
|
|
37
|
+
bb_entry = func.append_basic_block()
|
|
38
|
+
bb_loop = func.append_basic_block()
|
|
39
|
+
bb_exit = func.append_basic_block()
|
|
40
|
+
|
|
41
|
+
builder = ll.IRBuilder()
|
|
42
|
+
builder.position_at_end(bb_entry)
|
|
43
|
+
|
|
44
|
+
builder.branch(bb_loop)
|
|
45
|
+
builder.position_at_end(bb_loop)
|
|
46
|
+
|
|
47
|
+
index = builder.phi(ll.IntType(32))
|
|
48
|
+
index.add_incoming(ll.Constant(index.type, 0), bb_entry)
|
|
49
|
+
accum = builder.phi(ll.IntType(32))
|
|
50
|
+
accum.add_incoming(ll.Constant(accum.type, 0), bb_entry)
|
|
51
|
+
|
|
52
|
+
# These GEP and load need an excplicit type.
|
|
53
|
+
ptr = builder.gep(func.args[0], [index], source_etype=ll.IntType(32))
|
|
54
|
+
value = builder.load(ptr, typ=ll.IntType(32))
|
|
55
|
+
|
|
56
|
+
added = builder.add(accum, value)
|
|
57
|
+
accum.add_incoming(added, bb_loop)
|
|
58
|
+
|
|
59
|
+
indexp1 = builder.add(index, ll.Constant(index.type, 1))
|
|
60
|
+
index.add_incoming(indexp1, bb_loop)
|
|
61
|
+
|
|
62
|
+
cond = builder.icmp_unsigned('<', indexp1, func.args[1])
|
|
63
|
+
builder.cbranch(cond, bb_loop, bb_exit)
|
|
64
|
+
|
|
65
|
+
builder.position_at_end(bb_exit)
|
|
66
|
+
builder.ret(added)
|
|
67
|
+
|
|
68
|
+
strmod = str(module)
|
|
69
|
+
|
|
70
|
+
t2 = time()
|
|
71
|
+
|
|
72
|
+
print("-- generate IR:", t2-t1)
|
|
73
|
+
|
|
74
|
+
t3 = time()
|
|
75
|
+
|
|
76
|
+
llmod = llvm.parse_assembly(strmod)
|
|
77
|
+
|
|
78
|
+
t4 = time()
|
|
79
|
+
|
|
80
|
+
print("-- parse assembly:", t4-t3)
|
|
81
|
+
|
|
82
|
+
print(llmod)
|
|
83
|
+
|
|
84
|
+
pmb = llvm.create_pass_manager_builder()
|
|
85
|
+
pmb.opt_level = 2
|
|
86
|
+
pm = llvm.create_module_pass_manager()
|
|
87
|
+
pmb.populate(pm)
|
|
88
|
+
|
|
89
|
+
t5 = time()
|
|
90
|
+
|
|
91
|
+
pm.run(llmod)
|
|
92
|
+
|
|
93
|
+
t6 = time()
|
|
94
|
+
|
|
95
|
+
print("-- optimize:", t6-t5)
|
|
96
|
+
|
|
97
|
+
t7 = time()
|
|
98
|
+
|
|
99
|
+
target_machine = llvm.Target.from_default_triple().create_target_machine()
|
|
100
|
+
|
|
101
|
+
with llvm.create_mcjit_compiler(llmod, target_machine) as ee:
|
|
102
|
+
ee.finalize_object()
|
|
103
|
+
cfptr = ee.get_function_address("sum")
|
|
104
|
+
|
|
105
|
+
t8 = time()
|
|
106
|
+
print("-- JIT compile:", t8 - t7)
|
|
107
|
+
|
|
108
|
+
print(target_machine.emit_assembly(llmod))
|
|
109
|
+
|
|
110
|
+
cfunc = CFUNCTYPE(c_int, POINTER(c_int), c_int)(cfptr)
|
|
111
|
+
A = np.arange(10, dtype=np.int32)
|
|
112
|
+
res = cfunc(A.ctypes.data_as(POINTER(c_int)), A.size)
|
|
113
|
+
|
|
114
|
+
print(res, A.sum())
|
|
115
|
+
|
|
@@ -11,6 +11,8 @@ if(NOT MSVC)
|
|
|
11
11
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti -g")
|
|
12
12
|
endif()
|
|
13
13
|
|
|
14
|
+
set(CMAKE_CXX_STANDARD 17)
|
|
15
|
+
|
|
14
16
|
# Work around llvm/llvm-project#83802 - LLVM's Findzstd.cmake uses variables
|
|
15
17
|
# that require including `GNUInstallDirs`, but it does not include it itself.
|
|
16
18
|
include(GNUInstallDirs)
|
|
@@ -44,7 +46,7 @@ endif()
|
|
|
44
46
|
add_library(llvmlite SHARED assembly.cpp bitcode.cpp core.cpp initfini.cpp
|
|
45
47
|
module.cpp value.cpp executionengine.cpp transforms.cpp type.cpp
|
|
46
48
|
passmanagers.cpp targets.cpp dylib.cpp linker.cpp object_file.cpp
|
|
47
|
-
custom_passes.cpp orcjit.cpp memorymanager.cpp)
|
|
49
|
+
custom_passes.cpp orcjit.cpp memorymanager.cpp newpassmanagers.cpp)
|
|
48
50
|
|
|
49
51
|
# Find the libraries that correspond to the LLVM components
|
|
50
52
|
# that we wish to use.
|
|
@@ -12,7 +12,7 @@ INCLUDE = core.h
|
|
|
12
12
|
SRC = assembly.cpp bitcode.cpp core.cpp initfini.cpp module.cpp value.cpp \
|
|
13
13
|
executionengine.cpp transforms.cpp passmanagers.cpp type.cpp targets.cpp \
|
|
14
14
|
dylib.cpp linker.cpp object_file.cpp orcjit.cpp custom_passes.cpp \
|
|
15
|
-
memorymanager.cpp
|
|
15
|
+
memorymanager.cpp newpassmanagers.cpp
|
|
16
16
|
OUTPUT = libllvmlite.so
|
|
17
17
|
|
|
18
18
|
all: $(OUTPUT)
|
|
@@ -13,7 +13,7 @@ LIBS = $(LLVM_LIBS)
|
|
|
13
13
|
INCLUDE = core.h
|
|
14
14
|
OBJ = assembly.o bitcode.o core.o initfini.o module.o value.o \
|
|
15
15
|
executionengine.o transforms.o passmanagers.o targets.o type.o dylib.o \
|
|
16
|
-
linker.o object_file.o custom_passes.o orcjit.o memorymanager.o
|
|
16
|
+
linker.o object_file.o custom_passes.o orcjit.o memorymanager.o newpassmanagers.o
|
|
17
17
|
OUTPUT = libllvmlite.so
|
|
18
18
|
|
|
19
19
|
all: $(OUTPUT)
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
|
|
2
|
+
CXX = clang++
|
|
3
|
+
|
|
4
|
+
# -flto and --exclude-libs allow us to remove those parts of LLVM we don't use
|
|
5
|
+
CXX_FLTO_FLAGS ?= -flto
|
|
6
|
+
LD_FLTO_FLAGS ?= -flto -Wl,--exclude-libs=ALL
|
|
7
|
+
|
|
8
|
+
CXXFLAGS := $(CPPFLAGS) $(CXXFLAGS) $(LLVM_CXXFLAGS) $(CXX_FLTO_FLAGS)
|
|
9
|
+
LDFLAGS := $(LDFLAGS) $(LLVM_LDFLAGS) $(LD_FLTO_FLAGS)
|
|
10
|
+
LIBS = $(LLVM_LIBS)
|
|
11
|
+
INCLUDE = core.h
|
|
12
|
+
SRC = assembly.cpp bitcode.cpp core.cpp initfini.cpp module.cpp value.cpp \
|
|
13
|
+
executionengine.cpp transforms.cpp passmanagers.cpp type.cpp targets.cpp \
|
|
14
|
+
dylib.cpp linker.cpp object_file.cpp orcjit.cpp custom_passes.cpp \
|
|
15
|
+
memorymanager.cpp newpassmanagers.cpp
|
|
16
|
+
OUTPUT = libllvmlite.so
|
|
17
|
+
|
|
18
|
+
all: $(OUTPUT)
|
|
19
|
+
|
|
20
|
+
$(OUTPUT): $(SRC) $(INCLUDE)
|
|
21
|
+
$(CXX) -shared $(CXXFLAGS) $(SRC) -o $(OUTPUT) $(LDFLAGS) $(LIBS)
|
|
22
|
+
|
|
23
|
+
clean:
|
|
24
|
+
rm -rf test
|
|
@@ -9,7 +9,7 @@ INCLUDE = core.h
|
|
|
9
9
|
SRC = assembly.cpp bitcode.cpp core.cpp initfini.cpp module.cpp value.cpp \
|
|
10
10
|
executionengine.cpp transforms.cpp passmanagers.cpp targets.cpp type.cpp \
|
|
11
11
|
dylib.cpp linker.cpp object_file.cpp custom_passes.cpp orcjit.cpp \
|
|
12
|
-
memorymanager.cpp
|
|
12
|
+
memorymanager.cpp newpassmanagers.cpp
|
|
13
13
|
OUTPUT = libllvmlite.dylib
|
|
14
14
|
MACOSX_DEPLOYMENT_TARGET ?= 10.9
|
|
15
15
|
|
|
@@ -99,7 +99,28 @@ def find_windows_generator():
|
|
|
99
99
|
raise RuntimeError("No compatible cmake generator installed on this machine")
|
|
100
100
|
|
|
101
101
|
|
|
102
|
+
def remove_msvc_whole_program_optimization():
|
|
103
|
+
"""Remove MSVC whole-program optimization flags.
|
|
104
|
+
This workaround a segfault issue on windows.
|
|
105
|
+
Note: conda-build is known to enable the `-GL` flag.
|
|
106
|
+
"""
|
|
107
|
+
def drop_gl(flags):
|
|
108
|
+
try:
|
|
109
|
+
flags.remove('-GL')
|
|
110
|
+
except ValueError:
|
|
111
|
+
pass
|
|
112
|
+
else:
|
|
113
|
+
print(f"removed '-GL' flag in {flags}")
|
|
114
|
+
cflags = os.environ.get('CFLAGS', '').split(' ')
|
|
115
|
+
cxxflags = os.environ.get('CXXFLAGS', '').split(' ')
|
|
116
|
+
drop_gl(cflags)
|
|
117
|
+
drop_gl(cxxflags)
|
|
118
|
+
os.environ['CFLAGS'] = ' '.join(cflags)
|
|
119
|
+
os.environ['CXXFLAGS'] = ' '.join(cxxflags)
|
|
120
|
+
|
|
121
|
+
|
|
102
122
|
def main_windows():
|
|
123
|
+
remove_msvc_whole_program_optimization()
|
|
103
124
|
generator = find_windows_generator()
|
|
104
125
|
config = 'Release'
|
|
105
126
|
if not os.path.exists(build_dir):
|
|
@@ -167,13 +188,13 @@ def main_posix(kind, library_ext):
|
|
|
167
188
|
else:
|
|
168
189
|
(version, _) = out.split('.', 1)
|
|
169
190
|
version = int(version)
|
|
170
|
-
if version ==
|
|
171
|
-
msg = ("Building with LLVM
|
|
191
|
+
if version == 16:
|
|
192
|
+
msg = ("Building with LLVM 16; note that LLVM 16 support is "
|
|
172
193
|
"presently experimental")
|
|
173
194
|
show_warning(msg)
|
|
174
|
-
elif version !=
|
|
195
|
+
elif version != 15:
|
|
175
196
|
|
|
176
|
-
msg = ("Building llvmlite requires LLVM
|
|
197
|
+
msg = ("Building llvmlite requires LLVM 15, got "
|
|
177
198
|
"{!r}. Be sure to set LLVM_CONFIG to the right executable "
|
|
178
199
|
"path.\nRead the documentation at "
|
|
179
200
|
"http://llvmlite.pydata.org/ for more information about "
|
|
@@ -225,6 +246,8 @@ def main():
|
|
|
225
246
|
main_posix('linux', '.so')
|
|
226
247
|
elif sys.platform.startswith(('freebsd','openbsd')):
|
|
227
248
|
main_posix('freebsd', '.so')
|
|
249
|
+
elif sys.platform.startswith('netbsd'):
|
|
250
|
+
main_posix('netbsd', '.so')
|
|
228
251
|
elif sys.platform == 'darwin':
|
|
229
252
|
main_posix('osx', '.dylib')
|
|
230
253
|
else:
|
|
@@ -20,21 +20,19 @@ LLVMPY_CreateByteString(const char *buf, size_t len) {
|
|
|
20
20
|
API_EXPORT(void)
|
|
21
21
|
LLVMPY_DisposeString(const char *msg) { free(const_cast<char *>(msg)); }
|
|
22
22
|
|
|
23
|
+
// FIXME: Remove `enableOpaquePointers' once typed pointers are removed.
|
|
23
24
|
API_EXPORT(LLVMContextRef)
|
|
24
|
-
LLVMPY_GetGlobalContext() {
|
|
25
|
+
LLVMPY_GetGlobalContext(bool enableOpaquePointers) {
|
|
25
26
|
auto context = LLVMGetGlobalContext();
|
|
26
|
-
|
|
27
|
-
LLVMContextSetOpaquePointers(context, false);
|
|
28
|
-
#endif
|
|
27
|
+
LLVMContextSetOpaquePointers(context, enableOpaquePointers);
|
|
29
28
|
return context;
|
|
30
29
|
}
|
|
31
30
|
|
|
31
|
+
// FIXME: Remove `enableOpaquePointers' once typed pointers are removed.
|
|
32
32
|
API_EXPORT(LLVMContextRef)
|
|
33
|
-
LLVMPY_ContextCreate() {
|
|
33
|
+
LLVMPY_ContextCreate(bool enableOpaquePointers) {
|
|
34
34
|
LLVMContextRef context = LLVMContextCreate();
|
|
35
|
-
|
|
36
|
-
LLVMContextSetOpaquePointers(context, false);
|
|
37
|
-
#endif
|
|
35
|
+
LLVMContextSetOpaquePointers(context, enableOpaquePointers);
|
|
38
36
|
return context;
|
|
39
37
|
}
|
|
40
38
|
|
|
@@ -31,11 +31,13 @@ LLVMPY_CreateByteString(const char *buf, size_t len);
|
|
|
31
31
|
API_EXPORT(void)
|
|
32
32
|
LLVMPY_DisposeString(const char *msg);
|
|
33
33
|
|
|
34
|
+
// FIXME: Remove `enableOpaquePointers' once typed pointers are removed.
|
|
34
35
|
API_EXPORT(LLVMContextRef)
|
|
35
|
-
LLVMPY_GetGlobalContext();
|
|
36
|
+
LLVMPY_GetGlobalContext(bool enableOpaquePointers);
|
|
36
37
|
|
|
38
|
+
// FIXME: Remove `enableOpaquePointers' once typed pointers are removed.
|
|
37
39
|
API_EXPORT(LLVMContextRef)
|
|
38
|
-
LLVMPY_ContextCreate();
|
|
40
|
+
LLVMPY_ContextCreate(bool enableOpaquePointers);
|
|
39
41
|
|
|
40
42
|
} /* end extern "C" */
|
|
41
43
|
|