parent
f24ec84c7b
commit
a3ee589982
|
@ -1613,7 +1613,8 @@ yylex ()
|
|||
else if (TREE_UNSIGNED (traditional_type)
|
||||
!= TREE_UNSIGNED (ansi_type))
|
||||
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
|
||||
|
||||
|
|
|
@ -1048,63 +1048,53 @@ output_move_double (operands)
|
|||
|| (optype0 != REGOP && optype0 != CNSTOP && optype1 == REGOP
|
||||
&& (REGNO (operands[1]) & 1) == 0))
|
||||
{
|
||||
rtx op1, op2;
|
||||
rtx base = 0, offset = const0_rtx;
|
||||
rtx addr;
|
||||
rtx base, offset;
|
||||
|
||||
/* OP1 gets the register pair, and OP2 gets the memory address. */
|
||||
if (optype0 == REGOP)
|
||||
op1 = operands[0], op2 = operands[1];
|
||||
addr = operands[1];
|
||||
else
|
||||
op1 = operands[1], op2 = operands[0];
|
||||
addr = operands[0];
|
||||
|
||||
/* Now see if we can trust the address to be 8-byte aligned. */
|
||||
/* Trust double-precision floats in global variables. */
|
||||
/* Now see if we can trust the address to be 8-byte aligned.
|
||||
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");
|
||||
|
||||
base = 0;
|
||||
if (GET_CODE (XEXP (addr, 0)) == PLUS)
|
||||
{
|
||||
if (final_sequence)
|
||||
abort ();
|
||||
return (op1 == operands[0] ? "ldd %1,%0" : "std %1,%0");
|
||||
}
|
||||
|
||||
if (GET_CODE (XEXP (op2, 0)) == PLUS)
|
||||
{
|
||||
rtx temp = XEXP (op2, 0);
|
||||
if (GET_CODE (XEXP (temp, 0)) == REG)
|
||||
rtx temp = XEXP (addr, 0);
|
||||
if (GET_CODE (XEXP (temp, 0)) == REG
|
||||
&& GET_CODE (XEXP (temp, 1)) == CONST_INT)
|
||||
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
|
||||
&& (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
|
||||
&& (INTVAL (offset) & 0x7) == 0)
|
||||
{
|
||||
if (op1 == operands[0])
|
||||
return "ldd %1,%0";
|
||||
else
|
||||
return "std %1,%0";
|
||||
}
|
||||
if ((INTVAL (offset) & 0x7) == 0)
|
||||
return (addr == operands[1] ? "ldd %1,%0" : "std %1,%0");
|
||||
}
|
||||
/* 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
|
||||
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. */
|
||||
else if (GET_CODE (operands[1]) == MEM
|
||||
&& GET_MODE (operands[1]) == DFmode
|
||||
&& (CONSTANT_P (XEXP (operands[1], 0))
|
||||
/* Let user ask for it anyway. */
|
||||
|| TARGET_HOPE_ALIGN))
|
||||
return "ldd %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";
|
||||
because it could be a struct containing two ints or pointers.
|
||||
Hence, a constant DFmode address will always be 8-byte aligned.
|
||||
If TARGET_HOPE_ALIGN, then assume all doubles are aligned even if this
|
||||
is not a constant address. */
|
||||
else if (GET_CODE (addr) == MEM && GET_MODE (addr) == DFmode
|
||||
&& (CONSTANT_P (addr) || TARGET_HOPE_ALIGN))
|
||||
return (addr == operands[1] ? "ldd %1,%0" : "std %1,%0");
|
||||
}
|
||||
|
||||
if (optype0 == REGOP && optype1 == REGOP
|
||||
|
@ -1159,6 +1149,9 @@ output_move_double (operands)
|
|||
return "";
|
||||
}
|
||||
|
||||
/* Output assembler code to perform a doubleword move insn with perands
|
||||
OPERANDS, one of which must be a floating point register. */
|
||||
|
||||
char *
|
||||
output_fp_move_double (operands)
|
||||
rtx *operands;
|
||||
|
@ -1169,35 +1162,15 @@ output_fp_move_double (operands)
|
|||
{
|
||||
if (FP_REG_P (operands[1]))
|
||||
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)
|
||||
return "std %1,[%@-8]\n\tldd [%@-8],%0";
|
||||
else
|
||||
return "st %R1,[%@-4]\n\tst %1,[%@-8]\n\tldd [%@-8],%0";
|
||||
}
|
||||
addr = XEXP (operands[1], 0);
|
||||
|
||||
/* 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
|
||||
return output_move_double (operands);
|
||||
}
|
||||
else if (FP_REG_P (operands[1]))
|
||||
{
|
||||
|
@ -1208,28 +1181,8 @@ output_fp_move_double (operands)
|
|||
else
|
||||
return "std %1,[%@-8]\n\tld [%@-4],%R0\n\tld [%@-8],%0";
|
||||
}
|
||||
addr = XEXP (operands[0], 0);
|
||||
|
||||
/* 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
|
||||
return output_move_double (operands);
|
||||
}
|
||||
else abort ();
|
||||
}
|
||||
|
|
|
@ -1402,6 +1402,92 @@
|
|||
}"
|
||||
[(set_attr "type" "fp")
|
||||
(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
|
||||
|
||||
|
|
32
gcc/rtl.c
32
gcc/rtl.c
|
@ -383,21 +383,39 @@ add_dependence (insn, elem, dep_type)
|
|||
rtx elem;
|
||||
enum reg_note dep_type;
|
||||
{
|
||||
rtx link;
|
||||
rtx link, next;
|
||||
|
||||
/* Don't depend an insn on itself. */
|
||||
if (insn == elem)
|
||||
return;
|
||||
|
||||
/* If elem is part of a sequence that must be scheduled together, then
|
||||
make the dependence point to the last insn of the sequence. */
|
||||
if (NEXT_INSN (elem) && SCHED_GROUP_P (NEXT_INSN (elem)))
|
||||
make the dependence point to the last insn of the sequence.
|
||||
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)))
|
||||
elem = NEXT_INSN (elem);
|
||||
/* Again, don't depend an insn of itself. */
|
||||
if (insn == elem)
|
||||
/* Notes will never intervene here though, so don't bother checking
|
||||
for them. */
|
||||
while (next && SCHED_GROUP_P (next))
|
||||
next = NEXT_INSN (next);
|
||||
|
||||
/* Again, don't depend an insn on itself. */
|
||||
if (insn == next)
|
||||
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. */
|
||||
|
|
20
gcc/sched.c
20
gcc/sched.c
|
@ -1214,18 +1214,24 @@ sched_analyze_2 (x, insn)
|
|||
#ifdef HAVE_cc0
|
||||
case CC0:
|
||||
{
|
||||
rtx link;
|
||||
rtx link, prev;
|
||||
|
||||
/* There may be a note before this insn now, but all notes will
|
||||
be removed before we actually try to schedule the insns, so
|
||||
it won't cause a problem later. We must avoid it here though. */
|
||||
|
||||
/* User of CC0 depends on immediately preceding insn.
|
||||
There may be a note before this insn now, but all notes will
|
||||
be removed before we actually try to schedule the insns, so
|
||||
it doesn't matter. */
|
||||
SCHED_GROUP_P (insn) = 1;
|
||||
|
||||
/* Make a copy of all dependencies on PREV_INSN, and add to this insn.
|
||||
This is so that all the dependencies will apply to the group. */
|
||||
/* Make a copy of all dependencies on the immediately previous insn,
|
||||
and add to this insn. This is so that all the dependencies will
|
||||
apply to the group. */
|
||||
|
||||
for (link = LOG_LINKS (PREV_INSN (insn)); link; link = XEXP (link, 1))
|
||||
prev = PREV_INSN (insn);
|
||||
while (GET_CODE (prev) == NOTE)
|
||||
prev = PREV_INSN (prev);
|
||||
|
||||
for (link = LOG_LINKS (prev); link; link = XEXP (link, 1))
|
||||
add_dependence (insn, XEXP (link, 0), GET_MODE (link));
|
||||
|
||||
return;
|
||||
|
|
Loading…
Reference in New Issue