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