public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [committed] Work around bug in powf function on HP-UX
@ 2013-02-18 16:46 John David Anglin
  2013-03-11  0:52 ` John David Anglin
  0 siblings, 1 reply; 2+ messages in thread
From: John David Anglin @ 2013-02-18 16:46 UTC (permalink / raw)
  To: gcc-patches

The powf function on HP-UX incorrectly clobbers floating point register
%fr12.  It is supposed to be saved and restored by callee.  The patch
marks the register(s) as call used on HP-UX.  We still save and restore
the register is the prologue/epilogue, so the runtime isn't changed.

Tested on hppa2.0w-hp-hpux11 and hppa64-hp-hpux11.11.  Committed to
trunk.

Dave
-- 
J. David Anglin                                  dave.anglin@nrc-cnrc.gc.ca
National Research Council of Canada              (613) 990-0752 (FAX: 952-6602)

2013-02-18  John David Anglin  <dave.anglin@nrc-cnrc.gc.ca>

	PR target/56347
	* config/pa/pa.c (pa_conditional_register_usage): On HP-UX, mark
	registers %fr12 and %fr12R as call used.

Index: config/pa/pa.c
===================================================================
--- config/pa/pa.c	(revision 196122)
+++ config/pa/pa.c	(working copy)
@@ -10313,6 +10313,21 @@
 {
   int i;
 
+  if (TARGET_HPUX)
+    {
+      /* Work around powf bug in libm.  */
+      if (TARGET_64BIT)
+	{
+	  /* Mark %fr12 as call used.  */
+	  call_used_regs[40] = 1;
+	}
+      else
+	{
+	  /* Mark %fr12 and %fr12R as call used.  */
+	  call_used_regs[48] = 1;
+	  call_used_regs[49] = 1;
+	}
+    }
   if (!TARGET_64BIT && !TARGET_PA_11)
     {
       for (i = 56; i <= FP_REG_LAST; i++)

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [committed] Work around bug in powf function on HP-UX
  2013-02-18 16:46 [committed] Work around bug in powf function on HP-UX John David Anglin
@ 2013-03-11  0:52 ` John David Anglin
  0 siblings, 0 replies; 2+ messages in thread
From: John David Anglin @ 2013-03-11  0:52 UTC (permalink / raw)
  To: dave.anglin, John David Anglin; +Cc: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 701 bytes --]

On 18-Feb-13, at 11:45 AM, John David Anglin wrote:

> 2013-02-18  John David Anglin  <dave.anglin@nrc-cnrc.gc.ca>
>
> 	PR target/56347
> 	* config/pa/pa.c (pa_conditional_register_usage): On HP-UX, mark
> 	registers %fr12 and %fr12R as call used.

I committed the attached change.  It no longer unconditionally  
clobbers %fr12 and %fr12R
and instead uses special call patterns that clobber %fr12 to work  
around the problem.  It
is not perfect in that only direct calls are detected, but I think  
that is the best compromise.

Tested on hppa2.0w-hp-hpux11.11 and hppa64-hp-hpux11.11.  Build tested  
on hppa-unknown-linux-gnu.
Committed to trunk.

Dave
--
John David Anglin	dave.anglin@bell.net



[-- Attachment #2: pa-powf.d.5.txt --]
[-- Type: text/plain, Size: 10362 bytes --]

2013-03-10  John David Anglin  <dave.anglin@nrc-cnrc.gc.ca>

	PR target/56347
	* config/pa/pa.md (call_value): Check for calls to powf and direct to
	new call patterns that clobber %fr12.
	(call_val_powf, call_val_powf_pic, call_val_powf_64bit): New insn,
	split and postreload patterns.
	* config/pa/pa.c (pa_conditional_register_usage): Revert marking
	registers %fr12 and %fr12R as call used.

Index: config/pa/pa.md
===================================================================
--- config/pa/pa.md	(revision 196546)
+++ config/pa/pa.md	(working copy)
@@ -7600,7 +7600,6 @@
 			 (match_operand 2 "" "")))
 	      (clobber (reg:SI 2))])]
   ""
