This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: PATCH for [ARM] subsequent use of plus and minus operators couldbe improved
- From: Gábor Lóki <alga at rgai dot hu>
- To: Joern Rennecke <joern dot rennecke at superh dot com>
- Cc: Richard dot Earnshaw at arm dot com, Zack Weinberg <zack at codesourcery dot com>, gcc-patches<gcc-patches at gcc dot gnu dot org>
- Date: Thu, 08 May 2003 15:23:53 +0200
- Subject: Re: PATCH for [ARM] subsequent use of plus and minus operators couldbe improved
- References: <3EB7FADF.44E4DF44@superh.com>
Joern Rennecke wrote:
+ next = NEXT_INSN (insn);
If you only handle adjacent instructions, and don't use the data
available in reload_cse_move2add, putting the code there is just
confusing. You could put that code into any old loop that traverses
the insns. In that respect, I think your previous patch that did
a separate traversal was better.
If we really save a worthwhile amount of time by traversing the insns
only once - that would have to be because of better memory locality,
as putting too much into a single function tends to screw up register
allocation - then we should just merge all the post-reload operations
that don't need to run sequentially into one huge glob of code.
Doing your transformation without a cost check is also a bit dubious,
I have no information about how I can do this cost check correctly.
although with a well-written machine description, any disadvantagous
combination will probably be undone in the pre-sched2 instruction
splitting pass.
+ rtx new_value = GEN_INT (INTVAL (XEXP (insn_src, 1)) +
+ INTVAL (XEXP (next_src, 1)));
This new constant that you create can end up with incorrect sign extension.
Thanks, I missed it. Corrected patch can be seen in the attached file.
Regards,
Gábor Lóki
*** orig/gcc/reload1.c Sat Mar 29 00:22:05 2003
--- patch/gcc/reload1.c Thu May 8 14:23:52 2003
*************** reload_cse_move2add (first)
*** 9130,9135 ****
--- 9130,9192 ----
if (! INSN_P (insn))
continue;
pat = PATTERN (insn);
+
+ /* Try to transform
+ (set (regX) (plus (regY) (constA)))
+ (set (regX) (plus (regX) (constB)))
+ to
+ (set (regX) (plus (regY) (constA + constB))) */
+ if (NEXT_INSN (insn)
+ && GET_MODE (insn) == VOIDmode
+ && GET_MODE (NEXT_INSN (insn)) == VOIDmode
+ && GET_CODE (pat) == SET
+ && GET_CODE (NEXT_INSN (insn)) == INSN
+ && GET_CODE (PATTERN (NEXT_INSN (insn))) == SET)
+ {
+ rtx insn_dest, insn_src, next_dest, next_src;
+ insn_dest = SET_DEST (pat);
+ insn_src = SET_SRC (pat);
+ next_dest = SET_DEST (PATTERN (NEXT_INSN (insn)));
+ next_src = SET_SRC (PATTERN (NEXT_INSN (insn)));
+
+ if (GET_CODE (insn_dest) == REG
+ && GET_CODE (insn_src) == PLUS
+ && GET_CODE (XEXP (insn_src, 0)) == REG
+ && GET_CODE (XEXP (insn_src, 1)) == CONST_INT
+ && GET_CODE (next_dest) == REG
+ && GET_CODE (next_src) == PLUS
+ && GET_CODE (XEXP (next_src, 0)) == REG
+ && GET_CODE (XEXP (next_src, 1)) == CONST_INT
+ && REGNO (insn_dest) == REGNO (next_dest)
+ && REGNO (next_dest) == REGNO (XEXP (next_src, 0)))
+ {
+ int success = 0;
+ HOST_WIDE_INT constA = INTVAL (XEXP (insn_src, 1));
+ HOST_WIDE_INT constB = INTVAL (XEXP (next_src, 1));
+ HOST_WIDE_INT constSum = constA + constB;
+
+ /* Overflow occurs if constA and constB have the same sign, but
+ constA and constSum differ in sign. Use `^' to test whether
+ signs differ, and `>= 0' to isolate the sign. */
+ if (~(constA ^ constB) & (constA ^ constSum) >= 0)
+ {
+ if (constSum == 0)
+ /* Create (set (regX) (regY)) if the new
+ constant is zero. */
+ success = validate_change (insn,
+ &SET_SRC (pat),
+ XEXP (insn_src,0), 0);
+ else
+ /* Otherwise, replace constA with the new constant. */
+ success = validate_change (insn,
+ &XEXP (insn_src, 1),
+ GEN_INT (constSum), 0);
+ if (success)
+ delete_insn (NEXT_INSN (insn));
+ }
+ }
+ }
+
/* For simplicity, we only perform this optimization on
straightforward SETs. */
if (GET_CODE (pat) == SET