Hi,

in August 2016 Prathamesh implemented inter-procedural propagation of
known non-zero bits on integers.  In August that same year he then also
added the ability to track it for pointer, replacing separate alignment
tracking.

However, we still have an assert in ipcp_bits_lattice::meet_with from
the first commit that checks that any binary operation coming from an
arithmetic jump function is performed on integers.  Martin discovered
that when you compile chromium and stars are aligned correctly, you can
end up evaluating a pointer expression MAX_EXPR (param, 0) there which
trips the assert.

Unless Prathamesh can remember a reason why the assert is important, I
believe the correct thing is just to remove it.  In the case of this
MAX_EXPR, it will end up being evaluated in bit_value_binop which cannot
handle it and so we will end up with a BOTTOM lattice in the end.  In
the general case, bit_value_binop operates on widest_ints and so shoud
have no problem dealing with pointers.

I'm bootstrapping and testing the following patch to satisfy the rules
but since it only removes an assert and adds a testcase that I checked,
I do not expect any problems.  Is it OK for trunk, GCC 9 and 8?

Thanks,

Martin




2019-06-24  Martin Jambor  <mjam...@suse.cz>

        PR ipa/90939
        * ipa-cp.c (ipcp_bits_lattice::meet_with): Remove assert.

        testsuite/
        * g++.dg/lto/pr90939_[01].C: New test.
---
 gcc/ipa-cp.c                         |  1 -
 gcc/testsuite/g++.dg/lto/pr90939_0.C | 64 ++++++++++++++++++++++++++++
 gcc/testsuite/g++.dg/lto/pr90939_1.C | 45 +++++++++++++++++++
 3 files changed, 109 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/g++.dg/lto/pr90939_0.C
 create mode 100644 gcc/testsuite/g++.dg/lto/pr90939_1.C

diff --git a/gcc/ipa-cp.c b/gcc/ipa-cp.c
index d3a88756a91..69c00a9c5a5 100644
--- a/gcc/ipa-cp.c
+++ b/gcc/ipa-cp.c
@@ -1085,7 +1085,6 @@ ipcp_bits_lattice::meet_with (ipcp_bits_lattice& other, 
unsigned precision,
   if (TREE_CODE_CLASS (code) == tcc_binary)
     {
       tree type = TREE_TYPE (operand);
-      gcc_assert (INTEGRAL_TYPE_P (type));
       widest_int o_value, o_mask;
       get_value_and_mask (operand, &o_value, &o_mask);
 
diff --git a/gcc/testsuite/g++.dg/lto/pr90939_0.C 
b/gcc/testsuite/g++.dg/lto/pr90939_0.C
new file mode 100644
index 00000000000..8987c348015
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lto/pr90939_0.C
@@ -0,0 +1,64 @@
+// PR ipa/90939
+// { dg-lto-do link }
+// { dg-lto-options { { -flto -O3 } } }
+
+
+typedef char uint8_t;
+template <class T> class A {
+public:
+  A(T *);
+};
+template <typename Derived, typename Base> const Derived &To(Base &p1) {
+  return static_cast<const Derived &>(p1);
+}
+class H;
+template <typename, typename Base> const H *To(Base *p1) {
+  return p1 ? &To<H>(*p1) : nullptr;
+}
+enum TextDirection : uint8_t;
+enum WritingMode : unsigned;
+class B {
+public:
+  WritingMode m_fn1();
+};
+class C {
+public:
+  int &m_fn2();
+};
+class D { double d;};
+class H : public D {};
+class F {
+public:
+  F(C, A<const int>, B *, WritingMode, TextDirection);
+};
+
+class G {
+public:
+  C NGLayoutAlgorithm_node;
+  B NGLayoutAlgorithm_space;
+  TextDirection NGLayoutAlgorithm_direction;
+  H NGLayoutAlgorithm_break_token;
+  G(A<const int> p1) __attribute__((noinline))
+    : break_token_(&NGLayoutAlgorithm_break_token),
+        container_builder_(NGLayoutAlgorithm_node, p1, 
&NGLayoutAlgorithm_space,
+                           NGLayoutAlgorithm_space.m_fn1(),
+                           NGLayoutAlgorithm_direction) {}
+  G(C p1, const H *) : G(&p1.m_fn2()) {}
+  A<H> break_token_;
+  F container_builder_;
+};
+
+class I : G {
+public:
+  I(const D *) __attribute__((noinline));
+};
+C a;
+I::I(const D *p1) : G(a, To<H>(p1)) {}
+
+D gd[10];
+
+int main (int argc, char *argv[])
+{
+  I i(&(gd[argc%2]));
+  return 0;
+}
diff --git a/gcc/testsuite/g++.dg/lto/pr90939_1.C 
b/gcc/testsuite/g++.dg/lto/pr90939_1.C
new file mode 100644
index 00000000000..9add89494d7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lto/pr90939_1.C
@@ -0,0 +1,45 @@
+typedef char uint8_t;
+template <class T> class A {
+public:
+  A(T *);
+};
+
+enum TextDirection : uint8_t;
+enum WritingMode : unsigned;
+class B {
+public:
+  WritingMode m_fn1();
+};
+class C {
+public:
+  int &m_fn2();
+};
+
+class F {
+public:
+  F(C, A<const int>, B *, WritingMode, TextDirection);
+};
+class D { double d;};
+class H : public D {};
+
+
+
+template <class T> A<T>::A(T*) {}
+
+template class A<H>;
+template class A<int const>;
+
+WritingMode __attribute__((noipa))
+B::m_fn1()
+{
+  return (WritingMode) 0;
+}
+
+int gi;
+int & __attribute__((noipa))
+C::m_fn2 ()
+{
+  return gi;
+}
+
+__attribute__((noipa)) F::F(C, A<const int>, B *, WritingMode, TextDirection) 
{}
-- 
2.21.0

Reply via email to