diff options
author | jakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4> | 2015-11-27 09:01:20 +0000 |
---|---|---|
committer | jakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4> | 2015-11-27 09:01:20 +0000 |
commit | d411bc7ec319bf95d7d004aa16ac964cab5a0a61 (patch) | |
tree | 6e32a26908605a983ebe994d795e5db81468cc81 /gcc/optabs.c | |
parent | c5e4f5914dfabeca70a863a77437cd029a2ac59b (diff) | |
download | gcc-d411bc7ec319bf95d7d004aa16ac964cab5a0a61.tar.gz |
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.c | 49 |
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) { |