stupid.c (stupid_mark_refs): Generate a REG_UNUSED note for a register which is clobbered even if...

* stupid.c (stupid_mark_refs): Generate a REG_UNUSED note
	for a register which is clobbered even if the register
	was used by an earlier instruction.
	* i386.md (fix_truncsfdi2, fix_truncdfdi2,
	fix_truncxfdi2): Don't bother with the gen_reg_RTX.
	(fix_truncsfsi2, fix_truncsfdi2, fix_truncdfsi2,
	fix_truncdfdi2, fix_truncxfsi2, fix_truncxfdi2): Update
	operand constraints and modes.
	* i386.c (output_fix_trunc): Use HImode register to avoid
	memory stalls.  Call output_move_double instead of output_to_reg.
	(output_to_reg): Remove.
	* i386.h: Likewise.
	* i386.md (negsf2, negdf2, negxf2): Set the type
	attribute to fpop.

From-SVN: r26621
This commit is contained in:
John Wehle 1999-04-25 11:43:49 +00:00 committed by John Wehle
parent f41eba1d05
commit 10195bd88e
5 changed files with 186 additions and 251 deletions

View File

@ -1,3 +1,22 @@
Sun Apr 25 14:38:10 EDT 1999 John Wehle (john@feith.com)
* stupid.c (stupid_mark_refs): Generate a REG_UNUSED note
for a register which is clobbered even if the register
was used by an earlier instruction.
* i386.md (fix_truncsfdi2, fix_truncdfdi2,
fix_truncxfdi2): Don't bother with the gen_reg_RTX.
(fix_truncsfsi2, fix_truncsfdi2, fix_truncdfsi2,
fix_truncdfdi2, fix_truncxfsi2, fix_truncxfdi2): Update
operand constraints and modes.
* i386.c (output_fix_trunc): Use HImode register to avoid
memory stalls. Call output_move_double instead of output_to_reg.
(output_to_reg): Remove.
* i386.h: Likewise.
* i386.md (negsf2, negdf2, negxf2): Set the type
attribute to fpop.
Sat Apr 24 23:15:57 1999 Donn Terry (donn@interix.com)
* alpha.md (call_value_nt): Correct subscripts.

View File