-  "
 {
   rtx op;
   rtx dst = operands[0];
@@ -7668,7 +7667,13 @@
     {
       rtx r4 = gen_rtx_REG (word_mode, 4);
       if (GET_CODE (op) == SYMBOL_REF)
-	  emit_call_insn (gen_call_val_symref_64bit (dst, op, nb, r4));
+	{
+	  if (TARGET_HPUX && !TARGET_DISABLE_FPREGS && !TARGET_SOFT_FLOAT
+	      && !strcmp (targetm.strip_name_encoding (XSTR (op, 0)), "powf"))
+	    emit_call_insn (gen_call_val_powf_64bit (dst, op, nb, r4));
+	  else
+	    emit_call_insn (gen_call_val_symref_64bit (dst, op, nb, r4));
+	}
       else
 	{
 	  op = force_reg (word_mode, op);
@@ -7682,10 +7687,23 @@
 	  if (flag_pic)
 	    {
 	      rtx r4 = gen_rtx_REG (word_mode, 4);
-	      emit_call_insn (gen_call_val_symref_pic (dst, op, nb, r4));
+
+	      if (TARGET_HPUX && !TARGET_DISABLE_FPREGS && !TARGET_SOFT_FLOAT
+		  && !strcmp (targetm.strip_name_encoding (XSTR (op, 0)),
+			      "powf"))
+		emit_call_insn (gen_call_val_powf_pic (dst, op, nb, r4));
+	      else
+		emit_call_insn (gen_call_val_symref_pic (dst, op, nb, r4));
 	    }
 	  else
-	    emit_call_insn (gen_call_val_symref (dst, op, nb));
+	    {
+	      if (TARGET_HPUX && !TARGET_DISABLE_FPREGS && !TARGET_SOFT_FLOAT
+		  && !strcmp (targetm.strip_name_encoding (XSTR (op, 0)),
+			      "powf"))
+		emit_call_insn (gen_call_val_powf (dst, op, nb));
+	      else
+		emit_call_insn (gen_call_val_symref (dst, op, nb));
+	    }
 	}
       else
 	{
@@ -7702,7 +7720,7 @@
     }
 
   DONE;
-}")
+})
 
 (define_insn "call_val_symref"
   [(set (match_operand 0 "" "")
@@ -7722,6 +7740,26 @@
 	(cond [(and (const_int 0) (eq (const_int 0) (pc))) (const_int 8)]
 	      (symbol_ref "pa_attr_length_call (insn, 0)")))])
 
