[multiple changes]

2008-05-07 Kenneth Zadeck <zadeck@naturalbridge.com>

        PATCH rtl/7335
        PATCH rtl/33826
        * see.c (see_copy_insn): Copy new pure const attributes for new
        call.
        * c-decl.c (merge_decls): Ditto.
        * postreload.c (record_opr_changes): Change CONST_OR_PURE_CALL_P
        to RTL_CONST_OR_PURE_CALL_P.
        * tree.c (define_local_buitin): Rename DECL_IS_PURE to
        DECL_PURE_P.  Initialized DECL_LOOPING_CONST_PURE.
        (process_call_operands): Set tree_side_effects properly.
        * tree.h (TREE_READONLY_DECL_P): Removed.
        (DECL_IS_PURE): Renamed to DECL_PURE_P.
        (DECL_LOOPING_OR_CONST_P): New macro.
        (struct tree_function_decl): Added looping_const_or_pure_p.
        (ECF_*) Renumbered.
        (ECF_LOOPING_OR_CONST_P): New macro,
        * rtlanal.c (pure_const_p): Removed.
        * builtins.c (expand_builtin): Rename DECL_IS_PURE to DECL_PURE_P.
        * reorg.c (delete_prior_computation) Changed CONST_OR_PURE_CALL_P
        to RTL_CONST_CALL_P.
        * ipa-pure-const.c (pure_const_state_e): Added looping field.
        (check_decl, check_tree, check_call, scan_function): Initialize
        looping.
        (analyze_function): Rename DECL_IS_PURE to DECL_PURE_P.
        (static_execute): Set looping true for recursive functions.
        Undo setting state to IPA_NEITHER for recursive functions.
        * cse.c (cse_insn): 
        * ifcvt.c (noce_can_store_speculate_p): Changed
        CONST_OR_PURE_CALL_P and pure_call_p to RTL_CONST_CALL_P or 
        RTL_CONST_OR_PURE_CALL_P.
        * dse.c (scan_insn): Ditto.
        * local-alloc.c (validate_equiv_mem, memref_used_between_p): Ditto.
        * gcse.c (oprs_not_seen_p) Changed CONST_OR_PURE_CALL_P to
        RTL_CONST_OR_PURE_CALL_P.
        (store_killed_in_insn): Changed CONST_OR_PURE_CALL_P and
        pure_call_p to RTL_CONST_CALL_P.
        * gimplify.c (gimplify_call_expr): Clear side effects for
        non-looping pure and constant calls.
        * calls.c (emit_call_1): Set rtl flags from ecf flags.
        (flags_from_decl_or_type): Set ecf flags from decl flags.
        (initialize_argument_information): Turn off
        ECF_LOOPING_CONST_OR_PURE when turning off ECF_CONST.
        Change const to pure if callee_copies is true rather than just
        turning off const.
        (expand_call): Turn off ECF_LOOPING_PURE_CONST_CALL and remove old
        way of marking pure calls.
        (emit_library_call_value_1): Turn off ECF_LOOPING_PURE_CONST_CALL.
        Remove hack that was supposed to fix pr7335 and remove old
        way of marking pure calls.
        * emit-rtl.c (emit_copy_of_insn_after): Copy RTL_CONST_CALL_P,
        RTL_PURE_CALL_P, RTL_LOOPING_CONST_OR_PURE_CALL_P.
        * cselib.c (cselib_process_insn): Changed CONST_OR_PURE_CALL_P to
        RTL_CONST_OR_PURE_CALL_P.
        * tree-ssa-pre.c (can_value_number_call): Fixed spacing.
        * loop-invariant.c (find_exits, find_invariant_bb): Changed
        CONST_OR_PURE_CALL_P to RTL_CONST_OR_PURE_CALL_P.
        * sched-deps.c (schedule_analyze): Ditto.
        * rtl.h (struct rtx_def): Use call field, unchanging field, and
        return_val field of calls to represent pure and const function
        info.
        (CONST_OR_PURE_CALL_P): Deleted macro.
        (RTL_CONST_CALL_P, RTL_PURE_CALL_P,
        RTL_LOOPING_CONST_OR_PURE_CALL_P, RTL_CONST_OR_PURE_P): New macros.
        * tree-inline.c (copy_body_r): Changed TREE_READONLY_DECL_P to
        TREE_READONLY.
        * tree-optimize.c (execute_fixup_cfg): Added test for
        ECF_LOOPING_CONST_OR_PURE.
        * c-common.c (handle_pure_attribute): Changed DECL_IS_PURE to
        DECL_PURE_P.
        * tree-cfg.c (update_call_expr_flags): Do not clear tree side
        effects for looping pure or const calls.
        (verify_gimple_expr): Added verification code. 
        * config/alpha/alpha.c (alpha_legitimize_address,
        alpha_emit_xfloating_libcall): Changed CONST_OR_PURE_CALL_P to
        RTL_CONST_CALL_P.
        * config/s390/s390.c (s390_emit_tls_call_insn): Ditto.
        * config/rs6000/rs6000.c (rs6000_legitimize_tls_address): Ditto.
        * config/mips/mips.c (mips_call_tls_get_addr): Ditto.
        * cfgrtl.c (need_fake_edge_p): Changed CONST_OR_PURE_CALL_P to
        RTL_CONST_OR_PURE_CALL_P.
        * dce.c (deletable_insn_p): Allow non looping, non sibling, pure
        and const calls to be deleted.

java:
2008-05-07  Kenneth Zadeck <zadeck@naturalbridge.com>

	* decl.c (java_init_decl_processing): Change DECL_IS_PURE to
	DECL_PURE_P.

cp:
2008-05-07 Kenneth Zadeck <zadeck@naturalbridge.com>

	 * decl.c (duplicate_decls): Merge in DECL_PURE_P, TREE_READONLY,
	 DECL_LOOPING_CONST_OR_PURE_P attributes.
	 * rtti.c (build_dynamic_cast_1): Rename DECL_IS_PURE to
	 DECL_PURE_P.

gfortran:
2008-05-07 Kenneth Zadeck <zadeck@naturalbridge.com>

	 * trans-decl.c (gfc_get_extern_function_decl, build_function_decl):
	 Rename DECL_IS_PURE to DECL_PURE_P.

From-SVN: r135053
This commit is contained in:
Kenneth Zadeck 2008-05-07 20:48:07 +00:00 committed by Kenneth Zadeck
parent d320458418
commit becfd6e57b
41 changed files with 343 additions and 183 deletions

View File