@ -871,102 +871,6 @@ function_arg_partial_nregs (cum, mode, type, named)
return 0;
}
/* Output an insn to pop an value from the 387 top-of-stack to 386
register DEST. The 387 register stack is popped if DIES is true. If
the mode of DEST is an integer mode, a `fist' integer store is done,
otherwise a `fst' float store is done. */
void
output_to_reg (dest, dies, scratch_mem)
rtx dest;
int dies;
rtx scratch_mem;
{
rtx xops[4];
int size = GET_MODE_SIZE (GET_MODE (dest));
if (! scratch_mem)
xops[0] = AT_SP (Pmode);
else
xops[0] = scratch_mem;
xops[1] = stack_pointer_rtx;
xops[2] = GEN_INT (size);
xops[3] = dest;
if (! scratch_mem)
output_asm_insn (AS2 (sub%L1,%2,%1), xops);
if (GET_MODE_CLASS (GET_MODE (dest)) == MODE_INT)
{
if (dies)
output_asm_insn (AS1 (fistp%z3,%y0), xops);
else if (GET_MODE (xops[3]) == DImode && ! dies)
{
/* There is no DImode version of this without a stack pop, so
we must emulate it. It doesn't matter much what the second
instruction is, because the value being pushed on the FP stack
is not used except for the following stack popping store.
This case can only happen without optimization, so it doesn't
matter that it is inefficient. */
output_asm_insn (AS1 (fistp%z3,%0), xops);
output_asm_insn (AS1 (fild%z3,%0), xops);
}
else
output_asm_insn (AS1 (fist%z3,%y0), xops);
}
else if (GET_MODE_CLASS (GET_MODE (dest)) == MODE_FLOAT)
{
if (dies)
output_asm_insn (AS1 (fstp%z3,%y0), xops);
else
{
if (GET_MODE (dest) == XFmode)
{
output_asm_insn (AS1 (fstp%z3,%y0), xops);
output_asm_insn (AS1 (fld%z3,%y0), xops);
}
else
output_asm_insn (AS1 (fst%z3,%y0), xops);
}
}
else
abort ();
if (! scratch_mem)
output_asm_insn (AS1 (pop%L0,%0), &dest);
else
output_asm_insn (AS2 (mov%L0,%0,%3), xops);
if (size > UNITS_PER_WORD)
{
dest = gen_rtx_REG (SImode, REGNO (dest) + 1);
if (! scratch_mem)
output_asm_insn (AS1 (pop%L0,%0), &dest);
else
{
xops[0] = adj_offsettable_operand (xops[0], 4);
xops[3] = dest;
output_asm_insn (AS2 (mov%L0,%0,%3), xops);
}
if (size > 2 * UNITS_PER_WORD)
{
dest = gen_rtx_REG (SImode, REGNO (dest) + 1);
if (! scratch_mem)
output_asm_insn (AS1 (pop%L0,%0), &dest);
else
{
xops[0] = adj_offsettable_operand (xops[0], 4);
output_asm_insn (AS2 (mov%L0,%0,%3), xops);
}
}
}
}
char *
singlemove_string (operands)
rtx *operands;
@ -4087,10 +3991,10 @@ output_387_binary_op (insn, operands)
}
/* Output code for INSN to convert a float to a signed int. OPERANDS
are the insn operands. The output may be SFmode or DFmode and the
input operand may be SImode or DImode. As a special case, make sure
that the 387 stack top dies if the output mode is DImode, because the
hardware requires this. */
are the insn operands. The input may be SFmode, DFmode, or XFmode
and the output operand may be SImode or DImode. As a special case,
make sure that the 387 stack top dies if the output mode is DImode,
because the hardware requires this. */
char *
output_fix_trunc (insn, operands)
@ -4103,38 +4007,36 @@ output_fix_trunc (insn, operands)
if (! STACK_TOP_P (operands[1]))
abort ();
xops[0] = GEN_INT (12);
xops[1] = operands[4];
if (GET_MODE (operands[0]) == DImode && ! stack_top_dies)
abort ();
xops[0] = GEN_INT (0x0c00);
xops[1] = operands[5];
output_asm_insn (AS1 (fnstc%W2,%2), operands);
output_asm_insn (AS2 (mov%L2,%2,%4), operands);
output_asm_insn (AS2 (mov%B1,%0,%h1), xops);
output_asm_insn (AS2 (mov%L4,%4,%3), operands);
output_asm_insn (AS2 (mov%W5,%2,%w5), operands);
output_asm_insn (AS2 (or%W1,%0,%w1), xops);
output_asm_insn (AS2 (mov%W3,%w5,%3), operands);
output_asm_insn (AS1 (fldc%W3,%3), operands);
if (NON_STACK_REG_P (operands[0]))
output_to_reg (operands[0], stack_top_dies, operands[3]);
xops[0] = NON_STACK_REG_P (operands[0]) ? operands[4] : operands[0];
else if (GET_CODE (operands[0]) == MEM)
{
if (stack_top_dies)
output_asm_insn (AS1 (fistp%z0,%0), operands);
else if (GET_MODE (operands[0]) == DImode && ! stack_top_dies)
{
/* There is no DImode version of this without a stack pop, so
we must emulate it. It doesn't matter much what the second
instruction is, because the value being pushed on the FP stack
is not used except for the following stack popping store.
This case can only happen without optimization, so it doesn't
matter that it is inefficient. */
output_asm_insn (AS1 (fistp%z0,%0), operands);
output_asm_insn (AS1 (fild%z0,%0), operands);
}
else
output_asm_insn (AS1 (fist%z0,%0), operands);
}
if (stack_top_dies)
output_asm_insn (AS1 (fistp%z0,%y0), xops);
else
abort ();
output_asm_insn (AS1 (fist%z0,%y0), xops);
if (NON_STACK_REG_P (operands[0]))
{
if (GET_MODE (operands[0]) == SImode)
output_asm_insn (AS2 (mov%L0,%4,%0), operands);
else
{
xops[0] = operands[0];
xops[1] = operands[4];
output_asm_insn (output_move_double (xops), xops);
}
}
return AS1 (fldc%W2,%2);
}

