From patchwork Fri Jan 12 20:51:44 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakub Jelinek X-Patchwork-Id: 860193 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-471052-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="lEWlc5r5"; 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 3zJFKx4rn1z9sP1 for ; Sat, 13 Jan 2018 07:52:04 +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:date :from:to:cc:subject:message-id:reply-to:mime-version :content-type; q=dns; s=default; b=oPInv8k7ViSRdLCByYuCrZKijrIOy BSLUudhYxdm2CE/BIGbzalgFns1661r/iFM8DRjVUQUKaOiejomD2G0Am99b3wXP Zw2cI0jdVwGjYSpZLbR6O7cEGrrLpiEhzwa+tNL+Cwp6VSEdaspCV2ARUI9PaQ8h dULz7v/utszc2E= 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:date :from:to:cc:subject:message-id:reply-to:mime-version :content-type; s=default; bh=BVCxVHYT8QPQxwbg34K4hH7qU7A=; b=lEW lc5r52PnqkLwbIWyzYK/fl0d3ffOXa3rbJQjhooHvlLBDwXTZw4PHjMGsSy8aYkv m7ZiTLfTzQTH1QgL1MFgrRxu3hMsnD3x0L0oOZaQKL/oWrYwU59wMx1vFUxpVH5W 7hADLMnpwdPfZezQ8zUWhOlIO0S8HbTE4dt3Oz64= Received: (qmail 34931 invoked by alias); 12 Jan 2018 20:51: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 34858 invoked by uid 89); 12 Jan 2018 20:51:53 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-16.9 required=5.0 tests=BAYES_00, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, SPF_HELO_PASS, T_RP_MATCHES_RCVD autolearn=ham version=3.3.2 spammy= 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; Fri, 12 Jan 2018 20:51:50 +0000 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id C2C18C0860C1; Fri, 12 Jan 2018 20:51:49 +0000 (UTC) Received: from tucnak.zalov.cz (ovpn-117-22.ams2.redhat.com [10.36.117.22]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 5E61317976; Fri, 12 Jan 2018 20:51:49 +0000 (UTC) Received: from tucnak.zalov.cz (localhost [127.0.0.1]) by tucnak.zalov.cz (8.15.2/8.15.2) with ESMTP id w0CKpkuc012312; Fri, 12 Jan 2018 21:51:46 +0100 Received: (from jakub@localhost) by tucnak.zalov.cz (8.15.2/8.15.2/Submit) id w0CKpiIm012311; Fri, 12 Jan 2018 21:51:44 +0100 Date: Fri, 12 Jan 2018 21:51:44 +0100 From: Jakub Jelinek To: Richard Biener Cc: gcc-patches@gcc.gnu.org Subject: [PATCH] Introduce -fwrapp and make -fno-strict-overflow imply it (PR middle-end/82694) Message-ID: <20180112205144.GK2063@tucnak> Reply-To: Jakub Jelinek MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.9.1 (2017-09-22) X-IsSubscribed: yes Hi! Apparently Linux kernel contains various UB code that has been worked around through -fno-strict-overflow in 7.x and before, but when POINTER_TYPE_OVERFLOW_UNDEFINED has been removed it now fails to boot. The following patch follows the comments in the PR, essentially reverts Bin's removal of that, except that it is now controlled by a separate option and is included in TYPE_OVERFLOW_{WRAPS,UNDEFINED} macros. Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? 2018-01-12 Jakub Jelinek PR middle-end/82694 * common.opt (fstrict-overflow): No longer an alias. (fwrapp): New option. * tree.h (TYPE_OVERFLOW_WRAPS, TYPE_OVERFLOW_UNDEFINED): Define also for pointer types based on flag_wrapp. * opts.c (common_handle_option) : Set opts->x_flag_wrap[pv] to !value, clear opts->x_flag_trapv if opts->x_flag_wrapv got set. * fold-const.c (fold_comparison, fold_binary_loc): Revert 2017-08-01 changes, just use TYPE_OVERFLOW_UNDEFINED on pointer type instead of POINTER_TYPE_OVERFLOW_UNDEFINED. * match.pd: Likewise in address comparison pattern. * doc/invoke.texi: Document -fwrapv and -fstrict-overflow. * gcc.dg/no-strict-overflow-7.c: Revert 2017-08-01 changes. * gcc.dg/tree-ssa/pr81388-1.c: Likewise. Jakub --- gcc/common.opt.jj 2018-01-03 10:19:54.936533922 +0100 +++ gcc/common.opt 2018-01-12 14:53:28.254485349 +0100 @@ -2411,8 +2411,8 @@ Common Report Var(flag_strict_aliasing) Assume strict aliasing rules apply. fstrict-overflow -Common NegativeAlias Alias(fwrapv) -Treat signed overflow as undefined. Negated as -fwrapv. +Common Report +Treat signed overflow as undefined. Negated as -fwrapv -fwrapp. fsync-libcalls Common Report Var(flag_sync_libcalls) Init(1) @@ -2860,6 +2860,10 @@ fwhole-program Common Report Var(flag_whole_program) Init(0) Perform whole program optimizations. +fwrapp +Common Report Var(flag_wrapp) Optimization +Assume pointer overflow wraps around. + fwrapv Common Report Var(flag_wrapv) Optimization Assume signed arithmetic overflow wraps around. --- gcc/tree.h.jj 2018-01-11 18:58:50.993392760 +0100 +++ gcc/tree.h 2018-01-12 15:04:14.480526788 +0100 @@ -829,13 +829,16 @@ extern void omp_clause_range_check_faile /* Same as TYPE_UNSIGNED but converted to SIGNOP. */ #define TYPE_SIGN(NODE) ((signop) TYPE_UNSIGNED (NODE)) -/* True if overflow wraps around for the given integral type. That +/* True if overflow wraps around for the given integral or pointer type. That is, TYPE_MAX + 1 == TYPE_MIN. */ #define TYPE_OVERFLOW_WRAPS(TYPE) \ - (ANY_INTEGRAL_TYPE_CHECK(TYPE)->base.u.bits.unsigned_flag || flag_wrapv) + (POINTER_TYPE_P (TYPE) \ + ? flag_wrapp \ + : (ANY_INTEGRAL_TYPE_CHECK(TYPE)->base.u.bits.unsigned_flag \ + || flag_wrapv)) -/* True if overflow is undefined for the given integral type. We may - optimize on the assumption that values in the type never overflow. +/* True if overflow is undefined for the given integral or pointer type. + We may optimize on the assumption that values in the type never overflow. IMPORTANT NOTE: Any optimization based on TYPE_OVERFLOW_UNDEFINED must issue a warning based on warn_strict_overflow. In some cases @@ -843,8 +846,10 @@ extern void omp_clause_range_check_faile other cases it will be appropriate to simply set a flag and let the caller decide whether a warning is appropriate or not. */ #define TYPE_OVERFLOW_UNDEFINED(TYPE) \ - (!ANY_INTEGRAL_TYPE_CHECK(TYPE)->base.u.bits.unsigned_flag \ - && !flag_wrapv && !flag_trapv) + (POINTER_TYPE_P (TYPE) \ + ? !flag_wrapp \ + : (!ANY_INTEGRAL_TYPE_CHECK(TYPE)->base.u.bits.unsigned_flag \ + && !flag_wrapv && !flag_trapv)) /* True if overflow for the given integral type should issue a trap. */ --- gcc/opts.c.jj 2018-01-03 10:19:56.142534113 +0100 +++ gcc/opts.c 2018-01-12 14:55:06.670494955 +0100 @@ -2465,6 +2465,13 @@ common_handle_option (struct gcc_options opts->x_flag_wrapv = 0; break; + case OPT_fstrict_overflow: + opts->x_flag_wrapv = !value; + opts->x_flag_wrapp = !value; + if (!value) + opts->x_flag_trapv = 0; + break; + case OPT_fipa_icf: opts->x_flag_ipa_icf_functions = value; opts->x_flag_ipa_icf_variables = value; --- gcc/fold-const.c.jj 2018-01-04 22:08:04.394684734 +0100 +++ gcc/fold-const.c 2018-01-12 15:06:20.040532446 +0100 @@ -8551,9 +8551,13 @@ fold_comparison (location_t loc, enum tr { /* We can fold this expression to a constant if the non-constant offset parts are equal. */ - if (offset0 == offset1 - || (offset0 && offset1 - && operand_equal_p (offset0, offset1, 0))) + if ((offset0 == offset1 + || (offset0 && offset1 + && operand_equal_p (offset0, offset1, 0))) + && (equality_code + || (indirect_base0 + && (DECL_P (base0) || CONSTANT_CLASS_P (base0))) + || TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (arg0)))) { if (!equality_code && maybe_ne (bitpos0, bitpos1) @@ -8612,7 +8616,11 @@ fold_comparison (location_t loc, enum tr because pointer arithmetic is restricted to retain within an object and overflow on pointer differences is undefined as of 6.5.6/8 and /9 with respect to the signed ptrdiff_t. */ - else if (known_eq (bitpos0, bitpos1)) + else if (known_eq (bitpos0, bitpos1) + && (equality_code + || (indirect_base0 + && (DECL_P (base0) || CONSTANT_CLASS_P (base0))) + || TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (arg0)))) { /* By converting to signed sizetype we cover middle-end pointer arithmetic which operates on unsigned pointer types of size @@ -9721,8 +9729,8 @@ fold_binary_loc (location_t loc, enum tr /* With undefined overflow prefer doing association in a type which wraps on overflow, if that is one of the operand types. */ - if (POINTER_TYPE_P (type) - || (INTEGRAL_TYPE_P (type) && !TYPE_OVERFLOW_WRAPS (type))) + if ((POINTER_TYPE_P (type) || INTEGRAL_TYPE_P (type)) + && !TYPE_OVERFLOW_WRAPS (type)) { if (INTEGRAL_TYPE_P (TREE_TYPE (arg0)) && TYPE_OVERFLOW_WRAPS (TREE_TYPE (arg0))) @@ -9735,8 +9743,8 @@ fold_binary_loc (location_t loc, enum tr /* With undefined overflow we can only associate constants with one variable, and constants whose association doesn't overflow. */ - if (POINTER_TYPE_P (atype) - || (INTEGRAL_TYPE_P (atype) && !TYPE_OVERFLOW_WRAPS (atype))) + if ((POINTER_TYPE_P (atype) || INTEGRAL_TYPE_P (atype)) + && !TYPE_OVERFLOW_WRAPS (atype)) { if ((var0 && var1) || (minus_var0 && minus_var1)) { --- gcc/match.pd.jj 2018-01-09 21:53:38.366577609 +0100 +++ gcc/match.pd 2018-01-12 16:17:01.677944553 +0100 @@ -3610,7 +3610,14 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) || TREE_CODE (base1) == STRING_CST)) equal = (base0 == base1); } - (if (equal == 1) + (if (equal == 1 + && (cmp == EQ_EXPR || cmp == NE_EXPR + /* If the offsets are equal we can ignore overflow. */ + || known_eq (off0, off1) + || TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@0)) + /* Or if we compare using pointers to decls or strings. */ + || (POINTER_TYPE_P (TREE_TYPE (@2)) + && (DECL_P (base0) || TREE_CODE (base0) == STRING_CST)))) (switch (if (cmp == EQ_EXPR && (known_eq (off0, off1) || known_ne (off0, off1))) { constant_boolean_node (known_eq (off0, off1), type); }) --- gcc/doc/invoke.texi.jj 2018-01-12 11:36:20.115225557 +0100 +++ gcc/doc/invoke.texi 2018-01-12 16:14:11.369911474 +0100 @@ -12576,6 +12576,18 @@ The options @option{-ftrapv} and @option using @option{-ftrapv} @option{-fwrapv} @option{-fno-wrapv} on the command-line results in @option{-ftrapv} being effective. +@item -fwrapp +@opindex fwrapp +This option instructs the compiler to assume that pointer arithmetic +overflow on addition and subtraction wraps around using twos-complement +representation. This flag disables some optimizations which assume +pointer overflow is invalid. + +@item -fstrict-overflow +@opindex fstrict-overflow +This option implies @option{-fno-wrapv} @option{-fno-wrapp} and when negated +implies @option{-fwrapv} @option{-fwrapp}. + @item -fexceptions @opindex fexceptions Enable exception handling. Generates extra code needed to propagate --- gcc/testsuite/gcc.dg/tree-ssa/pr81388-1.c.jj 2017-08-01 12:14:27.740533590 +0200 +++ gcc/testsuite/gcc.dg/tree-ssa/pr81388-1.c 2018-01-12 16:22:34.427009184 +0100 @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -fno-strict-overflow -fdump-tree-tailc-details" } */ +/* { dg-options "-O2 -fno-strict-overflow -fdump-tree-ivcanon-details" } */ void bar(); void foo(char *dst) @@ -11,6 +11,4 @@ void foo(char *dst) } while (dst < end); } -/* The loop only iterates once because pointer overflow always has undefined - semantics. As a result, call to bar becomes tail call. */ -/* { dg-final { scan-tree-dump-times "Found tail call " 1 "tailc" } } */ +/* { dg-final { scan-tree-dump " zero if " "ivcanon" } } */ --- gcc/testsuite/gcc.dg/no-strict-overflow-7.c.jj 2017-08-01 12:14:27.941531251 +0200 +++ gcc/testsuite/gcc.dg/no-strict-overflow-7.c 2018-01-12 16:19:55.224978262 +0100 @@ -3,8 +3,8 @@ /* Source: Ian Lance Taylor. Dual of strict-overflow-6.c. */ -/* We can simplify the conditional because pointer overflow always has - undefined semantics. */ +/* We can only simplify the conditional when using strict overflow + semantics. */ int foo (char* p) @@ -12,4 +12,4 @@ foo (char* p) return p + 1000 < p; } -/* { dg-final { scan-tree-dump "return 0" "optimized" } } */ +/* { dg-final { scan-tree-dump "\[+\]\[ \]*1000" "optimized" } } */