/* 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 ();
/* 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)
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)
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);
}
}
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);
}
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)
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))
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
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: */
/* 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);
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)
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;
}
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;
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;
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.