[parisc-linux-cvs] Re: 64 bit compiler bug

amodra@one.net.au amodra@one.net.au
Thu, 31 May 2001 00:31:09 +0930


Here's what I finally commited to fix the 64-bit millicode call bug
(first group in Changelog), and a few other small fixes/enhancements.
The diff below for pa.md is against the source as it was before I
started attempting to fix the millicode problem as it shows the
final change better that way.

gcc/ChangeLog.puffin
	* config/pa/pa.c (emit_hpdiv_const): Return reg is r2 for 64-bit
	millicode.
	(insn_refs_are_delayed): Correct comment.
	* config/pa/pa.h (INSN_REFERENCES_ARE_DELAYED): Likewise.
	* config/pa/pa.md (mulsi3): If TARGET_64BIT, clobber r2
	instead of r31.  Make associated insn !TARGET_64BIT, and
	provide an additional 64-bit insn that clobbers r2.
	(divsi3): Likewise.
	(udivsi3): Likewise.
	(modsi3): Likewise.
	(umodsi3): Likewise.

	* config/pa/pa.c (hppa_init_pic_save): Revert back to saving pic
	register after last_parm_insn.
	(compute_frame_size): 64-bit frame marker is 16 bytes.

	* config/pa/pa-linux.h (FUNCTION_OK_FOR_SIBCALL): Define as 1.
	(CC1_SPEC): Define with -mno-space-regs as default.

Index: config/pa/pa-linux.h
===================================================================
RCS file: /home/cvs/parisc/gcc/gcc/config/pa/pa-linux.h,v
retrieving revision 1.21
diff -u -p -r1.21 pa-linux.h
--- pa-linux.h	2001/05/01 12:40:14	1.21
+++ pa-linux.h	2001/05/30 14:23:50
@@ -31,6 +31,9 @@ Boston, MA 02111-1307, USA.  */
 
 #undef CPLUSPLUS_CPP_SPEC
 
+#undef CC1_SPEC
+#define CC1_SPEC "%{pg:} %{p:} %{!mspace-regs:-mno-space-regs}"
+
 #undef	LIB_SPEC
 #define LIB_SPEC "%{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p}"
 
@@ -50,9 +53,8 @@ Boston, MA 02111-1307, USA.  */
       %{!dynamic-linker:-dynamic-linker /lib/ld.so.1}} \
       %{static:-static}}"
 
-/* Sibcalls, stubs, and elf sections don't play well.  */
 #undef FUNCTION_OK_FOR_SIBCALL
-#define FUNCTION_OK_FOR_SIBCALL(x) 0
+#define FUNCTION_OK_FOR_SIBCALL(DECL) 1
 
 /* glibc's profiling functions don't need gcc to allocate counters.  */
 #define NO_PROFILE_COUNTERS 1
Index: config/pa/pa.c
===================================================================
RCS file: /home/cvs/parisc/gcc/gcc/config/pa/pa.c,v
retrieving revision 1.21
diff -u -p -r1.21 pa.c
--- pa.c	2001/04/17 00:45:01	1.21
+++ pa.c	2001/05/30 14:24:31
@@ -2925,7 +2925,7 @@ compute_frame_size (size, fregs_live)
      allocated for any function that makes calls or otherwise allocates
      stack space.  */
   if (!current_function_is_leaf || fsize)
-    fsize += 32;
+    fsize += TARGET_64BIT ? 16 : 32;
 
   return (fsize + STACK_BOUNDARY - 1) & ~(STACK_BOUNDARY - 1);
 }
@@ -3271,7 +3271,6 @@ hppa_expand_prologue ()
     }
 }
 
-
 void
 output_function_epilogue (file, size)
      FILE *file;
@@ -3429,7 +3428,7 @@ hppa_expand_epilogue ()
 void
 hppa_init_pic_save ()
 {
-  rtx insn, picreg;
+  rtx insn, picreg, where;
 
   picreg = gen_rtx_REG (word_mode, PIC_OFFSET_TABLE_REGNUM);
   PIC_OFFSET_TABLE_SAVE_RTX = gen_reg_rtx (Pmode);
@@ -3437,11 +3436,14 @@ hppa_init_pic_save ()
   insn = gen_rtx_SET (VOIDmode, PIC_OFFSET_TABLE_SAVE_RTX, picreg);
 
   /* Emit the insn at the beginning of the function after the prologue.  */
-  if (tail_recursion_reentry)
-    emit_insn_before (insn, tail_recursion_reentry);
-  else
-    /* We must have been called via PROFILE_HOOK.  */
-    emit_insn (insn);
+  where = last_parm_insn;
+  if (!where)
+    {
+      push_topmost_sequence ();
+      where = get_insns ();
+      pop_topmost_sequence ();
+    }
+  emit_insn_after (insn, where);
 }
 
 void
