From patchwork Fri Oct 28 01:43:09 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Bergner X-Patchwork-Id: 122322 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id 3CC30B6F7D for ; Fri, 28 Oct 2011 12:44:30 +1100 (EST) Received: (qmail 30552 invoked by alias); 28 Oct 2011 01:44:28 -0000 Received: (qmail 30536 invoked by uid 22791); 28 Oct 2011 01:44:26 -0000 X-SWARE-Spam-Status: No, hits=-1.2 required=5.0 tests=AWL, BAYES_00, KAM_STOCKGEN, RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from e34.co.us.ibm.com (HELO e34.co.us.ibm.com) (32.97.110.152) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Fri, 28 Oct 2011 01:44:10 +0000 Received: from /spool/local by e34.co.us.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Thu, 27 Oct 2011 19:44:09 -0600 Received: from d03relay01.boulder.ibm.com ([9.17.195.226]) by e34.co.us.ibm.com ([192.168.1.134]) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Thu, 27 Oct 2011 19:43:13 -0600 Received: from d03av05.boulder.ibm.com (d03av05.boulder.ibm.com [9.17.195.85]) by d03relay01.boulder.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id p9S1hCdx298490 for ; Thu, 27 Oct 2011 19:43:12 -0600 Received: from d03av05.boulder.ibm.com (loopback [127.0.0.1]) by d03av05.boulder.ibm.com (8.14.4/8.13.1/NCO v10.0 AVout) with ESMTP id p9S1hCxl025290 for ; Thu, 27 Oct 2011 19:43:12 -0600 Received: from [192.168.1.101] (vorma.rchland.ibm.com [9.10.86.174]) by d03av05.boulder.ibm.com (8.14.4/8.13.1/NCO v10.0 AVin) with ESMTP id p9S1hBP0025270; Thu, 27 Oct 2011 19:43:11 -0600 Subject: Re: [PATCH, rs6000] Preserve link stack for 476 cpus From: Peter Bergner To: Richard Henderson Cc: David Edelsohn , gcc-patches In-Reply-To: <4E9719DD.7000304@redhat.com> References: <1315843660.6209.45.camel@otta> <1318520967.3133.69.camel@otta> <4E9719DD.7000304@redhat.com> Date: Thu, 27 Oct 2011 20:43:09 -0500 Message-ID: <1319766189.2996.39.camel@otta> Mime-Version: 1.0 x-cbid: 11102801-1780-0000-0000-00000085E6FB X-IsSubscribed: yes Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org On Thu, 2011-10-13 at 10:03 -0700, Richard Henderson wrote: > On 10/13/2011 08:49 AM, Peter Bergner wrote: > > + if (TARGET_LINK_STACK) > > + asm_fprintf (file, "\tbl 1f\n\tb 2f\n1:\n\tblr\n2:\n"); > > + else > > + asm_fprintf (file, "\tbcl 20,31,1f\n1:\n"); > > Wouldn't it be better to set up an out-of-line "blr" insn that could > be shared by all instances? That would solve a lot of this sort of > this sort of branch-to-branch-to-branch ugliness. > > See the i386 port for an example of this, if you need it. ...after returning from a short vacation... Ok, here's a patch to implement that, and it passes bootstrap and regtesting. Richard, is this what you had in mind? I'll note that I disabled rs6000_code_end for TARGET_POWERPC64, since I was running into linker errors when building libgcc. The merging of the thunk routines with comdat worked fine, but the thunk function also has a function descriptor and I couldn't figure out a way to get those merged properly (if it's even possible), so they led to multiply defined symbol linker errors. Peter * config.gcc (powerpc*-*-linux*): Add powerpc*-*-linux*ppc476* variant. * config/rs6000/476.h: New file. * config/rs6000/476.opt: Likewise. * config/rs6000/rs6000.h (TARGET_LINK_STACK): New define. (SET_TARGET_LINK_STACK): Likewise. (TARGET_ASM_CODE_END): Define. * config/rs6000/rs6000.c (rs6000_option_override_internal): Enable TARGET_LINK_STACK for -mtune=476 and -mtune=476fp. (rs6000_legitimize_tls_address): Emit the link stack preserving GOT code if TARGET_LINK_STACK. (rs6000_emit_load_toc_table): Likewise. (output_function_profiler): Likewise (macho_branch_islands): Likewise (machopic_output_stub): Likewise (get_ppc476_thunk_name): New function. (rs6000_code_end): Likewise. * config/rs6000/rs6000.md (load_toc_v4_PIC_1, load_toc_v4_PIC_1b): Convert to a define_expand. (load_toc_v4_PIC_1_normal): New define_insn. (load_toc_v4_PIC_1_476): Likewise. (load_toc_v4_PIC_1b_normal): Likewise. (load_toc_v4_PIC_1b_476): Likewise. Index: gcc/config.gcc =================================================================== --- gcc/config.gcc (revision 179091) +++ gcc/config.gcc (working copy) @@ -2133,6 +2133,9 @@ powerpc-*-linux* | powerpc64-*-linux*) esac tmake_file="${tmake_file} t-slibgcc-libgcc" case ${target} in + powerpc*-*-linux*ppc476*) + tm_file="${tm_file} rs6000/476.h" + extra_options="${extra_options} rs6000/476.opt" ;; powerpc*-*-linux*altivec*) tm_file="${tm_file} rs6000/linuxaltivec.h" ;; powerpc*-*-linux*spe*) Index: gcc/config/rs6000/476.h =================================================================== --- gcc/config/rs6000/476.h (revision 0) +++ gcc/config/rs6000/476.h (revision 0) @@ -0,0 +1,32 @@ +/* Enable IBM PowerPC 476 support. + Copyright (C) 2011 Free Software Foundation, Inc. + Contributed by Peter Bergner (bergner@vnet.ibm.com) + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3, or (at your + option) any later version. + + GCC is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#undef TARGET_LINK_STACK +#define TARGET_LINK_STACK (rs6000_link_stack) + +#undef SET_TARGET_LINK_STACK +#define SET_TARGET_LINK_STACK(X) do { TARGET_LINK_STACK = (X); } while (0) + +#undef TARGET_ASM_CODE_END +#define TARGET_ASM_CODE_END rs6000_code_end Index: gcc/config/rs6000/rs6000-protos.h =================================================================== --- gcc/config/rs6000/rs6000-protos.h (revision 179091) +++ gcc/config/rs6000/rs6000-protos.h (working copy) @@ -173,6 +173,7 @@ extern void rs6000_emit_eh_reg_restore ( extern const char * output_isel (rtx *); extern void rs6000_call_indirect_aix (rtx, rtx, rtx); extern void rs6000_aix_asm_output_dwarf_table_ref (char *); +extern void get_ppc476_thunk_name (char name[32]); /* Declare functions in rs6000-c.c */ Index: gcc/config/rs6000/476.opt =================================================================== --- gcc/config/rs6000/476.opt (revision 0) +++ gcc/config/rs6000/476.opt (revision 0) @@ -0,0 +1,24 @@ +; IBM PowerPC 476 options. +; +; Copyright (C) 2011 Free Software Foundation, Inc. +; Contributed by Peter Bergner (bergner@vnet.ibm.com) +; +; This file is part of GCC. +; +; GCC is free software; you can redistribute it and/or modify it under +; the terms of the GNU General Public License as published by the Free +; Software Foundation; either version 3, or (at your option) any later +; version. +; +; GCC is distributed in the hope that it will be useful, but WITHOUT ANY +; WARRANTY; without even the implied warranty of MERCHANTABILITY or +; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +; for more details. +; +; You should have received a copy of the GNU General Public License +; along with GCC; see the file COPYING3. If not see +; . + +mpreserve-ppc476-link-stack +Target Var(rs6000_link_stack) Init(1) Save +Preserve the PowerPC 476's link stack by matching up a blr with the bcl/bl insns used for GOT accesses Index: gcc/config/rs6000/rs6000.c =================================================================== --- gcc/config/rs6000/rs6000.c (revision 179091) +++ gcc/config/rs6000/rs6000.c (working copy) @@ -1618,7 +1618,6 @@ static const struct attribute_spec rs600 #undef TARGET_LEGITIMATE_CONSTANT_P #define TARGET_LEGITIMATE_CONSTANT_P rs6000_legitimate_constant_p -struct gcc_target targetm = TARGET_INITIALIZER; /* Simplifications for entries below. */ @@ -3244,6 +3243,11 @@ rs6000_option_override_internal (bool gl target_option_default_node = target_option_current_node = build_target_option_node (); + /* If not explicitly specified via option, decide whether to generate the + extra blr's required to preserve the link stack on some cpus (eg, 476). */ + if (TARGET_LINK_STACK == -1) + SET_TARGET_LINK_STACK (rs6000_cpu == PROCESSOR_PPC476); + return ret; } @@ -5932,6 +5936,8 @@ rs6000_legitimize_tls_address (rtx addr, lab = gen_label_rtx (); emit_insn (gen_load_toc_v4_PIC_1b (gsym, lab)); emit_move_insn (tmp1, gen_rtx_REG (Pmode, LR_REGNO)); + if (TARGET_LINK_STACK) + emit_insn (gen_addsi3 (tmp1, tmp1, GEN_INT (4))); emit_move_insn (tmp2, mem); last = emit_insn (gen_addsi3 (got, tmp1, tmp2)); set_unique_reg_note (last, REG_EQUAL, gsym); @@ -18923,6 +18929,8 @@ rs6000_emit_load_toc_table (int fromprol lab = gen_label_rtx (); emit_insn (gen_load_toc_v4_PIC_1b (tocsym, lab)); emit_move_insn (dest, gen_rtx_REG (Pmode, LR_REGNO)); + if (TARGET_LINK_STACK) + emit_insn (gen_addsi3 (dest, dest, GEN_INT (4))); emit_move_insn (temp0, gen_rtx_MEM (Pmode, dest)); } emit_insn (gen_addsi3 (dest, temp0, dest)); @@ -22493,7 +22501,15 @@ output_function_profiler (FILE *file, in } else if (TARGET_SECURE_PLT && flag_pic) { - asm_fprintf (file, "\tbcl 20,31,1f\n1:\n\t{st|stw} %s,4(%s)\n", + if (TARGET_LINK_STACK) + { + char name[32]; + get_ppc476_thunk_name (name); + asm_fprintf (file, "\tbl %s\n", name); + } + else + asm_fprintf (file, "\tbcl 20,31,1f\n1:\n"); + asm_fprintf (file, "\t{st|stw} %s,4(%s)\n", reg_names[0], reg_names[1]); asm_fprintf (file, "\tmflr %s\n", reg_names[12]); asm_fprintf (file, "\t{cau|addis} %s,%s,", @@ -22518,10 +22534,24 @@ output_function_profiler (FILE *file, in asm_fprintf (file, "\t{st|stw} %s,4(%s)\n", reg_names[0], reg_names[1]); /* Now, we need to get the address of the label. */ - fputs ("\tbcl 20,31,1f\n\t.long ", file); - assemble_name (file, buf); - fputs ("-.\n1:", file); - asm_fprintf (file, "\tmflr %s\n", reg_names[11]); + if (TARGET_LINK_STACK) + { + char name[32]; + get_ppc476_thunk_name (name); + asm_fprintf (file, "\tbl %s\n\tb 1f\n\t.long ", name); + assemble_name (file, buf); + fputs ("-.\n1:", file); + asm_fprintf (file, "\tmflr %s\n", reg_names[11]); + asm_fprintf (file, "\taddi %s,%s,4\n", + reg_names[11], reg_names[11]); + } + else + { + fputs ("\tbcl 20,31,1f\n\t.long ", file); + assemble_name (file, buf); + fputs ("-.\n1:", file); + asm_fprintf (file, "\tmflr %s\n", reg_names[11]); + } asm_fprintf (file, "\t{l|lwz} %s,0(%s)\n", reg_names[0], reg_names[11]); asm_fprintf (file, "\t{cax|add} %s,%s,%s\n", @@ -25004,11 +25034,24 @@ macho_branch_islands (void) #endif /* DBX_DEBUGGING_INFO || XCOFF_DEBUGGING_INFO */ if (flag_pic) { - strcat (tmp_buf, ":\n\tmflr r0\n\tbcl 20,31,"); - strcat (tmp_buf, label); - strcat (tmp_buf, "_pic\n"); - strcat (tmp_buf, label); - strcat (tmp_buf, "_pic:\n\tmflr r11\n"); + if (TARGET_LINK_STACK) + { + char name[32]; + get_ppc64_thunk_name (name); + strcat (tmp_buf, ":\n\tmflr r0\n\tbl "); + strcat (tmp_buf, name); + strcat (tmp_buf, "\n"); + strcat (tmp_buf, label); + strcat (tmp_buf, "_pic:\n\tmflr r11\n"); + } + else + { + strcat (tmp_buf, ":\n\tmflr r0\n\tbcl 20,31,"); + strcat (tmp_buf, label); + strcat (tmp_buf, "_pic\n"); + strcat (tmp_buf, label); + strcat (tmp_buf, "_pic:\n\tmflr r11\n"); + } strcat (tmp_buf, "\taddis r11,r11,ha16("); strcat (tmp_buf, name_buf); @@ -25154,8 +25197,18 @@ machopic_output_stub (FILE *file, const sprintf (local_label_0, "\"L%011d$spb\"", label); fprintf (file, "\tmflr r0\n"); - fprintf (file, "\tbcl 20,31,%s\n", local_label_0); - fprintf (file, "%s:\n\tmflr r11\n", local_label_0); + if (TARGET_LINK_STACK) + { + char name[32]; + get_ppc476_thunk_name (name); + fprintf (file, "\tbl %s\n", name); + fprintf (file, "%s:\n\tmflr r11\n", local_label_0); + } + else + { + fprintf (file, "\tbcl 20,31,%s\n", local_label_0); + fprintf (file, "%s:\n\tmflr r11\n", local_label_0); + } fprintf (file, "\taddis r11,r11,ha16(%s-%s)\n", lazy_ptr_name, local_label_0); fprintf (file, "\tmtlr r0\n"); @@ -27862,4 +27915,71 @@ rs6000_save_toc_in_prologue_p (void) return (cfun && cfun->machine && cfun->machine->save_toc_in_prologue); } +/* Fills in the label name that should be used for a 476 link stack thunk. */ + +void +get_ppc476_thunk_name (char name[32]) +{ + gcc_assert (TARGET_LINK_STACK); + + if (HAVE_GAS_HIDDEN) + sprintf (name, "__ppc476.get_thunk"); + else + ASM_GENERATE_INTERNAL_LABEL (name, "LPPC476_", 0); +} + +/* This function emits the simple thunk routine that is used to preserve + the link stack on the 476 cpu. */ + +static void +rs6000_code_end (void) +{ + char name[32]; + tree decl; + + if (!TARGET_LINK_STACK || !flag_pic || TARGET_POWERPC64) + return; + + get_ppc476_thunk_name (name); + + decl = build_decl (BUILTINS_LOCATION, FUNCTION_DECL, get_identifier (name), + build_function_type_list (void_type_node, NULL_TREE)); + DECL_RESULT (decl) = build_decl (BUILTINS_LOCATION, RESULT_DECL, + NULL_TREE, void_type_node); + TREE_PUBLIC (decl) = 1; + TREE_STATIC (decl) = 1; + + if (HAVE_GAS_HIDDEN) + { + DECL_COMDAT_GROUP (decl) = DECL_ASSEMBLER_NAME (decl); + targetm.asm_out.unique_section (decl, 0); + switch_to_section (get_named_section (decl, NULL, 0)); + targetm.asm_out.globalize_label (asm_out_file, name); + targetm.asm_out.assemble_visibility (decl, VISIBILITY_HIDDEN); + ASM_DECLARE_FUNCTION_NAME (asm_out_file, name, decl); + } + else + { + switch_to_section (text_section); + ASM_OUTPUT_LABEL (asm_out_file, name); + } + + DECL_INITIAL (decl) = make_node (BLOCK); + current_function_decl = decl; + init_function_start (decl); + first_function_block_is_cold = false; + /* Make sure unwind info is emitted for the thunk if needed. */ + final_start_function (emit_barrier (), asm_out_file, 1); + + fputs ("\tblr\n", asm_out_file); + + final_end_function (); + init_insn_lengths (); + free_after_compilation (cfun); + set_cfun (NULL); + current_function_decl = NULL; +} + +struct gcc_target targetm = TARGET_INITIALIZER; + #include "gt-rs6000.h" Index: gcc/config/rs6000/rs6000.h =================================================================== --- gcc/config/rs6000/rs6000.h (revision 179091) +++ gcc/config/rs6000/rs6000.h (working copy) @@ -313,6 +313,14 @@ extern const char *host_detect_local_cpu #define HAVE_AS_TLS 0 #endif +#ifndef TARGET_LINK_STACK +#define TARGET_LINK_STACK 0 +#endif + +#ifndef SET_TARGET_LINK_STACK +#define SET_TARGET_LINK_STACK(X) do { } while (0) +#endif + /* Return 1 for a symbol ref for a thread-local storage symbol. */ #define RS6000_SYMBOL_REF_TLS_P(RTX) \ (GET_CODE (RTX) == SYMBOL_REF && SYMBOL_REF_TLS_MODEL (RTX) != 0) Index: gcc/config/rs6000/rs6000.md =================================================================== --- gcc/config/rs6000/rs6000.md (revision 179091) +++ gcc/config/rs6000/rs6000.md (working copy) @@ -12081,27 +12081,81 @@ (define_insn "load_toc_v4_pic_si" [(set_attr "type" "branch") (set_attr "length" "4")]) -(define_insn "load_toc_v4_PIC_1" +(define_expand "load_toc_v4_PIC_1" + [(parallel [(set (reg:SI LR_REGNO) + (match_operand:SI 0 "immediate_operand" "s")) + (use (unspec [(match_dup 0)] UNSPEC_TOC))])] + "TARGET_ELF && DEFAULT_ABI != ABI_AIX + && (flag_pic == 2 || (flag_pic && TARGET_SECURE_PLT))" + "") + +(define_insn "load_toc_v4_PIC_1_normal" [(set (reg:SI LR_REGNO) (match_operand:SI 0 "immediate_operand" "s")) (use (unspec [(match_dup 0)] UNSPEC_TOC))] - "TARGET_ELF && DEFAULT_ABI != ABI_AIX + "!TARGET_LINK_STACK && TARGET_ELF && DEFAULT_ABI != ABI_AIX && (flag_pic == 2 || (flag_pic && TARGET_SECURE_PLT))" "bcl 20,31,%0\\n%0:" [(set_attr "type" "branch") (set_attr "length" "4")]) -(define_insn "load_toc_v4_PIC_1b" +(define_insn "load_toc_v4_PIC_1_476" + [(set (reg:SI LR_REGNO) + (match_operand:SI 0 "immediate_operand" "s")) + (use (unspec [(match_dup 0)] UNSPEC_TOC))] + "TARGET_LINK_STACK && TARGET_ELF && DEFAULT_ABI != ABI_AIX + && (flag_pic == 2 || (flag_pic && TARGET_SECURE_PLT))" + "* +{ + char name[32]; + static char templ[32]; + + get_ppc476_thunk_name (name); + sprintf (templ, \"bl %s\\n%%0:\", name); + return templ; +}" + [(set_attr "type" "branch") + (set_attr "length" "4")]) + +(define_expand "load_toc_v4_PIC_1b" + [(parallel [(set (reg:SI LR_REGNO) + (unspec:SI [(match_operand:SI 0 "immediate_operand" "s") + (label_ref (match_operand 1 "" ""))] + UNSPEC_TOCPTR)) + (match_dup 1)])] + "TARGET_ELF && DEFAULT_ABI != ABI_AIX && flag_pic == 2" + "") + +(define_insn "load_toc_v4_PIC_1b_normal" [(set (reg:SI LR_REGNO) (unspec:SI [(match_operand:SI 0 "immediate_operand" "s") (label_ref (match_operand 1 "" ""))] UNSPEC_TOCPTR)) (match_dup 1)] - "TARGET_ELF && DEFAULT_ABI != ABI_AIX && flag_pic == 2" + "!TARGET_LINK_STACK && TARGET_ELF && DEFAULT_ABI != ABI_AIX && flag_pic == 2" "bcl 20,31,$+8\;.long %0-$" [(set_attr "type" "branch") (set_attr "length" "8")]) +(define_insn "load_toc_v4_PIC_1b_476" + [(set (reg:SI LR_REGNO) + (unspec:SI [(match_operand:SI 0 "immediate_operand" "s") + (label_ref (match_operand 1 "" ""))] + UNSPEC_TOCPTR)) + (match_dup 1)] + "TARGET_LINK_STACK && TARGET_ELF && DEFAULT_ABI != ABI_AIX && flag_pic == 2" + "* +{ + char name[32]; + static char templ[32]; + + get_ppc476_thunk_name (name); + sprintf (templ, \"bl %s\\n\\tb $+8\\n\\t.long %%0-$\", name); + return templ; +}" + [(set_attr "type" "branch") + (set_attr "length" "16")]) + (define_insn "load_toc_v4_PIC_2" [(set (match_operand:SI 0 "gpc_reg_operand" "=r") (mem:SI (plus:SI (match_operand:SI 1 "gpc_reg_operand" "b")