aboutsummaryrefslogtreecommitdiff
path: root/gcc/optabs.c
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2015-11-27 10:01:20 +0100
committerJakub Jelinek <jakub@gcc.gnu.org>2015-11-27 10:01:20 +0100
commit4d95edca1212e23855e4f613b588cbc6dac89999 (patch)
tree6e32a26908605a983ebe994d795e5db81468cc81 /gcc/optabs.c
parentaec17bfe911ec61571db80eb5b0093a5b19e39e4 (diff)
downloadgcc-4d95edca1212e23855e4f613b588cbc6dac89999.zip
gcc-4d95edca1212e23855e4f613b588cbc6dac89999.tar.gz
gcc-4d95edca1212e23855e4f613b588cbc6dac89999.tar.bz2
re PR tree-optimization/68552 (ICE in in expand_expr_real_2 with -O2 -ftree-vectorize)
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. From-SVN: r231000
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 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)
{