aboutsummaryrefslogtreecommitdiff
path: root/gcc/optabs.c
diff options
context:
space:
mode:
authorjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>2015-11-27 09:01:20 +0000
committerjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>2015-11-27 09:01:20 +0000
commitd411bc7ec319bf95d7d004aa16ac964cab5a0a61 (patch)
tree6e32a26908605a983ebe994d795e5db81468cc81 /gcc/optabs.c
parentc5e4f5914dfabeca70a863a77437cd029a2ac59b (diff)
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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@231000 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/optabs.c')
-rw-r--r--gcc/optabs.c49
1 files changed, 38 insertions, 11 deletions
diff --git a/gcc/optabs.c b/gcc/optabs.c
index 40ef5829150..550764293b9 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)
{