@@ -40,12 +40,41 @@ void ir_consistency_check(void)
4040 IR_ASSERT (IR_ADD + 1 == IR_SUB );
4141}
4242
43- static bool ir_check_use_list (const ir_ctx * ctx , ir_ref from , ir_ref to )
43+ typedef struct {
44+ ir_arena * arena ;
45+ ir_bitset * use_set ;
46+ ir_bitset * input_set ;
47+ } ir_check_ctx ;
48+
49+ static bool ir_check_use_list (ir_check_ctx * check_ctx , const ir_ctx * ctx , ir_ref from , ir_ref to )
4450{
4551 ir_ref n , * p ;
4652 ir_use_list * use_list = & ctx -> use_lists [from ];
4753
4854 n = use_list -> count ;
55+ if (n > 16 ) {
56+ /* Avoid quadratic complexity by maintaining a temporary bit-set */
57+ ir_bitset set ;
58+
59+ if (!check_ctx -> use_set || !(set = check_ctx -> use_set [from ])) {
60+ if (!check_ctx -> arena ) {
61+ check_ctx -> arena = ir_arena_create (sizeof (ir_arena ) +
62+ ctx -> insns_count * sizeof (ir_bitset ) +
63+ ir_bitset_len (ctx -> insns_count ) * sizeof (ir_bitset_base_t ));
64+ }
65+ if (!check_ctx -> use_set ) {
66+ check_ctx -> use_set = ir_arena_alloc (& check_ctx -> arena , ctx -> insns_count * sizeof (ir_bitset ));
67+ memset (check_ctx -> use_set , 0 , ctx -> insns_count * sizeof (ir_bitset ));
68+ }
69+ check_ctx -> use_set [from ] = set = (ir_bitset )ir_arena_alloc (& check_ctx -> arena ,
70+ ir_bitset_len (ctx -> insns_count ) * sizeof (ir_bitset_base_t ));
71+ memset (set , 0 , ir_bitset_len (ctx -> insns_count ) * sizeof (ir_bitset_base_t ));
72+ for (p = & ctx -> use_edges [use_list -> refs ]; n > 0 ; p ++ , n -- ) {
73+ ir_bitset_incl (set , * p );
74+ }
75+ }
76+ return ir_bitset_in (set , to );
77+ }
4978 for (p = & ctx -> use_edges [use_list -> refs ]; n > 0 ; p ++ , n -- ) {
5079 if (* p == to ) {
5180 return 1 ;
@@ -54,12 +83,35 @@ static bool ir_check_use_list(const ir_ctx *ctx, ir_ref from, ir_ref to)
5483 return 0 ;
5584}
5685
57- static bool ir_check_input_list (const ir_ctx * ctx , ir_ref from , ir_ref to )
86+ static bool ir_check_input_list (ir_check_ctx * check_ctx , const ir_ctx * ctx , ir_ref from , ir_ref to )
5887{
5988 ir_insn * insn = & ctx -> ir_base [to ];
6089 ir_ref n , j , * p ;
6190
6291 n = ir_input_edges_count (ctx , insn );
92+ if (n > 16 ) {
93+ /* Avoid quadratic complexity by maintaining a temporary bit-set */
94+ ir_bitset set ;
95+
96+ if (!check_ctx -> input_set || !(set = check_ctx -> input_set [to ])) {
97+ if (!check_ctx -> arena ) {
98+ check_ctx -> arena = ir_arena_create (sizeof (ir_arena ) +
99+ ctx -> insns_count * sizeof (ir_bitset ) +
100+ ir_bitset_len (ctx -> insns_count ) * sizeof (ir_bitset_base_t ));
101+ }
102+ if (!check_ctx -> input_set ) {
103+ check_ctx -> input_set = ir_arena_alloc (& check_ctx -> arena , ctx -> insns_count * sizeof (ir_bitset ));
104+ memset (check_ctx -> input_set , 0 , ctx -> insns_count * sizeof (ir_bitset ));
105+ }
106+ check_ctx -> input_set [to ] = set = (ir_bitset )ir_arena_alloc (& check_ctx -> arena ,
107+ ir_bitset_len (ctx -> insns_count ) * sizeof (ir_bitset_base_t ));
108+ memset (set , 0 , ir_bitset_len (ctx -> insns_count ) * sizeof (ir_bitset_base_t ));
109+ for (j = 1 , p = insn -> ops + 1 ; j <= n ; j ++ , p ++ ) {
110+ if (* p > 0 ) ir_bitset_incl (set , * p );
111+ }
112+ }
113+ return ir_bitset_in (set , from );
114+ }
63115 for (j = 1 , p = insn -> ops + 1 ; j <= n ; j ++ , p ++ ) {
64116 if (* p == from ) {
65117 return 1 ;
@@ -93,6 +145,11 @@ bool ir_check(const ir_ctx *ctx)
93145 ir_type type ;
94146 uint32_t flags ;
95147 bool ok = 1 ;
148+ ir_check_ctx check_ctx ;
149+
150+ check_ctx .arena = NULL ;
151+ check_ctx .use_set = NULL ;
152+ check_ctx .input_set = NULL ;
96153
97154 for (i = IR_UNUSED + 1 , insn = ctx -> ir_base + i ; i < ctx -> insns_count ;) {
98155 if (insn -> op >= IR_LAST_OP ) {
@@ -255,7 +312,7 @@ bool ir_check(const ir_ctx *ctx)
255312 }
256313 if (ctx -> use_lists
257314 && use > 0
258- && !ir_check_use_list (ctx , use , i )) {
315+ && !ir_check_use_list (& check_ctx , ctx , use , i )) {
259316 fprintf (stderr , "ir_base[%d].ops[%d] is not in use list (%d)\n" , i , j , use );
260317 ok = 0 ;
261318 }
@@ -313,7 +370,7 @@ bool ir_check(const ir_ctx *ctx)
313370
314371 for (p = & ctx -> use_edges [use_list -> refs ]; n > 0 ; p ++ , n -- ) {
315372 use = * p ;
316- if (!ir_check_input_list (ctx , i , use )) {
373+ if (!ir_check_input_list (& check_ctx , ctx , i , use )) {
317374 fprintf (stderr , "ir_base[%d] is in use list of ir_base[%d]\n" , use , i );
318375 ok = 0 ;
319376 }
@@ -393,6 +450,10 @@ bool ir_check(const ir_ctx *ctx)
393450 insn += n ;
394451 }
395452
453+ if (check_ctx .arena ) {
454+ ir_arena_free (check_ctx .arena );
455+ }
456+
396457// if (!ok) {
397458// ir_dump_codegen(ctx, stderr);
398459// }
0 commit comments