]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
ipa: Improve how we derive value ranges from IPA invariants
authorMartin Jambor <mjambor@suse.cz>
Tue, 17 Dec 2024 10:17:14 +0000 (11:17 +0100)
committerMartin Jambor <jamborm@gcc.gnu.org>
Tue, 17 Dec 2024 10:19:36 +0000 (11:19 +0100)
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

gcc/cgraph.h
gcc/ipa-cp.cc
gcc/ipa-fnsummary.cc
gcc/ipa-prop.cc
gcc/ipa-prop.h
gcc/symtab.cc

index 50bae96de4cfd61977c746e1d4cc816b882cc59d..9b4cb6383afc2eab80007668cd509461dd04c995 100644 (file)
@@ -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 ();
 
index a664bc03f62a6f884609a932be7bf020c97ccdfb..5d7b3d25df5d05d6af688363f7cd19785312c5aa 100644 (file)
@@ -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);
     }
index 3f5e09960ef80c683ba1c8525e45799be809303f..6799ffe0b9af51178cc219ac567dcf87aebbfe80 100644 (file)
@@ -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))
index f0b915ba2be1f3ea1947464d2dafddf47fa24962..0daa950985b744bff0a3fe8b65fd323d74e5db58 100644 (file)
@@ -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
index 1ff71aba83043775dce7694017a696145ae844f8..d77340bfb6e78c0055ee63eeeff7fc9ededb10f5 100644 (file)
@@ -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);
index 5be463ff7682a39e25a6346c5bbfd2f76b1f1af3..3804383a4e1cd8666a870a45de35e7a30d0a2784 100644 (file)
@@ -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.