diff options
author | Richard Biener <rguenther@suse.de> | 2019-05-21 12:01:00 +0000 |
---|---|---|
committer | Richard Biener <rguenth@gcc.gnu.org> | 2019-05-21 12:01:00 +0000 |
commit | 4f8b89f092467f9550cb2aa873c2e30ac809c08a (patch) | |
tree | d44631d84c87d1c813dd1788c15ca29337dbdf91 /gcc/match.pd | |
parent | 3b0657dce501046ebe11b7ba30653a41221f4797 (diff) | |
download | gcc-4f8b89f092467f9550cb2aa873c2e30ac809c08a.zip gcc-4f8b89f092467f9550cb2aa873c2e30ac809c08a.tar.gz gcc-4f8b89f092467f9550cb2aa873c2e30ac809c08a.tar.bz2 |
re PR tree-optimization/90510 (Unnecessary permutation)
2019-05-21 Richard Biener <rguenther@suse.de>
PR middle-end/90510
* fold-const.c (fold_read_from_vector): New function.
* fold-const.h (fold_read_from_vector): Declare.
* match.pd (VEC_PERM_EXPR): Build BIT_INSERT_EXPRs for
single-element insert permutations. Canonicalize selector
further and fix issue with last commit.
* gcc.target/i386/pr90510.c: New testcase.
From-SVN: r271463
Diffstat (limited to 'gcc/match.pd')
-rw-r--r-- | gcc/match.pd | 56 |
1 files changed, 50 insertions, 6 deletions
diff --git a/gcc/match.pd b/gcc/match.pd index 9ff5212..f9bc097 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -5406,6 +5406,11 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) op0 = op1; sel.rotate_inputs (1); } + else if (known_ge (poly_uint64 (sel[0]), nelts)) + { + std::swap (op0, op1); + sel.rotate_inputs (1); + } } gassign *def; tree cop0 = op0, cop1 = op1; @@ -5429,9 +5434,46 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (with { bool changed = (op0 == op1 && !single_arg); + tree ins = NULL_TREE; + unsigned at = 0; + + /* See if the permutation is performing a single element + insert from a CONSTRUCTOR or constant and use a BIT_INSERT_EXPR + in that case. But only if the vector mode is supported, + otherwise this is invalid GIMPLE. */ + if (TYPE_MODE (type) != BLKmode + && (TREE_CODE (cop0) == VECTOR_CST + || TREE_CODE (cop0) == CONSTRUCTOR + || TREE_CODE (cop1) == VECTOR_CST + || TREE_CODE (cop1) == CONSTRUCTOR)) + { + if (sel.series_p (1, 1, nelts + 1, 1)) + { + /* After canonicalizing the first elt to come from the + first vector we only can insert the first elt from + the first vector. */ + at = 0; + ins = fold_read_from_vector (cop0, 0); + op0 = op1; + } + else + { + unsigned int encoded_nelts = sel.encoding ().encoded_nelts (); + for (at = 0; at < encoded_nelts; ++at) + if (maybe_ne (sel[at], at)) + break; + if (at < encoded_nelts && sel.series_p (at + 1, 1, at + 1, 1)) + { + if (known_lt (at, nelts)) + ins = fold_read_from_vector (cop0, sel[at]); + else + ins = fold_read_from_vector (cop1, sel[at] - nelts); + } + } + } /* Generate a canonical form of the selector. */ - if (sel.encoding () != builder) + if (!ins && sel.encoding () != builder) { /* Some targets are deficient and fail to expand a single argument permutation while still allowing an equivalent @@ -5450,10 +5492,12 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) so use the preferred form. */ op2 = vec_perm_indices_to_tree (TREE_TYPE (op2), sel); } - /* Differences in the encoder do not necessarily mean - differences in the resulting vector. */ - changed = !operand_equal_p (op2, oldop2, 0); + if (!operand_equal_p (op2, oldop2, 0)) + changed = true; } } - (if (changed) - (vec_perm { op0; } { op1; } { op2; }))))))))) + (if (ins) + (bit_insert { op0; } { ins; } + { bitsize_int (at * tree_to_uhwi (TYPE_SIZE (TREE_TYPE (type)))); }) + (if (changed) + (vec_perm { op0; } { op1; } { op2; })))))))))) |