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]

[committed] Fix bootstrap ICE on hppa64-hp-hpux11.11


This patch fixes an ICE introduced by the change to using the new IRA
register allocator on hppa64-hp-hpux11.11.  The main change is to revise
the PIC call patterns to avoid using a raw clobber of the non call
clobbered register r4 for the save and restore of the PIC register.
Instead, the patterns now explicitly expose the save of the PIC
register with a set, and the call .

The new patterns have to split after reload because the final pass
can't find the call in the patterns.  The noreturn case is special
as the PIC register can't be restored in that case.  The call has to
end the basic block.

Tested on hppa64-hp-hpux11.11, hppa2.0w-hp-hpux11.11 and hppa-unknown-linux-gnu
with no new regressions.  Committed to trunk.

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

2008-10-11  John David Anglin  <dave.anglin@nrc-cnrc.gc.ca>

	PR middle-end/37608
	* pa.md (call, call_value): Generate an rtx for register r4 and pass
	it to PIC call patterns.
	(call_symref_pic): Revise pattern to expose PIC register save.  Remove
	code generation and attributes from pattern.  Change peephole2 to split
	for noreturn case.  Revise split pattern for non noreturn case.
	(call_symref_64bit, call_reg_pic, call_reg_64bit, call_val_symref_pic,
	call_val_symref_64bit, call_val_reg_pic, call_val_reg_64bit): Likewise.
	* pa.c (attr_length_call): Simplify extraction of call rtx.  Add some
	asserts.

Index: config/pa/pa.md
===================================================================
--- config/pa/pa.md	(revision 140874)
+++ config/pa/pa.md	(working copy)
@@ -7669,19 +7669,20 @@
      need to have a use of the PIC register in the return pattern and
      the final save/restore operation is not needed.
      
-     I elected to just clobber %r4 in the PIC patterns and use it instead
+     I elected to just use register %r4 in the PIC patterns instead
      of trying to force hppa_pic_save_rtx () to a callee saved register.
      This might have required a new register class and constraint.  It
      was also simpler to just handle the restore from a register than a
      generic pseudo.  */
   if (TARGET_64BIT)
     {
+      rtx r4 = gen_rtx_REG (word_mode, 4);
       if (GET_CODE (op) == SYMBOL_REF)
-	call_insn = emit_call_insn (gen_call_symref_64bit (op, nb));
+	call_insn = emit_call_insn (gen_call_symref_64bit (op, nb, r4));
       else
 	{
 	  op = force_reg (word_mode, op);
-	  call_insn = emit_call_insn (gen_call_reg_64bit (op, nb));
+	  call_insn = emit_call_insn (gen_call_reg_64bit (op, nb, r4));
 	}
     }
   else
@@ -7689,17 +7690,22 @@
       if (GET_CODE (op) == SYMBOL_REF)
 	{
 	  if (flag_pic)
-	    call_insn = emit_call_insn (gen_call_symref_pic (op, nb));
+	    {
+	      rtx r4 = gen_rtx_REG (word_mode, 4);
+	      call_insn = emit_call_insn (gen_call_symref_pic (op, nb, r4));
+	    }
 	  else
 	    call_insn = emit_call_insn (gen_call_symref (op, nb));
 	}
       else
 	{
 	  rtx tmpreg = gen_rtx_REG (word_mode, 22);
-
 	  emit_move_insn (tmpreg, force_reg (word_mode, op));
 	  if (flag_pic)
-	    call_insn = emit_call_insn (gen_call_reg_pic (nb));
+	    {
+	      rtx r4 = gen_rtx_REG (word_mode, 4);
+	      call_insn = emit_call_insn (gen_call_reg_pic (nb, r4));
+	    }
 	  else
 	    call_insn = emit_call_insn (gen_call_reg (nb));
 	}
