@@ -251,10 +251,22 @@ static bool ir_sccp_meet_phi(ir_ctx *ctx, ir_insn *_values, ir_ref i, ir_insn *i
251
251
}
252
252
}
253
253
254
+ static bool ir_is_dead_load_ex (ir_ctx * ctx , ir_ref ref , uint32_t flags , ir_insn * insn )
255
+ {
256
+ if ((flags & (IR_OP_FLAG_MEM |IR_OP_FLAG_MEM_MASK )) == (IR_OP_FLAG_MEM |IR_OP_FLAG_MEM_LOAD )) {
257
+ return ctx -> use_lists [ref ].count == 1 ;
258
+ } else if (insn -> op == IR_ALLOCA ) {
259
+ return ctx -> use_lists [ref ].count == 1 ;
260
+ }
261
+ return 0 ;
262
+ }
263
+
254
264
static bool ir_is_dead_load (ir_ctx * ctx , ir_ref ref )
255
265
{
256
266
if (ctx -> use_lists [ref ].count == 1 ) {
257
- if ((ir_op_flags [ctx -> ir_base [ref ].op ] & (IR_OP_FLAG_MEM |IR_OP_FLAG_MEM_MASK )) == (IR_OP_FLAG_MEM |IR_OP_FLAG_MEM_LOAD )) {
267
+ uint32_t flags = ir_op_flags [ctx -> ir_base [ref ].op ];
268
+
269
+ if ((flags & (IR_OP_FLAG_MEM |IR_OP_FLAG_MEM_MASK )) == (IR_OP_FLAG_MEM |IR_OP_FLAG_MEM_LOAD )) {
258
270
return 1 ;
259
271
} else if (ctx -> ir_base [ref ].op == IR_ALLOCA ) {
260
272
return 1 ;
@@ -273,6 +285,25 @@ static bool ir_is_dead(ir_ctx *ctx, ir_ref ref)
273
285
return 0 ;
274
286
}
275
287
288
+ static ir_ref ir_find1 (ir_ctx * ctx , uint32_t optx , ir_ref op1 )
289
+ {
290
+ IR_ASSERT (!IR_IS_CONST_REF (op1 ));
291
+
292
+ ir_use_list * use_list = & ctx -> use_lists [op1 ];
293
+ ir_ref * p , n = use_list -> count ;
294
+
295
+ for (p = ctx -> use_edges + use_list -> refs ; n > 0 ; p ++ , n -- ) {
296
+ ir_ref use = * p ;
297
+ ir_insn * use_insn = & ctx -> ir_base [use ];
298
+
299
+ if (use_insn -> optx == optx ) {
300
+ IR_ASSERT (use_insn -> op1 == op1 );
301
+ return use ;
302
+ }
303
+ }
304
+ return IR_UNUSED ;
305
+ }
306
+
276
307
static bool ir_sccp_is_true (ir_ctx * ctx , ir_insn * _values , ir_ref a )
277
308
{
278
309
ir_insn * v = IR_IS_CONST_REF (a ) ? & ctx -> ir_base [a ] : & _values [a ];
@@ -285,6 +316,8 @@ static bool ir_sccp_is_equal(ir_ctx *ctx, ir_insn *_values, ir_ref a, ir_ref b)
285
316
ir_insn * v1 = IR_IS_CONST_REF (a ) ? & ctx -> ir_base [a ] : & _values [a ];
286
317
ir_insn * v2 = IR_IS_CONST_REF (b ) ? & ctx -> ir_base [b ] : & _values [b ];
287
318
319
+ IR_ASSERT (!IR_IS_SYM_CONST (v1 -> op ));
320
+ IR_ASSERT (!IR_IS_SYM_CONST (v2 -> op ));
288
321
return v1 -> val .u64 == v2 -> val .u64 ;
289
322
}
290
323
@@ -316,10 +349,8 @@ static void ir_sccp_remove_insn(ir_ctx *ctx, ir_insn *_values, ir_ref ref, ir_bi
316
349
* p = IR_UNUSED ;
317
350
if (input > 0 && _values [input ].op == IR_BOTTOM ) {
318
351
ir_use_list_remove_all (ctx , input , ref );
319
- /* schedule DCE */
320
- if ((IR_IS_FOLDABLE_OP (ctx -> ir_base [input ].op ) && ctx -> use_lists [input ].count == 0 )
321
- || ((ir_op_flags [ctx -> ir_base [input ].op ] & (IR_OP_FLAG_MEM |IR_OP_FLAG_MEM_MASK )) == (IR_OP_FLAG_MEM |IR_OP_FLAG_MEM_LOAD )
322
- && ctx -> use_lists [input ].count == 1 )) {
352
+ if (ir_is_dead (ctx , input )) {
353
+ /* schedule DCE */
323
354
ir_bitqueue_add (worklist , input );
324
355
}
325
356
}
@@ -340,12 +371,11 @@ static void ir_sccp_remove_insn2(ir_ctx *ctx, ir_ref ref, ir_bitqueue *worklist)
340
371
* p = IR_UNUSED ;
341
372
if (input > 0 ) {
342
373
ir_use_list_remove_all (ctx , input , ref );
343
- /* schedule DCE */
344
- if ((IR_IS_FOLDABLE_OP (ctx -> ir_base [input ].op ) && ctx -> use_lists [input ].count == 0 )
345
- || ((ir_op_flags [ctx -> ir_base [input ].op ] & (IR_OP_FLAG_MEM |IR_OP_FLAG_MEM_MASK )) == (IR_OP_FLAG_MEM |IR_OP_FLAG_MEM_LOAD )
346
- && ctx -> use_lists [input ].count == 1 )) {
374
+ if (ir_is_dead (ctx , input )) {
375
+ /* schedule DCE */
347
376
ir_bitqueue_add (worklist , input );
348
377
} else if (ctx -> ir_base [input ].op == IR_PHI && ctx -> use_lists [input ].count == 1 ) {
378
+ /* try to optimize PHI into ABS/MIN/MAX/COND */
349
379
ir_bitqueue_add (worklist , ctx -> ir_base [input ].op1 );
350
380
}
351
381
}
@@ -368,12 +398,11 @@ static void ir_sccp_replace_insn(ir_ctx *ctx, ir_insn *_values, ir_ref ref, ir_r
368
398
* p = IR_UNUSED ;
369
399
if (input > 0 ) {
370
400
ir_use_list_remove_all (ctx , input , ref );
371
- /* schedule DCE */
372
- if (worklist
373
- && ((IR_IS_FOLDABLE_OP (ctx -> ir_base [input ].op ) && ctx -> use_lists [input ].count == 0 )
374
- || ((ir_op_flags [ctx -> ir_base [input ].op ] & (IR_OP_FLAG_MEM |IR_OP_FLAG_MEM_MASK )) == (IR_OP_FLAG_MEM |IR_OP_FLAG_MEM_LOAD )
375
- && ctx -> use_lists [input ].count == 1 ))) {
376
- ir_bitqueue_add (worklist , input );
401
+ if (_values [input ].op == IR_BOTTOM ) {
402
+ if (ir_is_dead (ctx , input )) {
403
+ /* schedule DCE */
404
+ ir_bitqueue_add (worklist , input );
405
+ }
377
406
}
378
407
}
379
408
}
@@ -426,10 +455,11 @@ static void ir_sccp_replace_insn2(ir_ctx *ctx, ir_ref ref, ir_ref new_ref, ir_bi
426
455
* p = IR_UNUSED ;
427
456
if (input > 0 ) {
428
457
ir_use_list_remove_all (ctx , input , ref );
429
- /* schedule DCE */
430
- if ((IR_IS_FOLDABLE_OP (ctx -> ir_base [input ].op ) && ctx -> use_lists [input ].count == 0 )
431
- || ((ir_op_flags [ctx -> ir_base [input ].op ] & (IR_OP_FLAG_MEM |IR_OP_FLAG_MEM_MASK )) == (IR_OP_FLAG_MEM |IR_OP_FLAG_MEM_LOAD )
432
- && ctx -> use_lists [input ].count == 1 )) {
458
+ if (ir_is_dead (ctx , input )) {
459
+ /* schedule DCE */
460
+ ir_bitqueue_add (worklist , input );
461
+ } else if (ctx -> ir_base [input ].op == IR_PHI && ctx -> use_lists [input ].count == 1 ) {
462
+ /* try to optimize PHI into ABS/MIN/MAX/COND */
433
463
ir_bitqueue_add (worklist , input );
434
464
}
435
465
}
@@ -833,6 +863,7 @@ static ir_ref ir_promote_f2d(ir_ctx *ctx, ir_ref ref, ir_ref use)
833
863
{
834
864
ir_insn * insn = & ctx -> ir_base [ref ];
835
865
uint32_t count ;
866
+ ir_ref old_ref ;
836
867
837
868
IR_ASSERT (insn -> type == IR_FLOAT );
838
869
if (IR_IS_CONST_REF (ref )) {
@@ -863,6 +894,15 @@ static ir_ref ir_promote_f2d(ir_ctx *ctx, ir_ref ref, ir_ref use)
863
894
}
864
895
return insn -> op1 ;
865
896
case IR_INT2FP :
897
+ old_ref = ir_find1 (ctx , IR_OPTX (IR_INT2FP , IR_DOUBLE , 1 ), insn -> op1 );
898
+ if (old_ref ) {
899
+ IR_ASSERT (ctx -> use_lists [ref ].count == 1 );
900
+ ir_use_list_remove_one (ctx , insn -> op1 , ref );
901
+ CLEAR_USES (ref );
902
+ MAKE_NOP (insn );
903
+ ir_use_list_add (ctx , old_ref , use );
904
+ return old_ref ;
905
+ }
866
906
insn -> type = IR_DOUBLE ;
867
907
return ref ;
868
908
case IR_NEG :
@@ -1030,36 +1070,28 @@ static ir_ref ir_ext_const(ir_ctx *ctx, ir_insn *val_insn, ir_op op, ir_type typ
1030
1070
static ir_ref ir_ext_ref (ir_ctx * ctx , ir_ref var_ref , ir_ref src_ref , ir_op op , ir_type type )
1031
1071
{
1032
1072
uint32_t optx = IR_OPTX (op , type , 1 );
1033
- ir_ref new_ext_ref ;
1073
+ ir_ref ref ;
1034
1074
1035
1075
if (!IR_IS_CONST_REF (src_ref )) {
1036
- ir_use_list * use_list = & ctx -> use_lists [src_ref ];
1037
- ir_ref * p , n = use_list -> count ;
1038
-
1039
- for (p = ctx -> use_edges + use_list -> refs ; n > 0 ; p ++ , n -- ) {
1040
- ir_ref use = * p ;
1041
- ir_insn * use_insn = & ctx -> ir_base [use ];
1042
-
1043
- if (use_insn -> optx == optx ) {
1044
- IR_ASSERT (use_insn -> op1 == src_ref );
1045
- ir_use_list_add (ctx , use , var_ref );
1046
- if (!IR_IS_CONST_REF (src_ref )) {
1047
- ir_use_list_remove_one (ctx , src_ref , var_ref );
1048
- }
1049
- return use ;
1076
+ ref = ir_find1 (ctx , optx , src_ref );
1077
+ if (ref ) {
1078
+ ir_use_list_add (ctx , ref , var_ref );
1079
+ if (!IR_IS_CONST_REF (src_ref )) {
1080
+ ir_use_list_remove_one (ctx , src_ref , var_ref );
1050
1081
}
1082
+ return ref ;
1051
1083
}
1052
1084
}
1053
1085
1054
- new_ext_ref = ir_emit1 (ctx , optx , src_ref );
1086
+ ref = ir_emit1 (ctx , optx , src_ref );
1055
1087
ctx -> use_lists = ir_mem_realloc (ctx -> use_lists , ctx -> insns_count * sizeof (ir_use_list ));
1056
- ctx -> use_lists [new_ext_ref ].count = 0 ;
1057
- ctx -> use_lists [new_ext_ref ].refs = IR_UNUSED ;
1058
- ir_use_list_add (ctx , new_ext_ref , var_ref );
1088
+ ctx -> use_lists [ref ].count = 0 ;
1089
+ ctx -> use_lists [ref ].refs = IR_UNUSED ;
1090
+ ir_use_list_add (ctx , ref , var_ref );
1059
1091
if (!IR_IS_CONST_REF (src_ref )) {
1060
- ir_use_list_replace_one (ctx , src_ref , var_ref , new_ext_ref );
1092
+ ir_use_list_replace_one (ctx , src_ref , var_ref , ref );
1061
1093
}
1062
- return new_ext_ref ;
1094
+ return ref ;
1063
1095
}
1064
1096
1065
1097
static bool ir_try_promote_ext (ir_ctx * ctx , ir_ref ext_ref , ir_insn * insn , ir_bitqueue * worklist )
@@ -1111,10 +1143,9 @@ static bool ir_try_promote_ext(ir_ctx *ctx, ir_ref ext_ref, ir_insn *insn, ir_bi
1111
1143
phi_insn -> type = insn -> type ;
1112
1144
op_insn -> type = insn -> type ;
1113
1145
1114
- use_list = & ctx -> use_lists [ref ];
1115
- n = use_list -> count ;
1116
- for (p = & ctx -> use_edges [use_list -> refs ]; n > 0 ; p ++ , n -- ) {
1117
- use = * p ;
1146
+ for (n = 0 ; n < ctx -> use_lists [ref ].count ; n ++ ) {
1147
+ /* "use_lists" may be reallocated by ir_ext_ref() */
1148
+ use = ctx -> use_edges [ctx -> use_lists [ref ].refs + n ];
1118
1149
if (use == ext_ref ) {
1119
1150
continue ;
1120
1151
} else {
@@ -2320,9 +2351,7 @@ int ir_sccp(ir_ctx *ctx)
2320
2351
}
2321
2352
}
2322
2353
IR_MAKE_BOTTOM (i );
2323
- } else if (((flags & (IR_OP_FLAG_MEM |IR_OP_FLAG_MEM_MASK )) == (IR_OP_FLAG_MEM |IR_OP_FLAG_MEM_LOAD )
2324
- || insn -> op == IR_ALLOCA )
2325
- && ctx -> use_lists [i ].count == 1 ) {
2354
+ } else if (ir_is_dead_load_ex (ctx , i , flags , insn )) {
2326
2355
/* dead load */
2327
2356
_values [i ].optx = IR_LOAD ;
2328
2357
} else {
@@ -2430,7 +2459,7 @@ int ir_sccp(ir_ctx *ctx)
2430
2459
}
2431
2460
}
2432
2461
}
2433
- ir_sccp_replace_insn (ctx , _values , i , IR_UNUSED , NULL );
2462
+ ir_sccp_replace_insn (ctx , _values , i , IR_UNUSED , & worklist2 );
2434
2463
}
2435
2464
} else if (value -> op == IR_IF ) {
2436
2465
/* remove one way IF/SWITCH */
@@ -2523,10 +2552,7 @@ int ir_sccp(ir_ctx *ctx)
2523
2552
} else if (insn -> op == IR_MERGE ) {
2524
2553
ir_optimize_merge (ctx , i , insn , & worklist2 );
2525
2554
}
2526
- } else if (((ir_op_flags [insn -> op ] & (IR_OP_FLAG_MEM |IR_OP_FLAG_MEM_MASK )) == (IR_OP_FLAG_MEM |IR_OP_FLAG_MEM_LOAD )
2527
- || insn -> op == IR_ALLOCA )
2528
- && ctx -> use_lists [i ].count == 1 ) {
2529
- /* dead load */
2555
+ } else if (ir_is_dead_load (ctx , i )) {
2530
2556
ir_ref next = ctx -> use_edges [ctx -> use_lists [i ].refs ];
2531
2557
2532
2558
/* remove LOAD from double linked control list */
0 commit comments