From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [63.128.21.124]) by sourceware.org (Postfix) with ESMTP id 8567F386103C for ; Thu, 8 Oct 2020 13:54:49 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 8567F386103C Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-14-DK97mG8jO0-Y03Zgrmc0Sg-1; Thu, 08 Oct 2020 09:54:46 -0400 X-MC-Unique: DK97mG8jO0-Y03Zgrmc0Sg-1 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 5C22780A1B9; Thu, 8 Oct 2020 13:54:45 +0000 (UTC) Received: from tucnak.zalov.cz (ovpn-112-37.ams2.redhat.com [10.36.112.37]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 070EC5C1BD; Thu, 8 Oct 2020 13:54:44 +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 098DsgjK027057; Thu, 8 Oct 2020 15:54:43 +0200 Received: (from jakub@localhost) by tucnak.zalov.cz (8.15.2/8.15.2/Submit) id 098DsgpV027056; Thu, 8 Oct 2020 15:54:42 +0200 Date: Thu, 8 Oct 2020 15:54:41 +0200 From: Jakub Jelinek To: Aldy Hernandez , Richard Biener Cc: gcc-patches@gcc.gnu.org Subject: [PATCH] vrp: Fix up gcc.target/aarch64/pr90838.c [PR97312, PR94801] Message-ID: <20201008135441.GW2176@tucnak> Reply-To: Jakub Jelinek References: <20201008102211.GQ2176@tucnak> MIME-Version: 1.0 In-Reply-To: <20201008102211.GQ2176@tucnak> User-Agent: Mutt/1.11.3 (2019-02-01) X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Type: text/plain; charset=us-ascii Content-Disposition: inline X-Spam-Status: No, score=-6.4 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H5, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 08 Oct 2020 13:54:51 -0000 On Thu, Oct 08, 2020 at 12:22:11PM +0200, Jakub Jelinek via Gcc-patches wrote: > Perhaps another way out of this would be document and enforce that > __builtin_c[lt]z{,l,ll} etc calls are undefined at zero, but C[TL]Z ifn > calls are defined there based on *_DEFINED_VALUE_AT_ZERO (*) == 2 The following patch implements that, i.e. __builtin_c?z* now take full advantage of them being UB at zero, while the ifns are well defined at zero if *_DEFINED_VALUE_AT_ZERO (*) == 2. That is what fixes PR94801. Furthermore, to fix PR97312, if it is well defined at zero and the value at zero is prec, we don't lower the maximum unless the argument is known to be non-zero. For gimple-range.cc I guess we could improve it if needed e.g. by returning a [0,7][32,32] range for .CTZ of e.g. [0,137], but for now it (roughly) matches what vr-values.c does. Ok for trunk if it passes bootstrap/regtest? 2020-10-08 Jakub Jelinek PR tree-optimization/94801 PR target/97312 * vr-values.c (vr_values::extract_range_basic) : When stmt is not an internal-fn call or C?Z_DEFINED_VALUE_AT_ZERO is not 2, assume argument is not zero and thus use [0, prec-1] range unless it can be further improved. For CTZ, don't update maxi from upper bound if it was previously prec. * gimple-range.cc (gimple_ranger::range_of_builtin_call) : Likewise. * gcc.dg/tree-ssa/pr94801.c: New test. --- gcc/vr-values.c.jj 2020-10-07 10:47:47.065983121 +0200 +++ gcc/vr-values.c 2020-10-08 15:23:56.042631592 +0200 @@ -1208,34 +1208,42 @@ vr_values::extract_range_basic (value_ra mini = 0; maxi = 1; goto bitop_builtin; - /* __builtin_c[lt]z* return [0, prec-1], except for + /* __builtin_clz* return [0, prec-1], except for when the argument is 0, but that is undefined behavior. - On many targets where the CLZ RTL or optab value is defined - for 0 the value is prec, so include that in the range - by default. */ + Always handle __builtin_clz* which can be only written + by user as UB on 0 and so [0, prec-1] range, and the internal-fn + calls depending on how CLZ_DEFINED_VALUE_AT_ZERO is defined. */ CASE_CFN_CLZ: arg = gimple_call_arg (stmt, 0); prec = TYPE_PRECISION (TREE_TYPE (arg)); mini = 0; - maxi = prec; + maxi = prec - 1; mode = SCALAR_INT_TYPE_MODE (TREE_TYPE (arg)); - if (optab_handler (clz_optab, mode) != CODE_FOR_nothing - && CLZ_DEFINED_VALUE_AT_ZERO (mode, zerov) - /* Handle only the single common value. */ - && zerov != prec) - /* Magic value to give up, unless vr0 proves - arg is non-zero. */ - mini = -2; + if (gimple_call_internal_p (stmt)) + { + if (optab_handler (clz_optab, mode) != CODE_FOR_nothing + && CLZ_DEFINED_VALUE_AT_ZERO (mode, zerov) == 2) + { + /* Handle only the single common value. */ + if (zerov == prec) + maxi = prec; + /* Magic value to give up, unless vr0 proves + arg is non-zero. */ + else + mini = -2; + } + } if (TREE_CODE (arg) == SSA_NAME) { const value_range_equiv *vr0 = get_value_range (arg); /* From clz of VR_RANGE minimum we can compute result maximum. */ if (vr0->kind () == VR_RANGE - && TREE_CODE (vr0->min ()) == INTEGER_CST) + && TREE_CODE (vr0->min ()) == INTEGER_CST + && integer_nonzerop (vr0->min ())) { maxi = prec - 1 - tree_floor_log2 (vr0->min ()); - if (maxi != prec) + if (mini == -2) mini = 0; } else if (vr0->kind () == VR_ANTI_RANGE @@ -1251,9 +1259,14 @@ vr_values::extract_range_basic (value_ra if (vr0->kind () == VR_RANGE && TREE_CODE (vr0->max ()) == INTEGER_CST) { - mini = prec - 1 - tree_floor_log2 (vr0->max ()); - if (mini == prec) - break; + int newmini = prec - 1 - tree_floor_log2 (vr0->max ()); + if (newmini == prec) + { + if (maxi == prec) + mini = prec; + } + else + mini = newmini; } } if (mini == -2) @@ -1261,27 +1274,30 @@ vr_values::extract_range_basic (value_ra goto bitop_builtin; /* __builtin_ctz* return [0, prec-1], except for when the argument is 0, but that is undefined behavior. - If there is a ctz optab for this mode and - CTZ_DEFINED_VALUE_AT_ZERO, include that in the range, - otherwise just assume 0 won't be seen. */ + Always handle __builtin_ctz* which can be only written + by user as UB on 0 and so [0, prec-1] range, and the internal-fn + calls depending on how CTZ_DEFINED_VALUE_AT_ZERO is defined. */ CASE_CFN_CTZ: arg = gimple_call_arg (stmt, 0); prec = TYPE_PRECISION (TREE_TYPE (arg)); mini = 0; maxi = prec - 1; mode = SCALAR_INT_TYPE_MODE (TREE_TYPE (arg)); - if (optab_handler (ctz_optab, mode) != CODE_FOR_nothing - && CTZ_DEFINED_VALUE_AT_ZERO (mode, zerov)) + if (gimple_call_internal_p (stmt)) { - /* Handle only the two common values. */ - if (zerov == -1) - mini = -1; - else if (zerov == prec) - maxi = prec; - else - /* Magic value to give up, unless vr0 proves - arg is non-zero. */ - mini = -2; + if (optab_handler (ctz_optab, mode) != CODE_FOR_nothing + && CTZ_DEFINED_VALUE_AT_ZERO (mode, zerov) == 2) + { + /* Handle only the two common values. */ + if (zerov == -1) + mini = -1; + else if (zerov == prec) + maxi = prec; + else + /* Magic value to give up, unless vr0 proves + arg is non-zero. */ + mini = -2; + } } if (TREE_CODE (arg) == SSA_NAME) { @@ -1300,10 +1316,16 @@ vr_values::extract_range_basic (value_ra if (vr0->kind () == VR_RANGE && TREE_CODE (vr0->max ()) == INTEGER_CST) { - maxi = tree_floor_log2 (vr0->max ()); - /* For vr0 [0, 0] give up. */ - if (maxi == -1) - break; + int newmaxi = tree_floor_log2 (vr0->max ()); + if (newmaxi == -1) + { + if (mini == -1) + maxi = -1; + else if (maxi == prec) + mini = prec; + } + else if (maxi != prec) + maxi = newmaxi; } } if (mini == -2) --- gcc/gimple-range.cc.jj 2020-10-08 11:55:25.498313173 +0200 +++ gcc/gimple-range.cc 2020-10-08 15:36:14.926945183 +0200 @@ -636,28 +636,37 @@ gimple_ranger::range_of_builtin_call (ir // __builtin_c[lt]z* return [0, prec-1], except when the // argument is 0, but that is undefined behavior. // - // On many targets where the CLZ RTL or optab value is defined - // for 0, the value is prec, so include that in the range by - // default. + // For __builtin_c[lt]z* consider argument of 0 always undefined + // behavior, for internal fns depending on C?Z_DEFINED_VALUE_AT_ZERO. arg = gimple_call_arg (call, 0); prec = TYPE_PRECISION (TREE_TYPE (arg)); mini = 0; - maxi = prec; + maxi = prec - 1; mode = SCALAR_INT_TYPE_MODE (TREE_TYPE (arg)); - if (optab_handler (clz_optab, mode) != CODE_FOR_nothing - && CLZ_DEFINED_VALUE_AT_ZERO (mode, zerov) - // Only handle the single common value. - && zerov != prec) - // Magic value to give up, unless we can prove arg is non-zero. - mini = -2; + if (gimple_call_internal_p (call)) + { + if (optab_handler (clz_optab, mode) != CODE_FOR_nothing + && CLZ_DEFINED_VALUE_AT_ZERO (mode, zerov) == 2) + { + // Only handle the single common value. + if (zerov == prec) + maxi = prec; + else + // Magic value to give up, unless we can prove arg is non-zero. + mini = -2; + } + } gcc_assert (range_of_expr (r, arg, call)); // From clz of minimum we can compute result maximum. if (r.constant_p ()) { - maxi = prec - 1 - wi::floor_log2 (r.lower_bound ()); - if (maxi != prec) - mini = 0; + int newmaxi = prec - 1 - wi::floor_log2 (r.lower_bound ()); + if (newmaxi != prec) + { + mini = 0; + maxi = newmaxi; + } } else if (!range_includes_zero_p (&r)) { @@ -669,9 +678,14 @@ gimple_ranger::range_of_builtin_call (ir // From clz of maximum we can compute result minimum. if (r.constant_p ()) { - mini = prec - 1 - wi::floor_log2 (r.upper_bound ()); - if (mini == prec) - break; + int newmini = prec - 1 - wi::floor_log2 (r.upper_bound ()); + if (newmini == prec) + { + if (maxi == prec) + mini = prec; + } + else + mini = newmini; } if (mini == -2) break; @@ -682,25 +696,27 @@ gimple_ranger::range_of_builtin_call (ir // __builtin_ctz* return [0, prec-1], except for when the // argument is 0, but that is undefined behavior. // - // If there is a ctz optab for this mode and - // CTZ_DEFINED_VALUE_AT_ZERO, include that in the range, - // otherwise just assume 0 won't be seen. + // For __builtin_ctz* consider argument of 0 always undefined + // behavior, for internal fns depending on CTZ_DEFINED_VALUE_AT_ZERO. arg = gimple_call_arg (call, 0); prec = TYPE_PRECISION (TREE_TYPE (arg)); mini = 0; maxi = prec - 1; mode = SCALAR_INT_TYPE_MODE (TREE_TYPE (arg)); - if (optab_handler (ctz_optab, mode) != CODE_FOR_nothing - && CTZ_DEFINED_VALUE_AT_ZERO (mode, zerov)) + if (gimple_call_internal_p (call)) { - // Handle only the two common values. - if (zerov == -1) - mini = -1; - else if (zerov == prec) - maxi = prec; - else - // Magic value to give up, unless we can prove arg is non-zero. - mini = -2; + if (optab_handler (ctz_optab, mode) != CODE_FOR_nothing + && CTZ_DEFINED_VALUE_AT_ZERO (mode, zerov) == 2) + { + // Handle only the two common values. + if (zerov == -1) + mini = -1; + else if (zerov == prec) + maxi = prec; + else + // Magic value to give up, unless we can prove arg is non-zero. + mini = -2; + } } gcc_assert (range_of_expr (r, arg, call)); if (!r.undefined_p ()) @@ -714,8 +730,14 @@ gimple_ranger::range_of_builtin_call (ir // the maximum. wide_int max = r.upper_bound (); if (max == 0) - break; - maxi = wi::floor_log2 (max); + { + if (mini == -1) + maxi = -1; + else if (maxi == prec) + mini = prec; + } + else if (maxi != prec) + maxi = wi::floor_log2 (max); } if (mini == -2) break; --- gcc/testsuite/gcc.dg/tree-ssa/pr94801.c.jj 2020-10-08 15:35:01.837005736 +0200 +++ gcc/testsuite/gcc.dg/tree-ssa/pr94801.c 2020-10-08 15:34:49.252188342 +0200 @@ -0,0 +1,16 @@ +/* PR tree-optimization/94801 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ +/* { dg-final { scan-tree-dump-times "return 0;" 2 "optimized" } } */ + +int +foo (int a) +{ + return __builtin_clz (a) >> 5; +} + +int +bar (int a) +{ + return __builtin_ctz (a) >> 5; +} Jakub