On November 26, 2015 7:07:57 PM GMT+01:00, Jakub Jelinek <ja...@redhat.com> wrote: >Hi! > >My recent tree-vect-generic.c changes broke Alpha. My changes assume >that if there is vec_shr_optab, middle argument 0 vector and last >argument >shift-ish selector, then expand_vec_perm will always handle it, but it >turns >out it does not, because expand_vec_perm does not call >expand_vec_perm_1 >at all if the target does not have vec_perm_{const_,}optab for the >particular mode (Alpha has none). Looking at the code, there is also >another potential issue, if we happen not to optimize __builtin_shuffle >(zero_vector, zero_vector, shiftish_selector) into zero_vector, >we might again not be able to expand it. > >Thus, the following patch moves the vec_shr_optab expansion from >expand_vec_perm_1 (where it is attempted unnecessarily many times >anyway, >once for the mode and again for qimode with constant sel, once again >for the >mode and again for qimode if that failed and trying to use variable >permutation. > >Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk/5 >(if it >passes in Uros' testing)?
OK. Thanks, Richard. >2015-11-26 Jakub Jelinek <ja...@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. > >--- gcc/optabs.c.jj 2015-11-24 11:44:34.000000000 +0100 >+++ gcc/optabs.c 2015-11-26 16:48:05.565855431 +0100 >@@ -5274,17 +5274,6 @@ expand_vec_perm_1 (enum insn_code icode, > 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 > 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) > { > > Jakub