Hello,

On Wed, Apr 09 2025, Martin Jambor wrote:
> Hi,
>
> On Tue, Apr 08 2025, Jan Hubicka wrote:
>>> 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.
>>> 
>>> Bootstrapped and tested and LTO bootstrapped on x86_64-linux. OK for
>>> master?
>>> 
>>> Thanks,
>>> 
>>> Martin
>>> 
>>> 
>>> gcc/ChangeLog:
>>> 
>>> 2025-03-20  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 first operand type
>>>     rather than the final parameter one to perform meet with other
>>>     lattices.  Check the operation conforms with
>>>     expr_type_first_operand_type_p.
>>>     * tree.cc (expr_type_first_operand_type_p): Add POINTER_PLUS_EXPR.
>>> 
>>> gcc/testsuite/ChangeLog:
>>> 
>>> 2025-03-18  Martin Jambor  <mjam...@suse.cz>
>>> 
>>>     PR ipa/119318
>>>     * gcc.dg/ipa/pr119318.c: New test.
>>> +     if (!op_type)
>>> +       {
>>> +         op_type = ipa_get_type (caller_info, src_idx);
>>> +         if (!op_type)
>>> +           {
>>> +             if (dump_file && (dump_flags & TDF_DETAILS))
>>> +               fprintf (dump_file, "Setting dest_lattice to bottom, "
>>> +                        "because the operation involved in computing "
>>> +                        "param %i of %s is in an unknown type.\n",
>>> +                        idx, cs->callee->dump_name ());
>>> +             return dest_lattice->set_to_bottom ();
>>> +           }
>>> +       }
>>
>> When this can happen?
>> I can see that get_ipa_type returns NULL when there are no descriptor or
>> respective descriptor has NULL type, but I wonder in what cases this
>> happens in practice...
>
> That is a fair point, if we have jump functions for calls in a function,
> we will nowadays always have types of its formal parameters.  I'll be
> happy to replace the condition with an assert.

...I actually just ended up with removing the test because an assert
would just prevent a segfault on the next line.  The patch below has
been pre-approved by Honza, I'm currently testing it and plan to commit
it on Monday.

Thanks,

Martin


----------------------------------------------------------------------

>From ed46f21bbc5a1e9c339af50efb06712f04f2546b Mon Sep 17 00:00:00 2001
From: Martin Jambor <mjam...@suse.cz>
Date: Fri, 11 Apr 2025 16:34:32 +0200
Subject: [PATCH 2/7] 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 first operand type
        rather than the final parameter one to perform meet with other
        lattices.  Check the operation conforms with
        expr_type_first_operand_type_p.
        * tree.cc (expr_type_first_operand_type_p): Add POINTER_PLUS_EXPR.

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.
---
 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(-)
 create mode 100644 gcc/testsuite/gcc.dg/ipa/pr119318.c
 create mode 100644 gcc/testsuite/gcc.dg/ipa/pr119530.c

diff --git a/gcc/ipa-cp.cc b/gcc/ipa-cp.cc
index 264568989a9..fd2c4cca136 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 00000000000..8e62ec5e350
--- /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 00000000000..70f158a2de8
--- /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;
+}
-- 
2.49.0


Reply via email to