diff options
author | Aldy Hernandez <aldyh@redhat.com> | 2020-05-14 16:27:28 +0200 |
---|---|---|
committer | Aldy Hernandez <aldyh@redhat.com> | 2020-05-14 19:37:12 +0200 |
commit | af1295ebe16845ced1901c1dc6fb16ba33f57818 (patch) | |
tree | 1374402fa1cb3420d1d14783bebc1ea2440203c5 | |
parent | 07a3e492431f314bc93f6845efe4a3282b621365 (diff) | |
download | gcc-af1295ebe16845ced1901c1dc6fb16ba33f57818.zip gcc-af1295ebe16845ced1901c1dc6fb16ba33f57818.tar.gz gcc-af1295ebe16845ced1901c1dc6fb16ba33f57818.tar.bz2 |
Adjust gimple_range_adjustment so it works for imagpart and pointer_diff.
-rw-r--r-- | gcc/gimple-range-stmt.cc | 60 | ||||
-rw-r--r-- | gcc/range-op.cc | 20 |
2 files changed, 74 insertions, 6 deletions
diff --git a/gcc/gimple-range-stmt.cc b/gcc/gimple-range-stmt.cc index f94078c..f5d3a3f 100644 --- a/gcc/gimple-range-stmt.cc +++ b/gcc/gimple-range-stmt.cc @@ -32,22 +32,69 @@ along with GCC; see the file COPYING3. If not see #include "tree-cfg.h" #include "gimple-range-stmt.h" +// Adjust the range for a pointer difference where the operands came +// from a memchr. +// +// This notices the following sequence: +// +// def = __builtin_memchr (arg, 0, sz) +// n = def - arg +// +// The range for N can be narrowed to [0, PTRDIFF_MAX - 1]. + +static void +adjust_pointer_diff_expr (irange &res, const gimple *diff_stmt) +{ + tree op0 = gimple_assign_rhs1 (diff_stmt); + tree op1 = gimple_assign_rhs2 (diff_stmt); + tree op0_ptype = TREE_TYPE (TREE_TYPE (op0)); + tree op1_ptype = TREE_TYPE (TREE_TYPE (op1)); + gimple *call; + + if (TREE_CODE (op0) == SSA_NAME + && TREE_CODE (op1) == SSA_NAME + && (call = SSA_NAME_DEF_STMT (op0)) + && is_gimple_call (call) + && gimple_call_builtin_p (call, BUILT_IN_MEMCHR) + && TYPE_MODE (op0_ptype) == TYPE_MODE (char_type_node) + && TYPE_PRECISION (op0_ptype) == TYPE_PRECISION (char_type_node) + && TYPE_MODE (op1_ptype) == TYPE_MODE (char_type_node) + && TYPE_PRECISION (op1_ptype) == TYPE_PRECISION (char_type_node) + && gimple_call_builtin_p (call, BUILT_IN_MEMCHR) + && vrp_operand_equal_p (op1, gimple_call_arg (call, 0)) + && integer_zerop (gimple_call_arg (call, 1))) + { + tree max = vrp_val_max (ptrdiff_type_node); + wide_int wmax = wi::to_wide (max, TYPE_PRECISION (TREE_TYPE (max))); + tree expr_type = gimple_expr_type (diff_stmt); + tree range_min = build_zero_cst (expr_type); + tree range_max = wide_int_to_tree (expr_type, wmax - 1); + int_range<1> r (range_min, range_max); + res.intersect (r); + } +} + // This function looks for situations when walking the use/def chains // may provide additonal contextual range information not exposed on // this statement. Like knowing the IMAGPART return value from a // builtin function is a boolean result. +// We should rework how we're called, as we have an op_unknown entry +// for IMAGPART_EXPR and POINTER_DIFF_EXPR in range-ops just so this +// function gets called. + static void -gimple_range_adjustment (const gimple *stmt, irange &res) +gimple_range_adjustment (irange &res, const gimple *stmt) { switch (gimple_expr_code (stmt)) { + case POINTER_DIFF_EXPR: + adjust_pointer_diff_expr (res, stmt); + return; + case IMAGPART_EXPR: { - tree name; - tree type = TREE_TYPE (gimple_assign_lhs (stmt)); - - name = TREE_OPERAND (gimple_assign_rhs1 (stmt), 0); + tree name = TREE_OPERAND (gimple_assign_rhs1 (stmt), 0); if (TREE_CODE (name) == SSA_NAME) { gimple *def_stmt = SSA_NAME_DEF_STMT (name); @@ -63,6 +110,7 @@ gimple_range_adjustment (const gimple *stmt, irange &res) { int_range<1> r; r.set_varying (boolean_type_node); + tree type = TREE_TYPE (gimple_assign_lhs (stmt)); range_cast (r, type); res.intersect (r); } @@ -235,7 +283,7 @@ gimple_range_fold (const gimple *stmt, irange &res, r1, r2); // If there are any gimple lookups, do those now. - gimple_range_adjustment (stmt, res); + gimple_range_adjustment (res, stmt); return true; } diff --git a/gcc/range-op.cc b/gcc/range-op.cc index 9cb9249..131f224 100644 --- a/gcc/range-op.cc +++ b/gcc/range-op.cc @@ -2748,6 +2748,24 @@ operator_identity::op1_range (irange &r, tree type ATTRIBUTE_UNUSED, } +class operator_unknown : public range_operator +{ +public: + virtual bool fold_range (irange &r, tree type, + const irange &op1, + const irange &op2) const; +} op_unknown; + +bool +operator_unknown::fold_range (irange &r, tree type, + const irange &lh ATTRIBUTE_UNUSED, + const irange &rh ATTRIBUTE_UNUSED) const +{ + r.set_varying (type); + return true; +} + + class operator_abs : public range_operator { public: @@ -3195,6 +3213,8 @@ integral_table::integral_table () set (SSA_NAME, op_identity); set (PAREN_EXPR, op_identity); set (OBJ_TYPE_REF, op_identity); + set (IMAGPART_EXPR, op_unknown); + set (POINTER_DIFF_EXPR, op_unknown); set (ABS_EXPR, op_abs); set (ABSU_EXPR, op_absu); set (NEGATE_EXPR, op_negate); |