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]

Fix ACATS failure on SPARC


This patch fixes the last ACATS failure on SPARC (32-bit) on mainline (and on 
3.4 branch at -O2), namely:

FAIL:	cd10002

It was due to an inconsistency in the back-end as to whether the 'unimp' 
instruction should be emitted for zero-sized structures.  The back-end 
mostly says no, except the infamous "return peepholes" which presumably were 
not updated.

Fixed by using a single predicate throughout the back-end.  Bootstrapped and 
regtested on sparc64-sun-solaris2.9 and sparc-sun-solaris2.8.

Applied to mainline.


2004-05-07  Eric Botcazou  <ebotcazou@act-europe.fr>

	* config/sparc/sparc-protos.h (sparc_skip_caller_unimp): New
	declaration.
	* config/sparc/sparc.c (SKIP_CALLERS_UNIMP_P): Delete.
	(sparc_skip_caller_unimp): New global variable.
	(sparc_function_epilogue): Set 'sparc_skip_caller_unimp'.
	Use it instead of SKIP_CALLERS_UNIMP_P.
	* config/sparc/sparc.md (call expander): Add sanity check.
	(call_address_struct_value_sp32): Re-sync with expander.
	(call_symbolic_struct_value_sp32): Likewise.
	(return peepholes): Use 'sparc_skip_caller_unimp' instead
	of custom predicate.

-- 
Eric Botcazou
Index: config/sparc/sparc-protos.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/sparc/sparc-protos.h,v
retrieving revision 1.41
diff -u -p -r1.41 sparc-protos.h
--- config/sparc/sparc-protos.h	26 Feb 2004 18:40:40 -0000	1.41
+++ config/sparc/sparc-protos.h	7 May 2004 05:30:39 -0000
@@ -25,6 +25,7 @@ Boston, MA 02111-1307, USA.  */
 #define __SPARC_PROTOS_H__
 
 extern bool sparc_emitting_epilogue;
+extern bool sparc_skip_caller_unimp;
 
 #ifdef TREE_CODE
 extern struct rtx_def *function_value (tree, enum machine_mode, int);
Index: config/sparc/sparc.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/sparc/sparc.c,v
retrieving revision 1.298
diff -u -p -r1.298 sparc.c
--- config/sparc/sparc.c	8 Apr 2004 18:26:09 -0000	1.298
+++ config/sparc/sparc.c	7 May 2004 05:31:09 -0000
@@ -48,17 +48,6 @@ Boston, MA 02111-1307, USA.  */
 #include "target-def.h"
 #include "cfglayout.h"
 
-/* 1 if the caller has placed an "unimp" insn immediately after the call.
-   This is used in v8 code when calling a function that returns a structure.
-   v9 doesn't have this.  Be careful to have this test be the same as that
-   used on the call.  */
-
-#define SKIP_CALLERS_UNIMP_P  \
-(!TARGET_ARCH64 && current_function_returns_struct			\
- && ! integer_zerop (DECL_SIZE (DECL_RESULT (current_function_decl)))	\
- && (TREE_CODE (DECL_SIZE (DECL_RESULT (current_function_decl)))	\
-     == INTEGER_CST))
-
 /* Global variables for machine-dependent things.  */
 
 /* Size of frame.  Need to know this to emit return insns from leaf procedures.
@@ -81,6 +70,7 @@ rtx sparc_compare_op0, sparc_compare_op1
 /* Coordinate with the md file wrt special insns created by
    sparc_function_epilogue.  */
 bool sparc_emitting_epilogue;
