@@ -40,12 +40,41 @@ void ir_consistency_check(void)
40
40
IR_ASSERT (IR_ADD + 1 == IR_SUB );
41
41
}
42
42
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 )
44
50
{
45
51
ir_ref n , * p ;
46
52
ir_use_list * use_list = & ctx -> use_lists [from ];
47
53
48
54
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
+ }
49
78
for (p = & ctx -> use_edges [use_list -> refs ]; n > 0 ; p ++ , n -- ) {
50
79
if (* p == to ) {
51
80
return 1 ;
@@ -54,12 +83,35 @@ static bool ir_check_use_list(const ir_ctx *ctx, ir_ref from, ir_ref to)
54
83
return 0 ;
55
84
}
56
85
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 )
58
87
{
59
88
ir_insn * insn = & ctx -> ir_base [to ];
60
89
ir_ref n , j , * p ;
61
90
62
91
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
+ }
63
115
for (j = 1 , p = insn -> ops + 1 ; j <= n ; j ++ , p ++ ) {
64
116
if (* p == from ) {
65
117
return 1 ;
@@ -93,6 +145,11 @@ bool ir_check(const ir_ctx *ctx)
93
145
ir_type type ;
94
146
uint32_t flags ;
95
147
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 ;
96
153
97
154
for (i = IR_UNUSED + 1 , insn = ctx -> ir_base + i ; i < ctx -> insns_count ;) {
98
155
if (insn -> op >= IR_LAST_OP ) {
@@ -255,7 +312,7 @@ bool ir_check(const ir_ctx *ctx)
255
312
}
256
313
if (ctx -> use_lists
257
314
&& use > 0
258
- && !ir_check_use_list (ctx , use , i )) {
315
+ && !ir_check_use_list (& check_ctx , ctx , use , i )) {
259
316
fprintf (stderr , "ir_base[%d].ops[%d] is not in use list (%d)\n" , i , j , use );
260
317
ok = 0 ;
261
318
}
@@ -313,7 +370,7 @@ bool ir_check(const ir_ctx *ctx)
313
370
314
371
for (p = & ctx -> use_edges [use_list -> refs ]; n > 0 ; p ++ , n -- ) {
315
372
use = * p ;
316
- if (!ir_check_input_list (ctx , i , use )) {
373
+ if (!ir_check_input_list (& check_ctx , ctx , i , use )) {
317
374
fprintf (stderr , "ir_base[%d] is in use list of ir_base[%d]\n" , use , i );
318
375
ok = 0 ;
319
376
}
@@ -393,6 +450,10 @@ bool ir_check(const ir_ctx *ctx)
393
450
insn += n ;
394
451
}
395
452
453
+ if (check_ctx .arena ) {
454
+ ir_arena_free (check_ctx .arena );
455
+ }
456
+
396
457
// if (!ok) {
397
458
// ir_dump_codegen(ctx, stderr);
398
459
// }
0 commit comments