From patchwork Sat Jun 10 00:33:44 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Andrew MacLeod X-Patchwork-Id: 1793254 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=8.43.85.97; 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=DaKxaf9f; dkim-atps=neutral Received: from sourceware.org (ip-8-43-85-97.sourceware.org [8.43.85.97]) (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 4QdJqG5lBJz20Wg for ; Sat, 10 Jun 2023 10:34:17 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 2E0073856975 for ; Sat, 10 Jun 2023 00:34:14 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 2E0073856975 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1686357254; bh=v38H3J7A87xRbH4zMkvyi2P/w/oFG5Wc2n6rXs1EpOU=; h=Date:To:Cc:Subject:List-Id:List-Unsubscribe:List-Archive: List-Post:List-Help:List-Subscribe:From:Reply-To:From; b=DaKxaf9fukV3o08MK11GS4Bn6eamUJDMcr6SkFvr9ar45ZXbSPetY60G3n/DlAtIk dPRrbJZLcITF81I6P2d8x869+lqdRMgt/BwjKpIkIM5rIBtQLz/H3xZ2g6DPV0Dq91 mK2OsTxlT/W1S1lL+2awW2q6AgGNjkb5ii26rftY= 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 5747C3858D35 for ; Sat, 10 Jun 2023 00:33:49 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 5747C3858D35 Received: from mail-qk1-f199.google.com (mail-qk1-f199.google.com [209.85.222.199]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-543-Wn-CqTqxP7iIu0UzJaoAYw-1; Fri, 09 Jun 2023 20:33:47 -0400 X-MC-Unique: Wn-CqTqxP7iIu0UzJaoAYw-1 Received: by mail-qk1-f199.google.com with SMTP id af79cd13be357-75d556224e7so298845285a.1 for ; Fri, 09 Jun 2023 17:33:47 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1686357226; x=1688949226; 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=eFxsMJ+NbC8jhc7qO6vP5HbZX+Ly0qgJJoyxBSanjVE=; b=FCzu74eIsSrloVEcr4ZncK7IiZD012o9A0ZpVDwogzAsZCR+eBmaxR0WnNXgWXV/uN ZTBV0PsejKDwnpFNu+zsH9Qt2MnghJwQ4va4IDILbdsEdbG0kK1FGboReJb7lLRIog5e ambaIHdTGspJ0vGL1nmT98k1hoep1tr1val7oSSekEMhgBBUUnmKlk1a6mR8DAGgY3cU mT0J+r7/aUFTtaDXWKZBrKr+aSSK3kQkhRQtukpQQoWokrugaXGJmrb1ss+bfRDaOYNd gBynUokOemvsDNDE0U+XXiWagtGenH9FyXENka24JM3SqdwfI4vjjJo3kf4yxOocGK18 q5sQ== X-Gm-Message-State: AC+VfDxQQgOc22VcLDxcHhZI4hgVkwNUHLGQs9sj0Tl4zGShg/H8/JJt iGY1CpXPqwlxc7FfgeyP7pbpqR/aq+oytHP21ao3bd8jBznWiRzGDAeDnQyboaHI97YssrqiGee fFF72eAOjz8jLJOH8C42xYNK+A2rjj1jJuQeL1uxDFf7SYBWdvZpm1vsw6Nd5p7Qve99Bgrrje1 ZnWw== X-Received: by 2002:a05:620a:2b95:b0:75e:bb5e:3e6a with SMTP id dz21-20020a05620a2b9500b0075ebb5e3e6amr3132206qkb.26.1686357226481; Fri, 09 Jun 2023 17:33:46 -0700 (PDT) X-Google-Smtp-Source: ACHHUZ4OCUH2aMkleQ5cxHXTPnC5+KndVop+Me5RK/41k6bVmEK0reCsgZN5Ak/maDxebGeSBvwk6g== X-Received: by 2002:a05:620a:2b95:b0:75e:bb5e:3e6a with SMTP id dz21-20020a05620a2b9500b0075ebb5e3e6amr3132191qkb.26.1686357226103; Fri, 09 Jun 2023 17:33:46 -0700 (PDT) Received: from ?IPV6:2607:fea8:51df:4200::ca58? ([2607:fea8:51df:4200::ca58]) by smtp.gmail.com with ESMTPSA id n13-20020a05620a152d00b0075ebbd60771sm1367980qkk.84.2023.06.09.17.33.45 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Fri, 09 Jun 2023 17:33:45 -0700 (PDT) Message-ID: Date: Fri, 9 Jun 2023 20:33:44 -0400 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Thunderbird/102.11.0 To: gcc-patches Cc: "hernandez, aldy" Subject: [COMMITTED 1/15] - Provide a unified range-op table. X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Language: en-US X-Spam-Status: No, score=-12.4 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_NONE, TXREP, T_SCC_BODY_TEXT_LINE 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" With all the operators unified under range_operator, I can now start moving them into a unified table rather than have them spread around in various type tables. This patch creates a range_table for the unified operations, and has checks to ensure that if the operator comes from the unified table, it does not exist in any other table.  This is a sanity check for the duration of the transition. This patch also moves all the low hanging fruit opcodes which exist ion only one table directly into the unified table. It also introduced range-op-mixed.h which will contain the class declarations for any "shared" operators so that each implementation file can see the decl.   It also contains the common routines from range-op.h that some of the operators need. With the next patch , I will begin the transition, one opcode at a time, to the unified table.   By doing this in separate commits, we can easily isolate any potential problems that show up... not that I expect any, its fairly mechanical..but just in case. This first set will move all the integer/float shared opcodes into the header file and into the unified table.  The foperator_* classes will be removed and the methods themselves will simply be renamed to implement the unified range_operator method.  The code will remain in range-op-float.cc for those implementations, and the integral versions will remain in range-op.cc. All the patches bootstrap on x86_64-pc-linux-gnu and pass all regressions.  I wont add much more comment for most of them when they are equivalent in functionality.   Pushed. Andrew From df392fbd5d13c944479ed00fcb805e6f26d3fd4b Mon Sep 17 00:00:00 2001 From: Andrew MacLeod Date: Fri, 9 Jun 2023 12:58:57 -0400 Subject: [PATCH 01/31] Provide a unified range-op table. Create a table to prepare for unifying all operations into a single table. Move any operators which only occur in one table to the approriate initialization routine. Provide a mixed header file for range-ops with multiple categories. * range-op-float.cc (class float_table): Move to header. (float_table::float_table): Move float only operators to... (range_op_table::initialize_float_ops): Here. * range-op-mixed.h: New. * range-op.cc (integral_tree_table, pointer_tree_table): Moved to top of file. (float_tree_table): Moved from range-op-float.cc. (unified_tree_table): New. (unified_table::unified_table): New. Call initialize routines. (get_op_handler): Check unified table first. (range_op_handler::range_op_handler): Handle no type constructor. (integral_table::integral_table): Move integral only operators to... (range_op_table::initialize_integral_ops): Here. (pointer_table::pointer_table): Move pointer only operators to... (range_op_table::initialize_pointer_ops): Here. * range-op.h (enum bool_range_state): Move to range-op-mixed.h. (get_bool_state): Ditto. (empty_range_varying): Ditto. (relop_early_resolve): Ditto. (class range_op_table): Add new init methods for range types. (class integral_table): Move declaration to here. (class pointer_table): Move declaration to here. (class float_table): Move declaration to here. --- gcc/range-op-float.cc | 29 +++++++------- gcc/range-op-mixed.h | 78 +++++++++++++++++++++++++++++++++++++ gcc/range-op.cc | 89 +++++++++++++++++++++++++++++-------------- gcc/range-op.h | 89 ++++++++++++++++--------------------------- 4 files changed, 185 insertions(+), 100 deletions(-) create mode 100644 gcc/range-op-mixed.h diff --git a/gcc/range-op-float.cc b/gcc/range-op-float.cc index bb10accd78f..8659217659c 100644 --- a/gcc/range-op-float.cc +++ b/gcc/range-op-float.cc @@ -45,6 +45,7 @@ along with GCC; see the file COPYING3. If not see #include "wide-int.h" #include "value-relation.h" #include "range-op.h" +#include "range-op-mixed.h" // Default definitions for floating point operators. @@ -2807,15 +2808,6 @@ private: } } fop_div; -// Instantiate a range_op_table for floating point operations. -class float_table : public range_op_table -{ - public: - float_table (); -} global_floating_table; - -// Pointer to the float table so the dispatch code can access it. -range_op_table *floating_tree_table = &global_floating_table; float_table::float_table () { @@ -2833,6 +2825,19 @@ float_table::float_table () set (LE_EXPR, fop_le); set (GT_EXPR, fop_gt); set (GE_EXPR, fop_ge); + + set (ABS_EXPR, fop_abs); + set (NEGATE_EXPR, fop_negate); + set (PLUS_EXPR, fop_plus); + set (MINUS_EXPR, fop_minus); + set (MULT_EXPR, fop_mult); +} + +// Initialize any pointer operators to the primary table + +void +range_op_table::initialize_float_ops () +{ set (UNLE_EXPR, fop_unordered_le); set (UNLT_EXPR, fop_unordered_lt); set (UNGE_EXPR, fop_unordered_ge); @@ -2841,12 +2846,6 @@ float_table::float_table () set (ORDERED_EXPR, fop_ordered); set (UNORDERED_EXPR, fop_unordered); set (LTGT_EXPR, fop_ltgt); - - set (ABS_EXPR, fop_abs); - set (NEGATE_EXPR, fop_negate); - set (PLUS_EXPR, fop_plus); - set (MINUS_EXPR, fop_minus); - set (MULT_EXPR, fop_mult); set (RDIV_EXPR, fop_div); } diff --git a/gcc/range-op-mixed.h b/gcc/range-op-mixed.h new file mode 100644 index 00000000000..a78bc2ba59c --- /dev/null +++ b/gcc/range-op-mixed.h @@ -0,0 +1,78 @@ +/* Header file for mixed range operator class. + Copyright (C) 2017-2023 Free Software Foundation, Inc. + Contributed by Andrew MacLeod + and Aldy Hernandez . + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +. */ + +#ifndef GCC_RANGE_OP_MIXED_H +#define GCC_RANGE_OP_MIXED_H + +enum bool_range_state { BRS_FALSE, BRS_TRUE, BRS_EMPTY, BRS_FULL }; +bool_range_state get_bool_state (vrange &r, const vrange &lhs, tree val_type); + +// If the range of either op1 or op2 is undefined, set the result to +// varying and return TRUE. If the caller truly cares about a result, +// they should pass in a varying if it has an undefined that it wants +// treated as a varying. + +inline bool +empty_range_varying (vrange &r, tree type, + const vrange &op1, const vrange & op2) +{ + if (op1.undefined_p () || op2.undefined_p ()) + { + r.set_varying (type); + return true; + } + else + return false; +} + +// For relation opcodes, first try to see if the supplied relation +// forces a true or false result, and return that. +// Then check for undefined operands. If none of this applies, +// return false. + +inline bool +relop_early_resolve (irange &r, tree type, const vrange &op1, + 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) + { + r = range_true (type); + return true; + } + + // If known relation has no subset of this relation, always false. + if (relation_intersect (rel, my_rel) == VREL_UNDEFINED) + { + r = range_false (type); + return true; + } + + // If either operand is undefined, return VARYING. + if (empty_range_varying (r, type, op1, op2)) + return true; + + return false; +} + +#endif // GCC_RANGE_OP_MIXED_H diff --git a/gcc/range-op.cc b/gcc/range-op.cc index 44a95b20ffa..4e00c9f439e 100644 --- a/gcc/range-op.cc +++ b/gcc/range-op.cc @@ -47,36 +47,48 @@ along with GCC; see the file COPYING3. If not see #include "value-relation.h" #include "range-op.h" #include "tree-ssa-ccp.h" +#include "range-op-mixed.h" -// Instantiate a range op table for integral operations. +integral_table integral_tree_table; +pointer_table pointer_tree_table; +float_table float_tree_table; -class integral_table : public range_op_table +// Instantiate a range_op_table for unified operations. +class unified_table : public range_op_table { -public: - integral_table (); -} integral_tree_table; + public: + unified_table (); +} unified_tree_table; -// Instantiate a range op table for pointer operations. +// Invoke the initialization routines for each class of range. -class pointer_table : public range_op_table +unified_table::unified_table () { -public: - pointer_table (); -} pointer_tree_table; - + initialize_integral_ops (); + initialize_pointer_ops (); + initialize_float_ops (); +} // The tables are hidden and accessed via a simple extern function. range_operator * get_op_handler (enum tree_code code, tree type) { - // First check if there is a pointer specialization. + if (unified_tree_table[code]) + { + // Should not be in any other table if it is in the unified table. + gcc_checking_assert (!pointer_tree_table[code]); + gcc_checking_assert (!integral_tree_table[code]); + gcc_checking_assert (!float_tree_table[code]); + return unified_tree_table[code]; + } + if (POINTER_TYPE_P (type)) return pointer_tree_table[code]; if (INTEGRAL_TYPE_P (type)) return integral_tree_table[code]; if (frange::supports_p (type)) - return (*floating_tree_table)[code]; + return float_tree_table[code]; return NULL; } @@ -96,6 +108,13 @@ range_op_handler::range_op_handler (tree_code code, tree type) set_op_handler (code, type); } +// Constructing without a type must come from the unified table. + +range_op_handler::range_op_handler (tree_code code) +{ + m_operator = unified_tree_table[code]; +} + // Create a dispatch pattern for value range discriminators LHS, OP1, and OP2. // This is used to produce a unique value for each dispatch pattern. Shift // values are based on the size of the m_discriminator field in value_range.h. @@ -4875,6 +4894,26 @@ integral_table::integral_table () set (MIN_EXPR, op_min); set (MAX_EXPR, op_max); set (MULT_EXPR, op_mult); + set (NOP_EXPR, op_cast); + set (CONVERT_EXPR, op_cast); + set (BIT_AND_EXPR, op_bitwise_and); + set (BIT_IOR_EXPR, op_bitwise_or); + set (BIT_XOR_EXPR, op_bitwise_xor); + set (BIT_NOT_EXPR, op_bitwise_not); + set (INTEGER_CST, op_integer_cst); + set (SSA_NAME, op_ident); + set (PAREN_EXPR, op_ident); + set (OBJ_TYPE_REF, op_ident); + set (ABS_EXPR, op_abs); + set (NEGATE_EXPR, op_negate); + set (ADDR_EXPR, op_addr); +} + +// Initialize any integral operators to the primary table + +void +range_op_table::initialize_integral_ops () +{ set (TRUNC_DIV_EXPR, op_trunc_div); set (FLOOR_DIV_EXPR, op_floor_div); set (ROUND_DIV_EXPR, op_round_div); @@ -4882,27 +4921,13 @@ integral_table::integral_table () set (EXACT_DIV_EXPR, op_exact_div); set (LSHIFT_EXPR, op_lshift); set (RSHIFT_EXPR, op_rshift); - set (NOP_EXPR, op_cast); - set (CONVERT_EXPR, op_cast); set (TRUTH_AND_EXPR, op_logical_and); - set (BIT_AND_EXPR, op_bitwise_and); set (TRUTH_OR_EXPR, op_logical_or); - set (BIT_IOR_EXPR, op_bitwise_or); - set (BIT_XOR_EXPR, op_bitwise_xor); set (TRUNC_MOD_EXPR, op_trunc_mod); set (TRUTH_NOT_EXPR, op_logical_not); - set (BIT_NOT_EXPR, op_bitwise_not); - set (INTEGER_CST, op_integer_cst); - set (SSA_NAME, op_ident); - set (PAREN_EXPR, op_ident); - set (OBJ_TYPE_REF, op_ident); set (IMAGPART_EXPR, op_unknown); set (REALPART_EXPR, op_unknown); - set (POINTER_DIFF_EXPR, op_pointer_diff); - set (ABS_EXPR, op_abs); set (ABSU_EXPR, op_absu); - set (NEGATE_EXPR, op_negate); - set (ADDR_EXPR, op_addr); } pointer_table::pointer_table () @@ -4911,7 +4936,6 @@ pointer_table::pointer_table () set (BIT_IOR_EXPR, op_pointer_or); set (MIN_EXPR, op_ptr_min_max); set (MAX_EXPR, op_ptr_min_max); - set (POINTER_PLUS_EXPR, op_pointer_plus); set (EQ_EXPR, op_equal); set (NE_EXPR, op_not_equal); @@ -4929,6 +4953,15 @@ pointer_table::pointer_table () set (BIT_XOR_EXPR, op_bitwise_xor); } +// Initialize any pointer operators to the primary table + +void +range_op_table::initialize_pointer_ops () +{ + set (POINTER_PLUS_EXPR, op_pointer_plus); + set (POINTER_DIFF_EXPR, op_pointer_diff); +} + #if CHECKING_P #include "selftest.h" diff --git a/gcc/range-op.h b/gcc/range-op.h index 2abec3299ef..0721d4a302d 100644 --- a/gcc/range-op.h +++ b/gcc/range-op.h @@ -186,6 +186,7 @@ class range_op_handler public: range_op_handler (); range_op_handler (enum tree_code code, tree type); + range_op_handler (enum tree_code code); inline operator bool () const { return m_operator != NULL; } bool fold_range (vrange &r, tree type, @@ -272,69 +273,18 @@ relation_kind le_op1_op2_relation (const irange &lhs); relation_kind gt_op1_op2_relation (const irange &lhs); relation_kind ge_op1_op2_relation (const irange &lhs); -enum bool_range_state { BRS_FALSE, BRS_TRUE, BRS_EMPTY, BRS_FULL }; -bool_range_state get_bool_state (vrange &r, const vrange &lhs, tree val_type); - -// If the range of either op1 or op2 is undefined, set the result to -// varying and return TRUE. If the caller truly cares about a result, -// they should pass in a varying if it has an undefined that it wants -// treated as a varying. - -inline bool -empty_range_varying (vrange &r, tree type, - const vrange &op1, const vrange & op2) -{ - if (op1.undefined_p () || op2.undefined_p ()) - { - r.set_varying (type); - return true; - } - else - return false; -} - -// For relation opcodes, first try to see if the supplied relation -// forces a true or false result, and return that. -// Then check for undefined operands. If none of this applies, -// return false. - -inline bool -relop_early_resolve (irange &r, tree type, const vrange &op1, - 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) - { - r = range_true (type); - return true; - } - - // If known relation has no subset of this relation, always false. - if (relation_intersect (rel, my_rel) == VREL_UNDEFINED) - { - r = range_false (type); - return true; - } - - // If either operand is undefined, return VARYING. - if (empty_range_varying (r, type, op1, op2)) - return true; - - return false; -} - // This implements the range operator tables as local objects. class range_op_table { public: range_operator *operator[] (enum tree_code code); -protected: void set (enum tree_code code, range_operator &op); -private: +protected: range_operator *m_range_tree[MAX_TREE_CODES]; + void initialize_integral_ops (); + void initialize_pointer_ops (); + void initialize_float_ops (); }; @@ -357,8 +307,33 @@ range_op_table::set (enum tree_code code, range_operator &op) m_range_tree[code] = &op; } -// This holds the range op table for floating point operations. -extern range_op_table *floating_tree_table; +// This holds the range op tables + +class integral_table : public range_op_table +{ +public: + integral_table (); +}; +extern integral_table integral_tree_table; + +// Instantiate a range op table for pointer operations. + +class pointer_table : public range_op_table +{ +public: + pointer_table (); +}; +extern pointer_table pointer_tree_table; + +// Instantiate a range_op_table for floating point operations. +class float_table : public range_op_table +{ + public: + float_table (); +}; +extern float_table float_tree_table; + + extern range_operator *ptr_op_widen_mult_signed; extern range_operator *ptr_op_widen_mult_unsigned; -- 2.40.1