https://gcc.gnu.org/bugzilla/show_bug.cgi?id=127916
--- Comment #2 from GCC Commits <cvs-commit at gcc dot gnu.org> --- The master branch has been updated by Kyrylo Tkachov <[email protected]>: https://gcc.gnu.org/g:1dbe8802bdd361e2274d1c0bec5e75e09ad0bc64 commit r17-5261-g1dbe8802bdd361e2274d1c0bec5e75e09ad0bc64 Author: Kyrylo Tkachov <[email protected]> Date: Thu Oct 15 20:09:21 2026 +0200 match-sat-alu.pd: Fix a constant check in signed SAT_ADD [PR127357] The form T SUM = (T) ((UT) X + (UT) IMM); ((X ^ SUM) & (X ^ C3)) < 0 ? (-(T) (X < 0) ^ MAX) : SUM is a signed saturating add only when (X ^ C3) < 0 tests that X has the sign of IMM, that is when C3 and IMM have opposite signs. The source form has C3 == ~IMM. The pattern, added in r15-4994, checks (IMM & C3) == 0, which also accepts IMM = 1, C3 = 2: int s_sat (int x) { int sum = (int) ((unsigned) x + 1u); if (((x ^ sum) & (x ^ 2)) < 0) return -(int) (x < 0) ^ INT_MAX; return sum; } _4 = x_10(D) ^ 2; _5 = _3 & _4; if (_5 < 0) ... # _9 = PHI <_12(3), sum_11(2)> widening_mul replaces the PHI with _9 = .SAT_ADD (x_10(D), 1), so s_sat (INT_MAX) returns INT_MAX instead of INT_MIN. The vectorizer uses the same matcher, which is how the PR127357 testcase fails at -O3. s_sat in PR127916 is the same bug. Compare the sign bits of the two constants instead. This also accepts valid pairs that the old check rejected, such as IMM = 1, C3 = -3. Bootstrapped and tested as part of the series on aarch64-unknown-linux-gnu and x86_64-pc-linux-gnu. PR tree-optimization/127357 PR tree-optimization/127916 gcc/ChangeLog: * match-sat-alu.pd (signed_integer_sat_add): Require opposite signs for the two constants of the single AND IMM form. gcc/testsuite/ChangeLog: * gcc.dg/torture/pr127357.c: New test. Signed-off-by: Kyrylo Tkachov <[email protected]>