+;; powf function clobbers %fr12
+(define_insn "call_val_powf"
+  [(set (match_operand 0 "" "")
+	(call (mem:SI (match_operand 1 "call_operand_address" ""))
+	      (match_operand 2 "" "i")))
+   (clobber (reg:SI 1))
+   (clobber (reg:SI 2))
+   (clobber (reg:DF 48))
+   (use (const_int 1))]
+  "TARGET_HPUX && !TARGET_PORTABLE_RUNTIME && !TARGET_64BIT"
+  "*
+{
+  pa_output_arg_descriptor (insn);
+  return pa_output_call (insn, operands[1], 0);
+}"
+  [(set_attr "type" "call")
+   (set (attr "length")
+	(cond [(and (const_int 0) (eq (const_int 0) (pc))) (const_int 8)]
+	      (symbol_ref "pa_attr_length_call (insn, 0)")))])
+
 (define_insn "call_val_symref_pic"
   [(set (match_operand 0 "" "")
 	(call (mem:SI (match_operand 1 "call_operand_address" ""))
@@ -7804,6 +7842,95 @@
 	(cond [(and (const_int 0) (eq (const_int 0) (pc))) (const_int 8)]
 	      (symbol_ref "pa_attr_length_call (insn, 0)")))])
 
+;; powf function clobbers %fr12
+(define_insn "call_val_powf_pic"
+  [(set (match_operand 0 "" "")
+	(call (mem:SI (match_operand 1 "call_operand_address" ""))
+	      (match_operand 2 "" "i")))
+   (clobber (reg:SI 1))
+   (clobber (reg:SI 2))
+   (clobber (reg:DF 48))
+   (clobber (match_operand 3))
+   (use (reg:SI 19))
+   (use (const_int 1))]
+  "TARGET_HPUX && !TARGET_PORTABLE_RUNTIME && !TARGET_64BIT"
+  "#")
+
+;; Split out the PIC register save and restore after reload.  As the
+;; split is done after reload, there are some situations in which we
+;; unnecessarily save and restore %r4.  This happens when there is a
+;; single call and the PIC register is not used after the call.
+;;
+;; The split has to be done since call_from_call_insn () can't handle
+;; the pattern as is.  Noreturn calls are special because they have to
+;; terminate the basic block.  The split has to contain more than one
+;; insn.
+(define_split
+  [(parallel [(set (match_operand 0 "" "")
+	      (call (mem:SI (match_operand 1 "call_operand_address" ""))
+		    (match_operand 2 "" "")))
+	      (clobber (reg:SI 1))
+	      (clobber (reg:SI 2))
+	      (clobber (reg:DF 48))
+	      (clobber (match_operand 3))
+	      (use (reg:SI 19))
+	      (use (const_int 1))])]
+  "TARGET_HPUX && !TARGET_PORTABLE_RUNTIME && !TARGET_64BIT && reload_completed
+   && find_reg_note (insn, REG_NORETURN, NULL_RTX)"
+  [(set (match_dup 3) (reg:SI 19))
+   (parallel [(set (match_dup 0)
+	      (call (mem:SI (match_dup 1))
+		    (match_dup 2)))
+	      (clobber (reg:SI 1))
+	      (clobber (reg:SI 2))
+	      (clobber (reg:DF 48))
+	      (use (reg:SI 19))
+	      (use (const_int 1))])]
+  "")
+
+(define_split
+  [(parallel [(set (match_operand 0 "" "")
+	      (call (mem:SI (match_operand 1 "call_operand_address" ""))
+		    (match_operand 2 "" "")))
+	      (clobber (reg:SI 1))
+	      (clobber (reg:SI 2))
+	      (clobber (reg:DF 48))
+	      (clobber (match_operand 3))
+	      (use (reg:SI 19))
+	      (use (const_int 1))])]
+  "TARGET_HPUX && !TARGET_PORTABLE_RUNTIME && !TARGET_64BIT && reload_completed"
+  [(set (match_dup 3) (reg:SI 19))
+   (parallel [(set (match_dup 0)
+	      (call (mem:SI (match_dup 1))
+		    (match_dup 2)))
+	      (clobber (reg:SI 1))
+	      (clobber (reg:SI 2))
+	      (clobber (reg:DF 48))
+	      (use (reg:SI 19))
+	      (use (const_int 1))])
+   (set (reg:SI 19) (match_dup 3))]
+  "")
+
+(define_insn "*call_val_powf_pic_post_reload"
+  [(set (match_operand 0 "" "")
+	(call (mem:SI (match_operand 1 "call_operand_address" ""))
+	      (match_operand 2 "" "i")))
+   (clobber (reg:SI 1))
+   (clobber (reg:SI 2))
+   (clobber (reg:DF 48))
+   (use (reg:SI 19))
+   (use (const_int 1))]
+  "TARGET_HPUX && !TARGET_PORTABLE_RUNTIME && !TARGET_64BIT"
+  "*
+{
+  pa_output_arg_descriptor (insn);
+  return pa_output_call (insn, operands[1], 0);
+}"
+  [(set_attr "type" "call")
+   (set (attr "length")
+	(cond [(and (const_int 0) (eq (const_int 0) (pc))) (const_int 8)]
+	      (symbol_ref "pa_attr_length_call (insn, 0)")))])
+
 ;; This pattern is split if it is necessary to save and restore the
 ;; PIC register.
 (define_insn "call_val_symref_64bit"
@@ -7894,6 +8021,101 @@
 	(cond [(and (const_int 0) (eq (const_int 0) (pc))) (const_int 8)]
 	      (symbol_ref "pa_attr_length_call (insn, 0)")))])
 
