The current implementation re-uses the location of the selection pattern to generate a new one. This fails if the pattern resides in a read-only location. With the patch a new temporary register is allocated for that purpose.
gcc/ * optabs.c (expand_vec_perm): Allocate a temp reg for the new select pattern. --- gcc/optabs.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/gcc/optabs.c b/gcc/optabs.c index 983c8d9..8926efa 100644 --- a/gcc/optabs.c +++ b/gcc/optabs.c @@ -6784,14 +6784,18 @@ expand_vec_perm (machine_mode mode, rtx v0, rtx v1, rtx sel, rtx target) { /* Multiply each element by its byte size. */ machine_mode selmode = GET_MODE (sel); + /* We cannot re-use SEL as a temp operand since it might by in + read-only storage. */ + rtx sel_reg = gen_reg_rtx (selmode); + if (u == 2) - sel = expand_simple_binop (selmode, PLUS, sel, sel, - sel, 0, OPTAB_DIRECT); + sel_reg = expand_simple_binop (selmode, PLUS, sel, sel, + sel_reg, 0, OPTAB_DIRECT); else - sel = expand_simple_binop (selmode, ASHIFT, sel, - GEN_INT (exact_log2 (u)), - sel, 0, OPTAB_DIRECT); - gcc_assert (sel != NULL); + sel_reg = expand_simple_binop (selmode, ASHIFT, sel, + GEN_INT (exact_log2 (u)), + sel_reg, 0, OPTAB_DIRECT); + gcc_assert (sel_reg != NULL); /* Broadcast the low byte each element into each of its bytes. */ vec = rtvec_alloc (w); @@ -6803,7 +6807,7 @@ expand_vec_perm (machine_mode mode, rtx v0, rtx v1, rtx sel, rtx target) RTVEC_ELT (vec, i) = GEN_INT (this_e); } tmp = gen_rtx_CONST_VECTOR (qimode, vec); - sel = gen_lowpart (qimode, sel); + sel = gen_lowpart (qimode, sel_reg); sel = expand_vec_perm (qimode, sel, sel, tmp, NULL); gcc_assert (sel != NULL); -- 1.7.9.5