@@ -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+
44157def _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