https://gcc.gnu.org/g:de1c734a8ae034c92f485e7f58b7fcb1c921ecd2

commit r15-9427-gde1c734a8ae034c92f485e7f58b7fcb1c921ecd2
Author: Martin Jambor <mjam...@suse.cz>
Date:   Mon Apr 14 14:21:15 2025 +0200

    ipa-cp: Make propagation of bits in IPA-CP aware of type conversions 
(PR119318)
    
    After the propagation of constants and value ranges, it turns out
    that the propagation of known bits also needs to be made aware of any
    intermediate types in which any arithmetic operations are made and
    must limit its precision there.  This implements just that, using the
    newly collected and streamed types of the operations involved.
    
    This version removed the extra check that the type of a formal
    parameter is known pointed out in Honza in his review because I agree
    it is currently always known.  I have also added the testcase of PR
    119530 which is a duplicate of this bug.
    
    gcc/ChangeLog:
    
    2025-04-11  Martin Jambor  <mjam...@suse.cz>
    
            PR ipa/119318
            * ipa-cp.cc (ipcp_bits_lattice::meet_with_1): Set all mask bits
            not covered by precision to one.
            (ipcp_bits_lattice::meet_with): Likewise.
            (propagate_bits_across_jump_function): Use the stored operation
            type to perform meet with other lattices.
    
    gcc/testsuite/ChangeLog:
    
    2025-04-11  Martin Jambor  <mjam...@suse.cz>
    
            PR ipa/119318
            * gcc.dg/ipa/pr119318.c: New test.
            * gcc.dg/ipa/pr119530.c: Likwise.

Diff:
---
 gcc/ipa-cp.cc                       | 21 +++++++++++++++-----
 gcc/testsuite/gcc.dg/ipa/pr119318.c | 38 +++++++++++++++++++++++++++++++++++++
 gcc/testsuite/gcc.dg/ipa/pr119530.c | 21 ++++++++++++++++++++
 3 files changed, 75 insertions(+), 5 deletions(-)

diff --git a/gcc/ipa-cp.cc b/gcc/ipa-cp.cc
index 264568989a96..fd2c4cca1365 100644
--- a/gcc/ipa-cp.cc
+++ b/gcc/ipa-cp.cc
@@ -918,6 +918,8 @@ ipcp_bits_lattice::meet_with_1 (widest_int value, 
widest_int mask,
     m_mask |= m_value;
   m_value &= ~m_mask;
 
+  widest_int cap_mask = wi::bit_not (wi::sub (wi::lshift (1, precision), 1));
+  m_mask |= cap_mask;
   if (wi::sext (m_mask, precision) == -1)
     return set_to_bottom ();
 
@@ -996,6 +998,8 @@ ipcp_bits_lattice::meet_with (ipcp_bits_lattice& other, 
unsigned precision,
          adjusted_mask |= adjusted_value;
          adjusted_value &= ~adjusted_mask;
        }
+      widest_int cap_mask = wi::bit_not (wi::sub (wi::lshift (1, precision), 
1));
+      adjusted_mask |= cap_mask;
       if (wi::sext (adjusted_mask, precision) == -1)
        return set_to_bottom ();
       return set_to_constant (adjusted_value, adjusted_mask);
@@ -2507,14 +2511,12 @@ propagate_bits_across_jump_function (cgraph_edge *cs, 
int idx,
       return dest_lattice->set_to_bottom ();
     }
 
-  unsigned precision = TYPE_PRECISION (parm_type);
-  signop sgn = TYPE_SIGN (parm_type);
-
   if (jfunc->type == IPA_JF_PASS_THROUGH
       || jfunc->type == IPA_JF_ANCESTOR)
     {
       ipa_node_params *caller_info = ipa_node_params_sum->get (cs->caller);
       tree operand = NULL_TREE;
+      tree op_type = NULL_TREE;
       enum tree_code code;
       unsigned src_idx;
       bool keep_null = false;
@@ -2524,7 +2526,10 @@ propagate_bits_across_jump_function (cgraph_edge *cs, 
int idx,
          code = ipa_get_jf_pass_through_operation (jfunc);
          src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
          if (code != NOP_EXPR)
-           operand = ipa_get_jf_pass_through_operand (jfunc);
+           {
+             operand = ipa_get_jf_pass_through_operand (jfunc);
+             op_type = ipa_get_jf_pass_through_op_type (jfunc);
+           }
        }
       else
        {
@@ -2551,6 +2556,11 @@ propagate_bits_across_jump_function (cgraph_edge *cs, 
int idx,
 
       if (!src_lats->bits_lattice.bottom_p ())
        {
+         if (!op_type)
+           op_type = ipa_get_type (caller_info, src_idx);
+
+         unsigned precision = TYPE_PRECISION (op_type);
+         signop sgn = TYPE_SIGN (op_type);
          bool drop_all_ones
            = keep_null && !src_lats->bits_lattice.known_nonzero_p ();
 
@@ -2570,7 +2580,8 @@ propagate_bits_across_jump_function (cgraph_edge *cs, int 
idx,
            = widest_int::from (bm.mask (), TYPE_SIGN (parm_type));
          widest_int value
            = widest_int::from (bm.value (), TYPE_SIGN (parm_type));
-         return dest_lattice->meet_with (value, mask, precision);
+         return dest_lattice->meet_with (value, mask,
+                                         TYPE_PRECISION (parm_type));
        }
     }
   return dest_lattice->set_to_bottom ();
diff --git a/gcc/testsuite/gcc.dg/ipa/pr119318.c 
b/gcc/testsuite/gcc.dg/ipa/pr119318.c
new file mode 100644
index 000000000000..8e62ec5e3503
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/ipa/pr119318.c
@@ -0,0 +1,38 @@
+/* { dg-do run } */
+/* { dg-require-effective-target int128 } */
+/* { dg-additional-options "-Wno-psabi -w" } */
+/* { dg-options "-Wno-psabi -O2" } */
+
+typedef unsigned V __attribute__((vector_size (64)));
+typedef unsigned __int128 W __attribute__((vector_size (64)));
+
+W a;
+W b;
+W c = { -0xffff, -0xffff, -0xffff, -0xffff };
+
+static __attribute__((__noinline__, __noclone__)) W
+bar (unsigned __int128 u)
+{
+  return u + c;
+}
+
+static inline W
+foo (unsigned short s, V v)
+{
+  V y = (V) bar ((unsigned short) ~s);
+  v >>= y;
+  b ^= (W) a;
+  v *= v;
+  return (W) v + b;
+}
+
+
+int
+main ()
+{
+  W x = foo (0, (V) { 0, 5 });
+  for (unsigned i = 0; i < sizeof(x)/sizeof(x[0]); i++)
+    if (x[i] != (i ? 0 : 0x1900000000))
+      __builtin_abort();
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/ipa/pr119530.c 
b/gcc/testsuite/gcc.dg/ipa/pr119530.c
new file mode 100644
index 000000000000..70f158a2de84
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/ipa/pr119530.c
@@ -0,0 +1,21 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -fno-tree-vrp -fno-inline" } */
+
+struct a {
+  int b;
+};
+int c;
+char d;
+static int e(long f) { return f < 0; }
+static void g(unsigned f) { c = e(~f); }
+int main() {
+  int h;
+  struct a i = {128};
+  h = d > i.b;
+  g(h);
+  if (h)
+    __builtin_abort();
+  if (c)
+    __builtin_abort();
+  return 0;
+}

Reply via email to