]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
fold-const: Fix up multiple_of_p [PR112733]
authorJakub Jelinek <jakub@redhat.com>
Wed, 29 Nov 2023 11:26:50 +0000 (12:26 +0100)
committerJakub Jelinek <jakub@redhat.com>
Sun, 17 Dec 2023 13:54:44 +0000 (14:54 +0100)
We ICE on the following testcase when wi::multiple_of_p is called on
widest_int 1 and -128 with UNSIGNED.  I still need to work on the
actual wide-int.cc issue, the latest patch attached to the PR regressed
bitint-{38,39}.c, so will need to debug that, but there is a clear bug
on the fold-const.cc side as well - widest_int is a signed representation
by definition, using UNSIGNED with it certainly doesn't match what was
intended, because -128 as the second operand effectively means unsigned
131072 bit 0xfffff............ffff80 integer, not the signed char -128
that appeared in the source.

In the INTEGER_CST case a few lines above this we already use
    case INTEGER_CST:
      if (TREE_CODE (bottom) != INTEGER_CST || integer_zerop (bottom))
        return false;
      return wi::multiple_of_p (wi::to_widest (top), wi::to_widest (bottom),
                                SIGNED);
so I think using SIGNED with widest_int is best there (compared to the
other choices in the PR).

2023-11-29  Jakub Jelinek  <jakub@redhat.com>

PR middle-end/112733
* fold-const.c (multiple_of_p): Pass SIGNED rather than
UNSIGNED for wi::multiple_of_p on widest_int arguments.

* gcc.dg/pr112733.c: New test.

(cherry picked from commit 5c95bf945c632925efba86dd5dceccdb9da8884c)

gcc/fold-const.c
gcc/testsuite/gcc.dg/pr112733.c [new file with mode: 0644]

index 5b4053df520a319fe9792f49d2c7986dcbdfbcf1..f4fd980dbbc88b3959877377924cda0122842cca 100644 (file)
@@ -14185,7 +14185,7 @@ multiple_of_p (tree type, const_tree top, const_tree bottom)
              && TREE_CODE (op2) == INTEGER_CST
              && integer_pow2p (bottom)
              && wi::multiple_of_p (wi::to_widest (op2),
-                                   wi::to_widest (bottom), UNSIGNED))
+                                   wi::to_widest (bottom), SIGNED))
            return 1;
 
          op1 = gimple_assign_rhs1 (stmt);
diff --git a/gcc/testsuite/gcc.dg/pr112733.c b/gcc/testsuite/gcc.dg/pr112733.c
new file mode 100644 (file)
index 0000000..d6f99f7
--- /dev/null
@@ -0,0 +1,16 @@
+/* PR middle-end/112733 */
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+signed char a, c;
+short b;
+
+void
+foo (void)
+{
+  signed char *e = &a;
+  c = foo != 0;
+  *e &= c;
+  for (; b; --b)
+    *e &= -128;
+}