The following fixes a missed vectorization of std::min() when only one argument is a temporary. The following patch is the least intrusive and safest one - PRE already performs the necessary work to make this vectorizable, it's just that we end up with a dead store and clobber of a stack-local that the vectorizer is not happy about. The easiest fix is to schedule an update-address-taken phase at the right spot which rewrites it into SSA and then DCE can get rid of it. DSE would also do the job but is more expensive. Since PRE/VN have the chance to expose things that can be written into SSA doing so before loop opts sounds like a good idea in any case.
Bootstrap & regtest running on x86_64-unknown-linux-gnu. Queued for GCC 10 for which I also have a fix for phiprop which usually deals with std::min/max if-conversion. The one below is quite safe but it's not a regression unfortunately. Richard. 2019-03-11 Richard Biener <[email protected]> PR tree-optimization/89653 * tree-ssa-loop.c (pass_data_tree_loop_init): Execute update-address-taken before the pass. * passes.def (pass_tree_loop_init): Put comment before it. * g++.dg/vect/pr89653.cc: New testcase. Index: gcc/tree-ssa-loop.c =================================================================== --- gcc/tree-ssa-loop.c (revision 269569) +++ gcc/tree-ssa-loop.c (working copy) @@ -330,7 +330,7 @@ const pass_data pass_data_tree_loop_init PROP_cfg, /* properties_required */ 0, /* properties_provided */ 0, /* properties_destroyed */ - 0, /* todo_flags_start */ + TODO_update_address_taken, /* todo_flags_start */ 0, /* todo_flags_finish */ }; Index: gcc/passes.def =================================================================== --- gcc/passes.def (revision 269569) +++ gcc/passes.def (working copy) @@ -261,6 +261,8 @@ along with GCC; see the file COPYING3. NEXT_PASS (pass_fix_loops); NEXT_PASS (pass_tree_loop); PUSH_INSERT_PASSES_WITHIN (pass_tree_loop) + /* Before loop_init we rewrite no longer addressed locals into SSA + form if possible. */ NEXT_PASS (pass_tree_loop_init); NEXT_PASS (pass_tree_unswitch); NEXT_PASS (pass_scev_cprop); Index: gcc/testsuite/g++.dg/vect/pr89653.cc =================================================================== --- gcc/testsuite/g++.dg/vect/pr89653.cc (nonexistent) +++ gcc/testsuite/g++.dg/vect/pr89653.cc (working copy) @@ -0,0 +1,12 @@ +// { dg-do compile } +// { dg-require-effective-target vect_double } + +#include <algorithm> + +void loop1(double * const __restrict__ vec, double x, int end) +{ + for (int i = 0; i < end; ++i) + vec[i] = std::min(vec[i], vec[i]/x); +} + +// { dg-final { scan-tree-dump "vectorized 1 loops" "vect" } }
