From patchwork Mon Oct 17 13:25:40 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Andrew MacLeod X-Patchwork-Id: 1690947 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org 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=sourceware.org; envelope-from=gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.a=rsa-sha256 header.s=default header.b=sXJ2e9Iu; dkim-atps=neutral Received: from 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 (P-384) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4Mrd7F1D6Nz23kK for ; Tue, 18 Oct 2022 00:26:33 +1100 (AEDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 176603857B81 for ; Mon, 17 Oct 2022 13:26:31 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 176603857B81 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1666013191; bh=J3aw6tEBT67xZzE6ITrNaWZIxhP60JNHWYs/r4WBgKA=; h=Date:To:Subject:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:From; b=sXJ2e9Iu8liX/mwA8kMCHwkWwGHyMwLMAx1MzUW2zWzj3Xya1SBx+ZWsx8NPC2cvW D2dgasmwSM4RaBspNZWOuZVR0RRF2e19W7VErbN/w2/OeKW0cUgRpOHSFp1wDTVET8 5xlCiKAeF/IovK+ANiRjJ9nQcEi6svOhB9qd3v5A= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by sourceware.org (Postfix) with ESMTPS id 81727385828B for ; Mon, 17 Oct 2022 13:25:46 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 81727385828B Received: from mail-io1-f72.google.com (mail-io1-f72.google.com [209.85.166.72]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_128_GCM_SHA256) id us-mta-255-EOEFu1CUPLieDimy53wFpA-1; Mon, 17 Oct 2022 09:25:44 -0400 X-MC-Unique: EOEFu1CUPLieDimy53wFpA-1 Received: by mail-io1-f72.google.com with SMTP id w16-20020a6b4a10000000b006a5454c789eso7023304iob.20 for ; Mon, 17 Oct 2022 06:25:44 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=subject:from:cc:to:content-language:user-agent:mime-version:date :message-id:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=z8DfyJn8J089leVP591hkff6DvxkB1UyCsaSGCiT6zg=; b=CbECYv68O+PnYNw+jHXWPvq7swnkx8qebIQoBTO+QxOCwOoulfbNgNtQXXodbpTLx+ 93j7046ibCoJE3c68UPjNp26T9yudc3iNoQUlgeDVd6OmKQGbZ/9qV+tryKj/8w2tlBV P2J5QJmwuTeLqfdJd6CqTcjbBfADaqXxzzK6qWSL9doBJ9yWyp1pPzi86Fi1dErJic16 SyYRtEcTVwVDAdvIfNfk2IUNnUkDkvf1hOT3kIl8FamSvu4T+46HGJ3zXq+Nx05OJKSw ZwHYuiysGHDMNUAOsXA60dSq010OICUiXH050f6Ito50siKWukXx1+B+7s8NbV6+s0e8 hWxA== X-Gm-Message-State: ACrzQf0NlvzXLMsbeiJC78QKXXIu48r21z2xhWVYBOwucnN706iLhVBd uyhlCTE4bFYQ1u/N0BROCYLlrQLtMalOeQnoxQq8igsivGSVu8EqM4qYzV1COPnH1cmplxjfLZe Gb18fGcJHOng4Q8Uh2CKvCCqzv5zK4lzOG6clagWeX6qBVwMg++QAiSxMkAn2Z+ZtOFnpNA== X-Received: by 2002:a05:6e02:154a:b0:2fa:99fc:6c7e with SMTP id j10-20020a056e02154a00b002fa99fc6c7emr4592600ilu.285.1666013143328; Mon, 17 Oct 2022 06:25:43 -0700 (PDT) X-Google-Smtp-Source: AMsMyM6sqRg5faE9LvhN4SrihQ/jHeGua9hncYj9TMnOZrMiiJ2TwOS0fDirX98adR0fSeZsrESy4A== X-Received: by 2002:a05:6e02:154a:b0:2fa:99fc:6c7e with SMTP id j10-20020a056e02154a00b002fa99fc6c7emr4592588ilu.285.1666013142968; Mon, 17 Oct 2022 06:25:42 -0700 (PDT) Received: from ?IPV6:2607:fea8:a263:f600::50d4? ([2607:fea8:a263:f600::50d4]) by smtp.gmail.com with ESMTPSA id ce15-20020a0566381a8f00b0035b496b0a7fsm4414745jab.36.2022.10.17.06.25.41 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Mon, 17 Oct 2022 06:25:42 -0700 (PDT) Message-ID: <0f993407-dc43-c120-8bad-4b6c5b7a1aad@redhat.com> Date: Mon, 17 Oct 2022 09:25:40 -0400 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Thunderbird/102.2.1 To: gcc-patches Subject: [COMMITTED] Add relation_trio class for range-ops. X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Language: en-US X-Spam-Status: No, score=-12.0 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2, SPF_HELO_NONE, SPF_NONE, TXREP, T_FILL_THIS_FORM_FRAUD_PHISH, T_FILL_THIS_FORM_SHORT 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.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Andrew MacLeod via Gcc-patches From: Andrew MacLeod Reply-To: Andrew MacLeod Errors-To: gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org Sender: "Gcc-patches" When I first added relations to range_ops, I struggled with obfuscating the API too much by adding all of the 3 possible relations.  For simplicity, it seemed like only one was ever relevant, so elected to add one relation, and make it always the relation between the 2 known operands. fold_range()    - relation passed  op1 REL op2 op1_range()    - relation passed  lhs REL op2 op2_range()    - relation passed  lhs REL op1 With some of the floating point enhancements, we've tripped over cases where its useful to know one or more of the relations. This patch provides a new class in value_relation.h called "relation_trio" which packages up 3 relations into a single unsigned value, and allows them to be extracted by request.  I have changed all 3 of the primary range-ops interface routines mentioned above to take a relation_trio object by value rather than a relation kind, and then each range_op routines explicitly asks for the relation it is looking for. I have also audited the range-op and range-op-float routines to make sure that when op2_range invokes op1_range that we do the appropriate relation swapping. There is virtually no performance impact by this, and it is now clear when looking at one of the range-ops routines exactly what relation it is using.   This seems much less confusing. I have also adjusted the compute_operand[12]_range routines in GORI to also provide a second relation when appropriate. Bootstrapped on  x86_64-pc-linux-gnu with no regressions. Pushed. Andrew From b565ac19264a5827162d28537bccc8531c25e817 Mon Sep 17 00:00:00 2001 From: Andrew MacLeod Date: Thu, 13 Oct 2022 18:03:58 -0400 Subject: [PATCH 3/4] Add relation_trio class for range-ops. There are 3 possible relations range-ops might care about, but only the one most likely to be needed is supplied. This patch provides a new class relation_trio which allows 3 relations to be passed in a single word. fold_range (), op1_range (), and op2_range () are adjusted to take a relation_trio class instead of a relation_kind, then the routine can extract which relation it wants to work with. * gimple-range-fold.cc (fold_using_range::range_of_range_op): Provide relation_trio class. * gimple-range-gori.cc (gori_compute::refine_using_relation): Provide relation_trio class. (gori_compute::refine_using_relation): Ditto. (gori_compute::compute_operand1_range): Provide lhs_op2 and op1_op2 relations via relation_trio class. (gori_compute::compute_operand2_range): Ditto. * gimple-range-op.cc (gimple_range_op_handler::calc_op1): Use relation_trio instead of relation_kind. (gimple_range_op_handler::calc_op2): Ditto. (*::fold_range): Ditto. * gimple-range-op.h (gimple_range_op::calc_op1): Adjust prototypes. (gimple_range_op::calc_op2): Adjust prototypes. * range-op-float.cc (*::fold_range): Use relation_trio instead of relation_kind. (*::op1_range): Ditto. (*::op2_range): Ditto. * range-op.cc (*::fold_range): Use relation_trio instead of relation_kind. (*::op1_range): Ditto. (*::op2_range): Ditto. * range-op.h (class range_operator): Adjust prototypes. (class range_operator_float): Ditto. (class range_op_handler): Adjust prototypes. (relop_early_resolve): Pickup op1_op2 relation from relation_trio. * value-relation.cc (VREL_LAST): Adjust use to be one past the end of the enum. (relation_oracle::validate_relation): Use relation_trio in call to fold_range. * value-relation.h (enum relation_kind_t): Add VREL_LAST as final element. (class relation_trio): New. (TRIO_VARYING, TRIO_SHIFT, TRIO_MASK): New. --- gcc/gimple-range-fold.cc | 5 +- gcc/gimple-range-gori.cc | 43 ++++--- gcc/gimple-range-op.cc | 40 +++--- gcc/gimple-range-op.h | 4 +- gcc/range-op-float.cc | 170 +++++++++++++------------ gcc/range-op.cc | 267 ++++++++++++++++++++------------------- gcc/range-op.h | 29 +++-- gcc/value-relation.cc | 19 ++- gcc/value-relation.h | 119 +++++++++++++++-- 9 files changed, 405 insertions(+), 291 deletions(-) diff --git a/gcc/gimple-range-fold.cc b/gcc/gimple-range-fold.cc index c381ef94087..f91923782dc 100644 --- a/gcc/gimple-range-fold.cc +++ b/gcc/gimple-range-fold.cc @@ -578,7 +578,8 @@ fold_using_range::range_of_range_op (vrange &r, fputc ('\n', dump_file); } // Fold range, and register any dependency if available. - if (!handler.fold_range (r, type, range1, range2, rel)) + if (!handler.fold_range (r, type, range1, range2, + relation_trio::op1_op2 (rel))) r.set_varying (type); if (irange::supports_p (type)) relation_fold_and_or (as_a (r), s, src); @@ -597,7 +598,7 @@ fold_using_range::range_of_range_op (vrange &r, } if (gimple_range_ssa_p (op2)) { - rel= handler.lhs_op2_relation (r, range1, range2, rel); + rel = handler.lhs_op2_relation (r, range1, range2, rel); if (rel != VREL_VARYING) src.register_relation (s, rel, lhs, op2); } diff --git a/gcc/gimple-range-gori.cc b/gcc/gimple-range-gori.cc index 5ff067cadb5..610a5295e62 100644 --- a/gcc/gimple-range-gori.cc +++ b/gcc/gimple-range-gori.cc @@ -991,7 +991,7 @@ gori_compute::refine_using_relation (tree op1, vrange &op1_range, Value_Range new_result (type); if (!op_handler.op1_range (new_result, type, op1_def_p ? op1_range : op2_range, - other_op, k)) + other_op, relation_trio::lhs_op2 (k))) return false; if (op1_def_p) { @@ -1023,7 +1023,7 @@ gori_compute::refine_using_relation (tree op1, vrange &op1_range, Value_Range new_result (type); if (!op_handler.op2_range (new_result, type, op1_def_p ? op1_range : op2_range, - other_op, k)) + other_op, relation_trio::lhs_op1 (k))) return false; if (op1_def_p) { @@ -1074,6 +1074,7 @@ gori_compute::compute_operand1_range (vrange &r, { src.get_operand (op2_range, op2); relation_kind k = VREL_VARYING; + relation_kind op_op = (op1 == op2) ? VREL_EQ : VREL_VARYING; if (rel) { if (lhs_name == rel->op1 () && op1 == rel->op2 ()) @@ -1081,13 +1082,18 @@ gori_compute::compute_operand1_range (vrange &r, else if (lhs_name == rel->op2 () && op1 == rel->op1 ()) k = relation_swap (rel->kind ()); else if (op1 == rel->op1 () && op2 == rel->op2 ()) - refine_using_relation (op1, op1_range, op2, op2_range, src, - rel->kind ()); + { + op_op = rel->kind (); + refine_using_relation (op1, op1_range, op2, op2_range, src, op_op); + } else if (op1 == rel->op2 () && op2 == rel->op1 ()) - refine_using_relation (op1, op1_range, op2, op2_range, src, - relation_swap (rel->kind ())); + { + op_op = relation_swap (rel->kind ()); + refine_using_relation (op1, op1_range, op2, op2_range, src, op_op); + } } - if (!handler.calc_op1 (tmp, lhs, op2_range, k)) + if (!handler.calc_op1 (tmp, lhs, op2_range, relation_trio (VREL_VARYING, + k, op_op))) return false; } else @@ -1095,7 +1101,7 @@ gori_compute::compute_operand1_range (vrange &r, // We pass op1_range to the unary operation. Nomally it's a // hidden range_for_type parameter, but sometimes having the // actual range can result in better information. - if (!handler.calc_op1 (tmp, lhs, op1_range, VREL_VARYING)) + if (!handler.calc_op1 (tmp, lhs, op1_range, TRIO_VARYING)) return false; } @@ -1167,23 +1173,28 @@ gori_compute::compute_operand2_range (vrange &r, src.get_operand (op1_range, op1); src.get_operand (op2_range, op2); relation_kind k = VREL_VARYING; + relation_kind op_op = (op1 == op2) ? VREL_EQ : VREL_VARYING; if (rel) { if (lhs_name == rel->op1 () && op2 == rel->op2 ()) - k = rel->kind (); + k = rel->kind (); else if (lhs_name == rel->op2 () && op2 == rel->op1 ()) - k = relation_swap (rel->kind ()); + k = relation_swap (rel->kind ()); else if (op1 == rel->op1 () && op2 == rel->op2 ()) - refine_using_relation (op1, op1_range, op2, op2_range, src, - rel->kind ()); + { + op_op = rel->kind (); + refine_using_relation (op1, op1_range, op2, op2_range, src, op_op); + } else if (op1 == rel->op2 () && op2 == rel->op1 ()) - refine_using_relation (op1, op1_range, op2, op2_range, src, - relation_swap (rel->kind ())); + { + op_op = relation_swap (rel->kind ()); + refine_using_relation (op1, op1_range, op2, op2_range, src, op_op); + } } - // Intersect with range for op2 based on lhs and op1. - if (!handler.calc_op2 (tmp, lhs, op1_range, k)) + if (!handler.calc_op2 (tmp, lhs, op1_range, relation_trio (k, VREL_VARYING, + op_op))) return false; unsigned idx; diff --git a/gcc/gimple-range-op.cc b/gcc/gimple-range-op.cc index 2662319aadc..7764166d5fb 100644 --- a/gcc/gimple-range-op.cc +++ b/gcc/gimple-range-op.cc @@ -202,7 +202,7 @@ gimple_range_op_handler::calc_op1 (vrange &r, const vrange &lhs_range) bool gimple_range_op_handler::calc_op1 (vrange &r, const vrange &lhs_range, - const vrange &op2_range, relation_kind k) + const vrange &op2_range, relation_trio k) { // Give up on empty ranges. if (lhs_range.undefined_p ()) @@ -237,7 +237,7 @@ gimple_range_op_handler::calc_op1 (vrange &r, const vrange &lhs_range, bool gimple_range_op_handler::calc_op2 (vrange &r, const vrange &lhs_range, - const vrange &op1_range, relation_kind k) + const vrange &op1_range, relation_trio k) { // Give up on empty ranges. if (lhs_range.undefined_p ()) @@ -263,7 +263,7 @@ class cfn_constant_float_p : public range_operator_float public: using range_operator_float::fold_range; virtual bool fold_range (irange &r, tree type, const frange &lh, - const irange &, relation_kind) const + const irange &, relation_trio) const { if (lh.singleton_p ()) { @@ -285,7 +285,7 @@ class cfn_constant_p : public range_operator public: using range_operator::fold_range; virtual bool fold_range (irange &r, tree type, const irange &lh, - const irange &, relation_kind) const + const irange &, relation_trio) const { if (lh.singleton_p ()) { @@ -308,7 +308,7 @@ public: using range_operator_float::fold_range; using range_operator_float::op1_range; virtual bool fold_range (irange &r, tree type, const frange &lh, - const irange &, relation_kind) const override + const irange &, relation_trio) const override { bool signbit; if (lh.signbit_p (signbit)) @@ -322,7 +322,7 @@ public: return false; } virtual bool op1_range (frange &r, tree type, const irange &lhs, - const frange &, relation_kind) const override + const frange &, relation_trio) const override { if (lhs.zero_p ()) { @@ -348,7 +348,7 @@ class cfn_copysign : public range_operator_float public: using range_operator_float::fold_range; virtual bool fold_range (frange &r, tree type, const frange &lh, - const frange &rh, relation_kind) const override + const frange &rh, relation_trio) const override { frange neg; range_op_handler abs_op (ABS_EXPR, type); @@ -381,7 +381,7 @@ public: using range_operator::fold_range; cfn_toupper_tolower (bool toupper) { m_toupper = toupper; } virtual bool fold_range (irange &r, tree type, const irange &lh, - const irange &, relation_kind) const; + const irange &, relation_trio) const; private: bool get_letter_range (tree type, irange &lowers, irange &uppers) const; bool m_toupper; @@ -412,7 +412,7 @@ cfn_toupper_tolower::get_letter_range (tree type, irange &lowers, bool cfn_toupper_tolower::fold_range (irange &r, tree type, const irange &lh, - const irange &, relation_kind) const + const irange &, relation_trio) const { int_range<3> lowers; int_range<3> uppers; @@ -445,7 +445,7 @@ class cfn_ffs : public range_operator public: using range_operator::fold_range; virtual bool fold_range (irange &r, tree type, const irange &lh, - const irange &, relation_kind) const + const irange &, relation_trio) const { if (lh.undefined_p ()) return false; @@ -472,7 +472,7 @@ class cfn_popcount : public cfn_ffs public: using range_operator::fold_range; virtual bool fold_range (irange &r, tree type, const irange &lh, - const irange &rh, relation_kind rel) const + const irange &rh, relation_trio rel) const { if (lh.undefined_p ()) return false; @@ -502,14 +502,14 @@ public: cfn_clz (bool internal) { m_gimple_call_internal_p = internal; } using range_operator::fold_range; virtual bool fold_range (irange &r, tree type, const irange &lh, - const irange &, relation_kind) const; + const irange &, relation_trio) const; private: bool m_gimple_call_internal_p; } op_cfn_clz (false), op_cfn_clz_internal (true); bool cfn_clz::fold_range (irange &r, tree type, const irange &lh, - const irange &, relation_kind) const + const irange &, relation_trio) const { // __builtin_c[lt]z* return [0, prec-1], except when the // argument is 0, but that is undefined behavior. @@ -577,14 +577,14 @@ public: cfn_ctz (bool internal) { m_gimple_call_internal_p = internal; } using range_operator::fold_range; virtual bool fold_range (irange &r, tree type, const irange &lh, - const irange &, relation_kind) const; + const irange &, relation_trio) const; private: bool m_gimple_call_internal_p; } op_cfn_ctz (false), op_cfn_ctz_internal (true); bool cfn_ctz::fold_range (irange &r, tree type, const irange &lh, - const irange &, relation_kind) const + const irange &, relation_trio) const { if (lh.undefined_p ()) return false; @@ -647,7 +647,7 @@ class cfn_clrsb : public range_operator public: using range_operator::fold_range; virtual bool fold_range (irange &r, tree type, const irange &lh, - const irange &, relation_kind) const + const irange &, relation_trio) const { if (lh.undefined_p ()) return false; @@ -665,7 +665,7 @@ public: cfn_ubsan (enum tree_code code) { m_code = code; } using range_operator::fold_range; virtual bool fold_range (irange &r, tree type, const irange &lh, - const irange &rh, relation_kind rel) const + const irange &rh, relation_trio rel) const { range_op_handler handler (m_code, type); gcc_checking_assert (handler); @@ -699,7 +699,7 @@ class cfn_strlen : public range_operator public: using range_operator::fold_range; virtual bool fold_range (irange &r, tree type, const irange &, - const irange &, relation_kind) const + const irange &, relation_trio) const { tree max = vrp_val_max (ptrdiff_type_node); wide_int wmax @@ -724,7 +724,7 @@ public: cfn_goacc_dim (bool is_pos) { m_is_pos = is_pos; } using range_operator::fold_range; virtual bool fold_range (irange &r, tree type, const irange &lh, - const irange &, relation_kind) const + const irange &, relation_trio) const { tree axis_tree; if (!lh.singleton_p (&axis_tree)) @@ -751,7 +751,7 @@ class cfn_parity : public range_operator public: using range_operator::fold_range; virtual bool fold_range (irange &r, tree type, const irange &, - const irange &, relation_kind) const + const irange &, relation_trio) const { r.set (build_zero_cst (type), build_one_cst (type)); return true; diff --git a/gcc/gimple-range-op.h b/gcc/gimple-range-op.h index 3a555f29a65..be1305c58aa 100644 --- a/gcc/gimple-range-op.h +++ b/gcc/gimple-range-op.h @@ -36,9 +36,9 @@ public: tree operand2 () const { gcc_checking_assert (m_valid); return m_op2; } bool calc_op1 (vrange &r, const vrange &lhs_range); bool calc_op1 (vrange &r, const vrange &lhs_range, const vrange &op2_range, - relation_kind k = VREL_VARYING); + relation_trio = TRIO_VARYING); bool calc_op2 (vrange &r, const vrange &lhs_range, const vrange &op1_range, - relation_kind k = VREL_VARYING); + relation_trio = TRIO_VARYING); private: void maybe_builtin_call (); gimple *m_stmt; diff --git a/gcc/range-op-float.cc b/gcc/range-op-float.cc index 6cf2180ce59..e7334794b0d 100644 --- a/gcc/range-op-float.cc +++ b/gcc/range-op-float.cc @@ -53,7 +53,7 @@ range_operator_float::fold_range (frange &r ATTRIBUTE_UNUSED, tree type ATTRIBUTE_UNUSED, const frange &lh ATTRIBUTE_UNUSED, const frange &rh ATTRIBUTE_UNUSED, - relation_kind rel ATTRIBUTE_UNUSED) const + relation_trio) const { return false; } @@ -63,7 +63,7 @@ range_operator_float::fold_range (irange &r ATTRIBUTE_UNUSED, tree type ATTRIBUTE_UNUSED, const frange &lh ATTRIBUTE_UNUSED, const irange &rh ATTRIBUTE_UNUSED, - relation_kind rel ATTRIBUTE_UNUSED) const + relation_trio) const { return false; } @@ -73,7 +73,7 @@ range_operator_float::fold_range (irange &r ATTRIBUTE_UNUSED, tree type ATTRIBUTE_UNUSED, const frange &lh ATTRIBUTE_UNUSED, const frange &rh ATTRIBUTE_UNUSED, - relation_kind rel ATTRIBUTE_UNUSED) const + relation_trio) const { return false; } @@ -83,7 +83,7 @@ range_operator_float::op1_range (frange &r ATTRIBUTE_UNUSED, tree type ATTRIBUTE_UNUSED, const frange &lhs ATTRIBUTE_UNUSED, const frange &op2 ATTRIBUTE_UNUSED, - relation_kind rel ATTRIBUTE_UNUSED) const + relation_trio) const { return false; } @@ -93,7 +93,7 @@ range_operator_float::op1_range (frange &r ATTRIBUTE_UNUSED, tree type ATTRIBUTE_UNUSED, const irange &lhs ATTRIBUTE_UNUSED, const frange &op2 ATTRIBUTE_UNUSED, - relation_kind rel ATTRIBUTE_UNUSED) const + relation_trio) const { return false; } @@ -103,7 +103,7 @@ range_operator_float::op2_range (frange &r ATTRIBUTE_UNUSED, tree type ATTRIBUTE_UNUSED, const frange &lhs ATTRIBUTE_UNUSED, const frange &op1 ATTRIBUTE_UNUSED, - relation_kind rel ATTRIBUTE_UNUSED) const + relation_trio) const { return false; } @@ -113,7 +113,7 @@ range_operator_float::op2_range (frange &r ATTRIBUTE_UNUSED, tree type ATTRIBUTE_UNUSED, const irange &lhs ATTRIBUTE_UNUSED, const frange &op1 ATTRIBUTE_UNUSED, - relation_kind rel ATTRIBUTE_UNUSED) const + relation_trio) const { return false; } @@ -188,7 +188,7 @@ finite_operands_p (const frange &op1, const frange &op2) inline bool frelop_early_resolve (irange &r, tree type, const frange &op1, const frange &op2, - relation_kind rel, relation_kind my_rel) + relation_trio rel, relation_kind my_rel) { // If either operand is undefined, return VARYING. if (empty_range_varying (r, type, op1, op2)) @@ -324,14 +324,14 @@ class foperator_identity : public range_operator_float public: bool fold_range (frange &r, tree type ATTRIBUTE_UNUSED, const frange &op1, const frange &op2 ATTRIBUTE_UNUSED, - relation_kind = VREL_VARYING) const final override + relation_trio = TRIO_VARYING) const final override { r = op1; return true; } bool op1_range (frange &r, tree type ATTRIBUTE_UNUSED, const frange &lhs, const frange &op2 ATTRIBUTE_UNUSED, - relation_kind = VREL_VARYING) const final override + relation_trio = TRIO_VARYING) const final override { r = lhs; return true; @@ -348,26 +348,26 @@ class foperator_equal : public range_operator_float public: bool fold_range (irange &r, tree type, const frange &op1, const frange &op2, - relation_kind = VREL_VARYING) const final override; + relation_trio = TRIO_VARYING) const final override; relation_kind op1_op2_relation (const irange &lhs) const final override { return equal_op1_op2_relation (lhs); } bool op1_range (frange &r, tree type, const irange &lhs, const frange &op2, - relation_kind = VREL_VARYING) const final override; + relation_trio = TRIO_VARYING) const final override; bool op2_range (frange &r, tree type, const irange &lhs, const frange &op1, - relation_kind rel = VREL_VARYING) const final override + relation_trio rel = TRIO_VARYING) const final override { - return op1_range (r, type, lhs, op1, rel); + return op1_range (r, type, lhs, op1, rel.swap_op1_op2 ()); } } fop_equal; bool foperator_equal::fold_range (irange &r, tree type, const frange &op1, const frange &op2, - relation_kind rel) const + relation_trio rel) const { if (frelop_early_resolve (r, type, op1, op2, rel, VREL_EQ)) return true; @@ -403,8 +403,9 @@ bool foperator_equal::op1_range (frange &r, tree type, const irange &lhs, const frange &op2, - relation_kind rel) const + relation_trio trio) const { + relation_kind rel = trio.op1_op2 (); switch (get_bool_state (r, lhs, type)) { case BRS_TRUE: @@ -455,20 +456,20 @@ class foperator_not_equal : public range_operator_float public: bool fold_range (irange &r, tree type, const frange &op1, const frange &op2, - relation_kind rel = VREL_VARYING) const final override; + relation_trio rel = TRIO_VARYING) const final override; relation_kind op1_op2_relation (const irange &lhs) const final override { return not_equal_op1_op2_relation (lhs); } bool op1_range (frange &r, tree type, const irange &lhs, const frange &op2, - relation_kind = VREL_VARYING) const final override; + relation_trio = TRIO_VARYING) const final override; } fop_not_equal; bool foperator_not_equal::fold_range (irange &r, tree type, const frange &op1, const frange &op2, - relation_kind rel) const + relation_trio rel) const { if (frelop_early_resolve (r, type, op1, op2, rel, VREL_NE)) return true; @@ -505,8 +506,9 @@ bool foperator_not_equal::op1_range (frange &r, tree type, const irange &lhs, const frange &op2, - relation_kind rel) const + relation_trio trio) const { + relation_kind rel = trio.op1_op2 (); switch (get_bool_state (r, lhs, type)) { case BRS_TRUE: @@ -557,23 +559,23 @@ class foperator_lt : public range_operator_float public: bool fold_range (irange &r, tree type, const frange &op1, const frange &op2, - relation_kind = VREL_VARYING) const final override; + relation_trio = TRIO_VARYING) const final override; relation_kind op1_op2_relation (const irange &lhs) const final override { return lt_op1_op2_relation (lhs); } bool op1_range (frange &r, tree type, const irange &lhs, const frange &op2, - relation_kind = VREL_VARYING) const final override; + relation_trio = TRIO_VARYING) const final override; bool op2_range (frange &r, tree type, const irange &lhs, const frange &op1, - relation_kind = VREL_VARYING) const final override; + relation_trio = TRIO_VARYING) const final override; } fop_lt; bool foperator_lt::fold_range (irange &r, tree type, const frange &op1, const frange &op2, - relation_kind rel) const + relation_trio rel) const { if (frelop_early_resolve (r, type, op1, op2, rel, VREL_LT)) return true; @@ -599,7 +601,7 @@ foperator_lt::op1_range (frange &r, tree type, const irange &lhs, const frange &op2, - relation_kind) const + relation_trio) const { switch (get_bool_state (r, lhs, type)) { @@ -634,7 +636,7 @@ foperator_lt::op2_range (frange &r, tree type, const irange &lhs, const frange &op1, - relation_kind) const + relation_trio) const { switch (get_bool_state (r, lhs, type)) { @@ -673,23 +675,23 @@ class foperator_le : public range_operator_float public: bool fold_range (irange &r, tree type, const frange &op1, const frange &op2, - relation_kind rel = VREL_VARYING) const final override; + relation_trio rel = TRIO_VARYING) const final override; relation_kind op1_op2_relation (const irange &lhs) const final override { return le_op1_op2_relation (lhs); } bool op1_range (frange &r, tree type, const irange &lhs, const frange &op2, - relation_kind rel = VREL_VARYING) const final override; + relation_trio rel = TRIO_VARYING) const final override; bool op2_range (frange &r, tree type, const irange &lhs, const frange &op1, - relation_kind rel = VREL_VARYING) const final override; + relation_trio rel = TRIO_VARYING) const final override; } fop_le; bool foperator_le::fold_range (irange &r, tree type, const frange &op1, const frange &op2, - relation_kind rel) const + relation_trio rel) const { if (frelop_early_resolve (r, type, op1, op2, rel, VREL_LE)) return true; @@ -715,7 +717,7 @@ foperator_le::op1_range (frange &r, tree type, const irange &lhs, const frange &op2, - relation_kind) const + relation_trio) const { switch (get_bool_state (r, lhs, type)) { @@ -746,7 +748,7 @@ foperator_le::op2_range (frange &r, tree type, const irange &lhs, const frange &op1, - relation_kind) const + relation_trio) const { switch (get_bool_state (r, lhs, type)) { @@ -781,23 +783,23 @@ class foperator_gt : public range_operator_float public: bool fold_range (irange &r, tree type, const frange &op1, const frange &op2, - relation_kind = VREL_VARYING) const final override; + relation_trio = TRIO_VARYING) const final override; relation_kind op1_op2_relation (const irange &lhs) const final override { return gt_op1_op2_relation (lhs); } bool op1_range (frange &r, tree type, const irange &lhs, const frange &op2, - relation_kind = VREL_VARYING) const final override; + relation_trio = TRIO_VARYING) const final override; bool op2_range (frange &r, tree type, const irange &lhs, const frange &op1, - relation_kind = VREL_VARYING) const final override; + relation_trio = TRIO_VARYING) const final override; } fop_gt; bool foperator_gt::fold_range (irange &r, tree type, const frange &op1, const frange &op2, - relation_kind rel) const + relation_trio rel) const { if (frelop_early_resolve (r, type, op1, op2, rel, VREL_GT)) return true; @@ -823,7 +825,7 @@ foperator_gt::op1_range (frange &r, tree type, const irange &lhs, const frange &op2, - relation_kind) const + relation_trio) const { switch (get_bool_state (r, lhs, type)) { @@ -858,7 +860,7 @@ foperator_gt::op2_range (frange &r, tree type, const irange &lhs, const frange &op1, - relation_kind) const + relation_trio) const { switch (get_bool_state (r, lhs, type)) { @@ -897,23 +899,23 @@ class foperator_ge : public range_operator_float public: bool fold_range (irange &r, tree type, const frange &op1, const frange &op2, - relation_kind = VREL_VARYING) const final override; + relation_trio = TRIO_VARYING) const final override; relation_kind op1_op2_relation (const irange &lhs) const final override { return ge_op1_op2_relation (lhs); } bool op1_range (frange &r, tree type, const irange &lhs, const frange &op2, - relation_kind = VREL_VARYING) const final override; + relation_trio = TRIO_VARYING) const final override; bool op2_range (frange &r, tree type, const irange &lhs, const frange &op1, - relation_kind = VREL_VARYING) const final override; + relation_trio = TRIO_VARYING) const final override; } fop_ge; bool foperator_ge::fold_range (irange &r, tree type, const frange &op1, const frange &op2, - relation_kind rel) const + relation_trio rel) const { if (frelop_early_resolve (r, type, op1, op2, rel, VREL_GE)) return true; @@ -939,7 +941,7 @@ foperator_ge::op1_range (frange &r, tree type, const irange &lhs, const frange &op2, - relation_kind) const + relation_trio) const { switch (get_bool_state (r, lhs, type)) { @@ -969,7 +971,7 @@ bool foperator_ge::op2_range (frange &r, tree type, const irange &lhs, const frange &op1, - relation_kind) const + relation_trio) const { switch (get_bool_state (r, lhs, type)) { @@ -1008,22 +1010,22 @@ class foperator_unordered : public range_operator_float public: bool fold_range (irange &r, tree type, const frange &op1, const frange &op2, - relation_kind = VREL_VARYING) const final override; + relation_trio = TRIO_VARYING) const final override; bool op1_range (frange &r, tree type, const irange &lhs, const frange &op2, - relation_kind = VREL_VARYING) const final override; + relation_trio = TRIO_VARYING) const final override; bool op2_range (frange &r, tree type, const irange &lhs, const frange &op1, - relation_kind rel = VREL_VARYING) const final override + relation_trio rel = TRIO_VARYING) const final override { - return op1_range (r, type, lhs, op1, rel); + return op1_range (r, type, lhs, op1, rel.swap_op1_op2 ()); } } fop_unordered; bool foperator_unordered::fold_range (irange &r, tree type, const frange &op1, const frange &op2, - relation_kind) const + relation_trio) const { // UNORDERED is TRUE if either operand is a NAN. if (op1.known_isnan () || op2.known_isnan ()) @@ -1040,8 +1042,9 @@ bool foperator_unordered::op1_range (frange &r, tree type, const irange &lhs, const frange &op2, - relation_kind rel) const + relation_trio trio) const { + relation_kind rel = trio.op1_op2 (); switch (get_bool_state (r, lhs, type)) { case BRS_TRUE: @@ -1081,22 +1084,22 @@ class foperator_ordered : public range_operator_float public: bool fold_range (irange &r, tree type, const frange &op1, const frange &op2, - relation_kind = VREL_VARYING) const final override; + relation_trio = TRIO_VARYING) const final override; bool op1_range (frange &r, tree type, const irange &lhs, const frange &op2, - relation_kind = VREL_VARYING) const final override; + relation_trio = TRIO_VARYING) const final override; bool op2_range (frange &r, tree type, const irange &lhs, const frange &op1, - relation_kind rel = VREL_VARYING) const final override + relation_trio rel = TRIO_VARYING) const final override { - return op1_range (r, type, lhs, op1, rel); + return op1_range (r, type, lhs, op1, rel.swap_op1_op2 ()); } } fop_ordered; bool foperator_ordered::fold_range (irange &r, tree type, const frange &op1, const frange &op2, - relation_kind) const + relation_trio) const { if (op1.known_isnan () || op2.known_isnan ()) r = range_false (type); @@ -1111,8 +1114,9 @@ bool foperator_ordered::op1_range (frange &r, tree type, const irange &lhs, const frange &op2, - relation_kind rel) const + relation_trio trio) const { + relation_kind rel = trio.op1_op2 (); switch (get_bool_state (r, lhs, type)) { case BRS_TRUE: @@ -1148,7 +1152,7 @@ class foperator_negate : public range_operator_float public: bool fold_range (frange &r, tree type, const frange &op1, const frange &op2, - relation_kind = VREL_VARYING) const final override + relation_trio = TRIO_VARYING) const final override { if (empty_range_varying (r, type, op1, op2)) return true; @@ -1181,7 +1185,7 @@ public: } bool op1_range (frange &r, tree type, const frange &lhs, const frange &op2, - relation_kind rel = VREL_VARYING) const final override + relation_trio rel = TRIO_VARYING) const final override { return fold_range (r, type, lhs, op2, rel); } @@ -1194,16 +1198,16 @@ class foperator_abs : public range_operator_float public: bool fold_range (frange &r, tree type, const frange &op1, const frange &, - relation_kind = VREL_VARYING) const final override; + relation_trio = TRIO_VARYING) const final override; bool op1_range (frange &r, tree type, const frange &lhs, const frange &op2, - relation_kind rel = VREL_VARYING) const final override; + relation_trio rel = TRIO_VARYING) const final override; } fop_abs; bool foperator_abs::fold_range (frange &r, tree type, const frange &op1, const frange &op2, - relation_kind) const + relation_trio) const { if (empty_range_varying (r, type, op1, op2)) return true; @@ -1253,7 +1257,7 @@ foperator_abs::fold_range (frange &r, tree type, bool foperator_abs::op1_range (frange &r, tree type, const frange &lhs, const frange &op2, - relation_kind) const + relation_trio) const { if (empty_range_varying (r, type, lhs, op2)) return true; @@ -1282,7 +1286,7 @@ class foperator_unordered_lt : public range_operator_float public: bool fold_range (irange &r, tree type, const frange &op1, const frange &op2, - relation_kind rel = VREL_VARYING) const final override + relation_trio rel = TRIO_VARYING) const final override { if (op1.known_isnan () || op2.known_isnan ()) { @@ -1311,7 +1315,7 @@ class foperator_unordered_le : public range_operator_float public: bool fold_range (irange &r, tree type, const frange &op1, const frange &op2, - relation_kind rel = VREL_VARYING) const final override + relation_trio rel = TRIO_VARYING) const final override { if (op1.known_isnan () || op2.known_isnan ()) { @@ -1332,16 +1336,16 @@ public: } bool op1_range (frange &r, tree type, const irange &lhs, const frange &op2, - relation_kind = VREL_VARYING) const final override; + relation_trio = TRIO_VARYING) const final override; bool op2_range (frange &r, tree type, const irange &lhs, const frange &op1, - relation_kind = VREL_VARYING) const final override; + relation_trio = TRIO_VARYING) const final override; } fop_unordered_le; bool foperator_unordered_le::op1_range (frange &r, tree type, const irange &lhs, const frange &op2, - relation_kind) const + relation_trio) const { switch (get_bool_state (r, lhs, type)) { @@ -1365,7 +1369,7 @@ foperator_unordered_le::op2_range (frange &r, tree type, const irange &lhs, const frange &op1, - relation_kind) const + relation_trio) const { switch (get_bool_state (r, lhs, type)) { @@ -1392,7 +1396,7 @@ class foperator_unordered_gt : public range_operator_float public: bool fold_range (irange &r, tree type, const frange &op1, const frange &op2, - relation_kind rel = VREL_VARYING) const final override + relation_trio rel = TRIO_VARYING) const final override { if (op1.known_isnan () || op2.known_isnan ()) { @@ -1413,10 +1417,10 @@ public: } bool op1_range (frange &r, tree type, const irange &lhs, const frange &op2, - relation_kind = VREL_VARYING) const final override; + relation_trio = TRIO_VARYING) const final override; bool op2_range (frange &r, tree type, const irange &lhs, const frange &op1, - relation_kind = VREL_VARYING) const final override; + relation_trio = TRIO_VARYING) const final override; } fop_unordered_gt; bool @@ -1424,7 +1428,7 @@ foperator_unordered_gt::op1_range (frange &r, tree type, const irange &lhs, const frange &op2, - relation_kind) const + relation_trio) const { switch (get_bool_state (r, lhs, type)) { @@ -1448,7 +1452,7 @@ foperator_unordered_gt::op2_range (frange &r, tree type, const irange &lhs, const frange &op1, - relation_kind) const + relation_trio) const { switch (get_bool_state (r, lhs, type)) { @@ -1475,7 +1479,7 @@ class foperator_unordered_ge : public range_operator_float public: bool fold_range (irange &r, tree type, const frange &op1, const frange &op2, - relation_kind rel = VREL_VARYING) const final override + relation_trio rel = TRIO_VARYING) const final override { if (op1.known_isnan () || op2.known_isnan ()) { @@ -1496,10 +1500,10 @@ public: } bool op1_range (frange &r, tree type, const irange &lhs, const frange &op2, - relation_kind = VREL_VARYING) const final override; + relation_trio = TRIO_VARYING) const final override; bool op2_range (frange &r, tree type, const irange &lhs, const frange &op1, - relation_kind = VREL_VARYING) const final override; + relation_trio = TRIO_VARYING) const final override; } fop_unordered_ge; bool @@ -1507,7 +1511,7 @@ foperator_unordered_ge::op1_range (frange &r, tree type, const irange &lhs, const frange &op2, - relation_kind) const + relation_trio) const { switch (get_bool_state (r, lhs, type)) { @@ -1530,7 +1534,7 @@ bool foperator_unordered_ge::op2_range (frange &r, tree type, const irange &lhs, const frange &op1, - relation_kind) const + relation_trio) const { switch (get_bool_state (r, lhs, type)) { @@ -1557,7 +1561,7 @@ class foperator_unordered_equal : public range_operator_float public: bool fold_range (irange &r, tree type, const frange &op1, const frange &op2, - relation_kind rel = VREL_VARYING) const final override + relation_trio rel = TRIO_VARYING) const final override { if (op1.known_isnan () || op2.known_isnan ()) { @@ -1578,12 +1582,12 @@ public: } bool op1_range (frange &r, tree type, const irange &lhs, const frange &op2, - relation_kind = VREL_VARYING) const final override; + relation_trio = TRIO_VARYING) const final override; bool op2_range (frange &r, tree type, const irange &lhs, const frange &op1, - relation_kind rel = VREL_VARYING) const final override + relation_trio rel = TRIO_VARYING) const final override { - return op1_range (r, type, lhs, op1, rel); + return op1_range (r, type, lhs, op1, rel.swap_op1_op2 ()); } } fop_unordered_equal; @@ -1591,7 +1595,7 @@ bool foperator_unordered_equal::op1_range (frange &r, tree type, const irange &lhs, const frange &op2, - relation_kind) const + relation_trio) const { switch (get_bool_state (r, lhs, type)) { diff --git a/gcc/range-op.cc b/gcc/range-op.cc index cf7f0dcd670..49ee7be3d3b 100644 --- a/gcc/range-op.cc +++ b/gcc/range-op.cc @@ -179,12 +179,13 @@ bool range_operator::fold_range (irange &r, tree type, const irange &lh, const irange &rh, - relation_kind rel) const + relation_trio trio) const { gcc_checking_assert (r.supports_type_p (type)); if (empty_range_varying (r, type, lh, rh)) return true; + relation_kind rel = trio.op1_op2 (); unsigned num_lh = lh.num_pairs (); unsigned num_rh = rh.num_pairs (); @@ -227,7 +228,7 @@ range_operator::op1_range (irange &r ATTRIBUTE_UNUSED, tree type ATTRIBUTE_UNUSED, const irange &lhs ATTRIBUTE_UNUSED, const irange &op2 ATTRIBUTE_UNUSED, - relation_kind rel ATTRIBUTE_UNUSED) const + relation_trio) const { return false; } @@ -239,7 +240,7 @@ range_operator::op2_range (irange &r ATTRIBUTE_UNUSED, tree type ATTRIBUTE_UNUSED, const irange &lhs ATTRIBUTE_UNUSED, const irange &op1 ATTRIBUTE_UNUSED, - relation_kind rel ATTRIBUTE_UNUSED) const + relation_trio) const { return false; } @@ -453,15 +454,15 @@ public: virtual bool fold_range (irange &r, tree type, const irange &op1, const irange &op2, - relation_kind rel = VREL_VARYING) const; + relation_trio = TRIO_VARYING) const; virtual bool op1_range (irange &r, tree type, const irange &lhs, const irange &val, - relation_kind rel = VREL_VARYING) const; + relation_trio = TRIO_VARYING) const; virtual bool op2_range (irange &r, tree type, const irange &lhs, const irange &val, - relation_kind rel = VREL_VARYING) const; + relation_trio = TRIO_VARYING) const; virtual relation_kind op1_op2_relation (const irange &lhs) const; } op_equal; @@ -494,7 +495,7 @@ bool operator_equal::fold_range (irange &r, tree type, const irange &op1, const irange &op2, - relation_kind rel) const + relation_trio rel) const { if (relop_early_resolve (r, type, op1, op2, rel, VREL_EQ)) return true; @@ -527,7 +528,7 @@ bool operator_equal::op1_range (irange &r, tree type, const irange &lhs, const irange &op2, - relation_kind rel ATTRIBUTE_UNUSED) const + relation_trio) const { switch (get_bool_state (r, lhs, type)) { @@ -558,9 +559,9 @@ bool operator_equal::op2_range (irange &r, tree type, const irange &lhs, const irange &op1, - relation_kind rel) const + relation_trio rel) const { - return operator_equal::op1_range (r, type, lhs, op1, rel); + return operator_equal::op1_range (r, type, lhs, op1, rel.swap_op1_op2 ()); } class operator_not_equal : public range_operator @@ -572,15 +573,15 @@ public: virtual bool fold_range (irange &r, tree type, const irange &op1, const irange &op2, - relation_kind rel = VREL_VARYING) const; + relation_trio = TRIO_VARYING) const; virtual bool op1_range (irange &r, tree type, const irange &lhs, const irange &op2, - relation_kind rel = VREL_VARYING) const; + relation_trio = TRIO_VARYING) const; virtual bool op2_range (irange &r, tree type, const irange &lhs, const irange &op1, - relation_kind rel = VREL_VARYING) const; + relation_trio = TRIO_VARYING) const; virtual relation_kind op1_op2_relation (const irange &lhs) const; } op_not_equal; @@ -612,7 +613,7 @@ bool operator_not_equal::fold_range (irange &r, tree type, const irange &op1, const irange &op2, - relation_kind rel) const + relation_trio rel) const { if (relop_early_resolve (r, type, op1, op2, rel, VREL_NE)) return true; @@ -645,7 +646,7 @@ bool operator_not_equal::op1_range (irange &r, tree type, const irange &lhs, const irange &op2, - relation_kind rel ATTRIBUTE_UNUSED) const + relation_trio) const { switch (get_bool_state (r, lhs, type)) { @@ -677,9 +678,9 @@ bool operator_not_equal::op2_range (irange &r, tree type, const irange &lhs, const irange &op1, - relation_kind rel) const + relation_trio rel) const { - return operator_not_equal::op1_range (r, type, lhs, op1, rel); + return operator_not_equal::op1_range (r, type, lhs, op1, rel.swap_op1_op2 ()); } // (X < VAL) produces the range of [MIN, VAL - 1]. @@ -751,15 +752,15 @@ public: virtual bool fold_range (irange &r, tree type, const irange &op1, const irange &op2, - relation_kind rel = VREL_VARYING) const; + relation_trio = TRIO_VARYING) const; virtual bool op1_range (irange &r, tree type, const irange &lhs, const irange &op2, - relation_kind rel = VREL_VARYING) const; + relation_trio = TRIO_VARYING) const; virtual bool op2_range (irange &r, tree type, const irange &lhs, const irange &op1, - relation_kind rel = VREL_VARYING) const; + relation_trio = TRIO_VARYING) const; virtual relation_kind op1_op2_relation (const irange &lhs) const; } op_lt; @@ -791,7 +792,7 @@ bool operator_lt::fold_range (irange &r, tree type, const irange &op1, const irange &op2, - relation_kind rel) const + relation_trio rel) const { if (relop_early_resolve (r, type, op1, op2, rel, VREL_LT)) return true; @@ -815,7 +816,7 @@ bool operator_lt::op1_range (irange &r, tree type, const irange &lhs, const irange &op2, - relation_kind rel ATTRIBUTE_UNUSED) const + relation_trio) const { switch (get_bool_state (r, lhs, type)) { @@ -837,7 +838,7 @@ bool operator_lt::op2_range (irange &r, tree type, const irange &lhs, const irange &op1, - relation_kind rel ATTRIBUTE_UNUSED) const + relation_trio) const { switch (get_bool_state (r, lhs, type)) { @@ -865,15 +866,15 @@ public: virtual bool fold_range (irange &r, tree type, const irange &op1, const irange &op2, - relation_kind rel = VREL_VARYING) const; + relation_trio = TRIO_VARYING) const; virtual bool op1_range (irange &r, tree type, const irange &lhs, const irange &op2, - relation_kind rel = VREL_VARYING) const; + relation_trio = TRIO_VARYING) const; virtual bool op2_range (irange &r, tree type, const irange &lhs, const irange &op1, - relation_kind rel = VREL_VARYING) const; + relation_trio = TRIO_VARYING) const; virtual relation_kind op1_op2_relation (const irange &lhs) const; } op_le; @@ -905,7 +906,7 @@ bool operator_le::fold_range (irange &r, tree type, const irange &op1, const irange &op2, - relation_kind rel) const + relation_trio rel) const { if (relop_early_resolve (r, type, op1, op2, rel, VREL_LE)) return true; @@ -926,7 +927,7 @@ bool operator_le::op1_range (irange &r, tree type, const irange &lhs, const irange &op2, - relation_kind rel ATTRIBUTE_UNUSED) const + relation_trio) const { switch (get_bool_state (r, lhs, type)) { @@ -948,7 +949,7 @@ bool operator_le::op2_range (irange &r, tree type, const irange &lhs, const irange &op1, - relation_kind rel ATTRIBUTE_UNUSED) const + relation_trio) const { switch (get_bool_state (r, lhs, type)) { @@ -976,15 +977,15 @@ public: virtual bool fold_range (irange &r, tree type, const irange &op1, const irange &op2, - relation_kind rel = VREL_VARYING) const; + relation_trio = TRIO_VARYING) const; virtual bool op1_range (irange &r, tree type, const irange &lhs, const irange &op2, - relation_kind rel = VREL_VARYING) const; + relation_trio = TRIO_VARYING) const; virtual bool op2_range (irange &r, tree type, const irange &lhs, const irange &op1, - relation_kind rel = VREL_VARYING) const; + relation_trio = TRIO_VARYING) const; virtual relation_kind op1_op2_relation (const irange &lhs) const; } op_gt; @@ -1016,7 +1017,7 @@ operator_gt::op1_op2_relation (const irange &lhs) const bool operator_gt::fold_range (irange &r, tree type, const irange &op1, const irange &op2, - relation_kind rel) const + relation_trio rel) const { if (relop_early_resolve (r, type, op1, op2, rel, VREL_GT)) return true; @@ -1036,7 +1037,7 @@ operator_gt::fold_range (irange &r, tree type, bool operator_gt::op1_range (irange &r, tree type, const irange &lhs, const irange &op2, - relation_kind rel ATTRIBUTE_UNUSED) const + relation_trio) const { switch (get_bool_state (r, lhs, type)) { @@ -1058,7 +1059,7 @@ bool operator_gt::op2_range (irange &r, tree type, const irange &lhs, const irange &op1, - relation_kind rel ATTRIBUTE_UNUSED) const + relation_trio) const { switch (get_bool_state (r, lhs, type)) { @@ -1086,15 +1087,15 @@ public: virtual bool fold_range (irange &r, tree type, const irange &op1, const irange &op2, - relation_kind rel = VREL_VARYING) const; + relation_trio = TRIO_VARYING) const; virtual bool op1_range (irange &r, tree type, const irange &lhs, const irange &op2, - relation_kind rel = VREL_VARYING) const; + relation_trio = TRIO_VARYING) const; virtual bool op2_range (irange &r, tree type, const irange &lhs, const irange &op1, - relation_kind rel = VREL_VARYING) const; + relation_trio = TRIO_VARYING) const; virtual relation_kind op1_op2_relation (const irange &lhs) const; } op_ge; @@ -1126,7 +1127,7 @@ bool operator_ge::fold_range (irange &r, tree type, const irange &op1, const irange &op2, - relation_kind rel) const + relation_trio rel) const { if (relop_early_resolve (r, type, op1, op2, rel, VREL_GE)) return true; @@ -1147,7 +1148,7 @@ bool operator_ge::op1_range (irange &r, tree type, const irange &lhs, const irange &op2, - relation_kind rel ATTRIBUTE_UNUSED) const + relation_trio) const { switch (get_bool_state (r, lhs, type)) { @@ -1169,7 +1170,7 @@ bool operator_ge::op2_range (irange &r, tree type, const irange &lhs, const irange &op1, - relation_kind rel ATTRIBUTE_UNUSED) const + relation_trio) const { switch (get_bool_state (r, lhs, type)) { @@ -1198,11 +1199,11 @@ public: virtual bool op1_range (irange &r, tree type, const irange &lhs, const irange &op2, - relation_kind rel ATTRIBUTE_UNUSED) const; + relation_trio) const; virtual bool op2_range (irange &r, tree type, const irange &lhs, const irange &op1, - relation_kind rel ATTRIBUTE_UNUSED) const; + relation_trio) const; virtual void wi_fold (irange &r, tree type, const wide_int &lh_lb, const wide_int &lh_ub, @@ -1402,7 +1403,7 @@ bool operator_plus::op1_range (irange &r, tree type, const irange &lhs, const irange &op2, - relation_kind rel) const + relation_trio trio) const { if (lhs.undefined_p ()) return false; @@ -1411,6 +1412,7 @@ operator_plus::op1_range (irange &r, tree type, if (!minus) return false; bool res = minus.fold_range (r, type, lhs, op2); + relation_kind rel = trio.lhs_op2 (); // Check for a relation refinement. if (res) adjust_op1_for_overflow (r, op2, rel, true /* PLUS_EXPR */); @@ -1421,9 +1423,9 @@ bool operator_plus::op2_range (irange &r, tree type, const irange &lhs, const irange &op1, - relation_kind rel) const + relation_trio rel) const { - return op1_range (r, type, lhs, op1, rel); + return op1_range (r, type, lhs, op1, rel.swap_op1_op2 ()); } @@ -1436,11 +1438,11 @@ public: virtual bool op1_range (irange &r, tree type, const irange &lhs, const irange &op2, - relation_kind rel ATTRIBUTE_UNUSED) const; + relation_trio) const; virtual bool op2_range (irange &r, tree type, const irange &lhs, const irange &op1, - relation_kind rel ATTRIBUTE_UNUSED) const; + relation_trio) const; virtual void wi_fold (irange &r, tree type, const wide_int &lh_lb, const wide_int &lh_ub, @@ -1573,7 +1575,7 @@ bool operator_minus::op1_range (irange &r, tree type, const irange &lhs, const irange &op2, - relation_kind rel ATTRIBUTE_UNUSED) const + relation_trio trio) const { if (lhs.undefined_p ()) return false; @@ -1582,6 +1584,7 @@ operator_minus::op1_range (irange &r, tree type, if (!minus) return false; bool res = minus.fold_range (r, type, lhs, op2); + relation_kind rel = trio.lhs_op2 (); if (res) adjust_op1_for_overflow (r, op2, rel, false /* PLUS_EXPR */); return res; @@ -1592,7 +1595,7 @@ bool operator_minus::op2_range (irange &r, tree type, const irange &lhs, const irange &op1, - relation_kind rel ATTRIBUTE_UNUSED) const + relation_trio) const { if (lhs.undefined_p ()) return false; @@ -1752,17 +1755,17 @@ public: virtual bool op1_range (irange &r, tree type, const irange &lhs, const irange &op2, - relation_kind rel ATTRIBUTE_UNUSED) const; + relation_trio) const; virtual bool op2_range (irange &r, tree type, const irange &lhs, const irange &op1, - relation_kind rel ATTRIBUTE_UNUSED) const; + relation_trio) const; } op_mult; bool operator_mult::op1_range (irange &r, tree type, const irange &lhs, const irange &op2, - relation_kind rel ATTRIBUTE_UNUSED) const + relation_trio) const { tree offset; if (lhs.undefined_p ()) @@ -1783,9 +1786,9 @@ operator_mult::op1_range (irange &r, tree type, bool operator_mult::op2_range (irange &r, tree type, const irange &lhs, const irange &op1, - relation_kind rel) const + relation_trio rel) const { - return operator_mult::op1_range (r, type, lhs, op1, rel); + return operator_mult::op1_range (r, type, lhs, op1, rel.swap_op1_op2 ()); } bool @@ -2009,7 +2012,7 @@ public: virtual bool op1_range (irange &r, tree type, const irange &lhs, const irange &op2, - relation_kind rel ATTRIBUTE_UNUSED) const; + relation_trio) const; } op_exact_div; @@ -2017,7 +2020,7 @@ bool operator_exact_divide::op1_range (irange &r, tree type, const irange &lhs, const irange &op2, - relation_kind rel ATTRIBUTE_UNUSED) const + relation_trio) const { if (lhs.undefined_p ()) return false; @@ -2043,11 +2046,11 @@ public: virtual bool op1_range (irange &r, tree type, const irange &lhs, const irange &op2, - relation_kind rel = VREL_VARYING) const; + relation_trio rel = TRIO_VARYING) const; virtual bool fold_range (irange &r, tree type, const irange &op1, const irange &op2, - relation_kind rel = VREL_VARYING) const; + relation_trio rel = TRIO_VARYING) const; virtual void wi_fold (irange &r, tree type, const wide_int &lh_lb, const wide_int &lh_ub, @@ -2067,7 +2070,7 @@ public: virtual bool fold_range (irange &r, tree type, const irange &op1, const irange &op2, - relation_kind rel = VREL_VARYING) const; + relation_trio rel = TRIO_VARYING) const; virtual void wi_fold (irange &r, tree type, const wide_int &lh_lb, const wide_int &lh_ub, @@ -2080,7 +2083,7 @@ public: virtual bool op1_range (irange &, tree type, const irange &lhs, const irange &op2, - relation_kind rel = VREL_VARYING) const; + relation_trio rel = TRIO_VARYING) const; virtual relation_kind lhs_op1_relation (const irange &lhs, const irange &op1, const irange &op2, @@ -2106,7 +2109,7 @@ bool operator_lshift::fold_range (irange &r, tree type, const irange &op1, const irange &op2, - relation_kind rel) const + relation_trio rel) const { int_range_max shift_range; if (!get_shift_range (shift_range, type, op2)) @@ -2228,7 +2231,7 @@ operator_lshift::op1_range (irange &r, tree type, const irange &lhs, const irange &op2, - relation_kind rel ATTRIBUTE_UNUSED) const + relation_trio) const { if (lhs.undefined_p ()) return false; @@ -2301,7 +2304,7 @@ operator_rshift::op1_range (irange &r, tree type, const irange &lhs, const irange &op2, - relation_kind rel ATTRIBUTE_UNUSED) const + relation_trio) const { tree shift; if (lhs.undefined_p ()) @@ -2380,7 +2383,7 @@ bool operator_rshift::fold_range (irange &r, tree type, const irange &op1, const irange &op2, - relation_kind rel) const + relation_trio rel) const { int_range_max shift; if (!get_shift_range (shift, type, op2)) @@ -2412,11 +2415,11 @@ public: virtual bool fold_range (irange &r, tree type, const irange &op1, const irange &op2, - relation_kind rel = VREL_VARYING) const; + relation_trio rel = TRIO_VARYING) const; virtual bool op1_range (irange &r, tree type, const irange &lhs, const irange &op2, - relation_kind rel = VREL_VARYING) const; + relation_trio rel = TRIO_VARYING) const; virtual relation_kind lhs_op1_relation (const irange &lhs, const irange &op1, const irange &op2, @@ -2528,7 +2531,7 @@ bool operator_cast::fold_range (irange &r, tree type ATTRIBUTE_UNUSED, const irange &inner, const irange &outer, - relation_kind rel ATTRIBUTE_UNUSED) const + relation_trio) const { if (empty_range_varying (r, type, inner, outer)) return true; @@ -2567,7 +2570,7 @@ bool operator_cast::op1_range (irange &r, tree type, const irange &lhs, const irange &op2, - relation_kind rel ATTRIBUTE_UNUSED) const + relation_trio) const { if (lhs.undefined_p ()) return false; @@ -2682,15 +2685,15 @@ public: virtual bool fold_range (irange &r, tree type, const irange &lh, const irange &rh, - relation_kind rel = VREL_VARYING) const; + relation_trio rel = TRIO_VARYING) const; virtual bool op1_range (irange &r, tree type, const irange &lhs, const irange &op2, - relation_kind rel = VREL_VARYING) const; + relation_trio rel = TRIO_VARYING) const; virtual bool op2_range (irange &r, tree type, const irange &lhs, const irange &op1, - relation_kind rel = VREL_VARYING) const; + relation_trio rel = TRIO_VARYING) const; } op_logical_and; @@ -2698,7 +2701,7 @@ bool operator_logical_and::fold_range (irange &r, tree type, const irange &lh, const irange &rh, - relation_kind rel ATTRIBUTE_UNUSED) const + relation_trio) const { if (empty_range_varying (r, type, lh, rh)) return true; @@ -2721,7 +2724,7 @@ bool operator_logical_and::op1_range (irange &r, tree type, const irange &lhs, const irange &op2 ATTRIBUTE_UNUSED, - relation_kind rel ATTRIBUTE_UNUSED) const + relation_trio) const { switch (get_bool_state (r, lhs, type)) { @@ -2743,7 +2746,7 @@ bool operator_logical_and::op2_range (irange &r, tree type, const irange &lhs, const irange &op1, - relation_kind rel ATTRIBUTE_UNUSED) const + relation_trio) const { return operator_logical_and::op1_range (r, type, lhs, op1); } @@ -2758,15 +2761,15 @@ public: virtual bool fold_range (irange &r, tree type, const irange &lh, const irange &rh, - relation_kind rel = VREL_VARYING) const; + relation_trio rel = TRIO_VARYING) const; virtual bool op1_range (irange &r, tree type, const irange &lhs, const irange &op2, - relation_kind rel = VREL_VARYING) const; + relation_trio rel = TRIO_VARYING) const; virtual bool op2_range (irange &r, tree type, const irange &lhs, const irange &op1, - relation_kind rel = VREL_VARYING) const; + relation_trio rel = TRIO_VARYING) const; virtual void wi_fold (irange &r, tree type, const wide_int &lh_lb, const wide_int &lh_ub, @@ -2786,7 +2789,7 @@ bool operator_bitwise_and::fold_range (irange &r, tree type, const irange &lh, const irange &rh, - relation_kind rel ATTRIBUTE_UNUSED) const + relation_trio) const { if (range_operator::fold_range (r, type, lh, rh)) { @@ -3136,7 +3139,7 @@ bool operator_bitwise_and::op1_range (irange &r, tree type, const irange &lhs, const irange &op2, - relation_kind rel ATTRIBUTE_UNUSED) const + relation_trio) const { if (lhs.undefined_p ()) return false; @@ -3171,7 +3174,7 @@ bool operator_bitwise_and::op2_range (irange &r, tree type, const irange &lhs, const irange &op1, - relation_kind rel ATTRIBUTE_UNUSED) const + relation_trio) const { return operator_bitwise_and::op1_range (r, type, lhs, op1); } @@ -3186,22 +3189,22 @@ public: virtual bool fold_range (irange &r, tree type, const irange &lh, const irange &rh, - relation_kind rel = VREL_VARYING) const; + relation_trio rel = TRIO_VARYING) const; virtual bool op1_range (irange &r, tree type, const irange &lhs, const irange &op2, - relation_kind rel = VREL_VARYING) const; + relation_trio rel = TRIO_VARYING) const; virtual bool op2_range (irange &r, tree type, const irange &lhs, const irange &op1, - relation_kind rel = VREL_VARYING) const; + relation_trio rel = TRIO_VARYING) const; } op_logical_or; bool operator_logical_or::fold_range (irange &r, tree type ATTRIBUTE_UNUSED, const irange &lh, const irange &rh, - relation_kind rel ATTRIBUTE_UNUSED) const + relation_trio) const { if (empty_range_varying (r, type, lh, rh)) return true; @@ -3215,7 +3218,7 @@ bool operator_logical_or::op1_range (irange &r, tree type, const irange &lhs, const irange &op2 ATTRIBUTE_UNUSED, - relation_kind rel ATTRIBUTE_UNUSED) const + relation_trio) const { switch (get_bool_state (r, lhs, type)) { @@ -3237,7 +3240,7 @@ bool operator_logical_or::op2_range (irange &r, tree type, const irange &lhs, const irange &op1, - relation_kind rel ATTRIBUTE_UNUSED) const + relation_trio) const { return operator_logical_or::op1_range (r, type, lhs, op1); } @@ -3251,11 +3254,11 @@ public: virtual bool op1_range (irange &r, tree type, const irange &lhs, const irange &op2, - relation_kind rel = VREL_VARYING) const; + relation_trio rel = TRIO_VARYING) const; virtual bool op2_range (irange &r, tree type, const irange &lhs, const irange &op1, - relation_kind rel= VREL_VARYING) const; + relation_trio rel = TRIO_VARYING) const; virtual void wi_fold (irange &r, tree type, const wide_int &lh_lb, const wide_int &lh_ub, @@ -3323,7 +3326,7 @@ bool operator_bitwise_or::op1_range (irange &r, tree type, const irange &lhs, const irange &op2, - relation_kind rel ATTRIBUTE_UNUSED) const + relation_trio) const { if (lhs.undefined_p ()) return false; @@ -3345,7 +3348,7 @@ bool operator_bitwise_or::op2_range (irange &r, tree type, const irange &lhs, const irange &op1, - relation_kind rel ATTRIBUTE_UNUSED) const + relation_trio) const { return operator_bitwise_or::op1_range (r, type, lhs, op1); } @@ -3364,11 +3367,11 @@ public: virtual bool op1_range (irange &r, tree type, const irange &lhs, const irange &op2, - relation_kind rel = VREL_VARYING) const; + relation_trio rel = TRIO_VARYING) const; virtual bool op2_range (irange &r, tree type, const irange &lhs, const irange &op1, - relation_kind rel = VREL_VARYING) const; + relation_trio rel = TRIO_VARYING) const; virtual bool op1_op2_relation_effect (irange &lhs_range, tree type, const irange &op1_range, @@ -3454,7 +3457,7 @@ bool operator_bitwise_xor::op1_range (irange &r, tree type, const irange &lhs, const irange &op2, - relation_kind rel ATTRIBUTE_UNUSED) const + relation_trio) const { if (lhs.undefined_p () || lhs.varying_p ()) { @@ -3489,7 +3492,7 @@ bool operator_bitwise_xor::op2_range (irange &r, tree type, const irange &lhs, const irange &op1, - relation_kind rel ATTRIBUTE_UNUSED) const + relation_trio) const { return operator_bitwise_xor::op1_range (r, type, lhs, op1); } @@ -3507,11 +3510,11 @@ public: virtual bool op1_range (irange &r, tree type, const irange &lhs, const irange &op2, - relation_kind rel ATTRIBUTE_UNUSED) const; + relation_trio) const; virtual bool op2_range (irange &r, tree type, const irange &lhs, const irange &op1, - relation_kind rel ATTRIBUTE_UNUSED) const; + relation_trio) const; } op_trunc_mod; void @@ -3574,7 +3577,7 @@ bool operator_trunc_mod::op1_range (irange &r, tree type, const irange &lhs, const irange &, - relation_kind rel ATTRIBUTE_UNUSED) const + relation_trio) const { if (lhs.undefined_p ()) return false; @@ -3600,7 +3603,7 @@ bool operator_trunc_mod::op2_range (irange &r, tree type, const irange &lhs, const irange &, - relation_kind rel ATTRIBUTE_UNUSED) const + relation_trio) const { if (lhs.undefined_p ()) return false; @@ -3644,11 +3647,11 @@ public: virtual bool fold_range (irange &r, tree type, const irange &lh, const irange &rh, - relation_kind rel = VREL_VARYING) const; + relation_trio rel = TRIO_VARYING) const; virtual bool op1_range (irange &r, tree type, const irange &lhs, const irange &op2, - relation_kind rel = VREL_VARYING) const; + relation_trio rel = TRIO_VARYING) const; } op_logical_not; // Folding a logical NOT, oddly enough, involves doing nothing on the @@ -3669,7 +3672,7 @@ bool operator_logical_not::fold_range (irange &r, tree type, const irange &lh, const irange &rh ATTRIBUTE_UNUSED, - relation_kind rel ATTRIBUTE_UNUSED) const + relation_trio) const { if (empty_range_varying (r, type, lh, rh)) return true; @@ -3686,7 +3689,7 @@ operator_logical_not::op1_range (irange &r, tree type, const irange &lhs, const irange &op2, - relation_kind rel ATTRIBUTE_UNUSED) const + relation_trio) const { // Logical NOT is involutary...do it again. return fold_range (r, type, lhs, op2); @@ -3701,18 +3704,18 @@ public: virtual bool fold_range (irange &r, tree type, const irange &lh, const irange &rh, - relation_kind rel = VREL_VARYING) const; + relation_trio rel = TRIO_VARYING) const; virtual bool op1_range (irange &r, tree type, const irange &lhs, const irange &op2, - relation_kind rel = VREL_VARYING) const; + relation_trio rel = TRIO_VARYING) const; } op_bitwise_not; bool operator_bitwise_not::fold_range (irange &r, tree type, const irange &lh, const irange &rh, - relation_kind rel ATTRIBUTE_UNUSED) const + relation_trio) const { if (empty_range_varying (r, type, lh, rh)) return true; @@ -3730,7 +3733,7 @@ bool operator_bitwise_not::op1_range (irange &r, tree type, const irange &lhs, const irange &op2, - relation_kind rel ATTRIBUTE_UNUSED) const + relation_trio) const { if (lhs.undefined_p ()) return false; @@ -3749,14 +3752,14 @@ public: virtual bool fold_range (irange &r, tree type, const irange &op1, const irange &op2, - relation_kind rel = VREL_VARYING) const; + relation_trio rel = TRIO_VARYING) const; } op_integer_cst; bool operator_cst::fold_range (irange &r, tree type ATTRIBUTE_UNUSED, const irange &lh, const irange &rh ATTRIBUTE_UNUSED, - relation_kind rel ATTRIBUTE_UNUSED) const + relation_trio) const { r = lh; return true; @@ -3772,11 +3775,11 @@ public: virtual bool fold_range (irange &r, tree type, const irange &op1, const irange &op2, - relation_kind rel = VREL_VARYING) const; + relation_trio rel = TRIO_VARYING) const; virtual bool op1_range (irange &r, tree type, const irange &lhs, const irange &op2, - relation_kind rel = VREL_VARYING) const; + relation_trio rel = TRIO_VARYING) const; virtual relation_kind lhs_op1_relation (const irange &lhs, const irange &op1, const irange &op2, @@ -3801,7 +3804,7 @@ bool operator_identity::fold_range (irange &r, tree type ATTRIBUTE_UNUSED, const irange &lh, const irange &rh ATTRIBUTE_UNUSED, - relation_kind rel ATTRIBUTE_UNUSED) const + relation_trio) const { r = lh; return true; @@ -3811,7 +3814,7 @@ bool operator_identity::op1_range (irange &r, tree type ATTRIBUTE_UNUSED, const irange &lhs, const irange &op2 ATTRIBUTE_UNUSED, - relation_kind rel ATTRIBUTE_UNUSED) const + relation_trio) const { r = lhs; return true; @@ -3825,14 +3828,14 @@ public: virtual bool fold_range (irange &r, tree type, const irange &op1, const irange &op2, - relation_kind rel = VREL_VARYING) const; + relation_trio rel = TRIO_VARYING) const; } op_unknown; bool operator_unknown::fold_range (irange &r, tree type, const irange &lh ATTRIBUTE_UNUSED, const irange &rh ATTRIBUTE_UNUSED, - relation_kind rel ATTRIBUTE_UNUSED) const + relation_trio) const { r.set_varying (type); return true; @@ -3851,7 +3854,7 @@ class operator_abs : public range_operator virtual bool op1_range (irange &r, tree type, const irange &lhs, const irange &op2, - relation_kind rel ATTRIBUTE_UNUSED) const; + relation_trio) const; } op_abs; void @@ -3932,7 +3935,7 @@ bool operator_abs::op1_range (irange &r, tree type, const irange &lhs, const irange &op2, - relation_kind rel ATTRIBUTE_UNUSED) const + relation_trio) const { if (empty_range_varying (r, type, lhs, op2)) return true; @@ -4013,18 +4016,18 @@ class operator_negate : public range_operator virtual bool fold_range (irange &r, tree type, const irange &op1, const irange &op2, - relation_kind rel = VREL_VARYING) const; + relation_trio rel = TRIO_VARYING) const; virtual bool op1_range (irange &r, tree type, const irange &lhs, const irange &op2, - relation_kind rel = VREL_VARYING) const; + relation_trio rel = TRIO_VARYING) const; } op_negate; bool operator_negate::fold_range (irange &r, tree type, const irange &lh, const irange &rh, - relation_kind rel ATTRIBUTE_UNUSED) const + relation_trio) const { if (empty_range_varying (r, type, lh, rh)) return true; @@ -4037,7 +4040,7 @@ bool operator_negate::op1_range (irange &r, tree type, const irange &lhs, const irange &op2, - relation_kind rel ATTRIBUTE_UNUSED) const + relation_trio) const { // NEGATE is involutory. return fold_range (r, type, lhs, op2); @@ -4052,18 +4055,18 @@ public: virtual bool fold_range (irange &r, tree type, const irange &op1, const irange &op2, - relation_kind rel = VREL_VARYING) const; + relation_trio rel = TRIO_VARYING) const; virtual bool op1_range (irange &r, tree type, const irange &lhs, const irange &op2, - relation_kind rel = VREL_VARYING) const; + relation_trio rel = TRIO_VARYING) const; } op_addr; bool operator_addr_expr::fold_range (irange &r, tree type, const irange &lh, const irange &rh, - relation_kind rel ATTRIBUTE_UNUSED) const + relation_trio) const { if (empty_range_varying (r, type, lh, rh)) return true; @@ -4082,7 +4085,7 @@ bool operator_addr_expr::op1_range (irange &r, tree type, const irange &lhs, const irange &op2, - relation_kind rel ATTRIBUTE_UNUSED) const + relation_trio) const { return operator_addr_expr::fold_range (r, type, lhs, op2); } @@ -4204,11 +4207,11 @@ public: virtual bool op1_range (irange &r, tree type, const irange &lhs, const irange &op2, - relation_kind rel = VREL_VARYING) const; + relation_trio rel = TRIO_VARYING) const; virtual bool op2_range (irange &r, tree type, const irange &lhs, const irange &op1, - relation_kind rel = VREL_VARYING) const; + relation_trio rel = TRIO_VARYING) const; virtual void wi_fold (irange &r, tree type, const wide_int &lh_lb, const wide_int &lh_ub, const wide_int &rh_lb, const wide_int &rh_ub) const; @@ -4218,7 +4221,7 @@ bool pointer_or_operator::op1_range (irange &r, tree type, const irange &lhs, const irange &op2 ATTRIBUTE_UNUSED, - relation_kind rel ATTRIBUTE_UNUSED) const + relation_trio) const { if (lhs.undefined_p ()) return false; @@ -4236,7 +4239,7 @@ bool pointer_or_operator::op2_range (irange &r, tree type, const irange &lhs, const irange &op1, - relation_kind rel ATTRIBUTE_UNUSED) const + relation_trio) const { return pointer_or_operator::op1_range (r, type, lhs, op1); } @@ -4422,7 +4425,7 @@ bool range_op_handler::fold_range (vrange &r, tree type, const vrange &lh, const vrange &rh, - relation_kind rel) const + relation_trio rel) const { gcc_checking_assert (m_valid); if (m_int) @@ -4450,7 +4453,7 @@ bool range_op_handler::op1_range (vrange &r, tree type, const vrange &lhs, const vrange &op2, - relation_kind rel) const + relation_trio rel) const { gcc_checking_assert (m_valid); @@ -4474,7 +4477,7 @@ bool range_op_handler::op2_range (vrange &r, tree type, const vrange &lhs, const vrange &op1, - relation_kind rel) const + relation_trio rel) const { gcc_checking_assert (m_valid); if (lhs.undefined_p ()) diff --git a/gcc/range-op.h b/gcc/range-op.h index 48adcecc7c6..c7249890142 100644 --- a/gcc/range-op.h +++ b/gcc/range-op.h @@ -53,7 +53,7 @@ public: virtual bool fold_range (irange &r, tree type, const irange &lh, const irange &rh, - relation_kind rel = VREL_VARYING) const; + relation_trio = TRIO_VARYING) const; // Return the range for op[12] in the general case. LHS is the range for // the LHS of the expression, OP[12]is the range for the other @@ -69,11 +69,11 @@ public: virtual bool op1_range (irange &r, tree type, const irange &lhs, const irange &op2, - relation_kind rel = VREL_VARYING) const; + relation_trio = TRIO_VARYING) const; virtual bool op2_range (irange &r, tree type, const irange &lhs, const irange &op1, - relation_kind rel = VREL_VARYING) const; + relation_trio = TRIO_VARYING) const; // The following routines are used to represent relations between the // various operations. If the caller knows where the symbolics are, @@ -116,32 +116,32 @@ public: virtual bool fold_range (frange &r, tree type, const frange &lh, const frange &rh, - relation_kind rel = VREL_VARYING) const; + relation_trio = TRIO_VARYING) const; // Unary operations have the range of the LHS as op2. virtual bool fold_range (irange &r, tree type, const frange &lh, const irange &rh, - relation_kind rel = VREL_VARYING) const; + relation_trio = TRIO_VARYING) const; virtual bool fold_range (irange &r, tree type, const frange &lh, const frange &rh, - relation_kind rel = VREL_VARYING) const; + relation_trio = TRIO_VARYING) const; virtual bool op1_range (frange &r, tree type, const frange &lhs, const frange &op2, - relation_kind rel = VREL_VARYING) const; + relation_trio = TRIO_VARYING) const; virtual bool op1_range (frange &r, tree type, const irange &lhs, const frange &op2, - relation_kind rel = VREL_VARYING) const; + relation_trio = TRIO_VARYING) const; virtual bool op2_range (frange &r, tree type, const frange &lhs, const frange &op1, - relation_kind rel = VREL_VARYING) const; + relation_trio = TRIO_VARYING) const; virtual bool op2_range (frange &r, tree type, const irange &lhs, const frange &op1, - relation_kind rel = VREL_VARYING) const; + relation_trio = TRIO_VARYING) const; virtual relation_kind lhs_op1_relation (const frange &lhs, const frange &op1, @@ -173,15 +173,15 @@ public: bool fold_range (vrange &r, tree type, const vrange &lh, const vrange &rh, - relation_kind rel = VREL_VARYING) const; + relation_trio = TRIO_VARYING) const; bool op1_range (vrange &r, tree type, const vrange &lhs, const vrange &op2, - relation_kind rel = VREL_VARYING) const; + relation_trio = TRIO_VARYING) const; bool op2_range (vrange &r, tree type, const vrange &lhs, const vrange &op1, - relation_kind rel = VREL_VARYING) const; + relation_trio = TRIO_VARYING) const; relation_kind lhs_op1_relation (const vrange &lhs, const vrange &op1, const vrange &op2, @@ -240,9 +240,10 @@ empty_range_varying (vrange &r, tree type, inline bool relop_early_resolve (irange &r, tree type, const vrange &op1, - const vrange &op2, relation_kind rel, + const vrange &op2, relation_trio trio, relation_kind my_rel) { + relation_kind rel = trio.op1_op2 (); // If known relation is a complete subset of this relation, always true. if (relation_union (rel, my_rel) == my_rel) { diff --git a/gcc/value-relation.cc b/gcc/value-relation.cc index 3fb7b96c9e0..fed8a78723c 100644 --- a/gcc/value-relation.cc +++ b/gcc/value-relation.cc @@ -32,9 +32,7 @@ along with GCC; see the file COPYING3. If not see #include "alloc-pool.h" #include "dominance.h" -#define VREL_LAST VREL_PE64 - -static const char *kind_string[VREL_LAST + 1] = +static const char *kind_string[VREL_LAST] = { "varying", "undefined", "<", "<=", ">", ">=", "==", "!=", "pe8", "pe16", "pe32", "pe64" }; @@ -47,7 +45,7 @@ print_relation (FILE *f, relation_kind rel) } // This table is used to negate the operands. op1 REL op2 -> !(op1 REL op2). -relation_kind rr_negate_table[VREL_LAST + 1] = { +relation_kind rr_negate_table[VREL_LAST] = { VREL_VARYING, VREL_UNDEFINED, VREL_GE, VREL_GT, VREL_LE, VREL_LT, VREL_NE, VREL_EQ }; @@ -60,7 +58,7 @@ relation_negate (relation_kind r) } // This table is used to swap the operands. op1 REL op2 -> op2 REL op1. -relation_kind rr_swap_table[VREL_LAST + 1] = { +relation_kind rr_swap_table[VREL_LAST] = { VREL_VARYING, VREL_UNDEFINED, VREL_GT, VREL_GE, VREL_LT, VREL_LE, VREL_EQ, VREL_NE }; @@ -74,7 +72,7 @@ relation_swap (relation_kind r) // This table is used to perform an intersection between 2 relations. -relation_kind rr_intersect_table[VREL_LAST + 1][VREL_LAST + 1] = { +relation_kind rr_intersect_table[VREL_LAST][VREL_LAST] = { // VREL_VARYING { VREL_VARYING, VREL_UNDEFINED, VREL_LT, VREL_LE, VREL_GT, VREL_GE, VREL_EQ, VREL_NE }, @@ -112,7 +110,7 @@ relation_intersect (relation_kind r1, relation_kind r2) // This table is used to perform a union between 2 relations. -relation_kind rr_union_table[VREL_LAST + 1][VREL_LAST + 1] = { +relation_kind rr_union_table[VREL_LAST][VREL_LAST] = { // VREL_VARYING { VREL_VARYING, VREL_VARYING, VREL_VARYING, VREL_VARYING, VREL_VARYING, VREL_VARYING, VREL_VARYING, VREL_VARYING }, @@ -150,7 +148,7 @@ relation_union (relation_kind r1, relation_kind r2) // This table is used to determine transitivity between 2 relations. // (A relation0 B) and (B relation1 C) implies (A result C) -relation_kind rr_transitive_table[VREL_LAST + 1][VREL_LAST + 1] = { +relation_kind rr_transitive_table[VREL_LAST][VREL_LAST] = { // VREL_VARYING { VREL_VARYING, VREL_VARYING, VREL_VARYING, VREL_VARYING, VREL_VARYING, VREL_VARYING, VREL_VARYING, VREL_VARYING }, @@ -187,7 +185,7 @@ relation_transitive (relation_kind r1, relation_kind r2) // This vector maps a relation to the equivalent tree code. -tree_code relation_to_code [VREL_LAST + 1] = { +tree_code relation_to_code [VREL_LAST] = { ERROR_MARK, ERROR_MARK, LT_EXPR, LE_EXPR, GT_EXPR, GE_EXPR, EQ_EXPR, NE_EXPR }; @@ -226,7 +224,8 @@ relation_oracle::validate_relation (relation_kind rel, vrange &op1, vrange &op2) // If the relation cannot be folded for any reason, leave as is. Value_Range result (boolean_type_node); - if (!handler.fold_range (result, boolean_type_node, op1, op2, rel)) + if (!handler.fold_range (result, boolean_type_node, op1, op2, + relation_trio::op1_op2 (rel))) return rel; // The expression op1 REL op2 using REL should fold to [1,1]. diff --git a/gcc/value-relation.h b/gcc/value-relation.h index fa9097a8069..027d7416163 100644 --- a/gcc/value-relation.h +++ b/gcc/value-relation.h @@ -35,20 +35,21 @@ along with GCC; see the file COPYING3. If not see // utilizes the relation information to enhance it's range calculations, this // is totally transparent to the client, and they are free to make queries. // -// -// relation_kind is a typedef of enum tree_code, but has restricted range -// and a couple of extra values. +// relation_kind is a new enum which represents the different relations, +// often with a direct mapping to treee codes. ie VREL_EQ is equivalent to +// EQ_EXPR. // // A query is made requesting the relation between SSA1 and SSA@ in a basic // block, or on an edge, the possible return values are: // -// EQ_EXPR, NE_EXPR, LT_EXPR, LE_EXPR, GT_EXPR, and GE_EXPR mean the same. +// VREL_EQ, VREL_NE, VREL_LT, VREL_LE, VREL_GT, and VREL_GE mean the same. // VREL_VARYING : No relation between the 2 names. // VREL_UNDEFINED : Impossible relation (ie, A < B && A > B) // -// The oracle maintains EQ_EXPR relations with equivalency sets, so if a -// relation comes back EQ_EXPR, it is also possible to query the set of -// equivlaencies. These are basically bitmaps over ssa_names. +// The oracle maintains VREL_EQ relations with equivalency sets, so if a +// relation comes back VREL_EQ, it is also possible to query the set of +// equivlaencies. These are basically bitmaps over ssa_names. An iterator is +// provided later for this activity. // // Relations are maintained via the dominace trees and are optimized assuming // they are registered in dominance order. When a new relation is added, it @@ -56,10 +57,8 @@ along with GCC; see the file COPYING3. If not see // and registered at the specified block. -// Rather than introduce a new enumerated type for relations, we can use the -// existing tree_codes for relations, plus add a couple of #defines for -// the other cases. These codes are arranged such that VREL_VARYING is the -// first code, and all the rest are contiguous. +// These codes are arranged such that VREL_VARYING is the first code, and all +// the rest are contiguous. typedef enum relation_kind_t { @@ -74,7 +73,8 @@ typedef enum relation_kind_t VREL_PE8, // 8 bit partial equivalency VREL_PE16, // 16 bit partial equivalency VREL_PE32, // 32 bit partial equivalency - VREL_PE64 // 64 bit partial equivalency + VREL_PE64, // 64 bit partial equivalency + VREL_LAST // terminate, not a real relation. } relation_kind; // General relation kind transformations. @@ -315,6 +315,101 @@ protected: ((equiv_name) = iter.get_name (&equiv_rel)); \ iter.next ()) +// ----------------------------------------------------------------------- + +// Range-ops deals with a LHS and 2 operands. A relation trio is a set of +// 3 potential relations packed into a single unsigned value. +// 1 - LHS relation OP1 +// 2 - LHS relation OP2 +// 3 - OP1 relation OP2 +// VREL_VARYING is a value of 0, and is the default for each position. +class relation_trio +{ +public: + relation_trio (); + relation_trio (relation_kind lhs_op1, relation_kind lhs_op2, + relation_kind op1_op2); + relation_kind lhs_op1 (); + relation_kind lhs_op2 (); + relation_kind op1_op2 (); + relation_trio swap_op1_op2 (); + + static relation_trio lhs_op1 (relation_kind k); + static relation_trio lhs_op2 (relation_kind k); + static relation_trio op1_op2 (relation_kind k); + +protected: + unsigned m_val; +}; + +// Default VREL_VARYING for all 3 relations. +#define TRIO_VARYING relation_trio () + +#define TRIO_SHIFT 4 +#define TRIO_MASK 0x000F + +// These 3 classes are shortcuts for when a caller has a single relation to +// pass as a trio, it can simply construct the appropriate one. The other +// unspecified realtions will be VREL_VARYING. + +inline relation_trio::relation_trio () +{ + STATIC_ASSERT (VREL_LAST <= (1 << TRIO_SHIFT)); + m_val = 0; +} + +inline relation_trio::relation_trio (relation_kind lhs_op1, + relation_kind lhs_op2, + relation_kind op1_op2) +{ + STATIC_ASSERT (VREL_LAST <= (1 << TRIO_SHIFT)); + unsigned i1 = (unsigned) lhs_op1; + unsigned i2 = ((unsigned) lhs_op2) << TRIO_SHIFT; + unsigned i3 = ((unsigned) op1_op2) << (TRIO_SHIFT * 2); + m_val = i1 | i2 | i3; +} + +inline relation_trio +relation_trio::lhs_op1 (relation_kind k) +{ + return relation_trio (k, VREL_VARYING, VREL_VARYING); +} +inline relation_trio +relation_trio::lhs_op2 (relation_kind k) +{ + return relation_trio (VREL_VARYING, k, VREL_VARYING); +} +inline relation_trio +relation_trio::op1_op2 (relation_kind k) +{ + return relation_trio (VREL_VARYING, VREL_VARYING, k); +} + +inline relation_kind +relation_trio::lhs_op1 () +{ + return (relation_kind) (m_val & TRIO_MASK); +} + +inline relation_kind +relation_trio::lhs_op2 () +{ + return (relation_kind) ((m_val >> TRIO_SHIFT) & TRIO_MASK); +} + +inline relation_kind +relation_trio::op1_op2 () +{ + return (relation_kind) ((m_val >> (TRIO_SHIFT * 2)) & TRIO_MASK); +} + +inline relation_trio +relation_trio::swap_op1_op2 () +{ + return relation_trio (lhs_op2 (), lhs_op1 (), relation_swap (op1_op2 ())); +} + +// ----------------------------------------------------------------------- // The value-relation class is used to encapsulate the represention of an // individual relation between 2 ssa-names, and to facilitate operating on -- 2.37.3