+;; powf function clobbers %fr12
+(define_insn "call_val_powf_64bit"
+  [(set (match_operand 0 "" "")
+	(call (mem:SI (match_operand 1 "call_operand_address" ""))
+	      (match_operand 2 "" "i")))
+   (clobber (reg:DI 1))
+   (clobber (reg:DI 2))
+   (clobber (reg:DF 40))
+   (clobber (match_operand 3))
+   (use (reg:DI 27))
+   (use (reg:DI 29))
+   (use (const_int 1))]
+  "TARGET_64BIT && TARGET_HPUX"
+  "#")
+
+;; Split out the PIC register save and restore after reload.  As the
+;; split is done after reload, there are some situations in which we
+;; unnecessarily save and restore %r4.  This happens when there is a
+;; single call and the PIC register is not used after the call.
+;;
+;; The split has to be done since call_from_call_insn () can't handle
+;; the pattern as is.  Noreturn calls are special because they have to
+;; terminate the basic block.  The split has to contain more than one
+;; insn.
+(define_split
+  [(parallel [(set (match_operand 0 "" "")
+	      (call (mem:SI (match_operand 1 "call_operand_address" ""))
+		    (match_operand 2 "" "")))
+	      (clobber (reg:DI 1))
+	      (clobber (reg:DI 2))
+	      (clobber (reg:DF 40))
+	      (clobber (match_operand 3))
+	      (use (reg:DI 27))
+	      (use (reg:DI 29))
+	      (use (const_int 1))])]
+  "TARGET_64BIT && TARGET_HPUX && reload_completed
+   && find_reg_note (insn, REG_NORETURN, NULL_RTX)"
+  [(set (match_dup 3) (reg:DI 27))
+   (parallel [(set (match_dup 0)
+	      (call (mem:SI (match_dup 1))
+		    (match_dup 2)))
+	      (clobber (reg:DI 1))
+	      (clobber (reg:DI 2))
+	      (clobber (reg:DF 40))
+	      (use (reg:DI 27))
+	      (use (reg:DI 29))
+	      (use (const_int 1))])]
+  "")
+
+(define_split
+  [(parallel [(set (match_operand 0 "" "")
+	      (call (mem:SI (match_operand 1 "call_operand_address" ""))
+		    (match_operand 2 "" "")))
+	      (clobber (reg:DI 1))
+	      (clobber (reg:DI 2))
+	      (clobber (reg:DF 40))
+	      (clobber (match_operand 3))
+	      (use (reg:DI 27))
+	      (use (reg:DI 29))
+	      (use (const_int 1))])]
+  "TARGET_64BIT && TARGET_HPUX && reload_completed"
+  [(set (match_dup 3) (reg:DI 27))
+   (parallel [(set (match_dup 0)
+	      (call (mem:SI (match_dup 1))
+		    (match_dup 2)))
+	      (clobber (reg:DI 1))
+	      (clobber (reg:DI 2))
+	      (clobber (reg:DF 40))
+	      (use (reg:DI 27))
+	      (use (reg:DI 29))
+	      (use (const_int 1))])
+   (set (reg:DI 27) (match_dup 3))]
+  "")
+
+(define_insn "*call_val_powf_64bit_post_reload"
+  [(set (match_operand 0 "" "")
+	(call (mem:SI (match_operand 1 "call_operand_address" ""))
+	      (match_operand 2 "" "i")))
+   (clobber (reg:DI 1))
+   (clobber (reg:DI 2))
+   (clobber (reg:DF 40))
+   (use (reg:DI 27))
+   (use (reg:DI 29))
+   (use (const_int 1))]
+  "TARGET_64BIT && TARGET_HPUX"
+  "*
+{
+  pa_output_arg_descriptor (insn);
+  return pa_output_call (insn, operands[1], 0);
+}"
+  [(set_attr "type" "call")
+   (set (attr "length")
+	(cond [(and (const_int 0) (eq (const_int 0) (pc))) (const_int 8)]
+	      (symbol_ref "pa_attr_length_call (insn, 0)")))])
+
 (define_insn "call_val_reg"
   [(set (match_operand 0 "" "")
 	(call (mem:SI (reg:SI 22))
Index: config/pa/pa.c
===================================================================
--- config/pa/pa.c	(revision 196546)
+++ config/pa/pa.c	(working copy)
@@ -10313,21 +10313,6 @@
 {
   int i;
 
-  if (TARGET_HPUX)
-    {
-      /* Work around powf bug in libm.  */
-      if (TARGET_64BIT)
-	{
-	  /* Mark %fr12 as call used.  */
-	  call_used_regs[40] = 1;
-	}
-      else
-	{
-	  /* Mark %fr12 and %fr12R as call used.  */
-	  call_used_regs[48] = 1;
-	  call_used_regs[49] = 1;
-	}
-    }
   if (!TARGET_64BIT && !TARGET_PA_11)
     {
       for (i = 56; i <= FP_REG_LAST; i++)

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2013-03-11  0:52 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-02-18 16:46 [committed] Work around bug in powf function on HP-UX John David Anglin
2013-03-11  0:52 ` John David Anglin

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).