|
|
1.1 root 1: /* Optimize by combining instructions for GNU compiler.
2: Copyright (C) 1987 Free Software Foundation, Inc.
3:
4: This file is part of GNU CC.
5:
6: GNU CC is distributed in the hope that it will be useful,
7: but WITHOUT ANY WARRANTY. No author or distributor
8: accepts responsibility to anyone for the consequences of using it
9: or for whether it serves any particular purpose or works at all,
10: unless he says so in writing. Refer to the GNU CC General Public
11: License for full details.
12:
13: Everyone is granted permission to copy, modify and redistribute
14: GNU CC, but only under the conditions described in the
15: GNU CC General Public License. A copy of this license is
16: supposed to have been given to you along with GNU CC so you
17: can know your rights and responsibilities. It should be in a
18: file named COPYING. Among other things, the copyright notice
19: and this notice must be preserved on all copies. */
20:
21:
22: /* This module is essentially the "combiner" phase of the U. of Arizona
23: Portable Optimizer, but redone to work on our list-structured
24: representation for RTL instead of their string representation.
25:
26: The LOG_LINKS of each insn identify the most recent assignment
27: to each REG used in the insn. It is a list of previous insns,
28: each of which contains a SET for a REG that is used in this insn
29: and not used or set in between. LOG_LINKs never cross basic blocks.
30: They were set up by the preceding pass (lifetime analysis).
31:
32: We try to combine each pair of insns joined by a logical link.
33: We also try to combine triples of insns A, B and C when
34: C has a link back to B and B has a link back to A.
35:
36: LOG_LINKS does not have links for use of the CC0. They don't
37: need to, because the insn that sets the CC0 is always immediately
38: before the insn that tests it. So we always regard a branch
39: insn as having a logical link to the preceding insn.
40:
41: We check (with use_crosses_set_p) to avoid combining in such a way
42: as to move a computation to a place where its value would be different.
43:
44: Combination is done by mathematically substituting the previous
45: insn(s) values for the regs they set into the expressions in
46: the later insns that refer to these regs. If the result is a valid insn
47: for our target machine, according to the machine description,
48: we install it, delete the earlier insns, and update the data flow
49: information (LOG_LINKS and REG_NOTES) for what we did.
50:
51: To simplify substitution, we combine only when the earlier insn(s)
52: consist of only a single assignment. To simplify updating afterward,
53: we never combine when a subroutine call appears in the middle.
54:
55: Since we do not represent assignments to CC0 explicitly except when that
56: is all an insn does, there is no LOG_LINKS entry in an insn that uses
57: the condition code for the insn that set the condition code.
58: Fortunately, these two insns must be consecutive.
59: Therefore, every JUMP_INSN is taken to have an implicit logical link
60: to the preceding insn. This is not quite right, since non-jumps can
61: also use the condition code; but in practice such insns would not
62: combine anyway. */
63:
64: #include "config.h"
65: #include "rtl.h"
66: #include "regs.h"
67: #include "basic-block.h"
68: #include "insn-config.h"
69: #include "recog.h"
70:
71: #define max(A,B) ((A) > (B) ? (A) : (B))
72: #define min(A,B) ((A) < (B) ? (A) : (B))
73:
74: /* Number of attempts to combine instructions in this function. */
75:
76: static int combine_attempts;
77:
78: /* Number of attempts that got as far as substitution in this function. */
79:
80: static int combine_merges;
81:
82: /* Number of instructions combined with added SETs in this function. */
83:
84: static int combine_extras;
85:
86: /* Number of instructions combined in this function. */
87:
88: static int combine_successes;
89:
90: /* Totals over entire compilation. */
91:
92: static int total_attempts, total_merges, total_extras, total_successes;
93:
94:
95: /* Vector mapping INSN_UIDs to cuids.
96: The cuids are like uids but increase monononically always.
97: Combine always uses cuids so that it can compare them.
98: But actually renumbering the uids, which we used to do,
99: proves to be a bad idea because it makes it hard to compare
100: the dumps produced by earlier passes with those from later passes. */
101:
102: static short *uid_cuid;
103:
104: /* Get the cuid of an insn. */
105:
106: #define INSN_CUID(INSN) (uid_cuid[INSN_UID (INSN)])
107:
108:
109: /* Record last point of death of (hard or pseudo) register n. */
110:
111: static rtx *reg_last_death;
112:
113: /* Record last point of modification of (hard or pseudo) register n. */
114:
115: static rtx *reg_last_set;
116:
117: /* Record the cuid of the last insn that invalidated memory
118: (anything that writes memory, and subroutine calls). */
119:
120: static int mem_last_set;
121:
122: /* Record the cuid of the last CALL_INSN
123: so we can tell whether a potential combination crosses any calls. */
124:
125: static int last_call_cuid;
126:
127: /* When `subst' is called, this is the insn that is being modified
128: (by combining in a previous insn). The PATTERN of this insn
129: is still the old pattern partially modified and it should not be
130: looked at, but this may be used to examine the successors of the insn
131: to judge whether a simplification is valid. */
132:
133: static rtx subst_insn;
134:
135: /* Record one modification to rtl structure
136: to be undone by storing old_contents into *where. */
137:
138: struct undo
139: {
140: rtx *where;
141: rtx old_contents;
142: };
143:
144: /* Record a bunch of changes to be undone, up to MAX_UNDO of them.
145: num_undo says how many are currently recorded.
146: storage is nonzero if we must undo the allocation of new storage.
147: The value of storage is what to pass to obfree. */
148:
149: #define MAX_UNDO 10
150:
151: struct undobuf
152: {
153: int num_undo;
154: char *storage;
155: struct undo undo[MAX_UNDO];
156: };
157:
158: static struct undobuf undobuf;
159:
160: static void move_deaths ();
161: static void remove_death ();
162: static void record_dead_and_set_regs ();
163: int regno_dead_p ();
164: static int reg_set_in_range_p ();
165: static int use_crosses_set_p ();
166: static rtx subst ();
167: static void undo_all ();
168: static void add_links ();
169: static void add_incs ();
170: static int adjacent_insns_p ();
171: static rtx simplify_and_const_int ();
172: static rtx gen_lowpart_for_combine ();
173: static void simplify_set_cc0_and ();
174:
175: /* Main entry point for combiner. F is the first insn of the function.
176: NREGS is the first unused pseudo-reg number. */
177:
178: void
179: combine_instructions (f, nregs)
180: rtx f;
181: int nregs;
182: {
183: register rtx insn;
184: register int i;
185: register rtx links, nextlinks;
186: rtx prev;
187:
188: combine_attempts = 0;
189: combine_merges = 0;
190: combine_extras = 0;
191: combine_successes = 0;
192:
193: reg_last_death = (rtx *) alloca (nregs * sizeof (rtx));
194: reg_last_set = (rtx *) alloca (nregs * sizeof (rtx));
195: bzero (reg_last_death, nregs * sizeof (rtx));
196: bzero (reg_last_set, nregs * sizeof (rtx));
197:
198: init_recog ();
199:
200: /* Compute maximum uid value so uid_cuid can be allocated. */
201:
202: for (insn = f, i = 0; insn; insn = NEXT_INSN (insn))
203: if (INSN_UID (insn) > i)
204: i = INSN_UID (insn);
205:
206: uid_cuid = (short *) alloca ((i + 1) * sizeof (short));
207:
208: /* Compute the mapping from uids to cuids.
209: Cuids are numbers assigned to insns, like uids,
210: except that cuids increase monotonically through the code. */
211:
212: for (insn = f, i = 0; insn; insn = NEXT_INSN (insn))
213: INSN_CUID (insn) = ++i;
214:
215: /* Now scan all the insns in forward order. */
216:
217: last_call_cuid = 0;
218: mem_last_set = 0;
219: prev = 0;
220:
221: for (insn = f; insn; insn = NEXT_INSN (insn))
222: {
223: if (GET_CODE (insn) == INSN
224: || GET_CODE (insn) == CALL_INSN
225: || GET_CODE (insn) == JUMP_INSN)
226: {
227: retry:
228: /* Try this insn with each insn it links back to. */
229:
230: for (links = LOG_LINKS (insn); links; links = XEXP (links, 1))
231: if (try_combine (insn, XEXP (links, 0), 0))
232: goto retry;
233:
234: /* Try each sequence of three linked insns ending with this one. */
235:
236: for (links = LOG_LINKS (insn); links; links = XEXP (links, 1))
237: if (GET_CODE (XEXP (links, 0)) != NOTE)
238: for (nextlinks = LOG_LINKS (XEXP (links, 0)); nextlinks;
239: nextlinks = XEXP (nextlinks, 1))
240: if (try_combine (insn, XEXP (links, 0), XEXP (nextlinks, 0)))
241: goto retry;
242:
243: /* Try to combine a jump insn that uses CC0
244: with a preceding insn that sets CC0, and maybe with its
245: logical predecessor as well.
246: This is how we make decrement-and-branch insns.
247: We need this special code because data flow connections
248: via CC0 do not get entered in LOG_LINKS. */
249:
250: if (GET_CODE (insn) == JUMP_INSN
251: && prev != 0
252: && GET_CODE (prev) == INSN
253: && GET_CODE (PATTERN (prev)) == SET
254: && GET_CODE (SET_DEST (PATTERN (prev))) == CC0)
255: {
256: if (try_combine (insn, prev, 0))
257: goto retry;
258:
259: if (GET_CODE (prev) != NOTE)
260: for (nextlinks = LOG_LINKS (prev); nextlinks;
261: nextlinks = XEXP (nextlinks, 1))
262: if (try_combine (insn, prev, XEXP (nextlinks, 0)))
263: goto retry;
264: }
265: #if 0
266: /* Turned off because on 68020 it takes four insns to make
267: something like (a[b / 32] & (1 << (31 - (b % 32)))) != 0
268: that could actually be optimized, and that's an unlikely piece of code. */
269: /* If an insn gets or sets a bit field, try combining it
270: with two different insns whose results it uses. */
271: if (GET_CODE (insn) == INSN
272: && GET_CODE (PATTERN (insn)) == SET
273: && (GET_CODE (SET_DEST (PATTERN (insn))) == ZERO_EXTRACT
274: || GET_CODE (SET_DEST (PATTERN (insn))) == SIGN_EXTRACT
275: || GET_CODE (SET_SRC (PATTERN (insn))) == ZERO_EXTRACT
276: || GET_CODE (SET_SRC (PATTERN (insn))) == SIGN_EXTRACT))
277: {
278: for (links = LOG_LINKS (insn); links; links = XEXP (links, 1))
279: if (GET_CODE (XEXP (links, 0)) != NOTE)
280: for (nextlinks = XEXP (links, 1); nextlinks;
281: nextlinks = XEXP (nextlinks, 1))
282: if (try_combine (insn, XEXP (links, 0), XEXP (nextlinks, 0)))
283: goto retry;
284: }
285: #endif
286: record_dead_and_set_regs (insn);
287: prev = insn;
288: }
289: else if (GET_CODE (insn) != NOTE)
290: prev = 0;
291: }
292: total_attempts += combine_attempts;
293: total_merges += combine_merges;
294: total_extras += combine_extras;
295: total_successes += combine_successes;
296: }
297:
298: /* Try to combine the insns I1 and I2 into I3.
299: Here I1 appears earlier than I2, which is earlier than I3.
300: I1 can be zero; then we combine just I2 into I3.
301:
302: Return 1 if successful; if that happens, I1 and I2 are pseudo-deleted
303: by turning them into NOTEs, and I3 is modified.
304: Return 0 if the combination does not work. Then nothing is changed. */
305:
306: static int
307: try_combine (i3, i2, i1)
308: register rtx i3, i2, i1;
309: {
310: register rtx newpat;
311: int added_sets_1 = 0;
312: int added_sets_2 = 0;
313: int total_sets;
314: int i2_is_used;
315: register rtx link;
316: int insn_code_number;
317: int recog_flags = 0;
318: rtx i2dest, i2src;
319: rtx i1dest, i1src;
320:
321: combine_attempts++;
322:
323: /* Don't combine with something already used up by combination. */
324:
325: if (GET_CODE (i2) == NOTE
326: || (i1 && GET_CODE (i1) == NOTE))
327: return 0;
328:
329: /* Don't combine across a CALL_INSN, because that would possibly
330: change whether the life span of some REGs crosses calls or not,
331: and it is a pain to update that information. */
332:
333: if (INSN_CUID (i2) < last_call_cuid
334: || (i1 && INSN_CUID (i1) < last_call_cuid))
335: return 0;
336:
337: /* Can combine only if previous insn is a SET of a REG, a SUBREG or CC0.
338: That REG must be either set or dead by the final instruction
339: (so that we can safely forget about setting it).
340: Also test use_crosses_set_p to make sure that the value
341: that is to be substituted for the register
342: does not use any registers whose values alter in between.
343: Do not try combining with moves from one register to another
344: since it is better to let them be tied by register allocation.
345:
346: A set of a SUBREG is considered as if it were a set from
347: SUBREG. Thus, (SET (SUBREG:X (REG:Y...)) (something:X...))
348: is handled by substituting (SUBREG:Y (something:X...)) for (REG:Y...). */
349:
350: if (GET_CODE (PATTERN (i2)) != SET)
351: return 0;
352: i2dest = SET_DEST (PATTERN (i2));
353: i2src = SET_SRC (PATTERN (i2));
354: if (GET_CODE (i2dest) == SUBREG)
355: {
356: i2dest = SUBREG_REG (i2dest);
357: i2src = gen_rtx (SUBREG, GET_MODE (i2dest), i2src, 0);
358: }
359: if (GET_CODE (i2dest) != CC0
360: && (GET_CODE (i2dest) != REG
361: || GET_CODE (i2src) == REG
362: || use_crosses_set_p (i2src, INSN_CUID (i2))))
363: return 0;
364:
365: if (i1 != 0)
366: {
367: if (GET_CODE (PATTERN (i1)) != SET)
368: return 0;
369: i1dest = SET_DEST (PATTERN (i1));
370: i1src = SET_SRC (PATTERN (i1));
371: if (GET_CODE (i1dest) == SUBREG)
372: {
373: i1dest = SUBREG_REG (i1dest);
374: i1src = gen_rtx (SUBREG, GET_MODE (i1dest), i1src, 0);
375: }
376: if (GET_CODE (i1dest) != CC0
377: && (GET_CODE (i1dest) != REG
378: || GET_CODE (i1src) == REG
379: || use_crosses_set_p (i1src, INSN_CUID (i1))))
380: return 0;
381: }
382:
383: /* If I1 or I2 contains an autoincrement or autodecrement,
384: make sure that register is not used between there and I3.
385: Also insist that I3 not be a jump; if it were one
386: and the incremented register were spilled, we would lose. */
387: for (link = REG_NOTES (i2); link; link = XEXP (link, 1))
388: if ((enum reg_note) GET_MODE (link) == REG_INC)
389: if (GET_CODE (i3) == JUMP_INSN
390: || reg_used_between_p (XEXP (link, 0), i2, i3))
391: return 0;
392:
393: if (i1)
394: for (link = REG_NOTES (i1); link; link = XEXP (link, 1))
395: if ((enum reg_note) GET_MODE (link) == REG_INC)
396: if (GET_CODE (i3) == JUMP_INSN
397: || reg_used_between_p (XEXP (link, 0), i1, i3))
398: return 0;
399:
400: /* See if the SETs in i1 or i2 need to be kept around in the merged
401: instruction: whenever the value set there is still needed past i3. */
402: added_sets_2 = (GET_CODE (i2dest) != CC0
403: && ! dead_or_set_p (i3, i2dest));
404: if (i1)
405: added_sets_1 = ! (dead_or_set_p (i3, i1dest)
406: || dead_or_set_p (i2, i1dest));
407:
408: combine_merges++;
409:
410: undobuf.num_undo = 0;
411: undobuf.storage = 0;
412:
413: /* Substitute in the latest insn for the regs set by the earlier ones. */
414:
415: subst_insn = i3;
416: newpat = subst (PATTERN (i3), i2dest, i2src);
417: /* Record whether i2's body now appears within i3's body. */
418: i2_is_used = undobuf.num_undo;
419:
420: if (i1)
421: newpat = subst (newpat, i1dest, i1src);
422:
423: if (GET_CODE (PATTERN (i3)) == SET
424: && SET_DEST (PATTERN (i3)) == cc0_rtx
425: && GET_CODE (SET_SRC (PATTERN (i3))) == AND
426: && next_insn_tests_no_inequality (i3))
427: simplify_set_cc0_and (i3);
428:
429: /* If the actions of the earler insns must be kept
430: in addition to substituting them into the latest one,
431: we must make a new PARALLEL for the latest insn
432: to hold additional the SETs. */
433:
434: if (added_sets_1 || added_sets_2)
435: {
436: combine_extras++;
437:
438: /* Arrange to free later what we allocate now
439: if we don't accept this combination. */
440: if (!undobuf.storage)
441: undobuf.storage = (char *) oballoc (0);
442:
443: if (GET_CODE (newpat) == PARALLEL)
444: {
445: total_sets = XVECLEN (newpat, 0) + added_sets_1 + added_sets_2;
446: newpat = gen_rtx (PARALLEL, VOIDmode,
447: gen_rtvec_v (total_sets,
448: &XVECEXP (newpat, 0, 0)));
449: }
450: else
451: {
452: total_sets = 1 + added_sets_1 + added_sets_2;
453: newpat = gen_rtx (PARALLEL, VOIDmode,
454: gen_rtvec (total_sets, newpat));
455: }
456: if (added_sets_1)
457: {
458: XVECEXP (newpat, 0, --total_sets) = PATTERN (i1);
459: }
460: if (added_sets_2)
461: {
462: /* If there is no I1, use I2's body as is. */
463: if (i1 == 0
464: /* If I2 was stuck into I3, then anything within it has
465: already had I1 substituted into it when that was done to I3. */
466: || i2_is_used)
467: {
468: XVECEXP (newpat, 0, --total_sets) = PATTERN (i2);
469: }
470: else
471: XVECEXP (newpat, 0, --total_sets)
472: = subst (PATTERN (i2), i1dest, i1src);
473: }
474: }
475:
476: /* Is the result of combination a valid instruction? */
477: insn_code_number = recog (newpat, i3);
478:
479: if (insn_code_number >= 0)
480: {
481: /* Yes. Install it. */
482: register int regno;
483: INSN_CODE (i3) = insn_code_number;
484: PATTERN (i3) = newpat;
485: /* Most REGs that previously died in I2 now die in I3. */
486: move_deaths (i2src, INSN_CUID (i2), i3);
487: if (GET_CODE (i2dest) == REG)
488: {
489: /* If the reg formerly set in I2 died only once and that was in I3,
490: zero its use count so it won't make `reload' do any work. */
491: regno = REGNO (i2dest);
492: if (! added_sets_2)
493: reg_n_sets[regno]--;
494: if (reg_n_sets[regno] == 0 && regno_dead_p (regno, i3))
495: reg_n_refs[regno] = 0;
496: /* If a ref to REGNO was substituted into I3 from I2,
497: then it still dies there if it previously did.
498: Otherwise either REGNO never did die in I3 so remove_death is safe
499: or this entire life of REGNO is gone so remove its death. */
500: if (!added_sets_2
501: && ! reg_mentioned_p (i2dest, PATTERN (i3)))
502: remove_death (regno, i3);
503: }
504: /* The data flowing into I2 now flows into I3.
505: But we cannot always move I2's LOG_LINKS into I3,
506: since they must go to a setting of a REG from the
507: first use following. If I2 was the first use following a set,
508: I3 is now a use, but it is not the first use
509: if some instruction between I2 and I3 is also a use.
510: Here, for simplicity, we move the links only if
511: there are no real insns between I2 and I3. */
512: if (adjacent_insns_p (i2, i3))
513: add_links (i3, LOG_LINKS (i2));
514: /* Any registers previously autoincremented in I2
515: are now incremented in I3. */
516: add_incs (i3, REG_NOTES (i2));
517: /* Get rid of I2. */
518: LOG_LINKS (i2) = 0;
519: PUT_CODE (i2, NOTE);
520: NOTE_LINE_NUMBER (i2) = NOTE_INSN_DELETED;
521: NOTE_SOURCE_FILE (i2) = 0;
522: if (i1)
523: {
524: /* Likewise, merge the info from I1 and get rid of it. */
525: move_deaths (i1src, INSN_CUID (i1), i3);
526: if (GET_CODE (i1dest) == REG)
527: {
528: regno = REGNO (i1dest);
529: if (! added_sets_1)
530: reg_n_sets[regno]--;
531: if (reg_n_sets[regno] == 0 && regno_dead_p (regno, i3))
532: reg_n_refs[regno] = 0;
533: /* If a ref to REGNO was substituted into I3 from I1,
534: then it still dies there if it previously did.
535: Else either REGNO never did die in I3 so remove_death is safe
536: or this entire life of REGNO is gone so remove its death. */
537: if (! added_sets_1
538: && ! reg_mentioned_p (i1dest, PATTERN (i3)))
539: remove_death (regno, i3);
540: }
541: if (adjacent_insns_p (i2, i3))
542: add_links (i3, LOG_LINKS (i1));
543: add_incs (i3, REG_NOTES (i1));
544: LOG_LINKS (i1) = 0;
545: PUT_CODE (i1, NOTE);
546: NOTE_LINE_NUMBER (i1) = NOTE_INSN_DELETED;
547: NOTE_SOURCE_FILE (i1) = 0;
548: }
549:
550: combine_successes++;
551: return 1;
552: }
553:
554: /* Failure: change I3 back the way it was. */
555: undo_all ();
556:
557: return 0;
558: }
559:
560: /* Undo all the modifications recorded in undobuf. */
561:
562: static void
563: undo_all ()
564: {
565: register int i;
566: if (undobuf.num_undo > MAX_UNDO)
567: undobuf.num_undo = MAX_UNDO;
568: for (i = undobuf.num_undo - 1; i >= 0; i--)
569: *undobuf.undo[i].where = undobuf.undo[i].old_contents;
570: if (undobuf.storage)
571: obfree (undobuf.storage);
572: undobuf.num_undo = 0;
573: undobuf.storage = 0;
574: }
575:
576: /* Throughout X, replace FROM with TO, and return the result.
577: The result is TO if X is FROM;
578: otherwise the result is X, but its contents may have been modified.
579: If they were modified, a record was made in undobuf so that
580: undo_all will (among other things) return X to its original state.
581:
582: If the number of changes necessary is too much to record to undo,
583: the excess changes are not made, so the result is invalid.
584: The changes already made can still be undone.
585: undobuf.num_undo is incremented for such changes, so by testing that
586: the caller can tell whether the result is valid. */
587:
588: static rtx
589: subst (x, from, to)
590: register rtx x, from, to;
591: {
592: register char *fmt;
593: register int len, i;
594: register enum rtx_code code;
595:
596: /* THIS_TO is used to replace FROM if it appears exactly one
597: level down in X. Simplifications often work by changing
598: THIS_TO after observing that FROM appears in a specific way
599: one level down in X. Since only THIS_TO is changed, and TO
600: is left alone, further occurrences of FROM within the operands
601: of X are replaced normally. */
602: rtx this_to;
603:
604: if (x == from)
605: return to;
606:
607: code = GET_CODE (x);
608: this_to = to;
609:
610: /* A little bit of algebraic simplification here. */
611: switch (code)
612: {
613: /* This case has no effect except to speed things up. */
614: case REG:
615: case CONST_INT:
616: case CONST:
617: case SYMBOL_REF:
618: case LABEL_REF:
619: case PC:
620: case CC0:
621: return x;
622:
623: case NOT:
624: case NEG:
625: /* Don't let substitution introduce double-negatives. */
626: if (XEXP (x, 0) == from
627: && GET_CODE (to) == code)
628: return XEXP (to, 0);
629: break;
630:
631: case PLUS:
632: /* In (plus <foo> (ashift <bar> <n>))
633: change the shift to a multiply so we can recognize
634: scaled indexed addresses. */
635: if ((XEXP (x, 0) == from
636: || XEXP (x, 1) == from)
637: && GET_CODE (to) == ASHIFT
638: && GET_CODE (XEXP (to, 1)) == CONST_INT)
639: {
640: if (!undobuf.storage)
641: undobuf.storage = (char *) oballoc (0);
642: this_to = gen_rtx (MULT, GET_MODE (to),
643: XEXP (to, 0),
644: gen_rtx (CONST_INT, VOIDmode,
645: 1 << INTVAL (XEXP (to, 1))));
646: }
647: /* If we have something (putative index) being added to a sum,
648: associate it so that any constant term is outermost.
649: That's because that's the way indexed addresses are
650: now supposed to appear. */
651: if (((XEXP (x, 0) == from && GET_CODE (XEXP (x, 1)) == PLUS)
652: || (XEXP (x, 1) == from && GET_CODE (XEXP (x, 0)) == PLUS))
653: ||
654: ((XEXP (x, 0) == from || XEXP (x, 1) == from)
655: && GET_CODE (this_to) == PLUS))
656: {
657: rtx offset = 0, base, index;
658: if (GET_CODE (this_to) != PLUS)
659: {
660: index = this_to;
661: base = XEXP (x, 0) == from ? XEXP (x, 1) : XEXP (x, 0);
662: }
663: else
664: {
665: index = XEXP (x, 0) == from ? XEXP (x, 1) : XEXP (x, 0);
666: base = this_to;
667: }
668: if (CONSTANT_ADDRESS_P (XEXP (base, 0)))
669: {
670: offset = XEXP (base, 0);
671: base = XEXP (base, 1);
672: }
673: else if (CONSTANT_ADDRESS_P (XEXP (base, 1)))
674: {
675: offset = XEXP (base, 1);
676: base = XEXP (base, 0);
677: }
678: if (offset != 0)
679: {
680: if (!undobuf.storage)
681: undobuf.storage = (char *) oballoc (0);
682: return gen_rtx (PLUS, GET_MODE (index), offset,
683: gen_rtx (PLUS, GET_MODE (index),
684: index, base));
685: }
686: }
687: break;
688:
689: case MINUS:
690: /* Can simplify (minus:VOIDmode (zero/sign_extend FOO) CONST)
691: (which is a compare instruction, not a subtract instruction)
692: to (minus FOO CONST) if CONST fits in FOO's mode
693: and we are only testing equality.
694: In fact, this is valid for zero_extend if what follows is an
695: unsigned comparison, and for sign_extend with a signed comparison. */
696: if (GET_MODE (x) == VOIDmode
697: && XEXP (x, 0) == from
698: && (GET_CODE (to) == ZERO_EXTEND || GET_CODE (to) == SIGN_EXTEND)
699: && next_insn_tests_no_inequality (subst_insn)
700: && GET_CODE (XEXP (x, 1)) == CONST_INT
701: && ((unsigned) INTVAL (XEXP (x, 1))
702: < (1 << (BITS_PER_UNIT * GET_MODE_SIZE (GET_MODE (XEXP (to, 0)))))))
703: this_to = XEXP (to, 0);
704: break;
705:
706: case EQ:
707: case NE:
708: /* If comparing a subreg against zero, discard the subreg. */
709: if (XEXP (x, 0) == from
710: && GET_CODE (to) == SUBREG
711: && SUBREG_WORD (to) == 0
712: && XEXP (x, 1) == const0_rtx)
713: this_to = SUBREG_REG (to);
714:
715: /* If comparing a ZERO_EXTRACT against zero,
716: canonicalize to a SIGN_EXTRACT,
717: since the two are equivalent here. */
718: if (XEXP (x, 0) == from
719: && GET_CODE (this_to) == ZERO_EXTRACT
720: && XEXP (x, 1) == const0_rtx)
721: {
722: if (!undobuf.storage)
723: undobuf.storage = (char *) oballoc (0);
724: this_to = gen_rtx (SIGN_EXTRACT, GET_MODE (this_to),
725: XEXP (this_to, 0), XEXP (this_to, 1),
726: XEXP (this_to, 2));
727: }
728: /* If we are putting (ASHIFT 1 x) into (EQ (AND ... y) 0),
729: arrange to return (EQ (SIGN_EXTRACT y 1 x) 0),
730: which is what jump-on-bit instructions are written with. */
731: else if (XEXP (x, 1) == const0_rtx
732: && GET_CODE (XEXP (x, 0)) == AND
733: && (XEXP (XEXP (x, 0), 0) == from
734: || XEXP (XEXP (x, 0), 1) == from)
735: && GET_CODE (this_to) == ASHIFT
736: && XEXP (this_to, 0) == const1_rtx)
737: {
738: register rtx y = XEXP (XEXP (x, 0),
739: XEXP (XEXP (x, 0), 0) == from);
740: if (!undobuf.storage)
741: undobuf.storage = (char *) oballoc (0);
742: this_to = gen_rtx (SIGN_EXTRACT, GET_MODE (this_to),
743: y,
744: const1_rtx, XEXP (this_to, 1));
745: from = XEXP (x, 0);
746: }
747:
748: break;
749:
750: case ZERO_EXTEND:
751: if (XEXP (x, 0) == from
752: && GET_CODE (to) == ZERO_EXTEND)
753: this_to = XEXP (to, 0);
754: /* Zero-extending the result of an and with a constant can be done
755: with a wider and. */
756: if (XEXP (x, 0) == from
757: && GET_CODE (to) == AND
758: && GET_CODE (XEXP (to, 1)) == CONST_INT
759: && (GET_CODE (XEXP (to, 0)) == REG
760: || offsetable_address_p (XEXP (to, 0)))
761: /* Avoid getting wrong result if the constant has high bits set
762: that are irrelevant in the narrow mode where it is being used. */
763: && ((INTVAL (XEXP (to, 1))
764: & (-1 << (GET_MODE_SIZE (GET_MODE (to)) * BITS_PER_UNIT)))
765: == 0))
766: {
767: if (!undobuf.storage)
768: undobuf.storage = (char *) oballoc (0);
769: return gen_rtx (AND, GET_MODE (x),
770: gen_lowpart (GET_MODE (x), XEXP (to, 0)),
771: XEXP (to, 1));
772: }
773: break;
774:
775: case SIGN_EXTEND:
776: if (XEXP (x, 0) == from
777: && GET_CODE (to) == SIGN_EXTEND)
778: this_to = XEXP (to, 0);
779: /* Sign-extending the result of an and with a constant can be done
780: with a wider and, provided the high bit of the constant is 0. */
781: if (XEXP (x, 0) == from
782: && GET_CODE (to) == AND
783: && GET_CODE (XEXP (to, 1)) == CONST_INT
784: && (GET_CODE (XEXP (to, 0)) == REG
785: || offsetable_address_p (XEXP (to, 0)))
786: && ((INTVAL (XEXP (to, 1))
787: & (-1 << (GET_MODE_SIZE (GET_MODE (to)) * BITS_PER_UNIT - 1)))
788: == 0))
789: {
790: if (!undobuf.storage)
791: undobuf.storage = (char *) oballoc (0);
792: return gen_rtx (AND, GET_MODE (x),
793: gen_lowpart (GET_MODE (x), XEXP (to, 0)),
794: XEXP (to, 1));
795: }
796: break;
797:
798: case SET:
799: /* In (set (zero-extract <x> <1> <y>) (and <foo> <1>))
800: the `and' can be deleted. This can happen when storing a bit
801: that came from a set-flag insn followed by masking to one bit.
802: There is probably no need to optimize other field widths similarly
803: because on machines with bit-field insns `and' is not needed
804: to extract the fields. */
805: if (GET_CODE (XEXP (x, 0)) == ZERO_EXTRACT
806: && XEXP (XEXP (x, 0), 1) == const1_rtx
807: && XEXP (x, 1) == from
808: && GET_CODE (to) == AND
809: && XEXP (to, 1) == const1_rtx)
810: {
811: this_to = XEXP (to, 0);
812: }
813: break;
814:
815: case AND:
816: if (GET_CODE (XEXP (x, 1)) == CONST_INT)
817: {
818: rtx tem = simplify_and_const_int (x, from, to);
819: if (tem)
820: return tem;
821: }
822: break;
823:
824: case FLOAT:
825: /* (float (sign_extend <X>)) = (float <X>). */
826: if (XEXP (x, 0) == from
827: && GET_CODE (to) == SIGN_EXTEND)
828: this_to = XEXP (to, 0);
829: break;
830:
831: case ZERO_EXTRACT:
832: /* Extracting a single bit from the result of a shift:
833: see which bit it was before the shift and extract that directly. */
834: if (XEXP (x, 0) == from
835: && (GET_CODE (to) == ASHIFTRT || GET_CODE (to) == LSHIFTRT
836: || GET_CODE (to) == ASHIFT || GET_CODE (to) == LSHIFT)
837: && GET_CODE (XEXP (to, 1)) == CONST_INT
838: && XEXP (x, 1) == const1_rtx
839: && GET_CODE (XEXP (x, 2)) == CONST_INT)
840: {
841: int shift = INTVAL (XEXP (to, 1));
842: int newpos;
843: if (GET_CODE (to) == ASHIFT || GET_CODE (to) == LSHIFT)
844: shift = - shift;
845: #ifdef BITS_BIG_ENDIAN
846: shift = - shift;
847: #endif
848: newpos = INTVAL (XEXP (x, 2)) + shift;
849: if (newpos >= 0 &&
850: newpos < BITS_PER_UNIT * GET_MODE_SIZE (GET_MODE (from)))
851: {
852: if (!undobuf.storage)
853: undobuf.storage = (char *) oballoc (0);
854: return gen_rtx (ZERO_EXTRACT, GET_MODE (x),
855: XEXP (to, 0), const1_rtx,
856: gen_rtx (CONST_INT, VOIDmode, newpos));
857: }
858: }
859: break;
860:
861: case LSHIFTRT:
862: case ASHIFTRT:
863: case ROTATE:
864: case ROTATERT:
865: #ifdef SHIFT_COUNT_TRUNCATED
866: /* (lshift <X> (sign_extend <Y>)) = (lshift <X> <Y>) (most machines).
867: True for all kinds of shifts and also for zero_extend. */
868: if (XEXP (x, 1) == from
869: && (GET_CODE (to) == SIGN_EXTEND
870: || GET_CODE (to) == ZERO_EXTEND))
871: {
872: if (!undobuf.storage)
873: undobuf.storage = (char *) oballoc (0);
874: this_to = gen_rtx (SUBREG, GET_MODE (to), XEXP (to, 0), 0);
875: }
876: #endif
877: /* Two shifts in a row of same kind
878: in same direction with constant counts
879: may be combined. */
880: if (XEXP (x, 0) == from
881: && GET_CODE (to) == GET_CODE (x)
882: && GET_CODE (XEXP (x, 1)) == CONST_INT
883: && GET_CODE (XEXP (to, 1)) == CONST_INT
884: && INTVAL (XEXP (to, 1)) > 0
885: && INTVAL (XEXP (x, 1)) > 0
886: && (INTVAL (XEXP (x, 1)) + INTVAL (XEXP (to, 1))
887: < BITS_PER_UNIT * GET_MODE_SIZE (GET_MODE (x))))
888: {
889: if (!undobuf.storage)
890: undobuf.storage = (char *) oballoc (0);
891: return gen_rtx (GET_CODE (x), GET_MODE (x),
892: XEXP (to, 0),
893: gen_rtx (CONST_INT, VOIDmode,
894: INTVAL (XEXP (x, 1))
895: + INTVAL (XEXP (to, 1))));
896: }
897: break;
898:
899: case LSHIFT:
900: case ASHIFT:
901: #ifdef SHIFT_COUNT_TRUNCATED
902: /* (lshift <X> (sign_extend <Y>)) = (lshift <X> <Y>) (most machines).
903: True for all kinds of shifts and also for zero_extend. */
904: if (XEXP (x, 1) == from
905: && (GET_CODE (to) == SIGN_EXTEND
906: || GET_CODE (to) == ZERO_EXTEND))
907: {
908: if (!undobuf.storage)
909: undobuf.storage = (char *) oballoc (0);
910: this_to = gen_rtx (SUBREG, GET_MODE (to), XEXP (to, 0), 0);
911: }
912: #endif
913: /* (lshift (and (lshiftrt <foo> <X>) <Y>) <X>)
914: happens copying between bit fields in similar structures.
915: It can be replaced by one and instruction.
916: It does not matter whether the shifts are logical or arithmetic. */
917: if (GET_CODE (XEXP (x, 0)) == AND
918: && GET_CODE (XEXP (x, 1)) == CONST_INT
919: && INTVAL (XEXP (x, 1)) > 0
920: && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
921: && XEXP (XEXP (x, 0), 0) == from
922: && (GET_CODE (to) == LSHIFTRT
923: || GET_CODE (to) == ASHIFTRT)
924: #if 0
925: /* I now believe this restriction is unnecessary.
926: The outer shift will discard those bits in any case, right? */
927:
928: /* If inner shift is arithmetic, either it shifts left or
929: the bits it shifts the sign into are zeroed by the and. */
930: && (INTVAL (XEXP (x, 1)) < 0
931: || ((unsigned) INTVAL (XEXP (XEXP (x, 0), 1))
932: < 1 << (GET_MODE_BITSIZE (GET_MODE (x))
933: - INTVAL (XEXP (x, 0)))))
934: #endif
935: && GET_CODE (XEXP (to, 1)) == CONST_INT
936: && INTVAL (XEXP (x, 1)) == INTVAL (XEXP (to, 1)))
937: {
938: if (!undobuf.storage)
939: undobuf.storage = (char *) oballoc (0);
940: /* The constant in the new `and' is <Y> << <X>
941: but clear out all bits that don't belong in our mode. */
942: return gen_rtx (AND, GET_MODE (x), XEXP (to, 0),
943: gen_rtx (CONST_INT, VOIDmode,
944: (GET_MODE_MASK (GET_MODE (x))
945: & ((GET_MODE_MASK (GET_MODE (x))
946: & INTVAL (XEXP (XEXP (x, 0), 1)))
947: << INTVAL (XEXP (x, 1))))));
948: }
949: /* Two shifts in a row in same direction with constant counts
950: may be combined. */
951: if (XEXP (x, 0) == from
952: && (GET_CODE (to) == ASHIFT || GET_CODE (to) == LSHIFT)
953: && GET_CODE (XEXP (x, 1)) == CONST_INT
954: && GET_CODE (XEXP (to, 1)) == CONST_INT
955: && INTVAL (XEXP (to, 1)) > 0
956: && INTVAL (XEXP (x, 1)) > 0
957: && (INTVAL (XEXP (x, 1)) + INTVAL (XEXP (to, 1))
958: < BITS_PER_UNIT * GET_MODE_SIZE (GET_MODE (x))))
959: {
960: if (!undobuf.storage)
961: undobuf.storage = (char *) oballoc (0);
962: return gen_rtx (GET_CODE (x), GET_MODE (x),
963: XEXP (to, 0),
964: gen_rtx (CONST_INT, VOIDmode,
965: INTVAL (XEXP (x, 1))
966: + INTVAL (XEXP (to, 1))));
967: }
968: /* (ashift (ashiftrt <foo> <X>) <X>)
969: (or, on some machines, (ashift (ashift <foo> <-X>) <X>) instead)
970: happens if you divide by 2**N and then multiply by 2**N.
971: It can be replaced by one `and' instruction.
972: It does not matter whether the shifts are logical or arithmetic. */
973: if (GET_CODE (XEXP (x, 1)) == CONST_INT
974: && INTVAL (XEXP (x, 1)) > 0
975: && XEXP (x, 0) == from
976: && (((GET_CODE (to) == LSHIFTRT || GET_CODE (to) == ASHIFTRT)
977: && GET_CODE (XEXP (to, 1)) == CONST_INT
978: && INTVAL (XEXP (x, 1)) == INTVAL (XEXP (to, 1)))
979: ||
980: ((GET_CODE (to) == LSHIFT || GET_CODE (to) == ASHIFT)
981: && GET_CODE (XEXP (to, 1)) == CONST_INT
982: && INTVAL (XEXP (x, 1)) == - INTVAL (XEXP (to, 1)))))
983: {
984: if (!undobuf.storage)
985: undobuf.storage = (char *) oballoc (0);
986: /* The constant in the new `and' is <Y> << <X>
987: but clear out all bits that don't belong in our mode. */
988: return gen_rtx (AND, GET_MODE (x), XEXP (to, 0),
989: gen_rtx (CONST_INT, VOIDmode,
990: (GET_MODE_MASK (GET_MODE (x))
991: & (GET_MODE_MASK (GET_MODE (x))
992: << INTVAL (XEXP (x, 1))))));
993: }
994:
995: }
996:
997: len = GET_RTX_LENGTH (code);
998: fmt = GET_RTX_FORMAT (code);
999:
1000: /* Don't replace FROM where it is being stored in rather than used. */
1001: if (code == SET && SET_DEST (x) == from)
1002: fmt = "ie";
1003:
1004: for (i = 0; i < len; i++)
1005: {
1006: if (fmt[i] == 'E')
1007: {
1008: register int j;
1009: for (j = XVECLEN (x, i) - 1; j >= 0; j--)
1010: {
1011: register rtx new;
1012: if (XVECEXP (x, i, j) == from)
1013: new = this_to;
1014: else
1015: new = subst (XVECEXP (x, i, j), from, to);
1016: if (new != XVECEXP (x, i, j))
1017: {
1018: if (undobuf.num_undo < MAX_UNDO)
1019: {
1020: undobuf.undo[undobuf.num_undo].where = &XVECEXP (x, i, j);
1021: undobuf.undo[undobuf.num_undo].old_contents = XVECEXP (x, i, j);
1022: XVECEXP (x, i, j) = new;
1023: }
1024: undobuf.num_undo++;
1025: }
1026: }
1027: }
1028: else if (fmt[i] == 'e')
1029: {
1030: register rtx new;
1031:
1032: if (XEXP (x, i) == from)
1033: new = this_to;
1034: else
1035: new = subst (XEXP (x, i), from, to);
1036:
1037: if (new != XEXP (x, i))
1038: {
1039: if (undobuf.num_undo < MAX_UNDO)
1040: {
1041: undobuf.undo[undobuf.num_undo].where = &XEXP (x, i);
1042: undobuf.undo[undobuf.num_undo].old_contents = XEXP (x, i);
1043: XEXP (x, i) = new;
1044: }
1045: undobuf.num_undo++;
1046: }
1047: }
1048: }
1049: return x;
1050: }
1051:
1052: /* This is the AND case of the function subst. */
1053:
1054: static rtx
1055: simplify_and_const_int (x, from, to)
1056: rtx x, from, to;
1057: {
1058: register rtx varop = XEXP (x, 0);
1059: register int constop = INTVAL (XEXP (x, 1));
1060:
1061: /* (and (subreg (and <foo> <constant>) 0) <constant>)
1062: results from an andsi followed by an andqi,
1063: which happens frequently when storing bit-fields
1064: on something whose result comes from an andsi. */
1065: if (GET_CODE (varop) == SUBREG
1066: && XEXP (varop, 0) == from
1067: && subreg_lowpart_p (varop)
1068: && GET_CODE (to) == AND
1069: && GET_CODE (XEXP (to, 1)) == CONST_INT
1070: /* Verify that the result of the outer `and'
1071: is not affected by any bits not defined in the inner `and'.
1072: True if the outer mode is narrower, or if the outer constant
1073: masks to zero all the bits that the inner mode doesn't have. */
1074: && (GET_MODE_SIZE (GET_MODE (x)) < GET_MODE_SIZE (GET_MODE (from))
1075: || constop & (-1 << (BITS_PER_UNIT * GET_MODE_SIZE (GET_MODE (from)))) == 0))
1076: {
1077: if (!undobuf.storage)
1078: undobuf.storage = (char *) oballoc (0);
1079: return gen_rtx (AND, GET_MODE (x),
1080: gen_lowpart (GET_MODE (x), XEXP (to, 0)),
1081: gen_rtx (CONST_INT, VOIDmode,
1082: constop
1083: /* Remember that the bits outside that mode
1084: are not being changed, so the effect
1085: is as if they were all 1. */
1086: & INTVAL (XEXP (to, 1))));
1087: }
1088: /* (and (zero_extend <foo>) <constant>)
1089: often results from storing in a bit-field something
1090: that was calculated as a short. Replace with a single `and'
1091: in whose constant all bits not in <foo>'s mode are zero. */
1092: if (varop == from
1093: && GET_CODE (to) == ZERO_EXTEND)
1094: {
1095: if (!undobuf.storage)
1096: undobuf.storage = (char *) oballoc (0);
1097: return gen_rtx (AND, GET_MODE (x),
1098: gen_rtx (SUBREG, GET_MODE (x),
1099: XEXP (to, 0), 0),
1100: gen_rtx (CONST_INT, VOIDmode,
1101: constop
1102: & ((1 << (BITS_PER_UNIT * GET_MODE_SIZE (GET_MODE (XEXP (to, 0))))) - 1)));
1103: }
1104: /* (and (sign_extend <foo>) <constant>)
1105: can be replaced with (and (subreg <foo>) <constant>)
1106: if <constant> is narrower than <foo>'s mode,
1107: or with (zero_extend <foo>) if <constant> is a mask for that mode. */
1108: if (varop == from
1109: && GET_CODE (to) == SIGN_EXTEND
1110: && ((unsigned) constop
1111: <= ((1 << (BITS_PER_UNIT
1112: * GET_MODE_SIZE (GET_MODE (XEXP (to, 0)))))
1113: - 1)))
1114: {
1115: if (!undobuf.storage)
1116: undobuf.storage = (char *) oballoc (0);
1117: if (constop == ((1 << (BITS_PER_UNIT
1118: * GET_MODE_SIZE (GET_MODE (XEXP (to, 0)))))
1119: - 1))
1120: return gen_rtx (ZERO_EXTEND, GET_MODE (x), XEXP (to, 0));
1121: return gen_rtx (AND, GET_MODE (x),
1122: gen_rtx (SUBREG, GET_MODE (x),
1123: XEXP (to, 0), 0),
1124: XEXP (x, 1));
1125: }
1126: /* (and (and <foo> <constant>) <constant>)
1127: comes from two and instructions in a row. */
1128: if (varop == from
1129: && GET_CODE (to) == AND
1130: && GET_CODE (XEXP (to, 1)) == CONST_INT)
1131: {
1132: if (!undobuf.storage)
1133: undobuf.storage = (char *) oballoc (0);
1134: return gen_rtx (AND, GET_MODE (x),
1135: XEXP (to, 0),
1136: gen_rtx (CONST_INT, VOIDmode,
1137: constop
1138: & INTVAL (XEXP (to, 1))));
1139: }
1140: /* (and (ashiftrt (ashift FOO N) N) CONST)
1141: may be simplified to (and FOO CONST) if CONST masks off the bits
1142: changed by the two shifts. */
1143: if (GET_CODE (varop) == ASHIFTRT
1144: && GET_CODE (XEXP (varop, 1)) == CONST_INT
1145: && XEXP (varop, 0) == from
1146: && GET_CODE (to) == ASHIFT
1147: && GET_CODE (XEXP (to, 1)) == CONST_INT
1148: && INTVAL (XEXP (varop, 1)) == INTVAL (XEXP (to, 1))
1149: && ((unsigned) constop >> INTVAL (XEXP (varop, 1))) == 0)
1150: {
1151: if (!undobuf.storage)
1152: undobuf.storage = (char *) oballoc (0);
1153: /* If CONST is a mask for the low byte,
1154: change this into a zero-extend instruction
1155: from just the low byte of FOO. */
1156: if (constop == (1 << BITS_PER_UNIT) - 1)
1157: {
1158: rtx temp = gen_lowpart_for_combine (QImode, XEXP (to, 0));
1159: if (temp)
1160: return gen_rtx (ZERO_EXTEND, GET_MODE (x), temp);
1161: }
1162: return gen_rtx (AND, GET_MODE (x),
1163: XEXP (to, 0), XEXP (x, 1));
1164: }
1165:
1166: /* No simplification applies. */
1167: return 0;
1168: }
1169:
1170: /* Like gen_lowpart but for use by combine. In combine it is not possible
1171: to create any new pseudoregs. However, it is safe to create
1172: invalid memory addresses, because combine will try to recognize
1173: them and all they will do is make the combine attempt fail.
1174:
1175: Also, return zero if we don't see a way to make a lowpart. */
1176:
1177: static rtx
1178: gen_lowpart_for_combine (mode, x)
1179: enum machine_mode mode;
1180: register rtx x;
1181: {
1182: if (GET_CODE (x) == SUBREG || GET_CODE (x) == REG)
1183: return gen_lowpart (mode, x);
1184: if (GET_MODE (x) == mode)
1185: return 0;
1186: if (GET_CODE (x) == VOLATILE)
1187: return 0;
1188: if (GET_CODE (x) == MEM)
1189: {
1190: register int offset = 0;
1191: #ifdef WORDS_BIG_ENDIAN
1192: offset = (max (GET_MODE_SIZE (GET_MODE (x)), UNITS_PER_WORD)
1193: - max (GET_MODE_SIZE (mode), UNITS_PER_WORD));
1194: #endif
1195: #ifdef BYTES_BIG_ENDIAN
1196: if (GET_MODE_SIZE (mode) < UNITS_PER_WORD)
1197: offset -= (GET_MODE_SIZE (mode)
1198: - min (UNITS_PER_WORD,
1199: GET_MODE_SIZE (GET_MODE (x))));
1200: #endif
1201: return gen_rtx (MEM, mode, plus_constant (XEXP (x, 0),
1202: offset));
1203: }
1204: else
1205: return 0;
1206: }
1207:
1208: /* After substitution, if the resulting pattern looks like
1209: (set (cc0) (and ...)), this function is called to simplify the
1210: pattern into a bit-field operation if possible. */
1211:
1212: static void
1213: simplify_set_cc0_and (insn)
1214: rtx insn;
1215: {
1216: register rtx value = XEXP (PATTERN (insn), 1);
1217: register rtx op0 = XEXP (value, 0);
1218: register rtx op1 = XEXP (value, 1);
1219: int offset = 0;
1220: rtx var = 0;
1221: rtx bitnum = 0;
1222: int temp;
1223: int unit;
1224:
1225: /* Look for a constant power of 2 or a shifted 1
1226: on either side of the AND. Set VAR to the other side.
1227: Set BITNUM to the shift count of the 1 (as an rtx).
1228: Or, if bit number is constant, set OFFSET to the bit number. */
1229:
1230: switch (GET_CODE (op0))
1231: {
1232: case CONST_INT:
1233: temp = exact_log2 (INTVAL (op0));
1234: if (temp < 0)
1235: return;
1236: offset = temp;
1237: var = op1;
1238: break;
1239:
1240: case ASHIFT:
1241: case LSHIFT:
1242: if (XEXP (op0, 0) == const1_rtx)
1243: {
1244: bitnum = XEXP (op0, 1);
1245: var = op1;
1246: }
1247: }
1248: if (var == 0)
1249: switch (GET_CODE (op1))
1250: {
1251: case CONST_INT:
1252: temp = exact_log2 (INTVAL (op1));
1253: if (temp < 0)
1254: return;
1255: offset = temp;
1256: var = op0;
1257: break;
1258:
1259: case ASHIFT:
1260: case LSHIFT:
1261: if (XEXP (op1, 0) == const1_rtx)
1262: {
1263: bitnum = XEXP (op1, 1);
1264: var = op0;
1265: }
1266: }
1267:
1268: /* If VAR is 0, we didn't find something recognizable. */
1269: if (var == 0)
1270: return;
1271:
1272: if (!undobuf.storage)
1273: undobuf.storage = (char *) oballoc (0);
1274:
1275: /* If the bit position is currently exactly 0,
1276: extract a right-shift from the variable portion. */
1277: if (offset == 0
1278: && (GET_CODE (var) == ASHIFTRT || GET_CODE (var) == LSHIFTRT))
1279: {
1280: bitnum = XEXP (var, 1);
1281: var = XEXP (var, 0);
1282: }
1283:
1284: #ifdef BITS_BIG_ENDIAN
1285: unit = GET_MODE_SIZE (GET_MODE (var)) * BITS_PER_UNIT - 1;
1286:
1287: if (bitnum != 0)
1288: bitnum = gen_rtx (MINUS, SImode,
1289: gen_rtx (CONST_INT, VOIDmode, unit), bitnum);
1290: else
1291: offset = unit - offset;
1292: #endif
1293:
1294: if (bitnum == 0)
1295: bitnum = gen_rtx (CONST_INT, VOIDmode, offset);
1296:
1297: if (GET_CODE (var) == SUBREG && SUBREG_WORD (var) == 0)
1298: var = SUBREG_REG (var);
1299:
1300: if (undobuf.num_undo < MAX_UNDO)
1301: {
1302: undobuf.undo[undobuf.num_undo].where = &XEXP (PATTERN (insn), 1);
1303: undobuf.undo[undobuf.num_undo].old_contents = value;
1304: XEXP (PATTERN (insn), 1)
1305: = gen_rtx (ZERO_EXTRACT, VOIDmode, var, const1_rtx, bitnum);
1306: }
1307: undobuf.num_undo++;
1308: }
1309:
1310: /* Update the records of when each REG was most recently set or killed
1311: for the things done by INSN. This is the last thing done in processing
1312: INSN in the combiner loop.
1313:
1314: We update reg_last_set, reg_last_death, and also the similar information
1315: mem_last_set (which insn most recently modified memory)
1316: and last_call_cuid (which insn was the most recent subroutine call). */
1317:
1318: static void
1319: record_dead_and_set_regs (insn)
1320: rtx insn;
1321: {
1322: register rtx link;
1323: for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
1324: {
1325: if ((enum reg_note) GET_MODE (link) == REG_DEAD)
1326: reg_last_death[REGNO (XEXP (link, 0))] = insn;
1327: else if ((enum reg_note) GET_MODE (link) == REG_INC)
1328: reg_last_set[REGNO (XEXP (link, 0))] = insn;
1329: }
1330:
1331: if (GET_CODE (insn) == CALL_INSN)
1332: last_call_cuid = mem_last_set = INSN_CUID (insn);
1333:
1334: if (GET_CODE (PATTERN (insn)) == PARALLEL)
1335: {
1336: register int i;
1337: for (i = XVECLEN (PATTERN (insn), 0) - 1; i >= 0; i--)
1338: {
1339: register rtx elt = XVECEXP (PATTERN (insn), 0, i);
1340: register enum rtx_code code = GET_CODE (elt);
1341: if (code == SET || code == CLOBBER)
1342: {
1343: if (GET_CODE (XEXP (elt, 0)) == REG)
1344: reg_last_set[REGNO (XEXP (elt, 0))] = insn;
1345: else if (GET_CODE (XEXP (elt, 0)) == MEM)
1346: mem_last_set = INSN_CUID (insn);
1347: }
1348: }
1349: }
1350: else if (GET_CODE (PATTERN (insn)) == SET
1351: || GET_CODE (PATTERN (insn)) == CLOBBER)
1352: {
1353: register rtx x = XEXP (PATTERN (insn), 0);
1354: if (GET_CODE (x) == REG)
1355: reg_last_set[REGNO (x)] = insn;
1356: else if (GET_CODE (x) == MEM)
1357: mem_last_set = INSN_CUID (insn);
1358: }
1359: }
1360:
1361: /* Return nonzero if expression X refers to a REG or to memory
1362: that is set in an instruction more recent than FROM_CUID. */
1363:
1364: static int
1365: use_crosses_set_p (x, from_cuid)
1366: register rtx x;
1367: int from_cuid;
1368: {
1369: register char *fmt;
1370: register int i;
1371: register enum rtx_code code = GET_CODE (x);
1372:
1373: if (code == REG)
1374: {
1375: register int regno = REGNO (x);
1376: return (reg_last_set[regno]
1377: && INSN_CUID (reg_last_set[regno]) > from_cuid);
1378: }
1379:
1380: if (code == MEM && mem_last_set > from_cuid)
1381: return 1;
1382:
1383: fmt = GET_RTX_FORMAT (code);
1384:
1385: for (i = GET_RTX_LENGTH (code); i >= 0; i--)
1386: {
1387: if (fmt[i] == 'E')
1388: {
1389: register int j;
1390: for (j = XVECLEN (x, i) - 1; j >= 0; j--)
1391: if (use_crosses_set_p (XVECEXP (x, i, j), from_cuid))
1392: return 1;
1393: }
1394: else if (fmt[i] == 'e'
1395: && use_crosses_set_p (XEXP (x, i), from_cuid))
1396: return 1;
1397: }
1398: return 0;
1399: }
1400:
1401: /* Return nonzero if reg REGNO is marked as dying in INSN. */
1402:
1403: int
1404: regno_dead_p (regno, insn)
1405: int regno;
1406: rtx insn;
1407: {
1408: register rtx link;
1409:
1410: for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
1411: if (REGNO (XEXP (link, 0)) == regno
1412: && ((enum reg_note) GET_MODE (link) == REG_DEAD
1413: || (enum reg_note) GET_MODE (link) == REG_INC))
1414: return 1;
1415:
1416: return 0;
1417: }
1418:
1419: /* Remove register number REGNO from the dead registers list of INSN. */
1420:
1421: static void
1422: remove_death (regno, insn)
1423: int regno;
1424: rtx insn;
1425: {
1426: register rtx link, next;
1427: while ((link = REG_NOTES (insn))
1428: && REGNO (XEXP (link, 0)) == regno
1429: && (enum reg_note) GET_MODE (link) == REG_DEAD)
1430: REG_NOTES (insn) = XEXP (link, 1);
1431:
1432: if (link)
1433: while (next = XEXP (link, 1))
1434: {
1435: if (REGNO (XEXP (next, 0)) == regno
1436: && (enum reg_note) GET_MODE (next) == REG_DEAD)
1437: XEXP (link, 1) = XEXP (next, 1);
1438: else
1439: link = next;
1440: }
1441: }
1442:
1443: /* Return nonzero if J is the first insn following I,
1444: not counting labels, line numbers, etc.
1445: We assume that J follows I. */
1446:
1447: static int
1448: adjacent_insns_p (i, j)
1449: rtx i, j;
1450: {
1451: register rtx insn;
1452: for (insn = NEXT_INSN (i); insn != j; insn = NEXT_INSN (insn))
1453: if (GET_CODE (insn) == INSN
1454: || GET_CODE (insn) == CALL_INSN
1455: || GET_CODE (insn) == JUMP_INSN)
1456: return 0;
1457: return 1;
1458: }
1459:
1460: /* Concatenate the list of logical links LINKS
1461: into INSN's list of logical links.
1462: Modifies LINKS destructively. */
1463:
1464: static void
1465: add_links (insn, links)
1466: rtx insn, links;
1467: {
1468: if (LOG_LINKS (insn) == 0)
1469: LOG_LINKS (insn) = links;
1470: else
1471: {
1472: register rtx next, prev = LOG_LINKS (insn);
1473: while (next = XEXP (prev, 1))
1474: prev = next;
1475: XEXP (prev, 1) = links;
1476: }
1477: }
1478:
1479: /* Concatenate the any elements of the list of reg-notes INCS
1480: which are of type REG_INC
1481: into INSN's list of reg-notes. */
1482:
1483: static void
1484: add_incs (insn, incs)
1485: rtx insn, incs;
1486: {
1487: register rtx tail;
1488:
1489: for (tail = incs; tail; tail = XEXP (tail, 1))
1490: if ((enum reg_note) GET_MODE (tail) == REG_INC)
1491: REG_NOTES (insn)
1492: = gen_rtx (EXPR_LIST, REG_INC, XEXP (tail, 0), REG_NOTES (insn));
1493: }
1494:
1495: /* For each register (hardware or pseudo) used within expression X,
1496: if its death is in an instruction with cuid
1497: between FROM_CUID (inclusive) and TO_INSN (exclusive),
1498: mark it as dead in TO_INSN instead.
1499:
1500: This is done when X is being merged by combination into TO_INSN. */
1501:
1502: static void
1503: move_deaths (x, from_cuid, to_insn)
1504: rtx x;
1505: int from_cuid;
1506: rtx to_insn;
1507: {
1508: register char *fmt;
1509: register int len, i;
1510: register enum rtx_code code = GET_CODE (x);
1511:
1512: if (code == REG)
1513: {
1514: register rtx where_dead = reg_last_death[REGNO (x)];
1515:
1516: if (where_dead && INSN_CUID (where_dead) >= from_cuid
1517: && INSN_CUID (where_dead) < INSN_CUID (to_insn))
1518: {
1519: remove_death (REGNO (x), reg_last_death[REGNO (x)]);
1520: if (! dead_or_set_p (to_insn, x))
1521: REG_NOTES (to_insn)
1522: = gen_rtx (EXPR_LIST, REG_DEAD, x, REG_NOTES (to_insn));
1523: }
1524: return;
1525: }
1526:
1527: len = GET_RTX_LENGTH (code);
1528: fmt = GET_RTX_FORMAT (code);
1529:
1530: for (i = 0; i < len; i++)
1531: {
1532: if (fmt[i] == 'E')
1533: {
1534: register int j;
1535: for (j = XVECLEN (x, i) - 1; j >= 0; j--)
1536: move_deaths (XVECEXP (x, i, j), from_cuid, to_insn);
1537: }
1538: else if (fmt[i] == 'e')
1539: move_deaths (XEXP (x, i), from_cuid, to_insn);
1540: }
1541: }
1542:
1543: dump_combine_stats (file)
1544: char *file;
1545: {
1546: fprintf
1547: (file,
1548: ";; Combiner statistics: %d attempts, %d substitutions (%d requiring new space),\n;; %d successes.\n\n"
1549: , combine_attempts, combine_merges, combine_extras, combine_successes);
1550: }
1551:
1552: dump_combine_total_stats (file)
1553: char *file;
1554: {
1555: fprintf
1556: (file,
1557: "\n;; Combiner totals: %d attempts, %d substitutions (%d requiring new space),\n;; %d successes.\n",
1558: total_attempts, total_merges, total_extras, total_successes);
1559: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.