summaryrefslogtreecommitdiff
path: root/gcc/match.pd
diff options
context:
space:
mode:
authorRichard Biener <rguenther@suse.de>2019-05-21 12:01:00 +0000
committerRichard Biener <rguenth@gcc.gnu.org>2019-05-21 12:01:00 +0000
commit4f8b89f092467f9550cb2aa873c2e30ac809c08a (patch)
treed44631d84c87d1c813dd1788c15ca29337dbdf91 /gcc/match.pd
parent3b0657dce501046ebe11b7ba30653a41221f4797 (diff)
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.pd56
1 files changed, 50 insertions, 6 deletions
diff --git a/gcc/match.pd b/gcc/match.pd
index 9ff52123cd9..f9bc097c491 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; }))))))))))