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

Reply via email to