From patchwork Thu Sep 21 02:43:13 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Pinski X-Patchwork-Id: 1837491 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=marvell.com header.i=@marvell.com header.a=rsa-sha256 header.s=pfpt0220 header.b=XLo+JecK; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=2620:52:3:1:0:246e:9693:128c; helo=server2.sourceware.org; envelope-from=gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=patchwork.ozlabs.org) Received: from server2.sourceware.org (server2.sourceware.org [IPv6:2620:52:3:1:0:246e:9693:128c]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4Rrfq66SGpz1yh6 for ; Thu, 21 Sep 2023 12:43:45 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id A431C3858439 for ; Thu, 21 Sep 2023 02:43:43 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mx0b-0016f401.pphosted.com (mx0b-0016f401.pphosted.com [67.231.156.173]) by sourceware.org (Postfix) with ESMTPS id E03033858C52 for ; Thu, 21 Sep 2023 02:43:29 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org E03033858C52 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=marvell.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=marvell.com Received: from pps.filterd (m0045851.ppops.net [127.0.0.1]) by mx0b-0016f401.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 38KINXRr012101 for ; Wed, 20 Sep 2023 19:43:29 -0700 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=marvell.com; h=from : to : cc : subject : date : message-id : mime-version : content-transfer-encoding : content-type; s=pfpt0220; bh=s051yhz0Q5EjChe9PbM9TqWhbh26E6F5aFHtgY9kJwE=; b=XLo+JecKK4WqIKeHCC1RclRn2DvKG5djhJXztY1wupmwEXLnYfF3/c2btDndAZvOVmiN h++BrNOTSiTnMWHOmmOpwfIdsy2iI/bdYqoUTbb87oZVMeGeclLo05KftcevDkl+x5f6 cd4axFdIfMGMJ3sQGSRMPZOfCH5RLv6Z8a8BAYDg/Wxwl9aU8iigJzd3+smnALCz3oS0 8bu376YCuZghZrOYOQwtloNL/eDxJ0xlW436Su3d9gA9tYbbuixdjemLOJXn1MHzE4fW WFGbI62Ztp4GSUpvw75CobvLzhHeiurWumzqoINh6cCg1SeKagxHPnF6jIRAOysww0T5 QA== Received: from dc5-exch01.marvell.com ([199.233.59.181]) by mx0b-0016f401.pphosted.com (PPS) with ESMTPS id 3t85ptsdgb-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT) for ; Wed, 20 Sep 2023 19:43:28 -0700 Received: from DC5-EXCH01.marvell.com (10.69.176.38) by DC5-EXCH01.marvell.com (10.69.176.38) with Microsoft SMTP Server (TLS) id 15.0.1497.48; Wed, 20 Sep 2023 19:43:25 -0700 Received: from maili.marvell.com (10.69.176.80) by DC5-EXCH01.marvell.com (10.69.176.38) with Microsoft SMTP Server id 15.0.1497.48 via Frontend Transport; Wed, 20 Sep 2023 19:43:25 -0700 Received: from vpnclient.wrightpinski.org.com (unknown [10.69.242.187]) by maili.marvell.com (Postfix) with ESMTP id A17605B693B; Wed, 20 Sep 2023 19:43:25 -0700 (PDT) From: Andrew Pinski To: CC: Andrew Pinski Subject: [PATCH] MATCH: Simplify `(A ==/!= B) &/| (((cast)A) CMP C)` Date: Wed, 20 Sep 2023 19:43:13 -0700 Message-ID: <20230921024313.1941378-1-apinski@marvell.com> X-Mailer: git-send-email 2.31.1 MIME-Version: 1.0 X-Proofpoint-GUID: I8ld98KuBLNMxO7LuHoKlxDXEtkJjpRz X-Proofpoint-ORIG-GUID: I8ld98KuBLNMxO7LuHoKlxDXEtkJjpRz X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.267,Aquarius:18.0.980,Hydra:6.0.601,FMLib:17.11.176.26 definitions=2023-09-20_14,2023-09-20_01,2023-05-22_02 X-Spam-Status: No, score=-14.6 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_LOW, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org This patch adds support to the pattern for `(A == B) &/| (A CMP C)` where the second A could be casted to a different type. Some were handled correctly if using seperate `if` statements but not if combined with BIT_AND/BIT_IOR. In the case of pr111456-1.c, the testcase would pass if `--param=logical-op-non-short-circuit=0` was used but now can be optimized always. OK? Bootstrapped and tested on x86_64-linux-gnu. PR tree-optimization/106164 PR tree-optimization/111456 gcc/ChangeLog: * match.pd (`(A ==/!= B) & (A CMP C)`): Support an optional cast on the second A. (`(A ==/!= B) | (A CMP C)`): Likewise. gcc/testsuite/ChangeLog: * gcc.dg/tree-ssa/cmpbit-6.c: New test. * gcc.dg/tree-ssa/cmpbit-7.c: New test. * gcc.dg/tree-ssa/pr111456-1.c: New test. --- gcc/match.pd | 76 +++++++++++++--------- gcc/testsuite/gcc.dg/tree-ssa/cmpbit-6.c | 22 +++++++ gcc/testsuite/gcc.dg/tree-ssa/cmpbit-7.c | 28 ++++++++ gcc/testsuite/gcc.dg/tree-ssa/pr111456-1.c | 43 ++++++++++++ 4 files changed, 139 insertions(+), 30 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/cmpbit-6.c create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/cmpbit-7.c create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr111456-1.c diff --git a/gcc/match.pd b/gcc/match.pd index a37af05f873..0bf91bde486 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -2973,7 +2973,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) && TYPE_OVERFLOW_WRAPS (TREE_TYPE (@1))) (gt @0 (minus @1 { build_int_cst (TREE_TYPE (@1), 1); })))) -/* Convert (X == CST1) && (X OP2 CST2) to a known value +/* Convert (X == CST1) && ((other)X OP2 CST2) to a known value based on CST1 OP2 CST2. Similarly for (X != CST1). */ /* Convert (X == Y) && (X OP2 Y) to a known value if X is an integral type. Similarly for (X != Y). */ @@ -2981,26 +2981,30 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (for code1 (eq ne) (for code2 (eq ne lt gt le ge) (simplify - (bit_and:c (code1@3 @0 @1) (code2@4 @0 @2)) + (bit_and:c (code1:c@3 @0 @1) (code2:c@4 (convert?@c0 @0) @2)) (if ((TREE_CODE (@1) == INTEGER_CST && TREE_CODE (@2) == INTEGER_CST) || ((INTEGRAL_TYPE_P (TREE_TYPE (@1)) || POINTER_TYPE_P (TREE_TYPE (@1))) - && operand_equal_p (@1, @2))) + && bitwise_equal_p (@1, @2))) (with { bool one_before = false; bool one_after = false; int cmp = 0; + bool allbits = true; if (TREE_CODE (@1) == INTEGER_CST && TREE_CODE (@2) == INTEGER_CST) { - cmp = tree_int_cst_compare (@1, @2); + allbits = TYPE_PRECISION (TREE_TYPE (@1)) <= TYPE_PRECISION (TREE_TYPE (@2)); + auto t1 = wi::to_wide (fold_convert (TREE_TYPE (@2), @1)); + auto t2 = wi::to_wide (@2); + cmp = wi::cmp (t1, t2, TYPE_SIGN (TREE_TYPE (@2))); if (cmp < 0 - && wi::to_wide (@1) == wi::to_wide (@2) - 1) + && t1 == t2 - 1) one_before = true; if (cmp > 0 - && wi::to_wide (@1) == wi::to_wide (@2) + 1) + && t1 == t2 + 1) one_after = true; } bool val; @@ -3018,25 +3022,29 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (switch (if (code1 == EQ_EXPR && val) @3) (if (code1 == EQ_EXPR && !val) { constant_boolean_node (false, type); }) - (if (code1 == NE_EXPR && !val) @4) + (if (code1 == NE_EXPR && !val && allbits) @4) (if (code1 == NE_EXPR && code2 == GE_EXPR - && cmp == 0) - (gt @0 @1)) + && cmp == 0 + && allbits) + (gt @c0 (convert @1))) (if (code1 == NE_EXPR && code2 == LE_EXPR - && cmp == 0) - (lt @0 @1)) + && cmp == 0 + && allbits) + (lt @c0 (convert @1))) /* (a != (b+1)) & (a > b) -> a > (b+1) */ (if (code1 == NE_EXPR && code2 == GT_EXPR - && one_after) - (gt @0 @1)) + && one_after + && allbits) + (gt @c0 (convert @1))) /* (a != (b-1)) & (a < b) -> a < (b-1) */ (if (code1 == NE_EXPR && code2 == LT_EXPR - && one_before) - (lt @0 @1)) + && one_before + && allbits) + (lt @c0 (convert @1))) ) ) ) @@ -3100,26 +3108,30 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (for code1 (eq ne) (for code2 (eq ne lt gt le ge) (simplify - (bit_ior:c (code1@3 @0 @1) (code2@4 @0 @2)) + (bit_ior:c (code1:c@3 @0 @1) (code2:c@4 (convert?@c0 @0) @2)) (if ((TREE_CODE (@1) == INTEGER_CST && TREE_CODE (@2) == INTEGER_CST) || ((INTEGRAL_TYPE_P (TREE_TYPE (@1)) || POINTER_TYPE_P (TREE_TYPE (@1))) - && operand_equal_p (@1, @2))) + && bitwise_equal_p (@1, @2))) (with { bool one_before = false; bool one_after = false; int cmp = 0; + bool allbits = true; if (TREE_CODE (@1) == INTEGER_CST && TREE_CODE (@2) == INTEGER_CST) { - cmp = tree_int_cst_compare (@1, @2); + allbits = TYPE_PRECISION (TREE_TYPE (@1)) <= TYPE_PRECISION (TREE_TYPE (@2)); + auto t1 = wi::to_wide (fold_convert (TREE_TYPE (@2), @1)); + auto t2 = wi::to_wide (@2); + cmp = wi::cmp (t1, t2, TYPE_SIGN (TREE_TYPE (@2))); if (cmp < 0 - && wi::to_wide (@1) == wi::to_wide (@2) - 1) + && t1 == t2 - 1) one_before = true; if (cmp > 0 - && wi::to_wide (@1) == wi::to_wide (@2) + 1) + && t1 == t2 + 1) one_after = true; } bool val; @@ -3136,26 +3148,30 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) } (switch (if (code1 == EQ_EXPR && val) @4) - (if (code1 == NE_EXPR && val) { constant_boolean_node (true, type); }) - (if (code1 == NE_EXPR && !val) @3) + (if (code1 == NE_EXPR && val && allbits) { constant_boolean_node (true, type); }) + (if (code1 == NE_EXPR && !val && allbits) @3) (if (code1 == EQ_EXPR && code2 == GT_EXPR - && cmp == 0) - (ge @0 @1)) + && cmp == 0 + && allbits) + (ge @c0 @2)) (if (code1 == EQ_EXPR && code2 == LT_EXPR - && cmp == 0) - (le @0 @1)) + && cmp == 0 + && allbits) + (le @c0 @2)) /* (a == (b-1)) | (a >= b) -> a >= (b-1) */ (if (code1 == EQ_EXPR && code2 == GE_EXPR - && one_before) - (ge @0 @1)) + && one_before + && allbits) + (ge @c0 (convert @1))) /* (a == (b+1)) | (a <= b) -> a <= (b-1) */ (if (code1 == EQ_EXPR && code2 == LE_EXPR - && one_after) - (le @0 @1)) + && one_after + && allbits) + (le @c0 (convert @1))) ) ) ) diff --git a/gcc/testsuite/gcc.dg/tree-ssa/cmpbit-6.c b/gcc/testsuite/gcc.dg/tree-ssa/cmpbit-6.c new file mode 100644 index 00000000000..4ec73f030bb --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/cmpbit-6.c @@ -0,0 +1,22 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ +/* PR tree-optimization/106164 */ +/* PR tree-optimization/111456 */ + +_Bool iu(int a) +{ + _Bool t = a == 0; + unsigned t1 = a; + _Bool t2 = t1 >= 3; + return t & t2; +} + +_Bool is(int a) +{ + _Bool t = a == 0; + short t1 = a; + _Bool t2 = t1 >= 3; + return t & t2; +} + +/* { dg-final { scan-tree-dump-times "return 0" 2 "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/cmpbit-7.c b/gcc/testsuite/gcc.dg/tree-ssa/cmpbit-7.c new file mode 100644 index 00000000000..ee04ebbaaed --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/cmpbit-7.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-forwprop1" } */ +/* PR tree-optimization/106164 */ +/* PR tree-optimization/111456 */ + +_Bool f(int a) +{ + _Bool t = a == 3; + unsigned t1 = a; + _Bool t2 = t1 >= 3; + return t | t2; +} + +/* Should be able to optimize down to just `a > 2` during forwprop1 */ +/* { dg-final { scan-tree-dump-not "a_\[0-9\]+.D. == 3" "forwprop1" } } */ + +_Bool f1(int b) +{ + _Bool t = b == 3; + short t1 = b; + _Bool t2 = t1 >= 3; + return t | t2; +} + +/* Should be able to optimize down to just `a > 2` during forwprop1 as `((short)a) >= 3` is + true already when `a == 3`. */ +/* { dg-final { scan-tree-dump-not "b_\[0-9\]+.D. == 3" "forwprop1" } } */ +/* { dg-final { scan-tree-dump-times "_\[0-9\]+ > 2" 2 "forwprop1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr111456-1.c b/gcc/testsuite/gcc.dg/tree-ssa/pr111456-1.c new file mode 100644 index 00000000000..8a2f730b387 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr111456-1.c @@ -0,0 +1,43 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ +/* PR tree-optimization/111456 */ + +void foo(void); +static int i; +static int *j = &i; +static char l; +static void(a)(char) {} +static short(b)(short c, short d) { return c - d; } +static short(e)(short f, int g) { + return f < 0 || g < 0 || g >= 32 ? f : f >> g; +} +static short(h)(short f, int g) { return g >= 2 ?: f >> g; } +static char k(char m, short n) { + short o; + int *p = &i; + if (!(((m) >= 1) && ((m) <= 1))) { + __builtin_unreachable(); + } + o = e(i, i); + if (h(1, o)) + ; + else { + m = 0; + for (; m >= -20; m = b(m, 9)) + if (a(i), n) { + if (*p) + ; + else + foo(); + ; + } else + return l; + } + return i; +} +int main() { k(0 <= 0 > *j, i); } + + +/* { dg-final { scan-tree-dump-not "foo " "optimized" } } */ +/* { dg-final { scan-tree-dump "return 0;" "optimized" } } */ +