@@ -4535,6 +4537,8 @@ emit_hpdiv_const (operands, unsignedp)
       && INTVAL (operands[2]) < 16
       && magic_milli[INTVAL (operands[2])])
     {
+      rtx ret = gen_rtx_REG (SImode, TARGET_64BIT ? 2 : 31);
+
       emit_move_insn (gen_rtx_REG (SImode, 26), operands[1]);
       emit
 	(gen_rtx
@@ -4548,7 +4552,7 @@ emit_hpdiv_const (operands, unsignedp)
 		     gen_rtx_CLOBBER (VOIDmode, operands[3]),
 		     gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (SImode, 26)),
 		     gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (SImode, 25)),
-		     gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (SImode, 31)))));
+		     gen_rtx_CLOBBER (VOIDmode, ret))));
       emit_move_insn (operands[0], gen_rtx_REG (SImode, 29));
       return 1;
     }
@@ -6989,12 +6993,18 @@ pa_can_combine_p (new, anchor, floater, 
 
    Millicode calls always expect their arguments in the integer argument
    registers, and always return their result in %r29 (ret1).  They
-   are expected to clobber their arguments, %r1, %r29, and %r31 and
-   nothing else.
+   are expected to clobber their arguments, %r1, %r29, and the return
+   pointer which is %r31 on 32-bit and %r2 on 64-bit, and nothing else.
 
-   By considering this effects delayed reorg reorg can put insns
-   which set the argument registers into the delay slot of the millicode
-   call -- thus they act more like traditional CALL_INSNs.
+   This function tells reorg that the references to arguments and
+   millicode calls do not appear to happen until after the millicode call.
+   This allows reorg to put insns which set the argument registers into the
+   delay slot of the millicode call -- thus they act more like traditional
+   CALL_INSNs.
+
+   Note we can not consider side effects of the insn to be delayed because
+   the branch and link insn will clobber the return pointer.  If we happened
+   to use the return pointer in the delay slot of the call, then we lose.
 
    get_attr_type will try to recognize the given insn, so make sure to
    filter out things it will not accept -- SEQUENCE, USE and CLOBBER insns
Index: config/pa/pa.h
===================================================================
RCS file: /home/cvs/parisc/gcc/gcc/config/pa/pa.h,v
retrieving revision 1.13
diff -u -p -r1.13 pa.h
--- pa.h	2001/05/01 12:40:14	1.13
+++ pa.h	2001/05/30 14:24:53
@@ -1736,8 +1736,8 @@ while (0)
 
    Millicode calls always expect their arguments in the integer argument
    registers, and always return their result in %r29 (ret1).  They
-   are expected to clobber their arguments, %r1, %r29, and %r31 and
-   nothing else.
+   are expected to clobber their arguments, %r1, %r29, and the return
+   pointer which is %r31 on 32-bit and %r2 on 64-bit, and nothing else.
 
    This macro tells reorg that the references to arguments and
    millicode calls do not appear to happen until after the millicode call.
Index: config/pa/pa.md
===================================================================
RCS file: /home/cvs/parisc/gcc/gcc/config/pa/pa.md,v
retrieving revision 1.7
diff -u -p -r1.7 pa.md
--- pa.md	2001/04/17 00:45:01	1.7
+++ pa.md	2001/05/30 14:33:32
@@ -3869,11 +3869,12 @@
 	      (clobber (match_dup 3))
 	      (clobber (reg:SI 26))
 	      (clobber (reg:SI 25))
-	      (clobber (reg:SI 31))])
+	      (clobber (match_dup 4))])
    (set (match_operand:SI 0 "general_operand" "") (reg:SI 29))]
   ""
   "
 {
+  operands[4] = gen_rtx_REG (SImode, TARGET_64BIT ? 2 : 31);
   if (TARGET_PA_11 && ! TARGET_DISABLE_FPREGS && ! TARGET_SOFT_FLOAT)
     {
       rtx scratch = gen_reg_rtx (DImode);
@@ -3930,7 +3931,7 @@
    (clobber (reg:SI 26))
    (clobber (reg:SI 25))
    (clobber (reg:SI 31))]
-  ""
+  "!TARGET_64BIT"
   "* return output_mul_insn (0, insn);"
   [(set_attr "type" "milli")
    (set (attr "length")
@@ -3955,6 +3956,17 @@
 ;; Out of reach, can use ble
           (const_int 12)))])
 
