fix middle-end/17258
Richard Henderson
rth@redhat.com
Wed Sep 1 22:21:00 GMT 2004
On Wed, Sep 01, 2004 at 03:36:25PM -0400, John David Anglin wrote:
> On hppa2.0w-hp-hpux11.11, the bootstrap fails in stage1:
New patch. The answer to the question "Is this a sufficient test?"
is "No". ;-) Tightens that test, removes dead TARGET_EXPR code,
fixes ecf_flags.
r~
Index: calls.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/calls.c,v
retrieving revision 1.364
diff -c -p -d -r1.364 calls.c
*** calls.c 25 Aug 2004 09:51:21 -0000 1.364
--- calls.c 1 Sep 2004 22:18:04 -0000
*************** initialize_argument_information (int num
*** 970,1023 ****
if (pass_by_reference (args_so_far, TYPE_MODE (type),
type, argpos < n_named_args))
{
! /* If we're compiling a thunk, pass through invisible
! references instead of making a copy. */
! if (call_from_thunk_p
! || (FUNCTION_ARG_CALLEE_COPIES (*args_so_far, TYPE_MODE (type),
! type, argpos < n_named_args)
! /* If it's in a register, we must make a copy of it too. */
! /* ??? Is this a sufficient test? Is there a better one? */
! && !(TREE_CODE (args[i].tree_value) == VAR_DECL
! && REG_P (DECL_RTL (args[i].tree_value)))
! && ! TREE_ADDRESSABLE (type))
! )
! {
! /* C++ uses a TARGET_EXPR to indicate that we want to make a
! new object from the argument. If we are passing by
! invisible reference, the callee will do that for us, so we
! can strip off the TARGET_EXPR. This is not always safe,
! but it is safe in the only case where this is a useful
! optimization; namely, when the argument is a plain object.
! In that case, the frontend is just asking the backend to
! make a bitwise copy of the argument. */
! if (TREE_CODE (args[i].tree_value) == TARGET_EXPR
! && (DECL_P (TREE_OPERAND (args[i].tree_value, 1)))
! && ! REG_P (DECL_RTL (TREE_OPERAND (args[i].tree_value, 1))))
! args[i].tree_value = TREE_OPERAND (args[i].tree_value, 1);
! /* We can't use sibcalls if a callee-copied argument is stored
! in the current function's frame. */
! if (!call_from_thunk_p
! && (!DECL_P (args[i].tree_value)
! || !TREE_STATIC (args[i].tree_value)))
*may_tailcall = false;
! args[i].tree_value = build1 (ADDR_EXPR,
! build_pointer_type (type),
! args[i].tree_value);
! type = build_pointer_type (type);
! }
! else if (TREE_CODE (args[i].tree_value) == TARGET_EXPR)
! {
! /* In the V3 C++ ABI, parameters are destroyed in the caller.
! We implement this by passing the address of the temporary
! rather than expanding it into another allocated slot. */
! args[i].tree_value = build1 (ADDR_EXPR,
! build_pointer_type (type),
! args[i].tree_value);
! type = build_pointer_type (type);
! *may_tailcall = false;
}
else
{
--- 970,999 ----
if (pass_by_reference (args_so_far, TYPE_MODE (type),
type, argpos < n_named_args))
{
! bool callee_copies;
! tree base;
! callee_copies
! = FUNCTION_ARG_CALLEE_COPIES (*args_so_far, TYPE_MODE (type),
! type, argpos < n_named_args);
! /* If we're compiling a thunk, pass through invisible references
! instead of making a copy. */
! if (call_from_thunk_p
! || (callee_copies
! && !TREE_ADDRESSABLE (type)
! && (base = get_base_address (args[i].tree_value))
! && (!DECL_P (base) || MEM_P (DECL_RTL (base)))))
! {
! /* We can't use sibcalls if a callee-copied argument is
! stored in the current function's frame. */
! if (!call_from_thunk_p && DECL_P (base) && !TREE_STATIC (base))
*may_tailcall = false;
! 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);
}
else
{
*************** initialize_argument_information (int num
*** 1051,1062 ****
copy = assign_temp (type, 0, 1, 0);
store_expr (args[i].tree_value, copy, 0);
- *ecf_flags &= ~(ECF_CONST | ECF_PURE | ECF_LIBCALL_BLOCK);
! args[i].tree_value = build1 (ADDR_EXPR,
! build_pointer_type (type),
! make_tree (type, copy));
! type = build_pointer_type (type);
*may_tailcall = false;
}
}
--- 1027,1041 ----
copy = assign_temp (type, 0, 1, 0);
store_expr (args[i].tree_value, copy, 0);
! if (callee_copies)
! *ecf_flags &= ~(ECF_CONST | ECF_LIBCALL_BLOCK);
! else
! *ecf_flags &= ~(ECF_CONST | ECF_PURE | ECF_LIBCALL_BLOCK);
!
! args[i].tree_value
! = build_fold_addr_expr (make_tree (type, copy));
! type = TREE_TYPE (args[i].tree_value);
*may_tailcall = false;
}
}
*************** emit_library_call_value_1 (int retval, r
*** 3379,3403 ****
flags |= ECF_PURE;
}
! if (GET_MODE (val) == MEM && ! must_copy)
slot = val;
! else if (must_copy)
{
slot = assign_temp (lang_hooks.types.type_for_mode (mode, 0),
0, 1, 1);
emit_move_insn (slot, val);
}
- else
- {
- tree type = lang_hooks.types.type_for_mode (mode, 0);
-
- slot
- = gen_rtx_MEM (mode,
- expand_expr (build1 (ADDR_EXPR,
- build_pointer_type (type),
- make_tree (type, val)),
- NULL_RTX, VOIDmode, 0));
- }
call_fusage = gen_rtx_EXPR_LIST (VOIDmode,
gen_rtx_USE (VOIDmode, slot),
--- 3358,3371 ----
flags |= ECF_PURE;
}
! if (GET_MODE (val) == MEM && !must_copy)
slot = val;
! else
{
slot = assign_temp (lang_hooks.types.type_for_mode (mode, 0),
0, 1, 1);
emit_move_insn (slot, val);
}
call_fusage = gen_rtx_EXPR_LIST (VOIDmode,
gen_rtx_USE (VOIDmode, slot),
Index: fold-const.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/fold-const.c,v
retrieving revision 1.447
diff -c -p -d -r1.447 fold-const.c
*** fold-const.c 1 Sep 2004 16:32:39 -0000 1.447
--- fold-const.c 1 Sep 2004 22:18:06 -0000
*************** fold_relational_const (enum tree_code co
*** 10446,10451 ****
--- 10446,10455 ----
tree
build_fold_addr_expr_with_type (tree t, tree ptrtype)
{
+ /* The size of the object is not relevant when talking about its address. */
+ if (TREE_CODE (t) == WITH_SIZE_EXPR)
+ t = TREE_OPERAND (t, 0);
+
if (TREE_CODE (t) == INDIRECT_REF)
{
t = TREE_OPERAND (t, 0);
More information about the Gcc-patches
mailing list