From patchwork Thu Jul 27 21:36:03 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Sandiford X-Patchwork-Id: 794573 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-459211-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="pDvbKK7W"; 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 3xJQK24fPMz9s3T for ; Fri, 28 Jul 2017 07:36:20 +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:date:message-id:mime-version:content-type; q=dns; s= default; b=YSneb0LN5J3iKSXAK2ZKobaZic1jNHzdRrQID1FR9B0iNqHawLbnl dInyLhNA0d3oZo/NosFZ5+0oRKoqJJJtR/Q34QLyzH0rWVYTXykxO2PUcRSbxs0L NLxA4GQbG4zkYZQRmejw7WLZWQs6htakPoRUvS64q87ARqalcOrfZ4= 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:date:message-id:mime-version:content-type; s= default; bh=PiaY8OrMKHPfE+gvpXxoxCNcVGQ=; b=pDvbKK7WUVNni1ZuEHti vT3wSi30KW/DNr6FdqXAP8kazMJa7iS5q/wwVUuXLXkgaFMcd9M1pOXxNMCbOpY5 No67n8eD6deBR/5PfM+nk6jKBYDQESERD/2xWkNv0wCabGBxuHFjWF5BRnEGYIe1 x2n8vWDVd3gnXXJFkbsZOxk= Received: (qmail 120133 invoked by alias); 27 Jul 2017 21:36:10 -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 119197 invoked by uid 89); 27 Jul 2017 21:36:09 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-10.9 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_2, GIT_PATCH_3, KAM_ASCII_DIVIDERS, RCVD_IN_DNSWL_NONE, SPF_PASS autolearn=ham version=3.3.2 spammy=nsi, rfa X-HELO: mail-wr0-f172.google.com Received: from mail-wr0-f172.google.com (HELO mail-wr0-f172.google.com) (209.85.128.172) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Thu, 27 Jul 2017 21:36:07 +0000 Received: by mail-wr0-f172.google.com with SMTP id y43so148362699wrd.3 for ; Thu, 27 Jul 2017 14:36:07 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:mail-followup-to:subject:date:message-id :user-agent:mime-version; bh=hip3mw1sstacw24+Q8XgKW+Sm2xe+R5Rtc+OvUGZZ5I=; b=NduQB2yleXd3mRWTkXET/ronBi10dqh7bfgWMz+uoFtLmYGvzPSj7NXkHyPTYJQRIb 8h+dnqiQKdBj+w4EfJlIjv0wpqTTcA2lVqfG7H05UgjxU+sG7v7uoq/1QAg/4ozhWaJ1 fuzqRPtPVTZrffAEeJABdwr3VlhRskFqURhyaBuViNMaVmyfHsucwv6mqm0WgODquDLm 3U+yuJBkxzbtNbZqO5NKdU9+fzbqgA5We+26HhfhwfKuFIcRwT1pxtOAadSnyc5jD1bL kxzGnmKN66E69Acoy0WMIi/xDrXHov82xqdL9ZuBCqm1DUbbQ5pwaYxI+3kPDxz4nEQW x1ug== X-Gm-Message-State: AIVw113jWKiS13n2bRdALpYhmAFiERgXx4+R7+HX1sROQIYEHjN2oM9A 3+rM7jPWw2Kw7MWELtdKhA== X-Received: by 10.223.171.200 with SMTP id s66mr5025615wrc.38.1501191365309; Thu, 27 Jul 2017 14:36:05 -0700 (PDT) Received: from localhost ([2.26.27.176]) by smtp.gmail.com with ESMTPSA id z190sm17906358wmz.31.2017.07.27.14.36.03 for (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Thu, 27 Jul 2017 14:36:04 -0700 (PDT) From: Richard Sandiford To: gcc-patches@gcc.gnu.org Mail-Followup-To: gcc-patches@gcc.gnu.org, richard.sandiford@linaro.org Subject: RFA: Backport fix for PR80769 Date: Thu, 27 Jul 2017 22:36:03 +0100 Message-ID: <87y3r9tvek.fsf@linaro.org> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/25.2 (gnu/linux) MIME-Version: 1.0 This is a minimal-ish backport of the fix for PR80769. The trunk version also replaced open-coded instances of get_next_strinfo with calls to the new function. It also added asserts in various other places to try to ensure that related strinfos were consistently delayed or not delayed. Tested on aarch64-linux-gnu and x86_64-linux-gnu. OK for gcc-7-branch? (And OK for gcc-6-branch if the same patch passes testing there?) Richard 2017-07-27 Richard Sandiford gcc/ PR tree-optimization/80769 * tree-ssa-strlen.c (strinfo): Document that "stmt" is also used for malloc and calloc. Document the new invariant that all related strinfos have delayed lengths or none do. (get_next_strinfo): New function. (verify_related_strinfos): Move earlier in file. (set_endptr_and_length): New function, split out from... (get_string_length): ...here. Also set the lengths of related strinfos. gcc/testsuite/ PR tree-optimization/80769 * gcc.dg/strlenopt-31.c: New test. * gcc.dg/strlenopt-31g.c: Likewise. Index: gcc/tree-ssa-strlen.c =================================================================== --- gcc/tree-ssa-strlen.c 2017-05-10 18:04:24.514775477 +0100 +++ gcc/tree-ssa-strlen.c 2017-07-27 18:21:20.308966958 +0100 @@ -61,7 +61,13 @@ struct strinfo tree length; /* Any of the corresponding pointers for querying alias oracle. */ tree ptr; - /* Statement for delayed length computation. */ + /* This is used for two things: + + - To record the statement that should be used for delayed length + computations. We maintain the invariant that all related strinfos + have delayed lengths or none do. + + - To record the malloc or calloc call that produced this result. */ gimple *stmt; /* Pointer to '\0' if known, if NULL, it can be computed as ptr + length. */ @@ -156,6 +162,19 @@ get_strinfo (int idx) return (*stridx_to_strinfo)[idx]; } +/* Get the next strinfo in the chain after SI, or null if none. */ + +static inline strinfo * +get_next_strinfo (strinfo *si) +{ + if (si->next == 0) + return NULL; + strinfo *nextsi = get_strinfo (si->next); + if (nextsi == NULL || nextsi->first != si->first || nextsi->prev != si->idx) + return NULL; + return nextsi; +} + /* Helper function for get_stridx. */ static int @@ -438,6 +457,45 @@ set_strinfo (int idx, strinfo *si) (*stridx_to_strinfo)[idx] = si; } +/* Return the first strinfo in the related strinfo chain + if all strinfos in between belong to the chain, otherwise NULL. */ + +static strinfo * +verify_related_strinfos (strinfo *origsi) +{ + strinfo *si = origsi, *psi; + + if (origsi->first == 0) + return NULL; + for (; si->prev; si = psi) + { + if (si->first != origsi->first) + return NULL; + psi = get_strinfo (si->prev); + if (psi == NULL) + return NULL; + if (psi->next != si->idx) + return NULL; + } + if (si->idx != si->first) + return NULL; + return si; +} + +/* Set SI's endptr to ENDPTR and compute its length based on SI->ptr. + Use LOC for folding. */ + +static void +set_endptr_and_length (location_t loc, strinfo *si, tree endptr) +{ + si->endptr = endptr; + si->stmt = NULL; + tree start_as_size = fold_convert_loc (loc, size_type_node, si->ptr); + tree end_as_size = fold_convert_loc (loc, size_type_node, endptr); + si->length = fold_build2_loc (loc, MINUS_EXPR, size_type_node, + end_as_size, start_as_size); +} + /* Return string length, or NULL if it can't be computed. */ static tree @@ -533,12 +591,12 @@ get_string_length (strinfo *si) case BUILT_IN_STPCPY_CHK_CHKP: gcc_assert (lhs != NULL_TREE); loc = gimple_location (stmt); - si->endptr = lhs; - si->stmt = NULL; - lhs = fold_convert_loc (loc, size_type_node, lhs); - si->length = fold_convert_loc (loc, size_type_node, si->ptr); - si->length = fold_build2_loc (loc, MINUS_EXPR, size_type_node, - lhs, si->length); + set_endptr_and_length (loc, si, lhs); + for (strinfo *chainsi = verify_related_strinfos (si); + chainsi != NULL; + chainsi = get_next_strinfo (chainsi)) + if (chainsi->length == NULL) + set_endptr_and_length (loc, chainsi, lhs); break; case BUILT_IN_MALLOC: break; @@ -607,32 +665,6 @@ unshare_strinfo (strinfo *si) return nsi; } -/* Return first strinfo in the related strinfo chain - if all strinfos in between belong to the chain, otherwise - NULL. */ - -static strinfo * -verify_related_strinfos (strinfo *origsi) -{ - strinfo *si = origsi, *psi; - - if (origsi->first == 0) - return NULL; - for (; si->prev; si = psi) - { - if (si->first != origsi->first) - return NULL; - psi = get_strinfo (si->prev); - if (psi == NULL) - return NULL; - if (psi->next != si->idx) - return NULL; - } - if (si->idx != si->first) - return NULL; - return si; -} - /* Attempt to create a new strinfo for BASESI + OFF, or find existing strinfo if there is any. Return it's idx, or 0 if no strinfo has been created. */ Index: gcc/testsuite/gcc.dg/strlenopt-31.c =================================================================== --- /dev/null 2017-07-27 17:06:14.642985039 +0100 +++ gcc/testsuite/gcc.dg/strlenopt-31.c 2017-07-27 18:11:20.158804210 +0100 @@ -0,0 +1,25 @@ +/* { dg-do run } */ +/* { dg-options "-O2" } */ + +#include "strlenopt.h" + +__attribute__((noinline, noclone)) int +bar (char *p1, const char *q) +{ + strcpy (p1, "abcde"); + char *p2 = strchr (p1, '\0'); + strcpy (p2, q); + char *p3 = strchr (p2, '\0'); + memcpy (p3, "x", 2); + return strlen (p1); +} + +int +main (void) +{ + char buffer[10]; + int res = bar (buffer, "foo"); + if (strcmp (buffer, "abcdefoox") != 0 || res != 9) + abort (); + return 0; +} Index: gcc/testsuite/gcc.dg/strlenopt-31g.c =================================================================== --- /dev/null 2017-07-27 17:06:14.642985039 +0100 +++ gcc/testsuite/gcc.dg/strlenopt-31g.c 2017-07-27 18:11:20.158804210 +0100 @@ -0,0 +1,9 @@ +/* { dg-do run { target *-*-linux* *-*-gnu* } } */ +/* { dg-options "-O2 -fdump-tree-strlen" } */ + +#define USE_GNU +#include "strlenopt-31.c" + +/* { dg-final { scan-tree-dump-times "stpcpy \\(" 1 "strlen" } } */ +/* { dg-final { scan-tree-dump-times "memcpy \\(" 2 "strlen" } } */ +/* { dg-final { scan-tree-dump-not "strlen \\(" "strlen" } } */