@@ -625,9 +625,15 @@ static bool do_constant_folding_cond_32(uint32_t x, uint32_t y, TCGCond c)
625
625
return x <= y ;
626
626
case TCG_COND_GTU :
627
627
return x > y ;
628
- default :
629
- g_assert_not_reached ();
628
+ case TCG_COND_TSTEQ :
629
+ return (x & y ) == 0 ;
630
+ case TCG_COND_TSTNE :
631
+ return (x & y ) != 0 ;
632
+ case TCG_COND_ALWAYS :
633
+ case TCG_COND_NEVER :
634
+ break ;
630
635
}
636
+ g_assert_not_reached ();
631
637
}
632
638
633
639
static bool do_constant_folding_cond_64 (uint64_t x , uint64_t y , TCGCond c )
@@ -653,12 +659,18 @@ static bool do_constant_folding_cond_64(uint64_t x, uint64_t y, TCGCond c)
653
659
return x <= y ;
654
660
case TCG_COND_GTU :
655
661
return x > y ;
656
- default :
657
- g_assert_not_reached ();
662
+ case TCG_COND_TSTEQ :
663
+ return (x & y ) == 0 ;
664
+ case TCG_COND_TSTNE :
665
+ return (x & y ) != 0 ;
666
+ case TCG_COND_ALWAYS :
667
+ case TCG_COND_NEVER :
668
+ break ;
658
669
}
670
+ g_assert_not_reached ();
659
671
}
660
672
661
- static bool do_constant_folding_cond_eq (TCGCond c )
673
+ static int do_constant_folding_cond_eq (TCGCond c )
662
674
{
663
675
switch (c ) {
664
676
case TCG_COND_GT :
@@ -673,9 +685,14 @@ static bool do_constant_folding_cond_eq(TCGCond c)
673
685
case TCG_COND_LEU :
674
686
case TCG_COND_EQ :
675
687
return 1 ;
676
- default :
677
- g_assert_not_reached ();
688
+ case TCG_COND_TSTEQ :
689
+ case TCG_COND_TSTNE :
690
+ return -1 ;
691
+ case TCG_COND_ALWAYS :
692
+ case TCG_COND_NEVER :
693
+ break ;
678
694
}
695
+ g_assert_not_reached ();
679
696
}
680
697
681
698
/*
@@ -703,8 +720,10 @@ static int do_constant_folding_cond(TCGType type, TCGArg x,
703
720
} else if (arg_is_const_val (y , 0 )) {
704
721
switch (c ) {
705
722
case TCG_COND_LTU :
723
+ case TCG_COND_TSTNE :
706
724
return 0 ;
707
725
case TCG_COND_GEU :
726
+ case TCG_COND_TSTEQ :
708
727
return 1 ;
709
728
default :
710
729
return -1 ;
@@ -777,14 +796,38 @@ static int do_constant_folding_cond1(OptContext *ctx, TCGArg dest,
777
796
}
778
797
779
798
r = do_constant_folding_cond (ctx -> type , * p1 , * p2 , cond );
780
- return r ;
799
+ if (r >= 0 ) {
800
+ return r ;
801
+ }
802
+ if (!is_tst_cond (cond )) {
803
+ return -1 ;
804
+ }
805
+
806
+ /*
807
+ * TSTNE x,x -> NE x,0
808
+ * TSTNE x,-1 -> NE x,0
809
+ */
810
+ if (args_are_copies (* p1 , * p2 ) || arg_is_const_val (* p2 , -1 )) {
811
+ * p2 = arg_new_constant (ctx , 0 );
812
+ * pcond = tcg_tst_eqne_cond (cond );
813
+ return -1 ;
814
+ }
815
+
816
+ /* TSTNE x,sign -> LT x,0 */
817
+ if (arg_is_const_val (* p2 , (ctx -> type == TCG_TYPE_I32
818
+ ? INT32_MIN : INT64_MIN ))) {
819
+ * p2 = arg_new_constant (ctx , 0 );
820
+ * pcond = tcg_tst_ltge_cond (cond );
821
+ }
822
+ return -1 ;
781
823
}
782
824
783
825
static int do_constant_folding_cond2 (OptContext * ctx , TCGArg * args )
784
826
{
785
827
TCGArg al , ah , bl , bh ;
786
828
TCGCond c ;
787
829
bool swap ;
830
+ int r ;
788
831
789
832
swap = swap_commutative2 (args , args + 2 );
790
833
c = args [4 ];
@@ -806,21 +849,54 @@ static int do_constant_folding_cond2(OptContext *ctx, TCGArg *args)
806
849
tcg_target_ulong alv = arg_info (al )-> val ;
807
850
tcg_target_ulong ahv = arg_info (ah )-> val ;
808
851
uint64_t a = deposit64 (alv , 32 , 32 , ahv );
809
- return do_constant_folding_cond_64 (a , b , c );
852
+
853
+ r = do_constant_folding_cond_64 (a , b , c );
854
+ if (r >= 0 ) {
855
+ return r ;
856
+ }
810
857
}
858
+
811
859
if (b == 0 ) {
812
860
switch (c ) {
813
861
case TCG_COND_LTU :
862
+ case TCG_COND_TSTNE :
814
863
return 0 ;
815
864
case TCG_COND_GEU :
865
+ case TCG_COND_TSTEQ :
816
866
return 1 ;
817
867
default :
818
868
break ;
819
869
}
820
870
}
871
+
872
+ /* TSTNE x,-1 -> NE x,0 */
873
+ if (b == -1 && is_tst_cond (c )) {
874
+ args [3 ] = args [2 ] = arg_new_constant (ctx , 0 );
875
+ args [4 ] = tcg_tst_eqne_cond (c );
876
+ return -1 ;
877
+ }
878
+
879
+ /* TSTNE x,sign -> LT x,0 */
880
+ if (b == INT64_MIN && is_tst_cond (c )) {
881
+ /* bl must be 0, so copy that to bh */
882
+ args [3 ] = bl ;
883
+ args [4 ] = tcg_tst_ltge_cond (c );
884
+ return -1 ;
885
+ }
821
886
}
887
+
822
888
if (args_are_copies (al , bl ) && args_are_copies (ah , bh )) {
823
- return do_constant_folding_cond_eq (c );
889
+ r = do_constant_folding_cond_eq (c );
890
+ if (r >= 0 ) {
891
+ return r ;
892
+ }
893
+
894
+ /* TSTNE x,x -> NE x,0 */
895
+ if (is_tst_cond (c )) {
896
+ args [3 ] = args [2 ] = arg_new_constant (ctx , 0 );
897
+ args [4 ] = tcg_tst_eqne_cond (c );
898
+ return -1 ;
899
+ }
824
900
}
825
901
return -1 ;
826
902
}
@@ -1284,24 +1360,37 @@ static bool fold_brcond2(OptContext *ctx, TCGOp *op)
1284
1360
case 0 :
1285
1361
goto do_brcond_const ;
1286
1362
case 1 :
1287
- op -> opc = INDEX_op_brcond_i32 ;
1288
- op -> args [1 ] = op -> args [2 ];
1289
- op -> args [2 ] = cond ;
1290
- op -> args [3 ] = label ;
1291
- break ;
1363
+ goto do_brcond_low ;
1364
+ }
1365
+ break ;
1366
+
1367
+ case TCG_COND_TSTEQ :
1368
+ case TCG_COND_TSTNE :
1369
+ if (arg_is_const_val (op -> args [2 ], 0 )) {
1370
+ goto do_brcond_high ;
1371
+ }
1372
+ if (arg_is_const_val (op -> args [3 ], 0 )) {
1373
+ goto do_brcond_low ;
1292
1374
}
1293
1375
break ;
1294
1376
1295
1377
default :
1296
1378
break ;
1297
1379
1380
+ do_brcond_low :
1381
+ op -> opc = INDEX_op_brcond_i32 ;
1382
+ op -> args [1 ] = op -> args [2 ];
1383
+ op -> args [2 ] = cond ;
1384
+ op -> args [3 ] = label ;
1385
+ return fold_brcond (ctx , op );
1386
+
1298
1387
do_brcond_high :
1299
1388
op -> opc = INDEX_op_brcond_i32 ;
1300
1389
op -> args [0 ] = op -> args [1 ];
1301
1390
op -> args [1 ] = op -> args [3 ];
1302
1391
op -> args [2 ] = cond ;
1303
1392
op -> args [3 ] = label ;
1304
- break ;
1393
+ return fold_brcond ( ctx , op ) ;
1305
1394
1306
1395
do_brcond_const :
1307
1396
if (i == 0 ) {
@@ -1967,13 +2056,107 @@ static bool fold_remainder(OptContext *ctx, TCGOp *op)
1967
2056
return false;
1968
2057
}
1969
2058
2059
+ static void fold_setcond_tst_pow2 (OptContext * ctx , TCGOp * op , bool neg )
2060
+ {
2061
+ TCGOpcode and_opc , sub_opc , xor_opc , neg_opc , shr_opc , uext_opc , sext_opc ;
2062
+ TCGCond cond = op -> args [3 ];
2063
+ TCGArg ret , src1 , src2 ;
2064
+ TCGOp * op2 ;
2065
+ uint64_t val ;
2066
+ int sh ;
2067
+ bool inv ;
2068
+
2069
+ if (!is_tst_cond (cond ) || !arg_is_const (op -> args [2 ])) {
2070
+ return ;
2071
+ }
2072
+
2073
+ src2 = op -> args [2 ];
2074
+ val = arg_info (src2 )-> val ;
2075
+ if (!is_power_of_2 (val )) {
2076
+ return ;
2077
+ }
2078
+ sh = ctz64 (val );
2079
+
2080
+ switch (ctx -> type ) {
2081
+ case TCG_TYPE_I32 :
2082
+ and_opc = INDEX_op_and_i32 ;
2083
+ sub_opc = INDEX_op_sub_i32 ;
2084
+ xor_opc = INDEX_op_xor_i32 ;
2085
+ shr_opc = INDEX_op_shr_i32 ;
2086
+ neg_opc = INDEX_op_neg_i32 ;
2087
+ if (TCG_TARGET_extract_i32_valid (sh , 1 )) {
2088
+ uext_opc = TCG_TARGET_HAS_extract_i32 ? INDEX_op_extract_i32 : 0 ;
2089
+ sext_opc = TCG_TARGET_HAS_sextract_i32 ? INDEX_op_sextract_i32 : 0 ;
2090
+ }
2091
+ break ;
2092
+ case TCG_TYPE_I64 :
2093
+ and_opc = INDEX_op_and_i64 ;
2094
+ sub_opc = INDEX_op_sub_i64 ;
2095
+ xor_opc = INDEX_op_xor_i64 ;
2096
+ shr_opc = INDEX_op_shr_i64 ;
2097
+ neg_opc = INDEX_op_neg_i64 ;
2098
+ if (TCG_TARGET_extract_i64_valid (sh , 1 )) {
2099
+ uext_opc = TCG_TARGET_HAS_extract_i64 ? INDEX_op_extract_i64 : 0 ;
2100
+ sext_opc = TCG_TARGET_HAS_sextract_i64 ? INDEX_op_sextract_i64 : 0 ;
2101
+ }
2102
+ break ;
2103
+ default :
2104
+ g_assert_not_reached ();
2105
+ }
2106
+
2107
+ ret = op -> args [0 ];
2108
+ src1 = op -> args [1 ];
2109
+ inv = cond == TCG_COND_TSTEQ ;
2110
+
2111
+ if (sh && sext_opc && neg && !inv ) {
2112
+ op -> opc = sext_opc ;
2113
+ op -> args [1 ] = src1 ;
2114
+ op -> args [2 ] = sh ;
2115
+ op -> args [3 ] = 1 ;
2116
+ return ;
2117
+ } else if (sh && uext_opc ) {
2118
+ op -> opc = uext_opc ;
2119
+ op -> args [1 ] = src1 ;
2120
+ op -> args [2 ] = sh ;
2121
+ op -> args [3 ] = 1 ;
2122
+ } else {
2123
+ if (sh ) {
2124
+ op2 = tcg_op_insert_before (ctx -> tcg , op , shr_opc , 3 );
2125
+ op2 -> args [0 ] = ret ;
2126
+ op2 -> args [1 ] = src1 ;
2127
+ op2 -> args [2 ] = arg_new_constant (ctx , sh );
2128
+ src1 = ret ;
2129
+ }
2130
+ op -> opc = and_opc ;
2131
+ op -> args [1 ] = src1 ;
2132
+ op -> args [2 ] = arg_new_constant (ctx , 1 );
2133
+ }
2134
+
2135
+ if (neg && inv ) {
2136
+ op2 = tcg_op_insert_after (ctx -> tcg , op , sub_opc , 3 );
2137
+ op2 -> args [0 ] = ret ;
2138
+ op2 -> args [1 ] = ret ;
2139
+ op2 -> args [2 ] = arg_new_constant (ctx , 1 );
2140
+ } else if (inv ) {
2141
+ op2 = tcg_op_insert_after (ctx -> tcg , op , xor_opc , 3 );
2142
+ op2 -> args [0 ] = ret ;
2143
+ op2 -> args [1 ] = ret ;
2144
+ op2 -> args [2 ] = arg_new_constant (ctx , 1 );
2145
+ } else if (neg ) {
2146
+ op2 = tcg_op_insert_after (ctx -> tcg , op , neg_opc , 2 );
2147
+ op2 -> args [0 ] = ret ;
2148
+ op2 -> args [1 ] = ret ;
2149
+ }
2150
+ }
2151
+
1970
2152
static bool fold_setcond (OptContext * ctx , TCGOp * op )
1971
2153
{
1972
2154
int i = do_constant_folding_cond1 (ctx , op -> args [0 ], & op -> args [1 ],
1973
2155
& op -> args [2 ], & op -> args [3 ]);
1974
2156
if (i >= 0 ) {
1975
2157
return tcg_opt_gen_movi (ctx , op , op -> args [0 ], i );
1976
2158
}
2159
+ fold_setcond_tst_pow2 (ctx , op , false);
1977
2160
1978
2161
ctx -> z_mask = 1 ;
1979
2162
ctx -> s_mask = smask_from_zmask (1 );
@@ -1987,13 +2170,13 @@ static bool fold_negsetcond(OptContext *ctx, TCGOp *op)
1987
2170
if (i >= 0 ) {
1988
2171
return tcg_opt_gen_movi (ctx , op , op -> args [0 ], - i );
1989
2172
}
2173
+ fold_setcond_tst_pow2 (ctx , op , true);
1990
2174
1991
2175
/* Value is {0,-1} so all bits are repetitions of the sign. */
1992
2176
ctx -> s_mask = -1 ;
1993
2177
return false;
1994
2178
}
1995
2179
1996
-
1997
2180
static bool fold_setcond2 (OptContext * ctx , TCGOp * op )
1998
2181
{
1999
2182
TCGCond cond ;
@@ -2041,22 +2224,35 @@ static bool fold_setcond2(OptContext *ctx, TCGOp *op)
2041
2224
case 0 :
2042
2225
goto do_setcond_const ;
2043
2226
case 1 :
2044
- op -> args [2 ] = op -> args [3 ];
2045
- op -> args [3 ] = cond ;
2046
- op -> opc = INDEX_op_setcond_i32 ;
2047
- break ;
2227
+ goto do_setcond_low ;
2228
+ }
2229
+ break ;
2230
+
2231
+ case TCG_COND_TSTEQ :
2232
+ case TCG_COND_TSTNE :
2233
+ if (arg_is_const_val (op -> args [2 ], 0 )) {
2234
+ goto do_setcond_high ;
2235
+ }
2236
+ if (arg_is_const_val (op -> args [4 ], 0 )) {
2237
+ goto do_setcond_low ;
2048
2238
}
2049
2239
break ;
2050
2240
2051
2241
default :
2052
2242
break ;
2053
2243
2244
+ do_setcond_low :
2245
+ op -> args [2 ] = op -> args [3 ];
2246
+ op -> args [3 ] = cond ;
2247
+ op -> opc = INDEX_op_setcond_i32 ;
2248
+ return fold_setcond (ctx , op );
2249
+
2054
2250
do_setcond_high :
2055
2251
op -> args [1 ] = op -> args [2 ];
2056
2252
op -> args [2 ] = op -> args [4 ];
2057
2253
op -> args [3 ] = cond ;
2058
2254
op -> opc = INDEX_op_setcond_i32 ;
2059
- break ;
2255
+ return fold_setcond ( ctx , op ) ;
2060
2256
}
2061
2257
2062
2258
ctx -> z_mask = 1 ;
0 commit comments