On Wed, 4 Dec 2019, Jakub Jelinek wrote:
--- gcc/match.pd.jj 2019-12-03 10:20:00.244913801 +0100
+++ gcc/match.pd 2019-12-03 13:36:01.084435697 +0100
@@ -2159,20 +2159,26 @@ (define_operator_list COND_TERNARY
/* A - (A +- B) -> -+ B */
/* A +- (B -+ A) -> +- B */
(simplify
- (minus (plus:c @0 @1) @0)
- @1)
+ (minus (nop_convert (plus:c (nop_convert @0) @1)) @0)
+ (view_convert @1))
I know I introduced nop_convert, and it can be convenient, but IIRC it
also has some limitations.
int f(int b,unsigned c){
int a=c;
int d=a+b;
return d-a;
}
int g(int a, int b){
int d=(unsigned)a+b;
return d-a;
}
int h(int b,int a){
int d=a+b;
return d-a;
}
While g and h are properly optimized during forwprop1, f isn't, because
nop_convert sees that 'a' comes from a conversion, and only returns d
(unlike 'convert?' which would try both a and d).
When inside nop_convert we have an operation, say (nop_convert (plus
...)), there is no ambiguity, so we are fine. With just (nop_convert @0),
less so.
It happens that during EVRP, for some reason (different valuization
function?), nop_convert does not match the conversion, and we do optimize
f. But that almost looks like an accident.
convert? with explicit checks would probably work better for the inner
conversion, except that handling the vector view_convert case may become
painful. I didn't think too hard about possible fancy tricks like a second
nop_convert:
(minus (nop_convert (plus:c (nop_convert @0) @1)) (nop_convert @0))
--
Marc Glisse