@ -1,3 +1,89 @@
2008-05-07 Kenneth Zadeck <zadeck@naturalbridge.com>
PATCH rtl/7335
PATCH rtl/33826
* see.c (see_copy_insn): Copy new pure const attributes for new
call.
* c-decl.c (merge_decls): Ditto.
* postreload.c (record_opr_changes): Change CONST_OR_PURE_CALL_P
to RTL_CONST_OR_PURE_CALL_P.
* tree.c (define_local_buitin): Rename DECL_IS_PURE to
DECL_PURE_P. Initialized DECL_LOOPING_CONST_PURE.
(process_call_operands): Set tree_side_effects properly.
* tree.h (TREE_READONLY_DECL_P): Removed.
(DECL_IS_PURE): Renamed to DECL_PURE_P.
(DECL_LOOPING_OR_CONST_P): New macro.
(struct tree_function_decl): Added looping_const_or_pure_p.
(ECF_*) Renumbered.
(ECF_LOOPING_OR_CONST_P): New macro,
* rtlanal.c (pure_const_p): Removed.
* builtins.c (expand_builtin): Rename DECL_IS_PURE to DECL_PURE_P.
* reorg.c (delete_prior_computation) Changed CONST_OR_PURE_CALL_P
to RTL_CONST_CALL_P.
* ipa-pure-const.c (pure_const_state_e): Added looping field.
(check_decl, check_tree, check_call, scan_function): Initialize
looping.
(analyze_function): Rename DECL_IS_PURE to DECL_PURE_P.
(static_execute): Set looping true for recursive functions.
Undo setting state to IPA_NEITHER for recursive functions.
* cse.c (cse_insn):
* ifcvt.c (noce_can_store_speculate_p): Changed
CONST_OR_PURE_CALL_P and pure_call_p to RTL_CONST_CALL_P or
RTL_CONST_OR_PURE_CALL_P.
* dse.c (scan_insn): Ditto.
* local-alloc.c (validate_equiv_mem, memref_used_between_p): Ditto.
* gcse.c (oprs_not_seen_p) Changed CONST_OR_PURE_CALL_P to
RTL_CONST_OR_PURE_CALL_P.
(store_killed_in_insn): Changed CONST_OR_PURE_CALL_P and
pure_call_p to RTL_CONST_CALL_P.
* gimplify.c (gimplify_call_expr): Clear side effects for
non-looping pure and constant calls.
* calls.c (emit_call_1): Set rtl flags from ecf flags.
(flags_from_decl_or_type): Set ecf flags from decl flags.
(initialize_argument_information): Turn off
ECF_LOOPING_CONST_OR_PURE when turning off ECF_CONST.
Change const to pure if callee_copies is true rather than just
turning off const.
(expand_call): Turn off ECF_LOOPING_PURE_CONST_CALL and remove old
way of marking pure calls.
(emit_library_call_value_1): Turn off ECF_LOOPING_PURE_CONST_CALL.
Remove hack that was supposed to fix pr7335 and remove old
way of marking pure calls.
* emit-rtl.c (emit_copy_of_insn_after): Copy RTL_CONST_CALL_P,
RTL_PURE_CALL_P, RTL_LOOPING_CONST_OR_PURE_CALL_P.
* cselib.c (cselib_process_insn): Changed CONST_OR_PURE_CALL_P to
RTL_CONST_OR_PURE_CALL_P.
* tree-ssa-pre.c (can_value_number_call): Fixed spacing.
* loop-invariant.c (find_exits, find_invariant_bb): Changed
CONST_OR_PURE_CALL_P to RTL_CONST_OR_PURE_CALL_P.
* sched-deps.c (schedule_analyze): Ditto.
* rtl.h (struct rtx_def): Use call field, unchanging field, and
return_val field of calls to represent pure and const function
info.
(CONST_OR_PURE_CALL_P): Deleted macro.
(RTL_CONST_CALL_P, RTL_PURE_CALL_P,
RTL_LOOPING_CONST_OR_PURE_CALL_P, RTL_CONST_OR_PURE_P): New macros.
* tree-inline.c (copy_body_r): Changed TREE_READONLY_DECL_P to
TREE_READONLY.
* tree-optimize.c (execute_fixup_cfg): Added test for
ECF_LOOPING_CONST_OR_PURE.
* c-common.c (handle_pure_attribute): Changed DECL_IS_PURE to
DECL_PURE_P.
* tree-cfg.c (update_call_expr_flags): Do not clear tree side
effects for looping pure or const calls.
(verify_gimple_expr): Added verification code.
* config/alpha/alpha.c (alpha_legitimize_address,
alpha_emit_xfloating_libcall): Changed CONST_OR_PURE_CALL_P to
RTL_CONST_CALL_P.
* config/s390/s390.c (s390_emit_tls_call_insn): Ditto.
* config/rs6000/rs6000.c (rs6000_legitimize_tls_address): Ditto.
* config/mips/mips.c (mips_call_tls_get_addr): Ditto.
* cfgrtl.c (need_fake_edge_p): Changed CONST_OR_PURE_CALL_P to
RTL_CONST_OR_PURE_CALL_P.
* dce.c (deletable_insn_p): Allow non looping, non sibling, pure
and const calls to be deleted.
2008-05-08 Uros Bizjak <ubizjak@gmail.com>
PR target/35714

View File

