From 0689fa587ed870e886ec5d6a0404ba20771b93c3 Mon Sep 17 00:00:00 2001 From: Andrew MacLeod Date: Mon, 17 Oct 2022 10:23:55 -0400 Subject: [PATCH 2/3] Inferred support of ASSUME --- gcc/gimple-range-gori.h | 6 ++--- gcc/gimple-range-infer.cc | 50 +++++++++++++++++++++++++++++++++++++++ gcc/gimple-range.cc | 48 +++++++++++++++++++++++++++++++++++++ gcc/gimple-range.h | 1 + 4 files changed, 102 insertions(+), 3 deletions(-) diff --git a/gcc/gimple-range-gori.h b/gcc/gimple-range-gori.h index c7a32162a1b..6cc533b58b2 100644 --- a/gcc/gimple-range-gori.h +++ b/gcc/gimple-range-gori.h @@ -165,15 +165,15 @@ public: bool has_edge_range_p (tree name, basic_block bb = NULL); bool has_edge_range_p (tree name, edge e); void dump (FILE *f); + bool compute_operand_range (vrange &r, gimple *stmt, const vrange &lhs, + tree name, class fur_source &src, + value_relation *rel = NULL); private: bool refine_using_relation (tree op1, vrange &op1_range, tree op2, vrange &op2_range, fur_source &src, relation_kind k); bool may_recompute_p (tree name, edge e); bool may_recompute_p (tree name, basic_block bb = NULL); - bool compute_operand_range (vrange &r, gimple *stmt, const vrange &lhs, - tree name, class fur_source &src, - value_relation *rel = NULL); bool compute_operand_range_switch (vrange &r, gswitch *s, const vrange &lhs, tree name, fur_source &src); bool compute_operand1_range (vrange &r, gimple_range_op_handler &handler, diff --git a/gcc/gimple-range-infer.cc b/gcc/gimple-range-infer.cc index f0d66d047a6..46a781c7826 100644 --- a/gcc/gimple-range-infer.cc +++ b/gcc/gimple-range-infer.cc @@ -36,6 +36,29 @@ along with GCC; see the file COPYING3. If not see #include "gimple-walk.h" #include "cfganal.h" + +// This routine should be provided to properly look up any +// values of NAME that has been determined to have a value specified by +// the function ASSUME_ID. Return TRUE if it has a value and is NOT VARYING. + +// Given an ASSUME_ID name, return any range evaluated for NAME. + +bool +query_assume_call (vrange &r, tree assume_id, tree name) +{ + if (dump_file) + fprintf (dump_file, "query_assume_call injection\n"); + if (assume_id != NULL_TREE && irange::supports_p (TREE_TYPE (name))) + { + int_range<2> f (build_int_cst (TREE_TYPE (name), 42), + build_int_cst (TREE_TYPE (name), 42)); + r = f; + return true; + } + return false; +} + + // Adapted from infer_nonnull_range_by_dereference and check_loadstore // to process nonnull ssa_name OP in S. DATA contains a pointer to a // stmt range inference instance. @@ -111,6 +134,33 @@ gimple_infer_range::gimple_infer_range (gimple *s) // Fallthru and walk load/store ops now. } + if (is_a (s) && gimple_call_internal_p (s) + && gimple_call_internal_fn (s) == IFN_ASSUME) + { + tree assume_id = gimple_call_arg (s, 0); + for (unsigned i = 1; i < gimple_call_num_args (s); i++) + { + tree op = gimple_call_arg (s, i); + tree type = TREE_TYPE (op); + if (gimple_range_ssa_p (op) && Value_Range::supports_type_p (type)) + { + Value_Range assume_range (type); + if (query_assume_call (assume_range, assume_id, op)) + { + add_range (op, assume_range); + if (dump_file) + { + print_generic_expr (dump_file, assume_id, TDF_SLIM); + fprintf (dump_file, " assume inferred range of "); + print_generic_expr (dump_file, op, TDF_SLIM); + fprintf (dump_file, " to "); + assume_range.dump (dump_file); + fputc ('\n', dump_file); + } + } + } + } + } // Look for possible non-null values. if (flag_delete_null_pointer_checks && gimple_code (s) != GIMPLE_ASM && !gimple_clobber_p (s)) diff --git a/gcc/gimple-range.cc b/gcc/gimple-range.cc index d67d6499c78..f9d6b73e4e8 100644 --- a/gcc/gimple-range.cc +++ b/gcc/gimple-range.cc @@ -483,6 +483,54 @@ gimple_ranger::register_inferred_ranges (gimple *s) m_cache.apply_inferred_ranges (s); } +// This function is used to support the ASSUME keyword. If the current +// function returns an integral value, it will attempt to determine what +// the range of NAME is if the funciton returns 1. It will return TRUE +// if it finds a non-varying range, otherwise FALSE. + +bool +gimple_ranger::assume_range_p (vrange &r, tree name) +{ + bool result_p = false; + edge e; + edge_iterator ei; + basic_block exit_bb = EXIT_BLOCK_PTR_FOR_FN (cfun); + Value_Range tmp (TREE_TYPE (name)); + r.set_undefined (); + + FOR_EACH_EDGE (e, ei, exit_bb->preds) + { + result_p = false; + gimple_stmt_iterator gsi = gsi_last_nondebug_bb (e->src); + if (gsi_end_p (gsi)) + break; + gimple *s = gsi_stmt (gsi); + if (!is_a (s)) + break; + greturn *gret = as_a (s); + tree op = gimple_return_retval (gret); + if (!gimple_range_ssa_p (op)) + break; + gimple *def = SSA_NAME_DEF_STMT (op); + if (!def || gimple_get_lhs (def) != op) + break; + tree lhs_type = TREE_TYPE (op); + if (!irange::supports_p (lhs_type)) + break; + unsigned prec = TYPE_PRECISION (lhs_type); + int_range<2> lhs_range (lhs_type, wi::one (prec), wi::one (prec)); + fur_stmt src (s, this); + if (gori ().compute_operand_range (tmp, def, lhs_range, name, src)) + { + r.union_ (tmp); + result_p = true; + } + } + // If every exit predecessor does not calculate a value, we can + // assume nothing. + return result_p && !r.varying_p (); +} + // This routine will export whatever global ranges are known to GCC // SSA_RANGE_NAME_INFO and SSA_NAME_PTR_INFO fields. diff --git a/gcc/gimple-range.h b/gcc/gimple-range.h index 8b2ff5685e5..3a6fdd9dbe0 100644 --- a/gcc/gimple-range.h +++ b/gcc/gimple-range.h @@ -61,6 +61,7 @@ public: auto_edge_flag non_executable_edge_flag; bool fold_stmt (gimple_stmt_iterator *gsi, tree (*) (tree)); void register_inferred_ranges (gimple *s); + bool assume_range_p (vrange &r, tree name); protected: bool fold_range_internal (vrange &r, gimple *s, tree name); void prefill_name (vrange &r, tree name); -- 2.37.3