void bar (void); void foo (unsigned int a) { /* This one is equivalent to a >= (3 << 2). */ if ((a >> 2) >= 3) bar (); } void baz (unsigned int a) { /* This one is equivalent to a <= 7. */ if ((a & ~7) == 0) bar (); } The last tree in SSA form looks like: ;; Function foo (foo) foo (a) { unsigned int T.0; <bb 0>: T.0_2 = a_1 >> 2; if (T.0_2 > 2) goto <L0>; else goto <L1>; <L0>:; bar () [tail call]; <L1>:; return; } ;; Function baz (baz) baz (a) { unsigned int T.1; <bb 0>: T.1_2 = a_1 & 0fffffff8; if (T.1_2 == 0) goto <L0>; else goto <L1>; <L0>:; bar () [tail call]; <L1>:; return; } Note that in baz(), if "a" were of int, we would first have to create a temporary variable holding unsigned version of "a" before we can use an ordered comparison.
Confirmed.
Created attachment 6002 [details] A preliminary patch for the first case I still need to add checks for overflow, etc.
A slightly more comprehensive list of missing cases. I am not showing reversed conditions for conciseness. void bar (void); void rshift_gt (unsigned int a) { /* This is equivalent to a >= 23. */ if ((a >> 2) > 5) bar (); } void rshift_eq (unsigned int a) { /* This is equivalent to a <= 3. */ if ((a >> 2) == 0) bar (); } void mask_eq (unsigned int a) { /* This is equivalent to a <= 7. */ if ((a & ~7) == 0) bar (); } void mask_gt (unsigned int a) { /* This is equivalent to a > 15. */ if ((a & ~7) > 8) bar (); } void not_eq_cst (unsigned int a) { a = ~a; if (a == 123) bar (); } void not_eq_var (unsigned int a, unsigned int b) { a = ~a; b = ~b; if (a == b) bar (); } void neg_eq_cst (unsigned int a) { a = -a; if (a == 123) bar (); } void neg_eq_var (unsigned int a, unsigned int b) { a = -a; b = -b; if (a == b) bar (); } void minus_vars (unsigned int a, unsigned int b) { unsigned int tem; tem = a - b; if (tem == 0) bar (); } void xor_vars (unsigned int a, unsigned int b) { unsigned int tem; tem = a ^ b; if (tem == 0) bar (); } void xor_cst (unsigned int a) { a ^= 123; if (a == 456) bar (); }
One more case. void minus_cst (unsigned int a) { unsigned int tem; tem = 20 - a; if (tem == 5) bar (); }
One more case. void rotate_cst (unsigned int a) { a = (a << 10) | (a >> 22); if (a == 123) bar (); }
One more case. void bar (void); void foo (unsigned int a) { if ((a >> 5) & 1) bar (); } I get: foo (a) { _Bool T.2; unsigned int T.1; unsigned int T.0; <bb 0>: T.0_2 = a_1 >> 5; T.1_3 = T.0_2 & 1; T.2_4 = (_Bool)T.1_3; if (T.2_4) goto <L0>; else goto <L1>; <L0>:; bar () [tail call]; <L1>:; return; } We could have "if (T.1_3 != 0)". If nothing else, we can eliminate one temporary variable.
Some of these (though not everything) are done in RTL.
Subject: Re: [tree-ssa] some missed forward propagation opportunities In message <20040331024237.14588.qmail@sources.redhat.com>, "kazu at cs dot uma ss dot edu" writes: > >------- Additional Comments From kazu at cs dot umass dot edu 2004-03-31 02: >42 ------- >One more case. > >void bar (void); > >void >foo (unsigned int a) >{ > if ((a >> 5) & 1) > bar (); >} > >I get: > >foo (a) >{ > _Bool T.2; > unsigned int T.1; > unsigned int T.0; > ><bb 0>: > T.0_2 = a_1 >> 5; > T.1_3 = T.0_2 & 1; > T.2_4 = (_Bool)T.1_3; > if (T.2_4) goto <L0>; else goto <L1>; > ><L0>:; > bar () [tail call]; > ><L1>:; > return; > >} > >We could have "if (T.1_3 != 0)". >If nothing else, we can eliminate one temporary variable. Well, not only do we get to eliminate a temporary, we then have the ability to propagate T.1_3 == 0 on one arm of the branch. It's a pretty trivial extension to the existing forward propagation code [ It's the inversion of propagating from a TRUTH_NOT_EXPR. ] On hold pending a merge into the mainline. jeff
Fold should do all of these.
Subject: Re: [tree-ssa] some missed forward propagation opportunities In message <20040517014727.21847.qmail@sourceware.org>, "pinskia at gcc dot gnu dot org" writes: > >------- Additional Comments From pinskia at gcc dot gnu dot org 2004-05-17 0 >1:47 ------- >Fold should do all of these. Only if you're combining trees. And yes, I believe we ought to be combining trees :-) jeff
(In reply to Andrew Pinski from comment #9) > Fold should do all of these. Now I will say match-and-simplify should handle all of these. :)
Summary of the ones still need to be done: comment #0: * foo comment #3: * rshift_gt * rshift_eq * mask_gt * neg_eq_cst * neg_eq_var comment #4: * minus_cst
(In reply to Andrew Pinski from comment #12) > Summary of the ones still need to be done: > comment #0: > * foo PR 85234 (I think) > comment #3: > * rshift_gt PR 85234 (I think) > * rshift_eq PR 85234 (I think) > * mask_gt I don't think this has a bug # > * neg_eq_cst > * neg_eq_var PR 110134 (just submitted a patch for that) > > comment #4: > * minus_cst I don't think this has a bug #