re PR target/19162 (ICE while building libobjc's sendmsg.c)

* PR target/19162
	* arm.c (arm_apply_result_size): New function.
	* arm.h (APPLY_RESULT_SIZE): Define.
	* arm-protos.h (arm_apply_result_size): Add prototype.
	* arm.md (RO_REGNUM, FPA_F0_REGNUM, FPA_F7_REGNUM): New constants.
	(movxf): New expand.
	(ldmsi_postinc4_thumb, stmsi_postinc4_thumb): New patterns for Thumb.
	(call_value_symbol): Remove predicate for operand 0.
	(call_value_insn, sibcall_value, sibcall_value_insn): Likewise.
	(untyped_call): Rework to correclty return values for any type.
	(untyped_return): New expand.
	* fpa.md (movxf_fpa): Simplify and use sfm/lfm when appropriate.

From-SVN: r95119
This commit is contained in:
Richard Earnshaw 2005-02-16 21:57:10 +00:00 committed by Richard Earnshaw
parent f0b81cbc9f
commit 9f7bf991d0
6 changed files with 209 additions and 30 deletions

View File

@ -1,3 +1,18 @@
2005-02-16 Richard Earnshaw <rearnsha@arm.com>
* PR target/19162
* arm.c (arm_apply_result_size): New function.
* arm.h (APPLY_RESULT_SIZE): Define.
* arm-protos.h (arm_apply_result_size): Add prototype.
* arm.md (RO_REGNUM, FPA_F0_REGNUM, FPA_F7_REGNUM): New constants.
(movxf): New expand.
(ldmsi_postinc4_thumb, stmsi_postinc4_thumb): New patterns for Thumb.
(call_value_symbol): Remove predicate for operand 0.
(call_value_insn, sibcall_value, sibcall_value_insn): Likewise.
(untyped_call): Rework to correclty return values for any type.
(untyped_return): New expand.
* fpa.md (movxf_fpa): Simplify and use sfm/lfm when appropriate.
2005-02-16 Stan Shebs <shebs@apple.com>
* config.gcc (powerpc-*-darwin*): Use fragment for Darwin 8 or later.

View File

@ -123,6 +123,7 @@ extern void arm_init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx, tree);
extern bool arm_needs_doubleword_align (enum machine_mode, tree);
extern rtx arm_function_value(tree, tree);
#endif
extern int arm_apply_result_size (void);
#if defined AOF_ASSEMBLER
extern rtx aof_pic_entry (rtx);

View File

@ -2283,7 +2283,8 @@ arm_canonicalize_comparison (enum rtx_code code, rtx * op1)
/* Define how to find the value returned by a function. */
rtx arm_function_value(tree type, tree func ATTRIBUTE_UNUSED)
rtx
arm_function_value(tree type, tree func ATTRIBUTE_UNUSED)
{
enum machine_mode mode;
int unsignedp ATTRIBUTE_UNUSED;
@ -2297,6 +2298,28 @@ rtx arm_function_value(tree type, tree func ATTRIBUTE_UNUSED)
return LIBCALL_VALUE(mode);
}
/* Determine the amount of memory needed to store the possible return
registers of an untyped call. */
int
arm_apply_result_size (void)
{
int size = 16;
if (TARGET_ARM)
{
if (TARGET_HARD_FLOAT_ABI)
{
if (TARGET_FPA)
size += 12;
if (TARGET_MAVERICK)
size += 8;
}
if (TARGET_IWMMXT_ABI)
size += 8;
}
return size;
}
/* Decide whether a type should be returned in memory (true)
or in a register (false). This is called by the macro

View File

@ -1617,6 +1617,10 @@ enum reg_class
|| (TARGET_ARM && ((REGNO) == FIRST_FPA_REGNUM) \
&& TARGET_HARD_FLOAT_ABI && TARGET_FPA))
/* Amount of memory needed for an untyped call to save all possible return
registers. */
#define APPLY_RESULT_SIZE arm_apply_result_size()
/* How large values are returned */
/* A C expression which can inhibit the returning of certain function values
in registers, based on the type of value. */

View File

