diff options
author | glisse <glisse@138bc75d-0d04-0410-961f-82ee72b054a4> | 2012-08-21 13:27:00 +0000 |
---|---|---|
committer | glisse <glisse@138bc75d-0d04-0410-961f-82ee72b054a4> | 2012-08-21 13:27:00 +0000 |
commit | 496ec2adcb217bb4811e144c163807289423de50 (patch) | |
tree | ed52f070800b50c7623028376b73988cddec35ad /gcc/fold-const.c | |
parent | 78d53e33ea16afb990b4281e52baf74ce9dc0f47 (diff) | |
download | ppe42-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.c | 46 |
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; |