From patchwork Mon Oct 28 20:29:00 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Martin Sebor X-Patchwork-Id: 1185689 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-511919-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="oeCMV+Vx"; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="Pgyk0OfC"; 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 4725sp4dGxz9sPK for ; Tue, 29 Oct 2019 07:29:16 +1100 (AEDT) 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=LCz1s0wZg/hZzHhD51CZcFiTRcnd6T0crG3ii22h6g7zfnBK1R OBEp0fEPVkJklWToWfAB7x3KgF1DxfZUcpsy4TdYrBZQu3Xym+14u6Ypm8ZTQoVc QSAgL1OVTY4ClErFUZsePtnjlrrXiIioqVO6CLRj3oa+EZgMptj/2gCrg= 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=WUkhfA8J1MWgwLB5HEStUfCrStw=; b=oeCMV+VxN9kppVFrO9VM vCf4mbGG5i5DGm+W19zG5L+559yj6cztGxEtdjqj1HEtfBPU/b1JHTJkWOWvLJ1s Kl0rg0trUTruSR5CgiGH3cXeDw9M67P2ZWOtrM9oj1otIIy96BSiFP49ts3isxG6 qWQwy9qLEIO6P8vYKtbSk7E= Received: (qmail 55905 invoked by alias); 28 Oct 2019 20:29:08 -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 55893 invoked by uid 89); 28 Oct 2019 20:29:07 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-10.9 required=5.0 tests=AWL, BAYES_00, FREEMAIL_FROM, GIT_PATCH_2, GIT_PATCH_3, KAM_ASCII_DIVIDERS, RCVD_IN_DNSWL_NONE, SPF_PASS autolearn=ham version=3.3.1 spammy=rng, sk:compare, nulovernul, nul-over-nul X-HELO: mail-yb1-f171.google.com Received: from mail-yb1-f171.google.com (HELO mail-yb1-f171.google.com) (209.85.219.171) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 28 Oct 2019 20:29:06 +0000 Received: by mail-yb1-f171.google.com with SMTP id r68so4552314ybf.5 for ; Mon, 28 Oct 2019 13:29:05 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=to:from:subject:message-id:date:user-agent:mime-version :content-language; bh=+o7VXbxze2OzLwPR7uDy99mlHXioDU636XVVS3+qk1M=; b=Pgyk0OfC+KI/jb6J/mj5g6huat9W+Q1VwoXRYdwVsXTcYxWdP75cS5cgiwTM9961qT E94q4JAGy9dRFd0X/CWSzLFjN+N/IzSS3Q7CMa9vkB684kzTYAf/SBZ/D7lUGy7bUZoH y6+AJ2i3lSBS5ATkoY0IlGhNZd5tGPNmXllcuSStc4PpOgbvVP7tdXnPy1jfgF8ut8q0 PkODv6wCmZyfRIOVQ1eA/GQqzZioPT0GsrBrZbE5SQfkZms+8rlrbehFXh8mODcGm2Q4 DnsHPiHY4KvoWn2ati0Nvd+L0YpWVEbEYZygrZ8/EQDF62nL2UQ5COjUwQsMntSwfu1i a7kA== Received: from [192.168.0.41] (174-16-107-204.hlrn.qwest.net. [174.16.107.204]) by smtp.gmail.com with ESMTPSA id j5sm3716682ywc.57.2019.10.28.13.29.02 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Mon, 28 Oct 2019 13:29:03 -0700 (PDT) To: Jeff Law , gcc-patches From: Martin Sebor Subject: [PATCH] avoid eliminating live nul stores into strings of bounded length (PR 92226) Message-ID: <85cc163f-a0b1-9ac0-32fd-89e73dd3e02b@gmail.com> Date: Mon, 28 Oct 2019 14:29:00 -0600 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.6.1 MIME-Version: 1.0 X-IsSubscribed: yes A recent enhancement to take advantage of non-constant strlen results constrained to a known range interacts badly with the nul-over-nul optimization. The optimization eliminates nul stores that overwrite the exiting terminating nul of the destination string. This interaction causes the nul store to be eliminated in subset of cases when it shouldn't be. The attached patch fixes the bug by avoiding the optimization for such destinations. It also adjusts the comment that describes the function with the bug to make its return value clearer. Tested on x86_64-linux. Martin PR tree-optimization/92226 - live nul char store to array eliminated gcc/testsuite/ChangeLog: PR tree-optimization/92226 * gcc.dg/strlenopt-88.c: New test. gcc/ChangeLog: PR tree-optimization/92226 * tree-ssa-strlen.c (compare_nonzero_chars): Return -1 also when the offset is in the open range outlined by SI's length. Index: gcc/tree-ssa-strlen.c =================================================================== --- gcc/tree-ssa-strlen.c (revision 277521) +++ gcc/tree-ssa-strlen.c (working copy) @@ -193,10 +193,11 @@ static void handle_builtin_stxncpy (built_in_funct * +1 if SI is known to start with more than OFF nonzero characters. - * 0 if SI is known to start with OFF nonzero characters, - but is not known to start with more. + * 0 if SI is known to start with exactly OFF nonzero characters. - * -1 if SI might not start with OFF nonzero characters. */ + * -1 if SI either does not start with OFF nonzero characters + or the relationship between the number of leading nonzero + characters in SI and OFF is unknown. */ static inline int compare_nonzero_chars (strinfo *si, unsigned HOST_WIDE_INT off) @@ -221,7 +221,7 @@ compare_nonzero_chars (strinfo *si, unsigned HOST_ if (TREE_CODE (si->nonzero_chars) == INTEGER_CST) return compare_tree_int (si->nonzero_chars, off); - if (TREE_CODE (si->nonzero_chars) != SSA_NAME) + if (!rvals || TREE_CODE (si->nonzero_chars) != SSA_NAME) return -1; const value_range *vr @@ -232,7 +232,15 @@ compare_nonzero_chars (strinfo *si, unsigned HOST_ if (rng != VR_RANGE || !range_int_cst_p (vr)) return -1; - return compare_tree_int (vr->min (), off); + /* If the offset is less than the minimum length or if the bounds + of the length range are equal return the result of the comparison + same as in the constant case. Otherwise return a conservative + result. */ + int cmpmin = compare_tree_int (vr->min (), off); + if (cmpmin > 0 || tree_int_cst_equal (vr->min (), vr->max ())) + return cmpmin; + + return -1; } /* Return true if SI is known to be a zero-length string. */ Index: gcc/testsuite/gcc.dg/strlenopt-88.c =================================================================== --- gcc/testsuite/gcc.dg/strlenopt-88.c (nonexistent) +++ gcc/testsuite/gcc.dg/strlenopt-88.c (working copy) @@ -0,0 +1,196 @@ +/* PR tree-optimization/92226 - live nul char store to array eliminated + { dg-do run } + { dg-options "-O2 -Wall" } */ + +#include "strlenopt.h" + +#define NOIPA __attribute__ ((noipa)) + +unsigned nfails; + +char a[8]; + +void test (int line, const char *func, size_t expect) +{ + size_t len = strlen (a); + if (len == expect) + return; + + ++nfails; + + __builtin_printf ("assertion failed in %s on line %i: " + "strlen (\"%s\") == %zu, got %zu\n", + func, line, a, expect, len); +} + +NOIPA const char* str (size_t n) +{ + return "9876543210" + 10 - n; +} + +#define T(name, CMPEXP, LEN, IDX, EXPECT) \ + NOIPA static void name (void) \ + { \ + const char *s = str (LEN); \ + if (strlen (s) CMPEXP) \ + { \ + strcpy (a, s); \ + a[IDX] = 0; \ + test (__LINE__, #name, EXPECT); \ + } \ + } typedef void dummy_type + + +T (len_eq_1_store_nul_0, == 1, 1, 0, 0); +T (len_eq_1_store_nul_1, == 1, 1, 1, 1); +T (len_eq_1_store_nul_2, == 1, 1, 2, 1); +T (len_eq_1_store_nul_3, == 1, 1, 3, 1); +T (len_eq_1_store_nul_4, == 1, 1, 4, 1); + +T (len_eq_2_store_nul_0, == 2, 2, 0, 0); +T (len_eq_2_store_nul_1, == 2, 2, 1, 1); +T (len_eq_2_store_nul_2, == 2, 2, 2, 2); +T (len_eq_2_store_nul_3, == 2, 2, 3, 2); +T (len_eq_2_store_nul_4, == 2, 2, 4, 2); + +T (len_eq_3_store_nul_0, == 3, 3, 0, 0); +T (len_eq_3_store_nul_1, == 3, 3, 1, 1); +T (len_eq_3_store_nul_2, == 3, 3, 2, 2); +T (len_eq_3_store_nul_3, == 3, 3, 3, 3); +T (len_eq_3_store_nul_4, == 3, 3, 4, 3); + + +T (len_gt_1_store_nul_0, > 2, 2, 0, 0); +T (len_gt_1_store_nul_1, > 2, 2, 1, 1); +T (len_gt_1_store_nul_2, > 2, 2, 2, 2); +T (len_gt_1_store_nul_3, > 2, 2, 3, 2); +T (len_gt_1_store_nul_4, > 2, 2, 4, 2); + +T (len_gt_2_store_nul_0, > 2, 3, 0, 0); +T (len_gt_2_store_nul_1, > 2, 3, 1, 1); +T (len_gt_2_store_nul_2, > 2, 3, 2, 2); +T (len_gt_2_store_nul_3, > 2, 3, 3, 3); +T (len_gt_2_store_nul_4, > 2, 3, 4, 3); + +T (len_gt_3_store_nul_0, > 2, 4, 0, 0); +T (len_gt_3_store_nul_1, > 2, 4, 1, 1); +T (len_gt_3_store_nul_2, > 2, 4, 2, 2); +T (len_gt_3_store_nul_3, > 2, 4, 3, 3); +T (len_gt_3_store_nul_4, > 2, 4, 4, 4); + + +T (len_1_lt_4_store_nul_0, < 4, 1, 0, 0); +T (len_1_lt_4_store_nul_1, < 4, 1, 1, 1); +T (len_1_lt_4_store_nul_2, < 4, 1, 2, 1); +T (len_1_lt_4_store_nul_3, < 4, 1, 3, 1); +T (len_1_lt_4_store_nul_4, < 4, 1, 4, 1); +T (len_1_lt_4_store_nul_5, < 4, 1, 5, 1); +T (len_1_lt_4_store_nul_6, < 4, 1, 6, 1); +T (len_1_lt_4_store_nul_7, < 4, 1, 7, 1); + +T (len_2_lt_4_store_nul_0, < 4, 2, 0, 0); +T (len_2_lt_4_store_nul_1, < 4, 2, 1, 1); +T (len_2_lt_4_store_nul_2, < 4, 2, 2, 2); +T (len_2_lt_4_store_nul_3, < 4, 2, 3, 2); +T (len_2_lt_4_store_nul_4, < 4, 2, 4, 2); +T (len_2_lt_4_store_nul_5, < 4, 2, 5, 2); +T (len_2_lt_4_store_nul_6, < 4, 2, 6, 2); +T (len_2_lt_4_store_nul_7, < 4, 2, 7, 2); + +T (len_3_lt_4_store_nul_0, < 4, 3, 0, 0); +T (len_3_lt_4_store_nul_1, < 4, 3, 1, 1); +T (len_3_lt_4_store_nul_2, < 4, 3, 2, 2); +T (len_3_lt_4_store_nul_3, < 4, 3, 3, 3); +T (len_3_lt_4_store_nul_4, < 4, 3, 4, 3); +T (len_3_lt_4_store_nul_5, < 4, 3, 5, 3); +T (len_3_lt_4_store_nul_6, < 4, 3, 6, 3); +T (len_3_lt_4_store_nul_7, < 4, 3, 7, 3); + +T (len_7_lt_8_store_nul_0, < 8, 7, 0, 0); +T (len_7_lt_8_store_nul_1, < 8, 7, 1, 1); +T (len_7_lt_8_store_nul_2, < 8, 7, 2, 2); +T (len_7_lt_8_store_nul_3, < 8, 7, 3, 3); +T (len_7_lt_8_store_nul_4, < 8, 7, 4, 4); +T (len_7_lt_8_store_nul_5, < 8, 7, 5, 5); +T (len_7_lt_8_store_nul_6, < 8, 7, 6, 6); +T (len_7_lt_8_store_nul_7, < 8, 7, 7, 7); + + +int main (void) +{ + len_eq_1_store_nul_0 (); + len_eq_1_store_nul_1 (); + len_eq_1_store_nul_2 (); + len_eq_1_store_nul_3 (); + len_eq_1_store_nul_4 (); + + len_eq_2_store_nul_0 (); + len_eq_2_store_nul_1 (); + len_eq_2_store_nul_2 (); + len_eq_2_store_nul_3 (); + len_eq_2_store_nul_4 (); + + len_eq_3_store_nul_0 (); + len_eq_3_store_nul_1 (); + len_eq_3_store_nul_2 (); + len_eq_3_store_nul_3 (); + len_eq_3_store_nul_4 (); + + + len_gt_1_store_nul_0 (); + len_gt_1_store_nul_1 (); + len_gt_1_store_nul_2 (); + len_gt_1_store_nul_3 (); + len_gt_1_store_nul_4 (); + + len_gt_2_store_nul_0 (); + len_gt_2_store_nul_1 (); + len_gt_2_store_nul_2 (); + len_gt_2_store_nul_3 (); + len_gt_2_store_nul_4 (); + + len_gt_3_store_nul_0 (); + len_gt_3_store_nul_1 (); + len_gt_3_store_nul_2 (); + len_gt_3_store_nul_3 (); + len_gt_3_store_nul_4 (); + + len_1_lt_4_store_nul_0 (); + len_1_lt_4_store_nul_1 (); + len_1_lt_4_store_nul_2 (); + len_1_lt_4_store_nul_3 (); + len_1_lt_4_store_nul_4 (); + len_1_lt_4_store_nul_5 (); + len_1_lt_4_store_nul_6 (); + len_1_lt_4_store_nul_7 (); + + len_2_lt_4_store_nul_0 (); + len_2_lt_4_store_nul_1 (); + len_2_lt_4_store_nul_2 (); + len_2_lt_4_store_nul_3 (); + len_2_lt_4_store_nul_4 (); + len_2_lt_4_store_nul_5 (); + len_2_lt_4_store_nul_6 (); + len_2_lt_4_store_nul_7 (); + + len_3_lt_4_store_nul_0 (); + len_3_lt_4_store_nul_1 (); + len_3_lt_4_store_nul_2 (); + len_3_lt_4_store_nul_3 (); + len_3_lt_4_store_nul_4 (); + len_3_lt_4_store_nul_5 (); + len_3_lt_4_store_nul_6 (); + len_3_lt_4_store_nul_7 (); + + len_7_lt_8_store_nul_0 (); + len_7_lt_8_store_nul_1 (); + len_7_lt_8_store_nul_2 (); + len_7_lt_8_store_nul_3 (); + len_7_lt_8_store_nul_4 (); + len_7_lt_8_store_nul_5 (); + len_7_lt_8_store_nul_6 (); + len_7_lt_8_store_nul_7 (); + + if (nfails) + abort (); +}