1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
|
#! /bin/sh -e
# DP: ARM patch for large constant generation
src=gcc
if [ $# -eq 3 -a "$2" = '-d' ]; then
pdir="-d $3"
src=$3/gcc
elif [ $# -ne 1 ]; then
echo >&2 "`basename $0`: script expects -patch|-unpatch as argument"
exit 1
fi
case "$1" in
-patch)
patch $pdir -f --no-backup-if-mismatch -p1 --fuzz 10 < $0
cd $src && autoconf
;;
-unpatch)
patch $pdir -f --no-backup-if-mismatch -R -p1 --fuzz 10 < $0
cd $src && autoconf
;;
*)
echo >&2 "`basename $0`: script expects -patch|-unpatch as argument"
exit 1
esac
exit 0
--- src/gcc/config/arm/arm.c 2001/01/25 14:03:24 1.43.4.8
+++ src/gcc/config/arm/arm.c 2001/06/23 12:07:08
@@ -722,6 +722,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. */
int
@@ -1178,7 +1205,7 @@ arm_gen_constant (code, mode, val, targe
We start by looking for the largest block of zeros that are aligned on
a 2-bit boundary, we then fill up the temps, wrapping around to the
top of the word when we drop off the bottom.
- In the worst case this code should produce no more than four insns. */
+ In the worst case this code should produce no more than four insns. */
{
int best_start = 0;
int best_consecutive_zeros = 0;
@@ -1187,9 +1214,9 @@ arm_gen_constant (code, mode, val, targe
{
int consecutive_zeros = 0;
- if (! (remainder & (3 << i)))
+ if (!(remainder & (3 << i)))
{
- while ((i < 32) && ! (remainder & (3 << i)))
+ while ((i < 32) && !(remainder & (3 << i)))
{
consecutive_zeros += 2;
i += 2;
@@ -1202,10 +1229,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
{
|