From 340e0dd66466091ea2bbd160592c017eb67dc47d Mon Sep 17 00:00:00 2001 From: Ilya Leoshkevich Date: Fri, 9 Nov 2018 20:33:19 +0000 Subject: [PATCH] S/390: Allow relative addressing of literal pool entries r265490 allowed the compiler to choose in a more flexible way whether to use load or load-address-relative-long (LARL) instruction. When it chose LARL for literal pool references, the latter ones were rewritten by pass_s390_early_mach to use UNSPEC_LTREF, which assumes base register usage, which in turn is not compatible with LARL. The end result was an ICE because of unrecognizable insn. UNSPEC_LTREF and friends are necessary in order to communicate the dependency on the base register to pass_sched2. When relative addressing is used, no base register is necessary, so in such cases the rewrite must be avoided. gcc/ChangeLog: 2018-11-09 Ilya Leoshkevich PR target/87762 * config/s390/s390.c (s390_safe_relative_long_p): New function. (annotate_constant_pool_refs): Skip insns which support relative addressing. (annotate_constant_pool_refs_1): New helper function. (find_constant_pool_ref): Skip insns which support relative addression. (find_constant_pool_ref_1): New helper function. (replace_constant_pool_ref): Skip insns which support relative addressing. (replace_constant_pool_ref_1): New helper function. (s390_mainpool_start): Adapt to the new signature. (s390_mainpool_finish): Likewise. (s390_chunkify_start): Likewise. (s390_chunkify_finish): Likewise. (pass_s390_early_mach::execute): Likewise. (s390_prologue_plus_offset): Likewise. (s390_emit_prologue): Likewise. (s390_emit_epilogue): Likewise. From-SVN: r265991 --- gcc/ChangeLog | 22 ++++++++ gcc/config/s390/s390.c | 115 ++++++++++++++++++++++++++++------------- 2 files changed, 102 insertions(+), 35 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 45629bbfc77..6d1b40d1e94 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,25 @@ +2018-11-09 Ilya Leoshkevich + + PR target/87762 + * config/s390/s390.c (s390_safe_relative_long_p): New function. + (annotate_constant_pool_refs): Skip insns which support + relative addressing. + (annotate_constant_pool_refs_1): New helper function. + (find_constant_pool_ref): Skip insns which support relative + addression. + (find_constant_pool_ref_1): New helper function. + (replace_constant_pool_ref): Skip insns which support + relative addressing. + (replace_constant_pool_ref_1): New helper function. + (s390_mainpool_start): Adapt to the new signature. + (s390_mainpool_finish): Likewise. + (s390_chunkify_start): Likewise. + (s390_chunkify_finish): Likewise. + (pass_s390_early_mach::execute): Likewise. + (s390_prologue_plus_offset): Likewise. + (s390_emit_prologue): Likewise. + (s390_emit_epilogue): Likewise. + 2018-11-09 Jakub Jelinek * gimplify.c (gimplify_scan_omp_clauses): Call sorry_at for valid diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c index 0f33101d779..ab06ada0a16 100644 --- a/gcc/config/s390/s390.c +++ b/gcc/config/s390/s390.c @@ -2731,6 +2731,17 @@ s390_safe_attr_type (rtx_insn *insn) return TYPE_NONE; } +/* Return attribute relative_long of insn. */ + +static bool +s390_safe_relative_long_p (rtx_insn *insn) +{ + if (recog_memoized (insn) >= 0) + return get_attr_relative_long (insn) == RELATIVE_LONG_YES; + else + return false; +} + /* Return true if DISP is a valid short displacement. */ static bool @@ -8102,11 +8113,8 @@ s390_first_cycle_multipass_dfa_lookahead (void) return 4; } -/* Annotate every literal pool reference in X by an UNSPEC_LTREF expression. - Fix up MEMs as required. */ - static void -annotate_constant_pool_refs (rtx *x) +annotate_constant_pool_refs_1 (rtx *x) { int i, j; const char *fmt; @@ -8185,26 +8193,31 @@ annotate_constant_pool_refs (rtx *x) { if (fmt[i] == 'e') { - annotate_constant_pool_refs (&XEXP (*x, i)); + annotate_constant_pool_refs_1 (&XEXP (*x, i)); } else if (fmt[i] == 'E') { for (j = 0; j < XVECLEN (*x, i); j++) - annotate_constant_pool_refs (&XVECEXP (*x, i, j)); + annotate_constant_pool_refs_1 (&XVECEXP (*x, i, j)); } } } -/* Find an annotated literal pool symbol referenced in RTX X, - and store it at REF. Will abort if X contains references to - more than one such pool symbol; multiple references to the same - symbol are allowed, however. +/* Annotate every literal pool reference in INSN by an UNSPEC_LTREF expression. + Fix up MEMs as required. + Skip insns which support relative addressing, because they do not use a base + register. */ - The rtx pointed to by REF must be initialized to NULL_RTX - by the caller before calling this routine. */ +static void +annotate_constant_pool_refs (rtx_insn *insn) +{ + if (s390_safe_relative_long_p (insn)) + return; + annotate_constant_pool_refs_1 (&PATTERN (insn)); +} static void -find_constant_pool_ref (rtx x, rtx *ref) +find_constant_pool_ref_1 (rtx x, rtx *ref) { int i, j; const char *fmt; @@ -8236,21 +8249,37 @@ find_constant_pool_ref (rtx x, rtx *ref) { if (fmt[i] == 'e') { - find_constant_pool_ref (XEXP (x, i), ref); + find_constant_pool_ref_1 (XEXP (x, i), ref); } else if (fmt[i] == 'E') { for (j = 0; j < XVECLEN (x, i); j++) - find_constant_pool_ref (XVECEXP (x, i, j), ref); + find_constant_pool_ref_1 (XVECEXP (x, i, j), ref); } } } -/* Replace every reference to the annotated literal pool - symbol REF in X by its base plus OFFSET. */ +/* Find an annotated literal pool symbol referenced in INSN, + and store it at REF. Will abort if INSN contains references to + more than one such pool symbol; multiple references to the same + symbol are allowed, however. + + The rtx pointed to by REF must be initialized to NULL_RTX + by the caller before calling this routine. + + Skip insns which support relative addressing, because they do not use a base + register. */ + +static void +find_constant_pool_ref (rtx_insn *insn, rtx *ref) +{ + if (s390_safe_relative_long_p (insn)) + return; + find_constant_pool_ref_1 (PATTERN (insn), ref); +} static void -replace_constant_pool_ref (rtx *x, rtx ref, rtx offset) +replace_constant_pool_ref_1 (rtx *x, rtx ref, rtx offset) { int i, j; const char *fmt; @@ -8281,16 +8310,29 @@ replace_constant_pool_ref (rtx *x, rtx ref, rtx offset) { if (fmt[i] == 'e') { - replace_constant_pool_ref (&XEXP (*x, i), ref, offset); + replace_constant_pool_ref_1 (&XEXP (*x, i), ref, offset); } else if (fmt[i] == 'E') { for (j = 0; j < XVECLEN (*x, i); j++) - replace_constant_pool_ref (&XVECEXP (*x, i, j), ref, offset); + replace_constant_pool_ref_1 (&XVECEXP (*x, i, j), ref, offset); } } } +/* Replace every reference to the annotated literal pool + symbol REF in INSN by its base plus OFFSET. + Skip insns which support relative addressing, because they do not use a base + register. */ + +static void +replace_constant_pool_ref (rtx_insn *insn, rtx ref, rtx offset) +{ + if (s390_safe_relative_long_p (insn)) + return; + replace_constant_pool_ref_1 (&PATTERN (insn), ref, offset); +} + /* We keep a list of constants which we have to add to internal constant tables in the middle of large functions. */ @@ -8691,7 +8733,7 @@ s390_mainpool_start (void) if (NONJUMP_INSN_P (insn) || CALL_P (insn)) { rtx pool_ref = NULL_RTX; - find_constant_pool_ref (PATTERN (insn), &pool_ref); + find_constant_pool_ref (insn, &pool_ref); if (pool_ref) { rtx constant = get_pool_constant (pool_ref); @@ -8778,7 +8820,7 @@ s390_mainpool_finish (struct constant_pool *pool) if (NONJUMP_INSN_P (insn) || CALL_P (insn)) { rtx addr, pool_ref = NULL_RTX; - find_constant_pool_ref (PATTERN (insn), &pool_ref); + find_constant_pool_ref (insn, &pool_ref); if (pool_ref) { if (s390_execute_label (insn)) @@ -8787,7 +8829,7 @@ s390_mainpool_finish (struct constant_pool *pool) addr = s390_find_constant (pool, get_pool_constant (pool_ref), get_pool_mode (pool_ref)); - replace_constant_pool_ref (&PATTERN (insn), pool_ref, addr); + replace_constant_pool_ref (insn, pool_ref, addr); INSN_CODE (insn) = -1; } } @@ -8821,7 +8863,7 @@ s390_chunkify_start (void) if (NONJUMP_INSN_P (insn) || CALL_P (insn)) { rtx pool_ref = NULL_RTX; - find_constant_pool_ref (PATTERN (insn), &pool_ref); + find_constant_pool_ref (insn, &pool_ref); if (pool_ref) { rtx constant = get_pool_constant (pool_ref); @@ -8978,7 +9020,7 @@ s390_chunkify_finish (struct constant_pool *pool_list) if (NONJUMP_INSN_P (insn) || CALL_P (insn)) { rtx addr, pool_ref = NULL_RTX; - find_constant_pool_ref (PATTERN (insn), &pool_ref); + find_constant_pool_ref (insn, &pool_ref); if (pool_ref) { if (s390_execute_label (insn)) @@ -8988,7 +9030,7 @@ s390_chunkify_finish (struct constant_pool *pool_list) get_pool_constant (pool_ref), get_pool_mode (pool_ref)); - replace_constant_pool_ref (&PATTERN (insn), pool_ref, addr); + replace_constant_pool_ref (insn, pool_ref, addr); INSN_CODE (insn) = -1; } } @@ -10581,7 +10623,7 @@ pass_s390_early_mach::execute (function *fun) for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) if (INSN_P (insn)) { - annotate_constant_pool_refs (&PATTERN (insn)); + annotate_constant_pool_refs (insn); df_insn_rescan (insn); } return 0; @@ -10602,7 +10644,7 @@ make_pass_s390_early_mach (gcc::context *ctxt) static rtx s390_prologue_plus_offset (rtx target, rtx reg, rtx offset, bool frame_related_p) { - rtx insn; + rtx_insn *insn; rtx orig_offset = offset; gcc_assert (REG_P (target)); @@ -10636,7 +10678,7 @@ s390_prologue_plus_offset (rtx target, rtx reg, rtx offset, bool frame_related_p if (!CONST_INT_P (offset)) { - annotate_constant_pool_refs (&PATTERN (insn)); + annotate_constant_pool_refs (insn); if (frame_related_p) add_reg_note (insn, REG_FRAME_RELATED_EXPR, @@ -11076,7 +11118,7 @@ s390_emit_prologue (void) rtx_insn *insns = s390_load_got (); for (rtx_insn *insn = insns; insn; insn = NEXT_INSN (insn)) - annotate_constant_pool_refs (&PATTERN (insn)); + annotate_constant_pool_refs (insn); emit_insn (insns); } @@ -11140,7 +11182,8 @@ s390_emit_epilogue (bool sibcall) } else { - rtx insn, frame_off, cfa; + rtx_insn *insn; + rtx frame_off, cfa; offset = area_bottom < 0 ? -area_bottom : 0; frame_off = GEN_INT (cfun_frame_layout.frame_size - offset); @@ -11149,9 +11192,11 @@ s390_emit_epilogue (bool sibcall) gen_rtx_PLUS (Pmode, frame_pointer, frame_off)); if (DISP_IN_RANGE (INTVAL (frame_off))) { - insn = gen_rtx_SET (frame_pointer, - gen_rtx_PLUS (Pmode, frame_pointer, frame_off)); - insn = emit_insn (insn); + rtx set; + + set = gen_rtx_SET (frame_pointer, + gen_rtx_PLUS (Pmode, frame_pointer, frame_off)); + insn = emit_insn (set); } else { @@ -11159,7 +11204,7 @@ s390_emit_epilogue (bool sibcall) frame_off = force_const_mem (Pmode, frame_off); insn = emit_insn (gen_add2_insn (frame_pointer, frame_off)); - annotate_constant_pool_refs (&PATTERN (insn)); + annotate_constant_pool_refs (insn); } add_reg_note (insn, REG_CFA_ADJUST_CFA, cfa); RTX_FRAME_RELATED_P (insn) = 1; -- 2.30.2