From 9839edf18db53d249327cd6cc128112684d13dfd Mon Sep 17 00:00:00 2001 From: John David Anglin Date: Fri, 11 Jun 2004 22:46:13 +0000 Subject: [PATCH] pa.c (legitimize_pic_address): Use UNSPEC_DLTIND14R to identify unspec used for loading address from DLT. * pa.c (legitimize_pic_address): Use UNSPEC_DLTIND14R to identify unspec used for loading address from DLT. * pa.md: Define constants for the uses of UNSPEC and UNSPEC_VOLATILE. Change all users of UNSPEC and UNSPEC_VOLATILE to use new constants. Don't use short code sequence when loading the address of a nonlocal label. (nonlocal_goto): New expander. (indirect_goto): New jump pattern for nonlocal gotos. (short_jump): Remove extra whitespace. (builtin_longjmp): Clobber memory and hard frame pointer. Restore frame pointer via virtual_stack_vars_rtx when we have a nonlocal goto pattern. From-SVN: r83003 --- gcc/ChangeLog | 15 ++++++ gcc/config/pa/pa.c | 2 +- gcc/config/pa/pa.md | 117 +++++++++++++++++++++++++++++++++++++++----- 3 files changed, 122 insertions(+), 12 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 6533e7d6934..0a29cd904e6 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,18 @@ +2004-06-11 John David Anglin + + * pa.c (legitimize_pic_address): Use UNSPEC_DLTIND14R to identify + unspec used for loading address from DLT. + * pa.md: Define constants for the uses of UNSPEC and UNSPEC_VOLATILE. + Change all users of UNSPEC and UNSPEC_VOLATILE to use new constants. + Don't use short code sequence when loading the address of a nonlocal + label. + (nonlocal_goto): New expander. + (indirect_goto): New jump pattern for nonlocal gotos. + (short_jump): Remove extra whitespace. + (builtin_longjmp): Clobber memory and hard frame pointer. Restore + frame pointer via virtual_stack_vars_rtx when we have a nonlocal goto + pattern. + 2004-06-11 Roger Sayle * expmed.c (synth_mult): Add an additional MODE argument for the diff --git a/gcc/config/pa/pa.c b/gcc/config/pa/pa.c index d543f31b507..54030a23832 100644 --- a/gcc/config/pa/pa.c +++ b/gcc/config/pa/pa.c @@ -904,7 +904,7 @@ legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg) gen_rtx_LO_SUM (Pmode, tmp_reg, gen_rtx_UNSPEC (Pmode, gen_rtvec (1, orig), - 0))); + UNSPEC_DLTIND14R))); current_function_uses_pic_offset_table = 1; MEM_NOTRAP_P (pic_ref) = 1; diff --git a/gcc/config/pa/pa.md b/gcc/config/pa/pa.md index 646583cb3cb..23e5d513078 100644 --- a/gcc/config/pa/pa.md +++ b/gcc/config/pa/pa.md @@ -26,6 +26,25 @@ ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al. +;; Uses of UNSPEC in this file: + +(define_constants + [(UNSPEC_CFFC 0) ; canonicalize_funcptr_for_compare + (UNSPEC_GOTO 1) ; indirect_goto + (UNSPEC_DLTIND14R 2) ; + ]) + +;; UNSPEC_VOLATILE: + +(define_constants + [(UNSPECV_BLOCKAGE 0) ; blockage + (UNSPECV_DCACHE 1) ; dcacheflush + (UNSPECV_ICACHE 2) ; icacheflush + (UNSPECV_OPC 3) ; outline_prologue_call + (UNSPECV_OEC 4) ; outline_epilogue_call + (UNSPECV_LONGJMP 5) ; builtin_longjmp + ]) + ;; Insn type. Used to default other attribute values. ;; type "unary" insns have one input operand (1) and one output operand (0) @@ -2632,6 +2651,7 @@ /* If we're trying to load the address of a label that happens to be close, then we can use a shorter sequence. */ if (GET_CODE (operands[1]) == LABEL_REF + && !LABEL_REF_NONLOCAL_P (operands[1]) && INSN_ADDRESSES_SET_P () && abs (INSN_ADDRESSES (INSN_UID (XEXP (operands[1], 0))) - INSN_ADDRESSES (INSN_UID (insn))) < 8100) @@ -2666,6 +2686,7 @@ /* If we're trying to load the address of a label that happens to be close, then we can use a shorter sequence. */ if (GET_CODE (operands[1]) == LABEL_REF + && !LABEL_REF_NONLOCAL_P (operands[1]) && INSN_ADDRESSES_SET_P () && abs (INSN_ADDRESSES (INSN_UID (XEXP (operands[1], 0))) - INSN_ADDRESSES (INSN_UID (insn))) < 8100) @@ -6787,7 +6808,7 @@ (set_attr "length" "4")]) (define_insn "blockage" - [(unspec_volatile [(const_int 2)] 0)] + [(unspec_volatile [(const_int 2)] UNSPECV_BLOCKAGE)] "" "" [(set_attr "length" "0")]) @@ -6828,6 +6849,62 @@ [(set_attr "type" "branch") (set_attr "length" "4")]) +;;; An indirect jump can be optimized to a direct jump. GAS for the +;;; SOM target doesn't allow branching to a label inside a function. +;;; We also don't correctly compute branch distances for labels +;;; outside the current function. Thus, we use an indirect jump can't +;;; be optimized to a direct jump for all targets. We assume that +;;; the branch target is in the same space (i.e., nested function +;;; jumping to a label in an outer function in the same translation +;;; unit). +(define_expand "nonlocal_goto" + [(use (match_operand 0 "general_operand" "")) + (use (match_operand 1 "general_operand" "")) + (use (match_operand 2 "general_operand" "")) + (use (match_operand 3 "general_operand" ""))] + "" +{ + rtx lab = operands[1]; + rtx stack = operands[2]; + rtx fp = operands[3]; + + lab = copy_to_reg (lab); + + emit_insn (gen_rtx_CLOBBER (VOIDmode, + gen_rtx_MEM (BLKmode, + gen_rtx_SCRATCH (VOIDmode)))); + emit_insn (gen_rtx_CLOBBER (VOIDmode, + gen_rtx_MEM (BLKmode, + hard_frame_pointer_rtx))); + + /* Restore the frame pointer. The virtual_stack_vars_rtx is saved + instead of the hard_frame_pointer_rtx in the save area. As a + result, an extra instruction is needed to adjust for the offset + of the virtual stack variables and the frame pointer. */ + if (GET_CODE (fp) != REG) + fp = force_reg (Pmode, fp); + emit_move_insn (virtual_stack_vars_rtx, fp); + + emit_stack_restore (SAVE_NONLOCAL, stack, NULL_RTX); + + emit_insn (gen_rtx_USE (VOIDmode, hard_frame_pointer_rtx)); + emit_insn (gen_rtx_USE (VOIDmode, stack_pointer_rtx)); + + /* Nonlocal goto jumps are only used between functions in the same + translation unit. Thus, we can avoid the extra overhead of an + interspace jump. */ + emit_jump_insn (gen_indirect_goto (lab)); + emit_barrier (); + DONE; +}) + +(define_insn "indirect_goto" + [(unspec [(match_operand 0 "register_operand" "=r")] UNSPEC_GOTO)] + "GET_MODE (operands[0]) == word_mode" + "bv%* %%r0(%0)" + [(set_attr "type" "branch") + (set_attr "length" "4")]) + ;;; This jump is used in branch tables where the insn length is fixed. ;;; The length of this insn is adjusted if the delay slot is not filled. (define_insn "short_jump" @@ -8248,7 +8325,7 @@ add,l %2,%3,%3\;bv,n %%r0(%3)" [(set (pc) (match_operand 0 "pmode_register_operand" "a")) (clobber (reg:SI 2))] "!TARGET_64BIT" - "ldsid (%%sr0,%0),%%r2\; mtsp %%r2,%%sr0\; be%* 0(%%sr0,%0)" + "ldsid (%%sr0,%0),%%r2\;mtsp %%r2,%%sr0\;be%* 0(%%sr0,%0)" [(set_attr "type" "branch") (set_attr "length" "12")]) @@ -8261,7 +8338,7 @@ add,l %2,%3,%3\;bv,n %%r0(%3)" (set_attr "length" "4")]) (define_expand "builtin_longjmp" - [(unspec_volatile [(match_operand 0 "register_operand" "r")] 3)] + [(unspec_volatile [(match_operand 0 "register_operand" "r")] UNSPECV_LONGJMP)] "" " { @@ -8273,8 +8350,26 @@ add,l %2,%3,%3\;bv,n %%r0(%3)" (POINTER_SIZE * 2) / BITS_PER_UNIT)); rtx pv = gen_rtx_REG (Pmode, 1); + emit_insn (gen_rtx_CLOBBER (VOIDmode, + gen_rtx_MEM (BLKmode, + gen_rtx_SCRATCH (VOIDmode)))); + emit_insn (gen_rtx_CLOBBER (VOIDmode, + gen_rtx_MEM (BLKmode, + hard_frame_pointer_rtx))); + + /* Restore the frame pointer. The virtual_stack_vars_rtx is saved + instead of the hard_frame_pointer_rtx in the save area. We need + to adjust for the offset between these two values when we have + a nonlocal_goto pattern. When we don't have a nonlocal_goto + pattern, the receiver performs the adjustment. */ +#ifdef HAVE_nonlocal_goto + if (HAVE_nonlocal_goto) + emit_move_insn (virtual_stack_vars_rtx, force_reg (Pmode, fp)); + else +#endif + emit_move_insn (hard_frame_pointer_rtx, fp); + /* This bit is the same as expand_builtin_longjmp. */ - emit_move_insn (hard_frame_pointer_rtx, fp); emit_stack_restore (SAVE_NONLOCAL, stack, NULL_RTX); emit_insn (gen_rtx_USE (VOIDmode, hard_frame_pointer_rtx)); emit_insn (gen_rtx_USE (VOIDmode, stack_pointer_rtx)); @@ -8959,7 +9054,7 @@ add,l %2,%3,%3\;bv,n %%r0(%3)" ;; Operands 3 and 4 (icacheflush) are clobbered scratch registers. (define_insn "dcacheflush" [(const_int 1) - (unspec_volatile [(mem:BLK (scratch))] 0) + (unspec_volatile [(mem:BLK (scratch))] UNSPECV_DCACHE) (use (match_operand 0 "pmode_register_operand" "r")) (use (match_operand 1 "pmode_register_operand" "r")) (use (match_operand 2 "pmode_register_operand" "r")) @@ -8977,7 +9072,7 @@ add,l %2,%3,%3\;bv,n %%r0(%3)" (define_insn "icacheflush" [(const_int 2) - (unspec_volatile [(mem:BLK (scratch))] 0) + (unspec_volatile [(mem:BLK (scratch))] UNSPECV_ICACHE) (use (match_operand 0 "pmode_register_operand" "r")) (use (match_operand 1 "pmode_register_operand" "r")) (use (match_operand 2 "pmode_register_operand" "r")) @@ -8997,7 +9092,7 @@ add,l %2,%3,%3\;bv,n %%r0(%3)" ;; An out-of-line prologue. (define_insn "outline_prologue_call" - [(unspec_volatile [(const_int 0)] 0) + [(unspec_volatile [(const_int 0)] UNSPECV_OPC) (clobber (reg:SI 31)) (clobber (reg:SI 22)) (clobber (reg:SI 21)) @@ -9047,7 +9142,7 @@ add,l %2,%3,%3\;bv,n %%r0(%3)" ;; An out-of-line epilogue. (define_insn "outline_epilogue_call" - [(unspec_volatile [(const_int 1)] 0) + [(unspec_volatile [(const_int 1)] UNSPECV_OEC) (use (reg:SI 29)) (use (reg:SI 28)) (clobber (reg:SI 31)) @@ -9106,7 +9201,7 @@ add,l %2,%3,%3\;bv,n %%r0(%3)" ;; reliably compared to another function pointer. */ (define_expand "canonicalize_funcptr_for_compare" [(set (reg:SI 26) (match_operand:SI 1 "register_operand" "")) - (parallel [(set (reg:SI 29) (unspec:SI [(reg:SI 26)] 0)) + (parallel [(set (reg:SI 29) (unspec:SI [(reg:SI 26)] UNSPEC_CFFC)) (clobber (match_dup 2)) (clobber (reg:SI 26)) (clobber (reg:SI 22)) @@ -9136,8 +9231,8 @@ add,l %2,%3,%3\;bv,n %%r0(%3)" } }") -(define_insn "" - [(set (reg:SI 29) (unspec:SI [(reg:SI 26)] 0)) +(define_insn "*$$sh_func_adrs" + [(set (reg:SI 29) (unspec:SI [(reg:SI 26)] UNSPEC_CFFC)) (clobber (match_operand:SI 0 "register_operand" "=a")) (clobber (reg:SI 26)) (clobber (reg:SI 22))