alias.c: Reorder #include statements and remove duplicates.
[platform/upstream/gcc.git] / gcc / ree.c
1 /* Redundant Extension Elimination pass for the GNU compiler.
2    Copyright (C) 2010-2015 Free Software Foundation, Inc.
3    Contributed by Ilya Enkovich (ilya.enkovich@intel.com)
4
5    Based on the Redundant Zero-extension elimination pass contributed by
6    Sriraman Tallam (tmsriram@google.com) and Silvius Rus (rus@google.com).
7
8 This file is part of GCC.
9
10 GCC is free software; you can redistribute it and/or modify it under
11 the terms of the GNU General Public License as published by the Free
12 Software Foundation; either version 3, or (at your option) any later
13 version.
14
15 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
16 WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
18 for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with GCC; see the file COPYING3.  If not see
22 <http://www.gnu.org/licenses/>.  */
23
24
25 /* Problem Description :
26    --------------------
27    This pass is intended to remove redundant extension instructions.
28    Such instructions appear for different reasons.  We expect some of
29    them due to implicit zero-extension in 64-bit registers after writing
30    to their lower 32-bit half (e.g. for the x86-64 architecture).
31    Another possible reason is a type cast which follows a load (for
32    instance a register restore) and which can be combined into a single
33    instruction, and for which earlier local passes, e.g. the combiner,
34    weren't able to optimize.
35
36    How does this pass work  ?
37    --------------------------
38
39    This pass is run after register allocation.  Hence, all registers that
40    this pass deals with are hard registers.  This pass first looks for an
41    extension instruction that could possibly be redundant.  Such extension
42    instructions show up in RTL with the pattern  :
43    (set (reg:<SWI248> x) (any_extend:<SWI248> (reg:<SWI124> x))),
44    where x can be any hard register.
45    Now, this pass tries to eliminate this instruction by merging the
46    extension with the definitions of register x.  For instance, if
47    one of the definitions of register x was  :
48    (set (reg:SI x) (plus:SI (reg:SI z1) (reg:SI z2))),
49    followed by extension  :
50    (set (reg:DI x) (zero_extend:DI (reg:SI x)))
51    then the combination converts this into :
52    (set (reg:DI x) (zero_extend:DI (plus:SI (reg:SI z1) (reg:SI z2)))).
53    If all the merged definitions are recognizable assembly instructions,
54    the extension is effectively eliminated.
55
56    For example, for the x86-64 architecture, implicit zero-extensions
57    are captured with appropriate patterns in the i386.md file.  Hence,
58    these merged definition can be matched to a single assembly instruction.
59    The original extension instruction is then deleted if all the
60    definitions can be merged.
61
62    However, there are cases where the definition instruction cannot be
63    merged with an extension.  Examples are CALL instructions.  In such
64    cases, the original extension is not redundant and this pass does
65    not delete it.
66
67    Handling conditional moves :
68    ----------------------------
69
70    Architectures like x86-64 support conditional moves whose semantics for
71    extension differ from the other instructions.  For instance, the
72    instruction *cmov ebx, eax*
73    zero-extends eax onto rax only when the move from ebx to eax happens.
74    Otherwise, eax may not be zero-extended.  Consider conditional moves as
75    RTL instructions of the form
76    (set (reg:SI x) (if_then_else (cond) (reg:SI y) (reg:SI z))).
77    This pass tries to merge an extension with a conditional move by
78    actually merging the definitions of y and z with an extension and then
79    converting the conditional move into :
80    (set (reg:DI x) (if_then_else (cond) (reg:DI y) (reg:DI z))).
81    Since registers y and z are extended, register x will also be extended
82    after the conditional move.  Note that this step has to be done
83    transitively since the definition of a conditional copy can be
84    another conditional copy.
85
86    Motivating Example I :
87    ---------------------
88    For this program :
89    **********************************************
90    bad_code.c
91
92    int mask[1000];
93
94    int foo(unsigned x)
95    {
96      if (x < 10)
97        x = x * 45;
98      else
99        x = x * 78;
100      return mask[x];
101    }
102    **********************************************
103
104    $ gcc -O2 bad_code.c
105      ........
106      400315:       b8 4e 00 00 00          mov    $0x4e,%eax
107      40031a:       0f af f8                imul   %eax,%edi
108      40031d:       89 ff                   mov    %edi,%edi - useless extension
109      40031f:       8b 04 bd 60 19 40 00    mov    0x401960(,%rdi,4),%eax
110      400326:       c3                      retq
111      ......
112      400330:       ba 2d 00 00 00          mov    $0x2d,%edx
113      400335:       0f af fa                imul   %edx,%edi
114      400338:       89 ff                   mov    %edi,%edi - useless extension
115      40033a:       8b 04 bd 60 19 40 00    mov    0x401960(,%rdi,4),%eax
116      400341:       c3                      retq
117
118    $ gcc -O2 -free bad_code.c
119      ......
120      400315:       6b ff 4e                imul   $0x4e,%edi,%edi
121      400318:       8b 04 bd 40 19 40 00    mov    0x401940(,%rdi,4),%eax
122      40031f:       c3                      retq
123      400320:       6b ff 2d                imul   $0x2d,%edi,%edi
124      400323:       8b 04 bd 40 19 40 00    mov    0x401940(,%rdi,4),%eax
125      40032a:       c3                      retq
126
127    Motivating Example II :
128    ---------------------
129
130    Here is an example with a conditional move.
131
132    For this program :
133    **********************************************
134
135    unsigned long long foo(unsigned x , unsigned y)
136    {
137      unsigned z;
138      if (x > 100)
139        z = x + y;
140      else
141        z = x - y;
142      return (unsigned long long)(z);
143    }
144
145    $ gcc -O2 bad_code.c
146      ............
147      400360:       8d 14 3e                lea    (%rsi,%rdi,1),%edx
148      400363:       89 f8                   mov    %edi,%eax
149      400365:       29 f0                   sub    %esi,%eax
150      400367:       83 ff 65                cmp    $0x65,%edi
151      40036a:       0f 43 c2                cmovae %edx,%eax
152      40036d:       89 c0                   mov    %eax,%eax - useless extension
153      40036f:       c3                      retq
154
155    $ gcc -O2 -free bad_code.c
156      .............
157      400360:       89 fa                   mov    %edi,%edx
158      400362:       8d 04 3e                lea    (%rsi,%rdi,1),%eax
159      400365:       29 f2                   sub    %esi,%edx
160      400367:       83 ff 65                cmp    $0x65,%edi
161      40036a:       89 d6                   mov    %edx,%esi
162      40036c:       48 0f 42 c6             cmovb  %rsi,%rax
163      400370:       c3                      retq
164
165   Motivating Example III :
166   ---------------------
167
168   Here is an example with a type cast.
169
170   For this program :
171   **********************************************
172
173   void test(int size, unsigned char *in, unsigned char *out)
174   {
175     int i;
176     unsigned char xr, xg, xy=0;
177
178     for (i = 0; i < size; i++) {
179       xr = *in++;
180       xg = *in++;
181       xy = (unsigned char) ((19595*xr + 38470*xg) >> 16);
182       *out++ = xy;
183     }
184   }
185
186   $ gcc -O2 bad_code.c
187     ............
188     10:   0f b6 0e                movzbl (%rsi),%ecx
189     13:   0f b6 46 01             movzbl 0x1(%rsi),%eax
190     17:   48 83 c6 02             add    $0x2,%rsi
191     1b:   0f b6 c9                movzbl %cl,%ecx - useless extension
192     1e:   0f b6 c0                movzbl %al,%eax - useless extension
193     21:   69 c9 8b 4c 00 00       imul   $0x4c8b,%ecx,%ecx
194     27:   69 c0 46 96 00 00       imul   $0x9646,%eax,%eax
195
196    $ gcc -O2 -free bad_code.c
197      .............
198     10:   0f b6 0e                movzbl (%rsi),%ecx
199     13:   0f b6 46 01             movzbl 0x1(%rsi),%eax
200     17:   48 83 c6 02             add    $0x2,%rsi
201     1b:   69 c9 8b 4c 00 00       imul   $0x4c8b,%ecx,%ecx
202     21:   69 c0 46 96 00 00       imul   $0x9646,%eax,%eax
203
204    Usefulness :
205    ----------
206
207    The original redundant zero-extension elimination pass reported reduction
208    of the dynamic instruction count of a compression benchmark by 2.8% and
209    improvement of its run time by about 1%.
210
211    The additional performance gain with the enhanced pass is mostly expected
212    on in-order architectures where redundancy cannot be compensated by out of
213    order execution.  Measurements showed up to 10% performance gain (reduced
214    run time) on EEMBC 2.0 benchmarks on Atom processor with geomean performance
215    gain 1%.  */
216
217
218 #include "config.h"
219 #include "system.h"
220 #include "coretypes.h"
221 #include "backend.h"
222 #include "target.h"
223 #include "rtl.h"
224 #include "tree.h"
225 #include "df.h"
226 #include "tm_p.h"
227 #include "expmed.h"
228 #include "optabs.h"
229 #include "regs.h"
230 #include "emit-rtl.h"
231 #include "recog.h"
232 #include "cgraph.h"
233 #include "diagnostic-core.h"
234 #include "alias.h"
235 #include "flags.h"
236 #include "cfgrtl.h"
237 #include "dojump.h"
238 #include "explow.h"
239 #include "calls.h"
240 #include "varasm.h"
241 #include "stmt.h"
242 #include "expr.h"
243 #include "insn-attr.h"
244 #include "rtlhooks-def.h"
245 #include "params.h"
246 #include "tree-pass.h"
247
248 /* This structure represents a candidate for elimination.  */
249
250 struct ext_cand
251 {
252   /* The expression.  */
253   const_rtx expr;
254
255   /* The kind of extension.  */
256   enum rtx_code code;
257
258   /* The destination mode.  */
259   machine_mode mode;
260
261   /* The instruction where it lives.  */
262   rtx_insn *insn;
263 };
264
265
266 static int max_insn_uid;
267
268 /* Update or remove REG_EQUAL or REG_EQUIV notes for INSN.  */
269
270 static bool
271 update_reg_equal_equiv_notes (rtx_insn *insn, machine_mode new_mode,
272                               machine_mode old_mode, enum rtx_code code)
273 {
274   rtx *loc = &REG_NOTES (insn);
275   while (*loc)
276     {
277       enum reg_note kind = REG_NOTE_KIND (*loc);
278       if (kind == REG_EQUAL || kind == REG_EQUIV)
279         {
280           rtx orig_src = XEXP (*loc, 0);
281           /* Update equivalency constants.  Recall that RTL constants are
282              sign-extended.  */
283           if (GET_CODE (orig_src) == CONST_INT
284               && HOST_BITS_PER_WIDE_INT >= GET_MODE_BITSIZE (new_mode))
285             {
286               if (INTVAL (orig_src) >= 0 || code == SIGN_EXTEND)
287                 /* Nothing needed.  */;
288               else
289                 {
290                   /* Zero-extend the negative constant by masking out the
291                      bits outside the source mode.  */
292                   rtx new_const_int
293                     = gen_int_mode (INTVAL (orig_src)
294                                     & GET_MODE_MASK (old_mode),
295                                     new_mode);
296                   if (!validate_change (insn, &XEXP (*loc, 0),
297                                         new_const_int, true))
298                     return false;
299                 }
300               loc = &XEXP (*loc, 1);
301             }
302           /* Drop all other notes, they assume a wrong mode.  */
303           else if (!validate_change (insn, loc, XEXP (*loc, 1), true))
304             return false;
305         }
306       else
307         loc = &XEXP (*loc, 1);
308     }
309   return true;
310 }
311
312 /* Given a insn (CURR_INSN), an extension candidate for removal (CAND)
313    and a pointer to the SET rtx (ORIG_SET) that needs to be modified,
314    this code modifies the SET rtx to a new SET rtx that extends the
315    right hand expression into a register on the left hand side.  Note
316    that multiple assumptions are made about the nature of the set that
317    needs to be true for this to work and is called from merge_def_and_ext.
318
319    Original :
320    (set (reg a) (expression))
321
322    Transform :
323    (set (reg a) (any_extend (expression)))
324
325    Special Cases :
326    If the expression is a constant or another extension, then directly
327    assign it to the register.  */
328
329 static bool
330 combine_set_extension (ext_cand *cand, rtx_insn *curr_insn, rtx *orig_set)
331 {
332   rtx orig_src = SET_SRC (*orig_set);
333   machine_mode orig_mode = GET_MODE (SET_DEST (*orig_set));
334   rtx new_set;
335   rtx cand_pat = PATTERN (cand->insn);
336
337   /* If the extension's source/destination registers are not the same
338      then we need to change the original load to reference the destination
339      of the extension.  Then we need to emit a copy from that destination
340      to the original destination of the load.  */
341   rtx new_reg;
342   bool copy_needed
343     = (REGNO (SET_DEST (cand_pat)) != REGNO (XEXP (SET_SRC (cand_pat), 0)));
344   if (copy_needed)
345     new_reg = gen_rtx_REG (cand->mode, REGNO (SET_DEST (cand_pat)));
346   else
347     new_reg = gen_rtx_REG (cand->mode, REGNO (SET_DEST (*orig_set)));
348
349 #if 0
350   /* Rethinking test.  Temporarily disabled.  */
351   /* We're going to be widening the result of DEF_INSN, ensure that doing so
352      doesn't change the number of hard registers needed for the result.  */
353   if (HARD_REGNO_NREGS (REGNO (new_reg), cand->mode)
354       != HARD_REGNO_NREGS (REGNO (SET_DEST (*orig_set)),
355                            GET_MODE (SET_DEST (*orig_set))))
356         return false;
357 #endif
358
359   /* Merge constants by directly moving the constant into the register under
360      some conditions.  Recall that RTL constants are sign-extended.  */
361   if (GET_CODE (orig_src) == CONST_INT
362       && HOST_BITS_PER_WIDE_INT >= GET_MODE_BITSIZE (cand->mode))
363     {
364       if (INTVAL (orig_src) >= 0 || cand->code == SIGN_EXTEND)
365         new_set = gen_rtx_SET (new_reg, orig_src);
366       else
367         {
368           /* Zero-extend the negative constant by masking out the bits outside
369              the source mode.  */
370           rtx new_const_int
371             = gen_int_mode (INTVAL (orig_src) & GET_MODE_MASK (orig_mode),
372                             GET_MODE (new_reg));
373           new_set = gen_rtx_SET (new_reg, new_const_int);
374         }
375     }
376   else if (GET_MODE (orig_src) == VOIDmode)
377     {
378       /* This is mostly due to a call insn that should not be optimized.  */
379       return false;
380     }
381   else if (GET_CODE (orig_src) == cand->code)
382     {
383       /* Here is a sequence of two extensions.  Try to merge them.  */
384       rtx temp_extension
385         = gen_rtx_fmt_e (cand->code, cand->mode, XEXP (orig_src, 0));
386       rtx simplified_temp_extension = simplify_rtx (temp_extension);
387       if (simplified_temp_extension)
388         temp_extension = simplified_temp_extension;
389       new_set = gen_rtx_SET (new_reg, temp_extension);
390     }
391   else if (GET_CODE (orig_src) == IF_THEN_ELSE)
392     {
393       /* Only IF_THEN_ELSE of phi-type copies are combined.  Otherwise,
394          in general, IF_THEN_ELSE should not be combined.  */
395       return false;
396     }
397   else
398     {
399       /* This is the normal case.  */
400       rtx temp_extension
401         = gen_rtx_fmt_e (cand->code, cand->mode, orig_src);
402       rtx simplified_temp_extension = simplify_rtx (temp_extension);
403       if (simplified_temp_extension)
404         temp_extension = simplified_temp_extension;
405       new_set = gen_rtx_SET (new_reg, temp_extension);
406     }
407
408   /* This change is a part of a group of changes.  Hence,
409      validate_change will not try to commit the change.  */
410   if (validate_change (curr_insn, orig_set, new_set, true)
411       && update_reg_equal_equiv_notes (curr_insn, cand->mode, orig_mode,
412                                        cand->code))
413     {
414       if (dump_file)
415         {
416           fprintf (dump_file,
417                    "Tentatively merged extension with definition %s:\n",
418                    (copy_needed) ? "(copy needed)" : "");
419           print_rtl_single (dump_file, curr_insn);
420         }
421       return true;
422     }
423
424   return false;
425 }
426
427 /* Treat if_then_else insns, where the operands of both branches
428    are registers, as copies.  For instance,
429    Original :
430    (set (reg:SI a) (if_then_else (cond) (reg:SI b) (reg:SI c)))
431    Transformed :
432    (set (reg:DI a) (if_then_else (cond) (reg:DI b) (reg:DI c)))
433    DEF_INSN is the if_then_else insn.  */
434
435 static bool
436 transform_ifelse (ext_cand *cand, rtx_insn *def_insn)
437 {
438   rtx set_insn = PATTERN (def_insn);
439   rtx srcreg, dstreg, srcreg2;
440   rtx map_srcreg, map_dstreg, map_srcreg2;
441   rtx ifexpr;
442   rtx cond;
443   rtx new_set;
444
445   gcc_assert (GET_CODE (set_insn) == SET);
446
447   cond = XEXP (SET_SRC (set_insn), 0);
448   dstreg = SET_DEST (set_insn);
449   srcreg = XEXP (SET_SRC (set_insn), 1);
450   srcreg2 = XEXP (SET_SRC (set_insn), 2);
451   /* If the conditional move already has the right or wider mode,
452      there is nothing to do.  */
453   if (GET_MODE_SIZE (GET_MODE (dstreg)) >= GET_MODE_SIZE (cand->mode))
454     return true;
455
456   map_srcreg = gen_rtx_REG (cand->mode, REGNO (srcreg));
457   map_srcreg2 = gen_rtx_REG (cand->mode, REGNO (srcreg2));
458   map_dstreg = gen_rtx_REG (cand->mode, REGNO (dstreg));
459   ifexpr = gen_rtx_IF_THEN_ELSE (cand->mode, cond, map_srcreg, map_srcreg2);
460   new_set = gen_rtx_SET (map_dstreg, ifexpr);
461
462   if (validate_change (def_insn, &PATTERN (def_insn), new_set, true)
463       && update_reg_equal_equiv_notes (def_insn, cand->mode, GET_MODE (dstreg),
464                                        cand->code))
465     {
466       if (dump_file)
467         {
468           fprintf (dump_file,
469                    "Mode of conditional move instruction extended:\n");
470           print_rtl_single (dump_file, def_insn);
471         }
472       return true;
473     }
474
475   return false;
476 }
477
478 /* Get all the reaching definitions of an instruction.  The definitions are
479    desired for REG used in INSN.  Return the definition list or NULL if a
480    definition is missing.  If DEST is non-NULL, additionally push the INSN
481    of the definitions onto DEST.  */
482
483 static struct df_link *
484 get_defs (rtx_insn *insn, rtx reg, vec<rtx_insn *> *dest)
485 {
486   df_ref use;
487   struct df_link *ref_chain, *ref_link;
488
489   FOR_EACH_INSN_USE (use, insn)
490     {
491       if (GET_CODE (DF_REF_REG (use)) == SUBREG)
492         return NULL;
493       if (REGNO (DF_REF_REG (use)) == REGNO (reg))
494         break;
495     }
496
497   gcc_assert (use != NULL);
498
499   ref_chain = DF_REF_CHAIN (use);
500
501   for (ref_link = ref_chain; ref_link; ref_link = ref_link->next)
502     {
503       /* Problem getting some definition for this instruction.  */
504       if (ref_link->ref == NULL)
505         return NULL;
506       if (DF_REF_INSN_INFO (ref_link->ref) == NULL)
507         return NULL;
508     }
509
510   if (dest)
511     for (ref_link = ref_chain; ref_link; ref_link = ref_link->next)
512       dest->safe_push (DF_REF_INSN (ref_link->ref));
513
514   return ref_chain;
515 }
516
517 /* Return true if INSN is
518      (SET (reg REGNO (def_reg)) (if_then_else (cond) (REG x1) (REG x2)))
519    and store x1 and x2 in REG_1 and REG_2.  */
520
521 static bool
522 is_cond_copy_insn (rtx_insn *insn, rtx *reg1, rtx *reg2)
523 {
524   rtx expr = single_set (insn);
525
526   if (expr != NULL_RTX
527       && GET_CODE (expr) == SET
528       && GET_CODE (SET_DEST (expr)) == REG
529       && GET_CODE (SET_SRC (expr))  == IF_THEN_ELSE
530       && GET_CODE (XEXP (SET_SRC (expr), 1)) == REG
531       && GET_CODE (XEXP (SET_SRC (expr), 2)) == REG)
532     {
533       *reg1 = XEXP (SET_SRC (expr), 1);
534       *reg2 = XEXP (SET_SRC (expr), 2);
535       return true;
536     }
537
538   return false;
539 }
540
541 enum ext_modified_kind
542 {
543   /* The insn hasn't been modified by ree pass yet.  */
544   EXT_MODIFIED_NONE,
545   /* Changed into zero extension.  */
546   EXT_MODIFIED_ZEXT,
547   /* Changed into sign extension.  */
548   EXT_MODIFIED_SEXT
549 };
550
551 struct ATTRIBUTE_PACKED ext_modified
552 {
553   /* Mode from which ree has zero or sign extended the destination.  */
554   ENUM_BITFIELD(machine_mode) mode : 8;
555
556   /* Kind of modification of the insn.  */
557   ENUM_BITFIELD(ext_modified_kind) kind : 2;
558
559   unsigned int do_not_reextend : 1;
560
561   /* True if the insn is scheduled to be deleted.  */
562   unsigned int deleted : 1;
563 };
564
565 /* Vectors used by combine_reaching_defs and its helpers.  */
566 struct ext_state
567 {
568   /* In order to avoid constant alloc/free, we keep these
569      4 vectors live through the entire find_and_remove_re and just
570      truncate them each time.  */
571   vec<rtx_insn *> defs_list;
572   vec<rtx_insn *> copies_list;
573   vec<rtx_insn *> modified_list;
574   vec<rtx_insn *> work_list;
575
576   /* For instructions that have been successfully modified, this is
577      the original mode from which the insn is extending and
578      kind of extension.  */
579   struct ext_modified *modified;
580 };
581
582 /* Reaching Definitions of the extended register could be conditional copies
583    or regular definitions.  This function separates the two types into two
584    lists, STATE->DEFS_LIST and STATE->COPIES_LIST.  This is necessary because,
585    if a reaching definition is a conditional copy, merging the extension with
586    this definition is wrong.  Conditional copies are merged by transitively
587    merging their definitions.  The defs_list is populated with all the reaching
588    definitions of the extension instruction (EXTEND_INSN) which must be merged
589    with an extension.  The copies_list contains all the conditional moves that
590    will later be extended into a wider mode conditional move if all the merges
591    are successful.  The function returns false upon failure, true upon
592    success.  */
593
594 static bool
595 make_defs_and_copies_lists (rtx_insn *extend_insn, const_rtx set_pat,
596                             ext_state *state)
597 {
598   rtx src_reg = XEXP (SET_SRC (set_pat), 0);
599   bool *is_insn_visited;
600   bool ret = true;
601
602   state->work_list.truncate (0);
603
604   /* Initialize the work list.  */
605   if (!get_defs (extend_insn, src_reg, &state->work_list))
606     gcc_unreachable ();
607
608   is_insn_visited = XCNEWVEC (bool, max_insn_uid);
609
610   /* Perform transitive closure for conditional copies.  */
611   while (!state->work_list.is_empty ())
612     {
613       rtx_insn *def_insn = state->work_list.pop ();
614       rtx reg1, reg2;
615
616       gcc_assert (INSN_UID (def_insn) < max_insn_uid);
617
618       if (is_insn_visited[INSN_UID (def_insn)])
619         continue;
620       is_insn_visited[INSN_UID (def_insn)] = true;
621
622       if (is_cond_copy_insn (def_insn, &reg1, &reg2))
623         {
624           /* Push it onto the copy list first.  */
625           state->copies_list.safe_push (def_insn);
626
627           /* Now perform the transitive closure.  */
628           if (!get_defs (def_insn, reg1, &state->work_list)
629               || !get_defs (def_insn, reg2, &state->work_list))
630             {
631               ret = false;
632               break;
633             }
634         }
635       else
636         state->defs_list.safe_push (def_insn);
637     }
638
639   XDELETEVEC (is_insn_visited);
640
641   return ret;
642 }
643
644 /* If DEF_INSN has single SET expression, possibly buried inside
645    a PARALLEL, return the address of the SET expression, else
646    return NULL.  This is similar to single_set, except that
647    single_set allows multiple SETs when all but one is dead.  */
648 static rtx *
649 get_sub_rtx (rtx_insn *def_insn)
650 {
651   enum rtx_code code = GET_CODE (PATTERN (def_insn));
652   rtx *sub_rtx = NULL;
653
654   if (code == PARALLEL)
655     {
656       for (int i = 0; i < XVECLEN (PATTERN (def_insn), 0); i++)
657         {
658           rtx s_expr = XVECEXP (PATTERN (def_insn), 0, i);
659           if (GET_CODE (s_expr) != SET)
660             continue;
661
662           if (sub_rtx == NULL)
663             sub_rtx = &XVECEXP (PATTERN (def_insn), 0, i);
664           else
665             {
666               /* PARALLEL with multiple SETs.  */
667               return NULL;
668             }
669         }
670     }
671   else if (code == SET)
672     sub_rtx = &PATTERN (def_insn);
673   else
674     {
675       /* It is not a PARALLEL or a SET, what could it be ? */
676       return NULL;
677     }
678
679   gcc_assert (sub_rtx != NULL);
680   return sub_rtx;
681 }
682
683 /* Merge the DEF_INSN with an extension.  Calls combine_set_extension
684    on the SET pattern.  */
685
686 static bool
687 merge_def_and_ext (ext_cand *cand, rtx_insn *def_insn, ext_state *state)
688 {
689   machine_mode ext_src_mode;
690   rtx *sub_rtx;
691
692   ext_src_mode = GET_MODE (XEXP (SET_SRC (cand->expr), 0));
693   sub_rtx = get_sub_rtx (def_insn);
694
695   if (sub_rtx == NULL)
696     return false;
697
698   if (REG_P (SET_DEST (*sub_rtx))
699       && (GET_MODE (SET_DEST (*sub_rtx)) == ext_src_mode
700           || ((state->modified[INSN_UID (def_insn)].kind
701                == (cand->code == ZERO_EXTEND
702                    ? EXT_MODIFIED_ZEXT : EXT_MODIFIED_SEXT))
703               && state->modified[INSN_UID (def_insn)].mode
704                  == ext_src_mode)))
705     {
706       if (GET_MODE_SIZE (GET_MODE (SET_DEST (*sub_rtx)))
707           >= GET_MODE_SIZE (cand->mode))
708         return true;
709       /* If def_insn is already scheduled to be deleted, don't attempt
710          to modify it.  */
711       if (state->modified[INSN_UID (def_insn)].deleted)
712         return false;
713       if (combine_set_extension (cand, def_insn, sub_rtx))
714         {
715           if (state->modified[INSN_UID (def_insn)].kind == EXT_MODIFIED_NONE)
716             state->modified[INSN_UID (def_insn)].mode = ext_src_mode;
717           return true;
718         }
719     }
720
721   return false;
722 }
723
724 /* Given SRC, which should be one or more extensions of a REG, strip
725    away the extensions and return the REG.  */
726
727 static inline rtx
728 get_extended_src_reg (rtx src)
729 {
730   while (GET_CODE (src) == SIGN_EXTEND || GET_CODE (src) == ZERO_EXTEND)
731     src = XEXP (src, 0);
732   gcc_assert (REG_P (src));
733   return src;
734 }
735
736 /* This function goes through all reaching defs of the source
737    of the candidate for elimination (CAND) and tries to combine
738    the extension with the definition instruction.  The changes
739    are made as a group so that even if one definition cannot be
740    merged, all reaching definitions end up not being merged.
741    When a conditional copy is encountered, merging is attempted
742    transitively on its definitions.  It returns true upon success
743    and false upon failure.  */
744
745 static bool
746 combine_reaching_defs (ext_cand *cand, const_rtx set_pat, ext_state *state)
747 {
748   rtx_insn *def_insn;
749   bool merge_successful = true;
750   int i;
751   int defs_ix;
752   bool outcome;
753
754   state->defs_list.truncate (0);
755   state->copies_list.truncate (0);
756
757   outcome = make_defs_and_copies_lists (cand->insn, set_pat, state);
758
759   if (!outcome)
760     return false;
761
762   /* If the destination operand of the extension is a different
763      register than the source operand, then additional restrictions
764      are needed.  Note we have to handle cases where we have nested
765      extensions in the source operand.  */
766   bool copy_needed
767     = (REGNO (SET_DEST (PATTERN (cand->insn)))
768        != REGNO (get_extended_src_reg (SET_SRC (PATTERN (cand->insn)))));
769   if (copy_needed)
770     {
771       /* Considering transformation of
772          (set (reg1) (expression))
773          ...
774          (set (reg2) (any_extend (reg1)))
775
776          into
777
778          (set (reg2) (any_extend (expression)))
779          (set (reg1) (reg2))
780          ...  */
781
782       /* In theory we could handle more than one reaching def, it
783          just makes the code to update the insn stream more complex.  */
784       if (state->defs_list.length () != 1)
785         return false;
786
787       /* We require the candidate not already be modified.  It may,
788          for example have been changed from a (sign_extend (reg))
789          into (zero_extend (sign_extend (reg))).
790
791          Handling that case shouldn't be terribly difficult, but the code
792          here and the code to emit copies would need auditing.  Until
793          we see a need, this is the safe thing to do.  */
794       if (state->modified[INSN_UID (cand->insn)].kind != EXT_MODIFIED_NONE)
795         return false;
796
797       machine_mode dst_mode = GET_MODE (SET_DEST (PATTERN (cand->insn)));
798       rtx src_reg = get_extended_src_reg (SET_SRC (PATTERN (cand->insn)));
799
800       /* Ensure the number of hard registers of the copy match.  */
801       if (HARD_REGNO_NREGS (REGNO (src_reg), dst_mode)
802           != HARD_REGNO_NREGS (REGNO (src_reg), GET_MODE (src_reg)))
803         return false;
804
805       /* There's only one reaching def.  */
806       rtx_insn *def_insn = state->defs_list[0];
807
808       /* The defining statement must not have been modified either.  */
809       if (state->modified[INSN_UID (def_insn)].kind != EXT_MODIFIED_NONE)
810         return false;
811
812       /* The defining statement and candidate insn must be in the same block.
813          This is merely to keep the test for safety and updating the insn
814          stream simple.  Also ensure that within the block the candidate
815          follows the defining insn.  */
816       basic_block bb = BLOCK_FOR_INSN (cand->insn);
817       if (bb != BLOCK_FOR_INSN (def_insn)
818           || DF_INSN_LUID (def_insn) > DF_INSN_LUID (cand->insn))
819         return false;
820
821       /* If there is an overlap between the destination of DEF_INSN and
822          CAND->insn, then this transformation is not safe.  Note we have
823          to test in the widened mode.  */
824       rtx *dest_sub_rtx = get_sub_rtx (def_insn);
825       if (dest_sub_rtx == NULL
826           || !REG_P (SET_DEST (*dest_sub_rtx)))
827         return false;
828
829       rtx tmp_reg = gen_rtx_REG (GET_MODE (SET_DEST (PATTERN (cand->insn))),
830                                  REGNO (SET_DEST (*dest_sub_rtx)));
831       if (reg_overlap_mentioned_p (tmp_reg, SET_DEST (PATTERN (cand->insn))))
832         return false;
833
834       /* The destination register of the extension insn must not be
835          used or set between the def_insn and cand->insn exclusive.  */
836       if (reg_used_between_p (SET_DEST (PATTERN (cand->insn)),
837                               def_insn, cand->insn)
838           || reg_set_between_p (SET_DEST (PATTERN (cand->insn)),
839                                 def_insn, cand->insn))
840         return false;
841
842       /* We must be able to copy between the two registers.   Generate,
843          recognize and verify constraints of the copy.  Also fail if this
844          generated more than one insn.
845
846          This generates garbage since we throw away the insn when we're
847          done, only to recreate it later if this test was successful. 
848
849          Make sure to get the mode from the extension (cand->insn).  This
850          is different than in the code to emit the copy as we have not
851          modified the defining insn yet.  */
852       start_sequence ();
853       rtx pat = PATTERN (cand->insn);
854       rtx new_dst = gen_rtx_REG (GET_MODE (SET_DEST (pat)),
855                                  REGNO (get_extended_src_reg (SET_SRC (pat))));
856       rtx new_src = gen_rtx_REG (GET_MODE (SET_DEST (pat)),
857                                  REGNO (SET_DEST (pat)));
858       emit_move_insn (new_dst, new_src);
859
860       rtx_insn *insn = get_insns();
861       end_sequence ();
862       if (NEXT_INSN (insn))
863         return false;
864       if (recog_memoized (insn) == -1)
865         return false;
866       extract_insn (insn);
867       if (!constrain_operands (1, get_preferred_alternatives (insn, bb)))
868         return false;
869     }
870
871
872   /* If cand->insn has been already modified, update cand->mode to a wider
873      mode if possible, or punt.  */
874   if (state->modified[INSN_UID (cand->insn)].kind != EXT_MODIFIED_NONE)
875     {
876       machine_mode mode;
877       rtx set;
878
879       if (state->modified[INSN_UID (cand->insn)].kind
880           != (cand->code == ZERO_EXTEND
881               ? EXT_MODIFIED_ZEXT : EXT_MODIFIED_SEXT)
882           || state->modified[INSN_UID (cand->insn)].mode != cand->mode
883           || (set = single_set (cand->insn)) == NULL_RTX)
884         return false;
885       mode = GET_MODE (SET_DEST (set));
886       gcc_assert (GET_MODE_SIZE (mode) >= GET_MODE_SIZE (cand->mode));
887       cand->mode = mode;
888     }
889
890   merge_successful = true;
891
892   /* Go through the defs vector and try to merge all the definitions
893      in this vector.  */
894   state->modified_list.truncate (0);
895   FOR_EACH_VEC_ELT (state->defs_list, defs_ix, def_insn)
896     {
897       if (merge_def_and_ext (cand, def_insn, state))
898         state->modified_list.safe_push (def_insn);
899       else
900         {
901           merge_successful = false;
902           break;
903         }
904     }
905
906   /* Now go through the conditional copies vector and try to merge all
907      the copies in this vector.  */
908   if (merge_successful)
909     {
910       FOR_EACH_VEC_ELT (state->copies_list, i, def_insn)
911         {
912           if (transform_ifelse (cand, def_insn))
913             state->modified_list.safe_push (def_insn);
914           else
915             {
916               merge_successful = false;
917               break;
918             }
919         }
920     }
921
922   if (merge_successful)
923     {
924       /* Commit the changes here if possible
925          FIXME: It's an all-or-nothing scenario.  Even if only one definition
926          cannot be merged, we entirely give up.  In the future, we should allow
927          extensions to be partially eliminated along those paths where the
928          definitions could be merged.  */
929       if (apply_change_group ())
930         {
931           if (dump_file)
932             fprintf (dump_file, "All merges were successful.\n");
933
934           FOR_EACH_VEC_ELT (state->modified_list, i, def_insn)
935             {
936               ext_modified *modified = &state->modified[INSN_UID (def_insn)];
937               if (modified->kind == EXT_MODIFIED_NONE)
938                 modified->kind = (cand->code == ZERO_EXTEND ? EXT_MODIFIED_ZEXT
939                                                             : EXT_MODIFIED_SEXT);
940
941               if (copy_needed)
942                 modified->do_not_reextend = 1;
943             }
944           return true;
945         }
946       else
947         {
948           /* Changes need not be cancelled explicitly as apply_change_group
949              does it.  Print list of definitions in the dump_file for debug
950              purposes.  This extension cannot be deleted.  */
951           if (dump_file)
952             {
953               fprintf (dump_file,
954                        "Merge cancelled, non-mergeable definitions:\n");
955               FOR_EACH_VEC_ELT (state->modified_list, i, def_insn)
956                 print_rtl_single (dump_file, def_insn);
957             }
958         }
959     }
960   else
961     {
962       /* Cancel any changes that have been made so far.  */
963       cancel_changes (0);
964     }
965
966   return false;
967 }
968
969 /* Add an extension pattern that could be eliminated.  */
970
971 static void
972 add_removable_extension (const_rtx expr, rtx_insn *insn,
973                          vec<ext_cand> *insn_list,
974                          unsigned *def_map,
975                          bitmap init_regs)
976 {
977   enum rtx_code code;
978   machine_mode mode;
979   unsigned int idx;
980   rtx src, dest;
981
982   /* We are looking for SET (REG N) (ANY_EXTEND (REG N)).  */
983   if (GET_CODE (expr) != SET)
984     return;
985
986   src = SET_SRC (expr);
987   code = GET_CODE (src);
988   dest = SET_DEST (expr);
989   mode = GET_MODE (dest);
990
991   if (REG_P (dest)
992       && (code == SIGN_EXTEND || code == ZERO_EXTEND)
993       && REG_P (XEXP (src, 0)))
994     {
995       rtx reg = XEXP (src, 0);
996       struct df_link *defs, *def;
997       ext_cand *cand;
998
999       /* Zero-extension of an undefined value is partly defined (it's
1000          completely undefined for sign-extension, though).  So if there exists
1001          a path from the entry to this zero-extension that leaves this register
1002          uninitialized, removing the extension could change the behavior of
1003          correct programs.  So first, check it is not the case.  */
1004       if (code == ZERO_EXTEND && !bitmap_bit_p (init_regs, REGNO (reg)))
1005         {
1006           if (dump_file)
1007             {
1008               fprintf (dump_file, "Cannot eliminate extension:\n");
1009               print_rtl_single (dump_file, insn);
1010               fprintf (dump_file, " because it can operate on uninitialized"
1011                                   " data\n");
1012             }
1013           return;
1014         }
1015
1016       /* Second, make sure we can get all the reaching definitions.  */
1017       defs = get_defs (insn, reg, NULL);
1018       if (!defs)
1019         {
1020           if (dump_file)
1021             {
1022               fprintf (dump_file, "Cannot eliminate extension:\n");
1023               print_rtl_single (dump_file, insn);
1024               fprintf (dump_file, " because of missing definition(s)\n");
1025             }
1026           return;
1027         }
1028
1029       /* Third, make sure the reaching definitions don't feed another and
1030          different extension.  FIXME: this obviously can be improved.  */
1031       for (def = defs; def; def = def->next)
1032         if ((idx = def_map[INSN_UID (DF_REF_INSN (def->ref))])
1033             && idx != -1U
1034             && (cand = &(*insn_list)[idx - 1])
1035             && cand->code != code)
1036           {
1037             if (dump_file)
1038               {
1039                 fprintf (dump_file, "Cannot eliminate extension:\n");
1040                 print_rtl_single (dump_file, insn);
1041                 fprintf (dump_file, " because of other extension\n");
1042               }
1043             return;
1044           }
1045         /* For vector mode extensions, ensure that all uses of the
1046            XEXP (src, 0) register are the same extension (both code
1047            and to which mode), as unlike integral extensions lowpart
1048            subreg of the sign/zero extended register are not equal
1049            to the original register, so we have to change all uses or
1050            none.  */
1051         else if (VECTOR_MODE_P (GET_MODE (XEXP (src, 0))))
1052           {
1053             if (idx == 0)
1054               {
1055                 struct df_link *ref_chain, *ref_link;
1056
1057                 ref_chain = DF_REF_CHAIN (def->ref);
1058                 for (ref_link = ref_chain; ref_link; ref_link = ref_link->next)
1059                   {
1060                     if (ref_link->ref == NULL
1061                         || DF_REF_INSN_INFO (ref_link->ref) == NULL)
1062                       {
1063                         idx = -1U;
1064                         break;
1065                       }
1066                     rtx_insn *use_insn = DF_REF_INSN (ref_link->ref);
1067                     const_rtx use_set;
1068                     if (use_insn == insn || DEBUG_INSN_P (use_insn))
1069                       continue;
1070                     if (!(use_set = single_set (use_insn))
1071                         || !REG_P (SET_DEST (use_set))
1072                         || GET_MODE (SET_DEST (use_set)) != GET_MODE (dest)
1073                         || GET_CODE (SET_SRC (use_set)) != code
1074                         || !rtx_equal_p (XEXP (SET_SRC (use_set), 0),
1075                                          XEXP (src, 0)))
1076                       {
1077                         idx = -1U;
1078                         break;
1079                       }
1080                   }
1081                 if (idx == -1U)
1082                   def_map[INSN_UID (DF_REF_INSN (def->ref))] = idx;
1083               }
1084             if (idx == -1U)
1085               {
1086                 if (dump_file)
1087                   {
1088                     fprintf (dump_file, "Cannot eliminate extension:\n");
1089                     print_rtl_single (dump_file, insn);
1090                     fprintf (dump_file,
1091                              " because some vector uses aren't extension\n");
1092                   }
1093                 return;
1094               }
1095           }
1096
1097       /* Then add the candidate to the list and insert the reaching definitions
1098          into the definition map.  */
1099       ext_cand e = {expr, code, mode, insn};
1100       insn_list->safe_push (e);
1101       idx = insn_list->length ();
1102
1103       for (def = defs; def; def = def->next)
1104         def_map[INSN_UID (DF_REF_INSN (def->ref))] = idx;
1105     }
1106 }
1107
1108 /* Traverse the instruction stream looking for extensions and return the
1109    list of candidates.  */
1110
1111 static vec<ext_cand>
1112 find_removable_extensions (void)
1113 {
1114   vec<ext_cand> insn_list = vNULL;
1115   basic_block bb;
1116   rtx_insn *insn;
1117   rtx set;
1118   unsigned *def_map = XCNEWVEC (unsigned, max_insn_uid);
1119   bitmap_head init, kill, gen, tmp;
1120
1121   bitmap_initialize (&init, NULL);
1122   bitmap_initialize (&kill, NULL);
1123   bitmap_initialize (&gen, NULL);
1124   bitmap_initialize (&tmp, NULL);
1125
1126   FOR_EACH_BB_FN (bb, cfun)
1127     {
1128       bitmap_copy (&init, DF_MIR_IN (bb));
1129       bitmap_clear (&kill);
1130       bitmap_clear (&gen);
1131
1132       FOR_BB_INSNS (bb, insn)
1133         {
1134           if (NONDEBUG_INSN_P (insn))
1135             {
1136               set = single_set (insn);
1137               if (set != NULL_RTX)
1138                 add_removable_extension (set, insn, &insn_list, def_map,
1139                                          &init);
1140               df_mir_simulate_one_insn (bb, insn, &kill, &gen);
1141               bitmap_ior_and_compl (&tmp, &gen, &init, &kill);
1142               bitmap_copy (&init, &tmp);
1143             }
1144         }
1145     }
1146
1147   XDELETEVEC (def_map);
1148
1149   return insn_list;
1150 }
1151
1152 /* This is the main function that checks the insn stream for redundant
1153    extensions and tries to remove them if possible.  */
1154
1155 static void
1156 find_and_remove_re (void)
1157 {
1158   ext_cand *curr_cand;
1159   rtx_insn *curr_insn = NULL;
1160   int num_re_opportunities = 0, num_realized = 0, i;
1161   vec<ext_cand> reinsn_list;
1162   auto_vec<rtx_insn *> reinsn_del_list;
1163   auto_vec<rtx_insn *> reinsn_copy_list;
1164   ext_state state;
1165
1166   /* Construct DU chain to get all reaching definitions of each
1167      extension instruction.  */
1168   df_set_flags (DF_RD_PRUNE_DEAD_DEFS);
1169   df_chain_add_problem (DF_UD_CHAIN + DF_DU_CHAIN);
1170   df_mir_add_problem ();
1171   df_analyze ();
1172   df_set_flags (DF_DEFER_INSN_RESCAN);
1173
1174   max_insn_uid = get_max_uid ();
1175   reinsn_list = find_removable_extensions ();
1176   state.defs_list.create (0);
1177   state.copies_list.create (0);
1178   state.modified_list.create (0);
1179   state.work_list.create (0);
1180   if (reinsn_list.is_empty ())
1181     state.modified = NULL;
1182   else
1183     state.modified = XCNEWVEC (struct ext_modified, max_insn_uid);
1184
1185   FOR_EACH_VEC_ELT (reinsn_list, i, curr_cand)
1186     {
1187       num_re_opportunities++;
1188
1189       /* Try to combine the extension with the definition.  */
1190       if (dump_file)
1191         {
1192           fprintf (dump_file, "Trying to eliminate extension:\n");
1193           print_rtl_single (dump_file, curr_cand->insn);
1194         }
1195
1196       if (combine_reaching_defs (curr_cand, curr_cand->expr, &state))
1197         {
1198           if (dump_file)
1199             fprintf (dump_file, "Eliminated the extension.\n");
1200           num_realized++;
1201           /* If the RHS of the current candidate is not (extend (reg)), then
1202              we do not allow the optimization of extensions where
1203              the source and destination registers do not match.  Thus
1204              checking REG_P here is correct.  */
1205           if (REG_P (XEXP (SET_SRC (PATTERN (curr_cand->insn)), 0))
1206               && (REGNO (SET_DEST (PATTERN (curr_cand->insn)))
1207                   != REGNO (XEXP (SET_SRC (PATTERN (curr_cand->insn)), 0))))
1208             {
1209               reinsn_copy_list.safe_push (curr_cand->insn);
1210               reinsn_copy_list.safe_push (state.defs_list[0]);
1211             }
1212           reinsn_del_list.safe_push (curr_cand->insn);
1213           state.modified[INSN_UID (curr_cand->insn)].deleted = 1;
1214         }
1215     }
1216
1217   /* The copy list contains pairs of insns which describe copies we
1218      need to insert into the INSN stream.
1219
1220      The first insn in each pair is the extension insn, from which
1221      we derive the source and destination of the copy.
1222
1223      The second insn in each pair is the memory reference where the
1224      extension will ultimately happen.  We emit the new copy
1225      immediately after this insn.
1226
1227      It may first appear that the arguments for the copy are reversed.
1228      Remember that the memory reference will be changed to refer to the
1229      destination of the extention.  So we're actually emitting a copy
1230      from the new destination to the old destination.  */
1231   for (unsigned int i = 0; i < reinsn_copy_list.length (); i += 2)
1232     {
1233       rtx_insn *curr_insn = reinsn_copy_list[i];
1234       rtx_insn *def_insn = reinsn_copy_list[i + 1];
1235
1236       /* Use the mode of the destination of the defining insn
1237          for the mode of the copy.  This is necessary if the
1238          defining insn was used to eliminate a second extension
1239          that was wider than the first.  */
1240       rtx sub_rtx = *get_sub_rtx (def_insn);
1241       rtx pat = PATTERN (curr_insn);
1242       rtx new_dst = gen_rtx_REG (GET_MODE (SET_DEST (sub_rtx)),
1243                                  REGNO (XEXP (SET_SRC (pat), 0)));
1244       rtx new_src = gen_rtx_REG (GET_MODE (SET_DEST (sub_rtx)),
1245                                  REGNO (SET_DEST (pat)));
1246       rtx set = gen_rtx_SET (new_dst, new_src);
1247       emit_insn_after (set, def_insn);
1248     }
1249
1250   /* Delete all useless extensions here in one sweep.  */
1251   FOR_EACH_VEC_ELT (reinsn_del_list, i, curr_insn)
1252     delete_insn (curr_insn);
1253
1254   reinsn_list.release ();
1255   state.defs_list.release ();
1256   state.copies_list.release ();
1257   state.modified_list.release ();
1258   state.work_list.release ();
1259   XDELETEVEC (state.modified);
1260
1261   if (dump_file && num_re_opportunities > 0)
1262     fprintf (dump_file, "Elimination opportunities = %d realized = %d\n",
1263              num_re_opportunities, num_realized);
1264 }
1265
1266 /* Find and remove redundant extensions.  */
1267
1268 static unsigned int
1269 rest_of_handle_ree (void)
1270 {
1271   timevar_push (TV_REE);
1272   find_and_remove_re ();
1273   timevar_pop (TV_REE);
1274   return 0;
1275 }
1276
1277 namespace {
1278
1279 const pass_data pass_data_ree =
1280 {
1281   RTL_PASS, /* type */
1282   "ree", /* name */
1283   OPTGROUP_NONE, /* optinfo_flags */
1284   TV_REE, /* tv_id */
1285   0, /* properties_required */
1286   0, /* properties_provided */
1287   0, /* properties_destroyed */
1288   0, /* todo_flags_start */
1289   TODO_df_finish, /* todo_flags_finish */
1290 };
1291
1292 class pass_ree : public rtl_opt_pass
1293 {
1294 public:
1295   pass_ree (gcc::context *ctxt)
1296     : rtl_opt_pass (pass_data_ree, ctxt)
1297   {}
1298
1299   /* opt_pass methods: */
1300   virtual bool gate (function *) { return (optimize > 0 && flag_ree); }
1301   virtual unsigned int execute (function *) { return rest_of_handle_ree (); }
1302
1303 }; // class pass_ree
1304
1305 } // anon namespace
1306
1307 rtl_opt_pass *
1308 make_pass_ree (gcc::context *ctxt)
1309 {
1310   return new pass_ree (ctxt);
1311 }