On Fri, May 3, 2019 at 6:02 AM Richard Biener <rguent...@suse.de> wrote: > > > The following refactors simplify_vector_constructor and adds > handling of constants to it in a straight-forward way. > > A followup will handle the testcases posted in HJs patch. > > Bootstrap / regtest running on x86_64-unknown-linux-gnu. > > Richard. > > 2019-05-03 Richard Biener <rguent...@suse.de> > > PR tree-optimization/88828 > * tree-ssa-forwprop.c (get_bit_field_ref_def): Split out from... > (simplify_vector_constructor): ...here. Handle constants in > the constructor. > > * gcc.target/i386/pr88828-0.c: New testcase. > > Index: gcc/tree-ssa-forwprop.c > =================================================================== > --- gcc/tree-ssa-forwprop.c (revision 270847) > +++ gcc/tree-ssa-forwprop.c (working copy) > @@ -1997,6 +1997,44 @@ simplify_permutation (gimple_stmt_iterat > return 0; > } > > +/* Get the BIT_FIELD_REF definition of VAL, if any, looking through > + conversions with code CONV_CODE or update it if still ERROR_MARK. > + Return NULL_TREE if no such matching def was found. */ > + > +static tree > +get_bit_field_ref_def (tree val, enum tree_code &conv_code) > +{ > + if (TREE_CODE (val) != SSA_NAME) > + return NULL_TREE ; > + gimple *def_stmt = get_prop_source_stmt (val, false, NULL); > + if (!def_stmt) > + return NULL_TREE; > + enum tree_code code = gimple_assign_rhs_code (def_stmt); > + if (code == FLOAT_EXPR > + || code == FIX_TRUNC_EXPR) > + { > + tree op1 = gimple_assign_rhs1 (def_stmt); > + if (conv_code == ERROR_MARK) > + { > + if (maybe_ne (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (val))), > + GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (op1))))) > + return NULL_TREE; > + conv_code = code; > + } > + else if (conv_code != code) > + return NULL_TREE; > + if (TREE_CODE (op1) != SSA_NAME) > + return NULL_TREE; > + def_stmt = SSA_NAME_DEF_STMT (op1); > + if (! is_gimple_assign (def_stmt)) > + return NULL_TREE; > + code = gimple_assign_rhs_code (def_stmt); > + } > + if (code != BIT_FIELD_REF) > + return NULL_TREE; > + return gimple_assign_rhs1 (def_stmt); > +} > + > /* Recognize a VEC_PERM_EXPR. Returns true if there were any changes. */ > > static bool > @@ -2027,6 +2065,9 @@ simplify_vector_constructor (gimple_stmt > orig[1] = NULL; > conv_code = ERROR_MARK; > maybe_ident = true; > + tree one_constant = NULL_TREE; > + auto_vec<tree> constants; > + constants.safe_grow_cleared (nelts); > FOR_EACH_VEC_SAFE_ELT (CONSTRUCTOR_ELTS (op), i, elt) > { > tree ref, op1; > @@ -2034,68 +2075,55 @@ simplify_vector_constructor (gimple_stmt > if (i >= nelts) > return false; > > - if (TREE_CODE (elt->value) != SSA_NAME) > - return false; > - def_stmt = get_prop_source_stmt (elt->value, false, NULL); > - if (!def_stmt) > - return false; > - code = gimple_assign_rhs_code (def_stmt); > - if (code == FLOAT_EXPR > - || code == FIX_TRUNC_EXPR) > + op1 = get_bit_field_ref_def (elt->value, conv_code); > + if (op1) > { > - op1 = gimple_assign_rhs1 (def_stmt); > - if (conv_code == ERROR_MARK) > + ref = TREE_OPERAND (op1, 0); > + unsigned int j; > + for (j = 0; j < 2; ++j) > { > - if (maybe_ne (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE > (elt->value))), > - GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (op1))))) > - return false; > - conv_code = code; > + if (!orig[j]) > + { > + if (TREE_CODE (ref) != SSA_NAME) > + return false; > + if (! VECTOR_TYPE_P (TREE_TYPE (ref)) > + || ! useless_type_conversion_p (TREE_TYPE (op1), > + TREE_TYPE (TREE_TYPE > (ref)))) > + return false; > + if (j && !useless_type_conversion_p (TREE_TYPE (orig[0]), > + TREE_TYPE (ref))) > + return false; > + orig[j] = ref; > + break; > + } > + else if (ref == orig[j]) > + break; > } > - else if (conv_code != code) > + if (j == 2) > return false; > - if (TREE_CODE (op1) != SSA_NAME) > - return false; > - def_stmt = SSA_NAME_DEF_STMT (op1); > - if (! is_gimple_assign (def_stmt)) > + > + unsigned int elt; > + if (maybe_ne (bit_field_size (op1), elem_size) > + || !constant_multiple_p (bit_field_offset (op1), elem_size, > &elt)) > return false; > - code = gimple_assign_rhs_code (def_stmt); > + if (j) > + elt += nelts; > + if (elt != i) > + maybe_ident = false; > + sel.quick_push (elt); > } > - if (code != BIT_FIELD_REF) > - return false; > - op1 = gimple_assign_rhs1 (def_stmt); > - ref = TREE_OPERAND (op1, 0); > - unsigned int j; > - for (j = 0; j < 2; ++j) > + else if (CONSTANT_CLASS_P (elt->value)) > { > - if (!orig[j]) > - { > - if (TREE_CODE (ref) != SSA_NAME) > - return false; > - if (! VECTOR_TYPE_P (TREE_TYPE (ref)) > - || ! useless_type_conversion_p (TREE_TYPE (op1), > - TREE_TYPE (TREE_TYPE > (ref)))) > - return false; > - if (j && !useless_type_conversion_p (TREE_TYPE (orig[0]), > - TREE_TYPE (ref))) > - return false; > - orig[j] = ref; > - break; > - } > - else if (ref == orig[j]) > - break;
Missing else return false; [hjl@gnu-cfl-1 pr88828]$ cat x5.i typedef float __v4sf __attribute__ ((__vector_size__ (16))); __v4sf foo (__v4sf x, float f, float z) { __v4sf y = { f, x[0], z, x[3] }; return y; } [hjl@gnu-cfl-1 pr88828]$ make x5.s /export/build/gnu/tools-build/gcc-wip-debug/build-x86_64-linux/gcc/xgcc -B/export/build/gnu/tools-build/gcc-wip-debug/build-x86_64-linux/gcc/ -O2 -S x5.i during GIMPLE pass: forwprop x5.i: In function ‘foo’: x5.i:8:1: internal compiler error: in elt, at vector-builder.h:202 8 | } | ^ 0xe3fb73 vector_builder<poly_int<1u, long>, int_vector_builder<poly_int<1u, long> > >::elt(unsigned int) const /export/gnu/import/git/gitlab/x86-gcc/gcc/vector-builder.h:202 0x17b5665 vec_perm_indices::new_vector(int_vector_builder<poly_int<1u, long> > const&, unsigned int, poly_int<1u, unsigned long>) /export/gnu/import/git/gitlab/x86-gcc/gcc/vec-perm-indices.c:65 0xe3f93b vec_perm_indices::vec_perm_indices(int_vector_builder<poly_int<1u, long> > const&, unsigned int, poly_int<1u, unsigned long>) /export/gnu/import/git/gitlab/x86-gcc/gcc/vec-perm-indices.h:112 0x14e5fef simplify_vector_constructor /export/gnu/import/git/gitlab/x86-gcc/gcc/tree-ssa-forwprop.c:2155 0x14e8676 execute /export/gnu/import/git/gitlab/x86-gcc/gcc/tree-ssa-forwprop.c:2693 Please submit a full bug report, with preprocessed source if appropriate. Please include the complete backtrace with any bug report. See <https://gcc.gnu.org/bugs/> for instructions. make: *** [Makefile:19: x5.s] Error 1 [hjl@gnu-cfl-1 pr88828]$ This comes from my PR 88828 tests. > + if (orig[1] > + && orig[1] != error_mark_node) > + return false; > + orig[1] = error_mark_node; > + if (!one_constant) > + one_constant = elt->value; > + constants[i] = elt->value; > + sel.quick_push (i + nelts); > + maybe_ident = false; > } > - if (j == 2) > - return false; > - > - unsigned int elt; > - if (maybe_ne (bit_field_size (op1), elem_size) > - || !constant_multiple_p (bit_field_offset (op1), elem_size, &elt)) > - return false; > - if (j) > - elt += nelts; > - if (elt != i) > - maybe_ident = false; > - sel.quick_push (elt); > } > if (i < nelts) > return false; > @@ -2138,9 +2166,29 @@ simplify_vector_constructor (gimple_stmt > op2 = vec_perm_indices_to_tree (mask_type, indices); > if (!orig[1]) > orig[1] = orig[0]; > + if (orig[1] == error_mark_node) > + { > + tree_vector_builder vec (type, nelts, 1); > + for (unsigned i = 0; i < nelts; ++i) > + if (constants[i]) > + vec.quick_push (constants[i]); > + else > + /* ??? Push a don't-care value. */ > + vec.quick_push (one_constant); > + orig[1] = vec.build (); > + } > if (conv_code == ERROR_MARK) > gimple_assign_set_rhs_with_ops (gsi, VEC_PERM_EXPR, orig[0], > orig[1], op2); > + else if (TREE_CODE (orig[1]) == VECTOR_CST) > + { > + gimple *conv > + = gimple_build_assign (make_ssa_name (type), conv_code, orig[0]); > + orig[0] = gimple_assign_lhs (conv); > + gsi_insert_before (gsi, conv, GSI_SAME_STMT); > + gimple_assign_set_rhs_with_ops (gsi, VEC_PERM_EXPR, > + orig[0], orig[1], op2); > + } > else > { > gimple *perm Here is the updated patch. -- H.J.
From 3d306956a4de03cf725448101ba5d4bd438cd441 Mon Sep 17 00:00:00 2001 From: Richard Biener <rguent...@suse.de> Date: Fri, 3 May 2019 08:22:12 -0700 Subject: [PATCH] Prep for PR88828 fix The following refactors simplify_vector_constructor and adds handling of constants to it in a straight-forward way. A followup will handle the testcases posted in HJs patch. Bootstrap / regtest running on x86_64-unknown-linux-gnu. 2019-05-03 Richard Biener <rguent...@suse.de> PR tree-optimization/88828 * tree-ssa-forwprop.c (get_bit_field_ref_def): Split out from... (simplify_vector_constructor): ...here. Handle constants in the constructor. * gcc.target/i386/pr88828-0.c: New testcase. --- gcc/testsuite/gcc.target/i386/pr88828-0.c | 27 ++++ gcc/tree-ssa-forwprop.c | 159 ++++++++++++++-------- 2 files changed, 131 insertions(+), 55 deletions(-) create mode 100644 gcc/testsuite/gcc.target/i386/pr88828-0.c diff --git a/gcc/testsuite/gcc.target/i386/pr88828-0.c b/gcc/testsuite/gcc.target/i386/pr88828-0.c new file mode 100644 index 00000000000..3ddb2d13526 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr88828-0.c @@ -0,0 +1,27 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -msse4.2" } */ + +typedef int v4si __attribute__((vector_size(16))); +typedef float v4sf __attribute__((vector_size(16))); + +v4si foo (v4si x) +{ + return (v4si){ x[0], 1, x[2], 3 }; +} + +/* { dg-final { scan-assembler "pblendw" } } */ + +v4si bar (v4sf x) +{ + return (v4si){ 1, x[1], x[2], 3 }; +} + +/* { dg-final { scan-assembler "cvttps2dq" } } */ +/* { dg-final { scan-assembler "pblendw" } } */ + +v4si baz (v4si x) +{ + return (v4si) { x[1], x[2], x[3], 0 }; +} + +/* { dg-final { scan-assembler "psrldq" } } */ diff --git a/gcc/tree-ssa-forwprop.c b/gcc/tree-ssa-forwprop.c index 1553c9e70ac..7dd1e64335a 100644 --- a/gcc/tree-ssa-forwprop.c +++ b/gcc/tree-ssa-forwprop.c @@ -1997,17 +1997,54 @@ simplify_permutation (gimple_stmt_iterator *gsi) return 0; } +/* Get the BIT_FIELD_REF definition of VAL, if any, looking through + conversions with code CONV_CODE or update it if still ERROR_MARK. + Return NULL_TREE if no such matching def was found. */ + +static tree +get_bit_field_ref_def (tree val, enum tree_code &conv_code) +{ + if (TREE_CODE (val) != SSA_NAME) + return NULL_TREE ; + gimple *def_stmt = get_prop_source_stmt (val, false, NULL); + if (!def_stmt) + return NULL_TREE; + enum tree_code code = gimple_assign_rhs_code (def_stmt); + if (code == FLOAT_EXPR + || code == FIX_TRUNC_EXPR) + { + tree op1 = gimple_assign_rhs1 (def_stmt); + if (conv_code == ERROR_MARK) + { + if (maybe_ne (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (val))), + GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (op1))))) + return NULL_TREE; + conv_code = code; + } + else if (conv_code != code) + return NULL_TREE; + if (TREE_CODE (op1) != SSA_NAME) + return NULL_TREE; + def_stmt = SSA_NAME_DEF_STMT (op1); + if (! is_gimple_assign (def_stmt)) + return NULL_TREE; + code = gimple_assign_rhs_code (def_stmt); + } + if (code != BIT_FIELD_REF) + return NULL_TREE; + return gimple_assign_rhs1 (def_stmt); +} + /* Recognize a VEC_PERM_EXPR. Returns true if there were any changes. */ static bool simplify_vector_constructor (gimple_stmt_iterator *gsi) { gimple *stmt = gsi_stmt (*gsi); - gimple *def_stmt; tree op, op2, orig[2], type, elem_type; unsigned elem_size, i; unsigned HOST_WIDE_INT nelts; - enum tree_code code, conv_code; + enum tree_code conv_code; constructor_elt *elt; bool maybe_ident; @@ -2027,6 +2064,9 @@ simplify_vector_constructor (gimple_stmt_iterator *gsi) orig[1] = NULL; conv_code = ERROR_MARK; maybe_ident = true; + tree one_constant = NULL_TREE; + auto_vec<tree> constants; + constants.safe_grow_cleared (nelts); FOR_EACH_VEC_SAFE_ELT (CONSTRUCTOR_ELTS (op), i, elt) { tree ref, op1; @@ -2034,68 +2074,57 @@ simplify_vector_constructor (gimple_stmt_iterator *gsi) if (i >= nelts) return false; - if (TREE_CODE (elt->value) != SSA_NAME) - return false; - def_stmt = get_prop_source_stmt (elt->value, false, NULL); - if (!def_stmt) - return false; - code = gimple_assign_rhs_code (def_stmt); - if (code == FLOAT_EXPR - || code == FIX_TRUNC_EXPR) + op1 = get_bit_field_ref_def (elt->value, conv_code); + if (op1) { - op1 = gimple_assign_rhs1 (def_stmt); - if (conv_code == ERROR_MARK) + ref = TREE_OPERAND (op1, 0); + unsigned int j; + for (j = 0; j < 2; ++j) { - if (maybe_ne (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (elt->value))), - GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (op1))))) - return false; - conv_code = code; + if (!orig[j]) + { + if (TREE_CODE (ref) != SSA_NAME) + return false; + if (! VECTOR_TYPE_P (TREE_TYPE (ref)) + || ! useless_type_conversion_p (TREE_TYPE (op1), + TREE_TYPE (TREE_TYPE (ref)))) + return false; + if (j && !useless_type_conversion_p (TREE_TYPE (orig[0]), + TREE_TYPE (ref))) + return false; + orig[j] = ref; + break; + } + else if (ref == orig[j]) + break; } - else if (conv_code != code) - return false; - if (TREE_CODE (op1) != SSA_NAME) + if (j == 2) return false; - def_stmt = SSA_NAME_DEF_STMT (op1); - if (! is_gimple_assign (def_stmt)) + + unsigned int elt; + if (maybe_ne (bit_field_size (op1), elem_size) + || !constant_multiple_p (bit_field_offset (op1), elem_size, &elt)) return false; - code = gimple_assign_rhs_code (def_stmt); + if (j) + elt += nelts; + if (elt != i) + maybe_ident = false; + sel.quick_push (elt); } - if (code != BIT_FIELD_REF) - return false; - op1 = gimple_assign_rhs1 (def_stmt); - ref = TREE_OPERAND (op1, 0); - unsigned int j; - for (j = 0; j < 2; ++j) + else if (CONSTANT_CLASS_P (elt->value)) { - if (!orig[j]) - { - if (TREE_CODE (ref) != SSA_NAME) - return false; - if (! VECTOR_TYPE_P (TREE_TYPE (ref)) - || ! useless_type_conversion_p (TREE_TYPE (op1), - TREE_TYPE (TREE_TYPE (ref)))) - return false; - if (j && !useless_type_conversion_p (TREE_TYPE (orig[0]), - TREE_TYPE (ref))) - return false; - orig[j] = ref; - break; - } - else if (ref == orig[j]) - break; + if (orig[1] + && orig[1] != error_mark_node) + return false; + orig[1] = error_mark_node; + if (!one_constant) + one_constant = elt->value; + constants[i] = elt->value; + sel.quick_push (i + nelts); + maybe_ident = false; } - if (j == 2) - return false; - - unsigned int elt; - if (maybe_ne (bit_field_size (op1), elem_size) - || !constant_multiple_p (bit_field_offset (op1), elem_size, &elt)) + else return false; - if (j) - elt += nelts; - if (elt != i) - maybe_ident = false; - sel.quick_push (elt); } if (i < nelts) return false; @@ -2138,9 +2167,29 @@ simplify_vector_constructor (gimple_stmt_iterator *gsi) op2 = vec_perm_indices_to_tree (mask_type, indices); if (!orig[1]) orig[1] = orig[0]; + if (orig[1] == error_mark_node) + { + tree_vector_builder vec (type, nelts, 1); + for (unsigned i = 0; i < nelts; ++i) + if (constants[i]) + vec.quick_push (constants[i]); + else + /* ??? Push a don't-care value. */ + vec.quick_push (one_constant); + orig[1] = vec.build (); + } if (conv_code == ERROR_MARK) gimple_assign_set_rhs_with_ops (gsi, VEC_PERM_EXPR, orig[0], orig[1], op2); + else if (TREE_CODE (orig[1]) == VECTOR_CST) + { + gimple *conv + = gimple_build_assign (make_ssa_name (type), conv_code, orig[0]); + orig[0] = gimple_assign_lhs (conv); + gsi_insert_before (gsi, conv, GSI_SAME_STMT); + gimple_assign_set_rhs_with_ops (gsi, VEC_PERM_EXPR, + orig[0], orig[1], op2); + } else { gimple *perm -- 2.20.1