aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorMartin Jambor <mjambor@suse.cz>2024-12-17 11:17:14 +0100
committerMartin Jambor <jamborm@gcc.gnu.org>2024-12-17 11:19:36 +0100
commit5d740f56a162702a33379789a4d6134d9733aa71 (patch)
tree2e9b473909e8862ef5213db6e7bf900d336a0c6c /gcc
parent1eb41aeb49a491f5b18d160074e651a76afc655a (diff)
downloadgcc-5d740f56a162702a33379789a4d6134d9733aa71.zip
gcc-5d740f56a162702a33379789a4d6134d9733aa71.tar.gz
gcc-5d740f56a162702a33379789a4d6134d9733aa71.tar.bz2
ipa: Improve how we derive value ranges from IPA invariants
I believe that the current function ipa_range_set_and_normalize lacks a check that a base of an ADDR_EXPR lacks a test whether the base really cannot be NULL, so this patch adds it. Moreover, I never liked the name as I do not think it makes the value of ranges any more normal but rather just special-cases non-zero ip_invariant pointers. Therefore, I have given it a different name and moved it to a .cc file, our LTO bootstrap should inline (and/or split) it if necessary anyway. Because, as Honza correctly pointed out, deriving non-NULLness from a pointer depends on flag_delete_null_pointer_checks which is an optimization flag and thus depends on a given function, in this version of the patch ipa_get_range_from_ip_invariant gets a context_node parameter for that purpose. This then needs to be used within symtab_node::nonzero_address which gets a special overload in which the value of the flag can be provided as a parameter. gcc/ChangeLog: 2024-12-11 Martin Jambor <mjambor@suse.cz> * cgraph.h (symtab_node): Add a new overload of nonzero_address. * symtab.cc (symtab_node::nonzero_address): Add a new overload whith a parameter for delete_null_pointer_checks. Make the original overload call the new one which has retains the actual implementation. * ipa-prop.h (ipa_get_range_from_ip_invariant): Declare. (ipa_range_set_and_normalize): Remove. * ipa-prop.cc (ipa_get_range_from_ip_invariant): New function. (ipa_range_set_and_normalize): Remove. * ipa-cp.cc (ipa_vr_intersect_with_arith_jfunc): Add a new parameter context_node. Use ipa_get_range_from_ip_invariant instead of ipa_range_set_and_normalize and pass to it the new parameter. (ipa_value_range_from_jfunc): Pass cs->caller as the context_node to ipa_vr_intersect_with_arith_jfunc. (propagate_vr_across_jump_function): Likewise. (ipa_get_range_from_ip_invariant): New function. * ipa-fnsummary.cc (evaluate_conditions_for_known_args): Use ipa_get_range_from_ip_invariant instead of ipa_range_set_and_normalize
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cgraph.h4
-rw-r--r--gcc/ipa-cp.cc12
-rw-r--r--gcc/ipa-fnsummary.cc4
-rw-r--r--gcc/ipa-prop.cc37
-rw-r--r--gcc/ipa-prop.h15
-rw-r--r--gcc/symtab.cc21
6 files changed, 67 insertions, 26 deletions
diff --git a/gcc/cgraph.h b/gcc/cgraph.h
index 50bae96..9b4cb63 100644
--- a/gcc/cgraph.h
+++ b/gcc/cgraph.h
@@ -431,6 +431,10 @@ public:
/* Return true if ONE and TWO are part of the same COMDAT group. */
inline bool in_same_comdat_group_p (symtab_node *target);
+ /* Return true if symbol is known to be nonzero, assume that
+ flag_delete_null_pointer_checks is equal to delete_null_pointer_checks. */
+ bool nonzero_address (bool delete_null_pointer_checks);
+
/* Return true if symbol is known to be nonzero. */
bool nonzero_address ();
diff --git a/gcc/ipa-cp.cc b/gcc/ipa-cp.cc
index a664bc0..5d7b3d2 100644
--- a/gcc/ipa-cp.cc
+++ b/gcc/ipa-cp.cc
@@ -1693,11 +1693,14 @@ ipa_vr_operation_and_type_effects (vrange &dst_vr,
/* Given a PASS_THROUGH jump function JFUNC that takes as its source SRC_VR of
SRC_TYPE and the result needs to be DST_TYPE, if any value range information
- can be deduced at all, intersect VR with it. */
+ can be deduced at all, intersect VR with it. CONTEXT_NODE is the call graph
+ node representing the function for which optimization flags should be
+ evaluated. */
static void
ipa_vr_intersect_with_arith_jfunc (vrange &vr,
ipa_jump_func *jfunc,
+ cgraph_node *context_node,
const value_range &src_vr,
tree src_type,
tree dst_type)
@@ -1720,7 +1723,7 @@ ipa_vr_intersect_with_arith_jfunc (vrange &vr,
if (!handler)
return;
value_range op_vr (TREE_TYPE (operand));
- ipa_range_set_and_normalize (op_vr, operand);
+ ipa_get_range_from_ip_invariant (op_vr, operand, context_node);
tree operation_type;
if (TREE_CODE_CLASS (operation) == tcc_comparison)
@@ -1776,7 +1779,8 @@ ipa_value_range_from_jfunc (vrange &vr,
value_range srcvr;
(*sum->m_vr)[idx].get_vrange (srcvr);
- ipa_vr_intersect_with_arith_jfunc (vr, jfunc, srcvr, src_type, parm_type);
+ ipa_vr_intersect_with_arith_jfunc (vr, jfunc, cs->caller, srcvr, src_type,
+ parm_type);
}
}
@@ -2562,7 +2566,7 @@ propagate_vr_across_jump_function (cgraph_edge *cs, ipa_jump_func *jfunc,
if (ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR
|| !ipa_edge_within_scc (cs))
- ipa_vr_intersect_with_arith_jfunc (vr, jfunc,
+ ipa_vr_intersect_with_arith_jfunc (vr, jfunc, cs->caller,
src_lats->m_value_range.m_vr,
operand_type, param_type);
}
diff --git a/gcc/ipa-fnsummary.cc b/gcc/ipa-fnsummary.cc
index 3f5e099..6799ffe 100644
--- a/gcc/ipa-fnsummary.cc
+++ b/gcc/ipa-fnsummary.cc
@@ -518,7 +518,7 @@ evaluate_conditions_for_known_args (struct cgraph_node *node,
value_range op0 (TREE_TYPE (op->val[0]));
range_op_handler handler (op->code);
- ipa_range_set_and_normalize (op0, op->val[0]);
+ ipa_get_range_from_ip_invariant (op0, op->val[0], node);
if (!handler
|| !res.supports_type_p (op->type)
@@ -537,7 +537,7 @@ evaluate_conditions_for_known_args (struct cgraph_node *node,
value_range val_vr (TREE_TYPE (c->val));
range_op_handler handler (c->code);
- ipa_range_set_and_normalize (val_vr, c->val);
+ ipa_get_range_from_ip_invariant (val_vr, c->val, node);
if (!handler
|| !val_vr.supports_type_p (TREE_TYPE (c->val))
diff --git a/gcc/ipa-prop.cc b/gcc/ipa-prop.cc
index f0b915b..0daa950 100644
--- a/gcc/ipa-prop.cc
+++ b/gcc/ipa-prop.cc
@@ -2312,6 +2312,43 @@ ipa_set_jfunc_vr (ipa_jump_func *jf, const ipa_vr &vr)
ipa_set_jfunc_vr (jf, tmp);
}
+/* Given VAL that conforms to is_gimple_ip_invariant, produce a VRANGE that
+ represents it as a range. CONTEXT_NODE is the call graph node representing
+ the function for which optimization flags should be evaluated. */
+
+void
+ipa_get_range_from_ip_invariant (vrange &r, tree val, cgraph_node *context_node)
+{
+ if (TREE_CODE (val) == ADDR_EXPR)
+ {
+ symtab_node *symbol;
+ tree base = TREE_OPERAND (val, 0);
+ if (!DECL_P (base))
+ {
+ r.set_varying (TREE_TYPE (val));
+ return;
+ }
+ if (!decl_in_symtab_p (base))
+ {
+ r.set_nonzero (TREE_TYPE (val));
+ return;
+ }
+ if (!(symbol = symtab_node::get (base)))
+ {
+ r.set_varying (TREE_TYPE (val));
+ return;
+ }
+
+ bool delete_null_pointer_checks
+ = opt_for_fn (context_node->decl, flag_delete_null_pointer_checks);
+ if (symbol->nonzero_address (delete_null_pointer_checks))
+ r.set_nonzero (TREE_TYPE (val));
+ else
+ r.set_varying (TREE_TYPE (val));
+ }
+ else
+ r.set (val, val);
+}
/* If T is an SSA_NAME that is the result of a simple type conversion statement
from an integer type to another integer type which is known to be able to
diff --git a/gcc/ipa-prop.h b/gcc/ipa-prop.h
index 1ff71ab..d77340b 100644
--- a/gcc/ipa-prop.h
+++ b/gcc/ipa-prop.h
@@ -1258,7 +1258,7 @@ tree ipcp_get_aggregate_const (struct function *func, tree parm, bool by_ref,
HOST_WIDE_INT bit_size);
bool unadjusted_ptr_and_unit_offset (tree op, tree *ret,
poly_int64 *offset_ret);
-
+void ipa_get_range_from_ip_invariant (vrange &r, tree val, cgraph_node *node);
void ipa_prop_cc_finalize (void);
/* From tree-sra.cc: */
@@ -1267,19 +1267,6 @@ tree build_ref_for_offset (location_t, tree, poly_int64, bool, tree,
/* In ipa-cp.cc */
void ipa_cp_cc_finalize (void);
-
-/* Set R to the range of [VAL, VAL] while normalizing addresses to
- non-zero. */
-
-inline void
-ipa_range_set_and_normalize (vrange &r, tree val)
-{
- if (TREE_CODE (val) == ADDR_EXPR)
- r.set_nonzero (TREE_TYPE (val));
- else
- r.set (val, val);
-}
-
bool ipa_return_value_range (value_range &range, tree decl);
void ipa_record_return_value_range (value_range val);
bool ipa_jump_functions_equivalent_p (ipa_jump_func *jf1, ipa_jump_func *jf2);
diff --git a/gcc/symtab.cc b/gcc/symtab.cc
index 5be463f..3804383 100644
--- a/gcc/symtab.cc
+++ b/gcc/symtab.cc
@@ -2207,10 +2207,11 @@ symtab_node::get_partitioning_class (void)
return SYMBOL_PARTITION;
}
-/* Return true when symbol is known to be non-zero. */
+/* Return true when symbol is known to be non-zero, assume that
+ flag_delete_null_pointer_checks is equal to delete_null_pointer_checks. */
bool
-symtab_node::nonzero_address ()
+symtab_node::nonzero_address (bool delete_null_pointer_checks)
{
/* Weakrefs may be NULL when their target is not defined. */
if (alias && weakref)
@@ -2234,7 +2235,7 @@ symtab_node::nonzero_address ()
if (target->resolution != LDPR_UNKNOWN
&& target->resolution != LDPR_UNDEF
&& !target->can_be_discarded_p ()
- && flag_delete_null_pointer_checks)
+ && delete_null_pointer_checks)
return true;
return false;
}
@@ -2251,7 +2252,7 @@ symtab_node::nonzero_address ()
When parsing, beware the cases when WEAK attribute is added later. */
if ((!DECL_WEAK (decl) || DECL_COMDAT (decl))
- && flag_delete_null_pointer_checks)
+ && delete_null_pointer_checks)
{
refuse_visibility_changes = true;
return true;
@@ -2262,7 +2263,7 @@ symtab_node::nonzero_address ()
Play safe for flag_delete_null_pointer_checks where weak definition may
be re-defined by NULL. */
if (definition && !DECL_EXTERNAL (decl)
- && (flag_delete_null_pointer_checks || !DECL_WEAK (decl)))
+ && (delete_null_pointer_checks || !DECL_WEAK (decl)))
{
if (!DECL_WEAK (decl))
refuse_visibility_changes = true;
@@ -2273,11 +2274,19 @@ symtab_node::nonzero_address ()
if (resolution != LDPR_UNKNOWN
&& resolution != LDPR_UNDEF
&& !can_be_discarded_p ()
- && flag_delete_null_pointer_checks)
+ && delete_null_pointer_checks)
return true;
return false;
}
+/* Return true when symbol is known to be non-zero. */
+
+bool
+symtab_node::nonzero_address ()
+{
+ return nonzero_address (flag_delete_null_pointer_checks);
+}
+
/* Return 0 if symbol is known to have different address than S2,
Return 1 if symbol is known to have same address as S2,
return -1 otherwise.