From: Richard Biener Date: Mon, 23 Feb 2015 11:14:25 +0000 (+0000) Subject: Backport PRs 59354, 61634, 63844, 64909 X-Git-Tag: releases/gcc-4.9.3~333 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=18e1c0f9952c58ee701b1ad3ca5c721b9967b672;p=thirdparty%2Fgcc.git Backport PRs 59354, 61634, 63844, 64909 2015-02-23 Richard Biener Backport from mainline 2014-11-19 Richard Biener PR tree-optimization/63844 * omp-low.c (fixup_child_record_type): Use a restrict qualified referece type for the receiver parameter. 2014-11-27 Richard Biener PR tree-optimization/61634 * tree-vect-slp.c: Include gimple-walk.h. (vect_detect_hybrid_slp_stmts): Rewrite to propagate hybrid down the SLP tree for one scalar statement. (vect_detect_hybrid_slp_1): New walker function. (vect_detect_hybrid_slp_2): Likewise. (vect_detect_hybrid_slp): Properly handle pattern statements in a pre-scan over all loop stmts. * gcc.dg/vect/pr61634.c: New testcase. 2015-01-14 Richard Biener PR tree-optimization/59354 * tree-vect-slp.c (vect_build_slp_tree_1): Treat loads from groups larger than the slp group size as having gaps. * gcc.dg/vect/pr59354.c: New testcase. 2015-02-10 Richard Biener PR tree-optimization/64909 * tree-vect-loop.c (vect_estimate_min_profitable_iters): Properly pass a scalar-stmt count estimate to the cost model. * tree-vect-data-refs.c (vect_peeling_hash_get_lowest_cost): Likewise. * gcc.dg/vect/costmodel/x86_64/costmodel-pr64909.c: New testcase. From-SVN: r220912 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 098531d7952d..b2b2398a1d01 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,36 @@ +2015-02-23 Richard Biener + + Backport from mainline + 2014-11-19 Richard Biener + + PR tree-optimization/63844 + * omp-low.c (fixup_child_record_type): Use a restrict qualified + referece type for the receiver parameter. + + 2014-11-27 Richard Biener + + PR tree-optimization/61634 + * tree-vect-slp.c: Include gimple-walk.h. + (vect_detect_hybrid_slp_stmts): Rewrite to propagate hybrid + down the SLP tree for one scalar statement. + (vect_detect_hybrid_slp_1): New walker function. + (vect_detect_hybrid_slp_2): Likewise. + (vect_detect_hybrid_slp): Properly handle pattern statements + in a pre-scan over all loop stmts. + + 2015-01-14 Richard Biener + + PR tree-optimization/59354 + * tree-vect-slp.c (vect_build_slp_tree_1): Treat loads from + groups larger than the slp group size as having gaps. + + 2015-02-10 Richard Biener + + PR tree-optimization/64909 + * tree-vect-loop.c (vect_estimate_min_profitable_iters): Properly + pass a scalar-stmt count estimate to the cost model. + * tree-vect-data-refs.c (vect_peeling_hash_get_lowest_cost): Likewise. + 2015-02-20 Kyrylo Tkachov Backport from mainline diff --git a/gcc/omp-low.c b/gcc/omp-low.c index f0059be6b5db..f42c1d266cb5 100644 --- a/gcc/omp-low.c +++ b/gcc/omp-low.c @@ -1483,7 +1483,8 @@ fixup_child_record_type (omp_context *ctx) layout_type (type); } - TREE_TYPE (ctx->receiver_decl) = build_pointer_type (type); + TREE_TYPE (ctx->receiver_decl) + = build_qualified_type (build_reference_type (type), TYPE_QUAL_RESTRICT); } /* Instantiate decls as necessary in CTX to satisfy the data sharing diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index d54b35e38499..d9bff1567fc7 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,21 @@ +2015-02-23 Richard Biener + + Backport from mainline + 2014-11-27 Richard Biener + + PR tree-optimization/61634 + * gcc.dg/vect/pr61634.c: New testcase. + + 2015-01-14 Richard Biener + + PR tree-optimization/59354 + * gcc.dg/vect/pr59354.c: New testcase. + + 2015-02-10 Richard Biener + + PR tree-optimization/64909 + * gcc.dg/vect/costmodel/x86_64/costmodel-pr64909.c: New testcase. + 2015-02-23 Andreas Krebbel Backport from mainline diff --git a/gcc/testsuite/gcc.dg/vect/costmodel/x86_64/costmodel-pr64909.c b/gcc/testsuite/gcc.dg/vect/costmodel/x86_64/costmodel-pr64909.c new file mode 100644 index 000000000000..0f9feac6a333 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/costmodel/x86_64/costmodel-pr64909.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target vect_int } */ +/* { dg-additional-options "-mtune=bdver1" } */ + +unsigned short a[32]; +unsigned int b[32]; +void t() +{ + int i; + for (i=0;i<12;i++) + b[i]=a[i]; +} + +/* { dg-final { scan-tree-dump "vectorized 1 loops in function" "vect" } } */ +/* { dg-final { cleanup-tree-dump "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/pr59354.c b/gcc/testsuite/gcc.dg/vect/pr59354.c new file mode 100644 index 000000000000..37fca9d25a43 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/pr59354.c @@ -0,0 +1,35 @@ +/* { dg-do run } */ +/* { dg-additional-options "-O3" } */ + +#include "tree-vect.h" + +void abort (void); + +unsigned int a[256]; +unsigned char b[256]; + +int main() +{ + int i, z, x, y; + + check_vect (); + + for(i = 0; i < 256; i++) + { + a[i] = i % 5; + __asm__ volatile (""); + } + + for (z = 0; z < 16; z++) + for (y = 0; y < 4; y++) + for (x = 0; x < 4; x++) + b[y*64 + z*4 + x] = a[z*16 + y*4 + x]; + + if (b[4] != 1) + abort (); + + return 0; +} + +/* { dg-final { scan-tree-dump "vectorized 1 loop" "vect" { target { vect_pack_trunc } } } } */ +/* { dg-final { cleanup-tree-dump "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/pr61634.c b/gcc/testsuite/gcc.dg/vect/pr61634.c new file mode 100644 index 000000000000..80b2c3a25468 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/pr61634.c @@ -0,0 +1,24 @@ +/* { dg-do compile } */ + +int a, b, c, d; +short *e; +void fn1 (int p1[], int p2, int p3[], int p4[], int p5[], int *p6) +{ + int f; + c = *p1; + d = *p5; + (void)p6; + for (; a; a--) + { + f = *e >> 2; + *e++ = f; + b += f * f; + f = *e >> 2; + *e++ = f; + } + p4[0] = p3[0]; + for (;; p2--) + ; +} + +/* { dg-final { cleanup-tree-dump "vect" } } */ diff --git a/gcc/tree-vect-data-refs.c b/gcc/tree-vect-data-refs.c index 49303b1b58aa..04d6dc9d4f04 100644 --- a/gcc/tree-vect-data-refs.c +++ b/gcc/tree-vect-data-refs.c @@ -1150,10 +1150,13 @@ vect_peeling_hash_get_lowest_cost (_vect_peel_info **slot, } single_iter_cost = vect_get_single_scalar_iteration_cost (loop_vinfo); - outside_cost += vect_get_known_peeling_cost (loop_vinfo, elem->npeel, - &dummy, single_iter_cost, - &prologue_cost_vec, - &epilogue_cost_vec); + outside_cost += vect_get_known_peeling_cost + (loop_vinfo, elem->npeel, &dummy, + /* ??? We use this cost as number of stmts with scalar_stmt cost, + thus divide by that. This introduces rounding errors, thus better + introduce a new cost kind (raw_cost? scalar_iter_cost?). */ + single_iter_cost / vect_get_stmt_cost (scalar_stmt), + &prologue_cost_vec, &epilogue_cost_vec); /* Prologue and epilogue costs are added to the target model later. These costs depend only on the scalar iteration cost, the diff --git a/gcc/tree-vect-loop.c b/gcc/tree-vect-loop.c index 59512fea651d..bb8a9841d632 100644 --- a/gcc/tree-vect-loop.c +++ b/gcc/tree-vect-loop.c @@ -2801,6 +2801,11 @@ vect_estimate_min_profitable_iters (loop_vec_info loop_vinfo, statements. */ scalar_single_iter_cost = vect_get_single_scalar_iteration_cost (loop_vinfo); + /* ??? Below we use this cost as number of stmts with scalar_stmt cost, + thus divide by that. This introduces rounding errors, thus better + introduce a new cost kind (raw_cost? scalar_iter_cost?). */ + int scalar_single_iter_stmts + = scalar_single_iter_cost / vect_get_stmt_cost (scalar_stmt); /* Add additional cost for the peeled instructions in prologue and epilogue loop. @@ -2835,10 +2840,10 @@ vect_estimate_min_profitable_iters (loop_vec_info loop_vinfo, /* FORNOW: Don't attempt to pass individual scalar instructions to the model; just assume linear cost for scalar iterations. */ (void) add_stmt_cost (target_cost_data, - peel_iters_prologue * scalar_single_iter_cost, + peel_iters_prologue * scalar_single_iter_stmts, scalar_stmt, NULL, 0, vect_prologue); (void) add_stmt_cost (target_cost_data, - peel_iters_epilogue * scalar_single_iter_cost, + peel_iters_epilogue * scalar_single_iter_stmts, scalar_stmt, NULL, 0, vect_epilogue); } else @@ -2854,7 +2859,7 @@ vect_estimate_min_profitable_iters (loop_vec_info loop_vinfo, (void) vect_get_known_peeling_cost (loop_vinfo, peel_iters_prologue, &peel_iters_epilogue, - scalar_single_iter_cost, + scalar_single_iter_stmts, &prologue_cost_vec, &epilogue_cost_vec); diff --git a/gcc/tree-vect-slp.c b/gcc/tree-vect-slp.c index 59842291a998..7a03b2e9f65e 100644 --- a/gcc/tree-vect-slp.c +++ b/gcc/tree-vect-slp.c @@ -47,6 +47,7 @@ along with GCC; see the file COPYING3. If not see #include "optabs.h" #include "tree-vectorizer.h" #include "langhooks.h" +#include "gimple-walk.h" /* Extract the location of the basic block in the source code. Return the basic block location if succeed and NULL if not. */ @@ -671,8 +672,11 @@ vect_build_slp_tree_1 (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo, ??? We should enhance this to only disallow gaps inside vectors. */ if ((unrolling_factor > 1 - && GROUP_FIRST_ELEMENT (vinfo_for_stmt (stmt)) == stmt - && GROUP_GAP (vinfo_for_stmt (stmt)) != 0) + && ((GROUP_FIRST_ELEMENT (vinfo_for_stmt (stmt)) == stmt + && GROUP_GAP (vinfo_for_stmt (stmt)) != 0) + /* If the group is split up then GROUP_GAP + isn't correct here, nor is GROUP_FIRST_ELEMENT. */ + || GROUP_SIZE (vinfo_for_stmt (stmt)) > group_size)) || (GROUP_FIRST_ELEMENT (vinfo_for_stmt (stmt)) != stmt && GROUP_GAP (vinfo_for_stmt (stmt)) != 1)) { @@ -1761,51 +1765,83 @@ vect_make_slp_decision (loop_vec_info loop_vinfo) can't be SLPed) in the tree rooted at NODE. Mark such stmts as HYBRID. */ static void -vect_detect_hybrid_slp_stmts (slp_tree node) +vect_detect_hybrid_slp_stmts (slp_tree node, unsigned i, slp_vect_type stype) { - int i; - vec stmts = SLP_TREE_SCALAR_STMTS (node); - gimple stmt = stmts[0]; + gimple stmt = SLP_TREE_SCALAR_STMTS (node)[i]; imm_use_iterator imm_iter; gimple use_stmt; - stmt_vec_info stmt_vinfo = vinfo_for_stmt (stmt); + stmt_vec_info use_vinfo, stmt_vinfo = vinfo_for_stmt (stmt); slp_tree child; loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_vinfo); - struct loop *loop = NULL; - bb_vec_info bb_vinfo = STMT_VINFO_BB_VINFO (stmt_vinfo); - basic_block bb = NULL; + struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo); + int j; + + /* Propagate hybrid down the SLP tree. */ + if (stype == hybrid) + ; + else if (HYBRID_SLP_STMT (stmt_vinfo)) + stype = hybrid; + else + { + /* Check if a pure SLP stmt has uses in non-SLP stmts. */ + gcc_checking_assert (PURE_SLP_STMT (stmt_vinfo)); + if (TREE_CODE (gimple_op (stmt, 0)) == SSA_NAME) + FOR_EACH_IMM_USE_STMT (use_stmt, imm_iter, gimple_op (stmt, 0)) + if (gimple_bb (use_stmt) + && flow_bb_inside_loop_p (loop, gimple_bb (use_stmt)) + && (use_vinfo = vinfo_for_stmt (use_stmt)) + && !STMT_SLP_TYPE (use_vinfo) + && (STMT_VINFO_RELEVANT (use_vinfo) + || VECTORIZABLE_CYCLE_DEF (STMT_VINFO_DEF_TYPE (use_vinfo)) + || (STMT_VINFO_IN_PATTERN_P (use_vinfo) + && STMT_VINFO_RELATED_STMT (use_vinfo) + && !STMT_SLP_TYPE (vinfo_for_stmt + (STMT_VINFO_RELATED_STMT (use_vinfo))))) + && !(gimple_code (use_stmt) == GIMPLE_PHI + && STMT_VINFO_DEF_TYPE (use_vinfo) == vect_reduction_def)) + stype = hybrid; + } + + if (stype == hybrid) + STMT_SLP_TYPE (stmt_vinfo) = hybrid; + + FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (node), j, child) + vect_detect_hybrid_slp_stmts (child, i, stype); +} - if (!node) - return; +/* Helpers for vect_detect_hybrid_slp walking pattern stmt uses. */ - if (loop_vinfo) - loop = LOOP_VINFO_LOOP (loop_vinfo); - else - bb = BB_VINFO_BB (bb_vinfo); +static tree +vect_detect_hybrid_slp_1 (tree *tp, int *, void *data) +{ + walk_stmt_info *wi = (walk_stmt_info *)data; + struct loop *loopp = (struct loop *)wi->info; - FOR_EACH_VEC_ELT (SLP_TREE_SCALAR_STMTS (node), i, stmt) - if (PURE_SLP_STMT (vinfo_for_stmt (stmt)) - && TREE_CODE (gimple_op (stmt, 0)) == SSA_NAME) - FOR_EACH_IMM_USE_STMT (use_stmt, imm_iter, gimple_op (stmt, 0)) - if (gimple_bb (use_stmt) - && ((loop && flow_bb_inside_loop_p (loop, gimple_bb (use_stmt))) - || bb == gimple_bb (use_stmt)) - && (stmt_vinfo = vinfo_for_stmt (use_stmt)) - && !STMT_SLP_TYPE (stmt_vinfo) - && (STMT_VINFO_RELEVANT (stmt_vinfo) - || VECTORIZABLE_CYCLE_DEF (STMT_VINFO_DEF_TYPE (stmt_vinfo)) - || (STMT_VINFO_IN_PATTERN_P (stmt_vinfo) - && STMT_VINFO_RELATED_STMT (stmt_vinfo) - && !STMT_SLP_TYPE (vinfo_for_stmt (STMT_VINFO_RELATED_STMT (stmt_vinfo))))) - && !(gimple_code (use_stmt) == GIMPLE_PHI - && STMT_VINFO_DEF_TYPE (stmt_vinfo) - == vect_reduction_def)) - vect_mark_slp_stmts (node, hybrid, i); + if (wi->is_lhs) + return NULL_TREE; - FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (node), i, child) - vect_detect_hybrid_slp_stmts (child); + if (TREE_CODE (*tp) == SSA_NAME + && !SSA_NAME_IS_DEFAULT_DEF (*tp)) + { + gimple def_stmt = SSA_NAME_DEF_STMT (*tp); + if (flow_bb_inside_loop_p (loopp, gimple_bb (def_stmt)) + && PURE_SLP_STMT (vinfo_for_stmt (def_stmt))) + STMT_SLP_TYPE (vinfo_for_stmt (def_stmt)) = hybrid; + } + + return NULL_TREE; } +static tree +vect_detect_hybrid_slp_2 (gimple_stmt_iterator *gsi, bool *handled, + walk_stmt_info *) +{ + /* If the stmt is in a SLP instance then this isn't a reason + to mark use definitions in other SLP instances as hybrid. */ + if (STMT_SLP_TYPE (vinfo_for_stmt (gsi_stmt (*gsi))) != loop_vect) + *handled = true; + return NULL_TREE; +} /* Find stmts that must be both vectorized and SLPed. */ @@ -1820,8 +1856,41 @@ vect_detect_hybrid_slp (loop_vec_info loop_vinfo) dump_printf_loc (MSG_NOTE, vect_location, "=== vect_detect_hybrid_slp ===" "\n"); + /* First walk all pattern stmt in the loop and mark defs of uses as + hybrid because immediate uses in them are not recorded. */ + for (i = 0; i < LOOP_VINFO_LOOP (loop_vinfo)->num_nodes; ++i) + { + basic_block bb = LOOP_VINFO_BBS (loop_vinfo)[i]; + for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi); + gsi_next (&gsi)) + { + gimple stmt = gsi_stmt (gsi); + stmt_vec_info stmt_info = vinfo_for_stmt (stmt); + if (STMT_VINFO_IN_PATTERN_P (stmt_info)) + { + walk_stmt_info wi; + memset (&wi, 0, sizeof (wi)); + wi.info = LOOP_VINFO_LOOP (loop_vinfo); + gimple_stmt_iterator gsi2 + = gsi_for_stmt (STMT_VINFO_RELATED_STMT (stmt_info)); + walk_gimple_stmt (&gsi2, vect_detect_hybrid_slp_2, + vect_detect_hybrid_slp_1, &wi); + walk_gimple_seq (STMT_VINFO_PATTERN_DEF_SEQ (stmt_info), + vect_detect_hybrid_slp_2, + vect_detect_hybrid_slp_1, &wi); + } + } + } + + /* Then walk the SLP instance trees marking stmts with uses in + non-SLP stmts as hybrid, also propagating hybrid down the + SLP tree, collecting the above info on-the-fly. */ FOR_EACH_VEC_ELT (slp_instances, i, instance) - vect_detect_hybrid_slp_stmts (SLP_INSTANCE_TREE (instance)); + { + for (unsigned i = 0; i < SLP_INSTANCE_GROUP_SIZE (instance); ++i) + vect_detect_hybrid_slp_stmts (SLP_INSTANCE_TREE (instance), + i, pure_slp); + } }