@@ -7754,69 +7760,64 @@
    (set (attr "length") (symbol_ref "attr_length_call (insn, 0)"))])
 
 (define_insn "call_symref_pic"
-  [(call (mem:SI (match_operand 0 "call_operand_address" ""))
+  [(set (match_operand:SI 2 "register_operand" "=&r") (reg:SI 19))
+   (call (mem:SI (match_operand 0 "call_operand_address" ""))
 	 (match_operand 1 "" "i"))
    (clobber (reg:SI 1))
    (clobber (reg:SI 2))
-   (clobber (reg:SI 4))
+   (use (match_dup 2))
    (use (reg:SI 19))
    (use (const_int 0))]
   "!TARGET_PORTABLE_RUNTIME && !TARGET_64BIT"
-  "*
-{
-  output_arg_descriptor (insn);
-  return output_call (insn, operands[0], 0);
-}"
-  [(set_attr "type" "call")
-   (set (attr "length")
-	(plus (symbol_ref "attr_length_call (insn, 0)")
-	      (symbol_ref "attr_length_save_restore_dltp (insn)")))])
+  "#")
 
-;; Split out the PIC register save and restore after reload.  This is
-;; done only if the function returns.  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 "dead" after the call.  This isn't easy to fix as the usage of
-;; the PIC register isn't completely determined until the reload pass.
+;; 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 [(call (mem:SI (match_operand 0 "call_operand_address" ""))
+  [(parallel [(set (match_operand:SI 2 "register_operand" "") (reg:SI 19))
+	      (call (mem:SI (match_operand 0 "call_operand_address" ""))
 		    (match_operand 1 "" ""))
 	      (clobber (reg:SI 1))
 	      (clobber (reg:SI 2))
-	      (clobber (reg:SI 4))
+	      (use (match_dup 2))
 	      (use (reg:SI 19))
 	      (use (const_int 0))])]
-  "!TARGET_PORTABLE_RUNTIME && !TARGET_64BIT
-   && reload_completed
-   && !find_reg_note (insn, REG_NORETURN, NULL_RTX)"
-  [(set (reg:SI 4) (reg:SI 19))
+  "!TARGET_PORTABLE_RUNTIME && !TARGET_64BIT && reload_completed
+   && find_reg_note (insn, REG_NORETURN, NULL_RTX)"
+  [(set (match_dup 2) (reg:SI 19))
    (parallel [(call (mem:SI (match_dup 0))
 		    (match_dup 1))
 	      (clobber (reg:SI 1))
 	      (clobber (reg:SI 2))
 	      (use (reg:SI 19))
-	      (use (const_int 0))])
-   (set (reg:SI 19) (reg:SI 4))]
+	      (use (const_int 0))])]
   "")
 
