From patchwork Thu Oct 26 21:09:49 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Pinski X-Patchwork-Id: 158684 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:d641:0:b0:403:3b70:6f57 with SMTP id cy1csp171573vqb; Thu, 26 Oct 2023 14:10:21 -0700 (PDT) X-Google-Smtp-Source: AGHT+IH5b2Pr+Dtc3LOzTLEr1HrqvEHoSJcrE+s9ZusG/ym6U1n3/Je9KdkRMoLjHMjfKHGAOThv X-Received: by 2002:a05:620a:2908:b0:76c:e2db:42b0 with SMTP id m8-20020a05620a290800b0076ce2db42b0mr488176qkp.64.1698354620996; Thu, 26 Oct 2023 14:10:20 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1698354620; cv=pass; d=google.com; s=arc-20160816; b=yaR3J9e1cOKXXiEIokGizQZCAHJYGCJGROzMcIVBfoTkssSuD4l4KkRyKpBYwyWL/8 WPM5Gqp04dnotyf5HrtMrl+rKgoZL7s/e5YktyHGs7Jf/vqhigMvtqbiUC4xbs6DGuQx UXZpcDe3FnNZWG38Cn3QlRZ68NuKtaT6Y/CyZaizN8bgGZcE9a460ORZHUMBUzwDEyCj CJ2dD9EH6ewTPoOsnWn8wLsNLdmyI3MFOuWkXHs4ULzcoXsLPoc9ItgV/QKzYAjN7y0I cLBXNSnQGjQoUhIHPBPwmqf1mteO3j0ts5X74vG9Ux2LBmoZmx4XSlfH0rugHQwYmp4l uUyg== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=errors-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:content-transfer-encoding :mime-version:message-id:date:subject:cc:to:from:dkim-signature :arc-filter:dmarc-filter:delivered-to; bh=MFO7E5RcAMcqqt8Rv0IVn6ujffG2xcnruYTx2xsxDVI=; fh=HUGtWGYelUIGEawCthw3zL4YE3u5HCOc2KzDDaWspeg=; b=GD+h7xDz366pW6nd5P5d7fBW2qm5ztxHBMsd551nl1DYwfkUOSLJqZ/NzIzidFGWG4 cl/FyOwdeefw6OaclqP5Tdatx93CdB2yQZnLyq8y10ukn0PODw3qTOQupgYSrmJqAoOi KXxnGxxO1aqw4ob44NSB0961A6Y8FiWiye0x5Mc5dlCKr9qgb3G6JnlHkgrot78Orn2o WPkacoRH+QxMeD50cBaFtg+QfwjMVfny4EsXA+7mbXp8ehIOHmGaj+kIs4GHaVMDvoG4 2AuUVc1ICQfdAqB/i3fF/zFoAyxmr2AH/BtnAGV8uVjUq8/PGnS2Qn1e7URKFSe8Li7I aT1A== ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@gmail.com header.s=20230601 header.b=HDeE3OFG; arc=pass (i=1); spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 8.43.85.97 as permitted sender) smtp.mailfrom="gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org"; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: from server2.sourceware.org (server2.sourceware.org. [8.43.85.97]) by mx.google.com with ESMTPS id j3-20020a37c243000000b00779ed5165e9si55797qkm.189.2023.10.26.14.10.20 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 26 Oct 2023 14:10:20 -0700 (PDT) Received-SPF: pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 8.43.85.97 as permitted sender) client-ip=8.43.85.97; Authentication-Results: mx.google.com; dkim=pass header.i=@gmail.com header.s=20230601 header.b=HDeE3OFG; arc=pass (i=1); spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 8.43.85.97 as permitted sender) smtp.mailfrom="gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org"; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id BF5DB385352D for ; Thu, 26 Oct 2023 21:10:20 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-pf1-x430.google.com (mail-pf1-x430.google.com [IPv6:2607:f8b0:4864:20::430]) by sourceware.org (Postfix) with ESMTPS id 76C743858D35 for ; Thu, 26 Oct 2023 21:09:54 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 76C743858D35 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=gmail.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 76C743858D35 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::430 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1698354596; cv=none; b=l/fAUK9oinPaoP1Ap7Zb71YkhKxSNCYyErinGXeqPf4fNawDJVAt+efgUuhCbgm8rM6p6dQ/544zWYFLQfzwbkogfuYruyaohDdG3ATUOiQkynJbb+4EysdfXr6CL2RRDHP/FWVf1jznYNe1g6ZyMAGgsGmdAvwRIQcVivBX+AM= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1698354596; c=relaxed/simple; bh=2Fpj7yRXWQoWjvhq7j2pkAaNiqodS0nWWBO/jerXpFc=; h=DKIM-Signature:From:To:Subject:Date:Message-Id:MIME-Version; b=KpdoJVWWrcUrZ/e48fSXaYS5f63ZOMl6n87dbVmxPWxqW2rpNuuSxtKBA6NTgxZCG8cVi7Bzz6av0d1t5TZ/afwxk/GYI0IBnlJEoTPHLBLPIQRw1tAkl9whJfPDLHNyGBe49ahhk0tPMMBTaAZWSxVnjHXbCRMM+jkkvmeD/Fo= ARC-Authentication-Results: i=1; server2.sourceware.org Received: by mail-pf1-x430.google.com with SMTP id d2e1a72fcca58-6b5af4662b7so1314624b3a.3 for ; Thu, 26 Oct 2023 14:09:54 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1698354593; x=1698959393; darn=gcc.gnu.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=MFO7E5RcAMcqqt8Rv0IVn6ujffG2xcnruYTx2xsxDVI=; b=HDeE3OFGTgeSjfoyUNAwSldidFq79HcRnV1ENvlT5feH/uTVS/U0V1ohnx2gJOV0X7 xUN1h31t1/U+GPFXmyj+SOZJLJlAXM2IHIzLPynavruP/cMjfTa7u1CE32IGUpT7U2la PpVdq86NbjXFgl5hzPxkQ9CREM3o88fQTJ48MKAhG8Y1ljR2s4YdVHIIits3MQbXtmQz Ku+1kHMCzeQ33l2wIAcajh1jAxBfoju7fuxO3L3Ud6+JMJ2IPNScjwc2opV5ps0INVWV 3MsICYbVEIjoyno8h/b3aUWfzY63wIXjT9in2ZCCVvs3wxp8C49jsVNMdLj6QFlIMnwQ wssg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1698354593; x=1698959393; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=MFO7E5RcAMcqqt8Rv0IVn6ujffG2xcnruYTx2xsxDVI=; b=EbJ8vJ3EICh9ka7ComiV7L8W40CjnzOkThWp1meflAcUpT20+9mt9ZdJP/7KaFA//C 4mEchNRyrRwr+in2q5wfTu2pzKIUoWGndXna6Ia0moPAH1ZxgKopfvWm9iUenVXJ+fWT ZVmLu762iZ6ay38BzvMdz+/SMBjtNgMo8UA4GFf0OftlYKFE022AecNOgh4zAOoQjVa6 VwsGsCpQuls5Ae5qX/1dHJIttarvePWHGl8t2uJ++F/9i26mOUjj99EkoOJI4AGidL3R wc9Vs6b/R5o/escZb62fZIT1ShC0+Rhdbg6W/3HIkjMipp4KOMm4KDx9KRhGx5gavwuN 8oYA== X-Gm-Message-State: AOJu0YxGzcs1ZO2kN7m5k8qF/nUKp9gXVnZkZttBNV+IPEio0zhbG5Qq zRT8+L4kN47m+KE1lNs7kJqOdkxptE4= X-Received: by 2002:a05:6a00:16cb:b0:6bc:eb60:b26c with SMTP id l11-20020a056a0016cb00b006bceb60b26cmr786778pfc.25.1698354592890; Thu, 26 Oct 2023 14:09:52 -0700 (PDT) Received: from xeond2.wrightpinski.org ([98.97.118.94]) by smtp.gmail.com with ESMTPSA id p15-20020aa7860f000000b006889348ba6esm30477pfn.127.2023.10.26.14.09.52 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 26 Oct 2023 14:09:52 -0700 (PDT) From: Andrew Pinski To: gcc-patches@gcc.gnu.org Cc: Andrew Pinski Subject: [PATCH] MATCH: Simplify `(X &| B) CMP X` if possible [PR 101590] Date: Thu, 26 Oct 2023 14:09:49 -0700 Message-Id: <20231026210949.2881006-1-pinskia@gmail.com> X-Mailer: git-send-email 2.39.3 MIME-Version: 1.0 X-Spam-Status: No, score=-10.8 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, 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+ouuuleilei=gmail.com@gcc.gnu.org X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1780853895058667451 X-GMAIL-MSGID: 1780853895058667451 From: Andrew Pinski I noticed we were missing these simplifications so let's add them. This adds the following simplifications: U & N <= U -> true U & N > U -> false When U is known to be as non-negative. When N is also known to be non-negative, this is also true: U | N < U -> false U | N >= U -> true When N is a negative integer, the result flips and we get: U | N < U -> true U | N >= U -> false We could extend this later on to be the case where we know N is nonconstant but is known to be negative. Bootstrapped and tested on x86_64-linux-gnu with no regressions. PR tree-optimization/101590 PR tree-optimization/94884 gcc/ChangeLog: * match.pd (`(X BIT_OP Y) CMP X`): New pattern. gcc/testsuite/ChangeLog: * gcc.dg/tree-ssa/bitcmp-1.c: New test. * gcc.dg/tree-ssa/bitcmp-2.c: New test. * gcc.dg/tree-ssa/bitcmp-3.c: New test. * gcc.dg/tree-ssa/bitcmp-4.c: New test. * gcc.dg/tree-ssa/bitcmp-5.c: New test. * gcc.dg/tree-ssa/bitcmp-6.c: New test. --- gcc/match.pd | 24 +++++++++++++ gcc/testsuite/gcc.dg/tree-ssa/bitcmp-1.c | 20 +++++++++++ gcc/testsuite/gcc.dg/tree-ssa/bitcmp-2.c | 20 +++++++++++ gcc/testsuite/gcc.dg/tree-ssa/bitcmp-3.c | 21 ++++++++++++ gcc/testsuite/gcc.dg/tree-ssa/bitcmp-4.c | 36 ++++++++++++++++++++ gcc/testsuite/gcc.dg/tree-ssa/bitcmp-5.c | 43 ++++++++++++++++++++++++ gcc/testsuite/gcc.dg/tree-ssa/bitcmp-6.c | 41 ++++++++++++++++++++++ 7 files changed, 205 insertions(+) create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/bitcmp-1.c create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/bitcmp-2.c create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/bitcmp-3.c create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/bitcmp-4.c create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/bitcmp-5.c create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/bitcmp-6.c diff --git a/gcc/match.pd b/gcc/match.pd index 5f6aeb07ac0..7d651a6582d 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -2707,6 +2707,30 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (if (TREE_INT_CST_LOW (@1) & 1) { constant_boolean_node (cmp == NE_EXPR, type); }))) +/* + U & N <= U -> true + U & N > U -> false + U needs to be non-negative. + + U | N < U -> false + U | N >= U -> true + U and N needs to be non-negative + + U | N < U -> true + U | N >= U -> false + U needs to be non-negative and N needs to be a negative constant. + */ +(for cmp (lt ge le gt ) + bitop (bit_ior bit_ior bit_and bit_and) + (simplify + (cmp:c (bitop:c tree_expr_nonnegative_p@0 @1) @0) + (if (INTEGRAL_TYPE_P (TREE_TYPE (@0))) + (if (bitop == BIT_AND_EXPR || tree_expr_nonnegative_p (@1)) + { constant_boolean_node (cmp == GE_EXPR || cmp == LE_EXPR, type); } + /* The sign is opposite now so the comparison is swapped around. */ + (if (TREE_CODE (@1) == INTEGER_CST && wi::neg_p (wi::to_wide (@1))) + { constant_boolean_node (cmp == LT_EXPR, type); }))))) + /* Arguments on which one can call get_nonzero_bits to get the bits possibly set. */ (match with_possible_nonzero_bits diff --git a/gcc/testsuite/gcc.dg/tree-ssa/bitcmp-1.c b/gcc/testsuite/gcc.dg/tree-ssa/bitcmp-1.c new file mode 100644 index 00000000000..f3d515bb2d6 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/bitcmp-1.c @@ -0,0 +1,20 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ +/* PR tree-optimization/101590 */ + +int f_and_le(unsigned len) { + const unsigned N = 4; + unsigned newlen = len & -N; + return newlen <= len; // return 1 +} +int f_or_ge(unsigned len) { + const unsigned N = 4; + unsigned newlen = len | -N; + return newlen >= len; // return 1 +} + +/* { dg-final { scan-tree-dump-not " <= " "optimized" } } */ +/* { dg-final { scan-tree-dump-not " >= " "optimized" } } */ +/* { dg-final { scan-tree-dump-not " & " "optimized" } } */ +/* { dg-final { scan-tree-dump-not " \\\| " "optimized" } } */ +/* { dg-final { scan-tree-dump-times "return 1;" 2 "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/bitcmp-2.c b/gcc/testsuite/gcc.dg/tree-ssa/bitcmp-2.c new file mode 100644 index 00000000000..d0031d9ecb8 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/bitcmp-2.c @@ -0,0 +1,20 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ +/* PR tree-optimization/101590 */ + +int f_and_gt(unsigned len) { + const unsigned N = 4; + unsigned newlen = len & -N; + return newlen > len; // return 0 +} +int f_or_lt(unsigned len) { + const unsigned N = 4; + unsigned newlen = len | -N; + return newlen < len; // return 0 +} + +/* { dg-final { scan-tree-dump-not " > " "optimized" } } */ +/* { dg-final { scan-tree-dump-not " < " "optimized" } } */ +/* { dg-final { scan-tree-dump-not " & " "optimized" } } */ +/* { dg-final { scan-tree-dump-not " \\\| " "optimized" } } */ +/* { dg-final { scan-tree-dump-times "return 0;" 2 "optimized" } } */ \ No newline at end of file diff --git a/gcc/testsuite/gcc.dg/tree-ssa/bitcmp-3.c b/gcc/testsuite/gcc.dg/tree-ssa/bitcmp-3.c new file mode 100644 index 00000000000..5cfab7dc742 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/bitcmp-3.c @@ -0,0 +1,21 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ +/* PR tree-optimization/94884 */ + +#define bool _Bool +bool decide() __attribute((const)); + +inline unsigned getXOrY(unsigned x, unsigned y) +{ + return decide() ? y : x; +} + +bool f(unsigned x, unsigned y) +{ + return (x | y) >= getXOrY(x, y); +} + + +/* { dg-final { scan-tree-dump-not " >= " "optimized" } } */ +/* { dg-final { scan-tree-dump-not " \\\| " "optimized" } } */ +/* { dg-final { scan-tree-dump-times "return 1;" 1 "optimized" } } */ \ No newline at end of file diff --git a/gcc/testsuite/gcc.dg/tree-ssa/bitcmp-4.c b/gcc/testsuite/gcc.dg/tree-ssa/bitcmp-4.c new file mode 100644 index 00000000000..701014b2d0e --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/bitcmp-4.c @@ -0,0 +1,36 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ +/* PR tree-optimization/101590 */ + +int f_and_le(int len) { + const int N = 4; + int newlen = len & -N; + return newlen <= len; +} +int f_or_ge(int len) { + const int N = 4; + int newlen = len | -N; + return newlen >= len; +} + +int f_and_gt(int len) { + const int N = 4; + int newlen = len & -N; + return newlen > len; +} +int f_or_lt(int len) { + const int N = 4; + int newlen = len | -N; + return newlen < len; +} + +/* These cannot be optimized since we don't know if the sign + can change or not. */ +/* { dg-final { scan-tree-dump-times " > " 1 "optimized" } } */ +/* { dg-final { scan-tree-dump-times " < " 1 "optimized" } } */ +/* { dg-final { scan-tree-dump-times " <= " 1 "optimized" } } */ +/* { dg-final { scan-tree-dump-times " >= " 1 "optimized" } } */ +/* { dg-final { scan-tree-dump-times " & " 2 "optimized" } } */ +/* { dg-final { scan-tree-dump-times " \\\| " 2 "optimized" } } */ +/* { dg-final { scan-tree-dump-not "return 1;" "optimized" } } */ +/* { dg-final { scan-tree-dump-not "return 0;" "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/bitcmp-5.c b/gcc/testsuite/gcc.dg/tree-ssa/bitcmp-5.c new file mode 100644 index 00000000000..a6be14294b4 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/bitcmp-5.c @@ -0,0 +1,43 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ +/* PR tree-optimization/101590 */ + +/* These are the signed integer versions + of `(a & b) CMP a` and `(a | b) CMP a` + which can be optimized to 1. */ + + +/* For `&`, the non-negativeness of b is not taken into account. */ +int f_and_le(int len) { + len &= 0xfffff; + const int N = 4; + int newlen = len & -N; + return newlen <= len; // return 1 +} +int f_and_le_(int len, int N) { + len &= 0xfffff; + int newlen = len & -N; + return newlen <= len; // return 1 +} + + +/* For `|`, to get a known value, b either needs to be non-negative + or a constant. For the negative constant case, we swap around the comparison. */ +int f_or_ge_(int len, int N) { + len &= 0xfffff; + N &= 0xffff; + int newlen = len | N; + return newlen >= len; // return 1 +} +int f_or_lt(int len) { + len &= 0xfffff; + const int N = 4; + int newlen = len | -N; + return newlen < len; // return 1 +} + +/* { dg-final { scan-tree-dump-not " <= " "optimized" } } */ +/* { dg-final { scan-tree-dump-not " >= " "optimized" } } */ +/* { dg-final { scan-tree-dump-not " & " "optimized" } } */ +/* { dg-final { scan-tree-dump-not " \\\| " "optimized" } } */ +/* { dg-final { scan-tree-dump-times "return 1;" 4 "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/bitcmp-6.c b/gcc/testsuite/gcc.dg/tree-ssa/bitcmp-6.c new file mode 100644 index 00000000000..a86a19fbef2 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/bitcmp-6.c @@ -0,0 +1,41 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ +/* PR tree-optimization/101590 */ + +/* These are the signed integer versions + of `(a & b) CMP a` and `(a | b) CMP a` + which can be optimized to 0. */ + +/* For `&`, the non-negativeness of b is not taken into account. */ +int f_and_gt(int len) { + len &= 0xfffff; + const int N = 4; + int newlen = len & -N; + return newlen > len; // return 0 +} +int f_and_gt_(int len, int N) { + len &= 0xfffff; + int newlen = len & -N; + return newlen > len; // return 0 +} + +/* For `|`, to get a known value, b either needs to be non-negative + or a constant. For the negative constant case, we swap around the comparison. */ +int f_or_lt_(int len, int N) { + len &= 0xfffff; + N &= 0xffff; + int newlen = len | N; + return newlen < len; // return 0 +} +int f_or_ge(int len) { + len &= 0xfffff; + const int N = 4; + int newlen = len | -N; + return newlen >= len; // return 0 +} + +/* { dg-final { scan-tree-dump-not " > " "optimized" } } */ +/* { dg-final { scan-tree-dump-not " < " "optimized" } } */ +/* { dg-final { scan-tree-dump-not " & " "optimized" } } */ +/* { dg-final { scan-tree-dump-not " \\\| " "optimized" } } */ +/* { dg-final { scan-tree-dump-times "return 0;" 4 "optimized" } } */