@@ -967,6 +967,145 @@ static ir_ref ir_promote_i2i(ir_ctx *ctx, ir_type type, ir_ref ref, ir_ref use)
967
967
return ref ;
968
968
}
969
969
970
+ static ir_ref ir_ext_const (ir_ctx * ctx , ir_insn * val_insn , ir_op op , ir_type type )
971
+ {
972
+ ir_val new_val ;
973
+
974
+ switch (val_insn -> type ) {
975
+ default :
976
+ IR_ASSERT (0 );
977
+ case IR_I8 :
978
+ case IR_U8 :
979
+ case IR_BOOL :
980
+ if (op == IR_SEXT ) {
981
+ new_val .i64 = (int64_t )val_insn -> val .i8 ;
982
+ } else {
983
+ new_val .u64 = (uint64_t )val_insn -> val .u8 ;
984
+ }
985
+ break ;
986
+ case IR_I16 :
987
+ case IR_U16 :
988
+ if (op == IR_SEXT ) {
989
+ new_val .i64 = (int64_t )val_insn -> val .i16 ;
990
+ } else {
991
+ new_val .u64 = (uint64_t )val_insn -> val .u16 ;
992
+ }
993
+ break ;
994
+ case IR_I32 :
995
+ case IR_U32 :
996
+ if (op == IR_SEXT ) {
997
+ new_val .i64 = (int64_t )val_insn -> val .i32 ;
998
+ } else {
999
+ new_val .u64 = (uint64_t )val_insn -> val .u32 ;
1000
+ }
1001
+ break ;
1002
+ }
1003
+ return ir_const (ctx , new_val , type );
1004
+ }
1005
+
1006
+ static ir_ref ir_ext_ref (ir_ctx * ctx , ir_ref var_ref , ir_ref src_ref , ir_op op , ir_type type )
1007
+ {
1008
+ ir_ref new_ext_ref = ir_emit1 (ctx , IR_OPTX (op , type , 1 ), src_ref );
1009
+
1010
+ ctx -> use_lists = ir_mem_realloc (ctx -> use_lists , ctx -> insns_count * sizeof (ir_use_list ));
1011
+ ctx -> use_lists [new_ext_ref ].count = 0 ;
1012
+ ctx -> use_lists [new_ext_ref ].refs = IR_UNUSED ;
1013
+ ir_use_list_add (ctx , new_ext_ref , var_ref );
1014
+ if (!IR_IS_CONST_REF (src_ref )) {
1015
+ ir_use_list_replace_one (ctx , src_ref , var_ref , new_ext_ref );
1016
+ }
1017
+ return new_ext_ref ;
1018
+ }
1019
+
1020
+ static bool ir_try_promote_ext (ir_ctx * ctx , ir_ref ext_ref , ir_insn * insn , ir_bitqueue * worklist )
1021
+ {
1022
+ ir_type type = insn -> type ;
1023
+ ir_op op = insn -> op ;
1024
+ ir_ref ref = insn -> op1 ;
1025
+ ir_insn * phi_insn = & ctx -> ir_base [ref ];
1026
+ ir_insn * op_insn ;
1027
+ ir_use_list * use_list ;
1028
+ ir_ref n , * p , use , op_ref ;
1029
+
1030
+ /* Check for simple induction variable in the form: x2 = PHI(loop, x1, x3); x3 = ADD(x2, _); */
1031
+ if (phi_insn -> op != IR_PHI
1032
+ || phi_insn -> inputs_count != 3 /* (2 values) */
1033
+ || ctx -> ir_base [phi_insn -> op1 ].op != IR_LOOP_BEGIN ) {
1034
+ return 0 ;
1035
+ }
1036
+
1037
+ op_ref = phi_insn -> op3 ;
1038
+ op_insn = & ctx -> ir_base [op_ref ];
1039
+ if ((op_insn -> op != IR_ADD && op_insn -> op != IR_SUB && op_insn -> op != IR_MUL )
1040
+ || op_insn -> op1 != ref
1041
+ || op_insn -> op2 == ref
1042
+ || ctx -> use_lists [op_ref ].count != 1 ) {
1043
+ return 0 ;
1044
+ }
1045
+
1046
+ /* Check if we may change the type of the induction variable */
1047
+ use_list = & ctx -> use_lists [ref ];
1048
+ n = use_list -> count ;
1049
+ for (p = & ctx -> use_edges [use_list -> refs ]; n > 0 ; p ++ , n -- ) {
1050
+ use = * p ;
1051
+ if (use == op_ref || use == ext_ref ) {
1052
+ continue ;
1053
+ } else {
1054
+ ir_insn * use_insn = & ctx -> ir_base [use ];
1055
+
1056
+ if ((use_insn -> op >= IR_EQ && use_insn -> op <= IR_UGT )
1057
+ && use_insn -> op1 == ref
1058
+ && use_insn -> op2 != ref ) {
1059
+ continue ;
1060
+ } else if (use_insn -> op == IR_IF ) {
1061
+ continue ;
1062
+ } else {
1063
+ return 0 ;
1064
+ }
1065
+ }
1066
+ }
1067
+
1068
+ phi_insn -> type = insn -> type ;
1069
+ op_insn -> type = insn -> type ;
1070
+
1071
+ use_list = & ctx -> use_lists [ref ];
1072
+ n = use_list -> count ;
1073
+ for (p = & ctx -> use_edges [use_list -> refs ]; n > 0 ; p ++ , n -- ) {
1074
+ use = * p ;
1075
+ if (use == ext_ref ) {
1076
+ continue ;
1077
+ } else {
1078
+ ir_insn * use_insn = & ctx -> ir_base [use ];
1079
+
1080
+ if (use_insn -> op == IR_IF ) {
1081
+ continue ;
1082
+ }
1083
+ IR_ASSERT (((use_insn -> op >= IR_EQ && use_insn -> op <= IR_UGT )
1084
+ || use_insn -> op == IR_ADD || use_insn -> op == IR_SUB || use_insn -> op == IR_MUL )
1085
+ && use_insn -> op1 == ref
1086
+ && use_insn -> op2 != ref );
1087
+ if (IR_IS_CONST_REF (use_insn -> op2 )
1088
+ && !IR_IS_SYM_CONST (ctx -> ir_base [use_insn -> op2 ].op )) {
1089
+ ctx -> ir_base [use ].op2 = ir_ext_const (ctx , & ctx -> ir_base [use_insn -> op2 ], op , type );
1090
+ } else {
1091
+ ctx -> ir_base [use ].op2 = ir_ext_ref (ctx , use , use_insn -> op2 , op , type );
1092
+ }
1093
+ }
1094
+ }
1095
+
1096
+ ir_sccp_replace_insn2 (ctx , ext_ref , ref , worklist );
1097
+
1098
+ phi_insn = & ctx -> ir_base [ref ];
1099
+ if (IR_IS_CONST_REF (phi_insn -> op2 )
1100
+ && !IR_IS_SYM_CONST (ctx -> ir_base [phi_insn -> op2 ].op )) {
1101
+ ctx -> ir_base [ref ].op2 = ir_ext_const (ctx , & ctx -> ir_base [phi_insn -> op2 ], op , type );
1102
+ } else {
1103
+ ctx -> ir_base [ref ].op2 = ir_ext_ref (ctx , ref , phi_insn -> op2 , op , type );
1104
+ }
1105
+
1106
+ return 1 ;
1107
+ }
1108
+
970
1109
int ir_sccp (ir_ctx * ctx )
971
1110
{
972
1111
ir_ref i , j , n , * p , use ;
@@ -1025,12 +1164,18 @@ int ir_sccp(ir_ctx *ctx)
1025
1164
}
1026
1165
if (!may_benefit ) {
1027
1166
IR_MAKE_BOTTOM (i );
1028
- if (insn -> op == IR_FP2FP || insn -> op == IR_FP2INT || insn -> op == IR_TRUNC ) {
1167
+ if (insn -> op == IR_FP2FP || insn -> op == IR_FP2INT || insn -> op == IR_TRUNC
1168
+ || insn -> op == IR_ZEXT || insn -> op == IR_SEXT ) {
1029
1169
ir_bitqueue_add (& worklist2 , i );
1030
1170
}
1031
1171
} else if (!ir_sccp_fold (ctx , _values , i , insn -> opt , insn -> op1 , insn -> op2 , insn -> op3 )) {
1032
1172
/* not changed */
1033
1173
continue ;
1174
+ } else if (_values [i ].optx == IR_BOTTOM ) {
1175
+ if (insn -> op == IR_FP2FP || insn -> op == IR_FP2INT || insn -> op == IR_TRUNC
1176
+ || insn -> op == IR_ZEXT || insn -> op == IR_SEXT ) {
1177
+ ir_bitqueue_add (& worklist2 , i );
1178
+ }
1034
1179
}
1035
1180
} else {
1036
1181
IR_MAKE_BOTTOM (i );
@@ -1298,15 +1443,17 @@ int ir_sccp(ir_ctx *ctx)
1298
1443
ir_ref ref = ir_promote_d2f (ctx , insn -> op1 , i );
1299
1444
insn -> op1 = ref ;
1300
1445
ir_sccp_replace_insn2 (ctx , i , ref , & worklist2 );
1446
+ break ;
1301
1447
}
1302
1448
} else {
1303
1449
if (ir_may_promote_f2d (ctx , insn -> op1 )) {
1304
1450
ir_ref ref = ir_promote_f2d (ctx , insn -> op1 , i );
1305
1451
insn -> op1 = ref ;
1306
1452
ir_sccp_replace_insn2 (ctx , i , ref , & worklist2 );
1453
+ break ;
1307
1454
}
1308
1455
}
1309
- break ;
1456
+ goto folding ;
1310
1457
case IR_FP2INT :
1311
1458
if (ctx -> ir_base [insn -> op1 ].type == IR_DOUBLE ) {
1312
1459
if (ir_may_promote_d2f (ctx , insn -> op1 )) {
@@ -1317,15 +1464,25 @@ int ir_sccp(ir_ctx *ctx)
1317
1464
insn -> op1 = ir_promote_f2d (ctx , insn -> op1 , i );
1318
1465
}
1319
1466
}
1320
- break ;
1467
+ goto folding ;
1321
1468
case IR_TRUNC :
1322
1469
if (ir_may_promote_i2i (ctx , insn -> type , insn -> op1 )) {
1323
1470
ir_ref ref = ir_promote_i2i (ctx , insn -> type , insn -> op1 , i );
1324
1471
insn -> op1 = ref ;
1325
1472
ir_sccp_replace_insn2 (ctx , i , ref , & worklist2 );
1473
+ break ;
1474
+ }
1475
+ goto folding ;
1476
+ case IR_SEXT :
1477
+ case IR_ZEXT :
1478
+ if (ir_try_promote_ext (ctx , i , insn , & worklist2 )) {
1479
+ break ;
1326
1480
}
1481
+ goto folding ;
1482
+ case IR_PHI :
1327
1483
break ;
1328
1484
default :
1485
+ folding :
1329
1486
ir_sccp_fold2 (ctx , i , & worklist2 );
1330
1487
break ;
1331
1488
}
0 commit comments