From 95c8e04b098394262e6883b8ef5e713d080f92e5 Mon Sep 17 00:00:00 2001 From: Jim Wilson Date: Fri, 17 Nov 2000 22:18:25 +0000 Subject: [PATCH] Fix miscompilation of linux kernel ia64_do_signal routine. * config/ia64/ia64.c (emit_insn_group_barriers, case CALL_INSN): Don't clear need_barrier is next_insn is a CALL_INSN, or has instruction type B or UNKNOWN. From-SVN: r37528 --- gcc/ChangeLog | 6 ++++++ gcc/config/ia64/ia64.c | 25 +++++++++++++++++++++++-- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 2d200c0..bd36ead 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2000-11-17 Jim Wilson + + * config/ia64/ia64.c (emit_insn_group_barriers, case CALL_INSN): + Don't clear need_barrier is next_insn is a CALL_INSN, or has + instruction type B or UNKNOWN. + 2000-11-17 Neil Booth * cpperror.c (print_file_and_line): Don't display line number diff --git a/gcc/config/ia64/ia64.c b/gcc/config/ia64/ia64.c index e318dbb..e523eef 100644 --- a/gcc/config/ia64/ia64.c +++ b/gcc/config/ia64/ia64.c @@ -4460,24 +4460,45 @@ emit_insn_group_barriers (insns) memcpy (rws_sum, rws_insn, sizeof (rws_sum)); } - /* A call must end a group, otherwise the assembler might pack + /* A call must end a bundle, otherwise the assembler might pack it in with a following branch and then the function return goes to the wrong place. Do this unconditionally for unconditional calls, simply because it (1) looks nicer and (2) keeps the data structures more accurate for the insns following the call. */ + /* ??? A call doesn't have to end a bundle if it is followed by + a mutex call or branch. Two mutex calls/branches can be put in + the same bundle. */ need_barrier = 1; if (GET_CODE (PATTERN (insn)) == COND_EXEC) { rtx next_insn = insn; + enum attr_type type = TYPE_A; + do next_insn = next_nonnote_insn (next_insn); while (next_insn && GET_CODE (next_insn) == INSN && (GET_CODE (PATTERN (next_insn)) == USE || GET_CODE (PATTERN (next_insn)) == CLOBBER)); - if (next_insn && GET_CODE (next_insn) != JUMP_INSN) + + /* A call ends a bundle if there is a stop bit after it, + or if it is followed by a non-B-type instruction. + In the later case, we can elide the stop bit, and get faster + code when the predicate is false. */ + /* ??? The proper solution for this problem is to make gcc + explicitly bundle instructions. Then we don't need to + emit stop bits to force the assembler to start a new + bundle. */ + + /* Check the instruction type if it is not a branch or call. */ + if (next_insn && GET_CODE (next_insn) == INSN) + type = get_attr_type (next_insn); + + if (next_insn && GET_CODE (next_insn) != JUMP_INSN + && GET_CODE (next_insn) != CALL_INSN + && type != TYPE_B && type != TYPE_UNKNOWN) need_barrier = 0; } if (need_barrier) -- 2.7.4