@ -6098,7 +6098,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
none of its arguments are volatile, we can avoid expanding the
built-in call and just evaluate the arguments for side-effects. */
if (target == const0_rtx
&& (DECL_IS_PURE (fndecl) || TREE_READONLY (fndecl)))
&& (DECL_PURE_P (fndecl) || TREE_READONLY (fndecl)))
{
bool volatilep = false;
tree arg;

View File

@ -6019,7 +6019,7 @@ handle_pure_attribute (tree *node, tree name, tree ARG_UNUSED (args),
int ARG_UNUSED (flags), bool *no_add_attrs)
{
if (TREE_CODE (*node) == FUNCTION_DECL)
DECL_IS_PURE (*node) = 1;
DECL_PURE_P (*node) = 1;
/* ??? TODO: Support types. */
else
{

View File

@ -1729,10 +1729,10 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype)
DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (newdecl)
|= DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (olddecl);
TREE_THIS_VOLATILE (newdecl) |= TREE_THIS_VOLATILE (olddecl);
TREE_READONLY (newdecl) |= TREE_READONLY (olddecl);
DECL_IS_MALLOC (newdecl) |= DECL_IS_MALLOC (olddecl);
DECL_IS_OPERATOR_NEW (newdecl) |= DECL_IS_OPERATOR_NEW (olddecl);
DECL_IS_PURE (newdecl) |= DECL_IS_PURE (olddecl);
TREE_READONLY (newdecl) |= TREE_READONLY (olddecl);
DECL_PURE_P (newdecl) |= DECL_PURE_P (olddecl);
DECL_IS_NOVOPS (newdecl) |= DECL_IS_NOVOPS (olddecl);
}

View File

@ -359,21 +359,20 @@ emit_call_1 (rtx funexp, tree fntree, tree fndecl ATTRIBUTE_UNUSED,
/* Find the call we just emitted. */
call_insn = last_call_insn ();
/* Mark memory as used for "pure" function call. */
if (ecf_flags & ECF_PURE)
call_fusage
= gen_rtx_EXPR_LIST
(VOIDmode,
gen_rtx_USE (VOIDmode,
gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (VOIDmode))),
call_fusage);
/* Put the register usage information there. */
add_function_usage_to (call_insn, call_fusage);
/* If this is a const call, then set the insn's unchanging bit. */
if (ecf_flags & (ECF_CONST | ECF_PURE))
CONST_OR_PURE_CALL_P (call_insn) = 1;
if (ecf_flags & ECF_CONST)
RTL_CONST_CALL_P (call_insn) = 1;
/* If this is a pure call, then set the insn's unchanging bit. */
if (ecf_flags & ECF_PURE)
RTL_PURE_CALL_P (call_insn) = 1;
/* If this is a const call, then set the insn's unchanging bit. */
if (ecf_flags & ECF_LOOPING_CONST_OR_PURE)
RTL_LOOPING_CONST_OR_PURE_CALL_P (call_insn) = 1;
/* If this call can't throw, attach a REG_EH_REGION reg note to that
effect. */
@ -580,9 +579,13 @@ flags_from_decl_or_type (const_tree exp)
if (DECL_IS_RETURNS_TWICE (exp))
flags |= ECF_RETURNS_TWICE;
/* The function exp may have the `pure' attribute. */
if (DECL_IS_PURE (exp))
/* Process the pure and const attributes. */
if (TREE_READONLY (exp) && ! TREE_THIS_VOLATILE (exp))
flags |= ECF_CONST;
if (DECL_PURE_P (exp))
flags |= ECF_PURE;
if (DECL_LOOPING_CONST_OR_PURE_P (exp))
flags |= ECF_LOOPING_CONST_OR_PURE;
if (DECL_IS_NOVOPS (exp))
flags |= ECF_NOVOPS;
@ -590,9 +593,6 @@ flags_from_decl_or_type (const_tree exp)
if (TREE_NOTHROW (exp))
flags |= ECF_NOTHROW;
if (TREE_READONLY (exp) && ! TREE_THIS_VOLATILE (exp))
flags |= ECF_CONST;
flags = special_function_p (exp, flags);
}
else if (TYPE_P (exp) && TYPE_READONLY (exp) && ! TREE_THIS_VOLATILE (exp))
@ -1038,7 +1038,9 @@ initialize_argument_information (int num_actuals ATTRIBUTE_UNUSED,
args[i].tree_value = build_fold_addr_expr (args[i].tree_value);
type = TREE_TYPE (args[i].tree_value);
*ecf_flags &= ~(ECF_CONST | ECF_LIBCALL_BLOCK);
if (*ecf_flags & ECF_CONST)
*ecf_flags &= ~(ECF_CONST | ECF_LOOPING_CONST_OR_PURE);
*ecf_flags &= ~ECF_LIBCALL_BLOCK;
}
else
{
@ -1073,10 +1075,19 @@ initialize_argument_information (int num_actuals ATTRIBUTE_UNUSED,
store_expr (args[i].tree_value, copy, 0, false);
if (callee_copies)
*ecf_flags &= ~(ECF_CONST | ECF_LIBCALL_BLOCK);
else
*ecf_flags &= ~(ECF_CONST | ECF_PURE | ECF_LIBCALL_BLOCK);
*ecf_flags &= ~(ECF_LIBCALL_BLOCK);
/* Just change the const function to pure and then let
the next test clear the pure based on
callee_copies. */
if (*ecf_flags & ECF_CONST)
{
*ecf_flags &= ~ECF_CONST;
*ecf_flags |= ECF_PURE;
}
if (!callee_copies && *ecf_flags & ECF_PURE)
*ecf_flags &= ~(ECF_PURE | ECF_LOOPING_CONST_OR_PURE);
args[i].tree_value
= build_fold_addr_expr (make_tree (type, copy));
@ -2022,10 +2033,12 @@ expand_call (tree exp, rtx target, int ignore)
if (AGGREGATE_TYPE_P (TREE_TYPE (exp)))
warning (OPT_Waggregate_return, "function call has aggregate value");
/* If the result of a pure or const function call is ignored (or void),
and none of its arguments are volatile, we can avoid expanding the
call and just evaluate the arguments for side-effects. */
/* If the result of a non looping pure or const function call is
ignored (or void), and none of its arguments are volatile, we can
avoid expanding the call and just evaluate the arguments for
side-effects. */
if ((flags & (ECF_CONST | ECF_PURE))
&& (!(flags & ECF_LOOPING_CONST_OR_PURE))
&& (ignore || target == const0_rtx
|| TYPE_MODE (TREE_TYPE (exp)) == VOIDmode))
{
@ -2061,7 +2074,8 @@ expand_call (tree exp, rtx target, int ignore)
if (aggregate_value_p (exp, fndecl))
{
/* This call returns a big structure. */
flags &= ~(ECF_CONST | ECF_PURE | ECF_LIBCALL_BLOCK);
flags &= ~(ECF_CONST | ECF_PURE | ECF_LOOPING_CONST_OR_PURE
| ECF_LIBCALL_BLOCK);
#ifdef PCC_STATIC_STRUCT_RETURN
{
@ -2852,13 +2866,6 @@ expand_call (tree exp, rtx target, int ignore)
note = gen_rtx_EXPR_LIST (VOIDmode,
args[i].initial_value, note);
note = gen_rtx_EXPR_LIST (VOIDmode, funexp, note);
if (flags & ECF_PURE)
note = gen_rtx_EXPR_LIST (VOIDmode,
gen_rtx_USE (VOIDmode,
gen_rtx_MEM (BLKmode,
gen_rtx_SCRATCH (VOIDmode))),
note);
}
emit_libcall_block (insns, temp, valreg, note);
@ -3369,7 +3376,8 @@ emit_library_call_value_1 (int retval, rtx orgfun, rtx value,
mem_value = assign_temp (tfom, 0, 1, 1);
#endif
/* This call returns a big structure. */
flags &= ~(ECF_CONST | ECF_PURE | ECF_LIBCALL_BLOCK);
flags &= ~(ECF_CONST | ECF_PURE | ECF_LOOPING_CONST_OR_PURE
| ECF_LIBCALL_BLOCK);
}
}
else
@ -3472,10 +3480,9 @@ emit_library_call_value_1 (int retval, rtx orgfun, rtx value,
end_sequence ();
emit_insn (insns);
}
flags &= ~(ECF_CONST | ECF_PURE | ECF_LIBCALL_BLOCK);
/* If this was a CONST function, it is now PURE since
it now reads memory. */
/* If this was a CONST function, it is now PURE since it now
reads memory. */
if (flags & ECF_CONST)
{
flags &= ~ECF_CONST;
@ -3901,14 +3908,6 @@ emit_library_call_value_1 (int retval, rtx orgfun, rtx value,
insns = get_insns ();
end_sequence ();
if (flags & ECF_PURE)
note = gen_rtx_EXPR_LIST (VOIDmode,
gen_rtx_USE (VOIDmode,
gen_rtx_MEM (BLKmode,
gen_rtx_SCRATCH (VOIDmode))),
note);
emit_libcall_block (insns, temp, valreg, note);
valreg = temp;

View File

@ -2745,7 +2745,7 @@ need_fake_edge_p (const_rtx insn)
if ((CALL_P (insn)
&& !SIBLING_CALL_P (insn)
&& !find_reg_note (insn, REG_NORETURN, NULL)
&& !CONST_OR_PURE_CALL_P (insn)))
&& !(RTL_CONST_OR_PURE_CALL_P (insn))))
return true;
return ((GET_CODE (PATTERN (insn)) == ASM_OPERANDS

View File

@ -986,7 +986,7 @@ alpha_legitimize_address (rtx x, rtx scratch,
emit_insn (gen_movdi_er_tlsgd (r16, pic_offset_table_rtx, x, seq));
insn = gen_call_value_osf_tlsgd (r0, tga, seq);
insn = emit_call_insn (insn);
CONST_OR_PURE_CALL_P (insn) = 1;
RTL_CONST_CALL_P (insn) = 1;
use_reg (&CALL_INSN_FUNCTION_USAGE (insn), r16);
insn = get_insns ();
@ -1007,7 +1007,7 @@ alpha_legitimize_address (rtx x, rtx scratch,
emit_insn (gen_movdi_er_tlsldm (r16, pic_offset_table_rtx, seq));
insn = gen_call_value_osf_tlsldm (r0, tga, seq);
insn = emit_call_insn (insn);
CONST_OR_PURE_CALL_P (insn) = 1;
RTL_CONST_CALL_P (insn) = 1;
use_reg (&CALL_INSN_FUNCTION_USAGE (insn), r16);
insn = get_insns ();
@ -3013,7 +3013,7 @@ alpha_emit_xfloating_libcall (rtx func, rtx target, rtx operands[],
tmp = emit_call_insn (GEN_CALL_VALUE (reg, tmp, const0_rtx,
const0_rtx, const0_rtx));
CALL_INSN_FUNCTION_USAGE (tmp) = usage;
CONST_OR_PURE_CALL_P (tmp) = 1;
RTL_CONST_CALL_P (tmp) = 1;
tmp = get_insns ();
end_sequence ();

View File

@ -7859,7 +7859,7 @@ legitimize_tls_address (rtx x, enum tls_model model, int for_mov)
insns = get_insns ();
end_sequence ();
CONST_OR_PURE_CALL_P (insns) = 1;
RTL_CONST_CALL_P (insns) = 1;
emit_libcall_block (insns, dest, rax, x);
}
else if (TARGET_64BIT && TARGET_GNU2_TLS)
@ -7890,7 +7890,7 @@ legitimize_tls_address (rtx x, enum tls_model model, int for_mov)
note = gen_rtx_EXPR_LIST (VOIDmode, const0_rtx, NULL);
note = gen_rtx_EXPR_LIST (VOIDmode, ix86_tls_get_addr (), note);
CONST_OR_PURE_CALL_P (insns) = 1;
RTL_CONST_CALL_P (insns) = 1;
emit_libcall_block (insns, base, rax, note);
}
else if (TARGET_64BIT && TARGET_GNU2_TLS)

View File

@ -2371,7 +2371,7 @@ mips_call_tls_get_addr (rtx sym, enum mips_symbol_type type, rtx v0)
emit_insn (gen_rtx_SET (Pmode, a0,
gen_rtx_LO_SUM (Pmode, pic_offset_table_rtx, loc)));
insn = mips_expand_call (v0, mips_tls_symbol, const0_rtx, const0_rtx, false);
CONST_OR_PURE_CALL_P (insn) = 1;
RTL_CONST_CALL_P (insn) = 1;
use_reg (&CALL_INSN_FUNCTION_USAGE (insn), a0);
insn = get_insns ();

View File

@ -3902,7 +3902,7 @@ rs6000_legitimize_tls_address (rtx addr, enum tls_model model)
tga = gen_rtx_MEM (Pmode, rs6000_tls_get_addr ());
insn = gen_call_value (r3, tga, const0_rtx, const0_rtx);
insn = emit_call_insn (insn);
CONST_OR_PURE_CALL_P (insn) = 1;
RTL_CONST_CALL_P (insn) = 1;
use_reg (&CALL_INSN_FUNCTION_USAGE (insn), r3);
insn = get_insns ();
end_sequence ();
@ -3920,7 +3920,7 @@ rs6000_legitimize_tls_address (rtx addr, enum tls_model model)
tga = gen_rtx_MEM (Pmode, rs6000_tls_get_addr ());
insn = gen_call_value (r3, tga, const0_rtx, const0_rtx);
insn = emit_call_insn (insn);
CONST_OR_PURE_CALL_P (insn) = 1;
RTL_CONST_CALL_P (insn) = 1;
use_reg (&CALL_INSN_FUNCTION_USAGE (insn), r3);
insn = get_insns ();
end_sequence ();

View File

@ -3178,7 +3178,7 @@ s390_emit_tls_call_insn (rtx result_reg, rtx tls_call)
gen_rtx_REG (Pmode, RETURN_REGNUM));
use_reg (&CALL_INSN_FUNCTION_USAGE (insn), result_reg);
CONST_OR_PURE_CALL_P (insn) = 1;
RTL_CONST_CALL_P (insn) = 1;
}
/* ADDR contains a thread-local SYMBOL_REF. Generate code to compute

View File

@ -1,3 +1,11 @@
2008-05-07 Kenneth Zadeck <zadeck@naturalbridge.com>
* decl.c (duplicate_decls): Merge in DECL_PURE_P, TREE_READONLY,
DECL_LOOPING_CONST_OR_PURE_P attributes.
* rtti.c (build_dynamic_cast_1): Rename DECL_IS_PURE to
DECL_PURE_P.
2008-05-02 Simon Baldwin <simonb@google.com>
PR bootstrap/36108

View File

@ -1802,11 +1802,13 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
|= DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (olddecl);
DECL_NO_LIMIT_STACK (newdecl) |= DECL_NO_LIMIT_STACK (olddecl);
TREE_THIS_VOLATILE (newdecl) |= TREE_THIS_VOLATILE (olddecl);
TREE_READONLY (newdecl) |= TREE_READONLY (olddecl);
TREE_NOTHROW (newdecl) |= TREE_NOTHROW (olddecl);
DECL_IS_MALLOC (newdecl) |= DECL_IS_MALLOC (olddecl);
DECL_IS_OPERATOR_NEW (newdecl) |= DECL_IS_OPERATOR_NEW (olddecl);
DECL_IS_PURE (newdecl) |= DECL_IS_PURE (olddecl);
DECL_PURE_P (newdecl) |= DECL_PURE_P (olddecl);
TREE_READONLY (newdecl) |= TREE_READONLY (olddecl);
DECL_LOOPING_CONST_OR_PURE_P (newdecl)
|= DECL_LOOPING_CONST_OR_PURE_P (olddecl);
/* Keep the old RTL. */
COPY_DECL_RTL (olddecl, newdecl);
}

View File

@ -707,7 +707,7 @@ build_dynamic_cast_1 (tree type, tree expr, tsubst_flags_t complain)
(NULL_TREE, ptrdiff_type_node, void_list_node))));
tmp = build_function_type (ptr_type_node, tmp);
dcast_fn = build_library_fn_ptr (name, tmp);
DECL_IS_PURE (dcast_fn) = 1;
DECL_PURE_P (dcast_fn) = 1;
pop_abi_namespace ();
dynamic_cast_node = dcast_fn;
}