View File

@ -2713,7 +2713,6 @@ extern void function_arg_advance ();
extern struct rtx_def *function_arg ();
extern int function_arg_partial_nregs ();
extern char *output_strlen_unroll ();
extern void output_to_reg ();
extern char *singlemove_string ();
extern char *output_move_double ();
extern char *output_move_pushmem ();

View File

@ -2693,164 +2693,172 @@
}"
[(set_attr "type" "fpop")])
;; Signed conversion to DImode.
;; Conversions between floating point and fix point.
(define_expand "fix_truncxfdi2"
[(set (match_dup 2)
(match_operand:XF 1 "register_operand" ""))
(parallel [(set (match_operand:DI 0 "general_operand" "")
(fix:DI (fix:XF (match_dup 2))))
(define_expand "fix_truncsfsi2"
[(parallel [(set (match_operand:SI 0 "nonimmediate_operand" "")
(fix:SI (fix:SF (match_operand:SF 1 "register_operand" ""))))
(clobber (match_dup 2))
(clobber (match_dup 3))
(clobber (match_dup 4))
(clobber (match_scratch:SI 5 ""))])]
(clobber (match_scratch:HI 5 ""))])]
"TARGET_80387"
"
{
operands[1] = copy_to_mode_reg (XFmode, operands[1]);
operands[2] = gen_reg_rtx (XFmode);
operands[3] = (rtx) assign_386_stack_local (SImode, 0);
operands[4] = (rtx) assign_386_stack_local (DImode, 1);
operands[2] = (rtx) assign_386_stack_local (HImode, 0);
operands[3] = (rtx) assign_386_stack_local (HImode, 1);
operands[4] = (rtx) assign_386_stack_local (SImode, 0);
}")
(define_expand "fix_truncdfdi2"
[(set (match_dup 2)
(match_operand:DF 1 "register_operand" ""))
(parallel [(set (match_operand:DI 0 "general_operand" "")
(fix:DI (fix:DF (match_dup 2))))
(clobber (match_dup 2))
(clobber (match_dup 3))
(clobber (match_dup 4))
(clobber (match_scratch:SI 5 ""))])]
(define_insn ""
[(set (match_operand:SI 0 "nonimmediate_operand" "=m,!r")
(fix:SI (fix:SF (match_operand:SF 1 "register_operand" "f,f"))))
(clobber (match_operand:HI 2 "memory_operand" "m,m"))
(clobber (match_operand:HI 3 "memory_operand" "m,m"))
(clobber (match_operand:SI 4 "memory_operand" "m,m"))
(clobber (match_scratch:HI 5 "=&r,&r"))]
"TARGET_80387"
"
{
operands[1] = copy_to_mode_reg (DFmode, operands[1]);
operands[2] = gen_reg_rtx (DFmode);
operands[3] = (rtx) assign_386_stack_local (SImode, 0);
operands[4] = (rtx) assign_386_stack_local (DImode, 1);
}")
"* return output_fix_trunc (insn, operands);"
[(set_attr "type" "fpop")])
(define_expand "fix_truncsfdi2"
[(set (match_dup 2)
(match_operand:SF 1 "register_operand" ""))
(parallel [(set (match_operand:DI 0 "general_operand" "")
(fix:DI (fix:SF (match_dup 2))))
[(parallel [(set (match_operand:DI 0 "nonimmediate_operand" "")
(fix:DI (fix:SF (match_operand:SF 1 "register_operand" ""))))
(clobber (match_dup 1))
(clobber (match_dup 2))
(clobber (match_dup 3))
(clobber (match_dup 4))
(clobber (match_scratch:SI 5 ""))])]
(clobber (match_scratch:HI 5 ""))])]
"TARGET_80387"
"
{
operands[1] = copy_to_mode_reg (SFmode, operands[1]);
operands[2] = gen_reg_rtx (SFmode);
operands[3] = (rtx) assign_386_stack_local (SImode, 0);
operands[4] = (rtx) assign_386_stack_local (DImode, 1);
operands[2] = (rtx) assign_386_stack_local (HImode, 0);
operands[3] = (rtx) assign_386_stack_local (HImode, 1);
operands[4] = (rtx) assign_386_stack_local (DImode, 0);
}")
;; These match a signed conversion of either DFmode or SFmode to DImode.
(define_insn ""
[(set (match_operand:DI 0 "nonimmediate_operand" "=rm")
(fix:DI (fix:XF (match_operand:XF 1 "register_operand" "+f"))))
[(set (match_operand:DI 0 "nonimmediate_operand" "=m,!r")
(fix:DI (fix:SF (match_operand:SF 1 "register_operand" "f,f"))))
(clobber (match_dup 1))
(clobber (match_operand:SI 2 "memory_operand" "m"))
(clobber (match_operand:DI 3 "memory_operand" "m"))
(clobber (match_scratch:SI 4 "=&q"))]
(clobber (match_operand:HI 2 "memory_operand" "m,m"))
(clobber (match_operand:HI 3 "memory_operand" "m,m"))
(clobber (match_operand:DI 4 "memory_operand" "m,o"))
(clobber (match_scratch:HI 5 "=&r,&r"))]
"TARGET_80387"
"* return output_fix_trunc (insn, operands);")
(define_insn ""
[(set (match_operand:DI 0 "nonimmediate_operand" "=rm")
(fix:DI (fix:DF (match_operand:DF 1 "register_operand" "+f"))))
(clobber (match_dup 1))
(clobber (match_operand:SI 2 "memory_operand" "m"))
(clobber (match_operand:DI 3 "memory_operand" "m"))
(clobber (match_scratch:SI 4 "=&q"))]
"TARGET_80387"
"* return output_fix_trunc (insn, operands);")
(define_insn ""
[(set (match_operand:DI 0 "nonimmediate_operand" "=rm")
(fix:DI (fix:SF (match_operand:SF 1 "register_operand" "+f"))))
(clobber (match_dup 1))
(clobber (match_operand:SI 2 "memory_operand" "m"))
(clobber (match_operand:DI 3 "memory_operand" "m"))
(clobber (match_scratch:SI 4 "=&q"))]
"TARGET_80387"
"* return output_fix_trunc (insn, operands);")
;; Signed MODE_FLOAT conversion to SImode.
(define_expand "fix_truncxfsi2"
[(parallel [(set (match_operand:SI 0 "general_operand" "")
(fix:SI
(fix:XF (match_operand:XF 1 "register_operand" ""))))
(clobber (match_dup 2))
(clobber (match_dup 3))
(clobber (match_scratch:SI 4 ""))])]
"TARGET_80387"
"
{
operands[2] = (rtx) assign_386_stack_local (SImode, 0);
operands[3] = (rtx) assign_386_stack_local (DImode, 1);
}")
"* return output_fix_trunc (insn, operands);"
[(set_attr "type" "fpop")])
(define_expand "fix_truncdfsi2"
[(parallel [(set (match_operand:SI 0 "general_operand" "")
(fix:SI
(fix:DF (match_operand:DF 1 "register_operand" ""))))
[(parallel [(set (match_operand:SI 0 "nonimmediate_operand" "")
(fix:SI (fix:DF (match_operand:DF 1 "register_operand" ""))))
(clobber (match_dup 2))
(clobber (match_dup 3))
(clobber (match_scratch:SI 4 ""))])]
(clobber (match_dup 4))
(clobber (match_scratch:HI 5 ""))])]
"TARGET_80387"
"
{
operands[2] = (rtx) assign_386_stack_local (SImode, 0);
operands[3] = (rtx) assign_386_stack_local (DImode, 1);
operands[2] = (rtx) assign_386_stack_local (HImode, 0);
operands[3] = (rtx) assign_386_stack_local (HImode, 1);
operands[4] = (rtx) assign_386_stack_local (SImode, 0);
}")
(define_expand "fix_truncsfsi2"
[(parallel [(set (match_operand:SI 0 "general_operand" "")
(fix:SI
(fix:SF (match_operand:SF 1 "register_operand" ""))))
(define_insn ""
[(set (match_operand:SI 0 "nonimmediate_operand" "=m,!r")
(fix:SI (fix:DF (match_operand:DF 1 "register_operand" "f,f"))))
(clobber (match_operand:HI 2 "memory_operand" "m,m"))
(clobber (match_operand:HI 3 "memory_operand" "m,m"))
(clobber (match_operand:SI 4 "memory_operand" "m,m"))
(clobber (match_scratch:HI 5 "=&r,&r"))]
"TARGET_80387"
"* return output_fix_trunc (insn, operands);"
[(set_attr "type" "fpop")])
(define_expand "fix_truncdfdi2"
[(parallel [(set (match_operand:DI 0 "nonimmediate_operand" "")
(fix:DI (fix:DF (match_operand:DF 1 "register_operand" ""))))
(clobber (match_dup 1))
(clobber (match_dup 2))
(clobber (match_dup 3))
(clobber (match_scratch:SI 4 ""))])]
(clobber (match_dup 4))
(clobber (match_scratch:HI 5 ""))])]
"TARGET_80387"
"
{
operands[2] = (rtx) assign_386_stack_local (SImode, 0);
operands[3] = (rtx) assign_386_stack_local (DImode, 1);
operands[1] = copy_to_mode_reg (DFmode, operands[1]);
operands[2] = (rtx) assign_386_stack_local (HImode, 0);
operands[3] = (rtx) assign_386_stack_local (HImode, 1);
operands[4] = (rtx) assign_386_stack_local (DImode, 0);
}")
(define_insn ""
[(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
(fix:SI (fix:XF (match_operand:XF 1 "register_operand" "f"))))
(clobber (match_operand:SI 2 "memory_operand" "m"))
(clobber (match_operand:DI 3 "memory_operand" "m"))
(clobber (match_scratch:SI 4 "=&q"))]
[(set (match_operand:DI 0 "nonimmediate_operand" "=m,!r")
(fix:DI (fix:DF (match_operand:DF 1 "register_operand" "f,f"))))
(clobber (match_dup 1))
(clobber (match_operand:HI 2 "memory_operand" "m,m"))
(clobber (match_operand:HI 3 "memory_operand" "m,m"))
(clobber (match_operand:DI 4 "memory_operand" "m,o"))
(clobber (match_scratch:HI 5 "=&r,&r"))]
"TARGET_80387"
"* return output_fix_trunc (insn, operands);")
"* return output_fix_trunc (insn, operands);"
[(set_attr "type" "fpop")])
(define_expand "fix_truncxfsi2"
[(parallel [(set (match_operand:SI 0 "nonimmediate_operand" "")
(fix:SI (fix:XF (match_operand:XF 1 "register_operand" ""))))
(clobber (match_dup 2))
(clobber (match_dup 3))
(clobber (match_dup 4))
(clobber (match_scratch:HI 5 ""))])]
"TARGET_80387"
"
{
operands[2] = (rtx) assign_386_stack_local (HImode, 0);
operands[3] = (rtx) assign_386_stack_local (HImode, 1);
operands[4] = (rtx) assign_386_stack_local (SImode, 0);
}")
(define_insn ""
[(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
(fix:SI (fix:DF (match_operand:DF 1 "register_operand" "f"))))
(clobber (match_operand:SI 2 "memory_operand" "m"))
(clobber (match_operand:DI 3 "memory_operand" "m"))
(clobber (match_scratch:SI 4 "=&q"))]
[(set (match_operand:SI 0 "nonimmediate_operand" "=m,!r")
(fix:SI (fix:XF (match_operand:XF 1 "register_operand" "f,f"))))
(clobber (match_operand:HI 2 "memory_operand" "m,m"))
(clobber (match_operand:HI 3 "memory_operand" "m,m"))
(clobber (match_operand:SI 4 "memory_operand" "m,m"))
(clobber (match_scratch:HI 5 "=&r,&r"))]
"TARGET_80387"
"* return output_fix_trunc (insn, operands);")
"* return output_fix_trunc (insn, operands);"
[(set_attr "type" "fpop")])
(define_expand "fix_truncxfdi2"
[(parallel [(set (match_operand:DI 0 "nonimmediate_operand" "")
(fix:DI (fix:XF (match_operand:XF 1 "register_operand" ""))))
(clobber (match_dup 1))
(clobber (match_dup 2))
(clobber (match_dup 3))
(clobber (match_dup 4))
(clobber (match_scratch:HI 5 ""))])]
"TARGET_80387"
"
{
operands[1] = copy_to_mode_reg (XFmode, operands[1]);
operands[2] = (rtx) assign_386_stack_local (HImode, 0);
operands[3] = (rtx) assign_386_stack_local (HImode, 1);
operands[4] = (rtx) assign_386_stack_local (DImode, 0);
}")
(define_insn ""
[(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
(fix:SI (fix:SF (match_operand:SF 1 "register_operand" "f"))))
(clobber (match_operand:SI 2 "memory_operand" "m"))
(clobber (match_operand:DI 3 "memory_operand" "m"))
(clobber (match_scratch:SI 4 "=&q"))]
[(set (match_operand:DI 0 "nonimmediate_operand" "=m,!r")
(fix:DI (fix:XF (match_operand:XF 1 "register_operand" "f,f"))))
(clobber (match_dup 1))
(clobber (match_operand:HI 2 "memory_operand" "m,m"))
(clobber (match_operand:HI 3 "memory_operand" "m,m"))
(clobber (match_operand:DI 4 "memory_operand" "m,o"))
(clobber (match_scratch:HI 5 "=&r,&r"))]
"TARGET_80387"
"* return output_fix_trunc (insn, operands);")
"* return output_fix_trunc (insn, operands);"
[(set_attr "type" "fpop")])
;; Conversion between fixed point and floating point.
@ -4880,31 +4888,36 @@ byte_xor_operation:
[(set (match_operand:SF 0 "register_operand" "=f")
(neg:SF (match_operand:SF 1 "register_operand" "0")))]
"TARGET_80387"
"fchs")
"fchs"
[(set_attr "type" "fpop")])
(define_insn "negdf2"
[(set (match_operand:DF 0 "register_operand" "=f")
(neg:DF (match_operand:DF 1 "register_operand" "0")))]
"TARGET_80387"
"fchs")
"fchs"
[(set_attr "type" "fpop")])
(define_insn ""
[(set (match_operand:DF 0 "register_operand" "=f")
(neg:DF (float_extend:DF (match_operand:SF 1 "register_operand" "0"))))]
"TARGET_80387"
"fchs")
"fchs"
[(set_attr "type" "fpop")])
(define_insn "negxf2"
[(set (match_operand:XF 0 "register_operand" "=f")
(neg:XF (match_operand:XF 1 "register_operand" "0")))]
"TARGET_80387"
"fchs")
"fchs"
[(set_attr "type" "fpop")])
(define_insn ""
[(set (match_operand:XF 0 "register_operand" "=f")
(neg:XF (float_extend:XF (match_operand:DF 1 "register_operand" "0"))))]
"TARGET_80387"
"fchs")
"fchs"
[(set_attr "type" "fpop")])
;; Absolute value instructions

