* [PATCH] Vectorizer TLC
@ 2013-03-18 11:40 Richard Biener
0 siblings, 0 replies; 4+ messages in thread
From: Richard Biener @ 2013-03-18 11:40 UTC (permalink / raw)
To: gcc-patches
The following is a collection of TLC sitting in my local tree,
mostly resulting in less obscure IL after vectorization.
Bootstrapped on x86_64-unknown-linux-gnu, testing in progress.
Richard.
2013-03-18 Richard Biener <rguenther@suse.de>
* tree-vect-loop-manip.c (vect_create_cond_for_alias_checks):
Remove cond_expr_stmt_list argument and do not gimplify the
built expression.
(vect_loop_versioning): Adjust.
* tree-vect-data-refs.c (vect_create_addr_base_for_vector_ref):
Cleanup to use less temporaries.
(vect_create_data_ref_ptr): Cleanup.
Index: gcc/tree-vect-loop-manip.c
===================================================================
*** gcc/tree-vect-loop-manip.c.orig 2013-02-20 11:05:04.000000000 +0100
--- gcc/tree-vect-loop-manip.c 2013-03-18 11:38:46.633554021 +0100
*************** vect_vfa_segment_size (struct data_refer
*** 2271,2290 ****
Output:
COND_EXPR - conditional expression.
- COND_EXPR_STMT_LIST - statements needed to construct the conditional
- expression.
-
The returned value is the conditional expression to be used in the if
statement that controls which version of the loop gets executed at runtime.
*/
static void
! vect_create_cond_for_alias_checks (loop_vec_info loop_vinfo,
! tree * cond_expr,
! gimple_seq * cond_expr_stmt_list)
{
- struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
vec<ddr_p> may_alias_ddrs =
LOOP_VINFO_MAY_ALIAS_DDRS (loop_vinfo);
int vect_factor = LOOP_VINFO_VECT_FACTOR (loop_vinfo);
--- 2271,2284 ----
Output:
COND_EXPR - conditional expression.
The returned value is the conditional expression to be used in the if
statement that controls which version of the loop gets executed at runtime.
*/
static void
! vect_create_cond_for_alias_checks (loop_vec_info loop_vinfo, tree * cond_expr)
{
vec<ddr_p> may_alias_ddrs =
LOOP_VINFO_MAY_ALIAS_DDRS (loop_vinfo);
int vect_factor = LOOP_VINFO_VECT_FACTOR (loop_vinfo);
*************** vect_create_cond_for_alias_checks (loop_
*** 2333,2344 ****
dr_b = STMT_VINFO_DATA_REF (vinfo_for_stmt (stmt_b));
}
! addr_base_a =
! vect_create_addr_base_for_vector_ref (stmt_a, cond_expr_stmt_list,
! NULL_TREE, loop);
! addr_base_b =
! vect_create_addr_base_for_vector_ref (stmt_b, cond_expr_stmt_list,
! NULL_TREE, loop);
if (!operand_equal_p (DR_STEP (dr_a), DR_STEP (dr_b), 0))
length_factor = scalar_loop_iters;
--- 2327,2340 ----
dr_b = STMT_VINFO_DATA_REF (vinfo_for_stmt (stmt_b));
}
! addr_base_a
! = fold_build_pointer_plus (DR_BASE_ADDRESS (dr_a),
! size_binop (PLUS_EXPR, DR_OFFSET (dr_a),
! DR_INIT (dr_a)));
! addr_base_b
! = fold_build_pointer_plus (DR_BASE_ADDRESS (dr_b),
! size_binop (PLUS_EXPR, DR_OFFSET (dr_b),
! DR_INIT (dr_b)));
if (!operand_equal_p (DR_STEP (dr_a), DR_STEP (dr_b), 0))
length_factor = scalar_loop_iters;
*************** vect_loop_versioning (loop_vec_info loop
*** 2435,2442 ****
&cond_expr_stmt_list);
if (LOOP_REQUIRES_VERSIONING_FOR_ALIAS (loop_vinfo))
! vect_create_cond_for_alias_checks (loop_vinfo, &cond_expr,
! &cond_expr_stmt_list);
cond_expr = force_gimple_operand_1 (cond_expr, &gimplify_stmt_list,
is_gimple_condexpr, NULL_TREE);
--- 2431,2437 ----
&cond_expr_stmt_list);
if (LOOP_REQUIRES_VERSIONING_FOR_ALIAS (loop_vinfo))
! vect_create_cond_for_alias_checks (loop_vinfo, &cond_expr);
cond_expr = force_gimple_operand_1 (cond_expr, &gimplify_stmt_list,
is_gimple_condexpr, NULL_TREE);
Index: gcc/tree-vect-data-refs.c
===================================================================
*** gcc/tree-vect-data-refs.c.orig 2013-03-05 16:50:25.000000000 +0100
--- gcc/tree-vect-data-refs.c 2013-03-18 11:37:47.391898625 +0100
*************** vect_create_addr_base_for_vector_ref (gi
*** 3556,3574 ****
{
stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
struct data_reference *dr = STMT_VINFO_DATA_REF (stmt_info);
! tree data_ref_base = unshare_expr (DR_BASE_ADDRESS (dr));
const char *base_name;
! tree data_ref_base_var;
! tree vec_stmt;
! tree addr_base, addr_expr;
tree dest;
gimple_seq seq = NULL;
! tree base_offset = unshare_expr (DR_OFFSET (dr));
! tree init = unshare_expr (DR_INIT (dr));
tree vect_ptr_type;
tree step = TYPE_SIZE_UNIT (TREE_TYPE (DR_REF (dr)));
loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
- tree base;
if (loop_vinfo && loop && loop != (gimple_bb (stmt))->loop_father)
{
--- 3556,3571 ----
{
stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
struct data_reference *dr = STMT_VINFO_DATA_REF (stmt_info);
! tree data_ref_base;
const char *base_name;
! tree addr_base;
tree dest;
gimple_seq seq = NULL;
! tree base_offset;
! tree init;
tree vect_ptr_type;
tree step = TYPE_SIZE_UNIT (TREE_TYPE (DR_REF (dr)));
loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
if (loop_vinfo && loop && loop != (gimple_bb (stmt))->loop_father)
{
*************** vect_create_addr_base_for_vector_ref (gi
*** 3580,3585 ****
--- 3577,3588 ----
base_offset = unshare_expr (STMT_VINFO_DR_OFFSET (stmt_info));
init = unshare_expr (STMT_VINFO_DR_INIT (stmt_info));
}
+ else
+ {
+ data_ref_base = unshare_expr (DR_BASE_ADDRESS (dr));
+ base_offset = unshare_expr (DR_OFFSET (dr));
+ init = unshare_expr (DR_INIT (dr));
+ }
if (loop_vinfo)
base_name = get_name (data_ref_base);
*************** vect_create_addr_base_for_vector_ref (gi
*** 3590,3618 ****
base_name = get_name (DR_REF (dr));
}
- data_ref_base_var = create_tmp_var (TREE_TYPE (data_ref_base), "batmp");
- data_ref_base = force_gimple_operand (data_ref_base, &seq, true,
- data_ref_base_var);
- gimple_seq_add_seq (new_stmt_list, seq);
-
/* Create base_offset */
base_offset = size_binop (PLUS_EXPR,
fold_convert (sizetype, base_offset),
fold_convert (sizetype, init));
- dest = create_tmp_var (sizetype, "base_off");
- base_offset = force_gimple_operand (base_offset, &seq, true, dest);
- gimple_seq_add_seq (new_stmt_list, seq);
if (offset)
{
- tree tmp = create_tmp_var (sizetype, "offset");
-
offset = fold_build2 (MULT_EXPR, sizetype,
fold_convert (sizetype, offset), step);
base_offset = fold_build2 (PLUS_EXPR, sizetype,
base_offset, offset);
- base_offset = force_gimple_operand (base_offset, &seq, false, tmp);
- gimple_seq_add_seq (new_stmt_list, seq);
}
/* base + base_offset */
--- 3593,3609 ----
*************** vect_create_addr_base_for_vector_ref (gi
*** 3626,3659 ****
}
vect_ptr_type = build_pointer_type (STMT_VINFO_VECTYPE (stmt_info));
! base = get_base_address (DR_REF (dr));
! if (base
! && TREE_CODE (base) == MEM_REF)
! vect_ptr_type
! = build_qualified_type (vect_ptr_type,
! TYPE_QUALS (TREE_TYPE (TREE_OPERAND (base, 0))));
!
! vec_stmt = fold_convert (vect_ptr_type, addr_base);
! addr_expr = vect_get_new_vect_var (vect_ptr_type, vect_pointer_var,
! base_name);
! vec_stmt = force_gimple_operand (vec_stmt, &seq, false, addr_expr);
gimple_seq_add_seq (new_stmt_list, seq);
if (DR_PTR_INFO (dr)
! && TREE_CODE (vec_stmt) == SSA_NAME)
{
! duplicate_ssa_name_ptr_info (vec_stmt, DR_PTR_INFO (dr));
if (offset)
! mark_ptr_info_alignment_unknown (SSA_NAME_PTR_INFO (vec_stmt));
}
if (dump_enabled_p ())
{
dump_printf_loc (MSG_NOTE, vect_location, "created ");
! dump_generic_expr (MSG_NOTE, TDF_SLIM, vec_stmt);
}
! return vec_stmt;
}
--- 3617,3642 ----
}
vect_ptr_type = build_pointer_type (STMT_VINFO_VECTYPE (stmt_info));
! addr_base = fold_convert (vect_ptr_type, addr_base);
! dest = vect_get_new_vect_var (vect_ptr_type, vect_pointer_var, base_name);
! addr_base = force_gimple_operand (addr_base, &seq, false, dest);
gimple_seq_add_seq (new_stmt_list, seq);
if (DR_PTR_INFO (dr)
! && TREE_CODE (addr_base) == SSA_NAME)
{
! duplicate_ssa_name_ptr_info (addr_base, DR_PTR_INFO (dr));
if (offset)
! mark_ptr_info_alignment_unknown (SSA_NAME_PTR_INFO (addr_base));
}
if (dump_enabled_p ())
{
dump_printf_loc (MSG_NOTE, vect_location, "created ");
! dump_generic_expr (MSG_NOTE, TDF_SLIM, addr_base);
}
! return addr_base;
}
*************** vect_create_data_ref_ptr (gimple stmt, t
*** 3733,3739 ****
gimple incr;
tree step;
bb_vec_info bb_vinfo = STMT_VINFO_BB_VINFO (stmt_info);
- tree base;
gcc_assert (TREE_CODE (aggr_type) == ARRAY_TYPE
|| TREE_CODE (aggr_type) == VECTOR_TYPE);
--- 3716,3721 ----
*************** vect_create_data_ref_ptr (gimple stmt, t
*** 3785,3837 ****
dump_generic_expr (MSG_NOTE, TDF_SLIM, DR_BASE_OBJECT (dr));
}
! /* (1) Create the new aggregate-pointer variable. */
! aggr_ptr_type = build_pointer_type (aggr_type);
! base = get_base_address (DR_REF (dr));
! if (base
! && TREE_CODE (base) == MEM_REF)
! aggr_ptr_type
! = build_qualified_type (aggr_ptr_type,
! TYPE_QUALS (TREE_TYPE (TREE_OPERAND (base, 0))));
! aggr_ptr = vect_get_new_vect_var (aggr_ptr_type, vect_pointer_var, base_name);
!
! /* Vector and array types inherit the alias set of their component
type by default so we need to use a ref-all pointer if the data
reference does not conflict with the created aggregated data
reference because it is not addressable. */
! if (!alias_sets_conflict_p (get_deref_alias_set (aggr_ptr),
get_alias_set (DR_REF (dr))))
! {
! aggr_ptr_type
! = build_pointer_type_for_mode (aggr_type,
! TYPE_MODE (aggr_ptr_type), true);
! aggr_ptr = vect_get_new_vect_var (aggr_ptr_type, vect_pointer_var,
! base_name);
! }
!
/* Likewise for any of the data references in the stmt group. */
else if (STMT_VINFO_GROUP_SIZE (stmt_info) > 1)
{
gimple orig_stmt = STMT_VINFO_GROUP_FIRST_ELEMENT (stmt_info);
do
{
! tree lhs = gimple_assign_lhs (orig_stmt);
! if (!alias_sets_conflict_p (get_deref_alias_set (aggr_ptr),
! get_alias_set (lhs)))
{
! aggr_ptr_type
! = build_pointer_type_for_mode (aggr_type,
! TYPE_MODE (aggr_ptr_type), true);
! aggr_ptr
! = vect_get_new_vect_var (aggr_ptr_type, vect_pointer_var,
! base_name);
break;
}
!
! orig_stmt = STMT_VINFO_GROUP_NEXT_ELEMENT (vinfo_for_stmt (orig_stmt));
}
while (orig_stmt);
}
/* Note: If the dataref is in an inner-loop nested in LOOP, and we are
vectorizing LOOP (i.e., outer-loop vectorization), we need to create two
--- 3767,3803 ----
dump_generic_expr (MSG_NOTE, TDF_SLIM, DR_BASE_OBJECT (dr));
}
! /* (1) Create the new aggregate-pointer variable.
! Vector and array types inherit the alias set of their component
type by default so we need to use a ref-all pointer if the data
reference does not conflict with the created aggregated data
reference because it is not addressable. */
! bool need_ref_all = false;
! if (!alias_sets_conflict_p (get_alias_set (aggr_type),
get_alias_set (DR_REF (dr))))
! need_ref_all = true;
/* Likewise for any of the data references in the stmt group. */
else if (STMT_VINFO_GROUP_SIZE (stmt_info) > 1)
{
gimple orig_stmt = STMT_VINFO_GROUP_FIRST_ELEMENT (stmt_info);
do
{
! stmt_vec_info sinfo = vinfo_for_stmt (orig_stmt);
! struct data_reference *sdr = STMT_VINFO_DATA_REF (sinfo);
! if (!alias_sets_conflict_p (get_alias_set (aggr_type),
! get_alias_set (DR_REF (sdr))))
{
! need_ref_all = true;
break;
}
! orig_stmt = STMT_VINFO_GROUP_NEXT_ELEMENT (sinfo);
}
while (orig_stmt);
}
+ aggr_ptr_type = build_pointer_type_for_mode (aggr_type, ptr_mode,
+ need_ref_all);
+ aggr_ptr = vect_get_new_vect_var (aggr_ptr_type, vect_pointer_var, base_name);
+
/* Note: If the dataref is in an inner-loop nested in LOOP, and we are
vectorizing LOOP (i.e., outer-loop vectorization), we need to create two
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH] Vectorizer TLC
@ 2015-10-07 9:00 Richard Biener
0 siblings, 0 replies; 4+ messages in thread
From: Richard Biener @ 2015-10-07 9:00 UTC (permalink / raw)
To: gcc-patches
This fixes the type of stmt_vec_info_vec and avoids the pointless
creation of a loop_vec_info for the inner loop when doing outer loop
vectorization.
Bootstrapped / tested on x86_64-unknown-linux-gnu, applied.
Richard.
2015-10-07 Richard Biener <rguenther@suse.de>
* tree-vectorizer.h (stmt_vec_info_vec): Use vec<stmt_vec_info>.
(vinfo_for_stmt): Adjust.
(set_vinfo_for_stmt): Likewise.
* tree-vectorizer.c (stmt_vec_info_vec): Likewise.
* tree-vect-stmts.c (free_stmt_vec_info_vec): Likewise.
* tree-vect-loop.c (new_loop_vec_info): Remove special-casing
of inner loop.
(vect_analyze_loop_1): Remove.
(vect_analyze_loop_form_1): Avoid building a loop_vec_info for
inner loop when vectorizing an outer loop by splitting out from ...
(vect_analyze_loop_form): ... here.
Index: gcc/tree-vectorizer.h
===================================================================
--- gcc/tree-vectorizer.h (revision 228516)
+++ gcc/tree-vectorizer.h (working copy)
@@ -741,10 +741,7 @@ struct dataref_aux {
/* The maximum vectorization factor supported by any target (V64QI). */
#define MAX_VECTORIZATION_FACTOR 64
-/* Avoid GTY(()) on stmt_vec_info. */
-typedef void *vec_void_p;
-
-extern vec<vec_void_p> stmt_vec_info_vec;
+extern vec<stmt_vec_info> stmt_vec_info_vec;
void init_stmt_vec_info_vec (void);
void free_stmt_vec_info_vec (void);
@@ -758,7 +755,7 @@ vinfo_for_stmt (gimple *stmt)
if (uid == 0)
return NULL;
- return (stmt_vec_info) stmt_vec_info_vec[uid - 1];
+ return stmt_vec_info_vec[uid - 1];
}
/* Set vectorizer information INFO for STMT. */
@@ -772,10 +769,10 @@ set_vinfo_for_stmt (gimple *stmt, stmt_v
gcc_checking_assert (info);
uid = stmt_vec_info_vec.length () + 1;
gimple_set_uid (stmt, uid);
- stmt_vec_info_vec.safe_push ((vec_void_p) info);
+ stmt_vec_info_vec.safe_push (info);
}
else
- stmt_vec_info_vec[uid - 1] = (vec_void_p) info;
+ stmt_vec_info_vec[uid - 1] = info;
}
/* Return the earlier statement between STMT1 and STMT2. */
Index: gcc/tree-vectorizer.c
===================================================================
--- gcc/tree-vectorizer.c (revision 228516)
+++ gcc/tree-vectorizer.c (working copy)
@@ -87,7 +87,7 @@ along with GCC; see the file COPYING3.
source_location vect_location;
/* Vector mapping GIMPLE stmt to stmt_vec_info. */
-vec<vec_void_p> stmt_vec_info_vec;
+vec<stmt_vec_info> stmt_vec_info_vec;
\f
/* For mapping simduid to vectorization factor. */
Index: gcc/tree-vect-stmts.c
===================================================================
--- gcc/tree-vect-stmts.c (revision 228516)
+++ gcc/tree-vect-stmts.c (working copy)
@@ -8033,10 +8033,10 @@ void
free_stmt_vec_info_vec (void)
{
unsigned int i;
- vec_void_p info;
+ stmt_vec_info info;
FOR_EACH_VEC_ELT (stmt_vec_info_vec, i, info)
if (info != NULL)
- free_stmt_vec_info (STMT_VINFO_STMT ((stmt_vec_info) info));
+ free_stmt_vec_info (STMT_VINFO_STMT (info));
gcc_assert (stmt_vec_info_vec.exists ());
stmt_vec_info_vec.release ();
}
Index: gcc/tree-vect-loop.c
===================================================================
--- gcc/tree-vect-loop.c (revision 228516)
+++ gcc/tree-vect-loop.c (working copy)
@@ -907,53 +907,19 @@ new_loop_vec_info (struct loop *loop)
{
basic_block bb = bbs[i];
- /* BBs in a nested inner-loop will have been already processed (because
- we will have called vect_analyze_loop_form for any nested inner-loop).
- Therefore, for stmts in an inner-loop we just want to update the
- STMT_VINFO_LOOP_VINFO field of their stmt_info to point to the new
- loop_info of the outer-loop we are currently considering to vectorize
- (instead of the loop_info of the inner-loop).
- For stmts in other BBs we need to create a stmt_info from scratch. */
- if (bb->loop_father != loop)
- {
- /* Inner-loop bb. */
- gcc_assert (loop->inner && bb->loop_father == loop->inner);
- for (si = gsi_start_phis (bb); !gsi_end_p (si); gsi_next (&si))
- {
- gimple *phi = gsi_stmt (si);
- stmt_vec_info stmt_info = vinfo_for_stmt (phi);
- loop_vec_info inner_loop_vinfo =
- STMT_VINFO_LOOP_VINFO (stmt_info);
- gcc_assert (loop->inner == LOOP_VINFO_LOOP (inner_loop_vinfo));
- stmt_info->vinfo = res;
- }
- 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);
- loop_vec_info inner_loop_vinfo =
- STMT_VINFO_LOOP_VINFO (stmt_info);
- gcc_assert (loop->inner == LOOP_VINFO_LOOP (inner_loop_vinfo));
- stmt_info->vinfo = res;
- }
- }
- else
- {
- /* bb in current nest. */
- for (si = gsi_start_phis (bb); !gsi_end_p (si); gsi_next (&si))
- {
- gimple *phi = gsi_stmt (si);
- gimple_set_uid (phi, 0);
- set_vinfo_for_stmt (phi, new_stmt_vec_info (phi, res));
- }
+ for (si = gsi_start_phis (bb); !gsi_end_p (si); gsi_next (&si))
+ {
+ gimple *phi = gsi_stmt (si);
+ gimple_set_uid (phi, 0);
+ set_vinfo_for_stmt (phi, new_stmt_vec_info (phi, res));
+ }
- for (si = gsi_start_bb (bb); !gsi_end_p (si); gsi_next (&si))
- {
- gimple *stmt = gsi_stmt (si);
- gimple_set_uid (stmt, 0);
- set_vinfo_for_stmt (stmt, new_stmt_vec_info (stmt, res));
- }
- }
+ for (si = gsi_start_bb (bb); !gsi_end_p (si); gsi_next (&si))
+ {
+ gimple *stmt = gsi_stmt (si);
+ gimple_set_uid (stmt, 0);
+ set_vinfo_for_stmt (stmt, new_stmt_vec_info (stmt, res));
+ }
}
/* CHECKME: We want to visit all BBs before their successors (except for
@@ -1150,39 +1116,7 @@ vect_get_single_scalar_iteration_cost (l
}
-/* Function vect_analyze_loop_1.
-
- Apply a set of analyses on LOOP, and create a loop_vec_info struct
- for it. The different analyses will record information in the
- loop_vec_info struct. This is a subset of the analyses applied in
- vect_analyze_loop, to be applied on an inner-loop nested in the loop
- that is now considered for (outer-loop) vectorization. */
-
-static loop_vec_info
-vect_analyze_loop_1 (struct loop *loop)
-{
- loop_vec_info loop_vinfo;
-
- if (dump_enabled_p ())
- dump_printf_loc (MSG_NOTE, vect_location,
- "===== analyze_loop_nest_1 =====\n");
-
- /* Check the CFG characteristics of the loop (nesting, entry/exit, etc. */
-
- loop_vinfo = vect_analyze_loop_form (loop);
- if (!loop_vinfo)
- {
- if (dump_enabled_p ())
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- "bad inner-loop form.\n");
- return NULL;
- }
-
- return loop_vinfo;
-}
-
-
-/* Function vect_analyze_loop_form.
+/* Function vect_analyze_loop_form_1.
Verify that certain CFG restrictions hold, including:
- the loop has a pre-header
@@ -1190,14 +1124,11 @@ vect_analyze_loop_1 (struct loop *loop)
- the loop exit condition is simple enough, and the number of iterations
can be analyzed (a countable loop). */
-loop_vec_info
-vect_analyze_loop_form (struct loop *loop)
+bool
+vect_analyze_loop_form_1 (struct loop *loop, gcond **loop_cond,
+ tree *number_of_iterationsm1,
+ tree *number_of_iterations, gcond **inner_loop_cond)
{
- loop_vec_info loop_vinfo;
- gcond *loop_cond;
- tree number_of_iterations = NULL, number_of_iterationsm1 = NULL;
- loop_vec_info inner_loop_vinfo = NULL;
-
if (dump_enabled_p ())
dump_printf_loc (MSG_NOTE, vect_location,
"=== vect_analyze_loop_form ===\n");
@@ -1225,7 +1156,7 @@ vect_analyze_loop_form (struct loop *loo
if (dump_enabled_p ())
dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
"not vectorized: control flow in loop.\n");
- return NULL;
+ return false;
}
if (empty_block_p (loop->header))
@@ -1233,7 +1164,7 @@ vect_analyze_loop_form (struct loop *loo
if (dump_enabled_p ())
dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
"not vectorized: empty loop.\n");
- return NULL;
+ return false;
}
}
else
@@ -1263,28 +1194,7 @@ vect_analyze_loop_form (struct loop *loo
if (dump_enabled_p ())
dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
"not vectorized: multiple nested loops.\n");
- return NULL;
- }
-
- /* Analyze the inner-loop. */
- inner_loop_vinfo = vect_analyze_loop_1 (loop->inner);
- if (!inner_loop_vinfo)
- {
- if (dump_enabled_p ())
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- "not vectorized: Bad inner loop.\n");
- return NULL;
- }
-
- if (!expr_invariant_in_loop_p (loop,
- LOOP_VINFO_NITERS (inner_loop_vinfo)))
- {
- if (dump_enabled_p ())
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- "not vectorized: inner-loop count not"
- " invariant.\n");
- destroy_loop_vec_info (inner_loop_vinfo, true);
- return NULL;
+ return false;
}
if (loop->num_nodes != 5)
@@ -1292,24 +1202,38 @@ vect_analyze_loop_form (struct loop *loo
if (dump_enabled_p ())
dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
"not vectorized: control flow in loop.\n");
- destroy_loop_vec_info (inner_loop_vinfo, true);
- return NULL;
+ return false;
}
- gcc_assert (EDGE_COUNT (innerloop->header->preds) == 2);
- entryedge = EDGE_PRED (innerloop->header, 0);
- if (EDGE_PRED (innerloop->header, 0)->src == innerloop->latch)
- entryedge = EDGE_PRED (innerloop->header, 1);
-
+ entryedge = loop_preheader_edge (innerloop);
if (entryedge->src != loop->header
|| !single_exit (innerloop)
- || single_exit (innerloop)->dest != EDGE_PRED (loop->latch, 0)->src)
+ || single_exit (innerloop)->dest != EDGE_PRED (loop->latch, 0)->src)
{
if (dump_enabled_p ())
dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
"not vectorized: unsupported outerloop form.\n");
- destroy_loop_vec_info (inner_loop_vinfo, true);
- return NULL;
+ return false;
+ }
+
+ /* Analyze the inner-loop. */
+ tree inner_niterm1, inner_niter;
+ if (! vect_analyze_loop_form_1 (loop->inner, inner_loop_cond,
+ &inner_niterm1, &inner_niter, NULL))
+ {
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "not vectorized: Bad inner loop.\n");
+ return false;
+ }
+
+ if (!expr_invariant_in_loop_p (loop, inner_niter))
+ {
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "not vectorized: inner-loop count not"
+ " invariant.\n");
+ return false;
}
if (dump_enabled_p ())
@@ -1329,9 +1253,7 @@ vect_analyze_loop_form (struct loop *loo
dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
"not vectorized: too many incoming edges.\n");
}
- if (inner_loop_vinfo)
- destroy_loop_vec_info (inner_loop_vinfo, true);
- return NULL;
+ return false;
}
/* We assume that the loop exit condition is at the end of the loop. i.e,
@@ -1344,9 +1266,7 @@ vect_analyze_loop_form (struct loop *loo
if (dump_enabled_p ())
dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
"not vectorized: latch block not empty.\n");
- if (inner_loop_vinfo)
- destroy_loop_vec_info (inner_loop_vinfo, true);
- return NULL;
+ return false;
}
/* Make sure there exists a single-predecessor exit bb: */
@@ -1364,47 +1284,54 @@ vect_analyze_loop_form (struct loop *loo
if (dump_enabled_p ())
dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
"not vectorized: abnormal loop exit edge.\n");
- if (inner_loop_vinfo)
- destroy_loop_vec_info (inner_loop_vinfo, true);
- return NULL;
+ return false;
}
}
- loop_cond = vect_get_loop_niters (loop, &number_of_iterations,
- &number_of_iterationsm1);
- if (!loop_cond)
+ *loop_cond = vect_get_loop_niters (loop, number_of_iterations,
+ number_of_iterationsm1);
+ if (!*loop_cond)
{
if (dump_enabled_p ())
dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
"not vectorized: complicated exit condition.\n");
- if (inner_loop_vinfo)
- destroy_loop_vec_info (inner_loop_vinfo, true);
- return NULL;
+ return false;
}
- if (!number_of_iterations
- || chrec_contains_undetermined (number_of_iterations))
+ if (!*number_of_iterations
+ || chrec_contains_undetermined (*number_of_iterations))
{
if (dump_enabled_p ())
dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
"not vectorized: number of iterations cannot be "
"computed.\n");
- if (inner_loop_vinfo)
- destroy_loop_vec_info (inner_loop_vinfo, true);
- return NULL;
+ return false;
}
- if (integer_zerop (number_of_iterations))
+ if (integer_zerop (*number_of_iterations))
{
if (dump_enabled_p ())
dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
"not vectorized: number of iterations = 0.\n");
- if (inner_loop_vinfo)
- destroy_loop_vec_info (inner_loop_vinfo, true);
- return NULL;
+ return false;
}
- loop_vinfo = new_loop_vec_info (loop);
+ return true;
+}
+
+/* Analyze LOOP form and return a loop_vec_info if it is of suitable form. */
+
+loop_vec_info
+vect_analyze_loop_form (struct loop *loop)
+{
+ tree number_of_iterations, number_of_iterationsm1;
+ gcond *loop_cond, *inner_loop_cond = NULL;
+
+ if (! vect_analyze_loop_form_1 (loop, &loop_cond, &number_of_iterationsm1,
+ &number_of_iterations, &inner_loop_cond))
+ return NULL;
+
+ loop_vec_info loop_vinfo = new_loop_vec_info (loop);
LOOP_VINFO_NITERSM1 (loop_vinfo) = number_of_iterationsm1;
LOOP_VINFO_NITERS (loop_vinfo) = number_of_iterations;
LOOP_VINFO_NITERS_UNCHANGED (loop_vinfo) = number_of_iterations;
@@ -1421,16 +1348,17 @@ vect_analyze_loop_form (struct loop *loo
}
STMT_VINFO_TYPE (vinfo_for_stmt (loop_cond)) = loop_exit_ctrl_vec_info_type;
-
- /* CHECKME: May want to keep it around it in the future. */
- if (inner_loop_vinfo)
- destroy_loop_vec_info (inner_loop_vinfo, false);
+ if (inner_loop_cond)
+ STMT_VINFO_TYPE (vinfo_for_stmt (inner_loop_cond))
+ = loop_exit_ctrl_vec_info_type;
gcc_assert (!loop->aux);
loop->aux = loop_vinfo;
return loop_vinfo;
}
+
+
/* Scan the loop stmts and dependent on whether there are any (non-)SLP
statements update the vectorization factor. */
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH] Vectorizer TLC
@ 2015-06-16 11:59 Richard Biener
0 siblings, 0 replies; 4+ messages in thread
From: Richard Biener @ 2015-06-16 11:59 UTC (permalink / raw)
To: gcc-patches
The following makes us create less useless statements (as can be seen
from the needed change to recip-vec-sqrtf-avx.c where we now fully
unroll one of the loops).
Bootstrapped and tested on x86_64-unknown-linux-gnu, applied.
Richard.
2015-06-16 Richard Biener <rguenther@suse.de>
* tree-vect-stmts.c (vectorizable_store): Adjust.
(vectorizable_load): Likewise.
* tree-vect-data-refs.c (vect_create_addr_base_for_vector_ref):
Simplify.
(vect_create_data_ref_ptr): Likewise.
(bump_vector_ptr): Adjust.
* gcc.target/i386/recip-vec-sqrtf-avx.c: Disable unrolling.
Index: gcc/tree-vect-stmts.c
===================================================================
*** gcc/tree-vect-stmts.c (revision 224324)
--- gcc/tree-vect-stmts.c (working copy)
*************** vectorizable_store (gimple stmt, gimple_
*** 5572,5582 ****
vect_permute_store_chain(). */
vec_oprnd = result_chain[i];
! data_ref = build2 (MEM_REF, TREE_TYPE (vec_oprnd), dataref_ptr,
! dataref_offset
! ? dataref_offset
! : build_int_cst (reference_alias_ptr_type
! (DR_REF (first_dr)), 0));
align = TYPE_ALIGN_UNIT (vectype);
if (aligned_access_p (first_dr))
misalign = 0;
--- 5572,5583 ----
vect_permute_store_chain(). */
vec_oprnd = result_chain[i];
! data_ref = fold_build2 (MEM_REF, TREE_TYPE (vec_oprnd),
! dataref_ptr,
! dataref_offset
! ? dataref_offset
! : build_int_cst (reference_alias_ptr_type
! (DR_REF (first_dr)), 0));
align = TYPE_ALIGN_UNIT (vectype);
if (aligned_access_p (first_dr))
misalign = 0;
*************** vectorizable_store (gimple stmt, gimple_
*** 5595,5601 ****
TYPE_ALIGN (elem_type));
misalign = DR_MISALIGNMENT (first_dr);
}
! if (dataref_offset == NULL_TREE)
set_ptr_info_alignment (get_ptr_info (dataref_ptr), align,
misalign);
--- 5596,5603 ----
TYPE_ALIGN (elem_type));
misalign = DR_MISALIGNMENT (first_dr);
}
! if (dataref_offset == NULL_TREE
! && TREE_CODE (dataref_ptr) == SSA_NAME)
set_ptr_info_alignment (get_ptr_info (dataref_ptr), align,
misalign);
*************** vectorizable_load (gimple stmt, gimple_s
*** 6637,6647 ****
unsigned int align, misalign;
data_ref
! = build2 (MEM_REF, vectype, dataref_ptr,
! dataref_offset
! ? dataref_offset
! : build_int_cst (reference_alias_ptr_type
! (DR_REF (first_dr)), 0));
align = TYPE_ALIGN_UNIT (vectype);
if (alignment_support_scheme == dr_aligned)
{
--- 6645,6655 ----
unsigned int align, misalign;
data_ref
! = fold_build2 (MEM_REF, vectype, dataref_ptr,
! dataref_offset
! ? dataref_offset
! : build_int_cst (reference_alias_ptr_type
! (DR_REF (first_dr)), 0));
align = TYPE_ALIGN_UNIT (vectype);
if (alignment_support_scheme == dr_aligned)
{
*************** vectorizable_load (gimple stmt, gimple_s
*** 6663,6669 ****
TYPE_ALIGN (elem_type));
misalign = DR_MISALIGNMENT (first_dr);
}
! if (dataref_offset == NULL_TREE)
set_ptr_info_alignment (get_ptr_info (dataref_ptr),
align, misalign);
break;
--- 6671,6678 ----
TYPE_ALIGN (elem_type));
misalign = DR_MISALIGNMENT (first_dr);
}
! if (dataref_offset == NULL_TREE
! && TREE_CODE (dataref_ptr) == SSA_NAME)
set_ptr_info_alignment (get_ptr_info (dataref_ptr),
align, misalign);
break;
*************** vectorizable_load (gimple stmt, gimple_s
*** 6680,6686 ****
dr_explicit_realign,
dataref_ptr, NULL);
! ptr = copy_ssa_name (dataref_ptr);
new_stmt = gimple_build_assign
(ptr, BIT_AND_EXPR, dataref_ptr,
build_int_cst
--- 6689,6698 ----
dr_explicit_realign,
dataref_ptr, NULL);
! if (TREE_CODE (dataref_ptr) == SSA_NAME)
! ptr = copy_ssa_name (dataref_ptr);
! else
! ptr = make_ssa_name (TREE_TYPE (dataref_ptr));
new_stmt = gimple_build_assign
(ptr, BIT_AND_EXPR, dataref_ptr,
build_int_cst
*************** vectorizable_load (gimple stmt, gimple_s
*** 6710,6716 ****
build_int_cst
(TREE_TYPE (ptr),
-(HOST_WIDE_INT)TYPE_ALIGN_UNIT (vectype)));
! ptr = copy_ssa_name (dataref_ptr, new_stmt);
gimple_assign_set_lhs (new_stmt, ptr);
vect_finish_stmt_generation (stmt, new_stmt, gsi);
data_ref
--- 6722,6728 ----
build_int_cst
(TREE_TYPE (ptr),
-(HOST_WIDE_INT)TYPE_ALIGN_UNIT (vectype)));
! ptr = copy_ssa_name (ptr, new_stmt);
gimple_assign_set_lhs (new_stmt, ptr);
vect_finish_stmt_generation (stmt, new_stmt, gsi);
data_ref
*************** vectorizable_load (gimple stmt, gimple_s
*** 6720,6726 ****
break;
}
case dr_explicit_realign_optimized:
! new_temp = copy_ssa_name (dataref_ptr);
new_stmt = gimple_build_assign
(new_temp, BIT_AND_EXPR, dataref_ptr,
build_int_cst
--- 6732,6741 ----
break;
}
case dr_explicit_realign_optimized:
! if (TREE_CODE (dataref_ptr) == SSA_NAME)
! new_temp = copy_ssa_name (dataref_ptr);
! else
! new_temp = make_ssa_name (TREE_TYPE (dataref_ptr));
new_stmt = gimple_build_assign
(new_temp, BIT_AND_EXPR, dataref_ptr,
build_int_cst
Index: gcc/tree-vect-data-refs.c
===================================================================
*** gcc/tree-vect-data-refs.c (revision 224324)
--- gcc/tree-vect-data-refs.c (working copy)
*************** vect_create_addr_base_for_vector_ref (gi
*** 3956,3968 ****
}
vect_ptr_type = build_pointer_type (STMT_VINFO_VECTYPE (stmt_info));
- addr_base = fold_convert (vect_ptr_type, addr_base);
dest = vect_get_new_vect_var (vect_ptr_type, vect_pointer_var, base_name);
! addr_base = force_gimple_operand (addr_base, &seq, false, dest);
gimple_seq_add_seq (new_stmt_list, seq);
if (DR_PTR_INFO (dr)
! && TREE_CODE (addr_base) == SSA_NAME)
{
vect_duplicate_ssa_name_ptr_info (addr_base, dr, stmt_info);
if (offset || byte_offset)
--- 3956,3968 ----
}
vect_ptr_type = build_pointer_type (STMT_VINFO_VECTYPE (stmt_info));
dest = vect_get_new_vect_var (vect_ptr_type, vect_pointer_var, base_name);
! addr_base = force_gimple_operand (addr_base, &seq, true, dest);
gimple_seq_add_seq (new_stmt_list, seq);
if (DR_PTR_INFO (dr)
! && TREE_CODE (addr_base) == SSA_NAME
! && !SSA_NAME_PTR_INFO (addr_base))
{
vect_duplicate_ssa_name_ptr_info (addr_base, dr, stmt_info);
if (offset || byte_offset)
*************** vect_create_data_ref_ptr (gimple stmt, t
*** 4048,4054 ****
tree aggr_ptr_type;
tree aggr_ptr;
tree new_temp;
- gimple vec_stmt;
gimple_seq new_stmt_list = NULL;
edge pe = NULL;
basic_block new_bb;
--- 4048,4053 ----
*************** vect_create_data_ref_ptr (gimple stmt, t
*** 4196,4223 ****
}
*initial_address = new_temp;
!
! /* Create: p = (aggr_type *) initial_base */
! if (TREE_CODE (new_temp) != SSA_NAME
! || !useless_type_conversion_p (aggr_ptr_type, TREE_TYPE (new_temp)))
! {
! vec_stmt = gimple_build_assign (aggr_ptr,
! fold_convert (aggr_ptr_type, new_temp));
! aggr_ptr_init = make_ssa_name (aggr_ptr, vec_stmt);
! /* Copy the points-to information if it exists. */
! if (DR_PTR_INFO (dr))
! vect_duplicate_ssa_name_ptr_info (aggr_ptr_init, dr, stmt_info);
! gimple_assign_set_lhs (vec_stmt, aggr_ptr_init);
! if (pe)
! {
! new_bb = gsi_insert_on_edge_immediate (pe, vec_stmt);
! gcc_assert (!new_bb);
! }
! else
! gsi_insert_before (gsi, vec_stmt, GSI_SAME_STMT);
! }
! else
! aggr_ptr_init = new_temp;
/* (3) Handle the updating of the aggregate-pointer inside the loop.
This is needed when ONLY_INIT is false, and also when AT_LOOP is the
--- 4195,4201 ----
}
*initial_address = new_temp;
! aggr_ptr_init = new_temp;
/* (3) Handle the updating of the aggregate-pointer inside the loop.
This is needed when ONLY_INIT is false, and also when AT_LOOP is the
*************** bump_vector_ptr (tree dataref_ptr, gimpl
*** 4342,4348 ****
if (bump)
update = bump;
! new_dataref_ptr = copy_ssa_name (dataref_ptr);
incr_stmt = gimple_build_assign (new_dataref_ptr, POINTER_PLUS_EXPR,
dataref_ptr, update);
vect_finish_stmt_generation (stmt, incr_stmt, gsi);
--- 4320,4329 ----
if (bump)
update = bump;
! if (TREE_CODE (dataref_ptr) == SSA_NAME)
! new_dataref_ptr = copy_ssa_name (dataref_ptr);
! else
! new_dataref_ptr = make_ssa_name (TREE_TYPE (dataref_ptr));
incr_stmt = gimple_build_assign (new_dataref_ptr, POINTER_PLUS_EXPR,
dataref_ptr, update);
vect_finish_stmt_generation (stmt, incr_stmt, gsi);
Index: gcc/testsuite/gcc.target/i386/recip-vec-sqrtf-avx.c
===================================================================
--- gcc/testsuite/gcc.target/i386/recip-vec-sqrtf-avx.c (revision 224513)
+++ gcc/testsuite/gcc.target/i386/recip-vec-sqrtf-avx.c (working copy)
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -ffast-math -ftree-vectorize -mavx -mtune=generic -mfpmath=sse -mrecip" } */
+/* { dg-options "-O2 -ffast-math -ftree-vectorize -mavx -mtune=generic -mfpmath=sse -mrecip --param max-completely-peel-times=1" } */
float a[32];
float b[32];
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH] Vectorizer TLC
@ 2012-05-16 13:20 Richard Guenther
0 siblings, 0 replies; 4+ messages in thread
From: Richard Guenther @ 2012-05-16 13:20 UTC (permalink / raw)
To: gcc-patches
I noticed a write-only bitmap and some odd CFG hooks initializing code.
Removed as follows.
Bootstrapped and tested on x86_64-unknown-linux-gnu, applied.
Richard.
2012-05-16 Richard Guenther <rguenther@suse.de>
* tree-vect-loop-manip.c (slpeel_update_phi_nodes_for_guard1):
Remove set-only bitmap of new names.
(slpeel_tree_peel_loop_to_edge): Likewise. Do not set
CFG hooks.
* tree-flow.h (ssa_names_to_replace): Remove.
* tree-into-ssa.c (ssa_names_to_replace): Likewise.
Index: gcc/tree-vect-loop-manip.c
===================================================================
--- gcc/tree-vect-loop-manip.c (revision 187534)
+++ gcc/tree-vect-loop-manip.c (working copy)
@@ -489,8 +489,7 @@ LOOP-> loop1
static void
slpeel_update_phi_nodes_for_guard1 (edge guard_edge, struct loop *loop,
- bool is_new_loop, basic_block *new_exit_bb,
- bitmap *defs)
+ bool is_new_loop, basic_block *new_exit_bb)
{
gimple orig_phi, new_phi;
gimple update_phi, update_phi2;
@@ -586,7 +585,6 @@ slpeel_update_phi_nodes_for_guard1 (edge
gcc_assert (get_current_def (current_new_name) == NULL_TREE);
set_current_def (current_new_name, PHI_RESULT (new_phi));
- bitmap_set_bit (*defs, SSA_NAME_VERSION (current_new_name));
}
}
@@ -1159,7 +1157,6 @@ slpeel_tree_peel_loop_to_edge (struct lo
struct loop *new_loop = NULL, *first_loop, *second_loop;
edge skip_e;
tree pre_condition = NULL_TREE;
- bitmap definitions;
basic_block bb_before_second_loop, bb_after_second_loop;
basic_block bb_before_first_loop;
basic_block bb_between_loops;
@@ -1172,12 +1169,6 @@ slpeel_tree_peel_loop_to_edge (struct lo
if (!slpeel_can_duplicate_loop_p (loop, e))
return NULL;
- /* We have to initialize cfg_hooks. Then, when calling
- cfg_hooks->split_edge, the function tree_split_edge
- is actually called and, when calling cfg_hooks->duplicate_block,
- the function tree_duplicate_bb is called. */
- gimple_register_cfg_hooks ();
-
/* If the loop has a virtual PHI, but exit bb doesn't, create a virtual PHI
in the exit bb and rename all the uses after the loop. This simplifies
the *guard[12] routines, which assume loop closed SSA form for all PHIs
@@ -1259,7 +1250,6 @@ slpeel_tree_peel_loop_to_edge (struct lo
second_loop = loop;
}
- definitions = ssa_names_to_replace ();
slpeel_update_phis_for_duplicate_loop (loop, new_loop, e == exit_e);
rename_variables_in_loop (new_loop);
@@ -1397,7 +1387,7 @@ slpeel_tree_peel_loop_to_edge (struct lo
bb_before_second_loop, bb_before_first_loop);
slpeel_update_phi_nodes_for_guard1 (skip_e, first_loop,
first_loop == new_loop,
- &new_exit_bb, &definitions);
+ &new_exit_bb);
/* 3. Add the guard that controls whether the second loop is executed.
@@ -1441,7 +1431,6 @@ slpeel_tree_peel_loop_to_edge (struct lo
if (update_first_loop_count)
slpeel_make_loop_iterate_ntimes (first_loop, *first_niters);
- BITMAP_FREE (definitions);
delete_update_ssa ();
adjust_vec_debug_stmts ();
Index: gcc/tree-flow.h
===================================================================
*** gcc/tree-flow.h (revision 187589)
--- gcc/tree-flow.h (working copy)
*************** tree create_new_def_for (tree, gimple, d
*** 576,582 ****
bool need_ssa_update_p (struct function *);
bool name_mappings_registered_p (void);
bool name_registered_for_update_p (tree);
- bitmap ssa_names_to_replace (void);
void release_ssa_name_after_update_ssa (tree);
void compute_global_livein (bitmap, bitmap);
void mark_sym_for_renaming (tree);
--- 574,579 ----
Index: gcc/tree-into-ssa.c
===================================================================
*** gcc/tree-into-ssa.c (revision 187589)
--- gcc/tree-into-ssa.c (working copy)
*************** name_registered_for_update_p (tree n ATT
*** 3053,3078 ****
}
- /* Return the set of all the SSA names marked to be replaced. */
-
- bitmap
- ssa_names_to_replace (void)
- {
- unsigned i = 0;
- bitmap ret;
- sbitmap_iterator sbi;
-
- gcc_assert (update_ssa_initialized_fn == NULL
- || update_ssa_initialized_fn == cfun);
-
- ret = BITMAP_ALLOC (NULL);
- EXECUTE_IF_SET_IN_SBITMAP (old_ssa_names, 0, i, sbi)
- bitmap_set_bit (ret, i);
-
- return ret;
- }
-
-
/* Mark NAME to be released after update_ssa has finished. */
void
--- 3053,3058 ----
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2015-10-07 9:00 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-03-18 11:40 [PATCH] Vectorizer TLC Richard Biener
-- strict thread matches above, loose matches on Subject: below --
2015-10-07 9:00 Richard Biener
2015-06-16 11:59 Richard Biener
2012-05-16 13:20 Richard Guenther
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).