From: Richard Biener Date: Fri, 30 Sep 2016 07:06:16 +0000 (+0000) Subject: re PR tree-optimization/77399 (Poor code generation for vector casts and loads) X-Git-Tag: upstream/12.2.0~44436 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=f334c828feae86ecdcc6a8f0b35425147057539f;p=platform%2Fupstream%2Fgcc.git re PR tree-optimization/77399 (Poor code generation for vector casts and loads) 2016-09-30 Richard Biener PR tree-optimization/77399 * tree-ssa-forwprop.c (simplify_vector_constructor): Handle float <-> int conversions. * gcc.dg/tree-ssa/forwprop-35.c: New testcase. From-SVN: r240646 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 6892a5a..d0a4199 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2016-09-30 Richard Biener + + PR tree-optimization/77399 + * tree-ssa-forwprop.c (simplify_vector_constructor): Handle + float <-> int conversions. + 2016-09-30 Alan Modra * config/rs6000/rs6000.c (rs6000_opt_vars): Revert last change. diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index b5106656..7ea9961 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2016-09-30 Richard Biener + + PR tree-optimization/77399 + * gcc.dg/tree-ssa/forwprop-35.c: New testcase. + 2016-09-29 Sandra Loosemore * c-c++-common/pr27336.c: Make dependency on diff --git a/gcc/testsuite/gcc.dg/tree-ssa/forwprop-35.c b/gcc/testsuite/gcc.dg/tree-ssa/forwprop-35.c new file mode 100644 index 0000000..24a1ad9 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/forwprop-35.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-cddce1" } */ + +typedef int v4si __attribute__((vector_size(16))); +typedef float v4sf __attribute__((vector_size(16))); + +v4sf vec_cast(v4si f) +{ + return (v4sf){f[0], f[1], f[2], f[3]}; +} + +v4sf vec_cast_perm(v4si f) +{ + return (v4sf){f[1], f[1], f[2], f[3]}; +} + +/* { dg-final { scan-tree-dump-times "VEC_PERM_EXPR" 1 "cddce1" } } */ +/* { dg-final { scan-tree-dump-times "\\\(v4sf\\\) " 2 "cddce1" } } */ diff --git a/gcc/tree-ssa-forwprop.c b/gcc/tree-ssa-forwprop.c index 9cf2768..cd066ef 100644 --- a/gcc/tree-ssa-forwprop.c +++ b/gcc/tree-ssa-forwprop.c @@ -1953,7 +1953,7 @@ simplify_vector_constructor (gimple_stmt_iterator *gsi) gimple *def_stmt; tree op, op2, orig, type, elem_type; unsigned elem_size, nelts, i; - enum tree_code code; + enum tree_code code, conv_code; constructor_elt *elt; unsigned char *sel; bool maybe_ident; @@ -1970,6 +1970,7 @@ simplify_vector_constructor (gimple_stmt_iterator *gsi) sel = XALLOCAVEC (unsigned char, nelts); orig = NULL; + conv_code = ERROR_MARK; maybe_ident = true; FOR_EACH_VEC_SAFE_ELT (CONSTRUCTOR_ELTS (op), i, elt) { @@ -1984,6 +1985,26 @@ simplify_vector_constructor (gimple_stmt_iterator *gsi) if (!def_stmt) return false; code = gimple_assign_rhs_code (def_stmt); + if (code == FLOAT_EXPR + || code == FIX_TRUNC_EXPR) + { + op1 = gimple_assign_rhs1 (def_stmt); + if (conv_code == ERROR_MARK) + { + if (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (elt->value))) + != GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (op1)))) + return false; + conv_code = code; + } + else if (conv_code != code) + return false; + if (TREE_CODE (op1) != SSA_NAME) + return false; + def_stmt = SSA_NAME_DEF_STMT (op1); + if (! is_gimple_assign (def_stmt)) + return false; + code = gimple_assign_rhs_code (def_stmt); + } if (code != BIT_FIELD_REF) return false; op1 = gimple_assign_rhs1 (def_stmt); @@ -1997,7 +2018,9 @@ simplify_vector_constructor (gimple_stmt_iterator *gsi) { if (TREE_CODE (ref) != SSA_NAME) return false; - if (!useless_type_conversion_p (type, TREE_TYPE (ref))) + if (! VECTOR_TYPE_P (TREE_TYPE (ref)) + || ! useless_type_conversion_p (TREE_TYPE (op1), + TREE_TYPE (TREE_TYPE (ref)))) return false; orig = ref; } @@ -2009,8 +2032,19 @@ simplify_vector_constructor (gimple_stmt_iterator *gsi) if (i < nelts) return false; + if (! VECTOR_TYPE_P (TREE_TYPE (orig)) + || (TYPE_VECTOR_SUBPARTS (type) + != TYPE_VECTOR_SUBPARTS (TREE_TYPE (orig)))) + return false; + if (maybe_ident) - gimple_assign_set_rhs_from_tree (gsi, orig); + { + if (conv_code == ERROR_MARK) + gimple_assign_set_rhs_from_tree (gsi, orig); + else + gimple_assign_set_rhs_with_ops (gsi, conv_code, orig, + NULL_TREE, NULL_TREE); + } else { tree mask_type, *mask_elts; @@ -2028,7 +2062,18 @@ simplify_vector_constructor (gimple_stmt_iterator *gsi) for (i = 0; i < nelts; i++) mask_elts[i] = build_int_cst (TREE_TYPE (mask_type), sel[i]); op2 = build_vector (mask_type, mask_elts); - gimple_assign_set_rhs_with_ops (gsi, VEC_PERM_EXPR, orig, orig, op2); + if (conv_code == ERROR_MARK) + gimple_assign_set_rhs_with_ops (gsi, VEC_PERM_EXPR, orig, orig, op2); + else + { + gimple *perm + = gimple_build_assign (make_ssa_name (TREE_TYPE (orig)), + VEC_PERM_EXPR, orig, orig, op2); + orig = gimple_assign_lhs (perm); + gsi_insert_before (gsi, perm, GSI_SAME_STMT); + gimple_assign_set_rhs_with_ops (gsi, conv_code, orig, + NULL_TREE, NULL_TREE); + } } update_stmt (gsi_stmt (*gsi)); return true;