+2016-03-31 Jakub Jelinek <jakub@redhat.com>
+
+ PR rtl-optimization/70460
+ * ira.c (indirect_jump_optimize): Don't substitute LABEL_REF
+ with operand from REG_LABEL_OPERAND, instead substitute
+ SET_SRC or REG_EQUAL note content if it is a LABEL_REF.
+ Don't do anything for REG_NON_LOCAL_GOTO jumps.
+
2016-03-31 Alan Modra <amodra@gmail.com>
Backport from mainline
FOR_EACH_BB_REVERSE_FN (bb, cfun)
{
rtx insn = BB_END (bb);
- if (!JUMP_P (insn))
+ if (!JUMP_P (insn)
+ || find_reg_note (insn, REG_NON_LOCAL_GOTO, NULL_RTX))
continue;
rtx x = pc_set (insn);
if (!DF_REF_IS_ARTIFICIAL (def))
{
rtx def_insn = DF_REF_INSN (def);
- rtx note = find_reg_note (def_insn, REG_LABEL_OPERAND, NULL_RTX);
-
- if (note)
+ rtx lab = NULL_RTX;
+ rtx set = single_set (def_insn);
+ if (set && GET_CODE (SET_SRC (set)) == LABEL_REF)
+ lab = SET_SRC (set);
+ else
{
- /* Substitute a LABEL_REF to the label given by the
- note rather than using SET_SRC of DEF_INSN.
- DEF_INSN might be loading the label constant from
- a constant pool, which isn't what we want in a
- direct branch. */
- rtx lab = gen_rtx_LABEL_REF (Pmode, XEXP (note, 0));
- if (validate_replace_rtx (SET_SRC (x), lab, insn))
- rebuild_p = true;
+ rtx eqnote = find_reg_note (def_insn, REG_EQUAL, NULL_RTX);
+ if (eqnote && GET_CODE (XEXP (eqnote, 0)) == LABEL_REF)
+ lab = XEXP (eqnote, 0);
}
+ if (lab && validate_replace_rtx (SET_SRC (x), lab, insn))
+ rebuild_p = true;
}
}
}
--- /dev/null
+/* PR rtl-optimization/70460 */
+
+int c;
+
+__attribute__((noinline, noclone)) void
+foo (int x)
+{
+ static int b[] = { &&lab1 - &&lab0, &&lab2 - &&lab0 };
+ void *a = &&lab0 + b[x];
+ goto *a;
+lab1:
+ c += 2;
+lab2:
+ c++;
+lab0:
+ ;
+}
+
+int
+main ()
+{
+ foo (0);
+ if (c != 3)
+ __builtin_abort ();
+ foo (1);
+ if (c != 4)
+ __builtin_abort ();
+ return 0;
+}