+(define_insn ""
+  [(set (reg:SI 29) (mult:SI (reg:SI 26) (reg:SI 25)))
+   (clobber (match_operand:SI 0 "register_operand" "=a"))
+   (clobber (reg:SI 26))
+   (clobber (reg:SI 25))
+   (clobber (reg:SI 2))]
+  "TARGET_64BIT"
+  "* return output_mul_insn (0, insn);"
+  [(set_attr "type" "milli")
+   (set (attr "length") (const_int 4))])
+
 (define_expand "muldi3"
   [(set (match_operand:DI 0 "register_operand" "")
         (mult:DI (match_operand:DI 1 "register_operand" "")
@@ -4012,15 +4024,22 @@
 	      (clobber (match_dup 4))
 	      (clobber (reg:SI 26))
 	      (clobber (reg:SI 25))
-	      (clobber (reg:SI 31))])
+	      (clobber (match_dup 5))])
    (set (match_operand:SI 0 "general_operand" "") (reg:SI 29))]
   ""
   "
 {
   operands[3] = gen_reg_rtx (SImode);
-  operands[4] = gen_reg_rtx (SImode);
   if (TARGET_64BIT)
-    operands[4] = gen_rtx_REG (SImode, 2);
+    {
+      operands[5] = gen_rtx_REG (SImode, 2);
+      operands[4] = operands[5];
+    }
+  else
+    {
+      operands[5] = gen_rtx_REG (SImode, 31);
+      operands[4] = gen_reg_rtx (SImode);
+    }
   if (GET_CODE (operands[2]) == CONST_INT && emit_hpdiv_const (operands, 0))
     DONE;
 }")
@@ -4033,7 +4052,7 @@
    (clobber (reg:SI 26))
    (clobber (reg:SI 25))
    (clobber (reg:SI 31))]
-  ""
+  "!TARGET_64BIT"
   "*
    return output_div_insn (operands, 0, insn);"
   [(set_attr "type" "milli")
@@ -4059,6 +4078,20 @@
 ;; Out of reach, can use ble
           (const_int 12)))])
 
+(define_insn ""
+  [(set (reg:SI 29)
+	(div:SI (reg:SI 26) (match_operand:SI 0 "div_operand" "")))
+   (clobber (match_operand:SI 1 "register_operand" "=a"))
+   (clobber (match_operand:SI 2 "register_operand" "=&r"))
+   (clobber (reg:SI 26))
+   (clobber (reg:SI 25))
+   (clobber (reg:SI 2))]
+  "TARGET_64BIT"
+  "*
+   return output_div_insn (operands, 0, insn);"
+  [(set_attr "type" "milli")
+   (set (attr "length") (const_int 4))])
+
 (define_expand "udivsi3"
   [(set (reg:SI 26) (match_operand:SI 1 "move_operand" ""))
    (set (reg:SI 25) (match_operand:SI 2 "move_operand" ""))
@@ -4067,15 +4100,22 @@
 	      (clobber (match_dup 4))
 	      (clobber (reg:SI 26))
 	      (clobber (reg:SI 25))
-	      (clobber (reg:SI 31))])
+	      (clobber (match_dup 5))])
    (set (match_operand:SI 0 "general_operand" "") (reg:SI 29))]
   ""
   "
 {
   operands[3] = gen_reg_rtx (SImode);
-  operands[4] = gen_reg_rtx (SImode);
   if (TARGET_64BIT)
-    operands[4] = gen_rtx_REG (SImode, 2);
+    {
+      operands[5] = gen_rtx_REG (SImode, 2);
+      operands[4] = operands[5];
+    }
+  else
+    {
+      operands[5] = gen_rtx_REG (SImode, 31);
+      operands[4] = gen_reg_rtx (SImode);
+    }
   if (GET_CODE (operands[2]) == CONST_INT && emit_hpdiv_const (operands, 1))
     DONE;
 }")
@@ -4088,7 +4128,7 @@
    (clobber (reg:SI 26))
    (clobber (reg:SI 25))
    (clobber (reg:SI 31))]
-  ""
+  "!TARGET_64BIT"
   "*
    return output_div_insn (operands, 1, insn);"
   [(set_attr "type" "milli")
@@ -4114,6 +4154,20 @@
 ;; Out of reach, can use ble
           (const_int 12)))])
 
