Skip to content

Commit 87e2be0

Browse files
committed
Add a couple of examples with opaque pointers
This patch adds a couple of examples on how to use the new opaque pointer builder interfaces. The examples are based on the already existing examples with the same name.
1 parent a9ae1f2 commit 87e2be0

File tree

2 files changed

+153
-0
lines changed

2 files changed

+153
-0
lines changed

examples/opaque_pointers/llvmir.py

+38
Original file line numberDiff line numberDiff line change
@@ -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)

examples/opaque_pointers/sum.py

+115
Original file line numberDiff line numberDiff line change
@@ -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+

0 commit comments

Comments
 (0)