summaryrefslogtreecommitdiffstats
path: root/gcc/fold-const.c
diff options
context:
space:
mode:
authorglisse <glisse@138bc75d-0d04-0410-961f-82ee72b054a4>2012-08-21 13:27:00 +0000
committerglisse <glisse@138bc75d-0d04-0410-961f-82ee72b054a4>2012-08-21 13:27:00 +0000
commit496ec2adcb217bb4811e144c163807289423de50 (patch)
treeed52f070800b50c7623028376b73988cddec35ad /gcc/fold-const.c
parent78d53e33ea16afb990b4281e52baf74ce9dc0f47 (diff)
downloadppe42-gcc-496ec2adcb217bb4811e144c163807289423de50.tar.gz
ppe42-gcc-496ec2adcb217bb4811e144c163807289423de50.zip
2012-08-21 Marc Glisse <marc.glisse@inria.fr>
gcc/ * fold-const.c (fold_ternary_loc): Detect identity permutations. Canonicalize permutations more. * tree-ssa-forwprop.c (is_combined_permutation_identity): New function. (simplify_permutation): Likewise. (ssa_forward_propagate_and_combine): Call it. gcc/testsuite/ * gcc.dg/tree-ssa/forwprop-19.c: New testcase. * gcc.dg/fold-perm.c: Likewise. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@190561 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/fold-const.c')
-rw-r--r--gcc/fold-const.c46
1 files changed, 42 insertions, 4 deletions
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 3bfd203bea8..b386bb2c606 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -14155,11 +14155,17 @@ fold_ternary_loc (location_t loc, enum tree_code code, tree type,
case VEC_PERM_EXPR:
if (TREE_CODE (arg2) == VECTOR_CST)
{
- unsigned int nelts = TYPE_VECTOR_SUBPARTS (type), i;
+ unsigned int nelts = TYPE_VECTOR_SUBPARTS (type), i, mask;
unsigned char *sel = XALLOCAVEC (unsigned char, nelts);
tree t;
bool need_mask_canon = false;
+ bool all_in_vec0 = true;
+ bool all_in_vec1 = true;
+ bool maybe_identity = true;
+ bool single_arg = (op0 == op1);
+ bool changed = false;
+ mask = single_arg ? (nelts - 1) : (2 * nelts - 1);
gcc_assert (nelts == VECTOR_CST_NELTS (arg2));
for (i = 0; i < nelts; i++)
{
@@ -14167,11 +14173,27 @@ fold_ternary_loc (location_t loc, enum tree_code code, tree type,
if (TREE_CODE (val) != INTEGER_CST)
return NULL_TREE;
- sel[i] = TREE_INT_CST_LOW (val) & (2 * nelts - 1);
+ sel[i] = TREE_INT_CST_LOW (val) & mask;
if (TREE_INT_CST_HIGH (val)
|| ((unsigned HOST_WIDE_INT)
TREE_INT_CST_LOW (val) != sel[i]))
need_mask_canon = true;
+
+ if (sel[i] < nelts)
+ all_in_vec1 = false;
+ else
+ all_in_vec0 = false;
+
+ if ((sel[i] & (nelts-1)) != i)
+ maybe_identity = false;
+ }
+
+ if (maybe_identity)
+ {
+ if (all_in_vec0)
+ return op0;
+ if (all_in_vec1)
+ return op1;
}
if ((TREE_CODE (arg0) == VECTOR_CST
@@ -14184,15 +14206,31 @@ fold_ternary_loc (location_t loc, enum tree_code code, tree type,
return t;
}
+ if (all_in_vec0)
+ op1 = op0;
+ else if (all_in_vec1)
+ {
+ op0 = op1;
+ for (i = 0; i < nelts; i++)
+ sel[i] -= nelts;
+ need_mask_canon = true;
+ }
+
+ if (op0 == op1 && !single_arg)
+ changed = true;
+
if (need_mask_canon && arg2 == op2)
{
tree *tsel = XALLOCAVEC (tree, nelts);
tree eltype = TREE_TYPE (TREE_TYPE (arg2));
for (i = 0; i < nelts; i++)
tsel[i] = build_int_cst (eltype, sel[i]);
- t = build_vector (TREE_TYPE (arg2), tsel);
- return build3_loc (loc, VEC_PERM_EXPR, type, op0, op1, t);
+ op2 = build_vector (TREE_TYPE (arg2), tsel);
+ changed = true;
}
+
+ if (changed)
+ return build3_loc (loc, VEC_PERM_EXPR, type, op0, op1, op2);
}
return NULL_TREE;
OpenPOWER on IntegriCloud