From patchwork Mon Sep 9 12:24:01 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?q?Martin_Li=C5=A1ka?= X-Patchwork-Id: 1159694 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-508612-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=suse.cz Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="YwO3NFBF"; 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 46RnQy6y6Gz9s7T for ; Mon, 9 Sep 2019 22:24:26 +1000 (AEST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :subject:from:to:cc:references:message-id:date:mime-version :in-reply-to:content-type; q=dns; s=default; b=PptRBaq/4RqNnDZP1 WqQzqpjLz5wH9DHXxATzgu7kTAteG9Mpqm4EAC8qD8wehqeiPoNoYXRJV3UHmHDn 9b+HPWQdroq7Jo60wounKNu1kqFe1vif0klayr6L5UEMFuVgS7Gynr+ejKeNtPQq e7wR85wDtkBTgrRJazS/34ItVs= 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 :subject:from:to:cc:references:message-id:date:mime-version :in-reply-to:content-type; s=default; bh=VnaGq11xbQfJIQ4DEegKmnF 8bVk=; b=YwO3NFBFfj2U6puQK3e8FE2hVE07JKAq5RtgiP57494QiNoBLGC5v/K aUW40+Cr36RhWevKWW+67vLVxW+jn921Z9rT8a2Gm4hUKG+ysLK+LssVOuwF6G38 EnakfZf/x7j5K0d0QTozn8eTcXpIX23rGsMwSU4z3VJkZbWzAlb0= Received: (qmail 41184 invoked by alias); 9 Sep 2019 12:24: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 40463 invoked by uid 89); 9 Sep 2019 12:24:07 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-17.9 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, SPF_PASS autolearn=ham version=3.3.1 spammy=name's, kids, bit_and X-HELO: mx1.suse.de Received: from mx2.suse.de (HELO mx1.suse.de) (195.135.220.15) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 09 Sep 2019 12:24:03 +0000 Received: from relay2.suse.de (unknown [195.135.220.254]) by mx1.suse.de (Postfix) with ESMTP id 911A6AF38; Mon, 9 Sep 2019 12:24:01 +0000 (UTC) Subject: [PATCH 3/5] Rewrite part of and_comparisons_1 into match.pd. From: =?utf-8?q?Martin_Li=C5=A1ka?= To: Richard Biener , Li Jia He Cc: Andrew Pinski , Jeff Law , GCC Patches , Segher Boessenkool , wschmidt@linux.ibm.com, Martin Liska References: <1561615913-22109-1-git-send-email-helijia@linux.ibm.com> <6fb28248-5134-cec5-5045-45253e4d2eb0@redhat.com> <6d333ccf-9905-e929-c2dc-fc611ff929f1@linux.ibm.com> <845bc280-7bd6-509b-3830-4ebde50f1b20@linux.ibm.com> Message-ID: Date: Mon, 9 Sep 2019 14:24:01 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.8.0 MIME-Version: 1.0 In-Reply-To: X-IsSubscribed: yes Hi. The patch is about transition of and_comparisons_1 matching into match.pd. Patch can bootstrap on x86_64-linux-gnu and survives regression tests. Ready to be installed? Thanks, Martin From 15045058d6caf84734ea949a297b6e31d9a8647c Mon Sep 17 00:00:00 2001 From: Martin Liska Date: Fri, 6 Sep 2019 12:34:49 +0200 Subject: [PATCH 3/5] Rewrite part of and_comparisons_1 into match.pd. gcc/ChangeLog: 2019-09-09 Martin Liska * genmatch.c (dt_node::append_simplify): Ignore warning for the same location. * gimple-fold.c (same_bool_result_p): Handle newly created SSA_NAMEs ar arguments. (and_comparisons_1): Add new argument gimple_stmt_iterator. (and_var_with_comparison): Likewise. (and_var_with_comparison_1): Likewise. (or_comparisons_1): Likewise. (or_var_with_comparison): Likewise. (or_var_with_comparison_1): Likewise. (maybe_fold_comparisons_from_match_pd): Handle creation of temporary SSA_NAMEs. Add new argument gimple_stmt_iterator. (maybe_fold_and_comparisons): Likewise. (maybe_fold_or_comparisons): Likewise. * gimple-fold.h (maybe_fold_and_comparisons): Likewise. (maybe_fold_or_comparisons): Likewise. * match.pd: Add rules for (X OP1 CST1) && (X OP2 CST2). * tree-if-conv.c (fold_or_predicates): Do not pass gimple_stmt_iterator. * tree-ssa-ifcombine.c (ifcombine_ifandif): Pass gimple_stmt_iterator. * tree-ssa-reassoc.c (eliminate_redundant_comparison): Do not pass gimple_stmt_iterator. (optimize_vec_cond_expr): Likewise. --- gcc/genmatch.c | 4 +- gcc/gimple-fold.c | 261 +++++++++++++-------------------------- gcc/gimple-fold.h | 6 +- gcc/match.pd | 68 ++++++++++ gcc/tree-if-conv.c | 2 +- gcc/tree-ssa-ifcombine.c | 5 +- gcc/tree-ssa-reassoc.c | 11 +- 7 files changed, 172 insertions(+), 185 deletions(-) diff --git a/gcc/genmatch.c b/gcc/genmatch.c index 2e7bf27eeda..b7194448a0f 100644 --- a/gcc/genmatch.c +++ b/gcc/genmatch.c @@ -1894,9 +1894,11 @@ dt_node * dt_node::append_simplify (simplify *s, unsigned pattern_no, dt_operand **indexes) { + dt_simplify *s2; dt_simplify *n = new dt_simplify (s, pattern_no, indexes); for (unsigned i = 0; i < kids.length (); ++i) - if (dt_simplify *s2 = dyn_cast (kids[i])) + if ((s2 = dyn_cast (kids[i])) + && s->match->location != s2->s->match->location) { warning_at (s->match->location, "duplicate pattern"); warning_at (s2->s->match->location, "previous pattern defined here"); diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c index 8a9eca13b87..f9971c004b7 100644 --- a/gcc/gimple-fold.c +++ b/gcc/gimple-fold.c @@ -5350,6 +5350,19 @@ same_bool_result_p (const_tree op1, const_tree op2) if (operand_equal_p (op1, op2, 0)) return true; + /* Function maybe_fold_comparisons_from_match_pd creates temporary + SSA_NAMEs. */ + if (TREE_CODE (op1) == SSA_NAME && TREE_CODE (op2) == SSA_NAME) + { + gimple *s = SSA_NAME_DEF_STMT (op2); + if (is_gimple_assign (s)) + return same_bool_comparison_p (op1, gimple_assign_rhs_code (s), + gimple_assign_rhs1 (s), + gimple_assign_rhs2 (s)); + else + return false; + } + /* Check the cases where at least one of the operands is a comparison. These are a bit smarter than operand_equal_p in that they apply some identifies on SSA_NAMEs. */ @@ -5372,22 +5385,28 @@ same_bool_result_p (const_tree op1, const_tree op2) static tree and_comparisons_1 (enum tree_code code1, tree op1a, tree op1b, - enum tree_code code2, tree op2a, tree op2b); + enum tree_code code2, tree op2a, tree op2b, + gimple_stmt_iterator *gsi); static tree and_var_with_comparison (tree var, bool invert, - enum tree_code code2, tree op2a, tree op2b); + enum tree_code code2, tree op2a, tree op2b, + gimple_stmt_iterator *gsi); static tree and_var_with_comparison_1 (gimple *stmt, - enum tree_code code2, tree op2a, tree op2b); + enum tree_code code2, tree op2a, tree op2b, + gimple_stmt_iterator *gsi); static tree or_comparisons_1 (enum tree_code code1, tree op1a, tree op1b, - enum tree_code code2, tree op2a, tree op2b); + enum tree_code code2, tree op2a, tree op2b, + gimple_stmt_iterator *gsi); static tree or_var_with_comparison (tree var, bool invert, - enum tree_code code2, tree op2a, tree op2b); + enum tree_code code2, tree op2a, tree op2b, + gimple_stmt_iterator *gsi); static tree or_var_with_comparison_1 (gimple *stmt, - enum tree_code code2, tree op2a, tree op2b); + enum tree_code code2, tree op2a, tree op2b, + gimple_stmt_iterator *gsi); /* Helper function for and_comparisons_1: try to simplify the AND of the ssa variable VAR with the comparison specified by (OP2A CODE2 OP2B). @@ -5396,7 +5415,8 @@ or_var_with_comparison_1 (gimple *stmt, static tree and_var_with_comparison (tree var, bool invert, - enum tree_code code2, tree op2a, tree op2b) + enum tree_code code2, tree op2a, tree op2b, + gimple_stmt_iterator *gsi) { tree t; gimple *stmt = SSA_NAME_DEF_STMT (var); @@ -5411,9 +5431,9 @@ and_var_with_comparison (tree var, bool invert, if (invert) t = or_var_with_comparison_1 (stmt, invert_tree_comparison (code2, false), - op2a, op2b); + op2a, op2b, gsi); else - t = and_var_with_comparison_1 (stmt, code2, op2a, op2b); + t = and_var_with_comparison_1 (stmt, code2, op2a, op2b, gsi); return canonicalize_bool (t, invert); } @@ -5423,7 +5443,8 @@ and_var_with_comparison (tree var, bool invert, static tree and_var_with_comparison_1 (gimple *stmt, - enum tree_code code2, tree op2a, tree op2b) + enum tree_code code2, tree op2a, tree op2b, + gimple_stmt_iterator *gsi) { tree var = gimple_assign_lhs (stmt); tree true_test_var = NULL_TREE; @@ -5456,9 +5477,7 @@ and_var_with_comparison_1 (gimple *stmt, tree t = and_comparisons_1 (innercode, gimple_assign_rhs1 (stmt), gimple_assign_rhs2 (stmt), - code2, - op2a, - op2b); + code2, op2a, op2b, gsi); if (t) return t; } @@ -5489,11 +5508,13 @@ and_var_with_comparison_1 (gimple *stmt, else if (inner1 == false_test_var) return (is_and ? boolean_false_node - : and_var_with_comparison (inner2, false, code2, op2a, op2b)); + : and_var_with_comparison (inner2, false, code2, op2a, op2b, + gsi)); else if (inner2 == false_test_var) return (is_and ? boolean_false_node - : and_var_with_comparison (inner1, false, code2, op2a, op2b)); + : and_var_with_comparison (inner1, false, code2, op2a, op2b, + gsi)); /* Next, redistribute/reassociate the AND across the inner tests. Compute the first partial result, (inner1 AND (op2a code op2b)) */ @@ -5503,7 +5524,7 @@ and_var_with_comparison_1 (gimple *stmt, && (t = maybe_fold_and_comparisons (gimple_assign_rhs_code (s), gimple_assign_rhs1 (s), gimple_assign_rhs2 (s), - code2, op2a, op2b))) + code2, op2a, op2b, gsi))) { /* Handle the AND case, where we are reassociating: (inner1 AND inner2) AND (op2a code2 op2b) @@ -5535,7 +5556,7 @@ and_var_with_comparison_1 (gimple *stmt, && (t = maybe_fold_and_comparisons (gimple_assign_rhs_code (s), gimple_assign_rhs1 (s), gimple_assign_rhs2 (s), - code2, op2a, op2b))) + code2, op2a, op2b, gsi))) { /* Handle the AND case, where we are reassociating: (inner1 AND inner2) AND (op2a code2 op2b) @@ -5589,7 +5610,8 @@ and_var_with_comparison_1 (gimple *stmt, static tree and_comparisons_1 (enum tree_code code1, tree op1a, tree op1b, - enum tree_code code2, tree op2a, tree op2b) + enum tree_code code2, tree op2a, tree op2b, + gimple_stmt_iterator *gsi) { tree truth_type = truth_type_for (TREE_TYPE (op1a)); @@ -5618,136 +5640,6 @@ and_comparisons_1 (enum tree_code code1, tree op1a, tree op1b, return t; } - /* If both comparisons are of the same value against constants, we might - be able to merge them. */ - if (operand_equal_p (op1a, op2a, 0) - && TREE_CODE (op1b) == INTEGER_CST - && TREE_CODE (op2b) == INTEGER_CST) - { - int cmp = tree_int_cst_compare (op1b, op2b); - - /* If we have (op1a == op1b), we should either be able to - return that or FALSE, depending on whether the constant op1b - also satisfies the other comparison against op2b. */ - if (code1 == EQ_EXPR) - { - bool done = true; - bool val; - switch (code2) - { - case EQ_EXPR: val = (cmp == 0); break; - case NE_EXPR: val = (cmp != 0); break; - case LT_EXPR: val = (cmp < 0); break; - case GT_EXPR: val = (cmp > 0); break; - case LE_EXPR: val = (cmp <= 0); break; - case GE_EXPR: val = (cmp >= 0); break; - default: done = false; - } - if (done) - { - if (val) - return fold_build2 (code1, boolean_type_node, op1a, op1b); - else - return boolean_false_node; - } - } - /* Likewise if the second comparison is an == comparison. */ - else if (code2 == EQ_EXPR) - { - bool done = true; - bool val; - switch (code1) - { - case EQ_EXPR: val = (cmp == 0); break; - case NE_EXPR: val = (cmp != 0); break; - case LT_EXPR: val = (cmp > 0); break; - case GT_EXPR: val = (cmp < 0); break; - case LE_EXPR: val = (cmp >= 0); break; - case GE_EXPR: val = (cmp <= 0); break; - default: done = false; - } - if (done) - { - if (val) - return fold_build2 (code2, boolean_type_node, op2a, op2b); - else - return boolean_false_node; - } - } - - /* Same business with inequality tests. */ - else if (code1 == NE_EXPR) - { - bool val; - switch (code2) - { - case EQ_EXPR: val = (cmp != 0); break; - case NE_EXPR: val = (cmp == 0); break; - case LT_EXPR: val = (cmp >= 0); break; - case GT_EXPR: val = (cmp <= 0); break; - case LE_EXPR: val = (cmp > 0); break; - case GE_EXPR: val = (cmp < 0); break; - default: - val = false; - } - if (val) - return fold_build2 (code2, boolean_type_node, op2a, op2b); - } - else if (code2 == NE_EXPR) - { - bool val; - switch (code1) - { - case EQ_EXPR: val = (cmp == 0); break; - case NE_EXPR: val = (cmp != 0); break; - case LT_EXPR: val = (cmp <= 0); break; - case GT_EXPR: val = (cmp >= 0); break; - case LE_EXPR: val = (cmp < 0); break; - case GE_EXPR: val = (cmp > 0); break; - default: - val = false; - } - if (val) - return fold_build2 (code1, boolean_type_node, op1a, op1b); - } - - /* Chose the more restrictive of two < or <= comparisons. */ - else if ((code1 == LT_EXPR || code1 == LE_EXPR) - && (code2 == LT_EXPR || code2 == LE_EXPR)) - { - if ((cmp < 0) || (cmp == 0 && code1 == LT_EXPR)) - return fold_build2 (code1, boolean_type_node, op1a, op1b); - else - return fold_build2 (code2, boolean_type_node, op2a, op2b); - } - - /* Likewise chose the more restrictive of two > or >= comparisons. */ - else if ((code1 == GT_EXPR || code1 == GE_EXPR) - && (code2 == GT_EXPR || code2 == GE_EXPR)) - { - if ((cmp > 0) || (cmp == 0 && code1 == GT_EXPR)) - return fold_build2 (code1, boolean_type_node, op1a, op1b); - else - return fold_build2 (code2, boolean_type_node, op2a, op2b); - } - - /* Check for singleton ranges. */ - else if (cmp == 0 - && ((code1 == LE_EXPR && code2 == GE_EXPR) - || (code1 == GE_EXPR && code2 == LE_EXPR))) - return fold_build2 (EQ_EXPR, boolean_type_node, op1a, op2b); - - /* Check for disjoint ranges. */ - else if (cmp <= 0 - && (code1 == LT_EXPR || code1 == LE_EXPR) - && (code2 == GT_EXPR || code2 == GE_EXPR)) - return boolean_false_node; - else if (cmp >= 0 - && (code1 == GT_EXPR || code1 == GE_EXPR) - && (code2 == LT_EXPR || code2 == LE_EXPR)) - return boolean_false_node; - } - /* Perhaps the first comparison is (NAME != 0) or (NAME == 1) where NAME's definition is a truth value. See if there are any simplifications that can be done against the NAME's definition. */ @@ -5762,7 +5654,7 @@ and_comparisons_1 (enum tree_code code1, tree op1a, tree op1b, { case GIMPLE_ASSIGN: /* Try to simplify by copy-propagating the definition. */ - return and_var_with_comparison (op1a, invert, code2, op2a, op2b); + return and_var_with_comparison (op1a, invert, code2, op2a, op2b, gsi); case GIMPLE_PHI: /* If every argument to the PHI produces the same result when @@ -5813,7 +5705,7 @@ and_comparisons_1 (enum tree_code code1, tree op1a, tree op1b, gimple_bb (stmt))) return NULL_TREE; temp = and_var_with_comparison (arg, invert, code2, - op2a, op2b); + op2a, op2b, gsi); if (!temp) return NULL_TREE; else if (!result) @@ -5845,7 +5737,7 @@ static tree maybe_fold_comparisons_from_match_pd (enum tree_code code, enum tree_code code1, tree op1a, tree op1b, enum tree_code code2, tree op2a, - tree op2b) + tree op2b, gimple_stmt_iterator *gsi) { tree type = TREE_TYPE (op1a); if (TREE_CODE (type) != VECTOR_TYPE) @@ -5912,6 +5804,18 @@ maybe_fold_comparisons_from_match_pd (enum tree_code code, enum tree_code code1, return NULL_TREE; } } + else if (op.code.is_tree_code () + && TREE_CODE_CLASS ((tree_code)op.code) == tcc_comparison) + { + if (gsi) + { + tree r = make_ssa_name (type); + gassign *assign = gimple_build_assign (r, (tree_code)op.code, + op.ops[0], op.ops[1]); + gsi_insert_before (gsi, assign, GSI_SAME_STMT); + return r; + } + } } return NULL_TREE; @@ -5926,16 +5830,18 @@ maybe_fold_comparisons_from_match_pd (enum tree_code code, enum tree_code code1, tree maybe_fold_and_comparisons (enum tree_code code1, tree op1a, tree op1b, - enum tree_code code2, tree op2a, tree op2b) + enum tree_code code2, tree op2a, tree op2b, + gimple_stmt_iterator *gsi) { - if (tree t = and_comparisons_1 (code1, op1a, op1b, code2, op2a, op2b)) + if (tree t = maybe_fold_comparisons_from_match_pd (BIT_AND_EXPR, code1, op1a, + op1b, code2, op2a, op2b, + gsi)) return t; - if (tree t = and_comparisons_1 (code2, op2a, op2b, code1, op1a, op1b)) + if (tree t = and_comparisons_1 (code1, op1a, op1b, code2, op2a, op2b, gsi)) return t; - if (tree t = maybe_fold_comparisons_from_match_pd (BIT_AND_EXPR, code1, op1a, - op1b, code2, op2a, op2b)) + if (tree t = and_comparisons_1 (code2, op2a, op2b, code1, op1a, op1b, gsi)) return t; return NULL_TREE; @@ -5948,7 +5854,8 @@ maybe_fold_and_comparisons (enum tree_code code1, tree op1a, tree op1b, static tree or_var_with_comparison (tree var, bool invert, - enum tree_code code2, tree op2a, tree op2b) + enum tree_code code2, tree op2a, tree op2b, + gimple_stmt_iterator *gsi) { tree t; gimple *stmt = SSA_NAME_DEF_STMT (var); @@ -5963,9 +5870,9 @@ or_var_with_comparison (tree var, bool invert, if (invert) t = and_var_with_comparison_1 (stmt, invert_tree_comparison (code2, false), - op2a, op2b); + op2a, op2b, gsi); else - t = or_var_with_comparison_1 (stmt, code2, op2a, op2b); + t = or_var_with_comparison_1 (stmt, code2, op2a, op2b, gsi); return canonicalize_bool (t, invert); } @@ -5975,7 +5882,8 @@ or_var_with_comparison (tree var, bool invert, static tree or_var_with_comparison_1 (gimple *stmt, - enum tree_code code2, tree op2a, tree op2b) + enum tree_code code2, tree op2a, tree op2b, + gimple_stmt_iterator *gsi) { tree var = gimple_assign_lhs (stmt); tree true_test_var = NULL_TREE; @@ -6008,9 +5916,7 @@ or_var_with_comparison_1 (gimple *stmt, tree t = or_comparisons_1 (innercode, gimple_assign_rhs1 (stmt), gimple_assign_rhs2 (stmt), - code2, - op2a, - op2b); + code2, op2a, op2b, gsi); if (t) return t; } @@ -6041,11 +5947,13 @@ or_var_with_comparison_1 (gimple *stmt, else if (inner1 == false_test_var) return (is_or ? boolean_true_node - : or_var_with_comparison (inner2, false, code2, op2a, op2b)); + : or_var_with_comparison (inner2, false, code2, op2a, op2b, + gsi)); else if (inner2 == false_test_var) return (is_or ? boolean_true_node - : or_var_with_comparison (inner1, false, code2, op2a, op2b)); + : or_var_with_comparison (inner1, false, code2, op2a, op2b, + gsi)); /* Next, redistribute/reassociate the OR across the inner tests. Compute the first partial result, (inner1 OR (op2a code op2b)) */ @@ -6055,7 +5963,7 @@ or_var_with_comparison_1 (gimple *stmt, && (t = maybe_fold_or_comparisons (gimple_assign_rhs_code (s), gimple_assign_rhs1 (s), gimple_assign_rhs2 (s), - code2, op2a, op2b))) + code2, op2a, op2b, gsi))) { /* Handle the OR case, where we are reassociating: (inner1 OR inner2) OR (op2a code2 op2b) @@ -6087,7 +5995,7 @@ or_var_with_comparison_1 (gimple *stmt, && (t = maybe_fold_or_comparisons (gimple_assign_rhs_code (s), gimple_assign_rhs1 (s), gimple_assign_rhs2 (s), - code2, op2a, op2b))) + code2, op2a, op2b, gsi))) { /* Handle the OR case, where we are reassociating: (inner1 OR inner2) OR (op2a code2 op2b) @@ -6142,7 +6050,8 @@ or_var_with_comparison_1 (gimple *stmt, static tree or_comparisons_1 (enum tree_code code1, tree op1a, tree op1b, - enum tree_code code2, tree op2a, tree op2b) + enum tree_code code2, tree op2a, tree op2b, + gimple_stmt_iterator *gsi) { tree truth_type = truth_type_for (TREE_TYPE (op1a)); @@ -6315,7 +6224,7 @@ or_comparisons_1 (enum tree_code code1, tree op1a, tree op1b, { case GIMPLE_ASSIGN: /* Try to simplify by copy-propagating the definition. */ - return or_var_with_comparison (op1a, invert, code2, op2a, op2b); + return or_var_with_comparison (op1a, invert, code2, op2a, op2b, gsi); case GIMPLE_PHI: /* If every argument to the PHI produces the same result when @@ -6366,7 +6275,7 @@ or_comparisons_1 (enum tree_code code1, tree op1a, tree op1b, gimple_bb (stmt))) return NULL_TREE; temp = or_var_with_comparison (arg, invert, code2, - op2a, op2b); + op2a, op2b, gsi); if (!temp) return NULL_TREE; else if (!result) @@ -6396,16 +6305,18 @@ or_comparisons_1 (enum tree_code code1, tree op1a, tree op1b, tree maybe_fold_or_comparisons (enum tree_code code1, tree op1a, tree op1b, - enum tree_code code2, tree op2a, tree op2b) + enum tree_code code2, tree op2a, tree op2b, + gimple_stmt_iterator *gsi) { - if (tree t = or_comparisons_1 (code1, op1a, op1b, code2, op2a, op2b)) + if (tree t = maybe_fold_comparisons_from_match_pd (BIT_IOR_EXPR, code1, op1a, + op1b, code2, op2a, op2b, + gsi)) return t; - if (tree t = or_comparisons_1 (code2, op2a, op2b, code1, op1a, op1b)) + if (tree t = or_comparisons_1 (code1, op1a, op1b, code2, op2a, op2b, gsi)) return t; - if (tree t = maybe_fold_comparisons_from_match_pd (BIT_IOR_EXPR, code1, op1a, - op1b, code2, op2a, op2b)) + if (tree t = or_comparisons_1 (code2, op2a, op2b, code1, op1a, op1b, gsi)) return t; return NULL_TREE; diff --git a/gcc/gimple-fold.h b/gcc/gimple-fold.h index 673d484ff52..3c2d19862a0 100644 --- a/gcc/gimple-fold.h +++ b/gcc/gimple-fold.h @@ -32,9 +32,11 @@ extern bool fold_stmt (gimple_stmt_iterator *); extern bool fold_stmt (gimple_stmt_iterator *, tree (*) (tree)); extern bool fold_stmt_inplace (gimple_stmt_iterator *); extern tree maybe_fold_and_comparisons (enum tree_code, tree, tree, - enum tree_code, tree, tree); + enum tree_code, tree, tree, + gimple_stmt_iterator *gsi); extern tree maybe_fold_or_comparisons (enum tree_code, tree, tree, - enum tree_code, tree, tree); + enum tree_code, tree, tree, + gimple_stmt_iterator *gsi); extern bool optimize_atomic_compare_exchange_p (gimple *); extern void fold_builtin_atomic_compare_exchange (gimple_stmt_iterator *); extern bool arith_overflowed_p (enum tree_code, const_tree, const_tree, diff --git a/gcc/match.pd b/gcc/match.pd index 28512d19b73..2c64c460fda 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -1949,6 +1949,74 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (if (eqne == NE_EXPR) { constant_boolean_node (true, type); }))))) +/* Convert (X == CST1) && (X OP2 CST2) to a known value + based on CST1 OP2 CST2. Similarly for (X != CST1). */ + +(for code1 (eq ne) + (for code2 (eq ne lt gt le ge) + (for and (truth_and bit_and) + (simplify + (and:c (code1 @0 INTEGER_CST@1) (code2 @0 INTEGER_CST@2)) + (with + { + int cmp = tree_int_cst_compare (@1, @2); + bool val; + switch (code2) + { + case EQ_EXPR: val = (cmp == 0); break; + case NE_EXPR: val = (cmp != 0); break; + case LT_EXPR: val = (cmp < 0); break; + case GT_EXPR: val = (cmp > 0); break; + case LE_EXPR: val = (cmp <= 0); break; + case GE_EXPR: val = (cmp >= 0); break; + default: gcc_unreachable (); + } + } + (switch + (if (code1 == EQ_EXPR && val) (code1 @0 @1)) + (if (code1 == EQ_EXPR && !val) { constant_boolean_node (false, type); }) + (if (code1 == NE_EXPR && !val) (code2 @0 @2)))))))) + +/* Convert (X OP1 CST1) && (X OP2 CST2). */ + +(for code1 (lt le gt ge) + (for code2 (lt le gt ge) + (for and (truth_and bit_and) + (simplify + (and (code1:c @0 INTEGER_CST@1) (code2:c @0 INTEGER_CST@2)) + (with + { + int cmp = tree_int_cst_compare (@1, @2); + } + (switch + /* Chose the more restrictive of two < or <= comparisons. */ + (if ((code1 == LT_EXPR || code1 == LE_EXPR) + && (code2 == LT_EXPR || code2 == LE_EXPR)) + (if ((cmp < 0) || (cmp == 0 && code1 == LT_EXPR)) + (code1 @0 @1) + (code2 @0 @2))) + /* Likewise chose the more restrictive of two > or >= comparisons. */ + (if ((code1 == GT_EXPR || code1 == GE_EXPR) + && (code2 == GT_EXPR || code2 == GE_EXPR)) + (if ((cmp > 0) || (cmp == 0 && code1 == GT_EXPR)) + (code1 @0 @1) + (code2 @0 @2))) + /* Check for singleton ranges. */ + (if (cmp == 0 + && ((code1 == LE_EXPR && code2 == GE_EXPR) + || (code1 == GE_EXPR && code2 == LE_EXPR))) + (eq @0 @1)) + /* Check for disjoint ranges. */ + (if (cmp <= 0 + && (code1 == LT_EXPR || code1 == LE_EXPR) + && (code2 == GT_EXPR || code2 == GE_EXPR)) + { constant_boolean_node (false, type); }) + (if (cmp >= 0 + && (code1 == GT_EXPR || code1 == GE_EXPR) + && (code2 == LT_EXPR || code2 == LE_EXPR)) + { constant_boolean_node (false, type); }) + )))))) + /* We can't reassociate at all for saturating types. */ (if (!TYPE_SATURATING (type)) diff --git a/gcc/tree-if-conv.c b/gcc/tree-if-conv.c index da67e39e03a..459cba2f752 100644 --- a/gcc/tree-if-conv.c +++ b/gcc/tree-if-conv.c @@ -437,7 +437,7 @@ fold_or_predicates (location_t loc, tree c1, tree c2) if (code1 != ERROR_MARK && code2 != ERROR_MARK) { tree t = maybe_fold_or_comparisons (code1, op1a, op1b, - code2, op2a, op2b); + code2, op2a, op2b, NULL); if (t) return t; } diff --git a/gcc/tree-ssa-ifcombine.c b/gcc/tree-ssa-ifcombine.c index f30816ace7b..92542817604 100644 --- a/gcc/tree-ssa-ifcombine.c +++ b/gcc/tree-ssa-ifcombine.c @@ -555,15 +555,16 @@ ifcombine_ifandif (basic_block inner_cond_bb, bool inner_inv, return false; /* Don't return false so fast, try maybe_fold_or_comparisons? */ + gimple_stmt_iterator gsi = gsi_for_stmt (inner_cond); if (!(t = maybe_fold_and_comparisons (inner_cond_code, gimple_cond_lhs (inner_cond), gimple_cond_rhs (inner_cond), outer_cond_code, gimple_cond_lhs (outer_cond), - gimple_cond_rhs (outer_cond)))) + gimple_cond_rhs (outer_cond), + &gsi))) { tree t1, t2; - gimple_stmt_iterator gsi; bool logical_op_non_short_circuit = LOGICAL_OP_NON_SHORT_CIRCUIT; if (PARAM_VALUE (PARAM_LOGICAL_OP_NON_SHORT_CIRCUIT) != -1) logical_op_non_short_circuit diff --git a/gcc/tree-ssa-reassoc.c b/gcc/tree-ssa-reassoc.c index df76e66bccf..ae0752bb371 100644 --- a/gcc/tree-ssa-reassoc.c +++ b/gcc/tree-ssa-reassoc.c @@ -2091,11 +2091,13 @@ eliminate_redundant_comparison (enum tree_code opcode, if (opcode == BIT_IOR_EXPR) t = maybe_fold_or_comparisons (lcode, op1, op2, rcode, gimple_assign_rhs1 (def2), - gimple_assign_rhs2 (def2)); + gimple_assign_rhs2 (def2), + NULL); else t = maybe_fold_and_comparisons (lcode, op1, op2, rcode, gimple_assign_rhs1 (def2), - gimple_assign_rhs2 (def2)); + gimple_assign_rhs2 (def2), + NULL); if (!t) continue; @@ -3834,9 +3836,10 @@ optimize_vec_cond_expr (tree_code opcode, vec *ops) tree comb; if (opcode == BIT_AND_EXPR) - comb = maybe_fold_and_comparisons (cmp0, x0, y0, cmp1, x1, y1); + comb = maybe_fold_and_comparisons (cmp0, x0, y0, cmp1, x1, y1, + NULL); else if (opcode == BIT_IOR_EXPR) - comb = maybe_fold_or_comparisons (cmp0, x0, y0, cmp1, x1, y1); + comb = maybe_fold_or_comparisons (cmp0, x0, y0, cmp1, x1, y1, NULL); else gcc_unreachable (); if (comb == NULL) -- 2.23.0