home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 7 / FreshFishVol7.bin / bbs / gnu / gcc-2.3.3-src.lha / GNU / src / amiga / gcc-2.3.3 / explow.c < prev    next >
C/C++ Source or Header  |  1994-02-06  |  28KB  |  1,013 lines

  1. /* Subroutines for manipulating rtx's in semantically interesting ways.
  2.    Copyright (C) 1987, 1991 Free Software Foundation, Inc.
  3.  
  4. This file is part of GNU CC.
  5.  
  6. GNU CC is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 2, or (at your option)
  9. any later version.
  10.  
  11. GNU CC is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with GNU CC; see the file COPYING.  If not, write to
  18. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  19.  
  20.  
  21. #include "config.h"
  22. #include "rtl.h"
  23. #include "tree.h"
  24. #include "flags.h"
  25. #include "expr.h"
  26. #include "hard-reg-set.h"
  27. #include "insn-config.h"
  28. #include "recog.h"
  29. #include "insn-flags.h"
  30. #include "insn-codes.h"
  31.  
  32. /* Return an rtx for the sum of X and the integer C.
  33.  
  34.    This fucntion should be used via the `plus_constant' macro.  */
  35.  
  36. rtx
  37. plus_constant_wide (x, c)
  38.      register rtx x;
  39.      register HOST_WIDE_INT c;
  40. {
  41.   register RTX_CODE code;
  42.   register enum machine_mode mode;
  43.   register rtx tem;
  44.   int all_constant = 0;
  45.  
  46.   if (c == 0)
  47.     return x;
  48.  
  49.  restart:
  50.  
  51.   code = GET_CODE (x);
  52.   mode = GET_MODE (x);
  53.   switch (code)
  54.     {
  55.     case CONST_INT:
  56.       return GEN_INT (INTVAL (x) + c);
  57.  
  58.     case CONST_DOUBLE:
  59.       {
  60.     HOST_WIDE_INT l1 = CONST_DOUBLE_LOW (x);
  61.     HOST_WIDE_INT h1 = CONST_DOUBLE_HIGH (x);
  62.     HOST_WIDE_INT l2 = c;
  63.     HOST_WIDE_INT h2 = c < 0 ? ~0 : 0;
  64.     HOST_WIDE_INT lv, hv;
  65.  
  66.     add_double (l1, h1, l2, h2, &lv, &hv);
  67.  
  68.     return immed_double_const (lv, hv, VOIDmode);
  69.       }
  70.  
  71.     case MEM:
  72.       /* If this is a reference to the constant pool, try replacing it with
  73.      a reference to a new constant.  If the resulting address isn't
  74.      valid, don't return it because we have no way to validize it.  */
  75.       if (GET_CODE (XEXP (x, 0)) == SYMBOL_REF
  76.       && CONSTANT_POOL_ADDRESS_P (XEXP (x, 0)))
  77.     {
  78.       tem
  79.         = force_const_mem (GET_MODE (x),
  80.                    plus_constant (get_pool_constant (XEXP (x, 0)),
  81.                           c));
  82.       if (memory_address_p (GET_MODE (tem), XEXP (tem, 0)))
  83.         return tem;
  84.     }
  85.       break;
  86.  
  87.     case CONST:
  88.       /* If adding to something entirely constant, set a flag
  89.      so that we can add a CONST around the result.  */
  90.       x = XEXP (x, 0);
  91.       all_constant = 1;
  92.       goto restart;
  93.  
  94.     case SYMBOL_REF:
  95.     case LABEL_REF:
  96.       all_constant = 1;
  97.       break;
  98.  
  99.     case PLUS:
  100.       /* The interesting case is adding the integer to a sum.
  101.      Look for constant term in the sum and combine
  102.      with C.  For an integer constant term, we make a combined
  103.      integer.  For a constant term that is not an explicit integer,
  104.      we cannot really combine, but group them together anyway.  
  105.  
  106.      Use a recursive call in case the remaining operand is something
  107.      that we handle specially, such as a SYMBOL_REF.  */
  108.  
  109.       if (GET_CODE (XEXP (x, 1)) == CONST_INT)
  110.     return plus_constant (XEXP (x, 0), c + INTVAL (XEXP (x, 1)));
  111.       else if (CONSTANT_P (XEXP (x, 0)))
  112.     return gen_rtx (PLUS, mode,
  113.             plus_constant (XEXP (x, 0), c),
  114.             XEXP (x, 1));
  115.       else if (CONSTANT_P (XEXP (x, 1)))
  116.     return gen_rtx (PLUS, mode,
  117.             XEXP (x, 0),
  118.             plus_constant (XEXP (x, 1), c));
  119.     }
  120.  
  121.   if (c != 0)
  122.     x = gen_rtx (PLUS, mode, x, GEN_INT (c));
  123.  
  124.   if (GET_CODE (x) == SYMBOL_REF || GET_CODE (x) == LABEL_REF)
  125.     return x;
  126.   else if (all_constant)
  127.     return gen_rtx (CONST, mode, x);
  128.   else
  129.     return x;
  130. }
  131.  
  132. /* This is the same as `plus_constant', except that it handles LO_SUM.
  133.  
  134.    This function should be used via the `plus_constant_for_output' macro.  */
  135.  
  136. rtx
  137. plus_constant_for_output_wide (x, c)
  138.      register rtx x;
  139.      register HOST_WIDE_INT c;
  140. {
  141.   register RTX_CODE code = GET_CODE (x);
  142.   register enum machine_mode mode = GET_MODE (x);
  143.   int all_constant = 0;
  144.  
  145.   if (GET_CODE (x) == LO_SUM)
  146.     return gen_rtx (LO_SUM, mode, XEXP (x, 0),
  147.             plus_constant_for_output (XEXP (x, 1), c));
  148.  
  149.   else
  150.     return plus_constant (x, c);
  151. }
  152.  
  153. /* If X is a sum, return a new sum like X but lacking any constant terms.
  154.    Add all the removed constant terms into *CONSTPTR.
  155.    X itself is not altered.  The result != X if and only if
  156.    it is not isomorphic to X.  */
  157.  
  158. rtx
  159. eliminate_constant_term (x, constptr)
  160.      rtx x;
  161.      rtx *constptr;
  162. {
  163.   register rtx x0, x1;
  164.   rtx tem;
  165.  
  166.   if (GET_CODE (x) != PLUS)
  167.     return x;
  168.  
  169.   /* First handle constants appearing at this level explicitly.  */
  170.   if (GET_CODE (XEXP (x, 1)) == CONST_INT
  171.       && 0 != (tem = simplify_binary_operation (PLUS, GET_MODE (x), *constptr,
  172.                         XEXP (x, 1)))
  173.       && GET_CODE (tem) == CONST_INT)
  174.     {
  175.       *constptr = tem;
  176.       return eliminate_constant_term (XEXP (x, 0), constptr);
  177.     }
  178.  
  179.   tem = const0_rtx;
  180.   x0 = eliminate_constant_term (XEXP (x, 0), &tem);
  181.   x1 = eliminate_constant_term (XEXP (x, 1), &tem);
  182.   if ((x1 != XEXP (x, 1) || x0 != XEXP (x, 0))
  183.       && 0 != (tem = simplify_binary_operation (PLUS, GET_MODE (x),
  184.                         *constptr, tem))
  185.       && GET_CODE (tem) == CONST_INT)
  186.     {
  187.       *constptr = tem;
  188.       return gen_rtx (PLUS, GET_MODE (x), x0, x1);
  189.     }
  190.  
  191.   return x;
  192. }
  193.  
  194. /* Returns the insn that next references REG after INSN, or 0
  195.    if REG is clobbered before next referenced or we cannot find
  196.    an insn that references REG in a straight-line piece of code.  */
  197.  
  198. rtx
  199. find_next_ref (reg, insn)
  200.      rtx reg;
  201.      rtx insn;
  202. {
  203.   rtx next;
  204.  
  205.   for (insn = NEXT_INSN (insn); insn; insn = next)
  206.     {
  207.       next = NEXT_INSN (insn);
  208.       if (GET_CODE (insn) == NOTE)
  209.     continue;
  210.       if (GET_CODE (insn) == CODE_LABEL
  211.       || GET_CODE (insn) == BARRIER)
  212.     return 0;
  213.       if (GET_CODE (insn) == INSN
  214.       || GET_CODE (insn) == JUMP_INSN
  215.       || GET_CODE (insn) == CALL_INSN)
  216.     {
  217.       if (reg_set_p (reg, insn))
  218.         return 0;
  219.       if (reg_mentioned_p (reg, PATTERN (insn)))
  220.         return insn;
  221.       if (GET_CODE (insn) == JUMP_INSN)
  222.         {
  223.           if (simplejump_p (insn))
  224.         next = JUMP_LABEL (insn);
  225.           else
  226.         return 0;
  227.         }
  228.       if (GET_CODE (insn) == CALL_INSN
  229.           && REGNO (reg) < FIRST_PSEUDO_REGISTER
  230.           && call_used_regs[REGNO (reg)])
  231.         return 0;
  232.     }
  233.       else
  234.     abort ();
  235.     }
  236.   return 0;
  237. }
  238.  
  239. /* Return an rtx for the size in bytes of the value of EXP.  */
  240.  
  241. rtx
  242. expr_size (exp)
  243.      tree exp;
  244. {
  245.   return expand_expr (size_in_bytes (TREE_TYPE (exp)),
  246.               NULL_RTX, TYPE_MODE (sizetype), 0);
  247. }
  248.  
  249. /* Return a copy of X in which all memory references
  250.    and all constants that involve symbol refs
  251.    have been replaced with new temporary registers.
  252.    Also emit code to load the memory locations and constants
  253.    into those registers.
  254.  
  255.    If X contains no such constants or memory references,
  256.    X itself (not a copy) is returned.
  257.  
  258.    If a constant is found in the address that is not a legitimate constant
  259.    in an insn, it is left alone in the hope that it might be valid in the
  260.    address.
  261.  
  262.    X may contain no arithmetic except addition, subtraction and multiplication.
  263.    Values returned by expand_expr with 1 for sum_ok fit this constraint.  */
  264.  
  265. static rtx
  266. break_out_memory_refs (x)
  267.      register rtx x;
  268. {
  269.   if (GET_CODE (x) == MEM
  270.       || (CONSTANT_P (x) && LEGITIMATE_CONSTANT_P (x)
  271.       && GET_MODE (x) != VOIDmode))
  272.     {
  273.       register rtx temp = force_reg (GET_MODE (x), x);
  274.       mark_reg_pointer (temp);
  275.       x = temp;
  276.     }
  277.   else if (GET_CODE (x) == PLUS || GET_CODE (x) == MINUS
  278.        || GET_CODE (x) == MULT)
  279.     {
  280.       register rtx op0 = break_out_memory_refs (XEXP (x, 0));
  281.       register rtx op1 = break_out_memory_refs (XEXP (x, 1));
  282.       if (op0 != XEXP (x, 0) || op1 != XEXP (x, 1))
  283.     x = gen_rtx (GET_CODE (x), Pmode, op0, op1);
  284.     }
  285.   return x;
  286. }
  287.  
  288. /* Given a memory address or facsimile X, construct a new address,
  289.    currently equivalent, that is stable: future stores won't change it.
  290.  
  291.    X must be composed of constants, register and memory references
  292.    combined with addition, subtraction and multiplication:
  293.    in other words, just what you can get from expand_expr if sum_ok is 1.
  294.  
  295.    Works by making copies of all regs and memory locations used
  296.