View File

@ -5249,7 +5249,7 @@ cse_insn (rtx insn, rtx libcall_insn)
if (CALL_P (insn))
{
if (! CONST_OR_PURE_CALL_P (insn))
if (!(RTL_CONST_OR_PURE_CALL_P (insn)))
invalidate_memory ();
invalidate_for_call ();
}

View File

@ -1693,7 +1693,11 @@ cselib_process_insn (rtx insn)
GET_MODE (REG_VALUES (i)->elt->val_rtx))))
cselib_invalidate_regno (i, reg_raw_mode[i]);
if (! CONST_OR_PURE_CALL_P (insn))
/* Since it is not clear how cselib is going to be used, be
conservative here and treat looping pure or const functions
as if they were regular functions. */
if (RTL_LOOPING_CONST_OR_PURE_CALL_P (insn)
|| !(RTL_CONST_OR_PURE_CALL_P (insn)))
cselib_invalidate_mem (callmem);
}

View File

@ -99,6 +99,15 @@ deletable_insn_p (rtx insn, bool fast)
rtx body, x;
int i;
/* We can delete dead const or pure calls as long as they do not
infinite loop and are not sibling calls. The problem with
sibling calls is that it is hard to see the result. */
if (CALL_P (insn)
&& (!SIBLING_CALL_P (insn))
&& (RTL_CONST_OR_PURE_CALL_P (insn)
&& !RTL_LOOPING_CONST_OR_PURE_CALL_P (insn)))
return true;
if (!NONJUMP_INSN_P (insn))
return false;

View File

