* [PATCH 00/17] Move builtin functions to range-ops.
@ 2022-09-22 18:49 Andrew MacLeod
2022-09-22 18:53 ` [PATCH 01/17] Replace another snippet with a call to, gimple_range_ssa_names Andrew MacLeod
` (16 more replies)
0 siblings, 17 replies; 18+ messages in thread
From: Andrew MacLeod @ 2022-09-22 18:49 UTC (permalink / raw)
To: gcc-patches; +Cc: hernandez, aldy
Builtin functions have been handled until now as special cases in
gimple-range-fold.cc. This set of patches makes the changes required to
create a range_operator for those functions. This allows them to behave
like a normal unary/binary operation through out the ranger ecosystem.
In particular, it will enable us to make GORI aware of them as we can
now provide op1_range and op2_range routines, as well as registering an
relations as needed. None of these enhanced functions are provided yet,
this is strictly a conversion. This enables us to do this for any
operation with 1 or 2 operands.
There are 17 patches, some are bug fixes, some are infrastructure, a
couple are just missing functionality, but most are them are conversions
of the builtins. I did each builtin as a separate patch so if a
regression triggers, we can pinpoint it faster.
Of note:
Patch 2 : Modifies the range_op_handler class to store an integer
handler and a float handler rather than the old tree-code and type. By
looking up the handler immediately and storing the pointer, this opens
up the possibility of processing handlers which are not in a tree-code
table.
Patch 3 : Range-ops is suppose to be IL independent, designed to work in
RTL land as well. A little bit of gimple had crept in, and I needed a
layer that is gimple aware. This patch introduces a
gimple_range_op_handler which inherits from range_op_handler, and acts
as the connector between the gimple IL and range-ops. Some of that code
was in range-ops, and a lot more was located in the GORI file. All
those bits and pieces have been moved into the new class.
Patch 7 : This patch adjusts gimple_range_op_handler constructor to also
check if a builtin function call might have a range_operator object
available, and if so, return that. This initial conversion also adds
CFN_BUILT_IN_CONSTANT_P as the first builtin, removing it from the big
switch in gimple-range-fold.cc.
Patch 8-16 : Moves SIGNBIT, TOUPPER/LOWER, POPCOUNT, CLZ, CTZ, CLRSB,
UBSAN*, STRLEN, and GOACC to range-ops.
patch 17: Finally, moves CFA_BUILT_IN_PARITY to range-ops, and removes
the builtin-function code checks from range_of_call in gimple_range-fold.cc
These patches all bootstrap on x86_64-pc-linux-gnu with no regressions.
Performance wise, it all ends up as approximately a wash. (VRP a hair
slower, threading a hair faster)
Pushed.
Andrew
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH 01/17] Replace another snippet with a call to, gimple_range_ssa_names.
2022-09-22 18:49 [PATCH 00/17] Move builtin functions to range-ops Andrew MacLeod
@ 2022-09-22 18:53 ` Andrew MacLeod
2022-09-22 18:55 ` [PATCH 02/17] Adjust range_op_handler to store the handler directly Andrew MacLeod
` (15 subsequent siblings)
16 siblings, 0 replies; 18+ messages in thread
From: Andrew MacLeod @ 2022-09-22 18:53 UTC (permalink / raw)
To: gcc-patches; +Cc: hernandez, aldy
[-- Attachment #1: Type: text/plain, Size: 190 bytes --]
When the original patch was applied, I missed a spot which could
also be rewritten to use gimple_range_ssa_names.
Bootstrapped on x86_64-pc-linux-gnu with no regressions. Pushed.
Andrew
[-- Attachment #2: 0001-Replace-another-snippet-with-a-call-to-gimple_range_.patch --]
[-- Type: text/x-patch, Size: 1911 bytes --]
From 3cba5cd6e019182dbff756f621af048d55cdda98 Mon Sep 17 00:00:00 2001
From: Andrew MacLeod <amacleod@redhat.com>
Date: Wed, 31 Aug 2022 17:28:09 -0400
Subject: [PATCH 01/17] Replace another snippet with a call to
gimple_range_ssa_names.
When the original patch was applied, I missed a spot which could
also be rewritten to use gimple_range_ssa_names.
* tree-ssa-threadbackward.cc
(back_threader::find_paths_to_names): Replace sequence with
a call to gimple_range_ssa_names.
---
gcc/tree-ssa-threadbackward.cc | 20 +++-----------------
1 file changed, 3 insertions(+), 17 deletions(-)
diff --git a/gcc/tree-ssa-threadbackward.cc b/gcc/tree-ssa-threadbackward.cc
index 9725f50e639..2a8cfa3ee01 100644
--- a/gcc/tree-ssa-threadbackward.cc
+++ b/gcc/tree-ssa-threadbackward.cc
@@ -435,28 +435,14 @@ back_threader::find_paths_to_names (basic_block bb, bitmap interesting,
}
/* For other local defs process their uses, amending
imports on the way. */
- else if (gassign *ass = dyn_cast <gassign *> (def_stmt))
+ else
{
tree ssa[3];
- if (range_op_handler (ass))
- {
- ssa[0] = gimple_range_ssa_p (gimple_range_operand1 (ass));
- ssa[1] = gimple_range_ssa_p (gimple_range_operand2 (ass));
- ssa[2] = NULL_TREE;
- }
- else if (gimple_assign_rhs_code (ass) == COND_EXPR)
- {
- ssa[0] = gimple_range_ssa_p (gimple_assign_rhs1 (ass));
- ssa[1] = gimple_range_ssa_p (gimple_assign_rhs2 (ass));
- ssa[2] = gimple_range_ssa_p (gimple_assign_rhs3 (ass));
- }
- else
- continue;
- for (unsigned j = 0; j < 3; ++j)
+ unsigned lim = gimple_range_ssa_names (ssa, 3, def_stmt);
+ for (unsigned j = 0; j < lim; ++j)
{
tree rhs = ssa[j];
if (rhs
- && TREE_CODE (rhs) == SSA_NAME
&& bitmap_set_bit (m_imports,
SSA_NAME_VERSION (rhs)))
{
--
2.37.3
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH 02/17] Adjust range_op_handler to store the handler directly.
2022-09-22 18:49 [PATCH 00/17] Move builtin functions to range-ops Andrew MacLeod
2022-09-22 18:53 ` [PATCH 01/17] Replace another snippet with a call to, gimple_range_ssa_names Andrew MacLeod
@ 2022-09-22 18:55 ` Andrew MacLeod
2022-09-22 18:56 ` [PATCH 03/17] Create gimple_range_op_handler in a new source file Andrew MacLeod
` (14 subsequent siblings)
16 siblings, 0 replies; 18+ messages in thread
From: Andrew MacLeod @ 2022-09-22 18:55 UTC (permalink / raw)
To: gcc-patches; +Cc: hernandez, aldy
[-- Attachment #1: Type: text/plain, Size: 297 bytes --]
Range_op_handler currently stores a tree code and a type. It defers
checking to see if there is a valid handler until asked.
This change checks at constructor time and store a pointer to the
handler if there is one.
Bootstrapped on x86_64-pc-linux-gnu with no regressions. Pushed.
Andrew
[-- Attachment #2: 0002-Adjust-range_op_handler-to-store-the-handler-directl.patch --]
[-- Type: text/x-patch, Size: 11445 bytes --]
From 24c473a14d3cbe6fc44997122b532cb9406497cb Mon Sep 17 00:00:00 2001
From: Andrew MacLeod <amacleod@redhat.com>
Date: Wed, 31 Aug 2022 14:07:13 -0400
Subject: [PATCH 02/17] Adjust range_op_handler to store the handler directly.
Range_op_handler currently stores a tree code and a type. It defers
checking to see if there is a valid handler until asked.
This change checks at constuctor time and store a pointer to
the handler if there is one.
* range-op.cc (range_op_handler::set_op_handler): Set new fields.
(ange_op_handler::range_op_handler): Likewise.
(range_op_handler::operator bool): Remove.
(range_op_handler::fold_range): Use appropriate handler.
(range_op_handler::op1_range): Likewise.
(range_op_handler::op2_range): Likewise.
(range_op_handler::lhs_op1_relation): Likewise.
(range_op_handler::lhs_op2_relation): Likewise.
(range_op_handler::op1_op2_relation): Likewise.
* range-op.h (class range_op_handler): Store handler pointers.
(range_op_handler:: operator bool): Inline.
---
gcc/range-op.cc | 246 +++++++++++++++++++++---------------------------
gcc/range-op.h | 8 +-
2 files changed, 114 insertions(+), 140 deletions(-)
diff --git a/gcc/range-op.cc b/gcc/range-op.cc
index 806edf1012e..f642b3f26de 100644
--- a/gcc/range-op.cc
+++ b/gcc/range-op.cc
@@ -4159,48 +4159,63 @@ get_float_handler (enum tree_code code, tree)
return (*floating_tree_table)[code];
}
+void
+range_op_handler::set_op_handler (tree_code code, tree type)
+{
+ if (irange::supports_p (type))
+ {
+ m_float = NULL;
+ m_int = get_handler (code, type);
+ m_valid = m_int != NULL;
+ }
+ else if (frange::supports_p (type))
+ {
+ m_int = NULL;
+ m_float = get_float_handler (code, type);
+ m_valid = m_float != NULL;
+ }
+ else
+ {
+ m_int = NULL;
+ m_float = NULL;
+ m_valid = false;
+ }
+}
+
range_op_handler::range_op_handler (tree_code code, tree type)
- : m_code (code), m_type (type)
{
+ set_op_handler (code, type);
}
range_op_handler::range_op_handler (const gimple *s)
{
+ tree_code code = NOP_EXPR;
+ tree type = NULL_TREE;
+
if (const gassign *ass = dyn_cast<const gassign *> (s))
{
- m_code = gimple_assign_rhs_code (ass);
+ 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 (m_code) == tcc_comparison)
- m_type = TREE_TYPE (gimple_assign_rhs1 (ass));
+ if (TREE_CODE_CLASS (code) == tcc_comparison)
+ type = TREE_TYPE (gimple_assign_rhs1 (ass));
else
- m_type = TREE_TYPE (gimple_assign_lhs (ass));
+ type = TREE_TYPE (gimple_assign_lhs (ass));
}
else if (const gcond *cond = dyn_cast<const gcond *> (s))
{
- m_code = gimple_cond_code (cond);
- m_type = TREE_TYPE (gimple_cond_lhs (cond));
+ code = gimple_cond_code (cond);
+ type = TREE_TYPE (gimple_cond_lhs (cond));
}
- else
+
+ if (!type)
{
- // A null type means there is no handler for this combination,
- // but the decision whether there is one or not, is delayed
- // until operator bool below is queried.
- m_code = NOP_EXPR;
- m_type = nullptr;
+ m_int = NULL;
+ m_float = NULL;
+ m_valid = false;
}
-}
-
-// Return TRUE if there is a handler available for the current
-// combination of tree_code and type.
-
-range_op_handler::operator bool () const
-{
- if (!m_type)
- return false;
- if (frange::supports_p (m_type))
- return get_float_handler (m_code, m_type);
- return get_handler (m_code, m_type);
+ else
+ set_op_handler (code, type);
}
bool
@@ -4209,26 +4224,19 @@ range_op_handler::fold_range (vrange &r, tree type,
const vrange &rh,
relation_kind rel) const
{
- if (irange::supports_p (m_type))
- {
- range_operator *op = get_handler (m_code, m_type);
- return op->fold_range (as_a <irange> (r), type,
- as_a <irange> (lh),
- as_a <irange> (rh), rel);
- }
- if (frange::supports_p (m_type))
- {
- range_operator_float *op = get_float_handler (m_code, m_type);
- if (is_a <irange> (r))
- return op->fold_range (as_a <irange> (r), type,
- as_a <frange> (lh),
- as_a <frange> (rh), rel);
- return op->fold_range (as_a <frange> (r), type,
- as_a <frange> (lh),
- as_a <frange> (rh), rel);
- }
- gcc_unreachable ();
- return false;
+ gcc_checking_assert (m_valid);
+ if (m_int)
+ return m_int->fold_range (as_a <irange> (r), type,
+ as_a <irange> (lh),
+ as_a <irange> (rh), rel);
+
+ if (is_a <irange> (r))
+ return m_float->fold_range (as_a <irange> (r), type,
+ as_a <frange> (lh),
+ as_a <frange> (rh), rel);
+ return m_float->fold_range (as_a <frange> (r), type,
+ as_a <frange> (lh),
+ as_a <frange> (rh), rel);
}
bool
@@ -4237,26 +4245,19 @@ range_op_handler::op1_range (vrange &r, tree type,
const vrange &op2,
relation_kind rel) const
{
- if (irange::supports_p (m_type))
- {
- range_operator *op = get_handler (m_code, m_type);
- return op->op1_range (as_a <irange> (r), type,
- as_a <irange> (lhs),
- as_a <irange> (op2), rel);
- }
- if (frange::supports_p (m_type))
- {
- range_operator_float *op = get_float_handler (m_code, m_type);
- if (is_a <irange> (lhs))
- return op->op1_range (as_a <frange> (r), type,
- as_a <irange> (lhs),
- as_a <frange> (op2), rel);
- return op->op1_range (as_a <frange> (r), type,
- as_a <frange> (lhs),
- as_a <frange> (op2), rel);
- }
- gcc_unreachable ();
- return false;
+ gcc_checking_assert (m_valid);
+ if (m_int)
+ return m_int->op1_range (as_a <irange> (r), type,
+ as_a <irange> (lhs),
+ as_a <irange> (op2), rel);
+
+ if (is_a <irange> (lhs))
+ return m_float->op1_range (as_a <frange> (r), type,
+ as_a <irange> (lhs),
+ as_a <frange> (op2), rel);
+ return m_float->op1_range (as_a <frange> (r), type,
+ as_a <frange> (lhs),
+ as_a <frange> (op2), rel);
}
bool
@@ -4265,26 +4266,19 @@ range_op_handler::op2_range (vrange &r, tree type,
const vrange &op1,
relation_kind rel) const
{
- if (irange::supports_p (m_type))
- {
- range_operator *op = get_handler (m_code, m_type);
- return op->op2_range (as_a <irange> (r), type,
- as_a <irange> (lhs),
- as_a <irange> (op1), rel);
- }
- if (frange::supports_p (m_type))
- {
- range_operator_float *op = get_float_handler (m_code, m_type);
- if (is_a <irange> (lhs))
- return op->op2_range (as_a <frange> (r), type,
- as_a <irange> (lhs),
- as_a <frange> (op1), rel);
- return op->op2_range (as_a <frange> (r), type,
- as_a <frange> (lhs),
- as_a <frange> (op1), rel);
- }
- gcc_unreachable ();
- return false;
+ gcc_checking_assert (m_valid);
+ if (m_int)
+ return m_int->op2_range (as_a <irange> (r), type,
+ as_a <irange> (lhs),
+ as_a <irange> (op1), rel);
+
+ if (is_a <irange> (lhs))
+ return m_float->op2_range (as_a <frange> (r), type,
+ as_a <irange> (lhs),
+ as_a <frange> (op1), rel);
+ return m_float->op2_range (as_a <frange> (r), type,
+ as_a <frange> (lhs),
+ as_a <frange> (op1), rel);
}
relation_kind
@@ -4293,26 +4287,19 @@ range_op_handler::lhs_op1_relation (const vrange &lhs,
const vrange &op2,
relation_kind rel) const
{
- if (irange::supports_p (m_type))
- {
- range_operator *op = get_handler (m_code, m_type);
- return op->lhs_op1_relation (as_a <irange> (lhs),
- as_a <irange> (op1),
- as_a <irange> (op2), rel);
- }
- if (frange::supports_p (m_type))
- {
- range_operator_float *op = get_float_handler (m_code, m_type);
- if (is_a <irange> (lhs))
- return op->lhs_op1_relation (as_a <irange> (lhs),
- as_a <frange> (op1),
- as_a <frange> (op2), rel);
- return op->lhs_op1_relation (as_a <frange> (lhs),
- as_a <frange> (op1),
- as_a <frange> (op2), rel);
- }
- gcc_unreachable ();
- return VREL_VARYING;
+ gcc_checking_assert (m_valid);
+ if (m_int)
+ return m_int->lhs_op1_relation (as_a <irange> (lhs),
+ as_a <irange> (op1),
+ as_a <irange> (op2), rel);
+
+ if (is_a <irange> (lhs))
+ return m_float->lhs_op1_relation (as_a <irange> (lhs),
+ as_a <frange> (op1),
+ as_a <frange> (op2), rel);
+ return m_float->lhs_op1_relation (as_a <frange> (lhs),
+ as_a <frange> (op1),
+ as_a <frange> (op2), rel);
}
relation_kind
@@ -4321,43 +4308,28 @@ range_op_handler::lhs_op2_relation (const vrange &lhs,
const vrange &op2,
relation_kind rel) const
{
- if (irange::supports_p (m_type))
- {
- range_operator *op = get_handler (m_code, m_type);
- return op->lhs_op2_relation (as_a <irange> (lhs),
- as_a <irange> (op1),
- as_a <irange> (op2), rel);
- }
- if (frange::supports_p (m_type))
- {
- range_operator_float *op = get_float_handler (m_code, m_type);
- if (is_a <irange> (lhs))
- return op->lhs_op2_relation (as_a <irange> (lhs),
- as_a <frange> (op1),
- as_a <frange> (op2), rel);
- return op->lhs_op2_relation (as_a <frange> (lhs),
- as_a <frange> (op1),
- as_a <frange> (op2), rel);
- }
- gcc_unreachable ();
- return VREL_VARYING;
+ gcc_checking_assert (m_valid);
+ if (m_int)
+ return m_int->lhs_op2_relation (as_a <irange> (lhs),
+ as_a <irange> (op1),
+ as_a <irange> (op2), rel);
+
+ if (is_a <irange> (lhs))
+ return m_float->lhs_op2_relation (as_a <irange> (lhs),
+ as_a <frange> (op1),
+ as_a <frange> (op2), rel);
+ return m_float->lhs_op2_relation (as_a <frange> (lhs),
+ as_a <frange> (op1),
+ as_a <frange> (op2), rel);
}
relation_kind
range_op_handler::op1_op2_relation (const vrange &lhs) const
{
- if (irange::supports_p (m_type))
- {
- range_operator *op = get_handler (m_code, m_type);
- return op->op1_op2_relation (as_a <irange> (lhs));
- }
- if (frange::supports_p (m_type))
- {
- range_operator_float *op = get_float_handler (m_code, m_type);
- return op->op1_op2_relation (as_a <irange> (lhs));
- }
- gcc_unreachable ();
- return VREL_VARYING;
+ gcc_checking_assert (m_valid);
+ if (m_int)
+ return m_int->op1_op2_relation (as_a <irange> (lhs));
+ return m_float->op1_op2_relation (as_a <irange> (lhs));
}
// Cast the range in R to TYPE.
diff --git a/gcc/range-op.h b/gcc/range-op.h
index 37d9aa91c46..56c57c46a8e 100644
--- a/gcc/range-op.h
+++ b/gcc/range-op.h
@@ -162,7 +162,7 @@ class range_op_handler
public:
range_op_handler (enum tree_code code, tree type);
range_op_handler (const gimple *s);
- operator bool () const;
+ inline operator bool () const { return m_valid; }
bool fold_range (vrange &r, tree type,
const vrange &lh,
@@ -186,8 +186,10 @@ public:
relation_kind = VREL_VARYING) const;
relation_kind op1_op2_relation (const vrange &lhs) const;
private:
- enum tree_code m_code;
- tree m_type;
+ void set_op_handler (enum tree_code code, tree type);
+ bool m_valid;
+ range_operator *m_int;
+ range_operator_float *m_float;
};
extern bool range_cast (vrange &, tree type);
--
2.37.3
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH 03/17] Create gimple_range_op_handler in a new source file.
2022-09-22 18:49 [PATCH 00/17] Move builtin functions to range-ops Andrew MacLeod
2022-09-22 18:53 ` [PATCH 01/17] Replace another snippet with a call to, gimple_range_ssa_names Andrew MacLeod
2022-09-22 18:55 ` [PATCH 02/17] Adjust range_op_handler to store the handler directly Andrew MacLeod
@ 2022-09-22 18:56 ` Andrew MacLeod
2022-09-22 18:58 ` [PATCH 04/17] Fix calc_op1 for undefined op2_range Andrew MacLeod
` (13 subsequent siblings)
16 siblings, 0 replies; 18+ messages in thread
From: Andrew MacLeod @ 2022-09-22 18:56 UTC (permalink / raw)
To: gcc-patches; +Cc: hernandez, aldy
[-- Attachment #1: Type: text/plain, Size: 286 bytes --]
Range-ops is meant to be IL independent. Some gimple processing has
be placed in range-ops, and some is located in gori. Split it all into
a file and isolate it in a new class gimple_range_op_handler.
Bootstrapped on x86_64-pc-linux-gnu with no regressions. Pushed.
Andrew
[-- Attachment #2: 0003-Create-gimple_range_op_handler-in-a-new-source-file.patch --]
[-- Type: text/x-patch, Size: 39151 bytes --]
From 51ce06385bf259a092f830f1a6dcc4b98757919e Mon Sep 17 00:00:00 2001
From: Andrew MacLeod <amacleod@redhat.com>
Date: Thu, 1 Sep 2022 10:34:55 -0400
Subject: [PATCH 03/17] Create gimple_range_op_handler in a new source file.
Range-ops is meant to be IL independent. Some gimple processing has
be placed in range-ops, and some is located in gori. Split it all into
a file and isolate it in a new class gimple_range_op_handler.
* Makefile.in (OBJS): Add gimple-range-op.o.
* gimple-range-edge.cc (gimple_outgoing_range_stmt_p): Use
gimple_range_op_handler.
* gimple-range-fold.cc (gimple_range_base_of_assignment): Move
to a method in gimple_range_op_handler.
(gimple_range_operand1): Ditto.
(gimple_range_operand2): Ditto.
(fold_using_range::fold_stmt): Use gimple_range_op_handler.
(fold_using_range::range_of_range_op): Ditto.
(fold_using_range::relation_fold_and_or): Ditto.
(fur_source::register_outgoing_edges): Ditto.
(gimple_range_ssa_names): Relocate to gimple-range-op.cc.
* gimple-range-fold.h: Adjust prototypes.
* gimple-range-gori.cc (gimple_range_calc_op1): Move
to a method in gimple_range_op_handler.
(gimple_range_calc_op2): Ditto.
(gori_compute::compute_operand_range): Use
gimple_range_op_handler.
(gori_compute::compute_logical_operands): Ditto.
(compute_operand1_range): Ditto.
(gori_compute::compute_operand2_range): Ditto.
(gori_compute::compute_operand1_and_operand2_range): Ditto.
* gimple-range-gori.h: Adjust protoypes.
* gimple-range-op.cc: New. Supply gimple_range_op_handler methods.
* gimple-range-op.h: New. Supply gimple_range_op_handler class.
* gimple-range.cc (gimple_ranger::prefill_name): Use
gimple_range_op_handler.
(gimple_ranger::prefill_stmt_dependencies): Ditto.
* gimple-range.h: Include gimple-range-op.h.
* range-op.cc (range_op_handler::range_op_handler): Adjust and
remove gimple * parameter option.
* range-op.h: Adjust prototypes.
---
gcc/Makefile.in | 1 +
gcc/gimple-range-edge.cc | 2 +-
gcc/gimple-range-fold.cc | 153 +++++-------------------
gcc/gimple-range-fold.h | 12 +-
gcc/gimple-range-gori.cc | 134 ++++++---------------
gcc/gimple-range-gori.h | 27 ++---
gcc/gimple-range-op.cc | 245 +++++++++++++++++++++++++++++++++++++++
gcc/gimple-range-op.h | 51 ++++++++
gcc/gimple-range.cc | 11 +-
gcc/gimple-range.h | 2 +-
gcc/range-op.cc | 37 ++----
gcc/range-op.h | 4 +-
12 files changed, 386 insertions(+), 293 deletions(-)
create mode 100644 gcc/gimple-range-op.cc
create mode 100644 gcc/gimple-range-op.h
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index a4689d52e36..59b67d99441 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -1416,6 +1416,7 @@ OBJS = \
gimple-range-fold.o \
gimple-range-gori.o \
gimple-range-infer.o \
+ gimple-range-op.o \
gimple-range-trace.o \
gimple-ssa-backprop.o \
gimple-ssa-isolate-paths.o \
diff --git a/gcc/gimple-range-edge.cc b/gcc/gimple-range-edge.cc
index 194e8f87a4b..95deadffc55 100644
--- a/gcc/gimple-range-edge.cc
+++ b/gcc/gimple-range-edge.cc
@@ -43,7 +43,7 @@ gimple_outgoing_range_stmt_p (basic_block bb)
if (!gsi_end_p (gsi))
{
gimple *s = gsi_stmt (gsi);
- if (is_a<gcond *> (s) && range_op_handler (s))
+ if (is_a<gcond *> (s) && gimple_range_op_handler::supported_p (s))
return gsi_stmt (gsi);
if (is_a <gswitch *> (s))
return gsi_stmt (gsi);
diff --git a/gcc/gimple-range-fold.cc b/gcc/gimple-range-fold.cc
index a45fc7ad4c6..addf3e7f254 100644
--- a/gcc/gimple-range-fold.cc
+++ b/gcc/gimple-range-fold.cc
@@ -42,7 +42,7 @@ along with GCC; see the file COPYING3. If not see
#include "vr-values.h"
#include "range.h"
#include "value-query.h"
-#include "range-op.h"
+#include "gimple-range-op.h"
#include "gimple-range.h"
// Construct a fur_source, and set the m_query field.
@@ -463,73 +463,6 @@ gimple_range_adjustment (vrange &res, const gimple *stmt)
}
}
-// Return the base of the RHS of an assignment.
-
-static tree
-gimple_range_base_of_assignment (const gimple *stmt)
-{
- gcc_checking_assert (gimple_code (stmt) == GIMPLE_ASSIGN);
- tree op1 = gimple_assign_rhs1 (stmt);
- if (gimple_assign_rhs_code (stmt) == ADDR_EXPR)
- return get_base_address (TREE_OPERAND (op1, 0));
- return op1;
-}
-
-// Return the first operand of this statement if it is a valid operand
-// supported by ranges, otherwise return NULL_TREE. Special case is
-// &(SSA_NAME expr), return the SSA_NAME instead of the ADDR expr.
-
-tree
-gimple_range_operand1 (const gimple *stmt)
-{
- gcc_checking_assert (range_op_handler (stmt));
-
- switch (gimple_code (stmt))
- {
- case GIMPLE_COND:
- return gimple_cond_lhs (stmt);
- case GIMPLE_ASSIGN:
- {
- tree base = gimple_range_base_of_assignment (stmt);
- if (base && TREE_CODE (base) == MEM_REF)
- {
- // If the base address is an SSA_NAME, we return it
- // here. This allows processing of the range of that
- // name, while the rest of the expression is simply
- // ignored. The code in range_ops will see the
- // ADDR_EXPR and do the right thing.
- tree ssa = TREE_OPERAND (base, 0);
- if (TREE_CODE (ssa) == SSA_NAME)
- return ssa;
- }
- return base;
- }
- default:
- break;
- }
- return NULL;
-}
-
-// Return the second operand of statement STMT, otherwise return NULL_TREE.
-
-tree
-gimple_range_operand2 (const gimple *stmt)
-{
- gcc_checking_assert (range_op_handler (stmt));
-
- switch (gimple_code (stmt))
- {
- case GIMPLE_COND:
- return gimple_cond_rhs (stmt);
- case GIMPLE_ASSIGN:
- if (gimple_num_ops (stmt) >= 3)
- return gimple_assign_rhs2 (stmt);
- default:
- break;
- }
- return NULL_TREE;
-}
-
// Calculate a range for statement S and return it in R. If NAME is provided it
// represents the SSA_NAME on the LHS of the statement. It is only required
// if there is more than one lhs/output. If a range cannot
@@ -551,8 +484,9 @@ fold_using_range::fold_stmt (vrange &r, gimple *s, fur_source &src, tree name)
&& gimple_assign_rhs_code (s) == ADDR_EXPR)
return range_of_address (as_a <irange> (r), s, src);
- if (range_op_handler (s))
- res = range_of_range_op (r, s, src);
+ gimple_range_op_handler handler (s);
+ if (handler)
+ res = range_of_range_op (r, handler, src);
else if (is_a<gphi *>(s))
res = range_of_phi (r, as_a<gphi *> (s), src);
else if (is_a<gcall *>(s))
@@ -587,17 +521,19 @@ fold_using_range::fold_stmt (vrange &r, gimple *s, fur_source &src, tree name)
// If a range cannot be calculated, return false.
bool
-fold_using_range::range_of_range_op (vrange &r, gimple *s, fur_source &src)
+fold_using_range::range_of_range_op (vrange &r,
+ gimple_range_op_handler &handler,
+ fur_source &src)
{
+ gcc_checking_assert (handler);
+ gimple *s = handler.stmt ();
tree type = gimple_range_type (s);
if (!type)
return false;
- range_op_handler handler (s);
- gcc_checking_assert (handler);
- tree lhs = gimple_get_lhs (s);
- tree op1 = gimple_range_operand1 (s);
- tree op2 = gimple_range_operand2 (s);
+ tree lhs = handler.lhs ();
+ tree op1 = handler.operand1 ();
+ tree op2 = handler.operand2 ();
Value_Range range1 (TREE_TYPE (op1));
Value_Range range2 (op2 ? TREE_TYPE (op2) : TREE_TYPE (op1));
@@ -1430,9 +1366,10 @@ fold_using_range::relation_fold_and_or (irange& lhs_range, gimple *s,
else if (code != BIT_IOR_EXPR && code != TRUTH_OR_EXPR)
return;
- tree lhs = gimple_get_lhs (s);
- tree ssa1 = gimple_range_ssa_p (gimple_range_operand1 (s));
- tree ssa2 = gimple_range_ssa_p (gimple_range_operand2 (s));
+ gimple_range_op_handler handler (s);
+ tree lhs = handler.lhs ();
+ tree ssa1 = gimple_range_ssa_p (handler.operand1 ());
+ tree ssa2 = gimple_range_ssa_p (handler.operand2 ());
// Deal with || and && only when there is a full set of symbolics.
if (!lhs || !ssa1 || !ssa2
@@ -1448,18 +1385,18 @@ fold_using_range::relation_fold_and_or (irange& lhs_range, gimple *s,
gimple *ssa1_stmt = SSA_NAME_DEF_STMT (ssa1);
gimple *ssa2_stmt = SSA_NAME_DEF_STMT (ssa2);
- range_op_handler handler1 (SSA_NAME_DEF_STMT (ssa1));
- range_op_handler handler2 (SSA_NAME_DEF_STMT (ssa2));
+ gimple_range_op_handler handler1 (ssa1_stmt);
+ gimple_range_op_handler handler2 (ssa2_stmt);
// If either handler is not present, no relation can be found.
if (!handler1 || !handler2)
return;
// Both stmts will need to have 2 ssa names in the stmt.
- tree ssa1_dep1 = gimple_range_ssa_p (gimple_range_operand1 (ssa1_stmt));
- tree ssa1_dep2 = gimple_range_ssa_p (gimple_range_operand2 (ssa1_stmt));
- tree ssa2_dep1 = gimple_range_ssa_p (gimple_range_operand1 (ssa2_stmt));
- tree ssa2_dep2 = gimple_range_ssa_p (gimple_range_operand2 (ssa2_stmt));
+ tree ssa1_dep1 = gimple_range_ssa_p (handler1.operand1 ());
+ tree ssa1_dep2 = gimple_range_ssa_p (handler1.operand2 ());
+ tree ssa2_dep1 = gimple_range_ssa_p (handler2.operand1 ());
+ tree ssa2_dep2 = gimple_range_ssa_p (handler2.operand2 ());
if (!ssa1_dep1 || !ssa1_dep2 || !ssa2_dep1 || !ssa2_dep2)
return;
@@ -1516,7 +1453,7 @@ fur_source::register_outgoing_edges (gcond *s, irange &lhs_range, edge e0, edge
tree name;
basic_block bb = gimple_bb (s);
- range_op_handler handler (s);
+ gimple_range_op_handler handler (s);
if (!handler)
return;
@@ -1529,7 +1466,6 @@ fur_source::register_outgoing_edges (gcond *s, irange &lhs_range, edge e0, edge
e0 = NULL;
}
-
if (e1)
{
// If this edge is never taken, ignore it.
@@ -1544,8 +1480,8 @@ fur_source::register_outgoing_edges (gcond *s, irange &lhs_range, edge e0, edge
// First, register the gcond itself. This will catch statements like
// if (a_2 < b_5)
- tree ssa1 = gimple_range_ssa_p (gimple_range_operand1 (s));
- tree ssa2 = gimple_range_ssa_p (gimple_range_operand2 (s));
+ tree ssa1 = gimple_range_ssa_p (handler.operand1 ());
+ tree ssa2 = gimple_range_ssa_p (handler.operand2 ());
if (ssa1 && ssa2)
{
if (e0)
@@ -1575,11 +1511,11 @@ 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);
- range_op_handler handler (stmt);
+ gimple_range_op_handler handler (stmt);
if (!handler)
continue;
- tree ssa1 = gimple_range_ssa_p (gimple_range_operand1 (stmt));
- tree ssa2 = gimple_range_ssa_p (gimple_range_operand2 (stmt));
+ tree ssa1 = gimple_range_ssa_p (handler.operand1 ());
+ tree ssa2 = gimple_range_ssa_p (handler.operand2 ());
Value_Range r (TREE_TYPE (name));
if (ssa1 && ssa2)
{
@@ -1600,36 +1536,3 @@ fur_source::register_outgoing_edges (gcond *s, irange &lhs_range, edge e0, edge
}
}
}
-
-// Given stmt S, fill VEC, up to VEC_SIZE elements, with relevant ssa-names
-// on the statement. For efficiency, it is an error to not pass in enough
-// elements for the vector. Return the number of ssa-names.
-
-unsigned
-gimple_range_ssa_names (tree *vec, unsigned vec_size, gimple *stmt)
-{
- tree ssa;
- int count = 0;
-
- if (range_op_handler (stmt))
- {
- gcc_checking_assert (vec_size >= 2);
- if ((ssa = gimple_range_ssa_p (gimple_range_operand1 (stmt))))
- vec[count++] = ssa;
- if ((ssa = gimple_range_ssa_p (gimple_range_operand2 (stmt))))
- vec[count++] = ssa;
- }
- else if (is_a<gassign *> (stmt)
- && gimple_assign_rhs_code (stmt) == COND_EXPR)
- {
- gcc_checking_assert (vec_size >= 3);
- gassign *st = as_a<gassign *> (stmt);
- if ((ssa = gimple_range_ssa_p (gimple_assign_rhs1 (st))))
- vec[count++] = ssa;
- if ((ssa = gimple_range_ssa_p (gimple_assign_rhs2 (st))))
- vec[count++] = ssa;
- if ((ssa = gimple_range_ssa_p (gimple_assign_rhs3 (st))))
- vec[count++] = ssa;
- }
- return count;
-}
diff --git a/gcc/gimple-range-fold.h b/gcc/gimple-range-fold.h
index f2eab720213..ce18c66b8e7 100644
--- a/gcc/gimple-range-fold.h
+++ b/gcc/gimple-range-fold.h
@@ -96,15 +96,6 @@ range_compatible_p (tree type1, tree type2)
&& TYPE_SIGN (type1) == TYPE_SIGN (type2));
}
-extern tree gimple_range_operand1 (const gimple *s);
-extern tree gimple_range_operand2 (const gimple *s);
-
-// Given stmt S, fill VEC, up to VEC_SIZE elements, with relevant ssa-names
-// on the statement. For efficiency, it is an error to not pass in enough
-// elements for the vector. Return the number of ssa-names.
-
-unsigned gimple_range_ssa_names (tree *vec, unsigned vec_size, gimple *stmt);
-
// Source of all operands for fold_using_range and gori_compute.
// It abstracts out the source of an operand so it can come from a stmt or
// and edge or anywhere a derived class of fur_source wants.
@@ -169,7 +160,8 @@ public:
bool fold_stmt (vrange &r, gimple *s, class fur_source &src,
tree name = NULL_TREE);
protected:
- bool range_of_range_op (vrange &r, gimple *s, fur_source &src);
+ bool range_of_range_op (vrange &r, gimple_range_op_handler &handler,
+ fur_source &src);
bool range_of_call (vrange &r, gcall *call, fur_source &src);
bool range_of_cond_expr (vrange &r, gassign* cond, fur_source &src);
bool range_of_address (irange &r, gimple *s, fur_source &src);
diff --git a/gcc/gimple-range-gori.cc b/gcc/gimple-range-gori.cc
index 957b8d543fa..40b2f2f6ae9 100644
--- a/gcc/gimple-range-gori.cc
+++ b/gcc/gimple-range-gori.cc
@@ -29,83 +29,6 @@ along with GCC; see the file COPYING3. If not see
#include "gimple-pretty-print.h"
#include "gimple-range.h"
-// Calculate what we can determine of the range of this unary
-// statement's operand if the lhs of the expression has the range
-// LHS_RANGE. Return false if nothing can be determined.
-
-bool
-gimple_range_calc_op1 (vrange &r, const gimple *stmt, const vrange &lhs_range)
-{
- gcc_checking_assert (gimple_num_ops (stmt) < 3);
- // Give up on empty ranges.
- if (lhs_range.undefined_p ())
- return false;
-
- // Unary operations require the type of the first operand in the
- // second range position.
- tree type = TREE_TYPE (gimple_range_operand1 (stmt));
- Value_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
-// first operand if the lhs of the expression has the range LHS_RANGE
-// and the second operand has the range OP2_RANGE. Return false if
-// nothing can be determined.
-
-bool
-gimple_range_calc_op1 (vrange &r, const gimple *stmt,
- const vrange &lhs_range, const vrange &op2_range)
-{
- // Give up on empty ranges.
- if (lhs_range.undefined_p ())
- return false;
-
- // Unary operation are allowed to pass a range in for second operand
- // as there are often additional restrictions beyond the type which
- // can be imposed. See operator_cast::op1_range().
- tree type = TREE_TYPE (gimple_range_operand1 (stmt));
- // If op2 is undefined, solve as if it is varying.
- if (op2_range.undefined_p ())
- {
- // This is sometimes invoked on single operand stmts.
- if (gimple_num_ops (stmt) < 3)
- return false;
- tree op2_type = TREE_TYPE (gimple_range_operand2 (stmt));
- Value_Range trange (op2_type);
- trange.set_varying (op2_type);
- return range_op_handler (stmt).op1_range (r, type, lhs_range, trange);
- }
- 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
-// second operand if the lhs of the expression has the range LHS_RANGE
-// and the first operand has the range OP1_RANGE. Return false if
-// nothing can be determined.
-
-bool
-gimple_range_calc_op2 (vrange &r, const gimple *stmt,
- const vrange &lhs_range, const vrange &op1_range)
-{
- // Give up on empty ranges.
- if (lhs_range.undefined_p ())
- return false;
-
- tree type = TREE_TYPE (gimple_range_operand2 (stmt));
- // If op1 is undefined, solve as if it is varying.
- if (op1_range.undefined_p ())
- {
- tree op1_type = TREE_TYPE (gimple_range_operand1 (stmt));
- Value_Range trange (op1_type);
- trange.set_varying (op1_type);
- return range_op_handler (stmt).op2_range (r, type, lhs_range, trange);
- }
- return range_op_handler (stmt).op2_range (r, type, lhs_range,
- op1_range);
-}
-
// Return TRUE if GS is a logical && or || expression.
static inline bool
@@ -695,17 +618,18 @@ gori_compute::compute_operand_range (vrange &r, gimple *stmt,
if (is_a<gswitch *> (stmt))
return compute_operand_range_switch (r, as_a<gswitch *> (stmt), lhs, name,
src);
- if (!range_op_handler (stmt))
+ gimple_range_op_handler handler (stmt);
+ if (!handler)
return false;
- tree op1 = gimple_range_ssa_p (gimple_range_operand1 (stmt));
- tree op2 = gimple_range_ssa_p (gimple_range_operand2 (stmt));
+ tree op1 = gimple_range_ssa_p (handler.operand1 ());
+ tree op2 = gimple_range_ssa_p (handler.operand2 ());
// Handle end of lookup first.
if (op1 == name)
- return compute_operand1_range (r, stmt, lhs, name, src);
+ return compute_operand1_range (r, handler, lhs, name, src);
if (op2 == name)
- return compute_operand2_range (r, stmt, lhs, name, src);
+ return compute_operand2_range (r, handler, lhs, name, src);
// NAME is not in this stmt, but one of the names in it ought to be
// derived from it.
@@ -733,10 +657,10 @@ gori_compute::compute_operand_range (vrange &r, gimple *stmt,
tree type = TREE_TYPE (name);
Value_Range op1_trange (type), op1_frange (type);
Value_Range op2_trange (type), op2_frange (type);
- compute_logical_operands (op1_trange, op1_frange, stmt,
+ compute_logical_operands (op1_trange, op1_frange, handler,
as_a <irange> (lhs),
name, src, op1, op1_in_chain);
- compute_logical_operands (op2_trange, op2_frange, stmt,
+ compute_logical_operands (op2_trange, op2_frange, handler,
as_a <irange> (lhs),
name, src, op2, op2_in_chain);
res = logical_combine (r,
@@ -748,11 +672,11 @@ gori_compute::compute_operand_range (vrange &r, gimple *stmt,
}
// Follow the appropriate operands now.
else if (op1_in_chain && op2_in_chain)
- res = compute_operand1_and_operand2_range (r, stmt, lhs, name, src);
+ res = compute_operand1_and_operand2_range (r, handler, lhs, name, src);
else if (op1_in_chain)
- res = compute_operand1_range (r, stmt, lhs, name, src);
+ res = compute_operand1_range (r, handler, lhs, name, src);
else if (op2_in_chain)
- res = compute_operand2_range (r, stmt, lhs, name, src);
+ res = compute_operand2_range (r, handler, lhs, name, src);
else
gcc_unreachable ();
@@ -944,13 +868,14 @@ gori_compute::logical_combine (vrange &r, enum tree_code code,
void
gori_compute::compute_logical_operands (vrange &true_range, vrange &false_range,
- gimple *stmt,
+ gimple_range_op_handler &handler,
const irange &lhs,
tree name, fur_source &src,
tree op, bool op_in_chain)
{
+ gimple *stmt = handler.stmt ();
gimple *src_stmt = gimple_range_ssa_p (op) ? SSA_NAME_DEF_STMT (op) : NULL;
- if (!op_in_chain || !src_stmt || chain_import_p (gimple_get_lhs (stmt), op))
+ if (!op_in_chain || !src_stmt || chain_import_p (handler.lhs (), op))
{
// If op is not in the def chain, or defined in this block,
// use its known value on entry to the block.
@@ -999,12 +924,15 @@ gori_compute::compute_logical_operands (vrange &true_range, vrange &false_range,
// R, or false if no range could be calculated.
bool
-gori_compute::compute_operand1_range (vrange &r, gimple *stmt,
+gori_compute::compute_operand1_range (vrange &r,
+ gimple_range_op_handler &handler,
const vrange &lhs, tree name,
fur_source &src)
{
- tree op1 = gimple_range_operand1 (stmt);
- tree op2 = gimple_range_operand2 (stmt);
+ gimple *stmt = handler.stmt ();
+ tree op1 = handler.operand1 ();
+ tree op2 = handler.operand2 ();
+
Value_Range op1_range (TREE_TYPE (op1));
Value_Range tmp (TREE_TYPE (op1));
Value_Range op2_range (op2 ? TREE_TYPE (op2) : TREE_TYPE (op1));
@@ -1016,7 +944,7 @@ gori_compute::compute_operand1_range (vrange &r, gimple *stmt,
if (op2)
{
src.get_operand (op2_range, op2);
- if (!gimple_range_calc_op1 (tmp, stmt, lhs, op2_range))
+ if (!handler.calc_op1 (tmp, lhs, op2_range))
return false;
}
else
@@ -1024,7 +952,7 @@ gori_compute::compute_operand1_range (vrange &r, gimple *stmt,
// 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 (!gimple_range_calc_op1 (tmp, stmt, lhs, op1_range))
+ if (!handler.calc_op1 (tmp, lhs, op1_range))
return false;
}
@@ -1079,12 +1007,15 @@ gori_compute::compute_operand1_range (vrange &r, gimple *stmt,
// R, or false if no range could be calculated.
bool
-gori_compute::compute_operand2_range (vrange &r, gimple *stmt,
+gori_compute::compute_operand2_range (vrange &r,
+ gimple_range_op_handler &handler,
const vrange &lhs, tree name,
fur_source &src)
{
- tree op1 = gimple_range_operand1 (stmt);
- tree op2 = gimple_range_operand2 (stmt);
+ gimple *stmt = handler.stmt ();
+ tree op1 = handler.operand1 ();
+ tree op2 = handler.operand2 ();
+
Value_Range op1_range (TREE_TYPE (op1));
Value_Range op2_range (TREE_TYPE (op2));
Value_Range tmp (TREE_TYPE (op2));
@@ -1093,7 +1024,7 @@ gori_compute::compute_operand2_range (vrange &r, gimple *stmt,
src.get_operand (op2_range, op2);
// Intersect with range for op2 based on lhs and op1.
- if (!gimple_range_calc_op2 (tmp, stmt, lhs, op1_range))
+ if (!handler.calc_op2 (tmp, lhs, op1_range))
return false;
unsigned idx;
@@ -1148,7 +1079,8 @@ gori_compute::compute_operand2_range (vrange &r, gimple *stmt,
bool
gori_compute::compute_operand1_and_operand2_range (vrange &r,
- gimple *stmt,
+ gimple_range_op_handler
+ &handler,
const vrange &lhs,
tree name,
fur_source &src)
@@ -1157,11 +1089,11 @@ gori_compute::compute_operand1_and_operand2_range (vrange &r,
// Calculate a good a range for op2. Since op1 == op2, this will
// have already included whatever the actual range of name is.
- if (!compute_operand2_range (op_range, stmt, lhs, name, src))
+ if (!compute_operand2_range (op_range, handler, lhs, name, src))
return false;
// Now get the range thru op1.
- if (!compute_operand1_range (r, stmt, lhs, name, src))
+ if (!compute_operand1_range (r, handler, lhs, name, src))
return false;
// Both operands have to be simultaneously true, so perform an intersection.
diff --git a/gcc/gimple-range-gori.h b/gcc/gimple-range-gori.h
index 3d57ab94624..0c776ef853f 100644
--- a/gcc/gimple-range-gori.h
+++ b/gcc/gimple-range-gori.h
@@ -170,17 +170,18 @@ private:
tree name, class fur_source &src);
bool compute_operand_range_switch (vrange &r, gswitch *s, const vrange &lhs,
tree name, fur_source &src);
- bool compute_operand1_range (vrange &r, gimple *stmt, const vrange &lhs,
- tree name, fur_source &src);
- bool compute_operand2_range (vrange &r, gimple *stmt, const vrange &lhs,
- tree name, fur_source &src);
- bool compute_operand1_and_operand2_range (vrange &r, gimple *stmt,
+ bool compute_operand1_range (vrange &r, gimple_range_op_handler &handler,
+ const vrange &lhs, tree name, fur_source &src);
+ bool compute_operand2_range (vrange &r, gimple_range_op_handler &handler,
+ const vrange &lhs, tree name, fur_source &src);
+ bool compute_operand1_and_operand2_range (vrange &r,
+ gimple_range_op_handler &handler,
const vrange &lhs, tree name,
fur_source &src);
void compute_logical_operands (vrange &true_range, vrange &false_range,
- gimple *stmt, const irange &lhs,
- tree name, fur_source &src, tree op,
- bool op_in_chain);
+ gimple_range_op_handler &handler,
+ const irange &lhs, tree name, fur_source &src,
+ tree op, bool op_in_chain);
bool logical_combine (vrange &r, enum tree_code code, const irange &lhs,
const vrange &op1_true, const vrange &op1_false,
const vrange &op2_true, const vrange &op2_false);
@@ -192,16 +193,6 @@ private:
int m_not_executable_flag;
};
-// These routines provide a GIMPLE interface to the range-ops code.
-extern bool gimple_range_calc_op1 (vrange &r, const gimple *s,
- const vrange &lhs_range);
-extern bool gimple_range_calc_op1 (vrange &r, const gimple *s,
- const vrange &lhs_range,
- const vrange &op2_range);
-extern bool gimple_range_calc_op2 (vrange &r, const gimple *s,
- const vrange &lhs_range,
- const vrange &op1_range);
-
// For each name that is an import into BB's exports..
#define FOR_EACH_GORI_IMPORT_NAME(gori, bb, name) \
for (gori_export_iterator iter ((gori).imports ((bb))); \
diff --git a/gcc/gimple-range-op.cc b/gcc/gimple-range-op.cc
new file mode 100644
index 00000000000..f03125a0fc5
--- /dev/null
+++ b/gcc/gimple-range-op.cc
@@ -0,0 +1,245 @@
+/* Code for GIMPLE range op related routines.
+ Copyright (C) 2019-2022 Free Software Foundation, Inc.
+ Contributed by Andrew MacLeod <amacleod@redhat.com>
+ and Aldy Hernandez <aldyh@redhat.com>.
+
+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
+<http://www.gnu.org/licenses/>. */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "backend.h"
+#include "insn-codes.h"
+#include "tree.h"
+#include "gimple.h"
+#include "ssa.h"
+#include "gimple-pretty-print.h"
+#include "optabs-tree.h"
+#include "gimple-iterator.h"
+#include "gimple-fold.h"
+#include "wide-int.h"
+#include "fold-const.h"
+#include "case-cfn-macros.h"
+#include "omp-general.h"
+#include "cfgloop.h"
+#include "tree-ssa-loop.h"
+#include "tree-scalar-evolution.h"
+#include "langhooks.h"
+#include "vr-values.h"
+#include "range.h"
+#include "value-query.h"
+#include "gimple-range.h"
+
+// Given stmt S, fill VEC, up to VEC_SIZE elements, with relevant ssa-names
+// on the statement. For efficiency, it is an error to not pass in enough
+// elements for the vector. Return the number of ssa-names.
+
+unsigned
+gimple_range_ssa_names (tree *vec, unsigned vec_size, gimple *stmt)
+{
+ tree ssa;
+ int count = 0;
+
+ gimple_range_op_handler handler (stmt);
+ if (handler)
+ {
+ gcc_checking_assert (vec_size >= 2);
+ if ((ssa = gimple_range_ssa_p (handler.operand1 ())))
+ vec[count++] = ssa;
+ if ((ssa = gimple_range_ssa_p (handler.operand2 ())))
+ vec[count++] = ssa;
+ }
+ else if (is_a<gassign *> (stmt)
+ && gimple_assign_rhs_code (stmt) == COND_EXPR)
+ {
+ gcc_checking_assert (vec_size >= 3);
+ gassign *st = as_a<gassign *> (stmt);
+ if ((ssa = gimple_range_ssa_p (gimple_assign_rhs1 (st))))
+ vec[count++] = ssa;
+ if ((ssa = gimple_range_ssa_p (gimple_assign_rhs2 (st))))
+ vec[count++] = ssa;
+ if ((ssa = gimple_range_ssa_p (gimple_assign_rhs3 (st))))
+ vec[count++] = ssa;
+ }
+ return count;
+}
+
+// Return the base of the RHS of an assignment.
+
+static tree
+gimple_range_base_of_assignment (const gimple *stmt)
+{
+ gcc_checking_assert (gimple_code (stmt) == GIMPLE_ASSIGN);
+ tree op1 = gimple_assign_rhs1 (stmt);
+ if (gimple_assign_rhs_code (stmt) == ADDR_EXPR)
+ return get_base_address (TREE_OPERAND (op1, 0));
+ return op1;
+}
+
+// If statement is supported by range-ops, set the CODE and return the TYPE.
+
+static tree
+get_code_and_type (gimple *s, enum tree_code &code)
+{
+ tree type = NULL_TREE;
+ code = NOP_EXPR;
+
+ if (const gassign *ass = dyn_cast<const gassign *> (s))
+ {
+ 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)
+ type = TREE_TYPE (gimple_assign_rhs1 (ass));
+ else
+ type = TREE_TYPE (gimple_assign_lhs (ass));
+ }
+ else if (const gcond *cond = dyn_cast<const gcond *> (s))
+ {
+ code = gimple_cond_code (cond);
+ type = TREE_TYPE (gimple_cond_lhs (cond));
+ }
+ return type;
+}
+
+// If statement S has a supported range_op handler return TRUE.
+
+bool
+gimple_range_op_handler::supported_p (gimple *s)
+{
+ enum tree_code code;
+ tree type = get_code_and_type (s, code);
+ return (type && range_op_handler (code, type));
+}
+
+// Construct a handler object for statement S.
+
+gimple_range_op_handler::gimple_range_op_handler (gimple *s)
+{
+ enum tree_code code;
+ tree type = get_code_and_type (s, code);
+ m_stmt = s;
+ if (type)
+ set_op_handler (code, type);
+
+ if (m_valid)
+ switch (gimple_code (m_stmt))
+ {
+ case GIMPLE_COND:
+ m_op1 = gimple_cond_lhs (m_stmt);
+ m_op2 = gimple_cond_rhs (m_stmt);
+ break;
+ case GIMPLE_ASSIGN:
+ m_op1 = gimple_range_base_of_assignment (m_stmt);
+ if (m_op1 && TREE_CODE (m_op1) == MEM_REF)
+ {
+ // If the base address is an SSA_NAME, we return it
+ // here. This allows processing of the range of that
+ // name, while the rest of the expression is simply
+ // ignored. The code in range_ops will see the
+ // ADDR_EXPR and do the right thing.
+ tree ssa = TREE_OPERAND (m_op1, 0);
+ if (TREE_CODE (ssa) == SSA_NAME)
+ m_op1 = ssa;
+ }
+ if (gimple_num_ops (m_stmt) >= 3)
+ m_op2 = gimple_assign_rhs2 (m_stmt);
+ else
+ m_op2 = NULL_TREE;
+ break;
+ default:
+ m_op1 = NULL_TREE;
+ m_op2 = NULL_TREE;
+ break;
+ }
+}
+
+// Calculate what we can determine of the range of this unary
+// statement's operand if the lhs of the expression has the range
+// LHS_RANGE. Return false if nothing can be determined.
+
+bool
+gimple_range_op_handler::calc_op1 (vrange &r, const vrange &lhs_range)
+{
+ gcc_checking_assert (gimple_num_ops (m_stmt) < 3);
+ // Give up on empty ranges.
+ if (lhs_range.undefined_p ())
+ return false;
+
+ // Unary operations require the type of the first operand in the
+ // second range position.
+ tree type = TREE_TYPE (operand1 ());
+ Value_Range type_range (type);
+ type_range.set_varying (type);
+ return op1_range (r, type, lhs_range, type_range);
+}
+
+// Calculate what we can determine of the range of this statement's
+// first operand if the lhs of the expression has the range LHS_RANGE
+// and the second operand has the range OP2_RANGE. Return false if
+// nothing can be determined.
+
+bool
+gimple_range_op_handler::calc_op1 (vrange &r, const vrange &lhs_range,
+ const vrange &op2_range)
+{
+ // Give up on empty ranges.
+ if (lhs_range.undefined_p ())
+ return false;
+
+ // Unary operation are allowed to pass a range in for second operand
+ // as there are often additional restrictions beyond the type which
+ // can be imposed. See operator_cast::op1_range().
+ tree type = TREE_TYPE (operand1 ());
+ // If op2 is undefined, solve as if it is varying.
+ if (op2_range.undefined_p ())
+ {
+ // This is sometimes invoked on single operand stmts.
+ if (gimple_num_ops (m_stmt) < 3)
+ return false;
+ tree op2_type = TREE_TYPE (operand2 ());
+ Value_Range trange (op2_type);
+ trange.set_varying (op2_type);
+ return op1_range (r, type, lhs_range, trange);
+ }
+ return op1_range (r, type, lhs_range, op2_range);
+}
+
+// Calculate what we can determine of the range of this statement's
+// second operand if the lhs of the expression has the range LHS_RANGE
+// and the first operand has the range OP1_RANGE. Return false if
+// nothing can be determined.
+
+bool
+gimple_range_op_handler::calc_op2 (vrange &r, const vrange &lhs_range,
+ const vrange &op1_range)
+{
+ // Give up on empty ranges.
+ if (lhs_range.undefined_p ())
+ return false;
+
+ tree type = TREE_TYPE (operand2 ());
+ // If op1 is undefined, solve as if it is varying.
+ if (op1_range.undefined_p ())
+ {
+ tree op1_type = TREE_TYPE (operand1 ());
+ Value_Range trange (op1_type);
+ trange.set_varying (op1_type);
+ return op2_range (r, type, lhs_range, trange);
+ }
+ return op2_range (r, type, lhs_range, op1_range);
+}
diff --git a/gcc/gimple-range-op.h b/gcc/gimple-range-op.h
new file mode 100644
index 00000000000..8bc0a8fbe11
--- /dev/null
+++ b/gcc/gimple-range-op.h
@@ -0,0 +1,51 @@
+/* Header file for the GIMPLE range-op interface.
+ Copyright (C) 2022 Free Software Foundation, Inc.
+ Contributed by Andrew MacLeod <amacleod@redhat.com>
+ and Aldy Hernandez <aldyh@redhat.com>.
+
+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
+<http://www.gnu.org/licenses/>. */
+
+#ifndef GCC_GIMPLE_RANGE_OP_H
+#define GCC_GIMPLE_RANGE_OP_H
+
+#include "range-op.h"
+
+
+class gimple_range_op_handler : public range_op_handler
+{
+public:
+ static bool supported_p (gimple *s);
+ gimple_range_op_handler (gimple *s);
+ inline gimple *stmt () const { return m_stmt; }
+ inline tree lhs () const { return gimple_get_lhs (m_stmt); }
+ tree operand1 () const { gcc_checking_assert (m_valid); return m_op1; }
+ 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);
+ bool calc_op2 (vrange &r, const vrange &lhs_range, const vrange &op1_range);
+private:
+ gimple *m_stmt;
+ tree m_op1, m_op2;
+};
+
+// Given stmt S, fill VEC, up to VEC_SIZE elements, with relevant ssa-names
+// on the statement. For efficiency, it is an error to not pass in enough
+// elements for the vector. Return the number of ssa-names.
+
+unsigned gimple_range_ssa_names (tree *vec, unsigned vec_size, gimple *stmt);
+
+#endif // GCC_GIMPLE_RANGE_OP_H
diff --git a/gcc/gimple-range.cc b/gcc/gimple-range.cc
index eb347eee45b..d67d6499c78 100644
--- a/gcc/gimple-range.cc
+++ b/gcc/gimple-range.cc
@@ -341,7 +341,7 @@ gimple_ranger::prefill_name (vrange &r, tree name)
if (!gimple_range_ssa_p (name))
return;
gimple *stmt = SSA_NAME_DEF_STMT (name);
- if (!range_op_handler (stmt) && !is_a<gphi *> (stmt))
+ if (!gimple_range_op_handler::supported_p (stmt) && !is_a<gphi *> (stmt))
return;
bool current;
@@ -364,7 +364,7 @@ gimple_ranger::prefill_stmt_dependencies (tree ssa)
gcc_checking_assert (stmt && gimple_bb (stmt));
// Only pre-process range-ops and phis.
- if (!range_op_handler (stmt) && !is_a<gphi *> (stmt))
+ if (!gimple_range_op_handler::supported_p (stmt) && !is_a<gphi *> (stmt))
return;
// Mark where on the stack we are starting.
@@ -422,14 +422,15 @@ gimple_ranger::prefill_stmt_dependencies (tree ssa)
}
else
{
- gcc_checking_assert (range_op_handler (stmt));
- tree op = gimple_range_operand2 (stmt);
+ gimple_range_op_handler handler (stmt);
+ gcc_checking_assert (handler);
+ tree op = handler.operand2 ();
if (op)
{
Value_Range r (TREE_TYPE (op));
prefill_name (r, op);
}
- op = gimple_range_operand1 (stmt);
+ op = handler.operand1 ();
if (op)
{
Value_Range r (TREE_TYPE (op));
diff --git a/gcc/gimple-range.h b/gcc/gimple-range.h
index 34f61025ac3..8b2ff5685e5 100644
--- a/gcc/gimple-range.h
+++ b/gcc/gimple-range.h
@@ -24,7 +24,7 @@ along with GCC; see the file COPYING3. If not see
#include "range.h"
#include "value-query.h"
-#include "range-op.h"
+#include "gimple-range-op.h"
#include "gimple-range-trace.h"
#include "gimple-range-edge.h"
#include "gimple-range-fold.h"
diff --git a/gcc/range-op.cc b/gcc/range-op.cc
index f642b3f26de..9ae42b8331f 100644
--- a/gcc/range-op.cc
+++ b/gcc/range-op.cc
@@ -4182,42 +4182,19 @@ range_op_handler::set_op_handler (tree_code code, tree type)
}
}
-range_op_handler::range_op_handler (tree_code code, tree type)
+range_op_handler::range_op_handler ()
{
- set_op_handler (code, type);
+ m_int = NULL;
+ m_float = NULL;
+ m_valid = false;
}
-range_op_handler::range_op_handler (const gimple *s)
+range_op_handler::range_op_handler (tree_code code, tree type)
{
- tree_code code = NOP_EXPR;
- tree type = NULL_TREE;
-
- if (const gassign *ass = dyn_cast<const gassign *> (s))
- {
- 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)
- type = TREE_TYPE (gimple_assign_rhs1 (ass));
- else
- type = TREE_TYPE (gimple_assign_lhs (ass));
- }
- else if (const gcond *cond = dyn_cast<const gcond *> (s))
- {
- code = gimple_cond_code (cond);
- type = TREE_TYPE (gimple_cond_lhs (cond));
- }
-
- if (!type)
- {
- m_int = NULL;
- m_float = NULL;
- m_valid = false;
- }
- else
- set_op_handler (code, type);
+ set_op_handler (code, type);
}
+
bool
range_op_handler::fold_range (vrange &r, tree type,
const vrange &lh,
diff --git a/gcc/range-op.h b/gcc/range-op.h
index 56c57c46a8e..b4b5101a9e0 100644
--- a/gcc/range-op.h
+++ b/gcc/range-op.h
@@ -160,8 +160,8 @@ public:
class range_op_handler
{
public:
+ range_op_handler ();
range_op_handler (enum tree_code code, tree type);
- range_op_handler (const gimple *s);
inline operator bool () const { return m_valid; }
bool fold_range (vrange &r, tree type,
@@ -185,7 +185,7 @@ public:
const vrange &op2,
relation_kind = VREL_VARYING) const;
relation_kind op1_op2_relation (const vrange &lhs) const;
-private:
+protected:
void set_op_handler (enum tree_code code, tree type);
bool m_valid;
range_operator *m_int;
--
2.37.3
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH 04/17] Fix calc_op1 for undefined op2_range.
2022-09-22 18:49 [PATCH 00/17] Move builtin functions to range-ops Andrew MacLeod
` (2 preceding siblings ...)
2022-09-22 18:56 ` [PATCH 03/17] Create gimple_range_op_handler in a new source file Andrew MacLeod
@ 2022-09-22 18:58 ` Andrew MacLeod
2022-09-22 18:59 ` [PATCH 05/17] Add missing float fold_range prototype for floats Andrew MacLeod
` (12 subsequent siblings)
16 siblings, 0 replies; 18+ messages in thread
From: Andrew MacLeod @ 2022-09-22 18:58 UTC (permalink / raw)
To: gcc-patches; +Cc: hernandez, aldy
[-- Attachment #1: Type: text/plain, Size: 274 bytes --]
Unary operations pass the type of operand 1 into op1_range. If that
range is undefined, the routine blindly picks the type of operand
2,which in the case of a unary op, does not exist and traps.
Bootstrapped on x86_64-pc-linux-gnu with no regressions. Pushed.
Andrew
[-- Attachment #2: 0004-Fix-calc_op1-for-undefined-op2_range.patch --]
[-- Type: text/x-patch, Size: 1468 bytes --]
From a7a6649f4e7c459a95dee1600554ad06aaeb1cf6 Mon Sep 17 00:00:00 2001
From: Andrew MacLeod <amacleod@redhat.com>
Date: Thu, 22 Sep 2022 10:27:17 -0400
Subject: [PATCH 04/17] Fix calc_op1 for undefined op2_range.
Unary operations pass the type of operand 1 into op1_range. If that
range is undefined, the routine blindly picks the type of operand 2,
which in the case of a unary op, does not exist and traps.
* gimple-range-op.cc (gimple_range_op_handler::calc_op1): Use
operand 1 for second range if there is no operand 2.
---
gcc/gimple-range-op.cc | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/gcc/gimple-range-op.cc b/gcc/gimple-range-op.cc
index f03125a0fc5..ab5b389449d 100644
--- a/gcc/gimple-range-op.cc
+++ b/gcc/gimple-range-op.cc
@@ -208,10 +208,14 @@ gimple_range_op_handler::calc_op1 (vrange &r, const vrange &lhs_range,
// If op2 is undefined, solve as if it is varying.
if (op2_range.undefined_p ())
{
- // This is sometimes invoked on single operand stmts.
if (gimple_num_ops (m_stmt) < 3)
return false;
- tree op2_type = TREE_TYPE (operand2 ());
+ tree op2_type;
+ // This is sometimes invoked on single operand stmts.
+ if (operand2 ())
+ op2_type = TREE_TYPE (operand2 ());
+ else
+ op2_type = TREE_TYPE (operand1 ());
Value_Range trange (op2_type);
trange.set_varying (op2_type);
return op1_range (r, type, lhs_range, trange);
--
2.37.3
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH 05/17] Add missing float fold_range prototype for floats.
2022-09-22 18:49 [PATCH 00/17] Move builtin functions to range-ops Andrew MacLeod
` (3 preceding siblings ...)
2022-09-22 18:58 ` [PATCH 04/17] Fix calc_op1 for undefined op2_range Andrew MacLeod
@ 2022-09-22 18:59 ` Andrew MacLeod
2022-09-22 19:00 ` [PATCH 06/17] Always check the return value of fold_range Andrew MacLeod
` (11 subsequent siblings)
16 siblings, 0 replies; 18+ messages in thread
From: Andrew MacLeod @ 2022-09-22 18:59 UTC (permalink / raw)
To: gcc-patches; +Cc: hernandez, aldy
[-- Attachment #1: Type: text/plain, Size: 258 bytes --]
Unary operations require op2 to be the range of the type of the LHS.
This is so the type for the LHS can be properly set. There are is a
missing prototype for this combination.
Bootstrapped on x86_64-pc-linux-gnu with no regressions. Pushed.
Andrew
[-- Attachment #2: 0005-Add-missing-float-fold_range-prototype-for-floats.patch --]
[-- Type: text/x-patch, Size: 2701 bytes --]
From be2a25adbdc76a770f7470cc9f47892f7a4139ae Mon Sep 17 00:00:00 2001
From: Andrew MacLeod <amacleod@redhat.com>
Date: Tue, 20 Sep 2022 12:34:08 -0400
Subject: [PATCH 05/17] Add missing float fold_range prototype for floats.
Unary operations require op2 to be the range of the type of the LHS.
This is so the type for the LHS can be properly set.
* range-op-float.cc (range_operator_float::fold_range): New base
method for "int = float op int".
* range-op.cc (range_op_handler::fold_range): New case.
* range-op.h: Update prototypes.
---
gcc/range-op-float.cc | 10 ++++++++++
gcc/range-op.cc | 13 ++++++++++---
gcc/range-op.h | 5 +++++
3 files changed, 25 insertions(+), 3 deletions(-)
diff --git a/gcc/range-op-float.cc b/gcc/range-op-float.cc
index 2bd3dc9253f..aa5b7ed073d 100644
--- a/gcc/range-op-float.cc
+++ b/gcc/range-op-float.cc
@@ -58,6 +58,16 @@ range_operator_float::fold_range (frange &r ATTRIBUTE_UNUSED,
return false;
}
+bool
+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
+{
+ return false;
+}
+
bool
range_operator_float::fold_range (irange &r ATTRIBUTE_UNUSED,
tree type ATTRIBUTE_UNUSED,
diff --git a/gcc/range-op.cc b/gcc/range-op.cc
index 9ae42b8331f..072ebd32109 100644
--- a/gcc/range-op.cc
+++ b/gcc/range-op.cc
@@ -4208,9 +4208,16 @@ range_op_handler::fold_range (vrange &r, tree type,
as_a <irange> (rh), rel);
if (is_a <irange> (r))
- return m_float->fold_range (as_a <irange> (r), type,
- as_a <frange> (lh),
- as_a <frange> (rh), rel);
+ {
+ if (is_a <irange> (rh))
+ return m_float->fold_range (as_a <irange> (r), type,
+ as_a <frange> (lh),
+ as_a <irange> (rh), rel);
+ else
+ return m_float->fold_range (as_a <irange> (r), type,
+ as_a <frange> (lh),
+ as_a <frange> (rh), rel);
+ }
return m_float->fold_range (as_a <frange> (r), type,
as_a <frange> (lh),
as_a <frange> (rh), rel);
diff --git a/gcc/range-op.h b/gcc/range-op.h
index b4b5101a9e0..b2f063afb07 100644
--- a/gcc/range-op.h
+++ b/gcc/range-op.h
@@ -117,6 +117,11 @@ public:
const frange &lh,
const frange &rh,
relation_kind rel = VREL_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;
virtual bool fold_range (irange &r, tree type,
const frange &lh,
const frange &rh,
--
2.37.3
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH 06/17] Always check the return value of fold_range.
2022-09-22 18:49 [PATCH 00/17] Move builtin functions to range-ops Andrew MacLeod
` (4 preceding siblings ...)
2022-09-22 18:59 ` [PATCH 05/17] Add missing float fold_range prototype for floats Andrew MacLeod
@ 2022-09-22 19:00 ` Andrew MacLeod
2022-09-22 19:01 ` [PATCH 07/17] Add range-ops support for builtin functions Andrew MacLeod
` (10 subsequent siblings)
16 siblings, 0 replies; 18+ messages in thread
From: Andrew MacLeod @ 2022-09-22 19:00 UTC (permalink / raw)
To: gcc-patches; +Cc: hernandez, aldy
[-- Attachment #1: Type: text/plain, Size: 235 bytes --]
The fold_range routine in range-ops returns FALSE if the operation
fails. There are a few places which assume the operation was
successful. Fix those.
Bootstrapped on x86_64-pc-linux-gnu with no regressions. Pushed.
Andrew
[-- Attachment #2: 0006-Always-check-the-return-value-of-fold_range.patch --]
[-- Type: text/x-patch, Size: 4620 bytes --]
From 2f92f685da2ef9e82ee6262519919180df8f2dd9 Mon Sep 17 00:00:00 2001
From: Andrew MacLeod <amacleod@redhat.com>
Date: Wed, 21 Sep 2022 16:15:02 -0400
Subject: [PATCH 06/17] Always check the return value of fold_range.
The fold_range routine in range-ops returns FALSE if the operation
fails. There are a few places which assume the operation was
successful. Fix those.
* gimple-range-fold.cc (range_of_range_op): Set result to
VARYING if the call to fold_range fails.
* tree-data-ref.cc (compute_distributive_range): Ditto.
* tree-vrp.cc (range_fold_binary_expr): Ditto.
(range_fold_unary_expr): Ditto.
* value-query.cc (range_query::get_tree_range): Ditto.
---
gcc/gimple-range-fold.cc | 6 ++++--
gcc/tree-data-ref.cc | 6 ++++--
gcc/tree-vrp.cc | 6 ++++--
gcc/value-query.cc | 6 ++++--
4 files changed, 16 insertions(+), 8 deletions(-)
diff --git a/gcc/gimple-range-fold.cc b/gcc/gimple-range-fold.cc
index addf3e7f254..42408254c35 100644
--- a/gcc/gimple-range-fold.cc
+++ b/gcc/gimple-range-fold.cc
@@ -544,7 +544,8 @@ fold_using_range::range_of_range_op (vrange &r,
// Fold range, and register any dependency if available.
Value_Range r2 (type);
r2.set_varying (type);
- handler.fold_range (r, type, range1, r2);
+ if (!handler.fold_range (r, type, range1, r2))
+ r.set_varying (type);
if (lhs && gimple_range_ssa_p (op1))
{
if (src.gori ())
@@ -567,7 +568,8 @@ fold_using_range::range_of_range_op (vrange &r,
fputc ('\n', dump_file);
}
// Fold range, and register any dependency if available.
- handler.fold_range (r, type, range1, range2, rel);
+ if (!handler.fold_range (r, type, range1, range2, rel))
+ r.set_varying (type);
if (irange::supports_p (type))
relation_fold_and_or (as_a <irange> (r), s, src);
if (lhs)
diff --git a/gcc/tree-data-ref.cc b/gcc/tree-data-ref.cc
index ff9327f6deb..91bfb619d66 100644
--- a/gcc/tree-data-ref.cc
+++ b/gcc/tree-data-ref.cc
@@ -594,7 +594,8 @@ compute_distributive_range (tree type, value_range &op0_range,
if (result_range)
{
range_op_handler op (code, type);
- op.fold_range (*result_range, type, op0_range, op1_range);
+ if (!op.fold_range (*result_range, type, op0_range, op1_range))
+ result_range->set_varying (type);
}
/* The distributive property guarantees that if TYPE is no narrower
@@ -642,7 +643,8 @@ compute_distributive_range (tree type, value_range &op0_range,
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);
+ if (!op.fold_range (wide_range, ssizetype, op0_range, op1_range))
+ wide_range.set_varying (ssizetype);;
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 c3030a1b130..93482e5d102 100644
--- a/gcc/tree-vrp.cc
+++ b/gcc/tree-vrp.cc
@@ -1069,7 +1069,8 @@ 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);
+ if (!op.fold_range (*vr, expr_type, vr0, vr1))
+ vr->set_varying (expr_type);
}
/* Perform a unary operation on a range. */
@@ -1095,7 +1096,8 @@ range_fold_unary_expr (value_range *vr,
value_range vr0_cst (*vr0);
vr0_cst.normalize_addresses ();
- op.fold_range (*vr, expr_type, vr0_cst, value_range (expr_type));
+ if (!op.fold_range (*vr, expr_type, vr0_cst, value_range (expr_type)))
+ vr->set_varying (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 0bdd670982b..296784be31d 100644
--- a/gcc/value-query.cc
+++ b/gcc/value-query.cc
@@ -252,7 +252,8 @@ range_query::get_tree_range (vrange &r, tree expr, gimple *stmt)
Value_Range r1 (TREE_TYPE (TREE_OPERAND (expr, 1)));
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);
+ if (!op.fold_range (r, type, r0, r1))
+ r.set_varying (type);
}
else
r.set_varying (type);
@@ -268,7 +269,8 @@ range_query::get_tree_range (vrange &r, tree expr, gimple *stmt)
Value_Range r1 (type);
r1.set_varying (type);
range_of_expr (r0, TREE_OPERAND (expr, 0), stmt);
- op.fold_range (r, type, r0, r1);
+ if (!op.fold_range (r, type, r0, r1))
+ r.set_varying (type);
}
else
r.set_varying (type);
--
2.37.3
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH 07/17] Add range-ops support for builtin functions.
2022-09-22 18:49 [PATCH 00/17] Move builtin functions to range-ops Andrew MacLeod
` (5 preceding siblings ...)
2022-09-22 19:00 ` [PATCH 06/17] Always check the return value of fold_range Andrew MacLeod
@ 2022-09-22 19:01 ` Andrew MacLeod
2022-09-22 19:02 ` [PATCH 08/17] Convert CFN_BUILT_IN_SIGNBIT to range-ops Andrew MacLeod
` (9 subsequent siblings)
16 siblings, 0 replies; 18+ messages in thread
From: Andrew MacLeod @ 2022-09-22 19:01 UTC (permalink / raw)
To: gcc-patches; +Cc: hernandez, aldy
[-- Attachment #1: Type: text/plain, Size: 176 bytes --]
Check for builtins that can be a range-op entry and Convert
CFN_BUILT_IN_CONSTANT_P as first POC.
Bootstrapped on x86_64-pc-linux-gnu with no regressions. Pushed.
Andrew
[-- Attachment #2: 0007-Add-range-ops-support-for-builtin-functions.patch --]
[-- Type: text/x-patch, Size: 6083 bytes --]
From b40b3035879cf695b72010858b9705a344292bdb Mon Sep 17 00:00:00 2001
From: Andrew MacLeod <amacleod@redhat.com>
Date: Tue, 20 Sep 2022 16:53:37 -0400
Subject: [PATCH 07/17] Add range-ops support for builtin functions.
Convert CFN_BUILT_IN_CONSTANT_P as first POC.
* gimple-range-fold.cc
(fold_using_range::range_of_builtin_int_call): Remove case for
CFN_BUILT_IN_CONSTANT_P.
* gimple-range-op.cc (gimple_range_op_handler::supported_p):
Check if a call also creates a range-op object.
(gimple_range_op_handler): Also check builtin calls.
(class cfn_constant_float_p): New. Float CFN_BUILT_IN_CONSTANT_P.
(class cfn_constant_p): New. Integral CFN_BUILT_IN_CONSTANT_P.
(gimple_range_op_handler::maybe_builtin_call): Set arguments and
handler for supported built-in calls.
* gimple-range-op.h (maybe_builtin_call): New prototype.
---
gcc/gimple-range-fold.cc | 17 -------
gcc/gimple-range-op.cc | 104 ++++++++++++++++++++++++++++++++++++---
gcc/gimple-range-op.h | 1 +
3 files changed, 97 insertions(+), 25 deletions(-)
diff --git a/gcc/gimple-range-fold.cc b/gcc/gimple-range-fold.cc
index 42408254c35..63a1f517d28 100644
--- a/gcc/gimple-range-fold.cc
+++ b/gcc/gimple-range-fold.cc
@@ -944,23 +944,6 @@ fold_using_range::range_of_builtin_int_call (irange &r, gcall *call,
switch (func)
{
- case CFN_BUILT_IN_CONSTANT_P:
- {
- arg = gimple_call_arg (call, 0);
- Value_Range tmp (TREE_TYPE (arg));
- if (src.get_operand (tmp, arg) && tmp.singleton_p ())
- {
- r.set (build_one_cst (type), build_one_cst (type));
- return true;
- }
- if (cfun->after_inlining)
- {
- r.set_zero (type);
- return true;
- }
- break;
- }
-
case CFN_BUILT_IN_SIGNBIT:
{
arg = gimple_call_arg (call, 0);
diff --git a/gcc/gimple-range-op.cc b/gcc/gimple-range-op.cc
index ab5b389449d..bcc4c3d778c 100644
--- a/gcc/gimple-range-op.cc
+++ b/gcc/gimple-range-op.cc
@@ -123,7 +123,11 @@ gimple_range_op_handler::supported_p (gimple *s)
{
enum tree_code code;
tree type = get_code_and_type (s, code);
- return (type && range_op_handler (code, type));
+ if (type && range_op_handler (code, type))
+ return true;
+ if (is_a <gcall *> (s) && gimple_range_op_handler (s))
+ return true;
+ return false;
}
// Construct a handler object for statement S.
@@ -133,6 +137,8 @@ gimple_range_op_handler::gimple_range_op_handler (gimple *s)
enum tree_code code;
tree type = get_code_and_type (s, code);
m_stmt = s;
+ m_op1 = NULL_TREE;
+ m_op2 = NULL_TREE;
if (type)
set_op_handler (code, type);
@@ -142,7 +148,7 @@ gimple_range_op_handler::gimple_range_op_handler (gimple *s)
case GIMPLE_COND:
m_op1 = gimple_cond_lhs (m_stmt);
m_op2 = gimple_cond_rhs (m_stmt);
- break;
+ return;
case GIMPLE_ASSIGN:
m_op1 = gimple_range_base_of_assignment (m_stmt);
if (m_op1 && TREE_CODE (m_op1) == MEM_REF)
@@ -158,14 +164,15 @@ gimple_range_op_handler::gimple_range_op_handler (gimple *s)
}
if (gimple_num_ops (m_stmt) >= 3)
m_op2 = gimple_assign_rhs2 (m_stmt);
- else
- m_op2 = NULL_TREE;
- break;
+ return;
default:
- m_op1 = NULL_TREE;
- m_op2 = NULL_TREE;
- break;
+ gcc_unreachable ();
+ return;
}
+ // If no range-op table entry handled this stmt, check for other supported
+ // statements.
+ if (is_a <gcall *> (m_stmt))
+ maybe_builtin_call ();
}
// Calculate what we can determine of the range of this unary
@@ -247,3 +254,84 @@ gimple_range_op_handler::calc_op2 (vrange &r, const vrange &lhs_range,
}
return op2_range (r, type, lhs_range, op1_range);
}
+
+// --------------------------------------------------------------------
+
+// Implement range operator for float CFN_BUILT_IN_CONSTANT_P.
+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
+ {
+ if (lh.singleton_p ())
+ {
+ r.set (build_one_cst (type), build_one_cst (type));
+ return true;
+ }
+ if (cfun->after_inlining)
+ {
+ r.set_zero (type);
+ return true;
+ }
+ return false;
+ }
+} op_cfn_constant_float_p;
+
+// Implement range operator for integral CFN_BUILT_IN_CONSTANT_P.
+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
+ {
+ if (lh.singleton_p ())
+ {
+ r.set (build_one_cst (type), build_one_cst (type));
+ return true;
+ }
+ if (cfun->after_inlining)
+ {
+ r.set_zero (type);
+ return true;
+ }
+ return false;
+ }
+} op_cfn_constant_p;
+
+// Set up a gimple_range_op_handler for any built in function which can be
+// supported via range-ops.
+
+void
+gimple_range_op_handler::maybe_builtin_call ()
+{
+ gcc_checking_assert (is_a <gcall *> (m_stmt));
+
+ gcall *call = as_a <gcall *> (m_stmt);
+ combined_fn func = gimple_call_combined_fn (call);
+ if (func == CFN_LAST)
+ return;
+ tree type = gimple_range_type (call);
+ gcc_checking_assert (type);
+ if (!Value_Range::supports_type_p (type))
+ return;
+
+ switch (func)
+ {
+ case CFN_BUILT_IN_CONSTANT_P:
+ m_op1 = gimple_call_arg (call, 0);
+ m_valid = true;
+ if (irange::supports_p (TREE_TYPE (m_op1)))
+ m_int = &op_cfn_constant_p;
+ else if (frange::supports_p (TREE_TYPE (m_op1)))
+ m_float = &op_cfn_constant_float_p;
+ else
+ m_valid = false;
+ break;
+
+ default:
+ break;
+ }
+}
diff --git a/gcc/gimple-range-op.h b/gcc/gimple-range-op.h
index 8bc0a8fbe11..68764198bc0 100644
--- a/gcc/gimple-range-op.h
+++ b/gcc/gimple-range-op.h
@@ -38,6 +38,7 @@ public:
bool calc_op1 (vrange &r, const vrange &lhs_range, const vrange &op2_range);
bool calc_op2 (vrange &r, const vrange &lhs_range, const vrange &op1_range);
private:
+ void maybe_builtin_call ();
gimple *m_stmt;
tree m_op1, m_op2;
};
--
2.37.3
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH 08/17] Convert CFN_BUILT_IN_SIGNBIT to range-ops.
2022-09-22 18:49 [PATCH 00/17] Move builtin functions to range-ops Andrew MacLeod
` (6 preceding siblings ...)
2022-09-22 19:01 ` [PATCH 07/17] Add range-ops support for builtin functions Andrew MacLeod
@ 2022-09-22 19:02 ` Andrew MacLeod
2022-09-22 19:05 ` [PATCH 09/17] Convert CFN_BUILT_IN_TOUPPER and TOLOWER " Andrew MacLeod
` (8 subsequent siblings)
16 siblings, 0 replies; 18+ messages in thread
From: Andrew MacLeod @ 2022-09-22 19:02 UTC (permalink / raw)
To: gcc-patches; +Cc: hernandez, aldy
[-- Attachment #1: Type: text/plain, Size: 77 bytes --]
Bootstrapped on x86_64-pc-linux-gnu with no regressions. Pushed.
Andrew
[-- Attachment #2: 0008-Convert-CFN_BUILT_IN_SIGNBIT-to-range-ops.patch --]
[-- Type: text/x-patch, Size: 2384 bytes --]
From eb82b9f68eb8d0cc65a1a022154c8e729860ea59 Mon Sep 17 00:00:00 2001
From: Andrew MacLeod <amacleod@redhat.com>
Date: Wed, 21 Sep 2022 09:29:40 -0400
Subject: [PATCH 08/17] Convert CFN_BUILT_IN_SIGNBIT to range-ops.
* gimple-range-fold.cc (range_of_builtin_int_call): Remove case
for CFN_BUILT_IN_SIGNBIT.
* gimple-range-op.cc (class cfn_signbit): New.
(gimple_range_op_handler::maybe_builtin_call): Set arguments.
---
gcc/gimple-range-fold.cc | 20 --------------------
gcc/gimple-range-op.cc | 27 +++++++++++++++++++++++++++
2 files changed, 27 insertions(+), 20 deletions(-)
diff --git a/gcc/gimple-range-fold.cc b/gcc/gimple-range-fold.cc
index 63a1f517d28..417a925ac9f 100644
--- a/gcc/gimple-range-fold.cc
+++ b/gcc/gimple-range-fold.cc
@@ -944,26 +944,6 @@ fold_using_range::range_of_builtin_int_call (irange &r, gcall *call,
switch (func)
{
- case CFN_BUILT_IN_SIGNBIT:
- {
- arg = gimple_call_arg (call, 0);
- frange tmp;
- if (src.get_operand (tmp, arg))
- {
- bool signbit;
- if (tmp.signbit_p (signbit))
- {
- if (signbit)
- r.set_nonzero (type);
- else
- r.set_zero (type);
- return true;
- }
- return false;
- }
- break;
- }
-
case CFN_BUILT_IN_TOUPPER:
{
arg = gimple_call_arg (call, 0);
diff --git a/gcc/gimple-range-op.cc b/gcc/gimple-range-op.cc
index bcc4c3d778c..d62dff5f92e 100644
--- a/gcc/gimple-range-op.cc
+++ b/gcc/gimple-range-op.cc
@@ -301,6 +301,27 @@ public:
}
} op_cfn_constant_p;
+// Implement range operator for CFN_BUILT_IN_SIGNBIT.
+class cfn_signbit : 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
+ {
+ bool signbit;
+ if (lh.signbit_p (signbit))
+ {
+ if (signbit)
+ r.set_nonzero (type);
+ else
+ r.set_zero (type);
+ return true;
+ }
+ return false;
+ }
+} op_cfn_signbit;
+
// Set up a gimple_range_op_handler for any built in function which can be
// supported via range-ops.
@@ -331,6 +352,12 @@ gimple_range_op_handler::maybe_builtin_call ()
m_valid = false;
break;
+ case CFN_BUILT_IN_SIGNBIT:
+ m_op1 = gimple_call_arg (call, 0);
+ m_float = &op_cfn_signbit;
+ m_valid = true;
+ break;
+
default:
break;
}
--
2.37.3
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH 09/17] Convert CFN_BUILT_IN_TOUPPER and TOLOWER to range-ops.
2022-09-22 18:49 [PATCH 00/17] Move builtin functions to range-ops Andrew MacLeod
` (7 preceding siblings ...)
2022-09-22 19:02 ` [PATCH 08/17] Convert CFN_BUILT_IN_SIGNBIT to range-ops Andrew MacLeod
@ 2022-09-22 19:05 ` Andrew MacLeod
2022-09-22 19:05 ` [PATCH 10/17] Convert CFN_BUILT_FFS and CFN_POPCOUNT " Andrew MacLeod
` (7 subsequent siblings)
16 siblings, 0 replies; 18+ messages in thread
From: Andrew MacLeod @ 2022-09-22 19:05 UTC (permalink / raw)
To: gcc-patches; +Cc: hernandez, aldy
[-- Attachment #1: Type: text/plain, Size: 75 bytes --]
Bootstrapped on x86_64-pc-linux-gnu with no regressions. Pushed.
Andrew
[-- Attachment #2: 0009-Convert-CFN_BUILT_IN_TOUPPER-and-TOLOWER-to-range-op.patch --]
[-- Type: text/x-patch, Size: 5969 bytes --]
From 2f5da730f159de238500c82b0c6ef6c9ab91b1c2 Mon Sep 17 00:00:00 2001
From: Andrew MacLeod <amacleod@redhat.com>
Date: Tue, 20 Sep 2022 17:14:30 -0400
Subject: [PATCH 09/17] Convert CFN_BUILT_IN_TOUPPER and TOLOWER to range-ops.
* gimple-range-fold.cc (get_letter_range): Move to new class.
(range_of_builtin_int_call): Remove case for CFN_BUILT_IN_TOUPPER
and CFN_BUILT_IN_TOLOWER.
* gimple-range-op.cc (class cfn_toupper_tolower): New.
(gimple_range_op_handler::maybe_builtin_call): Set arguments.
---
gcc/gimple-range-fold.cc | 66 ----------------------------------
gcc/gimple-range-op.cc | 77 ++++++++++++++++++++++++++++++++++++++++
2 files changed, 77 insertions(+), 66 deletions(-)
diff --git a/gcc/gimple-range-fold.cc b/gcc/gimple-range-fold.cc
index 417a925ac9f..af1f83f7409 100644
--- a/gcc/gimple-range-fold.cc
+++ b/gcc/gimple-range-fold.cc
@@ -887,28 +887,6 @@ fold_using_range::range_of_builtin_ubsan_call (irange &r, gcall *call,
r.set_varying (type);
}
-// Return TRUE if we recognize the target character set and return the
-// range for lower case and upper case letters.
-
-static bool
-get_letter_range (tree type, irange &lowers, irange &uppers)
-{
- // ASCII
- int a = lang_hooks.to_target_charset ('a');
- int z = lang_hooks.to_target_charset ('z');
- int A = lang_hooks.to_target_charset ('A');
- int Z = lang_hooks.to_target_charset ('Z');
-
- if ((z - a == 25) && (Z - A == 25))
- {
- lowers = int_range<2> (build_int_cst (type, a), build_int_cst (type, z));
- uppers = int_range<2> (build_int_cst (type, A), build_int_cst (type, Z));
- return true;
- }
- // Unknown character set.
- return false;
-}
-
// For a builtin in CALL, return a range in R if known and return
// TRUE. Otherwise return FALSE.
@@ -944,50 +922,6 @@ fold_using_range::range_of_builtin_int_call (irange &r, gcall *call,
switch (func)
{
- case CFN_BUILT_IN_TOUPPER:
- {
- arg = gimple_call_arg (call, 0);
- // If the argument isn't compatible with the LHS, do nothing.
- if (!range_compatible_p (type, TREE_TYPE (arg)))
- return false;
- if (!src.get_operand (r, arg))
- return false;
-
- int_range<3> lowers;
- int_range<3> uppers;
- if (!get_letter_range (type, lowers, uppers))
- return false;
-
- // Return the range passed in without any lower case characters,
- // but including all the upper case ones.
- lowers.invert ();
- r.intersect (lowers);
- r.union_ (uppers);
- return true;
- }
-
- case CFN_BUILT_IN_TOLOWER:
- {
- arg = gimple_call_arg (call, 0);
- // If the argument isn't compatible with the LHS, do nothing.
- if (!range_compatible_p (type, TREE_TYPE (arg)))
- return false;
- if (!src.get_operand (r, arg))
- return false;
-
- int_range<3> lowers;
- int_range<3> uppers;
- if (!get_letter_range (type, lowers, uppers))
- return false;
-
- // Return the range passed in without any upper case characters,
- // but including all the lower case ones.
- uppers.invert ();
- r.intersect (uppers);
- r.union_ (lowers);
- return true;
- }
-
CASE_CFN_FFS:
CASE_CFN_POPCOUNT:
// __builtin_ffs* and __builtin_popcount* return [0, prec].
diff --git a/gcc/gimple-range-op.cc b/gcc/gimple-range-op.cc
index d62dff5f92e..45384d990ae 100644
--- a/gcc/gimple-range-op.cc
+++ b/gcc/gimple-range-op.cc
@@ -322,6 +322,71 @@ public:
}
} op_cfn_signbit;
+// Implement range operator for CFN_BUILT_IN_TOUPPER and CFN_BUILT_IN_TOLOWER.
+class cfn_toupper_tolower : public range_operator
+{
+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;
+private:
+ bool get_letter_range (tree type, irange &lowers, irange &uppers) const;
+ bool m_toupper;
+} op_cfn_toupper (true), op_cfn_tolower (false);
+
+// Return TRUE if we recognize the target character set and return the
+// range for lower case and upper case letters.
+
+bool
+cfn_toupper_tolower::get_letter_range (tree type, irange &lowers,
+ irange &uppers) const
+{
+ // ASCII
+ int a = lang_hooks.to_target_charset ('a');
+ int z = lang_hooks.to_target_charset ('z');
+ int A = lang_hooks.to_target_charset ('A');
+ int Z = lang_hooks.to_target_charset ('Z');
+
+ if ((z - a == 25) && (Z - A == 25))
+ {
+ lowers = int_range<2> (build_int_cst (type, a), build_int_cst (type, z));
+ uppers = int_range<2> (build_int_cst (type, A), build_int_cst (type, Z));
+ return true;
+ }
+ // Unknown character set.
+ return false;
+}
+
+bool
+cfn_toupper_tolower::fold_range (irange &r, tree type, const irange &lh,
+ const irange &, relation_kind) const
+{
+ int_range<3> lowers;
+ int_range<3> uppers;
+ if (!get_letter_range (type, lowers, uppers))
+ return false;
+
+ r = lh;
+ if (m_toupper)
+ {
+ // Return the range passed in without any lower case characters,
+ // but including all the upper case ones.
+ lowers.invert ();
+ r.intersect (lowers);
+ r.union_ (uppers);
+ }
+ else
+ {
+ // Return the range passed in without any lower case characters,
+ // but including all the upper case ones.
+ uppers.invert ();
+ r.intersect (uppers);
+ r.union_ (lowers);
+ }
+ return true;
+}
+
// Set up a gimple_range_op_handler for any built in function which can be
// supported via range-ops.
@@ -358,6 +423,18 @@ gimple_range_op_handler::maybe_builtin_call ()
m_valid = true;
break;
+ case CFN_BUILT_IN_TOUPPER:
+ case CFN_BUILT_IN_TOLOWER:
+ // Only proceed If the argument is compatible with the LHS.
+ m_op1 = gimple_call_arg (call, 0);
+ if (range_compatible_p (type, TREE_TYPE (m_op1)))
+ {
+ m_valid = true;
+ m_int = (func == CFN_BUILT_IN_TOLOWER) ? &op_cfn_tolower
+ : &op_cfn_toupper;
+ }
+ break;
+
default:
break;
}
--
2.37.3
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH 10/17] Convert CFN_BUILT_FFS and CFN_POPCOUNT to range-ops.
2022-09-22 18:49 [PATCH 00/17] Move builtin functions to range-ops Andrew MacLeod
` (8 preceding siblings ...)
2022-09-22 19:05 ` [PATCH 09/17] Convert CFN_BUILT_IN_TOUPPER and TOLOWER " Andrew MacLeod
@ 2022-09-22 19:05 ` Andrew MacLeod
2022-09-22 19:05 ` [PATCH 11/17] Convert CFN_CLZ builtins " Andrew MacLeod
` (6 subsequent siblings)
16 siblings, 0 replies; 18+ messages in thread
From: Andrew MacLeod @ 2022-09-22 19:05 UTC (permalink / raw)
To: gcc-patches; +Cc: hernandez, aldy
[-- Attachment #1: Type: text/plain, Size: 77 bytes --]
Bootstrapped on x86_64-pc-linux-gnu with no regressions. Pushed.
Andrew
[-- Attachment #2: 0010-Convert-CFN_BUILT_FFS-and-CFN_POPCOUNT-to-range-ops.patch --]
[-- Type: text/x-patch, Size: 3402 bytes --]
From 5f730c650184d4c8bfad513a9e0e593f87a5bf0c Mon Sep 17 00:00:00 2001
From: Andrew MacLeod <amacleod@redhat.com>
Date: Tue, 20 Sep 2022 18:07:14 -0400
Subject: [PATCH 10/17] Convert CFN_BUILT_FFS and CFN_POPCOUNT to range-ops.
* gimple-range-fold.cc (range_of_builtin_int_call): Remove case
for CFN_FFS and CFN_POPCOUNT.
* gimple-range-op.cc (class cfn_pocount): New.
(gimple_range_op_handler::maybe_builtin_call): Set arguments.
---
gcc/gimple-range-fold.cc | 22 ----------------------
gcc/gimple-range-op.cc | 34 ++++++++++++++++++++++++++++++++++
2 files changed, 34 insertions(+), 22 deletions(-)
diff --git a/gcc/gimple-range-fold.cc b/gcc/gimple-range-fold.cc
index af1f83f7409..ca531037e13 100644
--- a/gcc/gimple-range-fold.cc
+++ b/gcc/gimple-range-fold.cc
@@ -922,28 +922,6 @@ fold_using_range::range_of_builtin_int_call (irange &r, gcall *call,
switch (func)
{
- CASE_CFN_FFS:
- CASE_CFN_POPCOUNT:
- // __builtin_ffs* and __builtin_popcount* return [0, prec].
- arg = gimple_call_arg (call, 0);
- prec = TYPE_PRECISION (TREE_TYPE (arg));
- mini = 0;
- maxi = prec;
- src.get_operand (r, arg);
- // If arg is non-zero, then ffs or popcount are non-zero.
- if (!range_includes_zero_p (&r))
- mini = 1;
- // If some high bits are known to be zero, decrease the maximum.
- if (!r.undefined_p ())
- {
- if (TYPE_SIGN (r.type ()) == SIGNED)
- range_cast (r, unsigned_type_for (r.type ()));
- wide_int max = r.upper_bound ();
- maxi = wi::floor_log2 (max) + 1;
- }
- r.set (build_int_cst (type, mini), build_int_cst (type, maxi));
- return true;
-
CASE_CFN_PARITY:
r.set (build_zero_cst (type), build_one_cst (type));
return true;
diff --git a/gcc/gimple-range-op.cc b/gcc/gimple-range-op.cc
index 45384d990ae..84837f8ee43 100644
--- a/gcc/gimple-range-op.cc
+++ b/gcc/gimple-range-op.cc
@@ -387,6 +387,33 @@ cfn_toupper_tolower::fold_range (irange &r, tree type, const irange &lh,
return true;
}
+// Implement range operator for CFN_BUILT_IN_FFS and CFN_BUILT_IN_POPCOUNT.
+class cfn_popcount : 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
+ {
+ if (lh.undefined_p ())
+ return false;
+ // __builtin_ffs* and __builtin_popcount* return [0, prec].
+ int prec = TYPE_PRECISION (lh.type ());
+ // If arg is non-zero, then ffs or popcount are non-zero.
+ int mini = range_includes_zero_p (&lh) ? 0 : 1;
+ int maxi = prec;
+
+ // If some high bits are known to be zero, decrease the maximum.
+ int_range_max tmp = lh;
+ if (TYPE_SIGN (tmp.type ()) == SIGNED)
+ range_cast (tmp, unsigned_type_for (tmp.type ()));
+ wide_int max = tmp.upper_bound ();
+ maxi = wi::floor_log2 (max) + 1;
+ r.set (build_int_cst (type, mini), build_int_cst (type, maxi));
+ return true;
+ }
+} op_cfn_popcount;
+
// Set up a gimple_range_op_handler for any built in function which can be
// supported via range-ops.
@@ -435,6 +462,13 @@ gimple_range_op_handler::maybe_builtin_call ()
}
break;
+ CASE_CFN_FFS:
+ CASE_CFN_POPCOUNT:
+ m_op1 = gimple_call_arg (call, 0);
+ m_int = &op_cfn_popcount;
+ m_valid = true;
+ break;
+
default:
break;
}
--
2.37.3
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH 11/17] Convert CFN_CLZ builtins to range-ops.
2022-09-22 18:49 [PATCH 00/17] Move builtin functions to range-ops Andrew MacLeod
` (9 preceding siblings ...)
2022-09-22 19:05 ` [PATCH 10/17] Convert CFN_BUILT_FFS and CFN_POPCOUNT " Andrew MacLeod
@ 2022-09-22 19:05 ` Andrew MacLeod
2022-09-22 19:05 ` [PATCH 12/17] Convert CFN_CTZ " Andrew MacLeod
` (5 subsequent siblings)
16 siblings, 0 replies; 18+ messages in thread
From: Andrew MacLeod @ 2022-09-22 19:05 UTC (permalink / raw)
To: gcc-patches; +Cc: hernandez, aldy
[-- Attachment #1: Type: text/plain, Size: 76 bytes --]
Bootstrapped on x86_64-pc-linux-gnu with no regressions. Pushed.
Andrew
[-- Attachment #2: 0011-Convert-CFN_CLZ-builtins-to-range-ops.patch --]
[-- Type: text/x-patch, Size: 5823 bytes --]
From ae1669a98656cca594fcd2fef6bd2cd7308a361f Mon Sep 17 00:00:00 2001
From: Andrew MacLeod <amacleod@redhat.com>
Date: Tue, 20 Sep 2022 18:12:25 -0400
Subject: [PATCH 11/17] Convert CFN_CLZ builtins to range-ops.
* gimple-range-fold.cc (range_of_builtin_int_call): Remove case
for CFN_CLZ.
* gimple-range-op.cc (class cfn_clz): New.
(gimple_range_op_handler::maybe_builtin_call): Set arguments.
---
gcc/gimple-range-fold.cc | 61 -----------------------------
gcc/gimple-range-op.cc | 84 ++++++++++++++++++++++++++++++++++++++++
2 files changed, 84 insertions(+), 61 deletions(-)
diff --git a/gcc/gimple-range-fold.cc b/gcc/gimple-range-fold.cc
index ca531037e13..63eaa90be96 100644
--- a/gcc/gimple-range-fold.cc
+++ b/gcc/gimple-range-fold.cc
@@ -926,67 +926,6 @@ fold_using_range::range_of_builtin_int_call (irange &r, gcall *call,
r.set (build_zero_cst (type), build_one_cst (type));
return true;
- CASE_CFN_CLZ:
- // __builtin_c[lt]z* return [0, prec-1], except when the
- // argument is 0, but that is undefined behavior.
- //
- // For __builtin_c[lt]z* consider argument of 0 always undefined
- // behavior, for internal fns depending on C?Z_DEFINED_VALUE_AT_ZERO.
- arg = gimple_call_arg (call, 0);
- prec = TYPE_PRECISION (TREE_TYPE (arg));
- mini = 0;
- maxi = prec - 1;
- mode = SCALAR_INT_TYPE_MODE (TREE_TYPE (arg));
- if (gimple_call_internal_p (call))
- {
- if (optab_handler (clz_optab, mode) != CODE_FOR_nothing
- && CLZ_DEFINED_VALUE_AT_ZERO (mode, zerov) == 2)
- {
- // Only handle the single common value.
- if (zerov == prec)
- maxi = prec;
- else
- // Magic value to give up, unless we can prove arg is non-zero.
- mini = -2;
- }
- }
-
- src.get_operand (r, arg);
- // From clz of minimum we can compute result maximum.
- if (!r.undefined_p ())
- {
- // From clz of minimum we can compute result maximum.
- if (wi::gt_p (r.lower_bound (), 0, TYPE_SIGN (r.type ())))
- {
- maxi = prec - 1 - wi::floor_log2 (r.lower_bound ());
- if (mini == -2)
- mini = 0;
- }
- else if (!range_includes_zero_p (&r))
- {
- mini = 0;
- maxi = prec - 1;
- }
- if (mini == -2)
- break;
- // From clz of maximum we can compute result minimum.
- wide_int max = r.upper_bound ();
- int newmini = prec - 1 - wi::floor_log2 (max);
- if (max == 0)
- {
- // If CLZ_DEFINED_VALUE_AT_ZERO is 2 with VALUE of prec,
- // return [prec, prec], otherwise ignore the range.
- if (maxi == prec)
- mini = prec;
- }
- else
- mini = newmini;
- }
- if (mini == -2)
- break;
- r.set (build_int_cst (type, mini), build_int_cst (type, maxi));
- return true;
-
CASE_CFN_CTZ:
// __builtin_ctz* return [0, prec-1], except for when the
// argument is 0, but that is undefined behavior.
diff --git a/gcc/gimple-range-op.cc b/gcc/gimple-range-op.cc
index 84837f8ee43..caba49309f9 100644
--- a/gcc/gimple-range-op.cc
+++ b/gcc/gimple-range-op.cc
@@ -414,6 +414,81 @@ public:
}
} op_cfn_popcount;
+// Implement range operator for CFN_BUILT_IN_CLZ
+class cfn_clz : public range_operator
+{
+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;
+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
+{
+ // __builtin_c[lt]z* return [0, prec-1], except when the
+ // argument is 0, but that is undefined behavior.
+ //
+ // For __builtin_c[lt]z* consider argument of 0 always undefined
+ // behavior, for internal fns depending on C?Z_DEFINED_ALUE_AT_ZERO.
+ if (lh.undefined_p ())
+ return false;
+ int prec = TYPE_PRECISION (lh.type ());
+ int mini = 0;
+ int maxi = prec - 1;
+ int zerov = 0;
+ scalar_int_mode mode = SCALAR_INT_TYPE_MODE (lh.type ());
+ if (m_gimple_call_internal_p)
+ {
+ if (optab_handler (clz_optab, mode) != CODE_FOR_nothing
+ && CLZ_DEFINED_VALUE_AT_ZERO (mode, zerov) == 2)
+ {
+ // Only handle the single common value.
+ if (zerov == prec)
+ maxi = prec;
+ else
+ // Magic value to give up, unless we can prove arg is non-zero.
+ mini = -2;
+ }
+ }
+
+ // From clz of minimum we can compute result maximum.
+ if (wi::gt_p (lh.lower_bound (), 0, TYPE_SIGN (lh.type ())))
+ {
+ maxi = prec - 1 - wi::floor_log2 (lh.lower_bound ());
+ if (mini == -2)
+ mini = 0;
+ }
+ else if (!range_includes_zero_p (&lh))
+ {
+ mini = 0;
+ maxi = prec - 1;
+ }
+ if (mini == -2)
+ return false;
+ // From clz of maximum we can compute result minimum.
+ wide_int max = lh.upper_bound ();
+ int newmini = prec - 1 - wi::floor_log2 (max);
+ if (max == 0)
+ {
+ // If CLZ_DEFINED_VALUE_AT_ZERO is 2 with VALUE of prec,
+ // return [prec, prec], otherwise ignore the range.
+ if (maxi == prec)
+ mini = prec;
+ }
+ else
+ mini = newmini;
+
+ if (mini == -2)
+ return false;
+ r.set (build_int_cst (type, mini), build_int_cst (type, maxi));
+ return true;
+}
+
// Set up a gimple_range_op_handler for any built in function which can be
// supported via range-ops.
@@ -469,6 +544,15 @@ gimple_range_op_handler::maybe_builtin_call ()
m_valid = true;
break;
+ CASE_CFN_CLZ:
+ m_op1 = gimple_call_arg (call, 0);
+ m_valid = true;
+ if (gimple_call_internal_p (call))
+ m_int = &op_cfn_clz_internal;
+ else
+ m_int = &op_cfn_clz;
+ break;
+
default:
break;
}
--
2.37.3
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH 12/17] Convert CFN_CTZ builtins to range-ops.
2022-09-22 18:49 [PATCH 00/17] Move builtin functions to range-ops Andrew MacLeod
` (10 preceding siblings ...)
2022-09-22 19:05 ` [PATCH 11/17] Convert CFN_CLZ builtins " Andrew MacLeod
@ 2022-09-22 19:05 ` Andrew MacLeod
2022-09-22 19:06 ` [PATCH 13/17] Convert CFN_BUILT_IN_CLRSB " Andrew MacLeod
` (4 subsequent siblings)
16 siblings, 0 replies; 18+ messages in thread
From: Andrew MacLeod @ 2022-09-22 19:05 UTC (permalink / raw)
To: gcc-patches; +Cc: hernandez, aldy
[-- Attachment #1: Type: text/plain, Size: 75 bytes --]
Bootstrapped on x86_64-pc-linux-gnu with no regressions. Pushed.
Andrew
[-- Attachment #2: 0012-Convert-CFN_CTZ-builtins-to-range-ops.patch --]
[-- Type: text/x-patch, Size: 5945 bytes --]
From 55738d8d96bb4f39a72cf5e3739d35b39fc2146a Mon Sep 17 00:00:00 2001
From: Andrew MacLeod <amacleod@redhat.com>
Date: Tue, 20 Sep 2022 18:19:30 -0400
Subject: [PATCH 12/17] Convert CFN_CTZ builtins to range-ops.
* gimple-range-fold.cc (range_of_builtin_int_call): Remove case
for CFN_CTZ.
* gimple-range-op.cc (class cfn_ctz): New.
(gimple_range_op_handler::maybe_builtin_call): Set arguments.
---
gcc/gimple-range-fold.cc | 61 +------------------------------
gcc/gimple-range-op.cc | 79 ++++++++++++++++++++++++++++++++++++++++
2 files changed, 80 insertions(+), 60 deletions(-)
diff --git a/gcc/gimple-range-fold.cc b/gcc/gimple-range-fold.cc
index 63eaa90be96..96a138a7a02 100644
--- a/gcc/gimple-range-fold.cc
+++ b/gcc/gimple-range-fold.cc
@@ -917,7 +917,7 @@ fold_using_range::range_of_builtin_int_call (irange &r, gcall *call,
tree type = gimple_range_type (call);
tree arg;
- int mini, maxi, zerov = 0, prec;
+ int prec;
scalar_int_mode mode;
switch (func)
@@ -926,65 +926,6 @@ fold_using_range::range_of_builtin_int_call (irange &r, gcall *call,
r.set (build_zero_cst (type), build_one_cst (type));
return true;
- CASE_CFN_CTZ:
- // __builtin_ctz* return [0, prec-1], except for when the
- // argument is 0, but that is undefined behavior.
- //
- // For __builtin_ctz* consider argument of 0 always undefined
- // behavior, for internal fns depending on CTZ_DEFINED_VALUE_AT_ZERO.
- arg = gimple_call_arg (call, 0);
- prec = TYPE_PRECISION (TREE_TYPE (arg));
- mini = 0;
- maxi = prec - 1;
- mode = SCALAR_INT_TYPE_MODE (TREE_TYPE (arg));
- if (gimple_call_internal_p (call))
- {
- if (optab_handler (ctz_optab, mode) != CODE_FOR_nothing
- && CTZ_DEFINED_VALUE_AT_ZERO (mode, zerov) == 2)
- {
- // Handle only the two common values.
- if (zerov == -1)
- mini = -1;
- else if (zerov == prec)
- maxi = prec;
- else
- // Magic value to give up, unless we can prove arg is non-zero.
- mini = -2;
- }
- }
- src.get_operand (r, arg);
- if (!r.undefined_p ())
- {
- // If arg is non-zero, then use [0, prec - 1].
- if (!range_includes_zero_p (&r))
- {
- mini = 0;
- maxi = prec - 1;
- }
- // If some high bits are known to be zero, we can decrease
- // the maximum.
- wide_int max = r.upper_bound ();
- if (max == 0)
- {
- // Argument is [0, 0]. If CTZ_DEFINED_VALUE_AT_ZERO
- // is 2 with value -1 or prec, return [-1, -1] or [prec, prec].
- // Otherwise ignore the range.
- if (mini == -1)
- maxi = -1;
- else if (maxi == prec)
- mini = prec;
- }
- // If value at zero is prec and 0 is in the range, we can't lower
- // the upper bound. We could create two separate ranges though,
- // [0,floor_log2(max)][prec,prec] though.
- else if (maxi != prec)
- maxi = wi::floor_log2 (max);
- }
- if (mini == -2)
- break;
- r.set (build_int_cst (type, mini), build_int_cst (type, maxi));
- return true;
-
CASE_CFN_CLRSB:
arg = gimple_call_arg (call, 0);
prec = TYPE_PRECISION (TREE_TYPE (arg));
diff --git a/gcc/gimple-range-op.cc b/gcc/gimple-range-op.cc
index caba49309f9..801c2bb235e 100644
--- a/gcc/gimple-range-op.cc
+++ b/gcc/gimple-range-op.cc
@@ -489,6 +489,76 @@ cfn_clz::fold_range (irange &r, tree type, const irange &lh,
return true;
}
+// Implement range operator for CFN_BUILT_IN_CTZ
+class cfn_ctz : public range_operator
+{
+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;
+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
+{
+ if (lh.undefined_p ())
+ return false;
+ int prec = TYPE_PRECISION (lh.type ());
+ int mini = 0;
+ int maxi = prec - 1;
+ int zerov = 0;
+ scalar_int_mode mode = SCALAR_INT_TYPE_MODE (lh.type ());
+
+ if (m_gimple_call_internal_p)
+ {
+ if (optab_handler (ctz_optab, mode) != CODE_FOR_nothing
+ && CTZ_DEFINED_VALUE_AT_ZERO (mode, zerov) == 2)
+ {
+ // Handle only the two common values.
+ if (zerov == -1)
+ mini = -1;
+ else if (zerov == prec)
+ maxi = prec;
+ else
+ // Magic value to give up, unless we can prove arg is non-zero.
+ mini = -2;
+ }
+ }
+ // If arg is non-zero, then use [0, prec - 1].
+ if (!range_includes_zero_p (&lh))
+ {
+ mini = 0;
+ maxi = prec - 1;
+ }
+ // If some high bits are known to be zero, we can decrease
+ // the maximum.
+ wide_int max = lh.upper_bound ();
+ if (max == 0)
+ {
+ // Argument is [0, 0]. If CTZ_DEFINED_VALUE_AT_ZERO
+ // is 2 with value -1 or prec, return [-1, -1] or [prec, prec].
+ // Otherwise ignore the range.
+ if (mini == -1)
+ maxi = -1;
+ else if (maxi == prec)
+ mini = prec;
+ }
+ // If value at zero is prec and 0 is in the range, we can't lower
+ // the upper bound. We could create two separate ranges though,
+ // [0,floor_log2(max)][prec,prec] though.
+ else if (maxi != prec)
+ maxi = wi::floor_log2 (max);
+
+ if (mini == -2)
+ return false;
+ r.set (build_int_cst (type, mini), build_int_cst (type, maxi));
+ return true;
+}
+
// Set up a gimple_range_op_handler for any built in function which can be
// supported via range-ops.
@@ -553,6 +623,15 @@ gimple_range_op_handler::maybe_builtin_call ()
m_int = &op_cfn_clz;
break;
+ CASE_CFN_CTZ:
+ m_op1 = gimple_call_arg (call, 0);
+ m_valid = true;
+ if (gimple_call_internal_p (call))
+ m_int = &op_cfn_ctz_internal;
+ else
+ m_int = &op_cfn_ctz;
+ break;
+
default:
break;
}
--
2.37.3
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH 13/17] Convert CFN_BUILT_IN_CLRSB to range-ops.
2022-09-22 18:49 [PATCH 00/17] Move builtin functions to range-ops Andrew MacLeod
` (11 preceding siblings ...)
2022-09-22 19:05 ` [PATCH 12/17] Convert CFN_CTZ " Andrew MacLeod
@ 2022-09-22 19:06 ` Andrew MacLeod
2022-09-22 19:06 ` [PATCH 14/17] Convert CFN_BUILT_IN_UBSAN_CHECK_* " Andrew MacLeod
` (3 subsequent siblings)
16 siblings, 0 replies; 18+ messages in thread
From: Andrew MacLeod @ 2022-09-22 19:06 UTC (permalink / raw)
To: gcc-patches; +Cc: hernandez, aldy
[-- Attachment #1: Type: text/plain, Size: 77 bytes --]
Bootstrapped on x86_64-pc-linux-gnu with no regressions. Pushed.
Andrew
[-- Attachment #2: 0013-Convert-CFN_BUILT_IN_CLRSB-to-range-ops.patch --]
[-- Type: text/x-patch, Size: 2553 bytes --]
From f7e62b09300b6935bceaffb4c42f6edab80f52dc Mon Sep 17 00:00:00 2001
From: Andrew MacLeod <amacleod@redhat.com>
Date: Tue, 20 Sep 2022 18:21:04 -0400
Subject: [PATCH 13/17] Convert CFN_BUILT_IN_CLRSB to range-ops.
* gimple-range-fold.cc (range_of_builtin_int_call): Remove case
for CFN_BUILT_IN_CLRSB.
* gimple-range-op.cc (class cfn_clrsb): New.
(gimple_range_op_handler::maybe_builtin_call): Set arguments.
---
gcc/gimple-range-fold.cc | 7 -------
gcc/gimple-range-op.cc | 23 +++++++++++++++++++++++
2 files changed, 23 insertions(+), 7 deletions(-)
diff --git a/gcc/gimple-range-fold.cc b/gcc/gimple-range-fold.cc
index 96a138a7a02..1d7d1da7bbe 100644
--- a/gcc/gimple-range-fold.cc
+++ b/gcc/gimple-range-fold.cc
@@ -916,8 +916,6 @@ fold_using_range::range_of_builtin_int_call (irange &r, gcall *call,
return false;
tree type = gimple_range_type (call);
- tree arg;
- int prec;
scalar_int_mode mode;
switch (func)
@@ -926,11 +924,6 @@ fold_using_range::range_of_builtin_int_call (irange &r, gcall *call,
r.set (build_zero_cst (type), build_one_cst (type));
return true;
- CASE_CFN_CLRSB:
- arg = gimple_call_arg (call, 0);
- prec = TYPE_PRECISION (TREE_TYPE (arg));
- r.set (build_int_cst (type, 0), build_int_cst (type, prec - 1));
- return true;
case CFN_UBSAN_CHECK_ADD:
range_of_builtin_ubsan_call (r, call, PLUS_EXPR, src);
return true;
diff --git a/gcc/gimple-range-op.cc b/gcc/gimple-range-op.cc
index 801c2bb235e..bee225431e8 100644
--- a/gcc/gimple-range-op.cc
+++ b/gcc/gimple-range-op.cc
@@ -559,6 +559,23 @@ cfn_ctz::fold_range (irange &r, tree type, const irange &lh,
return true;
}
+
+// Implement range operator for CFN_BUILT_IN_
+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
+ {
+ if (lh.undefined_p ())
+ return false;
+ int prec = TYPE_PRECISION (lh.type ());
+ r.set (build_int_cst (type, 0), build_int_cst (type, prec - 1));
+ return true;
+ }
+} op_cfn_clrsb;
+
// Set up a gimple_range_op_handler for any built in function which can be
// supported via range-ops.
@@ -632,6 +649,12 @@ gimple_range_op_handler::maybe_builtin_call ()
m_int = &op_cfn_ctz;
break;
+ CASE_CFN_CLRSB:
+ m_op1 = gimple_call_arg (call, 0);
+ m_valid = true;
+ m_int = &op_cfn_clrsb;
+ break;
+
default:
break;
}
--
2.37.3
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH 14/17] Convert CFN_BUILT_IN_UBSAN_CHECK_* to range-ops.
2022-09-22 18:49 [PATCH 00/17] Move builtin functions to range-ops Andrew MacLeod
` (12 preceding siblings ...)
2022-09-22 19:06 ` [PATCH 13/17] Convert CFN_BUILT_IN_CLRSB " Andrew MacLeod
@ 2022-09-22 19:06 ` Andrew MacLeod
2022-09-22 19:08 ` [PATCH 15/17] Convert CFN_BUILT_IN_STRLEN " Andrew MacLeod
` (2 subsequent siblings)
16 siblings, 0 replies; 18+ messages in thread
From: Andrew MacLeod @ 2022-09-22 19:06 UTC (permalink / raw)
To: gcc-patches; +Cc: hernandez, aldy
[-- Attachment #1: Type: text/plain, Size: 78 bytes --]
Bootstrapped on x86_64-pc-linux-gnu with no regressions. Pushed.
Andrew
[-- Attachment #2: 0014-Convert-CFN_BUILT_IN_UBSAN_CHECK_-to-range-ops.patch --]
[-- Type: text/x-patch, Size: 5516 bytes --]
From b6f670ff706e35dc51a62db4206cb241dcac4963 Mon Sep 17 00:00:00 2001
From: Andrew MacLeod <amacleod@redhat.com>
Date: Tue, 20 Sep 2022 18:48:05 -0400
Subject: [PATCH 14/17] Convert CFN_BUILT_IN_UBSAN_CHECK_* to range-ops.
* gimple-range-fold.cc (range_of_builtin_ubsan_call): Delete.
(range_of_builtin_int_call): Remove cases for
CFN_BUILT_IN_UBSAN_CHECK.
* gimple-range-op.cc (class cfn_ubsan): New.
(gimple_range_op_handler::maybe_builtin_call): Set arguments.
---
gcc/gimple-range-fold.cc | 47 +--------------------------------
gcc/gimple-range-op.cc | 56 ++++++++++++++++++++++++++++++++++++++++
2 files changed, 57 insertions(+), 46 deletions(-)
diff --git a/gcc/gimple-range-fold.cc b/gcc/gimple-range-fold.cc
index 1d7d1da7bbe..d445270417a 100644
--- a/gcc/gimple-range-fold.cc
+++ b/gcc/gimple-range-fold.cc
@@ -852,41 +852,6 @@ fold_using_range::range_of_call (vrange &r, gcall *call, fur_source &src)
return true;
}
-// Return the range of a __builtin_ubsan* in CALL and set it in R.
-// CODE is the type of ubsan call (PLUS_EXPR, MINUS_EXPR or
-// MULT_EXPR).
-
-void
-fold_using_range::range_of_builtin_ubsan_call (irange &r, gcall *call,
- tree_code code, fur_source &src)
-{
- gcc_checking_assert (code == PLUS_EXPR || code == MINUS_EXPR
- || code == MULT_EXPR);
- tree type = gimple_range_type (call);
- range_op_handler op (code, type);
- gcc_checking_assert (op);
- int_range_max ir0, ir1;
- tree arg0 = gimple_call_arg (call, 0);
- tree arg1 = gimple_call_arg (call, 1);
- src.get_operand (ir0, arg0);
- src.get_operand (ir1, arg1);
- // Check for any relation between arg0 and arg1.
- relation_kind relation = src.query_relation (arg0, arg1);
-
- bool saved_flag_wrapv = flag_wrapv;
- // 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);
- flag_wrapv = saved_flag_wrapv;
-
- // If for both arguments vrp_valueize returned non-NULL, this should
- // have been already folded and if not, it wasn't folded because of
- // overflow. Avoid removing the UBSAN_CHECK_* calls in that case.
- if (r.singleton_p ())
- r.set_varying (type);
-}
-
// For a builtin in CALL, return a range in R if known and return
// TRUE. Otherwise return FALSE.
@@ -909,7 +874,7 @@ fold_using_range::range_of_builtin_call (vrange &r, gcall *call,
bool
fold_using_range::range_of_builtin_int_call (irange &r, gcall *call,
- fur_source &src)
+ fur_source &)
{
combined_fn func = gimple_call_combined_fn (call);
if (func == CFN_LAST)
@@ -924,16 +889,6 @@ fold_using_range::range_of_builtin_int_call (irange &r, gcall *call,
r.set (build_zero_cst (type), build_one_cst (type));
return true;
- case CFN_UBSAN_CHECK_ADD:
- range_of_builtin_ubsan_call (r, call, PLUS_EXPR, src);
- return true;
- case CFN_UBSAN_CHECK_SUB:
- range_of_builtin_ubsan_call (r, call, MINUS_EXPR, src);
- return true;
- case CFN_UBSAN_CHECK_MUL:
- range_of_builtin_ubsan_call (r, call, MULT_EXPR, src);
- return true;
-
case CFN_GOACC_DIM_SIZE:
case CFN_GOACC_DIM_POS:
// Optimizing these two internal functions helps the loop
diff --git a/gcc/gimple-range-op.cc b/gcc/gimple-range-op.cc
index bee225431e8..09b7dd2add3 100644
--- a/gcc/gimple-range-op.cc
+++ b/gcc/gimple-range-op.cc
@@ -576,6 +576,41 @@ public:
}
} op_cfn_clrsb;
+
+// Implement range operator for CFN_BUILT_IN_
+class cfn_ubsan : public range_operator
+{
+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
+ {
+ range_op_handler handler (m_code, type);
+ gcc_checking_assert (handler);
+
+ bool saved_flag_wrapv = flag_wrapv;
+ // Pretend the arithmetic is wrapping. If there is any overflow,
+ // we'll complain, but will actually do wrapping operation.
+ flag_wrapv = 1;
+ bool result = handler.fold_range (r, type, lh, rh, rel);
+ flag_wrapv = saved_flag_wrapv;
+
+ // If for both arguments vrp_valueize returned non-NULL, this should
+ // have been already folded and if not, it wasn't folded because of
+ // overflow. Avoid removing the UBSAN_CHECK_* calls in that case.
+ if (result && r.singleton_p ())
+ r.set_varying (type);
+ return result;
+ }
+private:
+ enum tree_code m_code;
+};
+
+cfn_ubsan op_cfn_ubsan_add (PLUS_EXPR);
+cfn_ubsan op_cfn_ubsan_sub (MINUS_EXPR);
+cfn_ubsan op_cfn_ubsan_mul (MULT_EXPR);
+
// Set up a gimple_range_op_handler for any built in function which can be
// supported via range-ops.
@@ -655,6 +690,27 @@ gimple_range_op_handler::maybe_builtin_call ()
m_int = &op_cfn_clrsb;
break;
+ case CFN_UBSAN_CHECK_ADD:
+ m_op1 = gimple_call_arg (call, 0);
+ m_op2 = gimple_call_arg (call, 1);
+ m_valid = true;
+ m_int = &op_cfn_ubsan_add;
+ break;
+
+ case CFN_UBSAN_CHECK_SUB:
+ m_op1 = gimple_call_arg (call, 0);
+ m_op2 = gimple_call_arg (call, 1);
+ m_valid = true;
+ m_int = &op_cfn_ubsan_sub;
+ break;
+
+ case CFN_UBSAN_CHECK_MUL:
+ m_op1 = gimple_call_arg (call, 0);
+ m_op2 = gimple_call_arg (call, 1);
+ m_valid = true;
+ m_int = &op_cfn_ubsan_mul;
+ break;
+
default:
break;
}
--
2.37.3
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH 15/17] Convert CFN_BUILT_IN_STRLEN to range-ops.
2022-09-22 18:49 [PATCH 00/17] Move builtin functions to range-ops Andrew MacLeod
` (13 preceding siblings ...)
2022-09-22 19:06 ` [PATCH 14/17] Convert CFN_BUILT_IN_UBSAN_CHECK_* " Andrew MacLeod
@ 2022-09-22 19:08 ` Andrew MacLeod
2022-09-22 19:10 ` [PATCH 16/17] Convert CFN_BUILT_IN_GOACC_DIM_* " Andrew MacLeod
2022-09-22 19:10 ` [PATCH 17/17] Convert CFN_BUILT_IN_PARITY " Andrew MacLeod
16 siblings, 0 replies; 18+ messages in thread
From: Andrew MacLeod @ 2022-09-22 19:08 UTC (permalink / raw)
To: gcc-patches; +Cc: hernandez, aldy
[-- Attachment #1: Type: text/plain, Size: 75 bytes --]
Bootstrapped on x86_64-pc-linux-gnu with no regressions. Pushed.
Andrew
[-- Attachment #2: 0015-Convert-CFN_BUILT_IN_STRLEN-to-range-ops.patch --]
[-- Type: text/x-patch, Size: 3470 bytes --]
From c750e675cb77f283ff991682db7740bc5f6d4cf4 Mon Sep 17 00:00:00 2001
From: Andrew MacLeod <amacleod@redhat.com>
Date: Tue, 20 Sep 2022 19:05:03 -0400
Subject: [PATCH 15/17] Convert CFN_BUILT_IN_STRLEN to range-ops.
* gimple-range-fold.cc (range_of_builtin_int_call): Remove case
for CFN_BUILT_IN_STRLEN.
* gimple-range-op.cc (class cfn_strlen): New.
(gimple_range_op_handler::maybe_builtin_call): Set arguments.
---
gcc/gimple-range-fold.cc | 21 ---------------------
gcc/gimple-range-op.cc | 37 +++++++++++++++++++++++++++++++++++++
2 files changed, 37 insertions(+), 21 deletions(-)
diff --git a/gcc/gimple-range-fold.cc b/gcc/gimple-range-fold.cc
index d445270417a..d22fb0e9352 100644
--- a/gcc/gimple-range-fold.cc
+++ b/gcc/gimple-range-fold.cc
@@ -908,27 +908,6 @@ fold_using_range::range_of_builtin_int_call (irange &r, gcall *call,
return true;
}
- case CFN_BUILT_IN_STRLEN:
- if (tree lhs = gimple_call_lhs (call))
- if (ptrdiff_type_node
- && (TYPE_PRECISION (ptrdiff_type_node)
- == TYPE_PRECISION (TREE_TYPE (lhs))))
- {
- tree type = TREE_TYPE (lhs);
- tree max = vrp_val_max (ptrdiff_type_node);
- wide_int wmax
- = wi::to_wide (max, TYPE_PRECISION (TREE_TYPE (max)));
- tree range_min = build_zero_cst (type);
- // To account for the terminating NULL, the maximum length
- // is one less than the maximum array size, which in turn
- // is one less than PTRDIFF_MAX (or SIZE_MAX where it's
- // smaller than the former type).
- // FIXME: Use max_object_size() - 1 here.
- tree range_max = wide_int_to_tree (type, wmax - 2);
- r.set (range_min, range_max);
- return true;
- }
- break;
default:
break;
}
diff --git a/gcc/gimple-range-op.cc b/gcc/gimple-range-op.cc
index 09b7dd2add3..f9161b5820f 100644
--- a/gcc/gimple-range-op.cc
+++ b/gcc/gimple-range-op.cc
@@ -611,6 +611,30 @@ cfn_ubsan op_cfn_ubsan_add (PLUS_EXPR);
cfn_ubsan op_cfn_ubsan_sub (MINUS_EXPR);
cfn_ubsan op_cfn_ubsan_mul (MULT_EXPR);
+
+// Implement range operator for CFN_BUILT_IN_STRLEN
+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
+ {
+ tree max = vrp_val_max (ptrdiff_type_node);
+ wide_int wmax
+ = wi::to_wide (max, TYPE_PRECISION (TREE_TYPE (max)));
+ tree range_min = build_zero_cst (type);
+ // To account for the terminating NULL, the maximum length
+ // is one less than the maximum array size, which in turn
+ // is one less than PTRDIFF_MAX (or SIZE_MAX where it's
+ // smaller than the former type).
+ // FIXME: Use max_object_size() - 1 here.
+ tree range_max = wide_int_to_tree (type, wmax - 2);
+ r.set (range_min, range_max);
+ return true;
+ }
+} op_cfn_strlen;
+
// Set up a gimple_range_op_handler for any built in function which can be
// supported via range-ops.
@@ -711,6 +735,19 @@ gimple_range_op_handler::maybe_builtin_call ()
m_int = &op_cfn_ubsan_mul;
break;
+ case CFN_BUILT_IN_STRLEN:
+ {
+ tree lhs = gimple_call_lhs (call);
+ if (lhs && ptrdiff_type_node && (TYPE_PRECISION (ptrdiff_type_node)
+ == TYPE_PRECISION (TREE_TYPE (lhs))))
+ {
+ m_op1 = gimple_call_arg (call, 0);
+ m_valid = true;
+ m_int = &op_cfn_strlen;
+ }
+ break;
+ }
+
default:
break;
}
--
2.37.3
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH 16/17] Convert CFN_BUILT_IN_GOACC_DIM_* to range-ops.
2022-09-22 18:49 [PATCH 00/17] Move builtin functions to range-ops Andrew MacLeod
` (14 preceding siblings ...)
2022-09-22 19:08 ` [PATCH 15/17] Convert CFN_BUILT_IN_STRLEN " Andrew MacLeod
@ 2022-09-22 19:10 ` Andrew MacLeod
2022-09-22 19:10 ` [PATCH 17/17] Convert CFN_BUILT_IN_PARITY " Andrew MacLeod
16 siblings, 0 replies; 18+ messages in thread
From: Andrew MacLeod @ 2022-09-22 19:10 UTC (permalink / raw)
To: gcc-patches; +Cc: hernandez, aldy
[-- Attachment #1: Type: text/plain, Size: 74 bytes --]
Bootstrapped on x86_64-pc-linux-gnu with no regressions. Pushed.
Andrew
[-- Attachment #2: 0016-Convert-CFN_BUILT_IN_GOACC_DIM_-to-range-ops.patch --]
[-- Type: text/x-patch, Size: 3647 bytes --]
From e7f035f66aa25e0537a0e3a76d43c71fe9531724 Mon Sep 17 00:00:00 2001
From: Andrew MacLeod <amacleod@redhat.com>
Date: Tue, 20 Sep 2022 19:19:30 -0400
Subject: [PATCH 16/17] Convert CFN_BUILT_IN_GOACC_DIM_* to range-ops.
* gimple-range-fold.cc (range_of_builtin_int_call): Remove case
for CFN_GOACC_DIM_*.
* gimple-range-op.cc (class cfn_goacc_dim): New.
(gimple_range_op_handler::maybe_builtin_call): Set arguments.
---
gcc/gimple-range-fold.cc | 19 ----------------
gcc/gimple-range-op.cc | 47 ++++++++++++++++++++++++++++++++++++++++
2 files changed, 47 insertions(+), 19 deletions(-)
diff --git a/gcc/gimple-range-fold.cc b/gcc/gimple-range-fold.cc
index d22fb0e9352..5e8a13e7337 100644
--- a/gcc/gimple-range-fold.cc
+++ b/gcc/gimple-range-fold.cc
@@ -889,25 +889,6 @@ fold_using_range::range_of_builtin_int_call (irange &r, gcall *call,
r.set (build_zero_cst (type), build_one_cst (type));
return true;
- case CFN_GOACC_DIM_SIZE:
- case CFN_GOACC_DIM_POS:
- // Optimizing these two internal functions helps the loop
- // optimizer eliminate outer comparisons. Size is [1,N]
- // and pos is [0,N-1].
- {
- bool is_pos = func == CFN_GOACC_DIM_POS;
- int axis = oacc_get_ifn_dim_arg (call);
- int size = oacc_get_fn_dim_size (current_function_decl, axis);
- if (!size)
- // If it's dynamic, the backend might know a hardware limitation.
- size = targetm.goacc.dim_limit (axis);
-
- r.set (build_int_cst (type, is_pos ? 0 : 1),
- size
- ? build_int_cst (type, size - is_pos) : vrp_val_max (type));
- return true;
- }
-
default:
break;
}
diff --git a/gcc/gimple-range-op.cc b/gcc/gimple-range-op.cc
index f9161b5820f..76295466e65 100644
--- a/gcc/gimple-range-op.cc
+++ b/gcc/gimple-range-op.cc
@@ -635,6 +635,34 @@ public:
}
} op_cfn_strlen;
+
+// Implement range operator for CFN_BUILT_IN_GOACC_DIM
+class cfn_goacc_dim : public range_operator
+{
+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
+ {
+ tree axis_tree;
+ if (!lh.singleton_p (&axis_tree))
+ return false;
+ HOST_WIDE_INT axis = TREE_INT_CST_LOW (axis_tree);
+ int size = oacc_get_fn_dim_size (current_function_decl, axis);
+ if (!size)
+ // If it's dynamic, the backend might know a hardware limitation.
+ size = targetm.goacc.dim_limit (axis);
+
+ r.set (build_int_cst (type, m_is_pos ? 0 : 1),
+ size
+ ? build_int_cst (type, size - m_is_pos) : vrp_val_max (type));
+ return true;
+ }
+private:
+ bool m_is_pos;
+} op_cfn_goacc_dim_size (false), op_cfn_goacc_dim_pos (true);
+
// Set up a gimple_range_op_handler for any built in function which can be
// supported via range-ops.
@@ -748,6 +776,25 @@ gimple_range_op_handler::maybe_builtin_call ()
break;
}
+ // Optimizing these two internal functions helps the loop
+ // optimizer eliminate outer comparisons. Size is [1,N]
+ // and pos is [0,N-1].
+ case CFN_GOACC_DIM_SIZE:
+ // This call will ensure all the asserts are triggered.
+ oacc_get_ifn_dim_arg (call);
+ m_op1 = gimple_call_arg (call, 0);
+ m_valid = true;
+ m_int = &op_cfn_goacc_dim_size;
+ break;
+
+ case CFN_GOACC_DIM_POS:
+ // This call will ensure all the asserts are triggered.
+ oacc_get_ifn_dim_arg (call);
+ m_op1 = gimple_call_arg (call, 0);
+ m_valid = true;
+ m_int = &op_cfn_goacc_dim_pos;
+ break;
+
default:
break;
}
--
2.37.3
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH 17/17] Convert CFN_BUILT_IN_PARITY to range-ops.
2022-09-22 18:49 [PATCH 00/17] Move builtin functions to range-ops Andrew MacLeod
` (15 preceding siblings ...)
2022-09-22 19:10 ` [PATCH 16/17] Convert CFN_BUILT_IN_GOACC_DIM_* " Andrew MacLeod
@ 2022-09-22 19:10 ` Andrew MacLeod
16 siblings, 0 replies; 18+ messages in thread
From: Andrew MacLeod @ 2022-09-22 19:10 UTC (permalink / raw)
To: gcc-patches; +Cc: hernandez, aldy
[-- Attachment #1: Type: text/plain, Size: 188 bytes --]
Also, as the last builtin remaining, also remove the builtin
infrastructure routines from fold_using_range.
Bootstrapped on x86_64-pc-linux-gnu with no regressions. Pushed.
Andrew
[-- Attachment #2: 0017-Convert-CFN_BUILT_IN_PARITY-to-range-ops.patch --]
[-- Type: text/x-patch, Size: 5405 bytes --]
From 5608e410914ebb7c8cc9fa50afc8ada3b22cbf2c Mon Sep 17 00:00:00 2001
From: Andrew MacLeod <amacleod@redhat.com>
Date: Tue, 20 Sep 2022 19:30:46 -0400
Subject: [PATCH 17/17] Convert CFN_BUILT_IN_PARITY to range-ops.
Also, as the last builtin remaining, also remove the builtin infrastrucure
routines from fold_using_range.
* gimple-range-fold.cc (range_of_range_op): Handle no operands.
(range_of_call): Do not check for builtins.
(fold_using_range::range_of_builtin_call): Delete.
(fold_using_range::range_of_builtin_int_call): Delete.
* gimple-range-fold.h: Adjust prototypes.
* gimple-range-op.cc (class cfn_parity): New.
(gimple_range_op_handler::maybe_builtin_call): Set arguments.
---
gcc/gimple-range-fold.cc | 60 ++++++++--------------------------------
gcc/gimple-range-fold.h | 4 ---
gcc/gimple-range-op.cc | 19 +++++++++++++
3 files changed, 31 insertions(+), 52 deletions(-)
diff --git a/gcc/gimple-range-fold.cc b/gcc/gimple-range-fold.cc
index 5e8a13e7337..c381ef94087 100644
--- a/gcc/gimple-range-fold.cc
+++ b/gcc/gimple-range-fold.cc
@@ -534,6 +534,16 @@ fold_using_range::range_of_range_op (vrange &r,
tree lhs = handler.lhs ();
tree op1 = handler.operand1 ();
tree op2 = handler.operand2 ();
+
+ // Certain types of builtin functions may have no arguments.
+ if (!op1)
+ {
+ Value_Range r1 (type);
+ if (!handler.fold_range (r, type, r1, r1))
+ r.set_varying (type);
+ return true;
+ }
+
Value_Range range1 (TREE_TYPE (op1));
Value_Range range2 (op2 ? TREE_TYPE (op2) : TREE_TYPE (op1));
@@ -823,7 +833,7 @@ fold_using_range::range_of_phi (vrange &r, gphi *phi, fur_source &src)
// If a range cannot be calculated, return false.
bool
-fold_using_range::range_of_call (vrange &r, gcall *call, fur_source &src)
+fold_using_range::range_of_call (vrange &r, gcall *call, fur_source &)
{
tree type = gimple_range_type (call);
if (!type)
@@ -832,9 +842,7 @@ fold_using_range::range_of_call (vrange &r, gcall *call, fur_source &src)
tree lhs = gimple_call_lhs (call);
bool strict_overflow_p;
- if (range_of_builtin_call (r, call, src))
- ;
- else if (gimple_stmt_nonnegative_warnv_p (call, &strict_overflow_p))
+ if (gimple_stmt_nonnegative_warnv_p (call, &strict_overflow_p))
r.set_nonnegative (type);
else if (gimple_call_nonnull_result_p (call)
|| gimple_call_nonnull_arg (call))
@@ -852,50 +860,6 @@ fold_using_range::range_of_call (vrange &r, gcall *call, fur_source &src)
return true;
}
-// For a builtin in CALL, return a range in R if known and return
-// TRUE. Otherwise return FALSE.
-
-bool
-fold_using_range::range_of_builtin_call (vrange &r, gcall *call,
- fur_source &src)
-{
- combined_fn func = gimple_call_combined_fn (call);
- if (func == CFN_LAST)
- return false;
-
- tree type = gimple_range_type (call);
- gcc_checking_assert (type);
-
- if (irange::supports_p (type))
- return range_of_builtin_int_call (as_a <irange> (r), call, src);
-
- return false;
-}
-
-bool
-fold_using_range::range_of_builtin_int_call (irange &r, gcall *call,
- fur_source &)
-{
- combined_fn func = gimple_call_combined_fn (call);
- if (func == CFN_LAST)
- return false;
-
- tree type = gimple_range_type (call);
- scalar_int_mode mode;
-
- switch (func)
- {
- CASE_CFN_PARITY:
- r.set (build_zero_cst (type), build_one_cst (type));
- return true;
-
- default:
- break;
- }
- return false;
-}
-
-
// Calculate a range for COND_EXPR statement S and return it in R.
// If a range cannot be calculated, return false.
diff --git a/gcc/gimple-range-fold.h b/gcc/gimple-range-fold.h
index ce18c66b8e7..d1ed2bca80f 100644
--- a/gcc/gimple-range-fold.h
+++ b/gcc/gimple-range-fold.h
@@ -165,10 +165,6 @@ protected:
bool range_of_call (vrange &r, gcall *call, fur_source &src);
bool range_of_cond_expr (vrange &r, gassign* cond, fur_source &src);
bool range_of_address (irange &r, gimple *s, fur_source &src);
- bool range_of_builtin_call (vrange &r, gcall *call, fur_source &src);
- bool range_of_builtin_int_call (irange &r, gcall *call, fur_source &src);
- void range_of_builtin_ubsan_call (irange &r, gcall *call, tree_code code,
- fur_source &src);
bool range_of_phi (vrange &r, gphi *phi, fur_source &src);
void range_of_ssa_name_with_loop_info (vrange &, tree, class loop *, gphi *,
fur_source &src);
diff --git a/gcc/gimple-range-op.cc b/gcc/gimple-range-op.cc
index 76295466e65..d7c6dfa933d 100644
--- a/gcc/gimple-range-op.cc
+++ b/gcc/gimple-range-op.cc
@@ -663,6 +663,20 @@ private:
bool m_is_pos;
} op_cfn_goacc_dim_size (false), op_cfn_goacc_dim_pos (true);
+
+// Implement range operator for CFN_BUILT_IN_
+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
+ {
+ r.set (build_zero_cst (type), build_one_cst (type));
+ return true;
+ }
+} op_cfn_parity;
+
// Set up a gimple_range_op_handler for any built in function which can be
// supported via range-ops.
@@ -795,6 +809,11 @@ gimple_range_op_handler::maybe_builtin_call ()
m_int = &op_cfn_goacc_dim_pos;
break;
+ CASE_CFN_PARITY:
+ m_valid = true;
+ m_int = &op_cfn_parity;
+ break;
+
default:
break;
}
--
2.37.3
^ permalink raw reply [flat|nested] 18+ messages in thread
end of thread, other threads:[~2022-09-22 19:10 UTC | newest]
Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-09-22 18:49 [PATCH 00/17] Move builtin functions to range-ops Andrew MacLeod
2022-09-22 18:53 ` [PATCH 01/17] Replace another snippet with a call to, gimple_range_ssa_names Andrew MacLeod
2022-09-22 18:55 ` [PATCH 02/17] Adjust range_op_handler to store the handler directly Andrew MacLeod
2022-09-22 18:56 ` [PATCH 03/17] Create gimple_range_op_handler in a new source file Andrew MacLeod
2022-09-22 18:58 ` [PATCH 04/17] Fix calc_op1 for undefined op2_range Andrew MacLeod
2022-09-22 18:59 ` [PATCH 05/17] Add missing float fold_range prototype for floats Andrew MacLeod
2022-09-22 19:00 ` [PATCH 06/17] Always check the return value of fold_range Andrew MacLeod
2022-09-22 19:01 ` [PATCH 07/17] Add range-ops support for builtin functions Andrew MacLeod
2022-09-22 19:02 ` [PATCH 08/17] Convert CFN_BUILT_IN_SIGNBIT to range-ops Andrew MacLeod
2022-09-22 19:05 ` [PATCH 09/17] Convert CFN_BUILT_IN_TOUPPER and TOLOWER " Andrew MacLeod
2022-09-22 19:05 ` [PATCH 10/17] Convert CFN_BUILT_FFS and CFN_POPCOUNT " Andrew MacLeod
2022-09-22 19:05 ` [PATCH 11/17] Convert CFN_CLZ builtins " Andrew MacLeod
2022-09-22 19:05 ` [PATCH 12/17] Convert CFN_CTZ " Andrew MacLeod
2022-09-22 19:06 ` [PATCH 13/17] Convert CFN_BUILT_IN_CLRSB " Andrew MacLeod
2022-09-22 19:06 ` [PATCH 14/17] Convert CFN_BUILT_IN_UBSAN_CHECK_* " Andrew MacLeod
2022-09-22 19:08 ` [PATCH 15/17] Convert CFN_BUILT_IN_STRLEN " Andrew MacLeod
2022-09-22 19:10 ` [PATCH 16/17] Convert CFN_BUILT_IN_GOACC_DIM_* " Andrew MacLeod
2022-09-22 19:10 ` [PATCH 17/17] Convert CFN_BUILT_IN_PARITY " Andrew MacLeod
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).