From 9fe1940081ab64552a1e9134efda54ecef94bb50 Mon Sep 17 00:00:00 2001 From: Andreas Krebbel Date: Wed, 24 Apr 2019 13:40:38 +0000 Subject: [PATCH] S/390: Fix PR89952 incorrect CFI This patch fixes a cases where inconsistent CFI is generated. After restoring the hard frame pointer (r11) from an FPR we have to set the CFA register. In order to be able to set it back to the stack pointer (r15) we have to make sure that r15 has been restored already. The patch also adds a scheduler dependency to prevent the instruction scheduler from swapping the r11 and r15 restore again. gcc/ChangeLog: 2019-04-24 Andreas Krebbel PR target/89952 * config/s390/s390.c (s390_restore_gprs_from_fprs): Restore GPRs from FPRs in reverse order. Generate REG_CFA_DEF_CFA note also for restored hard frame pointer. (s390_sched_dependencies_evaluation): Implement new target hook. (TARGET_SCHED_DEPENDENCIES_EVALUATION_HOOK): New macro definition. gcc/testsuite/ChangeLog: 2019-04-24 Andreas Krebbel PR target/89952 * gcc.target/s390/pr89952.c: New test. From-SVN: r270544 --- gcc/ChangeLog | 9 ++++ gcc/config/s390/s390.c | 62 ++++++++++++++++++++++++- gcc/testsuite/ChangeLog | 5 ++ gcc/testsuite/gcc.target/s390/pr89952.c | 12 +++++ 4 files changed, 86 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/gcc.target/s390/pr89952.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 1c70df7ce96..6d09649c1d0 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2019-04-24 Andreas Krebbel + + PR target/89952 + * config/s390/s390.c (s390_restore_gprs_from_fprs): Restore GPRs + from FPRs in reverse order. Generate REG_CFA_DEF_CFA note also + for restored hard frame pointer. + (s390_sched_dependencies_evaluation): Implement new target hook. + (TARGET_SCHED_DEPENDENCIES_EVALUATION_HOOK): New macro definition. + 2019-04-24 Claudiu Zissulescu * config/arc/arc-options.def: Fix typos and spelling mistakes. diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c index ad8eacdf4dc..fc4571d0d0c 100644 --- a/gcc/config/s390/s390.c +++ b/gcc/config/s390/s390.c @@ -10685,7 +10685,11 @@ s390_restore_gprs_from_fprs (void) if (!TARGET_Z10 || !TARGET_HARD_FLOAT || !crtl->is_leaf) return; - for (i = 6; i < 16; i++) + /* Restore the GPRs starting with the stack pointer. That way the + stack pointer already has its original value when it comes to + restoring the hard frame pointer. So we can set the cfa reg back + to the stack pointer. */ + for (i = STACK_POINTER_REGNUM; i >= 6; i--) { rtx_insn *insn; @@ -10701,7 +10705,13 @@ s390_restore_gprs_from_fprs (void) df_set_regs_ever_live (i, true); add_reg_note (insn, REG_CFA_RESTORE, gen_rtx_REG (DImode, i)); - if (i == STACK_POINTER_REGNUM) + + /* If either the stack pointer or the frame pointer get restored + set the CFA value to its value at function start. Doing this + for the frame pointer results in .cfi_def_cfa_register 15 + what is ok since if the stack pointer got modified it has + been restored already. */ + if (i == STACK_POINTER_REGNUM || i == HARD_FRAME_POINTER_REGNUM) add_reg_note (insn, REG_CFA_DEF_CFA, plus_constant (Pmode, stack_pointer_rtx, STACK_POINTER_OFFSET)); @@ -16294,6 +16304,49 @@ s390_case_values_threshold (void) return default_case_values_threshold (); } +/* Evaluate the insns between HEAD and TAIL and do back-end to install + back-end specific dependencies. + + Establish an ANTI dependency between r11 and r15 restores from FPRs + to prevent the instructions scheduler from reordering them since + this would break CFI. No further handling in the sched_reorder + hook is required since the r11 and r15 restore will never appear in + the same ready list with that change. */ +void +s390_sched_dependencies_evaluation (rtx_insn *head, rtx_insn *tail) +{ + if (!frame_pointer_needed || !epilogue_completed) + return; + + while (head != tail && DEBUG_INSN_P (head)) + head = NEXT_INSN (head); + + rtx_insn *r15_restore = NULL, *r11_restore = NULL; + + for (rtx_insn *insn = tail; insn != head; insn = PREV_INSN (insn)) + { + rtx set = single_set (insn); + if (!INSN_P (insn) + || !RTX_FRAME_RELATED_P (insn) + || set == NULL_RTX + || !REG_P (SET_DEST (set)) + || !FP_REG_P (SET_SRC (set))) + continue; + + if (REGNO (SET_DEST (set)) == HARD_FRAME_POINTER_REGNUM) + r11_restore = insn; + + if (REGNO (SET_DEST (set)) == STACK_POINTER_REGNUM) + r15_restore = insn; + } + + if (r11_restore == NULL || r15_restore == NULL) + return; + add_dependence (r11_restore, r15_restore, REG_DEP_ANTI); +} + + + /* Initialize GCC target structure. */ #undef TARGET_ASM_ALIGNED_HI_OP @@ -16585,6 +16638,11 @@ s390_case_values_threshold (void) #undef TARGET_CASE_VALUES_THRESHOLD #define TARGET_CASE_VALUES_THRESHOLD s390_case_values_threshold +#undef TARGET_SCHED_DEPENDENCIES_EVALUATION_HOOK +#define TARGET_SCHED_DEPENDENCIES_EVALUATION_HOOK \ + s390_sched_dependencies_evaluation + + /* Use only short displacement, since long displacement is not available for the floating point instructions. */ #undef TARGET_MAX_ANCHOR_OFFSET diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 42e75166b4a..6a34f20da3a 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2019-04-24 Andreas Krebbel + + PR target/89952 + * gcc.target/s390/pr89952.c: New test. + 2019-04-24 Jakub Jelinek PR target/90187 diff --git a/gcc/testsuite/gcc.target/s390/pr89952.c b/gcc/testsuite/gcc.target/s390/pr89952.c new file mode 100644 index 00000000000..9f48e0848a0 --- /dev/null +++ b/gcc/testsuite/gcc.target/s390/pr89952.c @@ -0,0 +1,12 @@ +/* { dg-do compile } */ +/* { dg-options "-march=zEC12 -fno-omit-frame-pointer -Os" } */ + + +extern void j(int); + +void +d(int e, long f, int g, int h, int i) { + if (h == 5 && i >= 4 && i <= 7) + h = e; + j(h); +} -- 2.30.2