The following patch fixes https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80818
The patch was successfully tested and bootstrapped on x86_64. The patch has no test because it is hard to check the problem. I checked manually that the patch solves the problem on a test provided by Andreas Krebbel.
Committed as rev. 255258.
Index: ChangeLog =================================================================== --- ChangeLog (revision 255255) +++ ChangeLog (working copy) @@ -1,3 +1,15 @@ +2017-11-29 Vladimir Makarov <vmaka...@redhat.com> + + PR rtl-optimization/80818 + * lra.c (collect_non_operand_hard_regs): New arg insn. Pass it + recursively. Use insn code for clobber. + (lra_set_insn_recog_data): Pass the new arg to + collect_non_operand_hard_regs. + (add_regs_to_insn_regno_info): Pass insn instead of uid. Use insn + code for clobber. + (lra_update_insn_regno_info): Pass insn to + add_regs_to_insn_regno_info. + 2017-11-29 Julia Koval <julia.ko...@intel.com> * config/i386/avx512vbmi2intrin.h (_mm512_shldv_epi16, Index: lra.c =================================================================== --- lra.c (revision 255256) +++ lra.c (working copy) @@ -807,7 +807,8 @@ setup_operand_alternative (lra_insn_reco to LIST. X is a part of insn given by DATA. Return the result list. */ static struct lra_insn_reg * -collect_non_operand_hard_regs (rtx *x, lra_insn_recog_data_t data, +collect_non_operand_hard_regs (rtx_insn *insn, rtx *x, + lra_insn_recog_data_t data, struct lra_insn_reg *list, enum op_type type, bool early_clobber) { @@ -881,25 +882,28 @@ collect_non_operand_hard_regs (rtx *x, l switch (code) { case SET: - list = collect_non_operand_hard_regs (&SET_DEST (op), data, + list = collect_non_operand_hard_regs (insn, &SET_DEST (op), data, list, OP_OUT, false); - list = collect_non_operand_hard_regs (&SET_SRC (op), data, + list = collect_non_operand_hard_regs (insn, &SET_SRC (op), data, list, OP_IN, false); break; case CLOBBER: - /* We treat clobber of non-operand hard registers as early - clobber (the behavior is expected from asm). */ - list = collect_non_operand_hard_regs (&XEXP (op, 0), data, - list, OP_OUT, true); - break; + { + int code = INSN_CODE (insn); + /* We treat clobber of non-operand hard registers as early + clobber (the behavior is expected from asm). */ + list = collect_non_operand_hard_regs (insn, &XEXP (op, 0), data, + list, OP_OUT, code < 0); + break; + } case PRE_INC: case PRE_DEC: case POST_INC: case POST_DEC: - list = collect_non_operand_hard_regs (&XEXP (op, 0), data, + list = collect_non_operand_hard_regs (insn, &XEXP (op, 0), data, list, OP_INOUT, false); break; case PRE_MODIFY: case POST_MODIFY: - list = collect_non_operand_hard_regs (&XEXP (op, 0), data, + list = collect_non_operand_hard_regs (insn, &XEXP (op, 0), data, list, OP_INOUT, false); - list = collect_non_operand_hard_regs (&XEXP (op, 1), data, + list = collect_non_operand_hard_regs (insn, &XEXP (op, 1), data, list, OP_IN, false); break; default: @@ -907,12 +911,12 @@ collect_non_operand_hard_regs (rtx *x, l for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) { if (fmt[i] == 'e') - list = collect_non_operand_hard_regs (&XEXP (op, i), data, + list = collect_non_operand_hard_regs (insn, &XEXP (op, i), data, list, OP_IN, false); else if (fmt[i] == 'E') for (j = XVECLEN (op, i) - 1; j >= 0; j--) - list = collect_non_operand_hard_regs (&XVECEXP (op, i, j), data, - list, OP_IN, false); + list = collect_non_operand_hard_regs (insn, &XVECEXP (op, i, j), + data, list, OP_IN, false); } } return list; @@ -1055,7 +1059,7 @@ lra_set_insn_recog_data (rtx_insn *insn) insn_static_data->hard_regs = NULL; else insn_static_data->hard_regs - = collect_non_operand_hard_regs (&PATTERN (insn), data, + = collect_non_operand_hard_regs (insn, &PATTERN (insn), data, NULL, OP_IN, false); data->arg_hard_regs = NULL; if (CALL_P (insn)) @@ -1402,13 +1406,14 @@ lra_get_copy (int n) /* This page contains code dealing with info about registers in insns. */ -/* Process X of insn UID recursively and add info (operand type is +/* Process X of INSN recursively and add info (operand type is given by TYPE, flag of that it is early clobber is EARLY_CLOBBER) about registers in X to the insn DATA. If X can be early clobbered, alternatives in which it can be early clobbered are given by EARLY_CLOBBER_ALTS. */ static void -add_regs_to_insn_regno_info (lra_insn_recog_data_t data, rtx x, int uid, +add_regs_to_insn_regno_info (lra_insn_recog_data_t data, rtx x, + rtx_insn *insn, enum op_type type, bool early_clobber, alternative_mask early_clobber_alts) { @@ -1436,7 +1441,7 @@ add_regs_to_insn_regno_info (lra_insn_re /* Process all regs even unallocatable ones as we need info about all regs for rematerialization pass. */ expand_reg_info (); - if (bitmap_set_bit (&lra_reg_info[regno].insn_bitmap, uid)) + if (bitmap_set_bit (&lra_reg_info[regno].insn_bitmap, INSN_UID (insn))) { data->regs = new_insn_reg (data->insn, regno, type, mode, subreg_p, early_clobber, early_clobber_alts, @@ -1471,20 +1476,25 @@ add_regs_to_insn_regno_info (lra_insn_re switch (code) { case SET: - add_regs_to_insn_regno_info (data, SET_DEST (x), uid, OP_OUT, false, 0); - add_regs_to_insn_regno_info (data, SET_SRC (x), uid, OP_IN, false, 0); + add_regs_to_insn_regno_info (data, SET_DEST (x), insn, OP_OUT, false, 0); + add_regs_to_insn_regno_info (data, SET_SRC (x), insn, OP_IN, false, 0); break; case CLOBBER: - /* We treat clobber of non-operand hard registers as early - clobber (the behavior is expected from asm). */ - add_regs_to_insn_regno_info (data, XEXP (x, 0), uid, OP_OUT, true, ALL_ALTERNATIVES); - break; + { + int code = INSN_CODE (insn); + + /* We treat clobber of non-operand hard registers as early + clobber (the behavior is expected from asm). */ + add_regs_to_insn_regno_info (data, XEXP (x, 0), insn, OP_OUT, + code < 0, code < 0 ? ALL_ALTERNATIVES : 0); + break; + } case PRE_INC: case PRE_DEC: case POST_INC: case POST_DEC: - add_regs_to_insn_regno_info (data, XEXP (x, 0), uid, OP_INOUT, false, 0); + add_regs_to_insn_regno_info (data, XEXP (x, 0), insn, OP_INOUT, false, 0); break; case PRE_MODIFY: case POST_MODIFY: - add_regs_to_insn_regno_info (data, XEXP (x, 0), uid, OP_INOUT, false, 0); - add_regs_to_insn_regno_info (data, XEXP (x, 1), uid, OP_IN, false, 0); + add_regs_to_insn_regno_info (data, XEXP (x, 0), insn, OP_INOUT, false, 0); + add_regs_to_insn_regno_info (data, XEXP (x, 1), insn, OP_IN, false, 0); break; default: if ((code != PARALLEL && code != EXPR_LIST) || type != OP_OUT) @@ -1505,11 +1515,11 @@ add_regs_to_insn_regno_info (lra_insn_re for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) { if (fmt[i] == 'e') - add_regs_to_insn_regno_info (data, XEXP (x, i), uid, type, false, 0); + add_regs_to_insn_regno_info (data, XEXP (x, i), insn, type, false, 0); else if (fmt[i] == 'E') { for (j = XVECLEN (x, i) - 1; j >= 0; j--) - add_regs_to_insn_regno_info (data, XVECEXP (x, i, j), uid, + add_regs_to_insn_regno_info (data, XVECEXP (x, i, j), insn, type, false, 0); } } @@ -1585,7 +1595,7 @@ setup_insn_reg_info (lra_insn_recog_data void lra_update_insn_regno_info (rtx_insn *insn) { - int i, uid, freq; + int i, freq; lra_insn_recog_data_t data; struct lra_static_insn_data *static_data; enum rtx_code code; @@ -1597,14 +1607,13 @@ lra_update_insn_regno_info (rtx_insn *in static_data = data->insn_static_data; freq = get_insn_freq (insn); invalidate_insn_data_regno_info (data, insn, freq); - uid = INSN_UID (insn); for (i = static_data->n_operands - 1; i >= 0; i--) - add_regs_to_insn_regno_info (data, *data->operand_loc[i], uid, + add_regs_to_insn_regno_info (data, *data->operand_loc[i], insn, static_data->operand[i].type, static_data->operand[i].early_clobber, static_data->operand[i].early_clobber_alts); if ((code = GET_CODE (PATTERN (insn))) == CLOBBER || code == USE) - add_regs_to_insn_regno_info (data, XEXP (PATTERN (insn), 0), uid, + add_regs_to_insn_regno_info (data, XEXP (PATTERN (insn), 0), insn, code == USE ? OP_IN : OP_OUT, false, 0); if (CALL_P (insn)) /* On some targets call insns can refer to pseudos in memory in @@ -1616,7 +1625,7 @@ lra_update_insn_regno_info (rtx_insn *in link = XEXP (link, 1)) if (((code = GET_CODE (XEXP (link, 0))) == USE || code == CLOBBER) && MEM_P (XEXP (XEXP (link, 0), 0))) - add_regs_to_insn_regno_info (data, XEXP (XEXP (link, 0), 0), uid, + add_regs_to_insn_regno_info (data, XEXP (XEXP (link, 0), 0), insn, code == USE ? OP_IN : OP_OUT, false, 0); if (NONDEBUG_INSN_P (insn)) setup_insn_reg_info (data, freq);