Commit a3ee5899 by Jim Wilson

*** empty log message ***

From-SVN: r742
parent f24ec84c
...@@ -1613,7 +1613,8 @@ yylex () ...@@ -1613,7 +1613,8 @@ yylex ()
else if (TREE_UNSIGNED (traditional_type) else if (TREE_UNSIGNED (traditional_type)
!= TREE_UNSIGNED (ansi_type)) != TREE_UNSIGNED (ansi_type))
warning ("integer constant is unsigned in ANSI C, signed with -traditional"); warning ("integer constant is unsigned in ANSI C, signed with -traditional");
else abort (); else
warning ("width of integer constant may change on other systems with -traditional");
} }
#endif #endif
......
...@@ -1048,63 +1048,53 @@ output_move_double (operands) ...@@ -1048,63 +1048,53 @@ output_move_double (operands)
|| (optype0 != REGOP && optype0 != CNSTOP && optype1 == REGOP || (optype0 != REGOP && optype0 != CNSTOP && optype1 == REGOP
&& (REGNO (operands[1]) & 1) == 0)) && (REGNO (operands[1]) & 1) == 0))
{ {
rtx op1, op2; rtx addr;
rtx base = 0, offset = const0_rtx; rtx base, offset;
/* OP1 gets the register pair, and OP2 gets the memory address. */
if (optype0 == REGOP) if (optype0 == REGOP)
op1 = operands[0], op2 = operands[1]; addr = operands[1];
else else
op1 = operands[1], op2 = operands[0]; addr = operands[0];
/* Now see if we can trust the address to be 8-byte aligned. */ /* Now see if we can trust the address to be 8-byte aligned.
/* Trust double-precision floats in global variables. */ Trust double-precision floats in global variables. */
if (GET_CODE (XEXP (op2, 0)) == LO_SUM && GET_MODE (op2) == DFmode) if (GET_CODE (XEXP (addr, 0)) == LO_SUM && GET_MODE (addr) == DFmode)
{ return (addr == operands[1] ? "ldd %1,%0" : "std %1,%0");
if (final_sequence)
abort ();
return (op1 == operands[0] ? "ldd %1,%0" : "std %1,%0");
}
if (GET_CODE (XEXP (op2, 0)) == PLUS) base = 0;
if (GET_CODE (XEXP (addr, 0)) == PLUS)
{ {
rtx temp = XEXP (op2, 0); rtx temp = XEXP (addr, 0);
if (GET_CODE (XEXP (temp, 0)) == REG) if (GET_CODE (XEXP (temp, 0)) == REG
&& GET_CODE (XEXP (temp, 1)) == CONST_INT)
base = XEXP (temp, 0), offset = XEXP (temp, 1); base = XEXP (temp, 0), offset = XEXP (temp, 1);
else if (GET_CODE (XEXP (temp, 1)) == REG)
base = XEXP (temp, 1), offset = XEXP (temp, 0);
} }
else if (GET_CODE (XEXP (addr, 0)) == REG)
base = XEXP (addr, 0), offset = const0_rtx;
/* Trust round enough offsets from the stack or frame pointer. */ /* Trust round enough offsets from the stack or frame pointer.
If TARGET_HOPE_ALIGN, trust round enough offset from any register
for DFmode loads. If it is obviously unaligned, don't ever
generate ldd or std. */
if (base if (base
&& (REGNO (base) == FRAME_POINTER_REGNUM && (REGNO (base) == FRAME_POINTER_REGNUM
|| REGNO (base) == STACK_POINTER_REGNUM)) || REGNO (base) == STACK_POINTER_REGNUM
|| (TARGET_HOPE_ALIGN && GET_MODE (addr) == DFmode)))
{ {
if (GET_CODE (offset) == CONST_INT if ((INTVAL (offset) & 0x7) == 0)
&& (INTVAL (offset) & 0x7) == 0) return (addr == operands[1] ? "ldd %1,%0" : "std %1,%0");
{
if (op1 == operands[0])
return "ldd %1,%0";
else
return "std %1,%0";
}
} }
/* We know structs not on the stack are properly aligned. Since a /* We know structs not on the stack are properly aligned. Since a
double asks for 8-byte alignment, we know it must have got that double asks for 8-byte alignment, we know it must have got that
if it is in a struct. But a DImode need not be 8-byte aligned, if it is in a struct. But a DImode need not be 8-byte aligned,
because it could be a struct containing two ints or pointers. */ because it could be a struct containing two ints or pointers.
else if (GET_CODE (operands[1]) == MEM Hence, a constant DFmode address will always be 8-byte aligned.
&& GET_MODE (operands[1]) == DFmode If TARGET_HOPE_ALIGN, then assume all doubles are aligned even if this
&& (CONSTANT_P (XEXP (operands[1], 0)) is not a constant address. */
/* Let user ask for it anyway. */ else if (GET_CODE (addr) == MEM && GET_MODE (addr) == DFmode
|| TARGET_HOPE_ALIGN)) && (CONSTANT_P (addr) || TARGET_HOPE_ALIGN))
return "ldd %1,%0"; return (addr == operands[1] ? "ldd %1,%0" : "std %1,%0");
else if (GET_CODE (operands[0]) == MEM
&& GET_MODE (operands[0]) == DFmode
&& (CONSTANT_P (XEXP (operands[0], 0))
|| TARGET_HOPE_ALIGN))
return "std %1,%0";
} }
if (optype0 == REGOP && optype1 == REGOP if (optype0 == REGOP && optype1 == REGOP
...@@ -1159,6 +1149,9 @@ output_move_double (operands) ...@@ -1159,6 +1149,9 @@ output_move_double (operands)
return ""; return "";
} }
/* Output assembler code to perform a doubleword move insn with perands
OPERANDS, one of which must be a floating point register. */
char * char *
output_fp_move_double (operands) output_fp_move_double (operands)
rtx *operands; rtx *operands;
...@@ -1169,35 +1162,15 @@ output_fp_move_double (operands) ...@@ -1169,35 +1162,15 @@ output_fp_move_double (operands)
{ {
if (FP_REG_P (operands[1])) if (FP_REG_P (operands[1]))
return "fmovs %1,%0\n\tfmovs %R1,%R0"; return "fmovs %1,%0\n\tfmovs %R1,%R0";
if (GET_CODE (operands[1]) == REG) else if (GET_CODE (operands[1]) == REG)
{ {
if ((REGNO (operands[1]) & 1) == 0) if ((REGNO (operands[1]) & 1) == 0)
return "std %1,[%@-8]\n\tldd [%@-8],%0"; return "std %1,[%@-8]\n\tldd [%@-8],%0";
else else
return "st %R1,[%@-4]\n\tst %1,[%@-8]\n\tldd [%@-8],%0"; return "st %R1,[%@-4]\n\tst %1,[%@-8]\n\tldd [%@-8],%0";
} }
addr = XEXP (operands[1], 0); else
return output_move_double (operands);
/* Use ldd if known to be aligned. */
if (TARGET_HOPE_ALIGN
|| (GET_CODE (addr) == PLUS
&& (((XEXP (addr, 0) == frame_pointer_rtx
|| XEXP (addr, 0) == stack_pointer_rtx)
&& GET_CODE (XEXP (addr, 1)) == CONST_INT
&& (INTVAL (XEXP (addr, 1)) & 0x7) == 0)
/* Arrays are known to be aligned,
and reg+reg addresses are used (on this machine)
only for array accesses. */
|| (REG_P (XEXP (addr, 0)) && REG_P (XEXP (addr, 1)))))
|| (GET_MODE (operands[0]) == DFmode
&& (GET_CODE (addr) == LO_SUM || CONSTANT_P (addr))))
return "ldd %1,%0";
/* Otherwise use two ld insns. */
operands[2]
= gen_rtx (MEM, GET_MODE (operands[1]),
plus_constant_for_output (addr, 4));
return "ld %1,%0\n\tld %2,%R0";
} }
else if (FP_REG_P (operands[1])) else if (FP_REG_P (operands[1]))
{ {
...@@ -1208,28 +1181,8 @@ output_fp_move_double (operands) ...@@ -1208,28 +1181,8 @@ output_fp_move_double (operands)
else else
return "std %1,[%@-8]\n\tld [%@-4],%R0\n\tld [%@-8],%0"; return "std %1,[%@-8]\n\tld [%@-4],%R0\n\tld [%@-8],%0";
} }
addr = XEXP (operands[0], 0); else
return output_move_double (operands);
/* Use std if we can be sure it is well-aligned. */
if (TARGET_HOPE_ALIGN
|| (GET_CODE (addr) == PLUS
&& (((XEXP (addr, 0) == frame_pointer_rtx
|| XEXP (addr, 0) == stack_pointer_rtx)
&& GET_CODE (XEXP (addr, 1)) == CONST_INT
&& (INTVAL (XEXP (addr, 1)) & 0x7) == 0)
/* Arrays are known to be aligned,
and reg+reg addresses are used (on this machine)
only for array accesses. */
|| (REG_P (XEXP (addr, 0)) && REG_P (XEXP (addr, 1)))))
|| (GET_MODE (operands[1]) == DFmode
&& (GET_CODE (addr) == LO_SUM || CONSTANT_P (addr))))
return "std %1,%0";
/* Otherwise use two st insns. */
operands[2]
= gen_rtx (MEM, GET_MODE (operands[0]),
plus_constant_for_output (addr, 4));
return "st %r1,%0\n\tst %R1,%2";
} }
else abort (); else abort ();
} }
......
...@@ -1402,6 +1402,92 @@ ...@@ -1402,6 +1402,92 @@
}" }"
[(set_attr "type" "fp") [(set_attr "type" "fp")
(set_attr "length" "3")]) (set_attr "length" "3")])
;; Allow combiner to combine a fix_truncdfsi2 with a floatsidf2
;; This eliminates 2 useless instructions.
;; The first one matches if the fixed result is needed. The second one
;; matches if the fixed result is not needed.
(define_insn ""
[(set (match_operand:DF 0 "general_operand" "=f")
(float:DF (fix:SI (fix:DF (match_operand:DF 1 "general_operand" "fm")))))
(set (match_operand:SI 2 "general_operand" "=rm")
(fix:SI (fix:DF (match_dup 1))))]
""
"*
{
if (FP_REG_P (operands[1]))
output_asm_insn (\"fdtoi %1,%0\", operands);
else
{
output_asm_insn (output_fp_move_double (operands), operands);
output_asm_insn (\"fdtoi %0,%0\", operands);
}
if (GET_CODE (operands[2]) == MEM)
return \"st %0,%2\;fitod %0,%0\";
else
return \"st %0,[%%fp-4]\;fitod %0,%0\;ld [%%fp-4],%2\";
}"
[(set_attr "type" "fp")
(set_attr "length" "5")])
(define_insn ""
[(set (match_operand:DF 0 "general_operand" "=f")
(float:DF (fix:SI (fix:DF (match_operand:DF 1 "general_operand" "fm")))))]
""
"*
{
if (FP_REG_P (operands[1]))
output_asm_insn (\"fdtoi %1,%0\", operands);
else
{
output_asm_insn (output_fp_move_double (operands), operands);
output_asm_insn (\"fdtoi %0,%0\", operands);
}
return \"fitod %0,%0\";
}"
[(set_attr "type" "fp")
(set_attr "length" "3")])
;; Allow combiner to combine a fix_truncsfsi2 with a floatsisf2
;; This eliminates 2 useless instructions.
;; The first one matches if the fixed result is needed. The second one
;; matches if the fixed result is not needed.
(define_insn ""
[(set (match_operand:SF 0 "general_operand" "=f")
(float:SF (fix:SI (fix:SF (match_operand:SF 1 "general_operand" "fm")))))
(set (match_operand:SI 2 "general_operand" "=rm")
(fix:SI (fix:SF (match_dup 1))))]
""
"*
{
if (FP_REG_P (operands[1]))
output_asm_insn (\"fstoi %1,%0\", operands);
else
output_asm_insn (\"ld %1,%0\;fstoi %0,%0\", operands);
if (GET_CODE (operands[2]) == MEM)
return \"st %0,%2\;fitos %0,%0\";
else
return \"st %0,[%%fp-4]\;fitos %0,%0\;ld [%%fp-4],%2\";
}"
[(set_attr "type" "fp")
(set_attr "length" "5")])
(define_insn ""
[(set (match_operand:SF 0 "general_operand" "=f")
(float:SF (fix:SI (fix:SF (match_operand:SF 1 "general_operand" "fm")))))]
""
"*
{
if (FP_REG_P (operands[1]))
output_asm_insn (\"fstoi %1,%0\", operands);
else
output_asm_insn (\"ld %1,%0\;fstoi %0,%0\", operands);
return \"fitos %0,%0\";
}"
[(set_attr "type" "fp")
(set_attr "length" "3")])
;;- arithmetic instructions ;;- arithmetic instructions
......
...@@ -383,21 +383,39 @@ add_dependence (insn, elem, dep_type) ...@@ -383,21 +383,39 @@ add_dependence (insn, elem, dep_type)
rtx elem; rtx elem;
enum reg_note dep_type; enum reg_note dep_type;
{ {
rtx link; rtx link, next;
/* Don't depend an insn on itself. */ /* Don't depend an insn on itself. */
if (insn == elem) if (insn == elem)
return; return;
/* If elem is part of a sequence that must be scheduled together, then /* If elem is part of a sequence that must be scheduled together, then
make the dependence point to the last insn of the sequence. */ make the dependence point to the last insn of the sequence.
if (NEXT_INSN (elem) && SCHED_GROUP_P (NEXT_INSN (elem))) When HAVE_cc0, it is possible for NOTEs to exist between users and
setters of the condition codes, so we must skip past notes here.
Otherwise, NOTEs are impossible here. */
next = NEXT_INSN (elem);
#ifdef HAVE_cc0
while (next && GET_CODE (next) == NOTE)
next = NEXT_INSN (next);
#endif
if (next && SCHED_GROUP_P (next))
{ {
while (NEXT_INSN (elem) && SCHED_GROUP_P (NEXT_INSN (elem))) /* Notes will never intervene here though, so don't bother checking
elem = NEXT_INSN (elem); for them. */
/* Again, don't depend an insn of itself. */ while (next && SCHED_GROUP_P (next))
if (insn == elem) next = NEXT_INSN (next);
/* Again, don't depend an insn on itself. */
if (insn == next)
return; return;
/* Make the dependence to NEXT, the last insn of the group, instead
of the original ELEM. */
elem = next;
} }
/* Check that we don't already have this dependence. */ /* Check that we don't already have this dependence. */
......
...@@ -1214,18 +1214,24 @@ sched_analyze_2 (x, insn) ...@@ -1214,18 +1214,24 @@ sched_analyze_2 (x, insn)
#ifdef HAVE_cc0 #ifdef HAVE_cc0
case CC0: case CC0:
{ {
rtx link; rtx link, prev;
/* User of CC0 depends on immediately preceding insn. /* There may be a note before this insn now, but all notes will
There may be a note before this insn now, but all notes will
be removed before we actually try to schedule the insns, so be removed before we actually try to schedule the insns, so
it doesn't matter. */ it won't cause a problem later. We must avoid it here though. */
/* User of CC0 depends on immediately preceding insn.
SCHED_GROUP_P (insn) = 1; SCHED_GROUP_P (insn) = 1;
/* Make a copy of all dependencies on PREV_INSN, and add to this insn. /* Make a copy of all dependencies on the immediately previous insn,
This is so that all the dependencies will apply to the group. */ and add to this insn. This is so that all the dependencies will
apply to the group. */
prev = PREV_INSN (insn);
while (GET_CODE (prev) == NOTE)
prev = PREV_INSN (prev);
for (link = LOG_LINKS (PREV_INSN (insn)); link; link = XEXP (link, 1)) for (link = LOG_LINKS (prev); link; link = XEXP (link, 1))
add_dependence (insn, XEXP (link, 0), GET_MODE (link)); add_dependence (insn, XEXP (link, 0), GET_MODE (link));
return; return;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment