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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
|
--- combine.c.orig Sun Nov 26 11:32:07 1995
+++ combine.c Mon Mar 20 13:29:10 2000
@@ -440,7 +440,7 @@
static int use_crosses_set_p PROTO((rtx, int));
static void reg_dead_at_p_1 PROTO((rtx, rtx));
static int reg_dead_at_p PROTO((rtx, rtx));
-static void move_deaths PROTO((rtx, int, rtx, rtx *));
+static void move_deaths PROTO((rtx, rtx, int, rtx, rtx *));
static int reg_bitfield_target_p PROTO((rtx, rtx));
static void distribute_notes PROTO((rtx, rtx, rtx, rtx, rtx, rtx));
static void distribute_links PROTO((rtx));
@@ -2077,8 +2077,38 @@
undobuf.other_insn, NULL_RTX, NULL_RTX, NULL_RTX);
}
- /* We now know that we can do this combination. Merge the insns and
- update the status of registers and LOG_LINKS. */
+ /* We now know that we can do this combination. */
+
+ /* Earlier we did all the checks required to determine if we could
+ logically combine three insns into one. Then we determined that
+ the machine description would not let us do it in one, but would
+ let us do it in two. Thus when generating two insns, they must,
+ in general, be adjacent -- one logical instruction if you will.
+
+ We could be complicated and figure out some rules that would allow
+ us to not move the insn, but it seems likely that the scheduler will
+ do as good with no muss. */
+
+ if (newi2pat && NEXT_INSN (i2) != i3)
+ {
+ rtx n = NEXT_INSN(i2);
+ int c = INSN_CUID(i2);
+
+ /* Move the instruction */
+ reorder_insns(i2, i2, PREV_INSN (i3));
+
+ /* Update the CUID map */
+ while (1)
+ {
+ uid_cuid[INSN_UID (n)] = c;
+ if (n == i2)
+ break;
+ n = NEXT_INSN(n);
+ ++c;
+ }
+ }
+
+ /* Merge the insns and update the status of registers and LOG_LINKS. */
{
rtx i3notes, i2notes, i1notes = 0;
@@ -2186,11 +2216,18 @@
}
/* Get death notes for everything that is now used in either I3 or
- I2 and used to die in a previous insn. */
+ I2 and used to die in a previous insn. If we built two new
+ patterns, move from i1 to i2 then i2 to i3 so that we get the
+ proper movement on registers that i2 modifies. */
- move_deaths (newpat, i1 ? INSN_CUID (i1) : INSN_CUID (i2), i3, &midnotes);
if (newi2pat)
- move_deaths (newi2pat, INSN_CUID (i1), i2, &midnotes);
+ {
+ move_deaths (newi2pat, NULL_RTX, INSN_CUID (i1), i2, &midnotes);
+ move_deaths (newpat, newi2pat, INSN_CUID (i1), i3, &midnotes);
+ }
+ else
+ move_deaths (newpat, NULL_RTX, i1 ? INSN_CUID (i1) : INSN_CUID (i2),
+ i3, &midnotes);
/* Distribute all the LOG_LINKS and REG_NOTES from I1, I2, and I3. */
if (i3notes)
@@ -10372,12 +10409,15 @@
TO_INSN (exclusive), put a REG_DEAD note for that register in the
list headed by PNOTES.
+ That said, don't move registers killed by maybe_kill_insn.
+
This is done when X is being merged by combination into TO_INSN. These
notes will then be distributed as needed. */
static void
-move_deaths (x, from_cuid, to_insn, pnotes)
+move_deaths (x, maybe_kill_insn, from_cuid, to_insn, pnotes)
rtx x;
+ rtx maybe_kill_insn;
int from_cuid;
rtx to_insn;
rtx *pnotes;
@@ -10392,6 +10432,11 @@
register rtx where_dead = reg_last_death[regno];
register rtx before_dead, after_dead;
+ /* Don't move the register if it gets killed in between from and to */
+ if (maybe_kill_insn && reg_set_p (x, maybe_kill_insn)
+ && !reg_referenced_p (x, maybe_kill_insn))
+ return;
+
/* WHERE_DEAD could be a USE insn made by combine, so first we
make sure that we have insns with valid INSN_CUID values. */
before_dead = where_dead;
@@ -10449,7 +10494,7 @@
for (i = regno + 1; i < ourend; i++)
move_deaths (gen_rtx (REG, reg_raw_mode[i], i),
- from_cuid, to_insn, &oldnotes);
+ maybe_kill_insn, from_cuid, to_insn, &oldnotes);
}
if (note != 0 && GET_MODE (XEXP (note, 0)) == GET_MODE (x))
@@ -10470,7 +10515,7 @@
{
rtx dest = SET_DEST (x);
- move_deaths (SET_SRC (x), from_cuid, to_insn, pnotes);
+ move_deaths (SET_SRC (x), maybe_kill_insn, from_cuid, to_insn, pnotes);
/* In the case of a ZERO_EXTRACT, a STRICT_LOW_PART, or a SUBREG
that accesses one word of a multi-word item, some
@@ -10485,7 +10530,7 @@
== ((GET_MODE_SIZE (GET_MODE (SUBREG_REG (dest)))
+ UNITS_PER_WORD - 1) / UNITS_PER_WORD))))
{
- move_deaths (dest, from_cuid, to_insn, pnotes);
+ move_deaths (dest, maybe_kill_insn, from_cuid, to_insn, pnotes);
return;
}
@@ -10499,7 +10544,8 @@
being replaced so the old value is not used in this insn. */
if (GET_CODE (dest) == MEM)
- move_deaths (XEXP (dest, 0), from_cuid, to_insn, pnotes);
+ move_deaths (XEXP (dest, 0), maybe_kill_insn, from_cuid,
+ to_insn, pnotes);
return;
}
@@ -10515,10 +10561,11 @@
{
register int j;
for (j = XVECLEN (x, i) - 1; j >= 0; j--)
- move_deaths (XVECEXP (x, i, j), from_cuid, to_insn, pnotes);
+ move_deaths (XVECEXP (x, i, j), maybe_kill_insn, from_cuid,
+ to_insn, pnotes);
}
else if (fmt[i] == 'e')
- move_deaths (XEXP (x, i), from_cuid, to_insn, pnotes);
+ move_deaths (XEXP (x, i), maybe_kill_insn, from_cuid, to_insn, pnotes);
}
}
|