On Tue, Nov 21, 2023 at 6:07 AM Jan Hubicka <hubi...@ucw.cz> wrote:
>
> > After this patch in addition to the problem already reported about
> > vlda1.c and return-value-range-1.c, we have noticed these regressions
> > on aarch64:
> > Running gcc:gcc.target/aarch64/aarch64.exp ...
> > FAIL: gcc.target/aarch64/movk.c scan-assembler movk\tx[0-9]+, 0x4667, lsl 16
> > FAIL: gcc.target/aarch64/movk.c scan-assembler movk\tx[0-9]+, 0x7a3d, lsl 32
> >
> > Running gcc:gcc.target/aarch64/simd/simd.exp ...
> > FAIL: gcc.target/aarch64/simd/vmulxd_f64_2.c scan-assembler-times
> > fmul[ \t]+[dD][0-9]+, ?[dD][0-9]+, ?[dD][0-9]+\n 1
> > FAIL: gcc.target/aarch64/simd/vmulxd_f64_2.c scan-assembler-times
> > fmulx[ \t]+[dD][0-9]+, ?[dD][0-9]+, ?[dD][0-9]+\n 4
> > FAIL: gcc.target/aarch64/simd/vmulxs_f32_2.c scan-assembler-times
> > fmul[ \t]+[sS][0-9]+, ?[sS][0-9]+, ?[sS][0-9]+\n 1
> > FAIL: gcc.target/aarch64/simd/vmulxs_f32_2.c scan-assembler-times
> > fmulx[ \t]+[sS][0-9]+, ?[sS][0-9]+, ?[sS][0-9]+\n 4
>
> Sorry for that - I guess we will see some on various targets.
> This is quite common issue - the testcase is having
> dummy_number_generator function returning constant and prevents
> inlining to avoid constant being visible to compiler.  This no longer
> works, since we get it from the return value range.  This should fix it.
>
> return-value_range-1.c should be fixed now and I do not have vlda1.c in
> my tree.  I will check.

This is the other change that needs to happen I think:
diff --git a/gcc/testsuite/gcc.target/aarch64/simd/vmulx.x
b/gcc/testsuite/gcc.target/aarch64/simd/vmulx.x
index 8968a64a95c..869e7485646 100644
--- a/gcc/testsuite/gcc.target/aarch64/simd/vmulx.x
+++ b/gcc/testsuite/gcc.target/aarch64/simd/vmulx.x
@@ -33,13 +33,13 @@
   while (0)                                                            \

 /* Functions used to return values that won't be optimised away.  */
-float32_t  __attribute__ ((noinline))
+float32_t  __attribute__ ((noipa))
 foo32 ()
 {
   return 1.0;
 }