+bool sparc_skip_caller_unimp;
 
 /* Vector to say how input registers are mapped to output registers.
    HARD_FRAME_POINTER_REGNUM cannot be remapped by this function to
@@ -4498,6 +4488,17 @@ sparc_function_epilogue (FILE *file,
 {
   const char *ret;
 
+  /* True if the caller has placed an "unimp" insn immediately after the call.
+     This insn is used in the 32-bit ABI when calling a function that returns
+     a non zero-sized structure. The 64-bit ABI doesn't have it.  Be careful
+     to have this test be the same as that used on the call.  */
+  sparc_skip_caller_unimp =
+    ! TARGET_ARCH64
+    && current_function_returns_struct
+    && (TREE_CODE (DECL_SIZE (DECL_RESULT (current_function_decl)))
+	== INTEGER_CST)
+    && ! integer_zerop (DECL_SIZE (DECL_RESULT (current_function_decl)));
+
   if (current_function_epilogue_delay_list == 0)
     {
       /* If code does not drop into the epilogue, we need
@@ -4532,9 +4533,9 @@ sparc_function_epilogue (FILE *file,
 
   /* Work out how to skip the caller's unimp instruction if required.  */
   if (leaf_function)
-    ret = (SKIP_CALLERS_UNIMP_P ? "jmp\t%o7+12" : "retl");
+    ret = (sparc_skip_caller_unimp ? "jmp\t%o7+12" : "retl");
   else
-    ret = (SKIP_CALLERS_UNIMP_P ? "jmp\t%i7+12" : "ret");
+    ret = (sparc_skip_caller_unimp ? "jmp\t%i7+12" : "ret");
 
   if (! leaf_function)
     {
@@ -4542,7 +4543,7 @@ sparc_function_epilogue (FILE *file,
 	{
 	  if (current_function_epilogue_delay_list)
 	    abort ();
-	  if (SKIP_CALLERS_UNIMP_P)
+	  if (sparc_skip_caller_unimp)
 	    abort ();
 
 	  fputs ("\trestore\n\tretl\n\tadd\t%sp, %g1, %sp\n", file);
@@ -4555,7 +4556,7 @@ sparc_function_epilogue (FILE *file,
 	  if (TARGET_V9 && ! epilogue_renumber (&delay, 1))
 	    {
 	      epilogue_renumber (&delay, 0);
-	      fputs (SKIP_CALLERS_UNIMP_P
+	      fputs (sparc_skip_caller_unimp
 		     ? "\treturn\t%i7+12\n"
 		     : "\treturn\t%i7+8\n", file);
 	      final_scan_insn (XEXP (current_function_epilogue_delay_list, 0),
@@ -4588,7 +4589,7 @@ sparc_function_epilogue (FILE *file,
 	      sparc_emitting_epilogue = false;
 	    }
 	}
-      else if (TARGET_V9 && ! SKIP_CALLERS_UNIMP_P)
+      else if (TARGET_V9 && ! sparc_skip_caller_unimp)
 	fputs ("\treturn\t%i7+8\n\tnop\n", file);
       else
 	fprintf (file, "\t%s\n\trestore\n", ret);
Index: config/sparc/sparc.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/sparc/sparc.md,v
retrieving revision 1.200
diff -u -p -r1.200 sparc.md
--- config/sparc/sparc.md	26 Mar 2004 11:13:48 -0000	1.200
+++ config/sparc/sparc.md	7 May 2004 05:31:37 -0000
@@ -7321,9 +7321,12 @@
 {
   rtx fn_rtx;
 
-   if (GET_MODE (operands[0]) != FUNCTION_MODE)
+  if (GET_MODE (operands[0]) != FUNCTION_MODE)
     abort ();
 
+  if (GET_CODE (operands[3]) != CONST_INT)
+    abort();
+
   if (GET_CODE (XEXP (operands[0], 0)) == LABEL_REF)
     {
       /* This is really a PIC sequence.  We want to represent
@@ -7333,6 +7336,7 @@
 	 call-clobbered registers?  We lose this if it is a JUMP_INSN.
 	 Why cannot we have delay slots filled if it were a CALL?  */
 
+      /* We accept negative sizes for untyped calls.  */
       if (! TARGET_ARCH64 && INTVAL (operands[3]) != 0)
 	emit_jump_insn
 	  (gen_rtx_PARALLEL
@@ -7353,6 +7357,7 @@
 
   fn_rtx = operands[0];
 
+  /* We accept negative sizes for untyped calls.  */
   if (! TARGET_ARCH64 && INTVAL (operands[3]) != 0)
     emit_call_insn
       (gen_rtx_PARALLEL
@@ -7419,7 +7424,7 @@
    (match_operand 2 "immediate_operand" "")
    (clobber (reg:SI 15))]
   ;;- Do not use operand 1 for most machines.
-  "! TARGET_ARCH64 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 0"
+  "! TARGET_ARCH64 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) > 0"
   "call\t%a0, %1\n\tnop\n\tunimp\t%2"
   [(set_attr "type" "call_no_delay_slot")
    (set_attr "length" "3")])
@@ -7432,7 +7437,7 @@
    (match_operand 2 "immediate_operand" "")
    (clobber (reg:SI 15))]
   ;;- Do not use operand 1 for most machines.
-  "! TARGET_ARCH64 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 0"
+  "! TARGET_ARCH64 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) > 0"
   "call\t%a0, %1\n\tnop\n\tunimp\t%2"
   [(set_attr "type" "call_no_delay_slot")
    (set_attr "length" "3")])
@@ -7450,7 +7455,8 @@
   [(set_attr "type" "call_no_delay_slot")
    (set_attr "length" "3")])
 
-;; This is a call that wants a structure value.
+;; This is a call that may want a structure value.  This is used for
+;; untyped_calls.
 (define_insn "*call_symbolic_untyped_struct_value_sp32"
   [(call (mem:SI (match_operand:SI 0 "symbolic_operand" "s"))
 	 (match_operand 1 "" ""))
@@ -8083,7 +8089,7 @@
    (return)]
   "sparc_emitting_epilogue"
 {
-  if (! TARGET_ARCH64 && current_function_returns_struct)
+  if (sparc_skip_caller_unimp)
     return "jmp\t%%i7+12\n\trestore %%g0, %1, %Y0";
   else if (TARGET_V9 && (GET_CODE (operands[1]) == CONST_INT
 			 || IN_OR_GLOBAL_P (operands[1])))
@@ -8100,7 +8106,7 @@
    (return)]
   "sparc_emitting_epilogue"
 {
-  if (! TARGET_ARCH64 && current_function_returns_struct)
+  if (sparc_skip_caller_unimp)
     return "jmp\t%%i7+12\n\trestore %%g0, %1, %Y0";
   else if (TARGET_V9 && (GET_CODE (operands[1]) == CONST_INT
 			 || IN_OR_GLOBAL_P (operands[1])))
@@ -8117,7 +8123,7 @@
    (return)]
   "sparc_emitting_epilogue"
 {
-  if (! TARGET_ARCH64 && current_function_returns_struct)
+  if (sparc_skip_caller_unimp)
     return "jmp\t%%i7+12\n\trestore %%g0, %1, %Y0";
   else if (TARGET_V9 && (GET_CODE (operands[1]) == CONST_INT
 			 || IN_OR_GLOBAL_P (operands[1])))
@@ -8134,7 +8140,7 @@
    (return)]
   "sparc_emitting_epilogue"
 {
-  if (! TARGET_ARCH64 && current_function_returns_struct)
+  if (sparc_skip_caller_unimp)
     return "jmp\t%%i7+12\n\trestore %%g0, %1, %Y0";
   else if (TARGET_V9 && IN_OR_GLOBAL_P (operands[1]))
     return "return\t%%i7+8\n\tmov\t%Y1, %Y0";
@@ -8165,7 +8171,7 @@
    (return)]
   "sparc_emitting_epilogue"
 {
-  if (! TARGET_ARCH64 && current_function_returns_struct)
+  if (sparc_skip_caller_unimp)
     return "jmp\t%%i7+12\n\trestore %r1, %2, %Y0";
   /* If operands are global or in registers, can use return */
   else if (TARGET_V9 && IN_OR_GLOBAL_P (operands[1])
@@ -8185,7 +8191,7 @@
    (return)]
   "sparc_emitting_epilogue && ! TARGET_CM_MEDMID"
 {
-  if (! TARGET_ARCH64 && current_function_returns_struct)
+  if (sparc_skip_caller_unimp)
     return "jmp\t%%i7+12\n\trestore %r1, %%lo(%a2), %Y0";
   /* If operands are global or in registers, can use return */
   else if (TARGET_V9 && IN_OR_GLOBAL_P (operands[1]))

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