https://gcc.gnu.org/bugzilla/show_bug.cgi?id=127813
--- Comment #3 from Drea Pinski <pinskia at gcc dot gnu.org> ---
I should note the way the following (related) code:
```
typedef unsigned int uint32_t;
uint32_t gg(uint32_t bit, uint32_t a, uint32_t b) {
uint32_t mask = -(bit == 2);
return (a & mask) | (b & ~mask);
}
```
gets converted is the following :
`a & -CMP` is convert into a * CMP and then into `CMP ? a : 0`
The following pattern does the later:
```
/* (m1 CMP m2) * d -> (m1 CMP m2) ? d : 0 */
(if (fold_before_rtl_expansion_p ())
(simplify
(mult:c (convert (tcc_comparison@0 @1 @2)) @3)
(if (INTEGRAL_TYPE_P (type)
&& INTEGRAL_TYPE_P (TREE_TYPE (@0)))
(cond @0 @3 { build_zero_cst (type); })))
```
And `a & ~-(CMP)` is handled a similar way though done into `CMP'` and the done
similar as the above.
And then `CMP ? a : 0 | CMP' ? b : 0` is merged into `CMP ? a : b` via:
```
/* Fold ((-(a < b) & c) | (-(a >= b) & d)) into a < b ? c : d. This is
canonicalized further and we recognize the conditional form:
(a < b ? c : 0) | (a >= b ? d : 0) into a < b ? c : d.
Handle also ^ and + in replacement of `|`. */
(for op (bit_ior bit_xor plus)
(simplify
(op
(cond (cmp@0 @01 @02) @3 zerop)
(cond (icmp@4 @01 @02) @5 zerop))
(if (INTEGRAL_TYPE_P (type)
&& invert_tree_comparison (cmp, HONOR_NANS (@01)) == icmp
/* The scalar version has to be canonicalized after vectorization
because it makes unconditional loads conditional ones, which
means we lose vectorization because the loads may trap. */
&& canonicalize_math_after_vectorization_p ())
(cond @0 @3 @5))))
```