Message ID | 20151126180757.GK5675@tucnak.redhat.com |
---|---|
State | New |
Headers | show |
On November 26, 2015 7:07:57 PM GMT+01:00, Jakub Jelinek <jakub@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 <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. > >--- 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
--- 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) {