diff options
author | Philip Blundell <philb@gnu.org> | 2001-01-04 20:19:48 +0000 |
---|---|---|
committer | Phil Blundell <pb@gcc.gnu.org> | 2001-01-04 20:19:48 +0000 |
commit | ceebdb0980bee33cbd7b08dcd350f4faa7634f27 (patch) | |
tree | 3ec75373ca28b0ad0d63d95fb668c8f7327670ad | |
parent | 1fd4f141391f8f683be28c3353d6753bd24d6905 (diff) | |
download | gcc-ceebdb0980bee33cbd7b08dcd350f4faa7634f27.zip gcc-ceebdb0980bee33cbd7b08dcd350f4faa7634f27.tar.gz gcc-ceebdb0980bee33cbd7b08dcd350f4faa7634f27.tar.bz2 |
arm.c (arm_gen_constant): Prefer to emit constants from bit 31 downwards, if this requires no more insns.
2001-01-04 Philip Blundell <philb@gnu.org>
* config/arm/arm.c (arm_gen_constant): Prefer to emit constants
from bit 31 downwards, if this requires no more insns.
(count_insns_for_constant): New helper function for above.
From-SVN: r38690
-rw-r--r-- | gcc/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/config/arm/arm.c | 60 |
2 files changed, 63 insertions, 3 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 87503ba..6a2c343 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2001-01-04 Philip Blundell <philb@gnu.org> + + * config/arm/arm.c (arm_gen_constant): Prefer to emit constants + from bit 31 downwards, if this requires no more insns. + (count_insns_for_constant): New helper function for above. + 2001-01-04 Alexandre Oliva <aoliva@redhat.com> * gencodes.c (output_predicate_decls): Remove empty initializer. diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index c3a936c..d71dcd1 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -986,6 +986,33 @@ arm_split_constant (code, mode, val, target, source, subtargets) return arm_gen_constant (code, mode, val, target, source, subtargets, 1); } +static int +count_insns_for_constant (HOST_WIDE_INT remainder, int i) +{ + HOST_WIDE_INT temp1; + int num_insns = 0; + do + { + int end; + + if (i <= 0) + i += 32; + if (remainder & (3 << (i - 2))) + { + end = i - 8; + if (end < 0) + end += 32; + temp1 = remainder & ((0x0ff << end) + | ((i < end) ? (0xff >> (32 - end)) : 0)); + remainder &= ~temp1; + num_insns++; + i -= 6; + } + i -= 2; + } while (remainder); + return num_insns; +} + /* As above, but extra parameter GENERATE which, if clear, suppresses RTL generation. */ static int @@ -1466,9 +1493,36 @@ arm_gen_constant (code, mode, val, target, source, subtargets, generate) } } - /* Now start emitting the insns, starting with the one with the highest - bit set: we do this so that the smallest number will be emitted last; - this is more likely to be combinable with addressing insns. */ + /* So long as it won't require any more insns to do so, it's + desirable to emit a small constant (in bits 0...9) in the last + insn. This way there is more chance that it can be combined with + a later addressing insn to form a pre-indexed load or store + operation. Consider: + + *((volatile int *)0xe0000100) = 1; + *((volatile int *)0xe0000110) = 2; + + We want this to wind up as: + + mov rA, #0xe0000000 + mov rB, #1 + str rB, [rA, #0x100] + mov rB, #2 + str rB, [rA, #0x110] + + rather than having to synthesize both large constants from scratch. + + Therefore, we calculate how many insns would be required to emit + the constant starting from `best_start', and also starting from + zero (ie with bit 31 first to be output). If `best_start' doesn't + yield a shorter sequence, we may as well use zero. */ + if (best_start != 0 + && ((((unsigned HOST_WIDE_INT) 1) << best_start) < remainder) + && (count_insns_for_constant (remainder, 0) <= + count_insns_for_constant (remainder, best_start))) + best_start = 0; + + /* Now start emitting the insns. */ i = best_start; do { |