patch for arm_gen_constant
Philip Blundell
philb@gnu.org
Thu Jan 4 12:18:00 GMT 2001
>This is ok, except for the cost that it incurs when there is no likely
>benefit to be gained. Can we devise a check that will only run the code
>when there is a likely benefit. Perhaps wrapping the new code in
Good idea. Here's what I checked in.
p.
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.
Index: arm.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/arm/arm.c,v
retrieving revision 1.130
diff -u -p -u -r1.130 arm.c
--- arm.c 2000/12/30 16:34:00 1.130
+++ arm.c 2001/01/04 20:15:05
@@ -986,6 +986,33 @@ arm_split_constant (code, mode, val, tar
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
@@ -1465,10 +1492,37 @@ arm_gen_constant (code, mode, val, targe
i -= 2;
}
}
+
+ /* 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, 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. */
+ /* Now start emitting the insns. */
i = best_start;
do
{
More information about the Gcc-patches
mailing list