aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog7
-rw-r--r--gcc/optabs.c49
2 files changed, 45 insertions, 11 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 1a04191..d70eddb 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,10 @@
+2015-11-27 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/68552
+ * optabs.c (expand_vec_perm_1): Move vec_shr handling from here...
+ (expand_vec_perm): ... here. Do it regardless of vec_perm_const_optab
+ or whether v0 == v1.
+
2015-11-27 Martin Liska <mliska@suse.cz>
* tree-ssa-uninit.c: Fix whitespaces in the source file.
diff --git a/gcc/optabs.c b/gcc/optabs.c
index 40ef582..5507642 100644
--- a/gcc/optabs.c
+++ b/gcc/optabs.c
@@ -5274,17 +5274,6 @@ expand_vec_perm_1 (enum insn_code icode, rtx target,
else
{
create_input_operand (&ops[1], v0, tmode);
- /* See if this can be handled with a vec_shr. We only do this if the
- second vector is all zeroes. */
- enum insn_code shift_code = optab_handler (vec_shr_optab, GET_MODE (v0));
- if (v1 == CONST0_RTX (GET_MODE (v1)) && shift_code)
- if (rtx shift_amt = shift_amt_for_vec_perm_mask (sel))
- {
- create_convert_operand_from_type (&ops[2], shift_amt,
- sizetype_tab[(int) stk_sizetype]);
- if (maybe_expand_insn (shift_code, 3, ops))
- return ops[0].value;
- }
create_input_operand (&ops[2], v1, tmode);
}
@@ -5326,6 +5315,44 @@ expand_vec_perm (machine_mode mode, rtx v0, rtx v1, rtx sel, rtx target)
gcc_assert (GET_MODE_CLASS (GET_MODE (sel)) == MODE_VECTOR_INT);
if (GET_CODE (sel) == CONST_VECTOR)
{
+ /* See if this can be handled with a vec_shr. We only do this if the
+ second vector is all zeroes. */
+ enum insn_code shift_code = optab_handler (vec_shr_optab, mode);
+ enum insn_code shift_code_qi = ((qimode != VOIDmode && qimode != mode)
+ ? optab_handler (vec_shr_optab, qimode)
+ : CODE_FOR_nothing);
+ rtx shift_amt = NULL_RTX;
+ if (v1 == CONST0_RTX (GET_MODE (v1))
+ && (shift_code != CODE_FOR_nothing
+ || shift_code_qi != CODE_FOR_nothing))
+ {
+ shift_amt = shift_amt_for_vec_perm_mask (sel);
+ if (shift_amt)
+ {
+ struct expand_operand ops[3];
+ if (shift_code != CODE_FOR_nothing)
+ {
+ create_output_operand (&ops[0], target, mode);
+ create_input_operand (&ops[1], v0, mode);
+ create_convert_operand_from_type (&ops[2], shift_amt,
+ sizetype);
+ if (maybe_expand_insn (shift_code, 3, ops))
+ return ops[0].value;
+ }
+ if (shift_code_qi != CODE_FOR_nothing)
+ {
+ tmp = gen_reg_rtx (qimode);
+ create_output_operand (&ops[0], tmp, qimode);
+ create_input_operand (&ops[1], gen_lowpart (qimode, v0),
+ qimode);
+ create_convert_operand_from_type (&ops[2], shift_amt,
+ sizetype);
+ if (maybe_expand_insn (shift_code_qi, 3, ops))
+ return gen_lowpart (mode, ops[0].value);
+ }
+ }
+ }
+
icode = direct_optab_handler (vec_perm_const_optab, mode);
if (icode != CODE_FOR_nothing)
{