From patchwork Thu Aug 8 14:11:44 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bernd Edlinger X-Patchwork-Id: 1144044 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-506503-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=hotmail.de Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="KM2nE+kt"; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4649Ky3rnQz9sNx for ; Fri, 9 Aug 2019 00:12:04 +1000 (AEST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:cc:subject:date:message-id:references:in-reply-to :content-type:mime-version; q=dns; s=default; b=eCoU7Le7lfvrTJic GNCvv6fj5LDRd1rVJvZlc3EWD9W9QyUNrWA7zeOWDgSjDl86a0/v3K6sdCBm0Mef ww+sbg0LlYZOpFkrU32H2nWaWZO8eCmwU64cxxiO2wD5h2Yq2E41HWyceOis0Q9Z Cd4tsRmNFHGqF1DmgiENyPj8w2g= 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:from :to:cc:subject:date:message-id:references:in-reply-to :content-type:mime-version; s=default; bh=YzfhTTMIMHYrewoaeK1wJD PeFms=; b=KM2nE+ktJ5dKKr+IDCTrPInt0eFL4pL6qh+wC7Wa0DSOxQJjZWIFC0 NpXe/yOpp1Tus4bAPbbKM92jYocpJj2QqNAF3Whh+SZBAClHsFMoGAt9ScNigFEI wVuQJuWuArIXiD7dgkoCIDZMnI/royeu3sBzJx257XJDwr/FPZGp8= Received: (qmail 34326 invoked by alias); 8 Aug 2019 14:11:53 -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 34304 invoked by uid 89); 8 Aug 2019 14:11:52 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-9.3 required=5.0 tests=AWL, BAYES_00, FREEMAIL_FROM, GIT_PATCH_2, GIT_PATCH_3, KAM_ASCII_DIVIDERS, RCVD_IN_DNSWL_NONE, SPF_HELO_PASS, SPF_PASS autolearn=ham version=3.3.1 spammy=builtins.c, UD:builtins.c, builtinsc, H*M:COM X-HELO: EUR02-HE1-obe.outbound.protection.outlook.com Received: from mail-oln040092068044.outbound.protection.outlook.com (HELO EUR02-HE1-obe.outbound.protection.outlook.com) (40.92.68.44) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Thu, 08 Aug 2019 14:11:49 +0000 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=a9fepw5jrA3BrmXxrn12JT7pokII7sDJ6VTOlgNC2I6a0hNaie09aXScpcLgzeLAXMZ4VP1BI9K6tMWwXT3VY94dqAn7FX/bbNDxn3SQTb0W3/DOoxD380QJUnlBHwt4w2pUWp0OtNK7QcqEZBsbqUoobcTL1aRc5Q88lm2WW9JmWAIYSQ9nPcgVRKfWM4scsW7CmyD289k1v02Z2m8ZQP9cp90uWuWcPWED9r2KymFMQnKy5+AaYNdmvHmG7noTFMOjRT0WdTKLR1DPq6mv95AotDu4qUZhK19HwPnqSxrxDI87+0MuyUDwbuveeEPPvAaMxh++ttMdnAmF/Vh91g== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=Kn9/SRPOIClPg920uhWW0WjiI36TawYXKFIZUUfj5MA=; b=deaoWLpYiDDhL6gAeC2ae+hRWu5CKD0rrRSPEji7uYNhgSWeV+tJrBK1m0IrAsPcYQY1yaorTLCvBQ7oHj3r/t6TXMN1K840TSbWYrfl73rjylfghQagg51rAQI2z1XZ8MF+EgDTRl8lotNA9EW27CIIweTwGQ5iOgNbEMxtl/spkhlOI4WfIvB0oMhCatdpSO5ZOxyavzahLC6rT5Mk+9+yOCbArUqpPMpyEdlZ0snY0Jy7zi7gEOaxDqH9nEzew/PFkZyn8LK8d4WOyin0biV4ckFhQNJX42eXn7xCJ/TPa+gD/5kgzl2V/Em4O7nqh9AdOn7pP8kHC27WWixChw== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=none; dmarc=none; dkim=none; arc=none Received: from HE1EUR02FT035.eop-EUR02.prod.protection.outlook.com (10.152.10.59) by HE1EUR02HT211.eop-EUR02.prod.protection.outlook.com (10.152.11.162) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384) id 15.20.2157.15; Thu, 8 Aug 2019 14:11:45 +0000 Received: from DB8PR10MB2569.EURPRD10.PROD.OUTLOOK.COM (10.152.10.59) by HE1EUR02FT035.mail.protection.outlook.com (10.152.10.127) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.2157.15 via Frontend Transport; Thu, 8 Aug 2019 14:11:45 +0000 Received: from DB8PR10MB2569.EURPRD10.PROD.OUTLOOK.COM ([fe80::d568:f5a6:5afc:c60e]) by DB8PR10MB2569.EURPRD10.PROD.OUTLOOK.COM ([fe80::d568:f5a6:5afc:c60e%7]) with mapi id 15.20.2115.005; Thu, 8 Aug 2019 14:11:45 +0000 From: Bernd Edlinger To: Richard Biener CC: "gcc-patches@gcc.gnu.org" , Richard Earnshaw , Ramana Radhakrishnan , Kyrill Tkachov , Eric Botcazou , Jeff Law , Jakub Jelinek Subject: [PATCHv4] Fix not 8-byte aligned ldrd/strd on ARMv5 (PR 89544) Date: Thu, 8 Aug 2019 14:11:44 +0000 Message-ID: References: In-Reply-To: x-microsoft-original-message-id: x-ms-exchange-transport-forked: True MIME-Version: 1.0 On 8/2/19 9:01 PM, Bernd Edlinger wrote: > On 8/2/19 3:11 PM, Richard Biener wrote: >> On Tue, 30 Jul 2019, Bernd Edlinger wrote: >> >>> >>> I have no test coverage for the movmisalign optab though, so I >>> rely on your code review for that part. >> >> It looks OK. I tried to make it trigger on the following on >> i?86 with -msse2: >> >> typedef int v4si __attribute__((vector_size (16))); >> >> struct S { v4si v; } __attribute__((packed)); >> >> v4si foo (struct S s) >> { >> return s.v; >> } >> > > Hmm, the entry_parm need to be a MEM_P and an unaligned one. > So the test case could be made to trigger it this way: > > typedef int v4si __attribute__((vector_size (16))); > > struct S { v4si v; } __attribute__((packed)); > > int t; > v4si foo (struct S a, struct S b, struct S c, struct S d, > struct S e, struct S f, struct S g, struct S h, > int i, int j, int k, int l, int m, int n, > int o, struct S s) > { > t = o; > return s.v; > } > Ah, I realized that there are already a couple of very similar test cases: gcc.target/i386/pr35767-1.c, gcc.target/i386/pr35767-1d.c, gcc.target/i386/pr35767-1i.c and gcc.target/i386/pr39445.c, which also manage to execute the movmisalign code with the latest patch version. So I thought that it is not necessary to add another one. > However the code path is still not reached, since targetm.slow_ualigned_access > is always FALSE, which is probably a flaw in my patch. > > So I think, > > + else if (MEM_P (data->entry_parm) > + && GET_MODE_ALIGNMENT (promoted_nominal_mode) > + > MEM_ALIGN (data->entry_parm) > + && targetm.slow_unaligned_access (promoted_nominal_mode, > + MEM_ALIGN (data->entry_parm))) > > should probably better be > > + else if (MEM_P (data->entry_parm) > + && GET_MODE_ALIGNMENT (promoted_nominal_mode) > + > MEM_ALIGN (data->entry_parm) > + && (((icode = optab_handler (movmisalign_optab, promoted_nominal_mode)) > + != CODE_FOR_nothing) > + || targetm.slow_unaligned_access (promoted_nominal_mode, > + MEM_ALIGN (data->entry_parm)))) > > Right? > > Then the modified test case would use the movmisalign optab. > However nothing changes in the end, since the i386 back-end is used to work > around the middle end not using movmisalign optab when it should do so. > I prefer the second form of the check, as it offers more test coverage, and is probably more correct than the former. Note there are more variations of this misalign check in expr.c, some are somehow odd, like expansion of MEM_REF and VIEW_CONVERT_EXPR: && mode != BLKmode && align < GET_MODE_ALIGNMENT (mode)) { if ((icode = optab_handler (movmisalign_optab, mode)) != CODE_FOR_nothing) [...] else if (targetm.slow_unaligned_access (mode, align)) temp = extract_bit_field (temp, GET_MODE_BITSIZE (mode), 0, TYPE_UNSIGNED (TREE_TYPE (exp)), (modifier == EXPAND_STACK_PARM ? NULL_RTX : target), mode, mode, false, alt_rtl); I wonder if they are correct this way, why shouldn't we use the movmisalign optab if it exists, regardless of TARGET_SLOW_UNALIGNED_ACCESSS ? > I wonder if I should try to add a gcc_checking_assert to the mov expand > patterns that the memory is properly aligned ? > Wow, that was a really exciting bug-hunt with those assertions around... >> @@ -3292,6 +3306,23 @@ assign_parm_setup_reg (struct assign_parm_data_all >> >> did_conversion = true; >> } >> + else if (MEM_P (data->entry_parm) >> + && GET_MODE_ALIGNMENT (promoted_nominal_mode) >> + > MEM_ALIGN (data->entry_parm) >> >> we arrive here by-passing >> >> else if (need_conversion) >> { >> /* We did not have an insn to convert directly, or the sequence >> generated appeared unsafe. We must first copy the parm to a >> pseudo reg, and save the conversion until after all >> parameters have been moved. */ >> >> int save_tree_used; >> rtx tempreg = gen_reg_rtx (GET_MODE (data->entry_parm)); >> >> emit_move_insn (tempreg, validated_mem); >> >> but this move instruction is invalid in the same way as the case >> you fix, no? So wouldn't it be better to do >> > > We could do that, but I supposed that there must be a reason why > assign_parm_setup_stack gets away with that same: > > if (data->promoted_mode != data->nominal_mode) > { > /* Conversion is required. */ > rtx tempreg = gen_reg_rtx (GET_MODE (data->entry_parm)); > > emit_move_insn (tempreg, validize_mem (copy_rtx (data->entry_parm))); > > > So either some back-ends are too permissive with us, > or there is a reason why promoted_mode != nominal_mode > does not happen together with unaligned entry_parm. > In a way that would be a rather unusual ABI. > To find out if that ever happens I added a couple of checking assertions in the arm mov expand patterns. So far the assertions did (almost) always hold, so it is likely not necessary to fiddle with all those naive move instructions here. So my gut feeling is, leave those places alone until there is a reason for changing them. However the assertion in movsi triggered a couple times in the ada testsuite due to expand_builtin_init_descriptor using a BLKmode MEM rtx, which is only 8-bit aligned. So, I set the ptr_mode alignment there explicitly. Several struct-layout-1.dg testcase tripped over misaligned complex_cst constants, fixed by varasm.c (align_variable). This is likely a wrong code bug, because misaligned complex constants, are expanded to misaligned MEM_REF, but the expansion cannot handle misaligned constants, only packed structure fields. Furthermore gcc.dg/Warray-bounds-33.c was fixed by the change in expr.c (expand_expr_real_1). Certainly is it invalid to read memory at a function address, but it should not ICE. The problem here, is the MEM_REF has no valid MEM_ALIGN, it looks like A32, so the misaligned code execution is not taken, but it is set to A8 below, but then we hit an ICE if the result is used: /* Don't set memory attributes if the base expression is SSA_NAME that got expanded as a MEM. In that case, we should just honor its original memory attributes. */ if (TREE_CODE (tem) != SSA_NAME || !MEM_P (orig_op0)) set_mem_attributes (op0, exp, 0); Finally gcc.dg/torture/pr48493.c required the change in assign_parm_setup_stack. This is just not using the correct MEM_ALIGN attribute value, while the memory is actually aligned. Note that set_mem_attributes does not always preserve the MEM_ALIGN of the ref, since: /* Default values from pre-existing memory attributes if present. */ refattrs = MEM_ATTRS (ref); if (refattrs) { /* ??? Can this ever happen? Calling this routine on a MEM that already carries memory attributes should probably be invalid. */ attrs.expr = refattrs->expr; attrs.offset_known_p = refattrs->offset_known_p; attrs.offset = refattrs->offset; attrs.size_known_p = refattrs->size_known_p; attrs.size = refattrs->size; attrs.align = refattrs->align; } but if we happen to set_mem_align to _exactly_ the MODE_ALIGNMENT the MEM_ATTRS are zero, and a smaller alignment may result. Well with those checks in place it should now be a lot harder to generate invalid code on STRICT_ALIGNMENT targets, without running into an ICE. Attached is the latest version of my arm alignment patch. Boot-strapped and reg-tested on x64_64-pc-linux-gnu and arm-linux-gnueabihf. Is it OK for trunk? Thanks Bernd. 2019-08-05 Bernd Edlinger PR middle-end/89544 * builtins.c (expand_builtin_init_descriptor): Set memory alignment. * expr.c (expand_expr_real_1): Handle FUNCTION_DECL as unaligned. * function.c (assign_parm_find_stack_rtl): Use larger alignment when possible. (assign_parm_setup_reg): Handle misaligned stack arguments. (assign_parm_setup_stack): Allocate properly aligned stack slots. * varasm.c (align_variable): Align constants of misaligned types. * config/arm/arm.md (movdi, movsi, movhi, movhf, movsf, movdf): Check strict alignment restrictions on memory addresses. * config/arm/neon.md (movti, mov, mov): Likewise. * config/arm/vec-common.md (mov): Likewise. testsuite: 2019-08-05 Bernd Edlinger PR middle-end/89544 * gcc.target/arm/unaligned-argument-1.c: New test. * gcc.target/arm/unaligned-argument-2.c: New test. Index: gcc/builtins.c =================================================================== --- gcc/builtins.c (revision 274168) +++ gcc/builtins.c (working copy) @@ -5756,6 +5756,7 @@ expand_builtin_init_descriptor (tree exp) r_descr = expand_normal (t_descr); m_descr = gen_rtx_MEM (BLKmode, r_descr); MEM_NOTRAP_P (m_descr) = 1; + set_mem_align (m_descr, GET_MODE_ALIGNMENT (ptr_mode)); r_func = expand_normal (t_func); r_chain = expand_normal (t_chain); Index: gcc/config/arm/arm.md =================================================================== --- gcc/config/arm/arm.md (revision 274168) +++ gcc/config/arm/arm.md (working copy) @@ -5824,6 +5824,12 @@ (match_operand:DI 1 "general_operand"))] "TARGET_EITHER" " + gcc_checking_assert (!MEM_P (operands[0]) + || MEM_ALIGN (operands[0]) + >= GET_MODE_ALIGNMENT (DImode)); + gcc_checking_assert (!MEM_P (operands[1]) + || MEM_ALIGN (operands[1]) + >= GET_MODE_ALIGNMENT (DImode)); if (can_create_pseudo_p ()) { if (!REG_P (operands[0])) @@ -6000,6 +6006,12 @@ { rtx base, offset, tmp; + gcc_checking_assert (!MEM_P (operands[0]) + || MEM_ALIGN (operands[0]) + >= GET_MODE_ALIGNMENT (SImode)); + gcc_checking_assert (!MEM_P (operands[1]) + || MEM_ALIGN (operands[1]) + >= GET_MODE_ALIGNMENT (SImode)); if (TARGET_32BIT || TARGET_HAVE_MOVT) { /* Everything except mem = const or mem = mem can be done easily. */ @@ -6489,6 +6501,12 @@ (match_operand:HI 1 "general_operand"))] "TARGET_EITHER" " + gcc_checking_assert (!MEM_P (operands[0]) + || MEM_ALIGN (operands[0]) + >= GET_MODE_ALIGNMENT (HImode)); + gcc_checking_assert (!MEM_P (operands[1]) + || MEM_ALIGN (operands[1]) + >= GET_MODE_ALIGNMENT (HImode)); if (TARGET_ARM) { if (can_create_pseudo_p ()) @@ -6898,6 +6916,12 @@ (match_operand:HF 1 "general_operand"))] "TARGET_EITHER" " + gcc_checking_assert (!MEM_P (operands[0]) + || MEM_ALIGN (operands[0]) + >= GET_MODE_ALIGNMENT (HFmode)); + gcc_checking_assert (!MEM_P (operands[1]) + || MEM_ALIGN (operands[1]) + >= GET_MODE_ALIGNMENT (HFmode)); if (TARGET_32BIT) { if (MEM_P (operands[0])) @@ -6962,6 +6986,12 @@ (match_operand:SF 1 "general_operand"))] "TARGET_EITHER" " + gcc_checking_assert (!MEM_P (operands[0]) + || MEM_ALIGN (operands[0]) + >= GET_MODE_ALIGNMENT (SFmode)); + gcc_checking_assert (!MEM_P (operands[1]) + || MEM_ALIGN (operands[1]) + >= GET_MODE_ALIGNMENT (SFmode)); if (TARGET_32BIT) { if (MEM_P (operands[0])) @@ -7057,6 +7087,12 @@ (match_operand:DF 1 "general_operand"))] "TARGET_EITHER" " + gcc_checking_assert (!MEM_P (operands[0]) + || MEM_ALIGN (operands[0]) + >= GET_MODE_ALIGNMENT (DFmode)); + gcc_checking_assert (!MEM_P (operands[1]) + || MEM_ALIGN (operands[1]) + >= GET_MODE_ALIGNMENT (DFmode)); if (TARGET_32BIT) { if (MEM_P (operands[0])) Index: gcc/config/arm/neon.md =================================================================== --- gcc/config/arm/neon.md (revision 274168) +++ gcc/config/arm/neon.md (working copy) @@ -127,6 +127,12 @@ (match_operand:TI 1 "general_operand"))] "TARGET_NEON" { + gcc_checking_assert (!MEM_P (operands[0]) + || MEM_ALIGN (operands[0]) + >= GET_MODE_ALIGNMENT (TImode)); + gcc_checking_assert (!MEM_P (operands[1]) + || MEM_ALIGN (operands[1]) + >= GET_MODE_ALIGNMENT (TImode)); if (can_create_pseudo_p ()) { if (!REG_P (operands[0])) @@ -139,6 +145,12 @@ (match_operand:VSTRUCT 1 "general_operand"))] "TARGET_NEON" { + gcc_checking_assert (!MEM_P (operands[0]) + || MEM_ALIGN (operands[0]) + >= GET_MODE_ALIGNMENT (mode)); + gcc_checking_assert (!MEM_P (operands[1]) + || MEM_ALIGN (operands[1]) + >= GET_MODE_ALIGNMENT (mode)); if (can_create_pseudo_p ()) { if (!REG_P (operands[0])) @@ -151,6 +163,12 @@ (match_operand:VH 1 "s_register_operand"))] "TARGET_NEON" { + gcc_checking_assert (!MEM_P (operands[0]) + || MEM_ALIGN (operands[0]) + >= GET_MODE_ALIGNMENT (mode)); + gcc_checking_assert (!MEM_P (operands[1]) + || MEM_ALIGN (operands[1]) + >= GET_MODE_ALIGNMENT (mode)); if (can_create_pseudo_p ()) { if (!REG_P (operands[0])) Index: gcc/config/arm/vec-common.md =================================================================== --- gcc/config/arm/vec-common.md (revision 274168) +++ gcc/config/arm/vec-common.md (working copy) @@ -26,6 +26,12 @@ "TARGET_NEON || (TARGET_REALLY_IWMMXT && VALID_IWMMXT_REG_MODE (mode))" { + gcc_checking_assert (!MEM_P (operands[0]) + || MEM_ALIGN (operands[0]) + >= GET_MODE_ALIGNMENT (mode)); + gcc_checking_assert (!MEM_P (operands[1]) + || MEM_ALIGN (operands[1]) + >= GET_MODE_ALIGNMENT (mode)); if (can_create_pseudo_p ()) { if (!REG_P (operands[0])) Index: gcc/expr.c =================================================================== --- gcc/expr.c (revision 274168) +++ gcc/expr.c (working copy) @@ -10796,6 +10796,14 @@ expand_expr_real_1 (tree exp, rtx target, machine_ MEM_VOLATILE_P (op0) = 1; } + if (MEM_P (op0) && TREE_CODE (tem) == FUNCTION_DECL) + { + if (op0 == orig_op0) + op0 = copy_rtx (op0); + + set_mem_align (op0, BITS_PER_UNIT); + } + /* In cases where an aligned union has an unaligned object as a field, we might be extracting a BLKmode value from an integer-mode (e.g., SImode) object. Handle this case Index: gcc/function.c =================================================================== --- gcc/function.c (revision 274168) +++ gcc/function.c (working copy) @@ -2697,8 +2697,23 @@ assign_parm_find_stack_rtl (tree parm, struct assi intentionally forcing upward padding. Otherwise we have to come up with a guess at the alignment based on OFFSET_RTX. */ poly_int64 offset; - if (data->locate.where_pad != PAD_DOWNWARD || data->entry_parm) + if (data->locate.where_pad == PAD_NONE || data->entry_parm) align = boundary; + else if (data->locate.where_pad == PAD_UPWARD) + { + align = boundary; + /* If the argument offset is actually more aligned than the nominal + stack slot boundary, take advantage of that excess alignment. + Don't make any assumptions if STACK_POINTER_OFFSET is in use. */ + if (poly_int_rtx_p (offset_rtx, &offset) + && STACK_POINTER_OFFSET == 0) + { + unsigned int offset_align = known_alignment (offset) * BITS_PER_UNIT; + if (offset_align == 0 || offset_align > STACK_BOUNDARY) + offset_align = STACK_BOUNDARY; + align = MAX (align, offset_align); + } + } else if (poly_int_rtx_p (offset_rtx, &offset)) { align = least_bit_hwi (boundary); @@ -3127,6 +3142,7 @@ assign_parm_setup_reg (struct assign_parm_data_all int unsignedp = TYPE_UNSIGNED (TREE_TYPE (parm)); bool did_conversion = false; bool need_conversion, moved; + enum insn_code icode; rtx rtl; /* Store the parm in a pseudoregister during the function, but we may @@ -3188,7 +3204,6 @@ assign_parm_setup_reg (struct assign_parm_data_all conversion. We verify that this insn does not clobber any hard registers. */ - enum insn_code icode; rtx op0, op1; icode = can_extend_p (promoted_nominal_mode, data->passed_mode, @@ -3291,6 +3306,23 @@ assign_parm_setup_reg (struct assign_parm_data_all did_conversion = true; } + else if (MEM_P (data->entry_parm) + && GET_MODE_ALIGNMENT (promoted_nominal_mode) + > MEM_ALIGN (data->entry_parm) + && (((icode = optab_handler (movmisalign_optab, + promoted_nominal_mode)) + != CODE_FOR_nothing) + || targetm.slow_unaligned_access (promoted_nominal_mode, + MEM_ALIGN (data->entry_parm)))) + { + if (icode != CODE_FOR_nothing) + emit_insn (GEN_FCN (icode) (parmreg, validated_mem)); + else + rtl = parmreg = extract_bit_field (validated_mem, + GET_MODE_BITSIZE (promoted_nominal_mode), 0, + unsignedp, parmreg, + promoted_nominal_mode, VOIDmode, false, NULL); + } else emit_move_insn (parmreg, validated_mem); @@ -3449,11 +3481,17 @@ assign_parm_setup_stack (struct assign_parm_data_a int align = STACK_SLOT_ALIGNMENT (data->passed_type, GET_MODE (data->entry_parm), TYPE_ALIGN (data->passed_type)); + if (align < (int)GET_MODE_ALIGNMENT (GET_MODE (data->entry_parm)) + && targetm.slow_unaligned_access (GET_MODE (data->entry_parm), + align)) + align = GET_MODE_ALIGNMENT (GET_MODE (data->entry_parm)); data->stack_parm = assign_stack_local (GET_MODE (data->entry_parm), GET_MODE_SIZE (GET_MODE (data->entry_parm)), align); + align = MEM_ALIGN (data->stack_parm); set_mem_attributes (data->stack_parm, parm, 1); + set_mem_align (data->stack_parm, align); } dest = validize_mem (copy_rtx (data->stack_parm)); Index: gcc/testsuite/gcc.target/arm/unaligned-argument-1.c =================================================================== --- gcc/testsuite/gcc.target/arm/unaligned-argument-1.c (revision 0) +++ gcc/testsuite/gcc.target/arm/unaligned-argument-1.c (working copy) @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target arm_arm_ok } */ +/* { dg-require-effective-target arm_ldrd_strd_ok } */ +/* { dg-options "-marm -mno-unaligned-access -O3" } */ + +struct s { + int a, b; +} __attribute__((aligned(8))); + +struct s f0; + +void f(int a, int b, int c, int d, struct s f) +{ + f0 = f; +} + +/* { dg-final { scan-assembler-times "ldrd" 1 } } */ +/* { dg-final { scan-assembler-times "strd" 1 } } */ +/* { dg-final { scan-assembler-times "stm" 0 } } */ Index: gcc/testsuite/gcc.target/arm/unaligned-argument-2.c =================================================================== --- gcc/testsuite/gcc.target/arm/unaligned-argument-2.c (revision 0) +++ gcc/testsuite/gcc.target/arm/unaligned-argument-2.c (working copy) @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target arm_arm_ok } */ +/* { dg-require-effective-target arm_ldrd_strd_ok } */ +/* { dg-options "-marm -mno-unaligned-access -O3" } */ + +struct s { + int a, b; +} __attribute__((aligned(8))); + +struct s f0; + +void f(int a, int b, int c, int d, int e, struct s f) +{ + f0 = f; +} + +/* { dg-final { scan-assembler-times "ldrd" 0 } } */ +/* { dg-final { scan-assembler-times "strd" 0 } } */ +/* { dg-final { scan-assembler-times "stm" 1 } } */ Index: gcc/varasm.c =================================================================== --- gcc/varasm.c (revision 274168) +++ gcc/varasm.c (working copy) @@ -1085,6 +1085,10 @@ align_variable (tree decl, bool dont_output_data) } } + if (align < GET_MODE_ALIGNMENT (DECL_MODE (decl)) + && targetm.slow_unaligned_access (DECL_MODE (decl), align)) + align = GET_MODE_ALIGNMENT (DECL_MODE (decl)); + /* Reset the alignment in case we have made it tighter, so we can benefit from it in get_pointer_alignment. */ SET_DECL_ALIGN (decl, align);