Annotation of GNUtools/cc/explow.c, revision 1.1

1.1     ! root        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 function 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:   tree size = size_in_bytes (TREE_TYPE (exp));
        !           246: 
        !           247:   if (TREE_CODE (size) != INTEGER_CST
        !           248:       && contains_placeholder_p (size))
        !           249:     size = build (WITH_RECORD_EXPR, sizetype, size, exp);
        !           250: 
        !           251:   return expand_expr (size, NULL_RTX, TYPE_MODE (sizetype), 0);
        !           252: }
        !           253: 
        !           254: /* Return a copy of X in which all memory references
        !           255:    and all constants that involve symbol refs
        !           256:    have been replaced with new temporary registers.
        !           257:    Also emit code to load the memory locations and constants
        !           258:    into those registers.
        !           259: 
        !           260:    If X contains no such constants or memory references,
        !           261:    X itself (not a copy) is returned.
        !           262: 
        !           263:    If a constant is found in the address that is not a legitimate constant
        !           264:    in an insn, it is left alone in the hope that it might be valid in the
        !           265:    address.
        !           266: 
        !           267:    X may contain no arithmetic except addition, subtraction and multiplication.
        !           268:    Values returned by expand_expr with 1 for sum_ok fit this constraint.  */
        !           269: 
        !           270: static rtx
        !           271: break_out_memory_refs (x)
        !           272:      register rtx x;
        !           273: {
        !           274:   if (GET_CODE (x) == MEM
        !           275:       || (CONSTANT_P (x) && CONSTANT_ADDRESS_P (x)
        !           276:          && GET_MODE (x) != VOIDmode))
        !           277:     {
        !           278:       register rtx temp = force_reg (GET_MODE (x), x);
        !           279:       mark_reg_pointer (temp);
        !           280:       x = temp;
        !           281:     }
        !           282:   else if (GET_CODE (x) == PLUS || GET_CODE (x) == MINUS
        !           283:           || GET_CODE (x) == MULT)
        !           284:     {
        !           285:       register rtx op0 = break_out_memory_refs (XEXP (x, 0));
        !           286:       register rtx op1 = break_out_memory_refs (XEXP (x, 1));
        !           287:       if (op0 != XEXP (x, 0) || op1 != XEXP (x, 1))
        !           288:        x = gen_rtx (GET_CODE (x), Pmode, op0, op1);
        !           289:     }
        !           290:   return x;
        !           291: }
        !           292: 
        !           293: /* Given a memory address or facsimile X, construct a new address,
        !           294:    currently equivalent, that is stable: future stores won't change it.
        !           295: 
        !           296:    X must be composed of constants, register and memory references
        !           297:    combined with addition, subtraction and multiplication:
        !           298:    in other words, just what you can get from expand_expr if sum_ok is 1.
        !           299: 
        !           300:    Works by making copies of all regs and memory locations used
        !           301:    by X and combining them the same way X does.
        !           302:    You could also stabilize the reference to this address
        !           303:    by copying the address to a register with copy_to_reg;
        !           304:    but then you wouldn't get indexed addressing in the reference.  */
        !           305: 
        !           306: rtx
        !           307: copy_all_regs (x)
        !           308:      register rtx x;
        !           309: {
        !           310:   if (GET_CODE (x) == REG)
        !           311:     {
        !           312:       if (REGNO (x) != FRAME_POINTER_REGNUM
        !           313: #if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM
        !           314:          && REGNO (x) != HARD_FRAME_POINTER_REGNUM
        !           315: #endif
        !           316:          )
        !           317:        x = copy_to_reg (x);
        !           318:     }
        !           319:   else if (GET_CODE (x) == MEM)
        !           320:     x = copy_to_reg (x);
        !           321:   else if (GET_CODE (x) == PLUS || GET_CODE (x) == MINUS
        !           322:           || GET_CODE (x) == MULT)
        !           323:     {
        !           324:       register rtx op0 = copy_all_regs (XEXP (x, 0));
        !           325:       register rtx op1 = copy_all_regs (XEXP (x, 1));
        !           326:       if (op0 != XEXP (x, 0) || op1 != XEXP (x, 1))
        !           327:        x = gen_rtx (GET_CODE (x), Pmode, op0, op1);
        !           328:     }
        !           329:   return x;
        !           330: }
        !           331: 
        !           332: /* Return something equivalent to X but valid as a memory address
        !           333:    for something of mode MODE.  When X is not itself valid, this
        !           334:    works by copying X or subexpressions of it into registers.  */
        !           335: 
        !           336: rtx
        !           337: memory_address (mode, x)
        !           338:      enum machine_mode mode;
        !           339:      register rtx x;
        !           340: {
        !           341:   register rtx oldx;
        !           342: 
        !           343:   /* By passing constant addresses thru registers
        !           344:      we get a chance to cse them.  */
        !           345:   if (! cse_not_expected && CONSTANT_P (x) && CONSTANT_ADDRESS_P (x))
        !           346:     return force_reg (Pmode, x);
        !           347: 
        !           348:   /* Accept a QUEUED that refers to a REG
        !           349:      even though that isn't a valid address.
        !           350:      On attempting to put this in an insn we will call protect_from_queue
        !           351:      which will turn it into a REG, which is valid.  */
        !           352:   if (GET_CODE (x) == QUEUED
        !           353:       && GET_CODE (QUEUED_VAR (x)) == REG)
        !           354:     return x;
        !           355: 
        !           356:   /* We get better cse by rejecting indirect addressing at this stage.
        !           357:      Let the combiner create indirect addresses where appropriate.
        !           358:      For now, generate the code so that the subexpressions useful to share
        !           359:      are visible.  But not if cse won't be done!  */
        !           360:   oldx = x;
        !           361:   if (! cse_not_expected && GET_CODE (x) != REG)
        !           362:     x = break_out_memory_refs (x);
        !           363: 
        !           364:   /* At this point, any valid address is accepted.  */
        !           365:   GO_IF_LEGITIMATE_ADDRESS (mode, x, win);
        !           366: 
        !           367:   /* If it was valid before but breaking out memory refs invalidated it,
        !           368:      use it the old way.  */
        !           369:   if (memory_address_p (mode, oldx))
        !           370:     goto win2;
        !           371: 
        !           372:   /* Perform machine-dependent transformations on X
        !           373:      in certain cases.  This is not necessary since the code
        !           374:      below can handle all possible cases, but machine-dependent
        !           375:      transformations can make better code.  */
        !           376:   LEGITIMIZE_ADDRESS (x, oldx, mode, win);
        !           377: 
        !           378:   /* PLUS and MULT can appear in special ways
        !           379:      as the result of attempts to make an address usable for indexing.
        !           380:      Usually they are dealt with by calling force_operand, below.
        !           381:      But a sum containing constant terms is special
        !           382:      if removing them makes the sum a valid address:
        !           383:      then we generate that address in a register
        !           384:      and index off of it.  We do this because it often makes
        !           385:      shorter code, and because the addresses thus generated
        !           386:      in registers often become common subexpressions.  */
        !           387:   if (GET_CODE (x) == PLUS)
        !           388:     {
        !           389:       rtx constant_term = const0_rtx;
        !           390:       rtx y = eliminate_constant_term (x, &constant_term);
        !           391:       if (constant_term == const0_rtx
        !           392:          || ! memory_address_p (mode, y))
        !           393:        return force_operand (x, NULL_RTX);
        !           394: 
        !           395:       y = gen_rtx (PLUS, GET_MODE (x), copy_to_reg (y), constant_term);
        !           396:       if (! memory_address_p (mode, y))
        !           397:        return force_operand (x, NULL_RTX);
        !           398:       return y;
        !           399:     }
        !           400:   if (GET_CODE (x) == MULT || GET_CODE (x) == MINUS)
        !           401:     return force_operand (x, NULL_RTX);
        !           402: 
        !           403:   /* If we have a register that's an invalid address,
        !           404:      it must be a hard reg of the wrong class.  Copy it to a pseudo.  */
        !           405:   if (GET_CODE (x) == REG)
        !           406:     return copy_to_reg (x);
        !           407: 
        !           408:   /* Last resort: copy the value to a register, since
        !           409:      the register is a valid address.  */
        !           410:   return force_reg (Pmode, x);
        !           411: 
        !           412:  win2:
        !           413:   x = oldx;
        !           414:  win:
        !           415:   if (flag_force_addr && ! cse_not_expected && GET_CODE (x) != REG
        !           416:       /* Don't copy an addr via a reg if it is one of our stack slots.  */
        !           417:       && ! (GET_CODE (x) == PLUS
        !           418:            && (XEXP (x, 0) == virtual_stack_vars_rtx
        !           419:                || XEXP (x, 0) == virtual_incoming_args_rtx)))
        !           420:     {
        !           421:       if (general_operand (x, Pmode))
        !           422:        return force_reg (Pmode, x);
        !           423:       else
        !           424:        return force_operand (x, NULL_RTX);
        !           425:     }
        !           426:   return x;
        !           427: }
        !           428: 
        !           429: /* Like `memory_address' but pretend `flag_force_addr' is 0.  */
        !           430: 
        !           431: rtx
        !           432: memory_address_noforce (mode, x)
        !           433:      enum machine_mode mode;
        !           434:      rtx x;
        !           435: {
        !           436:   int ambient_force_addr = flag_force_addr;
        !           437:   rtx val;
        !           438: 
        !           439:   flag_force_addr = 0;
        !           440:   val = memory_address (mode, x);
        !           441:   flag_force_addr = ambient_force_addr;
        !           442:   return val;
        !           443: }
        !           444: 
        !           445: /* Convert a mem ref into one with a valid memory address.
        !           446:    Pass through anything else unchanged.  */
        !           447: 
        !           448: rtx
        !           449: validize_mem (ref)
        !           450:      rtx ref;
        !           451: {
        !           452:   if (GET_CODE (ref) != MEM)
        !           453:     return ref;
        !           454:   if (memory_address_p (GET_MODE (ref), XEXP (ref, 0)))
        !           455:     return ref;
        !           456:   /* Don't alter REF itself, since that is probably a stack slot.  */
        !           457:   return change_address (ref, GET_MODE (ref), XEXP (ref, 0));
        !           458: }
        !           459: 
        !           460: /* Return a modified copy of X with its memory address copied
        !           461:    into a temporary register to protect it from side effects.
        !           462:    If X is not a MEM, it is returned unchanged (and not copied).
        !           463:    Perhaps even if it is a MEM, if there is no need to change it.  */
        !           464: 
        !           465: rtx
        !           466: stabilize (x)
        !           467:      rtx x;
        !           468: {
        !           469:   register rtx addr;
        !           470:   if (GET_CODE (x) != MEM)
        !           471:     return x;
        !           472:   addr = XEXP (x, 0);
        !           473:   if (rtx_unstable_p (addr))
        !           474:     {
        !           475:       rtx temp = copy_all_regs (addr);
        !           476:       rtx mem;
        !           477:       if (GET_CODE (temp) != REG)
        !           478:        temp = copy_to_reg (temp);
        !           479:       mem = gen_rtx (MEM, GET_MODE (x), temp);
        !           480: 
        !           481:       /* Mark returned memref with in_struct if it's in an array or
        !           482:         structure.  Copy const and volatile from original memref.  */
        !           483: 
        !           484:       MEM_IN_STRUCT_P (mem) = MEM_IN_STRUCT_P (x) || GET_CODE (addr) == PLUS;
        !           485:       RTX_UNCHANGING_P (mem) = RTX_UNCHANGING_P (x);
        !           486:       MEM_VOLATILE_P (mem) = MEM_VOLATILE_P (x);
        !           487:       return mem;
        !           488:     }
        !           489:   return x;
        !           490: }
        !           491: 
        !           492: /* Copy the value or contents of X to a new temp reg and return that reg.  */
        !           493: 
        !           494: rtx
        !           495: copy_to_reg (x)
        !           496:      rtx x;
        !           497: {
        !           498:   register rtx temp = gen_reg_rtx (GET_MODE (x));
        !           499:  
        !           500:   /* If not an operand, must be an address with PLUS and MULT so
        !           501:      do the computation.  */ 
        !           502:   if (! general_operand (x, VOIDmode))
        !           503:     x = force_operand (x, temp);
        !           504:   
        !           505:   if (x != temp)
        !           506:     emit_move_insn (temp, x);
        !           507: 
        !           508:   return temp;
        !           509: }
        !           510: 
        !           511: /* Like copy_to_reg but always give the new register mode Pmode
        !           512:    in case X is a constant.  */
        !           513: 
        !           514: rtx
        !           515: copy_addr_to_reg (x)
        !           516:      rtx x;
        !           517: {
        !           518:   return copy_to_mode_reg (Pmode, x);
        !           519: }
        !           520: 
        !           521: /* Like copy_to_reg but always give the new register mode MODE
        !           522:    in case X is a constant.  */
        !           523: 
        !           524: rtx
        !           525: copy_to_mode_reg (mode, x)
        !           526:      enum machine_mode mode;
        !           527:      rtx x;
        !           528: {
        !           529:   register rtx temp = gen_reg_rtx (mode);
        !           530:   
        !           531:   /* If not an operand, must be an address with PLUS and MULT so
        !           532:      do the computation.  */ 
        !           533:   if (! general_operand (x, VOIDmode))
        !           534:     x = force_operand (x, temp);
        !           535: 
        !           536:   if (GET_MODE (x) != mode && GET_MODE (x) != VOIDmode)
        !           537:     abort ();
        !           538:   if (x != temp)
        !           539:     emit_move_insn (temp, x);
        !           540:   return temp;
        !           541: }
        !           542: 
        !           543: /* Load X into a register if it is not already one.
        !           544:    Use mode MODE for the register.
        !           545:    X should be valid for mode MODE, but it may be a constant which
        !           546:    is valid for all integer modes; that's why caller must specify MODE.
        !           547: 
        !           548:    The caller must not alter the value in the register we return,
        !           549:    since we mark it as a "constant" register.  */
        !           550: 
        !           551: rtx
        !           552: force_reg (mode, x)
        !           553:      enum machine_mode mode;
        !           554:      rtx x;
        !           555: {
        !           556:   register rtx temp, insn;
        !           557: 
        !           558:   if (GET_CODE (x) == REG)
        !           559:     return x;
        !           560:   temp = gen_reg_rtx (mode);
        !           561:   insn = emit_move_insn (temp, x);
        !           562:   /* Let optimizers know that TEMP's value never changes
        !           563:      and that X can be substituted for it.  */
        !           564:   if (CONSTANT_P (x))
        !           565:     {
        !           566:       rtx note = find_reg_note (insn, REG_EQUAL, NULL_RTX);
        !           567: 
        !           568:       if (note)
        !           569:        XEXP (note, 0) = x;
        !           570:       else
        !           571:        REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_EQUAL, x, REG_NOTES (insn));
        !           572:     }
        !           573:   return temp;
        !           574: }
        !           575: 
        !           576: /* If X is a memory ref, copy its contents to a new temp reg and return
        !           577:    that reg.  Otherwise, return X.  */
        !           578: 
        !           579: rtx
        !           580: force_not_mem (x)
        !           581:      rtx x;
        !           582: {
        !           583:   register rtx temp;
        !           584:   if (GET_CODE (x) != MEM || GET_MODE (x) == BLKmode)
        !           585:     return x;
        !           586:   temp = gen_reg_rtx (GET_MODE (x));
        !           587:   emit_move_insn (temp, x);
        !           588:   return temp;
        !           589: }
        !           590: 
        !           591: /* Copy X to TARGET (if it's nonzero and a reg)
        !           592:    or to a new temp reg and return that reg.
        !           593:    MODE is the mode to use for X in case it is a constant.  */
        !           594: 
        !           595: rtx
        !           596: copy_to_suggested_reg (x, target, mode)
        !           597:      rtx x, target;
        !           598:      enum machine_mode mode;
        !           599: {
        !           600:   register rtx temp;
        !           601: 
        !           602:   if (target && GET_CODE (target) == REG)
        !           603:     temp = target;
        !           604:   else
        !           605:     temp = gen_reg_rtx (mode);
        !           606: 
        !           607:   emit_move_insn (temp, x);
        !           608:   return temp;
        !           609: }
        !           610: 
        !           611: /* Adjust the stack pointer by ADJUST (an rtx for a number of bytes).
        !           612:    This pops when ADJUST is positive.  ADJUST need not be constant.  */
        !           613: 
        !           614: void
        !           615: adjust_stack (adjust)
        !           616:      rtx adjust;
        !           617: {
        !           618:   rtx temp;
        !           619:   adjust = protect_from_queue (adjust, 0);
        !           620: 
        !           621:   if (adjust == const0_rtx)
        !           622:     return;
        !           623: 
        !           624:   temp = expand_binop (Pmode,
        !           625: #ifdef STACK_GROWS_DOWNWARD
        !           626:                       add_optab,
        !           627: #else
        !           628:                       sub_optab,
        !           629: #endif
        !           630:                       stack_pointer_rtx, adjust, stack_pointer_rtx, 0,
        !           631:                       OPTAB_LIB_WIDEN);
        !           632: 
        !           633:   if (temp != stack_pointer_rtx)
        !           634:     emit_move_insn (stack_pointer_rtx, temp);
        !           635: }
        !           636: 
        !           637: /* Adjust the stack pointer by minus ADJUST (an rtx for a number of bytes).
        !           638:    This pushes when ADJUST is positive.  ADJUST need not be constant.  */
        !           639: 
        !           640: void
        !           641: anti_adjust_stack (adjust)
        !           642:      rtx adjust;
        !           643: {
        !           644:   rtx temp;
        !           645:   adjust = protect_from_queue (adjust, 0);
        !           646: 
        !           647:   if (adjust == const0_rtx)
        !           648:     return;
        !           649: 
        !           650:   temp = expand_binop (Pmode,
        !           651: #ifdef STACK_GROWS_DOWNWARD
        !           652:                       sub_optab,
        !           653: #else
        !           654:                       add_optab,
        !           655: #endif
        !           656:                       stack_pointer_rtx, adjust, stack_pointer_rtx, 0,
        !           657:                       OPTAB_LIB_WIDEN);
        !           658: 
        !           659:   if (temp != stack_pointer_rtx)
        !           660:     emit_move_insn (stack_pointer_rtx, temp);
        !           661: }
        !           662: 
        !           663: /* Round the size of a block to be pushed up to the boundary required
        !           664:    by this machine.  SIZE is the desired size, which need not be constant.  */
        !           665: 
        !           666: rtx
        !           667: round_push (size)
        !           668:      rtx size;
        !           669: {
        !           670: #ifdef STACK_BOUNDARY
        !           671:   int align = STACK_BOUNDARY / BITS_PER_UNIT;
        !           672:   if (align == 1)
        !           673:     return size;
        !           674:   if (GET_CODE (size) == CONST_INT)
        !           675:     {
        !           676:       int new = (INTVAL (size) + align - 1) / align * align;
        !           677:       if (INTVAL (size) != new)
        !           678:        size = GEN_INT (new);
        !           679:     }
        !           680:   else
        !           681:     {
        !           682:       size = expand_divmod (0, CEIL_DIV_EXPR, Pmode, size, GEN_INT (align),
        !           683:                            NULL_RTX, 1);
        !           684:       size = expand_mult (Pmode, size, GEN_INT (align), NULL_RTX, 1);
        !           685:     }
        !           686: #endif /* STACK_BOUNDARY */
        !           687:   return size;
        !           688: }
        !           689: 
        !           690: /* Save the stack pointer for the purpose in SAVE_LEVEL.  PSAVE is a pointer
        !           691:    to a previously-created save area.  If no save area has been allocated,
        !           692:    this function will allocate one.  If a save area is specified, it
        !           693:    must be of the proper mode.
        !           694: 
        !           695:    The insns are emitted after insn AFTER, if nonzero, otherwise the insns
        !           696:    are emitted at the current position.  */
        !           697: 
        !           698: void
        !           699: emit_stack_save (save_level, psave, after)
        !           700:      enum save_level save_level;
        !           701:      rtx *psave;
        !           702:      rtx after;
        !           703: {
        !           704:   rtx sa = *psave;
        !           705:   /* The default is that we use a move insn and save in a Pmode object.  */
        !           706:   rtx (*fcn) () = gen_move_insn;
        !           707:   enum machine_mode mode = Pmode;
        !           708: 
        !           709:   /* See if this machine has anything special to do for this kind of save.  */
        !           710:   switch (save_level)
        !           711:     {
        !           712: #ifdef HAVE_save_stack_block
        !           713:     case SAVE_BLOCK:
        !           714:       if (HAVE_save_stack_block)
        !           715:        {
        !           716:          fcn = gen_save_stack_block;
        !           717:          mode = insn_operand_mode[CODE_FOR_save_stack_block][0];
        !           718:        }
        !           719:       break;
        !           720: #endif
        !           721: #ifdef HAVE_save_stack_function
        !           722:     case SAVE_FUNCTION:
        !           723:       if (HAVE_save_stack_function)
        !           724:        {
        !           725:          fcn = gen_save_stack_function;
        !           726:          mode = insn_operand_mode[CODE_FOR_save_stack_function][0];
        !           727:        }
        !           728:       break;
        !           729: #endif
        !           730: #ifdef HAVE_save_stack_nonlocal
        !           731:     case SAVE_NONLOCAL:
        !           732:       if (HAVE_save_stack_nonlocal)
        !           733:        {
        !           734:          fcn = gen_save_stack_nonlocal;
        !           735:          mode = insn_operand_mode[(int) CODE_FOR_save_stack_nonlocal][0];
        !           736:        }
        !           737:       break;
        !           738: #endif
        !           739:     }
        !           740: 
        !           741:   /* If there is no save area and we have to allocate one, do so.  Otherwise
        !           742:      verify the save area is the proper mode.  */
        !           743: 
        !           744:   if (sa == 0)
        !           745:     {
        !           746:       if (mode != VOIDmode)
        !           747:        {
        !           748:          if (save_level == SAVE_NONLOCAL)
        !           749:            *psave = sa = assign_stack_local (mode, GET_MODE_SIZE (mode), 0);
        !           750:          else
        !           751:            *psave = sa = gen_reg_rtx (mode);
        !           752:        }
        !           753:     }
        !           754:   else
        !           755:     {
        !           756:       if (mode == VOIDmode || GET_MODE (sa) != mode)
        !           757:        abort ();
        !           758:     }
        !           759: 
        !           760:   if (after)
        !           761:     {
        !           762:       rtx seq;
        !           763: 
        !           764:       start_sequence ();
        !           765:       /* We must validize inside the sequence, to ensure that any instructions
        !           766:         created by the validize call also get moved to the right place.  */
        !           767:       if (sa != 0)
        !           768:        sa = validize_mem (sa);
        !           769:       emit_insn (fcn (sa, stack_pointer_rtx));
        !           770:       seq = gen_sequence ();
        !           771:       end_sequence ();
        !           772:       emit_insn_after (seq, after);
        !           773:     }
        !           774:   else
        !           775:     {
        !           776:       if (sa != 0)
        !           777:        sa = validize_mem (sa);
        !           778:       emit_insn (fcn (sa, stack_pointer_rtx));
        !           779:     }
        !           780: }
        !           781: 
        !           782: /* Restore the stack pointer for the purpose in SAVE_LEVEL.  SA is the save
        !           783:    area made by emit_stack_save.  If it is zero, we have nothing to do. 
        !           784: 
        !           785:    Put any emitted insns after insn AFTER, if nonzero, otherwise at 
        !           786:    current position.  */
        !           787: 
        !           788: void
        !           789: emit_stack_restore (save_level, sa, after)
        !           790:      enum save_level save_level;
        !           791:      rtx after;
        !           792:      rtx sa;
        !           793: {
        !           794:   /* The default is that we use a move insn.  */
        !           795:   rtx (*fcn) () = gen_move_insn;
        !           796: 
        !           797:   /* See if this machine has anything special to do for this kind of save.  */
        !           798:   switch (save_level)
        !           799:     {
        !           800: #ifdef HAVE_restore_stack_block
        !           801:     case SAVE_BLOCK:
        !           802:       if (HAVE_restore_stack_block)
        !           803:        fcn = gen_restore_stack_block;
        !           804:       break;
        !           805: #endif
        !           806: #ifdef HAVE_restore_stack_function
        !           807:     case SAVE_FUNCTION:
        !           808:       if (HAVE_restore_stack_function)
        !           809:        fcn = gen_restore_stack_function;
        !           810:       break;
        !           811: #endif
        !           812: #ifdef HAVE_restore_stack_nonlocal
        !           813: 
        !           814:     case SAVE_NONLOCAL:
        !           815:       if (HAVE_restore_stack_nonlocal)
        !           816:        fcn = gen_restore_stack_nonlocal;
        !           817:       break;
        !           818: #endif
        !           819:     }
        !           820: 
        !           821:   if (sa != 0)
        !           822:     sa = validize_mem (sa);
        !           823: 
        !           824:   if (after)
        !           825:     {
        !           826:       rtx seq;
        !           827: 
        !           828:       start_sequence ();
        !           829:       emit_insn (fcn (stack_pointer_rtx, sa));
        !           830:       seq = gen_sequence ();
        !           831:       end_sequence ();
        !           832:       emit_insn_after (seq, after);
        !           833:     }
        !           834:   else
        !           835:     emit_insn (fcn (stack_pointer_rtx, sa));
        !           836: }
        !           837: 
        !           838: /* Return an rtx representing the address of an area of memory dynamically
        !           839:    pushed on the stack.  This region of memory is always aligned to
        !           840:    a multiple of BIGGEST_ALIGNMENT.
        !           841: 
        !           842:    Any required stack pointer alignment is preserved.
        !           843: 
        !           844:    SIZE is an rtx representing the size of the area.
        !           845:    TARGET is a place in which the address can be placed.
        !           846: 
        !           847:    KNOWN_ALIGN is the alignment (in bits) that we know SIZE has.  */
        !           848: 
        !           849: rtx
        !           850: allocate_dynamic_stack_space (size, target, known_align)
        !           851:      rtx size;
        !           852:      rtx target;
        !           853:      int known_align;
        !           854: {
        !           855:   /* Ensure the size is in the proper mode.  */
        !           856:   if (GET_MODE (size) != VOIDmode && GET_MODE (size) != Pmode)
        !           857:     size = convert_to_mode (Pmode, size, 1);
        !           858: 
        !           859:   /* We will need to ensure that the address we return is aligned to
        !           860:      BIGGEST_ALIGNMENT.  If STACK_DYNAMIC_OFFSET is defined, we don't
        !           861:      always know its final value at this point in the compilation (it 
        !           862:      might depend on the size of the outgoing parameter lists, for
        !           863:      example), so we must align the value to be returned in that case.
        !           864:      (Note that STACK_DYNAMIC_OFFSET will have a default non-zero value if
        !           865:      STACK_POINTER_OFFSET or ACCUMULATE_OUTGOING_ARGS are defined).
        !           866:      We must also do an alignment operation on the returned value if
        !           867:      the stack pointer alignment is less strict that BIGGEST_ALIGNMENT.
        !           868: 
        !           869:      If we have to align, we must leave space in SIZE for the hole
        !           870:      that might result from the alignment operation.  */
        !           871: 
        !           872: #if defined (STACK_DYNAMIC_OFFSET) || defined(STACK_POINTER_OFFSET) || defined (ALLOCATE_OUTGOING_ARGS)
        !           873: #define MUST_ALIGN
        !           874: #endif
        !           875: 
        !           876: #if ! defined (MUST_ALIGN) && (!defined(STACK_BOUNDARY) || STACK_BOUNDARY < BIGGEST_ALIGNMENT)
        !           877: #define MUST_ALIGN
        !           878: #endif
        !           879: 
        !           880: #ifdef MUST_ALIGN
        !           881: 
        !           882: #if 0 /* It turns out we must always make extra space, if MUST_ALIGN
        !           883:         because we must always round the address up at the end,
        !           884:         because we don't know whether the dynamic offset
        !           885:         will mess up the desired alignment.  */
        !           886:   /* If we have to round the address up regardless of known_align,
        !           887:      make extra space regardless, also.  */
        !           888:   if (known_align % BIGGEST_ALIGNMENT != 0)
        !           889: #endif
        !           890:     {
        !           891:       if (GET_CODE (size) == CONST_INT)
        !           892:        size = GEN_INT (INTVAL (size)
        !           893:                        + (BIGGEST_ALIGNMENT / BITS_PER_UNIT - 1));
        !           894:       else
        !           895:        size = expand_binop (Pmode, add_optab, size,
        !           896:                             GEN_INT (BIGGEST_ALIGNMENT / BITS_PER_UNIT - 1),
        !           897:                             NULL_RTX, 1, OPTAB_LIB_WIDEN);
        !           898:     }
        !           899: 
        !           900: #endif
        !           901: 
        !           902: #ifdef SETJMP_VIA_SAVE_AREA
        !           903:   /* If setjmp restores regs from a save area in the stack frame,
        !           904:      avoid clobbering the reg save area.  Note that the offset of
        !           905:      virtual_incoming_args_rtx includes the preallocated stack args space.
        !           906:      It would be no problem to clobber that, but it's on the wrong side
        !           907:      of the old save area.  */
        !           908:   {
        !           909:     rtx dynamic_offset
        !           910:       = expand_binop (Pmode, sub_optab, virtual_stack_dynamic_rtx,
        !           911:                      stack_pointer_rtx, NULL_RTX, 1, OPTAB_LIB_WIDEN);
        !           912:     size = expand_binop (Pmode, add_optab, size, dynamic_offset,
        !           913:                         NULL_RTX, 1, OPTAB_LIB_WIDEN);
        !           914:   }
        !           915: #endif /* SETJMP_VIA_SAVE_AREA */
        !           916: 
        !           917:   /* Round the size to a multiple of the required stack alignment.
        !           918:      Since the stack if presumed to be rounded before this allocation,
        !           919:      this will maintain the required alignment.
        !           920: 
        !           921:      If the stack grows downward, we could save an insn by subtracting
        !           922:      SIZE from the stack pointer and then aligning the stack pointer.
        !           923:      The problem with this is that the stack pointer may be unaligned
        !           924:      between the execution of the subtraction and alignment insns and
        !           925:      some machines do not allow this.  Even on those that do, some
        !           926:      signal handlers malfunction if a signal should occur between those
        !           927:      insns.  Since this is an extremely rare event, we have no reliable
        !           928:      way of knowing which systems have this problem.  So we avoid even
        !           929:      momentarily mis-aligning the stack.  */
        !           930: 
        !           931: #ifdef STACK_BOUNDARY
        !           932:   /* If we added a variable amount to SIZE,
        !           933:      we can no longer assume it is aligned.  */
        !           934: #if !defined (SETJMP_VIA_SAVE_AREA) && !defined (MUST_ALIGN)
        !           935:   if (known_align % STACK_BOUNDARY != 0)
        !           936: #endif
        !           937:     size = round_push (size);
        !           938: #endif
        !           939: 
        !           940:   do_pending_stack_adjust ();
        !           941: 
        !           942:   /* Don't use a TARGET that isn't a pseudo.  */
        !           943:   if (target == 0 || GET_CODE (target) != REG
        !           944:       || REGNO (target) < FIRST_PSEUDO_REGISTER)
        !           945:     target = gen_reg_rtx (Pmode);
        !           946: 
        !           947:   mark_reg_pointer (target);
        !           948: 
        !           949: #ifndef STACK_GROWS_DOWNWARD
        !           950:   emit_move_insn (target, virtual_stack_dynamic_rtx);
        !           951: #endif
        !           952: 
        !           953:   /* Perform the required allocation from the stack.  Some systems do
        !           954:      this differently than simply incrementing/decrementing from the
        !           955:      stack pointer.  */
        !           956: #ifdef HAVE_allocate_stack
        !           957:   if (HAVE_allocate_stack)
        !           958:     {
        !           959:       enum machine_mode mode
        !           960:        = insn_operand_mode[(int) CODE_FOR_allocate_stack][0];
        !           961: 
        !           962:       if (insn_operand_predicate[(int) CODE_FOR_allocate_stack][0]
        !           963:          && ! ((*insn_operand_predicate[(int) CODE_FOR_allocate_stack][0])
        !           964:                (size, mode)))
        !           965:        size = copy_to_mode_reg (mode, size);
        !           966: 
        !           967:       emit_insn (gen_allocate_stack (size));
        !           968:     }
        !           969:   else
        !           970: #endif
        !           971:     anti_adjust_stack (size);
        !           972: 
        !           973: #ifdef STACK_GROWS_DOWNWARD
        !           974:   emit_move_insn (target, virtual_stack_dynamic_rtx);
        !           975: #endif
        !           976: 
        !           977: #ifdef MUST_ALIGN
        !           978: #if 0  /* Even if we know the stack pointer has enough alignment,
        !           979:          there's no way to tell whether virtual_stack_dynamic_rtx shares that
        !           980:          alignment, so we still need to round the address up.  */
        !           981:   if (known_align % BIGGEST_ALIGNMENT != 0)
        !           982: #endif
        !           983:     {
        !           984:       target = expand_divmod (0, CEIL_DIV_EXPR, Pmode, target,
        !           985:                              GEN_INT (BIGGEST_ALIGNMENT / BITS_PER_UNIT),
        !           986:                              NULL_RTX, 1);
        !           987: 
        !           988:       target = expand_mult (Pmode, target,
        !           989:                            GEN_INT (BIGGEST_ALIGNMENT / BITS_PER_UNIT),
        !           990:                            NULL_RTX, 1);
        !           991:     }
        !           992: #endif
        !           993:   
        !           994:   /* Some systems require a particular insn to refer to the stack
        !           995:      to make the pages exist.  */
        !           996: #ifdef HAVE_probe
        !           997:   if (HAVE_probe)
        !           998:     emit_insn (gen_probe ());
        !           999: #endif
        !          1000: 
        !          1001:   return target;
        !          1002: }
        !          1003: 
        !          1004: /* Return an rtx representing the register or memory location
        !          1005:    in which a scalar value of data type VALTYPE
        !          1006:    was returned by a function call to function FUNC.
        !          1007:    FUNC is a FUNCTION_DECL node if the precise function is known,
        !          1008:    otherwise 0.  */
        !          1009: 
        !          1010: rtx
        !          1011: hard_function_value (valtype, func)
        !          1012:      tree valtype;
        !          1013:      tree func;
        !          1014: {
        !          1015:   return FUNCTION_VALUE (valtype, func);
        !          1016: }
        !          1017: 
        !          1018: /* Return an rtx representing the register or memory location
        !          1019:    in which a scalar value of mode MODE was returned by a library call.  */
        !          1020: 
        !          1021: rtx
        !          1022: hard_libcall_value (mode)
        !          1023:      enum machine_mode mode;
        !          1024: {
        !          1025:   return LIBCALL_VALUE (mode);
        !          1026: }
        !          1027: 
        !          1028: /* Look up the tree code for a given rtx code
        !          1029:    to provide the arithmetic operation for REAL_ARITHMETIC.
        !          1030:    The function returns an int because the caller may not know
        !          1031:    what `enum tree_code' means.  */
        !          1032: 
        !          1033: int
        !          1034: rtx_to_tree_code (code)
        !          1035:      enum rtx_code code;
        !          1036: {
        !          1037:   enum tree_code tcode;
        !          1038: 
        !          1039:   switch (code)
        !          1040:     {
        !          1041:     case PLUS:
        !          1042:       tcode = PLUS_EXPR;
        !          1043:       break;
        !          1044:     case MINUS:
        !          1045:       tcode = MINUS_EXPR;
        !          1046:       break;
        !          1047:     case MULT:
        !          1048:       tcode = MULT_EXPR;
        !          1049:       break;
        !          1050:     case DIV:
        !          1051:       tcode = RDIV_EXPR;
        !          1052:       break;
        !          1053:     case SMIN:
        !          1054:       tcode = MIN_EXPR;
        !          1055:       break;
        !          1056:     case SMAX:
        !          1057:       tcode = MAX_EXPR;
        !          1058:       break;
        !          1059:     default:
        !          1060:       tcode = LAST_AND_UNUSED_TREE_CODE;
        !          1061:       break;
        !          1062:     }
        !          1063:   return ((int) tcode);
        !          1064: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.