]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
tree-optimization/102659 - really avoid undef overflow in if-conversion
authorRichard Biener <rguenther@suse.de>
Thu, 14 Oct 2021 07:00:25 +0000 (09:00 +0200)
committerRichard Biener <rguenther@suse.de>
Thu, 14 Oct 2021 12:58:40 +0000 (14:58 +0200)
This plugs the remaining hole of POINTER_PLUS_EXPR with undefined
overflow.  Unfortunately we have to go through some lengths to
not put invariant conversions into the loop body since that confuses
the vectorizers gather/scatter discovery which relies on identifying
an invariant component of plus and minus expressions.  We can
emit those in the loop preheader but then we have to accept that
being non-empty when looking for the LOOP_VECTORIZED internal
function call in the vectorizer.

2021-10-14  Richard Biener  <rguenther@suse.de>

PR tree-optimization/102659
* tree-if-conv.c (if_convertible_gimple_assign_stmt_p): Also
rewrite pointer typed undefined overflow operations.
(predicate_statements): Likewise.  Make sure to emit invariant
conversions in the preheader.
* tree-vectorizer.c (vect_loop_vectorized_call): Look through
non-empty preheaders.
* tree-data-ref.c (dr_analyze_indices): Strip useless
conversions to the MEM_REF base type.

gcc/tree-data-ref.c
gcc/tree-if-conv.c
gcc/tree-vectorizer.c

index 18307a554fc03f471cfa2f5e99f6b201ef667002..57bac06242fa6a427bf0390291428eb0cedd1564 100644 (file)
@@ -1370,6 +1370,7 @@ dr_analyze_indices (struct indices *dri, tree ref, edge nest, loop_p loop)
       tree op = TREE_OPERAND (ref, 0);
       tree access_fn = analyze_scalar_evolution (loop, op);
       access_fn = instantiate_scev (nest, loop, access_fn);
+      STRIP_NOPS (access_fn);
       if (TREE_CODE (access_fn) == POLYNOMIAL_CHREC)
        {
          tree memoff = TREE_OPERAND (ref, 1);
index 0b6b07cfac62a92c7fa2ecffbe691c6e896ab660..15dcc1e2b94795677051c424c384645eb2b30cf7 100644 (file)
@@ -1047,7 +1047,8 @@ if_convertible_gimple_assign_stmt_p (gimple *stmt,
        fprintf (dump_file, "tree could trap...\n");
       return false;
     }
-  else if (INTEGRAL_TYPE_P (TREE_TYPE (lhs))
+  else if ((INTEGRAL_TYPE_P (TREE_TYPE (lhs))
+           || POINTER_TYPE_P (TREE_TYPE (lhs)))
           && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (lhs))
           && arith_code_with_undefined_signed_overflow
                                (gimple_assign_rhs_code (stmt)))
@@ -2520,6 +2521,7 @@ predicate_statements (loop_p loop)
       for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi);)
        {
          gassign *stmt = dyn_cast <gassign *> (gsi_stmt (gsi));
+         tree lhs;
          if (!stmt)
            ;
          else if (is_false_predicate (cond)
@@ -2574,15 +2576,36 @@ predicate_statements (loop_p loop)
 
              gsi_replace (&gsi, new_stmt, true);
            }
-         else if (INTEGRAL_TYPE_P (TREE_TYPE (gimple_assign_lhs (stmt)))
-                  && TYPE_OVERFLOW_UNDEFINED
-                       (TREE_TYPE (gimple_assign_lhs (stmt)))
+         else if (((lhs = gimple_assign_lhs (stmt)), true)
+                  && (INTEGRAL_TYPE_P (TREE_TYPE (lhs))
+                      || POINTER_TYPE_P (TREE_TYPE (lhs)))
+                  && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (lhs))
                   && arith_code_with_undefined_signed_overflow
                                                (gimple_assign_rhs_code (stmt)))
            {
              gsi_remove (&gsi, true);
-             gsi_insert_seq_before (&gsi, rewrite_to_defined_overflow (stmt),
-                                    GSI_LAST_NEW_STMT);
+             gimple_seq stmts = rewrite_to_defined_overflow (stmt);
+             bool first = true;
+             for (gimple_stmt_iterator gsi2 = gsi_start (stmts);
+                  !gsi_end_p (gsi2);)
+               {
+                 gassign *stmt2 = as_a <gassign *> (gsi_stmt (gsi2));
+                 gsi_remove (&gsi2, false);
+                 /* Make sure to move invariant conversions out of the
+                    loop.  */
+                 if (CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (stmt2))
+                     && expr_invariant_in_loop_p (loop,
+                                                  gimple_assign_rhs1 (stmt2)))
+                   gsi_insert_on_edge_immediate (loop_preheader_edge (loop),
+                                                 stmt2);
+                 else if (first)
+                   {
+                     gsi_insert_before (&gsi, stmt2, GSI_NEW_STMT);
+                     first = false;
+                   }
+                 else
+                   gsi_insert_after (&gsi, stmt2, GSI_NEW_STMT);
+               }
            }
          else if (gimple_vdef (stmt))
            {
@@ -2601,7 +2624,7 @@ predicate_statements (loop_p loop)
              gimple_assign_set_rhs1 (stmt, ifc_temp_var (type, rhs, &gsi));
              update_stmt (stmt);
            }
-         tree lhs = gimple_get_lhs (gsi_stmt (gsi));
+         lhs = gimple_get_lhs (gsi_stmt (gsi));
          if (lhs && TREE_CODE (lhs) == SSA_NAME)
            ssa_names.add (lhs);
          gsi_next (&gsi);
index 20daa31187d31cb5e029ca9703c1e7e52f4ee96e..4712dc6e7f907637774482a71036a0bd381c2bd2 100644 (file)
@@ -852,7 +852,8 @@ vect_loop_vectorized_call (class loop *loop, gcond **cond)
   do
     {
       g = last_stmt (bb);
-      if (g)
+      if ((g && gimple_code (g) == GIMPLE_COND)
+         || !single_succ_p (bb))
        break;
       if (!single_pred_p (bb))
        break;