This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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);


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]