@ -1967,7 +1967,7 @@ scan_insn (bb_info_t bb_info, rtx insn)
/* Const functions cannot do anything bad i.e. read memory,
however, they can read their parameters which may have
been pushed onto the stack. */
if (CONST_OR_PURE_CALL_P (insn) && !pure_call_p (insn))
if (RTL_CONST_CALL_P (insn))
{
insn_info_t i_ptr = active_local_stores;
insn_info_t last = NULL;

View File

@ -5464,7 +5464,10 @@ emit_copy_of_insn_after (rtx insn, rtx after)
CALL_INSN_FUNCTION_USAGE (new)
= copy_insn (CALL_INSN_FUNCTION_USAGE (insn));
SIBLING_CALL_P (new) = SIBLING_CALL_P (insn);
CONST_OR_PURE_CALL_P (new) = CONST_OR_PURE_CALL_P (insn);
RTL_CONST_CALL_P (new) = RTL_CONST_CALL_P (insn);
RTL_PURE_CALL_P (new) = RTL_PURE_CALL_P (insn);
RTL_LOOPING_CONST_OR_PURE_CALL_P (new)
= RTL_LOOPING_CONST_OR_PURE_CALL_P (insn);
break;
default:

View File

@ -1,3 +1,8 @@
2008-05-07 Kenneth Zadeck <zadeck@naturalbridge.com>
* trans-decl.c (gfc_get_extern_function_decl, build_function_decl):
Rename DECL_IS_PURE to DECL_PURE_P.
2008-05-06 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org>
* arith.c: (gfc_arith_concat, gfc_compare_string,

View File

@ -1197,7 +1197,7 @@ gfc_get_extern_function_decl (gfc_symbol * sym)
if (sym->attr.pure || sym->attr.elemental)
{
if (sym->attr.function && !gfc_return_by_reference (sym))
DECL_IS_PURE (fndecl) = 1;
DECL_PURE_P (fndecl) = 1;
/* TODO: check if pure SUBROUTINEs don't have INTENT(OUT)
parameters and don't use alternate returns (is this
allowed?). In that case, calls to them are meaningless, and
@ -1324,7 +1324,7 @@ build_function_decl (gfc_symbol * sym)
including an alternate return. In that case it can also be
marked as PURE. See also in gfc_get_extern_function_decl(). */
if (attr.function && !gfc_return_by_reference (sym))
DECL_IS_PURE (fndecl) = 1;
DECL_PURE_P (fndecl) = 1;
TREE_SIDE_EFFECTS (fndecl) = 0;
}

View File

@ -2309,7 +2309,7 @@ oprs_not_set_p (const_rtx x, const_rtx insn)
static void
mark_call (rtx insn)
{
if (! CONST_OR_PURE_CALL_P (insn))
if (! RTL_CONST_OR_PURE_CALL_P (insn))
record_last_mem_set_info (insn);
}
@ -5987,7 +5987,7 @@ store_killed_in_insn (const_rtx x, const_rtx x_regs, const_rtx insn, int after)
{
/* A normal or pure call might read from pattern,
but a const call will not. */
if (! CONST_OR_PURE_CALL_P (insn) || pure_call_p (insn))
if (RTL_CONST_CALL_P (insn))
return true;
/* But even a const call reads its parameters. Check whether the

View File

@ -2274,10 +2274,14 @@ gimplify_call_expr (tree *expr_p, tree *pre_p, bool want_value)
/* If the function is "const" or "pure", then clear TREE_SIDE_EFFECTS on its
decl. This allows us to eliminate redundant or useless
calls to "const" functions. */
if (TREE_CODE (*expr_p) == CALL_EXPR
&& (call_expr_flags (*expr_p) & (ECF_CONST | ECF_PURE)))
TREE_SIDE_EFFECTS (*expr_p) = 0;
if (TREE_CODE (*expr_p) == CALL_EXPR)
{
int flags = call_expr_flags (*expr_p);
if (flags & (ECF_CONST | ECF_PURE)
/* An infinite loop is considered a side effect. */
&& !(flags & (ECF_LOOPING_CONST_OR_PURE)))
TREE_SIDE_EFFECTS (*expr_p) = 0;
}
return ret;
}

View File

@ -2168,9 +2168,7 @@ noce_can_store_speculate_p (basic_block top_bb, const_rtx mem)
unconditionally before the barrier. */
if (INSN_P (insn)
&& (volatile_insn_p (PATTERN (insn))
|| (CALL_P (insn)
&& (!CONST_OR_PURE_CALL_P (insn)
|| pure_call_p (insn)))))
|| (CALL_P (insn) && (!RTL_CONST_CALL_P (insn)))))
return false;
if (memory_modified_in_insn_p (mem, insn))

View File

