aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorAndrew MacLeod <amacleod@redhat.com>2025-10-25 11:59:55 -0400
committerAndrew MacLeod <amacleod@redhat.com>2025-10-29 10:21:54 -0400
commit8b0e43d7ec87f53d5bbd0a2d4d876d0aa1327a33 (patch)
tree46a465c2f98c1b953f60481d08b9ba1f257ce454 /gcc
parentdd7dffb02ff5cd3a88654deacad67298ee8ed8fa (diff)
downloadgcc-8b0e43d7ec87f53d5bbd0a2d4d876d0aa1327a33.zip
gcc-8b0e43d7ec87f53d5bbd0a2d4d876d0aa1327a33.tar.gz
gcc-8b0e43d7ec87f53d5bbd0a2d4d876d0aa1327a33.tar.bz2
Handle VIEW_CONVERT_EXPR for non-floats.
Handle VIEW_CONVERT_EXPR for ranges as if it were a cast. PR tree-optimization/91191 gcc/ * gimple-range-op.cc (gimple_range_op_handler): Descend one operand lower for a VIEW_CONVERT_EXPR. * range-op-mixed.h (class operator_view): New. * range-op.cc (range_op_table): Add VIEW_CONVERT_EXPR case. (operator_view::fold_range): New. (operator_view::op1_range): New. (operator_view::update_bitmask): New. gcc/testsuite/ * gcc.dg/pr91191.c: New.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/gimple-range-op.cc4
-rw-r--r--gcc/range-op-mixed.h41
-rw-r--r--gcc/range-op.cc76
-rw-r--r--gcc/testsuite/gcc.dg/pr91191.c20
4 files changed, 141 insertions, 0 deletions
diff --git a/gcc/gimple-range-op.cc b/gcc/gimple-range-op.cc
index c9bc5c0..3a22606 100644
--- a/gcc/gimple-range-op.cc
+++ b/gcc/gimple-range-op.cc
@@ -150,6 +150,10 @@ gimple_range_op_handler::gimple_range_op_handler (gimple *s)
if (TREE_CODE (ssa) == SSA_NAME)
m_op1 = ssa;
}
+ // VIEW_CONVERT_EXPR needs to descend one level deeper to pick
+ // up the symbolic operand.
+ if (TREE_CODE (m_op1) == VIEW_CONVERT_EXPR)
+ m_op1 = TREE_OPERAND (m_op1, 0);
if (gimple_num_ops (m_stmt) >= 3)
m_op2 = gimple_assign_rhs2 (m_stmt);
// Check that operands are supported types. One check is enough.
diff --git a/gcc/range-op-mixed.h b/gcc/range-op-mixed.h
index 567b0cd..db31c2b 100644
--- a/gcc/range-op-mixed.h
+++ b/gcc/range-op-mixed.h
@@ -527,6 +527,47 @@ private:
const irange &outer) const;
};
+
+class operator_view : public range_operator
+{
+public:
+ using range_operator::fold_range;
+ using range_operator::op1_range;
+ using range_operator::update_bitmask;
+ bool fold_range (irange &r, tree type,
+ const irange &op1, const irange &op2,
+ relation_trio rel = TRIO_VARYING) const override;
+ bool fold_range (prange &r, tree type,
+ const prange &op1, const prange &op2,
+ relation_trio rel = TRIO_VARYING) const final override;
+ bool fold_range (irange &r, tree type,
+ const prange &op1, const irange &op2,
+ relation_trio rel = TRIO_VARYING) const final override;
+ bool fold_range (prange &r, tree type,
+ const irange &op1, const prange &op2,
+ relation_trio rel = TRIO_VARYING) const final override;
+
+ bool op1_range (irange &r, tree type,
+ const irange &lhs, const irange &op2,
+ relation_trio rel = TRIO_VARYING) const override;
+ bool op1_range (prange &r, tree type,
+ const prange &lhs, const prange &op2,
+ relation_trio rel = TRIO_VARYING) const final override;
+ bool op1_range (irange &r, tree type,
+ const prange &lhs, const irange &op2,
+ relation_trio rel = TRIO_VARYING) const final override;
+ bool op1_range (prange &r, tree type,
+ const irange &lhs, const prange &op2,
+ relation_trio rel = TRIO_VARYING) const final override;
+
+ void update_bitmask (irange &r, const irange &lh,
+ const irange &) const final override;
+private:
+// VIEW_CONVERT_EXPR works much like a cast between integral values, so use
+// the cast operator. Non-integrals are not handled as yet.
+ operator_cast m_cast;
+};
+
class operator_plus : public range_operator
{
public:
diff --git a/gcc/range-op.cc b/gcc/range-op.cc
index 6b6bf78..cf5b8fe 100644
--- a/gcc/range-op.cc
+++ b/gcc/range-op.cc
@@ -60,6 +60,7 @@ operator_ge op_ge;
operator_identity op_ident;
operator_cst op_cst;
operator_cast op_cast;
+operator_view op_view;
operator_plus op_plus;
operator_abs op_abs;
operator_minus op_minus;
@@ -97,6 +98,7 @@ range_op_table::range_op_table ()
set (INTEGER_CST, op_cst);
set (NOP_EXPR, op_cast);
set (CONVERT_EXPR, op_cast);
+ set (VIEW_CONVERT_EXPR, op_view);
set (FLOAT_EXPR, op_cast);
set (FIX_TRUNC_EXPR, op_cast);
set (PLUS_EXPR, op_plus);
@@ -3247,6 +3249,80 @@ operator_cast::op1_range (irange &r, tree type,
return true;
}
+// VIEW_CONVERT_EXPR works like a cast between integral values.
+// If the number of bits are not the same, behaviour is undefined,
+// so cast behaviour still works.
+
+bool
+operator_view::fold_range (irange &r, tree type,
+ const irange &op1, const irange &op2,
+ relation_trio rel) const
+{
+ return m_cast.fold_range (r, type, op1, op2, rel);
+}
+
+bool
+operator_view::fold_range (prange &r, tree type,
+ const prange &op1, const prange &op2,
+ relation_trio rel) const
+{
+ return m_cast.fold_range (r, type, op1, op2, rel);
+}
+bool
+operator_view::fold_range (irange &r, tree type,
+ const prange &op1, const irange &op2,
+ relation_trio rel) const
+{
+ return m_cast.fold_range (r, type, op1, op2, rel);
+}
+
+bool
+operator_view::fold_range (prange &r, tree type,
+ const irange &op1, const prange &op2,
+ relation_trio rel) const
+{
+ return m_cast.fold_range (r, type, op1, op2, rel);
+}
+
+bool
+operator_view::op1_range (irange &r, tree type,
+ const irange &lhs, const irange &op2,
+ relation_trio rel) const
+{
+ return m_cast.op1_range (r, type, lhs, op2, rel);
+}
+
+bool
+operator_view::op1_range (prange &r, tree type,
+ const prange &lhs, const prange &op2,
+ relation_trio rel) const
+{
+ return m_cast.op1_range (r, type, lhs, op2, rel);
+}
+
+bool
+operator_view::op1_range (irange &r, tree type,
+ const prange &lhs, const irange &op2,
+ relation_trio rel) const
+{
+ return m_cast.op1_range (r, type, lhs, op2, rel);
+}
+
+bool
+operator_view::op1_range (prange &r, tree type,
+ const irange &lhs, const prange &op2,
+ relation_trio rel) const
+{
+ return m_cast.op1_range (r, type, lhs, op2, rel);
+}
+
+void
+operator_view::update_bitmask (irange &r, const irange &lh,
+ const irange &rh) const
+{
+ m_cast.update_bitmask (r, lh, rh);
+}
+
class operator_logical_and : public range_operator
{
diff --git a/gcc/testsuite/gcc.dg/pr91191.c b/gcc/testsuite/gcc.dg/pr91191.c
new file mode 100644
index 0000000..7bf727e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr91191.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-evrp" } */
+
+unsigned char reg(_Bool b) {
+ union U {
+ unsigned char f0;
+ _Bool f1;
+ };
+ union U u;
+ u.f1 = b;
+ if (u.f0 > 1) {
+ // This cannot happen
+ // if b is only allowed
+ // to be 0 or 1:
+ return 42;
+ }
+ return 13;
+}
+
+/* { dg-final { scan-tree-dump "return 13" "evrp" } } */