From patchwork Mon Sep 6 12:11:33 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alan Modra X-Patchwork-Id: 63917 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 6E88CB70F2 for ; Mon, 6 Sep 2010 22:11:54 +1000 (EST) Received: (qmail 7925 invoked by alias); 6 Sep 2010 12:11:49 -0000 Received: (qmail 7913 invoked by uid 22791); 6 Sep 2010 12:11:47 -0000 X-SWARE-Spam-Status: No, hits=-1.3 required=5.0 tests=AWL, BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, FREEMAIL_FROM, KAM_STOCKGEN, RCVD_IN_DNSWL_NONE X-Spam-Check-By: sourceware.org Received: from mail-pz0-f47.google.com (HELO mail-pz0-f47.google.com) (209.85.210.47) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Mon, 06 Sep 2010 12:11:42 +0000 Received: by pzk2 with SMTP id 2so1461187pzk.20 for ; Mon, 06 Sep 2010 05:11:40 -0700 (PDT) Received: by 10.114.110.16 with SMTP id i16mr3462152wac.208.1283775100767; Mon, 06 Sep 2010 05:11:40 -0700 (PDT) Received: from bubble.grove.modra.org ([115.187.252.19]) by mx.google.com with ESMTPS id c24sm11122411wam.19.2010.09.06.05.11.37 (version=TLSv1/SSLv3 cipher=RC4-MD5); Mon, 06 Sep 2010 05:11:39 -0700 (PDT) Received: by bubble.grove.modra.org (Postfix, from userid 1000) id 7587B170C1EF; Mon, 6 Sep 2010 21:41:33 +0930 (CST) Date: Mon, 6 Sep 2010 21:41:33 +0930 From: Alan Modra To: gcc-patches@gcc.gnu.org, David Edelsohn Subject: Re: PowerPC64 large toc model Message-ID: <20100906121133.GL16874@bubble.grove.modra.org> Mail-Followup-To: gcc-patches@gcc.gnu.org, David Edelsohn References: <20100608125703.GI7312@bubble.grove.modra.org> <20100625104301.GI21855@bubble.grove.modra.org> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <20100625104301.GI21855@bubble.grove.modra.org> User-Agent: Mutt/1.5.20 (2009-06-14) 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 This patch reinstates the -mcmodel=medium option for PowerPC64 Linux. When I removed this option, I stated that I could implement the optimisation in the linker but that turns out to not be true. The problem is that there is no relocation on instructions that load an address out of the TOC, and you need one to reliably tie together the whole instruction sequence for the linker. The patch is not just a simple reversion of my 2010-06-25 patch, so I guess it needs a review. toc_relative_ok has been added to work around the potential shared library problem, and a test for NULL DECL_SIZE_UNIT added to offsettable_ok_by_alignment. Bootstrapped powerpc64-linux. Regression tests still running, C, C++ passed so far. OK to apply assuming no regressions found? * doc/invoke.text: Reinstate mcmodel=medium. * config/rs6000/linux64.h (SUBSUBTARGET_OVERRIDE_OPTIONS): Set CMODEL_MEDIUM as default. * config/rs6000/rs6000.h (enum rs6000_cmodel): Add CMODEL_MEDIUM. * config/rs6000/rs6000.c (rs6000_handle_option): Add mcmodel=medium. (toc_relative_ok, offsettable_ok_by_alignment): New functions. (rs6000_emit_move): Reinstate mcmodel=medium optimization. Index: gcc/doc/invoke.texi =================================================================== --- gcc/doc/invoke.texi (revision 163887) +++ gcc/doc/invoke.texi (working copy) @@ -15212,6 +15212,11 @@ scheduling parameters set by @option{-mt Generate PowerPC64 code for the small model: The TOC is limited to 64k. +@item -mcmodel=medium +@opindex mcmodel=medium +Generate PowerPC64 code for the medium model: The TOC and other static +data may be up to a total of 4G in size. + @item -mcmodel=large @opindex mcmodel=large Generate PowerPC64 code for the large model: The TOC may be up to 4G Index: gcc/config/rs6000/linux64.h =================================================================== --- gcc/config/rs6000/linux64.h (revision 163887) +++ gcc/config/rs6000/linux64.h (working copy) @@ -134,7 +134,7 @@ extern enum rs6000_cmodel cmodel; else \ { \ if (!rs6000_explicit_options.cmodel) \ - SET_CMODEL (CMODEL_LARGE); \ + SET_CMODEL (CMODEL_MEDIUM); \ if (cmodel != CMODEL_SMALL) \ { \ TARGET_NO_FP_IN_TOC = 0; \ Index: gcc/config/rs6000/rs6000.h =================================================================== --- gcc/config/rs6000/rs6000.h (revision 163887) +++ gcc/config/rs6000/rs6000.h (working copy) @@ -297,9 +297,11 @@ extern const char *host_detect_local_cpu /* Code model for 64-bit linux. small: 16-bit toc offsets. - large: 32-bit toc offsets. */ + medium: 32-bit toc offsets, static data and code within 2G of TOC pointer. + large: 32-bit toc offsets, no limit on static data and code. */ enum rs6000_cmodel { CMODEL_SMALL, + CMODEL_MEDIUM, CMODEL_LARGE }; Index: gcc/config/rs6000/rs6000.c =================================================================== --- gcc/config/rs6000/rs6000.c (revision 163887) +++ gcc/config/rs6000/rs6000.c (working copy) @@ -6992,6 +6992,80 @@ rs6000_eliminate_indexed_memrefs (rtx op copy_addr_to_reg (XEXP (operands[1], 0))); } +/* Return true if OP, a SYMBOL_REF, should be considered local when + generating -mcmodel=medium code. */ + +static bool +toc_relative_ok (rtx op) +{ + tree decl; + + if (!SYMBOL_REF_LOCAL_P (op)) + return false; + + /* This is a bit hard to explain. When building shared libraries, + you are supposed to pass -fpic or -fPIC to the compiler. + -fpic/-fPIC not only generate position independent code but also + generate code that supports ELF shared library global function + or variable overriding. ppc64 is always PIC and at least some of + the ELF shared libaray semantics of global variables happen to be + supported without -fpic/-fPIC. So people may not be careful + about using -fPIC for shared libs. + With -mcmodel=medium this situation changes. A shared library + built without -fpic/-fPIC requires text relocs for global var + access (and would fail to load since glibc ld.so doesn't support + the required dynamic relocs). So avoid this potential + problem by using -mcmodel=large access for global vars, unless + we know we are compiling for an executable. */ + if (flag_pie) + return true; + + decl = SYMBOL_REF_DECL (op); + if (!decl || !DECL_P (decl)) + return true; + if (!TREE_PUBLIC (decl)) + return true; + if (DECL_VISIBILITY (decl) != VISIBILITY_DEFAULT) + return true; + + /* If we get here we must have a global var. See binds_local_p. */ + return flag_whole_program; +} + +/* Return true if memory accesses to DECL are known to never straddle + a 32k boundary. */ + +static bool +offsettable_ok_by_alignment (tree decl) +{ + unsigned HOST_WIDE_INT dsize, dalign; + + /* Presume any compiler generated symbol_ref is suitably aligned. */ + if (!decl) + return true; + + if (TREE_CODE (decl) != VAR_DECL + && TREE_CODE (decl) != PARM_DECL + && TREE_CODE (decl) != RESULT_DECL + && TREE_CODE (decl) != FIELD_DECL) + return true; + + if (!DECL_SIZE_UNIT (decl)) + return false; + + if (!host_integerp (DECL_SIZE_UNIT (decl), 1)) + return false; + + dsize = tree_low_cst (DECL_SIZE_UNIT (decl), 1); + if (dsize <= 1) + return true; + if (dsize > 32768) + return false; + + dalign = DECL_ALIGN_UNIT (decl); + return dalign >= dsize; +} + /* Emit a move from SOURCE to DEST in mode MODE. */ void rs6000_emit_move (rtx dest, rtx source, enum machine_mode mode) @@ -7305,11 +7379,16 @@ rs6000_emit_move (rtx dest, rtx source, /* If this is a SYMBOL_REF that refers to a constant pool entry, and we have put it in the TOC, we just need to make a TOC-relative reference to it. */ - if (TARGET_TOC - && GET_CODE (operands[1]) == SYMBOL_REF - && constant_pool_expr_p (operands[1]) - && ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (operands[1]), - get_pool_mode (operands[1]))) + if ((TARGET_TOC + && GET_CODE (operands[1]) == SYMBOL_REF + && constant_pool_expr_p (operands[1]) + && ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (operands[1]), + get_pool_mode (operands[1]))) + || (TARGET_CMODEL == CMODEL_MEDIUM + && GET_CODE (operands[1]) == SYMBOL_REF + && !CONSTANT_POOL_ADDRESS_P (operands[1]) + && toc_relative_ok (operands[1]) + && offsettable_ok_by_alignment (SYMBOL_REF_DECL (operands[1])))) { rtx reg = NULL_RTX; if (TARGET_CMODEL != CMODEL_SMALL)