diff options
author | Michael Meissner <meissner@gcc.gnu.org> | 1994-09-20 18:36:51 +0000 |
---|---|---|
committer | Michael Meissner <meissner@gcc.gnu.org> | 1994-09-20 18:36:51 +0000 |
commit | b840bfb0a22793c3794793a6e4817f9fb7b8e03a (patch) | |
tree | 6807dcc71df9d1143e9db694545eb8346bd766b6 /gcc | |
parent | 3221f176136402b4df91492f2234ce203cba6e76 (diff) | |
download | gcc-b840bfb0a22793c3794793a6e4817f9fb7b8e03a.zip gcc-b840bfb0a22793c3794793a6e4817f9fb7b8e03a.tar.gz gcc-b840bfb0a22793c3794793a6e4817f9fb7b8e03a.tar.bz2 |
Respin DI support to be combine friendly; Allow push of SF without temp reg; Fix broken i386 untyped_call
From-SVN: r8098
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/config/i386/i386.c | 195 | ||||
-rw-r--r-- | gcc/config/i386/i386.h | 2 | ||||
-rw-r--r-- | gcc/config/i386/i386.md | 387 | ||||
-rw-r--r-- | gcc/objc/sendmsg.c | 4 |
4 files changed, 243 insertions, 345 deletions
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 0e9d4b3..5a9e882 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -378,6 +378,7 @@ find_addr_reg (addr) abort (); } + /* Output an insn to add the constant N to the register X. */ static void @@ -404,6 +405,7 @@ asm_add (n, x) } } + /* Output assembler code to perform a doubleword move insn with operands OPERANDS. */ @@ -735,6 +737,199 @@ compadr: return ""; } + + +#define MAX_TMPS 2 /* max temporary registers used */ + +/* Output the appropriate code to move push memory on the stack */ + +char * +output_move_pushmem (operands, insn, length, tmp_start, n_operands) + rtx operands[]; + rtx insn; + int length; + int tmp_start; + int n_operands; +{ + + struct { + char *load; + char *push; + rtx xops[2]; + } tmp_info[MAX_TMPS]; + + rtx src = operands[1]; + int max_tmps = 0; + int offset = 0; + int stack_p = reg_overlap_mentioned_p (stack_pointer_rtx, src); + int stack_offset = 0; + int i, num_tmps; + rtx xops[1]; + + if (!offsettable_memref_p (src)) + fatal_insn ("Source is not offsettable", insn); + + if ((length & 3) != 0) + fatal_insn ("Pushing non-word aligned size", insn); + + /* Figure out which temporary registers we have available */ + for (i = tmp_start; i < n_operands; i++) + { + if (GET_CODE (operands[i]) == REG) + { + if (reg_overlap_mentioned_p (operands[i], src)) + continue; + + tmp_info[ max_tmps++ ].xops[1] = operands[i]; + if (max_tmps == MAX_TMPS) + break; + } + } + + if (max_tmps == 0) + for (offset = length - 4; offset >= 0; offset -= 4) + { + xops[0] = adj_offsettable_operand (src, offset + stack_offset); + output_asm_insn (AS1(push%L0,%0), xops); + if (stack_p) + stack_offset += 4; + } + + else + for (offset = length - 4; offset >= 0; ) + { + for (num_tmps = 0; num_tmps < max_tmps && offset >= 0; num_tmps++) + { + tmp_info[num_tmps].load = AS2(mov%L0,%0,%1); + tmp_info[num_tmps].push = AS1(push%L0,%1); + tmp_info[num_tmps].xops[0] = adj_offsettable_operand (src, offset + stack_offset); + offset -= 4; + } + + for (i = 0; i < num_tmps; i++) + output_asm_insn (tmp_info[i].load, tmp_info[i].xops); + + for (i = 0; i < num_tmps; i++) + output_asm_insn (tmp_info[i].push, tmp_info[i].xops); + + if (stack_p) + stack_offset += 4*num_tmps; + } + + return ""; +} + + + +/* Output the appropriate code to move data between two memory locations */ + +char * +output_move_memory (operands, insn, length, tmp_start, n_operands) + rtx operands[]; + rtx insn; + int length; + int tmp_start; + int n_operands; +{ + struct { + char *load; + char *store; + rtx xops[3]; + } tmp_info[MAX_TMPS]; + + rtx dest = operands[0]; + rtx src = operands[1]; + rtx qi_tmp = NULL_RTX; + int max_tmps = 0; + int offset = 0; + int i, num_tmps; + rtx xops[3]; + + if (GET_CODE (dest) == MEM + && GET_CODE (XEXP (dest, 0)) == PRE_INC + && XEXP (XEXP (dest, 0), 0) == stack_pointer_rtx) + return output_move_pushmem (operands, insn, length, tmp_start, n_operands); + + if (!offsettable_memref_p (src)) + fatal_insn ("Source is not offsettable", insn); + + if (!offsettable_memref_p (dest)) + fatal_insn ("Destination is not offsettable", insn); + + /* Figure out which temporary registers we have available */ + for (i = tmp_start; i < n_operands; i++) + { + if (GET_CODE (operands[i]) == REG) + { + if ((length & 1) != 0 && !qi_tmp && QI_REG_P (operands[i])) + qi_tmp = operands[i]; + + if (reg_overlap_mentioned_p (operands[i], dest)) + fatal_insn ("Temporary register overlaps the destination", insn); + + if (reg_overlap_mentioned_p (operands[i], src)) + fatal_insn ("Temporary register overlaps the source", insn); + + tmp_info[ max_tmps++ ].xops[2] = operands[i]; + if (max_tmps == MAX_TMPS) + break; + } + } + + if (max_tmps == 0) + fatal_insn ("No scratch registers were found to do memory->memory moves", insn); + + if ((length & 1) != 0) + { + if (!qi_tmp) + fatal_insn ("No byte register found when moving odd # of bytes.", insn); + } + + while (length > 1) + { + for (num_tmps = 0; num_tmps < max_tmps; num_tmps++) + { + if (length >= 4) + { + tmp_info[num_tmps].load = AS2(mov%L0,%1,%2); + tmp_info[num_tmps].store = AS2(mov%L0,%2,%0); + tmp_info[num_tmps].xops[0] = adj_offsettable_operand (dest, offset); + tmp_info[num_tmps].xops[1] = adj_offsettable_operand (src, offset); + offset += 4; + length -= 4; + } + else if (length >= 2) + { + tmp_info[num_tmps].load = AS2(mov%W0,%1,%2); + tmp_info[num_tmps].store = AS2(mov%W0,%2,%0); + tmp_info[num_tmps].xops[0] = adj_offsettable_operand (dest, offset); + tmp_info[num_tmps].xops[1] = adj_offsettable_operand (src, offset); + offset += 2; + length -= 2; + } + else + break; + } + + for (i = 0; i < num_tmps; i++) + output_asm_insn (tmp_info[i].load, tmp_info[i].xops); + + for (i = 0; i < num_tmps; i++) + output_asm_insn (tmp_info[i].store, tmp_info[i].xops); + } + + if (length == 1) + { + xops[0] = adj_offsettable_operand (dest, offset); + xops[1] = adj_offsettable_operand (src, offset); + xops[2] = qi_tmp; + output_asm_insn (AS2(mov%B0,%1,%2), xops); + output_asm_insn (AS2(mov%B0,%2,%0), xops); + } + + return ""; +} + int standard_80387_constant_p (x) diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h index c68b32d..562f0bd 100644 --- a/gcc/config/i386/i386.h +++ b/gcc/config/i386/i386.h @@ -1704,6 +1704,8 @@ extern void output_op_from_reg (); extern void output_to_reg (); extern char *singlemove_string (); extern char *output_move_double (); +extern char *output_move_memory (); +extern char *output_move_pushmem (); extern int standard_80387_constant_p (); extern char *output_move_const_single (); extern int symbolic_operand (); diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 330002b..0c1c31c 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -808,6 +808,11 @@ /* Fastest way to change a 0 to a 1. */ return AS1 (inc%L0,%0); + if (flag_pic + && GET_CODE (operands[1]) == SYMBOL_REF + && CONSTANT_POOL_ADDRESS_P (operands[1])) + return AS2 (lea%L0,%a1,%0); + return AS2 (mov%L0,%1,%0); }") @@ -1108,9 +1113,9 @@ }") (define_insn "movsf_push" - [(set (match_operand:SF 0 "push_operand" "=<,<,<") - (match_operand:SF 1 "general_operand" "rF,f,m")) - (clobber (match_scratch:SI 2 "=X,X,r"))] + [(set (match_operand:SF 0 "push_operand" "=<,<,<,<") + (match_operand:SF 1 "general_operand" "rF,f,m,m")) + (clobber (match_scratch:SI 2 "=X,X,r,X"))] "" "* { @@ -1134,7 +1139,7 @@ RET; } - else if (GET_CODE (operands[1]) != MEM) + else if (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != REG) return AS1 (push%L1,%1); else @@ -1301,42 +1306,11 @@ RET; } - else if (GET_CODE (operands[1]) != MEM - || GET_CODE (operands[2]) != REG) + else if (GET_CODE (operands[1]) != MEM) return output_move_double (operands); else - { - rtx low[1], high[1], xop[4]; - - split_di (&operands[1], 1, low, high); - xop[0] = operands[2]; - xop[1] = operands[3]; - xop[2] = high[0]; - xop[3] = low[0]; - - if (GET_CODE (operands[3]) == REG) - { /* 2 scratch registers available */ - output_asm_insn (AS2 (mov%L0,%2,%0), xop); - output_asm_insn (AS2 (mov%L0,%3,%1), xop); - output_asm_insn (AS1 (push%L0,%0), xop); - output_asm_insn (AS1 (push%L0,%1), xop); - } - else - { /* 1 scratch register */ - output_asm_insn (AS2 (mov%L0,%2,%0), xop); - output_asm_insn (AS1 (push%L0,%0), xop); - - /* account for push above */ - if (reg_mentioned_p (stack_pointer_rtx, XEXP (xop[3], 0))) - xop[3] = adj_offsettable_operand (xop[3], 4); - - output_asm_insn (AS2 (mov%L0,%3,%0), xop); - output_asm_insn (AS1 (push%L0,%0), xop); - } - - RET; - } + return output_move_pushmem (operands, insn, GET_MODE_SIZE (DFmode), 2, 4); }") (define_insn "movdf_mem" @@ -1345,34 +1319,7 @@ (clobber (match_scratch:SI 2 "=&r,&r")) (clobber (match_scratch:SI 3 "=&r,X"))] "" - "* -{ - rtx low[2], high[2], xop[6]; - - split_di (operands, 2, low, high); - xop[0] = operands[2]; - xop[1] = operands[3]; - xop[2] = high[0]; - xop[3] = high[1]; - xop[4] = low[0]; - xop[5] = low[1]; - if (GET_CODE (operands[3]) == REG) - { /* 2 scratch registers available */ - output_asm_insn (AS2 (mov%L0,%5,%0), xop); - output_asm_insn (AS2 (mov%L0,%3,%1), xop); - output_asm_insn (AS2 (mov%L0,%0,%4), xop); - output_asm_insn (AS2 (mov%L0,%1,%2), xop); - } - else - { /* 1 scratch register */ - output_asm_insn (AS2 (mov%L0,%5,%0), xop); - output_asm_insn (AS2 (mov%L0,%0,%4), xop); - output_asm_insn (AS2 (mov%L0,%3,%0), xop); - output_asm_insn (AS2 (mov%L0,%0,%2), xop); - } - - RET; -}") + "* return output_move_memory (operands, insn, GET_MODE_SIZE (DFmode), 2, 4);") ;; For the purposes of regclass, prefer FLOAT_REGS. (define_insn "movdf_normal" @@ -1520,51 +1467,7 @@ return output_move_double (operands); else - { - rtx xop[5]; - - xop[0] = operands[2]; - xop[1] = operands[3]; - xop[2] = adj_offsettable_operand (operands[1], 8); - xop[3] = adj_offsettable_operand (operands[1], 4); - xop[4] = operands[1]; - - if (GET_CODE (operands[3]) == REG) - { /* 2 scratch registers available */ - output_asm_insn (AS2 (mov%L0,%2,%0), xop); - output_asm_insn (AS2 (mov%L0,%3,%1), xop); - output_asm_insn (AS1 (push%L0,%0), xop); - output_asm_insn (AS1 (push%L0,%1), xop); - - /* account for 2 pushes above */ - if (reg_mentioned_p (stack_pointer_rtx, XEXP (xop[4], 0))) - xop[4] = adj_offsettable_operand (xop[4], 8); - - output_asm_insn (AS2 (mov%L0,%4,%0), xop); - output_asm_insn (AS1 (push%L0,%0), xop); - } - else - { /* 1 scratch register */ - output_asm_insn (AS2 (mov%L0,%2,%0), xop); - output_asm_insn (AS1 (push%L0,%0), xop); - - /* account for 1 push above */ - if (reg_mentioned_p (stack_pointer_rtx, XEXP (xop[3], 0))) - xop[3] = adj_offsettable_operand (xop[3], 4); - - output_asm_insn (AS2 (mov%L0,%3,%0), xop); - output_asm_insn (AS1 (push%L0,%0), xop); - - /* account for 2 pushes above */ - if (reg_mentioned_p (stack_pointer_rtx, XEXP (xop[4], 0))) - xop[4] = adj_offsettable_operand (xop[4], 8); - - output_asm_insn (AS2 (mov%L0,%4,%0), xop); - output_asm_insn (AS1 (push%L0,%0), xop); - } - - RET; - } + return output_move_pushmem (operands, insn, GET_MODE_SIZE (XFmode), 2, 4); }") (define_insn "movxf_mem" @@ -1573,40 +1476,7 @@ (clobber (match_scratch:SI 2 "=&r,&r")) (clobber (match_scratch:SI 3 "=&r,X"))] "" - "* -{ - rtx xop[8]; - - xop[0] = operands[2]; - xop[1] = operands[3]; - xop[2] = adj_offsettable_operand (operands[1], 8); - xop[3] = adj_offsettable_operand (operands[1], 4); - xop[4] = operands[1]; - xop[5] = adj_offsettable_operand (operands[0], 8); - xop[6] = adj_offsettable_operand (operands[0], 4); - xop[7] = operands[0]; - - if (GET_CODE (operands[3]) == REG) - { /* 2 scratch registers available */ - output_asm_insn (AS2 (mov%L0,%2,%0), xop); - output_asm_insn (AS2 (mov%L0,%3,%1), xop); - output_asm_insn (AS2 (mov%L5,%0,%5), xop); - output_asm_insn (AS2 (mov%L6,%1,%6), xop); - output_asm_insn (AS2 (mov%L0,%4,%0), xop); - output_asm_insn (AS2 (mov%L7,%0,%7), xop); - } - else - { /* 1 scratch register */ - output_asm_insn (AS2 (mov%L0,%2,%0), xop); - output_asm_insn (AS2 (mov%L0,%0,%5), xop); - output_asm_insn (AS2 (mov%L0,%3,%0), xop); - output_asm_insn (AS2 (mov%L0,%0,%6), xop); - output_asm_insn (AS2 (mov%L0,%4,%0), xop); - output_asm_insn (AS2 (mov%L7,%0,%7), xop); - } - - RET; -}") + "* return output_move_memory (operands, insn, GET_MODE_SIZE (XFmode), 2, 4);") (define_insn "movxf_normal" [(set (match_operand:XF 0 "general_operand" "=f,fm,!*rf,!*rm") @@ -1678,34 +1548,7 @@ return AS1 (fxch,%0); }") -(define_expand "movdi" - [(set (match_operand:DI 0 "general_operand" "") - (match_operand:DI 1 "general_operand" ""))] - "" - " -{ - /* Special case memory->memory moves and pushes */ - if (TARGET_MOVE - && (reload_in_progress | reload_completed) == 0 - && GET_CODE (operands[0]) == MEM - && (GET_CODE (operands[1]) == MEM || push_operand (operands[0], DImode))) - { - rtx (*genfunc) PROTO((rtx, rtx)) = (push_operand (operands[0], DImode)) - ? gen_movdi_push - : gen_movdi_mem; - - emit_insn ((*genfunc) (operands[0], operands[1])); - DONE; - } -}") - -(define_insn "movdi_push_nomove" - [(set (match_operand:DI 0 "push_operand" "=<") - (match_operand:DI 1 "general_operand" "roiF"))] - "!TARGET_MOVE" - "* return output_move_double (operands);") - -(define_insn "movdi_push" +(define_insn "" [(set (match_operand:DI 0 "push_operand" "=<,<,<,<") (match_operand:DI 1 "general_operand" "riF,o,o,o")) (clobber (match_scratch:SI 2 "=X,&r,&r,X")) @@ -1713,85 +1556,29 @@ "" "* { - if (GET_CODE (operands[1]) != MEM - || GET_CODE (operands[2]) != REG) + if (GET_CODE (operands[1]) != MEM) return output_move_double (operands); else - { - rtx low[1], high[1], xop[4]; - - split_di (&operands[1], 1, low, high); - xop[0] = operands[2]; - xop[1] = operands[3]; - xop[2] = high[0]; - xop[3] = low[0]; - - if (GET_CODE (operands[3]) == REG) - { /* 2 scratch registers available */ - output_asm_insn (AS2 (mov%L0,%2,%0), xop); - output_asm_insn (AS2 (mov%L0,%3,%1), xop); - output_asm_insn (AS1 (push%L0,%0), xop); - output_asm_insn (AS1 (push%L0,%1), xop); - } - else - { /* 1 scratch register */ - output_asm_insn (AS2 (mov%L0,%2,%0), xop); - output_asm_insn (AS1 (push%L0,%0), xop); - - /* account for push above */ - if (reg_mentioned_p (stack_pointer_rtx, XEXP (xop[3], 0))) - xop[3] = adj_offsettable_operand (xop[3], 4); - - output_asm_insn (AS2 (mov%L0,%3,%0), xop); - output_asm_insn (AS1 (push%L0,%0), xop); - } - - RET; - } + return output_move_pushmem (operands, insn, GET_MODE_SIZE (DImode), 2, 4); }") -(define_insn "movdi_mem" - [(set (match_operand:DI 0 "memory_operand" "=o,o") - (match_operand:DI 1 "memory_operand" "o,o")) - (clobber (match_scratch:SI 2 "=&r,&r")) - (clobber (match_scratch:SI 3 "=&r,X"))] +(define_insn "movdi" + [(set (match_operand:DI 0 "general_operand" "=o,o,r,rm") + (match_operand:DI 1 "general_operand" "o,o,m,riF")) + (clobber (match_scratch:SI 2 "=&r,&r,X,X")) + (clobber (match_scratch:SI 3 "=&r,X,X,X"))] "" "* { rtx low[2], high[2], xop[6]; - split_di (operands, 2, low, high); - xop[0] = operands[2]; - xop[1] = operands[3]; - xop[2] = high[0]; - xop[3] = high[1]; - xop[4] = low[0]; - xop[5] = low[1]; - if (GET_CODE (operands[3]) == REG) - { /* 2 scratch registers available */ - output_asm_insn (AS2 (mov%L0,%5,%0), xop); - output_asm_insn (AS2 (mov%L0,%3,%1), xop); - output_asm_insn (AS2 (mov%L0,%0,%4), xop); - output_asm_insn (AS2 (mov%L0,%1,%2), xop); - } + if (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM) + return output_move_double (operands); else - { /* 1 scratch register */ - output_asm_insn (AS2 (mov%L0,%5,%0), xop); - output_asm_insn (AS2 (mov%L0,%0,%4), xop); - output_asm_insn (AS2 (mov%L0,%3,%0), xop); - output_asm_insn (AS2 (mov%L0,%0,%2), xop); - } - - RET; + return output_move_memory (operands, insn, GET_MODE_SIZE (DImode), 2, 4); }") -(define_insn "movdi_normal" - [(set (match_operand:DI 0 "general_operand" "=r,rm") - (match_operand:DI 1 "general_operand" "m,riF"))] - "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM) || (GET_CODE (operands[1]) != MEM)" - "* return output_move_double (operands);") - ;;- conversion instructions ;;- NONE @@ -5296,126 +5083,42 @@ "!HALF_PIC_P ()" "call %P1") +;; Call subroutine returning any type. + (define_expand "untyped_call" - [(parallel [(call (match_operand:QI 0 "indirect_operand" "") + [(parallel [(call (match_operand 0 "" "") (const_int 0)) - (match_operand:BLK 1 "memory_operand" "") + (match_operand 1 "" "") (match_operand 2 "" "")])] "" " { - rtx addr; + int i; - if (flag_pic) - current_function_uses_pic_offset_table = 1; - - /* With half-pic, force the address into a register. */ - addr = XEXP (operands[0], 0); - if (GET_CODE (addr) != REG && HALF_PIC_P () && !CONSTANT_ADDRESS_P (addr)) - XEXP (operands[0], 0) = force_reg (Pmode, addr); - - operands[1] = change_address (operands[1], DImode, XEXP (operands[1], 0)); - if (! expander_call_insn_operand (operands[1], QImode)) - operands[1] - = change_address (operands[1], VOIDmode, - copy_to_mode_reg (Pmode, XEXP (operands[1], 0))); -}") + emit_call_insn (gen_call (operands[0], const0_rtx, NULL, const0_rtx)); -(define_insn "" - [(call (match_operand:QI 0 "call_insn_operand" "m") - (const_int 0)) - (match_operand:DI 1 "memory_operand" "o") - (match_operand 2 "" "")] - "" - "* -{ - rtx addr = operands[1]; - - if (GET_CODE (operands[0]) == MEM - && ! CONSTANT_ADDRESS_P (XEXP (operands[0], 0))) + for (i = 0; i < XVECLEN (operands[2], 0); i++) { - operands[0] = XEXP (operands[0], 0); - output_asm_insn (AS1 (call,%*%0), operands); + rtx set = XVECEXP (operands[2], 0, i); + emit_move_insn (SET_DEST (set), SET_SRC (set)); } - else - output_asm_insn (AS1 (call,%P0), operands); - - operands[2] = gen_rtx (REG, SImode, 0); - output_asm_insn (AS2 (mov%L2,%2,%1), operands); - - operands[2] = gen_rtx (REG, SImode, 1); - operands[1] = adj_offsettable_operand (addr, 4); - output_asm_insn (AS2 (mov%L2,%2,%1), operands); - - operands[1] = adj_offsettable_operand (addr, 8); - return AS1 (fnsave,%1); -}") - -(define_insn "" - [(call (mem:QI (match_operand:SI 0 "symbolic_operand" "")) - (const_int 0)) - (match_operand:DI 1 "memory_operand" "o") - (match_operand 2 "" "")] - "!HALF_PIC_P ()" - "* -{ - rtx addr = operands[1]; - - output_asm_insn (AS1 (call,%P0), operands); - - operands[2] = gen_rtx (REG, SImode, 0); - output_asm_insn (AS2 (mov%L2,%2,%1), operands); - - operands[2] = gen_rtx (REG, SImode, 1); - operands[1] = adj_offsettable_operand (addr, 4); - output_asm_insn (AS2 (mov%L2,%2,%1), operands); - - operands[1] = adj_offsettable_operand (addr, 8); - return AS1 (fnsave,%1); -}") - -;; We use fnsave and frstor to save and restore the floating point result. -;; These are expensive instructions and require a large space to save the -;; FPU state. An more complicated alternative is to use fnstenv to store -;; the FPU environment and test whether the stack top is valid. Store the -;; result of the test, and if it is valid, pop and save the value. The -;; untyped_return would check the test and optionally push the saved value. - -(define_expand "untyped_return" - [(match_operand:BLK 0 "memory_operand" "") - (match_operand 1 "" "")] - "" - " -{ - rtx valreg1 = gen_rtx (REG, SImode, 0); - rtx valreg2 = gen_rtx (REG, SImode, 1); - rtx result = operands[0]; - - /* Restore the FPU state. */ - emit_insn (gen_update_return (change_address (result, SImode, - plus_constant (XEXP (result, 0), - 8)))); - /* Reload the function value registers. */ - emit_move_insn (valreg1, change_address (result, SImode, XEXP (result, 0))); - emit_move_insn (valreg2, - change_address (result, SImode, - plus_constant (XEXP (result, 0), 4))); - - /* Put USE insns before the return. */ - emit_insn (gen_rtx (USE, VOIDmode, valreg1)); - emit_insn (gen_rtx (USE, VOIDmode, valreg2)); - - /* Construct the return. */ - expand_null_return (); + /* The optimizer does not know that the call sets the function value + registers we stored in the result block. We avoid problems by + claiming that all hard registers are used and clobbered at this + point. */ + emit_insn (gen_blockage ()); DONE; }") -(define_insn "update_return" - [(unspec:SI [(match_operand:SI 0 "memory_operand" "m")] 0)] +;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and +;; all of memory. This blocks insns from being moved across this point. + +(define_insn "blockage" + [(unspec_volatile [(const_int 0)] 0)] "" - "frstor %0") + "") ;; Insn emitted into the body of a function to return from a function. ;; This is only done if the function's epilogue is known to be simple. diff --git a/gcc/objc/sendmsg.c b/gcc/objc/sendmsg.c index 3e4f504..8185485 100644 --- a/gcc/objc/sendmsg.c +++ b/gcc/objc/sendmsg.c @@ -68,9 +68,7 @@ nil_method(id receiver, SEL op, ...) } /* Given a class and selector, return the selector's implementation. */ -#ifndef i386 -__inline__ /* this is broken on i386... */ -#endif +__inline__ IMP get_imp (Class* class, SEL sel) { |