From patchwork Mon May 30 13:27:49 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aldy Hernandez X-Patchwork-Id: 54530 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id A101A38485B5 for ; Mon, 30 May 2022 13:31:42 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org A101A38485B5 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1653917502; bh=t5HH/ucHhGRLOUecMqVWMLNZWyWwEQX5wRtYR9VnJSo=; h=To:Subject:Date:In-Reply-To:References:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=RocufAUz6PkbQ+ESCj/7Kt1y/aePOGhOJ8QZJ9P5AxJQennW8I/oxQ/FwQ5cpw59x R/pMU++bvkS2Zslw3AWSh2TTlHdJ5heHS5qAO+OXE8CCsVKQEPgF+LXFDjTSfMu0Wn Ygqit0ifN/kWNLSbG+Hnla38xuELx1NwKmSvbdEI= 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 1E5EF385E03D for ; Mon, 30 May 2022 13:28:07 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 1E5EF385E03D Received: from mimecast-mx02.redhat.com (mx3-rdu2.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-385-ZG0jmDUAP320dfw9fsxIUg-1; Mon, 30 May 2022 09:28:05 -0400 X-MC-Unique: ZG0jmDUAP320dfw9fsxIUg-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.rdu2.redhat.com [10.11.54.2]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 30CF82919EC5 for ; Mon, 30 May 2022 13:28:05 +0000 (UTC) Received: from abulafia.quesejoda.com (unknown [10.39.194.246]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 84B4240EC002; Mon, 30 May 2022 13:28:04 +0000 (UTC) Received: from abulafia.quesejoda.com (localhost [127.0.0.1]) by abulafia.quesejoda.com (8.17.1/8.17.1) with ESMTPS id 24UDS2T01752182 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Mon, 30 May 2022 15:28:03 +0200 Received: (from aldyh@localhost) by abulafia.quesejoda.com (8.17.1/8.17.1/Submit) id 24UDS22a1752181; Mon, 30 May 2022 15:28:02 +0200 To: GCC patches Subject: [PATCH 3/5] Convert range-op.* to vrange. Date: Mon, 30 May 2022 15:27:49 +0200 Message-Id: <20220530132751.1752112-3-aldyh@redhat.com> In-Reply-To: <20220530132751.1752112-1-aldyh@redhat.com> References: <20220530132751.1752112-1-aldyh@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.11.54.2 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com 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, 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: Aldy Hernandez via Gcc-patches From: Aldy Hernandez Reply-To: Aldy Hernandez Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" This patch provides the infrastructure to make range-ops type agnostic. First, the range_op_handler function has been replaced with an object of the same name. It's coded in such a way to minimize changes to the code base, and to encapsulate the dispatch code. Instead of: range_operator *op = range_op_handler (code, type); if (op) op->fold_range (...); We now do: range_op_handler op (code, type); if (op) op->fold_range (...); I've folded gimple_range_handler into the range_op_handler class, since it's also a query into the range operators. Instead of: range_operator *handler = gimple_range_handler (stmt); We now do: range_op_handler handler (stmt); This all has the added benefit of moving all the dispatch code into an independent class and avoid polluting range_operator (which we'll further split later when frange and prange come live). There's this annoying "using" keyword that's been added to each operator due to hiding rules in C++. The issue is that we will have different virtual versions of fold_range() for each combination of operands. For example: // Traditional binary op on irange's. fold_range (irange &lhs, const irange &op1, const irange &op2); // For POINTER_DIFF_EXPR: fold_range (irange &lhs, const prange &op1, const prange &op2); // Cast from irange to prange. fold_range (prange &lhs, const irange &op1, const irange &op2); Overloading virtuals when there are multiple same named methods causes hidden virtuals warnings from -Woverloaded-virtual, thus the using keyword. An alternative would be to have different names: fold_range_III, fold_range_IPP, fold_range_PII, but that's uglier still. Tested on x86-64 & ppc64le Linux. gcc/ChangeLog: * gimple-range-edge.cc (gimple_outgoing_range_stmt_p): Adjust for vrange and convert range_op_handler function calls to use the identically named object. * gimple-range-fold.cc (gimple_range_operand1): Same. (gimple_range_operand2): Same. (fold_using_range::fold_stmt): Same. (fold_using_range::range_of_range_op): Same. (fold_using_range::range_of_builtin_ubsan_call): Same. (fold_using_range::relation_fold_and_or): Same. (fur_source::register_outgoing_edges): Same. * gimple-range-fold.h (gimple_range_handler): Remove. * gimple-range-gori.cc (gimple_range_calc_op1): Adjust for vrange. (gimple_range_calc_op2): Same. (range_def_chain::get_def_chain): Same. (gori_compute::compute_operand_range): Same. (gori_compute::condexpr_adjust): Same. * gimple-range.cc (gimple_ranger::prefill_name): Same. (gimple_ranger::prefill_stmt_dependencies): Same. * range-op.cc (get_bool_state): Same. (class operator_equal): Add using clause. (class operator_not_equal): Same. (class operator_lt): Same. (class operator_le): Same. (class operator_gt): Same. (class operator_ge): Same. (class operator_plus): Same. (class operator_minus): Same. (class operator_mult): Same. (class operator_exact_divide): Same. (class operator_lshift): Same. (class operator_rshift): Same. (class operator_cast): Same. (class operator_logical_and): Same. (class operator_bitwise_and): Same. (class operator_logical_or): Same. (class operator_bitwise_or): Same. (class operator_bitwise_xor): Same. (class operator_trunc_mod): Same. (class operator_logical_not): Same. (class operator_bitwise_not): Same. (class operator_cst): Same. (class operator_identity): Same. (class operator_unknown): Same. (class operator_abs): Same. (class operator_negate): Same. (class operator_addr_expr): Same. (class pointer_or_operator): Same. (operator_plus::op1_range): Adjust for vrange. (operator_minus::op1_range): Same. (operator_mult::op1_range): Same. (operator_cast::op1_range): Same. (operator_bitwise_not::fold_range): Same. (operator_negate::fold_range): Same. (range_op_handler): Rename to... (get_handler): ...this. (range_op_handler::range_op_handler): New. (range_op_handler::fold_range): New. (range_op_handler::op1_range): New. (range_op_handler::op2_range): New. (range_op_handler::lhs_op1_relation): New. (range_op_handler::lhs_op2_relation): New. (range_op_handler::op1_op2_relation): New. (range_cast): Adjust for vrange. * range-op.h (range_op_handler): Remove function. (range_cast): Adjust for vrange. (class range_op_handler): New. (get_bool_state): Adjust for vrange. (empty_range_varying): Same. (relop_early_resolve): Same. * tree-data-ref.cc (compute_distributive_range): Same. * tree-vrp.cc (get_range_op_handler): Remove. (range_fold_binary_symbolics_p): Use range_op_handler class instead of get_range_op_handler. (range_fold_unary_symbolics_p): Same. (range_fold_binary_expr): Same. (range_fold_unary_expr): Same. * value-query.cc (range_query::get_tree_range): Adjust for vrange. --- gcc/gimple-range-edge.cc | 2 +- gcc/gimple-range-fold.cc | 43 ++++---- gcc/gimple-range-fold.h | 15 --- gcc/gimple-range-gori.cc | 41 ++++---- gcc/gimple-range.cc | 6 +- gcc/range-op.cc | 215 ++++++++++++++++++++++++++++++++++----- gcc/range-op.h | 45 ++++++-- gcc/tree-data-ref.cc | 8 +- gcc/tree-vrp.cc | 44 ++++---- gcc/value-query.cc | 8 +- 10 files changed, 303 insertions(+), 124 deletions(-) diff --git a/gcc/gimple-range-edge.cc b/gcc/gimple-range-edge.cc index 0bee38ba770..5bbe23ae03d 100644 --- a/gcc/gimple-range-edge.cc +++ b/gcc/gimple-range-edge.cc @@ -42,7 +42,7 @@ gimple_outgoing_range_stmt_p (basic_block bb) if (!gsi_end_p (gsi)) { gimple *s = gsi_stmt (gsi); - if (is_a (s) && gimple_range_handler (s)) + if (is_a (s) && range_op_handler (s)) return gsi_stmt (gsi); gswitch *sw = dyn_cast (s); if (sw && irange::supports_type_p (TREE_TYPE (gimple_switch_index (sw)))) diff --git a/gcc/gimple-range-fold.cc b/gcc/gimple-range-fold.cc index 0a947c16c58..c53d2863d5e 100644 --- a/gcc/gimple-range-fold.cc +++ b/gcc/gimple-range-fold.cc @@ -482,7 +482,7 @@ gimple_range_base_of_assignment (const gimple *stmt) tree gimple_range_operand1 (const gimple *stmt) { - gcc_checking_assert (gimple_range_handler (stmt)); + gcc_checking_assert (range_op_handler (stmt)); switch (gimple_code (stmt)) { @@ -515,7 +515,7 @@ gimple_range_operand1 (const gimple *stmt) tree gimple_range_operand2 (const gimple *stmt) { - gcc_checking_assert (gimple_range_handler (stmt)); + gcc_checking_assert (range_op_handler (stmt)); switch (gimple_code (stmt)) { @@ -551,7 +551,7 @@ fold_using_range::fold_stmt (irange &r, gimple *s, fur_source &src, tree name) && gimple_assign_rhs_code (s) == ADDR_EXPR) return range_of_address (r, s, src); - if (gimple_range_handler (s)) + if (range_op_handler (s)) res = range_of_range_op (r, s, src); else if (is_a(s)) res = range_of_phi (r, as_a (s), src); @@ -593,7 +593,7 @@ fold_using_range::range_of_range_op (irange &r, gimple *s, fur_source &src) tree type = gimple_range_type (s); if (!type) return false; - range_operator *handler = gimple_range_handler (s); + range_op_handler handler (s); gcc_checking_assert (handler); tree lhs = gimple_get_lhs (s); @@ -606,13 +606,13 @@ fold_using_range::range_of_range_op (irange &r, gimple *s, fur_source &src) { // Fold range, and register any dependency if available. int_range<2> r2 (type); - handler->fold_range (r, type, range1, r2); + handler.fold_range (r, type, range1, r2); if (lhs && gimple_range_ssa_p (op1)) { if (src.gori ()) src.gori ()->register_dependency (lhs, op1); relation_kind rel; - rel = handler->lhs_op1_relation (r, range1, range1); + rel = handler.lhs_op1_relation (r, range1, range1); if (rel != VREL_VARYING) src.register_relation (s, rel, lhs, op1); } @@ -629,7 +629,7 @@ fold_using_range::range_of_range_op (irange &r, gimple *s, fur_source &src) fputc ('\n', dump_file); } // Fold range, and register any dependency if available. - handler->fold_range (r, type, range1, range2, rel); + handler.fold_range (r, type, range1, range2, rel); relation_fold_and_or (r, s, src); if (lhs) { @@ -640,13 +640,13 @@ fold_using_range::range_of_range_op (irange &r, gimple *s, fur_source &src) } if (gimple_range_ssa_p (op1)) { - rel = handler->lhs_op1_relation (r, range1, range2, rel); + rel = handler.lhs_op1_relation (r, range1, range2, rel); if (rel != VREL_VARYING) src.register_relation (s, rel, lhs, op1); } 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); } @@ -921,7 +921,7 @@ fold_using_range::range_of_builtin_ubsan_call (irange &r, gcall *call, gcc_checking_assert (code == PLUS_EXPR || code == MINUS_EXPR || code == MULT_EXPR); tree type = gimple_range_type (call); - range_operator *op = range_op_handler (code, type); + range_op_handler op (code, type); gcc_checking_assert (op); int_range_max ir0, ir1; tree arg0 = gimple_call_arg (call, 0); @@ -935,7 +935,7 @@ fold_using_range::range_of_builtin_ubsan_call (irange &r, gcall *call, // Pretend the arithmetic is wrapping. If there is any overflow, // we'll complain, but will actually do wrapping operation. flag_wrapv = 1; - op->fold_range (r, type, ir0, ir1, relation); + op.fold_range (r, type, ir0, ir1, relation); flag_wrapv = saved_flag_wrapv; // If for both arguments vrp_valueize returned non-NULL, this should @@ -1391,8 +1391,8 @@ fold_using_range::relation_fold_and_or (irange& lhs_range, gimple *s, else if (ssa1_dep1 != ssa2_dep2 || ssa1_dep2 != ssa2_dep1) return; - range_operator *handler1 = gimple_range_handler (SSA_NAME_DEF_STMT (ssa1)); - range_operator *handler2 = gimple_range_handler (SSA_NAME_DEF_STMT (ssa2)); + range_op_handler handler1 (SSA_NAME_DEF_STMT (ssa1)); + range_op_handler handler2 (SSA_NAME_DEF_STMT (ssa2)); // If either handler is not present, no relation is found. if (!handler1 || !handler2) @@ -1400,8 +1400,8 @@ fold_using_range::relation_fold_and_or (irange& lhs_range, gimple *s, int_range<2> bool_one (boolean_true_node, boolean_true_node); - relation_kind relation1 = handler1->op1_op2_relation (bool_one); - relation_kind relation2 = handler2->op1_op2_relation (bool_one); + relation_kind relation1 = handler1.op1_op2_relation (bool_one); + relation_kind relation2 = handler2.op1_op2_relation (bool_one); if (relation1 == VREL_VARYING || relation2 == VREL_VARYING) return; @@ -1441,7 +1441,6 @@ fur_source::register_outgoing_edges (gcond *s, irange &lhs_range, edge e0, edge int_range_max r; int_range<2> e0_range, e1_range; tree name; - range_operator *handler; basic_block bb = gimple_bb (s); if (e0) @@ -1472,17 +1471,17 @@ fur_source::register_outgoing_edges (gcond *s, irange &lhs_range, edge e0, edge tree ssa2 = gimple_range_ssa_p (gimple_range_operand2 (s)); if (ssa1 && ssa2) { - handler = gimple_range_handler (s); + range_op_handler handler (s); gcc_checking_assert (handler); if (e0) { - relation_kind relation = handler->op1_op2_relation (e0_range); + relation_kind relation = handler.op1_op2_relation (e0_range); if (relation != VREL_VARYING) register_relation (e0, relation, ssa1, ssa2); } if (e1) { - relation_kind relation = handler->op1_op2_relation (e1_range); + relation_kind relation = handler.op1_op2_relation (e1_range); if (relation != VREL_VARYING) register_relation (e1, relation, ssa1, ssa2); } @@ -1501,7 +1500,7 @@ fur_source::register_outgoing_edges (gcond *s, irange &lhs_range, edge e0, edge if (TREE_CODE (TREE_TYPE (name)) != BOOLEAN_TYPE) continue; gimple *stmt = SSA_NAME_DEF_STMT (name); - handler = gimple_range_handler (stmt); + range_op_handler handler (stmt); if (!handler) continue; tree ssa1 = gimple_range_ssa_p (gimple_range_operand1 (stmt)); @@ -1511,14 +1510,14 @@ fur_source::register_outgoing_edges (gcond *s, irange &lhs_range, edge e0, edge if (e0 && gori ()->outgoing_edge_range_p (r, e0, name, *m_query) && r.singleton_p ()) { - relation_kind relation = handler->op1_op2_relation (r); + relation_kind relation = handler.op1_op2_relation (r); if (relation != VREL_VARYING) register_relation (e0, relation, ssa1, ssa2); } if (e1 && gori ()->outgoing_edge_range_p (r, e1, name, *m_query) && r.singleton_p ()) { - relation_kind relation = handler->op1_op2_relation (r); + relation_kind relation = handler.op1_op2_relation (r); if (relation != VREL_VARYING) register_relation (e1, relation, ssa1, ssa2); } diff --git a/gcc/gimple-range-fold.h b/gcc/gimple-range-fold.h index 20cb73dabb9..4b5d4b6e0b8 100644 --- a/gcc/gimple-range-fold.h +++ b/gcc/gimple-range-fold.h @@ -41,21 +41,6 @@ bool fold_range (irange &r, gimple *s, irange &r1); bool fold_range (irange &r, gimple *s, irange &r1, irange &r2); bool fold_range (irange &r, gimple *s, unsigned num_elements, irange *vector); -// Return the range_operator pointer for this statement. This routine -// can also be used to gate whether a routine is range-ops enabled. - -static inline range_operator * -gimple_range_handler (const gimple *s) -{ - if (const gassign *ass = dyn_cast (s)) - return range_op_handler (gimple_assign_rhs_code (ass), - TREE_TYPE (gimple_assign_lhs (ass))); - if (const gcond *cond = dyn_cast (s)) - return range_op_handler (gimple_cond_code (cond), - TREE_TYPE (gimple_cond_lhs (cond))); - return NULL; -} - // Return the type of range which statement S calculates. If the type is // unsupported or no type can be determined, return NULL_TREE. diff --git a/gcc/gimple-range-gori.cc b/gcc/gimple-range-gori.cc index 3e15eb5192d..0e0cf2128e7 100644 --- a/gcc/gimple-range-gori.cc +++ b/gcc/gimple-range-gori.cc @@ -44,9 +44,9 @@ gimple_range_calc_op1 (irange &r, const gimple *stmt, const irange &lhs_range) // Unary operations require the type of the first operand in the // second range position. tree type = TREE_TYPE (gimple_range_operand1 (stmt)); - int_range<2> type_range (type); - return gimple_range_handler (stmt)->op1_range (r, type, lhs_range, - type_range); + tmp_range type_range (type); + type_range.set_varying (type); + return range_op_handler (stmt).op1_range (r, type, lhs_range, type_range); } // Calculate what we can determine of the range of this statement's @@ -72,12 +72,12 @@ gimple_range_calc_op1 (irange &r, const gimple *stmt, // This is sometimes invoked on single operand stmts. if (gimple_num_ops (stmt) < 3) return false; - int_range<2> trange (TREE_TYPE (gimple_range_operand2 (stmt))); - return gimple_range_handler (stmt)->op1_range (r, type, lhs_range, - trange); + tree op2_type = TREE_TYPE (gimple_range_operand2 (stmt)); + tmp_range trange (op2_type); + trange.set_varying (op2_type); + return range_op_handler (stmt).op1_range (r, type, lhs_range, trange); } - return gimple_range_handler (stmt)->op1_range (r, type, lhs_range, - op2_range); + return range_op_handler (stmt).op1_range (r, type, lhs_range, op2_range); } // Calculate what we can determine of the range of this statement's @@ -97,12 +97,13 @@ gimple_range_calc_op2 (irange &r, const gimple *stmt, // If op1 is undefined, solve as if it is varying. if (op1_range.undefined_p ()) { - int_range<2> trange (TREE_TYPE (gimple_range_operand1 (stmt))); - return gimple_range_handler (stmt)->op2_range (r, type, lhs_range, - trange); + tree op1_type = TREE_TYPE (gimple_range_operand1 (stmt)); + tmp_range trange (op1_type); + trange.set_varying (op1_type); + return range_op_handler (stmt).op2_range (r, type, lhs_range, trange); } - return gimple_range_handler (stmt)->op2_range (r, type, lhs_range, - op1_range); + return range_op_handler (stmt).op2_range (r, type, lhs_range, + op1_range); } // Return TRUE if GS is a logical && or || expression. @@ -346,7 +347,7 @@ range_def_chain::get_def_chain (tree name) } gimple *stmt = SSA_NAME_DEF_STMT (name); - if (gimple_range_handler (stmt)) + if (range_op_handler (stmt)) { ssa1 = gimple_range_ssa_p (gimple_range_operand1 (stmt)); ssa2 = gimple_range_ssa_p (gimple_range_operand2 (stmt)); @@ -707,7 +708,7 @@ gori_compute::compute_operand_range (irange &r, gimple *stmt, if (is_a (stmt)) return compute_operand_range_switch (r, as_a (stmt), lhs, name, src); - if (!gimple_range_handler (stmt)) + if (!range_op_handler (stmt)) return false; tree op1 = gimple_range_ssa_p (gimple_range_operand1 (stmt)); @@ -1328,7 +1329,7 @@ gori_compute::condexpr_adjust (irange &r1, irange &r2, gimple *, tree cond, tree type = TREE_TYPE (gimple_assign_rhs1 (cond_def)); if (!range_compatible_p (type, TREE_TYPE (gimple_assign_rhs2 (cond_def)))) return false; - range_operator *hand = range_op_handler (gimple_assign_rhs_code (cond_def), type); + range_op_handler hand (gimple_assign_rhs_code (cond_def), type); if (!hand) return false; @@ -1351,18 +1352,18 @@ gori_compute::condexpr_adjust (irange &r1, irange &r2, gimple *, tree cond, // the op1 or op2 routines based on its location. if (c1) { - if (!hand->op1_range (cond_false, type, m_bool_zero, cr)) + if (!hand.op1_range (cond_false, type, m_bool_zero, cr)) return false; - if (!hand->op1_range (cond_true, type, m_bool_one, cr)) + if (!hand.op1_range (cond_true, type, m_bool_one, cr)) return false; cond_false.intersect (cl); cond_true.intersect (cl); } else { - if (!hand->op2_range (cond_false, type, m_bool_zero, cl)) + if (!hand.op2_range (cond_false, type, m_bool_zero, cl)) return false; - if (!hand->op2_range (cond_true, type, m_bool_one, cl)) + if (!hand.op2_range (cond_true, type, m_bool_one, cl)) return false; cond_false.intersect (cr); cond_true.intersect (cr); diff --git a/gcc/gimple-range.cc b/gcc/gimple-range.cc index f5e9e77bc71..32d57c9e3db 100644 --- a/gcc/gimple-range.cc +++ b/gcc/gimple-range.cc @@ -339,7 +339,7 @@ gimple_ranger::prefill_name (irange &r, tree name) if (!gimple_range_ssa_p (name)) return; gimple *stmt = SSA_NAME_DEF_STMT (name); - if (!gimple_range_handler (stmt) && !is_a (stmt)) + if (!range_op_handler (stmt) && !is_a (stmt)) return; bool current; @@ -363,7 +363,7 @@ gimple_ranger::prefill_stmt_dependencies (tree ssa) gcc_checking_assert (stmt && gimple_bb (stmt)); // Only pre-process range-ops and phis. - if (!gimple_range_handler (stmt) && !is_a (stmt)) + if (!range_op_handler (stmt) && !is_a (stmt)) return; // Mark where on the stack we are starting. @@ -419,7 +419,7 @@ gimple_ranger::prefill_stmt_dependencies (tree ssa) } else { - gcc_checking_assert (gimple_range_handler (stmt)); + gcc_checking_assert (range_op_handler (stmt)); tree op = gimple_range_operand2 (stmt); if (op) prefill_name (r, op); diff --git a/gcc/range-op.cc b/gcc/range-op.cc index c88da8caa6c..6f6d2da573a 100644 --- a/gcc/range-op.cc +++ b/gcc/range-op.cc @@ -420,7 +420,7 @@ create_possibly_reversed_range (irange &r, tree type, // return the equivalent range for TYPE in R; if FALSE/TRUE, do nothing. bool_range_state -get_bool_state (irange &r, const irange &lhs, tree val_type) +get_bool_state (vrange &r, const vrange &lhs, tree val_type) { // If there is no result, then this is unexecutable. if (lhs.undefined_p ()) @@ -446,6 +446,9 @@ get_bool_state (irange &r, const irange &lhs, tree val_type) class operator_equal : public range_operator { + using range_operator::fold_range; + using range_operator::op1_range; + using range_operator::op2_range; public: virtual bool fold_range (irange &r, tree type, const irange &op1, @@ -562,6 +565,9 @@ operator_equal::op2_range (irange &r, tree type, class operator_not_equal : public range_operator { + using range_operator::fold_range; + using range_operator::op1_range; + using range_operator::op2_range; public: virtual bool fold_range (irange &r, tree type, const irange &op1, @@ -738,6 +744,9 @@ build_ge (irange &r, tree type, const wide_int &val) class operator_lt : public range_operator { + using range_operator::fold_range; + using range_operator::op1_range; + using range_operator::op2_range; public: virtual bool fold_range (irange &r, tree type, const irange &op1, @@ -846,6 +855,9 @@ operator_lt::op2_range (irange &r, tree type, class operator_le : public range_operator { + using range_operator::fold_range; + using range_operator::op1_range; + using range_operator::op2_range; public: virtual bool fold_range (irange &r, tree type, const irange &op1, @@ -954,6 +966,9 @@ operator_le::op2_range (irange &r, tree type, class operator_gt : public range_operator { + using range_operator::fold_range; + using range_operator::op1_range; + using range_operator::op2_range; public: virtual bool fold_range (irange &r, tree type, const irange &op1, @@ -1061,6 +1076,9 @@ operator_gt::op2_range (irange &r, tree type, class operator_ge : public range_operator { + using range_operator::fold_range; + using range_operator::op1_range; + using range_operator::op2_range; public: virtual bool fold_range (irange &r, tree type, const irange &op1, @@ -1169,6 +1187,10 @@ operator_ge::op2_range (irange &r, tree type, class operator_plus : public range_operator { + using range_operator::op1_range; + using range_operator::op2_range; + using range_operator::lhs_op1_relation; + using range_operator::lhs_op2_relation; public: virtual bool op1_range (irange &r, tree type, const irange &lhs, @@ -1286,7 +1308,7 @@ operator_plus::op1_range (irange &r, tree type, const irange &op2, relation_kind rel ATTRIBUTE_UNUSED) const { - return range_op_handler (MINUS_EXPR, type)->fold_range (r, type, lhs, op2); + return range_op_handler (MINUS_EXPR, type).fold_range (r, type, lhs, op2); } bool @@ -1295,12 +1317,15 @@ operator_plus::op2_range (irange &r, tree type, const irange &op1, relation_kind rel ATTRIBUTE_UNUSED) const { - return range_op_handler (MINUS_EXPR, type)->fold_range (r, type, lhs, op1); + return range_op_handler (MINUS_EXPR, type).fold_range (r, type, lhs, op1); } class operator_minus : public range_operator { + using range_operator::fold_range; + using range_operator::op1_range; + using range_operator::op2_range; public: virtual bool op1_range (irange &r, tree type, const irange &lhs, @@ -1445,7 +1470,7 @@ operator_minus::op1_range (irange &r, tree type, const irange &op2, relation_kind rel ATTRIBUTE_UNUSED) const { - return range_op_handler (PLUS_EXPR, type)->fold_range (r, type, lhs, op2); + return range_op_handler (PLUS_EXPR, type).fold_range (r, type, lhs, op2); } bool @@ -1597,6 +1622,8 @@ cross_product_operator::wi_cross_product (irange &r, tree type, class operator_mult : public cross_product_operator { + using range_operator::op1_range; + using range_operator::op2_range; public: virtual void wi_fold (irange &r, tree type, const wide_int &lh_lb, @@ -1629,8 +1656,8 @@ operator_mult::op1_range (irange &r, tree type, return false; if (op2.singleton_p (&offset) && !integer_zerop (offset)) - return range_op_handler (TRUNC_DIV_EXPR, type)->fold_range (r, type, - lhs, op2); + return range_op_handler (TRUNC_DIV_EXPR, type).fold_range (r, type, + lhs, op2); return false; } @@ -1857,6 +1884,7 @@ operator_div op_ceil_div (CEIL_DIV_EXPR); class operator_exact_divide : public operator_div { + using range_operator::op1_range; public: operator_exact_divide () : operator_div (TRUNC_DIV_EXPR) { } virtual bool op1_range (irange &r, tree type, @@ -1881,13 +1909,15 @@ operator_exact_divide::op1_range (irange &r, tree type, // If op2 is a multiple of 2, we would be able to set some non-zero bits. if (op2.singleton_p (&offset) && !integer_zerop (offset)) - return range_op_handler (MULT_EXPR, type)->fold_range (r, type, lhs, op2); + return range_op_handler (MULT_EXPR, type).fold_range (r, type, lhs, op2); return false; } class operator_lshift : public cross_product_operator { + using range_operator::fold_range; + using range_operator::op1_range; public: virtual bool op1_range (irange &r, tree type, const irange &lhs, @@ -1909,6 +1939,9 @@ public: class operator_rshift : public cross_product_operator { + using range_operator::fold_range; + using range_operator::op1_range; + using range_operator::lhs_op1_relation; public: virtual bool fold_range (irange &r, tree type, const irange &op1, @@ -2248,6 +2281,8 @@ operator_rshift::wi_fold (irange &r, tree type, class operator_cast: public range_operator { + using range_operator::fold_range; + using range_operator::op1_range; public: virtual bool fold_range (irange &r, tree type, const irange &op1, @@ -2417,10 +2452,9 @@ operator_cast::op1_range (irange &r, tree type, // Add this to the unsigned LHS range(s). int_range_max lim_range (type, lim, lim); int_range_max lhs_neg; - range_op_handler (PLUS_EXPR, type)->fold_range (lhs_neg, - type, - converted_lhs, - lim_range); + range_op_handler (PLUS_EXPR, type).fold_range (lhs_neg, type, + converted_lhs, + lim_range); // lhs_neg now has all the negative versions of the LHS. // Now union in all the values from SIGNED MIN (0x80000) to // lim-1 in order to fill in all the ranges with the upper @@ -2469,6 +2503,9 @@ operator_cast::op1_range (irange &r, tree type, class operator_logical_and : public range_operator { + using range_operator::fold_range; + using range_operator::op1_range; + using range_operator::op2_range; public: virtual bool fold_range (irange &r, tree type, const irange &lh, @@ -2542,6 +2579,9 @@ operator_logical_and::op2_range (irange &r, tree type, class operator_bitwise_and : public range_operator { + using range_operator::fold_range; + using range_operator::op1_range; + using range_operator::op2_range; public: virtual bool fold_range (irange &r, tree type, const irange &lh, @@ -2988,6 +3028,9 @@ operator_bitwise_and::op2_range (irange &r, tree type, class operator_logical_or : public range_operator { + using range_operator::fold_range; + using range_operator::op1_range; + using range_operator::op2_range; public: virtual bool fold_range (irange &r, tree type, const irange &lh, @@ -3051,6 +3094,8 @@ operator_logical_or::op2_range (irange &r, tree type, class operator_bitwise_or : public range_operator { + using range_operator::op1_range; + using range_operator::op2_range; public: virtual bool op1_range (irange &r, tree type, const irange &lhs, @@ -3155,6 +3200,8 @@ operator_bitwise_or::op2_range (irange &r, tree type, class operator_bitwise_xor : public range_operator { + using range_operator::op1_range; + using range_operator::op2_range; public: virtual void wi_fold (irange &r, tree type, const wide_int &lh_lb, @@ -3296,6 +3343,8 @@ operator_bitwise_xor::op2_range (irange &r, tree type, class operator_trunc_mod : public range_operator { + using range_operator::op1_range; + using range_operator::op2_range; public: virtual void wi_fold (irange &r, tree type, const wide_int &lh_lb, @@ -3432,6 +3481,8 @@ operator_trunc_mod::op2_range (irange &r, tree type, class operator_logical_not : public range_operator { + using range_operator::fold_range; + using range_operator::op1_range; public: virtual bool fold_range (irange &r, tree type, const irange &lh, @@ -3487,6 +3538,8 @@ operator_logical_not::op1_range (irange &r, class operator_bitwise_not : public range_operator { + using range_operator::fold_range; + using range_operator::op1_range; public: virtual bool fold_range (irange &r, tree type, const irange &lh, @@ -3513,8 +3566,7 @@ operator_bitwise_not::fold_range (irange &r, tree type, // ~X is simply -1 - X. int_range<1> minusone (type, wi::minus_one (TYPE_PRECISION (type)), wi::minus_one (TYPE_PRECISION (type))); - return range_op_handler (MINUS_EXPR, type)->fold_range (r, type, minusone, - lh); + return range_op_handler (MINUS_EXPR, type).fold_range (r, type, minusone, lh); } bool @@ -3533,6 +3585,7 @@ operator_bitwise_not::op1_range (irange &r, tree type, class operator_cst : public range_operator { + using range_operator::fold_range; public: virtual bool fold_range (irange &r, tree type, const irange &op1, @@ -3553,6 +3606,9 @@ operator_cst::fold_range (irange &r, tree type ATTRIBUTE_UNUSED, class operator_identity : public range_operator { + using range_operator::fold_range; + using range_operator::op1_range; + using range_operator::lhs_op1_relation; public: virtual bool fold_range (irange &r, tree type, const irange &op1, @@ -3605,6 +3661,7 @@ operator_identity::op1_range (irange &r, tree type ATTRIBUTE_UNUSED, class operator_unknown : public range_operator { + using range_operator::fold_range; public: virtual bool fold_range (irange &r, tree type, const irange &op1, @@ -3625,6 +3682,7 @@ operator_unknown::fold_range (irange &r, tree type, class operator_abs : public range_operator { + using range_operator::op1_range; public: virtual void wi_fold (irange &r, tree type, const wide_int &lh_lb, @@ -3790,6 +3848,8 @@ operator_absu::wi_fold (irange &r, tree type, class operator_negate : public range_operator { + using range_operator::fold_range; + using range_operator::op1_range; public: virtual bool fold_range (irange &r, tree type, const irange &op1, @@ -3810,9 +3870,8 @@ operator_negate::fold_range (irange &r, tree type, if (empty_range_varying (r, type, lh, rh)) return true; // -X is simply 0 - X. - return range_op_handler (MINUS_EXPR, type)->fold_range (r, type, - range_zero (type), - lh); + return range_op_handler (MINUS_EXPR, type).fold_range (r, type, + range_zero (type), lh); } bool @@ -3828,6 +3887,8 @@ operator_negate::op1_range (irange &r, tree type, class operator_addr_expr : public range_operator { + using range_operator::fold_range; + using range_operator::op1_range; public: virtual bool fold_range (irange &r, tree type, const irange &op1, @@ -3978,6 +4039,8 @@ pointer_and_operator::wi_fold (irange &r, tree type, class pointer_or_operator : public range_operator { + using range_operator::op1_range; + using range_operator::op2_range; public: virtual bool op1_range (irange &r, tree type, const irange &lhs, @@ -4139,8 +4202,8 @@ pointer_table::pointer_table () // The tables are hidden and accessed via a simple extern function. -range_operator * -range_op_handler (enum tree_code code, tree type) +static inline range_operator * +get_handler (enum tree_code code, tree type) { // First check if there is a pointer specialization. if (POINTER_TYPE_P (type)) @@ -4150,16 +4213,120 @@ range_op_handler (enum tree_code code, tree type) return NULL; } +range_op_handler::range_op_handler (tree_code code, tree type) +{ + m_op = get_handler (code, type); +} + +range_op_handler::range_op_handler (const gimple *s) +{ + if (const gassign *ass = dyn_cast (s)) + { + enum tree_code code = gimple_assign_rhs_code (ass); + // The LHS of a comparison is always an int, so we must look at + // the operands. + if (TREE_CODE_CLASS (code) == tcc_comparison) + m_op = get_handler (code, TREE_TYPE (gimple_assign_rhs1 (ass))); + else + m_op = get_handler (code, TREE_TYPE (gimple_assign_lhs (ass))); + } + else if (const gcond *cond = dyn_cast (s)) + m_op = get_handler (gimple_cond_code (cond), + TREE_TYPE (gimple_cond_lhs (cond))); + else + m_op = NULL; +} + +bool +range_op_handler::fold_range (vrange &r, tree type, + const vrange &lh, + const vrange &rh, + relation_kind rel) const +{ + if (is_a (lh)) + return m_op->fold_range (as_a (r), type, + as_a (lh), + as_a (rh), rel); + gcc_unreachable (); + return false; +} + +bool +range_op_handler::op1_range (vrange &r, tree type, + const vrange &lhs, + const vrange &op2, + relation_kind rel) const +{ + if (is_a (r)) + return m_op->op1_range (as_a (r), type, + as_a (lhs), + as_a (op2), rel); + gcc_unreachable (); + return false; +} + +bool +range_op_handler::op2_range (vrange &r, tree type, + const vrange &lhs, + const vrange &op1, + relation_kind rel) const +{ + if (is_a (r)) + return m_op->op2_range (as_a (r), type, + as_a (lhs), + as_a (op1), rel); + gcc_unreachable (); + return false; +} + +relation_kind +range_op_handler::lhs_op1_relation (const vrange &lhs, + const vrange &op1, + const vrange &op2, + relation_kind rel) const +{ + if (is_a (op1)) + return m_op->lhs_op1_relation (as_a (lhs), + as_a (op1), as_a (op2), rel); + gcc_unreachable (); + return VREL_VARYING; +} + +relation_kind +range_op_handler::lhs_op2_relation (const vrange &lhs, + const vrange &op1, + const vrange &op2, + relation_kind rel) const +{ + if (is_a (op1)) + return m_op->lhs_op2_relation (as_a (lhs), + as_a (op1), as_a (op2), rel); + gcc_unreachable (); + return VREL_VARYING; +} + +relation_kind +range_op_handler::op1_op2_relation (const vrange &lhs) const +{ + return m_op->op1_op2_relation (as_a (lhs)); +} + // Cast the range in R to TYPE. -void -range_cast (irange &r, tree type) +bool +range_cast (vrange &r, tree type) { - int_range_max tmp = r; - range_operator *op = range_op_handler (CONVERT_EXPR, type); + tmp_range tmp (r); + tmp_range varying (type); + varying.set_varying (type); + range_op_handler op (CONVERT_EXPR, type); // Call op_convert, if it fails, the result is varying. - if (!op->fold_range (r, type, tmp, int_range<1> (type))) - r.set_varying (type); + if (!op || !op.fold_range (r, type, tmp, varying)) + { + r.set_varying (type); + return false; + } + return true; } #if CHECKING_P diff --git a/gcc/range-op.h b/gcc/range-op.h index 5fdda326d4b..d0f50689897 100644 --- a/gcc/range-op.h +++ b/gcc/range-op.h @@ -108,8 +108,39 @@ protected: const wide_int &rh_ub) const; }; -extern range_operator *range_op_handler (enum tree_code code, tree type); -extern void range_cast (irange &, tree type); +class range_op_handler +{ +public: + range_op_handler (enum tree_code code, tree type); + range_op_handler (const gimple *s); + operator bool () const { return m_op; } + + bool fold_range (vrange &r, tree type, + const vrange &lh, + const vrange &rh, + relation_kind rel = VREL_VARYING) const; + bool op1_range (vrange &r, tree type, + const vrange &lhs, + const vrange &op2, + relation_kind rel = VREL_VARYING) const; + bool op2_range (vrange &r, tree type, + const vrange &lhs, + const vrange &op1, + relation_kind rel = VREL_VARYING) const; + relation_kind lhs_op1_relation (const vrange &lhs, + const vrange &op1, + const vrange &op2, + relation_kind = VREL_VARYING) const; + relation_kind lhs_op2_relation (const vrange &lhs, + const vrange &op1, + const vrange &op2, + relation_kind = VREL_VARYING) const; + relation_kind op1_op2_relation (const vrange &lhs) const; +private: + range_operator *m_op; +}; + +extern bool range_cast (vrange &, tree type); extern void wi_set_zero_nonzero_bits (tree type, const wide_int &, const wide_int &, wide_int &maybe_nonzero, @@ -124,7 +155,7 @@ 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 (irange &r, const irange &lhs, tree val_type); +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 truely cares about a result, @@ -132,8 +163,8 @@ bool_range_state get_bool_state (irange &r, const irange &lhs, tree val_type); // treated as a varying. inline bool -empty_range_varying (irange &r, tree type, - const irange &op1, const irange & op2) +empty_range_varying (vrange &r, tree type, + const vrange &op1, const vrange & op2) { if (op1.undefined_p () || op2.undefined_p ()) { @@ -150,8 +181,8 @@ empty_range_varying (irange &r, tree type, // return false. inline bool -relop_early_resolve (irange &r, tree type, const irange &op1, - const irange &op2, relation_kind rel, +relop_early_resolve (irange &r, tree type, const vrange &op1, + const vrange &op2, relation_kind rel, relation_kind my_rel) { // If known relation is a complete subset of this relation, always true. diff --git a/gcc/tree-data-ref.cc b/gcc/tree-data-ref.cc index 397792c3584..ae05fe74b95 100644 --- a/gcc/tree-data-ref.cc +++ b/gcc/tree-data-ref.cc @@ -593,8 +593,8 @@ compute_distributive_range (tree type, value_range &op0_range, gcc_assert (INTEGRAL_TYPE_P (type) && !TYPE_OVERFLOW_TRAPS (type)); if (result_range) { - range_operator *op = range_op_handler (code, type); - op->fold_range (*result_range, type, op0_range, op1_range); + range_op_handler op (code, type); + op.fold_range (*result_range, type, op0_range, op1_range); } /* The distributive property guarantees that if TYPE is no narrower @@ -639,10 +639,10 @@ compute_distributive_range (tree type, value_range &op0_range, range_cast (op0_range, ssizetype); range_cast (op1_range, ssizetype); value_range wide_range; - range_operator *op = range_op_handler (code, ssizetype); + range_op_handler op (code, ssizetype); bool saved_flag_wrapv = flag_wrapv; flag_wrapv = 1; - op->fold_range (wide_range, ssizetype, op0_range, op1_range); + op.fold_range (wide_range, ssizetype, op0_range, op1_range); flag_wrapv = saved_flag_wrapv; if (wide_range.num_pairs () != 1 || !range_int_cst_p (&wide_range)) return false; diff --git a/gcc/tree-vrp.cc b/gcc/tree-vrp.cc index 0784d658567..3c7b5af4737 100644 --- a/gcc/tree-vrp.cc +++ b/gcc/tree-vrp.cc @@ -924,20 +924,6 @@ extract_range_from_plus_minus_expr (value_range *vr, vr->set (min, max, kind); } -/* Return the range-ops handler for CODE and EXPR_TYPE. If no - suitable operator is found, return NULL and set VR to VARYING. */ - -static const range_operator * -get_range_op_handler (value_range *vr, - enum tree_code code, - tree expr_type) -{ - const range_operator *op = range_op_handler (code, expr_type); - if (!op) - vr->set_varying (expr_type); - return op; -} - /* If the types passed are supported, return TRUE, otherwise set VR to VARYING and return FALSE. */ @@ -1005,10 +991,12 @@ range_fold_binary_symbolics_p (value_range *vr, &vr0, &vr1); return true; } - const range_operator *op = get_range_op_handler (vr, code, expr_type); + range_op_handler op (code, expr_type); + if (!op) + vr->set_varying (expr_type); vr0.normalize_symbolics (); vr1.normalize_symbolics (); - return op->fold_range (*vr, expr_type, vr0, vr1); + return op.fold_range (*vr, expr_type, vr0, vr1); } return false; } @@ -1040,10 +1028,12 @@ range_fold_unary_symbolics_p (value_range *vr, range_fold_binary_expr (vr, MINUS_EXPR, expr_type, &minusone, vr0); return true; } - const range_operator *op = get_range_op_handler (vr, code, expr_type); + range_op_handler op (code, expr_type); + if (!op) + vr->set_varying (expr_type); value_range vr0_cst (*vr0); vr0_cst.normalize_symbolics (); - return op->fold_range (*vr, expr_type, vr0_cst, value_range (expr_type)); + return op.fold_range (*vr, expr_type, vr0_cst, value_range (expr_type)); } return false; } @@ -1060,9 +1050,12 @@ range_fold_binary_expr (value_range *vr, if (!supported_types_p (vr, expr_type) || !defined_ranges_p (vr, vr0_, vr1_)) return; - const range_operator *op = get_range_op_handler (vr, code, expr_type); + range_op_handler op (code, expr_type); if (!op) - return; + { + vr->set_varying (expr_type); + return; + } if (range_fold_binary_symbolics_p (vr, code, expr_type, vr0_, vr1_)) return; @@ -1075,7 +1068,7 @@ range_fold_binary_expr (value_range *vr, vr1.set_varying (expr_type); vr0.normalize_addresses (); vr1.normalize_addresses (); - op->fold_range (*vr, expr_type, vr0, vr1); + op.fold_range (*vr, expr_type, vr0, vr1); } /* Perform a unary operation on a range. */ @@ -1089,16 +1082,19 @@ range_fold_unary_expr (value_range *vr, if (!supported_types_p (vr, expr_type, vr0_type) || !defined_ranges_p (vr, vr0)) return; - const range_operator *op = get_range_op_handler (vr, code, expr_type); + range_op_handler op (code, expr_type); if (!op) - return; + { + vr->set_varying (expr_type); + return; + } if (range_fold_unary_symbolics_p (vr, code, expr_type, vr0)) return; value_range vr0_cst (*vr0); vr0_cst.normalize_addresses (); - op->fold_range (*vr, expr_type, vr0_cst, value_range (expr_type)); + op.fold_range (*vr, expr_type, vr0_cst, value_range (expr_type)); } /* If the range of values taken by OP can be inferred after STMT executes, diff --git a/gcc/value-query.cc b/gcc/value-query.cc index 26e3858103b..31e56eeae53 100644 --- a/gcc/value-query.cc +++ b/gcc/value-query.cc @@ -234,13 +234,13 @@ range_query::get_tree_range (irange &r, tree expr, gimple *stmt) } if (BINARY_CLASS_P (expr)) { - range_operator *op = range_op_handler (TREE_CODE (expr), type); + range_op_handler op (TREE_CODE (expr), type); if (op) { int_range_max r0, r1; range_of_expr (r0, TREE_OPERAND (expr, 0), stmt); range_of_expr (r1, TREE_OPERAND (expr, 1), stmt); - op->fold_range (r, type, r0, r1); + op.fold_range (r, type, r0, r1); } else r.set_varying (type); @@ -248,13 +248,13 @@ range_query::get_tree_range (irange &r, tree expr, gimple *stmt) } if (UNARY_CLASS_P (expr)) { - range_operator *op = range_op_handler (TREE_CODE (expr), type); + range_op_handler op (TREE_CODE (expr), type); tree op0_type = TREE_TYPE (TREE_OPERAND (expr, 0)); if (op && irange::supports_type_p (op0_type)) { int_range_max r0; range_of_expr (r0, TREE_OPERAND (expr, 0), stmt); - op->fold_range (r, type, r0, int_range<1> (type)); + op.fold_range (r, type, r0, int_range<1> (type)); } else r.set_varying (type);