aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJim Wilson <wilson@gcc.gnu.org>1992-04-14 10:46:57 -0700
committerJim Wilson <wilson@gcc.gnu.org>1992-04-14 10:46:57 -0700
commita3ee589982d1fd8b65e0adcf440f374159d86de8 (patch)
tree1dd3553444dcdf00926189b16c77a3f99f79c394 /gcc
parentf24ec84c7b8cb5bb59e7b0e7e73b2c8107fb6b5c (diff)
downloadgcc-a3ee589982d1fd8b65e0adcf440f374159d86de8.zip
gcc-a3ee589982d1fd8b65e0adcf440f374159d86de8.tar.gz
gcc-a3ee589982d1fd8b65e0adcf440f374159d86de8.tar.bz2
*** empty log message ***
From-SVN: r742
Diffstat (limited to 'gcc')
-rw-r--r--gcc/c-lex.c3
-rw-r--r--gcc/config/sparc/sparc.c123
-rw-r--r--gcc/config/sparc/sparc.md86
-rw-r--r--gcc/rtl.c32
-rw-r--r--gcc/sched.c20
5 files changed, 164 insertions, 100 deletions
diff --git a/gcc/c-lex.c b/gcc/c-lex.c
index 07bdf03..897cdec 100644
--- a/gcc/c-lex.c
+++ b/gcc/c-lex.c
@@ -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
diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c
index 3b5b9c2..83a3a1a 100644
--- a/gcc/config/sparc/sparc.c
+++ b/gcc/config/sparc/sparc.c
@@ -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 (final_sequence)
- abort ();
- return (op1 == operands[0] ? "ldd %1,%0" : "std %1,%0");
- }
+ if (GET_CODE (XEXP (addr, 0)) == LO_SUM && GET_MODE (addr) == DFmode)
+ return (addr == operands[1] ? "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);
- 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 ();
}
diff --git a/gcc/config/sparc/sparc.md b/gcc/config/sparc/sparc.md
index 2aa19e6..2693c17 100644
--- a/gcc/config/sparc/sparc.md
+++ b/gcc/config/sparc/sparc.md
@@ -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
diff --git a/gcc/rtl.c b/gcc/rtl.c
index b82e5f1..dee6152 100644
--- a/gcc/rtl.c
+++ b/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. */
diff --git a/gcc/sched.c b/gcc/sched.c
index 93e6a07..2a391e5 100644
--- a/gcc/sched.c
+++ b/gcc/sched.c
@@ -1214,18 +1214,24 @@ sched_analyze_2 (x, insn)
#ifdef HAVE_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
- 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;
- /* 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. */
+
+ 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));
return;