From: Jim Wilson Date: Sun, 19 Apr 1992 01:55:55 +0000 (-0700) Subject: *** empty log message *** X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=3501632240b1016da6a377785a8f7567ceb7dfcb;p=gcc.git *** empty log message *** From-SVN: r788 --- diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c index 83a3a1a8a37..aa7c291f5f5 100644 --- a/gcc/config/sparc/sparc.c +++ b/gcc/config/sparc/sparc.c @@ -2250,6 +2250,107 @@ output_arc_profiler (arcno, insert_after) emit_insn_after (gen_rtx (SET, VOIDmode, mem_ref, profiler_reg), insert_after); } + +/* Return 1 if REGNO (reg1) is even and REGNO (reg1) == REGNO (reg2) - 1. + This makes them candidates for using ldd and std insns. + + Note reg1 and reg2 *must* be hard registers. To be sure we will + abort if we are passed pseudo registers. */ + +int +registers_ok_for_ldd (reg1, reg2) + rtx reg1, reg2; +{ + + /* We might have been passed a SUBREG. */ + if (GET_CODE (reg1) != REG || GET_CODE (reg2) != REG) + return 0; + + /* Should never happen. */ + if (REGNO (reg1) > FIRST_PSEUDO_REGISTER + || REGNO (reg2) > FIRST_PSEUDO_REGISTER) + abort (); + + if (REGNO (reg1) % 2 != 0) + return 0; + + return (REGNO (reg1) == REGNO (reg2) - 1); + +} + +/* Return 1 if addr1 and addr2 are suitable for use in an ldd or + std insn. + + This can only happen when addr1 and addr2 are consecutive memory + locations (addr1 + 4 == addr2). addr1 must also be aligned on a + 64 bit boundary (addr1 % 8 == 0). + + We know %sp and %fp are kept aligned on a 64 bit boundary. Other + registers are assumed to *never* be properly aligned and are + rejected. + + Knowing %sp and %fp are kept aligned on a 64 bit boundary, we + need only check that the offset for addr1 % 8 == 0. */ + +int +memory_ok_for_ldd (addr1, addr2) + rtx addr1, addr2; +{ + int reg1, offset1; + + /* Extract a register number and offset (if used) from the first addr. */ + if (GET_CODE (addr1) == PLUS) + { + /* If not a REG, return zero. */ + if (GET_CODE (XEXP (addr1, 0)) != REG) + return 0; + else + { + reg1 = REGNO (XEXP (addr1, 0)); + /* The offset must be constant! */ + if (GET_CODE (XEXP (addr1, 1)) != CONST_INT) + return 0; + offset1 = INTVAL (XEXP (addr1, 1)); + } + } + else if (GET_CODE (addr1) != REG) + return 0; + else + { + reg1 = REGNO (addr1); + /* This was a simple (mem (reg)) expression. Offset is 0. */ + offset1 = 0; + } + + /* Make sure the second address is a (mem (plus (reg) (const_int). */ + if (GET_CODE (addr2) != PLUS) + return 0; + + if (GET_CODE (XEXP (addr2, 0)) != REG + || GET_CODE (XEXP (addr2, 1)) != CONST_INT) + return 0; + + /* Only %fp and %sp are allowed. Additionally both addresses must + use the same register. */ + if (reg1 != FRAME_POINTER_REGNUM && reg1 != STACK_POINTER_REGNUM) + return 0; + + if (reg1 != REGNO (XEXP (addr2, 0))) + return 0; + + /* The first offset must be evenly divisable by 8 to ensure the + address is 64 bit aligned. */ + if (offset1 % 8 != 0) + return 0; + + /* The offset for the second addr must be 4 more than the first addr. */ + if (INTVAL (XEXP (addr2, 1)) != offset1 + 4) + return 0; + + /* All the tests passed. addr1 and addr2 are valid for ldd and std + instructions. */ + return 1; +} /* Print operand X (an rtx) in assembler syntax to file FILE. CODE is a letter or dot (`z' in `%z0') or 0 if no letter was specified. diff --git a/gcc/config/sparc/sparc.md b/gcc/config/sparc/sparc.md index 2693c171205..31faa3c7104 100644 --- a/gcc/config/sparc/sparc.md +++ b/gcc/config/sparc/sparc.md @@ -2584,6 +2584,90 @@ ;; Peepholes go at the end. +;; Optimize consecutive loads or stores into ldd and std when possible. +;; The conditions in which we do this are very restricted and are +;; explained in the code for {registers,memory}_ok_for_ldd functions. + +(define_peephole + [(set (match_operand:SI 0 "register_operand" "r") + (match_operand:SI 1 "memory_operand" "")) + (set (match_operand:SI 2 "register_operand" "r") + (match_operand:SI 3 "memory_operand" ""))] + "registers_ok_for_ldd (operands[0], operands[2]) + && ! MEM_VOLATILE_P (operands[1]) && ! MEM_VOLATILE_P (operands[3]) + && memory_ok_for_ldd (XEXP (operands[1], 0), XEXP (operands[3], 0))" + "ldd %1,%0") + +(define_peephole + [(set (match_operand:SI 0 "memory_operand" "") + (match_operand:SI 1 "register_operand" "r")) + (set (match_operand:SI 2 "memory_operand" "") + (match_operand:SI 3 "register_operand" "r"))] + "registers_ok_for_ldd (operands[1], operands[3]) + && ! MEM_VOLATILE_P (operands[0]) && ! MEM_VOLATILE_P (operands[2]) + && memory_ok_for_ldd (XEXP (operands[0], 0), XEXP (operands[2], 0))" + "std %1,%0") + +(define_peephole + [(set (match_operand:SF 0 "register_operand" "fr") + (match_operand:SF 1 "memory_operand" "")) + (set (match_operand:SF 2 "register_operand" "fr") + (match_operand:SF 3 "memory_operand" ""))] + "registers_ok_for_ldd (operands[0], operands[2]) + && ! MEM_VOLATILE_P (operands[1]) && ! MEM_VOLATILE_P (operands[3]) + && memory_ok_for_ldd (XEXP (operands[1], 0), XEXP (operands[3], 0))" + "ldd %1,%0") + +(define_peephole + [(set (match_operand:SF 0 "memory_operand" "") + (match_operand:SF 1 "register_operand" "fr")) + (set (match_operand:SF 2 "memory_operand" "") + (match_operand:SF 3 "register_operand" "fr"))] + "registers_ok_for_ldd (operands[1], operands[3]) + && ! MEM_VOLATILE_P (operands[0]) && ! MEM_VOLATILE_P (operands[2]) + && memory_ok_for_ldd (XEXP (operands[0], 0), XEXP (operands[2], 0))" + "std %1,%0") + +(define_peephole + [(set (match_operand:SI 0 "register_operand" "r") + (match_operand:SI 1 "memory_operand" "")) + (set (match_operand:SI 2 "register_operand" "r") + (match_operand:SI 3 "memory_operand" ""))] + "registers_ok_for_ldd (operands[2], operands[0]) + && ! MEM_VOLATILE_P (operands[3]) && ! MEM_VOLATILE_P (operands[1]) + && memory_ok_for_ldd (XEXP (operands[3], 0), XEXP (operands[1], 0))" + "ldd %3,%2") + +(define_peephole + [(set (match_operand:SI 0 "memory_operand" "") + (match_operand:SI 1 "register_operand" "r")) + (set (match_operand:SI 2 "memory_operand" "") + (match_operand:SI 3 "register_operand" "r"))] + "registers_ok_for_ldd (operands[3], operands[1]) + && ! MEM_VOLATILE_P (operands[2]) && ! MEM_VOLATILE_P (operands[0]) + && memory_ok_for_ldd (XEXP (operands[2], 0), XEXP (operands[0], 0))" + "std %3,%2") + +(define_peephole + [(set (match_operand:SF 0 "register_operand" "fr") + (match_operand:SF 1 "memory_operand" "")) + (set (match_operand:SF 2 "register_operand" "fr") + (match_operand:SF 3 "memory_operand" ""))] + "registers_ok_for_ldd (operands[2], operands[0]) + && ! MEM_VOLATILE_P (operands[3]) && ! MEM_VOLATILE_P (operands[1]) + && memory_ok_for_ldd (XEXP (operands[3], 0), XEXP (operands[1], 0))" + "ldd %3,%2") + +(define_peephole + [(set (match_operand:SF 0 "memory_operand" "") + (match_operand:SF 1 "register_operand" "fr")) + (set (match_operand:SF 2 "memory_operand" "") + (match_operand:SF 3 "register_operand" "fr"))] + "registers_ok_for_ldd (operands[3], operands[1]) + && ! MEM_VOLATILE_P (operands[2]) && ! MEM_VOLATILE_P (operands[0]) + && memory_ok_for_ldd (XEXP (operands[2], 0), XEXP (operands[0], 0))" + "std %3,%2") + ;; Optimize the case of following a reg-reg move with a test ;; of reg just moved.