From patchwork Mon May 20 16:40:40 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sandra Loosemore X-Patchwork-Id: 245068 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]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client CN "localhost", Issuer "www.qmailtoaster.com" (not verified)) by ozlabs.org (Postfix) with ESMTPS id 827682C01BB for ; Tue, 21 May 2013 02:40:55 +1000 (EST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :message-id:date:from:mime-version:to:subject:content-type; q= dns; s=default; b=I3fjO+jn7sJ+Qe2FaDSotV6zqwxNP54w6CEwvT6F1SmGZa fPBCU3+c2SSreu1eXCrvbd5AHspnl7wEg0iGAbEFRKE1wlwDIcChV/yQ2Y/SG0xf 9gXATCOxiStCyUMilU1ukPDsj/mejled3LvUe6GFJpjU3FwjFzXmaiNWesUiU= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :message-id:date:from:mime-version:to:subject:content-type; s= default; bh=ERN+IqK7qWSXikX/oRwkKUlY16o=; b=jwTBeNIxC/3MQGl8W1Ql plwwjpgrrTqV9ioB4kKfSPykazzivucuW9PVnuf3BmD703W1uMMq5aho3tjW47K6 UrWfiZmRy348ZVKFLCS+Q+0ImHBt9/WvBXukfuBdfD4AL1B3AVDYIQ/exk/O3vMX dZoV+nkyDjUbFaKgJOyjO/Y= Received: (qmail 9437 invoked by alias); 20 May 2013 16:40:48 -0000 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 Received: (qmail 9425 invoked by uid 89); 20 May 2013 16:40:48 -0000 X-Spam-SWARE-Status: No, score=-3.3 required=5.0 tests=AWL, BAYES_00, KHOP_RCVD_UNTRUST, RCVD_IN_HOSTKARMA_W, RCVD_IN_HOSTKARMA_WL, TW_CP autolearn=ham version=3.3.1 Received: from relay1.mentorg.com (HELO relay1.mentorg.com) (192.94.38.131) by sourceware.org (qpsmtpd/0.84/v0.84-167-ge50287c) with ESMTP; Mon, 20 May 2013 16:40:47 +0000 Received: from svr-orw-exc-10.mgc.mentorg.com ([147.34.98.58]) by relay1.mentorg.com with esmtp id 1UeT8f-0007Pa-Ae from Sandra_Loosemore@mentor.com for gcc-patches@gcc.gnu.org; Mon, 20 May 2013 09:40:45 -0700 Received: from SVR-ORW-FEM-02.mgc.mentorg.com ([147.34.96.206]) by SVR-ORW-EXC-10.mgc.mentorg.com with Microsoft SMTPSVC(6.0.3790.4675); Mon, 20 May 2013 09:40:45 -0700 Received: from [IPv6:::1] (147.34.91.1) by svr-orw-fem-02.mgc.mentorg.com (147.34.96.168) with Microsoft SMTP Server id 14.2.247.3; Mon, 20 May 2013 09:40:44 -0700 Message-ID: <519A5208.3080102@codesourcery.com> Date: Mon, 20 May 2013 10:40:40 -0600 From: Sandra Loosemore User-Agent: Mozilla/5.0 (X11; Linux i686; rv:17.0) Gecko/20130329 Thunderbird/17.0.5 MIME-Version: 1.0 To: Subject: [patch, powerpc] increase array alignment for Altivec X-Virus-Found: No This patch is a revised version of one previously posted by Pat Wellander a couple of years ago, to align arrays of size >= 16 bytes on a 16-byte boundary to make better use of Altivec instructions. http://gcc.gnu.org/ml/gcc-patches/2011-03/msg01345.html The original patch only increased the alignment of local arrays, which works because the stack is already aligned at 16 bytes for Altivec. The comments on the original patch submission were that this should apply to all arrays and that it should also look for structs containing arrays that would benefit from being 16-byte-aligned as well. I've made both those changes here, and enabled the additional alignment only when not -Os to address concerns about wasting memory. I noted that the additional alignment of static arrays is partially redundant with existing generic vector optimizations; I xfailed a couple of tests that were failing because there was nothing left for those passes to do any more. I regression-tested this on powerpc-none-eabi. OK to commit? -Sandra 2013-05-20 Sandra Loosemore Pat Wellander gcc/ * config/rs6000/rs6000-protos.h (rs6000_data_alignment): Declare. * config/rs6000/rs6000.c (align_for_altivec): New. (rs6000_data_alignment): New. * config/rs6000/rs6000.h (DATA_ALIGNMENT): Expand to call rs6000_data_alignment. gcc/testsuite/ * gcc.target/powerpc/altivec-35.c: New test case. * gcc.dg/vect/section-anchors-vect-69.c: Xfail for Altivec. * gcc.dg/vect/aligned-section-anchors-nest-1.c: Likewise. Index: gcc/config/rs6000/rs6000-protos.h =================================================================== --- gcc/config/rs6000/rs6000-protos.h (revision 199031) +++ gcc/config/rs6000/rs6000-protos.h (working copy) @@ -28,6 +28,7 @@ #ifdef TREE_CODE extern void init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx, int, int, int, tree, enum machine_mode); +extern unsigned rs6000_data_alignment (const_tree, unsigned); #endif /* TREE_CODE */ extern bool easy_altivec_constant (rtx, enum machine_mode); Index: gcc/config/rs6000/rs6000.c =================================================================== --- gcc/config/rs6000/rs6000.c (revision 199031) +++ gcc/config/rs6000/rs6000.c (working copy) @@ -5119,6 +5119,74 @@ invalid_e500_subreg (rtx op, enum machin return false; } +/* Return true if TYPE is a candidate for extra alignment on Altivec. + This includes arrays with size of at least 16 bytes (128 bits) and + structs/unions with such an array at an offset that is a multiple + of 16 bytes. */ +static bool +align_for_altivec (const_tree type) +{ + if (TREE_CODE (type) == ARRAY_TYPE + && tree_low_cst (TYPE_SIZE (type), 1) >= 128) + return true; + + else if (TREE_CODE (type) == RECORD_TYPE + || TREE_CODE (type) == UNION_TYPE) + { + tree field; + for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field)) + if (TREE_CODE (field) == FIELD_DECL + && (tree_low_cst (DECL_FIELD_OFFSET (field), 1) & 0xf) == 0 + && align_for_altivec (TREE_TYPE (field))) + return true; + } + + return false; +} + + +/* Implement DATA_ALIGNMENT. */ + +unsigned +rs6000_data_alignment (const_tree type, unsigned align) +{ + /* Align SPE vectors and paired floats to 64 bits and other vectors + to 128 bits. */ + if (TREE_CODE (type) == VECTOR_TYPE) + { + if (TARGET_SPE && SPE_VECTOR_MODE (TYPE_MODE (type))) + return 64; + else if (TARGET_PAIRED_FLOAT && PAIRED_VECTOR_MODE (TYPE_MODE (type))) + return 64; + else + return 128; + } + + /* Align E500 v2 doubles to 64 bits. */ + if (TARGET_E500_DOUBLE + && TREE_CODE (type) == REAL_TYPE + && TYPE_MODE (type) == DFmode) + return 64; + + /* Align Altivec arrays >= 16 bytes on a 16-byte boundary, but only + if not -Os. Also check for structs or unions containing such an array + appropriately aligned within the struct, and align them, too. + Note that on Altivec the stack is 16-byte aligned, otherwise this + would not work for local array variables. */ + if (TARGET_ALTIVEC && !optimize_size && align_for_altivec (type)) + return 128; + + /* Make char arrays word-aligned so strcpy will be faster. */ + if (TREE_CODE (type) == ARRAY_TYPE + && TYPE_MODE (TREE_TYPE (type)) == QImode + && align < BITS_PER_WORD) + return BITS_PER_WORD; + + /* Use the specified alignment. */ + return align; +} + + /* AIX increases natural record alignment to doubleword if the first field is an FP double while the FP fields remain word aligned. */ Index: gcc/config/rs6000/rs6000.h =================================================================== --- gcc/config/rs6000/rs6000.h (revision 199031) +++ gcc/config/rs6000/rs6000.h (working copy) @@ -782,21 +782,10 @@ extern unsigned rs6000_pointer_size; ? BITS_PER_WORD \ : (ALIGN)) -/* Make arrays of chars word-aligned for the same reasons. - Align vectors to 128 bits. Align SPE vectors and E500 v2 doubles to - 64 bits. */ +/* Data alignment requirements for SPE and Altivec are complicated enough + that we defer to a helper function. */ #define DATA_ALIGNMENT(TYPE, ALIGN) \ - (TREE_CODE (TYPE) == VECTOR_TYPE \ - ? (((TARGET_SPE && SPE_VECTOR_MODE (TYPE_MODE (TYPE))) \ - || (TARGET_PAIRED_FLOAT && PAIRED_VECTOR_MODE (TYPE_MODE (TYPE)))) \ - ? 64 : 128) \ - : ((TARGET_E500_DOUBLE \ - && TREE_CODE (TYPE) == REAL_TYPE \ - && TYPE_MODE (TYPE) == DFmode) \ - ? 64 \ - : (TREE_CODE (TYPE) == ARRAY_TYPE \ - && TYPE_MODE (TREE_TYPE (TYPE)) == QImode \ - && (ALIGN) < BITS_PER_WORD) ? BITS_PER_WORD : (ALIGN))) + (rs6000_data_alignment ((TYPE), (ALIGN))) /* Nonzero if move instructions will actually fail to work when given unaligned data. */ Index: gcc/testsuite/gcc.target/powerpc/altivec-35.c =================================================================== --- gcc/testsuite/gcc.target/powerpc/altivec-35.c (revision 0) +++ gcc/testsuite/gcc.target/powerpc/altivec-35.c (revision 0) @@ -0,0 +1,64 @@ +/* altivec-35.c */ +/* { dg-do run { target powerpc*-*-* } } */ +/* { dg-require-effective-target powerpc_altivec_ok } */ +/* { dg-options "-O0 -maltivec" } */ + +#include + +/* Check Alignment of large Altivec arrays is at least 128 bits. */ + +struct s +{ + int a[5]; + char b; +}; + +union u +{ + int a; + struct s ss; +}; + +long a1[5], a2[6], a3[4]; +char c1[17]; +struct s s1; +union u u1; + +#define CHECK(ADDR) \ + if (((long) (ADDR)) & 0xf) abort (); + +int main(void) +{ + long aa1[5], aa2[6], aa3[4]; + char cc1[17]; + struct s ss1; + union u uu1; + + static long aaa1[5], aaa2[6], aaa3[4]; + static char ccc1[17]; + static struct s sss1; + static union u uuu1; + + CHECK (a1); + CHECK (a2); + CHECK (a3); + CHECK (c1); + CHECK (&s1); + CHECK (&u1); + + CHECK (aa1); + CHECK (aa2); + CHECK (aa3); + CHECK (cc1); + CHECK (&ss1); + CHECK (&uu1); + + CHECK (aaa1); + CHECK (aaa2); + CHECK (aaa3); + CHECK (ccc1); + CHECK (&sss1); + CHECK (&uuu1); + + return 0; +} Index: gcc/testsuite/gcc.dg/vect/section-anchors-vect-69.c =================================================================== --- gcc/testsuite/gcc.dg/vect/section-anchors-vect-69.c (revision 199031) +++ gcc/testsuite/gcc.dg/vect/section-anchors-vect-69.c (working copy) @@ -115,6 +115,7 @@ int main (void) /* { dg-final { scan-tree-dump-times "Vectorizing an unaligned access" 0 "vect" } } */ /* Alignment forced using versioning until the pass that increases alignment is extended to handle structs. */ -/* { dg-final { scan-tree-dump-times "Alignment of access forced using peeling" 4 "vect" { target {vect_int && vector_alignment_reachable } } } } */ +/* Altivec already aligns these arrays appropriately by default. */ +/* { dg-final { scan-tree-dump-times "Alignment of access forced using peeling" 4 "vect" { target {vect_int && vector_alignment_reachable } xfail { powerpc_altivec_ok } } } } */ /* { dg-final { scan-tree-dump-times "Alignment of access forced using versioning" 4 "vect" { target {vect_int && {! vector_alignment_reachable} } } } } */ /* { dg-final { cleanup-tree-dump "vect" } } */ Index: gcc/testsuite/gcc.dg/vect/aligned-section-anchors-nest-1.c =================================================================== --- gcc/testsuite/gcc.dg/vect/aligned-section-anchors-nest-1.c (revision 199031) +++ gcc/testsuite/gcc.dg/vect/aligned-section-anchors-nest-1.c (working copy) @@ -30,5 +30,7 @@ int *foo(void) return &c[0][0]; } -/* { dg-final { scan-ipa-dump-times "Increasing alignment of decl" 3 "increase_alignment" } } */ +/* Altivec already aligns these arrays appropriately by default, so there + is nothing for the increase_alignment pass to do. */ +/* { dg-final { scan-ipa-dump-times "Increasing alignment of decl" 3 "increase_alignment" { xfail { powerpc_altivec_ok } } } } */ /* { dg-final { cleanup-ipa-dump "increase_alignment" } } */