https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104360
--- Comment #2 from Andrew Pinski <pinskia at gcc dot gnu.org> --- Note it is easier to detect the vector version of this though: isN_3 = x_2(D) < { 0, 0, 0, 0, 0, 0, 0, 0 }; x_4 = x_2(D) ^ isN_3; _5 = x_4 - isN_3; Pattern here: (minus @0 (bit_xor:c @0 (lt@1 @0 vertor_zero_p))) than the scalar version: _10 = x_6(D) < 0; _11 = (int) _10; _12 = -_11; _1 = (short int) _12; x_7 = _1 ^ x_6(D); x.1_2 = (unsigned short) x_7; _3 = (unsigned short) _12; _4 = x.1_2 - _3; _8 = (i16) _4; Because of the overflow and such. If we used -fwrapv we get: _7 = x_3(D) < 0; _8 = (int) _7; _9 = -_8; _1 = (short int) _9; x_4 = _1 ^ x_3(D); _5 = x_4 - _1; Where we could reduce _1 to just: t = (short int) _7; _1 = -t; And then it is just pattern matching. For int we get: _6 = x_2(D) < 0; _7 = (int) _6; _8 = -_7; x_3 = x_2(D) ^ _8; _4 = x_3 + _7; Which should be easy to pattern match. (plus:c (bit_xor:c @0 (neg (convert@1 (lt @0 zero_p)))) @1)