diff options
| author | Andrew MacLeod <amacleod@redhat.com> | 2025-10-25 11:59:55 -0400 |
|---|---|---|
| committer | Andrew MacLeod <amacleod@redhat.com> | 2025-10-29 10:21:54 -0400 |
| commit | 8b0e43d7ec87f53d5bbd0a2d4d876d0aa1327a33 (patch) | |
| tree | 46a465c2f98c1b953f60481d08b9ba1f257ce454 /gcc | |
| parent | dd7dffb02ff5cd3a88654deacad67298ee8ed8fa (diff) | |
| download | gcc-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.cc | 4 | ||||
| -rw-r--r-- | gcc/range-op-mixed.h | 41 | ||||
| -rw-r--r-- | gcc/range-op.cc | 76 | ||||
| -rw-r--r-- | gcc/testsuite/gcc.dg/pr91191.c | 20 |
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" } } */ |
