From 6bb36601f1c5a8f758f29523d514f9e27ee711f8 Mon Sep 17 00:00:00 2001 From: Jeff Law Date: Thu, 10 Nov 1994 21:33:43 -0700 Subject: [PATCH] * PA PIC support. * pa.c (secondary_reload_class): Refine. Readonly data needs a secondary reload only during PIC generation. Loading a floating point register with a constant requires a register from R1_REGS during -fPIC code generation. (read_only_operand): Constant pool entries are no longer read only during PIC code generation. (hppa_legitimize_address): If flag_pic is nonzero, then immediately call legitimize_pic_address. (emit_move_sequence): Call legitimize_pic_address to handle constant data. Handle secondary reloads for PIC. Use pic_label_operand rather than open coding the test. Handle loading a LABEL_REF when generating PIC. (legitimzie_pic_address): Handle constant data addressing for PIC here. Fix loading of symbolic addresses for -fPIC generation. (pic_label_operand): Renamed from pic_operand. Handle any read only operand (such as constant data). Reject function addresses, Accept SYMBOL_REF with the read-only bit set. Generalize to handle (const (plus (reg) (int))). (finalize_pic): Delete unused function. (check_pic): Delete function. (pic_pc_rtx): Delete variable definition. (current_function_uses_pic_offset_table): Delete extern decl. (force_reg, validize_mem): Likewise. (output_global_address): Don't tack on "-$global$" when generating PIC code. (finalize_pic): Don't emit code for initialization of hppa_save_pic_table_rtx here. Don't claim we USE pic_offset_table_rtx at function end. * pa.h (SELECT_RTX_SECTION): Define. During PIC generation everything (in the constant pool) goes into the data space. (PRINT_OPERAND_ADDRESS): Handle CONST_INTs during PIC generation. Handle LO_SUM address during -fPIC generation. (LEGITIMATE_CONSTANT_P): Reject function labels when generating PIC code. (GO_IF_LEGITIMATE_ADDRESS): Only accept pic_reg + SYMBOL_REF for -fpic. (EXTRA_SECTION_FUNCTIONS): For -fpic, use the TEXT section for constants to avoid GAS lossage. (OVERRIDE_OPTIONS): Delete. (PIC_OFFSET_TABLE_REG_CALL_CLOBBERED): Define. (FINALIZE_PIC): Delete definition. (INIT_EXPANDERS): Define. Clear hppa_save_pic_table_rtx here. * pa.md: Use !flag_pic rather than calling check_pic. (HImode high and lo_sum): Only accept const_int_operands. (pic_load_label): Force output to be in %r1. (pic_highpart): New pattern. Output must go into %r1. More linker trickery. (symbolic high and lo_sum): Disallow during PIC generation if source is a symbolic operand. Handle CONST_INT LO_SUM during PIC generation. Simplify. (define_split for symbolic_operand load): Do not accept a symbolic operand that is a pic_label_operand. (pic_load_label): Name this pattern. Mask least significant bits and optimize when a simple label is within reach of an ldo. (call, call_value): Emit new-style USE information for pic_offset_table_rtx. Emit code for initialization of hppa_save_pic_table_rtx and wrap it into push_topmost_sequence() and pop_topmost_sequence() calls. From-SVN: r8419 --- gcc/config/pa/pa.c | 131 ++++++++++++++++++++--------------------- gcc/config/pa/pa.h | 57 ++++++++++-------- gcc/config/pa/pa.md | 140 ++++++++++++++++++++++++++++++-------------- 3 files changed, 195 insertions(+), 133 deletions(-) diff --git a/gcc/config/pa/pa.c b/gcc/config/pa/pa.c index 168cf0cd690..2ec55bab639 100644 --- a/gcc/config/pa/pa.c +++ b/gcc/config/pa/pa.c @@ -219,11 +219,29 @@ reg_or_cint_move_operand (op, mode) } int -pic_operand (op, mode) +pic_label_operand (op, mode) rtx op; enum machine_mode mode; { - return flag_pic && GET_CODE (op) == LABEL_REF; + if (!flag_pic) + return 0; + + switch (GET_CODE (op)) + { + case LABEL_REF: + return 1; + case SYMBOL_REF: + return (read_only_operand (op) && !FUNCTION_NAME_P (XSTR (op, 0))); + case CONST: + op = XEXP (op, 0); + return (((GET_CODE (XEXP (op, 0)) == SYMBOL_REF + && read_only_operand (XEXP (op, 0)) + && !FUNCTION_NAME_P (XSTR (XEXP (op, 0), 0))) + || GET_CODE (XEXP (op, 0)) == LABEL_REF) + && GET_CODE (XEXP (op, 1)) == CONST_INT); + default: + return 0; + } } int @@ -235,32 +253,6 @@ fp_reg_operand (op, mode) } -extern int current_function_uses_pic_offset_table; -extern rtx force_reg (), validize_mem (); - -/* The rtx for the global offset table which is a special form - that *is* a position independent symbolic constant. */ -rtx pic_pc_rtx; - -/* Ensure that we are not using patterns that are not OK with PIC. */ - -int -check_pic (i) - int i; -{ - extern rtx recog_operand[]; - switch (flag_pic) - { - case 1: - if (GET_CODE (recog_operand[i]) == SYMBOL_REF - || (GET_CODE (recog_operand[i]) == CONST - && ! rtx_equal_p (pic_pc_rtx, recog_operand[i]))) - abort (); - case 2: - default: - return 1; - } -} /* Return truth value of whether OP can be used as an operand in a three operand arithmetic insn that accepts registers of mode MODE @@ -480,6 +472,13 @@ legitimize_pic_address (orig, mode, reg) { rtx pic_ref = orig; + /* Lables and read-only data need special handling. */ + if (pic_label_operand (orig)) + { + emit_insn (gen_pic_load_label (reg, orig)); + current_function_uses_pic_offset_table = 1; + return reg; + } if (GET_CODE (orig) == SYMBOL_REF) { if (reg == 0) @@ -487,15 +486,12 @@ legitimize_pic_address (orig, mode, reg) if (flag_pic == 2) { - emit_insn (gen_rtx (SET, VOIDmode, reg, - gen_rtx (HIGH, Pmode, orig))); - emit_insn (gen_rtx (SET, VOIDmode, reg, - gen_rtx (LO_SUM, Pmode, reg, orig))); - orig = reg; + emit_insn (gen_pic_highpart (reg, pic_offset_table_rtx, orig)); + pic_ref = (gen_rtx (MEM, Pmode, gen_rtx (LO_SUM, Pmode, reg, orig))); } - pic_ref = gen_rtx (MEM, Pmode, - gen_rtx (PLUS, Pmode, - pic_offset_table_rtx, orig)); + else + pic_ref = gen_rtx (MEM, Pmode, + gen_rtx (PLUS, Pmode, pic_offset_table_rtx, orig)); current_function_uses_pic_offset_table = 1; RTX_UNCHANGING_P (pic_ref) = 1; emit_move_insn (reg, pic_ref); @@ -531,24 +527,6 @@ legitimize_pic_address (orig, mode, reg) return pic_ref; } -/* Emit special PIC prologues and epilogues. */ - -void -finalize_pic () -{ - if (hppa_save_pic_table_rtx) - { - emit_insn_after (gen_rtx (SET, VOIDmode, - hppa_save_pic_table_rtx, - gen_rtx (REG, Pmode, PIC_OFFSET_TABLE_REGNUM)), - get_insns ()); - /* Need to emit this whether or not we obey regdecls, - since setjmp/longjmp can cause life info to screw up. */ - hppa_save_pic_table_rtx = 0; - } - emit_insn (gen_rtx (USE, VOIDmode, pic_offset_table_rtx)); -} - /* Try machine-dependent ways of modifying an illegitimate address to be legitimate. If we find one, return the new, valid address. This macro is used in only one place: `memory_address' in explow.c. @@ -607,6 +585,9 @@ hppa_legitimize_address (x, oldx, mode) { rtx orig = x; + if (flag_pic) + return legitimize_pic_address (x, mode, gen_reg_rtx (Pmode)); + /* Strip off CONST. */ if (GET_CODE (x) == CONST) x = XEXP (x, 0); @@ -727,9 +708,6 @@ hppa_legitimize_address (x, oldx, mode) } } - if (flag_pic) - return legitimize_pic_address (x, mode, gen_reg_rtx (Pmode)); - return orig; } @@ -895,16 +873,16 @@ emit_move_sequence (operands, mode, scratch_reg) rtx temp; if (reload_in_progress || reload_completed) - temp = operand0; + temp = scratch_reg ? scratch_reg : operand0; else temp = gen_reg_rtx (Pmode); operands[1] = legitimize_pic_address (operand1, mode, temp); - emit_insn (gen_rtx (SET, VOIDmode, operand0, operands[1])); + emit_insn (gen_rtx (SET, VOIDmode, operand0, operands[1])); } - /* On the HPPA, references to data space are supposed to */ - /* use dp, register 27, but showing it in the RTL inhibits various - cse and loop optimizations. */ + /* On the HPPA, references to data space are supposed to use dp, + register 27, but showing it in the RTL inhibits various cse + and loop optimizations. */ else { rtx temp, set, const_part = NULL; @@ -982,8 +960,16 @@ read_only_operand (operand) { if (GET_CODE (operand) == CONST) operand = XEXP (XEXP (operand, 0), 0); - if (GET_CODE (operand) == SYMBOL_REF) - return SYMBOL_REF_FLAG (operand) || CONSTANT_POOL_ADDRESS_P (operand); + if (flag_pic) + { + if (GET_CODE (operand) == SYMBOL_REF) + return SYMBOL_REF_FLAG (operand) && !CONSTANT_POOL_ADDRESS_P (operand); + } + else + { + if (GET_CODE (operand) == SYMBOL_REF) + return SYMBOL_REF_FLAG (operand) || CONSTANT_POOL_ADDRESS_P (operand); + } return 1; } @@ -2950,7 +2936,7 @@ output_global_address (file, x) if (GET_CODE (x) == SYMBOL_REF && read_only_operand (x)) assemble_name (file, XSTR (x, 0)); - else if (GET_CODE (x) == SYMBOL_REF) + else if (GET_CODE (x) == SYMBOL_REF && !flag_pic) { assemble_name (file, XSTR (x, 0)); fprintf (file, "-$global$"); @@ -2994,7 +2980,7 @@ output_global_address (file, x) sep = "-"; else abort (); - if (!read_only_operand (base)) + if (!read_only_operand (base) && !flag_pic) fprintf (file, "-$global$"); fprintf (file, "%s", sep); if (offset) fprintf (file,"%d", offset); @@ -3261,6 +3247,14 @@ secondary_reload_class (class, mode, in) { int regno = true_regnum (in); + /* Trying to load a constant into a FP register during PIC code + generation will require %r1 as a scratch register. */ + if (flag_pic == 2 + && GET_MODE_CLASS (mode) == MODE_INT + && FP_REG_CLASS_P (class) + && (GET_CODE (in) == CONST_INT || GET_CODE (in) == CONST_DOUBLE)) + return R1_REGS; + if (((regno >= FIRST_PSEUDO_REGISTER || regno == -1) && GET_MODE_CLASS (mode) == MODE_INT && FP_REG_CLASS_P (class)) @@ -3270,6 +3264,11 @@ secondary_reload_class (class, mode, in) if (GET_CODE (in) == HIGH) in = XEXP (in, 0); + if (!flag_pic + && symbolic_operand (in, VOIDmode) + && read_only_operand (in)) + return NO_REGS; + if (class != R1_REGS && symbolic_operand (in, VOIDmode)) return R1_REGS; diff --git a/gcc/config/pa/pa.h b/gcc/config/pa/pa.h index bc7624d27e1..cf880aff622 100644 --- a/gcc/config/pa/pa.h +++ b/gcc/config/pa/pa.h @@ -182,21 +182,6 @@ extern int target_flags; #define WCHAR_TYPE "unsigned int" #define WCHAR_TYPE_SIZE 32 -/* Sometimes certain combinations of command options do not make sense - on a particular target machine. You can define a macro - `OVERRIDE_OPTIONS' to take account of this. This macro, if - defined, is executed once just after all the command options have - been parsed. - - On the PA, it is used to explicitly warn the user that -fpic and -fPIC - do not work. */ - -#define OVERRIDE_OPTIONS \ -{ \ - if (flag_pic != 0) \ - warning ("-fpic and -fPIC are not supported on the PA."); \ -} - /* Show we can debug even without a frame pointer. */ #define CAN_DEBUG_WITHOUT_FP @@ -495,8 +480,12 @@ extern int target_flags; data references. */ #define PIC_OFFSET_TABLE_REGNUM 19 +#define PIC_OFFSET_TABLE_REG_CALL_CLOBBERED 1 -#define FINALIZE_PIC finalize_pic () +/* Initialize hppa_save_pic_table_rtx before RTL generation for + each function. We used to do this in FINALIZE_PIC, but FINALIZE_PIC + isn't always called for static inline functions. */ +#define INIT_EXPANDERS hppa_save_pic_table_rtx = 0; /* SOM ABI says that objects larger than 64 bits are returned in memory. */ #define RETURN_IN_MEMORY(TYPE) \ @@ -1185,8 +1174,9 @@ extern union tree_node *current_function_decl; floating-point, except for floating-point zero. */ #define LEGITIMATE_CONSTANT_P(X) \ - (GET_MODE_CLASS (GET_MODE (X)) != MODE_FLOAT \ - || (X) == CONST0_RTX (GET_MODE (X))) + ((GET_MODE_CLASS (GET_MODE (X)) != MODE_FLOAT \ + || (X) == CONST0_RTX (GET_MODE (X))) \ + && !(flag_pic && function_label_operand (X, VOIDmode))) /* Subroutine for EXTRA_CONSTRAINT. @@ -1307,9 +1297,7 @@ extern union tree_node *current_function_decl; && REG_OK_FOR_BASE_P (XEXP (X, 1))) \ goto ADDR; \ else if (flag_pic == 1 \ - && GET_CODE (XEXP (X, 1)) != REG \ - && GET_CODE (XEXP (X, 1)) != LO_SUM \ - && GET_CODE (XEXP (X, 1)) != MEM) \ + && GET_CODE (XEXP (X, 1)) == SYMBOL_REF)\ goto ADDR; \ } \ else if (REG_P (XEXP (X, 0)) \ @@ -1427,6 +1415,17 @@ while (0) 1 + (SYMBOL_NAME)[1] == '@'\ : (SYMBOL_NAME)[0] == '@')) +/* Arghh. This is used for stuff in the constant pool; this may include + function addresses on the PA, which during PIC code generation must + reside in the data space. Unfortuantely, there's no way to determine + if a particular label in the constant pool refers to a function address. + So just force everything into the data space during PIC generation. */ +#define SELECT_RTX_SECTION(RTX,MODE) \ + if (flag_pic) \ + data_section (); \ + else \ + readonly_data_section (); + /* Specify the machine mode that this machine uses for the index in the tablejump instruction. */ #define CASE_VECTOR_MODE DImode @@ -1682,6 +1681,10 @@ do { fprintf (FILE, "\t.SPACE $PRIVATE$\n\ #define EXTRA_SECTIONS in_bss, in_readonly_data +/* FIXME: GAS doesn't grok expressions involving two symbols in different + segments (aka subspaces). Two avoid creating such expressions, we place + readonly data into the $CODE$ subspace when generating PIC code. If + GAS ever handles such expressions, this hack can disappear. */ #define EXTRA_SECTION_FUNCTIONS \ void \ bss_section () \ @@ -1697,7 +1700,10 @@ readonly_data () \ { \ if (in_section != in_readonly_data) \ { \ - fprintf (asm_out_file, "%s\n", READONLY_DATA_ASM_OP); \ + if (flag_pic) \ + fprintf (asm_out_file, "%s\n", TEXT_SECTION_ASM_OP); \ + else \ + fprintf (asm_out_file, "%s\n", READONLY_DATA_ASM_OP); \ in_section = in_readonly_data; \ } \ } @@ -1980,7 +1986,12 @@ readonly_data () \ fprintf (FILE, "%d(0,%s)", offset, reg_names [REGNO (base)]); \ break; \ case LO_SUM: \ - fputs ("R'", FILE); \ + if (flag_pic == 0 || !symbolic_operand (XEXP (addr, 1))) \ + fputs ("R'", FILE); \ + else if (flag_pic == 1) \ + abort (); \ + else if (flag_pic == 2) \ + fputs ("RT'", FILE); \ output_global_address (FILE, XEXP (addr, 1)); \ fputs ("(", FILE); \ output_operand (XEXP (addr, 0), 0); \ diff --git a/gcc/config/pa/pa.md b/gcc/config/pa/pa.md index 81b3341e507..3bb5b073193 100644 --- a/gcc/config/pa/pa.md +++ b/gcc/config/pa/pa.md @@ -1124,10 +1124,11 @@ (set_attr "length" "4")]) ;; For pic -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (match_operand:SI 1 "pic_operand" "i")) - (clobber (match_scratch:SI 2 "=a"))] +;; Note since this pattern can be created at reload time (via movsi), all +;; the same rules for movsi apply here. (no new pseudos, no temporaries). +(define_insn "pic_load_label" + [(set (match_operand:SI 0 "register_operand" "=a") + (match_operand:SI 1 "pic_label_operand" ""))] "" "* { @@ -1138,14 +1139,43 @@ xoperands[0] = operands[0]; xoperands[1] = operands[1]; xoperands[2] = label_rtx; - output_asm_insn (\"bl .+8,%0\;addil L'%1-%2,%0\", xoperands); - ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (label_rtx)); - output_asm_insn (\"ldo R'%1-%2(1),%0\", xoperands); + output_asm_insn (\"bl .+8,%0\", xoperands); + output_asm_insn (\"depi 0,31,2,%0\", xoperands); + ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", + CODE_LABEL_NUMBER (label_rtx)); + + /* 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 + && insn_addresses + && abs (insn_addresses[INSN_UID (XEXP (operands[1], 0))] + - insn_current_address) < 8100) + { + /* Prefixing with R% here is wrong, it extracts just 11 bits and is + always non-negative. */ + output_asm_insn (\"ldo %1-%2(%0),%0\", xoperands); + } + else + { + output_asm_insn (\"addil L%%%1-%2,%0\", xoperands); + output_asm_insn (\"ldo R%%%1-%2(%0),%0\", xoperands); + } return \"\"; - } -" +}" [(set_attr "type" "multi") - (set_attr "length" "12")]) + (set_attr "length" "16")]) ; 12 or 16 + +(define_insn "pic_highpart" + [(set (match_operand:SI 0 "register_operand" "=a") + (plus (match_operand:SI 1 "register_operand" "r") + (high:SI (match_operand 2 "" ""))))] + "symbolic_operand (operands[2], Pmode) + && ! function_label_operand (operands[2]) + && ! read_only_operand (operands[2]) + && flag_pic == 2" + "addil LT'%G2,%1" + [(set_attr "type" "binary") + (set_attr "length" "4")]) ;; Always use addil rather than ldil;add sequences. This allows the ;; HP linker to eliminate the dp relocation if the symbolic operand @@ -1155,9 +1185,9 @@ (high:SI (match_operand 1 "" "")))] "symbolic_operand (operands[1], Pmode) && ! function_label_operand (operands[1]) - && ! read_only_operand (operands[1])" - "@ - addil L'%G1,%%r27" + && ! read_only_operand (operands[1]) + && ! flag_pic" + "addil L'%G1,%%r27" [(set_attr "type" "binary") (set_attr "length" "4")]) @@ -1199,7 +1229,8 @@ (define_insn "" [(set (match_operand:SI 0 "register_operand" "=r") (high:SI (match_operand 1 "" "")))] - "check_pic (1) && !is_function_label_plus_const (operands[1])" + "(!flag_pic || !symbolic_operand (operands[1]), Pmode) + && !is_function_label_plus_const (operands[1])" "ldil L'%G1,%0" [(set_attr "type" "move") (set_attr "length" "4")]) @@ -1233,7 +1264,15 @@ (lo_sum:SI (match_operand:SI 1 "register_operand" "r") (match_operand:SI 2 "immediate_operand" "i")))] "!is_function_label_plus_const (operands[2])" - "ldo R'%G2(%1),%0" + "* +{ + if (flag_pic == 2 && symbolic_operand (operands[2], Pmode)) + return \"ldw RT'%G2(%1),%0\"; + else if (flag_pic == 1 && symbolic_operand (operands[2], Pmode)) + abort (); + else + return \"ldo R'%G2(%1),%0\"; +}" [(set_attr "length" "4")]) ;; Now that a symbolic_address plus a constant is broken up early @@ -1245,7 +1284,7 @@ [(set (match_operand:SI 0 "register_operand" "") (match_operand:SI 1 "symbolic_operand" "")) (clobber (match_operand:SI 2 "register_operand" ""))] - "" + "! (flag_pic && pic_label_operand (operands[1], SImode))" [(set (match_dup 2) (high:SI (match_dup 1))) (set (match_dup 0) (lo_sum:SI (match_dup 2) (match_dup 1)))] "") @@ -1337,8 +1376,8 @@ (define_insn "" [(set (match_operand:HI 0 "register_operand" "=r") - (high:HI (match_operand 1 "" "")))] - "check_pic (1)" + (high:HI (match_operand 1 "const_int_operand" "")))] + "" "ldil L'%G1,%0" [(set_attr "type" "move") (set_attr "length" "4")]) @@ -1346,7 +1385,7 @@ (define_insn "" [(set (match_operand:HI 0 "register_operand" "=r") (lo_sum:HI (match_operand:HI 1 "register_operand" "r") - (match_operand 2 "immediate_operand" "i")))] + (match_operand 2 "const_int_operand" "i")))] "" "ldo R'%G2(%1),%0" [(set_attr "length" "4")]) @@ -1651,7 +1690,7 @@ (define_insn "" [(set (match_operand:DI 0 "register_operand" "=r") (high:DI (match_operand 1 "" "")))] - "check_pic (1)" + "" "* { rtx op0 = operands[0]; @@ -3102,10 +3141,7 @@ " { rtx op; - - if (flag_pic) - emit_insn (gen_rtx (USE, VOIDmode, - gen_rtx (REG, Pmode, PIC_OFFSET_TABLE_REGNUM))); + rtx call_insn; if (TARGET_LONG_CALLS) op = force_reg (SImode, XEXP (operands[0], 0)); @@ -3118,17 +3154,27 @@ to change the named call into an indirect call in some cases (using two patterns keeps CSE from performing this optimization). */ if (GET_CODE (op) == SYMBOL_REF) - emit_call_insn (gen_call_internal_symref (op, operands[1])); + call_insn = emit_call_insn (gen_call_internal_symref (op, operands[1])); else - emit_call_insn (gen_call_internal_reg (force_reg (SImode, op), - operands[1])); + call_insn = emit_call_insn (gen_call_internal_reg (force_reg (SImode, op), + operands[1])); if (flag_pic) { + use_reg (&CALL_INSN_FUNCTION_USAGE (call_insn), pic_offset_table_rtx); + if (!hppa_save_pic_table_rtx) - hppa_save_pic_table_rtx = gen_reg_rtx (Pmode); - emit_insn (gen_rtx (SET, VOIDmode, - gen_rtx (REG, Pmode, PIC_OFFSET_TABLE_REGNUM), + { + hppa_save_pic_table_rtx = gen_reg_rtx (Pmode); + push_topmost_sequence (); + emit_insn_after (gen_rtx (SET, VOIDmode, + hppa_save_pic_table_rtx, + pic_offset_table_rtx), + get_insns ()); + pop_topmost_sequence (); + } + + emit_insn (gen_rtx (SET, VOIDmode, pic_offset_table_rtx, hppa_save_pic_table_rtx)); } DONE; @@ -3173,15 +3219,11 @@ (call (match_operand:SI 1 "" "") (match_operand 2 "" ""))) (clobber (reg:SI 2))])] - ;;- Don't use operand 1 for most machines. "" " { rtx op; - - if (flag_pic) - emit_insn (gen_rtx (USE, VOIDmode, - gen_rtx (REG, Pmode, PIC_OFFSET_TABLE_REGNUM))); + rtx call_insn; if (TARGET_LONG_CALLS) op = force_reg (SImode, XEXP (operands[1], 0)); @@ -3194,19 +3236,30 @@ to change the named call into an indirect call in some cases (using two patterns keeps CSE from performing this optimization). */ if (GET_CODE (op) == SYMBOL_REF) - emit_call_insn (gen_call_value_internal_symref (operands[0], op, - operands[2])); + call_insn = emit_call_insn (gen_call_value_internal_symref (operands[0], + op, + operands[2])); else - emit_call_insn (gen_call_value_internal_reg (operands[0], - force_reg (SImode, op), - operands[2])); + call_insn = emit_call_insn (gen_call_value_internal_reg (operands[0], + force_reg (SImode, op), + operands[2])); if (flag_pic) { + use_reg (&CALL_INSN_FUNCTION_USAGE (call_insn), pic_offset_table_rtx); + if (!hppa_save_pic_table_rtx) - hppa_save_pic_table_rtx = gen_reg_rtx (Pmode); - emit_insn (gen_rtx (SET, VOIDmode, - gen_rtx (REG, Pmode, PIC_OFFSET_TABLE_REGNUM), + { + hppa_save_pic_table_rtx = gen_reg_rtx (Pmode); + push_topmost_sequence (); + emit_insn_after (gen_rtx (SET, VOIDmode, + hppa_save_pic_table_rtx, + pic_offset_table_rtx), + get_insns ()); + pop_topmost_sequence (); + } + + emit_insn (gen_rtx (SET, VOIDmode, pic_offset_table_rtx, hppa_save_pic_table_rtx)); } DONE; @@ -3234,7 +3287,6 @@ (match_operand 2 "" "i"))) (clobber (reg:SI 2)) (use (const_int 1))] - ;;- Don't use operand 1 for most machines. "" "* { -- 2.30.2