This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.
Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|
Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |
Other format: | [Raw text] |
Sorry in advance for the long message. And I'm sure this sort of thing has been discussed before. But anyway... Reload seems a bit too eager to force constants into memory, at least on some architectures. And while looking into that, I wondered whether it was doing enough to cater for SECONDARY_MEMORY_NEEDED. Say we have: (set (reg:SI r1) (reg:SI r2)) and: r1 & r2 are pseudos, r1 is allocated a general register, r2 isn't, but is found to be equivalent to a constant C, C isn't accepted by the movsi constraints If there are two alternatives: reg <- reg reg <- mem then both are treated as needing one reload (cost: 6 units). However, this code in find_reloads: /* We prefer to reload pseudos over reloading other things, since such reloads may be able to be eliminated later. If we are reloading a SCRATCH, we won't be generating any insns, just using a register, so it is also preferred. So bump REJECT in other cases. Don't do this in the case where we are forcing a constant into memory and it will then win since we don't want to have a different alternative match then. */ if (! (GET_CODE (operand) == REG && REGNO (operand) >= FIRST_PSEUDO_REGISTER) && GET_CODE (operand) != SCRATCH && ! (const_to_mem && constmemok)) reject += 2; will increase the cost of the reg <- reg alternative by 2 units, deliberately making the reg <- mem one cheaper. I can see that that makes sense for targets where symbol_refs are valid addresses. But when they aren't, we'll end up having to reload the constant pool address into a register. For example, on mips-linux-gnu, we'd get the equivalent of: .LC0: .word C la temp,.LC0 lw r1,(temp) See the attached stress.c for a brute-force example. So, my question is: do we really need to prefer reg <- mem over reg <- reg on targets that will need to reload the pool address? Choosing reg <- reg will mean that the input reload will "rematerialise" the constant (by calling the move expanders or by using the reload_in pattern). And reload's optimisers are often able to remove any redundant reg <- reg moves that this might create. I tried two ways of making the reg <- mem alternative more costly: - Disable the const_to_mem get-out clause above if symbol_refs aren't valid addresses. [patch-1.diff] - (More aggressive:) Count the expected symbol_ref reload as a full extra reload. [patch-2.diff] The patches are supposed to be mutually exclusive. They follow the existing convention of testing for addressing modes in init_reload. To see how the changes affect ports other than mips, I tried taking one configuration from each backend[*] and diffing the output of c-torture. I'd copied stress.c to c-torture first, so it's included in the analysis below. ([*] aside from n32k & iq2000, which didn't build) All files were compiled with: <dir>/xgcc -B<dir>/ -O2 -S foo.c -o foo.s The results were as follows (ignore the last column for now ;): CVS Patch 1 Patch 2 vs. vs. vs. Patch 1 Patch 2 Patch 3 alpha-linux-gnu same better? arc-elf n/a n/a arm-elf same n/a avr-elf n/a n/a c4x-elf n/a n/a cris-elf n/a n/a d30v-elf n/a n/a dsp16xx-elf same n/a fr30-elf same n/a frv-elf same n/a h8300-elf n/a n/a hppa-linux-gnu same better? i370-linux-gnu same n/a i686-linux-gnu n/a better? ia64-linux-gnu same n/a ip2k-elf same n/a m32r-elf same n/a m68hc11-elf n/a n/a m68k-elf n/a n/a mcore-elf ---- n/a mips-linux-gnu better n/a mmix n/a n/a mn10300-elf n/a n/a pdp11-elf n/a n/a powerpc-linux-gnu better? same s390-linux-gnu ---- ---- same sh64-elf same better? n/a sparc-linux-gnu better? worse better? (= patch 1) v850-elf better? n/a xstormy16-elf same n/a vax-ultrix n/a n/a xtensa-elf same n/a Key to "CVS vs. Patch 1": n/a: The target allows symbolic addresses, so the patch has no effect. same: The target doesn't allow symbolic addresses but the patch has no effect anyway. Presumably the md patterns had matching constant constraints. better: The output looks better to me. I'm not real judge of powerpc, sparc or v850 code though, so I've attached the diffs below. There were two problems: - mcore-elf ICEd for a few more tests. It seems that the movsi patterns can't handle all legitimate constants when called during reload. - There are lots of s390-linux-gnu changesm, some of which look better and some of which look worse. I've attached the diff for reference, but... As far as s390 goes, the init_reload test wasn't really supposed to fail in the first place. The port _does_ treat constant pool addresses as legitimate. The problem is that the test in init_reload is for a general symbol_ref, not a constant pool address. I couldn't think of a good way of fixing this within the current framework. For example, if we set the dummy symbol's CONSTANT_POOL_ADDRESS_P bit, the backend might pass the symbol to functions like get_pool_mode(), which would then abort. -> One alternative would be to add a target hook. It could take a mode as argument and return a bitset of supported addressing types: reg + reg, constant pool address, indirect memref, etc. Maybe we could have a default implementation that does something akin to init_reload. Anyway, in terms of output code, patch 1 seems to be a strict improvement for everything except s390. That's including mcore, since there's an improvement to one test and no change in the others. But before trying to fix the mcore & s390 problems, I thought I'd see whether the general idea is OK. What do you think? Moving on to patch 2... it only differed from patch 1 on two targets: sh64-elf (for which it seems to be an improvement) and sparc-linux-gnu, for which it was a regression. Diffs for both attached. Personally, I slightly prefer patch 2 to patch 1. Giving the symbol_ref reload a cost of 6 units seems more in keeping with the surrounding code. So, I tried to track down the source of the sparc problem. We had insns like: (set (reg:SF %fx) (const_double:SF 0)) which matched *movsf_insn_novis. The best two alternatives were r <- G and f <- m, with the following costs: CVS Patch 1 Patch 2 (1) r <- G 9 9 9 (6) f <- m 6 8 12 The cost of alternative (1) seems a little low to me since the output reload has to be done through memory. If we count it as two reloads instead of one, using: #ifdef SECONDARY_MEMORY_NEEDED if (GET_CODE (operand) == REG && REGNO (operand) < FIRST_PSEUDO_REGISTER && this_alternative[i] != NO_REGS && (SECONDARY_MEMORY_NEEDED (this_alternative[i], REGNO_REG_CLASS (REGNO (operand)), GET_MODE (operand)))) losers++; #endif then the results for patch 2 are the same as for patch 1 on sparc. I've attached this modified version of patch 2 as patch 3. I tried running it through all targets that define SECONDARY_MEMORY_NEEDED, including those that accept symbol_ref addresses. Aside from s390, it seems to be a strict improvement compared with CVS and patch 2. Diffs attached once again. ;) FWIW, patch 2 was bootstrapped & regression tested on various mips targets. But this isn't really an RFA because of the s390 & mcore issues. Richard
Attachment:
stress.c
Description: Text document
Index: reload.h =================================================================== RCS file: /cvs/gcc/gcc/gcc/reload.h,v retrieving revision 1.45 diff -u -d -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.45 reload.h --- reload.h 6 Jul 2003 09:56:07 -0000 1.45 +++ reload.h 24 Aug 2003 19:52:51 -0000 @@ -187,6 +187,8 @@ extern int reload_first_uid; extern char indirect_symref_ok; +extern bool symbolic_address_ok; + /* Nonzero if an address (plus (reg frame_pointer) (reg ...)) is valid. */ extern char double_reg_address_ok; Index: reload1.c =================================================================== RCS file: /cvs/gcc/gcc/gcc/reload1.c,v retrieving revision 1.406 diff -u -d -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.406 reload1.c --- reload1.c 19 Jul 2003 14:47:13 -0000 1.406 +++ reload1.c 24 Aug 2003 19:52:53 -0000 @@ -226,6 +230,9 @@ static char spill_indirect_levels; which these are valid is the same as spill_indirect_levels, above. */ char indirect_symref_ok; +/* Nonzero if symbolic addresses are legitimate. */ +bool symbolic_address_ok; + /* Nonzero if an address (plus (reg frame_pointer) (reg ...)) is valid. */ char double_reg_address_ok; @@ -454,6 +461,10 @@ init_reload (void) tem = gen_rtx_MEM (Pmode, gen_rtx_SYMBOL_REF (Pmode, "foo")); indirect_symref_ok = memory_address_p (QImode, tem); + + /* See whether (SYMBOL_REF ...) itself is a legitimate address. */ + + symbolic_address_ok = memory_address_p (word_mode, XEXP (tem, 0)); /* See if reg+reg is a valid (and offsettable) address. */ Index: reload.c =================================================================== RCS file: /cvs/gcc/gcc/gcc/reload.c,v retrieving revision 1.220 diff -u -d -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.220 reload.c --- reload.c 19 Jul 2003 14:47:13 -0000 1.220 +++ reload.c 24 Aug 2003 19:52:55 -0000 @@ -3404,7 +3404,7 @@ find_reloads (rtx insn, int replace, int if (! (GET_CODE (operand) == REG && REGNO (operand) >= FIRST_PSEUDO_REGISTER) && GET_CODE (operand) != SCRATCH - && ! (const_to_mem && constmemok)) + && ! (const_to_mem && constmemok && symbolic_address_ok)) reject += 2; /* Input reloads can be inherited more often than output
Index: reload.h =================================================================== RCS file: /cvs/gcc/gcc/gcc/reload.h,v retrieving revision 1.45 diff -u -d -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.45 reload.h --- reload.h 6 Jul 2003 09:56:07 -0000 1.45 +++ reload.h 24 Aug 2003 19:50:24 -0000 @@ -187,6 +187,8 @@ extern int reload_first_uid; extern char indirect_symref_ok; +extern bool symbolic_address_ok; + /* Nonzero if an address (plus (reg frame_pointer) (reg ...)) is valid. */ extern char double_reg_address_ok; Index: reload1.c =================================================================== RCS file: /cvs/gcc/gcc/gcc/reload1.c,v retrieving revision 1.406 diff -u -d -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.406 reload1.c --- reload1.c 19 Jul 2003 14:47:13 -0000 1.406 +++ reload1.c 24 Aug 2003 19:50:26 -0000 @@ -226,6 +230,9 @@ static char spill_indirect_levels; which these are valid is the same as spill_indirect_levels, above. */ char indirect_symref_ok; +/* Nonzero if symbolic addresses are legitimate. */ +bool symbolic_address_ok; + /* Nonzero if an address (plus (reg frame_pointer) (reg ...)) is valid. */ char double_reg_address_ok; @@ -454,6 +461,10 @@ init_reload (void) tem = gen_rtx_MEM (Pmode, gen_rtx_SYMBOL_REF (Pmode, "foo")); indirect_symref_ok = memory_address_p (QImode, tem); + + /* See whether (SYMBOL_REF ...) itself is a legitimate address. */ + + symbolic_address_ok = memory_address_p (word_mode, XEXP (tem, 0)); /* See if reg+reg is a valid (and offsettable) address. */ Index: reload.c =================================================================== RCS file: /cvs/gcc/gcc/gcc/reload.c,v retrieving revision 1.220 diff -u -d -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.220 reload.c --- reload.c 19 Jul 2003 14:47:13 -0000 1.220 +++ reload.c 24 Aug 2003 19:50:28 -0000 @@ -3366,7 +3366,8 @@ find_reloads (rtx insn, int replace, int && operand_mode[i] != VOIDmode) { const_to_mem = 1; - if (this_alternative[i] != (int) NO_REGS) + if (this_alternative[i] != (int) NO_REGS + || !symbolic_address_ok) losers++; }
Index: reload.h =================================================================== RCS file: /cvs/gcc/gcc/gcc/reload.h,v retrieving revision 1.45 diff -u -d -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.45 reload.h --- reload.h 6 Jul 2003 09:56:07 -0000 1.45 +++ reload.h 24 Aug 2003 19:49:43 -0000 @@ -187,6 +187,8 @@ extern int reload_first_uid; extern char indirect_symref_ok; +extern bool symbolic_address_ok; + /* Nonzero if an address (plus (reg frame_pointer) (reg ...)) is valid. */ extern char double_reg_address_ok; Index: reload1.c =================================================================== RCS file: /cvs/gcc/gcc/gcc/reload1.c,v retrieving revision 1.406 diff -u -d -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.406 reload1.c --- reload1.c 19 Jul 2003 14:47:13 -0000 1.406 +++ reload1.c 24 Aug 2003 19:49:46 -0000 @@ -226,6 +230,9 @@ static char spill_indirect_levels; which these are valid is the same as spill_indirect_levels, above. */ char indirect_symref_ok; +/* Nonzero if symbolic addresses are legitimate. */ +bool symbolic_address_ok; + /* Nonzero if an address (plus (reg frame_pointer) (reg ...)) is valid. */ char double_reg_address_ok; @@ -454,6 +461,10 @@ init_reload (void) tem = gen_rtx_MEM (Pmode, gen_rtx_SYMBOL_REF (Pmode, "foo")); indirect_symref_ok = memory_address_p (QImode, tem); + + /* See whether (SYMBOL_REF ...) itself is a legitimate address. */ + + symbolic_address_ok = memory_address_p (word_mode, XEXP (tem, 0)); /* See if reg+reg is a valid (and offsettable) address. */ Index: reload.c =================================================================== RCS file: /cvs/gcc/gcc/gcc/reload.c,v retrieving revision 1.220 diff -u -d -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.220 reload.c --- reload.c 19 Jul 2003 14:47:13 -0000 1.220 +++ reload.c 24 Aug 2003 19:49:48 -0000 @@ -3366,7 +3366,8 @@ find_reloads (rtx insn, int replace, int && operand_mode[i] != VOIDmode) { const_to_mem = 1; - if (this_alternative[i] != (int) NO_REGS) + if (this_alternative[i] != (int) NO_REGS + || !symbolic_address_ok) losers++; } @@ -3392,6 +3393,17 @@ find_reloads (rtx insn, int replace, int else if (modified[i] != RELOAD_WRITE && no_input_reloads && ! const_to_mem) bad = 1; + +#ifdef SECONDARY_MEMORY_NEEDED + if (GET_CODE (operand) == REG + && REGNO (operand) < FIRST_PSEUDO_REGISTER + && this_alternative[i] != NO_REGS + && (SECONDARY_MEMORY_NEEDED + (this_alternative[i], + REGNO_REG_CLASS (REGNO (operand)), + GET_MODE (operand)))) + losers++; +#endif /* We prefer to reload pseudos over reloading other things, since such reloads may be able to be eliminated later.
Attachment:
patch-effects.tar.bz2
Description: BZip2 compressed data
Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|
Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |