Commit 22d8712a by Jakub Jelinek Committed by Jakub Jelinek

re PR tree-optimization/51074 (No constant folding performed for VEC_PERM_EXPR,…

re PR tree-optimization/51074 (No constant folding performed for VEC_PERM_EXPR, VEC_INTERLEAVE*EXPR, VEC_EXTRACT*EXPR)

	PR tree-optimization/51074
	* fold-const.c (vec_cst_ctor_to_array, fold_vec_perm): New functions.
	(fold_binary_loc): Handle VEC_EXTRACT_EVEN_EXPR,
	VEC_EXTRACT_ODD_EXPR, VEC_INTERLEAVE_HIGH_EXPR and
	VEC_INTERLEAVE_LOW_EXPR with VECTOR_CST or CONSTRUCTOR operands.
	(fold_ternary_loc): Handle VEC_PERM_EXPR with VECTOR_CST or
	CONSTRUCTOR operands.
	* tree-ssa-propagate.c (valid_gimple_rhs_p): Handle ternary
	expressions.
	* tree-vect-generic.c (lower_vec_perm): Mask sel_int elements
	to 0 .. 2 * elements - 1.

From-SVN: r181297
parent 05409788
2011-11-11 Jakub Jelinek <jakub@redhat.com>
PR tree-optimization/51074
* fold-const.c (vec_cst_ctor_to_array, fold_vec_perm): New functions.
(fold_binary_loc): Handle VEC_EXTRACT_EVEN_EXPR,
VEC_EXTRACT_ODD_EXPR, VEC_INTERLEAVE_HIGH_EXPR and
VEC_INTERLEAVE_LOW_EXPR with VECTOR_CST or CONSTRUCTOR operands.
(fold_ternary_loc): Handle VEC_PERM_EXPR with VECTOR_CST or
CONSTRUCTOR operands.
* tree-ssa-propagate.c (valid_gimple_rhs_p): Handle ternary
expressions.
* tree-vect-generic.c (lower_vec_perm): Mask sel_int elements
to 0 .. 2 * elements - 1.
2011-11-11 Richard Henderson <rth@redhat.com> 2011-11-11 Richard Henderson <rth@redhat.com>
* gimple-pretty-print.c (dump_gimple_omp_atomic_load): Dump needed. * gimple-pretty-print.c (dump_gimple_omp_atomic_load): Dump needed.
...@@ -9528,6 +9528,86 @@ get_pointer_modulus_and_residue (tree expr, unsigned HOST_WIDE_INT *residue, ...@@ -9528,6 +9528,86 @@ get_pointer_modulus_and_residue (tree expr, unsigned HOST_WIDE_INT *residue,
return 1; return 1;
} }
/* Helper function for fold_vec_perm. Store elements of VECTOR_CST or
CONSTRUCTOR ARG into array ELTS and return true if successful. */
static bool
vec_cst_ctor_to_array (tree arg, tree *elts)
{
unsigned int nelts = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg)), i;
if (TREE_CODE (arg) == VECTOR_CST)
{
tree t;
for (i = 0, t = TREE_VECTOR_CST_ELTS (arg);
i < nelts && t; i++, t = TREE_CHAIN (t))
elts[i] = TREE_VALUE (t);
if (t)
return false;
}
else if (TREE_CODE (arg) == CONSTRUCTOR)
{
constructor_elt *elt;
FOR_EACH_VEC_ELT (constructor_elt, CONSTRUCTOR_ELTS (arg), i, elt)
if (i >= nelts)
return false;
else
elts[i] = elt->value;
}
else
return false;
for (; i < nelts; i++)
elts[i]
= fold_convert (TREE_TYPE (TREE_TYPE (arg)), integer_zero_node);
return true;
}
/* Attempt to fold vector permutation of ARG0 and ARG1 vectors using SEL
selector. Return the folded VECTOR_CST or CONSTRUCTOR if successful,
NULL_TREE otherwise. */
static tree
fold_vec_perm (tree type, tree arg0, tree arg1, const unsigned char *sel)
{
unsigned int nelts = TYPE_VECTOR_SUBPARTS (type), i;
tree *elts;
bool need_ctor = false;
gcc_assert (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0)) == nelts
&& TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg1)) == nelts);
if (TREE_TYPE (TREE_TYPE (arg0)) != TREE_TYPE (type)
|| TREE_TYPE (TREE_TYPE (arg1)) != TREE_TYPE (type))
return NULL_TREE;
elts = XALLOCAVEC (tree, nelts * 3);
if (!vec_cst_ctor_to_array (arg0, elts)
|| !vec_cst_ctor_to_array (arg1, elts + nelts))
return NULL_TREE;
for (i = 0; i < nelts; i++)
{
if (!CONSTANT_CLASS_P (elts[sel[i]]))
need_ctor = true;
elts[i + 2 * nelts] = unshare_expr (elts[sel[i]]);
}
if (need_ctor)
{
VEC(constructor_elt,gc) *v = VEC_alloc (constructor_elt, gc, nelts);
for (i = 0; i < nelts; i++)
CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, elts[2 * nelts + i]);
return build_constructor (type, v);
}
else
{
tree vals = NULL_TREE;
for (i = 0; i < nelts; i++)
vals = tree_cons (NULL_TREE, elts[3 * nelts - i - 1], vals);
return build_vector (type, vals);
}
}
/* Fold a binary expression of code CODE and type TYPE with operands /* Fold a binary expression of code CODE and type TYPE with operands
OP0 and OP1. LOC is the location of the resulting expression. OP0 and OP1. LOC is the location of the resulting expression.
...@@ -13381,6 +13461,41 @@ fold_binary_loc (location_t loc, ...@@ -13381,6 +13461,41 @@ fold_binary_loc (location_t loc,
/* An ASSERT_EXPR should never be passed to fold_binary. */ /* An ASSERT_EXPR should never be passed to fold_binary. */
gcc_unreachable (); gcc_unreachable ();
case VEC_EXTRACT_EVEN_EXPR:
case VEC_EXTRACT_ODD_EXPR:
case VEC_INTERLEAVE_HIGH_EXPR:
case VEC_INTERLEAVE_LOW_EXPR:
if ((TREE_CODE (arg0) == VECTOR_CST
|| TREE_CODE (arg0) == CONSTRUCTOR)
&& (TREE_CODE (arg1) == VECTOR_CST
|| TREE_CODE (arg1) == CONSTRUCTOR))
{
unsigned int nelts = TYPE_VECTOR_SUBPARTS (type), i;
unsigned char *sel = XALLOCAVEC (unsigned char, nelts);
for (i = 0; i < nelts; i++)
switch (code)
{
case VEC_EXTRACT_EVEN_EXPR:
sel[i] = i * 2;
break;
case VEC_EXTRACT_ODD_EXPR:
sel[i] = i * 2 + 1;
break;
case VEC_INTERLEAVE_HIGH_EXPR:
sel[i] = (i + nelts) / 2 + ((i & 1) ? nelts : 0);
break;
case VEC_INTERLEAVE_LOW_EXPR:
sel[i] = i / 2 + ((i & 1) ? nelts : 0);
break;
default:
gcc_unreachable ();
}
return fold_vec_perm (type, arg0, arg1, sel);
}
return NULL_TREE;
default: default:
return NULL_TREE; return NULL_TREE;
} /* switch (code) */ } /* switch (code) */
...@@ -13767,6 +13882,55 @@ fold_ternary_loc (location_t loc, enum tree_code code, tree type, ...@@ -13767,6 +13882,55 @@ fold_ternary_loc (location_t loc, enum tree_code code, tree type,
return fold_fma (loc, type, arg0, arg1, arg2); return fold_fma (loc, type, arg0, arg1, arg2);
case VEC_PERM_EXPR:
if (TREE_CODE (arg2) == VECTOR_CST)
{
unsigned int nelts = TYPE_VECTOR_SUBPARTS (type), i;
unsigned char *sel = XALLOCAVEC (unsigned char, nelts);
tree t;
bool need_mask_canon = false;
gcc_assert (nelts == TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg2)));
for (i = 0, t = TREE_VECTOR_CST_ELTS (arg2);
i < nelts && t; i++, t = TREE_CHAIN (t))
{
if (TREE_CODE (TREE_VALUE (t)) != INTEGER_CST)
return NULL_TREE;
sel[i] = TREE_INT_CST_LOW (TREE_VALUE (t)) & (2 * nelts - 1);
if (TREE_INT_CST_HIGH (TREE_VALUE (t))
|| ((unsigned HOST_WIDE_INT)
TREE_INT_CST_LOW (TREE_VALUE (t)) != sel[i]))
need_mask_canon = true;
}
if (t)
return NULL_TREE;
for (; i < nelts; i++)
sel[i] = 0;
if ((TREE_CODE (arg0) == VECTOR_CST
|| TREE_CODE (arg0) == CONSTRUCTOR)
&& (TREE_CODE (arg1) == VECTOR_CST
|| TREE_CODE (arg1) == CONSTRUCTOR))
{
t = fold_vec_perm (type, arg0, arg1, sel);
if (t != NULL_TREE)
return t;
}
if (need_mask_canon && arg2 == op2)
{
tree list = NULL_TREE, eltype = TREE_TYPE (TREE_TYPE (arg2));
for (i = 0; i < nelts; i++)
list = tree_cons (NULL_TREE,
build_int_cst (eltype, sel[nelts - i - 1]),
list);
t = build_vector (TREE_TYPE (arg2), list);
return build3_loc (loc, VEC_PERM_EXPR, type, op0, op1, t);
}
}
return NULL_TREE;
default: default:
return NULL_TREE; return NULL_TREE;
} /* switch (code) */ } /* switch (code) */
......
...@@ -602,6 +602,16 @@ valid_gimple_rhs_p (tree expr) ...@@ -602,6 +602,16 @@ valid_gimple_rhs_p (tree expr)
break; break;
default: default:
if (get_gimple_rhs_class (code) == GIMPLE_TERNARY_RHS)
{
if (((code == VEC_COND_EXPR || code == COND_EXPR)
? !is_gimple_condexpr (TREE_OPERAND (expr, 0))
: !is_gimple_val (TREE_OPERAND (expr, 0)))
|| !is_gimple_val (TREE_OPERAND (expr, 1))
|| !is_gimple_val (TREE_OPERAND (expr, 2)))
return false;
break;
}
return false; return false;
} }
break; break;
......
...@@ -649,7 +649,7 @@ lower_vec_perm (gimple_stmt_iterator *gsi) ...@@ -649,7 +649,7 @@ lower_vec_perm (gimple_stmt_iterator *gsi)
tree vals = TREE_VECTOR_CST_ELTS (mask); tree vals = TREE_VECTOR_CST_ELTS (mask);
for (i = 0; i < elements; ++i, vals = TREE_CHAIN (vals)) for (i = 0; i < elements; ++i, vals = TREE_CHAIN (vals))
sel_int[i] = TREE_INT_CST_LOW (TREE_VALUE (vals)); sel_int[i] = TREE_INT_CST_LOW (TREE_VALUE (vals)) & (2 * elements - 1);
if (can_vec_perm_p (TYPE_MODE (vect_type), false, sel_int)) if (can_vec_perm_p (TYPE_MODE (vect_type), false, sel_int))
return; return;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment