Re: [PATCH] match.pd: drop a clamp whose bounds cross
Jeffrey Law <[email protected]> Wed, 5 Aug 2026 22:33:40 -0600
| Newsgroups | gmane.comp.gcc.patches |
|---|---|
| Message-ID | <[email protected]> |
On 8/4/2026 3:54 AM, [email protected] wrote: > From: Kyrylo Tkachov <[email protected]> > > MIN (MAX (X, Y + CST), Y) is Y for a positive CST: the inner select is at > least Y + CST, which is strictly above Y where the type cannot wrap, so the > outer select always takes Y. The dual holds for MAX over MIN with a > negative offset. Both leave the whole nest dead. > > int f (int x, int y) > { > int a = x > y + 7 ? x : y + 7; > return a < y ? a : y; > } > > aarch64 -O2 before: > > add w2, w1, 7 > cmp w2, w0 > csel w0, w2, w0, ge > cmp w0, w1 > csel w0, w0, w1, le > > after: > > mov w0, w1 > > The shape arises after inlining, when a clamp helper is instantiated with a > lower bound that the caller has already pushed above the upper one. The > existing min/max-with-offset rules only cover the case where the two selects > name the same operand, so the nest survived. > > Bootstrapped and tested on aarch64-none-linux-gnu. > Ok for trunk? > Thanks, > Kyrill > > gcc/ChangeLog: > > * match.pd (MIN (MAX (X, Y + CST), Y)): New simplification. > (MAX (MIN (X, Y + CST), Y)): Likewise. > > gcc/testsuite/ChangeLog: > > * gcc.dg/tree-ssa/minmax-offset-absorb-1.c: New test. Generally OK. Just one testcase question. > + > +/* Must not fold: the offset has the wrong sign for the outer select. */ > +int keep2 (int x, int y) > +{ > + int a = x > y - 7 ? x : y - 7; > + return a < y ? a : y; > +} So very happy to see both positive and negative tests. This one probably isn't testing what you think since it appears the MAX_EXPR is never discovered. We discover the MIN_EXPR, but the MAX is still in if-then form. So not really sure the scans are testing this in the way you want. Not sure if you want to adjust that or not. For reference the IL looks like this: _1 = y_3(D) + -6; if (_1 > x_4(D)) goto <bb 4>; [50.00%] else goto <bb 3>; [50.00%] ;; succ: 4 [50.0% (guessed)] count:536870912 (estimated locally, freq 0.5000) (TRUE_VALUE,EXECUTABLE) ;; 3 [50.0% (guessed)] count:536870912 (estimated locally, freq 0.5000) (FALSE_VALUE,EXECUTABLE) ;; basic block 3, loop depth 0, count 536870912 (estimated locally, freq 0.5000), maybe hot ;; prev block 2, next block 4, flags: (NEW, REACHABLE, VISITED) ;; pred: 2 [50.0% (guessed)] count:536870912 (estimated locally, freq 0.5000) (FALSE_VALUE,EXECUTABLE) _8 = MIN_EXPR <y_3(D), x_4(D)>; goto <bb 5>; [100.00%] ;; succ: 5 [always] count:536870912 (estimated locally, freq 0.5000) (FALLTHRU,EXECUTABLE) ;; basic block 4, loop depth 0, count 536870912 (estimated locally, freq 0.5000), maybe hot ;; prev block 3, next block 5, flags: (NEW, REACHABLE, VISITED) ;; pred: 2 [50.0% (guessed)] count:536870912 (estimated locally, freq 0.5000) (TRUE_VALUE,EXECUTABLE) a_5 = y_3(D) + -7; ;; succ: 5 [always] count:536870912 (estimated locally, freq 0.5000) (FALLTHRU,EXECUTABLE) ;; basic block 5, loop depth 0, count 1073741824 (estimated locally, freq 1.0000), maybe hot ;; prev block 4, next block 1, flags: (NEW, REACHABLE, VISITED) ;; pred: 4 [always] count:536870912 (estimated locally, freq 0.5000) (FALLTHRU,EXECUTABLE) ;; 3 [always] count:536870912 (estimated locally, freq 0.5000) (FALLTHRU,EXECUTABLE) # prephitmp_9 = PHI <a_5(4), _8(3)> return prephitmp_9; Jeff