@ -19,7 +19,8 @@ along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
/* This file mark functions as being either const (TREE_READONLY) or
pure (DECL_IS_PURE).
pure (DECL_PURE_P). It can also set the a variant of these that
are allowed to infinite loop (DECL_LOOPING_CONST_PURE_P).
This must be run after inlining decisions have been made since
otherwise, the local sets will not contain information that is
@ -69,6 +70,7 @@ enum pure_const_state_e
struct funct_state_d
{
enum pure_const_state_e pure_const_state;
bool looping;
bool state_set_in_source;
};
@ -95,6 +97,7 @@ check_decl (funct_state local,
if (lookup_attribute ("used", DECL_ATTRIBUTES (t)))
{
local->pure_const_state = IPA_NEITHER;
local->looping = false;
return;
}
@ -103,6 +106,7 @@ check_decl (funct_state local,
if (TREE_THIS_VOLATILE (t))
{
local->pure_const_state = IPA_NEITHER;
local->looping = false;
return;
}
@ -116,6 +120,7 @@ check_decl (funct_state local,
if (checking_write)
{
local->pure_const_state = IPA_NEITHER;
local->looping = false;
return;
}
@ -174,6 +179,7 @@ check_tree (funct_state local, tree t, bool checking_write)
if (TREE_THIS_VOLATILE (t))
{
local->pure_const_state = IPA_NEITHER;
local->looping = false;
return;
}
@ -199,6 +205,7 @@ check_tree (funct_state local, tree t, bool checking_write)
if (checking_write)
{
local->pure_const_state = IPA_NEITHER;
local->looping = false;
return;
}
else if (local->pure_const_state == IPA_CONST)
@ -346,7 +353,10 @@ check_call (funct_state local, tree call_expr)
/* When bad things happen to bad functions, they cannot be const
or pure. */
if (setjmp_call_p (callee_t))
local->pure_const_state = IPA_NEITHER;
{
local->pure_const_state = IPA_NEITHER;
local->looping = false;
}
if (DECL_BUILT_IN_CLASS (callee_t) == BUILT_IN_NORMAL)
switch (DECL_FUNCTION_CODE (callee_t))
@ -354,6 +364,7 @@ check_call (funct_state local, tree call_expr)
case BUILT_IN_LONGJMP:
case BUILT_IN_NONLOCAL_GOTO:
local->pure_const_state = IPA_NEITHER;
local->looping = false;
break;
default:
break;
@ -480,7 +491,10 @@ scan_function (tree *tp,
case LABEL_EXPR:
if (DECL_NONLOCAL (TREE_OPERAND (t, 0)))
/* Target of long jump. */
local->pure_const_state = IPA_NEITHER;
{
local->pure_const_state = IPA_NEITHER;
local->looping = false;
}
break;
case CALL_EXPR:
@ -513,6 +527,10 @@ analyze_function (struct cgraph_node *fn)
l->pure_const_state = IPA_CONST;
l->state_set_in_source = false;
if (DECL_LOOPING_CONST_OR_PURE_P (decl))
l->looping = true;
else
l->looping = false;
/* If this function does not return normally or does not bind local,
do not touch this unless it has been marked as const or pure by the
@ -529,7 +547,7 @@ analyze_function (struct cgraph_node *fn)
l->pure_const_state = IPA_CONST;
l->state_set_in_source = true;
}
if (DECL_IS_PURE (decl))
if (DECL_PURE_P (decl))
{
l->pure_const_state = IPA_PURE;
l->state_set_in_source = true;
@ -644,6 +662,7 @@ static_execute (void)
for (i = 0; i < order_pos; i++ )
{
enum pure_const_state_e pure_const_state = IPA_CONST;
bool looping = false;
int count = 0;
node = order[i];
@ -655,6 +674,9 @@ static_execute (void)
if (pure_const_state < w_l->pure_const_state)
pure_const_state = w_l->pure_const_state;
if (w_l->looping)
looping = true;
if (pure_const_state == IPA_NEITHER)
break;
@ -663,24 +685,8 @@ static_execute (void)
struct cgraph_edge *e;
count++;
/* FIXME!!! Because of pr33826, we cannot have either
immediate or transitive recursive functions marked as
pure or const because dce can delete a function that
is in reality an infinite loop. A better solution
than just outlawing them is to add another bit the
functions to distinguish recursive from non recursive
pure and const function. This would allow the
recursive ones to be cse'd but not dce'd. In this
same vein, we could allow functions with loops to
also be cse'd but not dce'd.
Unfortunately we are late in stage 3, and the fix
described above is is not appropriate. */
if (count > 1)
{
pure_const_state = IPA_NEITHER;
break;
}
looping = true;
for (e = w->callees; e; e = e->next_callee)
{
@ -688,13 +694,8 @@ static_execute (void)
/* Only look at the master nodes and skip external nodes. */
y = cgraph_master_clone (y);
/* Check for immediate recursive functions. See the
FIXME above. */
if (w == y)
{
pure_const_state = IPA_NEITHER;
break;
}
looping = true;
if (y)
{
funct_state y_l = get_function_state (y);
@ -702,6 +703,8 @@ static_execute (void)
pure_const_state = y_l->pure_const_state;
if (pure_const_state == IPA_NEITHER)
break;
if (y_l->looping)
looping = true;
}
}
}
@ -724,15 +727,19 @@ static_execute (void)
{
case IPA_CONST:
TREE_READONLY (w->decl) = 1;
DECL_LOOPING_CONST_OR_PURE_P (w->decl) = looping;
if (dump_file)
fprintf (dump_file, "Function found to be const: %s\n",
fprintf (dump_file, "Function found to be %sconst: %s\n",
looping ? "looping " : "",
lang_hooks.decl_printable_name(w->decl, 2));
break;
case IPA_PURE:
DECL_IS_PURE (w->decl) = 1;
DECL_PURE_P (w->decl) = 1;
DECL_LOOPING_CONST_OR_PURE_P (w->decl) = looping;
if (dump_file)
fprintf (dump_file, "Function found to be pure: %s\n",
fprintf (dump_file, "Function found to be %spure: %s\n",
looping ? "looping " : "",
lang_hooks.decl_printable_name(w->decl, 2));
break;

View File

@ -1,3 +1,8 @@
2008-05-07 Kenneth Zadeck <zadeck@naturalbridge.com>
* decl.c (java_init_decl_processing): Change DECL_IS_PURE to
DECL_PURE_P.
2008-04-23 Paolo Bonzini <bonzini@gnu.org>
* class.c (build_utf8_ref): Don't set TREE_INVARIANT.

View File

@ -906,7 +906,7 @@ java_init_decl_processing (void)
= add_builtin_function ("_Jv_ResolvePoolEntry",
build_function_type (ptr_type_node, t),
0,NOT_BUILT_IN, NULL, NULL_TREE);
DECL_IS_PURE (soft_resolvepoolentry_node) = 1;
DECL_PURE_P (soft_resolvepoolentry_node) = 1;
throw_node = add_builtin_function ("_Jv_Throw",
build_function_type (void_type_node, t),
0, NOT_BUILT_IN, NULL, NULL_TREE);
@ -1000,7 +1000,7 @@ java_init_decl_processing (void)
= add_builtin_function ("_Jv_IsInstanceOf",
build_function_type (boolean_type_node, t),
0, NOT_BUILT_IN, NULL, NULL_TREE);
DECL_IS_PURE (soft_instanceof_node) = 1;
DECL_PURE_P (soft_instanceof_node) = 1;
t = tree_cons (NULL_TREE, object_ptr_type_node,
tree_cons (NULL_TREE, object_ptr_type_node, endlink));
soft_checkarraystore_node
@ -1014,7 +1014,7 @@ java_init_decl_processing (void)
= add_builtin_function ("_Jv_LookupInterfaceMethodIdx",
build_function_type (ptr_type_node, t),
0, NOT_BUILT_IN, NULL, NULL_TREE);
DECL_IS_PURE (soft_lookupinterfacemethod_node) = 1;
DECL_PURE_P (soft_lookupinterfacemethod_node) = 1;
t = tree_cons (NULL_TREE, ptr_type_node,
tree_cons (NULL_TREE, ptr_type_node,
tree_cons (NULL_TREE, ptr_type_node, endlink)));

View File

@ -505,7 +505,7 @@ validate_equiv_mem (rtx start, rtx reg, rtx memref)
return 1;
if (CALL_P (insn) && ! MEM_READONLY_P (memref)
&& ! CONST_OR_PURE_CALL_P (insn))
&& ! RTL_CONST_OR_PURE_CALL_P (insn))
return 0;
note_stores (PATTERN (insn), validate_equiv_mem_from_store, NULL);
@ -781,9 +781,7 @@ memref_used_between_p (rtx memref, rtx start, rtx end)
return 1;
/* Nonconst functions may access memory. */
if (CALL_P (insn)
&& (! CONST_OR_PURE_CALL_P (insn)
|| pure_call_p (insn)))
if (CALL_P (insn) && (! RTL_CONST_CALL_P (insn)))
return 1;
}

View File

@ -563,7 +563,8 @@ find_exits (struct loop *loop, basic_block *body,
FOR_BB_INSNS (body[i], insn)
{
if (CALL_P (insn)
&& !CONST_OR_PURE_CALL_P (insn))
&& (RTL_LOOPING_CONST_OR_PURE_CALL_P (insn)
|| !RTL_CONST_OR_PURE_CALL_P (insn)))
{
has_call = true;
bitmap_set_bit (may_exit, i);
@ -904,7 +905,8 @@ find_invariants_bb (basic_block bb, bool always_reached, bool always_executed)
if (always_reached
&& CALL_P (insn)
&& !CONST_OR_PURE_CALL_P (insn))
&& (RTL_LOOPING_CONST_OR_PURE_CALL_P (insn)
|| ! RTL_CONST_OR_PURE_CALL_P (insn)))
always_reached = false;
}
}

View File

@ -758,7 +758,7 @@ record_opr_changes (rtx insn)
}
}
if (! CONST_OR_PURE_CALL_P (insn))
if (! RTL_CONST_OR_PURE_CALL_P (insn))
record_last_mem_set_info (insn);
}
}

View File

