Hi! The x+x -> x*2 simplication obviously requires that 2 is representable in type, so that rules out unsigned _BitInt(1) and signed _BitInt(2) (and 1 too in C2Y, ditto unsigned:1 and signed:2 and :1), otherwise we don't multiply by 2 but by 0 or -2. While perhaps we could transform in those cases x+x to x<<1, I'm not convinced it is worth it.
Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? 2026-07-15 Jakub Jelinek <[email protected]> PR tree-optimization/126257 * match.pd (x+x -> x*2): Only optimize if 2 is representable in the type. * gcc.dg/torture/bitint-101.c: New test. --- gcc/match.pd.jj 2026-07-13 18:32:06.113290278 +0200 +++ gcc/match.pd 2026-07-14 15:38:09.693784224 +0200 @@ -5889,7 +5889,8 @@ (define_operator_list SYNC_FETCH_AND_AND (plus @0 @0) (if (SCALAR_FLOAT_TYPE_P (type)) (mult @0 { build_real (type, dconst2); }) - (if (INTEGRAL_TYPE_P (type)) + (if (INTEGRAL_TYPE_P (type) + && TYPE_PRECISION (type) > (2 - TYPE_UNSIGNED (type))) (mult @0 { build_int_cst (type, 2); })))) /* 0 - X -> -X. */ --- gcc/testsuite/gcc.dg/torture/bitint-101.c.jj 2026-07-14 15:40:44.962967133 +0200 +++ gcc/testsuite/gcc.dg/torture/bitint-101.c 2026-07-14 15:40:16.140304439 +0200 @@ -0,0 +1,26 @@ +/* PR tree-optimization/126257 */ +/* { dg-do run } */ + +_BitInt(2) a; +long long b, c, d; + +int +main () +{ + int e; + _BitInt(2) f; + bool g; + long long h = b; +lab: + e = h; + if (e != 4) + f = -1; + f = f + f; + a = f; + g = d - 4; + if (!g) + goto lab; + c = a; + if (c != -2) + __builtin_abort (); +} Jakub
