On 2/16/19 12:12 AM, Jakub Jelinek wrote:
Hi!

Both the C and C++ standard guarantee that the argc argument to main is
non-negative, the following patch sets (or adjusts) the corresponding
SSA_NAME_RANGE_INFO.  While main is just one, with IPA VRP it can also
propagate etc.  I had to change one testcase because it started optimizing
it better (the test has been folded away), so no sinking was done.

If/when this goes in it might make sense to also set argv and argv[0]
to nonnull.

Martin


Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2019-02-16  Jakub Jelinek  <ja...@redhat.com>

        PR tree-optimization/89350
        * gimple-ssa-evrp.c: Include tree-dfa.h and langhooks.h.
        (maybe_set_main_argc_range): New function.
        (execute_early_vrp): Call it.

        * gcc.dg/tree-ssa/vrp122.c: New test.
        * gcc.dg/tree-ssa/ssa-sink-3.c (main): Rename to ...
        (bar): ... this.

--- gcc/gimple-ssa-evrp.c.jj    2019-01-01 12:37:15.712998659 +0100
+++ gcc/gimple-ssa-evrp.c       2019-02-15 09:49:56.768534668 +0100
@@ -41,6 +41,8 @@ along with GCC; see the file COPYING3.
  #include "tree-cfgcleanup.h"
  #include "vr-values.h"
  #include "gimple-ssa-evrp-analyze.h"
+#include "tree-dfa.h"
+#include "langhooks.h"
class evrp_folder : public substitute_and_fold_engine
  {
@@ -291,6 +293,39 @@ evrp_dom_walker::cleanup (void)
    evrp_folder.vr_values->cleanup_edges_and_switches ();
  }
+/* argc in main in C/C++ is guaranteed to be non-negative. Adjust the
+   range info for it.  */
+
+static void
+maybe_set_main_argc_range (void)
+{
+  if (!DECL_ARGUMENTS (current_function_decl)
+      || !(lang_GNU_C () || lang_GNU_CXX () || lang_GNU_OBJC ()))
+    return;
+
+  tree argc = DECL_ARGUMENTS (current_function_decl);
+  if (TYPE_MAIN_VARIANT (TREE_TYPE (argc)) != integer_type_node)
+    return;
+
+  argc = ssa_default_def (cfun, argc);
+  if (argc == NULL_TREE)
+    return;
+
+  wide_int min, max;
+  value_range_kind kind = get_range_info (argc, &min, &max);
+  if (kind == VR_VARYING)
+    {
+      min = wi::zero (TYPE_PRECISION (integer_type_node));
+      max = wi::to_wide (TYPE_MAX_VALUE (integer_type_node));
+    }
+  else if (kind == VR_RANGE && wi::neg_p (min) && !wi::neg_p (max))
+    min = wi::zero (TYPE_PRECISION (integer_type_node));
+  else
+    return;
+
+  set_range_info (argc, VR_RANGE, min, max);
+}
+
  /* Main entry point for the early vrp pass which is a simplified non-iterative
     version of vrp where basic blocks are visited in dominance order.  Value
     ranges discovered in early vrp will also be used by ipa-vrp.  */
@@ -307,6 +342,10 @@ execute_early_vrp ()
    scev_initialize ();
    calculate_dominance_info (CDI_DOMINATORS);
+ /* argc in main in C/C++ is guaranteed to be non-negative. */
+  if (MAIN_NAME_P (DECL_NAME (current_function_decl)))
+    maybe_set_main_argc_range ();
+
    /* Walk stmts in dominance order and propagate VRP.  */
    evrp_dom_walker walker;
    walker.walk (ENTRY_BLOCK_PTR_FOR_FN (cfun));
--- gcc/testsuite/gcc.dg/tree-ssa/vrp122.c.jj   2019-02-15 09:54:07.016357759 
+0100
+++ gcc/testsuite/gcc.dg/tree-ssa/vrp122.c      2019-02-15 09:53:59.299486561 
+0100
@@ -0,0 +1,14 @@
+/* PR tree-optimization/89350 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+/* { dg-final { scan-tree-dump-not "link_error \\\(" "optimized" } } */
+
+extern void link_error (void);
+
+int
+main (int argc, const char *argv[])
+{
+  if (argc < 0)
+    link_error ();
+  return 0;
+}
--- gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-3.c.jj       2015-05-29 
15:03:44.947546711 +0200
+++ gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-3.c  2019-02-16 08:04:29.951126611 
+0100
@@ -2,7 +2,7 @@
  /* { dg-options "-O2 -fdump-tree-sink-stats" } */
  extern void foo(int a);
  int
-main (int argc)
+bar (int argc)
  {
    int a;
    a = argc + 1;

        Jakub


Reply via email to