+(define_insn ""
+  [(set (reg:SI 29)
+	(udiv:SI (reg:SI 26) (match_operand:SI 0 "div_operand" "")))
+   (clobber (match_operand:SI 1 "register_operand" "=a"))
+   (clobber (match_operand:SI 2 "register_operand" "=&r"))
+   (clobber (reg:SI 26))
+   (clobber (reg:SI 25))
+   (clobber (reg:SI 2))]
+  "TARGET_64BIT"
+  "*
+   return output_div_insn (operands, 1, insn);"
+  [(set_attr "type" "milli")
+   (set (attr "length") (const_int 4))])
+
 (define_expand "modsi3"
   [(set (reg:SI 26) (match_operand:SI 1 "move_operand" ""))
    (set (reg:SI 25) (match_operand:SI 2 "move_operand" ""))
@@ -4122,14 +4176,21 @@
 	      (clobber (match_dup 4))
 	      (clobber (reg:SI 26))
 	      (clobber (reg:SI 25))
-	      (clobber (reg:SI 31))])
+	      (clobber (match_dup 5))])
    (set (match_operand:SI 0 "general_operand" "") (reg:SI 29))]
   ""
   "
 {
-  operands[4] = gen_reg_rtx (SImode);
   if (TARGET_64BIT)
-    operands[4] = gen_rtx_REG (SImode, 2);
+    {
+      operands[5] = gen_rtx_REG (SImode, 2);
+      operands[4] = operands[5];
+    }
+  else
+    {
+      operands[5] = gen_rtx_REG (SImode, 31);
+      operands[4] = gen_reg_rtx (SImode);
+    }
   operands[3] = gen_reg_rtx (SImode);
 }")
 
@@ -4140,7 +4201,7 @@
    (clobber (reg:SI 26))
    (clobber (reg:SI 25))
    (clobber (reg:SI 31))]
-  ""
+  "!TARGET_64BIT"
   "*
   return output_mod_insn (0, insn);"
   [(set_attr "type" "milli")
@@ -4166,6 +4227,19 @@
 ;; Out of reach, can use ble
           (const_int 12)))])
 
+(define_insn ""
+  [(set (reg:SI 29) (mod:SI (reg:SI 26) (reg:SI 25)))
+   (clobber (match_operand:SI 0 "register_operand" "=a"))
+   (clobber (match_operand:SI 1 "register_operand" "=&r"))
+   (clobber (reg:SI 26))
+   (clobber (reg:SI 25))
+   (clobber (reg:SI 2))]
+  "TARGET_64BIT"
+  "*
+  return output_mod_insn (0, insn);"
+  [(set_attr "type" "milli")
+   (set (attr "length") (const_int 4))])
+
 (define_expand "umodsi3"
   [(set (reg:SI 26) (match_operand:SI 1 "move_operand" ""))
    (set (reg:SI 25) (match_operand:SI 2 "move_operand" ""))
@@ -4174,14 +4248,21 @@
 	      (clobber (match_dup 4))
 	      (clobber (reg:SI 26))
 	      (clobber (reg:SI 25))
-	      (clobber (reg:SI 31))])
+	      (clobber (match_dup 5))])
    (set (match_operand:SI 0 "general_operand" "") (reg:SI 29))]
   ""
   "
 {
-  operands[4] = gen_reg_rtx (SImode);
   if (TARGET_64BIT)
-    operands[4] = gen_rtx_REG (SImode, 2);
+    {
+      operands[5] = gen_rtx_REG (SImode, 2);
+      operands[4] = operands[5];
+    }
+  else
+    {
+      operands[5] = gen_rtx_REG (SImode, 31);
+      operands[4] = gen_reg_rtx (SImode);
+    }
   operands[3] = gen_reg_rtx (SImode);
 }")
 
@@ -4192,7 +4273,7 @@
    (clobber (reg:SI 26))
    (clobber (reg:SI 25))
    (clobber (reg:SI 31))]
-  ""
+  "!TARGET_64BIT"
   "*
   return output_mod_insn (1, insn);"
   [(set_attr "type" "milli")
@@ -4217,6 +4298,19 @@
 
 ;; Out of reach, can use ble
           (const_int 12)))])
+
+(define_insn ""
+  [(set (reg:SI 29) (umod:SI (reg:SI 26) (reg:SI 25)))
+   (clobber (match_operand:SI 0 "register_operand" "=a"))
+   (clobber (match_operand:SI 1 "register_operand" "=&r"))
+   (clobber (reg:SI 26))
+   (clobber (reg:SI 25))
+   (clobber (reg:SI 2))]
+  "TARGET_64BIT"
+  "*
+  return output_mod_insn (1, insn);"
+  [(set_attr "type" "milli")
+   (set (attr "length") (const_int 4))])
 
 ;;- and instructions
 ;; We define DImode `and` so with DImode `not` we can get