aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-vect-loop-manip.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/tree-vect-loop-manip.cc')
-rw-r--r--gcc/tree-vect-loop-manip.cc136
1 files changed, 124 insertions, 12 deletions
diff --git a/gcc/tree-vect-loop-manip.cc b/gcc/tree-vect-loop-manip.cc
index ff6159e..acf3642 100644
--- a/gcc/tree-vect-loop-manip.cc
+++ b/gcc/tree-vect-loop-manip.cc
@@ -385,6 +385,63 @@ vect_maybe_permute_loop_masks (gimple_seq *seq, rgroup_controls *dest_rgm,
return false;
}
+/* Populate DEST_RGM->controls, given that they should add up to STEP.
+
+ STEP = MIN_EXPR <ivtmp_34, VF>;
+
+ First length (MIN (X, VF/N)):
+ loop_len_15 = MIN_EXPR <STEP, VF/N>;
+
+ Second length:
+ tmp = STEP - loop_len_15;
+ loop_len_16 = MIN (tmp, VF/N);
+
+ Third length:
+ tmp2 = tmp - loop_len_16;
+ loop_len_17 = MIN (tmp2, VF/N);
+
+ Last length:
+ loop_len_18 = tmp2 - loop_len_17;
+*/
+
+static void
+vect_adjust_loop_lens_control (tree iv_type, gimple_seq *seq,
+ rgroup_controls *dest_rgm, tree step)
+{
+ tree ctrl_type = dest_rgm->type;
+ poly_uint64 nitems_per_ctrl
+ = TYPE_VECTOR_SUBPARTS (ctrl_type) * dest_rgm->factor;
+ tree length_limit = build_int_cst (iv_type, nitems_per_ctrl);
+
+ for (unsigned int i = 0; i < dest_rgm->controls.length (); ++i)
+ {
+ tree ctrl = dest_rgm->controls[i];
+ if (i == 0)
+ {
+ /* First iteration: MIN (X, VF/N) capped to the range [0, VF/N]. */
+ gassign *assign
+ = gimple_build_assign (ctrl, MIN_EXPR, step, length_limit);
+ gimple_seq_add_stmt (seq, assign);
+ }
+ else if (i == dest_rgm->controls.length () - 1)
+ {
+ /* Last iteration: Remain capped to the range [0, VF/N]. */
+ gassign *assign = gimple_build_assign (ctrl, MINUS_EXPR, step,
+ dest_rgm->controls[i - 1]);
+ gimple_seq_add_stmt (seq, assign);
+ }
+ else
+ {
+ /* (MIN (remain, VF*I/N)) capped to the range [0, VF/N]. */
+ step = gimple_build (seq, MINUS_EXPR, iv_type, step,
+ dest_rgm->controls[i - 1]);
+ gassign *assign
+ = gimple_build_assign (ctrl, MIN_EXPR, step, length_limit);
+ gimple_seq_add_stmt (seq, assign);
+ }
+ }
+}
+
/* Helper for vect_set_loop_condition_partial_vectors. Generate definitions
for all the rgroup controls in RGC and return a control that is nonzero
when the loop needs to iterate. Add any new preheader statements to
@@ -425,7 +482,8 @@ vect_set_loop_controls_directly (class loop *loop, loop_vec_info loop_vinfo,
gimple_seq *header_seq,
gimple_stmt_iterator loop_cond_gsi,
rgroup_controls *rgc, tree niters,
- tree niters_skip, bool might_wrap_p)
+ tree niters_skip, bool might_wrap_p,
+ tree *iv_step)
{
tree compare_type = LOOP_VINFO_RGROUP_COMPARE_TYPE (loop_vinfo);
tree iv_type = LOOP_VINFO_RGROUP_IV_TYPE (loop_vinfo);
@@ -468,6 +526,39 @@ vect_set_loop_controls_directly (class loop *loop, loop_vec_info loop_vinfo,
gimple_stmt_iterator incr_gsi;
bool insert_after;
standard_iv_increment_position (loop, &incr_gsi, &insert_after);
+ if (LOOP_VINFO_USING_DECREMENTING_IV_P (loop_vinfo))
+ {
+ /* Create an IV that counts down from niters_total and whose step
+ is the (variable) amount processed in the current iteration:
+ ...
+ _10 = (unsigned long) count_12(D);
+ ...
+ # ivtmp_9 = PHI <ivtmp_35(6), _10(5)>
+ _36 = MIN_EXPR <ivtmp_9, POLY_INT_CST [4, 4]>;
+ ...
+ vect__4.8_28 = .LEN_LOAD (_17, 32B, _36, 0);
+ ...
+ ivtmp_35 = ivtmp_9 - _36;
+ ...
+ if (ivtmp_35 != 0)
+ goto <bb 4>; [83.33%]
+ else
+ goto <bb 5>; [16.67%]
+ */
+ nitems_total = gimple_convert (preheader_seq, iv_type, nitems_total);
+ tree step = rgc->controls.length () == 1 ? rgc->controls[0]
+ : make_ssa_name (iv_type);
+ /* Create decrement IV. */
+ create_iv (nitems_total, MINUS_EXPR, step, NULL_TREE, loop, &incr_gsi,
+ insert_after, &index_before_incr, &index_after_incr);
+ gimple_seq_add_stmt (header_seq, gimple_build_assign (step, MIN_EXPR,
+ index_before_incr,
+ nitems_step));
+ *iv_step = step;
+ return index_after_incr;
+ }
+
+ /* Create increment IV. */
create_iv (build_int_cst (iv_type, 0), PLUS_EXPR, nitems_step, NULL_TREE,
loop, &incr_gsi, insert_after, &index_before_incr,
&index_after_incr);
@@ -733,7 +824,9 @@ vect_set_loop_condition_partial_vectors (class loop *loop,
the first control from any rgroup for the loop condition; here we
arbitrarily pick the last. */
tree test_ctrl = NULL_TREE;
+ tree iv_step = NULL_TREE;
rgroup_controls *rgc;
+ rgroup_controls *iv_rgc = nullptr;
unsigned int i;
auto_vec<rgroup_controls> *controls = use_masks_p
? &LOOP_VINFO_MASKS (loop_vinfo)
@@ -753,17 +846,36 @@ vect_set_loop_condition_partial_vectors (class loop *loop,
continue;
}
- /* See whether zero-based IV would ever generate all-false masks
- or zero length before wrapping around. */
- bool might_wrap_p = vect_rgroup_iv_might_wrap_p (loop_vinfo, rgc);
-
- /* Set up all controls for this group. */
- test_ctrl = vect_set_loop_controls_directly (loop, loop_vinfo,
- &preheader_seq,
- &header_seq,
- loop_cond_gsi, rgc,
- niters, niters_skip,
- might_wrap_p);
+ if (!LOOP_VINFO_USING_DECREMENTING_IV_P (loop_vinfo)
+ || !iv_rgc
+ || (iv_rgc->max_nscalars_per_iter * iv_rgc->factor
+ != rgc->max_nscalars_per_iter * rgc->factor))
+ {
+ /* See whether zero-based IV would ever generate all-false masks
+ or zero length before wrapping around. */
+ bool might_wrap_p = vect_rgroup_iv_might_wrap_p (loop_vinfo, rgc);
+
+ /* Set up all controls for this group. */
+ test_ctrl
+ = vect_set_loop_controls_directly (loop, loop_vinfo,
+ &preheader_seq, &header_seq,
+ loop_cond_gsi, rgc, niters,
+ niters_skip, might_wrap_p,
+ &iv_step);
+
+ iv_rgc = rgc;
+ }
+
+ if (LOOP_VINFO_USING_DECREMENTING_IV_P (loop_vinfo)
+ && rgc->controls.length () > 1)
+ {
+ /* vect_set_loop_controls_directly creates an IV whose step
+ is equal to the expected sum of RGC->controls. Use that
+ information to populate RGC->controls. */
+ tree iv_type = LOOP_VINFO_RGROUP_IV_TYPE (loop_vinfo);
+ gcc_assert (iv_step);
+ vect_adjust_loop_lens_control (iv_type, &header_seq, rgc, iv_step);
+ }
}
/* Emit all accumulated statements. */