From patchwork Wed Nov 2 17:08:34 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thomas Preudhomme X-Patchwork-Id: 690491 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.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3t8F1p57L7z9vDY for ; Thu, 3 Nov 2016 04:09:01 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b=SLm2qdJE; dkim-atps=neutral DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:to :from:subject:message-id:date:mime-version:content-type; q=dns; s=default; b=PuTyujdBuPWvD+OzITvZzvJfn5btxhc7bON1PeywmgogRC1oei R6riXhboaCZHjfOTt8GHYXGw9q8Nj75IoVAnDy8SEa5IPBj2lGF/bj7f0X2I2bdy BwMeOYnM976lPhP/1WWvV30SiDqW/VPW2rG5eGNDMqLVilp/DL4yEvahk= 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:to :from:subject:message-id:date:mime-version:content-type; s= default; bh=3N0/7BGggAEKDwDfyY9Vq/fhGeA=; b=SLm2qdJEYmCv4ljah1kv 7za3uYCXUcnxTfHafEShJAy5/8q554zkltRGkO1iXSPhw56V+ixDJIFzdcDQjr1K cd0k7+CZvdSE32RaYJFCvUZGwh5dNWai2SLqj2YdOmtU5lmwm0hNtLtwrp7dhaYR j2xABB7fCKb5QctDTqTBxwk= Received: (qmail 67573 invoked by alias); 2 Nov 2016 17:08:49 -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 67018 invoked by uid 89); 2 Nov 2016 17:08:48 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-3.2 required=5.0 tests=BAYES_00, KAM_LAZY_DOMAIN_SECURITY, RP_MATCHES_RCVD autolearn=ham version=3.3.2 spammy=Hx-languages-length:2504, LR_REGNUM, lr_regnum X-HELO: foss.arm.com Received: from foss.arm.com (HELO foss.arm.com) (217.140.101.70) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Wed, 02 Nov 2016 17:08:38 +0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.72.51.249]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 9A42229; Wed, 2 Nov 2016 10:08:36 -0700 (PDT) Received: from [10.2.206.52] (usa-sjc-imap-foss1.foss.arm.com [10.72.51.249]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id DADDF3F318; Wed, 2 Nov 2016 10:08:35 -0700 (PDT) To: Kyrill Tkachov , Ramana Radhakrishnan , Richard Earnshaw , "gcc-patches@gcc.gnu.org" From: Thomas Preudhomme Subject: [PATCH, GCC/ARM] Fix PR77933: stack corruption on ARM when using high registers and lr Message-ID: <34d1835c-9eea-1f86-0c93-30aeace74762@foss.arm.com> Date: Wed, 2 Nov 2016 17:08:34 +0000 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.2.0 MIME-Version: 1.0 X-IsSubscribed: yes Hi, When saving registers, function thumb1_expand_prologue () aims at minimizing the number of push instructions. One of the optimization it does is to push lr alongside high register(s) (after having moved them to low register(s)) when there is no low register to save. The way this is implemented is to add lr to the list of registers that can be pushed just before the push happens. This would then push lr and allows it to be used for further push if there was not enough registers to push all high registers to be pushed. However, the logic that decides what register to move high registers to before being pushed only looks at low registers (see for loop initialization). This means not only that lr is not used for pushing high registers but also that lr is not removed from the list of registers to be pushed when it's not used. This extra lr push is not poped in epilogue leading in stack corruption. This patch changes the loop to iterate over register r0 to lr so as to both fix the stack corruption and reuse lr to push some high register when possible. ChangeLog entry are as follow: *** gcc/ChangeLog *** 2016-11-01 Thomas Preud'homme PR target/77933 * config/arm/arm.c (thumb1_expand_prologue): Also check for lr being a pushable register. *** gcc/testsuite/ChangeLog *** 2016-11-01 Thomas Preud'homme PR target/77933 * gcc.target/arm/pr77933.c: New test. Testing: no regression on arm-none-eabi GCC cross-compiler targeting Cortex-M0 Is this ok for trunk? Best regards, Thomas diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index dd8d5e5db8ca50daab648e58df290969aa794862..22a20caf42389748fc64ee0a3f880c6bea4c8f49 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -24990,7 +24990,7 @@ thumb1_expand_prologue (void) { unsigned long real_regs_mask = 0; - for (regno = LAST_LO_REGNUM; regno >= 0; regno --) + for (regno = LR_REGNUM; regno >= 0; regno --) { if (pushable_regs & (1 << regno)) { diff --git a/gcc/testsuite/gcc.target/arm/pr77933.c b/gcc/testsuite/gcc.target/arm/pr77933.c new file mode 100644 index 0000000000000000000000000000000000000000..cba7e9bb9aa57c6755f79b5ec2ea1a8744e23599 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/pr77933.c @@ -0,0 +1,9 @@ +/* { dg-do run } */ +/* { dg-options "-O1" } */ + +int +main (void) +{ + __asm__ volatile ("" : : : "r8", "r9", "lr"); + return 0; +}