diff options
author | Andrew MacLeod <amacleod@redhat.com> | 2020-11-12 11:53:52 -0500 |
---|---|---|
committer | Andrew MacLeod <amacleod@redhat.com> | 2020-11-13 09:36:20 -0500 |
commit | 47923622c663ffad8b14aa93706183290d4f6791 (patch) | |
tree | 640a99535f2c668fbee54205870cd5f00deec8c0 /gcc/gimple-range.cc | |
parent | ac91af71c93462cbc701bbd104fa21894bb15e86 (diff) | |
download | gcc-47923622c663ffad8b14aa93706183290d4f6791.zip gcc-47923622c663ffad8b14aa93706183290d4f6791.tar.gz gcc-47923622c663ffad8b14aa93706183290d4f6791.tar.bz2 |
Cleanup range of address calculations.
Align EVRP and ranger for how ranges of ADDR_EXPR are calculated.
gcc/
* gimple-range.cc: (gimple_ranger::range_of_range_op): Check for
ADDR_EXPR and call range_of_address.
(gimple_ranger::range_of_address): Rename from
range_of_non_trivial_assignment and match vrp_stmt_computes_nonzero.
* gimple-range.h: (range_of_address): Renamed.
* range-op.cc: (pointer_table): Add INTEGER_CST handler.
gcc/testsuite/
* gcc.dg/tree-ssa/pr78655.c: New.
Diffstat (limited to 'gcc/gimple-range.cc')
-rw-r--r-- | gcc/gimple-range.cc | 99 |
1 files changed, 68 insertions, 31 deletions
diff --git a/gcc/gimple-range.cc b/gcc/gimple-range.cc index 92a6335..4f5d502 100644 --- a/gcc/gimple-range.cc +++ b/gcc/gimple-range.cc @@ -431,8 +431,9 @@ gimple_ranger::range_of_range_op (irange &r, gimple *s) m_cache.register_dependency (lhs, op2); } - if (range_of_non_trivial_assignment (r, s)) - return true; + if (gimple_code (s) == GIMPLE_ASSIGN + && gimple_assign_rhs_code (s) == ADDR_EXPR) + return range_of_address (r, s); if (range_of_expr (range1, op1, s)) { @@ -446,48 +447,84 @@ gimple_ranger::range_of_range_op (irange &r, gimple *s) return true; } -// Calculate the range of a non-trivial assignment. That is, is one -// inolving arithmetic on an SSA name (for example, an ADDR_EXPR). +// Calculate the range of an assignment containing an ADDR_EXPR. // Return the range in R. -// -// If a range cannot be calculated, return false. +// If a range cannot be calculated, set it to VARYING and return true. bool -gimple_ranger::range_of_non_trivial_assignment (irange &r, gimple *stmt) +gimple_ranger::range_of_address (irange &r, gimple *stmt) { - if (gimple_code (stmt) != GIMPLE_ASSIGN) - return false; + gcc_checking_assert (gimple_code (stmt) == GIMPLE_ASSIGN); + gcc_checking_assert (gimple_assign_rhs_code (stmt) == ADDR_EXPR); - tree base = gimple_range_base_of_assignment (stmt); - if (base) + bool strict_overflow_p; + tree expr = gimple_assign_rhs1 (stmt); + poly_int64 bitsize, bitpos; + tree offset; + machine_mode mode; + int unsignedp, reversep, volatilep; + tree base = get_inner_reference (TREE_OPERAND (expr, 0), &bitsize, + &bitpos, &offset, &mode, &unsignedp, + &reversep, &volatilep); + + + if (base != NULL_TREE + && TREE_CODE (base) == MEM_REF + && TREE_CODE (TREE_OPERAND (base, 0)) == SSA_NAME) { - if (TREE_CODE (base) == MEM_REF) + tree ssa = TREE_OPERAND (base, 0); + gcc_checking_assert (irange::supports_type_p (TREE_TYPE (ssa))); + range_of_expr (r, ssa, stmt); + range_cast (r, TREE_TYPE (gimple_assign_rhs1 (stmt))); + + poly_offset_int off = 0; + bool off_cst = false; + if (offset == NULL_TREE || TREE_CODE (offset) == INTEGER_CST) { - if (TREE_CODE (TREE_OPERAND (base, 0)) == SSA_NAME) - { - int_range_max range1; - tree ssa = TREE_OPERAND (base, 0); - if (range_of_expr (range1, ssa, stmt)) - { - tree type = TREE_TYPE (ssa); - range_operator *op = range_op_handler (POINTER_PLUS_EXPR, - type); - int_range<2> offset (TREE_OPERAND (base, 1), - TREE_OPERAND (base, 1)); - op->fold_range (r, type, range1, offset); - return true; - } - } - return false; + off = mem_ref_offset (base); + if (offset) + off += poly_offset_int::from (wi::to_poly_wide (offset), + SIGNED); + off <<= LOG2_BITS_PER_UNIT; + off += bitpos; + off_cst = true; } - if (gimple_assign_rhs_code (stmt) == ADDR_EXPR) + /* If &X->a is equal to X, the range of X is the result. */ + if (off_cst && known_eq (off, 0)) + return true; + else if (flag_delete_null_pointer_checks + && !TYPE_OVERFLOW_WRAPS (TREE_TYPE (expr))) + { + /* For -fdelete-null-pointer-checks -fno-wrapv-pointer we don't + allow going from non-NULL pointer to NULL. */ + if(!range_includes_zero_p (&r)) + return true; + } + /* If MEM_REF has a "positive" offset, consider it non-NULL + always, for -fdelete-null-pointer-checks also "negative" + ones. Punt for unknown offsets (e.g. variable ones). */ + if (!TYPE_OVERFLOW_WRAPS (TREE_TYPE (expr)) + && off_cst + && known_ne (off, 0) + && (flag_delete_null_pointer_checks || known_gt (off, 0))) { - // Handle "= &a" and return non-zero. r = range_nonzero (TREE_TYPE (gimple_assign_rhs1 (stmt))); return true; } + r = int_range<2> (TREE_TYPE (gimple_assign_rhs1 (stmt))); + return true; } - return false; + + // Handle "= &a". + if (tree_single_nonzero_warnv_p (expr, &strict_overflow_p)) + { + r = range_nonzero (TREE_TYPE (gimple_assign_rhs1 (stmt))); + return true; + } + + // Otherwise return varying. + r = int_range<2> (TREE_TYPE (gimple_assign_rhs1 (stmt))); + return true; } // Calculate a range for phi statement S and return it in R. |