Skip to content

Commit 828b8af

Browse files
enh: add LLVM implementation for inner-ordered
1 parent fc75883 commit 828b8af

File tree

5 files changed

+538
-0
lines changed

5 files changed

+538
-0
lines changed

pydatastructs/linear_data_structures/_backend/cpp/algorithms/algorithms.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ static PyMethodDef algorithms_PyMethodDef[] = {
1010
METH_VARARGS | METH_KEYWORDS, ""},
1111
{"bubble_sort_llvm", (PyCFunction)bubble_sort_llvm,
1212
METH_VARARGS | METH_KEYWORDS, ""},
13+
{"is_ordered_llvm", (PyCFunction) is_ordered_llvm,
14+
METH_VARARGS | METH_KEYWORDS, ""},
1315
{"selection_sort", (PyCFunction) selection_sort,
1416
METH_VARARGS | METH_KEYWORDS, ""},
1517
{"insertion_sort", (PyCFunction) insertion_sort,

pydatastructs/linear_data_structures/_backend/cpp/algorithms/llvm_algorithms.py

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,119 @@ def get_bubble_sort_ptr(dtype: str) -> int:
4141

4242
return _materialize(dtype)
4343

44+
45+
def get_is_ordered_ptr(dtype: str) -> int:
46+
dtype = dtype.lower().strip()
47+
if dtype not in _SUPPORTED:
48+
raise ValueError(f"Unsupported dtype '{dtype}'. Supported: {list(_SUPPORTED)}")
49+
50+
return _materialize_is_ordered(dtype)
51+
52+
53+
def _build_is_ordered_ir(dtype: str) -> str:
54+
if dtype not in _SUPPORTED:
55+
raise ValueError(f"Unsupported dtype '{dtype}'. Supported: {list(_SUPPORTED)}")
56+
57+
T, _ = _SUPPORTED[dtype]
58+
i32 = ir.IntType(32)
59+
i64 = ir.IntType(64)
60+
61+
mod = ir.Module(name=f"is_ordered_{dtype}_module")
62+
fn_name = f"is_ordered_{dtype}"
63+
64+
fn_ty = ir.FunctionType(i32, [T.as_pointer(), i32])
65+
fn = ir.Function(mod, fn_ty, name=fn_name)
66+
67+
arr, n = fn.args
68+
arr.name, n.name = "arr", "n"
69+
70+
b_entry = fn.append_basic_block("entry")
71+
b_loop = fn.append_basic_block("loop")
72+
b_check = fn.append_basic_block("check")
73+
b_ret_true = fn.append_basic_block("ret_true")
74+
b_ret_false = fn.append_basic_block("ret_false")
75+
b_exit = fn.append_basic_block("exit")
76+
77+
b = ir.IRBuilder(b_entry)
78+
cond_trivial = b.icmp_signed("<=", n, ir.Constant(i32, 1))
79+
b.cbranch(cond_trivial, b_ret_true, b_loop)
80+
81+
b.position_at_end(b_loop)
82+
i = b.phi(i32, name="i")
83+
i.add_incoming(ir.Constant(i32, 1), b_entry)
84+
85+
cond_loop = b.icmp_signed("<", i, n)
86+
b.cbranch(cond_loop, b_check, b_ret_true)
87+
88+
b.position_at_end(b_check)
89+
i64_idx = b.sext(i, i64)
90+
iprev = b.sub(i, ir.Constant(i32, 1))
91+
iprev64 = b.sext(iprev, i64)
92+
93+
ptr_i = b.gep(arr, [i64_idx], inbounds=True)
94+
ptr_iprev = b.gep(arr, [iprev64], inbounds=True)
95+
96+
val_i = b.load(ptr_i)
97+
val_iprev = b.load(ptr_iprev)
98+
99+
if isinstance(T, ir.IntType):
100+
cond = b.icmp_signed("<=", val_iprev, val_i)
101+
else:
102+
cond = b.fcmp_ordered("<=", val_iprev, val_i, fastmath=True)
103+
104+
b.cbranch(cond, b.loop, b_ret_false)
105+
106+
b.position_at_end(b_ret_false)
107+
b.ret(ir.Constant(i32, 0))
108+
109+
b.position_at_end(b.loop)
110+
i_next = b.add(i, ir.Constant(i32, 1))
111+
i.add_incoming(i_next, b.loop)
112+
b.branch(b_loop)
113+
114+
b.position_at_end(b_ret_true)
115+
b.ret(ir.Constant(i32, 1))
116+
117+
return str(mod)
118+
119+
120+
def _materialize_is_ordered(dtype: str) -> int:
121+
_ensure_target_machine()
122+
123+
if dtype in _fn_ptr_cache:
124+
return _fn_ptr_cache[dtype]
125+
126+
try:
127+
llvm_ir = _build_is_ordered_ir(dtype)
128+
mod = binding.parse_assembly(llvm_ir)
129+
mod.verify()
130+
131+
try:
132+
pm = binding.ModulePassManager()
133+
pm.add_instruction_combining_pass()
134+
pm.add_reassociate_pass()
135+
pm.add_gvn_pass()
136+
pm.add_cfg_simplification_pass()
137+
pm.run(mod)
138+
except AttributeError:
139+
pass
140+
141+
engine = binding.create_mcjit_compiler(mod, _target_machine)
142+
engine.finalize_object()
143+
engine.run_static_constructors()
144+
145+
addr = engine.get_function_address(f"is_ordered_{dtype}")
146+
if not addr:
147+
raise RuntimeError(f"Failed to get address for is_ordered_{dtype}")
148+
149+
_fn_ptr_cache[dtype] = addr
150+
_engines[dtype] = engine
151+
152+
return addr
153+
154+
except Exception as e:
155+
raise RuntimeError(f"Failed to materialize function for dtype {dtype}: {e}")
156+
44157
def _build_bubble_sort_ir(dtype: str) -> str:
45158
if dtype not in _SUPPORTED:
46159
raise ValueError(f"Unsupported dtype '{dtype}'. Supported: {list(_SUPPORTED)}")

0 commit comments

Comments
 (0)