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.

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