diff options
author | Richard Biener <rguenther@suse.de> | 2019-05-03 10:39:56 +0000 |
---|---|---|
committer | Richard Biener <rguenth@gcc.gnu.org> | 2019-05-03 10:39:56 +0000 |
commit | a7eb97ad269b6509bd7b31ca373daea98e4d7e85 (patch) | |
tree | a29da7cddfeb73ebddf097156d20dfb4b360880c | |
parent | e7a89a659afeaae763761dab0a7fd3f2f7ddcbe2 (diff) | |
download | gcc-a7eb97ad269b6509bd7b31ca373daea98e4d7e85.zip gcc-a7eb97ad269b6509bd7b31ca373daea98e4d7e85.tar.gz gcc-a7eb97ad269b6509bd7b31ca373daea98e4d7e85.tar.bz2 |
re PR middle-end/88963 (gcc generates terrible code for vectors of 64+ length which are not natively supported)
2019-05-03 Richard Biener <rguenther@suse.de>
PR tree-optimization/88963
* tree-ssa-forwprop.c (pass_forwprop::execute): Rewrite
vector loads feeding only BIT_FIELD_REFs to component
loads. Rewrite stores fed by CONSTRUCTORs to component
stores.
* gcc.dg/tree-ssa/ssa-fre-31.c: Disable forwprop.
* gcc.target/i386/pr88963-1.c: New testcase.
* gcc.target/i386/pr88963-2.c: Likewise.
From-SVN: r270844
-rw-r--r-- | gcc/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-31.c | 2 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/i386/pr88963-1.c | 13 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/i386/pr88963-2.c | 14 | ||||
-rw-r--r-- | gcc/tree-ssa-forwprop.c | 125 |
6 files changed, 168 insertions, 1 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 346cb5f..80c34be 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2019-05-03 Richard Biener <rguenther@suse.de> + + PR tree-optimization/88963 + * tree-ssa-forwprop.c (pass_forwprop::execute): Rewrite + vector loads feeding only BIT_FIELD_REFs to component + loads. Rewrite stores fed by CONSTRUCTORs to component + stores. + 2019-05-03 Jakub Jelinek <jakub@redhat.com> * opts.h (finish_options): Remove lang_mask argument. diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 2bb5609..57a07d1 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2019-05-03 Richard Biener <rguenther@suse.de> + + PR tree-optimization/88963 + * gcc.dg/tree-ssa/ssa-fre-31.c: Disable forwprop. + * gcc.target/i386/pr88963-1.c: New testcase. + * gcc.target/i386/pr88963-2.c: Likewise. + 2019-05-03 Dominique d'Humieres <dominiq@gcc.gnu.org> PR target/88809 diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-31.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-31.c index 6402c81..3d429ab 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-31.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-31.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O -fdump-tree-fre1-details" } */ +/* { dg-options "-O -fdump-tree-fre1-details -fno-tree-forwprop" } */ /* { dg-additional-options "-fno-common" { target hppa*-*-hpux* } } */ typedef double d128 __attribute__((vector_size(16))); diff --git a/gcc/testsuite/gcc.target/i386/pr88963-1.c b/gcc/testsuite/gcc.target/i386/pr88963-1.c new file mode 100644 index 0000000..e6f1525 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr88963-1.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=x86-64 -mavx2 -fdump-tree-optimized" } */ + +typedef int VInt __attribute__((vector_size(64))); + +void test(VInt*__restrict a, VInt*__restrict b, + VInt*__restrict c) +{ + *a = *b + *c; +} + +/* Vector loads and stores should be split. */ +/* { dg-final { scan-tree-dump-not "vector\\(16\\)" "optimized" } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr88963-2.c b/gcc/testsuite/gcc.target/i386/pr88963-2.c new file mode 100644 index 0000000..114f1f5 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr88963-2.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=x86-64 -msse2 -fdump-tree-optimized" } */ + +typedef int VInt __attribute__((vector_size(64))); + +void test(VInt*__restrict a, VInt*__restrict b, + VInt*__restrict c) +{ + *a = *b + *c; +} + +/* Vector loads and stores should be split. */ +/* { dg-final { scan-tree-dump-not "vector\\(16\\)" "optimized" } } */ +/* { dg-final { scan-tree-dump-not "vector\\(8\\)" "optimized" } } */ diff --git a/gcc/tree-ssa-forwprop.c b/gcc/tree-ssa-forwprop.c index bbfa1bc..1553c9e 100644 --- a/gcc/tree-ssa-forwprop.c +++ b/gcc/tree-ssa-forwprop.c @@ -2400,6 +2400,72 @@ pass_forwprop::execute (function *fun) else gsi_next (&gsi); } + else if (TREE_CODE (TREE_TYPE (lhs)) == VECTOR_TYPE + && TYPE_MODE (TREE_TYPE (lhs)) == BLKmode + && gimple_assign_load_p (stmt) + && !gimple_has_volatile_ops (stmt) + && (TREE_CODE (gimple_assign_rhs1 (stmt)) + != TARGET_MEM_REF) + && !stmt_can_throw_internal (cfun, stmt)) + { + /* Rewrite loads used only in BIT_FIELD_REF extractions to + component-wise loads. */ + use_operand_p use_p; + imm_use_iterator iter; + bool rewrite = true; + FOR_EACH_IMM_USE_FAST (use_p, iter, lhs) + { + gimple *use_stmt = USE_STMT (use_p); + if (is_gimple_debug (use_stmt)) + continue; + if (!is_gimple_assign (use_stmt) + || gimple_assign_rhs_code (use_stmt) != BIT_FIELD_REF) + { + rewrite = false; + break; + } + } + if (rewrite) + { + gimple *use_stmt; + FOR_EACH_IMM_USE_STMT (use_stmt, iter, lhs) + { + if (is_gimple_debug (use_stmt)) + { + if (gimple_debug_bind_p (use_stmt)) + { + gimple_debug_bind_reset_value (use_stmt); + update_stmt (use_stmt); + } + continue; + } + + tree bfr = gimple_assign_rhs1 (use_stmt); + tree new_rhs = fold_build3 (BIT_FIELD_REF, + TREE_TYPE (bfr), + unshare_expr (rhs), + TREE_OPERAND (bfr, 1), + TREE_OPERAND (bfr, 2)); + gimple *new_stmt + = gimple_build_assign (gimple_assign_lhs (use_stmt), + new_rhs); + + location_t loc = gimple_location (use_stmt); + gimple_set_location (new_stmt, loc); + gimple_stmt_iterator gsi2 = gsi_for_stmt (use_stmt); + unlink_stmt_vdef (use_stmt); + gsi_remove (&gsi2, true); + + gsi_insert_before (&gsi, new_stmt, GSI_SAME_STMT); + } + + release_defs (stmt); + gsi_remove (&gsi, true); + } + else + gsi_next (&gsi); + } + else if (code == COMPLEX_EXPR) { /* Rewrite stores of a single-use complex build expression @@ -2440,6 +2506,65 @@ pass_forwprop::execute (function *fun) else gsi_next (&gsi); } + else if (code == CONSTRUCTOR + && VECTOR_TYPE_P (TREE_TYPE (rhs)) + && TYPE_MODE (TREE_TYPE (rhs)) == BLKmode + && CONSTRUCTOR_NELTS (rhs) > 0 + && (!VECTOR_TYPE_P (TREE_TYPE (CONSTRUCTOR_ELT (rhs, 0)->value)) + || (TYPE_MODE (TREE_TYPE (CONSTRUCTOR_ELT (rhs, 0)->value)) + != BLKmode))) + { + /* Rewrite stores of a single-use vector constructors + to component-wise stores if the mode isn't supported. */ + use_operand_p use_p; + gimple *use_stmt; + if (single_imm_use (lhs, &use_p, &use_stmt) + && gimple_store_p (use_stmt) + && !gimple_has_volatile_ops (use_stmt) + && is_gimple_assign (use_stmt) + && (TREE_CODE (gimple_assign_lhs (use_stmt)) + != TARGET_MEM_REF)) + { + tree elt_t = TREE_TYPE (CONSTRUCTOR_ELT (rhs, 0)->value); + unsigned HOST_WIDE_INT elt_w + = tree_to_uhwi (TYPE_SIZE (elt_t)); + unsigned HOST_WIDE_INT n + = tree_to_uhwi (TYPE_SIZE (TREE_TYPE (rhs))); + for (unsigned HOST_WIDE_INT bi = 0; bi < n; bi += elt_w) + { + unsigned HOST_WIDE_INT ci = bi / elt_w; + tree new_rhs; + if (ci < CONSTRUCTOR_NELTS (rhs)) + new_rhs = CONSTRUCTOR_ELT (rhs, ci)->value; + else + new_rhs = build_zero_cst (elt_t); + tree use_lhs = gimple_assign_lhs (use_stmt); + tree new_lhs = build3 (BIT_FIELD_REF, + elt_t, + unshare_expr (use_lhs), + bitsize_int (elt_w), + bitsize_int (bi)); + gimple *new_stmt = gimple_build_assign (new_lhs, new_rhs); + location_t loc = gimple_location (use_stmt); + gimple_set_location (new_stmt, loc); + gimple_set_vuse (new_stmt, gimple_vuse (use_stmt)); + gimple_set_vdef (new_stmt, + make_ssa_name (gimple_vop (cfun))); + SSA_NAME_DEF_STMT (gimple_vdef (new_stmt)) = new_stmt; + gimple_set_vuse (use_stmt, gimple_vdef (new_stmt)); + gimple_stmt_iterator gsi2 = gsi_for_stmt (use_stmt); + gsi_insert_before (&gsi2, new_stmt, GSI_SAME_STMT); + } + gimple_stmt_iterator gsi2 = gsi_for_stmt (use_stmt); + unlink_stmt_vdef (use_stmt); + release_defs (use_stmt); + gsi_remove (&gsi2, true); + release_defs (stmt); + gsi_remove (&gsi, true); + } + else + gsi_next (&gsi); + } else gsi_next (&gsi); } |