summaryrefslogtreecommitdiff
path: root/gcc/config/pa
diff options
context:
space:
mode:
authordanglin <danglin@138bc75d-0d04-0410-961f-82ee72b054a4>2013-03-11 00:44:28 +0000
committerdanglin <danglin@138bc75d-0d04-0410-961f-82ee72b054a4>2013-03-11 00:44:28 +0000
commita1fcab4cba2eae8ad2c41fb2ce6361c8f8c6c598 (patch)
tree332a3049038409c188e3f806a37cd4933763d755 /gcc/config/pa
parentc25479685a75b98900649fbd73a65fec0e451b20 (diff)
downloadgcc-a1fcab4cba2eae8ad2c41fb2ce6361c8f8c6c598.tar.gz
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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@196588 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/config/pa')
-rw-r--r--gcc/config/pa/pa.c15
-rw-r--r--gcc/config/pa/pa.md232
2 files changed, 227 insertions, 20 deletions
diff --git a/gcc/config/pa/pa.c b/gcc/config/pa/pa.c
index 7816eeb54e4..0d39483d908 100644
--- a/gcc/config/pa/pa.c
+++ b/gcc/config/pa/pa.c
@@ -10313,21 +10313,6 @@ pa_conditional_register_usage (void)
{
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++)
diff --git a/gcc/config/pa/pa.md b/gcc/config/pa/pa.md
index d5696e908e0..5e6d5652e71 100644
--- a/gcc/config/pa/pa.md
+++ b/gcc/config/pa/pa.md
@@ -7600,7 +7600,6 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
(match_operand 2 "" "")))
(clobber (reg:SI 2))])]
""
- "
{
rtx op;
rtx dst = operands[0];
@@ -7668,7 +7667,13 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
{
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 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
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 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
}
DONE;
-}")
+})
(define_insn "call_val_symref"
[(set (match_operand 0 "" "")
@@ -7722,6 +7740,26 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
(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 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
(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 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
(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))