@ -30,12 +30,15 @@
;; Register numbers
(define_constants
[(IP_REGNUM 12) ; Scratch register
[(R0_REGNUM 0) ; First CORE register
(IP_REGNUM 12) ; Scratch register
(SP_REGNUM 13) ; Stack pointer
(LR_REGNUM 14) ; Return address register
(PC_REGNUM 15) ; Program counter
(CC_REGNUM 24) ; Condition code pseudo register
(LAST_ARM_REGNUM 15)
(LAST_ARM_REGNUM 15) ;
(FPA_F0_REGNUM 16) ; FIRST_FPA_REGNUM
(FPA_F7_REGNUM 23) ; LAST_FPA_REGNUM
]
)
;; 3rd operand to select_dominance_cc_mode
@ -5216,6 +5219,16 @@
(set_attr "pool_range" "*,*,*,1020,*,*")]
)
(define_expand "movxf"
[(set (match_operand:XF 0 "general_operand" "")
(match_operand:XF 1 "general_operand" ""))]
"TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
"
if (GET_CODE (operands[0]) == MEM)
operands[1] = force_reg (XFmode, operands[1]);
"
)
;; Vector Moves
(define_expand "movv2si"
[(set (match_operand:V2SI 0 "nonimmediate_operand" "")
@ -5288,6 +5301,24 @@
(set_attr "predicable" "yes")]
)
(define_insn "*ldmsi_postinc4_thumb"
[(match_parallel 0 "load_multiple_operation"
[(set (match_operand:SI 1 "s_register_operand" "=l")
(plus:SI (match_operand:SI 2 "s_register_operand" "1")
(const_int 16)))
(set (match_operand:SI 3 "arm_hard_register_operand" "")
(mem:SI (match_dup 2)))
(set (match_operand:SI 4 "arm_hard_register_operand" "")
(mem:SI (plus:SI (match_dup 2) (const_int 4))))
(set (match_operand:SI 5 "arm_hard_register_operand" "")
(mem:SI (plus:SI (match_dup 2) (const_int 8))))
(set (match_operand:SI 6 "arm_hard_register_operand" "")
(mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
"TARGET_THUMB && XVECLEN (operands[0], 0) == 5"
"ldmia\\t%1!, {%3, %4, %5, %6}"
[(set_attr "type" "load4")]
)
(define_insn "*ldmsi_postinc3"
[(match_parallel 0 "load_multiple_operation"
[(set (match_operand:SI 1 "s_register_operand" "=r")
@ -5409,6 +5440,24 @@
(set_attr "type" "store4")]
)
(define_insn "*stmsi_postinc4_thumb"
[(match_parallel 0 "store_multiple_operation"
[(set (match_operand:SI 1 "s_register_operand" "=l")
(plus:SI (match_operand:SI 2 "s_register_operand" "1")
(const_int 16)))
(set (mem:SI (match_dup 2))
(match_operand:SI 3 "arm_hard_register_operand" ""))
(set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
(match_operand:SI 4 "arm_hard_register_operand" ""))
(set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
(match_operand:SI 5 "arm_hard_register_operand" ""))
(set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
(match_operand:SI 6 "arm_hard_register_operand" ""))])]
"TARGET_THUMB && XVECLEN (operands[0], 0) == 5"
"stmia\\t%1!, {%3, %4, %5, %6}"
[(set_attr "type" "store4")]
)
(define_insn "*stmsi_postinc3"
[(match_parallel 0 "store_multiple_operation"
[(set (match_operand:SI 1 "s_register_operand" "=r")
@ -7560,7 +7609,7 @@
)
(define_insn "*call_value_symbol"
[(set (match_operand 0 "s_register_operand" "")
[(set (match_operand 0 "" "")
(call (mem:SI (match_operand:SI 1 "" ""))
(match_operand:SI 2 "" "")))
(use (match_operand 3 "" ""))
@ -7589,7 +7638,7 @@
)
(define_insn "*call_value_insn"
[(set (match_operand 0 "register_operand" "")
[(set (match_operand 0 "" "")
(call (mem:SI (match_operand 1 "" ""))
(match_operand 2 "" "")))
(use (match_operand 3 "" ""))
@ -7617,7 +7666,7 @@
)
(define_expand "sibcall_value"
[(parallel [(set (match_operand 0 "register_operand" "")
[(parallel [(set (match_operand 0 "" "")
(call (match_operand 1 "memory_operand" "")
(match_operand 2 "general_operand" "")))
(return)
@ -7643,7 +7692,7 @@
)
(define_insn "*sibcall_value_insn"
[(set (match_operand 0 "s_register_operand" "")
[(set (match_operand 0 "" "")
(call (mem:SI (match_operand:SI 1 "" "X"))
(match_operand 2 "" "")))
(return)
@ -7749,18 +7798,59 @@
(const_int 0))
(match_operand 1 "" "")
(match_operand 2 "" "")])]
"TARGET_ARM"
"TARGET_EITHER"
"
{
int i;
rtx par = gen_rtx_PARALLEL (VOIDmode,
rtvec_alloc (XVECLEN (operands[2], 0)));
rtx addr = gen_reg_rtx (Pmode);
rtx mem;
int size = 0;
emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx));
emit_move_insn (addr, XEXP (operands[1], 0));
mem = change_address (operands[1], BLKmode, addr);
for (i = 0; i < XVECLEN (operands[2], 0); i++)
{
rtx set = XVECEXP (operands[2], 0, i);
rtx src = SET_SRC (XVECEXP (operands[2], 0, i));
emit_move_insn (SET_DEST (set), SET_SRC (set));
/* Default code only uses r0 as a return value, but we could
be using anything up to 4 registers. */
if (REGNO (src) == R0_REGNUM)
src = gen_rtx_REG (TImode, R0_REGNUM);
XVECEXP (par, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, src,
GEN_INT (size));
size += GET_MODE_SIZE (GET_MODE (src));
}
emit_call_insn (GEN_CALL_VALUE (par, operands[0], const0_rtx, NULL,
const0_rtx));
size = 0;
for (i = 0; i < XVECLEN (par, 0); i++)
{
HOST_WIDE_INT offset = 0;
rtx reg = XEXP (XVECEXP (par, 0, i), 0);
if (size != 0)
emit_move_insn (addr, plus_constant (addr, size));
mem = change_address (mem, GET_MODE (reg), NULL);
if (REGNO (reg) == R0_REGNUM)
{
/* On thumb we have to use a write-back instruction. */
emit_insn (arm_gen_store_multiple (R0_REGNUM, 4, addr, TRUE,
TARGET_THUMB ? TRUE : FALSE, mem, &offset));
size = TARGET_ARM ? 16 : 0;
}
else
{
emit_move_insn (mem, reg);
size = GET_MODE_SIZE (GET_MODE (reg));
}
}
/* The optimizer does not know that the call sets the function value
@ -7773,6 +7863,55 @@
}"
)
(define_expand "untyped_return"
[(match_operand:BLK 0 "memory_operand" "")
(match_operand 1 "" "")]
"TARGET_EITHER"
"
{
int i;
rtx addr = gen_reg_rtx (Pmode);
rtx mem;
int size = 0;
emit_move_insn (addr, XEXP (operands[0], 0));
mem = change_address (operands[0], BLKmode, addr);
for (i = 0; i < XVECLEN (operands[1], 0); i++)
{
HOST_WIDE_INT offset = 0;
rtx reg = SET_DEST (XVECEXP (operands[1], 0, i));
if (size != 0)
emit_move_insn (addr, plus_constant (addr, size));
mem = change_address (mem, GET_MODE (reg), NULL);
if (REGNO (reg) == R0_REGNUM)
{
/* On thumb we have to use a write-back instruction. */
emit_insn (arm_gen_load_multiple (R0_REGNUM, 4, addr, TRUE,
TARGET_THUMB ? TRUE : FALSE, mem, &offset));
size = TARGET_ARM ? 16 : 0;
}
else
{
emit_move_insn (reg, mem);
size = GET_MODE_SIZE (GET_MODE (reg));
}
}
/* Emit USE insns before the return. */
for (i = 0; i < XVECLEN (operands[1], 0); i++)
emit_insn (gen_rtx_USE (VOIDmode,
SET_DEST (XVECEXP (operands[1], 0, i))));
/* Construct the return. */
expand_naked_return ();
DONE;
}"
)
;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
;; all of memory. This blocks insns from being moved across this point.

View File

@ -581,33 +581,31 @@
(set_attr "neg_pool_range" "*,*,*,*,1008,*,*,1008,*,*,*")]
)
;; Saving and restoring the floating point registers in the prologue should
;; be done in XFmode, even though we don't support that for anything else
;; (Well, strictly it's 'internal representation', but that's effectively
;; XFmode).
;; We treat XFmode as meaning 'internal format'. It's the right size and we
;; don't use it for anything else. We only support moving between FPA
;; registers and moving an FPA register to/from memory.
(define_insn "*movxf_fpa"
[(set (match_operand:XF 0 "nonimmediate_operand" "=f,f,f,m,f,r,r")
(match_operand:XF 1 "general_operand" "fG,H,m,f,r,f,r"))]
"TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA && reload_completed"
[(set (match_operand:XF 0 "nonimmediate_operand" "=f,f,m")
(match_operand:XF 1 "general_operand" "f,m,f"))]
"TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA
&& (register_operand (operands[0], XFmode)
|| register_operand (operands[1], XFmode))"
"*
switch (which_alternative)
{
default:
case 0: return \"mvf%?e\\t%0, %1\";
case 1: return \"mnf%?e\\t%0, #%N1\";
case 2: return \"ldf%?e\\t%0, %1\";
case 3: return \"stf%?e\\t%1, %0\";
case 4: return output_mov_long_double_fpa_from_arm (operands);
case 5: return output_mov_long_double_arm_from_fpa (operands);
case 6: return output_mov_long_double_arm_from_arm (operands);
case 1: if (arm_fpu_arch == FPUTYPE_FPA_EMU2)
return \"ldf%?e\\t%0, %1\";
return \"lfm%?\\t%0, 1, %1\";
case 2: if (arm_fpu_arch == FPUTYPE_FPA_EMU2)
return \"stf%?e\\t%1, %0\";
return \"sfm%?\\t%1, 1, %0\";
}
"
[(set_attr "length" "4,4,4,4,8,8,12")
[(set_attr "length" "4,4,4")
(set_attr "predicable" "yes")
(set_attr "type" "ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r,*")
(set_attr "pool_range" "*,*,1024,*,*,*,*")
(set_attr "neg_pool_range" "*,*,1004,*,*,*,*")]
(set_attr "type" "ffarith,f_load,f_store")]
)
(define_insn "*cmpsf_fpa"
@ -749,4 +747,3 @@
(set_attr "type" "ffarith")
(set_attr "conds" "use")]
)