From patchwork Tue Dec 6 22:24:09 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Botcazou X-Patchwork-Id: 129837 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 A2A181007D5 for ; Wed, 7 Dec 2011 09:26:15 +1100 (EST) Received: (qmail 22143 invoked by alias); 6 Dec 2011 22:26:13 -0000 Received: (qmail 22133 invoked by uid 22791); 6 Dec 2011 22:26:11 -0000 X-SWARE-Spam-Status: No, hits=-1.9 required=5.0 tests=AWL,BAYES_00,TW_CP X-Spam-Check-By: sourceware.org Received: from mel.act-europe.fr (HELO mel.act-europe.fr) (194.98.77.210) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Tue, 06 Dec 2011 22:25:57 +0000 Received: from localhost (localhost [127.0.0.1]) by filtered-smtp.eu.adacore.com (Postfix) with ESMTP id EBC80CB0F8F for ; Tue, 6 Dec 2011 23:25:57 +0100 (CET) Received: from mel.act-europe.fr ([127.0.0.1]) by localhost (smtp.eu.adacore.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id GFtDLA0OU8bc for ; Tue, 6 Dec 2011 23:25:57 +0100 (CET) Received: from [192.168.1.2] (bon31-6-88-161-99-133.fbx.proxad.net [88.161.99.133]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by mel.act-europe.fr (Postfix) with ESMTP id A546ACB0F2D for ; Tue, 6 Dec 2011 23:25:57 +0100 (CET) From: Eric Botcazou To: gcc-patches@gcc.gnu.org Subject: [PATCH] Fix PR tree-optimization/51315 Date: Tue, 6 Dec 2011 23:24:09 +0100 User-Agent: KMail/1.9.9 MIME-Version: 1.0 Message-Id: <201112062324.09783.ebotcazou@adacore.com> 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 Hi, this is a regression present on mainline and 4.6 branch at -O for the SPARC. The compiler generates an unaligned access for the memcpy call in: char *s union { int32_t i; char a[sizeof (int32_t)]; } v; memcpy (v.a, s, sizeof (int32_t)); The memcpy call is folded to an assignment between a couple of MEM_REFs: MEM[(char * {ref-all})&v] = MEM[(char * {ref-all})s_1]; with type 'char a[4]'. The problem is that SRA turns this into: v$i_27 = MEM[(char * {ref-all})s_1].i; but s isn't aligned enough for an int32_t access. I don't think we can scalarize in this case on strict-alignment targets. The SRA pass already contains an alignment check, but it is purely internal to the RHS and this is clearly not sufficient anymore with MEM_REFs. The proposed fix is to enhance this alignment check to take into account both the RHS and the LHS (much like the memcpy folder). I think it subsumes the previous check, which could be viewed as a check involving the RHS and the type of the LHS. But there is a hitch: get_object_alignment is conservative for MEM_REF (unlike for INDIRECT_REF) so a trick is needed in order not to pessimize in some cases. Tested on SPARC/Solaris. OK for mainline and 4.6 branch? 2011-12-06 Eric Botcazou PR tree-optimization/51315 * tree-sra.c (tree_non_mode_aligned_mem_p): Rename to... (tree_non_aligned_mem_p): ...this. Add ALIGN parameter. Look into MEM_REFs and deal with simple dereferences specially. (build_accesses_from_assign): Adjust for above change. (access_precludes_ipa_sra_p): Likewise. 2011-12-06 Eric Botcazou * gcc.c-torture/execute/20111206-1.c: New test. Index: tree-sra.c =================================================================== --- tree-sra.c (revision 181993) +++ tree-sra.c (working copy) @@ -1067,26 +1067,31 @@ disqualify_ops_if_throwing_stmt (gimple return false; } -/* Return true iff type of EXP is not sufficiently aligned. */ +/* Return true if EXP is a memory reference less aligned than ALIGN. This is + invoked only on strict-alignment targets. */ static bool -tree_non_mode_aligned_mem_p (tree exp) +tree_non_aligned_mem_p (tree exp, unsigned int align) { - enum machine_mode mode = TYPE_MODE (TREE_TYPE (exp)); - unsigned int align; + unsigned int exp_align; if (TREE_CODE (exp) == VIEW_CONVERT_EXPR) exp = TREE_OPERAND (exp, 0); - if (TREE_CODE (exp) == SSA_NAME - || TREE_CODE (exp) == MEM_REF - || mode == BLKmode - || is_gimple_min_invariant (exp) - || !STRICT_ALIGNMENT) + if (TREE_CODE (exp) == SSA_NAME || is_gimple_min_invariant (exp)) return false; - align = get_object_alignment (exp); - if (GET_MODE_ALIGNMENT (mode) > align) + /* get_object_alignment will fall back to BITS_PER_UNIT if it cannot + compute an explicit alignment. Pretend that dereferenced pointers + are always aligned on strict-alignment targets. */ + if (TREE_CODE (exp) == MEM_REF + && TREE_CODE (TREE_OPERAND (exp, 0)) == SSA_NAME + && integer_zerop (TREE_OPERAND (exp, 1))) + exp_align = TYPE_ALIGN (TREE_TYPE (exp)); + else + exp_align = get_object_alignment (exp); + + if (exp_align < align) return true; return false; @@ -1120,7 +1125,9 @@ build_accesses_from_assign (gimple stmt) if (lacc) { lacc->grp_assignment_write = 1; - lacc->grp_unscalarizable_region |= tree_non_mode_aligned_mem_p (rhs); + if (STRICT_ALIGNMENT + && tree_non_aligned_mem_p (rhs, get_object_alignment (lhs))) + lacc->grp_unscalarizable_region = 1; } if (racc) @@ -1129,7 +1136,9 @@ build_accesses_from_assign (gimple stmt) if (should_scalarize_away_bitmap && !gimple_has_volatile_ops (stmt) && !is_gimple_reg_type (racc->type)) bitmap_set_bit (should_scalarize_away_bitmap, DECL_UID (racc->base)); - racc->grp_unscalarizable_region |= tree_non_mode_aligned_mem_p (lhs); + if (STRICT_ALIGNMENT + && tree_non_aligned_mem_p (lhs, get_object_alignment (rhs))) + racc->grp_unscalarizable_region = 1; } if (lacc && racc @@ -3705,7 +3714,8 @@ access_precludes_ipa_sra_p (struct acces || gimple_code (access->stmt) == GIMPLE_ASM)) return true; - if (tree_non_mode_aligned_mem_p (access->expr)) + if (STRICT_ALIGNMENT + && tree_non_aligned_mem_p (access->expr, TYPE_ALIGN (access->type))) return true; return false;