From patchwork Mon Aug 19 01:11:38 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeff Law X-Patchwork-Id: 1148966 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-507202-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="EDlEPYxt"; 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 46BbVf4Dgwz9s3Z for ; Mon, 19 Aug 2019 11:11:52 +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:subject:message-id:date:mime-version:content-type; q=dns; s= default; b=Z+nPi6+BFS01brvR5s5Obiq/uJH3cfEHJyGpA7T4XPTYbOEuLrDso lf/5rG788814w1NU6KEpog56PvEpdO8a6Mh9edzF5CjJ+Mo21D+vYW3ERQPXU7rl bG8PHWcRgv0HbKFwomPrNbKz4gc7eR7JMFmywbvXvi9CB0ROD+V45U= 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:subject:message-id:date:mime-version:content-type; s= default; bh=eG5tOT7qkTw6yvH1dkR6tXHsaFg=; b=EDlEPYxtaLZ0DP2DDJ5y sSQevIuq0tSvw01cpsU3AXC0qjkgi72PEoph3vZ302GpqUInfPvydfyramqHyp+B KZ4zqnUDdxIopaY5lohZ4hOJlJjTnmXnXx1cSR2inkpHKSdxO3B2sx6buFGvrLkD xQhEKQsDT5PlcZZWYp9KCDw= Received: (qmail 95711 invoked by alias); 19 Aug 2019 01:11:43 -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 95702 invoked by uid 89); 19 Aug 2019 01:11:43 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-14.5 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, SPF_HELO_PASS autolearn=ham version=3.3.1 spammy=partially, *stmt, conservative, gsi X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 19 Aug 2019 01:11:41 +0000 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 95E8AA391E5 for ; Mon, 19 Aug 2019 01:11:40 +0000 (UTC) Received: from localhost.localdomain (ovpn-112-5.rdu2.redhat.com [10.10.112.5]) by smtp.corp.redhat.com (Postfix) with ESMTP id EC439B32DA for ; Mon, 19 Aug 2019 01:11:39 +0000 (UTC) From: Jeff Law Openpgp: preference=signencrypt To: gcc-patches Subject: [RFA] [PR tree-optimization/80576] Handle strcpy and strcpy_chk in DSE Message-ID: Date: Sun, 18 Aug 2019 19:11:38 -0600 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.4.0 MIME-Version: 1.0 X-IsSubscribed: yes So this builds on the previous DSE patch to add handling of strcpy and resolves the remainder of 80576. Recall there's two cases to consider. If the strcpy is the first store (ie, potentially dead), then the conservative choice when setting up the ao_ref is to take the smaller of the destination object's size and the maximum length of the source string. For the second store (ie, the killing store) we want the minimum of the length of the source string when setting up the ao_ref. We do not handle trimming in the case of a partially dead call to strcpy. We only handle cases where it's fully dead. Bootstrapped and regression tested on x86_64, i686, aarch64, ppc64, ppc64le, s390x & sparc64. Also built and tested the various *-elf targets with no regressions. I also verified the new test passes on all those targets. Several other targets have been bootstrapped (alpha, m68k, various arm* things, mipsisa32r2, riscv64 and others). OK for the trunk? Jeff PR tree-optimization/80576 * tree-ssa-dse.c (initialize_ao_ref_for_dse): Handle strcpy and strcpy_chk. (dse_dom_walker::dse_optimize_stmt): Similarly. * gcc.dg/tree-ssa/ssa-dse-41.c: New test. commit 24f60672cacb4da2ae898ec7e90bd55f52073954 Author: Jeff Law Date: Fri Aug 9 18:13:50 2019 -0400 MOre DSE improvements Add test diff --git a/gcc/tree-ssa-dse.c b/gcc/tree-ssa-dse.c index ae03980f792..47907617aaf 100644 --- a/gcc/tree-ssa-dse.c +++ b/gcc/tree-ssa-dse.c @@ -181,6 +181,56 @@ initialize_ao_ref_for_dse (gimple *stmt, ao_ref *write, bool maxlen) return true; } + case BUILT_IN_STRCPY: + case BUILT_IN_STRCPY_CHK: + { + tree dest = gimple_call_arg (stmt, 0); + tree src = gimple_call_arg (stmt, 1); + tree size = NULL_TREE; + + /* Get the range of the length of the source string. */ + c_strlen_data src_data = { }; + if (get_range_strlen (src, &src_data, 1)) + { + size = maxlen ? src_data.maxlen : src_data.minlen; + + /* Adjust the source length to account for NUL terminator. */ + size = fold_build2 (PLUS_EXPR, TREE_TYPE (size), size, integer_one_node); + } + + /* If we are asking for the minimum size and did not get a usable + size from get_range_strlen, then the minimum size would be zero + and there's nothing we can do. If we were asking for the + maximum size, then we can try and get a size from the destination + object. */ + if (!maxlen && !size) + return false; + + /* If we did not get a size from the source operand, then try to + get it from the size of the destination object's type. + + If we got a size from the source operand, then choose the + minimum of the size from the operand and the size we got + from the input operand. In theory the latter would be + sufficient, but the size from the input operand is a range + and could, in theory, be larger than the output buffer + due to imprecision in the computation of the size. */ + tree dest_size = objsize_from_type (dest); + if (!size) + size = dest_size; + else if (dest_size) + size = fold_build2 (MIN_EXPR, TREE_TYPE (dest_size), + dest_size, size); + + /* If we still don't have size information, then assume we can + not analyze this case. */ + if (!size) + return false; + + ao_ref_init_from_ptr_and_size (write, dest, size); + return true; + } + /* A calloc call can never be dead, but it can make subsequent stores redundant if they store 0 into the same memory locations. */ @@ -1078,6 +1128,26 @@ dse_dom_walker::dse_optimize_stmt (gimple_stmt_iterator *gsi) return; } + case BUILT_IN_STRCPY: + case BUILT_IN_STRCPY_CHK: + { + enum dse_store_status store_status; + m_byte_tracking_enabled + = setup_live_bytes_from_ref (&ref, m_live_bytes); + store_status = dse_classify_store (&ref, stmt, + m_byte_tracking_enabled, + m_live_bytes); + if (store_status == DSE_STORE_LIVE) + return; + + /* We don't handle trimming these calls, though we might + be able to trim a strcpy into a strncpy for example. */ + + if (store_status == DSE_STORE_DEAD) + delete_dead_or_redundant_call (gsi, "dead"); + break; + } + case BUILT_IN_CALLOC: /* We already know the arguments are integer constants. */ dse_optimize_redundant_stores (stmt); diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-41.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-41.c new file mode 100644 index 00000000000..0f64c265c29 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-41.c @@ -0,0 +1,40 @@ +/* { dg-options "-O2 -fdump-tree-dse-details -fno-tree-vrp -fno-tree-forwprop" } */ +extern void frob (char *); +void g (int x) +{ + char a[8]; + __builtin_strcpy (a, x ? "12345" : "56789"); + __builtin_memset (a, 0, sizeof a); + frob (a); +} + +void h (int x) +{ + char a[8]; + __builtin_memset (a, 0, sizeof a); + __builtin_strcpy (a, x ? "12345" : "56789"); + frob (a); +} + + +void i (int x) +{ + char a[8]; + __builtin_strcpy (a, x ? "12345" : "56"); + __builtin_memset (a, 0, sizeof a); + frob (a); +} + +void j (int x) +{ + char a[8]; + __builtin_memset (a, 0, sizeof a); + __builtin_strcpy (a, x ? "12345" : "56"); + frob (a); +} + +/* We can delete the dead strcpy call in the first and third tests. */ + +/* { dg-final { scan-tree-dump-times "Deleted dead call" 2 "dse1" } } */ +/* { dg-final { scan-tree-dump-times "Trimming statement " 2 "dse1" } } */ +