-;; Remove the clobber of register 4 when optimizing.  This has to be
-;; done with a peephole optimization rather than a split because the
-;; split sequence for a call must be longer than one instruction.
-(define_peephole2
-  [(parallel [(call (mem:SI (match_operand 0 "call_operand_address" ""))
+(define_split
+  [(parallel [(set (match_operand:SI 2 "register_operand" "") (reg:SI 19))
+	      (call (mem:SI (match_operand 0 "call_operand_address" ""))
 		    (match_operand 1 "" ""))
 	      (clobber (reg:SI 1))
 	      (clobber (reg:SI 2))
-	      (clobber (reg:SI 4))
+	      (use (match_dup 2))
 	      (use (reg:SI 19))
 	      (use (const_int 0))])]
   "!TARGET_PORTABLE_RUNTIME && !TARGET_64BIT && reload_completed"
-  [(parallel [(call (mem:SI (match_dup 0))
+  [(set (match_dup 2) (reg:SI 19))
+   (parallel [(call (mem:SI (match_dup 0))
 		    (match_dup 1))
 	      (clobber (reg:SI 1))
 	      (clobber (reg:SI 2))
 	      (use (reg:SI 19))
-	      (use (const_int 0))])]
+	      (use (const_int 0))])
+   (set (reg:SI 19) (match_dup 2))]
   "")
 
 (define_insn "*call_symref_pic_post_reload"
@@ -7838,74 +7839,69 @@
 ;; This pattern is split if it is necessary to save and restore the
 ;; PIC register.
 (define_insn "call_symref_64bit"
-  [(call (mem:SI (match_operand 0 "call_operand_address" ""))
+  [(set (match_operand:DI 2 "register_operand" "=&r") (reg:DI 27))
+   (call (mem:SI (match_operand 0 "call_operand_address" ""))
 	 (match_operand 1 "" "i"))
    (clobber (reg:DI 1))
    (clobber (reg:DI 2))
-   (clobber (reg:DI 4))
+   (use (match_dup 2))
    (use (reg:DI 27))
    (use (reg:DI 29))
    (use (const_int 0))]
   "TARGET_64BIT"
-  "*
-{
-  output_arg_descriptor (insn);
-  return output_call (insn, operands[0], 0);
-}"
-  [(set_attr "type" "call")
-   (set (attr "length")
-	(plus (symbol_ref "attr_length_call (insn, 0)")
-	      (symbol_ref "attr_length_save_restore_dltp (insn)")))])
+  "#")
 
-;; Split out the PIC register save and restore after reload.  This is
-;; done only if the function returns.  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 "dead" after the call.  This isn't easy to fix as the usage of
-;; the PIC register isn't completely determined until the reload pass.
+;; 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 [(call (mem:SI (match_operand 0 "call_operand_address" ""))
+  [(parallel [(set (match_operand:DI 2 "register_operand" "") (reg:DI 27))
+	      (call (mem:SI (match_operand 0 "call_operand_address" ""))
 		    (match_operand 1 "" ""))
 	      (clobber (reg:DI 1))
 	      (clobber (reg:DI 2))
-	      (clobber (reg:DI 4))
+	      (use (match_dup 2))
 	      (use (reg:DI 27))
 	      (use (reg:DI 29))
 	      (use (const_int 0))])]
-  "TARGET_64BIT
-   && reload_completed
-   && !find_reg_note (insn, REG_NORETURN, NULL_RTX)"
-  [(set (reg:DI 4) (reg:DI 27))
+  "TARGET_64BIT && reload_completed
+   && find_reg_note (insn, REG_NORETURN, NULL_RTX)"
+  [(set (match_dup 2) (reg:DI 27))
    (parallel [(call (mem:SI (match_dup 0))
 		    (match_dup 1))
 	      (clobber (reg:DI 1))
 	      (clobber (reg:DI 2))
 	      (use (reg:DI 27))
 	      (use (reg:DI 29))
-	      (use (const_int 0))])
-   (set (reg:DI 27) (reg:DI 4))]
+	      (use (const_int 0))])]
   "")
 
-;; Remove the clobber of register 4 when optimizing.  This has to be
-;; done with a peephole optimization rather than a split because the
-;; split sequence for a call must be longer than one instruction.
-(define_peephole2
-  [(parallel [(call (mem:SI (match_operand 0 "call_operand_address" ""))
+(define_split
+  [(parallel [(set (match_operand:DI 2 "register_operand" "") (reg:DI 27))
+	      (call (mem:SI (match_operand 0 "call_operand_address" ""))
 		    (match_operand 1 "" ""))
 	      (clobber (reg:DI 1))
 	      (clobber (reg:DI 2))
-	      (clobber (reg:DI 4))
+	      (use (match_dup 2))
 	      (use (reg:DI 27))
 	      (use (reg:DI 29))
 	      (use (const_int 0))])]
   "TARGET_64BIT && reload_completed"
-  [(parallel [(call (mem:SI (match_dup 0))
+  [(set (match_dup 2) (reg:DI 27))
+   (parallel [(call (mem:SI (match_dup 0))
 		    (match_dup 1))
 	      (clobber (reg:DI 1))
 	      (clobber (reg:DI 2))
 	      (use (reg:DI 27))
 	      (use (reg:DI 29))
-	      (use (const_int 0))])]
+	      (use (const_int 0))])
+   (set (reg:DI 27) (match_dup 2))]
   "")
 
 (define_insn "*call_symref_64bit_post_reload"
@@ -7942,68 +7938,64 @@
 ;; This pattern is split if it is necessary to save and restore the
 ;; PIC register.
 (define_insn "call_reg_pic"
-  [(call (mem:SI (reg:SI 22))
+  [(set (match_operand:SI 1 "register_operand" "=&r") (reg:SI 19))
+   (call (mem:SI (reg:SI 22))
 	 (match_operand 0 "" "i"))
    (clobber (reg:SI 1))
    (clobber (reg:SI 2))
-   (clobber (reg:SI 4))
+   (use (match_dup 1))
    (use (reg:SI 19))
    (use (const_int 1))]
   "!TARGET_64BIT"
-  "*
-{
-  return output_indirect_call (insn, gen_rtx_REG (word_mode, 22));
-}"
-  [(set_attr "type" "dyncall")
-   (set (attr "length")
-	(plus (symbol_ref "attr_length_indirect_call (insn)")
-	      (symbol_ref "attr_length_save_restore_dltp (insn)")))])
+  "#")
 
-;; Split out the PIC register save and restore after reload.  This is
-;; done only if the function returns.  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 "dead" after the call.  This isn't easy to fix as the usage of
-;; the PIC register isn't completely determined until the reload pass.
+;; 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 [(call (mem:SI (reg:SI 22))
+  [(parallel [(set (match_operand:SI 1 "register_operand" "") (reg:SI 19))
+	      (call (mem:SI (reg:SI 22))
 		    (match_operand 0 "" ""))
 	      (clobber (reg:SI 1))
 	      (clobber (reg:SI 2))
-	      (clobber (reg:SI 4))
+	      (use (match_dup 1))
 	      (use (reg:SI 19))
 	      (use (const_int 1))])]
-  "!TARGET_64BIT
-   && reload_completed
-   && !find_reg_note (insn, REG_NORETURN, NULL_RTX)"
-  [(set (reg:SI 4) (reg:SI 19))
+  "!TARGET_64BIT && reload_completed
+   && find_reg_note (insn, REG_NORETURN, NULL_RTX)"
+  [(set (match_dup 1) (reg:SI 19))
    (parallel [(call (mem:SI (reg:SI 22))
 		    (match_dup 0))
 	      (clobber (reg:SI 1))
 	      (clobber (reg:SI 2))
 	      (use (reg:SI 19))
-	      (use (const_int 1))])
-   (set (reg:SI 19) (reg:SI 4))]
+	      (use (const_int 1))])]
   "")
 
-;; Remove the clobber of register 4 when optimizing.  This has to be
-;; done with a peephole optimization rather than a split because the
-;; split sequence for a call must be longer than one instruction.
-(define_peephole2
-  [(parallel [(call (mem:SI (reg:SI 22))
+(define_split
+  [(parallel [(set (match_operand:SI 1 "register_operand" "") (reg:SI 19))
+	      (call (mem:SI (reg:SI 22))
 		    (match_operand 0 "" ""))
 	      (clobber (reg:SI 1))
 	      (clobber (reg:SI 2))
-	      (clobber (reg:SI 4))
+	      (use (match_dup 1))
 	      (use (reg:SI 19))
 	      (use (const_int 1))])]
   "!TARGET_64BIT && reload_completed"
-  [(parallel [(call (mem:SI (reg:SI 22))
+  [(set (match_dup 1) (reg:SI 19))
+   (parallel [(call (mem:SI (reg:SI 22))
 		    (match_dup 0))
 	      (clobber (reg:SI 1))
 	      (clobber (reg:SI 2))
 	      (use (reg:SI 19))
-	      (use (const_int 1))])]
+	      (use (const_int 1))])
+   (set (reg:SI 19) (match_dup 1))]
   "")
 
 (define_insn "*call_reg_pic_post_reload"
@@ -8024,73 +8016,75 @@
 ;; This pattern is split if it is necessary to save and restore the
 ;; PIC register.
 (define_insn "call_reg_64bit"
-  [(call (mem:SI (match_operand:DI 0 "register_operand" "r"))
+  [(set (match_operand:DI 2 "register_operand" "=&r") (reg:DI 27))
+   (call (mem:SI (match_operand:DI 0 "register_operand" "r"))
 	 (match_operand 1 "" "i"))
+   (clobber (reg:DI 1))
    (clobber (reg:DI 2))
-   (clobber (reg:DI 4))
+   (use (match_dup 2))
    (use (reg:DI 27))
    (use (reg:DI 29))
    (use (const_int 1))]
   "TARGET_64BIT"
-  "*
-{
-  return output_indirect_call (insn, operands[0]);
-}"
-  [(set_attr "type" "dyncall")
-   (set (attr "length")
-	(plus (symbol_ref "attr_length_indirect_call (insn)")
-	      (symbol_ref "attr_length_save_restore_dltp (insn)")))])
+  "#")
 
-;; Split out the PIC register save and restore after reload.  This is
-;; done only if the function returns.  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 "dead" after the call.  This isn't easy to fix as the usage of
-;; the PIC register isn't completely determined until the reload pass.
+;; 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 [(call (mem:SI (match_operand 0 "register_operand" ""))
+  [(parallel [(set (match_operand:DI 2 "register_operand" "") (reg:DI 27))
+	      (call (mem:SI (match_operand 0 "register_operand" ""))
 		    (match_operand 1 "" ""))
+	      (clobber (reg:DI 1))
 	      (clobber (reg:DI 2))
-	      (clobber (reg:DI 4))
+	      (use (match_dup 2))
 	      (use (reg:DI 27))
 	      (use (reg:DI 29))
 	      (use (const_int 1))])]
-  "TARGET_64BIT
-   && reload_completed
-   && !find_reg_note (insn, REG_NORETURN, NULL_RTX)"
-  [(set (reg:DI 4) (reg:DI 27))
+  "TARGET_64BIT && reload_completed
+   && find_reg_note (insn, REG_NORETURN, NULL_RTX)"
+  [(set (match_dup 2) (reg:DI 27))
    (parallel [(call (mem:SI (match_dup 0))
 		    (match_dup 1))
+	      (clobber (reg:DI 1))
 	      (clobber (reg:DI 2))
 	      (use (reg:DI 27))
 	      (use (reg:DI 29))
-	      (use (const_int 1))])
-   (set (reg:DI 27) (reg:DI 4))]
+	      (use (const_int 1))])]
   "")
 
-;; Remove the clobber of register 4 when optimizing.  This has to be
-;; done with a peephole optimization rather than a split because the
-;; split sequence for a call must be longer than one instruction.
-(define_peephole2
-  [(parallel [(call (mem:SI (match_operand 0 "register_operand" ""))
+(define_split
+  [(parallel [(set (match_operand:DI 2 "register_operand" "") (reg:DI 27))
+	      (call (mem:SI (match_operand 0 "register_operand" ""))
 		    (match_operand 1 "" ""))
+	      (clobber (reg:DI 1))
 	      (clobber (reg:DI 2))
-	      (clobber (reg:DI 4))
+	      (use (match_dup 2))
 	      (use (reg:DI 27))
 	      (use (reg:DI 29))
 	      (use (const_int 1))])]
   "TARGET_64BIT && reload_completed"
-  [(parallel [(call (mem:SI (match_dup 0))
+  [(set (match_dup 2) (reg:DI 27))
+   (parallel [(call (mem:SI (match_dup 0))
 		    (match_dup 1))
+	      (clobber (reg:DI 1))
 	      (clobber (reg:DI 2))
 	      (use (reg:DI 27))
 	      (use (reg:DI 29))
-	      (use (const_int 1))])]
+	      (use (const_int 1))])
+   (set (reg:DI 27) (match_dup 2))]
   "")
 
 (define_insn "*call_reg_64bit_post_reload"
   [(call (mem:SI (match_operand:DI 0 "register_operand" "r"))
 	 (match_operand 1 "" "i"))
+   (clobber (reg:DI 1))
    (clobber (reg:DI 2))
    (use (reg:DI 27))
    (use (reg:DI 29))
@@ -8168,19 +8162,22 @@
      need to have a use of the PIC register in the return pattern and
      the final save/restore operation is not needed.
      
-     I elected to just clobber %r4 in the PIC patterns and use it instead
+     I elected to just use register %r4 in the PIC patterns instead
      of trying to force hppa_pic_save_rtx () to a callee saved register.
      This might have required a new register class and constraint.  It
      was also simpler to just handle the restore from a register than a
      generic pseudo.  */
   if (TARGET_64BIT)
     {
+      rtx r4 = gen_rtx_REG (word_mode, 4);
       if (GET_CODE (op) == SYMBOL_REF)
-	call_insn = emit_call_insn (gen_call_val_symref_64bit (dst, op, nb));
+	call_insn
+	  = emit_call_insn (gen_call_val_symref_64bit (dst, op, nb, r4));
       else
 	{
 	  op = force_reg (word_mode, op);
-	  call_insn = emit_call_insn (gen_call_val_reg_64bit (dst, op, nb));
+	  call_insn
+	    = emit_call_insn (gen_call_val_reg_64bit (dst, op, nb, r4));
 	}
     }
   else
@@ -8188,17 +8185,23 @@
       if (GET_CODE (op) == SYMBOL_REF)
 	{
 	  if (flag_pic)
-	    call_insn = emit_call_insn (gen_call_val_symref_pic (dst, op, nb));
+	    {
+	      rtx r4 = gen_rtx_REG (word_mode, 4);
+	      call_insn
+		= emit_call_insn (gen_call_val_symref_pic (dst, op, nb, r4));
+	    }
 	  else
 	    call_insn = emit_call_insn (gen_call_val_symref (dst, op, nb));
 	}
       else
 	{
 	  rtx tmpreg = gen_rtx_REG (word_mode, 22);
-
 	  emit_move_insn (tmpreg, force_reg (word_mode, op));
 	  if (flag_pic)
-	    call_insn = emit_call_insn (gen_call_val_reg_pic (dst, nb));
+	    {
+	      rtx r4 = gen_rtx_REG (word_mode, 4);
+	      call_insn = emit_call_insn (gen_call_val_reg_pic (dst, nb, r4));
+	    }
 	  else
 	    call_insn = emit_call_insn (gen_call_val_reg (dst, nb));
 	}
@@ -8224,74 +8227,69 @@
    (set (attr "length") (symbol_ref "attr_length_call (insn, 0)"))])
 
 (define_insn "call_val_symref_pic"
-  [(set (match_operand 0 "" "")
+  [(set (match_operand:SI 3 "register_operand" "=&r") (reg:SI 19))
+   (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:SI 4))
+   (use (match_dup 3))
    (use (reg:SI 19))
    (use (const_int 0))]
   "!TARGET_PORTABLE_RUNTIME && !TARGET_64BIT"
-  "*
-{
-  output_arg_descriptor (insn);
-  return output_call (insn, operands[1], 0);
-}"
-  [(set_attr "type" "call")
-   (set (attr "length")
-	(plus (symbol_ref "attr_length_call (insn, 0)")
-	      (symbol_ref "attr_length_save_restore_dltp (insn)")))])
+  "#")
 
-;; Split out the PIC register save and restore after reload.  This is
-;; done only if the function returns.  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 "dead" after the call.  This isn't easy to fix as the usage of
-;; the PIC register isn't completely determined until the reload pass.
+;; 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 "" "")
+  [(parallel [(set (match_operand:SI 3 "register_operand" "") (reg:SI 19))
+	      (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:SI 4))
+	      (use (match_dup 3))
 	      (use (reg:SI 19))
 	      (use (const_int 0))])]
-  "!TARGET_PORTABLE_RUNTIME && !TARGET_64BIT
-   && reload_completed
-   && !find_reg_note (insn, REG_NORETURN, NULL_RTX)"
-  [(set (reg:SI 4) (reg:SI 19))
+  "!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))
 	      (use (reg:SI 19))
-	      (use (const_int 0))])
-   (set (reg:SI 19) (reg:SI 4))]
+	      (use (const_int 0))])]
   "")
 
-;; Remove the clobber of register 4 when optimizing.  This has to be
-;; done with a peephole optimization rather than a split because the
-;; split sequence for a call must be longer than one instruction.
-(define_peephole2
-  [(parallel [(set (match_operand 0 "" "")
+(define_split
+  [(parallel [(set (match_operand:SI 3 "register_operand" "") (reg:SI 19))
+	      (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:SI 4))
+	      (use (match_dup 3))
 	      (use (reg:SI 19))
 	      (use (const_int 0))])]
   "!TARGET_PORTABLE_RUNTIME && !TARGET_64BIT && reload_completed"
-  [(parallel [(set (match_dup 0)
+  [(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))
 	      (use (reg:SI 19))
-	      (use (const_int 0))])]
+	      (use (const_int 0))])
+   (set (reg:SI 19) (match_dup 3))]
   "")
 
 (define_insn "*call_val_symref_pic_post_reload"
@@ -8314,46 +8312,42 @@
 ;; This pattern is split if it is necessary to save and restore the
 ;; PIC register.
 (define_insn "call_val_symref_64bit"
-  [(set (match_operand 0 "" "")
+  [(set (match_operand:DI 3 "register_operand" "=&r") (reg:DI 27))
+   (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:DI 4))
+   (use (match_dup 3))
    (use (reg:DI 27))
    (use (reg:DI 29))
    (use (const_int 0))]
   "TARGET_64BIT"
-  "*
-{
-  output_arg_descriptor (insn);
-  return output_call (insn, operands[1], 0);
-}"
-  [(set_attr "type" "call")
-   (set (attr "length")
-	(plus (symbol_ref "attr_length_call (insn, 0)")
-	      (symbol_ref "attr_length_save_restore_dltp (insn)")))])
+  "#")
 
-;; Split out the PIC register save and restore after reload.  This is
-;; done only if the function returns.  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 "dead" after the call.  This isn't easy to fix as the usage of
-;; the PIC register isn't completely determined until the reload pass.
+;; 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 "" "")
+  [(parallel [(set (match_operand:DI 3 "register_operand" "") (reg:DI 27))
+	      (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:DI 4))
+	      (use (match_dup 3))
 	      (use (reg:DI 27))
 	      (use (reg:DI 29))
 	      (use (const_int 0))])]
-  "TARGET_64BIT
-   && reload_completed
-   && !find_reg_note (insn, REG_NORETURN, NULL_RTX)"
-  [(set (reg:DI 4) (reg:DI 27))
+  "TARGET_64BIT && 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)))
@@ -8361,32 +8355,31 @@
 	      (clobber (reg:DI 2))
 	      (use (reg:DI 27))
 	      (use (reg:DI 29))
-	      (use (const_int 0))])
-   (set (reg:DI 27) (reg:DI 4))]
+	      (use (const_int 0))])]
   "")
 
-;; Remove the clobber of register 4 when optimizing.  This has to be
-;; done with a peephole optimization rather than a split because the
-;; split sequence for a call must be longer than one instruction.
-(define_peephole2
-  [(parallel [(set (match_operand 0 "" "")
+(define_split
+  [(parallel [(set (match_operand:DI 3 "register_operand" "") (reg:DI 27))
+	      (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:DI 4))
+	      (use (match_dup 3))
 	      (use (reg:DI 27))
 	      (use (reg:DI 29))
 	      (use (const_int 0))])]
   "TARGET_64BIT && reload_completed"
-  [(parallel [(set (match_dup 0)
+  [(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))
 	      (use (reg:DI 27))
 	      (use (reg:DI 29))
-	      (use (const_int 0))])]
+	      (use (const_int 0))])
+   (set (reg:DI 27) (match_dup 3))]
   "")
 
 (define_insn "*call_val_symref_64bit_post_reload"
@@ -8425,73 +8418,69 @@
 ;; This pattern is split if it is necessary to save and restore the
 ;; PIC register.
 (define_insn "call_val_reg_pic"
-  [(set (match_operand 0 "" "")
+  [(set (match_operand:SI 2 "register_operand" "=&r") (reg:SI 19))
+   (set (match_operand 0 "" "")
 	(call (mem:SI (reg:SI 22))
 	      (match_operand 1 "" "i")))
    (clobber (reg:SI 1))
    (clobber (reg:SI 2))
-   (clobber (reg:SI 4))
+   (use (match_dup 2))
    (use (reg:SI 19))
    (use (const_int 1))]
   "!TARGET_64BIT"
-  "*
-{
-  return output_indirect_call (insn, gen_rtx_REG (word_mode, 22));
-}"
-  [(set_attr "type" "dyncall")
-   (set (attr "length")
-	(plus (symbol_ref "attr_length_indirect_call (insn)")
-	      (symbol_ref "attr_length_save_restore_dltp (insn)")))])
+  "#")
 
-;; Split out the PIC register save and restore after reload.  This is
-;; done only if the function returns.  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 "dead" after the call.  This isn't easy to fix as the usage of
-;; the PIC register isn't completely determined until the reload pass.
+;; 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 "" "")
+  [(parallel [(set (match_operand:SI 2 "register_operand" "") (reg:SI 19))
+	      (set (match_operand 0 "" "")
 		   (call (mem:SI (reg:SI 22))
 			 (match_operand 1 "" "")))
 	      (clobber (reg:SI 1))
 	      (clobber (reg:SI 2))
-	      (clobber (reg:SI 4))
+	      (use (match_dup 2))
 	      (use (reg:SI 19))
 	      (use (const_int 1))])]
-  "!TARGET_64BIT
-   && reload_completed
-   && !find_reg_note (insn, REG_NORETURN, NULL_RTX)"
-  [(set (reg:SI 4) (reg:SI 19))
+  "!TARGET_64BIT && reload_completed
+   && find_reg_note (insn, REG_NORETURN, NULL_RTX)"
+  [(set (match_dup 2) (reg:SI 19))
    (parallel [(set (match_dup 0)
 		   (call (mem:SI (reg:SI 22))
 			 (match_dup 1)))
 	      (clobber (reg:SI 1))
 	      (clobber (reg:SI 2))
 	      (use (reg:SI 19))
-	      (use (const_int 1))])
-   (set (reg:SI 19) (reg:SI 4))]
+	      (use (const_int 1))])]
   "")
 
-;; Remove the clobber of register 4 when optimizing.  This has to be
-;; done with a peephole optimization rather than a split because the
-;; split sequence for a call must be longer than one instruction.
-(define_peephole2
-  [(parallel [(set (match_operand 0 "" "")
+(define_split
+  [(parallel [(set (match_operand:SI 2 "register_operand" "") (reg:SI 19))
+	      (set (match_operand 0 "" "")
 		   (call (mem:SI (reg:SI 22))
 			 (match_operand 1 "" "")))
 	      (clobber (reg:SI 1))
 	      (clobber (reg:SI 2))
-	      (clobber (reg:SI 4))
+	      (use (match_dup 2))
 	      (use (reg:SI 19))
 	      (use (const_int 1))])]
   "!TARGET_64BIT && reload_completed"
-  [(parallel [(set (match_dup 0)
+  [(set (match_dup 2) (reg:SI 19))
+   (parallel [(set (match_dup 0)
 		   (call (mem:SI (reg:SI 22))
 			 (match_dup 1)))
 	      (clobber (reg:SI 1))
 	      (clobber (reg:SI 2))
 	      (use (reg:SI 19))
-	      (use (const_int 1))])]
+	      (use (const_int 1))])
+   (set (reg:SI 19) (match_dup 2))]
   "")
 
 (define_insn "*call_val_reg_pic_post_reload"
@@ -8513,79 +8502,81 @@
 ;; This pattern is split if it is necessary to save and restore the
 ;; PIC register.
 (define_insn "call_val_reg_64bit"
-  [(set (match_operand 0 "" "")
+  [(set (match_operand:DI 3 "register_operand" "=&r") (reg:DI 27))
+   (set (match_operand 0 "" "")
 	(call (mem:SI (match_operand:DI 1 "register_operand" "r"))
 	      (match_operand 2 "" "i")))
+   (clobber (reg:DI 1))
    (clobber (reg:DI 2))
-   (clobber (reg:DI 4))
+   (use (match_dup 3))
    (use (reg:DI 27))
    (use (reg:DI 29))
    (use (const_int 1))]
   "TARGET_64BIT"
-  "*
-{
-  return output_indirect_call (insn, operands[1]);
-}"
-  [(set_attr "type" "dyncall")
-   (set (attr "length")
-	(plus (symbol_ref "attr_length_indirect_call (insn)")
-	      (symbol_ref "attr_length_save_restore_dltp (insn)")))])
+  "#")
 
-;; Split out the PIC register save and restore after reload.  This is
-;; done only if the function returns.  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 "dead" after the call.  This isn't easy to fix as the usage of
-;; the PIC register isn't completely determined until the reload pass.
+;; 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 "" "")
+  [(parallel [(set (match_operand:DI 3 "register_operand" "") (reg:DI 27))
+	      (set (match_operand 0 "" "")
 		   (call (mem:SI (match_operand:DI 1 "register_operand" ""))
 			 (match_operand 2 "" "")))
+	      (clobber (reg:DI 1))
 	      (clobber (reg:DI 2))
-	      (clobber (reg:DI 4))
+	      (use (match_dup 3))
 	      (use (reg:DI 27))
 	      (use (reg:DI 29))
 	      (use (const_int 1))])]
-  "TARGET_64BIT
-   && reload_completed
-   && !find_reg_note (insn, REG_NORETURN, NULL_RTX)"
-  [(set (reg:DI 4) (reg:DI 27))
+  "TARGET_64BIT && 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))
 	      (use (reg:DI 27))
 	      (use (reg:DI 29))
-	      (use (const_int 1))])
-   (set (reg:DI 27) (reg:DI 4))]
+	      (use (const_int 1))])]
   "")
 
-;; Remove the clobber of register 4 when optimizing.  This has to be
-;; done with a peephole optimization rather than a split because the
-;; split sequence for a call must be longer than one instruction.
-(define_peephole2
-  [(parallel [(set (match_operand 0 "" "")
+(define_split
+  [(parallel [(set (match_operand:DI 3 "register_operand" "") (reg:DI 27))
+	      (set (match_operand 0 "" "")
 		   (call (mem:SI (match_operand:DI 1 "register_operand" ""))
 			 (match_operand 2 "" "")))
+	      (clobber (reg:DI 1))
 	      (clobber (reg:DI 2))
-	      (clobber (reg:DI 4))
+	      (use (match_dup 3))
 	      (use (reg:DI 27))
 	      (use (reg:DI 29))
 	      (use (const_int 1))])]
   "TARGET_64BIT && reload_completed"
-  [(parallel [(set (match_dup 0)
+  [(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))
 	      (use (reg:DI 27))
 	      (use (reg:DI 29))
-	      (use (const_int 1))])]
+	      (use (const_int 1))])
+   (set (reg:DI 27) (match_dup 3))]
   "")
 
 (define_insn "*call_val_reg_64bit_post_reload"
   [(set (match_operand 0 "" "")
 	(call (mem:SI (match_operand:DI 1 "register_operand" "r"))
 	      (match_operand 2 "" "i")))
+   (clobber (reg:DI 1))
    (clobber (reg:DI 2))
    (use (reg:DI 27))
    (use (reg:DI 29))
Index: config/pa/pa.c
===================================================================
--- config/pa/pa.c	(revision 140874)
+++ config/pa/pa.c	(working copy)
@@ -7377,12 +7377,14 @@
 attr_length_call (rtx insn, int sibcall)
 {
   int local_call;
-  rtx call_dest;
+  rtx call, call_dest;
   tree call_decl;
   int length = 0;
   rtx pat = PATTERN (insn);
   unsigned long distance = -1;
 
+  gcc_assert (GET_CODE (insn) == CALL_INSN);
+
   if (INSN_ADDRESSES_SET_P ())
     {
       unsigned long total;
@@ -7393,12 +7395,17 @@
 	distance = -1;
     }
 
+  gcc_assert (GET_CODE (pat) == PARALLEL);
+
+  /* Get the call rtx.  */
+  call = XVECEXP (pat, 0, 0);
+  if (GET_CODE (call) == SET)
+    call = SET_SRC (call);
+
+  gcc_assert (GET_CODE (call) == CALL);
+
   /* Determine if this is a local call.  */
-  if (GET_CODE (XVECEXP (pat, 0, 0)) == CALL)
-    call_dest = XEXP (XEXP (XVECEXP (pat, 0, 0), 0), 0);
-  else
-    call_dest = XEXP (XEXP (XEXP (XVECEXP (pat, 0, 0), 1), 0), 0);
-
+  call_dest = XEXP (XEXP (call, 0), 0);
   call_decl = SYMBOL_REF_DECL (call_dest);
   local_call = call_decl && targetm.binds_local_p (call_decl);
 


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