This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH pa.c]: Fix corner case in output of conditional branches
- From: "John David Anglin" <dave at hiauly1 dot hia dot nrc dot ca>
- To: gcc-patches at gcc dot gnu dot org, hainque at ACT-Europe dot FR
- Date: Sat, 22 Mar 2003 15:21:03 -0500 (EST)
- Subject: [PATCH pa.c]: Fix corner case in output of conditional branches
The enclosed patch corrects the miscompilation of the following ada test
program when compiled with -O1 on the 3.2 branch.
procedure X is
type Kind_T is
(K_1, K_2, K_3, K_4, K_5,
K_6, K_7, K_8, K_9, K_10,
K_11, K_12, K_13, K_14, K_15,
K_16, K_17);
type Object_T (Kind : Kind_T) is record
case Kind is
when K_1 => null;
when K_4 => null;
when K_9 => null;
when K_10 => null;
when K_11 => null;
when K_12 => null;
when K_14 => null;
when K_15 => null;
when K_16 => null;
when K_17 => RC : Integer;
when others => null;
end case;
end record;
type Point_T is record
Pkind : Kind_T;
X, Y : Integer;
end record;
function Get_Object_For (Point : Point_T)
return Object_T
is
O : Object_T (Point.Pkind);
begin
return O;
exception
when others =>
raise Constraint_Error;
end;
PP : Point_T;
OO : Object_T (K_4);
begin
PP.Pkind := K_4;
OO := Get_Object_For (PP);
end;
The jump optimization fails and we end up with a conditional branch
to its delay slot. This branch was preceded by another conditional
branch to the same branch target. We deleted the conditional branch
that branched to its delay slot. This then changed the branch
target of the preceding branch to its delay slot. This caused the
following instruction to be nullified when it shouldn't have been.
I thought of testing for this situation but decided to just go with
the simple and safe route of emitting a nop when we have a conditional
branch to its delay slot. Really, jump optimization should delete
these instructions.
I also changed a number of uses of next_active_insn to next_real_insn
but just on 3.3 and the trunk. We really want to use next_real_insn
in these cases. next_active_insn works because we don't have any
bare USE's and CLOBBER's in the instruction stream postreload as
far as I know.
Tested on hppa64-hp-hpux11.*, hppa2.0-hp-hpux11*, hppa1.1-hp-hpux10.20
and hppa-unknown-linux-gnu, 3.2 - trunk.
Installed 3.2, 3.3 and trunk.
Dave
--
J. David Anglin dave dot anglin at nrc-cnrc dot gc dot ca
National Research Council of Canada (613) 990-0752 (FAX: 952-6602)
2003-03-22 John David Anglin <dave dot anglin at nrc-cnrc dot gc dot ca>
* pa.c (output_cbranch, output_bb, output_bvb): Output nop for
conditional branch to the following instruction. Use next_real_insn
instead of next_active_insn.
(output_dbra, output_movb, jump_in_call_delay): Use next_real_insn
instead of next_active_insn.
Index: config/pa/pa.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/pa/pa.c,v
retrieving revision 1.203
diff -u -3 -p -r1.203 pa.c
--- config/pa/pa.c 19 Mar 2003 04:41:48 -0000 1.203
+++ config/pa/pa.c 20 Mar 2003 20:43:07 -0000
@@ -5549,13 +5549,18 @@ output_cbranch (operands, nullify, lengt
int useskip = 0;
rtx xoperands[5];
- /* A conditional branch to the following instruction (eg the delay slot) is
- asking for a disaster. This can happen when not optimizing.
-
- In such cases it is safe to emit nothing. */
+ /* A conditional branch to the following instruction (eg the delay slot)
+ is asking for a disaster. This can happen when not optimizing and
+ when jump optimization fails.
+
+ While it usually safe to emit nothing, this can fail if the preceding
+ instruction is a nullified branch with an empty delay slot and the
+ same branch target as this branch. We could check for this but
+ jump optimization should eliminate these jumps. It is always
+ safe to emit a nop. */
- if (next_active_insn (JUMP_LABEL (insn)) == next_active_insn (insn))
- return "";
+ if (next_real_insn (JUMP_LABEL (insn)) == next_real_insn (insn))
+ return "nop";
/* If this is a long branch with its delay slot unfilled, set `nullify'
as it can nullify the delay slot and save a nop. */
@@ -5851,8 +5856,8 @@ output_bb (operands, nullify, length, ne
is only used when optimizing; jump optimization should eliminate the
jump. But be prepared just in case. */
- if (next_active_insn (JUMP_LABEL (insn)) == next_active_insn (insn))
- return "";
+ if (next_real_insn (JUMP_LABEL (insn)) == next_real_insn (insn))
+ return "nop";
/* If this is a long branch with its delay slot unfilled, set `nullify'
as it can nullify the delay slot and save a nop. */
@@ -5999,8 +6004,8 @@ output_bvb (operands, nullify, length, n
is only used when optimizing; jump optimization should eliminate the
jump. But be prepared just in case. */
- if (next_active_insn (JUMP_LABEL (insn)) == next_active_insn (insn))
- return "";
+ if (next_real_insn (JUMP_LABEL (insn)) == next_real_insn (insn))
+ return "nop";
/* If this is a long branch with its delay slot unfilled, set `nullify'
as it can nullify the delay slot and save a nop. */
@@ -6140,7 +6145,7 @@ output_dbra (operands, insn, which_alter
/* A conditional branch to the following instruction (eg the delay slot) is
asking for a disaster. Be prepared! */
- if (next_active_insn (JUMP_LABEL (insn)) == next_active_insn (insn))
+ if (next_real_insn (JUMP_LABEL (insn)) == next_real_insn (insn))
{
if (which_alternative == 0)
return "ldo %1(%0),%0";
@@ -6247,7 +6252,7 @@ output_movb (operands, insn, which_alter
/* A conditional branch to the following instruction (eg the delay slot) is
asking for a disaster. Be prepared! */
- if (next_active_insn (JUMP_LABEL (insn)) == next_active_insn (insn))
+ if (next_real_insn (JUMP_LABEL (insn)) == next_real_insn (insn))
{
if (which_alternative == 0)
return "copy %1,%0";
@@ -7585,9 +7590,9 @@ jump_in_call_delay (insn)
if (PREV_INSN (insn)
&& PREV_INSN (PREV_INSN (insn))
- && GET_CODE (next_active_insn (PREV_INSN (PREV_INSN (insn)))) == INSN)
+ && GET_CODE (next_real_insn (PREV_INSN (PREV_INSN (insn)))) == INSN)
{
- rtx test_insn = next_active_insn (PREV_INSN (PREV_INSN (insn)));
+ rtx test_insn = next_real_insn (PREV_INSN (PREV_INSN (insn)));
return (GET_CODE (PATTERN (test_insn)) == SEQUENCE
&& XVECEXP (PATTERN (test_insn), 0, 1) == insn);