View File

@ -682,16 +682,18 @@ stupid_mark_refs (x, chain)
if (last_setjmp_suid < reg_where_dead[regno])
regs_crosses_setjmp[regno] = 1;
/* If this register is only used in this insn and is only
set, mark it unused. We have to do this even when not
optimizing so that MD patterns which count on this
behavior (e.g., it not causing an output reload on
an insn setting CC) will operate correctly. */
/* If this register is clobbered or it is only used in
this insn and is only set, mark it unused. We have
to do this even when not optimizing so that MD patterns
which count on this behavior (e.g., it not causing an
output reload on an insn setting CC) will operate
correctly. */
if (GET_CODE (SET_DEST (x)) == REG
&& REGNO_FIRST_UID (regno) == INSN_UID (insn)
&& REGNO_LAST_UID (regno) == INSN_UID (insn)
&& (code == CLOBBER || ! reg_mentioned_p (SET_DEST (x),
SET_SRC (x))))
&& (code == CLOBBER
|| (REGNO_FIRST_UID (regno) == INSN_UID (insn)
&& REGNO_LAST_UID (regno) == INSN_UID (insn)
&& ! reg_mentioned_p (SET_DEST (x),
SET_SRC (x)))))
REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_UNUSED,
SET_DEST (x),
REG_NOTES (insn));