@ -3155,7 +3155,7 @@ delete_prior_computation (rtx note, rtx insn)
/* If we reach a CALL which is not calling a const function
or the callee pops the arguments, then give up. */
if (CALL_P (our_prev)
&& (! CONST_OR_PURE_CALL_P (our_prev)
&& (! RTL_CONST_CALL_P (our_prev)
|| GET_CODE (pat) != SET || GET_CODE (SET_SRC (pat)) != CALL))
break;

View File

@ -253,14 +253,17 @@ struct rtx_def GTY((chain_next ("RTX_NEXT (&%h)"),
In a CODE_LABEL, part of the two-bit alternate entry field. */
unsigned int jump : 1;
/* In a CODE_LABEL, part of the two-bit alternate entry field.
1 in a MEM if it cannot trap. */
1 in a MEM if it cannot trap.
1 in a CALL_INSN logically equivalent to
ECF_LOOPING_CONST_OR_PURE and DECL_LOOPING_CONST_OR_PURE_P. */
unsigned int call : 1;
/* 1 in a REG, MEM, or CONCAT if the value is set at most once, anywhere.
1 in a SUBREG if it references an unsigned object whose mode has been
from a promoted to a wider mode.
1 in a SYMBOL_REF if it addresses something in the per-function
constants pool.
1 in a CALL_INSN, NOTE, or EXPR_LIST for a const or pure call.
1 in a CALL_INSN logically equivalent to ECF_CONST and TREE_READONLY.
1 in a NOTE, or EXPR_LIST for a const call.
1 in a JUMP_INSN, CALL_INSN, or INSN of an annulling branch. */
unsigned int unchanging : 1;
/* 1 in a MEM or ASM_OPERANDS expression if the memory reference is volatile.
@ -303,7 +306,8 @@ struct rtx_def GTY((chain_next ("RTX_NEXT (&%h)"),
unsigned frame_related : 1;
/* 1 in a REG or PARALLEL that is the current function's return value.
1 in a MEM if it refers to a scalar.
1 in a SYMBOL_REF for a weak symbol. */
1 in a SYMBOL_REF for a weak symbol.
1 in a CALL_INSN logically equivalent to ECF_PURE and DECL_PURE_P. */
unsigned return_val : 1;
/* The first element of the operands of this rtx.
@ -765,10 +769,24 @@ extern void rtl_check_failed_flag (const char *, const_rtx, const char *,
(RTL_FLAG_CHECK6("INSN_DELETED_P", (RTX), INSN, CALL_INSN, JUMP_INSN, \
CODE_LABEL, BARRIER, NOTE)->volatil)
/* 1 if RTX is a call to a const function. Built from ECF_CONST and
TREE_READONLY. */
#define RTL_CONST_CALL_P(RTX) \
(RTL_FLAG_CHECK1("RTL_CONST_CALL_P", (RTX), CALL_INSN)->unchanging)
/* 1 if RTX is a call to a pure function. Built from ECF_PURE and
DECL_PURE_P. */
#define RTL_PURE_CALL_P(RTX) \
(RTL_FLAG_CHECK1("RTL_PURE_CALL_P", (RTX), CALL_INSN)->return_val)
/* 1 if RTX is a call to a const or pure function. */
#define CONST_OR_PURE_CALL_P(RTX) \
(RTL_FLAG_CHECK3("CONST_OR_PURE_CALL_P", (RTX), CALL_INSN, NOTE, \
EXPR_LIST)->unchanging)
#define RTL_CONST_OR_PURE_CALL_P(RTX) \
(RTL_CONST_CALL_P(RTX) || RTL_PURE_CALL_P(RTX))
/* 1 if RTX is a call to a looping const or pure function. Built from
ECF_LOOPING_CONST_OR_PURE and DECL_LOOPING_CONST_OR_PURE_P. */
#define RTL_LOOPING_CONST_OR_PURE_CALL_P(RTX) \
(RTL_FLAG_CHECK1("CONST_OR_PURE_CALL_P", (RTX), CALL_INSN)->call)
/* 1 if RTX is a call_insn for a sibling call. */
#define SIBLING_CALL_P(RTX) \
@ -1733,7 +1751,6 @@ extern rtx find_reg_equal_equiv_note (const_rtx);
extern rtx find_constant_src (const_rtx);
extern int find_reg_fusage (const_rtx, enum rtx_code, const_rtx);
extern int find_regno_fusage (const_rtx, enum rtx_code, unsigned int);
extern int pure_call_p (const_rtx);
extern void remove_note (rtx, const_rtx);
extern void remove_reg_equal_equiv_notes (rtx);
extern int side_effects_p (const_rtx);

View File

@ -1846,29 +1846,6 @@ find_regno_fusage (const_rtx insn, enum rtx_code code, unsigned int regno)
return 0;
}
/* Return true if INSN is a call to a pure function. */
int
pure_call_p (const_rtx insn)
{
const_rtx link;
if (!CALL_P (insn) || ! CONST_OR_PURE_CALL_P (insn))
return 0;
/* Look for the note that differentiates const and pure functions. */
for (link = CALL_INSN_FUNCTION_USAGE (insn); link; link = XEXP (link, 1))
{
rtx u, m;
if (GET_CODE (u = XEXP (link, 0)) == USE
&& MEM_P (m = XEXP (u, 0)) && GET_MODE (m) == BLKmode
&& GET_CODE (XEXP (m, 0)) == SCRATCH)
return 1;
}
return 0;
}
/* Remove register note NOTE from the REG_NOTES of INSN. */

View File

@ -2304,7 +2304,8 @@ sched_analyze (struct deps *deps, rtx head, rtx tail)
all pending reads and writes, and start new dependencies starting
from here. But only flush writes for constant calls (which may
be passed a pointer to something we haven't written yet). */
flush_pending_lists (deps, insn, true, !CONST_OR_PURE_CALL_P (insn));
flush_pending_lists (deps, insn, true,
! RTL_CONST_OR_PURE_CALL_P (insn));
/* Remember the last function call for limiting lifetimes. */
free_INSN_LIST_list (&deps->last_function_call);

View File

@ -2430,7 +2430,10 @@ see_copy_insn (rtx insn)
CALL_INSN_FUNCTION_USAGE (ret)
= copy_rtx (CALL_INSN_FUNCTION_USAGE (insn));
SIBLING_CALL_P (ret) = SIBLING_CALL_P (insn);
CONST_OR_PURE_CALL_P (ret) = CONST_OR_PURE_CALL_P (insn);
RTL_CONST_CALL_P (ret) = RTL_CONST_CALL_P (insn);
RTL_PURE_CALL_P (ret) = RTL_PURE_CALL_P (insn);
RTL_LOOPING_CONST_OR_PURE_CALL_P (ret)
= RTL_LOOPING_CONST_OR_PURE_CALL_P (insn);
}
else
gcc_unreachable ();

View File

@ -1792,9 +1792,11 @@ static void
update_call_expr_flags (tree call)
{
tree decl = get_callee_fndecl (call);
int flags;
if (!decl)
return;
if (call_expr_flags (call) & (ECF_CONST | ECF_PURE))
flags = call_expr_flags (call);
if (flags & (ECF_CONST | ECF_PURE) && !(flags & ECF_LOOPING_CONST_OR_PURE))
TREE_SIDE_EFFECTS (call) = 0;
if (TREE_NOTHROW (decl))
TREE_NOTHROW (call) = 1;
@ -3906,7 +3908,19 @@ verify_gimple_expr (tree expr)
case CALL_EXPR:
/* FIXME. The C frontend passes unpromoted arguments in case it
didn't see a function declaration before the call. */
return false;
{
tree decl = CALL_EXPR_FN (expr);
if (TREE_CODE (decl) == FUNCTION_DECL
&& DECL_LOOPING_CONST_OR_PURE_P (decl)
&& (!DECL_PURE_P (decl))
&& (!TREE_READONLY (decl)))
{
error ("invalid pure const state for function");
return true;
}
return false;
}
case OBJ_TYPE_REF:
/* FIXME. */

View File

@ -671,7 +671,7 @@ copy_body_r (tree *tp, int *walk_subtrees, void *data)
{
value = *n;
STRIP_TYPE_NOPS (value);
if (TREE_CONSTANT (value) || TREE_READONLY_DECL_P (value))
if (TREE_CONSTANT (value) || TREE_READONLY (value))
{
*tp = build_empty_stmt ();
return copy_body_r (tp, walk_subtrees, data);

View File

@ -299,7 +299,8 @@ execute_fixup_cfg (void)
tree call = get_call_expr_in (stmt);
tree decl = call ? get_callee_fndecl (call) : NULL;
if (decl && call_expr_flags (call) & (ECF_CONST | ECF_PURE)
if (decl && call_expr_flags (call) & (ECF_CONST | ECF_PURE
| ECF_LOOPING_CONST_OR_PURE)
&& TREE_SIDE_EFFECTS (call))
{
if (gimple_in_ssa_p (cfun))

View File

@ -2077,7 +2077,7 @@ can_value_number_call (tree stmt)
{
tree call = get_call_expr_in (stmt);
if (call_expr_flags (call) & (ECF_PURE | ECF_CONST))
if (call_expr_flags (call) & (ECF_PURE | ECF_CONST))
return true;
return false;
}

View File

@ -7373,7 +7373,9 @@ local_define_builtin (const char *name, tree type, enum built_in_function code,
if (ecf_flags & ECF_CONST)
TREE_READONLY (decl) = 1;
if (ecf_flags & ECF_PURE)
DECL_IS_PURE (decl) = 1;
DECL_PURE_P (decl) = 1;
if (ecf_flags & ECF_LOOPING_CONST_OR_PURE)
DECL_LOOPING_CONST_OR_PURE_P (decl) = 1;
if (ecf_flags & ECF_NORETURN)
TREE_THIS_VOLATILE (decl) = 1;
if (ecf_flags & ECF_NOTHROW)
@ -7766,7 +7768,7 @@ process_call_operands (tree t)
/* Calls have side-effects, except those to const or
pure functions. */
i = call_expr_flags (t);
if (!(i & (ECF_CONST | ECF_PURE)))
if ((i & ECF_LOOPING_CONST_OR_PURE) || !(i & (ECF_CONST | ECF_PURE)))
side_effects = 1;
}
TREE_SIDE_EFFECTS (t) = side_effects;

View File

@ -788,7 +788,7 @@ enum tree_node_structure_enum {
&__t->phi.a[__i]; }))
#define OMP_CLAUSE_ELT_CHECK(T, I) __extension__ \
(*({__typeof (T) const __t = (T); \
(*({__typeof (T) const __t = (T); \
const int __i = (I); \
if (TREE_CODE (__t) != OMP_CLAUSE) \
tree_check_failed (__t, __FILE__, __LINE__, __FUNCTION__, \
@ -1281,13 +1281,11 @@ extern void omp_clause_range_check_failed (const_tree, const char *, int,
#define TREE_THIS_NOTRAP(NODE) ((NODE)->base.nothrow_flag)
/* In a VAR_DECL, PARM_DECL or FIELD_DECL, or any kind of ..._REF node,
nonzero means it may not be the lhs of an assignment. */
nonzero means it may not be the lhs of an assignment.
Nonzero in a FUNCTION_DECL means this function should be treated
as "const" function (can only read its arguments). */
#define TREE_READONLY(NODE) (NON_TYPE_CHECK (NODE)->base.readonly_flag)
/* Nonzero if NODE is a _DECL with TREE_READONLY set. */
#define TREE_READONLY_DECL_P(NODE)\
(DECL_P (NODE) && TREE_READONLY (NODE))
/* Value of expression is constant. Always on in all ..._CST nodes. May
also appear in an expression or decl where the value is constant. */
#define TREE_CONSTANT(NODE) (NON_TYPE_CHECK (NODE)->base.constant_flag)
@ -3256,7 +3254,16 @@ struct tree_decl_non_common GTY(())
/* Nonzero in a FUNCTION_DECL means this function should be treated
as "pure" function (like const function, but may read global memory). */
#define DECL_IS_PURE(NODE) (FUNCTION_DECL_CHECK (NODE)->function_decl.pure_flag)
#define DECL_PURE_P(NODE) (FUNCTION_DECL_CHECK (NODE)->function_decl.pure_flag)
/* Nonzero only if one of TREE_READONLY or DECL_PURE_P is nonzero AND
the const or pure function may not terminate. When this is nonzero
for a const or pure function, it can be dealt with by cse passes
but cannot be removed by dce passes since you are not allowed to
change an infinite looping program into one that terminates without
error. */
#define DECL_LOOPING_CONST_OR_PURE_P(NODE) \
(FUNCTION_DECL_CHECK (NODE)->function_decl.looping_const_or_pure_flag)
/* Nonzero in a FUNCTION_DECL means this function should be treated
as "novops" function (function that does not read global memory,
@ -3354,7 +3361,6 @@ struct tree_function_decl GTY(())
unsigned returns_twice_flag : 1;
unsigned malloc_flag : 1;
unsigned operator_new_flag : 1;
unsigned pure_flag : 1;
unsigned declared_inline_flag : 1;
unsigned regdecl_flag : 1;
@ -3362,8 +3368,11 @@ struct tree_function_decl GTY(())
unsigned no_instrument_function_entry_exit : 1;
unsigned no_limit_stack : 1;
unsigned disregard_inline_limits : 1;
unsigned pure_flag : 1;
unsigned looping_const_or_pure_flag : 1;
/* 4 bits left */
/* 3 bits left */
};
/* For a TYPE_DECL, holds the "original" type. (TREE_TYPE has the copy.) */
@ -4987,28 +4996,34 @@ extern tree build_duplicate_type (tree);
/* Nonzero if this is a call to a function whose return value depends
solely on its arguments, has no side effects, and does not read
global memory. */
#define ECF_CONST 1
/* Nonzero if this call will never return. */
#define ECF_NORETURN 2
/* Nonzero if this is a call to malloc or a related function. */
#define ECF_MALLOC 4
/* Nonzero if it is plausible that this is a call to alloca. */
#define ECF_MAY_BE_ALLOCA 8
/* Nonzero if this is a call to a function that won't throw an exception. */
#define ECF_NOTHROW 16
/* Nonzero if this is a call to setjmp or a related function. */
#define ECF_RETURNS_TWICE 32
/* Nonzero if this call replaces the current stack frame. */
#define ECF_SIBCALL 64
global memory. This corresponds to TREE_READONLY for function
decls. */
#define ECF_CONST (1 << 0)
/* Nonzero if this is a call to "pure" function (like const function,
but may read memory. */
#define ECF_PURE 128
but may read memory. This corresponds to DECL_PURE_P for function
decls. */
#define ECF_PURE (1 << 1)
/* Nonzero if this is ECF_CONST or ECF_PURE but cannot be proven to no
infinite loop. This corresponds to DECL_LOOPING_CONST_OR_PURE_P
for function decls.*/
#define ECF_LOOPING_CONST_OR_PURE (1 << 2)
/* Nonzero if this call will never return. */
#define ECF_NORETURN (1 << 3)
/* Nonzero if this is a call to malloc or a related function. */
#define ECF_MALLOC (1 << 4)
/* Nonzero if it is plausible that this is a call to alloca. */
#define ECF_MAY_BE_ALLOCA (1 << 5)
/* Nonzero if this is a call to a function that won't throw an exception. */
#define ECF_NOTHROW (1 << 6)
/* Nonzero if this is a call to setjmp or a related function. */
#define ECF_RETURNS_TWICE (1 << 7)
/* Nonzero if this call replaces the current stack frame. */
#define ECF_SIBCALL (1 << 8)
/* Create libcall block around the call. */
#define ECF_LIBCALL_BLOCK 256
#define ECF_LIBCALL_BLOCK (1 << 9)
/* Function does not read or write memory (but may have side effects, so
it does not necessarily fit ECF_CONST). */
#define ECF_NOVOPS 512
#define ECF_NOVOPS (1 << 10)
extern int flags_from_decl_or_type (const_tree);
extern int call_expr_flags (const_tree);