From: Jim Wilson Date: Tue, 14 Apr 1992 17:46:57 +0000 (-0700) Subject: *** empty log message *** X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=a3ee589982d1fd8b65e0adcf440f374159d86de8;p=gcc.git *** empty log message *** From-SVN: r742 --- diff --git a/gcc/c-lex.c b/gcc/c-lex.c index 07bdf039b1b..897cdec69ef 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 3b5b9c24970..83a3a1a8a37 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 2aa19e616d2..2693c171205 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 b82e5f13968..dee61522db3 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 93e6a07d2f9..2a391e5c616 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;