On Wed, Jun 20, 2018 at 12:28 PM Richard Sandiford <richard.sandif...@arm.com> wrote: > > Although the first pattern match wins in the sense that no later > function can match the *old* gimple statement, it still seems worth > letting them match the *new* gimple statements, just like we would if > the original IR had included that sequence from the outset. > > This is mostly true after the later patch for PR85694, where e.g. we > could recognise: > > signed char a; > int ap = (int) a; > int res = ap * 3; > > as the pattern: > > short ap' = (short) a; > short res = ap' * 3; // S1: definition statement > int res = (int) res; // S2: pattern statement > > and then apply the mult pattern to "ap' * 3". The patch needs to > come first (without its own test cases) so that the main over-widening > patch doesn't regress anything. > > Tested on aarch64-linux-gnu and x86_64-linux-gnu. OK to install?
OK. Richard. > Richard > > > 2018-06-20 Richard Sandiford <richard.sandif...@arm.com> > > gcc/ > * gimple-iterator.c (gsi_for_stmt): Add a new overload that takes > the containing gimple_seq *. > * gimple-iterator.h (gsi_for_stmt): Declare it. > * tree-vect-patterns.c (vect_recog_dot_prod_pattern) > (vect_recog_sad_pattern, vect_recog_widen_sum_pattern) > (vect_recog_widen_shift_pattern, vect_recog_rotate_pattern) > (vect_recog_vector_vector_shift_pattern, vect_recog_divmod_pattern) > (vect_recog_mask_conversion_pattern): Remove STMT_VINFO_IN_PATTERN_P > checks. > (vect_init_pattern_stmt, vect_set_pattern_stmt): New functions, > split out from... > (vect_mark_pattern_stmts): ...here. Handle cases in which the > statement being replaced is part of an existing pattern > definition sequence, inserting the new pattern statements before > the original one. > (vect_pattern_recog_1): Don't return a bool. If the statement > is already part of a pattern, instead apply pattern matching > to the pattern definition statements. Don't clear the > STMT_VINFO_RELATED_STMT if is_pattern_stmt_p. > (vect_pattern_recog): Don't break after the first match; > continue processing the pattern definition statements instead. > Don't bail out for STMT_VINFO_IN_PATTERN_P here. > > Index: gcc/gimple-iterator.c > =================================================================== > --- gcc/gimple-iterator.c 2018-05-02 08:38:09.833407589 +0100 > +++ gcc/gimple-iterator.c 2018-06-20 11:26:07.913295807 +0100 > @@ -619,6 +619,18 @@ gsi_for_stmt (gimple *stmt) > return i; > } > > +/* Get an iterator for STMT, which is known to belong to SEQ. This is > + equivalent to starting at the beginning of SEQ and searching forward > + until STMT is found. */ > + > +gimple_stmt_iterator > +gsi_for_stmt (gimple *stmt, gimple_seq *seq) > +{ > + gimple_stmt_iterator i = gsi_start_1 (seq); > + i.ptr = stmt; > + return i; > +} > + > /* Finds iterator for PHI. */ > > gphi_iterator > Index: gcc/gimple-iterator.h > =================================================================== > --- gcc/gimple-iterator.h 2018-05-02 08:38:10.117404903 +0100 > +++ gcc/gimple-iterator.h 2018-06-20 11:26:07.913295807 +0100 > @@ -79,6 +79,7 @@ extern void gsi_insert_after (gimple_stm > enum gsi_iterator_update); > extern bool gsi_remove (gimple_stmt_iterator *, bool); > extern gimple_stmt_iterator gsi_for_stmt (gimple *); > +extern gimple_stmt_iterator gsi_for_stmt (gimple *, gimple_seq *); > extern gphi_iterator gsi_for_phi (gphi *); > extern void gsi_move_after (gimple_stmt_iterator *, gimple_stmt_iterator *); > extern void gsi_move_before (gimple_stmt_iterator *, gimple_stmt_iterator *); > Index: gcc/tree-vect-patterns.c > =================================================================== > --- gcc/tree-vect-patterns.c 2018-06-20 11:26:00.497361237 +0100 > +++ gcc/tree-vect-patterns.c 2018-06-20 11:26:07.913295807 +0100 > @@ -60,6 +60,42 @@ vect_pattern_detected (const char *name, > } > } > > +/* Associate pattern statement PATTERN_STMT with ORIG_STMT_INFO. > + Set its vector type to VECTYPE if it doesn't have one already. */ > + > +static void > +vect_init_pattern_stmt (gimple *pattern_stmt, stmt_vec_info orig_stmt_info, > + tree vectype) > +{ > + stmt_vec_info pattern_stmt_info = vinfo_for_stmt (pattern_stmt); > + if (pattern_stmt_info == NULL) > + { > + pattern_stmt_info = new_stmt_vec_info (pattern_stmt, > + orig_stmt_info->vinfo); > + set_vinfo_for_stmt (pattern_stmt, pattern_stmt_info); > + } > + gimple_set_bb (pattern_stmt, gimple_bb (orig_stmt_info->stmt)); > + > + STMT_VINFO_RELATED_STMT (pattern_stmt_info) = orig_stmt_info->stmt; > + STMT_VINFO_DEF_TYPE (pattern_stmt_info) > + = STMT_VINFO_DEF_TYPE (orig_stmt_info); > + if (!STMT_VINFO_VECTYPE (pattern_stmt_info)) > + STMT_VINFO_VECTYPE (pattern_stmt_info) = vectype; > +} > + > +/* Set the pattern statement of ORIG_STMT_INFO to PATTERN_STMT. > + Also set the vector type of PATTERN_STMT to VECTYPE, if it doesn't > + have one already. */ > + > +static void > +vect_set_pattern_stmt (gimple *pattern_stmt, stmt_vec_info orig_stmt_info, > + tree vectype) > +{ > + STMT_VINFO_IN_PATTERN_P (orig_stmt_info) = true; > + STMT_VINFO_RELATED_STMT (orig_stmt_info) = pattern_stmt; > + vect_init_pattern_stmt (pattern_stmt, orig_stmt_info, vectype); > +} > + > static inline void > append_pattern_def_seq (stmt_vec_info stmt_info, gimple *stmt) > { > @@ -353,9 +389,6 @@ vect_recog_dot_prod_pattern (vec<gimple > /* Starting from LAST_STMT, follow the defs of its uses in search > of the above pattern. */ > > - if (STMT_VINFO_IN_PATTERN_P (stmt_vinfo)) > - return NULL; > - > if (!vect_reassociating_reduction_p (stmt_vinfo, PLUS_EXPR, > &oprnd0, &oprnd1)) > return NULL; > @@ -513,9 +546,6 @@ vect_recog_sad_pattern (vec<gimple *> *s > /* Starting from LAST_STMT, follow the defs of its uses in search > of the above pattern. */ > > - if (STMT_VINFO_IN_PATTERN_P (stmt_vinfo)) > - return NULL; > - > tree plus_oprnd0, plus_oprnd1; > if (!vect_reassociating_reduction_p (stmt_vinfo, PLUS_EXPR, > &plus_oprnd0, &plus_oprnd1)) > @@ -1128,9 +1158,6 @@ vect_recog_widen_sum_pattern (vec<gimple > tree var; > bool promotion; > > - if (STMT_VINFO_IN_PATTERN_P (stmt_vinfo)) > - return NULL; > - > /* Look for the following pattern > DX = (TYPE) X; > sum_1 = DX + sum_0; > @@ -1606,9 +1633,6 @@ vect_recog_widen_shift_pattern (vec<gimp > if (!is_gimple_assign (last_stmt) || !vinfo_for_stmt (last_stmt)) > return NULL; > > - if (STMT_VINFO_IN_PATTERN_P (vinfo_for_stmt (last_stmt))) > - return NULL; > - > if (gimple_assign_rhs_code (last_stmt) != LSHIFT_EXPR) > return NULL; > > @@ -1743,9 +1767,6 @@ vect_recog_rotate_pattern (vec<gimple *> > return NULL; > } > > - if (STMT_VINFO_IN_PATTERN_P (stmt_vinfo)) > - return NULL; > - > lhs = gimple_assign_lhs (last_stmt); > oprnd0 = gimple_assign_rhs1 (last_stmt); > type = TREE_TYPE (oprnd0); > @@ -1991,9 +2012,6 @@ vect_recog_vector_vector_shift_pattern ( > return NULL; > } > > - if (STMT_VINFO_IN_PATTERN_P (stmt_vinfo)) > - return NULL; > - > lhs = gimple_assign_lhs (last_stmt); > oprnd0 = gimple_assign_rhs1 (last_stmt); > oprnd1 = gimple_assign_rhs2 (last_stmt); > @@ -2492,9 +2510,6 @@ vect_recog_divmod_pattern (vec<gimple *> > return NULL; > } > > - if (STMT_VINFO_IN_PATTERN_P (stmt_vinfo)) > - return NULL; > - > oprnd0 = gimple_assign_rhs1 (last_stmt); > oprnd1 = gimple_assign_rhs2 (last_stmt); > itype = TREE_TYPE (oprnd0); > @@ -3829,11 +3844,6 @@ vect_recog_mask_conversion_pattern (vec< > /* Check for cond expression requiring mask conversion. */ > if (rhs_code == COND_EXPR) > { > - /* vect_recog_mixed_size_cond_pattern could apply. > - Do nothing then. */ > - if (STMT_VINFO_IN_PATTERN_P (stmt_vinfo)) > - return NULL; > - > vectype1 = get_vectype_for_scalar_type (TREE_TYPE (lhs)); > > if (TREE_CODE (rhs1) == SSA_NAME) > @@ -4222,42 +4232,59 @@ const unsigned int NUM_PATTERNS = ARRAY_ > vect_mark_pattern_stmts (gimple *orig_stmt, gimple *pattern_stmt, > tree pattern_vectype) > { > - stmt_vec_info pattern_stmt_info, def_stmt_info; > stmt_vec_info orig_stmt_info = vinfo_for_stmt (orig_stmt); > - vec_info *vinfo = orig_stmt_info->vinfo; > - gimple *def_stmt; > + gimple *def_seq = STMT_VINFO_PATTERN_DEF_SEQ (orig_stmt_info); > > - pattern_stmt_info = vinfo_for_stmt (pattern_stmt); > - if (pattern_stmt_info == NULL) > + bool old_pattern_p = is_pattern_stmt_p (orig_stmt_info); > + if (old_pattern_p) > { > - pattern_stmt_info = new_stmt_vec_info (pattern_stmt, vinfo); > - set_vinfo_for_stmt (pattern_stmt, pattern_stmt_info); > + /* We're replacing a statement in an existing pattern definition > + sequence. */ > + if (dump_enabled_p ()) > + { > + dump_printf_loc (MSG_NOTE, vect_location, > + "replacing earlier pattern "); > + dump_gimple_stmt (MSG_NOTE, TDF_SLIM, orig_stmt, 0); > + } > + > + /* To keep the book-keeping simple, just swap the lhs of the > + old and new statements, so that the old one has a valid but > + unused lhs. */ > + tree old_lhs = gimple_get_lhs (orig_stmt); > + gimple_set_lhs (orig_stmt, gimple_get_lhs (pattern_stmt)); > + gimple_set_lhs (pattern_stmt, old_lhs); > + > + if (dump_enabled_p ()) > + { > + dump_printf_loc (MSG_NOTE, vect_location, "with "); > + dump_gimple_stmt (MSG_NOTE, TDF_SLIM, pattern_stmt, 0); > + } > + > + /* Switch to the statement that ORIG replaces. */ > + orig_stmt_info > + = vinfo_for_stmt (STMT_VINFO_RELATED_STMT (orig_stmt_info)); > + > + /* We shouldn't be replacing the main pattern statement. */ > + gcc_assert (STMT_VINFO_RELATED_STMT (orig_stmt_info) != orig_stmt); > } > - gimple_set_bb (pattern_stmt, gimple_bb (orig_stmt)); > > - STMT_VINFO_RELATED_STMT (pattern_stmt_info) = orig_stmt; > - STMT_VINFO_DEF_TYPE (pattern_stmt_info) > - = STMT_VINFO_DEF_TYPE (orig_stmt_info); > - STMT_VINFO_VECTYPE (pattern_stmt_info) = pattern_vectype; > - STMT_VINFO_IN_PATTERN_P (orig_stmt_info) = true; > - STMT_VINFO_RELATED_STMT (orig_stmt_info) = pattern_stmt; > - if (gimple *def_seq = STMT_VINFO_PATTERN_DEF_SEQ (orig_stmt_info)) > + if (def_seq) > for (gimple_stmt_iterator si = gsi_start (def_seq); > !gsi_end_p (si); gsi_next (&si)) > - { > - def_stmt = gsi_stmt (si); > - def_stmt_info = vinfo_for_stmt (def_stmt); > - if (def_stmt_info == NULL) > - { > - def_stmt_info = new_stmt_vec_info (def_stmt, vinfo); > - set_vinfo_for_stmt (def_stmt, def_stmt_info); > - } > - gimple_set_bb (def_stmt, gimple_bb (orig_stmt)); > - STMT_VINFO_RELATED_STMT (def_stmt_info) = orig_stmt; > - STMT_VINFO_DEF_TYPE (def_stmt_info) = vect_internal_def; > - if (STMT_VINFO_VECTYPE (def_stmt_info) == NULL_TREE) > - STMT_VINFO_VECTYPE (def_stmt_info) = pattern_vectype; > - } > + vect_init_pattern_stmt (gsi_stmt (si), orig_stmt_info, > pattern_vectype); > + > + if (old_pattern_p) > + { > + vect_init_pattern_stmt (pattern_stmt, orig_stmt_info, pattern_vectype); > + > + /* Insert all the new pattern statements before the original one. */ > + gimple_seq *orig_def_seq = &STMT_VINFO_PATTERN_DEF_SEQ > (orig_stmt_info); > + gimple_stmt_iterator gsi = gsi_for_stmt (orig_stmt, orig_def_seq); > + gsi_insert_seq_before_without_update (&gsi, def_seq, GSI_SAME_STMT); > + gsi_insert_before_without_update (&gsi, pattern_stmt, GSI_SAME_STMT); > + } > + else > + vect_set_pattern_stmt (pattern_stmt, orig_stmt_info, pattern_vectype); > } > > /* Function vect_pattern_recog_1 > @@ -4278,7 +4305,7 @@ vect_mark_pattern_stmts (gimple *orig_st > This function also does some bookkeeping, as explained in the > documentation > for vect_recog_pattern. */ > > -static bool > +static void > vect_pattern_recog_1 (vect_recog_func *recog_func, > gimple_stmt_iterator si, > vec<gimple *> *stmts_to_replace) > @@ -4289,6 +4316,20 @@ vect_pattern_recog_1 (vect_recog_func *r > tree pattern_vectype; > int i; > > + /* If this statement has already been replaced with pattern statements, > + leave the original statement alone, since the first match wins. > + Instead try to match against the definition statements that feed > + the main pattern statement. */ > + stmt_info = vinfo_for_stmt (stmt); > + if (STMT_VINFO_IN_PATTERN_P (stmt_info)) > + { > + gimple_stmt_iterator gsi; > + for (gsi = gsi_start (STMT_VINFO_PATTERN_DEF_SEQ (stmt_info)); > + !gsi_end_p (gsi); gsi_next (&gsi)) > + vect_pattern_recog_1 (recog_func, gsi, stmts_to_replace); > + return; > + } > + > stmts_to_replace->truncate (0); > stmts_to_replace->quick_push (stmt); > pattern_stmt = recog_func->fn (stmts_to_replace, &pattern_vectype); > @@ -4301,9 +4342,10 @@ vect_pattern_recog_1 (vect_recog_func *r > i++) > { > stmt_info = vinfo_for_stmt (stmt); > - STMT_VINFO_RELATED_STMT (stmt_info) = NULL; > + if (!is_pattern_stmt_p (stmt_info)) > + STMT_VINFO_RELATED_STMT (stmt_info) = NULL; > } > - return false; > + return; > } > > stmt = stmts_to_replace->last (); > @@ -4351,7 +4393,7 @@ vect_pattern_recog_1 (vect_recog_func *r > vect_mark_pattern_stmts (stmt, pattern_stmt, NULL_TREE); > } > > - return true; > + return; > } > > > @@ -4456,17 +4498,10 @@ vect_pattern_recog (vec_info *vinfo) > { > basic_block bb = bbs[i]; > for (si = gsi_start_bb (bb); !gsi_end_p (si); gsi_next (&si)) > - { > - gimple *stmt = gsi_stmt (si); > - stmt_vec_info stmt_info = vinfo_for_stmt (stmt); > - if (stmt_info && STMT_VINFO_IN_PATTERN_P (stmt_info)) > - continue; > - /* Scan over all generic vect_recog_xxx_pattern functions. */ > - for (j = 0; j < NUM_PATTERNS; j++) > - if (vect_pattern_recog_1 (&vect_vect_recog_func_ptrs[j], si, > - &stmts_to_replace)) > - break; > - } > + /* Scan over all generic vect_recog_xxx_pattern functions. */ > + for (j = 0; j < NUM_PATTERNS; j++) > + vect_pattern_recog_1 (&vect_vect_recog_func_ptrs[j], si, > + &stmts_to_replace); > } > } > else > @@ -4477,16 +4512,13 @@ vect_pattern_recog (vec_info *vinfo) > { > gimple *stmt = gsi_stmt (si); > stmt_vec_info stmt_info = vinfo_for_stmt (stmt); > - if (stmt_info > - && (!STMT_VINFO_VECTORIZABLE (stmt_info) > - || STMT_VINFO_IN_PATTERN_P (stmt_info))) > + if (stmt_info && !STMT_VINFO_VECTORIZABLE (stmt_info)) > continue; > > /* Scan over all generic vect_recog_xxx_pattern functions. */ > for (j = 0; j < NUM_PATTERNS; j++) > - if (vect_pattern_recog_1 (&vect_vect_recog_func_ptrs[j], si, > - &stmts_to_replace)) > - break; > + vect_pattern_recog_1 (&vect_vect_recog_func_ptrs[j], si, > + &stmts_to_replace); > } > } > }