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