From 97eb24c42a5d82617e576165867dd6678b6b1262 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Thu, 31 Mar 2016 15:00:52 +0200 Subject: [PATCH] re PR rtl-optimization/70460 (Miscompilation of glibc on i686-linux starting with r234101) 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. * gcc.c-torture/execute/pr70460.c: New test. From-SVN: r234614 --- gcc/ChangeLog | 8 +++++ gcc/ira.c | 24 +++++++-------- gcc/testsuite/ChangeLog | 5 ++++ gcc/testsuite/gcc.c-torture/execute/pr70460.c | 29 +++++++++++++++++++ 4 files changed, 54 insertions(+), 12 deletions(-) create mode 100644 gcc/testsuite/gcc.c-torture/execute/pr70460.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 9edee6b17b7..64c8fcd5ca5 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2016-03-31 Jakub Jelinek + + 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 Martin Liska * passes.c (execute_one_pass): Do not call diff --git a/gcc/ira.c b/gcc/ira.c index c12318a6227..8ac153badb3 100644 --- a/gcc/ira.c +++ b/gcc/ira.c @@ -3870,7 +3870,8 @@ indirect_jump_optimize (void) FOR_EACH_BB_REVERSE_FN (bb, cfun) { rtx_insn *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); @@ -3884,19 +3885,18 @@ indirect_jump_optimize (void) if (!DF_REF_IS_ARTIFICIAL (def)) { rtx_insn *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; } } } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 7df13570e3d..aa0e17e1519 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2016-03-31 Jakub Jelinek + + PR rtl-optimization/70460 + * gcc.c-torture/execute/pr70460.c: New test. + 2016-03-31 Richard Biener PR c++/70430 diff --git a/gcc/testsuite/gcc.c-torture/execute/pr70460.c b/gcc/testsuite/gcc.c-torture/execute/pr70460.c new file mode 100644 index 00000000000..bfecea0932e --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/pr70460.c @@ -0,0 +1,29 @@ +/* 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; +} -- 2.30.2