-float64_t  __attribute__ ((noinline))
+float64_t  __attribute__ ((noipa))
 foo64 ()
 {
   return 1.0;


Thanks,
Andrew Pinski

>
> diff --git a/gcc/testsuite/gcc.target/aarch64/movk.c 
> b/gcc/testsuite/gcc.target/aarch64/movk.c
> index e6e4e3a8961..6b1f3f8ecf5 100644
> --- a/gcc/testsuite/gcc.target/aarch64/movk.c
> +++ b/gcc/testsuite/gcc.target/aarch64/movk.c
> @@ -1,8 +1,9 @@
>  /* { dg-do run } */
> -/* { dg-options "-O2 --save-temps -fno-inline" } */
> +/* { dg-options "-O2 --save-temps" } */
>
>  extern void abort (void);
>
> +__attribute__ ((noipa))
>  long long int
>  dummy_number_generator ()
>  {
>
> >
> > We have already sent you a notification for the regression on arm, but
> > it includes on vla-1.c and return-value-range-1.c.
> > The notification email contains a pointer to the page where we record
> > all the configurations that regress because of this patch:
> >
> > https://linaro.atlassian.net/browse/GNU-1025
> >
> > Can you have a look?
> >
> > Thanks,
> >
> > Christophe
> >
> >
> >
> >
> > > diff --git a/gcc/cgraph.cc b/gcc/cgraph.cc
> > > index e41e5ad3ae7..71dacf23ce1 100644
> > > --- a/gcc/cgraph.cc
> > > +++ b/gcc/cgraph.cc
> > > @@ -2629,6 +2629,54 @@ cgraph_node::set_malloc_flag (bool malloc_p)
> > >    return changed;
> > >  }
> > >
> > > +/* Worker to set malloc flag.  */
> > > +static void
> > > +add_detected_attribute_1 (cgraph_node *node, const char *attr, bool 
> > > *changed)
> > > +{
> > > +  if (!lookup_attribute (attr, DECL_ATTRIBUTES (node->decl)))
> > > +    {
> > > +      DECL_ATTRIBUTES (node->decl) = tree_cons (get_identifier (attr),
> > > +                                        NULL_TREE, DECL_ATTRIBUTES 
> > > (node->decl));
> > > +      *changed = true;
> > > +    }
> > > +
> > > +  ipa_ref *ref;
> > > +  FOR_EACH_ALIAS (node, ref)
> > > +    {
> > > +      cgraph_node *alias = dyn_cast<cgraph_node *> (ref->referring);
> > > +      if (alias->get_availability () > AVAIL_INTERPOSABLE)
> > > +       add_detected_attribute_1 (alias, attr, changed);
> > > +    }
> > > +
> > > +  for (cgraph_edge *e = node->callers; e; e = e->next_caller)
> > > +    if (e->caller->thunk
> > > +       && (e->caller->get_availability () > AVAIL_INTERPOSABLE))
> > > +      add_detected_attribute_1 (e->caller, attr, changed);
> > > +}
> > > +
> > > +/* Set DECL_IS_MALLOC on NODE's decl and on NODE's aliases if any.  */
> > > +
> > > +bool
> > > +cgraph_node::add_detected_attribute (const char *attr)
> > > +{
> > > +  bool changed = false;
> > > +
> > > +  if (get_availability () > AVAIL_INTERPOSABLE)
> > > +    add_detected_attribute_1 (this, attr, &changed);
> > > +  else
> > > +    {
> > > +      ipa_ref *ref;
> > > +
> > > +      FOR_EACH_ALIAS (this, ref)
> > > +       {
> > > +         cgraph_node *alias = dyn_cast<cgraph_node *> (ref->referring);
> > > +         if (alias->get_availability () > AVAIL_INTERPOSABLE)
> > > +           add_detected_attribute_1 (alias, attr, &changed);
> > > +       }
> > > +    }
> > > +  return changed;
> > > +}
> > > +
> > >  /* Worker to set noreturng flag.  */
> > >  static void
> > >  set_noreturn_flag_1 (cgraph_node *node, bool noreturn_p, bool *changed)
> > > diff --git a/gcc/cgraph.h b/gcc/cgraph.h
> > > index cedaaac3a45..cfdd9f693a8 100644
> > > --- a/gcc/cgraph.h
> > > +++ b/gcc/cgraph.h
> > > @@ -1190,6 +1190,10 @@ struct GTY((tag ("SYMTAB_FUNCTION"))) cgraph_node 
> > > : public symtab_node
> > >
> > >    bool set_pure_flag (bool pure, bool looping);
> > >
> > > +  /* Add attribute ATTR to cgraph_node's decl and on aliases of the node
> > > +     if any.  */
> > > +  bool add_detected_attribute (const char *attr);
> > > +
> > >    /* Call callback on function and aliases associated to the function.
> > >       When INCLUDE_OVERWRITABLE is false, overwritable aliases and thunks 
> > > are
> > >       skipped. */
> > > diff --git a/gcc/common.opt b/gcc/common.opt
> > > index d21db5d4a20..c6599c7147b 100644
> > > --- a/gcc/common.opt
> > > +++ b/gcc/common.opt
> > > @@ -781,6 +781,10 @@ Wsuggest-attribute=malloc
> > >  Common Var(warn_suggest_attribute_malloc) Warning
> > >  Warn about functions which might be candidates for 
> > > __attribute__((malloc)).
> > >
> > > +Wsuggest-attribute=returns_nonnull
> > > +Common Warning
> > > +Warn about functions which might be candidates for 
> > > __attribute__((returns_nonnull)).
> > > +
> > >  Wsuggest-final-types
> > >  Common Var(warn_suggest_final_types) Warning
> > >  Warn about C++ polymorphic types where adding final keyword would 
> > > improve code quality.
> > > diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
> > > index 1f109679c70..3c33104df0a 100644
> > > --- a/gcc/doc/invoke.texi
> > > +++ b/gcc/doc/invoke.texi
> > > @@ -8093,7 +8093,7 @@ if the array is referenced as a flexible array 
> > > member.
> > >
> > >  @opindex Wsuggest-attribute=
> > >  @opindex Wno-suggest-attribute=
> > > -@item 
> > > -Wsuggest-attribute=@r{[}pure@r{|}const@r{|}noreturn@r{|}format@r{|}cold@r{|}malloc@r{]}
> > > +@item 
> > > -Wsuggest-attribute=@r{[}pure@r{|}const@r{|}noreturn@r{|}format@r{|}cold@r{|}malloc@r{]}returns_nonnull@r{|}
> > >  Warn for cases where adding an attribute may be beneficial. The
> > >  attributes currently supported are listed below.
> > >
> > > @@ -8113,9 +8113,11 @@ attributes currently supported are listed below.
> > >  @itemx -Wsuggest-attribute=noreturn
> > >  @itemx -Wmissing-noreturn
> > >  @itemx -Wsuggest-attribute=malloc
> > > +@itemx -Wsuggest-attribute=returns_nonnull
> > > +@itemx -Wno-suggest-attribute=returns_nonnull
> > >
> > >  Warn about functions that might be candidates for attributes
> > > -@code{pure}, @code{const} or @code{noreturn} or @code{malloc}. The 
> > > compiler
> > > +@code{pure}, @code{const}, @code{noreturn}, @code{malloc} or 
> > > @code{returns_nonnull}. The compiler
> > >  only warns for functions visible in other compilation units or (in the 
> > > case of
> > >  @code{pure} and @code{const}) if it cannot prove that the function 
> > > returns
> > >  normally. A function returns normally if it doesn't contain an infinite 
> > > loop or
> > > diff --git a/gcc/gimple-range-fold.cc b/gcc/gimple-range-fold.cc
> > > index 6e9530c3d7f..998b7608d78 100644
> > > --- a/gcc/gimple-range-fold.cc
> > > +++ b/gcc/gimple-range-fold.cc
> > > @@ -44,6 +44,11 @@ along with GCC; see the file COPYING3.  If not see
> > >  #include "value-query.h"
> > >  #include "gimple-range-op.h"
> > >  #include "gimple-range.h"
> > > +#include "cgraph.h"
> > > +#include "alloc-pool.h"
> > > +#include "symbol-summary.h"
> > > +#include "ipa-utils.h"
> > > +#include "ipa-prop.h"
> > >  // Construct a fur_source, and set the m_query field.
> > >
> > >  fur_source::fur_source (range_query *q)
> > > @@ -1013,6 +1018,25 @@ fold_using_range::range_of_call (vrange &r, gcall 
> > > *call, fur_source &)
> > >    else
> > >      r.set_varying (type);
> > >
> > > +  tree callee = gimple_call_fndecl (call);
> > > +  if (callee
> > > +      && useless_type_conversion_p (TREE_TYPE (TREE_TYPE (callee)), 
> > > type))
> > > +    {
> > > +      Value_Range val;
> > > +      if (ipa_return_value_range (val, callee))
> > > +       {
> > > +         r.intersect (val);
> > > +         if (dump_file && (dump_flags & TDF_DETAILS))
> > > +           {
> > > +             fprintf (dump_file, "Using return value range of ");
> > > +             print_generic_expr (dump_file, callee, TDF_SLIM);
> > > +             fprintf (dump_file, ": ");
> > > +             val.dump (dump_file);
> > > +             fprintf (dump_file, "\n");
> > > +           }
> > > +       }
> > > +    }
> > > +
> > >    // If there is an LHS, intersect that with what is known.
> > >    if (lhs)
> > >      {
> > > diff --git a/gcc/ipa-prop.cc b/gcc/ipa-prop.cc
> > > index 7de2b788185..e77bc9c340b 100644
> > > --- a/gcc/ipa-prop.cc
> > > +++ b/gcc/ipa-prop.cc
> > > @@ -237,6 +237,35 @@ gt_ggc_mx (ipa_vr *&x)
> > >    return gt_ggc_mx ((ipa_vr *) x);
> > >  }
> > >
> > > +/* Analysis summery of function call return value.  */
> > > +struct GTY(()) ipa_return_value_summary
> > > +{
> > > +  /* Known value range.
> > > +     This needs to be wrapped in struccture due to specific way
> > > +     we allocate ipa_vr. */
> > > +  ipa_vr *vr;
> > > +};
> > > +
> > > +/* Function summary for return values.  */
> > > +class ipa_return_value_sum_t : public function_summary 
> > > <ipa_return_value_summary *>
> > > +{
> > > +public:
> > > +  ipa_return_value_sum_t (symbol_table *table, bool ggc):
> > > +    function_summary <ipa_return_value_summary *> (table, ggc) { }
> > > +
> > > +  /* Hook that is called by summary when a node is duplicated.  */
> > > +  void duplicate (cgraph_node *,
> > > +                 cgraph_node *,
> > > +                 ipa_return_value_summary *data,
> > > +                 ipa_return_value_summary *data2) final override
> > > +  {
> > > +    *data2=*data;
> > > +  }
> > > +};
> > > +
> > > +/* Variable hoding the return value summary.  */
> > > +static GTY(()) function_summary <ipa_return_value_summary *> 
> > > *ipa_return_value_sum;
> > > +
> > >
> > >  /* Return true if DECL_FUNCTION_SPECIFIC_OPTIMIZATION of the decl 
> > > associated
> > >     with NODE should prevent us from analyzing it for the purposes of 
> > > IPA-CP.  */
> > > @@ -5915,5 +5944,49 @@ ipcp_transform_function (struct cgraph_node *node)
> > >    return modified_mem_access ? TODO_update_ssa_only_virtuals : 0;
> > >  }
> > >
> > > +/* Record that current function return value range is VAL.  */
> > > +
> > > +void
> > > +ipa_record_return_value_range (Value_Range val)
> > > +{
> > > +  cgraph_node *n = cgraph_node::get (current_function_decl);
> > > +  if (!ipa_return_value_sum)
> > > +    {
> > > +      if (!ipa_vr_hash_table)
> > > +       ipa_vr_hash_table = 
> > > hash_table<ipa_vr_ggc_hash_traits>::create_ggc (37);
> > > +      ipa_return_value_sum = new (ggc_alloc_no_dtor 
> > > <ipa_return_value_sum_t> ())
> > > +             ipa_return_value_sum_t (symtab, true);
> > > +      ipa_return_value_sum->disable_insertion_hook ();
> > > +    }
> > > +  ipa_return_value_sum->get_create (n)->vr = ipa_get_value_range (val);
> > > +  if (dump_file && (dump_flags & TDF_DETAILS))
> > > +    {
> > > +      fprintf (dump_file, "Recording return range ");
> > > +      val.dump (dump_file);
> > > +      fprintf (dump_file, "\n");
> > > +    }
> > > +}
> > > +
> > > +/* Return true if value range of DECL is known and if so initialize 
> > > RANGE.  */
> > > +
> > > +bool
> > > +ipa_return_value_range (Value_Range &range, tree decl)
> > > +{
> > > +  cgraph_node *n = cgraph_node::get (decl);
> > > +  if (!n || !ipa_return_value_sum)
> > > +    return false;
> > > +  enum availability avail;
> > > +  n = n->ultimate_alias_target (&avail);
> > > +  if (avail < AVAIL_AVAILABLE)
> > > +    return false;
> > > +  if (n->decl != decl && !useless_type_conversion_p (TREE_TYPE (decl), 
> > > TREE_TYPE (n->decl)))
> > > +    return false;
> > > +  ipa_return_value_summary *v = ipa_return_value_sum->get (n);
> > > +  if (!v)
> > > +    return false;
> > > +  v->vr->get_vrange (range);
> > > +  return true;
> > > +}
> > > +
> > >
> > >  #include "gt-ipa-prop.h"
> > > diff --git a/gcc/ipa-prop.h b/gcc/ipa-prop.h
> > > index fcd0e5c638f..5901c805c40 100644
> > > --- a/gcc/ipa-prop.h
> > > +++ b/gcc/ipa-prop.h
> > > @@ -309,7 +309,7 @@ public:
> > >    void get_vrange (Value_Range &) const;
> > >    bool equal_p (const vrange &) const;
> > >    const vrange_storage *storage () const { return m_storage; }
> > > -  void streamer_read (lto_input_block *, data_in *);
> > > +  void streamer_read (lto_input_block *, class data_in *);
> > >    void streamer_write (output_block *) const;
> > >    void dump (FILE *) const;
> > >
> > > @@ -1274,4 +1274,7 @@ ipa_range_set_and_normalize (vrange &r, tree val)
> > >      r.set (val, val);
> > >  }
> > >
> > > +bool ipa_return_value_range (Value_Range &range, tree decl);
> > > +void ipa_record_return_value_range (Value_Range val);
> > > +
> > >  #endif /* IPA_PROP_H */
> > > diff --git a/gcc/ipa-pure-const.cc b/gcc/ipa-pure-const.cc
> > > index 058a7dd3019..3060ffeefcd 100644
> > > --- a/gcc/ipa-pure-const.cc
> > > +++ b/gcc/ipa-pure-const.cc
> > > @@ -292,6 +292,15 @@ warn_function_cold (tree decl)
> > >                          true, warned_about, "cold");
> > >  }
> > >
> > > +void
> > > +warn_function_returns_nonnull (tree decl)
> > > +{
> > > +  static hash_set<tree> *warned_about;
> > > +  warned_about
> > > +    = suggest_attribute (OPT_Wsuggest_attribute_returns_nonnull, decl,
> > > +                        true, warned_about, "returns_nonnull");
> > > +}
> > > +
> > >  /* Check to see if the use (or definition when CHECKING_WRITE is true)
> > >     variable T is legal in a function that is either pure or const.  */
> > >
> > > diff --git a/gcc/ipa-utils.h b/gcc/ipa-utils.h
> > > index 0eefcf40d44..84728c589ea 100644
> > > --- a/gcc/ipa-utils.h
> > > +++ b/gcc/ipa-utils.h
> > > @@ -105,6 +105,7 @@ tree prevailing_odr_type (tree type);
> > >  void enable_odr_based_tbaa (tree type);
> > >  bool odr_based_tbaa_p (const_tree type);
> > >  void set_type_canonical_for_odr_type (tree type, tree canonical);
> > > +void warn_function_returns_nonnull (tree);
> > >
> > >  void register_odr_enum (tree type);
> > >
> > > diff --git a/gcc/symbol-summary.h b/gcc/symbol-summary.h
> > > index 3ed61627382..5fd49a2552e 100644
> > > --- a/gcc/symbol-summary.h
> > > +++ b/gcc/symbol-summary.h
> > > @@ -71,7 +71,7 @@ public:
> > >         = m_symtab->add_cgraph_insertion_hook (m_symtab_insertion, this);
> > >    }
> > >
> > > -  /* Enable insertion hook invocation.  */
> > > +  /* Disable insertion hook invocation.  */
> > >    void disable_insertion_hook ()
> > >    {
> > >      if (m_symtab_insertion_hook != NULL)
> > > diff --git a/gcc/testsuite/g++.dg/ipa/devirt-2.C 
> > > b/gcc/testsuite/g++.dg/ipa/devirt-2.C
> > > index 48a94e09828..1797db6c81c 100644
> > > --- a/gcc/testsuite/g++.dg/ipa/devirt-2.C
> > > +++ b/gcc/testsuite/g++.dg/ipa/devirt-2.C
> > > @@ -43,7 +43,7 @@ int C::foo (int i)
> > >    return i + 3;
> > >  }
> > >
> > > -int __attribute__ ((noinline,noclone)) get_input(void)
> > > +int __attribute__ ((noinline,noclone,noipa)) get_input(void)
> > >  {
> > >    return 1;
> > >  }
> > > diff --git a/gcc/testsuite/g++.dg/ipa/devirt-7.C 
> > > b/gcc/testsuite/g++.dg/ipa/devirt-7.C
> > > index f27a264fd1e..b24b2bca5f9 100644
> > > --- a/gcc/testsuite/g++.dg/ipa/devirt-7.C
> > > +++ b/gcc/testsuite/g++.dg/ipa/devirt-7.C
> > > @@ -1,7 +1,7 @@
> > >  /* Verify that IPA-CP can do devirtualization even if the virtual call
> > >     comes from a method that has been early-inlined into a descendant.  */
> > >  /* { dg-do run } */
> > > -/* { dg-options "-O3 -fdump-ipa-cp"  } */
> > > +/* { dg-options "-O3 -fdump-ipa-cp -fno-ipa-vrp"  } */
> > >  /* { dg-add-options bind_pic_locally } */
> > >
> > >  extern "C" void abort (void);
> > > diff --git a/gcc/testsuite/g++.dg/ipa/ipa-icf-2.C 
> > > b/gcc/testsuite/g++.dg/ipa/ipa-icf-2.C
> > > index 7f56189eebb..ae121e8a762 100644
> > > --- a/gcc/testsuite/g++.dg/ipa/ipa-icf-2.C
> > > +++ b/gcc/testsuite/g++.dg/ipa/ipa-icf-2.C
> > > @@ -1,5 +1,5 @@
> > >  /* { dg-do compile } */
> > > -/* { dg-options "-O2 -fdump-ipa-icf-optimized"  } */
> > > +/* { dg-options "-O2 -fdump-ipa-icf-optimized -fno-ipa-vrp"  } */
> > >
> > >  class A
> > >  {
> > > diff --git a/gcc/testsuite/g++.dg/ipa/ipa-icf-3.C 
> > > b/gcc/testsuite/g++.dg/ipa/ipa-icf-3.C
> > > index 5a3cca24fa2..03c10f12db2 100644
> > > --- a/gcc/testsuite/g++.dg/ipa/ipa-icf-3.C
> > > +++ b/gcc/testsuite/g++.dg/ipa/ipa-icf-3.C
> > > @@ -1,5 +1,5 @@
> > >  /* { dg-do compile } */
> > > -/* { dg-options "-O2 -fdump-ipa-icf-optimized"  } */
> > > +/* { dg-options "-O2 -fdump-ipa-icf-optimized -fno-ipa-vrp"  } */
> > >
> > >  __attribute__ ((noinline))
> > >  int zero()
> > > diff --git a/gcc/testsuite/g++.dg/ipa/ivinline-1.C 
> > > b/gcc/testsuite/g++.dg/ipa/ivinline-1.C
> > > index 2d988bc6d55..ccb1870ec69 100644
> > > --- a/gcc/testsuite/g++.dg/ipa/ivinline-1.C
> > > +++ b/gcc/testsuite/g++.dg/ipa/ivinline-1.C
> > > @@ -1,7 +1,7 @@
> > >  /* Verify that simple virtual calls are inlined even without early
> > >     inlining.  */
> > >  /* { dg-do run { target { nonpic || pie_enabled } } } */
> > > -/* { dg-options "-O3 -fdump-ipa-inline -fno-early-inlining -fno-ipa-cp"  
> > > } */
> > > +/* { dg-options "-O3 -fdump-ipa-inline -fno-early-inlining -fno-ipa-cp 
> > > -fno-ipa-vrp"  } */
> > >
> > >  extern "C" void abort (void);
> > >
> > > diff --git a/gcc/testsuite/g++.dg/ipa/ivinline-3.C 
> > > b/gcc/testsuite/g++.dg/ipa/ivinline-3.C
> > > index f756a16bae9..02e7e443fa9 100644
> > > --- a/gcc/testsuite/g++.dg/ipa/ivinline-3.C
> > > +++ b/gcc/testsuite/g++.dg/ipa/ivinline-3.C
> > > @@ -1,7 +1,7 @@
> > >  /* Verify that simple virtual calls on an object refrence are inlined
> > >     even without early inlining.  */
> > >  /* { dg-do run { target { nonpic || pie_enabled } } } */
> > > -/* { dg-options "-O3 -fdump-ipa-inline -fno-early-inlining -fno-ipa-cp"  
> > > } */
> > > +/* { dg-options "-O3 -fdump-ipa-inline -fno-early-inlining -fno-ipa-cp 
> > > -fno-ipa-vrp"  } */
> > >
> > >  extern "C" void abort (void);
> > >
> > > diff --git a/gcc/testsuite/g++.dg/ipa/ivinline-5.C 
> > > b/gcc/testsuite/g++.dg/ipa/ivinline-5.C
> > > index 6c19907686e..cb889d1e84f 100644
> > > --- a/gcc/testsuite/g++.dg/ipa/ivinline-5.C
> > > +++ b/gcc/testsuite/g++.dg/ipa/ivinline-5.C
> > > @@ -1,7 +1,7 @@
> > >  /* Verify that virtual call inlining does not pick a wrong method when
> > >     there is a user defined ancestor in an object.  */
> > >  /* { dg-do run { target { nonpic || pie_enabled } } } */
> > > -/* { dg-options "-O3 -fdump-ipa-inline -fno-early-inlining -fno-ipa-cp"  
> > > } */
> > > +/* { dg-options "-O3 -fdump-ipa-inline -fno-early-inlining -fno-ipa-cp 
> > > -fno-ipa-vrp"  } */
> > >
> > >  extern "C" void abort (void);
> > >
> > > diff --git a/gcc/testsuite/g++.dg/ipa/ivinline-8.C 
> > > b/gcc/testsuite/g++.dg/ipa/ivinline-8.C
> > > index bc81abfe347..f29e818e357 100644
> > > --- a/gcc/testsuite/g++.dg/ipa/ivinline-8.C
> > > +++ b/gcc/testsuite/g++.dg/ipa/ivinline-8.C
> > > @@ -1,7 +1,7 @@
> > >  /* Verify that virtual calls are inlined (ithout early inlining) even
> > >     when their caller is itself indirectly inlined.  */
> > >  /* { dg-do run { target { nonpic || pie_enabled } } } */
> > > -/* { dg-options "-O3 -fdump-ipa-inline -fno-early-inlining -fno-ipa-cp"  
> > > } */
> > > +/* { dg-options "-O3 -fdump-ipa-inline -fno-early-inlining -fno-ipa-cp 
> > > -fno-ipa-vrp"  } */
> > >
> > >  extern "C" void abort (void);
> > >
> > > diff --git a/gcc/testsuite/g++.dg/ipa/nothrow-1.C 
> > > b/gcc/testsuite/g++.dg/ipa/nothrow-1.C
> > > index b30b0215924..1f243109619 100644
> > > --- a/gcc/testsuite/g++.dg/ipa/nothrow-1.C
> > > +++ b/gcc/testsuite/g++.dg/ipa/nothrow-1.C
> > > @@ -1,5 +1,5 @@
> > >  /* { dg-do compile } */
> > > -/* { dg-options "-O2 -fnon-call-exceptions -fdump-tree-optimized"  } */
> > > +/* { dg-options "-O2 -fnon-call-exceptions -fdump-tree-optimized 
> > > -fno-ipa-vrp"  } */
> > >  int *ptr;
> > >  static int barvar;
> > >
> > > diff --git a/gcc/testsuite/g++.dg/ipa/pure-const-1.C 
> > > b/gcc/testsuite/g++.dg/ipa/pure-const-1.C
> > > index 61940c670e7..c18278cae11 100644
> > > --- a/gcc/testsuite/g++.dg/ipa/pure-const-1.C
> > > +++ b/gcc/testsuite/g++.dg/ipa/pure-const-1.C
> > > @@ -1,5 +1,5 @@
> > >  /* { dg-do compile } */
> > > -/* { dg-options "-O2 -fdump-tree-optimized"  } */
> > > +/* { dg-options "-O2 -fdump-tree-optimized -fno-ipa-vrp"  } */
> > >  int *ptr;
> > >  static int barvar;
> > >
> > > diff --git a/gcc/testsuite/g++.dg/ipa/pure-const-2.C 
> > > b/gcc/testsuite/g++.dg/ipa/pure-const-2.C
> > > index 6e739de4ade..d5f18bfa9be 100644
> > > --- a/gcc/testsuite/g++.dg/ipa/pure-const-2.C
> > > +++ b/gcc/testsuite/g++.dg/ipa/pure-const-2.C
> > > @@ -1,5 +1,5 @@
> > >  /* { dg-do compile } */
> > > -/* { dg-options "-O2 -fdump-tree-optimized"  } */
> > > +/* { dg-options "-O2 -fdump-tree-optimized -fno-ipa-vrp"  } */
> > >  int *ptr;
> > >  static int barvar;
> > >  /* We can not detect A to be const because it may be interposed by 
> > > unoptimized
> > > diff --git a/gcc/testsuite/g++.dg/lto/inline-crossmodule-1_0.C 
> > > b/gcc/testsuite/g++.dg/lto/inline-crossmodule-1_0.C
> > > index 0294dcc4bfb..c56360ef66e 100644
> > > --- a/gcc/testsuite/g++.dg/lto/inline-crossmodule-1_0.C
> > > +++ b/gcc/testsuite/g++.dg/lto/inline-crossmodule-1_0.C
> > > @@ -1,5 +1,5 @@
> > >  // { dg-lto-do link }
> > > -/* { dg-lto-options { "-O2 -fno-early-inlining -fno-implicit-constexpr 
> > > -flto -fdump-ipa-inline-details" } } */
> > > +/* { dg-lto-options { "-O2 -fno-early-inlining -fno-implicit-constexpr 
> > > -flto -fdump-ipa-inline-details -fno-ipa-vrp" } } */
> > >  #include "inline-crossmodule-1.h"
> > >  int a::key ()
> > >  {
> > > diff --git a/gcc/testsuite/gcc.c-torture/compile/pr106433.c 
> > > b/gcc/testsuite/gcc.c-torture/compile/pr106433.c
> > > index b840e5ecd93..e02ad5ffe15 100644
> > > --- a/gcc/testsuite/gcc.c-torture/compile/pr106433.c
> > > +++ b/gcc/testsuite/gcc.c-torture/compile/pr106433.c
> > > @@ -2,7 +2,7 @@
> > >
> > >  int m, *p;
> > >
> > > -__attribute__ ((simd)) int
> > > +__attribute__ ((simd,noipa)) int
> > >  bar (int x)
> > >  {
> > >    if (x)
> > > diff --git a/gcc/testsuite/gcc.c-torture/execute/frame-address.c 
> > > b/gcc/testsuite/gcc.c-torture/execute/frame-address.c
> > > index 5afa691e409..5950581054d 100644
> > > --- a/gcc/testsuite/gcc.c-torture/execute/frame-address.c
> > > +++ b/gcc/testsuite/gcc.c-torture/execute/frame-address.c
> > > @@ -1,10 +1,10 @@
> > >  /* { dg-require-effective-target return_address } */
> > >  void abort (void);
> > >
> > > -int check_fa_work (const char *, const char *) __attribute__((noinline));
> > > -int check_fa_mid (const char *) __attribute__((noinline));
> > > -int check_fa (char *) __attribute__((noinline));
> > > -int how_much (void) __attribute__((noinline));
> > > +int check_fa_work (const char *, const char *) 
> > > __attribute__((noinline,noipa));
> > > +int check_fa_mid (const char *) __attribute__((noinline,noipa));
> > > +int check_fa (char *) __attribute__((noinline,noipa));
> > > +int how_much (void) __attribute__((noinline,noipa));
> > >
> > >  int check_fa_work (const char *c, const char *f)
> > >  {
> > > diff --git a/gcc/testsuite/gcc.dg/ipa/fopt-info-inline-1.c 
> > > b/gcc/testsuite/gcc.dg/ipa/fopt-info-inline-1.c
> > > index 4032ad13e19..155a6829b88 100644
> > > --- a/gcc/testsuite/gcc.dg/ipa/fopt-info-inline-1.c
> > > +++ b/gcc/testsuite/gcc.dg/ipa/fopt-info-inline-1.c
> > > @@ -1,4 +1,4 @@
> > > -/* { dg-options "-O3 -fopt-info-inline-optimized-missed" } */
> > > +/* { dg-options "-O3 -fopt-info-inline-optimized-missed -fno-ipa-vrp" } 
> > > */
> > >
> > >  static int foo (int a)
> > >  {
> > > diff --git a/gcc/testsuite/gcc.dg/ipa/ipa-icf-25.c 
> > > b/gcc/testsuite/gcc.dg/ipa/ipa-icf-25.c
> > > index fad0891283e..cbda6858890 100644
> > > --- a/gcc/testsuite/gcc.dg/ipa/ipa-icf-25.c
> > > +++ b/gcc/testsuite/gcc.dg/ipa/ipa-icf-25.c
> > > @@ -1,5 +1,5 @@
> > >  /* { dg-do compile } */
> > > -/* { dg-options "-O2 -fdump-ipa-icf-optimized-all"  } */
> > > +/* { dg-options "-O2 -fdump-ipa-icf-optimized-all -fno-ipa-vrp"  } */
> > >
> > >  static int zip();
> > >  static int zap();
> > > diff --git a/gcc/testsuite/gcc.dg/ipa/ipa-icf-38.c 
> > > b/gcc/testsuite/gcc.dg/ipa/ipa-icf-38.c
> > > index 57c5262dd4a..a8824d040e5 100644
> > > --- a/gcc/testsuite/gcc.dg/ipa/ipa-icf-38.c
> > > +++ b/gcc/testsuite/gcc.dg/ipa/ipa-icf-38.c
> > > @@ -1,6 +1,6 @@
> > >  /* { dg-do link } */
> > >  /* { dg-require-alias "" } */
> > > -/* { dg-options "-O2 -fdump-ipa-icf-optimized -flto 
> > > -fdump-tree-optimized" } */
> > > +/* { dg-options "-O2 -fdump-ipa-icf-optimized -flto 
> > > -fdump-tree-optimized -fno-ipa-vrp" } */
> > >  /* { dg-require-effective-target lto } */
> > >  /* { dg-additional-sources "ipa-icf-38a.c" }*/
> > >
> > > diff --git a/gcc/testsuite/gcc.dg/ipa/pure-const-1.c 
> > > b/gcc/testsuite/gcc.dg/ipa/pure-const-1.c
> > > index dd58457b629..10b572781c7 100644
> > > --- a/gcc/testsuite/gcc.dg/ipa/pure-const-1.c
> > > +++ b/gcc/testsuite/gcc.dg/ipa/pure-const-1.c
> > > @@ -1,5 +1,5 @@
> > >  /* { dg-do compile { target { nonpic || pie_enabled } } } */
> > > -/* { dg-options "-O3 -fdump-tree-local-pure-const1 -fdump-ipa-pure-const 
> > > -fdump-tree-optimized -fno-early-inlining -fgnu89-inline" } */
> > > +/* { dg-options "-O3 -fno-ipa-vrp -fdump-tree-local-pure-const1 
> > > -fdump-ipa-pure-const -fdump-tree-optimized -fno-early-inlining 
> > > -fgnu89-inline" } */
> > >  void abort (void);
> > >  int error_code;
> > >  static int val;
> > > diff --git a/gcc/testsuite/gcc.dg/ipa/remref-0.c 
> > > b/gcc/testsuite/gcc.dg/ipa/remref-0.c
> > > index 6073c028a98..497136e3607 100644
> > > --- a/gcc/testsuite/gcc.dg/ipa/remref-0.c
> > > +++ b/gcc/testsuite/gcc.dg/ipa/remref-0.c
> > > @@ -3,7 +3,7 @@
> > >  /* { dg-do compile } */
> > >  /* { dg-options "-O3 -fno-early-inlining -fno-ipa-sra -fno-ipa-cp 
> > > -fdump-ipa-inline -fdump-tree-optimized"  } */
> > >
> > > -extern int __attribute__ ((noinline, noclone, used))
> > > +extern int __attribute__ ((noinline, noclone, used, noipa))
> > >  stuff (int i)
> > >  {
> > >    return 0;
> > > diff --git a/gcc/testsuite/gcc.dg/tree-prof/time-profiler-1.c 
> > > b/gcc/testsuite/gcc.dg/tree-prof/time-profiler-1.c
> > > index 455f923f3f4..3f1d1e04619 100644
> > > --- a/gcc/testsuite/gcc.dg/tree-prof/time-profiler-1.c
> > > +++ b/gcc/testsuite/gcc.dg/tree-prof/time-profiler-1.c
> > > @@ -1,4 +1,4 @@
> > > -/* { dg-options "-O2 -fdump-ipa-profile" } */
> > > +/* { dg-options "-O2 -fdump-ipa-profile -fno-ipa-vrp" } */
> > >
> > >  __attribute__ ((noinline))
> > >  int foo()
> > > diff --git a/gcc/testsuite/gcc.dg/tree-prof/time-profiler-2.c 
> > > b/gcc/testsuite/gcc.dg/tree-prof/time-profiler-2.c
> > > index e6eaeb99810..eed0b1dd08d 100644
> > > --- a/gcc/testsuite/gcc.dg/tree-prof/time-profiler-2.c
> > > +++ b/gcc/testsuite/gcc.dg/tree-prof/time-profiler-2.c
> > > @@ -1,4 +1,4 @@
> > > -/* { dg-options "-O2 -fdump-ipa-profile" } */
> > > +/* { dg-options "-O2 -fdump-ipa-profile -fno-ipa-vrp" } */
> > >
> > >  #include <unistd.h>
> > >
> > > diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr110269.c 
> > > b/gcc/testsuite/gcc.dg/tree-ssa/pr110269.c
> > > index c68a6f91604..dd5022f3b0c 100644
> > > --- a/gcc/testsuite/gcc.dg/tree-ssa/pr110269.c
> > > +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr110269.c
> > > @@ -1,5 +1,5 @@
> > >  /* { dg-do compile } */
> > > -/* { dg-options "-O2 -fdump-tree-ccp2 -fdump-tree-optimized" } */
> > > +/* { dg-options "-O2 -fdump-tree-ccp2 -fdump-tree-optimized 
> > > -fno-ipa-vrp" } */
> > >
> > >  void foo(void);
> > >  static int a = 1, c;
> > > diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr20701.c 
> > > b/gcc/testsuite/gcc.dg/tree-ssa/pr20701.c
> > > index f05076cafac..3a7c03b27ff 100644
> > > --- a/gcc/testsuite/gcc.dg/tree-ssa/pr20701.c
> > > +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr20701.c
> > > @@ -1,5 +1,5 @@
> > >  /* { dg-do compile } */
> > > -/* { dg-options "-O2 -fdump-tree-vrp1 -fno-early-inlining 
> > > -fdelete-null-pointer-checks -fno-thread-jumps" } */
> > > +/* { dg-options "-O2 -fdump-tree-vrp1 -fno-early-inlining 
> > > -fdelete-null-pointer-checks -fno-thread-jumps -fno-ipa-vrp" } */
> > >
> > >  typedef struct {
> > >    int code;
> > > diff --git a/gcc/testsuite/gcc.dg/tree-ssa/return-value-range-1.c 
> > > b/gcc/testsuite/gcc.dg/tree-ssa/return-value-range-1.c
> > > new file mode 100644
> > > index 00000000000..4db52233c5d
> > > --- /dev/null
> > > +++ b/gcc/testsuite/gcc.dg/tree-ssa/return-value-range-1.c
> > > @@ -0,0 +1,22 @@
> > > +/* { dg-do ling } */
> > > +/* { dg-options "-O1 -dump-tree-evrp-details" } */
> > > +__attribute__ ((__noinline__))
> > > +int a(char c)
> > > +{
> > > +       return c;
> > > +}
> > > +void link_error ();
> > > +
> > > +void
> > > +test(int d)
> > > +{
> > > +       if (a(d) > 200)
> > > +               link_error ();
> > > +}
> > > +int
> > > +main(int argc, char **argv)
> > > +{
> > > +       test(argc);
> > > +       return 0;
> > > +}
> > > +/* { dg-final { scan-tree-dump-times "Recording return range" 2 "evrp"} 
> > > } */
> > > diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp05.c 
> > > b/gcc/testsuite/gcc.dg/tree-ssa/vrp05.c
> > > index 7f38e8d3852..f7ba16c20bb 100644
> > > --- a/gcc/testsuite/gcc.dg/tree-ssa/vrp05.c
> > > +++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp05.c
> > > @@ -1,5 +1,5 @@
> > >  /* { dg-do compile } */
> > > -/* { dg-options "-O2 -fdump-tree-vrp1 -fno-early-inlining 
> > > -fno-thread-jumps" } */
> > > +/* { dg-options "-O2 -fdump-tree-vrp1 -fno-early-inlining 
> > > -fno-thread-jumps -fno-ipa-vrp" } */
> > >
> > >
> > >  inline int ten()
> > > diff --git a/gcc/tree-vrp.cc b/gcc/tree-vrp.cc
> > > index 917fa873714..82001eff20e 100644
> > > --- a/gcc/tree-vrp.cc
> > > +++ b/gcc/tree-vrp.cc
> > > @@ -52,6 +52,12 @@ along with GCC; see the file COPYING3.  If not see
> > >  #include "gimple-fold.h"
> > >  #include "tree-dfa.h"
> > >  #include "tree-ssa-dce.h"
> > > +#include "alloc-pool.h"
> > > +#include "cgraph.h"
> > > +#include "symbol-summary.h"
> > > +#include "ipa-utils.h"
> > > +#include "ipa-prop.h"
> > > +#include "attribs.h"
> > >
> > >  // This class is utilized by VRP and ranger to remove 
> > > __builtin_unreachable
> > >  // calls, and reflect any resulting global ranges.
> > > @@ -1081,6 +1087,51 @@ execute_ranger_vrp (struct function *fun, bool 
> > > warn_array_bounds_p,
> > >        array_checker.check ();
> > >      }
> > >
> > > +
> > > +  if (Value_Range::supports_type_p (TREE_TYPE
> > > +                                    (TREE_TYPE (current_function_decl)))
> > > +      && flag_ipa_vrp
> > > +      && !lookup_attribute ("noipa", DECL_ATTRIBUTES 
> > > (current_function_decl)))
> > > +    {
> > > +      edge e;
> > > +      edge_iterator ei;
> > > +      bool found = false;
> > > +      Value_Range return_range (TREE_TYPE (TREE_TYPE 
> > > (current_function_decl)));
> > > +      FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR_FOR_FN (cfun)->preds)
> > > +       if (greturn *ret = dyn_cast <greturn *> (*gsi_last_bb (e->src)))
> > > +         {
> > > +           tree retval = gimple_return_retval (ret);
> > > +           if (!retval)
> > > +             {
> > > +               return_range.set_varying (TREE_TYPE (TREE_TYPE 
> > > (current_function_decl)));
> > > +               found = true;
> > > +               continue;
> > > +             }
> > > +           Value_Range r (TREE_TYPE (retval));
> > > +           if (ranger->range_of_expr (r, retval, ret)
> > > +               && !r.undefined_p ()
> > > +               && !r.varying_p ())
> > > +             {
> > > +               if (!found)
> > > +                 return_range = r;
> > > +               else
> > > +                 return_range.union_ (r);
> > > +             }
> > > +           else
> > > +             return_range.set_varying (TREE_TYPE (retval));
> > > +           found = true;
> > > +         }
> > > +      if (found && !return_range.varying_p ())
> > > +       {
> > > +         ipa_record_return_value_range (return_range);
> > > +         if (POINTER_TYPE_P (TREE_TYPE (TREE_TYPE 
> > > (current_function_decl)))
> > > +             && return_range.nonzero_p ()
> > > +             && cgraph_node::get (current_function_decl)
> > > +                       ->add_detected_attribute ("returns_nonnull"))
> > > +           warn_function_returns_nonnull (current_function_decl);
> > > +       }
> > > +    }
> > > +
> > >    phi_analysis_finalize ();
> > >    disable_ranger (fun);
> > >    scev_finalize ();

Reply via email to